2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-19 18:53:52 +08:00

Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
  [WATCHDOG] make watchdog/hpwdt.c:asminline_call() static
  [WATCHDOG] Remove volatiles from watchdog device structures
  [WATCHDOG] replace remaining __FUNCTION__ occurrences
  [WATCHDOG] hpwdt: Use dmi_walk() instead of own copy
  [WATCHDOG] Fix return value warning in hpwdt
  [WATCHDOG] Fix declaration of struct smbios_entry_point in hpwdt
  [WATCHDOG] it8712f_wdt support for 16-bit timeout values, WDIOC_GETSTATUS
This commit is contained in:
Linus Torvalds 2008-03-10 18:02:16 -07:00
commit dae311b42f
8 changed files with 99 additions and 215 deletions

View File

@ -59,9 +59,9 @@ static int ticks = 10000;
static struct { static struct {
struct completion stop; struct completion stop;
volatile int running; int running;
struct timer_list timer; struct timer_list timer;
volatile int queue; int queue;
int default_ticks; int default_ticks;
unsigned long inuse; unsigned long inuse;
} cpu5wdt_device; } cpu5wdt_device;

View File

@ -58,41 +58,6 @@ struct bios32_service_dir {
u8 reserved[5]; u8 reserved[5];
}; };
/*
* smbios_entry_point - defines SMBIOS entry point structure
*
* anchor[4] - anchor string (_SM_)
* checksum - checksum of the entry point structure
* length - length of the entry point structure
* major_ver - major version (02h for revision 2.1)
* minor_ver - minor version (01h for revision 2.1)
* max_struct_size - size of the largest SMBIOS structure
* revision - entry point structure revision implemented
* formatted_area[5] - reserved
* intermediate_anchor[5] - intermediate anchor string (_DMI_)
* intermediate_checksum - intermediate checksum
* table_length - structure table length
* table_address - structure table address
* table_num_structs - number of SMBIOS structures present
* bcd_revision - BCD revision
*/
struct smbios_entry_point {
u8 anchor[4];
u8 checksum;
u8 length;
u8 major_ver;
u8 minor_ver;
u16 max_struct_size;
u8 revision;
u8 formatted_area[5];
u8 intermediate_anchor[5];
u8 intermediate_checksum;
u16 table_length;
u64 table_address;
u16 table_num_structs;
u8 bcd_revision;
};
/* type 212 */ /* type 212 */
struct smbios_cru64_info { struct smbios_cru64_info {
u8 type; u8 type;
@ -175,31 +140,13 @@ static struct pci_device_id hpwdt_devices[] = {
}; };
MODULE_DEVICE_TABLE(pci, hpwdt_devices); MODULE_DEVICE_TABLE(pci, hpwdt_devices);
/*
* bios_checksum
*/
static int __devinit bios_checksum(const char __iomem *ptr, int len)
{
char sum = 0;
int i;
/*
* calculate checksum of size bytes. This should add up
* to zero if we have a valid header.
*/
for (i = 0; i < len; i++)
sum += ptr[i];
return ((sum == 0) && (len > 0));
}
#ifndef CONFIG_X86_64 #ifndef CONFIG_X86_64
/* --32 Bit Bios------------------------------------------------------------ */ /* --32 Bit Bios------------------------------------------------------------ */
#define HPWDT_ARCH 32 #define HPWDT_ARCH 32
asmlinkage void asminline_call(struct cmn_registers *pi86Regs, static void asminline_call(struct cmn_registers *pi86Regs,
unsigned long *pRomEntry) unsigned long *pRomEntry)
{ {
asm("pushl %ebp \n\t" asm("pushl %ebp \n\t"
"movl %esp, %ebp \n\t" "movl %esp, %ebp \n\t"
@ -302,6 +249,24 @@ static int __devinit cru_detect(unsigned long map_entry,
return retval; return retval;
} }
/*
* bios_checksum
*/
static int __devinit bios_checksum(const char __iomem *ptr, int len)
{
char sum = 0;
int i;
/*
* calculate checksum of size bytes. This should add up
* to zero if we have a valid header.
*/
for (i = 0; i < len; i++)
sum += ptr[i];
return ((sum == 0) && (len > 0));
}
/* /*
* bios32_present * bios32_present
* *
@ -368,8 +333,8 @@ static int __devinit detect_cru_service(void)
#define HPWDT_ARCH 64 #define HPWDT_ARCH 64
asmlinkage void asminline_call(struct cmn_registers *pi86Regs, static void asminline_call(struct cmn_registers *pi86Regs,
unsigned long *pRomEntry) unsigned long *pRomEntry)
{ {
asm("pushq %rbp \n\t" asm("pushq %rbp \n\t"
"movq %rsp, %rbp \n\t" "movq %rsp, %rbp \n\t"
@ -410,12 +375,8 @@ asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
* dmi_find_cru * dmi_find_cru
* *
* Routine Description: * Routine Description:
* This function checks wether or not a SMBIOS/DMI record is * This function checks whether or not a SMBIOS/DMI record is
* the 64bit CRU info or not * the 64bit CRU info or not
*
* Return Value:
* 0 : SUCCESS - if record found
* <0 : FAILURE - if record not found
*/ */
static void __devinit dmi_find_cru(const struct dmi_header *dm) static void __devinit dmi_find_cru(const struct dmi_header *dm)
{ {
@ -434,138 +395,11 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm)
} }
} }
/*
* dmi_table
*
* Routine Description:
* Decode the SMBIOS/DMI table and check if we have a 64bit CRU record
* or not.
*
* We have to be cautious here. We have seen BIOSes with DMI pointers
* pointing to completely the wrong place for example
*/
static void __devinit dmi_table(u8 *buf, int len, int num,
void (*decode)(const struct dmi_header *))
{
u8 *data = buf;
int i = 0;
/*
* Stop when we see all the items the table claimed to have
* OR we run off the end of the table (also happens)
*/
while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
const struct dmi_header *dm = (const struct dmi_header *)data;
/*
* We want to know the total length (formated area and strings)
* before decoding to make sure we won't run off the table in
* dmi_decode or dmi_string
*/
data += dm->length;
while ((data - buf < len - 1) && (data[0] || data[1]))
data++;
if (data - buf < len - 1)
decode(dm);
data += 2;
i++;
}
}
/*
* smbios_present
*
* Routine Description:
* This function parses the SMBIOS entry point table to retrieve
* the 64 bit CRU Service.
*
* Return Value:
* 0 : SUCCESS
* <0 : FAILURE
*/
static int __devinit smbios_present(const char __iomem *p)
{
struct smbios_entry_point *eps =
(struct smbios_entry_point *) p;
int length;
u8 *buf;
/* check if we have indeed the SMBIOS table entry point */
if ((strncmp((char *)eps->anchor, "_SM_",
sizeof(eps->anchor))) == 0) {
length = eps->length;
/* SMBIOS v2.1 implementation might use 0x1e */
if ((length == 0x1e) &&
(eps->major_ver == 2) &&
(eps->minor_ver == 1))
length = 0x1f;
/*
* Now we will check:
* - SMBIOS checksum must be 0
* - intermediate anchor should be _DMI_
* - intermediate checksum should be 0
*/
if ((bios_checksum(p, length)) &&
(strncmp((char *)eps->intermediate_anchor, "_DMI_",
sizeof(eps->intermediate_anchor)) == 0) &&
(bios_checksum(p+0x10, 15))) {
buf = ioremap(eps->table_address, eps->table_length);
if (buf == NULL)
return -ENODEV;
/* Scan the DMI table for the 64 bit CRU service */
dmi_table(buf, eps->table_length,
eps->table_num_structs, dmi_find_cru);
iounmap(buf);
return 0;
}
}
return -ENODEV;
}
static int __devinit smbios_scan_machine(void)
{
char __iomem *p, *q;
int rc;
if (efi_enabled) {
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
return -ENODEV;
p = ioremap(efi.smbios, 32);
if (p == NULL)
return -ENOMEM;
rc = smbios_present(p);
iounmap(p);
} else {
/*
* Search from 0x0f0000 through 0x0fffff, inclusive.
*/
p = ioremap(PCI_ROM_BASE1, ROM_SIZE);
if (p == NULL)
return -ENOMEM;
for (q = p; q < p + ROM_SIZE; q += 16) {
rc = smbios_present(q);
if (!rc) {
break;
}
}
iounmap(p);
}
}
static int __devinit detect_cru_service(void) static int __devinit detect_cru_service(void)
{ {
cru_rom_addr = NULL; cru_rom_addr = NULL;
smbios_scan_machine(); /* will become dmi_walk(dmi_find_cru); */ dmi_walk(dmi_find_cru);
/* if cru_rom_addr has been set then we found a CRU service */ /* if cru_rom_addr has been set then we found a CRU service */
return ((cru_rom_addr != NULL)? 0: -ENODEV); return ((cru_rom_addr != NULL)? 0: -ENODEV);

View File

@ -7,7 +7,8 @@
* *
* drivers/char/watchdog/scx200_wdt.c * drivers/char/watchdog/scx200_wdt.c
* drivers/hwmon/it87.c * drivers/hwmon/it87.c
* IT8712F EC-LPC I/O Preliminary Specification 0.9.2.pdf * IT8712F EC-LPC I/O Preliminary Specification 0.8.2
* IT8712F EC-LPC I/O Preliminary Specification 0.9.3
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@ -40,6 +41,7 @@ MODULE_DESCRIPTION("IT8712F Watchdog Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
static int max_units = 255;
static int margin = 60; /* in seconds */ static int margin = 60; /* in seconds */
module_param(margin, int, 0); module_param(margin, int, 0);
MODULE_PARM_DESC(margin, "Watchdog margin in seconds"); MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
@ -51,6 +53,7 @@ MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
static struct semaphore it8712f_wdt_sem; static struct semaphore it8712f_wdt_sem;
static unsigned expect_close; static unsigned expect_close;
static spinlock_t io_lock; static spinlock_t io_lock;
static unsigned char revision;
/* Dog Food address - We use the game port address */ /* Dog Food address - We use the game port address */
static unsigned short address; static unsigned short address;
@ -108,6 +111,15 @@ superio_inw(int reg)
return val; return val;
} }
static void
superio_outw(int val, int reg)
{
outb(reg++, REG);
outb((val >> 8) & 0xff, VAL);
outb(reg, REG);
outb(val & 0xff, VAL);
}
static inline void static inline void
superio_select(int ldn) superio_select(int ldn)
{ {
@ -143,15 +155,33 @@ static void
it8712f_wdt_update_margin(void) it8712f_wdt_update_margin(void)
{ {
int config = WDT_OUT_KRST | WDT_OUT_PWROK; int config = WDT_OUT_KRST | WDT_OUT_PWROK;
int units = margin;
printk(KERN_INFO NAME ": timer margin %d seconds\n", margin); /* Switch to minutes precision if the configured margin
* value does not fit within the register width.
/* The timeout register only has 8bits wide */ */
if (margin < 256) if (units <= max_units) {
config |= WDT_UNIT_SEC; /* else UNIT are MINUTES */ config |= WDT_UNIT_SEC; /* else UNIT is MINUTES */
printk(KERN_INFO NAME ": timer margin %d seconds\n", units);
} else {
units /= 60;
printk(KERN_INFO NAME ": timer margin %d minutes\n", units);
}
superio_outb(config, WDT_CONFIG); superio_outb(config, WDT_CONFIG);
superio_outb((margin > 255) ? (margin / 60) : margin, WDT_TIMEOUT); if (revision >= 0x08)
superio_outw(units, WDT_TIMEOUT);
else
superio_outb(units, WDT_TIMEOUT);
}
static int
it8712f_wdt_get_status(void)
{
if (superio_inb(WDT_CONTROL) & 0x01)
return WDIOF_CARDRESET;
else
return 0;
} }
static void static void
@ -234,7 +264,7 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
.firmware_version = 1, .firmware_version = 1,
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
}; };
int new_margin; int value;
switch (cmd) { switch (cmd) {
default: default:
@ -244,17 +274,27 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
return -EFAULT; return -EFAULT;
return 0; return 0;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
superio_enter();
superio_select(LDN_GPIO);
value = it8712f_wdt_get_status();
superio_exit();
return put_user(value, p);
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
return put_user(0, p); return put_user(0, p);
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
it8712f_wdt_ping(); it8712f_wdt_ping();
return 0; return 0;
case WDIOC_SETTIMEOUT: case WDIOC_SETTIMEOUT:
if (get_user(new_margin, p)) if (get_user(value, p))
return -EFAULT; return -EFAULT;
if (new_margin < 1) if (value < 1)
return -EINVAL; return -EINVAL;
margin = new_margin; if (value > (max_units * 60))
return -EINVAL;
margin = value;
superio_enter(); superio_enter();
superio_select(LDN_GPIO); superio_select(LDN_GPIO);
@ -262,6 +302,7 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
superio_exit(); superio_exit();
it8712f_wdt_ping(); it8712f_wdt_ping();
/* Fall through */
case WDIOC_GETTIMEOUT: case WDIOC_GETTIMEOUT:
if (put_user(margin, p)) if (put_user(margin, p))
return -EFAULT; return -EFAULT;
@ -336,9 +377,18 @@ it8712f_wdt_find(unsigned short *address)
} }
err = 0; err = 0;
printk(KERN_DEBUG NAME ": Found IT%04xF chip revision %d - " revision = superio_inb(DEVREV) & 0x0f;
/* Later revisions have 16-bit values per datasheet 0.9.1 */
if (revision >= 0x08)
max_units = 65535;
if (margin > (max_units * 60))
margin = (max_units * 60);
printk(KERN_INFO NAME ": Found IT%04xF chip revision %d - "
"using DogFood address 0x%x\n", "using DogFood address 0x%x\n",
chip_type, superio_inb(DEVREV) & 0x0f, *address); chip_type, revision, *address);
exit: exit:
superio_exit(); superio_exit();

View File

@ -141,7 +141,7 @@ static unsigned long next_heartbeat = 0;
#ifndef ZF_DEBUG #ifndef ZF_DEBUG
# define dprintk(format, args...) # define dprintk(format, args...)
#else #else
# define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __FUNCTION__, __LINE__ , ## args) # define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __func__, __LINE__ , ## args)
#endif #endif

View File

@ -59,9 +59,9 @@ static int ticks = 100 * HZ;
static struct { static struct {
struct completion stop; struct completion stop;
volatile int running; int running;
struct timer_list timer; struct timer_list timer;
volatile int queue; int queue;
int default_ticks; int default_ticks;
unsigned long inuse; unsigned long inuse;
unsigned gpio; unsigned gpio;

View File

@ -179,11 +179,11 @@ static void usb_pcwd_intr_done(struct urb *urb)
case -ENOENT: case -ENOENT:
case -ESHUTDOWN: case -ESHUTDOWN:
/* this urb is terminated, clean up */ /* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); dbg("%s - urb shutting down with status: %d", __func__, urb->status);
return; return;
/* -EPIPE: should clear the halt */ /* -EPIPE: should clear the halt */
default: /* error */ default: /* error */
dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); dbg("%s - nonzero urb status received: %d", __func__, urb->status);
goto resubmit; goto resubmit;
} }

