aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/battery.c2
-rw-r--r--drivers/acpi/numa.c4
-rw-r--r--drivers/acpi/pci_bind.c3
-rw-r--r--drivers/acpi/sbs.c27
-rw-r--r--drivers/acpi/sbshc.c17
-rw-r--r--drivers/acpi/sbshc.h6
-rw-r--r--drivers/acpi/video.c4
-rw-r--r--drivers/atm/fore200e.c3
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c2
-rw-r--r--drivers/ide/Kconfig6
-rw-r--r--drivers/ide/ide-cd.c35
-rw-r--r--drivers/ide/ide-disk.c33
-rw-r--r--drivers/ide/ide-dma.c66
-rw-r--r--drivers/ide/ide-io.c3
-rw-r--r--drivers/ide/ide-iops.c3
-rw-r--r--drivers/ide/ide-lib.c55
-rw-r--r--drivers/ide/ide-probe.c21
-rw-r--r--drivers/ide/ide.c30
-rw-r--r--drivers/ide/pci/hpt366.c71
-rw-r--r--drivers/ide/pci/pdc202xx_new.c3
-rw-r--r--drivers/ide/setup-pci.c31
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c15
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c4
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.c27
-rw-r--r--drivers/infiniband/hw/ehca/hipz_hw.h1
-rw-r--r--drivers/media/Makefile2
-rw-r--r--drivers/media/dvb/frontends/s5h1409.c11
-rw-r--r--drivers/media/video/bt866.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c1
-rw-r--r--drivers/media/video/videobuf-core.c4
-rw-r--r--drivers/misc/thinkpad_acpi.c4
-rw-r--r--drivers/net/fs_enet/mac-scc.c2
-rw-r--r--drivers/net/irda/irda-usb.c5
-rw-r--r--drivers/net/irda/mcs7780.c2
-rw-r--r--drivers/net/irda/stir4200.c10
-rw-r--r--drivers/net/wan/syncppp.c35
-rw-r--r--drivers/sbus/char/cpwatchdog.c2
-rw-r--r--drivers/scsi/ide-scsi.c17
-rw-r--r--drivers/watchdog/Kconfig23
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/at32ap700x_wdt.c69
-rw-r--r--drivers/watchdog/bfin_wdt.c2
-rw-r--r--drivers/watchdog/it8712f_wdt.c400
-rw-r--r--drivers/watchdog/sbc7240_wdt.c324
-rw-r--r--drivers/watchdog/w83697hf_wdt.c4
46 files changed, 1119 insertions, 274 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 7d6be23eff8..8f7505d304b 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -125,7 +125,7 @@ static int acpi_battery_technology(struct acpi_battery *battery)
return POWER_SUPPLY_TECHNOLOGY_NiMH;
if (!strcasecmp("LION", battery->type))
return POWER_SUPPLY_TECHNOLOGY_LION;
- if (!strcasecmp("LI-ION", battery->type))
+ if (!strncasecmp("LI-ION", battery->type, 6))
return POWER_SUPPLY_TECHNOLOGY_LION;
if (!strcasecmp("LiP", battery->type))
return POWER_SUPPLY_TECHNOLOGY_LIPO;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index ab04d848b19..0822d9fc1cb 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -38,9 +38,9 @@ ACPI_MODULE_NAME("numa");
static nodemask_t nodes_found_map = NODE_MASK_NONE;
/* maps to convert between proximity domain and logical node ID */
-static int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS]
+static int pxm_to_node_map[MAX_PXM_DOMAINS]
= { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL };
-static int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]
+static int node_to_pxm_map[MAX_NUMNODES]
= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
int pxm_to_node(int pxm)
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 028969370bb..388300de005 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -294,9 +294,6 @@ int acpi_pci_unbind(struct acpi_device *device)
acpi_get_data(device->handle, acpi_pci_data_handler,
(void **)&data);
if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "Unable to get data from device %s",
- acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 6045cdbe176..22cb95b349e 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -54,12 +54,6 @@
#define ACPI_BATTERY_DIR_NAME "BAT%i"
#define ACPI_AC_DIR_NAME "AC0"
-enum acpi_sbs_device_addr {
- ACPI_SBS_CHARGER = 0x9,
- ACPI_SBS_MANAGER = 0xa,
- ACPI_SBS_BATTERY = 0xb,
-};
-
#define ACPI_SBS_NOTIFY_STATUS 0x80
#define ACPI_SBS_NOTIFY_INFO 0x81
@@ -539,7 +533,7 @@ static struct proc_dir_entry *acpi_battery_dir = NULL;
static inline char *acpi_battery_units(struct acpi_battery *battery)
{
- return acpi_battery_mode(battery) ? " mWh" : " mAh";
+ return acpi_battery_mode(battery) ? " mW" : " mA";
}
@@ -556,10 +550,10 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
if (!battery->present)
goto end;
- seq_printf(seq, "design capacity: %i%s\n",
+ seq_printf(seq, "design capacity: %i%sh\n",
battery->design_capacity * acpi_battery_scale(battery),
acpi_battery_units(battery));
- seq_printf(seq, "last full capacity: %i%s\n",
+ seq_printf(seq, "last full capacity: %i%sh\n",
battery->full_charge_capacity * acpi_battery_scale(battery),
acpi_battery_units(battery));
seq_printf(seq, "battery technology: rechargeable\n");
@@ -590,7 +584,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
{
struct acpi_battery *battery = seq->private;
struct acpi_sbs *sbs = battery->sbs;
- int result = 0;
+ int rate;
mutex_lock(&sbs->lock);
seq_printf(seq, "present: %s\n",
@@ -604,9 +598,12 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
seq_printf(seq, "charging state: %s\n",
(battery->current_now < 0) ? "discharging" :
((battery->current_now > 0) ? "charging" : "charged"));
- seq_printf(seq, "present rate: %d mA\n",
- abs(battery->current_now) * acpi_battery_ipscale(battery));
- seq_printf(seq, "remaining capacity: %i%s\n",
+ rate = abs(battery->current_now) * acpi_battery_ipscale(battery);
+ rate *= (acpi_battery_mode(battery))?(battery->voltage_now *
+ acpi_battery_vscale(battery)/1000):1;
+ seq_printf(seq, "present rate: %d%s\n", rate,
+ acpi_battery_units(battery));
+ seq_printf(seq, "remaining capacity: %i%sh\n",
battery->capacity_now * acpi_battery_scale(battery),
acpi_battery_units(battery));
seq_printf(seq, "present voltage: %i mV\n",
@@ -614,7 +611,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
end:
mutex_unlock(&sbs->lock);
- return result;
+ return 0;
}
static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
@@ -638,7 +635,7 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
acpi_battery_get_alarm(battery);
seq_printf(seq, "alarm: ");
if (battery->alarm_capacity)
- seq_printf(seq, "%i%s\n",
+ seq_printf(seq, "%i%sh\n",
battery->alarm_capacity *
acpi_battery_scale(battery),
acpi_battery_units(battery));
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index 046d7c3ed35..fd40b6a1d63 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -202,10 +202,9 @@ int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc)
EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback);
-static void acpi_smbus_callback(void *context)
+static inline void acpi_smbus_callback(void *context)
{
struct acpi_smb_hc *hc = context;
-
if (hc->callback)
hc->callback(hc->context);
}
@@ -214,6 +213,7 @@ static int smbus_alarm(void *context)
{
struct acpi_smb_hc *hc = context;
union acpi_smb_status status;
+ u8 address;
if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw))
return 0;
/* Check if it is only a completion notify */
@@ -222,9 +222,18 @@ static int smbus_alarm(void *context)
if (!status.fields.alarm)
return 0;
mutex_lock(&hc->lock);
+ smb_hc_read(hc, ACPI_SMB_ALARM_ADDRESS, &address);
+ status.fields.alarm = 0;
smb_hc_write(hc, ACPI_SMB_STATUS, status.raw);
- if (hc->callback)
- acpi_os_execute(OSL_GPE_HANDLER, acpi_smbus_callback, hc);
+ /* We are only interested in events coming from known devices */
+ switch (address >> 1) {
+ case ACPI_SBS_CHARGER:
+ case ACPI_SBS_MANAGER:
+ case ACPI_SBS_BATTERY:
+ acpi_os_execute(OSL_GPE_HANDLER,
+ acpi_smbus_callback, hc);
+ default:;
+ }
mutex_unlock(&hc->lock);
return 0;
}
diff --git a/drivers/acpi/sbshc.h b/drivers/acpi/sbshc.h
index 3bda3491a97..a57b0762dd7 100644
--- a/drivers/acpi/sbshc.h
+++ b/drivers/acpi/sbshc.h
@@ -16,6 +16,12 @@ enum acpi_smb_protocol {
static const u8 SMBUS_PEC = 0x80;
+enum acpi_sbs_device_addr {
+ ACPI_SBS_CHARGER = 0x9,
+ ACPI_SBS_MANAGER = 0xa,
+ ACPI_SBS_BATTERY = 0xb,
+};
+
typedef void (*smbus_alarm_callback)(void *context);
extern int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address,
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 44a0d9ba9bd..bd77e81e81c 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -577,7 +577,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
struct acpi_video_device_brightness *br = NULL;
- memset(&device->cap, 0, 4);
+ memset(&device->cap, 0, sizeof(device->cap));
if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) {
device->cap._ADR = 1;
@@ -697,7 +697,7 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
{
acpi_handle h_dummy1;
- memset(&video->cap, 0, 4);
+ memset(&video->cap, 0, sizeof(video->cap));
if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) {
video->cap._DOS = 1;
}
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 8b12925fe7a..f97e050338f 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -2689,7 +2689,7 @@ fore200e_init(struct fore200e* fore200e)
return 0;
}
-
+#ifdef CONFIG_ATM_FORE200E_PCA
static int __devinit
fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
{
@@ -2756,7 +2756,6 @@ static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev)
}
-#ifdef CONFIG_ATM_FORE200E_PCA
static struct pci_device_id fore200e_pca_tbl[] = {
{ PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID,
0, 0, (unsigned long) &fore200e_bus[0] },
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index e686fc92516..8f45ca9235a 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -669,6 +669,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
return 0;
case WDIOC_SET_PRETIMEOUT:
+ case WDIOC_SETPRETIMEOUT:
i = copy_from_user(&val, argp, sizeof(int));
if (i)
return -EFAULT;
@@ -676,6 +677,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
case WDIOC_GET_PRETIMEOUT:
+ case WDIOC_GETPRETIMEOUT:
i = copy_to_user(argp, &pretimeout, sizeof(pretimeout));
if (i)
return -EFAULT;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 45b22282f14..fb06555708a 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -390,7 +390,7 @@ config IDEPCI_PCIBUS_ORDER
# TODO: split it on per host driver config options (or module parameters)
config BLK_DEV_OFFBOARD
- bool "Boot off-board chipsets first support"
+ bool "Boot off-board chipsets first support (DEPRECATED)"
depends on BLK_DEV_IDEPCI && (BLK_DEV_AEC62XX || BLK_DEV_GENERIC || BLK_DEV_HPT34X || BLK_DEV_HPT366 || BLK_DEV_PDC202XX_NEW || BLK_DEV_PDC202XX_OLD || BLK_DEV_TC86C001)
help
Normally, IDE controllers built into the motherboard (on-board
@@ -410,6 +410,10 @@ config BLK_DEV_OFFBOARD
Note that, if you do this, the order of the hd* devices will be
rearranged which may require modification of fstab and other files.
+ Please also note that this method of assuring stable naming of
+ IDE devices is unreliable and use other means for achieving it
+ (i.e. udev).
+
If in doubt, say N.
config BLK_DEV_GENERIC
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 57a5f63d6ae..92ac658dac3 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1650,31 +1650,6 @@ static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
return 1;
}
-static void post_transform_command(struct request *req)
-{
- u8 *c = req->cmd;
- char *ibuf;
-
- if (!blk_pc_request(req))
- return;
-
- if (req->bio)
- ibuf = bio_data(req->bio);
- else
- ibuf = req->data;
-
- if (!ibuf)
- return;
-
- /*
- * set ansi-revision and response data as atapi
- */
- if (c[0] == GPCMD_INQUIRY) {
- ibuf[2] |= 2;
- ibuf[3] = (ibuf[3] & 0xf0) | 2;
- }
-}
-
typedef void (xfer_func_t)(ide_drive_t *, void *, u32);
/*
@@ -1810,9 +1785,6 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
return ide_started;
end_request:
- if (!rq->data_len)
- post_transform_command(rq);
-
spin_lock_irqsave(&ide_lock, flags);
blkdev_dequeue_request(rq);
end_that_request_last(rq, 1);
@@ -3049,12 +3021,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
else
printk(" drive");
- printk(", %dkB Cache", be16_to_cpu(cap.buffer_size));
-
- if (drive->using_dma)
- ide_dma_verbose(drive);
-
- printk("\n");
+ printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(cap.buffer_size));
return nslots;
}
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 00123d99527..b1781908e1f 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -13,32 +13,6 @@
* and Andre Hedrick <andre@linux-ide.org>
*
* This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
- *
- * Version 1.00 move disk only code from ide.c to ide-disk.c
- * support optional byte-swapping of all data
- * Version 1.01 fix previous byte-swapping code
- * Version 1.02 remove ", LBA" from drive identification msgs
- * Version 1.03 fix display of id->buf_size for big-endian
- * Version 1.04 add /proc configurable settings and S.M.A.R.T support
- * Version 1.05 add capacity support for ATA3 >= 8GB
- * Version 1.06 get boot-up messages to show full cyl count
- * Version 1.07 disable door-locking if it fails
- * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB,
- * process of adding new ATA4 compliance.
- * fixed problems in allowing fdisk to see
- * the entire disk.
- * Version 1.09 added increment of rq->sector in ide_multwrite
- * added UDMA 3/4 reporting
- * Version 1.10 request queue changes, Ultra DMA 100
- * Version 1.11 added 48-bit lba
- * Version 1.12 adding taskfile io access method
- * Version 1.13 added standby and flush-cache for notifier
- * Version 1.14 added acoustic-wcache
- * Version 1.15 convert all calls to ide_raw_taskfile
- * since args will return register content.
- * Version 1.16 added suspend-resume-checkpower
- * Version 1.17 do flush on standby, do flush on ATA < ATA6
- * fix wcache setup.
*/
#define IDEDISK_VERSION "1.18"
@@ -961,11 +935,8 @@ static void idedisk_setup (ide_drive_t *drive)
if (id->buf_size)
printk (" w/%dKiB Cache", id->buf_size/2);
- printk(", CHS=%d/%d/%d",
- drive->bios_cyl, drive->bios_head, drive->bios_sect);
- if (drive->using_dma)
- ide_dma_verbose(drive);
- printk("\n");
+ printk(KERN_CONT ", CHS=%d/%d/%d\n",
+ drive->bios_cyl, drive->bios_head, drive->bios_sect);
/* write cache enabled? */
if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5)))
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 0d795a1678c..4703837bf1f 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -611,12 +611,6 @@ static int __ide_dma_test_irq(ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
u8 dma_stat = hwif->INB(hwif->dma_status);
-#if 0 /* do not set unless you know what you are doing */
- if (dma_stat & 4) {
- u8 stat = hwif->INB(IDE_STATUS_REG);
- hwif->OUTB(hwif->dma_status, dma_stat & 0xE4);
- }
-#endif
/* return 1 if INTR asserted */
if ((dma_stat & 4) == 4)
return 1;
@@ -753,10 +747,12 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
mode = XFER_MW_DMA_1;
}
- printk(KERN_DEBUG "%s: %s mode selected\n", drive->name,
+ mode = min(mode, req_mode);
+
+ printk(KERN_INFO "%s: %s mode selected\n", drive->name,
mode ? ide_xfer_verbose(mode) : "no DMA");
- return min(mode, req_mode);
+ return mode;
}
EXPORT_SYMBOL_GPL(ide_find_dma_mode);
@@ -772,6 +768,9 @@ static int ide_tune_dma(ide_drive_t *drive)
if (__ide_dma_bad_drive(drive))
return 0;
+ if (ide_id_dma_bug(drive))
+ return 0;
+
if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
return config_drive_for_dma(drive);
@@ -806,58 +805,23 @@ static int ide_dma_check(ide_drive_t *drive)
return vdma ? 0 : -1;
}
-void ide_dma_verbose(ide_drive_t *drive)
+int ide_id_dma_bug(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
+ struct hd_driveid *id = drive->id;
if (id->field_valid & 4) {
if ((id->dma_ultra >> 8) && (id->dma_mword >> 8))
- goto bug_dma_off;
- if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) {
- if (((id->dma_ultra >> 11) & 0x1F) &&
- eighty_ninty_three(drive)) {
- if ((id->dma_ultra >> 15) & 1) {
- printk(", UDMA(mode 7)");
- } else if ((id->dma_ultra >> 14) & 1) {
- printk(", UDMA(133)");
- } else if ((id->dma_ultra >> 13) & 1) {
- printk(", UDMA(100)");
- } else if ((id->dma_ultra >> 12) & 1) {
- printk(", UDMA(66)");
- } else if ((id->dma_ultra >> 11) & 1) {
- printk(", UDMA(44)");
- } else
- goto mode_two;
- } else {
- mode_two:
- if ((id->dma_ultra >> 10) & 1) {
- printk(", UDMA(33)");
- } else if ((id->dma_ultra >> 9) & 1) {
- printk(", UDMA(25)");
- } else if ((id->dma_ultra >> 8) & 1) {
- printk(", UDMA(16)");
- }
- }
- } else {
- printk(", (U)DMA"); /* Can be BIOS-enabled! */
- }
+ goto err_out;
} else if (id->field_valid & 2) {
if ((id->dma_mword >> 8) && (id->dma_1word >> 8))
- goto bug_dma_off;
- printk(", DMA");
- } else if (id->field_valid & 1) {
- goto bug_dma_off;
+ goto err_out;
}
- return;
-bug_dma_off:
- printk(", BUG DMA OFF");
- hwif->dma_off_quietly(drive);
- return;
+ return 0;
+err_out:
+ printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name);
+ return 1;
}
-EXPORT_SYMBOL(ide_dma_verbose);
-
int ide_set_dma(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index db22d1ff4e5..bef781fec50 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -970,7 +970,8 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
if (rc)
printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
SELECT_DRIVE(drive);
- HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
+ if (IDE_CONTROL_REG)
+ HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
rc = ide_wait_not_busy(HWIF(drive), 100000);
if (rc)
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 5c3256180ae..cef405ddaf0 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -748,6 +748,9 @@ int ide_driveid_update(ide_drive_t *drive)
drive->id->dma_1word = id->dma_1word;
/* anything more ? */
kfree(id);
+
+ if (drive->using_dma && ide_id_dma_bug(drive))
+ ide_dma_off(drive);
}
return 1;
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 1609b8604f5..062d3bcb247 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -29,41 +29,44 @@
* Add common non I/O op stuff here. Make sure it has proper
* kernel-doc function headers or your patch will be rejected
*/
-
+
+static const char *udma_str[] =
+ { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
+ "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
+static const char *mwdma_str[] =
+ { "MWDMA0", "MWDMA1", "MWDMA2" };
+static const char *swdma_str[] =
+ { "SWDMA0", "SWDMA1", "SWDMA2" };
+static const char *pio_str[] =
+ { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
/**
* ide_xfer_verbose - return IDE mode names
- * @xfer_rate: rate to name
+ * @mode: transfer mode
*
* Returns a constant string giving the name of the mode
* requested.
*/
-char *ide_xfer_verbose (u8 xfer_rate)
+const char *ide_xfer_verbose(u8 mode)
{
- switch(xfer_rate) {
- case XFER_UDMA_7: return("UDMA 7");
- case XFER_UDMA_6: return("UDMA 6");
- case XFER_UDMA_5: return("UDMA 5");
- case XFER_UDMA_4: return("UDMA 4");
- case XFER_UDMA_3: return("UDMA 3");
- case XFER_UDMA_2: return("UDMA 2");
- case XFER_UDMA_1: return("UDMA 1");
- case XFER_UDMA_0: return("UDMA 0");
- case XFER_MW_DMA_2: return("MW DMA 2");
- case XFER_MW_DMA_1: return("MW DMA 1");
- case XFER_MW_DMA_0: return("MW DMA 0");
- case XFER_SW_DMA_2: return("SW DMA 2");
- case XFER_SW_DMA_1: return("SW DMA 1");
- case XFER_SW_DMA_0: return("SW DMA 0");
- case XFER_PIO_4: return("PIO 4");
- case XFER_PIO_3: return("PIO 3");
- case XFER_PIO_2: return("PIO 2");
- case XFER_PIO_1: return("PIO 1");
- case XFER_PIO_0: return("PIO 0");
- case XFER_PIO_SLOW: return("PIO SLOW");
- default: return("XFER ERROR");
- }
+ const char *s;
+ u8 i = mode & 0xf;
+
+ if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
+ s = udma_str[i];
+ else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
+ s = mwdma_str[i];
+ else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
+ s = swdma_str[i];
+ else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
+ s = pio_str[i & 0x7];
+ else if (mode == XFER_PIO_SLOW)
+ s = "PIO SLOW";
+ else
+ s = "XFER ERROR";
+
+ return s;
}
EXPORT_SYMBOL(ide_xfer_verbose);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index ee848c70599..2994523be7b 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -13,22 +13,8 @@
*
* This is the IDE probe module, as evolved from hd.c and ide.c.
*
- * Version 1.00 move drive probing code from ide.c to ide-probe.c
- * Version 1.01 fix compilation problem for m68k
- * Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot
- * by Andrea Arcangeli
- * Version 1.03 fix for (hwif->chipset == ide_4drives)
- * Version 1.04 fixed buggy treatments of known flash memory cards
- *
- * Version 1.05 fix for (hwif->chipset == ide_pdc4030)
- * added ide6/7/8/9
- * allowed for secondary flash card to be detectable
- * with new flag : drive->ata_flash : 1;
- * Version 1.06 stream line request queue and prep for cascade project.
- * Version 1.07 max_sect <= 255; slower disks would get behind and
- * then fall over when they get to 256. Paul G.
- * Version 1.10 Update set for new IDE. drive->id is now always
- * valid after probe time even with noprobe
+ * -- increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot
+ * by Andrea Arcangeli
*/
#include <linux/module.h>
@@ -667,7 +653,8 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
/* Ignore disks that we will not probe for later. */
if (!drive->noprobe || drive->present) {
SELECT_DRIVE(drive);
- hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ if (IDE_CONTROL_REG)
+ hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
mdelay(2);
rc = ide_wait_not_busy(hwif, 35000);
if (rc)
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 674a65c1a13..54943da6e4e 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -800,11 +800,17 @@ int set_io_32bit(ide_drive_t *drive, int arg)
if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
return -EINVAL;
+ if (ide_spin_wait_hwgroup(drive))
+ return -EBUSY;
+
drive->io_32bit = arg;
#ifdef CONFIG_BLK_DEV_DTC2278
if (HWIF(drive)->chipset == ide_dtc2278)
HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
#endif /* CONFIG_BLK_DEV_DTC2278 */
+
+ spin_unlock_irq(&ide_lock);
+
return 0;
}
@@ -1670,10 +1676,34 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "ide:m-%s\n", media_string(drive));
}
+static ssize_t model_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->id->model);
+}
+
+static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->id->fw_rev);
+}
+
+static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->id->serial_no);
+}
+
static struct device_attribute ide_dev_attrs[] = {
__ATTR_RO(media),
__ATTR_RO(drivename),
__ATTR_RO(modalias),
+ __ATTR_RO(model),
+ __ATTR_RO(firmware),
+ __ATTR(serial, 0400, serial_show, NULL),
__ATTR_NULL
};
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 5682895d36d..9fce25bdec8 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 1.21 Oct 23, 2007
+ * linux/drivers/ide/pci/hpt366.c Version 1.22 Dec 4, 2007
*
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
@@ -310,6 +310,8 @@ static u32 twenty_five_base_hpt36x[] = {
/* XFER_PIO_0 */ 0xc0d08585
};
+#if 0
+/* These are the timing tables from the HighPoint open source drivers... */
static u32 thirty_three_base_hpt37x[] = {
/* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */
/* XFER_UDMA_5 */ 0x12446231,
@@ -369,6 +371,73 @@ static u32 sixty_six_base_hpt37x[] = {
/* XFER_PIO_1 */ 0x0d029d26,
/* XFER_PIO_0 */ 0x0d029d5e
};
+#else
+/*
+ * The following are the new timing tables with PIO mode data/taskfile transfer
+ * overclocking fixed...
+ */
+
+/* This table is taken from the HPT370 data manual rev. 1.02 */
+static u32 thirty_three_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x16455031, /* 0x16655031 ?? */
+ /* XFER_UDMA_5 */ 0x16455031,
+ /* XFER_UDMA_4 */ 0x16455031,
+ /* XFER_UDMA_3 */ 0x166d5031,
+ /* XFER_UDMA_2 */ 0x16495031,
+ /* XFER_UDMA_1 */ 0x164d5033,
+ /* XFER_UDMA_0 */ 0x16515097,
+
+ /* XFER_MW_DMA_2 */ 0x26515031,
+ /* XFER_MW_DMA_1 */ 0x26515033,
+ /* XFER_MW_DMA_0 */ 0x26515097,
+
+ /* XFER_PIO_4 */ 0x06515021,
+ /* XFER_PIO_3 */ 0x06515022,
+ /* XFER_PIO_2 */ 0x06515033,
+ /* XFER_PIO_1 */ 0x06915065,
+ /* XFER_PIO_0 */ 0x06d1508a
+};
+
+static u32 fifty_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x1a861842,
+ /* XFER_UDMA_5 */ 0x1a861842,
+ /* XFER_UDMA_4 */ 0x1aae1842,
+ /* XFER_UDMA_3 */ 0x1a8e1842,
+ /* XFER_UDMA_2 */ 0x1a0e1842,
+ /* XFER_UDMA_1 */ 0x1a161854,
+ /* XFER_UDMA_0 */ 0x1a1a18ea,
+
+ /* XFER_MW_DMA_2 */ 0x2a821842,
+ /* XFER_MW_DMA_1 */ 0x2a821854,
+ /* XFER_MW_DMA_0 */ 0x2a8218ea,
+
+ /* XFER_PIO_4 */ 0x0a821842,
+ /* XFER_PIO_3 */ 0x0a821843,
+ /* XFER_PIO_2 */ 0x0a821855,
+ /* XFER_PIO_1 */ 0x0ac218a8,
+ /* XFER_PIO_0 */ 0x0b02190c
+};
+
+static u32 sixty_six_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x1c86fe62,
+ /* XFER_UDMA_5 */ 0x1caefe62, /* 0x1c8afe62 */
+ /* XFER_UDMA_4 */ 0x1c8afe62,
+ /* XFER_UDMA_3 */ 0x1c8efe62,
+ /* XFER_UDMA_2 */ 0x1c92fe62,
+ /* XFER_UDMA_1 */ 0x1c9afe62,
+ /* XFER_UDMA_0 */ 0x1c82fe62,
+
+ /* XFER_MW_DMA_2 */ 0x2c82fe62,
+ /* XFER_MW_DMA_1 */ 0x2c82fe66,
+ /* XFER_MW_DMA_0 */ 0x2c82ff2e,
+
+ /* XFER_PIO_4 */ 0x0c82fe62,
+ /* XFER_PIO_3 */ 0x0c82fe84,
+ /* XFER_PIO_2 */ 0x0c82fea6,
+ /* XFER_PIO_1 */ 0x0d02ff26,
+ /* XFER_PIO_0 */ 0x0d42ff7f
+};
+#endif
#define HPT366_DEBUG_DRIVE_INFO 0
#define HPT371_ALLOW_ATA133_6 1
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 4234efeba60..2b4f44e45a1 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -482,8 +482,9 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
{
struct pci_dev *dev2;
- dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 2,
+ dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1,
PCI_FUNC(dev->devfn)));
+
if (dev2 &&
dev2->vendor == dev->vendor &&
dev2->device == dev->device) {
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 25fd0905322..d2cd5a3d38f 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -704,7 +704,7 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
/*
* Module interfaces
*/
-
+
static int pre_init = 1; /* Before first ordered IDE scan */
static LIST_HEAD(ide_pci_drivers);
@@ -714,7 +714,7 @@ static LIST_HEAD(ide_pci_drivers);
* @module: owner module of the driver
*
* Registers a driver with the IDE layer. The IDE layer arranges that
- * boot time setup is done in the expected device order and then
+ * boot time setup is done in the expected device order and then
* hands the controllers off to the core PCI code to do the rest of
* the work.
*
@@ -724,13 +724,12 @@ static LIST_HEAD(ide_pci_drivers);
int __ide_pci_register_driver(struct pci_driver *driver, struct module *module,
const char *mod_name)
{
- if(!pre_init)
+ if (!pre_init)
return __pci_register_driver(driver, module, mod_name);
driver->driver.owner = module;
list_add_tail(&driver->node, &ide_pci_drivers);
return 0;
}
-
EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
/**
@@ -741,17 +740,18 @@ EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
* This is only used during boot up to get the ordering correct. After
* boot up the pci layer takes over the job.
*/
-
+
static int __init ide_scan_pcidev(struct pci_dev *dev)
{
struct list_head *l;
struct pci_driver *d;
-
+
list_for_each(l, &ide_pci_drivers) {
d = list_entry(l, struct pci_driver, node);
if (d->id_table) {
- const struct pci_device_id *id = pci_match_id(d->id_table,
- dev);
+ const struct pci_device_id *id =
+ pci_match_id(d->id_table, dev);
+
if (id != NULL && d->probe(dev, id) >= 0) {
dev->driver = d;
pci_dev_get(dev);
@@ -779,13 +779,13 @@ void __init ide_scan_pcibus (int scan_direction)
pre_init = 0;
if (!scan_direction)
- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
ide_scan_pcidev(dev);
else
- while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev))
- != NULL)
+ while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID,
+ dev)))
ide_scan_pcidev(dev);
-
+
/*
* Hand the drivers over to the PCI layer now we
* are post init.
@@ -794,9 +794,10 @@ void __init ide_scan_pcibus (int scan_direction)
list_for_each_safe(l, n, &ide_pci_drivers) {
list_del(l);
d = list_entry(l, struct pci_driver, node);
- if (__pci_register_driver(d, d->driver.owner, d->driver.mod_name))
- printk(KERN_ERR "%s: failed to register driver for %s\n",
- __FUNCTION__, d->driver.mod_name);
+ if (__pci_register_driver(d, d->driver.owner,
+ d->driver.mod_name))
+ printk(KERN_ERR "%s: failed to register %s driver\n",
+ __FUNCTION__, d->driver.mod_name);
}
}
#endif
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 87f12d4312a..74d2b72a11d 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -322,6 +322,7 @@ extern int ehca_static_rate;
extern int ehca_port_act_time;
extern int ehca_use_hp_mr;
extern int ehca_scaling_code;
+extern int ehca_lock_hcalls;
struct ipzu_queue_resp {
u32 qe_size; /* queue entry size */
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 90d4334179b..6a56d86a295 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -43,13 +43,14 @@
#ifdef CONFIG_PPC_64K_PAGES
#include <linux/slab.h>
#endif
+
#include "ehca_classes.h"
#include "ehca_iverbs.h"
#include "ehca_mrmw.h"
#include "ehca_tools.h"
#include "hcp_if.h"
-#define HCAD_VERSION "0024"
+#define HCAD_VERSION "0025"
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
@@ -66,6 +67,7 @@ int ehca_poll_all_eqs = 1;
int ehca_static_rate = -1;
int ehca_scaling_code = 0;
int ehca_mr_largepage = 1;
+int ehca_lock_hcalls = -1;
module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
module_param_named(debug_level, ehca_debug_level, int, S_IRUGO);
@@ -77,6 +79,7 @@ module_param_named(poll_all_eqs, ehca_poll_all_eqs, int, S_IRUGO);
module_param_named(static_rate, ehca_static_rate, int, S_IRUGO);
module_param_named(scaling_code, ehca_scaling_code, int, S_IRUGO);
module_param_named(mr_largepage, ehca_mr_largepage, int, S_IRUGO);
+module_param_named(lock_hcalls, ehca_lock_hcalls, bool, S_IRUGO);
MODULE_PARM_DESC(open_aqp1,
"AQP1 on startup (0: no (default), 1: yes)");
@@ -102,6 +105,9 @@ MODULE_PARM_DESC(scaling_code,
MODULE_PARM_DESC(mr_largepage,
"use large page for MR (0: use PAGE_SIZE (default), "
"1: use large page depending on MR size");
+MODULE_PARM_DESC(lock_hcalls,
+ "serialize all hCalls made by the driver "
+ "(default: autodetect)");
DEFINE_RWLOCK(ehca_qp_idr_lock);
DEFINE_RWLOCK(ehca_cq_idr_lock);
@@ -258,6 +264,7 @@ static struct cap_descr {
{ HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" },
{ HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" },
{ HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" },
+ { HCA_CAP_H_ALLOC_RES_SYNC, "HCA_CAP_H_ALLOC_RES_SYNC" },
};
static int ehca_sense_attributes(struct ehca_shca *shca)
@@ -333,6 +340,12 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap))
ehca_gen_dbg(" %s", hca_cap_descr[i].descr);
+ /* Autodetect hCall locking -- the "H_ALLOC_RESOURCE synced" flag is
+ * a firmware property, so it's valid across all adapters
+ */
+ if (ehca_lock_hcalls == -1)
+ ehca_lock_hcalls = !(shca->hca_cap & HCA_CAP_H_ALLOC_RES_SYNC);
+
/* translate supported MR page sizes; always support 4K */
shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
if (ehca_mr_largepage) { /* support extra sizes only if enabled */
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index dd126681fed..eff5fb55604 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -838,7 +838,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
/* copy back return values */
srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr;
- srq_init_attr->attr.max_sge = qp_init_attr.cap.max_recv_sge;
+ srq_init_attr->attr.max_sge = 3;
/* drive SRQ into RTR state */
mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
@@ -1750,7 +1750,7 @@ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
}
srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1;
- srq_attr->max_sge = qpcb->actual_nr_sges_in_rq_wqe;
+ srq_attr->max_sge = 3;
srq_attr->srq_limit = EHCA_BMASK_GET(
MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index c16a21374bb..7029aa65375 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -120,26 +120,21 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
unsigned long arg7)
{
long ret;
- int i, sleep_msecs, do_lock;
- unsigned long flags;
+ int i, sleep_msecs;
+ unsigned long flags = 0;
ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
- /* lock H_FREE_RESOURCE(MR) against itself and H_ALLOC_RESOURCE(MR) */
- if ((opcode == H_FREE_RESOURCE) && (arg7 == 5)) {
- arg7 = 0; /* better not upset firmware */
- do_lock = 1;
- }
-
for (i = 0; i < 5; i++) {
- if (do_lock)
+ /* serialize hCalls to work around firmware issue */
+ if (ehca_lock_hcalls)
spin_lock_irqsave(&hcall_lock, flags);
ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
arg5, arg6, arg7);
- if (do_lock)
+ if (ehca_lock_hcalls)
spin_unlock_irqrestore(&hcall_lock, flags);
if (H_IS_LONG_BUSY(ret)) {
@@ -174,24 +169,22 @@ static long ehca_plpar_hcall9(unsigned long opcode,
unsigned long arg9)
{
long ret;
- int i, sleep_msecs, do_lock;
+ int i, sleep_msecs;
unsigned long flags = 0;
ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
- /* lock H_ALLOC_RESOURCE(MR) against itself and H_FREE_RESOURCE(MR) */
- do_lock = ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5));
-
for (i = 0; i < 5; i++) {
- if (do_lock)
+ /* serialize hCalls to work around firmware issue */
+ if (ehca_lock_hcalls)
spin_lock_irqsave(&hcall_lock, flags);
ret = plpar_hcall9(opcode, outs,
arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9);
- if (do_lock)
+ if (ehca_lock_hcalls)
spin_unlock_irqrestore(&hcall_lock, flags);
if (H_IS_LONG_BUSY(ret)) {
@@ -821,7 +814,7 @@ u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
adapter_handle.handle, /* r4 */
mr->ipz_mr_handle.handle, /* r5 */
- 0, 0, 0, 0, 5);
+ 0, 0, 0, 0, 0);
}
u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h
index 485b8400359..bf996c7acc4 100644
--- a/drivers/infiniband/hw/ehca/hipz_hw.h
+++ b/drivers/infiniband/hw/ehca/hipz_hw.h
@@ -378,6 +378,7 @@ struct hipz_query_hca {
#define HCA_CAP_UD_LL_QP EHCA_BMASK_IBM(16, 16)
#define HCA_CAP_RESIZE_MR EHCA_BMASK_IBM(17, 17)
#define HCA_CAP_MINI_QP EHCA_BMASK_IBM(18, 18)
+#define HCA_CAP_H_ALLOC_RES_SYNC EHCA_BMASK_IBM(19, 19)
/* query port response block */
struct hipz_query_port {
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 8fa19939c2b..8cf91353b56 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -3,6 +3,6 @@
#
obj-y := common/
-obj-$(CONFIG_VIDEO_DEV) += video/
+obj-y += video/
obj-$(CONFIG_VIDEO_DEV) += radio/
obj-$(CONFIG_DVB_CORE) += dvb/
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index 8dee7ec9456..562d9208857 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -107,7 +107,7 @@ static struct vsb_snr_tab {
u16 val;
u16 data;
} vsb_snr_tab[] = {
- { 1023, 770, },
+ { 924, 300, },
{ 923, 300, },
{ 918, 295, },
{ 915, 290, },
@@ -154,6 +154,7 @@ static struct qam64_snr_tab {
u16 val;
u16 data;
} qam64_snr_tab[] = {
+ { 1, 0, },
{ 12, 300, },
{ 15, 290, },
{ 18, 280, },
@@ -217,6 +218,7 @@ static struct qam64_snr_tab {
{ 95, 202, },
{ 96, 201, },
{ 104, 200, },
+ { 255, 0, },
};
/* QAM256 SNR lookup table */
@@ -224,6 +226,7 @@ static struct qam256_snr_tab {
u16 val;
u16 data;
} qam256_snr_tab[] = {
+ { 1, 0, },
{ 12, 400, },
{ 13, 390, },
{ 15, 380, },
@@ -292,6 +295,7 @@ static struct qam256_snr_tab {
{ 105, 262, },
{ 106, 261, },
{ 110, 260, },
+ { 255, 0, },
};
/* 8 bit registers, 16 bit values */
@@ -670,14 +674,15 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
u16 reg;
dprintk("%s()\n", __FUNCTION__);
- reg = s5h1409_readreg(state, 0xf1) & 0x1ff;
-
switch(state->current_modulation) {
case QAM_64:
+ reg = s5h1409_readreg(state, 0xf0) & 0xff;
return s5h1409_qam64_lookup_snr(fe, snr, reg);
case QAM_256:
+ reg = s5h1409_readreg(state, 0xf0) & 0xff;
return s5h1409_qam256_lookup_snr(fe, snr, reg);
case VSB_8:
+ reg = s5h1409_readreg(state, 0xf1) & 0x3ff;
return s5h1409_vsb_lookup_snr(fe, snr, reg);
default:
break;
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
index b767b098d14..96b415576f0 100644
--- a/drivers/media/video/bt866.c
+++ b/drivers/media/video/bt866.c
@@ -300,7 +300,6 @@ static struct i2c_client bt866_client_tmpl =
.addr = 0,
.adapter = NULL,
.driver = &i2c_driver_bt866,
- .usage_count = 0
};
static int bt866_found_proc(struct i2c_adapter *adapter,
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index c6eb1e37a46..98c1b084a71 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -3221,6 +3221,7 @@ struct saa7134_board saa7134_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
+ .tuner_config = 1,
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_tv,
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
index 81f77d2b4bd..c8a5cb57963 100644
--- a/drivers/media/video/videobuf-core.c
+++ b/drivers/media/video/videobuf-core.c
@@ -909,7 +909,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
if (q->streaming)
goto done;
if (!q->reading) {
- retval = videobuf_read_start(q);
+ retval = __videobuf_read_start(q);
if (retval < 0)
goto done;
}
@@ -982,7 +982,7 @@ unsigned int videobuf_poll_stream(struct file *file,
struct videobuf_buffer, stream);
} else {
if (!q->reading)
- videobuf_read_start(q);
+ __videobuf_read_start(q);
if (!q->reading) {
rc = POLLERR;
} else if (NULL == q->read_buf) {
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index ab23a322158..cf56647a6ca 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -987,9 +987,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */
KEY_UNKNOWN, /* 0x0D: FN+INSERT */
KEY_UNKNOWN, /* 0x0E: FN+DELETE */
- KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */
+ KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
/* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
- KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */
+ KEY_RESERVED, /* 0x10: FN+END (brightness down) */
KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 03134f47a4e..48f2f300593 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -158,7 +158,7 @@ static int setup_data(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
struct fs_platform_info *fpi = fep->fpi;
fep->scc.idx = fs_get_scc_index(fpi->fs_no);
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index c6355c00fd7..9081234ab45 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1168,6 +1168,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self)
static int irda_usb_net_open(struct net_device *netdev)
{
struct irda_usb_cb *self;
+ unsigned long flags;
char hwname[16];
int i;
@@ -1177,13 +1178,16 @@ static int irda_usb_net_open(struct net_device *netdev)
self = (struct irda_usb_cb *) netdev->priv;
IRDA_ASSERT(self != NULL, return -1;);
+ spin_lock_irqsave(&self->lock, flags);
/* Can only open the device if it's there */
if(!self->present) {
+ spin_unlock_irqrestore(&self->lock, flags);
IRDA_WARNING("%s(), device not present!\n", __FUNCTION__);
return -1;
}
if(self->needspatch) {
+ spin_unlock_irqrestore(&self->lock, flags);
IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ;
return -EIO ;
}
@@ -1198,6 +1202,7 @@ static int irda_usb_net_open(struct net_device *netdev)
/* To do *before* submitting Rx urbs and starting net Tx queue
* Jean II */
self->netopen = 1;
+ spin_unlock_irqrestore(&self->lock, flags);
/*
* Now that everything should be initialized properly,
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index 0b769192d4c..93916cf33f2 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -677,6 +677,8 @@ static int mcs_net_close(struct net_device *netdev)
/* Stop transmit processing */
netif_stop_queue(netdev);
+ kfree_skb(mcs->rx_buff.skb);
+
/* kill and free the receive and transmit URBs */
usb_kill_urb(mcs->rx_urb);
usb_free_urb(mcs->rx_urb);
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 042bc2f0417..e59c485bc49 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -142,9 +142,6 @@ enum StirCtrl2Mask {
};
enum StirFifoCtlMask {
- FIFOCTL_EOF = 0x80,
- FIFOCTL_UNDER = 0x40,
- FIFOCTL_OVER = 0x20,
FIFOCTL_DIR = 0x10,
FIFOCTL_CLR = 0x08,
FIFOCTL_EMPTY = 0x04,
@@ -594,9 +591,10 @@ static int fifo_txwait(struct stir_cb *stir, int space)
{
int err;
unsigned long count, status;
+ unsigned long prev_count = 0x1fff;
/* Read FIFO status and count */
- for(;;) {
+ for (;; prev_count = count) {
err = read_reg(stir, REG_FIFOCTL, stir->fifo_status,
FIFO_REGS_SIZE);
if (unlikely(err != FIFO_REGS_SIZE)) {
@@ -629,6 +627,10 @@ static int fifo_txwait(struct stir_cb *stir, int space)
if (space >= 0 && STIR_FIFO_SIZE - 4 > space + count)
return 0;
+ /* queue confused */
+ if (prev_count < count)
+ break;
+
/* estimate transfer time for remaining chars */
msleep((count * 8000) / stir->speed);
}
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index 232ecba5340..61e24b7a45a 100644
--- a/drivers/net/wan/syncppp.c
+++ b/drivers/net/wan/syncppp.c
@@ -107,24 +107,24 @@
struct ppp_header {
u8 address;
u8 control;
- u16 protocol;
+ __be16 protocol;
};
#define PPP_HEADER_LEN sizeof (struct ppp_header)
struct lcp_header {
u8 type;
u8 ident;
- u16 len;
+ __be16 len;
};
#define LCP_HEADER_LEN sizeof (struct lcp_header)
struct cisco_packet {
- u32 type;
- u32 par1;
- u32 par2;
- u16 rel;
- u16 time0;
- u16 time1;
+ __be32 type;
+ __be32 par1;
+ __be32 par2;
+ __be16 rel;
+ __be16 time0;
+ __be16 time1;
};
#define CISCO_PACKET_LEN 18
#define CISCO_BIG_PACKET_LEN 20
@@ -139,7 +139,7 @@ static struct sk_buff_head tx_queue;
static void sppp_keepalive (unsigned long dummy);
static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type,
u8 ident, u16 len, void *data);
-static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2);
+static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2);
static void sppp_lcp_input (struct sppp *sp, struct sk_buff *m);
static void sppp_cisco_input (struct sppp *sp, struct sk_buff *m);
static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *m);
@@ -447,7 +447,7 @@ static void sppp_keepalive (unsigned long dummy)
sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq,
sp->pp_rseq);
else if (sp->lcp.state == LCP_STATE_OPENED) {
- long nmagic = htonl (sp->lcp.magic);
+ __be32 nmagic = htonl (sp->lcp.magic);
sp->lcp.echoid = ++sp->pp_seq;
sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ,
sp->lcp.echoid, 4, &nmagic);
@@ -667,7 +667,7 @@ badreq:
dev->name, len);
break;
}
- if (ntohl (*(long*)(h+1)) == sp->lcp.magic) {
+ if (ntohl (*(__be32*)(h+1)) == sp->lcp.magic) {
/* Line loopback mode detected. */
printk (KERN_WARNING "%s: loopback\n", dev->name);
if_down (dev);
@@ -680,7 +680,7 @@ badreq:
sppp_lcp_open (sp);
break;
}
- *(long*)(h+1) = htonl (sp->lcp.magic);
+ *(__be32 *)(h+1) = htonl (sp->lcp.magic);
sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1);
break;
case LCP_ECHO_REPLY:
@@ -692,7 +692,7 @@ badreq:
dev->name, len);
break;
}
- if (ntohl (*(long*)(h+1)) != sp->lcp.magic)
+ if (ntohl(*(__be32 *)(h+1)) != sp->lcp.magic)
sp->pp_alivecnt = 0;
break;
}
@@ -765,7 +765,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
{
struct in_device *in_dev;
struct in_ifaddr *ifa;
- __be32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
+ __be32 addr = 0, mask = htonl(~0U); /* FIXME: is the mask correct? */
#ifdef CONFIG_INET
rcu_read_lock();
if ((in_dev = __in_dev_get_rcu(dev)) != NULL)
@@ -782,8 +782,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
}
rcu_read_unlock();
#endif
- /* I hope both addr and mask are in the net order */
- sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask);
+ sppp_cisco_send (sp, CISCO_ADDR_REPLY, ntohl(addr), ntohl(mask));
break;
}
}
@@ -844,7 +843,7 @@ static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type,
* Send Cisco keepalive packet.
*/
-static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2)
+static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2)
{
struct ppp_header *h;
struct cisco_packet *ch;
@@ -868,7 +867,7 @@ static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2)
ch->type = htonl (type);
ch->par1 = htonl (par1);
ch->par2 = htonl (par2);
- ch->rel = -1;
+ ch->rel = htons(0xffff);
ch->time0 = htons ((u16) (t >> 16));
ch->time1 = htons ((u16) t);
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index 7b5773d8821..a4e75814366 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -154,7 +154,7 @@ struct wd_device {
};
static struct wd_device wd_dev = {
- 0, SPIN_LOCK_UNLOCKED, 0, 0, 0, 0,
+ 0, __SPIN_LOCK_UNLOCKED(wd_dev.lock), 0, 0, 0, 0,
};
static struct timer_list wd_timer;
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 7a835a35f21..9706de9d98d 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -242,6 +242,11 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
}
}
+static void ide_scsi_hex_dump(u8 *data, int len)
+{
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0);
+}
+
static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_command)
{
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
@@ -272,8 +277,7 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd;
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: queue cmd = ", drive->name);
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, pc->c,
- 6, 0);
+ ide_scsi_hex_dump(pc->c, 6);
}
rq->rq_disk = scsi->disk;
return ide_do_drive_cmd(drive, rq, ide_preempt);
@@ -328,8 +332,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer;
if (log) {
printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
- pc->buffer, 16, 0);
+ ide_scsi_hex_dump(pc->buffer, 16);
}
memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE);
kfree(pc->buffer);
@@ -808,12 +811,10 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
- cmd->cmnd, cmd->cmd_len, 0);
+ ide_scsi_hex_dump(cmd->cmnd, cmd->cmd_len);
if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) {
printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number);
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
- pc->c, 12, 0);
+ ide_scsi_hex_dump(pc->c, 12);
}
}
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 2792bc1a726..52dff40ec19 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -392,6 +392,16 @@ config ITCO_VENDOR_SUPPORT
devices. At this moment we only have additional support for some
SuperMicro Inc. motherboards.
+config IT8712F_WDT
+ tristate "IT8712F (Smart Guardian) Watchdog Timer"
+ depends on X86
+ ---help---
+ This is the driver for the built-in watchdog timer on the IT8712F
+ Super I/0 chipset used on many motherboards.
+
+ To compile this driver as a module, choose M here: the
+ module will be called it8712f_wdt.
+
config SC1200_WDT
tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
depends on X86
@@ -456,6 +466,19 @@ config SBC8360_WDT
Most people will say N.
+config SBC7240_WDT
+ tristate "SBC Nano 7240 Watchdog Timer"
+ depends on X86_32
+ ---help---
+ This is the driver for the hardware watchdog found on the IEI
+ single board computers EPIC Nano 7240 (and likely others). This
+ watchdog simply watches your kernel to make sure it doesn't freeze,
+ and if it does, it reboots your computer after a certain amount of
+ time.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sbc7240_wdt.
+
config CPU5_WDT
tristate "SMA CPU5 Watchdog"
depends on X86
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 7d9e5734f8b..87483cc6325 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,11 +66,13 @@ obj-$(CONFIG_IBMASR) += ibmasr.o
obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o
+obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o
obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o
obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
+obj-$(CONFIG_SBC7240_WDT) += sbc7240_wdt.o
obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o
obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index 54a516169d0..fb5ed6478f7 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -6,6 +6,19 @@
* 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.
+ *
+ *
+ * Errata: WDT Clear is blocked after WDT Reset
+ *
+ * A watchdog timer event will, after reset, block writes to the WDT_CLEAR
+ * register, preventing the program to clear the next Watchdog Timer Reset.
+ *
+ * If you still want to use the WDT after a WDT reset a small code can be
+ * insterted at the startup checking the AVR32_PM.rcause register for WDT reset
+ * and use a GPIO pin to reset the system. This method requires that one of the
+ * GPIO pins are available and connected externally to the RESET_N pin. After
+ * the GPIO pin has pulled down the reset line the GPIO will be reset and leave
+ * the pin tristated with pullup.
*/
#include <linux/init.h>
@@ -44,6 +57,13 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
#define WDT_CLR 0x04
+#define WDT_RCAUSE 0x10
+#define WDT_RCAUSE_POR 0
+#define WDT_RCAUSE_EXT 2
+#define WDT_RCAUSE_WDT 3
+#define WDT_RCAUSE_JTAG 4
+#define WDT_RCAUSE_SERP 5
+
#define WDT_BIT(name) (1 << WDT_##name)
#define WDT_BF(name, value) ((value) << WDT_##name)
@@ -56,6 +76,7 @@ struct wdt_at32ap700x {
void __iomem *regs;
spinlock_t io_lock;
int timeout;
+ int boot_status;
unsigned long users;
struct miscdevice miscdev;
};
@@ -126,7 +147,7 @@ static int at32_wdt_close(struct inode *inode, struct file *file)
at32_wdt_stop();
} else {
dev_dbg(wdt->miscdev.parent,
- "Unexpected close, not stopping watchdog!\n");
+ "unexpected close, not stopping watchdog!\n");
at32_wdt_pat();
}
clear_bit(1, &wdt->users);
@@ -154,6 +175,33 @@ static int at32_wdt_settimeout(int time)
return 0;
}
+/*
+ * Get the watchdog status.
+ */
+static int at32_wdt_get_status(void)
+{
+ int rcause;
+ int status = 0;
+
+ rcause = wdt_readl(wdt, RCAUSE);
+
+ switch (rcause) {
+ case WDT_BIT(RCAUSE_EXT):
+ status = WDIOF_EXTERN1;
+ break;
+ case WDT_BIT(RCAUSE_WDT):
+ status = WDIOF_CARDRESET;
+ break;
+ case WDT_BIT(RCAUSE_POR): /* fall through */
+ case WDT_BIT(RCAUSE_JTAG): /* fall through */
+ case WDT_BIT(RCAUSE_SERP): /* fall through */
+ default:
+ break;
+ }
+
+ return status;
+}
+
static struct watchdog_info at32_wdt_info = {
.identity = "at32ap700x watchdog",
.options = WDIOF_SETTIMEOUT |
@@ -194,10 +242,12 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file,
case WDIOC_GETTIMEOUT:
ret = put_user(wdt->timeout, p);
break;
- case WDIOC_GETSTATUS: /* fall through */
- case WDIOC_GETBOOTSTATUS:
+ case WDIOC_GETSTATUS:
ret = put_user(0, p);
break;
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(wdt->boot_status, p);
+ break;
case WDIOC_SETOPTIONS:
ret = get_user(time, p);
if (ret)
@@ -282,8 +332,19 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "could not map I/O memory\n");
goto err_free;
}
+
spin_lock_init(&wdt->io_lock);
- wdt->users = 0;
+ wdt->boot_status = at32_wdt_get_status();
+
+ /* Work-around for watchdog silicon errata. */
+ if (wdt->boot_status & WDIOF_CARDRESET) {
+ dev_info(&pdev->dev, "CPU must be reset with external "
+ "reset or POR due to silicon errata.\n");
+ ret = -EIO;
+ goto err_iounmap;
+ } else {
+ wdt->users = 0;
+ }
wdt->miscdev.minor = WATCHDOG_MINOR;
wdt->miscdev.name = "watchdog";
wdt->miscdev.fops = &at32_wdt_fops;
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 309d27913fc..31dc7a69e90 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -71,7 +71,7 @@ static int nowayout = WATCHDOG_NOWAYOUT;
static struct watchdog_info bfin_wdt_info;
static unsigned long open_check;
static char expect_close;
-static spinlock_t bfin_wdt_spinlock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(bfin_wdt_spinlock);
/**
* bfin_wdt_keepalive - Keep the Userspace Watchdog Alive
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
new file mode 100644
index 00000000000..6330fc02464
--- /dev/null
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -0,0 +1,400 @@
+/*
+ * IT8712F "Smart Guardian" Watchdog support
+ *
+ * Copyright (c) 2006-2007 Jorge Boncompte - DTI2 <jorge@dti2.net>
+ *
+ * Based on info and code taken from:
+ *
+ * drivers/char/watchdog/scx200_wdt.c
+ * drivers/hwmon/it87.c
+ * IT8712F EC-LPC I/O Preliminary Specification 0.9.2.pdf
+ *
+ * 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.
+ *
+ * The author(s) of this software shall not be held liable for damages
+ * of any nature resulting due to the use of this software. This
+ * software is provided AS-IS with no warranties.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define NAME "it8712f_wdt"
+
+MODULE_AUTHOR("Jorge Boncompte - DTI2 <jorge@dti2.net>");
+MODULE_DESCRIPTION("IT8712F Watchdog Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+static int margin = 60; /* in seconds */
+module_param(margin, int, 0);
+MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
+
+static struct semaphore it8712f_wdt_sem;
+static unsigned expect_close;
+static spinlock_t io_lock;
+
+/* Dog Food address - We use the game port address */
+static unsigned short address;
+
+#define REG 0x2e /* The register to read/write */
+#define VAL 0x2f /* The value to read/write */
+
+#define LDN 0x07 /* Register: Logical device select */
+#define DEVID 0x20 /* Register: Device ID */
+#define DEVREV 0x22 /* Register: Device Revision */
+#define ACT_REG 0x30 /* LDN Register: Activation */
+#define BASE_REG 0x60 /* LDN Register: Base address */
+
+#define IT8712F_DEVID 0x8712
+
+#define LDN_GPIO 0x07 /* GPIO and Watch Dog Timer */
+#define LDN_GAME 0x09 /* Game Port */
+
+#define WDT_CONTROL 0x71 /* WDT Register: Control */
+#define WDT_CONFIG 0x72 /* WDT Register: Configuration */
+#define WDT_TIMEOUT 0x73 /* WDT Register: Timeout Value */
+
+#define WDT_RESET_GAME 0x10
+#define WDT_RESET_KBD 0x20
+#define WDT_RESET_MOUSE 0x40
+#define WDT_RESET_CIR 0x80
+
+#define WDT_UNIT_SEC 0x80 /* If 0 in MINUTES */
+
+#define WDT_OUT_PWROK 0x10
+#define WDT_OUT_KRST 0x40
+
+static int
+superio_inb(int reg)
+{
+ outb(reg, REG);
+ return inb(VAL);
+}
+
+static void
+superio_outb(int val, int reg)
+{
+ outb(reg, REG);
+ outb(val, VAL);
+}
+
+static int
+superio_inw(int reg)
+{
+ int val;
+ outb(reg++, REG);
+ val = inb(VAL) << 8;
+ outb(reg, REG);
+ val |= inb(VAL);
+ return val;
+}
+
+static inline void
+superio_select(int ldn)
+{
+ outb(LDN, REG);
+ outb(ldn, VAL);
+}
+
+static inline void
+superio_enter(void)
+{
+ spin_lock(&io_lock);
+ outb(0x87, REG);
+ outb(0x01, REG);
+ outb(0x55, REG);
+ outb(0x55, REG);
+}
+
+static inline void
+superio_exit(void)
+{
+ outb(0x02, REG);
+ outb(0x02, VAL);
+ spin_unlock(&io_lock);
+}
+
+static inline void
+it8712f_wdt_ping(void)
+{
+ inb(address);
+}
+
+static void
+it8712f_wdt_update_margin(void)
+{
+ int config = WDT_OUT_KRST | WDT_OUT_PWROK;
+
+ printk(KERN_INFO NAME ": timer margin %d seconds\n", margin);
+
+ /* The timeout register only has 8bits wide */
+ if (margin < 256)
+ config |= WDT_UNIT_SEC; /* else UNIT are MINUTES */
+ superio_outb(config, WDT_CONFIG);
+
+ superio_outb((margin > 255) ? (margin / 60) : margin, WDT_TIMEOUT);
+}
+
+static void
+it8712f_wdt_enable(void)
+{
+ printk(KERN_DEBUG NAME ": enabling watchdog timer\n");
+ superio_enter();
+ superio_select(LDN_GPIO);
+
+ superio_outb(WDT_RESET_GAME, WDT_CONTROL);
+
+ it8712f_wdt_update_margin();
+
+ superio_exit();
+
+ it8712f_wdt_ping();
+}
+
+static void
+it8712f_wdt_disable(void)
+{
+ printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
+
+ superio_enter();
+ superio_select(LDN_GPIO);
+
+ superio_outb(0, WDT_CONFIG);
+ superio_outb(0, WDT_CONTROL);
+ superio_outb(0, WDT_TIMEOUT);
+
+ superio_exit();
+}
+
+static int
+it8712f_wdt_notify(struct notifier_block *this,
+ unsigned long code, void *unused)
+{
+ if (code == SYS_HALT || code == SYS_POWER_OFF)
+ if (!nowayout)
+ it8712f_wdt_disable();
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block it8712f_wdt_notifier = {
+ .notifier_call = it8712f_wdt_notify,
+};
+
+static ssize_t
+it8712f_wdt_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ /* check for a magic close character */
+ if (len) {
+ size_t i;
+
+ it8712f_wdt_ping();
+
+ expect_close = 0;
+ for (i = 0; i < len; ++i) {
+ char c;
+ if (get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 42;
+ }
+ }
+
+ return len;
+}
+
+static int
+it8712f_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ static struct watchdog_info ident = {
+ .identity = "IT8712F Watchdog",
+ .firmware_version = 1,
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+ };
+ int new_margin;
+
+ switch (cmd) {
+ default:
+ return -ENOTTY;
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user(argp, &ident, sizeof(ident)))
+ return -EFAULT;
+ return 0;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+ case WDIOC_KEEPALIVE:
+ it8712f_wdt_ping();
+ return 0;
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_margin, p))
+ return -EFAULT;
+ if (new_margin < 1)
+ return -EINVAL;
+ margin = new_margin;
+ superio_enter();
+ superio_select(LDN_GPIO);
+
+ it8712f_wdt_update_margin();
+
+ superio_exit();
+ it8712f_wdt_ping();
+ case WDIOC_GETTIMEOUT:
+ if (put_user(margin, p))
+ return -EFAULT;
+ return 0;
+ }
+}
+
+static int
+it8712f_wdt_open(struct inode *inode, struct file *file)
+{
+ /* only allow one at a time */
+ if (down_trylock(&it8712f_wdt_sem))
+ return -EBUSY;
+ it8712f_wdt_enable();
+
+ return nonseekable_open(inode, file);
+}
+
+static int
+it8712f_wdt_release(struct inode *inode, struct file *file)
+{
+ if (expect_close != 42) {
+ printk(KERN_WARNING NAME
+ ": watchdog device closed unexpectedly, will not"
+ " disable the watchdog timer\n");
+ } else if (!nowayout) {
+ it8712f_wdt_disable();
+ }
+ expect_close = 0;
+ up(&it8712f_wdt_sem);
+
+ return 0;
+}
+
+static struct file_operations it8712f_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = it8712f_wdt_write,
+ .ioctl = it8712f_wdt_ioctl,
+ .open = it8712f_wdt_open,
+ .release = it8712f_wdt_release,
+};
+
+static struct miscdevice it8712f_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &it8712f_wdt_fops,
+};
+
+static int __init
+it8712f_wdt_find(unsigned short *address)
+{
+ int err = -ENODEV;
+ int chip_type;
+
+ superio_enter();
+ chip_type = superio_inw(DEVID);
+ if (chip_type != IT8712F_DEVID)
+ goto exit;
+
+ superio_select(LDN_GAME);
+ superio_outb(1, ACT_REG);
+ if (!(superio_inb(ACT_REG) & 0x01)) {
+ printk(KERN_ERR NAME ": Device not activated, skipping\n");
+ goto exit;
+ }
+
+ *address = superio_inw(BASE_REG);
+ if (*address == 0) {
+ printk(KERN_ERR NAME ": Base address not set, skipping\n");
+ goto exit;
+ }
+
+ err = 0;
+ printk(KERN_DEBUG NAME ": Found IT%04xF chip revision %d - "
+ "using DogFood address 0x%x\n",
+ chip_type, superio_inb(DEVREV) & 0x0f, *address);
+
+exit:
+ superio_exit();
+ return err;
+}
+
+static int __init
+it8712f_wdt_init(void)
+{
+ int err = 0;
+
+ spin_lock_init(&io_lock);
+
+ if (it8712f_wdt_find(&address))
+ return -ENODEV;
+
+ if (!request_region(address, 1, "IT8712F Watchdog")) {
+ printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
+ return -EBUSY;
+ }
+
+ it8712f_wdt_disable();
+
+ sema_init(&it8712f_wdt_sem, 1);
+
+ err = register_reboot_notifier(&it8712f_wdt_notifier);
+ if (err) {
+ printk(KERN_ERR NAME ": unable to register reboot notifier\n");
+ goto out;
+ }
+
+ err = misc_register(&it8712f_wdt_miscdev);
+ if (err) {
+ printk(KERN_ERR NAME
+ ": cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, err);
+ goto reboot_out;
+ }
+
+ return 0;
+
+
+reboot_out:
+ unregister_reboot_notifier(&it8712f_wdt_notifier);
+out:
+ release_region(address, 1);
+ return err;
+}
+
+static void __exit
+it8712f_wdt_exit(void)
+{
+ misc_deregister(&it8712f_wdt_miscdev);
+ unregister_reboot_notifier(&it8712f_wdt_notifier);
+ release_region(address, 1);
+}
+
+module_init(it8712f_wdt_init);
+module_exit(it8712f_wdt_exit);
diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c
new file mode 100644
index 00000000000..4c8cefbd862
--- /dev/null
+++ b/drivers/watchdog/sbc7240_wdt.c
@@ -0,0 +1,324 @@
+/*
+ * NANO7240 SBC Watchdog device driver
+ *
+ * Based on w83877f.c by Scott Jennings,
+ *
+ * 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;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * (c) Copyright 2007 Gilles GIGAN <gilles.gigan@jcu.edu.au>
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define SBC7240_PREFIX "sbc7240_wdt: "
+
+#define SBC7240_ENABLE_PORT 0x443
+#define SBC7240_DISABLE_PORT 0x043
+#define SBC7240_SET_TIMEOUT_PORT SBC7240_ENABLE_PORT
+#define SBC7240_MAGIC_CHAR 'V'
+
+#define SBC7240_TIMEOUT 30
+#define SBC7240_MAX_TIMEOUT 255
+static int timeout = SBC7240_TIMEOUT; /* in seconds */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<="
+ __MODULE_STRING(SBC7240_MAX_TIMEOUT) ", default="
+ __MODULE_STRING(SBC7240_TIMEOUT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Disable watchdog when closing device file");
+
+#define SBC7240_OPEN_STATUS_BIT 0
+#define SBC7240_ENABLED_STATUS_BIT 1
+#define SBC7240_EXPECT_CLOSE_STATUS_BIT 2
+static unsigned long wdt_status;
+
+/*
+ * Utility routines
+ */
+
+static void wdt_disable(void)
+{
+ /* disable the watchdog */
+ if (test_and_clear_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status)) {
+ inb_p(SBC7240_DISABLE_PORT);
+ printk(KERN_INFO SBC7240_PREFIX
+ "Watchdog timer is now disabled.\n");
+ }
+}
+
+static void wdt_enable(void)
+{
+ /* enable the watchdog */
+ if (!test_and_set_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status)) {
+ inb_p(SBC7240_ENABLE_PORT);
+ printk(KERN_INFO SBC7240_PREFIX
+ "Watchdog timer is now enabled.\n");
+ }
+}
+
+static int wdt_set_timeout(int t)
+{
+ if (t < 1 || t > SBC7240_MAX_TIMEOUT) {
+ printk(KERN_ERR SBC7240_PREFIX
+ "timeout value must be 1<=x<=%d\n",
+ SBC7240_MAX_TIMEOUT);
+ return -1;
+ }
+ /* set the timeout */
+ outb_p((unsigned)t, SBC7240_SET_TIMEOUT_PORT);
+ timeout = t;
+ printk(KERN_INFO SBC7240_PREFIX "timeout set to %d seconds\n", t);
+ return 0;
+}
+
+/* Whack the dog */
+static inline void wdt_keepalive(void)
+{
+ if (test_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status))
+ inb_p(SBC7240_ENABLE_PORT);
+}
+
+/*
+ * /dev/watchdog handling
+ */
+static ssize_t fop_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ size_t i;
+ char c;
+
+ if (count) {
+ if (!nowayout) {
+ clear_bit(SBC7240_EXPECT_CLOSE_STATUS_BIT,
+ &wdt_status);
+
+ /* is there a magic char ? */
+ for (i = 0; i != count; i++) {
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == SBC7240_MAGIC_CHAR) {
+ set_bit(SBC7240_EXPECT_CLOSE_STATUS_BIT,
+ &wdt_status);
+ break;
+ }
+ }
+ }
+
+ wdt_keepalive();
+ }
+
+ return count;
+}
+
+static int fop_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(SBC7240_OPEN_STATUS_BIT, &wdt_status))
+ return -EBUSY;
+
+ wdt_enable();
+
+ return nonseekable_open(inode, file);
+}
+
+static int fop_close(struct inode *inode, struct file *file)
+{
+ if (test_and_clear_bit(SBC7240_EXPECT_CLOSE_STATUS_BIT, &wdt_status)
+ || !nowayout) {
+ wdt_disable();
+ } else {
+ printk(KERN_CRIT SBC7240_PREFIX
+ "Unexpected close, not stopping watchdog!\n");
+ wdt_keepalive();
+ }
+
+ clear_bit(SBC7240_OPEN_STATUS_BIT, &wdt_status);
+ return 0;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING|
+ WDIOF_SETTIMEOUT|
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 1,
+ .identity = "SBC7240",
+};
+
+
+static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user
+ ((void __user *)arg, &ident, sizeof(ident))
+ ? -EFAULT : 0;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, (int __user *)arg);
+ case WDIOC_KEEPALIVE:
+ wdt_keepalive();
+ return 0;
+ case WDIOC_SETOPTIONS:{
+ int options;
+ int retval = -EINVAL;
+
+ if (get_user(options, (int __user *)arg))
+ return -EFAULT;
+
+ if (options & WDIOS_DISABLECARD) {
+ wdt_disable();
+ retval = 0;
+ }
+
+ if (options & WDIOS_ENABLECARD) {
+ wdt_enable();
+ retval = 0;
+ }
+
+ return retval;
+ }
+ case WDIOC_SETTIMEOUT:{
+ int new_timeout;
+
+ if (get_user(new_timeout, (int __user *)arg))
+ return -EFAULT;
+
+ if (wdt_set_timeout(new_timeout))
+ return -EINVAL;
+
+ /* Fall through */
+ }
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout, (int __user *)arg);
+ default:
+ return -ENOTTY;
+ }
+}
+
+static const struct file_operations wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = fop_write,
+ .open = fop_open,
+ .release = fop_close,
+ .ioctl = fop_ioctl,
+};
+
+static struct miscdevice wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &wdt_fops,
+};
+
+/*
+ * Notifier for system down
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT)
+ wdt_disable();
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block wdt_notifier = {
+ .notifier_call = wdt_notify_sys,
+};
+
+static void __exit sbc7240_wdt_unload(void)
+{
+ printk(KERN_INFO SBC7240_PREFIX "Removing watchdog\n");
+ misc_deregister(&wdt_miscdev);
+
+ unregister_reboot_notifier(&wdt_notifier);
+ release_region(SBC7240_ENABLE_PORT, 1);
+}
+
+static int __init sbc7240_wdt_init(void)
+{
+ int rc = -EBUSY;
+
+ if (!request_region(SBC7240_ENABLE_PORT, 1, "SBC7240 WDT")) {
+ printk(KERN_ERR SBC7240_PREFIX
+ "I/O address 0x%04x already in use\n",
+ SBC7240_ENABLE_PORT);
+ rc = -EIO;
+ goto err_out;
+ }
+
+ /* The IO port 0x043 used to disable the watchdog
+ * is already claimed by the system timer, so we
+ * cant request_region() it ...*/
+
+ if (timeout < 1 || timeout > SBC7240_MAX_TIMEOUT) {
+ timeout = SBC7240_TIMEOUT;
+ printk(KERN_INFO SBC7240_PREFIX
+ "timeout value must be 1<=x<=%d, using %d\n",
+ SBC7240_MAX_TIMEOUT, timeout);
+ }
+ wdt_set_timeout(timeout);
+ wdt_disable();
+
+ rc = register_reboot_notifier(&wdt_notifier);
+ if (rc) {
+ printk(KERN_ERR SBC7240_PREFIX
+ "cannot register reboot notifier (err=%d)\n", rc);
+ goto err_out_region;
+ }
+
+ rc = misc_register(&wdt_miscdev);
+ if (rc) {
+ printk(KERN_ERR SBC7240_PREFIX
+ "cannot register miscdev on minor=%d (err=%d)\n",
+ wdt_miscdev.minor, rc);
+ goto err_out_reboot_notifier;
+ }
+
+ printk(KERN_INFO SBC7240_PREFIX
+ "Watchdog driver for SBC7240 initialised (nowayout=%d)\n",
+ nowayout);
+
+ return 0;
+
+err_out_reboot_notifier:
+ unregister_reboot_notifier(&wdt_notifier);
+err_out_region:
+ release_region(SBC7240_ENABLE_PORT, 1);
+err_out:
+ return rc;
+}
+
+module_init(sbc7240_wdt_init);
+module_exit(sbc7240_wdt_unload);
+
+MODULE_AUTHOR("Gilles Gigan");
+MODULE_DESCRIPTION("Watchdog device driver for single board"
+ " computers EPIC Nano 7240 from iEi");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c
index c622a0e6c9a..6ea125eabea 100644
--- a/drivers/watchdog/w83697hf_wdt.c
+++ b/drivers/watchdog/w83697hf_wdt.c
@@ -382,8 +382,10 @@ wdt_init(void)
/* we will autodetect the W83697HF/HG watchdog */
for (i = 0; ((!found) && (w83697hf_ioports[i] != 0)); i++) {
wdt_io = w83697hf_ioports[i];
- if (!w83697hf_check_wdt())
+ if (!w83697hf_check_wdt()) {
found++;
+ break;
+ }
}
} else {
if (!w83697hf_check_wdt())