From a9bd53bc49ee8984633e57c1d9d45111c58e9457 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 28 Jul 2005 14:42:00 -0400 Subject: [ACPI] HPET driver now checks for acpi_register_gsi() errors Signed-off-by: Kenji Kaneshige Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/char/hpet.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 5ec732e..a8d4c47 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -906,11 +906,15 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) if (irqp->number_of_interrupts > 0) { hdp->hd_nirqs = irqp->number_of_interrupts; - for (i = 0; i < hdp->hd_nirqs; i++) - hdp->hd_irq[i] = + for (i = 0; i < hdp->hd_nirqs; i++) { + int rc = acpi_register_gsi(irqp->interrupts[i], irqp->edge_level, irqp->active_high_low); + if (rc < 0) + return AE_ERROR; + hdp->hd_irq[i] = rc; + } } } -- cgit v1.1 From 46acac3b4fd8ef66eec63b51de8d556a17c7d4f7 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 11 Aug 2005 20:28:56 -0700 Subject: [AGPGART] Drop duplicate setting of info->mode in agp_copy_info() Spotted by Jeremy Fitzhardinge, this change crept in with the multiple backend support. It's clearly incorrect to overwrite info->mode after we just went to lengths to determine which bits to mask out. Signed-off-by: Dave Jones --- drivers/char/agp/generic.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index f0079e9..eb05242 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -319,7 +319,6 @@ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info) info->mode = bridge->mode & ~AGP3_RESERVED_MASK; else info->mode = bridge->mode & ~AGP2_RESERVED_MASK; - info->mode = bridge->mode; info->aper_base = bridge->gart_bus_addr; info->aper_size = agp_return_size(); info->max_memory = bridge->max_memory_agp; -- cgit v1.1 From 8c8b83854ea973ee7f37db6612d10d3acc5531d9 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 17 Aug 2005 23:08:11 -0700 Subject: Fix up various printk levels and whitespace corrections. Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- drivers/char/agp/generic.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index eb05242..ac9da0c 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -355,7 +355,7 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start) return -EINVAL; if (curr->is_bound == TRUE) { - printk (KERN_INFO PFX "memory %p is already bound!\n", curr); + printk(KERN_INFO PFX "memory %p is already bound!\n", curr); return -EINVAL; } if (curr->is_flushed == FALSE) { @@ -390,7 +390,7 @@ int agp_unbind_memory(struct agp_memory *curr) return -EINVAL; if (curr->is_bound != TRUE) { - printk (KERN_INFO PFX "memory %p was not bound!\n", curr); + printk(KERN_INFO PFX "memory %p was not bound!\n", curr); return -EINVAL; } @@ -414,7 +414,7 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ u32 tmp; if (*requested_mode & AGP2_RESERVED_MASK) { - printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode); + printk(KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode); *requested_mode &= ~AGP2_RESERVED_MASK; } @@ -422,7 +422,7 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ tmp = *requested_mode & 7; switch (tmp) { case 0: - printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm); + printk(KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm); *requested_mode |= AGPSTAT2_1X; break; case 1: @@ -492,18 +492,18 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ u32 tmp; if (*requested_mode & AGP3_RESERVED_MASK) { - printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode); + printk(KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode); *requested_mode &= ~AGP3_RESERVED_MASK; } /* Check the speed bits make sense. */ tmp = *requested_mode & 7; if (tmp == 0) { - printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm); + printk(KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm); *requested_mode |= AGPSTAT3_4X; } if (tmp >= 3) { - printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4); + printk(KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4); *requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X; } @@ -532,7 +532,7 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ * AGP2.x 4x -> AGP3.0 4x. */ if (*requested_mode & AGPSTAT2_4X) { - printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n", + printk(KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n", current->comm, *requested_mode); *requested_mode &= ~AGPSTAT2_4X; *requested_mode |= AGPSTAT3_4X; @@ -543,7 +543,7 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ * but have been passed an AGP 2.x mode. * Convert AGP 1x,2x,4x -> AGP 3.0 4x. */ - printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n", + printk(KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n", current->comm, *requested_mode); *requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X); *requested_mode |= AGPSTAT3_4X; @@ -553,13 +553,13 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ if (!(*bridge_agpstat & AGPSTAT3_8X)) { *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); *bridge_agpstat |= AGPSTAT3_4X; - printk ("%s requested AGPx8 but bridge not capable.\n", current->comm); + printk(KERN_INFO PFX "%s requested AGPx8 but bridge not capable.\n", current->comm); return; } if (!(*vga_agpstat & AGPSTAT3_8X)) { *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); *bridge_agpstat |= AGPSTAT3_4X; - printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm); + printk(KERN_INFO PFX "%s requested AGPx8 but graphic card not capable.\n", current->comm); return; } /* All set, bridge & device can do AGP x8*/ @@ -577,13 +577,13 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X)) *bridge_agpstat |= AGPSTAT3_4X; else { - printk (KERN_INFO PFX "Badness. Don't know which AGP mode to set. " + printk(KERN_INFO PFX "Badness. Don't know which AGP mode to set. " "[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n", origbridge, origvga, *bridge_agpstat, *vga_agpstat); if (!(*bridge_agpstat & AGPSTAT3_4X)) - printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n"); + printk(KERN_INFO PFX "Bridge couldn't do AGP x4.\n"); if (!(*vga_agpstat & AGPSTAT3_4X)) - printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n"); + printk(KERN_INFO PFX "Graphic card couldn't do AGP x4.\n"); return; } } @@ -621,7 +621,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode for (;;) { device = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, device); if (!device) { - printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n"); + printk(KERN_INFO PFX "Couldn't find an AGP VGA controller.\n"); return 0; } cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); @@ -733,7 +733,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode) pci_write_config_dword(bridge->dev, bridge->capndx+AGPCTRL, temp); - printk (KERN_INFO PFX "Device is in legacy mode," + printk(KERN_INFO PFX "Device is in legacy mode," " falling back to 2.x\n"); } } -- cgit v1.1 From 8466361ad5233d4356a4601e16b66c25277920d1 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 24 Aug 2005 12:09:07 -0400 Subject: [ACPI] delete CONFIG_ACPI_INTERPRETER it is a synonym for CONFIG_ACPI Signed-off-by: Len Brown --- drivers/char/ipmi/ipmi_si_intf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index a44b973..c51b02d 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -986,7 +986,7 @@ MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for" #define IPMI_MEM_ADDR_SPACE 1 #define IPMI_IO_ADDR_SPACE 2 -#if defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_X86) || defined(CONFIG_PCI) +#if defined(CONFIG_ACPI) || defined(CONFIG_X86) || defined(CONFIG_PCI) static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr) { int i; @@ -1362,7 +1362,7 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) } -#ifdef CONFIG_ACPI_INTERPRETER +#ifdef CONFIG_ACPI #include @@ -2067,7 +2067,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) rv = try_init_mem(intf_num, &new_smi); if (rv) rv = try_init_port(intf_num, &new_smi); -#ifdef CONFIG_ACPI_INTERPRETER +#ifdef CONFIG_ACPI if ((rv) && (si_trydefaults)) { rv = try_init_acpi(intf_num, &new_smi); } -- cgit v1.1 From 76f58584824c61eb5b3bdbf019236815921d2e7c Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 24 Aug 2005 12:10:49 -0400 Subject: [ACPI] delete CONFIG_ACPI_BUS it is a synonym for CONFIG_ACPI Signed-off-by: Len Brown --- drivers/char/tpm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 79e9832..b58adfe 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -17,7 +17,7 @@ config TCG_TPM obtained at: . To compile this driver as a module, choose M here; the module will be called tpm. If unsure, say N. - Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI_BUS + Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI and CONFIG_PNPACPI. config TCG_NSC -- cgit v1.1 From 4fbd1514173a80f9dc93e8ebbd6d4eb97cee123e Mon Sep 17 00:00:00 2001 From: Yann Droneaud Date: Tue, 7 Jun 2005 16:54:01 +0200 Subject: [ACPI] check acpi_disabled in IPMI Signed-off-by: Yann Droneaud Signed-off-by: Len Brown --- drivers/char/ipmi/ipmi_si_intf.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index c51b02d..adbec73 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1484,6 +1484,9 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) char *io_type; u8 addr_space; + if (acpi_disabled) + return -ENODEV; + if (acpi_failure) return -ENODEV; -- cgit v1.1 From 29db35edb2548c3b0299c53d62d5f26d77a8e58f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 1 Sep 2005 10:50:13 -0700 Subject: [AGPGART] Remove trailing space before \n From: Denis Vlasenko Signed-off-by: Dave Jones --- drivers/char/agp/amd64-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 59f589d..0a7624a 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -429,7 +429,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) struct pci_dev *dev1; int i; unsigned size = amd64_fetch_size(); - printk(KERN_INFO "Setting up ULi AGP. \n"); + printk(KERN_INFO "Setting up ULi AGP.\n"); dev1 = pci_find_slot ((unsigned int)pdev->bus->number,PCI_DEVFN(0,0)); if (dev1 == NULL) { printk(KERN_INFO PFX "Detected a ULi chipset, " -- cgit v1.1 From ebede60741e2cec6d210f137fd22a30e37abc0be Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 2 Sep 2005 12:20:18 -0700 Subject: [SPARC32]: More dependencies fallout More stuff that got exposed to sparc32 build due to inclusion of drivers/char/Kconfig in arch/sparc/Kconfig needs to be excluded. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/char/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 7333b41..d6adc26 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. -- cgit v1.1 From be3df0f94d77ba3cff40c14c3e21a753c40ba6f2 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 17 Aug 2005 01:49:24 +0200 Subject: [WATCHDOG] Makefile-probe_order-patch Re-arrange Makefile according to what we want to probe first. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Makefile | 69 ++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 23 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index c183883..d9b0ed5 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -2,42 +2,65 @@ # Makefile for the WatchDog device drivers. # +# Only one watchdog can succeed. We probe the ISA/PCI/USB based +# watchdog-cards first, then the architecture specific watchdog +# drivers and then the architecture independant "softdog" driver. +# This means that if your ISA/PCI/USB card isn't detected that +# you can fall back to an architecture specific driver and if +# that also fails then you can fall back to the software watchdog +# to give you some cover. + +# ISA-based Watchdog Cards obj-$(CONFIG_PCWATCHDOG) += pcwd.o -obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o -obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o -obj-$(CONFIG_IB700_WDT) += ib700wdt.o obj-$(CONFIG_MIXCOMWD) += mixcomwd.o -obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o -obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o obj-$(CONFIG_WDT) += wdt.o + +# PCI-based Watchdog Cards +obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o obj-$(CONFIG_WDTPCI) += wdt_pci.o + +# USB-based Watchdog Cards +obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o + +# ARM Architecture obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o -obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o -obj-$(CONFIG_MACHZ_WDT) += machzwd.o -obj-$(CONFIG_SH_WDT) += shwdt.o +obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o +obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o -obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o -obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o -obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o -obj-$(CONFIG_SC520_WDT) += sc520_wdt.o -obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o + +# X86 (i386 + ia64 + x86_64) Architecture +obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o +obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o -obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o +obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o +obj-$(CONFIG_SC520_WDT) += sc520_wdt.o +obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o +obj-$(CONFIG_IB700_WDT) += ib700wdt.o obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o +obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o +obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o +obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o +obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o -obj-$(CONFIG_INDYDOG) += indydog.o -obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o -obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o -obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o -obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o +obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o +obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o +obj-$(CONFIG_MACHZ_WDT) += machzwd.o + +# PowerPC Architecture obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o -# Only one watchdog can succeed. We probe the hardware watchdog -# drivers first, then the softdog driver. This means if your hardware -# watchdog dies or is 'borrowed' for some reason the software watchdog -# still gives you some cover. +# MIPS Architecture +obj-$(CONFIG_INDYDOG) += indydog.o + +# S390 Architecture + +# SUPERH Architecture +obj-$(CONFIG_SH_WDT) += shwdt.o + +# SPARC64 Architecture +# Architecture Independant obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o -- cgit v1.1 From 09c8a9a0c0fe5b3182b6ecfa556fa77a55892c93 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 3 Sep 2005 13:46:56 +0200 Subject: [WATCHDOG] Kconfig+Makefile-clean Clean the Kconfig+Makefile according to a sorted list of the drivers of each architecture (and sub-architecture). Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 43 +++++++++++++++++++++--------------------- drivers/char/watchdog/Makefile | 4 +++- 2 files changed, 25 insertions(+), 22 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index b53e2e2..f4bf6c3 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -84,6 +84,17 @@ config 977_WATCHDOG Not sure? It's safe to say N. +config IXP2000_WATCHDOG + tristate "IXP2000 Watchdog" + depends on WATCHDOG && ARCH_IXP2000 + help + Say Y here if to include support for the watchdog timer + in the Intel IXP2000(2400, 2800, 2850) network processors. + This driver can be built as a module by choosing M. The module + will be called ixp2000_wdt. + + Say N if you are unsure. + config IXP4XX_WATCHDOG tristate "IXP4xx Watchdog" depends on WATCHDOG && ARCH_IXP4XX @@ -100,17 +111,6 @@ config IXP4XX_WATCHDOG Say N if you are unsure. -config IXP2000_WATCHDOG - tristate "IXP2000 Watchdog" - depends on WATCHDOG && ARCH_IXP2000 - help - Say Y here if to include support for the watchdog timer - in the Intel IXP2000(2400, 2800, 2850) network processors. - This driver can be built as a module by choosing M. The module - will be called ixp2000_wdt. - - Say N if you are unsure. - config S3C2410_WATCHDOG tristate "S3C2410 Watchdog" depends on WATCHDOG && ARCH_S3C2410 @@ -346,6 +346,17 @@ config 8xx_WDT tristate "MPC8xx Watchdog Timer" depends on WATCHDOG && 8xx +# PPC64 Architecture + +config WATCHDOG_RTAS + tristate "RTAS watchdog" + depends on WATCHDOG && PPC_RTAS + help + This driver adds watchdog support for the RTAS watchdog. + + To compile this driver as a module, choose M here. The module + will be called wdrtas. + # MIPS Architecture config INDYDOG @@ -414,16 +425,6 @@ config WATCHDOG_RIO machines. The watchdog timeout period is normally one minute but can be changed with a boot-time parameter. -# ppc64 RTAS watchdog -config WATCHDOG_RTAS - tristate "RTAS watchdog" - depends on WATCHDOG && PPC_RTAS - help - This driver adds watchdog support for the RTAS watchdog. - - To compile this driver as a module, choose M here. The module - will be called wdrtas. - # # ISA-based Watchdog Cards # diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index d9b0ed5..6f02f4c 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -25,8 +25,8 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o # ARM Architecture obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o -obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o +obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o @@ -50,6 +50,8 @@ obj-$(CONFIG_MACHZ_WDT) += machzwd.o # PowerPC Architecture obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o + +# PPC64 Architecture obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o # MIPS Architecture -- cgit v1.1 From 2dab3cabc4b3c1ef53965233dc8a05e0ddeeb38e Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Wed, 17 Aug 2005 08:58:34 +0200 Subject: [WATCHDOG] correct sysfs name for watchdog devices While looking for possible candidates for our udev.rules package, I found a few odd ->name properties. /dev/watchdog has minor 130 according to devices.txt. Since all watchdog drivers use the misc_register() call, they will end up in /sys/class/misc/$foo. udev may create the /dev/watchdog node if the driver is loaded. I dont have such a device, so I cant test it. The drivers below provide names with spaces and even with / in it. Not a big deal, but apps may expect /dev/watchdog. Signed-off-by: Olaf Hering Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/ixp2000_wdt.c | 2 +- drivers/char/watchdog/ixp4xx_wdt.c | 2 +- drivers/char/watchdog/scx200_wdt.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c index e7640bc..0cfb9b9 100644 --- a/drivers/char/watchdog/ixp2000_wdt.c +++ b/drivers/char/watchdog/ixp2000_wdt.c @@ -182,7 +182,7 @@ static struct file_operations ixp2000_wdt_fops = static struct miscdevice ixp2000_wdt_miscdev = { .minor = WATCHDOG_MINOR, - .name = "IXP2000 Watchdog", + .name = "watchdog", .fops = &ixp2000_wdt_fops, }; diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c index 8d916af..b5be8b1 100644 --- a/drivers/char/watchdog/ixp4xx_wdt.c +++ b/drivers/char/watchdog/ixp4xx_wdt.c @@ -176,7 +176,7 @@ static struct file_operations ixp4xx_wdt_fops = static struct miscdevice ixp4xx_wdt_miscdev = { .minor = WATCHDOG_MINOR, - .name = "IXP4xx Watchdog", + .name = "watchdog", .fops = &ixp4xx_wdt_fops, }; diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c index c456856..b4a102a 100644 --- a/drivers/char/watchdog/scx200_wdt.c +++ b/drivers/char/watchdog/scx200_wdt.c @@ -206,7 +206,7 @@ static struct file_operations scx200_wdt_fops = { static struct miscdevice scx200_wdt_miscdev = { .minor = WATCHDOG_MINOR, - .name = NAME, + .name = "watchdog", .fops = &scx200_wdt_fops, }; -- cgit v1.1 From af4bb822bc65efb087cd36b83789f22161a6515b Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 17 Aug 2005 09:03:23 +0200 Subject: [WATCHDOG] s3c2410 watchdog power management Patch from Dimitry Andric , updated by Ben Dooks . Patch is against 2.6.11-mm2 Add power management support to the s3c2410 watchdog, so that it is shut-down over suspend, and re-initialised on resume. Also add Dimitry to the list of authors. Signed-off-by: Dimitry Andric Signed-off-by: Ben Dooks Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/s3c2410_wdt.c | 51 ++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index f85ac89..52243578 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c @@ -27,7 +27,9 @@ * Fixed tmr_count / wdt_count confusion * Added configurable debug * - * 11-Jan-2004 BJD Fixed divide-by-2 in timeout code + * 11-Jan-2005 BJD Fixed divide-by-2 in timeout code + * + * 25-Jan-2005 DA Added suspend/resume support * * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA */ @@ -479,15 +481,57 @@ static int s3c2410wdt_remove(struct device *dev) return 0; } +#ifdef CONFIG_PM + +static unsigned long wtcon_save; +static unsigned long wtdat_save; + +static int s3c2410wdt_suspend(struct device *dev, u32 state, u32 level) +{ + if (level == SUSPEND_POWER_DOWN) { + /* Save watchdog state, and turn it off. */ + wtcon_save = readl(wdt_base + S3C2410_WTCON); + wtdat_save = readl(wdt_base + S3C2410_WTDAT); + + /* Note that WTCNT doesn't need to be saved. */ + s3c2410wdt_stop(); + } + + return 0; +} + +static int s3c2410wdt_resume(struct device *dev, u32 level) +{ + if (level == RESUME_POWER_ON) { + /* Restore watchdog state. */ + + writel(wtdat_save, wdt_base + S3C2410_WTDAT); + writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */ + writel(wtcon_save, wdt_base + S3C2410_WTCON); + + printk(KERN_INFO PFX "watchdog %sabled\n", + (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis"); + } + + return 0; +} + +#else +#define s3c2410wdt_suspend NULL +#define s3c2410wdt_resume NULL +#endif /* CONFIG_PM */ + + static struct device_driver s3c2410wdt_driver = { .name = "s3c2410-wdt", .bus = &platform_bus_type, .probe = s3c2410wdt_probe, .remove = s3c2410wdt_remove, + .suspend = s3c2410wdt_suspend, + .resume = s3c2410wdt_resume, }; - static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; static int __init watchdog_init(void) @@ -505,7 +549,8 @@ static void __exit watchdog_exit(void) module_init(watchdog_init); module_exit(watchdog_exit); -MODULE_AUTHOR("Ben Dooks "); +MODULE_AUTHOR("Ben Dooks , " + "Dimitry Andric "); MODULE_DESCRIPTION("S3C2410 Watchdog Device Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.1 From 94f1e9f316b10972b77a64344006c3bf8a4929b4 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 17 Aug 2005 09:04:52 +0200 Subject: [WATCHDOG] s3c2410 watchdog - replace reboot notifier Patch from Dimitry Andric Change to using platfrom driver's .shutdown method instead of an reboot notifier Signed-off-by: Dimitry Andric Signed-off-by: Ben Dooks Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/s3c2410_wdt.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index 52243578..8b292bf 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c @@ -30,6 +30,7 @@ * 11-Jan-2005 BJD Fixed divide-by-2 in timeout code * * 25-Jan-2005 DA Added suspend/resume support + * Replaced reboot notifier with .shutdown method * * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA */ @@ -42,8 +43,6 @@ #include #include #include -#include -#include #include #include #include @@ -319,20 +318,6 @@ static int s3c2410wdt_ioctl(struct inode *inode, struct file *file, } } -/* - * Notifier for system down - */ - -static int s3c2410wdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if(code==SYS_DOWN || code==SYS_HALT) { - /* Turn the WDT off */ - s3c2410wdt_stop(); - } - return NOTIFY_DONE; -} - /* kernel interface */ static struct file_operations s3c2410wdt_fops = { @@ -350,10 +335,6 @@ static struct miscdevice s3c2410wdt_miscdev = { .fops = &s3c2410wdt_fops, }; -static struct notifier_block s3c2410wdt_notifier = { - .notifier_call = s3c2410wdt_notify_sys, -}; - /* interrupt handler code */ static irqreturn_t s3c2410wdt_irq(int irqno, void *param, @@ -434,18 +415,10 @@ static int s3c2410wdt_probe(struct device *dev) } } - ret = register_reboot_notifier(&s3c2410wdt_notifier); - if (ret) { - printk (KERN_ERR PFX "cannot register reboot notifier (%d)\n", - ret); - return ret; - } - ret = misc_register(&s3c2410wdt_miscdev); if (ret) { printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", WATCHDOG_MINOR, ret); - unregister_reboot_notifier(&s3c2410wdt_notifier); return ret; } @@ -481,6 +454,11 @@ static int s3c2410wdt_remove(struct device *dev) return 0; } +static void s3c2410wdt_shutdown(struct device *dev) +{ + s3c2410wdt_stop(); +} + #ifdef CONFIG_PM static unsigned long wtcon_save; @@ -527,6 +505,7 @@ static struct device_driver s3c2410wdt_driver = { .bus = &platform_bus_type, .probe = s3c2410wdt_probe, .remove = s3c2410wdt_remove, + .shutdown = s3c2410wdt_shutdown, .suspend = s3c2410wdt_suspend, .resume = s3c2410wdt_resume, }; @@ -543,7 +522,6 @@ static int __init watchdog_init(void) static void __exit watchdog_exit(void) { driver_unregister(&s3c2410wdt_driver); - unregister_reboot_notifier(&s3c2410wdt_notifier); } module_init(watchdog_init); -- cgit v1.1 From 93642ecd463df30d032da8ac37c2676cee4ad876 Mon Sep 17 00:00:00 2001 From: "P@Draig Brady" Date: Wed, 17 Aug 2005 09:06:07 +0200 Subject: [WATCHDOG] w83627hf_wdt.c-initialized_bios_bug Attached is a small update to the w83627hf watchdog driver to initialise appropriately if it was already initialised in the BIOS. On tyan motherboards for e.g. you can init the watchdog to 4 mins, then when the driver is loaded it sets the watchdog to "seconds" mode, and then machine will reboot within 4 seconds. So this patch resets the timeout to the configured value if the watchdog is already running. Signed-off-by: P@draig Brady Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83627hf_wdt.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c index 465e0fd..b5d8210 100644 --- a/drivers/char/watchdog/w83627hf_wdt.c +++ b/drivers/char/watchdog/w83627hf_wdt.c @@ -93,6 +93,12 @@ w83627hf_init(void) w83627hf_select_wd_register(); + outb_p(0xF6, WDT_EFER); /* Select CRF6 */ + t=inb_p(WDT_EFDR); /* read CRF6 */ + if (t != 0) { + printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); + outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ + } outb_p(0xF5, WDT_EFER); /* Select CRF5 */ t=inb_p(WDT_EFDR); /* read CRF5 */ t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ -- cgit v1.1 From 1cc77248106aafc12ba529953f652d6f8db2c84d Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Fri, 19 Aug 2005 14:14:07 +0200 Subject: [WATCHDOG] softdog-timer-running-oops.patch The softdog watchdog timer has a bug that can create an oops: 1. Load the module without the nowayout option. 2. Open the driver and close it without writing 'V' before close. 3. Unload the module. The timer will continue to run... 4. Oops happens when timer fires. Reported Sun, 10 Oct 2004, by Michael Schierl Fix is easy: always take a reference on the module on open. Release it only when the device is closed and no timer is running. Tested on 2.6.13-rc6 using the soft_noboot option. While the timer is running and the device is closed, the module use count stays at 1. After the timer fires, it drops to 0. Repeatedly opening and closing the driver caused no problems. Please apply. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/softdog.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c index 4d7ed93..20e5eb8 100644 --- a/drivers/char/watchdog/softdog.c +++ b/drivers/char/watchdog/softdog.c @@ -77,7 +77,7 @@ static void watchdog_fire(unsigned long); static struct timer_list watchdog_ticktock = TIMER_INITIALIZER(watchdog_fire, 0, 0); -static unsigned long timer_alive; +static unsigned long driver_open, orphan_timer; static char expect_close; @@ -87,6 +87,9 @@ static char expect_close; static void watchdog_fire(unsigned long data) { + if (test_and_clear_bit(0, &orphan_timer)) + module_put(THIS_MODULE); + if (soft_noboot) printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); else @@ -128,9 +131,9 @@ static int softdog_set_heartbeat(int t) static int softdog_open(struct inode *inode, struct file *file) { - if(test_and_set_bit(0, &timer_alive)) + if (test_and_set_bit(0, &driver_open)) return -EBUSY; - if (nowayout) + if (!test_and_clear_bit(0, &orphan_timer)) __module_get(THIS_MODULE); /* * Activate timer @@ -147,11 +150,13 @@ static int softdog_release(struct inode *inode, struct file *file) */ if (expect_close == 42) { softdog_stop(); + module_put(THIS_MODULE); } else { printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + set_bit(0, &orphan_timer); softdog_keepalive(); } - clear_bit(0, &timer_alive); + clear_bit(0, &driver_open); expect_close = 0; return 0; } -- cgit v1.1 From 9b4e3b13b147e9b737de63188a9ae740eaa8c36d Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sat, 3 Sep 2005 16:26:49 +0100 Subject: [SERIAL] Fix moxa tty driver name The moxa driver was named "ttya", which is wrong: 1) Documentation/devices.txt says that the name should be "ttyMX". 2) First 10 ports (ttya0...ttya9) clash with the legacy pty driver. This patch changes the driver name to "ttyMX". http://bugme.osdl.org/show_bug.cgi?id=5012 Signed-off-by: Sergey Vlasov Signed-off-by: Russell King --- drivers/char/moxa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 95f7046..79e490e 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; -- cgit v1.1 From e8a650150b1001bc34d506e4c44538463d368890 Mon Sep 17 00:00:00 2001 From: Marcel Selhorst Date: Sat, 3 Sep 2005 15:54:20 -0700 Subject: [PATCH] tpm_infineon: Bugfix in PNPACPI-handling This patch corrects the PNP-handling inside the tpm-driver and some minor coding style bugs. Note: the pci-device and pnp-device mixture is currently necessary, since the used "tpm"-interface requires a pci-dev in order to register the driver. This will be fixed within the next iterations. Signed-off-by: Marcel Selhorst Cc: Kylene Hall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tpm/tpm_infineon.c | 76 ++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 31 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index dc8c540..939e51e 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -14,7 +14,6 @@ * License. */ -#include #include #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); } -- cgit v1.1 From a2f40ccd294d14e5aca464c1913e8e0d8de35fca Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 3 Sep 2005 15:55:33 -0700 Subject: [PATCH] ppc32: Added support for the Book-E style Watchdog Timer PowerPC 40x and Book-E processors support a watchdog timer at the processor core level. The timer has implementation dependent timeout frequencies that can be configured by software. One the first Watchdog timeout we get a critical exception. It is left to board specific code to determine what should happen at this point. If nothing is done and another timeout period expires the processor may attempt to reset the machine. Command line parameters: wdt=0 : disable watchdog (default) wdt=1 : enable watchdog wdt_period=N : N sets the value of the Watchdog Timer Period. The Watchdog Timer Period meaning is implementation specific. Check User Manual for the processor for more details. This patch is based off of work done by Takeharu Kato. Signed-off-by: Matt McClintock Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/watchdog/Kconfig | 4 + drivers/char/watchdog/Makefile | 1 + drivers/char/watchdog/booke_wdt.c | 191 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 drivers/char/watchdog/booke_wdt.c (limited to 'drivers/char') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index b53e2e2..95335b4 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -346,6 +346,10 @@ 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) + # MIPS Architecture config INDYDOG diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index c183883..b16dfea 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 0000000..7281f39 --- /dev/null +++ b/drivers/char/watchdog/booke_wdt.c @@ -0,0 +1,191 @@ +/* + * drivers/char/watchdog/booke_wdt.c + * + * Watchdog timer for PowerPC Book-E systems + * + * Author: Matthew McClintock + * Maintainer: Kumar Gala + * + * 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 +#include +#include +#include +#include +#include + +#include +#include + +/* 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 wdt_enable = 0; +u32 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(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(wdt_period, (u32 *) arg)) + return -EFAULT; + mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(wdt_period)); + return 0; + case WDIOC_GETTIMEOUT: + return put_user(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 (wdt_enable == 0) { + wdt_enable = 1; + booke_wdt_enable(); + printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", + 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 (wdt_enable == 1) { + printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", + wdt_period); + booke_wdt_enable(); + } + + return ret; +} +device_initcall(booke_wdt_init); -- cgit v1.1 From 39cdc4bfb5c587c617ab6a28083c19101154e149 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 3 Sep 2005 15:55:39 -0700 Subject: [PATCH] ppc32: Cleaned up global namespace of Book-E watchdog variables Renamed global variables used to convey if the watchdog is enabled and periodicity of the timer and moved the declarations into a header for these variables Signed-off-by: Matt McClintock Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/watchdog/Kconfig | 3 +++ drivers/char/watchdog/booke_wdt.c | 23 ++++++++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 95335b4..c3898af 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -349,6 +349,9 @@ config 8xx_WDT 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 diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index 7281f39..abc30cc 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c @@ -23,6 +23,7 @@ #include #include +#include /* If the kernel parameter wdt_enable=1, the watchdog will be enabled at boot. * Also, the wdt_period sets the watchdog timer period timeout. @@ -38,8 +39,8 @@ #define WDT_PERIOD_DEFAULT 4 /* Refer to the PPC40x and PPC4xx manuals */ #endif /* for timing information */ -u32 wdt_enable = 0; -u32 wdt_period = WDT_PERIOD_DEFAULT; +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)) @@ -55,7 +56,7 @@ static __inline__ void booke_wdt_enable(void) u32 val; val = mfspr(SPRN_TCR); - val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(wdt_period)); + val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); mtspr(SPRN_TCR, val); } @@ -108,12 +109,12 @@ static int booke_wdt_ioctl (struct inode *inode, struct file *file, booke_wdt_ping(); return 0; case WDIOC_SETTIMEOUT: - if (get_user(wdt_period, (u32 *) arg)) + if (get_user(booke_wdt_period, (u32 *) arg)) return -EFAULT; - mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(wdt_period)); + mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period)); return 0; case WDIOC_GETTIMEOUT: - return put_user(wdt_period, (u32 *) arg); + return put_user(booke_wdt_period, (u32 *) arg); case WDIOC_SETOPTIONS: if (get_user(tmp, (u32 *) arg)) return -EINVAL; @@ -134,11 +135,11 @@ static int booke_wdt_ioctl (struct inode *inode, struct file *file, */ static int booke_wdt_open (struct inode *inode, struct file *file) { - if (wdt_enable == 0) { - wdt_enable = 1; + 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", - wdt_period); + booke_wdt_period); } return 0; @@ -180,9 +181,9 @@ static int __init booke_wdt_init(void) return ret; } - if (wdt_enable == 1) { + if (booke_wdt_enabled == 1) { printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", - wdt_period); + booke_wdt_period); booke_wdt_enable(); } -- cgit v1.1 From 63b799f9ded82444212afdcf61379a247d544909 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Sat, 3 Sep 2005 15:56:13 -0700 Subject: [PATCH] mips: add TANBAC VR4131 multichip module This patch has added TANBAC VR4131 multichip module in arch/mips/Kconfig Signed-off-by: Yoichi Yuasa Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 7333b41..116a7b1 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -842,8 +842,9 @@ config SONYPI config TANBAC_TB0219 tristate "TANBAC TB0219 base board support" - depends TANBAC_TB0229 - + depends TANBAC_TB022X + select PCI + select PCI_VR41XX menu "Ftape, the floppy tape device driver" -- cgit v1.1 From 466adc66cf6eea0268c8678834c8c6a56e5a2f9e Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Sat, 3 Sep 2005 15:56:14 -0700 Subject: [PATCH] fix warning of TANBAC_TB0219 in drivers/char/Kconfig $ make menuconfig scripts/kconfig/mconf arch/i386/Kconfig drivers/char/Kconfig:847:warning: 'select' used by config symbol 'TANBAC_TB0219' refer to undefined symbol 'PCI_VR41XX' Here is a patch for this warning fix. Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/Kconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 116a7b1..f418f45 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -843,8 +843,6 @@ config SONYPI config TANBAC_TB0219 tristate "TANBAC TB0219 base board support" depends TANBAC_TB022X - select PCI - select PCI_VR41XX menu "Ftape, the floppy tape device driver" -- cgit v1.1 From 89625eb186b9b0b9454d44126f8b1bcc72ad93b7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 5 Sep 2005 21:23:23 +1000 Subject: drm: fix issue with handle lookup for a 0 handle On 32-bit PPC a 0 handle is valid for AGP space, the 32/64 lookup doesn't handle 0 correctly. From: Ben Herrenschmidt and Paul Mackerras Signed-off-by: Dave Airlie --- drivers/char/drm/drm_bufs.c | 64 ++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index e0743eb..8eff073 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -48,8 +48,8 @@ unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource) } EXPORT_SYMBOL(drm_get_resource_len); -static drm_local_map_t *drm_find_matching_map(drm_device_t *dev, - drm_local_map_t *map) +static drm_map_list_t *drm_find_matching_map(drm_device_t *dev, + drm_local_map_t *map) { struct list_head *list; @@ -57,7 +57,7 @@ static drm_local_map_t *drm_find_matching_map(drm_device_t *dev, drm_map_list_t *entry = list_entry(list, drm_map_list_t, head); if (entry->map && map->type == entry->map->type && entry->map->offset == map->offset) { - return entry->map; + return entry; } } @@ -114,14 +114,13 @@ static __inline__ unsigned int HandleID(unsigned long lhandle, drm_device_t *dev * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where * applicable and if supported by the kernel. */ -int drm_addmap(drm_device_t * dev, unsigned int offset, - unsigned int size, drm_map_type_t type, - drm_map_flags_t flags, drm_local_map_t ** map_ptr) +int drm_addmap_core(drm_device_t * dev, unsigned int offset, + unsigned int size, drm_map_type_t type, + drm_map_flags_t flags, drm_map_list_t **maplist) { drm_map_t *map; drm_map_list_t *list; drm_dma_handle_t *dmah; - drm_local_map_t *found_map; map = drm_alloc( sizeof(*map), DRM_MEM_MAPS ); if ( !map ) @@ -166,17 +165,17 @@ int drm_addmap(drm_device_t * dev, unsigned int offset, * needing to be aware of it. Therefore, we just return success * when the server tries to create a duplicate map. */ - found_map = drm_find_matching_map(dev, map); - if (found_map != NULL) { - if (found_map->size != map->size) { + list = drm_find_matching_map(dev, map); + if (list != NULL) { + if (list->map->size != map->size) { DRM_DEBUG("Matching maps of type %d with " "mismatched sizes, (%ld vs %ld)\n", - map->type, map->size, found_map->size); - found_map->size = map->size; + map->type, map->size, list->map->size); + list->map->size = map->size; } drm_free(map, sizeof(*map), DRM_MEM_MAPS); - *map_ptr = found_map; + *maplist = list; return 0; } @@ -264,9 +263,22 @@ int drm_addmap(drm_device_t * dev, unsigned int offset, : map->offset, dev); up(&dev->struct_sem); - *map_ptr = map; + *maplist = list; return 0; } + +int drm_addmap(drm_device_t *dev, unsigned int offset, + unsigned int size, drm_map_type_t type, + drm_map_flags_t flags, drm_local_map_t **map_ptr) +{ + drm_map_list_t *list; + int rc; + + rc = drm_addmap_core(dev, offset, size, type, flags, &list); + if (!rc) + *map_ptr = list->map; + return rc; +} EXPORT_SYMBOL(drm_addmap); int drm_addmap_ioctl(struct inode *inode, struct file *filp, @@ -275,10 +287,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->head->dev; drm_map_t map; - drm_map_t *map_ptr; + drm_map_list_t *maplist; drm_map_t __user *argp = (void __user *)arg; int err; - unsigned long handle = 0; if (!(filp->f_mode & 3)) return -EACCES; /* Require read/write */ @@ -287,26 +298,15 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp, return -EFAULT; } - err = drm_addmap(dev, map.offset, map.size, map.type, map.flags, - &map_ptr); + err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags, + &maplist); - if (err) { + if (err) return err; - } - - { - drm_map_list_t *_entry; - list_for_each_entry(_entry, &dev->maplist->head, head) { - if (_entry->map == map_ptr) - handle = _entry->user_token; - } - if (!handle) - return -EFAULT; - } - if (copy_to_user(argp, map_ptr, sizeof(*map_ptr))) + if (copy_to_user(argp, maplist->map, sizeof(drm_map_t))) return -EFAULT; - if (put_user(handle, &argp->handle)) + if (put_user(maplist->user_token, &argp->handle)) return -EFAULT; return 0; } -- cgit v1.1 From f210973bb6d17aa220c797e8ea23d127d96859b7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 5 Sep 2005 21:33:44 +1000 Subject: drm: small cleanups This patch contains the following small cleanups: - make two needlessly global functions static - drm_sysfs.c: every file should #include the header with the prototypes of the global functions it is offering Signed-off-by: Adrian Bunk Signed-off-by: Dave Airlie --- drivers/char/drm/drm_bufs.c | 2 +- drivers/char/drm/drm_context.c | 2 +- drivers/char/drm/drm_sysfs.c | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 8eff073..f28e70a 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -1041,7 +1041,7 @@ static int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request) return 0; } -int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request) +static int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request) { drm_device_dma_t *dma = dev->dma; drm_buf_entry_t *entry; diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c index f515567..5028927 100644 --- a/drivers/char/drm/drm_context.c +++ b/drivers/char/drm/drm_context.c @@ -308,7 +308,7 @@ found: * * Attempt to set drm_device::context_flag. */ -int drm_context_switch( drm_device_t *dev, int old, int new ) +static int drm_context_switch( drm_device_t *dev, int old, int new ) { if ( test_and_set_bit( 0, &dev->context_flag ) ) { DRM_ERROR( "Reentering -- FIXME\n" ); diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 2fc10c4..475cc5e 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c @@ -17,6 +17,7 @@ #include #include "drm_core.h" +#include "drmP.h" struct drm_sysfs_class { struct class_device_attribute attr; -- cgit v1.1 From 908f9c485042e516bb3749f4361129a94772fe26 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 5 Sep 2005 21:51:30 +1000 Subject: drm: fix MGA on non AGP systems Al Viro noticed that MGA wouldn't build on non AGP systems. Signed-off-by: Dave Airlie --- drivers/char/drm/mga_dma.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c index 567b425..fc7d4a5 100644 --- a/drivers/char/drm/mga_dma.c +++ b/drivers/char/drm/mga_dma.c @@ -417,6 +417,7 @@ int mga_driver_preinit(drm_device_t *dev, unsigned long flags) return 0; } +#if __OS_HAS_AGP /** * Bootstrap the driver for AGP DMA. * @@ -560,6 +561,13 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev, DRM_INFO("Initialized card for AGP DMA.\n"); return 0; } +#else +static int mga_do_agp_dma_bootstrap(drm_device_t * dev, + drm_mga_dma_bootstrap_t * dma_bs) +{ + return -EINVAL; +} +#endif /** * Bootstrap the driver for PCI DMA. @@ -697,7 +705,6 @@ static int mga_do_dma_bootstrap(drm_device_t * dev, * carve off portions of it for internal uses. The remaining memory * is returned to user-mode to be used for AGP textures. */ - if (is_agp) { err = mga_do_agp_dma_bootstrap(dev, dma_bs); } @@ -932,6 +939,7 @@ static int mga_do_cleanup_dma( drm_device_t *dev ) drm_core_ioremapfree(dev->agp_buffer_map, dev); if (dev_priv->used_new_dma_init) { +#if __OS_HAS_AGP if (dev_priv->agp_mem != NULL) { dev_priv->agp_textures = NULL; drm_unbind_agp(dev_priv->agp_mem); @@ -944,7 +952,7 @@ static int mga_do_cleanup_dma( drm_device_t *dev ) if ((dev->agp != NULL) && dev->agp->acquired) { err = drm_agp_release(dev); } - +#endif dev_priv->used_new_dma_init = 0; } @@ -965,7 +973,7 @@ static int mga_do_cleanup_dma( drm_device_t *dev ) } } - return 0; + return err; } int mga_dma_init( DRM_IOCTL_ARGS ) -- cgit v1.1 From 1d25240fcfce0e55540a273b1e1b07d304065a31 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 5 Sep 2005 23:30:15 -0700 Subject: [MOXA]: Fix this driver properly. Actually, proper fix of that breakage is embarrassingly simple - it's yet another gratitious leftover include of asm/segment.h, so incremental to the previos would be removal of that BROKEN and removal of bogus include from mxser.c itself. Signed-off-by: David S. Miller --- drivers/char/Kconfig | 2 +- drivers/char/mxser.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index df5f2b0..f418f45 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 && (BROKEN || !SPARC32) + depends on SERIAL_NONSTANDARD help Say Y here if you have a Moxa SmartIO multiport serial card. diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index f022f09..d0ef1ae 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -63,7 +63,6 @@ #include #include #include -#include #include #include -- cgit v1.1 From 53d0fc27af3a3ab22c0ffb67857adfa18977e681 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 5 Sep 2005 23:33:05 -0700 Subject: [RTC]: Use SA_SHIRQ in sparc specific code. Based upon a report from Jason Wever. Signed-off-by: David S. Miller --- drivers/char/rtc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index cd4fe8b..63fff7c 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -938,10 +938,9 @@ found: /* * XXX Interrupt pin #7 in Espresso is shared between RTC and - * PCI Slot 2 INTA# (and some INTx# in Slot 1). SA_INTERRUPT here - * is asking for trouble with add-on boards. Change to SA_SHIRQ. + * PCI Slot 2 INTA# (and some INTx# in Slot 1). */ - if (request_irq(rtc_irq, rtc_interrupt, SA_INTERRUPT, "rtc", (void *)&rtc_port)) { + if (request_irq(rtc_irq, rtc_interrupt, SA_SHIRQ, "rtc", (void *)&rtc_port)) { /* * Standard way for sparc to print irq's is to use * __irq_itoa(). I think for EBus it's ok to use %d. -- cgit v1.1 From c0f2f761e1ea3923952e31cce2cdb7d65f450fbd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 5 Sep 2005 23:35:41 -0700 Subject: [SPARC64]: Kconfig fix (GEN_RTC dependencies) Yet another architecture not coverd by GEN_RTC - sparc64 never picked it until now and it doesn't have asm/rtc.h to go with it, so it wouldn't compile anyway (or have these ioctls in the user-visible headers, for that matter). FWIW, I'm very tempted to introduce ARCH_HAS_GEN_RTC and have it set in arch/*/Kconfig for architectures that know what to do with this stuff - for something supposedly generic the list of architectures where it doesn't work is getting too long... Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/char/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index f418f45..a1de06d 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -735,7 +735,7 @@ config SGI_IP27_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" - depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32 + depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32 && !SPARC64 ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you -- cgit v1.1 From f2cf8e25ba4cf4e0881e612125858b4eed563ee4 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 6 Sep 2005 15:16:44 -0700 Subject: [PATCH] Clean up the old digi support and rescue it Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/Kconfig | 2 +- drivers/char/digi1.h | 38 +- drivers/char/digiFep1.h | 154 ++--- drivers/char/epca.c | 1588 ++++++++++++++--------------------------------- drivers/char/epca.h | 108 ++-- 5 files changed, 610 insertions(+), 1280 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index a1de06d..2bc9d64 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -138,7 +138,7 @@ config CYZ_INTR config DIGIEPCA tristate "Digiboard Intelligent Async Support" - depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (!64BIT || BROKEN) + depends on SERIAL_NONSTANDARD ---help--- This is a driver for Digi International's Xx, Xeve, and Xem series of cards which provide multiple serial ports. You would need diff --git a/drivers/char/digi1.h b/drivers/char/digi1.h index 184378d..94d4eab 100644 --- a/drivers/char/digi1.h +++ b/drivers/char/digi1.h @@ -1,46 +1,46 @@ /* Definitions for DigiBoard ditty(1) command. */ #if !defined(TIOCMODG) -#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */ -#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */ +#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ +#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ #endif #if !defined(TIOCMSET) -#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */ -#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */ +#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ +#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ #endif #if !defined(TIOCMBIC) -#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */ -#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */ +#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ +#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ #endif #if !defined(TIOCSDTR) -#define TIOCSDTR ('e'<<8) | 0 /* set DTR */ -#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */ +#define TIOCSDTR (('e'<<8) | 0) /* set DTR */ +#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ #endif /************************************************************************ * Ioctl command arguments for DIGI parameters. ************************************************************************/ -#define DIGI_GETA ('e'<<8) | 94 /* Read params */ +#define DIGI_GETA (('e'<<8) | 94) /* Read params */ -#define DIGI_SETA ('e'<<8) | 95 /* Set params */ -#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */ -#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */ +#define DIGI_SETA (('e'<<8) | 95) /* Set params */ +#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ +#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ -#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */ +#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ /* control characters */ -#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */ +#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ /* control characters */ -#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */ +#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ /* flow control chars */ -#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */ +#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ /* flow control chars */ -#define DIGI_GETINFO ('e'<<8) | 103 /* Fill in digi_info */ -#define DIGI_POLLER ('e'<<8) | 104 /* Turn on/off poller */ -#define DIGI_INIT ('e'<<8) | 105 /* Allow things to run. */ +#define DIGI_GETINFO (('e'<<8) | 103) /* Fill in digi_info */ +#define DIGI_POLLER (('e'<<8) | 104) /* Turn on/off poller */ +#define DIGI_INIT (('e'<<8) | 105) /* Allow things to run. */ struct digiflow_struct { diff --git a/drivers/char/digiFep1.h b/drivers/char/digiFep1.h index c47d7fc..3c1f192 100644 --- a/drivers/char/digiFep1.h +++ b/drivers/char/digiFep1.h @@ -13,88 +13,88 @@ struct global_data { - volatile ushort cin; - volatile ushort cout; - volatile ushort cstart; - volatile ushort cmax; - volatile ushort ein; - volatile ushort eout; - volatile ushort istart; - volatile ushort imax; + u16 cin; + u16 cout; + u16 cstart; + u16 cmax; + u16 ein; + u16 eout; + u16 istart; + u16 imax; }; struct board_chan { - int filler1; - int filler2; - volatile ushort tseg; - volatile ushort tin; - volatile ushort tout; - volatile ushort tmax; - - volatile ushort rseg; - volatile ushort rin; - volatile ushort rout; - volatile ushort rmax; - - volatile ushort tlow; - volatile ushort rlow; - volatile ushort rhigh; - volatile ushort incr; - - volatile ushort etime; - volatile ushort edelay; - volatile unchar *dev; - - volatile ushort iflag; - volatile ushort oflag; - volatile ushort cflag; - volatile ushort gmask; - - volatile ushort col; - volatile ushort delay; - volatile ushort imask; - volatile ushort tflush; - - int filler3; - int filler4; - int filler5; - int filler6; - - volatile unchar num; - volatile unchar ract; - volatile unchar bstat; - volatile unchar tbusy; - volatile unchar iempty; - volatile unchar ilow; - volatile unchar idata; - volatile unchar eflag; - - volatile unchar tflag; - volatile unchar rflag; - volatile unchar xmask; - volatile unchar xval; - volatile unchar mstat; - volatile unchar mchange; - volatile unchar mint; - volatile unchar lstat; - - volatile unchar mtran; - volatile unchar orun; - volatile unchar startca; - volatile unchar stopca; - volatile unchar startc; - volatile unchar stopc; - volatile unchar vnext; - volatile unchar hflow; - - volatile unchar fillc; - volatile unchar ochar; - volatile unchar omask; - - unchar filler7; - unchar filler8[28]; + u32 filler1; + u32 filler2; + u16 tseg; + u16 tin; + u16 tout; + u16 tmax; + + u16 rseg; + u16 rin; + u16 rout; + u16 rmax; + + u16 tlow; + u16 rlow; + u16 rhigh; + u16 incr; + + u16 etime; + u16 edelay; + unchar *dev; + + u16 iflag; + u16 oflag; + u16 cflag; + u16 gmask; + + u16 col; + u16 delay; + u16 imask; + u16 tflush; + + u32 filler3; + u32 filler4; + u32 filler5; + u32 filler6; + + u8 num; + u8 ract; + u8 bstat; + u8 tbusy; + u8 iempty; + u8 ilow; + u8 idata; + u8 eflag; + + u8 tflag; + u8 rflag; + u8 xmask; + u8 xval; + u8 mstat; + u8 mchange; + u8 mint; + u8 lstat; + + u8 mtran; + u8 orun; + u8 startca; + u8 stopca; + u8 startc; + u8 stopc; + u8 vnext; + u8 hflow; + + u8 fillc; + u8 ochar; + u8 omask; + + u8 filler7; + u8 filler8[28]; }; diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 6025e18..58d3738 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -6,6 +6,8 @@ For technical support please email digiLinux@dgii.com or call Digi tech support at (612) 912-3456 + ** This driver is no longer supported by Digi ** + Much of this design and code came from epca.c which was copyright (C) 1994, 1995 Troy De Jongh, and subsquently modified by David Nugent, Christoph Lameter, Mike McLagan. @@ -43,31 +45,19 @@ #include #include #include - -#ifdef CONFIG_PCI -#define ENABLE_PCI -#endif /* CONFIG_PCI */ - -#define putUser(arg1, arg2) put_user(arg1, (unsigned long __user *)arg2) -#define getUser(arg1, arg2) get_user(arg1, (unsigned __user *)arg2) - -#ifdef ENABLE_PCI +#include #include #include "digiPCI.h" -#endif /* ENABLE_PCI */ + #include "digi1.h" #include "digiFep1.h" #include "epca.h" #include "epcaconfig.h" -#if BITS_PER_LONG != 32 -# error FIXME: this driver only works on 32-bit platforms -#endif - /* ---------------------- Begin defines ------------------------ */ -#define VERSION "1.3.0.1-LK" +#define VERSION "1.3.0.1-LK2.6" /* This major needs to be submitted to Linux to join the majors list */ @@ -81,13 +71,17 @@ /* ----------------- Begin global definitions ------------------- */ -static char mesg[100]; static int nbdevs, num_cards, liloconfig; static int digi_poller_inhibited = 1 ; static int setup_error_code; static int invalid_lilo_config; +/* The ISA boards do window flipping into the same spaces so its only sane + with a single lock. It's still pretty efficient */ + +static spinlock_t epca_lock = SPIN_LOCK_UNLOCKED; + /* ----------------------------------------------------------------------- MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 7 below. @@ -129,58 +123,58 @@ static struct timer_list epca_timer; configured. ----------------------------------------------------------------------- */ -static inline void memwinon(struct board_info *b, unsigned int win); -static inline void memwinoff(struct board_info *b, unsigned int win); -static inline void globalwinon(struct channel *ch); -static inline void rxwinon(struct channel *ch); -static inline void txwinon(struct channel *ch); -static inline void memoff(struct channel *ch); -static inline void assertgwinon(struct channel *ch); -static inline void assertmemoff(struct channel *ch); +static void memwinon(struct board_info *b, unsigned int win); +static void memwinoff(struct board_info *b, unsigned int win); +static void globalwinon(struct channel *ch); +static void rxwinon(struct channel *ch); +static void txwinon(struct channel *ch); +static void memoff(struct channel *ch); +static void assertgwinon(struct channel *ch); +static void assertmemoff(struct channel *ch); /* ---- Begin more 'specific' memory functions for cx_like products --- */ -static inline void pcxem_memwinon(struct board_info *b, unsigned int win); -static inline void pcxem_memwinoff(struct board_info *b, unsigned int win); -static inline void pcxem_globalwinon(struct channel *ch); -static inline void pcxem_rxwinon(struct channel *ch); -static inline void pcxem_txwinon(struct channel *ch); -static inline void pcxem_memoff(struct channel *ch); +static void pcxem_memwinon(struct board_info *b, unsigned int win); +static void pcxem_memwinoff(struct board_info *b, unsigned int win); +static void pcxem_globalwinon(struct channel *ch); +static void pcxem_rxwinon(struct channel *ch); +static void pcxem_txwinon(struct channel *ch); +static void pcxem_memoff(struct channel *ch); /* ------ Begin more 'specific' memory functions for the pcxe ------- */ -static inline void pcxe_memwinon(struct board_info *b, unsigned int win); -static inline void pcxe_memwinoff(struct board_info *b, unsigned int win); -static inline void pcxe_globalwinon(struct channel *ch); -static inline void pcxe_rxwinon(struct channel *ch); -static inline void pcxe_txwinon(struct channel *ch); -static inline void pcxe_memoff(struct channel *ch); +static void pcxe_memwinon(struct board_info *b, unsigned int win); +static void pcxe_memwinoff(struct board_info *b, unsigned int win); +static void pcxe_globalwinon(struct channel *ch); +static void pcxe_rxwinon(struct channel *ch); +static void pcxe_txwinon(struct channel *ch); +static void pcxe_memoff(struct channel *ch); /* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */ /* Note : pc64xe and pcxi share the same windowing routines */ -static inline void pcxi_memwinon(struct board_info *b, unsigned int win); -static inline void pcxi_memwinoff(struct board_info *b, unsigned int win); -static inline void pcxi_globalwinon(struct channel *ch); -static inline void pcxi_rxwinon(struct channel *ch); -static inline void pcxi_txwinon(struct channel *ch); -static inline void pcxi_memoff(struct channel *ch); +static void pcxi_memwinon(struct board_info *b, unsigned int win); +static void pcxi_memwinoff(struct board_info *b, unsigned int win); +static void pcxi_globalwinon(struct channel *ch); +static void pcxi_rxwinon(struct channel *ch); +static void pcxi_txwinon(struct channel *ch); +static void pcxi_memoff(struct channel *ch); /* - Begin 'specific' do nothing memory functions needed for some cards - */ -static inline void dummy_memwinon(struct board_info *b, unsigned int win); -static inline void dummy_memwinoff(struct board_info *b, unsigned int win); -static inline void dummy_globalwinon(struct channel *ch); -static inline void dummy_rxwinon(struct channel *ch); -static inline void dummy_txwinon(struct channel *ch); -static inline void dummy_memoff(struct channel *ch); -static inline void dummy_assertgwinon(struct channel *ch); -static inline void dummy_assertmemoff(struct channel *ch); +static void dummy_memwinon(struct board_info *b, unsigned int win); +static void dummy_memwinoff(struct board_info *b, unsigned int win); +static void dummy_globalwinon(struct channel *ch); +static void dummy_rxwinon(struct channel *ch); +static void dummy_txwinon(struct channel *ch); +static void dummy_memoff(struct channel *ch); +static void dummy_assertgwinon(struct channel *ch); +static void dummy_assertmemoff(struct channel *ch); /* ------------------- Begin declare functions ----------------------- */ -static inline struct channel *verifyChannel(register struct tty_struct *); -static inline void pc_sched_event(struct channel *, int); +static struct channel *verifyChannel(struct tty_struct *); +static void pc_sched_event(struct channel *, int); static void epca_error(int, char *); static void pc_close(struct tty_struct *, struct file *); static void shutdown(struct channel *); @@ -215,15 +209,11 @@ static void pc_unthrottle(struct tty_struct *tty); static void digi_send_break(struct channel *ch, int msec); static void setup_empty_event(struct tty_struct *tty, struct channel *ch); void epca_setup(char *, int *); -void console_print(const char *); static int get_termio(struct tty_struct *, struct termio __user *); static int pc_write(struct tty_struct *, const unsigned char *, int); -int pc_init(void); - -#ifdef ENABLE_PCI +static int pc_init(void); static int init_PCI(void); -#endif /* ENABLE_PCI */ /* ------------------------------------------------------------------ @@ -237,41 +227,41 @@ static int init_PCI(void); making direct calls deserves what they get. -------------------------------------------------------------------- */ -static inline void memwinon(struct board_info *b, unsigned int win) +static void memwinon(struct board_info *b, unsigned int win) { (b->memwinon)(b, win); } -static inline void memwinoff(struct board_info *b, unsigned int win) +static void memwinoff(struct board_info *b, unsigned int win) { (b->memwinoff)(b, win); } -static inline void globalwinon(struct channel *ch) +static void globalwinon(struct channel *ch) { (ch->board->globalwinon)(ch); } -static inline void rxwinon(struct channel *ch) +static void rxwinon(struct channel *ch) { (ch->board->rxwinon)(ch); } -static inline void txwinon(struct channel *ch) +static void txwinon(struct channel *ch) { (ch->board->txwinon)(ch); } -static inline void memoff(struct channel *ch) +static void memoff(struct channel *ch) { (ch->board->memoff)(ch); } -static inline void assertgwinon(struct channel *ch) +static void assertgwinon(struct channel *ch) { (ch->board->assertgwinon)(ch); } -static inline void assertmemoff(struct channel *ch) +static void assertmemoff(struct channel *ch) { (ch->board->assertmemoff)(ch); } @@ -281,66 +271,66 @@ static inline void assertmemoff(struct channel *ch) and CX series cards. ------------------------------------------------------------ */ -static inline void pcxem_memwinon(struct board_info *b, unsigned int win) +static void pcxem_memwinon(struct board_info *b, unsigned int win) { - outb_p(FEPWIN|win, (int)b->port + 1); + outb_p(FEPWIN|win, b->port + 1); } -static inline void pcxem_memwinoff(struct board_info *b, unsigned int win) +static void pcxem_memwinoff(struct board_info *b, unsigned int win) { - outb_p(0, (int)b->port + 1); + outb_p(0, b->port + 1); } -static inline void pcxem_globalwinon(struct channel *ch) +static void pcxem_globalwinon(struct channel *ch) { outb_p( FEPWIN, (int)ch->board->port + 1); } -static inline void pcxem_rxwinon(struct channel *ch) +static void pcxem_rxwinon(struct channel *ch) { outb_p(ch->rxwin, (int)ch->board->port + 1); } -static inline void pcxem_txwinon(struct channel *ch) +static void pcxem_txwinon(struct channel *ch) { outb_p(ch->txwin, (int)ch->board->port + 1); } -static inline void pcxem_memoff(struct channel *ch) +static void pcxem_memoff(struct channel *ch) { outb_p(0, (int)ch->board->port + 1); } /* ----------------- Begin pcxe memory window stuff ------------------ */ -static inline void pcxe_memwinon(struct board_info *b, unsigned int win) +static void pcxe_memwinon(struct board_info *b, unsigned int win) { - outb_p(FEPWIN | win, (int)b->port + 1); + outb_p(FEPWIN | win, b->port + 1); } -static inline void pcxe_memwinoff(struct board_info *b, unsigned int win) +static void pcxe_memwinoff(struct board_info *b, unsigned int win) { - outb_p(inb((int)b->port) & ~FEPMEM, - (int)b->port + 1); - outb_p(0, (int)b->port + 1); + outb_p(inb(b->port) & ~FEPMEM, + b->port + 1); + outb_p(0, b->port + 1); } -static inline void pcxe_globalwinon(struct channel *ch) +static void pcxe_globalwinon(struct channel *ch) { outb_p( FEPWIN, (int)ch->board->port + 1); } -static inline void pcxe_rxwinon(struct channel *ch) +static void pcxe_rxwinon(struct channel *ch) { outb_p(ch->rxwin, (int)ch->board->port + 1); } -static inline void pcxe_txwinon(struct channel *ch) +static void pcxe_txwinon(struct channel *ch) { outb_p(ch->txwin, (int)ch->board->port + 1); } -static inline void pcxe_memoff(struct channel *ch) +static void pcxe_memoff(struct channel *ch) { outb_p(0, (int)ch->board->port); outb_p(0, (int)ch->board->port + 1); @@ -348,44 +338,44 @@ static inline void pcxe_memoff(struct channel *ch) /* ------------- Begin pc64xe and pcxi memory window stuff -------------- */ -static inline void pcxi_memwinon(struct board_info *b, unsigned int win) +static void pcxi_memwinon(struct board_info *b, unsigned int win) { - outb_p(inb((int)b->port) | FEPMEM, (int)b->port); + outb_p(inb(b->port) | FEPMEM, b->port); } -static inline void pcxi_memwinoff(struct board_info *b, unsigned int win) +static void pcxi_memwinoff(struct board_info *b, unsigned int win) { - outb_p(inb((int)b->port) & ~FEPMEM, (int)b->port); + outb_p(inb(b->port) & ~FEPMEM, b->port); } -static inline void pcxi_globalwinon(struct channel *ch) +static void pcxi_globalwinon(struct channel *ch) { - outb_p(FEPMEM, (int)ch->board->port); + outb_p(FEPMEM, ch->board->port); } -static inline void pcxi_rxwinon(struct channel *ch) +static void pcxi_rxwinon(struct channel *ch) { - outb_p(FEPMEM, (int)ch->board->port); + outb_p(FEPMEM, ch->board->port); } -static inline void pcxi_txwinon(struct channel *ch) +static void pcxi_txwinon(struct channel *ch) { - outb_p(FEPMEM, (int)ch->board->port); + outb_p(FEPMEM, ch->board->port); } -static inline void pcxi_memoff(struct channel *ch) +static void pcxi_memoff(struct channel *ch) { - outb_p(0, (int)ch->board->port); + outb_p(0, ch->board->port); } -static inline void pcxi_assertgwinon(struct channel *ch) +static void pcxi_assertgwinon(struct channel *ch) { - epcaassert(inb((int)ch->board->port) & FEPMEM, "Global memory off"); + epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off"); } -static inline void pcxi_assertmemoff(struct channel *ch) +static void pcxi_assertmemoff(struct channel *ch) { - epcaassert(!(inb((int)ch->board->port) & FEPMEM), "Memory on"); + epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on"); } @@ -398,185 +388,143 @@ static inline void pcxi_assertmemoff(struct channel *ch) may or may not do anything. ---------------------------------------------------------------------------*/ -static inline void dummy_memwinon(struct board_info *b, unsigned int win) +static void dummy_memwinon(struct board_info *b, unsigned int win) { } -static inline void dummy_memwinoff(struct board_info *b, unsigned int win) +static void dummy_memwinoff(struct board_info *b, unsigned int win) { } -static inline void dummy_globalwinon(struct channel *ch) +static void dummy_globalwinon(struct channel *ch) { } -static inline void dummy_rxwinon(struct channel *ch) +static void dummy_rxwinon(struct channel *ch) { } -static inline void dummy_txwinon(struct channel *ch) +static void dummy_txwinon(struct channel *ch) { } -static inline void dummy_memoff(struct channel *ch) +static void dummy_memoff(struct channel *ch) { } -static inline void dummy_assertgwinon(struct channel *ch) +static void dummy_assertgwinon(struct channel *ch) { } -static inline void dummy_assertmemoff(struct channel *ch) +static void dummy_assertmemoff(struct channel *ch) { } /* ----------------- Begin verifyChannel function ----------------------- */ -static inline struct channel *verifyChannel(register struct tty_struct *tty) +static struct channel *verifyChannel(struct tty_struct *tty) { /* Begin verifyChannel */ - /* -------------------------------------------------------------------- This routine basically provides a sanity check. It insures that the channel returned is within the proper range of addresses as well as properly initialized. If some bogus info gets passed in through tty->driver_data this should catch it. - --------------------------------------------------------------------- */ - - if (tty) - { /* Begin if tty */ - - register struct channel *ch = (struct channel *)tty->driver_data; - - if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) - { + --------------------------------------------------------------------- */ + if (tty) { + struct channel *ch = (struct channel *)tty->driver_data; + if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) { if (ch->magic == EPCA_MAGIC) return ch; } - - } /* End if tty */ - - /* Else return a NULL for invalid */ + } return NULL; } /* End verifyChannel */ /* ------------------ Begin pc_sched_event ------------------------- */ -static inline void pc_sched_event(struct channel *ch, int event) -{ /* Begin pc_sched_event */ - - +static void pc_sched_event(struct channel *ch, int event) +{ /* ---------------------------------------------------------------------- We call this to schedule interrupt processing on some event. The kernel sees our request and calls the related routine in OUR driver. -------------------------------------------------------------------------*/ - ch->event |= 1 << event; schedule_work(&ch->tqueue); - - } /* End pc_sched_event */ /* ------------------ Begin epca_error ------------------------- */ static void epca_error(int line, char *msg) -{ /* Begin epca_error */ - +{ printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg); - return; - -} /* End epca_error */ +} /* ------------------ Begin pc_close ------------------------- */ static void pc_close(struct tty_struct * tty, struct file * filp) -{ /* Begin pc_close */ - +{ struct channel *ch; unsigned long flags; - /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - - if ((ch = verifyChannel(tty)) != NULL) - { /* Begin if ch != NULL */ - - save_flags(flags); - cli(); - - if (tty_hung_up_p(filp)) - { - restore_flags(flags); + if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */ + spin_lock_irqsave(&epca_lock, flags); + if (tty_hung_up_p(filp)) { + spin_unlock_irqrestore(&epca_lock, flags); return; } - /* Check to see if the channel is open more than once */ - if (ch->count-- > 1) - { /* Begin channel is open more than once */ - + if (ch->count-- > 1) { + /* Begin channel is open more than once */ /* ------------------------------------------------------------- Return without doing anything. Someone might still be using the channel. ---------------------------------------------------------------- */ - - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); return; } /* End channel is open more than once */ /* Port open only once go ahead with shutdown & reset */ - - if (ch->count < 0) - { - ch->count = 0; - } + if (ch->count < 0) + BUG(); /* --------------------------------------------------------------- Let the rest of the driver know the channel is being closed. This becomes important if an open is attempted before close is finished. ------------------------------------------------------------------ */ - ch->asyncflags |= ASYNC_CLOSING; - tty->closing = 1; - if (ch->asyncflags & ASYNC_INITIALIZED) - { + spin_unlock_irqrestore(&epca_lock, flags); + + if (ch->asyncflags & ASYNC_INITIALIZED) { /* Setup an event to indicate when the transmit buffer empties */ setup_empty_event(tty, ch); tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ } - if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); tty_ldisc_flush(tty); shutdown(ch); + + spin_lock_irqsave(&epca_lock, flags); tty->closing = 0; ch->event = 0; ch->tty = NULL; + spin_unlock_irqrestore(&epca_lock, flags); - if (ch->blocked_open) - { /* Begin if blocked_open */ - + if (ch->blocked_open) { /* Begin if blocked_open */ if (ch->close_delay) - { msleep_interruptible(jiffies_to_msecs(ch->close_delay)); - } - wake_up_interruptible(&ch->open_wait); - } /* End if blocked_open */ - ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | ASYNC_CLOSING); wake_up_interruptible(&ch->close_wait); - - - restore_flags(flags); - } /* End if ch != NULL */ - } /* End pc_close */ /* ------------------ Begin shutdown ------------------------- */ @@ -586,15 +534,14 @@ static void shutdown(struct channel *ch) unsigned long flags; struct tty_struct *tty; - volatile struct board_chan *bc; + struct board_chan *bc; if (!(ch->asyncflags & ASYNC_INITIALIZED)) return; - save_flags(flags); - cli(); - globalwinon(ch); + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); bc = ch->brdchan; /* ------------------------------------------------------------------ @@ -604,20 +551,17 @@ static void shutdown(struct channel *ch) --------------------------------------------------------------------- */ if (bc) - bc->idata = 0; - + writeb(0, &bc->idata); tty = ch->tty; /* ---------------------------------------------------------------- If we're a modem control device and HUPCL is on, drop RTS & DTR. ------------------------------------------------------------------ */ - if (tty->termios->c_cflag & HUPCL) - { + if (tty->termios->c_cflag & HUPCL) { ch->omodem &= ~(ch->m_rts | ch->m_dtr); fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1); } - memoff(ch); /* ------------------------------------------------------------------ @@ -628,7 +572,7 @@ static void shutdown(struct channel *ch) /* Prevent future Digi programmed interrupts from coming active */ ch->asyncflags &= ~ASYNC_INITIALIZED; - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); } /* End shutdown */ @@ -636,7 +580,6 @@ static void shutdown(struct channel *ch) static void pc_hangup(struct tty_struct *tty) { /* Begin pc_hangup */ - struct channel *ch; /* --------------------------------------------------------- @@ -644,25 +587,21 @@ static void pc_hangup(struct tty_struct *tty) if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - if ((ch = verifyChannel(tty)) != NULL) - { /* Begin if ch != NULL */ - + if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */ unsigned long flags; - save_flags(flags); - cli(); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); tty_ldisc_flush(tty); shutdown(ch); + spin_lock_irqsave(&epca_lock, flags); ch->tty = NULL; ch->event = 0; ch->count = 0; - restore_flags(flags); ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED); + spin_unlock_irqrestore(&epca_lock, flags); wake_up_interruptible(&ch->open_wait); - } /* End if ch != NULL */ } /* End pc_hangup */ @@ -672,18 +611,14 @@ static void pc_hangup(struct tty_struct *tty) static int pc_write(struct tty_struct * tty, const unsigned char *buf, int bytesAvailable) { /* Begin pc_write */ - - register unsigned int head, tail; - register int dataLen; - register int size; - register int amountCopied; - - + unsigned int head, tail; + int dataLen; + int size; + int amountCopied; struct channel *ch; unsigned long flags; int remain; - volatile struct board_chan *bc; - + struct board_chan *bc; /* ---------------------------------------------------------------- pc_write is primarily called directly by the kernel routine @@ -706,24 +641,20 @@ static int pc_write(struct tty_struct * tty, bc = ch->brdchan; size = ch->txbufsize; - amountCopied = 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); - head = bc->tin & (size - 1); - tail = bc->tout; + head = readw(&bc->tin) & (size - 1); + tail = readw(&bc->tout); - if (tail != bc->tout) - tail = bc->tout; + if (tail != readw(&bc->tout)) + tail = readw(&bc->tout); tail &= (size - 1); /* If head >= tail, head has not wrapped around. */ - if (head >= tail) - { /* Begin head has not wrapped */ - + if (head >= tail) { /* Begin head has not wrapped */ /* --------------------------------------------------------------- remain (much like dataLen above) represents the total amount of space available on the card for data. Here dataLen represents @@ -731,26 +662,19 @@ static int pc_write(struct tty_struct * tty, buffer. This is important because a memcpy cannot be told to automatically wrap around when it hits the buffer end. ------------------------------------------------------------------ */ - dataLen = size - head; remain = size - (head - tail) - 1; - - } /* End head has not wrapped */ - else - { /* Begin head has wrapped around */ + } else { /* Begin head has wrapped around */ remain = tail - head - 1; dataLen = remain; } /* End head has wrapped around */ - /* ------------------------------------------------------------------- Check the space on the card. If we have more data than space; reduce the amount of data to fit the space. ---------------------------------------------------------------------- */ - bytesAvailable = min(remain, bytesAvailable); - txwinon(ch); while (bytesAvailable > 0) { /* Begin while there is data to copy onto card */ @@ -767,26 +691,21 @@ static int pc_write(struct tty_struct * tty, amountCopied += dataLen; bytesAvailable -= dataLen; - if (head >= size) - { + if (head >= size) { head = 0; dataLen = tail; } - } /* End while there is data to copy onto card */ - ch->statusflags |= TXBUSY; globalwinon(ch); - bc->tin = head; + writew(head, &bc->tin); - if ((ch->statusflags & LOWWAIT) == 0) - { + if ((ch->statusflags & LOWWAIT) == 0) { ch->statusflags |= LOWWAIT; - bc->ilow = 1; + writeb(1, &bc->ilow); } memoff(ch); - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); return(amountCopied); } /* End pc_write */ @@ -795,11 +714,7 @@ static int pc_write(struct tty_struct * tty, static void pc_put_char(struct tty_struct *tty, unsigned char c) { /* Begin pc_put_char */ - - pc_write(tty, &c, 1); - return; - } /* End pc_put_char */ /* ------------------ Begin pc_write_room ------------------------- */ @@ -811,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty) struct channel *ch; unsigned long flags; unsigned int head, tail; - volatile struct board_chan *bc; + struct board_chan *bc; remain = 0; @@ -820,33 +735,29 @@ static int pc_write_room(struct tty_struct *tty) if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - if ((ch = verifyChannel(tty)) != NULL) - { - save_flags(flags); - cli(); + if ((ch = verifyChannel(tty)) != NULL) { + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); bc = ch->brdchan; - head = bc->tin & (ch->txbufsize - 1); - tail = bc->tout; + head = readw(&bc->tin) & (ch->txbufsize - 1); + tail = readw(&bc->tout); - if (tail != bc->tout) - tail = bc->tout; + if (tail != readw(&bc->tout)) + tail = readw(&bc->tout); /* Wrap tail if necessary */ tail &= (ch->txbufsize - 1); if ((remain = tail - head - 1) < 0 ) remain += ch->txbufsize; - if (remain && (ch->statusflags & LOWWAIT) == 0) - { + if (remain && (ch->statusflags & LOWWAIT) == 0) { ch->statusflags |= LOWWAIT; - bc->ilow = 1; + writeb(1, &bc->ilow); } memoff(ch); - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); } - /* Return how much room is left on card */ return remain; @@ -862,8 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty) int remain; unsigned long flags; struct channel *ch; - volatile struct board_chan *bc; - + struct board_chan *bc; /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct @@ -873,34 +783,27 @@ static int pc_chars_in_buffer(struct tty_struct *tty) if ((ch = verifyChannel(tty)) == NULL) return(0); - save_flags(flags); - cli(); + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); bc = ch->brdchan; - tail = bc->tout; - head = bc->tin; - ctail = ch->mailbox->cout; + tail = readw(&bc->tout); + head = readw(&bc->tin); + ctail = readw(&ch->mailbox->cout); - if (tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0) + if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0) chars = 0; - else - { /* Begin if some space on the card has been used */ - - head = bc->tin & (ch->txbufsize - 1); + else { /* Begin if some space on the card has been used */ + head = readw(&bc->tin) & (ch->txbufsize - 1); tail &= (ch->txbufsize - 1); - /* -------------------------------------------------------------- The logic here is basically opposite of the above pc_write_room here we are finding the amount of bytes in the buffer filled. Not the amount of bytes empty. ------------------------------------------------------------------- */ - if ((remain = tail - head - 1) < 0 ) remain += ch->txbufsize; - chars = (int)(ch->txbufsize - remain); - /* ------------------------------------------------------------- Make it possible to wakeup anything waiting for output in tty_ioctl.c, etc. @@ -908,15 +811,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty) If not already set. Setup an event to indicate when the transmit buffer empties ----------------------------------------------------------------- */ - if (!(ch->statusflags & EMPTYWAIT)) setup_empty_event(tty,ch); } /* End if some space on the card has been used */ - memoff(ch); - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); /* Return number of characters residing on card. */ return(chars); @@ -930,67 +830,46 @@ static void pc_flush_buffer(struct tty_struct *tty) unsigned int tail; unsigned long flags; struct channel *ch; - volatile struct board_chan *bc; - - + struct board_chan *bc; /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - if ((ch = verifyChannel(tty)) == NULL) return; - save_flags(flags); - cli(); - + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); - bc = ch->brdchan; - tail = bc->tout; - + tail = readw(&bc->tout); /* Have FEP move tout pointer; effectively flushing transmit buffer */ - fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); - memoff(ch); - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); - } /* End pc_flush_buffer */ /* ------------------ Begin pc_flush_chars ---------------------- */ static void pc_flush_chars(struct tty_struct *tty) { /* Begin pc_flush_chars */ - struct channel * ch; - /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - - if ((ch = verifyChannel(tty)) != NULL) - { + if ((ch = verifyChannel(tty)) != NULL) { unsigned long flags; - - save_flags(flags); - cli(); - + spin_lock_irqsave(&epca_lock, flags); /* ---------------------------------------------------------------- If not already set and the transmitter is busy setup an event to indicate when the transmit empties. ------------------------------------------------------------------- */ - if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT)) setup_empty_event(tty,ch); - - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); } - } /* End pc_flush_chars */ /* ------------------ Begin block_til_ready ---------------------- */ @@ -998,14 +877,11 @@ static void pc_flush_chars(struct tty_struct *tty) static int block_til_ready(struct tty_struct *tty, struct file *filp, struct channel *ch) { /* Begin block_til_ready */ - DECLARE_WAITQUEUE(wait,current); int retval, do_clocal = 0; unsigned long flags; - - if (tty_hung_up_p(filp)) - { + if (tty_hung_up_p(filp)) { if (ch->asyncflags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else @@ -1017,8 +893,7 @@ static int block_til_ready(struct tty_struct *tty, If the device is in the middle of being closed, then block until it's done, and then try again. -------------------------------------------------------------------- */ - if (ch->asyncflags & ASYNC_CLOSING) - { + if (ch->asyncflags & ASYNC_CLOSING) { interruptible_sleep_on(&ch->close_wait); if (ch->asyncflags & ASYNC_HUP_NOTIFY) @@ -1027,43 +902,29 @@ static int block_til_ready(struct tty_struct *tty, return -ERESTARTSYS; } - if (filp->f_flags & O_NONBLOCK) - { + if (filp->f_flags & O_NONBLOCK) { /* ----------------------------------------------------------------- If non-blocking mode is set, then make the check up front and then exit. -------------------------------------------------------------------- */ - ch->asyncflags |= ASYNC_NORMAL_ACTIVE; - return 0; } - - if (tty->termios->c_cflag & CLOCAL) do_clocal = 1; - - /* Block waiting for the carrier detect and the line to become free */ + /* Block waiting for the carrier detect and the line to become free */ retval = 0; add_wait_queue(&ch->open_wait, &wait); - save_flags(flags); - cli(); - + spin_lock_irqsave(&epca_lock, flags); /* We dec count so that pc_close will know when to free things */ if (!tty_hung_up_p(filp)) ch->count--; - - restore_flags(flags); - ch->blocked_open++; - while(1) { /* Begin forever while */ - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || !(ch->asyncflags & ASYNC_INITIALIZED)) { @@ -1073,17 +934,14 @@ static int block_til_ready(struct tty_struct *tty, retval = -ERESTARTSYS; break; } - if (!(ch->asyncflags & ASYNC_CLOSING) && (do_clocal || (ch->imodem & ch->dcd))) break; - - if (signal_pending(current)) - { + if (signal_pending(current)) { retval = -ERESTARTSYS; break; } - + spin_unlock_irqrestore(&epca_lock, flags); /* --------------------------------------------------------------- Allow someone else to be scheduled. We will occasionally go through this loop until one of the above conditions change. @@ -1091,25 +949,23 @@ static int block_til_ready(struct tty_struct *tty, prevent this loop from hogging the cpu. ------------------------------------------------------------------ */ schedule(); + spin_lock_irqsave(&epca_lock, flags); } /* End forever while */ current->state = TASK_RUNNING; remove_wait_queue(&ch->open_wait, &wait); - cli(); if (!tty_hung_up_p(filp)) ch->count++; - restore_flags(flags); - ch->blocked_open--; + spin_unlock_irqrestore(&epca_lock, flags); + if (retval) return retval; ch->asyncflags |= ASYNC_NORMAL_ACTIVE; - return 0; - } /* End block_til_ready */ /* ------------------ Begin pc_open ---------------------- */ @@ -1120,17 +976,12 @@ static int pc_open(struct tty_struct *tty, struct file * filp) struct channel *ch; unsigned long flags; int line, retval, boardnum; - volatile struct board_chan *bc; - volatile unsigned int head; + struct board_chan *bc; + unsigned int head; line = tty->index; - if (line < 0 || line >= nbdevs) - { - printk(KERN_ERR " - pc_open : line out of range in pc_open\n"); - tty->driver_data = NULL; - return(-ENODEV); - } - + if (line < 0 || line >= nbdevs) + return -ENODEV; ch = &digi_channels[line]; boardnum = ch->boardnum; @@ -1143,66 +994,49 @@ static int pc_open(struct tty_struct *tty, struct file * filp) goes here. ---------------------------------------------------------------------- */ - if (invalid_lilo_config) - { + if (invalid_lilo_config) { if (setup_error_code & INVALID_BOARD_TYPE) - printk(KERN_ERR " - pc_open: Invalid board type specified in LILO command\n"); - + printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n"); if (setup_error_code & INVALID_NUM_PORTS) - printk(KERN_ERR " - pc_open: Invalid number of ports specified in LILO command\n"); - + printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n"); if (setup_error_code & INVALID_MEM_BASE) - printk(KERN_ERR " - pc_open: Invalid board memory address specified in LILO command\n"); - + printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n"); if (setup_error_code & INVALID_PORT_BASE) - printk(KERN_ERR " - pc_open: Invalid board port address specified in LILO command\n"); - + printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n"); if (setup_error_code & INVALID_BOARD_STATUS) - printk(KERN_ERR " - pc_open: Invalid board status specified in LILO command\n"); - + printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n"); if (setup_error_code & INVALID_ALTPIN) - printk(KERN_ERR " - pc_open: Invalid board altpin specified in LILO command\n"); - + printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n"); tty->driver_data = NULL; /* Mark this device as 'down' */ - return(-ENODEV); + return -ENODEV; } - - if ((boardnum >= num_cards) || (boards[boardnum].status == DISABLED)) - { + if (boardnum >= num_cards || boards[boardnum].status == DISABLED) { tty->driver_data = NULL; /* Mark this device as 'down' */ return(-ENODEV); } - if (( bc = ch->brdchan) == 0) - { + if ((bc = ch->brdchan) == 0) { tty->driver_data = NULL; - return(-ENODEV); + return -ENODEV; } + spin_lock_irqsave(&epca_lock, flags); /* ------------------------------------------------------------------ Every time a channel is opened, increment a counter. This is necessary because we do not wish to flush and shutdown the channel until the last app holding the channel open, closes it. --------------------------------------------------------------------- */ - ch->count++; - /* ---------------------------------------------------------------- Set a kernel structures pointer to our local channel structure. This way we can get to it when passed only a tty struct. ------------------------------------------------------------------ */ - tty->driver_data = ch; - /* ---------------------------------------------------------------- If this is the first time the channel has been opened, initialize the tty->termios struct otherwise let pc_close handle it. -------------------------------------------------------------------- */ - - save_flags(flags); - cli(); - globalwinon(ch); ch->statusflags = 0; @@ -1213,8 +1047,8 @@ static int pc_open(struct tty_struct *tty, struct file * filp) Set receive head and tail ptrs to each other. This indicates no data available to read. ----------------------------------------------------------------- */ - head = bc->rin; - bc->rout = head; + head = readw(&bc->rin); + writew(head, &bc->rout); /* Set the channels associated tty structure */ ch->tty = tty; @@ -1224,122 +1058,74 @@ static int pc_open(struct tty_struct *tty, struct file * filp) issues, etc.... It effect both control flags and input flags. -------------------------------------------------------------------- */ epcaparam(tty,ch); - ch->asyncflags |= ASYNC_INITIALIZED; memoff(ch); - - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); retval = block_til_ready(tty, filp, ch); if (retval) - { return retval; - } - /* ------------------------------------------------------------- Set this again in case a hangup set it to zero while this open() was waiting for the line... --------------------------------------------------------------- */ + spin_lock_irqsave(&epca_lock, flags); ch->tty = tty; - - save_flags(flags); - cli(); globalwinon(ch); - /* Enable Digi Data events */ - bc->idata = 1; - + writeb(1, &bc->idata); memoff(ch); - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); return 0; - } /* End pc_open */ -#ifdef MODULE static int __init epca_module_init(void) { /* Begin init_module */ - - unsigned long flags; - - save_flags(flags); - cli(); - - pc_init(); - - restore_flags(flags); - - return(0); + return pc_init(); } module_init(epca_module_init); -#endif -#ifdef ENABLE_PCI static struct pci_driver epca_driver; -#endif - -#ifdef MODULE -/* -------------------- Begin cleanup_module ---------------------- */ static void __exit epca_module_exit(void) { - int count, crd; struct board_info *bd; struct channel *ch; - unsigned long flags; del_timer_sync(&epca_timer); - save_flags(flags); - cli(); - if ((tty_unregister_driver(pc_driver)) || (tty_unregister_driver(pc_info))) { - printk(KERN_WARNING " - DIGI : cleanup_module failed to un-register tty driver\n"); - restore_flags(flags); + printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n"); return; } put_tty_driver(pc_driver); put_tty_driver(pc_info); - for (crd = 0; crd < num_cards; crd++) - { /* Begin for each card */ - + for (crd = 0; crd < num_cards; crd++) { /* Begin for each card */ bd = &boards[crd]; - if (!bd) { /* Begin sanity check */ printk(KERN_ERR " - Digi : cleanup_module failed\n"); return; } /* End sanity check */ - - ch = card_ptr[crd]; - + ch = card_ptr[crd]; for (count = 0; count < bd->numports; count++, ch++) { /* Begin for each port */ - - if (ch) - { + if (ch) { if (ch->tty) tty_hangup(ch->tty); kfree(ch->tmp_buf); } - } /* End for each port */ } /* End for each card */ - -#ifdef ENABLE_PCI pci_unregister_driver (&epca_driver); -#endif - - restore_flags(flags); - } + module_exit(epca_module_exit); -#endif /* MODULE */ static struct tty_operations pc_ops = { .open = pc_open, @@ -1371,34 +1157,15 @@ static struct tty_operations info_ops = { /* ------------------ Begin pc_init ---------------------- */ -int __init pc_init(void) +static int __init pc_init(void) { /* Begin pc_init */ - - /* ---------------------------------------------------------------- - pc_init is called by the operating system during boot up prior to - any open calls being made. In the older versions of Linux (Prior - to 2.0.0) an entry is made into tty_io.c. A pointer to the last - memory location (from kernel space) used (kmem_start) is passed - to pc_init. It is pc_inits responsibility to modify this value - for any memory that the Digi driver might need and then return - this value to the operating system. For example if the driver - wishes to allocate 1K of kernel memory, pc_init would return - (kmem_start + 1024). This memory (Between kmem_start and kmem_start - + 1024) would then be available for use exclusively by the driver. - In this case our driver does not allocate any of this kernel - memory. - ------------------------------------------------------------------*/ - - ulong flags; int crd; struct board_info *bd; unsigned char board_id = 0; -#ifdef ENABLE_PCI int pci_boards_found, pci_count; pci_count = 0; -#endif /* ENABLE_PCI */ pc_driver = alloc_tty_driver(MAX_ALLOC); if (!pc_driver) @@ -1416,8 +1183,7 @@ int __init pc_init(void) Note : If LILO has ran epca_setup then epca_setup will handle defining num_cards as well as copying the data into the board structure. -------------------------------------------------------------------------- */ - if (!liloconfig) - { /* Begin driver has been configured via. epcaconfig */ + if (!liloconfig) { /* Begin driver has been configured via. epcaconfig */ nbdevs = NBDEVS; num_cards = NUMCARDS; @@ -1440,8 +1206,6 @@ int __init pc_init(void) printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION); -#ifdef ENABLE_PCI - /* ------------------------------------------------------------------ NOTE : This code assumes that the number of ports found in the boards array is correct. This could be wrong if @@ -1467,8 +1231,6 @@ int __init pc_init(void) pci_boards_found += init_PCI(); num_cards += pci_boards_found; -#endif /* ENABLE_PCI */ - pc_driver->owner = THIS_MODULE; pc_driver->name = "ttyD"; pc_driver->devfs_name = "tts/D"; @@ -1499,9 +1261,6 @@ int __init pc_init(void) tty_set_operations(pc_info, &info_ops); - save_flags(flags); - cli(); - for (crd = 0; crd < num_cards; crd++) { /* Begin for each card */ @@ -1610,11 +1369,7 @@ int __init pc_init(void) if ((board_id & 0x30) == 0x30) bd->memory_seg = 0x8000; - } /* End it is an XI card */ - else - { - printk(KERN_ERR " - Board at 0x%x doesn't appear to be an XI\n",(int)bd->port); - } + } else printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port); break; } /* End switch on bd->type */ @@ -1634,9 +1389,6 @@ int __init pc_init(void) init_timer(&epca_timer); epca_timer.function = epcapoll; mod_timer(&epca_timer, jiffies + HZ/25); - - restore_flags(flags); - return 0; } /* End pc_init */ @@ -1647,10 +1399,10 @@ static void post_fep_init(unsigned int crd) { /* Begin post_fep_init */ int i; - unchar *memaddr; - volatile struct global_data *gd; + unsigned char *memaddr; + struct global_data *gd; struct board_info *bd; - volatile struct board_chan *bc; + struct board_chan *bc; struct channel *ch; int shrinkmem = 0, lowwater ; @@ -1669,9 +1421,7 @@ static void post_fep_init(unsigned int crd) after DIGI_INIT has been called will return the proper values. ------------------------------------------------------------------- */ - if (bd->type >= PCIXEM) /* If the board in question is PCI */ - { /* Begin get PCI number of ports */ - + if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */ /* -------------------------------------------------------------------- Below we use XEMPORTS as a memory offset regardless of which PCI card it is. This is because all of the supported PCI cards have @@ -1685,15 +1435,15 @@ static void post_fep_init(unsigned int crd) (FYI - The id should be located at 0x1ac (And may use up to 4 bytes if the box in question is a XEM or CX)). ------------------------------------------------------------------------ */ - - bd->numports = (unsigned short)*(unsigned char *)bus_to_virt((unsigned long) - (bd->re_map_membase + XEMPORTS)); - - + /* PCI cards are already remapped at this point ISA are not */ + bd->numports = readw(bd->re_map_membase + XEMPORTS); epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports"); nbdevs += (bd->numports); - - } /* End get PCI number of ports */ + } else { + /* Fix up the mappings for ISA/EISA etc */ + /* FIXME: 64K - can we be smarter ? */ + bd->re_map_membase = ioremap(bd->membase, 0x10000); + } if (crd != 0) card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports; @@ -1701,19 +1451,9 @@ static void post_fep_init(unsigned int crd) card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */ ch = card_ptr[crd]; - - epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range"); - memaddr = (unchar *)bd->re_map_membase; - - /* - The below command is necessary because newer kernels (2.1.x and - up) do not have a 1:1 virtual to physical mapping. The below - call adjust for that. - */ - - memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr); + memaddr = bd->re_map_membase; /* ----------------------------------------------------------------- The below assignment will set bc to point at the BEGINING of @@ -1721,7 +1461,7 @@ static void post_fep_init(unsigned int crd) 8 and 64 of these structures. -------------------------------------------------------------------- */ - bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT); + bc = (struct board_chan *)(memaddr + CHANSTRUCT); /* ------------------------------------------------------------------- The below assignment will set gd to point at the BEGINING of @@ -1730,20 +1470,18 @@ static void post_fep_init(unsigned int crd) pointer begins at 0xd10. ---------------------------------------------------------------------- */ - gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL); + gd = (struct global_data *)(memaddr + GLOBAL); /* -------------------------------------------------------------------- XEPORTS (address 0xc22) points at the number of channels the card supports. (For 64XE, XI, XEM, and XR use 0xc02) ----------------------------------------------------------------------- */ - if (((bd->type == PCXEVE) | (bd->type == PCXE)) && - (*(ushort *)((ulong)memaddr + XEPORTS) < 3)) + if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3)) shrinkmem = 1; if (bd->type < PCIXEM) if (!request_region((int)bd->port, 4, board_desc[bd->type])) return; - memwinon(bd, 0); /* -------------------------------------------------------------------- @@ -1753,17 +1491,16 @@ static void post_fep_init(unsigned int crd) /* For every port on the card do ..... */ - for (i = 0; i < bd->numports; i++, ch++, bc++) - { /* Begin for each port */ + for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */ + unsigned long flags; ch->brdchan = bc; ch->mailbox = gd; INIT_WORK(&ch->tqueue, do_softint, ch); ch->board = &boards[crd]; - switch (bd->type) - { /* Begin switch bd->type */ - + spin_lock_irqsave(&epca_lock, flags); + switch (bd->type) { /* ---------------------------------------------------------------- Since some of the boards use different bitmaps for their control signals we cannot hard code these values and retain @@ -1796,14 +1533,12 @@ static void post_fep_init(unsigned int crd) } /* End switch bd->type */ - if (boards[crd].altpin) - { + if (boards[crd].altpin) { ch->dsr = ch->m_dcd; ch->dcd = ch->m_dsr; ch->digiext.digi_flags |= DIGI_ALTPIN; } - else - { + else { ch->dcd = ch->m_dcd; ch->dsr = ch->m_dsr; } @@ -1813,14 +1548,12 @@ static void post_fep_init(unsigned int crd) ch->magic = EPCA_MAGIC; ch->tty = NULL; - if (shrinkmem) - { + if (shrinkmem) { fepcmd(ch, SETBUFFER, 32, 0, 0, 0); shrinkmem = 0; } - switch (bd->type) - { /* Begin switch bd->type */ + switch (bd->type) { case PCIXEM: case PCIXRJ: @@ -1878,13 +1611,13 @@ static void post_fep_init(unsigned int crd) fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0); - bc->edelay = 100; - bc->idata = 1; + writew(100, &bc->edelay); + writeb(1, &bc->idata); - ch->startc = bc->startc; - ch->stopc = bc->stopc; - ch->startca = bc->startca; - ch->stopca = bc->stopca; + ch->startc = readb(&bc->startc); + ch->stopc = readb(&bc->stopc); + ch->startca = readb(&bc->startca); + ch->stopca = readb(&bc->stopca); ch->fepcflag = 0; ch->fepiflag = 0; @@ -1899,27 +1632,23 @@ static void post_fep_init(unsigned int crd) ch->blocked_open = 0; init_waitqueue_head(&ch->open_wait); init_waitqueue_head(&ch->close_wait); + + spin_unlock_irqrestore(&epca_lock, flags); + ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL); - if (!(ch->tmp_buf)) - { + if (!ch->tmp_buf) { printk(KERN_ERR "POST FEP INIT : kmalloc failed for port 0x%x\n",i); release_region((int)bd->port, 4); while(i-- > 0) kfree((ch--)->tmp_buf); return; - } - else + } else memset((void *)ch->tmp_buf,0,ch->txbufsize); } /* End for each port */ printk(KERN_INFO "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); - sprintf(mesg, - "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", - VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); - console_print(mesg); - memwinoff(bd, 0); } /* End post_fep_init */ @@ -1943,9 +1672,6 @@ static void epcapoll(unsigned long ignored) buffer empty) and acts on those events. ----------------------------------------------------------------------- */ - save_flags(flags); - cli(); - for (crd = 0; crd < num_cards; crd++) { /* Begin for each card */ @@ -1961,6 +1687,8 @@ static void epcapoll(unsigned long ignored) some legacy boards. ---------------------------------------------------------------- */ + spin_lock_irqsave(&epca_lock, flags); + assertmemoff(ch); globalwinon(ch); @@ -1970,21 +1698,19 @@ static void epcapoll(unsigned long ignored) the transmit or receive queue. ------------------------------------------------------------------- */ - head = ch->mailbox->ein; - tail = ch->mailbox->eout; + head = readw(&ch->mailbox->ein); + tail = readw(&ch->mailbox->eout); /* If head isn't equal to tail we have an event */ if (head != tail) doevent(crd); - memoff(ch); - } /* End for each card */ + spin_unlock_irqrestore(&epca_lock, flags); + } /* End for each card */ mod_timer(&epca_timer, jiffies + (HZ / 25)); - - restore_flags(flags); } /* End epcapoll */ /* --------------------- Begin doevent ------------------------ */ @@ -1992,53 +1718,42 @@ static void epcapoll(unsigned long ignored) static void doevent(int crd) { /* Begin doevent */ - volatile unchar *eventbuf; + void *eventbuf; struct channel *ch, *chan0; static struct tty_struct *tty; - volatile struct board_info *bd; - volatile struct board_chan *bc; - register volatile unsigned int tail, head; - register int event, channel; - register int mstat, lstat; + struct board_info *bd; + struct board_chan *bc; + unsigned int tail, head; + int event, channel; + int mstat, lstat; /* ------------------------------------------------------------------- This subroutine is called by epcapoll when an event is detected in the event queue. This routine responds to those events. --------------------------------------------------------------------- */ - bd = &boards[crd]; chan0 = card_ptr[crd]; epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range"); - assertgwinon(chan0); - - while ((tail = chan0->mailbox->eout) != (head = chan0->mailbox->ein)) + while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) { /* Begin while something in event queue */ - assertgwinon(chan0); - - eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->re_map_membase + tail + ISTART)); - + eventbuf = bd->re_map_membase + tail + ISTART; /* Get the channel the event occurred on */ - channel = eventbuf[0]; - + channel = readb(eventbuf); /* Get the actual event code that occurred */ - event = eventbuf[1]; - + event = readb(eventbuf + 1); /* ---------------------------------------------------------------- The two assignments below get the current modem status (mstat) and the previous modem status (lstat). These are useful becuase an event could signal a change in modem signals itself. ------------------------------------------------------------------- */ - - mstat = eventbuf[2]; - lstat = eventbuf[3]; + mstat = readb(eventbuf + 2); + lstat = readb(eventbuf + 3); ch = chan0 + channel; - - if ((unsigned)channel >= bd->numports || !ch) - { + if ((unsigned)channel >= bd->numports || !ch) { if (channel >= bd->numports) ch = chan0; bc = ch->brdchan; @@ -2048,97 +1763,53 @@ static void doevent(int crd) if ((bc = ch->brdchan) == NULL) goto next; - if (event & DATA_IND) - { /* Begin DATA_IND */ - + if (event & DATA_IND) { /* Begin DATA_IND */ receive_data(ch); assertgwinon(ch); - } /* End DATA_IND */ /* else *//* Fix for DCD transition missed bug */ - if (event & MODEMCHG_IND) - { /* Begin MODEMCHG_IND */ - + if (event & MODEMCHG_IND) { /* Begin MODEMCHG_IND */ /* A modem signal change has been indicated */ - ch->imodem = mstat; - - if (ch->asyncflags & ASYNC_CHECK_CD) - { + if (ch->asyncflags & ASYNC_CHECK_CD) { if (mstat & ch->dcd) /* We are now receiving dcd */ wake_up_interruptible(&ch->open_wait); else pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */ } - } /* End MODEMCHG_IND */ - tty = ch->tty; - if (tty) - { /* Begin if valid tty */ - - if (event & BREAK_IND) - { /* Begin if BREAK_IND */ - + if (tty) { /* Begin if valid tty */ + if (event & BREAK_IND) { /* Begin if BREAK_IND */ /* A break has been indicated */ - tty->flip.count++; *tty->flip.flag_buf_ptr++ = TTY_BREAK; - *tty->flip.char_buf_ptr++ = 0; - tty_schedule_flip(tty); - - } /* End if BREAK_IND */ - else - if (event & LOWTX_IND) - { /* Begin LOWTX_IND */ - + } else if (event & LOWTX_IND) { /* Begin LOWTX_IND */ if (ch->statusflags & LOWWAIT) { /* Begin if LOWWAIT */ - ch->statusflags &= ~LOWWAIT; tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); - } /* End if LOWWAIT */ - - } /* End LOWTX_IND */ - else - if (event & EMPTYTX_IND) - { /* Begin EMPTYTX_IND */ - + } else if (event & EMPTYTX_IND) { /* Begin EMPTYTX_IND */ /* This event is generated by setup_empty_event */ - ch->statusflags &= ~TXBUSY; - if (ch->statusflags & EMPTYWAIT) - { /* Begin if EMPTYWAIT */ - + if (ch->statusflags & EMPTYWAIT) { /* Begin if EMPTYWAIT */ ch->statusflags &= ~EMPTYWAIT; tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } /* End if EMPTYWAIT */ - } /* End EMPTYTX_IND */ - } /* End if valid tty */ - - next: globalwinon(ch); - - if (!bc) - printk(KERN_ERR " - bc == NULL in doevent!\n"); - else - bc->idata = 1; - - chan0->mailbox->eout = (tail + 4) & (IMAX - ISTART - 4); + BUG_ON(!bc); + writew(1, &bc->idata); + writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout); globalwinon(chan0); - } /* End while something in event queue */ - } /* End doevent */ /* --------------------- Begin fepcmd ------------------------ */ @@ -2146,7 +1817,6 @@ static void doevent(int crd) static void fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds, int bytecmd) { /* Begin fepcmd */ - unchar *memaddr; unsigned int head, cmdTail, cmdStart, cmdMax; long count; @@ -2155,93 +1825,57 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte, /* This is the routine in which commands may be passed to the card. */ if (ch->board->status == DISABLED) - { return; - } - assertgwinon(ch); - /* Remember head (As well as max) is just an offset not a base addr */ - head = ch->mailbox->cin; - + head = readw(&ch->mailbox->cin); /* cmdStart is a base address */ - cmdStart = ch->mailbox->cstart; - + cmdStart = readw(&ch->mailbox->cstart); /* ------------------------------------------------------------------ We do the addition below because we do not want a max pointer relative to cmdStart. We want a max pointer that points at the physical end of the command queue. -------------------------------------------------------------------- */ - - cmdMax = (cmdStart + 4 + (ch->mailbox->cmax)); - + cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax)); memaddr = ch->board->re_map_membase; - /* - The below command is necessary because newer kernels (2.1.x and - up) do not have a 1:1 virtual to physical mapping. The below - call adjust for that. - */ - - memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr); - - if (head >= (cmdMax - cmdStart) || (head & 03)) - { - printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, - cmd, head); - printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, - cmdMax, cmdStart); + if (head >= (cmdMax - cmdStart) || (head & 03)) { + printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, cmd, head); + printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, cmdMax, cmdStart); return; } - - if (bytecmd) - { - *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd; - - *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum; + if (bytecmd) { + writeb(cmd, memaddr + head + cmdStart + 0); + writeb(ch->channelnum, memaddr + head + cmdStart + 1); /* Below word_or_byte is bits to set */ - *(volatile unchar *)(memaddr + head + cmdStart + 2) = (unchar)word_or_byte; + writeb(word_or_byte, memaddr + head + cmdStart + 2); /* Below byte2 is bits to reset */ - *(volatile unchar *)(memaddr + head + cmdStart + 3) = (unchar)byte2; - - } - else - { - *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd; - *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum; - *(volatile ushort*)(memaddr + head + cmdStart + 2) = (ushort)word_or_byte; + writeb(byte2, memaddr + head + cmdStart + 3); + } else { + writeb(cmd, memaddr + head + cmdStart + 0); + writeb(ch->channelnum, memaddr + head + cmdStart + 1); + writeb(word_or_byte, memaddr + head + cmdStart + 2); } - head = (head + 4) & (cmdMax - cmdStart - 4); - ch->mailbox->cin = head; - + writew(head, &ch->mailbox->cin); count = FEPTIMEOUT; - for (;;) - { /* Begin forever loop */ - + for (;;) { /* Begin forever loop */ count--; - if (count == 0) - { + if (count == 0) { printk(KERN_ERR " - Fep not responding in fepcmd()\n"); return; } - - head = ch->mailbox->cin; - cmdTail = ch->mailbox->cout; - + head = readw(&ch->mailbox->cin); + cmdTail = readw(&ch->mailbox->cout); n = (head - cmdTail) & (cmdMax - cmdStart - 4); - /* ---------------------------------------------------------- Basically this will break when the FEP acknowledges the command by incrementing cmdTail (Making it equal to head). ------------------------------------------------------------- */ - if (n <= ncmds * (sizeof(short) * 4)) break; /* Well nearly forever :-) */ - } /* End forever loop */ - } /* End fepcmd */ /* --------------------------------------------------------------------- @@ -2255,11 +1889,9 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte, static unsigned termios2digi_h(struct channel *ch, unsigned cflag) { /* Begin termios2digi_h */ - unsigned res = 0; - if (cflag & CRTSCTS) - { + if (cflag & CRTSCTS) { ch->digiext.digi_flags |= (RTSPACE | CTSPACE); res |= ((ch->m_cts) | (ch->m_rts)); } @@ -2295,7 +1927,6 @@ static unsigned termios2digi_i(struct channel *ch, unsigned iflag) unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP|IXON|IXANY|IXOFF); - if (ch->digiext.digi_flags & DIGI_AIXON) res |= IAIXON; return res; @@ -2308,28 +1939,15 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag) { /* Begin termios2digi_c */ unsigned res = 0; - -#ifdef SPEED_HACK - /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */ - if ((cflag & CBAUD)== B38400) cflag=cflag - B38400 + B115200; - if ((cflag & CBAUD)== B19200) cflag=cflag - B19200 + B57600; -#endif /* SPEED_HACK */ - - if (cflag & CBAUDEX) - { /* Begin detected CBAUDEX */ - + if (cflag & CBAUDEX) { /* Begin detected CBAUDEX */ ch->digiext.digi_flags |= DIGI_FAST; - /* ------------------------------------------------------------- HUPCL bit is used by FEP to indicate fast baud table is to be used. ----------------------------------------------------------------- */ - res |= FEP_HUPCL; - } /* End detected CBAUDEX */ else ch->digiext.digi_flags &= ~DIGI_FAST; - /* ------------------------------------------------------------------- CBAUD has bit position 0x1000 set these days to indicate Linux baud rate remap. Digi hardware can't handle the bit assignment. @@ -2337,7 +1955,6 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag) bit out. ---------------------------------------------------------------------- */ res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE); - /* ------------------------------------------------------------- This gets a little confusing. The Digi cards have their own representation of c_cflags controling baud rate. For the most @@ -2357,10 +1974,8 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag) should be checked for a screened out prior to termios2digi_c returning. Since CLOCAL isn't used by the board this can be ignored as long as the returned value is used only by Digi hardware. - ----------------------------------------------------------------- */ - - if (cflag & CBAUDEX) - { + ----------------------------------------------------------------- */ + if (cflag & CBAUDEX) { /* ------------------------------------------------------------- The below code is trying to guarantee that only baud rates 115200 and 230400 are remapped. We use exclusive or because @@ -2371,138 +1986,96 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag) if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) || (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX)))) - { res += 1; - } } - return res; } /* End termios2digi_c */ /* --------------------- Begin epcaparam ----------------------- */ +/* Caller must hold the locks */ static void epcaparam(struct tty_struct *tty, struct channel *ch) { /* Begin epcaparam */ unsigned int cmdHead; struct termios *ts; - volatile struct board_chan *bc; + struct board_chan *bc; unsigned mval, hflow, cflag, iflag; bc = ch->brdchan; epcaassert(bc !=0, "bc out of range"); assertgwinon(ch); - ts = tty->termios; - - if ((ts->c_cflag & CBAUD) == 0) - { /* Begin CBAUD detected */ - - cmdHead = bc->rin; + if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ + cmdHead = readw(&bc->rin); bc->rout = cmdHead; - cmdHead = bc->tin; - + cmdHead = readw(&bc->tin); /* Changing baud in mid-stream transmission can be wonderful */ /* --------------------------------------------------------------- Flush current transmit buffer by setting cmdTail pointer (tout) to cmdHead pointer (tin). Hopefully the transmit buffer is empty. ----------------------------------------------------------------- */ - fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0); mval = 0; - - } /* End CBAUD detected */ - else - { /* Begin CBAUD not detected */ - + } else { /* Begin CBAUD not detected */ /* ------------------------------------------------------------------- c_cflags have changed but that change had nothing to do with BAUD. Propagate the change to the card. ---------------------------------------------------------------------- */ - cflag = termios2digi_c(ch, ts->c_cflag); - - if (cflag != ch->fepcflag) - { + if (cflag != ch->fepcflag) { ch->fepcflag = cflag; /* Set baud rate, char size, stop bits, parity */ fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0); } - - /* ---------------------------------------------------------------- If the user has not forced CLOCAL and if the device is not a CALLOUT device (Which is always CLOCAL) we set flags such that the driver will wait on carrier detect. ------------------------------------------------------------------- */ - if (ts->c_cflag & CLOCAL) - { /* Begin it is a cud device or a ttyD device with CLOCAL on */ ch->asyncflags &= ~ASYNC_CHECK_CD; - } /* End it is a cud device or a ttyD device with CLOCAL on */ else - { /* Begin it is a ttyD device */ ch->asyncflags |= ASYNC_CHECK_CD; - } /* End it is a ttyD device */ - mval = ch->m_dtr | ch->m_rts; - } /* End CBAUD not detected */ - iflag = termios2digi_i(ch, ts->c_iflag); - /* Check input mode flags */ - - if (iflag != ch->fepiflag) - { + if (iflag != ch->fepiflag) { ch->fepiflag = iflag; - /* --------------------------------------------------------------- Command sets channels iflag structure on the board. Such things as input soft flow control, handling of parity errors, and break handling are all set here. ------------------------------------------------------------------- */ - /* break handling, parity handling, input stripping, flow control chars */ fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0); } - /* --------------------------------------------------------------- Set the board mint value for this channel. This will cause hardware events to be generated each time the DCD signal (Described in mint) changes. ------------------------------------------------------------------- */ - bc->mint = ch->dcd; - + writeb(ch->dcd, &bc->mint); if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD)) if (ch->digiext.digi_flags & DIGI_FORCEDCD) - bc->mint = 0; - - ch->imodem = bc->mstat; - + writeb(0, &bc->mint); + ch->imodem = readb(&bc->mstat); hflow = termios2digi_h(ch, ts->c_cflag); - - if (hflow != ch->hflow) - { + if (hflow != ch->hflow) { ch->hflow = hflow; - /* -------------------------------------------------------------- Hard flow control has been selected but the board is not using it. Activate hard flow control now. ----------------------------------------------------------------- */ - fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1); } - - mval ^= ch->modemfake & (mval ^ ch->modem); - if (ch->omodem ^ mval) - { + if (ch->omodem ^ mval) { ch->omodem = mval; - /* -------------------------------------------------------------- The below command sets the DTR and RTS mstat structure. If hard flow control is NOT active these changes will drive the @@ -2514,87 +2087,65 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) /* First reset DTR & RTS; then set them */ fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1); fepcmd(ch, SETMODEM, mval, 0, 0, 1); - } - - if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) - { + if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) { ch->fepstartc = ch->startc; ch->fepstopc = ch->stopc; - /* ------------------------------------------------------------ The XON / XOFF characters have changed; propagate these changes to the card. --------------------------------------------------------------- */ - fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); } - - if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) - { + if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) { ch->fepstartca = ch->startca; ch->fepstopca = ch->stopca; - /* --------------------------------------------------------------- Similar to the above, this time the auxilarly XON / XOFF characters have changed; propagate these changes to the card. ------------------------------------------------------------------ */ - fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); } - } /* End epcaparam */ /* --------------------- Begin receive_data ----------------------- */ - +/* Caller holds lock */ static void receive_data(struct channel *ch) { /* Begin receive_data */ unchar *rptr; struct termios *ts = NULL; struct tty_struct *tty; - volatile struct board_chan *bc; - register int dataToRead, wrapgap, bytesAvailable; - register unsigned int tail, head; + struct board_chan *bc; + int dataToRead, wrapgap, bytesAvailable; + unsigned int tail, head; unsigned int wrapmask; int rc; - /* --------------------------------------------------------------- This routine is called by doint when a receive data event has taken place. ------------------------------------------------------------------- */ globalwinon(ch); - if (ch->statusflags & RXSTOPPED) return; - tty = ch->tty; if (tty) ts = tty->termios; - bc = ch->brdchan; - - if (!bc) - { - printk(KERN_ERR " - bc is NULL in receive_data!\n"); - return; - } - + BUG_ON(!bc); wrapmask = ch->rxbufsize - 1; /* --------------------------------------------------------------------- Get the head and tail pointers to the receiver queue. Wrap the head pointer if it has reached the end of the buffer. ------------------------------------------------------------------------ */ - - head = bc->rin; + head = readw(&bc->rin); head &= wrapmask; - tail = bc->rout & wrapmask; + tail = readw(&bc->rout) & wrapmask; bytesAvailable = (head - tail) & wrapmask; - if (bytesAvailable == 0) return; @@ -2602,8 +2153,7 @@ static void receive_data(struct channel *ch) If CREAD bit is off or device not open, set TX tail to head --------------------------------------------------------------------- */ - if (!tty || !ts || !(ts->c_cflag & CREAD)) - { + if (!tty || !ts || !(ts->c_cflag & CREAD)) { bc->rout = head; return; } @@ -2611,64 +2161,45 @@ static void receive_data(struct channel *ch) if (tty->flip.count == TTY_FLIPBUF_SIZE) return; - if (bc->orun) - { - bc->orun = 0; - printk(KERN_WARNING "overrun! DigiBoard device %s\n",tty->name); + if (readb(&bc->orun)) { + writeb(0, &bc->orun); + printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name); } - rxwinon(ch); rptr = tty->flip.char_buf_ptr; rc = tty->flip.count; - - while (bytesAvailable > 0) - { /* Begin while there is data on the card */ - + while (bytesAvailable > 0) { /* Begin while there is data on the card */ wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail; - /* --------------------------------------------------------------- Even if head has wrapped around only report the amount of data to be equal to the size - tail. Remember memcpy can't automaticly wrap around the receive buffer. ----------------------------------------------------------------- */ - dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable; - /* -------------------------------------------------------------- Make sure we don't overflow the buffer ----------------------------------------------------------------- */ - if ((rc + dataToRead) > TTY_FLIPBUF_SIZE) dataToRead = TTY_FLIPBUF_SIZE - rc; - if (dataToRead == 0) break; - /* --------------------------------------------------------------- Move data read from our card into the line disciplines buffer for translation if necessary. ------------------------------------------------------------------ */ - - if ((memcpy(rptr, ch->rxptr + tail, dataToRead)) != rptr) - printk(KERN_ERR " - receive_data : memcpy failed\n"); - + memcpy_fromio(rptr, ch->rxptr + tail, dataToRead); rc += dataToRead; rptr += dataToRead; tail = (tail + dataToRead) & wrapmask; bytesAvailable -= dataToRead; - } /* End while there is data on the card */ - - tty->flip.count = rc; tty->flip.char_buf_ptr = rptr; globalwinon(ch); - bc->rout = tail; - + writew(tail, &bc->rout); /* Must be called with global data */ tty_schedule_flip(ch->tty); return; - } /* End receive_data */ static int info_ioctl(struct tty_struct *tty, struct file * file, @@ -2676,17 +2207,15 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, { switch (cmd) { /* Begin switch cmd */ - case DIGI_GETINFO: { /* Begin case DIGI_GETINFO */ - struct digi_info di ; int brd; - getUser(brd, (unsigned int __user *)arg); - - if ((brd < 0) || (brd >= num_cards) || (num_cards == 0)) - return (-ENODEV); + if(get_user(brd, (unsigned int __user *)arg)) + return -EFAULT; + if (brd < 0 || brd >= num_cards || num_cards == 0) + return -ENODEV; memset(&di, 0, sizeof(di)); @@ -2694,8 +2223,9 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, di.status = boards[brd].status; di.type = boards[brd].type ; di.numports = boards[brd].numports ; - di.port = boards[brd].port ; - di.membase = boards[brd].membase ; + /* Legacy fixups - just move along nothing to see */ + di.port = (unsigned char *)boards[brd].port ; + di.membase = (unsigned char *)boards[brd].membase ; if (copy_to_user((void __user *)arg, &di, sizeof (di))) return -EFAULT; @@ -2709,39 +2239,29 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, int brd = arg & 0xff000000 >> 16 ; unsigned char state = arg & 0xff ; - if ((brd < 0) || (brd >= num_cards)) - { - printk(KERN_ERR " - DIGI POLLER : brd not valid!\n"); + if (brd < 0 || brd >= num_cards) { + printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n"); return (-ENODEV); } - digi_poller_inhibited = state ; break ; - } /* End case DIGI_POLLER */ case DIGI_INIT: { /* Begin case DIGI_INIT */ - /* ------------------------------------------------------------ This call is made by the apps to complete the initilization of the board(s). This routine is responsible for setting the card to its initial state and setting the drivers control fields to the sutianle settings for the card in question. ---------------------------------------------------------------- */ - int crd ; for (crd = 0; crd < num_cards; crd++) post_fep_init (crd); - break ; - } /* End case DIGI_INIT */ - - default: - return -ENOIOCTLCMD; - + return -ENOTTY; } /* End switch cmd */ return (0) ; } @@ -2750,43 +2270,33 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, static int pc_tiocmget(struct tty_struct *tty, struct file *file) { struct channel *ch = (struct channel *) tty->driver_data; - volatile struct board_chan *bc; + struct board_chan *bc; unsigned int mstat, mflag = 0; unsigned long flags; if (ch) bc = ch->brdchan; else - { - printk(KERN_ERR " - ch is NULL in pc_tiocmget!\n"); - return(-EINVAL); - } + return -EINVAL; - save_flags(flags); - cli(); + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); - mstat = bc->mstat; + mstat = readb(&bc->mstat); memoff(ch); - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); if (mstat & ch->m_dtr) mflag |= TIOCM_DTR; - if (mstat & ch->m_rts) mflag |= TIOCM_RTS; - if (mstat & ch->m_cts) mflag |= TIOCM_CTS; - if (mstat & ch->dsr) mflag |= TIOCM_DSR; - if (mstat & ch->m_ri) mflag |= TIOCM_RI; - if (mstat & ch->dcd) mflag |= TIOCM_CD; - return mflag; } @@ -2796,13 +2306,10 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file, struct channel *ch = (struct channel *) tty->driver_data; unsigned long flags; - if (!ch) { - printk(KERN_ERR " - ch is NULL in pc_tiocmset!\n"); - return(-EINVAL); - } + if (!ch) + return -EINVAL; - save_flags(flags); - cli(); + spin_lock_irqsave(&epca_lock, flags); /* * I think this modemfake stuff is broken. It doesn't * correctly reflect the behaviour desired by the TIOCM* @@ -2824,17 +2331,14 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file, ch->modemfake |= ch->m_dtr; ch->modem &= ~ch->m_dtr; } - globalwinon(ch); - /* -------------------------------------------------------------- The below routine generally sets up parity, baud, flow control issues, etc.... It effect both control flags and input flags. ------------------------------------------------------------------ */ - epcaparam(tty,ch); memoff(ch); - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); return 0; } @@ -2847,19 +2351,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, unsigned long flags; unsigned int mflag, mstat; unsigned char startc, stopc; - volatile struct board_chan *bc; + struct board_chan *bc; struct channel *ch = (struct channel *) tty->driver_data; void __user *argp = (void __user *)arg; if (ch) bc = ch->brdchan; else - { - printk(KERN_ERR " - ch is NULL in pc_ioctl!\n"); - return(-EINVAL); - } - - save_flags(flags); + return -EINVAL; /* ------------------------------------------------------------------- For POSIX compliance we need to add more ioctls. See tty_ioctl.c @@ -2871,46 +2370,39 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, { /* Begin switch cmd */ case TCGETS: - if (copy_to_user(argp, - tty->termios, sizeof(struct termios))) + if (copy_to_user(argp, tty->termios, sizeof(struct termios))) return -EFAULT; - return(0); - + return 0; case TCGETA: return get_termio(tty, argp); - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); if (retval) return retval; - /* Setup an event to indicate when the transmit buffer empties */ - + spin_lock_irqsave(&epca_lock, flags); setup_empty_event(tty,ch); + spin_unlock_irqrestore(&epca_lock, flags); tty_wait_until_sent(tty, 0); if (!arg) digi_send_break(ch, HZ/4); /* 1/4 second */ return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); if (retval) return retval; /* Setup an event to indicate when the transmit buffer empties */ - + spin_lock_irqsave(&epca_lock, flags); setup_empty_event(tty,ch); + spin_unlock_irqrestore(&epca_lock, flags); tty_wait_until_sent(tty, 0); digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4); return 0; - case TIOCGSOFTCAR: if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg)) return -EFAULT; return 0; - case TIOCSSOFTCAR: { unsigned int value; @@ -2922,75 +2414,63 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, (value ? CLOCAL : 0)); return 0; } - case TIOCMODG: mflag = pc_tiocmget(tty, file); if (put_user(mflag, (unsigned long __user *)argp)) return -EFAULT; break; - case TIOCMODS: if (get_user(mstat, (unsigned __user *)argp)) return -EFAULT; return pc_tiocmset(tty, file, mstat, ~mstat); - case TIOCSDTR: + spin_lock_irqsave(&epca_lock, flags); ch->omodem |= ch->m_dtr; - cli(); globalwinon(ch); fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1); memoff(ch); - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); break; case TIOCCDTR: + spin_lock_irqsave(&epca_lock, flags); ch->omodem &= ~ch->m_dtr; - cli(); globalwinon(ch); fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1); memoff(ch); - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); break; - case DIGI_GETA: if (copy_to_user(argp, &ch->digiext, sizeof(digi_t))) return -EFAULT; break; - case DIGI_SETAW: case DIGI_SETAF: - if ((cmd) == (DIGI_SETAW)) - { + if (cmd == DIGI_SETAW) { /* Setup an event to indicate when the transmit buffer empties */ - + spin_lock_irqsave(&epca_lock, flags); setup_empty_event(tty,ch); + spin_unlock_irqrestore(&epca_lock, flags); tty_wait_until_sent(tty, 0); - } - else - { + } else { /* ldisc lock already held in ioctl */ if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); } - /* Fall Thru */ - case DIGI_SETA: if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) return -EFAULT; - if (ch->digiext.digi_flags & DIGI_ALTPIN) - { + if (ch->digiext.digi_flags & DIGI_ALTPIN) { ch->dcd = ch->m_dsr; ch->dsr = ch->m_dcd; - } - else - { + } else { ch->dcd = ch->m_dcd; ch->dsr = ch->m_dsr; } - cli(); + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); /* ----------------------------------------------------------------- @@ -3000,25 +2480,22 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, epcaparam(tty,ch); memoff(ch); - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); break; case DIGI_GETFLOW: case DIGI_GETAFLOW: - cli(); + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); - if ((cmd) == (DIGI_GETFLOW)) - { - dflow.startc = bc->startc; - dflow.stopc = bc->stopc; - } - else - { - dflow.startc = bc->startca; - dflow.stopc = bc->stopca; + if (cmd == DIGI_GETFLOW) { + dflow.startc = readb(&bc->startc); + dflow.stopc = readb(&bc->stopc); + } else { + dflow.startc = readb(&bc->startca); + dflow.stopc = readb(&bc->stopca); } memoff(ch); - restore_flags(flags); + spin_unlock_irqrestore(&epca_lock, flags); if (copy_to_user(argp, &dflow, sizeof(dflow))) return -EFAULT; @@ -3026,13 +2503,10 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, case DIGI_SETAFLOW: case DIGI_SETFLOW: - if ((cmd) == (DIGI_SETFLOW)) - { + if (cmd == DIGI_SETFLOW) { startc = ch->startc; stopc = ch->stopc; - } - else - { + } else { startc = ch->startca; stopc = ch->stopca; } @@ -3040,40 +2514,31 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, if (copy_from_user(&dflow, argp, sizeof(dflow))) return -EFAULT; - if (dflow.startc != startc || dflow.stopc != stopc) - { /* Begin if setflow toggled */ - cli(); + if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */ + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); - if ((cmd) == (DIGI_SETFLOW)) - { + if (cmd == DIGI_SETFLOW) { ch->fepstartc = ch->startc = dflow.startc; ch->fepstopc = ch->stopc = dflow.stopc; fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); - } - else - { + } else { ch->fepstartca = ch->startca = dflow.startc; ch->fepstopca = ch->stopca = dflow.stopc; fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); } - if (ch->statusflags & TXSTOPPED) + if (ch->statusflags & TXSTOPPED) pc_start(tty); memoff(ch); - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); } /* End if setflow toggled */ break; - default: return -ENOIOCTLCMD; - } /* End switch cmd */ - return 0; - } /* End pc_ioctl */ /* --------------------- Begin pc_set_termios ----------------------- */ @@ -3083,20 +2548,16 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) struct channel *ch; unsigned long flags; - /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - - if ((ch = verifyChannel(tty)) != NULL) - { /* Begin if channel valid */ - - save_flags(flags); - cli(); + if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); epcaparam(tty, ch); memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); if ((old_termios->c_cflag & CRTSCTS) && ((tty->termios->c_cflag & CRTSCTS) == 0)) @@ -3106,8 +2567,6 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) (tty->termios->c_cflag & CLOCAL)) wake_up_interruptible(&ch->open_wait); - restore_flags(flags); - } /* End if channel valid */ } /* End pc_set_termios */ @@ -3116,29 +2575,18 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) static void do_softint(void *private_) { /* Begin do_softint */ - struct channel *ch = (struct channel *) private_; - - /* Called in response to a modem change event */ - - if (ch && ch->magic == EPCA_MAGIC) - { /* Begin EPCA_MAGIC */ - + if (ch && ch->magic == EPCA_MAGIC) { /* Begin EPCA_MAGIC */ struct tty_struct *tty = ch->tty; - if (tty && tty->driver_data) - { - if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) - { /* Begin if clear_bit */ - + if (tty && tty->driver_data) { + if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { /* Begin if clear_bit */ tty_hangup(tty); /* FIXME: module removal race here - AKPM */ wake_up_interruptible(&ch->open_wait); ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; - } /* End if clear_bit */ } - } /* End EPCA_MAGIC */ } /* End do_softint */ @@ -3154,82 +2602,49 @@ static void pc_stop(struct tty_struct *tty) struct channel *ch; unsigned long flags; - /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - - if ((ch = verifyChannel(tty)) != NULL) - { /* Begin if valid channel */ - - save_flags(flags); - cli(); - - if ((ch->statusflags & TXSTOPPED) == 0) - { /* Begin if transmit stop requested */ - + if ((ch = verifyChannel(tty)) != NULL) { /* Begin if valid channel */ + spin_lock_irqsave(&epca_lock, flags); + if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */ globalwinon(ch); - /* STOP transmitting now !! */ - fepcmd(ch, PAUSETX, 0, 0, 0, 0); - ch->statusflags |= TXSTOPPED; memoff(ch); - } /* End if transmit stop requested */ - - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); } /* End if valid channel */ - } /* End pc_stop */ /* --------------------- Begin pc_start ----------------------- */ static void pc_start(struct tty_struct *tty) { /* Begin pc_start */ - struct channel *ch; - /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - - if ((ch = verifyChannel(tty)) != NULL) - { /* Begin if channel valid */ - + if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ unsigned long flags; - - save_flags(flags); - cli(); - + spin_lock_irqsave(&epca_lock, flags); /* Just in case output was resumed because of a change in Digi-flow */ - if (ch->statusflags & TXSTOPPED) - { /* Begin transmit resume requested */ - - volatile struct board_chan *bc; - + if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ + struct board_chan *bc; globalwinon(ch); bc = ch->brdchan; if (ch->statusflags & LOWWAIT) - bc->ilow = 1; - + writeb(1, &bc->ilow); /* Okay, you can start transmitting again... */ - fepcmd(ch, RESUMETX, 0, 0, 0, 0); - ch->statusflags &= ~TXSTOPPED; memoff(ch); - } /* End transmit resume requested */ - - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); } /* End if channel valid */ - } /* End pc_start */ /* ------------------------------------------------------------------ @@ -3244,86 +2659,55 @@ ______________________________________________________________________ */ static void pc_throttle(struct tty_struct * tty) { /* Begin pc_throttle */ - struct channel *ch; unsigned long flags; - /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - - if ((ch = verifyChannel(tty)) != NULL) - { /* Begin if channel valid */ - - - save_flags(flags); - cli(); - - if ((ch->statusflags & RXSTOPPED) == 0) - { + if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ + spin_lock_irqsave(&epca_lock, flags); + if ((ch->statusflags & RXSTOPPED) == 0) { globalwinon(ch); fepcmd(ch, PAUSERX, 0, 0, 0, 0); - ch->statusflags |= RXSTOPPED; memoff(ch); } - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); } /* End if channel valid */ - } /* End pc_throttle */ /* --------------------- Begin unthrottle ----------------------- */ static void pc_unthrottle(struct tty_struct *tty) { /* Begin pc_unthrottle */ - struct channel *ch; unsigned long flags; - volatile struct board_chan *bc; - - /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. ------------------------------------------------------------- */ - - if ((ch = verifyChannel(tty)) != NULL) - { /* Begin if channel valid */ - - + if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ /* Just in case output was resumed because of a change in Digi-flow */ - save_flags(flags); - cli(); - - if (ch->statusflags & RXSTOPPED) - { - + spin_lock_irqsave(&epca_lock, flags); + if (ch->statusflags & RXSTOPPED) { globalwinon(ch); - bc = ch->brdchan; fepcmd(ch, RESUMERX, 0, 0, 0, 0); - ch->statusflags &= ~RXSTOPPED; memoff(ch); } - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); } /* End if channel valid */ - } /* End pc_unthrottle */ /* --------------------- Begin digi_send_break ----------------------- */ void digi_send_break(struct channel *ch, int msec) { /* Begin digi_send_break */ - unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); - /* -------------------------------------------------------------------- Maybe I should send an infinite break here, schedule() for msec amount of time, and then stop the break. This way, @@ -3331,36 +2715,28 @@ void digi_send_break(struct channel *ch, int msec) to be called (i.e. via an ioctl()) more than once in msec amount of time. Try this for now... ------------------------------------------------------------------------ */ - fepcmd(ch, SENDBREAK, msec, 0, 10, 0); memoff(ch); - - restore_flags(flags); - + spin_unlock_irqrestore(&epca_lock, flags); } /* End digi_send_break */ /* --------------------- Begin setup_empty_event ----------------------- */ +/* Caller MUST hold the lock */ + static void setup_empty_event(struct tty_struct *tty, struct channel *ch) { /* Begin setup_empty_event */ - volatile struct board_chan *bc = ch->brdchan; - unsigned long int flags; + struct board_chan *bc = ch->brdchan; - save_flags(flags); - cli(); globalwinon(ch); ch->statusflags |= EMPTYWAIT; - /* ------------------------------------------------------------------ When set the iempty flag request a event to be generated when the transmit buffer is empty (If there is no BREAK in progress). --------------------------------------------------------------------- */ - - bc->iempty = 1; + writeb(1, &bc->iempty); memoff(ch); - restore_flags(flags); - } /* End setup_empty_event */ /* --------------------- Begin get_termio ----------------------- */ @@ -3369,10 +2745,10 @@ static int get_termio(struct tty_struct * tty, struct termio __user * termio) { /* Begin get_termio */ return kernel_termios_to_user_termio(termio, tty->termios); } /* End get_termio */ + /* ---------------------- Begin epca_setup -------------------------- */ void epca_setup(char *str, int *ints) { /* Begin epca_setup */ - struct board_info board; int index, loop, last; char *temp, *t2; @@ -3394,49 +2770,41 @@ void epca_setup(char *str, int *ints) for (last = 0, index = 1; index <= ints[0]; index++) switch(index) { /* Begin parse switch */ - case 1: board.status = ints[index]; - /* --------------------------------------------------------- We check for 2 (As opposed to 1; because 2 is a flag instructing the driver to ignore epcaconfig.) For this reason we check for 2. ------------------------------------------------------------ */ - if (board.status == 2) - { /* Begin ignore epcaconfig as well as lilo cmd line */ + if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */ nbdevs = 0; num_cards = 0; return; } /* End ignore epcaconfig as well as lilo cmd line */ - if (board.status > 2) - { - printk(KERN_ERR " - epca_setup: Invalid board status 0x%x\n", board.status); + if (board.status > 2) { + printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status); invalid_lilo_config = 1; setup_error_code |= INVALID_BOARD_STATUS; return; } last = index; break; - case 2: board.type = ints[index]; - if (board.type >= PCIXEM) - { - printk(KERN_ERR " - epca_setup: Invalid board type 0x%x\n", board.type); + if (board.type >= PCIXEM) { + printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type); invalid_lilo_config = 1; setup_error_code |= INVALID_BOARD_TYPE; return; } last = index; break; - case 3: board.altpin = ints[index]; - if (board.altpin > 1) - { - printk(KERN_ERR " - epca_setup: Invalid board altpin 0x%x\n", board.altpin); + if (board.altpin > 1) { + printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin); invalid_lilo_config = 1; setup_error_code |= INVALID_ALTPIN; return; @@ -3446,9 +2814,8 @@ void epca_setup(char *str, int *ints) case 4: board.numports = ints[index]; - if ((board.numports < 2) || (board.numports > 256)) - { - printk(KERN_ERR " - epca_setup: Invalid board numports 0x%x\n", board.numports); + if (board.numports < 2 || board.numports > 256) { + printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports); invalid_lilo_config = 1; setup_error_code |= INVALID_NUM_PORTS; return; @@ -3458,10 +2825,9 @@ void epca_setup(char *str, int *ints) break; case 5: - board.port = (unsigned char *)ints[index]; - if (ints[index] <= 0) - { - printk(KERN_ERR " - epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port); + board.port = ints[index]; + if (ints[index] <= 0) { + printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port); invalid_lilo_config = 1; setup_error_code |= INVALID_PORT_BASE; return; @@ -3470,10 +2836,9 @@ void epca_setup(char *str, int *ints) break; case 6: - board.membase = (unsigned char *)ints[index]; - if (ints[index] <= 0) - { - printk(KERN_ERR " - epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase); + board.membase = ints[index]; + if (ints[index] <= 0) { + printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase); invalid_lilo_config = 1; setup_error_code |= INVALID_MEM_BASE; return; @@ -3487,21 +2852,16 @@ void epca_setup(char *str, int *ints) } /* End parse switch */ - while (str && *str) - { /* Begin while there is a string arg */ - + while (str && *str) { /* Begin while there is a string arg */ /* find the next comma or terminator */ temp = str; - /* While string is not null, and a comma hasn't been found */ while (*temp && (*temp != ',')) temp++; - if (!*temp) temp = NULL; else *temp++ = 0; - /* Set index to the number of args + 1 */ index = last + 1; @@ -3511,12 +2871,10 @@ void epca_setup(char *str, int *ints) len = strlen(str); if (strncmp("Disable", str, len) == 0) board.status = 0; - else - if (strncmp("Enable", str, len) == 0) + else if (strncmp("Enable", str, len) == 0) board.status = 1; - else - { - printk(KERN_ERR " - epca_setup: Invalid status %s\n", str); + else { + printk(KERN_ERR "epca_setup: Invalid status %s\n", str); invalid_lilo_config = 1; setup_error_code |= INVALID_BOARD_STATUS; return; @@ -3525,22 +2883,17 @@ void epca_setup(char *str, int *ints) break; case 2: - for(loop = 0; loop < EPCA_NUM_TYPES; loop++) if (strcmp(board_desc[loop], str) == 0) break; - - /* --------------------------------------------------------------- If the index incremented above refers to a legitamate board type set it here. ------------------------------------------------------------------*/ - if (index < EPCA_NUM_TYPES) board.type = loop; - else - { - printk(KERN_ERR " - epca_setup: Invalid board type: %s\n", str); + else { + printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str); invalid_lilo_config = 1; setup_error_code |= INVALID_BOARD_TYPE; return; @@ -3552,12 +2905,10 @@ void epca_setup(char *str, int *ints) len = strlen(str); if (strncmp("Disable", str, len) == 0) board.altpin = 0; - else - if (strncmp("Enable", str, len) == 0) + else if (strncmp("Enable", str, len) == 0) board.altpin = 1; - else - { - printk(KERN_ERR " - epca_setup: Invalid altpin %s\n", str); + else { + printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str); invalid_lilo_config = 1; setup_error_code |= INVALID_ALTPIN; return; @@ -3570,9 +2921,8 @@ void epca_setup(char *str, int *ints) while (isdigit(*t2)) t2++; - if (*t2) - { - printk(KERN_ERR " - epca_setup: Invalid port count %s\n", str); + if (*t2) { + printk(KERN_ERR "epca_setup: Invalid port count %s\n", str); invalid_lilo_config = 1; setup_error_code |= INVALID_NUM_PORTS; return; @@ -3601,15 +2951,14 @@ void epca_setup(char *str, int *ints) while (isxdigit(*t2)) t2++; - if (*t2) - { - printk(KERN_ERR " - epca_setup: Invalid i/o address %s\n", str); + if (*t2) { + printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str); invalid_lilo_config = 1; setup_error_code |= INVALID_PORT_BASE; return; } - board.port = (unsigned char *)simple_strtoul(str, NULL, 16); + board.port = simple_strtoul(str, NULL, 16); last = index; break; @@ -3618,52 +2967,38 @@ void epca_setup(char *str, int *ints) while (isxdigit(*t2)) t2++; - if (*t2) - { - printk(KERN_ERR " - epca_setup: Invalid memory base %s\n",str); + if (*t2) { + printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str); invalid_lilo_config = 1; setup_error_code |= INVALID_MEM_BASE; return; } - - board.membase = (unsigned char *)simple_strtoul(str, NULL, 16); + board.membase = simple_strtoul(str, NULL, 16); last = index; break; - default: - printk(KERN_ERR "PC/Xx: Too many string parms\n"); + printk(KERN_ERR "epca: Too many string parms\n"); return; } str = temp; - } /* End while there is a string arg */ - - if (last < 6) - { - printk(KERN_ERR "PC/Xx: Insufficient parms specified\n"); + if (last < 6) { + printk(KERN_ERR "epca: Insufficient parms specified\n"); return; } /* I should REALLY validate the stuff here */ - /* Copies our local copy of board into boards */ memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board)); - - /* Does this get called once per lilo arg are what ? */ - printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n", num_cards, board_desc[board.type], board.numports, (int)board.port, (unsigned int) board.membase); - num_cards++; - } /* End epca_setup */ - -#ifdef ENABLE_PCI /* ------------------------ Begin init_PCI --------------------------- */ enum epic_board_types { @@ -3685,7 +3020,6 @@ static struct { { PCIXRJ, 2, }, }; - static int __devinit epca_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -3711,10 +3045,8 @@ static int __devinit epca_init_one (struct pci_dev *pdev, boards[board_idx].status = ENABLED; boards[board_idx].type = epca_info_tbl[info_idx].board_type; boards[board_idx].numports = 0x0; - boards[board_idx].port = - (unsigned char *)((char *) addr + PCI_IO_OFFSET); - boards[board_idx].membase = - (unsigned char *)((char *) addr); + boards[board_idx].port = addr + PCI_IO_OFFSET; + boards[board_idx].membase = addr; if (!request_mem_region (addr + PCI_IO_OFFSET, 0x200000, "epca")) { printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n", @@ -3775,15 +3107,13 @@ static struct pci_device_id epca_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, epca_pci_tbl); int __init init_PCI (void) -{ /* Begin init_PCI */ +{ /* Begin init_PCI */ memset (&epca_driver, 0, sizeof (epca_driver)); epca_driver.name = "epca"; epca_driver.id_table = epca_pci_tbl; epca_driver.probe = epca_init_one; return pci_register_driver(&epca_driver); -} /* End init_PCI */ - -#endif /* ENABLE_PCI */ +} MODULE_LICENSE("GPL"); diff --git a/drivers/char/epca.h b/drivers/char/epca.h index 52205ef..20eeb5a 100644 --- a/drivers/char/epca.h +++ b/drivers/char/epca.h @@ -85,73 +85,73 @@ static char *board_desc[] = struct channel { long magic; - unchar boardnum; - unchar channelnum; - unchar omodem; /* FEP output modem status */ - unchar imodem; /* FEP input modem status */ - unchar modemfake; /* Modem values to be forced */ - unchar modem; /* Force values */ - unchar hflow; - unchar dsr; - unchar dcd; - unchar m_rts ; /* The bits used in whatever FEP */ - unchar m_dcd ; /* is indiginous to this board to */ - unchar m_dsr ; /* represent each of the physical */ - unchar m_cts ; /* handshake lines */ - unchar m_ri ; - unchar m_dtr ; - unchar stopc; - unchar startc; - unchar stopca; - unchar startca; - unchar fepstopc; - unchar fepstartc; - unchar fepstopca; - unchar fepstartca; - unchar txwin; - unchar rxwin; - ushort fepiflag; - ushort fepcflag; - ushort fepoflag; - ushort txbufhead; - ushort txbufsize; - ushort rxbufhead; - ushort rxbufsize; + unsigned char boardnum; + unsigned char channelnum; + unsigned char omodem; /* FEP output modem status */ + unsigned char imodem; /* FEP input modem status */ + unsigned char modemfake; /* Modem values to be forced */ + unsigned char modem; /* Force values */ + unsigned char hflow; + unsigned char dsr; + unsigned char dcd; + unsigned char m_rts ; /* The bits used in whatever FEP */ + unsigned char m_dcd ; /* is indiginous to this board to */ + unsigned char m_dsr ; /* represent each of the physical */ + unsigned char m_cts ; /* handshake lines */ + unsigned char m_ri ; + unsigned char m_dtr ; + unsigned char stopc; + unsigned char startc; + unsigned char stopca; + unsigned char startca; + unsigned char fepstopc; + unsigned char fepstartc; + unsigned char fepstopca; + unsigned char fepstartca; + unsigned char txwin; + unsigned char rxwin; + unsigned short fepiflag; + unsigned short fepcflag; + unsigned short fepoflag; + unsigned short txbufhead; + unsigned short txbufsize; + unsigned short rxbufhead; + unsigned short rxbufsize; int close_delay; int count; int blocked_open; - ulong event; + unsigned long event; int asyncflags; uint dev; - ulong statusflags; - ulong c_iflag; - ulong c_cflag; - ulong c_lflag; - ulong c_oflag; - unchar *txptr; - unchar *rxptr; - unchar *tmp_buf; + unsigned long statusflags; + unsigned long c_iflag; + unsigned long c_cflag; + unsigned long c_lflag; + unsigned long c_oflag; + unsigned char *txptr; + unsigned char *rxptr; + unsigned char *tmp_buf; struct board_info *board; - volatile struct board_chan *brdchan; + struct board_chan *brdchan; struct digi_struct digiext; struct tty_struct *tty; wait_queue_head_t open_wait; wait_queue_head_t close_wait; - struct work_struct tqueue; - volatile struct global_data *mailbox; + struct work_struct tqueue; + struct global_data *mailbox; }; struct board_info { - unchar status; - unchar type; - unchar altpin; - ushort numports; - unchar *port; - unchar *membase; - unchar __iomem *re_map_port; - unchar *re_map_membase; - ulong memory_seg; + unsigned char status; + unsigned char type; + unsigned char altpin; + unsigned short numports; + unsigned long port; + unsigned long membase; + unsigned char __iomem *re_map_port; + unsigned char *re_map_membase; + unsigned long memory_seg; void ( * memwinon ) (struct board_info *, unsigned int) ; void ( * memwinoff ) (struct board_info *, unsigned int) ; void ( * globalwinon ) (struct channel *) ; @@ -160,6 +160,6 @@ struct board_info void ( * memoff ) (struct channel *) ; void ( * assertgwinon ) (struct channel *) ; void ( * assertmemoff ) (struct channel *) ; - unchar poller_inhibited ; + unsigned char poller_inhibited ; }; -- cgit v1.1 From edf83015fcbff8976b75b42b565a77e9d450c567 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 6 Sep 2005 15:16:56 -0700 Subject: [PATCH] remove a dead extern in mem.c Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/mem.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 850a78c..f182752 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -35,10 +35,6 @@ # include #endif -#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR) -extern void tapechar_init(void); -#endif - /* * Architectures vary in how they handle caching for addresses * outside of main memory. -- cgit v1.1 From 573fc113133e0b0984d2c0090e706c6506661f91 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 6 Sep 2005 15:16:58 -0700 Subject: [PATCH] move m68k rtc drivers over to initcalls this gets rid of the last two explicit initializations in misc.c Signed-off-by: Christoph Hellwig Acked-by: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/misc.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 931efd5..0c83751 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -63,8 +63,6 @@ static DECLARE_MUTEX(misc_sem); #define DYNAMIC_MINORS 64 /* like dynamic majors */ static unsigned char misc_minors[DYNAMIC_MINORS / 8]; -extern int rtc_DP8570A_init(void); -extern int rtc_MK48T08_init(void); extern int pmu_device_init(void); #ifdef CONFIG_PROC_FS @@ -303,12 +301,7 @@ static int __init misc_init(void) misc_class = class_create(THIS_MODULE, "misc"); if (IS_ERR(misc_class)) return PTR_ERR(misc_class); -#ifdef CONFIG_MVME16x - rtc_MK48T08_init(); -#endif -#ifdef CONFIG_BVME6000 - rtc_DP8570A_init(); -#endif + if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { printk("unable to get major %d for misc devices\n", MISC_MAJOR); -- cgit v1.1 From a10077708233becfbae7b0104e1e8c0569359aa7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 6 Sep 2005 15:16:59 -0700 Subject: [PATCH] move 68360serial.c over use initcalls this is the last serial driver not using initcalls. Signed-off-by: Christoph Hellwig Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6e4be3b..9d65712 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -153,7 +153,6 @@ static int tty_release(struct inode *, struct file *); int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); static int tty_fasync(int fd, struct file * filp, int on); -extern void rs_360_init(void); static void release_mem(struct tty_struct *tty, int idx); @@ -2911,11 +2910,6 @@ void __init console_init(void) #ifdef CONFIG_EARLY_PRINTK disable_early_printk(); #endif -#ifdef CONFIG_SERIAL_68360 - /* This is not a console initcall. I know not what it's doing here. - So I haven't moved it. dwmw2 */ - rs_360_init(); -#endif call = __con_initcall_start; while (call < __con_initcall_end) { (*call)(); -- cgit v1.1 From d2052c1676a39cae101a81f3da8a4ade8b668c88 Mon Sep 17 00:00:00 2001 From: Erik Waling Date: Tue, 6 Sep 2005 15:17:02 -0700 Subject: [PATCH] sonypi SPIC initialisation fix Newer Sony VAIO models (VGN-S480, VGN-S460, VGN-S3XP etc) use a new method to initialize the SPIC device. The new way to initialize (and disable) the device comes directly from the AML code in the _CRS, _SRS and _DIS methods from the DSDT table. This patch adds support for the new models. Signed-off-by: Erik Waling Signed-off-by: Stelian Pop Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/sonypi.c | 117 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 20 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index cefbe98..35cf1ed 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -98,12 +98,13 @@ MODULE_PARM_DESC(useinput, #define SONYPI_DEVICE_MODEL_TYPE1 1 #define SONYPI_DEVICE_MODEL_TYPE2 2 +#define SONYPI_DEVICE_MODEL_TYPE3 3 /* type1 models use those */ #define SONYPI_IRQ_PORT 0x8034 #define SONYPI_IRQ_SHIFT 22 -#define SONYPI_BASE 0x50 -#define SONYPI_G10A (SONYPI_BASE+0x14) +#define SONYPI_TYPE1_BASE 0x50 +#define SONYPI_G10A (SONYPI_TYPE1_BASE+0x14) #define SONYPI_TYPE1_REGION_SIZE 0x08 #define SONYPI_TYPE1_EVTYPE_OFFSET 0x04 @@ -114,6 +115,13 @@ MODULE_PARM_DESC(useinput, #define SONYPI_TYPE2_REGION_SIZE 0x20 #define SONYPI_TYPE2_EVTYPE_OFFSET 0x12 +/* type3 series specifics */ +#define SONYPI_TYPE3_BASE 0x40 +#define SONYPI_TYPE3_GID2 (SONYPI_TYPE3_BASE+0x48) /* 16 bits */ +#define SONYPI_TYPE3_MISC (SONYPI_TYPE3_BASE+0x6d) /* 8 bits */ +#define SONYPI_TYPE3_REGION_SIZE 0x20 +#define SONYPI_TYPE3_EVTYPE_OFFSET 0x12 + /* battery / brightness addresses */ #define SONYPI_BAT_FLAGS 0x81 #define SONYPI_LCD_LIGHT 0x96 @@ -159,6 +167,10 @@ static struct sonypi_ioport_list sonypi_type2_ioport_list[] = { { 0x0, 0x0 } }; +/* same as in type 2 models */ +static struct sonypi_ioport_list *sonypi_type3_ioport_list = + sonypi_type2_ioport_list; + /* The set of possible interrupts */ struct sonypi_irq_list { u16 irq; @@ -180,6 +192,9 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = { { 0, 0x00 } /* no IRQ, 0x00 in SIRQ in AML */ }; +/* same as in type2 models */ +static struct sonypi_irq_list *sonypi_type3_irq_list = sonypi_type2_irq_list; + #define SONYPI_CAMERA_BRIGHTNESS 0 #define SONYPI_CAMERA_CONTRAST 1 #define SONYPI_CAMERA_HUE 2 @@ -223,6 +238,7 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = { #define SONYPI_MEYE_MASK 0x00000400 #define SONYPI_MEMORYSTICK_MASK 0x00000800 #define SONYPI_BATTERY_MASK 0x00001000 +#define SONYPI_WIRELESS_MASK 0x00002000 struct sonypi_event { u8 data; @@ -305,6 +321,13 @@ static struct sonypi_event sonypi_blueev[] = { { 0, 0 } }; +/* The set of possible wireless events */ +static struct sonypi_event sonypi_wlessev[] = { + { 0x59, SONYPI_EVENT_WIRELESS_ON }, + { 0x5a, SONYPI_EVENT_WIRELESS_OFF }, + { 0, 0 } +}; + /* The set of possible back button events */ static struct sonypi_event sonypi_backev[] = { { 0x20, SONYPI_EVENT_BACK_PRESSED }, @@ -391,6 +414,12 @@ static struct sonypi_eventtypes { { SONYPI_DEVICE_MODEL_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, + { SONYPI_DEVICE_MODEL_TYPE3, 0, 0xffffffff, sonypi_releaseev }, + { SONYPI_DEVICE_MODEL_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, + { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, + { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, + { SONYPI_DEVICE_MODEL_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, + { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0 } }; @@ -563,6 +592,23 @@ static void sonypi_type2_srs(void) udelay(10); } +static void sonypi_type3_srs(void) +{ + u16 v16; + u8 v8; + + /* This model type uses the same initialiazation of + * the embedded controller as the type2 models. */ + sonypi_type2_srs(); + + /* Initialization of PCI config space of the LPC interface bridge. */ + v16 = (sonypi_device.ioport1 & 0xFFF0) | 0x01; + pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, v16); + pci_read_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, &v8); + v8 = (v8 & 0xCF) | 0x10; + pci_write_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, v8); +} + /* Disables the device - this comes from the AML code in the ACPI bios */ static void sonypi_type1_dis(void) { @@ -587,6 +633,13 @@ static void sonypi_type2_dis(void) printk(KERN_WARNING "ec_write failed\n"); } +static void sonypi_type3_dis(void) +{ + sonypi_type2_dis(); + udelay(10); + pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, 0); +} + static u8 sonypi_call1(u8 dev) { u8 v1, v2; @@ -1067,10 +1120,17 @@ static struct miscdevice sonypi_misc_device = { static void sonypi_enable(unsigned int camera_on) { - if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) - sonypi_type2_srs(); - else + switch (sonypi_device.model) { + case SONYPI_DEVICE_MODEL_TYPE1: sonypi_type1_srs(); + break; + case SONYPI_DEVICE_MODEL_TYPE2: + sonypi_type2_srs(); + break; + case SONYPI_DEVICE_MODEL_TYPE3: + sonypi_type3_srs(); + break; + } sonypi_call1(0x82); sonypi_call2(0x81, 0xff); @@ -1094,10 +1154,18 @@ static int sonypi_disable(void) if (!SONYPI_ACPI_ACTIVE && fnkeyinit) outb(0xf1, 0xb2); - if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) - sonypi_type2_dis(); - else + switch (sonypi_device.model) { + case SONYPI_DEVICE_MODEL_TYPE1: sonypi_type1_dis(); + break; + case SONYPI_DEVICE_MODEL_TYPE2: + sonypi_type2_dis(); + break; + case SONYPI_DEVICE_MODEL_TYPE3: + sonypi_type3_dis(); + break; + } + return 0; } @@ -1143,12 +1211,16 @@ static int __devinit sonypi_probe(void) struct sonypi_irq_list *irq_list; struct pci_dev *pcidev; - pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, NULL); + if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) + sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; + else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) + sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; + else + sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; sonypi_device.dev = pcidev; - sonypi_device.model = pcidev ? - SONYPI_DEVICE_MODEL_TYPE1 : SONYPI_DEVICE_MODEL_TYPE2; spin_lock_init(&sonypi_device.fifo_lock); sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, @@ -1176,16 +1248,22 @@ static int __devinit sonypi_probe(void) goto out_miscreg; } - if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) { + + if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { + ioport_list = sonypi_type1_ioport_list; + sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE; + sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET; + irq_list = sonypi_type1_irq_list; + } else if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) { ioport_list = sonypi_type2_ioport_list; sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE; sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET; irq_list = sonypi_type2_irq_list; } else { - ioport_list = sonypi_type1_ioport_list; - sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE; - sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET; - irq_list = sonypi_type1_irq_list; + ioport_list = sonypi_type3_ioport_list; + sonypi_device.region_size = SONYPI_TYPE3_REGION_SIZE; + sonypi_device.evtype_offset = SONYPI_TYPE3_EVTYPE_OFFSET; + irq_list = sonypi_type3_irq_list; } for (i = 0; ioport_list[i].port1; i++) { @@ -1274,11 +1352,10 @@ static int __devinit sonypi_probe(void) printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver" "v%s.\n", SONYPI_DRIVER_VERSION); - printk(KERN_INFO "sonypi: detected %s model, " + printk(KERN_INFO "sonypi: detected type%d model, " "verbose = %d, fnkeyinit = %s, camera = %s, " "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", - (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ? - "type1" : "type2", + sonypi_device.model, verbose, fnkeyinit ? "on" : "off", camera ? "on" : "off", -- cgit v1.1 From 9f4a6dce10941380ad7365cc9b0ef038ed56cbf9 Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Tue, 6 Sep 2005 15:17:03 -0700 Subject: [PATCH] sonypi: remove obsolete event Remove old obsolete event. Signed-off-by: Stelian Pop Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/sonypi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 35cf1ed..36ae9ad 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -406,7 +406,6 @@ static struct sonypi_eventtypes { { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, { SONYPI_DEVICE_MODEL_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev }, - { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_HELP_MASK, sonypi_helpev }, { SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev }, { SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, { SONYPI_DEVICE_MODEL_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, -- cgit v1.1 From 2d237c63659c098a662b1b09d43460f04c498436 Mon Sep 17 00:00:00 2001 From: Stephane Doyon Date: Tue, 6 Sep 2005 15:17:31 -0700 Subject: [PATCH] Console blanking locking fix I've had WARN_CONSOLE_UNLOCKED warnings when calling TIOCLINUX TIOCL_BLANKSCREEN and TIOCL_UNBLANKSCREEN. (I'm blind and I use a braille display. I use those functions to blank my laptop's screen so people don't read it, and hopefully to conserve power.) The warnings are from these places: do_blank_screen at drivers/char/vt.c:2754 (Not tainted) save_screen at drivers/char/vt.c:575 (Not tainted) do_unblank_screen at drivers/char/vt.c:2822 (Not tainted) set_palette at drivers/char/vt.c:2908 (Not tainted) At a glance I would think the following patch ought to fix that. Tested on one machine. Could you please tell me if this is correct and/or forward the patch where appropriate... Signed-off-by: Stephane Doyon Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/vt.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 665103c..27b6c29 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2272,7 +2272,9 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) ret = paste_selection(tty); break; case TIOCL_UNBLANKSCREEN: + acquire_console_sem(); unblank_screen(); + release_console_sem(); break; case TIOCL_SELLOADLUT: ret = sel_loadlut(p); @@ -2317,8 +2319,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) } break; case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */ + acquire_console_sem(); ignore_poke = 1; do_blank_screen(0); + release_console_sem(); break; case TIOCL_BLANKEDSCREEN: ret = console_blanked; -- cgit v1.1 From 414edcd32aa54bad8827e7c74cace168006c5fab Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 6 Sep 2005 15:17:52 -0700 Subject: [PATCH] vt: fix possible memory corruption in complement_pos Based on a patch from Andr Pereira de Almeida It might be possible for the saved pointer (*p) to become invalid in between vc_resizes, so saving the screen offset instead of the screen pointer is saner. This bug is very hard to trigger though, but Andre probably did, if he's submitting this patch. Anyway, with Andre's patch, it's still possible for the offsets to be still illegal, if the new screen size is smaller than the old one. So I've also added checks if the offsets are still within the screenbuffer size. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/vt.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 27b6c29..b8d0c29 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -434,21 +434,25 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed) /* used by selection: complement pointer position */ void complement_pos(struct vc_data *vc, int offset) { - static unsigned short *p; + static int old_offset = -1; static unsigned short old; static unsigned short oldx, oldy; WARN_CONSOLE_UNLOCKED(); - if (p) { - scr_writew(old, p); + if (old_offset != -1 && old_offset >= 0 && + old_offset < vc->vc_screenbuf_size) { + scr_writew(old, screenpos(vc, old_offset, 1)); if (DO_UPDATE(vc)) vc->vc_sw->con_putc(vc, old, oldy, oldx); } - if (offset == -1) - p = NULL; - else { + + old_offset = offset; + + if (offset != -1 && offset >= 0 && + offset < vc->vc_screenbuf_size) { unsigned short new; + unsigned short *p; p = screenpos(vc, offset, 1); old = scr_readw(p); new = old ^ vc->vc_complement_mask; @@ -459,6 +463,7 @@ void complement_pos(struct vc_data *vc, int offset) vc->vc_sw->con_putc(vc, new, oldy, oldx); } } + } static void insert_char(struct vc_data *vc, unsigned int nr) -- cgit v1.1 From 96803820b3d9830518083c02681fd3f72987ae4d Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 6 Sep 2005 15:17:54 -0700 Subject: [PATCH] hpet: fix drift and url The HPET driver is using a parts per second drift factor instead of the standard parts per million drift the time interpolator code expects. This patch fixes that problem and updates the URL for the HPET spec. Signed-off-by: Alex Williamson Cc: "Robert W. Picco" Acked-by: "Pallipadi, Venkatesh" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hpet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 762fa43..a695f25 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -44,7 +44,7 @@ /* * The High Precision Event Timer driver. * This driver is closely modelled after the rtc.c driver. - * http://www.intel.com/labs/platcomp/hpet/hpetspec.htm + * http://www.intel.com/hardwaredesign/hpetspec.htm */ #define HPET_USER_FREQ (64) #define HPET_DRIFT (500) @@ -712,7 +712,7 @@ static void hpet_register_interpolator(struct hpets *hpetp) ti->shift = 10; ti->addr = &hpetp->hp_hpet->hpet_mc; ti->frequency = hpet_time_div(hpets->hp_period); - ti->drift = ti->frequency * HPET_DRIFT / 1000000; + ti->drift = HPET_DRIFT; ti->mask = -1; hpetp->hp_interpolator = ti; -- cgit v1.1 From 5ba4d46dc44c5399bc4e7a39239de5a1690848a4 Mon Sep 17 00:00:00 2001 From: Philipp Matthias Hahn Date: Tue, 6 Sep 2005 15:17:56 -0700 Subject: [PATCH] tpm: fix tpm_atmel.c on ICH6 While installing Debian on our new IBM X41 Tablet, I tried briefly to use the built-in Atmel TPM. The Athmel TPM is also located on the LPC-bus of the ICH6. To make it work I had to apply the following patch: Signed-off-by: Philipp Matthias Hahn Acked-by: Kylene Jo Hall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tpm/tpm_atmel.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index cc2cc77..c0d6491 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c @@ -206,6 +206,9 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)}, {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)}, {0,} -- cgit v1.1 From 82ca76b6b160b6fce46f78c069f87fe1a4dc0778 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 6 Sep 2005 15:18:35 -0700 Subject: [PATCH] drivers: convert kcalloc to kzalloc This patch converts kcalloc(1, ...) calls to use the new kzalloc() function. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/mbcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index 115dbb3..3fa64c6 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c @@ -750,7 +750,7 @@ static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id) dev->soft = NULL; - soft = kcalloc(1, sizeof(struct mbcs_soft), GFP_KERNEL); + soft = kzalloc(sizeof(struct mbcs_soft), GFP_KERNEL); if (soft == NULL) return -ENOMEM; -- cgit v1.1 From b224cd3a0ca376dd52f382905c1aaf5a83a54692 Mon Sep 17 00:00:00 2001 From: Andrey Panin Date: Tue, 6 Sep 2005 15:18:37 -0700 Subject: [PATCH] IPMI: use dmi_find_device() This patch replaces homebrew DMI scanning code in IPMI System Interface driver with dmi_find_device() call. Signed-off-by: Andrey Panin Cc: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 105 +++++++-------------------------------- 1 file changed, 17 insertions(+), 88 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index a44b973..51ce508 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -75,6 +75,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v) #include #include "ipmi_si_sm.h" #include +#include #define IPMI_SI_VERSION "v33" @@ -1610,22 +1611,15 @@ typedef struct dmi_ipmi_data static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; static int dmi_data_entries; -typedef struct dmi_header +static int __init decode_dmi(struct dmi_header *dm, int intf_num) { - u8 type; - u8 length; - u16 handle; -} dmi_header_t; - -static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) -{ - u8 __iomem *data = (u8 __iomem *)dm; + u8 *data = (u8 *)dm; unsigned long base_addr; u8 reg_spacing; - u8 len = readb(&dm->length); + u8 len = dm->length; dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; - ipmi_data->type = readb(&data[4]); + ipmi_data->type = data[4]; memcpy(&base_addr, data+8, sizeof(unsigned long)); if (len >= 0x11) { @@ -1640,12 +1634,12 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) } /* If bit 4 of byte 0x10 is set, then the lsb for the address is odd. */ - ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4); + ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); - ipmi_data->irq = readb(&data[0x11]); + ipmi_data->irq = data[0x11]; /* The top two bits of byte 0x10 hold the register spacing. */ - reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6; + reg_spacing = (data[0x10] & 0xC0) >> 6; switch(reg_spacing){ case 0x00: /* Byte boundaries */ ipmi_data->offset = 1; @@ -1673,7 +1667,7 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) ipmi_data->offset = 1; } - ipmi_data->slave_addr = readb(&data[6]); + ipmi_data->slave_addr = data[6]; if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { dmi_data_entries++; @@ -1685,82 +1679,17 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) return -1; } -static int dmi_table(u32 base, int len, int num) -{ - u8 __iomem *buf; - struct dmi_header __iomem *dm; - u8 __iomem *data; - int i=1; - int status=-1; - int intf_num = 0; - - buf = ioremap(base, len); - if(buf==NULL) - return -1; - - data = buf; - - while(ilength)) >= len) - break; - - if (readb(&dm->type) == 38) { - if (decode_dmi(dm, intf_num) == 0) { - intf_num++; - if (intf_num >= SI_MAX_DRIVERS) - break; - } - } - - data+=readb(&dm->length); - while((data-buf) < len && (readb(data)||readb(data+1))) - data++; - data+=2; - i++; - } - iounmap(buf); - - return status; -} - -static inline int dmi_checksum(u8 *buf) -{ - u8 sum=0; - int a; - - for(a=0; a<15; a++) - sum+=buf[a]; - return (sum==0); -} - -static int dmi_decode(void) +static void __init dmi_find_bmc(void) { - u8 buf[15]; - u32 fp=0xF0000; - -#ifdef CONFIG_SIMNOW - return -1; -#endif + struct dmi_device *dev = NULL; + int intf_num = 0; - while(fp < 0xFFFFF) - { - isa_memcpy_fromio(buf, fp, 15); - if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) - { - u16 num=buf[13]<<8|buf[12]; - u16 len=buf[7]<<8|buf[6]; - u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; + while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { + if (intf_num >= SI_MAX_DRIVERS) + break; - if(dmi_table(base, len, num) == 0) - return 0; - } - fp+=16; + decode_dmi((struct dmi_header *) dev->device_data, intf_num++); } - - return -1; } static int try_init_smbios(int intf_num, struct smi_info **new_info) @@ -2293,7 +2222,7 @@ static __init int init_ipmi_si(void) printk("\n"); #ifdef CONFIG_X86 - dmi_decode(); + dmi_find_bmc(); #endif rv = init_one_smi(0, &(smi_infos[pos])); -- cgit v1.1 From c14979b993021377228958498937bcdd9539cbce Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 6 Sep 2005 15:18:38 -0700 Subject: [PATCH] ipmi: add per-channel IPMB addresses IPMI allows multiple IPMB channels on a single interface, and each channel might have a different IPMB address. However, the driver has only one IPMB address that it uses for everything. This patch adds new IOCTLS and a new internal interface for setting per-channel IPMB addresses and LUNs. New systems are coming out with support for multiple IPMB channels, and they are broken without this patch. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_devintf.c | 94 ++++++++++++++++++++++--- drivers/char/ipmi/ipmi_msghandler.c | 137 +++++++++++++++++++++++++----------- 2 files changed, 178 insertions(+), 53 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index e0a5357..5571e92 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -411,6 +411,7 @@ static int ipmi_ioctl(struct inode *inode, break; } + /* The next four are legacy, not per-channel. */ case IPMICTL_SET_MY_ADDRESS_CMD: { unsigned int val; @@ -420,22 +421,25 @@ static int ipmi_ioctl(struct inode *inode, break; } - ipmi_set_my_address(priv->user, val); - rv = 0; + rv = ipmi_set_my_address(priv->user, 0, val); break; } case IPMICTL_GET_MY_ADDRESS_CMD: { - unsigned int val; + unsigned int val; + unsigned char rval; + + rv = ipmi_get_my_address(priv->user, 0, &rval); + if (rv) + break; - val = ipmi_get_my_address(priv->user); + val = rval; if (copy_to_user(arg, &val, sizeof(val))) { rv = -EFAULT; break; } - rv = 0; break; } @@ -448,24 +452,94 @@ static int ipmi_ioctl(struct inode *inode, break; } - ipmi_set_my_LUN(priv->user, val); - rv = 0; + rv = ipmi_set_my_LUN(priv->user, 0, val); break; } case IPMICTL_GET_MY_LUN_CMD: { - unsigned int val; + unsigned int val; + unsigned char rval; + + rv = ipmi_get_my_LUN(priv->user, 0, &rval); + if (rv) + break; - val = ipmi_get_my_LUN(priv->user); + val = rval; if (copy_to_user(arg, &val, sizeof(val))) { rv = -EFAULT; break; } - rv = 0; break; } + + case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD: + { + struct ipmi_channel_lun_address_set val; + + if (copy_from_user(&val, arg, sizeof(val))) { + rv = -EFAULT; + break; + } + + return ipmi_set_my_address(priv->user, val.channel, val.value); + break; + } + + case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD: + { + struct ipmi_channel_lun_address_set val; + + if (copy_from_user(&val, arg, sizeof(val))) { + rv = -EFAULT; + break; + } + + rv = ipmi_get_my_address(priv->user, val.channel, &val.value); + if (rv) + break; + + if (copy_to_user(arg, &val, sizeof(val))) { + rv = -EFAULT; + break; + } + break; + } + + case IPMICTL_SET_MY_CHANNEL_LUN_CMD: + { + struct ipmi_channel_lun_address_set val; + + if (copy_from_user(&val, arg, sizeof(val))) { + rv = -EFAULT; + break; + } + + rv = ipmi_set_my_LUN(priv->user, val.channel, val.value); + break; + } + + case IPMICTL_GET_MY_CHANNEL_LUN_CMD: + { + struct ipmi_channel_lun_address_set val; + + if (copy_from_user(&val, arg, sizeof(val))) { + rv = -EFAULT; + break; + } + + rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value); + if (rv) + break; + + if (copy_to_user(arg, &val, sizeof(val))) { + rv = -EFAULT; + break; + } + break; + } + case IPMICTL_SET_TIMING_PARMS_CMD: { struct ipmi_timing_parms parms; diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index e16c13f..84d477c 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -124,6 +124,14 @@ struct ipmi_channel { unsigned char medium; unsigned char protocol; + + /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, + but may be changed by the user. */ + unsigned char address; + + /* My LUN. This should generally stay the SMS LUN, but just in + case... */ + unsigned char lun; }; #ifdef CONFIG_PROC_FS @@ -135,7 +143,7 @@ struct ipmi_proc_entry #endif #define IPMI_IPMB_NUM_SEQ 64 -#define IPMI_MAX_CHANNELS 8 +#define IPMI_MAX_CHANNELS 16 struct ipmi_smi { /* What interface number are we? */ @@ -199,14 +207,6 @@ struct ipmi_smi this is registered. */ ipmi_user_t all_cmd_rcvr; - /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, - but may be changed by the user. */ - unsigned char my_address; - - /* My LUN. This should generally stay the SMS LUN, but just in - case... */ - unsigned char my_lun; - /* The event receiver for my BMC, only really used at panic shutdown as a place to store this. */ unsigned char event_receiver; @@ -766,26 +766,44 @@ void ipmi_get_version(ipmi_user_t user, *minor = user->intf->version_minor; } -void ipmi_set_my_address(ipmi_user_t user, - unsigned char address) +int ipmi_set_my_address(ipmi_user_t user, + unsigned int channel, + unsigned char address) { - user->intf->my_address = address; + if (channel >= IPMI_MAX_CHANNELS) + return -EINVAL; + user->intf->channels[channel].address = address; + return 0; } -unsigned char ipmi_get_my_address(ipmi_user_t user) +int ipmi_get_my_address(ipmi_user_t user, + unsigned int channel, + unsigned char *address) { - return user->intf->my_address; + if (channel >= IPMI_MAX_CHANNELS) + return -EINVAL; + *address = user->intf->channels[channel].address; + return 0; } -void ipmi_set_my_LUN(ipmi_user_t user, - unsigned char LUN) +int ipmi_set_my_LUN(ipmi_user_t user, + unsigned int channel, + unsigned char LUN) { - user->intf->my_lun = LUN & 0x3; + if (channel >= IPMI_MAX_CHANNELS) + return -EINVAL; + user->intf->channels[channel].lun = LUN & 0x3; + return 0; } -unsigned char ipmi_get_my_LUN(ipmi_user_t user) +int ipmi_get_my_LUN(ipmi_user_t user, + unsigned int channel, + unsigned char *address) { - return user->intf->my_lun; + if (channel >= IPMI_MAX_CHANNELS) + return -EINVAL; + *address = user->intf->channels[channel].lun; + return 0; } int ipmi_set_gets_events(ipmi_user_t user, int val) @@ -1213,7 +1231,7 @@ static inline int i_ipmi_request(ipmi_user_t user, unsigned char ipmb_seq; long seqid; - if (addr->channel > IPMI_NUM_CHANNELS) { + if (addr->channel >= IPMI_NUM_CHANNELS) { spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); @@ -1346,6 +1364,18 @@ static inline int i_ipmi_request(ipmi_user_t user, return rv; } +static int check_addr(ipmi_smi_t intf, + struct ipmi_addr *addr, + unsigned char *saddr, + unsigned char *lun) +{ + if (addr->channel >= IPMI_MAX_CHANNELS) + return -EINVAL; + *lun = intf->channels[addr->channel].lun; + *saddr = intf->channels[addr->channel].address; + return 0; +} + int ipmi_request_settime(ipmi_user_t user, struct ipmi_addr *addr, long msgid, @@ -1355,6 +1385,12 @@ int ipmi_request_settime(ipmi_user_t user, int retries, unsigned int retry_time_ms) { + unsigned char saddr, lun; + int rv; + + rv = check_addr(user->intf, addr, &saddr, &lun); + if (rv) + return rv; return i_ipmi_request(user, user->intf, addr, @@ -1363,8 +1399,8 @@ int ipmi_request_settime(ipmi_user_t user, user_msg_data, NULL, NULL, priority, - user->intf->my_address, - user->intf->my_lun, + saddr, + lun, retries, retry_time_ms); } @@ -1378,6 +1414,12 @@ int ipmi_request_supply_msgs(ipmi_user_t user, struct ipmi_recv_msg *supplied_recv, int priority) { + unsigned char saddr, lun; + int rv; + + rv = check_addr(user->intf, addr, &saddr, &lun); + if (rv) + return rv; return i_ipmi_request(user, user->intf, addr, @@ -1387,8 +1429,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user, supplied_smi, supplied_recv, priority, - user->intf->my_address, - user->intf->my_lun, + saddr, + lun, -1, 0); } @@ -1397,8 +1439,15 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off, { char *out = (char *) page; ipmi_smi_t intf = data; + int i; + int rv= 0; - return sprintf(out, "%x\n", intf->my_address); + for (i=0; ichannels[i].address); + out[rv-1] = '\n'; /* Replace the final space with a newline */ + out[rv] = '\0'; + rv++; + return rv; } static int version_file_read_proc(char *page, char **start, off_t off, @@ -1592,8 +1641,8 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan) NULL, NULL, 0, - intf->my_address, - intf->my_lun, + intf->channels[0].address, + intf->channels[0].lun, -1, 0); } @@ -1696,11 +1745,13 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, new_intf->intf_num = i; new_intf->version_major = version_major; new_intf->version_minor = version_minor; - if (slave_addr == 0) - new_intf->my_address = IPMI_BMC_SLAVE_ADDR; - else - new_intf->my_address = slave_addr; - new_intf->my_lun = 2; /* the SMS LUN. */ + for (j=0; jchannels[j].address + = IPMI_BMC_SLAVE_ADDR; + new_intf->channels[j].lun = 2; + } + if (slave_addr != 0) + new_intf->channels[0].address = slave_addr; rwlock_init(&(new_intf->users_lock)); INIT_LIST_HEAD(&(new_intf->users)); new_intf->handlers = handlers; @@ -1985,7 +2036,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, msg->data[3] = msg->rsp[6]; msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3); msg->data[5] = ipmb_checksum(&(msg->data[3]), 2); - msg->data[6] = intf->my_address; + msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address; /* rqseq/lun */ msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3); msg->data[8] = msg->rsp[8]; /* cmd */ @@ -2919,8 +2970,8 @@ static void send_panic_events(char *str) &smi_msg, &recv_msg, 0, - intf->my_address, - intf->my_lun, + intf->channels[0].address, + intf->channels[0].lun, 0, 1); /* Don't retry, and don't wait. */ } @@ -2965,8 +3016,8 @@ static void send_panic_events(char *str) &smi_msg, &recv_msg, 0, - intf->my_address, - intf->my_lun, + intf->channels[0].address, + intf->channels[0].lun, 0, 1); /* Don't retry, and don't wait. */ if (intf->local_event_generator) { @@ -2985,8 +3036,8 @@ static void send_panic_events(char *str) &smi_msg, &recv_msg, 0, - intf->my_address, - intf->my_lun, + intf->channels[0].address, + intf->channels[0].lun, 0, 1); /* no retry, and no wait. */ } intf->null_user_handler = NULL; @@ -2996,7 +3047,7 @@ static void send_panic_events(char *str) be zero, and it must not be my address. */ if (((intf->event_receiver & 1) == 0) && (intf->event_receiver != 0) - && (intf->event_receiver != intf->my_address)) + && (intf->event_receiver != intf->channels[0].address)) { /* The event receiver is valid, send an IPMB message. */ @@ -3031,7 +3082,7 @@ static void send_panic_events(char *str) data[0] = 0; data[1] = 0; data[2] = 0xf0; /* OEM event without timestamp. */ - data[3] = intf->my_address; + data[3] = intf->channels[0].address; data[4] = j++; /* sequence # */ /* Always give 11 bytes, so strncpy will fill it with zeroes for me. */ @@ -3047,8 +3098,8 @@ static void send_panic_events(char *str) &smi_msg, &recv_msg, 0, - intf->my_address, - intf->my_lun, + intf->channels[0].address, + intf->channels[0].lun, 0, 1); /* no retry, and no wait. */ } } -- cgit v1.1 From 75b0768a396f2a25901b7b1edc87b95cdb3af4ef Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 6 Sep 2005 15:18:38 -0700 Subject: [PATCH] ipmi: high-res timer support fixes Fix some problems with the high-res timer support. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 51ce508..60f2f96 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -61,11 +61,11 @@ # endif static inline void add_usec_to_timer(struct timer_list *t, long v) { - t->sub_expires += nsec_to_arch_cycle(v * 1000); - while (t->sub_expires >= arch_cycles_per_jiffy) + t->arch_cycle_expires += nsec_to_arch_cycle(v * 1000); + while (t->arch_cycle_expires >= arch_cycles_per_jiffy) { t->expires++; - t->sub_expires -= arch_cycles_per_jiffy; + t->arch_cycle_expires -= arch_cycles_per_jiffy; } } #endif @@ -762,18 +762,20 @@ static void si_restart_short_timer(struct smi_info *smi_info) #if defined(CONFIG_HIGH_RES_TIMERS) unsigned long flags; unsigned long jiffies_now; + unsigned long seq; if (del_timer(&(smi_info->si_timer))) { /* If we don't delete the timer, then it will go off immediately, anyway. So we only process if we actually delete the timer. */ - /* We already have irqsave on, so no need for it - here. */ - read_lock(&xtime_lock); - jiffies_now = jiffies; - smi_info->si_timer.expires = jiffies_now; - smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now); + do { + seq = read_seqbegin_irqsave(&xtime_lock, flags); + jiffies_now = jiffies; + smi_info->si_timer.expires = jiffies_now; + smi_info->si_timer.arch_cycle_expires + = get_arch_cycles(jiffies_now); + } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); @@ -827,15 +829,19 @@ static void smi_timeout(unsigned long data) /* If the state machine asks for a short delay, then shorten the timer timeout. */ if (smi_result == SI_SM_CALL_WITH_DELAY) { +#if defined(CONFIG_HIGH_RES_TIMERS) + unsigned long seq; +#endif spin_lock_irqsave(&smi_info->count_lock, flags); smi_info->short_timeouts++; spin_unlock_irqrestore(&smi_info->count_lock, flags); #if defined(CONFIG_HIGH_RES_TIMERS) - read_lock(&xtime_lock); - smi_info->si_timer.expires = jiffies; - smi_info->si_timer.sub_expires - = get_arch_cycles(smi_info->si_timer.expires); - read_unlock(&xtime_lock); + do { + seq = read_seqbegin_irqsave(&xtime_lock, flags); + smi_info->si_timer.expires = jiffies; + smi_info->si_timer.arch_cycle_expires + = get_arch_cycles(smi_info->si_timer.expires); + } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); #else smi_info->si_timer.expires = jiffies + 1; @@ -846,7 +852,7 @@ static void smi_timeout(unsigned long data) spin_unlock_irqrestore(&smi_info->count_lock, flags); smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; #if defined(CONFIG_HIGH_RES_TIMERS) - smi_info->si_timer.sub_expires = 0; + smi_info->si_timer.arch_cycle_expires = 0; #endif } -- cgit v1.1 From 8f05ee9a63b414da4fd036a9dab2d27727301188 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 6 Sep 2005 15:18:39 -0700 Subject: [PATCH] ipmi: watchdog/NMI interaction fixes There are some interactions between IPMI NMI timeouts and the other operations of the IPMI driver. This make sure those interactions are handled properly. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_watchdog.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index d35a953..82d5643 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -259,7 +259,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, data[1] = 0; WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state); - if (pretimeout > 0) { + if ((pretimeout > 0) && (ipmi_watchdog_state != WDOG_TIMEOUT_NONE)) { WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val); data[2] = pretimeout; } else { @@ -817,15 +817,19 @@ static void ipmi_register_watchdog(int ipmi_intf) static int ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled) { + /* If we are not expecting a timeout, ignore it. */ + if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) + return NOTIFY_DONE; + /* If no one else handled the NMI, we assume it was the IPMI watchdog. */ - if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) + if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) { + /* On some machines, the heartbeat will give + an error and not work unless we re-enable + the timer. So do so. */ + pretimeout_since_last_heartbeat = 1; panic(PFX "pre-timeout"); - - /* On some machines, the heartbeat will give - an error and not work unless we re-enable - the timer. So do so. */ - pretimeout_since_last_heartbeat = 1; + } return NOTIFY_DONE; } -- cgit v1.1 From 3ae0e0f9b15b95a2c3e64088d2a85e3f4a707681 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 6 Sep 2005 15:18:41 -0700 Subject: [PATCH] ipmi: OEM flag handling and hacks for some Dell machines The ipmi driver does not have a way to handle firmware-generated events which have the OEM[012] Data Available flags set. In such a case, the SMS_ATN bit may never get cleared by firmware, leaving the driver looping infinitely but never able to make any progress. This patch first simplifies storage and use of the data returned from an IPMI Get Device ID command. It then creates a new per-OEM handler hook, which should know how to handle events with the OEM[012] Data Available flags set. It then uses this to implement a workaround for IPMI 1.5-capable Dell PowerEdge servers which are susceptable to setting the OEM[012] Data Available flags when the driver can't handle it. Signed-off-by: Matt Domsch Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 117 +++++++++++++++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 12 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 60f2f96..4fb36d4 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -110,6 +110,21 @@ enum si_type { SI_KCS, SI_SMIC, SI_BT }; +struct ipmi_device_id { + unsigned char device_id; + unsigned char device_revision; + unsigned char firmware_revision_1; + unsigned char firmware_revision_2; + unsigned char ipmi_version; + unsigned char additional_device_support; + unsigned char manufacturer_id[3]; + unsigned char product_id[2]; + unsigned char aux_firmware_revision[4]; +} __attribute__((packed)); + +#define ipmi_version_major(v) ((v)->ipmi_version & 0xf) +#define ipmi_version_minor(v) ((v)->ipmi_version >> 4) + struct smi_info { ipmi_smi_t intf; @@ -132,12 +147,24 @@ struct smi_info void (*irq_cleanup)(struct smi_info *info); unsigned int io_size; + /* Per-OEM handler, called from handle_flags(). + Returns 1 when handle_flags() needs to be re-run + or 0 indicating it set si_state itself. + */ + int (*oem_data_avail_handler)(struct smi_info *smi_info); + /* Flags from the last GET_MSG_FLAGS command, used when an ATTN is set to hold the flags until we are done handling everything from the flags. */ #define RECEIVE_MSG_AVAIL 0x01 #define EVENT_MSG_BUFFER_FULL 0x02 #define WDT_PRE_TIMEOUT_INT 0x08 +#define OEM0_DATA_AVAIL 0x20 +#define OEM1_DATA_AVAIL 0x40 +#define OEM2_DATA_AVAIL 0x80 +#define OEM_DATA_AVAIL (OEM0_DATA_AVAIL | \ + OEM1_DATA_AVAIL | \ + OEM2_DATA_AVAIL) unsigned char msg_flags; /* If set to true, this will request events the next time the @@ -176,11 +203,7 @@ struct smi_info interrupts. */ int interrupt_disabled; - unsigned char ipmi_si_dev_rev; - unsigned char ipmi_si_fw_rev_major; - unsigned char ipmi_si_fw_rev_minor; - unsigned char ipmi_version_major; - unsigned char ipmi_version_minor; + struct ipmi_device_id device_id; /* Slave address, could be reported from DMI. */ unsigned char slave_addr; @@ -323,6 +346,7 @@ static inline void enable_si_irq(struct smi_info *smi_info) static void handle_flags(struct smi_info *smi_info) { + retry: if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { /* Watchdog pre-timeout */ spin_lock(&smi_info->count_lock); @@ -372,6 +396,10 @@ static void handle_flags(struct smi_info *smi_info) smi_info->curr_msg->data, smi_info->curr_msg->data_size); smi_info->si_state = SI_GETTING_EVENTS; + } else if (smi_info->msg_flags & OEM_DATA_AVAIL) { + if (smi_info->oem_data_avail_handler) + if (smi_info->oem_data_avail_handler(smi_info)) + goto retry; } else { smi_info->si_state = SI_NORMAL; } @@ -1927,11 +1955,8 @@ static int try_get_dev_id(struct smi_info *smi_info) } /* Record info from the get device id, in case we need it. */ - smi_info->ipmi_si_dev_rev = resp[4] & 0xf; - smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f; - smi_info->ipmi_si_fw_rev_minor = resp[6]; - smi_info->ipmi_version_major = resp[7] & 0xf; - smi_info->ipmi_version_minor = resp[7] >> 4; + memcpy(&smi_info->device_id, &resp[3], + min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id))); out: kfree(resp); @@ -1992,6 +2017,72 @@ static int stat_file_read_proc(char *page, char **start, off_t off, return (out - ((char *) page)); } +/* + * oem_data_avail_to_receive_msg_avail + * @info - smi_info structure with msg_flags set + * + * Converts flags from OEM_DATA_AVAIL to RECEIVE_MSG_AVAIL + * Returns 1 indicating need to re-run handle_flags(). + */ +static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info) +{ + smi_info->msg_flags = (smi_info->msg_flags & ~OEM_DATA_AVAIL) | + RECEIVE_MSG_AVAIL; + return 1; +} + +/* + * setup_dell_poweredge_oem_data_handler + * @info - smi_info.device_id must be populated + * + * Systems that match, but have firmware version < 1.40 may assert + * OEM0_DATA_AVAIL on their own, without being told via Set Flags that + * it's safe to do so. Such systems will de-assert OEM1_DATA_AVAIL + * upon receipt of IPMI_GET_MSG_CMD, so we should treat these flags + * as RECEIVE_MSG_AVAIL instead. + * + * As Dell has no plans to release IPMI 1.5 firmware that *ever* + * assert the OEM[012] bits, and if it did, the driver would have to + * change to handle that properly, we don't actually check for the + * firmware version. + * Device ID = 0x20 BMC on PowerEdge 8G servers + * Device Revision = 0x80 + * Firmware Revision1 = 0x01 BMC version 1.40 + * Firmware Revision2 = 0x40 BCD encoded + * IPMI Version = 0x51 IPMI 1.5 + * Manufacturer ID = A2 02 00 Dell IANA + * + */ +#define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20 +#define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80 +#define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51 +#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} +static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) +{ + struct ipmi_device_id *id = &smi_info->device_id; + const char mfr[3]=DELL_IANA_MFR_ID; + if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr)) && + id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID && + id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV && + id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) { + smi_info->oem_data_avail_handler = + oem_data_avail_to_receive_msg_avail; + } +} + +/* + * setup_oem_data_handler + * @info - smi_info.device_id must be filled in already + * + * Fills in smi_info.device_id.oem_data_available_handler + * when we know what function to use there. + */ + +static void setup_oem_data_handler(struct smi_info *smi_info) +{ + setup_dell_poweredge_oem_data_handler(smi_info); +} + /* Returns 0 if initialized, or negative on an error. */ static int init_one_smi(int intf_num, struct smi_info **smi) { @@ -2090,6 +2181,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) if (rv) goto out_err; + setup_oem_data_handler(new_smi); + /* Try to claim any interrupts. */ new_smi->irq_setup(new_smi); @@ -2123,8 +2216,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) rv = ipmi_register_smi(&handlers, new_smi, - new_smi->ipmi_version_major, - new_smi->ipmi_version_minor, + ipmi_version_major(&new_smi->device_id), + ipmi_version_minor(&new_smi->device_id), new_smi->slave_addr, &(new_smi->intf)); if (rv) { -- cgit v1.1 From 1fdd75bd6cfa60a54b6db91d9256a711ab52fef3 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 6 Sep 2005 15:18:42 -0700 Subject: [PATCH] ipmi: clean up versioning of the IPMI driver This adds MODULE_VERSION, MODULE_DESCRIPTION, and MODULE_AUTHOR tags to the IPMI driver modules. Also changes the MODULE_VERSION to remove the prepended 'v' on each value, consistent with the module versioning policy. This patch also removes all the version information from everything except the ipmi_msghandler module. Signed-off-by: Matt Domsch Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_bt_sm.c | 3 --- drivers/char/ipmi/ipmi_devintf.c | 7 +++---- drivers/char/ipmi/ipmi_kcs_sm.c | 3 --- drivers/char/ipmi/ipmi_msghandler.c | 8 ++++++-- drivers/char/ipmi/ipmi_poweroff.c | 6 +++--- drivers/char/ipmi/ipmi_si_intf.c | 14 +++----------- drivers/char/ipmi/ipmi_smic_sm.c | 3 --- drivers/char/ipmi/ipmi_watchdog.c | 9 ++++----- 8 files changed, 19 insertions(+), 34 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 5ce9c62..64c9afa 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -31,8 +31,6 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -#define IPMI_BT_VERSION "v33" - static int bt_debug = 0x00; /* Production value 0, see following flags */ #define BT_DEBUG_ENABLE 1 @@ -501,7 +499,6 @@ static int bt_size(void) struct si_sm_handlers bt_smi_handlers = { - .version = IPMI_BT_VERSION, .init_data = bt_init_data, .start_transaction = bt_start_transaction, .get_result = bt_get_result, diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 5571e92..883ac43 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -47,8 +47,6 @@ #include #include -#define IPMI_DEVINTF_VERSION "v33" - struct ipmi_file_private { ipmi_user_t user; @@ -822,8 +820,7 @@ static __init int init_ipmi_devintf(void) if (ipmi_major < 0) return -EINVAL; - printk(KERN_INFO "ipmi device interface version " - IPMI_DEVINTF_VERSION "\n"); + printk(KERN_INFO "ipmi device interface\n"); ipmi_class = class_create(THIS_MODULE, "ipmi"); if (IS_ERR(ipmi_class)) { @@ -866,3 +863,5 @@ static __exit void cleanup_ipmi(void) module_exit(cleanup_ipmi); MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Corey Minyard "); +MODULE_DESCRIPTION("Linux device interface for the IPMI message handler."); diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index 48cce24..d21853a 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -42,8 +42,6 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -#define IPMI_KCS_VERSION "v33" - /* Set this if you want a printout of why the state machine was hosed when it gets hosed. */ #define DEBUG_HOSED_REASON @@ -489,7 +487,6 @@ static void kcs_cleanup(struct si_sm_data *kcs) struct si_sm_handlers kcs_smi_handlers = { - .version = IPMI_KCS_VERSION, .init_data = init_kcs_data, .start_transaction = start_kcs_transaction, .get_result = get_kcs_result, diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 84d477c..05293d0 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -47,7 +47,8 @@ #include #define PFX "IPMI message handler: " -#define IPMI_MSGHANDLER_VERSION "v33" + +#define IPMI_DRIVER_VERSION "36.0" static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); static int ipmi_init_msghandler(void); @@ -3150,7 +3151,7 @@ static int ipmi_init_msghandler(void) return 0; printk(KERN_INFO "ipmi message handler version " - IPMI_MSGHANDLER_VERSION "\n"); + IPMI_DRIVER_VERSION "\n"); for (i=0; i"); +MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI interface."); +MODULE_VERSION(IPMI_DRIVER_VERSION); EXPORT_SYMBOL(ipmi_create_user); EXPORT_SYMBOL(ipmi_destroy_user); diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index f951c30..1583329 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -42,7 +42,6 @@ #include #define PFX "IPMI poweroff: " -#define IPMI_POWEROFF_VERSION "v33" /* Where to we insert our poweroff function? */ extern void (*pm_power_off)(void); @@ -582,8 +581,7 @@ static int ipmi_poweroff_init (void) struct proc_dir_entry *file; printk ("Copyright (C) 2004 MontaVista Software -" - " IPMI Powerdown via sys_reboot version " - IPMI_POWEROFF_VERSION ".\n"); + " IPMI Powerdown via sys_reboot.\n"); switch (poweroff_control) { case IPMI_CHASSIS_POWER_CYCLE: @@ -642,3 +640,5 @@ module_exit(ipmi_poweroff_cleanup); module_init(ipmi_poweroff_init); MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Corey Minyard "); +MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot"); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 4fb36d4..b43172a 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -77,8 +77,6 @@ static inline void add_usec_to_timer(struct timer_list *t, long v) #include #include -#define IPMI_SI_VERSION "v33" - /* Measure times between events in the driver. */ #undef DEBUG_TIMING @@ -2310,15 +2308,7 @@ static __init int init_ipmi_si(void) } } - printk(KERN_INFO "IPMI System Interface driver version " - IPMI_SI_VERSION); - if (kcs_smi_handlers.version) - printk(", KCS version %s", kcs_smi_handlers.version); - if (smic_smi_handlers.version) - printk(", SMIC version %s", smic_smi_handlers.version); - if (bt_smi_handlers.version) - printk(", BT version %s", bt_smi_handlers.version); - printk("\n"); + printk(KERN_INFO "IPMI System Interface driver.\n"); #ifdef CONFIG_X86 dmi_find_bmc(); @@ -2430,3 +2420,5 @@ static __exit void cleanup_ipmi_si(void) module_exit(cleanup_ipmi_si); MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Corey Minyard "); +MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT system interfaces."); diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c index ae18747..add2aa2 100644 --- a/drivers/char/ipmi/ipmi_smic_sm.c +++ b/drivers/char/ipmi/ipmi_smic_sm.c @@ -46,8 +46,6 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -#define IPMI_SMIC_VERSION "v33" - /* smic_debug is a bit-field * SMIC_DEBUG_ENABLE - turned on for now * SMIC_DEBUG_MSG - commands and their responses @@ -588,7 +586,6 @@ static int smic_size(void) struct si_sm_handlers smic_smi_handlers = { - .version = IPMI_SMIC_VERSION, .init_data = init_smic_data, .start_transaction = start_smic_transaction, .get_result = smic_get_result, diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 82d5643..77ece1f 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -53,8 +53,6 @@ #define PFX "IPMI Watchdog: " -#define IPMI_WATCHDOG_VERSION "v33" - /* * The IPMI command/response information for the watchdog timer. */ @@ -928,9 +926,6 @@ static int __init ipmi_wdog_init(void) { int rv; - printk(KERN_INFO PFX "driver version " - IPMI_WATCHDOG_VERSION "\n"); - if (strcmp(action, "reset") == 0) { action_val = WDOG_TIMEOUT_RESET; } else if (strcmp(action, "none") == 0) { @@ -1015,6 +1010,8 @@ static int __init ipmi_wdog_init(void) register_reboot_notifier(&wdog_reboot_notifier); notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier); + printk(KERN_INFO PFX "driver initialized\n"); + return 0; } @@ -1066,3 +1063,5 @@ static void __exit ipmi_wdog_exit(void) module_exit(ipmi_wdog_exit); module_init(ipmi_wdog_init); MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Corey Minyard "); +MODULE_DESCRIPTION("watchdog timer based upon the IPMI interface."); -- cgit v1.1 From 56a55ec64806fb56e0cd43b0f726020b74c6689b Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 6 Sep 2005 15:18:42 -0700 Subject: [PATCH] ipmi: fix panic ipmb response The "null message handler" in the IPMI driver is used in startup and panic situations to handle messages. It was only designed to work with messages from the local management controller, but in some cases it was used to get messages from remote managmenet controllers, and the system would then panic. This patch makes the "null message handler" in the IPMI driver more general so it works with any kind of message. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 107 ++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 40 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 05293d0..d0ed252 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -219,7 +219,7 @@ struct ipmi_smi interface comes in with a NULL user, call this routine with it. Note that the message will still be freed by the caller. This only works on the system interface. */ - void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg); + void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg); /* When we are scanning the channels for an SMI, this will tell which channel we are scanning. */ @@ -459,7 +459,27 @@ unsigned int ipmi_addr_length(int addr_type) static void deliver_response(struct ipmi_recv_msg *msg) { - msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data); + if (! msg->user) { + ipmi_smi_t intf = msg->user_msg_data; + unsigned long flags; + + /* Special handling for NULL users. */ + if (intf->null_user_handler) { + intf->null_user_handler(intf, msg); + spin_lock_irqsave(&intf->counter_lock, flags); + intf->handled_local_responses++; + spin_unlock_irqrestore(&intf->counter_lock, flags); + } else { + /* No handler, so give up. */ + spin_lock_irqsave(&intf->counter_lock, flags); + intf->unhandled_local_responses++; + spin_unlock_irqrestore(&intf->counter_lock, flags); + } + ipmi_free_recv_msg(msg); + } else { + msg->user->handler->ipmi_recv_hndl(msg, + msg->user->handler_data); + } } /* Find the next sequence number not being used and add the given @@ -1389,6 +1409,8 @@ int ipmi_request_settime(ipmi_user_t user, unsigned char saddr, lun; int rv; + if (! user) + return -EINVAL; rv = check_addr(user->intf, addr, &saddr, &lun); if (rv) return rv; @@ -1418,6 +1440,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user, unsigned char saddr, lun; int rv; + if (! user) + return -EINVAL; rv = check_addr(user->intf, addr, &saddr, &lun); if (rv) return rv; @@ -1638,7 +1662,7 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan) (struct ipmi_addr *) &si, 0, &msg, - NULL, + intf, NULL, NULL, 0, @@ -1648,19 +1672,20 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan) } static void -channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) +channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) { int rv = 0; int chan; - if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2)) - && (msg->rsp[1] == IPMI_GET_CHANNEL_INFO_CMD)) + if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) + && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) + && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD)) { /* It's the one we want */ - if (msg->rsp[2] != 0) { + if (msg->msg.data[0] != 0) { /* Got an error from the channel, just go on. */ - if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) { + if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) { /* If the MC does not support this command, that is legal. We just assume it has one IPMB at channel @@ -1677,13 +1702,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) } goto next_channel; } - if (msg->rsp_size < 6) { + if (msg->msg.data_len < 4) { /* Message not big enough, just go on. */ goto next_channel; } chan = intf->curr_channel; - intf->channels[chan].medium = msg->rsp[4] & 0x7f; - intf->channels[chan].protocol = msg->rsp[5] & 0x1f; + intf->channels[chan].medium = msg->msg.data[2] & 0x7f; + intf->channels[chan].protocol = msg->msg.data[3] & 0x1f; next_channel: intf->curr_channel++; @@ -2382,6 +2407,14 @@ static int handle_bmc_rsp(ipmi_smi_t intf, unsigned long flags; recv_msg = (struct ipmi_recv_msg *) msg->user_data; + if (recv_msg == NULL) + { + printk(KERN_WARNING"IPMI message received with no owner. This\n" + "could be because of a malformed message, or\n" + "because of a hardware error. Contact your\n" + "hardware vender for assistance\n"); + return 0; + } /* Make sure the user still exists. */ list_for_each_entry(user, &(intf->users), link) { @@ -2392,19 +2425,11 @@ static int handle_bmc_rsp(ipmi_smi_t intf, } } - if (!found) { - /* Special handling for NULL users. */ - if (!recv_msg->user && intf->null_user_handler){ - intf->null_user_handler(intf, msg); - spin_lock_irqsave(&intf->counter_lock, flags); - intf->handled_local_responses++; - spin_unlock_irqrestore(&intf->counter_lock, flags); - }else{ - /* The user for the message went away, so give up. */ - spin_lock_irqsave(&intf->counter_lock, flags); - intf->unhandled_local_responses++; - spin_unlock_irqrestore(&intf->counter_lock, flags); - } + if ((! found) && recv_msg->user) { + /* The user for the message went away, so give up. */ + spin_lock_irqsave(&intf->counter_lock, flags); + intf->unhandled_local_responses++; + spin_unlock_irqrestore(&intf->counter_lock, flags); ipmi_free_recv_msg(recv_msg); } else { struct ipmi_system_interface_addr *smi_addr; @@ -2890,28 +2915,30 @@ static void dummy_recv_done_handler(struct ipmi_recv_msg *msg) } #ifdef CONFIG_IPMI_PANIC_STRING -static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) +static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg) { - if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2)) - && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD) - && (msg->rsp[2] == IPMI_CC_NO_ERROR)) + if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) + && (msg->msg.netfn == IPMI_NETFN_SENSOR_EVENT_RESPONSE) + && (msg->msg.cmd == IPMI_GET_EVENT_RECEIVER_CMD) + && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) { /* A get event receiver command, save it. */ - intf->event_receiver = msg->rsp[3]; - intf->event_receiver_lun = msg->rsp[4] & 0x3; + intf->event_receiver = msg->msg.data[1]; + intf->event_receiver_lun = msg->msg.data[2] & 0x3; } } -static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) +static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg) { - if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2)) - && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD) - && (msg->rsp[2] == IPMI_CC_NO_ERROR)) + if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) + && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) + && (msg->msg.cmd == IPMI_GET_DEVICE_ID_CMD) + && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) { /* A get device id command, save if we are an event receiver or generator. */ - intf->local_sel_device = (msg->rsp[8] >> 2) & 1; - intf->local_event_generator = (msg->rsp[8] >> 5) & 1; + intf->local_sel_device = (msg->msg.data[6] >> 2) & 1; + intf->local_event_generator = (msg->msg.data[6] >> 5) & 1; } } #endif @@ -2967,7 +2994,7 @@ static void send_panic_events(char *str) &addr, 0, &msg, - NULL, + intf, &smi_msg, &recv_msg, 0, @@ -3013,7 +3040,7 @@ static void send_panic_events(char *str) &addr, 0, &msg, - NULL, + intf, &smi_msg, &recv_msg, 0, @@ -3033,7 +3060,7 @@ static void send_panic_events(char *str) &addr, 0, &msg, - NULL, + intf, &smi_msg, &recv_msg, 0, @@ -3095,7 +3122,7 @@ static void send_panic_events(char *str) &addr, 0, &msg, - NULL, + intf, &smi_msg, &recv_msg, 0, -- cgit v1.1 From 168524d673f99550d75af49eb3f5d2850420eb66 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 6 Sep 2005 15:18:43 -0700 Subject: [PATCH] ipmi: add hacks for IPMI chassis poweroff for certain Dell servers This patch allows Dell servers with IPMI controllers that predate IPMI 1.5 to use the standard poweroff or powercycle commands. These systems firmware don't set the chassis capability bit in the Get Device ID, but they do implement the standard poweroff and powercycle commands. Tested on RHEL3 kernel 2.4.21-20.ELsmp on a PowerEdge 2600. The standard ipmi_poweroff driver cannot drive these systems. With this patch, they power off or powercycle as expected. Signed-off-by: Matt Domsch Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_poweroff.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 1583329..1705901 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -62,6 +62,7 @@ MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of p static unsigned int mfg_id; static unsigned int prod_id; static unsigned char capabilities; +static unsigned char ipmi_version; /* We use our own messages for this operation, we don't let the system allocate them, since we may be in a panic situation. The whole @@ -337,6 +338,25 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user) } /* + * ipmi_dell_chassis_detect() + * Dell systems with IPMI < 1.5 don't set the chassis capability bit + * but they can handle a chassis poweroff or powercycle command. + */ + +#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} +static int ipmi_dell_chassis_detect (ipmi_user_t user) +{ + const char ipmi_version_major = ipmi_version & 0xF; + const char ipmi_version_minor = (ipmi_version >> 4) & 0xF; + const char mfr[3]=DELL_IANA_MFR_ID; + if (!memcmp(mfr, &mfg_id, sizeof(mfr)) && + ipmi_version_major <= 1 && + ipmi_version_minor < 5) + return 1; + return 0; +} + +/* * Standard chassis support */ @@ -413,6 +433,9 @@ static struct poweroff_function poweroff_functions[] = { { .platform_type = "CPI1", .detect = ipmi_cpi1_detect, .poweroff_func = ipmi_poweroff_cpi1 }, + { .platform_type = "chassis", + .detect = ipmi_dell_chassis_detect, + .poweroff_func = ipmi_poweroff_chassis }, /* Chassis should generally be last, other things should override it. */ { .platform_type = "chassis", @@ -498,6 +521,7 @@ static void ipmi_po_new_smi(int if_num) prod_id = (halt_recv_msg.msg.data[10] | (halt_recv_msg.msg.data[11] << 8)); capabilities = halt_recv_msg.msg.data[6]; + ipmi_version = halt_recv_msg.msg.data[5]; /* Scan for a poweroff method */ -- cgit v1.1 From e8b336173b86c5db5dd5ae5ad33f3f8605878d0d Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 6 Sep 2005 15:18:45 -0700 Subject: [PATCH] ipmi: style cleanups Clean up various style issues in the IPMI driver. Should be no functional changes. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_bt_sm.c | 66 +++++++++++------ drivers/char/ipmi/ipmi_msghandler.c | 46 ++++++------ drivers/char/ipmi/ipmi_poweroff.c | 2 +- drivers/char/ipmi/ipmi_si_intf.c | 141 ++++++++++++++++++------------------ drivers/char/ipmi/ipmi_watchdog.c | 19 +++-- 5 files changed, 146 insertions(+), 128 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 64c9afa..3386267 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -161,7 +161,8 @@ static int bt_start_transaction(struct si_sm_data *bt, { unsigned int i; - if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) return -1; + if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) + return -1; if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) return -2; @@ -169,7 +170,8 @@ static int bt_start_transaction(struct si_sm_data *bt, if (bt_debug & BT_DEBUG_MSG) { printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); - for (i = 0; i < size; i ++) printk (" %02x", data[i]); + for (i = 0; i < size; i ++) + printk (" %02x", data[i]); printk("\n"); } bt->write_data[0] = size + 1; /* all data plus seq byte */ @@ -208,15 +210,18 @@ static int bt_get_result(struct si_sm_data *bt, } else { data[0] = bt->read_data[1]; data[1] = bt->read_data[3]; - if (length < msg_len) bt->truncated = 1; + if (length < msg_len) + bt->truncated = 1; if (bt->truncated) { /* can be set in read_all_bytes() */ data[2] = IPMI_ERR_MSG_TRUNCATED; msg_len = 3; - } else memcpy(data + 2, bt->read_data + 4, msg_len - 2); + } else + memcpy(data + 2, bt->read_data + 4, msg_len - 2); if (bt_debug & BT_DEBUG_MSG) { printk (KERN_WARNING "BT: res (raw)"); - for (i = 0; i < msg_len; i++) printk(" %02x", data[i]); + for (i = 0; i < msg_len; i++) + printk(" %02x", data[i]); printk ("\n"); } } @@ -229,8 +234,10 @@ static int bt_get_result(struct si_sm_data *bt, static void reset_flags(struct si_sm_data *bt) { - if (BT_STATUS & BT_H_BUSY) BT_CONTROL(BT_H_BUSY); - if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY); + if (BT_STATUS & BT_H_BUSY) + BT_CONTROL(BT_H_BUSY); + if (BT_STATUS & BT_B_BUSY) + BT_CONTROL(BT_B_BUSY); BT_CONTROL(BT_CLR_WR_PTR); BT_CONTROL(BT_SMS_ATN); #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION @@ -239,7 +246,8 @@ static void reset_flags(struct si_sm_data *bt) BT_CONTROL(BT_H_BUSY); BT_CONTROL(BT_B2H_ATN); BT_CONTROL(BT_CLR_RD_PTR); - for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) BMC2HOST; + for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) + BMC2HOST; BT_CONTROL(BT_H_BUSY); } #endif @@ -256,7 +264,8 @@ static inline void write_all_bytes(struct si_sm_data *bt) printk (" %02x", bt->write_data[i]); printk ("\n"); } - for (i = 0; i < bt->write_count; i++) HOST2BMC(bt->write_data[i]); + for (i = 0; i < bt->write_count; i++) + HOST2BMC(bt->write_data[i]); } static inline int read_all_bytes(struct si_sm_data *bt) @@ -276,7 +285,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) bt->truncated = 1; return 1; /* let next XACTION START clean it up */ } - for (i = 1; i <= bt->read_count; i++) bt->read_data[i] = BMC2HOST; + for (i = 1; i <= bt->read_count; i++) + bt->read_data[i] = BMC2HOST; bt->read_count++; /* account for the length byte */ if (bt_debug & BT_DEBUG_MSG) { @@ -293,7 +303,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) return 1; - if (bt_debug & BT_DEBUG_MSG) printk(KERN_WARNING "BT: bad packet: " + if (bt_debug & BT_DEBUG_MSG) + printk(KERN_WARNING "BT: bad packet: " "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", bt->write_data[1], bt->write_data[2], bt->write_data[3], bt->read_data[1], bt->read_data[2], bt->read_data[3]); @@ -357,7 +368,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) time); bt->last_state = bt->state; - if (bt->state == BT_STATE_HOSED) return SI_SM_HOSED; + if (bt->state == BT_STATE_HOSED) + return SI_SM_HOSED; if (bt->state != BT_STATE_IDLE) { /* do timeout test */ @@ -369,7 +381,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT (noticed in ipmi_smic_sm.c January 2004) */ - if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100; + if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) + time = 100; bt->timeout -= time; if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { error_recovery(bt, "timed out"); @@ -391,12 +404,14 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) BT_CONTROL(BT_H_BUSY); break; } - if (status & BT_B2H_ATN) break; + if (status & BT_B2H_ATN) + break; bt->state = BT_STATE_WRITE_BYTES; return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ case BT_STATE_WRITE_BYTES: - if (status & (BT_B_BUSY | BT_H2B_ATN)) break; + if (status & (BT_B_BUSY | BT_H2B_ATN)) + break; BT_CONTROL(BT_CLR_WR_PTR); write_all_bytes(bt); BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ @@ -404,7 +419,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ - if (status & (BT_H2B_ATN | BT_B_BUSY)) break; + if (status & (BT_H2B_ATN | BT_B_BUSY)) + break; bt->state = BT_STATE_B2H_WAIT; /* fall through with status */ @@ -413,15 +429,18 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ case BT_STATE_B2H_WAIT: - if (!(status & BT_B2H_ATN)) break; + if (!(status & BT_B2H_ATN)) + break; /* Assume ordered, uncached writes: no need to wait */ - if (!(status & BT_H_BUSY)) BT_CONTROL(BT_H_BUSY); /* set */ + if (!(status & BT_H_BUSY)) + BT_CONTROL(BT_H_BUSY); /* set */ BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ i = read_all_bytes(bt); BT_CONTROL(BT_H_BUSY); /* clear */ - if (!i) break; /* Try this state again */ + if (!i) /* Try this state again */ + break; bt->state = BT_STATE_READ_END; return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ @@ -434,7 +453,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) #ifdef MAKE_THIS_TRUE_IF_NECESSARY - if (status & BT_H_BUSY) break; + if (status & BT_H_BUSY) + break; #endif bt->seq++; bt->state = BT_STATE_IDLE; @@ -457,7 +477,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) break; case BT_STATE_RESET3: - if (bt->timeout > 0) return SI_SM_CALL_WITH_DELAY; + if (bt->timeout > 0) + return SI_SM_CALL_WITH_DELAY; bt->state = BT_STATE_RESTART; /* printk in debug modes */ break; @@ -483,7 +504,8 @@ static int bt_detect(struct si_sm_data *bt) but that's what you get from reading a bogus address, so we test that first. The calling routine uses negative logic. */ - if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1; + if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) + return 1; reset_flags(bt); return 0; } diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index d0ed252..792f4c2 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -117,7 +117,7 @@ struct seq_table do { \ seq = ((msgid >> 26) & 0x3f); \ seqid = (msgid & 0x3fffff); \ - } while(0) + } while (0) #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff) @@ -326,7 +326,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) down_read(&interfaces_sem); down_write(&smi_watchers_sem); list_add(&(watcher->link), &smi_watchers); - for (i=0; inew_smi(i); } @@ -496,9 +496,9 @@ static int intf_next_seq(ipmi_smi_t intf, int rv = 0; unsigned int i; - for (i=intf->curr_seq; + for (i = intf->curr_seq; (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq; - i=(i+1)%IPMI_IPMB_NUM_SEQ) + i = (i+1)%IPMI_IPMB_NUM_SEQ) { if (! intf->seq_table[i].inuse) break; @@ -733,7 +733,7 @@ static int ipmi_destroy_user_nolock(ipmi_user_t user) /* Remove the user from the interfaces sequence table. */ spin_lock_irqsave(&(user->intf->seq_lock), flags); - for (i=0; iintf->seq_table[i].inuse && (user->intf->seq_table[i].recv_msg->user == user)) { @@ -1370,7 +1370,7 @@ static inline int i_ipmi_request(ipmi_user_t user, #ifdef DEBUG_MSGING { int m; - for (m=0; mdata_size; m++) + for (m = 0; m < smi_msg->data_size; m++) printk(" %2.2x", smi_msg->data[m]); printk("\n"); } @@ -1467,7 +1467,7 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off, int i; int rv= 0; - for (i=0; ichannels[i].address); out[rv-1] = '\n'; /* Replace the final space with a newline */ out[rv] = '\0'; @@ -1766,12 +1766,12 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, rv = -ENOMEM; down_write(&interfaces_sem); - for (i=0; iintf_num = i; new_intf->version_major = version_major; new_intf->version_minor = version_minor; - for (j=0; jchannels[j].address = IPMI_BMC_SLAVE_ADDR; new_intf->channels[j].lun = 2; @@ -1783,7 +1783,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, new_intf->handlers = handlers; new_intf->send_info = send_info; spin_lock_init(&(new_intf->seq_lock)); - for (j=0; jseq_table[j].inuse = 0; new_intf->seq_table[j].seqid = 0; } @@ -1891,7 +1891,7 @@ static void clean_up_interface_data(ipmi_smi_t intf) free_recv_msg_list(&(intf->waiting_events)); free_cmd_rcvr_list(&(intf->cmd_rcvrs)); - for (i=0; iseq_table[i].inuse) && (intf->seq_table[i].recv_msg)) { @@ -1910,7 +1910,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf) down_write(&interfaces_sem); if (list_empty(&(intf->users))) { - for (i=0; idata_size; m++) + for (m = 0; m < msg->data_size; m++) printk(" %2.2x", msg->data[m]); printk("\n"); } @@ -2469,7 +2469,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf, #ifdef DEBUG_MSGING int m; printk("Recv:"); - for (m=0; mrsp_size; m++) + for (m = 0; m < msg->rsp_size; m++) printk(" %2.2x", msg->rsp[m]); printk("\n"); #endif @@ -2703,7 +2703,7 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, { int m; printk("Resend: "); - for (m=0; mdata_size; m++) + for (m = 0; m < smi_msg->data_size; m++) printk(" %2.2x", smi_msg->data[m]); printk("\n"); } @@ -2724,7 +2724,7 @@ ipmi_timeout_handler(long timeout_period) INIT_LIST_HEAD(&timeouts); spin_lock(&interfaces_lock); - for (i=0; iseq_lock), flags); - for (j=0; jseq_table[j]); if (!ent->inuse) continue; @@ -2789,7 +2789,7 @@ ipmi_timeout_handler(long timeout_period) spin_unlock(&intf->counter_lock); smi_msg = smi_from_recv_msg(intf, ent->recv_msg, j, ent->seqid); - if(!smi_msg) + if (! smi_msg) continue; spin_unlock_irqrestore(&(intf->seq_lock),flags); @@ -2820,7 +2820,7 @@ static void ipmi_request_event(void) int i; spin_lock(&interfaces_lock); - for (i=0; ixmit_msgs.next; } - if (!entry) { + if (! entry) { smi_info->curr_msg = NULL; rv = SI_SM_IDLE; } else { @@ -328,7 +328,7 @@ static void start_clear_flags(struct smi_info *smi_info) memory, we will re-enable the interrupt. */ static inline void disable_si_irq(struct smi_info *smi_info) { - if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { + if ((smi_info->irq) && (! smi_info->interrupt_disabled)) { disable_irq_nosync(smi_info->irq); smi_info->interrupt_disabled = 1; } @@ -359,7 +359,7 @@ static void handle_flags(struct smi_info *smi_info) } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { /* Messages available. */ smi_info->curr_msg = ipmi_alloc_smi_msg(); - if (!smi_info->curr_msg) { + if (! smi_info->curr_msg) { disable_si_irq(smi_info); smi_info->si_state = SI_NORMAL; return; @@ -378,7 +378,7 @@ static void handle_flags(struct smi_info *smi_info) } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { /* Events available. */ smi_info->curr_msg = ipmi_alloc_smi_msg(); - if (!smi_info->curr_msg) { + if (! smi_info->curr_msg) { disable_si_irq(smi_info); smi_info->si_state = SI_NORMAL; return; @@ -414,7 +414,7 @@ static void handle_transaction_done(struct smi_info *smi_info) #endif switch (smi_info->si_state) { case SI_NORMAL: - if (!smi_info->curr_msg) + if (! smi_info->curr_msg) break; smi_info->curr_msg->rsp_size @@ -1047,7 +1047,7 @@ static int std_irq_setup(struct smi_info *info) { int rv; - if (!info->irq) + if (! info->irq) return 0; if (info->si_type == SI_BT) { @@ -1056,7 +1056,7 @@ static int std_irq_setup(struct smi_info *info) SA_INTERRUPT, DEVICE_NAME, info); - if (!rv) + if (! rv) /* Enable the interrupt in the BT interface. */ info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, IPMI_BT_INTMASK_ENABLE_IRQ_BIT); @@ -1081,7 +1081,7 @@ static int std_irq_setup(struct smi_info *info) static void std_irq_cleanup(struct smi_info *info) { - if (!info->irq) + if (! info->irq) return; if (info->si_type == SI_BT) @@ -1154,7 +1154,7 @@ static int port_setup(struct smi_info *info) unsigned int *addr = info->io.info; int mapsize; - if (!addr || (!*addr)) + if (! addr || (! *addr)) return -ENODEV; info->io_cleanup = port_cleanup; @@ -1197,15 +1197,15 @@ static int try_init_port(int intf_num, struct smi_info **new_info) { struct smi_info *info; - if (!ports[intf_num]) + if (! ports[intf_num]) return -ENODEV; - if (!is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, + if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, ports[intf_num])) return -ENODEV; info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) { + if (! info) { printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); return -ENOMEM; } @@ -1215,10 +1215,10 @@ static int try_init_port(int intf_num, struct smi_info **new_info) info->io.info = &(ports[intf_num]); info->io.addr = NULL; info->io.regspacing = regspacings[intf_num]; - if (!info->io.regspacing) + if (! info->io.regspacing) info->io.regspacing = DEFAULT_REGSPACING; info->io.regsize = regsizes[intf_num]; - if (!info->io.regsize) + if (! info->io.regsize) info->io.regsize = DEFAULT_REGSPACING; info->io.regshift = regshifts[intf_num]; info->irq = 0; @@ -1303,7 +1303,7 @@ static int mem_setup(struct smi_info *info) unsigned long *addr = info->io.info; int mapsize; - if (!addr || (!*addr)) + if (! addr || (! *addr)) return -ENODEV; info->io_cleanup = mem_cleanup; @@ -1358,15 +1358,15 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) { struct smi_info *info; - if (!addrs[intf_num]) + if (! addrs[intf_num]) return -ENODEV; - if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, + if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, addrs[intf_num])) return -ENODEV; info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) { + if (! info) { printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); return -ENOMEM; } @@ -1376,10 +1376,10 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) info->io.info = &addrs[intf_num]; info->io.addr = NULL; info->io.regspacing = regspacings[intf_num]; - if (!info->io.regspacing) + if (! info->io.regspacing) info->io.regspacing = DEFAULT_REGSPACING; info->io.regsize = regsizes[intf_num]; - if (!info->io.regsize) + if (! info->io.regsize) info->io.regsize = DEFAULT_REGSPACING; info->io.regshift = regshifts[intf_num]; info->irq = 0; @@ -1437,7 +1437,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) { acpi_status status; - if (!info->irq) + if (! info->irq) return 0; /* FIXME - is level triggered right? */ @@ -1461,7 +1461,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) static void acpi_gpe_irq_cleanup(struct smi_info *info) { - if (!info->irq) + if (! info->irq) return; acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); @@ -1537,10 +1537,10 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) addr_space = IPMI_MEM_ADDR_SPACE; else addr_space = IPMI_IO_ADDR_SPACE; - if (!is_new_interface(-1, addr_space, spmi->addr.address)) + if (! is_new_interface(-1, addr_space, spmi->addr.address)) return -ENODEV; - if (!spmi->addr.register_bit_width) { + if (! spmi->addr.register_bit_width) { acpi_failure = 1; return -ENODEV; } @@ -1567,7 +1567,7 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) } info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) { + if (! info) { printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); return -ENOMEM; } @@ -1645,7 +1645,7 @@ static int dmi_data_entries; static int __init decode_dmi(struct dmi_header *dm, int intf_num) { - u8 *data = (u8 *)dm; + u8 *data = (u8 *)dm; unsigned long base_addr; u8 reg_spacing; u8 len = dm->length; @@ -1714,7 +1714,7 @@ static int __init decode_dmi(struct dmi_header *dm, int intf_num) static void __init dmi_find_bmc(void) { struct dmi_device *dev = NULL; - int intf_num = 0; + int intf_num = 0; while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { if (intf_num >= SI_MAX_DRIVERS) @@ -1726,14 +1726,14 @@ static void __init dmi_find_bmc(void) static int try_init_smbios(int intf_num, struct smi_info **new_info) { - struct smi_info *info; - dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; - char *io_type; + struct smi_info *info; + dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; + char *io_type; if (intf_num >= dmi_data_entries) return -ENODEV; - switch(ipmi_data->type) { + switch (ipmi_data->type) { case 0x01: /* KCS */ si_type[intf_num] = "kcs"; break; @@ -1748,7 +1748,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) } info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) { + if (! info) { printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); return -ENOMEM; } @@ -1772,7 +1772,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) regspacings[intf_num] = ipmi_data->offset; info->io.regspacing = regspacings[intf_num]; - if (!info->io.regspacing) + if (! info->io.regspacing) info->io.regspacing = DEFAULT_REGSPACING; info->io.regsize = DEFAULT_REGSPACING; info->io.regshift = regshifts[intf_num]; @@ -1814,14 +1814,14 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) pci_smic_checked = 1; - if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, - NULL))) - ; - else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) && - pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID) - fe_rmc = 1; - else - return -ENODEV; + pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL); + if (! pci_dev) { + pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL); + if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)) + fe_rmc = 1; + else + return -ENODEV; + } error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); if (error) @@ -1834,7 +1834,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) } /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ - if (!(base_addr & 0x0001)) + if (! (base_addr & 0x0001)) { pci_dev_put(pci_dev); printk(KERN_ERR @@ -1844,17 +1844,17 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) } base_addr &= 0xFFFE; - if (!fe_rmc) + if (! fe_rmc) /* Data register starts at base address + 1 in eRMC */ ++base_addr; - if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { + if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { pci_dev_put(pci_dev); return -ENODEV; } info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) { + if (! info) { pci_dev_put(pci_dev); printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); return -ENOMEM; @@ -1865,7 +1865,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) ports[intf_num] = base_addr; info->io.info = &(ports[intf_num]); info->io.regspacing = regspacings[intf_num]; - if (!info->io.regspacing) + if (! info->io.regspacing) info->io.regspacing = DEFAULT_REGSPACING; info->io.regsize = DEFAULT_REGSPACING; info->io.regshift = regshifts[intf_num]; @@ -1886,7 +1886,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) { #ifdef CONFIG_PCI - if (find_pci_smic(intf_num, new_info)==0) + if (find_pci_smic(intf_num, new_info) == 0) return 0; #endif /* Include other methods here. */ @@ -1904,7 +1904,7 @@ static int try_get_dev_id(struct smi_info *smi_info) int rv = 0; resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); - if (!resp) + if (! resp) return -ENOMEM; /* Do a Get Device ID command, since it comes back with some @@ -1986,7 +1986,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, struct smi_info *smi = data; out += sprintf(out, "interrupts_enabled: %d\n", - smi->irq && !smi->interrupt_disabled); + smi->irq && ! smi->interrupt_disabled); out += sprintf(out, "short_timeouts: %ld\n", smi->short_timeouts); out += sprintf(out, "long_timeouts: %ld\n", @@ -2024,8 +2024,8 @@ static int stat_file_read_proc(char *page, char **start, off_t off, */ static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info) { - smi_info->msg_flags = (smi_info->msg_flags & ~OEM_DATA_AVAIL) | - RECEIVE_MSG_AVAIL; + smi_info->msg_flags = ((smi_info->msg_flags & ~OEM_DATA_AVAIL) | + RECEIVE_MSG_AVAIL); return 1; } @@ -2059,10 +2059,11 @@ static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) { struct ipmi_device_id *id = &smi_info->device_id; const char mfr[3]=DELL_IANA_MFR_ID; - if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr)) && - id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID && - id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV && - id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) { + if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) + && (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID) + && (id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV) + && (id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION)) + { smi_info->oem_data_avail_handler = oem_data_avail_to_receive_msg_avail; } @@ -2092,19 +2093,15 @@ static int init_one_smi(int intf_num, struct smi_info **smi) if (rv) rv = try_init_port(intf_num, &new_smi); #ifdef CONFIG_ACPI_INTERPRETER - if ((rv) && (si_trydefaults)) { + if (rv && si_trydefaults) rv = try_init_acpi(intf_num, &new_smi); - } #endif #ifdef CONFIG_X86 - if ((rv) && (si_trydefaults)) { + if (rv && si_trydefaults) rv = try_init_smbios(intf_num, &new_smi); - } #endif - if ((rv) && (si_trydefaults)) { + if (rv && si_trydefaults) rv = try_init_plug_and_play(intf_num, &new_smi); - } - if (rv) return rv; @@ -2114,7 +2111,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) new_smi->si_sm = NULL; new_smi->handlers = NULL; - if (!new_smi->irq_setup) { + if (! new_smi->irq_setup) { new_smi->irq = irqs[intf_num]; new_smi->irq_setup = std_irq_setup; new_smi->irq_cleanup = std_irq_cleanup; @@ -2148,7 +2145,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) /* Allocate the state machine's data and initialize it. */ new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); - if (!new_smi->si_sm) { + if (! new_smi->si_sm) { printk(" Could not allocate state machine memory\n"); rv = -ENOMEM; goto out_err; @@ -2256,7 +2253,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) /* Wait for the timer to stop. This avoids problems with race conditions removing the timer here. */ - while (!new_smi->timer_stopped) { + while (! new_smi->timer_stopped) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } @@ -2296,7 +2293,7 @@ static __init int init_ipmi_si(void) /* Parse out the si_type string into its components. */ str = si_type_str; if (*str != '\0') { - for (i=0; (itimer_stopped) { + while (! to_clean->timer_stopped) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } /* Interrupts and timeouts are stopped, now make sure the interface is in a clean state. */ - while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) { + while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { poll(to_clean); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); @@ -2410,10 +2407,10 @@ static __exit void cleanup_ipmi_si(void) { int i; - if (!initialized) + if (! initialized) return; - for (i=0; i Date: Tue, 6 Sep 2005 15:18:45 -0700 Subject: [PATCH] ipmi: remove unused fields This removes the unused "all_cmd_rcvr" variable from the IPMI driver. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 42 ++++++++++--------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 792f4c2..463351d 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -202,12 +202,6 @@ struct ipmi_smi struct list_head waiting_events; unsigned int waiting_events_count; /* How many events in queue? */ - /* This will be non-null if someone registers to receive all - IPMI commands (this is for interface emulation). There - may not be any things in the cmd_rcvrs list above when - this is registered. */ - ipmi_user_t all_cmd_rcvr; - /* The event receiver for my BMC, only really used at panic shutdown as a place to store this. */ unsigned char event_receiver; @@ -867,11 +861,6 @@ int ipmi_register_for_cmd(ipmi_user_t user, read_lock(&(user->intf->users_lock)); write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); - if (user->intf->all_cmd_rcvr != NULL) { - rv = -EBUSY; - goto out_unlock; - } - /* Make sure the command/netfn is not already registered. */ list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) { if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) { @@ -886,7 +875,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, rcvr->user = user; list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs)); } - out_unlock: + write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); read_unlock(&(user->intf->users_lock)); @@ -1799,7 +1788,6 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, rwlock_init(&(new_intf->cmd_rcvr_lock)); init_waitqueue_head(&new_intf->waitq); INIT_LIST_HEAD(&(new_intf->cmd_rcvrs)); - new_intf->all_cmd_rcvr = NULL; spin_lock_init(&(new_intf->counter_lock)); @@ -2037,15 +2025,11 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, read_lock(&(intf->cmd_rcvr_lock)); - if (intf->all_cmd_rcvr) { - user = intf->all_cmd_rcvr; - } else { - /* Find the command/netfn. */ - list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - user = rcvr->user; - break; - } + /* Find the command/netfn. */ + list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { + if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { + user = rcvr->user; + break; } } read_unlock(&(intf->cmd_rcvr_lock)); @@ -2222,15 +2206,11 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, read_lock(&(intf->cmd_rcvr_lock)); - if (intf->all_cmd_rcvr) { - user = intf->all_cmd_rcvr; - } else { - /* Find the command/netfn. */ - list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - user = rcvr->user; - break; - } + /* Find the command/netfn. */ + list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { + if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { + user = rcvr->user; + break; } } read_unlock(&(intf->cmd_rcvr_lock)); -- cgit v1.1 From 8c702e16207c70119d03df924de35f8c3629a5c4 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 6 Sep 2005 15:18:46 -0700 Subject: [PATCH] ipmi poweroff: fix chassis control The IPMI power control function proc_write_chassctrl was badly written, it directly used userspace pointers, it assumed that strings were NULL terminated, and it used the evil sscanf function. This converts over to using the sysctl interface for this data and changes the semantics to be a little more logical. Signed-off-by: Corey Minyard Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_poweroff.c | 132 +++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 74 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 42ea984..e82a96b 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -52,11 +52,11 @@ extern void (*pm_power_off)(void); #define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */ /* the IPMI data command */ -static int poweroff_control = IPMI_CHASSIS_POWER_DOWN; +static int poweroff_powercycle; /* parameter definition to allow user to flag power cycle */ -module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN); -MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); +module_param(poweroff_powercycle, int, 0); +MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); /* Stuff from the get device id command. */ static unsigned int mfg_id; @@ -385,37 +385,34 @@ static void ipmi_poweroff_chassis (ipmi_user_t user) powercyclefailed: printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", - ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle")); + (poweroff_powercycle ? "cycle" : "down")); /* * Power down */ send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; - data[0] = poweroff_control; + if (poweroff_powercycle) + data[0] = IPMI_CHASSIS_POWER_CYCLE; + else + data[0] = IPMI_CHASSIS_POWER_DOWN; send_msg.data = data; send_msg.data_len = sizeof(data); rv = ipmi_request_in_rc_mode(user, (struct ipmi_addr *) &smi_addr, &send_msg); if (rv) { - switch (poweroff_control) { - case IPMI_CHASSIS_POWER_CYCLE: - /* power cycle failed, default to power down */ - printk(KERN_ERR PFX "Unable to send chassis power " \ - "cycle message, IPMI error 0x%x\n", rv); - poweroff_control = IPMI_CHASSIS_POWER_DOWN; - goto powercyclefailed; - - case IPMI_CHASSIS_POWER_DOWN: - default: - printk(KERN_ERR PFX "Unable to send chassis power " \ - "down message, IPMI error 0x%x\n", rv); - break; + if (poweroff_powercycle) { + /* power cycle failed, default to power down */ + printk(KERN_ERR PFX "Unable to send chassis power " \ + "cycle message, IPMI error 0x%x\n", rv); + poweroff_powercycle = 0; + goto powercyclefailed; } - } - return; + printk(KERN_ERR PFX "Unable to send chassis power " \ + "down message, IPMI error 0x%x\n", rv); + } } @@ -561,39 +558,35 @@ static struct ipmi_smi_watcher smi_watcher = #ifdef CONFIG_PROC_FS -/* displays properties to proc */ -static int proc_read_chassctrl(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n", - poweroff_control); -} +#include + +static ctl_table ipmi_table[] = { + { .ctl_name = DEV_IPMI_POWEROFF_POWERCYCLE, + .procname = "poweroff_powercycle", + .data = &poweroff_powercycle, + .maxlen = sizeof(poweroff_powercycle), + .mode = 0644, + .proc_handler = &proc_dointvec }, + { } +}; -/* process property writes from proc */ -static int proc_write_chassctrl(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - int rv = count; - unsigned int newval = 0; - - sscanf(buffer, "%d", &newval); - switch (newval) { - case IPMI_CHASSIS_POWER_CYCLE: - printk(KERN_INFO PFX "power cycle is now enabled\n"); - poweroff_control = newval; - break; - - case IPMI_CHASSIS_POWER_DOWN: - poweroff_control = IPMI_CHASSIS_POWER_DOWN; - break; - - default: - rv = -EINVAL; - break; - } +static ctl_table ipmi_dir_table[] = { + { .ctl_name = DEV_IPMI, + .procname = "ipmi", + .mode = 0555, + .child = ipmi_table }, + { } +}; - return rv; -} +static ctl_table ipmi_root_table[] = { + { .ctl_name = CTL_DEV, + .procname = "dev", + .mode = 0555, + .child = ipmi_dir_table }, + { } +}; + +static struct ctl_table_header *ipmi_table_header; #endif /* CONFIG_PROC_FS */ /* @@ -601,41 +594,32 @@ static int proc_write_chassctrl(struct file *file, const char *buffer, */ static int ipmi_poweroff_init (void) { - int rv; - struct proc_dir_entry *file; + int rv; printk ("Copyright (C) 2004 MontaVista Software -" " IPMI Powerdown via sys_reboot.\n"); - switch (poweroff_control) { - case IPMI_CHASSIS_POWER_CYCLE: - printk(KERN_INFO PFX "Power cycle is enabled.\n"); - break; + if (poweroff_powercycle) + printk(KERN_INFO PFX "Power cycle is enabled.\n"); - case IPMI_CHASSIS_POWER_DOWN: - default: - poweroff_control = IPMI_CHASSIS_POWER_DOWN; - break; +#ifdef CONFIG_PROC_FS + ipmi_table_header = register_sysctl_table(ipmi_root_table, 1); + if (!ipmi_table_header) { + printk(KERN_ERR PFX "Unable to register powercycle sysctl\n"); + rv = -ENOMEM; + goto out_err; } +#endif +#ifdef CONFIG_PROC_FS rv = ipmi_smi_watcher_register(&smi_watcher); +#endif if (rv) { + unregister_sysctl_table(ipmi_table_header); printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); goto out_err; } -#ifdef CONFIG_PROC_FS - file = create_proc_entry("poweroff_control", 0, proc_ipmi_root); - if (!file) { - printk(KERN_ERR PFX "Unable to create proc power control\n"); - } else { - file->nlink = 1; - file->read_proc = proc_read_chassctrl; - file->write_proc = proc_write_chassctrl; - file->owner = THIS_MODULE; - } -#endif - out_err: return rv; } @@ -646,7 +630,7 @@ static __exit void ipmi_poweroff_cleanup(void) int rv; #ifdef CONFIG_PROC_FS - remove_proc_entry("poweroff_control", proc_ipmi_root); + unregister_sysctl_table(ipmi_table_header); #endif ipmi_smi_watcher_unregister(&smi_watcher); -- cgit v1.1 From 982245f01734e9d5a3ab98b2b2e9761ae7719094 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 17 Jul 2005 04:22:20 +0200 Subject: [PATCH] PCI: remove CONFIG_PCI_NAMES This patch removes CONFIG_PCI_NAMES. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/char/drm/drmP.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 6f98701..121cc85 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -1071,5 +1071,9 @@ extern void *drm_calloc(size_t nmemb, size_t size, int area); extern unsigned long drm_core_get_map_ofs(drm_map_t *map); extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev); +#ifndef pci_pretty_name +#define pci_pretty_name(dev) "" +#endif + #endif /* __KERNEL__ */ #endif -- cgit v1.1 From f91f4d923f4039bf3460eca299ed5a3f7ecd7b96 Mon Sep 17 00:00:00 2001 From: "viro@ZenIV.linux.org.uk" Date: Fri, 9 Sep 2005 17:02:51 +0100 Subject: [PATCH] gratuitous includes of asm/serial.h Removed gratuitous includes of asm/serial.h in synklinkmp and ip2main. Allows to remove the rest of "broken on sparc32" in drivers/char - this stuff doesn't break the build anymore. Since it got zero testing, it almost certainly won't work there, though... Signed-off-by: Al Viro Acked-by: Russell King Signed-off-by: Linus Torvalds --- drivers/char/Kconfig | 4 ++-- drivers/char/ip2main.c | 1 - drivers/char/synclinkmp.c | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 2bc9d64..c29365d 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -80,7 +80,7 @@ config SERIAL_NONSTANDARD config COMPUTONE tristate "Computone IntelliPort Plus serial support" - depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (BROKEN || !SPARC32) + depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP ---help--- This driver supports the entire family of Intelliport II/Plus controllers with the exception of the MicroChannel controllers and @@ -208,7 +208,7 @@ config SYNCLINK config SYNCLINKMP tristate "SyncLink Multiport support" - depends on SERIAL_NONSTANDARD && (BROKEN || !SPARC32) + depends on SERIAL_NONSTANDARD help Enable support for the SyncLink Multiport (2 or 4 ports) serial adapter, running asynchronous and HDLC communications up diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index cf0cd58..066d7b5 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c @@ -120,7 +120,6 @@ #include #include -#include #include diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index ec949e4..8982eaf 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include -- cgit v1.1 From ff55fe2075e3901db4dbdc00e0b44a71bef97afd Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Fri, 9 Sep 2005 13:01:57 -0700 Subject: [PATCH] pty_chars_in_buffer oops fix The idea of this patch is to lock both sides of a ptmx/pty pair during line discipline changing. This is needed to ensure that say a poll on one side of the pty doesn't occur while the line discipline is actively being changed. This resulted in an oops reported on lkml, see: http://marc.theaimsgroup.com/?l=linux-kernel&m=111342171410005&w=2 A 'hacky' approach was previously implmemented which served to eliminate the poll vs. line discipline changing race. However, this patch takes a more general approach to the issue. The patch only adds locking on a less often used path, the line-discipline changing path, as opposed to locking the ptmx/pty pair on read/write/poll paths. The patch below, takes both ldisc locks in either order b/c the locks are both taken under the same spinlock(). I thought about locking the ptmx/pty separately, such as master always first but that introduces a 3 way deadlock. For example, process 1 does a blocking read on the slave side. Then, process 2 does an ldisc change on the slave side, which acquires the master ldisc lock but not the slave's. Finally, process 3 does a write which blocks on the process 2's ldisc reference. This patch does introduce some changes in semantics. For example, a line discipline change on side 'a' of a ptmx/pty pair, will now wait for a read/write to complete on the other side, or side 'b'. The current behavior is to simply wait for any read/writes on only side 'a', not both sides 'a' and 'b'. I think this behavior makes sense, but I wanted to point it out. I've tested the patch with a bunch of read/write/poll while changing the line discipline out from underneath. This patch obviates the need for the above "hide the problem" patch. Signed-off-by: Jason Baron Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/pty.c | 5 ++-- drivers/char/tty_io.c | 79 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 28 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/pty.c b/drivers/char/pty.c index da32889..49f3997 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -149,15 +149,14 @@ static int pty_write_room(struct tty_struct *tty) static int pty_chars_in_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; - ssize_t (*chars_in_buffer)(struct tty_struct *); int count; /* We should get the line discipline lock for "tty->link" */ - if (!to || !(chars_in_buffer = to->ldisc.chars_in_buffer)) + if (!to || !to->ldisc.chars_in_buffer) return 0; /* The ldisc must report 0 if no characters available to be read */ - count = chars_in_buffer(to); + count = to->ldisc.chars_in_buffer(to); if (tty->driver->subtype == PTY_TYPE_SLAVE) return count; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 9d65712..6a56ae4 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -469,21 +469,19 @@ static void tty_ldisc_enable(struct tty_struct *tty) static int tty_set_ldisc(struct tty_struct *tty, int ldisc) { - int retval = 0; - struct tty_ldisc o_ldisc; + int retval = 0; + struct tty_ldisc o_ldisc; char buf[64]; int work; unsigned long flags; struct tty_ldisc *ld; + struct tty_struct *o_tty; if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS)) return -EINVAL; restart: - if (tty->ldisc.num == ldisc) - return 0; /* We are already in the desired discipline */ - ld = tty_ldisc_get(ldisc); /* Eduardo Blanco */ /* Cyrus Durgin */ @@ -494,45 +492,74 @@ restart: if (ld == NULL) return -EINVAL; - o_ldisc = tty->ldisc; - tty_wait_until_sent(tty, 0); + if (tty->ldisc.num == ldisc) { + tty_ldisc_put(ldisc); + return 0; + } + + o_ldisc = tty->ldisc; + o_tty = tty->link; + /* * Make sure we don't change while someone holds a * reference to the line discipline. The TTY_LDISC bit * prevents anyone taking a reference once it is clear. * We need the lock to avoid racing reference takers. */ - + spin_lock_irqsave(&tty_ldisc_lock, flags); - if(tty->ldisc.refcount) - { - /* Free the new ldisc we grabbed. Must drop the lock - first. */ + if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { + if(tty->ldisc.refcount) { + /* Free the new ldisc we grabbed. Must drop the lock + first. */ + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + tty_ldisc_put(ldisc); + /* + * There are several reasons we may be busy, including + * random momentary I/O traffic. We must therefore + * retry. We could distinguish between blocking ops + * and retries if we made tty_ldisc_wait() smarter. That + * is up for discussion. + */ + if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) + return -ERESTARTSYS; + goto restart; + } + if(o_tty && o_tty->ldisc.refcount) { + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + tty_ldisc_put(ldisc); + if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) + return -ERESTARTSYS; + goto restart; + } + } + + /* if the TTY_LDISC bit is set, then we are racing against another ldisc change */ + + if (!test_bit(TTY_LDISC, &tty->flags)) { spin_unlock_irqrestore(&tty_ldisc_lock, flags); tty_ldisc_put(ldisc); - /* - * There are several reasons we may be busy, including - * random momentary I/O traffic. We must therefore - * retry. We could distinguish between blocking ops - * and retries if we made tty_ldisc_wait() smarter. That - * is up for discussion. - */ - if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) - return -ERESTARTSYS; + ld = tty_ldisc_ref_wait(tty); + tty_ldisc_deref(ld); goto restart; } - clear_bit(TTY_LDISC, &tty->flags); + + clear_bit(TTY_LDISC, &tty->flags); clear_bit(TTY_DONT_FLIP, &tty->flags); + if (o_tty) { + clear_bit(TTY_LDISC, &o_tty->flags); + clear_bit(TTY_DONT_FLIP, &o_tty->flags); + } spin_unlock_irqrestore(&tty_ldisc_lock, flags); - + /* * From this point on we know nobody has an ldisc * usage reference, nor can they obtain one until * we say so later on. */ - + work = cancel_delayed_work(&tty->flip.work); /* * Wait for ->hangup_work and ->flip.work handlers to terminate @@ -583,10 +610,12 @@ restart: */ tty_ldisc_enable(tty); + if (o_tty) + tty_ldisc_enable(o_tty); /* Restart it in case no characters kick it off. Safe if already running */ - if(work) + if (work) schedule_delayed_work(&tty->flip.work, 1); return retval; } -- cgit v1.1 From 4a918bc233c8b9537fbc05a8bbb33928a4980cc5 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Fri, 9 Sep 2005 13:02:12 -0700 Subject: [PATCH] synclink.c: compiler optimisation fix Make some fields of DMA descriptor volatile to prevent compiler optimizations. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclink.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 37c8bea..747eb8d 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $ + * $Id: synclink.c,v 4.37 2005/09/07 13:13:19 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -141,9 +141,9 @@ static MGSL_PARAMS default_params = { typedef struct _DMABUFFERENTRY { u32 phys_addr; /* 32-bit flat physical address of data buffer */ - u16 count; /* buffer size/data count */ - u16 status; /* Control/status field */ - u16 rcc; /* character count field */ + volatile u16 count; /* buffer size/data count */ + volatile u16 status; /* Control/status field */ + volatile u16 rcc; /* character count field */ u16 reserved; /* padding required by 16C32 */ u32 link; /* 32-bit flat link to next buffer entry */ char *virt_addr; /* virtual address of data buffer */ @@ -896,7 +896,7 @@ module_param_array(txdmabufs, int, NULL, 0); module_param_array(txholdbufs, int, NULL, 0); static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "$Revision: 4.28 $"; +static char *driver_version = "$Revision: 4.37 $"; static int synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent); -- cgit v1.1 From 9661239f7f698ba3a79db5e8ab5bb2f4090663d9 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Fri, 9 Sep 2005 13:02:13 -0700 Subject: [PATCH] synclink.c: add clear stats Add the ability to clear statistics. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclink.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 747eb8d..26b421b 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1814,6 +1814,8 @@ static int startup(struct mgsl_struct * info) info->pending_bh = 0; + memset(&info->icount, 0, sizeof(info->icount)); + init_timer(&info->tx_timer); info->tx_timer.data = (unsigned long)info; info->tx_timer.function = mgsl_tx_timeout; @@ -2470,12 +2472,12 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user * printk("%s(%d):mgsl_get_params(%s)\n", __FILE__,__LINE__, info->device_name); - COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount)); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_get_stats(%s) user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); - return -EFAULT; + if (!user_icount) { + memset(&info->icount, 0, sizeof(info->icount)); + } else { + COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); + if (err) + return -EFAULT; } return 0; -- cgit v1.1 From 7c1fff58cfaaf1c4b6a31a569e18cb7d2d8db0a6 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Fri, 9 Sep 2005 13:02:14 -0700 Subject: [PATCH] synclink.c: add loopback to async mode Add internal loopback support for asynchronous mode operation. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclink.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 26b421b..ea2d54b 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -6151,6 +6151,11 @@ static void usc_set_async_mode( struct mgsl_struct *info ) usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); } + if (info->params.loopback) { + info->loopback_bits = 0x300; + outw(0x0300, info->io_base + CCAR); + } + } /* end of usc_set_async_mode() */ /* usc_loopback_frame() -- cgit v1.1 From 7f3edb94564d319cd58cc11c2c986b7ec25643d8 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Fri, 9 Sep 2005 13:02:14 -0700 Subject: [PATCH] synclinkmp.c: fix double mapping of signals Serial signals were incorrectly mapped twice to events. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclinkmp.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 8982eaf..1bde04d 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -1,5 +1,5 @@ /* - * $Id: synclinkmp.c,v 4.34 2005/03/04 15:07:10 paulkf Exp $ + * $Id: synclinkmp.c,v 4.38 2005/07/15 13:29:44 paulkf Exp $ * * Device driver for Microgate SyncLink Multiport * high speed multiprotocol serial adapter. @@ -486,7 +486,7 @@ module_param_array(maxframe, int, NULL, 0); module_param_array(dosyncppp, int, NULL, 0); static char *driver_name = "SyncLink MultiPort driver"; -static char *driver_version = "$Revision: 4.34 $"; +static char *driver_version = "$Revision: 4.38 $"; static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); static void synclinkmp_remove_one(struct pci_dev *dev); @@ -555,7 +555,6 @@ static int set_txidle(SLMP_INFO *info, int idle_mode); static int tx_enable(SLMP_INFO *info, int enable); static int tx_abort(SLMP_INFO *info); static int rx_enable(SLMP_INFO *info, int enable); -static int map_status(int signals); static int modem_input_wait(SLMP_INFO *info,int arg); static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr); static int tiocmget(struct tty_struct *tty, struct file *file); @@ -3108,16 +3107,6 @@ static int rx_enable(SLMP_INFO * info, int enable) return 0; } -static int map_status(int signals) -{ - /* Map status bits to API event bits */ - - return ((signals & SerialSignal_DSR) ? MgslEvent_DsrActive : MgslEvent_DsrInactive) + - ((signals & SerialSignal_CTS) ? MgslEvent_CtsActive : MgslEvent_CtsInactive) + - ((signals & SerialSignal_DCD) ? MgslEvent_DcdActive : MgslEvent_DcdInactive) + - ((signals & SerialSignal_RI) ? MgslEvent_RiActive : MgslEvent_RiInactive); -} - /* wait for specified event to occur */ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr) @@ -3144,7 +3133,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr) /* return immediately if state matches requested events */ get_signals(info); - s = map_status(info->serial_signals); + s = info->serial_signals; events = mask & ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + -- cgit v1.1 From 761a444d8d059e4e2de326383b1dec4a636e0a92 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Fri, 9 Sep 2005 13:02:15 -0700 Subject: [PATCH] synclinkmp.c: disable burst transfers Disable burst transfers on adapter local bus. Hardware feature does not work on latest version of adapter. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclinkmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 1bde04d..d55dbf1 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -643,7 +643,7 @@ static unsigned char tx_active_fifo_level = 16; // tx request FIFO activation le static unsigned char tx_negate_fifo_level = 32; // tx request FIFO negation level in bytes static u32 misc_ctrl_value = 0x007e4040; -static u32 lcr1_brdr_value = 0x00800029; +static u32 lcr1_brdr_value = 0x00800028; static u32 read_ahead_count = 8; -- cgit v1.1 From 166692e4a045348109f66b493e1b41afde6f3769 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Fri, 9 Sep 2005 13:02:16 -0700 Subject: [PATCH] synclinkmp.c: add statistics clear Add ability to clear statistics. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclinkmp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index d55dbf1..eb31a3b 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -2748,6 +2748,8 @@ static int startup(SLMP_INFO * info) info->pending_bh = 0; + memset(&info->icount, 0, sizeof(info->icount)); + /* program hardware for current parameters */ reset_port(info); @@ -2951,12 +2953,12 @@ static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount) printk("%s(%d):%s get_params()\n", __FILE__,__LINE__, info->device_name); - COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount)); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):%s get_stats() user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); - return -EFAULT; + if (!user_icount) { + memset(&info->icount, 0, sizeof(info->icount)); + } else { + COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); + if (err) + return -EFAULT; } return 0; -- cgit v1.1 From 6e8dcee3e63f5a2cba4affff4bbb6e228f4b258a Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Fri, 9 Sep 2005 13:02:17 -0700 Subject: [PATCH] synclinkmp.c: fix async internal loopback Fix async internal loopback by not using enable_loopback function which reprograms clocking and should only be used for hdlc mode. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclinkmp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index eb31a3b..6fb165c 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -4479,11 +4479,13 @@ void async_mode(SLMP_INFO *info) /* MD2, Mode Register 2 * * 07..02 Reserved, must be 0 - * 01..00 CNCT<1..0> Channel connection, 0=normal + * 01..00 CNCT<1..0> Channel connection, 00=normal 11=local loopback * * 0000 0000 */ RegValue = 0x00; + if (info->params.loopback) + RegValue |= (BIT1 + BIT0); write_reg(info, MD2, RegValue); /* RXS, Receive clock source @@ -4564,9 +4566,6 @@ void async_mode(SLMP_INFO *info) write_reg(info, IE2, info->ie2_value); set_rate( info, info->params.data_rate * 16 ); - - if (info->params.loopback) - enable_loopback(info,1); } /* Program the SCA for HDLC communications. -- cgit v1.1 From badf16621c1f9d1ac753be056fce11b43d6e0be5 Mon Sep 17 00:00:00 2001 From: Dipankar Sarma Date: Fri, 9 Sep 2005 13:04:10 -0700 Subject: [PATCH] files: break up files struct In order for the RCU to work, the file table array, sets and their sizes must be updated atomically. Instead of ensuring this through too many memory barriers, we put the arrays and their sizes in a separate structure. This patch takes the first step of putting the file table elements in a separate structure fdtable that is embedded withing files_struct. It also changes all the users to refer to the file table using files_fdtable() macro. Subsequent applciation of RCU becomes easier after this. Signed-off-by: Dipankar Sarma Signed-Off-By: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6a56ae4..0bfc7af 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2454,6 +2454,7 @@ static void __do_SAK(void *arg) int i; struct file *filp; struct tty_ldisc *disc; + struct fdtable *fdt; if (!tty) return; @@ -2480,7 +2481,8 @@ static void __do_SAK(void *arg) task_lock(p); if (p->files) { spin_lock(&p->files->file_lock); - for (i=0; i < p->files->max_fds; i++) { + fdt = files_fdtable(p->files); + for (i=0; i < fdt->max_fds; i++) { filp = fcheck_files(p->files, i); if (!filp) continue; -- cgit v1.1 From b835996f628eadb55c5fb222ba46fe9395bf73c7 Mon Sep 17 00:00:00 2001 From: Dipankar Sarma Date: Fri, 9 Sep 2005 13:04:14 -0700 Subject: [PATCH] files: lock-free fd look-up With the use of RCU in files structure, the look-up of files using fds can now be lock-free. The lookup is protected by rcu_read_lock()/rcu_read_unlock(). This patch changes the readers to use lock-free lookup. Signed-off-by: Maneesh Soni Signed-off-by: Ravikiran Thirumalai Signed-off-by: Dipankar Sarma Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 0bfc7af..e5953f3 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2480,7 +2480,7 @@ static void __do_SAK(void *arg) } task_lock(p); if (p->files) { - spin_lock(&p->files->file_lock); + rcu_read_lock(); fdt = files_fdtable(p->files); for (i=0; i < fdt->max_fds; i++) { filp = fcheck_files(p->files, i); @@ -2495,7 +2495,7 @@ static void __do_SAK(void *arg) break; } } - spin_unlock(&p->files->file_lock); + rcu_read_unlock(); } task_unlock(p); } while_each_task_pid(session, PIDTYPE_SID, p); -- cgit v1.1 From 3b41dc1a3c7839a765ffa560a5ae07aa5d253cc8 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Fri, 9 Sep 2005 13:04:39 -0700 Subject: [PATCH] console: Fix buffer copy on vc resize On a vc resize, the contents of the old screen buffer are transferred to the new screenbuffer. If the new screenbuffer is smaller than the old one, only the contents from the bottom are copied to new. If the contents of the old buffer are located at the top, then the contents will not be copied to the new buffer resulting in a blank screen. This bug will happen only if the vc in question is not in the foreground. Doing an fbset -a or con2fbmap will trigger this bug. To fix this problem, base the start of the copy from the location of the current cursor. If the cursor is near the top of the buffer, copy the contents at the top, and if the cursor is near the bottom of the buffer, then copy the contents at the bottom. In the unlikely case where the new row size is greater than 2x smaller than the old one, and the cursor is in the middle, copy 1/2 screenful from the top and bottom of the cursor position. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/vt.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index b8d0c29..1e33cb0 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -751,6 +751,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; unsigned int old_cols, old_rows, old_row_size, old_screen_size; unsigned int new_cols, new_rows, new_row_size, new_screen_size; + unsigned int end; unsigned short *newscreen; WARN_CONSOLE_UNLOCKED(); @@ -794,20 +795,44 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) old_origin = vc->vc_origin; new_origin = (long) newscreen; new_scr_end = new_origin + new_screen_size; - if (new_rows < old_rows) - old_origin += (old_rows - new_rows) * old_row_size; + + if (vc->vc_y > new_rows) { + if (old_rows - vc->vc_y < new_rows) { + /* + * Cursor near the bottom, copy contents from the + * bottom of buffer + */ + old_origin += (old_rows - new_rows) * old_row_size; + end = vc->vc_scr_end; + } else { + /* + * Cursor is in no man's land, copy 1/2 screenful + * from the top and bottom of cursor position + */ + old_origin += (vc->vc_y - new_rows/2) * old_row_size; + end = old_origin + new_screen_size; + } + } else + /* + * Cursor near the top, copy contents from the top of buffer + */ + end = (old_rows > new_rows) ? old_origin + new_screen_size : + vc->vc_scr_end; update_attr(vc); - while (old_origin < vc->vc_scr_end) { - scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth); + while (old_origin < end) { + scr_memcpyw((unsigned short *) new_origin, + (unsigned short *) old_origin, rlth); if (rrem) - scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem); + scr_memsetw((void *)(new_origin + rlth), + vc->vc_video_erase_char, rrem); old_origin += old_row_size; new_origin += new_row_size; } if (new_scr_end > new_origin) - scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin); + scr_memsetw((void *)new_origin, vc->vc_video_erase_char, + new_scr_end - new_origin); if (vc->vc_kmalloced) kfree(vc->vc_screenbuf); vc->vc_screenbuf = newscreen; -- cgit v1.1 From 8d06afab73a75f40ae2864e6c296356bab1ab473 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 9 Sep 2005 13:10:40 -0700 Subject: [PATCH] timer initialization cleanup: DEFINE_TIMER Clean up timer initialization by introducing DEFINE_TIMER a'la DEFINE_SPINLOCK. Build and boot-tested on x86. A similar patch has been been in the -RT tree for some time. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/cyclades.c | 2 +- drivers/char/hangcheck-timer.c | 3 +-- drivers/char/ip2main.c | 2 +- drivers/char/istallion.c | 2 +- drivers/char/keyboard.c | 3 +-- drivers/char/watchdog/mixcomwd.c | 2 +- 6 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 6a5337b..cf4c364 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -865,7 +865,7 @@ static void cyz_poll(unsigned long); static long cyz_polling_cycle = CZ_DEF_POLL; static int cyz_timeron = 0; -static struct timer_list cyz_timerlist = TIMER_INITIALIZER(cyz_poll, 0, 0); +static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); #else /* CONFIG_CYZ_INTR */ static void cyz_rx_restart(unsigned long); diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c index 81d811e..a54bc93 100644 --- a/drivers/char/hangcheck-timer.c +++ b/drivers/char/hangcheck-timer.c @@ -149,8 +149,7 @@ static unsigned long long hangcheck_tsc, hangcheck_tsc_margin; static void hangcheck_fire(unsigned long); -static struct timer_list hangcheck_ticktock = - TIMER_INITIALIZER(hangcheck_fire, 0, 0); +static DEFINE_TIMER(hangcheck_ticktock, hangcheck_fire, 0, 0); static void hangcheck_fire(unsigned long data) diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index 066d7b5..9e4e26a 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c @@ -254,7 +254,7 @@ static unsigned long bh_counter = 0; * selected, the board is serviced periodically to see if anything needs doing. */ #define POLL_TIMEOUT (jiffies + 1) -static struct timer_list PollTimer = TIMER_INITIALIZER(ip2_poll, 0, 0); +static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); static char TimerOn; #ifdef IP2DEBUG_TRACE diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 52a073e..9c19e54 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -780,7 +780,7 @@ static struct file_operations stli_fsiomem = { * much cheaper on host cpu than using interrupts. It turns out to * not increase character latency by much either... */ -static struct timer_list stli_timerlist = TIMER_INITIALIZER(stli_poll, 0, 0); +static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0); static int stli_timeron; diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 523fd3c..1745065 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -233,8 +233,7 @@ static void kd_nosound(unsigned long ignored) } } -static struct timer_list kd_mksound_timer = - TIMER_INITIALIZER(kd_nosound, 0, 0); +static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0); void kd_mksound(unsigned int hz, unsigned int ticks) { diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c index c9b301d..7fc2188 100644 --- a/drivers/char/watchdog/mixcomwd.c +++ b/drivers/char/watchdog/mixcomwd.c @@ -59,7 +59,7 @@ static unsigned long mixcomwd_opened; /* long req'd for setbit --RR */ static int watchdog_port; static int mixcomwd_timer_alive; -static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0); +static DEFINE_TIMER(mixcomwd_timer, NULL, 0, 0); static char expect_close; static int nowayout = WATCHDOG_NOWAYOUT; -- cgit v1.1 From 18fb9442576c79fc2f4bca1fd90c3aa4d1115e97 Mon Sep 17 00:00:00 2001 From: "viro@ZenIV.linux.org.uk" Date: Fri, 9 Sep 2005 20:14:05 +0100 Subject: [PATCH] trivial __user annotations (ipmi) Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_devintf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 883ac43..a09ff10 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -735,7 +735,8 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, case COMPAT_IPMICTL_RECEIVE_MSG: case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC: { - struct ipmi_recv *precv64, recv64; + struct ipmi_recv __user *precv64; + struct ipmi_recv recv64; if (get_compat_ipmi_recv(&recv64, compat_ptr(arg))) return -EFAULT; @@ -748,7 +749,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, ((cmd == COMPAT_IPMICTL_RECEIVE_MSG) ? IPMICTL_RECEIVE_MSG : IPMICTL_RECEIVE_MSG_TRUNC), - (long) precv64); + (unsigned long) precv64); if (rc != 0) return rc; -- cgit v1.1