View File

@ -144,7 +144,7 @@ static int s3c2410wdt_start(void)
} }
DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n", DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n",
__FUNCTION__, wdt_count, wtcon); __func__, wdt_count, wtcon);
writel(wdt_count, wdt_base + S3C2410_WTDAT); writel(wdt_count, wdt_base + S3C2410_WTDAT);
writel(wdt_count, wdt_base + S3C2410_WTCNT); writel(wdt_count, wdt_base + S3C2410_WTCNT);
@ -167,7 +167,7 @@ static int s3c2410wdt_set_heartbeat(int timeout)
count = timeout * freq; count = timeout * freq;
DBG("%s: count=%d, timeout=%d, freq=%d\n", DBG("%s: count=%d, timeout=%d, freq=%d\n",
__FUNCTION__, count, timeout, freq); __func__, count, timeout, freq);
/* if the count is bigger than the watchdog register, /* if the count is bigger than the watchdog register,
then work out what we need to do (and if) we can then work out what we need to do (and if) we can
@ -189,7 +189,7 @@ static int s3c2410wdt_set_heartbeat(int timeout)
tmr_margin = timeout; tmr_margin = timeout;
DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n", DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n",
__FUNCTION__, timeout, divisor, count, count/divisor); __func__, timeout, divisor, count, count/divisor);
count /= divisor; count /= divisor;
wdt_count = count; wdt_count = count;
@ -355,7 +355,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
int ret; int ret;
int size; int size;
DBG("%s: probe=%p\n", __FUNCTION__, pdev); DBG("%s: probe=%p\n", __func__, pdev);
dev = &pdev->dev; dev = &pdev->dev;
wdt_dev = &pdev->dev; wdt_dev = &pdev->dev;

View File

@ -298,7 +298,7 @@ static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) { PAGE_SIZE, vma->vm_page_prot)) {
printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n", printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
__FUNCTION__); __func__);
return -EAGAIN; return -EAGAIN;
} }