diff options
Diffstat (limited to 'drivers')
86 files changed, 1495 insertions, 921 deletions
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index c4b75ecf946..55959e4d1cb 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -417,9 +417,9 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]); chan = (here[3] & uPD98401_AAL5_CHAN) >> uPD98401_AAL5_CHAN_SHIFT; if (chan < zatm_dev->chans && zatm_dev->rx_map[chan]) { - int pos = ZATM_VCC(vcc)->pool; - + int pos; vcc = zatm_dev->rx_map[chan]; + pos = ZATM_VCC(vcc)->pool; if (skb == zatm_dev->last_free[pos]) zatm_dev->last_free[pos] = NULL; skb_unlink(skb, zatm_dev->pool + pos); diff --git a/drivers/base/node.c b/drivers/base/node.c index 904b27caf69..16c513aa4d4 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -39,13 +39,25 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) int n; int nid = dev->id; struct sysinfo i; + struct page_state ps; unsigned long inactive; unsigned long active; unsigned long free; si_meminfo_node(&i, nid); + get_page_state_node(&ps, nid); __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); + /* Check for negative values in these approximate counters */ + if ((long)ps.nr_dirty < 0) + ps.nr_dirty = 0; + if ((long)ps.nr_writeback < 0) + ps.nr_writeback = 0; + if ((long)ps.nr_mapped < 0) + ps.nr_mapped = 0; + if ((long)ps.nr_slab < 0) + ps.nr_slab = 0; + n = sprintf(buf, "\n" "Node %d MemTotal: %8lu kB\n" "Node %d MemFree: %8lu kB\n" @@ -55,7 +67,11 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) "Node %d HighTotal: %8lu kB\n" "Node %d HighFree: %8lu kB\n" "Node %d LowTotal: %8lu kB\n" - "Node %d LowFree: %8lu kB\n", + "Node %d LowFree: %8lu kB\n" + "Node %d Dirty: %8lu kB\n" + "Node %d Writeback: %8lu kB\n" + "Node %d Mapped: %8lu kB\n" + "Node %d Slab: %8lu kB\n", nid, K(i.totalram), nid, K(i.freeram), nid, K(i.totalram - i.freeram), @@ -64,7 +80,11 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) nid, K(i.totalhigh), nid, K(i.freehigh), nid, K(i.totalram - i.totalhigh), - nid, K(i.freeram - i.freehigh)); + nid, K(i.freeram - i.freehigh), + nid, K(ps.nr_dirty), + nid, K(ps.nr_writeback), + nid, K(ps.nr_mapped), + nid, K(ps.nr_slab)); n += hugetlb_report_node_meminfo(nid, buf + n); return n; } diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index bdd96b03b88..0a7aa07b9a2 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c @@ -26,11 +26,11 @@ int resume_device(struct device * dev) down(&dev->sem); if (dev->power.pm_parent - && dev->power.pm_parent->power.power_state) { + && dev->power.pm_parent->power.power_state.event) { dev_err(dev, "PM: resume from %d, parent %s still %d\n", - dev->power.power_state, + dev->power.power_state.event, dev->power.pm_parent->bus_id, - dev->power.pm_parent->power.power_state); + dev->power.pm_parent->power.power_state.event); } if (dev->bus && dev->bus->resume) { dev_dbg(dev,"resuming\n"); @@ -54,7 +54,7 @@ void dpm_resume(void) list_add_tail(entry, &dpm_active); up(&dpm_list_sem); - if (!dev->power.prev_state) + if (!dev->power.prev_state.event) resume_device(dev); down(&dpm_list_sem); put_device(dev); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 325962d8019..e8f0519f5df 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -13,10 +13,10 @@ static void runtime_resume(struct device * dev) { dev_dbg(dev, "resuming\n"); - if (!dev->power.power_state) + if (!dev->power.power_state.event) return; if (!resume_device(dev)) - dev->power.power_state = 0; + dev->power.power_state = PMSG_ON; } @@ -49,10 +49,10 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state) int error = 0; down(&dpm_sem); - if (dev->power.power_state == state) + if (dev->power.power_state.event == state.event) goto Done; - if (dev->power.power_state) + if (dev->power.power_state.event) runtime_resume(dev); if (!(error = suspend_device(dev, state))) diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 2ccee3763ac..50501764d05 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -40,22 +40,22 @@ int suspend_device(struct device * dev, pm_message_t state) int error = 0; down(&dev->sem); - if (dev->power.power_state) { + if (dev->power.power_state.event) { dev_dbg(dev, "PM: suspend %d-->%d\n", - dev->power.power_state, state); + dev->power.power_state.event, state.event); } if (dev->power.pm_parent - && dev->power.pm_parent->power.power_state) { + && dev->power.pm_parent->power.power_state.event) { dev_err(dev, "PM: suspend %d->%d, parent %s already %d\n", - dev->power.power_state, state, + dev->power.power_state.event, state.event, dev->power.pm_parent->bus_id, - dev->power.pm_parent->power.power_state); + dev->power.pm_parent->power.power_state.event); } dev->power.prev_state = dev->power.power_state; - if (dev->bus && dev->bus->suspend && !dev->power.power_state) { + if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) { dev_dbg(dev, "suspending\n"); error = dev->bus->suspend(dev, state); } diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index f82b3df9545..8d04fb435c1 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -26,19 +26,19 @@ static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf) { - return sprintf(buf, "%u\n", dev->power.power_state); + return sprintf(buf, "%u\n", dev->power.power_state.event); } static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n) { - u32 state; + pm_message_t state; char * rest; int error = 0; - state = simple_strtoul(buf, &rest, 10); + state.event = simple_strtoul(buf, &rest, 10); if (*rest) return -EINVAL; - if (state) + if (state.event) error = dpm_runtime_suspend(dev, state); else dpm_runtime_resume(dev); diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index b594768b024..879036d4b30 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -455,7 +455,7 @@ config INITRAMFS_ROOT_GID #for instance. config LBD bool "Support for Large Block Devices" - depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH || UML + depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML help Say Y here if you want to attach large (bigger than 2TB) discs to your machine, or if you want to have a raid or loopback device diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c index 5be6f998d8c..3d4261c39f1 100644 --- a/drivers/block/cryptoloop.c +++ b/drivers/block/cryptoloop.c @@ -57,9 +57,11 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) mode = strsep(&cmsp, "-"); if (mode == NULL || strcmp(mode, "cbc") == 0) - tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC); + tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC | + CRYPTO_TFM_REQ_MAY_SLEEP); else if (strcmp(mode, "ecb") == 0) - tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB); + tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB | + CRYPTO_TFM_REQ_MAY_SLEEP); if (tfm == NULL) return -EINVAL; diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 7333b41d422..df5f2b0e075 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -175,7 +175,7 @@ config MOXA_INTELLIO config MOXA_SMARTIO tristate "Moxa SmartIO support" - depends on SERIAL_NONSTANDARD + depends on SERIAL_NONSTANDARD && (BROKEN || !SPARC32) help Say Y here if you have a Moxa SmartIO multiport serial card. @@ -842,8 +842,7 @@ config SONYPI config TANBAC_TB0219 tristate "TANBAC TB0219 base board support" - depends TANBAC_TB0229 - + depends TANBAC_TB022X menu "Ftape, the floppy tape device driver" diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 95f7046ff05..79e490ef2cf 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -339,7 +339,7 @@ static int __init moxa_init(void) init_MUTEX(&moxaBuffSem); moxaDriver->owner = THIS_MODULE; - moxaDriver->name = "ttya"; + moxaDriver->name = "ttyMX"; moxaDriver->devfs_name = "tts/a"; moxaDriver->major = ttymajor; moxaDriver->minor_start = 0; diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index dc8c540391f..939e51e119e 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -14,7 +14,6 @@ * License. */ -#include <acpi/acpi_bus.h> #include <linux/pnp.h> #include "tpm.h" @@ -29,9 +28,10 @@ #define TPM_MAX_TRIES 5000 #define TPM_INFINEON_DEV_VEN_VALUE 0x15D1 -/* These values will be filled after ACPI-call */ +/* These values will be filled after PnP-call */ static int TPM_INF_DATA = 0; static int TPM_INF_ADDR = 0; +static int pnp_registered = 0; /* TPM header definitions */ enum infineon_tpm_header { @@ -356,24 +356,26 @@ static const struct pnp_device_id tpm_pnp_tbl[] = { {"IFX0102", 0}, {"", 0} }; +MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); -static int __devinit tpm_inf_acpi_probe(struct pnp_dev *dev, +static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { - TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff); - TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff); - tpm_inf.base = pnp_port_start(dev, 1); - dev_info(&dev->dev, "Found %s with ID %s\n", - dev->name, dev_id->id); - if (!((tpm_inf.base >> 8) & 0xff)) - tpm_inf.base = 0; - return 0; + if (pnp_port_valid(dev, 0)) { + TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff); + TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff); + tpm_inf.base = pnp_port_start(dev, 1); + dev_info(&dev->dev, "Found %s with ID %s\n", + dev->name, dev_id->id); + return 0; + } + return -ENODEV; } static struct pnp_driver tpm_inf_pnp = { .name = "tpm_inf_pnp", .id_table = tpm_pnp_tbl, - .probe = tpm_inf_acpi_probe, + .probe = tpm_inf_pnp_probe, }; static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, @@ -386,19 +388,30 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, int productid[2]; char chipname[20]; - if (pci_enable_device(pci_dev)) - return -EIO; + rc = pci_enable_device(pci_dev); + if (rc) + return rc; dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device); - /* read IO-ports from ACPI */ - pnp_register_driver(&tpm_inf_pnp); - pnp_unregister_driver(&tpm_inf_pnp); + /* read IO-ports from PnP */ + rc = pnp_register_driver(&tpm_inf_pnp); + if (rc < 0) { + dev_err(&pci_dev->dev, + "Error %x from pnp_register_driver!\n",rc); + goto error2; + } + if (!rc) { + dev_info(&pci_dev->dev, "No Infineon TPM found!\n"); + goto error; + } else { + pnp_registered = 1; + } /* Make sure, we have received valid config ports */ if (!TPM_INF_ADDR) { - pci_disable_device(pci_dev); - return -EIO; + dev_err(&pci_dev->dev, "No valid IO-ports received!\n"); + goto error; } /* query chip for its vendor, its version number a.s.o. */ @@ -418,23 +431,21 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, switch ((productid[0] << 8) | productid[1]) { case 6: - sprintf(chipname, " (SLD 9630 TT 1.1)"); + snprintf(chipname, sizeof(chipname), " (SLD 9630 TT 1.1)"); break; case 11: - sprintf(chipname, " (SLB 9635 TT 1.2)"); + snprintf(chipname, sizeof(chipname), " (SLB 9635 TT 1.2)"); break; default: - sprintf(chipname, " (unknown chip)"); + snprintf(chipname, sizeof(chipname), " (unknown chip)"); break; } - chipname[19] = 0; if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { if (tpm_inf.base == 0) { dev_err(&pci_dev->dev, "No IO-ports found!\n"); - pci_disable_device(pci_dev); - return -EIO; + goto error; } /* configure TPM with IO-ports */ outb(IOLIMH, TPM_INF_ADDR); @@ -452,8 +463,7 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, dev_err(&pci_dev->dev, "Could not set IO-ports to %04x\n", tpm_inf.base); - pci_disable_device(pci_dev); - return -EIO; + goto error; } /* activate register */ @@ -479,14 +489,16 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, productid[0], productid[1], chipname); rc = tpm_register_hardware(pci_dev, &tpm_inf); - if (rc < 0) { - pci_disable_device(pci_dev); - return -ENODEV; - } + if (rc < 0) + goto error; return 0; } else { dev_info(&pci_dev->dev, "No Infineon TPM found!\n"); +error: + pnp_unregister_driver(&tpm_inf_pnp); +error2: pci_disable_device(pci_dev); + pnp_registered = 0; return -ENODEV; } } @@ -521,6 +533,8 @@ static int __init init_inf(void) static void __exit cleanup_inf(void) { + if (pnp_registered) + pnp_unregister_driver(&tpm_inf_pnp); pci_unregister_driver(&inf_pci_driver); } diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index b53e2e2b5ae..c3898afce3a 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -346,6 +346,13 @@ config 8xx_WDT tristate "MPC8xx Watchdog Timer" depends on WATCHDOG && 8xx +config BOOKE_WDT + tristate "PowerPC Book-E Watchdog Timer" + depends on WATCHDOG && (BOOKE || 4xx) + ---help--- + Please see Documentation/watchdog/watchdog-api.txt for + more information. + # MIPS Architecture config INDYDOG diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index c1838834ea7..b16dfea2813 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o +obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o # Only one watchdog can succeed. We probe the hardware watchdog # drivers first, then the softdog driver. This means if your hardware diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c new file mode 100644 index 00000000000..abc30cca664 --- /dev/null +++ b/drivers/char/watchdog/booke_wdt.c @@ -0,0 +1,192 @@ +/* + * drivers/char/watchdog/booke_wdt.c + * + * Watchdog timer for PowerPC Book-E systems + * + * Author: Matthew McClintock + * Maintainer: Kumar Gala <kumar.gala@freescale.com> + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * 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. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/notifier.h> +#include <linux/watchdog.h> + +#include <asm/reg_booke.h> +#include <asm/uaccess.h> +#include <asm/system.h> + +/* If the kernel parameter wdt_enable=1, the watchdog will be enabled at boot. + * Also, the wdt_period sets the watchdog timer period timeout. + * For E500 cpus the wdt_period sets which bit changing from 0->1 will + * trigger a watchog timeout. This watchdog timeout will occur 3 times, the + * first time nothing will happen, the second time a watchdog exception will + * occur, and the final time the board will reset. + */ + +#ifdef CONFIG_FSL_BOOKE +#define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ +#else +#define WDT_PERIOD_DEFAULT 4 /* Refer to the PPC40x and PPC4xx manuals */ +#endif /* for timing information */ + +u32 booke_wdt_enabled = 0; +u32 booke_wdt_period = WDT_PERIOD_DEFAULT; + +#ifdef CONFIG_FSL_BOOKE +#define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15)) +#else +#define WDTP(x) (TCR_WP(x)) +#endif + +/* + * booke_wdt_enable: + */ +static __inline__ void booke_wdt_enable(void) +{ + u32 val; + + val = mfspr(SPRN_TCR); + val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); + + mtspr(SPRN_TCR, val); +} + +/* + * booke_wdt_ping: + */ +static __inline__ void booke_wdt_ping(void) +{ + mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); +} + +/* + * booke_wdt_write: + */ +static ssize_t booke_wdt_write (struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + booke_wdt_ping(); + return count; +} + +static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .firmware_version = 0, + .identity = "PowerPC Book-E Watchdog", +}; + +/* + * booke_wdt_ioctl: + */ +static int booke_wdt_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + u32 tmp = 0; + + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user ((struct watchdog_info *) arg, &ident, + sizeof(struct watchdog_info))) + return -EFAULT; + case WDIOC_GETSTATUS: + return put_user(ident.options, (u32 *) arg); + case WDIOC_GETBOOTSTATUS: + /* XXX: something is clearing TSR */ + tmp = mfspr(SPRN_TSR) & TSR_WRS(3); + /* returns 1 if last reset was caused by the WDT */ + return (tmp ? 1 : 0); + case WDIOC_KEEPALIVE: + booke_wdt_ping(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(booke_wdt_period, (u32 *) arg)) + return -EFAULT; + mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period)); + return 0; + case WDIOC_GETTIMEOUT: + return put_user(booke_wdt_period, (u32 *) arg); + case WDIOC_SETOPTIONS: + if (get_user(tmp, (u32 *) arg)) + return -EINVAL; + if (tmp == WDIOS_ENABLECARD) { + booke_wdt_ping(); + break; + } else + return -EINVAL; + return 0; + default: + return -ENOIOCTLCMD; + } + + return 0; +} +/* + * booke_wdt_open: + */ +static int booke_wdt_open (struct inode *inode, struct file *file) +{ + if (booke_wdt_enabled == 0) { + booke_wdt_enabled = 1; + booke_wdt_enable(); + printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", + booke_wdt_period); + } + + return 0; +} + +static struct file_operations booke_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = booke_wdt_write, + .ioctl = booke_wdt_ioctl, + .open = booke_wdt_open, +}; + +static struct miscdevice booke_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &booke_wdt_fops, +}; + +static void __exit booke_wdt_exit(void) +{ + misc_deregister(&booke_wdt_miscdev); +} + +/* + * booke_wdt_init: + */ +static int __init booke_wdt_init(void) +{ + int ret = 0; + + printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n"); + ident.firmware_version = cpu_specs[0].pvr_value; + + ret = misc_register(&booke_wdt_miscdev); + if (ret) { + printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + return ret; + } + + if (booke_wdt_enabled == 1) { + printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", + booke_wdt_period); + booke_wdt_enable(); + } + + return ret; +} +device_initcall(booke_wdt_init); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 248e3cc8b35..f174aee659e 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -150,7 +150,7 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s switch (rq->pm->pm_step) { case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */ - if (rq->pm->pm_state == 4) + if (rq->pm->pm_state == PM_EVENT_FREEZE) rq->pm->pm_step = ide_pm_state_completed; else rq->pm->pm_step = idedisk_pm_standby; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index dae1bd5b8c3..73ca8f73917 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1229,7 +1229,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t state) rq.special = &args; rq.pm = &rqpm; rqpm.pm_step = ide_pm_state_start_suspend; - rqpm.pm_state = state; + rqpm.pm_state = state.event; return ide_do_drive_cmd(drive, &rq, ide_wait); } @@ -1248,7 +1248,7 @@ static int generic_ide_resume(struct device *dev) rq.special = &args; rq.pm = &rqpm; rqpm.pm_step = ide_pm_state_start_resume; - rqpm.pm_state = 0; + rqpm.pm_state = PM_EVENT_ON; return ide_do_drive_cmd(drive, &rq, ide_head_wait); } diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 10592cec6c4..24e21b2838c 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -350,9 +350,9 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) { ide_hwif_t *hwif = NULL; - printk("SC1200: suspend(%u)\n", state); + printk("SC1200: suspend(%u)\n", state.event); - if (state == 0) { + if (state.event == PM_EVENT_ON) { // we only save state when going from full power to less // @@ -386,8 +386,8 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) /* You don't need to iterate over disks -- sysfs should have done that for you already */ pci_disable_device(dev); - pci_set_power_state(dev,state); - dev->current_state = state; + pci_set_power_state(dev, pci_choose_state(dev, state)); + dev->current_state = state.event; return 0; } @@ -396,8 +396,8 @@ static int sc1200_resume (struct pci_dev *dev) ide_hwif_t *hwif = NULL; printk("SC1200: resume\n"); - pci_set_power_state(dev,0); // bring chip back from sleep state - dev->current_state = 0; + pci_set_power_state(dev, PCI_D0); // bring chip back from sleep state + dev->current_state = PM_EVENT_ON; pci_enable_device(dev); // // loop over all interfaces that are part of this pci device: diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index ea65b070a36..87d1f8a1f41 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1504,12 +1504,12 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) } static int -pmac_ide_macio_suspend(struct macio_dev *mdev, u32 state) +pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t state) { ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); int rc = 0; - if (state != mdev->ofdev.dev.power.power_state && state >= 2) { + if (state.event != mdev->ofdev.dev.power.power_state.event && state.event >= PM_EVENT_SUSPEND) { rc = pmac_ide_do_suspend(hwif); if (rc == 0) mdev->ofdev.dev.power.power_state = state; @@ -1524,10 +1524,10 @@ pmac_ide_macio_resume(struct macio_dev *mdev) ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); int rc = 0; - if (mdev->ofdev.dev.power.power_state != 0) { + if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) { rc = pmac_ide_do_resume(hwif); if (rc == 0) - mdev->ofdev.dev.power.power_state = 0; + mdev->ofdev.dev.power.power_state = PMSG_ON; } return rc; @@ -1608,12 +1608,12 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) } static int -pmac_ide_pci_suspend(struct pci_dev *pdev, u32 state) +pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t state) { ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev); int rc = 0; - if (state != pdev->dev.power.power_state && state >= 2) { + if (state.event != pdev->dev.power.power_state.event && state.event >= 2) { rc = pmac_ide_do_suspend(hwif); if (rc == 0) pdev->dev.power.power_state = state; @@ -1628,10 +1628,10 @@ pmac_ide_pci_resume(struct pci_dev *pdev) ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev); int rc = 0; - if (pdev->dev.power.power_state != 0) { + if (pdev->dev.power.power_state.event != PM_EVENT_ON) { rc = pmac_ide_do_resume(hwif); if (rc == 0) - pdev->dev.power.power_state = 0; + pdev->dev.power.power_state = PMSG_ON; } return rc; diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 20e3a165989..f8b278d3559 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -160,6 +160,8 @@ struct input_event_compat { # define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) #elif defined(CONFIG_ARCH_S390) # define COMPAT_TEST test_thread_flag(TIF_31BIT) +#elif defined(CONFIG_MIPS) +# define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR) #else # define COMPAT_TEST test_thread_flag(TIF_32BIT) #endif diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 7c16c25fc5d..c0712a1ea5a 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -708,7 +708,7 @@ static int __pmac media_bay_suspend(struct macio_dev *mdev, pm_message_t state) { struct media_bay_info *bay = macio_get_drvdata(mdev); - if (state != mdev->ofdev.dev.power.power_state && state == PM_SUSPEND_MEM) { + if (state.event != mdev->ofdev.dev.power.power_state.event && state.event == PM_EVENT_SUSPEND) { down(&bay->lock); bay->sleeping = 1; set_mb_power(bay, 0); @@ -723,8 +723,8 @@ static int __pmac media_bay_resume(struct macio_dev *mdev) { struct media_bay_info *bay = macio_get_drvdata(mdev); - if (mdev->ofdev.dev.power.power_state != 0) { - mdev->ofdev.dev.power.power_state = 0; + if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) { + mdev->ofdev.dev.power.power_state = PMSG_ON; /* We re-enable the bay using it's previous content only if it did not change. Note those bozo timings, diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 4a0a0ad2d03..645a2e5c70a 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -3065,7 +3065,7 @@ static int pmu_sys_suspended = 0; static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state) { - if (state != PM_SUSPEND_DISK || pmu_sys_suspended) + if (state.event != PM_EVENT_SUSPEND || pmu_sys_suspended) return 0; /* Suspend PMU event interrupts */ diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index d0a4bab220e..b82bc315047 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -144,7 +144,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, } /* Hash the cipher key with the given hash algorithm */ - hash_tfm = crypto_alloc_tfm(opts, 0); + hash_tfm = crypto_alloc_tfm(opts, CRYPTO_TFM_REQ_MAY_SLEEP); if (hash_tfm == NULL) { ti->error = PFX "Error initializing ESSIV hash"; return -EINVAL; @@ -172,7 +172,8 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, /* Setup the essiv_tfm with the given salt */ essiv_tfm = crypto_alloc_tfm(crypto_tfm_alg_name(cc->tfm), - CRYPTO_TFM_MODE_ECB); + CRYPTO_TFM_MODE_ECB | + CRYPTO_TFM_REQ_MAY_SLEEP); if (essiv_tfm == NULL) { ti->error = PFX "Error allocating crypto tfm for ESSIV"; kfree(salt); @@ -587,7 +588,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad1; } - tfm = crypto_alloc_tfm(cipher, crypto_flags); + tfm = crypto_alloc_tfm(cipher, crypto_flags | CRYPTO_TFM_REQ_MAY_SLEEP); if (!tfm) { ti->error = PFX "Error allocating crypto tfm"; goto bad1; diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 7d8b3cad350..9ea5747b121 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -888,7 +888,7 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) if (down_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; - if (state > 0) { /* state 0 seems to mean DEVICE_PM_ON */ + if (state.event > PM_EVENT_ON) { struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); #ifdef ENABLE_RC cancel_delayed_work(&cinergyt2->rc_query_work); diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3f574239609..16c85c081e6 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -254,6 +254,7 @@ config VIDEO_SAA7134_DVB select VIDEO_BUF_DVB select DVB_MT352 select DVB_CX22702 + select DVB_TDA1004X ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index eee9322ce21..087efb4dea0 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -4047,7 +4047,6 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) struct bttv_buffer_set idle; unsigned long flags; - dprintk("bttv%d: suspend %d\n", btv->c.nr, state); /* stop dma + irqs */ spin_lock_irqsave(&btv->s_lock,flags); diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 62f1b8ddb98..e956234abf2 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -1416,7 +1416,7 @@ static int msp_detach(struct i2c_client *client); static int msp_probe(struct i2c_adapter *adap); static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg); -static int msp_suspend(struct device * dev, u32 state, u32 level); +static int msp_suspend(struct device * dev, pm_message_t state, u32 level); static int msp_resume(struct device * dev, u32 level); static void msp_wake_thread(struct i2c_client *client); @@ -1817,7 +1817,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int msp_suspend(struct device * dev, u32 state, u32 level) +static int msp_suspend(struct device * dev, pm_message_t state, u32 level) { struct i2c_client *c = container_of(dev, struct i2c_client, dev); diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 108c3ad7d62..a28a395d6df 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -760,7 +760,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int tda9887_suspend(struct device * dev, u32 state, u32 level) +static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level) { dprintk("tda9887: suspend\n"); return 0; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index f0a579827a2..a155e99a263 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -672,7 +672,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int tuner_suspend(struct device *dev, u32 state, u32 level) +static int tuner_suspend(struct device *dev, pm_message_t state, u32 level) { struct i2c_client *c = container_of (dev, struct i2c_client, dev); struct tuner *t = i2c_get_clientdata (c); diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 7babf6af4e2..55a72c7ad00 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -2004,14 +2004,14 @@ bnx2_init_cpus(struct bnx2 *bp) } static int -bnx2_set_power_state(struct bnx2 *bp, int state) +bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) { u16 pmcsr; pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr); switch (state) { - case 0: { + case PCI_D0: { u32 val; pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, @@ -2032,7 +2032,7 @@ bnx2_set_power_state(struct bnx2 *bp, int state) REG_WR(bp, BNX2_RPM_CONFIG, val); break; } - case 3: { + case PCI_D3hot: { int i; u32 val, wol_msg; @@ -3886,7 +3886,7 @@ bnx2_open(struct net_device *dev) struct bnx2 *bp = dev->priv; int rc; - bnx2_set_power_state(bp, 0); + bnx2_set_power_state(bp, PCI_D0); bnx2_disable_int(bp); rc = bnx2_alloc_mem(bp); @@ -4197,7 +4197,7 @@ bnx2_close(struct net_device *dev) bnx2_free_mem(bp); bp->link_up = 0; netif_carrier_off(bp->dev); - bnx2_set_power_state(bp, 3); + bnx2_set_power_state(bp, PCI_D3hot); return 0; } @@ -5203,7 +5203,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP); - bnx2_set_power_state(bp, 0); + bnx2_set_power_state(bp, PCI_D0); bp->chip_id = REG_RD(bp, BNX2_MISC_ID); @@ -5495,7 +5495,7 @@ bnx2_remove_one(struct pci_dev *pdev) } static int -bnx2_suspend(struct pci_dev *pdev, u32 state) +bnx2_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); struct bnx2 *bp = dev->priv; @@ -5513,7 +5513,7 @@ bnx2_suspend(struct pci_dev *pdev, u32 state) reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; bnx2_reset_chip(bp, reset_code); bnx2_free_skbs(bp); - bnx2_set_power_state(bp, state); + bnx2_set_power_state(bp, pci_choose_state(pdev, state)); return 0; } @@ -5526,7 +5526,7 @@ bnx2_resume(struct pci_dev *pdev) if (!netif_running(dev)) return 0; - bnx2_set_power_state(bp, 0); + bnx2_set_power_state(bp, PCI_D0); netif_device_attach(dev); bnx2_init_nic(bp); bnx2_netif_start(bp); diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 9b596e0bbf9..7c8a0a22dcd 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -162,7 +162,7 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); static void e1000_restore_vlan(struct e1000_adapter *adapter); -static int e1000_suspend(struct pci_dev *pdev, uint32_t state); +static int e1000_suspend(struct pci_dev *pdev, pm_message_t state); #ifdef CONFIG_PM static int e1000_resume(struct pci_dev *pdev); #endif @@ -3642,7 +3642,7 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) } static int -e1000_suspend(struct pci_dev *pdev, uint32_t state) +e1000_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev_priv(netdev); @@ -3726,9 +3726,7 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) } pci_disable_device(pdev); - - state = (state > 0) ? 3 : 0; - pci_set_power_state(pdev, state); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } @@ -3741,13 +3739,13 @@ e1000_resume(struct pci_dev *pdev) struct e1000_adapter *adapter = netdev_priv(netdev); uint32_t manc, ret_val, swsm; - pci_set_power_state(pdev, 0); + pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); ret_val = pci_enable_device(pdev); pci_set_master(pdev); - pci_enable_wake(pdev, 3, 0); - pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); e1000_reset(adapter); E1000_WRITE_REG(&adapter->hw, WUS, ~0); diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index 006e4f57560..6d9de626c96 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -1749,11 +1749,6 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) struct net_device *ndev = pci_get_drvdata(pdev); vlsi_irda_dev_t *idev; - if (state < 1 || state > 3 ) { - IRDA_ERROR("%s - %s: invalid pm state request: %u\n", - __FUNCTION__, PCIDEV_NAME(pdev), state); - return 0; - } if (!ndev) { IRDA_ERROR("%s - %s: no netdevice \n", __FUNCTION__, PCIDEV_NAME(pdev)); @@ -1762,12 +1757,12 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) idev = ndev->priv; down(&idev->sem); if (pdev->current_state != 0) { /* already suspended */ - if (state > pdev->current_state) { /* simply go deeper */ - pci_set_power_state(pdev,state); - pdev->current_state = state; + if (state.event > pdev->current_state) { /* simply go deeper */ + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + pdev->current_state = state.event; } else - IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state); + IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state.event); up(&idev->sem); return 0; } @@ -1781,8 +1776,8 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) idev->new_baud = idev->baud; } - pci_set_power_state(pdev,state); - pdev->current_state = state; + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + pdev->current_state = state.event; idev->resume_ok = 1; up(&idev->sem); return 0; @@ -1807,8 +1802,8 @@ static int vlsi_irda_resume(struct pci_dev *pdev) return 0; } - pci_set_power_state(pdev, 0); - pdev->current_state = 0; + pci_set_power_state(pdev, PCI_D0); + pdev->current_state = PM_EVENT_ON; if (!idev->resume_ok) { /* should be obsolete now - but used to happen due to: diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 41f62c0c5fc..5e81494e9a9 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -128,7 +128,7 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) /* Suspend and resume. Copied from platform_suspend and * platform_resume */ -static int mdio_bus_suspend(struct device * dev, u32 state) +static int mdio_bus_suspend(struct device * dev, pm_message_t state) { int ret = 0; struct device_driver *drv = dev->driver; diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 2608e7a3d21..3f67a42e850 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -948,6 +948,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs) u32 gem_status = readl(gp->regs + GREG_STAT); if (gem_status == 0) { + netif_poll_enable(dev); spin_unlock_irqrestore(&gp->lock, flags); return IRQ_NONE; } diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h index 7143fd7cf3f..ff8ae5f7997 100644 --- a/drivers/net/sungem.h +++ b/drivers/net/sungem.h @@ -1020,7 +1020,7 @@ struct gem { struct gem_init_block *init_block; struct sk_buff *rx_skbs[RX_RING_SIZE]; - struct sk_buff *tx_skbs[RX_RING_SIZE]; + struct sk_buff *tx_skbs[TX_RING_SIZE]; dma_addr_t gblock_dvma; struct pci_dev *pdev; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index af8263a1580..3faf62310f8 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -66,8 +66,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.37" -#define DRV_MODULE_RELDATE "August 25, 2005" +#define DRV_MODULE_VERSION "3.38" +#define DRV_MODULE_RELDATE "September 1, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -121,12 +121,9 @@ TG3_RX_RCB_RING_SIZE(tp)) #define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \ TG3_TX_RING_SIZE) -#define TX_RING_GAP(TP) \ - (TG3_TX_RING_SIZE - (TP)->tx_pending) #define TX_BUFFS_AVAIL(TP) \ - (((TP)->tx_cons <= (TP)->tx_prod) ? \ - (TP)->tx_cons + (TP)->tx_pending - (TP)->tx_prod : \ - (TP)->tx_cons - (TP)->tx_prod - TX_RING_GAP(TP)) + ((TP)->tx_pending - \ + (((TP)->tx_prod - (TP)->tx_cons) & (TG3_TX_RING_SIZE - 1))) #define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) #define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64) @@ -2880,9 +2877,13 @@ static void tg3_tx(struct tg3 *tp) tp->tx_cons = sw_idx; - if (netif_queue_stopped(tp->dev) && - (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)) - netif_wake_queue(tp->dev); + if (unlikely(netif_queue_stopped(tp->dev))) { + spin_lock(&tp->tx_lock); + if (netif_queue_stopped(tp->dev) && + (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)) + netif_wake_queue(tp->dev); + spin_unlock(&tp->tx_lock); + } } /* Returns size of skb allocated or < 0 on error. @@ -3198,9 +3199,7 @@ static int tg3_poll(struct net_device *netdev, int *budget) /* run TX completion thread */ if (sblk->idx[0].tx_consumer != tp->tx_cons) { - spin_lock(&tp->tx_lock); tg3_tx(tp); - spin_unlock(&tp->tx_lock); } /* run RX thread, within the bounds set by NAPI. @@ -3716,8 +3715,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; - if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) + if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) { netif_stop_queue(dev); + if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) + netif_wake_queue(tp->dev); + } out_unlock: mmiowb(); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index effab0b9adc..50b8c6754b1 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -18,6 +18,9 @@ /* * Changes: * + * Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14 + * Add TUNSETLINK ioctl to set the link encapsulation + * * Mark Smith <markzzzsmith@yahoo.com.au> * Use random_ether_addr() for tap MAC address. * @@ -612,6 +615,18 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner); break; + case TUNSETLINK: + /* Only allow setting the type when the interface is down */ + if (tun->dev->flags & IFF_UP) { + DBG(KERN_INFO "%s: Linktype set failed because interface is up\n", + tun->dev->name); + return -EBUSY; + } else { + tun->dev->type = (int) arg; + DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type); + } + break; + #ifdef TUN_DEBUG case TUNSETDEBUG: tun->debug = arg; diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 6db1fb6461d..dbcb5a8a219 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1308,7 +1308,7 @@ static int micsetup(struct airo_info *ai) { int i; if (ai->tfm == NULL) - ai->tfm = crypto_alloc_tfm("aes", 0); + ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP); if (ai->tfm == NULL) { printk(KERN_ERR "airo: failed to load transform for AES\n"); @@ -2239,7 +2239,7 @@ static void airo_read_stats(struct airo_info *ai) { u32 *vals = stats_rid.vals; clear_bit(JOB_STATS, &ai->flags); - if (ai->power) { + if (ai->power.event) { up(&ai->sem); return; } @@ -2410,8 +2410,7 @@ void stop_airo_card( struct net_device *dev, int freeres ) } } #ifdef MICSUPPORT - if (ai->tfm) - crypto_free_tfm(ai->tfm); + crypto_free_tfm(ai->tfm); #endif del_airo_dev( dev ); free_netdev( dev ); @@ -2969,7 +2968,7 @@ static int airo_thread(void *data) { break; } - if (ai->power || test_bit(FLAG_FLASHING, &ai->flags)) { + if (ai->power.event || test_bit(FLAG_FLASHING, &ai->flags)) { up(&ai->sem); continue; } @@ -5521,7 +5520,7 @@ static int airo_pci_resume(struct pci_dev *pdev) pci_restore_state(pdev); pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0); - if (ai->power > 1) { + if (ai->power.event > 1) { reset_card(dev, 0); mpi_init_descriptors(ai); setup_card(ai, dev->dev_addr, 0); @@ -7123,7 +7122,7 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) int rc = 0; struct airo_info *ai = (struct airo_info *)dev->priv; - if (ai->power) + if (ai->power.event) return 0; switch (cmd) { @@ -7202,7 +7201,7 @@ static void airo_read_wireless_stats(struct airo_info *local) /* Get stats out of the card */ clear_bit(JOB_WSTATS, &local->flags); - if (local->power) { + if (local->power.event) { up(&local->sem); return; } diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 4f567ef6178..025f8cdb556 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -416,7 +416,7 @@ static int prism2_pci_suspend(struct pci_dev *pdev, pm_message_t state) prism2_suspend(dev); pci_save_state(pdev); pci_disable_device(pdev); - pci_set_power_state(pdev, 3); + pci_set_power_state(pdev, PCI_D3hot); return 0; } diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 6d0b6b1df4c..2a3bd607a5c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7225,7 +7225,7 @@ static void ipw_pci_remove(struct pci_dev *pdev) #ifdef CONFIG_PM -static int ipw_pci_suspend(struct pci_dev *pdev, u32 state) +static int ipw_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct ipw_priv *priv = pci_get_drvdata(pdev); struct net_device *dev = priv->net_dev; @@ -7240,7 +7240,7 @@ static int ipw_pci_suspend(struct pci_dev *pdev, u32 state) pci_save_state(pdev); pci_disable_device(pdev); - pci_set_power_state(pdev, state); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c index 7a6f52ea7fa..42e03438291 100644 --- a/drivers/net/wireless/orinoco_pci.c +++ b/drivers/net/wireless/orinoco_pci.c @@ -301,8 +301,6 @@ static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) unsigned long flags; int err; - printk(KERN_DEBUG "%s: Orinoco-PCI entering sleep mode (state=%d)\n", - dev->name, state); err = orinoco_lock(priv, &flags); if (err) { diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index c17391d947f..dc040caab7d 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -267,8 +267,6 @@ prism54_suspend(struct pci_dev *pdev, pm_message_t state) islpci_private *priv = ndev ? netdev_priv(ndev) : NULL; BUG_ON(!priv); - printk(KERN_NOTICE "%s: got suspend request (state %d)\n", - ndev->name, state); pci_save_state(pdev); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1b34fc56067..c62d2f04339 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -333,13 +333,17 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) if (platform_pci_choose_state) { ret = platform_pci_choose_state(dev, state); if (ret >= 0) - state = ret; + state.event = ret; } - switch (state) { - case 0: return PCI_D0; - case 3: return PCI_D3hot; + + switch (state.event) { + case PM_EVENT_ON: + return PCI_D0; + case PM_EVENT_FREEZE: + case PM_EVENT_SUSPEND: + return PCI_D3hot; default: - printk("They asked me for state %d\n", state); + printk("They asked me for state %d\n", state.event); BUG(); } return PCI_D0; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bb36bb69803..140354a2aa7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -422,6 +422,25 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic ); /* + * VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit. + * This leads to doubled level interrupt rates. + * Set this bit to get rid of cycle wastage. + * Otherwise uncritical. + */ +static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev) +{ + u8 misc_control2; +#define BYPASS_APIC_DEASSERT 8 + + pci_read_config_byte(dev, 0x5B, &misc_control2); + if (!(misc_control2 & BYPASS_APIC_DEASSERT)) { + printk(KERN_INFO "PCI: Bypassing VIA 8237 APIC De-Assert Message\n"); + pci_write_config_byte(dev, 0x5B, misc_control2|BYPASS_APIC_DEASSERT); + } +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert); + +/* * The AMD io apic can hang the box when an apic irq is masked. * We check all revs >= B0 (yet not in the pre production!) as the bug * is currently marked NoFix diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig index dc1c89dbdb8..6e7d7b06421 100644 --- a/drivers/s390/block/Kconfig +++ b/drivers/s390/block/Kconfig @@ -49,7 +49,7 @@ config DASD_FBA config DASD_DIAG tristate "Support for DIAG access to Disks" - depends on DASD && ARCH_S390X = 'n' + depends on DASD && ( ARCH_S390X = 'n' || EXPERIMENTAL) help Select this option if you want to use Diagnose250 command to access Disks under VM. If you are not running under VM or unsure what it is, diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d5f53980749..8fc891a9d47 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -7,7 +7,7 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.165 $ + * $Revision: 1.167 $ */ #include <linux/config.h> @@ -1131,17 +1131,13 @@ __dasd_process_blk_queue(struct dasd_device * device) request_queue_t *queue; struct request *req; struct dasd_ccw_req *cqr; - int nr_queued, feature_ro; + int nr_queued; queue = device->request_queue; /* No queue ? Then there is nothing to do. */ if (queue == NULL) return; - feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); - if (feature_ro < 0) /* no devmap */ - return; - /* * We requeue request from the block device queue to the ccw * queue only in two states. In state DASD_STATE_READY the @@ -1162,7 +1158,8 @@ __dasd_process_blk_queue(struct dasd_device * device) nr_queued < DASD_CHANQ_MAX_SIZE) { req = elv_next_request(queue); - if (feature_ro && rq_data_dir(req) == WRITE) { + if (device->features & DASD_FEATURE_READONLY && + rq_data_dir(req) == WRITE) { DBF_DEV_EVENT(DBF_ERR, device, "Rejecting write request %p", req); @@ -1814,17 +1811,13 @@ dasd_generic_set_online (struct ccw_device *cdev, { struct dasd_device *device; - int feature_diag, rc; + int rc; device = dasd_create_device(cdev); if (IS_ERR(device)) return PTR_ERR(device); - feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG); - if (feature_diag < 0) - return feature_diag; - - if (feature_diag) { + if (device->features & DASD_FEATURE_USEDIAG) { if (!dasd_diag_discipline_pointer) { printk (KERN_WARNING "dasd_generic couldn't online device %s " diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index d948566bb24..bda896d9d78 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -11,7 +11,7 @@ * functions may not be called from interrupt context. In particular * dasd_get_device is a no-no from interrupt context. * - * $Revision: 1.40 $ + * $Revision: 1.43 $ */ #include <linux/config.h> @@ -513,6 +513,7 @@ dasd_create_device(struct ccw_device *cdev) if (!devmap->device) { devmap->device = device; device->devindex = devmap->devindex; + device->features = devmap->features; get_device(&cdev->dev); device->cdev = cdev; rc = 0; @@ -643,6 +644,8 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf devmap->features |= DASD_FEATURE_READONLY; else devmap->features &= ~DASD_FEATURE_READONLY; + if (devmap->device) + devmap->device->features = devmap->features; if (devmap->device && devmap->device->gdp) set_disk_ro(devmap->device->gdp, ro_flag); spin_unlock(&dasd_devmap_lock); @@ -758,7 +761,8 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag) devmap->features |= feature; else devmap->features &= ~feature; - + if (devmap->device) + devmap->device->features = devmap->features; spin_unlock(&dasd_devmap_lock); return 0; } diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 127699830fa..7478423b53b 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -6,17 +6,18 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.42 $ + * $Revision: 1.49 $ */ #include <linux/config.h> #include <linux/stddef.h> #include <linux/kernel.h> #include <linux/slab.h> -#include <linux/hdreg.h> /* HDIO_GETGEO */ +#include <linux/hdreg.h> #include <linux/bio.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/jiffies.h> #include <asm/dasd.h> #include <asm/debug.h> @@ -28,58 +29,89 @@ #include "dasd_int.h" #include "dasd_diag.h" -#ifdef PRINTK_HEADER -#undef PRINTK_HEADER -#endif /* PRINTK_HEADER */ #define PRINTK_HEADER "dasd(diag):" MODULE_LICENSE("GPL"); +/* The maximum number of blocks per request (max_blocks) is dependent on the + * amount of storage that is available in the static I/O buffer for each + * device. Currently each device gets 2 pages. We want to fit two requests + * into the available memory so that we can immediately start the next if one + * finishes. */ +#define DIAG_MAX_BLOCKS (((2 * PAGE_SIZE - sizeof(struct dasd_ccw_req) - \ + sizeof(struct dasd_diag_req)) / \ + sizeof(struct dasd_diag_bio)) / 2) +#define DIAG_MAX_RETRIES 32 +#define DIAG_TIMEOUT 50 * HZ + struct dasd_discipline dasd_diag_discipline; struct dasd_diag_private { struct dasd_diag_characteristics rdc_data; struct dasd_diag_rw_io iob; struct dasd_diag_init_io iib; - unsigned int pt_block; + blocknum_t pt_block; }; struct dasd_diag_req { - int block_count; + unsigned int block_count; struct dasd_diag_bio bio[0]; }; +static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */ + +/* Perform DIAG250 call with block I/O parameter list iob (input and output) + * and function code cmd. + * In case of an exception return 3. Otherwise return result of bitwise OR of + * resulting condition code and DIAG return code. */ static __inline__ int dia250(void *iob, int cmd) { + typedef struct { + char _[max(sizeof (struct dasd_diag_init_io), + sizeof (struct dasd_diag_rw_io))]; + } addr_type; int rc; - __asm__ __volatile__(" lhi %0,3\n" - " lr 0,%2\n" - " diag 0,%1,0x250\n" - "0: ipm %0\n" - " srl %0,28\n" - " or %0,1\n" - "1:\n" -#ifndef CONFIG_ARCH_S390X - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 0b,1b\n" - ".previous\n" + __asm__ __volatile__( +#ifdef CONFIG_ARCH_S390X + " lghi %0,3\n" + " lgr 0,%3\n" + " diag 0,%2,0x250\n" + "0: ipm %0\n" + " srl %0,28\n" + " or %0,1\n" + "1:\n" + ".section __ex_table,\"a\"\n" + " .align 8\n" + " .quad 0b,1b\n" + ".previous\n" #else - ".section __ex_table,\"a\"\n" - " .align 8\n" - " .quad 0b,1b\n" - ".previous\n" + " lhi %0,3\n" + " lr 0,%3\n" + " diag 0,%2,0x250\n" + "0: ipm %0\n" + " srl %0,28\n" + " or %0,1\n" + "1:\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,1b\n" + ".previous\n" #endif - : "=&d" (rc) - : "d" (cmd), "d" ((void *) __pa(iob)) - : "0", "1", "cc"); + : "=&d" (rc), "=m" (*(addr_type *) iob) + : "d" (cmd), "d" (iob), "m" (*(addr_type *) iob) + : "0", "1", "cc"); return rc; } +/* Initialize block I/O to DIAG device using the specified blocksize and + * block offset. On success, return zero and set end_block to contain the + * number of blocks on the device minus the specified offset. Return non-zero + * otherwise. */ static __inline__ int -mdsk_init_io(struct dasd_device * device, int blocksize, int offset, int size) +mdsk_init_io(struct dasd_device *device, unsigned int blocksize, + blocknum_t offset, blocknum_t *end_block) { struct dasd_diag_private *private; struct dasd_diag_init_io *iib; @@ -92,14 +124,18 @@ mdsk_init_io(struct dasd_device * device, int blocksize, int offset, int size) iib->dev_nr = _ccw_device_get_device_number(device->cdev); iib->block_size = blocksize; iib->offset = offset; - iib->start_block = 0; - iib->end_block = size; + iib->flaga = DASD_DIAG_FLAGA_DEFAULT; rc = dia250(iib, INIT_BIO); - return rc & 3; + if ((rc & 3) == 0 && end_block) + *end_block = iib->end_block; + + return rc; } +/* Remove block I/O environment for device. Return zero on success, non-zero + * otherwise. */ static __inline__ int mdsk_term_io(struct dasd_device * device) { @@ -112,9 +148,25 @@ mdsk_term_io(struct dasd_device * device) memset(iib, 0, sizeof (struct dasd_diag_init_io)); iib->dev_nr = _ccw_device_get_device_number(device->cdev); rc = dia250(iib, TERM_BIO); - return rc & 3; + return rc; +} + +/* Error recovery for failed DIAG requests - try to reestablish the DIAG + * environment. */ +static void +dasd_diag_erp(struct dasd_device *device) +{ + int rc; + + mdsk_term_io(device); + rc = mdsk_init_io(device, device->bp_block, 0, NULL); + if (rc) + DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, " + "rc=%d", rc); } +/* Start a given request at the device. Return zero on success, non-zero + * otherwise. */ static int dasd_start_diag(struct dasd_ccw_req * cqr) { @@ -124,32 +176,66 @@ dasd_start_diag(struct dasd_ccw_req * cqr) int rc; device = cqr->device; + if (cqr->retries < 0) { + DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p " + "- no retry left)", cqr); + cqr->status = DASD_CQR_FAILED; + return -EIO; + } private = (struct dasd_diag_private *) device->private; dreq = (struct dasd_diag_req *) cqr->data; private->iob.dev_nr = _ccw_device_get_device_number(device->cdev); private->iob.key = 0; - private->iob.flags = 2; /* do asynchronous io */ + private->iob.flags = DASD_DIAG_RWFLAG_ASYNC; private->iob.block_count = dreq->block_count; - private->iob.interrupt_params = (u32)(addr_t) cqr; + private->iob.interrupt_params = (addr_t) cqr; private->iob.bio_list = __pa(dreq->bio); + private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; cqr->startclk = get_clock(); + cqr->starttime = jiffies; + cqr->retries--; rc = dia250(&private->iob, RW_BIO); - if (rc > 8) { - DEV_MESSAGE(KERN_WARNING, device, "dia250 returned CC %d", rc); - cqr->status = DASD_CQR_ERROR; - } else if (rc == 0) { + switch (rc) { + case 0: /* Synchronous I/O finished successfully */ + cqr->stopclk = get_clock(); cqr->status = DASD_CQR_DONE; - dasd_schedule_bh(device); - } else { + /* Indicate to calling function that only a dasd_schedule_bh() + and no timer is needed */ + rc = -EACCES; + break; + case 8: /* Asynchronous I/O was started */ cqr->status = DASD_CQR_IN_IO; rc = 0; + break; + default: /* Error condition */ + cqr->status = DASD_CQR_QUEUED; + DEV_MESSAGE(KERN_WARNING, device, "dia250 returned rc=%d", rc); + dasd_diag_erp(device); + rc = -EIO; + break; } return rc; } +/* Terminate given request at the device. */ +static int +dasd_diag_term_IO(struct dasd_ccw_req * cqr) +{ + struct dasd_device *device; + + device = cqr->device; + mdsk_term_io(device); + mdsk_init_io(device, device->bp_block, 0, NULL); + cqr->status = DASD_CQR_CLEAR; + cqr->stopclk = get_clock(); + dasd_schedule_bh(device); + return 0; +} + +/* Handle external interruption. */ static void dasd_ext_handler(struct pt_regs *regs, __u16 code) { @@ -157,25 +243,27 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code) struct dasd_device *device; unsigned long long expires; unsigned long flags; - char status; - int ip; - - /* - * Get the external interruption subcode. VM stores - * this in the 'cpu address' field associated with - * the external interrupt. For diag 250 the subcode - * needs to be 3. - */ - if ((S390_lowcore.cpu_addr & 0xff00) != 0x0300) - return; - status = *((char *) &S390_lowcore.ext_params + 5); - ip = S390_lowcore.ext_params; + u8 int_code, status; + addr_t ip; + int rc; + int_code = *((u8 *) DASD_DIAG_LC_INT_CODE); + status = *((u8 *) DASD_DIAG_LC_INT_STATUS); + switch (int_code) { + case DASD_DIAG_CODE_31BIT: + ip = (addr_t) *((u32 *) DASD_DIAG_LC_INT_PARM_31BIT); + break; + case DASD_DIAG_CODE_64BIT: + ip = (addr_t) *((u64 *) DASD_DIAG_LC_INT_PARM_64BIT); + break; + default: + return; + } if (!ip) { /* no intparm: unsolicited interrupt */ MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt"); return; } - cqr = (struct dasd_ccw_req *)(addr_t) ip; + cqr = (struct dasd_ccw_req *) ip; device = (struct dasd_device *) cqr->device; if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { DEV_MESSAGE(KERN_WARNING, device, @@ -188,6 +276,15 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code) /* get irq lock to modify request queue */ spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + /* Check for a pending clear operation */ + if (cqr->status == DASD_CQR_CLEAR) { + cqr->status = DASD_CQR_QUEUED; + dasd_clear_timer(device); + dasd_schedule_bh(device); + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + return; + } + cqr->stopclk = get_clock(); expires = 0; @@ -198,16 +295,22 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code) next = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); if (next->status == DASD_CQR_QUEUED) { - if (dasd_start_diag(next) == 0) + rc = dasd_start_diag(next); + if (rc == 0) expires = next->expires; - else + else if (rc != -EACCES) DEV_MESSAGE(KERN_WARNING, device, "%s", "Interrupt fastpath " "failed!"); } } - } else - cqr->status = DASD_CQR_FAILED; + } else { + cqr->status = DASD_CQR_QUEUED; + DEV_MESSAGE(KERN_WARNING, device, "interrupt status for " + "request %p was %d (%d retries left)", cqr, status, + cqr->retries); + dasd_diag_erp(device); + } if (expires != 0) dasd_set_timer(device, expires); @@ -218,14 +321,17 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code) spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); } +/* Check whether device can be controlled by DIAG discipline. Return zero on + * success, non-zero otherwise. */ static int dasd_diag_check_device(struct dasd_device *device) { struct dasd_diag_private *private; struct dasd_diag_characteristics *rdc_data; struct dasd_diag_bio bio; - long *label; - int sb, bsize; + struct dasd_diag_cms_label *label; + blocknum_t end_block; + unsigned int sb, bsize; int rc; private = (struct dasd_diag_private *) device->private; @@ -244,8 +350,11 @@ dasd_diag_check_device(struct dasd_device *device) rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics); rc = diag210((struct diag210 *) rdc_data); - if (rc) + if (rc) { + DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device " + "information (rc=%d)", rc); return -ENOTSUPP; + } /* Figure out position of label block */ switch (private->rdc_data.vdev_class) { @@ -256,6 +365,8 @@ dasd_diag_check_device(struct dasd_device *device) private->pt_block = 2; break; default: + DEV_MESSAGE(KERN_WARNING, device, "unsupported device class " + "(class=%d)", private->rdc_data.vdev_class); return -ENOTSUPP; } @@ -269,15 +380,17 @@ dasd_diag_check_device(struct dasd_device *device) mdsk_term_io(device); /* figure out blocksize of device */ - label = (long *) get_zeroed_page(GFP_KERNEL); + label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL); if (label == NULL) { DEV_MESSAGE(KERN_WARNING, device, "%s", "No memory to allocate initialization request"); return -ENOMEM; } + rc = 0; + end_block = 0; /* try all sizes - needed for ECKD devices */ for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) { - mdsk_init_io(device, bsize, 0, 64); + mdsk_init_io(device, bsize, 0, &end_block); memset(&bio, 0, sizeof (struct dasd_diag_bio)); bio.type = MDSK_READ_REQ; bio.block_number = private->pt_block + 1; @@ -289,37 +402,45 @@ dasd_diag_check_device(struct dasd_device *device) private->iob.block_count = 1; private->iob.interrupt_params = 0; private->iob.bio_list = __pa(&bio); - if (dia250(&private->iob, RW_BIO) == 0) + private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; + rc = dia250(&private->iob, RW_BIO); + if (rc == 0 || rc == 3) break; mdsk_term_io(device); } - if (bsize <= PAGE_SIZE && label[0] == 0xc3d4e2f1) { - /* get formatted blocksize from label block */ - bsize = (int) label[3]; - device->blocks = label[7]; + if (rc == 3) { + DEV_MESSAGE(KERN_WARNING, device, "%s", "DIAG call failed"); + rc = -EOPNOTSUPP; + } else if (rc != 0) { + DEV_MESSAGE(KERN_WARNING, device, "device access failed " + "(rc=%d)", rc); + rc = -EIO; + } else { + if (memcmp(label->label_id, DASD_DIAG_CMS1, + sizeof(DASD_DIAG_CMS1)) == 0) { + /* get formatted blocksize from label block */ + bsize = (unsigned int) label->block_size; + device->blocks = (unsigned long) label->block_count; + } else + device->blocks = end_block; device->bp_block = bsize; device->s2b_shift = 0; /* bits to shift 512 to get a block */ for (sb = 512; sb < bsize; sb = sb << 1) device->s2b_shift++; DEV_MESSAGE(KERN_INFO, device, - "capacity (%dkB blks): %ldkB", - (device->bp_block >> 10), - (device->blocks << device->s2b_shift) >> 1); + "(%ld B/blk): %ldkB", + (unsigned long) device->bp_block, + (unsigned long) (device->blocks << + device->s2b_shift) >> 1); rc = 0; - } else { - if (bsize > PAGE_SIZE) - DEV_MESSAGE(KERN_WARNING, device, "%s", - "DIAG access failed"); - else - DEV_MESSAGE(KERN_WARNING, device, "%s", - "volume is not CMS formatted"); - rc = -EMEDIUMTYPE; } free_page((long) label); return rc; } +/* Fill in virtual disk geometry for device. Return zero on success, non-zero + * otherwise. */ static int dasd_diag_fill_geometry(struct dasd_device *device, struct hd_geometry *geo) { @@ -349,6 +470,8 @@ dasd_diag_erp_postaction(struct dasd_ccw_req * cqr) return dasd_default_erp_postaction; } +/* Create DASD request from block device request. Return pointer to new + * request on success, ERR_PTR otherwise. */ static struct dasd_ccw_req * dasd_diag_build_cp(struct dasd_device * device, struct request *req) { @@ -358,9 +481,9 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) struct bio *bio; struct bio_vec *bv; char *dst; - int count, datasize; + unsigned int count, datasize; sector_t recid, first_rec, last_rec; - unsigned blksize, off; + unsigned int blksize, off; unsigned char rw_cmd; int i; @@ -413,13 +536,16 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) } } } + cqr->retries = DIAG_MAX_RETRIES; cqr->buildclk = get_clock(); cqr->device = device; - cqr->expires = 50 * HZ; /* 50 seconds */ + cqr->expires = DIAG_TIMEOUT; cqr->status = DASD_CQR_FILLED; return cqr; } +/* Release DASD request. Return non-zero if request was successful, zero + * otherwise. */ static int dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req) { @@ -430,6 +556,7 @@ dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req) return status; } +/* Fill in IOCTL data for device. */ static int dasd_diag_fill_info(struct dasd_device * device, struct dasd_information2_t * info) @@ -437,7 +564,7 @@ dasd_diag_fill_info(struct dasd_device * device, struct dasd_diag_private *private; private = (struct dasd_diag_private *) device->private; - info->label_block = private->pt_block; + info->label_block = (unsigned int) private->pt_block; info->FBA_layout = 1; info->format = DASD_FORMAT_LDL; info->characteristics_size = sizeof (struct dasd_diag_characteristics); @@ -456,26 +583,15 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, "dump sense not available for DIAG data"); } -/* - * max_blocks is dependent on the amount of storage that is available - * in the static io buffer for each device. Currently each device has - * 8192 bytes (=2 pages). dasd diag is only relevant for 31 bit. - * The struct dasd_ccw_req has 96 bytes, the struct dasd_diag_req has - * 8 bytes and the struct dasd_diag_bio for each block has 16 bytes. - * That makes: - * (8192 - 96 - 8) / 16 = 505.5 blocks at maximum. - * We want to fit two into the available memory so that we can immediately - * start the next request if one finishes off. That makes 252.75 blocks - * for one request. Give a little safety and the result is 240. - */ struct dasd_discipline dasd_diag_discipline = { .owner = THIS_MODULE, .name = "DIAG", .ebcname = "DIAG", - .max_blocks = 240, + .max_blocks = DIAG_MAX_BLOCKS, .check_device = dasd_diag_check_device, .fill_geometry = dasd_diag_fill_geometry, .start_IO = dasd_start_diag, + .term_IO = dasd_diag_term_IO, .examine_error = dasd_diag_examine_error, .erp_action = dasd_diag_erp_action, .erp_postaction = dasd_diag_erp_postaction, @@ -493,7 +609,7 @@ dasd_diag_init(void) "Machine is not VM: %s " "discipline not initializing", dasd_diag_discipline.name); - return -EINVAL; + return -ENODEV; } ASCEBC(dasd_diag_discipline.ebcname, 4); @@ -506,13 +622,6 @@ dasd_diag_init(void) static void __exit dasd_diag_cleanup(void) { - if (!MACHINE_IS_VM) { - MESSAGE_LOG(KERN_INFO, - "Machine is not VM: %s " - "discipline not cleaned", - dasd_diag_discipline.name); - return; - } unregister_external_interrupt(0x2603, dasd_ext_handler); ctl_clear_bit(0, 9); dasd_diag_discipline_pointer = NULL; @@ -520,22 +629,3 @@ dasd_diag_cleanup(void) module_init(dasd_diag_init); module_exit(dasd_diag_cleanup); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: 1 - * tab-width: 8 - * End: - */ diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h index a0c38e30397..b26eb28df4b 100644 --- a/drivers/s390/block/dasd_diag.h +++ b/drivers/s390/block/dasd_diag.h @@ -6,7 +6,7 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.6 $ + * $Revision: 1.7 $ */ #define MDSK_WRITE_REQ 0x01 @@ -19,6 +19,18 @@ #define DEV_CLASS_FBA 0x01 #define DEV_CLASS_ECKD 0x04 +#define DASD_DIAG_LC_INT_CODE 132 +#define DASD_DIAG_LC_INT_STATUS 133 +#define DASD_DIAG_LC_INT_PARM_31BIT 128 +#define DASD_DIAG_LC_INT_PARM_64BIT 4536 +#define DASD_DIAG_CODE_31BIT 0x03 +#define DASD_DIAG_CODE_64BIT 0x07 + +#define DASD_DIAG_RWFLAG_ASYNC 0x02 +#define DASD_DIAG_RWFLAG_NOCACHE 0x01 + +#define DASD_DIAG_FLAGA_FORMAT_64BIT 0x80 + struct dasd_diag_characteristics { u16 dev_nr; u16 rdc_len; @@ -32,35 +44,106 @@ struct dasd_diag_characteristics { u8 rdev_features; } __attribute__ ((packed, aligned(4))); +struct dasd_diag_cms_label { + u8 label_id[4]; + u8 vol_id[6]; + u16 version_id; + u32 block_size; + u32 origin_ptr; + u32 usable_count; + u32 formatted_count; + u32 block_count; + u32 used_count; + u32 fst_size; + u32 fst_count; + u8 format_date[6]; + u8 reserved1[2]; + u32 disk_offset; + u32 map_block; + u32 hblk_disp; + u32 user_disp; + u8 reserved2[4]; + u8 segment_name[8]; +} __attribute__ ((packed)); + +#ifdef CONFIG_ARCH_S390X +#define DASD_DIAG_FLAGA_DEFAULT DASD_DIAG_FLAGA_FORMAT_64BIT + +typedef u64 blocknum_t; +typedef s64 sblocknum_t; + +struct dasd_diag_bio { + u8 type; + u8 status; + u8 spare1[2]; + u32 alet; + blocknum_t block_number; + u64 buffer; +} __attribute__ ((packed, aligned(8))); + +struct dasd_diag_init_io { + u16 dev_nr; + u8 flaga; + u8 spare1[21]; + u32 block_size; + u8 spare2[4]; + blocknum_t offset; + sblocknum_t start_block; + blocknum_t end_block; + u8 spare3[8]; +} __attribute__ ((packed, aligned(8))); + +struct dasd_diag_rw_io { + u16 dev_nr; + u8 flaga; + u8 spare1[21]; + u8 key; + u8 flags; + u8 spare2[2]; + u32 block_count; + u32 alet; + u8 spare3[4]; + u64 interrupt_params; + u64 bio_list; + u8 spare4[8]; +} __attribute__ ((packed, aligned(8))); +#else /* CONFIG_ARCH_S390X */ +#define DASD_DIAG_FLAGA_DEFAULT 0x0 + +typedef u32 blocknum_t; +typedef s32 sblocknum_t; + struct dasd_diag_bio { u8 type; u8 status; u16 spare1; - u32 block_number; + blocknum_t block_number; u32 alet; u32 buffer; } __attribute__ ((packed, aligned(8))); struct dasd_diag_init_io { u16 dev_nr; - u16 spare1[11]; + u8 flaga; + u8 spare1[21]; u32 block_size; - u32 offset; - u32 start_block; - u32 end_block; - u32 spare2[6]; + blocknum_t offset; + sblocknum_t start_block; + blocknum_t end_block; + u8 spare2[24]; } __attribute__ ((packed, aligned(8))); struct dasd_diag_rw_io { u16 dev_nr; - u16 spare1[11]; + u8 flaga; + u8 spare1[21]; u8 key; u8 flags; - u16 spare2; + u8 spare2[2]; u32 block_count; u32 alet; u32 bio_list; u32 interrupt_params; - u32 spare3[5]; + u8 spare3[20]; } __attribute__ ((packed, aligned(8))); - +#endif /* CONFIG_ARCH_S390X */ diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 96c49349701..a601c9a3354 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -9,7 +9,7 @@ * * gendisk related functions for the dasd driver. * - * $Revision: 1.50 $ + * $Revision: 1.51 $ */ #include <linux/config.h> @@ -31,16 +31,12 @@ int dasd_gendisk_alloc(struct dasd_device *device) { struct gendisk *gdp; - int len, feature_ro; + int len; /* Make sure the minor for this device exists. */ if (device->devindex >= DASD_PER_MAJOR) return -EBUSY; - feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); - if (feature_ro < 0) - return feature_ro; - gdp = alloc_disk(1 << DASD_PARTN_BITS); if (!gdp) return -ENOMEM; @@ -75,7 +71,7 @@ dasd_gendisk_alloc(struct dasd_device *device) sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id); - if (feature_ro) + if (device->features & DASD_FEATURE_READONLY) set_disk_ro(gdp, 1); gdp->private_data = device; gdp->queue = device->request_queue; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index a9f38b23598..9fab04f3056 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -6,7 +6,7 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.64 $ + * $Revision: 1.65 $ */ #ifndef DASD_INT_H @@ -286,6 +286,7 @@ struct dasd_device { unsigned int bp_block; /* bytes per block */ unsigned int s2b_shift; /* log2 (bp_block/512) */ unsigned long flags; /* per device flags */ + unsigned short features; /* copy of devmap-features (read-only!) */ /* Device discipline stuff. */ struct dasd_discipline *discipline; diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 980c555aa53..789595b3fa0 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -7,7 +7,7 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.45 $ + * $Revision: 1.47 $ * * i/o controls for the dasd driver. */ @@ -296,7 +296,6 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args) { struct dasd_device *device; struct format_data_t fdata; - int feature_ro; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -308,10 +307,7 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args) if (device == NULL) return -ENODEV; - feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); - if (feature_ro < 0) - return feature_ro; - if (feature_ro) + if (device->features & DASD_FEATURE_READONLY) return -EROFS; if (copy_from_user(&fdata, (void __user *) args, sizeof (struct format_data_t))) @@ -384,7 +380,7 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) struct dasd_device *device; struct dasd_information2_t *dasd_info; unsigned long flags; - int rc, feature_ro; + int rc; struct ccw_device *cdev; device = bdev->bd_disk->private_data; @@ -394,10 +390,6 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) if (!device->discipline->fill_info) return -EINVAL; - feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); - if (feature_ro < 0) - return feature_ro; - dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL); if (dasd_info == NULL) return -ENOMEM; @@ -427,7 +419,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) (dasd_check_blocksize(device->bp_block))) dasd_info->format = DASD_FORMAT_NONE; - dasd_info->features |= feature_ro; + dasd_info->features |= + ((device->features & DASD_FEATURE_READONLY) != 0); if (device->discipline) memcpy(dasd_info->type, device->discipline->name, 4); diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 43c34f8c5e6..fff9020d488 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -9,7 +9,7 @@ * * /proc interface for the dasd driver. * - * $Revision: 1.32 $ + * $Revision: 1.33 $ */ #include <linux/config.h> @@ -55,7 +55,6 @@ dasd_devices_show(struct seq_file *m, void *v) { struct dasd_device *device; char *substr; - int feature; device = dasd_device_from_devindex((unsigned long) v - 1); if (IS_ERR(device)) @@ -79,10 +78,7 @@ dasd_devices_show(struct seq_file *m, void *v) else seq_printf(m, " is ????????"); /* Print devices features. */ - feature = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); - if (feature < 0) - return 0; - substr = feature ? "(ro)" : " "; + substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " "; seq_printf(m, "%4s: ", substr); /* Print device status information. */ switch ((device != NULL) ? device->state : -1) { diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index d5eefeaba50..328d9cbc56a 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -632,12 +632,9 @@ __raw3270_size_device(struct raw3270 *rp) raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data); rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request); - if (rc) { + if (rc) /* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */ - if (rc == -EOPNOTSUPP && MACHINE_IS_VM) - return __raw3270_size_device_vm(rp); return rc; - } /* Wait for attention interrupt. */ #ifdef CONFIG_TN3270_CONSOLE @@ -695,7 +692,10 @@ raw3270_size_device(struct raw3270 *rp) down(&raw3270_init_sem); rp->view = &raw3270_init_view; raw3270_init_view.dev = rp; - rc = __raw3270_size_device(rp); + if (MACHINE_IS_VM) + rc = __raw3270_size_device_vm(rp); + else + rc = __raw3270_size_device(rp); raw3270_init_view.dev = 0; rp->view = 0; up(&raw3270_init_sem); @@ -710,6 +710,12 @@ raw3270_size_device(struct raw3270 *rp) rp->model = 4; if (rp->rows == 27 && rp->cols == 132) rp->model = 5; + } else { + /* Couldn't detect size. Use default model 2. */ + rp->model = 2; + rp->rows = 24; + rp->cols = 80; + return 0; } return rc; } diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index ea813bdce1d..185bc73c3ec 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.134 $ + * $Revision: 1.135 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -815,8 +815,9 @@ __clear_subchannel_easy(unsigned int schid) struct tpi_info ti; if (tpi(&ti)) { - tsch(schid, (struct irb *)__LC_IRB); - return 0; + tsch(ti.irq, (struct irb *)__LC_IRB); + if (ti.irq == schid) + return 0; } udelay(100); } diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index ee7a05e0c3b..fbe4202a3f6 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -13,7 +13,7 @@ #include <linux/init.h> #include <asm/ccwdev.h> -#include <asm/qdio.h> +#include <asm/cio.h> #include "cio.h" #include "cio_debug.h" @@ -21,7 +21,6 @@ #include "device.h" #include "chsc.h" #include "ioasm.h" -#include "qdio.h" int device_is_online(struct subchannel *sch) diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 02d01a0de16..ad3fe5aeb66 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device_ops.c * - * $Revision: 1.56 $ + * $Revision: 1.57 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -19,14 +19,12 @@ #include <asm/ccwdev.h> #include <asm/idals.h> -#include <asm/qdio.h> #include "cio.h" #include "cio_debug.h" #include "css.h" #include "chsc.h" #include "device.h" -#include "qdio.h" int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index c874607d9a8..45480a2bc4c 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -21,7 +21,7 @@ struct tpi_info { * Some S390 specific IO instructions as inline */ -extern __inline__ int stsch(int irq, volatile struct schib *addr) +static inline int stsch(int irq, volatile struct schib *addr) { int ccode; @@ -36,7 +36,7 @@ extern __inline__ int stsch(int irq, volatile struct schib *addr) return ccode; } -extern __inline__ int msch(int irq, volatile struct schib *addr) +static inline int msch(int irq, volatile struct schib *addr) { int ccode; @@ -51,7 +51,7 @@ extern __inline__ int msch(int irq, volatile struct schib *addr) return ccode; } -extern __inline__ int msch_err(int irq, volatile struct schib *addr) +static inline int msch_err(int irq, volatile struct schib *addr) { int ccode; @@ -79,7 +79,7 @@ extern __inline__ int msch_err(int irq, volatile struct schib *addr) return ccode; } -extern __inline__ int tsch(int irq, volatile struct irb *addr) +static inline int tsch(int irq, volatile struct irb *addr) { int ccode; @@ -94,7 +94,7 @@ extern __inline__ int tsch(int irq, volatile struct irb *addr) return ccode; } -extern __inline__ int tpi( volatile struct tpi_info *addr) +static inline int tpi( volatile struct tpi_info *addr) { int ccode; @@ -108,7 +108,7 @@ extern __inline__ int tpi( volatile struct tpi_info *addr) return ccode; } -extern __inline__ int ssch(int irq, volatile struct orb *addr) +static inline int ssch(int irq, volatile struct orb *addr) { int ccode; @@ -123,7 +123,7 @@ extern __inline__ int ssch(int irq, volatile struct orb *addr) return ccode; } -extern __inline__ int rsch(int irq) +static inline int rsch(int irq) { int ccode; @@ -138,7 +138,7 @@ extern __inline__ int rsch(int irq) return ccode; } -extern __inline__ int csch(int irq) +static inline int csch(int irq) { int ccode; @@ -153,7 +153,7 @@ extern __inline__ int csch(int irq) return ccode; } -extern __inline__ int hsch(int irq) +static inline int hsch(int irq) { int ccode; @@ -168,7 +168,7 @@ extern __inline__ int hsch(int irq) return ccode; } -extern __inline__ int xsch(int irq) +static inline int xsch(int irq) { int ccode; @@ -183,7 +183,7 @@ extern __inline__ int xsch(int irq) return ccode; } -extern __inline__ int chsc(void *chsc_area) +static inline int chsc(void *chsc_area) { int cc; @@ -198,7 +198,7 @@ extern __inline__ int chsc(void *chsc_area) return cc; } -extern __inline__ int iac( void) +static inline int iac( void) { int ccode; @@ -210,7 +210,7 @@ extern __inline__ int iac( void) return ccode; } -extern __inline__ int rchp(int chpid) +static inline int rchp(int chpid) { int ccode; diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h index bcabac7a7c4..e319e78b5ea 100644 --- a/drivers/s390/crypto/z90common.h +++ b/drivers/s390/crypto/z90common.h @@ -27,7 +27,7 @@ #ifndef _Z90COMMON_H_ #define _Z90COMMON_H_ -#define VERSION_Z90COMMON_H "$Revision: 1.16 $" +#define VERSION_Z90COMMON_H "$Revision: 1.17 $" #define RESPBUFFSIZE 256 @@ -164,5 +164,4 @@ struct CPRBX { #define UMIN(a,b) ((a) < (b) ? (a) : (b)) #define IS_EVEN(x) ((x) == (2 * ((x) / 2))) - #endif diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c index beb6a5e0da2..c215e088973 100644 --- a/drivers/s390/crypto/z90hardware.c +++ b/drivers/s390/crypto/z90hardware.c @@ -32,7 +32,7 @@ #include "z90crypt.h" #include "z90common.h" -#define VERSION_Z90HARDWARE_C "$Revision: 1.33 $" +#define VERSION_Z90HARDWARE_C "$Revision: 1.34 $" char z90hardware_version[] __initdata = "z90hardware.o (" VERSION_Z90HARDWARE_C "/" @@ -283,48 +283,6 @@ struct type6_msg { struct CPRB CPRB; }; -union request_msg { - union type4_msg t4msg; - struct type6_msg t6msg; -}; - -struct request_msg_ext { - int q_nr; - unsigned char *psmid; - union request_msg reqMsg; -}; - -struct type82_hdr { - unsigned char reserved1; - unsigned char type; - unsigned char reserved2[2]; - unsigned char reply_code; - unsigned char reserved3[3]; -}; - -#define TYPE82_RSP_CODE 0x82 - -#define REPLY_ERROR_MACHINE_FAILURE 0x10 -#define REPLY_ERROR_PREEMPT_FAILURE 0x12 -#define REPLY_ERROR_CHECKPT_FAILURE 0x14 -#define REPLY_ERROR_MESSAGE_TYPE 0x20 -#define REPLY_ERROR_INVALID_COMM_CD 0x21 -#define REPLY_ERROR_INVALID_MSG_LEN 0x23 -#define REPLY_ERROR_RESERVD_FIELD 0x24 -#define REPLY_ERROR_FORMAT_FIELD 0x29 -#define REPLY_ERROR_INVALID_COMMAND 0x30 -#define REPLY_ERROR_MALFORMED_MSG 0x40 -#define REPLY_ERROR_RESERVED_FIELDO 0x50 -#define REPLY_ERROR_WORD_ALIGNMENT 0x60 -#define REPLY_ERROR_MESSAGE_LENGTH 0x80 -#define REPLY_ERROR_OPERAND_INVALID 0x82 -#define REPLY_ERROR_OPERAND_SIZE 0x84 -#define REPLY_ERROR_EVEN_MOD_IN_OPND 0x85 -#define REPLY_ERROR_RESERVED_FIELD 0x88 -#define REPLY_ERROR_TRANSPORT_FAIL 0x90 -#define REPLY_ERROR_PACKET_TRUNCATED 0xA0 -#define REPLY_ERROR_ZERO_BUFFER_LEN 0xB0 - struct type86_hdr { unsigned char reserved1; unsigned char type; @@ -338,7 +296,7 @@ struct type86_hdr { #define TYPE86_FMT2 0x02 struct type86_fmt2_msg { - struct type86_hdr hdr; + struct type86_hdr header; unsigned char reserved[4]; unsigned char apfs[4]; unsigned int count1; @@ -538,6 +496,8 @@ static struct function_and_rules_block static_pke_function_and_rulesX = { {'M','R','P',' ',' ',' ',' ',' '} }; +static unsigned char static_PKE_function_code[2] = {0x50, 0x4B}; + struct T6_keyBlock_hdrX { unsigned short blen; unsigned short ulen; @@ -688,9 +648,38 @@ static struct cca_public_sec static_cca_pub_sec = { #define RESPONSE_CPRB_SIZE 0x000006B8 #define RESPONSE_CPRBX_SIZE 0x00000724 -#define CALLER_HEADER 12 +struct error_hdr { + unsigned char reserved1; + unsigned char type; + unsigned char reserved2[2]; + unsigned char reply_code; + unsigned char reserved3[3]; +}; -static unsigned char static_PKE_function_code[2] = {0x50, 0x4B}; +#define TYPE82_RSP_CODE 0x82 + +#define REP82_ERROR_MACHINE_FAILURE 0x10 +#define REP82_ERROR_PREEMPT_FAILURE 0x12 +#define REP82_ERROR_CHECKPT_FAILURE 0x14 +#define REP82_ERROR_MESSAGE_TYPE 0x20 +#define REP82_ERROR_INVALID_COMM_CD 0x21 +#define REP82_ERROR_INVALID_MSG_LEN 0x23 +#define REP82_ERROR_RESERVD_FIELD 0x24 +#define REP82_ERROR_FORMAT_FIELD 0x29 +#define REP82_ERROR_INVALID_COMMAND 0x30 +#define REP82_ERROR_MALFORMED_MSG 0x40 +#define REP82_ERROR_RESERVED_FIELDO 0x50 +#define REP82_ERROR_WORD_ALIGNMENT 0x60 +#define REP82_ERROR_MESSAGE_LENGTH 0x80 +#define REP82_ERROR_OPERAND_INVALID 0x82 +#define REP82_ERROR_OPERAND_SIZE 0x84 +#define REP82_ERROR_EVEN_MOD_IN_OPND 0x85 +#define REP82_ERROR_RESERVED_FIELD 0x88 +#define REP82_ERROR_TRANSPORT_FAIL 0x90 +#define REP82_ERROR_PACKET_TRUNCATED 0xA0 +#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0 + +#define CALLER_HEADER 12 static inline int testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat) @@ -1212,9 +1201,9 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext) struct ap_status_word stat_word; enum devstat stat; int ccode; + u32 *q_nr_p = (u32 *)msg_ext; - ((struct request_msg_ext *) msg_ext)->q_nr = - (dev_nr << SKIP_BITL) + cdx; + *q_nr_p = (dev_nr << SKIP_BITL) + cdx; PDEBUG("msg_len passed to sen: %d\n", msg_len); PDEBUG("q number passed to sen: %02x%02x%02x%02x\n", msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3]); @@ -2104,7 +2093,7 @@ convert_response(unsigned char *response, unsigned char *buffer, int *respbufflen_p, unsigned char *resp_buff) { struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer; - struct type82_hdr *t82h_p = (struct type82_hdr *) response; + struct error_hdr *errh_p = (struct error_hdr *) response; struct type84_hdr *t84h_p = (struct type84_hdr *) response; struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response; int reply_code, service_rc, service_rs, src_l; @@ -2117,12 +2106,13 @@ convert_response(unsigned char *response, unsigned char *buffer, service_rc = 0; service_rs = 0; src_l = 0; - switch (t82h_p->type) { + switch (errh_p->type) { case TYPE82_RSP_CODE: - reply_code = t82h_p->reply_code; - src_p = (unsigned char *)t82h_p; - PRINTK("Hardware error: Type 82 Message Header: " + reply_code = errh_p->reply_code; + src_p = (unsigned char *)errh_p; + PRINTK("Hardware error: Type %02X Message Header: " "%02x%02x%02x%02x%02x%02x%02x%02x\n", + errh_p->type, src_p[0], src_p[1], src_p[2], src_p[3], src_p[4], src_p[5], src_p[6], src_p[7]); break; @@ -2131,7 +2121,7 @@ convert_response(unsigned char *response, unsigned char *buffer, src_p = response + (int)t84h_p->len - src_l; break; case TYPE86_RSP_CODE: - reply_code = t86m_p->hdr.reply_code; + reply_code = t86m_p->header.reply_code; if (reply_code != 0) break; cprb_p = (struct CPRB *) @@ -2143,6 +2133,9 @@ convert_response(unsigned char *response, unsigned char *buffer, le2toI(cprb_p->ccp_rscode, &service_rs); if ((service_rc == 8) && (service_rs == 66)) PDEBUG("Bad block format on PCICC\n"); + else if ((service_rc == 8) && (service_rs == 65)) + PDEBUG("Probably an even modulus on " + "PCICC\n"); else if ((service_rc == 8) && (service_rs == 770)) { PDEBUG("Invalid key length on PCICC\n"); unset_ext_bitlens(); @@ -2155,7 +2148,7 @@ convert_response(unsigned char *response, unsigned char *buffer, return REC_USE_PCICA; } else - PRINTK("service rc/rs: %d/%d\n", + PRINTK("service rc/rs (PCICC): %d/%d\n", service_rc, service_rs); return REC_OPERAND_INV; } @@ -2169,7 +2162,10 @@ convert_response(unsigned char *response, unsigned char *buffer, if (service_rc != 0) { service_rs = (int) cprbx_p->ccp_rscode; if ((service_rc == 8) && (service_rs == 66)) - PDEBUG("Bad block format on PCXICC\n"); + PDEBUG("Bad block format on PCIXCC\n"); + else if ((service_rc == 8) && (service_rs == 65)) + PDEBUG("Probably an even modulus on " + "PCIXCC\n"); else if ((service_rc == 8) && (service_rs == 770)) { PDEBUG("Invalid key length on PCIXCC\n"); unset_ext_bitlens(); @@ -2182,7 +2178,7 @@ convert_response(unsigned char *response, unsigned char *buffer, return REC_USE_PCICA; } else - PRINTK("service rc/rs: %d/%d\n", + PRINTK("service rc/rs (PCIXCC): %d/%d\n", service_rc, service_rs); return REC_OPERAND_INV; } @@ -2195,20 +2191,25 @@ convert_response(unsigned char *response, unsigned char *buffer, } break; default: + src_p = (unsigned char *)errh_p; + PRINTK("Unrecognized Message Header: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + src_p[0], src_p[1], src_p[2], src_p[3], + src_p[4], src_p[5], src_p[6], src_p[7]); return REC_BAD_MESSAGE; } if (reply_code) switch (reply_code) { - case REPLY_ERROR_OPERAND_INVALID: + case REP82_ERROR_OPERAND_INVALID: return REC_OPERAND_INV; - case REPLY_ERROR_OPERAND_SIZE: + case REP82_ERROR_OPERAND_SIZE: return REC_OPERAND_SIZE; - case REPLY_ERROR_EVEN_MOD_IN_OPND: + case REP82_ERROR_EVEN_MOD_IN_OPND: return REC_EVEN_MOD; - case REPLY_ERROR_MESSAGE_TYPE: + case REP82_ERROR_MESSAGE_TYPE: return WRONG_DEVICE_TYPE; - case REPLY_ERROR_TRANSPORT_FAIL: + case REP82_ERROR_TRANSPORT_FAIL: PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n", t86m_p->apfs[0], t86m_p->apfs[1], t86m_p->apfs[2], t86m_p->apfs[3]); @@ -2229,7 +2230,7 @@ convert_response(unsigned char *response, unsigned char *buffer, PDEBUG("Length returned = %d\n", src_l); tgt_p = resp_buff + icaMsg_p->outputdatalength - src_l; memcpy(tgt_p, src_p, src_l); - if ((t82h_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) { + if ((errh_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) { memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l); if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l)) return REC_INVALID_PAD; diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 9ec29bb41b2..6aeef3bacc3 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -31,6 +31,7 @@ #include <linux/init.h> #include <linux/interrupt.h> // for tasklets #include <linux/ioctl32.h> +#include <linux/miscdevice.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kobject_uevent.h> @@ -39,19 +40,8 @@ #include <linux/version.h> #include "z90crypt.h" #include "z90common.h" -#ifndef Z90CRYPT_USE_HOTPLUG -#include <linux/miscdevice.h> -#endif - -#define VERSION_CODE(vers, rel, seq) (((vers)<<16) | ((rel)<<8) | (seq)) -#if LINUX_VERSION_CODE < VERSION_CODE(2,4,0) /* version < 2.4 */ -# error "This kernel is too old: not supported" -#endif -#if LINUX_VERSION_CODE > VERSION_CODE(2,7,0) /* version > 2.6 */ -# error "This kernel is too recent: not supported by this file" -#endif -#define VERSION_Z90MAIN_C "$Revision: 1.57 $" +#define VERSION_Z90MAIN_C "$Revision: 1.62 $" static char z90main_version[] __initdata = "z90main.o (" VERSION_Z90MAIN_C "/" @@ -63,21 +53,12 @@ extern char z90hardware_version[]; * Defaults that may be modified. */ -#ifndef Z90CRYPT_USE_HOTPLUG /** * You can specify a different minor at compile time. */ #ifndef Z90CRYPT_MINOR #define Z90CRYPT_MINOR MISC_DYNAMIC_MINOR #endif -#else -/** - * You can specify a different major at compile time. - */ -#ifndef Z90CRYPT_MAJOR -#define Z90CRYPT_MAJOR 0 -#endif -#endif /** * You can specify a different domain at compile time or on the insmod @@ -97,7 +78,7 @@ extern char z90hardware_version[]; * older than CLEANUPTIME seconds in the past. */ #ifndef CLEANUPTIME -#define CLEANUPTIME 20 +#define CLEANUPTIME 15 #endif /** @@ -298,6 +279,10 @@ struct z90crypt { * it contains the request; at READ, the response. The function * send_to_crypto_device converts the request to device-dependent * form and use the caller's OPEN-allocated buffer for the response. + * + * For the contents of caller_dev_dep_req and caller_dev_dep_req_p + * because that points to it, see the discussion in z90hardware.c. + * Search for "extended request message block". */ struct caller { int caller_buf_l; // length of original request @@ -398,24 +383,9 @@ static int z90crypt_status_write(struct file *, const char __user *, unsigned long, void *); /** - * Hotplug support - */ - -#ifdef Z90CRYPT_USE_HOTPLUG -#define Z90CRYPT_HOTPLUG_ADD 1 -#define Z90CRYPT_HOTPLUG_REMOVE 2 - -static void z90crypt_hotplug_event(int, int, int); -#endif - -/** * Storage allocated at initialization and used throughout the life of * this insmod */ -#ifdef Z90CRYPT_USE_HOTPLUG -static int z90crypt_major = Z90CRYPT_MAJOR; -#endif - static int domain = DOMAIN_INDEX; static struct z90crypt z90crypt; static int quiesce_z90crypt; @@ -444,14 +414,12 @@ static struct file_operations z90crypt_fops = { .release = z90crypt_release }; -#ifndef Z90CRYPT_USE_HOTPLUG static struct miscdevice z90crypt_misc_device = { .minor = Z90CRYPT_MINOR, .name = DEV_NAME, .fops = &z90crypt_fops, .devfs_name = DEV_NAME }; -#endif /** * Documentation values. @@ -603,7 +571,6 @@ z90crypt_init_module(void) return -EINVAL; } -#ifndef Z90CRYPT_USE_HOTPLUG /* Register as misc device with given minor (or get a dynamic one). */ result = misc_register(&z90crypt_misc_device); if (result < 0) { @@ -611,18 +578,6 @@ z90crypt_init_module(void) z90crypt_misc_device.minor, result); return result; } -#else - /* Register the major (or get a dynamic one). */ - result = register_chrdev(z90crypt_major, REG_NAME, &z90crypt_fops); - if (result < 0) { - PRINTKW("register_chrdev (major %d) failed with %d.\n", - z90crypt_major, result); - return result; - } - - if (z90crypt_major == 0) - z90crypt_major = result; -#endif PDEBUG("Registered " DEV_NAME " with result %d\n", result); @@ -645,11 +600,6 @@ z90crypt_init_module(void) } else PRINTK("No devices at startup\n"); -#ifdef Z90CRYPT_USE_HOTPLUG - /* generate hotplug event for device node generation */ - z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_ADD); -#endif - /* Initialize globals. */ spin_lock_init(&queuespinlock); @@ -701,17 +651,10 @@ z90crypt_init_module(void) return 0; // success init_module_cleanup: -#ifndef Z90CRYPT_USE_HOTPLUG if ((nresult = misc_deregister(&z90crypt_misc_device))) PRINTK("misc_deregister failed with %d.\n", nresult); else PDEBUG("misc_deregister successful.\n"); -#else - if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME))) - PRINTK("unregister_chrdev failed with %d.\n", nresult); - else - PDEBUG("unregister_chrdev successful.\n"); -#endif return result; // failure } @@ -728,19 +671,10 @@ z90crypt_cleanup_module(void) remove_proc_entry("driver/z90crypt", 0); -#ifndef Z90CRYPT_USE_HOTPLUG if ((nresult = misc_deregister(&z90crypt_misc_device))) PRINTK("misc_deregister failed with %d.\n", nresult); else PDEBUG("misc_deregister successful.\n"); -#else - z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_REMOVE); - - if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME))) - PRINTK("unregister_chrdev failed with %d.\n", nresult); - else - PDEBUG("unregister_chrdev successful.\n"); -#endif /* Remove the tasks */ tasklet_kill(&reader_tasklet); @@ -748,6 +682,9 @@ z90crypt_cleanup_module(void) del_timer(&config_timer); del_timer(&cleanup_timer); + if (z90_device_work) + destroy_workqueue(z90_device_work); + destroy_z90crypt(); PRINTKN("Unloaded.\n"); @@ -766,8 +703,6 @@ z90crypt_cleanup_module(void) * z90crypt_status_write * disable_card * enable_card - * scan_char - * scan_string * * Helper functions: * z90crypt_rsa @@ -1057,9 +992,10 @@ remove_device(struct device *device_p) * The MCL must be applied and the newer bitlengths enabled for these to work. * * Card Type Old limit New limit + * PCICA ??-2048 same (the lower limit is less than 128 bit...) * PCICC 512-1024 512-2048 - * PCIXCC_MCL2 512-2048 no change (applying this MCL == card is MCL3+) - * PCIXCC_MCL3 512-2048 128-2048 + * PCIXCC_MCL2 512-2048 ----- (applying any GA LIC will make an MCL3 card) + * PCIXCC_MCL3 ----- 128-2048 * CEX2C 512-2048 128-2048 * * ext_bitlens (extended bitlengths) is a global, since you should not apply an @@ -1104,7 +1040,7 @@ select_device_type(int *dev_type_p, int bytelength) if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) { /** * bitlength is a factor, PCICA is the most capable, even with - * the new MCL. + * the new MCL for PCIXCC. */ if ((bytelength < PCIXCC_MIN_MOD_SIZE) || (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) { @@ -2144,73 +2080,15 @@ enable_card(int card_index) z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count--; } -static inline int -scan_char(unsigned char *bf, unsigned int len, - unsigned int *offs, unsigned int *p_eof, unsigned char c) -{ - unsigned int i, found; - - found = 0; - for (i = 0; i < len; i++) { - if (bf[i] == c) { - found = 1; - break; - } - if (bf[i] == '\0') { - *p_eof = 1; - break; - } - if (bf[i] == '\n') { - break; - } - } - *offs = i+1; - return found; -} - -static inline int -scan_string(unsigned char *bf, unsigned int len, - unsigned int *offs, unsigned int *p_eof, unsigned char *s) -{ - unsigned int temp_len, temp_offs, found, eof; - - temp_len = temp_offs = found = eof = 0; - while (!eof && !found) { - found = scan_char(bf+temp_len, len-temp_len, - &temp_offs, &eof, *s); - - temp_len += temp_offs; - if (eof) { - found = 0; - break; - } - - if (found) { - if (len >= temp_offs+strlen(s)) { - found = !strncmp(bf+temp_len-1, s, strlen(s)); - if (found) { - *offs = temp_len+strlen(s)-1; - break; - } - } else { - found = 0; - *p_eof = 1; - break; - } - } - } - return found; -} - static int z90crypt_status_write(struct file *file, const char __user *buffer, unsigned long count, void *data) { - int i, j, len, offs, found, eof; - unsigned char *lbuf; + int j, eol; + unsigned char *lbuf, *ptr; unsigned int local_count; -#define LBUFSIZE 600 +#define LBUFSIZE 1200 lbuf = kmalloc(LBUFSIZE, GFP_KERNEL); if (!lbuf) { PRINTK("kmalloc failed!\n"); @@ -2227,49 +2105,46 @@ z90crypt_status_write(struct file *file, const char __user *buffer, return -EFAULT; } - lbuf[local_count-1] = '\0'; + lbuf[local_count] = '\0'; - len = 0; - eof = 0; - found = 0; - while (!eof) { - found = scan_string(lbuf+len, local_count-len, &offs, &eof, - "Online devices"); - len += offs; - if (found == 1) - break; + ptr = strstr(lbuf, "Online devices"); + if (ptr == 0) { + PRINTK("Unable to parse data (missing \"Online devices\")\n"); + kfree(lbuf); + return count; } - if (eof) { + ptr = strstr(ptr, "\n"); + if (ptr == 0) { + PRINTK("Unable to parse data (missing newline after \"Online devices\")\n"); kfree(lbuf); return count; } + ptr++; - if (found) - found = scan_char(lbuf+len, local_count-len, &offs, &eof, '\n'); - - if (!found || eof) { + if (strstr(ptr, "Waiting work element counts") == NULL) { + PRINTK("Unable to parse data (missing \"Waiting work element counts\")\n"); kfree(lbuf); return count; } - len += offs; j = 0; - for (i = 0; i < 80; i++) { - switch (*(lbuf+len+i)) { + eol = 0; + while ((j < 64) && (*ptr != '\0')) { + switch (*ptr) { case '\t': case ' ': break; case '\n': default: - eof = 1; + eol = 1; break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': + case '0': // no device + case '1': // PCICA + case '2': // PCICC + case '3': // PCIXCC_MCL2 + case '4': // PCIXCC_MCL3 + case '5': // CEX2C j++; break; case 'd': @@ -2283,8 +2158,9 @@ z90crypt_status_write(struct file *file, const char __user *buffer, j++; break; } - if (eof) + if (eol) break; + ptr++; } kfree(lbuf); @@ -3479,45 +3355,5 @@ probe_PCIXCC_type(struct device *devPtr) return rv; } -#ifdef Z90CRYPT_USE_HOTPLUG -static void -z90crypt_hotplug_event(int dev_major, int dev_minor, int action) -{ -#ifdef CONFIG_HOTPLUG - char *argv[3]; - char *envp[6]; - char major[20]; - char minor[20]; - - sprintf(major, "MAJOR=%d", dev_major); - sprintf(minor, "MINOR=%d", dev_minor); - - argv[0] = hotplug_path; - argv[1] = "z90crypt"; - argv[2] = 0; - - envp[0] = "HOME=/"; - envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; - - switch (action) { - case Z90CRYPT_HOTPLUG_ADD: - envp[2] = "ACTION=add"; - break; - case Z90CRYPT_HOTPLUG_REMOVE: - envp[2] = "ACTION=remove"; - break; - default: - BUG(); - break; - } - envp[3] = major; - envp[4] = minor; - envp[5] = 0; - - call_usermodehelper(argv[0], argv, envp, 0); -#endif -} -#endif - module_init(z90crypt_init_module); module_exit(z90crypt_cleanup_module); diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 5bb255e02ac..4191fd9d4d1 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c @@ -240,7 +240,7 @@ s390_revalidate_registers(struct mci *mci) * Floating point control register can't be restored. * Task will be terminated. */ - asm volatile ("lfpc 0(%0)" : : "a" (&zero)); + asm volatile ("lfpc 0(%0)" : : "a" (&zero), "m" (zero)); kill_task = 1; } diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig index a41778a490d..3a8152906bf 100644 --- a/drivers/sbus/char/Kconfig +++ b/drivers/sbus/char/Kconfig @@ -69,11 +69,40 @@ config SUN_JSFLASH If you say Y here, you will be able to boot from your JavaStation's Flash memory. -# XXX Why don't we do "source drivers/char/Config.in" somewhere? -# no shit -config RTC - tristate "PC-style Real Time Clock Support" - depends on PCI && EXPERIMENTAL && SPARC32 +config BBC_I2C + tristate "UltraSPARC-III bootbus i2c controller driver" + depends on PCI && SPARC64 + help + The BBC devices on the UltraSPARC III have two I2C controllers. The + first I2C controller connects mainly to configuration PROMs (NVRAM, + CPU configuration, DIMM types, etc.). The second I2C controller + connects to environmental control devices such as fans and + temperature sensors. The second controller also connects to the + smartcard reader, if present. Say Y to enable support for these. + +config ENVCTRL + tristate "SUNW, envctrl support" + depends on PCI && SPARC64 + help + Kernel support for temperature and fan monitoring on Sun SME + machines. + + To compile this driver as a module, choose M here: the + module will be called envctrl. + +config DISPLAY7SEG + tristate "7-Segment Display support" + depends on PCI && SPARC64 + ---help--- + This is the driver for the 7-segment display and LED present on + Sun Microsystems CompactPCI models CP1400 and CP1500. + + To compile this driver as a module, choose M here: the + module will be called display7seg. + + If you do not have a CompactPCI model CP1400 or CP1500, or + another UltraSPARC-IIi-cEngine boardset with a 7-segment display, + you should say N to this option. endmenu diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 12c208fb18c..787ad00a2b7 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -250,7 +250,7 @@ config SCSI_DECNCR config SCSI_DECSII tristate "DEC SII Scsi Driver" - depends on MACH_DECSTATION && SCSI && MIPS32 + depends on MACH_DECSTATION && SCSI && 32BIT config BLK_DEV_3W_XXXX_RAID tristate "3ware 5/6/7/8xxx ATA-RAID support" diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index ff1933298da..a4857db4f9b 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1766,7 +1766,7 @@ static int mesh_suspend(struct macio_dev *mdev, pm_message_t state) struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev); unsigned long flags; - if (state == mdev->ofdev.dev.power.power_state || state < 2) + if (state.event == mdev->ofdev.dev.power.power_state.event || state.event < 2) return 0; scsi_block_requests(ms->host); @@ -1791,7 +1791,7 @@ static int mesh_resume(struct macio_dev *mdev) struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev); unsigned long flags; - if (mdev->ofdev.dev.power.power_state == 0) + if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON) return 0; set_mesh_power(ms, 1); @@ -1802,7 +1802,7 @@ static int mesh_resume(struct macio_dev *mdev) enable_irq(ms->meshintr); scsi_unblock_requests(ms->host); - mdev->ofdev.dev.power.power_state = 0; + mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON; return 0; } diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 74b80f7c062..e39818a34a0 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -308,7 +308,7 @@ config SERIAL_S3C2410_CONSOLE config SERIAL_DZ bool "DECstation DZ serial driver" - depends on MACH_DECSTATION && MIPS32 + depends on MACH_DECSTATION && 32BIT select SERIAL_CORE help DZ11-family serial controllers for VAXstations, including the diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 282b32351d8..25825f2aba2 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -403,10 +403,8 @@ static int cpm_uart_startup(struct uart_port *port) inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo) { - unsigned long target_jiffies = jiffies + pinfo->wait_closing; - - while (!time_after(jiffies, target_jiffies)) - schedule(); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(pinfo->wait_closing); } /* @@ -425,9 +423,12 @@ static void cpm_uart_shutdown(struct uart_port *port) /* If the port is not the console, disable Rx and Tx. */ if (!(pinfo->flags & FLAG_CONSOLE)) { /* Wait for all the BDs marked sent */ - while(!cpm_uart_tx_empty(port)) + while(!cpm_uart_tx_empty(port)) { + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(2); - if(pinfo->wait_closing) + } + + if (pinfo->wait_closing) cpm_uart_wait_until_send(pinfo); /* Stop uarts */ diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index c4c8f4b44f5..15ad58d9488 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c @@ -142,6 +142,14 @@ void scc2_lineif(struct uart_cpm_port *pinfo) * be supported in a sane fashion. */ #ifndef CONFIG_STX_GP3 +#ifdef CONFIG_MPC8560_ADS + volatile iop_cpm2_t *io = &cpm2_immr->im_ioport; + io->iop_ppard |= 0x00000018; + io->iop_psord &= ~0x00000008; /* Rx */ + io->iop_psord &= ~0x00000010; /* Tx */ + io->iop_pdird &= ~0x00000008; /* Rx */ + io->iop_pdird |= 0x00000010; /* Tx */ +#else volatile iop_cpm2_t *io = &cpm2_immr->im_ioport; io->iop_pparb |= 0x008b0000; io->iop_pdirb |= 0x00880000; @@ -149,6 +157,7 @@ void scc2_lineif(struct uart_cpm_port *pinfo) io->iop_pdirb &= ~0x00030000; io->iop_psorb &= ~0x00030000; #endif +#endif cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff; cpm2_immr->im_cpmux.cmx_scr |= 0x00090000; pinfo->brg = 2; @@ -257,6 +266,7 @@ int cpm_uart_init_portdesc(void) cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0]; cpm_uart_ports[UART_SMC1].smcup = (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC1]; + *(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1; cpm_uart_ports[UART_SMC1].port.mapbase = (unsigned long)&cpm2_immr->im_smc[0]; cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX); @@ -269,6 +279,7 @@ int cpm_uart_init_portdesc(void) cpm_uart_ports[UART_SMC2].smcp = (smc_t *) & cpm2_immr->im_smc[1]; cpm_uart_ports[UART_SMC2].smcup = (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC2]; + *(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2; cpm_uart_ports[UART_SMC2].port.mapbase = (unsigned long)&cpm2_immr->im_smc[1]; cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX); diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 23b8871e74c..5690594b257 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -5041,17 +5041,3 @@ rs_init(void) /* this makes sure that rs_init is called during kernel boot */ module_init(rs_init); - -/* - * register_serial and unregister_serial allows for serial ports to be - * configured at run-time, to support PCMCIA modems. - */ -int -register_serial(struct serial_struct *req) -{ - return -1; -} - -void unregister_serial(int line) -{ -} diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 5bfde99e245..5ddd8ab1f10 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1600,7 +1600,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) return 0; } - if (pm_state == mdev->ofdev.dev.power.power_state || pm_state < 2) + if (pm_state.event == mdev->ofdev.dev.power.power_state.event) return 0; pmz_debug("suspend, switching to state %d\n", pm_state); @@ -1660,7 +1660,7 @@ static int pmz_resume(struct macio_dev *mdev) if (uap == NULL) return 0; - if (mdev->ofdev.dev.power.power_state == 0) + if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON) return 0; pmz_debug("resume, switching to state 0\n"); @@ -1713,7 +1713,7 @@ static int pmz_resume(struct macio_dev *mdev) pmz_debug("resume, switching complete\n"); - mdev->ofdev.dev.power.power_state = 0; + mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON; return 0; } diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index dea156a62d0..2d8622eef70 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1947,21 +1947,29 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) static inline void uart_report_port(struct uart_driver *drv, struct uart_port *port) { - printk("%s%d", drv->dev_name, port->line); - printk(" at "); + char address[64]; + switch (port->iotype) { case UPIO_PORT: - printk("I/O 0x%x", port->iobase); + snprintf(address, sizeof(address), + "I/O 0x%x", port->iobase); break; case UPIO_HUB6: - printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6); + snprintf(address, sizeof(address), + "I/O 0x%x offset 0x%x", port->iobase, port->hub6); break; case UPIO_MEM: case UPIO_MEM32: - printk("MMIO 0x%lx", port->mapbase); + snprintf(address, sizeof(address), + "MMIO 0x%lx", port->mapbase); + break; + default: + strlcpy(address, "*unknown*", sizeof(address)); break; } - printk(" (irq = %d) is a %s\n", port->irq, uart_type(port)); + + printk(KERN_INFO "%s%d at %s (irq = %d) is a %s\n", + drv->dev_name, port->line, address, port->irq, uart_type(port)); } static void diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c3e46d24a37..c9412daff68 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1570,7 +1570,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, struct usb_driver *driver; intf = udev->actconfig->interface[i]; - if (state <= intf->dev.power.power_state) + if (state.event <= intf->dev.power.power_state.event) continue; if (!intf->dev.driver) continue; @@ -1578,11 +1578,11 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, if (driver->suspend) { status = driver->suspend(intf, state); - if (intf->dev.power.power_state != state + if (intf->dev.power.power_state.event != state.event || status) dev_err(&intf->dev, "suspend %d fail, code %d\n", - state, status); + state.event, status); } /* only drivers with suspend() can ever resume(); @@ -1595,7 +1595,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, * since we know every driver's probe/disconnect works * even for drivers that can't suspend. */ - if (!driver->suspend || state > PM_SUSPEND_MEM) { + if (!driver->suspend || state.event > PM_EVENT_FREEZE) { #if 1 dev_warn(&intf->dev, "resume is unsafe!\n"); #else @@ -1616,7 +1616,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, * policies (when HNP doesn't apply) once we have mechanisms to * turn power back on! (Likely not before 2.7...) */ - if (state > PM_SUSPEND_MEM) { + if (state.event > PM_EVENT_FREEZE) { dev_warn(&udev->dev, "no poweroff yet, suspending instead\n"); } @@ -1733,7 +1733,7 @@ static int finish_port_resume(struct usb_device *udev) struct usb_driver *driver; intf = udev->actconfig->interface[i]; - if (intf->dev.power.power_state == PMSG_ON) + if (intf->dev.power.power_state.event == PM_EVENT_ON) continue; if (!intf->dev.driver) { /* FIXME maybe force to alt 0 */ @@ -1747,11 +1747,11 @@ static int finish_port_resume(struct usb_device *udev) /* can we do better than just logging errors? */ status = driver->resume(intf); - if (intf->dev.power.power_state != PMSG_ON + if (intf->dev.power.power_state.event != PM_EVENT_ON || status) dev_dbg(&intf->dev, "resume fail, state %d code %d\n", - intf->dev.power.power_state, status); + intf->dev.power.power_state.event, status); } status = 0; @@ -1934,7 +1934,7 @@ static int hub_resume(struct usb_interface *intf) unsigned port1; int status; - if (intf->dev.power.power_state == PM_SUSPEND_ON) + if (intf->dev.power.power_state.event == PM_EVENT_ON) return 0; for (port1 = 1; port1 <= hdev->maxchild; port1++) { diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 99c85d2f92d..2cddd8a0043 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1400,7 +1400,7 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message) driver = to_usb_driver(dev->driver); /* there's only one USB suspend state */ - if (intf->dev.power.power_state) + if (intf->dev.power.power_state.event) return 0; if (driver->suspend) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index b01efb6b36f..65ac9fef3a7 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -641,7 +641,7 @@ show_registers (struct class_device *class_dev, char *buf) spin_lock_irqsave (&ehci->lock, flags); - if (bus->controller->power.power_state) { + if (bus->controller->power.power_state.event) { size = scnprintf (next, size, "bus %s, device %s (driver " DRIVER_VERSION ")\n" "%s\n" diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index c58408c95c3..447f488f5d9 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -631,7 +631,7 @@ show_registers (struct class_device *class_dev, char *buf) hcd->product_desc, hcd_name); - if (bus->controller->power.power_state) { + if (bus->controller->power.power_state.event) { size -= scnprintf (next, size, "SUSPENDED (no register access)\n"); goto done; diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 7a890a65f55..80eaf659c19 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1781,9 +1781,9 @@ sl811h_suspend(struct device *dev, pm_message_t state, u32 phase) if (phase != SUSPEND_POWER_DOWN) return retval; - if (state <= PM_SUSPEND_MEM) + if (state.event == PM_EVENT_FREEZE) retval = sl811h_hub_suspend(hcd); - else + else if (state.event == PM_EVENT_SUSPEND) port_power(sl811, 0); if (retval == 0) dev->power.power_state = state; @@ -1802,7 +1802,7 @@ sl811h_resume(struct device *dev, u32 phase) /* with no "check to see if VBUS is still powered" board hook, * let's assume it'd only be powered to enable remote wakeup. */ - if (dev->power.power_state > PM_SUSPEND_MEM + if (dev->power.power_state.event == PM_EVENT_SUSPEND || !hcd->can_wakeup) { sl811->port1 = 0; port_power(sl811, 1); diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index cda7249a90b..fd7fb98e4b2 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1533,7 +1533,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) if (down_interruptible (&dev->sem)) return -ERESTARTSYS; - if (intf->dev.power.power_state != PMSG_ON) { + if (intf->dev.power.power_state.event != PM_EVENT_ON) { up (&dev->sem); return -EHOSTUNREACH; } diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 7bc1d44d881..b0eba3ac642 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -2323,17 +2323,16 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) * can properly take care of D3 ? Also, with swsusp, we * know we'll be rebooted, ... */ -#ifdef CONFIG_PPC_PMAC +#ifndef CONFIG_PPC_PMAC /* HACK ALERT ! Once I find a proper way to say to each driver * individually what will happen with it's PCI slot, I'll change * that. On laptops, the AGP slot is just unclocked, so D2 is * expected, while on desktops, the card is powered off */ - if (state >= 3) - state = 2; + return 0; #endif /* CONFIG_PPC_PMAC */ - if (state != 2 || state == pdev->dev.power.power_state) + if (state.event == pdev->dev.power.power_state.event) return 0; printk(KERN_DEBUG "aty128fb: suspending...\n"); @@ -2367,7 +2366,7 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) * used dummy fb ops, 2.5 need proper support for this at the * fbdev level */ - if (state == 2) + if (state.event != PM_EVENT_ON) aty128_set_suspend(par, 1); release_console_sem(); @@ -2382,12 +2381,11 @@ static int aty128_do_resume(struct pci_dev *pdev) struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; - if (pdev->dev.power.power_state == 0) + if (pdev->dev.power.power_state.event == PM_EVENT_ON) return 0; /* Wakeup chip */ - if (pdev->dev.power.power_state == 2) - aty128_set_suspend(par, 0); + aty128_set_suspend(par, 0); par->asleep = 0; /* Restore display & engine */ diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 8c42538dc8c..3e10bd837d9 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -2022,17 +2022,16 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) struct fb_info *info = pci_get_drvdata(pdev); struct atyfb_par *par = (struct atyfb_par *) info->par; -#ifdef CONFIG_PPC_PMAC +#ifndef CONFIG_PPC_PMAC /* HACK ALERT ! Once I find a proper way to say to each driver * individually what will happen with it's PCI slot, I'll change * that. On laptops, the AGP slot is just unclocked, so D2 is * expected, while on desktops, the card is powered off */ - if (state >= 3) - state = 2; + return 0; #endif /* CONFIG_PPC_PMAC */ - if (state != 2 || state == pdev->dev.power.power_state) + if (state.event == pdev->dev.power.power_state.event) return 0; acquire_console_sem(); @@ -2071,12 +2070,12 @@ static int atyfb_pci_resume(struct pci_dev *pdev) struct fb_info *info = pci_get_drvdata(pdev); struct atyfb_par *par = (struct atyfb_par *) info->par; - if (pdev->dev.power.power_state == 0) + if (pdev->dev.power.power_state.event == PM_EVENT_ON) return 0; acquire_console_sem(); - if (pdev->dev.power.power_state == 2) + if (pdev->dev.power.power_state.event == 2) aty_power_mgmt(0, par); par->asleep = 0; diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 98352af3932..59a1b6f8506 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2526,18 +2526,18 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) struct radeonfb_info *rinfo = info->par; int i; - if (state == pdev->dev.power.power_state) + if (state.event == pdev->dev.power.power_state.event) return 0; printk(KERN_DEBUG "radeonfb (%s): suspending to state: %d...\n", - pci_name(pdev), state); + pci_name(pdev), state.event); /* For suspend-to-disk, we cheat here. We don't suspend anything and * let fbcon continue drawing until we are all set. That shouldn't * really cause any problem at this point, provided that the wakeup * code knows that any state in memory may not match the HW */ - if (state != PM_SUSPEND_MEM) + if (state.event == PM_EVENT_FREEZE) goto done; acquire_console_sem(); @@ -2616,7 +2616,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev) struct radeonfb_info *rinfo = info->par; int rc = 0; - if (pdev->dev.power.power_state == 0) + if (pdev->dev.power.power_state.event == PM_EVENT_ON) return 0; if (rinfo->no_schedule) { @@ -2626,7 +2626,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev) acquire_console_sem(); printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", - pci_name(pdev), pdev->dev.power.power_state); + pci_name(pdev), pdev->dev.power.power_state.event); if (pci_enable_device(pdev)) { @@ -2637,7 +2637,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev) } pci_set_master(pdev); - if (pdev->dev.power.power_state == PM_SUSPEND_MEM) { + if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { /* Wakeup chip. Check from config space if we were powered off * (todo: additionally, check CLK_PIN_CNTL too) */ diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index e75a965ec76..4131243cfdf 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -462,9 +462,9 @@ static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct fb_info *p = pci_get_drvdata(pdev); - if (state == pdev->dev.power.power_state) + if (state.event == pdev->dev.power.power_state.event) return 0; - if (state != PM_SUSPEND_MEM) + if (state.event != PM_SUSPEND_MEM) goto done; acquire_console_sem(); diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 7513fb9b19c..6db183462b9 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1506,12 +1506,12 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t state) struct i810fb_par *par = (struct i810fb_par *) info->par; int blank = 0, prev_state = par->cur_state; - if (state == prev_state) + if (state.event == prev_state) return 0; - par->cur_state = state; + par->cur_state = state.event; - switch (state) { + switch (state.event) { case 1: blank = VESA_VSYNC_SUSPEND; break; diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c index 3e00ad7f2e3..28d1fe5fe34 100644 --- a/drivers/video/pmag-aa-fb.c +++ b/drivers/video/pmag-aa-fb.c @@ -413,7 +413,7 @@ static struct fb_ops aafb_ops = { static int __init init_one(int slot) { - unsigned long base_addr = get_tc_base_addr(slot); + unsigned long base_addr = CKSEG1ADDR(get_tc_base_addr(slot)); struct aafb_info *ip = &my_fb_info[slot]; memset(ip, 0, sizeof(struct aafb_info)); diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index f8095588e99..c98f1c8d7dc 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -1,57 +1,55 @@ /* - * linux/drivers/video/pmag-ba-fb.c + * linux/drivers/video/pmag-ba-fb.c * - * PMAG-BA TurboChannel framebuffer card support ... derived from: + * PMAG-BA TURBOchannel Color Frame Buffer (CFB) card support, + * derived from: * "HP300 Topcat framebuffer support (derived from macfb of all things) * Phil Blundell <philb@gnu.org> 1998", the original code can be - * found in the file hpfb.c in the same directory. + * found in the file hpfb.c in the same directory. * * Based on digital document: * "PMAG-BA TURBOchannel Color Frame Buffer * Functional Specification", Revision 1.2, August 27, 1990 * - * DECstation related code Copyright (C) 1999, 2000, 2001 by - * Michael Engel <engel@unix-ag.org>, - * Karsten Merker <merker@linuxtag.org> and + * DECstation related code Copyright (C) 1999, 2000, 2001 by + * Michael Engel <engel@unix-ag.org>, + * Karsten Merker <merker@linuxtag.org> and * Harald Koerfgen. - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of this - * archive for more details. + * Copyright (c) 2005 Maciej W. Rozycki * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> + +#include <linux/compiler.h> #include <linux/errno.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/init.h> #include <linux/fb.h> -#include <asm/bootinfo.h> -#include <asm/dec/machtype.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/types.h> + +#include <asm/bug.h> +#include <asm/io.h> +#include <asm/system.h> + #include <asm/dec/tc.h> + #include <video/pmag-ba-fb.h> -struct pmag_ba_ramdac_regs { - unsigned char addr_low; - unsigned char pad0[3]; - unsigned char addr_hi; - unsigned char pad1[3]; - unsigned char data; - unsigned char pad2[3]; - unsigned char cmap; + +struct pmagbafb_par { + struct fb_info *next; + volatile void __iomem *mmio; + volatile u32 __iomem *dac; + int slot; }; -/* - * Max 3 TURBOchannel slots -> max 3 PMAG-BA :) - */ -static struct fb_info pmagba_fb_info[3]; -static struct fb_var_screeninfo pmagbafb_defined = { +static struct fb_info *root_pmagbafb_dev; + +static struct fb_var_screeninfo pmagbafb_defined __initdata = { .xres = 1024, .yres = 864, .xres_virtual = 1024, @@ -61,58 +59,71 @@ static struct fb_var_screeninfo pmagbafb_defined = { .green.length = 8, .blue.length = 8, .activate = FB_ACTIVATE_NOW, - .height = 274, - .width = 195, - .accel = FB_ACCEL_NONE, + .height = -1, + .width = -1, + .accel_flags = FB_ACCEL_NONE, + .pixclock = 14452, + .left_margin = 116, + .right_margin = 12, + .upper_margin = 34, + .lower_margin = 12, + .hsync_len = 128, + .vsync_len = 3, + .sync = FB_SYNC_ON_GREEN, .vmode = FB_VMODE_NONINTERLACED, }; -static struct fb_fix_screeninfo pmagbafb_fix = { +static struct fb_fix_screeninfo pmagbafb_fix __initdata = { .id = "PMAG-BA", - .smem_len = (1024 * 864), + .smem_len = (1024 * 1024), .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_PSEUDOCOLOR, .line_length = 1024, + .mmio_len = PMAG_BA_SIZE - PMAG_BA_BT459, }; -/* - * Turn hardware cursor off - */ -void pmagbafb_erase_cursor(struct pmag_ba_ramdac_regs *bt459_regs) + +static inline void dac_write(struct pmagbafb_par *par, unsigned int reg, u8 v) { - bt459_regs->addr_low = 0; - bt459_regs->addr_hi = 3; - bt459_regs->data = 0; + writeb(v, par->dac + reg / 4); } +static inline u8 dac_read(struct pmagbafb_par *par, unsigned int reg) +{ + return readb(par->dac + reg / 4); +} + + /* - * Set the palette. + * Set the palette. */ -static int pmagbafb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) +static int pmagbafb_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) { - struct pmag_ba_ramdac_regs *bt459_regs = (struct pmag_ba_ramdac_regs *) info->par; + struct pmagbafb_par *par = info->par; - if (regno >= info->cmap.len) - return 1; + BUG_ON(regno >= info->cmap.len); red >>= 8; /* The cmap fields are 16 bits */ - green >>= 8; /* wide, but the harware colormap */ + green >>= 8; /* wide, but the hardware colormap */ blue >>= 8; /* registers are only 8 bits wide */ - bt459_regs->addr_low = (__u8) regno; - bt459_regs->addr_hi = 0; - bt459_regs->cmap = red; - bt459_regs->cmap = green; - bt459_regs->cmap = blue; + mb(); + dac_write(par, BT459_ADDR_LO, regno); + dac_write(par, BT459_ADDR_HI, 0x00); + wmb(); + dac_write(par, BT459_CMAP, red); + wmb(); + dac_write(par, BT459_CMAP, green); + wmb(); + dac_write(par, BT459_CMAP, blue); + return 0; } static struct fb_ops pmagbafb_ops = { .owner = THIS_MODULE, - .fb_get_fix = gen_get_fix, - .fb_get_var = gen_get_var, .fb_setcolreg = pmagbafb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, @@ -120,63 +131,133 @@ static struct fb_ops pmagbafb_ops = { .fb_cursor = soft_cursor, }; -int __init pmagbafb_init_one(int slot) + +/* + * Turn the hardware cursor off. + */ +static void __init pmagbafb_erase_cursor(struct fb_info *info) +{ + struct pmagbafb_par *par = info->par; + + mb(); + dac_write(par, BT459_ADDR_LO, 0x00); + dac_write(par, BT459_ADDR_HI, 0x03); + wmb(); + dac_write(par, BT459_DATA, 0x00); +} + + +static int __init pmagbafb_init_one(int slot) { - unsigned long base_addr = get_tc_base_addr(slot); - struct fb_info *info = &pmagba_fb_info[slot]; - struct display *disp = &pmagba_disp[slot]; - - printk("PMAG-BA framebuffer in slot %d\n", slot); - /* - * Framebuffer display memory base address and friends - */ - pmagbafb_fix.smem_start = base_addr + PMAG_BA_ONBOARD_FBMEM_OFFSET; - info->par = (base_addr + PMAG_BA_BT459_OFFSET); - - /* - * Configure the Bt459 RAM DAC - */ - pmagbafb_erase_cursor((struct pmag_ba_ramdac_regs *) info->par); - - /* - * Let there be consoles.. - */ + struct fb_info *info; + struct pmagbafb_par *par; + unsigned long base_addr; + + info = framebuffer_alloc(sizeof(struct pmagbafb_par), NULL); + if (!info) + return -ENOMEM; + + par = info->par; + par->slot = slot; + claim_tc_card(par->slot); + + base_addr = get_tc_base_addr(par->slot); + + par->next = root_pmagbafb_dev; + root_pmagbafb_dev = info; + + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) + goto err_alloc; + info->fbops = &pmagbafb_ops; + info->fix = pmagbafb_fix; info->var = pmagbafb_defined; - info->fix = pmagbafb_fix; - info->screen_base = pmagbafb_fix.smem_start; info->flags = FBINFO_DEFAULT; - fb_alloc_cmap(&fb_info.cmap, 256, 0); + /* MMIO mapping setup. */ + info->fix.mmio_start = base_addr; + par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); + if (!par->mmio) + goto err_cmap; + par->dac = par->mmio + PMAG_BA_BT459; + + /* Frame buffer mapping setup. */ + info->fix.smem_start = base_addr + PMAG_BA_FBMEM; + info->screen_base = ioremap_nocache(info->fix.smem_start, + info->fix.smem_len); + if (!info->screen_base) + goto err_mmio_map; + info->screen_size = info->fix.smem_len; + + pmagbafb_erase_cursor(info); if (register_framebuffer(info) < 0) - return 1; + goto err_smem_map; + + pr_info("fb%d: %s frame buffer device in slot %d\n", + info->node, info->fix.id, par->slot); + return 0; + + +err_smem_map: + iounmap(info->screen_base); + +err_mmio_map: + iounmap(par->mmio); + +err_cmap: + fb_dealloc_cmap(&info->cmap); + +err_alloc: + root_pmagbafb_dev = par->next; + release_tc_card(par->slot); + framebuffer_release(info); + return -ENXIO; } -/* - * Initialise the framebuffer - */ +static void __exit pmagbafb_exit_one(void) +{ + struct fb_info *info = root_pmagbafb_dev; + struct pmagbafb_par *par = info->par; -int __init pmagbafb_init(void) + unregister_framebuffer(info); + iounmap(info->screen_base); + iounmap(par->mmio); + fb_dealloc_cmap(&info->cmap); + root_pmagbafb_dev = par->next; + release_tc_card(par->slot); + framebuffer_release(info); +} + + +/* + * Initialise the framebuffer. + */ +static int __init pmagbafb_init(void) { - int sid; - int found = 0; + int count = 0; + int slot; if (fb_get_options("pmagbafb", NULL)) - return -ENODEV; - - if (TURBOCHANNEL) { - while ((sid = search_tc_card("PMAG-BA")) >= 0) { - found = 1; - claim_tc_card(sid); - pmagbafb_init_one(sid); - } - return found ? 0 : -ENODEV; - } else { - return -ENODEV; + return -ENXIO; + + while ((slot = search_tc_card("PMAG-BA")) >= 0) { + if (pmagbafb_init_one(slot) < 0) + break; + count++; } + return (count > 0) ? 0 : -ENXIO; } +static void __exit pmagbafb_exit(void) +{ + while (root_pmagbafb_dev) + pmagbafb_exit_one(); +} + + module_init(pmagbafb_init); +module_exit(pmagbafb_exit); + MODULE_LICENSE("GPL"); diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index d14eaee91cf..a483b13e117 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -1,114 +1,128 @@ /* - * linux/drivers/video/pmagb-b-fb.c + * linux/drivers/video/pmagb-b-fb.c * - * PMAGB-B TurboChannel framebuffer card support ... derived from: + * PMAGB-B TURBOchannel Smart Frame Buffer (SFB) card support, + * derived from: * "HP300 Topcat framebuffer support (derived from macfb of all things) * Phil Blundell <philb@gnu.org> 1998", the original code can be - * found in the file hpfb.c in the same directory. + * found in the file hpfb.c in the same directory. * - * DECstation related code Copyright (C) 1999, 2000, 2001 by - * Michael Engel <engel@unix-ag.org>, - * Karsten Merker <merker@linuxtag.org> and + * DECstation related code Copyright (C) 1999, 2000, 2001 by + * Michael Engel <engel@unix-ag.org>, + * Karsten Merker <merker@linuxtag.org> and * Harald Koerfgen. - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of this - * archive for more details. + * Copyright (c) 2005 Maciej W. Rozycki * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. */ -/* - * We currently only support the PMAGB-B in high resolution mode - * as I know of no way to detect low resolution mode set via jumper. - * KM, 2001/01/07 - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/slab.h> +#include <linux/compiler.h> #include <linux/delay.h> -#include <linux/init.h> +#include <linux/errno.h> #include <linux/fb.h> -#include <asm/bootinfo.h> -#include <asm/dec/machtype.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/types.h> + +#include <asm/bug.h> +#include <asm/io.h> +#include <asm/system.h> + #include <asm/dec/tc.h> + #include <video/pmagb-b-fb.h> -struct pmagb_b_ramdac_regs { - unsigned char addr_low; - unsigned char pad0[3]; - unsigned char addr_hi; - unsigned char pad1[3]; - unsigned char data; - unsigned char pad2[3]; - unsigned char cmap; + +struct pmagbbfb_par { + struct fb_info *next; + volatile void __iomem *mmio; + volatile void __iomem *smem; + volatile u32 __iomem *sfb; + volatile u32 __iomem *dac; + unsigned int osc0; + unsigned int osc1; + int slot; }; -/* - * Max 3 TURBOchannel slots -> max 3 PMAGB-B :) - */ -static struct fb_info pmagbb_fb_info[3]; -static struct fb_var_screeninfo pmagbbfb_defined = { - .xres = 1280, - .yres = 1024, - .xres_virtual = 1280, - .yres_virtual = 1024, +static struct fb_info *root_pmagbbfb_dev; + +static struct fb_var_screeninfo pmagbbfb_defined __initdata = { .bits_per_pixel = 8, .red.length = 8, .green.length = 8, .blue.length = 8, .activate = FB_ACTIVATE_NOW, - .height = 274, - .width = 195, + .height = -1, + .width = -1, .accel_flags = FB_ACCEL_NONE, + .sync = FB_SYNC_ON_GREEN, .vmode = FB_VMODE_NONINTERLACED, }; -static struct fb_fix_screeninfo pmagbafb_fix = { +static struct fb_fix_screeninfo pmagbbfb_fix __initdata = { .id = "PMAGB-BA", - .smem_len = (1280 * 1024), + .smem_len = (2048 * 1024), .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_PSEUDOCOLOR, - .line_length = 1280, + .mmio_len = PMAGB_B_FBMEM, +}; + + +static inline void sfb_write(struct pmagbbfb_par *par, unsigned int reg, u32 v) +{ + writel(v, par->sfb + reg / 4); } -/* - * Turn hardware cursor off - */ -void pmagbbfb_erase_cursor(struct pmagb_b_ramdac_regs *bt459_regs) +static inline u32 sfb_read(struct pmagbbfb_par *par, unsigned int reg) +{ + return readl(par->sfb + reg / 4); +} + +static inline void dac_write(struct pmagbbfb_par *par, unsigned int reg, u8 v) { - bt459_regs->addr_low = 0; - bt459_regs->addr_hi = 3; - bt459_regs->data = 0; + writeb(v, par->dac + reg / 4); } +static inline u8 dac_read(struct pmagbbfb_par *par, unsigned int reg) +{ + return readb(par->dac + reg / 4); +} + +static inline void gp0_write(struct pmagbbfb_par *par, u32 v) +{ + writel(v, par->mmio + PMAGB_B_GP0); +} + + /* - * Set the palette. + * Set the palette. */ -static int pmagbbfb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) +static int pmagbbfb_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) { - struct pmagb_b_ramdac_regs *bt459_regs = (struct pmagb_b_ramdac_regs *) info->par; - - if (regno >= info->cmap.len) - return 1; + struct pmagbbfb_par *par = info->par; + + BUG_ON(regno >= info->cmap.len); red >>= 8; /* The cmap fields are 16 bits */ - green >>= 8; /* wide, but the harware colormap */ + green >>= 8; /* wide, but the hardware colormap */ blue >>= 8; /* registers are only 8 bits wide */ - bt459_regs->addr_low = (__u8) regno; - bt459_regs->addr_hi = 0; - bt459_regs->cmap = red; - bt459_regs->cmap = green; - bt459_regs->cmap = blue; + mb(); + dac_write(par, BT459_ADDR_LO, regno); + dac_write(par, BT459_ADDR_HI, 0x00); + wmb(); + dac_write(par, BT459_CMAP, red); + wmb(); + dac_write(par, BT459_CMAP, green); + wmb(); + dac_write(par, BT459_CMAP, blue); + return 0; } @@ -121,62 +135,247 @@ static struct fb_ops pmagbbfb_ops = { .fb_cursor = soft_cursor, }; -int __init pmagbbfb_init_one(int slot) + +/* + * Turn the hardware cursor off. + */ +static void __init pmagbbfb_erase_cursor(struct fb_info *info) +{ + struct pmagbbfb_par *par = info->par; + + mb(); + dac_write(par, BT459_ADDR_LO, 0x00); + dac_write(par, BT459_ADDR_HI, 0x03); + wmb(); + dac_write(par, BT459_DATA, 0x00); +} + +/* + * Set up screen parameters. + */ +static void __init pmagbbfb_screen_setup(struct fb_info *info) +{ + struct pmagbbfb_par *par = info->par; + + info->var.xres = ((sfb_read(par, SFB_REG_VID_HOR) >> + SFB_VID_HOR_PIX_SHIFT) & SFB_VID_HOR_PIX_MASK) * 4; + info->var.xres_virtual = info->var.xres; + info->var.yres = (sfb_read(par, SFB_REG_VID_VER) >> + SFB_VID_VER_SL_SHIFT) & SFB_VID_VER_SL_MASK; + info->var.yres_virtual = info->var.yres; + info->var.left_margin = ((sfb_read(par, SFB_REG_VID_HOR) >> + SFB_VID_HOR_BP_SHIFT) & + SFB_VID_HOR_BP_MASK) * 4; + info->var.right_margin = ((sfb_read(par, SFB_REG_VID_HOR) >> + SFB_VID_HOR_FP_SHIFT) & + SFB_VID_HOR_FP_MASK) * 4; + info->var.upper_margin = (sfb_read(par, SFB_REG_VID_VER) >> + SFB_VID_VER_BP_SHIFT) & SFB_VID_VER_BP_MASK; + info->var.lower_margin = (sfb_read(par, SFB_REG_VID_VER) >> + SFB_VID_VER_FP_SHIFT) & SFB_VID_VER_FP_MASK; + info->var.hsync_len = ((sfb_read(par, SFB_REG_VID_HOR) >> + SFB_VID_HOR_SYN_SHIFT) & + SFB_VID_HOR_SYN_MASK) * 4; + info->var.vsync_len = (sfb_read(par, SFB_REG_VID_VER) >> + SFB_VID_VER_SYN_SHIFT) & SFB_VID_VER_SYN_MASK; + + info->fix.line_length = info->var.xres; +}; + +/* + * Determine oscillator configuration. + */ +static void __init pmagbbfb_osc_setup(struct fb_info *info) { - unsigned long base_addr = get_tc_base_addr(slot); - struct fb_info *info = &pmagbb_fb_info[slot]; - - printk("PMAGB-BA framebuffer in slot %d\n", slot); - /* - * Framebuffer display memory base address and friends - */ - pmagbbfb_fix.smem_start = base_addr + PMAGB_B_ONBOARD_FBMEM_OFFSET; - info->par = (base_addr + PMAGB_B_BT459_OFFSET); - - /* - * Configure the Bt459 RAM DAC - */ - pmagbbfb_erase_cursor((struct pmagb_b_ramdac_regs *) info->par); - - /* - * Let there be consoles.. - */ + static unsigned int pmagbbfb_freqs[] __initdata = { + 130808, 119843, 104000, 92980, 74367, 72800, + 69197, 66000, 65000, 50350, 36000, 32000, 25175 + }; + struct pmagbbfb_par *par = info->par; + u32 count0 = 8, count1 = 8, counttc = 16 * 256 + 8; + u32 freq0, freq1, freqtc = get_tc_speed() / 250; + int i, j; + + gp0_write(par, 0); /* select Osc0 */ + for (j = 0; j < 16; j++) { + mb(); + sfb_write(par, SFB_REG_TCCLK_COUNT, 0); + mb(); + for (i = 0; i < 100; i++) { /* nominally max. 20.5us */ + if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0) + break; + udelay(1); + } + count0 += sfb_read(par, SFB_REG_VIDCLK_COUNT); + } + + gp0_write(par, 1); /* select Osc1 */ + for (j = 0; j < 16; j++) { + mb(); + sfb_write(par, SFB_REG_TCCLK_COUNT, 0); + + for (i = 0; i < 100; i++) { /* nominally max. 20.5us */ + if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0) + break; + udelay(1); + } + count1 += sfb_read(par, SFB_REG_VIDCLK_COUNT); + } + + freq0 = (freqtc * count0 + counttc / 2) / counttc; + par->osc0 = freq0; + if (freq0 >= pmagbbfb_freqs[0] - (pmagbbfb_freqs[0] + 32) / 64 && + freq0 <= pmagbbfb_freqs[0] + (pmagbbfb_freqs[0] + 32) / 64) + par->osc0 = pmagbbfb_freqs[0]; + + freq1 = (par->osc0 * count1 + count0 / 2) / count0; + par->osc1 = freq1; + for (i = 0; i < sizeof(pmagbbfb_freqs) / sizeof(*pmagbbfb_freqs); i++) + if (freq1 >= pmagbbfb_freqs[i] - + (pmagbbfb_freqs[i] + 128) / 256 && + freq1 <= pmagbbfb_freqs[i] + + (pmagbbfb_freqs[i] + 128) / 256) { + par->osc1 = pmagbbfb_freqs[i]; + break; + } + + if (par->osc0 - par->osc1 <= (par->osc0 + par->osc1 + 256) / 512 || + par->osc1 - par->osc0 <= (par->osc0 + par->osc1 + 256) / 512) + par->osc1 = 0; + + gp0_write(par, par->osc1 != 0); /* reselect OscX */ + + info->var.pixclock = par->osc1 ? + (1000000000 + par->osc1 / 2) / par->osc1 : + (1000000000 + par->osc0 / 2) / par->osc0; +}; + + +static int __init pmagbbfb_init_one(int slot) +{ + char freq0[12], freq1[12]; + struct fb_info *info; + struct pmagbbfb_par *par; + unsigned long base_addr; + u32 vid_base; + + info = framebuffer_alloc(sizeof(struct pmagbbfb_par), NULL); + if (!info) + return -ENOMEM; + + par = info->par; + par->slot = slot; + claim_tc_card(par->slot); + + base_addr = get_tc_base_addr(par->slot); + + par->next = root_pmagbbfb_dev; + root_pmagbbfb_dev = info; + + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) + goto err_alloc; + info->fbops = &pmagbbfb_ops; - info->var = pmagbbfb_defined; info->fix = pmagbbfb_fix; - info->screen_base = pmagbbfb_fix.smem_start; + info->var = pmagbbfb_defined; info->flags = FBINFO_DEFAULT; - fb_alloc_cmap(&fb_info.cmap, 256, 0); + /* MMIO mapping setup. */ + info->fix.mmio_start = base_addr; + par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); + if (!par->mmio) + goto err_cmap; + par->sfb = par->mmio + PMAGB_B_SFB; + par->dac = par->mmio + PMAGB_B_BT459; + + /* Frame buffer mapping setup. */ + info->fix.smem_start = base_addr + PMAGB_B_FBMEM; + par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len); + if (!par->smem) + goto err_mmio_map; + vid_base = sfb_read(par, SFB_REG_VID_BASE); + info->screen_base = (void __iomem *)par->smem + vid_base * 0x1000; + info->screen_size = info->fix.smem_len - 2 * vid_base * 0x1000; + + pmagbbfb_erase_cursor(info); + pmagbbfb_screen_setup(info); + pmagbbfb_osc_setup(info); if (register_framebuffer(info) < 0) - return 1; + goto err_smem_map; + + snprintf(freq0, sizeof(freq0), "%u.%03uMHz", + par->osc0 / 1000, par->osc0 % 1000); + snprintf(freq1, sizeof(freq1), "%u.%03uMHz", + par->osc1 / 1000, par->osc1 % 1000); + + pr_info("fb%d: %s frame buffer device in slot %d\n", + info->node, info->fix.id, par->slot); + pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n", + info->node, freq0, par->osc1 ? freq1 : "disabled", + par->osc1 != 0); + return 0; + + +err_smem_map: + iounmap(par->smem); + +err_mmio_map: + iounmap(par->mmio); + +err_cmap: + fb_dealloc_cmap(&info->cmap); + +err_alloc: + root_pmagbbfb_dev = par->next; + release_tc_card(par->slot); + framebuffer_release(info); + return -ENXIO; } -/* - * Initialise the framebuffer - */ +static void __exit pmagbbfb_exit_one(void) +{ + struct fb_info *info = root_pmagbbfb_dev; + struct pmagbbfb_par *par = info->par; + + unregister_framebuffer(info); + iounmap(par->smem); + iounmap(par->mmio); + fb_dealloc_cmap(&info->cmap); + root_pmagbbfb_dev = par->next; + release_tc_card(par->slot); + framebuffer_release(info); +} -int __init pmagbbfb_init(void) + +/* + * Initialise the framebuffer. + */ +static int __init pmagbbfb_init(void) { - int sid; - int found = 0; + int count = 0; + int slot; if (fb_get_options("pmagbbfb", NULL)) - return -ENODEV; + return -ENXIO; - if (TURBOCHANNEL) { - while ((sid = search_tc_card("PMAGB-BA")) >= 0) { - found = 1; - claim_tc_card(sid); - pmagbbfb_init_one(sid); - } - return found ? 0 : -ENODEV; - } else { - return -ENODEV; + while ((slot = search_tc_card("PMAGB-BA")) >= 0) { + if (pmagbbfb_init_one(slot) < 0) + break; + count++; } + return (count > 0) ? 0 : -ENXIO; +} + +static void __exit pmagbbfb_exit(void) +{ + while (root_pmagbbfb_dev) + pmagbbfb_exit_one(); } + module_init(pmagbbfb_init); +module_exit(pmagbbfb_exit); + MODULE_LICENSE("GPL"); diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index 3848be2b9d2..fa98d91c42e 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -655,7 +655,7 @@ bail: } #ifdef CONFIG_PM -static int s1d13xxxfb_suspend(struct device *dev, u32 state, u32 level) +static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state, u32 level) { struct fb_info *info = dev_get_drvdata(dev); struct s1d13xxxfb_par *s1dfb = info->par; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index f4633d1891f..117ad42f120 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -2110,7 +2110,6 @@ static int savagefb_suspend (struct pci_dev* dev, pm_message_t state) struct savagefb_par *par = (struct savagefb_par *)info->par; DBG("savagefb_suspend"); - printk(KERN_DEBUG "state: %u\n", state); acquire_console_sem(); fb_set_suspend(info, pci_choose_state(dev, state)); |