diff options
Diffstat (limited to 'drivers')
329 files changed, 7196 insertions, 6404 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index 81e3659..34f1e10 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_SGI_SN) += sn/ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ +obj-$(CONFIG_ARCH_SHMOBILE) += sh/ obj-$(CONFIG_GENERIC_TIME) += clocksource/ obj-$(CONFIG_DMA_ENGINE) += dma/ obj-$(CONFIG_DCA) += dca/ diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 66cc3f3..a8d8998 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -32,7 +32,7 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o # acpi-y += bus.o glue.o acpi-y += scan.o -acpi-y += processor_pdc.o +acpi-y += processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o @@ -61,7 +61,7 @@ obj-$(CONFIG_ACPI_SBS) += sbs.o obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o # processor has its own "processor." module_param namespace -processor-y := processor_core.o processor_throttling.o +processor-y := processor_driver.o processor_throttling.o processor-y += processor_idle.o processor_thermal.o processor-$(CONFIG_CPU_FREQ) += processor_perflib.o diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index cc8a102..7116bc8 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -375,8 +375,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Must have a valid thread ID */ - + /* Must have a valid thread. */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, "Cannot release Mutex [%4.4s], null thread info", diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 58d2c91..75f39f2 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -54,6 +54,7 @@ #define ACPI_BATTERY_DEVICE_NAME "Battery" #define ACPI_BATTERY_NOTIFY_STATUS 0x80 #define ACPI_BATTERY_NOTIFY_INFO 0x81 +#define ACPI_BATTERY_NOTIFY_THRESHOLD 0x82 #define _COMPONENT ACPI_BATTERY_COMPONENT @@ -88,10 +89,15 @@ static const struct acpi_device_id battery_device_ids[] = { MODULE_DEVICE_TABLE(acpi, battery_device_ids); -/* For buggy DSDTs that report negative 16-bit values for either charging - * or discharging current and/or report 0 as 65536 due to bad math. - */ -#define QUIRK_SIGNED16_CURRENT 0x0001 +enum { + ACPI_BATTERY_ALARM_PRESENT, + ACPI_BATTERY_XINFO_PRESENT, + /* For buggy DSDTs that report negative 16-bit values for either + * charging or discharging current and/or report 0 as 65536 + * due to bad math. + */ + ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, +}; struct acpi_battery { struct mutex lock; @@ -109,6 +115,12 @@ struct acpi_battery { int design_voltage; int design_capacity_warning; int design_capacity_low; + int cycle_count; + int measurement_accuracy; + int max_sampling_time; + int min_sampling_time; + int max_averaging_interval; + int min_averaging_interval; int capacity_granularity_1; int capacity_granularity_2; int alarm; @@ -118,8 +130,7 @@ struct acpi_battery { char oem_info[32]; int state; int power_unit; - u8 alarm_present; - long quirks; + unsigned long flags; }; #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); @@ -198,6 +209,9 @@ static int acpi_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = acpi_battery_technology(battery); break; + case POWER_SUPPLY_PROP_CYCLE_COUNT: + val->intval = battery->cycle_count; + break; case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: val->intval = battery->design_voltage * 1000; break; @@ -239,6 +253,7 @@ static enum power_supply_property charge_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, @@ -254,6 +269,7 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, @@ -305,6 +321,28 @@ static struct acpi_offsets info_offsets[] = { {offsetof(struct acpi_battery, oem_info), 1}, }; +static struct acpi_offsets extended_info_offsets[] = { + {offsetof(struct acpi_battery, power_unit), 0}, + {offsetof(struct acpi_battery, design_capacity), 0}, + {offsetof(struct acpi_battery, full_charge_capacity), 0}, + {offsetof(struct acpi_battery, technology), 0}, + {offsetof(struct acpi_battery, design_voltage), 0}, + {offsetof(struct acpi_battery, design_capacity_warning), 0}, + {offsetof(struct acpi_battery, design_capacity_low), 0}, + {offsetof(struct acpi_battery, cycle_count), 0}, + {offsetof(struct acpi_battery, measurement_accuracy), 0}, + {offsetof(struct acpi_battery, max_sampling_time), 0}, + {offsetof(struct acpi_battery, min_sampling_time), 0}, + {offsetof(struct acpi_battery, max_averaging_interval), 0}, + {offsetof(struct acpi_battery, min_averaging_interval), 0}, + {offsetof(struct acpi_battery, capacity_granularity_1), 0}, + {offsetof(struct acpi_battery, capacity_granularity_2), 0}, + {offsetof(struct acpi_battery, model_number), 1}, + {offsetof(struct acpi_battery, serial_number), 1}, + {offsetof(struct acpi_battery, type), 1}, + {offsetof(struct acpi_battery, oem_info), 1}, +}; + static int extract_package(struct acpi_battery *battery, union acpi_object *package, struct acpi_offsets *offsets, int num) @@ -350,22 +388,29 @@ static int acpi_battery_get_info(struct acpi_battery *battery) { int result = -EFAULT; acpi_status status = 0; + char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)? + "_BIX" : "_BIF"; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; if (!acpi_battery_present(battery)) return 0; mutex_lock(&battery->lock); - status = acpi_evaluate_object(battery->device->handle, "_BIF", - NULL, &buffer); + status = acpi_evaluate_object(battery->device->handle, name, + NULL, &buffer); mutex_unlock(&battery->lock); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); + ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name)); return -ENODEV; } - - result = extract_package(battery, buffer.pointer, - info_offsets, ARRAY_SIZE(info_offsets)); + if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)) + result = extract_package(battery, buffer.pointer, + extended_info_offsets, + ARRAY_SIZE(extended_info_offsets)); + else + result = extract_package(battery, buffer.pointer, + info_offsets, ARRAY_SIZE(info_offsets)); kfree(buffer.pointer); return result; } @@ -399,7 +444,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery) battery->update_time = jiffies; kfree(buffer.pointer); - if ((battery->quirks & QUIRK_SIGNED16_CURRENT) && + if (test_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags) && battery->rate_now != -1) battery->rate_now = abs((s16)battery->rate_now); @@ -412,7 +457,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER }; struct acpi_object_list arg_list = { 1, &arg0 }; - if (!acpi_battery_present(battery)|| !battery->alarm_present) + if (!acpi_battery_present(battery) || + !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags)) return -ENODEV; arg0.integer.value = battery->alarm; @@ -437,10 +483,10 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) /* See if alarms are supported, and if so, set default */ status = acpi_get_handle(battery->device->handle, "_BTP", &handle); if (ACPI_FAILURE(status)) { - battery->alarm_present = 0; + clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags); return 0; } - battery->alarm_present = 1; + set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags); if (!battery->alarm) battery->alarm = battery->design_capacity_warning; return acpi_battery_set_alarm(battery); @@ -510,9 +556,8 @@ static void sysfs_remove_battery(struct acpi_battery *battery) static void acpi_battery_quirks(struct acpi_battery *battery) { - battery->quirks = 0; if (dmi_name_in_vendors("Acer") && battery->power_unit) { - battery->quirks |= QUIRK_SIGNED16_CURRENT; + set_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags); } } @@ -590,6 +635,7 @@ static int acpi_battery_print_info(struct seq_file *seq, int result) seq_printf(seq, "design capacity low: %d %sh\n", battery->design_capacity_low, acpi_battery_units(battery)); + seq_printf(seq, "cycle count: %i\n", battery->cycle_count); seq_printf(seq, "capacity granularity 1: %d %sh\n", battery->capacity_granularity_1, acpi_battery_units(battery)); @@ -841,6 +887,7 @@ static int acpi_battery_add(struct acpi_device *device) { int result = 0; struct acpi_battery *battery = NULL; + acpi_handle handle; if (!device) return -EINVAL; battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); @@ -851,6 +898,9 @@ static int acpi_battery_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); device->driver_data = battery; mutex_init(&battery->lock); + if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, + "_BIX", &handle))) + set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); acpi_battery_update(battery); #ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_battery_add_fs(device); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a52126e..b70cd37 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -190,16 +190,16 @@ int acpi_bus_get_power(acpi_handle handle, int *state) * Get the device's power state either directly (via _PSC) or * indirectly (via power resources). */ - if (device->power.flags.explicit_get) { + if (device->power.flags.power_resources) { + result = acpi_power_get_inferred_state(device); + if (result) + return result; + } else if (device->power.flags.explicit_get) { status = acpi_evaluate_integer(device->handle, "_PSC", NULL, &psc); if (ACPI_FAILURE(status)) return -ENODEV; device->power.state = (int)psc; - } else if (device->power.flags.power_resources) { - result = acpi_power_get_inferred_state(device); - if (result) - return result; } *state = device->power.state; diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index b2586f5..d9a85f1 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -605,7 +605,7 @@ register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops, list_for_each_entry(dock_station, &dock_stations, sibling) { /* * An ATA bay can be in a dock and itself can be ejected - * seperately, so there are two 'dock stations' which need the + * separately, so there are two 'dock stations' which need the * ops */ dd = find_dock_dependent_device(dock_station, handle); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index d7a6bbb..1ac28c6 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -76,8 +76,9 @@ enum ec_command { enum { EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_STORM, /* GPE storm detected */ - EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and + EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and * OpReg are installed */ + EC_FLAGS_FROZEN, /* Transactions are suspended */ }; /* If we find an EC via the ECDT, we need to keep a ptr to its context */ @@ -291,6 +292,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) if (t->rdata) memset(t->rdata, 0, t->rlen); mutex_lock(&ec->lock); + if (test_bit(EC_FLAGS_FROZEN, &ec->flags)) { + status = -EINVAL; + goto unlock; + } if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) { @@ -453,6 +458,32 @@ int ec_transaction(u8 command, EXPORT_SYMBOL(ec_transaction); +void acpi_ec_suspend_transactions(void) +{ + struct acpi_ec *ec = first_ec; + + if (!ec) + return; + + mutex_lock(&ec->lock); + /* Prevent transactions from being carried out */ + set_bit(EC_FLAGS_FROZEN, &ec->flags); + mutex_unlock(&ec->lock); +} + +void acpi_ec_resume_transactions(void) +{ + struct acpi_ec *ec = first_ec; + + if (!ec) + return; + + mutex_lock(&ec->lock); + /* Allow transactions to be carried out again */ + clear_bit(EC_FLAGS_FROZEN, &ec->flags); + mutex_unlock(&ec->lock); +} + static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) { int result; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 9c4c962..e284113 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -49,6 +49,8 @@ void acpi_early_processor_set_pdc(void); int acpi_ec_init(void); int acpi_ec_ecdt_probe(void); int acpi_boot_ec_enable(void); +void acpi_ec_suspend_transactions(void); +void acpi_ec_resume_transactions(void); /*-------------------------------------------------------------------------- Suspend/Resume diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index d0d25e2..1ac678d 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c @@ -435,7 +435,7 @@ acpi_system_write_wakeup_device(struct file *file, found_dev->wakeup.gpe_device)) { printk(KERN_WARNING "ACPI: '%s' and '%s' have the same GPE, " - "can't disable/enable one seperately\n", + "can't disable/enable one separately\n", dev->pnp.bus_id, found_dev->pnp.bus_id); dev->wakeup.state.enabled = found_dev->wakeup.state.enabled; diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e9b7b40..791ac7b 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -1,383 +1,62 @@ /* - * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $) + * Copyright (C) 2005 Intel Corporation + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. * - * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> - * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> - * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de> - * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> - * - Added processor hotplug support - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * TBD: - * 1. Make # power states dynamic. - * 2. Support duty_cycle values that span bit 4. - * 3. Optimize by having scheduler determine business instead of - * having us try to calculate it here. - * 4. Need C1 timing -- must modify kernel (IRQ handler) to get this. + * Alex Chiang <achiang@hp.com> + * - Unified x86/ia64 implementations + * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> + * - Added _PDC for platforms with Intel CPUs */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/pm.h> -#include <linux/cpufreq.h> -#include <linux/cpu.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> #include <linux/dmi.h> -#include <linux/moduleparam.h> -#include <linux/cpuidle.h> -#include <asm/io.h> -#include <asm/system.h> -#include <asm/cpu.h> -#include <asm/delay.h> -#include <asm/uaccess.h> -#include <asm/processor.h> -#include <asm/smp.h> -#include <asm/acpi.h> - -#include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> #include <acpi/processor.h> -#define PREFIX "ACPI: " - -#define ACPI_PROCESSOR_CLASS "processor" -#define ACPI_PROCESSOR_DEVICE_NAME "Processor" -#define ACPI_PROCESSOR_FILE_INFO "info" -#define ACPI_PROCESSOR_FILE_THROTTLING "throttling" -#define ACPI_PROCESSOR_FILE_LIMIT "limit" -#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 -#define ACPI_PROCESSOR_NOTIFY_POWER 0x81 -#define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 - -#define ACPI_PROCESSOR_LIMIT_USER 0 -#define ACPI_PROCESSOR_LIMIT_THERMAL 1 +#include "internal.h" +#define PREFIX "ACPI: " #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_core"); -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION("ACPI Processor Driver"); -MODULE_LICENSE("GPL"); - -static int acpi_processor_add(struct acpi_device *device); -static int acpi_processor_remove(struct acpi_device *device, int type); -#ifdef CONFIG_ACPI_PROCFS -static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); -#endif -static void acpi_processor_notify(struct acpi_device *device, u32 event); -static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); -static int acpi_processor_handle_eject(struct acpi_processor *pr); - - -static const struct acpi_device_id processor_device_ids[] = { - {ACPI_PROCESSOR_OBJECT_HID, 0}, - {"ACPI0007", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, processor_device_ids); - -static struct acpi_driver acpi_processor_driver = { - .name = "processor", - .class = ACPI_PROCESSOR_CLASS, - .ids = processor_device_ids, - .ops = { - .add = acpi_processor_add, - .remove = acpi_processor_remove, - .suspend = acpi_processor_suspend, - .resume = acpi_processor_resume, - .notify = acpi_processor_notify, - }, -}; - -#define INSTALL_NOTIFY_HANDLER 1 -#define UNINSTALL_NOTIFY_HANDLER 2 -#ifdef CONFIG_ACPI_PROCFS -static const struct file_operations acpi_processor_info_fops = { - .owner = THIS_MODULE, - .open = acpi_processor_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -DEFINE_PER_CPU(struct acpi_processor *, processors); -EXPORT_PER_CPU_SYMBOL(processors); - -struct acpi_processor_errata errata __read_mostly; - -/* -------------------------------------------------------------------------- - Errata Handling - -------------------------------------------------------------------------- */ - -static int acpi_processor_errata_piix4(struct pci_dev *dev) +static int set_no_mwait(const struct dmi_system_id *id) { - u8 value1 = 0; - u8 value2 = 0; - - - if (!dev) - return -EINVAL; - - /* - * Note that 'dev' references the PIIX4 ACPI Controller. - */ - - switch (dev->revision) { - case 0: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n")); - break; - case 1: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n")); - break; - case 2: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n")); - break; - case 3: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n")); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n")); - break; - } - - switch (dev->revision) { - - case 0: /* PIIX4 A-step */ - case 1: /* PIIX4 B-step */ - /* - * See specification changes #13 ("Manual Throttle Duty Cycle") - * and #14 ("Enabling and Disabling Manual Throttle"), plus - * erratum #5 ("STPCLK# Deassertion Time") from the January - * 2002 PIIX4 specification update. Applies to only older - * PIIX4 models. - */ - errata.piix4.throttle = 1; - - case 2: /* PIIX4E */ - case 3: /* PIIX4M */ - /* - * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA - * Livelock") from the January 2002 PIIX4 specification update. - * Applies to all PIIX4 models. - */ - - /* - * BM-IDE - * ------ - * Find the PIIX4 IDE Controller and get the Bus Master IDE - * Status register address. We'll use this later to read - * each IDE controller's DMA status to make sure we catch all - * DMA activity. - */ - dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB, - PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) { - errata.piix4.bmisx = pci_resource_start(dev, 4); - pci_dev_put(dev); - } - - /* - * Type-F DMA - * ---------- - * Find the PIIX4 ISA Controller and read the Motherboard - * DMA controller's status to see if Type-F (Fast) DMA mode - * is enabled (bit 7) on either channel. Note that we'll - * disable C3 support if this is enabled, as some legacy - * devices won't operate well if fast DMA is disabled. - */ - dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_0, - PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) { - pci_read_config_byte(dev, 0x76, &value1); - pci_read_config_byte(dev, 0x77, &value2); - if ((value1 & 0x80) || (value2 & 0x80)) - errata.piix4.fdma = 1; - pci_dev_put(dev); - } - - break; - } - - if (errata.piix4.bmisx) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Bus master activity detection (BM-IDE) erratum enabled\n")); - if (errata.piix4.fdma) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Type-F DMA livelock erratum (C3 disabled)\n")); - + printk(KERN_NOTICE PREFIX "%s detected - " + "disabling mwait for CPU C-states\n", id->ident); + idle_nomwait = 1; return 0; } -static int acpi_processor_errata(struct acpi_processor *pr) -{ - int result = 0; - struct pci_dev *dev = NULL; - - - if (!pr) - return -EINVAL; - - /* - * PIIX4 - */ - dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, - PCI_ANY_ID, NULL); - if (dev) { - result = acpi_processor_errata_piix4(dev); - pci_dev_put(dev); - } - - return result; -} - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_PROCFS -static struct proc_dir_entry *acpi_processor_dir = NULL; - -static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_processor *pr = seq->private; - - - if (!pr) - goto end; - - seq_printf(seq, "processor id: %d\n" - "acpi id: %d\n" - "bus mastering control: %s\n" - "power management: %s\n" - "throttling control: %s\n" - "limit interface: %s\n", - pr->id, - pr->acpi_id, - pr->flags.bm_control ? "yes" : "no", - pr->flags.power ? "yes" : "no", - pr->flags.throttling ? "yes" : "no", - pr->flags.limit ? "yes" : "no"); - - end: - return 0; -} - -static int acpi_processor_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_processor_info_seq_show, - PDE(inode)->data); -} - -static int __cpuinit acpi_processor_add_fs(struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_processor_dir); - if (!acpi_device_dir(device)) - return -ENODEV; - } - - /* 'info' [R] */ - entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO, - S_IRUGO, acpi_device_dir(device), - &acpi_processor_info_fops, - acpi_driver_data(device)); - if (!entry) - return -EIO; - - /* 'throttling' [R/W] */ - entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING, - S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device), - &acpi_processor_throttling_fops, - acpi_driver_data(device)); - if (!entry) - return -EIO; - - /* 'limit' [R/W] */ - entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT, - S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device), - &acpi_processor_limit_fops, - acpi_driver_data(device)); - if (!entry) - return -EIO; - return 0; -} -static int acpi_processor_remove_fs(struct acpi_device *device) -{ - - if (acpi_device_dir(device)) { - remove_proc_entry(ACPI_PROCESSOR_FILE_INFO, - acpi_device_dir(device)); - remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING, - acpi_device_dir(device)); - remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT, - acpi_device_dir(device)); - remove_proc_entry(acpi_device_bid(device), acpi_processor_dir); - acpi_device_dir(device) = NULL; - } - - return 0; -} -#else -static inline int acpi_processor_add_fs(struct acpi_device *device) -{ - return 0; -} -static inline int acpi_processor_remove_fs(struct acpi_device *device) -{ - return 0; -} -#endif - -/* Use the acpiid in MADT to map cpus in case of SMP */ - -#ifndef CONFIG_SMP -static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { return -1; } -#else - -static struct acpi_table_madt *madt; +static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { + { + set_no_mwait, "IFL91 board", { + DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), + DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"), + DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL}, + { + set_no_mwait, "Extensa 5220", { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), + DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, + {}, +}; +#ifdef CONFIG_SMP static int map_lapic_id(struct acpi_subtable_header *entry, u32 acpi_id, int *apic_id) { struct acpi_madt_local_apic *lapic = (struct acpi_madt_local_apic *)entry; - if ((lapic->lapic_flags & ACPI_MADT_ENABLED) && - lapic->processor_id == acpi_id) { - *apic_id = lapic->id; - return 1; - } - return 0; + + if (!(lapic->lapic_flags & ACPI_MADT_ENABLED)) + return 0; + + if (lapic->processor_id != acpi_id) + return 0; + + *apic_id = lapic->id; + return 1; } static int map_x2apic_id(struct acpi_subtable_header *entry, @@ -385,22 +64,16 @@ static int map_x2apic_id(struct acpi_subtable_header *entry, { struct acpi_madt_local_x2apic *apic = (struct acpi_madt_local_x2apic *)entry; - u32 tmp = apic->local_apic_id; - /* Only check enabled APICs*/ if (!(apic->lapic_flags & ACPI_MADT_ENABLED)) return 0; - /* Device statement declaration type */ - if (device_declaration) { - if (apic->uid == acpi_id) - goto found; + if (device_declaration && (apic->uid == acpi_id)) { + *apic_id = apic->local_apic_id; + return 1; } return 0; -found: - *apic_id = tmp; - return 1; } static int map_lsapic_id(struct acpi_subtable_header *entry, @@ -408,35 +81,34 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, { struct acpi_madt_local_sapic *lsapic = (struct acpi_madt_local_sapic *)entry; - u32 tmp = (lsapic->id << 8) | lsapic->eid; - /* Only check enabled APICs*/ if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED)) return 0; - /* Device statement declaration type */ if (device_declaration) { - if (entry->length < 16) - printk(KERN_ERR PREFIX - "Invalid LSAPIC with Device type processor (SAPIC ID %#x)\n", - tmp); - else if (lsapic->uid == acpi_id) - goto found; - /* Processor statement declaration type */ - } else if (lsapic->processor_id == acpi_id) - goto found; + if ((entry->length < 16) || (lsapic->uid != acpi_id)) + return 0; + } else if (lsapic->processor_id != acpi_id) + return 0; - return 0; -found: - *apic_id = tmp; + *apic_id = (lsapic->id << 8) | lsapic->eid; return 1; } static int map_madt_entry(int type, u32 acpi_id) { unsigned long madt_end, entry; + static struct acpi_table_madt *madt; + static int read_madt; int apic_id = -1; + if (!read_madt) { + if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0, + (struct acpi_table_header **)&madt))) + madt = NULL; + read_madt++; + } + if (!madt) return apic_id; @@ -496,7 +168,7 @@ exit: return apic_id; } -static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) +int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) { int i; int apic_id = -1; @@ -513,630 +185,170 @@ static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) } return -1; } +EXPORT_SYMBOL_GPL(acpi_get_cpuid); #endif -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -static int acpi_processor_get_info(struct acpi_device *device) +static bool processor_physically_present(acpi_handle handle) { - acpi_status status = 0; + int cpuid, type; + u32 acpi_id; + acpi_status status; + acpi_object_type acpi_type; + unsigned long long tmp; union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; - struct acpi_processor *pr; - int cpu_index, device_declaration = 0; - static int cpu0_initialized; - - pr = acpi_driver_data(device); - if (!pr) - return -EINVAL; - - if (num_online_cpus() > 1) - errata.smp = TRUE; - - acpi_processor_errata(pr); - - /* - * Check to see if we have bus mastering arbitration control. This - * is required for proper C3 usage (to maintain cache coherency). - */ - if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) { - pr->flags.bm_control = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Bus mastering arbitration control present\n")); - } else - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No bus mastering arbitration control\n")); - - if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) { - /* Declared with "Processor" statement; match ProcessorID */ - status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Evaluating processor object\n"); - return -ENODEV; - } - - /* - * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. - * >>> 'acpi_get_processor_id(acpi_id, &id)' in - * arch/xxx/acpi.c - */ - pr->acpi_id = object.processor.proc_id; - } else { - /* - * Declared with "Device" statement; match _UID. - * Note that we don't handle string _UIDs yet. - */ - unsigned long long value; - status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, - NULL, &value); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Evaluating processor _UID [%#x]\n", status); - return -ENODEV; - } - device_declaration = 1; - pr->acpi_id = value; - } - cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); - - /* Handle UP system running SMP kernel, with no LAPIC in MADT */ - if (!cpu0_initialized && (cpu_index == -1) && - (num_online_cpus() == 1)) { - cpu_index = 0; - } - - cpu0_initialized = 1; - - pr->id = cpu_index; - - /* - * Extra Processor objects may be enumerated on MP systems with - * less than the max # of CPUs. They should be ignored _iff - * they are physically not present. - */ - if (pr->id == -1) { - if (ACPI_FAILURE - (acpi_processor_hotadd_init(pr->handle, &pr->id))) { - return -ENODEV; - } - } - /* - * On some boxes several processors use the same processor bus id. - * But they are located in different scope. For example: - * \_SB.SCK0.CPU0 - * \_SB.SCK1.CPU0 - * Rename the processor device bus id. And the new bus id will be - * generated as the following format: - * CPU+CPU ID. - */ - sprintf(acpi_device_bid(device), "CPU%X", pr->id); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, - pr->acpi_id)); - - if (!object.processor.pblk_address) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); - else if (object.processor.pblk_length != 6) - printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n", - object.processor.pblk_length); - else { - pr->throttling.address = object.processor.pblk_address; - pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset; - pr->throttling.duty_width = acpi_gbl_FADT.duty_width; - - pr->pblk = object.processor.pblk_address; - - /* - * We don't care about error returns - we just try to mark - * these reserved so that nobody else is confused into thinking - * that this region might be unused.. - * - * (In particular, allocating the IO range for Cardbus) - */ - request_region(pr->throttling.address, 6, "ACPI CPU throttle"); - } - - /* - * If ACPI describes a slot number for this CPU, we can use it - * ensure we get the right value in the "physical id" field - * of /proc/cpuinfo - */ - status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer); - if (ACPI_SUCCESS(status)) - arch_fix_phys_package_id(pr->id, object.integer.value); - - return 0; -} - -static DEFINE_PER_CPU(void *, processor_device_array); - -static void acpi_processor_notify(struct acpi_device *device, u32 event) -{ - struct acpi_processor *pr = acpi_driver_data(device); - int saved; - - if (!pr) - return; - switch (event) { - case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: - saved = pr->performance_platform_limit; - acpi_processor_ppc_has_changed(pr, 1); - if (saved == pr->performance_platform_limit) - break; - acpi_bus_generate_proc_event(device, event, - pr->performance_platform_limit); - acpi_bus_generate_netlink_event(device->pnp.device_class, - dev_name(&device->dev), event, - pr->performance_platform_limit); + status = acpi_get_type(handle, &acpi_type); + if (ACPI_FAILURE(status)) + return false; + + switch (acpi_type) { + case ACPI_TYPE_PROCESSOR: + status = acpi_evaluate_object(handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) + return false; + acpi_id = object.processor.proc_id; break; - case ACPI_PROCESSOR_NOTIFY_POWER: - acpi_processor_cst_has_changed(pr); - acpi_bus_generate_proc_event(device, event, 0); - acpi_bus_generate_netlink_event(device->pnp.device_class, - dev_name(&device->dev), event, 0); + case ACPI_TYPE_DEVICE: + status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp); + if (ACPI_FAILURE(status)) + return false; + acpi_id = tmp; break; - case ACPI_PROCESSOR_NOTIFY_THROTTLING: - acpi_processor_tstate_has_changed(pr); - acpi_bus_generate_proc_event(device, event, 0); - acpi_bus_generate_netlink_event(device->pnp.device_class, - dev_name(&device->dev), event, 0); default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; + return false; } - return; -} + type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; + cpuid = acpi_get_cpuid(handle, type, acpi_id); -static int acpi_cpu_soft_notify(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - struct acpi_processor *pr = per_cpu(processors, cpu); + if (cpuid == -1) + return false; - if (action == CPU_ONLINE && pr) { - acpi_processor_ppc_has_changed(pr, 0); - acpi_processor_cst_has_changed(pr); - acpi_processor_tstate_has_changed(pr); - } - return NOTIFY_OK; + return true; } -static struct notifier_block acpi_cpu_notifier = +static void acpi_set_pdc_bits(u32 *buf) { - .notifier_call = acpi_cpu_soft_notify, -}; - -static int __cpuinit acpi_processor_add(struct acpi_device *device) -{ - struct acpi_processor *pr = NULL; - int result = 0; - struct sys_device *sysdev; - - pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); - if (!pr) - return -ENOMEM; - - if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { - kfree(pr); - return -ENOMEM; - } - - pr->handle = device->handle; - strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); - device->driver_data = pr; - - result = acpi_processor_get_info(device); - if (result) { - /* Processor is physically not present */ - return 0; - } - - BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); - - /* - * Buggy BIOS check - * ACPI id of processors can be reported wrongly by the BIOS. - * Don't trust it blindly - */ - if (per_cpu(processor_device_array, pr->id) != NULL && - per_cpu(processor_device_array, pr->id) != device) { - printk(KERN_WARNING "BIOS reported wrong ACPI id " - "for the processor\n"); - result = -ENODEV; - goto err_free_cpumask; - } - per_cpu(processor_device_array, pr->id) = device; + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; - per_cpu(processors, pr->id) = pr; + /* Enable coordination with firmware's _TSD info */ + buf[2] = ACPI_PDC_SMP_T_SWCOORD; - result = acpi_processor_add_fs(device); - if (result) - goto err_free_cpumask; - - sysdev = get_cpu_sysdev(pr->id); - if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { - result = -EFAULT; - goto err_remove_fs; - } - - /* _PDC call should be done before doing anything else (if reqd.). */ - acpi_processor_set_pdc(pr->handle); - -#ifdef CONFIG_CPU_FREQ - acpi_processor_ppc_has_changed(pr, 0); -#endif - acpi_processor_get_throttling_info(pr); - acpi_processor_get_limit_info(pr); - - - acpi_processor_power_init(pr, device); - - pr->cdev = thermal_cooling_device_register("Processor", device, - &processor_cooling_ops); - if (IS_ERR(pr->cdev)) { - result = PTR_ERR(pr->cdev); - goto err_power_exit; - } - - dev_dbg(&device->dev, "registered as cooling_device%d\n", - pr->cdev->id); - - result = sysfs_create_link(&device->dev.kobj, - &pr->cdev->device.kobj, - "thermal_cooling"); - if (result) { - printk(KERN_ERR PREFIX "Create sysfs link\n"); - goto err_thermal_unregister; - } - result = sysfs_create_link(&pr->cdev->device.kobj, - &device->dev.kobj, - "device"); - if (result) { - printk(KERN_ERR PREFIX "Create sysfs link\n"); - goto err_remove_sysfs; - } - - return 0; - -err_remove_sysfs: - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); -err_thermal_unregister: - thermal_cooling_device_unregister(pr->cdev); -err_power_exit: - acpi_processor_power_exit(pr, device); -err_remove_fs: - acpi_processor_remove_fs(device); -err_free_cpumask: - free_cpumask_var(pr->throttling.shared_cpu_map); - - return result; + /* Twiddle arch-specific bits needed for _PDC */ + arch_acpi_set_pdc_bits(buf); } -static int acpi_processor_remove(struct acpi_device *device, int type) +static struct acpi_object_list *acpi_processor_alloc_pdc(void) { - struct acpi_processor *pr = NULL; - - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - pr = acpi_driver_data(device); - - if (pr->id >= nr_cpu_ids) - goto free; + struct acpi_object_list *obj_list; + union acpi_object *obj; + u32 *buf; - if (type == ACPI_BUS_REMOVAL_EJECT) { - if (acpi_processor_handle_eject(pr)) - return -EINVAL; + /* allocate and initialize pdc. It will be used later. */ + obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); + if (!obj_list) { + printk(KERN_ERR "Memory allocation error\n"); + return NULL; } - acpi_processor_power_exit(pr, device); - - sysfs_remove_link(&device->dev.kobj, "sysdev"); - - acpi_processor_remove_fs(device); - - if (pr->cdev) { - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - sysfs_remove_link(&pr->cdev->device.kobj, "device"); - thermal_cooling_device_unregister(pr->cdev); - pr->cdev = NULL; + obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + if (!obj) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj_list); + return NULL; } - per_cpu(processors, pr->id) = NULL; - per_cpu(processor_device_array, pr->id) = NULL; - -free: - free_cpumask_var(pr->throttling.shared_cpu_map); - kfree(pr); - - return 0; -} - -#ifdef CONFIG_ACPI_HOTPLUG_CPU -/**************************************************************************** - * Acpi processor hotplug support * - ****************************************************************************/ - -static int is_processor_present(acpi_handle handle) -{ - acpi_status status; - unsigned long long sta = 0; - - - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - - if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT)) - return 1; - - /* - * _STA is mandatory for a processor that supports hot plug - */ - if (status == AE_NOT_FOUND) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Processor does not support hot plug\n")); - else - ACPI_EXCEPTION((AE_INFO, status, - "Processor Device is not present")); - return 0; -} - -static -int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) -{ - acpi_handle phandle; - struct acpi_device *pdev; - - - if (acpi_get_parent(handle, &phandle)) { - return -ENODEV; + buf = kmalloc(12, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj); + kfree(obj_list); + return NULL; } - if (acpi_bus_get_device(phandle, &pdev)) { - return -ENODEV; - } + acpi_set_pdc_bits(buf); - if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { - return -ENODEV; - } + obj->type = ACPI_TYPE_BUFFER; + obj->buffer.length = 12; + obj->buffer.pointer = (u8 *) buf; + obj_list->count = 1; + obj_list->pointer = obj; - return 0; + return obj_list; } -static void __ref acpi_processor_hotplug_notify(acpi_handle handle, - u32 event, void *data) +/* + * _PDC is required for a BIOS-OS handshake for most of the newer + * ACPI processor features. + */ +static int +acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { - struct acpi_processor *pr; - struct acpi_device *device = NULL; - int result; - + acpi_status status = AE_OK; - switch (event) { - case ACPI_NOTIFY_BUS_CHECK: - case ACPI_NOTIFY_DEVICE_CHECK: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Processor driver received %s event\n", - (event == ACPI_NOTIFY_BUS_CHECK) ? - "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK")); - - if (!is_processor_present(handle)) - break; + if (idle_nomwait) { + /* + * If mwait is disabled for CPU C-states, the C2C3_FFH access + * mode will be disabled in the parameter of _PDC object. + * Of course C1_FFH access mode will also be disabled. + */ + union acpi_object *obj; + u32 *buffer = NULL; - if (acpi_bus_get_device(handle, &device)) { - result = acpi_processor_device_add(handle, &device); - if (result) - printk(KERN_ERR PREFIX - "Unable to add the device\n"); - break; - } - break; - case ACPI_NOTIFY_EJECT_REQUEST: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "received ACPI_NOTIFY_EJECT_REQUEST\n")); + obj = pdc_in->pointer; + buffer = (u32 *)(obj->buffer.pointer); + buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); - if (acpi_bus_get_device(handle, &device)) { - printk(KERN_ERR PREFIX - "Device don't exist, dropping EJECT\n"); - break; - } - pr = acpi_driver_data(device); - if (!pr) { - printk(KERN_ERR PREFIX - "Driver data is NULL, dropping EJECT\n"); - return; - } - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; } + status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); - return; -} - -static acpi_status -processor_walk_namespace_cb(acpi_handle handle, - u32 lvl, void *context, void **rv) -{ - acpi_status status; - int *action = context; - acpi_object_type type = 0; - - status = acpi_get_type(handle, &type); if (ACPI_FAILURE(status)) - return (AE_OK); - - if (type != ACPI_TYPE_PROCESSOR) - return (AE_OK); - - switch (*action) { - case INSTALL_NOTIFY_HANDLER: - acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - acpi_processor_hotplug_notify, - NULL); - break; - case UNINSTALL_NOTIFY_HANDLER: - acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - acpi_processor_hotplug_notify); - break; - default: - break; - } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Could not evaluate _PDC, using legacy perf. control.\n")); - return (AE_OK); + return status; } -static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu) +void acpi_processor_set_pdc(acpi_handle handle) { + struct acpi_object_list *obj_list; - if (!is_processor_present(handle)) { - return AE_ERROR; - } + if (arch_has_acpi_pdc() == false) + return; - if (acpi_map_lsapic(handle, p_cpu)) - return AE_ERROR; + obj_list = acpi_processor_alloc_pdc(); + if (!obj_list) + return; - if (arch_register_cpu(*p_cpu)) { - acpi_unmap_lsapic(*p_cpu); - return AE_ERROR; - } + acpi_processor_eval_pdc(handle, obj_list); - return AE_OK; + kfree(obj_list->pointer->buffer.pointer); + kfree(obj_list->pointer); + kfree(obj_list); } +EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -static int acpi_processor_handle_eject(struct acpi_processor *pr) +static acpi_status +early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { - if (cpu_online(pr->id)) - cpu_down(pr->id); + if (processor_physically_present(handle) == false) + return AE_OK; - arch_unregister_cpu(pr->id); - acpi_unmap_lsapic(pr->id); - return (0); -} -#else -static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu) -{ - return AE_ERROR; -} -static int acpi_processor_handle_eject(struct acpi_processor *pr) -{ - return (-EINVAL); + acpi_processor_set_pdc(handle); + return AE_OK; } -#endif -static -void acpi_processor_install_hotplug_notify(void) +void __init acpi_early_processor_set_pdc(void) { -#ifdef CONFIG_ACPI_HOTPLUG_CPU - int action = INSTALL_NOTIFY_HANDLER; - acpi_walk_namespace(ACPI_TYPE_PROCESSOR, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - processor_walk_namespace_cb, NULL, &action, NULL); -#endif - register_hotcpu_notifier(&acpi_cpu_notifier); -} + /* + * Check whether the system is DMI table. If yes, OSPM + * should not use mwait for CPU-states. + */ + dmi_check_system(processor_idle_dmi_table); -static -void acpi_processor_uninstall_hotplug_notify(void) -{ -#ifdef CONFIG_ACPI_HOTPLUG_CPU - int action = UNINSTALL_NOTIFY_HANDLER; - acpi_walk_namespace(ACPI_TYPE_PROCESSOR, - ACPI_ROOT_OBJECT, + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - processor_walk_namespace_cb, NULL, &action, NULL); -#endif - unregister_hotcpu_notifier(&acpi_cpu_notifier); + early_init_pdc, NULL, NULL, NULL); } - -/* - * We keep the driver loaded even when ACPI is not running. - * This is needed for the powernow-k8 driver, that works even without - * ACPI, but needs symbols from this driver - */ - -static int __init acpi_processor_init(void) -{ - int result = 0; - - if (acpi_disabled) - return 0; - - memset(&errata, 0, sizeof(errata)); - -#ifdef CONFIG_SMP - if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0, - (struct acpi_table_header **)&madt))) - madt = NULL; -#endif -#ifdef CONFIG_ACPI_PROCFS - acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); - if (!acpi_processor_dir) - return -ENOMEM; -#endif - result = cpuidle_register_driver(&acpi_idle_driver); - if (result < 0) - goto out_proc; - - result = acpi_bus_register_driver(&acpi_processor_driver); - if (result < 0) - goto out_cpuidle; - - acpi_processor_install_hotplug_notify(); - - acpi_thermal_cpufreq_init(); - - acpi_processor_ppc_init(); - - acpi_processor_throttling_init(); - - return 0; - -out_cpuidle: - cpuidle_unregister_driver(&acpi_idle_driver); - -out_proc: -#ifdef CONFIG_ACPI_PROCFS - remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); -#endif - - return result; -} - -static void __exit acpi_processor_exit(void) -{ - if (acpi_disabled) - return; - - acpi_processor_ppc_exit(); - - acpi_thermal_cpufreq_exit(); - - acpi_processor_uninstall_hotplug_notify(); - - acpi_bus_unregister_driver(&acpi_processor_driver); - - cpuidle_unregister_driver(&acpi_idle_driver); - -#ifdef CONFIG_ACPI_PROCFS - remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); -#endif - - return; -} - -module_init(acpi_processor_init); -module_exit(acpi_processor_exit); - -EXPORT_SYMBOL(acpi_processor_set_thermal_limit); - -MODULE_ALIAS("processor"); diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c new file mode 100644 index 0000000..b5658cd --- /dev/null +++ b/drivers/acpi/processor_driver.c @@ -0,0 +1,978 @@ +/* + * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $) + * + * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> + * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> + * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de> + * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> + * - Added processor hotplug support + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * TBD: + * 1. Make # power states dynamic. + * 2. Support duty_cycle values that span bit 4. + * 3. Optimize by having scheduler determine business instead of + * having us try to calculate it here. + * 4. Need C1 timing -- must modify kernel (IRQ handler) to get this. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/pm.h> +#include <linux/cpufreq.h> +#include <linux/cpu.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/dmi.h> +#include <linux/moduleparam.h> +#include <linux/cpuidle.h> + +#include <asm/io.h> +#include <asm/system.h> +#include <asm/cpu.h> +#include <asm/delay.h> +#include <asm/uaccess.h> +#include <asm/processor.h> +#include <asm/smp.h> +#include <asm/acpi.h> + +#include <acpi/acpi_bus.h> +#include <acpi/acpi_drivers.h> +#include <acpi/processor.h> + +#define PREFIX "ACPI: " + +#define ACPI_PROCESSOR_CLASS "processor" +#define ACPI_PROCESSOR_DEVICE_NAME "Processor" +#define ACPI_PROCESSOR_FILE_INFO "info" +#define ACPI_PROCESSOR_FILE_THROTTLING "throttling" +#define ACPI_PROCESSOR_FILE_LIMIT "limit" +#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 +#define ACPI_PROCESSOR_NOTIFY_POWER 0x81 +#define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 + +#define ACPI_PROCESSOR_LIMIT_USER 0 +#define ACPI_PROCESSOR_LIMIT_THERMAL 1 + +#define _COMPONENT ACPI_PROCESSOR_COMPONENT +ACPI_MODULE_NAME("processor_driver"); + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION("ACPI Processor Driver"); +MODULE_LICENSE("GPL"); + +static int acpi_processor_add(struct acpi_device *device); +static int acpi_processor_remove(struct acpi_device *device, int type); +#ifdef CONFIG_ACPI_PROCFS +static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); +#endif +static void acpi_processor_notify(struct acpi_device *device, u32 event); +static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); +static int acpi_processor_handle_eject(struct acpi_processor *pr); + + +static const struct acpi_device_id processor_device_ids[] = { + {ACPI_PROCESSOR_OBJECT_HID, 0}, + {"ACPI0007", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, processor_device_ids); + +static struct acpi_driver acpi_processor_driver = { + .name = "processor", + .class = ACPI_PROCESSOR_CLASS, + .ids = processor_device_ids, + .ops = { + .add = acpi_processor_add, + .remove = acpi_processor_remove, + .suspend = acpi_processor_suspend, + .resume = acpi_processor_resume, + .notify = acpi_processor_notify, + }, +}; + +#define INSTALL_NOTIFY_HANDLER 1 +#define UNINSTALL_NOTIFY_HANDLER 2 +#ifdef CONFIG_ACPI_PROCFS +static const struct file_operations acpi_processor_info_fops = { + .owner = THIS_MODULE, + .open = acpi_processor_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +DEFINE_PER_CPU(struct acpi_processor *, processors); +EXPORT_PER_CPU_SYMBOL(processors); + +struct acpi_processor_errata errata __read_mostly; + +/* -------------------------------------------------------------------------- + Errata Handling + -------------------------------------------------------------------------- */ + +static int acpi_processor_errata_piix4(struct pci_dev *dev) +{ + u8 value1 = 0; + u8 value2 = 0; + + + if (!dev) + return -EINVAL; + + /* + * Note that 'dev' references the PIIX4 ACPI Controller. + */ + + switch (dev->revision) { + case 0: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n")); + break; + case 1: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n")); + break; + case 2: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n")); + break; + case 3: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n")); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n")); + break; + } + + switch (dev->revision) { + + case 0: /* PIIX4 A-step */ + case 1: /* PIIX4 B-step */ + /* + * See specification changes #13 ("Manual Throttle Duty Cycle") + * and #14 ("Enabling and Disabling Manual Throttle"), plus + * erratum #5 ("STPCLK# Deassertion Time") from the January + * 2002 PIIX4 specification update. Applies to only older + * PIIX4 models. + */ + errata.piix4.throttle = 1; + + case 2: /* PIIX4E */ + case 3: /* PIIX4M */ + /* + * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA + * Livelock") from the January 2002 PIIX4 specification update. + * Applies to all PIIX4 models. + */ + + /* + * BM-IDE + * ------ + * Find the PIIX4 IDE Controller and get the Bus Master IDE + * Status register address. We'll use this later to read + * each IDE controller's DMA status to make sure we catch all + * DMA activity. + */ + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB, + PCI_ANY_ID, PCI_ANY_ID, NULL); + if (dev) { + errata.piix4.bmisx = pci_resource_start(dev, 4); + pci_dev_put(dev); + } + + /* + * Type-F DMA + * ---------- + * Find the PIIX4 ISA Controller and read the Motherboard + * DMA controller's status to see if Type-F (Fast) DMA mode + * is enabled (bit 7) on either channel. Note that we'll + * disable C3 support if this is enabled, as some legacy + * devices won't operate well if fast DMA is disabled. + */ + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_0, + PCI_ANY_ID, PCI_ANY_ID, NULL); + if (dev) { + pci_read_config_byte(dev, 0x76, &value1); + pci_read_config_byte(dev, 0x77, &value2); + if ((value1 & 0x80) || (value2 & 0x80)) + errata.piix4.fdma = 1; + pci_dev_put(dev); + } + + break; + } + + if (errata.piix4.bmisx) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Bus master activity detection (BM-IDE) erratum enabled\n")); + if (errata.piix4.fdma) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Type-F DMA livelock erratum (C3 disabled)\n")); + + return 0; +} + +static int acpi_processor_errata(struct acpi_processor *pr) +{ + int result = 0; + struct pci_dev *dev = NULL; + + + if (!pr) + return -EINVAL; + + /* + * PIIX4 + */ + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, + PCI_ANY_ID, NULL); + if (dev) { + result = acpi_processor_errata_piix4(dev); + pci_dev_put(dev); + } + + return result; +} + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_PROCFS +static struct proc_dir_entry *acpi_processor_dir = NULL; + +static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_processor *pr = seq->private; + + + if (!pr) + goto end; + + seq_printf(seq, "processor id: %d\n" + "acpi id: %d\n" + "bus mastering control: %s\n" + "power management: %s\n" + "throttling control: %s\n" + "limit interface: %s\n", + pr->id, + pr->acpi_id, + pr->flags.bm_control ? "yes" : "no", + pr->flags.power ? "yes" : "no", + pr->flags.throttling ? "yes" : "no", + pr->flags.limit ? "yes" : "no"); + + end: + return 0; +} + +static int acpi_processor_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_processor_info_seq_show, + PDE(inode)->data); +} + +static int __cpuinit acpi_processor_add_fs(struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_processor_dir); + if (!acpi_device_dir(device)) + return -ENODEV; + } + + /* 'info' [R] */ + entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO, + S_IRUGO, acpi_device_dir(device), + &acpi_processor_info_fops, + acpi_driver_data(device)); + if (!entry) + return -EIO; + + /* 'throttling' [R/W] */ + entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING, + S_IFREG | S_IRUGO | S_IWUSR, + acpi_device_dir(device), + &acpi_processor_throttling_fops, + acpi_driver_data(device)); + if (!entry) + return -EIO; + + /* 'limit' [R/W] */ + entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT, + S_IFREG | S_IRUGO | S_IWUSR, + acpi_device_dir(device), + &acpi_processor_limit_fops, + acpi_driver_data(device)); + if (!entry) + return -EIO; + return 0; +} +static int acpi_processor_remove_fs(struct acpi_device *device) +{ + + if (acpi_device_dir(device)) { + remove_proc_entry(ACPI_PROCESSOR_FILE_INFO, + acpi_device_dir(device)); + remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING, + acpi_device_dir(device)); + remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT, + acpi_device_dir(device)); + remove_proc_entry(acpi_device_bid(device), acpi_processor_dir); + acpi_device_dir(device) = NULL; + } + + return 0; +} +#else +static inline int acpi_processor_add_fs(struct acpi_device *device) +{ + return 0; +} +static inline int acpi_processor_remove_fs(struct acpi_device *device) +{ + return 0; +} +#endif + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +static int acpi_processor_get_info(struct acpi_device *device) +{ + acpi_status status = 0; + union acpi_object object = { 0 }; + struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; + struct acpi_processor *pr; + int cpu_index, device_declaration = 0; + static int cpu0_initialized; + + pr = acpi_driver_data(device); + if (!pr) + return -EINVAL; + + if (num_online_cpus() > 1) + errata.smp = TRUE; + + acpi_processor_errata(pr); + + /* + * Check to see if we have bus mastering arbitration control. This + * is required for proper C3 usage (to maintain cache coherency). + */ + if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) { + pr->flags.bm_control = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Bus mastering arbitration control present\n")); + } else + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "No bus mastering arbitration control\n")); + + if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) { + /* Declared with "Processor" statement; match ProcessorID */ + status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Evaluating processor object\n"); + return -ENODEV; + } + + /* + * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. + * >>> 'acpi_get_processor_id(acpi_id, &id)' in + * arch/xxx/acpi.c + */ + pr->acpi_id = object.processor.proc_id; + } else { + /* + * Declared with "Device" statement; match _UID. + * Note that we don't handle string _UIDs yet. + */ + unsigned long long value; + status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, + NULL, &value); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX + "Evaluating processor _UID [%#x]\n", status); + return -ENODEV; + } + device_declaration = 1; + pr->acpi_id = value; + } + cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id); + + /* Handle UP system running SMP kernel, with no LAPIC in MADT */ + if (!cpu0_initialized && (cpu_index == -1) && + (num_online_cpus() == 1)) { + cpu_index = 0; + } + + cpu0_initialized = 1; + + pr->id = cpu_index; + + /* + * Extra Processor objects may be enumerated on MP systems with + * less than the max # of CPUs. They should be ignored _iff + * they are physically not present. + */ + if (pr->id == -1) { + if (ACPI_FAILURE + (acpi_processor_hotadd_init(pr->handle, &pr->id))) { + return -ENODEV; + } + } + /* + * On some boxes several processors use the same processor bus id. + * But they are located in different scope. For example: + * \_SB.SCK0.CPU0 + * \_SB.SCK1.CPU0 + * Rename the processor device bus id. And the new bus id will be + * generated as the following format: + * CPU+CPU ID. + */ + sprintf(acpi_device_bid(device), "CPU%X", pr->id); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, + pr->acpi_id)); + + if (!object.processor.pblk_address) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); + else if (object.processor.pblk_length != 6) + printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n", + object.processor.pblk_length); + else { + pr->throttling.address = object.processor.pblk_address; + pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset; + pr->throttling.duty_width = acpi_gbl_FADT.duty_width; + + pr->pblk = object.processor.pblk_address; + + /* + * We don't care about error returns - we just try to mark + * these reserved so that nobody else is confused into thinking + * that this region might be unused.. + * + * (In particular, allocating the IO range for Cardbus) + */ + request_region(pr->throttling.address, 6, "ACPI CPU throttle"); + } + + /* + * If ACPI describes a slot number for this CPU, we can use it + * ensure we get the right value in the "physical id" field + * of /proc/cpuinfo + */ + status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer); + if (ACPI_SUCCESS(status)) + arch_fix_phys_package_id(pr->id, object.integer.value); + + return 0; +} + +static DEFINE_PER_CPU(void *, processor_device_array); + +static void acpi_processor_notify(struct acpi_device *device, u32 event) +{ + struct acpi_processor *pr = acpi_driver_data(device); + int saved; + + if (!pr) + return; + + switch (event) { + case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: + saved = pr->performance_platform_limit; + acpi_processor_ppc_has_changed(pr, 1); + if (saved == pr->performance_platform_limit) + break; + acpi_bus_generate_proc_event(device, event, + pr->performance_platform_limit); + acpi_bus_generate_netlink_event(device->pnp.device_class, + dev_name(&device->dev), event, + pr->performance_platform_limit); + break; + case ACPI_PROCESSOR_NOTIFY_POWER: + acpi_processor_cst_has_changed(pr); + acpi_bus_generate_proc_event(device, event, 0); + acpi_bus_generate_netlink_event(device->pnp.device_class, + dev_name(&device->dev), event, 0); + break; + case ACPI_PROCESSOR_NOTIFY_THROTTLING: + acpi_processor_tstate_has_changed(pr); + acpi_bus_generate_proc_event(device, event, 0); + acpi_bus_generate_netlink_event(device->pnp.device_class, + dev_name(&device->dev), event, 0); + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return; +} + +static int acpi_cpu_soft_notify(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + struct acpi_processor *pr = per_cpu(processors, cpu); + + if (action == CPU_ONLINE && pr) { + acpi_processor_ppc_has_changed(pr, 0); + acpi_processor_cst_has_changed(pr); + acpi_processor_tstate_has_changed(pr); + } + return NOTIFY_OK; +} + +static struct notifier_block acpi_cpu_notifier = +{ + .notifier_call = acpi_cpu_soft_notify, +}; + +static int __cpuinit acpi_processor_add(struct acpi_device *device) +{ + struct acpi_processor *pr = NULL; + int result = 0; + struct sys_device *sysdev; + + pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); + if (!pr) + return -ENOMEM; + + if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { + kfree(pr); + return -ENOMEM; + } + + pr->handle = device->handle; + strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); + device->driver_data = pr; + + result = acpi_processor_get_info(device); + if (result) { + /* Processor is physically not present */ + return 0; + } + + BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); + + /* + * Buggy BIOS check + * ACPI id of processors can be reported wrongly by the BIOS. + * Don't trust it blindly + */ + if (per_cpu(processor_device_array, pr->id) != NULL && + per_cpu(processor_device_array, pr->id) != device) { + printk(KERN_WARNING "BIOS reported wrong ACPI id " + "for the processor\n"); + result = -ENODEV; + goto err_free_cpumask; + } + per_cpu(processor_device_array, pr->id) = device; + + per_cpu(processors, pr->id) = pr; + + result = acpi_processor_add_fs(device); + if (result) + goto err_free_cpumask; + + sysdev = get_cpu_sysdev(pr->id); + if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { + result = -EFAULT; + goto err_remove_fs; + } + +#ifdef CONFIG_CPU_FREQ + acpi_processor_ppc_has_changed(pr, 0); +#endif + acpi_processor_get_throttling_info(pr); + acpi_processor_get_limit_info(pr); + + + acpi_processor_power_init(pr, device); + + pr->cdev = thermal_cooling_device_register("Processor", device, + &processor_cooling_ops); + if (IS_ERR(pr->cdev)) { + result = PTR_ERR(pr->cdev); + goto err_power_exit; + } + + dev_dbg(&device->dev, "registered as cooling_device%d\n", + pr->cdev->id); + + result = sysfs_create_link(&device->dev.kobj, + &pr->cdev->device.kobj, + "thermal_cooling"); + if (result) { + printk(KERN_ERR PREFIX "Create sysfs link\n"); + goto err_thermal_unregister; + } + result = sysfs_create_link(&pr->cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) { + printk(KERN_ERR PREFIX "Create sysfs link\n"); + goto err_remove_sysfs; + } + + return 0; + +err_remove_sysfs: + sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); +err_thermal_unregister: + thermal_cooling_device_unregister(pr->cdev); +err_power_exit: + acpi_processor_power_exit(pr, device); +err_remove_fs: + acpi_processor_remove_fs(device); +err_free_cpumask: + free_cpumask_var(pr->throttling.shared_cpu_map); + + return result; +} + +static int acpi_processor_remove(struct acpi_device *device, int type) +{ + struct acpi_processor *pr = NULL; + + + if (!device || !acpi_driver_data(device)) + return -EINVAL; + + pr = acpi_driver_data(device); + + if (pr->id >= nr_cpu_ids) + goto free; + + if (type == ACPI_BUS_REMOVAL_EJECT) { + if (acpi_processor_handle_eject(pr)) + return -EINVAL; + } + + acpi_processor_power_exit(pr, device); + + sysfs_remove_link(&device->dev.kobj, "sysdev"); + + acpi_processor_remove_fs(device); + + if (pr->cdev) { + sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); + sysfs_remove_link(&pr->cdev->device.kobj, "device"); + thermal_cooling_device_unregister(pr->cdev); + pr->cdev = NULL; + } + + per_cpu(processors, pr->id) = NULL; + per_cpu(processor_device_array, pr->id) = NULL; + +free: + free_cpumask_var(pr->throttling.shared_cpu_map); + kfree(pr); + + return 0; +} + +#ifdef CONFIG_ACPI_HOTPLUG_CPU +/**************************************************************************** + * Acpi processor hotplug support * + ****************************************************************************/ + +static int is_processor_present(acpi_handle handle) +{ + acpi_status status; + unsigned long long sta = 0; + + + status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); + + if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT)) + return 1; + + /* + * _STA is mandatory for a processor that supports hot plug + */ + if (status == AE_NOT_FOUND) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Processor does not support hot plug\n")); + else + ACPI_EXCEPTION((AE_INFO, status, + "Processor Device is not present")); + return 0; +} + +static +int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) +{ + acpi_handle phandle; + struct acpi_device *pdev; + + + if (acpi_get_parent(handle, &phandle)) { + return -ENODEV; + } + + if (acpi_bus_get_device(phandle, &pdev)) { + return -ENODEV; + } + + if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { + return -ENODEV; + } + + return 0; +} + +static void __ref acpi_processor_hotplug_notify(acpi_handle handle, + u32 event, void *data) +{ + struct acpi_processor *pr; + struct acpi_device *device = NULL; + int result; + + + switch (event) { + case ACPI_NOTIFY_BUS_CHECK: + case ACPI_NOTIFY_DEVICE_CHECK: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Processor driver received %s event\n", + (event == ACPI_NOTIFY_BUS_CHECK) ? + "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK")); + + if (!is_processor_present(handle)) + break; + + if (acpi_bus_get_device(handle, &device)) { + result = acpi_processor_device_add(handle, &device); + if (result) + printk(KERN_ERR PREFIX + "Unable to add the device\n"); + break; + } + break; + case ACPI_NOTIFY_EJECT_REQUEST: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "received ACPI_NOTIFY_EJECT_REQUEST\n")); + + if (acpi_bus_get_device(handle, &device)) { + printk(KERN_ERR PREFIX + "Device don't exist, dropping EJECT\n"); + break; + } + pr = acpi_driver_data(device); + if (!pr) { + printk(KERN_ERR PREFIX + "Driver data is NULL, dropping EJECT\n"); + return; + } + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return; +} + +static acpi_status +processor_walk_namespace_cb(acpi_handle handle, + u32 lvl, void *context, void **rv) +{ + acpi_status status; + int *action = context; + acpi_object_type type = 0; + + status = acpi_get_type(handle, &type); + if (ACPI_FAILURE(status)) + return (AE_OK); + + if (type != ACPI_TYPE_PROCESSOR) + return (AE_OK); + + switch (*action) { + case INSTALL_NOTIFY_HANDLER: + acpi_install_notify_handler(handle, + ACPI_SYSTEM_NOTIFY, + acpi_processor_hotplug_notify, + NULL); + break; + case UNINSTALL_NOTIFY_HANDLER: + acpi_remove_notify_handler(handle, + ACPI_SYSTEM_NOTIFY, + acpi_processor_hotplug_notify); + break; + default: + break; + } + + return (AE_OK); +} + +static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu) +{ + + if (!is_processor_present(handle)) { + return AE_ERROR; + } + + if (acpi_map_lsapic(handle, p_cpu)) + return AE_ERROR; + + if (arch_register_cpu(*p_cpu)) { + acpi_unmap_lsapic(*p_cpu); + return AE_ERROR; + } + + return AE_OK; +} + +static int acpi_processor_handle_eject(struct acpi_processor *pr) +{ + if (cpu_online(pr->id)) + cpu_down(pr->id); + + arch_unregister_cpu(pr->id); + acpi_unmap_lsapic(pr->id); + return (0); +} +#else +static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu) +{ + return AE_ERROR; +} +static int acpi_processor_handle_eject(struct acpi_processor *pr) +{ + return (-EINVAL); +} +#endif + +static +void acpi_processor_install_hotplug_notify(void) +{ +#ifdef CONFIG_ACPI_HOTPLUG_CPU + int action = INSTALL_NOTIFY_HANDLER; + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, + ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + processor_walk_namespace_cb, NULL, &action, NULL); +#endif + register_hotcpu_notifier(&acpi_cpu_notifier); +} + +static +void acpi_processor_uninstall_hotplug_notify(void) +{ +#ifdef CONFIG_ACPI_HOTPLUG_CPU + int action = UNINSTALL_NOTIFY_HANDLER; + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, + ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + processor_walk_namespace_cb, NULL, &action, NULL); +#endif + unregister_hotcpu_notifier(&acpi_cpu_notifier); +} + +/* + * We keep the driver loaded even when ACPI is not running. + * This is needed for the powernow-k8 driver, that works even without + * ACPI, but needs symbols from this driver + */ + +static int __init acpi_processor_init(void) +{ + int result = 0; + + if (acpi_disabled) + return 0; + + memset(&errata, 0, sizeof(errata)); + +#ifdef CONFIG_ACPI_PROCFS + acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); + if (!acpi_processor_dir) + return -ENOMEM; +#endif + result = cpuidle_register_driver(&acpi_idle_driver); + if (result < 0) + goto out_proc; + + result = acpi_bus_register_driver(&acpi_processor_driver); + if (result < 0) + goto out_cpuidle; + + acpi_processor_install_hotplug_notify(); + + acpi_thermal_cpufreq_init(); + + acpi_processor_ppc_init(); + + acpi_processor_throttling_init(); + + return 0; + +out_cpuidle: + cpuidle_unregister_driver(&acpi_idle_driver); + +out_proc: +#ifdef CONFIG_ACPI_PROCFS + remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); +#endif + + return result; +} + +static void __exit acpi_processor_exit(void) +{ + if (acpi_disabled) + return; + + acpi_processor_ppc_exit(); + + acpi_thermal_cpufreq_exit(); + + acpi_processor_uninstall_hotplug_notify(); + + acpi_bus_unregister_driver(&acpi_processor_driver); + + cpuidle_unregister_driver(&acpi_idle_driver); + +#ifdef CONFIG_ACPI_PROCFS + remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); +#endif + + return; +} + +module_init(acpi_processor_init); +module_exit(acpi_processor_exit); + +EXPORT_SYMBOL(acpi_processor_set_thermal_limit); + +MODULE_ALIAS("processor"); diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c deleted file mode 100644 index e306ba9..0000000 --- a/drivers/acpi/processor_pdc.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2005 Intel Corporation - * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. - * - * Alex Chiang <achiang@hp.com> - * - Unified x86/ia64 implementations - * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> - * - Added _PDC for platforms with Intel CPUs - */ -#include <linux/dmi.h> - -#include <acpi/acpi_drivers.h> -#include <acpi/processor.h> - -#include "internal.h" - -#define PREFIX "ACPI: " -#define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME("processor_pdc"); - -static int set_no_mwait(const struct dmi_system_id *id) -{ - printk(KERN_NOTICE PREFIX "%s detected - " - "disabling mwait for CPU C-states\n", id->ident); - idle_nomwait = 1; - return 0; -} - -static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { - { - set_no_mwait, "IFL91 board", { - DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), - DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"), - DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL}, - { - set_no_mwait, "Extensa 5220", { - DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), - DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, - {}, -}; - -static void acpi_set_pdc_bits(u32 *buf) -{ - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - - /* Enable coordination with firmware's _TSD info */ - buf[2] = ACPI_PDC_SMP_T_SWCOORD; - - /* Twiddle arch-specific bits needed for _PDC */ - arch_acpi_set_pdc_bits(buf); -} - -static struct acpi_object_list *acpi_processor_alloc_pdc(void) -{ - struct acpi_object_list *obj_list; - union acpi_object *obj; - u32 *buf; - - /* allocate and initialize pdc. It will be used later. */ - obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); - if (!obj_list) { - printk(KERN_ERR "Memory allocation error\n"); - return NULL; - } - - obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!obj) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj_list); - return NULL; - } - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj); - kfree(obj_list); - return NULL; - } - - acpi_set_pdc_bits(buf); - - obj->type = ACPI_TYPE_BUFFER; - obj->buffer.length = 12; - obj->buffer.pointer = (u8 *) buf; - obj_list->count = 1; - obj_list->pointer = obj; - - return obj_list; -} - -/* - * _PDC is required for a BIOS-OS handshake for most of the newer - * ACPI processor features. - */ -static int -acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) -{ - acpi_status status = AE_OK; - - if (idle_nomwait) { - /* - * If mwait is disabled for CPU C-states, the C2C3_FFH access - * mode will be disabled in the parameter of _PDC object. - * Of course C1_FFH access mode will also be disabled. - */ - union acpi_object *obj; - u32 *buffer = NULL; - - obj = pdc_in->pointer; - buffer = (u32 *)(obj->buffer.pointer); - buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); - - } - status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); - - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Could not evaluate _PDC, using legacy perf. control.\n")); - - return status; -} - -static int early_pdc_done; - -void acpi_processor_set_pdc(acpi_handle handle) -{ - struct acpi_object_list *obj_list; - - if (arch_has_acpi_pdc() == false) - return; - - if (early_pdc_done) - return; - - obj_list = acpi_processor_alloc_pdc(); - if (!obj_list) - return; - - acpi_processor_eval_pdc(handle, obj_list); - - kfree(obj_list->pointer->buffer.pointer); - kfree(obj_list->pointer); - kfree(obj_list); -} -EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); - -static int early_pdc_optin; -static int set_early_pdc_optin(const struct dmi_system_id *id) -{ - early_pdc_optin = 1; - return 0; -} - -static int param_early_pdc_optin(char *s) -{ - early_pdc_optin = 1; - return 1; -} -__setup("acpi_early_pdc_eval", param_early_pdc_optin); - -static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = { - { - set_early_pdc_optin, "HP Envy", { - DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL}, - { - set_early_pdc_optin, "HP Pavilion dv6", { - DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL}, - { - set_early_pdc_optin, "HP Pavilion dv7", { - DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL}, - {}, -}; - -static acpi_status -early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_processor_set_pdc(handle); - return AE_OK; -} - -void __init acpi_early_processor_set_pdc(void) -{ - /* - * Check whether the system is DMI table. If yes, OSPM - * should not use mwait for CPU-states. - */ - dmi_check_system(processor_idle_dmi_table); - - /* - * Allow systems to opt-in to early _PDC evaluation. - */ - dmi_check_system(early_pdc_optin_table); - if (!early_pdc_optin) - return; - - acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - early_init_pdc, NULL, NULL, NULL); - - early_pdc_done = 1; -} diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 7ded754..29c6f57 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -1133,9 +1133,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) int result = 0; struct acpi_processor_throttling *pthrottling; - if (!pr) - return -EINVAL; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", pr->throttling.address, diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index b16ddbf..89ad111 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -217,6 +217,9 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = acpi_battery_technology(battery); break; + case POWER_SUPPLY_PROP_CYCLE_COUNT: + val->intval = battery->cycle_count; + break; case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: val->intval = battery->design_voltage * acpi_battery_vscale(battery) * 1000; @@ -276,6 +279,7 @@ static enum power_supply_property sbs_charge_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, @@ -560,6 +564,7 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) battery->design_voltage * acpi_battery_vscale(battery)); seq_printf(seq, "design capacity warning: unknown\n"); seq_printf(seq, "design capacity low: unknown\n"); + seq_printf(seq, "cycle count: %i\n", battery->cycle_count); seq_printf(seq, "capacity granularity 1: unknown\n"); seq_printf(seq, "capacity granularity 2: unknown\n"); seq_printf(seq, "model number: %s\n", battery->device_name); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3bde594..f74834a 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -552,8 +552,17 @@ static void acpi_hibernation_leave(void) hibernate_nvs_restore(); } -static void acpi_pm_enable_gpes(void) +static int acpi_pm_pre_restore(void) { + acpi_disable_all_gpes(); + acpi_os_wait_events_complete(NULL); + acpi_ec_suspend_transactions(); + return 0; +} + +static void acpi_pm_restore_cleanup(void) +{ + acpi_ec_resume_transactions(); acpi_enable_all_runtime_gpes(); } @@ -565,8 +574,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { .prepare = acpi_pm_prepare, .enter = acpi_hibernation_enter, .leave = acpi_hibernation_leave, - .pre_restore = acpi_pm_disable_gpes, - .restore_cleanup = acpi_pm_enable_gpes, + .pre_restore = acpi_pm_pre_restore, + .restore_cleanup = acpi_pm_restore_cleanup, }; /** @@ -618,8 +627,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = { .prepare = acpi_pm_disable_gpes, .enter = acpi_hibernation_enter, .leave = acpi_hibernation_leave, - .pre_restore = acpi_pm_disable_gpes, - .restore_cleanup = acpi_pm_enable_gpes, + .pre_restore = acpi_pm_pre_restore, + .restore_cleanup = acpi_pm_restore_cleanup, .recover = acpi_pm_finish, }; #endif /* CONFIG_HIBERNATION */ diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 9073ada..5d38935 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -368,7 +368,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) int valid = 0; int i; - /* Critical Shutdown (required) */ + /* Critical Shutdown */ if (flag & ACPI_TRIPS_CRITICAL) { status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp); @@ -379,17 +379,19 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) * Below zero (Celsius) values clearly aren't right for sure.. * ... so lets discard those as invalid. */ - if (ACPI_FAILURE(status) || - tz->trips.critical.temperature <= 2732) { + if (ACPI_FAILURE(status)) { + tz->trips.critical.flags.valid = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "No critical threshold\n")); + } else if (tmp <= 2732) { + printk(KERN_WARNING FW_BUG "Invalid critical threshold " + "(%llu)\n", tmp); tz->trips.critical.flags.valid = 0; - ACPI_EXCEPTION((AE_INFO, status, - "No or invalid critical threshold")); - return -ENODEV; } else { tz->trips.critical.flags.valid = 1; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found critical threshold [%lu]\n", - tz->trips.critical.temperature)); + "Found critical threshold [%lu]\n", + tz->trips.critical.temperature)); } if (tz->trips.critical.flags.valid == 1) { if (crt == -1) { @@ -575,7 +577,23 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { - return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); + int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); + + if (ret) + return ret; + + valid = tz->trips.critical.flags.valid | + tz->trips.hot.flags.valid | + tz->trips.passive.flags.valid; + + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) + valid |= tz->trips.active[i].flags.valid; + + if (!valid) { + printk(KERN_WARNING FW_BUG "No valid trip found\n"); + return -ENODEV; + } + return 0; } static void acpi_thermal_check(void *data) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 11882db..c9a49f4 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -289,51 +289,6 @@ acpi_evaluate_integer(acpi_handle handle, EXPORT_SYMBOL(acpi_evaluate_integer); -#if 0 -acpi_status -acpi_evaluate_string(acpi_handle handle, - acpi_string pathname, - acpi_object_list * arguments, acpi_string * data) -{ - acpi_status status = AE_OK; - acpi_object *element = NULL; - acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - - - if (!data) - return AE_BAD_PARAMETER; - - status = acpi_evaluate_object(handle, pathname, arguments, &buffer); - if (ACPI_FAILURE(status)) { - acpi_util_eval_error(handle, pathname, status); - return status; - } - - element = (acpi_object *) buffer.pointer; - - if ((element->type != ACPI_TYPE_STRING) - || (element->type != ACPI_TYPE_BUFFER) - || !element->string.length) { - acpi_util_eval_error(handle, pathname, AE_BAD_DATA); - return AE_BAD_DATA; - } - - *data = kzalloc(element->string.length + 1, GFP_KERNEL); - if (!data) { - printk(KERN_ERR PREFIX "Memory allocation\n"); - return -ENOMEM; - } - - memcpy(*data, element->string.pointer, element->string.length); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data)); - - kfree(buffer.pointer); - - return AE_OK; -} -#endif - acpi_status acpi_evaluate_reference(acpi_handle handle, acpi_string pathname, diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 6e9b491..2ff2b6ab 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -327,7 +327,7 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level); static int acpi_video_device_lcd_get_level_current( struct acpi_video_device *device, - unsigned long long *level); + unsigned long long *level, int init); static int acpi_video_get_next_level(struct acpi_video_device *device, u32 level_current, u32 event); static int acpi_video_switch_brightness(struct acpi_video_device *device, @@ -345,7 +345,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd) struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); - if (acpi_video_device_lcd_get_level_current(vd, &cur_level)) + if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0)) return -EINVAL; for (i = 2; i < vd->brightness->count; i++) { if (vd->brightness->levels[i] == cur_level) @@ -414,7 +414,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig unsigned long long level; int offset; - if (acpi_video_device_lcd_get_level_current(video, &level)) + if (acpi_video_device_lcd_get_level_current(video, &level, 0)) return -EINVAL; for (offset = 2; offset < video->brightness->count; offset++) if (level == video->brightness->levels[offset]) { @@ -609,7 +609,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = { static int acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, - unsigned long long *level) + unsigned long long *level, int init) { acpi_status status = AE_OK; int i; @@ -633,10 +633,16 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, device->brightness->curr = *level; return 0; } - /* BQC returned an invalid level. Stop using it. */ - ACPI_WARNING((AE_INFO, "%s returned an invalid level", - buf)); - device->cap._BQC = device->cap._BCQ = 0; + if (!init) { + /* + * BQC returned an invalid level. + * Stop using it. + */ + ACPI_WARNING((AE_INFO, + "%s returned an invalid level", + buf)); + device->cap._BQC = device->cap._BCQ = 0; + } } else { /* Fixme: * should we return an error or ignore this failure? @@ -892,7 +898,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) if (!device->cap._BQC) goto set_level; - result = acpi_video_device_lcd_get_level_current(device, &level_old); + result = acpi_video_device_lcd_get_level_current(device, &level_old, 1); if (result) goto out_free_levels; @@ -903,7 +909,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) if (result) goto out_free_levels; - result = acpi_video_device_lcd_get_level_current(device, &level); + result = acpi_video_device_lcd_get_level_current(device, &level, 0); if (result) goto out_free_levels; @@ -1996,7 +2002,7 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) goto out; result = acpi_video_device_lcd_get_level_current(device, - &level_current); + &level_current, 0); if (result) goto out; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9c77b0d..4a28420 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2232,7 +2232,7 @@ retry: * Some drives were very specific about that exact sequence. * * Note that ATA4 says lba is mandatory so the second check - * shoud never trigger. + * should never trigger. */ if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) { err_mask = ata_dev_init_params(dev, id[3], id[6]); diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 02441fd..561dec2 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2287,7 +2287,7 @@ EXPORT_SYMBOL_GPL(ata_sff_postreset); * @qc: command * * Drain the FIFO and device of any stuck data following a command - * failing to complete. In some cases this is neccessary before a + * failing to complete. In some cases this is necessary before a * reset will recover the device. * */ diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 294f302..8e5e132 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -161,7 +161,7 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev) * * Called when the libata layer is about to issue a command. We wrap * this interface so that we can load the correct ATA timings if - * neccessary. + * necessary. */ static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc) diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index c86c716..727a81c 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -180,7 +180,7 @@ static void hpt3x3_init_chipset(struct pci_dev *dev) * @id: Entry in match table * * Perform basic initialisation. We set the device up so we access all - * ports via BAR4. This is neccessary to work around errata. + * ports via BAR4. This is necessary to work around errata. */ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 3610353..147de2f 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -131,7 +131,7 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev, * @qc: command * * Drain the FIFO and device of any stuck data following a command - * failing to complete. In some cases this is neccessary before a + * failing to complete. In some cases this is necessary before a * reset will recover the device. * */ diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 2bf3a6e..d9301e8 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -95,7 +95,7 @@ extern char usermode_helper[]; /* All EEs on the free list should have ID_VACANT (== 0) * freshly allocated EEs get !ID_VACANT (== 1) - * so if it says "cannot dereference null pointer at adress 0x00000001", + * so if it says "cannot dereference null pointer at address 0x00000001", * it is most likely one of these :( */ #define ID_IN_SYNC (4711ULL) @@ -1171,7 +1171,7 @@ extern int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf /* Meta data layout We reserve a 128MB Block (4k aligned) * either at the end of the backing device - * or on a seperate meta data device. */ + * or on a separate meta data device. */ #define MD_RESERVED_SECT (128LU << 11) /* 128 MB, unit sectors */ /* The following numbers are sectors */ diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index f22c1bc..16119d7 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -57,7 +57,7 @@ * * It may me handed over to the local disk subsystem. * It may be completed by the local disk subsystem, - * either sucessfully or with io-error. + * either successfully or with io-error. * In case it is a READ request, and it failed locally, * it may be retried remotely. * diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index b9b1170..90c4038 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -144,13 +144,23 @@ * Better audit of register_blkdev. */ -#define FLOPPY_SANITY_CHECK #undef FLOPPY_SILENT_DCL_CLEAR #define REALLY_SLOW_IO #define DEBUGT 2 -#define DCL_DEBUG /* debug disk change line */ + +#define DPRINT(format, args...) \ + pr_info("floppy%d: " format, current_drive, ##args) + +#define DCL_DEBUG /* debug disk change line */ +#ifdef DCL_DEBUG +#define debug_dcl(test, fmt, args...) \ + do { if ((test) & FD_DEBUG) DPRINT(fmt, ##args); } while (0) +#else +#define debug_dcl(test, fmt, args...) \ + do { if (0) DPRINT(fmt, ##args); } while (0) +#endif /* do print messages for unexpected interrupts */ static int print_unex = 1; @@ -180,6 +190,8 @@ static int print_unex = 1; #include <linux/mod_devicetable.h> #include <linux/buffer_head.h> /* for invalidate_buffers() */ #include <linux/mutex.h> +#include <linux/io.h> +#include <linux/uaccess.h> /* * PS/2 floppies have much slower step rates than regular floppies. @@ -191,8 +203,6 @@ static int slow_floppy; #include <asm/dma.h> #include <asm/irq.h> #include <asm/system.h> -#include <asm/io.h> -#include <asm/uaccess.h> static int FLOPPY_IRQ = 6; static int FLOPPY_DMA = 2; @@ -241,8 +251,6 @@ static int allowed_drive_mask = 0x33; static int irqdma_allocated; -#define DEVICE_NAME "floppy" - #include <linux/blkdev.h> #include <linux/blkpg.h> #include <linux/cdrom.h> /* for the compatibility eject ioctl */ @@ -250,7 +258,7 @@ static int irqdma_allocated; static struct request *current_req; static struct request_queue *floppy_queue; -static void do_fd_request(struct request_queue * q); +static void do_fd_request(struct request_queue *q); #ifndef fd_get_dma_residue #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) @@ -263,7 +271,7 @@ static void do_fd_request(struct request_queue * q); #endif #ifndef fd_dma_mem_alloc -#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size)) +#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL, get_order(size)) #endif static inline void fallback_on_nodma_alloc(char **addr, size_t l) @@ -273,7 +281,7 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l) return; /* we have the memory */ if (can_use_virtual_dma != 2) return; /* no fallback allowed */ - printk("DMA memory shortage. Temporarily falling back on virtual DMA\n"); + pr_info("DMA memory shortage. Temporarily falling back on virtual DMA\n"); *addr = (char *)nodma_mem_alloc(l); #else return; @@ -283,59 +291,50 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l) /* End dma memory related stuff */ static unsigned long fake_change; -static int initialising = 1; +static bool initialized; -#define ITYPE(x) (((x)>>2) & 0x1f) -#define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) -#define UNIT(x) ((x) & 0x03) /* drive on fdc */ -#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */ +#define ITYPE(x) (((x) >> 2) & 0x1f) +#define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) +#define UNIT(x) ((x) & 0x03) /* drive on fdc */ +#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */ /* reverse mapping from unit and fdc to drive */ #define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2)) -#define DP (&drive_params[current_drive]) -#define DRS (&drive_state[current_drive]) -#define DRWE (&write_errors[current_drive]) -#define FDCS (&fdc_state[fdc]) -#define CLEARF(x) clear_bit(x##_BIT, &DRS->flags) -#define SETF(x) set_bit(x##_BIT, &DRS->flags) -#define TESTF(x) test_bit(x##_BIT, &DRS->flags) -#define UDP (&drive_params[drive]) -#define UDRS (&drive_state[drive]) -#define UDRWE (&write_errors[drive]) -#define UFDCS (&fdc_state[FDC(drive)]) -#define UCLEARF(x) clear_bit(x##_BIT, &UDRS->flags) -#define USETF(x) set_bit(x##_BIT, &UDRS->flags) -#define UTESTF(x) test_bit(x##_BIT, &UDRS->flags) +#define DP (&drive_params[current_drive]) +#define DRS (&drive_state[current_drive]) +#define DRWE (&write_errors[current_drive]) +#define FDCS (&fdc_state[fdc]) -#define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args) +#define UDP (&drive_params[drive]) +#define UDRS (&drive_state[drive]) +#define UDRWE (&write_errors[drive]) +#define UFDCS (&fdc_state[FDC(drive)]) -#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2) -#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH) - -#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x))) +#define PH_HEAD(floppy, head) (((((floppy)->stretch & 2) >> 1) ^ head) << 2) +#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH) /* read/write */ -#define COMMAND raw_cmd->cmd[0] -#define DR_SELECT raw_cmd->cmd[1] -#define TRACK raw_cmd->cmd[2] -#define HEAD raw_cmd->cmd[3] -#define SECTOR raw_cmd->cmd[4] -#define SIZECODE raw_cmd->cmd[5] -#define SECT_PER_TRACK raw_cmd->cmd[6] -#define GAP raw_cmd->cmd[7] -#define SIZECODE2 raw_cmd->cmd[8] +#define COMMAND (raw_cmd->cmd[0]) +#define DR_SELECT (raw_cmd->cmd[1]) +#define TRACK (raw_cmd->cmd[2]) +#define HEAD (raw_cmd->cmd[3]) +#define SECTOR (raw_cmd->cmd[4]) +#define SIZECODE (raw_cmd->cmd[5]) +#define SECT_PER_TRACK (raw_cmd->cmd[6]) +#define GAP (raw_cmd->cmd[7]) +#define SIZECODE2 (raw_cmd->cmd[8]) #define NR_RW 9 /* format */ -#define F_SIZECODE raw_cmd->cmd[2] -#define F_SECT_PER_TRACK raw_cmd->cmd[3] -#define F_GAP raw_cmd->cmd[4] -#define F_FILL raw_cmd->cmd[5] +#define F_SIZECODE (raw_cmd->cmd[2]) +#define F_SECT_PER_TRACK (raw_cmd->cmd[3]) +#define F_GAP (raw_cmd->cmd[4]) +#define F_FILL (raw_cmd->cmd[5]) #define NR_F 6 /* - * Maximum disk size (in kilobytes). This default is used whenever the - * current disk size is unknown. + * Maximum disk size (in kilobytes). + * This default is used whenever the current disk size is unknown. * [Now it is rather a minimum] */ #define MAX_DISK_SIZE 4 /* 3984 */ @@ -345,16 +344,17 @@ static int initialising = 1; */ #define MAX_REPLIES 16 static unsigned char reply_buffer[MAX_REPLIES]; -static int inr; /* size of reply buffer, when called from interrupt */ -#define ST0 (reply_buffer[0]) -#define ST1 (reply_buffer[1]) -#define ST2 (reply_buffer[2]) -#define ST3 (reply_buffer[0]) /* result of GETSTATUS */ -#define R_TRACK (reply_buffer[3]) -#define R_HEAD (reply_buffer[4]) -#define R_SECTOR (reply_buffer[5]) -#define R_SIZECODE (reply_buffer[6]) -#define SEL_DLY (2*HZ/100) +static int inr; /* size of reply buffer, when called from interrupt */ +#define ST0 (reply_buffer[0]) +#define ST1 (reply_buffer[1]) +#define ST2 (reply_buffer[2]) +#define ST3 (reply_buffer[0]) /* result of GETSTATUS */ +#define R_TRACK (reply_buffer[3]) +#define R_HEAD (reply_buffer[4]) +#define R_SECTOR (reply_buffer[5]) +#define R_SIZECODE (reply_buffer[6]) + +#define SEL_DLY (2 * HZ / 100) /* * this struct defines the different floppy drive types. @@ -505,9 +505,9 @@ static char floppy_device_name[] = "floppy"; static int probing; /* Synchronization of FDC access. */ -#define FD_COMMAND_NONE -1 -#define FD_COMMAND_ERROR 2 -#define FD_COMMAND_OKAY 3 +#define FD_COMMAND_NONE -1 +#define FD_COMMAND_ERROR 2 +#define FD_COMMAND_OKAY 3 static volatile int command_status = FD_COMMAND_NONE; static unsigned long fdc_busy; @@ -515,11 +515,6 @@ static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); static DECLARE_WAIT_QUEUE_HEAD(command_done); #define NO_SIGNAL (!interruptible || !signal_pending(current)) -#define CALL(x) if ((x) == -EINTR) return -EINTR -#define ECALL(x) if ((ret = (x))) return ret; -#define _WAIT(x,i) CALL(ret=wait_til_done((x),i)) -#define WAIT(x) _WAIT((x),interruptible) -#define IWAIT(x) _WAIT((x),1) /* Errors during formatting are counted here. */ static int format_errors; @@ -545,8 +540,9 @@ static int max_buffer_sectors; static int *errors; typedef void (*done_f)(int); static struct cont_t { - void (*interrupt)(void); /* this is called after the interrupt of the - * main command */ + void (*interrupt)(void); + /* this is called after the interrupt of the + * main command */ void (*redo)(void); /* this is called to retry the operation */ void (*error)(void); /* this is called to tally an error */ done_f done; /* this is called to say if the operation has @@ -571,7 +567,6 @@ static void floppy_release_irq_and_dma(void); * reset doesn't need to be tested before sending commands, because * output_byte is automatically disabled when reset is set. */ -#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } } static void reset_fdc(void); /* @@ -579,9 +574,9 @@ static void reset_fdc(void); * information to interrupts. They are the data used for the current * request. */ -#define NO_TRACK -1 -#define NEED_1_RECAL -2 -#define NEED_2_RECAL -3 +#define NO_TRACK -1 +#define NEED_1_RECAL -2 +#define NEED_2_RECAL -3 static int usage_count; @@ -621,39 +616,35 @@ static inline void set_debugt(void) debugtimer = jiffies; } -static inline void debugt(const char *message) +static inline void debugt(const char *func, const char *msg) { if (DP->flags & DEBUGT) - printk("%s dtime=%lu\n", message, jiffies - debugtimer); + pr_info("%s:%s dtime=%lu\n", func, msg, jiffies - debugtimer); } #else static inline void set_debugt(void) { } -static inline void debugt(const char *message) { } +static inline void debugt(const char *func, const char *msg) { } #endif /* DEBUGT */ -typedef void (*timeout_fn) (unsigned long); +typedef void (*timeout_fn)(unsigned long); static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0); static const char *timeout_message; -#ifdef FLOPPY_SANITY_CHECK -static void is_alive(const char *message) +static void is_alive(const char *func, const char *message) { /* this routine checks whether the floppy driver is "alive" */ - if (test_bit(0, &fdc_busy) && command_status < 2 - && !timer_pending(&fd_timeout)) { - DPRINT("timeout handler died: %s\n", message); + if (test_bit(0, &fdc_busy) && command_status < 2 && + !timer_pending(&fd_timeout)) { + DPRINT("%s: timeout handler died. %s\n", func, message); } } -#endif -static void (*do_floppy) (void) = NULL; - -#ifdef FLOPPY_SANITY_CHECK +static void (*do_floppy)(void) = NULL; #define OLOGSIZE 20 -static void (*lasthandler) (void); +static void (*lasthandler)(void); static unsigned long interruptjiffies; static unsigned long resultjiffies; static int resultsize; @@ -666,12 +657,11 @@ static struct output_log { } output_log[OLOGSIZE]; static int output_log_pos; -#endif #define current_reqD -1 #define MAXTIMEOUT -2 -static void __reschedule_timeout(int drive, const char *message, int marg) +static void __reschedule_timeout(int drive, const char *message) { if (drive == current_reqD) drive = current_drive; @@ -682,25 +672,22 @@ static void __reschedule_timeout(int drive, const char *message, int marg) } else fd_timeout.expires = jiffies + UDP->timeout; add_timer(&fd_timeout); - if (UDP->flags & FD_DEBUG) { - DPRINT("reschedule timeout "); - printk(message, marg); - printk("\n"); - } + if (UDP->flags & FD_DEBUG) + DPRINT("reschedule timeout %s\n", message); timeout_message = message; } -static void reschedule_timeout(int drive, const char *message, int marg) +static void reschedule_timeout(int drive, const char *message) { unsigned long flags; spin_lock_irqsave(&floppy_lock, flags); - __reschedule_timeout(drive, message, marg); + __reschedule_timeout(drive, message); spin_unlock_irqrestore(&floppy_lock, flags); } -#define INFBOUND(a,b) (a)=max_t(int, a, b) -#define SUPBOUND(a,b) (a)=min_t(int, a, b) +#define INFBOUND(a, b) (a) = max_t(int, a, b) +#define SUPBOUND(a, b) (a) = min_t(int, a, b) /* * Bottom half floppy driver. @@ -739,7 +726,6 @@ static int disk_change(int drive) { int fdc = FDC(drive); -#ifdef FLOPPY_SANITY_CHECK if (time_before(jiffies, UDRS->select_date + UDP->select_delay)) DPRINT("WARNING disk change called early\n"); if (!(FDCS->dor & (0x10 << UNIT(drive))) || @@ -748,31 +734,27 @@ static int disk_change(int drive) DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive), (unsigned int)FDCS->dor); } -#endif -#ifdef DCL_DEBUG - if (UDP->flags & FD_DEBUG) { - DPRINT("checking disk change line for drive %d\n", drive); - DPRINT("jiffies=%lu\n", jiffies); - DPRINT("disk change line=%x\n", fd_inb(FD_DIR) & 0x80); - DPRINT("flags=%lx\n", UDRS->flags); - } -#endif + debug_dcl(UDP->flags, + "checking disk change line for drive %d\n", drive); + debug_dcl(UDP->flags, "jiffies=%lu\n", jiffies); + debug_dcl(UDP->flags, "disk change line=%x\n", fd_inb(FD_DIR) & 0x80); + debug_dcl(UDP->flags, "flags=%lx\n", UDRS->flags); + if (UDP->flags & FD_BROKEN_DCL) - return UTESTF(FD_DISK_CHANGED); + return test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) { - USETF(FD_VERIFY); /* verify write protection */ - if (UDRS->maxblock) { - /* mark it changed */ - USETF(FD_DISK_CHANGED); - } + set_bit(FD_VERIFY_BIT, &UDRS->flags); + /* verify write protection */ + + if (UDRS->maxblock) /* mark it changed */ + set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); /* invalidate its geometry */ if (UDRS->keep_data >= 0) { if ((UDP->flags & FTD_MSG) && current_type[drive] != NULL) - DPRINT("Disk type is undefined after " - "disk change\n"); + DPRINT("Disk type is undefined after disk change\n"); current_type[drive] = NULL; floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1; } @@ -780,7 +762,7 @@ static int disk_change(int drive) return 1; } else { UDRS->last_checked = jiffies; - UCLEARF(FD_DISK_NEWCHANGE); + clear_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags); } return 0; } @@ -790,6 +772,12 @@ static inline int is_selected(int dor, int unit) return ((dor & (0x10 << unit)) && (dor & 3) == unit); } +static bool is_ready_state(int status) +{ + int state = status & (STATUS_READY | STATUS_DIR | STATUS_DMA); + return state == STATUS_READY; +} + static int set_dor(int fdc, char mask, char data) { unsigned char unit; @@ -806,11 +794,8 @@ static int set_dor(int fdc, char mask, char data) unit = olddor & 0x3; if (is_selected(olddor, unit) && !is_selected(newdor, unit)) { drive = REVDRIVE(fdc, unit); -#ifdef DCL_DEBUG - if (UDP->flags & FD_DEBUG) { - DPRINT("calling disk change from set_dor\n"); - } -#endif + debug_dcl(UDP->flags, + "calling disk change from set_dor\n"); disk_change(drive); } FDCS->dor = newdor; @@ -834,8 +819,10 @@ static void twaddle(void) DRS->select_date = jiffies; } -/* reset all driver information about the current fdc. This is needed after - * a reset, and after a raw command. */ +/* + * Reset all driver information about the current fdc. + * This is needed after a reset, and after a raw command. + */ static void reset_fdc_info(int mode) { int drive; @@ -857,7 +844,7 @@ static void set_fdc(int drive) current_drive = drive; } if (fdc != 1 && fdc != 0) { - printk("bad fdc value\n"); + pr_info("bad fdc value\n"); return; } set_dor(fdc, ~0, 8); @@ -871,11 +858,10 @@ static void set_fdc(int drive) } /* locks the driver */ -static int _lock_fdc(int drive, int interruptible, int line) +static int _lock_fdc(int drive, bool interruptible, int line) { if (!usage_count) { - printk(KERN_ERR - "Trying to lock fdc while usage count=0 at line %d\n", + pr_err("Trying to lock fdc while usage count=0 at line %d\n", line); return -1; } @@ -904,15 +890,13 @@ static int _lock_fdc(int drive, int interruptible, int line) } command_status = FD_COMMAND_NONE; - __reschedule_timeout(drive, "lock fdc", 0); + __reschedule_timeout(drive, "lock fdc"); set_fdc(drive); return 0; } -#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__) - -#define LOCK_FDC(drive,interruptible) \ -if (lock_fdc(drive,interruptible)) return -EINTR; +#define lock_fdc(drive, interruptible) \ + _lock_fdc(drive, interruptible, __LINE__) /* unlocks the driver */ static inline void unlock_fdc(void) @@ -924,7 +908,7 @@ static inline void unlock_fdc(void) DPRINT("FDC access conflict!\n"); if (do_floppy) - DPRINT("device interrupt still active at FDC release: %p!\n", + DPRINT("device interrupt still active at FDC release: %pf!\n", do_floppy); command_status = FD_COMMAND_NONE; spin_lock_irqsave(&floppy_lock, flags); @@ -1003,7 +987,7 @@ static void empty(void) static DECLARE_WORK(floppy_work, NULL); -static void schedule_bh(void (*handler) (void)) +static void schedule_bh(void (*handler)(void)) { PREPARE_WORK(&floppy_work, (work_func_t)handler); schedule_work(&floppy_work); @@ -1026,11 +1010,7 @@ static void cancel_activity(void) * transfer */ static void fd_watchdog(void) { -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG) { - DPRINT("calling disk change from watchdog\n"); - } -#endif + debug_dcl(DP->flags, "calling disk change from watchdog\n"); if (disk_change(current_drive)) { DPRINT("disk removed during i/o\n"); @@ -1039,7 +1019,7 @@ static void fd_watchdog(void) reset_fdc(); } else { del_timer(&fd_timer); - fd_timer.function = (timeout_fn) fd_watchdog; + fd_timer.function = (timeout_fn)fd_watchdog; fd_timer.expires = jiffies + HZ / 10; add_timer(&fd_timer); } @@ -1105,25 +1085,23 @@ static void setup_DMA(void) { unsigned long f; -#ifdef FLOPPY_SANITY_CHECK if (raw_cmd->length == 0) { int i; - printk("zero dma transfer size:"); + pr_info("zero dma transfer size:"); for (i = 0; i < raw_cmd->cmd_count; i++) - printk("%x,", raw_cmd->cmd[i]); - printk("\n"); + pr_cont("%x,", raw_cmd->cmd[i]); + pr_cont("\n"); cont->done(0); FDCS->reset = 1; return; } if (((unsigned long)raw_cmd->kernel_data) % 512) { - printk("non aligned address: %p\n", raw_cmd->kernel_data); + pr_info("non aligned address: %p\n", raw_cmd->kernel_data); cont->done(0); FDCS->reset = 1; return; } -#endif f = claim_dma_lock(); fd_disable_dma(); #ifdef fd_dma_setup @@ -1165,7 +1143,7 @@ static int wait_til_ready(void) if (status & STATUS_READY) return status; } - if (!initialising) { + if (initialized) { DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc); show_floppy(); } @@ -1176,22 +1154,21 @@ static int wait_til_ready(void) /* sends a command byte to the fdc */ static int output_byte(char byte) { - int status; + int status = wait_til_ready(); - if ((status = wait_til_ready()) < 0) + if (status < 0) return -1; - if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) { + + if (is_ready_state(status)) { fd_outb(byte, FD_DATA); -#ifdef FLOPPY_SANITY_CHECK output_log[output_log_pos].data = byte; output_log[output_log_pos].status = status; output_log[output_log_pos].jiffies = jiffies; output_log_pos = (output_log_pos + 1) % OLOGSIZE; -#endif return 0; } FDCS->reset = 1; - if (!initialising) { + if (initialized) { DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n", byte, fdc, status); show_floppy(); @@ -1199,8 +1176,6 @@ static int output_byte(char byte) return -1; } -#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;} - /* gets the response from the fdc */ static int result(void) { @@ -1208,14 +1183,13 @@ static int result(void) int status = 0; for (i = 0; i < MAX_REPLIES; i++) { - if ((status = wait_til_ready()) < 0) + status = wait_til_ready(); + if (status < 0) break; status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA; if ((status & ~STATUS_BUSY) == STATUS_READY) { -#ifdef FLOPPY_SANITY_CHECK resultjiffies = jiffies; resultsize = i; -#endif return i; } if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY)) @@ -1223,10 +1197,9 @@ static int result(void) else break; } - if (!initialising) { - DPRINT - ("get result error. Fdc=%d Last status=%x Read bytes=%d\n", - fdc, status, i); + if (initialized) { + DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n", + fdc, status, i); show_floppy(); } FDCS->reset = 1; @@ -1237,12 +1210,14 @@ static int result(void) /* does the fdc need more output? */ static int need_more_output(void) { - int status; + int status = wait_til_ready(); - if ((status = wait_til_ready()) < 0) + if (status < 0) return -1; - if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) + + if (is_ready_state(status)) return MORE_OUTPUT; + return result(); } @@ -1264,9 +1239,12 @@ static inline void perpendicular_mode(void) default: DPRINT("Invalid data rate for perpendicular mode!\n"); cont->done(0); - FDCS->reset = 1; /* convenient way to return to - * redo without to much hassle (deep - * stack et al. */ + FDCS->reset = 1; + /* + * convenient way to return to + * redo without too much hassle + * (deep stack et al.) + */ return; } } else @@ -1366,9 +1344,9 @@ static void fdc_specify(void) /* Convert step rate from microseconds to milliseconds and 4 bits */ srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR); - if (slow_floppy) { + if (slow_floppy) srt = srt / 4; - } + SUPBOUND(srt, 0xf); INFBOUND(srt, 0); @@ -1415,16 +1393,46 @@ static int fdc_dtr(void) * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) */ FDCS->dtr = raw_cmd->rate & 3; - return (fd_wait_for_completion(jiffies + 2UL * HZ / 100, - (timeout_fn) floppy_ready)); + return fd_wait_for_completion(jiffies + 2UL * HZ / 100, + (timeout_fn)floppy_ready); } /* fdc_dtr */ static void tell_sector(void) { - printk(": track %d, head %d, sector %d, size %d", - R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE); + pr_cont(": track %d, head %d, sector %d, size %d", + R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE); } /* tell_sector */ +static void print_errors(void) +{ + DPRINT(""); + if (ST0 & ST0_ECE) { + pr_cont("Recalibrate failed!"); + } else if (ST2 & ST2_CRC) { + pr_cont("data CRC error"); + tell_sector(); + } else if (ST1 & ST1_CRC) { + pr_cont("CRC error"); + tell_sector(); + } else if ((ST1 & (ST1_MAM | ST1_ND)) || + (ST2 & ST2_MAM)) { + if (!probing) { + pr_cont("sector not found"); + tell_sector(); + } else + pr_cont("probe failed..."); + } else if (ST2 & ST2_WC) { /* seek error */ + pr_cont("wrong cylinder"); + } else if (ST2 & ST2_BC) { /* cylinder marked as bad */ + pr_cont("bad cylinder"); + } else { + pr_cont("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", + ST0, ST1, ST2); + tell_sector(); + } + pr_cont("\n"); +} + /* * OK, this error interpreting routine is called after a * DMA read/write has succeeded @@ -1437,7 +1445,7 @@ static int interpret_errors(void) char bad; if (inr != 7) { - DPRINT("-- FDC reply error"); + DPRINT("-- FDC reply error\n"); FDCS->reset = 1; return 1; } @@ -1450,43 +1458,17 @@ static int interpret_errors(void) bad = 1; if (ST1 & ST1_WP) { DPRINT("Drive is write protected\n"); - CLEARF(FD_DISK_WRITABLE); + clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); cont->done(0); bad = 2; } else if (ST1 & ST1_ND) { - SETF(FD_NEED_TWADDLE); + set_bit(FD_NEED_TWADDLE_BIT, &DRS->flags); } else if (ST1 & ST1_OR) { if (DP->flags & FTD_MSG) DPRINT("Over/Underrun - retrying\n"); bad = 0; } else if (*errors >= DP->max_errors.reporting) { - DPRINT(""); - if (ST0 & ST0_ECE) { - printk("Recalibrate failed!"); - } else if (ST2 & ST2_CRC) { - printk("data CRC error"); - tell_sector(); - } else if (ST1 & ST1_CRC) { - printk("CRC error"); - tell_sector(); - } else if ((ST1 & (ST1_MAM | ST1_ND)) - || (ST2 & ST2_MAM)) { - if (!probing) { - printk("sector not found"); - tell_sector(); - } else - printk("probe failed..."); - } else if (ST2 & ST2_WC) { /* seek error */ - printk("wrong cylinder"); - } else if (ST2 & ST2_BC) { /* cylinder marked as bad */ - printk("bad cylinder"); - } else { - printk - ("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", - ST0, ST1, ST2); - tell_sector(); - } - printk("\n"); + print_errors(); } if (ST2 & ST2_WC || ST2 & ST2_BC) /* wrong cylinder => recal */ @@ -1531,9 +1513,9 @@ static void setup_rw_floppy(void) */ if (time_after(ready_date, jiffies + DP->select_delay)) { ready_date -= DP->select_delay; - function = (timeout_fn) floppy_start; + function = (timeout_fn)floppy_start; } else - function = (timeout_fn) setup_rw_floppy; + function = (timeout_fn)setup_rw_floppy; /* wait until the floppy is spinning fast enough */ if (fd_wait_for_completion(ready_date, function)) @@ -1551,7 +1533,7 @@ static void setup_rw_floppy(void) for (i = 0; i < raw_cmd->cmd_count; i++) r |= output_byte(raw_cmd->cmd[i]); - debugt("rw_command: "); + debugt(__func__, "rw_command"); if (r) { cont->error(); @@ -1574,7 +1556,7 @@ static int blind_seek; */ static void seek_interrupt(void) { - debugt("seek interrupt:"); + debugt(__func__, ""); if (inr != 2 || (ST0 & 0xF8) != 0x20) { DPRINT("seek failed\n"); DRS->track = NEED_2_RECAL; @@ -1583,14 +1565,11 @@ static void seek_interrupt(void) return; } if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) { -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG) { - DPRINT - ("clearing NEWCHANGE flag because of effective seek\n"); - DPRINT("jiffies=%lu\n", jiffies); - } -#endif - CLEARF(FD_DISK_NEWCHANGE); /* effective seek */ + debug_dcl(DP->flags, + "clearing NEWCHANGE flag because of effective seek\n"); + debug_dcl(DP->flags, "jiffies=%lu\n", jiffies); + clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); + /* effective seek */ DRS->select_date = jiffies; } DRS->track = ST1; @@ -1599,26 +1578,23 @@ static void seek_interrupt(void) static void check_wp(void) { - if (TESTF(FD_VERIFY)) { - /* check write protection */ + if (test_bit(FD_VERIFY_BIT, &DRS->flags)) { + /* check write protection */ output_byte(FD_GETSTATUS); output_byte(UNIT(current_drive)); if (result() != 1) { FDCS->reset = 1; return; } - CLEARF(FD_VERIFY); - CLEARF(FD_NEED_TWADDLE); -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG) { - DPRINT("checking whether disk is write protected\n"); - DPRINT("wp=%x\n", ST3 & 0x40); - } -#endif + clear_bit(FD_VERIFY_BIT, &DRS->flags); + clear_bit(FD_NEED_TWADDLE_BIT, &DRS->flags); + debug_dcl(DP->flags, + "checking whether disk is write protected\n"); + debug_dcl(DP->flags, "wp=%x\n", ST3 & 0x40); if (!(ST3 & 0x40)) - SETF(FD_DISK_WRITABLE); + set_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); else - CLEARF(FD_DISK_WRITABLE); + clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); } } @@ -1628,19 +1604,15 @@ static void seek_floppy(void) blind_seek = 0; -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG) { - DPRINT("calling disk change from seek\n"); - } -#endif + debug_dcl(DP->flags, "calling disk change from %s\n", __func__); - if (!TESTF(FD_DISK_NEWCHANGE) && + if (!test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) && disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) { /* the media changed flag should be cleared after the seek. * If it isn't, this means that there is really no disk in * the drive. */ - SETF(FD_DISK_CHANGED); + set_bit(FD_DISK_CHANGED_BIT, &DRS->flags); cont->done(0); cont->redo(); return; @@ -1648,7 +1620,7 @@ static void seek_floppy(void) if (DRS->track <= NEED_1_RECAL) { recalibrate_floppy(); return; - } else if (TESTF(FD_DISK_NEWCHANGE) && + } else if (test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) && (raw_cmd->flags & FD_RAW_NEED_DISK) && (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) { /* we seek to clear the media-changed condition. Does anybody @@ -1677,19 +1649,22 @@ static void seek_floppy(void) do_floppy = seek_interrupt; output_byte(FD_SEEK); output_byte(UNIT(current_drive)); - LAST_OUT(track); - debugt("seek command:"); + if (output_byte(track) < 0) { + reset_fdc(); + return; + } + debugt(__func__, ""); } static void recal_interrupt(void) { - debugt("recal interrupt:"); + debugt(__func__, ""); if (inr != 2) FDCS->reset = 1; else if (ST0 & ST0_ECE) { switch (DRS->track) { case NEED_1_RECAL: - debugt("recal interrupt need 1 recal:"); + debugt(__func__, "need 1 recal"); /* after a second recalibrate, we still haven't * reached track 0. Probably no drive. Raise an * error, as failing immediately might upset @@ -1698,25 +1673,21 @@ static void recal_interrupt(void) cont->redo(); return; case NEED_2_RECAL: - debugt("recal interrupt need 2 recal:"); + debugt(__func__, "need 2 recal"); /* If we already did a recalibrate, * and we are not at track 0, this * means we have moved. (The only way * not to move at recalibration is to * be already at track 0.) Clear the * new change flag */ -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG) { - DPRINT - ("clearing NEWCHANGE flag because of second recalibrate\n"); - } -#endif + debug_dcl(DP->flags, + "clearing NEWCHANGE flag because of second recalibrate\n"); - CLEARF(FD_DISK_NEWCHANGE); + clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); DRS->select_date = jiffies; /* fall through */ default: - debugt("recal interrupt default:"); + debugt(__func__, "default"); /* Recalibrate moves the head by at * most 80 steps. If after one * recalibrate we don't have reached @@ -1738,8 +1709,8 @@ static void print_result(char *message, int inr) DPRINT("%s ", message); if (inr >= 0) for (i = 0; i < inr; i++) - printk("repl[%d]=%x ", i, reply_buffer[i]); - printk("\n"); + pr_cont("repl[%d]=%x ", i, reply_buffer[i]); + pr_cont("\n"); } /* interrupt handler. Note that this can be called externally on the Sparc */ @@ -1760,10 +1731,10 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) do_floppy = NULL; if (fdc >= N_FDC || FDCS->address == -1) { /* we don't even know which FDC is the culprit */ - printk("DOR0=%x\n", fdc_state[0].dor); - printk("floppy interrupt on bizarre fdc %d\n", fdc); - printk("handler=%p\n", handler); - is_alive("bizarre fdc"); + pr_info("DOR0=%x\n", fdc_state[0].dor); + pr_info("floppy interrupt on bizarre fdc %d\n", fdc); + pr_info("handler=%pf\n", handler); + is_alive(__func__, "bizarre fdc"); return IRQ_NONE; } @@ -1777,7 +1748,7 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) * activity. */ - do_print = !handler && print_unex && !initialising; + do_print = !handler && print_unex && initialized; inr = result(); if (do_print) @@ -1790,15 +1761,15 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) if (do_print) print_result("sensei", inr); max_sensei--; - } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2 - && max_sensei); + } while ((ST0 & 0x83) != UNIT(current_drive) && + inr == 2 && max_sensei); } if (!handler) { FDCS->reset = 1; return IRQ_NONE; } schedule_bh(handler); - is_alive("normal interrupt end"); + is_alive(__func__, "normal interrupt end"); /* FIXME! Was it really for us? */ return IRQ_HANDLED; @@ -1806,10 +1777,11 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) static void recalibrate_floppy(void) { - debugt("recalibrate floppy:"); + debugt(__func__, ""); do_floppy = recal_interrupt; output_byte(FD_RECALIBRATE); - LAST_OUT(UNIT(current_drive)); + if (output_byte(UNIT(current_drive)) < 0) + reset_fdc(); } /* @@ -1817,10 +1789,10 @@ static void recalibrate_floppy(void) */ static void reset_interrupt(void) { - debugt("reset interrupt:"); + debugt(__func__, ""); result(); /* get the status ready for set_fdc */ if (FDCS->reset) { - printk("reset set in interrupt, calling %p\n", cont->error); + pr_info("reset set in interrupt, calling %pf\n", cont->error); cont->error(); /* a reset just after a reset. BAD! */ } cont->redo(); @@ -1858,53 +1830,49 @@ static void show_floppy(void) { int i; - printk("\n"); - printk("floppy driver state\n"); - printk("-------------------\n"); - printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n", - jiffies, interruptjiffies, jiffies - interruptjiffies, - lasthandler); + pr_info("\n"); + pr_info("floppy driver state\n"); + pr_info("-------------------\n"); + pr_info("now=%lu last interrupt=%lu diff=%lu last called handler=%pf\n", + jiffies, interruptjiffies, jiffies - interruptjiffies, + lasthandler); -#ifdef FLOPPY_SANITY_CHECK - printk("timeout_message=%s\n", timeout_message); - printk("last output bytes:\n"); + pr_info("timeout_message=%s\n", timeout_message); + pr_info("last output bytes:\n"); for (i = 0; i < OLOGSIZE; i++) - printk("%2x %2x %lu\n", - output_log[(i + output_log_pos) % OLOGSIZE].data, - output_log[(i + output_log_pos) % OLOGSIZE].status, - output_log[(i + output_log_pos) % OLOGSIZE].jiffies); - printk("last result at %lu\n", resultjiffies); - printk("last redo_fd_request at %lu\n", lastredo); - for (i = 0; i < resultsize; i++) { - printk("%2x ", reply_buffer[i]); - } - printk("\n"); -#endif - - printk("status=%x\n", fd_inb(FD_STATUS)); - printk("fdc_busy=%lu\n", fdc_busy); + pr_info("%2x %2x %lu\n", + output_log[(i + output_log_pos) % OLOGSIZE].data, + output_log[(i + output_log_pos) % OLOGSIZE].status, + output_log[(i + output_log_pos) % OLOGSIZE].jiffies); + pr_info("last result at %lu\n", resultjiffies); + pr_info("last redo_fd_request at %lu\n", lastredo); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, + reply_buffer, resultsize, true); + + pr_info("status=%x\n", fd_inb(FD_STATUS)); + pr_info("fdc_busy=%lu\n", fdc_busy); if (do_floppy) - printk("do_floppy=%p\n", do_floppy); + pr_info("do_floppy=%pf\n", do_floppy); if (work_pending(&floppy_work)) - printk("floppy_work.func=%p\n", floppy_work.func); + pr_info("floppy_work.func=%pf\n", floppy_work.func); if (timer_pending(&fd_timer)) - printk("fd_timer.function=%p\n", fd_timer.function); + pr_info("fd_timer.function=%pf\n", fd_timer.function); if (timer_pending(&fd_timeout)) { - printk("timer_function=%p\n", fd_timeout.function); - printk("expires=%lu\n", fd_timeout.expires - jiffies); - printk("now=%lu\n", jiffies); - } - printk("cont=%p\n", cont); - printk("current_req=%p\n", current_req); - printk("command_status=%d\n", command_status); - printk("\n"); + pr_info("timer_function=%pf\n", fd_timeout.function); + pr_info("expires=%lu\n", fd_timeout.expires - jiffies); + pr_info("now=%lu\n", jiffies); + } + pr_info("cont=%p\n", cont); + pr_info("current_req=%p\n", current_req); + pr_info("command_status=%d\n", command_status); + pr_info("\n"); } static void floppy_shutdown(unsigned long data) { unsigned long flags; - if (!initialising) + if (initialized) show_floppy(); cancel_activity(); @@ -1916,17 +1884,17 @@ static void floppy_shutdown(unsigned long data) /* avoid dma going to a random drive after shutdown */ - if (!initialising) + if (initialized) DPRINT("floppy timeout called\n"); FDCS->reset = 1; if (cont) { cont->done(0); cont->redo(); /* this will recall reset when needed */ } else { - printk("no cont in shutdown!\n"); + pr_info("no cont in shutdown!\n"); process_fd_request(); } - is_alive("floppy shutdown"); + is_alive(__func__, ""); } /* start motor, check media-changed condition and write protection */ @@ -1954,27 +1922,26 @@ static int start_motor(void (*function)(void)) set_dor(fdc, mask, data); /* wait_for_completion also schedules reset if needed. */ - return (fd_wait_for_completion(DRS->select_date + DP->select_delay, - (timeout_fn) function)); + return fd_wait_for_completion(DRS->select_date + DP->select_delay, + (timeout_fn)function); } static void floppy_ready(void) { - CHECK_RESET; + if (FDCS->reset) { + reset_fdc(); + return; + } if (start_motor(floppy_ready)) return; if (fdc_dtr()) return; -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG) { - DPRINT("calling disk change from floppy_ready\n"); - } -#endif + debug_dcl(DP->flags, "calling disk change from floppy_ready\n"); if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) && disk_change(current_drive) && !DP->select_delay) - twaddle(); /* this clears the dcl on certain drive/controller - * combinations */ + twaddle(); /* this clears the dcl on certain + * drive/controller combinations */ #ifdef fd_chose_dma_mode if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) { @@ -1998,15 +1965,11 @@ static void floppy_ready(void) static void floppy_start(void) { - reschedule_timeout(current_reqD, "floppy start", 0); + reschedule_timeout(current_reqD, "floppy start"); scandrives(); -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG) { - DPRINT("setting NEWCHANGE in floppy_start\n"); - } -#endif - SETF(FD_DISK_NEWCHANGE); + debug_dcl(DP->flags, "setting NEWCHANGE in floppy_start\n"); + set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); floppy_ready(); } @@ -2026,7 +1989,7 @@ static void floppy_start(void) static void do_wakeup(void) { - reschedule_timeout(MAXTIMEOUT, "do wakeup", 0); + reschedule_timeout(MAXTIMEOUT, "do wakeup"); cont = NULL; command_status += 2; wake_up(&command_done); @@ -2046,7 +2009,7 @@ static struct cont_t intr_cont = { .done = (done_f)empty }; -static int wait_til_done(void (*handler)(void), int interruptible) +static int wait_til_done(void (*handler)(void), bool interruptible) { int ret; @@ -2064,7 +2027,7 @@ static int wait_til_done(void (*handler)(void), int interruptible) if (command_status >= 2 || !NO_SIGNAL) break; - is_alive("wait_til_done"); + is_alive(__func__, ""); schedule(); } @@ -2180,9 +2143,9 @@ static void format_interrupt(void) cont->redo(); } -#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2) -#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1)) +#define FM_MODE(x, y) ((y) & ~(((x)->rate & 0x80) >> 1)) #define CT(x) ((x) | 0xc0) + static void setup_format_params(int track) { int n; @@ -2197,8 +2160,8 @@ static void setup_format_params(int track) raw_cmd = &default_raw_cmd; raw_cmd->track = track; - raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | - FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; + raw_cmd->flags = (FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | + FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK); raw_cmd->rate = _floppy->rate & 0x43; raw_cmd->cmd_count = NR_F; COMMAND = FM_MODE(_floppy, FD_FORMAT); @@ -2257,7 +2220,7 @@ static void redo_format(void) buffer_track = -1; setup_format_params(format_req.track << STRETCH(_floppy)); floppy_start(); - debugt("queue format request"); + debugt(__func__, "queue format request"); } static struct cont_t format_cont = { @@ -2271,7 +2234,9 @@ static int do_format(int drive, struct format_descr *tmp_format_req) { int ret; - LOCK_FDC(drive, 1); + if (lock_fdc(drive, true)) + return -EINTR; + set_floppy(drive); if (!_floppy || _floppy->track > DP->tracks || @@ -2286,7 +2251,9 @@ static int do_format(int drive, struct format_descr *tmp_format_req) format_errors = 0; cont = &format_cont; errors = &format_errors; - IWAIT(redo_format); + ret = wait_til_done(redo_format, true); + if (ret == -EINTR) + return -EINTR; process_fd_request(); return ret; } @@ -2320,12 +2287,14 @@ static void request_done(int uptodate) struct request *req = current_req; unsigned long flags; int block; + char msg[sizeof("request done ") + sizeof(int) * 3]; probing = 0; - reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate); + snprintf(msg, sizeof(msg), "request done %d", uptodate); + reschedule_timeout(MAXTIMEOUT, msg); if (!req) { - printk("floppy.c: no request in request_done\n"); + pr_info("floppy.c: no request in request_done\n"); return; } @@ -2377,7 +2346,7 @@ static void rw_interrupt(void) DRS->first_read_date = jiffies; nr_sectors = 0; - CODE2SIZE; + ssize = DIV_ROUND_UP(1 << SIZECODE, 4); if (ST1 & ST1_EOC) eoc = 1; @@ -2393,20 +2362,18 @@ static void rw_interrupt(void) R_HEAD - HEAD) * SECT_PER_TRACK + R_SECTOR - SECTOR + eoc) << SIZECODE >> 2; -#ifdef FLOPPY_SANITY_CHECK if (nr_sectors / ssize > DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) { DPRINT("long rw: %x instead of %lx\n", nr_sectors, current_count_sectors); - printk("rs=%d s=%d\n", R_SECTOR, SECTOR); - printk("rh=%d h=%d\n", R_HEAD, HEAD); - printk("rt=%d t=%d\n", R_TRACK, TRACK); - printk("heads=%d eoc=%d\n", heads, eoc); - printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, - fsector_t, ssize); - printk("in_sector_offset=%d\n", in_sector_offset); + pr_info("rs=%d s=%d\n", R_SECTOR, SECTOR); + pr_info("rh=%d h=%d\n", R_HEAD, HEAD); + pr_info("rt=%d t=%d\n", R_TRACK, TRACK); + pr_info("heads=%d eoc=%d\n", heads, eoc); + pr_info("spt=%d st=%d ss=%d\n", + SECT_PER_TRACK, fsector_t, ssize); + pr_info("in_sector_offset=%d\n", in_sector_offset); } -#endif nr_sectors -= in_sector_offset; INFBOUND(nr_sectors, 0); @@ -2511,19 +2478,17 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) blk_rq_sectors(current_req)); remaining = current_count_sectors << 9; -#ifdef FLOPPY_SANITY_CHECK if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) { DPRINT("in copy buffer\n"); - printk("current_count_sectors=%ld\n", current_count_sectors); - printk("remaining=%d\n", remaining >> 9); - printk("current_req->nr_sectors=%u\n", - blk_rq_sectors(current_req)); - printk("current_req->current_nr_sectors=%u\n", - blk_rq_cur_sectors(current_req)); - printk("max_sector=%d\n", max_sector); - printk("ssize=%d\n", ssize); + pr_info("current_count_sectors=%ld\n", current_count_sectors); + pr_info("remaining=%d\n", remaining >> 9); + pr_info("current_req->nr_sectors=%u\n", + blk_rq_sectors(current_req)); + pr_info("current_req->current_nr_sectors=%u\n", + blk_rq_cur_sectors(current_req)); + pr_info("max_sector=%d\n", max_sector); + pr_info("ssize=%d\n", ssize); } -#endif buffer_max = max(max_sector, buffer_max); @@ -2539,26 +2504,24 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) SUPBOUND(size, remaining); buffer = page_address(bv->bv_page) + bv->bv_offset; -#ifdef FLOPPY_SANITY_CHECK if (dma_buffer + size > floppy_track_buffer + (max_buffer_sectors << 10) || dma_buffer < floppy_track_buffer) { DPRINT("buffer overrun in copy buffer %d\n", - (int)((floppy_track_buffer - - dma_buffer) >> 9)); - printk("fsector_t=%d buffer_min=%d\n", - fsector_t, buffer_min); - printk("current_count_sectors=%ld\n", - current_count_sectors); + (int)((floppy_track_buffer - dma_buffer) >> 9)); + pr_info("fsector_t=%d buffer_min=%d\n", + fsector_t, buffer_min); + pr_info("current_count_sectors=%ld\n", + current_count_sectors); if (CT(COMMAND) == FD_READ) - printk("read\n"); + pr_info("read\n"); if (CT(COMMAND) == FD_WRITE) - printk("write\n"); + pr_info("write\n"); break; } if (((unsigned long)buffer) % 512) DPRINT("%p buffer not aligned\n", buffer); -#endif + if (CT(COMMAND) == FD_READ) memcpy(buffer, dma_buffer, size); else @@ -2567,13 +2530,11 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) remaining -= size; dma_buffer += size; } -#ifdef FLOPPY_SANITY_CHECK if (remaining) { if (remaining > 0) max_sector -= remaining >> 9; DPRINT("weirdness: remaining %d\n", remaining >> 9); } -#endif } /* work around a bug in pseudo DMA @@ -2593,15 +2554,14 @@ static void virtualdmabug_workaround(void) hard_sectors = raw_cmd->length >> (7 + SIZECODE); end_sector = SECTOR + hard_sectors - 1; -#ifdef FLOPPY_SANITY_CHECK if (end_sector > SECT_PER_TRACK) { - printk("too many sectors %d > %d\n", - end_sector, SECT_PER_TRACK); + pr_info("too many sectors %d > %d\n", + end_sector, SECT_PER_TRACK); return; } -#endif - SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points - * to end of transfer */ + SECT_PER_TRACK = end_sector; + /* make sure SECT_PER_TRACK + * points to end of transfer */ } } @@ -2624,7 +2584,7 @@ static int make_raw_rw_request(void) int ssize; if (max_buffer_sectors == 0) { - printk("VFS: Block I/O scheduled on unopened device\n"); + pr_info("VFS: Block I/O scheduled on unopened device\n"); return 0; } @@ -2641,7 +2601,7 @@ static int make_raw_rw_request(void) raw_cmd->flags |= FD_RAW_WRITE; COMMAND = FM_MODE(_floppy, FD_WRITE); } else { - DPRINT("make_raw_rw_request: unknown command\n"); + DPRINT("%s: unknown command\n", __func__); return 0; } @@ -2659,7 +2619,8 @@ static int make_raw_rw_request(void) HEAD = fsector_t / _floppy->sect; if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) || - TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect) + test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) && + fsector_t < _floppy->sect) max_sector = _floppy->sect; /* 2M disks have phantom sectors on the first track */ @@ -2685,7 +2646,7 @@ static int make_raw_rw_request(void) raw_cmd->track = TRACK << STRETCH(_floppy); DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD); GAP = _floppy->gap; - CODE2SIZE; + ssize = DIV_ROUND_UP(1 << SIZECODE, 4); SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + FD_SECTBASE(_floppy); @@ -2730,8 +2691,10 @@ static int make_raw_rw_request(void) } } else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) { if (CT(COMMAND) == FD_WRITE) { - if (fsector_t + blk_rq_sectors(current_req) > ssize && - fsector_t + blk_rq_sectors(current_req) < ssize + ssize) + unsigned int sectors; + + sectors = fsector_t + blk_rq_sectors(current_req); + if (sectors > ssize && sectors < ssize + ssize) max_size = ssize + ssize; else max_size = ssize; @@ -2752,12 +2715,10 @@ static int make_raw_rw_request(void) * on a 64 bit machine! */ max_size = buffer_chain_size(); - dma_limit = - (MAX_DMA_ADDRESS - - ((unsigned long)current_req->buffer)) >> 9; - if ((unsigned long)max_size > dma_limit) { + dma_limit = (MAX_DMA_ADDRESS - + ((unsigned long)current_req->buffer)) >> 9; + if ((unsigned long)max_size > dma_limit) max_size = dma_limit; - } /* 64 kb boundaries */ if (CROSS_64KB(current_req->buffer, max_size << 9)) max_size = (K_64 - @@ -2773,16 +2734,16 @@ static int make_raw_rw_request(void) */ if (!direct || (indirect * 2 > direct * 3 && - *errors < DP->max_errors.read_track && ((!probing - || (DP->read_track & (1 << DRS->probed_format)))))) { + *errors < DP->max_errors.read_track && + ((!probing || + (DP->read_track & (1 << DRS->probed_format)))))) { max_size = blk_rq_sectors(current_req); } else { raw_cmd->kernel_data = current_req->buffer; raw_cmd->length = current_count_sectors << 9; if (raw_cmd->length == 0) { - DPRINT - ("zero dma transfer attempted from make_raw_request\n"); - DPRINT("indirect=%d direct=%d fsector_t=%d", + DPRINT("%s: zero dma transfer attempted\n", __func__); + DPRINT("indirect=%d direct=%d fsector_t=%d\n", indirect, direct, fsector_t); return 0; } @@ -2802,25 +2763,22 @@ static int make_raw_rw_request(void) ((CT(COMMAND) == FD_READ || (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) && max_sector > 2 * max_buffer_sectors + buffer_min && - max_size + fsector_t > 2 * max_buffer_sectors + buffer_min) - /* not enough space */ - ) { + max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)) { + /* not enough space */ buffer_track = -1; buffer_drive = current_drive; buffer_max = buffer_min = aligned_sector_t; } raw_cmd->kernel_data = floppy_track_buffer + - ((aligned_sector_t - buffer_min) << 9); + ((aligned_sector_t - buffer_min) << 9); if (CT(COMMAND) == FD_WRITE) { /* copy write buffer to track buffer. * if we get here, we know that the write * is either aligned or the data already in the buffer * (buffer will be overwritten) */ -#ifdef FLOPPY_SANITY_CHECK if (in_sector_offset && buffer_track == -1) DPRINT("internal error offset !=0 on write\n"); -#endif buffer_track = raw_cmd->track; buffer_drive = current_drive; copy_buffer(ssize, max_sector, @@ -2834,7 +2792,6 @@ static int make_raw_rw_request(void) raw_cmd->length = in_sector_offset + current_count_sectors; raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1; raw_cmd->length <<= 9; -#ifdef FLOPPY_SANITY_CHECK if ((raw_cmd->length < current_count_sectors << 9) || (raw_cmd->kernel_data != current_req->buffer && CT(COMMAND) == FD_WRITE && @@ -2845,19 +2802,19 @@ static int make_raw_rw_request(void) DPRINT("fractionary current count b=%lx s=%lx\n", raw_cmd->length, current_count_sectors); if (raw_cmd->kernel_data != current_req->buffer) - printk("addr=%d, length=%ld\n", - (int)((raw_cmd->kernel_data - - floppy_track_buffer) >> 9), - current_count_sectors); - printk("st=%d ast=%d mse=%d msi=%d\n", - fsector_t, aligned_sector_t, max_sector, max_size); - printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE); - printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n", - COMMAND, SECTOR, HEAD, TRACK); - printk("buffer drive=%d\n", buffer_drive); - printk("buffer track=%d\n", buffer_track); - printk("buffer_min=%d\n", buffer_min); - printk("buffer_max=%d\n", buffer_max); + pr_info("addr=%d, length=%ld\n", + (int)((raw_cmd->kernel_data - + floppy_track_buffer) >> 9), + current_count_sectors); + pr_info("st=%d ast=%d mse=%d msi=%d\n", + fsector_t, aligned_sector_t, max_sector, max_size); + pr_info("ssize=%x SIZECODE=%d\n", ssize, SIZECODE); + pr_info("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n", + COMMAND, SECTOR, HEAD, TRACK); + pr_info("buffer drive=%d\n", buffer_drive); + pr_info("buffer track=%d\n", buffer_track); + pr_info("buffer_min=%d\n", buffer_min); + pr_info("buffer_max=%d\n", buffer_max); return 0; } @@ -2868,14 +2825,14 @@ static int make_raw_rw_request(void) raw_cmd->kernel_data + raw_cmd->length > floppy_track_buffer + (max_buffer_sectors << 10)) { DPRINT("buffer overrun in schedule dma\n"); - printk("fsector_t=%d buffer_min=%d current_count=%ld\n", - fsector_t, buffer_min, raw_cmd->length >> 9); - printk("current_count_sectors=%ld\n", - current_count_sectors); + pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n", + fsector_t, buffer_min, raw_cmd->length >> 9); + pr_info("current_count_sectors=%ld\n", + current_count_sectors); if (CT(COMMAND) == FD_READ) - printk("read\n"); + pr_info("read\n"); if (CT(COMMAND) == FD_WRITE) - printk("write\n"); + pr_info("write\n"); return 0; } } else if (raw_cmd->length > blk_rq_bytes(current_req) || @@ -2884,14 +2841,13 @@ static int make_raw_rw_request(void) return 0; } else if (raw_cmd->length < current_count_sectors << 9) { DPRINT("more sectors than bytes\n"); - printk("bytes=%ld\n", raw_cmd->length >> 9); - printk("sectors=%ld\n", current_count_sectors); + pr_info("bytes=%ld\n", raw_cmd->length >> 9); + pr_info("sectors=%ld\n", current_count_sectors); } if (raw_cmd->length == 0) { DPRINT("zero dma transfer attempted from make_raw_request\n"); return 0; } -#endif virtualdmabug_workaround(); return 2; @@ -2899,7 +2855,6 @@ static int make_raw_rw_request(void) static void redo_fd_request(void) { -#define REPEAT {request_done(0); continue; } int drive; int tmp; @@ -2907,63 +2862,63 @@ static void redo_fd_request(void) if (current_drive < N_DRIVE) floppy_off(current_drive); - for (;;) { - if (!current_req) { - struct request *req; - - spin_lock_irq(floppy_queue->queue_lock); - req = blk_fetch_request(floppy_queue); - spin_unlock_irq(floppy_queue->queue_lock); - if (!req) { - do_floppy = NULL; - unlock_fdc(); - return; - } - current_req = req; - } - drive = (long)current_req->rq_disk->private_data; - set_fdc(drive); - reschedule_timeout(current_reqD, "redo fd request", 0); +do_request: + if (!current_req) { + struct request *req; - set_floppy(drive); - raw_cmd = &default_raw_cmd; - raw_cmd->flags = 0; - if (start_motor(redo_fd_request)) + spin_lock_irq(floppy_queue->queue_lock); + req = blk_fetch_request(floppy_queue); + spin_unlock_irq(floppy_queue->queue_lock); + if (!req) { + do_floppy = NULL; + unlock_fdc(); return; - disk_change(current_drive); - if (test_bit(current_drive, &fake_change) || - TESTF(FD_DISK_CHANGED)) { - DPRINT("disk absent or changed during operation\n"); - REPEAT; - } - if (!_floppy) { /* Autodetection */ - if (!probing) { - DRS->probed_format = 0; - if (next_valid_format()) { - DPRINT("no autodetectable formats\n"); - _floppy = NULL; - REPEAT; - } - } - probing = 1; - _floppy = - floppy_type + DP->autodetect[DRS->probed_format]; - } else - probing = 0; - errors = &(current_req->errors); - tmp = make_raw_rw_request(); - if (tmp < 2) { - request_done(tmp); - continue; } + current_req = req; + } + drive = (long)current_req->rq_disk->private_data; + set_fdc(drive); + reschedule_timeout(current_reqD, "redo fd request"); - if (TESTF(FD_NEED_TWADDLE)) - twaddle(); - schedule_bh(floppy_start); - debugt("queue fd request"); + set_floppy(drive); + raw_cmd = &default_raw_cmd; + raw_cmd->flags = 0; + if (start_motor(redo_fd_request)) return; + + disk_change(current_drive); + if (test_bit(current_drive, &fake_change) || + test_bit(FD_DISK_CHANGED_BIT, &DRS->flags)) { + DPRINT("disk absent or changed during operation\n"); + request_done(0); + goto do_request; + } + if (!_floppy) { /* Autodetection */ + if (!probing) { + DRS->probed_format = 0; + if (next_valid_format()) { + DPRINT("no autodetectable formats\n"); + _floppy = NULL; + request_done(0); + goto do_request; + } + } + probing = 1; + _floppy = floppy_type + DP->autodetect[DRS->probed_format]; + } else + probing = 0; + errors = &(current_req->errors); + tmp = make_raw_rw_request(); + if (tmp < 2) { + request_done(tmp); + goto do_request; } -#undef REPEAT + + if (test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) + twaddle(); + schedule_bh(floppy_start); + debugt(__func__, "queue fd request"); + return; } static struct cont_t rw_cont = { @@ -2979,30 +2934,30 @@ static void process_fd_request(void) schedule_bh(redo_fd_request); } -static void do_fd_request(struct request_queue * q) +static void do_fd_request(struct request_queue *q) { if (max_buffer_sectors == 0) { - printk("VFS: do_fd_request called on non-open device\n"); + pr_info("VFS: %s called on non-open device\n", __func__); return; } if (usage_count == 0) { - printk("warning: usage count=0, current_req=%p exiting\n", - current_req); - printk("sect=%ld type=%x flags=%x\n", - (long)blk_rq_pos(current_req), current_req->cmd_type, - current_req->cmd_flags); + pr_info("warning: usage count=0, current_req=%p exiting\n", + current_req); + pr_info("sect=%ld type=%x flags=%x\n", + (long)blk_rq_pos(current_req), current_req->cmd_type, + current_req->cmd_flags); return; } if (test_bit(0, &fdc_busy)) { /* fdc busy, this new request will be treated when the current one is done */ - is_alive("do fd request, old request running"); + is_alive(__func__, "old request running"); return; } - lock_fdc(MAXTIMEOUT, 0); + lock_fdc(MAXTIMEOUT, false); process_fd_request(); - is_alive("do fd request"); + is_alive(__func__, ""); } static struct cont_t poll_cont = { @@ -3012,24 +2967,18 @@ static struct cont_t poll_cont = { .done = generic_done }; -static int poll_drive(int interruptible, int flag) +static int poll_drive(bool interruptible, int flag) { - int ret; - /* no auto-sense, just clear dcl */ raw_cmd = &default_raw_cmd; raw_cmd->flags = flag; raw_cmd->track = 0; raw_cmd->cmd_count = 0; cont = &poll_cont; -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG) { - DPRINT("setting NEWCHANGE in poll_drive\n"); - } -#endif - SETF(FD_DISK_NEWCHANGE); - WAIT(floppy_ready); - return ret; + debug_dcl(DP->flags, "setting NEWCHANGE in poll_drive\n"); + set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); + + return wait_til_done(floppy_ready, interruptible); } /* @@ -3039,7 +2988,7 @@ static int poll_drive(int interruptible, int flag) static void reset_intr(void) { - printk("weird, reset interrupt called\n"); + pr_info("weird, reset interrupt called\n"); } static struct cont_t reset_cont = { @@ -3049,20 +2998,23 @@ static struct cont_t reset_cont = { .done = generic_done }; -static int user_reset_fdc(int drive, int arg, int interruptible) +static int user_reset_fdc(int drive, int arg, bool interruptible) { int ret; - ret = 0; - LOCK_FDC(drive, interruptible); + if (lock_fdc(drive, interruptible)) + return -EINTR; + if (arg == FD_RESET_ALWAYS) FDCS->reset = 1; if (FDCS->reset) { cont = &reset_cont; - WAIT(reset_fdc); + ret = wait_til_done(reset_fdc, interruptible); + if (ret == -EINTR) + return -EINTR; } process_fd_request(); - return ret; + return 0; } /* @@ -3075,17 +3027,12 @@ static inline int fd_copyout(void __user *param, const void *address, return copy_to_user(param, address, size) ? -EFAULT : 0; } -static inline int fd_copyin(void __user *param, void *address, unsigned long size) +static inline int fd_copyin(void __user *param, void *address, + unsigned long size) { return copy_from_user(address, param, size) ? -EFAULT : 0; } -#define _COPYOUT(x) (copy_to_user((void __user *)param, &(x), sizeof(x)) ? -EFAULT : 0) -#define _COPYIN(x) (copy_from_user(&(x), (void __user *)param, sizeof(x)) ? -EFAULT : 0) - -#define COPYOUT(x) ECALL(_COPYOUT(x)) -#define COPYIN(x) ECALL(_COPYIN(x)) - static inline const char *drive_name(int type, int drive) { struct floppy_struct *floppy; @@ -3156,23 +3103,29 @@ static struct cont_t raw_cmd_cont = { .done = raw_cmd_done }; -static inline int raw_cmd_copyout(int cmd, char __user *param, +static inline int raw_cmd_copyout(int cmd, void __user *param, struct floppy_raw_cmd *ptr) { int ret; while (ptr) { - COPYOUT(*ptr); + ret = copy_to_user(param, ptr, sizeof(*ptr)); + if (ret) + return -EFAULT; param += sizeof(struct floppy_raw_cmd); if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) { - if (ptr->length >= 0 - && ptr->length <= ptr->buffer_length) - ECALL(fd_copyout - (ptr->data, ptr->kernel_data, - ptr->buffer_length - ptr->length)); + if (ptr->length >= 0 && + ptr->length <= ptr->buffer_length) { + long length = ptr->buffer_length - ptr->length; + ret = fd_copyout(ptr->data, ptr->kernel_data, + length); + if (ret) + return ret; + } } ptr = ptr->next; } + return 0; } @@ -3195,7 +3148,7 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr) } } -static inline int raw_cmd_copyin(int cmd, char __user *param, +static inline int raw_cmd_copyin(int cmd, void __user *param, struct floppy_raw_cmd **rcmd) { struct floppy_raw_cmd *ptr; @@ -3203,17 +3156,19 @@ static inline int raw_cmd_copyin(int cmd, char __user *param, int i; *rcmd = NULL; - while (1) { - ptr = (struct floppy_raw_cmd *) - kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER); - if (!ptr) - return -ENOMEM; - *rcmd = ptr; - COPYIN(*ptr); - ptr->next = NULL; - ptr->buffer_length = 0; - param += sizeof(struct floppy_raw_cmd); - if (ptr->cmd_count > 33) + +loop: + ptr = kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER); + if (!ptr) + return -ENOMEM; + *rcmd = ptr; + ret = copy_from_user(ptr, param, sizeof(*ptr)); + if (ret) + return -EFAULT; + ptr->next = NULL; + ptr->buffer_length = 0; + param += sizeof(struct floppy_raw_cmd); + if (ptr->cmd_count > 33) /* the command may now also take up the space * initially intended for the reply & the * reply count. Needed for long 82078 commands @@ -3222,31 +3177,35 @@ static inline int raw_cmd_copyin(int cmd, char __user *param, * 16 bytes for a structure, you'll one day * discover that you really need 17... */ + return -EINVAL; + + for (i = 0; i < 16; i++) + ptr->reply[i] = 0; + ptr->resultcode = 0; + ptr->kernel_data = NULL; + + if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { + if (ptr->length <= 0) return -EINVAL; + ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length); + fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length); + if (!ptr->kernel_data) + return -ENOMEM; + ptr->buffer_length = ptr->length; + } + if (ptr->flags & FD_RAW_WRITE) { + ret = fd_copyin(ptr->data, ptr->kernel_data, ptr->length); + if (ret) + return ret; + } - for (i = 0; i < 16; i++) - ptr->reply[i] = 0; - ptr->resultcode = 0; - ptr->kernel_data = NULL; - - if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { - if (ptr->length <= 0) - return -EINVAL; - ptr->kernel_data = - (char *)fd_dma_mem_alloc(ptr->length); - fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length); - if (!ptr->kernel_data) - return -ENOMEM; - ptr->buffer_length = ptr->length; - } - if (ptr->flags & FD_RAW_WRITE) - ECALL(fd_copyin(ptr->data, ptr->kernel_data, - ptr->length)); + if (ptr->flags & FD_RAW_MORE) { rcmd = &(ptr->next); - if (!(ptr->flags & FD_RAW_MORE)) - return 0; ptr->rate &= 0x43; + goto loop; } + + return 0; } static int raw_cmd_ioctl(int cmd, void __user *param) @@ -3283,12 +3242,8 @@ static int raw_cmd_ioctl(int cmd, void __user *param) raw_cmd = my_raw_cmd; cont = &raw_cmd_cont; - ret = wait_til_done(floppy_start, 1); -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG) { - DPRINT("calling disk change from raw_cmd ioctl\n"); - } -#endif + ret = wait_til_done(floppy_start, true); + debug_dcl(DP->flags, "calling disk change from raw_cmd ioctl\n"); if (ret != -EINTR && FDCS->reset) ret = -EIO; @@ -3327,7 +3282,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, if (!capable(CAP_SYS_ADMIN)) return -EPERM; mutex_lock(&open_lock); - if (lock_fdc(drive, 1)) { + if (lock_fdc(drive, true)) { mutex_unlock(&open_lock); return -EINTR; } @@ -3346,11 +3301,15 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, mutex_unlock(&open_lock); } else { int oldStretch; - LOCK_FDC(drive, 1); - if (cmd != FDDEFPRM) + + if (lock_fdc(drive, true)) + return -EINTR; + if (cmd != FDDEFPRM) { /* notice a disk change immediately, else * we lose our settings immediately*/ - CALL(poll_drive(1, FD_RAW_NEED_DISK)); + if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) + return -EINTR; + } oldStretch = g->stretch; user_params[drive] = *g; if (buffer_drive == drive) @@ -3415,7 +3374,7 @@ static inline int normalize_ioctl(int *cmd, int *size) *size = _IOC_SIZE(*cmd); *cmd = ioctl_table[i]; if (*size > _IOC_SIZE(*cmd)) { - printk("ioctl not yet supported\n"); + pr_info("ioctl not yet supported\n"); return -EFAULT; } return 0; @@ -3429,8 +3388,10 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) if (type) *g = &floppy_type[type]; else { - LOCK_FDC(drive, 0); - CALL(poll_drive(0, 0)); + if (lock_fdc(drive, false)) + return -EINTR; + if (poll_drive(false, 0) == -EINTR) + return -EINTR; process_fd_request(); *g = current_type[drive]; } @@ -3459,10 +3420,6 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { -#define FD_IOCTL_ALLOWED (mode & (FMODE_WRITE|FMODE_WRITE_IOCTL)) -#define OUT(c,x) case c: outparam = (const char *) (x); break -#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0 - int drive = (long)bdev->bd_disk->private_data; int type = ITYPE(UDRS->fd_device); int i; @@ -3474,26 +3431,28 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, struct floppy_max_errors max_errors; struct floppy_drive_params dp; } inparam; /* parameters coming from user space */ - const char *outparam; /* parameters passed back to user space */ + const void *outparam; /* parameters passed back to user space */ /* convert compatibility eject ioctls into floppy eject ioctl. * We do this in order to provide a means to eject floppy disks before * installing the new fdutils package */ if (cmd == CDROMEJECT || /* CD-ROM eject */ - cmd == 0x6470 /* SunOS floppy eject */ ) { + cmd == 0x6470) { /* SunOS floppy eject */ DPRINT("obsolete eject ioctl\n"); DPRINT("please use floppycontrol --eject\n"); cmd = FDEJECT; } - /* convert the old style command into a new style command */ - if ((cmd & 0xff00) == 0x0200) { - ECALL(normalize_ioctl(&cmd, &size)); - } else + if (!((cmd & 0xff00) == 0x0200)) return -EINVAL; + /* convert the old style command into a new style command */ + ret = normalize_ioctl(&cmd, &size); + if (ret) + return ret; + /* permission checks */ - if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) || + if (((cmd & 0x40) && !(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) || ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) return -EPERM; @@ -3501,129 +3460,142 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, return -EINVAL; /* copyin */ - CLEARSTRUCT(&inparam); - if (_IOC_DIR(cmd) & _IOC_WRITE) - ECALL(fd_copyin((void __user *)param, &inparam, size)) - - switch (cmd) { - case FDEJECT: - if (UDRS->fd_ref != 1) - /* somebody else has this drive open */ - return -EBUSY; - LOCK_FDC(drive, 1); - - /* do the actual eject. Fails on - * non-Sparc architectures */ - ret = fd_eject(UNIT(drive)); - - USETF(FD_DISK_CHANGED); - USETF(FD_VERIFY); - process_fd_request(); + memset(&inparam, 0, sizeof(inparam)); + if (_IOC_DIR(cmd) & _IOC_WRITE) { + ret = fd_copyin((void __user *)param, &inparam, size); + if (ret) return ret; - case FDCLRPRM: - LOCK_FDC(drive, 1); - current_type[drive] = NULL; - floppy_sizes[drive] = MAX_DISK_SIZE << 1; - UDRS->keep_data = 0; - return invalidate_drive(bdev); - case FDSETPRM: - case FDDEFPRM: - return set_geometry(cmd, &inparam.g, - drive, type, bdev); - case FDGETPRM: - ECALL(get_floppy_geometry(drive, type, - (struct floppy_struct **) - &outparam)); - break; - - case FDMSGON: - UDP->flags |= FTD_MSG; - return 0; - case FDMSGOFF: - UDP->flags &= ~FTD_MSG; - return 0; - - case FDFMTBEG: - LOCK_FDC(drive, 1); - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - ret = UDRS->flags; - process_fd_request(); - if (ret & FD_VERIFY) - return -ENODEV; - if (!(ret & FD_DISK_WRITABLE)) - return -EROFS; - return 0; - case FDFMTTRK: - if (UDRS->fd_ref != 1) - return -EBUSY; - return do_format(drive, &inparam.f); - case FDFMTEND: - case FDFLUSH: - LOCK_FDC(drive, 1); - return invalidate_drive(bdev); - - case FDSETEMSGTRESH: - UDP->max_errors.reporting = - (unsigned short)(param & 0x0f); - return 0; - OUT(FDGETMAXERRS, &UDP->max_errors); - IN(FDSETMAXERRS, &UDP->max_errors, max_errors); - - case FDGETDRVTYP: - outparam = drive_name(type, drive); - SUPBOUND(size, strlen(outparam) + 1); - break; - - IN(FDSETDRVPRM, UDP, dp); - OUT(FDGETDRVPRM, UDP); - - case FDPOLLDRVSTAT: - LOCK_FDC(drive, 1); - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - process_fd_request(); - /* fall through */ - OUT(FDGETDRVSTAT, UDRS); - - case FDRESET: - return user_reset_fdc(drive, (int)param, 1); - - OUT(FDGETFDCSTAT, UFDCS); + } - case FDWERRORCLR: - CLEARSTRUCT(UDRWE); - return 0; - OUT(FDWERRORGET, UDRWE); - - case FDRAWCMD: - if (type) - return -EINVAL; - LOCK_FDC(drive, 1); - set_floppy(drive); - CALL(i = raw_cmd_ioctl(cmd, (void __user *)param)); - process_fd_request(); - return i; + switch (cmd) { + case FDEJECT: + if (UDRS->fd_ref != 1) + /* somebody else has this drive open */ + return -EBUSY; + if (lock_fdc(drive, true)) + return -EINTR; - case FDTWADDLE: - LOCK_FDC(drive, 1); - twaddle(); - process_fd_request(); - return 0; + /* do the actual eject. Fails on + * non-Sparc architectures */ + ret = fd_eject(UNIT(drive)); - default: + set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); + set_bit(FD_VERIFY_BIT, &UDRS->flags); + process_fd_request(); + return ret; + case FDCLRPRM: + if (lock_fdc(drive, true)) + return -EINTR; + current_type[drive] = NULL; + floppy_sizes[drive] = MAX_DISK_SIZE << 1; + UDRS->keep_data = 0; + return invalidate_drive(bdev); + case FDSETPRM: + case FDDEFPRM: + return set_geometry(cmd, &inparam.g, drive, type, bdev); + case FDGETPRM: + ret = get_floppy_geometry(drive, type, + (struct floppy_struct **)&outparam); + if (ret) + return ret; + break; + case FDMSGON: + UDP->flags |= FTD_MSG; + return 0; + case FDMSGOFF: + UDP->flags &= ~FTD_MSG; + return 0; + case FDFMTBEG: + if (lock_fdc(drive, true)) + return -EINTR; + if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) + return -EINTR; + ret = UDRS->flags; + process_fd_request(); + if (ret & FD_VERIFY) + return -ENODEV; + if (!(ret & FD_DISK_WRITABLE)) + return -EROFS; + return 0; + case FDFMTTRK: + if (UDRS->fd_ref != 1) + return -EBUSY; + return do_format(drive, &inparam.f); + case FDFMTEND: + case FDFLUSH: + if (lock_fdc(drive, true)) + return -EINTR; + return invalidate_drive(bdev); + case FDSETEMSGTRESH: + UDP->max_errors.reporting = (unsigned short)(param & 0x0f); + return 0; + case FDGETMAXERRS: + outparam = &UDP->max_errors; + break; + case FDSETMAXERRS: + UDP->max_errors = inparam.max_errors; + break; + case FDGETDRVTYP: + outparam = drive_name(type, drive); + SUPBOUND(size, strlen((const char *)outparam) + 1); + break; + case FDSETDRVPRM: + *UDP = inparam.dp; + break; + case FDGETDRVPRM: + outparam = UDP; + break; + case FDPOLLDRVSTAT: + if (lock_fdc(drive, true)) + return -EINTR; + if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) + return -EINTR; + process_fd_request(); + /* fall through */ + case FDGETDRVSTAT: + outparam = UDRS; + break; + case FDRESET: + return user_reset_fdc(drive, (int)param, true); + case FDGETFDCSTAT: + outparam = UFDCS; + break; + case FDWERRORCLR: + memset(UDRWE, 0, sizeof(*UDRWE)); + return 0; + case FDWERRORGET: + outparam = UDRWE; + break; + case FDRAWCMD: + if (type) return -EINVAL; - } + if (lock_fdc(drive, true)) + return -EINTR; + set_floppy(drive); + i = raw_cmd_ioctl(cmd, (void __user *)param); + if (i == -EINTR) + return -EINTR; + process_fd_request(); + return i; + case FDTWADDLE: + if (lock_fdc(drive, true)) + return -EINTR; + twaddle(); + process_fd_request(); + return 0; + default: + return -EINVAL; + } if (_IOC_DIR(cmd) & _IOC_READ) return fd_copyout((void __user *)param, outparam, size); - else - return 0; -#undef OUT -#undef IN + + return 0; } static void __init config_types(void) { - int first = 1; + bool has_drive = false; int drive; /* read drive info out of physical CMOS */ @@ -3655,17 +3627,22 @@ static void __init config_types(void) name = temparea; } if (name) { - const char *prepend = ","; - if (first) { - prepend = KERN_INFO "Floppy drive(s):"; - first = 0; + const char *prepend; + if (!has_drive) { + prepend = ""; + has_drive = true; + pr_info("Floppy drive(s):"); + } else { + prepend = ","; } - printk("%s fd%d is %s", prepend, drive, name); + + pr_cont("%s fd%d is %s", prepend, drive, name); } *UDP = *params; } - if (!first) - printk("\n"); + + if (has_drive) + pr_cont("\n"); } static int floppy_release(struct gendisk *disk, fmode_t mode) @@ -3705,8 +3682,8 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) goto out2; if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) { - USETF(FD_DISK_CHANGED); - USETF(FD_VERIFY); + set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); + set_bit(FD_VERIFY_BIT, &UDRS->flags); } if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (mode & FMODE_EXCL))) @@ -3735,9 +3712,8 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) INFBOUND(try, 16); tmp = (char *)fd_dma_mem_alloc(1024 * try); } - if (!tmp && !floppy_track_buffer) { + if (!tmp && !floppy_track_buffer) fallback_on_nodma_alloc(&tmp, 2048 * try); - } if (!tmp && !floppy_track_buffer) { DPRINT("Unable to allocate DMA memory\n"); goto out; @@ -3767,11 +3743,12 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) if (mode & (FMODE_READ|FMODE_WRITE)) { UDRS->last_checked = 0; check_disk_change(bdev); - if (UTESTF(FD_DISK_CHANGED)) + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) goto out; } res = -EROFS; - if ((mode & FMODE_WRITE) && !(UTESTF(FD_DISK_WRITABLE))) + if ((mode & FMODE_WRITE) && + !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) goto out; } mutex_unlock(&open_lock); @@ -3795,17 +3772,18 @@ static int check_floppy_change(struct gendisk *disk) { int drive = (long)disk->private_data; - if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || + test_bit(FD_VERIFY_BIT, &UDRS->flags)) return 1; if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { - lock_fdc(drive, 0); - poll_drive(0, 0); + lock_fdc(drive, false); + poll_drive(false, 0); process_fd_request(); } - if (UTESTF(FD_DISK_CHANGED) || - UTESTF(FD_VERIFY) || + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || + test_bit(FD_VERIFY_BIT, &UDRS->flags) || test_bit(drive, &fake_change) || (!ITYPE(UDRS->fd_device) && !current_type[drive])) return 1; @@ -3818,8 +3796,7 @@ static int check_floppy_change(struct gendisk *disk) * a disk in the drive, and whether that disk is writable. */ -static void floppy_rb0_complete(struct bio *bio, - int err) +static void floppy_rb0_complete(struct bio *bio, int err) { complete((struct completion *)bio->bi_private); } @@ -3877,14 +3854,16 @@ static int floppy_revalidate(struct gendisk *disk) int cf; int res = 0; - if (UTESTF(FD_DISK_CHANGED) || - UTESTF(FD_VERIFY) || test_bit(drive, &fake_change) || NO_GEOM) { + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || + test_bit(FD_VERIFY_BIT, &UDRS->flags) || + test_bit(drive, &fake_change) || NO_GEOM) { if (usage_count == 0) { - printk("VFS: revalidate called on non-open device.\n"); + pr_info("VFS: revalidate called on non-open device.\n"); return -EFAULT; } - lock_fdc(drive, 0); - cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY); + lock_fdc(drive, false); + cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || + test_bit(FD_VERIFY_BIT, &UDRS->flags)); if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) { process_fd_request(); /*already done by another thread */ return 0; @@ -3894,7 +3873,7 @@ static int floppy_revalidate(struct gendisk *disk) if (buffer_drive == drive) buffer_track = -1; clear_bit(drive, &fake_change); - UCLEARF(FD_DISK_CHANGED); + clear_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); if (cf) UDRS->generation++; if (NO_GEOM) { @@ -3902,7 +3881,7 @@ static int floppy_revalidate(struct gendisk *disk) res = __floppy_read_block_0(opened_bdev[drive]); } else { if (cf) - poll_drive(0, FD_RAW_NEED_DISK); + poll_drive(false, FD_RAW_NEED_DISK); process_fd_request(); } } @@ -3934,21 +3913,21 @@ static char __init get_fdc_version(void) output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */ if (FDCS->reset) return FDC_NONE; - if ((r = result()) <= 0x00) + r = result(); + if (r <= 0x00) return FDC_NONE; /* No FDC present ??? */ if ((r == 1) && (reply_buffer[0] == 0x80)) { - printk(KERN_INFO "FDC %d is an 8272A\n", fdc); + pr_info("FDC %d is an 8272A\n", fdc); return FDC_8272A; /* 8272a/765 don't know DUMPREGS */ } if (r != 10) { - printk - ("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n", - fdc, r); + pr_info("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n", + fdc, r); return FDC_UNKNOWN; } if (!fdc_configure()) { - printk(KERN_INFO "FDC %d is an 82072\n", fdc); + pr_info("FDC %d is an 82072\n", fdc); return FDC_82072; /* 82072 doesn't know CONFIGURE */ } @@ -3956,52 +3935,50 @@ static char __init get_fdc_version(void) if (need_more_output() == MORE_OUTPUT) { output_byte(0); } else { - printk(KERN_INFO "FDC %d is an 82072A\n", fdc); + pr_info("FDC %d is an 82072A\n", fdc); return FDC_82072A; /* 82072A as found on Sparcs. */ } output_byte(FD_UNLOCK); r = result(); if ((r == 1) && (reply_buffer[0] == 0x80)) { - printk(KERN_INFO "FDC %d is a pre-1991 82077\n", fdc); - return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know + pr_info("FDC %d is a pre-1991 82077\n", fdc); + return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know * LOCK/UNLOCK */ } if ((r != 1) || (reply_buffer[0] != 0x00)) { - printk("FDC %d init: UNLOCK: unexpected return of %d bytes.\n", - fdc, r); + pr_info("FDC %d init: UNLOCK: unexpected return of %d bytes.\n", + fdc, r); return FDC_UNKNOWN; } output_byte(FD_PARTID); r = result(); if (r != 1) { - printk("FDC %d init: PARTID: unexpected return of %d bytes.\n", - fdc, r); + pr_info("FDC %d init: PARTID: unexpected return of %d bytes.\n", + fdc, r); return FDC_UNKNOWN; } if (reply_buffer[0] == 0x80) { - printk(KERN_INFO "FDC %d is a post-1991 82077\n", fdc); + pr_info("FDC %d is a post-1991 82077\n", fdc); return FDC_82077; /* Revised 82077AA passes all the tests */ } switch (reply_buffer[0] >> 5) { case 0x0: /* Either a 82078-1 or a 82078SL running at 5Volt */ - printk(KERN_INFO "FDC %d is an 82078.\n", fdc); + pr_info("FDC %d is an 82078.\n", fdc); return FDC_82078; case 0x1: - printk(KERN_INFO "FDC %d is a 44pin 82078\n", fdc); + pr_info("FDC %d is a 44pin 82078\n", fdc); return FDC_82078; case 0x2: - printk(KERN_INFO "FDC %d is a S82078B\n", fdc); + pr_info("FDC %d is a S82078B\n", fdc); return FDC_S82078B; case 0x3: - printk(KERN_INFO "FDC %d is a National Semiconductor PC87306\n", - fdc); + pr_info("FDC %d is a National Semiconductor PC87306\n", fdc); return FDC_87306; default: - printk(KERN_INFO - "FDC %d init: 82078 variant with unknown PARTID=%d.\n", - fdc, reply_buffer[0] >> 5); + pr_info("FDC %d init: 82078 variant with unknown PARTID=%d.\n", + fdc, reply_buffer[0] >> 5); return FDC_82078_UNKN; } } /* get_fdc_version */ @@ -4113,9 +4090,9 @@ static int __init floppy_setup(char *str) else param = config_params[i].def_param; if (config_params[i].fn) - config_params[i]. - fn(ints, param, - config_params[i].param2); + config_params[i].fn(ints, param, + config_params[i]. + param2); if (config_params[i].var) { DPRINT("%s=%d\n", str, param); *config_params[i].var = param; @@ -4129,8 +4106,8 @@ static int __init floppy_setup(char *str) DPRINT("allowed options are:"); for (i = 0; i < ARRAY_SIZE(config_params); i++) - printk(" %s", config_params[i].name); - printk("\n"); + pr_cont(" %s", config_params[i].name); + pr_cont("\n"); } else DPRINT("botched floppy option\n"); DPRINT("Read Documentation/blockdev/floppy.txt\n"); @@ -4148,7 +4125,8 @@ static ssize_t floppy_cmos_show(struct device *dev, drive = p->id; return sprintf(buf, "%X\n", UDP->cmos); } -DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL); + +DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL); static void floppy_device_release(struct device *dev) { @@ -4160,7 +4138,7 @@ static int floppy_resume(struct device *dev) for (fdc = 0; fdc < N_FDC; fdc++) if (FDCS->address != -1) - user_reset_fdc(-1, FD_RESET_ALWAYS, 0); + user_reset_fdc(-1, FD_RESET_ALWAYS, false); return 0; } @@ -4172,8 +4150,8 @@ static const struct dev_pm_ops floppy_pm_ops = { static struct platform_driver floppy_driver = { .driver = { - .name = "floppy", - .pm = &floppy_pm_ops, + .name = "floppy", + .pm = &floppy_pm_ops, }, }; @@ -4245,16 +4223,16 @@ static int __init floppy_init(void) else floppy_sizes[i] = MAX_DISK_SIZE << 1; - reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT); + reschedule_timeout(MAXTIMEOUT, "floppy init"); config_types(); for (i = 0; i < N_FDC; i++) { fdc = i; - CLEARSTRUCT(FDCS); + memset(FDCS, 0, sizeof(*FDCS)); FDCS->dtr = -1; FDCS->dor = 0x4; #if defined(__sparc__) || defined(__mc68000__) - /*sparcs/sun3x don't have a DOR reset which we can fall back on to */ + /*sparcs/sun3x don't have a DOR reset which we can fall back on to */ #ifdef __mc68000__ if (MACH_IS_SUN3X) #endif @@ -4283,11 +4261,11 @@ static int __init floppy_init(void) /* initialise drive state */ for (drive = 0; drive < N_DRIVE; drive++) { - CLEARSTRUCT(UDRS); - CLEARSTRUCT(UDRWE); - USETF(FD_DISK_NEWCHANGE); - USETF(FD_DISK_CHANGED); - USETF(FD_VERIFY); + memset(UDRS, 0, sizeof(*UDRS)); + memset(UDRWE, 0, sizeof(*UDRWE)); + set_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags); + set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); + set_bit(FD_VERIFY_BIT, &UDRS->flags); UDRS->fd_device = -1; floppy_track_buffer = NULL; max_buffer_sectors = 0; @@ -4307,7 +4285,7 @@ static int __init floppy_init(void) if (FDCS->address == -1) continue; FDCS->rawcmd = 2; - if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) { + if (user_reset_fdc(-1, FD_RESET_ALWAYS, false)) { /* free ioports reserved by floppy_grab_irq_and_dma() */ floppy_release_regions(fdc); FDCS->address = -1; @@ -4330,12 +4308,12 @@ static int __init floppy_init(void) * properly, so force a reset for the standard FDC clones, * to avoid interrupt garbage. */ - user_reset_fdc(-1, FD_RESET_ALWAYS, 0); + user_reset_fdc(-1, FD_RESET_ALWAYS, false); } fdc = 0; del_timer(&fd_timeout); current_drive = 0; - initialising = 0; + initialized = true; if (have_no_fdc) { DPRINT("no floppy controllers found\n"); err = have_no_fdc; @@ -4356,7 +4334,8 @@ static int __init floppy_init(void) if (err) goto out_flush_work; - err = device_create_file(&floppy_device[drive].dev,&dev_attr_cmos); + err = device_create_file(&floppy_device[drive].dev, + &dev_attr_cmos); if (err) goto out_unreg_platform_dev; @@ -4420,8 +4399,10 @@ static int floppy_request_regions(int fdc) const struct io_region *p; for (p = io_regions; p < ARRAY_END(io_regions); p++) { - if (!request_region(FDCS->address + p->offset, p->size, "floppy")) { - DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address + p->offset); + if (!request_region(FDCS->address + p->offset, + p->size, "floppy")) { + DPRINT("Floppy io-port 0x%04lx in use\n", + FDCS->address + p->offset); floppy_release_allocated_regions(fdc, p); return -EBUSY; } @@ -4512,11 +4493,9 @@ cleanup: static void floppy_release_irq_and_dma(void) { int old_fdc; -#ifdef FLOPPY_SANITY_CHECK #ifndef __sparc__ int drive; #endif -#endif long tmpsize; unsigned long tmpaddr; unsigned long flags; @@ -4547,20 +4526,18 @@ static void floppy_release_irq_and_dma(void) buffer_min = buffer_max = -1; fd_dma_mem_free(tmpaddr, tmpsize); } -#ifdef FLOPPY_SANITY_CHECK #ifndef __sparc__ for (drive = 0; drive < N_FDC * 4; drive++) if (timer_pending(motor_off_timer + drive)) - printk("motor off timer %d still active\n", drive); + pr_info("motor off timer %d still active\n", drive); #endif if (timer_pending(&fd_timeout)) - printk("floppy timer still active:%s\n", timeout_message); + pr_info("floppy timer still active:%s\n", timeout_message); if (timer_pending(&fd_timer)) - printk("auxiliary floppy timer still active\n"); + pr_info("auxiliary floppy timer still active\n"); if (work_pending(&floppy_work)) - printk("work still pending\n"); -#endif + pr_info("work still pending\n"); old_fdc = fdc; for (fdc = 0; fdc < N_FDC; fdc++) if (FDCS->address != -1) @@ -4577,7 +4554,9 @@ static void __init parse_floppy_cfg_string(char *cfg) char *ptr; while (*cfg) { - for (ptr = cfg; *cfg && *cfg != ' ' && *cfg != '\t'; cfg++) ; + ptr = cfg; + while (*cfg && *cfg != ' ' && *cfg != '\t') + cfg++; if (*cfg) { *cfg = '\0'; cfg++; @@ -4625,6 +4604,7 @@ static void __exit floppy_module_exit(void) /* eject disk, if any */ fd_eject(0); } + module_exit(floppy_module_exit); module_param(floppy, charp, 0); @@ -4636,9 +4616,10 @@ MODULE_LICENSE("GPL"); /* This doesn't actually get used other than for module information */ static const struct pnp_device_id floppy_pnpids[] = { - { "PNP0700", 0 }, - { } + {"PNP0700", 0}, + {} }; + MODULE_DEVICE_TABLE(pnp, floppy_pnpids); #else diff --git a/drivers/char/ChangeLog b/drivers/char/ChangeLog deleted file mode 100644 index 56b8a2e..0000000 --- a/drivers/char/ChangeLog +++ /dev/null @@ -1,775 +0,0 @@ -2001-08-11 Tim Waugh <twaugh@redhat.com> - - * serial.c (get_pci_port): Deal with awkward Titan cards. - -1998-08-26 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c (rs_open): Correctly decrement the module in-use count - on errors. - -Thu Feb 19 14:24:08 1998 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * tty_io.c (tty_name): Remove the non-reentrant (and non-SMP safe) - version of tty_name, and rename the reentrant _tty_name - function to be tty_name. - (tty_open): Add a warning message stating callout devices - are deprecated. - -Mon Dec 1 08:24:15 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * tty_io.c (tty_get_baud_rate): Print a warning syslog if the - tty->alt_speed kludge is used; this means the system is - using the deprecated SPD_HI ioctls. - -Mon Nov 24 10:37:49 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c, esp.c, rocket.c: Change drivers to take advantage of - tty_get_baud_rate(). - - * tty_io.c (tty_get_baud_rate): New function which computes the - correct baud rate for the tty. More factoring out of - common code out of the serial driver to the high-level tty - functions.... - -Sat Nov 22 07:53:36 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c, esp.c, rocket.c: Add tty->driver.break() routine, and - allow high-level tty code to handle the break and soft - carrier ioctls. - - * tty_ioctl.c (n_tty_ioctl): Support TIOCGSOFTCAR and - TIOCSSOFTCAR, so that device drivers don't have to support - it. - - * serial.c (autoconfig): Change 16750 test to hopefully eliminate - false results by people with strange 16550As being - detected as 16750s. Hopefully 16750s will still be - detected as 16750, and other weird UARTs won't get poorly - autodetected. If this doesn't work, I'll have to disable - the auto identification for the 16750. - - * tty_io.c (tty_hangup): Now actually do the tty hangup - processing during the timer processing, and disable - interrupts while doing the hangup processing. This avoids - several nasty race conditions which happened when the - hangup processing was done asynchronously. - (tty_ioctl): Do break handling in the tty driver if - driver's break function is supported. - (tty_flip_buffer_push): New exported function which should - be used by drivers to push characters in the flip buffer - to the tty handler. This may either be done using a task - queue function for better CPU efficiency, or directly for - low latency operation. - - * serial.c (rs_set_termios): Fix bug rs_set_termios when - transitioning away from B0, submitted by Stanislav - Voronyi. - -Thu Jun 19 20:05:58 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c (begin_break, end_break, rs_ioctl): Applied patch - to support BSD ioctls to set and clear the break - condition explicitly. - - * console.c (scrup, scrdown, insert_line, delete_line): Applied - fix suggested by Aaron Tiensivu to speed up block scrolls - up and down. - - * n_tty.c (opost_block, write_chan): Added a modified "fast - console" patch which processes a block of text via - "cooking" efficiently. - -Wed Jun 18 15:25:50 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * tty_io.c (init_dev, release_dev): Applied fix suggested by Bill - Hawes to prevent race conditions in the tty code. - - * n_tty.c (n_tty_chars_in_buffer): Applied fix suggested by Bill - Hawes so that n_tty_chars_in_buffer returns the correct - value in the case when the tty is in cannonical mode. (To - avoid a pty deadlock with telnetd.) - -Thu Feb 27 01:53:08 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c (change_speed): Add support for the termios flag - CMSPAR, which allows the user to select stick parity. - (i.e, if PARODD is set, the parity bit is always 1; if - PARRODD is not set, then the parity bit is always 0). - -Wed Feb 26 19:03:10 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c (cleanup_module): Fix memory leak when using the serial - driver as a module; make sure tmp_buf gets freed! - -Tue Feb 25 11:01:59 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c (set_modem_info): Add support for setting and clearing - the OUT1 and OUT2 bits. (For special case UART's, usually - for half-duplex.) - (autoconfig, change_speed): Fix TI 16750 support. - -Sun Feb 16 00:14:43 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * tty_io.c (release_dev): Add sanity check to make sure there are - no waiters on tty->read_wait or tty->write_wait. - - * serial.c (rs_init): Don't autoconfig a device if the I/O region - is already reserved. - - * serial.c (serial_proc_info): Add support for /proc/serial. - -Thu Feb 13 00:49:10 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c (receive_chars): When the UART repotrs an overrun - condition, it does so with a valid character. Changed to - not throw away the valid character, but instead report the - overrun after the valid character. - - * serial.c: Added new #ifdef's for some of the advanced serial - driver features. A minimal driver that only supports COM - 1/2/3/4 without sharing serial interrupts only takes 17k; - the full driver takes 32k. - -Wed Feb 12 14:50:44 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * vt.c: - * pty.c: - * tty_ioctl.c: - * serial.c: Update routines to use the new 2.1 memory access - routines. - -Wed Dec 4 07:51:52 1996 Theodore Ts'o <tytso@localhost.mit.edu> - - * serial.c (change_speed): Use save_flags(); cli() and - restore_flags() in order to ensure we don't accidentally - turn on interrupts when starting up the port. - (startup): Move the insertion of serial structure into the - IRQ chain earlier into the startup processing. Interrupts - should be off this whole time, but we eventually will want - to reduce this window. - -Thu Nov 21 10:05:22 1996 Theodore Ts'o <tytso@localhost.mit.edu> - - * tty_ioctl.c (tty_wait_until_sent): Always check the driver - wait_until_ready routine, even if there are no characters - in the xmit buffer. (There may be charactes in the device - FIFO.) - (n_tty_ioctl): Add new flag tty->flow_stopped which - indicates whether the tty is stopped due to a request by - the TCXONC ioctl (used by tcflow). If so, don't let an - incoming XOFF character restart the tty. The tty can only - be restarted by another TCXONC request. - - * tty_io.c (start_tty): Don't allow the tty to be restarted if - tty->flow_stopped is true. - - * n_tty.c (n_tty_receive_char): If tty->flow_stopped is true, and - IXANY is set, don't eat a character trying to restart the - tty. - - * serial.c (startup): Remove need for MCR_noint from the - async_struct structure. Only turn on DTR and RTS if the - baud rate is not zero. - (change_speed): More accurately calculate the timeout - value based on the word size. Move responsibility of - hangup when speed becomes B0 to rs_set_termios() - (set_serial_info): When changing the UART type set the - current xmit_fifo_size as well as the permanent - xmit_fifo_size. - (rs_ioctl): Fix TCSBRK (used by tcdrain) and TCSBRKP - ioctls to return EINTR if interrupted by a signal. - (rs_set_termios): If the baud rate changes to or from B0, - this function is now responsible for setting or clearing - DTR and RTS. DTR and RTS are only be changed on the - transition to or from the B0 state. - (rs_close): Wait for the characters to drain based on - info->timeout. At low baud rates (50 bps), it may take a - long time for the FIFO to completely drain out! - (rs_wait_until_sent): Fixed timeout handling. Now - releases control to the scheduler, but checks frequently - enough so that the function is sensitive enough to pass - the timing requirements of the NIST-PCTS. - (block_til_ready): When opening the device, don't turn on - DTR and RTS if the baud rate is B0. - -Thu Nov 14 00:06:09 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c (autoconfig): Fix autoconfiguration problems; - info->flags wasn't getting initialized from the state - structure. Put in more paranoid test for the 16750. - -Fri Nov 8 20:19:50 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * n_tty.c (n_tty_flush_buffer): Only call driver->unthrottle() if - the tty was previous throttled. - (n_tty_set_termios, write_chan): Add changes suggested by - Simon P. Allen to allow hardware cooking. - - * tty_ioctl.c (set_termios): If we get a signal while waiting for - the tty to drain, return -EINTR. - - * serial.c (change_speed): Add support for CREAD, as required by - POSIX. - -Sat Nov 2 20:43:10 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * serial.c: Wholesale changes. Added support for the Startech - 16650 and 16650V2 chips. (WARNING: the new startech - 16650A may or may not work!) Added support for the - TI16750 (not yet tested). Split async_struct into a - transient part (async_struct) and a permanent part - (serial_state) which contains the configuration - information for the ports. Added new driver routines - wait_until_sent() and send_xchar() to help with POSIX - compliance. Added support for radio clocks which waggle - the carrier detect line (CONFIG_HARD_PPS). - - * tty_ioctl.c (tty_wait_until_sent): Added call to new driver - function tty->driver.wait_until_sent(), which returns when - the tty's device xmit buffers are drained. Needed for - full POSIX compliance. - - (send_prio_char): New function, called by the ioctl's - TCIOFF and TCION; uses the new driver call send_xchar(), - which will send the XON or XOFF character at high priority - (and even if tty output is stopped). - -Wed Jun 5 18:52:04 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * pty.c (pty_close): When closing a pty, make sure packet mode is - cleared. - -Sun May 26 09:33:52 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * vesa_blank.c (set_vesa_blanking): Add missing verify_area() call. - - * selection.c (set_selection): Add missing verify_area() call. - - * tty_io.c (tty_ioctl): Add missing verify_area() calls. - - * serial.c (rs_ioctl): Add missing verify_area() calls. - (rs_init): Allow initialization of serial driver - configuration from a module. - - * random.c (extract_entropy): Add missing verify_area call. - Don't limit number of characters returned to - 32,768. Extract entropy is now no longer a inlined - function. - - (random_read): Check return value in case extract_entropy - returns an error. - - (secure_tcp_sequence_number): New function which returns a - secure TCP sequence number. This is needed to prevent some - nasty TCP hijacking attacks. - - (init_std_data): Initialize using gettimeofday() instead of - struct timeval xtime. - - (fast_add_entropy_word, add_entropy_word): Rename the - inline function add_entropy_word() to - fast_add_entropy_word(). Make add_entropy_word() be the - non-inlined function which is used in non-timing critical - places, in order to save space. - - (initialize_benchmark, begin_benchmark, end_benchmark): New - functions defined when RANDOM_BENCHMARK is defined. They - allow us to benchmark the speed of the - add_timer_randomness() call. - - (int_ln, rotate_left): Add two new inline functions with - i386 optimized asm instructions. This speeds up the - critical add_entropy_word() and add_timer_randomness() - functions, which are called from interrupt handlers. - -Tue May 7 22:51:11 1996 <tytso@rsts-11.mit.edu> - - * random.c (add_timer_randomness): Limit the amount randomness - that we estimate to 12 bits. (An arbitrary amount). - - (extract_entropy): To make it harder to analyze the hash - function, fold the hash function in half using XOR, and - use the folded result as the value to emit to the user. - Also, add timer randomness each pass through the - exact_entropy call, to increase the amount of unknown - values during the extraction process. - - (random_ioctl): Use IOR/IOW definitions to define the - ioctl values used by the /dev/random driver. Allow the - old ioctl values to be used for backwards compatibility - (for a limited amount of time). - -Wed Apr 24 14:02:04 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> - - * random.c (add_timer_randomness): Use 2nd derivative as well to - better estimate entropy. - - (rand_initialize): Explicitly initialize all the pointers - to NULL. (Clearing pointers using memset isn't portable.) - Initialize the random pool with OS-dependent data. - - (random_write): Add sanity checking to the arguments to - random_write(), so that bad arguments won't cause a kernel - SEGV. - - (random_read): Update the access time of the device inode - when you return data to the user. - - (random_ioctl): Wake up the random_wait channel when there - are only WAIT_INPUT_BITS available. Add more paranoia - checks to make sure entropy_count doesn't go beyond the - bounds of (0, POOLSIZE). Add a few missing verify_area - checks. Add support for the RNDCLEARPOOL ioctl, which - zaps the random pool. - - (add_timer_randomness): Wake up the random_wait - channel only when there are WAIT_INPUT_BITS available. - - (random_select): Allow a random refresh daemon process to - select on /dev/random for writing; wake up the daemon when - there are less than WAIT_OUTPUT_BITS bits of randomness - available. - -Tue Apr 23 22:56:07 1996 <tytso@rsts-11.mit.edu> - - * tty_io.c (init_dev): Change return code when user attempts to - open master pty which is already open from EAGAIN to EIO, - to match with BSD expectations. EIO is more correct - anyway, since EAGAIN implies that retrying will be - successful --- which it might be.... Eventually!! - - * pty.c (pty_open, pty_close): Fix wait loop so that we don't - busy loop while waiting for the master side to open. - Fix tty opening/closing logic. TTY_SLAVE_CLOSED was - renamed to TTY_OTHER_CLOSED, so that the name is more - descriptive. Also fixed code so that the tty flag - actually works correctly now.... - -Mon Apr 1 10:22:01 1996 <tytso@rsts-11.mit.edu> - - * serial.c (rs_close): Cleaned up modularization changes. - Remove code which forced line discipline back to N_TTY - this is done in the tty upper layers, and there's no - reason to do it here. (Making this change also - removed the requirement that the serial module access - the internal kernel symbol "ldiscs".) - - * tty_io.c (tty_init): Formally register a tty_driver entry for - /dev/tty (device 4, 0) and /dev/console (device 5, 0). - This guarantees that major device numbers 4 and 5 will be - reserved for the tty subsystem (as they have to be because - of /dev/tty and /dev/console). Removed tty_regdev, as - this interface is no longer necessary. - -Sun Mar 17 20:42:47 GMT 1996 <ah@doc.ic.ac.uk> - - * serial.c : modularisation (changes in linux/fs/device.c allow - kerneld to automatically load the serial module). - - * Makefile, Config.in : serial modularisation adds. - - * tty_io.c : tty_init_ctty used by to register "cua" driver just - for the /dev/tty device (5,0). Added tty_regdev. - - * serial.c (shutdown, rs_ioctl) : when port shuts down wakeup processes - waiting on delta_msr_wait. The TIOCMIWAIT ioctl returns EIO - if no change was done since the time of call. - -Sat Mar 16 14:33:13 1996 <aeb@cwi.nl> - - * tty_io.c (disassociate_ctty): If disassociate_ctty is called by - exit, do not perform an implicit vhangup on a pty. - -Fri Feb 9 14:15:47 1996 <tytso@rsts-11.mit.edu> - - * serial.c (block_til_ready): Fixed another race condition which - happens if a hangup happens during the open. - -Wed Jan 10 10:08:00 1996 <tytso@rsts-11.mit.edu> - - * serial.c (block_til_ready): Remove race condition which happened - if a hangup condition happened during the setup of the - UART, before rs_open() called block_til_ready(). This - caused the info->count counter to be erroneously - decremented. - - * serial.c (startup, rs_open): Remove race condition that could - cause a memory leak of one page. (Fortunately, both race - conditions were relatively rare in practice.) - -Tue Dec 5 13:21:27 1995 <tytso@rsts-11.mit.edu> - - * serial.c (check_modem_status, rs_ioctl): Support the new - ioctl()'s TIOCGICOUNT, TIOCMIWAIT. These allow an - application program to wait on a modem serial register - status bit change, and to find out how many changes have - taken place for the MSR bits. - - (rs_write): Eliminate a race condition which is introduced - if it is necessary to wait for the semaphore. - -Sat Nov 4 17:14:45 1995 <tytso@rsts-11.mit.edu> - - * tty_io.c (tty_init): Move registration of TTY_MAJOR and - TTY_AUX_MAJOR to the end, so that /proc/devices looks - prettier. - - * pty.c (pty_init): Use new major numbers for PTY master and slave - devices. This allow us to have more than 64 pty's. We - register the old pty devices for backwards compatibility. - Note that a system should either be using the old pty - devices or the new pty devices --- in general, it should - try to use both, since they map into the same pty table. - The old pty devices are strictly for backwards compatibility. - -Wed Oct 11 12:45:24 1995 <tytso@rsts-11.mit.edu> - - * tty_io.c (disassociate_ctty): If disassociate_ctty is called by - exit, perform an implicit vhangup on the tty. - - * pty.c (pty_close): When the master pty is closed, send a hangup - to the slave pty. - (pty_open): Use the flag TTY_SLAVE_CLOSED to test to see - if there are any open slave ptys, instead of using - tty->link->count. The old method got confused if there - were processes that had hung-up file descriptors on the - slave tty. - -Tue May 2 00:53:25 1995 <tytso@rsx-11.mit.edu> - - * tty_io.c (tty_set_ldisc): Wait until the output buffer is - drained before closing the old line discipline --- needed - in only one case: XON/XOFF processing. - - * n_tty.c (n_tty_close): Don't bother waiting until the output - driver is closed; in general, the line discipline - shouldn't care if the hardware is finished - transmitting before the line discipline terminates. - - * tty_io.c (release_dev): Shutdown the line discipline after - decrementing the tty count variable; but set the - TTY_CLOSING flag so that we know that this tty structure - isn't long for this world. - - * tty_io.c (init_dev): Add sanity code to check to see if - TTY_CLOSING is set on a tty structure; if so, something - bad has happened (probably a line discipline close blocked - when it shouldn't have; so do a kernel printk and then - return an error). - -Wed Apr 26 10:23:44 1995 Theodore Y. Ts'o <tytso@localhost> - - * tty_io.c (release_dev): Try to shutdown the line discipline - *before* decrementing the tty count variable; this removes - a potential race condition which occurs when the line - discipline close blocks, and another process then tries - open the same serial port. - - * serial.c (rs_hangup): When hanging up, flush the output buffer - before shutting down the UART. Otherwise the line - discipline close blocks waiting for the characters to get - flushed, which never happens until the serial port gets reused. - -Wed Apr 12 08:06:16 1995 Theodore Y. Ts'o <tytso@localhost> - - * serial.c (do_serial_hangup, do_softint, check_modem_status, - rs_init): Hangups are now scheduled via a separate tqueue - structure in the async_struct structure, tqueue_hangup. - This task is pushed on to the tq_schedule queue, so that - it is processed synchronously by the scheduler. - -Sat Feb 18 12:13:51 1995 Theodore Y. Ts'o (tytso@rt-11) - - * tty_io.c (disassociate_ctty, tty_open, tty_ioctl): Clear - current->tty_old_pgrp field when a session leader - acquires a controlling tty, and after a session leader - has disassociated from a controlling tty. - -Fri Feb 17 09:34:09 1995 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (rs_interrupt_single, rs_interrupt, rs_interrupt_multi): - Change the number of passes made from 64 to be 256, - configurable with the #define RS_ISR_PASS_LIMIT. - - * serial.c (rs_init, set_serial_info, get_serial_info, rs_close): - Remove support for closing_wait2. Instead, set - tty->closing and rely on the line discipline to prevent - echo wars. - - * n_tty.c (n_tty_receive_char): IEXTEN does not need to be - enabled in order for IXANY to be active. - - If tty->closing is set, then only process XON and XOFF - characters. - -Sun Feb 12 23:57:48 1995 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (rs_timer): Change the interrupt poll time from 60 - seconds to 10 seconds, configurable with the #define - RS_STROBE_TIME. - - * serial.c (rs_interrupt_multi, startup, shutdown, rs_ioctl, - set_multiport_struct, get_multiport_struct): Add - provisions for a new type of interrupt service routine, - which better supports multiple serial ports on a single - IRQ. - -Sun Feb 5 19:35:11 1995 Theodore Y. Ts'o (tytso@rt-11) - - * tty_ioctl.c (n_tty_ioctl, set_termios, tty_wait_until_sent): - * serial.c (rs_ioctl, rs_close): - * cyclades.c (cy_ioctl, cy_close): - * n_tty.c (n_tty_close): Rename wait_until_sent to - tty_wait_until_sent, so that it's a better name to export - in ksyms.c. - -Sat Feb 4 23:36:20 1995 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (rs_close): Added missing check for closing_wait2 being - ASYNC_CLOSING_WAIT_NONE. - -Thu Jan 26 09:02:49 1995 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (rs_init, set_serial_info, get_serial_info, - rs_close): Support close_wait in the serial driver. - This is helpful for slow devices (like serial - plotters) so that their outputs don't get flushed upon - device close. This has to be configurable because - normally we don't want ports to be hung up for long - periods of time during a close when they are not - connected to a device, or the device is powered off. - - The default is to wait 30 seconds; in the case of a - very slow device, the close_wait timeout should be - lengthened. If it is set to 0, the kernel will wait - forever for all of the data to be transmitted. - -Thu Jan 17 01:17:20 1995 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (startup, change_speed, rs_init): Add support to detect - the StarTech 16650 chip. Treat it as a 16450 for now, - because of its FIFO bugs. - -Thu Jan 5 21:21:57 1995 <dahinds@users.sourceforge.net> - - * serial.c: (receive_char): Added counter to prevent infinite loop - when a PCMCIA serial device is ejected. - -Thu Dec 29 17:53:48 1994 <tytso@rsx-11.mit.edu> - - * tty_io.c (check_tty_count): New procedure which checks - tty->count to make sure that it matches with the number of - open file descriptors which point at the structure. If - the number doesn't match, it prints a warning message. - -Wed Dec 28 15:41:51 1994 <tytso@rsx-11.mit.edu> - - * tty_io.c (do_tty_hangup, disassociate_ctty): At hangup time, - save the tty's current foreground process group in the - session leader's task structure. When the session leader - terminates, send a SIGHUP, SIGCONT to that process group. - This is not required by POSIX, but it's not prohibited - either, and it appears to be the least intrusive way - to fix a problem that dialup servers have with - orphaned process groups caused by modem hangups. - -Thu Dec 8 14:52:11 1994 <tytso@rsx-11.mit.edu> - - * serial.c (rs_ioctl): Don't allow most ioctl's if the serial port - isn't initialized. - - * serial.c (rs_close): Don't clear the IER if the serial port - isn't initialized. - - * serial.c (block_til_ready): Don't try to block on the dialin - port if the serial port isn't initialized. - -Wed Dec 7 10:48:30 1994 Si Park (si@wimpol.demon.co.uk) - * tty_io.c (tty_register_driver): Fix bug when linking onto - the tty_drivers list. We now test that there are elements - already on the list before setting the back link from the - first element to the new driver. - - * tty_io.c (tty_unregister_driver): Fix bug in unlinking the - specified driver from the tty_drivers list. We were not - setting the back link correctly. This used to result in - a dangling back link pointer and cause panics on the next - call to get_tty_driver(). - -Tue Nov 29 10:21:09 1994 Theodore Y. Ts'o (tytso@rt-11) - - * tty_io.c (tty_unregister_driver): Fix bug in - tty_unregister_driver where the pointer to the refcount is - tested, instead of the refcount itself. This caused - tty_unregister_driver to always return EBUSY. - -Sat Nov 26 11:59:24 1994 Theodore Y. Ts'o (tytso@rt-11) - - * tty_io.c (tty_ioctl): Add support for the new ioctl - TIOCTTYGSTRUCT, which allow a kernel debugging program - direct read access to the tty and tty_driver structures. - -Fri Nov 25 17:26:22 1994 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (rs_set_termios): Don't wake up processes blocked in - open when the CLOCAL flag changes, since a blocking - open only samples the CLOCAL flag once when it blocks, - and doesn't check it again. (n.b. FreeBSD has a - different behavior for blocking opens; it's not clear - whether Linux or FreeBSD's interpretation is correct. - POSIX doesn't give clear guidance on this issue, so - this may change in the future....) - - * serial.c (block_til_ready): Use the correct termios structure to - check the CLOCAL flag. If the cuaXX device is active, - then check the saved termios for the ttySXX device. - Otherwise, use the currently active termios structure. - -Sun Nov 6 21:05:44 1994 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (change_speed): Add support for direct access of - 57,600 and 115,200 bps. - -Wed Nov 2 10:32:36 1994 Theodore Y. Ts'o (tytso@rt-11) - - * n_tty.c (n_tty_receive_room): Only allow excess characters - through if we are in ICANON mode *and* there are other no - pending lines in the buffer. Otherwise cut and paste over - 4k breaks. - -Sat Oct 29 18:17:34 1994 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (rs_ioctl, get_lsr_info): Added patch suggested by Arne - Riiber so that user mode programs can tell when the - transmitter shift register is empty. - -Thu Oct 27 23:14:29 1994 Theodore Y. Ts'o (tytso@rt-11) - - * tty_ioctl.c (wait_until_sent): Added debugging printk statements - (under the #ifdef TTY_DEBUG_WAIT_UNTIL_SENT) - - * serial.c (rs_interrupt, rs_interrupt_single, receive_chars, - change_speed, rs_close): rs_close now disables receiver - interrupts when closing the serial port. This allows the - serial port to close quickly when Linux and a modem (or a - mouse) are engaged in an echo war; when closing the serial - port, we now first stop listening to incoming characters, - and *then* wait for the transmit buffer to drain. - - In order to make this change, the info->read_status_mask - is now used to control what bits of the line status - register are looked at in the interrupt routine in all - cases; previously it was only used in receive_chars to - select a few of the status bits. - -Mon Oct 24 23:36:21 1994 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (rs_close): Add a timeout to the transmitter flush - loop; this is just a sanity check in case we have flaky - (or non-existent-but-configured-by-the-user) hardware. - -Fri Oct 21 09:37:23 1994 Theodore Y. Ts'o (tytso@rt-11) - - * tty_io.c (tty_fasync): When asynchronous I/O is enabled, if the - process or process group has not be specified yet, set it - to be the tty's process group, or if that is not yet set, - to the current process's pid. - -Thu Oct 20 23:17:28 1994 Theodore Y. Ts'o (tytso@rt-11) - - * n_tty.c (n_tty_receive_room): If we are doing input - canonicalization, let as many characters through as - possible, so that the excess characters can be "beeped". - -Tue Oct 18 10:02:43 1994 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (rs_start): Removed an incorrect '!' that was - preventing transmit interrupts from being re-enabled in - rs_start(). Fortunately in most cases it would be - re-enabled elsewhere, but this still should be fixed - correctly. - -Sun Oct 9 23:46:03 1994 Theodore Y. Ts'o (tytso@rt-11) - - * tty_io.c (do_tty_hangup): If the tty driver flags - TTY_DRIVER_RESET_TERMIOS is set, then reset the termios - settings back to the driver's initial configuration. This - allows the termios settings to be reset even if a process - has hung up file descriptors keeping a pty's termios from - being freed and reset. - - * tty_io.c (release_dev): Fix memory leak. The pty's other - termios structure should also be freed. - - * serial.c (rs_close, shutdown): Change how we wait for the - transmitter to completely drain before shutting down the - serial port. We now do it by scheduling in another - process instead of busy looping with the interrupts turned - on. This may eliminate some race condition problems that - some people seem to be reporting. - -Sun Sep 25 14:18:14 1994 Theodore Y. Ts'o (tytso@rt-11) - - * tty_io.c (release_dev): When freeing a tty make sure that both - the tty and the o_tty (if present) aren't a process's - controlling tty. (Previously, we only checked the tty.) - - * serial.c (change_speed): Only enable the Modem Status - Interrupt for a port if CLOCAL is not set or CRTSCTS - is set. If we're not checking the carrier detect and - CTS line, there's no point in enabling the modem - status interrupt. This will save spurious interrupts - from slowing down systems who have terminals that - don't support either line. (Of course, if you want - only one of CD and CTS support, you will need a - properly wired serial cable.) - -Thu Sep 22 08:32:48 1994 Theodore Y. Ts'o (tytso@rt-11) - - * tty_io.c (do_SAK): Return if tty is null. - - * tty_io.c (_tty_name): Return "NULL tty" if the passed in tty is - NULL. - -Sat Sep 17 13:19:25 1994 Theodore Y. Ts'o (tytso@rt-11) - - * tty_ioctl.c (n_tty_ioctl): Fix TIOCGLCKTRMIOS and - TIOCSLCKTRMIOS, which were totally broken. Remove - extra indirection from argument; it should be a struct - termios *, not a struct termios **. - &real_tty->termios_locked should have been - real_tty->termios_locked. This caused us to be - reading and writing the termios_locked structure to - random places in kernel memory. - - * tty_io.c (release_dev): Oops! Forgot to delete a critical kfree - of the locked_termios. This leaves the locked_termios - structure pointed at a freed object. - -Fri Sep 16 08:13:25 1994 Theodore Y. Ts'o (tytso@rt-11) - - * tty_io.c (tty_open): Don't check for an exclusive open until - after the device specific open routine has been called. - Otherwise, the serial device ref counting will be screwed - up. - - * serial.c (rs_open, block_til_ready): Don't set termios structure - until after block_til_ready has returned successfully. - Modify block_til_ready to check the normal_termios - structure directly, so it doesn't rely on termios being - set before it's called. - -Thu Sep 15 23:34:01 1994 Theodore Y. Ts'o (tytso@rt-11) - - * serial.c (rs_close): Turn off interrupts during rs_close() to - prevent a race condition with the hangup code (which - runs during a software interrupt). - - * tty_io.c (release_dev): Don't free the locked_termios structure; - its state must be retained across device opens. - - - * tty_io.c (tty_unregister_driver): Added function to unregister a - tty driver. (For loadable device drivers.) - - diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 2fb3a48..4b66c69 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -57,7 +57,7 @@ config AGP_AMD config AGP_AMD64 tristate "AMD Opteron/Athlon64 on-CPU GART support" - depends on AGP && X86 + depends on AGP && X86 && K8_NB help This option gives you AGP support for the GLX component of X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 919a285..a3e10dc 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -298,7 +298,7 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem, j++; } } else { - /* sg may merge pages, but we have to seperate + /* sg may merge pages, but we have to separate * per-page addr for GTT */ unsigned int len, m; diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index fe2cb2f..a7424bf 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c @@ -14,7 +14,7 @@ /* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter */ /* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3 */ /* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes */ -/* adresses de base des cartes, IOCTL 6 plus complet */ +/* addresses de base des cartes, IOCTL 6 plus complet */ /* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification */ /* de code autre que le texte V2.6.1 en V2.8.0 */ /*****************************************************************************/ diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index fd02426..21c5495 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c @@ -353,7 +353,7 @@ static void hvc_close_event(struct HvLpEvent *event) if (!hvlpevent_is_int(event)) { printk(KERN_WARNING - "hvc: got unexpected close acknowlegement\n"); + "hvc: got unexpected close acknowledgement\n"); return; } diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 9b3e09c..10f868e 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -71,7 +71,7 @@ MODULE_VERSION(DRV_MODULE_VERSION); * x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1 * * The RNG_CTL_VCO value of each noise cell must be programmed - * seperately. This is why 4 control register values must be provided + * separately. This is why 4 control register values must be provided * to the hypervisor. During a write, the hypervisor writes them all, * one at a time, to the actual RNG_CTL register. The first three * values are used to setup the desired RNG_CTL_VCO for each entropy diff --git a/drivers/char/ip2/i2hw.h b/drivers/char/ip2/i2hw.h index 8aa6e7a..c0ba6c0 100644 --- a/drivers/char/ip2/i2hw.h +++ b/drivers/char/ip2/i2hw.h @@ -559,7 +559,7 @@ Loadware may be sent to the board in two ways: 2) It may be hard-coded into your source by including a .h file (typically supplied by Computone), which declares a data array and initializes every - element. This acheives the same result as if an entire loadware file had + element. This achieves the same result as if an entire loadware file had been read into the array. This requires more data space in your program, but access to the file system diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 176f175..4462b11 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -295,6 +295,9 @@ struct smi_info { static int force_kipmid[SI_MAX_PARMS]; static int num_force_kipmid; +static unsigned int kipmid_max_busy_us[SI_MAX_PARMS]; +static int num_max_busy_us; + static int unload_when_empty = 1; static int try_smi_init(struct smi_info *smi); @@ -925,23 +928,77 @@ static void set_run_to_completion(void *send_info, int i_run_to_completion) } } +/* + * Use -1 in the nsec value of the busy waiting timespec to tell that + * we are spinning in kipmid looking for something and not delaying + * between checks + */ +static inline void ipmi_si_set_not_busy(struct timespec *ts) +{ + ts->tv_nsec = -1; +} +static inline int ipmi_si_is_busy(struct timespec *ts) +{ + return ts->tv_nsec != -1; +} + +static int ipmi_thread_busy_wait(enum si_sm_result smi_result, + const struct smi_info *smi_info, + struct timespec *busy_until) +{ + unsigned int max_busy_us = 0; + + if (smi_info->intf_num < num_max_busy_us) + max_busy_us = kipmid_max_busy_us[smi_info->intf_num]; + if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY) + ipmi_si_set_not_busy(busy_until); + else if (!ipmi_si_is_busy(busy_until)) { + getnstimeofday(busy_until); + timespec_add_ns(busy_until, max_busy_us*NSEC_PER_USEC); + } else { + struct timespec now; + getnstimeofday(&now); + if (unlikely(timespec_compare(&now, busy_until) > 0)) { + ipmi_si_set_not_busy(busy_until); + return 0; + } + } + return 1; +} + + +/* + * A busy-waiting loop for speeding up IPMI operation. + * + * Lousy hardware makes this hard. This is only enabled for systems + * that are not BT and do not have interrupts. It starts spinning + * when an operation is complete or until max_busy tells it to stop + * (if that is enabled). See the paragraph on kimid_max_busy_us in + * Documentation/IPMI.txt for details. + */ static int ipmi_thread(void *data) { struct smi_info *smi_info = data; unsigned long flags; enum si_sm_result smi_result; + struct timespec busy_until; + ipmi_si_set_not_busy(&busy_until); set_user_nice(current, 19); while (!kthread_should_stop()) { + int busy_wait; + spin_lock_irqsave(&(smi_info->si_lock), flags); smi_result = smi_event_handler(smi_info, 0); spin_unlock_irqrestore(&(smi_info->si_lock), flags); + busy_wait = ipmi_thread_busy_wait(smi_result, smi_info, + &busy_until); if (smi_result == SI_SM_CALL_WITHOUT_DELAY) ; /* do nothing */ - else if (smi_result == SI_SM_CALL_WITH_DELAY) + else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) schedule(); else - schedule_timeout_interruptible(1); + schedule_timeout_interruptible(0); } return 0; } @@ -1144,7 +1201,7 @@ static int regsizes[SI_MAX_PARMS]; static unsigned int num_regsizes; static int regshifts[SI_MAX_PARMS]; static unsigned int num_regshifts; -static int slave_addrs[SI_MAX_PARMS]; +static int slave_addrs[SI_MAX_PARMS]; /* Leaving 0 chooses the default value */ static unsigned int num_slave_addrs; #define IPMI_IO_ADDR_SPACE 0 @@ -1212,6 +1269,11 @@ module_param(unload_when_empty, int, 0); MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" " specified or found, default is 1. Setting to 0" " is useful for hot add of devices using hotmod."); +module_param_array(kipmid_max_busy_us, uint, &num_max_busy_us, 0644); +MODULE_PARM_DESC(kipmid_max_busy_us, + "Max time (in microseconds) to busy-wait for IPMI data before" + " sleeping. 0 (default) means to wait forever. Set to 100-500" + " if kipmid is using up a lot of CPU time."); static void std_irq_cleanup(struct smi_info *info) @@ -1607,7 +1669,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) regsize = 1; regshift = 0; irq = 0; - ipmb = 0x20; + ipmb = 0; /* Choose the default if not specified */ next = strchr(curr, ':'); if (next) { @@ -1799,6 +1861,7 @@ static __devinit void hardcode_find_bmc(void) info->irq = irqs[i]; if (info->irq) info->irq_setup = std_irq_setup; + info->slave_addr = slave_addrs[i]; try_smi_init(info); } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 48788db..1f3215a 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -3,7 +3,7 @@ * * Copyright (C) 1991, 1992 Linus Torvalds * - * Added devfs support. + * Added devfs support. * Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu> * Shared /dev/zero mmapping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com> */ @@ -44,36 +44,6 @@ static inline unsigned long size_inside_page(unsigned long start, return min(sz, size); } -/* - * Architectures vary in how they handle caching for addresses - * outside of main memory. - * - */ -static inline int uncached_access(struct file *file, unsigned long addr) -{ -#if defined(CONFIG_IA64) - /* - * On ia64, we ignore O_DSYNC because we cannot tolerate memory attribute aliases. - */ - return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); -#elif defined(CONFIG_MIPS) - { - extern int __uncached_access(struct file *file, - unsigned long addr); - - return __uncached_access(file, addr); - } -#else - /* - * Accessing memory above the top the kernel knows about or through a file pointer - * that was marked O_DSYNC will be done non-cached. - */ - if (file->f_flags & O_DSYNC) - return 1; - return addr >= __pa(high_memory); -#endif -} - #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE static inline int valid_phys_addr_range(unsigned long addr, size_t count) { @@ -115,15 +85,15 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) } #endif -void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr) +void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr) { } /* - * This funcion reads the *physical* memory. The f_pos points directly to the - * memory location. + * This funcion reads the *physical* memory. The f_pos points directly to the + * memory location. */ -static ssize_t read_mem(struct file * file, char __user * buf, +static ssize_t read_mem(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; @@ -140,10 +110,10 @@ static ssize_t read_mem(struct file * file, char __user * buf, if (sz > 0) { if (clear_user(buf, sz)) return -EFAULT; - buf += sz; - p += sz; - count -= sz; - read += sz; + buf += sz; + p += sz; + count -= sz; + read += sz; } } #endif @@ -157,9 +127,9 @@ static ssize_t read_mem(struct file * file, char __user * buf, return -EPERM; /* - * On ia64 if a page has been mapped somewhere as - * uncached, then it must also be accessed uncached - * by the kernel or data corruption may occur + * On ia64 if a page has been mapped somewhere as uncached, then + * it must also be accessed uncached by the kernel or data + * corruption may occur. */ ptr = xlate_dev_mem_ptr(p); if (!ptr) @@ -180,7 +150,7 @@ static ssize_t read_mem(struct file * file, char __user * buf, return read; } -static ssize_t write_mem(struct file * file, const char __user * buf, +static ssize_t write_mem(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; @@ -212,9 +182,9 @@ static ssize_t write_mem(struct file * file, const char __user * buf, return -EPERM; /* - * On ia64 if a page has been mapped somewhere as - * uncached, then it must also be accessed uncached - * by the kernel or data corruption may occur + * On ia64 if a page has been mapped somewhere as uncached, then + * it must also be accessed uncached by the kernel or data + * corruption may occur. */ ptr = xlate_dev_mem_ptr(p); if (!ptr) { @@ -242,13 +212,46 @@ static ssize_t write_mem(struct file * file, const char __user * buf, return written; } -int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file, +int __weak phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, unsigned long size, pgprot_t *vma_prot) { return 1; } #ifndef __HAVE_PHYS_MEM_ACCESS_PROT + +/* + * Architectures vary in how they handle caching for addresses + * outside of main memory. + * + */ +static int uncached_access(struct file *file, unsigned long addr) +{ +#if defined(CONFIG_IA64) + /* + * On ia64, we ignore O_DSYNC because we cannot tolerate memory + * attribute aliases. + */ + return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); +#elif defined(CONFIG_MIPS) + { + extern int __uncached_access(struct file *file, + unsigned long addr); + + return __uncached_access(file, addr); + } +#else + /* + * Accessing memory above the top the kernel knows about or through a + * file pointer + * that was marked O_DSYNC will be done non-cached. + */ + if (file->f_flags & O_DSYNC) + return 1; + return addr >= __pa(high_memory); +#endif +} + static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, pgprot_t vma_prot) { @@ -294,7 +297,7 @@ static const struct vm_operations_struct mmap_mem_ops = { #endif }; -static int mmap_mem(struct file * file, struct vm_area_struct * vma) +static int mmap_mem(struct file *file, struct vm_area_struct *vma) { size_t size = vma->vm_end - vma->vm_start; @@ -329,7 +332,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) } #ifdef CONFIG_DEVKMEM -static int mmap_kmem(struct file * file, struct vm_area_struct * vma) +static int mmap_kmem(struct file *file, struct vm_area_struct *vma) { unsigned long pfn; @@ -337,9 +340,9 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; /* - * RED-PEN: on some architectures there is more mapped memory - * than available in mem_map which pfn_valid checks - * for. Perhaps should add a new macro here. + * RED-PEN: on some architectures there is more mapped memory than + * available in mem_map which pfn_valid checks for. Perhaps should add a + * new macro here. * * RED-PEN: vmalloc is not supported right now. */ @@ -389,7 +392,7 @@ static ssize_t read_oldmem(struct file *file, char __user *buf, /* * This function reads the *virtual* memory as seen by the kernel. */ -static ssize_t read_kmem(struct file *file, char __user *buf, +static ssize_t read_kmem(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; @@ -400,8 +403,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf, read = 0; if (p < (unsigned long) high_memory) { low_count = count; - if (count > (unsigned long) high_memory - p) - low_count = (unsigned long) high_memory - p; + if (count > (unsigned long)high_memory - p) + low_count = (unsigned long)high_memory - p; #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED /* we don't have page 0 mapped on sparc and m68k.. */ @@ -465,9 +468,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf, } -static inline ssize_t -do_write_kmem(unsigned long p, const char __user *buf, - size_t count, loff_t *ppos) +static ssize_t do_write_kmem(unsigned long p, const char __user *buf, + size_t count, loff_t *ppos) { ssize_t written, sz; unsigned long copied; @@ -491,9 +493,9 @@ do_write_kmem(unsigned long p, const char __user *buf, sz = size_inside_page(p, count); /* - * On ia64 if a page has been mapped somewhere as - * uncached, then it must also be accessed uncached - * by the kernel or data corruption may occur + * On ia64 if a page has been mapped somewhere as uncached, then + * it must also be accessed uncached by the kernel or data + * corruption may occur. */ ptr = xlate_dev_kmem_ptr((char *)p); @@ -514,11 +516,10 @@ do_write_kmem(unsigned long p, const char __user *buf, return written; } - /* * This function writes to the *virtual* memory as seen by the kernel. */ -static ssize_t write_kmem(struct file * file, const char __user * buf, +static ssize_t write_kmem(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; @@ -570,17 +571,17 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, #endif #ifdef CONFIG_DEVPORT -static ssize_t read_port(struct file * file, char __user * buf, +static ssize_t read_port(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long i = *ppos; char __user *tmp = buf; if (!access_ok(VERIFY_WRITE, buf, count)) - return -EFAULT; + return -EFAULT; while (count-- > 0 && i < 65536) { - if (__put_user(inb(i),tmp) < 0) - return -EFAULT; + if (__put_user(inb(i), tmp) < 0) + return -EFAULT; i++; tmp++; } @@ -588,22 +589,22 @@ static ssize_t read_port(struct file * file, char __user * buf, return tmp-buf; } -static ssize_t write_port(struct file * file, const char __user * buf, +static ssize_t write_port(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long i = *ppos; const char __user * tmp = buf; - if (!access_ok(VERIFY_READ,buf,count)) + if (!access_ok(VERIFY_READ, buf, count)) return -EFAULT; while (count-- > 0 && i < 65536) { char c; if (__get_user(c, tmp)) { if (tmp > buf) break; - return -EFAULT; + return -EFAULT; } - outb(c,i); + outb(c, i); i++; tmp++; } @@ -612,13 +613,13 @@ static ssize_t write_port(struct file * file, const char __user * buf, } #endif -static ssize_t read_null(struct file * file, char __user * buf, +static ssize_t read_null(struct file *file, char __user *buf, size_t count, loff_t *ppos) { return 0; } -static ssize_t write_null(struct file * file, const char __user * buf, +static ssize_t write_null(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { return count; @@ -630,13 +631,13 @@ static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf, return sd->len; } -static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out, +static ssize_t splice_write_null(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null); } -static ssize_t read_zero(struct file * file, char __user * buf, +static ssize_t read_zero(struct file *file, char __user *buf, size_t count, loff_t *ppos) { size_t written; @@ -667,7 +668,7 @@ static ssize_t read_zero(struct file * file, char __user * buf, return written ? written : -EFAULT; } -static int mmap_zero(struct file * file, struct vm_area_struct * vma) +static int mmap_zero(struct file *file, struct vm_area_struct *vma) { #ifndef CONFIG_MMU return -ENOSYS; @@ -677,7 +678,7 @@ static int mmap_zero(struct file * file, struct vm_area_struct * vma) return 0; } -static ssize_t write_full(struct file * file, const char __user * buf, +static ssize_t write_full(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { return -ENOSPC; @@ -688,8 +689,7 @@ static ssize_t write_full(struct file * file, const char __user * buf, * can fopen() both devices with "a" now. This was previously impossible. * -- SRB. */ - -static loff_t null_lseek(struct file * file, loff_t offset, int orig) +static loff_t null_lseek(struct file *file, loff_t offset, int orig) { return file->f_pos = 0; } @@ -702,24 +702,31 @@ static loff_t null_lseek(struct file * file, loff_t offset, int orig) * also note that seeking relative to the "end of file" isn't supported: * it has no meaning, so it returns -EINVAL. */ -static loff_t memory_lseek(struct file * file, loff_t offset, int orig) +static loff_t memory_lseek(struct file *file, loff_t offset, int orig) { loff_t ret; mutex_lock(&file->f_path.dentry->d_inode->i_mutex); switch (orig) { - case 0: - file->f_pos = offset; - ret = file->f_pos; - force_successful_syscall_return(); + case SEEK_CUR: + offset += file->f_pos; + if ((unsigned long long)offset < + (unsigned long long)file->f_pos) { + ret = -EOVERFLOW; break; - case 1: - file->f_pos += offset; - ret = file->f_pos; - force_successful_syscall_return(); + } + case SEEK_SET: + /* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */ + if ((unsigned long long)offset >= ~0xFFFULL) { + ret = -EOVERFLOW; break; - default: - ret = -EINVAL; + } + file->f_pos = offset; + ret = file->f_pos; + force_successful_syscall_return(); + break; + default: + ret = -EINVAL; } mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return ret; @@ -803,7 +810,7 @@ static const struct file_operations oldmem_fops = { }; #endif -static ssize_t kmsg_write(struct file * file, const char __user * buf, +static ssize_t kmsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *tmp; @@ -825,7 +832,7 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf, } static const struct file_operations kmsg_fops = { - .write = kmsg_write, + .write = kmsg_write, }; static const struct memdev { @@ -876,7 +883,7 @@ static int memory_open(struct inode *inode, struct file *filp) } static const struct file_operations memory_fops = { - .open = memory_open, + .open = memory_open, }; static char *mem_devnode(struct device *dev, mode_t *mode) @@ -897,7 +904,7 @@ static int __init chr_dev_init(void) if (err) return err; - if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) + if (register_chrdev(MEM_MAJOR, "mem", &memory_fops)) printk("unable to get major %d for memory devs\n", MEM_MAJOR); mem_class = class_create(THIS_MODULE, "mem"); diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 918711a..04fd0d8 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -546,7 +546,7 @@ static void mmtimer_tasklet(unsigned long data) { int nodeid = data; struct mmtimer_node *mn = &timers[nodeid]; - struct mmtimer *x = rb_entry(mn->next, struct mmtimer, list); + struct mmtimer *x; struct k_itimer *t; unsigned long flags; diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 2e50f4d..bdae832 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -48,6 +48,7 @@ #include <linux/audit.h> #include <linux/file.h> #include <linux/uaccess.h> +#include <linux/module.h> #include <asm/system.h> @@ -2091,3 +2092,19 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { .receive_buf = n_tty_receive_buf, .write_wakeup = n_tty_write_wakeup }; + +/** + * n_tty_inherit_ops - inherit N_TTY methods + * @ops: struct tty_ldisc_ops where to save N_TTY methods + * + * Used by a generic struct tty_ldisc_ops to easily inherit N_TTY + * methods. + */ + +void n_tty_inherit_ops(struct tty_ldisc_ops *ops) +{ + *ops = tty_ldisc_N_TTY; + ops->owner = NULL; + ops->refcount = ops->flags = 0; +} +EXPORT_SYMBOL_GPL(n_tty_inherit_ops); diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 385c44b..5ee4248 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -220,7 +220,7 @@ static void pty_set_termios(struct tty_struct *tty, * @tty: tty being resized * @ws: window size being set. * - * Update the termios variables and send the neccessary signals to + * Update the termios variables and send the necessary signals to * peform a terminal resize correctly */ diff --git a/drivers/char/random.c b/drivers/char/random.c index 2849713..2fd3d39 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1191,7 +1191,7 @@ const struct file_operations urandom_fops = { void generate_random_uuid(unsigned char uuid_out[16]) { get_random_bytes(uuid_out, 16); - /* Set UUID version to 4 --- truely random generation */ + /* Set UUID version to 4 --- truly random generation */ uuid_out[6] = (uuid_out[6] & 0x0F) | 0x40; /* Set the UUID variant to DCE */ uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80; diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 986aa60..1ec3d5c 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1989,7 +1989,7 @@ void mvme167_serial_console_setup(int cflag) /* * Attempt to set up all channels to something reasonable, and * bang out a INIT_CHAN command. We should then be able to limit - * the ammount of fiddling we have to do in normal running. + * the amount of fiddling we have to do in normal running. */ for (ch = 3; ch >= 0; ch--) { diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index ac16fbe..283a15b 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c @@ -148,7 +148,6 @@ void tty_audit_fork(struct signal_struct *sig) spin_lock_irq(¤t->sighand->siglock); sig->audit_tty = current->signal->audit_tty; spin_unlock_irq(¤t->sighand->siglock); - sig->tty_audit_buf = NULL; } /** diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index dcb9083..a42c466 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2028,7 +2028,7 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) * @rows: rows (character) * @cols: cols (character) * - * Update the termios variables and send the neccessary signals to + * Update the termios variables and send the necessary signals to * peform a terminal resize correctly */ diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 50faa1f..bd1d116 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -821,7 +821,7 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, * * Resize a virtual console, clipping according to the actual constraints. * If the caller passes a tty structure then update the termios winsize - * information and perform any neccessary signal handling. + * information and perform any necessary signal handling. * * Caller must hold the console semaphore. Takes the termios mutex and * ctrl_lock of the tty IFF a tty is passed. @@ -2119,8 +2119,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co uint8_t inverse; uint8_t width; u16 himask, charmask; - const unsigned char *orig_buf = NULL; - int orig_count; if (in_interrupt()) return count; @@ -2142,8 +2140,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co release_console_sem(); return 0; } - orig_buf = buf; - orig_count = count; himask = vc->vc_hi_font_mask; charmask = himask ? 0x1ff : 0xff; diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index 09ad915..73e8b17 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c @@ -321,7 +321,7 @@ static atomic_t hifn_dev_number; #define HIFN_PUBOPLEN_MOD_M 0x0000007f /* modulus length mask */ #define HIFN_PUBOPLEN_MOD_S 0 /* modulus length shift */ #define HIFN_PUBOPLEN_EXP_M 0x0003ff80 /* exponent length mask */ -#define HIFN_PUBOPLEN_EXP_S 7 /* exponent lenght shift */ +#define HIFN_PUBOPLEN_EXP_S 7 /* exponent length shift */ #define HIFN_PUBOPLEN_RED_M 0x003c0000 /* reducend length mask */ #define HIFN_PUBOPLEN_RED_S 18 /* reducend length shift */ diff --git a/drivers/dma/coh901318_lli.h b/drivers/dma/coh901318_lli.h index 7bf713b..7a5c809 100644 --- a/drivers/dma/coh901318_lli.h +++ b/drivers/dma/coh901318_lli.h @@ -30,7 +30,7 @@ struct device; * @pool: pool handle * @dev: dma device * @lli_nbr: number of lli:s in the pool - * @algin: adress alignemtn of lli:s + * @algin: address alignemtn of lli:s * returns 0 on success otherwise none zero */ int coh901318_pool_create(struct coh901318_pool *pool, diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index d205d49..243e9aa 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -75,6 +75,14 @@ static struct edac_pci_ctl_info *e752x_pci; #define E752X_NR_CSROWS 8 /* number of csrows */ /* E752X register addresses - device 0 function 0 */ +#define E752X_MCHSCRB 0x52 /* Memory Scrub register (16b) */ + /* + * 6:5 Scrub Completion Count + * 3:2 Scrub Rate (i3100 only) + * 01=fast 10=normal + * 1:0 Scrub Mode enable + * 00=off 10=on + */ #define E752X_DRB 0x60 /* DRAM row boundary register (8b) */ #define E752X_DRA 0x70 /* DRAM row attribute register (8b) */ /* @@ -240,6 +248,41 @@ static const struct e752x_dev_info e752x_devs[] = { .ctl_name = "3100"}, }; +/* Valid scrub rates for the e752x/3100 hardware memory scrubber. We + * map the scrubbing bandwidth to a hardware register value. The 'set' + * operation finds the 'matching or higher value'. Note that scrubbing + * on the e752x can only be enabled/disabled. The 3100 supports + * a normal and fast mode. + */ + +#define SDRATE_EOT 0xFFFFFFFF + +struct scrubrate { + u32 bandwidth; /* bandwidth consumed by scrubbing in bytes/sec */ + u16 scrubval; /* register value for scrub rate */ +}; + +/* Rate below assumes same performance as i3100 using PC3200 DDR2 in + * normal mode. e752x bridges don't support choosing normal or fast mode, + * so the scrubbing bandwidth value isn't all that important - scrubbing is + * either on or off. + */ +static const struct scrubrate scrubrates_e752x[] = { + {0, 0x00}, /* Scrubbing Off */ + {500000, 0x02}, /* Scrubbing On */ + {SDRATE_EOT, 0x00} /* End of Table */ +}; + +/* Fast mode: 2 GByte PC3200 DDR2 scrubbed in 33s = 63161283 bytes/s + * Normal mode: 125 (32000 / 256) times slower than fast mode. + */ +static const struct scrubrate scrubrates_i3100[] = { + {0, 0x00}, /* Scrubbing Off */ + {500000, 0x0a}, /* Normal mode - 32k clocks */ + {62500000, 0x06}, /* Fast mode - 256 clocks */ + {SDRATE_EOT, 0x00} /* End of Table */ +}; + static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page) { @@ -915,6 +958,68 @@ static void e752x_check(struct mem_ctl_info *mci) e752x_process_error_info(mci, &info, 1); } +/* Program byte/sec bandwidth scrub rate to hardware */ +static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *new_bw) +{ + const struct scrubrate *scrubrates; + struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; + struct pci_dev *pdev = pvt->dev_d0f0; + int i; + + if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0) + scrubrates = scrubrates_i3100; + else + scrubrates = scrubrates_e752x; + + /* Translate the desired scrub rate to a e752x/3100 register value. + * Search for the bandwidth that is equal or greater than the + * desired rate and program the cooresponding register value. + */ + for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++) + if (scrubrates[i].bandwidth >= *new_bw) + break; + + if (scrubrates[i].bandwidth == SDRATE_EOT) + return -1; + + pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval); + + return 0; +} + +/* Convert current scrub rate value into byte/sec bandwidth */ +static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) +{ + const struct scrubrate *scrubrates; + struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; + struct pci_dev *pdev = pvt->dev_d0f0; + u16 scrubval; + int i; + + if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0) + scrubrates = scrubrates_i3100; + else + scrubrates = scrubrates_e752x; + + /* Find the bandwidth matching the memory scrubber configuration */ + pci_read_config_word(pdev, E752X_MCHSCRB, &scrubval); + scrubval = scrubval & 0x0f; + + for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++) + if (scrubrates[i].scrubval == scrubval) + break; + + if (scrubrates[i].bandwidth == SDRATE_EOT) { + e752x_printk(KERN_WARNING, + "Invalid sdram scrub control value: 0x%x\n", scrubval); + return -1; + } + + *bw = scrubrates[i].bandwidth; + + return 0; +} + /* Return 1 if dual channel mode is active. Else return 0. */ static inline int dual_channel_active(u16 ddrcsr) { @@ -1073,10 +1178,7 @@ fail: /* Setup system bus parity mask register. * Sysbus parity supported on: - * e7320/e7520/e7525 + Xeon - * i3100 + Xeon/Celeron - * Sysbus parity not supported on: - * i3100 + Pentium M/Celeron M/Core Duo/Core2 Duo + * e7320/e7520/e7525 + Xeon */ static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt) { @@ -1087,10 +1189,7 @@ static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt) /* Allow module parameter override, else see if CPU supports parity */ if (sysbus_parity != -1) { enable = sysbus_parity; - } else if (cpu_id[0] && - ((strstr(cpu_id, "Pentium") && strstr(cpu_id, " M ")) || - (strstr(cpu_id, "Celeron") && strstr(cpu_id, " M ")) || - (strstr(cpu_id, "Core") && strstr(cpu_id, "Duo")))) { + } else if (cpu_id[0] && !strstr(cpu_id, "Xeon")) { e752x_printk(KERN_INFO, "System Bus Parity not " "supported by CPU, disabling\n"); enable = 0; @@ -1187,6 +1286,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) mci->dev_name = pci_name(pdev); mci->edac_check = e752x_check; mci->ctl_page_to_phys = ctl_page_to_phys; + mci->set_sdram_scrub_rate = set_sdram_scrub_rate; + mci->get_sdram_scrub_rate = get_sdram_scrub_rate; /* set the map type. 1 = normal, 0 = reversed * Must be set before e752x_init_csrows in case csrow mapping diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index ecd5928..94cac0a 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -239,16 +239,15 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op, /* we only need the error registers */ r.start += 0xe00; - if (!devm_request_mem_region(&op->dev, r.start, - r.end - r.start + 1, pdata->name)) { + if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r), + pdata->name)) { printk(KERN_ERR "%s: Error while requesting mem region\n", __func__); res = -EBUSY; goto err; } - pdata->pci_vbase = devm_ioremap(&op->dev, r.start, - r.end - r.start + 1); + pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r)); if (!pdata->pci_vbase) { printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__); res = -ENOMEM; @@ -668,15 +667,125 @@ static struct of_platform_driver mpc85xx_l2_err_driver = { /**************************** MC Err device ***************************/ +/* + * Taken from table 8-55 in the MPC8641 User's Manual and/or 9-61 in the + * MPC8572 User's Manual. Each line represents a syndrome bit column as a + * 64-bit value, but split into an upper and lower 32-bit chunk. The labels + * below correspond to Freescale's manuals. + */ +static unsigned int ecc_table[16] = { + /* MSB LSB */ + /* [0:31] [32:63] */ + 0xf00fe11e, 0xc33c0ff7, /* Syndrome bit 7 */ + 0x00ff00ff, 0x00fff0ff, + 0x0f0f0f0f, 0x0f0fff00, + 0x11113333, 0x7777000f, + 0x22224444, 0x8888222f, + 0x44448888, 0xffff4441, + 0x8888ffff, 0x11118882, + 0xffff1111, 0x22221114, /* Syndrome bit 0 */ +}; + +/* + * Calculate the correct ECC value for a 64-bit value specified by high:low + */ +static u8 calculate_ecc(u32 high, u32 low) +{ + u32 mask_low; + u32 mask_high; + int bit_cnt; + u8 ecc = 0; + int i; + int j; + + for (i = 0; i < 8; i++) { + mask_high = ecc_table[i * 2]; + mask_low = ecc_table[i * 2 + 1]; + bit_cnt = 0; + + for (j = 0; j < 32; j++) { + if ((mask_high >> j) & 1) + bit_cnt ^= (high >> j) & 1; + if ((mask_low >> j) & 1) + bit_cnt ^= (low >> j) & 1; + } + + ecc |= bit_cnt << i; + } + + return ecc; +} + +/* + * Create the syndrome code which is generated if the data line specified by + * 'bit' failed. Eg generate an 8-bit codes seen in Table 8-55 in the MPC8641 + * User's Manual and 9-61 in the MPC8572 User's Manual. + */ +static u8 syndrome_from_bit(unsigned int bit) { + int i; + u8 syndrome = 0; + + /* + * Cycle through the upper or lower 32-bit portion of each value in + * ecc_table depending on if 'bit' is in the upper or lower half of + * 64-bit data. + */ + for (i = bit < 32; i < 16; i += 2) + syndrome |= ((ecc_table[i] >> (bit % 32)) & 1) << (i / 2); + + return syndrome; +} + +/* + * Decode data and ecc syndrome to determine what went wrong + * Note: This can only decode single-bit errors + */ +static void sbe_ecc_decode(u32 cap_high, u32 cap_low, u32 cap_ecc, + int *bad_data_bit, int *bad_ecc_bit) +{ + int i; + u8 syndrome; + + *bad_data_bit = -1; + *bad_ecc_bit = -1; + + /* + * Calculate the ECC of the captured data and XOR it with the captured + * ECC to find an ECC syndrome value we can search for + */ + syndrome = calculate_ecc(cap_high, cap_low) ^ cap_ecc; + + /* Check if a data line is stuck... */ + for (i = 0; i < 64; i++) { + if (syndrome == syndrome_from_bit(i)) { + *bad_data_bit = i; + return; + } + } + + /* If data is correct, check ECC bits for errors... */ + for (i = 0; i < 8; i++) { + if ((syndrome >> i) & 0x1) { + *bad_ecc_bit = i; + return; + } + } +} + static void mpc85xx_mc_check(struct mem_ctl_info *mci) { struct mpc85xx_mc_pdata *pdata = mci->pvt_info; struct csrow_info *csrow; + u32 bus_width; u32 err_detect; u32 syndrome; u32 err_addr; u32 pfn; int row_index; + u32 cap_high; + u32 cap_low; + int bad_data_bit; + int bad_ecc_bit; err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT); if (!err_detect) @@ -692,6 +801,15 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) } syndrome = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ECC); + + /* Mask off appropriate bits of syndrome based on bus width */ + bus_width = (in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG) & + DSC_DBW_MASK) ? 32 : 64; + if (bus_width == 64) + syndrome &= 0xff; + else + syndrome &= 0xffff; + err_addr = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ADDRESS); pfn = err_addr >> PAGE_SHIFT; @@ -701,14 +819,35 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) break; } - mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data High: %#8.8x\n", - in_be32(pdata->mc_vbase + - MPC85XX_MC_CAPTURE_DATA_HI)); - mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data Low: %#8.8x\n", - in_be32(pdata->mc_vbase + - MPC85XX_MC_CAPTURE_DATA_LO)); - mpc85xx_mc_printk(mci, KERN_ERR, "syndrome: %#8.8x\n", syndrome); - mpc85xx_mc_printk(mci, KERN_ERR, "err addr: %#8.8x\n", err_addr); + cap_high = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_HI); + cap_low = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_LO); + + /* + * Analyze single-bit errors on 64-bit wide buses + * TODO: Add support for 32-bit wide buses + */ + if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) { + sbe_ecc_decode(cap_high, cap_low, syndrome, + &bad_data_bit, &bad_ecc_bit); + + if (bad_data_bit != -1) + mpc85xx_mc_printk(mci, KERN_ERR, + "Faulty Data bit: %d\n", bad_data_bit); + if (bad_ecc_bit != -1) + mpc85xx_mc_printk(mci, KERN_ERR, + "Faulty ECC bit: %d\n", bad_ecc_bit); + + mpc85xx_mc_printk(mci, KERN_ERR, + "Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n", + cap_high ^ (1 << (bad_data_bit - 32)), + cap_low ^ (1 << bad_data_bit), + syndrome ^ (1 << bad_ecc_bit)); + } + + mpc85xx_mc_printk(mci, KERN_ERR, + "Captured Data / ECC:\t%#8.8x_%08x / %#2.2x\n", + cap_high, cap_low, syndrome); + mpc85xx_mc_printk(mci, KERN_ERR, "Err addr: %#8.8x\n", err_addr); mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn); /* we are out of range */ diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h index 52432ee..cb24df8 100644 --- a/drivers/edac/mpc85xx_edac.h +++ b/drivers/edac/mpc85xx_edac.h @@ -48,6 +48,9 @@ #define DSC_MEM_EN 0x80000000 #define DSC_ECC_EN 0x20000000 #define DSC_RD_EN 0x10000000 +#define DSC_DBW_MASK 0x00180000 +#define DSC_DBW_32 0x00080000 +#define DSC_DBW_64 0x00000000 #define DSC_SDTYPE_MASK 0x07000000 diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 71247da..75bceee7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -3545,7 +3545,7 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b * at which modes should be set up in the dual link style. * * Following the header, the BMP (ver 0xa) table has several records, - * indexed by a seperate xlat table, indexed in turn by the fp strap in + * indexed by a separate xlat table, indexed in turn by the fp strap in * EXTDEV_BOOT. Each record had a config byte, followed by 6 script * numbers for use by INIT_SUB which controlled panel init and power, * and finally a dword of ms to sleep between power off and on diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 5f8d987..4b9aaf2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -553,7 +553,7 @@ struct drm_nouveau_private { uint32_t ramro_offset; uint32_t ramro_size; - /* base physical adresses */ + /* base physical addresses */ uint64_t fb_phys; uint64_t fb_available_size; uint64_t fb_mappable_pages; diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 3c32f84..40ab6d9 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -1093,7 +1093,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* judging by the first tile offset needed, could possibly directly address/clear 4x4 tiles instead of 8x2 * 4x4 macro tiles, though would still need clear mask for - right/bottom if truely 4x4 granularity is desired ? */ + right/bottom if truly 4x4 granularity is desired ? */ OUT_RING(tileoffset * 16); /* the number of tiles to clear */ OUT_RING(nrtilesx + 1); diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c index 5935b88..34079f2 100644 --- a/drivers/gpu/drm/via/via_irq.c +++ b/drivers/gpu/drm/via/via_irq.c @@ -150,7 +150,7 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) cur_irq++; } - /* Acknowlege interrupts */ + /* Acknowledge interrupts */ VIA_WRITE(VIA_REG_INTERRUPT, status); @@ -165,7 +165,7 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv) u32 status; if (dev_priv) { - /* Acknowlege interrupts */ + /* Acknowledge interrupts */ status = VIA_READ(VIA_REG_INTERRUPT); VIA_WRITE(VIA_REG_INTERRUPT, status | dev_priv->irq_pending_mask); diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 79d9edd..7a0d2e4 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -68,22 +68,25 @@ static const struct { #define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ &max, EV_KEY, (c)) -static inline int match_scancode(int code, int scancode) +static inline int match_scancode(unsigned int code, unsigned int scancode) { if (scancode == 0) return 1; - return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode); + + return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode; } -static inline int match_keycode(int code, int keycode) +static inline int match_keycode(unsigned int code, unsigned int keycode) { if (keycode == 0) return 1; - return (code == keycode); + + return code == keycode; } static struct hid_usage *hidinput_find_key(struct hid_device *hid, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { int i, j, k; struct hid_report *report; @@ -105,8 +108,8 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid, return NULL; } -static int hidinput_getkeycode(struct input_dev *dev, int scancode, - int *keycode) +static int hidinput_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct hid_device *hid = input_get_drvdata(dev); struct hid_usage *usage; @@ -119,16 +122,13 @@ static int hidinput_getkeycode(struct input_dev *dev, int scancode, return -EINVAL; } -static int hidinput_setkeycode(struct input_dev *dev, int scancode, - int keycode) +static int hidinput_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct hid_device *hid = input_get_drvdata(dev); struct hid_usage *usage; int old_keycode; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - usage = hidinput_find_key(hid, scancode, 0); if (usage) { old_keycode = usage->code; diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 02ce9cf..d06083f 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -73,7 +73,6 @@ config I2C_SMBUS source drivers/i2c/algos/Kconfig source drivers/i2c/busses/Kconfig -source drivers/i2c/chips/Kconfig config I2C_DEBUG_CORE bool "I2C Core debugging messages" @@ -98,12 +97,4 @@ config I2C_DEBUG_BUS a problem with I2C support and want to see more of what is going on. -config I2C_DEBUG_CHIP - bool "I2C Chip debugging messages" - help - Say Y here if you want the I2C chip drivers to produce a bunch of - debug messages to the system log. Select this if you are having - a problem with I2C support and want to see more of what is going - on. - endif # I2C diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index acd0250..a7d9b4b 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -6,7 +6,7 @@ obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o obj-$(CONFIG_I2C) += i2c-core.o obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o -obj-y += busses/ chips/ algos/ +obj-y += algos/ busses/ ifeq ($(CONFIG_I2C_DEBUG_CORE),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index e25e139..e8d568c 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -522,6 +522,12 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, int i, ret; unsigned short nak_ok; + if (adap->pre_xfer) { + ret = adap->pre_xfer(i2c_adap); + if (ret < 0) + return ret; + } + bit_dbg(3, &i2c_adap->dev, "emitting start condition\n"); i2c_start(adap); for (i = 0; i < num; i++) { @@ -570,6 +576,9 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, bailout: bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n"); i2c_stop(adap); + + if (adap->post_xfer) + adap->post_xfer(i2c_adap); return ret; } diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 7ce7577..6b6bd06 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -176,7 +176,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) */ if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) { DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp)); - return -ENXIO; /* definetly not PCF8584 */ + return -ENXIO; /* definitely not PCF8584 */ } /* load own address in S0, effective address is (own << 1) */ diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 9da5b05..299b918 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -416,9 +416,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, data->block[0] = 32; /* max for SMBus block reads */ } + /* Experience has shown that the block buffer can only be used for + SMBus (not I2C) block transactions, even though the datasheet + doesn't mention this limitation. */ if ((i801_features & FEATURE_BLOCK_BUFFER) - && !(command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_READ) + && command != I2C_SMBUS_I2C_BLOCK_DATA && i801_set_block_buffer_mode() == 0) result = i801_block_transaction_by_block(data, read_write, hwpec); diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 1c440a7..b289ec9 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -122,9 +122,14 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len); if (rc) { - dev_err(&adap->dev, - "I2C transfer at 0x%02x failed, size %d, err %d\n", - addrdir >> 1, size, rc); + if (rc == -ENXIO) + dev_dbg(&adap->dev, + "I2C transfer at 0x%02x failed, size %d, " + "err %d\n", addrdir >> 1, size, rc); + else + dev_err(&adap->dev, + "I2C transfer at 0x%02x failed, size %d, " + "err %d\n", addrdir >> 1, size, rc); goto bail; } @@ -175,10 +180,16 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap, goto bail; } rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len); - if (rc < 0) - dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n", - addrdir & 1 ? "read from" : "write to", addrdir >> 1, - rc); + if (rc < 0) { + if (rc == -ENXIO) + dev_dbg(&adap->dev, "I2C %s 0x%02x failed, err %d\n", + addrdir & 1 ? "read from" : "write to", + addrdir >> 1, rc); + else + dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n", + addrdir & 1 ? "read from" : "write to", + addrdir >> 1, rc); + } bail: pmac_i2c_close(bus); return rc < 0 ? rc : 1; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 7647a20..90ffbf6 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -12,7 +12,7 @@ * * History: * Apr 2002: Initial version [CS] - * Jun 2002: Properly seperated algo/adap [FB] + * Jun 2002: Properly separated algo/adap [FB] * Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem] * Jan 2003: added limited signal handling [Kai-Uwe Bloem] * Sep 2004: Major rework to ensure efficient bus handling [RMK] diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index eece39a..f0ef8da 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -32,6 +32,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/errno.h> +#include <linux/delay.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/interrupt.h> diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig deleted file mode 100644 index ae4539d..0000000 --- a/drivers/i2c/chips/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -# -# Miscellaneous I2C chip drivers configuration -# -# *** DEPRECATED! Do not add new entries! See Makefile *** -# - -menu "Miscellaneous I2C Chip support" - -config SENSORS_TSL2550 - tristate "Taos TSL2550 ambient light sensor" - depends on EXPERIMENTAL - help - If you say yes here you get support for the Taos TSL2550 - ambient light sensor. - - This driver can also be built as a module. If so, the module - will be called tsl2550. - -endmenu diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile deleted file mode 100644 index fe0af0f..0000000 --- a/drivers/i2c/chips/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# -# Makefile for miscellaneous I2C chip drivers. -# -# Do not add new drivers to this directory! It is DEPRECATED. -# -# Device drivers are better grouped according to the functionality they -# implement rather than to the bus they are connected to. In particular: -# * Hardware monitoring chip drivers go to drivers/hwmon -# * RTC chip drivers go to drivers/rtc -# * I/O expander drivers go to drivers/gpio -# - -obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o - -ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) -EXTRA_CFLAGS += -DDEBUG -endif - diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 4212782..7a8201e 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -22,7 +22,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/device.h> -#include <linux/semaphore.h> #include <linux/interrupt.h> #include <linux/workqueue.h> #include <linux/i2c.h> @@ -55,7 +54,7 @@ static int smbus_do_alert(struct device *dev, void *addrp) * Drivers should either disable alerts, or provide at least * a minimal handler. Lock so client->driver won't change. */ - down(&dev->sem); + device_lock(dev); if (client->driver) { if (client->driver->alert) client->driver->alert(client, data->flag); @@ -63,7 +62,7 @@ static int smbus_do_alert(struct device *dev, void *addrp) dev_warn(&client->dev, "no driver alert()!\n"); } else dev_dbg(&client->dev, "alert with no driver\n"); - up(&dev->sem); + device_unlock(dev); /* Stop iterating after we find the device */ return -EBUSY; diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index 9555fd2..bf47fee 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c @@ -1452,7 +1452,7 @@ static int __devinit add_card(struct pci_dev *dev, PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c"); } else { PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom"); - /* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a), + /* FIXME: probably we should rewrite the max_rec, max_ROM(1394a), * generation(1394a) and link_spd(1394a) field and recalculate * the CRC */ diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 58463da..e351b15 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -2953,6 +2953,9 @@ static void ib_mad_remove_device(struct ib_device *device) { int i, num_ports, cur_port; + if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) + return; + if (device->node_type == RDMA_NODE_IB_SWITCH) { num_ports = 1; cur_port = 0; diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c index ee1d8b4..63f975f 100644 --- a/drivers/infiniband/hw/cxgb3/iwch.c +++ b/drivers/infiniband/hw/cxgb3/iwch.c @@ -189,6 +189,7 @@ static void close_rnic_dev(struct t3cdev *tdev) list_for_each_entry_safe(dev, tmp, &dev_list, entry) { if (dev->rdev.t3cdev_p == tdev) { dev->rdev.flags = CXIO_ERROR_FATAL; + synchronize_net(); cancel_delayed_work_sync(&dev->db_drop_task); list_del(&dev->entry); iwch_unregister_device(dev); @@ -217,6 +218,7 @@ static void iwch_event_handler(struct t3cdev *tdev, u32 evt, u32 port_id) switch (evt) { case OFFLOAD_STATUS_DOWN: { rdev->flags = CXIO_ERROR_FATAL; + synchronize_net(); event.event = IB_EVENT_DEVICE_FATAL; dispatch = 1; break; diff --git a/drivers/infiniband/hw/ehca/ehca_qes.h b/drivers/infiniband/hw/ehca/ehca_qes.h index 5d28e3e..90c4efa 100644 --- a/drivers/infiniband/hw/ehca/ehca_qes.h +++ b/drivers/infiniband/hw/ehca/ehca_qes.h @@ -46,7 +46,7 @@ #include "ehca_tools.h" -/* virtual scatter gather entry to specify remote adresses with length */ +/* virtual scatter gather entry to specify remote addresses with length */ struct ehca_vsgentry { u64 vaddr; u32 lkey; @@ -148,7 +148,7 @@ struct ehca_wqe { u32 immediate_data; union { struct { - u64 remote_virtual_adress; + u64 remote_virtual_address; u32 rkey; u32 reserved; u64 atomic_1st_op_dma_len; diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index e3ec7fd..9a3fbfc 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c @@ -269,7 +269,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp, /* no break is intentional here */ case IB_QPT_RC: /* TODO: atomic not implemented */ - wqe_p->u.nud.remote_virtual_adress = + wqe_p->u.nud.remote_virtual_address = send_wr->wr.rdma.remote_addr; wqe_p->u.nud.rkey = send_wr->wr.rdma.rkey; diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index ce7f538..9250755 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -1899,9 +1899,14 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic) u16 wqe_fragment_index; u64 wqe_frag; u32 cqp_head; + u32 wqm_cfg0; unsigned long flags; int ret; + /* clear wqe stall before destroying NIC QP */ + wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0); + nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF); + /* Free remaining NIC receive buffers */ while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) { nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail]; @@ -2020,6 +2025,9 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic) pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase, nesvnic->nic_pbase); + + /* restore old wqm_cfg0 value */ + nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0); } /** diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 9b1e7f8..bbbfe9f 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -160,6 +160,7 @@ enum indexed_regs { NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI = 0x7004, NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO = 0x7008, NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI = 0x700c, + NES_IDX_WQM_CONFIG0 = 0x5000, NES_IDX_WQM_CONFIG1 = 0x5004, NES_IDX_CM_CONFIG = 0x5100, NES_IDX_NIC_LOGPORT_TO_PHYPORT = 0x6000, diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index a1d79b6..91fdde3 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1595,7 +1595,6 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, struct nes_vnic *nesvnic; struct net_device *netdev; struct nic_qp_map *curr_qp_map; - u32 u32temp; u8 phy_type = nesdev->nesadapter->phy_type[nesdev->mac_index]; netdev = alloc_etherdev(sizeof(struct nes_vnic)); @@ -1707,6 +1706,10 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, ((phy_type == NES_PHY_TYPE_PUMA_1G) && (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) || ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) { + u32 u32temp; + u32 link_mask; + u32 link_val; + u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + (0x200 * (nesdev->mac_index & 1))); if (phy_type != NES_PHY_TYPE_PUMA_1G) { @@ -1715,13 +1718,36 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, (0x200 * (nesdev->mac_index & 1)), u32temp); } + /* Check and set linkup here. This is for back to back */ + /* configuration where second port won't get link interrupt */ + switch (phy_type) { + case NES_PHY_TYPE_PUMA_1G: + if (nesdev->mac_index < 2) { + link_mask = 0x01010000; + link_val = 0x01010000; + } else { + link_mask = 0x02020000; + link_val = 0x02020000; + } + break; + default: + link_mask = 0x0f1f0000; + link_val = 0x0f0f0000; + break; + } + + u32temp = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0 + + (0x200 * (nesdev->mac_index & 1))); + if ((u32temp & link_mask) == link_val) + nesvnic->linkup = 1; + /* clear the MAC interrupt status, assumes direct logical to physical mapping */ u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index)); nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp); nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp); nes_init_phy(nesdev); - } return netdev; diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 815725f..6992829 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1323,6 +1323,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, nesqp->nesqp_context->aeq_token_low = cpu_to_le32((u32)((unsigned long)(nesqp))); nesqp->nesqp_context->aeq_token_high = cpu_to_le32((u32)(upper_32_bits((unsigned long)(nesqp)))); nesqp->nesqp_context->ird_ord_sizes = cpu_to_le32(NES_QPCONTEXT_ORDIRD_ALSMM | + NES_QPCONTEXT_ORDIRD_AAH | ((((u32)nesadapter->max_irrq_wr) << NES_QPCONTEXT_ORDIRD_IRDSIZE_SHIFT) & NES_QPCONTEXT_ORDIRD_IRDSIZE_MASK)); if (disable_mpa_crc) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 83a7751..bc65837 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -708,6 +708,7 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_cm_tx_buf *tx_req; u64 addr; + int rc; if (unlikely(skb->len > tx->mtu)) { ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n", @@ -739,9 +740,10 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ tx_req->mapping = addr; - if (unlikely(post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), - addr, skb->len))) { - ipoib_warn(priv, "post_send failed\n"); + rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), + addr, skb->len); + if (unlikely(rc)) { + ipoib_warn(priv, "post_send failed, error %d\n", rc); ++dev->stats.tx_errors; ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); @@ -752,6 +754,8 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ if (++priv->tx_outstanding == ipoib_sendq_size) { ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", tx->qp->qp_num); + if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP)) + ipoib_warn(priv, "request notify on send CQ failed\n"); netif_stop_queue(dev); } } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 8c91d9f..5df40b1 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -529,7 +529,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_tx_buf *tx_req; - int hlen; + int hlen, rc; void *phead; if (skb_is_gso(skb)) { @@ -585,9 +585,10 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, netif_stop_queue(dev); } - if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), - address->ah, qpn, tx_req, phead, hlen))) { - ipoib_warn(priv, "post_send failed\n"); + rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), + address->ah, qpn, tx_req, phead, hlen); + if (unlikely(rc)) { + ipoib_warn(priv, "post_send failed, error %d\n", rc); ++dev->stats.tx_errors; --priv->tx_outstanding; ipoib_dma_unmap_tx(priv->ca, tx_req); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 9f9816b..2ee6c7a 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -515,7 +515,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, struct input_absinfo abs; struct ff_effect effect; int __user *ip = (int __user *)p; - int i, t, u, v; + unsigned int i, t, u, v; int error; switch (cmd) { diff --git a/drivers/input/input.c b/drivers/input/input.c index 41168d5..e2aad0a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -582,7 +582,8 @@ static int input_fetch_keycode(struct input_dev *dev, int scancode) } static int input_default_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, + unsigned int *keycode) { if (!dev->keycodesize) return -EINVAL; @@ -596,7 +597,8 @@ static int input_default_getkeycode(struct input_dev *dev, } static int input_default_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { int old_keycode; int i; @@ -654,11 +656,9 @@ static int input_default_setkeycode(struct input_dev *dev, * This function should be called by anyone interested in retrieving current * keymap. Presently keyboard and evdev handlers use it. */ -int input_get_keycode(struct input_dev *dev, int scancode, int *keycode) +int input_get_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { - if (scancode < 0) - return -EINVAL; - return dev->getkeycode(dev, scancode, keycode); } EXPORT_SYMBOL(input_get_keycode); @@ -672,16 +672,14 @@ EXPORT_SYMBOL(input_get_keycode); * This function should be called by anyone needing to update current * keymap. Presently keyboard and evdev handlers use it. */ -int input_set_keycode(struct input_dev *dev, int scancode, int keycode) +int input_set_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { unsigned long flags; int old_keycode; int retval; - if (scancode < 0) - return -EINVAL; - - if (keycode < 0 || keycode > KEY_MAX) + if (keycode > KEY_MAX) return -EINVAL; spin_lock_irqsave(&dev->event_lock, flags); @@ -1881,35 +1879,37 @@ static int input_open_file(struct inode *inode, struct file *file) const struct file_operations *old_fops, *new_fops = NULL; int err; - lock_kernel(); + err = mutex_lock_interruptible(&input_mutex); + if (err) + return err; + /* No load-on-demand here? */ handler = input_table[iminor(inode) >> 5]; - if (!handler || !(new_fops = fops_get(handler->fops))) { - err = -ENODEV; - goto out; - } + if (handler) + new_fops = fops_get(handler->fops); + + mutex_unlock(&input_mutex); /* * That's _really_ odd. Usually NULL ->open means "nothing special", * not "no device". Oh, well... */ - if (!new_fops->open) { + if (!new_fops || !new_fops->open) { fops_put(new_fops); err = -ENODEV; goto out; } + old_fops = file->f_op; file->f_op = new_fops; err = new_fops->open(inode, file); - if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); } fops_put(old_fops); out: - unlock_kernel(); return err; } diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index ae998d9..7a55714 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -819,7 +819,7 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) int i; int err; - if (pad_type < 1 || pad_type > GC_MAX) { + if (pad_type < 1 || pad_type >= GC_MAX) { pr_err("Pad type %d unknown\n", pad_type); return -EINVAL; } diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index fe376a2..593c052 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -162,7 +162,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) input_sync(input); if (bfin_kpad_get_keypressed(bf54x_kpad)) { - disable_irq(bf54x_kpad->irq); + disable_irq_nosync(bf54x_kpad->irq); bf54x_kpad->lastkey = key; mod_timer(&bf54x_kpad->timer, jiffies + bf54x_kpad->keyup_test_jiffies); diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index 9caed30..b1ab298 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -192,11 +192,18 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd) static irqreturn_t locomokbd_interrupt(int irq, void *dev_id) { struct locomokbd *locomokbd = dev_id; + u16 r; + + r = locomo_readl(locomokbd->base + LOCOMO_KIC); + if ((r & 0x0001) == 0) + return IRQ_HANDLED; + + locomo_writel(r & ~0x0100, locomokbd->base + LOCOMO_KIC); /* Ack */ + /** wait chattering delay **/ udelay(100); locomokbd_scankeyboard(locomokbd); - return IRQ_HANDLED; } @@ -210,6 +217,25 @@ static void locomokbd_timer_callback(unsigned long data) locomokbd_scankeyboard(locomokbd); } +static int locomokbd_open(struct input_dev *dev) +{ + struct locomokbd *locomokbd = input_get_drvdata(dev); + u16 r; + + r = locomo_readl(locomokbd->base + LOCOMO_KIC) | 0x0010; + locomo_writel(r, locomokbd->base + LOCOMO_KIC); + return 0; +} + +static void locomokbd_close(struct input_dev *dev) +{ + struct locomokbd *locomokbd = input_get_drvdata(dev); + u16 r; + + r = locomo_readl(locomokbd->base + LOCOMO_KIC) & ~0x0010; + locomo_writel(r, locomokbd->base + LOCOMO_KIC); +} + static int __devinit locomokbd_probe(struct locomo_dev *dev) { struct locomokbd *locomokbd; @@ -253,6 +279,8 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev) input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; + input_dev->open = locomokbd_open; + input_dev->close = locomokbd_close; input_dev->dev.parent = &dev->dev; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | @@ -261,6 +289,8 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev) input_dev->keycodesize = sizeof(locomokbd_keycode[0]); input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode); + input_set_drvdata(input_dev, locomokbd); + memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode)); for (i = 0; i < LOCOMOKBD_NUMKEYS; i++) set_bit(locomokbd->keycode[i], input_dev->keybit); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7097bfe..23140a3 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -214,6 +214,17 @@ config INPUT_TWL4030_PWRBUTTON To compile this driver as a module, choose M here. The module will be called twl4030_pwrbutton. +config INPUT_TWL4030_VIBRA + tristate "Support for TWL4030 Vibrator" + depends on TWL4030_CORE + select TWL4030_CODEC + select INPUT_FF_MEMLESS + help + This option enables support for TWL4030 Vibrator Driver. + + To compile this driver as a module, choose M here. The module will + be called twl4030_vibra. + config INPUT_UINPUT tristate "User level driver support" help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index b611615..7e95a5d 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o +obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 0501f0e..15be543 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -474,10 +474,11 @@ static void ati_remote2_complete_key(struct urb *urb) } static int ati_remote2_getkeycode(struct input_dev *idev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { struct ati_remote2 *ar2 = input_get_drvdata(idev); - int index, mode; + unsigned int mode; + int index; mode = scancode >> 8; if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) @@ -491,10 +492,12 @@ static int ati_remote2_getkeycode(struct input_dev *idev, return 0; } -static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode) +static int ati_remote2_setkeycode(struct input_dev *idev, + unsigned int scancode, unsigned int keycode) { struct ati_remote2 *ar2 = input_get_drvdata(idev); - int index, mode, old_keycode; + unsigned int mode, old_keycode; + int index; mode = scancode >> 8; if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) @@ -504,9 +507,6 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc if (index < 0) return -EINVAL; - if (keycode < KEY_RESERVED || keycode > KEY_MAX) - return -EINVAL; - old_keycode = ar2->keycode[mode][index]; ar2->keycode[mode][index] = keycode; __set_bit(keycode, idev->keybit); diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c new file mode 100644 index 0000000..2fb79e0 --- /dev/null +++ b/drivers/input/misc/twl4030-vibra.c @@ -0,0 +1,297 @@ +/* + * twl4030-vibra.c - TWL4030 Vibrator driver + * + * Copyright (C) 2008-2010 Nokia Corporation + * + * Written by Henrik Saari <henrik.saari@nokia.com> + * Updates by Felipe Balbi <felipe.balbi@nokia.com> + * Input by Jari Vanhala <ext-jari.vanhala@nokia.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/module.h> +#include <linux/jiffies.h> +#include <linux/platform_device.h> +#include <linux/workqueue.h> +#include <linux/i2c/twl.h> +#include <linux/mfd/twl4030-codec.h> +#include <linux/input.h> + +/* MODULE ID2 */ +#define LEDEN 0x00 + +/* ForceFeedback */ +#define EFFECT_DIR_180_DEG 0x8000 /* range is 0 - 0xFFFF */ + +struct vibra_info { + struct device *dev; + struct input_dev *input_dev; + + struct workqueue_struct *workqueue; + struct work_struct play_work; + + bool enabled; + int speed; + int direction; + + bool coexist; +}; + +static void vibra_disable_leds(void) +{ + u8 reg; + + /* Disable LEDA & LEDB, cannot be used with vibra (PWM) */ + twl_i2c_read_u8(TWL4030_MODULE_LED, ®, LEDEN); + reg &= ~0x03; + twl_i2c_write_u8(TWL4030_MODULE_LED, LEDEN, reg); +} + +/* Powers H-Bridge and enables audio clk */ +static void vibra_enable(struct vibra_info *info) +{ + u8 reg; + + twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER); + + /* turn H-Bridge on */ + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); + + twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL); + + info->enabled = true; +} + +static void vibra_disable(struct vibra_info *info) +{ + u8 reg; + + /* Power down H-Bridge */ + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); + + twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); + twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); + + info->enabled = false; +} + +static void vibra_play_work(struct work_struct *work) +{ + struct vibra_info *info = container_of(work, + struct vibra_info, play_work); + int dir; + int pwm; + u8 reg; + + dir = info->direction; + pwm = info->speed; + + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + if (pwm && (!info->coexist || !(reg & TWL4030_VIBRA_SEL))) { + + if (!info->enabled) + vibra_enable(info); + + /* set vibra rotation direction */ + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + reg = (dir) ? (reg | TWL4030_VIBRA_DIR) : + (reg & ~TWL4030_VIBRA_DIR); + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg, TWL4030_REG_VIBRA_CTL); + + /* set PWM, 1 = max, 255 = min */ + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + 256 - pwm, TWL4030_REG_VIBRA_SET); + } else { + if (info->enabled) + vibra_disable(info); + } +} + +/*** Input/ForceFeedback ***/ + +static int vibra_play(struct input_dev *input, void *data, + struct ff_effect *effect) +{ + struct vibra_info *info = input_get_drvdata(input); + + info->speed = effect->u.rumble.strong_magnitude >> 8; + if (!info->speed) + info->speed = effect->u.rumble.weak_magnitude >> 9; + info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1; + queue_work(info->workqueue, &info->play_work); + return 0; +} + +static int twl4030_vibra_open(struct input_dev *input) +{ + struct vibra_info *info = input_get_drvdata(input); + + info->workqueue = create_singlethread_workqueue("vibra"); + if (info->workqueue == NULL) { + dev_err(&input->dev, "couldn't create workqueue\n"); + return -ENOMEM; + } + return 0; +} + +static void twl4030_vibra_close(struct input_dev *input) +{ + struct vibra_info *info = input_get_drvdata(input); + + cancel_work_sync(&info->play_work); + INIT_WORK(&info->play_work, vibra_play_work); /* cleanup */ + destroy_workqueue(info->workqueue); + info->workqueue = NULL; + + if (info->enabled) + vibra_disable(info); +} + +/*** Module ***/ +#if CONFIG_PM +static int twl4030_vibra_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct vibra_info *info = platform_get_drvdata(pdev); + + if (info->enabled) + vibra_disable(info); + + return 0; +} + +static int twl4030_vibra_resume(struct device *dev) +{ + vibra_disable_leds(); + return 0; +} + +static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, + twl4030_vibra_suspend, twl4030_vibra_resume); +#endif + +static int __devinit twl4030_vibra_probe(struct platform_device *pdev) +{ + struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; + struct vibra_info *info; + int ret; + + if (!pdata) { + dev_dbg(&pdev->dev, "platform_data not available\n"); + return -EINVAL; + } + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->dev = &pdev->dev; + info->coexist = pdata->coexist; + INIT_WORK(&info->play_work, vibra_play_work); + + info->input_dev = input_allocate_device(); + if (info->input_dev == NULL) { + dev_err(&pdev->dev, "couldn't allocate input device\n"); + ret = -ENOMEM; + goto err_kzalloc; + } + + input_set_drvdata(info->input_dev, info); + + info->input_dev->name = "twl4030:vibrator"; + info->input_dev->id.version = 1; + info->input_dev->dev.parent = pdev->dev.parent; + info->input_dev->open = twl4030_vibra_open; + info->input_dev->close = twl4030_vibra_close; + __set_bit(FF_RUMBLE, info->input_dev->ffbit); + + ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); + if (ret < 0) { + dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n"); + goto err_ialloc; + } + + ret = input_register_device(info->input_dev); + if (ret < 0) { + dev_dbg(&pdev->dev, "couldn't register input device\n"); + goto err_iff; + } + + vibra_disable_leds(); + + platform_set_drvdata(pdev, info); + return 0; + +err_iff: + input_ff_destroy(info->input_dev); +err_ialloc: + input_free_device(info->input_dev); +err_kzalloc: + kfree(info); + return ret; +} + +static int __devexit twl4030_vibra_remove(struct platform_device *pdev) +{ + struct vibra_info *info = platform_get_drvdata(pdev); + + /* this also free ff-memless and calls close if needed */ + input_unregister_device(info->input_dev); + kfree(info); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver twl4030_vibra_driver = { + .probe = twl4030_vibra_probe, + .remove = __devexit_p(twl4030_vibra_remove), + .driver = { + .name = "twl4030_codec_vibra", + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &twl4030_vibra_pm_ops, +#endif + }, +}; + +static int __init twl4030_vibra_init(void) +{ + return platform_driver_register(&twl4030_vibra_driver); +} +module_init(twl4030_vibra_init); + +static void __exit twl4030_vibra_exit(void) +{ + platform_driver_unregister(&twl4030_vibra_driver); +} +module_exit(twl4030_vibra_exit); + +MODULE_ALIAS("platform:twl4030_codec_vibra"); + +MODULE_DESCRIPTION("TWL4030 Vibra driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nokia Corporation"); diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c index cbec3df..9c155a4 100644 --- a/drivers/input/misc/winbond-cir.c +++ b/drivers/input/misc/winbond-cir.c @@ -385,26 +385,24 @@ wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode) } static int -wbcir_getkeycode(struct input_dev *dev, int scancode, int *keycode) +wbcir_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct wbcir_data *data = input_get_drvdata(dev); - *keycode = (int)wbcir_do_getkeycode(data, (u32)scancode); + *keycode = wbcir_do_getkeycode(data, scancode); return 0; } static int -wbcir_setkeycode(struct input_dev *dev, int sscancode, int keycode) +wbcir_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct wbcir_data *data = input_get_drvdata(dev); struct wbcir_keyentry *keyentry; struct wbcir_keyentry *new_keyentry; unsigned long flags; unsigned int old_keycode = KEY_RESERVED; - u32 scancode = (u32)sscancode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); if (!new_keyentry) diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index ba4f5dd..1e54bce 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -97,8 +97,9 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) wm831x_on->dev->phys = "wm831x_on/input0"; wm831x_on->dev->dev.parent = &pdev->dev; - ret = wm831x_request_irq(wm831x, irq, wm831x_on_irq, - IRQF_TRIGGER_RISING, "wm831x_on", wm831x_on); + ret = request_threaded_irq(irq, NULL, wm831x_on_irq, + IRQF_TRIGGER_RISING, "wm831x_on", + wm831x_on); if (ret < 0) { dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret); goto err_input_dev; @@ -114,7 +115,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) return 0; err_irq: - wm831x_free_irq(wm831x, irq, NULL); + free_irq(irq, wm831x_on); err_input_dev: input_free_device(wm831x_on->dev); err: @@ -127,7 +128,7 @@ static int __devexit wm831x_on_remove(struct platform_device *pdev) struct wm831x_on *wm831x_on = platform_get_drvdata(pdev); int irq = platform_get_irq(pdev, 0); - wm831x_free_irq(wm831x_on->wm831x, irq, wm831x_on); + free_irq(irq, wm831x_on); cancel_delayed_work_sync(&wm831x_on->work); input_unregister_device(wm831x_on->dev); kfree(wm831x_on); diff --git a/drivers/input/misc/yealink.h b/drivers/input/misc/yealink.h index 48af0be..1e0f523 100644 --- a/drivers/input/misc/yealink.h +++ b/drivers/input/misc/yealink.h @@ -127,7 +127,7 @@ struct yld_ctl_packet { * yld_status struct. */ -/* LCD, each segment must be driven seperately. +/* LCD, each segment must be driven separately. * * Layout: * diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index f93c2c0..7490f1d 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -63,6 +63,8 @@ static const struct alps_model_info alps_model_data[] = { { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ + { { 0x52, 0x01, 0x14 }, 0xff, 0xff, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ }; /* @@ -118,40 +120,27 @@ static void alps_report_buttons(struct psmouse *psmouse, struct input_dev *dev1, struct input_dev *dev2, int left, int right, int middle) { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - if (model->flags & ALPS_PS2_INTERLEAVED) { - struct input_dev *dev; + struct input_dev *dev; - /* - * If shared button has already been reported on the - * other device (dev2) then this event should be also - * sent through that device. - */ - dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_LEFT, left); + /* + * If shared button has already been reported on the + * other device (dev2) then this event should be also + * sent through that device. + */ + dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_LEFT, left); - dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_RIGHT, right); + dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_RIGHT, right); - dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_MIDDLE, middle); + dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_MIDDLE, middle); - /* - * Sync the _other_ device now, we'll do the first - * device later once we report the rest of the events. - */ - input_sync(dev2); - } else { - /* - * For devices with non-interleaved packets we know what - * device buttons belong to so we can simply report them. - */ - input_report_key(dev1, BTN_LEFT, left); - input_report_key(dev1, BTN_RIGHT, right); - input_report_key(dev1, BTN_MIDDLE, middle); - } + /* + * Sync the _other_ device now, we'll do the first + * device later once we report the rest of the events. + */ + input_sync(dev2); } static void alps_process_packet(struct psmouse *psmouse) diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 908b5b4..53ec7dd 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -205,8 +205,8 @@ struct atp { bool overflow_warned; int x_old; /* last reported x/y, */ int y_old; /* used for smoothing */ - signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; - signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; + u8 xy_cur[ATP_XSENSORS + ATP_YSENSORS]; + u8 xy_old[ATP_XSENSORS + ATP_YSENSORS]; int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; int idlecount; /* number of empty packets */ struct work_struct work; @@ -531,7 +531,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { /* accumulate the change */ - signed char change = dev->xy_old[i] - dev->xy_cur[i]; + int change = dev->xy_old[i] - dev->xy_cur[i]; dev->xy_acc[i] -= change; /* prevent down drifting */ diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index a13d80f..f34b22b 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -15,7 +15,6 @@ #include <linux/sched.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/poll.h> #include <linux/module.h> #include <linux/init.h> @@ -542,10 +541,8 @@ static int mousedev_open(struct inode *inode, struct file *file) if (i >= MOUSEDEV_MINORS) return -ENODEV; - lock_kernel(); error = mutex_lock_interruptible(&mousedev_table_mutex); if (error) { - unlock_kernel(); return error; } mousedev = mousedev_table[i]; @@ -554,7 +551,6 @@ static int mousedev_open(struct inode *inode, struct file *file) mutex_unlock(&mousedev_table_mutex); if (!mousedev) { - unlock_kernel(); return -ENODEV; } @@ -575,7 +571,6 @@ static int mousedev_open(struct inode *inode, struct file *file) goto err_free_client; file->private_data = client; - unlock_kernel(); return 0; err_free_client: @@ -583,7 +578,6 @@ static int mousedev_open(struct inode *inode, struct file *file) kfree(client); err_put_mousedev: put_device(&mousedev->dev); - unlock_kernel(); return error; } diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2a5982e..ead0494 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -442,6 +442,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { }, }, { + /* Medion Akoya E1222 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_PRODUCT_NAME, "E122X"), + }, + }, + { /* Mivvy M310 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), @@ -624,6 +631,9 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id * strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name)); } + /* Keyboard ports are always supposed to be wakeup-enabled */ + device_set_wakeup_enable(&dev->dev, true); + i8042_pnp_kbd_devices++; return 0; } diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index b54aee7..9302ba0 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -430,7 +430,7 @@ static bool i8042_filter(unsigned char data, unsigned char str, } if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) { - dbg("Filtered out by platfrom filter\n"); + dbg("Filtered out by platform filter\n"); return true; } @@ -1386,6 +1386,8 @@ static int __init i8042_probe(struct platform_device *dev) { int error; + i8042_platform_device = dev; + error = i8042_controller_selftest(); if (error) return error; @@ -1421,6 +1423,7 @@ static int __init i8042_probe(struct platform_device *dev) i8042_free_aux_ports(); /* in case KBD failed but AUX not */ i8042_free_irqs(); i8042_controller_reset(); + i8042_platform_device = NULL; return error; } @@ -1430,6 +1433,7 @@ static int __devexit i8042_remove(struct platform_device *dev) i8042_unregister_ports(); i8042_free_irqs(); i8042_controller_reset(); + i8042_platform_device = NULL; return 0; } @@ -1448,6 +1452,7 @@ static struct platform_driver i8042_driver = { static int __init i8042_init(void) { + struct platform_device *pdev; int err; dbg_init(); @@ -1460,31 +1465,18 @@ static int __init i8042_init(void) if (err) goto err_platform_exit; - i8042_platform_device = platform_device_alloc("i8042", -1); - if (!i8042_platform_device) { - err = -ENOMEM; + pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); + if (IS_ERR(pdev)) { + err = PTR_ERR(pdev); goto err_platform_exit; } - err = platform_device_add(i8042_platform_device); - if (err) - goto err_free_device; - - err = platform_driver_probe(&i8042_driver, i8042_probe); - if (err) - goto err_del_device; - panic_blink = i8042_panic_blink; return 0; - err_del_device: - platform_device_del(i8042_platform_device); - err_free_device: - platform_device_put(i8042_platform_device); err_platform_exit: i8042_platform_exit(); - return err; } diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 27fdaaf..9986648 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -81,12 +81,12 @@ static int serio_raw_open(struct inode *inode, struct file *file) struct serio_raw_list *list; int retval = 0; - lock_kernel(); retval = mutex_lock_interruptible(&serio_raw_mutex); if (retval) - goto out_bkl; + return retval; - if (!(serio_raw = serio_raw_locate(iminor(inode)))) { + serio_raw = serio_raw_locate(iminor(inode)); + if (!serio_raw) { retval = -ENODEV; goto out; } @@ -96,7 +96,8 @@ static int serio_raw_open(struct inode *inode, struct file *file) goto out; } - if (!(list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) { + list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL); + if (!list) { retval = -ENOMEM; goto out; } @@ -109,8 +110,6 @@ static int serio_raw_open(struct inode *inode, struct file *file) out: mutex_unlock(&serio_raw_mutex); -out_bkl: - unlock_kernel(); return retval; } diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index fbd3987..e6bde55 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -64,7 +64,8 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev, EXPORT_SYMBOL(sparse_keymap_entry_from_keycode); static int sparse_keymap_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, + unsigned int *keycode) { const struct key_entry *key = sparse_keymap_entry_from_scancode(dev, scancode); @@ -78,7 +79,8 @@ static int sparse_keymap_getkeycode(struct input_dev *dev, } static int sparse_keymap_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { struct key_entry *key; int old_keycode; diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 7d005a3..4be039d 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -362,7 +362,7 @@ static const int macroKeyEvents[] = { }; /*********************************************************************** - * Map values to strings and back. Every map shoudl have the following + * Map values to strings and back. Every map should have the following * as its last element: { NULL, AIPTEK_INVALID_VALUE }. */ #define AIPTEK_INVALID_VALUE -1 diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index a1770e6..8b5d287 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -371,7 +371,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi } else if (pen) { /* penabled only accepts exact bytes of data */ if (features->type == TABLETPC2FG) - features->pktlen = WACOM_PKGLEN_PENABLED; + features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->x_max = wacom_le16_to_cpu(&report[i + 3]); @@ -410,7 +410,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi } else if (pen) { /* penabled only accepts exact bytes of data */ if (features->type == TABLETPC2FG) - features->pktlen = WACOM_PKGLEN_PENABLED; + features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->y_max = wacom_le16_to_cpu(&report[i + 3]); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 3d81443..b3ba343 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -155,19 +155,19 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; - int x, y, rw; - static int penData = 0; + int x, y, prox; + int rw = 0; + int retval = 0; if (data[0] != WACOM_REPORT_PENABLED) { dbg("wacom_graphire_irq: received unknown report #%d", data[0]); - return 0; + goto exit; } - if (data[1] & 0x80) { - /* in prox and not a pad data */ - penData = 1; - - switch ((data[1] >> 5) & 3) { + prox = data[1] & 0x80; + if (prox || wacom->id[0]) { + if (prox) { + switch ((data[1] >> 5) & 3) { case 0: /* Pen */ wacom->tool[0] = BTN_TOOL_PEN; @@ -181,23 +181,13 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) case 2: /* Mouse with wheel */ wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); - if (features->type == WACOM_G4 || features->type == WACOM_MO) { - rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); - wacom_report_rel(wcombo, REL_WHEEL, -rw); - } else - wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); /* fall through */ case 3: /* Mouse without wheel */ wacom->tool[0] = BTN_TOOL_MOUSE; wacom->id[0] = CURSOR_DEVICE_ID; - wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); - wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); - if (features->type == WACOM_G4 || features->type == WACOM_MO) - wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); - else - wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); break; + } } x = wacom_le16_to_cpu(&data[2]); y = wacom_le16_to_cpu(&data[4]); @@ -208,36 +198,32 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); - } - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ - wacom_report_key(wcombo, wacom->tool[0], 1); - } else if (wacom->id[0]) { - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - if (wacom->tool[0] == BTN_TOOL_MOUSE) { - wacom_report_key(wcombo, BTN_LEFT, 0); - wacom_report_key(wcombo, BTN_RIGHT, 0); - wacom_report_abs(wcombo, ABS_DISTANCE, 0); } else { - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); - wacom_report_key(wcombo, BTN_STYLUS, 0); - wacom_report_key(wcombo, BTN_STYLUS2, 0); + wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); + wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); + if (features->type == WACOM_G4 || + features->type == WACOM_MO) { + wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); + rw = (signed)(data[7] & 0x04) - (data[7] & 0x03); + } else { + wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); + rw = -(signed)data[6]; + } + wacom_report_rel(wcombo, REL_WHEEL, rw); } - wacom->id[0] = 0; - wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ - wacom_report_key(wcombo, wacom->tool[0], 0); + + if (!prox) + wacom->id[0] = 0; + wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ + wacom_report_key(wcombo, wacom->tool[0], prox); + wacom_input_sync(wcombo); /* sync last event */ } /* send pad data */ switch (features->type) { case WACOM_G4: - if (data[7] & 0xf8) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } + prox = data[7] & 0xf8; + if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); @@ -245,29 +231,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_rel(wcombo, REL_WHEEL, rw); wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } else if (wacom->id[1]) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } - wacom->id[1] = 0; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); - wacom_report_rel(wcombo, REL_WHEEL, 0); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); + if (!prox) + wacom->id[1] = 0; + wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); } + retval = 1; break; case WACOM_MO: - if ((data[7] & 0xf8) || (data[8] & 0xff)) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } + prox = (data[7] & 0xf8) || data[8]; + if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); @@ -275,27 +248,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); + if (!prox) + wacom->id[1] = 0; wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } else if (wacom->id[1]) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } - wacom->id[1] = 0; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); - wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); - wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); - wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); } + retval = 1; break; } - return 1; +exit: + return retval; } static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) @@ -636,9 +598,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) { wacom_report_abs(wcombo, ABS_X, - (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8)); + data[2 + idx * 2] | ((data[3 + idx * 2] & 0x7f) << 8)); wacom_report_abs(wcombo, ABS_Y, - (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8)); + data[6 + idx * 2] | ((data[7 + idx * 2] & 0x7f) << 8)); wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); wacom_report_key(wcombo, wacom->tool[idx], 1); if (idx) @@ -782,31 +744,24 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) touchInProx = 0; - if (prox) { /* in prox */ - if (!wacom->id[0]) { - /* Going into proximity select tool */ - wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; - if (wacom->tool[0] == BTN_TOOL_PEN) - wacom->id[0] = STYLUS_DEVICE_ID; - else - wacom->id[0] = ERASER_DEVICE_ID; - } - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); - pressure = ((data[7] & 0x01) << 8) | data[6]; - if (pressure < 0) - pressure = features->pressure_max + pressure + 1; - wacom_report_abs(wcombo, ABS_PRESSURE, pressure); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); - } else { - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_key(wcombo, BTN_STYLUS, 0); - wacom_report_key(wcombo, BTN_STYLUS2, 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); + if (!wacom->id[0]) { /* first in prox */ + /* Going into proximity select tool */ + wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; + if (wacom->tool[0] == BTN_TOOL_PEN) + wacom->id[0] = STYLUS_DEVICE_ID; + else + wacom->id[0] = ERASER_DEVICE_ID; + } + wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); + wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); + wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); + wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); + pressure = ((data[7] & 0x01) << 8) | data[6]; + if (pressure < 0) + pressure = features->pressure_max + pressure + 1; + wacom_report_abs(wcombo, ABS_PRESSURE, pressure); + wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); + if (!prox) { /* out-prox */ wacom->id[0] = 0; /* pen is out so touch can be enabled now */ touchInProx = 1; @@ -1028,7 +983,7 @@ static const struct wacom_features wacom_features_0x93 = static const struct wacom_features wacom_features_0x9A = { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; static const struct wacom_features wacom_features_0x9F = - { "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC }; + { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; static const struct wacom_features wacom_features_0xE2 = { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; static const struct wacom_features wacom_features_0xE3 = diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 8590b1e..b50cf04 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -17,7 +17,6 @@ #define WACOM_PKGLEN_GRAPHIRE 8 #define WACOM_PKGLEN_BBFUN 9 #define WACOM_PKGLEN_INTUOS 10 -#define WACOM_PKGLEN_PENABLED 8 #define WACOM_PKGLEN_TPC1FG 5 #define WACOM_PKGLEN_TPC2FG 14 diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 7208654..8a8fa4d 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -24,17 +24,18 @@ config TOUCHSCREEN_88PM860X module will be called 88pm860x-ts. config TOUCHSCREEN_ADS7846 - tristate "ADS7846/TSC2046 and ADS7843 based touchscreens" + tristate "ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens" depends on SPI_MASTER depends on HWMON = n || HWMON help Say Y here if you have a touchscreen interface using the - ADS7846/TSC2046 or ADS7843 controller, and your board-specific - setup code includes that in its table of SPI devices. + ADS7846/TSC2046/AD7873 or ADS7843/AD7843 controller, + and your board-specific setup code includes that in its + table of SPI devices. If HWMON is selected, and the driver is told the reference voltage on your board, you will also get hwmon interfaces for the voltage - (and on ads7846/tsc2046, temperature) sensors of this chip. + (and on ads7846/tsc2046/ad7873, temperature) sensors of this chip. If unsure, say N (but it's safe to say "Y"). diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index eb83939c..e019d53 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -46,7 +46,7 @@ #include <linux/spi/ad7877.h> #include <asm/irq.h> -#define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) +#define TS_PEN_UP_TIMEOUT msecs_to_jiffies(100) #define MAX_SPI_FREQ_HZ 20000000 #define MAX_12BIT ((1<<12)-1) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 8b05d8e..532279c 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -36,6 +36,7 @@ * TSC2046 is just newer ads7846 silicon. * Support for ads7843 tested on Atmel at91sam926x-EK. * Support for ads7845 has only been stubbed in. + * Support for Analog Devices AD7873 and AD7843 tested. * * IRQ handling needs a workaround because of a shortcoming in handling * edge triggered IRQs on some platforms like the OMAP1/2. These @@ -821,6 +822,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) spin_unlock_irq(&ts->lock); + if (device_may_wakeup(&ts->spi->dev)) + enable_irq_wake(ts->spi->irq); + return 0; } @@ -829,6 +833,9 @@ static int ads7846_resume(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + if (device_may_wakeup(&ts->spi->dev)) + disable_irq_wake(ts->spi->irq); + spin_lock_irq(&ts->lock); ts->is_suspended = 0; @@ -984,6 +991,15 @@ static int __devinit ads7846_probe(struct spi_device *spi) vref = pdata->keep_vref_on; + if (ts->model == 7873) { + /* The AD7873 is almost identical to the ADS7846 + * keep VREF off during differential/ratiometric + * conversion modes + */ + ts->model = 7846; + vref = 0; + } + /* set up the transfers to read touchscreen state; this assumes we * use formula #2 for pressure, not #3. */ @@ -1191,6 +1207,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) if (err) goto err_remove_attr_group; + device_init_wakeup(&spi->dev, pdata->wakeup); + return 0; err_remove_attr_group: @@ -1220,6 +1238,8 @@ static int __devexit ads7846_remove(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + device_init_wakeup(&spi->dev, false); + ads784x_hwmon_unregister(spi, ts); input_unregister_device(ts->input); diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index 09095c7..f0bc6fa 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -1712,13 +1712,13 @@ mISDNisar_init(struct isar_hw *isar, void *hw) } EXPORT_SYMBOL(mISDNisar_init); -static int isar_mod_init(void) +static int __init isar_mod_init(void) { pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV); return 0; } -static void isar_mod_cleanup(void) +static void __exit isar_mod_cleanup(void) { pr_notice("mISDN: ISAR module unloaded\n"); } diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index adb1e8c..00c60e2 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1347,7 +1347,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) /* * isdn net devices manage lots of configuration variables as linked lists. * Those lists must only be manipulated from user space. Some of the ioctl's - * service routines access user space and are not atomic. Therefor, ioctl's + * service routines access user space and are not atomic. Therefore, ioctl's * manipulating the lists and ioctl's sleeping while accessing the lists * are serialized by means of a semaphore. */ diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 43ff4d3..6eac588 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c @@ -1114,7 +1114,7 @@ static struct Bprotocol DSP = { .create = dspcreate }; -static int dsp_init(void) +static int __init dsp_init(void) { int err; int tics; @@ -1212,7 +1212,7 @@ static int dsp_init(void) } -static void dsp_cleanup(void) +static void __exit dsp_cleanup(void) { mISDN_unregister_Bprotocol(&DSP); diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index f1e8af5..325b1ad 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -477,7 +477,7 @@ l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len) printk(KERN_DEBUG "%s: received frame, parsing... (%d)\n", __func__, len); - /* check lenght */ + /* check length */ if (len < 1+1+2) { printk(KERN_WARNING "%s: packet error - length %d below " "4 bytes\n", __func__, len); @@ -1509,7 +1509,7 @@ l1oip_init(void) printk(KERN_DEBUG "%s: interface %d is %s with %s.\n", __func__, l1oip_cnt, pri ? "PRI" : "BRI", bundle ? "bundled IP packet for all B-channels" : - "seperate IP packets for every B-channel"); + "separate IP packets for every B-channel"); hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC); if (!hc) { diff --git a/drivers/isdn/sc/hardware.h b/drivers/isdn/sc/hardware.h index 9e6d530..6273248 100644 --- a/drivers/isdn/sc/hardware.h +++ b/drivers/isdn/sc/hardware.h @@ -87,7 +87,7 @@ #define BRI_CHANNELS 2 /* Number of B channels */ #define BRI_BASEPG_VAL 0x98 #define BRI_MAGIC 0x60000 /* Magic Number */ -#define BRI_MEMSIZE 0x10000 /* Ammount of RAM (64K) */ +#define BRI_MEMSIZE 0x10000 /* Amount of RAM (64K) */ #define BRI_PARTNO "72-029" #define BRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS; /* diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index 5738d8b..921373e 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -948,10 +948,16 @@ static void do_monitor_cpu_combined(void) printk(KERN_WARNING "Warning ! Temperature way above maximum (%d) !\n", temp_combi >> 16); state0->overtemp += CPU_MAX_OVERTEMP / 4; - } else if (temp_combi > (state0->mpu.tmax << 16)) + } else if (temp_combi > (state0->mpu.tmax << 16)) { state0->overtemp++; - else + printk(KERN_WARNING "Temperature %d above max %d. overtemp %d\n", + temp_combi >> 16, state0->mpu.tmax, state0->overtemp); + } else { + if (state0->overtemp) + printk(KERN_WARNING "Temperature back down to %d\n", + temp_combi >> 16); state0->overtemp = 0; + } if (state0->overtemp >= CPU_MAX_OVERTEMP) critical_state = 1; if (state0->overtemp > 0) { @@ -1023,10 +1029,16 @@ static void do_monitor_cpu_split(struct cpu_pid_state *state) " (%d) !\n", state->index, temp >> 16); state->overtemp += CPU_MAX_OVERTEMP / 4; - } else if (temp > (state->mpu.tmax << 16)) + } else if (temp > (state->mpu.tmax << 16)) { state->overtemp++; - else + printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n", + state->index, temp >> 16, state->mpu.tmax, state->overtemp); + } else { + if (state->overtemp) + printk(KERN_WARNING "CPU %d temperature back down to %d\n", + state->index, temp >> 16); state->overtemp = 0; + } if (state->overtemp >= CPU_MAX_OVERTEMP) critical_state = 1; if (state->overtemp > 0) { @@ -1085,10 +1097,16 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state) " (%d) !\n", state->index, temp >> 16); state->overtemp = CPU_MAX_OVERTEMP / 4; - } else if (temp > (state->mpu.tmax << 16)) + } else if (temp > (state->mpu.tmax << 16)) { state->overtemp++; - else + printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n", + state->index, temp >> 16, state->mpu.tmax, state->overtemp); + } else { + if (state->overtemp) + printk(KERN_WARNING "CPU %d temperature back down to %d\n", + state->index, temp >> 16); state->overtemp = 0; + } if (state->overtemp >= CPU_MAX_OVERTEMP) critical_state = 1; if (state->overtemp > 0) { diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h index 393cc9d..df3680e 100644 --- a/drivers/macintosh/therm_pm72.h +++ b/drivers/macintosh/therm_pm72.h @@ -269,7 +269,7 @@ struct slots_pid_state #define CPU_TEMP_HISTORY_SIZE 2 #define CPU_POWER_HISTORY_SIZE 10 #define CPU_PID_INTERVAL 1 -#define CPU_MAX_OVERTEMP 30 +#define CPU_MAX_OVERTEMP 90 #define CPUA_PUMP_RPM_INDEX 7 #define CPUB_PUMP_RPM_INDEX 8 diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 0903f53..0a3b4ed 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -123,7 +123,7 @@ static int ir_copy_table(struct ir_scancode_table *destin, * If the key is not found, returns -EINVAL, otherwise, returns 0. */ static int ir_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { int elem; struct ir_input_dev *ir_dev = input_get_drvdata(dev); @@ -291,7 +291,7 @@ static int ir_insert_key(struct ir_scancode_table *rc_tab, * If the key is not found, returns -EINVAL, otherwise, returns 0. */ static int ir_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, unsigned int keycode) { int rc = 0; struct ir_input_dev *ir_dev = input_get_drvdata(dev); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 52e4ce4..80dda30 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -214,14 +214,14 @@ struct dvb_tuner_ops { int (*get_status)(struct dvb_frontend *fe, u32 *status); int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength); - /** These are provided seperately from set_params in order to facilitate silicon - * tuners which require sophisticated tuning loops, controlling each parameter seperately. */ + /** These are provided separately from set_params in order to facilitate silicon + * tuners which require sophisticated tuning loops, controlling each parameter separately. */ int (*set_frequency)(struct dvb_frontend *fe, u32 frequency); int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth); /* - * These are provided seperately from set_params in order to facilitate silicon - * tuners which require sophisticated tuning loops, controlling each parameter seperately. + * These are provided separately from set_params in order to facilitate silicon + * tuners which require sophisticated tuning loops, controlling each parameter separately. */ int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index a03ef7e..852fe89 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -9,7 +9,7 @@ #include <linux/usb/input.h> static int dvb_usb_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { struct dvb_usb_device *d = input_get_drvdata(dev); @@ -39,7 +39,7 @@ static int dvb_usb_getkeycode(struct input_dev *dev, } static int dvb_usb_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, unsigned int keycode) { struct dvb_usb_device *d = input_get_drvdata(dev); diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 12279f6..716870a 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -4404,7 +4404,7 @@ static void rv605_muxsel(struct bttv *btv, unsigned int input) /* Tibet Systems 'Progress DVR' CS16 muxsel helper [Chris Fanning] * * The CS16 (available on eBay cheap) is a PCI board with four Fusion - * 878A chips, a PCI bridge, an Atmel microcontroller, four sync seperator + * 878A chips, a PCI bridge, an Atmel microcontroller, four sync separator * chips, ten eight input analog multiplexors, a not chip and a few * other components. * @@ -4426,7 +4426,7 @@ static void rv605_muxsel(struct bttv *btv, unsigned int input) * * There is an ATMEL microcontroller with an 8031 core on board. I have not * determined what function (if any) it provides. With the microcontroller - * and sync seperator chips a guess is that it might have to do with video + * and sync separator chips a guess is that it might have to do with video * switching and maybe some digital I/O. */ static void tibetCS16_muxsel(struct bttv *btv, unsigned int input) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index bc4ced6..f36e11a 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -512,7 +512,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { /* * The FX2 chip does not give us a zero length read at end of frame. * It does, however, give a short read at the end of a frame, if - * neccessary, rather than run two frames together. + * necessary, rather than run two frames together. * * By choosing the right bulk transfer size, we are guaranteed to always * get a short read for the last read of each frame. Frame sizes are diff --git a/drivers/media/video/pwc/philips.txt b/drivers/media/video/pwc/philips.txt index f9f3584..d38dd79 100644 --- a/drivers/media/video/pwc/philips.txt +++ b/drivers/media/video/pwc/philips.txt @@ -33,7 +33,7 @@ a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin contains decompression routines that allow you to use higher image sizes and framerates; in addition the webcam uses less bandwidth on the USB bus (handy if you want to run more than 1 camera simultaneously). These routines fall -under a NDA, and may therefor not be distributed as source; however, its use +under a NDA, and may therefore not be distributed as source; however, its use is completely optional. You can build this code either into your kernel, or as a module. I recommend diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 4af7382..494957b 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -120,7 +120,7 @@ extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2], /* Write multiple registers with constant values. For example: sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18}); - Register adresses must be < 256. + Register addresses must be < 256. */ #define sn9c102_write_const_regs(sn9c102_device, data...) \ ({ static const u8 _valreg[][2] = {data}; \ diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index 0446524..6bf6bc7 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -6,7 +6,7 @@ The tea6420 is a bus controlled audio-matrix with 5 stereo inputs, 4 stereo outputs and gain control for each output. - It is cascadable, i.e. it can be found at the adresses 0x98 + It is cascadable, i.e. it can be found at the addresses 0x98 and 0x9a on the i2c-bus. For detailed informations download the specifications directly diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index e5ab621..ef5ce26 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -539,7 +539,7 @@ static int i2o_iop_reset(struct i2o_controller *c) * which is indeterminate. We need to wait until the IOP has * rebooted before we can let the system talk to it. We read * the inbound Free_List until a message is available. If we - * can't read one in the given ammount of time, we assume the + * can't read one in the given amount of time, we assume the * IOP could not reboot properly. */ osm_debug("%s: Reset in progress, waiting for reboot...\n", diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 951fa9b..2a5a0b7 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -11,7 +11,7 @@ config MFD_CORE config MFD_88PM860X bool "Support Marvell 88PM8606/88PM8607" - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE help This supports for Marvell 88PM8606/88PM8607 Power Management IC. @@ -205,7 +205,7 @@ config PMIC_ADP5520 config MFD_MAX8925 bool "Maxim Semiconductor MAX8925 PMIC Support" - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE help Say yes here to support for Maxim Semiconductor MAX8925. This is @@ -226,7 +226,7 @@ config MFD_WM8400 config MFD_WM831X bool "Support Wolfson Microelectronics WM831x/2x PMICs" select MFD_CORE - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS help Support for the Wolfson Microelecronics WM831x and WM832x PMICs. This driver provides common support for accessing the device, @@ -235,6 +235,7 @@ config MFD_WM831X config MFD_WM8350 bool + depends on GENERIC_HARDIRQS config MFD_WM8350_CONFIG_MODE_0 bool @@ -287,7 +288,7 @@ config MFD_WM8352_CONFIG_MODE_3 config MFD_WM8350_I2C bool "Support Wolfson Microelectronics WM8350 with I2C" select MFD_WM8350 - depends on I2C=y + depends on I2C=y && GENERIC_HARDIRQS help The WM8350 is an integrated audio and power management subsystem with watchdog and RTC functionality for embedded diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index dc9ea95..7b6652f 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -523,7 +523,7 @@ unsigned long sm501_set_clock(struct device *dev, unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK); unsigned char reg; unsigned int pll_reg = 0; - unsigned long sm501_freq; /* the actual frequency acheived */ + unsigned long sm501_freq; /* the actual frequency achieved */ struct sm501_clock to; @@ -533,7 +533,7 @@ unsigned long sm501_set_clock(struct device *dev, switch (clksrc) { case SM501_CLOCK_P2XCLK: - /* This clock is divided in half so to achive the + /* This clock is divided in half so to achieve the * requested frequency the value must be multiplied by * 2. This clock also has an additional pre divisor */ @@ -562,7 +562,7 @@ unsigned long sm501_set_clock(struct device *dev, break; case SM501_CLOCK_V2XCLK: - /* This clock is divided in half so to achive the + /* This clock is divided in half so to achieve the * requested frequency the value must be multiplied by 2. */ sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2); @@ -648,7 +648,7 @@ unsigned long sm501_find_clock(struct device *dev, unsigned long req_freq) { struct sm501_devdata *sm = dev_get_drvdata(dev); - unsigned long sm501_freq; /* the frequency achiveable by the 501 */ + unsigned long sm501_freq; /* the frequency achieveable by the 501 */ struct sm501_clock to; switch (clksrc) { @@ -1430,7 +1430,7 @@ static int __devinit sm501_plat_probe(struct platform_device *dev) } sm->regs_claim = request_mem_region(sm->io_res->start, - resource_size(sm->io_res), "sm501"); + 0x100, "sm501"); if (sm->regs_claim == NULL) { dev_err(&dev->dev, "cannot claim registers\n"); @@ -1644,7 +1644,7 @@ static int __devinit sm501_pci_probe(struct pci_dev *dev, sm->mem_res = &dev->resource[0]; sm->regs_claim = request_mem_region(sm->io_res->start, - resource_size(sm->io_res), "sm501"); + 0x100, "sm501"); if (sm->regs_claim == NULL) { dev_err(&dev->dev, "cannot claim registers\n"); err= -EBUSY; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index d16af6a..2191c8d 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -268,6 +268,16 @@ config ISL29003 This driver can also be built as a module. If so, the module will be called isl29003. +config SENSORS_TSL2550 + tristate "Taos TSL2550 ambient light sensor" + depends on I2C && SYSFS + help + If you say yes here you get support for the Taos TSL2550 + ambient light sensor. + + This driver can also be built as a module. If so, the module + will be called tsl2550. + config EP93XX_PWM tristate "EP93xx PWM support" depends on ARCH_EP93XX diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 049ff24..27c4843 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_SGI_GRU) += sgi-gru/ obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfgpt.o obj-$(CONFIG_HP_ILO) += hpilo.o obj-$(CONFIG_ISL29003) += isl29003.o +obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 2cb2736..db7d0f2 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -505,6 +505,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) * Export the EEPROM bytes through sysfs, since that's convenient. * By default, only root should see the data (maybe passwords etc) */ + sysfs_bin_attr_init(&at24->bin); at24->bin.attr.name = "eeprom"; at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; at24->bin.read = at24_bin_read; diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h index 02a77b8..7a8b906 100644 --- a/drivers/misc/sgi-gru/grutables.h +++ b/drivers/misc/sgi-gru/grutables.h @@ -516,8 +516,7 @@ struct gru_blade_state { /* Scan all active GRUs in a GRU bitmap */ #define for_each_gru_in_bitmap(gid, map) \ - for ((gid) = find_first_bit((map), GRU_MAX_GRUS); (gid) < GRU_MAX_GRUS;\ - (gid)++, (gid) = find_next_bit((map), GRU_MAX_GRUS, (gid))) + for_each_set_bit((gid), (map), GRU_MAX_GRUS) /* Scan all active GRUs on a specific blade */ #define for_each_gru_on_blade(gru, nid, i) \ @@ -536,23 +535,17 @@ struct gru_blade_state { /* Scan each CBR whose bit is set in a TFM (or copy of) */ #define for_each_cbr_in_tfm(i, map) \ - for ((i) = find_first_bit(map, GRU_NUM_CBE); \ - (i) < GRU_NUM_CBE; \ - (i)++, (i) = find_next_bit(map, GRU_NUM_CBE, i)) + for_each_set_bit((i), (map), GRU_NUM_CBE) /* Scan each CBR in a CBR bitmap. Note: multiple CBRs in an allocation unit */ #define for_each_cbr_in_allocation_map(i, map, k) \ - for ((k) = find_first_bit(map, GRU_CBR_AU); (k) < GRU_CBR_AU; \ - (k) = find_next_bit(map, GRU_CBR_AU, (k) + 1)) \ + for_each_set_bit((k), (map), GRU_CBR_AU) \ for ((i) = (k)*GRU_CBR_AU_SIZE; \ (i) < ((k) + 1) * GRU_CBR_AU_SIZE; (i)++) /* Scan each DSR in a DSR bitmap. Note: multiple DSRs in an allocation unit */ #define for_each_dsr_in_allocation_map(i, map, k) \ - for ((k) = find_first_bit((const unsigned long *)map, GRU_DSR_AU);\ - (k) < GRU_DSR_AU; \ - (k) = find_next_bit((const unsigned long *)map, \ - GRU_DSR_AU, (k) + 1)) \ + for_each_set_bit((k), (const unsigned long *)(map), GRU_DSR_AU) \ for ((i) = (k) * GRU_DSR_AU_CL; \ (i) < ((k) + 1) * GRU_DSR_AU_CL; (i)++) diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/misc/tsl2550.c index a0702f3..483ae5f 100644 --- a/drivers/i2c/chips/tsl2550.c +++ b/drivers/misc/tsl2550.c @@ -47,8 +47,8 @@ struct tsl2550_data { struct i2c_client *client; struct mutex update_lock; - unsigned int power_state : 1; - unsigned int operating_mode : 1; + unsigned int power_state:1; + unsigned int operating_mode:1; }; /* diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index 3fab78b..723e508 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -575,7 +575,7 @@ static int uart_carrier_raised(struct tty_port *tport) struct sdio_uart_port *port = container_of(tport, struct sdio_uart_port, port); unsigned int ret = sdio_uart_claim_func(port); - if (ret) /* Missing hardware shoudn't block for carrier */ + if (ret) /* Missing hardware shouldn't block for carrier */ return 1; ret = sdio_uart_get_mctrl(port); sdio_uart_release_func(port); diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index f4b97d3..3168ebd 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1089,6 +1089,7 @@ void mmc_rescan(struct work_struct *work) mmc_claim_host(host); mmc_power_up(host); + sdio_reset(host); mmc_go_idle(host); mmc_send_if_cond(host, host->ocr_avail); diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index 4eb7825..dea36d9 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c @@ -67,13 +67,13 @@ int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) return err; } -int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, - unsigned addr, u8 in, u8* out) +static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn, + unsigned addr, u8 in, u8 *out) { struct mmc_command cmd; int err; - BUG_ON(!card); + BUG_ON(!host); BUG_ON(fn > 7); /* sanity check */ @@ -90,11 +90,11 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, cmd.arg |= in; cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; - err = mmc_wait_for_cmd(card->host, &cmd, 0); + err = mmc_wait_for_cmd(host, &cmd, 0); if (err) return err; - if (mmc_host_is_spi(card->host)) { + if (mmc_host_is_spi(host)) { /* host driver already reported errors */ } else { if (cmd.resp[0] & R5_ERROR) @@ -106,7 +106,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, } if (out) { - if (mmc_host_is_spi(card->host)) + if (mmc_host_is_spi(host)) *out = (cmd.resp[0] >> 8) & 0xFF; else *out = cmd.resp[0] & 0xFF; @@ -115,6 +115,13 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, return 0; } +int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, + unsigned addr, u8 in, u8 *out) +{ + BUG_ON(!card); + return mmc_io_rw_direct_host(card->host, write, fn, addr, in, out); +} + int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz) { @@ -182,3 +189,20 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, return 0; } +int sdio_reset(struct mmc_host *host) +{ + int ret; + u8 abort; + + /* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */ + + ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort); + if (ret) + abort = 0x08; + else + abort |= 0x08; + + ret = mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL); + return ret; +} + diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h index e2e74b0..12a4d3a 100644 --- a/drivers/mmc/core/sdio_ops.h +++ b/drivers/mmc/core/sdio_ops.h @@ -17,6 +17,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, unsigned addr, u8 in, u8* out); int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); +int sdio_reset(struct mmc_host *host); #endif diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index b31946e..4c068e5 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c @@ -1250,9 +1250,7 @@ msmsdcc_resume(struct platform_device *dev) if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) mmc_resume_host(mmc); - if (host->stat_irq) - enable_irq(host->stat_irq); - else if (host->stat_irq) + if (host->stat_irq) enable_irq(host->stat_irq); } return 0; diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 60a2b69..2df9041 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -4,7 +4,7 @@ * This is a driver for the SDHC controller found in Freescale MX2/MX3 * SoCs. It is basically the same hardware as found on MX1 (imxmmc.c). * Unlike the hardware found on MX1, this hardware just works and does - * not need all the quirks found in imxmmc.c, hence the seperate driver. + * not need all the quirks found in imxmmc.c, hence the separate driver. * * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com> @@ -708,7 +708,7 @@ static int mxcmci_probe(struct platform_device *pdev) mmc->max_blk_size = 2048; mmc->max_blk_count = 65535; mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; - mmc->max_seg_size = mmc->max_seg_size; + mmc->max_seg_size = mmc->max_req_size; host = mmc_priv(mmc); host->base = ioremap(r->start, resource_size(r)); diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index ca584d0..ca584d0 100755..100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 1bec5e1..8db1148 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -226,7 +226,7 @@ struct unlock_addr { * exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore, * should not be used. The problem is that structures with * initializers have extra fields initialized to 0. It is _very_ - * desireable to have the unlock address entries for unsupported + * desirable to have the unlock address entries for unsupported * data widths automatically initialized - that means that * MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here * must go unused. diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 8aca552..8aca552 100755..100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c index c48cad2..30e12c8 100644 --- a/drivers/mtd/maps/pismo.c +++ b/drivers/mtd/maps/pismo.c @@ -118,7 +118,7 @@ static int __devinit pismo_add_device(struct pismo_data *pismo, int i, { struct platform_device *dev; struct resource res = { }; - phys_addr_t base = region.base; + phys_addr_t base = region->base; int ret; if (base == ~0) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index dafb919..76a76be 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -4,7 +4,7 @@ * http://www.simtec.co.uk/products/SWLINUX/ * Ben Dooks <ben@simtec.co.uk> * - * Generic platfrom device based RAM map + * Generic platform device based RAM map * * 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 diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index bb64656..1157d56 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -444,7 +444,7 @@ config MTD_NAND_FSL_UPM config MTD_NAND_MXC tristate "MXC NAND support" - depends on ARCH_MX2 || ARCH_MX3 + depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 help This enables the driver for the NAND flash controller on the MXC processors. diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c index 087bcd7..7d1cca7a 100644 --- a/drivers/mtd/nand/bcm_umi_nand.c +++ b/drivers/mtd/nand/bcm_umi_nand.c @@ -381,7 +381,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) if (!r) return -ENXIO; - /* map physical adress */ + /* map physical address */ bcm_umi_io_base = ioremap(r->start, r->end - r->start + 1); if (!bcm_umi_io_base) { @@ -525,7 +525,7 @@ static int bcm_umi_nand_remove(struct platform_device *pdev) /* Release resources, unregister device */ nand_release(board_mtd); - /* unmap physical adress */ + /* unmap physical address */ iounmap(bcm_umi_io_base); /* Free the MTD device structure */ diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 45dec57..b2900d8 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -507,7 +507,7 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) * MXC NANDFC can only perform full page+spare or * spare-only read/write. When the upper layers * layers perform a read/write buf operation, - * we will used the saved column adress to index into + * we will used the saved column address to index into * the full page. */ send_addr(host, 0, page_addr == -1); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 7029cd5..0ba5b8e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -907,7 +907,7 @@ config SMC91X select CRC32 select MII depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || \ - MIPS || BLACKFIN || MN10300 + MIPS || BLACKFIN || MN10300 || COLDFIRE help This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 8ca6391..a1d4188 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -575,9 +575,9 @@ static int ks8695_poll(struct napi_struct *napi, int budget) if (work_done < budget) { unsigned long flags; spin_lock_irqsave(&ksp->rx_lock, flags); + __napi_complete(napi); /*enable rx interrupt*/ writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN); - __napi_complete(napi); spin_unlock_irqrestore(&ksp->rx_lock, flags); } return work_done; diff --git a/drivers/net/atlx/atl2.h b/drivers/net/atlx/atl2.h index d918bbe..927e4de 100644 --- a/drivers/net/atlx/atl2.h +++ b/drivers/net/atlx/atl2.h @@ -442,7 +442,7 @@ struct atl2_hw { struct atl2_ring_header { /* pointer to the descriptor ring memory */ void *desc; - /* physical adress of the descriptor ring */ + /* physical address of the descriptor ring */ dma_addr_t dma; /* length of descriptor ring in bytes */ unsigned int size; diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index be81fb2..8f07525 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -290,11 +290,6 @@ extern const struct ethtool_ops be_ethtool_ops; #define drvr_stats(adapter) (&adapter->stats.drvr_stats) -static inline unsigned int be_pci_func(struct be_adapter *adapter) -{ - return PCI_FUNC(adapter->pdev->devfn); -} - #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) #define PAGE_SHIFT_4K 12 diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 4b1f805..c592153 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -465,8 +465,6 @@ int be_cmd_eq_create(struct be_adapter *adapter, req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); - AMAP_SET_BITS(struct amap_eq_context, func, req->context, - be_pci_func(adapter)); AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); /* 4byte eqe*/ AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); @@ -629,7 +627,6 @@ int be_cmd_cq_create(struct be_adapter *adapter, AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); - AMAP_SET_BITS(struct amap_cq_context, func, ctxt, be_pci_func(adapter)); be_dws_cpu_to_le(ctxt, sizeof(req->context)); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); @@ -678,7 +675,6 @@ int be_cmd_mccq_create(struct be_adapter *adapter, req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); - AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, be_pci_func(adapter)); AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, be_encoded_q_len(mccq->len)); @@ -727,8 +723,6 @@ int be_cmd_txq_create(struct be_adapter *adapter, AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, be_encoded_q_len(txq->len)); - AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt, - be_pci_func(adapter)); AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1); AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id); diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index 5ffb149..2d4a4b8 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -114,8 +114,7 @@ #define IMG_TYPE_ISCSI_BACKUP 9 #define IMG_TYPE_FCOE_FW_ACTIVE 10 #define IMG_TYPE_FCOE_FW_BACKUP 11 -#define IMG_TYPE_NCSI_BITFILE 13 -#define IMG_TYPE_NCSI_8051 14 +#define IMG_TYPE_NCSI_FW 13 #define FLASHROM_OPER_FLASH 1 #define FLASHROM_OPER_SAVE 2 @@ -127,6 +126,7 @@ #define FLASH_IMAGE_MAX_SIZE_g3 (2097152) /* Max fw image size */ #define FLASH_BIOS_IMAGE_MAX_SIZE_g3 (524288) /* Max OPTION ROM img sz */ #define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3 (1048576) /* Max Redboot image sz */ +#define FLASH_NCSI_IMAGE_MAX_SIZE_g3 (262144) /* Max NSCI image sz */ #define FLASH_NCSI_MAGIC (0x16032009) #define FLASH_NCSI_DISABLED (0) @@ -144,6 +144,7 @@ #define FLASH_FCoE_BIOS_START_g2 (524288) #define FLASH_REDBOOT_START_g2 (0) +#define FLASH_NCSI_START_g3 (15990784) #define FLASH_iSCSI_PRIMARY_IMAGE_START_g3 (2097152) #define FLASH_iSCSI_BACKUP_IMAGE_START_g3 (4194304) #define FLASH_FCoE_PRIMARY_IMAGE_START_g3 (6291456) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index a703ed8..43e8032 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1382,7 +1382,7 @@ rx_eq_free: /* There are 8 evt ids per func. Retruns the evt id's bit number */ static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id) { - return eq_id - 8 * be_pci_func(adapter); + return eq_id % 8; } static irqreturn_t be_intx(int irq, void *dev) @@ -1880,8 +1880,9 @@ static int be_flash_data(struct be_adapter *adapter, const u8 *p = fw->data; struct be_cmd_write_flashrom *req = flash_cmd->va; struct flash_comp *pflashcomp; + int num_comp; - struct flash_comp gen3_flash_types[8] = { + struct flash_comp gen3_flash_types[9] = { { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE, FLASH_IMAGE_MAX_SIZE_g3}, { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT, @@ -1897,7 +1898,9 @@ static int be_flash_data(struct be_adapter *adapter, { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE, FLASH_IMAGE_MAX_SIZE_g3}, { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP, - FLASH_IMAGE_MAX_SIZE_g3} + FLASH_IMAGE_MAX_SIZE_g3}, + { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW, + FLASH_NCSI_IMAGE_MAX_SIZE_g3} }; struct flash_comp gen2_flash_types[8] = { { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE, @@ -1921,11 +1924,16 @@ static int be_flash_data(struct be_adapter *adapter, if (adapter->generation == BE_GEN3) { pflashcomp = gen3_flash_types; filehdr_size = sizeof(struct flash_file_hdr_g3); + num_comp = 9; } else { pflashcomp = gen2_flash_types; filehdr_size = sizeof(struct flash_file_hdr_g2); + num_comp = 8; } - for (i = 0; i < 8; i++) { + for (i = 0; i < num_comp; i++) { + if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) && + memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) + continue; if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) && (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset, pflashcomp[i].size, @@ -1985,16 +1993,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) struct be_dma_mem flash_cmd; int status, i = 0; const u8 *p; - char fw_ver[FW_VER_LEN]; - char fw_cfg; - - status = be_cmd_get_fw_ver(adapter, fw_ver); - if (status) - return status; - fw_cfg = *(fw_ver + 2); - if (fw_cfg == '0') - fw_cfg = '1'; strcpy(fw_file, func); status = request_firmware(&fw, fw_file, &adapter->pdev->dev); diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index bf7f9ba..866905f 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -26,6 +26,7 @@ #define DRV_NAME "bfin_can" #define BFIN_CAN_TIMEOUT 100 +#define TX_ECHO_SKB_MAX 1 /* * transmit and receive channels @@ -593,7 +594,7 @@ struct net_device *alloc_bfin_candev(void) struct net_device *dev; struct bfin_can_priv *priv; - dev = alloc_candev(sizeof(*priv)); + dev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX); if (!dev) return NULL; diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 11c8784..3345109 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -876,9 +876,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne return NETDEV_TX_OK; nomem: - if (skb) - dev_kfree_skb(skb); - + dev_kfree_skb(skb); stats->tx_dropped++; return NETDEV_TX_OK; diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 7cbcfb0..9bd155e 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -5072,7 +5072,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, INIT_WORK(&cp->reset_task, cas_reset_task); /* Default link parameters */ - if (link_mode >= 0 && link_mode <= 6) + if (link_mode >= 0 && link_mode < 6) cp->link_cntl = link_modes[link_mode]; else cp->link_cntl = BMCR_ANENABLE; diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 7138411..55d99ca 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -248,7 +248,7 @@ static void restart_sched(unsigned long); * * Interrupts are handled by a single CPU and it is likely that on a MP system * the application is migrated to another CPU. In that scenario, we try to - * seperate the RX(in irq context) and TX state in order to decrease memory + * separate the RX(in irq context) and TX state in order to decrease memory * contention. */ struct sge { diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index b85c81f..60777fd 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -28,6 +28,7 @@ #include <linux/delay.h> #include <linux/netdevice.h> +#include <linux/if_vlan.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/skbuff.h> @@ -55,9 +56,9 @@ module_param(dumb_switch, int, 0444); MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable"); MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus"); -#define CPMAC_VERSION "0.5.1" -/* frame size + 802.1q tag */ -#define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4) +#define CPMAC_VERSION "0.5.2" +/* frame size + 802.1q tag + FCS size */ +#define CPMAC_SKB_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) #define CPMAC_QUEUES 8 /* Ethernet registers */ @@ -1136,8 +1137,9 @@ static int __devinit cpmac_probe(struct platform_device *pdev) } if (phy_id == PHY_MAX_ADDR) { - dev_err(&pdev->dev, "no PHY present\n"); - return -ENODEV; + dev_err(&pdev->dev, "no PHY present, falling back to switch on MDIO bus 0\n"); + strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */ + phy_id = pdev->id; } dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES); @@ -1290,8 +1292,8 @@ void __devexit cpmac_exit(void) { platform_driver_unregister(&cpmac_driver); mdiobus_unregister(cpmac_mii); - mdiobus_free(cpmac_mii); iounmap(cpmac_mii->priv); + mdiobus_free(cpmac_mii); } module_init(cpmac_init); diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 1462401..b0208e4 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -580,7 +580,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) } #ifdef CONFIG_SH_HICOSH4 - /* truely reset the chip */ + /* truly reset the chip */ writeword(ioaddr, ADD_PORT, 0x0114); writeword(ioaddr, DATA_PORT, 0x0040); #endif diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 3e453e1..9e3e875 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1294,6 +1294,7 @@ static void cxgb_down(struct adapter *adapter) free_irq_resources(adapter); quiesce_rx(adapter); + t3_sge_stop(adapter); flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */ } diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 78e265b..67e61b2 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -197,13 +197,13 @@ static inline void refill_rspq(struct adapter *adapter, /** * need_skb_unmap - does the platform need unmapping of sk_buffs? * - * Returns true if the platfrom needs sk_buff unmapping. The compiler + * Returns true if the platform needs sk_buff unmapping. The compiler * optimizes away unecessary code if this returns true. */ static inline int need_skb_unmap(void) { /* - * This structure is used to tell if the platfrom needs buffer + * This structure is used to tell if the platform needs buffer * unmapping by checking if DECLARE_PCI_UNMAP_ADDR defines anything. */ struct dummy { diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 1ac9440..8bd086a 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -2385,7 +2385,7 @@ static int emac_dev_open(struct net_device *ndev) struct emac_priv *priv = netdev_priv(ndev); netif_carrier_off(ndev); - for (cnt = 0; cnt <= ETH_ALEN; cnt++) + for (cnt = 0; cnt < ETH_ALEN; cnt++) ndev->dev_addr[cnt] = priv->mac_addr[cnt]; /* Configuration items */ @@ -2658,7 +2658,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) pdata = pdev->dev.platform_data; if (!pdata) { - printk(KERN_ERR "DaVinci EMAC: No platfrom data\n"); + printk(KERN_ERR "DaVinci EMAC: No platform data\n"); return -ENODEV; } diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 3c95acb..712ccc6 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1346,7 +1346,7 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) * * 1) down * 2) autoneg_progress - * 3) autoneg_complete (the link sucessfully autonegotiated) + * 3) autoneg_complete (the link successfully autonegotiated) * 4) forced_up (the link has been forced up, it did not autonegotiate) * **/ diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index db05ec3..e301e26 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -320,6 +320,8 @@ #define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ /* Header split receive */ +#define E1000_RFCTL_NFSW_DIS 0x00000040 +#define E1000_RFCTL_NFSR_DIS 0x00000080 #define E1000_RFCTL_ACK_DIS 0x00001000 #define E1000_RFCTL_EXTEN 0x00008000 #define E1000_RFCTL_IPV6_EX_DIS 0x00010000 diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 54d03a0..8b5e157 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -2740,6 +2740,16 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) reg &= ~(1 << 31); ew32(STATUS, reg); } + + /* + * work-around descriptor data corruption issue during nfs v2 udp + * traffic, just disable the nfs filtering capability + */ + reg = er32(RFCTL); + reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); + ew32(RFCTL, reg); + + return; } /** diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 2425ed1..a8b2c0d 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -647,7 +647,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) if (!(rxcw & E1000_RXCW_IV)) { mac->serdes_has_link = true; e_dbg("SERDES: Link up - autoneg " - "completed sucessfully.\n"); + "completed successfully.\n"); } else { mac->serdes_has_link = false; e_dbg("SERDES: Link down - invalid" diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 61a7b43..b671555 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2021,7 +2021,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* setup the TxBD length and buffer pointer for the first BD */ - tx_queue->tx_skbuff[tx_queue->skb_curtx] = skb; txbdp_start->bufPtr = dma_map_single(&priv->ofdev->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); @@ -2053,6 +2052,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) txbdp_start->lstatus = lstatus; + eieio(); /* force lstatus write before tx_skbuff */ + + tx_queue->tx_skbuff[tx_queue->skb_curtx] = skb; + /* Update the current skb pointer to the next entry we will use * (wrapping if necessary) */ tx_queue->skb_curtx = (tx_queue->skb_curtx + 1) & diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 583a21c..0ed25f0 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -688,7 +688,7 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter) /* start with one vector for every rx queue */ numvecs = adapter->num_rx_queues; - /* if tx handler is seperate add 1 for every tx queue */ + /* if tx handler is separate add 1 for every tx queue */ if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) numvecs += adapter->num_tx_queues; diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index e8e33bb..2c9b3af 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1651,6 +1651,8 @@ static int irda_usb_probe(struct usb_interface *intf, self->rx_urb = kcalloc(self->max_rx_urb, sizeof(struct urb *), GFP_KERNEL); + if (!self->rx_urb) + goto err_free_net; for (i = 0; i < self->max_rx_urb; i++) { self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); @@ -1783,6 +1785,8 @@ err_out_2: err_out_1: for (i = 0; i < self->max_rx_urb; i++) usb_free_urb(self->rx_urb[i]); + kfree(self->rx_urb); +err_free_net: free_netdev(net); err_out: return ret; diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index c412e80..1dcdce0 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -331,7 +331,7 @@ static int sa1100_irda_resume(struct platform_device *pdev) * If we missed a speed change, initialise at the new speed * directly. It is debatable whether this is actually * required, but in the interests of continuing from where - * we left off it is desireable. The converse argument is + * we left off it is desirable. The converse argument is * that we should re-negotiate at 9600 baud again. */ if (si->newspeed) { diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index b5219cc..0573e0b 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -407,7 +407,7 @@ static irqreturn_t ks8851_irq(int irq, void *pw) * @buff: The buffer address * @len: The length of the data to read * - * Issue an RXQ FIFO read command and read the @len ammount of data from + * Issue an RXQ FIFO read command and read the @len amount of data from * the FIFO into the buffer specified by @buff. */ static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index b40a851..0da94b2 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -423,6 +423,11 @@ struct qlcnic_adapter_stats { u64 lro_pkts; u64 rxbytes; u64 txbytes; + u64 lrobytes; + u64 lso_frames; + u64 xmit_on; + u64 xmit_off; + u64 skb_alloc_failure; }; /* @@ -1095,11 +1100,11 @@ struct qlcnic_brdinfo { static const struct qlcnic_brdinfo qlcnic_boards[] = { {0x1077, 0x8020, 0x1077, 0x203, - "8200 Series Single Port 10GbE Converged Network Adapter \ - (TCP/IP Networking)"}, + "8200 Series Single Port 10GbE Converged Network Adapter " + "(TCP/IP Networking)"}, {0x1077, 0x8020, 0x1077, 0x207, - "8200 Series Dual Port 10GbE Converged Network Adapter \ - (TCP/IP Networking)"}, + "8200 Series Dual Port 10GbE Converged Network Adapter " + "(TCP/IP Networking)"}, {0x1077, 0x8020, 0x1077, 0x20b, "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"}, {0x1077, 0x8020, 0x1077, 0x20c, diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 8da6ec8..f83e15f 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -59,6 +59,17 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = { QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)}, {"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, + {"lrobytes", + QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)}, + {"lso_frames", + QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)}, + {"xmit_on", + QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)}, + {"xmit_off", + QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)}, + {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure), + QLC_OFF(stats.skb_alloc_failure)}, + }; #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) @@ -785,6 +796,11 @@ qlcnic_get_ethtool_stats(struct net_device *dev, } } +static u32 qlcnic_get_tx_csum(struct net_device *dev) +{ + return dev->features & NETIF_F_IP_CSUM; +} + static u32 qlcnic_get_rx_csum(struct net_device *dev) { struct qlcnic_adapter *adapter = netdev_priv(dev); @@ -995,6 +1011,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = { .set_ringparam = qlcnic_set_ringparam, .get_pauseparam = qlcnic_get_pauseparam, .set_pauseparam = qlcnic_set_pauseparam, + .get_tx_csum = qlcnic_get_tx_csum, .set_tx_csum = ethtool_op_set_tx_csum, .set_sg = ethtool_op_set_sg, .get_tso = qlcnic_get_tso, diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 99a4d13..da00e16 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -349,6 +349,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, if (nr_desc >= qlcnic_tx_avail(tx_ring)) { netif_tx_stop_queue(tx_ring->txq); __netif_tx_unlock_bh(tx_ring->txq); + adapter->stats.xmit_off++; return -EBUSY; } @@ -397,20 +398,16 @@ qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); } -static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, - u8 *addr, struct list_head *del_list) +static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, u8 *addr) { struct list_head *head; struct qlcnic_mac_list_s *cur; /* look up if already exists */ - list_for_each(head, del_list) { + list_for_each(head, &adapter->mac_list) { cur = list_entry(head, struct qlcnic_mac_list_s, list); - - if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { - list_move_tail(head, &adapter->mac_list); + if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) return 0; - } } cur = kzalloc(sizeof(struct qlcnic_mac_list_s), GFP_ATOMIC); @@ -432,14 +429,9 @@ void qlcnic_set_multi(struct net_device *netdev) struct dev_mc_list *mc_ptr; u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; u32 mode = VPORT_MISS_MODE_DROP; - LIST_HEAD(del_list); - struct list_head *head; - struct qlcnic_mac_list_s *cur; - list_splice_tail_init(&adapter->mac_list, &del_list); - - qlcnic_nic_add_mac(adapter, adapter->mac_addr, &del_list); - qlcnic_nic_add_mac(adapter, bcast_addr, &del_list); + qlcnic_nic_add_mac(adapter, adapter->mac_addr); + qlcnic_nic_add_mac(adapter, bcast_addr); if (netdev->flags & IFF_PROMISC) { mode = VPORT_MISS_MODE_ACCEPT_ALL; @@ -454,22 +446,12 @@ void qlcnic_set_multi(struct net_device *netdev) if (!netdev_mc_empty(netdev)) { netdev_for_each_mc_addr(mc_ptr, netdev) { - qlcnic_nic_add_mac(adapter, mc_ptr->dmi_addr, - &del_list); + qlcnic_nic_add_mac(adapter, mc_ptr->dmi_addr); } } send_fw_cmd: qlcnic_nic_set_promisc(adapter, mode); - head = &del_list; - while (!list_empty(head)) { - cur = list_entry(head->next, struct qlcnic_mac_list_s, list); - - qlcnic_sre_macaddr_change(adapter, - cur->mac_addr, QLCNIC_MAC_DEL); - list_del(&cur->list); - kfree(cur); - } } int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index ea00ab4..7c34e4e 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -568,21 +568,123 @@ struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section) return NULL; } +#define FILEHEADER_SIZE (14 * 4) + static int -qlcnic_set_product_offs(struct qlcnic_adapter *adapter) +qlcnic_validate_header(struct qlcnic_adapter *adapter) { - struct uni_table_desc *ptab_descr; const u8 *unirom = adapter->fw->data; - u32 i; + struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; + __le32 fw_file_size = adapter->fw->size; __le32 entries; + __le32 entry_size; + __le32 tab_size; + + if (fw_file_size < FILEHEADER_SIZE) + return -EINVAL; + + entries = cpu_to_le32(directory->num_entries); + entry_size = cpu_to_le32(directory->entry_size); + tab_size = cpu_to_le32(directory->findex) + (entries * entry_size); + + if (fw_file_size < tab_size) + return -EINVAL; + + return 0; +} + +static int +qlcnic_validate_bootld(struct qlcnic_adapter *adapter) +{ + struct uni_table_desc *tab_desc; + struct uni_data_desc *descr; + const u8 *unirom = adapter->fw->data; + int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + + QLCNIC_UNI_BOOTLD_IDX_OFF)); + __le32 offs; + __le32 tab_size; + __le32 data_size; + + tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD); + + if (!tab_desc) + return -EINVAL; + + tab_size = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size * (idx + 1))); + + if (adapter->fw->size < tab_size) + return -EINVAL; + + offs = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * (idx)); + descr = (struct uni_data_desc *)&unirom[offs]; + + data_size = descr->findex + cpu_to_le32(descr->size); + + if (adapter->fw->size < data_size) + return -EINVAL; + + return 0; +} + +static int +qlcnic_validate_fw(struct qlcnic_adapter *adapter) +{ + struct uni_table_desc *tab_desc; + struct uni_data_desc *descr; + const u8 *unirom = adapter->fw->data; + int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + + QLCNIC_UNI_FIRMWARE_IDX_OFF)); + __le32 offs; + __le32 tab_size; + __le32 data_size; + + tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW); + + if (!tab_desc) + return -EINVAL; + + tab_size = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size * (idx + 1))); + + if (adapter->fw->size < tab_size) + return -EINVAL; + + offs = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * (idx)); + descr = (struct uni_data_desc *)&unirom[offs]; + data_size = descr->findex + cpu_to_le32(descr->size); + + if (adapter->fw->size < data_size) + return -EINVAL; + + return 0; +} + +static int +qlcnic_validate_product_offs(struct qlcnic_adapter *adapter) +{ + struct uni_table_desc *ptab_descr; + const u8 *unirom = adapter->fw->data; int mn_present = qlcnic_has_mn(adapter); + __le32 entries; + __le32 entry_size; + __le32 tab_size; + u32 i; ptab_descr = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_PRODUCT_TBL); - if (ptab_descr == NULL) - return -1; + if (!ptab_descr) + return -EINVAL; entries = cpu_to_le32(ptab_descr->num_entries); + entry_size = cpu_to_le32(ptab_descr->entry_size); + tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size); + + if (adapter->fw->size < tab_size) + return -EINVAL; + nomn: for (i = 0; i < entries; i++) { @@ -609,7 +711,37 @@ nomn: mn_present = 0; goto nomn; } - return -1; + return -EINVAL; +} + +static int +qlcnic_validate_unified_romimage(struct qlcnic_adapter *adapter) +{ + if (qlcnic_validate_header(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: header validation failed\n"); + return -EINVAL; + } + + if (qlcnic_validate_product_offs(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: product validation failed\n"); + return -EINVAL; + } + + if (qlcnic_validate_bootld(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: bootld validation failed\n"); + return -EINVAL; + } + + if (qlcnic_validate_fw(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: firmware validation failed\n"); + return -EINVAL; + } + + return 0; } static @@ -715,7 +847,7 @@ qlcnic_get_bios_version(struct qlcnic_adapter *adapter) bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off]) + QLCNIC_UNI_BIOS_VERSION_OFF)); - return (bios_ver << 24) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); + return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); } int @@ -858,7 +990,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter) u8 fw_type = adapter->fw_type; if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) { - if (qlcnic_set_product_offs(adapter)) + if (qlcnic_validate_unified_romimage(adapter)) return -EINVAL; min_size = QLCNIC_UNI_FW_MIN_SIZE; @@ -1114,8 +1246,10 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, struct pci_dev *pdev = adapter->pdev; buffer->skb = dev_alloc_skb(rds_ring->skb_size); - if (!buffer->skb) + if (!buffer->skb) { + adapter->stats.skb_alloc_failure++; return -ENOMEM; + } skb = buffer->skb; @@ -1289,7 +1423,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, netif_receive_skb(skb); adapter->stats.lro_pkts++; - adapter->stats.rxbytes += length; + adapter->stats.lrobytes += length; return buffer; } @@ -1505,6 +1639,8 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, adapter->diag_cnt++; dev_kfree_skb_any(skb); + adapter->stats.rx_pkts++; + adapter->stats.rxbytes += length; return buffer; } diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 665e8e5..fc72156 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -118,6 +118,7 @@ qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, if (qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH) { netif_stop_queue(adapter->netdev); smp_mb(); + adapter->stats.xmit_off++; } } @@ -1385,6 +1386,7 @@ qlcnic_tso_check(struct net_device *netdev, int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; struct cmd_desc_type0 *hwdesc; struct vlan_ethhdr *vh; + struct qlcnic_adapter *adapter = netdev_priv(netdev); if (protocol == cpu_to_be16(ETH_P_8021Q)) { @@ -1494,6 +1496,7 @@ qlcnic_tso_check(struct net_device *netdev, tx_ring->producer = producer; barrier(); + adapter->stats.lso_frames++; } static int @@ -1573,6 +1576,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (unlikely(no_of_desc + 2 > qlcnic_tx_avail(tx_ring))) { netif_stop_queue(netdev); + adapter->stats.xmit_off++; return NETDEV_TX_BUSY; } @@ -1880,6 +1884,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { netif_wake_queue(netdev); adapter->tx_timeo_cnt = 0; + adapter->stats.xmit_on++; } __netif_tx_unlock(tx_ring->txq); } diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 05b8bde..7dbff87 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -405,7 +405,7 @@ static int ql_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) u32 wol = 0; status = ql_mb_wol_mode(qdev, wol); netif_err(qdev, drv, qdev->ndev, "WOL %s (wol code 0x%x)\n", - status == 0 ? "cleared sucessfully" : "clear failed", + status == 0 ? "cleared successfully" : "clear failed", wol); } diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index c26ec5d..fd34f26 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3855,7 +3855,7 @@ int ql_wol(struct ql_adapter *qdev) status = ql_mb_wol_mode(qdev, wol); netif_err(qdev, drv, qdev->ndev, "WOL %s (wol code 0x%x) on %s\n", - (status == 0) ? "Sucessfully set" : "Failed", + (status == 0) ? "Successfully set" : "Failed", wol, qdev->ndev->name); } diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index dfc3573..9d3ebf3 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4270,7 +4270,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->cur_tx += frags + 1; - smp_wmb(); + wmb(); RTL_W8(TxPoll, NPQ); /* set polling bit */ @@ -4621,7 +4621,7 @@ static int rtl8169_poll(struct napi_struct *napi, int budget) * until it does. */ tp->intr_mask = 0xffff; - smp_wmb(); + wmb(); RTL_W16(IntrMask, tp->intr_event); } diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 43bc66a..df70657 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -923,8 +923,8 @@ static int init_shared_mem(struct s2io_nic *nic) tmp_v_addr = mac_control->stats_mem; mac_control->stats_info = (struct stat_block *)tmp_v_addr; memset(tmp_v_addr, 0, size); - DBG_PRINT(INIT_DBG, "%s: Ring Mem PHY: 0x%llx\n", dev->name, - (unsigned long long)tmp_p_addr); + DBG_PRINT(INIT_DBG, "%s: Ring Mem PHY: 0x%llx\n", + dev_name(&nic->pdev->dev), (unsigned long long)tmp_p_addr); mac_control->stats_info->sw_stat.mem_allocated += mem_allocated; return SUCCESS; } @@ -3480,7 +3480,7 @@ static void s2io_reset(struct s2io_nic *sp) struct swStat *swstats; DBG_PRINT(INIT_DBG, "%s: Resetting XFrame card %s\n", - __func__, sp->dev->name); + __func__, pci_name(sp->pdev)); /* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */ pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd)); diff --git a/drivers/net/sfc/regs.h b/drivers/net/sfc/regs.h index 89d606f..18a3be4 100644 --- a/drivers/net/sfc/regs.h +++ b/drivers/net/sfc/regs.h @@ -95,7 +95,7 @@ #define FRF_AA_INT_ACK_KER_FIELD_LBN 0 #define FRF_AA_INT_ACK_KER_FIELD_WIDTH 32 -/* INT_ISR0_REG: Function 0 Interrupt Acknowlege Status register */ +/* INT_ISR0_REG: Function 0 Interrupt Acknowledge Status register */ #define FR_BZ_INT_ISR0 0x00000090 #define FRF_BZ_INT_ISR_REG_LBN 0 #define FRF_BZ_INT_ISR_REG_WIDTH 64 diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c index a85efcf..e8387d2 100644 --- a/drivers/net/skfp/ess.c +++ b/drivers/net/skfp/ess.c @@ -557,7 +557,7 @@ static void ess_send_alc_req(struct s_smc *smc) /* * send never allocation request where the requested payload and - * overhead is zero or deallocate bandwidht when no bandwidth is + * overhead is zero or deallocate bandwidth when no bandwidth is * parsed */ if (!smc->mib.fddiESSPayload) { diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 653bdd7..d8ec4c1 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4863,6 +4863,7 @@ static int sky2_resume(struct pci_dev *pdev) if (!hw) return 0; + rtnl_lock(); err = pci_set_power_state(pdev, PCI_D0); if (err) goto out; @@ -4884,7 +4885,6 @@ static int sky2_resume(struct pci_dev *pdev) sky2_write32(hw, B0_IMSK, Y2_IS_BASE); napi_enable(&hw->napi); - rtnl_lock(); for (i = 0; i < hw->ports; i++) { err = sky2_reattach(hw->dev[i]); if (err) diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 5479954..8d2772c 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -330,6 +330,48 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r, #include <unit/smc91111.h> +#elif defined(CONFIG_ARCH_MSM) + +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 1 + +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) + +#define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH + +#elif defined(CONFIG_COLDFIRE) + +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 1 + +static inline void mcf_insw(void *a, unsigned char *p, int l) +{ + u16 *wp = (u16 *) p; + while (l-- > 0) + *wp++ = readw(a); +} + +static inline void mcf_outsw(void *a, unsigned char *p, int l) +{ + u16 *wp = (u16 *) p; + while (l-- > 0) + writew(*wp++, a); +} + +#define SMC_inw(a, r) _swapw(readw((a) + (r))) +#define SMC_outw(v, a, r) writew(_swapw(v), (a) + (r)) +#define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l) +#define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l) + +#define SMC_IRQ_FLAGS (IRQF_DISABLED) + #else /* diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 30110a1..34fa10d 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -1347,7 +1347,7 @@ static int smsc9420_open(struct net_device *dev) netif_carrier_off(dev); - /* disable, mask and acknowlege all interrupts */ + /* disable, mask and acknowledge all interrupts */ spin_lock_irqsave(&pd->int_lock, flags); int_cfg = smsc9420_reg_read(pd, INT_CFG) & (~INT_CFG_IRQ_EN_); smsc9420_reg_write(pd, INT_CFG, int_cfg); diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 2f8a8c3..5ba9d98 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -474,7 +474,7 @@ spider_net_prepare_rx_descr(struct spider_net_card *card, * spider_net_enable_rxchtails - sets RX dmac chain tail addresses * @card: card structure * - * spider_net_enable_rxchtails sets the RX DMAC chain tail adresses in the + * spider_net_enable_rxchtails sets the RX DMAC chain tail addresses in the * chip by writing to the appropriate register. DMA is enabled in * spider_net_enable_rxdmac. */ @@ -1820,7 +1820,7 @@ spider_net_enable_card(struct spider_net_card *card) spider_net_write_reg(card, SPIDER_NET_ECMODE, SPIDER_NET_ECMODE_VALUE); - /* set chain tail adress for RX chains and + /* set chain tail address for RX chains and * enable DMA */ spider_net_enable_rxchtails(card); spider_net_enable_rxdmac(card); diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 4344017..70196bc 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -782,7 +782,7 @@ static int gem_rx(struct gem *gp, int work_to_do) break; /* When writing back RX descriptor, GEM writes status - * then buffer address, possibly in seperate transactions. + * then buffer address, possibly in separate transactions. * If we don't wait for the chip to write both, we could * post a new buffer to this descriptor then have GEM spam * on the buffer address. We sync on the RX completion diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 0c97802..f549309 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -1851,7 +1851,7 @@ static void bdx_tx_push_desc(struct bdx_priv *priv, void *data, int size) * @data - desc's data * @size - desc's size * - * NOTE: this func does check for available space and, if neccessary, waits for + * NOTE: this func does check for available space and, if necessary, waits for * NIC to read existing data before writing new one. */ static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0fa7688..22cf1c4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5279,7 +5279,7 @@ static void tg3_poll_controller(struct net_device *dev) struct tg3 *tp = netdev_priv(dev); for (i = 0; i < tp->irq_cnt; i++) - tg3_interrupt(tp->napi[i].irq_vec, dev); + tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); } #endif @@ -9776,7 +9776,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ADVERTISED_Pause | ADVERTISED_Asym_Pause; - if (!(tp->tg3_flags2 & TG3_FLAG_10_100_ONLY)) + if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) mask |= ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full; diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index 21a0175..ee71bcf 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -693,7 +693,7 @@ static netdev_tx_t tms380tr_hardware_send_packet(struct sk_buff *skb, * NOTE: This function should be used whenever the status of any TPL must be * modified by the driver, because the compiler may otherwise change the * order of instructions such that writing the TPL status may be executed at - * an undesireable time. When this function is used, the status is always + * an undesirable time. When this function is used, the status is always * written when the function is called. */ static void tms380tr_write_tpl_status(TPL *tpl, unsigned int Status) @@ -2264,7 +2264,7 @@ static void tms380tr_rcv_status_irq(struct net_device *dev) * This function should be used whenever the status of any RPL must be * modified by the driver, because the compiler may otherwise change the * order of instructions such that writing the RPL status may be executed - * at an undesireable time. When this function is used, the status is + * at an undesirable time. When this function is used, the status is * always written when the function is called. */ static void tms380tr_write_rpl_status(RPL *rpl, unsigned int Status) diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c index 93f4e83..49f05d1 100644 --- a/drivers/net/tulip/eeprom.c +++ b/drivers/net/tulip/eeprom.c @@ -143,6 +143,12 @@ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp) void __devinit tulip_parse_eeprom(struct net_device *dev) { + /* + dev is not registered at this point, so logging messages can't + use dev_<level> or netdev_<level> but dev->name is good via a + hack in the caller + */ + /* The last media info list parsed, for multiport boards. */ static struct mediatable *last_mediatable; static unsigned char *last_ee_data; @@ -161,15 +167,14 @@ void __devinit tulip_parse_eeprom(struct net_device *dev) if (ee_data[0] == 0xff) { if (last_mediatable) { controller_index++; - dev_info(&dev->dev, - "Controller %d of multiport board\n", - controller_index); + pr_info("%s: Controller %d of multiport board\n", + dev->name, controller_index); tp->mtable = last_mediatable; ee_data = last_ee_data; goto subsequent_board; } else - dev_info(&dev->dev, - "Missing EEPROM, this interface may not work correctly!\n"); + pr_info("%s: Missing EEPROM, this interface may not work correctly!\n", + dev->name); return; } /* Do a fix-up based on the vendor half of the station address prefix. */ @@ -181,15 +186,14 @@ void __devinit tulip_parse_eeprom(struct net_device *dev) i++; /* An Accton EN1207, not an outlaw Maxtech. */ memcpy(ee_data + 26, eeprom_fixups[i].newtable, sizeof(eeprom_fixups[i].newtable)); - dev_info(&dev->dev, - "Old format EEPROM on '%s' board. Using substitute media control info\n", - eeprom_fixups[i].name); + pr_info("%s: Old format EEPROM on '%s' board. Using substitute media control info\n", + dev->name, eeprom_fixups[i].name); break; } } if (eeprom_fixups[i].name == NULL) { /* No fixup found. */ - dev_info(&dev->dev, - "Old style EEPROM with no media selection information\n"); + pr_info("%s: Old style EEPROM with no media selection information\n", + dev->name); return; } } @@ -217,8 +221,8 @@ subsequent_board: /* there is no phy information, don't even try to build mtable */ if (count == 0) { if (tulip_debug > 0) - dev_warn(&dev->dev, - "no phy info, aborting mtable build\n"); + pr_warning("%s: no phy info, aborting mtable build\n", + dev->name); return; } @@ -234,8 +238,10 @@ subsequent_board: mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0; mtable->csr15dir = mtable->csr15val = 0; - dev_info(&dev->dev, "EEPROM default media type %s\n", - media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]); + pr_info("%s: EEPROM default media type %s\n", + dev->name, + media & 0x0800 ? "Autosense" + : medianame[media & MEDIA_MASK]); for (i = 0; i < count; i++) { struct medialeaf *leaf = &mtable->mleaf[i]; @@ -298,17 +304,17 @@ subsequent_board: } if (tulip_debug > 1 && leaf->media == 11) { unsigned char *bp = leaf->leafdata; - dev_info(&dev->dev, - "MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n", - bp[0], bp[1], bp[2 + bp[1]*2], - bp[5 + bp[2 + bp[1]*2]*2], - bp[4 + bp[2 + bp[1]*2]*2]); + pr_info("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n", + dev->name, + bp[0], bp[1], bp[2 + bp[1]*2], + bp[5 + bp[2 + bp[1]*2]*2], + bp[4 + bp[2 + bp[1]*2]*2]); } - dev_info(&dev->dev, - "Index #%d - Media %s (#%d) described by a %s (%d) block\n", - i, medianame[leaf->media & 15], leaf->media, - leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>", - leaf->type); + pr_info("%s: Index #%d - Media %s (#%d) described by a %s (%d) block\n", + dev->name, + i, medianame[leaf->media & 15], leaf->media, + leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>", + leaf->type); } if (new_advertise) tp->sym_advertise = new_advertise; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index ce1efa4..96c39bd 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1437,7 +1437,7 @@ static int tun_chr_close(struct inode *inode, struct file *file) __tun_detach(tun); - /* If desireable, unregister the netdevice. */ + /* If desirable, unregister the netdevice. */ if (!(tun->flags & TUN_PERSIST)) { rtnl_lock(); if (dev->reg_state == NETREG_REGISTERED) diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index e3ddcb8..cd24e5f 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -480,7 +480,7 @@ typhoon_hello(struct typhoon *tp) typhoon_inc_cmd_index(&ring->lastWrite, 1); INIT_COMMAND_NO_RESPONSE(cmd, TYPHOON_CMD_HELLO_RESP); - smp_wmb(); + wmb(); iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY); spin_unlock(&tp->command_lock); } @@ -1311,13 +1311,15 @@ typhoon_init_interface(struct typhoon *tp) tp->txlo_dma_addr = le32_to_cpu(iface->txLoAddr); tp->card_state = Sleeping; - smp_wmb(); tp->offload = TYPHOON_OFFLOAD_IP_CHKSUM | TYPHOON_OFFLOAD_TCP_CHKSUM; tp->offload |= TYPHOON_OFFLOAD_UDP_CHKSUM | TSO_OFFLOAD_ON; spin_lock_init(&tp->command_lock); spin_lock_init(&tp->state_lock); + + /* Force the writes to the shared memory area out before continuing. */ + wmb(); } static void @@ -2096,7 +2098,7 @@ typhoon_tx_timeout(struct net_device *dev) if(typhoon_reset(tp->ioaddr, WaitNoSleep) < 0) { netdev_warn(dev, "could not reset in tx timeout\n"); - goto truely_dead; + goto truly_dead; } /* If we ever start using the Hi ring, it will need cleaning too */ @@ -2105,13 +2107,13 @@ typhoon_tx_timeout(struct net_device *dev) if(typhoon_start_runtime(tp) < 0) { netdev_err(dev, "could not start runtime in tx timeout\n"); - goto truely_dead; + goto truly_dead; } netif_wake_queue(dev); return; -truely_dead: +truly_dead: /* Reset the hardware, and turn off carrier to avoid more timeouts */ typhoon_reset(tp->ioaddr, NoWait); netif_carrier_off(dev); diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 23a9751..1b0aef3 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -430,7 +430,7 @@ static void hw_add_addr_in_hash(struct ucc_geth_private *ugeth, ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); /* Ethernet frames are defined in Little Endian mode, - therefor to insert */ + therefore to insert */ /* the address to the hash (Big Endian mode), we reverse the bytes.*/ set_mac_addr(&p_82xx_addr_filt->taddr.h, p_enet_addr); diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 20e3460..9e05639 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -54,6 +54,7 @@ static const char driver_name [] = "asix"; #define AX_CMD_WRITE_IPG0 0x12 #define AX_CMD_WRITE_IPG1 0x13 #define AX_CMD_READ_NODE_ID 0x13 +#define AX_CMD_WRITE_NODE_ID 0x14 #define AX_CMD_WRITE_IPG2 0x14 #define AX_CMD_WRITE_MULTI_FILTER 0x16 #define AX88172_CMD_READ_NODE_ID 0x17 @@ -165,6 +166,7 @@ static const char driver_name [] = "asix"; /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ struct asix_data { u8 multi_filter[AX_MCAST_FILTER_SIZE]; + u8 mac_addr[ETH_ALEN]; u8 phymode; u8 ledmode; u8 eeprom_len; @@ -732,6 +734,30 @@ static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } +static int asix_set_mac_address(struct net_device *net, void *p) +{ + struct usbnet *dev = netdev_priv(net); + struct asix_data *data = (struct asix_data *)&dev->data; + struct sockaddr *addr = p; + + if (netif_running(net)) + return -EBUSY; + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); + + /* We use the 20 byte dev->data + * for our 6 byte mac buffer + * to avoid allocating memory that + * is tricky to free later */ + memcpy(data->mac_addr, addr->sa_data, ETH_ALEN); + asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, + data->mac_addr); + + return 0; +} + /* We need to override some ethtool_ops so we require our own structure so we don't interfere with other usbnet devices that may be connected at the same time. */ @@ -919,7 +945,7 @@ static const struct net_device_ops ax88772_netdev_ops = { .ndo_start_xmit = usbnet_start_xmit, .ndo_tx_timeout = usbnet_tx_timeout, .ndo_change_mtu = usbnet_change_mtu, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = asix_set_mac_address, .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = asix_ioctl, .ndo_set_multicast_list = asix_set_multicast, @@ -1213,7 +1239,7 @@ static const struct net_device_ops ax88178_netdev_ops = { .ndo_stop = usbnet_stop, .ndo_start_xmit = usbnet_start_xmit, .ndo_tx_timeout = usbnet_tx_timeout, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = asix_set_mac_address, .ndo_validate_addr = eth_validate_addr, .ndo_set_multicast_list = asix_set_multicast, .ndo_do_ioctl = asix_ioctl, diff --git a/drivers/net/usb/pegasus.h b/drivers/net/usb/pegasus.h index 5d02f02..b90d876 100644 --- a/drivers/net/usb/pegasus.h +++ b/drivers/net/usb/pegasus.h @@ -177,7 +177,7 @@ PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400c, PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0xabc1, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c, - DEFAULT_GPIO_RESET | PEGASUS_II ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046, @@ -208,6 +208,8 @@ PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100, */ PEGASUS_DEV_CLASS( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, 0x00, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "Belkin F5U122 10/100 USB Ethernet", VENDOR_BELKIN, 0x0122, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987, @@ -249,7 +251,7 @@ PEGASUS_DEV( "GIGABYTE GN-BR402W Wireless Router", VENDOR_GIGABYTE, 0x8002, PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "HP hn210c Ethernet USB", VENDOR_HP, 0x811c, - DEFAULT_GPIO_RESET | PEGASUS_II ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913, diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index b36bf96..f0bd70f 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -811,7 +811,7 @@ static ssize_t cosa_read(struct file *file, cosa_enable_rx(chan); spin_lock_irqsave(&cosa->lock, flags); add_wait_queue(&chan->rxwaitq, &wait); - while(!chan->rx_status) { + while (!chan->rx_status) { current->state = TASK_INTERRUPTIBLE; spin_unlock_irqrestore(&cosa->lock, flags); schedule(); @@ -896,7 +896,7 @@ static ssize_t cosa_write(struct file *file, spin_lock_irqsave(&cosa->lock, flags); add_wait_queue(&chan->txwaitq, &wait); - while(!chan->tx_status) { + while (!chan->tx_status) { current->state = TASK_INTERRUPTIBLE; spin_unlock_irqrestore(&cosa->lock, flags); schedule(); @@ -1153,7 +1153,7 @@ static int cosa_ioctl_common(struct cosa_data *cosa, struct channel_data *channel, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; - switch(cmd) { + switch (cmd) { case COSAIORSET: /* Reset the device */ if (!capable(CAP_NET_ADMIN)) return -EACCES; @@ -1704,7 +1704,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) spin_unlock_irqrestore(&cosa->lock, flags); return; } - while(1) { + while (1) { cosa->txchan++; i++; if (cosa->txchan >= cosa->nchannels) @@ -2010,7 +2010,7 @@ again: static void debug_status_in(struct cosa_data *cosa, int status) { char *s; - switch(status & SR_CMD_FROM_SRP_MASK) { + switch (status & SR_CMD_FROM_SRP_MASK) { case SR_UP_REQUEST: s = "RX_REQ"; break; diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index f1bff98..1ceccf1 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -141,7 +141,7 @@ static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev) data->address != CISCO_UNICAST) return cpu_to_be16(ETH_P_HDLC); - switch(data->protocol) { + switch (data->protocol) { case cpu_to_be16(ETH_P_IP): case cpu_to_be16(ETH_P_IPX): case cpu_to_be16(ETH_P_IPV6): @@ -190,7 +190,7 @@ static int cisco_rx(struct sk_buff *skb) cisco_data = (struct cisco_packet*)(skb->data + sizeof (struct hdlc_header)); - switch(ntohl (cisco_data->type)) { + switch (ntohl (cisco_data->type)) { case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ in_dev = dev->ip_ptr; addr = 0; @@ -245,8 +245,8 @@ static int cisco_rx(struct sk_buff *skb) dev_kfree_skb_any(skb); return NET_RX_SUCCESS; - } /* switch(keepalive type) */ - } /* switch(protocol) */ + } /* switch (keepalive type) */ + } /* switch (protocol) */ printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name, ntohs(data->protocol)); diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index aa9248f..6e1ca25 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -202,10 +202,10 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr) return 0; /* return protocol only, no settable parameters */ case IF_PROTO_X25: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - if(dev->flags & IFF_UP) + if (dev->flags & IFF_UP) return -EBUSY; result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index e803a7d..25c24f0 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -612,7 +612,7 @@ ssize_t i2400m_bm_cmd(struct i2400m *i2400m, goto error_wait_for_ack; } rx_bytes = result; - /* verify the ack and read more if neccessary [result is the + /* verify the ack and read more if necessary [result is the * final amount of bytes we get in the ack] */ result = __i2400m_bm_ack_verify(i2400m, opcode, ack, ack_size, flags); if (result < 0) diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 04df9bb..820b128 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h @@ -627,7 +627,7 @@ enum i2400m_bm_cmd_flags { * @I2400M_BRI_NO_REBOOT: Do not reboot the device and proceed * directly to wait for a reboot barker from the device. * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot - * rom after reading the MAC adress. This is quite a dirty hack, + * rom after reading the MAC address. This is quite a dirty hack, * if you ask me -- the device requires the bootrom to be * intialized after reading the MAC address. */ diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c index 76a50ac..14f876b 100644 --- a/drivers/net/wimax/i2400m/sdio.c +++ b/drivers/net/wimax/i2400m/sdio.c @@ -304,7 +304,7 @@ error_kzalloc: * * The device will be fully reset internally, but won't be * disconnected from the bus (so no reenumeration will - * happen). Firmware upload will be neccessary. + * happen). Firmware upload will be necessary. * * The device will send a reboot barker that will trigger the driver * to reinitialize the state via __i2400m_dev_reset_handle. @@ -314,7 +314,7 @@ error_kzalloc: * * The device will be fully reset internally, disconnected from the * bus an a reenumeration will happen. Firmware upload will be - * neccessary. Thus, we don't do any locking or struct + * necessary. Thus, we don't do any locking or struct * reinitialization, as we are going to be fully disconnected and * reenumerated. * diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 98f4f8c..99f04c4 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -246,7 +246,7 @@ error_kzalloc: * * The device will be fully reset internally, but won't be * disconnected from the USB bus (so no reenumeration will - * happen). Firmware upload will be neccessary. + * happen). Firmware upload will be necessary. * * The device will send a reboot barker in the notification endpoint * that will trigger the driver to reinitialize the state @@ -257,7 +257,7 @@ error_kzalloc: * * The device will be fully reset internally, disconnected from the * USB bus an a reenumeration will happen. Firmware upload will be - * neccessary. Thus, we don't do any locking or struct + * necessary. Thus, we don't do any locking or struct * reinitialization, as we are going to be fully disconnected and * reenumerated. * diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 698d567..dc5018a 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -5255,7 +5255,8 @@ static int set_wep_key(struct airo_info *ai, u16 index, const char *key, WepKeyRid wkr; int rc; - WARN_ON(keylen == 0); + if (WARN_ON(keylen == 0)) + return -1; memset(&wkr, 0, sizeof(wkr)); wkr.len = cpu_to_le16(sizeof(wkr)); diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 8c8ce67..dc662b7 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -166,6 +166,7 @@ struct ar9170 { struct ath_common common; struct mutex mutex; enum ar9170_device_state state; + bool registered; unsigned long bad_hw_nagger; int (*open)(struct ar9170 *); diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index a6452af..257c734 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2512,7 +2512,7 @@ void *ar9170_alloc(size_t priv_size) /* * this buffer is used for rx stream reconstruction. * Under heavy load this device (or the transport layer?) - * tends to split the streams into seperate rx descriptors. + * tends to split the streams into separate rx descriptors. */ skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL); @@ -2701,7 +2701,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", wiphy_name(ar->hw->wiphy)); - return err; + ar->registered = true; + return 0; err_unreg: ieee80211_unregister_hw(ar->hw); @@ -2712,11 +2713,14 @@ err_out: void ar9170_unregister(struct ar9170 *ar) { + if (ar->registered) { #ifdef CONFIG_AR9170_LEDS - ar9170_unregister_leds(ar); + ar9170_unregister_leds(ar); #endif /* CONFIG_AR9170_LEDS */ - kfree_skb(ar->rx_failover); ieee80211_unregister_hw(ar->hw); + } + + kfree_skb(ar->rx_failover); mutex_destroy(&ar->mutex); } diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 0f36118..4e30197 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -582,43 +582,6 @@ static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, return 0; } -static int ar9170_usb_request_firmware(struct ar9170_usb *aru) -{ - int err = 0; - - err = request_firmware(&aru->firmware, "ar9170.fw", - &aru->udev->dev); - if (!err) { - aru->init_values = NULL; - return 0; - } - - if (aru->req_one_stage_fw) { - dev_err(&aru->udev->dev, "ar9170.fw firmware file " - "not found and is required for this device\n"); - return -EINVAL; - } - - dev_err(&aru->udev->dev, "ar9170.fw firmware file " - "not found, trying old firmware...\n"); - - err = request_firmware(&aru->init_values, "ar9170-1.fw", - &aru->udev->dev); - if (err) { - dev_err(&aru->udev->dev, "file with init values not found.\n"); - return err; - } - - err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); - if (err) { - release_firmware(aru->init_values); - dev_err(&aru->udev->dev, "firmware file not found.\n"); - return err; - } - - return err; -} - static int ar9170_usb_reset(struct ar9170_usb *aru) { int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); @@ -757,6 +720,103 @@ err_out: return err; } +static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) +{ + struct device *parent = aru->udev->dev.parent; + + /* unbind anything failed */ + if (parent) + down(&parent->sem); + device_release_driver(&aru->udev->dev); + if (parent) + up(&parent->sem); +} + +static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) +{ + struct ar9170_usb *aru = context; + int err; + + aru->firmware = fw; + + if (!fw) { + dev_err(&aru->udev->dev, "firmware file not found.\n"); + goto err_freefw; + } + + err = ar9170_usb_init_device(aru); + if (err) + goto err_freefw; + + err = ar9170_usb_open(&aru->common); + if (err) + goto err_unrx; + + err = ar9170_register(&aru->common, &aru->udev->dev); + + ar9170_usb_stop(&aru->common); + if (err) + goto err_unrx; + + return; + + err_unrx: + ar9170_usb_cancel_urbs(aru); + + err_freefw: + ar9170_usb_firmware_failed(aru); +} + +static void ar9170_usb_firmware_inits(const struct firmware *fw, + void *context) +{ + struct ar9170_usb *aru = context; + int err; + + if (!fw) { + dev_err(&aru->udev->dev, "file with init values not found.\n"); + ar9170_usb_firmware_failed(aru); + return; + } + + aru->init_values = fw; + + /* ok so we have the init values -- get code for two-stage */ + + err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", + &aru->udev->dev, GFP_KERNEL, aru, + ar9170_usb_firmware_finish); + if (err) + ar9170_usb_firmware_failed(aru); +} + +static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) +{ + struct ar9170_usb *aru = context; + int err; + + if (fw) { + ar9170_usb_firmware_finish(fw, context); + return; + } + + if (aru->req_one_stage_fw) { + dev_err(&aru->udev->dev, "ar9170.fw firmware file " + "not found and is required for this device\n"); + ar9170_usb_firmware_failed(aru); + return; + } + + dev_err(&aru->udev->dev, "ar9170.fw firmware file " + "not found, trying old firmware...\n"); + + err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", + &aru->udev->dev, GFP_KERNEL, aru, + ar9170_usb_firmware_inits); + if (err) + ar9170_usb_firmware_failed(aru); +} + static bool ar9170_requires_one_stage(const struct usb_device_id *id) { if (!id->driver_info) @@ -814,33 +874,9 @@ static int ar9170_usb_probe(struct usb_interface *intf, if (err) goto err_freehw; - err = ar9170_usb_request_firmware(aru); - if (err) - goto err_freehw; - - err = ar9170_usb_init_device(aru); - if (err) - goto err_freefw; - - err = ar9170_usb_open(ar); - if (err) - goto err_unrx; - - err = ar9170_register(ar, &udev->dev); - - ar9170_usb_stop(ar); - if (err) - goto err_unrx; - - return 0; - -err_unrx: - ar9170_usb_cancel_urbs(aru); - -err_freefw: - release_firmware(aru->init_values); - release_firmware(aru->firmware); - + return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", + &aru->udev->dev, GFP_KERNEL, aru, + ar9170_usb_firmware_step2); err_freehw: usb_set_intfdata(intf, NULL); usb_put_dev(udev); @@ -860,12 +896,12 @@ static void ar9170_usb_disconnect(struct usb_interface *intf) ar9170_unregister(&aru->common); ar9170_usb_cancel_urbs(aru); - release_firmware(aru->init_values); - release_firmware(aru->firmware); - usb_put_dev(aru->udev); usb_set_intfdata(intf, NULL); ieee80211_free_hw(aru->common.hw); + + release_firmware(aru->init_values); + release_firmware(aru->firmware); } #ifdef CONFIG_PM diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 6a3f4da..10b5226 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -429,8 +429,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; AR5K_EEPROM_READ(o++, val); - ee->ee_i_cal[mode] = (val >> 8) & 0x3f; - ee->ee_q_cal[mode] = (val >> 3) & 0x1f; + ee->ee_i_cal[mode] = (val >> 5) & 0x3f; + ee->ee_q_cal[mode] = val & 0x1f; if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { AR5K_EEPROM_READ(o++, val); diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 72474c0..eff3323 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1386,38 +1386,39 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, goto done; /* Calibration has finished, get the results and re-run */ + + /* work around empty results which can apparently happen on 5212 */ for (i = 0; i <= 10; i++) { iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "iq_corr:%x i_pwr:%x q_pwr:%x", iq_corr, i_pwr, q_pwr); + if (i_pwr && q_pwr) + break; } i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; q_coffd = q_pwr >> 7; - /* No correction */ - if (i_coffd == 0 || q_coffd == 0) + /* protect against divide by 0 and loss of sign bits */ + if (i_coffd == 0 || q_coffd < 2) goto done; - i_coff = ((-iq_corr) / i_coffd); - - /* Boundary check */ - if (i_coff > 31) - i_coff = 31; - if (i_coff < -32) - i_coff = -32; + i_coff = (-iq_corr) / i_coffd; + i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ - q_coff = (((s32)i_pwr / q_coffd) - 128); + q_coff = (i_pwr / q_coffd) - 128; + q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */ - /* Boundary check */ - if (q_coff > 15) - q_coff = 15; - if (q_coff < -16) - q_coff = -16; + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "new I:%d Q:%d (i_coffd:%x q_coffd:%x)", + i_coff, q_coff, i_coffd, q_coffd); - /* Commit new I/Q value */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | - ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); + /* Commit new I/Q values (set enable bit last to match HAL sources) */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, i_coff); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, q_coff); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); /* Re-enable calibration -if we don't we'll commit * the same values again and again */ @@ -1873,7 +1874,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) break; case AR5K_ANTMODE_FIXED_A: def_ant = 1; - tx_ant = 0; + tx_ant = 1; use_def_for_tx = true; update_def_on_tx = false; use_def_for_rts = true; @@ -1882,7 +1883,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) break; case AR5K_ANTMODE_FIXED_B: def_ant = 2; - tx_ant = 0; + tx_ant = 2; use_def_for_tx = true; update_def_on_tx = false; use_def_for_rts = true; diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 4cb9c5d..1464f89 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -2187,6 +2187,7 @@ */ #define AR5K_PHY_IQ 0x9920 /* Register Address */ #define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ +#define AR5K_PHY_IQ_CORR_Q_Q_COFF_S 0 #define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ #define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 #define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index a35a7db..cbf28e3 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -851,12 +851,15 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, AR5K_INIT_CYCRSSI_THR1); - /* I/Q correction - * TODO: Per channel i/q infos ? */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CORR_ENABLE | - (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | - ee->ee_q_cal[ee_mode]); + /* I/Q correction (set enable bit last to match HAL sources) */ + /* TODO: Per channel i/q infos ? */ + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, + ee->ee_i_cal[ee_mode]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, + ee->ee_q_cal[ee_mode]); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); + } /* Heavy clipping -disable for now */ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) @@ -1379,11 +1382,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_set_sleep_clock(ah, true); /* - * Disable beacons and reset the register + * Disable beacons and reset the TSF */ - AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | - AR5K_BEACON_RESET_TSF); - + AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); + ath5k_hw_reset_tsf(ah); return 0; } diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index ac34a05..0e79e58 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1323,7 +1323,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, - u32 changed) + u32 changed, enum nl80211_channel_type oper_chan_type) { struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; @@ -1340,8 +1340,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) return; - if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || - sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) + if (oper_chan_type == NL80211_CHAN_HT40MINUS || + oper_chan_type == NL80211_CHAN_HT40PLUS) oper_cw40 = true; oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 47294f9..b2c8207 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2258,7 +2258,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) if (ATH_TXQ_SETUP(sc, i)) { txq = &sc->tx.txq[i]; - spin_lock(&txq->axq_lock); + spin_lock_bh(&txq->axq_lock); list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { @@ -2279,7 +2279,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) } } - spin_unlock(&txq->axq_lock); + spin_unlock_bh(&txq->axq_lock); } } } diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 63c2a7a..5c7aa1b 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -3177,14 +3177,27 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) int total_nr = 0; int i; struct pci_pool *pool; - u32 *virts[CB_NUMBER_OF_ELEMENTS_SMALL]; - dma_addr_t phys[CB_NUMBER_OF_ELEMENTS_SMALL]; + void **virts; + dma_addr_t *phys; IPW_DEBUG_TRACE("<< : \n"); + virts = kmalloc(sizeof(void *) * CB_NUMBER_OF_ELEMENTS_SMALL, + GFP_KERNEL); + if (!virts) + return -ENOMEM; + + phys = kmalloc(sizeof(dma_addr_t) * CB_NUMBER_OF_ELEMENTS_SMALL, + GFP_KERNEL); + if (!phys) { + kfree(virts); + return -ENOMEM; + } pool = pci_pool_create("ipw2200", priv->pci_dev, CB_MAX_LENGTH, 0, 0); if (!pool) { IPW_ERROR("pci_pool_create failed\n"); + kfree(phys); + kfree(virts); return -ENOMEM; } @@ -3254,6 +3267,8 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) pci_pool_free(pool, virts[i], phys[i]); pci_pool_destroy(pool); + kfree(phys); + kfree(virts); return ret; } diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index bf45391..a6d5e42 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h @@ -797,7 +797,7 @@ struct libipw_device { /* Probe / Beacon management */ struct list_head network_free_list; struct list_head network_list; - struct libipw_network *networks; + struct libipw_network *networks[MAX_NETWORK_COUNT]; int scans; int scan_age; diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index 1ae0b2b..2fa5586 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -67,16 +67,17 @@ void *libipw_wiphy_privid = &libipw_wiphy_privid; static int libipw_networks_allocate(struct libipw_device *ieee) { - if (ieee->networks) - return 0; - - ieee->networks = - kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network), - GFP_KERNEL); - if (!ieee->networks) { - printk(KERN_WARNING "%s: Out of memory allocating beacons\n", - ieee->dev->name); - return -ENOMEM; + int i, j; + + for (i = 0; i < MAX_NETWORK_COUNT; i++) { + ieee->networks[i] = kzalloc(sizeof(struct libipw_network), + GFP_KERNEL); + if (!ieee->networks[i]) { + LIBIPW_ERROR("Out of memory allocating beacons\n"); + for (j = 0; j < i; j++) + kfree(ieee->networks[j]); + return -ENOMEM; + } } return 0; @@ -97,15 +98,11 @@ static inline void libipw_networks_free(struct libipw_device *ieee) { int i; - if (!ieee->networks) - return; - - for (i = 0; i < MAX_NETWORK_COUNT; i++) - if (ieee->networks[i].ibss_dfs) - kfree(ieee->networks[i].ibss_dfs); - - kfree(ieee->networks); - ieee->networks = NULL; + for (i = 0; i < MAX_NETWORK_COUNT; i++) { + if (ieee->networks[i]->ibss_dfs) + kfree(ieee->networks[i]->ibss_dfs); + kfree(ieee->networks[i]); + } } void libipw_networks_age(struct libipw_device *ieee, @@ -130,7 +127,7 @@ static void libipw_networks_initialize(struct libipw_device *ieee) INIT_LIST_HEAD(&ieee->network_free_list); INIT_LIST_HEAD(&ieee->network_list); for (i = 0; i < MAX_NETWORK_COUNT; i++) - list_add_tail(&ieee->networks[i].list, + list_add_tail(&ieee->networks[i]->list, &ieee->network_free_list); } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 303cc81..e0678d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -184,7 +184,7 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) { int idx; - for (idx = 0; idx < IWL_RATE_COUNT; idx++) + for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++) if (iwl3945_rates[idx].plcp == plcp) return idx; return -1; @@ -805,7 +805,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, int sta_id, int tx_id) { u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; - u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1); + u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945); u16 rate_mask; int rate; u8 rts_retry_limit; @@ -2146,7 +2146,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) /* fill in channel group's nominal powers for each rate */ for (rate_index = 0; - rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) { + rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) { switch (rate_index) { case IWL_RATE_36M_INDEX_TABLE: if (i == 0) /* B/G */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6aeb82b..818367b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1463,59 +1463,66 @@ static void iwl_nic_start(struct iwl_priv *priv) } +static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); +static int iwl_mac_setup_register(struct iwl_priv *priv); + +static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) +{ + const char *name_pre = priv->cfg->fw_name_pre; + + if (first) + priv->fw_index = priv->cfg->ucode_api_max; + else + priv->fw_index--; + + if (priv->fw_index < priv->cfg->ucode_api_min) { + IWL_ERR(priv, "no suitable firmware found!\n"); + return -ENOENT; + } + + sprintf(priv->firmware_name, "%s%d%s", + name_pre, priv->fw_index, ".ucode"); + + IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n", + priv->firmware_name); + + return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, + &priv->pci_dev->dev, GFP_KERNEL, priv, + iwl_ucode_callback); +} + /** - * iwl_read_ucode - Read uCode images from disk file. + * iwl_ucode_callback - callback when firmware was loaded * - * Copy into buffers for card to fetch via bus-mastering + * If loaded successfully, copies the firmware into buffers + * for the card to fetch (via DMA). */ -static int iwl_read_ucode(struct iwl_priv *priv) +static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) { + struct iwl_priv *priv = context; struct iwl_ucode_header *ucode; - int ret = -EINVAL, index; - const struct firmware *ucode_raw; - const char *name_pre = priv->cfg->fw_name_pre; const unsigned int api_max = priv->cfg->ucode_api_max; const unsigned int api_min = priv->cfg->ucode_api_min; - char buf[25]; u8 *src; size_t len; u32 api_ver, build; u32 inst_size, data_size, init_size, init_data_size, boot_size; + int err; u16 eeprom_ver; - /* Ask kernel firmware_class module to get the boot firmware off disk. - * request_firmware() is synchronous, file is in memory on return. */ - for (index = api_max; index >= api_min; index--) { - sprintf(buf, "%s%d%s", name_pre, index, ".ucode"); - ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); - if (ret < 0) { - IWL_ERR(priv, "%s firmware file req failed: %d\n", - buf, ret); - if (ret == -ENOENT) - continue; - else - goto error; - } else { - if (index < api_max) - IWL_ERR(priv, "Loaded firmware %s, " - "which is deprecated. " - "Please use API v%u instead.\n", - buf, api_max); - - IWL_DEBUG_INFO(priv, "Got firmware '%s' file (%zd bytes) from disk\n", - buf, ucode_raw->size); - break; - } + if (!ucode_raw) { + IWL_ERR(priv, "request for firmware file '%s' failed.\n", + priv->firmware_name); + goto try_again; } - if (ret < 0) - goto error; + IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", + priv->firmware_name, ucode_raw->size); /* Make sure that we got at least the v1 header! */ if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { IWL_ERR(priv, "File size way too small!\n"); - ret = -EINVAL; - goto err_release; + goto try_again; } /* Data from ucode file: header followed by uCode images */ @@ -1540,10 +1547,9 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_ERR(priv, "Driver unable to support your firmware API. " "Driver supports v%u, firmware is v%u.\n", api_max, api_ver); - priv->ucode_ver = 0; - ret = -EINVAL; - goto err_release; + goto try_again; } + if (api_ver != api_max) IWL_ERR(priv, "Firmware has old API version. Expected v%u, " "got v%u. New firmware can be obtained " @@ -1585,6 +1591,12 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", boot_size); + /* + * For any of the failures below (before allocating pci memory) + * we will try to load a version with a smaller API -- maybe the + * user just got a corrupted version of the latest API. + */ + /* Verify size of file vs. image size info in file's header */ if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) + @@ -1594,41 +1606,35 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "uCode file size %d does not match expected size\n", (int)ucode_raw->size); - ret = -EINVAL; - goto err_release; + goto try_again; } /* Verify that uCode images will fit in card's SRAM */ if (inst_size > priv->hw_params.max_inst_size) { IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", inst_size); - ret = -EINVAL; - goto err_release; + goto try_again; } if (data_size > priv->hw_params.max_data_size) { IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", data_size); - ret = -EINVAL; - goto err_release; + goto try_again; } if (init_size > priv->hw_params.max_inst_size) { IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", init_size); - ret = -EINVAL; - goto err_release; + goto try_again; } if (init_data_size > priv->hw_params.max_data_size) { IWL_INFO(priv, "uCode init data len %d too large to fit in\n", init_data_size); - ret = -EINVAL; - goto err_release; + goto try_again; } if (boot_size > priv->hw_params.max_bsm_size) { IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n", boot_size); - ret = -EINVAL; - goto err_release; + goto try_again; } /* Allocate ucode buffers for card's bus-master loading ... */ @@ -1712,20 +1718,36 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); memcpy(priv->ucode_boot.v_addr, src, len); + /************************************************** + * This is still part of probe() in a sense... + * + * 9. Setup and register with mac80211 and debugfs + **************************************************/ + err = iwl_mac_setup_register(priv); + if (err) + goto out_unbind; + + err = iwl_dbgfs_register(priv, DRV_NAME); + if (err) + IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); + /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); - return 0; + return; + + try_again: + /* try next, if any */ + if (iwl_request_firmware(priv, false)) + goto out_unbind; + release_firmware(ucode_raw); + return; err_pci_alloc: IWL_ERR(priv, "failed to allocate pci memory\n"); - ret = -ENOMEM; iwl_dealloc_ucode_pci(priv); - - err_release: + out_unbind: + device_release_driver(&priv->pci_dev->dev); release_firmware(ucode_raw); - - error: - return ret; } static const char *desc_lookup_text[] = { @@ -2631,7 +2653,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) */ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX + 1; + hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; /* we create the 802.11 header and a zero-length SSID element */ hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; @@ -2667,21 +2689,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) /* we should be verifying the device is ready to be opened */ mutex_lock(&priv->mutex); - - /* fetch ucode file from disk, alloc and copy to bus-master buffers ... - * ucode filename and max sizes are card-specific. */ - - if (!priv->ucode_code.len) { - ret = iwl_read_ucode(priv); - if (ret) { - IWL_ERR(priv, "Could not read microcode: %d\n", ret); - mutex_unlock(&priv->mutex); - return ret; - } - } - ret = __iwl_up(priv); - mutex_unlock(&priv->mutex); if (ret) @@ -3654,17 +3662,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_power_initialize(priv); iwl_tt_initialize(priv); - /************************************************** - * 9. Setup and register with mac80211 and debugfs - **************************************************/ - err = iwl_mac_setup_register(priv); + err = iwl_request_firmware(priv, true); if (err) goto out_remove_sysfs; - err = iwl_dbgfs_register(priv, DRV_NAME); - if (err) - IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); - return 0; out_remove_sysfs: diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ab891b9..6054c5f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1132,6 +1132,7 @@ struct iwl_priv { u8 rev_id; /* uCode images, save to reload in case of failure */ + int fw_index; /* firmware we're trying to load */ u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ struct fw_desc ucode_code; /* runtime inst */ @@ -1142,6 +1143,7 @@ struct iwl_priv { struct fw_desc ucode_boot; /* bootstrap inst */ enum ucode_type ucode_type; u8 ucode_write_complete; /* the image write is complete */ + char firmware_name[25]; struct iwl_rxon_time_cmd rxon_timing; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index dd9ff2e..bd2f7c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -638,20 +638,9 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, if (left < 0) return 0; *pos++ = WLAN_EID_SSID; - if (!priv->is_internal_short_scan && - priv->scan_request->n_ssids) { - struct cfg80211_ssid *ssid = - priv->scan_request->ssids; - - /* Broadcast if ssid_len is 0 */ - *pos++ = ssid->ssid_len; - memcpy(pos, ssid->ssid, ssid->ssid_len); - pos += ssid->ssid_len; - len += 2 + ssid->ssid_len; - } else { - *pos++ = 0; - len += 2; - } + *pos++ = 0; + + len += 2; if (WARN_ON(left < ie_len)) return len; @@ -780,26 +769,20 @@ static void iwl_bg_request_scan(struct work_struct *data) if (priv->is_internal_short_scan) { IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); } else if (priv->scan_request->n_ssids) { + int i, p = 0; IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); - /* - * The first SSID to scan is stuffed into the probe request - * template and the remaining ones are handled through the - * direct_scan array. - */ - if (priv->scan_request->n_ssids > 1) { - int i, p = 0; - for (i = 1; i < priv->scan_request->n_ssids; i++) { - if (!priv->scan_request->ssids[i].ssid_len) - continue; - scan->direct_scan[p].id = WLAN_EID_SSID; - scan->direct_scan[p].len = - priv->scan_request->ssids[i].ssid_len; - memcpy(scan->direct_scan[p].ssid, - priv->scan_request->ssids[i].ssid, - priv->scan_request->ssids[i].ssid_len); - n_probes++; - p++; - } + for (i = 0; i < priv->scan_request->n_ssids; i++) { + /* always does wildcard anyway */ + if (!priv->scan_request->ssids[i].ssid_len) + continue; + scan->direct_scan[p].id = WLAN_EID_SSID; + scan->direct_scan[p].len = + priv->scan_request->ssids[i].ssid_len; + memcpy(scan->direct_scan[p].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + n_probes++; + p++; } is_active = true; } else diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h index a3a79b5..a855a99 100644 --- a/drivers/net/wireless/iwmc3200wifi/lmac.h +++ b/drivers/net/wireless/iwmc3200wifi/lmac.h @@ -262,7 +262,7 @@ struct iwm_ct_kill_cfg_cmd { /* Power Management */ #define POWER_TABLE_CMD 0x77 -#define SAVE_RESTORE_ADRESS_CMD 0x78 +#define SAVE_RESTORE_ADDRESS_CMD 0x78 #define REPLY_WATERMARK_CMD 0x79 #define PM_DEBUG_STATISTIC_NOTIFIC 0x7B #define PD_FLUSH_N_NOTIFICATION 0x7C diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 9f6d6bf..2887047 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1496,51 +1496,67 @@ static void set_multicast_list(struct usbnet *usbdev) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct dev_mc_list *mclist; - __le32 filter; - int ret, i, size; - char *buf; + __le32 filter, basefilter; + int ret; + char *mc_addrs = NULL; + int mc_count; - filter = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; + basefilter = filter = RNDIS_PACKET_TYPE_DIRECTED | + RNDIS_PACKET_TYPE_BROADCAST; - netif_addr_lock_bh(usbdev->net); if (usbdev->net->flags & IFF_PROMISC) { filter |= RNDIS_PACKET_TYPE_PROMISCUOUS | RNDIS_PACKET_TYPE_ALL_LOCAL; - } else if (usbdev->net->flags & IFF_ALLMULTI || - netdev_mc_count(usbdev->net) > priv->multicast_size) { + } else if (usbdev->net->flags & IFF_ALLMULTI) { + filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; + } + + if (filter != basefilter) + goto set_filter; + + /* + * mc_list should be accessed holding the lock, so copy addresses to + * local buffer first. + */ + netif_addr_lock_bh(usbdev->net); + mc_count = netdev_mc_count(usbdev->net); + if (mc_count > priv->multicast_size) { filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; - } else if (!netdev_mc_empty(usbdev->net)) { - size = min(priv->multicast_size, netdev_mc_count(usbdev->net)); - buf = kmalloc(size * ETH_ALEN, GFP_KERNEL); - if (!buf) { + } else if (mc_count) { + int i = 0; + + mc_addrs = kmalloc(mc_count * ETH_ALEN, GFP_ATOMIC); + if (!mc_addrs) { netdev_warn(usbdev->net, "couldn't alloc %d bytes of memory\n", - size * ETH_ALEN); + mc_count * ETH_ALEN); netif_addr_unlock_bh(usbdev->net); return; } - i = 0; - netdev_for_each_mc_addr(mclist, usbdev->net) { - if (i == size) - break; - memcpy(buf + i++ * ETH_ALEN, mclist->dmi_addr, ETH_ALEN); - } + netdev_for_each_mc_addr(mclist, usbdev->net) + memcpy(mc_addrs + i++ * ETH_ALEN, + mclist->dmi_addr, ETH_ALEN); + } + netif_addr_unlock_bh(usbdev->net); - ret = rndis_set_oid(usbdev, OID_802_3_MULTICAST_LIST, buf, - i * ETH_ALEN); - if (ret == 0 && i > 0) + if (filter != basefilter) + goto set_filter; + + if (mc_count) { + ret = rndis_set_oid(usbdev, OID_802_3_MULTICAST_LIST, mc_addrs, + mc_count * ETH_ALEN); + kfree(mc_addrs); + if (ret == 0) filter |= RNDIS_PACKET_TYPE_MULTICAST; else filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; netdev_dbg(usbdev->net, "OID_802_3_MULTICAST_LIST(%d, max: %d) -> %d\n", - i, priv->multicast_size, ret); - - kfree(buf); + mc_count, priv->multicast_size, ret); } - netif_addr_unlock_bh(usbdev->net); +set_filter: ret = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter, sizeof(filter)); if (ret < 0) { diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index ee34c13..9b04964 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -368,7 +368,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, /* * The encryption key doesn't fit within the CSR cache, - * this means we should allocate it seperately and use + * this means we should allocate it separately and use * rt2x00usb_vendor_request() to send the key to the hardware. */ reg = KEY_ENTRY(key->hw_key_idx); @@ -382,7 +382,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, /* * The driver does not support the IV/EIV generation * in hardware. However it demands the data to be provided - * both seperately as well as inside the frame. + * both separately as well as inside the frame. * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib * to ensure rt2x00lib will not strip the data from the * frame after the copy, now we must tell mac80211 diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index aca8c12..91cce2d 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1225,7 +1225,7 @@ MODULE_LICENSE("GPL"); #ifdef CONFIG_RT2800PCI_SOC static int rt2800soc_probe(struct platform_device *pdev) { - return rt2x00soc_probe(pdev, rt2800pci_ops); + return rt2x00soc_probe(pdev, &rt2800pci_ops); } static struct platform_driver rt2800soc_driver = { diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5e4ee20..d27d7d5 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -99,7 +99,7 @@ static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, * There are 2 variations of the rt2870 firmware. * a) size: 4kb * b) size: 8kb - * Note that (b) contains 2 seperate firmware blobs of 4k + * Note that (b) contains 2 separate firmware blobs of 4k * within the file. The first blob is the same firmware as (a), * but the second blob is for the additional chipsets. */ @@ -117,7 +117,7 @@ static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, /* * 8kb firmware files must be checked as if it were - * 2 seperate firmware files. + * 2 separate firmware files. */ while (offset < len) { if (!rt2800usb_check_crc(data + offset, 4096)) diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 70c04c2..28a1c46 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -109,7 +109,7 @@ struct rt2x00debug_intf { /* * HW crypto statistics. - * All statistics are stored seperately per cipher type. + * All statistics are stored separately per cipher type. */ struct rt2x00debug_crypto crypto_stats[CIPHER_MAX]; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b93731b..dd5ab8f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -394,7 +394,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, /* * Hardware might have stripped the IV/EIV/ICV data, * in that case it is possible that the data was - * provided seperately (through hardware descriptor) + * provided separately (through hardware descriptor) * in which case we should reinsert the data into the frame. */ if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) && diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 0b4801a..5b6b789 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -497,7 +497,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, /* * When hardware encryption is supported, and this frame * is to be encrypted, we should strip the IV/EIV data from - * the frame so we can provide it to the driver seperately. + * the frame so we can provide it to the driver separately. */ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index 4efdc96..111c0ff 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c @@ -112,6 +112,7 @@ exit_free_device: return retval; } +EXPORT_SYMBOL_GPL(rt2x00soc_probe); int rt2x00soc_remove(struct platform_device *pdev) { diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.h b/drivers/net/wireless/rt2x00/rt2x00soc.h index 4739edf..474cbfc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.h +++ b/drivers/net/wireless/rt2x00/rt2x00soc.h @@ -26,8 +26,6 @@ #ifndef RT2X00SOC_H #define RT2X00SOC_H -#define KSEG1ADDR(__ptr) __ptr - /* * SoC driver handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e2da928..1774727 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -476,7 +476,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, * The driver does not support the IV/EIV generation * in hardware. However it doesn't support the IV/EIV * inside the ieee80211 frame either, but requires it - * to be provided seperately for the descriptor. + * to be provided separately for the descriptor. * rt2x00lib will cut the IV/EIV data out of all frames * given to us by mac80211, but we must tell mac80211 * to generate the IV/EIV data. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index f39a8ed..290d70b 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -339,7 +339,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, * The driver does not support the IV/EIV generation * in hardware. However it doesn't support the IV/EIV * inside the ieee80211 frame either, but requires it - * to be provided seperately for the descriptor. + * to be provided separately for the descriptor. * rt2x00lib will cut the IV/EIV data out of all frames * given to us by mac80211, but we must tell mac80211 * to generate the IV/EIV data. @@ -439,7 +439,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, * The driver does not support the IV/EIV generation * in hardware. However it doesn't support the IV/EIV * inside the ieee80211 frame either, but requires it - * to be provided seperately for the descriptor. + * to be provided separately for the descriptor. * rt2x00lib will cut the IV/EIV data out of all frames * given to us by mac80211, but we must tell mac80211 * to generate the IV/EIV data. @@ -1661,7 +1661,7 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, /* * Hardware has stripped IV/EIV data from 802.11 frame during - * decryption. It has provided the data seperately but rt2x00lib + * decryption. It has provided the data separately but rt2x00lib * should decide if it should be reinserted. */ rxdesc->flags |= RX_FLAG_IV_STRIPPED; @@ -2352,6 +2352,8 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, + /* CEIVA */ + { USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) }, /* CNet */ { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 2d555cc..00e09e2 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -350,7 +350,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, first_idx = info->status.rates[0].idx; ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates)); retries = &zd_retry_rates[first_idx]; - ZD_ASSERT(0<=retry && retry<=retries->count); + ZD_ASSERT(1 <= retry && retry <= retries->count); info->status.rates[0].idx = retries->rate[0]; info->status.rates[0].count = 1; // (retry > 1 ? 2 : 1); @@ -360,7 +360,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, info->status.rates[i].count = 1; // ((i==retry-1) && success ? 1:2); } for (; i<IEEE80211_TX_MAX_RATES && i<retry; i++) { - info->status.rates[i].idx = retries->rate[retry-1]; + info->status.rates[i].idx = retries->rate[retry - 1]; info->status.rates[i].count = 1; // (success ? 1:2); } if (i<IEEE80211_TX_MAX_RATES) @@ -374,7 +374,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, * zd_mac_tx_failed - callback for failed frames * @dev: the mac80211 wireless device * - * This function is called if a frame couldn't be successfully be + * This function is called if a frame couldn't be successfully * transferred. The first frame from the tx queue, will be selected and * reported as error to the upper layers. */ @@ -424,12 +424,10 @@ void zd_mac_tx_failed(struct urb *urb) first_idx = info->status.rates[0].idx; ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates)); retries = &zd_retry_rates[first_idx]; - if (retry < 0 || retry > retries->count) { + if (retry <= 0 || retry > retries->count) continue; - } - ZD_ASSERT(0<=retry && retry<=retries->count); - final_idx = retries->rate[retry-1]; + final_idx = retries->rate[retry - 1]; final_rate = zd_rates[final_idx].hw_value; if (final_rate != tx_status->rate) { diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog deleted file mode 100644 index 8565bbb..0000000 --- a/drivers/parport/ChangeLog +++ /dev/null @@ -1,583 +0,0 @@ -2001-10-11 Tim Waugh <twaugh@redhat.com> - * parport_pc.c, parport_serial.c: Support for NetMos cards. - + Patch originally from Michael Reinelt <reinelt@eunet.at>. - -2002-04-25 Tim Waugh <twaugh@redhat.com> - - * parport_serial.c, parport_pc.c: Move some SIIG cards around. - Patch from Andrey Panin. - -2002-01-20 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_compat_write_block_pio, - parport_pc_ecp_write_block_pio, parport_pc_ecp_read_block_pio): - Use the default implementations if the caller wants to use - O_NONBLOCK. - -2002-02-25 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c: Make sure that priv->ctr_writable includes IntEn - even if IRQ is given as a parameter. - -2002-01-21 Tim Waugh <twaugh@redhat.com> - - * daisy.c: Apply patch from Max Vorobiev to make parport_daisy_select - work for ECP/EPP modes. - -2002-01-13 Niels Kristian Bech Jensen <nkbj@image.dk> - - * parport_pc.c: Change some occurrences of frob_set_mode to - ECR_WRITE. This fixes PLIP. - -2002-01-04 Tim Waugh <twaugh@redhat.com> - - * share.c (parport_claim_or_block): Sleep interruptibly to prevent - a possible deadlock. - -2001-12-07 Damian Gruszka <damian.gruszka@VisionSystems.de> - - * parport_pc.c (ECR_WRITE): Define. If there are forbidden bits - in the ECR register for some chips, this will be a useful place to - put that knowledge. - (change_mode): Use ECR_WRITE. - (parport_pc_restore_state): Likewise. - (parport_ECPPS2_supported): Likewise. - (parport_ECPEPP_supported): Likewise. - (irq_probe_EPP): Likewise. - (programmable_irq_support): Likewise. - (programmable_dma_support): Likewise. - (parport_pc_probe_port): Likewise. - - (frob_set_mode): New function. Set the mode bits of the ECR. - (get_fifo_residue): Use frob_set_mode. - (parport_pc_ecpepp_read_data): Likewise. - (parport_pc_ecpepp_write_data): Likewise. - (parport_pc_ecpepp_read_addr): Likewise. - (parport_pc_ecpepp_write_addr): Likewise. - (parport_pc_compat_write_block_pio): Likewise. - (parport_pc_ecp_write_block_pio): Likewise. - (parport_ECR_present): Likewise. - (parport_ECP_supported): Likewise. - (parport_EPP_supported): Likewise. - (parport_ECPEPP_supported): Likewise. - (programmable_irq_support): Likewise. - (irq_probe_ECP): Likewise. - (programmable_dma_support): Likewise. - - (parport_pc_enable_irq): Only enable interrupts if we know which - IRQ line they will come from. - (parport_pc_init_state): Set nErrIntrEn at initialisation. - (parport_pc_restore_state): Only write writable bits of CTR. - (parport_irq_probe): If no IRQ is found, take ackIntEn out of the - writable bit set. - -2001-12-07 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_fifo_write_block_pio): Correct typo. - (parport_pc_init_state): Only set ackIntEn if we know which IRQ - line the interrupts will come from. - -2001-12-07 Tim Waugh <twaugh@redhat.com> - - * ieee1284_ops.c (parport_ieee1284_epp_write_addr, - parport_ieee1284_epp_read_addr): Actually do something useful. - -2001-12-07 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (dmaval): Don't use DMA by default. It seems to be - too buggy at the moment. Use 'dma=auto' to restore the previous - behaviour. - -2001-12-07 Tim Waugh <twaugh@redhat.com> - - * daisy.c (DEBUG): Undefine. - -2001-12-06 Tim Waugh <twaugh@redhat.com> - - * ieee1284_ops.c (parport_ieee1284_ecp_read_data): Mask off - PARPORT_CONTROL_AUTOFD as well. Bug spotted by Joe - <joeja@mindspring.com>. - -2001-12-03 Rich Liu <Rich.Liu@ite.com.tw> - - * parport_pc.c (sio_ite_8872_probe): ITE8873 is a single-port - serial board, not a serial+parallel. - -2001-11-30 Niels Kristian Bech Jensen <nkbj@image.dk> - - * parport_pc.c: Fix compiler warning. - -2001-11-14 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_pci_probe): Hooks for PCI cards before - and after probing for ports. - * parport_serial.c (parport_register): Likewise. - -2001-11-12 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (init_module): Warn when parameters are ignored. - -2001-11-01 Damian Gruszka <damian.gruszka@VisionSystems.de> - - * parport_serial.c (serial_register): Set base_baud before - calling register_serial. - -2001-10-26 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_irq_probe): When ECR programmable IRQ - support fails, generate interrupts using the FIFO even if we don't - want to use the FIFO for real data transfers. - (parport_pc_probe_port): Display the ECR address if we have an - ECR, not just if we will use the FIFO. - -2001-10-24 Dave Strauss <D.Strauss@motorola.com> - - * parport_pc.c (parport_pc_compat_write_block_pio, - parport_pc_ecp_write_block_pio): Allow a few seconds for an ECP - transfer to finish up. - -2001-10-11 Tim Waugh <twaugh@redhat.com> - - * parport_pc (sio_ite_8872_probe): New function, submitted by Rich - Liu from ITE. Cleaned up, removed bogus phys_to_virt calls. - -2001-10-24 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c: Support for AKS AladdinCARD. Patch from - Aladdin Knowledge Systems (Christian Groessler). - -2001-10-24 Tim Waugh <twaugh@redhat.com> - - * ieee1284_ops.c (parport_ieee1284_ecp_read_data): Try to minimise - turnaround time. - - * ieee1284.c (parport_poll_peripheral): Try a couple of times - first without delaying. - -2001-10-10 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c: Support for OX16PCI954 PCI card. - -2001-10-10 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c: Support for OX12PCI840 PCI card (reported by - mk@daveg.com). Lock-ups diagnosed by Ronnie Arosa (and now we - just don't trust its ECR). - -2001-10-10 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> - - * parport_pc.c: Support for AVLAB cards. - -2001-10-10 Tim Waugh <twaugh@redhat.com> - - * ieee1284_ops.c (ecp_forward_to_reverse, ecp_reverse_to_forward): - Remember to retry direction switch if it fails. Patch from David - Lambert. - -2001-10-08 David C. Hansen <haveblue@us.ibm.com> - - * share.c: Make driverlist_lock and parportlist_lock static. - -2001-10-08 Philip Blundell <philb@gnu.org> - - * parport_pc.c: New modular parameter verbose_logging. - Make port->modes indicate the modes that we are prepared to use, - rather than the modes that are available. - -2001-10-07 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_probe_port): Fix memory leak spotted by - Kipp Cannon. - -2001-10-07 Tim Waugh <twaugh@redhat.com> - - * parport_serial.c: Remove NetMos support, since it causes problems - for some people. - -2001-08-30 Tim Waugh <twaugh@redhat.com> - - * parport_serial.c (parport_serial_pci_probe): Clean-up on partial - registration failure. - -2001-08-14 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_init_superio): Allow for more than one - SuperIO device. Patch from Rich Lio (ITE). - -2001-08-11 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c: Support for Titan Electronics cards. - -2001-08-08 Tim Waugh <twaugh@redhat.com> - - * share.c (parport_unregister_device): Remove device from wait list - too. - -2001-06-20 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c: Make 'io_hi=0' work. - -2001-05-31 Tim Waugh <twaugh@redhat.com> - - * parport_serial.c: New file. - -2001-06-05 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_unregister_port): New exported function. - Do the opposite of parport_pc_probe_port. - (cleanup_module): Use it. - -2001-05-22 Juan Quintela <quintela@mandrakesoft.com> - - * parport_amiga.c: Set printk levels. - * parport_gsc.c: Likewise. - * parport_mfc3.c: Likewise. - * parport_pc.c: Likewise. - * parport_sunbpp.c: Likewise. - * probe.c: Likewise. - * share.c: Likewise. - -2001-05-10 Fred Barnes <frmb2@ukc.ac.uk> - - * parport_pc.c (parport_pc_epp_read_data): added support for - reading from a w91284pic peripheral, flag is PARPORT_W91284PIC. - -2001-05-07 Fred Barnes <frmb2@ukc.ac.uk> - - * parport_pc.c (parport_pc_epp_read_data, - parport_pc_epp_write_data, parport_pc_epp_read_addr, - parport_pc_epp_write_addr): support for fast reads/writes using - the PARPORT_EPP_FAST flag. - - * ieee1284.c (parport_read, parport_write): added code to handle - software EPP mode (IEEE1284_MODE_EPPSWE). Added code to allow - BYTE mode reverse transfers (previously always went for NIBBLE - mode). - - * ieee1284_ops.c (parport_ieee1284_epp_read_data, - parport_ieee1284_epp_write_data): fixed various polarity problems. - Also (theoretically) fixed address versions (.._addr), but no - hardware to test this on. - - * parport_pc.h: added parport_dump_state() function for debugging. - Needs to have DEBUG_PARPORT to be defined for it to be included. - -2001-05-03 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c: Fix the compile problem I introduce from the last - change. - -2001-04-20 Paul Gortmaker <p_gortmaker@yahoo.com> - - * parport_pc.c: Cut down the size quite a bit (more than 4k off - the object, about 1k off the zImage) for the older non-PCI - machines which are typically resource starved anyway... - -2001-03-26 R Horn <rjh@world.std.com> - - * parport_pc.c: Some commentary changes. - -2001-04-19 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_probe_port): Remove __devinit - attribute. Export unconditionally. - -2001-04-14 Jeff Garzik <jgarzik@pobox.com> - - Merged: 2001-03-30 Tim Waugh <twaugh@redhat.com> - - * drivers/parport/parport_pc.c: Make Via SuperIO chipsets behave - like everything else with respect to irq= and dma= parameters. - -2001-04-08 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_save_state): Read from the soft copy of - the control port. - (parport_pc_restore_state): Update the soft copy of the control - port. - -2001-03-26 Tim Waugh <twaugh@redhat.com> - - * share.c (parport_find_number, parport_find_base): Trigger - a lowlevel driver load if there are no ports yet. - -2001-03-26 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_ECP_supported): Remove the IRQ conflict - check since it seems totally unreliable. - -2001-03-02 Tim Waugh <twaugh@redhat.com> - - * ieee1284_ops.c (parport_ieee1284_read_nibble): Reset nAutoFd - on timeout. Matches 2.2.x behaviour. - -2001-03-02 Andrew Morton - - * parport_pc.c (registered_parport): New static variable. - (parport_pc_find_ports): Set it when we register PCI driver. - (init_module): Unregister PCI driver if necessary when we - fail. - -2001-03-02 Tim Waugh <twaugh@redhat.com> - - * ieee1284_ops.c (parport_ieee1284_write_compat): Don't use - down_trylock to reset the IRQ count. Don't even use sema_init, - because it's not even necessary to reset the count. I can't - remember why we ever did. - -2001-01-04 Peter Osterlund <peter.osterlund@mailbox.swipnet.se> - - * ieee1284.c (parport_negotiate): Fix missing printk argument. - -2001-01-03 Paul Schleger <Paul.Schleger@t-online.de> - - * probe.c (parse_data): Get rid of trailing blanks in values. - Needed for XEROX XJ8C printer. - -2001-01-03 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_probe_port): Say something when probes - are omitted. - -2001-01-03 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (sio_via_686a_probe): Correct dma=255 fix. - -2000-11-21 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_ecp_write_block_pio): Fix - reverse-to-forward logic. Spotted by Roland Kuck - <rci@cityweb.de>. - -2000-09-16 Cesar Eduardo Barros <cesarb@nitnet.com.br> - - * parport_pc.c (sio_via_686a_probe): Handle case - where hardware returns 255 for IRQ or DMA. - -2000-07-20 Eddie C. Dost <ecd@skynet.be> - - * share.c (attach_driver_chain): attach[i](port) needs to be - replaced by attach[count](port). - -2000-07-20 Eddie C. Dost <ecd@skynet.be> - - * daisy.c (add_dev): kmalloc args are in wrong order. - -2000-07-12 Tim Waugh <twaugh@redhat.com> - - * share.c: Documentation for parport_{get,port}_port, - parport_find_{number,base}. - -2000-07-12 Tim Waugh <twaugh@redhat.com> - - * share.c (parport_unregister_device): Remove unneeded locking - (test cad==dev). - (parport_claim): Likewise. - (parport_find_number): New function. - -2000-07-12 Tim Waugh <twaugh@redhat.com> - - * share.c (parport_register_port): Hold the parportlist_lock while - looking for a free parport number. - (parport_register_driver): Make sure that attach can block. - (attach_driver_chain): Likewise. - -2000-07-12 Tim Waugh <twaugh@redhat.com> - - * share.c (call_driver_chain): Do reference counting things. - (parport_get_port): New function. - (parport_put_port): New function. - (parport_register_port): Initialise reference count to zero. - (parport_unregister_port): Check reference count rather than - driver list to see if we can free the port. - -2000-07-12 Tim Waugh <twaugh@redhat.com> - - * share.c: Clarifications in doc comments. - -2000-07-12 Tim Waugh <twaugh@redhat.com> - - * share.c (parport_unregister_port): Fix typo in comment. - -2000-07-11 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> - - * parport_pc.c: Support for the full range of Timedia cards. - -2000-07-08 Tim Waugh <twaugh@redhat.com> - - * daisy.c: License block comments as part of parportbook. - * ieee1284.c: Likewise. - * share.c: Likewise. - -2000-06-30 Petr Vandrovec <vandrove@vc.cvut.cz> - - * procfs.c (do_hardware_modes): Generated string can be up to 34 - chars long. - -2000-06-20 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> - - * parport_pc.c (parport_pc_compat_write_block_pio): Warn about - change_mode failures. - (parport_pc_ecp_write_block_pio): Likewise. - (parport_pc_ecp_read_block_pio): Likewise. - -2000-06-20 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> - - * parport_pc.c (parport_SPP_supported): Warn more about possibly - incorrect parameters. - -2000-06-15 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_ECP_supported): Set PARPORT_MODE_COMPAT - for ECP ports, since they can all do hardware accelerated - compatibility mode (I assume). - -2000-06-13 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (cleanup_module): Remark about possible bugs. - -2000-06-13 Tim Waugh <twaugh@redhat.com> - - * procfs.c: Break 'hardware' out into separate files. - -2000-05-28 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> - - * Fix PCI ID printk for non-superio PCI cards. - -2000-05-28 Tim Waugh <twaugh@redhat.com> - - * share.c (call_driver_chain): Get the driverlist_lock. - (parport_register_device): Make sure that port->devices always - looks consistent. - (parport_register_driver): Ensure that parport drivers are given - parameters that are valid for the duration of the callback by - locking the portlist against changes. - (parport_unregister_driver): Likewise. - (parport_claim): Don't overwrite flags. - -2000-05-28 Tim Waugh <twaugh@redhat.com> - - * daisy.c (assign_addrs): Avoid double-probing daisy-chain devices - if the first probe succeeds. - -2000-05-16 Tim Waugh <twaugh@redhat.com> - - * share.c (parport_claim): Fix SMP race. - -2000-05-15 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> - - * parport_pc.c (parport_pc_compat_write_block_pio): Check for - timeouts. - (parport_pc_ecp_write_block_pio): Likewise. - (parport_pc_ecp_read_block_pio): Likewise. - -2000-05-02 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> - - * parport_pc.c: PCI SYBA patch and verbose PCI detection. - -2000-05-02 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> - - * parport_pc.c (decode_smsc): Fix SMSC 665/666 identification. - -2000-04-28 Tim Waugh <twaugh@redhat.com> - - * ieee1284.c: Short function descriptions can't be multiline. - - * daisy.c: Short function descriptions can't be multiline. - -2000-04-19 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_fifo_write_block_dma): Make maxlen - calculation a bit clearer. - - * ieee1284.c (parport_negotiate): Turn on data line drivers. - - * ieee1284_ops.c (parport_ieee1284_read_byte): Turn off data line - drivers. - (parport_ieee1284_write_compat): Turn on data line drivers. - - * daisy.c (assign_addrs): Turn on data line drivers. - (cpp_mux): Likewise. - (cpp_daisy): Likewise. - -2000-04-04 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c: Add support for another PCI card. - -2000-04-04 Tim Waugh <twaugh@redhat.com> - - * daisy.c: Documentation in kernel-doc format. - - * ieee1284.c: Likewise. - - * share.c: Likewise. - -2000-04-01 Tim Waugh <twaugh@redhat.com> - - * share.c (parport_register_device): Need to hold the module - reference counts before sleeping. - -2000-03-27 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_ecp_read_block_pio): Correct operation - when peripheral is trying to send data when we stop listening. - -2000-03-22 Tim Waugh <twaugh@redhat.com> - - * init.c (parport_setup): Fix return value. - -2000-03-21 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_pci_probe): Fix return value; call - pci_enable_device. - -2000-03-16 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_ECP_supported): This seems to trigger on - machines that don't have an IRQ conflict; toned down the warning - message accordingly. - -2000-03-16 Gunther Mayer <gunther.mayer@braunschweig.netsurf.de> - - * parport_pc.c (show_parconfig_smsc37c669): Fix typo. - (decode_winbond): More IDs. - (winbond_check): Protect against false positives. - (winbond_check2): Likewise. - (smsc_check): Likewise. - -2000-03-15 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (cleanup_module): Don't call pci_unregister_driver - if we didn't call pci_register_driver first. - -2000-03-13 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (parport_pc_init): Moved from asm/parport.h. - - * Config.in: CONFIG_PARPORT_PC_SUPERIO: new option. - - * parport_pc.c (show_parconfig_smsc37c669): Make __devinit. - (show_parconfig_winbond): Likewise. - (decode_winbond): Likewise. - (decode_smsc): Likewise. - (winbond_check): Likewise. - (winbond_check2): Likewise. - (smsc_check): Likewise. - (detect_and_report_winbond): Likewise. - (detect_and_report_smsc): Likewise. - (get_superio_dma): Likewise. - (get_superio_irq): Likewise. - (parport_pc_find_isa_ports): New function. - (parport_pc_find_ports): New function. - (init_module): Make superio a config option, not a parameter. - -2000-03-10 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c (decode_winbond): Use correct 83877ATF chip ID. - (decode_winbond): Fix typo. - -2000-03-09 Tim Waugh <twaugh@redhat.com> - - * parport_pc.c: Integrate SuperIO PCI probe with normal PCI card - probe, so that the MODULE_DEVICE_TABLE is complete. - diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cb2fd01..b5dad9f3 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -749,6 +749,24 @@ static int acpiphp_bus_trim(acpi_handle handle) return retval; } +static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) +{ + struct acpiphp_func *func; + union acpi_object params[2]; + struct acpi_object_list arg_list; + + list_for_each_entry(func, &slot->funcs, sibling) { + arg_list.count = 2; + arg_list.pointer = params; + params[0].type = ACPI_TYPE_INTEGER; + params[0].integer.value = ACPI_ADR_SPACE_PCI_CONFIG; + params[1].type = ACPI_TYPE_INTEGER; + params[1].integer.value = 1; + /* _REG is optional, we don't care about if there is failure */ + acpi_evaluate_object(func->handle, "_REG", &arg_list, NULL); + } +} + /** * enable_device - enable, configure a slot * @slot: slot to be enabled @@ -805,6 +823,7 @@ static int __ref enable_device(struct acpiphp_slot *slot) pci_bus_assign_resources(bus); acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); + acpiphp_set_acpi_region(slot); pci_enable_bridges(bus); pci_bus_add_devices(bus); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 897fa5c..cb1dd5f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1583,8 +1583,10 @@ void pci_pm_init(struct pci_dev *dev) int pm; u16 pmc; + pm_runtime_forbid(&dev->dev); device_enable_async_suspend(&dev->dev); dev->wakeup_prepared = false; + dev->pm_cap = 0; /* find PCI PM capability in list */ @@ -2296,35 +2298,6 @@ void pci_msi_off(struct pci_dev *dev) } } -#ifndef HAVE_ARCH_PCI_SET_DMA_MASK -/* - * These can be overridden by arch-specific implementations - */ -int -pci_set_dma_mask(struct pci_dev *dev, u64 mask) -{ - if (!pci_dma_supported(dev, mask)) - return -EIO; - - dev->dma_mask = mask; - dev_dbg(&dev->dev, "using %dbit DMA mask\n", fls64(mask)); - - return 0; -} - -int -pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) -{ - if (!pci_dma_supported(dev, mask)) - return -EIO; - - dev->dev.coherent_dma_mask = mask; - dev_dbg(&dev->dev, "using %dbit consistent DMA mask\n", fls64(mask)); - - return 0; -} -#endif - #ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) { @@ -3066,8 +3039,6 @@ EXPORT_SYMBOL(pci_set_mwi); EXPORT_SYMBOL(pci_try_set_mwi); EXPORT_SYMBOL(pci_clear_mwi); EXPORT_SYMBOL_GPL(pci_intx); -EXPORT_SYMBOL(pci_set_dma_mask); -EXPORT_SYMBOL(pci_set_consistent_dma_mask); EXPORT_SYMBOL(pci_assign_resource); EXPORT_SYMBOL(pci_find_parent_resource); EXPORT_SYMBOL(pci_select_bars); diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index de6bc33..db79ca6 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -21,11 +21,18 @@ #include "sa1111_generic.h" +#define IDX_IRQ_S0_READY_NINT (0) +#define IDX_IRQ_S0_CD_VALID (1) +#define IDX_IRQ_S0_BVD1_STSCHG (2) +#define IDX_IRQ_S1_READY_NINT (3) +#define IDX_IRQ_S1_CD_VALID (4) +#define IDX_IRQ_S1_BVD1_STSCHG (5) + static struct pcmcia_irqs irqs[] = { - { 0, IRQ_S0_CD_VALID, "SA1111 PCMCIA card detect" }, - { 0, IRQ_S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" }, - { 1, IRQ_S1_CD_VALID, "SA1111 CF card detect" }, - { 1, IRQ_S1_BVD1_STSCHG, "SA1111 CF BVD1" }, + { 0, NO_IRQ, "SA1111 PCMCIA card detect" }, + { 0, NO_IRQ, "SA1111 PCMCIA BVD1" }, + { 1, NO_IRQ, "SA1111 CF card detect" }, + { 1, NO_IRQ, "SA1111 CF BVD1" }, }; static int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *skt) @@ -136,7 +143,9 @@ int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops, s->soc.ops = ops; s->soc.socket.owner = ops->owner; s->soc.socket.dev.parent = &dev->dev; - s->soc.socket.pci_irq = s->soc.nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT; + s->soc.socket.pci_irq = s->soc.nr ? + dev->irq[IDX_IRQ_S0_READY_NINT] : + dev->irq[IDX_IRQ_S1_READY_NINT]; s->dev = dev; ret = add(&s->soc); @@ -162,6 +171,12 @@ static int pcmcia_probe(struct sa1111_dev *dev) base = dev->mapbase; + /* Initialize PCMCIA IRQs */ + irqs[0].irq = dev->irq[IDX_IRQ_S0_CD_VALID]; + irqs[1].irq = dev->irq[IDX_IRQ_S0_BVD1_STSCHG]; + irqs[2].irq = dev->irq[IDX_IRQ_S1_CD_VALID]; + irqs[3].irq = dev->irq[IDX_IRQ_S1_BVD1_STSCHG]; + /* * Initialise the suspend state. */ diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 1b1dddb..bed764e 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -142,7 +142,7 @@ static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap; static struct input_dev *dell_wmi_input_dev; -static struct key_entry *dell_wmi_get_entry_by_scancode(int code) +static struct key_entry *dell_wmi_get_entry_by_scancode(unsigned int code) { struct key_entry *key; @@ -153,7 +153,7 @@ static struct key_entry *dell_wmi_get_entry_by_scancode(int code) return NULL; } -static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode) +static struct key_entry *dell_wmi_get_entry_by_keycode(unsigned int keycode) { struct key_entry *key; @@ -164,8 +164,8 @@ static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode) return NULL; } -static int dell_wmi_getkeycode(struct input_dev *dev, int scancode, - int *keycode) +static int dell_wmi_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode); @@ -177,13 +177,11 @@ static int dell_wmi_getkeycode(struct input_dev *dev, int scancode, return -EINVAL; } -static int dell_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int dell_wmi_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; + unsigned int old_keycode; key = dell_wmi_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 7ccf33c..5608636 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -278,7 +278,7 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); -static struct key_entry *hp_wmi_get_entry_by_scancode(int code) +static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code) { struct key_entry *key; @@ -289,7 +289,7 @@ static struct key_entry *hp_wmi_get_entry_by_scancode(int code) return NULL; } -static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode) +static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode) { struct key_entry *key; @@ -300,7 +300,8 @@ static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode) return NULL; } -static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int hp_wmi_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode); @@ -312,13 +313,11 @@ static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) return -EINVAL; } -static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int hp_wmi_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; + unsigned int old_keycode; key = hp_wmi_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index fe7cf01..c9fc479 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -200,7 +200,7 @@ static struct acpi_driver acpi_pcc_driver = { }; #define KEYMAP_SIZE 11 -static const int initial_keymap[KEYMAP_SIZE] = { +static const unsigned int initial_keymap[KEYMAP_SIZE] = { /* 0 */ KEY_RESERVED, /* 1 */ KEY_BRIGHTNESSDOWN, /* 2 */ KEY_BRIGHTNESSUP, @@ -222,7 +222,7 @@ struct pcc_acpi { struct acpi_device *device; struct input_dev *input_dev; struct backlight_device *backlight; - int keymap[KEYMAP_SIZE]; + unsigned int keymap[KEYMAP_SIZE]; }; struct pcc_keyinput { @@ -445,7 +445,8 @@ static struct attribute_group pcc_attr_group = { /* hotkey input device driver */ -static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int pcc_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct pcc_acpi *pcc = input_get_drvdata(dev); @@ -457,7 +458,7 @@ static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode) return 0; } -static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode) +static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode) { int i; @@ -469,7 +470,8 @@ static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode) return 0; } -static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int pcc_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct pcc_acpi *pcc = input_get_drvdata(dev); int oldkeycode; @@ -477,9 +479,6 @@ static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode) if (scancode >= ARRAY_SIZE(pcc->keymap)) return -EINVAL; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - oldkeycode = pcc->keymap[scancode]; pcc->keymap[scancode] = keycode; diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 3f71a60..5a3d851 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -145,7 +145,7 @@ struct sony_laptop_input_s { struct input_dev *key_dev; struct kfifo fifo; spinlock_t fifo_lock; - struct workqueue_struct *wq; + struct timer_list release_key_timer; }; static struct sony_laptop_input_s sony_laptop_input = { @@ -299,20 +299,26 @@ static int sony_laptop_input_keycode_map[] = { }; /* release buttons after a short delay if pressed */ -static void do_sony_laptop_release_key(struct work_struct *work) +static void do_sony_laptop_release_key(unsigned long unused) { struct sony_laptop_keypress kp; + unsigned long flags; + + spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags); - while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, - sizeof(kp), &sony_laptop_input.fifo_lock) - == sizeof(kp)) { - msleep(10); + if (kfifo_out(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { input_report_key(kp.dev, kp.key, 0); input_sync(kp.dev); } + + /* If there is something in the fifo schedule next release. */ + if (kfifo_len(&sony_laptop_input.fifo) != 0) + mod_timer(&sony_laptop_input.release_key_timer, + jiffies + msecs_to_jiffies(10)); + + spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags); } -static DECLARE_WORK(sony_laptop_release_key_work, - do_sony_laptop_release_key); /* forward event to the input subsystem */ static void sony_laptop_report_input_event(u8 event) @@ -366,13 +372,13 @@ static void sony_laptop_report_input_event(u8 event) /* we emit the scancode so we can always remap the key */ input_event(kp.dev, EV_MSC, MSC_SCAN, event); input_sync(kp.dev); - kfifo_in_locked(&sony_laptop_input.fifo, - (unsigned char *)&kp, sizeof(kp), - &sony_laptop_input.fifo_lock); - if (!work_pending(&sony_laptop_release_key_work)) - queue_work(sony_laptop_input.wq, - &sony_laptop_release_key_work); + /* schedule key release */ + kfifo_in_locked(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp), + &sony_laptop_input.fifo_lock); + mod_timer(&sony_laptop_input.release_key_timer, + jiffies + msecs_to_jiffies(10)); } else dprintk("unknown input event %.2x\n", event); } @@ -390,27 +396,21 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) /* kfifo */ spin_lock_init(&sony_laptop_input.fifo_lock); - error = - kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); + error = kfifo_alloc(&sony_laptop_input.fifo, + SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); if (error) { printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); goto err_dec_users; } - /* init workqueue */ - sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); - if (!sony_laptop_input.wq) { - printk(KERN_ERR DRV_PFX - "Unable to create workqueue.\n"); - error = -ENXIO; - goto err_free_kfifo; - } + setup_timer(&sony_laptop_input.release_key_timer, + do_sony_laptop_release_key, 0); /* input keys */ key_dev = input_allocate_device(); if (!key_dev) { error = -ENOMEM; - goto err_destroy_wq; + goto err_free_kfifo; } key_dev->name = "Sony Vaio Keys"; @@ -419,18 +419,15 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) key_dev->dev.parent = &acpi_device->dev; /* Initialize the Input Drivers: special keys */ - set_bit(EV_KEY, key_dev->evbit); - set_bit(EV_MSC, key_dev->evbit); - set_bit(MSC_SCAN, key_dev->mscbit); + input_set_capability(key_dev, EV_MSC, MSC_SCAN); + + __set_bit(EV_KEY, key_dev->evbit); key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); key_dev->keycode = &sony_laptop_input_keycode_map; - for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { - if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { - set_bit(sony_laptop_input_keycode_map[i], - key_dev->keybit); - } - } + for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) + __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit); + __clear_bit(KEY_RESERVED, key_dev->keybit); error = input_register_device(key_dev); if (error) @@ -450,9 +447,8 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) jog_dev->id.vendor = PCI_VENDOR_ID_SONY; key_dev->dev.parent = &acpi_device->dev; - jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); - jog_dev->relbit[0] = BIT_MASK(REL_WHEEL); + input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE); + input_set_capability(jog_dev, EV_REL, REL_WHEEL); error = input_register_device(jog_dev); if (error) @@ -473,9 +469,6 @@ err_unregister_keydev: err_free_keydev: input_free_device(key_dev); -err_destroy_wq: - destroy_workqueue(sony_laptop_input.wq); - err_free_kfifo: kfifo_free(&sony_laptop_input.fifo); @@ -486,12 +479,23 @@ err_dec_users: static void sony_laptop_remove_input(void) { - /* cleanup only after the last user has gone */ + struct sony_laptop_keypress kp = { NULL }; + + /* Cleanup only after the last user has gone */ if (!atomic_dec_and_test(&sony_laptop_input.users)) return; - /* flush workqueue first */ - flush_workqueue(sony_laptop_input.wq); + del_timer_sync(&sony_laptop_input.release_key_timer); + + /* + * Generate key-up events for remaining keys. Note that we don't + * need locking since nobody is adding new events to the kfifo. + */ + while (kfifo_out(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { + input_report_key(kp.dev, kp.key, 0); + input_sync(kp.dev); + } /* destroy input devs */ input_unregister_device(sony_laptop_input.key_dev); @@ -502,7 +506,6 @@ static void sony_laptop_remove_input(void) sony_laptop_input.jog_dev = NULL; } - destroy_workqueue(sony_laptop_input.wq); kfifo_free(&sony_laptop_input.fifo); } diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e7b0c3b..c64e352 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -1668,7 +1668,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv) * Table of recommended minimum BIOS versions * * Reasons for listing: - * 1. Stable BIOS, listed because the unknown ammount of + * 1. Stable BIOS, listed because the unknown amount of * bugs and bad ACPI behaviour on older versions * * 2. BIOS or EC fw with known bugs that trigger on Linux @@ -7108,7 +7108,7 @@ static struct ibm_struct volume_driver_data = { * * Fan speed changes of any sort (including those caused by the * disengaged mode) are usually done slowly by the firmware as the - * maximum ammount of fan duty cycle change per second seems to be + * maximum amount of fan duty cycle change per second seems to be * limited. * * Reading is not available if GFAN exists. diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index 02f3d4e..4d6516f 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -46,7 +46,7 @@ static struct tps_key_entry topstar_keymap[] = { { } }; -static struct tps_key_entry *tps_get_key_by_scancode(int code) +static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code) { struct tps_key_entry *key; @@ -57,7 +57,7 @@ static struct tps_key_entry *tps_get_key_by_scancode(int code) return NULL; } -static struct tps_key_entry *tps_get_key_by_keycode(int code) +static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code) { struct tps_key_entry *key; @@ -126,7 +126,8 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) return 0; } -static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int topstar_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct tps_key_entry *key = tps_get_key_by_scancode(scancode); @@ -137,14 +138,12 @@ static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) return 0; } -static int topstar_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int topstar_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct tps_key_entry *key; int old_keycode; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - key = tps_get_key_by_scancode(scancode); if (!key) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 405b969..789240d 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -745,7 +745,7 @@ static struct backlight_ops toshiba_backlight_data = { .update_status = set_lcd_status, }; -static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code) +static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code) { struct key_entry *key; @@ -756,7 +756,7 @@ static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code) return NULL; } -static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code) +static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code) { struct key_entry *key; @@ -767,8 +767,8 @@ static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code) return NULL; } -static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode, - int *keycode) +static int toshiba_acpi_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode); @@ -780,14 +780,11 @@ static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode, return -EINVAL; } -static int toshiba_acpi_setkeycode(struct input_dev *dev, int scancode, - int keycode) +static int toshiba_acpi_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; + unsigned int old_keycode; key = toshiba_acpi_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index c790e0c..ff05e61 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -99,6 +99,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(present), POWER_SUPPLY_ATTR(online), POWER_SUPPLY_ATTR(technology), + POWER_SUPPLY_ATTR(cycle_count), POWER_SUPPLY_ATTR(voltage_max), POWER_SUPPLY_ATTR(voltage_min), POWER_SUPPLY_ATTR(voltage_max_design), diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig index cc2eb8e..1afe4e0 100644 --- a/drivers/pps/Kconfig +++ b/drivers/pps/Kconfig @@ -30,4 +30,6 @@ config PPS_DEBUG messages to the system log. Select this if you are having a problem with PPS support and want to see more of what is going on. +source drivers/pps/clients/Kconfig + endmenu diff --git a/drivers/pps/Makefile b/drivers/pps/Makefile index 19ea582..98960dd 100644 --- a/drivers/pps/Makefile +++ b/drivers/pps/Makefile @@ -4,5 +4,6 @@ pps_core-y := pps.o kapi.o sysfs.o obj-$(CONFIG_PPS) := pps_core.o +obj-y += clients/ ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig new file mode 100644 index 0000000..4e801bd --- /dev/null +++ b/drivers/pps/clients/Kconfig @@ -0,0 +1,25 @@ +# +# PPS clients configuration +# + +if PPS + +comment "PPS clients support" + +config PPS_CLIENT_KTIMER + tristate "Kernel timer client (Testing client, use for debug)" + help + If you say yes here you get support for a PPS debugging client + which uses a kernel timer to generate the PPS signal. + + This driver can also be built as a module. If so, the module + will be called pps-ktimer. + +config PPS_CLIENT_LDISC + tristate "PPS line discipline" + depends on PPS + help + If you say yes here you get support for a PPS source connected + with the CD (Carrier Detect) pin of your serial port. + +endif diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile new file mode 100644 index 0000000..812c9b1 --- /dev/null +++ b/drivers/pps/clients/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for PPS clients. +# + +obj-$(CONFIG_PPS_CLIENT_KTIMER) += pps-ktimer.o +obj-$(CONFIG_PPS_CLIENT_LDISC) += pps-ldisc.o + +ifeq ($(CONFIG_PPS_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif diff --git a/drivers/pps/clients/pps-ktimer.c b/drivers/pps/clients/pps-ktimer.c new file mode 100644 index 0000000..e7ef5b8 --- /dev/null +++ b/drivers/pps/clients/pps-ktimer.c @@ -0,0 +1,123 @@ +/* + * pps-ktimer.c -- kernel timer test client + * + * + * Copyright (C) 2005-2006 Rodolfo Giometti <giometti@linux.it> + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/time.h> +#include <linux/timer.h> +#include <linux/pps_kernel.h> + +/* + * Global variables + */ + +static int source; +static struct timer_list ktimer; + +/* + * The kernel timer + */ + +static void pps_ktimer_event(unsigned long ptr) +{ + struct timespec __ts; + struct pps_ktime ts; + + /* First of all we get the time stamp... */ + getnstimeofday(&__ts); + + pr_info("PPS event at %lu\n", jiffies); + + /* ... and translate it to PPS time data struct */ + ts.sec = __ts.tv_sec; + ts.nsec = __ts.tv_nsec; + + pps_event(source, &ts, PPS_CAPTUREASSERT, NULL); + + mod_timer(&ktimer, jiffies + HZ); +} + +/* + * The echo function + */ + +static void pps_ktimer_echo(int source, int event, void *data) +{ + pr_info("echo %s %s for source %d\n", + event & PPS_CAPTUREASSERT ? "assert" : "", + event & PPS_CAPTURECLEAR ? "clear" : "", + source); +} + +/* + * The PPS info struct + */ + +static struct pps_source_info pps_ktimer_info = { + .name = "ktimer", + .path = "", + .mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | + PPS_ECHOASSERT | + PPS_CANWAIT | PPS_TSFMT_TSPEC, + .echo = pps_ktimer_echo, + .owner = THIS_MODULE, +}; + +/* + * Module staff + */ + +static void __exit pps_ktimer_exit(void) +{ + del_timer_sync(&ktimer); + pps_unregister_source(source); + + pr_info("ktimer PPS source unregistered\n"); +} + +static int __init pps_ktimer_init(void) +{ + int ret; + + ret = pps_register_source(&pps_ktimer_info, + PPS_CAPTUREASSERT | PPS_OFFSETASSERT); + if (ret < 0) { + printk(KERN_ERR "cannot register ktimer source\n"); + return ret; + } + source = ret; + + setup_timer(&ktimer, pps_ktimer_event, 0); + mod_timer(&ktimer, jiffies + HZ); + + pr_info("ktimer PPS source registered at %d\n", source); + + return 0; +} + +module_init(pps_ktimer_init); +module_exit(pps_ktimer_exit); + +MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); +MODULE_DESCRIPTION("dummy PPS source by using a kernel timer (just for debug)"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pps/clients/pps-ldisc.c b/drivers/pps/clients/pps-ldisc.c new file mode 100644 index 0000000..8e1932d --- /dev/null +++ b/drivers/pps/clients/pps-ldisc.c @@ -0,0 +1,154 @@ +/* + * pps-ldisc.c -- PPS line discipline + * + * + * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/serial_core.h> +#include <linux/tty.h> +#include <linux/pps_kernel.h> + +#define PPS_TTY_MAGIC 0x0001 + +static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status, + struct timespec *ts) +{ + int id = (long)tty->disc_data; + struct timespec __ts; + struct pps_ktime pps_ts; + + /* First of all we get the time stamp... */ + getnstimeofday(&__ts); + + /* Does caller give us a timestamp? */ + if (ts) { /* Yes. Let's use it! */ + pps_ts.sec = ts->tv_sec; + pps_ts.nsec = ts->tv_nsec; + } else { /* No. Do it ourself! */ + pps_ts.sec = __ts.tv_sec; + pps_ts.nsec = __ts.tv_nsec; + } + + /* Now do the PPS event report */ + pps_event(id, &pps_ts, status ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR, + NULL); + + pr_debug("PPS %s at %lu on source #%d\n", + status ? "assert" : "clear", jiffies, id); +} + +static int (*alias_n_tty_open)(struct tty_struct *tty); + +static int pps_tty_open(struct tty_struct *tty) +{ + struct pps_source_info info; + struct tty_driver *drv = tty->driver; + int index = tty->index + drv->name_base; + int ret; + + info.owner = THIS_MODULE; + info.dev = NULL; + snprintf(info.name, PPS_MAX_NAME_LEN, "%s%d", drv->driver_name, index); + snprintf(info.path, PPS_MAX_NAME_LEN, "/dev/%s%d", drv->name, index); + info.mode = PPS_CAPTUREBOTH | \ + PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \ + PPS_CANWAIT | PPS_TSFMT_TSPEC; + + ret = pps_register_source(&info, PPS_CAPTUREBOTH | \ + PPS_OFFSETASSERT | PPS_OFFSETCLEAR); + if (ret < 0) { + pr_err("cannot register PPS source \"%s\"\n", info.path); + return ret; + } + tty->disc_data = (void *)(long)ret; + + /* Should open N_TTY ldisc too */ + ret = alias_n_tty_open(tty); + if (ret < 0) + pps_unregister_source((long)tty->disc_data); + + pr_info("PPS source #%d \"%s\" added\n", ret, info.path); + + return 0; +} + +static void (*alias_n_tty_close)(struct tty_struct *tty); + +static void pps_tty_close(struct tty_struct *tty) +{ + int id = (long)tty->disc_data; + + pps_unregister_source(id); + alias_n_tty_close(tty); + + pr_info("PPS source #%d removed\n", id); +} + +static struct tty_ldisc_ops pps_ldisc_ops; + +/* + * Module stuff + */ + +static int __init pps_tty_init(void) +{ + int err; + + /* Inherit the N_TTY's ops */ + n_tty_inherit_ops(&pps_ldisc_ops); + + /* Save N_TTY's open()/close() methods */ + alias_n_tty_open = pps_ldisc_ops.open; + alias_n_tty_close = pps_ldisc_ops.close; + + /* Init PPS_TTY data */ + pps_ldisc_ops.owner = THIS_MODULE; + pps_ldisc_ops.magic = PPS_TTY_MAGIC; + pps_ldisc_ops.name = "pps_tty"; + pps_ldisc_ops.dcd_change = pps_tty_dcd_change; + pps_ldisc_ops.open = pps_tty_open; + pps_ldisc_ops.close = pps_tty_close; + + err = tty_register_ldisc(N_PPS, &pps_ldisc_ops); + if (err) + pr_err("can't register PPS line discipline\n"); + else + pr_info("PPS line discipline registered\n"); + + return err; +} + +static void __exit pps_tty_cleanup(void) +{ + int err; + + err = tty_unregister_ldisc(N_PPS); + if (err) + pr_err("can't unregister PPS line discipline\n"); + else + pr_info("PPS line discipline removed\n"); +} + +module_init(pps_tty_init); +module_exit(pps_tty_cleanup); + +MODULE_ALIAS_LDISC(N_PPS); +MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); +MODULE_DESCRIPTION("PPS TTY device driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 33c0e98..bc90b09 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -22,48 +22,57 @@ * the best guess is to add 0.5s. */ +int rtc_hctosys_ret = -ENODEV; + static int __init rtc_hctosys(void) { - int err; + int err = -ENODEV; struct rtc_time tm; + struct timespec tv = { + .tv_nsec = NSEC_PER_SEC >> 1, + }; struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { - printk("%s: unable to open rtc device (%s)\n", + pr_err("%s: unable to open rtc device (%s)\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); - return -ENODEV; + goto err_open; } err = rtc_read_time(rtc, &tm); - if (err == 0) { - err = rtc_valid_tm(&tm); - if (err == 0) { - struct timespec tv; + if (err) { + dev_err(rtc->dev.parent, + "hctosys: unable to read the hardware clock\n"); + goto err_read; - tv.tv_nsec = NSEC_PER_SEC >> 1; + } - rtc_tm_to_time(&tm, &tv.tv_sec); + err = rtc_valid_tm(&tm); + if (err) { + dev_err(rtc->dev.parent, + "hctosys: invalid date/time\n"); + goto err_invalid; + } - do_settimeofday(&tv); + rtc_tm_to_time(&tm, &tv.tv_sec); - dev_info(rtc->dev.parent, - "setting system clock to " - "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, - (unsigned int) tv.tv_sec); - } - else - dev_err(rtc->dev.parent, - "hctosys: invalid date/time\n"); - } - else - dev_err(rtc->dev.parent, - "hctosys: unable to read the hardware clock\n"); + do_settimeofday(&tv); + dev_info(rtc->dev.parent, + "setting system clock to " + "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, + (unsigned int) tv.tv_sec); + +err_invalid: +err_read: rtc_class_close(rtc); - return 0; +err_open: + rtc_hctosys_ret = err; + + return err; } late_initcall(rtc_hctosys); diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 7dd23a6..380083c 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c @@ -107,8 +107,9 @@ rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, char *buf) { #ifdef CONFIG_RTC_HCTOSYS_DEVICE - if (strcmp(dev_name(&to_rtc_device(dev)->dev), - CONFIG_RTC_HCTOSYS_DEVICE) == 0) + if (rtc_hctosys_ret == 0 && + strcmp(dev_name(&to_rtc_device(dev)->dev), + CONFIG_RTC_HCTOSYS_DEVICE) == 0) return sprintf(buf, "1\n"); else #endif diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 62ddf52..2a4c566 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -373,7 +373,7 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) rq->rc = ccw_device_start(rp->cdev, &rq->ccw, (unsigned long) rq, 0, 0); if (rq->rc == 0) - return; /* Sucessfully restarted. */ + return; /* Successfully restarted. */ break; case RAW3270_IO_STOP: if (!rq) diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index ec88c59..f6d72e1 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -196,7 +196,7 @@ __sclp_start_request(struct sclp_req *req) req->start_count++; if (rc == 0) { - /* Sucessfully started request */ + /* Successfully started request */ req->status = SCLP_REQ_RUNNING; sclp_running_state = sclp_running_state_running; __sclp_set_request_timer(SCLP_RETRY_INTERVAL * HZ, diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index a3ac445..fcd005a 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -763,7 +763,8 @@ static inline int qeth_get_micros(void) static inline int qeth_get_ip_version(struct sk_buff *skb) { - switch (skb->protocol) { + struct ethhdr *ehdr = (struct ethhdr *)skb->data; + switch (ehdr->h_proto) { case ETH_P_IPV6: return 6; case ETH_P_IP: diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 7d25bdd..3bd4206 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -537,7 +537,8 @@ static void qeth_send_control_data_cb(struct qeth_channel *channel, dev_err(&card->gdev->dev, "The qeth device is not configured " "for the OSI layer required by z/VM\n"); - qeth_schedule_recovery(card); + else + qeth_schedule_recovery(card); goto out; } @@ -1113,8 +1114,6 @@ static int qeth_setup_card(struct qeth_card *card) card->ipato.enabled = 0; card->ipato.invert4 = 0; card->ipato.invert6 = 0; - if (card->info.type == QETH_CARD_TYPE_IQD) - card->options.checksum_type = NO_CHECKSUMMING; /* init QDIO stuff */ qeth_init_qdio_info(card); return 0; diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 88ae435..25dfd5a 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -8,6 +8,9 @@ * Frank Blaschka <frank.blaschka@de.ibm.com> */ +#define KMSG_COMPONENT "qeth" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include <linux/list.h> #include <linux/rwsem.h> #include <asm/ebcdic.h> diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 51fde6f..6f1e303 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1071,11 +1071,9 @@ static int qeth_l2_recover(void *ptr) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); else { - if (card->dev) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); dev_warn(&card->gdev->dev, "The qeth device driver " "failed to recover an error on the device\n"); } @@ -1129,11 +1127,9 @@ static int qeth_l2_pm_resume(struct ccwgroup_device *gdev) if (card->state == CARD_STATE_RECOVER) { rc = __qeth_l2_set_online(card->gdev, 1); if (rc) { - if (card->dev) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); } } else rc = __qeth_l2_set_online(card->gdev, 0); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 5475834..b3b6e87 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1691,39 +1691,43 @@ qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply, cmd = (struct qeth_ipa_cmd *)data; rc = cmd->hdr.return_code; - if (rc) { + if (rc) QETH_DBF_TEXT_(TRACE, 2, "dxter%x", rc); - if (cmd->data.diagass.action == QETH_DIAGS_CMD_TRACE_ENABLE) { - switch (rc) { - case IPA_RC_HARDWARE_AUTH_ERROR: - dev_warn(&card->gdev->dev, "The device is not " - "authorized to run as a HiperSockets " - "network traffic analyzer\n"); - break; - case IPA_RC_TRACE_ALREADY_ACTIVE: - dev_warn(&card->gdev->dev, "A HiperSockets " - "network traffic analyzer is already " - "active in the HiperSockets LAN\n"); - break; - default: - break; - } - } - return 0; - } - switch (cmd->data.diagass.action) { case QETH_DIAGS_CMD_TRACE_QUERY: break; case QETH_DIAGS_CMD_TRACE_DISABLE: - card->info.promisc_mode = SET_PROMISC_MODE_OFF; - dev_info(&card->gdev->dev, "The HiperSockets network traffic " - "analyzer is deactivated\n"); + switch (rc) { + case 0: + case IPA_RC_INVALID_SUBCMD: + card->info.promisc_mode = SET_PROMISC_MODE_OFF; + dev_info(&card->gdev->dev, "The HiperSockets network " + "traffic analyzer is deactivated\n"); + break; + default: + break; + } break; case QETH_DIAGS_CMD_TRACE_ENABLE: - card->info.promisc_mode = SET_PROMISC_MODE_ON; - dev_info(&card->gdev->dev, "The HiperSockets network traffic " - "analyzer is activated\n"); + switch (rc) { + case 0: + card->info.promisc_mode = SET_PROMISC_MODE_ON; + dev_info(&card->gdev->dev, "The HiperSockets network " + "traffic analyzer is activated\n"); + break; + case IPA_RC_HARDWARE_AUTH_ERROR: + dev_warn(&card->gdev->dev, "The device is not " + "authorized to run as a HiperSockets network " + "traffic analyzer\n"); + break; + case IPA_RC_TRACE_ALREADY_ACTIVE: + dev_warn(&card->gdev->dev, "A HiperSockets " + "network traffic analyzer is already " + "active in the HiperSockets LAN\n"); + break; + default: + break; + } break; default: QETH_DBF_MESSAGE(2, "Unknown sniffer action (0x%04x) on %s\n", @@ -2215,11 +2219,9 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) if (recovery_mode) qeth_l3_stop(card->dev); else { - if (card->dev) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); } if (!card->use_hard_stop) { rc = qeth_send_stoplan(card); @@ -2900,10 +2902,8 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) int data_offset = -1; int nr_frags; - if ((card->info.type == QETH_CARD_TYPE_IQD) && - (((skb->protocol != htons(ETH_P_IPV6)) && - (skb->protocol != htons(ETH_P_IP))) || - card->options.sniffer)) + if (((card->info.type == QETH_CARD_TYPE_IQD) && (!ipv)) || + card->options.sniffer) goto tx_drop; if ((card->state != CARD_STATE_UP) || !card->lan_online) { @@ -2949,14 +2949,14 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (data_offset < 0) skb_pull(new_skb, ETH_HLEN); } else { - if (new_skb->protocol == htons(ETH_P_IP)) { + if (ipv == 4) { if (card->dev->type == ARPHRD_IEEE802_TR) skb_pull(new_skb, TR_HLEN); else skb_pull(new_skb, ETH_HLEN); } - if (new_skb->protocol == ETH_P_IPV6 && card->vlangrp && + if (ipv == 6 && card->vlangrp && vlan_tx_tag_present(new_skb)) { skb_push(new_skb, VLAN_HLEN); skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4); @@ -3534,11 +3534,9 @@ static int qeth_l3_pm_resume(struct ccwgroup_device *gdev) if (card->state == CARD_STATE_RECOVER) { rc = __qeth_l3_set_online(card->gdev, 1); if (rc) { - if (card->dev) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); } } else rc = __qeth_l3_set_online(card->gdev, 0); diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 208d6df..ff5716d 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -492,7 +492,7 @@ static void init_alloc_map(struct orc_host * host) * init_orchid - initialise the host adapter * @host:host adapter to initialise * - * Initialise the controller and if neccessary load the firmware. + * Initialise the controller and if necessary load the firmware. * * Returns -1 if the initialisation fails. */ diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 89a5948..a771416 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -531,7 +531,7 @@ static void initio_read_eeprom(unsigned long base) * initio_stop_bm - stop bus master * @host: InitIO we are stopping * - * Stop any pending DMA operation, aborting the DMA if neccessary + * Stop any pending DMA operation, aborting the DMA if necessary */ static void initio_stop_bm(struct initio_host * host) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 6fde2fa..774e7ac 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -48,7 +48,7 @@ struct kmem_cache *scsi_pkt_cachep; #define FC_SRB_CMD_SENT (1 << 0) /* cmd has been sent */ #define FC_SRB_RCV_STATUS (1 << 1) /* response has arrived */ #define FC_SRB_ABORT_PENDING (1 << 2) /* cmd abort sent to device */ -#define FC_SRB_ABORTED (1 << 3) /* abort acknowleged */ +#define FC_SRB_ABORTED (1 << 3) /* abort acknowledged */ #define FC_SRB_DISCONTIG (1 << 4) /* non-sequential data recvd */ #define FC_SRB_COMPL (1 << 5) /* fc_io_compl has been run */ #define FC_SRB_FCP_PROCESSING_TMO (1 << 6) /* timer function processing */ @@ -519,7 +519,7 @@ crc_err: * * Called after receiving a Transfer Ready data descriptor. * If the LLD is capable of sequence offload then send down the - * seq_blen ammount of data in single frame, otherwise send + * seq_blen amount of data in single frame, otherwise send * multiple frames of the maximum frame payload supported by * the target port. */ diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 08b6634..2a40a6e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -981,7 +981,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, * function returns, it does not guarantee all the IOCBs are actually aborted. * * Return code - * 0 - Sucessfully issued abort iocb on all outstanding flogis (Always 0) + * 0 - Successfully issued abort iocb on all outstanding flogis (Always 0) **/ int lpfc_els_abort_flogi(struct lpfc_hba *phba) @@ -3129,7 +3129,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (ndlp && NLP_CHK_NODE_ACT(ndlp) && (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) { /* A LS_RJT associated with Default RPI cleanup has its own - * seperate code path. + * separate code path. */ if (!(ndlp->nlp_flag & NLP_RM_DFLT_RPI)) ls_rjt = 1; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 7f21b47..483fb74 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1575,7 +1575,7 @@ lpfc_bg_scsi_prep_dma_buf(struct lpfc_hba *phba, case LPFC_PG_TYPE_NO_DIF: num_bde = lpfc_bg_setup_bpl(phba, scsi_cmnd, bpl, datasegcnt); - /* we shoud have 2 or more entries in buffer list */ + /* we should have 2 or more entries in buffer list */ if (num_bde < 2) goto err; break; @@ -1612,7 +1612,7 @@ lpfc_bg_scsi_prep_dma_buf(struct lpfc_hba *phba, num_bde = lpfc_bg_setup_bpl_prot(phba, scsi_cmnd, bpl, datasegcnt, protsegcnt); - /* we shoud have 3 or more entries in buffer list */ + /* we should have 3 or more entries in buffer list */ if (num_bde < 3) goto err; break; diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index 7db28cd..8c61a4f 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -187,7 +187,7 @@ #define S_IO BIT(1) /* Input/Output line from SCSI bus */ #define S_CD BIT(2) /* Command/Data line from SCSI bus */ #define S_BUSY BIT(3) /* Busy line from SCSI bus */ -#define S_ACK BIT(4) /* Acknowlege line from SCSI bus */ +#define S_ACK BIT(4) /* Acknowledge line from SCSI bus */ #define S_REQUEST BIT(5) /* Request line from SCSI bus */ #define S_SELECT BIT(6) /* */ #define S_ATN BIT(7) /* */ diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 9b44c6f..7985ae4 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -2924,7 +2924,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) break; default: PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("unkown device type(%x)\n", deviceType)); + pm8001_printk("unknown device type(%x)\n", deviceType)); break; } phy->phy_type |= PORT_TYPE_SAS; diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 7f9c83a..3b2c98f 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -600,7 +600,7 @@ static void pm8001_free_dev(struct pm8001_device *pm8001_dev) * by the command "OPC_INB_REG_DEV", after that the HBA will assign a * device ID(according to device's sas address) and returned it to LLDD. From * now on, we communicate with HBA FW with the device ID which HBA assigned - * rather than sas address. it is the neccessary step for our HBA but it is + * rather than sas address. it is the necessary step for our HBA but it is * the optional for other HBA driver. */ static int pm8001_dev_found_notify(struct domain_device *dev) diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index 92f89d5..b8ad07c 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h @@ -938,7 +938,7 @@ static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { /* * pmcraid_ioctl_header - definition of header structure that preceeds all the - * buffers given as ioctl arguements. + * buffers given as ioctl arguments. * * .signature : always ASCII string, "PMCRAID" * .reserved : not used diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index fa34b92..1b82170 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -738,7 +738,7 @@ static int __devinit qpti_register_irq(struct qlogicpti *qpti) * sanely maintain. */ if (request_irq(qpti->irq, qpti_intr, - IRQF_SHARED, "Qlogic/PTI", qpti)) + IRQF_SHARED, "QlogicPTI", qpti)) goto fail; printk("qlogicpti%d: IRQ %d ", qpti->qpti_id, qpti->irq); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 1dd4d84..83881df 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2111,7 +2111,7 @@ static int sd_revalidate_disk(struct gendisk *disk) * which is followed by sdaaa. * * This is basically 26 base counting with one extra 'nil' entry - * at the beggining from the second digit on and can be + * at the beginning from the second digit on and can be * determined using similar method as 26 base conversion with the * index shifted -1 after each digit is computed. * diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 1d7a878..0d9d6f7 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -595,8 +595,6 @@ static int ses_intf_add(struct device *cdev, ses_dev->page10_len = len; buf = NULL; } - kfree(hdr_buf); - scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL); if (!scomp) goto err_free; @@ -608,6 +606,8 @@ static int ses_intf_add(struct device *cdev, goto err_free; } + kfree(hdr_buf); + edev->scratch = ses_dev; for (i = 0; i < components; i++) edev->component[i].scratch = scomp + i; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 7c4ebe6e..c3db16b 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2408,6 +2408,21 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, } static void +serial8250_set_ldisc(struct uart_port *port) +{ + int line = port->line; + + if (line >= port->state->port.tty->driver->num) + return; + + if (port->state->port.tty->ldisc->ops->num == N_PPS) { + port->flags |= UPF_HARDPPS_CD; + serial8250_enable_ms(port); + } else + port->flags &= ~UPF_HARDPPS_CD; +} + +static void serial8250_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { @@ -2628,6 +2643,7 @@ static struct uart_ops serial8250_pops = { .startup = serial8250_startup, .shutdown = serial8250_shutdown, .set_termios = serial8250_set_termios, + .set_ldisc = serial8250_set_ldisc, .pm = serial8250_pm, .type = serial8250_type, .release_port = serial8250_release_port, diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index d6ff733..f55c494 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -447,7 +447,7 @@ config SERIAL_CLPS711X_CONSOLE config SERIAL_SAMSUNG tristate "Samsung SoC serial support" - depends on ARM && PLAT_S3C + depends on ARM && PLAT_SAMSUNG select SERIAL_CORE help Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, @@ -455,11 +455,18 @@ config SERIAL_SAMSUNG provide all of these ports, depending on how the serial port pins are configured. +config SERIAL_SAMSUNG_UARTS_4 + bool + depends on ARM && PLAT_SAMSUNG + default y if CPU_S3C2443 + help + Internal node for the common case of 4 Samsung compatible UARTs + config SERIAL_SAMSUNG_UARTS int - depends on ARM && PLAT_S3C + depends on ARM && PLAT_SAMSUNG default 2 if ARCH_S3C2400 - default 4 if ARCH_S5PC1XX || ARCH_S3C64XX || CPU_S3C2443 + default 4 if SERIAL_SAMSUNG_UARTS_4 default 3 help Select the number of available UART ports for the Samsung S3C @@ -526,20 +533,30 @@ config SERIAL_S3C24A0 Serial port support for the Samsung S3C24A0 SoC config SERIAL_S3C6400 - tristate "Samsung S3C6400/S3C6410 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410) + tristate "Samsung S3C6400/S3C6410/S5P6440 Seria port support" + depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440) + select SERIAL_SAMSUNG_UARTS_4 default y help - Serial port support for the Samsung S3C6400 and S3C6410 + Serial port support for the Samsung S3C6400, S3C6410 and S5P6440 SoCs config SERIAL_S5PC100 tristate "Samsung S5PC100 Serial port support" depends on SERIAL_SAMSUNG && CPU_S5PC100 + select SERIAL_SAMSUNG_UARTS_4 default y help Serial port support for the Samsung S5PC100 SoCs +config SERIAL_S5PV210 + tristate "Samsung S5PV210 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442) + select SERIAL_SAMSUNG_UARTS_4 if CPU_S5PV210 + default y + help + Serial port support for Samsung's S5P Family of SoC's + config SERIAL_MAX3100 tristate "MAX3100 support" depends on SPI @@ -996,7 +1013,7 @@ config SERIAL_IP22_ZILOG_CONSOLE config SERIAL_SH_SCI tristate "SuperH SCI(F) serial port support" - depends on HAVE_CLK && (SUPERH || H8300) + depends on HAVE_CLK && (SUPERH || H8300 || ARCH_SHMOBILE) select SERIAL_CORE config SERIAL_SH_SCI_NR_UARTS diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 5548fe7..6aa4723 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o +obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 429a8ae..e4b3c2c 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -471,6 +471,20 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, spin_unlock_irqrestore(&uap->port.lock, flags); } +static void pl010_set_ldisc(struct uart_port *port) +{ + int line = port->line; + + if (line >= port->state->port.tty->driver->num) + return; + + if (port->state->port.tty->ldisc->ops->num == N_PPS) { + port->flags |= UPF_HARDPPS_CD; + pl010_enable_ms(port); + } else + port->flags &= ~UPF_HARDPPS_CD; +} + static const char *pl010_type(struct uart_port *port) { return port->type == PORT_AMBA ? "AMBA" : NULL; @@ -531,6 +545,7 @@ static struct uart_ops amba_pl010_pops = { .startup = pl010_startup, .shutdown = pl010_shutdown, .set_termios = pl010_set_termios, + .set_ldisc = pl010_set_ldisc, .type = pl010_type, .release_port = pl010_release_port, .request_port = pl010_request_port, diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index d00fcf8..e579d7a 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -440,7 +440,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) temp = readl(sport->port.membase + USR2); if (temp & USR2_BRCD) { - writel(temp | USR2_BRCD, sport->port.membase + USR2); + writel(USR2_BRCD, sport->port.membase + USR2); if (uart_handle_break(&sport->port)) continue; } diff --git a/drivers/serial/s3c2412.c b/drivers/serial/s3c2412.c index ce75e28..1700b1a 100644 --- a/drivers/serial/s3c2412.c +++ b/drivers/serial/s3c2412.c @@ -102,6 +102,7 @@ static struct s3c24xx_uart_info s3c2412_uart_inf = { .name = "Samsung S3C2412 UART", .type = PORT_S3C2412, .fifosize = 64, + .has_divslot = 1, .rx_fifomask = S3C2440_UFSTAT_RXMASK, .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, .rx_fifofull = S3C2440_UFSTAT_RXFULL, diff --git a/drivers/serial/s5pv210.c b/drivers/serial/s5pv210.c new file mode 100644 index 0000000..8dc0383 --- /dev/null +++ b/drivers/serial/s5pv210.c @@ -0,0 +1,154 @@ +/* linux/drivers/serial/s5pv210.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Based on drivers/serial/s3c6400.c + * + * Driver for Samsung S5PV210 SoC UARTs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/serial.h> + +#include <asm/irq.h> +#include <mach/hardware.h> +#include <plat/regs-serial.h> +#include "samsung.h" + +static int s5pv210_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + if (strcmp(clk->name, "pclk") == 0) + ucon &= ~S5PV210_UCON_CLKMASK; + else if (strcmp(clk->name, "uclk1") == 0) + ucon |= S5PV210_UCON_CLKMASK; + else { + printk(KERN_ERR "unknown clock source %s\n", clk->name); + return -EINVAL; + } + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + + +static int s5pv210_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + u32 ucon = rd_regl(port, S3C2410_UCON); + + clk->divisor = 1; + + switch (ucon & S5PV210_UCON_CLKMASK) { + case S5PV210_UCON_PCLK: + clk->name = "pclk"; + break; + case S5PV210_UCON_UCLK: + clk->name = "uclk1"; + break; + } + + return 0; +} + +static int s5pv210_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + ucon &= S5PV210_UCON_CLKMASK; + wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); + + /* reset both fifos */ + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + return 0; +} + +#define S5PV210_UART_DEFAULT_INFO(fifo_size) \ + .name = "Samsung S5PV210 UART0", \ + .type = PORT_S3C6400, \ + .fifosize = fifo_size, \ + .has_divslot = 1, \ + .rx_fifomask = S5PV210_UFSTAT_RXMASK, \ + .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \ + .rx_fifofull = S5PV210_UFSTAT_RXFULL, \ + .tx_fifofull = S5PV210_UFSTAT_TXFULL, \ + .tx_fifomask = S5PV210_UFSTAT_TXMASK, \ + .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, \ + .get_clksrc = s5pv210_serial_getsource, \ + .set_clksrc = s5pv210_serial_setsource, \ + .reset_port = s5pv210_serial_resetport + +static struct s3c24xx_uart_info s5p_port_fifo256 = { + S5PV210_UART_DEFAULT_INFO(256), +}; + +static struct s3c24xx_uart_info s5p_port_fifo64 = { + S5PV210_UART_DEFAULT_INFO(64), +}; + +static struct s3c24xx_uart_info s5p_port_fifo16 = { + S5PV210_UART_DEFAULT_INFO(16), +}; + +static struct s3c24xx_uart_info *s5p_uart_inf[] = { + [0] = &s5p_port_fifo256, + [1] = &s5p_port_fifo64, + [2] = &s5p_port_fifo16, + [3] = &s5p_port_fifo16, +}; + +/* device management */ +static int s5p_serial_probe(struct platform_device *pdev) +{ + return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]); +} + +static struct platform_driver s5p_serial_drv = { + .probe = s5p_serial_probe, + .remove = __devexit_p(s3c24xx_serial_remove), + .driver = { + .name = "s5pv210-uart", + .owner = THIS_MODULE, + }, +}; + +static int __init s5pv210_serial_console_init(void) +{ + return s3c24xx_serial_initconsole(&s5p_serial_drv, s5p_uart_inf); +} + +console_initcall(s5pv210_serial_console_init); + +static int __init s5p_serial_init(void) +{ + return s3c24xx_serial_init(&s5p_serial_drv, *s5p_uart_inf); +} + +static void __exit s5p_serial_exit(void) +{ + platform_driver_unregister(&s5p_serial_drv); +} + +module_init(s5p_serial_init); +module_exit(s5p_serial_exit); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s5pv210-uart"); +MODULE_DESCRIPTION("Samsung S5PV210 UART Driver support"); +MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>"); diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index 52e3df1..a9d6c56 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -1271,7 +1271,7 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) unsigned long ufstat, utrstat; if (ufcon & S3C2410_UFCON_FIFOMODE) { - /* fifo mode - check ammount of data in fifo registers... */ + /* fifo mode - check amount of data in fifo registers... */ ufstat = rd_regl(port, S3C2410_UFSTAT); return (ufstat & info->tx_fifofull) ? 0 : 1; @@ -1374,7 +1374,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, * data. */ -static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info) +static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info **info) { struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports; struct platform_device **platdev_ptr; @@ -1385,7 +1385,7 @@ static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info) platdev_ptr = s3c24xx_uart_devs; for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) { - s3c24xx_serial_init_port(ptr, info, *platdev_ptr); + s3c24xx_serial_init_port(ptr, info[i], *platdev_ptr); } return 0; @@ -1451,7 +1451,7 @@ static struct console s3c24xx_serial_console = { }; int s3c24xx_serial_initconsole(struct platform_driver *drv, - struct s3c24xx_uart_info *info) + struct s3c24xx_uart_info **info) { struct platform_device *dev = s3c24xx_uart_devs[0]; diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h index 1fb2234..0ac06a0 100644 --- a/drivers/serial/samsung.h +++ b/drivers/serial/samsung.h @@ -75,19 +75,24 @@ extern int s3c24xx_serial_probe(struct platform_device *dev, extern int __devexit s3c24xx_serial_remove(struct platform_device *dev); extern int s3c24xx_serial_initconsole(struct platform_driver *drv, - struct s3c24xx_uart_info *uart); + struct s3c24xx_uart_info **uart); extern int s3c24xx_serial_init(struct platform_driver *drv, struct s3c24xx_uart_info *info); #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE -#define s3c24xx_console_init(__drv, __inf) \ -static int __init s3c_serial_console_init(void) \ -{ \ - return s3c24xx_serial_initconsole(__drv, __inf); \ -} \ - \ +#define s3c24xx_console_init(__drv, __inf) \ +static int __init s3c_serial_console_init(void) \ +{ \ + struct s3c24xx_uart_info *uinfo[CONFIG_SERIAL_SAMSUNG_UARTS]; \ + int i; \ + \ + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++) \ + uinfo[i] = __inf; \ + return s3c24xx_serial_initconsole(__drv, uinfo); \ +} \ + \ console_initcall(s3c_serial_console_init) #else diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index f7d2589..fad67d3 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -30,7 +30,8 @@ */ # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0 #elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) + defined(CONFIG_CPU_SUBTYPE_SH7721) || \ + defined(CONFIG_ARCH_SHMOBILE) # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ # define PORT_PTCR 0xA405011EUL # define PORT_PVCR 0xA4050122UL @@ -228,7 +229,8 @@ #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) + defined(CONFIG_CPU_SUBTYPE_SH7721) || \ + defined(CONFIG_ARCH_SHMOBILE) # define SCIF_ORER 0x0200 # define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER) # define SCIF_RFDC_MASK 0x007f @@ -261,7 +263,8 @@ #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) + defined(CONFIG_CPU_SUBTYPE_SH7721) || \ + defined(CONFIG_ARCH_SHMOBILE) # define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc) # define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73) # define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf) @@ -356,7 +359,7 @@ SCI_OUT(sci_size, sci_offset, value); \ } -#ifdef CONFIG_CPU_SH3 +#if defined(CONFIG_CPU_SH3) || defined(CONFIG_ARCH_SHMOBILE) #if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ @@ -366,7 +369,8 @@ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) + defined(CONFIG_CPU_SUBTYPE_SH7721) || \ + defined(CONFIG_ARCH_SHMOBILE) #define SCIF_FNS(name, scif_offset, scif_size) \ CPU_SCIF_FNS(name, scif_offset, scif_size) #else @@ -401,7 +405,8 @@ #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) + defined(CONFIG_CPU_SUBTYPE_SH7721) || \ + defined(CONFIG_ARCH_SHMOBILE) SCIF_FNS(SCSMR, 0x00, 16) SCIF_FNS(SCBRR, 0x04, 8) @@ -413,7 +418,7 @@ SCIF_FNS(SCFCR, 0x18, 16) SCIF_FNS(SCFDR, 0x1c, 16) SCIF_FNS(SCxTDR, 0x20, 8) SCIF_FNS(SCxRDR, 0x24, 8) -SCIF_FNS(SCLSR, 0x24, 16) +SCIF_FNS(SCLSR, 0x00, 0) #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ defined(CONFIG_CPU_SUBTYPE_SH7724) SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) @@ -583,7 +588,8 @@ static inline int sci_rxd_in(struct uart_port *port) #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) + defined(CONFIG_CPU_SUBTYPE_SH7721) || \ + defined(CONFIG_ARCH_SHMOBILE) #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ defined(CONFIG_CPU_SUBTYPE_SH7724) diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 3a5a17d..c275039 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -762,6 +762,10 @@ static void __init intc_register_irq(struct intc_desc *desc, if (desc->hw.ack_regs) ack_handle[irq] = intc_ack_data(desc, d, enum_id); + +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */ +#endif } static unsigned int __init save_reg(struct intc_desc_int *d, @@ -1024,8 +1028,12 @@ unsigned int create_irq_nr(unsigned int irq_want, int node) out_unlock: spin_unlock_irqrestore(&vector_lock, flags); - if (irq > 0) + if (irq > 0) { dynamic_irq_init(irq); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */ +#endif + } return irq; } diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index c010733..1fabede 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c @@ -275,7 +275,7 @@ static inline u32 ack_bit(unsigned int irq) * Claim the FIQ handler (only one can be active at any one time) and * then setup the correct transfer code for this transfer. * - * This call updates all the necessary state information if sucessful, + * This call updates all the necessary state information if successful, * so the caller does not need to do anything more than start the transfer * as normal, since the IRQ will have been re-routed to the FIQ handler. */ diff --git a/drivers/usb/gadget/fsl_mx3_udc.c b/drivers/usb/gadget/fsl_mx3_udc.c index 4bc2bf3..20a802e 100644 --- a/drivers/usb/gadget/fsl_mx3_udc.c +++ b/drivers/usb/gadget/fsl_mx3_udc.c @@ -17,6 +17,8 @@ #include <linux/fsl_devices.h> #include <linux/platform_device.h> +#include <mach/hardware.h> + static struct clk *mxc_ahb_clk; static struct clk *mxc_usb_clk; @@ -28,14 +30,16 @@ int fsl_udc_clk_init(struct platform_device *pdev) pdata = pdev->dev.platform_data; - mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb"); - if (IS_ERR(mxc_ahb_clk)) - return PTR_ERR(mxc_ahb_clk); + if (!cpu_is_mx35()) { + mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb"); + if (IS_ERR(mxc_ahb_clk)) + return PTR_ERR(mxc_ahb_clk); - ret = clk_enable(mxc_ahb_clk); - if (ret < 0) { - dev_err(&pdev->dev, "clk_enable(\"usb_ahb\") failed\n"); - goto eenahb; + ret = clk_enable(mxc_ahb_clk); + if (ret < 0) { + dev_err(&pdev->dev, "clk_enable(\"usb_ahb\") failed\n"); + goto eenahb; + } } /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ @@ -50,6 +54,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) if (pdata->phy_mode != FSL_USB2_PHY_ULPI && (freq < 59999000 || freq > 60001000)) { dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq); + ret = -EINVAL; goto eclkrate; } @@ -66,9 +71,11 @@ eclkrate: clk_put(mxc_usb_clk); mxc_usb_clk = NULL; egusb: - clk_disable(mxc_ahb_clk); + if (!cpu_is_mx35()) + clk_disable(mxc_ahb_clk); eenahb: - clk_put(mxc_ahb_clk); + if (!cpu_is_mx35()) + clk_put(mxc_ahb_clk); return ret; } @@ -90,6 +97,8 @@ void fsl_udc_clk_release(void) clk_disable(mxc_usb_clk); clk_put(mxc_usb_clk); } - clk_disable(mxc_ahb_clk); - clk_put(mxc_ahb_clk); + if (!cpu_is_mx35()) { + clk_disable(mxc_ahb_clk); + clk_put(mxc_ahb_clk); + } } diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index e6fedbd..be5fb34 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -65,6 +65,10 @@ #include <mach/pxa25x-udc.h> #endif +#ifdef CONFIG_ARCH_LUBBOCK +#include <mach/lubbock.h> +#endif + #include <asm/mach/udc_pxa2xx.h> diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 7e5bf59..f742c8e 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -30,7 +30,7 @@ #include <plat/regs-usb-hsotg-phy.h> #include <plat/regs-usb-hsotg.h> -#include <plat/regs-sys.h> +#include <mach/regs-sys.h> #include <plat/udc-hs.h> #define DMA_ADDR_INVALID (~((dma_addr_t)0)) diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 6691381..a883f9d 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -274,7 +274,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) /* NOTE: DaVinci shadows the Mentor IRQs. Don't manage them through * the Mentor registers (except for setup), use the TI ones and EOI. * - * Docs describe irq "vector" registers asociated with the CPPI and + * Docs describe irq "vector" registers associated with the CPPI and * USB EOI registers. These hold a bitmask corresponding to the * current IRQ, not an irq handler address. Would using those bits * resolve some of the races observed in this dispatch code?? diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 292894a..8d8062b 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -491,7 +491,7 @@ static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum) #define MUSB_FLAT_OFFSET(_epnum, _offset) \ (USB_OFFSET(USB_EP_NI0_TXMAXP) + (0x40 * (_epnum)) + (_offset)) -/* Not implemented - HW has seperate Tx/Rx FIFO */ +/* Not implemented - HW has separate Tx/Rx FIFO */ #define MUSB_TXCSR_MODE 0x0000 static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size) diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index baf74b4..e23c779 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -152,7 +152,7 @@ struct cypress_private { int isthrottled; /* if throttled, discard reads */ wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ char prev_status, diff_status; /* used for TIOCMIWAIT */ - /* we pass a pointer to this as the arguement sent to + /* we pass a pointer to this as the argument sent to cypress_set_termios old_termios */ struct ktermios tmp_termios; /* stores the old termios settings */ }; diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index f37476e..701452a 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -115,7 +115,7 @@ static void opticon_bulk_callback(struct urb *urb) } } else { dev_dbg(&priv->udev->dev, - "Improper ammount of data received from the device, " + "Improper amount of data received from the device, " "%d bytes", urb->actual_length); } diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 7239888..ee190cc 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -94,7 +94,7 @@ static void symbol_int_callback(struct urb *urb) } } else { dev_dbg(&priv->udev->dev, - "Improper ammount of data received from the device, " + "Improper amount of data received from the device, " "%d bytes", urb->actual_length); } diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index fd2fd4e..759cda5 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h @@ -198,7 +198,7 @@ struct wusb_port { * ports) this HC will take. Read-only. * * @port Array of port status for each fake root port. Guaranteed to - * always be the same lenght during device existence + * always be the same length during device existence * [this allows for some unlocked but referenced reading]. * * @mmcies_max Max number of Information Elements this HC can send diff --git a/drivers/uwb/i1480/i1480-est.c b/drivers/uwb/i1480/i1480-est.c index 7bf8c6f..f2eb4d8 100644 --- a/drivers/uwb/i1480/i1480-est.c +++ b/drivers/uwb/i1480/i1480-est.c @@ -54,7 +54,7 @@ static struct uwb_est_entry i1480_est_fd01[] = { .size = sizeof(struct i1480_rceb) + 2 }, }; -static int i1480_est_init(void) +static int __init i1480_est_init(void) { int result = uwb_est_register(i1480_CET_VS1, 0x00, 0x8086, 0x0c3b, i1480_est_fd00, @@ -73,7 +73,7 @@ static int i1480_est_init(void) } module_init(i1480_est_init); -static void i1480_est_exit(void) +static void __exit i1480_est_exit(void) { uwb_est_unregister(i1480_CET_VS1, 0x00, 0x8086, 0x0c3b, i1480_est_fd00, ARRAY_SIZE(i1480_est_fd00)); diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c index 5a777d8..6210fe1 100644 --- a/drivers/uwb/uwbd.c +++ b/drivers/uwb/uwbd.c @@ -43,7 +43,7 @@ * * EVENTS * - * Events have a type, a subtype, a lenght, some other stuff and the + * Events have a type, a subtype, a length, some other stuff and the * data blob, which depends on the event. The header is 'struct * uwb_event'; for payloads, see 'struct uwbd_evt_*'. * diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 0b17824..2110556 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -308,7 +308,7 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, * Pseudocolor: * uses offset = 0 && length = RAMDAC register width. * var->{color}.offset is 0 - * var->{color}.length contains widht of DAC + * var->{color}.length contains width of DAC * cmap is not used * RAMDAC[X] is programmed to (red, green, blue) * Truecolor: diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 5a5c303..dabe804 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -400,9 +400,12 @@ config FB_SA1100 If you plan to use the LCD display with your SA-1100 system, say Y here. +config HAVE_FB_IMX + bool + config FB_IMX tristate "Motorola i.MX LCD support" - depends on FB && (ARCH_MX1 || ARCH_MX2) + depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -909,6 +912,18 @@ config FB_XVR2500 mostly initialized the card already. It is treated as a completely dumb framebuffer device. +config FB_XVR1000 + bool "Sun XVR-1000 support" + depends on SPARC64 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the Sun XVR-1000 and similar + graphics cards. The driver only works on sparc64 systems where + the system firmware has mostly initialized the card already. It + is treated as a completely dumb framebuffer device. + config FB_PVR2 tristate "NEC PowerVR 2 display support" depends on FB && SH_DREAMCAST @@ -1494,7 +1509,6 @@ config FB_VIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select I2C_ALGOBIT select I2C help @@ -1945,6 +1959,27 @@ config FB_S3C2410_DEBUG Turn on debugging messages. Note that you can set/unset at run time through sysfs +config FB_NUC900 + bool "NUC900 LCD framebuffer support" + depends on FB && ARCH_W90X900 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Nuvoton + NUC900 processor + +config GPM1040A0_320X240 + bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD" + depends on FB_NUC900 + +config FB_NUC900_DEBUG + bool "NUC900 lcd debug messages" + depends on FB_NUC900 + help + Turn on debugging messages. Note that you can set/unset at run time + through sysfs + config FB_SM501 tristate "Silicon Motion SM501 framebuffer support" depends on FB && MFD_SM501 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 4ecb30c..ddc2af2 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -79,6 +79,7 @@ obj-$(CONFIG_FB_N411) += n411.o obj-$(CONFIG_FB_HGA) += hgafb.o obj-$(CONFIG_FB_XVR500) += sunxvr500.o obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o +obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o obj-$(CONFIG_FB_IGA) += igafb.o obj-$(CONFIG_FB_APOLLO) += dnfb.o obj-$(CONFIG_FB_Q40) += q40fb.o @@ -129,6 +130,7 @@ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ obj-$(CONFIG_FB_MSM) += msm/ +obj-$(CONFIG_FB_NUC900) += nuc900fb.o # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index 9fe90ce..e70bc22 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -140,7 +140,7 @@ static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dc /* 3 <= m <= 257 */ if (m >= 3 && m <= 257) { - unsigned new_error = ((Ftarget * n) - (Fref * m)) >= 0 ? + unsigned new_error = Ftarget * n >= Fref * m ? ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n)); if (new_error < best_error) { best_n = n; @@ -152,7 +152,7 @@ static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dc else if (m <= 1028) { /* remember there are still only 8-bits of precision in m, so * avoid over-optimistic error calculations */ - unsigned new_error = ((Ftarget * n) - (Fref * (m & ~3))) >= 0 ? + unsigned new_error = Ftarget * n >= Fref * (m & ~3) ? ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n)); if (new_error < best_error) { best_n = n; diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index e49ae5e..814312a 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -82,7 +82,6 @@ struct bfin_bf54xfb_info { unsigned char *fb_buffer; /* RGB Buffer */ dma_addr_t dma_handle; - int lq043_mmap; int lq043_open_cnt; int irq; spinlock_t lock; /* lock */ @@ -316,7 +315,6 @@ static int bfin_bf54x_fb_release(struct fb_info *info, int user) spin_lock(&fbi->lock); fbi->lq043_open_cnt--; - fbi->lq043_mmap = 0; if (fbi->lq043_open_cnt <= 0) { @@ -374,33 +372,6 @@ static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var, return 0; } -static int bfin_bf54x_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - - struct bfin_bf54xfb_info *fbi = info->par; - - if (fbi->lq043_mmap) - return -1; - - spin_lock(&fbi->lock); - fbi->lq043_mmap = 1; - spin_unlock(&fbi->lock); - - vma->vm_start = (unsigned long)(fbi->fb_buffer); - - vma->vm_end = vma->vm_start + info->fix.smem_len; - /* For those who don't understand how mmap works, go read - * Documentation/nommu-mmap.txt. - * For those that do, you will know that the VM_MAYSHARE flag - * must be set in the vma->vm_flags structure on noMMU - * Other flags can be set, and are documented in - * include/linux/mm.h - */ - vma->vm_flags |= VM_MAYSHARE | VM_SHARED; - - return 0; -} - int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { if (nocursor) @@ -452,7 +423,6 @@ static struct fb_ops bfin_bf54x_fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_mmap = bfin_bf54x_fb_mmap, .fb_cursor = bfin_bf54x_fb_cursor, .fb_setcolreg = bfin_bf54x_fb_setcolreg, }; diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c index b690c26..0387236 100644 --- a/drivers/video/bfin-lq035q1-fb.c +++ b/drivers/video/bfin-lq035q1-fb.c @@ -22,7 +22,6 @@ #include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> -#include <linux/dma-mapping.h> #include <asm/blackfin.h> #include <asm/irq.h> diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 2549c53..5653d08 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -87,7 +87,6 @@ struct bfin_t350mcqbfb_info { struct device *dev; unsigned char *fb_buffer; /* RGB Buffer */ dma_addr_t dma_handle; - int lq043_mmap; int lq043_open_cnt; int irq; spinlock_t lock; /* lock */ @@ -235,7 +234,6 @@ static int bfin_t350mcqb_fb_release(struct fb_info *info, int user) spin_lock(&fbi->lock); fbi->lq043_open_cnt--; - fbi->lq043_mmap = 0; if (fbi->lq043_open_cnt <= 0) { bfin_t350mcqb_disable_ppi(); @@ -293,32 +291,6 @@ static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var, return 0; } -static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - struct bfin_t350mcqbfb_info *fbi = info->par; - - if (fbi->lq043_mmap) - return -1; - - spin_lock(&fbi->lock); - fbi->lq043_mmap = 1; - spin_unlock(&fbi->lock); - - vma->vm_start = (unsigned long)(fbi->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET); - - vma->vm_end = vma->vm_start + info->fix.smem_len; - /* For those who don't understand how mmap works, go read - * Documentation/nommu-mmap.txt. - * For those that do, you will know that the VM_MAYSHARE flag - * must be set in the vma->vm_flags structure on noMMU - * Other flags can be set, and are documented in - * include/linux/mm.h - */ - vma->vm_flags |= VM_MAYSHARE | VM_SHARED; - - return 0; -} - int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { if (nocursor) @@ -370,7 +342,6 @@ static struct fb_ops bfin_t350mcqb_fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_mmap = bfin_t350mcqb_fb_mmap, .fb_cursor = bfin_t350mcqb_fb_cursor, .fb_setcolreg = bfin_t350mcqb_fb_setcolreg, }; diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c index df9ccb9..ebda687 100644 --- a/drivers/video/broadsheetfb.c +++ b/drivers/video/broadsheetfb.c @@ -29,11 +29,65 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/list.h> +#include <linux/firmware.h> #include <linux/uaccess.h> #include <video/broadsheetfb.h> -/* Display specific information */ +/* track panel specific parameters */ +struct panel_info { + int w; + int h; + u16 sdcfg; + u16 gdcfg; + u16 lutfmt; + u16 fsynclen; + u16 fendfbegin; + u16 lsynclen; + u16 lendlbegin; + u16 pixclk; +}; + +/* table of panel specific parameters to be indexed into by the board drivers */ +static struct panel_info panel_table[] = { + { /* standard 6" on TFT backplane */ + .w = 800, + .h = 600, + .sdcfg = (100 | (1 << 8) | (1 << 9)), + .gdcfg = 2, + .lutfmt = (4 | (1 << 7)), + .fsynclen = 4, + .fendfbegin = (10 << 8) | 4, + .lsynclen = 10, + .lendlbegin = (100 << 8) | 4, + .pixclk = 6, + }, + { /* custom 3.7" flexible on PET or steel */ + .w = 320, + .h = 240, + .sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)), + .gdcfg = 3, + .lutfmt = (4 | (1 << 7)), + .fsynclen = 0, + .fendfbegin = (80 << 8) | 4, + .lsynclen = 10, + .lendlbegin = (80 << 8) | 20, + .pixclk = 14, + }, + { /* standard 9.7" on TFT backplane */ + .w = 1200, + .h = 825, + .sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)), + .gdcfg = 2, + .lutfmt = (4 | (1 << 7)), + .fsynclen = 0, + .fendfbegin = (4 << 8) | 4, + .lsynclen = 4, + .lendlbegin = (60 << 8) | 10, + .pixclk = 3, + }, +}; + #define DPY_W 800 #define DPY_H 600 @@ -62,30 +116,30 @@ static struct fb_var_screeninfo broadsheetfb_var __devinitdata = { }; /* main broadsheetfb functions */ -static void broadsheet_issue_data(struct broadsheetfb_par *par, u16 data) +static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data) { par->board->set_ctl(par, BS_WR, 0); par->board->set_hdb(par, data); par->board->set_ctl(par, BS_WR, 1); } -static void broadsheet_issue_cmd(struct broadsheetfb_par *par, u16 data) +static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data) { par->board->set_ctl(par, BS_DC, 0); - broadsheet_issue_data(par, data); + broadsheet_gpio_issue_data(par, data); } -static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data) +static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data) { par->board->wait_for_rdy(par); par->board->set_ctl(par, BS_CS, 0); - broadsheet_issue_cmd(par, data); + broadsheet_gpio_issue_cmd(par, data); par->board->set_ctl(par, BS_DC, 1); par->board->set_ctl(par, BS_CS, 1); } -static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, +static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, int argc, u16 *argv) { int i; @@ -93,15 +147,43 @@ static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, par->board->wait_for_rdy(par); par->board->set_ctl(par, BS_CS, 0); - broadsheet_issue_cmd(par, cmd); + broadsheet_gpio_issue_cmd(par, cmd); par->board->set_ctl(par, BS_DC, 1); for (i = 0; i < argc; i++) - broadsheet_issue_data(par, argv[i]); + broadsheet_gpio_issue_data(par, argv[i]); par->board->set_ctl(par, BS_CS, 1); } -static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, +static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, + int argc, u16 *argv) +{ + int i; + + par->board->mmio_write(par, BS_MMIO_CMD, cmd); + + for (i = 0; i < argc; i++) + par->board->mmio_write(par, BS_MMIO_DATA, argv[i]); +} + +static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data) +{ + if (par->board->mmio_write) + par->board->mmio_write(par, BS_MMIO_CMD, data); + else + broadsheet_gpio_send_command(par, data); +} + +static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, + int argc, u16 *argv) +{ + if (par->board->mmio_write) + broadsheet_mmio_send_cmdargs(par, cmd, argc, argv); + else + broadsheet_gpio_send_cmdargs(par, cmd, argc, argv); +} + +static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size, u16 *data) { int i; @@ -121,7 +203,30 @@ static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, par->board->set_ctl(par, BS_CS, 1); } -static u16 broadsheet_get_data(struct broadsheetfb_par *par) +static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size, + u16 *data) +{ + int i; + u16 tmp; + + for (i = 0; i < size; i++) { + tmp = (data[i] & 0x0F) << 4; + tmp |= (data[i] & 0x0F00) << 4; + par->board->mmio_write(par, BS_MMIO_DATA, tmp); + } + +} + +static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, + u16 *data) +{ + if (par->board->mmio_write) + broadsheet_mmio_burst_write(par, size, data); + else + broadsheet_gpio_burst_write(par, size, data); +} + +static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par) { u16 res; /* wait for ready to go hi. (lo is busy) */ @@ -141,7 +246,16 @@ static u16 broadsheet_get_data(struct broadsheetfb_par *par) return res; } -static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, + +static u16 broadsheet_get_data(struct broadsheetfb_par *par) +{ + if (par->board->mmio_read) + return par->board->mmio_read(par); + else + return broadsheet_gpio_get_data(par); +} + +static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg, u16 data) { /* wait for ready to go hi. (lo is busy) */ @@ -150,44 +264,541 @@ static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, /* cs lo, dc lo for cmd, we lo for each data, db as usual */ par->board->set_ctl(par, BS_CS, 0); - broadsheet_issue_cmd(par, BS_CMD_WR_REG); + broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG); par->board->set_ctl(par, BS_DC, 1); - broadsheet_issue_data(par, reg); - broadsheet_issue_data(par, data); + broadsheet_gpio_issue_data(par, reg); + broadsheet_gpio_issue_data(par, data); par->board->set_ctl(par, BS_CS, 1); } +static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg, + u16 data) +{ + par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG); + par->board->mmio_write(par, BS_MMIO_DATA, reg); + par->board->mmio_write(par, BS_MMIO_DATA, data); + +} + +static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, + u16 data) +{ + if (par->board->mmio_write) + broadsheet_mmio_write_reg(par, reg, data); + else + broadsheet_gpio_write_reg(par, reg, data); +} + +static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg, + u32 data) +{ + broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF); + broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF); +} + + static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg) { - broadsheet_send_command(par, reg); - msleep(100); + broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, ®); + par->board->wait_for_rdy(par); return broadsheet_get_data(par); } +/* functions for waveform manipulation */ +static int is_broadsheet_pll_locked(struct broadsheetfb_par *par) +{ + return broadsheet_read_reg(par, 0x000A) & 0x0001; +} + +static int broadsheet_setup_plls(struct broadsheetfb_par *par) +{ + int retry_count = 0; + u16 tmp; + + /* disable arral saemipu mode */ + broadsheet_write_reg(par, 0x0006, 0x0000); + + broadsheet_write_reg(par, 0x0010, 0x0004); + broadsheet_write_reg(par, 0x0012, 0x5949); + broadsheet_write_reg(par, 0x0014, 0x0040); + broadsheet_write_reg(par, 0x0016, 0x0000); + + do { + if (retry_count++ > 100) + return -ETIMEDOUT; + mdelay(1); + } while (!is_broadsheet_pll_locked(par)); + + tmp = broadsheet_read_reg(par, 0x0006); + tmp &= ~0x1; + broadsheet_write_reg(par, 0x0006, tmp); + + return 0; +} + +static int broadsheet_setup_spi(struct broadsheetfb_par *par) +{ + + broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1)); + broadsheet_write_reg(par, 0x0208, 0x0001); + + return 0; +} + +static int broadsheet_setup_spiflash(struct broadsheetfb_par *par, + u16 *orig_sfmcd) +{ + + *orig_sfmcd = broadsheet_read_reg(par, 0x0204); + broadsheet_write_reg(par, 0x0208, 0); + broadsheet_write_reg(par, 0x0204, 0); + broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1)); + + return 0; +} + +static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par, + u16 reg, int bitnum, int val, + int timeout) +{ + u16 tmp; + + do { + tmp = broadsheet_read_reg(par, reg); + if (((tmp >> bitnum) & 1) == val) + return 0; + mdelay(1); + } while (timeout--); + + return -ETIMEDOUT; +} + +static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data) +{ + broadsheet_write_reg(par, 0x0202, (data | 0x100)); + + return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100); +} + +static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data) +{ + int err; + u16 tmp; + + broadsheet_write_reg(par, 0x0202, 0); + + err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100); + if (err) + return err; + + tmp = broadsheet_read_reg(par, 0x200); + + *data = tmp & 0xFF; + + return 0; +} + +static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par, + int timeout) +{ + u8 tmp; + int err; + + do { + broadsheet_write_reg(par, 0x0208, 1); + + err = broadsheet_spiflash_write_byte(par, 0x05); + if (err) + goto failout; + + err = broadsheet_spiflash_read_byte(par, &tmp); + if (err) + goto failout; + + broadsheet_write_reg(par, 0x0208, 0); + + if (!(tmp & 0x1)) + return 0; + + mdelay(5); + } while (timeout--); + + dev_err(par->info->device, "Timed out waiting for spiflash status\n"); + return -ETIMEDOUT; + +failout: + broadsheet_write_reg(par, 0x0208, 0); + return err; +} + +static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par, + u8 op, u32 addr) +{ + int i; + u8 tmp; + int err; + + broadsheet_write_reg(par, 0x0208, 1); + + err = broadsheet_spiflash_write_byte(par, op); + if (err) + return err; + + for (i = 2; i >= 0; i--) { + tmp = ((addr >> (i * 8)) & 0xFF); + err = broadsheet_spiflash_write_byte(par, tmp); + if (err) + return err; + } + + return err; +} + +static int broadsheet_verify_spiflash(struct broadsheetfb_par *par, + int *flash_type) +{ + int err = 0; + u8 sig; + + err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000); + if (err) + goto failout; + + err = broadsheet_spiflash_read_byte(par, &sig); + if (err) + goto failout; + + if ((sig != 0x10) && (sig != 0x11)) { + dev_err(par->info->device, "Unexpected flash type\n"); + err = -EINVAL; + goto failout; + } + + *flash_type = sig; + +failout: + broadsheet_write_reg(par, 0x0208, 0); + return err; +} + +static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par, + u16 *initial_sfmcd, int *flash_type) + +{ + int err; + + err = broadsheet_setup_plls(par); + if (err) + return err; + + broadsheet_write_reg(par, 0x0106, 0x0203); + + err = broadsheet_setup_spi(par); + if (err) + return err; + + err = broadsheet_setup_spiflash(par, initial_sfmcd); + if (err) + return err; + + return broadsheet_verify_spiflash(par, flash_type); +} + +static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par, + int mode) +{ + int err; + + broadsheet_write_reg(par, 0x0208, 1); + if (mode) + err = broadsheet_spiflash_write_byte(par, 0x06); + else + err = broadsheet_spiflash_write_byte(par, 0x04); + + broadsheet_write_reg(par, 0x0208, 0); + return err; +} + +static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par, + int addr) +{ + int err; + + broadsheet_spiflash_write_control(par, 1); + + err = broadsheet_spiflash_op_on_address(par, 0xD8, addr); + + broadsheet_write_reg(par, 0x0208, 0); + + if (err) + return err; + + err = broadsheet_spiflash_wait_for_status(par, 1000); + + return err; +} + +static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par, + int addr, int size, char *data) +{ + int err; + int i; + + err = broadsheet_spiflash_op_on_address(par, 0x03, addr); + if (err) + goto failout; + + for (i = 0; i < size; i++) { + err = broadsheet_spiflash_read_byte(par, &data[i]); + if (err) + goto failout; + } + +failout: + broadsheet_write_reg(par, 0x0208, 0); + return err; +} + +#define BS_SPIFLASH_PAGE_SIZE 256 +static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par, + int addr, const char *data) +{ + int err; + int i; + + broadsheet_spiflash_write_control(par, 1); + + err = broadsheet_spiflash_op_on_address(par, 0x02, addr); + if (err) + goto failout; + + for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) { + err = broadsheet_spiflash_write_byte(par, data[i]); + if (err) + goto failout; + } + + broadsheet_write_reg(par, 0x0208, 0); + + err = broadsheet_spiflash_wait_for_status(par, 100); + +failout: + return err; +} + +static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par, + int addr, const char *data, int sector_size) +{ + int i; + int err; + + for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) { + err = broadsheet_spiflash_write_page(par, addr + i, &data[i]); + if (err) + return err; + } + return 0; +} + +/* + * The caller must guarantee that the data to be rewritten is entirely + * contained within this sector. That is, data_start_addr + data_len + * must be less than sector_start_addr + sector_size. + */ +static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par, + int sector_size, int data_start_addr, + int data_len, const char *data) +{ + int err; + char *sector_buffer; + int tail_start_addr; + int start_sector_addr; + + sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL); + if (!sector_buffer) + return -ENOMEM; + + /* the start address of the sector is the 0th byte of that sector */ + start_sector_addr = (data_start_addr / sector_size) * sector_size; + + /* + * check if there is head data that we need to readback into our sector + * buffer first + */ + if (data_start_addr != start_sector_addr) { + /* + * we need to read every byte up till the start address of our + * data and we put it into our sector buffer. + */ + err = broadsheet_spiflash_read_range(par, start_sector_addr, + data_start_addr, sector_buffer); + if (err) + return err; + } + + /* now we copy our data into the right place in the sector buffer */ + memcpy(sector_buffer + data_start_addr, data, data_len); + + /* + * now we check if there is a tail section of the sector that we need to + * readback. + */ + tail_start_addr = (data_start_addr + data_len) % sector_size; + + if (tail_start_addr) { + int tail_len; + + tail_len = sector_size - tail_start_addr; + + /* now we read this tail into our sector buffer */ + err = broadsheet_spiflash_read_range(par, tail_start_addr, + tail_len, sector_buffer + tail_start_addr); + if (err) + return err; + } + + /* if we got here we have the full sector that we want to rewrite. */ + + /* first erase the sector */ + err = broadsheet_spiflash_erase_sector(par, start_sector_addr); + if (err) + return err; + + /* now write it */ + err = broadsheet_spiflash_write_sector(par, start_sector_addr, + sector_buffer, sector_size); + return err; +} + +static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr, + const u8 *wfm, int bytecount, int flash_type) +{ + int sector_size; + int err; + int cur_addr; + int writecount; + int maxlen; + int offset = 0; + + switch (flash_type) { + case 0x10: + sector_size = 32*1024; + break; + case 0x11: + default: + sector_size = 64*1024; + break; + } + + while (bytecount) { + cur_addr = wfm_addr + offset; + maxlen = roundup(cur_addr, sector_size) - cur_addr; + writecount = min(bytecount, maxlen); + + err = broadsheet_spiflash_rewrite_sector(par, sector_size, + cur_addr, writecount, wfm + offset); + if (err) + return err; + + offset += writecount; + bytecount -= writecount; + } + + return 0; +} + +static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par, + const u8 *wfm, size_t wfm_size) +{ + int err = 0; + u16 initial_sfmcd = 0; + int flash_type = 0; + + err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type); + if (err) + goto failout; + + err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type); + +failout: + broadsheet_write_reg(par, 0x0204, initial_sfmcd); + return err; +} + +static ssize_t broadsheet_loadstore_waveform(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + int err; + struct fb_info *info = dev_get_drvdata(dev); + struct broadsheetfb_par *par = info->par; + const struct firmware *fw_entry; + + if (len < 1) + return -EINVAL; + + err = request_firmware(&fw_entry, "broadsheet.wbf", dev); + if (err < 0) { + dev_err(dev, "Failed to get broadsheet waveform\n"); + goto err_failed; + } + + /* try to enforce reasonable min max on waveform */ + if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) { + dev_err(dev, "Invalid waveform\n"); + err = -EINVAL; + goto err_failed; + } + + mutex_lock(&(par->io_lock)); + err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data, + fw_entry->size); + + mutex_unlock(&(par->io_lock)); + if (err < 0) { + dev_err(dev, "Failed to store broadsheet waveform\n"); + goto err_failed; + } + + dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size); + + return len; + +err_failed: + return err; +} +static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL, + broadsheet_loadstore_waveform); + +/* upper level functions that manipulate the display and other stuff */ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) { u16 args[5]; - - args[0] = DPY_W; - args[1] = DPY_H; - args[2] = (100 | (1 << 8) | (1 << 9)); /* sdcfg */ - args[3] = 2; /* gdrv cfg */ - args[4] = (4 | (1 << 7)); /* lut index format */ + int xres = par->info->var.xres; + int yres = par->info->var.yres; + + args[0] = panel_table[par->panel_index].w; + args[1] = panel_table[par->panel_index].h; + args[2] = panel_table[par->panel_index].sdcfg; + args[3] = panel_table[par->panel_index].gdcfg; + args[4] = panel_table[par->panel_index].lutfmt; broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); /* did the controller really set it? */ broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); - args[0] = 4; /* fsync len */ - args[1] = (10 << 8) | 4; /* fend/fbegin len */ - args[2] = 10; /* line sync len */ - args[3] = (100 << 8) | 4; /* line end/begin len */ - args[4] = 6; /* pixel clock cfg */ + args[0] = panel_table[par->panel_index].fsynclen; + args[1] = panel_table[par->panel_index].fendfbegin; + args[2] = panel_table[par->panel_index].lsynclen; + args[3] = panel_table[par->panel_index].lendlbegin; + args[4] = panel_table[par->panel_index].pixclk; broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args); + broadsheet_write_reg32(par, 0x310, xres*yres*2); + /* setup waveform */ args[0] = 0x886; args[1] = 0; @@ -207,8 +818,9 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) args[0] = 0x154; broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); - broadsheet_burst_write(par, DPY_W*DPY_H/2, - (u16 *) par->info->screen_base); + broadsheet_burst_write(par, (panel_table[par->panel_index].w * + panel_table[par->panel_index].h)/2, + (u16 *) par->info->screen_base); broadsheet_send_command(par, BS_CMD_LD_IMG_END); @@ -222,6 +834,21 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) par->board->wait_for_rdy(par); } +static void __devinit broadsheet_identify(struct broadsheetfb_par *par) +{ + u16 rev, prc; + struct device *dev = par->info->device; + + rev = broadsheet_read_reg(par, BS_REG_REV); + prc = broadsheet_read_reg(par, BS_REG_PRC); + dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc); + + if (prc != 0x0047) + dev_warn(dev, "Unrecognized Broadsheet Product Code\n"); + if (rev != 0x0100) + dev_warn(dev, "Unrecognized Broadsheet Revision\n"); +} + static void __devinit broadsheet_init(struct broadsheetfb_par *par) { broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN); @@ -236,6 +863,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par, u16 args[5]; unsigned char *buf = (unsigned char *)par->info->screen_base; + mutex_lock(&(par->io_lock)); /* y1 must be a multiple of 4 so drop the lower bits */ y1 &= 0xFFFC; /* y2 must be a multiple of 4 , but - 1 so up the lower bits */ @@ -265,6 +893,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par, broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); par->board->wait_for_rdy(par); + mutex_unlock(&(par->io_lock)); } @@ -272,13 +901,15 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par) { u16 args[5]; + mutex_lock(&(par->io_lock)); args[0] = 0x3 << 4; broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); args[0] = 0x154; broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); - broadsheet_burst_write(par, DPY_W*DPY_H/2, - (u16 *) par->info->screen_base); + broadsheet_burst_write(par, (panel_table[par->panel_index].w * + panel_table[par->panel_index].h)/2, + (u16 *) par->info->screen_base); broadsheet_send_command(par, BS_CMD_LD_IMG_END); @@ -290,7 +921,7 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); par->board->wait_for_rdy(par); - + mutex_unlock(&(par->io_lock)); } /* this is called back from the deferred io workqueue */ @@ -436,6 +1067,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) unsigned char *videomemory; struct broadsheetfb_par *par; int i; + int dpyw, dpyh; + int panel_index; /* pick up board specific routines */ board = dev->dev.platform_data; @@ -450,7 +1083,24 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) if (!info) goto err; - videomemorysize = (DPY_W*DPY_H); + switch (board->get_panel_type()) { + case 37: + panel_index = 1; + break; + case 97: + panel_index = 2; + break; + case 6: + default: + panel_index = 0; + break; + } + + dpyw = panel_table[panel_index].w; + dpyh = panel_table[panel_index].h; + + videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE); + videomemory = vmalloc(videomemorysize); if (!videomemory) goto err_fb_rel; @@ -460,16 +1110,25 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) info->screen_base = (char *)videomemory; info->fbops = &broadsheetfb_ops; + broadsheetfb_var.xres = dpyw; + broadsheetfb_var.yres = dpyh; + broadsheetfb_var.xres_virtual = dpyw; + broadsheetfb_var.yres_virtual = dpyh; info->var = broadsheetfb_var; + + broadsheetfb_fix.line_length = dpyw; info->fix = broadsheetfb_fix; info->fix.smem_len = videomemorysize; par = info->par; + par->panel_index = panel_index; par->info = info; par->board = board; par->write_reg = broadsheet_write_reg; par->read_reg = broadsheet_read_reg; init_waitqueue_head(&par->waitq); + mutex_init(&par->io_lock); + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; info->fbdefio = &broadsheetfb_defio; @@ -496,13 +1155,20 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) if (retval < 0) goto err_free_irq; + broadsheet_identify(par); + broadsheet_init(par); retval = register_framebuffer(info); if (retval < 0) goto err_free_irq; + platform_set_drvdata(dev, info); + retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform); + if (retval < 0) + goto err_unreg_fb; + printk(KERN_INFO "fb%d: Broadsheet frame buffer, using %dK of video memory\n", info->node, videomemorysize >> 10); @@ -510,6 +1176,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) return 0; +err_unreg_fb: + unregister_framebuffer(info); err_free_irq: board->cleanup(par); err_cmap: @@ -530,6 +1198,8 @@ static int __devexit broadsheetfb_remove(struct platform_device *dev) if (info) { struct broadsheetfb_par *par = info->par; + + device_remove_file(info->dev, &dev_attr_loadstore_waveform); unregister_framebuffer(info); fb_deferred_io_cleanup(info); par->board->cleanup(par); diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c index fabb0c5..8280a58 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfb.c @@ -31,15 +31,6 @@ #define CARMINE_MEM_SIZE 0x8000000 #define DRV_NAME "mb862xxfb" -#if defined(CONFIG_LWMON5) -static struct mb862xx_gc_mode lwmon5_gc_mode = { - /* Mode for Sharp LQ104V1DG61 TFT LCD Panel */ - { "640x480", 60, 640, 480, 40000, 48, 16, 32, 11, 96, 2, 0, 0, 0 }, - /* 16 bits/pixel, 32MB, 100MHz, SDRAM memory mode value */ - 16, 0x2000000, GC_CCF_COT_100, 0x414fb7f2 -}; -#endif - #if defined(CONFIG_SOCRATES) static struct mb862xx_gc_mode socrates_gc_mode = { /* Mode for Prime View PM070WL4 TFT LCD Panel */ @@ -600,10 +591,6 @@ static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, goto irqdisp; } -#if defined(CONFIG_LWMON5) - par->gc_mode = &lwmon5_gc_mode; -#endif - #if defined(CONFIG_SOCRATES) par->gc_mode = &socrates_gc_mode; #endif diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index 01f77bc..afea9ab 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c @@ -693,7 +693,7 @@ static void __devinit setup_memc(struct fb_info *fbi) unsigned long tmp; int i; - /* FIXME: use platfrom specific parameters */ + /* FIXME: use platform specific parameters */ /* setup SDRAM controller */ write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | LMCFG_LMA_TS), diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 0129f1b..b895aae 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -893,7 +893,7 @@ const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var, } /** - * fb_add_videomode: adds videomode entry to modelist + * fb_add_videomode - adds videomode entry to modelist * @mode: videomode to add * @head: struct list_head of modelist * @@ -928,7 +928,7 @@ int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head) } /** - * fb_delete_videomode: removed videomode entry from modelist + * fb_delete_videomode - removed videomode entry from modelist * @mode: videomode to remove * @head: struct list_head of modelist * @@ -953,7 +953,7 @@ void fb_delete_videomode(const struct fb_videomode *mode, } /** - * fb_destroy_modelist: destroy modelist + * fb_destroy_modelist - destroy modelist * @head: struct list_head of modelist */ void fb_destroy_modelist(struct list_head *head) @@ -968,7 +968,7 @@ void fb_destroy_modelist(struct list_head *head) EXPORT_SYMBOL_GPL(fb_destroy_modelist); /** - * fb_videomode_to_modelist: convert mode array to mode list + * fb_videomode_to_modelist - convert mode array to mode list * @modedb: array of struct fb_videomode * @num: number of entries in array * @head: struct list_head of modelist diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c new file mode 100644 index 0000000..6bf0d46 --- /dev/null +++ b/drivers/video/nuc900fb.c @@ -0,0 +1,779 @@ +/* + * + * Copyright (c) 2009 Nuvoton technology corporation + * All rights reserved. + * + * 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. + * + * Description: + * Nuvoton LCD Controller Driver + * Author: + * Wang Qiang (rurality.linux@gmail.com) 2009/12/11 + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/workqueue.h> +#include <linux/wait.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/cpufreq.h> +#include <linux/io.h> +#include <linux/pm.h> +#include <linux/device.h> + +#include <mach/map.h> +#include <mach/regs-clock.h> +#include <mach/regs-ldm.h> +#include <mach/fb.h> +#include <mach/clkdev.h> + +#include "nuc900fb.h" + + +/* + * Initialize the nuc900 video (dual) buffer address + */ +static void nuc900fb_set_lcdaddr(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + void __iomem *regs = fbi->io; + unsigned long vbaddr1, vbaddr2; + + vbaddr1 = info->fix.smem_start; + vbaddr2 = info->fix.smem_start; + vbaddr2 += info->fix.line_length * info->var.yres; + + /* set frambuffer start phy addr*/ + writel(vbaddr1, regs + REG_LCM_VA_BADDR0); + writel(vbaddr2, regs + REG_LCM_VA_BADDR1); + + writel(fbi->regs.lcd_va_fbctrl, regs + REG_LCM_VA_FBCTRL); + writel(fbi->regs.lcd_va_scale, regs + REG_LCM_VA_SCALE); +} + +/* + * calculate divider for lcd div + */ +static unsigned int nuc900fb_calc_pixclk(struct nuc900fb_info *fbi, + unsigned long pixclk) +{ + unsigned long clk = fbi->clk_rate; + unsigned long long div; + + /* pixclk is in picseconds. our clock is in Hz*/ + /* div = (clk * pixclk)/10^12 */ + div = (unsigned long long)clk * pixclk; + div >>= 12; + do_div(div, 625 * 625UL * 625); + + dev_dbg(fbi->dev, "pixclk %ld, divisor is %lld\n", pixclk, div); + + return div; +} + +/* + * Check the video params of 'var'. + */ +static int nuc900fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data; + struct nuc900fb_display *display = NULL; + struct nuc900fb_display *default_display = mach_info->displays + + mach_info->default_display; + int i; + + dev_dbg(fbi->dev, "check_var(var=%p, info=%p)\n", var, info); + + /* validate x/y resolution */ + /* choose default mode if possible */ + if (var->xres == default_display->xres && + var->yres == default_display->yres && + var->bits_per_pixel == default_display->bpp) + display = default_display; + else + for (i = 0; i < mach_info->num_displays; i++) + if (var->xres == mach_info->displays[i].xres && + var->yres == mach_info->displays[i].yres && + var->bits_per_pixel == mach_info->displays[i].bpp) { + display = mach_info->displays + i; + break; + } + + if (display == NULL) { + printk(KERN_ERR "wrong resolution or depth %dx%d at %d bit per pixel\n", + var->xres, var->yres, var->bits_per_pixel); + return -EINVAL; + } + + /* it should be the same size as the display */ + var->xres_virtual = display->xres; + var->yres_virtual = display->yres; + var->height = display->height; + var->width = display->width; + + /* copy lcd settings */ + var->pixclock = display->pixclock; + var->left_margin = display->left_margin; + var->right_margin = display->right_margin; + var->upper_margin = display->upper_margin; + var->lower_margin = display->lower_margin; + var->vsync_len = display->vsync_len; + var->hsync_len = display->hsync_len; + + var->transp.offset = 0; + var->transp.length = 0; + + fbi->regs.lcd_dccs = display->dccs; + fbi->regs.lcd_device_ctrl = display->devctl; + fbi->regs.lcd_va_fbctrl = display->fbctrl; + fbi->regs.lcd_va_scale = display->scale; + + /* set R/G/B possions */ + switch (var->bits_per_pixel) { + case 1: + case 2: + case 4: + case 8: + default: + var->red.offset = 0; + var->red.length = var->bits_per_pixel; + var->green = var->red; + var->blue = var->red; + break; + case 12: + var->red.length = 4; + var->green.length = 4; + var->blue.length = 4; + var->red.offset = 8; + var->green.offset = 4; + var->blue.offset = 0; + break; + case 16: + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + break; + case 18: + var->red.length = 6; + var->green.length = 6; + var->blue.length = 6; + var->red.offset = 12; + var->green.offset = 6; + var->blue.offset = 0; + break; + case 32: + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + break; + } + + return 0; +} + +/* + * Calculate lcd register values from var setting & save into hw + */ +static void nuc900fb_calculate_lcd_regs(const struct fb_info *info, + struct nuc900fb_hw *regs) +{ + const struct fb_var_screeninfo *var = &info->var; + int vtt = var->height + var->upper_margin + var->lower_margin; + int htt = var->width + var->left_margin + var->right_margin; + int hsync = var->width + var->right_margin; + int vsync = var->height + var->lower_margin; + + regs->lcd_crtc_size = LCM_CRTC_SIZE_VTTVAL(vtt) | + LCM_CRTC_SIZE_HTTVAL(htt); + regs->lcd_crtc_dend = LCM_CRTC_DEND_VDENDVAL(var->height) | + LCM_CRTC_DEND_HDENDVAL(var->width); + regs->lcd_crtc_hr = LCM_CRTC_HR_EVAL(var->width + 5) | + LCM_CRTC_HR_SVAL(var->width + 1); + regs->lcd_crtc_hsync = LCM_CRTC_HSYNC_EVAL(hsync + var->hsync_len) | + LCM_CRTC_HSYNC_SVAL(hsync); + regs->lcd_crtc_vr = LCM_CRTC_VR_EVAL(vsync + var->vsync_len) | + LCM_CRTC_VR_SVAL(vsync); + +} + +/* + * Activate (set) the controller from the given framebuffer + * information + */ +static void nuc900fb_activate_var(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + void __iomem *regs = fbi->io; + struct fb_var_screeninfo *var = &info->var; + int clkdiv; + + clkdiv = nuc900fb_calc_pixclk(fbi, var->pixclock) - 1; + if (clkdiv < 0) + clkdiv = 0; + + nuc900fb_calculate_lcd_regs(info, &fbi->regs); + + /* set the new lcd registers*/ + + dev_dbg(fbi->dev, "new lcd register set:\n"); + dev_dbg(fbi->dev, "dccs = 0x%08x\n", fbi->regs.lcd_dccs); + dev_dbg(fbi->dev, "dev_ctl = 0x%08x\n", fbi->regs.lcd_device_ctrl); + dev_dbg(fbi->dev, "crtc_size = 0x%08x\n", fbi->regs.lcd_crtc_size); + dev_dbg(fbi->dev, "crtc_dend = 0x%08x\n", fbi->regs.lcd_crtc_dend); + dev_dbg(fbi->dev, "crtc_hr = 0x%08x\n", fbi->regs.lcd_crtc_hr); + dev_dbg(fbi->dev, "crtc_hsync = 0x%08x\n", fbi->regs.lcd_crtc_hsync); + dev_dbg(fbi->dev, "crtc_vr = 0x%08x\n", fbi->regs.lcd_crtc_vr); + + writel(fbi->regs.lcd_device_ctrl, regs + REG_LCM_DEV_CTRL); + writel(fbi->regs.lcd_crtc_size, regs + REG_LCM_CRTC_SIZE); + writel(fbi->regs.lcd_crtc_dend, regs + REG_LCM_CRTC_DEND); + writel(fbi->regs.lcd_crtc_hr, regs + REG_LCM_CRTC_HR); + writel(fbi->regs.lcd_crtc_hsync, regs + REG_LCM_CRTC_HSYNC); + writel(fbi->regs.lcd_crtc_vr, regs + REG_LCM_CRTC_VR); + + /* set lcd address pointers */ + nuc900fb_set_lcdaddr(info); + + writel(fbi->regs.lcd_dccs, regs + REG_LCM_DCCS); +} + +/* + * Alters the hardware state. + * + */ +static int nuc900fb_set_par(struct fb_info *info) +{ + struct fb_var_screeninfo *var = &info->var; + + switch (var->bits_per_pixel) { + case 32: + case 24: + case 18: + case 16: + case 12: + info->fix.visual = FB_VISUAL_TRUECOLOR; + break; + case 1: + info->fix.visual = FB_VISUAL_MONO01; + break; + default: + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + break; + } + + info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; + + /* activate this new configuration */ + nuc900fb_activate_var(info); + return 0; +} + +static inline unsigned int chan_to_field(unsigned int chan, + struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int nuc900fb_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + unsigned int val; + + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + /* true-colour, use pseuo-palette */ + if (regno < 16) { + u32 *pal = info->pseudo_palette; + + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue, &info->var.blue); + pal[regno] = val; + } + break; + + default: + return 1; /* unknown type */ + } + return 0; +} + +/** + * nuc900fb_blank + * + */ +static int nuc900fb_blank(int blank_mode, struct fb_info *info) +{ + + return 0; +} + +static struct fb_ops nuc900fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = nuc900fb_check_var, + .fb_set_par = nuc900fb_set_par, + .fb_blank = nuc900fb_blank, + .fb_setcolreg = nuc900fb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + + +static inline void modify_gpio(void __iomem *reg, + unsigned long set, unsigned long mask) +{ + unsigned long tmp; + tmp = readl(reg) & ~mask; + writel(tmp | set, reg); +} + +/* + * Initialise LCD-related registers + */ +static int nuc900fb_init_registers(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data; + void __iomem *regs = fbi->io; + + /*reset the display engine*/ + writel(0, regs + REG_LCM_DCCS); + writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_ENG_RST, + regs + REG_LCM_DCCS); + ndelay(100); + writel(readl(regs + REG_LCM_DCCS) & (~LCM_DCCS_ENG_RST), + regs + REG_LCM_DCCS); + ndelay(100); + + writel(0, regs + REG_LCM_DEV_CTRL); + + /* config gpio output */ + modify_gpio(W90X900_VA_GPIO + 0x54, mach_info->gpio_dir, + mach_info->gpio_dir_mask); + modify_gpio(W90X900_VA_GPIO + 0x58, mach_info->gpio_data, + mach_info->gpio_data_mask); + + return 0; +} + + +/* + * Alloc the SDRAM region of NUC900 for the frame buffer. + * The buffer should be a non-cached, non-buffered, memory region + * to allow palette and pixel writes without flushing the cache. + */ +static int __init nuc900fb_map_video_memory(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + dma_addr_t map_dma; + unsigned long map_size = PAGE_ALIGN(info->fix.smem_len); + + dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n", + fbi, map_size); + + info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, + &map_dma, GFP_KERNEL); + + if (!info->screen_base) + return -ENOMEM; + + memset(info->screen_base, 0x00, map_size); + info->fix.smem_start = map_dma; + + return 0; +} + +static inline void nuc900fb_unmap_video_memory(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len), + info->screen_base, info->fix.smem_start); +} + +static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id) +{ + struct nuc900fb_info *fbi = dev_id; + void __iomem *regs = fbi->io; + void __iomem *irq_base = fbi->irq_base; + unsigned long lcdirq = readl(regs + REG_LCM_INT_CS); + + if (lcdirq & LCM_INT_CS_DISP_F_STATUS) { + writel(readl(irq_base) | 1<<30, irq_base); + + /* wait VA_EN low */ + if ((readl(regs + REG_LCM_DCCS) & + LCM_DCCS_SINGLE) == LCM_DCCS_SINGLE) + while ((readl(regs + REG_LCM_DCCS) & + LCM_DCCS_VA_EN) == LCM_DCCS_VA_EN) + ; + /* display_out-enable */ + writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_DISP_OUT_EN, + regs + REG_LCM_DCCS); + /* va-enable*/ + writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_VA_EN, + regs + REG_LCM_DCCS); + } else if (lcdirq & LCM_INT_CS_UNDERRUN_INT) { + writel(readl(irq_base) | LCM_INT_CS_UNDERRUN_INT, irq_base); + } else if (lcdirq & LCM_INT_CS_BUS_ERROR_INT) { + writel(readl(irq_base) | LCM_INT_CS_BUS_ERROR_INT, irq_base); + } + + return IRQ_HANDLED; +} + +#ifdef CONFIG_CPU_FREQ + +static int nuc900fb_cpufreq_transition(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct nuc900fb_info *info; + struct fb_info *fbinfo; + long delta_f; + info = container_of(nb, struct nuc900fb_info, freq_transition); + fbinfo = platform_get_drvdata(to_platform_device(info->dev)); + + delta_f = info->clk_rate - clk_get_rate(info->clk); + + if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) || + (val == CPUFREQ_PRECHANGE && delta_f < 0)) { + info->clk_rate = clk_get_rate(info->clk); + nuc900fb_activate_var(fbinfo); + } + + return 0; +} + +static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi) +{ + fbi->freq_transition.notifier_call = nuc900fb_cpufreq_transition; + return cpufreq_register_notifier(&fbi->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); +} + +static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *fbi) +{ + cpufreq_unregister_notifier(&fbi->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); +} +#else +static inline int nuc900fb_cpufreq_transition(struct notifier_block *nb, + unsigned long val, void *data) +{ + return 0; +} + +static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi) +{ + return 0; +} + +static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *info) +{ +} +#endif + +static char driver_name[] = "nuc900fb"; + +static int __devinit nuc900fb_probe(struct platform_device *pdev) +{ + struct nuc900fb_info *fbi; + struct nuc900fb_display *display; + struct fb_info *fbinfo; + struct nuc900fb_mach_info *mach_info; + struct resource *res; + int ret; + int irq; + int i; + int size; + + dev_dbg(&pdev->dev, "devinit\n"); + mach_info = pdev->dev.platform_data; + if (mach_info == NULL) { + dev_err(&pdev->dev, + "no platform data for lcd, cannot attach\n"); + return -EINVAL; + } + + if (mach_info->default_display > mach_info->num_displays) { + dev_err(&pdev->dev, + "default display No. is %d but only %d displays \n", + mach_info->default_display, mach_info->num_displays); + return -EINVAL; + } + + + display = mach_info->displays + mach_info->default_display; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq for device\n"); + return -ENOENT; + } + + fbinfo = framebuffer_alloc(sizeof(struct nuc900fb_info), &pdev->dev); + if (!fbinfo) + return -ENOMEM; + + platform_set_drvdata(pdev, fbinfo); + + fbi = fbinfo->par; + fbi->dev = &pdev->dev; + +#ifdef CONFIG_CPU_NUC950 + fbi->drv_type = LCDDRV_NUC950; +#endif + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + size = (res->end - res->start) + 1; + fbi->mem = request_mem_region(res->start, size, pdev->name); + if (fbi->mem == NULL) { + dev_err(&pdev->dev, "failed to alloc memory region\n"); + ret = -ENOENT; + goto free_fb; + } + + fbi->io = ioremap(res->start, size); + if (fbi->io == NULL) { + dev_err(&pdev->dev, "ioremap() of lcd registers failed\n"); + ret = -ENXIO; + goto release_mem_region; + } + + fbi->irq_base = fbi->io + REG_LCM_INT_CS; + + + /* Stop the LCD */ + writel(0, fbi->io + REG_LCM_DCCS); + + /* fill the fbinfo*/ + strcpy(fbinfo->fix.id, driver_name); + fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; + fbinfo->fix.type_aux = 0; + fbinfo->fix.xpanstep = 0; + fbinfo->fix.ypanstep = 0; + fbinfo->fix.ywrapstep = 0; + fbinfo->fix.accel = FB_ACCEL_NONE; + fbinfo->var.nonstd = 0; + fbinfo->var.activate = FB_ACTIVATE_NOW; + fbinfo->var.accel_flags = 0; + fbinfo->var.vmode = FB_VMODE_NONINTERLACED; + fbinfo->fbops = &nuc900fb_ops; + fbinfo->flags = FBINFO_FLAG_DEFAULT; + fbinfo->pseudo_palette = &fbi->pseudo_pal; + + ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED, + pdev->name, fbinfo); + if (ret) { + dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n", + irq, ret); + ret = -EBUSY; + goto release_regs; + } + + nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2); + + fbi->clk = clk_get(&pdev->dev, NULL); + if (!fbi->clk || IS_ERR(fbi->clk)) { + printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n"); + ret = -ENOENT; + goto release_irq; + } + + clk_enable(fbi->clk); + dev_dbg(&pdev->dev, "got and enabled clock\n"); + + fbi->clk_rate = clk_get_rate(fbi->clk); + + /* calutate the video buffer size */ + for (i = 0; i < mach_info->num_displays; i++) { + unsigned long smem_len = mach_info->displays[i].xres; + smem_len *= mach_info->displays[i].yres; + smem_len *= mach_info->displays[i].bpp; + smem_len >>= 3; + if (fbinfo->fix.smem_len < smem_len) + fbinfo->fix.smem_len = smem_len; + } + + /* Initialize Video Memory */ + ret = nuc900fb_map_video_memory(fbinfo); + if (ret) { + printk(KERN_ERR "Failed to allocate video RAM: %x\n", ret); + goto release_clock; + } + + dev_dbg(&pdev->dev, "got video memory\n"); + + fbinfo->var.xres = display->xres; + fbinfo->var.yres = display->yres; + fbinfo->var.bits_per_pixel = display->bpp; + + nuc900fb_init_registers(fbinfo); + + nuc900fb_check_var(&fbinfo->var, fbinfo); + + ret = nuc900fb_cpufreq_register(fbi); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register cpufreq\n"); + goto free_video_memory; + } + + ret = register_framebuffer(fbinfo); + if (ret) { + printk(KERN_ERR "failed to register framebuffer device: %d\n", + ret); + goto free_cpufreq; + } + + printk(KERN_INFO "fb%d: %s frame buffer device\n", + fbinfo->node, fbinfo->fix.id); + + return 0; + +free_cpufreq: + nuc900fb_cpufreq_deregister(fbi); +free_video_memory: + nuc900fb_unmap_video_memory(fbinfo); +release_clock: + clk_disable(fbi->clk); + clk_put(fbi->clk); +release_irq: + free_irq(irq, fbi); +release_regs: + iounmap(fbi->io); +release_mem_region: + release_mem_region((unsigned long)fbi->mem, size); +free_fb: + framebuffer_release(fbinfo); + return ret; +} + +/* + * shutdown the lcd controller + */ +static void nuc900fb_stop_lcd(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + void __iomem *regs = fbi->io; + + writel((~LCM_DCCS_DISP_INT_EN) | (~LCM_DCCS_VA_EN) | (~LCM_DCCS_OSD_EN), + regs + REG_LCM_DCCS); +} + +/* + * Cleanup + */ +static int nuc900fb_remove(struct platform_device *pdev) +{ + struct fb_info *fbinfo = platform_get_drvdata(pdev); + struct nuc900fb_info *fbi = fbinfo->par; + int irq; + + nuc900fb_stop_lcd(fbinfo); + msleep(1); + + nuc900fb_unmap_video_memory(fbinfo); + + iounmap(fbi->io); + + irq = platform_get_irq(pdev, 0); + free_irq(irq, fbi); + + release_resource(fbi->mem); + kfree(fbi->mem); + + platform_set_drvdata(pdev, NULL); + framebuffer_release(fbinfo); + + return 0; +} + +#ifdef CONFIG_PM + +/* + * suspend and resume support for the lcd controller + */ + +static int nuc900fb_suspend(struct platform_device *dev, pm_message_t state) +{ + struct fb_info *fbinfo = platform_get_drvdata(dev); + struct nuc900fb_info *info = fbinfo->par; + + nuc900fb_stop_lcd(); + msleep(1); + clk_disable(info->clk); + return 0; +} + +static int nuc900fb_resume(struct platform_device *dev) +{ + struct fb_info *fbinfo = platform_get_drvdata(dev); + struct nuc900fb_info *fbi = fbinfo->par; + + printk(KERN_INFO "nuc900fb resume\n"); + + clk_enable(fbi->clk); + msleep(1); + + nuc900fb_init_registers(fbinfo); + nuc900fb_activate_var(bfinfo); + + return 0; +} + +#else +#define nuc900fb_suspend NULL +#define nuc900fb_resume NULL +#endif + +static struct platform_driver nuc900fb_driver = { + .probe = nuc900fb_probe, + .remove = nuc900fb_remove, + .suspend = nuc900fb_suspend, + .resume = nuc900fb_resume, + .driver = { + .name = "nuc900-lcd", + .owner = THIS_MODULE, + }, +}; + +int __devinit nuc900fb_init(void) +{ + return platform_driver_register(&nuc900fb_driver); +} + +static void __exit nuc900fb_cleanup(void) +{ + platform_driver_unregister(&nuc900fb_driver); +} + +module_init(nuc900fb_init); +module_exit(nuc900fb_cleanup); + +MODULE_DESCRIPTION("Framebuffer driver for the NUC900"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/nuc900fb.h b/drivers/video/nuc900fb.h new file mode 100644 index 0000000..6c23aa3 --- /dev/null +++ b/drivers/video/nuc900fb.h @@ -0,0 +1,55 @@ +/* + * + * Copyright (c) 2009 Nuvoton technology corporation + * All rights reserved. + * + * 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. + * + * Auther: + * Wang Qiang(rurality.linux@gmail.com) 2009/12/16 + */ + +#ifndef __NUC900FB_H +#define __NUC900FB_H + +#include <mach/map.h> +#include <mach/fb.h> + +enum nuc900_lcddrv_type { + LCDDRV_NUC910, + LCDDRV_NUC930, + LCDDRV_NUC932, + LCDDRV_NUC950, + LCDDRV_NUC960, +}; + + +#define PALETTE_BUFFER_SIZE 256 +#define PALETTE_BUFF_CLEAR (0x80000000) /* entry is clear/invalid */ + +struct nuc900fb_info { + struct device *dev; + struct clk *clk; + + struct resource *mem; + void __iomem *io; + void __iomem *irq_base; + int drv_type; + struct nuc900fb_hw regs; + unsigned long clk_rate; + +#ifdef CONFIG_CPU_FREQ + struct notifier_block freq_transition; +#endif + + /* keep these registers in case we need to re-write palette */ + u32 palette_buffer[PALETTE_BUFFER_SIZE]; + u32 pseudo_pal[16]; +}; + +int nuc900fb_init(void); + +#endif /* __NUC900FB_H */ diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c index a334839..9557f96 100644 --- a/drivers/video/omap/lcdc.c +++ b/drivers/video/omap/lcdc.c @@ -389,7 +389,7 @@ static int omap_lcdc_enable_plane(int plane, int enable) /* * Configure the LCD DMA for a palette load operation and do the palette * downloading synchronously. We don't use the frame+palette load mode of - * the controller, since the palette can always be downloaded seperately. + * the controller, since the palette can always be downloaded separately. */ static void load_palette(void) { diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 36436ee..27f93aa 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -896,7 +896,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green, * Pseudocolor: * uses offset = 0 && length = DAC register width. * var->{color}.offset is 0 - * var->{color}.length contains widht of DAC + * var->{color}.length contains width of DAC * cmap is not used * DAC[X] is programmed to (red, green, blue) * Truecolor: diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index 0deb0a8..7b63429 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -517,12 +517,12 @@ s1d13xxxfb_bitblt_copyarea(struct fb_info *info, const struct fb_copyarea *area) src = (sy * stride) + (bpp * sx); } - /* set source adress */ + /* set source address */ s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff)); s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff); s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff); - /* set destination adress */ + /* set destination address */ s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff)); s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff); s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff); diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 9d2b6bc..a531a0f 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1891,9 +1891,6 @@ static struct fb_ops sisfb_ops = { .fb_fillrect = fbcon_sis_fillrect, .fb_copyarea = fbcon_sis_copyarea, .fb_imageblit = cfb_imageblit, -#ifdef CONFIG_FB_SOFT_CURSOR - .fb_cursor = soft_cursor, -#endif .fb_sync = fbcon_sis_sync, #ifdef SIS_NEW_CONFIG_COMPAT .fb_compat_ioctl= sisfb_ioctl, diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 35370d0..b7dc180 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -411,7 +411,7 @@ static int sm501fb_set_par_common(struct fb_info *info, struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; unsigned long pixclock; /* pixelclock in Hz */ - unsigned long sm501pixclock; /* pixelclock the 501 can achive in Hz */ + unsigned long sm501pixclock; /* pixelclock the 501 can achieve in Hz */ unsigned int mem_type; unsigned int clock_type; unsigned int head_addr; diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 609d0a5..79840f1 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -1102,7 +1102,7 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp) * detect dac type * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset, * dram refresh disabled, FbiInit remaped. - * TODO: mmh.. maybe i shoud put the "prerequisite" in the func ... + * TODO: mmh.. maybe i should put the "prerequisite" in the func ... */ diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c new file mode 100644 index 0000000..a8248c0 --- /dev/null +++ b/drivers/video/sunxvr1000.c @@ -0,0 +1,228 @@ +/* sunxvr1000.c: Sun XVR-1000 driver for sparc64 systems + * + * Copyright (C) 2010 David S. Miller (davem@davemloft.net) + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/of_device.h> + +struct gfb_info { + struct fb_info *info; + + char __iomem *fb_base; + unsigned long fb_base_phys; + + struct device_node *of_node; + + unsigned int width; + unsigned int height; + unsigned int depth; + unsigned int fb_size; + + u32 pseudo_palette[16]; +}; + +static int __devinit gfb_get_props(struct gfb_info *gp) +{ + gp->width = of_getintprop_default(gp->of_node, "width", 0); + gp->height = of_getintprop_default(gp->of_node, "height", 0); + gp->depth = of_getintprop_default(gp->of_node, "depth", 32); + + if (!gp->width || !gp->height) { + printk(KERN_ERR "gfb: Critical properties missing for %s\n", + gp->of_node->full_name); + return -EINVAL; + } + + return 0; +} + +static int gfb_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + u32 value; + + if (regno < 16) { + red >>= 8; + green >>= 8; + blue >>= 8; + + value = (blue << 16) | (green << 8) | red; + ((u32 *)info->pseudo_palette)[regno] = value; + } + + return 0; +} + +static struct fb_ops gfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = gfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int __devinit gfb_set_fbinfo(struct gfb_info *gp) +{ + struct fb_info *info = gp->info; + struct fb_var_screeninfo *var = &info->var; + + info->flags = FBINFO_DEFAULT; + info->fbops = &gfb_ops; + info->screen_base = gp->fb_base; + info->screen_size = gp->fb_size; + + info->pseudo_palette = gp->pseudo_palette; + + /* Fill fix common fields */ + strlcpy(info->fix.id, "gfb", sizeof(info->fix.id)); + info->fix.smem_start = gp->fb_base_phys; + info->fix.smem_len = gp->fb_size; + info->fix.type = FB_TYPE_PACKED_PIXELS; + if (gp->depth == 32 || gp->depth == 24) + info->fix.visual = FB_VISUAL_TRUECOLOR; + else + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + + var->xres = gp->width; + var->yres = gp->height; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + var->bits_per_pixel = gp->depth; + + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + + if (fb_alloc_cmap(&info->cmap, 256, 0)) { + printk(KERN_ERR "gfb: Cannot allocate color map.\n"); + return -ENOMEM; + } + + return 0; +} + +static int __devinit gfb_probe(struct of_device *op, + const struct of_device_id *match) +{ + struct device_node *dp = op->node; + struct fb_info *info; + struct gfb_info *gp; + int err; + + info = framebuffer_alloc(sizeof(struct gfb_info), &op->dev); + if (!info) { + printk(KERN_ERR "gfb: Cannot allocate fb_info\n"); + err = -ENOMEM; + goto err_out; + } + + gp = info->par; + gp->info = info; + gp->of_node = dp; + + gp->fb_base_phys = op->resource[6].start; + + err = gfb_get_props(gp); + if (err) + goto err_release_fb; + + /* Framebuffer length is the same regardless of resolution. */ + info->fix.line_length = 16384; + gp->fb_size = info->fix.line_length * gp->height; + + gp->fb_base = of_ioremap(&op->resource[6], 0, + gp->fb_size, "gfb fb"); + if (!gp->fb_base) + goto err_release_fb; + + err = gfb_set_fbinfo(gp); + if (err) + goto err_unmap_fb; + + printk("gfb: Found device at %s\n", dp->full_name); + + err = register_framebuffer(info); + if (err < 0) { + printk(KERN_ERR "gfb: Could not register framebuffer %s\n", + dp->full_name); + goto err_unmap_fb; + } + + dev_set_drvdata(&op->dev, info); + + return 0; + +err_unmap_fb: + of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size); + +err_release_fb: + framebuffer_release(info); + +err_out: + return err; +} + +static int __devexit gfb_remove(struct of_device *op) +{ + struct fb_info *info = dev_get_drvdata(&op->dev); + struct gfb_info *gp = info->par; + + unregister_framebuffer(info); + + iounmap(gp->fb_base); + + of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size); + + framebuffer_release(info); + + dev_set_drvdata(&op->dev, NULL); + + return 0; +} + +static const struct of_device_id gfb_match[] = { + { + .name = "SUNW,gfb", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, ffb_match); + +static struct of_platform_driver gfb_driver = { + .name = "gfb", + .match_table = gfb_match, + .probe = gfb_probe, + .remove = __devexit_p(gfb_remove), +}; + +static int __init gfb_init(void) +{ + if (fb_get_options("gfb", NULL)) + return -ENODEV; + + return of_register_driver(&gfb_driver, &of_bus_type); +} + +static void __exit gfb_exit(void) +{ + of_unregister_driver(&gfb_driver); +} + +module_init(gfb_init); +module_exit(gfb_exit); + +MODULE_DESCRIPTION("framebuffer driver for Sun XVR-1000 graphics"); +MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile index e533b4b..eeed238 100644 --- a/drivers/video/via/Makefile +++ b/drivers/video/via/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_FB_VIA) += viafb.o -viafb-y :=viafbdev.o hw.o iface.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o +viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index 474f428..8c06bd3 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h @@ -107,7 +107,6 @@ struct tmds_chip_information { int tmds_chip_name; int tmds_chip_slave_addr; - int dvi_panel_id; int data_mode; int output_interface; int i2c_port; @@ -142,14 +141,9 @@ struct tmds_setting_information { int iga_path; int h_active; int v_active; - int bpp; - int refresh_rate; - int get_dvi_size_method; int max_pixel_clock; - int dvi_panel_size; - int dvi_panel_hres; - int dvi_panel_vres; - int native_size; + int max_hres; + int max_vres; }; struct lvds_setting_information { @@ -160,7 +154,6 @@ struct lvds_setting_information { int refresh_rate; int get_lcd_size_method; int lcd_panel_id; - int lcd_panel_size; int lcd_panel_hres; int lcd_panel_vres; int display_method; diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index 67b3693..abe59b8 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c @@ -23,11 +23,10 @@ static void tmds_register_write(int index, u8 data); static int tmds_register_read(int index); static int tmds_register_read_bytes(int index, u8 *buff, int buff_len); -static int check_reduce_blanking_mode(int mode_index, - int refresh_rate); -static int dvi_get_panel_size_from_DDCv1(void); -static int dvi_get_panel_size_from_DDCv2(void); -static unsigned char dvi_get_panel_info(void); +static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information + *tmds_chip, struct tmds_setting_information *tmds_setting); +static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information + *tmds_chip, struct tmds_setting_information *tmds_setting); static int viafb_dvi_query_EDID(void); static int check_tmds_chip(int device_id_subaddr, int device_id) @@ -38,23 +37,24 @@ static int check_tmds_chip(int device_id_subaddr, int device_id) return FAIL; } -void viafb_init_dvi_size(void) +void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, + struct tmds_setting_information *tmds_setting) { DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n"); - DEBUG_MSG(KERN_INFO - "viaparinfo->tmds_setting_info->get_dvi_size_method %d\n", - viaparinfo->tmds_setting_info->get_dvi_size_method); - switch (viaparinfo->tmds_setting_info->get_dvi_size_method) { - case GET_DVI_SIZE_BY_SYSTEM_BIOS: + viafb_dvi_sense(); + switch (viafb_dvi_query_EDID()) { + case 1: + dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting); break; - case GET_DVI_SZIE_BY_HW_STRAPPING: + case 2: + dvi_get_panel_size_from_DDCv2(tmds_chip, tmds_setting); break; - case GET_DVI_SIZE_BY_VGA_BIOS: default: - dvi_get_panel_info(); + printk(KERN_WARNING "viafb_init_dvi_size: DVI panel size undetected!\n"); break; } + return; } @@ -189,42 +189,14 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) return 0; } -static int check_reduce_blanking_mode(int mode_index, - int refresh_rate) -{ - if (refresh_rate != 60) - return false; - - switch (mode_index) { - /* Following modes have reduce blanking mode. */ - case VIA_RES_1360X768: - case VIA_RES_1400X1050: - case VIA_RES_1440X900: - case VIA_RES_1600X900: - case VIA_RES_1680X1050: - case VIA_RES_1920X1080: - case VIA_RES_1920X1200: - break; - - default: - DEBUG_MSG(KERN_INFO - "This dvi mode %d have no reduce blanking mode!\n", - mode_index); - return false; - } - - return true; -} - /* DVI Set Mode */ -void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga) +void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp, + int set_iga) { - struct VideoModeTable *videoMode = NULL; + struct VideoModeTable *rb_mode; struct crt_mode_table *pDviTiming; unsigned long desirePixelClock, maxPixelClock; - int status = 0; - videoMode = viafb_get_modetbl_pointer(video_index); - pDviTiming = videoMode->crtc; + pDviTiming = mode->crtc; desirePixelClock = pDviTiming->clk / 1000000; maxPixelClock = (unsigned long)viaparinfo-> tmds_setting_info->max_pixel_clock; @@ -232,20 +204,14 @@ void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga) DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { - /*Check if reduce-blanking mode is exist */ - status = - check_reduce_blanking_mode(video_index, - pDviTiming->refresh_rate); - if (status) { - video_index += 100; /*Use reduce-blanking mode */ - videoMode = viafb_get_modetbl_pointer(video_index); - pDviTiming = videoMode->crtc; - DEBUG_MSG(KERN_INFO - "DVI use reduce blanking mode %d!!\n", - video_index); + rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr, + mode->crtc[0].crtc.ver_addr); + if (rb_mode) { + mode = rb_mode; + pDviTiming = rb_mode->crtc; } } - viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga); + viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga); viafb_set_output_path(DEVICE_DVI, set_iga, viaparinfo->chip_info->tmds_chip_info.output_interface); } @@ -350,25 +316,18 @@ static int viafb_dvi_query_EDID(void) return false; } -/* - * - * int dvi_get_panel_size_from_DDCv1(void) - * - * - Get Panel Size Using EDID1 Table - * - * Return Type: int - * - */ -static int dvi_get_panel_size_from_DDCv1(void) +/* Get Panel Size Using EDID1 Table */ +static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information + *tmds_chip, struct tmds_setting_information *tmds_setting) { - int i, max_h = 0, max_v = 0, tmp, restore; + int i, max_h = 0, tmp, restore; unsigned char rData; unsigned char EDID_DATA[18]; DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); - restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0; + restore = tmds_chip->tmds_chip_slave_addr; + tmds_chip->tmds_chip_slave_addr = 0xA0; rData = tmds_register_read(0x23); if (rData & 0x3C) @@ -414,8 +373,8 @@ static int dvi_get_panel_size_from_DDCv1(void) /* The first two byte must be zero. */ if (EDID_DATA[3] == 0xFD) { /* To get max pixel clock. */ - viaparinfo->tmds_setting_info-> - max_pixel_clock = EDID_DATA[9] * 10; + tmds_setting->max_pixel_clock = + EDID_DATA[9] * 10; } } break; @@ -425,154 +384,88 @@ static int dvi_get_panel_size_from_DDCv1(void) } } + tmds_setting->max_hres = max_h; switch (max_h) { case 640: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_640X480; + tmds_setting->max_vres = 480; break; case 800: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_800X600; + tmds_setting->max_vres = 600; break; case 1024: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1024X768; + tmds_setting->max_vres = 768; break; case 1280: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1280X1024; + tmds_setting->max_vres = 1024; break; case 1400: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1400X1050; + tmds_setting->max_vres = 1050; break; case 1440: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1440X1050; + tmds_setting->max_vres = 1050; break; case 1600: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1600X1200; + tmds_setting->max_vres = 1200; break; case 1920: - if (max_v == 1200) { - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1920X1200; - } else { - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1920X1080; - } - + tmds_setting->max_vres = 1080; break; default: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1024X768; - DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d !\ - set default panel size.\n", max_h); + DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d ! " + "set default panel size.\n", max_h); break; } DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", - viaparinfo->tmds_setting_info->max_pixel_clock); - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; - return viaparinfo->tmds_setting_info->dvi_panel_size; + tmds_setting->max_pixel_clock); + tmds_chip->tmds_chip_slave_addr = restore; } -/* - * - * int dvi_get_panel_size_from_DDCv2(void) - * - * - Get Panel Size Using EDID2 Table - * - * Return Type: int - * - */ -static int dvi_get_panel_size_from_DDCv2(void) +/* Get Panel Size Using EDID2 Table */ +static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information + *tmds_chip, struct tmds_setting_information *tmds_setting) { - int HSize = 0, restore; + int restore; unsigned char R_Buffer[2]; DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n"); - restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2; + restore = tmds_chip->tmds_chip_slave_addr; + tmds_chip->tmds_chip_slave_addr = 0xA2; /* Horizontal: 0x76, 0x77 */ tmds_register_read_bytes(0x76, R_Buffer, 2); - HSize = R_Buffer[0]; - HSize += R_Buffer[1] << 8; + tmds_setting->max_hres = R_Buffer[0] + (R_Buffer[1] << 8); - switch (HSize) { + switch (tmds_setting->max_hres) { case 640: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_640X480; + tmds_setting->max_vres = 480; break; case 800: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_800X600; + tmds_setting->max_vres = 600; break; case 1024: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1024X768; + tmds_setting->max_vres = 768; break; case 1280: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1280X1024; + tmds_setting->max_vres = 1024; break; case 1400: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1400X1050; + tmds_setting->max_vres = 1050; break; case 1440: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1440X1050; + tmds_setting->max_vres = 1050; break; case 1600: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1600X1200; - break; - default: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1024X768; - DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d!\ - set default panel size.\n", HSize); - break; - } - - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; - return viaparinfo->tmds_setting_info->dvi_panel_size; -} - -/* - * - * unsigned char dvi_get_panel_info(void) - * - * - Get Panel Size - * - * Return Type: unsigned char - */ -static unsigned char dvi_get_panel_info(void) -{ - unsigned char dvipanelsize; - DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n"); - - viafb_dvi_sense(); - switch (viafb_dvi_query_EDID()) { - case 1: - dvi_get_panel_size_from_DDCv1(); - break; - case 2: - dvi_get_panel_size_from_DDCv2(); + tmds_setting->max_vres = 1200; break; default: + DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d! " + "set default panel size.\n", tmds_setting->max_hres); break; } - DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n", - viaparinfo->tmds_setting_info->dvi_panel_size); - dvipanelsize = (unsigned char)(viaparinfo-> - tmds_setting_info->dvi_panel_size); - return dvipanelsize; + tmds_chip->tmds_chip_slave_addr = restore; } /* If Disable DVI, turn off pad */ diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h index e1ec37f..0dffcfd 100644 --- a/drivers/video/via/dvi.h +++ b/drivers/video/via/dvi.h @@ -53,12 +53,13 @@ #define DEV_CONNECT_DVI 0x01 #define DEV_CONNECT_HDMI 0x02 -struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index); int viafb_dvi_sense(void); void viafb_dvi_disable(void); void viafb_dvi_enable(void); int viafb_tmds_trasmitter_identify(void); -void viafb_init_dvi_size(void); -void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga); +void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, + struct tmds_setting_information *tmds_setting); +void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp, + int set_iga); #endif /* __DVI_H__ */ diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c index b675cdb..1ee511b 100644 --- a/drivers/video/via/global.c +++ b/drivers/video/via/global.c @@ -23,15 +23,12 @@ int viafb_platform_epia_dvi = STATE_OFF; int viafb_device_lcd_dualedge = STATE_OFF; int viafb_bus_width = 12; int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI; -int viafb_memsize; int viafb_DeviceStatus = CRT_Device; int viafb_hotplug; int viafb_refresh = 60; int viafb_refresh1 = 60; int viafb_lcd_dsp_method = LCD_EXPANDSION; int viafb_lcd_mode = LCD_OPENLDI; -int viafb_bpp = 32; -int viafb_bpp1 = 32; int viafb_CRT_ON = 1; int viafb_DVI_ON; int viafb_LCD_ON ; @@ -42,8 +39,6 @@ int viafb_hotplug_Xres = 640; int viafb_hotplug_Yres = 480; int viafb_hotplug_bpp = 32; int viafb_hotplug_refresh = 60; -unsigned int viafb_second_offset; -int viafb_second_size; int viafb_primary_dev = None_Device; unsigned int viafb_second_xres = 640; unsigned int viafb_second_yres = 480; diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index d69d0ca..8d95d5f 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h @@ -35,7 +35,6 @@ #include "debug.h" -#include "iface.h" #include "viafbdev.h" #include "chip.h" #include "accel.h" @@ -68,8 +67,6 @@ extern int viafb_refresh; extern int viafb_refresh1; extern int viafb_lcd_dsp_method; extern int viafb_lcd_mode; -extern int viafb_bpp; -extern int viafb_bpp1; extern int viafb_CRT_ON; extern int viafb_hotplug_Xres; diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 3e083ff..f2583b1 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -524,7 +524,6 @@ static void dvi_patch_skew_dvp1(void); static void dvi_patch_skew_dvp_low(void); static void set_dvi_output_path(int set_iga, int output_interface); static void set_lcd_output_path(int set_iga, int output_interface); -static int search_mode_setting(int ModeInfoIndex); static void load_fix_bit_crtc_reg(void); static void init_gfx_chip_info(struct pci_dev *pdev, const struct pci_device_id *pdi); @@ -686,6 +685,84 @@ void viafb_set_secondary_pitch(u32 pitch) viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80); } +void viafb_set_primary_color_depth(u8 depth) +{ + u8 value; + + DEBUG_MSG(KERN_DEBUG "viafb_set_primary_color_depth(%d)\n", depth); + switch (depth) { + case 8: + value = 0x00; + break; + case 15: + value = 0x04; + break; + case 16: + value = 0x14; + break; + case 24: + value = 0x0C; + break; + case 30: + value = 0x08; + break; + default: + printk(KERN_WARNING "viafb_set_primary_color_depth: " + "Unsupported depth: %d\n", depth); + return; + } + + viafb_write_reg_mask(0x15, VIASR, value, 0x1C); +} + +void viafb_set_secondary_color_depth(u8 depth) +{ + u8 value; + + DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_color_depth(%d)\n", depth); + switch (depth) { + case 8: + value = 0x00; + break; + case 16: + value = 0x40; + break; + case 24: + value = 0xC0; + break; + case 30: + value = 0x80; + break; + default: + printk(KERN_WARNING "viafb_set_secondary_color_depth: " + "Unsupported depth: %d\n", depth); + return; + } + + viafb_write_reg_mask(0x67, VIACR, value, 0xC0); +} + +static void set_color_register(u8 index, u8 red, u8 green, u8 blue) +{ + outb(0xFF, 0x3C6); /* bit mask of palette */ + outb(index, 0x3C8); + outb(red, 0x3C9); + outb(green, 0x3C9); + outb(blue, 0x3C9); +} + +void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue) +{ + viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01); + set_color_register(index, red, green, blue); +} + +void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue) +{ + viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01); + set_color_register(index, red, green, blue); +} + void viafb_set_output_path(int device, int set_iga, int output_interface) { switch (device) { @@ -710,11 +787,8 @@ static void set_crt_output_path(int set_iga) viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6); break; case IGA2: - case IGA1_IGA2: viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7); viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6); - if (set_iga == IGA1_IGA2) - viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3); break; } } @@ -904,13 +978,6 @@ static void set_lcd_output_path(int set_iga, int output_interface) enable_second_display_channel(); break; - - case IGA1_IGA2: - viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3); - viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); - - disable_second_display_channel(); - break; } switch (output_interface) { @@ -987,49 +1054,6 @@ static void set_lcd_output_path(int set_iga, int output_interface) } } -/* Search Mode Index */ -static int search_mode_setting(int ModeInfoIndex) -{ - int i = 0; - - while ((i < NUM_TOTAL_MODETABLE) && - (ModeInfoIndex != CLE266Modes[i].ModeIndex)) - i++; - if (i >= NUM_TOTAL_MODETABLE) - i = 0; - return i; - -} - -struct VideoModeTable *viafb_get_modetbl_pointer(int Index) -{ - struct VideoModeTable *TmpTbl = NULL; - TmpTbl = &CLE266Modes[search_mode_setting(Index)]; - return TmpTbl; -} - -struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index) -{ - struct VideoModeTable *TmpTbl = NULL; - int i = 0; - while ((i < NUM_TOTAL_CEA_MODES) && - (Index != CEA_HDMI_Modes[i].ModeIndex)) - i++; - if ((i < NUM_TOTAL_CEA_MODES)) - TmpTbl = &CEA_HDMI_Modes[i]; - else { - /*Still use general timing if don't find CEA timing */ - i = 0; - while ((i < NUM_TOTAL_MODETABLE) && - (Index != CLE266Modes[i].ModeIndex)) - i++; - if (i >= NUM_TOTAL_MODETABLE) - i = 0; - TmpTbl = &CLE266Modes[i]; - } - return TmpTbl; -} - static void load_fix_bit_crtc_reg(void) { /* always set to 1 */ @@ -1121,15 +1145,13 @@ void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) struct io_register *reg = NULL; switch (set_iga) { - case IGA1_IGA2: case IGA1: reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte); viafb_load_reg_num = fetch_count_reg. iga1_fetch_count_reg.reg_num; reg = fetch_count_reg.iga1_fetch_count_reg.reg; viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); - if (set_iga == IGA1) - break; + break; case IGA2: reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte); viafb_load_reg_num = fetch_count_reg. @@ -1499,7 +1521,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) /* H.W. Reset : ON */ viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); - if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { + if (set_iga == IGA1) { /* Change D,N FOR VCLK */ switch (viaparinfo->chip_info->gfx_chip_name) { case UNICHROME_CLE266: @@ -1528,7 +1550,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) } } - if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { + if (set_iga == IGA2) { /* Change D,N FOR LCK */ switch (viaparinfo->chip_info->gfx_chip_name) { case UNICHROME_CLE266: @@ -1557,12 +1579,12 @@ void viafb_set_vclock(u32 CLK, int set_iga) viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); /* Reset PLL */ - if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { + if (set_iga == IGA1) { viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); } - if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { + if (set_iga == IGA2) { viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0); viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0); } @@ -1805,47 +1827,15 @@ void viafb_load_crtc_timing(struct display_timing device_timing, viafb_lock_crt(); } -void viafb_set_color_depth(int bpp_byte, int set_iga) -{ - if (set_iga == IGA1) { - switch (bpp_byte) { - case MODE_8BPP: - viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E); - break; - case MODE_16BPP: - viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE); - break; - case MODE_32BPP: - viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE); - break; - } - } else { - switch (bpp_byte) { - case MODE_8BPP: - viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7); - break; - case MODE_16BPP: - viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7); - break; - case MODE_32BPP: - viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7); - break; - } - } -} - void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, - int mode_index, int bpp_byte, int set_iga) + struct VideoModeTable *video_mode, int bpp_byte, int set_iga) { - struct VideoModeTable *video_mode; struct display_timing crt_reg; int i; int index = 0; int h_addr, v_addr; u32 pll_D_N; - video_mode = &CLE266Modes[search_mode_setting(mode_index)]; - for (i = 0; i < video_mode->mode_array; i++) { index = i; @@ -1858,8 +1848,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, /* Mode 640x480 has border, but LCD/DFP didn't have border. */ /* So we would delete border. */ - if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480) - && (viaparinfo->crt_setting_info->refresh_rate == 60)) { + if ((viafb_LCD_ON | viafb_DVI_ON) + && video_mode->crtc[0].crtc.hor_addr == 640 + && video_mode->crtc[0].crtc.ver_addr == 480 + && viaparinfo->crt_setting_info->refresh_rate == 60) { /* The border is 8 pixels. */ crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; @@ -1912,9 +1904,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) viafb_load_FIFO_reg(set_iga, h_addr, v_addr); - /* load SR Register About Memory and Color part */ - viafb_set_color_depth(bpp_byte, set_iga); - pll_D_N = viafb_get_clk_value(crt_table[index].clk); DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N); viafb_set_vclock(pll_D_N, set_iga); @@ -1956,9 +1945,6 @@ void viafb_update_device_setting(int hres, int vres, viaparinfo->tmds_setting_info->h_active = hres; viaparinfo->tmds_setting_info->v_active = vres; - viaparinfo->tmds_setting_info->bpp = bpp; - viaparinfo->tmds_setting_info->refresh_rate = - vmode_refresh; viaparinfo->lvds_setting_info->h_active = hres; viaparinfo->lvds_setting_info->v_active = vres; @@ -1975,9 +1961,6 @@ void viafb_update_device_setting(int hres, int vres, if (viaparinfo->tmds_setting_info->iga_path == IGA2) { viaparinfo->tmds_setting_info->h_active = hres; viaparinfo->tmds_setting_info->v_active = vres; - viaparinfo->tmds_setting_info->bpp = bpp; - viaparinfo->tmds_setting_info->refresh_rate = - vmode_refresh; } if (viaparinfo->lvds_setting_info->iga_path == IGA2) { @@ -2076,9 +2059,8 @@ static void init_tmds_chip_info(void) DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n", viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); - viaparinfo->tmds_setting_info->get_dvi_size_method = - GET_DVI_SIZE_BY_VGA_BIOS; - viafb_init_dvi_size(); + viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info, + &viaparinfo->shared->tmds_setting_info); } static void init_lvds_chip_info(void) @@ -2195,28 +2177,19 @@ static void set_display_channel(void) } } -int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, - int vmode_index1, int hor_res1, int ver_res1, int video_bpp1) +int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, + struct VideoModeTable *vmode_tbl1, int video_bpp1) { int i, j; int port; u8 value, index, mask; - struct VideoModeTable *vmode_tbl; struct crt_mode_table *crt_timing; - struct VideoModeTable *vmode_tbl1 = NULL; struct crt_mode_table *crt_timing1 = NULL; - DEBUG_MSG(KERN_INFO "Set Mode!!\n"); - DEBUG_MSG(KERN_INFO - "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n", - vmode_index, hor_res, ver_res, video_bpp); - device_screen_off(); - vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)]; crt_timing = vmode_tbl->crtc; if (viafb_SAMM_ON == 1) { - vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)]; crt_timing1 = vmode_tbl1->crtc; } @@ -2267,12 +2240,11 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, outb(VPIT.SR[i - 1], VIASR + 1); } - viafb_set_primary_address(0); - viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); + viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2); viafb_set_iga_path(); /* Write CRTC */ - viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1); + viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1); /* Write Graphic Controller */ for (i = 0; i < StdGR; i++) { @@ -2292,65 +2264,25 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, /* Update Patch Register */ - if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) - || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) { - for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) { - if (res_patch_table[i].mode_index == vmode_index) { - for (j = 0; - j < res_patch_table[i].table_length; j++) { - index = - res_patch_table[i]. - io_reg_table[j].index; - port = - res_patch_table[i]. - io_reg_table[j].port; - value = - res_patch_table[i]. - io_reg_table[j].value; - mask = - res_patch_table[i]. - io_reg_table[j].mask; - viafb_write_reg_mask(index, port, value, - mask); - } - } - } - } - - if (viafb_SAMM_ON == 1) { - if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) - || (viaparinfo->chip_info->gfx_chip_name == - UNICHROME_K400)) { - for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) { - if (res_patch_table[i].mode_index == - vmode_index1) { - for (j = 0; - j < - res_patch_table[i]. - table_length; j++) { - index = - res_patch_table[i]. - io_reg_table[j].index; - port = - res_patch_table[i]. - io_reg_table[j].port; - value = - res_patch_table[i]. - io_reg_table[j].value; - mask = - res_patch_table[i]. - io_reg_table[j].mask; - viafb_write_reg_mask(index, - port, value, mask); - } - } - } + if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 + || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) + && vmode_tbl->crtc[0].crtc.hor_addr == 1024 + && vmode_tbl->crtc[0].crtc.ver_addr == 768) { + for (j = 0; j < res_patch_table[0].table_length; j++) { + index = res_patch_table[0].io_reg_table[j].index; + port = res_patch_table[0].io_reg_table[j].port; + value = res_patch_table[0].io_reg_table[j].value; + mask = res_patch_table[0].io_reg_table[j].mask; + viafb_write_reg_mask(index, port, value, mask); } } viafb_set_primary_pitch(viafbinfo->fix.line_length); viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length : viafbinfo->fix.line_length); + viafb_set_primary_color_depth(viaparinfo->depth); + viafb_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth + : viaparinfo->depth); /* Update Refresh Rate Setting */ /* Clear On Screen */ @@ -2359,11 +2291,11 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, if (viafb_CRT_ON) { if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path == IGA2)) { - viafb_fill_crtc_timing(crt_timing1, vmode_index1, + viafb_fill_crtc_timing(crt_timing1, vmode_tbl1, video_bpp1 / 8, viaparinfo->crt_setting_info->iga_path); } else { - viafb_fill_crtc_timing(crt_timing, vmode_index, + viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, viaparinfo->crt_setting_info->iga_path); } @@ -2373,7 +2305,7 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode to 8 alignment (1368),there is several pixels (2 pixels) on right side of screen. */ - if (hor_res % 8) { + if (vmode_tbl->crtc[0].crtc.hor_addr % 8) { viafb_unlock_crt(); viafb_write_reg(CR02, VIACR, viafb_read_reg(VIACR, CR02) - 1); @@ -2384,14 +2316,14 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, if (viafb_DVI_ON) { if (viafb_SAMM_ON && (viaparinfo->tmds_setting_info->iga_path == IGA2)) { - viafb_dvi_set_mode(viafb_get_mode_index + viafb_dvi_set_mode(viafb_get_mode (viaparinfo->tmds_setting_info->h_active, viaparinfo->tmds_setting_info-> v_active), video_bpp1, viaparinfo-> tmds_setting_info->iga_path); } else { - viafb_dvi_set_mode(viafb_get_mode_index + viafb_dvi_set_mode(viafb_get_mode (viaparinfo->tmds_setting_info->h_active, viaparinfo-> tmds_setting_info->v_active), @@ -2445,8 +2377,8 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, /* If set mode normally, save resolution information for hot-plug . */ if (!viafb_hotplug) { - viafb_hotplug_Xres = hor_res; - viafb_hotplug_Yres = ver_res; + viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr; + viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr; viafb_hotplug_bpp = video_bpp; viafb_hotplug_refresh = viafb_refresh; @@ -2706,13 +2638,11 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ /*According var's xres, yres fill var's other timing information*/ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, - int mode_index) + struct VideoModeTable *vmode_tbl) { - struct VideoModeTable *vmode_tbl = NULL; struct crt_mode_table *crt_timing = NULL; struct display_timing crt_reg; int i = 0, index = 0; - vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)]; crt_timing = vmode_tbl->crtc; for (i = 0; i < vmode_tbl->mode_array; i++) { index = i; @@ -2721,36 +2651,6 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, } crt_reg = crt_timing[index].crtc; - switch (var->bits_per_pixel) { - case 8: - var->red.offset = 0; - var->green.offset = 0; - var->blue.offset = 0; - var->red.length = 6; - var->green.length = 6; - var->blue.length = 6; - break; - case 16: - var->red.offset = 11; - var->green.offset = 5; - var->blue.offset = 0; - var->red.length = 5; - var->green.length = 6; - var->blue.length = 5; - break; - case 32: - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - break; - default: - /* never happed, put here to keep consistent */ - break; - } - var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); var->left_margin = crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index b874d95..12ef32d 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -22,6 +22,7 @@ #ifndef __HW_H__ #define __HW_H__ +#include "viamode.h" #include "global.h" /*************************************************** @@ -862,8 +863,6 @@ struct pci_device_id_info { }; extern unsigned int viafb_second_virtual_xres; -extern unsigned int viafb_second_offset; -extern int viafb_second_size; extern int viafb_SAMM_ON; extern int viafb_dual_fb; extern int viafb_LCD2_ON; @@ -874,8 +873,9 @@ extern int viafb_hotplug; void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); void viafb_set_output_path(int device, int set_iga, int output_interface); + void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, - int mode_index, int bpp_byte, int set_iga); + struct VideoModeTable *video_mode, int bpp_byte, int set_iga); void viafb_set_vclock(u32 CLK, int set_iga); void viafb_load_reg(int timing_value, int viafb_load_reg_num, @@ -891,16 +891,15 @@ void viafb_lock_crt(void); void viafb_unlock_crt(void); void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); void viafb_write_regx(struct io_reg RegTable[], int ItemNum); -struct VideoModeTable *viafb_get_modetbl_pointer(int Index); u32 viafb_get_clk_value(int clk); void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); -void viafb_set_color_depth(int bpp_byte, int set_iga); void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ *p_gfx_dpa_setting); -int viafb_setmode(int vmode_index, int hor_res, int ver_res, - int video_bpp, int vmode_index1, int hor_res1, - int ver_res1, int video_bpp1); +int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, + struct VideoModeTable *vmode_tbl1, int video_bpp1); +void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, + struct VideoModeTable *vmode_tbl); void viafb_init_chip_info(struct pci_dev *pdev, const struct pci_device_id *pdi); void viafb_init_dac(int set_iga); @@ -915,6 +914,8 @@ void viafb_set_primary_address(u32 addr); void viafb_set_secondary_address(u32 addr); void viafb_set_primary_pitch(u32 pitch); void viafb_set_secondary_pitch(u32 pitch); +void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); +void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue); void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); #endif /* __HW_H__ */ diff --git a/drivers/video/via/iface.c b/drivers/video/via/iface.c deleted file mode 100644 index 1570636..0000000 --- a/drivers/video/via/iface.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. - - * 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, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE.See the GNU General Public License - * for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "global.h" - -/* Get frame buffer size from VGA BIOS */ - -unsigned int viafb_get_memsize(void) -{ - unsigned int m; - - /* If memory size provided by user */ - if (viafb_memsize) - m = viafb_memsize * Mb; - else { - m = (unsigned int)viafb_read_reg(VIASR, SR39); - m = m * (4 * Mb); - - if ((m < (16 * Mb)) || (m > (64 * Mb))) - m = 16 * Mb; - } - DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb); - return m; -} - -/* Get Video Buffer Starting Physical Address(back door)*/ - -unsigned long viafb_get_videobuf_addr(void) -{ - struct pci_dev *pdev = NULL; - unsigned char sys_mem; - unsigned char video_mem; - unsigned long sys_mem_size; - unsigned long video_mem_size; - /*system memory = 256 MB, video memory 64 MB */ - unsigned long vmem_starting_adr = 0x0C000000; - - pdev = - (struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID, - VIA_K800_BRIDGE_DID, NULL); - if (pdev != NULL) { - pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG, - &sys_mem); - pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG, - &video_mem); - video_mem = (video_mem & 0x70) >> 4; - sys_mem_size = ((unsigned long)sys_mem) << 24; - if (video_mem != 0) - video_mem_size = (1 << (video_mem)) * 1024 * 1024; - else - video_mem_size = 0; - - vmem_starting_adr = sys_mem_size - video_mem_size; - pci_dev_put(pdev); - } - - DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n", - vmem_starting_adr); - return vmem_starting_adr; -} diff --git a/drivers/video/via/iface.h b/drivers/video/via/iface.h deleted file mode 100644 index 790ec3e..0000000 --- a/drivers/video/via/iface.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. - - * 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, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE.See the GNU General Public License - * for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __IFACE_H__ -#define __IFACE_H__ - -#define Kb (1024) -#define Mb (Kb*Kb) - -#define VIA_K800_BRIDGE_VID 0x1106 -#define VIA_K800_BRIDGE_DID 0x3204 - -#define VIA_K800_SYSTEM_MEMORY_REG 0x47 -#define VIA_K800_VIDEO_MEMORY_REG 0xA1 - -extern int viafb_memsize; -unsigned int viafb_get_memsize(void); -unsigned long viafb_get_videobuf_addr(void); - -#endif /* __IFACE_H__ */ diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 09353e2..1b1ccdc 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c @@ -22,25 +22,7 @@ #include "global.h" #include "lcdtbl.h" -static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = { - /* IGA2 Shadow Horizontal Total */ - {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } }, - /* IGA2 Shadow Horizontal Blank End */ - {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } }, - /* IGA2 Shadow Vertical Total */ - {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } }, - /* IGA2 Shadow Vertical Addressable Video */ - {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } }, - /* IGA2 Shadow Vertical Blank Start */ - {IGA2_SHADOW_VER_BLANK_START_REG_NUM, - {{CR72, 0, 7}, {CR74, 4, 6} } }, - /* IGA2 Shadow Vertical Blank End */ - {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } }, - /* IGA2 Shadow Vertical Sync Start */ - {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } }, - /* IGA2 Shadow Vertical Sync End */ - {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } } -}; +#define viafb_compact_res(x, y) (((x)<<16)|(y)) static struct _lcd_scaling_factor lcd_scaling_factor = { /* LCD Horizontal Scaling Factor Register */ @@ -59,16 +41,10 @@ static struct _lcd_scaling_factor lcd_scaling_factor_CLE = { static int check_lvds_chip(int device_id_subaddr, int device_id); static bool lvds_identify_integratedlvds(void); -static int fp_id_to_vindex(int panel_id); +static void fp_id_to_vindex(int panel_id); static int lvds_register_read(int index); static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, int panel_vres); -static void load_lcd_k400_patch_tbl(int set_hres, int set_vres, - int panel_id); -static void load_lcd_p880_patch_tbl(int set_hres, int set_vres, - int panel_id); -static void load_lcd_patch_regs(int set_hres, int set_vres, - int panel_id, int set_iga); static void via_pitch_alignment_patch_lcd( struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information @@ -98,8 +74,6 @@ static void check_diport_of_integrated_lvds( static struct display_timing lcd_centering_timging(struct display_timing mode_crt_reg, struct display_timing panel_crt_reg); -static void load_crtc_shadow_timing(struct display_timing mode_timing, - struct display_timing panel_timing); static void viafb_load_scaling_factor_for_p4m900(int set_hres, int set_vres, int panel_hres, int panel_vres); @@ -125,33 +99,24 @@ void viafb_init_lcd_size(void) break; case GET_LCD_SIZE_BY_VGA_BIOS: DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n"); - viaparinfo->lvds_setting_info->lcd_panel_size = - fp_id_to_vindex(viafb_lcd_panel_id); + fp_id_to_vindex(viafb_lcd_panel_id); DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", viaparinfo->lvds_setting_info->lcd_panel_id); - DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n", - viaparinfo->lvds_setting_info->lcd_panel_size); break; case GET_LCD_SIZE_BY_USER_SETTING: DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n"); - viaparinfo->lvds_setting_info->lcd_panel_size = - fp_id_to_vindex(viafb_lcd_panel_id); + fp_id_to_vindex(viafb_lcd_panel_id); DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", viaparinfo->lvds_setting_info->lcd_panel_id); - DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n", - viaparinfo->lvds_setting_info->lcd_panel_size); break; default: DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n"); viaparinfo->lvds_setting_info->lcd_panel_id = LCD_PANEL_ID1_800X600; - viaparinfo->lvds_setting_info->lcd_panel_size = - fp_id_to_vindex(LCD_PANEL_ID1_800X600); + fp_id_to_vindex(LCD_PANEL_ID1_800X600); } viaparinfo->lvds_setting_info2->lcd_panel_id = viaparinfo->lvds_setting_info->lcd_panel_id; - viaparinfo->lvds_setting_info2->lcd_panel_size = - viaparinfo->lvds_setting_info->lcd_panel_size; viaparinfo->lvds_setting_info2->lcd_panel_hres = viaparinfo->lvds_setting_info->lcd_panel_hres; viaparinfo->lvds_setting_info2->lcd_panel_vres = @@ -171,13 +136,13 @@ static bool lvds_identify_integratedlvds(void) if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = INTEGRATED_LVDS; - DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\ - (Internal LVDS + External LVDS)\n"); + DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! " + "(Internal LVDS + External LVDS)\n"); } else { viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = INTEGRATED_LVDS; - DEBUG_MSG(KERN_INFO "Not found external LVDS,\ - so can't support two dual channel LVDS!\n"); + DEBUG_MSG(KERN_INFO "Not found external LVDS, " + "so can't support two dual channel LVDS!\n"); } } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) { /* Two single channel LCD (Internal LVDS + Internal LVDS): */ @@ -185,8 +150,8 @@ static bool lvds_identify_integratedlvds(void) INTEGRATED_LVDS; viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = INTEGRATED_LVDS; - DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\ - (Internal LVDS + Internal LVDS)\n"); + DEBUG_MSG(KERN_INFO "Support two single channel LVDS! " + "(Internal LVDS + Internal LVDS)\n"); } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) { /* If we have found external LVDS, just use it, otherwise, we will use internal LVDS as default. */ @@ -248,7 +213,7 @@ int viafb_lvds_trasmitter_identify(void) return FAIL; } -static int fp_id_to_vindex(int panel_id) +static void fp_id_to_vindex(int panel_id) { DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n"); @@ -264,7 +229,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID0_640X480; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_640X480; break; case 0x1: viaparinfo->lvds_setting_info->lcd_panel_hres = 800; @@ -273,7 +237,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID1_800X600; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_800X600; break; case 0x2: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -282,7 +245,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID2_1024X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1024X768; break; case 0x3: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -291,7 +253,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID3_1280X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1280X768; break; case 0x4: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -300,7 +261,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID4_1280X1024; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1280X1024; break; case 0x5: viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; @@ -309,7 +269,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID5_1400X1050; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1400X1050; break; case 0x6: viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; @@ -318,7 +277,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID6_1600X1200; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1600X1200; break; case 0x8: viaparinfo->lvds_setting_info->lcd_panel_hres = 800; @@ -327,7 +285,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_IDA_800X480; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_800X480; break; case 0x9: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -336,7 +293,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID2_1024X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1024X768; break; case 0xA: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -345,7 +301,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID2_1024X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1024X768; break; case 0xB: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -354,7 +309,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID2_1024X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1024X768; break; case 0xC: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -363,7 +317,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID3_1280X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1280X768; break; case 0xD: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -372,7 +325,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID4_1280X1024; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1280X1024; break; case 0xE: viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; @@ -381,7 +333,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID5_1400X1050; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1400X1050; break; case 0xF: viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; @@ -390,7 +341,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID6_1600X1200; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1600X1200; break; case 0x10: viaparinfo->lvds_setting_info->lcd_panel_hres = 1366; @@ -399,7 +349,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID7_1366X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1368X768; break; case 0x11: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -408,7 +357,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID8_1024X600; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1024X600; break; case 0x12: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -417,7 +365,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID3_1280X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1280X768; break; case 0x13: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -426,7 +373,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID9_1280X800; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1280X800; break; case 0x14: viaparinfo->lvds_setting_info->lcd_panel_hres = 1360; @@ -435,7 +381,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_IDB_1360X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1360X768; break; case 0x15: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -444,7 +389,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID3_1280X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1280X768; break; case 0x16: viaparinfo->lvds_setting_info->lcd_panel_hres = 480; @@ -453,7 +397,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_IDC_480X640; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_480X640; break; default: viaparinfo->lvds_setting_info->lcd_panel_hres = 800; @@ -462,7 +405,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID1_800X600; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_800X600; } } @@ -573,284 +515,6 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, } } -static void load_lcd_k400_patch_tbl(int set_hres, int set_vres, - int panel_id) -{ - int vmode_index; - int reg_num = 0; - struct io_reg *lcd_patch_reg = NULL; - - vmode_index = viafb_get_mode_index(set_hres, set_vres); - switch (panel_id) { - /* LCD 800x600 */ - case LCD_PANEL_ID1_800X600: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6; - lcd_patch_reg = K400_LCD_RES_6X4_8X6; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6; - lcd_patch_reg = K400_LCD_RES_7X4_8X6; - break; - } - break; - - /* LCD 1024x768 */ - case LCD_PANEL_ID2_1024X768: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7; - lcd_patch_reg = K400_LCD_RES_6X4_10X7; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7; - lcd_patch_reg = K400_LCD_RES_7X4_10X7; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7; - lcd_patch_reg = K400_LCD_RES_8X6_10X7; - break; - } - break; - - /* LCD 1280x1024 */ - case LCD_PANEL_ID4_1280X1024: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10; - lcd_patch_reg = K400_LCD_RES_6X4_12X10; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10; - lcd_patch_reg = K400_LCD_RES_7X4_12X10; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10; - lcd_patch_reg = K400_LCD_RES_8X6_12X10; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10; - lcd_patch_reg = K400_LCD_RES_10X7_12X10; - break; - - } - break; - - /* LCD 1400x1050 */ - case LCD_PANEL_ID5_1400X1050: - switch (vmode_index) { - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10; - lcd_patch_reg = K400_LCD_RES_6X4_14X10; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10; - lcd_patch_reg = K400_LCD_RES_8X6_14X10; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10; - lcd_patch_reg = K400_LCD_RES_10X7_14X10; - break; - case VIA_RES_1280X768: - case VIA_RES_1280X800: - case VIA_RES_1280X960: - case VIA_RES_1280X1024: - reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10; - lcd_patch_reg = K400_LCD_RES_12X10_14X10; - break; - } - break; - - /* LCD 1600x1200 */ - case LCD_PANEL_ID6_1600X1200: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12; - lcd_patch_reg = K400_LCD_RES_6X4_16X12; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12; - lcd_patch_reg = K400_LCD_RES_7X4_16X12; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12; - lcd_patch_reg = K400_LCD_RES_8X6_16X12; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12; - lcd_patch_reg = K400_LCD_RES_10X7_16X12; - break; - case VIA_RES_1280X768: - case VIA_RES_1280X800: - case VIA_RES_1280X960: - case VIA_RES_1280X1024: - reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12; - lcd_patch_reg = K400_LCD_RES_12X10_16X12; - break; - } - break; - - /* LCD 1366x768 */ - case LCD_PANEL_ID7_1366X768: - switch (vmode_index) { - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7; - lcd_patch_reg = K400_LCD_RES_6X4_1366X7; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7; - lcd_patch_reg = K400_LCD_RES_7X4_1366X7; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7; - lcd_patch_reg = K400_LCD_RES_8X6_1366X7; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7; - lcd_patch_reg = K400_LCD_RES_10X7_1366X7; - break; - case VIA_RES_1280X768: - case VIA_RES_1280X800: - case VIA_RES_1280X960: - case VIA_RES_1280X1024: - reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7; - lcd_patch_reg = K400_LCD_RES_12X10_1366X7; - break; - } - break; - - /* LCD 1360x768 */ - case LCD_PANEL_IDB_1360X768: - break; - } - if (reg_num != 0) { - /* H.W. Reset : ON */ - viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); - - viafb_write_regx(lcd_patch_reg, reg_num); - - /* H.W. Reset : OFF */ - viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); - - /* Reset PLL */ - viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); - viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); - - /* Fire! */ - outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc); - } -} - -static void load_lcd_p880_patch_tbl(int set_hres, int set_vres, - int panel_id) -{ - int vmode_index; - int reg_num = 0; - struct io_reg *lcd_patch_reg = NULL; - - vmode_index = viafb_get_mode_index(set_hres, set_vres); - - switch (panel_id) { - case LCD_PANEL_ID5_1400X1050: - switch (vmode_index) { - case VIA_RES_640X480: - reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10; - lcd_patch_reg = P880_LCD_RES_6X4_14X10; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10; - lcd_patch_reg = P880_LCD_RES_8X6_14X10; - break; - } - break; - case LCD_PANEL_ID6_1600X1200: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12; - lcd_patch_reg = P880_LCD_RES_6X4_16X12; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12; - lcd_patch_reg = P880_LCD_RES_7X4_16X12; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12; - lcd_patch_reg = P880_LCD_RES_8X6_16X12; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12; - lcd_patch_reg = P880_LCD_RES_10X7_16X12; - break; - case VIA_RES_1280X768: - case VIA_RES_1280X960: - case VIA_RES_1280X1024: - reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12; - lcd_patch_reg = P880_LCD_RES_12X10_16X12; - break; - } - break; - - } - if (reg_num != 0) { - /* H.W. Reset : ON */ - viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); - - viafb_write_regx(lcd_patch_reg, reg_num); - - /* H.W. Reset : OFF */ - viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); - - /* Reset PLL */ - viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); - viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); - - /* Fire! */ - outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc); - } -} - -static void load_lcd_patch_regs(int set_hres, int set_vres, - int panel_id, int set_iga) -{ - int vmode_index; - - vmode_index = viafb_get_mode_index(set_hres, set_vres); - - viafb_unlock_crt(); - - /* Patch for simultaneous & Expansion */ - if ((set_iga == IGA1_IGA2) && - (viaparinfo->lvds_setting_info->display_method == - LCD_EXPANDSION)) { - switch (viaparinfo->chip_info->gfx_chip_name) { - case UNICHROME_CLE266: - case UNICHROME_K400: - load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id); - break; - case UNICHROME_K800: - break; - case UNICHROME_PM800: - case UNICHROME_CN700: - case UNICHROME_CX700: - load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id); - } - } - - viafb_lock_crt(); -} - static void via_pitch_alignment_patch_lcd( struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information @@ -949,29 +613,25 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info) { - int video_index = plvds_setting_info->lcd_panel_size; int set_iga = plvds_setting_info->iga_path; int mode_bpp = plvds_setting_info->bpp; - int set_hres, set_vres; - int panel_hres, panel_vres; + int set_hres = plvds_setting_info->h_active; + int set_vres = plvds_setting_info->v_active; + int panel_hres = plvds_setting_info->lcd_panel_hres; + int panel_vres = plvds_setting_info->lcd_panel_vres; u32 pll_D_N; - int offset; struct display_timing mode_crt_reg, panel_crt_reg; struct crt_mode_table *panel_crt_table = NULL; - struct VideoModeTable *vmode_tbl = NULL; + struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres, + panel_vres); DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); /* Get mode table */ mode_crt_reg = mode_crt_table->crtc; /* Get panel table Pointer */ - vmode_tbl = viafb_get_modetbl_pointer(video_index); panel_crt_table = vmode_tbl->crtc; panel_crt_reg = panel_crt_table->crtc; DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); - set_hres = plvds_setting_info->h_active; - set_vres = plvds_setting_info->v_active; - panel_hres = plvds_setting_info->lcd_panel_hres; - panel_vres = plvds_setting_info->lcd_panel_vres; if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); plvds_setting_info->vclk = panel_crt_table->clk; @@ -1001,54 +661,12 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, } } - if (set_iga == IGA1_IGA2) { - load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg); - /* Fill shadow registers */ - - switch (plvds_setting_info->lcd_panel_id) { - case LCD_PANEL_ID0_640X480: - offset = 80; - break; - case LCD_PANEL_ID1_800X600: - case LCD_PANEL_IDA_800X480: - offset = 110; - break; - case LCD_PANEL_ID2_1024X768: - offset = 150; - break; - case LCD_PANEL_ID3_1280X768: - case LCD_PANEL_ID4_1280X1024: - case LCD_PANEL_ID5_1400X1050: - case LCD_PANEL_ID9_1280X800: - offset = 190; - break; - case LCD_PANEL_ID6_1600X1200: - offset = 250; - break; - case LCD_PANEL_ID7_1366X768: - case LCD_PANEL_IDB_1360X768: - offset = 212; - break; - default: - offset = 140; - break; - } - - /* Offset for simultaneous */ - viafb_set_secondary_pitch(offset << 3); - DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n"); - viafb_load_fetch_count_reg(set_hres, 4, IGA2); - /* Fetch count for simultaneous */ - } else { /* SAMM */ - /* Fetch count for IGA2 only */ - viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); - - if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) - && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) - viafb_load_FIFO_reg(set_iga, set_hres, set_vres); + /* Fetch count for IGA2 only */ + viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); - viafb_set_color_depth(mode_bpp / 8, set_iga); - } + if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) + && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) + viafb_load_FIFO_reg(set_iga, set_hres, set_vres); fill_lcd_format(); @@ -1065,11 +683,6 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)) viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); - load_lcd_patch_regs(set_hres, set_vres, - plvds_setting_info->lcd_panel_id, set_iga); - - DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n"); - /* Patch for non 32bit alignment mode */ via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info); } @@ -1283,8 +896,7 @@ void viafb_lcd_enable(void) viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48); } - if ((viaparinfo->lvds_setting_info->iga_path == IGA1) - || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) { + if (viaparinfo->lvds_setting_info->iga_path == IGA1) { /* CRT path set to IGA2 */ viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40); /* IGA2 path disabled */ @@ -1476,210 +1088,6 @@ static struct display_timing lcd_centering_timging(struct display_timing return crt_reg; } -static void load_crtc_shadow_timing(struct display_timing mode_timing, - struct display_timing panel_timing) -{ - struct io_register *reg = NULL; - int i; - int viafb_load_reg_Num = 0; - int reg_value = 0; - - if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) { - /* Expansion */ - for (i = 12; i < 20; i++) { - switch (i) { - case H_TOTAL_SHADOW_INDEX: - reg_value = - IGA2_HOR_TOTAL_SHADOW_FORMULA - (panel_timing.hor_total); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.hor_total_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.hor_total_shadow.reg; - break; - case H_BLANK_END_SHADOW_INDEX: - reg_value = - IGA2_HOR_BLANK_END_SHADOW_FORMULA - (panel_timing.hor_blank_start, - panel_timing.hor_blank_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - hor_blank_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - hor_blank_end_shadow.reg; - break; - case V_TOTAL_SHADOW_INDEX: - reg_value = - IGA2_VER_TOTAL_SHADOW_FORMULA - (panel_timing.ver_total); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_total_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.ver_total_shadow.reg; - break; - case V_ADDR_SHADOW_INDEX: - reg_value = - IGA2_VER_ADDR_SHADOW_FORMULA - (panel_timing.ver_addr); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_addr_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg; - break; - case V_BLANK_SATRT_SHADOW_INDEX: - reg_value = - IGA2_VER_BLANK_START_SHADOW_FORMULA - (panel_timing.ver_blank_start); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_blank_start_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_blank_start_shadow.reg; - break; - case V_BLANK_END_SHADOW_INDEX: - reg_value = - IGA2_VER_BLANK_END_SHADOW_FORMULA - (panel_timing.ver_blank_start, - panel_timing.ver_blank_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_blank_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_blank_end_shadow.reg; - break; - case V_SYNC_SATRT_SHADOW_INDEX: - reg_value = - IGA2_VER_SYNC_START_SHADOW_FORMULA - (panel_timing.ver_sync_start); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_sync_start_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_sync_start_shadow.reg; - break; - case V_SYNC_END_SHADOW_INDEX: - reg_value = - IGA2_VER_SYNC_END_SHADOW_FORMULA - (panel_timing.ver_sync_start, - panel_timing.ver_sync_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_sync_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_sync_end_shadow.reg; - break; - } - viafb_load_reg(reg_value, - viafb_load_reg_Num, reg, VIACR); - } - } else { /* Centering */ - for (i = 12; i < 20; i++) { - switch (i) { - case H_TOTAL_SHADOW_INDEX: - reg_value = - IGA2_HOR_TOTAL_SHADOW_FORMULA - (panel_timing.hor_total); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.hor_total_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.hor_total_shadow.reg; - break; - case H_BLANK_END_SHADOW_INDEX: - reg_value = - IGA2_HOR_BLANK_END_SHADOW_FORMULA - (panel_timing.hor_blank_start, - panel_timing.hor_blank_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - hor_blank_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - hor_blank_end_shadow.reg; - break; - case V_TOTAL_SHADOW_INDEX: - reg_value = - IGA2_VER_TOTAL_SHADOW_FORMULA - (panel_timing.ver_total); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_total_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.ver_total_shadow.reg; - break; - case V_ADDR_SHADOW_INDEX: - reg_value = - IGA2_VER_ADDR_SHADOW_FORMULA - (mode_timing.ver_addr); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_addr_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg; - break; - case V_BLANK_SATRT_SHADOW_INDEX: - reg_value = - IGA2_VER_BLANK_START_SHADOW_FORMULA - (mode_timing.ver_blank_start); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_blank_start_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_blank_start_shadow.reg; - break; - case V_BLANK_END_SHADOW_INDEX: - reg_value = - IGA2_VER_BLANK_END_SHADOW_FORMULA - (panel_timing.ver_blank_start, - panel_timing.ver_blank_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_blank_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_blank_end_shadow.reg; - break; - case V_SYNC_SATRT_SHADOW_INDEX: - reg_value = - IGA2_VER_SYNC_START_SHADOW_FORMULA( - (panel_timing.ver_sync_start - - panel_timing.ver_blank_start) + - (panel_timing.ver_addr - - mode_timing.ver_addr) / 2 + - mode_timing.ver_addr); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_sync_start_shadow. - reg_num; - reg = - iga2_shadow_crtc_reg.ver_sync_start_shadow. - reg; - break; - case V_SYNC_END_SHADOW_INDEX: - reg_value = - IGA2_VER_SYNC_END_SHADOW_FORMULA( - (panel_timing.ver_sync_start - - panel_timing.ver_blank_start) + - (panel_timing.ver_addr - - mode_timing.ver_addr) / 2 + - mode_timing.ver_addr, - panel_timing.ver_sync_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_sync_end_shadow. - reg_num; - reg = - iga2_shadow_crtc_reg.ver_sync_end_shadow. - reg; - break; - } - viafb_load_reg(reg_value, - viafb_load_reg_Num, reg, VIACR); - } - } -} - bool viafb_lcd_get_mobile_state(bool *mobile) { unsigned char *romptr, *tableptr; diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 7cd03e2..d55aaa7 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -43,61 +43,6 @@ /* Video Memory Size */ #define VIDEO_MEMORY_SIZE_16M 0x1000000 -/* Definition Mode Index -*/ -#define VIA_RES_640X480 0 -#define VIA_RES_800X600 1 -#define VIA_RES_1024X768 2 -#define VIA_RES_1152X864 3 -#define VIA_RES_1280X1024 4 -#define VIA_RES_1600X1200 5 -#define VIA_RES_1440X1050 6 -#define VIA_RES_1280X768 7 -#define VIA_RES_1280X960 8 -#define VIA_RES_1920X1440 9 -#define VIA_RES_848X480 10 -#define VIA_RES_1400X1050 11 -#define VIA_RES_720X480 12 -#define VIA_RES_720X576 13 -#define VIA_RES_1024X512 14 -#define VIA_RES_856X480 15 -#define VIA_RES_1024X576 16 -#define VIA_RES_640X400 17 -#define VIA_RES_1280X720 18 -#define VIA_RES_1920X1080 19 -#define VIA_RES_800X480 20 -#define VIA_RES_1368X768 21 -#define VIA_RES_1024X600 22 -#define VIA_RES_1280X800 23 -#define VIA_RES_1680X1050 24 -#define VIA_RES_960X600 25 -#define VIA_RES_1000X600 26 -#define VIA_RES_1088X612 27 -#define VIA_RES_1152X720 28 -#define VIA_RES_1200X720 29 -#define VIA_RES_1280X600 30 -#define VIA_RES_1360X768 31 -#define VIA_RES_1366X768 32 -#define VIA_RES_1440X900 33 -#define VIA_RES_1600X900 34 -#define VIA_RES_1600X1024 35 -#define VIA_RES_1792X1344 36 -#define VIA_RES_1856X1392 37 -#define VIA_RES_1920X1200 38 -#define VIA_RES_2048X1536 39 -#define VIA_RES_480X640 40 - -/*Reduce Blanking*/ -#define VIA_RES_1360X768_RB 131 -#define VIA_RES_1440X900_RB 133 -#define VIA_RES_1400X1050_RB 111 -#define VIA_RES_1600X900_RB 134 -#define VIA_RES_1680X1050_RB 124 -#define VIA_RES_1920X1080_RB 119 -#define VIA_RES_1920X1200_RB 138 - -#define VIA_RES_INVALID 255 - /* standard VGA IO port */ #define VIARMisc 0x3CC @@ -118,7 +63,6 @@ /* Display path */ #define IGA1 1 #define IGA2 2 -#define IGA1_IGA2 3 /* Define Color Depth */ #define MODE_8BPP 1 diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c index d53c3d5..aefdeee 100644 --- a/drivers/video/via/via_utility.c +++ b/drivers/video/via/via_utility.c @@ -239,15 +239,3 @@ void viafb_get_gamma_support_state(int bpp, unsigned int *support_state) else *support_state = CRT_Device | DVI_Device | LCD_Device; } - -int viafb_input_parameter_converter(int parameter_value) -{ - int result; - - if (parameter_value >= 1 && parameter_value <= 9) - result = 1 << (parameter_value - 1); - else - result = 1; - - return result; -} diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h index 2fd4552..1670ba8 100644 --- a/drivers/video/via/via_utility.h +++ b/drivers/video/via/via_utility.h @@ -30,6 +30,5 @@ bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres); void viafb_set_gamma_table(int bpp, unsigned int *gamma_table); void viafb_get_gamma_table(unsigned int *gamma_table); void viafb_get_gamma_support_state(int bpp, unsigned int *support_state); -int viafb_input_parameter_converter(int parameter_value); #endif /* __VIAUTILITY_H__ */ diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 3028e7d..ce7783b 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -26,18 +26,22 @@ #include "global.h" -static struct fb_var_screeninfo default_var; static char *viafb_name = "Via"; static u32 pseudo_pal[17]; /* video mode */ -static char *viafb_mode = "640x480"; -static char *viafb_mode1 = "640x480"; +static char *viafb_mode; +static char *viafb_mode1; +static int viafb_bpp = 32; +static int viafb_bpp1 = 32; + +static unsigned int viafb_second_offset; +static int viafb_second_size; static int viafb_accel = 1; /* Added for specifying active devices.*/ -char *viafb_active_dev = ""; +char *viafb_active_dev; /*Added for specify lcd output port*/ char *viafb_lcd_port = ""; @@ -50,18 +54,78 @@ static void apply_second_mode_setting(struct fb_var_screeninfo *sec_var); static void retrieve_device_setting(struct viafb_ioctl_setting *setting_info); +static int viafb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info); static struct fb_ops viafb_ops; +static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth) +{ + var->grayscale = 0; + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; + var->nonstd = 0; + switch (depth) { + case 8: + var->bits_per_pixel = 8; + var->red.offset = 0; + var->green.offset = 0; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + break; + case 15: + var->bits_per_pixel = 16; + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + break; + case 16: + var->bits_per_pixel = 16; + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + break; + case 24: + var->bits_per_pixel = 32; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + break; + case 30: + var->bits_per_pixel = 32; + var->red.offset = 20; + var->green.offset = 10; + var->blue.offset = 0; + var->red.length = 10; + var->green.length = 10; + var->blue.length = 10; + break; + } +} + static void viafb_update_fix(struct fb_info *info) { u32 bpp = info->var.bits_per_pixel; info->fix.visual = bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - info->fix.line_length = - ((info->var.xres_virtual + 7) & ~7) * bpp / 8; + info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7; } static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, @@ -75,6 +139,7 @@ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; + fix->visual = FB_VISUAL_TRUECOLOR; fix->xpanstep = fix->ywrapstep = 0; fix->ypanstep = 1; @@ -97,9 +162,10 @@ static int viafb_release(struct fb_info *info, int user) static int viafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - int vmode_index, htotal, vtotal; + int htotal, vtotal, depth; + struct VideoModeTable *vmode_entry; struct viafb_par *ppar = info->par; - u32 long_refresh; + u32 long_refresh, line; DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); /* Sanity check */ @@ -107,26 +173,36 @@ static int viafb_check_var(struct fb_var_screeninfo *var, if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) return -EINVAL; - vmode_index = viafb_get_mode_index(var->xres, var->yres); - if (vmode_index == VIA_RES_INVALID) { + vmode_entry = viafb_get_mode(var->xres, var->yres); + if (!vmode_entry) { DEBUG_MSG(KERN_INFO "viafb: Mode %dx%dx%d not supported!!\n", var->xres, var->yres, var->bits_per_pixel); return -EINVAL; } - if (24 == var->bits_per_pixel) - var->bits_per_pixel = 32; + depth = fb_get_color_depth(var, &info->fix); + if (!depth) + depth = var->bits_per_pixel; - if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && - var->bits_per_pixel != 32) + if (depth < 0 || depth > 32) return -EINVAL; + else if (!depth) + depth = 24; + else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1) + depth = 15; + else if (depth == 30) + depth = 30; + else if (depth <= 8) + depth = 8; + else if (depth <= 16) + depth = 16; + else + depth = 24; - if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F) - /*32 pixel alignment */ - var->xres_virtual = (var->xres_virtual + 31) & ~31; - if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > - ppar->memsize) + viafb_fill_var_color_info(var, depth); + line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7; + if (line * var->yres_virtual > ppar->memsize) return -EINVAL; /* Based on var passed in to calculate the refresh, @@ -142,7 +218,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var, viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh); /* Adjust var according to our driver's own table */ - viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); + viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); if (info->var.accel_flags & FB_ACCELF_TEXT && !ppar->shared->engine_mmio) info->var.accel_flags = 0; @@ -153,39 +229,45 @@ static int viafb_check_var(struct fb_var_screeninfo *var, static int viafb_set_par(struct fb_info *info) { struct viafb_par *viapar = info->par; - int vmode_index; - int vmode_index1 = 0; + struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); viapar->depth = fb_get_color_depth(&info->var, &info->fix); - viafb_update_device_setting(info->var.xres, info->var.yres, - info->var.bits_per_pixel, viafb_refresh, 0); + viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, + viafbinfo->var.bits_per_pixel, viafb_refresh, 0); - vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres); - - if (viafb_SAMM_ON == 1) { + vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); + if (viafb_dual_fb) { + vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres, + viafbinfo1->var.yres); + viafb_update_device_setting(viafbinfo1->var.xres, + viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, + viafb_refresh1, 1); + } else if (viafb_SAMM_ON == 1) { DEBUG_MSG(KERN_INFO "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", viafb_second_xres, viafb_second_yres, viafb_bpp1); - vmode_index1 = viafb_get_mode_index(viafb_second_xres, + vmode_entry1 = viafb_get_mode(viafb_second_xres, viafb_second_yres); - DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n", - vmode_index1); viafb_update_device_setting(viafb_second_xres, viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); } - if (vmode_index != VIA_RES_INVALID) { + if (vmode_entry) { viafb_update_fix(info); - viafb_bpp = info->var.bits_per_pixel; + if (viafb_dual_fb && viapar->iga_path == IGA2) + viafb_bpp1 = info->var.bits_per_pixel; + else + viafb_bpp = info->var.bits_per_pixel; + if (info->var.accel_flags & FB_ACCELF_TEXT) info->flags &= ~FBINFO_HWACCEL_DISABLED; else info->flags |= FBINFO_HWACCEL_DISABLED; - viafb_setmode(vmode_index, info->var.xres, info->var.yres, - info->var.bits_per_pixel, vmode_index1, - viafb_second_xres, viafb_second_yres, viafb_bpp1); + viafb_setmode(vmode_entry, info->var.bits_per_pixel, + vmode_entry1, viafb_bpp1); + viafb_pan_display(&info->var, info); } return 0; @@ -195,234 +277,52 @@ static int viafb_set_par(struct fb_info *info) static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; - unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16; - DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n"); - if (regno >= cmap_entries) - return 1; - if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { - /* - * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev. - */ - outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); - rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; - } - switch (info->var.bits_per_pixel) { - case 8: - outb(0x1A, 0x3C4); - sr1a = inb(0x3C5); - outb(0x1B, 0x3C4); - sr1b = inb(0x3C5); - outb(0x67, 0x3D4); - cr67 = inb(0x3D5); - outb(0x6A, 0x3D4); - cr6a = inb(0x3D5); - - /* Map the 3C6/7/8/9 to the IGA2 */ - outb(0x1A, 0x3C4); - outb(sr1a | 0x01, 0x3C5); - /* Second Display Engine colck always on */ - outb(0x1B, 0x3C4); - outb(sr1b | 0x80, 0x3C5); - /* Second Display Color Depth 8 */ - outb(0x67, 0x3D4); - outb(cr67 & 0x3F, 0x3D5); - outb(0x6A, 0x3D4); - /* Second Display Channel Reset CR6A[6]) */ - outb(cr6a & 0xBF, 0x3D5); - /* Second Display Channel Enable CR6A[7] */ - outb(cr6a | 0x80, 0x3D5); - /* Second Display Channel stop reset) */ - outb(cr6a | 0x40, 0x3D5); - - /* Bit mask of palette */ - outb(0xFF, 0x3c6); - /* Write one register of IGA2 */ - outb(regno, 0x3C8); - if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && - rev >= 15) { - shift = 8; - viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); - viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); - } else { - shift = 10; - viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); - viafb_write_reg_mask(SR15, VIASR, 0, BIT7); - } - outb(red >> shift, 0x3C9); - outb(green >> shift, 0x3C9); - outb(blue >> shift, 0x3C9); - - /* Map the 3C6/7/8/9 to the IGA1 */ - outb(0x1A, 0x3C4); - outb(sr1a & 0xFE, 0x3C5); - /* Bit mask of palette */ - outb(0xFF, 0x3c6); - /* Write one register of IGA1 */ - outb(regno, 0x3C8); - outb(red >> shift, 0x3C9); - outb(green >> shift, 0x3C9); - outb(blue >> shift, 0x3C9); - - outb(0x1A, 0x3C4); - outb(sr1a, 0x3C5); - outb(0x1B, 0x3C4); - outb(sr1b, 0x3C5); - outb(0x67, 0x3D4); - outb(cr67, 0x3D5); - outb(0x6A, 0x3D4); - outb(cr6a, 0x3D5); - break; - case 16: - ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) | - ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); - break; - case 32: - ((u32 *) info->pseudo_palette)[regno] = - ((transp & 0xFF00) << 16) | - ((red & 0xFF00) << 8) | - ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); - break; - } - - return 0; + struct viafb_par *viapar = info->par; + u32 r, g, b; -} + if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { + if (regno > 255) + return -EINVAL; -/*CALLED BY: fb_set_cmap */ -/* fb_set_var, pass 256 colors */ -/*CALLED BY: fb_set_cmap */ -/* fbcon_set_palette, pass 16 colors */ -static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info) -{ - u32 len = cmap->len; - u32 i; - u16 *pred = cmap->red; - u16 *pgreen = cmap->green; - u16 *pblue = cmap->blue; - u16 *ptransp = cmap->transp; - u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; - if (len > 256) - return 1; - if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { - /* - * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip - * rev. - */ - outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); - rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; - } - switch (info->var.bits_per_pixel) { - case 8: - outb(0x1A, 0x3C4); - sr1a = inb(0x3C5); - outb(0x1B, 0x3C4); - sr1b = inb(0x3C5); - outb(0x67, 0x3D4); - cr67 = inb(0x3D5); - outb(0x6A, 0x3D4); - cr6a = inb(0x3D5); - /* Map the 3C6/7/8/9 to the IGA2 */ - outb(0x1A, 0x3C4); - outb(sr1a | 0x01, 0x3C5); - outb(0x1B, 0x3C4); - /* Second Display Engine colck always on */ - outb(sr1b | 0x80, 0x3C5); - outb(0x67, 0x3D4); - /* Second Display Color Depth 8 */ - outb(cr67 & 0x3F, 0x3D5); - outb(0x6A, 0x3D4); - /* Second Display Channel Reset CR6A[6]) */ - outb(cr6a & 0xBF, 0x3D5); - /* Second Display Channel Enable CR6A[7] */ - outb(cr6a | 0x80, 0x3D5); - /* Second Display Channel stop reset) */ - outb(cr6a | 0xC0, 0x3D5); - - /* Bit mask of palette */ - outb(0xFF, 0x3c6); - outb(0x00, 0x3C8); - if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && - rev >= 15) { - shift = 8; - viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); - viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); - } else { - shift = 10; - viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); - viafb_write_reg_mask(SR15, VIASR, 0, BIT7); - } - for (i = 0; i < len; i++) { - outb((*(pred + i)) >> shift, 0x3C9); - outb((*(pgreen + i)) >> shift, 0x3C9); - outb((*(pblue + i)) >> shift, 0x3C9); - } + if (!viafb_dual_fb || viapar->iga_path == IGA1) + viafb_set_primary_color_register(regno, red >> 8, + green >> 8, blue >> 8); - outb(0x1A, 0x3C4); - /* Map the 3C6/7/8/9 to the IGA1 */ - outb(sr1a & 0xFE, 0x3C5); - /* Bit mask of palette */ - outb(0xFF, 0x3c6); - outb(0x00, 0x3C8); - for (i = 0; i < len; i++) { - outb((*(pred + i)) >> shift, 0x3C9); - outb((*(pgreen + i)) >> shift, 0x3C9); - outb((*(pblue + i)) >> shift, 0x3C9); - } + if (!viafb_dual_fb || viapar->iga_path == IGA2) + viafb_set_secondary_color_register(regno, red >> 8, + green >> 8, blue >> 8); + } else { + if (regno > 15) + return -EINVAL; - outb(0x1A, 0x3C4); - outb(sr1a, 0x3C5); - outb(0x1B, 0x3C4); - outb(sr1b, 0x3C5); - outb(0x67, 0x3D4); - outb(cr67, 0x3D5); - outb(0x6A, 0x3D4); - outb(cr6a, 0x3D5); - break; - case 16: - if (len > 17) - return 0; /* Because static u32 pseudo_pal[17]; */ - for (i = 0; i < len; i++) - ((u32 *) info->pseudo_palette)[i] = - (*(pred + i) & 0xF800) | - ((*(pgreen + i) & 0xFC00) >> 5) | - ((*(pblue + i) & 0xF800) >> 11); - break; - case 32: - if (len > 17) - return 0; - if (ptransp) { - for (i = 0; i < len; i++) - ((u32 *) info->pseudo_palette)[i] = - ((*(ptransp + i) & 0xFF00) << 16) | - ((*(pred + i) & 0xFF00) << 8) | - ((*(pgreen + i) & 0xFF00)) | - ((*(pblue + i) & 0xFF00) >> 8); - } else { - for (i = 0; i < len; i++) - ((u32 *) info->pseudo_palette)[i] = - 0x00000000 | - ((*(pred + i) & 0xFF00) << 8) | - ((*(pgreen + i) & 0xFF00)) | - ((*(pblue + i) & 0xFF00) >> 8); - } - break; + r = (red >> (16 - info->var.red.length)) + << info->var.red.offset; + b = (blue >> (16 - info->var.blue.length)) + << info->var.blue.offset; + g = (green >> (16 - info->var.green.length)) + << info->var.green.offset; + ((u32 *) info->pseudo_palette)[regno] = r | g | b; } + return 0; } static int viafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - unsigned int offset; - - DEBUG_MSG(KERN_INFO "viafb_pan_display!\n"); - - offset = (var->xoffset + (var->yoffset * var->xres_virtual)) * - var->bits_per_pixel / 16; + struct viafb_par *viapar = info->par; + u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset) + * (var->bits_per_pixel / 8) + viapar->vram_addr; + + DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); + if (!viafb_dual_fb) { + viafb_set_primary_address(vram_addr); + viafb_set_secondary_address(vram_addr); + } else if (viapar->iga_path == IGA1) + viafb_set_primary_address(vram_addr); + else + viafb_set_secondary_address(vram_addr); - DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset); - viafb_set_primary_address(offset); return 0; } @@ -476,6 +376,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) u32 gpu32; DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); + printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n"); memset(&u, 0, sizeof(u)); switch (cmd) { @@ -1015,23 +916,6 @@ static int viafb_sync(struct fb_info *info) return 0; } -int viafb_get_mode_index(int hres, int vres) -{ - u32 i; - DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n"); - - for (i = 0; i < NUM_TOTAL_MODETABLE; i++) - if (CLE266Modes[i].mode_array && - CLE266Modes[i].crtc[0].crtc.hor_addr == hres && - CLE266Modes[i].crtc[0].crtc.ver_addr == vres) - break; - - if (i == NUM_TOTAL_MODETABLE) - return VIA_RES_INVALID; - - return CLE266Modes[i].ModeIndex; -} - static void check_available_device_to_enable(int device_id) { int device_num = 0; @@ -1330,7 +1214,7 @@ static void retrieve_device_setting(struct viafb_ioctl_setting setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; } -static void parse_active_dev(void) +static int parse_active_dev(void) { viafb_CRT_ON = STATE_OFF; viafb_DVI_ON = STATE_OFF; @@ -1341,60 +1225,63 @@ static void parse_active_dev(void) IGA path to devices in SAMM case. */ /* Note: The previous of active_dev is primary device, and the following is secondary device. */ - if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) { + if (!viafb_active_dev) { + viafb_CRT_ON = STATE_ON; + viafb_SAMM_ON = STATE_OFF; + } else if (!strcmp(viafb_active_dev, "CRT+DVI")) { /* CRT+DVI */ viafb_CRT_ON = STATE_ON; viafb_DVI_ON = STATE_ON; viafb_primary_dev = CRT_Device; - } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) { + } else if (!strcmp(viafb_active_dev, "DVI+CRT")) { /* DVI+CRT */ viafb_CRT_ON = STATE_ON; viafb_DVI_ON = STATE_ON; viafb_primary_dev = DVI_Device; - } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) { + } else if (!strcmp(viafb_active_dev, "CRT+LCD")) { /* CRT+LCD */ viafb_CRT_ON = STATE_ON; viafb_LCD_ON = STATE_ON; viafb_primary_dev = CRT_Device; - } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) { + } else if (!strcmp(viafb_active_dev, "LCD+CRT")) { /* LCD+CRT */ viafb_CRT_ON = STATE_ON; viafb_LCD_ON = STATE_ON; viafb_primary_dev = LCD_Device; - } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) { + } else if (!strcmp(viafb_active_dev, "DVI+LCD")) { /* DVI+LCD */ viafb_DVI_ON = STATE_ON; viafb_LCD_ON = STATE_ON; viafb_primary_dev = DVI_Device; - } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) { + } else if (!strcmp(viafb_active_dev, "LCD+DVI")) { /* LCD+DVI */ viafb_DVI_ON = STATE_ON; viafb_LCD_ON = STATE_ON; viafb_primary_dev = LCD_Device; - } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) { + } else if (!strcmp(viafb_active_dev, "LCD+LCD2")) { viafb_LCD_ON = STATE_ON; viafb_LCD2_ON = STATE_ON; viafb_primary_dev = LCD_Device; - } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) { + } else if (!strcmp(viafb_active_dev, "LCD2+LCD")) { viafb_LCD_ON = STATE_ON; viafb_LCD2_ON = STATE_ON; viafb_primary_dev = LCD2_Device; - } else if (!strncmp(viafb_active_dev, "CRT", 3)) { + } else if (!strcmp(viafb_active_dev, "CRT")) { /* CRT only */ viafb_CRT_ON = STATE_ON; viafb_SAMM_ON = STATE_OFF; - } else if (!strncmp(viafb_active_dev, "DVI", 3)) { + } else if (!strcmp(viafb_active_dev, "DVI")) { /* DVI only */ viafb_DVI_ON = STATE_ON; viafb_SAMM_ON = STATE_OFF; - } else if (!strncmp(viafb_active_dev, "LCD", 3)) { + } else if (!strcmp(viafb_active_dev, "LCD")) { /* LCD only */ viafb_LCD_ON = STATE_ON; viafb_SAMM_ON = STATE_OFF; - } else { - viafb_CRT_ON = STATE_ON; - viafb_SAMM_ON = STATE_OFF; - } + } else + return -EINVAL; + + return 0; } static int parse_port(char *opt_str, int *output_interface) @@ -1823,35 +1710,37 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) remove_proc_entry("viafb", NULL); } -static void parse_mode(const char *str, u32 *xres, u32 *yres) +static int parse_mode(const char *str, u32 *xres, u32 *yres) { char *ptr; + if (!str) { + *xres = 640; + *yres = 480; + return 0; + } + *xres = simple_strtoul(str, &ptr, 10); if (ptr[0] != 'x') - goto out_default; + return -EINVAL; *yres = simple_strtoul(&ptr[1], &ptr, 10); if (ptr[0]) - goto out_default; - - return; + return -EINVAL; -out_default: - printk(KERN_WARNING "viafb received invalid mode string: %s\n", str); - *xres = 640; - *yres = 480; + return 0; } static int __devinit via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { u32 default_xres, default_yres; - int vmode_index; + struct VideoModeTable *vmode_entry; + struct fb_var_screeninfo default_var; u32 viafb_par_length; DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); - + memset(&default_var, 0, sizeof(default_var)); viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); /* Allocate fb_info and ***_par here, also including some other needed @@ -1877,7 +1766,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, if (viafb_dual_fb) viafb_SAMM_ON = 1; - parse_active_dev(); parse_lcd_port(); parse_dvi_port(); @@ -1926,9 +1814,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, } parse_mode(viafb_mode, &default_xres, &default_yres); - vmode_index = viafb_get_mode_index(default_xres, default_yres); - DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index); - + vmode_entry = viafb_get_mode(default_xres, default_yres); if (viafb_SAMM_ON == 1) { parse_mode(viafb_mode1, &viafb_second_xres, &viafb_second_yres); @@ -1947,19 +1833,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viafb_second_virtual_yres = viafb_second_yres; } - switch (viafb_bpp) { - case 0 ... 8: - viafb_bpp = 8; - break; - case 9 ... 16: - viafb_bpp = 16; - break; - case 17 ... 32: - viafb_bpp = 32; - break; - default: - viafb_bpp = 8; - } default_var.xres = default_xres; default_var.yres = default_yres; switch (default_xres) { @@ -1972,8 +1845,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, } default_var.yres_virtual = default_yres; default_var.bits_per_pixel = viafb_bpp; - if (default_var.bits_per_pixel == 15) - default_var.bits_per_pixel = 16; default_var.pixclock = viafb_get_pixclock(default_xres, default_yres, viafb_refresh); default_var.left_margin = (default_xres >> 3) & 0xf8; @@ -1982,6 +1853,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, default_var.lower_margin = 4; default_var.hsync_len = default_var.left_margin; default_var.vsync_len = 4; + viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); + viafbinfo->var = default_var; if (viafb_dual_fb) { viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev); @@ -2016,8 +1889,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, default_var.yres = viafb_second_yres; default_var.xres_virtual = viafb_second_virtual_xres; default_var.yres_virtual = viafb_second_virtual_yres; - if (viafb_bpp1 != viafb_bpp) - viafb_bpp1 = viafb_bpp; default_var.bits_per_pixel = viafb_bpp1; default_var.pixclock = viafb_get_pixclock(viafb_second_xres, viafb_second_yres, @@ -2037,9 +1908,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, &viafbinfo1->fix); } - viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); - viafb_check_var(&default_var, viafbinfo); - viafbinfo->var = default_var; + viafb_check_var(&viafbinfo->var, viafbinfo); viafb_update_fix(viafbinfo); viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, &viafbinfo->fix); @@ -2197,12 +2066,20 @@ static struct pci_driver viafb_driver = { static int __init viafb_init(void) { + u32 dummy; #ifndef MODULE char *option = NULL; if (fb_get_options("viafb", &option)) return -ENODEV; viafb_setup(option); #endif + if (parse_mode(viafb_mode, &dummy, &dummy) + || parse_mode(viafb_mode1, &dummy, &dummy) + || viafb_bpp < 0 || viafb_bpp > 32 + || viafb_bpp1 < 0 || viafb_bpp1 > 32 + || parse_active_dev()) + return -EINVAL; + printk(KERN_INFO "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", VERSION_MAJOR, VERSION_MINOR); @@ -2230,15 +2107,12 @@ static struct fb_ops viafb_ops = { .fb_cursor = viafb_cursor, .fb_ioctl = viafb_ioctl, .fb_sync = viafb_sync, - .fb_setcmap = viafb_setcmap, }; module_init(viafb_init); module_exit(viafb_exit); #ifdef MODULE -module_param(viafb_memsize, int, S_IRUSR); - module_param(viafb_mode, charp, S_IRUSR); MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index 0c94d24..61b5953 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h @@ -83,22 +83,16 @@ struct viafb_par { extern unsigned int viafb_second_virtual_yres; extern unsigned int viafb_second_virtual_xres; -extern unsigned int viafb_second_offset; -extern int viafb_second_size; extern int viafb_SAMM_ON; extern int viafb_dual_fb; extern int viafb_LCD2_ON; extern int viafb_LCD_ON; extern int viafb_DVI_ON; extern int viafb_hotplug; -extern int viafb_memsize; extern int strict_strtoul(const char *cp, unsigned int base, unsigned long *res); -void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, - int mode_index); -int viafb_get_mode_index(int hres, int vres); u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info, u8 index); diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index b74f8a6..af50e24 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c @@ -412,7 +412,7 @@ struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C}, }; struct patch_table res_patch_table[] = { - {VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768} + {ARRAY_SIZE(PM1024x768), PM1024x768} }; /* struct VPITTable { @@ -879,169 +879,151 @@ struct crt_mode_table CRTM2048x1536[] = { {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} } }; -/* Video Mode Table */ -/* struct VideoModeTable {*/ -/* int ModeIndex;*/ -/* struct crt_mode_table *crtc;*/ -/* int mode_array;*/ -/* };*/ -struct VideoModeTable CLE266Modes[] = { +struct VideoModeTable viafb_modes[] = { /* Display : 480x640 (GTF) */ - {VIA_RES_480X640, CRTM480x640, ARRAY_SIZE(CRTM480x640)}, + {CRTM480x640, ARRAY_SIZE(CRTM480x640)}, /* Display : 640x480 */ - {VIA_RES_640X480, CRTM640x480, ARRAY_SIZE(CRTM640x480)}, + {CRTM640x480, ARRAY_SIZE(CRTM640x480)}, /* Display : 720x480 (GTF) */ - {VIA_RES_720X480, CRTM720x480, ARRAY_SIZE(CRTM720x480)}, + {CRTM720x480, ARRAY_SIZE(CRTM720x480)}, /* Display : 720x576 (GTF) */ - {VIA_RES_720X576, CRTM720x576, ARRAY_SIZE(CRTM720x576)}, + {CRTM720x576, ARRAY_SIZE(CRTM720x576)}, /* Display : 800x600 */ - {VIA_RES_800X600, CRTM800x600, ARRAY_SIZE(CRTM800x600)}, + {CRTM800x600, ARRAY_SIZE(CRTM800x600)}, /* Display : 800x480 (CVT) */ - {VIA_RES_800X480, CRTM800x480, ARRAY_SIZE(CRTM800x480)}, + {CRTM800x480, ARRAY_SIZE(CRTM800x480)}, /* Display : 848x480 (CVT) */ - {VIA_RES_848X480, CRTM848x480, ARRAY_SIZE(CRTM848x480)}, + {CRTM848x480, ARRAY_SIZE(CRTM848x480)}, /* Display : 852x480 (GTF) */ - {VIA_RES_856X480, CRTM852x480, ARRAY_SIZE(CRTM852x480)}, + {CRTM852x480, ARRAY_SIZE(CRTM852x480)}, /* Display : 1024x512 (GTF) */ - {VIA_RES_1024X512, CRTM1024x512, ARRAY_SIZE(CRTM1024x512)}, + {CRTM1024x512, ARRAY_SIZE(CRTM1024x512)}, /* Display : 1024x600 */ - {VIA_RES_1024X600, CRTM1024x600, ARRAY_SIZE(CRTM1024x600)}, - - /* Display : 1024x576 (GTF) */ - /*{ VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, */ + {CRTM1024x600, ARRAY_SIZE(CRTM1024x600)}, /* Display : 1024x768 */ - {VIA_RES_1024X768, CRTM1024x768, ARRAY_SIZE(CRTM1024x768)}, + {CRTM1024x768, ARRAY_SIZE(CRTM1024x768)}, /* Display : 1152x864 */ - {VIA_RES_1152X864, CRTM1152x864, ARRAY_SIZE(CRTM1152x864)}, + {CRTM1152x864, ARRAY_SIZE(CRTM1152x864)}, /* Display : 1280x768 (GTF) */ - {VIA_RES_1280X768, CRTM1280x768, ARRAY_SIZE(CRTM1280x768)}, + {CRTM1280x768, ARRAY_SIZE(CRTM1280x768)}, /* Display : 960x600 (CVT) */ - {VIA_RES_960X600, CRTM960x600, ARRAY_SIZE(CRTM960x600)}, + {CRTM960x600, ARRAY_SIZE(CRTM960x600)}, /* Display : 1000x600 (GTF) */ - {VIA_RES_1000X600, CRTM1000x600, ARRAY_SIZE(CRTM1000x600)}, + {CRTM1000x600, ARRAY_SIZE(CRTM1000x600)}, /* Display : 1024x576 (GTF) */ - {VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, + {CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, /* Display : 1088x612 (GTF) */ - {VIA_RES_1088X612, CRTM1088x612, ARRAY_SIZE(CRTM1088x612)}, + {CRTM1088x612, ARRAY_SIZE(CRTM1088x612)}, /* Display : 1152x720 (CVT) */ - {VIA_RES_1152X720, CRTM1152x720, ARRAY_SIZE(CRTM1152x720)}, + {CRTM1152x720, ARRAY_SIZE(CRTM1152x720)}, /* Display : 1200x720 (GTF) */ - {VIA_RES_1200X720, CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, + {CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, /* Display : 1280x600 (GTF) */ - {VIA_RES_1280X600, CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, + {CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, /* Display : 1280x800 (CVT) */ - {VIA_RES_1280X800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, - - /* Display : 1280x800 (GTF) */ - /*{ M1280x800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, */ + {CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, /* Display : 1280x960 */ - {VIA_RES_1280X960, CRTM1280x960, ARRAY_SIZE(CRTM1280x960)}, + {CRTM1280x960, ARRAY_SIZE(CRTM1280x960)}, /* Display : 1280x1024 */ - {VIA_RES_1280X1024, CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)}, + {CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)}, /* Display : 1360x768 (CVT) */ - {VIA_RES_1360X768, CRTM1360x768, ARRAY_SIZE(CRTM1360x768)}, - - /* Display : 1360x768 (CVT Reduce Blanking) */ - {VIA_RES_1360X768_RB, CRTM1360x768_RB, - ARRAY_SIZE(CRTM1360x768_RB)}, + {CRTM1360x768, ARRAY_SIZE(CRTM1360x768)}, /* Display : 1366x768 */ - {VIA_RES_1366X768, CRTM1366x768, ARRAY_SIZE(CRTM1366x768)}, + {CRTM1366x768, ARRAY_SIZE(CRTM1366x768)}, /* Display : 1368x768 (GTF) */ - /*{ M1368x768,CRTM1368x768,ARRAY_SIZE(CRTM1368x768)}, */ - /* Display : 1368x768 (GTF) */ - {VIA_RES_1368X768, CRTM1368x768, ARRAY_SIZE(CRTM1368x768)}, + {CRTM1368x768, ARRAY_SIZE(CRTM1368x768)}, /* Display : 1440x900 (CVT) */ - {VIA_RES_1440X900, CRTM1440x900, ARRAY_SIZE(CRTM1440x900)}, - - /* Display : 1440x900 (CVT Reduce Blanking) */ - {VIA_RES_1440X900_RB, CRTM1440x900_RB, - ARRAY_SIZE(CRTM1440x900_RB)}, + {CRTM1440x900, ARRAY_SIZE(CRTM1440x900)}, /* Display : 1440x1050 (GTF) */ - {VIA_RES_1440X1050, CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)}, - - /* Display : 1400x1050 (CVT Reduce Blanking) */ - {VIA_RES_1400X1050_RB, CRTM1400x1050_RB, - ARRAY_SIZE(CRTM1400x1050_RB)}, + {CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)}, /* Display : 1600x900 (CVT) */ - {VIA_RES_1600X900, CRTM1600x900, ARRAY_SIZE(CRTM1600x900)}, - - /* Display : 1600x900 (CVT Reduce Blanking) */ - {VIA_RES_1600X900_RB, CRTM1600x900_RB, - ARRAY_SIZE(CRTM1600x900_RB)}, + {CRTM1600x900, ARRAY_SIZE(CRTM1600x900)}, /* Display : 1600x1024 (GTF) */ - {VIA_RES_1600X1024, CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)}, + {CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)}, /* Display : 1600x1200 */ - {VIA_RES_1600X1200, CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)}, + {CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)}, /* Display : 1680x1050 (CVT) */ - {VIA_RES_1680X1050, CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)}, - - /* Display : 1680x1050 (CVT Reduce Blanking) */ - {VIA_RES_1680X1050_RB, CRTM1680x1050_RB, - ARRAY_SIZE(CRTM1680x1050_RB)}, + {CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)}, /* Display : 1792x1344 (DMT) */ - {VIA_RES_1792X1344, CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)}, + {CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)}, /* Display : 1856x1392 (DMT) */ - {VIA_RES_1856X1392, CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)}, + {CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)}, /* Display : 1920x1440 */ - {VIA_RES_1920X1440, CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)}, + {CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)}, /* Display : 2048x1536 */ - {VIA_RES_2048X1536, CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)}, + {CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)}, /* Display : 1280x720 */ - {VIA_RES_1280X720, CRTM1280x720, ARRAY_SIZE(CRTM1280x720)}, + {CRTM1280x720, ARRAY_SIZE(CRTM1280x720)}, /* Display : 1920x1080 (CVT) */ - {VIA_RES_1920X1080, CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)}, - - /* Display : 1920x1080 (CVT Reduce Blanking) */ - {VIA_RES_1920X1080_RB, CRTM1920x1080_RB, - ARRAY_SIZE(CRTM1920x1080_RB)}, + {CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)}, /* Display : 1920x1200 (CVT) */ - {VIA_RES_1920X1200, CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)}, - - /* Display : 1920x1200 (CVT Reduce Blanking) */ - {VIA_RES_1920X1200_RB, CRTM1920x1200_RB, - ARRAY_SIZE(CRTM1920x1200_RB)}, + {CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)}, /* Display : 1400x1050 (CVT) */ - {VIA_RES_1400X1050, CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)} + {CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)} }; + +struct VideoModeTable viafb_rb_modes[] = { + /* Display : 1360x768 (CVT Reduce Blanking) */ + {CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)}, + + /* Display : 1440x900 (CVT Reduce Blanking) */ + {CRTM1440x900_RB, ARRAY_SIZE(CRTM1440x900_RB)}, + + /* Display : 1400x1050 (CVT Reduce Blanking) */ + {CRTM1400x1050_RB, ARRAY_SIZE(CRTM1400x1050_RB)}, + + /* Display : 1600x900 (CVT Reduce Blanking) */ + {CRTM1600x900_RB, ARRAY_SIZE(CRTM1600x900_RB)}, + + /* Display : 1680x1050 (CVT Reduce Blanking) */ + {CRTM1680x1050_RB, ARRAY_SIZE(CRTM1680x1050_RB)}, + + /* Display : 1920x1080 (CVT Reduce Blanking) */ + {CRTM1920x1080_RB, ARRAY_SIZE(CRTM1920x1080_RB)}, + + /* Display : 1920x1200 (CVT Reduce Blanking) */ + {CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)} +}; + struct crt_mode_table CEAM1280x720[] = { {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP, M1280X720_CEA_R60_VSP, @@ -1056,8 +1038,8 @@ struct crt_mode_table CEAM1920x1080[] = { }; struct VideoModeTable CEA_HDMI_Modes[] = { /* Display : 1280x720 */ - {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, - {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} + {CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, + {CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} }; int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl); @@ -1069,4 +1051,28 @@ int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs); int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs); int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); -int NUM_TOTAL_MODETABLE = ARRAY_SIZE(CLE266Modes); + + +struct VideoModeTable *viafb_get_mode(int hres, int vres) +{ + u32 i; + for (i = 0; i < ARRAY_SIZE(viafb_modes); i++) + if (viafb_modes[i].mode_array && + viafb_modes[i].crtc[0].crtc.hor_addr == hres && + viafb_modes[i].crtc[0].crtc.ver_addr == vres) + return &viafb_modes[i]; + + return NULL; +} + +struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) +{ + u32 i; + for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++) + if (viafb_rb_modes[i].mode_array && + viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres && + viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres) + return &viafb_rb_modes[i]; + + return NULL; +} diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index a9d6554..5b1ced8 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h @@ -32,13 +32,11 @@ struct VPITTable { }; struct VideoModeTable { - int ModeIndex; struct crt_mode_table *crtc; int mode_array; }; struct patch_table { - int mode_index; int table_length; struct io_reg *io_reg_table; }; @@ -59,13 +57,11 @@ extern int NUM_TOTAL_CX700_ModeXregs; extern int NUM_TOTAL_VX855_ModeXregs; extern int NUM_TOTAL_CLE266_ModeXregs; extern int NUM_TOTAL_PATCH_MODE; -extern int NUM_TOTAL_MODETABLE; /********************/ /* Mode Table */ /********************/ -extern struct VideoModeTable CLE266Modes[]; extern struct crt_mode_table CEAM1280x720[]; extern struct crt_mode_table CEAM1920x1080[]; extern struct VideoModeTable CEA_HDMI_Modes[]; @@ -81,4 +77,8 @@ extern struct io_reg CLE266_ModeXregs[]; extern struct io_reg PM1024x768[]; extern struct patch_table res_patch_table[]; extern struct VPITTable VPIT; + +struct VideoModeTable *viafb_get_mode(int hres, int vres); +struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); + #endif /* __VIAMODE_H__ */ diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index 406caa6..e5f7441 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -214,7 +214,7 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev) (++retries < DS2482_WAIT_IDLE_TIMEOUT)); } - if (retries > DS2482_WAIT_IDLE_TIMEOUT) + if (retries >= DS2482_WAIT_IDLE_TIMEOUT) printk(KERN_ERR "%s: timeout on channel %d\n", __func__, pdev->channel); diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index 65244c0..4926703 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -102,7 +102,7 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) return ((__raw_readb(ctrl_addr)) >> 3) & 0x1; } -static int __init mxc_w1_probe(struct platform_device *pdev) +static int __devinit mxc_w1_probe(struct platform_device *pdev) { struct mxc_w1_device *mdev; struct resource *res; @@ -166,7 +166,7 @@ failed_clk: /* * disassociate the w1 device from the driver */ -static int mxc_w1_remove(struct platform_device *pdev) +static int __devexit mxc_w1_remove(struct platform_device *pdev) { struct mxc_w1_device *mdev = platform_get_drvdata(pdev); struct resource *res; diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index acc7e3b..ad5897d 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -986,7 +986,7 @@ int w1_process(void *data) return 0; } -static int w1_init(void) +static int __init w1_init(void) { int retval; @@ -1034,7 +1034,7 @@ err_out_exit_init: return retval; } -static void w1_fini(void) +static void __exit w1_fini(void) { struct w1_master *dev; diff --git a/drivers/zorro/zorro.ids b/drivers/zorro/zorro.ids index 0c0f99e..de24e3d 100644 --- a/drivers/zorro/zorro.ids +++ b/drivers/zorro/zorro.ids @@ -108,7 +108,7 @@ 0c00 500XP/SupraDrive WordSync [SCSI Host Adapter] 0d00 SupraDrive WordSync II [SCSI Host Adapter] 1000 2400zi+ [Modem] -0422 Computer Systems Assosiates +0422 Computer Systems Associates 1100 Magnum 40 [Accelerator and SCSI Host Adapter] 1500 12 Gauge [SCSI Host Adapter] 0439 Marc Michael Groth |