aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2008-08-27 15:29:46 +1000
committerSimon Horman <horms@verge.net.au>2008-08-27 15:29:46 +1000
commit09bf825e8e3049db1d72d464d0a6b857cc037a43 (patch)
tree0a6fb6c4992c18fbfc8a7df9a4059c36050a0a62 /drivers
parente3c2ced8d21410e8bc897480081e2ffc516c0f70 (diff)
parentc2d42545774c4bba7232521d836d0793330e3a4e (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/dock.c11
-rw-r--r--drivers/acpi/ec.c36
-rw-r--r--drivers/acpi/executer/exconfig.c3
-rw-r--r--drivers/acpi/namespace/nsnames.c34
-rw-r--r--drivers/acpi/pci_link.c12
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/processor_idle.c1
-rw-r--r--drivers/acpi/processor_perflib.c2
-rw-r--r--drivers/acpi/resources/rscalc.c3
-rw-r--r--drivers/acpi/utilities/utalloc.c8
-rw-r--r--drivers/acpi/utilities/utdelete.c13
-rw-r--r--drivers/acpi/utilities/utobject.c13
-rw-r--r--drivers/acpi/wmi.c2
-rw-r--r--drivers/block/brd.c2
-rw-r--r--drivers/block/nbd.c10
-rw-r--r--drivers/bluetooth/Kconfig10
-rw-r--r--drivers/bluetooth/bt3c_cs.c2
-rw-r--r--drivers/bluetooth/btusb.c282
-rw-r--r--drivers/bluetooth/hci_ldisc.c2
-rw-r--r--drivers/bluetooth/hci_usb.c2
-rw-r--r--drivers/bluetooth/hci_vhci.c2
-rw-r--r--drivers/cdrom/cdrom.c7
-rw-r--r--drivers/cdrom/gdrom.c7
-rw-r--r--drivers/cdrom/viocd.c7
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c8
-rw-r--r--drivers/char/pcmcia/ipwireless/tty.c1
-rw-r--r--drivers/char/synclink_gt.c1
-rw-r--r--drivers/char/tty_io.c72
-rw-r--r--drivers/char/vt.c82
-rw-r--r--drivers/char/vt_ioctl.c4
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c1
-rw-r--r--drivers/cpuidle/governors/ladder.c26
-rw-r--r--drivers/cpuidle/governors/menu.c42
-rw-r--r--drivers/dma/mv_xor.c2
-rw-r--r--drivers/firewire/Kconfig4
-rw-r--r--drivers/hid/usbhid/hid-quirks.c12
-rw-r--r--drivers/hwmon/Kconfig16
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/abituguru3.c134
-rw-r--r--drivers/hwmon/adcxx.c329
-rw-r--r--drivers/hwmon/applesmc.c20
-rw-r--r--drivers/hwmon/coretemp.c5
-rw-r--r--drivers/hwmon/hwmon-vid.c36
-rw-r--r--drivers/hwmon/i5k_amb.c28
-rw-r--r--drivers/hwmon/ibmaem.c27
-rw-r--r--drivers/hwmon/w83791d.c3
-rw-r--r--drivers/ide/ide-cd.c20
-rw-r--r--drivers/ide/pci/aec62xx.c2
-rw-r--r--drivers/ide/pci/cy82c693.c2
-rw-r--r--drivers/ide/pci/hpt366.c2
-rw-r--r--drivers/ide/pci/it821x.c2
-rw-r--r--drivers/ide/pci/pdc202xx_new.c2
-rw-r--r--drivers/ide/pci/scc_pata.c2
-rw-r--r--drivers/ide/pci/sgiioc4.c4
-rw-r--r--drivers/ide/pci/siimage.c2
-rw-r--r--drivers/ide/pci/sis5513.c2
-rw-r--r--drivers/ide/pci/tc86c001.c2
-rw-r--r--drivers/ide/pci/via82cxxx.c2
-rw-r--r--drivers/ieee1394/nodemgr.c63
-rw-r--r--drivers/ieee1394/nodemgr.h2
-rw-r--r--drivers/ieee1394/sbp2.c25
-rw-r--r--drivers/input/evdev.c63
-rw-r--r--drivers/input/joystick/xpad.c1
-rw-r--r--drivers/input/keyboard/gpio_keys.c4
-rw-r--r--drivers/input/misc/cobalt_btns.c3
-rw-r--r--drivers/input/mouse/Kconfig23
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/bcm5974.c681
-rw-r--r--drivers/input/mouse/gpio_mouse.c1
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h7
-rw-r--r--drivers/input/serio/xilinx_ps2.c4
-rw-r--r--drivers/input/tablet/gtco.c1
-rw-r--r--drivers/input/touchscreen/Kconfig21
-rw-r--r--drivers/input/touchscreen/migor_ts.c11
-rw-r--r--drivers/input/touchscreen/wm9705.c1
-rw-r--r--drivers/input/touchscreen/wm9712.c1
-rw-r--r--drivers/input/touchscreen/wm9713.c1
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c1
-rw-r--r--drivers/md/md.c33
-rw-r--r--drivers/md/raid10.c9
-rw-r--r--drivers/md/raid5.c32
-rw-r--r--drivers/misc/acer-wmi.c19
-rw-r--r--drivers/misc/eeepc-laptop.c2
-rw-r--r--drivers/mmc/host/s3cmci.c17
-rw-r--r--drivers/mmc/host/sdricoh_cs.c1
-rw-r--r--drivers/mtd/nand/orion_nand.c2
-rw-r--r--drivers/net/bnx2x.h2
-rw-r--r--drivers/net/bnx2x_main.c220
-rw-r--r--drivers/of/device.c10
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c38
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c7
-rw-r--r--drivers/pci/probe.c3
-rw-r--r--drivers/pci/setup-bus.c35
-rw-r--r--drivers/pcmcia/pxa2xx_palmtx.c49
-rw-r--r--drivers/rtc/Kconfig2
-rw-r--r--drivers/rtc/rtc-bfin.c60
-rw-r--r--drivers/rtc/rtc-dev.c5
-rw-r--r--drivers/rtc/rtc-ds1374.c10
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c3
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c37
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h4
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c119
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h10
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c11
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c14
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c18
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/serial/Kconfig1
-rw-r--r--drivers/spi/spi.c40
-rw-r--r--drivers/usb/host/ehci-orion.c2
-rw-r--r--drivers/video/bf54x-lq043fb.c15
-rw-r--r--drivers/video/fb_defio.c19
-rw-r--r--drivers/video/fbmem.c4
-rw-r--r--drivers/video/fsl-diu-fb.c32
-rw-r--r--drivers/video/pm2fb.c1
-rw-r--r--drivers/video/pxafb.c68
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c2
-rw-r--r--drivers/watchdog/s3c2410_wdt.c2
122 files changed, 2653 insertions, 606 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index bb7c51f712b..7d2edf143f1 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -563,9 +563,6 @@ EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
*/
static int handle_eject_request(struct dock_station *ds, u32 event)
{
- if (!dock_present(ds))
- return -ENODEV;
-
if (dock_in_progress(ds))
return -EBUSY;
@@ -573,8 +570,16 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
* here we need to generate the undock
* event prior to actually doing the undock
* so that the device struct still exists.
+ * Also, even send the dock event if the
+ * device is not present anymore
*/
dock_event(ds, event, UNDOCK_EVENT);
+
+ if (!dock_present(ds)) {
+ complete_undock(ds);
+ return -ENODEV;
+ }
+
hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
undock(ds);
eject_dock(ds);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 5622aee996b..13593f9f219 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -110,6 +110,31 @@ static struct acpi_ec {
u8 handlers_installed;
} *boot_ec, *first_ec;
+/*
+ * Some Asus system have exchanged ECDT data/command IO addresses.
+ */
+static int print_ecdt_error(const struct dmi_system_id *id)
+{
+ printk(KERN_NOTICE PREFIX "%s detected - "
+ "ECDT has exchanged control/data I/O address\n",
+ id->ident);
+ return 0;
+}
+
+static struct dmi_system_id __cpuinitdata ec_dmi_table[] = {
+ {
+ print_ecdt_error, "Asus L4R", {
+ DMI_MATCH(DMI_BIOS_VERSION, "1008.006"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),
+ DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL},
+ {
+ print_ecdt_error, "Asus M6R", {
+ DMI_MATCH(DMI_BIOS_VERSION, "0207"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M6R"),
+ DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL},
+ {},
+};
+
/* --------------------------------------------------------------------------
Transaction Management
-------------------------------------------------------------------------- */
@@ -196,6 +221,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
return 0;
msleep(1);
}
+ if (acpi_ec_check_status(ec,event))
+ return 0;
}
pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n",
acpi_ec_read_status(ec),
@@ -911,6 +938,15 @@ int __init acpi_ec_ecdt_probe(void)
pr_info(PREFIX "EC description table is found, configuring boot EC\n");
boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address;
+ if (dmi_check_system(ec_dmi_table)) {
+ /*
+ * If the board falls into ec_dmi_table, it means
+ * that ECDT table gives the incorrect command/status
+ * & data I/O address. Just fix it.
+ */
+ boot_ec->data_addr = ecdt_ptr->control.address;
+ boot_ec->command_addr = ecdt_ptr->data.address;
+ }
boot_ec->gpe = ecdt_ptr->gpe;
boot_ec->handle = ACPI_ROOT_OBJECT;
acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle);
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 2a32c843cb4..8892b9824fa 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -479,5 +479,8 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
acpi_tb_set_table_loaded_flag(table_index, FALSE);
+ /* Table unloaded, remove a reference to the ddb_handle object */
+
+ acpi_ut_remove_reference(ddb_handle);
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index 549db42f16c..bd577387800 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -56,13 +56,14 @@ ACPI_MODULE_NAME("nsnames")
* Size - Size of the pathname
* *name_buffer - Where to return the pathname
*
- * RETURN: Places the pathname into the name_buffer, in external format
+ * RETURN: Status
+ * Places the pathname into the name_buffer, in external format
* (name segments separated by path separators)
*
* DESCRIPTION: Generate a full pathaname
*
******************************************************************************/
-void
+acpi_status
acpi_ns_build_external_path(struct acpi_namespace_node *node,
acpi_size size, char *name_buffer)
{
@@ -77,7 +78,7 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
if (index < ACPI_NAME_SIZE) {
name_buffer[0] = AML_ROOT_PREFIX;
name_buffer[1] = 0;
- return;
+ return (AE_OK);
}
/* Store terminator byte, then build name backwards */
@@ -105,11 +106,13 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
if (index != 0) {
ACPI_ERROR((AE_INFO,
- "Could not construct pathname; index=%X, size=%X, Path=%s",
+ "Could not construct external pathname; index=%X, size=%X, Path=%s",
(u32) index, (u32) size, &name_buffer[size]));
+
+ return (AE_BAD_PARAMETER);
}
- return;
+ return (AE_OK);
}
#ifdef ACPI_DEBUG_OUTPUT
@@ -129,6 +132,7 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
{
+ acpi_status status;
char *name_buffer;
acpi_size size;
@@ -138,8 +142,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
size = acpi_ns_get_pathname_length(node);
if (!size) {
- ACPI_ERROR((AE_INFO, "Invalid node failure"));
- return_PTR(NULL);
+ return (NULL);
}
/* Allocate a buffer to be returned to caller */
@@ -152,7 +155,11 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
/* Build the path in the allocated buffer */
- acpi_ns_build_external_path(node, size, name_buffer);
+ status = acpi_ns_build_external_path(node, size, name_buffer);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
return_PTR(name_buffer);
}
#endif
@@ -186,7 +193,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
while (next_node && (next_node != acpi_gbl_root_node)) {
if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) {
ACPI_ERROR((AE_INFO,
- "Invalid NS Node (%p) while traversing path",
+ "Invalid Namespace Node (%p) while traversing namespace",
next_node));
return 0;
}
@@ -234,8 +241,7 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
required_size = acpi_ns_get_pathname_length(node);
if (!required_size) {
- ACPI_ERROR((AE_INFO, "Invalid node failure"));
- return_ACPI_STATUS(AE_ERROR);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Validate/Allocate/Clear caller buffer */
@@ -247,7 +253,11 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
/* Build the path in the caller buffer */
- acpi_ns_build_external_path(node, required_size, buffer->pointer);
+ status =
+ acpi_ns_build_external_path(node, required_size, buffer->pointer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n",
(char *)buffer->pointer, (u32) required_size));
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 89f3b2abfdc..cf47805a744 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -849,7 +849,7 @@ static int __init acpi_irq_penalty_update(char *str, int used)
if (irq < 0)
continue;
- if (irq >= ACPI_MAX_IRQS)
+ if (irq >= ARRAY_SIZE(acpi_irq_penalty))
continue;
if (used)
@@ -872,10 +872,12 @@ static int __init acpi_irq_penalty_update(char *str, int used)
*/
void acpi_penalize_isa_irq(int irq, int active)
{
- if (active)
- acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
- else
- acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
+ if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
+ if (active)
+ acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
+ else
+ acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
+ }
}
/*
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index e36422a7122..d3f0a62efcc 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -123,7 +123,7 @@ struct acpi_processor_errata errata __read_mostly;
static int set_no_mwait(const struct dmi_system_id *id)
{
printk(KERN_NOTICE PREFIX "%s detected - "
- "disable mwait for CPU C-stetes\n", id->ident);
+ "disabling mwait for CPU C-states\n", id->ident);
idle_nomwait = 1;
return 0;
}
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 283c08f5f4d..cf5b1b7b684 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -41,7 +41,6 @@
#include <linux/pm_qos_params.h>
#include <linux/clockchips.h>
#include <linux/cpuidle.h>
-#include <linux/cpuidle.h>
/*
* Include the apic definitions for x86 to have the APIC timer related defines
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 0133af49cf0..80e32093e97 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -70,7 +70,7 @@ static DEFINE_MUTEX(performance_mutex);
* 0 -> cpufreq low level drivers initialized -> consider _PPC values
* 1 -> ignore _PPC totally -> forced by user through boot param
*/
-static unsigned int ignore_ppc = -1;
+static int ignore_ppc = -1;
module_param(ignore_ppc, uint, 0644);
MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
"limited by BIOS, this should help");
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index f61ebc679e6..d9063ea414e 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -587,6 +587,9 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
} else {
temp_size_needed +=
acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
+ if (!temp_size_needed) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
}
} else {
/*
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index e7bf34a7b1d..7dcb67e0b21 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -242,10 +242,12 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
{
acpi_status status = AE_OK;
- if (!required_length) {
- WARN_ON(1);
- return AE_ERROR;
+ /* Parameter validation */
+
+ if (!buffer || !required_length) {
+ return (AE_BAD_PARAMETER);
}
+
switch (buffer->length) {
case ACPI_NO_BUFFER:
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index c5c791a575c..42609d3a8aa 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -135,6 +135,10 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
obj_pointer = object->package.elements;
break;
+ /*
+ * These objects have a possible list of notify handlers.
+ * Device object also may have a GPE block.
+ */
case ACPI_TYPE_DEVICE:
if (object->device.gpe_block) {
@@ -142,9 +146,14 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
gpe_block);
}
- /* Walk the handler list for this device */
+ /*lint -fallthrough */
+
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_THERMAL:
+
+ /* Walk the notify handler list for this object */
- handler_desc = object->device.handler;
+ handler_desc = object->common_notify.handler;
while (handler_desc) {
next_desc = handler_desc->address_space.next;
acpi_ut_remove_reference(handler_desc);
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index e25484495e6..916eff399eb 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -425,6 +425,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
acpi_size * obj_length)
{
acpi_size length;
+ acpi_size size;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object);
@@ -484,10 +485,14 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
* Get the actual length of the full pathname to this object.
* The reference will be converted to the pathname to the object
*/
- length +=
- ACPI_ROUND_UP_TO_NATIVE_WORD
- (acpi_ns_get_pathname_length
- (internal_object->reference.node));
+ size =
+ acpi_ns_get_pathname_length(internal_object->
+ reference.node);
+ if (!size) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ length += ACPI_ROUND_UP_TO_NATIVE_WORD(size);
break;
default:
diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c
index c33b1c6e93b..cfe2c833474 100644
--- a/drivers/acpi/wmi.c
+++ b/drivers/acpi/wmi.c
@@ -347,7 +347,7 @@ struct acpi_buffer *out)
strcpy(method, "WQ");
strncat(method, block->object_id, 2);
- status = acpi_evaluate_object(handle, method, NULL, out);
+ status = acpi_evaluate_object(handle, method, &input, out);
/*
* If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 24b97b0bef9..d070d492e38 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -571,8 +571,8 @@ out_free:
list_del(&brd->brd_list);
brd_free(brd);
}
+ unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
- unregister_blkdev(RAMDISK_MAJOR, "brd");
return -ENOMEM;
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index ad98dda6037..1778e4a2c67 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -707,15 +707,15 @@ static int __init nbd_init(void)
BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
- nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
- if (!nbd_dev)
- return -ENOMEM;
-
if (max_part < 0) {
printk(KERN_CRIT "nbd: max_part must be >= 0\n");
return -EINVAL;
}
+ nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
+ if (!nbd_dev)
+ return -ENOMEM;
+
part_shift = 0;
if (max_part > 0)
part_shift = fls(max_part);
@@ -779,6 +779,7 @@ out:
blk_cleanup_queue(nbd_dev[i].disk->queue);
put_disk(nbd_dev[i].disk);
}
+ kfree(nbd_dev);
return err;
}
@@ -795,6 +796,7 @@ static void __exit nbd_cleanup(void)
}
}
unregister_blkdev(NBD_MAJOR, "nbd");
+ kfree(nbd_dev);
printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR);
}
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index a235ca78746..7cb4029a537 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -3,8 +3,8 @@ menu "Bluetooth device drivers"
depends on BT
config BT_HCIUSB
- tristate "HCI USB driver"
- depends on USB
+ tristate "HCI USB driver (old version)"
+ depends on USB && BT_HCIBTUSB=n
help
Bluetooth HCI USB driver.
This driver is required if you want to use Bluetooth devices with
@@ -23,15 +23,13 @@ config BT_HCIUSB_SCO
Say Y here to compile support for SCO over HCI USB.
config BT_HCIBTUSB
- tristate "HCI USB driver (alternate version)"
- depends on USB && EXPERIMENTAL && BT_HCIUSB=n
+ tristate "HCI USB driver"
+ depends on USB
help
Bluetooth HCI USB driver.
This driver is required if you want to use Bluetooth devices with
USB interface.
- This driver is still experimental and has no SCO support.
-
Say Y here to compile support for Bluetooth USB devices into the
kernel or say M to compile it as module (btusb).
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 593b7c59503..27058477cc8 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -60,7 +60,7 @@
/* ======================== Module parameters ======================== */
-MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>");
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("BT3CPCC.bin");
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 95ae9ba5661..6a010681ecf 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2,7 +2,7 @@
*
* Generic Bluetooth USB driver
*
- * Copyright (C) 2005-2007 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@
#define BT_DBG(D...)
#endif
-#define VERSION "0.2"
+#define VERSION "0.3"
static int ignore_dga;
static int ignore_csr;
@@ -160,12 +160,16 @@ static struct usb_device_id blacklist_table[] = {
{ } /* Terminating entry */
};
+#define BTUSB_MAX_ISOC_FRAMES 10
+
#define BTUSB_INTR_RUNNING 0
#define BTUSB_BULK_RUNNING 1
+#define BTUSB_ISOC_RUNNING 2
struct btusb_data {
struct hci_dev *hdev;
struct usb_device *udev;
+ struct usb_interface *isoc;
spinlock_t lock;
@@ -176,10 +180,15 @@ struct btusb_data {
struct usb_anchor tx_anchor;
struct usb_anchor intr_anchor;
struct usb_anchor bulk_anchor;
+ struct usb_anchor isoc_anchor;
struct usb_endpoint_descriptor *intr_ep;
struct usb_endpoint_descriptor *bulk_tx_ep;
struct usb_endpoint_descriptor *bulk_rx_ep;
+ struct usb_endpoint_descriptor *isoc_tx_ep;
+ struct usb_endpoint_descriptor *isoc_rx_ep;
+
+ int isoc_altsetting;
};
static void btusb_intr_complete(struct urb *urb)
@@ -195,6 +204,8 @@ static void btusb_intr_complete(struct urb *urb)
return;
if (urb->status == 0) {
+ hdev->stat.byte_rx += urb->actual_length;
+
if (hci_recv_fragment(hdev, HCI_EVENT_PKT,
urb->transfer_buffer,
urb->actual_length) < 0) {
@@ -216,7 +227,7 @@ static void btusb_intr_complete(struct urb *urb)
}
}
-static inline int btusb_submit_intr_urb(struct hci_dev *hdev)
+static int btusb_submit_intr_urb(struct hci_dev *hdev)
{
struct btusb_data *data = hdev->driver_data;
struct urb *urb;
@@ -226,6 +237,9 @@ static inline int btusb_submit_intr_urb(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
+ if (!data->intr_ep)
+ return -ENODEV;
+
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
@@ -274,6 +288,8 @@ static void btusb_bulk_complete(struct urb *urb)
return;
if (urb->status == 0) {
+ hdev->stat.byte_rx += urb->actual_length;
+
if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT,
urb->transfer_buffer,
urb->actual_length) < 0) {
@@ -295,7 +311,7 @@ static void btusb_bulk_complete(struct urb *urb)
}
}
-static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
+static int btusb_submit_bulk_urb(struct hci_dev *hdev)
{
struct btusb_data *data = hdev->driver_data;
struct urb *urb;
@@ -305,6 +321,9 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
+ if (!data->bulk_rx_ep)
+ return -ENODEV;
+
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return -ENOMEM;
@@ -339,6 +358,127 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
return err;
}
+static void btusb_isoc_complete(struct urb *urb)
+{
+ struct hci_dev *hdev = urb->context;
+ struct btusb_data *data = hdev->driver_data;
+ int i, err;
+
+ BT_DBG("%s urb %p status %d count %d", hdev->name,
+ urb, urb->status, urb->actual_length);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return;
+
+ if (urb->status == 0) {
+ for (i = 0; i < urb->number_of_packets; i++) {
+ unsigned int offset = urb->iso_frame_desc[i].offset;
+ unsigned int length = urb->iso_frame_desc[i].actual_length;
+
+ if (urb->iso_frame_desc[i].status)
+ continue;
+
+ hdev->stat.byte_rx += length;
+
+ if (hci_recv_fragment(hdev, HCI_SCODATA_PKT,
+ urb->transfer_buffer + offset,
+ length) < 0) {
+ BT_ERR("%s corrupted SCO packet", hdev->name);
+ hdev->stat.err_rx++;
+ }
+ }
+ }
+
+ if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags))
+ return;
+
+ usb_anchor_urb(urb, &data->isoc_anchor);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ BT_ERR("%s urb %p failed to resubmit (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
+ }
+}
+
+static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
+{
+ int i, offset = 0;
+
+ BT_DBG("len %d mtu %d", len, mtu);
+
+ for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu;
+ i++, offset += mtu, len -= mtu) {
+ urb->iso_frame_desc[i].offset = offset;
+ urb->iso_frame_desc[i].length = mtu;
+ }
+
+ if (len && i < BTUSB_MAX_ISOC_FRAMES) {
+ urb->iso_frame_desc[i].offset = offset;
+ urb->iso_frame_desc[i].length = len;
+ i++;
+ }
+
+ urb->number_of_packets = i;
+}
+
+static int btusb_submit_isoc_urb(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hdev->driver_data;
+ struct urb *urb;
+ unsigned char *buf;
+ unsigned int pipe;
+ int err, size;
+
+ BT_DBG("%s", hdev->name);
+
+ if (!data->isoc_rx_ep)
+ return -ENODEV;
+
+ urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
+ if (!urb)
+ return -ENOMEM;
+
+ size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) *
+ BTUSB_MAX_ISOC_FRAMES;
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
+
+ urb->dev = data->udev;
+ urb->pipe = pipe;
+ urb->context = hdev;
+ urb->complete = btusb_isoc_complete;
+ urb->interval = data->isoc_rx_ep->bInterval;
+
+ urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
+ urb->transfer_buffer = buf;
+ urb->transfer_buffer_length = size;
+
+ __fill_isoc_descriptor(urb, size,
+ le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
+
+ usb_anchor_urb(urb, &data->isoc_anchor);
+
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err < 0) {
+ BT_ERR("%s urb %p submission failed (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
+ kfree(buf);
+ }
+
+ usb_free_urb(urb);
+
+ return err;
+}
+
static void btusb_tx_complete(struct urb *urb)
{
struct sk_buff *skb = urb->context;
@@ -392,6 +532,9 @@ static int btusb_close(struct hci_dev *hdev)
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ usb_kill_anchored_urbs(&data->intr_anchor);
+
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
usb_kill_anchored_urbs(&data->bulk_anchor);
@@ -453,6 +596,9 @@ static int btusb_send_frame(struct sk_buff *skb)
break;
case HCI_ACLDATA_PKT:
+ if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1)
+ return -ENODEV;
+
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
@@ -467,9 +613,31 @@ static int btusb_send_frame(struct sk_buff *skb)
break;
case HCI_SCODATA_PKT:
+ if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1)
+ return -ENODEV;
+
+ urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC);
+ if (!urb)
+ return -ENOMEM;
+
+ pipe = usb_sndisocpipe(data->udev,
+ data->isoc_tx_ep->bEndpointAddress);
+
+ urb->dev = data->udev;
+ urb->pipe = pipe;
+ urb->context = skb;
+ urb->complete = btusb_tx_complete;
+ urb->interval = data->isoc_tx_ep->bInterval;
+
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->transfer_buffer = skb->data;
+ urb->transfer_buffer_length = skb->len;
+
+ __fill_isoc_descriptor(urb, skb->len,
+ le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
+
hdev->stat.sco_tx++;
- kfree_skb(skb);
- return 0;
+ break;
default:
return -EILSEQ;
@@ -508,22 +676,86 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
schedule_work(&data->work);
}
+static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting)
+{
+ struct btusb_data *data = hdev->driver_data;
+ struct usb_interface *intf = data->isoc;
+ struct usb_endpoint_descriptor *ep_desc;
+ int i, err;
+
+ if (!data->isoc)
+ return -ENODEV;
+
+ err = usb_set_interface(data->udev, 1, altsetting);
+ if (err < 0) {
+ BT_ERR("%s setting interface failed (%d)", hdev->name, -err);
+ return err;
+ }
+
+ data->isoc_altsetting = altsetting;
+
+ data->isoc_tx_ep = NULL;
+ data->isoc_rx_ep = NULL;
+
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+ ep_desc = &intf->cur_altsetting->endpoint[i].desc;
+
+ if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) {
+ data->isoc_tx_ep = ep_desc;
+ continue;
+ }
+
+ if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) {
+ data->isoc_rx_ep = ep_desc;
+ continue;
+ }
+ }
+
+ if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
+ BT_ERR("%s invalid SCO descriptors", hdev->name);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static void btusb_work(struct work_struct *work)
{
struct btusb_data *data = container_of(work, struct btusb_data, work);
struct hci_dev *hdev = data->hdev;
- if (hdev->conn_hash.acl_num == 0) {
+ if (hdev->conn_hash.acl_num > 0) {
+ if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
+ if (btusb_submit_bulk_urb(hdev) < 0)
+ clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+ else
+ btusb_submit_bulk_urb(hdev);
+ }
+ } else {
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
usb_kill_anchored_urbs(&data->bulk_anchor);
- return;
}
- if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
- if (btusb_submit_bulk_urb(hdev) < 0)
- clear_bit(BTUSB_BULK_RUNNING, &data->flags);
- else
- btusb_submit_bulk_urb(hdev);
+ if (hdev->conn_hash.sco_num > 0) {
+ if (data->isoc_altsetting != 2) {
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ usb_kill_anchored_urbs(&data->isoc_anchor);
+
+ if (__set_isoc_interface(hdev, 2) < 0)
+ return;
+ }
+
+ if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+ if (btusb_submit_isoc_urb(hdev) < 0)
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ else
+ btusb_submit_isoc_urb(hdev);
+ }
+ } else {
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ usb_kill_anchored_urbs(&data->isoc_anchor);
+
+ __set_isoc_interface(hdev, 0);
}
}
@@ -597,6 +829,7 @@ static int btusb_probe(struct usb_interface *intf,
init_usb_anchor(&data->tx_anchor);
init_usb_anchor(&data->intr_anchor);
init_usb_anchor(&data->bulk_anchor);
+ init_usb_anchor(&data->isoc_anchor);
hdev = hci_alloc_dev();
if (!hdev) {
@@ -620,6 +853,9 @@ static int btusb_probe(struct usb_interface *intf,
hdev->owner = THIS_MODULE;
+ /* interface numbers are hardcoded in the spec */
+ data->isoc = usb_ifnum_to_if(data->udev, 1);
+
if (reset || id->driver_info & BTUSB_RESET)
set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
@@ -628,11 +864,16 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
}
+ if (id->driver_info & BTUSB_BROKEN_ISOC)
+ data->isoc = NULL;
+
if (id->driver_info & BTUSB_SNIFFER) {
- struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_device *udev = data->udev;
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+
+ data->isoc = NULL;
}
if (id->driver_info & BTUSB_BCM92035) {
@@ -646,6 +887,16 @@ static int btusb_probe(struct usb_interface *intf,
}
}
+ if (data->isoc) {
+ err = usb_driver_claim_interface(&btusb_driver,
+ data->isoc, NULL);
+ if (err < 0) {
+ hci_free_dev(hdev);
+ kfree(data);
+ return err;
+ }
+ }
+
err = hci_register_dev(hdev);
if (err < 0) {
hci_free_dev(hdev);
@@ -670,6 +921,9 @@ static void btusb_disconnect(struct usb_interface *intf)
hdev = data->hdev;
+ if (data->isoc)
+ usb_driver_release_interface(&btusb_driver, data->isoc);
+
usb_set_intfdata(intf, NULL);
hci_unregister_dev(hdev);
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 69df187d74c..8dfcf77cb71 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -577,7 +577,7 @@ module_exit(hci_uart_exit);
module_param(reset, bool, 0644);
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
-MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index e397572bf57..3c453924f83 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -1130,7 +1130,7 @@ module_param(isoc, int, 0644);
MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support");
#endif
-MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index d97700aa54a..7320a71b636 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -377,7 +377,7 @@ module_exit(vhci_exit);
module_param(minor, int, 0444);
MODULE_PARM_DESC(minor, "Miscellaneous minor device number");
-MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index d9d1b65d206..74031de517e 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -408,7 +408,6 @@ int register_cdrom(struct cdrom_device_info *cdi)
ENSURE(get_last_session, CDC_MULTI_SESSION);
ENSURE(get_mcn, CDC_MCN);
ENSURE(reset, CDC_RESET);
- ENSURE(audio_ioctl, CDC_PLAY_AUDIO);
ENSURE(generic_packet, CDC_GENERIC_PACKET);
cdi->mc_flags = 0;
cdo->n_minors = 0;
@@ -2506,8 +2505,6 @@ static int cdrom_ioctl_get_subchnl(struct cdrom_device_info *cdi,
/* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/
- if (!CDROM_CAN(CDC_PLAY_AUDIO))
- return -ENOSYS;
if (copy_from_user(&q, argp, sizeof(q)))
return -EFAULT;
@@ -2538,8 +2535,6 @@ static int cdrom_ioctl_read_tochdr(struct cdrom_device_info *cdi,
/* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */
- if (!CDROM_CAN(CDC_PLAY_AUDIO))
- return -ENOSYS;
if (copy_from_user(&header, argp, sizeof(header)))
return -EFAULT;
@@ -2562,8 +2557,6 @@ static int cdrom_ioctl_read_tocentry(struct cdrom_device_info *cdi,
/* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */
- if (!CDROM_CAN(CDC_PLAY_AUDIO))
- return -ENOSYS;
if (copy_from_user(&entry, argp, sizeof(entry)))
return -EFAULT;
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 1e0455bd6df..1231d95aa69 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -471,6 +471,12 @@ cleanup_sense_final:
return err;
}
+static int gdrom_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
+ void *arg)
+{
+ return -EINVAL;
+}
+
static struct cdrom_device_ops gdrom_ops = {
.open = gdrom_open,
.release = gdrom_release,
@@ -478,6 +484,7 @@ static struct cdrom_device_ops gdrom_ops = {
.media_changed = gdrom_mediachanged,
.get_last_session = gdrom_get_last_session,
.reset = gdrom_hardreset,
+ .audio_ioctl = gdrom_audio_ioctl,
.capability = CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R,
.n_minors = 1,
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 9d0dfe6e0d6..031e0e1a1a3 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -550,12 +550,19 @@ return_complete:
}
}
+static int viocd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
+ void *arg)
+{
+ return -EINVAL;
+}
+
static struct cdrom_device_ops viocd_dops = {
.open = viocd_open,
.release = viocd_release,
.media_changed = viocd_media_changed,
.lock_door = viocd_lock_door,
.generic_packet = viocd_packet,
+ .audio_ioctl = viocd_audio_ioctl,
.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM
};
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index f52931e1c16..8e8afb6141f 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2695,15 +2695,13 @@ static __devinit void default_find_bmc(void)
for (i = 0; ; i++) {
if (!ipmi_defaults[i].port)
break;
-
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- return;
-
#ifdef CONFIG_PPC_MERGE
if (check_legacy_ioport(ipmi_defaults[i].port))
continue;
#endif
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return;
info->addr_source = NULL;
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c
index b1414507997..3a23e7694d5 100644
--- a/drivers/char/pcmcia/ipwireless/tty.c
+++ b/drivers/char/pcmcia/ipwireless/tty.c
@@ -29,7 +29,6 @@
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/uaccess.h>
-#include <linux/version.h>
#include "tty.h"
#include "network.h"
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 509c89ac5bd..08911ed6649 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -47,7 +47,6 @@
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 0e6866fe0f9..a27160ba21d 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2496,45 +2496,25 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
}
/**
- * tiocswinsz - implement window size set ioctl
- * @tty; tty
- * @arg: user buffer for result
+ * tty_do_resize - resize event
+ * @tty: tty being resized
+ * @real_tty: real tty (if using a pty/tty pair)
+ * @rows: rows (character)
+ * @cols: cols (character)
*
- * Copies the user idea of the window size to the kernel. Traditionally
- * this is just advisory information but for the Linux console it
- * actually has driver level meaning and triggers a VC resize.
- *
- * Locking:
- * Called function use the console_sem is used to ensure we do
- * not try and resize the console twice at once.
- * The tty->termios_mutex is used to ensure we don't double
- * resize and get confused. Lock order - tty->termios_mutex before
- * console sem
+ * Update the termios variables and send the neccessary signals to
+ * peform a terminal resize correctly
*/
-static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
- struct winsize __user *arg)
+int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
+ struct winsize *ws)
{
- struct winsize tmp_ws;
struct pid *pgrp, *rpgrp;
unsigned long flags;
- if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
- return -EFAULT;
-
mutex_lock(&tty->termios_mutex);
- if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
+ if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
goto done;
-
-#ifdef CONFIG_VT
- if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
- if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col,
- tmp_ws.ws_row)) {
- mutex_unlock(&tty->termios_mutex);
- return -ENXIO;
- }
- }
-#endif
/* Get the PID values and reference them so we can
avoid holding the tty ctrl lock while sending signals */
spin_lock_irqsave(&tty->ctrl_lock, flags);
@@ -2550,14 +2530,42 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
put_pid(pgrp);
put_pid(rpgrp);
- tty->winsize = tmp_ws;
- real_tty->winsize = tmp_ws;
+ tty->winsize = *ws;
+ real_tty->winsize = *ws;
done:
mutex_unlock(&tty->termios_mutex);
return 0;
}
/**
+ * tiocswinsz - implement window size set ioctl
+ * @tty; tty
+ * @arg: user buffer for result
+ *
+ * Copies the user idea of the window size to the kernel. Traditionally
+ * this is just advisory information but for the Linux console it
+ * actually has driver level meaning and triggers a VC resize.
+ *
+ * Locking:
+ * Driver dependant. The default do_resize method takes the
+ * tty termios mutex and ctrl_lock. The console takes its own lock
+ * then calls into the default method.
+ */
+
+static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
+ struct winsize __user *arg)
+{
+ struct winsize tmp_ws;
+ if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
+ return -EFAULT;
+
+ if (tty->ops->resize)
+ return tty->ops->resize(tty, real_tty, &tmp_ws);
+ else
+ return tty_do_resize(tty, real_tty, &tmp_ws);
+}
+
+/**
* tioccons - allow admin to move logical console
* @file: the file to become console
*
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 1bc00c9d860..60359c36091 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -803,7 +803,25 @@ static inline int resize_screen(struct vc_data *vc, int width, int height,
*/
#define VC_RESIZE_MAXCOL (32767)
#define VC_RESIZE_MAXROW (32767)
-int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
+
+/**
+ * vc_do_resize - resizing method for the tty
+ * @tty: tty being resized
+ * @real_tty: real tty (different to tty if a pty/tty pair)
+ * @vc: virtual console private data
+ * @cols: columns
+ * @lines: lines
+ *
+ * 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.
+ *
+ * Caller must hold the console semaphore. Takes the termios mutex and
+ * ctrl_lock of the tty IFF a tty is passed.
+ */
+
+static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
+ struct vc_data *vc, unsigned int cols, unsigned int lines)
{
unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
unsigned int old_cols, old_rows, old_row_size, old_screen_size;
@@ -907,24 +925,15 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
gotoxy(vc, vc->vc_x, vc->vc_y);
save_cur(vc);
- if (vc->vc_tty) {
- struct winsize ws, *cws = &vc->vc_tty->winsize;
- struct pid *pgrp = NULL;
-
+ if (tty) {
+ /* Rewrite the requested winsize data with the actual
+ resulting sizes */
+ struct winsize ws;
memset(&ws, 0, sizeof(ws));
ws.ws_row = vc->vc_rows;
ws.ws_col = vc->vc_cols;
ws.ws_ypixel = vc->vc_scan_lines;
-
- spin_lock_irq(&vc->vc_tty->ctrl_lock);
- if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col))
- pgrp = get_pid(vc->vc_tty->pgrp);
- spin_unlock_irq(&vc->vc_tty->ctrl_lock);
- if (pgrp) {
- kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
- put_pid(pgrp);
- }
- *cws = ws;
+ tty_do_resize(tty, real_tty, &ws);
}
if (CON_IS_VISIBLE(vc))
@@ -932,14 +941,47 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
return err;
}
-int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
+/**
+ * vc_resize - resize a VT
+ * @vc: virtual console
+ * @cols: columns
+ * @rows: rows
+ *
+ * Resize a virtual console as seen from the console end of things. We
+ * use the common vc_do_resize methods to update the structures. The
+ * caller must hold the console sem to protect console internals and
+ * vc->vc_tty
+ */
+
+int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
+{
+ return vc_do_resize(vc->vc_tty, vc->vc_tty, vc, cols, rows);
+}
+
+/**
+ * vt_resize - resize a VT
+ * @tty: tty to resize
+ * @real_tty: tty if a pty/tty pair
+ * @ws: winsize attributes
+ *
+ * Resize a virtual terminal. This is called by the tty layer as we
+ * register our own handler for resizing. The mutual helper does all
+ * the actual work.
+ *
+ * Takes the console sem and the called methods then take the tty
+ * termios_mutex and the tty ctrl_lock in that order.
+ */
+
+int vt_resize(struct tty_struct *tty, struct tty_struct *real_tty,
+ struct winsize *ws)
{
- int rc;
+ struct vc_data *vc = tty->driver_data;
+ int ret;
acquire_console_sem();
- rc = vc_resize(vc, cols, lines);
+ ret = vc_do_resize(tty, real_tty, vc, ws->ws_col, ws->ws_row);
release_console_sem();
- return rc;
+ return ret;
}
void vc_deallocate(unsigned int currcons)
@@ -2907,6 +2949,7 @@ static const struct tty_operations con_ops = {
.start = con_start,
.throttle = con_throttle,
.unthrottle = con_unthrottle,
+ .resize = vt_resize,
};
int __init vty_init(void)
@@ -4061,7 +4104,6 @@ EXPORT_SYMBOL(default_blu);
EXPORT_SYMBOL(update_region);
EXPORT_SYMBOL(redraw_screen);
EXPORT_SYMBOL(vc_resize);
-EXPORT_SYMBOL(vc_lock_resize);
EXPORT_SYMBOL(fg_console);
EXPORT_SYMBOL(console_blank_hook);
EXPORT_SYMBOL(console_blanked);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 3211afd9d57..c904e9ad4a7 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -947,14 +947,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
get_user(cc, &vtsizes->v_cols))
ret = -EFAULT;
else {
+ acquire_console_sem();
for (i = 0; i < MAX_NR_CONSOLES; i++) {
vc = vc_cons[i].d;
if (vc) {
vc->vc_resize_user = 1;
- vc_lock_resize(vc_cons[i].d, cc, ll);
+ vc_resize(vc_cons[i].d, cc, ll);
}
}
+ release_console_sem();
}
break;
}
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 8bfee5fb722..278c9857bcf 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -74,7 +74,6 @@
* currently programmed in the FPGA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index ba7b9a6b17a..a4bec3f919a 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -67,10 +67,17 @@ static int ladder_select_state(struct cpuidle_device *dev)
struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
struct ladder_device_state *last_state;
int last_residency, last_idx = ldev->last_state_idx;
+ int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
if (unlikely(!ldev))
return 0;
+ /* Special case when user has set very strict latency requirement */
+ if (unlikely(latency_req == 0)) {
+ ladder_do_selection(ldev, last_idx, 0);
+ return 0;
+ }
+
last_state = &ldev->states[last_idx];
if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
@@ -81,8 +88,7 @@ static int ladder_select_state(struct cpuidle_device *dev)
/* consider promotion */
if (last_idx < dev->state_count - 1 &&
last_residency > last_state->threshold.promotion_time &&
- dev->states[last_idx + 1].exit_latency <=
- pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
+ dev->states[last_idx + 1].exit_latency <= latency_req) {
last_state->stats.promotion_count++;
last_state->stats.demotion_count = 0;
if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
@@ -92,7 +98,19 @@ static int ladder_select_state(struct cpuidle_device *dev)
}
/* consider demotion */
- if (last_idx > 0 &&
+ if (last_idx > CPUIDLE_DRIVER_STATE_START &&
+ dev->states[last_idx].exit_latency > latency_req) {
+ int i;
+
+ for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {
+ if (dev->states[i].exit_latency <= latency_req)
+ break;
+ }
+ ladder_do_selection(ldev, last_idx, i);
+ return i;
+ }
+
+ if (last_idx > CPUIDLE_DRIVER_STATE_START &&
last_residency < last_state->threshold.demotion_time) {
last_state->stats.demotion_count++;
last_state->stats.promotion_count = 0;
@@ -117,7 +135,7 @@ static int ladder_enable_device(struct cpuidle_device *dev)
struct ladder_device_state *lstate;
struct cpuidle_state *state;
- ldev->last_state_idx = 0;
+ ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
for (i = 0; i < dev->state_count; i++) {
state = &dev->states[i];
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 78d77c5dc35..8d7cf3f3145 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -34,21 +34,28 @@ static DEFINE_PER_CPU(struct menu_device, menu_devices);
static int menu_select(struct cpuidle_device *dev)
{
struct menu_device *data = &__get_cpu_var(menu_devices);
+ int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
int i;
+ /* Special case when user has set very strict latency requirement */
+ if (unlikely(latency_req == 0)) {
+ data->last_state_idx = 0;
+ return 0;
+ }
+
/* determine the expected residency time */
data->expected_us =
(u32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000;
/* find the deepest idle state that satisfies our constraints */
- for (i = 1; i < dev->state_count; i++) {
+ for (i = CPUIDLE_DRIVER_STATE_START + 1; i < dev->state_count; i++) {
struct cpuidle_state *s = &dev->states[i];
if (s->target_residency > data->expected_us)
break;
if (s->target_residency > data->predicted_us)
break;
- if (s->exit_latency > pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY))
+ if (s->exit_latency > latency_req)
break;
}
@@ -67,9 +74,9 @@ static void menu_reflect(struct cpuidle_device *dev)
{
struct menu_device *data = &__get_cpu_var(menu_devices);
int last_idx = data->last_state_idx;
- unsigned int measured_us =
- cpuidle_get_last_residency(dev) + data->elapsed_us;
+ unsigned int last_idle_us = cpuidle_get_last_residency(dev);
struct cpuidle_state *target = &dev->states[last_idx];
+ unsigned int measured_us;
/*
* Ugh, this idle state doesn't support residency measurements, so we
@@ -77,20 +84,27 @@ static void menu_reflect(struct cpuidle_device *dev)
* for one full standard timer tick. However, be aware that this
* could potentially result in a suboptimal state transition.
*/
- if (!(target->flags & CPUIDLE_FLAG_TIME_VALID))
- measured_us = USEC_PER_SEC / HZ;
+ if (unlikely(!(target->flags & CPUIDLE_FLAG_TIME_VALID)))
+ last_idle_us = USEC_PER_SEC / HZ;
+
+ /*
+ * measured_us and elapsed_us are the cumulative idle time, since the
+ * last time we were woken out of idle by an interrupt.
+ */
+ if (data->elapsed_us <= data->elapsed_us + last_idle_us)
+ measured_us = data->elapsed_us + last_idle_us;
+ else
+ measured_us = -1;
+
+ /* Predict time until next break event */
+ data->predicted_us = max(measured_us, data->last_measured_us);
- /* Predict time remaining until next break event */
- if (measured_us + BREAK_FUZZ < data->expected_us - target->exit_latency) {
- data->predicted_us = max(measured_us, data->last_measured_us);
+ if (last_idle_us + BREAK_FUZZ <
+ data->expected_us - target->exit_latency) {
data->last_measured_us = measured_us;
data->elapsed_us = 0;
} else {
- if (data->elapsed_us < data->elapsed_us + measured_us)
- data->elapsed_us = measured_us;
- else
- data->elapsed_us = -1;
- data->predicted_us = max(measured_us, data->last_measured_us);
+ data->elapsed_us = measured_us;
}
}
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index a4e4494663b..0328da020a1 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -25,7 +25,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/memory.h>
-#include <asm/plat-orion/mv_xor.h>
+#include <plat/mv_xor.h>
#include "mv_xor.h"
static void mv_xor_issue_pending(struct dma_chan *chan);
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
index fa6d6abefd4..45090243820 100644
--- a/drivers/firewire/Kconfig
+++ b/drivers/firewire/Kconfig
@@ -12,8 +12,8 @@ config FIREWIRE
This is the "Juju" FireWire stack, a new alternative implementation
designed for robustness and simplicity. You can build either this
stack, or the old stack (the ieee1394 driver, ohci1394 etc.) or both.
- Please read http://wiki.linux1394.org/JujuMigration before you
- enable the new stack.
+ Please read http://ieee1394.wiki.kernel.org/index.php/Juju_Migration
+ before you enable the new stack.
To compile this driver as a module, say M here: the module will be
called firewire-core.
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 61e78a4369b..b15f8824963 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -654,12 +654,12 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE},
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index bf4ebfb86fa..d402e8d813c 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -77,6 +77,22 @@ config SENSORS_AD7418
This driver can also be built as a module. If so, the module
will be called ad7418.
+config SENSORS_ADCXX
+ tristate "National Semiconductor ADCxxxSxxx"
+ depends on SPI_MASTER && EXPERIMENTAL
+ help
+ If you say yes here you get support for the National Semiconductor
+ ADC<bb><c>S<sss> chip family, where
+ * bb is the resolution in number of bits (8, 10, 12)
+ * c is the number of channels (1, 2, 4, 8)
+ * sss is the maximum conversion speed (021 for 200 kSPS, 051 for 500
+ kSPS and 101 for 1 MSPS)
+
+ Examples : ADC081S101, ADC124S501, ...
+
+ This driver can also be built as a module. If so, the module
+ will be called adcxx.
+
config SENSORS_ADM1021
tristate "Analog Devices ADM1021 and compatibles"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 7943e5cefb0..950134ab842 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o
obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o
obj-$(CONFIG_SENSORS_AD7414) += ad7414.o
obj-$(CONFIG_SENSORS_AD7418) += ad7418.o
+obj-$(CONFIG_SENSORS_ADCXX) += adcxx.o
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o
obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index f00f497b9ca..d568c65c137 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -1,5 +1,8 @@
/*
- abituguru3.c Copyright (c) 2006 Hans de Goede <j.w.r.degoede@hhs.nl>
+ abituguru3.c
+
+ Copyright (c) 2006-2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+ Copyright (c) 2008 Alistair John Strachan <alistair@devzero.co.uk>
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
@@ -116,7 +119,7 @@ struct abituguru3_sensor_info {
struct abituguru3_motherboard_info {
u16 id;
- const char *name;
+ const char *dmi_name;
/* + 1 -> end of sensors indicated by a sensor with name == NULL */
struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1];
};
@@ -161,7 +164,7 @@ struct abituguru3_data {
/* Constants */
static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
- { 0x000C, "unknown", {
+ { 0x000C, NULL /* Unknown, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 10, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -183,7 +186,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX1 Fan", 35, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x000D, "Abit AW8", {
+ { 0x000D, NULL /* Abit AW8, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 10, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -212,7 +215,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX5 Fan", 39, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x000E, "AL-8", {
+ { 0x000E, NULL /* AL-8, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 10, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -233,7 +236,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "SYS Fan", 34, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x000F, "unknown", {
+ { 0x000F, NULL /* Unknown, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 10, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -254,7 +257,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "SYS Fan", 34, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0010, "Abit NI8 SLI GR", {
+ { 0x0010, NULL /* Abit NI8 SLI GR, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 10, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -276,7 +279,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "OTES1 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0011, "Abit AT8 32X", {
+ { 0x0011, NULL /* Abit AT8 32X, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 20, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -302,7 +305,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX2 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0012, "Abit AN8 32X", {
+ { 0x0012, NULL /* Abit AN8 32X, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 20, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -324,7 +327,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX1 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0013, "Abit AW8D", {
+ { 0x0013, NULL /* Abit AW8D, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 10, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -353,7 +356,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX5 Fan", 39, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0014, "Abit AB9 Pro", {
+ { 0x0014, NULL /* Abit AB9 Pro, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 10, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -374,7 +377,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "SYS Fan", 34, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0015, "unknown", {
+ { 0x0015, NULL /* Unknown, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 20, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -398,7 +401,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0016, "AW9D-MAX", {
+ { 0x0016, NULL /* AW9D-MAX, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -426,7 +429,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "OTES1 Fan", 38, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0017, "unknown", {
+ { 0x0017, NULL /* Unknown, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -451,7 +454,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 FAN", 37, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0018, "unknown", {
+ { 0x0018, NULL /* Unknown, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -478,7 +481,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0019, "unknown", {
+ { 0x0019, NULL /* Unknown, need DMI string */, {
{ "CPU Core", 7, 0, 10, 1, 0 },
{ "DDR2", 13, 0, 20, 1, 0 },
{ "DDR2 VTT", 14, 0, 10, 1, 0 },
@@ -505,7 +508,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 FAN", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x001A, "Abit IP35 Pro", {
+ { 0x001A, "IP35 Pro(Intel P35-ICH9R)", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -533,7 +536,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX4 Fan", 37, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x001B, "unknown", {
+ { 0x001B, NULL /* Unknown, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR3", 1, 0, 20, 1, 0 },
{ "DDR3 VTT", 2, 0, 10, 1, 0 },
@@ -560,7 +563,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x001C, "unknown", {
+ { 0x001C, NULL /* Unknown, need DMI string */, {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -935,9 +938,18 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
goto abituguru3_probe_error;
}
data->sensors = abituguru3_motherboards[i].sensors;
+
printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
- "ID: %04X (%s)\n", (unsigned int)id,
- abituguru3_motherboards[i].name);
+ "ID: %04X\n", (unsigned int)id);
+
+#ifdef CONFIG_DMI
+ if (!abituguru3_motherboards[i].dmi_name) {
+ printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
+ "not detected using DMI. Please send the output of "
+ "\"dmidecode\" to the abituguru3 maintainer"
+ "(see MAINTAINERS)\n");
+ }
+#endif
/* Fill the sysfs attr array */
sysfs_attr_i = 0;
@@ -1109,6 +1121,46 @@ static struct platform_driver abituguru3_driver = {
.resume = abituguru3_resume
};
+#ifdef CONFIG_DMI
+
+static int __init abituguru3_dmi_detect(void)
+{
+ const char *board_vendor, *board_name;
+ int i, err = (force) ? 1 : -ENODEV;
+
+ board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+ if (!board_vendor || strcmp(board_vendor, "http://www.abit.com.tw/"))
+ return err;
+
+ board_name = dmi_get_system_info(DMI_BOARD_NAME);
+ if (!board_name)
+ return err;
+
+ for (i = 0; abituguru3_motherboards[i].id; i++) {
+ const char *dmi_name = abituguru3_motherboards[i].dmi_name;
+ if (dmi_name && !strcmp(dmi_name, board_name))
+ break;
+ }
+
+ if (!abituguru3_motherboards[i].id)
+ return 1;
+
+ return 0;
+}
+
+#else /* !CONFIG_DMI */
+
+static inline int abituguru3_dmi_detect(void)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_DMI */
+
+/* FIXME: Manual detection should die eventually; we need to collect stable
+ * DMI model names first before we can rely entirely on CONFIG_DMI.
+ */
+
static int __init abituguru3_detect(void)
{
/* See if there is an uguru3 there. An idle uGuru3 will hold 0x00 or
@@ -1119,7 +1171,7 @@ static int __init abituguru3_detect(void)
if (((data_val == 0x00) || (data_val == 0x08)) &&
((cmd_val == 0xAC) || (cmd_val == 0x05) ||
(cmd_val == 0x55)))
- return ABIT_UGURU3_BASE;
+ return 0;
ABIT_UGURU3_DEBUG("no Abit uGuru3 found, data = 0x%02X, cmd = "
"0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
@@ -1127,7 +1179,7 @@ static int __init abituguru3_detect(void)
if (force) {
printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is "
"present because of \"force\" parameter\n");
- return ABIT_UGURU3_BASE;
+ return 0;
}
/* No uGuru3 found */
@@ -1138,27 +1190,29 @@ static struct platform_device *abituguru3_pdev;
static int __init abituguru3_init(void)
{
- int address, err;
struct resource res = { .flags = IORESOURCE_IO };
-
-#ifdef CONFIG_DMI
- const char *board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
-
- /* safety check, refuse to load on non Abit motherboards */
- if (!force && (!board_vendor ||
- strcmp(board_vendor, "http://www.abit.com.tw/")))
- return -ENODEV;
-#endif
-
- address = abituguru3_detect();
- if (address < 0)
- return address;
+ int err;
+
+ /* Attempt DMI detection first */
+ err = abituguru3_dmi_detect();
+ if (err < 0)
+ return err;
+
+ /* Fall back to manual detection if there was no exact
+ * board name match, or force was specified.
+ */
+ if (err > 0) {
+ err = abituguru3_detect();
+ if (err)
+ return err;
+ }
err = platform_driver_register(&abituguru3_driver);
if (err)
goto exit;
- abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME, address);
+ abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME,
+ ABIT_UGURU3_BASE);
if (!abituguru3_pdev) {
printk(KERN_ERR ABIT_UGURU3_NAME
": Device allocation failed\n");
@@ -1166,8 +1220,8 @@ static int __init abituguru3_init(void)
goto exit_driver_unregister;
}
- res.start = address;
- res.end = address + ABIT_UGURU3_REGION_LENGTH - 1;
+ res.start = ABIT_UGURU3_BASE;
+ res.end = ABIT_UGURU3_BASE + ABIT_UGURU3_REGION_LENGTH - 1;
res.name = ABIT_UGURU3_NAME;
err = platform_device_add_resources(abituguru3_pdev, &res, 1);
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
new file mode 100644
index 00000000000..242294db3db
--- /dev/null
+++ b/drivers/hwmon/adcxx.c
@@ -0,0 +1,329 @@
+/*
+ * adcxx.c
+ *
+ * The adcxx4s is an AD converter family from National Semiconductor (NS).
+ *
+ * Copyright (c) 2008 Marc Pignat <marc.pignat@hevs.ch>
+ *
+ * The adcxx4s communicates with a host processor via an SPI/Microwire Bus
+ * interface. This driver supports the whole family of devices with name
+ * ADC<bb><c>S<sss>, where
+ * * bb is the resolution in number of bits (8, 10, 12)
+ * * c is the number of channels (1, 2, 4, 8)
+ * * sss is the maximum conversion speed (021 for 200 kSPS, 051 for 500 kSPS
+ * and 101 for 1 MSPS)
+ *
+ * Complete datasheets are available at National's website here:
+ * http://www.national.com/ds/DC/ADC<bb><c>S<sss>.pdf
+ *
+ * Handling of 8, 10 and 12 bits converters are the same, the
+ * unavailable bits are 0 :)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/mutex.h>
+#include <linux/spi/spi.h>
+
+#define DRVNAME "adcxx"
+
+struct adcxx {
+ struct device *hwmon_dev;
+ struct mutex lock;
+ u32 channels;
+ u32 reference; /* in millivolts */
+};
+
+/* sysfs hook function */
+static ssize_t adcxx_read(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adcxx *adc = dev_get_drvdata(&spi->dev);
+ u8 tx_buf[2] = { attr->index << 3 }; /* other bits are don't care */
+ u8 rx_buf[2];
+ int status;
+ int value;
+
+ if (mutex_lock_interruptible(&adc->lock))
+ return -ERESTARTSYS;
+
+ status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf),
+ rx_buf, sizeof(rx_buf));
+ if (status < 0) {
+ dev_warn(dev, "spi_write_then_read failed with status %d\n",
+ status);
+ goto out;
+ }
+
+ value = (rx_buf[0] << 8) + rx_buf[1];
+ dev_dbg(dev, "raw value = 0x%x\n", value);
+
+ value = value * adc->reference >> 12;
+ status = sprintf(buf, "%d\n", value);
+out:
+ mutex_unlock(&adc->lock);
+ return status;
+}
+
+static ssize_t adcxx_show_min(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ /* The minimum reference is 0 for this chip family */
+ return sprintf(buf, "0\n");
+}
+
+static ssize_t adcxx_show_max(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct adcxx *adc = dev_get_drvdata(&spi->dev);
+ u32 reference;
+
+ if (mutex_lock_interruptible(&adc->lock))
+ return -ERESTARTSYS;
+
+ reference = adc->reference;
+
+ mutex_unlock(&adc->lock);
+
+ return sprintf(buf, "%d\n", reference);
+}
+
+static ssize_t adcxx_set_max(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct adcxx *adc = dev_get_drvdata(&spi->dev);
+ unsigned long value;
+
+ if (strict_strtoul(buf, 10, &value))
+ return -EINVAL;
+
+ if (mutex_lock_interruptible(&adc->lock))
+ return -ERESTARTSYS;
+
+ adc->reference = value;
+
+ mutex_unlock(&adc->lock);
+
+ return count;
+}
+
+static ssize_t adcxx_show_name(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct adcxx *adc = dev_get_drvdata(&spi->dev);
+
+ return sprintf(buf, "adcxx%ds\n", adc->channels);
+}
+
+static struct sensor_device_attribute ad_input[] = {
+ SENSOR_ATTR(name, S_IRUGO, adcxx_show_name, NULL, 0),
+ SENSOR_ATTR(in_min, S_IRUGO, adcxx_show_min, NULL, 0),
+ SENSOR_ATTR(in_max, S_IWUSR | S_IRUGO, adcxx_show_max,
+ adcxx_set_max, 0),
+ SENSOR_ATTR(in0_input, S_IRUGO, adcxx_read, NULL, 0),
+ SENSOR_ATTR(in1_input, S_IRUGO, adcxx_read, NULL, 1),
+ SENSOR_ATTR(in2_input, S_IRUGO, adcxx_read, NULL, 2),
+ SENSOR_ATTR(in3_input, S_IRUGO, adcxx_read, NULL, 3),
+ SENSOR_ATTR(in4_input, S_IRUGO, adcxx_read, NULL, 4),
+ SENSOR_ATTR(in5_input, S_IRUGO, adcxx_read, NULL, 5),
+ SENSOR_ATTR(in6_input, S_IRUGO, adcxx_read, NULL, 6),
+ SENSOR_ATTR(in7_input, S_IRUGO, adcxx_read, NULL, 7),
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit adcxx_probe(struct spi_device *spi, int channels)
+{
+ struct adcxx *adc;
+ int status;
+ int i;
+
+ adc = kzalloc(sizeof *adc, GFP_KERNEL);
+ if (!adc)
+ return -ENOMEM;
+
+ /* set a default value for the reference */
+ adc->reference = 3300;
+ adc->channels = channels;
+ mutex_init(&adc->lock);
+
+ mutex_lock(&adc->lock);
+
+ dev_set_drvdata(&spi->dev, adc);
+
+ for (i = 0; i < 3 + adc->channels; i++) {
+ status = device_create_file(&spi->dev, &ad_input[i].dev_attr);
+ if (status) {
+ dev_err(&spi->dev, "device_create_file failed.\n");
+ goto out_err;
+ }
+ }
+
+ adc->hwmon_dev = hwmon_device_register(&spi->dev);
+ if (IS_ERR(adc->hwmon_dev)) {
+ dev_err(&spi->dev, "hwmon_device_register failed.\n");
+ status = PTR_ERR(adc->hwmon_dev);
+ goto out_err;
+ }
+
+ mutex_unlock(&adc->lock);
+ return 0;
+
+out_err:
+ for (i--; i >= 0; i--)
+ device_remove_file(&spi->dev, &ad_input[i].dev_attr);
+
+ dev_set_drvdata(&spi->dev, NULL);
+ mutex_unlock(&adc->lock);
+ kfree(adc);
+ return status;
+}
+
+static int __devinit adcxx1s_probe(struct spi_device *spi)
+{
+ return adcxx_probe(spi, 1);
+}
+
+static int __devinit adcxx2s_probe(struct spi_device *spi)
+{
+ return adcxx_probe(spi, 2);
+}
+
+static int __devinit adcxx4s_probe(struct spi_device *spi)
+{
+ return adcxx_probe(spi, 4);
+}
+
+static int __devinit adcxx8s_probe(struct spi_device *spi)
+{
+ return adcxx_probe(spi, 8);
+}
+
+static int __devexit adcxx_remove(struct spi_device *spi)
+{
+ struct adcxx *adc = dev_get_drvdata(&spi->dev);
+ int i;
+
+ mutex_lock(&adc->lock);
+ hwmon_device_unregister(adc->hwmon_dev);
+ for (i = 0; i < 3 + adc->channels; i++)
+ device_remove_file(&spi->dev, &ad_input[i].dev_attr);
+
+ dev_set_drvdata(&spi->dev, NULL);
+ mutex_unlock(&adc->lock);
+ kfree(adc);
+
+ return 0;
+}
+
+static struct spi_driver adcxx1s_driver = {
+ .driver = {
+ .name = "adcxx1s",
+ .owner = THIS_MODULE,
+ },
+ .probe = adcxx1s_probe,
+ .remove = __devexit_p(adcxx_remove),
+};
+
+static struct spi_driver adcxx2s_driver = {
+ .driver = {
+ .name = "adcxx2s",
+ .owner = THIS_MODULE,
+ },
+ .probe = adcxx2s_probe,
+ .remove = __devexit_p(adcxx_remove),
+};
+
+static struct spi_driver adcxx4s_driver = {
+ .driver = {
+ .name = "adcxx4s",
+ .owner = THIS_MODULE,
+ },
+ .probe = adcxx4s_probe,
+ .remove = __devexit_p(adcxx_remove),
+};
+
+static struct spi_driver adcxx8s_driver = {
+ .driver = {
+ .name = "adcxx8s",
+ .owner = THIS_MODULE,
+ },
+ .probe = adcxx8s_probe,
+ .remove = __devexit_p(adcxx_remove),
+};
+
+static int __init init_adcxx(void)
+{
+ int status;
+ status = spi_register_driver(&adcxx1s_driver);
+ if (status)
+ goto reg_1_failed;
+
+ status = spi_register_driver(&adcxx2s_driver);
+ if (status)
+ goto reg_2_failed;
+
+ status = spi_register_driver(&adcxx4s_driver);
+ if (status)
+ goto reg_4_failed;
+
+ status = spi_register_driver(&adcxx8s_driver);
+ if (status)
+ goto reg_8_failed;
+
+ return status;
+
+reg_8_failed:
+ spi_unregister_driver(&adcxx4s_driver);
+reg_4_failed:
+ spi_unregister_driver(&adcxx2s_driver);
+reg_2_failed:
+ spi_unregister_driver(&adcxx1s_driver);
+reg_1_failed:
+ return status;
+}
+
+static void __exit exit_adcxx(void)
+{
+ spi_unregister_driver(&adcxx1s_driver);
+ spi_unregister_driver(&adcxx2s_driver);
+ spi_unregister_driver(&adcxx4s_driver);
+ spi_unregister_driver(&adcxx8s_driver);
+}
+
+module_init(init_adcxx);
+module_exit(exit_adcxx);
+
+MODULE_AUTHOR("Marc Pignat");
+MODULE_DESCRIPTION("National Semiconductor adcxx8sxxx Linux driver");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("adcxx1s");
+MODULE_ALIAS("adcxx2s");
+MODULE_ALIAS("adcxx4s");
+MODULE_ALIAS("adcxx8s");
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index aacc0c4b809..b06b8e090a2 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -98,6 +98,12 @@ static const char* temperature_sensors_sets[][36] = {
"TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
"TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
"TM9S", "TN0H", "TS0C", NULL },
+/* Set 5: iMac */
+ { "TC0D", "TA0P", "TG0P", "TG0D", "TG0H", "TH0P", "Tm0P", "TO0P",
+ "Tp0C", NULL },
+/* Set 6: Macbook3 set */
+ { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H",
+ "Th0S", "Th1H", NULL },
};
/* List of keys used to read/write fan speeds */
@@ -1223,6 +1229,10 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
{ .accelerometer = 0, .light = 0, .temperature_set = 3 },
/* MacPro: temperature set 4 */
{ .accelerometer = 0, .light = 0, .temperature_set = 4 },
+/* iMac: temperature set 5 */
+ { .accelerometer = 0, .light = 0, .temperature_set = 5 },
+/* MacBook3: accelerometer and temperature set 6 */
+ { .accelerometer = 1, .light = 0, .temperature_set = 6 },
};
/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
@@ -1232,10 +1242,14 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
(void*)&applesmc_dmi_data[0]},
- { applesmc_dmi_match, "Apple MacBook", {
+ { applesmc_dmi_match, "Apple MacBook (v2)", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") },
(void*)&applesmc_dmi_data[1]},
+ { applesmc_dmi_match, "Apple MacBook (v3)", {
+ DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") },
+ (void*)&applesmc_dmi_data[6]},
{ applesmc_dmi_match, "Apple MacBook", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
@@ -1248,6 +1262,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
(void*)&applesmc_dmi_data[4]},
+ { applesmc_dmi_match, "Apple iMac", {
+ DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME,"iMac") },
+ (void*)&applesmc_dmi_data[5]},
{ .ident = NULL }
};
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 70239acecc8..93c17223b52 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -413,10 +413,11 @@ static int __init coretemp_init(void)
for_each_online_cpu(i) {
struct cpuinfo_x86 *c = &cpu_data(i);
- /* check if family 6, models 0xe, 0xf, 0x16, 0x17 */
+ /* check if family 6, models 0xe, 0xf, 0x16, 0x17, 0x1A */
if ((c->cpuid_level < 0) || (c->x86 != 0x6) ||
!((c->x86_model == 0xe) || (c->x86_model == 0xf) ||
- (c->x86_model == 0x16) || (c->x86_model == 0x17))) {
+ (c->x86_model == 0x16) || (c->x86_model == 0x17) ||
+ (c->x86_model == 0x1A))) {
/* supported CPU not found, but report the unknown
family 6 CPU */
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 7b0a32c4dcf..c54eff92be4 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -37,13 +37,21 @@
* For VRD 10.0 and up, "VRD x.y Design Guide",
* available at http://developer.intel.com/.
*
- * AMD NPT 0Fh (Athlon64 & Opteron), AMD Publication 32559,
+ * AMD Athlon 64 and AMD Opteron Processors, AMD Publication 26094,
+ * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/26094.PDF
+ * Table 74. VID Code Voltages
+ * This corresponds to an arbitrary VRM code of 24 in the functions below.
+ * These CPU models (K8 revision <= E) have 5 VID pins. See also:
+ * Revision Guide for AMD Athlon 64 and AMD Opteron Processors, AMD Publication 25759,
+ * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25759.pdf
+ *
+ * AMD NPT Family 0Fh Processors, AMD Publication 32559,
* http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
* Table 71. VID Code Voltages
- * AMD Opteron processors don't follow the Intel specifications.
- * I'm going to "make up" 2.4 as the spec number for the Opterons.
- * No good reason just a mnemonic for the 24x Opteron processor
- * series.
+ * This corresponds to an arbitrary VRM code of 25 in the functions below.
+ * These CPU models (K8 revision >= F) have 6 VID pins. See also:
+ * Revision Guide for AMD NPT Family 0Fh Processors, AMD Publication 33610,
+ * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf
*
* The 17 specification is in fact Intel Mobile Voltage Positioning -
* (IMVP-II). You can find more information in the datasheet of Max1718
@@ -95,7 +103,12 @@ int vid_from_reg(int val, u8 vrm)
return 0;
return((1600000 - (val - 2) * 6250 + 500) / 1000);
- case 24: /* AMD NPT 0Fh (Athlon64 & Opteron) */
+ case 24: /* Athlon64 & Opteron */
+ val &= 0x1f;
+ if (val == 0x1f)
+ return 0;
+ /* fall through */
+ case 25: /* AMD NPT 0Fh */
val &= 0x3f;
return (val < 32) ? 1550 - 25 * val
: 775 - (25 * (val - 31)) / 2;
@@ -157,11 +170,16 @@ struct vrm_model {
#ifdef CONFIG_X86
-/* the stepping parameter is highest acceptable stepping for current line */
+/*
+ * The stepping parameter is highest acceptable stepping for current line.
+ * The model match must be exact for 4-bit values. For model values 0x10
+ * and above (extended model), all models below the parameter will match.
+ */
static struct vrm_model vrm_models[] = {
{X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */
- {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */
+ {X86_VENDOR_AMD, 0xF, 0x3F, ANY, 24}, /* Athlon 64, Opteron */
+ {X86_VENDOR_AMD, 0xF, ANY, ANY, 25}, /* NPT family 0Fh */
{X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */
{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */
{X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */
@@ -189,6 +207,8 @@ static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
if (vrm_models[i].vendor==vendor)
if ((vrm_models[i].eff_family==eff_family)
&& ((vrm_models[i].eff_model==eff_model) ||
+ (vrm_models[i].eff_model >= 0x10 &&
+ eff_model <= vrm_models[i].eff_model) ||
(vrm_models[i].eff_model==ANY)) &&
(eff_stepping <= vrm_models[i].eff_stepping))
return vrm_models[i].vrm_type;
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index f9e2ed621f7..2ede9388096 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -81,6 +81,8 @@ static unsigned long amb_reg_temp(unsigned int amb)
#define MAX_AMBS_PER_CHANNEL 16
#define MAX_AMBS (MAX_MEM_CHANNELS * \
MAX_AMBS_PER_CHANNEL)
+#define CHANNEL_SHIFT 4
+#define DIMM_MASK 0xF
/*
* Ugly hack: For some reason the highest bit is set if there
* are _any_ DIMMs in the channel. Attempting to read from
@@ -89,7 +91,7 @@ static unsigned long amb_reg_temp(unsigned int amb)
* might prevent us from seeing the 16th DIMM in the channel.
*/
#define REAL_MAX_AMBS_PER_CHANNEL 15
-#define KNOBS_PER_AMB 5
+#define KNOBS_PER_AMB 6
static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit)
{
@@ -238,6 +240,16 @@ static ssize_t show_amb_temp(struct device *dev,
500 * amb_read_byte(data, amb_reg_temp(attr->index)));
}
+static ssize_t show_label(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+ return sprintf(buf, "Ch. %d DIMM %d\n", attr->index >> CHANNEL_SHIFT,
+ attr->index & DIMM_MASK);
+}
+
static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
{
int i, j, k, d = 0;
@@ -268,6 +280,20 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
continue;
d++;
+ /* sysfs label */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_label", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_label;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
/* Temperature sysfs knob */
iattr = data->attrs + data->num_attrs;
snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index c9416e65748..0f70dc20410 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -1,6 +1,6 @@
/*
- * A hwmon driver for the IBM Active Energy Manager temperature/power sensors
- * and capping functionality.
+ * A hwmon driver for the IBM System Director Active Energy Manager (AEM)
+ * temperature/power/energy sensors and capping functionality.
* Copyright (C) 2008 IBM
*
* Author: Darrick J. Wong <djwong@us.ibm.com>
@@ -463,12 +463,18 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
}
/* Update AEM energy registers */
+static void update_aem_energy_one(struct aem_data *data, int which)
+{
+ aem_read_sensor(data, AEM_ENERGY_ELEMENT, which,
+ &data->energy[which], 8);
+}
+
static void update_aem_energy(struct aem_data *data)
{
- aem_read_sensor(data, AEM_ENERGY_ELEMENT, 0, &data->energy[0], 8);
+ update_aem_energy_one(data, 0);
if (data->ver_major < 2)
return;
- aem_read_sensor(data, AEM_ENERGY_ELEMENT, 1, &data->energy[1], 8);
+ update_aem_energy_one(data, 1);
}
/* Update all AEM1 sensors */
@@ -676,7 +682,8 @@ static int aem_find_aem2(struct aem_ipmi_data *data,
return -ETIMEDOUT;
if (data->rx_result || data->rx_msg_len != sizeof(*fi_resp) ||
- memcmp(&fi_resp->id, &system_x_id, sizeof(system_x_id)))
+ memcmp(&fi_resp->id, &system_x_id, sizeof(system_x_id)) ||
+ fi_resp->num_instances <= instance_num)
return -ENOENT;
return 0;
@@ -849,7 +856,7 @@ static ssize_t aem_show_power(struct device *dev,
struct timespec b, a;
mutex_lock(&data->lock);
- update_aem_energy(data);
+ update_aem_energy_one(data, attr->index);
getnstimeofday(&b);
before = data->energy[attr->index];
@@ -861,7 +868,7 @@ static ssize_t aem_show_power(struct device *dev,
return 0;
}
- update_aem_energy(data);
+ update_aem_energy_one(data, attr->index);
getnstimeofday(&a);
after = data->energy[attr->index];
mutex_unlock(&data->lock);
@@ -880,7 +887,9 @@ static ssize_t aem_show_energy(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct aem_data *a = dev_get_drvdata(dev);
- a->update(a);
+ mutex_lock(&a->lock);
+ update_aem_energy_one(a, attr->index);
+ mutex_unlock(&a->lock);
return sprintf(buf, "%llu\n",
(unsigned long long)a->energy[attr->index] * 1000);
@@ -1104,7 +1113,7 @@ static void __exit aem_exit(void)
}
MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
-MODULE_DESCRIPTION("IBM Active Energy Manager power/temp sensor driver");
+MODULE_DESCRIPTION("IBM AEM power/temp/energy sensor driver");
MODULE_LICENSE("GPL");
module_init(aem_init);
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index daa7d121483..de21142d106 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -1055,9 +1055,10 @@ static int w83791d_probe(struct i2c_client *client,
{
struct w83791d_data *data;
struct device *dev = &client->dev;
- int i, val1, err;
+ int i, err;
#ifdef DEBUG
+ int val1;
val1 = w83791d_read(client, W83791D_REG_DID_VID4);
dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n",
(val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 89a112d513a..49a8c589e34 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1272,9 +1272,9 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
*/
static void msf_from_bcd(struct atapi_msf *msf)
{
- msf->minute = BCD2BIN(msf->minute);
- msf->second = BCD2BIN(msf->second);
- msf->frame = BCD2BIN(msf->frame);
+ msf->minute = bcd2bin(msf->minute);
+ msf->second = bcd2bin(msf->second);
+ msf->frame = bcd2bin(msf->frame);
}
int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
@@ -1415,8 +1415,8 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
return stat;
if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
- toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
- toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
+ toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
+ toc->hdr.last_track = bcd2bin(toc->hdr.last_track);
}
ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
@@ -1456,8 +1456,8 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
return stat;
if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
- toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
- toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
+ toc->hdr.first_track = (u8)bin2bcd(CDROM_LEADOUT);
+ toc->hdr.last_track = (u8)bin2bcd(CDROM_LEADOUT);
} else {
toc->hdr.first_track = CDROM_LEADOUT;
toc->hdr.last_track = CDROM_LEADOUT;
@@ -1470,14 +1470,14 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->hdr.toc_length = be16_to_cpu(toc->hdr.toc_length);
if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
- toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
- toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
+ toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
+ toc->hdr.last_track = bcd2bin(toc->hdr.last_track);
}
for (i = 0; i <= ntracks; i++) {
if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD)
- toc->ent[i].track = BCD2BIN(toc->ent[i].track);
+ toc->ent[i].track = bcd2bin(toc->ent[i].track);
msf_from_bcd(&toc->ent[i].addr.msf);
}
toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute,
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index 40644b6f1c0..3187215e8f8 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -307,7 +307,7 @@ static struct pci_driver driver = {
.name = "AEC62xx_IDE",
.id_table = aec62xx_pci_tbl,
.probe = aec62xx_init_one,
- .remove = aec62xx_remove,
+ .remove = __devexit_p(aec62xx_remove),
};
static int __init aec62xx_ide_init(void)
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index bfae2f882f4..e6d8ee88d56 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -447,7 +447,7 @@ static struct pci_driver driver = {
.name = "Cypress_IDE",
.id_table = cy82c693_pci_tbl,
.probe = cy82c693_init_one,
- .remove = cy82c693_remove,
+ .remove = __devexit_p(cy82c693_remove),
};
static int __init cy82c693_ide_init(void)
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 748793a413a..eb107eef0db 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1620,7 +1620,7 @@ static struct pci_driver driver = {
.name = "HPT366_IDE",
.id_table = hpt366_pci_tbl,
.probe = hpt366_init_one,
- .remove = hpt366_remove,
+ .remove = __devexit_p(hpt366_remove),
};
static int __init hpt366_ide_init(void)
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index b6dc723de70..4a1508a707c 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -686,7 +686,7 @@ static struct pci_driver driver = {
.name = "ITE821x IDE",
.id_table = it821x_pci_tbl,
.probe = it821x_init_one,
- .remove = it821x_remove,
+ .remove = __devexit_p(it821x_remove),
};
static int __init it821x_ide_init(void)
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 0f609b72f47..d477da6b585 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -566,7 +566,7 @@ static struct pci_driver driver = {
.name = "Promise_IDE",
.id_table = pdc202new_pci_tbl,
.probe = pdc202new_init_one,
- .remove = pdc202new_remove,
+ .remove = __devexit_p(pdc202new_remove),
};
static int __init pdc202new_ide_init(void)
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 6cde48bba6f..44cccd1e086 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -954,7 +954,7 @@ static struct pci_driver driver = {
.name = "SCC IDE",
.id_table = scc_pci_tbl,
.probe = scc_init_one,
- .remove = scc_remove,
+ .remove = __devexit_p(scc_remove),
};
static int scc_ide_init(void)
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 42eef19a18f..681306c9d79 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -621,9 +621,9 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
DRV_NAME)) {
printk(KERN_ERR
- "%s : %s -- ERROR, Addresses "
+ "%s %s: -- ERROR, Addresses "
"0x%p to 0x%p ALREADY in use\n",
- __func__, DRV_NAME, (void *) cmd_phys_base,
+ DRV_NAME, pci_name(dev), (void *)cmd_phys_base,
(void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
return -ENOMEM;
}
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 445ce6fbea3..db2b88a369a 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -832,7 +832,7 @@ static struct pci_driver driver = {
.name = "SiI_IDE",
.id_table = siimage_pci_tbl,
.probe = siimage_init_one,
- .remove = siimage_remove,
+ .remove = __devexit_p(siimage_remove),
};
static int __init siimage_ide_init(void)
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index e5a4b42b4e3..5efe21d6ef9 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -610,7 +610,7 @@ static struct pci_driver driver = {
.name = "SIS_IDE",
.id_table = sis5513_pci_tbl,
.probe = sis5513_init_one,
- .remove = sis5513_remove,
+ .remove = __devexit_p(sis5513_remove),
};
static int __init sis5513_ide_init(void)
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index 7fc88c375e5..927277c54ec 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -249,7 +249,7 @@ static struct pci_driver driver = {
.name = "TC86C001",
.id_table = tc86c001_pci_tbl,
.probe = tc86c001_init_one,
- .remove = tc86c001_remove,
+ .remove = __devexit_p(tc86c001_remove),
};
static int __init tc86c001_ide_init(void)
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index a6b2cc83f29..94fb9ab3223 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -491,7 +491,7 @@ static struct pci_driver driver = {
.name = "VIA_IDE",
.id_table = via_pci_tbl,
.probe = via_init_one,
- .remove = via_remove,
+ .remove = __devexit_p(via_remove),
};
static int __init via_ide_init(void)
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 994a21e5a0a..16240a78965 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -844,7 +844,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
ne->host = host;
ne->nodeid = nodeid;
ne->generation = generation;
- ne->needs_probe = 1;
+ ne->needs_probe = true;
ne->guid = guid;
ne->guid_vendor_id = (guid >> 40) & 0xffffff;
@@ -1144,7 +1144,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
struct csr1212_keyval *kv, *vendor_name_kv = NULL;
u8 last_key_id = 0;
- ne->needs_probe = 0;
+ ne->needs_probe = false;
csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) {
switch (kv->key.id) {
@@ -1295,7 +1295,7 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
nodemgr_update_bus_options(ne);
/* Mark the node as new, so it gets re-probed */
- ne->needs_probe = 1;
+ ne->needs_probe = true;
} else {
/* old cache is valid, so update its generation */
struct nodemgr_csr_info *ci = ne->csr->private;
@@ -1566,57 +1566,60 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
struct probe_param {
struct host_info *hi;
int generation;
+ bool probe_now;
};
-static int __nodemgr_node_probe(struct device *dev, void *data)
+static int node_probe(struct device *dev, void *data)
{
- struct probe_param *param = (struct probe_param *)data;
+ struct probe_param *p = data;
struct node_entry *ne;
+ if (p->generation != get_hpsb_generation(p->hi->host))
+ return -EAGAIN;
+
ne = container_of(dev, struct node_entry, node_dev);
- if (!ne->needs_probe)
- nodemgr_probe_ne(param->hi, ne, param->generation);
- if (ne->needs_probe)
- nodemgr_probe_ne(param->hi, ne, param->generation);
+ if (ne->needs_probe == p->probe_now)
+ nodemgr_probe_ne(p->hi, ne, p->generation);
return 0;
}
static void nodemgr_node_probe(struct host_info *hi, int generation)
{
- struct hpsb_host *host = hi->host;
- struct probe_param param;
+ struct probe_param p;
- param.hi = hi;
- param.generation = generation;
- /* Do some processing of the nodes we've probed. This pulls them
+ p.hi = hi;
+ p.generation = generation;
+ /*
+ * Do some processing of the nodes we've probed. This pulls them
* into the sysfs layer if needed, and can result in processing of
* unit-directories, or just updating the node and it's
* unit-directories.
*
* Run updates before probes. Usually, updates are time-critical
- * while probes are time-consuming. (Well, those probes need some
- * improvement...) */
-
- class_for_each_device(&nodemgr_ne_class, NULL, &param,
- __nodemgr_node_probe);
-
- /* If we had a bus reset while we were scanning the bus, it is
- * possible that we did not probe all nodes. In that case, we
- * skip the clean up for now, since we could remove nodes that
- * were still on the bus. Another bus scan is pending which will
- * do the clean up eventually.
+ * while probes are time-consuming.
*
+ * Meanwhile, another bus reset may have happened. In this case we
+ * skip everything here and let the next bus scan handle it.
+ * Otherwise we may prematurely remove nodes which are still there.
+ */
+ p.probe_now = false;
+ if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
+ return;
+
+ p.probe_now = true;
+ if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
+ return;
+ /*
* Now let's tell the bus to rescan our devices. This may seem
* like overhead, but the driver-model core will only scan a
* device for a driver when either the device is added, or when a
* new driver is added. A bus reset is a good reason to rescan
* devices that were there before. For example, an sbp2 device
* may become available for login, if the host that held it was
- * just removed. */
-
- if (generation == get_hpsb_generation(host))
- if (bus_rescan_devices(&ieee1394_bus_type))
- HPSB_DEBUG("bus_rescan_devices had an error");
+ * just removed.
+ */
+ if (bus_rescan_devices(&ieee1394_bus_type) != 0)
+ HPSB_DEBUG("bus_rescan_devices had an error");
}
static int nodemgr_send_resume_packet(struct hpsb_host *host)
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 919e92e2a95..6eb26465a84 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -97,7 +97,7 @@ struct node_entry {
struct hpsb_host *host; /* Host this node is attached to */
nodeid_t nodeid; /* NodeID */
struct bus_options busopt; /* Bus Options */
- int needs_probe;
+ bool needs_probe;
unsigned int generation; /* Synced with hpsb generation */
/* The following is read from the config rom */
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 9cbf3154d24..1d6ad343553 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -731,15 +731,26 @@ static int sbp2_update(struct unit_directory *ud)
{
struct sbp2_lu *lu = ud->device.driver_data;
- if (sbp2_reconnect_device(lu)) {
- /* Reconnect has failed. Perhaps we didn't reconnect fast
- * enough. Try a regular login, but first log out just in
- * case of any weirdness. */
+ if (sbp2_reconnect_device(lu) != 0) {
+ /*
+ * Reconnect failed. If another bus reset happened,
+ * let nodemgr proceed and call sbp2_update again later
+ * (or sbp2_remove if this node went away).
+ */
+ if (!hpsb_node_entry_valid(lu->ne))
+ return 0;
+ /*
+ * Or the target rejected the reconnect because we weren't
+ * fast enough. Try a regular login, but first log out
+ * just in case of any weirdness.
+ */
sbp2_logout_device(lu);
- if (sbp2_login_device(lu)) {
- /* Login failed too, just fail, and the backend
- * will call our sbp2_remove for us */
+ if (sbp2_login_device(lu) != 0) {
+ if (!hpsb_node_entry_valid(lu->ne))
+ return 0;
+
+ /* Maybe another initiator won the login. */
SBP2_ERR("Failed to reconnect to sbp2 device!");
return -EBUSY;
}
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 2d65411f676..3524bef62be 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -647,6 +647,47 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
return copy_to_user(p, str, len) ? -EFAULT : len;
}
+#define OLD_KEY_MAX 0x1ff
+static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode)
+{
+ static unsigned long keymax_warn_time;
+ unsigned long *bits;
+ int len;
+
+ switch (_IOC_NR(cmd) & EV_MAX) {
+
+ case 0: bits = dev->evbit; len = EV_MAX; break;
+ case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
+ case EV_REL: bits = dev->relbit; len = REL_MAX; break;
+ case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
+ case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
+ case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
+ case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
+ case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
+ case EV_SW: bits = dev->swbit; len = SW_MAX; break;
+ default: return -EINVAL;
+ }
+
+ /*
+ * Work around bugs in userspace programs that like to do
+ * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len'
+ * should be in bytes, not in bits.
+ */
+ if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) {
+ len = OLD_KEY_MAX;
+ if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000))
+ printk(KERN_WARNING
+ "evdev.c(EVIOCGBIT): Suspicious buffer size %u, "
+ "limiting output to %zu bytes. See "
+ "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n",
+ OLD_KEY_MAX,
+ BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
+ }
+
+ return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
+}
+#undef OLD_KEY_MAX
+
static long evdev_do_ioctl(struct file *file, unsigned int cmd,
void __user *p, int compat_mode)
{
@@ -733,26 +774,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
if (_IOC_DIR(cmd) == _IOC_READ) {
- if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) {
-
- unsigned long *bits;
- int len;
-
- switch (_IOC_NR(cmd) & EV_MAX) {
-
- case 0: bits = dev->evbit; len = EV_MAX; break;
- case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
- case EV_REL: bits = dev->relbit; len = REL_MAX; break;
- case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
- case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
- case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
- case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
- case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
- case EV_SW: bits = dev->swbit; len = SW_MAX; break;
- default: return -EINVAL;
- }
- return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
- }
+ if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
+ return handle_eviocgbit(dev, cmd, p, compat_mode);
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 87d3e7eabff..6791be81eb2 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -127,6 +127,7 @@ static const struct xpad_device {
{ 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index be58730e636..ec96b369dd7 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -9,7 +9,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
@@ -118,6 +117,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
unsigned int type = button->type ?: EV_KEY;
bdata->input = input;
+ bdata->button = button;
setup_timer(&bdata->timer,
gpio_check_button, (unsigned long)bdata);
@@ -256,7 +256,7 @@ static int gpio_keys_resume(struct platform_device *pdev)
#define gpio_keys_resume NULL
#endif
-struct platform_driver gpio_keys_device_driver = {
+static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = __devexit_p(gpio_keys_remove),
.suspend = gpio_keys_suspend,
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
index 6a1f48b76e3..2adf9cb265d 100644
--- a/drivers/input/misc/cobalt_btns.c
+++ b/drivers/input/misc/cobalt_btns.c
@@ -148,6 +148,9 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
return 0;
}
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_DESCRIPTION("Cobalt button interface driver");
+MODULE_LICENSE("GPL");
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:Cobalt buttons");
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 7bbea097cda..f996546fc44 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -130,6 +130,29 @@ config MOUSE_APPLETOUCH
To compile this driver as a module, choose M here: the
module will be called appletouch.
+config MOUSE_BCM5974
+ tristate "Apple USB BCM5974 Multitouch trackpad support"
+ depends on USB_ARCH_HAS_HCD
+ select USB
+ help
+ Say Y here if you have an Apple USB BCM5974 Multitouch
+ trackpad.
+
+ The BCM5974 is the multitouch trackpad found in the Macbook
+ Air (JAN2008) and Macbook Pro Penryn (FEB2008) laptops.
+
+ It is also found in the IPhone (2007) and Ipod Touch (2008).
+
+ This driver provides multitouch functionality together with
+ the synaptics X11 driver.
+
+ The interface is currently identical to the appletouch interface,
+ for further information, see
+ <file:Documentation/input/appletouch.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bcm5974.
+
config MOUSE_INPORT
tristate "InPort/MS/ATIXL busmouse"
depends on ISA
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 9e6e3633082..d4d20251609 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
+obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
new file mode 100644
index 00000000000..2ec921bf3c6
--- /dev/null
+++ b/drivers/input/mouse/bcm5974.c
@@ -0,0 +1,681 @@
+/*
+ * Apple USB BCM5974 (Macbook Air and Penryn Macbook Pro) multitouch driver
+ *
+ * Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se)
+ *
+ * The USB initialization and package decoding was made by
+ * Scott Shawcroft as part of the touchd user-space driver project:
+ * Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com)
+ *
+ * The BCM5974 driver is based on the appletouch driver:
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
+ * Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
+ * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
+ * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb/input.h>
+#include <linux/hid.h>
+#include <linux/mutex.h>
+
+#define USB_VENDOR_ID_APPLE 0x05ac
+
+/* MacbookAir, aka wellspring */
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224
+#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225
+/* MacbookProPenryn, aka wellspring2 */
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
+
+#define BCM5974_DEVICE(prod) { \
+ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_INT_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL), \
+ .idVendor = USB_VENDOR_ID_APPLE, \
+ .idProduct = (prod), \
+ .bInterfaceClass = USB_INTERFACE_CLASS_HID, \
+ .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE \
+}
+
+/* table of devices that work with this driver */
+static const struct usb_device_id bcm5974_table [] = {
+ /* MacbookAir1.1 */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_JIS),
+ /* MacbookProPenryn */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
+ /* Terminating entry */
+ {}
+};
+MODULE_DEVICE_TABLE(usb, bcm5974_table);
+
+MODULE_AUTHOR("Henrik Rydberg");
+MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver");
+MODULE_LICENSE("GPL");
+
+#define dprintk(level, format, a...)\
+ { if (debug >= level) printk(KERN_DEBUG format, ##a); }
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activate debugging output");
+
+/* button data structure */
+struct bt_data {
+ u8 unknown1; /* constant */
+ u8 button; /* left button */
+ u8 rel_x; /* relative x coordinate */
+ u8 rel_y; /* relative y coordinate */
+};
+
+/* trackpad header structure */
+struct tp_header {
+ u8 unknown1[16]; /* constants, timers, etc */
+ u8 fingers; /* number of fingers on trackpad */
+ u8 unknown2[9]; /* constants, timers, etc */
+};
+
+/* trackpad finger structure */
+struct tp_finger {
+ __le16 origin; /* left/right origin? */
+ __le16 abs_x; /* absolute x coodinate */
+ __le16 abs_y; /* absolute y coodinate */
+ __le16 rel_x; /* relative x coodinate */
+ __le16 rel_y; /* relative y coodinate */
+ __le16 size_major; /* finger size, major axis? */
+ __le16 size_minor; /* finger size, minor axis? */
+ __le16 orientation; /* 16384 when point, else 15 bit angle */
+ __le16 force_major; /* trackpad force, major axis? */
+ __le16 force_minor; /* trackpad force, minor axis? */
+ __le16 unused[3]; /* zeros */
+ __le16 multi; /* one finger: varies, more fingers: constant */
+};
+
+/* trackpad data structure, empirically at least ten fingers */
+struct tp_data {
+ struct tp_header header;
+ struct tp_finger finger[16];
+};
+
+/* device-specific parameters */
+struct bcm5974_param {
+ int dim; /* logical dimension */
+ int fuzz; /* logical noise value */
+ int devmin; /* device minimum reading */
+ int devmax; /* device maximum reading */
+};
+
+/* device-specific configuration */
+struct bcm5974_config {
+ int ansi, iso, jis; /* the product id of this device */
+ int bt_ep; /* the endpoint of the button interface */
+ int bt_datalen; /* data length of the button interface */
+ int tp_ep; /* the endpoint of the trackpad interface */
+ int tp_datalen; /* data length of the trackpad interface */
+ struct bcm5974_param p; /* finger pressure limits */
+ struct bcm5974_param w; /* finger width limits */
+ struct bcm5974_param x; /* horizontal limits */
+ struct bcm5974_param y; /* vertical limits */
+};
+
+/* logical device structure */
+struct bcm5974 {
+ char phys[64];
+ struct usb_device *udev; /* usb device */
+ struct usb_interface *intf; /* our interface */
+ struct input_dev *input; /* input dev */
+ struct bcm5974_config cfg; /* device configuration */
+ struct mutex pm_mutex; /* serialize access to open/suspend */
+ int opened; /* 1: opened, 0: closed */
+ struct urb *bt_urb; /* button usb request block */
+ struct bt_data *bt_data; /* button transferred data */
+ struct urb *tp_urb; /* trackpad usb request block */
+ struct tp_data *tp_data; /* trackpad transferred data */
+};
+
+/* logical dimensions */
+#define DIM_PRESSURE 256 /* maximum finger pressure */
+#define DIM_WIDTH 16 /* maximum finger width */
+#define DIM_X 1280 /* maximum trackpad x value */
+#define DIM_Y 800 /* maximum trackpad y value */
+
+/* logical signal quality */
+#define SN_PRESSURE 45 /* pressure signal-to-noise ratio */
+#define SN_WIDTH 100 /* width signal-to-noise ratio */
+#define SN_COORD 250 /* coordinate signal-to-noise ratio */
+
+/* device constants */
+static const struct bcm5974_config bcm5974_config_table[] = {
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
+ 0x84, sizeof(struct bt_data),
+ 0x81, sizeof(struct tp_data),
+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+ { DIM_X, DIM_X / SN_COORD, -4824, 5342 },
+ { DIM_Y, DIM_Y / SN_COORD, -172, 5820 }
+ },
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING2_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
+ 0x84, sizeof(struct bt_data),
+ 0x81, sizeof(struct tp_data),
+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+ { DIM_X, DIM_X / SN_COORD, -4824, 4824 },
+ { DIM_Y, DIM_Y / SN_COORD, -172, 4290 }
+ },
+ {}
+};
+
+/* return the device-specific configuration by device */
+static const struct bcm5974_config *bcm5974_get_config(struct usb_device *udev)
+{
+ u16 id = le16_to_cpu(udev->descriptor.idProduct);
+ const struct bcm5974_config *cfg;
+
+ for (cfg = bcm5974_config_table; cfg->ansi; ++cfg)
+ if (cfg->ansi == id || cfg->iso == id || cfg->jis == id)
+ return cfg;
+
+ return bcm5974_config_table;
+}
+
+/* convert 16-bit little endian to signed integer */
+static inline int raw2int(__le16 x)
+{
+ return (signed short)le16_to_cpu(x);
+}
+
+/* scale device data to logical dimensions (asserts devmin < devmax) */
+static inline int int2scale(const struct bcm5974_param *p, int x)
+{
+ return x * p->dim / (p->devmax - p->devmin);
+}
+
+/* all logical value ranges are [0,dim). */
+static inline int int2bound(const struct bcm5974_param *p, int x)
+{
+ int s = int2scale(p, x);
+
+ return clamp_val(s, 0, p->dim - 1);
+}
+
+/* setup which logical events to report */
+static void setup_events_to_report(struct input_dev *input_dev,
+ const struct bcm5974_config *cfg)
+{
+ __set_bit(EV_ABS, input_dev->evbit);
+
+ input_set_abs_params(input_dev, ABS_PRESSURE,
+ 0, cfg->p.dim, cfg->p.fuzz, 0);
+ input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
+ 0, cfg->w.dim, cfg->w.fuzz, 0);
+ input_set_abs_params(input_dev, ABS_X,
+ 0, cfg->x.dim, cfg->x.fuzz, 0);
+ input_set_abs_params(input_dev, ABS_Y,
+ 0, cfg->y.dim, cfg->y.fuzz, 0);
+
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+ __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+ __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
+ __set_bit(BTN_LEFT, input_dev->keybit);
+}
+
+/* report button data as logical button state */
+static int report_bt_state(struct bcm5974 *dev, int size)
+{
+ if (size != sizeof(struct bt_data))
+ return -EIO;
+
+ input_report_key(dev->input, BTN_LEFT, dev->bt_data->button);
+ input_sync(dev->input);
+
+ return 0;
+}
+
+/* report trackpad data as logical trackpad state */
+static int report_tp_state(struct bcm5974 *dev, int size)
+{
+ const struct bcm5974_config *c = &dev->cfg;
+ const struct tp_finger *f = dev->tp_data->finger;
+ struct input_dev *input = dev->input;
+ const int fingers = (size - 26) / 28;
+ int p = 0, w, x, y, n = 0;
+
+ if (size < 26 || (size - 26) % 28 != 0)
+ return -EIO;
+
+ if (fingers) {
+ p = raw2int(f->force_major);
+ w = raw2int(f->size_major);
+ x = raw2int(f->abs_x);
+ y = raw2int(f->abs_y);
+ n = p > 0 ? fingers : 0;
+
+ dprintk(9,
+ "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
+ p, w, x, y, n);
+
+ input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w));
+ input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin));
+ input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y));
+ }
+
+ input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p));
+
+ input_report_key(input, BTN_TOOL_FINGER, n == 1);
+ input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2);
+ input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2);
+
+ input_sync(input);
+
+ return 0;
+}
+
+/* Wellspring initialization constants */
+#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
+#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
+#define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300
+#define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0
+#define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01
+
+static int bcm5974_wellspring_mode(struct bcm5974 *dev)
+{
+ char *data = kmalloc(8, GFP_KERNEL);
+ int retval = 0, size;
+
+ if (!data) {
+ err("bcm5974: out of memory");
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ /* read configuration */
+ size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+ BCM5974_WELLSPRING_MODE_READ_REQUEST_ID,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
+ BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
+
+ if (size != 8) {
+ err("bcm5974: could not read from device");
+ retval = -EIO;
+ goto out;
+ }
+
+ /* apply the mode switch */
+ data[0] = BCM5974_WELLSPRING_MODE_VENDOR_VALUE;
+
+ /* write configuration */
+ size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
+ BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
+
+ if (size != 8) {
+ err("bcm5974: could not write to device");
+ retval = -EIO;
+ goto out;
+ }
+
+ dprintk(2, "bcm5974: switched to wellspring mode.\n");
+
+ out:
+ kfree(data);
+ return retval;
+}
+
+static void bcm5974_irq_button(struct urb *urb)
+{
+ struct bcm5974 *dev = urb->context;
+ int error;
+
+ switch (urb->status) {
+ case 0:
+ break;
+ case -EOVERFLOW:
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ dbg("bcm5974: button urb shutting down: %d", urb->status);
+ return;
+ default:
+ dbg("bcm5974: button urb status: %d", urb->status);
+ goto exit;
+ }
+
+ if (report_bt_state(dev, dev->bt_urb->actual_length))
+ dprintk(1, "bcm5974: bad button package, length: %d\n",
+ dev->bt_urb->actual_length);
+
+exit:
+ error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC);
+ if (error)
+ err("bcm5974: button urb failed: %d", error);
+}
+
+static void bcm5974_irq_trackpad(struct urb *urb)
+{
+ struct bcm5974 *dev = urb->context;
+ int error;
+
+ switch (urb->status) {
+ case 0:
+ break;
+ case -EOVERFLOW:
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ dbg("bcm5974: trackpad urb shutting down: %d", urb->status);
+ return;
+ default:
+ dbg("bcm5974: trackpad urb status: %d", urb->status);
+ goto exit;
+ }
+
+ /* control response ignored */
+ if (dev->tp_urb->actual_length == 2)
+ goto exit;
+
+ if (report_tp_state(dev, dev->tp_urb->actual_length))
+ dprintk(1, "bcm5974: bad trackpad package, length: %d\n",
+ dev->tp_urb->actual_length);
+
+exit:
+ error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC);
+ if (error)
+ err("bcm5974: trackpad urb failed: %d", error);
+}
+
+/*
+ * The Wellspring trackpad, like many recent Apple trackpads, share
+ * the usb device with the keyboard. Since keyboards are usually
+ * handled by the HID system, the device ends up being handled by two
+ * modules. Setting up the device therefore becomes slightly
+ * complicated. To enable multitouch features, a mode switch is
+ * required, which is usually applied via the control interface of the
+ * device. It can be argued where this switch should take place. In
+ * some drivers, like appletouch, the switch is made during
+ * probe. However, the hid module may also alter the state of the
+ * device, resulting in trackpad malfunction under certain
+ * circumstances. To get around this problem, there is at least one
+ * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to
+ * recieve a reset_resume request rather than the normal resume.
+ * Since the implementation of reset_resume is equal to mode switch
+ * plus start_traffic, it seems easier to always do the switch when
+ * starting traffic on the device.
+ */
+static int bcm5974_start_traffic(struct bcm5974 *dev)
+{
+ if (bcm5974_wellspring_mode(dev)) {
+ dprintk(1, "bcm5974: mode switch failed\n");
+ goto error;
+ }
+
+ if (usb_submit_urb(dev->bt_urb, GFP_KERNEL))
+ goto error;
+
+ if (usb_submit_urb(dev->tp_urb, GFP_KERNEL))
+ goto err_kill_bt;
+
+ return 0;
+
+err_kill_bt:
+ usb_kill_urb(dev->bt_urb);
+error:
+ return -EIO;
+}
+
+static void bcm5974_pause_traffic(struct bcm5974 *dev)
+{
+ usb_kill_urb(dev->tp_urb);
+ usb_kill_urb(dev->bt_urb);
+}
+
+/*
+ * The code below implements open/close and manual suspend/resume.
+ * All functions may be called in random order.
+ *
+ * Opening a suspended device fails with EACCES - permission denied.
+ *
+ * Failing a resume leaves the device resumed but closed.
+ */
+static int bcm5974_open(struct input_dev *input)
+{
+ struct bcm5974 *dev = input_get_drvdata(input);
+ int error;
+
+ error = usb_autopm_get_interface(dev->intf);
+ if (error)
+ return error;
+
+ mutex_lock(&dev->pm_mutex);
+
+ error = bcm5974_start_traffic(dev);
+ if (!error)
+ dev->opened = 1;
+
+ mutex_unlock(&dev->pm_mutex);
+
+ if (error)
+ usb_autopm_put_interface(dev->intf);
+
+ return error;
+}
+
+static void bcm5974_close(struct input_dev *input)
+{
+ struct bcm5974 *dev = input_get_drvdata(input);
+
+ mutex_lock(&dev->pm_mutex);
+
+ bcm5974_pause_traffic(dev);
+ dev->opened = 0;
+
+ mutex_unlock(&dev->pm_mutex);
+
+ usb_autopm_put_interface(dev->intf);
+}
+
+static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message)
+{
+ struct bcm5974 *dev = usb_get_intfdata(iface);
+
+ mutex_lock(&dev->pm_mutex);
+
+ if (dev->opened)
+ bcm5974_pause_traffic(dev);
+
+ mutex_unlock(&dev->pm_mutex);
+
+ return 0;
+}
+
+static int bcm5974_resume(struct usb_interface *iface)
+{
+ struct bcm5974 *dev = usb_get_intfdata(iface);
+ int error = 0;
+
+ mutex_lock(&dev->pm_mutex);
+
+ if (dev->opened)
+ error = bcm5974_start_traffic(dev);
+
+ mutex_unlock(&dev->pm_mutex);
+
+ return error;
+}
+
+static int bcm5974_probe(struct usb_interface *iface,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(iface);
+ const struct bcm5974_config *cfg;
+ struct bcm5974 *dev;
+ struct input_dev *input_dev;
+ int error = -ENOMEM;
+
+ /* find the product index */
+ cfg = bcm5974_get_config(udev);
+
+ /* allocate memory for our device state and initialize it */
+ dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!dev || !input_dev) {
+ err("bcm5974: out of memory");
+ goto err_free_devs;
+ }
+
+ dev->udev = udev;
+ dev->intf = iface;
+ dev->input = input_dev;
+ dev->cfg = *cfg;
+ mutex_init(&dev->pm_mutex);
+
+ /* setup urbs */
+ dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->bt_urb)
+ goto err_free_devs;
+
+ dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->tp_urb)
+ goto err_free_bt_urb;
+
+ dev->bt_data = usb_buffer_alloc(dev->udev,
+ dev->cfg.bt_datalen, GFP_KERNEL,
+ &dev->bt_urb->transfer_dma);
+ if (!dev->bt_data)
+ goto err_free_urb;
+
+ dev->tp_data = usb_buffer_alloc(dev->udev,
+ dev->cfg.tp_datalen, GFP_KERNEL,
+ &dev->tp_urb->transfer_dma);
+ if (!dev->tp_data)
+ goto err_free_bt_buffer;
+
+ usb_fill_int_urb(dev->bt_urb, udev,
+ usb_rcvintpipe(udev, cfg->bt_ep),
+ dev->bt_data, dev->cfg.bt_datalen,
+ bcm5974_irq_button, dev, 1);
+
+ usb_fill_int_urb(dev->tp_urb, udev,
+ usb_rcvintpipe(udev, cfg->tp_ep),
+ dev->tp_data, dev->cfg.tp_datalen,
+ bcm5974_irq_trackpad, dev, 1);
+
+ /* create bcm5974 device */
+ usb_make_path(udev, dev->phys, sizeof(dev->phys));
+ strlcat(dev->phys, "/input0", sizeof(dev->phys));
+
+ input_dev->name = "bcm5974";
+ input_dev->phys = dev->phys;
+ usb_to_input_id(dev->udev, &input_dev->id);
+ input_dev->dev.parent = &iface->dev;
+
+ input_set_drvdata(input_dev, dev);
+
+ input_dev->open = bcm5974_open;
+ input_dev->close = bcm5974_close;
+
+ setup_events_to_report(input_dev, cfg);
+
+ error = input_register_device(dev->input);
+ if (error)
+ goto err_free_buffer;
+
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(iface, dev);
+
+ return 0;
+
+err_free_buffer:
+ usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
+ dev->tp_data, dev->tp_urb->transfer_dma);
+err_free_bt_buffer:
+ usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
+ dev->bt_data, dev->bt_urb->transfer_dma);
+err_free_urb:
+ usb_free_urb(dev->tp_urb);
+err_free_bt_urb:
+ usb_free_urb(dev->bt_urb);
+err_free_devs:
+ usb_set_intfdata(iface, NULL);
+ input_free_device(input_dev);
+ kfree(dev);
+ return error;
+}
+
+static void bcm5974_disconnect(struct usb_interface *iface)
+{
+ struct bcm5974 *dev = usb_get_intfdata(iface);
+
+ usb_set_intfdata(iface, NULL);
+
+ input_unregister_device(dev->input);
+ usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
+ dev->tp_data, dev->tp_urb->transfer_dma);
+ usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
+ dev->bt_data, dev->bt_urb->transfer_dma);
+ usb_free_urb(dev->tp_urb);
+ usb_free_urb(dev->bt_urb);
+ kfree(dev);
+}
+
+static struct usb_driver bcm5974_driver = {
+ .name = "bcm5974",
+ .probe = bcm5974_probe,
+ .disconnect = bcm5974_disconnect,
+ .suspend = bcm5974_suspend,
+ .resume = bcm5974_resume,
+ .reset_resume = bcm5974_resume,
+ .id_table = bcm5974_table,
+ .supports_autosuspend = 1,
+};
+
+static int __init bcm5974_init(void)
+{
+ return usb_register(&bcm5974_driver);
+}
+
+static void __exit bcm5974_exit(void)
+{
+ usb_deregister(&bcm5974_driver);
+}
+
+module_init(bcm5974_init);
+module_exit(bcm5974_exit);
+
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
index 33929018487..72cf5e33790 100644
--- a/drivers/input/mouse/gpio_mouse.c
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -9,7 +9,6 @@
*/
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/input-polldev.h>
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index fe732a574ec..3282b741e24 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -394,6 +394,13 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),
},
},
+ {
+ .ident = "Acer TravelMate 4280",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"),
+ },
+ },
{ }
};
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index 0ed044d5e68..765007899d9 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -269,8 +269,8 @@ static int xps2_setup(struct device *dev, struct resource *regs_res,
* we have the PS2 in a good state */
out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET);
- dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%08X, irq=%d\n",
- drvdata->phys_addr, (u32)drvdata->base_address, drvdata->irq);
+ dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%p, irq=%d\n",
+ drvdata->phys_addr, drvdata->base_address, drvdata->irq);
serio = &drvdata->serio;
serio->id.type = SERIO_8042;
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index b9b7a98bc5a..7df0228e836 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -64,7 +64,6 @@ Scott Hill shill@gtcocalcomp.com
#include <asm/byteorder.h>
-#include <linux/version.h>
#include <linux/usb/input.h>
/* Version with a Major number of 2 is for kernel inclusion only. */
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6e60a97a234..25287e80e23 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -249,29 +249,26 @@ config TOUCHSCREEN_WM97XX
config TOUCHSCREEN_WM9705
bool "WM9705 Touchscreen interface support"
depends on TOUCHSCREEN_WM97XX
+ default y
help
- Say Y here if you have a Wolfson Microelectronics WM9705
- touchscreen controller connected to your system.
-
- If unsure, say N.
+ Say Y here to enable support for the Wolfson Microelectronics
+ WM9705 touchscreen controller.
config TOUCHSCREEN_WM9712
bool "WM9712 Touchscreen interface support"
depends on TOUCHSCREEN_WM97XX
+ default y
help
- Say Y here if you have a Wolfson Microelectronics WM9712
- touchscreen controller connected to your system.
-
- If unsure, say N.
+ Say Y here to enable support for the Wolfson Microelectronics
+ WM9712 touchscreen controller.
config TOUCHSCREEN_WM9713
bool "WM9713 Touchscreen interface support"
depends on TOUCHSCREEN_WM97XX
+ default y
help
- Say Y here if you have a Wolfson Microelectronics WM9713 touchscreen
- controller connected to your system.
-
- If unsure, say N.
+ Say Y here to enable support for the Wolfson Microelectronics
+ WM9713 touchscreen controller.
config TOUCHSCREEN_WM97XX_MAINSTONE
tristate "WM97xx Mainstone accelerated touch"
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c
index c1cd99d5898..504ca11749a 100644
--- a/drivers/input/touchscreen/migor_ts.c
+++ b/drivers/input/touchscreen/migor_ts.c
@@ -173,7 +173,7 @@ static int migor_ts_probe(struct i2c_client *client,
input_set_abs_params(input, ABS_X, 95, 955, 0, 0);
input_set_abs_params(input, ABS_Y, 85, 935, 0, 0);
- input->name = client->driver_name;
+ input->name = client->name;
input->id.bustype = BUS_I2C;
input->dev.parent = &client->dev;
@@ -192,7 +192,7 @@ static int migor_ts_probe(struct i2c_client *client,
goto err1;
error = request_irq(priv->irq, migor_ts_isr, IRQF_TRIGGER_LOW,
- client->driver_name, priv);
+ client->name, priv);
if (error) {
dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
goto err2;
@@ -224,12 +224,19 @@ static int migor_ts_remove(struct i2c_client *client)
return 0;
}
+static const struct i2c_device_id migor_ts_id[] = {
+ { "migor_ts", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, migor_ts);
+
static struct i2c_driver migor_ts_driver = {
.driver = {
.name = "migor_ts",
},
.probe = migor_ts_probe,
.remove = migor_ts_remove,
+ .id_table = migor_ts_id,
};
static int __init migor_ts_init(void)
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
index 978e1a13ffc..372efbc694f 100644
--- a/drivers/input/touchscreen/wm9705.c
+++ b/drivers/input/touchscreen/wm9705.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/delay.h>
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
index 4c5d85a249a..c8bb1e7335f 100644
--- a/drivers/input/touchscreen/wm9712.c
+++ b/drivers/input/touchscreen/wm9712.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/delay.h>
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
index 838458792ea..781ee83547e 100644
--- a/drivers/input/touchscreen/wm9713.c
+++ b/drivers/input/touchscreen/wm9713.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/delay.h>
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index cdc24ad314e..d589ab0e3ad 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -37,7 +37,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c7aae66c6f9..8cfadc5bd2b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2393,6 +2393,8 @@ static void analyze_sbs(mddev_t * mddev)
}
+static void md_safemode_timeout(unsigned long data);
+
static ssize_t
safe_delay_show(mddev_t *mddev, char *page)
{
@@ -2432,9 +2434,12 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
if (msec == 0)
mddev->safemode_delay = 0;
else {
+ unsigned long old_delay = mddev->safemode_delay;
mddev->safemode_delay = (msec*HZ)/1000;
if (mddev->safemode_delay == 0)
mddev->safemode_delay = 1;
+ if (mddev->safemode_delay < old_delay)
+ md_safemode_timeout((unsigned long)mddev);
}
return len;
}
@@ -4634,6 +4639,11 @@ static int update_size(mddev_t *mddev, sector_t num_sectors)
*/
if (mddev->sync_thread)
return -EBUSY;
+ if (mddev->bitmap)
+ /* Sorry, cannot grow a bitmap yet, just remove it,
+ * grow, and re-add.
+ */
+ return -EBUSY;
rdev_for_each(rdev, tmp, mddev) {
sector_t avail;
avail = rdev->size * 2;
@@ -5993,7 +6003,7 @@ static int remove_and_add_spares(mddev_t *mddev)
}
}
- if (mddev->degraded) {
+ if (mddev->degraded && ! mddev->ro) {
rdev_for_each(rdev, rtmp, mddev) {
if (rdev->raid_disk >= 0 &&
!test_bit(In_sync, &rdev->flags) &&
@@ -6067,6 +6077,8 @@ void md_check_recovery(mddev_t *mddev)
flush_signals(current);
}
+ if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
+ return;
if ( ! (
(mddev->flags && !mddev->external) ||
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
@@ -6080,6 +6092,15 @@ void md_check_recovery(mddev_t *mddev)
if (mddev_trylock(mddev)) {
int spares = 0;
+ if (mddev->ro) {
+ /* Only thing we do on a ro array is remove
+ * failed devices.
+ */
+ remove_and_add_spares(mddev);
+ clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ goto unlock;
+ }
+
if (!mddev->external) {
int did_change = 0;
spin_lock_irq(&mddev->write_lock);
@@ -6117,7 +6138,8 @@ void md_check_recovery(mddev_t *mddev)
/* resync has finished, collect result */
md_unregister_thread(mddev->sync_thread);
mddev->sync_thread = NULL;
- if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
+ if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
+ !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
/* success...*/
/* activate any spares */
if (mddev->pers->spare_active(mddev))
@@ -6169,6 +6191,7 @@ void md_check_recovery(mddev_t *mddev)
} else if ((spares = remove_and_add_spares(mddev))) {
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+ clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
} else if (mddev->recovery_cp < MaxSector) {
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
@@ -6232,7 +6255,11 @@ static int md_notify_reboot(struct notifier_block *this,
for_each_mddev(mddev, tmp)
if (mddev_trylock(mddev)) {
- do_md_stop (mddev, 1, 0);
+ /* Force a switch to readonly even array
+ * appears to still be in use. Hence
+ * the '100'.
+ */
+ do_md_stop (mddev, 1, 100);
mddev_unlock(mddev);
}
/*
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index d41bebb6da0..e34cd0e6247 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -76,11 +76,13 @@ static void r10bio_pool_free(void *r10_bio, void *data)
kfree(r10_bio);
}
+/* Maximum size of each resync request */
#define RESYNC_BLOCK_SIZE (64*1024)
-//#define RESYNC_BLOCK_SIZE PAGE_SIZE
-#define RESYNC_SECTORS (RESYNC_BLOCK_SIZE >> 9)
#define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
-#define RESYNC_WINDOW (2048*1024)
+/* amount of memory to reserve for resync requests */
+#define RESYNC_WINDOW (1024*1024)
+/* maximum number of concurrent requests, memory permitting */
+#define RESYNC_DEPTH (32*1024*1024/RESYNC_BLOCK_SIZE)
/*
* When performing a resync, we need to read and compare, so
@@ -690,7 +692,6 @@ static int flush_pending_writes(conf_t *conf)
* there is no normal IO happeing. It must arrange to call
* lower_barrier when the particular background IO completes.
*/
-#define RESYNC_DEPTH 32
static void raise_barrier(conf_t *conf, int force)
{
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 40e93967565..224de022e7c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2568,10 +2568,10 @@ static bool handle_stripe5(struct stripe_head *sh)
if (dev->written)
s.written++;
rdev = rcu_dereference(conf->disks[i].rdev);
- if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
+ if (blocked_rdev == NULL &&
+ rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
- break;
}
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
/* The ReadError flag will just be confusing now */
@@ -2588,8 +2588,14 @@ static bool handle_stripe5(struct stripe_head *sh)
rcu_read_unlock();
if (unlikely(blocked_rdev)) {
- set_bit(STRIPE_HANDLE, &sh->state);
- goto unlock;
+ if (s.syncing || s.expanding || s.expanded ||
+ s.to_write || s.written) {
+ set_bit(STRIPE_HANDLE, &sh->state);
+ goto unlock;
+ }
+ /* There is nothing for the blocked_rdev to block */
+ rdev_dec_pending(blocked_rdev, conf->mddev);
+ blocked_rdev = NULL;
}
if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) {
@@ -2832,10 +2838,10 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
if (dev->written)
s.written++;
rdev = rcu_dereference(conf->disks[i].rdev);
- if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
+ if (blocked_rdev == NULL &&
+ rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
- break;
}
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
/* The ReadError flag will just be confusing now */
@@ -2853,9 +2859,16 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
rcu_read_unlock();
if (unlikely(blocked_rdev)) {
- set_bit(STRIPE_HANDLE, &sh->state);
- goto unlock;
+ if (s.syncing || s.expanding || s.expanded ||
+ s.to_write || s.written) {
+ set_bit(STRIPE_HANDLE, &sh->state);
+ goto unlock;
+ }
+ /* There is nothing for the blocked_rdev to block */
+ rdev_dec_pending(blocked_rdev, conf->mddev);
+ blocked_rdev = NULL;
}
+
pr_debug("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d,%d\n",
s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
@@ -4446,6 +4459,9 @@ static int raid5_check_reshape(mddev_t *mddev)
return -EINVAL; /* Cannot shrink array or change level yet */
if (mddev->delta_disks == 0)
return 0; /* nothing to do */
+ if (mddev->bitmap)
+ /* Cannot grow a bitmap yet */
+ return -EBUSY;
/* Can only proceed if there are plenty of stripe_heads.
* We need a minimum of one full stripe,, and for sensible progress
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index e7a3fe508df..b2d9878dc3f 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -803,11 +803,30 @@ static acpi_status get_u32(u32 *value, u32 cap)
static acpi_status set_u32(u32 value, u32 cap)
{
+ acpi_status status;
+
if (interface->capability & cap) {
switch (interface->type) {
case ACER_AMW0:
return AMW0_set_u32(value, cap, interface);
case ACER_AMW0_V2:
+ if (cap == ACER_CAP_MAILLED)
+ return AMW0_set_u32(value, cap, interface);
+
+ /*
+ * On some models, some WMID methods don't toggle
+ * properly. For those cases, we want to run the AMW0
+ * method afterwards to be certain we've really toggled
+ * the device state.
+ */
+ if (cap == ACER_CAP_WIRELESS ||
+ cap == ACER_CAP_BLUETOOTH) {
+ status = WMID_set_u32(value, cap, interface);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ return AMW0_set_u32(value, cap, interface);
+ }
case ACER_WMID:
return WMID_set_u32(value, cap, interface);
default:
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c
index 9e8d79e7e9f..facdb9893c8 100644
--- a/drivers/misc/eeepc-laptop.c
+++ b/drivers/misc/eeepc-laptop.c
@@ -553,9 +553,9 @@ static void eeepc_hwmon_exit(void)
hwmon = eeepc_hwmon_device;
if (!hwmon)
return ;
- hwmon_device_unregister(hwmon);
sysfs_remove_group(&hwmon->kobj,
&hwmon_attribute_group);
+ hwmon_device_unregister(hwmon);
eeepc_hwmon_device = NULL;
}
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 7c994e1ae27..ae16d845d74 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -595,8 +595,9 @@ static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)
return IRQ_HANDLED;
}
-void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
- int size, enum s3c2410_dma_buffresult result)
+static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch,
+ void *buf_id, int size,
+ enum s3c2410_dma_buffresult result)
{
struct s3cmci_host *host = buf_id;
unsigned long iflags;
@@ -740,8 +741,8 @@ request_done:
mmc_request_done(host->mmc, mrq);
}
-
-void s3cmci_dma_setup(struct s3cmci_host *host, enum s3c2410_dmasrc source)
+static void s3cmci_dma_setup(struct s3cmci_host *host,
+ enum s3c2410_dmasrc source)
{
static enum s3c2410_dmasrc last_source = -1;
static int setup_ok;
@@ -1003,8 +1004,9 @@ static void s3cmci_send_request(struct mmc_host *mmc)
enable_irq(host->irq);
}
-static int s3cmci_card_present(struct s3cmci_host *host)
+static int s3cmci_card_present(struct mmc_host *mmc)
{
+ struct s3cmci_host *host = mmc_priv(mmc);
struct s3c24xx_mci_pdata *pdata = host->pdata;
int ret;
@@ -1023,7 +1025,7 @@ static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
host->cmd_is_stop = 0;
host->mrq = mrq;
- if (s3cmci_card_present(host) == 0) {
+ if (s3cmci_card_present(mmc) == 0) {
dbg(host, dbg_err, "%s: no medium present\n", __func__);
host->mrq->cmd->error = -ENOMEDIUM;
mmc_request_done(mmc, mrq);
@@ -1138,6 +1140,7 @@ static struct mmc_host_ops s3cmci_ops = {
.request = s3cmci_request,
.set_ios = s3cmci_set_ios,
.get_ro = s3cmci_get_ro,
+ .get_cd = s3cmci_card_present,
};
static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
@@ -1206,7 +1209,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
}
host->base = ioremap(host->mem->start, RESSIZE(host->mem));
- if (host->base == 0) {
+ if (!host->base) {
dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
ret = -EINVAL;
goto probe_free_mem_region;
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c
index f99e9f72162..1df44d966bd 100644
--- a/drivers/mmc/host/sdricoh_cs.c
+++ b/drivers/mmc/host/sdricoh_cs.c
@@ -29,7 +29,6 @@
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/scatterlist.h>
-#include <linux/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 64002488c6e..917cf8d3ae9 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -19,7 +19,7 @@
#include <asm/io.h>
#include <asm/sizes.h>
#include <mach/hardware.h>
-#include <asm/plat-orion/orion_nand.h>
+#include <plat/orion_nand.h>
#ifdef CONFIG_MTD_CMDLINE_PARTS
static const char *part_probes[] = { "cmdlinepart", NULL };
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index b468f904c7f..a14dba1afcc 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -271,7 +271,7 @@ struct bnx2x_fastpath {
(fp->tx_pkt_prod != fp->tx_pkt_cons))
#define BNX2X_HAS_RX_WORK(fp) \
- (fp->rx_comp_cons != le16_to_cpu(*fp->rx_cons_sb))
+ (fp->rx_comp_cons != rx_cons_sb)
#define BNX2X_HAS_WORK(fp) (BNX2X_HAS_RX_WORK(fp) || BNX2X_HAS_TX_WORK(fp))
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 971576b4368..82deea0a63f 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -59,8 +59,8 @@
#include "bnx2x.h"
#include "bnx2x_init.h"
-#define DRV_MODULE_VERSION "1.45.17"
-#define DRV_MODULE_RELDATE "2008/08/13"
+#define DRV_MODULE_VERSION "1.45.20"
+#define DRV_MODULE_RELDATE "2008/08/25"
#define BNX2X_BC_VER 0x040200
/* Time in jiffies before concluding the transmitter is hung */
@@ -1717,8 +1717,8 @@ static int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource)
return -EEXIST;
}
- /* Try for 1 second every 5ms */
- for (cnt = 0; cnt < 200; cnt++) {
+ /* Try for 5 second every 5ms */
+ for (cnt = 0; cnt < 1000; cnt++) {
/* Try to acquire the lock */
REG_WR(bp, hw_lock_control_reg + 4, resource_bit);
lock_status = REG_RD(bp, hw_lock_control_reg);
@@ -2550,6 +2550,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
BNX2X_ERR("SPIO5 hw attention\n");
switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+ case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1021G:
case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
/* Fan failure attention */
@@ -4605,6 +4606,17 @@ static void bnx2x_init_internal_common(struct bnx2x *bp)
{
int i;
+ if (bp->flags & TPA_ENABLE_FLAG) {
+ struct tstorm_eth_tpa_exist tpa = {0};
+
+ tpa.tpa_exist = 1;
+
+ REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET,
+ ((u32 *)&tpa)[0]);
+ REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET + 4,
+ ((u32 *)&tpa)[1]);
+ }
+
/* Zero this manually as its initialization is
currently missing in the initTool */
for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
@@ -5337,6 +5349,7 @@ static int bnx2x_init_common(struct bnx2x *bp)
}
switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+ case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1021G:
case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
/* Fan failure is indicated by SPIO 5 */
bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
@@ -5363,17 +5376,6 @@ static int bnx2x_init_common(struct bnx2x *bp)
enable_blocks_attention(bp);
- if (bp->flags & TPA_ENABLE_FLAG) {
- struct tstorm_eth_tpa_exist tmp = {0};
-
- tmp.tpa_exist = 1;
-
- REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET,
- ((u32 *)&tmp)[0]);
- REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET + 4,
- ((u32 *)&tmp)[1]);
- }
-
if (!BP_NOMCP(bp)) {
bnx2x_acquire_phy_lock(bp);
bnx2x_common_init_phy(bp, bp->common.shmem_base);
@@ -5531,6 +5533,7 @@ static int bnx2x_init_port(struct bnx2x *bp)
/* Port DMAE comes here */
switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+ case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1021G:
case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
/* add SPIO 5 to group 0 */
val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
@@ -6055,6 +6058,44 @@ static int bnx2x_req_irq(struct bnx2x *bp)
return rc;
}
+static void bnx2x_napi_enable(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_queue(bp, i)
+ napi_enable(&bnx2x_fp(bp, i, napi));
+}
+
+static void bnx2x_napi_disable(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_queue(bp, i)
+ napi_disable(&bnx2x_fp(bp, i, napi));
+}
+
+static void bnx2x_netif_start(struct bnx2x *bp)
+{
+ if (atomic_dec_and_test(&bp->intr_sem)) {
+ if (netif_running(bp->dev)) {
+ if (bp->state == BNX2X_STATE_OPEN)
+ netif_wake_queue(bp->dev);
+ bnx2x_napi_enable(bp);
+ bnx2x_int_enable(bp);
+ }
+ }
+}
+
+static void bnx2x_netif_stop(struct bnx2x *bp)
+{
+ bnx2x_int_disable_sync(bp);
+ if (netif_running(bp->dev)) {
+ bnx2x_napi_disable(bp);
+ netif_tx_disable(bp->dev);
+ bp->dev->trans_start = jiffies; /* prevent tx timeout */
+ }
+}
+
/*
* Init service functions
*/
@@ -6338,7 +6379,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = bnx2x_init_hw(bp, load_code);
if (rc) {
BNX2X_ERR("HW init failed, aborting\n");
- goto load_error;
+ goto load_int_disable;
}
/* Setup NIC internals and enable interrupts */
@@ -6350,7 +6391,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
- goto load_int_disable;
+ goto load_rings_free;
}
}
@@ -6360,8 +6401,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Enable Rx interrupt handling before sending the ramrod
as it's completed on Rx FP queue */
- for_each_queue(bp, i)
- napi_enable(&bnx2x_fp(bp, i, napi));
+ bnx2x_napi_enable(bp);
/* Enable interrupt handling */
atomic_set(&bp->intr_sem, 0);
@@ -6369,7 +6409,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = bnx2x_setup_leading(bp);
if (rc) {
BNX2X_ERR("Setup leading failed!\n");
- goto load_stop_netif;
+ goto load_netif_stop;
}
if (CHIP_IS_E1H(bp))
@@ -6382,7 +6422,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
for_each_nondefault_queue(bp, i) {
rc = bnx2x_setup_multi(bp, i);
if (rc)
- goto load_stop_netif;
+ goto load_netif_stop;
}
if (CHIP_IS_E1(bp))
@@ -6427,20 +6467,17 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
return 0;
-load_stop_netif:
+load_netif_stop:
+ bnx2x_napi_disable(bp);
+load_rings_free:
+ /* Free SKBs, SGEs, TPA pool and driver internals */
+ bnx2x_free_skbs(bp);
for_each_queue(bp, i)
- napi_disable(&bnx2x_fp(bp, i, napi));
-
+ bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
load_int_disable:
bnx2x_int_disable_sync(bp);
-
/* Release IRQs */
bnx2x_free_irq(bp);
-
- /* Free SKBs, SGEs, TPA pool and driver internals */
- bnx2x_free_skbs(bp);
- for_each_queue(bp, i)
- bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
load_error:
bnx2x_free_mem(bp);
@@ -6455,7 +6492,7 @@ static int bnx2x_stop_multi(struct bnx2x *bp, int index)
/* halt the connection */
bp->fp[index].state = BNX2X_FP_STATE_HALTING;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, 0, 0);
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, index, 0);
/* Wait for completion */
rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, index,
@@ -6613,11 +6650,9 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bp->rx_mode = BNX2X_RX_MODE_NONE;
bnx2x_set_storm_rx_mode(bp);
- if (netif_running(bp->dev)) {
- netif_tx_disable(bp->dev);
- bp->dev->trans_start = jiffies; /* prevent tx timeout */
- }
-
+ bnx2x_netif_stop(bp);
+ if (!netif_running(bp->dev))
+ bnx2x_napi_disable(bp);
del_timer_sync(&bp->timer);
SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb,
(DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
@@ -6631,9 +6666,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
smp_rmb();
while (BNX2X_HAS_TX_WORK(fp)) {
- if (!netif_running(bp->dev))
- bnx2x_tx_int(fp, 1000);
-
+ bnx2x_tx_int(fp, 1000);
if (!cnt) {
BNX2X_ERR("timeout waiting for queue[%d]\n",
i);
@@ -6649,46 +6682,12 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
smp_rmb();
}
}
-
/* Give HW time to discard old tx messages */
msleep(1);
- for_each_queue(bp, i)
- napi_disable(&bnx2x_fp(bp, i, napi));
- /* Disable interrupts after Tx and Rx are disabled on stack level */
- bnx2x_int_disable_sync(bp);
-
/* Release IRQs */
bnx2x_free_irq(bp);
- if (unload_mode == UNLOAD_NORMAL)
- reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-
- else if (bp->flags & NO_WOL_FLAG) {
- reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
- if (CHIP_IS_E1H(bp))
- REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
-
- } else if (bp->wol) {
- u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
- u8 *mac_addr = bp->dev->dev_addr;
- u32 val;
- /* The mac address is written to entries 1-4 to
- preserve entry 0 which is used by the PMF */
- u8 entry = (BP_E1HVN(bp) + 1)*8;
-
- val = (mac_addr[0] << 8) | mac_addr[1];
- EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry, val);
-
- val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
- (mac_addr[4] << 8) | mac_addr[5];
- EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val);
-
- reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN;
-
- } else
- reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-
if (CHIP_IS_E1(bp)) {
struct mac_configuration_cmd *config =
bnx2x_sp(bp, mcast_config);
@@ -6711,14 +6710,41 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0);
} else { /* E1H */
+ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+
bnx2x_set_mac_addr_e1h(bp, 0);
for (i = 0; i < MC_HASH_SIZE; i++)
REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
}
- if (CHIP_IS_E1H(bp))
- REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+ if (unload_mode == UNLOAD_NORMAL)
+ reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
+
+ else if (bp->flags & NO_WOL_FLAG) {
+ reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
+ if (CHIP_IS_E1H(bp))
+ REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
+
+ } else if (bp->wol) {
+ u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+ u8 *mac_addr = bp->dev->dev_addr;
+ u32 val;
+ /* The mac address is written to entries 1-4 to
+ preserve entry 0 which is used by the PMF */
+ u8 entry = (BP_E1HVN(bp) + 1)*8;
+
+ val = (mac_addr[0] << 8) | mac_addr[1];
+ EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry, val);
+
+ val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
+ (mac_addr[4] << 8) | mac_addr[5];
+ EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val);
+
+ reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN;
+
+ } else
+ reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
/* Close multi and leading connections
Completions for ramrods are collected in a synchronous way */
@@ -6821,6 +6847,10 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
*/
bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
+ if (val == 0x7)
+ REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
+
if (val == 0x7) {
u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
/* save our func */
@@ -6898,7 +6928,6 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
(SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
DRV_MSG_SEQ_NUMBER_MASK);
}
- bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
}
}
@@ -8617,34 +8646,6 @@ test_mem_exit:
return rc;
}
-static void bnx2x_netif_start(struct bnx2x *bp)
-{
- int i;
-
- if (atomic_dec_and_test(&bp->intr_sem)) {
- if (netif_running(bp->dev)) {
- bnx2x_int_enable(bp);
- for_each_queue(bp, i)
- napi_enable(&bnx2x_fp(bp, i, napi));
- if (bp->state == BNX2X_STATE_OPEN)
- netif_wake_queue(bp->dev);
- }
- }
-}
-
-static void bnx2x_netif_stop(struct bnx2x *bp)
-{
- int i;
-
- if (netif_running(bp->dev)) {
- netif_tx_disable(bp->dev);
- bp->dev->trans_start = jiffies; /* prevent tx timeout */
- for_each_queue(bp, i)
- napi_disable(&bnx2x_fp(bp, i, napi));
- }
- bnx2x_int_disable_sync(bp);
-}
-
static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up)
{
int cnt = 1000;
@@ -9250,6 +9251,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
napi);
struct bnx2x *bp = fp->bp;
int work_done = 0;
+ u16 rx_cons_sb;
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
@@ -9265,10 +9267,16 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
if (BNX2X_HAS_TX_WORK(fp))
bnx2x_tx_int(fp, budget);
+ rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
+ if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
+ rx_cons_sb++;
if (BNX2X_HAS_RX_WORK(fp))
work_done = bnx2x_rx_int(fp, budget);
rmb(); /* BNX2X_HAS_WORK() reads the status block */
+ rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
+ if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
+ rx_cons_sb++;
/* must not complete if we consumed full budget */
if ((work_done < budget) && !BNX2X_HAS_WORK(fp)) {
@@ -9484,8 +9492,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
fp_index = (smp_processor_id() % bp->num_queues);
fp = &bp->fp[fp_index];
- if (unlikely(bnx2x_tx_avail(bp->fp) <
- (skb_shinfo(skb)->nr_frags + 3))) {
+ if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) {
bp->eth_stats.driver_xoff++,
netif_stop_queue(dev);
BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
@@ -9548,7 +9555,6 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_bd->vlan = cpu_to_le16(pkt_prod);
if (xmit_type) {
-
/* turn on parsing and get a BD */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
pbd = (void *)&fp->tx_desc_ring[bd_prod];
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 8a1d93a2bb8..51e5214071d 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -57,6 +57,15 @@ static ssize_t devspec_show(struct device *dev,
return sprintf(buf, "%s\n", ofdev->node->full_name);
}
+static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct of_device *ofdev;
+
+ ofdev = to_of_device(dev);
+ return sprintf(buf, "%s\n", ofdev->node->name);
+}
+
static ssize_t modalias_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -71,6 +80,7 @@ static ssize_t modalias_show(struct device *dev,
struct device_attribute of_platform_device_attrs[] = {
__ATTR_RO(devspec),
+ __ATTR_RO(name),
__ATTR_RO(modalias),
__ATTR_NULL
};
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 93e37f0666a..e17ef54f0ef 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -382,7 +382,7 @@ EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
{
acpi_status status;
- acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+ acpi_handle chandle, handle;
struct pci_dev *pdev = dev;
struct pci_bus *parent;
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -399,10 +399,25 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
* Per PCI firmware specification, we should run the ACPI _OSC
* method to get control of hotplug hardware before using it. If
* an _OSC is missing, we look for an OSHP to do the same thing.
- * To handle different BIOS behavior, we look for _OSC and OSHP
- * within the scope of the hotplug controller and its parents,
+ * To handle different BIOS behavior, we look for _OSC on a root
+ * bridge preferentially (according to PCI fw spec). Later for
+ * OSHP within the scope of the hotplug controller and its parents,
* upto the host bridge under which this controller exists.
*/
+ handle = acpi_find_root_bridge_handle(pdev);
+ if (handle) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
+ dbg("Trying to get hotplug control for %s\n",
+ (char *)string.pointer);
+ status = pci_osc_control_set(handle, flags);
+ if (ACPI_SUCCESS(status))
+ goto got_one;
+ kfree(string.pointer);
+ string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };
+ }
+
+ pdev = dev;
+ handle = DEVICE_ACPI_HANDLE(&dev->dev);
while (!handle) {
/*
* This hotplug controller was not listed in the ACPI name
@@ -427,15 +442,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
dbg("Trying to get hotplug control for %s \n",
(char *)string.pointer);
- status = pci_osc_control_set(handle, flags);
- if (status == AE_NOT_FOUND)
- status = acpi_run_oshp(handle);
- if (ACPI_SUCCESS(status)) {
- dbg("Gained control for hotplug HW for pci %s (%s)\n",
- pci_name(dev), (char *)string.pointer);
- kfree(string.pointer);
- return 0;
- }
+ status = acpi_run_oshp(handle);
+ if (ACPI_SUCCESS(status))
+ goto got_one;
if (acpi_root_bridge(handle))
break;
chandle = handle;
@@ -449,6 +458,11 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
kfree(string.pointer);
return -ENODEV;
+got_one:
+ dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev),
+ (char *)string.pointer);
+ kfree(string.pointer);
+ return 0;
}
EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index 30f581b8791..6dd7b13e980 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -36,12 +36,7 @@ int aer_osc_setup(struct pcie_device *pciedev)
if (acpi_pci_disabled)
return -1;
- /* Find root host bridge */
- while (pdev->bus->self)
- pdev = pdev->bus->self;
- handle = acpi_get_pci_rootbridge_handle(
- pci_domain_nr(pdev->bus), pdev->bus->number);
-
+ handle = acpi_find_root_bridge_handle(pdev);
if (handle) {
pcie_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
status = pci_osc_control_set(handle,
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index a04498d390c..cce2f4cb1fb 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -383,6 +383,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->start = base;
if (!res->end)
res->end = limit + 0xfff;
+ printk(KERN_INFO "PCI: bridge %s io port: [%llx, %llx]\n", pci_name(dev), res->start, res->end);
}
res = child->resource[1];
@@ -394,6 +395,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
res->start = base;
res->end = limit + 0xfffff;
+ printk(KERN_INFO "PCI: bridge %s 32bit mmio: [%llx, %llx]\n", pci_name(dev), res->start, res->end);
}
res = child->resource[2];
@@ -429,6 +431,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
res->start = base;
res->end = limit + 0xfffff;
+ printk(KERN_INFO "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n", pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64)?"64":"32",res->start, res->end);
}
}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 827c0a520e2..82634a2f1b1 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -530,6 +530,36 @@ void __ref pci_bus_assign_resources(struct pci_bus *bus)
}
EXPORT_SYMBOL(pci_bus_assign_resources);
+static void pci_bus_dump_res(struct pci_bus *bus)
+{
+ int i;
+
+ for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
+ struct resource *res = bus->resource[i];
+ if (!res)
+ continue;
+
+ printk(KERN_INFO "bus: %02x index %x %s: [%llx, %llx]\n", bus->number, i, (res->flags & IORESOURCE_IO)? "io port":"mmio", res->start, res->end);
+ }
+}
+
+static void pci_bus_dump_resources(struct pci_bus *bus)
+{
+ struct pci_bus *b;
+ struct pci_dev *dev;
+
+
+ pci_bus_dump_res(bus);
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ b = dev->subordinate;
+ if (!b)
+ continue;
+
+ pci_bus_dump_resources(b);
+ }
+}
+
void __init
pci_assign_unassigned_resources(void)
{
@@ -545,4 +575,9 @@ pci_assign_unassigned_resources(void)
pci_bus_assign_resources(bus);
pci_enable_bridges(bus);
}
+
+ /* dump the resource on buses */
+ list_for_each_entry(bus, &pci_root_buses, node) {
+ pci_bus_dump_resources(bus);
+ }
}
diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c
index a8771ffc61e..e07b5c51ec5 100644
--- a/drivers/pcmcia/pxa2xx_palmtx.c
+++ b/drivers/pcmcia/pxa2xx_palmtx.c
@@ -23,12 +23,57 @@
static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
- skt->irq = IRQ_GPIO(GPIO_NR_PALMTX_PCMCIA_READY);
+ int ret;
+
+ ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER1, "PCMCIA PWR1");
+ if (ret)
+ goto err1;
+ ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER1, 0);
+ if (ret)
+ goto err2;
+
+ ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER2, "PCMCIA PWR2");
+ if (ret)
+ goto err2;
+ ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER2, 0);
+ if (ret)
+ goto err3;
+
+ ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_RESET, "PCMCIA RST");
+ if (ret)
+ goto err3;
+ ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_RESET, 1);
+ if (ret)
+ goto err4;
+
+ ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_READY, "PCMCIA RDY");
+ if (ret)
+ goto err4;
+ ret = gpio_direction_input(GPIO_NR_PALMTX_PCMCIA_READY);
+ if (ret)
+ goto err5;
+
+ skt->irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY);
return 0;
+
+err5:
+ gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
+err4:
+ gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
+err3:
+ gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
+err2:
+ gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
+err1:
+ return ret;
}
static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
{
+ gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
+ gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
+ gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
+ gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
}
static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
@@ -109,7 +154,7 @@ static void __exit palmtx_pcmcia_exit(void)
platform_device_unregister(palmtx_pcmcia_device);
}
-fs_initcall(palmtx_pcmcia_init);
+module_init(palmtx_pcmcia_init);
module_exit(palmtx_pcmcia_exit);
MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 90ab7382540..9a9755c92fa 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -561,7 +561,7 @@ config RTC_DRV_AT91SAM9_GPBR
config RTC_DRV_BFIN
tristate "Blackfin On-Chip RTC"
- depends on BLACKFIN
+ depends on BLACKFIN && !BF561
help
If you say yes here you will get support for the
Blackfin On-Chip Real Time Clock.
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c
index a1af4c27939..34439ce3967 100644
--- a/drivers/rtc/rtc-bfin.c
+++ b/drivers/rtc/rtc-bfin.c
@@ -218,26 +218,6 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
-static int bfin_rtc_open(struct device *dev)
-{
- int ret;
-
- dev_dbg_stamp(dev);
-
- ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev);
- if (!ret)
- bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE);
-
- return ret;
-}
-
-static void bfin_rtc_release(struct device *dev)
-{
- dev_dbg_stamp(dev);
- bfin_rtc_reset(dev, 0);
- free_irq(IRQ_RTC, dev);
-}
-
static void bfin_rtc_int_set(u16 rtc_int)
{
bfin_write_RTC_ISTAT(rtc_int);
@@ -370,8 +350,6 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq)
}
static struct rtc_class_ops bfin_rtc_ops = {
- .open = bfin_rtc_open,
- .release = bfin_rtc_release,
.ioctl = bfin_rtc_ioctl,
.read_time = bfin_rtc_read_time,
.set_time = bfin_rtc_set_time,
@@ -383,29 +361,44 @@ static struct rtc_class_ops bfin_rtc_ops = {
static int __devinit bfin_rtc_probe(struct platform_device *pdev)
{
struct bfin_rtc *rtc;
+ struct device *dev = &pdev->dev;
int ret = 0;
+ unsigned long timeout;
- dev_dbg_stamp(&pdev->dev);
+ dev_dbg_stamp(dev);
+ /* Allocate memory for our RTC struct */
rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
if (unlikely(!rtc))
return -ENOMEM;
+ platform_set_drvdata(pdev, rtc);
+ device_init_wakeup(dev, 1);
- rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
- ret = PTR_ERR(rtc->rtc_dev);
+ /* Grab the IRQ and init the hardware */
+ ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev);
+ if (unlikely(ret))
goto err;
- }
-
- /* see comment at top of file about stopwatch/PIE */
+ /* sometimes the bootloader touched things, but the write complete was not
+ * enabled, so let's just do a quick timeout here since the IRQ will not fire ...
+ */
+ timeout = jiffies + HZ;
+ while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)
+ if (time_after(jiffies, timeout))
+ break;
+ bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE);
bfin_write_RTC_SWCNT(0);
- platform_set_drvdata(pdev, rtc);
-
- device_init_wakeup(&pdev->dev, 1);
+ /* Register our RTC with the RTC framework */
+ rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE);
+ if (unlikely(IS_ERR(rtc))) {
+ ret = PTR_ERR(rtc->rtc_dev);
+ goto err_irq;
+ }
return 0;
+ err_irq:
+ free_irq(IRQ_RTC, dev);
err:
kfree(rtc);
return ret;
@@ -414,7 +407,10 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev)
static int __devexit bfin_rtc_remove(struct platform_device *pdev)
{
struct bfin_rtc *rtc = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ bfin_rtc_reset(dev, 0);
+ free_irq(IRQ_RTC, dev);
rtc_device_unregister(rtc->rtc_dev);
platform_set_drvdata(pdev, NULL);
kfree(rtc);
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 35dcc06eb3e..f118252f3a9 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -403,11 +403,14 @@ static long rtc_dev_ioctl(struct file *file,
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
case RTC_UIE_OFF:
+ mutex_unlock(&rtc->ops_lock);
clear_uie(rtc);
- break;
+ return 0;
case RTC_UIE_ON:
+ mutex_unlock(&rtc->ops_lock);
err = set_uie(rtc);
+ return err;
#endif
default:
err = -ENOTTY;
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 640acd20fdd..a150418fba7 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -173,7 +173,7 @@ static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
int cr, sr;
int ret = 0;
- if (client->irq < 0)
+ if (client->irq <= 0)
return -EINVAL;
mutex_lock(&ds1374->mutex);
@@ -212,7 +212,7 @@ static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
int cr;
int ret = 0;
- if (client->irq < 0)
+ if (client->irq <= 0)
return -EINVAL;
ret = ds1374_read_time(dev, &now);
@@ -381,7 +381,7 @@ static int ds1374_probe(struct i2c_client *client,
if (ret)
goto out_free;
- if (client->irq >= 0) {
+ if (client->irq > 0) {
ret = request_irq(client->irq, ds1374_irq, 0,
"ds1374", client);
if (ret) {
@@ -401,7 +401,7 @@ static int ds1374_probe(struct i2c_client *client,
return 0;
out_irq:
- if (client->irq >= 0)
+ if (client->irq > 0)
free_irq(client->irq, client);
out_free:
@@ -414,7 +414,7 @@ static int __devexit ds1374_remove(struct i2c_client *client)
{
struct ds1374 *ds1374 = i2c_get_clientdata(client);
- if (client->irq >= 0) {
+ if (client->irq > 0) {
mutex_lock(&ds1374->mutex);
ds1374->exiting = 1;
mutex_unlock(&ds1374->mutex);
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index e7c7b4ebc1f..2dee69da35c 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -376,7 +376,7 @@ static int get_lun(struct scsi_device *sdev, struct rdac_dh_data *h)
if (inqp->page_id[0] != 'e' || inqp->page_id[1] != 'd' ||
inqp->page_id[2] != 'i' || inqp->page_id[3] != 'd')
return SCSI_DH_NOSYS;
- h->lun = scsilun_to_int((struct scsi_lun *)inqp->lun);
+ h->lun = inqp->lun[7]; /* Uses only the last byte */
}
return err;
}
@@ -386,6 +386,7 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
int err;
struct c9_inquiry *inqp;
+ h->lun_state = RDAC_LUN_UNOWNED;
err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h);
if (err == SCSI_DH_OK) {
inqp = &h->inq.c9;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index ae560bc04f9..4e0b7c8eb32 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -556,11 +556,12 @@ static void ibmvfc_link_down(struct ibmvfc_host *vhost,
/**
* ibmvfc_init_host - Start host initialization
* @vhost: ibmvfc host struct
+ * @relogin: is this a re-login?
*
* Return value:
* nothing
**/
-static void ibmvfc_init_host(struct ibmvfc_host *vhost)
+static void ibmvfc_init_host(struct ibmvfc_host *vhost, int relogin)
{
struct ibmvfc_target *tgt;
@@ -574,6 +575,11 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost)
}
if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
+ if (!relogin) {
+ memset(vhost->async_crq.msgs, 0, PAGE_SIZE);
+ vhost->async_crq.cur = 0;
+ }
+
list_for_each_entry(tgt, &vhost->targets, queue)
tgt->need_login = 1;
scsi_block_requests(vhost->host);
@@ -1059,9 +1065,10 @@ static void ibmvfc_get_starget_port_id(struct scsi_target *starget)
static int ibmvfc_wait_while_resetting(struct ibmvfc_host *vhost)
{
long timeout = wait_event_timeout(vhost->init_wait_q,
- (vhost->state == IBMVFC_ACTIVE ||
- vhost->state == IBMVFC_HOST_OFFLINE ||
- vhost->state == IBMVFC_LINK_DEAD),
+ ((vhost->state == IBMVFC_ACTIVE ||
+ vhost->state == IBMVFC_HOST_OFFLINE ||
+ vhost->state == IBMVFC_LINK_DEAD) &&
+ vhost->action == IBMVFC_HOST_ACTION_NONE),
(init_timeout * HZ));
return timeout ? 0 : -EIO;
@@ -1450,8 +1457,8 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
struct scsi_cmnd *cmnd = evt->cmnd;
- int rsp_len = 0;
- int sense_len = rsp->fcp_sense_len;
+ u32 rsp_len = 0;
+ u32 sense_len = rsp->fcp_sense_len;
if (cmnd) {
if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID)
@@ -1468,7 +1475,7 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
rsp_len = rsp->fcp_rsp_len;
if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE)
sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len;
- if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len)
+ if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8)
memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len);
ibmvfc_log_error(evt);
@@ -2077,17 +2084,18 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
{
const char *desc = ibmvfc_get_ae_desc(crq->event);
- ibmvfc_log(vhost, 3, "%s event received\n", desc);
+ ibmvfc_log(vhost, 3, "%s event received. scsi_id: %lx, wwpn: %lx,"
+ " node_name: %lx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name);
switch (crq->event) {
case IBMVFC_AE_LINK_UP:
case IBMVFC_AE_RESUME:
vhost->events_to_log |= IBMVFC_AE_LINKUP;
- ibmvfc_init_host(vhost);
+ ibmvfc_init_host(vhost, 1);
break;
case IBMVFC_AE_SCN_FABRIC:
vhost->events_to_log |= IBMVFC_AE_RSCN;
- ibmvfc_init_host(vhost);
+ ibmvfc_init_host(vhost, 1);
break;
case IBMVFC_AE_SCN_NPORT:
case IBMVFC_AE_SCN_GROUP:
@@ -2133,13 +2141,13 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
/* Send back a response */
rc = ibmvfc_send_crq_init_complete(vhost);
if (rc == 0)
- ibmvfc_init_host(vhost);
+ ibmvfc_init_host(vhost, 0);
else
dev_err(vhost->dev, "Unable to send init rsp. rc=%ld\n", rc);
break;
case IBMVFC_CRQ_INIT_COMPLETE:
dev_info(vhost->dev, "Partner initialization complete\n");
- ibmvfc_init_host(vhost);
+ ibmvfc_init_host(vhost, 0);
break;
default:
dev_err(vhost->dev, "Unknown crq message type: %d\n", crq->format);
@@ -3357,8 +3365,6 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost)
mad->buffer.va = vhost->login_buf_dma;
mad->buffer.len = sizeof(*vhost->login_buf);
- memset(vhost->async_crq.msgs, 0, PAGE_SIZE);
- vhost->async_crq.cur = 0;
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
if (!ibmvfc_send_event(evt, vhost, default_timeout))
@@ -3601,8 +3607,9 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
}
}
- if (vhost->reinit) {
+ if (vhost->reinit && !ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
vhost->reinit = 0;
+ scsi_block_requests(vhost->host);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
} else {
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 4bf6e374f07..fb3177ab669 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -29,8 +29,8 @@
#include "viosrp.h"
#define IBMVFC_NAME "ibmvfc"
-#define IBMVFC_DRIVER_VERSION "1.0.1"
-#define IBMVFC_DRIVER_DATE "(July 11, 2008)"
+#define IBMVFC_DRIVER_VERSION "1.0.2"
+#define IBMVFC_DRIVER_DATE "(August 14, 2008)"
#define IBMVFC_DEFAULT_TIMEOUT 15
#define IBMVFC_INIT_TIMEOUT 30
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 6b24b9cdb04..7b1502c0ab6 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1636,7 +1636,7 @@ static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev)
unsigned long desired_io = max_requests * sizeof(union viosrp_iu);
/* add io space for sg data */
- desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT *
+ desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * 512 *
IBMVSCSI_CMDS_PER_LUN_DEFAULT);
return desired_io;
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index fc7ac158476..97b763378e7 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_sas.c
- * Version : v00.00.03.20-rc1
+ * Version : v00.00.04.01-rc1
*
* Authors:
* (email-id : megaraidlinux@lsi.com)
@@ -71,6 +71,10 @@ static struct pci_device_id megasas_pci_table[] = {
/* ppc IOP */
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
/* ppc IOP */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)},
+ /* gen2*/
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)},
+ /* gen2*/
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
/* xscale IOP, vega */
{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
@@ -198,6 +202,9 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
*/
writel(status, &regs->outbound_intr_status);
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_intr_status);
+
return 0;
}
@@ -293,6 +300,9 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
*/
writel(status, &regs->outbound_doorbell_clear);
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_doorbell_clear);
+
return 0;
}
/**
@@ -318,6 +328,99 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
};
/**
+* The following functions are defined for gen2 (deviceid : 0x78 0x79)
+* controllers
+*/
+
+/**
+ * megasas_enable_intr_gen2 - Enables interrupts
+ * @regs: MFI register set
+ */
+static inline void
+megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
+{
+ writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
+
+ /* write ~0x00000005 (4 & 1) to the intr mask*/
+ writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
+
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr_gen2 - Disables interrupt
+ * @regs: MFI register set
+ */
+static inline void
+megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
+{
+ u32 mask = 0xFFFFFFFF;
+ writel(mask, &regs->outbound_intr_mask);
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_gen2 - returns the current FW status value
+ * @regs: MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
+{
+ return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_clear_interrupt_gen2 - Check & clear interrupt
+ * @regs: MFI register set
+ */
+static int
+megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
+{
+ u32 status;
+ /*
+ * Check if it is our interrupt
+ */
+ status = readl(&regs->outbound_intr_status);
+
+ if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK))
+ return 1;
+
+ /*
+ * Clear the interrupt by writing back the same value
+ */
+ writel(status, &regs->outbound_doorbell_clear);
+
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_intr_status);
+
+ return 0;
+}
+/**
+ * megasas_fire_cmd_gen2 - Sends command to the FW
+ * @frame_phys_addr : Physical address of cmd
+ * @frame_count : Number of frames for the command
+ * @regs : MFI register set
+ */
+static inline void
+megasas_fire_cmd_gen2(dma_addr_t frame_phys_addr, u32 frame_count,
+ struct megasas_register_set __iomem *regs)
+{
+ writel((frame_phys_addr | (frame_count<<1))|1,
+ &(regs)->inbound_queue_port);
+}
+
+static struct megasas_instance_template megasas_instance_template_gen2 = {
+
+ .fire_cmd = megasas_fire_cmd_gen2,
+ .enable_intr = megasas_enable_intr_gen2,
+ .disable_intr = megasas_disable_intr_gen2,
+ .clear_intr = megasas_clear_intr_gen2,
+ .read_fw_status_reg = megasas_read_fw_status_reg_gen2,
+};
+
+/**
* This is the end of set of functions & definitions
* specific to ppc (deviceid : 0x60) controllers
*/
@@ -1976,7 +2079,12 @@ static int megasas_init_mfi(struct megasas_instance *instance)
/*
* Map the message registers
*/
- instance->base_addr = pci_resource_start(instance->pdev, 0);
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) {
+ instance->base_addr = pci_resource_start(instance->pdev, 1);
+ } else {
+ instance->base_addr = pci_resource_start(instance->pdev, 0);
+ }
if (pci_request_regions(instance->pdev, "megasas: LSI")) {
printk(KERN_DEBUG "megasas: IO memory region busy!\n");
@@ -1998,6 +2106,10 @@ static int megasas_init_mfi(struct megasas_instance *instance)
case PCI_DEVICE_ID_LSI_SAS1078DE:
instance->instancet = &megasas_instance_template_ppc;
break;
+ case PCI_DEVICE_ID_LSI_SAS1078GEN2:
+ case PCI_DEVICE_ID_LSI_SAS0079GEN2:
+ instance->instancet = &megasas_instance_template_gen2;
+ break;
case PCI_DEVICE_ID_LSI_SAS1064R:
case PCI_DEVICE_ID_DELL_PERC5:
default:
@@ -2857,6 +2969,7 @@ static void megasas_shutdown(struct pci_dev *pdev)
{
struct megasas_instance *instance = pci_get_drvdata(pdev);
megasas_flush_cache(instance);
+ megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
}
/**
@@ -3292,7 +3405,7 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun
return retval;
}
-static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl,
+static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
megasas_sysfs_set_dbg_lvl);
static ssize_t
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index b0c41e67170..0d033248fdf 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -18,9 +18,9 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.03.20-rc1"
-#define MEGASAS_RELDATE "March 10, 2008"
-#define MEGASAS_EXT_VERSION "Mon. March 10 11:02:31 PDT 2008"
+#define MEGASAS_VERSION "00.00.04.01"
+#define MEGASAS_RELDATE "July 24, 2008"
+#define MEGASAS_EXT_VERSION "Thu July 24 11:41:51 PST 2008"
/*
* Device IDs
@@ -28,6 +28,8 @@
#define PCI_DEVICE_ID_LSI_SAS1078R 0x0060
#define PCI_DEVICE_ID_LSI_SAS1078DE 0x007C
#define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413
+#define PCI_DEVICE_ID_LSI_SAS1078GEN2 0x0078
+#define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079
/*
* =====================================
@@ -580,6 +582,8 @@ struct megasas_ctrl_info {
#define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10)
#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
+#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001
+#define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004)
/*
* register set for both 1068 and 1078 controllers
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index a319a20ed44..45e7dcb4b34 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -993,6 +993,17 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
{
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+ /*
+ * At this point all fcport's software-states are cleared. Perform any
+ * final cleanup of firmware resources (PCBs and XCBs).
+ */
+ if (fcport->loop_id != FC_NO_LOOP_ID) {
+ fcport->ha->isp_ops->fabric_logout(fcport->ha, fcport->loop_id,
+ fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
+ fcport->loop_id = FC_NO_LOOP_ID;
+ }
+
qla2x00_abort_fcport_cmds(fcport);
scsi_target_unblock(&rport->dev);
}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6da31ba9440..94a720eabfd 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2237,6 +2237,7 @@ typedef struct scsi_qla_host {
#define REGISTER_FDMI_NEEDED 26
#define FCPORT_UPDATE_NEEDED 27
#define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */
+#define UNLOADING 29
uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 601a6b29750..ee89ddd64aa 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -976,8 +976,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
&ha->fw_attributes, &ha->fw_memory_size);
qla2x00_resize_request_q(ha);
ha->flags.npiv_supported = 0;
- if ((IS_QLA24XX(ha) || IS_QLA25XX(ha)) &&
- (ha->fw_attributes & BIT_2)) {
+ if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) ||
+ IS_QLA84XX(ha)) &&
+ (ha->fw_attributes & BIT_2)) {
ha->flags.npiv_supported = 1;
if ((!ha->max_npiv_vports) ||
((ha->max_npiv_vports + 1) %
@@ -3251,6 +3252,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
{
int rval;
uint8_t status = 0;
+ scsi_qla_host_t *vha;
if (ha->flags.online) {
ha->flags.online = 0;
@@ -3265,6 +3267,8 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN);
qla2x00_mark_all_devices_lost(ha, 0);
+ list_for_each_entry(vha, &ha->vp_list, vp_list)
+ qla2x00_mark_all_devices_lost(vha, 0);
} else {
if (!atomic_read(&ha->loop_down_timer))
atomic_set(&ha->loop_down_timer,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 874d802edb7..45a3b93eed5 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -879,11 +879,12 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
sp->request_sense_ptr += sense_len;
sp->request_sense_length -= sense_len;
if (sp->request_sense_length != 0)
- sp->ha->status_srb = sp;
+ sp->fcport->ha->status_srb = sp;
DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) "
- "cmd=%p pid=%ld\n", __func__, sp->ha->host_no, cp->device->channel,
- cp->device->id, cp->device->lun, cp, cp->serial_number));
+ "cmd=%p pid=%ld\n", __func__, sp->fcport->ha->host_no,
+ cp->device->channel, cp->device->id, cp->device->lun, cp,
+ cp->serial_number));
if (sense_len)
DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
CMD_ACTUAL_SNSLEN(cp)));
@@ -1184,9 +1185,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
atomic_read(&fcport->state)));
cp->result = DID_BUS_BUSY << 16;
- if (atomic_read(&fcport->state) == FCS_ONLINE) {
- qla2x00_mark_device_lost(ha, fcport, 1, 1);
- }
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1);
break;
case CS_RESET:
@@ -1229,7 +1229,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
/* Check to see if logout occurred. */
if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
- qla2x00_mark_device_lost(ha, fcport, 1, 1);
+ qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1);
break;
default:
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index bc90d6b8d0a..813bc7784c0 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2686,7 +2686,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
set_bit(VP_IDX_ACQUIRED, &vha->vp_flags);
set_bit(VP_DPC_NEEDED, &ha->dpc_flags);
- wake_up_process(ha->dpc_thread);
+ qla2xxx_wake_dpc(ha);
}
}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7c8af7ed2a5..26afe44265c 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -780,7 +780,8 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha, unsigned int t,
sp = pha->outstanding_cmds[cnt];
if (!sp)
continue;
- if (ha->vp_idx != sp->ha->vp_idx)
+
+ if (ha->vp_idx != sp->fcport->ha->vp_idx)
continue;
match = 0;
switch (type) {
@@ -1080,9 +1081,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res)
sp = ha->outstanding_cmds[cnt];
if (sp) {
ha->outstanding_cmds[cnt] = NULL;
- sp->flags = 0;
sp->cmd->result = res;
- sp->cmd->host_scribble = (unsigned char *)NULL;
qla2x00_sp_compl(ha, sp);
}
}
@@ -1776,10 +1775,15 @@ probe_out:
static void
qla2x00_remove_one(struct pci_dev *pdev)
{
- scsi_qla_host_t *ha;
+ scsi_qla_host_t *ha, *vha, *temp;
ha = pci_get_drvdata(pdev);
+ list_for_each_entry_safe(vha, temp, &ha->vp_list, vp_list)
+ fc_vport_terminate(vha->fc_vport);
+
+ set_bit(UNLOADING, &ha->dpc_flags);
+
qla2x00_dfs_remove(ha);
qla84xx_put_chip(ha);
@@ -2451,8 +2455,10 @@ qla2x00_do_dpc(void *data)
void
qla2xxx_wake_dpc(scsi_qla_host_t *ha)
{
- if (ha->dpc_thread)
- wake_up_process(ha->dpc_thread);
+ struct task_struct *t = ha->dpc_thread;
+
+ if (!test_bit(UNLOADING, &ha->dpc_flags) && t)
+ wake_up_process(t);
}
/*
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 676c390db35..4160e4caa7b 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.02.01-k6"
+#define QLA2XXX_VERSION "8.02.01-k7"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 3b4a14e355c..77cb34270fc 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -449,6 +449,7 @@ config SERIAL_CLPS711X_CONSOLE
config SERIAL_SAMSUNG
tristate "Samsung SoC serial support"
depends on ARM && PLAT_S3C24XX
+ select SERIAL_CORE
help
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
providing /dev/ttySAC0, 1 and 2 (note, some machines may not
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 964124b60db..75e86865234 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -226,10 +226,11 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
* Companion function to spi_alloc_device. Devices allocated with
* spi_alloc_device can be added onto the spi bus with this function.
*
- * Returns 0 on success; non-zero on failure
+ * Returns 0 on success; negative errno on failure
*/
int spi_add_device(struct spi_device *spi)
{
+ static DEFINE_MUTEX(spi_add_lock);
struct device *dev = spi->master->dev.parent;
int status;
@@ -246,26 +247,43 @@ int spi_add_device(struct spi_device *spi)
"%s.%u", spi->master->dev.bus_id,
spi->chip_select);
- /* drivers may modify this initial i/o setup */
+
+ /* We need to make sure there's no other device with this
+ * chipselect **BEFORE** we call setup(), else we'll trash
+ * its configuration. Lock against concurrent add() calls.
+ */
+ mutex_lock(&spi_add_lock);
+
+ if (bus_find_device_by_name(&spi_bus_type, NULL, spi->dev.bus_id)
+ != NULL) {
+ dev_err(dev, "chipselect %d already in use\n",
+ spi->chip_select);
+ status = -EBUSY;
+ goto done;
+ }
+
+ /* Drivers may modify this initial i/o setup, but will
+ * normally rely on the device being setup. Devices
+ * using SPI_CS_HIGH can't coexist well otherwise...
+ */
status = spi->master->setup(spi);
if (status < 0) {
dev_err(dev, "can't %s %s, status %d\n",
"setup", spi->dev.bus_id, status);
- return status;
+ goto done;
}
- /* driver core catches callers that misbehave by defining
- * devices that already exist.
- */
+ /* Device may be bound to an active driver when this returns */
status = device_add(&spi->dev);
- if (status < 0) {
+ if (status < 0)
dev_err(dev, "can't %s %s, status %d\n",
"add", spi->dev.bus_id, status);
- return status;
- }
+ else
+ dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
- dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
- return 0;
+done:
+ mutex_unlock(&spi_add_lock);
+ return status;
}
EXPORT_SYMBOL_GPL(spi_add_device);
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 5fbdc14e63b..5416cf96900 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -12,7 +12,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mbus.h>
-#include <asm/plat-orion/ehci-orion.h>
+#include <plat/ehci-orion.h>
#define rdl(off) __raw_readl(hcd->regs + (off))
#define wrl(off, val) __raw_writel((val), hcd->regs + (off))
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 940467aed13..6d5aa806777 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -733,7 +733,6 @@ static int bfin_bf54x_remove(struct platform_device *pdev)
static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state)
{
struct fb_info *fbinfo = platform_get_drvdata(pdev);
- struct bfin_bf54xfb_info *info = fbinfo->par;
bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
disable_dma(CH_EPPI0);
@@ -747,8 +746,18 @@ static int bfin_bf54x_resume(struct platform_device *pdev)
struct fb_info *fbinfo = platform_get_drvdata(pdev);
struct bfin_bf54xfb_info *info = fbinfo->par;
- enable_dma(CH_EPPI0);
- bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
+ if (info->lq043_open_cnt) {
+
+ bfin_write_EPPI0_CONTROL(0);
+ SSYNC();
+
+ config_dma(info);
+ config_ppi(info);
+
+ /* start dma */
+ enable_dma(CH_EPPI0);
+ bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
+ }
return 0;
}
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 59df132cc37..4835bdc4e9f 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -114,6 +114,17 @@ static struct vm_operations_struct fb_deferred_io_vm_ops = {
.page_mkwrite = fb_deferred_io_mkwrite,
};
+static int fb_deferred_io_set_page_dirty(struct page *page)
+{
+ if (!PageDirty(page))
+ SetPageDirty(page);
+ return 0;
+}
+
+static const struct address_space_operations fb_deferred_io_aops = {
+ .set_page_dirty = fb_deferred_io_set_page_dirty,
+};
+
static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
vma->vm_ops = &fb_deferred_io_vm_ops;
@@ -163,6 +174,14 @@ void fb_deferred_io_init(struct fb_info *info)
}
EXPORT_SYMBOL_GPL(fb_deferred_io_init);
+void fb_deferred_io_open(struct fb_info *info,
+ struct inode *inode,
+ struct file *file)
+{
+ file->f_mapping->a_ops = &fb_deferred_io_aops;
+}
+EXPORT_SYMBOL_GPL(fb_deferred_io_open);
+
void fb_deferred_io_cleanup(struct fb_info *info)
{
void *screen_base = (void __force *) info->screen_base;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 6b487801eea..98843c2ecf7 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1344,6 +1344,10 @@ fb_open(struct inode *inode, struct file *file)
if (res)
module_put(info->fbops->owner);
}
+#ifdef CONFIG_FB_DEFERRED_IO
+ if (info->fbdefio)
+ fb_deferred_io_open(info, inode, file);
+#endif
out:
unlock_kernel();
return res;
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index bd320a2bfb7..fb51197d1c9 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -479,6 +479,10 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
base_plane_width = machine_data->fsl_diu_info[0]->var.xres;
base_plane_height = machine_data->fsl_diu_info[0]->var.yres;
+ if (mfbi->x_aoi_d < 0)
+ mfbi->x_aoi_d = 0;
+ if (mfbi->y_aoi_d < 0)
+ mfbi->y_aoi_d = 0;
switch (index) {
case 0:
if (mfbi->x_aoi_d != 0)
@@ -778,6 +782,22 @@ static void unmap_video_memory(struct fb_info *info)
}
/*
+ * Using the fb_var_screeninfo in fb_info we set the aoi of this
+ * particular framebuffer. It is a light version of fsl_diu_set_par.
+ */
+static int fsl_diu_set_aoi(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct mfb_info *mfbi = info->par;
+ struct diu_ad *ad = mfbi->ad;
+
+ /* AOI should not be greater than display size */
+ ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
+ ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
+ return 0;
+}
+
+/*
* Using the fb_var_screeninfo in fb_info we set the resolution of this
* particular framebuffer. This function alters the fb_fix_screeninfo stored
* in fb_info. It does not alter var in fb_info since we are using that
@@ -817,11 +837,11 @@ static int fsl_diu_set_par(struct fb_info *info)
diu_ops.get_pixel_format(var->bits_per_pixel,
machine_data->monitor_port);
ad->addr = cpu_to_le32(info->fix.smem_start);
- ad->src_size_g_alpha = cpu_to_le32((var->yres << 12) |
- var->xres) | mfbi->g_alpha;
- /* fix me. AOI should not be greater than display size */
+ ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
+ var->xres_virtual) | mfbi->g_alpha;
+ /* AOI should not be greater than display size */
ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres);
- ad->offset_xyi = 0;
+ ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
/* Disable chroma keying function */
@@ -921,6 +941,8 @@ static int fsl_diu_pan_display(struct fb_var_screeninfo *var,
else
info->var.vmode &= ~FB_VMODE_YWRAP;
+ fsl_diu_set_aoi(info);
+
return 0;
}
@@ -989,7 +1011,7 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
pr_debug("set AOI display offset of index %d to (%d,%d)\n",
mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
fsl_diu_check_var(&info->var, info);
- fsl_diu_set_par(info);
+ fsl_diu_set_aoi(info);
break;
case MFB_GET_AOID:
aoi_d.x_aoi_d = mfbi->x_aoi_d;
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 3f1ca2adda3..c6dd924976a 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -1746,6 +1746,7 @@ static void __devexit pm2fb_remove(struct pci_dev *pdev)
release_mem_region(fix->mmio_start, fix->mmio_len);
pci_set_drvdata(pdev, NULL);
+ fb_dealloc_cmap(&info->cmap);
kfree(info->pixmap.addr);
kfree(info);
}
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index e7aa7ae8fca..97204497d9f 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1031,7 +1031,9 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
- pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD);
+
+ if ((lccr0 & LCCR0_PAS) == 0)
+ pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD);
}
static void pxafb_enable_controller(struct pxafb_info *fbi)
@@ -1400,6 +1402,8 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi,
if (lcd_conn == LCD_MONO_STN_8BPP)
fbi->lccr0 |= LCCR0_DPD;
+ fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0;
+
fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff);
fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0;
fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0;
@@ -1673,53 +1677,63 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
#define pxafb_setup_options() (0)
#endif
-static int __devinit pxafb_probe(struct platform_device *dev)
-{
- struct pxafb_info *fbi;
- struct pxafb_mach_info *inf;
- struct resource *r;
- int irq, ret;
-
- dev_dbg(&dev->dev, "pxafb_probe\n");
-
- inf = dev->dev.platform_data;
- ret = -ENOMEM;
- fbi = NULL;
- if (!inf)
- goto failed;
-
- ret = pxafb_parse_options(&dev->dev, g_options);
- if (ret < 0)
- goto failed;
-
#ifdef DEBUG_VAR
- /* Check for various illegal bit-combinations. Currently only
- * a warning is given. */
+/* Check for various illegal bit-combinations. Currently only
+ * a warning is given. */
+static void __devinit pxafb_check_options(struct device *dev,
+ struct pxafb_mach_info *inf)
+{
+ if (inf->lcd_conn)
+ return;
if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
- dev_warn(&dev->dev, "machine LCCR0 setting contains "
+ dev_warn(dev, "machine LCCR0 setting contains "
"illegal bits: %08x\n",
inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
- dev_warn(&dev->dev, "machine LCCR3 setting contains "
+ dev_warn(dev, "machine LCCR3 setting contains "
"illegal bits: %08x\n",
inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
if (inf->lccr0 & LCCR0_DPD &&
((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
(inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
(inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))
- dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is "
+ dev_warn(dev, "Double Pixel Data (DPD) mode is "
"only valid in passive mono"
" single panel mode\n");
if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
(inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
- dev_warn(&dev->dev, "Dual panel only valid in passive mode\n");
+ dev_warn(dev, "Dual panel only valid in passive mode\n");
if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
(inf->modes->upper_margin || inf->modes->lower_margin))
- dev_warn(&dev->dev, "Upper and lower margins must be 0 in "
+ dev_warn(dev, "Upper and lower margins must be 0 in "
"passive mode\n");
+}
+#else
+#define pxafb_check_options(...) do {} while (0)
#endif
+static int __devinit pxafb_probe(struct platform_device *dev)
+{
+ struct pxafb_info *fbi;
+ struct pxafb_mach_info *inf;
+ struct resource *r;
+ int irq, ret;
+
+ dev_dbg(&dev->dev, "pxafb_probe\n");
+
+ inf = dev->dev.platform_data;
+ ret = -ENOMEM;
+ fbi = NULL;
+ if (!inf)
+ goto failed;
+
+ ret = pxafb_parse_options(&dev->dev, g_options);
+ if (ret < 0)
+ goto failed;
+
+ pxafb_check_options(&dev->dev, inf);
+
dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",
inf->modes->xres,
inf->modes->yres,
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index f6ef6cca73c..4c32c06579a 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -595,6 +595,8 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
info->fbops = &sh_mobile_lcdc_ops;
info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres;
+ info->var.width = cfg->lcd_size_cfg.width;
+ info->var.height = cfg->lcd_size_cfg.height;
info->var.activate = FB_ACTIVATE_NOW;
error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp);
if (error)
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 3da2b90d2fe..22715e3be5e 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -157,8 +157,6 @@ static void s3c2410wdt_start(void)
writel(wdt_count, wdt_base + S3C2410_WTCNT);
writel(wtcon, wdt_base + S3C2410_WTCON);
spin_unlock(&wdt_lock);
-
- return 0;
}
static int s3c2410wdt_set_heartbeat(int timeout)