mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
This commit is contained in:
commit
4961e02f19
3607 changed files with 185407 additions and 86837 deletions
|
|
@ -96,8 +96,6 @@ source "drivers/edac/Kconfig"
|
|||
|
||||
source "drivers/rtc/Kconfig"
|
||||
|
||||
source "drivers/clocksource/Kconfig"
|
||||
|
||||
source "drivers/dma/Kconfig"
|
||||
|
||||
source "drivers/dca/Kconfig"
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -279,9 +279,9 @@ int __init acpi_numa_init(void)
|
|||
/* SRAT: Static Resource Affinity Table */
|
||||
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
|
||||
acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
|
||||
acpi_parse_x2apic_affinity, NR_CPUS);
|
||||
acpi_parse_x2apic_affinity, nr_cpu_ids);
|
||||
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
|
||||
acpi_parse_processor_affinity, NR_CPUS);
|
||||
acpi_parse_processor_affinity, nr_cpu_ids);
|
||||
ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
|
||||
acpi_parse_memory_affinity,
|
||||
NR_NODE_MEMBLKS);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
978
drivers/acpi/processor_driver.c
Normal file
978
drivers/acpi/processor_driver.c
Normal file
|
|
@ -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");
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -561,7 +561,7 @@ end:
|
|||
}
|
||||
|
||||
int acpi_processor_preregister_performance(
|
||||
struct acpi_processor_performance *performance)
|
||||
struct acpi_processor_performance __percpu *performance)
|
||||
{
|
||||
int count, count_target;
|
||||
int retval = 0;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
|
|||
struct acpi_table_header *header = NULL;
|
||||
struct acpi_table_attr *attr = NULL;
|
||||
|
||||
sysfs_attr_init(&table_attr->attr.attr);
|
||||
if (table_header->signature[0] != '\0')
|
||||
memcpy(table_attr->name, table_header->signature,
|
||||
ACPI_NAME_SIZE);
|
||||
|
|
@ -475,6 +476,7 @@ void acpi_irq_stats_init(void)
|
|||
goto fail;
|
||||
strncpy(name, buffer, strlen(buffer) + 1);
|
||||
|
||||
sysfs_attr_init(&counter_attrs[i].attr);
|
||||
counter_attrs[i].attr.name = name;
|
||||
counter_attrs[i].attr.mode = 0644;
|
||||
counter_attrs[i].show = counter_show;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ static struct fb_ops cfag12864bfb_ops = {
|
|||
.fb_mmap = cfag12864bfb_mmap,
|
||||
};
|
||||
|
||||
static int __init cfag12864bfb_probe(struct platform_device *device)
|
||||
static int __devinit cfag12864bfb_probe(struct platform_device *device)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct fb_info *info = framebuffer_alloc(0, &device->dev);
|
||||
|
|
|
|||
|
|
@ -3,35 +3,50 @@ menu "Generic Driver Options"
|
|||
config UEVENT_HELPER_PATH
|
||||
string "path to uevent helper"
|
||||
depends on HOTPLUG
|
||||
default "/sbin/hotplug"
|
||||
default ""
|
||||
help
|
||||
Path to uevent helper program forked by the kernel for
|
||||
every uevent.
|
||||
Before the switch to the netlink-based uevent source, this was
|
||||
used to hook hotplug scripts into kernel device events. It
|
||||
usually pointed to a shell script at /sbin/hotplug.
|
||||
This should not be used today, because usual systems create
|
||||
many events at bootup or device discovery in a very short time
|
||||
frame. One forked process per event can create so many processes
|
||||
that it creates a high system load, or on smaller systems
|
||||
it is known to create out-of-memory situations during bootup.
|
||||
|
||||
config DEVTMPFS
|
||||
bool "Create a kernel maintained /dev tmpfs (EXPERIMENTAL)"
|
||||
bool "Maintain a devtmpfs filesystem to mount at /dev"
|
||||
depends on HOTPLUG && SHMEM && TMPFS
|
||||
help
|
||||
This creates a tmpfs filesystem, and mounts it at bootup
|
||||
and mounts it at /dev. The kernel driver core creates device
|
||||
nodes for all registered devices in that filesystem. All device
|
||||
nodes are owned by root and have the default mode of 0600.
|
||||
Userspace can add and delete the nodes as needed. This is
|
||||
intended to simplify bootup, and make it possible to delay
|
||||
the initial coldplug at bootup done by udev in userspace.
|
||||
It should also provide a simpler way for rescue systems
|
||||
to bring up a kernel with dynamic major/minor numbers.
|
||||
Meaningful symlinks, permissions and device ownership must
|
||||
still be handled by userspace.
|
||||
If unsure, say N here.
|
||||
This creates a tmpfs filesystem instance early at bootup.
|
||||
In this filesystem, the kernel driver core maintains device
|
||||
nodes with their default names and permissions for all
|
||||
registered devices with an assigned major/minor number.
|
||||
Userspace can modify the filesystem content as needed, add
|
||||
symlinks, and apply needed permissions.
|
||||
It provides a fully functional /dev directory, where usually
|
||||
udev runs on top, managing permissions and adding meaningful
|
||||
symlinks.
|
||||
In very limited environments, it may provide a sufficient
|
||||
functional /dev without any further help. It also allows simple
|
||||
rescue systems, and reliably handles dynamic major/minor numbers.
|
||||
|
||||
config DEVTMPFS_MOUNT
|
||||
bool "Automount devtmpfs at /dev"
|
||||
bool "Automount devtmpfs at /dev, after the kernel mounted the rootfs"
|
||||
depends on DEVTMPFS
|
||||
help
|
||||
This will mount devtmpfs at /dev if the kernel mounts the root
|
||||
filesystem. It will not affect initramfs based mounting.
|
||||
If unsure, say N here.
|
||||
This will instruct the kernel to automatically mount the
|
||||
devtmpfs filesystem at /dev, directly after the kernel has
|
||||
mounted the root filesystem. The behavior can be overridden
|
||||
with the commandline parameter: devtmpfs.mount=0|1.
|
||||
This option does not affect initramfs based booting, here
|
||||
the devtmpfs filesystem always needs to be mounted manually
|
||||
after the roots is mounted.
|
||||
With this option enabled, it allows to bring up a system in
|
||||
rescue mode with init=/bin/sh, even when the /dev directory
|
||||
on the rootfs is completely empty.
|
||||
|
||||
config STANDALONE
|
||||
bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct sysfs_ops driver_sysfs_ops = {
|
||||
static const struct sysfs_ops driver_sysfs_ops = {
|
||||
.show = drv_attr_show,
|
||||
.store = drv_attr_store,
|
||||
};
|
||||
|
|
@ -115,7 +115,7 @@ static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct sysfs_ops bus_sysfs_ops = {
|
||||
static const struct sysfs_ops bus_sysfs_ops = {
|
||||
.show = bus_attr_show,
|
||||
.store = bus_attr_store,
|
||||
};
|
||||
|
|
@ -154,7 +154,7 @@ static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct kset_uevent_ops bus_uevent_ops = {
|
||||
static const struct kset_uevent_ops bus_uevent_ops = {
|
||||
.filter = bus_uevent_filter,
|
||||
};
|
||||
|
||||
|
|
@ -173,10 +173,10 @@ static ssize_t driver_unbind(struct device_driver *drv,
|
|||
dev = bus_find_device_by_name(bus, NULL, buf);
|
||||
if (dev && dev->driver == drv) {
|
||||
if (dev->parent) /* Needed for USB */
|
||||
down(&dev->parent->sem);
|
||||
device_lock(dev->parent);
|
||||
device_release_driver(dev);
|
||||
if (dev->parent)
|
||||
up(&dev->parent->sem);
|
||||
device_unlock(dev->parent);
|
||||
err = count;
|
||||
}
|
||||
put_device(dev);
|
||||
|
|
@ -200,12 +200,12 @@ static ssize_t driver_bind(struct device_driver *drv,
|
|||
dev = bus_find_device_by_name(bus, NULL, buf);
|
||||
if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
|
||||
if (dev->parent) /* Needed for USB */
|
||||
down(&dev->parent->sem);
|
||||
down(&dev->sem);
|
||||
device_lock(dev->parent);
|
||||
device_lock(dev);
|
||||
err = driver_probe_device(drv, dev);
|
||||
up(&dev->sem);
|
||||
device_unlock(dev);
|
||||
if (dev->parent)
|
||||
up(&dev->parent->sem);
|
||||
device_unlock(dev->parent);
|
||||
|
||||
if (err > 0) {
|
||||
/* success */
|
||||
|
|
@ -744,10 +744,10 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
|
|||
|
||||
if (!dev->driver) {
|
||||
if (dev->parent) /* Needed for USB */
|
||||
down(&dev->parent->sem);
|
||||
device_lock(dev->parent);
|
||||
ret = device_attach(dev);
|
||||
if (dev->parent)
|
||||
up(&dev->parent->sem);
|
||||
device_unlock(dev->parent);
|
||||
}
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
|
@ -779,10 +779,10 @@ int device_reprobe(struct device *dev)
|
|||
{
|
||||
if (dev->driver) {
|
||||
if (dev->parent) /* Needed for USB */
|
||||
down(&dev->parent->sem);
|
||||
device_lock(dev->parent);
|
||||
device_release_driver(dev);
|
||||
if (dev->parent)
|
||||
up(&dev->parent->sem);
|
||||
device_unlock(dev->parent);
|
||||
}
|
||||
return bus_rescan_devices_helper(dev, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
|
|||
ssize_t ret = -EIO;
|
||||
|
||||
if (class_attr->show)
|
||||
ret = class_attr->show(cp->class, buf);
|
||||
ret = class_attr->show(cp->class, class_attr, buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
|
|||
ssize_t ret = -EIO;
|
||||
|
||||
if (class_attr->store)
|
||||
ret = class_attr->store(cp->class, buf, count);
|
||||
ret = class_attr->store(cp->class, class_attr, buf, count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ static void class_release(struct kobject *kobj)
|
|||
kfree(cp);
|
||||
}
|
||||
|
||||
static struct sysfs_ops class_sysfs_ops = {
|
||||
static const struct sysfs_ops class_sysfs_ops = {
|
||||
.show = class_attr_show,
|
||||
.store = class_attr_store,
|
||||
};
|
||||
|
|
@ -490,6 +490,16 @@ void class_interface_unregister(struct class_interface *class_intf)
|
|||
class_put(parent);
|
||||
}
|
||||
|
||||
ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct class_attribute_string *cs;
|
||||
cs = container_of(attr, struct class_attribute_string, attr);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", cs->str);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(show_class_attr_string);
|
||||
|
||||
struct class_compat {
|
||||
struct kobject *kobj;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct sysfs_ops dev_sysfs_ops = {
|
||||
static const struct sysfs_ops dev_sysfs_ops = {
|
||||
.show = dev_attr_show,
|
||||
.store = dev_attr_store,
|
||||
};
|
||||
|
|
@ -252,7 +252,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
|
|||
return retval;
|
||||
}
|
||||
|
||||
static struct kset_uevent_ops device_uevent_ops = {
|
||||
static const struct kset_uevent_ops device_uevent_ops = {
|
||||
.filter = dev_uevent_filter,
|
||||
.name = dev_uevent_name,
|
||||
.uevent = dev_uevent,
|
||||
|
|
@ -306,15 +306,10 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
|||
{
|
||||
enum kobject_action action;
|
||||
|
||||
if (kobject_action_type(buf, count, &action) == 0) {
|
||||
if (kobject_action_type(buf, count, &action) == 0)
|
||||
kobject_uevent(&dev->kobj, action);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_err(dev, "uevent: unsupported action-string; this will "
|
||||
"be ignored in a future kernel version\n");
|
||||
kobject_uevent(&dev->kobj, KOBJ_ADD);
|
||||
out:
|
||||
else
|
||||
dev_err(dev, "uevent: unknown action-string\n");
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
@ -607,6 +602,7 @@ static struct kobject *get_device_parent(struct device *dev,
|
|||
int retval;
|
||||
|
||||
if (dev->class) {
|
||||
static DEFINE_MUTEX(gdp_mutex);
|
||||
struct kobject *kobj = NULL;
|
||||
struct kobject *parent_kobj;
|
||||
struct kobject *k;
|
||||
|
|
@ -623,6 +619,8 @@ static struct kobject *get_device_parent(struct device *dev,
|
|||
else
|
||||
parent_kobj = &parent->kobj;
|
||||
|
||||
mutex_lock(&gdp_mutex);
|
||||
|
||||
/* find our class-directory at the parent and reference it */
|
||||
spin_lock(&dev->class->p->class_dirs.list_lock);
|
||||
list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
|
||||
|
|
@ -631,20 +629,26 @@ static struct kobject *get_device_parent(struct device *dev,
|
|||
break;
|
||||
}
|
||||
spin_unlock(&dev->class->p->class_dirs.list_lock);
|
||||
if (kobj)
|
||||
if (kobj) {
|
||||
mutex_unlock(&gdp_mutex);
|
||||
return kobj;
|
||||
}
|
||||
|
||||
/* or create a new class-directory at the parent device */
|
||||
k = kobject_create();
|
||||
if (!k)
|
||||
if (!k) {
|
||||
mutex_unlock(&gdp_mutex);
|
||||
return NULL;
|
||||
}
|
||||
k->kset = &dev->class->p->class_dirs;
|
||||
retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
|
||||
if (retval < 0) {
|
||||
mutex_unlock(&gdp_mutex);
|
||||
kobject_put(k);
|
||||
return NULL;
|
||||
}
|
||||
/* do not emit an uevent for this simple "glue" directory */
|
||||
mutex_unlock(&gdp_mutex);
|
||||
return k;
|
||||
}
|
||||
|
||||
|
|
@ -1574,22 +1578,16 @@ int device_rename(struct device *dev, char *new_name)
|
|||
if (old_class_name) {
|
||||
new_class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
if (new_class_name) {
|
||||
error = sysfs_create_link_nowarn(&dev->parent->kobj,
|
||||
&dev->kobj,
|
||||
new_class_name);
|
||||
if (error)
|
||||
goto out;
|
||||
sysfs_remove_link(&dev->parent->kobj, old_class_name);
|
||||
error = sysfs_rename_link(&dev->parent->kobj,
|
||||
&dev->kobj,
|
||||
old_class_name,
|
||||
new_class_name);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (dev->class) {
|
||||
error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj,
|
||||
&dev->kobj, dev_name(dev));
|
||||
if (error)
|
||||
goto out;
|
||||
sysfs_remove_link(&dev->class->p->class_subsys.kobj,
|
||||
old_device_name);
|
||||
error = sysfs_rename_link(&dev->class->p->class_subsys.kobj,
|
||||
&dev->kobj, old_device_name, new_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,11 @@
|
|||
|
||||
#include "base.h"
|
||||
|
||||
static struct sysdev_class_attribute *cpu_sysdev_class_attrs[];
|
||||
|
||||
struct sysdev_class cpu_sysdev_class = {
|
||||
.name = "cpu",
|
||||
.attrs = cpu_sysdev_class_attrs,
|
||||
};
|
||||
EXPORT_SYMBOL(cpu_sysdev_class);
|
||||
|
||||
|
|
@ -76,34 +79,24 @@ void unregister_cpu(struct cpu *cpu)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
||||
static ssize_t cpu_probe_store(struct class *class, const char *buf,
|
||||
static ssize_t cpu_probe_store(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
return arch_cpu_probe(buf, count);
|
||||
}
|
||||
|
||||
static ssize_t cpu_release_store(struct class *class, const char *buf,
|
||||
static ssize_t cpu_release_store(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
return arch_cpu_release(buf, count);
|
||||
}
|
||||
|
||||
static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
|
||||
static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store);
|
||||
|
||||
int __init cpu_probe_release_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
|
||||
&class_attr_probe.attr);
|
||||
if (!rc)
|
||||
rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
|
||||
&class_attr_release.attr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
device_initcall(cpu_probe_release_init);
|
||||
static SYSDEV_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
|
||||
static SYSDEV_ATTR(release, S_IWUSR, NULL, cpu_release_store);
|
||||
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
|
||||
|
||||
#else /* ... !CONFIG_HOTPLUG_CPU */
|
||||
|
|
@ -141,31 +134,39 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
|
|||
/*
|
||||
* Print cpu online, possible, present, and system maps
|
||||
*/
|
||||
static ssize_t print_cpus_map(char *buf, const struct cpumask *map)
|
||||
|
||||
struct cpu_attr {
|
||||
struct sysdev_class_attribute attr;
|
||||
const struct cpumask *const * const map;
|
||||
};
|
||||
|
||||
static ssize_t show_cpus_attr(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int n = cpulist_scnprintf(buf, PAGE_SIZE-2, map);
|
||||
struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
|
||||
int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *(ca->map));
|
||||
|
||||
buf[n++] = '\n';
|
||||
buf[n] = '\0';
|
||||
return n;
|
||||
}
|
||||
|
||||
#define print_cpus_func(type) \
|
||||
static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \
|
||||
{ \
|
||||
return print_cpus_map(buf, cpu_##type##_mask); \
|
||||
} \
|
||||
static struct sysdev_class_attribute attr_##type##_map = \
|
||||
_SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
|
||||
#define _CPU_ATTR(name, map) \
|
||||
{ _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map }
|
||||
|
||||
print_cpus_func(online);
|
||||
print_cpus_func(possible);
|
||||
print_cpus_func(present);
|
||||
/* Keep in sync with cpu_sysdev_class_attrs */
|
||||
static struct cpu_attr cpu_attrs[] = {
|
||||
_CPU_ATTR(online, &cpu_online_mask),
|
||||
_CPU_ATTR(possible, &cpu_possible_mask),
|
||||
_CPU_ATTR(present, &cpu_present_mask),
|
||||
};
|
||||
|
||||
/*
|
||||
* Print values for NR_CPUS and offlined cpus
|
||||
*/
|
||||
static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf)
|
||||
static ssize_t print_cpus_kernel_max(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr, char *buf)
|
||||
{
|
||||
int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
|
||||
return n;
|
||||
|
|
@ -175,7 +176,8 @@ static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
|
|||
/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
|
||||
unsigned int total_cpus;
|
||||
|
||||
static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf)
|
||||
static ssize_t print_cpus_offline(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr, char *buf)
|
||||
{
|
||||
int n = 0, len = PAGE_SIZE-2;
|
||||
cpumask_var_t offline;
|
||||
|
|
@ -204,29 +206,6 @@ static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf)
|
|||
}
|
||||
static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
|
||||
|
||||
static struct sysdev_class_attribute *cpu_state_attr[] = {
|
||||
&attr_online_map,
|
||||
&attr_possible_map,
|
||||
&attr_present_map,
|
||||
&attr_kernel_max,
|
||||
&attr_offline,
|
||||
};
|
||||
|
||||
static int cpu_states_init(void)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cpu_state_attr); i++) {
|
||||
int ret;
|
||||
ret = sysdev_class_create_file(&cpu_sysdev_class,
|
||||
cpu_state_attr[i]);
|
||||
if (!err)
|
||||
err = ret;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* register_cpu - Setup a sysfs device for a CPU.
|
||||
* @cpu - cpu->hotpluggable field set to 1 will generate a control file in
|
||||
|
|
@ -272,9 +251,6 @@ int __init cpu_dev_init(void)
|
|||
int err;
|
||||
|
||||
err = sysdev_class_register(&cpu_sysdev_class);
|
||||
if (!err)
|
||||
err = cpu_states_init();
|
||||
|
||||
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
|
||||
if (!err)
|
||||
err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
|
||||
|
|
@ -282,3 +258,16 @@ int __init cpu_dev_init(void)
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = {
|
||||
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
||||
&attr_probe,
|
||||
&attr_release,
|
||||
#endif
|
||||
&cpu_attrs[0].attr,
|
||||
&cpu_attrs[1].attr,
|
||||
&cpu_attrs[2].attr,
|
||||
&attr_kernel_max,
|
||||
&attr_offline,
|
||||
NULL
|
||||
};
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ static void driver_sysfs_remove(struct device *dev)
|
|||
* for before calling this. (It is ok to call with no other effort
|
||||
* from a driver's probe() method.)
|
||||
*
|
||||
* This function must be called with @dev->sem held.
|
||||
* This function must be called with the device lock held.
|
||||
*/
|
||||
int device_bind_driver(struct device *dev)
|
||||
{
|
||||
|
|
@ -190,8 +190,8 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe);
|
|||
* This function returns -ENODEV if the device is not registered,
|
||||
* 1 if the device is bound successfully and 0 otherwise.
|
||||
*
|
||||
* This function must be called with @dev->sem held. When called for a
|
||||
* USB interface, @dev->parent->sem must be held as well.
|
||||
* This function must be called with @dev lock held. When called for a
|
||||
* USB interface, @dev->parent lock must be held as well.
|
||||
*/
|
||||
int driver_probe_device(struct device_driver *drv, struct device *dev)
|
||||
{
|
||||
|
|
@ -233,13 +233,13 @@ static int __device_attach(struct device_driver *drv, void *data)
|
|||
* 0 if no matching driver was found;
|
||||
* -ENODEV if the device is not registered.
|
||||
*
|
||||
* When called for a USB interface, @dev->parent->sem must be held.
|
||||
* When called for a USB interface, @dev->parent lock must be held.
|
||||
*/
|
||||
int device_attach(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
down(&dev->sem);
|
||||
device_lock(dev);
|
||||
if (dev->driver) {
|
||||
ret = device_bind_driver(dev);
|
||||
if (ret == 0)
|
||||
|
|
@ -253,7 +253,7 @@ int device_attach(struct device *dev)
|
|||
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
|
||||
pm_runtime_put_sync(dev);
|
||||
}
|
||||
up(&dev->sem);
|
||||
device_unlock(dev);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_attach);
|
||||
|
|
@ -276,13 +276,13 @@ static int __driver_attach(struct device *dev, void *data)
|
|||
return 0;
|
||||
|
||||
if (dev->parent) /* Needed for USB */
|
||||
down(&dev->parent->sem);
|
||||
down(&dev->sem);
|
||||
device_lock(dev->parent);
|
||||
device_lock(dev);
|
||||
if (!dev->driver)
|
||||
driver_probe_device(drv, dev);
|
||||
up(&dev->sem);
|
||||
device_unlock(dev);
|
||||
if (dev->parent)
|
||||
up(&dev->parent->sem);
|
||||
device_unlock(dev->parent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -303,8 +303,8 @@ int driver_attach(struct device_driver *drv)
|
|||
EXPORT_SYMBOL_GPL(driver_attach);
|
||||
|
||||
/*
|
||||
* __device_release_driver() must be called with @dev->sem held.
|
||||
* When called for a USB interface, @dev->parent->sem must be held as well.
|
||||
* __device_release_driver() must be called with @dev lock held.
|
||||
* When called for a USB interface, @dev->parent lock must be held as well.
|
||||
*/
|
||||
static void __device_release_driver(struct device *dev)
|
||||
{
|
||||
|
|
@ -343,7 +343,7 @@ static void __device_release_driver(struct device *dev)
|
|||
* @dev: device.
|
||||
*
|
||||
* Manually detach device from driver.
|
||||
* When called for a USB interface, @dev->parent->sem must be held.
|
||||
* When called for a USB interface, @dev->parent lock must be held.
|
||||
*/
|
||||
void device_release_driver(struct device *dev)
|
||||
{
|
||||
|
|
@ -352,9 +352,9 @@ void device_release_driver(struct device *dev)
|
|||
* within their ->remove callback for the same device, they
|
||||
* will deadlock right here.
|
||||
*/
|
||||
down(&dev->sem);
|
||||
device_lock(dev);
|
||||
__device_release_driver(dev);
|
||||
up(&dev->sem);
|
||||
device_unlock(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_release_driver);
|
||||
|
||||
|
|
@ -381,13 +381,13 @@ void driver_detach(struct device_driver *drv)
|
|||
spin_unlock(&drv->p->klist_devices.k_lock);
|
||||
|
||||
if (dev->parent) /* Needed for USB */
|
||||
down(&dev->parent->sem);
|
||||
down(&dev->sem);
|
||||
device_lock(dev->parent);
|
||||
device_lock(dev);
|
||||
if (dev->driver == drv)
|
||||
__device_release_driver(dev);
|
||||
up(&dev->sem);
|
||||
device_unlock(dev);
|
||||
if (dev->parent)
|
||||
up(&dev->parent->sem);
|
||||
device_unlock(dev->parent);
|
||||
put_device(dev);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -301,6 +301,19 @@ int devtmpfs_delete_node(struct device *dev)
|
|||
if (dentry->d_inode) {
|
||||
err = vfs_getattr(nd.path.mnt, dentry, &stat);
|
||||
if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
|
||||
struct iattr newattrs;
|
||||
/*
|
||||
* before unlinking this node, reset permissions
|
||||
* of possible references like hardlinks
|
||||
*/
|
||||
newattrs.ia_uid = 0;
|
||||
newattrs.ia_gid = 0;
|
||||
newattrs.ia_mode = stat.mode & ~0777;
|
||||
newattrs.ia_valid =
|
||||
ATTR_UID|ATTR_GID|ATTR_MODE;
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
notify_change(dentry, &newattrs);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
err = vfs_unlink(nd.path.dentry->d_inode,
|
||||
dentry);
|
||||
if (!err || err == -ENOENT)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
#include <linux/kthread.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "base.h"
|
||||
|
||||
#define to_dev(obj) container_of(obj, struct device, kobj)
|
||||
|
||||
|
|
@ -69,7 +68,9 @@ fw_load_abort(struct firmware_priv *fw_priv)
|
|||
}
|
||||
|
||||
static ssize_t
|
||||
firmware_timeout_show(struct class *class, char *buf)
|
||||
firmware_timeout_show(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", loading_timeout);
|
||||
}
|
||||
|
|
@ -87,7 +88,9 @@ firmware_timeout_show(struct class *class, char *buf)
|
|||
* Note: zero means 'wait forever'.
|
||||
**/
|
||||
static ssize_t
|
||||
firmware_timeout_store(struct class *class, const char *buf, size_t count)
|
||||
firmware_timeout_store(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
loading_timeout = simple_strtol(buf, NULL, 10);
|
||||
if (loading_timeout < 0)
|
||||
|
|
@ -610,7 +613,7 @@ request_firmware_work_func(void *arg)
|
|||
}
|
||||
|
||||
/**
|
||||
* request_firmware_nowait: asynchronous version of request_firmware
|
||||
* request_firmware_nowait - asynchronous version of request_firmware
|
||||
* @module: module requesting the firmware
|
||||
* @uevent: sends uevent to copy the firmware image if this flag
|
||||
* is non-zero else the firmware copy must be done manually.
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ static int memory_uevent(struct kset *kset, struct kobject *obj, struct kobj_uev
|
|||
return retval;
|
||||
}
|
||||
|
||||
static struct kset_uevent_ops memory_uevent_ops = {
|
||||
static const struct kset_uevent_ops memory_uevent_ops = {
|
||||
.name = memory_uevent_name,
|
||||
.uevent = memory_uevent,
|
||||
};
|
||||
|
|
@ -309,17 +309,18 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
|
|||
* Block size attribute stuff
|
||||
*/
|
||||
static ssize_t
|
||||
print_block_size(struct class *class, char *buf)
|
||||
print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
|
||||
}
|
||||
|
||||
static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
|
||||
static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
|
||||
|
||||
static int block_size_init(void)
|
||||
{
|
||||
return sysfs_create_file(&memory_sysdev_class.kset.kobj,
|
||||
&class_attr_block_size_bytes.attr);
|
||||
&attr_block_size_bytes.attr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -330,7 +331,8 @@ static int block_size_init(void)
|
|||
*/
|
||||
#ifdef CONFIG_ARCH_MEMORY_PROBE
|
||||
static ssize_t
|
||||
memory_probe_store(struct class *class, const char *buf, size_t count)
|
||||
memory_probe_store(struct class *class, struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
u64 phys_addr;
|
||||
int nid;
|
||||
|
|
@ -367,7 +369,9 @@ static inline int memory_probe_init(void)
|
|||
|
||||
/* Soft offline a page */
|
||||
static ssize_t
|
||||
store_soft_offline_page(struct class *class, const char *buf, size_t count)
|
||||
store_soft_offline_page(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
u64 pfn;
|
||||
|
|
@ -384,7 +388,9 @@ store_soft_offline_page(struct class *class, const char *buf, size_t count)
|
|||
|
||||
/* Forcibly offline a page, including killing processes. */
|
||||
static ssize_t
|
||||
store_hard_offline_page(struct class *class, const char *buf, size_t count)
|
||||
store_hard_offline_page(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
u64 pfn;
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/swap.h>
|
||||
|
||||
static struct sysdev_class_attribute *node_state_attrs[];
|
||||
|
||||
static struct sysdev_class node_class = {
|
||||
.name = "node",
|
||||
.attrs = node_state_attrs,
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -544,76 +547,52 @@ static ssize_t print_nodes_state(enum node_states state, char *buf)
|
|||
return n;
|
||||
}
|
||||
|
||||
static ssize_t print_nodes_possible(struct sysdev_class *class, char *buf)
|
||||
{
|
||||
return print_nodes_state(N_POSSIBLE, buf);
|
||||
}
|
||||
|
||||
static ssize_t print_nodes_online(struct sysdev_class *class, char *buf)
|
||||
{
|
||||
return print_nodes_state(N_ONLINE, buf);
|
||||
}
|
||||
|
||||
static ssize_t print_nodes_has_normal_memory(struct sysdev_class *class,
|
||||
char *buf)
|
||||
{
|
||||
return print_nodes_state(N_NORMAL_MEMORY, buf);
|
||||
}
|
||||
|
||||
static ssize_t print_nodes_has_cpu(struct sysdev_class *class, char *buf)
|
||||
{
|
||||
return print_nodes_state(N_CPU, buf);
|
||||
}
|
||||
|
||||
static SYSDEV_CLASS_ATTR(possible, 0444, print_nodes_possible, NULL);
|
||||
static SYSDEV_CLASS_ATTR(online, 0444, print_nodes_online, NULL);
|
||||
static SYSDEV_CLASS_ATTR(has_normal_memory, 0444, print_nodes_has_normal_memory,
|
||||
NULL);
|
||||
static SYSDEV_CLASS_ATTR(has_cpu, 0444, print_nodes_has_cpu, NULL);
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
static ssize_t print_nodes_has_high_memory(struct sysdev_class *class,
|
||||
char *buf)
|
||||
{
|
||||
return print_nodes_state(N_HIGH_MEMORY, buf);
|
||||
}
|
||||
|
||||
static SYSDEV_CLASS_ATTR(has_high_memory, 0444, print_nodes_has_high_memory,
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
struct sysdev_class_attribute *node_state_attr[] = {
|
||||
&attr_possible,
|
||||
&attr_online,
|
||||
&attr_has_normal_memory,
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
&attr_has_high_memory,
|
||||
#endif
|
||||
&attr_has_cpu,
|
||||
struct node_attr {
|
||||
struct sysdev_class_attribute attr;
|
||||
enum node_states state;
|
||||
};
|
||||
|
||||
static int node_states_init(void)
|
||||
static ssize_t show_node_state(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr, char *buf)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
for (i = 0; i < NR_NODE_STATES; i++) {
|
||||
int ret;
|
||||
ret = sysdev_class_create_file(&node_class, node_state_attr[i]);
|
||||
if (!err)
|
||||
err = ret;
|
||||
}
|
||||
return err;
|
||||
struct node_attr *na = container_of(attr, struct node_attr, attr);
|
||||
return print_nodes_state(na->state, buf);
|
||||
}
|
||||
|
||||
#define _NODE_ATTR(name, state) \
|
||||
{ _SYSDEV_CLASS_ATTR(name, 0444, show_node_state, NULL), state }
|
||||
|
||||
static struct node_attr node_state_attr[] = {
|
||||
_NODE_ATTR(possible, N_POSSIBLE),
|
||||
_NODE_ATTR(online, N_ONLINE),
|
||||
_NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
|
||||
_NODE_ATTR(has_cpu, N_CPU),
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
_NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct sysdev_class_attribute *node_state_attrs[] = {
|
||||
&node_state_attr[0].attr,
|
||||
&node_state_attr[1].attr,
|
||||
&node_state_attr[2].attr,
|
||||
&node_state_attr[3].attr,
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
&node_state_attr[4].attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
#define NODE_CALLBACK_PRI 2 /* lower than SLAB */
|
||||
static int __init register_node_type(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES);
|
||||
|
||||
ret = sysdev_class_register(&node_class);
|
||||
if (!ret) {
|
||||
ret = node_states_init();
|
||||
hotplug_memory_notifier(node_memory_callback,
|
||||
NODE_CALLBACK_PRI);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ struct platform_object {
|
|||
};
|
||||
|
||||
/**
|
||||
* platform_device_put
|
||||
* platform_device_put - destroy a platform device
|
||||
* @pdev: platform device to free
|
||||
*
|
||||
* Free all memory associated with a platform device. This function must
|
||||
|
|
@ -152,7 +152,7 @@ static void platform_device_release(struct device *dev)
|
|||
}
|
||||
|
||||
/**
|
||||
* platform_device_alloc
|
||||
* platform_device_alloc - create a platform device
|
||||
* @name: base name of the device we're adding
|
||||
* @id: instance id
|
||||
*
|
||||
|
|
@ -177,7 +177,7 @@ struct platform_device *platform_device_alloc(const char *name, int id)
|
|||
EXPORT_SYMBOL_GPL(platform_device_alloc);
|
||||
|
||||
/**
|
||||
* platform_device_add_resources
|
||||
* platform_device_add_resources - add resources to a platform device
|
||||
* @pdev: platform device allocated by platform_device_alloc to add resources to
|
||||
* @res: set of resources that needs to be allocated for the device
|
||||
* @num: number of resources
|
||||
|
|
@ -202,7 +202,7 @@ int platform_device_add_resources(struct platform_device *pdev,
|
|||
EXPORT_SYMBOL_GPL(platform_device_add_resources);
|
||||
|
||||
/**
|
||||
* platform_device_add_data
|
||||
* platform_device_add_data - add platform-specific data to a platform device
|
||||
* @pdev: platform device allocated by platform_device_alloc to add resources to
|
||||
* @data: platform specific data for this platform device
|
||||
* @size: size of platform specific data
|
||||
|
|
@ -344,7 +344,7 @@ void platform_device_unregister(struct platform_device *pdev)
|
|||
EXPORT_SYMBOL_GPL(platform_device_unregister);
|
||||
|
||||
/**
|
||||
* platform_device_register_simple
|
||||
* platform_device_register_simple - add a platform-level device and its resources
|
||||
* @name: base name of the device we're adding
|
||||
* @id: instance id
|
||||
* @res: set of resources that needs to be allocated for the device
|
||||
|
|
@ -396,7 +396,7 @@ error:
|
|||
EXPORT_SYMBOL_GPL(platform_device_register_simple);
|
||||
|
||||
/**
|
||||
* platform_device_register_data
|
||||
* platform_device_register_data - add a platform-level device with platform-specific data
|
||||
* @parent: parent device for the device we're adding
|
||||
* @name: base name of the device we're adding
|
||||
* @id: instance id
|
||||
|
|
@ -473,7 +473,7 @@ static void platform_drv_shutdown(struct device *_dev)
|
|||
}
|
||||
|
||||
/**
|
||||
* platform_driver_register
|
||||
* platform_driver_register - register a driver for platform-level devices
|
||||
* @drv: platform driver structure
|
||||
*/
|
||||
int platform_driver_register(struct platform_driver *drv)
|
||||
|
|
@ -491,7 +491,7 @@ int platform_driver_register(struct platform_driver *drv)
|
|||
EXPORT_SYMBOL_GPL(platform_driver_register);
|
||||
|
||||
/**
|
||||
* platform_driver_unregister
|
||||
* platform_driver_unregister - unregister a driver for platform-level devices
|
||||
* @drv: platform driver structure
|
||||
*/
|
||||
void platform_driver_unregister(struct platform_driver *drv)
|
||||
|
|
@ -548,6 +548,64 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(platform_driver_probe);
|
||||
|
||||
/**
|
||||
* platform_create_bundle - register driver and create corresponding device
|
||||
* @driver: platform driver structure
|
||||
* @probe: the driver probe routine, probably from an __init section
|
||||
* @res: set of resources that needs to be allocated for the device
|
||||
* @n_res: number of resources
|
||||
* @data: platform specific data for this platform device
|
||||
* @size: size of platform specific data
|
||||
*
|
||||
* Use this in legacy-style modules that probe hardware directly and
|
||||
* register a single platform device and corresponding platform driver.
|
||||
*/
|
||||
struct platform_device * __init_or_module platform_create_bundle(
|
||||
struct platform_driver *driver,
|
||||
int (*probe)(struct platform_device *),
|
||||
struct resource *res, unsigned int n_res,
|
||||
const void *data, size_t size)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
int error;
|
||||
|
||||
pdev = platform_device_alloc(driver->driver.name, -1);
|
||||
if (!pdev) {
|
||||
error = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
error = platform_device_add_resources(pdev, res, n_res);
|
||||
if (error)
|
||||
goto err_pdev_put;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
error = platform_device_add_data(pdev, data, size);
|
||||
if (error)
|
||||
goto err_pdev_put;
|
||||
}
|
||||
|
||||
error = platform_device_add(pdev);
|
||||
if (error)
|
||||
goto err_pdev_put;
|
||||
|
||||
error = platform_driver_probe(driver, probe);
|
||||
if (error)
|
||||
goto err_pdev_del;
|
||||
|
||||
return pdev;
|
||||
|
||||
err_pdev_del:
|
||||
platform_device_del(pdev);
|
||||
err_pdev_put:
|
||||
platform_device_put(pdev);
|
||||
err_out:
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(platform_create_bundle);
|
||||
|
||||
/* modalias support enables more hands-off userspace setup:
|
||||
* (a) environment variable lets new-style hotplug events work once system is
|
||||
* fully running: "modprobe $MODALIAS"
|
||||
|
|
@ -578,7 +636,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||
}
|
||||
|
||||
static const struct platform_device_id *platform_match_id(
|
||||
struct platform_device_id *id,
|
||||
const struct platform_device_id *id,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
while (id->name[0]) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
obj-$(CONFIG_PM) += sysfs.o
|
||||
obj-$(CONFIG_PM_SLEEP) += main.o
|
||||
obj-$(CONFIG_PM_RUNTIME) += runtime.o
|
||||
obj-$(CONFIG_PM_OPS) += generic_ops.o
|
||||
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
|
||||
|
||||
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
|
||||
|
|
|
|||
233
drivers/base/power/generic_ops.c
Normal file
233
drivers/base/power/generic_ops.c
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* drivers/base/power/generic_ops.c - Generic PM callbacks for subsystems
|
||||
*
|
||||
* Copyright (c) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
|
||||
*
|
||||
* This file is released under the GPLv2.
|
||||
*/
|
||||
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
/**
|
||||
* pm_generic_runtime_idle - Generic runtime idle callback for subsystems.
|
||||
* @dev: Device to handle.
|
||||
*
|
||||
* If PM operations are defined for the @dev's driver and they include
|
||||
* ->runtime_idle(), execute it and return its error code, if nonzero.
|
||||
* Otherwise, execute pm_runtime_suspend() for the device and return 0.
|
||||
*/
|
||||
int pm_generic_runtime_idle(struct device *dev)
|
||||
{
|
||||
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||
|
||||
if (pm && pm->runtime_idle) {
|
||||
int ret = pm->runtime_idle(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_suspend(dev);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_generic_runtime_idle);
|
||||
|
||||
/**
|
||||
* pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems.
|
||||
* @dev: Device to suspend.
|
||||
*
|
||||
* If PM operations are defined for the @dev's driver and they include
|
||||
* ->runtime_suspend(), execute it and return its error code. Otherwise,
|
||||
* return -EINVAL.
|
||||
*/
|
||||
int pm_generic_runtime_suspend(struct device *dev)
|
||||
{
|
||||
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||
int ret;
|
||||
|
||||
ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_generic_runtime_suspend);
|
||||
|
||||
/**
|
||||
* pm_generic_runtime_resume - Generic runtime resume callback for subsystems.
|
||||
* @dev: Device to resume.
|
||||
*
|
||||
* If PM operations are defined for the @dev's driver and they include
|
||||
* ->runtime_resume(), execute it and return its error code. Otherwise,
|
||||
* return -EINVAL.
|
||||
*/
|
||||
int pm_generic_runtime_resume(struct device *dev)
|
||||
{
|
||||
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||
int ret;
|
||||
|
||||
ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : -EINVAL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_generic_runtime_resume);
|
||||
#endif /* CONFIG_PM_RUNTIME */
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/**
|
||||
* __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback.
|
||||
* @dev: Device to handle.
|
||||
* @event: PM transition of the system under way.
|
||||
*
|
||||
* If the device has not been suspended at run time, execute the
|
||||
* suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and
|
||||
* return its error code. Otherwise, return zero.
|
||||
*/
|
||||
static int __pm_generic_call(struct device *dev, int event)
|
||||
{
|
||||
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||
int (*callback)(struct device *);
|
||||
|
||||
if (!pm || pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
switch (event) {
|
||||
case PM_EVENT_SUSPEND:
|
||||
callback = pm->suspend;
|
||||
break;
|
||||
case PM_EVENT_FREEZE:
|
||||
callback = pm->freeze;
|
||||
break;
|
||||
case PM_EVENT_HIBERNATE:
|
||||
callback = pm->poweroff;
|
||||
break;
|
||||
case PM_EVENT_THAW:
|
||||
callback = pm->thaw;
|
||||
break;
|
||||
default:
|
||||
callback = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return callback ? callback(dev) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_generic_suspend - Generic suspend callback for subsystems.
|
||||
* @dev: Device to suspend.
|
||||
*/
|
||||
int pm_generic_suspend(struct device *dev)
|
||||
{
|
||||
return __pm_generic_call(dev, PM_EVENT_SUSPEND);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_generic_suspend);
|
||||
|
||||
/**
|
||||
* pm_generic_freeze - Generic freeze callback for subsystems.
|
||||
* @dev: Device to freeze.
|
||||
*/
|
||||
int pm_generic_freeze(struct device *dev)
|
||||
{
|
||||
return __pm_generic_call(dev, PM_EVENT_FREEZE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_generic_freeze);
|
||||
|
||||
/**
|
||||
* pm_generic_poweroff - Generic poweroff callback for subsystems.
|
||||
* @dev: Device to handle.
|
||||
*/
|
||||
int pm_generic_poweroff(struct device *dev)
|
||||
{
|
||||
return __pm_generic_call(dev, PM_EVENT_HIBERNATE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_generic_poweroff);
|
||||
|
||||
/**
|
||||
* pm_generic_thaw - Generic thaw callback for subsystems.
|
||||
* @dev: Device to thaw.
|
||||
*/
|
||||
int pm_generic_thaw(struct device *dev)
|
||||
{
|
||||
return __pm_generic_call(dev, PM_EVENT_THAW);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_generic_thaw);
|
||||
|
||||
/**
|
||||
* __pm_generic_resume - Generic resume/restore callback for subsystems.
|
||||
* @dev: Device to handle.
|
||||
* @event: PM transition of the system under way.
|
||||
*
|
||||
* Execute the resume/resotre callback provided by the @dev's driver, if
|
||||
* defined. If it returns 0, change the device's runtime PM status to 'active'.
|
||||
* Return the callback's error code.
|
||||
*/
|
||||
static int __pm_generic_resume(struct device *dev, int event)
|
||||
{
|
||||
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||
int (*callback)(struct device *);
|
||||
int ret;
|
||||
|
||||
if (!pm)
|
||||
return 0;
|
||||
|
||||
switch (event) {
|
||||
case PM_EVENT_RESUME:
|
||||
callback = pm->resume;
|
||||
break;
|
||||
case PM_EVENT_RESTORE:
|
||||
callback = pm->restore;
|
||||
break;
|
||||
default:
|
||||
callback = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!callback)
|
||||
return 0;
|
||||
|
||||
ret = callback(dev);
|
||||
if (!ret) {
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_generic_resume - Generic resume callback for subsystems.
|
||||
* @dev: Device to resume.
|
||||
*/
|
||||
int pm_generic_resume(struct device *dev)
|
||||
{
|
||||
return __pm_generic_resume(dev, PM_EVENT_RESUME);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_generic_resume);
|
||||
|
||||
/**
|
||||
* pm_generic_restore - Generic restore callback for subsystems.
|
||||
* @dev: Device to restore.
|
||||
*/
|
||||
int pm_generic_restore(struct device *dev)
|
||||
{
|
||||
return __pm_generic_resume(dev, PM_EVENT_RESTORE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_generic_restore);
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
struct dev_pm_ops generic_subsys_pm_ops = {
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.suspend = pm_generic_suspend,
|
||||
.resume = pm_generic_resume,
|
||||
.freeze = pm_generic_freeze,
|
||||
.thaw = pm_generic_thaw,
|
||||
.poweroff = pm_generic_poweroff,
|
||||
.restore = pm_generic_restore,
|
||||
#endif
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
.runtime_suspend = pm_generic_runtime_suspend,
|
||||
.runtime_resume = pm_generic_runtime_resume,
|
||||
.runtime_idle = pm_generic_runtime_idle,
|
||||
#endif
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(generic_subsys_pm_ops);
|
||||
|
|
@ -35,8 +35,8 @@
|
|||
* because children are guaranteed to be discovered after parents, and
|
||||
* are inserted at the back of the list on discovery.
|
||||
*
|
||||
* Since device_pm_add() may be called with a device semaphore held,
|
||||
* we must never try to acquire a device semaphore while holding
|
||||
* Since device_pm_add() may be called with a device lock held,
|
||||
* we must never try to acquire a device lock while holding
|
||||
* dpm_list_mutex.
|
||||
*/
|
||||
|
||||
|
|
@ -508,7 +508,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
|
|||
TRACE_RESUME(0);
|
||||
|
||||
dpm_wait(dev->parent, async);
|
||||
down(&dev->sem);
|
||||
device_lock(dev);
|
||||
|
||||
dev->power.status = DPM_RESUMING;
|
||||
|
||||
|
|
@ -543,7 +543,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
|
|||
}
|
||||
}
|
||||
End:
|
||||
up(&dev->sem);
|
||||
device_unlock(dev);
|
||||
complete_all(&dev->power.completion);
|
||||
|
||||
TRACE_RESUME(error);
|
||||
|
|
@ -629,7 +629,7 @@ static void dpm_resume(pm_message_t state)
|
|||
*/
|
||||
static void device_complete(struct device *dev, pm_message_t state)
|
||||
{
|
||||
down(&dev->sem);
|
||||
device_lock(dev);
|
||||
|
||||
if (dev->class && dev->class->pm && dev->class->pm->complete) {
|
||||
pm_dev_dbg(dev, state, "completing class ");
|
||||
|
|
@ -646,7 +646,7 @@ static void device_complete(struct device *dev, pm_message_t state)
|
|||
dev->bus->pm->complete(dev);
|
||||
}
|
||||
|
||||
up(&dev->sem);
|
||||
device_unlock(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -809,7 +809,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
|
|||
int error = 0;
|
||||
|
||||
dpm_wait_for_children(dev, async);
|
||||
down(&dev->sem);
|
||||
device_lock(dev);
|
||||
|
||||
if (async_error)
|
||||
goto End;
|
||||
|
|
@ -849,7 +849,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
|
|||
dev->power.status = DPM_OFF;
|
||||
|
||||
End:
|
||||
up(&dev->sem);
|
||||
device_unlock(dev);
|
||||
complete_all(&dev->power.completion);
|
||||
|
||||
return error;
|
||||
|
|
@ -938,7 +938,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
|
|||
{
|
||||
int error = 0;
|
||||
|
||||
down(&dev->sem);
|
||||
device_lock(dev);
|
||||
|
||||
if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) {
|
||||
pm_dev_dbg(dev, state, "preparing ");
|
||||
|
|
@ -962,7 +962,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
|
|||
suspend_report_result(dev->class->pm->prepare, error);
|
||||
}
|
||||
End:
|
||||
up(&dev->sem);
|
||||
device_unlock(dev);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ sysdev_store(struct kobject *kobj, struct attribute *attr,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static struct sysfs_ops sysfs_ops = {
|
||||
static const struct sysfs_ops sysfs_ops = {
|
||||
.show = sysdev_show,
|
||||
.store = sysdev_store,
|
||||
};
|
||||
|
|
@ -89,7 +89,7 @@ static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
|
|||
struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
|
||||
|
||||
if (class_attr->show)
|
||||
return class_attr->show(class, buffer);
|
||||
return class_attr->show(class, class_attr, buffer);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
|
@ -100,11 +100,11 @@ static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr,
|
|||
struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
|
||||
|
||||
if (class_attr->store)
|
||||
return class_attr->store(class, buffer, count);
|
||||
return class_attr->store(class, class_attr, buffer, count);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static struct sysfs_ops sysfs_class_ops = {
|
||||
static const struct sysfs_ops sysfs_class_ops = {
|
||||
.show = sysdev_class_show,
|
||||
.store = sysdev_class_store,
|
||||
};
|
||||
|
|
@ -145,13 +145,20 @@ int sysdev_class_register(struct sysdev_class *cls)
|
|||
if (retval)
|
||||
return retval;
|
||||
|
||||
return kset_register(&cls->kset);
|
||||
retval = kset_register(&cls->kset);
|
||||
if (!retval && cls->attrs)
|
||||
retval = sysfs_create_files(&cls->kset.kobj,
|
||||
(const struct attribute **)cls->attrs);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void sysdev_class_unregister(struct sysdev_class *cls)
|
||||
{
|
||||
pr_debug("Unregistering sysdev class '%s'\n",
|
||||
kobject_name(&cls->kset.kobj));
|
||||
if (cls->attrs)
|
||||
sysfs_remove_files(&cls->kset.kobj,
|
||||
(const struct attribute **)cls->attrs);
|
||||
kset_unregister(&cls->kset);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -476,7 +476,9 @@ static void class_osdblk_release(struct class *cls)
|
|||
kfree(cls);
|
||||
}
|
||||
|
||||
static ssize_t class_osdblk_list(struct class *c, char *data)
|
||||
static ssize_t class_osdblk_list(struct class *c,
|
||||
struct class_attribute *attr,
|
||||
char *data)
|
||||
{
|
||||
int n = 0;
|
||||
struct list_head *tmp;
|
||||
|
|
@ -500,7 +502,9 @@ static ssize_t class_osdblk_list(struct class *c, char *data)
|
|||
return n;
|
||||
}
|
||||
|
||||
static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count)
|
||||
static ssize_t class_osdblk_add(struct class *c,
|
||||
struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct osdblk_device *osdev;
|
||||
ssize_t rc;
|
||||
|
|
@ -592,7 +596,9 @@ err_out_mod:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t class_osdblk_remove(struct class *c, const char *buf,
|
||||
static ssize_t class_osdblk_remove(struct class *c,
|
||||
struct class_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct osdblk_device *osdev = NULL;
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ static ssize_t kobj_pkt_store(struct kobject *kobj,
|
|||
return len;
|
||||
}
|
||||
|
||||
static struct sysfs_ops kobj_pkt_ops = {
|
||||
static const struct sysfs_ops kobj_pkt_ops = {
|
||||
.show = kobj_pkt_show,
|
||||
.store = kobj_pkt_store
|
||||
};
|
||||
|
|
@ -337,7 +337,9 @@ static void class_pktcdvd_release(struct class *cls)
|
|||
{
|
||||
kfree(cls);
|
||||
}
|
||||
static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
|
||||
static ssize_t class_pktcdvd_show_map(struct class *c,
|
||||
struct class_attribute *attr,
|
||||
char *data)
|
||||
{
|
||||
int n = 0;
|
||||
int idx;
|
||||
|
|
@ -356,7 +358,9 @@ static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
|
|||
return n;
|
||||
}
|
||||
|
||||
static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
|
||||
static ssize_t class_pktcdvd_store_add(struct class *c,
|
||||
struct class_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
unsigned int major, minor;
|
||||
|
|
@ -376,7 +380,9 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf,
|
||||
static ssize_t class_pktcdvd_store_remove(struct class *c,
|
||||
struct class_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
unsigned int major, minor;
|
||||
|
|
|
|||
|
|
@ -1,775 +0,0 @@
|
|||
2001-08-11 Tim Waugh <[email protected]>
|
||||
|
||||
* serial.c (get_pci_port): Deal with awkward Titan cards.
|
||||
|
||||
1998-08-26 Theodore Ts'o <[email protected]>
|
||||
|
||||
* serial.c (rs_open): Correctly decrement the module in-use count
|
||||
on errors.
|
||||
|
||||
Thu Feb 19 14:24:08 1998 Theodore Ts'o <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* pty.c (pty_close): When closing a pty, make sure packet mode is
|
||||
cleared.
|
||||
|
||||
Sun May 26 09:33:52 1996 Theodore Ts'o <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* serial.c: (receive_char): Added counter to prevent infinite loop
|
||||
when a PCMCIA serial device is ejected.
|
||||
|
||||
Thu Dec 29 17:53:48 1994 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 <[email protected]>
|
||||
|
||||
* 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 ([email protected])
|
||||
* 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.)
|
||||
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
#include <asm/smp.h>
|
||||
#include "agp.h"
|
||||
|
||||
int intel_agp_enabled;
|
||||
EXPORT_SYMBOL(intel_agp_enabled);
|
||||
|
||||
/*
|
||||
* If we have Intel graphics, we're not going to have anything other than
|
||||
* an Intel IOMMU. So make the correct use of the PCI DMA API contingent
|
||||
|
|
@ -65,6 +68,10 @@
|
|||
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
|
||||
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
|
||||
#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
|
||||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100
|
||||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102
|
||||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104
|
||||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106
|
||||
|
||||
/* cover 915 and 945 variants */
|
||||
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
|
||||
|
|
@ -99,7 +106,9 @@
|
|||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB)
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
|
||||
|
||||
extern int agp_memory_reserved;
|
||||
|
||||
|
|
@ -148,6 +157,25 @@ extern int agp_memory_reserved;
|
|||
#define INTEL_I7505_AGPCTRL 0x70
|
||||
#define INTEL_I7505_MCHCFG 0x50
|
||||
|
||||
#define SNB_GMCH_CTRL 0x50
|
||||
#define SNB_GMCH_GMS_STOLEN_MASK 0xF8
|
||||
#define SNB_GMCH_GMS_STOLEN_32M (1 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_64M (2 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_96M (3 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_128M (4 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_160M (5 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_192M (6 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_224M (7 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_256M (8 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_288M (9 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
|
||||
|
||||
static const struct aper_size_info_fixed intel_i810_sizes[] =
|
||||
{
|
||||
{64, 16384, 4},
|
||||
|
|
@ -270,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;
|
||||
|
||||
|
|
@ -294,6 +322,13 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
|
|||
off_t pg_start, int mask_type)
|
||||
{
|
||||
int i, j;
|
||||
u32 cache_bits = 0;
|
||||
|
||||
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
|
||||
{
|
||||
cache_bits = I830_PTE_SYSTEM_CACHED;
|
||||
}
|
||||
|
||||
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
|
||||
writel(agp_bridge->driver->mask_memory(agp_bridge,
|
||||
|
|
@ -614,7 +649,7 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
|
|||
static void intel_i830_init_gtt_entries(void)
|
||||
{
|
||||
u16 gmch_ctrl;
|
||||
int gtt_entries;
|
||||
int gtt_entries = 0;
|
||||
u8 rdct;
|
||||
int local = 0;
|
||||
static const int ddt[4] = { 0, 16, 32, 64 };
|
||||
|
|
@ -706,6 +741,63 @@ static void intel_i830_init_gtt_entries(void)
|
|||
gtt_entries = 0;
|
||||
break;
|
||||
}
|
||||
} else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
|
||||
/*
|
||||
* SandyBridge has new memory control reg at 0x50.w
|
||||
*/
|
||||
u16 snb_gmch_ctl;
|
||||
pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
|
||||
switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) {
|
||||
case SNB_GMCH_GMS_STOLEN_32M:
|
||||
gtt_entries = MB(32) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_64M:
|
||||
gtt_entries = MB(64) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_96M:
|
||||
gtt_entries = MB(96) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_128M:
|
||||
gtt_entries = MB(128) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_160M:
|
||||
gtt_entries = MB(160) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_192M:
|
||||
gtt_entries = MB(192) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_224M:
|
||||
gtt_entries = MB(224) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_256M:
|
||||
gtt_entries = MB(256) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_288M:
|
||||
gtt_entries = MB(288) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_320M:
|
||||
gtt_entries = MB(320) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_352M:
|
||||
gtt_entries = MB(352) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_384M:
|
||||
gtt_entries = MB(384) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_416M:
|
||||
gtt_entries = MB(416) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_448M:
|
||||
gtt_entries = MB(448) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_480M:
|
||||
gtt_entries = MB(480) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_512M:
|
||||
gtt_entries = MB(512) - KB(size);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
|
||||
case I855_GMCH_GMS_STOLEN_1M:
|
||||
|
|
@ -1357,6 +1449,8 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
|
|||
case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
|
||||
case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
|
||||
case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
|
||||
case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
|
||||
case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
|
||||
*gtt_offset = *gtt_size = MB(2);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -2338,9 +2432,9 @@ static const struct intel_driver_description {
|
|||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "Pineview",
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "GMA3150",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "Pineview",
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "GMA3150",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0,
|
||||
"GM45", NULL, &intel_i965_driver },
|
||||
|
|
@ -2355,13 +2449,17 @@ static const struct intel_driver_description {
|
|||
{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
|
||||
"G41", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0,
|
||||
"Ironlake/D", NULL, &intel_i965_driver },
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
|
||||
"Ironlake/M", NULL, &intel_i965_driver },
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
|
||||
"Ironlake/MA", NULL, &intel_i965_driver },
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
|
||||
"Ironlake/MC2", NULL, &intel_i965_driver },
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, 0,
|
||||
"Sandybridge", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, 0,
|
||||
"Sandybridge", NULL, &intel_i965_driver },
|
||||
{ 0, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
@ -2371,7 +2469,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
|||
struct agp_bridge_data *bridge;
|
||||
u8 cap_ptr = 0;
|
||||
struct resource *r;
|
||||
int i;
|
||||
int i, err;
|
||||
|
||||
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
|
||||
|
||||
|
|
@ -2463,7 +2561,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
pci_set_drvdata(pdev, bridge);
|
||||
return agp_add_bridge(bridge);
|
||||
err = agp_add_bridge(bridge);
|
||||
if (!err)
|
||||
intel_agp_enabled = 1;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit agp_intel_remove(struct pci_dev *pdev)
|
||||
|
|
@ -2568,6 +2669,8 @@ static struct pci_device_id agp_intel_pci_table[] = {
|
|||
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -158,13 +158,11 @@ static unsigned int cy_isa_addresses[] = {
|
|||
|
||||
#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
|
||||
|
||||
#ifdef MODULE
|
||||
static long maddr[NR_CARDS];
|
||||
static int irq[NR_CARDS];
|
||||
|
||||
module_param_array(maddr, long, NULL, 0);
|
||||
module_param_array(irq, int, NULL, 0);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_ISA */
|
||||
|
||||
|
|
@ -598,12 +596,6 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
|
|||
save_car = readb(base_addr + (CyCAR << index));
|
||||
cy_writeb(base_addr + (CyCAR << index), save_xir);
|
||||
|
||||
/* validate the port# (as configured and open) */
|
||||
if (channel + chip * 4 >= cinfo->nports) {
|
||||
cy_writeb(base_addr + (CySRER << index),
|
||||
readb(base_addr + (CySRER << index)) & ~CyTxRdy);
|
||||
goto end;
|
||||
}
|
||||
info = &cinfo->ports[channel + chip * 4];
|
||||
tty = tty_port_tty_get(&info->port);
|
||||
if (tty == NULL) {
|
||||
|
|
@ -3316,13 +3308,10 @@ static int __init cy_detect_isa(void)
|
|||
unsigned short cy_isa_irq, nboard;
|
||||
void __iomem *cy_isa_address;
|
||||
unsigned short i, j, cy_isa_nchan;
|
||||
#ifdef MODULE
|
||||
int isparam = 0;
|
||||
#endif
|
||||
|
||||
nboard = 0;
|
||||
|
||||
#ifdef MODULE
|
||||
/* Check for module parameters */
|
||||
for (i = 0; i < NR_CARDS; i++) {
|
||||
if (maddr[i] || i) {
|
||||
|
|
@ -3332,7 +3321,6 @@ static int __init cy_detect_isa(void)
|
|||
if (!maddr[i])
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* scan the address table probing for Cyclom-Y/ISA boards */
|
||||
for (i = 0; i < NR_ISA_ADDRS; i++) {
|
||||
|
|
@ -3353,11 +3341,10 @@ static int __init cy_detect_isa(void)
|
|||
iounmap(cy_isa_address);
|
||||
continue;
|
||||
}
|
||||
#ifdef MODULE
|
||||
|
||||
if (isparam && i < NR_CARDS && irq[i])
|
||||
cy_isa_irq = irq[i];
|
||||
else
|
||||
#endif
|
||||
/* find out the board's irq by probing */
|
||||
cy_isa_irq = detect_isa_irq(cy_isa_address);
|
||||
if (cy_isa_irq == 0) {
|
||||
|
|
@ -4208,3 +4195,4 @@ module_exit(cy_cleanup_module);
|
|||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(CY_VERSION);
|
||||
MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);
|
||||
MODULE_FIRMWARE("cyzfirm.bin");
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ static void hvc_console_print(struct console *co, const char *b,
|
|||
return;
|
||||
|
||||
/* This console adapter was removed so it is not usable. */
|
||||
if (vtermnos[index] < 0)
|
||||
if (vtermnos[index] == -1)
|
||||
return;
|
||||
|
||||
while (count > 0 || i > 0) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
|
|||
*
|
||||
* This function allocates a new struct iucv_tty_buffer element and, optionally,
|
||||
* allocates an internal data buffer with the specified size @size.
|
||||
* The internal data buffer is always allocated with GFP_DMA which is
|
||||
* required for receiving and sending data with IUCV.
|
||||
* Note: The total message size arises from the internal buffer size and the
|
||||
* members of the iucv_tty_msg structure.
|
||||
* The function returns NULL if memory allocation has failed.
|
||||
|
|
@ -154,7 +156,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags)
|
|||
|
||||
if (size > 0) {
|
||||
bufp->msg.length = MSG_SIZE(size);
|
||||
bufp->mbuf = kmalloc(bufp->msg.length, flags);
|
||||
bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA);
|
||||
if (!bufp->mbuf) {
|
||||
mempool_free(bufp, hvc_iucv_mempool);
|
||||
return NULL;
|
||||
|
|
@ -237,7 +239,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv,
|
|||
if (!rb->mbuf) { /* message not yet received ... */
|
||||
/* allocate mem to store msg data; if no memory is available
|
||||
* then leave the buffer on the list and re-try later */
|
||||
rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC);
|
||||
rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA);
|
||||
if (!rb->mbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ static int DumpFifoBuffer( char __user *, int);
|
|||
|
||||
static void ip2_init_board(int, const struct firmware *);
|
||||
static unsigned short find_eisa_board(int);
|
||||
static int ip2_setup(char *str);
|
||||
|
||||
/***************/
|
||||
/* Static Data */
|
||||
|
|
@ -263,7 +264,7 @@ static int tracewrap;
|
|||
/* Macros */
|
||||
/**********/
|
||||
|
||||
#if defined(MODULE) && defined(IP2DEBUG_OPEN)
|
||||
#ifdef IP2DEBUG_OPEN
|
||||
#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
|
||||
tty->name,(pCh->flags), \
|
||||
tty->count,/*GET_USE_COUNT(module)*/0,s)
|
||||
|
|
@ -285,7 +286,10 @@ MODULE_AUTHOR("Doug McNash");
|
|||
MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define MAX_CMD_STR 50
|
||||
|
||||
static int poll_only;
|
||||
static char cmd[MAX_CMD_STR];
|
||||
|
||||
static int Eisa_irq;
|
||||
static int Eisa_slot;
|
||||
|
|
@ -309,6 +313,8 @@ module_param_array(io, int, NULL, 0);
|
|||
MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
|
||||
module_param(poll_only, bool, 0);
|
||||
MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
|
||||
module_param_string(ip2, cmd, MAX_CMD_STR, 0);
|
||||
MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='");
|
||||
|
||||
/* for sysfs class support */
|
||||
static struct class *ip2_class;
|
||||
|
|
@ -487,7 +493,6 @@ static const struct firmware *ip2_request_firmware(void)
|
|||
return fw;
|
||||
}
|
||||
|
||||
#ifndef MODULE
|
||||
/******************************************************************************
|
||||
* ip2_setup:
|
||||
* str: kernel command line string
|
||||
|
|
@ -531,7 +536,6 @@ static int __init ip2_setup(char *str)
|
|||
return 1;
|
||||
}
|
||||
__setup("ip2=", ip2_setup);
|
||||
#endif /* !MODULE */
|
||||
|
||||
static int __init ip2_loadmain(void)
|
||||
{
|
||||
|
|
@ -539,14 +543,20 @@ static int __init ip2_loadmain(void)
|
|||
int err = 0;
|
||||
i2eBordStrPtr pB = NULL;
|
||||
int rc = -1;
|
||||
struct pci_dev *pdev = NULL;
|
||||
const struct firmware *fw = NULL;
|
||||
char *str;
|
||||
|
||||
str = cmd;
|
||||
|
||||
if (poll_only) {
|
||||
/* Hard lock the interrupts to zero */
|
||||
irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
|
||||
}
|
||||
|
||||
/* Check module parameter with 'ip2=' has been passed or not */
|
||||
if (!poll_only && (!strncmp(str, "ip2=", 4)))
|
||||
ip2_setup(str);
|
||||
|
||||
ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
|
||||
|
||||
/* process command line arguments to modprobe or
|
||||
|
|
@ -612,6 +622,7 @@ static int __init ip2_loadmain(void)
|
|||
case PCI:
|
||||
#ifdef CONFIG_PCI
|
||||
{
|
||||
struct pci_dev *pdev = NULL;
|
||||
u32 addr;
|
||||
int status;
|
||||
|
||||
|
|
@ -626,7 +637,7 @@ static int __init ip2_loadmain(void)
|
|||
|
||||
if (pci_enable_device(pdev)) {
|
||||
dev_err(&pdev->dev, "can't enable device\n");
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
ip2config.type[i] = PCI;
|
||||
ip2config.pci_dev[i] = pci_dev_get(pdev);
|
||||
|
|
@ -638,6 +649,8 @@ static int __init ip2_loadmain(void)
|
|||
dev_err(&pdev->dev, "I/O address error\n");
|
||||
|
||||
ip2config.irq[i] = pdev->irq;
|
||||
out:
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
#else
|
||||
printk(KERN_ERR "IP2: PCI card specified but PCI "
|
||||
|
|
@ -656,7 +669,6 @@ static int __init ip2_loadmain(void)
|
|||
break;
|
||||
} /* switch */
|
||||
} /* for */
|
||||
pci_dev_put(pdev);
|
||||
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i) {
|
||||
if (ip2config.addr[i]) {
|
||||
|
|
@ -3197,3 +3209,5 @@ static struct pci_device_id ip2main_pci_tbl[] __devinitdata = {
|
|||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl);
|
||||
|
||||
MODULE_FIRMWARE("intelliport2.bin");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@
|
|||
* 64-bit verification
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -140,7 +142,6 @@
|
|||
#define InterruptTheCard(base) outw(0, (base) + 0xc)
|
||||
#define ClearInterrupt(base) inw((base) + 0x0a)
|
||||
|
||||
#define pr_dbg(str...) pr_debug("ISICOM: " str)
|
||||
#ifdef DEBUG
|
||||
#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
|
||||
#else
|
||||
|
|
@ -249,8 +250,7 @@ static int lock_card(struct isi_board *card)
|
|||
spin_unlock_irqrestore(&card->card_lock, card->flags);
|
||||
msleep(10);
|
||||
}
|
||||
printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
|
||||
card->base);
|
||||
pr_warning("Failed to lock Card (0x%lx)\n", card->base);
|
||||
|
||||
return 0; /* Failed to acquire the card! */
|
||||
}
|
||||
|
|
@ -379,13 +379,13 @@ static inline int __isicom_paranoia_check(struct isi_port const *port,
|
|||
char *name, const char *routine)
|
||||
{
|
||||
if (!port) {
|
||||
printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for "
|
||||
"dev %s in %s.\n", name, routine);
|
||||
pr_warning("Warning: bad isicom magic for dev %s in %s.\n",
|
||||
name, routine);
|
||||
return 1;
|
||||
}
|
||||
if (port->magic != ISICOM_MAGIC) {
|
||||
printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for "
|
||||
"dev %s in %s.\n", name, routine);
|
||||
pr_warning("Warning: NULL isicom port for dev %s in %s.\n",
|
||||
name, routine);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -450,8 +450,8 @@ static void isicom_tx(unsigned long _data)
|
|||
if (!(inw(base + 0x02) & (1 << port->channel)))
|
||||
continue;
|
||||
|
||||
pr_dbg("txing %d bytes, port%d.\n", txcount,
|
||||
port->channel + 1);
|
||||
pr_debug("txing %d bytes, port%d.\n",
|
||||
txcount, port->channel + 1);
|
||||
outw((port->channel << isi_card[card].shift_count) | txcount,
|
||||
base);
|
||||
residue = NO;
|
||||
|
|
@ -547,8 +547,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
|||
byte_count = header & 0xff;
|
||||
|
||||
if (channel + 1 > card->port_count) {
|
||||
printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
|
||||
"%d(channel) > port_count.\n", base, channel+1);
|
||||
pr_warning("%s(0x%lx): %d(channel) > port_count.\n",
|
||||
__func__, base, channel+1);
|
||||
outw(0x0000, base+0x04); /* enable interrupts */
|
||||
spin_unlock(&card->card_lock);
|
||||
return IRQ_HANDLED;
|
||||
|
|
@ -582,14 +582,15 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
|||
if (port->status & ISI_DCD) {
|
||||
if (!(header & ISI_DCD)) {
|
||||
/* Carrier has been lost */
|
||||
pr_dbg("interrupt: DCD->low.\n"
|
||||
);
|
||||
pr_debug("%s: DCD->low.\n",
|
||||
__func__);
|
||||
port->status &= ~ISI_DCD;
|
||||
tty_hangup(tty);
|
||||
}
|
||||
} else if (header & ISI_DCD) {
|
||||
/* Carrier has been detected */
|
||||
pr_dbg("interrupt: DCD->high.\n");
|
||||
pr_debug("%s: DCD->high.\n",
|
||||
__func__);
|
||||
port->status |= ISI_DCD;
|
||||
wake_up_interruptible(&port->port.open_wait);
|
||||
}
|
||||
|
|
@ -641,17 +642,19 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
|||
break;
|
||||
|
||||
case 2: /* Statistics */
|
||||
pr_dbg("isicom_interrupt: stats!!!.\n");
|
||||
pr_debug("%s: stats!!!\n", __func__);
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_dbg("Intr: Unknown code in status packet.\n");
|
||||
pr_debug("%s: Unknown code in status packet.\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
} else { /* Data Packet */
|
||||
|
||||
count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
|
||||
pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count);
|
||||
pr_debug("%s: Can rx %d of %d bytes.\n",
|
||||
__func__, count, byte_count);
|
||||
word_count = count >> 1;
|
||||
insw(base, rp, word_count);
|
||||
byte_count -= (word_count << 1);
|
||||
|
|
@ -661,8 +664,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
|||
byte_count -= 2;
|
||||
}
|
||||
if (byte_count > 0) {
|
||||
pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
|
||||
"bytes...\n", base, channel + 1);
|
||||
pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n",
|
||||
__func__, base, channel + 1);
|
||||
/* drain out unread xtra data */
|
||||
while (byte_count > 0) {
|
||||
inw(base);
|
||||
|
|
@ -888,8 +891,8 @@ static void isicom_shutdown_port(struct isi_port *port)
|
|||
struct isi_board *card = port->card;
|
||||
|
||||
if (--card->count < 0) {
|
||||
pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
|
||||
card->base, card->count);
|
||||
pr_debug("%s: bad board(0x%lx) count %d.\n",
|
||||
__func__, card->base, card->count);
|
||||
card->count = 0;
|
||||
}
|
||||
/* last port was closed, shutdown that board too */
|
||||
|
|
@ -1681,13 +1684,13 @@ static int __init isicom_init(void)
|
|||
|
||||
retval = tty_register_driver(isicom_normal);
|
||||
if (retval) {
|
||||
pr_dbg("Couldn't register the dialin driver\n");
|
||||
pr_debug("Couldn't register the dialin driver\n");
|
||||
goto err_puttty;
|
||||
}
|
||||
|
||||
retval = pci_register_driver(&isicom_driver);
|
||||
if (retval < 0) {
|
||||
printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
|
||||
pr_err("Unable to register pci driver.\n");
|
||||
goto err_unrtty;
|
||||
}
|
||||
|
||||
|
|
@ -1717,3 +1720,8 @@ module_exit(isicom_exit);
|
|||
MODULE_AUTHOR("MultiTech");
|
||||
MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("isi608.bin");
|
||||
MODULE_FIRMWARE("isi608em.bin");
|
||||
MODULE_FIRMWARE("isi616em.bin");
|
||||
MODULE_FIRMWARE("isi4608.bin");
|
||||
MODULE_FIRMWARE("isi4616.bin");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -164,24 +164,25 @@ static unsigned int moxaFuncTout = HZ / 2;
|
|||
static unsigned int moxaLowWaterChk;
|
||||
static DEFINE_MUTEX(moxa_openlock);
|
||||
static DEFINE_SPINLOCK(moxa_lock);
|
||||
/* Variables for insmod */
|
||||
#ifdef MODULE
|
||||
|
||||
static unsigned long baseaddr[MAX_BOARDS];
|
||||
static unsigned int type[MAX_BOARDS];
|
||||
static unsigned int numports[MAX_BOARDS];
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("William Chen");
|
||||
MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
#ifdef MODULE
|
||||
MODULE_FIRMWARE("c218tunx.cod");
|
||||
MODULE_FIRMWARE("cp204unx.cod");
|
||||
MODULE_FIRMWARE("c320tunx.cod");
|
||||
|
||||
module_param_array(type, uint, NULL, 0);
|
||||
MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
|
||||
module_param_array(baseaddr, ulong, NULL, 0);
|
||||
MODULE_PARM_DESC(baseaddr, "base address");
|
||||
module_param_array(numports, uint, NULL, 0);
|
||||
MODULE_PARM_DESC(numports, "numports (ignored for C218)");
|
||||
#endif
|
||||
|
||||
module_param(ttymajor, int, 0);
|
||||
|
||||
/*
|
||||
|
|
@ -1024,6 +1025,8 @@ static int __init moxa_init(void)
|
|||
{
|
||||
unsigned int isabrds = 0;
|
||||
int retval = 0;
|
||||
struct moxa_board_conf *brd = moxa_boards;
|
||||
unsigned int i;
|
||||
|
||||
printk(KERN_INFO "MOXA Intellio family driver version %s\n",
|
||||
MOXA_VERSION);
|
||||
|
|
@ -1051,10 +1054,7 @@ static int __init moxa_init(void)
|
|||
}
|
||||
|
||||
/* Find the boards defined from module args. */
|
||||
#ifdef MODULE
|
||||
{
|
||||
struct moxa_board_conf *brd = moxa_boards;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < MAX_BOARDS; i++) {
|
||||
if (!baseaddr[i])
|
||||
break;
|
||||
|
|
@ -1087,8 +1087,6 @@ static int __init moxa_init(void)
|
|||
isabrds++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
retval = pci_register_driver(&moxa_pci_driver);
|
||||
|
|
|
|||
|
|
@ -895,8 +895,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
|
|||
if (inb(info->ioaddr + UART_LSR) == 0xff) {
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
if (capable(CAP_SYS_ADMIN)) {
|
||||
if (tty)
|
||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
||||
return 0;
|
||||
} else
|
||||
return -ENODEV;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -136,10 +136,6 @@ static int debug;
|
|||
#define RECEIVE_BUF_MAX 4
|
||||
|
||||
|
||||
/* Define all types of vendors and devices to support */
|
||||
#define VENDOR1 0x1931 /* Vendor Option */
|
||||
#define DEVICE1 0x000c /* HSDPA card */
|
||||
|
||||
#define R_IIR 0x0000 /* Interrupt Identity Register */
|
||||
#define R_FCR 0x0000 /* Flow Control Register */
|
||||
#define R_IER 0x0004 /* Interrupt Enable Register */
|
||||
|
|
@ -371,6 +367,8 @@ struct port {
|
|||
struct mutex tty_sem;
|
||||
wait_queue_head_t tty_wait;
|
||||
struct async_icount tty_icount;
|
||||
|
||||
struct nozomi *dc;
|
||||
};
|
||||
|
||||
/* Private data one for each card in the system */
|
||||
|
|
@ -405,7 +403,7 @@ struct buffer {
|
|||
|
||||
/* Global variables */
|
||||
static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
|
||||
{PCI_DEVICE(VENDOR1, DEVICE1)},
|
||||
{PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
@ -414,6 +412,8 @@ MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
|
|||
static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
|
||||
static struct tty_driver *ntty_driver;
|
||||
|
||||
static const struct tty_port_operations noz_tty_port_ops;
|
||||
|
||||
/*
|
||||
* find card by tty_index
|
||||
*/
|
||||
|
|
@ -853,8 +853,6 @@ static int receive_data(enum port_type index, struct nozomi *dc)
|
|||
goto put;
|
||||
}
|
||||
|
||||
tty_buffer_request_room(tty, size);
|
||||
|
||||
while (size > 0) {
|
||||
read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX);
|
||||
|
||||
|
|
@ -1473,9 +1471,11 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
|
|||
|
||||
for (i = 0; i < MAX_PORT; i++) {
|
||||
struct device *tty_dev;
|
||||
|
||||
mutex_init(&dc->port[i].tty_sem);
|
||||
tty_port_init(&dc->port[i].port);
|
||||
struct port *port = &dc->port[i];
|
||||
port->dc = dc;
|
||||
mutex_init(&port->tty_sem);
|
||||
tty_port_init(&port->port);
|
||||
port->port.ops = &noz_tty_port_ops;
|
||||
tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
|
||||
&pdev->dev);
|
||||
|
||||
|
|
@ -1600,67 +1600,74 @@ static void set_dtr(const struct tty_struct *tty, int dtr)
|
|||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Called when the userspace process opens the tty, /dev/noz*. */
|
||||
static int ntty_open(struct tty_struct *tty, struct file *file)
|
||||
static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||
{
|
||||
struct port *port = get_port_by_tty(tty);
|
||||
struct nozomi *dc = get_dc_by_tty(tty);
|
||||
unsigned long flags;
|
||||
|
||||
int ret;
|
||||
if (!port || !dc || dc->state != NOZOMI_STATE_READY)
|
||||
return -ENODEV;
|
||||
|
||||
if (mutex_lock_interruptible(&port->tty_sem))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
port->port.count++;
|
||||
dc->open_ttys++;
|
||||
|
||||
/* Enable interrupt downlink for channel */
|
||||
if (port->port.count == 1) {
|
||||
tty->driver_data = port;
|
||||
tty_port_tty_set(&port->port, tty);
|
||||
DBG1("open: %d", port->token_dl);
|
||||
spin_lock_irqsave(&dc->spin_mutex, flags);
|
||||
dc->last_ier = dc->last_ier | port->token_dl;
|
||||
writew(dc->last_ier, dc->reg_ier);
|
||||
spin_unlock_irqrestore(&dc->spin_mutex, flags);
|
||||
ret = tty_init_termios(tty);
|
||||
if (ret == 0) {
|
||||
tty_driver_kref_get(driver);
|
||||
driver->ttys[tty->index] = tty;
|
||||
}
|
||||
mutex_unlock(&port->tty_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ntty_cleanup(struct tty_struct *tty)
|
||||
{
|
||||
tty->driver_data = NULL;
|
||||
}
|
||||
|
||||
static int ntty_activate(struct tty_port *tport, struct tty_struct *tty)
|
||||
{
|
||||
struct port *port = container_of(tport, struct port, port);
|
||||
struct nozomi *dc = port->dc;
|
||||
unsigned long flags;
|
||||
|
||||
DBG1("open: %d", port->token_dl);
|
||||
spin_lock_irqsave(&dc->spin_mutex, flags);
|
||||
dc->last_ier = dc->last_ier | port->token_dl;
|
||||
writew(dc->last_ier, dc->reg_ier);
|
||||
dc->open_ttys++;
|
||||
spin_unlock_irqrestore(&dc->spin_mutex, flags);
|
||||
printk("noz: activated %d: %p\n", tty->index, tport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called when the userspace process close the tty, /dev/noz*. Also
|
||||
called immediately if ntty_open fails in which case tty->driver_data
|
||||
will be NULL an we exit by the first return */
|
||||
|
||||
static void ntty_close(struct tty_struct *tty, struct file *file)
|
||||
static int ntty_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
struct nozomi *dc = get_dc_by_tty(tty);
|
||||
struct port *nport = tty->driver_data;
|
||||
struct tty_port *port = &nport->port;
|
||||
struct port *port = get_port_by_tty(tty);
|
||||
return tty_port_open(&port->port, tty, filp);
|
||||
}
|
||||
|
||||
static void ntty_shutdown(struct tty_port *tport)
|
||||
{
|
||||
struct port *port = container_of(tport, struct port, port);
|
||||
struct nozomi *dc = port->dc;
|
||||
unsigned long flags;
|
||||
|
||||
if (!dc || !nport)
|
||||
return;
|
||||
|
||||
/* Users cannot interrupt a close */
|
||||
mutex_lock(&nport->tty_sem);
|
||||
|
||||
WARN_ON(!port->count);
|
||||
|
||||
DBG1("close: %d", port->token_dl);
|
||||
spin_lock_irqsave(&dc->spin_mutex, flags);
|
||||
dc->last_ier &= ~(port->token_dl);
|
||||
writew(dc->last_ier, dc->reg_ier);
|
||||
dc->open_ttys--;
|
||||
port->count--;
|
||||
spin_unlock_irqrestore(&dc->spin_mutex, flags);
|
||||
printk("noz: shutdown %p\n", tport);
|
||||
}
|
||||
|
||||
if (port->count == 0) {
|
||||
DBG1("close: %d", nport->token_dl);
|
||||
tty_port_tty_set(port, NULL);
|
||||
spin_lock_irqsave(&dc->spin_mutex, flags);
|
||||
dc->last_ier &= ~(nport->token_dl);
|
||||
writew(dc->last_ier, dc->reg_ier);
|
||||
spin_unlock_irqrestore(&dc->spin_mutex, flags);
|
||||
}
|
||||
mutex_unlock(&nport->tty_sem);
|
||||
static void ntty_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
struct port *port = tty->driver_data;
|
||||
if (port)
|
||||
tty_port_close(&port->port, tty, filp);
|
||||
}
|
||||
|
||||
static void ntty_hangup(struct tty_struct *tty)
|
||||
{
|
||||
struct port *port = tty->driver_data;
|
||||
tty_port_hangup(&port->port);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1680,15 +1687,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
|
|||
if (!dc || !port)
|
||||
return -ENODEV;
|
||||
|
||||
if (unlikely(!mutex_trylock(&port->tty_sem))) {
|
||||
/*
|
||||
* must test lock as tty layer wraps calls
|
||||
* to this function with BKL
|
||||
*/
|
||||
dev_err(&dc->pdev->dev, "Would have deadlocked - "
|
||||
"return EAGAIN\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
mutex_lock(&port->tty_sem);
|
||||
|
||||
if (unlikely(!port->port.count)) {
|
||||
DBG1(" ");
|
||||
|
|
@ -1728,25 +1727,23 @@ exit:
|
|||
* This method is called by the upper tty layer.
|
||||
* #according to sources N_TTY.c it expects a value >= 0 and
|
||||
* does not check for negative values.
|
||||
*
|
||||
* If the port is unplugged report lots of room and let the bits
|
||||
* dribble away so we don't block anything.
|
||||
*/
|
||||
static int ntty_write_room(struct tty_struct *tty)
|
||||
{
|
||||
struct port *port = tty->driver_data;
|
||||
int room = 0;
|
||||
int room = 4096;
|
||||
const struct nozomi *dc = get_dc_by_tty(tty);
|
||||
|
||||
if (!dc || !port)
|
||||
return 0;
|
||||
if (!mutex_trylock(&port->tty_sem))
|
||||
return 0;
|
||||
|
||||
if (!port->port.count)
|
||||
goto exit;
|
||||
|
||||
room = port->fifo_ul.size - kfifo_len(&port->fifo_ul);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&port->tty_sem);
|
||||
if (dc) {
|
||||
mutex_lock(&port->tty_sem);
|
||||
if (port->port.count)
|
||||
room = port->fifo_ul.size -
|
||||
kfifo_len(&port->fifo_ul);
|
||||
mutex_unlock(&port->tty_sem);
|
||||
}
|
||||
return room;
|
||||
}
|
||||
|
||||
|
|
@ -1906,10 +1903,16 @@ exit_in_buffer:
|
|||
return rval;
|
||||
}
|
||||
|
||||
static const struct tty_port_operations noz_tty_port_ops = {
|
||||
.activate = ntty_activate,
|
||||
.shutdown = ntty_shutdown,
|
||||
};
|
||||
|
||||
static const struct tty_operations tty_ops = {
|
||||
.ioctl = ntty_ioctl,
|
||||
.open = ntty_open,
|
||||
.close = ntty_close,
|
||||
.hangup = ntty_hangup,
|
||||
.write = ntty_write,
|
||||
.write_room = ntty_write_room,
|
||||
.unthrottle = ntty_unthrottle,
|
||||
|
|
@ -1917,6 +1920,8 @@ static const struct tty_operations tty_ops = {
|
|||
.chars_in_buffer = ntty_chars_in_buffer,
|
||||
.tiocmget = ntty_tiocmget,
|
||||
.tiocmset = ntty_tiocmset,
|
||||
.install = ntty_install,
|
||||
.cleanup = ntty_cleanup,
|
||||
};
|
||||
|
||||
/* Module initialization */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -658,8 +658,7 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
|
|||
info->mon.char_max = char_count;
|
||||
info->mon.char_last = char_count;
|
||||
#endif
|
||||
len = tty_buffer_request_room(tty, char_count);
|
||||
while (len--) {
|
||||
while (char_count--) {
|
||||
data = base_addr[CyRDR];
|
||||
tty_insert_flip_char(tty, data, TTY_NORMAL);
|
||||
#ifdef CYCLOM_16Y_HACK
|
||||
|
|
@ -1990,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--) {
|
||||
|
|
|
|||
|
|
@ -646,8 +646,6 @@ static void sx_receive(struct specialix_board *bp)
|
|||
dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
|
||||
port->hits[count > 8 ? 9 : count]++;
|
||||
|
||||
tty_buffer_request_room(tty, count);
|
||||
|
||||
while (count--)
|
||||
tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
|
||||
tty_flip_buffer_push(tty);
|
||||
|
|
|
|||
|
|
@ -2031,7 +2031,7 @@ static int mgsl_put_char(struct tty_struct *tty, unsigned char ch)
|
|||
if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char"))
|
||||
return 0;
|
||||
|
||||
if (!tty || !info->xmit_buf)
|
||||
if (!info->xmit_buf)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&info->irq_spinlock, flags);
|
||||
|
|
@ -2121,7 +2121,7 @@ static int mgsl_write(struct tty_struct * tty,
|
|||
if (mgsl_paranoia_check(info, tty->name, "mgsl_write"))
|
||||
goto cleanup;
|
||||
|
||||
if (!tty || !info->xmit_buf)
|
||||
if (!info->xmit_buf)
|
||||
goto cleanup;
|
||||
|
||||
if ( info->params.mode == MGSL_MODE_HDLC ||
|
||||
|
|
|
|||
|
|
@ -468,7 +468,7 @@ static unsigned int free_tbuf_count(struct slgt_info *info);
|
|||
static unsigned int tbuf_bytes(struct slgt_info *info);
|
||||
static void reset_tbufs(struct slgt_info *info);
|
||||
static void tdma_reset(struct slgt_info *info);
|
||||
static void tx_load(struct slgt_info *info, const char *buf, unsigned int count);
|
||||
static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count);
|
||||
|
||||
static void get_signals(struct slgt_info *info);
|
||||
static void set_signals(struct slgt_info *info);
|
||||
|
|
@ -813,59 +813,32 @@ static int write(struct tty_struct *tty,
|
|||
int ret = 0;
|
||||
struct slgt_info *info = tty->driver_data;
|
||||
unsigned long flags;
|
||||
unsigned int bufs_needed;
|
||||
|
||||
if (sanity_check(info, tty->name, "write"))
|
||||
goto cleanup;
|
||||
return -EIO;
|
||||
|
||||
DBGINFO(("%s write count=%d\n", info->device_name, count));
|
||||
|
||||
if (!info->tx_buf)
|
||||
goto cleanup;
|
||||
if (!info->tx_buf || (count > info->max_frame_size))
|
||||
return -EIO;
|
||||
|
||||
if (count > info->max_frame_size) {
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
if (!count || tty->stopped || tty->hw_stopped)
|
||||
return 0;
|
||||
|
||||
if (!count)
|
||||
goto cleanup;
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
|
||||
if (!info->tx_active && info->tx_count) {
|
||||
if (info->tx_count) {
|
||||
/* send accumulated data from send_char() */
|
||||
tx_load(info, info->tx_buf, info->tx_count);
|
||||
goto start;
|
||||
if (!tx_load(info, info->tx_buf, info->tx_count))
|
||||
goto cleanup;
|
||||
info->tx_count = 0;
|
||||
}
|
||||
bufs_needed = (count/DMABUFSIZE);
|
||||
if (count % DMABUFSIZE)
|
||||
++bufs_needed;
|
||||
if (bufs_needed > free_tbuf_count(info))
|
||||
goto cleanup;
|
||||
|
||||
ret = info->tx_count = count;
|
||||
tx_load(info, buf, count);
|
||||
goto start;
|
||||
|
||||
start:
|
||||
if (info->tx_count && !tty->stopped && !tty->hw_stopped) {
|
||||
spin_lock_irqsave(&info->lock,flags);
|
||||
if (!info->tx_active)
|
||||
tx_start(info);
|
||||
else if (!(rd_reg32(info, TDCSR) & BIT0)) {
|
||||
/* transmit still active but transmit DMA stopped */
|
||||
unsigned int i = info->tbuf_current;
|
||||
if (!i)
|
||||
i = info->tbuf_count;
|
||||
i--;
|
||||
/* if DMA buf unsent must try later after tx idle */
|
||||
if (desc_count(info->tbufs[i]))
|
||||
ret = 0;
|
||||
}
|
||||
if (ret > 0)
|
||||
update_tx_timer(info);
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
}
|
||||
if (tx_load(info, buf, count))
|
||||
ret = count;
|
||||
|
||||
cleanup:
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
DBGINFO(("%s write rc=%d\n", info->device_name, ret));
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -882,7 +855,7 @@ static int put_char(struct tty_struct *tty, unsigned char ch)
|
|||
if (!info->tx_buf)
|
||||
return 0;
|
||||
spin_lock_irqsave(&info->lock,flags);
|
||||
if (!info->tx_active && (info->tx_count < info->max_frame_size)) {
|
||||
if (info->tx_count < info->max_frame_size) {
|
||||
info->tx_buf[info->tx_count++] = ch;
|
||||
ret = 1;
|
||||
}
|
||||
|
|
@ -981,10 +954,8 @@ static void flush_chars(struct tty_struct *tty)
|
|||
DBGINFO(("%s flush_chars start transmit\n", info->device_name));
|
||||
|
||||
spin_lock_irqsave(&info->lock,flags);
|
||||
if (!info->tx_active && info->tx_count) {
|
||||
tx_load(info, info->tx_buf,info->tx_count);
|
||||
tx_start(info);
|
||||
}
|
||||
if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
|
||||
info->tx_count = 0;
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
}
|
||||
|
||||
|
|
@ -997,10 +968,9 @@ static void flush_buffer(struct tty_struct *tty)
|
|||
return;
|
||||
DBGINFO(("%s flush_buffer\n", info->device_name));
|
||||
|
||||
spin_lock_irqsave(&info->lock,flags);
|
||||
if (!info->tx_active)
|
||||
info->tx_count = 0;
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
info->tx_count = 0;
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
|
||||
tty_wakeup(tty);
|
||||
}
|
||||
|
|
@ -1033,12 +1003,10 @@ static void tx_release(struct tty_struct *tty)
|
|||
if (sanity_check(info, tty->name, "tx_release"))
|
||||
return;
|
||||
DBGINFO(("%s tx_release\n", info->device_name));
|
||||
spin_lock_irqsave(&info->lock,flags);
|
||||
if (!info->tx_active && info->tx_count) {
|
||||
tx_load(info, info->tx_buf, info->tx_count);
|
||||
tx_start(info);
|
||||
}
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
|
||||
info->tx_count = 0;
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1506,27 +1474,25 @@ static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
|
|||
|
||||
DBGINFO(("%s hdlc_xmit\n", dev->name));
|
||||
|
||||
if (!skb->len)
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* stop sending until this frame completes */
|
||||
netif_stop_queue(dev);
|
||||
|
||||
/* copy data to device buffers */
|
||||
info->tx_count = skb->len;
|
||||
tx_load(info, skb->data, skb->len);
|
||||
|
||||
/* update network statistics */
|
||||
dev->stats.tx_packets++;
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
|
||||
/* done with socket buffer, so free it */
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
/* save start time for transmit timeout detection */
|
||||
dev->trans_start = jiffies;
|
||||
|
||||
spin_lock_irqsave(&info->lock,flags);
|
||||
tx_start(info);
|
||||
update_tx_timer(info);
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
tx_load(info, skb->data, skb->len);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
|
||||
/* done with socket buffer, so free it */
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
|
@ -2180,7 +2146,7 @@ static void isr_serial(struct slgt_info *info)
|
|||
|
||||
if (info->params.mode == MGSL_MODE_ASYNC) {
|
||||
if (status & IRQ_TXIDLE) {
|
||||
if (info->tx_count)
|
||||
if (info->tx_active)
|
||||
isr_txeom(info, status);
|
||||
}
|
||||
if (info->rx_pio && (status & IRQ_RXDATA))
|
||||
|
|
@ -2276,13 +2242,42 @@ static void isr_tdma(struct slgt_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* return true if there are unsent tx DMA buffers, otherwise false
|
||||
*
|
||||
* if there are unsent buffers then info->tbuf_start
|
||||
* is set to index of first unsent buffer
|
||||
*/
|
||||
static bool unsent_tbufs(struct slgt_info *info)
|
||||
{
|
||||
unsigned int i = info->tbuf_current;
|
||||
bool rc = false;
|
||||
|
||||
/*
|
||||
* search backwards from last loaded buffer (precedes tbuf_current)
|
||||
* for first unsent buffer (desc_count > 0)
|
||||
*/
|
||||
|
||||
do {
|
||||
if (i)
|
||||
i--;
|
||||
else
|
||||
i = info->tbuf_count - 1;
|
||||
if (!desc_count(info->tbufs[i]))
|
||||
break;
|
||||
info->tbuf_start = i;
|
||||
rc = true;
|
||||
} while (i != info->tbuf_current);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void isr_txeom(struct slgt_info *info, unsigned short status)
|
||||
{
|
||||
DBGISR(("%s txeom status=%04x\n", info->device_name, status));
|
||||
|
||||
slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
|
||||
tdma_reset(info);
|
||||
reset_tbufs(info);
|
||||
if (status & IRQ_TXUNDER) {
|
||||
unsigned short val = rd_reg16(info, TCR);
|
||||
wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
|
||||
|
|
@ -2297,8 +2292,12 @@ static void isr_txeom(struct slgt_info *info, unsigned short status)
|
|||
info->icount.txok++;
|
||||
}
|
||||
|
||||
if (unsent_tbufs(info)) {
|
||||
tx_start(info);
|
||||
update_tx_timer(info);
|
||||
return;
|
||||
}
|
||||
info->tx_active = false;
|
||||
info->tx_count = 0;
|
||||
|
||||
del_timer(&info->tx_timer);
|
||||
|
||||
|
|
@ -3949,7 +3948,7 @@ static void tx_start(struct slgt_info *info)
|
|||
info->tx_enabled = true;
|
||||
}
|
||||
|
||||
if (info->tx_count) {
|
||||
if (desc_count(info->tbufs[info->tbuf_start])) {
|
||||
info->drop_rts_on_tx_done = false;
|
||||
|
||||
if (info->params.mode != MGSL_MODE_ASYNC) {
|
||||
|
|
@ -4772,25 +4771,36 @@ static unsigned int tbuf_bytes(struct slgt_info *info)
|
|||
}
|
||||
|
||||
/*
|
||||
* load transmit DMA buffer(s) with data
|
||||
* load data into transmit DMA buffer ring and start transmitter if needed
|
||||
* return true if data accepted, otherwise false (buffers full)
|
||||
*/
|
||||
static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
|
||||
static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size)
|
||||
{
|
||||
unsigned short count;
|
||||
unsigned int i;
|
||||
struct slgt_desc *d;
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
/* check required buffer space */
|
||||
if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info))
|
||||
return false;
|
||||
|
||||
DBGDATA(info, buf, size, "tx");
|
||||
|
||||
/*
|
||||
* copy data to one or more DMA buffers in circular ring
|
||||
* tbuf_start = first buffer for this data
|
||||
* tbuf_current = next free buffer
|
||||
*
|
||||
* Copy all data before making data visible to DMA controller by
|
||||
* setting descriptor count of the first buffer.
|
||||
* This prevents an active DMA controller from reading the first DMA
|
||||
* buffers of a frame and stopping before the final buffers are filled.
|
||||
*/
|
||||
|
||||
info->tbuf_start = i = info->tbuf_current;
|
||||
|
||||
while (size) {
|
||||
d = &info->tbufs[i];
|
||||
if (++i == info->tbuf_count)
|
||||
i = 0;
|
||||
|
||||
count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size);
|
||||
memcpy(d->buf, buf, count);
|
||||
|
|
@ -4808,11 +4818,27 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
|
|||
else
|
||||
set_desc_eof(*d, 0);
|
||||
|
||||
set_desc_count(*d, count);
|
||||
/* set descriptor count for all but first buffer */
|
||||
if (i != info->tbuf_start)
|
||||
set_desc_count(*d, count);
|
||||
d->buf_count = count;
|
||||
|
||||
if (++i == info->tbuf_count)
|
||||
i = 0;
|
||||
}
|
||||
|
||||
info->tbuf_current = i;
|
||||
|
||||
/* set first buffer count to make new data visible to DMA controller */
|
||||
d = &info->tbufs[info->tbuf_start];
|
||||
set_desc_count(*d, d->buf_count);
|
||||
|
||||
/* start transmitter if needed and update transmit timeout */
|
||||
if (!info->tx_active)
|
||||
tx_start(info);
|
||||
update_tx_timer(info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int register_test(struct slgt_info *info)
|
||||
|
|
@ -4934,9 +4960,7 @@ static int loopback_test(struct slgt_info *info)
|
|||
spin_lock_irqsave(&info->lock,flags);
|
||||
async_mode(info);
|
||||
rx_start(info);
|
||||
info->tx_count = count;
|
||||
tx_load(info, buf, count);
|
||||
tx_start(info);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
|
||||
/* wait for receive complete */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -231,9 +231,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size)
|
|||
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
|
||||
|
||||
/**
|
||||
* tty_insert_flip_string - Add characters to the tty buffer
|
||||
* tty_insert_flip_string_fixed_flag - Add characters to the tty buffer
|
||||
* @tty: tty structure
|
||||
* @chars: characters
|
||||
* @flag: flag value for each character
|
||||
* @size: size
|
||||
*
|
||||
* Queue a series of bytes to the tty buffering. All the characters
|
||||
|
|
@ -242,18 +243,19 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
|
|||
* Locking: Called functions may take tty->buf.lock
|
||||
*/
|
||||
|
||||
int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
|
||||
size_t size)
|
||||
int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
|
||||
const unsigned char *chars, char flag, size_t size)
|
||||
{
|
||||
int copied = 0;
|
||||
do {
|
||||
int space = tty_buffer_request_room(tty, size - copied);
|
||||
int goal = min(size - copied, TTY_BUFFER_PAGE);
|
||||
int space = tty_buffer_request_room(tty, goal);
|
||||
struct tty_buffer *tb = tty->buf.tail;
|
||||
/* If there is no space then tb may be NULL */
|
||||
if (unlikely(space == 0))
|
||||
break;
|
||||
memcpy(tb->char_buf_ptr + tb->used, chars, space);
|
||||
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
|
||||
memset(tb->flag_buf_ptr + tb->used, flag, space);
|
||||
tb->used += space;
|
||||
copied += space;
|
||||
chars += space;
|
||||
|
|
@ -262,7 +264,7 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
|
|||
} while (unlikely(size > copied));
|
||||
return copied;
|
||||
}
|
||||
EXPORT_SYMBOL(tty_insert_flip_string);
|
||||
EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
|
||||
|
||||
/**
|
||||
* tty_insert_flip_string_flags - Add characters to the tty buffer
|
||||
|
|
@ -283,7 +285,8 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
|
|||
{
|
||||
int copied = 0;
|
||||
do {
|
||||
int space = tty_buffer_request_room(tty, size - copied);
|
||||
int goal = min(size - copied, TTY_BUFFER_PAGE);
|
||||
int space = tty_buffer_request_room(tty, goal);
|
||||
struct tty_buffer *tb = tty->buf.tail;
|
||||
/* If there is no space then tb may be NULL */
|
||||
if (unlikely(space == 0))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -706,12 +706,13 @@ static void tty_reset_termios(struct tty_struct *tty)
|
|||
/**
|
||||
* tty_ldisc_reinit - reinitialise the tty ldisc
|
||||
* @tty: tty to reinit
|
||||
* @ldisc: line discipline to reinitialize
|
||||
*
|
||||
* Switch the tty back to N_TTY line discipline and leave the
|
||||
* ldisc state closed
|
||||
* Switch the tty to a line discipline and leave the ldisc
|
||||
* state closed
|
||||
*/
|
||||
|
||||
static void tty_ldisc_reinit(struct tty_struct *tty)
|
||||
static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
|
||||
{
|
||||
struct tty_ldisc *ld;
|
||||
|
||||
|
|
@ -721,10 +722,10 @@ static void tty_ldisc_reinit(struct tty_struct *tty)
|
|||
/*
|
||||
* Switch the line discipline back
|
||||
*/
|
||||
ld = tty_ldisc_get(N_TTY);
|
||||
ld = tty_ldisc_get(ldisc);
|
||||
BUG_ON(IS_ERR(ld));
|
||||
tty_ldisc_assign(tty, ld);
|
||||
tty_set_termios_ldisc(tty, N_TTY);
|
||||
tty_set_termios_ldisc(tty, ldisc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -745,6 +746,8 @@ static void tty_ldisc_reinit(struct tty_struct *tty)
|
|||
void tty_ldisc_hangup(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_ldisc *ld;
|
||||
int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* FIXME! What are the locking issues here? This may me overdoing
|
||||
|
|
@ -772,25 +775,32 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
|||
wake_up_interruptible_poll(&tty->read_wait, POLLIN);
|
||||
/*
|
||||
* Shutdown the current line discipline, and reset it to
|
||||
* N_TTY.
|
||||
* N_TTY if need be.
|
||||
*
|
||||
* Avoid racing set_ldisc or tty_ldisc_release
|
||||
*/
|
||||
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
|
||||
/* Avoid racing set_ldisc or tty_ldisc_release */
|
||||
mutex_lock(&tty->ldisc_mutex);
|
||||
tty_ldisc_halt(tty);
|
||||
if (tty->ldisc) { /* Not yet closed */
|
||||
/* Switch back to N_TTY */
|
||||
tty_ldisc_reinit(tty);
|
||||
/* At this point we have a closed ldisc and we want to
|
||||
reopen it. We could defer this to the next open but
|
||||
it means auditing a lot of other paths so this is
|
||||
a FIXME */
|
||||
WARN_ON(tty_ldisc_open(tty, tty->ldisc));
|
||||
tty_ldisc_enable(tty);
|
||||
mutex_lock(&tty->ldisc_mutex);
|
||||
tty_ldisc_halt(tty);
|
||||
/* At this point we have a closed ldisc and we want to
|
||||
reopen it. We could defer this to the next open but
|
||||
it means auditing a lot of other paths so this is
|
||||
a FIXME */
|
||||
if (tty->ldisc) { /* Not yet closed */
|
||||
if (reset == 0) {
|
||||
tty_ldisc_reinit(tty, tty->termios->c_line);
|
||||
err = tty_ldisc_open(tty, tty->ldisc);
|
||||
}
|
||||
mutex_unlock(&tty->ldisc_mutex);
|
||||
tty_reset_termios(tty);
|
||||
/* If the re-open fails or we reset then go to N_TTY. The
|
||||
N_TTY open cannot fail */
|
||||
if (reset || err) {
|
||||
tty_ldisc_reinit(tty, N_TTY);
|
||||
WARN_ON(tty_ldisc_open(tty, tty->ldisc));
|
||||
}
|
||||
tty_ldisc_enable(tty);
|
||||
}
|
||||
mutex_unlock(&tty->ldisc_mutex);
|
||||
if (reset)
|
||||
tty_reset_termios(tty);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ static ssize_t send_control_msg(struct port *port, unsigned int event,
|
|||
struct scatterlist sg[1];
|
||||
struct virtio_console_control cpkt;
|
||||
struct virtqueue *vq;
|
||||
int len;
|
||||
unsigned int len;
|
||||
|
||||
if (!use_multiport(port->portdev))
|
||||
return 0;
|
||||
|
|
@ -1071,27 +1071,27 @@ static void config_intr(struct virtio_device *vdev)
|
|||
static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
|
||||
{
|
||||
struct port_buffer *buf;
|
||||
unsigned int ret;
|
||||
int err;
|
||||
unsigned int nr_added_bufs;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
nr_added_bufs = 0;
|
||||
do {
|
||||
buf = alloc_buf(PAGE_SIZE);
|
||||
if (!buf)
|
||||
break;
|
||||
|
||||
spin_lock_irq(lock);
|
||||
err = add_inbuf(vq, buf);
|
||||
if (err < 0) {
|
||||
ret = add_inbuf(vq, buf);
|
||||
if (ret < 0) {
|
||||
spin_unlock_irq(lock);
|
||||
free_buf(buf);
|
||||
break;
|
||||
}
|
||||
ret++;
|
||||
nr_added_bufs++;
|
||||
spin_unlock_irq(lock);
|
||||
} while (err > 0);
|
||||
} while (ret > 0);
|
||||
|
||||
return ret;
|
||||
return nr_added_bufs;
|
||||
}
|
||||
|
||||
static int add_port(struct ports_device *portdev, u32 id)
|
||||
|
|
@ -1100,6 +1100,7 @@ static int add_port(struct ports_device *portdev, u32 id)
|
|||
struct port *port;
|
||||
struct port_buffer *buf;
|
||||
dev_t devt;
|
||||
unsigned int nr_added_bufs;
|
||||
int err;
|
||||
|
||||
port = kmalloc(sizeof(*port), GFP_KERNEL);
|
||||
|
|
@ -1144,8 +1145,8 @@ static int add_port(struct ports_device *portdev, u32 id)
|
|||
init_waitqueue_head(&port->waitqueue);
|
||||
|
||||
/* Fill the in_vq with buffers so the host can send us data. */
|
||||
err = fill_queue(port->in_vq, &port->inbuf_lock);
|
||||
if (!err) {
|
||||
nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock);
|
||||
if (!nr_added_bufs) {
|
||||
dev_err(port->dev, "Error allocating inbufs\n");
|
||||
err = -ENOMEM;
|
||||
goto free_device;
|
||||
|
|
@ -1442,12 +1443,14 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
|
|||
INIT_LIST_HEAD(&portdev->ports);
|
||||
|
||||
if (multiport) {
|
||||
unsigned int nr_added_bufs;
|
||||
|
||||
spin_lock_init(&portdev->cvq_lock);
|
||||
INIT_WORK(&portdev->control_work, &control_work_handler);
|
||||
INIT_WORK(&portdev->config_work, &config_work_handler);
|
||||
|
||||
err = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
|
||||
if (!err) {
|
||||
nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
|
||||
if (!nr_added_bufs) {
|
||||
dev_err(&vdev->dev,
|
||||
"Error allocating buffers for control queue\n");
|
||||
err = -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -888,7 +888,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
|
|||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) {
|
||||
if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS && tmp.mode != VT_PROCESS_AUTO) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1622,7 +1622,7 @@ static void complete_change_console(struct vc_data *vc)
|
|||
* telling it that it has acquired. Also check if it has died and
|
||||
* clean up (similar to logic employed in change_console())
|
||||
*/
|
||||
if (vc->vt_mode.mode == VT_PROCESS) {
|
||||
if (vc->vt_mode.mode == VT_PROCESS || vc->vt_mode.mode == VT_PROCESS_AUTO) {
|
||||
/*
|
||||
* Send the signal as privileged - kill_pid() will
|
||||
* tell us if the process has gone or something else
|
||||
|
|
@ -1682,7 +1682,7 @@ void change_console(struct vc_data *new_vc)
|
|||
* vt to auto control.
|
||||
*/
|
||||
vc = vc_cons[fg_console].d;
|
||||
if (vc->vt_mode.mode == VT_PROCESS) {
|
||||
if (vc->vt_mode.mode == VT_PROCESS || vc->vt_mode.mode == VT_PROCESS_AUTO) {
|
||||
/*
|
||||
* Send the signal as privileged - kill_pid() will
|
||||
* tell us if the process has gone or something else
|
||||
|
|
@ -1693,27 +1693,28 @@ void change_console(struct vc_data *new_vc)
|
|||
*/
|
||||
vc->vt_newvt = new_vc->vc_num;
|
||||
if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
|
||||
if(vc->vt_mode.mode == VT_PROCESS)
|
||||
/*
|
||||
* It worked. Mark the vt to switch to and
|
||||
* return. The process needs to send us a
|
||||
* VT_RELDISP ioctl to complete the switch.
|
||||
*/
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* It worked. Mark the vt to switch to and
|
||||
* return. The process needs to send us a
|
||||
* VT_RELDISP ioctl to complete the switch.
|
||||
* The controlling process has died, so we revert back to
|
||||
* normal operation. In this case, we'll also change back
|
||||
* to KD_TEXT mode. I'm not sure if this is strictly correct
|
||||
* but it saves the agony when the X server dies and the screen
|
||||
* remains blanked due to KD_GRAPHICS! It would be nice to do
|
||||
* this outside of VT_PROCESS but there is no single process
|
||||
* to account for and tracking tty count may be undesirable.
|
||||
*/
|
||||
return;
|
||||
reset_vc(vc);
|
||||
}
|
||||
|
||||
/*
|
||||
* The controlling process has died, so we revert back to
|
||||
* normal operation. In this case, we'll also change back
|
||||
* to KD_TEXT mode. I'm not sure if this is strictly correct
|
||||
* but it saves the agony when the X server dies and the screen
|
||||
* remains blanked due to KD_GRAPHICS! It would be nice to do
|
||||
* this outside of VT_PROCESS but there is no single process
|
||||
* to account for and tracking tty count may be undesirable.
|
||||
*/
|
||||
reset_vc(vc);
|
||||
|
||||
/*
|
||||
* Fall through to normal (VT_AUTO) handling of the switch...
|
||||
* Fall through to normal (VT_AUTO and VT_PROCESS_AUTO) handling of the switch...
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
config CS5535_CLOCK_EVENT_SRC
|
||||
tristate "CS5535/CS5536 high-res timer (MFGPT) events"
|
||||
depends on GENERIC_TIME && GENERIC_CLOCKEVENTS && CS5535_MFGPT
|
||||
help
|
||||
This driver provides a clock event source based on the MFGPT
|
||||
timer(s) in the CS5535 and CS5536 companion chips.
|
||||
MFGPTs have a better resolution and max interval than the
|
||||
generic PIT, and are suitable for use as high-res timers.
|
||||
|
||||
|
|
@ -766,7 +766,7 @@ static void cpufreq_sysfs_release(struct kobject *kobj)
|
|||
complete(&policy->kobj_unregister);
|
||||
}
|
||||
|
||||
static struct sysfs_ops sysfs_ops = {
|
||||
static const struct sysfs_ops sysfs_ops = {
|
||||
.show = show,
|
||||
.store = store,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -100,8 +100,8 @@ struct menu_device {
|
|||
int needs_update;
|
||||
|
||||
unsigned int expected_us;
|
||||
u64 predicted_us;
|
||||
unsigned int measured_us;
|
||||
u64 predicted_us;
|
||||
unsigned int exit_us;
|
||||
unsigned int bucket;
|
||||
u64 correction_factor[BUCKETS];
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ static int __init cpuidle_sysfs_setup(char *unused)
|
|||
__setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
|
||||
|
||||
static ssize_t show_available_governors(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t i = 0;
|
||||
|
|
@ -41,6 +42,7 @@ out:
|
|||
}
|
||||
|
||||
static ssize_t show_current_driver(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
|
@ -56,6 +58,7 @@ static ssize_t show_current_driver(struct sysdev_class *class,
|
|||
}
|
||||
|
||||
static ssize_t show_current_governor(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
|
@ -71,6 +74,7 @@ static ssize_t show_current_governor(struct sysdev_class *class,
|
|||
}
|
||||
|
||||
static ssize_t store_current_governor(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
char gov_name[CPUIDLE_NAME_LEN];
|
||||
|
|
@ -191,7 +195,7 @@ static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct sysfs_ops cpuidle_sysfs_ops = {
|
||||
static const struct sysfs_ops cpuidle_sysfs_ops = {
|
||||
.show = cpuidle_show,
|
||||
.store = cpuidle_store,
|
||||
};
|
||||
|
|
@ -277,7 +281,7 @@ static ssize_t cpuidle_state_show(struct kobject * kobj,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct sysfs_ops cpuidle_state_sysfs_ops = {
|
||||
static const struct sysfs_ops cpuidle_state_sysfs_ops = {
|
||||
.show = cpuidle_state_show,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,22 @@ menuconfig DMADEVICES
|
|||
DMA Device drivers supported by the configured arch, it may
|
||||
be empty in some cases.
|
||||
|
||||
config DMADEVICES_DEBUG
|
||||
bool "DMA Engine debugging"
|
||||
depends on DMADEVICES != n
|
||||
help
|
||||
This is an option for use by developers; most people should
|
||||
say N here. This enables DMA engine core and driver debugging.
|
||||
|
||||
config DMADEVICES_VDEBUG
|
||||
bool "DMA Engine verbose debugging"
|
||||
depends on DMADEVICES_DEBUG != n
|
||||
help
|
||||
This is an option for use by developers; most people should
|
||||
say N here. This enables deeper (more verbose) debugging of
|
||||
the DMA engine core and drivers.
|
||||
|
||||
|
||||
if DMADEVICES
|
||||
|
||||
comment "DMA Devices"
|
||||
|
|
@ -69,6 +85,13 @@ config FSL_DMA
|
|||
The Elo is the DMA controller on some 82xx and 83xx parts, and the
|
||||
Elo Plus is the DMA controller on 85xx and 86xx parts.
|
||||
|
||||
config MPC512X_DMA
|
||||
tristate "Freescale MPC512x built-in DMA engine support"
|
||||
depends on PPC_MPC512x
|
||||
select DMA_ENGINE
|
||||
---help---
|
||||
Enable support for the Freescale MPC512x built-in DMA engine.
|
||||
|
||||
config MV_XOR
|
||||
bool "Marvell XOR engine support"
|
||||
depends on PLAT_ORION
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
ifeq ($(CONFIG_DMADEVICES_DEBUG),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
ifeq ($(CONFIG_DMADEVICES_VDEBUG),y)
|
||||
EXTRA_CFLAGS += -DVERBOSE_DEBUG
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
|
||||
obj-$(CONFIG_NET_DMA) += iovlock.o
|
||||
obj-$(CONFIG_DMATEST) += dmatest.o
|
||||
obj-$(CONFIG_INTEL_IOATDMA) += ioat/
|
||||
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
|
||||
obj-$(CONFIG_FSL_DMA) += fsldma.o
|
||||
obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
|
||||
obj-$(CONFIG_MV_XOR) += mv_xor.o
|
||||
obj-$(CONFIG_DW_DMAC) += dw_dmac.o
|
||||
obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ struct coh901318_desc {
|
|||
unsigned int sg_len;
|
||||
struct coh901318_lli *data;
|
||||
enum dma_data_direction dir;
|
||||
int pending_irqs;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
|
|
@ -72,7 +71,6 @@ struct coh901318_chan {
|
|||
|
||||
unsigned long nbr_active_done;
|
||||
unsigned long busy;
|
||||
int pending_irqs;
|
||||
|
||||
struct coh901318_base *base;
|
||||
};
|
||||
|
|
@ -80,18 +78,16 @@ struct coh901318_chan {
|
|||
static void coh901318_list_print(struct coh901318_chan *cohc,
|
||||
struct coh901318_lli *lli)
|
||||
{
|
||||
struct coh901318_lli *l;
|
||||
dma_addr_t addr = virt_to_phys(lli);
|
||||
struct coh901318_lli *l = lli;
|
||||
int i = 0;
|
||||
|
||||
while (addr) {
|
||||
l = phys_to_virt(addr);
|
||||
while (l) {
|
||||
dev_vdbg(COHC_2_DEV(cohc), "i %d, lli %p, ctrl 0x%x, src 0x%x"
|
||||
", dst 0x%x, link 0x%x link_virt 0x%p\n",
|
||||
", dst 0x%x, link 0x%x virt_link_addr 0x%p\n",
|
||||
i, l, l->control, l->src_addr, l->dst_addr,
|
||||
l->link_addr, phys_to_virt(l->link_addr));
|
||||
l->link_addr, l->virt_link_addr);
|
||||
i++;
|
||||
addr = l->link_addr;
|
||||
l = l->virt_link_addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +121,7 @@ static int coh901318_debugfs_read(struct file *file, char __user *buf,
|
|||
goto err_kmalloc;
|
||||
tmp = dev_buf;
|
||||
|
||||
tmp += sprintf(tmp, "DMA -- enable dma channels\n");
|
||||
tmp += sprintf(tmp, "DMA -- enabled dma channels\n");
|
||||
|
||||
for (i = 0; i < debugfs_dma_base->platform->max_channels; i++)
|
||||
if (started_channels & (1 << i))
|
||||
|
|
@ -337,16 +333,22 @@ coh901318_desc_get(struct coh901318_chan *cohc)
|
|||
* TODO: alloc a pile of descs instead of just one,
|
||||
* avoid many small allocations.
|
||||
*/
|
||||
desc = kmalloc(sizeof(struct coh901318_desc), GFP_NOWAIT);
|
||||
desc = kzalloc(sizeof(struct coh901318_desc), GFP_NOWAIT);
|
||||
if (desc == NULL)
|
||||
goto out;
|
||||
INIT_LIST_HEAD(&desc->node);
|
||||
dma_async_tx_descriptor_init(&desc->desc, &cohc->chan);
|
||||
} else {
|
||||
/* Reuse an old desc. */
|
||||
desc = list_first_entry(&cohc->free,
|
||||
struct coh901318_desc,
|
||||
node);
|
||||
list_del(&desc->node);
|
||||
/* Initialize it a bit so it's not insane */
|
||||
desc->sg = NULL;
|
||||
desc->sg_len = 0;
|
||||
desc->desc.callback = NULL;
|
||||
desc->desc.callback_param = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
@ -364,10 +366,6 @@ static void
|
|||
coh901318_desc_submit(struct coh901318_chan *cohc, struct coh901318_desc *desc)
|
||||
{
|
||||
list_add_tail(&desc->node, &cohc->active);
|
||||
|
||||
BUG_ON(cohc->pending_irqs != 0);
|
||||
|
||||
cohc->pending_irqs = desc->pending_irqs;
|
||||
}
|
||||
|
||||
static struct coh901318_desc *
|
||||
|
|
@ -592,6 +590,10 @@ static struct coh901318_desc *coh901318_queue_start(struct coh901318_chan *cohc)
|
|||
return cohd_que;
|
||||
}
|
||||
|
||||
/*
|
||||
* This tasklet is called from the interrupt handler to
|
||||
* handle each descriptor (DMA job) that is sent to a channel.
|
||||
*/
|
||||
static void dma_tasklet(unsigned long data)
|
||||
{
|
||||
struct coh901318_chan *cohc = (struct coh901318_chan *) data;
|
||||
|
|
@ -600,55 +602,58 @@ static void dma_tasklet(unsigned long data)
|
|||
dma_async_tx_callback callback;
|
||||
void *callback_param;
|
||||
|
||||
dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d"
|
||||
" nbr_active_done %ld\n", __func__,
|
||||
cohc->id, cohc->nbr_active_done);
|
||||
|
||||
spin_lock_irqsave(&cohc->lock, flags);
|
||||
|
||||
/* get first active entry from list */
|
||||
/* get first active descriptor entry from list */
|
||||
cohd_fin = coh901318_first_active_get(cohc);
|
||||
|
||||
BUG_ON(cohd_fin->pending_irqs == 0);
|
||||
|
||||
if (cohd_fin == NULL)
|
||||
goto err;
|
||||
|
||||
cohd_fin->pending_irqs--;
|
||||
cohc->completed = cohd_fin->desc.cookie;
|
||||
|
||||
if (cohc->nbr_active_done == 0)
|
||||
return;
|
||||
|
||||
if (!cohd_fin->pending_irqs) {
|
||||
/* release the lli allocation*/
|
||||
coh901318_lli_free(&cohc->base->pool, &cohd_fin->data);
|
||||
}
|
||||
|
||||
dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d pending_irqs %d"
|
||||
" nbr_active_done %ld\n", __func__,
|
||||
cohc->id, cohc->pending_irqs, cohc->nbr_active_done);
|
||||
|
||||
/* callback to client */
|
||||
/* locate callback to client */
|
||||
callback = cohd_fin->desc.callback;
|
||||
callback_param = cohd_fin->desc.callback_param;
|
||||
|
||||
if (!cohd_fin->pending_irqs) {
|
||||
coh901318_desc_remove(cohd_fin);
|
||||
/* sign this job as completed on the channel */
|
||||
cohc->completed = cohd_fin->desc.cookie;
|
||||
|
||||
/* return desc to free-list */
|
||||
coh901318_desc_free(cohc, cohd_fin);
|
||||
}
|
||||
/* release the lli allocation and remove the descriptor */
|
||||
coh901318_lli_free(&cohc->base->pool, &cohd_fin->data);
|
||||
|
||||
if (cohc->nbr_active_done)
|
||||
cohc->nbr_active_done--;
|
||||
/* return desc to free-list */
|
||||
coh901318_desc_remove(cohd_fin);
|
||||
coh901318_desc_free(cohc, cohd_fin);
|
||||
|
||||
spin_unlock_irqrestore(&cohc->lock, flags);
|
||||
|
||||
/* Call the callback when we're done */
|
||||
if (callback)
|
||||
callback(callback_param);
|
||||
|
||||
spin_lock_irqsave(&cohc->lock, flags);
|
||||
|
||||
/*
|
||||
* If another interrupt fired while the tasklet was scheduling,
|
||||
* we don't get called twice, so we have this number of active
|
||||
* counter that keep track of the number of IRQs expected to
|
||||
* be handled for this channel. If there happen to be more than
|
||||
* one IRQ to be ack:ed, we simply schedule this tasklet again.
|
||||
*/
|
||||
cohc->nbr_active_done--;
|
||||
if (cohc->nbr_active_done) {
|
||||
dev_dbg(COHC_2_DEV(cohc), "scheduling tasklet again, new IRQs "
|
||||
"came in while we were scheduling this tasklet\n");
|
||||
if (cohc_chan_conf(cohc)->priority_high)
|
||||
tasklet_hi_schedule(&cohc->tasklet);
|
||||
else
|
||||
tasklet_schedule(&cohc->tasklet);
|
||||
}
|
||||
spin_unlock_irqrestore(&cohc->lock, flags);
|
||||
|
||||
if (callback)
|
||||
callback(callback_param);
|
||||
spin_unlock_irqrestore(&cohc->lock, flags);
|
||||
|
||||
return;
|
||||
|
||||
|
|
@ -667,16 +672,17 @@ static void dma_tc_handle(struct coh901318_chan *cohc)
|
|||
if (!cohc->allocated)
|
||||
return;
|
||||
|
||||
BUG_ON(cohc->pending_irqs == 0);
|
||||
spin_lock(&cohc->lock);
|
||||
|
||||
cohc->pending_irqs--;
|
||||
cohc->nbr_active_done++;
|
||||
|
||||
if (cohc->pending_irqs == 0 && coh901318_queue_start(cohc) == NULL)
|
||||
if (coh901318_queue_start(cohc) == NULL)
|
||||
cohc->busy = 0;
|
||||
|
||||
BUG_ON(list_empty(&cohc->active));
|
||||
|
||||
spin_unlock(&cohc->lock);
|
||||
|
||||
if (cohc_chan_conf(cohc)->priority_high)
|
||||
tasklet_hi_schedule(&cohc->tasklet);
|
||||
else
|
||||
|
|
@ -870,6 +876,7 @@ coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
|||
struct coh901318_chan *cohc = to_coh901318_chan(chan);
|
||||
int lli_len;
|
||||
u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&cohc->lock, flg);
|
||||
|
||||
|
|
@ -890,22 +897,19 @@ coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
|||
if (data == NULL)
|
||||
goto err;
|
||||
|
||||
cohd = coh901318_desc_get(cohc);
|
||||
cohd->sg = NULL;
|
||||
cohd->sg_len = 0;
|
||||
cohd->data = data;
|
||||
|
||||
cohd->pending_irqs =
|
||||
coh901318_lli_fill_memcpy(
|
||||
&cohc->base->pool, data, src, size, dest,
|
||||
cohc_chan_param(cohc)->ctrl_lli_chained,
|
||||
ctrl_last);
|
||||
cohd->flags = flags;
|
||||
ret = coh901318_lli_fill_memcpy(
|
||||
&cohc->base->pool, data, src, size, dest,
|
||||
cohc_chan_param(cohc)->ctrl_lli_chained,
|
||||
ctrl_last);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
COH_DBG(coh901318_list_print(cohc, data));
|
||||
|
||||
dma_async_tx_descriptor_init(&cohd->desc, chan);
|
||||
|
||||
/* Pick a descriptor to handle this transfer */
|
||||
cohd = coh901318_desc_get(cohc);
|
||||
cohd->data = data;
|
||||
cohd->flags = flags;
|
||||
cohd->desc.tx_submit = coh901318_tx_submit;
|
||||
|
||||
spin_unlock_irqrestore(&cohc->lock, flg);
|
||||
|
|
@ -924,6 +928,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
|||
struct coh901318_chan *cohc = to_coh901318_chan(chan);
|
||||
struct coh901318_lli *data;
|
||||
struct coh901318_desc *cohd;
|
||||
const struct coh901318_params *params;
|
||||
struct scatterlist *sg;
|
||||
int len = 0;
|
||||
int size;
|
||||
|
|
@ -931,7 +936,9 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
|||
u32 ctrl_chained = cohc_chan_param(cohc)->ctrl_lli_chained;
|
||||
u32 ctrl = cohc_chan_param(cohc)->ctrl_lli;
|
||||
u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
|
||||
u32 config;
|
||||
unsigned long flg;
|
||||
int ret;
|
||||
|
||||
if (!sgl)
|
||||
goto out;
|
||||
|
|
@ -947,15 +954,14 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
|||
/* Trigger interrupt after last lli */
|
||||
ctrl_last |= COH901318_CX_CTRL_TC_IRQ_ENABLE;
|
||||
|
||||
cohd = coh901318_desc_get(cohc);
|
||||
cohd->sg = NULL;
|
||||
cohd->sg_len = 0;
|
||||
cohd->dir = direction;
|
||||
params = cohc_chan_param(cohc);
|
||||
config = params->config;
|
||||
|
||||
if (direction == DMA_TO_DEVICE) {
|
||||
u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE |
|
||||
COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE;
|
||||
|
||||
config |= COH901318_CX_CFG_RM_MEMORY_TO_PRIMARY;
|
||||
ctrl_chained |= tx_flags;
|
||||
ctrl_last |= tx_flags;
|
||||
ctrl |= tx_flags;
|
||||
|
|
@ -963,16 +969,14 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
|||
u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST |
|
||||
COH901318_CX_CTRL_DST_ADDR_INC_ENABLE;
|
||||
|
||||
config |= COH901318_CX_CFG_RM_PRIMARY_TO_MEMORY;
|
||||
ctrl_chained |= rx_flags;
|
||||
ctrl_last |= rx_flags;
|
||||
ctrl |= rx_flags;
|
||||
} else
|
||||
goto err_direction;
|
||||
|
||||
dma_async_tx_descriptor_init(&cohd->desc, chan);
|
||||
|
||||
cohd->desc.tx_submit = coh901318_tx_submit;
|
||||
|
||||
coh901318_set_conf(cohc, config);
|
||||
|
||||
/* The dma only supports transmitting packages up to
|
||||
* MAX_DMA_PACKET_SIZE. Calculate to total number of
|
||||
|
|
@ -994,32 +998,37 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
|||
len += factor;
|
||||
}
|
||||
|
||||
pr_debug("Allocate %d lli:s for this transfer\n", len);
|
||||
data = coh901318_lli_alloc(&cohc->base->pool, len);
|
||||
|
||||
if (data == NULL)
|
||||
goto err_dma_alloc;
|
||||
|
||||
/* initiate allocated data list */
|
||||
cohd->pending_irqs =
|
||||
coh901318_lli_fill_sg(&cohc->base->pool, data, sgl, sg_len,
|
||||
cohc_dev_addr(cohc),
|
||||
ctrl_chained,
|
||||
ctrl,
|
||||
ctrl_last,
|
||||
direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
|
||||
cohd->data = data;
|
||||
|
||||
cohd->flags = flags;
|
||||
ret = coh901318_lli_fill_sg(&cohc->base->pool, data, sgl, sg_len,
|
||||
cohc_dev_addr(cohc),
|
||||
ctrl_chained,
|
||||
ctrl,
|
||||
ctrl_last,
|
||||
direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
|
||||
if (ret)
|
||||
goto err_lli_fill;
|
||||
|
||||
COH_DBG(coh901318_list_print(cohc, data));
|
||||
|
||||
/* Pick a descriptor to handle this transfer */
|
||||
cohd = coh901318_desc_get(cohc);
|
||||
cohd->dir = direction;
|
||||
cohd->flags = flags;
|
||||
cohd->desc.tx_submit = coh901318_tx_submit;
|
||||
cohd->data = data;
|
||||
|
||||
spin_unlock_irqrestore(&cohc->lock, flg);
|
||||
|
||||
return &cohd->desc;
|
||||
err_lli_fill:
|
||||
err_dma_alloc:
|
||||
err_direction:
|
||||
coh901318_desc_remove(cohd);
|
||||
coh901318_desc_free(cohc, cohd);
|
||||
spin_unlock_irqrestore(&cohc->lock, flg);
|
||||
out:
|
||||
return NULL;
|
||||
|
|
@ -1092,9 +1101,8 @@ coh901318_terminate_all(struct dma_chan *chan)
|
|||
/* release the lli allocation*/
|
||||
coh901318_lli_free(&cohc->base->pool, &cohd->data);
|
||||
|
||||
coh901318_desc_remove(cohd);
|
||||
|
||||
/* return desc to free-list */
|
||||
coh901318_desc_remove(cohd);
|
||||
coh901318_desc_free(cohc, cohd);
|
||||
}
|
||||
|
||||
|
|
@ -1102,16 +1110,14 @@ coh901318_terminate_all(struct dma_chan *chan)
|
|||
/* release the lli allocation*/
|
||||
coh901318_lli_free(&cohc->base->pool, &cohd->data);
|
||||
|
||||
coh901318_desc_remove(cohd);
|
||||
|
||||
/* return desc to free-list */
|
||||
coh901318_desc_remove(cohd);
|
||||
coh901318_desc_free(cohc, cohd);
|
||||
}
|
||||
|
||||
|
||||
cohc->nbr_active_done = 0;
|
||||
cohc->busy = 0;
|
||||
cohc->pending_irqs = 0;
|
||||
|
||||
spin_unlock_irqrestore(&cohc->lock, flags);
|
||||
}
|
||||
|
|
@ -1138,7 +1144,6 @@ void coh901318_base_init(struct dma_device *dma, const int *pick_chans,
|
|||
|
||||
spin_lock_init(&cohc->lock);
|
||||
|
||||
cohc->pending_irqs = 0;
|
||||
cohc->nbr_active_done = 0;
|
||||
cohc->busy = 0;
|
||||
INIT_LIST_HEAD(&cohc->free);
|
||||
|
|
@ -1254,12 +1259,17 @@ static int __init coh901318_probe(struct platform_device *pdev)
|
|||
base->dma_memcpy.device_issue_pending = coh901318_issue_pending;
|
||||
base->dma_memcpy.device_terminate_all = coh901318_terminate_all;
|
||||
base->dma_memcpy.dev = &pdev->dev;
|
||||
/*
|
||||
* This controller can only access address at even 32bit boundaries,
|
||||
* i.e. 2^2
|
||||
*/
|
||||
base->dma_memcpy.copy_align = 2;
|
||||
err = dma_async_device_register(&base->dma_memcpy);
|
||||
|
||||
if (err)
|
||||
goto err_register_memcpy;
|
||||
|
||||
dev_dbg(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n",
|
||||
dev_info(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n",
|
||||
(u32) base->virtbase);
|
||||
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ coh901318_lli_alloc(struct coh901318_pool *pool, unsigned int len)
|
|||
|
||||
lli = head;
|
||||
lli->phy_this = phy;
|
||||
lli->link_addr = 0x00000000;
|
||||
lli->virt_link_addr = 0x00000000U;
|
||||
|
||||
for (i = 1; i < len; i++) {
|
||||
lli_prev = lli;
|
||||
|
|
@ -85,13 +87,13 @@ coh901318_lli_alloc(struct coh901318_pool *pool, unsigned int len)
|
|||
|
||||
DEBUGFS_POOL_COUNTER_ADD(pool, 1);
|
||||
lli->phy_this = phy;
|
||||
lli->link_addr = 0x00000000;
|
||||
lli->virt_link_addr = 0x00000000U;
|
||||
|
||||
lli_prev->link_addr = phy;
|
||||
lli_prev->virt_link_addr = lli;
|
||||
}
|
||||
|
||||
lli->link_addr = 0x00000000U;
|
||||
|
||||
spin_unlock(&pool->lock);
|
||||
|
||||
return head;
|
||||
|
|
@ -166,8 +168,7 @@ coh901318_lli_fill_memcpy(struct coh901318_pool *pool,
|
|||
lli->src_addr = src;
|
||||
lli->dst_addr = dst;
|
||||
|
||||
/* One irq per single transfer */
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -223,8 +224,7 @@ coh901318_lli_fill_single(struct coh901318_pool *pool,
|
|||
lli->src_addr = src;
|
||||
lli->dst_addr = dst;
|
||||
|
||||
/* One irq per single transfer */
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -240,7 +240,6 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
|
|||
u32 ctrl_sg;
|
||||
dma_addr_t src = 0;
|
||||
dma_addr_t dst = 0;
|
||||
int nbr_of_irq = 0;
|
||||
u32 bytes_to_transfer;
|
||||
u32 elem_size;
|
||||
|
||||
|
|
@ -269,15 +268,12 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
|
|||
ctrl_sg = ctrl ? ctrl : ctrl_last;
|
||||
|
||||
|
||||
if ((ctrl_sg & ctrl_irq_mask))
|
||||
nbr_of_irq++;
|
||||
|
||||
if (dir == DMA_TO_DEVICE)
|
||||
/* increment source address */
|
||||
src = sg_dma_address(sg);
|
||||
src = sg_phys(sg);
|
||||
else
|
||||
/* increment destination address */
|
||||
dst = sg_dma_address(sg);
|
||||
dst = sg_phys(sg);
|
||||
|
||||
bytes_to_transfer = sg_dma_len(sg);
|
||||
|
||||
|
|
@ -310,8 +306,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
|
|||
}
|
||||
spin_unlock(&pool->lock);
|
||||
|
||||
/* There can be many IRQs per sg transfer */
|
||||
return nbr_of_irq;
|
||||
return 0;
|
||||
err:
|
||||
spin_unlock(&pool->lock);
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ struct dma_chan_tbl_ent {
|
|||
/**
|
||||
* channel_table - percpu lookup table for memory-to-memory offload providers
|
||||
*/
|
||||
static struct dma_chan_tbl_ent *channel_table[DMA_TX_TYPE_END];
|
||||
static struct dma_chan_tbl_ent __percpu *channel_table[DMA_TX_TYPE_END];
|
||||
|
||||
static int __init dma_channel_table_init(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ static int dmatest_func(void *data)
|
|||
dma_cookie_t cookie;
|
||||
enum dma_status status;
|
||||
enum dma_ctrl_flags flags;
|
||||
u8 pq_coefs[pq_sources];
|
||||
u8 pq_coefs[pq_sources + 1];
|
||||
int ret;
|
||||
int src_cnt;
|
||||
int dst_cnt;
|
||||
|
|
@ -257,7 +257,7 @@ static int dmatest_func(void *data)
|
|||
} else if (thread->type == DMA_PQ) {
|
||||
src_cnt = pq_sources | 1; /* force odd to ensure dst = src */
|
||||
dst_cnt = 2;
|
||||
for (i = 0; i < pq_sources; i++)
|
||||
for (i = 0; i < src_cnt; i++)
|
||||
pq_coefs[i] = 1;
|
||||
} else
|
||||
goto err_srcs;
|
||||
|
|
@ -347,7 +347,7 @@ static int dmatest_func(void *data)
|
|||
else if (thread->type == DMA_XOR)
|
||||
tx = dev->device_prep_dma_xor(chan,
|
||||
dma_dsts[0] + dst_off,
|
||||
dma_srcs, xor_sources,
|
||||
dma_srcs, src_cnt,
|
||||
len, flags);
|
||||
else if (thread->type == DMA_PQ) {
|
||||
dma_addr_t dma_pq[dst_cnt];
|
||||
|
|
@ -355,7 +355,7 @@ static int dmatest_func(void *data)
|
|||
for (i = 0; i < dst_cnt; i++)
|
||||
dma_pq[i] = dma_dsts[i] + dst_off;
|
||||
tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs,
|
||||
pq_sources, pq_coefs,
|
||||
src_cnt, pq_coefs,
|
||||
len, flags);
|
||||
}
|
||||
|
||||
|
|
|
|||
1217
drivers/dma/fsldma.c
1217
drivers/dma/fsldma.c
File diff suppressed because it is too large
Load diff
|
|
@ -92,11 +92,9 @@ struct fsl_desc_sw {
|
|||
struct list_head node;
|
||||
struct list_head tx_list;
|
||||
struct dma_async_tx_descriptor async_tx;
|
||||
struct list_head *ld;
|
||||
void *priv;
|
||||
} __attribute__((aligned(32)));
|
||||
|
||||
struct fsl_dma_chan_regs {
|
||||
struct fsldma_chan_regs {
|
||||
u32 mr; /* 0x00 - Mode Register */
|
||||
u32 sr; /* 0x04 - Status Register */
|
||||
u64 cdar; /* 0x08 - Current descriptor address register */
|
||||
|
|
@ -106,20 +104,19 @@ struct fsl_dma_chan_regs {
|
|||
u64 ndar; /* 0x24 - Next Descriptor Address Register */
|
||||
};
|
||||
|
||||
struct fsl_dma_chan;
|
||||
struct fsldma_chan;
|
||||
#define FSL_DMA_MAX_CHANS_PER_DEVICE 4
|
||||
|
||||
struct fsl_dma_device {
|
||||
void __iomem *reg_base; /* DGSR register base */
|
||||
struct resource reg; /* Resource for register */
|
||||
struct fsldma_device {
|
||||
void __iomem *regs; /* DGSR register base */
|
||||
struct device *dev;
|
||||
struct dma_device common;
|
||||
struct fsl_dma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
|
||||
struct fsldma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
|
||||
u32 feature; /* The same as DMA channels */
|
||||
int irq; /* Channel IRQ */
|
||||
};
|
||||
|
||||
/* Define macros for fsl_dma_chan->feature property */
|
||||
/* Define macros for fsldma_chan->feature property */
|
||||
#define FSL_DMA_LITTLE_ENDIAN 0x00000000
|
||||
#define FSL_DMA_BIG_ENDIAN 0x00000001
|
||||
|
||||
|
|
@ -130,28 +127,28 @@ struct fsl_dma_device {
|
|||
#define FSL_DMA_CHAN_PAUSE_EXT 0x00001000
|
||||
#define FSL_DMA_CHAN_START_EXT 0x00002000
|
||||
|
||||
struct fsl_dma_chan {
|
||||
struct fsl_dma_chan_regs __iomem *reg_base;
|
||||
struct fsldma_chan {
|
||||
struct fsldma_chan_regs __iomem *regs;
|
||||
dma_cookie_t completed_cookie; /* The maximum cookie completed */
|
||||
spinlock_t desc_lock; /* Descriptor operation lock */
|
||||
struct list_head ld_queue; /* Link descriptors queue */
|
||||
struct list_head ld_pending; /* Link descriptors queue */
|
||||
struct list_head ld_running; /* Link descriptors queue */
|
||||
struct dma_chan common; /* DMA common channel */
|
||||
struct dma_pool *desc_pool; /* Descriptors pool */
|
||||
struct device *dev; /* Channel device */
|
||||
struct resource reg; /* Resource for register */
|
||||
int irq; /* Channel IRQ */
|
||||
int id; /* Raw id of this channel */
|
||||
struct tasklet_struct tasklet;
|
||||
u32 feature;
|
||||
|
||||
void (*toggle_ext_pause)(struct fsl_dma_chan *fsl_chan, int enable);
|
||||
void (*toggle_ext_start)(struct fsl_dma_chan *fsl_chan, int enable);
|
||||
void (*set_src_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
|
||||
void (*set_dest_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
|
||||
void (*set_request_count)(struct fsl_dma_chan *fsl_chan, int size);
|
||||
void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
|
||||
void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
|
||||
void (*set_src_loop_size)(struct fsldma_chan *fsl_chan, int size);
|
||||
void (*set_dst_loop_size)(struct fsldma_chan *fsl_chan, int size);
|
||||
void (*set_request_count)(struct fsldma_chan *fsl_chan, int size);
|
||||
};
|
||||
|
||||
#define to_fsl_chan(chan) container_of(chan, struct fsl_dma_chan, common)
|
||||
#define to_fsl_chan(chan) container_of(chan, struct fsldma_chan, common)
|
||||
#define to_fsl_desc(lh) container_of(lh, struct fsl_desc_sw, node)
|
||||
#define tx_to_fsl_desc(tx) container_of(tx, struct fsl_desc_sw, async_tx)
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ static irqreturn_t ioat_dma_do_interrupt(int irq, void *data)
|
|||
}
|
||||
|
||||
attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
|
||||
for_each_bit(bit, &attnstatus, BITS_PER_LONG) {
|
||||
for_each_set_bit(bit, &attnstatus, BITS_PER_LONG) {
|
||||
chan = ioat_chan_by_index(instance, bit);
|
||||
tasklet_schedule(&chan->cleanup_task);
|
||||
}
|
||||
|
|
@ -94,16 +94,12 @@ static irqreturn_t ioat_dma_do_interrupt_msix(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void ioat1_cleanup_tasklet(unsigned long data);
|
||||
|
||||
/* common channel initialization */
|
||||
void ioat_init_channel(struct ioatdma_device *device,
|
||||
struct ioat_chan_common *chan, int idx,
|
||||
void (*timer_fn)(unsigned long),
|
||||
void (*tasklet)(unsigned long),
|
||||
unsigned long ioat)
|
||||
void ioat_init_channel(struct ioatdma_device *device, struct ioat_chan_common *chan, int idx)
|
||||
{
|
||||
struct dma_device *dma = &device->common;
|
||||
struct dma_chan *c = &chan->common;
|
||||
unsigned long data = (unsigned long) c;
|
||||
|
||||
chan->device = device;
|
||||
chan->reg_base = device->reg_base + (0x80 * (idx + 1));
|
||||
|
|
@ -112,14 +108,12 @@ void ioat_init_channel(struct ioatdma_device *device,
|
|||
list_add_tail(&chan->common.device_node, &dma->channels);
|
||||
device->idx[idx] = chan;
|
||||
init_timer(&chan->timer);
|
||||
chan->timer.function = timer_fn;
|
||||
chan->timer.data = ioat;
|
||||
tasklet_init(&chan->cleanup_task, tasklet, ioat);
|
||||
chan->timer.function = device->timer_fn;
|
||||
chan->timer.data = data;
|
||||
tasklet_init(&chan->cleanup_task, device->cleanup_fn, data);
|
||||
tasklet_disable(&chan->cleanup_task);
|
||||
}
|
||||
|
||||
static void ioat1_timer_event(unsigned long data);
|
||||
|
||||
/**
|
||||
* ioat1_dma_enumerate_channels - find and initialize the device's channels
|
||||
* @device: the device to be enumerated
|
||||
|
|
@ -155,10 +149,7 @@ static int ioat1_enumerate_channels(struct ioatdma_device *device)
|
|||
if (!ioat)
|
||||
break;
|
||||
|
||||
ioat_init_channel(device, &ioat->base, i,
|
||||
ioat1_timer_event,
|
||||
ioat1_cleanup_tasklet,
|
||||
(unsigned long) ioat);
|
||||
ioat_init_channel(device, &ioat->base, i);
|
||||
ioat->xfercap = xfercap;
|
||||
spin_lock_init(&ioat->desc_lock);
|
||||
INIT_LIST_HEAD(&ioat->free_desc);
|
||||
|
|
@ -532,12 +523,12 @@ ioat1_dma_prep_memcpy(struct dma_chan *c, dma_addr_t dma_dest,
|
|||
return &desc->txd;
|
||||
}
|
||||
|
||||
static void ioat1_cleanup_tasklet(unsigned long data)
|
||||
static void ioat1_cleanup_event(unsigned long data)
|
||||
{
|
||||
struct ioat_dma_chan *chan = (void *)data;
|
||||
struct ioat_dma_chan *ioat = to_ioat_chan((void *) data);
|
||||
|
||||
ioat1_cleanup(chan);
|
||||
writew(IOAT_CHANCTRL_RUN, chan->base.reg_base + IOAT_CHANCTRL_OFFSET);
|
||||
ioat1_cleanup(ioat);
|
||||
writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
|
||||
}
|
||||
|
||||
void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
|
||||
|
|
@ -687,7 +678,7 @@ static void ioat1_cleanup(struct ioat_dma_chan *ioat)
|
|||
|
||||
static void ioat1_timer_event(unsigned long data)
|
||||
{
|
||||
struct ioat_dma_chan *ioat = (void *) data;
|
||||
struct ioat_dma_chan *ioat = to_ioat_chan((void *) data);
|
||||
struct ioat_chan_common *chan = &ioat->base;
|
||||
|
||||
dev_dbg(to_dev(chan), "%s: state: %lx\n", __func__, chan->state);
|
||||
|
|
@ -734,16 +725,17 @@ static void ioat1_timer_event(unsigned long data)
|
|||
spin_unlock_bh(&chan->cleanup_lock);
|
||||
}
|
||||
|
||||
static enum dma_status
|
||||
ioat1_dma_is_complete(struct dma_chan *c, dma_cookie_t cookie,
|
||||
enum dma_status
|
||||
ioat_is_dma_complete(struct dma_chan *c, dma_cookie_t cookie,
|
||||
dma_cookie_t *done, dma_cookie_t *used)
|
||||
{
|
||||
struct ioat_dma_chan *ioat = to_ioat_chan(c);
|
||||
struct ioat_chan_common *chan = to_chan_common(c);
|
||||
struct ioatdma_device *device = chan->device;
|
||||
|
||||
if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)
|
||||
return DMA_SUCCESS;
|
||||
|
||||
ioat1_cleanup(ioat);
|
||||
device->cleanup_fn((unsigned long) c);
|
||||
|
||||
return ioat_is_complete(c, cookie, done, used);
|
||||
}
|
||||
|
|
@ -1146,7 +1138,7 @@ ioat_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
|
|||
return entry->show(&chan->common, page);
|
||||
}
|
||||
|
||||
struct sysfs_ops ioat_sysfs_ops = {
|
||||
const struct sysfs_ops ioat_sysfs_ops = {
|
||||
.show = ioat_attr_show,
|
||||
};
|
||||
|
||||
|
|
@ -1199,12 +1191,14 @@ int __devinit ioat1_dma_probe(struct ioatdma_device *device, int dca)
|
|||
device->intr_quirk = ioat1_intr_quirk;
|
||||
device->enumerate_channels = ioat1_enumerate_channels;
|
||||
device->self_test = ioat_dma_self_test;
|
||||
device->timer_fn = ioat1_timer_event;
|
||||
device->cleanup_fn = ioat1_cleanup_event;
|
||||
dma = &device->common;
|
||||
dma->device_prep_dma_memcpy = ioat1_dma_prep_memcpy;
|
||||
dma->device_issue_pending = ioat1_dma_memcpy_issue_pending;
|
||||
dma->device_alloc_chan_resources = ioat1_dma_alloc_chan_resources;
|
||||
dma->device_free_chan_resources = ioat1_dma_free_chan_resources;
|
||||
dma->device_is_tx_complete = ioat1_dma_is_complete;
|
||||
dma->device_is_tx_complete = ioat_is_dma_complete;
|
||||
|
||||
err = ioat_probe(device);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
* @intr_quirk: interrupt setup quirk (for ioat_v1 devices)
|
||||
* @enumerate_channels: hw version specific channel enumeration
|
||||
* @reset_hw: hw version specific channel (re)initialization
|
||||
* @cleanup_tasklet: select between the v2 and v3 cleanup routines
|
||||
* @cleanup_fn: select between the v2 and v3 cleanup routines
|
||||
* @timer_fn: select between the v2 and v3 timer watchdog routines
|
||||
* @self_test: hardware version specific self test for each supported op type
|
||||
*
|
||||
|
|
@ -80,7 +80,7 @@ struct ioatdma_device {
|
|||
void (*intr_quirk)(struct ioatdma_device *device);
|
||||
int (*enumerate_channels)(struct ioatdma_device *device);
|
||||
int (*reset_hw)(struct ioat_chan_common *chan);
|
||||
void (*cleanup_tasklet)(unsigned long data);
|
||||
void (*cleanup_fn)(unsigned long data);
|
||||
void (*timer_fn)(unsigned long data);
|
||||
int (*self_test)(struct ioatdma_device *device);
|
||||
};
|
||||
|
|
@ -337,17 +337,16 @@ struct dca_provider * __devinit ioat_dca_init(struct pci_dev *pdev,
|
|||
void __iomem *iobase);
|
||||
unsigned long ioat_get_current_completion(struct ioat_chan_common *chan);
|
||||
void ioat_init_channel(struct ioatdma_device *device,
|
||||
struct ioat_chan_common *chan, int idx,
|
||||
void (*timer_fn)(unsigned long),
|
||||
void (*tasklet)(unsigned long),
|
||||
unsigned long ioat);
|
||||
struct ioat_chan_common *chan, int idx);
|
||||
enum dma_status ioat_is_dma_complete(struct dma_chan *c, dma_cookie_t cookie,
|
||||
dma_cookie_t *done, dma_cookie_t *used);
|
||||
void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
|
||||
size_t len, struct ioat_dma_descriptor *hw);
|
||||
bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
|
||||
unsigned long *phys_complete);
|
||||
void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
|
||||
void ioat_kobject_del(struct ioatdma_device *device);
|
||||
extern struct sysfs_ops ioat_sysfs_ops;
|
||||
extern const struct sysfs_ops ioat_sysfs_ops;
|
||||
extern struct ioat_sysfs_entry ioat_version_attr;
|
||||
extern struct ioat_sysfs_entry ioat_cap_attr;
|
||||
#endif /* IOATDMA_H */
|
||||
|
|
|
|||
|
|
@ -51,48 +51,40 @@ MODULE_PARM_DESC(ioat_ring_max_alloc_order,
|
|||
|
||||
void __ioat2_issue_pending(struct ioat2_dma_chan *ioat)
|
||||
{
|
||||
void * __iomem reg_base = ioat->base.reg_base;
|
||||
struct ioat_chan_common *chan = &ioat->base;
|
||||
|
||||
ioat->pending = 0;
|
||||
ioat->dmacount += ioat2_ring_pending(ioat);
|
||||
ioat->issued = ioat->head;
|
||||
/* make descriptor updates globally visible before notifying channel */
|
||||
wmb();
|
||||
writew(ioat->dmacount, reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
|
||||
dev_dbg(to_dev(&ioat->base),
|
||||
writew(ioat->dmacount, chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
|
||||
dev_dbg(to_dev(chan),
|
||||
"%s: head: %#x tail: %#x issued: %#x count: %#x\n",
|
||||
__func__, ioat->head, ioat->tail, ioat->issued, ioat->dmacount);
|
||||
}
|
||||
|
||||
void ioat2_issue_pending(struct dma_chan *chan)
|
||||
void ioat2_issue_pending(struct dma_chan *c)
|
||||
{
|
||||
struct ioat2_dma_chan *ioat = to_ioat2_chan(chan);
|
||||
struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
|
||||
|
||||
spin_lock_bh(&ioat->ring_lock);
|
||||
if (ioat->pending == 1)
|
||||
if (ioat2_ring_pending(ioat)) {
|
||||
spin_lock_bh(&ioat->ring_lock);
|
||||
__ioat2_issue_pending(ioat);
|
||||
spin_unlock_bh(&ioat->ring_lock);
|
||||
spin_unlock_bh(&ioat->ring_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ioat2_update_pending - log pending descriptors
|
||||
* @ioat: ioat2+ channel
|
||||
*
|
||||
* set pending to '1' unless pending is already set to '2', pending == 2
|
||||
* indicates that submission is temporarily blocked due to an in-flight
|
||||
* reset. If we are already above the ioat_pending_level threshold then
|
||||
* just issue pending.
|
||||
*
|
||||
* called with ring_lock held
|
||||
* Check if the number of unsubmitted descriptors has exceeded the
|
||||
* watermark. Called with ring_lock held
|
||||
*/
|
||||
static void ioat2_update_pending(struct ioat2_dma_chan *ioat)
|
||||
{
|
||||
if (unlikely(ioat->pending == 2))
|
||||
return;
|
||||
else if (ioat2_ring_pending(ioat) > ioat_pending_level)
|
||||
if (ioat2_ring_pending(ioat) > ioat_pending_level)
|
||||
__ioat2_issue_pending(ioat);
|
||||
else
|
||||
ioat->pending = 1;
|
||||
}
|
||||
|
||||
static void __ioat2_start_null_desc(struct ioat2_dma_chan *ioat)
|
||||
|
|
@ -166,7 +158,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
|
|||
seen_current = true;
|
||||
}
|
||||
ioat->tail += i;
|
||||
BUG_ON(!seen_current); /* no active descs have written a completion? */
|
||||
BUG_ON(active && !seen_current); /* no active descs have written a completion? */
|
||||
|
||||
chan->last_completion = phys_complete;
|
||||
if (ioat->head == ioat->tail) {
|
||||
|
|
@ -207,9 +199,9 @@ static void ioat2_cleanup(struct ioat2_dma_chan *ioat)
|
|||
spin_unlock_bh(&chan->cleanup_lock);
|
||||
}
|
||||
|
||||
void ioat2_cleanup_tasklet(unsigned long data)
|
||||
void ioat2_cleanup_event(unsigned long data)
|
||||
{
|
||||
struct ioat2_dma_chan *ioat = (void *) data;
|
||||
struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
|
||||
|
||||
ioat2_cleanup(ioat);
|
||||
writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
|
||||
|
|
@ -291,7 +283,7 @@ static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)
|
|||
|
||||
void ioat2_timer_event(unsigned long data)
|
||||
{
|
||||
struct ioat2_dma_chan *ioat = (void *) data;
|
||||
struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
|
||||
struct ioat_chan_common *chan = &ioat->base;
|
||||
|
||||
spin_lock_bh(&chan->cleanup_lock);
|
||||
|
|
@ -397,10 +389,7 @@ int ioat2_enumerate_channels(struct ioatdma_device *device)
|
|||
if (!ioat)
|
||||
break;
|
||||
|
||||
ioat_init_channel(device, &ioat->base, i,
|
||||
device->timer_fn,
|
||||
device->cleanup_tasklet,
|
||||
(unsigned long) ioat);
|
||||
ioat_init_channel(device, &ioat->base, i);
|
||||
ioat->xfercap_log = xfercap_log;
|
||||
spin_lock_init(&ioat->ring_lock);
|
||||
if (device->reset_hw(&ioat->base)) {
|
||||
|
|
@ -546,7 +535,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c)
|
|||
ioat->head = 0;
|
||||
ioat->issued = 0;
|
||||
ioat->tail = 0;
|
||||
ioat->pending = 0;
|
||||
ioat->alloc_order = order;
|
||||
spin_unlock_bh(&ioat->ring_lock);
|
||||
|
||||
|
|
@ -701,7 +689,7 @@ int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_descs)
|
|||
|
||||
mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);
|
||||
spin_unlock_bh(&chan->cleanup_lock);
|
||||
device->timer_fn((unsigned long) ioat);
|
||||
device->timer_fn((unsigned long) &chan->common);
|
||||
} else
|
||||
spin_unlock_bh(&chan->cleanup_lock);
|
||||
return -ENOMEM;
|
||||
|
|
@ -785,7 +773,7 @@ void ioat2_free_chan_resources(struct dma_chan *c)
|
|||
|
||||
tasklet_disable(&chan->cleanup_task);
|
||||
del_timer_sync(&chan->timer);
|
||||
device->cleanup_tasklet((unsigned long) ioat);
|
||||
device->cleanup_fn((unsigned long) c);
|
||||
device->reset_hw(chan);
|
||||
|
||||
spin_lock_bh(&ioat->ring_lock);
|
||||
|
|
@ -815,25 +803,9 @@ void ioat2_free_chan_resources(struct dma_chan *c)
|
|||
|
||||
chan->last_completion = 0;
|
||||
chan->completion_dma = 0;
|
||||
ioat->pending = 0;
|
||||
ioat->dmacount = 0;
|
||||
}
|
||||
|
||||
enum dma_status
|
||||
ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie,
|
||||
dma_cookie_t *done, dma_cookie_t *used)
|
||||
{
|
||||
struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
|
||||
struct ioatdma_device *device = ioat->base.device;
|
||||
|
||||
if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)
|
||||
return DMA_SUCCESS;
|
||||
|
||||
device->cleanup_tasklet((unsigned long) ioat);
|
||||
|
||||
return ioat_is_complete(c, cookie, done, used);
|
||||
}
|
||||
|
||||
static ssize_t ring_size_show(struct dma_chan *c, char *page)
|
||||
{
|
||||
struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
|
||||
|
|
@ -874,7 +846,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca)
|
|||
|
||||
device->enumerate_channels = ioat2_enumerate_channels;
|
||||
device->reset_hw = ioat2_reset_hw;
|
||||
device->cleanup_tasklet = ioat2_cleanup_tasklet;
|
||||
device->cleanup_fn = ioat2_cleanup_event;
|
||||
device->timer_fn = ioat2_timer_event;
|
||||
device->self_test = ioat_dma_self_test;
|
||||
dma = &device->common;
|
||||
|
|
@ -882,7 +854,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca)
|
|||
dma->device_issue_pending = ioat2_issue_pending;
|
||||
dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;
|
||||
dma->device_free_chan_resources = ioat2_free_chan_resources;
|
||||
dma->device_is_tx_complete = ioat2_is_complete;
|
||||
dma->device_is_tx_complete = ioat_is_dma_complete;
|
||||
|
||||
err = ioat_probe(device);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ extern int ioat_ring_alloc_order;
|
|||
* @head: allocated index
|
||||
* @issued: hardware notification point
|
||||
* @tail: cleanup index
|
||||
* @pending: lock free indicator for issued != head
|
||||
* @dmacount: identical to 'head' except for occasionally resetting to zero
|
||||
* @alloc_order: log2 of the number of allocated descriptors
|
||||
* @ring: software ring buffer implementation of hardware ring
|
||||
|
|
@ -61,7 +60,6 @@ struct ioat2_dma_chan {
|
|||
u16 tail;
|
||||
u16 dmacount;
|
||||
u16 alloc_order;
|
||||
int pending;
|
||||
struct ioat_ring_ent **ring;
|
||||
spinlock_t ring_lock;
|
||||
};
|
||||
|
|
@ -178,12 +176,10 @@ ioat2_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest,
|
|||
void ioat2_issue_pending(struct dma_chan *chan);
|
||||
int ioat2_alloc_chan_resources(struct dma_chan *c);
|
||||
void ioat2_free_chan_resources(struct dma_chan *c);
|
||||
enum dma_status ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie,
|
||||
dma_cookie_t *done, dma_cookie_t *used);
|
||||
void __ioat2_restart_chan(struct ioat2_dma_chan *ioat);
|
||||
bool reshape_ring(struct ioat2_dma_chan *ioat, int order);
|
||||
void __ioat2_issue_pending(struct ioat2_dma_chan *ioat);
|
||||
void ioat2_cleanup_tasklet(unsigned long data);
|
||||
void ioat2_cleanup_event(unsigned long data);
|
||||
void ioat2_timer_event(unsigned long data);
|
||||
int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo);
|
||||
int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo);
|
||||
|
|
|
|||
|
|
@ -293,17 +293,25 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
|
|||
}
|
||||
}
|
||||
ioat->tail += i;
|
||||
BUG_ON(!seen_current); /* no active descs have written a completion? */
|
||||
BUG_ON(active && !seen_current); /* no active descs have written a completion? */
|
||||
chan->last_completion = phys_complete;
|
||||
if (ioat->head == ioat->tail) {
|
||||
|
||||
active = ioat2_ring_active(ioat);
|
||||
if (active == 0) {
|
||||
dev_dbg(to_dev(chan), "%s: cancel completion timeout\n",
|
||||
__func__);
|
||||
clear_bit(IOAT_COMPLETION_PENDING, &chan->state);
|
||||
mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT);
|
||||
}
|
||||
/* 5 microsecond delay per pending descriptor */
|
||||
writew(min((5 * active), IOAT_INTRDELAY_MASK),
|
||||
chan->device->reg_base + IOAT_INTRDELAY_OFFSET);
|
||||
}
|
||||
|
||||
static void ioat3_cleanup(struct ioat2_dma_chan *ioat)
|
||||
/* try to cleanup, but yield (via spin_trylock) to incoming submissions
|
||||
* with the expectation that we will immediately poll again shortly
|
||||
*/
|
||||
static void ioat3_cleanup_poll(struct ioat2_dma_chan *ioat)
|
||||
{
|
||||
struct ioat_chan_common *chan = &ioat->base;
|
||||
unsigned long phys_complete;
|
||||
|
|
@ -329,29 +337,41 @@ static void ioat3_cleanup(struct ioat2_dma_chan *ioat)
|
|||
spin_unlock_bh(&chan->cleanup_lock);
|
||||
}
|
||||
|
||||
static void ioat3_cleanup_tasklet(unsigned long data)
|
||||
/* run cleanup now because we already delayed the interrupt via INTRDELAY */
|
||||
static void ioat3_cleanup_sync(struct ioat2_dma_chan *ioat)
|
||||
{
|
||||
struct ioat2_dma_chan *ioat = (void *) data;
|
||||
struct ioat_chan_common *chan = &ioat->base;
|
||||
unsigned long phys_complete;
|
||||
|
||||
ioat3_cleanup(ioat);
|
||||
writew(IOAT_CHANCTRL_RUN | IOAT3_CHANCTRL_COMPL_DCA_EN,
|
||||
ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
|
||||
prefetch(chan->completion);
|
||||
|
||||
spin_lock_bh(&chan->cleanup_lock);
|
||||
if (!ioat_cleanup_preamble(chan, &phys_complete)) {
|
||||
spin_unlock_bh(&chan->cleanup_lock);
|
||||
return;
|
||||
}
|
||||
spin_lock_bh(&ioat->ring_lock);
|
||||
|
||||
__cleanup(ioat, phys_complete);
|
||||
|
||||
spin_unlock_bh(&ioat->ring_lock);
|
||||
spin_unlock_bh(&chan->cleanup_lock);
|
||||
}
|
||||
|
||||
static void ioat3_cleanup_event(unsigned long data)
|
||||
{
|
||||
struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
|
||||
|
||||
ioat3_cleanup_sync(ioat);
|
||||
writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
|
||||
}
|
||||
|
||||
static void ioat3_restart_channel(struct ioat2_dma_chan *ioat)
|
||||
{
|
||||
struct ioat_chan_common *chan = &ioat->base;
|
||||
unsigned long phys_complete;
|
||||
u32 status;
|
||||
|
||||
status = ioat_chansts(chan);
|
||||
if (is_ioat_active(status) || is_ioat_idle(status))
|
||||
ioat_suspend(chan);
|
||||
while (is_ioat_active(status) || is_ioat_idle(status)) {
|
||||
status = ioat_chansts(chan);
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
ioat2_quiesce(chan, 0);
|
||||
if (ioat_cleanup_preamble(chan, &phys_complete))
|
||||
__cleanup(ioat, phys_complete);
|
||||
|
||||
|
|
@ -360,7 +380,7 @@ static void ioat3_restart_channel(struct ioat2_dma_chan *ioat)
|
|||
|
||||
static void ioat3_timer_event(unsigned long data)
|
||||
{
|
||||
struct ioat2_dma_chan *ioat = (void *) data;
|
||||
struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
|
||||
struct ioat_chan_common *chan = &ioat->base;
|
||||
|
||||
spin_lock_bh(&chan->cleanup_lock);
|
||||
|
|
@ -426,7 +446,7 @@ ioat3_is_complete(struct dma_chan *c, dma_cookie_t cookie,
|
|||
if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)
|
||||
return DMA_SUCCESS;
|
||||
|
||||
ioat3_cleanup(ioat);
|
||||
ioat3_cleanup_poll(ioat);
|
||||
|
||||
return ioat_is_complete(c, cookie, done, used);
|
||||
}
|
||||
|
|
@ -1239,11 +1259,11 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
|
|||
|
||||
if (is_raid_device) {
|
||||
dma->device_is_tx_complete = ioat3_is_complete;
|
||||
device->cleanup_tasklet = ioat3_cleanup_tasklet;
|
||||
device->cleanup_fn = ioat3_cleanup_event;
|
||||
device->timer_fn = ioat3_timer_event;
|
||||
} else {
|
||||
dma->device_is_tx_complete = ioat2_is_complete;
|
||||
device->cleanup_tasklet = ioat2_cleanup_tasklet;
|
||||
dma->device_is_tx_complete = ioat_is_dma_complete;
|
||||
device->cleanup_fn = ioat2_cleanup_event;
|
||||
device->timer_fn = ioat2_timer_event;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
#define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */
|
||||
|
||||
#define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */
|
||||
#define IOAT_INTRDELAY_INT_DELAY_MASK 0x3FFF /* Interrupt Delay Time */
|
||||
#define IOAT_INTRDELAY_MASK 0x3FFF /* Interrupt Delay Time */
|
||||
#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalescing Supported */
|
||||
|
||||
#define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue