diff options
Diffstat (limited to 'drivers')
263 files changed, 9306 insertions, 1763 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index f4f632917509..b0243fd55ac0 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
| @@ -312,9 +312,13 @@ config ACPI_DEBUG | |||
| 312 | bool "Debug Statements" | 312 | bool "Debug Statements" |
| 313 | default n | 313 | default n |
| 314 | help | 314 | help |
| 315 | The ACPI driver can optionally report errors with a great deal | 315 | The ACPI subsystem can produce debug output. Saying Y enables this |
| 316 | of verbosity. Saying Y enables these statements. This will increase | 316 | output and increases the kernel size by around 50K. |
| 317 | your kernel size by around 50K. | 317 | |
| 318 | Use the acpi.debug_layer and acpi.debug_level kernel command-line | ||
| 319 | parameters documented in Documentation/acpi/debug.txt and | ||
| 320 | Documentation/kernel-parameters.txt to control the type and | ||
| 321 | amount of debug output. | ||
| 318 | 322 | ||
| 319 | config ACPI_DEBUG_FUNC_TRACE | 323 | config ACPI_DEBUG_FUNC_TRACE |
| 320 | bool "Additionally enable ACPI function tracing" | 324 | bool "Additionally enable ACPI function tracing" |
| @@ -324,14 +328,6 @@ config ACPI_DEBUG_FUNC_TRACE | |||
| 324 | ACPI Debug Statements slow down ACPI processing. Function trace | 328 | ACPI Debug Statements slow down ACPI processing. Function trace |
| 325 | is about half of the penalty and is rarely useful. | 329 | is about half of the penalty and is rarely useful. |
| 326 | 330 | ||
| 327 | config ACPI_EC | ||
| 328 | bool | ||
| 329 | default y | ||
| 330 | help | ||
| 331 | This driver is required on some systems for the proper operation of | ||
| 332 | the battery and thermal drivers. If you are compiling for a | ||
| 333 | mobile system, say Y. | ||
| 334 | |||
| 335 | config ACPI_PCI_SLOT | 331 | config ACPI_PCI_SLOT |
| 336 | tristate "PCI slot detection driver" | 332 | tristate "PCI slot detection driver" |
| 337 | default n | 333 | default n |
| @@ -341,10 +337,6 @@ config ACPI_PCI_SLOT | |||
| 341 | help you correlate PCI bus addresses with the physical geography | 337 | help you correlate PCI bus addresses with the physical geography |
| 342 | of your slots. If you are unsure, say N. | 338 | of your slots. If you are unsure, say N. |
| 343 | 339 | ||
| 344 | config ACPI_POWER | ||
| 345 | bool | ||
| 346 | default y | ||
| 347 | |||
| 348 | config ACPI_SYSTEM | 340 | config ACPI_SYSTEM |
| 349 | bool | 341 | bool |
| 350 | default y | 342 | default y |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d91c027ece8f..3c0c93300f12 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
| @@ -39,19 +39,23 @@ obj-y += sleep/ | |||
| 39 | obj-y += bus.o glue.o | 39 | obj-y += bus.o glue.o |
| 40 | obj-y += scan.o | 40 | obj-y += scan.o |
| 41 | # Keep EC driver first. Initialization of others depend on it. | 41 | # Keep EC driver first. Initialization of others depend on it. |
| 42 | obj-$(CONFIG_ACPI_EC) += ec.o | 42 | obj-y += ec.o |
| 43 | obj-$(CONFIG_ACPI_AC) += ac.o | 43 | obj-$(CONFIG_ACPI_AC) += ac.o |
| 44 | obj-$(CONFIG_ACPI_BATTERY) += battery.o | 44 | obj-$(CONFIG_ACPI_BATTERY) += battery.o |
| 45 | obj-$(CONFIG_ACPI_BUTTON) += button.o | 45 | obj-$(CONFIG_ACPI_BUTTON) += button.o |
| 46 | obj-$(CONFIG_ACPI_FAN) += fan.o | 46 | obj-$(CONFIG_ACPI_FAN) += fan.o |
| 47 | obj-$(CONFIG_ACPI_DOCK) += dock.o | 47 | obj-$(CONFIG_ACPI_DOCK) += dock.o |
| 48 | obj-$(CONFIG_ACPI_VIDEO) += video.o | 48 | obj-$(CONFIG_ACPI_VIDEO) += video.o |
| 49 | ifdef CONFIG_ACPI_VIDEO | ||
| 50 | obj-y += video_detect.o | ||
| 51 | endif | ||
| 52 | |||
| 49 | obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o | 53 | obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o |
| 50 | obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o | 54 | obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o |
| 51 | obj-$(CONFIG_ACPI_PROCESSOR) += processor.o | 55 | obj-$(CONFIG_ACPI_PROCESSOR) += processor.o |
| 52 | obj-$(CONFIG_ACPI_CONTAINER) += container.o | 56 | obj-$(CONFIG_ACPI_CONTAINER) += container.o |
| 53 | obj-$(CONFIG_ACPI_THERMAL) += thermal.o | 57 | obj-$(CONFIG_ACPI_THERMAL) += thermal.o |
| 54 | obj-$(CONFIG_ACPI_POWER) += power.o | 58 | obj-y += power.o |
| 55 | obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o | 59 | obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o |
| 56 | obj-$(CONFIG_ACPI_DEBUG) += debug.o | 60 | obj-$(CONFIG_ACPI_DEBUG) += debug.o |
| 57 | obj-$(CONFIG_ACPI_NUMA) += numa.o | 61 | obj-$(CONFIG_ACPI_NUMA) += numa.o |
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index d72a1b6c8a94..9b917dac7732 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | #include <acpi/acpi_bus.h> | 37 | #include <acpi/acpi_bus.h> |
| 38 | #include <acpi/acpi_drivers.h> | 38 | #include <acpi/acpi_drivers.h> |
| 39 | 39 | ||
| 40 | #define ACPI_AC_COMPONENT 0x00020000 | ||
| 41 | #define ACPI_AC_CLASS "ac_adapter" | 40 | #define ACPI_AC_CLASS "ac_adapter" |
| 42 | #define ACPI_AC_DEVICE_NAME "AC Adapter" | 41 | #define ACPI_AC_DEVICE_NAME "AC Adapter" |
| 43 | #define ACPI_AC_FILE_STATE "state" | 42 | #define ACPI_AC_FILE_STATE "state" |
| @@ -242,7 +241,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) | |||
| 242 | acpi_ac_get_state(ac); | 241 | acpi_ac_get_state(ac); |
| 243 | acpi_bus_generate_proc_event(device, event, (u32) ac->state); | 242 | acpi_bus_generate_proc_event(device, event, (u32) ac->state); |
| 244 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 243 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
| 245 | device->dev.bus_id, event, | 244 | dev_name(&device->dev), event, |
| 246 | (u32) ac->state); | 245 | (u32) ac->state); |
| 247 | #ifdef CONFIG_ACPI_SYSFS_POWER | 246 | #ifdef CONFIG_ACPI_SYSFS_POWER |
| 248 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); | 247 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); |
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 71d21c51c45f..63a17b55b39b 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | #include <linux/memory_hotplug.h> | 32 | #include <linux/memory_hotplug.h> |
| 33 | #include <acpi/acpi_drivers.h> | 33 | #include <acpi/acpi_drivers.h> |
| 34 | 34 | ||
| 35 | #define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL | ||
| 36 | #define ACPI_MEMORY_DEVICE_CLASS "memory" | 35 | #define ACPI_MEMORY_DEVICE_CLASS "memory" |
| 37 | #define ACPI_MEMORY_DEVICE_HID "PNP0C80" | 36 | #define ACPI_MEMORY_DEVICE_HID "PNP0C80" |
| 38 | #define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" | 37 | #define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b2133e89ad9a..1423b0c0cd2e 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
| @@ -46,7 +46,6 @@ | |||
| 46 | 46 | ||
| 47 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF | 47 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF |
| 48 | 48 | ||
| 49 | #define ACPI_BATTERY_COMPONENT 0x00040000 | ||
| 50 | #define ACPI_BATTERY_CLASS "battery" | 49 | #define ACPI_BATTERY_CLASS "battery" |
| 51 | #define ACPI_BATTERY_DEVICE_NAME "Battery" | 50 | #define ACPI_BATTERY_DEVICE_NAME "Battery" |
| 52 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 | 51 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 |
| @@ -782,7 +781,7 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
| 782 | acpi_bus_generate_proc_event(device, event, | 781 | acpi_bus_generate_proc_event(device, event, |
| 783 | acpi_battery_present(battery)); | 782 | acpi_battery_present(battery)); |
| 784 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 783 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
| 785 | device->dev.bus_id, event, | 784 | dev_name(&device->dev), event, |
| 786 | acpi_battery_present(battery)); | 785 | acpi_battery_present(battery)); |
| 787 | #ifdef CONFIG_ACPI_SYSFS_POWER | 786 | #ifdef CONFIG_ACPI_SYSFS_POWER |
| 788 | /* acpi_batter_update could remove power_supply object */ | 787 | /* acpi_batter_update could remove power_supply object */ |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c797c6473f31..7edf6d913c13 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -688,6 +688,14 @@ void __init acpi_early_init(void) | |||
| 688 | if (acpi_disabled) | 688 | if (acpi_disabled) |
| 689 | return; | 689 | return; |
| 690 | 690 | ||
| 691 | /* | ||
| 692 | * ACPI CA initializes acpi_dbg_level to non-zero, which means | ||
| 693 | * we get debug output merely by turning on CONFIG_ACPI_DEBUG. | ||
| 694 | * Turn it off so we don't get output unless the user specifies | ||
| 695 | * acpi.debug_level. | ||
| 696 | */ | ||
| 697 | acpi_dbg_level = 0; | ||
| 698 | |||
| 691 | printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); | 699 | printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); |
| 692 | 700 | ||
| 693 | /* enable workarounds, unless strict ACPI spec. compliance */ | 701 | /* enable workarounds, unless strict ACPI spec. compliance */ |
| @@ -774,7 +782,7 @@ static int __init acpi_bus_init(void) | |||
| 774 | "Unable to initialize ACPI OS objects\n"); | 782 | "Unable to initialize ACPI OS objects\n"); |
| 775 | goto error1; | 783 | goto error1; |
| 776 | } | 784 | } |
| 777 | #ifdef CONFIG_ACPI_EC | 785 | |
| 778 | /* | 786 | /* |
| 779 | * ACPI 2.0 requires the EC driver to be loaded and work before | 787 | * ACPI 2.0 requires the EC driver to be loaded and work before |
| 780 | * the EC device is found in the namespace (i.e. before acpi_initialize_objects() | 788 | * the EC device is found in the namespace (i.e. before acpi_initialize_objects() |
| @@ -785,7 +793,6 @@ static int __init acpi_bus_init(void) | |||
| 785 | */ | 793 | */ |
| 786 | status = acpi_ec_ecdt_probe(); | 794 | status = acpi_ec_ecdt_probe(); |
| 787 | /* Ignore result. Not having an ECDT is not fatal. */ | 795 | /* Ignore result. Not having an ECDT is not fatal. */ |
| 788 | #endif | ||
| 789 | 796 | ||
| 790 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); | 797 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); |
| 791 | if (ACPI_FAILURE(status)) { | 798 | if (ACPI_FAILURE(status)) { |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index cb046c3fc3f2..171fd914f435 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
| 34 | #include <acpi/acpi_drivers.h> | 34 | #include <acpi/acpi_drivers.h> |
| 35 | 35 | ||
| 36 | #define ACPI_BUTTON_COMPONENT 0x00080000 | ||
| 37 | #define ACPI_BUTTON_CLASS "button" | 36 | #define ACPI_BUTTON_CLASS "button" |
| 38 | #define ACPI_BUTTON_FILE_INFO "info" | 37 | #define ACPI_BUTTON_FILE_INFO "info" |
| 39 | #define ACPI_BUTTON_FILE_STATE "state" | 38 | #define ACPI_BUTTON_FILE_STATE "state" |
| @@ -479,7 +478,7 @@ static int acpi_button_add(struct acpi_device *device) | |||
| 479 | device->wakeup.gpe_number, | 478 | device->wakeup.gpe_number, |
| 480 | ACPI_GPE_TYPE_WAKE_RUN); | 479 | ACPI_GPE_TYPE_WAKE_RUN); |
| 481 | acpi_enable_gpe(device->wakeup.gpe_device, | 480 | acpi_enable_gpe(device->wakeup.gpe_device, |
| 482 | device->wakeup.gpe_number, ACPI_NOT_ISR); | 481 | device->wakeup.gpe_number); |
| 483 | device->wakeup.state.enabled = 1; | 482 | device->wakeup.state.enabled = 1; |
| 484 | } | 483 | } |
| 485 | 484 | ||
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index 4441e84b28a9..307963bd1043 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | ACPI_MODULE_NAME("cm_sbs"); | 34 | ACPI_MODULE_NAME("cm_sbs"); |
| 35 | #define ACPI_AC_CLASS "ac_adapter" | 35 | #define ACPI_AC_CLASS "ac_adapter" |
| 36 | #define ACPI_BATTERY_CLASS "battery" | 36 | #define ACPI_BATTERY_CLASS "battery" |
| 37 | #define ACPI_SBS_COMPONENT 0x00080000 | ||
| 38 | #define _COMPONENT ACPI_SBS_COMPONENT | 37 | #define _COMPONENT ACPI_SBS_COMPONENT |
| 39 | static struct proc_dir_entry *acpi_ac_dir; | 38 | static struct proc_dir_entry *acpi_ac_dir; |
| 40 | static struct proc_dir_entry *acpi_battery_dir; | 39 | static struct proc_dir_entry *acpi_battery_dir; |
| @@ -105,9 +104,3 @@ void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param) | |||
| 105 | return; | 104 | return; |
| 106 | } | 105 | } |
| 107 | EXPORT_SYMBOL(acpi_unlock_battery_dir); | 106 | EXPORT_SYMBOL(acpi_unlock_battery_dir); |
| 108 | |||
| 109 | static int __init acpi_cm_sbs_init(void) | ||
| 110 | { | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | subsys_initcall(acpi_cm_sbs_init); | ||
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 134818b265a9..17020c12623c 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #define INSTALL_NOTIFY_HANDLER 1 | 41 | #define INSTALL_NOTIFY_HANDLER 1 |
| 42 | #define UNINSTALL_NOTIFY_HANDLER 2 | 42 | #define UNINSTALL_NOTIFY_HANDLER 2 |
| 43 | 43 | ||
| 44 | #define ACPI_CONTAINER_COMPONENT 0x01000000 | ||
| 45 | #define _COMPONENT ACPI_CONTAINER_COMPONENT | 44 | #define _COMPONENT ACPI_CONTAINER_COMPONENT |
| 46 | ACPI_MODULE_NAME("container"); | 45 | ACPI_MODULE_NAME("container"); |
| 47 | 46 | ||
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index abf36b4b1d1d..c48396892008 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c | |||
| @@ -44,6 +44,21 @@ static const struct acpi_dlayer acpi_debug_layers[] = { | |||
| 44 | ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), | 44 | ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), |
| 45 | ACPI_DEBUG_INIT(ACPI_COMPILER), | 45 | ACPI_DEBUG_INIT(ACPI_COMPILER), |
| 46 | ACPI_DEBUG_INIT(ACPI_TOOLS), | 46 | ACPI_DEBUG_INIT(ACPI_TOOLS), |
| 47 | |||
| 48 | ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), | ||
| 49 | ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), | ||
| 50 | ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), | ||
| 51 | ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), | ||
| 52 | ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), | ||
| 53 | ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), | ||
| 54 | ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), | ||
| 55 | ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), | ||
| 56 | ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), | ||
| 57 | ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), | ||
| 58 | ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), | ||
| 59 | ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), | ||
| 60 | ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), | ||
| 61 | ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), | ||
| 47 | }; | 62 | }; |
| 48 | 63 | ||
| 49 | static const struct acpi_dlevel acpi_debug_levels[] = { | 64 | static const struct acpi_dlevel acpi_debug_levels[] = { |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ef42316f89f5..cf41f9fc24a7 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -70,7 +70,7 @@ enum ec_command { | |||
| 70 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ | 70 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
| 71 | #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ | 71 | #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ |
| 72 | 72 | ||
| 73 | #define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts | 73 | #define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts |
| 74 | per one transaction */ | 74 | per one transaction */ |
| 75 | 75 | ||
| 76 | enum { | 76 | enum { |
| @@ -100,8 +100,11 @@ struct transaction { | |||
| 100 | u8 *rdata; | 100 | u8 *rdata; |
| 101 | unsigned short irq_count; | 101 | unsigned short irq_count; |
| 102 | u8 command; | 102 | u8 command; |
| 103 | u8 wi; | ||
| 104 | u8 ri; | ||
| 103 | u8 wlen; | 105 | u8 wlen; |
| 104 | u8 rlen; | 106 | u8 rlen; |
| 107 | bool done; | ||
| 105 | }; | 108 | }; |
| 106 | 109 | ||
| 107 | static struct acpi_ec { | 110 | static struct acpi_ec { |
| @@ -178,34 +181,45 @@ static int ec_transaction_done(struct acpi_ec *ec) | |||
| 178 | unsigned long flags; | 181 | unsigned long flags; |
| 179 | int ret = 0; | 182 | int ret = 0; |
| 180 | spin_lock_irqsave(&ec->curr_lock, flags); | 183 | spin_lock_irqsave(&ec->curr_lock, flags); |
| 181 | if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen)) | 184 | if (!ec->curr || ec->curr->done) |
| 182 | ret = 1; | 185 | ret = 1; |
| 183 | spin_unlock_irqrestore(&ec->curr_lock, flags); | 186 | spin_unlock_irqrestore(&ec->curr_lock, flags); |
| 184 | return ret; | 187 | return ret; |
| 185 | } | 188 | } |
| 186 | 189 | ||
| 190 | static void start_transaction(struct acpi_ec *ec) | ||
| 191 | { | ||
| 192 | ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0; | ||
| 193 | ec->curr->done = false; | ||
| 194 | acpi_ec_write_cmd(ec, ec->curr->command); | ||
| 195 | } | ||
| 196 | |||
| 187 | static void gpe_transaction(struct acpi_ec *ec, u8 status) | 197 | static void gpe_transaction(struct acpi_ec *ec, u8 status) |
| 188 | { | 198 | { |
| 189 | unsigned long flags; | 199 | unsigned long flags; |
| 190 | spin_lock_irqsave(&ec->curr_lock, flags); | 200 | spin_lock_irqsave(&ec->curr_lock, flags); |
| 191 | if (!ec->curr) | 201 | if (!ec->curr) |
| 192 | goto unlock; | 202 | goto unlock; |
| 193 | if (ec->curr->wlen > 0) { | 203 | if (ec->curr->wlen > ec->curr->wi) { |
| 194 | if ((status & ACPI_EC_FLAG_IBF) == 0) { | 204 | if ((status & ACPI_EC_FLAG_IBF) == 0) |
| 195 | acpi_ec_write_data(ec, *(ec->curr->wdata++)); | 205 | acpi_ec_write_data(ec, |
| 196 | --ec->curr->wlen; | 206 | ec->curr->wdata[ec->curr->wi++]); |
| 197 | } else | 207 | else |
| 198 | /* false interrupt, state didn't change */ | 208 | goto err; |
| 199 | ++ec->curr->irq_count; | 209 | } else if (ec->curr->rlen > ec->curr->ri) { |
| 200 | |||
| 201 | } else if (ec->curr->rlen > 0) { | ||
| 202 | if ((status & ACPI_EC_FLAG_OBF) == 1) { | 210 | if ((status & ACPI_EC_FLAG_OBF) == 1) { |
| 203 | *(ec->curr->rdata++) = acpi_ec_read_data(ec); | 211 | ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec); |
| 204 | --ec->curr->rlen; | 212 | if (ec->curr->rlen == ec->curr->ri) |
| 213 | ec->curr->done = true; | ||
| 205 | } else | 214 | } else |
| 206 | /* false interrupt, state didn't change */ | 215 | goto err; |
| 207 | ++ec->curr->irq_count; | 216 | } else if (ec->curr->wlen == ec->curr->wi && |
| 208 | } | 217 | (status & ACPI_EC_FLAG_IBF) == 0) |
| 218 | ec->curr->done = true; | ||
| 219 | goto unlock; | ||
| 220 | err: | ||
| 221 | /* false interrupt, state didn't change */ | ||
| 222 | ++ec->curr->irq_count; | ||
| 209 | unlock: | 223 | unlock: |
| 210 | spin_unlock_irqrestore(&ec->curr_lock, flags); | 224 | spin_unlock_irqrestore(&ec->curr_lock, flags); |
| 211 | } | 225 | } |
| @@ -215,6 +229,15 @@ static int acpi_ec_wait(struct acpi_ec *ec) | |||
| 215 | if (wait_event_timeout(ec->wait, ec_transaction_done(ec), | 229 | if (wait_event_timeout(ec->wait, ec_transaction_done(ec), |
| 216 | msecs_to_jiffies(ACPI_EC_DELAY))) | 230 | msecs_to_jiffies(ACPI_EC_DELAY))) |
| 217 | return 0; | 231 | return 0; |
| 232 | /* try restart command if we get any false interrupts */ | ||
| 233 | if (ec->curr->irq_count && | ||
| 234 | (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { | ||
| 235 | pr_debug(PREFIX "controller reset, restart transaction\n"); | ||
| 236 | start_transaction(ec); | ||
| 237 | if (wait_event_timeout(ec->wait, ec_transaction_done(ec), | ||
| 238 | msecs_to_jiffies(ACPI_EC_DELAY))) | ||
| 239 | return 0; | ||
| 240 | } | ||
| 218 | /* missing GPEs, switch back to poll mode */ | 241 | /* missing GPEs, switch back to poll mode */ |
| 219 | if (printk_ratelimit()) | 242 | if (printk_ratelimit()) |
| 220 | pr_info(PREFIX "missing confirmations, " | 243 | pr_info(PREFIX "missing confirmations, " |
| @@ -239,10 +262,10 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) | |||
| 239 | static int ec_poll(struct acpi_ec *ec) | 262 | static int ec_poll(struct acpi_ec *ec) |
| 240 | { | 263 | { |
| 241 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 264 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); |
| 242 | msleep(1); | 265 | udelay(ACPI_EC_UDELAY); |
| 243 | while (time_before(jiffies, delay)) { | 266 | while (time_before(jiffies, delay)) { |
| 244 | gpe_transaction(ec, acpi_ec_read_status(ec)); | 267 | gpe_transaction(ec, acpi_ec_read_status(ec)); |
| 245 | msleep(1); | 268 | udelay(ACPI_EC_UDELAY); |
| 246 | if (ec_transaction_done(ec)) | 269 | if (ec_transaction_done(ec)) |
| 247 | return 0; | 270 | return 0; |
| 248 | } | 271 | } |
| @@ -259,14 +282,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
| 259 | /* disable GPE during transaction if storm is detected */ | 282 | /* disable GPE during transaction if storm is detected */ |
| 260 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | 283 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
| 261 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 284 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
| 262 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 285 | acpi_disable_gpe(NULL, ec->gpe); |
| 263 | } | 286 | } |
| 264 | /* start transaction */ | 287 | /* start transaction */ |
| 265 | spin_lock_irqsave(&ec->curr_lock, tmp); | 288 | spin_lock_irqsave(&ec->curr_lock, tmp); |
| 266 | /* following two actions should be kept atomic */ | 289 | /* following two actions should be kept atomic */ |
| 267 | t->irq_count = 0; | ||
| 268 | ec->curr = t; | 290 | ec->curr = t; |
| 269 | acpi_ec_write_cmd(ec, ec->curr->command); | 291 | start_transaction(ec); |
| 270 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) | 292 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) |
| 271 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 293 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
| 272 | spin_unlock_irqrestore(&ec->curr_lock, tmp); | 294 | spin_unlock_irqrestore(&ec->curr_lock, tmp); |
| @@ -283,10 +305,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
| 283 | /* check if we received SCI during transaction */ | 305 | /* check if we received SCI during transaction */ |
| 284 | ec_check_sci(ec, acpi_ec_read_status(ec)); | 306 | ec_check_sci(ec, acpi_ec_read_status(ec)); |
| 285 | /* it is safe to enable GPE outside of transaction */ | 307 | /* it is safe to enable GPE outside of transaction */ |
| 286 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 308 | acpi_enable_gpe(NULL, ec->gpe); |
| 287 | } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && | 309 | } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && |
| 288 | t->irq_count > ACPI_EC_STORM_THRESHOLD) { | 310 | t->irq_count > ACPI_EC_STORM_THRESHOLD) { |
| 289 | pr_debug(PREFIX "GPE storm detected\n"); | 311 | pr_info(PREFIX "GPE storm detected, " |
| 312 | "transactions will use polling mode\n"); | ||
| 290 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); | 313 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); |
| 291 | } | 314 | } |
| 292 | return ret; | 315 | return ret; |
| @@ -558,17 +581,26 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
| 558 | pr_debug(PREFIX "~~~> interrupt\n"); | 581 | pr_debug(PREFIX "~~~> interrupt\n"); |
| 559 | status = acpi_ec_read_status(ec); | 582 | status = acpi_ec_read_status(ec); |
| 560 | 583 | ||
| 561 | gpe_transaction(ec, status); | 584 | if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) { |
| 562 | if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) | 585 | gpe_transaction(ec, status); |
| 563 | wake_up(&ec->wait); | 586 | if (ec_transaction_done(ec) && |
| 587 | (status & ACPI_EC_FLAG_IBF) == 0) | ||
| 588 | wake_up(&ec->wait); | ||
| 589 | } | ||
| 564 | 590 | ||
| 565 | ec_check_sci(ec, status); | 591 | ec_check_sci(ec, status); |
| 566 | if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && | 592 | if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && |
| 567 | !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { | 593 | !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { |
| 568 | /* this is non-query, must be confirmation */ | 594 | /* this is non-query, must be confirmation */ |
| 569 | if (printk_ratelimit()) | 595 | if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
| 570 | pr_info(PREFIX "non-query interrupt received," | 596 | if (printk_ratelimit()) |
| 597 | pr_info(PREFIX "non-query interrupt received," | ||
| 598 | " switching to interrupt mode\n"); | ||
| 599 | } else { | ||
| 600 | /* hush, STORM switches the mode every transaction */ | ||
| 601 | pr_debug(PREFIX "non-query interrupt received," | ||
| 571 | " switching to interrupt mode\n"); | 602 | " switching to interrupt mode\n"); |
| 603 | } | ||
| 572 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 604 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
| 573 | } | 605 | } |
| 574 | return ACPI_INTERRUPT_HANDLED; | 606 | return ACPI_INTERRUPT_HANDLED; |
| @@ -736,7 +768,7 @@ static acpi_status | |||
| 736 | ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) | 768 | ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) |
| 737 | { | 769 | { |
| 738 | acpi_status status; | 770 | acpi_status status; |
| 739 | unsigned long long tmp; | 771 | unsigned long long tmp = 0; |
| 740 | 772 | ||
| 741 | struct acpi_ec *ec = context; | 773 | struct acpi_ec *ec = context; |
| 742 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | 774 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, |
| @@ -751,6 +783,7 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) | |||
| 751 | return status; | 783 | return status; |
| 752 | ec->gpe = tmp; | 784 | ec->gpe = tmp; |
| 753 | /* Use the global lock for all EC transactions? */ | 785 | /* Use the global lock for all EC transactions? */ |
| 786 | tmp = 0; | ||
| 754 | acpi_evaluate_integer(handle, "_GLK", NULL, &tmp); | 787 | acpi_evaluate_integer(handle, "_GLK", NULL, &tmp); |
| 755 | ec->global_lock = tmp; | 788 | ec->global_lock = tmp; |
| 756 | ec->handle = handle; | 789 | ec->handle = handle; |
| @@ -868,7 +901,7 @@ static int ec_install_handlers(struct acpi_ec *ec) | |||
| 868 | if (ACPI_FAILURE(status)) | 901 | if (ACPI_FAILURE(status)) |
| 869 | return -ENODEV; | 902 | return -ENODEV; |
| 870 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); | 903 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); |
| 871 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 904 | acpi_enable_gpe(NULL, ec->gpe); |
| 872 | status = acpi_install_address_space_handler(ec->handle, | 905 | status = acpi_install_address_space_handler(ec->handle, |
| 873 | ACPI_ADR_SPACE_EC, | 906 | ACPI_ADR_SPACE_EC, |
| 874 | &acpi_ec_space_handler, | 907 | &acpi_ec_space_handler, |
| @@ -1007,7 +1040,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) | |||
| 1007 | /* Stop using GPE */ | 1040 | /* Stop using GPE */ |
| 1008 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); | 1041 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); |
| 1009 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 1042 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
| 1010 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 1043 | acpi_disable_gpe(NULL, ec->gpe); |
| 1011 | return 0; | 1044 | return 0; |
| 1012 | } | 1045 | } |
| 1013 | 1046 | ||
| @@ -1016,7 +1049,7 @@ static int acpi_ec_resume(struct acpi_device *device) | |||
| 1016 | struct acpi_ec *ec = acpi_driver_data(device); | 1049 | struct acpi_ec *ec = acpi_driver_data(device); |
| 1017 | /* Enable use of GPE back */ | 1050 | /* Enable use of GPE back */ |
| 1018 | clear_bit(EC_FLAGS_NO_GPE, &ec->flags); | 1051 | clear_bit(EC_FLAGS_NO_GPE, &ec->flags); |
| 1019 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 1052 | acpi_enable_gpe(NULL, ec->gpe); |
| 1020 | return 0; | 1053 | return 0; |
| 1021 | } | 1054 | } |
| 1022 | 1055 | ||
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index c5e53aae86f7..f45c74fe745e 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c | |||
| @@ -289,8 +289,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
| 289 | */ | 289 | */ |
| 290 | status = acpi_hw_low_disable_gpe(gpe_event_info); | 290 | status = acpi_hw_low_disable_gpe(gpe_event_info); |
| 291 | return_ACPI_STATUS(status); | 291 | return_ACPI_STATUS(status); |
| 292 | |||
| 293 | return_ACPI_STATUS(AE_OK); | ||
| 294 | } | 292 | } |
| 295 | 293 | ||
| 296 | /******************************************************************************* | 294 | /******************************************************************************* |
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 73bfd6bf962f..41554f736b68 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c | |||
| @@ -248,21 +248,15 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) | |||
| 248 | * DESCRIPTION: Enable an ACPI event (general purpose) | 248 | * DESCRIPTION: Enable an ACPI event (general purpose) |
| 249 | * | 249 | * |
| 250 | ******************************************************************************/ | 250 | ******************************************************************************/ |
| 251 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | 251 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) |
| 252 | { | 252 | { |
| 253 | acpi_status status = AE_OK; | 253 | acpi_status status = AE_OK; |
| 254 | acpi_cpu_flags flags; | ||
| 254 | struct acpi_gpe_event_info *gpe_event_info; | 255 | struct acpi_gpe_event_info *gpe_event_info; |
| 255 | 256 | ||
| 256 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); | 257 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); |
| 257 | 258 | ||
| 258 | /* Use semaphore lock if not executing at interrupt level */ | 259 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
| 259 | |||
| 260 | if (flags & ACPI_NOT_ISR) { | ||
| 261 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
| 262 | if (ACPI_FAILURE(status)) { | ||
| 263 | return_ACPI_STATUS(status); | ||
| 264 | } | ||
| 265 | } | ||
| 266 | 260 | ||
| 267 | /* Ensure that we have a valid GPE number */ | 261 | /* Ensure that we have a valid GPE number */ |
| 268 | 262 | ||
| @@ -277,9 +271,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | |||
| 277 | status = acpi_ev_enable_gpe(gpe_event_info, TRUE); | 271 | status = acpi_ev_enable_gpe(gpe_event_info, TRUE); |
| 278 | 272 | ||
| 279 | unlock_and_exit: | 273 | unlock_and_exit: |
| 280 | if (flags & ACPI_NOT_ISR) { | 274 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
| 281 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
| 282 | } | ||
| 283 | return_ACPI_STATUS(status); | 275 | return_ACPI_STATUS(status); |
| 284 | } | 276 | } |
| 285 | 277 | ||
| @@ -299,22 +291,15 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | |||
| 299 | * DESCRIPTION: Disable an ACPI event (general purpose) | 291 | * DESCRIPTION: Disable an ACPI event (general purpose) |
| 300 | * | 292 | * |
| 301 | ******************************************************************************/ | 293 | ******************************************************************************/ |
| 302 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | 294 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) |
| 303 | { | 295 | { |
| 304 | acpi_status status = AE_OK; | 296 | acpi_status status = AE_OK; |
| 297 | acpi_cpu_flags flags; | ||
| 305 | struct acpi_gpe_event_info *gpe_event_info; | 298 | struct acpi_gpe_event_info *gpe_event_info; |
| 306 | 299 | ||
| 307 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); | 300 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); |
| 308 | 301 | ||
| 309 | /* Use semaphore lock if not executing at interrupt level */ | 302 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
| 310 | |||
| 311 | if (flags & ACPI_NOT_ISR) { | ||
| 312 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
| 313 | if (ACPI_FAILURE(status)) { | ||
| 314 | return_ACPI_STATUS(status); | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | /* Ensure that we have a valid GPE number */ | 303 | /* Ensure that we have a valid GPE number */ |
| 319 | 304 | ||
| 320 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 305 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
| @@ -325,10 +310,8 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | |||
| 325 | 310 | ||
| 326 | status = acpi_ev_disable_gpe(gpe_event_info); | 311 | status = acpi_ev_disable_gpe(gpe_event_info); |
| 327 | 312 | ||
| 328 | unlock_and_exit: | 313 | unlock_and_exit: |
| 329 | if (flags & ACPI_NOT_ISR) { | 314 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
| 330 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
| 331 | } | ||
| 332 | return_ACPI_STATUS(status); | 315 | return_ACPI_STATUS(status); |
| 333 | } | 316 | } |
| 334 | 317 | ||
| @@ -521,6 +504,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) | |||
| 521 | if (value) | 504 | if (value) |
| 522 | *event_status |= ACPI_EVENT_FLAG_SET; | 505 | *event_status |= ACPI_EVENT_FLAG_SET; |
| 523 | 506 | ||
| 507 | if (acpi_gbl_fixed_event_handlers[event].handler) | ||
| 508 | *event_status |= ACPI_EVENT_FLAG_HANDLE; | ||
| 509 | |||
| 524 | return_ACPI_STATUS(status); | 510 | return_ACPI_STATUS(status); |
| 525 | } | 511 | } |
| 526 | 512 | ||
| @@ -571,6 +557,9 @@ acpi_get_gpe_status(acpi_handle gpe_device, | |||
| 571 | 557 | ||
| 572 | status = acpi_hw_get_gpe_status(gpe_event_info, event_status); | 558 | status = acpi_hw_get_gpe_status(gpe_event_info, event_status); |
| 573 | 559 | ||
| 560 | if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) | ||
| 561 | *event_status |= ACPI_EVENT_FLAG_HANDLE; | ||
| 562 | |||
| 574 | unlock_and_exit: | 563 | unlock_and_exit: |
| 575 | if (flags & ACPI_NOT_ISR) { | 564 | if (flags & ACPI_NOT_ISR) { |
| 576 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | 565 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 60d54d1f6b19..eaaee1660bdf 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <acpi/acpi_bus.h> | 34 | #include <acpi/acpi_bus.h> |
| 35 | #include <acpi/acpi_drivers.h> | 35 | #include <acpi/acpi_drivers.h> |
| 36 | 36 | ||
| 37 | #define ACPI_FAN_COMPONENT 0x00200000 | ||
| 38 | #define ACPI_FAN_CLASS "fan" | 37 | #define ACPI_FAN_CLASS "fan" |
| 39 | #define ACPI_FAN_FILE_STATE "state" | 38 | #define ACPI_FAN_FILE_STATE "state" |
| 40 | 39 | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 24649ada08df..adec3d15810a 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -140,6 +140,46 @@ struct device *acpi_get_physical_device(acpi_handle handle) | |||
| 140 | 140 | ||
| 141 | EXPORT_SYMBOL(acpi_get_physical_device); | 141 | EXPORT_SYMBOL(acpi_get_physical_device); |
| 142 | 142 | ||
| 143 | /* ToDo: When a PCI bridge is found, return the PCI device behind the bridge | ||
| 144 | * This should work in general, but did not on a Lenovo T61 for the | ||
| 145 | * graphics card. But this must be fixed when the PCI device is | ||
| 146 | * bound and the kernel device struct is attached to the acpi device | ||
| 147 | * Note: A success call will increase reference count by one | ||
| 148 | * Do call put_device(dev) on the returned device then | ||
| 149 | */ | ||
| 150 | struct device *acpi_get_physical_pci_device(acpi_handle handle) | ||
| 151 | { | ||
| 152 | struct device *dev; | ||
| 153 | long long device_id; | ||
| 154 | acpi_status status; | ||
| 155 | |||
| 156 | status = | ||
| 157 | acpi_evaluate_integer(handle, "_ADR", NULL, &device_id); | ||
| 158 | |||
| 159 | if (ACPI_FAILURE(status)) | ||
| 160 | return NULL; | ||
| 161 | |||
| 162 | /* We need to attempt to determine whether the _ADR refers to a | ||
| 163 | PCI device or not. There's no terribly good way to do this, | ||
| 164 | so the best we can hope for is to assume that there'll never | ||
| 165 | be a device in the host bridge */ | ||
| 166 | if (device_id >= 0x10000) { | ||
| 167 | /* It looks like a PCI device. Does it exist? */ | ||
| 168 | dev = acpi_get_physical_device(handle); | ||
| 169 | } else { | ||
| 170 | /* It doesn't look like a PCI device. Does its parent | ||
| 171 | exist? */ | ||
| 172 | acpi_handle phandle; | ||
| 173 | if (acpi_get_parent(handle, &phandle)) | ||
| 174 | return NULL; | ||
| 175 | dev = acpi_get_physical_device(phandle); | ||
| 176 | } | ||
| 177 | if (!dev) | ||
| 178 | return NULL; | ||
| 179 | return dev; | ||
| 180 | } | ||
| 181 | EXPORT_SYMBOL(acpi_get_physical_pci_device); | ||
| 182 | |||
| 143 | static int acpi_bind_one(struct device *dev, acpi_handle handle) | 183 | static int acpi_bind_one(struct device *dev, acpi_handle handle) |
| 144 | { | 184 | { |
| 145 | struct acpi_device *acpi_dev; | 185 | struct acpi_device *acpi_dev; |
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index fcfdef7b4fdd..e52ad91ce2dc 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
| @@ -531,7 +531,7 @@ int __init acpi_irq_penalty_init(void) | |||
| 531 | return 0; | 531 | return 0; |
| 532 | } | 532 | } |
| 533 | 533 | ||
| 534 | static int acpi_irq_balance; /* 0: static, 1: balance */ | 534 | static int acpi_irq_balance = -1; /* 0: static, 1: balance */ |
| 535 | 535 | ||
| 536 | static int acpi_pci_link_allocate(struct acpi_pci_link *link) | 536 | static int acpi_pci_link_allocate(struct acpi_pci_link *link) |
| 537 | { | 537 | { |
| @@ -950,10 +950,17 @@ device_initcall(irqrouter_init_sysfs); | |||
| 950 | 950 | ||
| 951 | static int __init acpi_pci_link_init(void) | 951 | static int __init acpi_pci_link_init(void) |
| 952 | { | 952 | { |
| 953 | |||
| 954 | if (acpi_noirq) | 953 | if (acpi_noirq) |
| 955 | return 0; | 954 | return 0; |
| 956 | 955 | ||
| 956 | if (acpi_irq_balance == -1) { | ||
| 957 | /* no command line switch: enable balancing in IOAPIC mode */ | ||
| 958 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) | ||
| 959 | acpi_irq_balance = 1; | ||
| 960 | else | ||
| 961 | acpi_irq_balance = 0; | ||
| 962 | } | ||
| 963 | |||
| 957 | acpi_link.count = 0; | 964 | acpi_link.count = 0; |
| 958 | INIT_LIST_HEAD(&acpi_link.entries); | 965 | INIT_LIST_HEAD(&acpi_link.entries); |
| 959 | 966 | ||
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1b8f67d21d53..642554b1b60c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -376,15 +376,9 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) | |||
| 376 | 376 | ||
| 377 | static int __init acpi_pci_root_init(void) | 377 | static int __init acpi_pci_root_init(void) |
| 378 | { | 378 | { |
| 379 | |||
| 380 | if (acpi_pci_disabled) | 379 | if (acpi_pci_disabled) |
| 381 | return 0; | 380 | return 0; |
| 382 | 381 | ||
| 383 | /* DEBUG: | ||
| 384 | acpi_dbg_layer = ACPI_PCI_COMPONENT; | ||
| 385 | acpi_dbg_level = 0xFFFFFFFF; | ||
| 386 | */ | ||
| 387 | |||
| 388 | if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) | 382 | if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) |
| 389 | return -ENODEV; | 383 | return -ENODEV; |
| 390 | 384 | ||
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index a1718e56103b..bb7d50dd2818 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
| @@ -44,9 +44,8 @@ | |||
| 44 | #include <acpi/acpi_bus.h> | 44 | #include <acpi/acpi_bus.h> |
| 45 | #include <acpi/acpi_drivers.h> | 45 | #include <acpi/acpi_drivers.h> |
| 46 | 46 | ||
| 47 | #define _COMPONENT ACPI_POWER_COMPONENT | 47 | #define _COMPONENT ACPI_POWER_COMPONENT |
| 48 | ACPI_MODULE_NAME("power"); | 48 | ACPI_MODULE_NAME("power"); |
| 49 | #define ACPI_POWER_COMPONENT 0x00800000 | ||
| 50 | #define ACPI_POWER_CLASS "power_resource" | 49 | #define ACPI_POWER_CLASS "power_resource" |
| 51 | #define ACPI_POWER_DEVICE_NAME "Power Resource" | 50 | #define ACPI_POWER_DEVICE_NAME "Power Resource" |
| 52 | #define ACPI_POWER_FILE_INFO "info" | 51 | #define ACPI_POWER_FILE_INFO "info" |
| @@ -153,7 +152,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state) | |||
| 153 | ACPI_POWER_RESOURCE_STATE_OFF; | 152 | ACPI_POWER_RESOURCE_STATE_OFF; |
| 154 | 153 | ||
| 155 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", | 154 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", |
| 156 | acpi_ut_get_node_name(handle), state ? "on" : "off")); | 155 | acpi_ut_get_node_name(handle), |
| 156 | *state ? "on" : "off")); | ||
| 157 | 157 | ||
| 158 | return 0; | 158 | return 0; |
| 159 | } | 159 | } |
| @@ -516,11 +516,6 @@ int acpi_power_transition(struct acpi_device *device, int state) | |||
| 516 | cl = &device->power.states[device->power.state].resources; | 516 | cl = &device->power.states[device->power.state].resources; |
| 517 | tl = &device->power.states[state].resources; | 517 | tl = &device->power.states[state].resources; |
| 518 | 518 | ||
| 519 | if (!cl->count && !tl->count) { | ||
| 520 | result = -ENODEV; | ||
| 521 | goto end; | ||
| 522 | } | ||
| 523 | |||
| 524 | /* TBD: Resources must be ordered. */ | 519 | /* TBD: Resources must be ordered. */ |
| 525 | 520 | ||
| 526 | /* | 521 | /* |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 24a362f8034c..34948362f41d 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -59,7 +59,6 @@ | |||
| 59 | #include <acpi/acpi_drivers.h> | 59 | #include <acpi/acpi_drivers.h> |
| 60 | #include <acpi/processor.h> | 60 | #include <acpi/processor.h> |
| 61 | 61 | ||
| 62 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
| 63 | #define ACPI_PROCESSOR_CLASS "processor" | 62 | #define ACPI_PROCESSOR_CLASS "processor" |
| 64 | #define ACPI_PROCESSOR_DEVICE_NAME "Processor" | 63 | #define ACPI_PROCESSOR_DEVICE_NAME "Processor" |
| 65 | #define ACPI_PROCESSOR_FILE_INFO "info" | 64 | #define ACPI_PROCESSOR_FILE_INFO "info" |
| @@ -89,6 +88,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr); | |||
| 89 | 88 | ||
| 90 | 89 | ||
| 91 | static const struct acpi_device_id processor_device_ids[] = { | 90 | static const struct acpi_device_id processor_device_ids[] = { |
| 91 | {ACPI_PROCESSOR_OBJECT_HID, 0}, | ||
| 92 | {ACPI_PROCESSOR_HID, 0}, | 92 | {ACPI_PROCESSOR_HID, 0}, |
| 93 | {"", 0}, | 93 | {"", 0}, |
| 94 | }; | 94 | }; |
| @@ -409,7 +409,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device) | |||
| 409 | /* Use the acpiid in MADT to map cpus in case of SMP */ | 409 | /* Use the acpiid in MADT to map cpus in case of SMP */ |
| 410 | 410 | ||
| 411 | #ifndef CONFIG_SMP | 411 | #ifndef CONFIG_SMP |
| 412 | static int get_cpu_id(acpi_handle handle, u32 acpi_id) {return -1;} | 412 | static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { return -1; } |
| 413 | #else | 413 | #else |
| 414 | 414 | ||
| 415 | static struct acpi_table_madt *madt; | 415 | static struct acpi_table_madt *madt; |
| @@ -428,27 +428,35 @@ static int map_lapic_id(struct acpi_subtable_header *entry, | |||
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | static int map_lsapic_id(struct acpi_subtable_header *entry, | 430 | static int map_lsapic_id(struct acpi_subtable_header *entry, |
| 431 | u32 acpi_id, int *apic_id) | 431 | int device_declaration, u32 acpi_id, int *apic_id) |
| 432 | { | 432 | { |
| 433 | struct acpi_madt_local_sapic *lsapic = | 433 | struct acpi_madt_local_sapic *lsapic = |
| 434 | (struct acpi_madt_local_sapic *)entry; | 434 | (struct acpi_madt_local_sapic *)entry; |
| 435 | u32 tmp = (lsapic->id << 8) | lsapic->eid; | ||
| 436 | |||
| 435 | /* Only check enabled APICs*/ | 437 | /* Only check enabled APICs*/ |
| 436 | if (lsapic->lapic_flags & ACPI_MADT_ENABLED) { | 438 | if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED)) |
| 437 | /* First check against id */ | 439 | return 0; |
| 438 | if (lsapic->processor_id == acpi_id) { | 440 | |
| 439 | *apic_id = (lsapic->id << 8) | lsapic->eid; | 441 | /* Device statement declaration type */ |
| 440 | return 1; | 442 | if (device_declaration) { |
| 441 | /* Check against optional uid */ | 443 | if (entry->length < 16) |
| 442 | } else if (entry->length >= 16 && | 444 | printk(KERN_ERR PREFIX |
| 443 | lsapic->uid == acpi_id) { | 445 | "Invalid LSAPIC with Device type processor (SAPIC ID %#x)\n", |
| 444 | *apic_id = lsapic->uid; | 446 | tmp); |
| 445 | return 1; | 447 | else if (lsapic->uid == acpi_id) |
| 446 | } | 448 | goto found; |
| 447 | } | 449 | /* Processor statement declaration type */ |
| 450 | } else if (lsapic->processor_id == acpi_id) | ||
| 451 | goto found; | ||
| 452 | |||
| 448 | return 0; | 453 | return 0; |
| 454 | found: | ||
| 455 | *apic_id = tmp; | ||
| 456 | return 1; | ||
| 449 | } | 457 | } |
| 450 | 458 | ||
| 451 | static int map_madt_entry(u32 acpi_id) | 459 | static int map_madt_entry(int type, u32 acpi_id) |
| 452 | { | 460 | { |
| 453 | unsigned long madt_end, entry; | 461 | unsigned long madt_end, entry; |
| 454 | int apic_id = -1; | 462 | int apic_id = -1; |
| @@ -469,7 +477,7 @@ static int map_madt_entry(u32 acpi_id) | |||
| 469 | if (map_lapic_id(header, acpi_id, &apic_id)) | 477 | if (map_lapic_id(header, acpi_id, &apic_id)) |
| 470 | break; | 478 | break; |
| 471 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 479 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
| 472 | if (map_lsapic_id(header, acpi_id, &apic_id)) | 480 | if (map_lsapic_id(header, type, acpi_id, &apic_id)) |
| 473 | break; | 481 | break; |
| 474 | } | 482 | } |
| 475 | entry += header->length; | 483 | entry += header->length; |
| @@ -477,7 +485,7 @@ static int map_madt_entry(u32 acpi_id) | |||
| 477 | return apic_id; | 485 | return apic_id; |
| 478 | } | 486 | } |
| 479 | 487 | ||
| 480 | static int map_mat_entry(acpi_handle handle, u32 acpi_id) | 488 | static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) |
| 481 | { | 489 | { |
| 482 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 490 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 483 | union acpi_object *obj; | 491 | union acpi_object *obj; |
| @@ -500,7 +508,7 @@ static int map_mat_entry(acpi_handle handle, u32 acpi_id) | |||
| 500 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { | 508 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { |
| 501 | map_lapic_id(header, acpi_id, &apic_id); | 509 | map_lapic_id(header, acpi_id, &apic_id); |
| 502 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 510 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
| 503 | map_lsapic_id(header, acpi_id, &apic_id); | 511 | map_lsapic_id(header, type, acpi_id, &apic_id); |
| 504 | } | 512 | } |
| 505 | 513 | ||
| 506 | exit: | 514 | exit: |
| @@ -509,14 +517,14 @@ exit: | |||
| 509 | return apic_id; | 517 | return apic_id; |
| 510 | } | 518 | } |
| 511 | 519 | ||
| 512 | static int get_cpu_id(acpi_handle handle, u32 acpi_id) | 520 | static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) |
| 513 | { | 521 | { |
| 514 | int i; | 522 | int i; |
| 515 | int apic_id = -1; | 523 | int apic_id = -1; |
| 516 | 524 | ||
| 517 | apic_id = map_mat_entry(handle, acpi_id); | 525 | apic_id = map_mat_entry(handle, type, acpi_id); |
| 518 | if (apic_id == -1) | 526 | if (apic_id == -1) |
| 519 | apic_id = map_madt_entry(acpi_id); | 527 | apic_id = map_madt_entry(type, acpi_id); |
| 520 | if (apic_id == -1) | 528 | if (apic_id == -1) |
| 521 | return apic_id; | 529 | return apic_id; |
| 522 | 530 | ||
| @@ -532,15 +540,16 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id) | |||
| 532 | Driver Interface | 540 | Driver Interface |
| 533 | -------------------------------------------------------------------------- */ | 541 | -------------------------------------------------------------------------- */ |
| 534 | 542 | ||
| 535 | static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) | 543 | static int acpi_processor_get_info(struct acpi_device *device) |
| 536 | { | 544 | { |
| 537 | acpi_status status = 0; | 545 | acpi_status status = 0; |
| 538 | union acpi_object object = { 0 }; | 546 | union acpi_object object = { 0 }; |
| 539 | struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; | 547 | struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; |
| 540 | int cpu_index; | 548 | struct acpi_processor *pr; |
| 549 | int cpu_index, device_declaration = 0; | ||
| 541 | static int cpu0_initialized; | 550 | static int cpu0_initialized; |
| 542 | 551 | ||
| 543 | 552 | pr = acpi_driver_data(device); | |
| 544 | if (!pr) | 553 | if (!pr) |
| 545 | return -EINVAL; | 554 | return -EINVAL; |
| 546 | 555 | ||
| @@ -561,22 +570,23 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) | |||
| 561 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 570 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 562 | "No bus mastering arbitration control\n")); | 571 | "No bus mastering arbitration control\n")); |
| 563 | 572 | ||
| 564 | /* Check if it is a Device with HID and UID */ | 573 | if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) { |
| 565 | if (has_uid) { | 574 | /* |
| 575 | * Declared with "Device" statement; match _UID. | ||
| 576 | * Note that we don't handle string _UIDs yet. | ||
| 577 | */ | ||
| 566 | unsigned long long value; | 578 | unsigned long long value; |
| 567 | status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, | 579 | status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, |
| 568 | NULL, &value); | 580 | NULL, &value); |
| 569 | if (ACPI_FAILURE(status)) { | 581 | if (ACPI_FAILURE(status)) { |
| 570 | printk(KERN_ERR PREFIX "Evaluating processor _UID\n"); | 582 | printk(KERN_ERR PREFIX |
| 583 | "Evaluating processor _UID [%#x]\n", status); | ||
| 571 | return -ENODEV; | 584 | return -ENODEV; |
| 572 | } | 585 | } |
| 586 | device_declaration = 1; | ||
| 573 | pr->acpi_id = value; | 587 | pr->acpi_id = value; |
| 574 | } else { | 588 | } else { |
| 575 | /* | 589 | /* Declared with "Processor" statement; match ProcessorID */ |
| 576 | * Evalute the processor object. Note that it is common on SMP to | ||
| 577 | * have the first (boot) processor with a valid PBLK address while | ||
| 578 | * all others have a NULL address. | ||
| 579 | */ | ||
| 580 | status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); | 590 | status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); |
| 581 | if (ACPI_FAILURE(status)) { | 591 | if (ACPI_FAILURE(status)) { |
| 582 | printk(KERN_ERR PREFIX "Evaluating processor object\n"); | 592 | printk(KERN_ERR PREFIX "Evaluating processor object\n"); |
| @@ -584,12 +594,13 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) | |||
| 584 | } | 594 | } |
| 585 | 595 | ||
| 586 | /* | 596 | /* |
| 587 | * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. | 597 | * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. |
| 588 | * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c | 598 | * >>> 'acpi_get_processor_id(acpi_id, &id)' in |
| 589 | */ | 599 | * arch/xxx/acpi.c |
| 600 | */ | ||
| 590 | pr->acpi_id = object.processor.proc_id; | 601 | pr->acpi_id = object.processor.proc_id; |
| 591 | } | 602 | } |
| 592 | cpu_index = get_cpu_id(pr->handle, pr->acpi_id); | 603 | cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); |
| 593 | 604 | ||
| 594 | /* Handle UP system running SMP kernel, with no LAPIC in MADT */ | 605 | /* Handle UP system running SMP kernel, with no LAPIC in MADT */ |
| 595 | if (!cpu0_initialized && (cpu_index == -1) && | 606 | if (!cpu0_initialized && (cpu_index == -1) && |
| @@ -661,7 +672,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) | |||
| 661 | 672 | ||
| 662 | pr = acpi_driver_data(device); | 673 | pr = acpi_driver_data(device); |
| 663 | 674 | ||
| 664 | result = acpi_processor_get_info(pr, device->flags.unique_id); | 675 | result = acpi_processor_get_info(device); |
| 665 | if (result) { | 676 | if (result) { |
| 666 | /* Processor is physically not present */ | 677 | /* Processor is physically not present */ |
| 667 | return 0; | 678 | return 0; |
| @@ -761,20 +772,20 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) | |||
| 761 | acpi_bus_generate_proc_event(device, event, | 772 | acpi_bus_generate_proc_event(device, event, |
| 762 | pr->performance_platform_limit); | 773 | pr->performance_platform_limit); |
| 763 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 774 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
| 764 | device->dev.bus_id, event, | 775 | dev_name(&device->dev), event, |
| 765 | pr->performance_platform_limit); | 776 | pr->performance_platform_limit); |
| 766 | break; | 777 | break; |
| 767 | case ACPI_PROCESSOR_NOTIFY_POWER: | 778 | case ACPI_PROCESSOR_NOTIFY_POWER: |
| 768 | acpi_processor_cst_has_changed(pr); | 779 | acpi_processor_cst_has_changed(pr); |
| 769 | acpi_bus_generate_proc_event(device, event, 0); | 780 | acpi_bus_generate_proc_event(device, event, 0); |
| 770 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 781 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
| 771 | device->dev.bus_id, event, 0); | 782 | dev_name(&device->dev), event, 0); |
| 772 | break; | 783 | break; |
| 773 | case ACPI_PROCESSOR_NOTIFY_THROTTLING: | 784 | case ACPI_PROCESSOR_NOTIFY_THROTTLING: |
| 774 | acpi_processor_tstate_has_changed(pr); | 785 | acpi_processor_tstate_has_changed(pr); |
| 775 | acpi_bus_generate_proc_event(device, event, 0); | 786 | acpi_bus_generate_proc_event(device, event, 0); |
| 776 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 787 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
| 777 | device->dev.bus_id, event, 0); | 788 | dev_name(&device->dev), event, 0); |
| 778 | default: | 789 | default: |
| 779 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 790 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 780 | "Unsupported event [0x%x]\n", event)); | 791 | "Unsupported event [0x%x]\n", event)); |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 81b40ed5379e..5f8d746a9b81 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -59,7 +59,6 @@ | |||
| 59 | #include <acpi/processor.h> | 59 | #include <acpi/processor.h> |
| 60 | #include <asm/processor.h> | 60 | #include <asm/processor.h> |
| 61 | 61 | ||
| 62 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
| 63 | #define ACPI_PROCESSOR_CLASS "processor" | 62 | #define ACPI_PROCESSOR_CLASS "processor" |
| 64 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 63 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 65 | ACPI_MODULE_NAME("processor_idle"); | 64 | ACPI_MODULE_NAME("processor_idle"); |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index dbcf260ea93f..0d7b772bef50 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
| @@ -44,9 +44,9 @@ | |||
| 44 | #endif | 44 | #endif |
| 45 | 45 | ||
| 46 | #include <acpi/acpi_bus.h> | 46 | #include <acpi/acpi_bus.h> |
| 47 | #include <acpi/acpi_drivers.h> | ||
| 47 | #include <acpi/processor.h> | 48 | #include <acpi/processor.h> |
| 48 | 49 | ||
| 49 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
| 50 | #define ACPI_PROCESSOR_CLASS "processor" | 50 | #define ACPI_PROCESSOR_CLASS "processor" |
| 51 | #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" | 51 | #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" |
| 52 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 52 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index ef34b18f95ca..b1eb376fae45 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c | |||
| @@ -40,7 +40,6 @@ | |||
| 40 | #include <acpi/processor.h> | 40 | #include <acpi/processor.h> |
| 41 | #include <acpi/acpi_drivers.h> | 41 | #include <acpi/acpi_drivers.h> |
| 42 | 42 | ||
| 43 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
| 44 | #define ACPI_PROCESSOR_CLASS "processor" | 43 | #define ACPI_PROCESSOR_CLASS "processor" |
| 45 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 46 | ACPI_MODULE_NAME("processor_thermal"); | 45 | ACPI_MODULE_NAME("processor_thermal"); |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 3da2df93d924..a0c38c94a8a0 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
| @@ -38,9 +38,9 @@ | |||
| 38 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
| 39 | 39 | ||
| 40 | #include <acpi/acpi_bus.h> | 40 | #include <acpi/acpi_bus.h> |
| 41 | #include <acpi/acpi_drivers.h> | ||
| 41 | #include <acpi/processor.h> | 42 | #include <acpi/processor.h> |
| 42 | 43 | ||
| 43 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
| 44 | #define ACPI_PROCESSOR_CLASS "processor" | 44 | #define ACPI_PROCESSOR_CLASS "processor" |
| 45 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 45 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 46 | ACPI_MODULE_NAME("processor_throttling"); | 46 | ACPI_MODULE_NAME("processor_throttling"); |
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index 755baf2ca70a..a6b662c00b67 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c | |||
| @@ -15,28 +15,9 @@ void acpi_reboot(void) | |||
| 15 | 15 | ||
| 16 | rr = &acpi_gbl_FADT.reset_register; | 16 | rr = &acpi_gbl_FADT.reset_register; |
| 17 | 17 | ||
| 18 | /* | 18 | /* Is the reset register supported? */ |
| 19 | * Is the ACPI reset register supported? | 19 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || |
| 20 | * | 20 | rr->bit_width != 8 || rr->bit_offset != 0) |
| 21 | * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates | ||
| 22 | * whether the ACPI reset mechanism is supported. | ||
| 23 | * | ||
| 24 | * However, some boxes have this bit clear, yet a valid | ||
| 25 | * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only | ||
| 26 | * mechanism that works for them after S3. | ||
| 27 | * | ||
| 28 | * This suggests that other operating systems may not be checking | ||
| 29 | * the RESET_REG_SUP bit, and are using other means to decide | ||
| 30 | * whether to use the ACPI reboot mechanism or not. | ||
| 31 | * | ||
| 32 | * So when acpi reboot is requested, | ||
| 33 | * only the reset_register is checked. If the following | ||
| 34 | * conditions are met, it indicates that the reset register is supported. | ||
| 35 | * a. reset_register is not zero | ||
| 36 | * b. the access width is eight | ||
| 37 | * c. the bit_offset is zero | ||
| 38 | */ | ||
| 39 | if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0) | ||
| 40 | return; | 21 | return; |
| 41 | 22 | ||
| 42 | reset_value = acpi_gbl_FADT.reset_value; | 23 | reset_value = acpi_gbl_FADT.reset_value; |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a9dda8e0f9f9..bd5253ee5c85 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -109,8 +109,7 @@ static int acpi_bus_hot_remove_device(void *context) | |||
| 109 | return 0; | 109 | return 0; |
| 110 | 110 | ||
| 111 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 111 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 112 | "Hot-removing device %s...\n", device->dev.bus_id)); | 112 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
| 113 | |||
| 114 | 113 | ||
| 115 | if (acpi_bus_trim(device, 1)) { | 114 | if (acpi_bus_trim(device, 1)) { |
| 116 | printk(KERN_ERR PREFIX | 115 | printk(KERN_ERR PREFIX |
| @@ -460,7 +459,7 @@ static int acpi_device_register(struct acpi_device *device, | |||
| 460 | acpi_device_bus_id->instance_no = 0; | 459 | acpi_device_bus_id->instance_no = 0; |
| 461 | list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); | 460 | list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); |
| 462 | } | 461 | } |
| 463 | sprintf(device->dev.bus_id, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); | 462 | dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); |
| 464 | 463 | ||
| 465 | if (device->parent) { | 464 | if (device->parent) { |
| 466 | list_add_tail(&device->node, &device->parent->children); | 465 | list_add_tail(&device->node, &device->parent->children); |
| @@ -484,7 +483,8 @@ static int acpi_device_register(struct acpi_device *device, | |||
| 484 | 483 | ||
| 485 | result = acpi_device_setup_files(device); | 484 | result = acpi_device_setup_files(device); |
| 486 | if(result) | 485 | if(result) |
| 487 | printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", device->dev.bus_id); | 486 | printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", |
| 487 | dev_name(&device->dev)); | ||
| 488 | 488 | ||
| 489 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; | 489 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; |
| 490 | return 0; | 490 | return 0; |
| @@ -919,36 +919,6 @@ static void acpi_device_get_busid(struct acpi_device *device, | |||
| 919 | } | 919 | } |
| 920 | } | 920 | } |
| 921 | 921 | ||
| 922 | static int | ||
| 923 | acpi_video_bus_match(struct acpi_device *device) | ||
| 924 | { | ||
| 925 | acpi_handle h_dummy; | ||
| 926 | |||
| 927 | if (!device) | ||
| 928 | return -EINVAL; | ||
| 929 | |||
| 930 | /* Since there is no HID, CID for ACPI Video drivers, we have | ||
| 931 | * to check well known required nodes for each feature we support. | ||
| 932 | */ | ||
| 933 | |||
| 934 | /* Does this device able to support video switching ? */ | ||
| 935 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && | ||
| 936 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) | ||
| 937 | return 0; | ||
| 938 | |||
| 939 | /* Does this device able to retrieve a video ROM ? */ | ||
| 940 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) | ||
| 941 | return 0; | ||
| 942 | |||
| 943 | /* Does this device able to configure which video head to be POSTed ? */ | ||
| 944 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && | ||
| 945 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && | ||
| 946 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) | ||
| 947 | return 0; | ||
| 948 | |||
| 949 | return -ENODEV; | ||
| 950 | } | ||
| 951 | |||
| 952 | /* | 922 | /* |
| 953 | * acpi_bay_match - see if a device is an ejectable driver bay | 923 | * acpi_bay_match - see if a device is an ejectable driver bay |
| 954 | * | 924 | * |
| @@ -1031,7 +1001,7 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
| 1031 | will get autoloaded and the device might still match | 1001 | will get autoloaded and the device might still match |
| 1032 | against another driver. | 1002 | against another driver. |
| 1033 | */ | 1003 | */ |
| 1034 | if (ACPI_SUCCESS(acpi_video_bus_match(device))) | 1004 | if (acpi_is_video_device(device)) |
| 1035 | cid_add = ACPI_VIDEO_HID; | 1005 | cid_add = ACPI_VIDEO_HID; |
| 1036 | else if (ACPI_SUCCESS(acpi_bay_match(device))) | 1006 | else if (ACPI_SUCCESS(acpi_bay_match(device))) |
| 1037 | cid_add = ACPI_BAY_HID; | 1007 | cid_add = ACPI_BAY_HID; |
| @@ -1043,7 +1013,7 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
| 1043 | hid = ACPI_POWER_HID; | 1013 | hid = ACPI_POWER_HID; |
| 1044 | break; | 1014 | break; |
| 1045 | case ACPI_BUS_TYPE_PROCESSOR: | 1015 | case ACPI_BUS_TYPE_PROCESSOR: |
| 1046 | hid = ACPI_PROCESSOR_HID; | 1016 | hid = ACPI_PROCESSOR_OBJECT_HID; |
| 1047 | break; | 1017 | break; |
| 1048 | case ACPI_BUS_TYPE_SYSTEM: | 1018 | case ACPI_BUS_TYPE_SYSTEM: |
| 1049 | hid = ACPI_SYSTEM_HID; | 1019 | hid = ACPI_SYSTEM_HID; |
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 631ee2ee2ca0..4dbc2271acf5 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c | |||
| @@ -367,7 +367,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
| 367 | if (ldev) | 367 | if (ldev) |
| 368 | seq_printf(seq, "%s:%s", | 368 | seq_printf(seq, "%s:%s", |
| 369 | ldev->bus ? ldev->bus->name : "no-bus", | 369 | ldev->bus ? ldev->bus->name : "no-bus", |
| 370 | ldev->bus_id); | 370 | dev_name(ldev)); |
| 371 | seq_printf(seq, "\n"); | 371 | seq_printf(seq, "\n"); |
| 372 | put_device(ldev); | 372 | put_device(ldev); |
| 373 | 373 | ||
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 38655eb132dc..dea4c23df764 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c | |||
| @@ -88,7 +88,7 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
| 88 | spin_unlock(&acpi_device_lock); | 88 | spin_unlock(&acpi_device_lock); |
| 89 | if (!dev->wakeup.flags.run_wake) | 89 | if (!dev->wakeup.flags.run_wake) |
| 90 | acpi_enable_gpe(dev->wakeup.gpe_device, | 90 | acpi_enable_gpe(dev->wakeup.gpe_device, |
| 91 | dev->wakeup.gpe_number, ACPI_ISR); | 91 | dev->wakeup.gpe_number); |
| 92 | spin_lock(&acpi_device_lock); | 92 | spin_lock(&acpi_device_lock); |
| 93 | } | 93 | } |
| 94 | spin_unlock(&acpi_device_lock); | 94 | spin_unlock(&acpi_device_lock); |
| @@ -122,7 +122,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
| 122 | ACPI_GPE_TYPE_WAKE_RUN); | 122 | ACPI_GPE_TYPE_WAKE_RUN); |
| 123 | /* Re-enable it, since set_gpe_type will disable it */ | 123 | /* Re-enable it, since set_gpe_type will disable it */ |
| 124 | acpi_enable_gpe(dev->wakeup.gpe_device, | 124 | acpi_enable_gpe(dev->wakeup.gpe_device, |
| 125 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 125 | dev->wakeup.gpe_number); |
| 126 | spin_lock(&acpi_device_lock); | 126 | spin_lock(&acpi_device_lock); |
| 127 | } | 127 | } |
| 128 | continue; | 128 | continue; |
| @@ -133,7 +133,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
| 133 | /* Never disable run-wake GPE */ | 133 | /* Never disable run-wake GPE */ |
| 134 | if (!dev->wakeup.flags.run_wake) { | 134 | if (!dev->wakeup.flags.run_wake) { |
| 135 | acpi_disable_gpe(dev->wakeup.gpe_device, | 135 | acpi_disable_gpe(dev->wakeup.gpe_device, |
| 136 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 136 | dev->wakeup.gpe_number); |
| 137 | acpi_clear_gpe(dev->wakeup.gpe_device, | 137 | acpi_clear_gpe(dev->wakeup.gpe_device, |
| 138 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 138 | dev->wakeup.gpe_number, ACPI_NOT_ISR); |
| 139 | } | 139 | } |
| @@ -162,7 +162,7 @@ static int __init acpi_wakeup_device_init(void) | |||
| 162 | dev->wakeup.gpe_number, | 162 | dev->wakeup.gpe_number, |
| 163 | ACPI_GPE_TYPE_WAKE_RUN); | 163 | ACPI_GPE_TYPE_WAKE_RUN); |
| 164 | acpi_enable_gpe(dev->wakeup.gpe_device, | 164 | acpi_enable_gpe(dev->wakeup.gpe_device, |
| 165 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 165 | dev->wakeup.gpe_number); |
| 166 | dev->wakeup.state.enabled = 1; | 166 | dev->wakeup.state.enabled = 1; |
| 167 | spin_lock(&acpi_device_lock); | 167 | spin_lock(&acpi_device_lock); |
| 168 | } | 168 | } |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1d74171b7940..6e4107f82403 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
| @@ -78,9 +78,15 @@ static ssize_t acpi_table_show(struct kobject *kobj, | |||
| 78 | container_of(bin_attr, struct acpi_table_attr, attr); | 78 | container_of(bin_attr, struct acpi_table_attr, attr); |
| 79 | struct acpi_table_header *table_header = NULL; | 79 | struct acpi_table_header *table_header = NULL; |
| 80 | acpi_status status; | 80 | acpi_status status; |
| 81 | char name[ACPI_NAME_SIZE]; | ||
| 82 | |||
| 83 | if (strncmp(table_attr->name, "NULL", 4)) | ||
| 84 | memcpy(name, table_attr->name, ACPI_NAME_SIZE); | ||
| 85 | else | ||
| 86 | memcpy(name, "\0\0\0\0", 4); | ||
| 81 | 87 | ||
| 82 | status = | 88 | status = |
| 83 | acpi_get_table(table_attr->name, table_attr->instance, | 89 | acpi_get_table(name, table_attr->instance, |
| 84 | &table_header); | 90 | &table_header); |
| 85 | if (ACPI_FAILURE(status)) | 91 | if (ACPI_FAILURE(status)) |
| 86 | return -ENODEV; | 92 | return -ENODEV; |
| @@ -95,21 +101,24 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | |||
| 95 | struct acpi_table_header *header = NULL; | 101 | struct acpi_table_header *header = NULL; |
| 96 | struct acpi_table_attr *attr = NULL; | 102 | struct acpi_table_attr *attr = NULL; |
| 97 | 103 | ||
| 98 | memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE); | 104 | if (table_header->signature[0] != '\0') |
| 105 | memcpy(table_attr->name, table_header->signature, | ||
| 106 | ACPI_NAME_SIZE); | ||
| 107 | else | ||
| 108 | memcpy(table_attr->name, "NULL", 4); | ||
| 99 | 109 | ||
| 100 | list_for_each_entry(attr, &acpi_table_attr_list, node) { | 110 | list_for_each_entry(attr, &acpi_table_attr_list, node) { |
| 101 | if (!memcmp(table_header->signature, attr->name, | 111 | if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) |
| 102 | ACPI_NAME_SIZE)) | ||
| 103 | if (table_attr->instance < attr->instance) | 112 | if (table_attr->instance < attr->instance) |
| 104 | table_attr->instance = attr->instance; | 113 | table_attr->instance = attr->instance; |
| 105 | } | 114 | } |
| 106 | table_attr->instance++; | 115 | table_attr->instance++; |
| 107 | 116 | ||
| 108 | if (table_attr->instance > 1 || (table_attr->instance == 1 && | 117 | if (table_attr->instance > 1 || (table_attr->instance == 1 && |
| 109 | !acpi_get_table(table_header-> | 118 | !acpi_get_table |
| 110 | signature, 2, | 119 | (table_header->signature, 2, &header))) |
| 111 | &header))) | 120 | sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", |
| 112 | sprintf(table_attr->name + 4, "%d", table_attr->instance); | 121 | table_attr->instance); |
| 113 | 122 | ||
| 114 | table_attr->attr.size = 0; | 123 | table_attr->attr.size = 0; |
| 115 | table_attr->attr.read = acpi_table_show; | 124 | table_attr->attr.read = acpi_table_show; |
| @@ -167,7 +176,6 @@ static int acpi_system_sysfs_init(void) | |||
| 167 | #define COUNT_ERROR 2 /* other */ | 176 | #define COUNT_ERROR 2 /* other */ |
| 168 | #define NUM_COUNTERS_EXTRA 3 | 177 | #define NUM_COUNTERS_EXTRA 3 |
| 169 | 178 | ||
| 170 | #define ACPI_EVENT_VALID 0x01 | ||
| 171 | struct event_counter { | 179 | struct event_counter { |
| 172 | u32 count; | 180 | u32 count; |
| 173 | u32 flags; | 181 | u32 flags; |
| @@ -312,12 +320,6 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) | |||
| 312 | } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) | 320 | } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) |
| 313 | result = acpi_get_event_status(index - num_gpes, status); | 321 | result = acpi_get_event_status(index - num_gpes, status); |
| 314 | 322 | ||
| 315 | /* | ||
| 316 | * sleep/power button GPE/Fixed Event is enabled after acpi_system_init, | ||
| 317 | * check the status at runtime and mark it as valid once it's enabled | ||
| 318 | */ | ||
| 319 | if (!result && (*status & ACPI_EVENT_FLAG_ENABLED)) | ||
| 320 | all_counters[index].flags |= ACPI_EVENT_VALID; | ||
| 321 | end: | 323 | end: |
| 322 | return result; | 324 | return result; |
| 323 | } | 325 | } |
| @@ -346,12 +348,14 @@ static ssize_t counter_show(struct kobject *kobj, | |||
| 346 | if (result) | 348 | if (result) |
| 347 | goto end; | 349 | goto end; |
| 348 | 350 | ||
| 349 | if (!(all_counters[index].flags & ACPI_EVENT_VALID)) | 351 | if (!(status & ACPI_EVENT_FLAG_HANDLE)) |
| 350 | size += sprintf(buf + size, " invalid"); | 352 | size += sprintf(buf + size, " invalid"); |
| 351 | else if (status & ACPI_EVENT_FLAG_ENABLED) | 353 | else if (status & ACPI_EVENT_FLAG_ENABLED) |
| 352 | size += sprintf(buf + size, " enable"); | 354 | size += sprintf(buf + size, " enabled"); |
| 355 | else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) | ||
| 356 | size += sprintf(buf + size, " wake_enabled"); | ||
| 353 | else | 357 | else |
| 354 | size += sprintf(buf + size, " disable"); | 358 | size += sprintf(buf + size, " disabled"); |
| 355 | 359 | ||
| 356 | end: | 360 | end: |
| 357 | size += sprintf(buf + size, "\n"); | 361 | size += sprintf(buf + size, "\n"); |
| @@ -385,7 +389,7 @@ static ssize_t counter_set(struct kobject *kobj, | |||
| 385 | if (result) | 389 | if (result) |
| 386 | goto end; | 390 | goto end; |
| 387 | 391 | ||
| 388 | if (!(all_counters[index].flags & ACPI_EVENT_VALID)) { | 392 | if (!(status & ACPI_EVENT_FLAG_HANDLE)) { |
| 389 | printk(KERN_WARNING PREFIX | 393 | printk(KERN_WARNING PREFIX |
| 390 | "Can not change Invalid GPE/Fixed Event status\n"); | 394 | "Can not change Invalid GPE/Fixed Event status\n"); |
| 391 | return -EINVAL; | 395 | return -EINVAL; |
| @@ -394,10 +398,10 @@ static ssize_t counter_set(struct kobject *kobj, | |||
| 394 | if (index < num_gpes) { | 398 | if (index < num_gpes) { |
| 395 | if (!strcmp(buf, "disable\n") && | 399 | if (!strcmp(buf, "disable\n") && |
| 396 | (status & ACPI_EVENT_FLAG_ENABLED)) | 400 | (status & ACPI_EVENT_FLAG_ENABLED)) |
| 397 | result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR); | 401 | result = acpi_disable_gpe(handle, index); |
| 398 | else if (!strcmp(buf, "enable\n") && | 402 | else if (!strcmp(buf, "enable\n") && |
| 399 | !(status & ACPI_EVENT_FLAG_ENABLED)) | 403 | !(status & ACPI_EVENT_FLAG_ENABLED)) |
| 400 | result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR); | 404 | result = acpi_enable_gpe(handle, index); |
| 401 | else if (!strcmp(buf, "clear\n") && | 405 | else if (!strcmp(buf, "clear\n") && |
| 402 | (status & ACPI_EVENT_FLAG_SET)) | 406 | (status & ACPI_EVENT_FLAG_SET)) |
| 403 | result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); | 407 | result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); |
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 2c7885e7ffba..2817158fb6a1 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c | |||
| @@ -304,7 +304,7 @@ static void acpi_tb_convert_fadt(void) | |||
| 304 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at | 304 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at |
| 305 | * offset 45, 55, 95, and the word located at offset 109, 110. | 305 | * offset 45, 55, 95, and the word located at offset 109, 110. |
| 306 | */ | 306 | */ |
| 307 | if (acpi_gbl_FADT.header.revision < 3) { | 307 | if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) { |
| 308 | acpi_gbl_FADT.preferred_profile = 0; | 308 | acpi_gbl_FADT.preferred_profile = 0; |
| 309 | acpi_gbl_FADT.pstate_control = 0; | 309 | acpi_gbl_FADT.pstate_control = 0; |
| 310 | acpi_gbl_FADT.cst_control = 0; | 310 | acpi_gbl_FADT.cst_control = 0; |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index ad6cae938f0b..073ff09218a9 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
| @@ -47,7 +47,6 @@ | |||
| 47 | #include <acpi/acpi_bus.h> | 47 | #include <acpi/acpi_bus.h> |
| 48 | #include <acpi/acpi_drivers.h> | 48 | #include <acpi/acpi_drivers.h> |
| 49 | 49 | ||
| 50 | #define ACPI_THERMAL_COMPONENT 0x04000000 | ||
| 51 | #define ACPI_THERMAL_CLASS "thermal_zone" | 50 | #define ACPI_THERMAL_CLASS "thermal_zone" |
| 52 | #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" | 51 | #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" |
| 53 | #define ACPI_THERMAL_FILE_STATE "state" | 52 | #define ACPI_THERMAL_FILE_STATE "state" |
| @@ -576,7 +575,7 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) | |||
| 576 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, | 575 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, |
| 577 | tz->trips.critical.flags.enabled); | 576 | tz->trips.critical.flags.enabled); |
| 578 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, | 577 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, |
| 579 | tz->device->dev.bus_id, | 578 | dev_name(&tz->device->dev), |
| 580 | ACPI_THERMAL_NOTIFY_CRITICAL, | 579 | ACPI_THERMAL_NOTIFY_CRITICAL, |
| 581 | tz->trips.critical.flags.enabled); | 580 | tz->trips.critical.flags.enabled); |
| 582 | 581 | ||
| @@ -605,7 +604,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz) | |||
| 605 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT, | 604 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT, |
| 606 | tz->trips.hot.flags.enabled); | 605 | tz->trips.hot.flags.enabled); |
| 607 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, | 606 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, |
| 608 | tz->device->dev.bus_id, | 607 | dev_name(&tz->device->dev), |
| 609 | ACPI_THERMAL_NOTIFY_HOT, | 608 | ACPI_THERMAL_NOTIFY_HOT, |
| 610 | tz->trips.hot.flags.enabled); | 609 | tz->trips.hot.flags.enabled); |
| 611 | 610 | ||
| @@ -1592,14 +1591,14 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data) | |||
| 1592 | acpi_thermal_check(tz); | 1591 | acpi_thermal_check(tz); |
| 1593 | acpi_bus_generate_proc_event(device, event, 0); | 1592 | acpi_bus_generate_proc_event(device, event, 0); |
| 1594 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 1593 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
| 1595 | device->dev.bus_id, event, 0); | 1594 | dev_name(&device->dev), event, 0); |
| 1596 | break; | 1595 | break; |
| 1597 | case ACPI_THERMAL_NOTIFY_DEVICES: | 1596 | case ACPI_THERMAL_NOTIFY_DEVICES: |
| 1598 | acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); | 1597 | acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); |
| 1599 | acpi_thermal_check(tz); | 1598 | acpi_thermal_check(tz); |
| 1600 | acpi_bus_generate_proc_event(device, event, 0); | 1599 | acpi_bus_generate_proc_event(device, event, 0); |
| 1601 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 1600 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
| 1602 | device->dev.bus_id, event, 0); | 1601 | dev_name(&device->dev), event, 0); |
| 1603 | break; | 1602 | break; |
| 1604 | default: | 1603 | default: |
| 1605 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1604 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a29b0ccac65a..baa441929720 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #include <acpi/acpi_bus.h> | 41 | #include <acpi/acpi_bus.h> |
| 42 | #include <acpi/acpi_drivers.h> | 42 | #include <acpi/acpi_drivers.h> |
| 43 | 43 | ||
| 44 | #define ACPI_VIDEO_COMPONENT 0x08000000 | ||
| 45 | #define ACPI_VIDEO_CLASS "video" | 44 | #define ACPI_VIDEO_CLASS "video" |
| 46 | #define ACPI_VIDEO_BUS_NAME "Video Bus" | 45 | #define ACPI_VIDEO_BUS_NAME "Video Bus" |
| 47 | #define ACPI_VIDEO_DEVICE_NAME "Video Device" | 46 | #define ACPI_VIDEO_DEVICE_NAME "Video Device" |
| @@ -739,7 +738,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 739 | device->cap._DSS = 1; | 738 | device->cap._DSS = 1; |
| 740 | } | 739 | } |
| 741 | 740 | ||
| 742 | max_level = acpi_video_init_brightness(device); | 741 | if (acpi_video_backlight_support()) |
| 742 | max_level = acpi_video_init_brightness(device); | ||
| 743 | 743 | ||
| 744 | if (device->cap._BCL && device->cap._BCM && max_level > 0) { | 744 | if (device->cap._BCL && device->cap._BCM && max_level > 0) { |
| 745 | int result; | 745 | int result; |
| @@ -785,18 +785,21 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 785 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 785 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
| 786 | 786 | ||
| 787 | } | 787 | } |
| 788 | if (device->cap._DCS && device->cap._DSS){ | 788 | |
| 789 | static int count = 0; | 789 | if (acpi_video_display_switch_support()) { |
| 790 | char *name; | 790 | |
| 791 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 791 | if (device->cap._DCS && device->cap._DSS) { |
| 792 | if (!name) | 792 | static int count; |
| 793 | return; | 793 | char *name; |
| 794 | sprintf(name, "acpi_video%d", count++); | 794 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); |
| 795 | device->output_dev = video_output_register(name, | 795 | if (!name) |
| 796 | NULL, device, &acpi_output_properties); | 796 | return; |
| 797 | kfree(name); | 797 | sprintf(name, "acpi_video%d", count++); |
| 798 | device->output_dev = video_output_register(name, | ||
| 799 | NULL, device, &acpi_output_properties); | ||
| 800 | kfree(name); | ||
| 801 | } | ||
| 798 | } | 802 | } |
| 799 | return; | ||
| 800 | } | 803 | } |
| 801 | 804 | ||
| 802 | /* | 805 | /* |
| @@ -842,11 +845,16 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) | |||
| 842 | static int acpi_video_bus_check(struct acpi_video_bus *video) | 845 | static int acpi_video_bus_check(struct acpi_video_bus *video) |
| 843 | { | 846 | { |
| 844 | acpi_status status = -ENOENT; | 847 | acpi_status status = -ENOENT; |
| 845 | 848 | struct device *dev; | |
| 846 | 849 | ||
| 847 | if (!video) | 850 | if (!video) |
| 848 | return -EINVAL; | 851 | return -EINVAL; |
| 849 | 852 | ||
| 853 | dev = acpi_get_physical_pci_device(video->device->handle); | ||
| 854 | if (!dev) | ||
| 855 | return -ENODEV; | ||
| 856 | put_device(dev); | ||
| 857 | |||
| 850 | /* Since there is no HID, CID and so on for VGA driver, we have | 858 | /* Since there is no HID, CID and so on for VGA driver, we have |
| 851 | * to check well known required nodes. | 859 | * to check well known required nodes. |
| 852 | */ | 860 | */ |
| @@ -2094,12 +2102,6 @@ static int __init acpi_video_init(void) | |||
| 2094 | { | 2102 | { |
| 2095 | int result = 0; | 2103 | int result = 0; |
| 2096 | 2104 | ||
| 2097 | |||
| 2098 | /* | ||
| 2099 | acpi_dbg_level = 0xFFFFFFFF; | ||
| 2100 | acpi_dbg_layer = 0x08000000; | ||
| 2101 | */ | ||
| 2102 | |||
| 2103 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); | 2105 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); |
| 2104 | if (!acpi_video_dir) | 2106 | if (!acpi_video_dir) |
| 2105 | return -ENODEV; | 2107 | return -ENODEV; |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c new file mode 100644 index 000000000000..f022eb6f5637 --- /dev/null +++ b/drivers/acpi/video_detect.c | |||
| @@ -0,0 +1,267 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2008 SuSE Linux Products GmbH | ||
| 3 | * Thomas Renninger <trenn@suse.de> | ||
| 4 | * | ||
| 5 | * May be copied or modified under the terms of the GNU General Public License | ||
| 6 | * | ||
| 7 | * video_detect.c: | ||
| 8 | * Provides acpi_is_video_device() for early scanning of ACPI devices in scan.c | ||
| 9 | * There a Linux specific (Spec does not provide a HID for video devices) is | ||
| 10 | * assinged | ||
| 11 | * | ||
| 12 | * After PCI devices are glued with ACPI devices | ||
| 13 | * acpi_get_physical_pci_device() can be called to identify ACPI graphics | ||
| 14 | * devices for which a real graphics card is plugged in | ||
| 15 | * | ||
| 16 | * Now acpi_video_get_capabilities() can be called to check which | ||
| 17 | * capabilities the graphics cards plugged in support. The check for general | ||
| 18 | * video capabilities will be triggered by the first caller of | ||
| 19 | * acpi_video_get_capabilities(NULL); which will happen when the first | ||
| 20 | * backlight (or display output) switching supporting driver calls: | ||
| 21 | * acpi_video_backlight_support(); | ||
| 22 | * | ||
| 23 | * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B) | ||
| 24 | * are available, video.ko should be used to handle the device. | ||
| 25 | * | ||
| 26 | * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi, | ||
| 27 | * sony_acpi,... can take care about backlight brightness and display output | ||
| 28 | * switching. | ||
| 29 | * | ||
| 30 | * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m) | ||
| 31 | * this file will not be compiled, acpi_video_get_capabilities() and | ||
| 32 | * acpi_video_backlight_support() will always return 0 and vendor specific | ||
| 33 | * drivers always can handle backlight. | ||
| 34 | * | ||
| 35 | */ | ||
| 36 | |||
| 37 | #include <linux/acpi.h> | ||
| 38 | #include <linux/dmi.h> | ||
| 39 | |||
| 40 | ACPI_MODULE_NAME("video"); | ||
| 41 | #define _COMPONENT ACPI_VIDEO_COMPONENT | ||
| 42 | |||
| 43 | static long acpi_video_support; | ||
| 44 | static bool acpi_video_caps_checked; | ||
| 45 | |||
| 46 | static acpi_status | ||
| 47 | acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, | ||
| 48 | void **retyurn_value) | ||
| 49 | { | ||
| 50 | long *cap = context; | ||
| 51 | acpi_handle h_dummy; | ||
| 52 | |||
| 53 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) && | ||
| 54 | ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) { | ||
| 55 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " | ||
| 56 | "support\n")); | ||
| 57 | *cap |= ACPI_VIDEO_BACKLIGHT; | ||
| 58 | /* We have backlight support, no need to scan further */ | ||
| 59 | return AE_CTRL_TERMINATE; | ||
| 60 | } | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | /* Returns true if the device is a video device which can be handled by | ||
| 65 | * video.ko. | ||
| 66 | * The device will get a Linux specific CID added in scan.c to | ||
| 67 | * identify the device as an ACPI graphics device | ||
| 68 | * Be aware that the graphics device may not be physically present | ||
| 69 | * Use acpi_video_get_capabilities() to detect general ACPI video | ||
| 70 | * capabilities of present cards | ||
| 71 | */ | ||
| 72 | long acpi_is_video_device(struct acpi_device *device) | ||
| 73 | { | ||
| 74 | acpi_handle h_dummy; | ||
| 75 | long video_caps = 0; | ||
| 76 | |||
| 77 | if (!device) | ||
| 78 | return 0; | ||
| 79 | |||
| 80 | /* Does this device able to support video switching ? */ | ||
| 81 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && | ||
| 82 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) | ||
| 83 | video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; | ||
| 84 | |||
| 85 | /* Does this device able to retrieve a video ROM ? */ | ||
| 86 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) | ||
| 87 | video_caps |= ACPI_VIDEO_ROM_AVAILABLE; | ||
| 88 | |||
| 89 | /* Does this device able to configure which video head to be POSTed ? */ | ||
| 90 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && | ||
| 91 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && | ||
| 92 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) | ||
| 93 | video_caps |= ACPI_VIDEO_DEVICE_POSTING; | ||
| 94 | |||
| 95 | /* Only check for backlight functionality if one of the above hit. */ | ||
| 96 | if (video_caps) | ||
| 97 | acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle, | ||
| 98 | ACPI_UINT32_MAX, acpi_backlight_cap_match, | ||
| 99 | &video_caps, NULL); | ||
| 100 | |||
| 101 | return video_caps; | ||
| 102 | } | ||
| 103 | EXPORT_SYMBOL(acpi_is_video_device); | ||
| 104 | |||
| 105 | static acpi_status | ||
| 106 | find_video(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
| 107 | { | ||
| 108 | long *cap = context; | ||
| 109 | struct device *dev; | ||
| 110 | struct acpi_device *acpi_dev; | ||
| 111 | |||
| 112 | const struct acpi_device_id video_ids[] = { | ||
| 113 | {ACPI_VIDEO_HID, 0}, | ||
| 114 | {"", 0}, | ||
| 115 | }; | ||
| 116 | if (acpi_bus_get_device(handle, &acpi_dev)) | ||
| 117 | return AE_OK; | ||
| 118 | |||
| 119 | if (!acpi_match_device_ids(acpi_dev, video_ids)) { | ||
| 120 | dev = acpi_get_physical_pci_device(handle); | ||
| 121 | if (!dev) | ||
| 122 | return AE_OK; | ||
| 123 | put_device(dev); | ||
| 124 | *cap |= acpi_is_video_device(acpi_dev); | ||
| 125 | } | ||
| 126 | return AE_OK; | ||
| 127 | } | ||
| 128 | |||
| 129 | /* | ||
| 130 | * Returns the video capabilities of a specific ACPI graphics device | ||
| 131 | * | ||
| 132 | * if NULL is passed as argument all ACPI devices are enumerated and | ||
| 133 | * all graphics capabilities of physically present devices are | ||
| 134 | * summerized and returned. This is cached and done only once. | ||
| 135 | */ | ||
| 136 | long acpi_video_get_capabilities(acpi_handle graphics_handle) | ||
| 137 | { | ||
| 138 | long caps = 0; | ||
| 139 | struct acpi_device *tmp_dev; | ||
| 140 | acpi_status status; | ||
| 141 | |||
| 142 | if (acpi_video_caps_checked && graphics_handle == NULL) | ||
| 143 | return acpi_video_support; | ||
| 144 | |||
| 145 | if (!graphics_handle) { | ||
| 146 | /* Only do the global walk through all graphics devices once */ | ||
| 147 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 148 | ACPI_UINT32_MAX, find_video, | ||
| 149 | &caps, NULL); | ||
| 150 | /* There might be boot param flags set already... */ | ||
| 151 | acpi_video_support |= caps; | ||
| 152 | acpi_video_caps_checked = 1; | ||
| 153 | /* Add blacklists here. Be careful to use the right *DMI* bits | ||
| 154 | * to still be able to override logic via boot params, e.g.: | ||
| 155 | * | ||
| 156 | * if (dmi_name_in_vendors("XY")) { | ||
| 157 | * acpi_video_support |= | ||
| 158 | * ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR; | ||
| 159 | * acpi_video_support |= | ||
| 160 | * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; | ||
| 161 | *} | ||
| 162 | */ | ||
| 163 | } else { | ||
| 164 | status = acpi_bus_get_device(graphics_handle, &tmp_dev); | ||
| 165 | if (ACPI_FAILURE(status)) { | ||
| 166 | ACPI_EXCEPTION((AE_INFO, status, "Invalid device")); | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | acpi_walk_namespace(ACPI_TYPE_DEVICE, graphics_handle, | ||
| 170 | ACPI_UINT32_MAX, find_video, | ||
| 171 | &caps, NULL); | ||
| 172 | } | ||
| 173 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support %s %s\n", | ||
| 174 | graphics_handle ? caps : acpi_video_support, | ||
| 175 | graphics_handle ? "on device " : "in general", | ||
| 176 | graphics_handle ? acpi_device_bid(tmp_dev) : "")); | ||
| 177 | return caps; | ||
| 178 | } | ||
| 179 | EXPORT_SYMBOL(acpi_video_get_capabilities); | ||
| 180 | |||
| 181 | /* Returns true if video.ko can do backlight switching */ | ||
| 182 | int acpi_video_backlight_support(void) | ||
| 183 | { | ||
| 184 | /* | ||
| 185 | * We must check whether the ACPI graphics device is physically plugged | ||
| 186 | * in. Therefore this must be called after binding PCI and ACPI devices | ||
| 187 | */ | ||
| 188 | if (!acpi_video_caps_checked) | ||
| 189 | acpi_video_get_capabilities(NULL); | ||
| 190 | |||
| 191 | /* First check for boot param -> highest prio */ | ||
| 192 | if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR) | ||
| 193 | return 0; | ||
| 194 | else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO) | ||
| 195 | return 1; | ||
| 196 | |||
| 197 | /* Then check for DMI blacklist -> second highest prio */ | ||
| 198 | if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VENDOR) | ||
| 199 | return 0; | ||
| 200 | else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VIDEO) | ||
| 201 | return 1; | ||
| 202 | |||
| 203 | /* Then go the default way */ | ||
| 204 | return acpi_video_support & ACPI_VIDEO_BACKLIGHT; | ||
| 205 | } | ||
| 206 | EXPORT_SYMBOL(acpi_video_backlight_support); | ||
| 207 | |||
| 208 | /* | ||
| 209 | * Returns true if video.ko can do display output switching. | ||
| 210 | * This does not work well/at all with binary graphics drivers | ||
| 211 | * which disable system io ranges and do it on their own. | ||
| 212 | */ | ||
| 213 | int acpi_video_display_switch_support(void) | ||
| 214 | { | ||
| 215 | if (!acpi_video_caps_checked) | ||
| 216 | acpi_video_get_capabilities(NULL); | ||
| 217 | |||
| 218 | if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR) | ||
| 219 | return 0; | ||
| 220 | else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO) | ||
| 221 | return 1; | ||
| 222 | |||
| 223 | if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR) | ||
| 224 | return 0; | ||
| 225 | else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO) | ||
| 226 | return 1; | ||
| 227 | |||
| 228 | return acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING; | ||
| 229 | } | ||
| 230 | EXPORT_SYMBOL(acpi_video_display_switch_support); | ||
| 231 | |||
| 232 | /* | ||
| 233 | * Use acpi_display_output=vendor/video or acpi_backlight=vendor/video | ||
| 234 | * To force that backlight or display output switching is processed by vendor | ||
| 235 | * specific acpi drivers or video.ko driver. | ||
| 236 | */ | ||
| 237 | int __init acpi_backlight(char *str) | ||
| 238 | { | ||
| 239 | if (str == NULL || *str == '\0') | ||
| 240 | return 1; | ||
| 241 | else { | ||
| 242 | if (!strcmp("vendor", str)) | ||
| 243 | acpi_video_support |= | ||
| 244 | ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR; | ||
| 245 | if (!strcmp("video", str)) | ||
| 246 | acpi_video_support |= | ||
| 247 | ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; | ||
| 248 | } | ||
| 249 | return 1; | ||
| 250 | } | ||
| 251 | __setup("acpi_backlight=", acpi_backlight); | ||
| 252 | |||
| 253 | int __init acpi_display_output(char *str) | ||
| 254 | { | ||
| 255 | if (str == NULL || *str == '\0') | ||
| 256 | return 1; | ||
| 257 | else { | ||
| 258 | if (!strcmp("vendor", str)) | ||
| 259 | acpi_video_support |= | ||
| 260 | ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR; | ||
| 261 | if (!strcmp("video", str)) | ||
| 262 | acpi_video_support |= | ||
| 263 | ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; | ||
| 264 | } | ||
| 265 | return 1; | ||
| 266 | } | ||
| 267 | __setup("acpi_display_output=", acpi_display_output); | ||
diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c index 47cd7baf9b1b..8a8b377712c9 100644 --- a/drivers/acpi/wmi.c +++ b/drivers/acpi/wmi.c | |||
| @@ -660,7 +660,7 @@ static void acpi_wmi_notify(acpi_handle handle, u32 event, void *data) | |||
| 660 | wblock->handler(event, wblock->handler_data); | 660 | wblock->handler(event, wblock->handler_data); |
| 661 | 661 | ||
| 662 | acpi_bus_generate_netlink_event( | 662 | acpi_bus_generate_netlink_event( |
| 663 | device->pnp.device_class, device->dev.bus_id, | 663 | device->pnp.device_class, dev_name(&device->dev), |
| 664 | event, 0); | 664 | event, 0); |
| 665 | break; | 665 | break; |
| 666 | } | 666 | } |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 0cd3ad497136..4214bfb13bbd 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -612,7 +612,7 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) | |||
| 612 | if (tf->flags & ATA_TFLAG_LBA48) { | 612 | if (tf->flags & ATA_TFLAG_LBA48) { |
| 613 | block |= (u64)tf->hob_lbah << 40; | 613 | block |= (u64)tf->hob_lbah << 40; |
| 614 | block |= (u64)tf->hob_lbam << 32; | 614 | block |= (u64)tf->hob_lbam << 32; |
| 615 | block |= tf->hob_lbal << 24; | 615 | block |= (u64)tf->hob_lbal << 24; |
| 616 | } else | 616 | } else |
| 617 | block |= (tf->device & 0xf) << 24; | 617 | block |= (tf->device & 0xf) << 24; |
| 618 | 618 | ||
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8077bdf5d30d..32da9a93ce44 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
| @@ -610,9 +610,6 @@ void ata_scsi_error(struct Scsi_Host *host) | |||
| 610 | if (ata_ncq_enabled(dev)) | 610 | if (ata_ncq_enabled(dev)) |
| 611 | ehc->saved_ncq_enabled |= 1 << devno; | 611 | ehc->saved_ncq_enabled |= 1 << devno; |
| 612 | } | 612 | } |
| 613 | |||
| 614 | /* set last reset timestamp to some time in the past */ | ||
| 615 | ehc->last_reset = jiffies - 60 * HZ; | ||
| 616 | } | 613 | } |
| 617 | 614 | ||
| 618 | ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; | 615 | ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; |
| @@ -2281,17 +2278,21 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2281 | if (link->flags & ATA_LFLAG_NO_SRST) | 2278 | if (link->flags & ATA_LFLAG_NO_SRST) |
| 2282 | softreset = NULL; | 2279 | softreset = NULL; |
| 2283 | 2280 | ||
| 2284 | now = jiffies; | 2281 | /* make sure each reset attemp is at least COOL_DOWN apart */ |
| 2285 | deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); | 2282 | if (ehc->i.flags & ATA_EHI_DID_RESET) { |
| 2286 | if (time_before(now, deadline)) | 2283 | now = jiffies; |
| 2287 | schedule_timeout_uninterruptible(deadline - now); | 2284 | WARN_ON(time_after(ehc->last_reset, now)); |
| 2285 | deadline = ata_deadline(ehc->last_reset, | ||
| 2286 | ATA_EH_RESET_COOL_DOWN); | ||
| 2287 | if (time_before(now, deadline)) | ||
| 2288 | schedule_timeout_uninterruptible(deadline - now); | ||
| 2289 | } | ||
| 2288 | 2290 | ||
| 2289 | spin_lock_irqsave(ap->lock, flags); | 2291 | spin_lock_irqsave(ap->lock, flags); |
| 2290 | ap->pflags |= ATA_PFLAG_RESETTING; | 2292 | ap->pflags |= ATA_PFLAG_RESETTING; |
| 2291 | spin_unlock_irqrestore(ap->lock, flags); | 2293 | spin_unlock_irqrestore(ap->lock, flags); |
| 2292 | 2294 | ||
| 2293 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET); | 2295 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET); |
| 2294 | ehc->last_reset = jiffies; | ||
| 2295 | 2296 | ||
| 2296 | ata_link_for_each_dev(dev, link) { | 2297 | ata_link_for_each_dev(dev, link) { |
| 2297 | /* If we issue an SRST then an ATA drive (not ATAPI) | 2298 | /* If we issue an SRST then an ATA drive (not ATAPI) |
| @@ -2379,7 +2380,6 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2379 | /* | 2380 | /* |
| 2380 | * Perform reset | 2381 | * Perform reset |
| 2381 | */ | 2382 | */ |
| 2382 | ehc->last_reset = jiffies; | ||
| 2383 | if (ata_is_host_link(link)) | 2383 | if (ata_is_host_link(link)) |
| 2384 | ata_eh_freeze_port(ap); | 2384 | ata_eh_freeze_port(ap); |
| 2385 | 2385 | ||
| @@ -2391,6 +2391,7 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2391 | reset == softreset ? "soft" : "hard"); | 2391 | reset == softreset ? "soft" : "hard"); |
| 2392 | 2392 | ||
| 2393 | /* mark that this EH session started with reset */ | 2393 | /* mark that this EH session started with reset */ |
| 2394 | ehc->last_reset = jiffies; | ||
| 2394 | if (reset == hardreset) | 2395 | if (reset == hardreset) |
| 2395 | ehc->i.flags |= ATA_EHI_DID_HARDRESET; | 2396 | ehc->i.flags |= ATA_EHI_DID_HARDRESET; |
| 2396 | else | 2397 | else |
| @@ -2535,7 +2536,7 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2535 | ata_eh_done(link, NULL, ATA_EH_RESET); | 2536 | ata_eh_done(link, NULL, ATA_EH_RESET); |
| 2536 | if (slave) | 2537 | if (slave) |
| 2537 | ata_eh_done(slave, NULL, ATA_EH_RESET); | 2538 | ata_eh_done(slave, NULL, ATA_EH_RESET); |
| 2538 | ehc->last_reset = jiffies; | 2539 | ehc->last_reset = jiffies; /* update to completion time */ |
| 2539 | ehc->i.action |= ATA_EH_REVALIDATE; | 2540 | ehc->i.action |= ATA_EH_REVALIDATE; |
| 2540 | 2541 | ||
| 2541 | rc = 0; | 2542 | rc = 0; |
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 4b4739486327..9033d164c4ec 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
| @@ -1227,10 +1227,19 @@ fsm_start: | |||
| 1227 | /* ATA PIO protocol */ | 1227 | /* ATA PIO protocol */ |
| 1228 | if (unlikely((status & ATA_DRQ) == 0)) { | 1228 | if (unlikely((status & ATA_DRQ) == 0)) { |
| 1229 | /* handle BSY=0, DRQ=0 as error */ | 1229 | /* handle BSY=0, DRQ=0 as error */ |
| 1230 | if (likely(status & (ATA_ERR | ATA_DF))) | 1230 | if (likely(status & (ATA_ERR | ATA_DF))) { |
| 1231 | /* device stops HSM for abort/error */ | 1231 | /* device stops HSM for abort/error */ |
| 1232 | qc->err_mask |= AC_ERR_DEV; | 1232 | qc->err_mask |= AC_ERR_DEV; |
| 1233 | else { | 1233 | |
| 1234 | /* If diagnostic failed and this is | ||
| 1235 | * IDENTIFY, it's likely a phantom | ||
| 1236 | * device. Mark hint. | ||
| 1237 | */ | ||
| 1238 | if (qc->dev->horkage & | ||
| 1239 | ATA_HORKAGE_DIAGNOSTIC) | ||
| 1240 | qc->err_mask |= | ||
| 1241 | AC_ERR_NODEV_HINT; | ||
| 1242 | } else { | ||
| 1234 | /* HSM violation. Let EH handle this. | 1243 | /* HSM violation. Let EH handle this. |
| 1235 | * Phantom devices also trigger this | 1244 | * Phantom devices also trigger this |
| 1236 | * condition. Mark hint. | 1245 | * condition. Mark hint. |
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 1b2d4a0f5f74..8b236af84c2e 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c | |||
| @@ -72,7 +72,6 @@ | |||
| 72 | /** | 72 | /** |
| 73 | * cs5535_cable_detect - detect cable type | 73 | * cs5535_cable_detect - detect cable type |
| 74 | * @ap: Port to detect on | 74 | * @ap: Port to detect on |
| 75 | * @deadline: deadline jiffies for the operation | ||
| 76 | * | 75 | * |
| 77 | * Perform cable detection for ATA66 capable cable. Return a libata | 76 | * Perform cable detection for ATA66 capable cable. Return a libata |
| 78 | * cable type. | 77 | * cable type. |
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index 73f8332cb679..afed92976198 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c | |||
| @@ -110,7 +110,6 @@ static inline int cs5536_write(struct pci_dev *pdev, int reg, int val) | |||
| 110 | /** | 110 | /** |
| 111 | * cs5536_cable_detect - detect cable type | 111 | * cs5536_cable_detect - detect cable type |
| 112 | * @ap: Port to detect on | 112 | * @ap: Port to detect on |
| 113 | * @deadline: deadline jiffies for the operation | ||
| 114 | * | 113 | * |
| 115 | * Perform cable detection for ATA66 capable cable. Return a libata | 114 | * Perform cable detection for ATA66 capable cable. Return a libata |
| 116 | * cable type. | 115 | * cable type. |
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 271cb64d429e..64b2e2281ee7 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c | |||
| @@ -416,6 +416,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { | |||
| 416 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), | 416 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), |
| 417 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), | 417 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), |
| 418 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), | 418 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), |
| 419 | PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506), | ||
| 419 | PCMCIA_DEVICE_NULL, | 420 | PCMCIA_DEVICE_NULL, |
| 420 | }; | 421 | }; |
| 421 | 422 | ||
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c index c8cc027789fe..6aeeeeb34124 100644 --- a/drivers/ata/pata_sch.c +++ b/drivers/ata/pata_sch.c | |||
| @@ -83,7 +83,7 @@ static struct ata_port_operations sch_pata_ops = { | |||
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | static struct ata_port_info sch_port_info = { | 85 | static struct ata_port_info sch_port_info = { |
| 86 | .flags = 0, | 86 | .flags = ATA_FLAG_SLAVE_POSS, |
| 87 | .pio_mask = ATA_PIO4, /* pio0-4 */ | 87 | .pio_mask = ATA_PIO4, /* pio0-4 */ |
| 88 | .mwdma_mask = ATA_MWDMA2, /* mwdma0-2 */ | 88 | .mwdma_mask = ATA_MWDMA2, /* mwdma0-2 */ |
| 89 | .udma_mask = ATA_UDMA5, /* udma0-5 */ | 89 | .udma_mask = ATA_UDMA5, /* udma0-5 */ |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 61ad8d639ba3..0344a8a8321d 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
| @@ -21,7 +21,8 @@ config BLK_DEV_FD | |||
| 21 | ---help--- | 21 | ---help--- |
| 22 | If you want to use the floppy disk drive(s) of your PC under Linux, | 22 | If you want to use the floppy disk drive(s) of your PC under Linux, |
| 23 | say Y. Information about this driver, especially important for IBM | 23 | say Y. Information about this driver, especially important for IBM |
| 24 | Thinkpad users, is contained in <file:Documentation/floppy.txt>. | 24 | Thinkpad users, is contained in |
| 25 | <file:Documentation/blockdev/floppy.txt>. | ||
| 25 | That file also contains the location of the Floppy driver FAQ as | 26 | That file also contains the location of the Floppy driver FAQ as |
| 26 | well as location of the fdutils package used to configure additional | 27 | well as location of the fdutils package used to configure additional |
| 27 | parameters of the driver at run time. | 28 | parameters of the driver at run time. |
| @@ -76,7 +77,7 @@ config PARIDE | |||
| 76 | your computer's parallel port. Most of them are actually IDE devices | 77 | your computer's parallel port. Most of them are actually IDE devices |
| 77 | using a parallel port IDE adapter. This option enables the PARIDE | 78 | using a parallel port IDE adapter. This option enables the PARIDE |
| 78 | subsystem which contains drivers for many of these external drives. | 79 | subsystem which contains drivers for many of these external drives. |
| 79 | Read <file:Documentation/paride.txt> for more information. | 80 | Read <file:Documentation/blockdev/paride.txt> for more information. |
| 80 | 81 | ||
| 81 | If you have said Y to the "Parallel-port support" configuration | 82 | If you have said Y to the "Parallel-port support" configuration |
| 82 | option, you may share a single port between your printer and other | 83 | option, you may share a single port between your printer and other |
| @@ -114,9 +115,9 @@ config BLK_CPQ_DA | |||
| 114 | help | 115 | help |
| 115 | This is the driver for Compaq Smart Array controllers. Everyone | 116 | This is the driver for Compaq Smart Array controllers. Everyone |
| 116 | using these boards should say Y here. See the file | 117 | using these boards should say Y here. See the file |
| 117 | <file:Documentation/cpqarray.txt> for the current list of boards | 118 | <file:Documentation/blockdev/cpqarray.txt> for the current list of |
| 118 | supported by this driver, and for further information on the use of | 119 | boards supported by this driver, and for further information on the |
| 119 | this driver. | 120 | use of this driver. |
| 120 | 121 | ||
| 121 | config BLK_CPQ_CISS_DA | 122 | config BLK_CPQ_CISS_DA |
| 122 | tristate "Compaq Smart Array 5xxx support" | 123 | tristate "Compaq Smart Array 5xxx support" |
| @@ -124,7 +125,7 @@ config BLK_CPQ_CISS_DA | |||
| 124 | help | 125 | help |
| 125 | This is the driver for Compaq Smart Array 5xxx controllers. | 126 | This is the driver for Compaq Smart Array 5xxx controllers. |
| 126 | Everyone using these boards should say Y here. | 127 | Everyone using these boards should say Y here. |
| 127 | See <file:Documentation/cciss.txt> for the current list of | 128 | See <file:Documentation/blockdev/cciss.txt> for the current list of |
| 128 | boards supported by this driver, and for further information | 129 | boards supported by this driver, and for further information |
| 129 | on the use of this driver. | 130 | on the use of this driver. |
| 130 | 131 | ||
| @@ -135,7 +136,7 @@ config CISS_SCSI_TAPE | |||
| 135 | help | 136 | help |
| 136 | When enabled (Y), this option allows SCSI tape drives and SCSI medium | 137 | When enabled (Y), this option allows SCSI tape drives and SCSI medium |
| 137 | changers (tape robots) to be accessed via a Compaq 5xxx array | 138 | changers (tape robots) to be accessed via a Compaq 5xxx array |
| 138 | controller. (See <file:Documentation/cciss.txt> for more details.) | 139 | controller. (See <file:Documentation/blockdev/cciss.txt> for more details.) |
| 139 | 140 | ||
| 140 | "SCSI support" and "SCSI tape support" must also be enabled for this | 141 | "SCSI support" and "SCSI tape support" must also be enabled for this |
| 141 | option to work. | 142 | option to work. |
| @@ -149,8 +150,8 @@ config BLK_DEV_DAC960 | |||
| 149 | help | 150 | help |
| 150 | This driver adds support for the Mylex DAC960, AcceleRAID, and | 151 | This driver adds support for the Mylex DAC960, AcceleRAID, and |
| 151 | eXtremeRAID PCI RAID controllers. See the file | 152 | eXtremeRAID PCI RAID controllers. See the file |
| 152 | <file:Documentation/README.DAC960> for further information about | 153 | <file:Documentation/blockdev/README.DAC960> for further information |
| 153 | this driver. | 154 | about this driver. |
| 154 | 155 | ||
| 155 | To compile this driver as a module, choose M here: the | 156 | To compile this driver as a module, choose M here: the |
| 156 | module will be called DAC960. | 157 | module will be called DAC960. |
| @@ -278,9 +279,9 @@ config BLK_DEV_NBD | |||
| 278 | userland (making server and client physically the same computer, | 279 | userland (making server and client physically the same computer, |
| 279 | communicating using the loopback network device). | 280 | communicating using the loopback network device). |
| 280 | 281 | ||
| 281 | Read <file:Documentation/nbd.txt> for more information, especially | 282 | Read <file:Documentation/blockdev/nbd.txt> for more information, |
| 282 | about where to find the server code, which runs in user space and | 283 | especially about where to find the server code, which runs in user |
| 283 | does not need special kernel support. | 284 | space and does not need special kernel support. |
| 284 | 285 | ||
| 285 | Note that this has nothing to do with the network file systems NFS | 286 | Note that this has nothing to do with the network file systems NFS |
| 286 | or Coda; you can say N here even if you intend to use NFS or Coda. | 287 | or Coda; you can say N here even if you intend to use NFS or Coda. |
| @@ -321,8 +322,8 @@ config BLK_DEV_RAM | |||
| 321 | store a copy of a minimal root file system off of a floppy into RAM | 322 | store a copy of a minimal root file system off of a floppy into RAM |
| 322 | during the initial install of Linux. | 323 | during the initial install of Linux. |
| 323 | 324 | ||
| 324 | Note that the kernel command line option "ramdisk=XX" is now | 325 | Note that the kernel command line option "ramdisk=XX" is now obsolete. |
| 325 | obsolete. For details, read <file:Documentation/ramdisk.txt>. | 326 | For details, read <file:Documentation/blockdev/ramdisk.txt>. |
| 326 | 327 | ||
| 327 | To compile this driver as a module, choose M here: the | 328 | To compile this driver as a module, choose M here: the |
| 328 | module will be called rd. | 329 | module will be called rd. |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 14db747a636e..cf29cc4e6ab7 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
| @@ -4124,7 +4124,7 @@ static int __init floppy_setup(char *str) | |||
| 4124 | printk("\n"); | 4124 | printk("\n"); |
| 4125 | } else | 4125 | } else |
| 4126 | DPRINT("botched floppy option\n"); | 4126 | DPRINT("botched floppy option\n"); |
| 4127 | DPRINT("Read Documentation/floppy.txt\n"); | 4127 | DPRINT("Read Documentation/blockdev/floppy.txt\n"); |
| 4128 | return 0; | 4128 | return 0; |
| 4129 | } | 4129 | } |
| 4130 | 4130 | ||
diff --git a/drivers/block/ub.c b/drivers/block/ub.c index fccac18d3111..048d71d244d7 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c | |||
| @@ -1546,8 +1546,6 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) | |||
| 1546 | 1546 | ||
| 1547 | /* | 1547 | /* |
| 1548 | * Reset management | 1548 | * Reset management |
| 1549 | * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing. | ||
| 1550 | * XXX Make usb_sync_reset asynchronous. | ||
| 1551 | */ | 1549 | */ |
| 1552 | 1550 | ||
| 1553 | static void ub_reset_enter(struct ub_dev *sc, int try) | 1551 | static void ub_reset_enter(struct ub_dev *sc, int try) |
| @@ -1633,6 +1631,22 @@ static void ub_reset_task(struct work_struct *work) | |||
| 1633 | } | 1631 | } |
| 1634 | 1632 | ||
| 1635 | /* | 1633 | /* |
| 1634 | * XXX Reset brackets are too much hassle to implement, so just stub them | ||
| 1635 | * in order to prevent forced unbinding (which deadlocks solid when our | ||
| 1636 | * ->disconnect method waits for the reset to complete and this kills keventd). | ||
| 1637 | * | ||
| 1638 | * XXX Tell Alan to move usb_unlock_device inside of usb_reset_device, | ||
| 1639 | * or else the post_reset is invoked, and restats I/O on a locked device. | ||
| 1640 | */ | ||
| 1641 | static int ub_pre_reset(struct usb_interface *iface) { | ||
| 1642 | return 0; | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | static int ub_post_reset(struct usb_interface *iface) { | ||
| 1646 | return 0; | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | /* | ||
| 1636 | * This is called from a process context. | 1650 | * This is called from a process context. |
| 1637 | */ | 1651 | */ |
| 1638 | static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun) | 1652 | static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun) |
| @@ -2446,6 +2460,8 @@ static struct usb_driver ub_driver = { | |||
| 2446 | .probe = ub_probe, | 2460 | .probe = ub_probe, |
| 2447 | .disconnect = ub_disconnect, | 2461 | .disconnect = ub_disconnect, |
| 2448 | .id_table = ub_usb_ids, | 2462 | .id_table = ub_usb_ids, |
| 2463 | .pre_reset = ub_pre_reset, | ||
| 2464 | .post_reset = ub_post_reset, | ||
| 2449 | }; | 2465 | }; |
| 2450 | 2466 | ||
| 2451 | static int __init ub_init(void) | 2467 | static int __init ub_init(void) |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 43b35d0369d6..43d6ba83a191 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -124,7 +124,7 @@ config COMPUTONE | |||
| 124 | which give you many serial ports. You would need something like this | 124 | which give you many serial ports. You would need something like this |
| 125 | to connect more than two modems to your Linux box, for instance in | 125 | to connect more than two modems to your Linux box, for instance in |
| 126 | order to become a dial-in server. If you have a card like that, say | 126 | order to become a dial-in server. If you have a card like that, say |
| 127 | Y here and read <file:Documentation/computone.txt>. | 127 | Y here and read <file:Documentation/serial/computone.txt>. |
| 128 | 128 | ||
| 129 | To compile this driver as module, choose M here: the | 129 | To compile this driver as module, choose M here: the |
| 130 | module will be called ip2. | 130 | module will be called ip2. |
| @@ -136,7 +136,7 @@ config ROCKETPORT | |||
| 136 | This driver supports Comtrol RocketPort and RocketModem PCI boards. | 136 | This driver supports Comtrol RocketPort and RocketModem PCI boards. |
| 137 | These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or | 137 | These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or |
| 138 | modems. For information about the RocketPort/RocketModem boards | 138 | modems. For information about the RocketPort/RocketModem boards |
| 139 | and this driver read <file:Documentation/rocket.txt>. | 139 | and this driver read <file:Documentation/serial/rocket.txt>. |
| 140 | 140 | ||
| 141 | To compile this driver as a module, choose M here: the | 141 | To compile this driver as a module, choose M here: the |
| 142 | module will be called rocket. | 142 | module will be called rocket. |
| @@ -154,7 +154,7 @@ config CYCLADES | |||
| 154 | your Linux box, for instance in order to become a dial-in server. | 154 | your Linux box, for instance in order to become a dial-in server. |
| 155 | 155 | ||
| 156 | For information about the Cyclades-Z card, read | 156 | For information about the Cyclades-Z card, read |
| 157 | <file:Documentation/README.cycladesZ>. | 157 | <file:Documentation/serial/README.cycladesZ>. |
| 158 | 158 | ||
| 159 | To compile this driver as a module, choose M here: the | 159 | To compile this driver as a module, choose M here: the |
| 160 | module will be called cyclades. | 160 | module will be called cyclades. |
| @@ -183,7 +183,7 @@ config DIGIEPCA | |||
| 183 | box, for instance in order to become a dial-in server. This driver | 183 | box, for instance in order to become a dial-in server. This driver |
| 184 | supports the original PC (ISA) boards as well as PCI, and EISA. If | 184 | supports the original PC (ISA) boards as well as PCI, and EISA. If |
| 185 | you have a card like this, say Y here and read the file | 185 | you have a card like this, say Y here and read the file |
| 186 | <file:Documentation/digiepca.txt>. | 186 | <file:Documentation/serial/digiepca.txt>. |
| 187 | 187 | ||
| 188 | To compile this driver as a module, choose M here: the | 188 | To compile this driver as a module, choose M here: the |
| 189 | module will be called epca. | 189 | module will be called epca. |
| @@ -289,7 +289,7 @@ config RISCOM8 | |||
| 289 | which gives you many serial ports. You would need something like | 289 | which gives you many serial ports. You would need something like |
| 290 | this to connect more than two modems to your Linux box, for instance | 290 | this to connect more than two modems to your Linux box, for instance |
| 291 | in order to become a dial-in server. If you have a card like that, | 291 | in order to become a dial-in server. If you have a card like that, |
| 292 | say Y here and read the file <file:Documentation/riscom8.txt>. | 292 | say Y here and read the file <file:Documentation/serial/riscom8.txt>. |
| 293 | 293 | ||
| 294 | Also it's possible to say M here and compile this driver as kernel | 294 | Also it's possible to say M here and compile this driver as kernel |
| 295 | loadable module; the module will be called riscom8. | 295 | loadable module; the module will be called riscom8. |
| @@ -304,8 +304,8 @@ config SPECIALIX | |||
| 304 | your Linux box, for instance in order to become a dial-in server. | 304 | your Linux box, for instance in order to become a dial-in server. |
| 305 | 305 | ||
| 306 | If you have a card like that, say Y here and read the file | 306 | If you have a card like that, say Y here and read the file |
| 307 | <file:Documentation/specialix.txt>. Also it's possible to say M here | 307 | <file:Documentation/serial/specialix.txt>. Also it's possible to say |
| 308 | and compile this driver as kernel loadable module which will be | 308 | M here and compile this driver as kernel loadable module which will be |
| 309 | called specialix. | 309 | called specialix. |
| 310 | 310 | ||
| 311 | config SX | 311 | config SX |
| @@ -313,7 +313,7 @@ config SX | |||
| 313 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) | 313 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) |
| 314 | help | 314 | help |
| 315 | This is a driver for the SX and SI multiport serial cards. | 315 | This is a driver for the SX and SI multiport serial cards. |
| 316 | Please read the file <file:Documentation/sx.txt> for details. | 316 | Please read the file <file:Documentation/serial/sx.txt> for details. |
| 317 | 317 | ||
| 318 | This driver can only be built as a module ( = code which can be | 318 | This driver can only be built as a module ( = code which can be |
| 319 | inserted in and removed from the running kernel whenever you want). | 319 | inserted in and removed from the running kernel whenever you want). |
| @@ -344,8 +344,8 @@ config STALDRV | |||
| 344 | like this to connect more than two modems to your Linux box, for | 344 | like this to connect more than two modems to your Linux box, for |
| 345 | instance in order to become a dial-in server. If you say Y here, | 345 | instance in order to become a dial-in server. If you say Y here, |
| 346 | you will be asked for your specific card model in the next | 346 | you will be asked for your specific card model in the next |
| 347 | questions. Make sure to read <file:Documentation/stallion.txt> in | 347 | questions. Make sure to read <file:Documentation/serial/stallion.txt> |
| 348 | this case. If you have never heard about all this, it's safe to | 348 | in this case. If you have never heard about all this, it's safe to |
| 349 | say N. | 349 | say N. |
| 350 | 350 | ||
| 351 | config STALLION | 351 | config STALLION |
| @@ -354,7 +354,7 @@ config STALLION | |||
| 354 | help | 354 | help |
| 355 | If you have an EasyIO or EasyConnection 8/32 multiport Stallion | 355 | If you have an EasyIO or EasyConnection 8/32 multiport Stallion |
| 356 | card, then this is for you; say Y. Make sure to read | 356 | card, then this is for you; say Y. Make sure to read |
| 357 | <file:Documentation/stallion.txt>. | 357 | <file:Documentation/serial/stallion.txt>. |
| 358 | 358 | ||
| 359 | To compile this driver as a module, choose M here: the | 359 | To compile this driver as a module, choose M here: the |
| 360 | module will be called stallion. | 360 | module will be called stallion. |
| @@ -365,7 +365,7 @@ config ISTALLION | |||
| 365 | help | 365 | help |
| 366 | If you have an EasyConnection 8/64, ONboard, Brumby or Stallion | 366 | If you have an EasyConnection 8/64, ONboard, Brumby or Stallion |
| 367 | serial multiport card, say Y here. Make sure to read | 367 | serial multiport card, say Y here. Make sure to read |
| 368 | <file:Documentation/stallion.txt>. | 368 | <file:Documentation/serial/stallion.txt>. |
| 369 | 369 | ||
| 370 | To compile this driver as a module, choose M here: the | 370 | To compile this driver as a module, choose M here: the |
| 371 | module will be called istallion. | 371 | module will be called istallion. |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 8a59aaa21be5..7a88dfd4427b 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
| @@ -422,9 +422,11 @@ struct ipmi_smi { | |||
| 422 | /** | 422 | /** |
| 423 | * The driver model view of the IPMI messaging driver. | 423 | * The driver model view of the IPMI messaging driver. |
| 424 | */ | 424 | */ |
| 425 | static struct device_driver ipmidriver = { | 425 | static struct platform_driver ipmidriver = { |
| 426 | .name = "ipmi", | 426 | .driver = { |
| 427 | .bus = &platform_bus_type | 427 | .name = "ipmi", |
| 428 | .bus = &platform_bus_type | ||
| 429 | } | ||
| 428 | }; | 430 | }; |
| 429 | static DEFINE_MUTEX(ipmidriver_mutex); | 431 | static DEFINE_MUTEX(ipmidriver_mutex); |
| 430 | 432 | ||
| @@ -2384,9 +2386,9 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
| 2384 | * representing the interfaced BMC already | 2386 | * representing the interfaced BMC already |
| 2385 | */ | 2387 | */ |
| 2386 | if (bmc->guid_set) | 2388 | if (bmc->guid_set) |
| 2387 | old_bmc = ipmi_find_bmc_guid(&ipmidriver, bmc->guid); | 2389 | old_bmc = ipmi_find_bmc_guid(&ipmidriver.driver, bmc->guid); |
| 2388 | else | 2390 | else |
| 2389 | old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver, | 2391 | old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver.driver, |
| 2390 | bmc->id.product_id, | 2392 | bmc->id.product_id, |
| 2391 | bmc->id.device_id); | 2393 | bmc->id.device_id); |
| 2392 | 2394 | ||
| @@ -2416,7 +2418,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
| 2416 | snprintf(name, sizeof(name), | 2418 | snprintf(name, sizeof(name), |
| 2417 | "ipmi_bmc.%4.4x", bmc->id.product_id); | 2419 | "ipmi_bmc.%4.4x", bmc->id.product_id); |
| 2418 | 2420 | ||
| 2419 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver, | 2421 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver.driver, |
| 2420 | bmc->id.product_id, | 2422 | bmc->id.product_id, |
| 2421 | bmc->id.device_id)) { | 2423 | bmc->id.device_id)) { |
| 2422 | if (!warn_printed) { | 2424 | if (!warn_printed) { |
| @@ -2446,7 +2448,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
| 2446 | " Unable to allocate platform device\n"); | 2448 | " Unable to allocate platform device\n"); |
| 2447 | return -ENOMEM; | 2449 | return -ENOMEM; |
| 2448 | } | 2450 | } |
| 2449 | bmc->dev->dev.driver = &ipmidriver; | 2451 | bmc->dev->dev.driver = &ipmidriver.driver; |
| 2450 | dev_set_drvdata(&bmc->dev->dev, bmc); | 2452 | dev_set_drvdata(&bmc->dev->dev, bmc); |
| 2451 | kref_init(&bmc->refcount); | 2453 | kref_init(&bmc->refcount); |
| 2452 | 2454 | ||
| @@ -4247,7 +4249,7 @@ static int ipmi_init_msghandler(void) | |||
| 4247 | if (initialized) | 4249 | if (initialized) |
| 4248 | return 0; | 4250 | return 0; |
| 4249 | 4251 | ||
| 4250 | rv = driver_register(&ipmidriver); | 4252 | rv = driver_register(&ipmidriver.driver); |
| 4251 | if (rv) { | 4253 | if (rv) { |
| 4252 | printk(KERN_ERR PFX "Could not register IPMI driver\n"); | 4254 | printk(KERN_ERR PFX "Could not register IPMI driver\n"); |
| 4253 | return rv; | 4255 | return rv; |
| @@ -4308,7 +4310,7 @@ static __exit void cleanup_ipmi(void) | |||
| 4308 | remove_proc_entry(proc_ipmi_root->name, NULL); | 4310 | remove_proc_entry(proc_ipmi_root->name, NULL); |
| 4309 | #endif /* CONFIG_PROC_FS */ | 4311 | #endif /* CONFIG_PROC_FS */ |
| 4310 | 4312 | ||
| 4311 | driver_unregister(&ipmidriver); | 4313 | driver_unregister(&ipmidriver.driver); |
| 4312 | 4314 | ||
| 4313 | initialized = 0; | 4315 | initialized = 0; |
| 4314 | 4316 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 3123bf57ad91..3000135f2ead 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
| @@ -114,9 +114,11 @@ static char *si_to_str[] = { "kcs", "smic", "bt" }; | |||
| 114 | 114 | ||
| 115 | #define DEVICE_NAME "ipmi_si" | 115 | #define DEVICE_NAME "ipmi_si" |
| 116 | 116 | ||
| 117 | static struct device_driver ipmi_driver = { | 117 | static struct platform_driver ipmi_driver = { |
| 118 | .name = DEVICE_NAME, | 118 | .driver = { |
| 119 | .bus = &platform_bus_type | 119 | .name = DEVICE_NAME, |
| 120 | .bus = &platform_bus_type | ||
| 121 | } | ||
| 120 | }; | 122 | }; |
| 121 | 123 | ||
| 122 | 124 | ||
| @@ -2868,7 +2870,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
| 2868 | goto out_err; | 2870 | goto out_err; |
| 2869 | } | 2871 | } |
| 2870 | new_smi->dev = &new_smi->pdev->dev; | 2872 | new_smi->dev = &new_smi->pdev->dev; |
| 2871 | new_smi->dev->driver = &ipmi_driver; | 2873 | new_smi->dev->driver = &ipmi_driver.driver; |
| 2872 | 2874 | ||
| 2873 | rv = platform_device_add(new_smi->pdev); | 2875 | rv = platform_device_add(new_smi->pdev); |
| 2874 | if (rv) { | 2876 | if (rv) { |
| @@ -2983,7 +2985,7 @@ static __devinit int init_ipmi_si(void) | |||
| 2983 | initialized = 1; | 2985 | initialized = 1; |
| 2984 | 2986 | ||
| 2985 | /* Register the device drivers. */ | 2987 | /* Register the device drivers. */ |
| 2986 | rv = driver_register(&ipmi_driver); | 2988 | rv = driver_register(&ipmi_driver.driver); |
| 2987 | if (rv) { | 2989 | if (rv) { |
| 2988 | printk(KERN_ERR | 2990 | printk(KERN_ERR |
| 2989 | "init_ipmi_si: Unable to register driver: %d\n", | 2991 | "init_ipmi_si: Unable to register driver: %d\n", |
| @@ -3052,7 +3054,7 @@ static __devinit int init_ipmi_si(void) | |||
| 3052 | #ifdef CONFIG_PPC_OF | 3054 | #ifdef CONFIG_PPC_OF |
| 3053 | of_unregister_platform_driver(&ipmi_of_platform_driver); | 3055 | of_unregister_platform_driver(&ipmi_of_platform_driver); |
| 3054 | #endif | 3056 | #endif |
| 3055 | driver_unregister(&ipmi_driver); | 3057 | driver_unregister(&ipmi_driver.driver); |
| 3056 | printk(KERN_WARNING | 3058 | printk(KERN_WARNING |
| 3057 | "ipmi_si: Unable to find any System Interface(s)\n"); | 3059 | "ipmi_si: Unable to find any System Interface(s)\n"); |
| 3058 | return -ENODEV; | 3060 | return -ENODEV; |
| @@ -3151,7 +3153,7 @@ static __exit void cleanup_ipmi_si(void) | |||
| 3151 | cleanup_one_si(e); | 3153 | cleanup_one_si(e); |
| 3152 | mutex_unlock(&smi_infos_lock); | 3154 | mutex_unlock(&smi_infos_lock); |
| 3153 | 3155 | ||
| 3154 | driver_unregister(&ipmi_driver); | 3156 | driver_unregister(&ipmi_driver.driver); |
| 3155 | } | 3157 | } |
| 3156 | module_exit(cleanup_ipmi_si); | 3158 | module_exit(cleanup_ipmi_si); |
| 3157 | 3159 | ||
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 7d30ee1d3fca..04e4549299ba 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
| @@ -7,12 +7,14 @@ | |||
| 7 | * Original driver code supplied by Multi-Tech | 7 | * Original driver code supplied by Multi-Tech |
| 8 | * | 8 | * |
| 9 | * Changes | 9 | * Changes |
| 10 | * 1/9/98 alan@redhat.com Merge to 2.0.x kernel tree | 10 | * 1/9/98 alan@lxorguk.ukuu.org.uk |
| 11 | * Merge to 2.0.x kernel tree | ||
| 11 | * Obtain and use official major/minors | 12 | * Obtain and use official major/minors |
| 12 | * Loader switched to a misc device | 13 | * Loader switched to a misc device |
| 13 | * (fixed range check bug as a side effect) | 14 | * (fixed range check bug as a side effect) |
| 14 | * Printk clean up | 15 | * Printk clean up |
| 15 | * 9/12/98 alan@redhat.com Rough port to 2.1.x | 16 | * 9/12/98 alan@lxorguk.ukuu.org.uk |
| 17 | * Rough port to 2.1.x | ||
| 16 | * | 18 | * |
| 17 | * 10/6/99 sameer Merged the ISA and PCI drivers to | 19 | * 10/6/99 sameer Merged the ISA and PCI drivers to |
| 18 | * a new unified driver. | 20 | * a new unified driver. |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 8beef50f95a0..047766915411 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
| @@ -14,7 +14,8 @@ | |||
| 14 | * (at your option) any later version. | 14 | * (at your option) any later version. |
| 15 | * | 15 | * |
| 16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox | 16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox |
| 17 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. | 17 | * <alan@lxorguk.ukuu.org.uk>. The original 1.8 code is available on |
| 18 | * www.moxa.com. | ||
| 18 | * - Fixed x86_64 cleanness | 19 | * - Fixed x86_64 cleanness |
| 19 | */ | 20 | */ |
| 20 | 21 | ||
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 2457b07dabd6..f4374437a033 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
| @@ -523,7 +523,7 @@ static int acpi_driver_registered; | |||
| 523 | 523 | ||
| 524 | static int sonypi_ec_write(u8 addr, u8 value) | 524 | static int sonypi_ec_write(u8 addr, u8 value) |
| 525 | { | 525 | { |
| 526 | #ifdef CONFIG_ACPI_EC | 526 | #ifdef CONFIG_ACPI |
| 527 | if (SONYPI_ACPI_ACTIVE) | 527 | if (SONYPI_ACPI_ACTIVE) |
| 528 | return ec_write(addr, value); | 528 | return ec_write(addr, value); |
| 529 | #endif | 529 | #endif |
| @@ -539,7 +539,7 @@ static int sonypi_ec_write(u8 addr, u8 value) | |||
| 539 | 539 | ||
| 540 | static int sonypi_ec_read(u8 addr, u8 *value) | 540 | static int sonypi_ec_read(u8 addr, u8 *value) |
| 541 | { | 541 | { |
| 542 | #ifdef CONFIG_ACPI_EC | 542 | #ifdef CONFIG_ACPI |
| 543 | if (SONYPI_ACPI_ACTIVE) | 543 | if (SONYPI_ACPI_ACTIVE) |
| 544 | return ec_read(addr, value); | 544 | return ec_read(addr, value); |
| 545 | #endif | 545 | #endif |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 242fd46fda22..a16b94f12eb2 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
| @@ -72,7 +72,7 @@ | |||
| 72 | /* | 72 | /* |
| 73 | * There is a bunch of documentation about the card, jumpers, config | 73 | * There is a bunch of documentation about the card, jumpers, config |
| 74 | * settings, restrictions, cables, device names and numbers in | 74 | * settings, restrictions, cables, device names and numbers in |
| 75 | * Documentation/specialix.txt | 75 | * Documentation/serial/specialix.txt |
| 76 | */ | 76 | */ |
| 77 | 77 | ||
| 78 | #include <linux/module.h> | 78 | #include <linux/module.h> |
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index ec249d2db633..d883e1b8bb8c 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c | |||
| @@ -270,6 +270,6 @@ static void __exit dca_exit(void) | |||
| 270 | dca_sysfs_exit(); | 270 | dca_sysfs_exit(); |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | module_init(dca_init); | 273 | subsys_initcall(dca_init); |
| 274 | module_exit(dca_exit); | 274 | module_exit(dca_exit); |
| 275 | 275 | ||
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index dc003a3a787d..5317e08221ec 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
| @@ -399,8 +399,8 @@ int dma_async_device_register(struct dma_device *device) | |||
| 399 | chan->chan_id = chancnt++; | 399 | chan->chan_id = chancnt++; |
| 400 | chan->dev.class = &dma_devclass; | 400 | chan->dev.class = &dma_devclass; |
| 401 | chan->dev.parent = device->dev; | 401 | chan->dev.parent = device->dev; |
| 402 | snprintf(chan->dev.bus_id, BUS_ID_SIZE, "dma%dchan%d", | 402 | dev_set_name(&chan->dev, "dma%dchan%d", |
| 403 | device->dev_id, chan->chan_id); | 403 | device->dev_id, chan->chan_id); |
| 404 | 404 | ||
| 405 | rc = device_register(&chan->dev); | 405 | rc = device_register(&chan->dev); |
| 406 | if (rc) { | 406 | if (rc) { |
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index d1e381e35a9e..ed9636bfb54a 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c | |||
| @@ -20,11 +20,11 @@ static unsigned int test_buf_size = 16384; | |||
| 20 | module_param(test_buf_size, uint, S_IRUGO); | 20 | module_param(test_buf_size, uint, S_IRUGO); |
| 21 | MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); | 21 | MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); |
| 22 | 22 | ||
| 23 | static char test_channel[BUS_ID_SIZE]; | 23 | static char test_channel[20]; |
| 24 | module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); | 24 | module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); |
| 25 | MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); | 25 | MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); |
| 26 | 26 | ||
| 27 | static char test_device[BUS_ID_SIZE]; | 27 | static char test_device[20]; |
| 28 | module_param_string(device, test_device, sizeof(test_device), S_IRUGO); | 28 | module_param_string(device, test_device, sizeof(test_device), S_IRUGO); |
| 29 | MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); | 29 | MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); |
| 30 | 30 | ||
| @@ -80,14 +80,14 @@ static bool dmatest_match_channel(struct dma_chan *chan) | |||
| 80 | { | 80 | { |
| 81 | if (test_channel[0] == '\0') | 81 | if (test_channel[0] == '\0') |
| 82 | return true; | 82 | return true; |
| 83 | return strcmp(chan->dev.bus_id, test_channel) == 0; | 83 | return strcmp(dev_name(&chan->dev), test_channel) == 0; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static bool dmatest_match_device(struct dma_device *device) | 86 | static bool dmatest_match_device(struct dma_device *device) |
| 87 | { | 87 | { |
| 88 | if (test_device[0] == '\0') | 88 | if (test_device[0] == '\0') |
| 89 | return true; | 89 | return true; |
| 90 | return strcmp(device->dev->bus_id, test_device) == 0; | 90 | return strcmp(dev_name(device->dev), test_device) == 0; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | static unsigned long dmatest_random(void) | 93 | static unsigned long dmatest_random(void) |
| @@ -332,7 +332,7 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) | |||
| 332 | 332 | ||
| 333 | dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); | 333 | dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); |
| 334 | if (!dtc) { | 334 | if (!dtc) { |
| 335 | pr_warning("dmatest: No memory for %s\n", chan->dev.bus_id); | 335 | pr_warning("dmatest: No memory for %s\n", dev_name(&chan->dev)); |
| 336 | return DMA_NAK; | 336 | return DMA_NAK; |
| 337 | } | 337 | } |
| 338 | 338 | ||
| @@ -343,16 +343,16 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) | |||
| 343 | thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); | 343 | thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); |
| 344 | if (!thread) { | 344 | if (!thread) { |
| 345 | pr_warning("dmatest: No memory for %s-test%u\n", | 345 | pr_warning("dmatest: No memory for %s-test%u\n", |
| 346 | chan->dev.bus_id, i); | 346 | dev_name(&chan->dev), i); |
| 347 | break; | 347 | break; |
| 348 | } | 348 | } |
| 349 | thread->chan = dtc->chan; | 349 | thread->chan = dtc->chan; |
| 350 | smp_wmb(); | 350 | smp_wmb(); |
| 351 | thread->task = kthread_run(dmatest_func, thread, "%s-test%u", | 351 | thread->task = kthread_run(dmatest_func, thread, "%s-test%u", |
| 352 | chan->dev.bus_id, i); | 352 | dev_name(&chan->dev), i); |
| 353 | if (IS_ERR(thread->task)) { | 353 | if (IS_ERR(thread->task)) { |
| 354 | pr_warning("dmatest: Failed to run thread %s-test%u\n", | 354 | pr_warning("dmatest: Failed to run thread %s-test%u\n", |
| 355 | chan->dev.bus_id, i); | 355 | dev_name(&chan->dev), i); |
| 356 | kfree(thread); | 356 | kfree(thread); |
| 357 | break; | 357 | break; |
| 358 | } | 358 | } |
| @@ -362,7 +362,7 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) | |||
| 362 | list_add_tail(&thread->node, &dtc->threads); | 362 | list_add_tail(&thread->node, &dtc->threads); |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | pr_info("dmatest: Started %u threads using %s\n", i, chan->dev.bus_id); | 365 | pr_info("dmatest: Started %u threads using %s\n", i, dev_name(&chan->dev)); |
| 366 | 366 | ||
| 367 | list_add_tail(&dtc->node, &dmatest_channels); | 367 | list_add_tail(&dtc->node, &dmatest_channels); |
| 368 | nr_channels++; | 368 | nr_channels++; |
| @@ -379,7 +379,7 @@ static enum dma_state_client dmatest_remove_channel(struct dma_chan *chan) | |||
| 379 | list_del(&dtc->node); | 379 | list_del(&dtc->node); |
| 380 | dmatest_cleanup_channel(dtc); | 380 | dmatest_cleanup_channel(dtc); |
| 381 | pr_debug("dmatest: lost channel %s\n", | 381 | pr_debug("dmatest: lost channel %s\n", |
| 382 | chan->dev.bus_id); | 382 | dev_name(&chan->dev)); |
| 383 | return DMA_ACK; | 383 | return DMA_ACK; |
| 384 | } | 384 | } |
| 385 | } | 385 | } |
| @@ -418,7 +418,7 @@ dmatest_event(struct dma_client *client, struct dma_chan *chan, | |||
| 418 | 418 | ||
| 419 | default: | 419 | default: |
| 420 | pr_info("dmatest: Unhandled event %u (%s)\n", | 420 | pr_info("dmatest: Unhandled event %u (%s)\n", |
| 421 | state, chan->dev.bus_id); | 421 | state, dev_name(&chan->dev)); |
| 422 | break; | 422 | break; |
| 423 | } | 423 | } |
| 424 | 424 | ||
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index b0438c4f0c30..ecd743f7cc61 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c | |||
| @@ -525,7 +525,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx) | |||
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; | 527 | hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; |
| 528 | if (new->async_tx.callback) { | 528 | if (first->async_tx.callback) { |
| 529 | hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; | 529 | hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; |
| 530 | if (first != new) { | 530 | if (first != new) { |
| 531 | /* move callback into to last desc */ | 531 | /* move callback into to last desc */ |
| @@ -617,7 +617,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx) | |||
| 617 | } | 617 | } |
| 618 | 618 | ||
| 619 | hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_CP_STS; | 619 | hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_CP_STS; |
| 620 | if (new->async_tx.callback) { | 620 | if (first->async_tx.callback) { |
| 621 | hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; | 621 | hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; |
| 622 | if (first != new) { | 622 | if (first != new) { |
| 623 | /* move callback into to last desc */ | 623 | /* move callback into to last desc */ |
| @@ -807,6 +807,12 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) | |||
| 807 | struct ioat_desc_sw *desc, *_desc; | 807 | struct ioat_desc_sw *desc, *_desc; |
| 808 | int in_use_descs = 0; | 808 | int in_use_descs = 0; |
| 809 | 809 | ||
| 810 | /* Before freeing channel resources first check | ||
| 811 | * if they have been previously allocated for this channel. | ||
| 812 | */ | ||
| 813 | if (ioat_chan->desccount == 0) | ||
| 814 | return; | ||
| 815 | |||
| 810 | tasklet_disable(&ioat_chan->cleanup_task); | 816 | tasklet_disable(&ioat_chan->cleanup_task); |
| 811 | ioat_dma_memcpy_cleanup(ioat_chan); | 817 | ioat_dma_memcpy_cleanup(ioat_chan); |
| 812 | 818 | ||
| @@ -869,6 +875,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) | |||
| 869 | ioat_chan->last_completion = ioat_chan->completion_addr = 0; | 875 | ioat_chan->last_completion = ioat_chan->completion_addr = 0; |
| 870 | ioat_chan->pending = 0; | 876 | ioat_chan->pending = 0; |
| 871 | ioat_chan->dmacount = 0; | 877 | ioat_chan->dmacount = 0; |
| 878 | ioat_chan->desccount = 0; | ||
| 872 | ioat_chan->watchdog_completion = 0; | 879 | ioat_chan->watchdog_completion = 0; |
| 873 | ioat_chan->last_compl_desc_addr_hw = 0; | 880 | ioat_chan->last_compl_desc_addr_hw = 0; |
| 874 | ioat_chan->watchdog_tcp_cookie = | 881 | ioat_chan->watchdog_tcp_cookie = |
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index 71fba82462cb..c7a9306d951d 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
| @@ -411,6 +411,7 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx) | |||
| 411 | int slot_cnt; | 411 | int slot_cnt; |
| 412 | int slots_per_op; | 412 | int slots_per_op; |
| 413 | dma_cookie_t cookie; | 413 | dma_cookie_t cookie; |
| 414 | dma_addr_t next_dma; | ||
| 414 | 415 | ||
| 415 | grp_start = sw_desc->group_head; | 416 | grp_start = sw_desc->group_head; |
| 416 | slot_cnt = grp_start->slot_cnt; | 417 | slot_cnt = grp_start->slot_cnt; |
| @@ -425,12 +426,12 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx) | |||
| 425 | &old_chain_tail->chain_node); | 426 | &old_chain_tail->chain_node); |
| 426 | 427 | ||
| 427 | /* fix up the hardware chain */ | 428 | /* fix up the hardware chain */ |
| 428 | iop_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys); | 429 | next_dma = grp_start->async_tx.phys; |
| 430 | iop_desc_set_next_desc(old_chain_tail, next_dma); | ||
| 431 | BUG_ON(iop_desc_get_next_desc(old_chain_tail) != next_dma); /* flush */ | ||
| 429 | 432 | ||
| 430 | /* 1/ don't add pre-chained descriptors | 433 | /* check for pre-chained descriptors */ |
| 431 | * 2/ dummy read to flush next_desc write | 434 | iop_paranoia(iop_desc_get_next_desc(sw_desc)); |
| 432 | */ | ||
| 433 | BUG_ON(iop_desc_get_next_desc(sw_desc)); | ||
| 434 | 435 | ||
| 435 | /* increment the pending count by the number of slots | 436 | /* increment the pending count by the number of slots |
| 436 | * memcpy operations have a 1:1 (slot:operation) relation | 437 | * memcpy operations have a 1:1 (slot:operation) relation |
diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c index e763d723e4cf..9f6fe46a9b87 100644 --- a/drivers/dma/iovlock.c +++ b/drivers/dma/iovlock.c | |||
| @@ -55,7 +55,6 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) | |||
| 55 | int nr_iovecs = 0; | 55 | int nr_iovecs = 0; |
| 56 | int iovec_len_used = 0; | 56 | int iovec_len_used = 0; |
| 57 | int iovec_pages_used = 0; | 57 | int iovec_pages_used = 0; |
| 58 | long err; | ||
| 59 | 58 | ||
| 60 | /* don't pin down non-user-based iovecs */ | 59 | /* don't pin down non-user-based iovecs */ |
| 61 | if (segment_eq(get_fs(), KERNEL_DS)) | 60 | if (segment_eq(get_fs(), KERNEL_DS)) |
| @@ -72,23 +71,21 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) | |||
| 72 | local_list = kmalloc(sizeof(*local_list) | 71 | local_list = kmalloc(sizeof(*local_list) |
| 73 | + (nr_iovecs * sizeof (struct dma_page_list)) | 72 | + (nr_iovecs * sizeof (struct dma_page_list)) |
| 74 | + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL); | 73 | + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL); |
| 75 | if (!local_list) { | 74 | if (!local_list) |
| 76 | err = -ENOMEM; | ||
| 77 | goto out; | 75 | goto out; |
| 78 | } | ||
| 79 | 76 | ||
| 80 | /* list of pages starts right after the page list array */ | 77 | /* list of pages starts right after the page list array */ |
| 81 | pages = (struct page **) &local_list->page_list[nr_iovecs]; | 78 | pages = (struct page **) &local_list->page_list[nr_iovecs]; |
| 82 | 79 | ||
| 80 | local_list->nr_iovecs = 0; | ||
| 81 | |||
| 83 | for (i = 0; i < nr_iovecs; i++) { | 82 | for (i = 0; i < nr_iovecs; i++) { |
| 84 | struct dma_page_list *page_list = &local_list->page_list[i]; | 83 | struct dma_page_list *page_list = &local_list->page_list[i]; |
| 85 | 84 | ||
| 86 | len -= iov[i].iov_len; | 85 | len -= iov[i].iov_len; |
| 87 | 86 | ||
| 88 | if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) { | 87 | if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) |
| 89 | err = -EFAULT; | ||
| 90 | goto unpin; | 88 | goto unpin; |
| 91 | } | ||
| 92 | 89 | ||
| 93 | page_list->nr_pages = num_pages_spanned(&iov[i]); | 90 | page_list->nr_pages = num_pages_spanned(&iov[i]); |
| 94 | page_list->base_address = iov[i].iov_base; | 91 | page_list->base_address = iov[i].iov_base; |
| @@ -109,10 +106,8 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) | |||
| 109 | NULL); | 106 | NULL); |
| 110 | up_read(¤t->mm->mmap_sem); | 107 | up_read(¤t->mm->mmap_sem); |
| 111 | 108 | ||
| 112 | if (ret != page_list->nr_pages) { | 109 | if (ret != page_list->nr_pages) |
| 113 | err = -ENOMEM; | ||
| 114 | goto unpin; | 110 | goto unpin; |
| 115 | } | ||
| 116 | 111 | ||
| 117 | local_list->nr_iovecs = i + 1; | 112 | local_list->nr_iovecs = i + 1; |
| 118 | } | 113 | } |
| @@ -122,7 +117,7 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) | |||
| 122 | unpin: | 117 | unpin: |
| 123 | dma_unpin_iovec_pages(local_list); | 118 | dma_unpin_iovec_pages(local_list); |
| 124 | out: | 119 | out: |
| 125 | return ERR_PTR(err); | 120 | return NULL; |
| 126 | } | 121 | } |
| 127 | 122 | ||
| 128 | void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) | 123 | void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) |
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index f0d9b415db50..d335086f4a26 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c | |||
| @@ -1381,6 +1381,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) | |||
| 1381 | if (mci == NULL) | 1381 | if (mci == NULL) |
| 1382 | return -ENOMEM; | 1382 | return -ENOMEM; |
| 1383 | 1383 | ||
| 1384 | kobject_get(&mci->edac_mci_kobj); | ||
| 1384 | debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); | 1385 | debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); |
| 1385 | 1386 | ||
| 1386 | mci->dev = &pdev->dev; /* record ptr to the generic device */ | 1387 | mci->dev = &pdev->dev; /* record ptr to the generic device */ |
| @@ -1453,6 +1454,7 @@ fail1: | |||
| 1453 | i5000_put_devices(mci); | 1454 | i5000_put_devices(mci); |
| 1454 | 1455 | ||
| 1455 | fail0: | 1456 | fail0: |
| 1457 | kobject_put(&mci->edac_mci_kobj); | ||
| 1456 | edac_mc_free(mci); | 1458 | edac_mc_free(mci); |
| 1457 | return -ENODEV; | 1459 | return -ENODEV; |
| 1458 | } | 1460 | } |
| @@ -1498,7 +1500,7 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev) | |||
| 1498 | 1500 | ||
| 1499 | /* retrieve references to resources, and free those resources */ | 1501 | /* retrieve references to resources, and free those resources */ |
| 1500 | i5000_put_devices(mci); | 1502 | i5000_put_devices(mci); |
| 1501 | 1503 | kobject_put(&mci->edac_mci_kobj); | |
| 1502 | edac_mc_free(mci); | 1504 | edac_mc_free(mci); |
| 1503 | } | 1505 | } |
| 1504 | 1506 | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 7f2ee27fe76b..48f49d93d249 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -65,6 +65,14 @@ config GPIO_SYSFS | |||
| 65 | 65 | ||
| 66 | # put expanders in the right section, in alphabetical order | 66 | # put expanders in the right section, in alphabetical order |
| 67 | 67 | ||
| 68 | comment "Memory mapped GPIO expanders:" | ||
| 69 | |||
| 70 | config GPIO_XILINX | ||
| 71 | bool "Xilinx GPIO support" | ||
| 72 | depends on PPC_OF | ||
| 73 | help | ||
| 74 | Say yes here to support the Xilinx FPGA GPIO device | ||
| 75 | |||
| 68 | comment "I2C GPIO expanders:" | 76 | comment "I2C GPIO expanders:" |
| 69 | 77 | ||
| 70 | config GPIO_MAX732X | 78 | config GPIO_MAX732X |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 6aafdeb9ad03..49ac64e515e6 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -10,4 +10,5 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | |||
| 10 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 10 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
| 11 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 11 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
| 12 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 12 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
| 13 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o | ||
| 13 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o | 14 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o |
diff --git a/drivers/gpio/xilinx_gpio.c b/drivers/gpio/xilinx_gpio.c new file mode 100644 index 000000000000..3c1177abebd3 --- /dev/null +++ b/drivers/gpio/xilinx_gpio.c | |||
| @@ -0,0 +1,235 @@ | |||
| 1 | /* | ||
| 2 | * Xilinx gpio driver | ||
| 3 | * | ||
| 4 | * Copyright 2008 Xilinx, Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 | ||
| 8 | * as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * You should have received a copy of the GNU General Public License | ||
| 11 | * along with this program; if not, write to the Free Software | ||
| 12 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/errno.h> | ||
| 17 | #include <linux/of_device.h> | ||
| 18 | #include <linux/of_platform.h> | ||
| 19 | #include <linux/of_gpio.h> | ||
| 20 | #include <linux/io.h> | ||
| 21 | #include <linux/gpio.h> | ||
| 22 | |||
| 23 | /* Register Offset Definitions */ | ||
| 24 | #define XGPIO_DATA_OFFSET (0x0) /* Data register */ | ||
| 25 | #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ | ||
| 26 | |||
| 27 | struct xgpio_instance { | ||
| 28 | struct of_mm_gpio_chip mmchip; | ||
| 29 | u32 gpio_state; /* GPIO state shadow register */ | ||
| 30 | u32 gpio_dir; /* GPIO direction shadow register */ | ||
| 31 | spinlock_t gpio_lock; /* Lock used for synchronization */ | ||
| 32 | }; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * xgpio_get - Read the specified signal of the GPIO device. | ||
| 36 | * @gc: Pointer to gpio_chip device structure. | ||
| 37 | * @gpio: GPIO signal number. | ||
| 38 | * | ||
| 39 | * This function reads the specified signal of the GPIO device. It returns 0 if | ||
| 40 | * the signal clear, 1 if signal is set or negative value on error. | ||
| 41 | */ | ||
| 42 | static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 43 | { | ||
| 44 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 45 | |||
| 46 | return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1; | ||
| 47 | } | ||
| 48 | |||
| 49 | /** | ||
| 50 | * xgpio_set - Write the specified signal of the GPIO device. | ||
| 51 | * @gc: Pointer to gpio_chip device structure. | ||
| 52 | * @gpio: GPIO signal number. | ||
| 53 | * @val: Value to be written to specified signal. | ||
| 54 | * | ||
| 55 | * This function writes the specified value in to the specified signal of the | ||
| 56 | * GPIO device. | ||
| 57 | */ | ||
| 58 | static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 59 | { | ||
| 60 | unsigned long flags; | ||
| 61 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 62 | struct xgpio_instance *chip = | ||
| 63 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
| 64 | |||
| 65 | spin_lock_irqsave(&chip->gpio_lock, flags); | ||
| 66 | |||
| 67 | /* Write to GPIO signal and set its direction to output */ | ||
| 68 | if (val) | ||
| 69 | chip->gpio_state |= 1 << gpio; | ||
| 70 | else | ||
| 71 | chip->gpio_state &= ~(1 << gpio); | ||
| 72 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | ||
| 73 | |||
| 74 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | ||
| 75 | } | ||
| 76 | |||
| 77 | /** | ||
| 78 | * xgpio_dir_in - Set the direction of the specified GPIO signal as input. | ||
| 79 | * @gc: Pointer to gpio_chip device structure. | ||
| 80 | * @gpio: GPIO signal number. | ||
| 81 | * | ||
| 82 | * This function sets the direction of specified GPIO signal as input. | ||
| 83 | * It returns 0 if direction of GPIO signals is set as input otherwise it | ||
| 84 | * returns negative error value. | ||
| 85 | */ | ||
| 86 | static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
| 87 | { | ||
| 88 | unsigned long flags; | ||
| 89 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 90 | struct xgpio_instance *chip = | ||
| 91 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
| 92 | |||
| 93 | spin_lock_irqsave(&chip->gpio_lock, flags); | ||
| 94 | |||
| 95 | /* Set the GPIO bit in shadow register and set direction as input */ | ||
| 96 | chip->gpio_dir |= (1 << gpio); | ||
| 97 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | ||
| 98 | |||
| 99 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | ||
| 100 | |||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | /** | ||
| 105 | * xgpio_dir_out - Set the direction of the specified GPIO signal as output. | ||
| 106 | * @gc: Pointer to gpio_chip device structure. | ||
| 107 | * @gpio: GPIO signal number. | ||
| 108 | * @val: Value to be written to specified signal. | ||
| 109 | * | ||
| 110 | * This function sets the direction of specified GPIO signal as output. If all | ||
| 111 | * GPIO signals of GPIO chip is configured as input then it returns | ||
| 112 | * error otherwise it returns 0. | ||
| 113 | */ | ||
| 114 | static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 115 | { | ||
| 116 | unsigned long flags; | ||
| 117 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 118 | struct xgpio_instance *chip = | ||
| 119 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
| 120 | |||
| 121 | spin_lock_irqsave(&chip->gpio_lock, flags); | ||
| 122 | |||
| 123 | /* Write state of GPIO signal */ | ||
| 124 | if (val) | ||
| 125 | chip->gpio_state |= 1 << gpio; | ||
| 126 | else | ||
| 127 | chip->gpio_state &= ~(1 << gpio); | ||
| 128 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | ||
| 129 | |||
| 130 | /* Clear the GPIO bit in shadow register and set direction as output */ | ||
| 131 | chip->gpio_dir &= (~(1 << gpio)); | ||
| 132 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | ||
| 133 | |||
| 134 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | /** | ||
| 140 | * xgpio_save_regs - Set initial values of GPIO pins | ||
| 141 | * @mm_gc: pointer to memory mapped GPIO chip structure | ||
| 142 | */ | ||
| 143 | static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) | ||
| 144 | { | ||
| 145 | struct xgpio_instance *chip = | ||
| 146 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
| 147 | |||
| 148 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | ||
| 149 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | ||
| 150 | } | ||
| 151 | |||
| 152 | /** | ||
| 153 | * xgpio_of_probe - Probe method for the GPIO device. | ||
| 154 | * @np: pointer to device tree node | ||
| 155 | * | ||
| 156 | * This function probes the GPIO device in the device tree. It initializes the | ||
| 157 | * driver data structure. It returns 0, if the driver is bound to the GPIO | ||
| 158 | * device, or a negative value if there is an error. | ||
| 159 | */ | ||
| 160 | static int __devinit xgpio_of_probe(struct device_node *np) | ||
| 161 | { | ||
| 162 | struct xgpio_instance *chip; | ||
| 163 | struct of_gpio_chip *ofchip; | ||
| 164 | int status = 0; | ||
| 165 | const u32 *tree_info; | ||
| 166 | |||
| 167 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
| 168 | if (!chip) | ||
| 169 | return -ENOMEM; | ||
| 170 | ofchip = &chip->mmchip.of_gc; | ||
| 171 | |||
| 172 | /* Update GPIO state shadow register with default value */ | ||
| 173 | tree_info = of_get_property(np, "xlnx,dout-default", NULL); | ||
| 174 | if (tree_info) | ||
| 175 | chip->gpio_state = *tree_info; | ||
| 176 | |||
| 177 | /* Update GPIO direction shadow register with default value */ | ||
| 178 | chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */ | ||
| 179 | tree_info = of_get_property(np, "xlnx,tri-default", NULL); | ||
| 180 | if (tree_info) | ||
| 181 | chip->gpio_dir = *tree_info; | ||
| 182 | |||
| 183 | /* Check device node and parent device node for device width */ | ||
| 184 | ofchip->gc.ngpio = 32; /* By default assume full GPIO controller */ | ||
| 185 | tree_info = of_get_property(np, "xlnx,gpio-width", NULL); | ||
| 186 | if (!tree_info) | ||
| 187 | tree_info = of_get_property(np->parent, | ||
| 188 | "xlnx,gpio-width", NULL); | ||
| 189 | if (tree_info) | ||
| 190 | ofchip->gc.ngpio = *tree_info; | ||
| 191 | |||
| 192 | spin_lock_init(&chip->gpio_lock); | ||
| 193 | |||
| 194 | ofchip->gpio_cells = 2; | ||
| 195 | ofchip->gc.direction_input = xgpio_dir_in; | ||
| 196 | ofchip->gc.direction_output = xgpio_dir_out; | ||
| 197 | ofchip->gc.get = xgpio_get; | ||
| 198 | ofchip->gc.set = xgpio_set; | ||
| 199 | |||
| 200 | chip->mmchip.save_regs = xgpio_save_regs; | ||
| 201 | |||
| 202 | /* Call the OF gpio helper to setup and register the GPIO device */ | ||
| 203 | status = of_mm_gpiochip_add(np, &chip->mmchip); | ||
| 204 | if (status) { | ||
| 205 | kfree(chip); | ||
| 206 | pr_err("%s: error in probe function with status %d\n", | ||
| 207 | np->full_name, status); | ||
| 208 | return status; | ||
| 209 | } | ||
| 210 | pr_info("XGpio: %s: registered\n", np->full_name); | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static struct of_device_id xgpio_of_match[] __devinitdata = { | ||
| 215 | { .compatible = "xlnx,xps-gpio-1.00.a", }, | ||
| 216 | { /* end of list */ }, | ||
| 217 | }; | ||
| 218 | |||
| 219 | static int __init xgpio_init(void) | ||
| 220 | { | ||
| 221 | struct device_node *np; | ||
| 222 | |||
| 223 | for_each_matching_node(np, xgpio_of_match) | ||
| 224 | xgpio_of_probe(np); | ||
| 225 | |||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | /* Make sure we get initialized before anyone else tries to use us */ | ||
| 230 | subsys_initcall(xgpio_init); | ||
| 231 | /* No exit call at the moment as we cannot unregister of GPIO chips */ | ||
| 232 | |||
| 233 | MODULE_AUTHOR("Xilinx, Inc."); | ||
| 234 | MODULE_DESCRIPTION("Xilinx GPIO driver"); | ||
| 235 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 96f416afc3f6..3ab1e9cc4692 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
| @@ -266,11 +266,19 @@ int drm_init(struct drm_driver *driver) | |||
| 266 | for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { | 266 | for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { |
| 267 | pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; | 267 | pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; |
| 268 | 268 | ||
| 269 | /* Loop around setting up a DRM device for each PCI device | ||
| 270 | * matching our ID and device class. If we had the internal | ||
| 271 | * function that pci_get_subsys and pci_get_class used, we'd | ||
| 272 | * be able to just pass pid in instead of doing a two-stage | ||
| 273 | * thing. | ||
| 274 | */ | ||
| 269 | pdev = NULL; | 275 | pdev = NULL; |
| 270 | /* pass back in pdev to account for multiple identical cards */ | ||
| 271 | while ((pdev = | 276 | while ((pdev = |
| 272 | pci_get_subsys(pid->vendor, pid->device, pid->subvendor, | 277 | pci_get_subsys(pid->vendor, pid->device, pid->subvendor, |
| 273 | pid->subdevice, pdev)) != NULL) { | 278 | pid->subdevice, pdev)) != NULL) { |
| 279 | if ((pdev->class & pid->class_mask) != pid->class) | ||
| 280 | continue; | ||
| 281 | |||
| 274 | /* stealth mode requires a manual probe */ | 282 | /* stealth mode requires a manual probe */ |
| 275 | pci_dev_get(pdev); | 283 | pci_dev_get(pdev); |
| 276 | drm_get_dev(pdev, pid, driver); | 284 | drm_get_dev(pdev, pid, driver); |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 212a94f715b2..15c8dabc3e97 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -280,8 +280,6 @@ int drm_irq_uninstall(struct drm_device * dev) | |||
| 280 | 280 | ||
| 281 | drm_vblank_cleanup(dev); | 281 | drm_vblank_cleanup(dev); |
| 282 | 282 | ||
| 283 | dev->locked_tasklet_func = NULL; | ||
| 284 | |||
| 285 | return 0; | 283 | return 0; |
| 286 | } | 284 | } |
| 287 | EXPORT_SYMBOL(drm_irq_uninstall); | 285 | EXPORT_SYMBOL(drm_irq_uninstall); |
| @@ -699,81 +697,3 @@ void drm_handle_vblank(struct drm_device *dev, int crtc) | |||
| 699 | drm_vbl_send_signals(dev, crtc); | 697 | drm_vbl_send_signals(dev, crtc); |
| 700 | } | 698 | } |
| 701 | EXPORT_SYMBOL(drm_handle_vblank); | 699 | EXPORT_SYMBOL(drm_handle_vblank); |
| 702 | |||
| 703 | /** | ||
| 704 | * Tasklet wrapper function. | ||
| 705 | * | ||
| 706 | * \param data DRM device in disguise. | ||
| 707 | * | ||
| 708 | * Attempts to grab the HW lock and calls the driver callback on success. On | ||
| 709 | * failure, leave the lock marked as contended so the callback can be called | ||
| 710 | * from drm_unlock(). | ||
| 711 | */ | ||
| 712 | static void drm_locked_tasklet_func(unsigned long data) | ||
| 713 | { | ||
| 714 | struct drm_device *dev = (struct drm_device *)data; | ||
| 715 | unsigned long irqflags; | ||
| 716 | void (*tasklet_func)(struct drm_device *); | ||
| 717 | |||
| 718 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | ||
| 719 | tasklet_func = dev->locked_tasklet_func; | ||
| 720 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
| 721 | |||
| 722 | if (!tasklet_func || | ||
| 723 | !drm_lock_take(&dev->lock, | ||
| 724 | DRM_KERNEL_CONTEXT)) { | ||
| 725 | return; | ||
| 726 | } | ||
| 727 | |||
| 728 | dev->lock.lock_time = jiffies; | ||
| 729 | atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); | ||
| 730 | |||
| 731 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | ||
| 732 | tasklet_func = dev->locked_tasklet_func; | ||
| 733 | dev->locked_tasklet_func = NULL; | ||
| 734 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
| 735 | |||
| 736 | if (tasklet_func != NULL) | ||
| 737 | tasklet_func(dev); | ||
| 738 | |||
| 739 | drm_lock_free(&dev->lock, | ||
| 740 | DRM_KERNEL_CONTEXT); | ||
| 741 | } | ||
| 742 | |||
| 743 | /** | ||
| 744 | * Schedule a tasklet to call back a driver hook with the HW lock held. | ||
| 745 | * | ||
| 746 | * \param dev DRM device. | ||
| 747 | * \param func Driver callback. | ||
| 748 | * | ||
| 749 | * This is intended for triggering actions that require the HW lock from an | ||
| 750 | * interrupt handler. The lock will be grabbed ASAP after the interrupt handler | ||
| 751 | * completes. Note that the callback may be called from interrupt or process | ||
| 752 | * context, it must not make any assumptions about this. Also, the HW lock will | ||
| 753 | * be held with the kernel context or any client context. | ||
| 754 | */ | ||
| 755 | void drm_locked_tasklet(struct drm_device *dev, void (*func)(struct drm_device *)) | ||
| 756 | { | ||
| 757 | unsigned long irqflags; | ||
| 758 | static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0); | ||
| 759 | |||
| 760 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ) || | ||
| 761 | test_bit(TASKLET_STATE_SCHED, &drm_tasklet.state)) | ||
| 762 | return; | ||
| 763 | |||
| 764 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | ||
| 765 | |||
| 766 | if (dev->locked_tasklet_func) { | ||
| 767 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
| 768 | return; | ||
| 769 | } | ||
| 770 | |||
| 771 | dev->locked_tasklet_func = func; | ||
| 772 | |||
| 773 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
| 774 | |||
| 775 | drm_tasklet.data = (unsigned long)dev; | ||
| 776 | |||
| 777 | tasklet_hi_schedule(&drm_tasklet); | ||
| 778 | } | ||
| 779 | EXPORT_SYMBOL(drm_locked_tasklet); | ||
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 888159e03d26..1cfa72031f8f 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c | |||
| @@ -154,8 +154,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 154 | int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) | 154 | int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) |
| 155 | { | 155 | { |
| 156 | struct drm_lock *lock = data; | 156 | struct drm_lock *lock = data; |
| 157 | unsigned long irqflags; | ||
| 158 | void (*tasklet_func)(struct drm_device *); | ||
| 159 | 157 | ||
| 160 | if (lock->context == DRM_KERNEL_CONTEXT) { | 158 | if (lock->context == DRM_KERNEL_CONTEXT) { |
| 161 | DRM_ERROR("Process %d using kernel context %d\n", | 159 | DRM_ERROR("Process %d using kernel context %d\n", |
| @@ -163,13 +161,6 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 163 | return -EINVAL; | 161 | return -EINVAL; |
| 164 | } | 162 | } |
| 165 | 163 | ||
| 166 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | ||
| 167 | tasklet_func = dev->locked_tasklet_func; | ||
| 168 | dev->locked_tasklet_func = NULL; | ||
| 169 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
| 170 | if (tasklet_func != NULL) | ||
| 171 | tasklet_func(dev); | ||
| 172 | |||
| 173 | atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); | 164 | atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); |
| 174 | 165 | ||
| 175 | /* kernel_context_switch isn't used by any of the x86 drm | 166 | /* kernel_context_switch isn't used by any of the x86 drm |
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 141e33004a76..66c96ec66672 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
| @@ -92,7 +92,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, | |||
| 92 | 92 | ||
| 93 | spin_lock_init(&dev->count_lock); | 93 | spin_lock_init(&dev->count_lock); |
| 94 | spin_lock_init(&dev->drw_lock); | 94 | spin_lock_init(&dev->drw_lock); |
| 95 | spin_lock_init(&dev->tasklet_lock); | ||
| 96 | spin_lock_init(&dev->lock.spinlock); | 95 | spin_lock_init(&dev->lock.spinlock); |
| 97 | init_timer(&dev->timer); | 96 | init_timer(&dev->timer); |
| 98 | mutex_init(&dev->struct_mutex); | 97 | mutex_init(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 256e22963ae4..0d215e38606a 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -154,6 +154,9 @@ static int i915_dma_cleanup(struct drm_device * dev) | |||
| 154 | if (I915_NEED_GFX_HWS(dev)) | 154 | if (I915_NEED_GFX_HWS(dev)) |
| 155 | i915_free_hws(dev); | 155 | i915_free_hws(dev); |
| 156 | 156 | ||
| 157 | dev_priv->sarea = NULL; | ||
| 158 | dev_priv->sarea_priv = NULL; | ||
| 159 | |||
| 157 | return 0; | 160 | return 0; |
| 158 | } | 161 | } |
| 159 | 162 | ||
| @@ -442,7 +445,7 @@ static void i915_emit_breadcrumb(struct drm_device *dev) | |||
| 442 | 445 | ||
| 443 | BEGIN_LP_RING(4); | 446 | BEGIN_LP_RING(4); |
| 444 | OUT_RING(MI_STORE_DWORD_INDEX); | 447 | OUT_RING(MI_STORE_DWORD_INDEX); |
| 445 | OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT); | 448 | OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); |
| 446 | OUT_RING(dev_priv->counter); | 449 | OUT_RING(dev_priv->counter); |
| 447 | OUT_RING(0); | 450 | OUT_RING(0); |
| 448 | ADVANCE_LP_RING(); | 451 | ADVANCE_LP_RING(); |
| @@ -573,7 +576,7 @@ static int i915_dispatch_flip(struct drm_device * dev) | |||
| 573 | 576 | ||
| 574 | BEGIN_LP_RING(4); | 577 | BEGIN_LP_RING(4); |
| 575 | OUT_RING(MI_STORE_DWORD_INDEX); | 578 | OUT_RING(MI_STORE_DWORD_INDEX); |
| 576 | OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT); | 579 | OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); |
| 577 | OUT_RING(dev_priv->counter); | 580 | OUT_RING(dev_priv->counter); |
| 578 | OUT_RING(0); | 581 | OUT_RING(0); |
| 579 | ADVANCE_LP_RING(); | 582 | ADVANCE_LP_RING(); |
| @@ -608,7 +611,6 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, | |||
| 608 | struct drm_file *file_priv) | 611 | struct drm_file *file_priv) |
| 609 | { | 612 | { |
| 610 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 613 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 611 | u32 *hw_status = dev_priv->hw_status_page; | ||
| 612 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) | 614 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) |
| 613 | dev_priv->sarea_priv; | 615 | dev_priv->sarea_priv; |
| 614 | drm_i915_batchbuffer_t *batch = data; | 616 | drm_i915_batchbuffer_t *batch = data; |
| @@ -634,7 +636,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, | |||
| 634 | mutex_unlock(&dev->struct_mutex); | 636 | mutex_unlock(&dev->struct_mutex); |
| 635 | 637 | ||
| 636 | if (sarea_priv) | 638 | if (sarea_priv) |
| 637 | sarea_priv->last_dispatch = (int)hw_status[5]; | 639 | sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); |
| 638 | return ret; | 640 | return ret; |
| 639 | } | 641 | } |
| 640 | 642 | ||
| @@ -642,7 +644,6 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | |||
| 642 | struct drm_file *file_priv) | 644 | struct drm_file *file_priv) |
| 643 | { | 645 | { |
| 644 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 646 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 645 | u32 *hw_status = dev_priv->hw_status_page; | ||
| 646 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) | 647 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) |
| 647 | dev_priv->sarea_priv; | 648 | dev_priv->sarea_priv; |
| 648 | drm_i915_cmdbuffer_t *cmdbuf = data; | 649 | drm_i915_cmdbuffer_t *cmdbuf = data; |
| @@ -670,7 +671,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | |||
| 670 | } | 671 | } |
| 671 | 672 | ||
| 672 | if (sarea_priv) | 673 | if (sarea_priv) |
| 673 | sarea_priv->last_dispatch = (int)hw_status[5]; | 674 | sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); |
| 674 | return 0; | 675 | return 0; |
| 675 | } | 676 | } |
| 676 | 677 | ||
| @@ -849,8 +850,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 849 | * be lost or delayed | 850 | * be lost or delayed |
| 850 | */ | 851 | */ |
| 851 | if (!IS_I945G(dev) && !IS_I945GM(dev) && !IS_I965GM(dev)) | 852 | if (!IS_I945G(dev) && !IS_I945GM(dev) && !IS_I965GM(dev)) |
| 852 | if (pci_enable_msi(dev->pdev)) | 853 | pci_enable_msi(dev->pdev); |
| 853 | DRM_ERROR("failed to enable MSI\n"); | ||
| 854 | 854 | ||
| 855 | intel_opregion_init(dev); | 855 | intel_opregion_init(dev); |
| 856 | 856 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 572dcd0e3e0d..ef1c0b8f8d07 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -88,13 +88,6 @@ struct mem_block { | |||
| 88 | struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ | 88 | struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | typedef struct _drm_i915_vbl_swap { | ||
| 92 | struct list_head head; | ||
| 93 | drm_drawable_t drw_id; | ||
| 94 | unsigned int pipe; | ||
| 95 | unsigned int sequence; | ||
| 96 | } drm_i915_vbl_swap_t; | ||
| 97 | |||
| 98 | struct opregion_header; | 91 | struct opregion_header; |
| 99 | struct opregion_acpi; | 92 | struct opregion_acpi; |
| 100 | struct opregion_swsci; | 93 | struct opregion_swsci; |
| @@ -146,10 +139,6 @@ typedef struct drm_i915_private { | |||
| 146 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; | 139 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; |
| 147 | int vblank_pipe; | 140 | int vblank_pipe; |
| 148 | 141 | ||
| 149 | spinlock_t swaps_lock; | ||
| 150 | drm_i915_vbl_swap_t vbl_swaps; | ||
| 151 | unsigned int swaps_pending; | ||
| 152 | |||
| 153 | struct intel_opregion opregion; | 142 | struct intel_opregion opregion; |
| 154 | 143 | ||
| 155 | /* Register state */ | 144 | /* Register state */ |
| @@ -157,6 +146,7 @@ typedef struct drm_i915_private { | |||
| 157 | u32 saveDSPACNTR; | 146 | u32 saveDSPACNTR; |
| 158 | u32 saveDSPBCNTR; | 147 | u32 saveDSPBCNTR; |
| 159 | u32 saveDSPARB; | 148 | u32 saveDSPARB; |
| 149 | u32 saveRENDERSTANDBY; | ||
| 160 | u32 savePIPEACONF; | 150 | u32 savePIPEACONF; |
| 161 | u32 savePIPEBCONF; | 151 | u32 savePIPEBCONF; |
| 162 | u32 savePIPEASRC; | 152 | u32 savePIPEASRC; |
| @@ -241,9 +231,6 @@ typedef struct drm_i915_private { | |||
| 241 | u8 saveDACDATA[256*3]; /* 256 3-byte colors */ | 231 | u8 saveDACDATA[256*3]; /* 256 3-byte colors */ |
| 242 | u8 saveCR[37]; | 232 | u8 saveCR[37]; |
| 243 | 233 | ||
| 244 | /** Work task for vblank-related ring access */ | ||
| 245 | struct work_struct vblank_work; | ||
| 246 | |||
| 247 | struct { | 234 | struct { |
| 248 | struct drm_mm gtt_space; | 235 | struct drm_mm gtt_space; |
| 249 | 236 | ||
| @@ -444,7 +431,6 @@ extern int i915_irq_wait(struct drm_device *dev, void *data, | |||
| 444 | void i915_user_irq_get(struct drm_device *dev); | 431 | void i915_user_irq_get(struct drm_device *dev); |
| 445 | void i915_user_irq_put(struct drm_device *dev); | 432 | void i915_user_irq_put(struct drm_device *dev); |
| 446 | 433 | ||
| 447 | extern void i915_vblank_work_handler(struct work_struct *work); | ||
| 448 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); | 434 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); |
| 449 | extern void i915_driver_irq_preinstall(struct drm_device * dev); | 435 | extern void i915_driver_irq_preinstall(struct drm_device * dev); |
| 450 | extern int i915_driver_irq_postinstall(struct drm_device *dev); | 436 | extern int i915_driver_irq_postinstall(struct drm_device *dev); |
| @@ -622,8 +608,9 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; } | |||
| 622 | * The area from dword 0x20 to 0x3ff is available for driver usage. | 608 | * The area from dword 0x20 to 0x3ff is available for driver usage. |
| 623 | */ | 609 | */ |
| 624 | #define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg]) | 610 | #define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg]) |
| 625 | #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, 5) | 611 | #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX) |
| 626 | #define I915_GEM_HWS_INDEX 0x20 | 612 | #define I915_GEM_HWS_INDEX 0x20 |
| 613 | #define I915_BREADCRUMB_INDEX 0x21 | ||
| 627 | 614 | ||
| 628 | extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | 615 | extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); |
| 629 | 616 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b0ec73fa6a93..6b4a2bd20640 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1455,11 +1455,9 @@ i915_gem_object_set_domain_range(struct drm_gem_object *obj, | |||
| 1455 | read_domains, write_domain); | 1455 | read_domains, write_domain); |
| 1456 | 1456 | ||
| 1457 | /* Wait on any GPU rendering to the object to be flushed. */ | 1457 | /* Wait on any GPU rendering to the object to be flushed. */ |
| 1458 | if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) { | 1458 | ret = i915_gem_object_wait_rendering(obj); |
| 1459 | ret = i915_gem_object_wait_rendering(obj); | 1459 | if (ret) |
| 1460 | if (ret) | 1460 | return ret; |
| 1461 | return ret; | ||
| 1462 | } | ||
| 1463 | 1461 | ||
| 1464 | if (obj_priv->page_cpu_valid == NULL) { | 1462 | if (obj_priv->page_cpu_valid == NULL) { |
| 1465 | obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE, | 1463 | obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE, |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 26f48932a51e..82752d6177a4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -80,211 +80,6 @@ i915_pipe_enabled(struct drm_device *dev, int pipe) | |||
| 80 | return 0; | 80 | return 0; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | /** | ||
| 84 | * Emit blits for scheduled buffer swaps. | ||
| 85 | * | ||
| 86 | * This function will be called with the HW lock held. | ||
| 87 | * Because this function must grab the ring mutex (dev->struct_mutex), | ||
| 88 | * it can no longer run at soft irq time. We'll fix this when we do | ||
| 89 | * the DRI2 swap buffer work. | ||
| 90 | */ | ||
| 91 | static void i915_vblank_tasklet(struct drm_device *dev) | ||
| 92 | { | ||
| 93 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
| 94 | unsigned long irqflags; | ||
| 95 | struct list_head *list, *tmp, hits, *hit; | ||
| 96 | int nhits, nrects, slice[2], upper[2], lower[2], i; | ||
| 97 | unsigned counter[2]; | ||
| 98 | struct drm_drawable_info *drw; | ||
| 99 | drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 100 | u32 cpp = dev_priv->cpp; | ||
| 101 | u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | | ||
| 102 | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||
| 103 | XY_SRC_COPY_BLT_WRITE_RGB) | ||
| 104 | : XY_SRC_COPY_BLT_CMD; | ||
| 105 | u32 src_pitch = sarea_priv->pitch * cpp; | ||
| 106 | u32 dst_pitch = sarea_priv->pitch * cpp; | ||
| 107 | u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24); | ||
| 108 | RING_LOCALS; | ||
| 109 | |||
| 110 | mutex_lock(&dev->struct_mutex); | ||
| 111 | |||
| 112 | if (IS_I965G(dev) && sarea_priv->front_tiled) { | ||
| 113 | cmd |= XY_SRC_COPY_BLT_DST_TILED; | ||
| 114 | dst_pitch >>= 2; | ||
| 115 | } | ||
| 116 | if (IS_I965G(dev) && sarea_priv->back_tiled) { | ||
| 117 | cmd |= XY_SRC_COPY_BLT_SRC_TILED; | ||
| 118 | src_pitch >>= 2; | ||
| 119 | } | ||
| 120 | |||
| 121 | counter[0] = drm_vblank_count(dev, 0); | ||
| 122 | counter[1] = drm_vblank_count(dev, 1); | ||
| 123 | |||
| 124 | DRM_DEBUG("\n"); | ||
| 125 | |||
| 126 | INIT_LIST_HEAD(&hits); | ||
| 127 | |||
| 128 | nhits = nrects = 0; | ||
| 129 | |||
| 130 | spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); | ||
| 131 | |||
| 132 | /* Find buffer swaps scheduled for this vertical blank */ | ||
| 133 | list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { | ||
| 134 | drm_i915_vbl_swap_t *vbl_swap = | ||
| 135 | list_entry(list, drm_i915_vbl_swap_t, head); | ||
| 136 | int pipe = vbl_swap->pipe; | ||
| 137 | |||
| 138 | if ((counter[pipe] - vbl_swap->sequence) > (1<<23)) | ||
| 139 | continue; | ||
| 140 | |||
| 141 | list_del(list); | ||
| 142 | dev_priv->swaps_pending--; | ||
| 143 | drm_vblank_put(dev, pipe); | ||
| 144 | |||
| 145 | spin_unlock(&dev_priv->swaps_lock); | ||
| 146 | spin_lock(&dev->drw_lock); | ||
| 147 | |||
| 148 | drw = drm_get_drawable_info(dev, vbl_swap->drw_id); | ||
| 149 | |||
| 150 | list_for_each(hit, &hits) { | ||
| 151 | drm_i915_vbl_swap_t *swap_cmp = | ||
| 152 | list_entry(hit, drm_i915_vbl_swap_t, head); | ||
| 153 | struct drm_drawable_info *drw_cmp = | ||
| 154 | drm_get_drawable_info(dev, swap_cmp->drw_id); | ||
| 155 | |||
| 156 | /* Make sure both drawables are still | ||
| 157 | * around and have some rectangles before | ||
| 158 | * we look inside to order them for the | ||
| 159 | * blts below. | ||
| 160 | */ | ||
| 161 | if (drw_cmp && drw_cmp->num_rects > 0 && | ||
| 162 | drw && drw->num_rects > 0 && | ||
| 163 | drw_cmp->rects[0].y1 > drw->rects[0].y1) { | ||
| 164 | list_add_tail(list, hit); | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | spin_unlock(&dev->drw_lock); | ||
| 170 | |||
| 171 | /* List of hits was empty, or we reached the end of it */ | ||
| 172 | if (hit == &hits) | ||
| 173 | list_add_tail(list, hits.prev); | ||
| 174 | |||
| 175 | nhits++; | ||
| 176 | |||
| 177 | spin_lock(&dev_priv->swaps_lock); | ||
| 178 | } | ||
| 179 | |||
| 180 | if (nhits == 0) { | ||
| 181 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | ||
| 182 | mutex_unlock(&dev->struct_mutex); | ||
| 183 | return; | ||
| 184 | } | ||
| 185 | |||
| 186 | spin_unlock(&dev_priv->swaps_lock); | ||
| 187 | |||
| 188 | i915_kernel_lost_context(dev); | ||
| 189 | |||
| 190 | if (IS_I965G(dev)) { | ||
| 191 | BEGIN_LP_RING(4); | ||
| 192 | |||
| 193 | OUT_RING(GFX_OP_DRAWRECT_INFO_I965); | ||
| 194 | OUT_RING(0); | ||
| 195 | OUT_RING(((sarea_priv->width - 1) & 0xffff) | ((sarea_priv->height - 1) << 16)); | ||
| 196 | OUT_RING(0); | ||
| 197 | ADVANCE_LP_RING(); | ||
| 198 | } else { | ||
| 199 | BEGIN_LP_RING(6); | ||
| 200 | |||
| 201 | OUT_RING(GFX_OP_DRAWRECT_INFO); | ||
| 202 | OUT_RING(0); | ||
| 203 | OUT_RING(0); | ||
| 204 | OUT_RING(sarea_priv->width | sarea_priv->height << 16); | ||
| 205 | OUT_RING(sarea_priv->width | sarea_priv->height << 16); | ||
| 206 | OUT_RING(0); | ||
| 207 | |||
| 208 | ADVANCE_LP_RING(); | ||
| 209 | } | ||
| 210 | |||
| 211 | sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; | ||
| 212 | |||
| 213 | upper[0] = upper[1] = 0; | ||
| 214 | slice[0] = max(sarea_priv->pipeA_h / nhits, 1); | ||
| 215 | slice[1] = max(sarea_priv->pipeB_h / nhits, 1); | ||
| 216 | lower[0] = sarea_priv->pipeA_y + slice[0]; | ||
| 217 | lower[1] = sarea_priv->pipeB_y + slice[0]; | ||
| 218 | |||
| 219 | spin_lock(&dev->drw_lock); | ||
| 220 | |||
| 221 | /* Emit blits for buffer swaps, partitioning both outputs into as many | ||
| 222 | * slices as there are buffer swaps scheduled in order to avoid tearing | ||
| 223 | * (based on the assumption that a single buffer swap would always | ||
| 224 | * complete before scanout starts). | ||
| 225 | */ | ||
| 226 | for (i = 0; i++ < nhits; | ||
| 227 | upper[0] = lower[0], lower[0] += slice[0], | ||
| 228 | upper[1] = lower[1], lower[1] += slice[1]) { | ||
| 229 | if (i == nhits) | ||
| 230 | lower[0] = lower[1] = sarea_priv->height; | ||
| 231 | |||
| 232 | list_for_each(hit, &hits) { | ||
| 233 | drm_i915_vbl_swap_t *swap_hit = | ||
| 234 | list_entry(hit, drm_i915_vbl_swap_t, head); | ||
| 235 | struct drm_clip_rect *rect; | ||
| 236 | int num_rects, pipe; | ||
| 237 | unsigned short top, bottom; | ||
| 238 | |||
| 239 | drw = drm_get_drawable_info(dev, swap_hit->drw_id); | ||
| 240 | |||
| 241 | /* The drawable may have been destroyed since | ||
| 242 | * the vblank swap was queued | ||
| 243 | */ | ||
| 244 | if (!drw) | ||
| 245 | continue; | ||
| 246 | |||
| 247 | rect = drw->rects; | ||
| 248 | pipe = swap_hit->pipe; | ||
| 249 | top = upper[pipe]; | ||
| 250 | bottom = lower[pipe]; | ||
| 251 | |||
| 252 | for (num_rects = drw->num_rects; num_rects--; rect++) { | ||
| 253 | int y1 = max(rect->y1, top); | ||
| 254 | int y2 = min(rect->y2, bottom); | ||
| 255 | |||
| 256 | if (y1 >= y2) | ||
| 257 | continue; | ||
| 258 | |||
| 259 | BEGIN_LP_RING(8); | ||
| 260 | |||
| 261 | OUT_RING(cmd); | ||
| 262 | OUT_RING(ropcpp | dst_pitch); | ||
| 263 | OUT_RING((y1 << 16) | rect->x1); | ||
| 264 | OUT_RING((y2 << 16) | rect->x2); | ||
| 265 | OUT_RING(sarea_priv->front_offset); | ||
| 266 | OUT_RING((y1 << 16) | rect->x1); | ||
| 267 | OUT_RING(src_pitch); | ||
| 268 | OUT_RING(sarea_priv->back_offset); | ||
| 269 | |||
| 270 | ADVANCE_LP_RING(); | ||
| 271 | } | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
| 276 | mutex_unlock(&dev->struct_mutex); | ||
| 277 | |||
| 278 | list_for_each_safe(hit, tmp, &hits) { | ||
| 279 | drm_i915_vbl_swap_t *swap_hit = | ||
| 280 | list_entry(hit, drm_i915_vbl_swap_t, head); | ||
| 281 | |||
| 282 | list_del(hit); | ||
| 283 | |||
| 284 | drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER); | ||
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 | /* Called from drm generic code, passed a 'crtc', which | 83 | /* Called from drm generic code, passed a 'crtc', which |
| 289 | * we use as a pipe index | 84 | * we use as a pipe index |
| 290 | */ | 85 | */ |
| @@ -322,40 +117,6 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) | |||
| 322 | return count; | 117 | return count; |
| 323 | } | 118 | } |
| 324 | 119 | ||
| 325 | void | ||
| 326 | i915_vblank_work_handler(struct work_struct *work) | ||
| 327 | { | ||
| 328 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, | ||
| 329 | vblank_work); | ||
| 330 | struct drm_device *dev = dev_priv->dev; | ||
| 331 | unsigned long irqflags; | ||
| 332 | |||
| 333 | if (dev->lock.hw_lock == NULL) { | ||
| 334 | i915_vblank_tasklet(dev); | ||
| 335 | return; | ||
| 336 | } | ||
| 337 | |||
| 338 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | ||
| 339 | dev->locked_tasklet_func = i915_vblank_tasklet; | ||
| 340 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
| 341 | |||
| 342 | /* Try to get the lock now, if this fails, the lock | ||
| 343 | * holder will execute the tasklet during unlock | ||
| 344 | */ | ||
| 345 | if (!drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) | ||
| 346 | return; | ||
| 347 | |||
| 348 | dev->lock.lock_time = jiffies; | ||
| 349 | atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); | ||
| 350 | |||
| 351 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | ||
| 352 | dev->locked_tasklet_func = NULL; | ||
| 353 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
| 354 | |||
| 355 | i915_vblank_tasklet(dev); | ||
| 356 | drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT); | ||
| 357 | } | ||
| 358 | |||
| 359 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | 120 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) |
| 360 | { | 121 | { |
| 361 | struct drm_device *dev = (struct drm_device *) arg; | 122 | struct drm_device *dev = (struct drm_device *) arg; |
| @@ -433,9 +194,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 433 | if (iir & I915_ASLE_INTERRUPT) | 194 | if (iir & I915_ASLE_INTERRUPT) |
| 434 | opregion_asle_intr(dev); | 195 | opregion_asle_intr(dev); |
| 435 | 196 | ||
| 436 | if (vblank && dev_priv->swaps_pending > 0) | ||
| 437 | schedule_work(&dev_priv->vblank_work); | ||
| 438 | |||
| 439 | return IRQ_HANDLED; | 197 | return IRQ_HANDLED; |
| 440 | } | 198 | } |
| 441 | 199 | ||
| @@ -454,12 +212,10 @@ static int i915_emit_irq(struct drm_device * dev) | |||
| 454 | if (dev_priv->sarea_priv) | 212 | if (dev_priv->sarea_priv) |
| 455 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter; | 213 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter; |
| 456 | 214 | ||
| 457 | BEGIN_LP_RING(6); | 215 | BEGIN_LP_RING(4); |
| 458 | OUT_RING(MI_STORE_DWORD_INDEX); | 216 | OUT_RING(MI_STORE_DWORD_INDEX); |
| 459 | OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT); | 217 | OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); |
| 460 | OUT_RING(dev_priv->counter); | 218 | OUT_RING(dev_priv->counter); |
| 461 | OUT_RING(0); | ||
| 462 | OUT_RING(0); | ||
| 463 | OUT_RING(MI_USER_INTERRUPT); | 219 | OUT_RING(MI_USER_INTERRUPT); |
| 464 | ADVANCE_LP_RING(); | 220 | ADVANCE_LP_RING(); |
| 465 | 221 | ||
| @@ -696,123 +452,21 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data, | |||
| 696 | int i915_vblank_swap(struct drm_device *dev, void *data, | 452 | int i915_vblank_swap(struct drm_device *dev, void *data, |
| 697 | struct drm_file *file_priv) | 453 | struct drm_file *file_priv) |
| 698 | { | 454 | { |
| 699 | drm_i915_private_t *dev_priv = dev->dev_private; | 455 | /* The delayed swap mechanism was fundamentally racy, and has been |
| 700 | drm_i915_vblank_swap_t *swap = data; | 456 | * removed. The model was that the client requested a delayed flip/swap |
| 701 | drm_i915_vbl_swap_t *vbl_swap, *vbl_old; | 457 | * from the kernel, then waited for vblank before continuing to perform |
| 702 | unsigned int pipe, seqtype, curseq; | 458 | * rendering. The problem was that the kernel might wake the client |
| 703 | unsigned long irqflags; | 459 | * up before it dispatched the vblank swap (since the lock has to be |
| 704 | struct list_head *list; | 460 | * held while touching the ringbuffer), in which case the client would |
| 705 | int ret; | 461 | * clear and start the next frame before the swap occurred, and |
| 706 | 462 | * flicker would occur in addition to likely missing the vblank. | |
| 707 | if (!dev_priv || !dev_priv->sarea_priv) { | 463 | * |
| 708 | DRM_ERROR("%s called with no initialization\n", __func__); | 464 | * In the absence of this ioctl, userland falls back to a correct path |
| 709 | return -EINVAL; | 465 | * of waiting for a vblank, then dispatching the swap on its own. |
| 710 | } | 466 | * Context switching to userland and back is plenty fast enough for |
| 711 | 467 | * meeting the requirements of vblank swapping. | |
| 712 | if (dev_priv->sarea_priv->rotation) { | ||
| 713 | DRM_DEBUG("Rotation not supported\n"); | ||
| 714 | return -EINVAL; | ||
| 715 | } | ||
| 716 | |||
| 717 | if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | | ||
| 718 | _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) { | ||
| 719 | DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype); | ||
| 720 | return -EINVAL; | ||
| 721 | } | ||
| 722 | |||
| 723 | pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; | ||
| 724 | |||
| 725 | seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); | ||
| 726 | |||
| 727 | if (!(dev_priv->vblank_pipe & (1 << pipe))) { | ||
| 728 | DRM_ERROR("Invalid pipe %d\n", pipe); | ||
| 729 | return -EINVAL; | ||
| 730 | } | ||
| 731 | |||
| 732 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
| 733 | |||
| 734 | if (!drm_get_drawable_info(dev, swap->drawable)) { | ||
| 735 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
| 736 | DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable); | ||
| 737 | return -EINVAL; | ||
| 738 | } | ||
| 739 | |||
| 740 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
| 741 | |||
| 742 | /* | ||
| 743 | * We take the ref here and put it when the swap actually completes | ||
| 744 | * in the tasklet. | ||
| 745 | */ | 468 | */ |
| 746 | ret = drm_vblank_get(dev, pipe); | 469 | return -EINVAL; |
| 747 | if (ret) | ||
| 748 | return ret; | ||
| 749 | curseq = drm_vblank_count(dev, pipe); | ||
| 750 | |||
| 751 | if (seqtype == _DRM_VBLANK_RELATIVE) | ||
| 752 | swap->sequence += curseq; | ||
| 753 | |||
| 754 | if ((curseq - swap->sequence) <= (1<<23)) { | ||
| 755 | if (swap->seqtype & _DRM_VBLANK_NEXTONMISS) { | ||
| 756 | swap->sequence = curseq + 1; | ||
| 757 | } else { | ||
| 758 | DRM_DEBUG("Missed target sequence\n"); | ||
| 759 | drm_vblank_put(dev, pipe); | ||
| 760 | return -EINVAL; | ||
| 761 | } | ||
| 762 | } | ||
| 763 | |||
| 764 | vbl_swap = drm_calloc(1, sizeof(*vbl_swap), DRM_MEM_DRIVER); | ||
| 765 | |||
| 766 | if (!vbl_swap) { | ||
| 767 | DRM_ERROR("Failed to allocate memory to queue swap\n"); | ||
| 768 | drm_vblank_put(dev, pipe); | ||
| 769 | return -ENOMEM; | ||
| 770 | } | ||
| 771 | |||
| 772 | vbl_swap->drw_id = swap->drawable; | ||
| 773 | vbl_swap->pipe = pipe; | ||
| 774 | vbl_swap->sequence = swap->sequence; | ||
| 775 | |||
| 776 | spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); | ||
| 777 | |||
| 778 | list_for_each(list, &dev_priv->vbl_swaps.head) { | ||
| 779 | vbl_old = list_entry(list, drm_i915_vbl_swap_t, head); | ||
| 780 | |||
| 781 | if (vbl_old->drw_id == swap->drawable && | ||
| 782 | vbl_old->pipe == pipe && | ||
| 783 | vbl_old->sequence == swap->sequence) { | ||
| 784 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | ||
| 785 | drm_vblank_put(dev, pipe); | ||
| 786 | drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); | ||
| 787 | DRM_DEBUG("Already scheduled\n"); | ||
| 788 | return 0; | ||
| 789 | } | ||
| 790 | } | ||
| 791 | |||
| 792 | if (dev_priv->swaps_pending >= 10) { | ||
| 793 | DRM_DEBUG("Too many swaps queued\n"); | ||
| 794 | DRM_DEBUG(" pipe 0: %d pipe 1: %d\n", | ||
| 795 | drm_vblank_count(dev, 0), | ||
| 796 | drm_vblank_count(dev, 1)); | ||
| 797 | |||
| 798 | list_for_each(list, &dev_priv->vbl_swaps.head) { | ||
| 799 | vbl_old = list_entry(list, drm_i915_vbl_swap_t, head); | ||
| 800 | DRM_DEBUG("\tdrw %x pipe %d seq %x\n", | ||
| 801 | vbl_old->drw_id, vbl_old->pipe, | ||
| 802 | vbl_old->sequence); | ||
| 803 | } | ||
| 804 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | ||
| 805 | drm_vblank_put(dev, pipe); | ||
| 806 | drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); | ||
| 807 | return -EBUSY; | ||
| 808 | } | ||
| 809 | |||
| 810 | list_add_tail(&vbl_swap->head, &dev_priv->vbl_swaps.head); | ||
| 811 | dev_priv->swaps_pending++; | ||
| 812 | |||
| 813 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | ||
| 814 | |||
| 815 | return 0; | ||
| 816 | } | 470 | } |
| 817 | 471 | ||
| 818 | /* drm_dma.h hooks | 472 | /* drm_dma.h hooks |
| @@ -831,11 +485,6 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
| 831 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 485 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 832 | int ret, num_pipes = 2; | 486 | int ret, num_pipes = 2; |
| 833 | 487 | ||
| 834 | spin_lock_init(&dev_priv->swaps_lock); | ||
| 835 | INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); | ||
| 836 | INIT_WORK(&dev_priv->vblank_work, i915_vblank_work_handler); | ||
| 837 | dev_priv->swaps_pending = 0; | ||
| 838 | |||
| 839 | /* Set initial unmasked IRQs to just the selected vblank pipes. */ | 488 | /* Set initial unmasked IRQs to just the selected vblank pipes. */ |
| 840 | dev_priv->irq_mask_reg = ~0; | 489 | dev_priv->irq_mask_reg = ~0; |
| 841 | 490 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5c2d9f206d05..0e476eba36e6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -527,6 +527,9 @@ | |||
| 527 | #define C0DRB3 0x10206 | 527 | #define C0DRB3 0x10206 |
| 528 | #define C1DRB3 0x10606 | 528 | #define C1DRB3 0x10606 |
| 529 | 529 | ||
| 530 | /** GM965 GM45 render standby register */ | ||
| 531 | #define MCHBAR_RENDER_STANDBY 0x111B8 | ||
| 532 | |||
| 530 | /* | 533 | /* |
| 531 | * Overlay regs | 534 | * Overlay regs |
| 532 | */ | 535 | */ |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 603fe742ccd4..5ddc6e595c0c 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -240,6 +240,10 @@ int i915_save_state(struct drm_device *dev) | |||
| 240 | 240 | ||
| 241 | pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); | 241 | pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); |
| 242 | 242 | ||
| 243 | /* Render Standby */ | ||
| 244 | if (IS_I965G(dev) && IS_MOBILE(dev)) | ||
| 245 | dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); | ||
| 246 | |||
| 243 | /* Display arbitration control */ | 247 | /* Display arbitration control */ |
| 244 | dev_priv->saveDSPARB = I915_READ(DSPARB); | 248 | dev_priv->saveDSPARB = I915_READ(DSPARB); |
| 245 | 249 | ||
| @@ -365,6 +369,11 @@ int i915_restore_state(struct drm_device *dev) | |||
| 365 | 369 | ||
| 366 | pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); | 370 | pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); |
| 367 | 371 | ||
| 372 | /* Render Standby */ | ||
| 373 | if (IS_I965G(dev) && IS_MOBILE(dev)) | ||
| 374 | I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY); | ||
| 375 | |||
| 376 | /* Display arbitration */ | ||
| 368 | I915_WRITE(DSPARB, dev_priv->saveDSPARB); | 377 | I915_WRITE(DSPARB, dev_priv->saveDSPARB); |
| 369 | 378 | ||
| 370 | /* Pipe & plane A info */ | 379 | /* Pipe & plane A info */ |
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 073894824e6b..abdc1ae38467 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c | |||
| @@ -1751,6 +1751,12 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1751 | else | 1751 | else |
| 1752 | dev_priv->flags |= RADEON_IS_PCI; | 1752 | dev_priv->flags |= RADEON_IS_PCI; |
| 1753 | 1753 | ||
| 1754 | ret = drm_addmap(dev, drm_get_resource_start(dev, 2), | ||
| 1755 | drm_get_resource_len(dev, 2), _DRM_REGISTERS, | ||
| 1756 | _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio); | ||
| 1757 | if (ret != 0) | ||
| 1758 | return ret; | ||
| 1759 | |||
| 1754 | DRM_DEBUG("%s card detected\n", | 1760 | DRM_DEBUG("%s card detected\n", |
| 1755 | ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); | 1761 | ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); |
| 1756 | return ret; | 1762 | return ret; |
| @@ -1767,12 +1773,6 @@ int radeon_driver_firstopen(struct drm_device *dev) | |||
| 1767 | 1773 | ||
| 1768 | dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; | 1774 | dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; |
| 1769 | 1775 | ||
| 1770 | ret = drm_addmap(dev, drm_get_resource_start(dev, 2), | ||
| 1771 | drm_get_resource_len(dev, 2), _DRM_REGISTERS, | ||
| 1772 | _DRM_READ_ONLY, &dev_priv->mmio); | ||
| 1773 | if (ret != 0) | ||
| 1774 | return ret; | ||
| 1775 | |||
| 1776 | dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); | 1776 | dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); |
| 1777 | ret = drm_addmap(dev, dev_priv->fb_aper_offset, | 1777 | ret = drm_addmap(dev, dev_priv->fb_aper_offset, |
| 1778 | drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, | 1778 | drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, |
| @@ -1788,6 +1788,9 @@ int radeon_driver_unload(struct drm_device *dev) | |||
| 1788 | drm_radeon_private_t *dev_priv = dev->dev_private; | 1788 | drm_radeon_private_t *dev_priv = dev->dev_private; |
| 1789 | 1789 | ||
| 1790 | DRM_DEBUG("\n"); | 1790 | DRM_DEBUG("\n"); |
| 1791 | |||
| 1792 | drm_rmmap(dev, dev_priv->mmio); | ||
| 1793 | |||
| 1791 | drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); | 1794 | drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); |
| 1792 | 1795 | ||
| 1793 | dev->dev_private = NULL; | 1796 | dev->dev_private = NULL; |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 02f5575ba395..7a183789be97 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h | |||
| @@ -287,7 +287,6 @@ typedef struct drm_radeon_private { | |||
| 287 | unsigned long gart_textures_offset; | 287 | unsigned long gart_textures_offset; |
| 288 | 288 | ||
| 289 | drm_local_map_t *sarea; | 289 | drm_local_map_t *sarea; |
| 290 | drm_local_map_t *mmio; | ||
| 291 | drm_local_map_t *cp_ring; | 290 | drm_local_map_t *cp_ring; |
| 292 | drm_local_map_t *ring_rptr; | 291 | drm_local_map_t *ring_rptr; |
| 293 | drm_local_map_t *gart_textures; | 292 | drm_local_map_t *gart_textures; |
| @@ -318,6 +317,7 @@ typedef struct drm_radeon_private { | |||
| 318 | 317 | ||
| 319 | int num_gb_pipes; | 318 | int num_gb_pipes; |
| 320 | int track_flush; | 319 | int track_flush; |
| 320 | drm_local_map_t *mmio; | ||
| 321 | } drm_radeon_private_t; | 321 | } drm_radeon_private_t; |
| 322 | 322 | ||
| 323 | typedef struct drm_radeon_buf_priv { | 323 | typedef struct drm_radeon_buf_priv { |
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index c6ab4ba60c52..9b97795e45ad 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c | |||
| @@ -55,10 +55,11 @@ struct apple_key_translation { | |||
| 55 | 55 | ||
| 56 | static struct apple_key_translation apple_fn_keys[] = { | 56 | static struct apple_key_translation apple_fn_keys[] = { |
| 57 | { KEY_BACKSPACE, KEY_DELETE }, | 57 | { KEY_BACKSPACE, KEY_DELETE }, |
| 58 | { KEY_ENTER, KEY_INSERT }, | ||
| 58 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, | 59 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, |
| 59 | { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, | 60 | { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, |
| 60 | { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */ | 61 | { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, |
| 61 | { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */ | 62 | { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY }, |
| 62 | { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY }, | 63 | { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY }, |
| 63 | { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY }, | 64 | { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY }, |
| 64 | { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, | 65 | { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, |
| @@ -418,6 +419,12 @@ static const struct hid_device_id apple_devices[] = { | |||
| 418 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | 419 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, |
| 419 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), | 420 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), |
| 420 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | 421 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, |
| 422 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), | ||
| 423 | .driver_data = APPLE_HAS_FN }, | ||
| 424 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), | ||
| 425 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
| 426 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), | ||
| 427 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | ||
| 421 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), | 428 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), |
| 422 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, | 429 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, |
| 423 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), | 430 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1903e7515650..147ec591a806 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1250,9 +1250,11 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1250 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, | 1250 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, |
| 1251 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, | 1251 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, |
| 1252 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, | 1252 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, |
| 1253 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, | ||
| 1254 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, | ||
| 1255 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, | ||
| 1253 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1256 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1254 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1257 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1255 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, | ||
| 1256 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1258 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
| 1257 | { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, | 1259 | { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, |
| 1258 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1260 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
| @@ -1408,6 +1410,7 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
| 1408 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, | 1410 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, |
| 1409 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)}, | 1411 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)}, |
| 1410 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)}, | 1412 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)}, |
| 1413 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, | ||
| 1411 | { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, | 1414 | { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, |
| 1412 | { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, | 1415 | { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, |
| 1413 | { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, | 1416 | { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, |
| @@ -1485,6 +1488,7 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
| 1485 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, | 1488 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, |
| 1486 | { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, | 1489 | { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, |
| 1487 | { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, | 1490 | { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, |
| 1491 | { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, | ||
| 1488 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, | 1492 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, |
| 1489 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, | 1493 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, |
| 1490 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, | 1494 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, |
| @@ -1572,6 +1576,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { | |||
| 1572 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, | 1576 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, |
| 1573 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, | 1577 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, |
| 1574 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, | 1578 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, |
| 1579 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, | ||
| 1580 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, | ||
| 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, | ||
| 1575 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1582 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1576 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1583 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1577 | { } | 1584 | { } |
| @@ -1729,7 +1736,7 @@ static int __init hid_init(void) | |||
| 1729 | goto err_bus; | 1736 | goto err_bus; |
| 1730 | 1737 | ||
| 1731 | #ifdef CONFIG_HID_COMPAT | 1738 | #ifdef CONFIG_HID_COMPAT |
| 1732 | hid_compat_wq = create_workqueue("hid_compat"); | 1739 | hid_compat_wq = create_singlethread_workqueue("hid_compat"); |
| 1733 | if (!hid_compat_wq) { | 1740 | if (!hid_compat_wq) { |
| 1734 | hidraw_exit(); | 1741 | hidraw_exit(); |
| 1735 | goto err; | 1742 | goto err; |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 5cc404291736..d70075dd3d81 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -82,6 +82,9 @@ | |||
| 82 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 | 82 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 |
| 83 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 | 83 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 |
| 84 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 | 84 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 |
| 85 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 | ||
| 86 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 | ||
| 87 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 | ||
| 85 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | 88 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a |
| 86 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | 89 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b |
| 87 | #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 | 90 | #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 |
| @@ -253,6 +256,9 @@ | |||
| 253 | #define USB_VENDOR_ID_KBGEAR 0x084e | 256 | #define USB_VENDOR_ID_KBGEAR 0x084e |
| 254 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 | 257 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 |
| 255 | 258 | ||
| 259 | #define USB_VENDOR_ID_KWORLD 0x1b80 | ||
| 260 | #define USB_DEVICE_ID_KWORLD_RADIO_FM700 0xd700 | ||
| 261 | |||
| 256 | #define USB_VENDOR_ID_LABTEC 0x1020 | 262 | #define USB_VENDOR_ID_LABTEC 0x1020 |
| 257 | #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 | 263 | #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 |
| 258 | 264 | ||
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 894d52e05bf9..7685ae6808c4 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
| @@ -38,7 +38,7 @@ static int hidraw_major; | |||
| 38 | static struct cdev hidraw_cdev; | 38 | static struct cdev hidraw_cdev; |
| 39 | static struct class *hidraw_class; | 39 | static struct class *hidraw_class; |
| 40 | static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; | 40 | static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; |
| 41 | static DEFINE_SPINLOCK(minors_lock); | 41 | static DEFINE_MUTEX(minors_lock); |
| 42 | 42 | ||
| 43 | static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 43 | static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
| 44 | { | 44 | { |
| @@ -159,13 +159,13 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
| 159 | struct hidraw_list *list; | 159 | struct hidraw_list *list; |
| 160 | int err = 0; | 160 | int err = 0; |
| 161 | 161 | ||
| 162 | lock_kernel(); | ||
| 163 | if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { | 162 | if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { |
| 164 | err = -ENOMEM; | 163 | err = -ENOMEM; |
| 165 | goto out; | 164 | goto out; |
| 166 | } | 165 | } |
| 167 | 166 | ||
| 168 | spin_lock(&minors_lock); | 167 | lock_kernel(); |
| 168 | mutex_lock(&minors_lock); | ||
| 169 | if (!hidraw_table[minor]) { | 169 | if (!hidraw_table[minor]) { |
| 170 | printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", | 170 | printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", |
| 171 | minor); | 171 | minor); |
| @@ -180,13 +180,16 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
| 180 | file->private_data = list; | 180 | file->private_data = list; |
| 181 | 181 | ||
| 182 | dev = hidraw_table[minor]; | 182 | dev = hidraw_table[minor]; |
| 183 | if (!dev->open++) | 183 | if (!dev->open++) { |
| 184 | dev->hid->ll_driver->open(dev->hid); | 184 | err = dev->hid->ll_driver->open(dev->hid); |
| 185 | if (err < 0) | ||
| 186 | dev->open--; | ||
| 187 | } | ||
| 185 | 188 | ||
| 186 | out_unlock: | 189 | out_unlock: |
| 187 | spin_unlock(&minors_lock); | 190 | mutex_unlock(&minors_lock); |
| 188 | out: | ||
| 189 | unlock_kernel(); | 191 | unlock_kernel(); |
| 192 | out: | ||
| 190 | return err; | 193 | return err; |
| 191 | 194 | ||
| 192 | } | 195 | } |
| @@ -310,7 +313,7 @@ int hidraw_connect(struct hid_device *hid) | |||
| 310 | 313 | ||
| 311 | result = -EINVAL; | 314 | result = -EINVAL; |
| 312 | 315 | ||
| 313 | spin_lock(&minors_lock); | 316 | mutex_lock(&minors_lock); |
| 314 | 317 | ||
| 315 | for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { | 318 | for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { |
| 316 | if (hidraw_table[minor]) | 319 | if (hidraw_table[minor]) |
| @@ -320,9 +323,8 @@ int hidraw_connect(struct hid_device *hid) | |||
| 320 | break; | 323 | break; |
| 321 | } | 324 | } |
| 322 | 325 | ||
| 323 | spin_unlock(&minors_lock); | ||
| 324 | |||
| 325 | if (result) { | 326 | if (result) { |
| 327 | mutex_unlock(&minors_lock); | ||
| 326 | kfree(dev); | 328 | kfree(dev); |
| 327 | goto out; | 329 | goto out; |
| 328 | } | 330 | } |
| @@ -331,14 +333,14 @@ int hidraw_connect(struct hid_device *hid) | |||
| 331 | NULL, "%s%d", "hidraw", minor); | 333 | NULL, "%s%d", "hidraw", minor); |
| 332 | 334 | ||
| 333 | if (IS_ERR(dev->dev)) { | 335 | if (IS_ERR(dev->dev)) { |
| 334 | spin_lock(&minors_lock); | ||
| 335 | hidraw_table[minor] = NULL; | 336 | hidraw_table[minor] = NULL; |
| 336 | spin_unlock(&minors_lock); | 337 | mutex_unlock(&minors_lock); |
| 337 | result = PTR_ERR(dev->dev); | 338 | result = PTR_ERR(dev->dev); |
| 338 | kfree(dev); | 339 | kfree(dev); |
| 339 | goto out; | 340 | goto out; |
| 340 | } | 341 | } |
| 341 | 342 | ||
| 343 | mutex_unlock(&minors_lock); | ||
| 342 | init_waitqueue_head(&dev->wait); | 344 | init_waitqueue_head(&dev->wait); |
| 343 | INIT_LIST_HEAD(&dev->list); | 345 | INIT_LIST_HEAD(&dev->list); |
| 344 | 346 | ||
| @@ -360,9 +362,9 @@ void hidraw_disconnect(struct hid_device *hid) | |||
| 360 | 362 | ||
| 361 | hidraw->exist = 0; | 363 | hidraw->exist = 0; |
| 362 | 364 | ||
| 363 | spin_lock(&minors_lock); | 365 | mutex_lock(&minors_lock); |
| 364 | hidraw_table[hidraw->minor] = NULL; | 366 | hidraw_table[hidraw->minor] = NULL; |
| 365 | spin_unlock(&minors_lock); | 367 | mutex_unlock(&minors_lock); |
| 366 | 368 | ||
| 367 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); | 369 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); |
| 368 | 370 | ||
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 18e5ddd722cd..d746bf8284dd 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -781,6 +781,8 @@ static int usbhid_start(struct hid_device *hid) | |||
| 781 | unsigned int n, insize = 0; | 781 | unsigned int n, insize = 0; |
| 782 | int ret; | 782 | int ret; |
| 783 | 783 | ||
| 784 | clear_bit(HID_DISCONNECTED, &usbhid->iofl); | ||
| 785 | |||
| 784 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; | 786 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; |
| 785 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); | 787 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); |
| 786 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); | 788 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); |
| @@ -847,12 +849,6 @@ static int usbhid_start(struct hid_device *hid) | |||
| 847 | } | 849 | } |
| 848 | } | 850 | } |
| 849 | 851 | ||
| 850 | if (!usbhid->urbin) { | ||
| 851 | err_hid("couldn't find an input interrupt endpoint"); | ||
| 852 | ret = -ENODEV; | ||
| 853 | goto fail; | ||
| 854 | } | ||
| 855 | |||
| 856 | init_waitqueue_head(&usbhid->wait); | 852 | init_waitqueue_head(&usbhid->wait); |
| 857 | INIT_WORK(&usbhid->reset_work, hid_reset); | 853 | INIT_WORK(&usbhid->reset_work, hid_reset); |
| 858 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | 854 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); |
| @@ -888,6 +884,9 @@ fail: | |||
| 888 | usb_free_urb(usbhid->urbin); | 884 | usb_free_urb(usbhid->urbin); |
| 889 | usb_free_urb(usbhid->urbout); | 885 | usb_free_urb(usbhid->urbout); |
| 890 | usb_free_urb(usbhid->urbctrl); | 886 | usb_free_urb(usbhid->urbctrl); |
| 887 | usbhid->urbin = NULL; | ||
| 888 | usbhid->urbout = NULL; | ||
| 889 | usbhid->urbctrl = NULL; | ||
| 891 | hid_free_buffers(dev, hid); | 890 | hid_free_buffers(dev, hid); |
| 892 | mutex_unlock(&usbhid->setup); | 891 | mutex_unlock(&usbhid->setup); |
| 893 | return ret; | 892 | return ret; |
| @@ -924,6 +923,9 @@ static void usbhid_stop(struct hid_device *hid) | |||
| 924 | usb_free_urb(usbhid->urbin); | 923 | usb_free_urb(usbhid->urbin); |
| 925 | usb_free_urb(usbhid->urbctrl); | 924 | usb_free_urb(usbhid->urbctrl); |
| 926 | usb_free_urb(usbhid->urbout); | 925 | usb_free_urb(usbhid->urbout); |
| 926 | usbhid->urbin = NULL; /* don't mess up next start */ | ||
| 927 | usbhid->urbctrl = NULL; | ||
| 928 | usbhid->urbout = NULL; | ||
| 927 | 929 | ||
| 928 | hid_free_buffers(hid_to_usb_dev(hid), hid); | 930 | hid_free_buffers(hid_to_usb_dev(hid), hid); |
| 929 | mutex_unlock(&usbhid->setup); | 931 | mutex_unlock(&usbhid->setup); |
| @@ -940,15 +942,26 @@ static struct hid_ll_driver usb_hid_driver = { | |||
| 940 | 942 | ||
| 941 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | 943 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 942 | { | 944 | { |
| 945 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
| 943 | struct usb_device *dev = interface_to_usbdev(intf); | 946 | struct usb_device *dev = interface_to_usbdev(intf); |
| 944 | struct usbhid_device *usbhid; | 947 | struct usbhid_device *usbhid; |
| 945 | struct hid_device *hid; | 948 | struct hid_device *hid; |
| 949 | unsigned int n, has_in = 0; | ||
| 946 | size_t len; | 950 | size_t len; |
| 947 | int ret; | 951 | int ret; |
| 948 | 952 | ||
| 949 | dbg_hid("HID probe called for ifnum %d\n", | 953 | dbg_hid("HID probe called for ifnum %d\n", |
| 950 | intf->altsetting->desc.bInterfaceNumber); | 954 | intf->altsetting->desc.bInterfaceNumber); |
| 951 | 955 | ||
| 956 | for (n = 0; n < interface->desc.bNumEndpoints; n++) | ||
| 957 | if (usb_endpoint_is_int_in(&interface->endpoint[n].desc)) | ||
| 958 | has_in++; | ||
| 959 | if (!has_in) { | ||
| 960 | dev_err(&intf->dev, "couldn't find an input interrupt " | ||
| 961 | "endpoint\n"); | ||
| 962 | return -ENODEV; | ||
| 963 | } | ||
| 964 | |||
| 952 | hid = hid_allocate_device(); | 965 | hid = hid_allocate_device(); |
| 953 | if (IS_ERR(hid)) | 966 | if (IS_ERR(hid)) |
| 954 | return PTR_ERR(hid); | 967 | return PTR_ERR(hid); |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 6de1e0ffd391..c709e821f04b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -159,6 +159,16 @@ config SENSORS_ADM9240 | |||
| 159 | This driver can also be built as a module. If so, the module | 159 | This driver can also be built as a module. If so, the module |
| 160 | will be called adm9240. | 160 | will be called adm9240. |
| 161 | 161 | ||
| 162 | config SENSORS_ADT7462 | ||
| 163 | tristate "Analog Devices ADT7462" | ||
| 164 | depends on I2C && EXPERIMENTAL | ||
| 165 | help | ||
| 166 | If you say yes here you get support for the Analog Devices | ||
| 167 | ADT7462 temperature monitoring chips. | ||
| 168 | |||
| 169 | This driver can also be built as a module. If so, the module | ||
| 170 | will be called adt7462. | ||
| 171 | |||
| 162 | config SENSORS_ADT7470 | 172 | config SENSORS_ADT7470 |
| 163 | tristate "Analog Devices ADT7470" | 173 | tristate "Analog Devices ADT7470" |
| 164 | depends on I2C && EXPERIMENTAL | 174 | depends on I2C && EXPERIMENTAL |
| @@ -825,6 +835,25 @@ config SENSORS_HDAPS | |||
| 825 | Say Y here if you have an applicable laptop and want to experience | 835 | Say Y here if you have an applicable laptop and want to experience |
| 826 | the awesome power of hdaps. | 836 | the awesome power of hdaps. |
| 827 | 837 | ||
| 838 | config SENSORS_LIS3LV02D | ||
| 839 | tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer" | ||
| 840 | depends on ACPI && INPUT | ||
| 841 | default n | ||
| 842 | help | ||
| 843 | This driver provides support for the LIS3LV02Dx accelerometer. In | ||
| 844 | particular, it can be found in a number of HP laptops, which have the | ||
| 845 | "Mobile Data Protection System 3D" or "3D DriveGuard" feature. On such | ||
| 846 | systems the driver should load automatically (via ACPI). The | ||
| 847 | accelerometer might also be found in other systems, connected via SPI | ||
| 848 | or I2C. The accelerometer data is readable via | ||
| 849 | /sys/devices/platform/lis3lv02d. | ||
| 850 | |||
| 851 | This driver also provides an absolute input class device, allowing | ||
| 852 | the laptop to act as a pinball machine-esque joystick. | ||
| 853 | |||
| 854 | This driver can also be built as a module. If so, the module | ||
| 855 | will be called lis3lv02d. | ||
| 856 | |||
| 828 | config SENSORS_APPLESMC | 857 | config SENSORS_APPLESMC |
| 829 | tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" | 858 | tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" |
| 830 | depends on INPUT && X86 | 859 | depends on INPUT && X86 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 042d5a78622e..58fc5be5355d 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
| @@ -25,6 +25,7 @@ obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o | |||
| 25 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o | 25 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o |
| 26 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o | 26 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o |
| 27 | obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o | 27 | obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o |
| 28 | obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o | ||
| 28 | obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o | 29 | obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o |
| 29 | obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o | 30 | obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o |
| 30 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o | 31 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o |
| @@ -48,6 +49,7 @@ obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o | |||
| 48 | obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o | 49 | obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o |
| 49 | obj-$(CONFIG_SENSORS_IT87) += it87.o | 50 | obj-$(CONFIG_SENSORS_IT87) += it87.o |
| 50 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o | 51 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o |
| 52 | obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o | ||
| 51 | obj-$(CONFIG_SENSORS_LM63) += lm63.o | 53 | obj-$(CONFIG_SENSORS_LM63) += lm63.o |
| 52 | obj-$(CONFIG_SENSORS_LM70) += lm70.o | 54 | obj-$(CONFIG_SENSORS_LM70) += lm70.o |
| 53 | obj-$(CONFIG_SENSORS_LM75) += lm75.o | 55 | obj-$(CONFIG_SENSORS_LM75) += lm75.o |
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c new file mode 100644 index 000000000000..66107b4dc12a --- /dev/null +++ b/drivers/hwmon/adt7462.c | |||
| @@ -0,0 +1,2002 @@ | |||
| 1 | /* | ||
| 2 | * A hwmon driver for the Analog Devices ADT7462 | ||
| 3 | * Copyright (C) 2008 IBM | ||
| 4 | * | ||
| 5 | * Author: Darrick J. Wong <djwong@us.ibm.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/jiffies.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/hwmon.h> | ||
| 26 | #include <linux/hwmon-sysfs.h> | ||
| 27 | #include <linux/err.h> | ||
| 28 | #include <linux/mutex.h> | ||
| 29 | #include <linux/delay.h> | ||
| 30 | #include <linux/log2.h> | ||
| 31 | |||
| 32 | /* Addresses to scan */ | ||
| 33 | static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END }; | ||
| 34 | |||
| 35 | /* Insmod parameters */ | ||
| 36 | I2C_CLIENT_INSMOD_1(adt7462); | ||
| 37 | |||
| 38 | /* ADT7462 registers */ | ||
| 39 | #define ADT7462_REG_DEVICE 0x3D | ||
| 40 | #define ADT7462_REG_VENDOR 0x3E | ||
| 41 | #define ADT7462_REG_REVISION 0x3F | ||
| 42 | |||
| 43 | #define ADT7462_REG_MIN_TEMP_BASE_ADDR 0x44 | ||
| 44 | #define ADT7462_REG_MIN_TEMP_MAX_ADDR 0x47 | ||
| 45 | #define ADT7462_REG_MAX_TEMP_BASE_ADDR 0x48 | ||
| 46 | #define ADT7462_REG_MAX_TEMP_MAX_ADDR 0x4B | ||
| 47 | #define ADT7462_REG_TEMP_BASE_ADDR 0x88 | ||
| 48 | #define ADT7462_REG_TEMP_MAX_ADDR 0x8F | ||
| 49 | |||
| 50 | #define ADT7462_REG_FAN_BASE_ADDR 0x98 | ||
| 51 | #define ADT7462_REG_FAN_MAX_ADDR 0x9F | ||
| 52 | #define ADT7462_REG_FAN2_BASE_ADDR 0xA2 | ||
| 53 | #define ADT7462_REG_FAN2_MAX_ADDR 0xA9 | ||
| 54 | #define ADT7462_REG_FAN_ENABLE 0x07 | ||
| 55 | #define ADT7462_REG_FAN_MIN_BASE_ADDR 0x78 | ||
| 56 | #define ADT7462_REG_FAN_MIN_MAX_ADDR 0x7F | ||
| 57 | |||
| 58 | #define ADT7462_REG_CFG2 0x02 | ||
| 59 | #define ADT7462_FSPD_MASK 0x20 | ||
| 60 | |||
| 61 | #define ADT7462_REG_PWM_BASE_ADDR 0xAA | ||
| 62 | #define ADT7462_REG_PWM_MAX_ADDR 0xAD | ||
| 63 | #define ADT7462_REG_PWM_MIN_BASE_ADDR 0x28 | ||
| 64 | #define ADT7462_REG_PWM_MIN_MAX_ADDR 0x2B | ||
| 65 | #define ADT7462_REG_PWM_MAX 0x2C | ||
| 66 | #define ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR 0x5C | ||
| 67 | #define ADT7462_REG_PWM_TEMP_MIN_MAX_ADDR 0x5F | ||
| 68 | #define ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR 0x60 | ||
| 69 | #define ADT7462_REG_PWM_TEMP_RANGE_MAX_ADDR 0x63 | ||
| 70 | #define ADT7462_PWM_HYST_MASK 0x0F | ||
| 71 | #define ADT7462_PWM_RANGE_MASK 0xF0 | ||
| 72 | #define ADT7462_PWM_RANGE_SHIFT 4 | ||
| 73 | #define ADT7462_REG_PWM_CFG_BASE_ADDR 0x21 | ||
| 74 | #define ADT7462_REG_PWM_CFG_MAX_ADDR 0x24 | ||
| 75 | #define ADT7462_PWM_CHANNEL_MASK 0xE0 | ||
| 76 | #define ADT7462_PWM_CHANNEL_SHIFT 5 | ||
| 77 | |||
| 78 | #define ADT7462_REG_PIN_CFG_BASE_ADDR 0x10 | ||
| 79 | #define ADT7462_REG_PIN_CFG_MAX_ADDR 0x13 | ||
| 80 | #define ADT7462_PIN7_INPUT 0x01 /* cfg0 */ | ||
| 81 | #define ADT7462_DIODE3_INPUT 0x20 | ||
| 82 | #define ADT7462_DIODE1_INPUT 0x40 | ||
| 83 | #define ADT7462_VID_INPUT 0x80 | ||
| 84 | #define ADT7462_PIN22_INPUT 0x04 /* cfg1 */ | ||
| 85 | #define ADT7462_PIN21_INPUT 0x08 | ||
| 86 | #define ADT7462_PIN19_INPUT 0x10 | ||
| 87 | #define ADT7462_PIN15_INPUT 0x20 | ||
| 88 | #define ADT7462_PIN13_INPUT 0x40 | ||
| 89 | #define ADT7462_PIN8_INPUT 0x80 | ||
| 90 | #define ADT7462_PIN23_MASK 0x03 | ||
| 91 | #define ADT7462_PIN23_SHIFT 0 | ||
| 92 | #define ADT7462_PIN26_MASK 0x0C /* cfg2 */ | ||
| 93 | #define ADT7462_PIN26_SHIFT 2 | ||
| 94 | #define ADT7462_PIN25_MASK 0x30 | ||
| 95 | #define ADT7462_PIN25_SHIFT 4 | ||
| 96 | #define ADT7462_PIN24_MASK 0xC0 | ||
| 97 | #define ADT7462_PIN24_SHIFT 6 | ||
| 98 | #define ADT7462_PIN26_VOLT_INPUT 0x08 | ||
| 99 | #define ADT7462_PIN25_VOLT_INPUT 0x20 | ||
| 100 | #define ADT7462_PIN28_SHIFT 6 /* cfg3 */ | ||
| 101 | #define ADT7462_PIN28_VOLT 0x5 | ||
| 102 | |||
| 103 | #define ADT7462_REG_ALARM1 0xB8 | ||
| 104 | #define ADT7462_LT_ALARM 0x02 | ||
| 105 | #define ADT7462_R1T_ALARM 0x04 | ||
| 106 | #define ADT7462_R2T_ALARM 0x08 | ||
| 107 | #define ADT7462_R3T_ALARM 0x10 | ||
| 108 | #define ADT7462_REG_ALARM2 0xBB | ||
| 109 | #define ADT7462_V0_ALARM 0x01 | ||
| 110 | #define ADT7462_V1_ALARM 0x02 | ||
| 111 | #define ADT7462_V2_ALARM 0x04 | ||
| 112 | #define ADT7462_V3_ALARM 0x08 | ||
| 113 | #define ADT7462_V4_ALARM 0x10 | ||
| 114 | #define ADT7462_V5_ALARM 0x20 | ||
| 115 | #define ADT7462_V6_ALARM 0x40 | ||
| 116 | #define ADT7462_V7_ALARM 0x80 | ||
| 117 | #define ADT7462_REG_ALARM3 0xBC | ||
| 118 | #define ADT7462_V8_ALARM 0x08 | ||
| 119 | #define ADT7462_V9_ALARM 0x10 | ||
| 120 | #define ADT7462_V10_ALARM 0x20 | ||
| 121 | #define ADT7462_V11_ALARM 0x40 | ||
| 122 | #define ADT7462_V12_ALARM 0x80 | ||
| 123 | #define ADT7462_REG_ALARM4 0xBD | ||
| 124 | #define ADT7462_F0_ALARM 0x01 | ||
| 125 | #define ADT7462_F1_ALARM 0x02 | ||
| 126 | #define ADT7462_F2_ALARM 0x04 | ||
| 127 | #define ADT7462_F3_ALARM 0x08 | ||
| 128 | #define ADT7462_F4_ALARM 0x10 | ||
| 129 | #define ADT7462_F5_ALARM 0x20 | ||
| 130 | #define ADT7462_F6_ALARM 0x40 | ||
| 131 | #define ADT7462_F7_ALARM 0x80 | ||
| 132 | #define ADT7462_ALARM1 0x0000 | ||
| 133 | #define ADT7462_ALARM2 0x0100 | ||
| 134 | #define ADT7462_ALARM3 0x0200 | ||
| 135 | #define ADT7462_ALARM4 0x0300 | ||
| 136 | #define ADT7462_ALARM_REG_SHIFT 8 | ||
| 137 | #define ADT7462_ALARM_FLAG_MASK 0x0F | ||
| 138 | |||
| 139 | #define ADT7462_TEMP_COUNT 4 | ||
| 140 | #define ADT7462_TEMP_REG(x) (ADT7462_REG_TEMP_BASE_ADDR + (x * 2)) | ||
| 141 | #define ADT7462_TEMP_MIN_REG(x) (ADT7462_REG_MIN_TEMP_BASE_ADDR + (x)) | ||
| 142 | #define ADT7462_TEMP_MAX_REG(x) (ADT7462_REG_MAX_TEMP_BASE_ADDR + (x)) | ||
| 143 | #define TEMP_FRAC_OFFSET 6 | ||
| 144 | |||
| 145 | #define ADT7462_FAN_COUNT 8 | ||
| 146 | #define ADT7462_REG_FAN_MIN(x) (ADT7462_REG_FAN_MIN_BASE_ADDR + (x)) | ||
| 147 | |||
| 148 | #define ADT7462_PWM_COUNT 4 | ||
| 149 | #define ADT7462_REG_PWM(x) (ADT7462_REG_PWM_BASE_ADDR + (x)) | ||
| 150 | #define ADT7462_REG_PWM_MIN(x) (ADT7462_REG_PWM_MIN_BASE_ADDR + (x)) | ||
| 151 | #define ADT7462_REG_PWM_TMIN(x) \ | ||
| 152 | (ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR + (x)) | ||
| 153 | #define ADT7462_REG_PWM_TRANGE(x) \ | ||
| 154 | (ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR + (x)) | ||
| 155 | |||
| 156 | #define ADT7462_PIN_CFG_REG_COUNT 4 | ||
| 157 | #define ADT7462_REG_PIN_CFG(x) (ADT7462_REG_PIN_CFG_BASE_ADDR + (x)) | ||
| 158 | #define ADT7462_REG_PWM_CFG(x) (ADT7462_REG_PWM_CFG_BASE_ADDR + (x)) | ||
| 159 | |||
| 160 | #define ADT7462_ALARM_REG_COUNT 4 | ||
| 161 | |||
| 162 | /* | ||
| 163 | * The chip can measure 13 different voltage sources: | ||
| 164 | * | ||
| 165 | * 1. +12V1 (pin 7) | ||
| 166 | * 2. Vccp1/+2.5V/+1.8V/+1.5V (pin 23) | ||
| 167 | * 3. +12V3 (pin 22) | ||
| 168 | * 4. +5V (pin 21) | ||
| 169 | * 5. +1.25V/+0.9V (pin 19) | ||
| 170 | * 6. +2.5V/+1.8V (pin 15) | ||
| 171 | * 7. +3.3v (pin 13) | ||
| 172 | * 8. +12V2 (pin 8) | ||
| 173 | * 9. Vbatt/FSB_Vtt (pin 26) | ||
| 174 | * A. +3.3V/+1.2V1 (pin 25) | ||
| 175 | * B. Vccp2/+2.5V/+1.8V/+1.5V (pin 24) | ||
| 176 | * C. +1.5V ICH (only if BOTH pin 28/29 are set to +1.5V) | ||
| 177 | * D. +1.5V 3GPIO (only if BOTH pin 28/29 are set to +1.5V) | ||
| 178 | * | ||
| 179 | * Each of these 13 has a factor to convert raw to voltage. Even better, | ||
| 180 | * the pins can be connected to other sensors (tach/gpio/hot/etc), which | ||
| 181 | * makes the bookkeeping tricky. | ||
| 182 | * | ||
| 183 | * Some, but not all, of these voltages have low/high limits. | ||
| 184 | */ | ||
| 185 | #define ADT7462_VOLT_COUNT 12 | ||
| 186 | |||
| 187 | #define ADT7462_VENDOR 0x41 | ||
| 188 | #define ADT7462_DEVICE 0x62 | ||
| 189 | /* datasheet only mentions a revision 4 */ | ||
| 190 | #define ADT7462_REVISION 0x04 | ||
| 191 | |||
| 192 | /* How often do we reread sensors values? (In jiffies) */ | ||
| 193 | #define SENSOR_REFRESH_INTERVAL (2 * HZ) | ||
| 194 | |||
| 195 | /* How often do we reread sensor limit values? (In jiffies) */ | ||
| 196 | #define LIMIT_REFRESH_INTERVAL (60 * HZ) | ||
| 197 | |||
| 198 | /* datasheet says to divide this number by the fan reading to get fan rpm */ | ||
| 199 | #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) | ||
| 200 | #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM | ||
| 201 | #define FAN_PERIOD_INVALID 65535 | ||
| 202 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | ||
| 203 | |||
| 204 | #define MASK_AND_SHIFT(value, prefix) \ | ||
| 205 | (((value) & prefix##_MASK) >> prefix##_SHIFT) | ||
| 206 | |||
| 207 | #define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) | ||
| 208 | |||
| 209 | struct adt7462_data { | ||
| 210 | struct device *hwmon_dev; | ||
| 211 | struct attribute_group attrs; | ||
| 212 | struct mutex lock; | ||
| 213 | char sensors_valid; | ||
| 214 | char limits_valid; | ||
| 215 | unsigned long sensors_last_updated; /* In jiffies */ | ||
| 216 | unsigned long limits_last_updated; /* In jiffies */ | ||
| 217 | |||
| 218 | u8 temp[ADT7462_TEMP_COUNT]; | ||
| 219 | /* bits 6-7 are quarter pieces of temp */ | ||
| 220 | u8 temp_frac[ADT7462_TEMP_COUNT]; | ||
| 221 | u8 temp_min[ADT7462_TEMP_COUNT]; | ||
| 222 | u8 temp_max[ADT7462_TEMP_COUNT]; | ||
| 223 | u16 fan[ADT7462_FAN_COUNT]; | ||
| 224 | u8 fan_enabled; | ||
| 225 | u8 fan_min[ADT7462_FAN_COUNT]; | ||
| 226 | u8 cfg2; | ||
| 227 | u8 pwm[ADT7462_PWM_COUNT]; | ||
| 228 | u8 pin_cfg[ADT7462_PIN_CFG_REG_COUNT]; | ||
| 229 | u8 voltages[ADT7462_VOLT_COUNT]; | ||
| 230 | u8 volt_max[ADT7462_VOLT_COUNT]; | ||
| 231 | u8 volt_min[ADT7462_VOLT_COUNT]; | ||
| 232 | u8 pwm_min[ADT7462_PWM_COUNT]; | ||
| 233 | u8 pwm_tmin[ADT7462_PWM_COUNT]; | ||
| 234 | u8 pwm_trange[ADT7462_PWM_COUNT]; | ||
| 235 | u8 pwm_max; /* only one per chip */ | ||
| 236 | u8 pwm_cfg[ADT7462_PWM_COUNT]; | ||
| 237 | u8 alarms[ADT7462_ALARM_REG_COUNT]; | ||
| 238 | }; | ||
| 239 | |||
| 240 | static int adt7462_probe(struct i2c_client *client, | ||
| 241 | const struct i2c_device_id *id); | ||
| 242 | static int adt7462_detect(struct i2c_client *client, int kind, | ||
| 243 | struct i2c_board_info *info); | ||
| 244 | static int adt7462_remove(struct i2c_client *client); | ||
| 245 | |||
| 246 | static const struct i2c_device_id adt7462_id[] = { | ||
| 247 | { "adt7462", adt7462 }, | ||
| 248 | { } | ||
| 249 | }; | ||
| 250 | MODULE_DEVICE_TABLE(i2c, adt7462_id); | ||
| 251 | |||
| 252 | static struct i2c_driver adt7462_driver = { | ||
| 253 | .class = I2C_CLASS_HWMON, | ||
| 254 | .driver = { | ||
| 255 | .name = "adt7462", | ||
| 256 | }, | ||
| 257 | .probe = adt7462_probe, | ||
| 258 | .remove = adt7462_remove, | ||
| 259 | .id_table = adt7462_id, | ||
| 260 | .detect = adt7462_detect, | ||
| 261 | .address_data = &addr_data, | ||
| 262 | }; | ||
| 263 | |||
| 264 | /* | ||
| 265 | * 16-bit registers on the ADT7462 are low-byte first. The data sheet says | ||
| 266 | * that the low byte must be read before the high byte. | ||
| 267 | */ | ||
| 268 | static inline int adt7462_read_word_data(struct i2c_client *client, u8 reg) | ||
| 269 | { | ||
| 270 | u16 foo; | ||
| 271 | foo = i2c_smbus_read_byte_data(client, reg); | ||
| 272 | foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8); | ||
| 273 | return foo; | ||
| 274 | } | ||
| 275 | |||
| 276 | /* For some reason these registers are not contiguous. */ | ||
| 277 | static int ADT7462_REG_FAN(int fan) | ||
| 278 | { | ||
| 279 | if (fan < 4) | ||
| 280 | return ADT7462_REG_FAN_BASE_ADDR + (2 * fan); | ||
| 281 | return ADT7462_REG_FAN2_BASE_ADDR + (2 * (fan - 4)); | ||
| 282 | } | ||
| 283 | |||
| 284 | /* Voltage registers are scattered everywhere */ | ||
| 285 | static int ADT7462_REG_VOLT_MAX(struct adt7462_data *data, int which) | ||
| 286 | { | ||
| 287 | switch (which) { | ||
| 288 | case 0: | ||
| 289 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
| 290 | return 0x7C; | ||
| 291 | break; | ||
| 292 | case 1: | ||
| 293 | return 0x69; | ||
| 294 | case 2: | ||
| 295 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
| 296 | return 0x7F; | ||
| 297 | break; | ||
| 298 | case 3: | ||
| 299 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
| 300 | return 0x7E; | ||
| 301 | break; | ||
| 302 | case 4: | ||
| 303 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) | ||
| 304 | return 0x4B; | ||
| 305 | break; | ||
| 306 | case 5: | ||
| 307 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) | ||
| 308 | return 0x49; | ||
| 309 | break; | ||
| 310 | case 6: | ||
| 311 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
| 312 | return 0x68; | ||
| 313 | break; | ||
| 314 | case 7: | ||
| 315 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
| 316 | return 0x7D; | ||
| 317 | break; | ||
| 318 | case 8: | ||
| 319 | if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) | ||
| 320 | return 0x6C; | ||
| 321 | break; | ||
| 322 | case 9: | ||
| 323 | if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) | ||
| 324 | return 0x6B; | ||
| 325 | break; | ||
| 326 | case 10: | ||
| 327 | return 0x6A; | ||
| 328 | case 11: | ||
| 329 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
| 330 | ADT7462_PIN28_VOLT && | ||
| 331 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
| 332 | return 0x50; | ||
| 333 | break; | ||
| 334 | case 12: | ||
| 335 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
| 336 | ADT7462_PIN28_VOLT && | ||
| 337 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
| 338 | return 0x4C; | ||
| 339 | break; | ||
| 340 | } | ||
| 341 | return -ENODEV; | ||
| 342 | } | ||
| 343 | |||
| 344 | static int ADT7462_REG_VOLT_MIN(struct adt7462_data *data, int which) | ||
| 345 | { | ||
| 346 | switch (which) { | ||
| 347 | case 0: | ||
| 348 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
| 349 | return 0x6D; | ||
| 350 | break; | ||
| 351 | case 1: | ||
| 352 | return 0x72; | ||
| 353 | case 2: | ||
| 354 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
| 355 | return 0x6F; | ||
| 356 | break; | ||
| 357 | case 3: | ||
| 358 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
| 359 | return 0x71; | ||
| 360 | break; | ||
| 361 | case 4: | ||
| 362 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) | ||
| 363 | return 0x47; | ||
| 364 | break; | ||
| 365 | case 5: | ||
| 366 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) | ||
| 367 | return 0x45; | ||
| 368 | break; | ||
| 369 | case 6: | ||
| 370 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
| 371 | return 0x70; | ||
| 372 | break; | ||
| 373 | case 7: | ||
| 374 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
| 375 | return 0x6E; | ||
| 376 | break; | ||
| 377 | case 8: | ||
| 378 | if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) | ||
| 379 | return 0x75; | ||
| 380 | break; | ||
| 381 | case 9: | ||
| 382 | if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) | ||
| 383 | return 0x74; | ||
| 384 | break; | ||
| 385 | case 10: | ||
| 386 | return 0x73; | ||
| 387 | case 11: | ||
| 388 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
| 389 | ADT7462_PIN28_VOLT && | ||
| 390 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
| 391 | return 0x76; | ||
| 392 | break; | ||
| 393 | case 12: | ||
| 394 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
| 395 | ADT7462_PIN28_VOLT && | ||
| 396 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
| 397 | return 0x77; | ||
| 398 | break; | ||
| 399 | } | ||
| 400 | return -ENODEV; | ||
| 401 | } | ||
| 402 | |||
| 403 | static int ADT7462_REG_VOLT(struct adt7462_data *data, int which) | ||
| 404 | { | ||
| 405 | switch (which) { | ||
| 406 | case 0: | ||
| 407 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
| 408 | return 0xA3; | ||
| 409 | break; | ||
| 410 | case 1: | ||
| 411 | return 0x90; | ||
| 412 | case 2: | ||
| 413 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
| 414 | return 0xA9; | ||
| 415 | break; | ||
| 416 | case 3: | ||
| 417 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
| 418 | return 0xA7; | ||
| 419 | break; | ||
| 420 | case 4: | ||
| 421 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) | ||
| 422 | return 0x8F; | ||
| 423 | break; | ||
| 424 | case 5: | ||
| 425 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) | ||
| 426 | return 0x8B; | ||
| 427 | break; | ||
| 428 | case 6: | ||
| 429 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
| 430 | return 0x96; | ||
| 431 | break; | ||
| 432 | case 7: | ||
| 433 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
| 434 | return 0xA5; | ||
| 435 | break; | ||
| 436 | case 8: | ||
| 437 | if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) | ||
| 438 | return 0x93; | ||
| 439 | break; | ||
| 440 | case 9: | ||
| 441 | if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) | ||
| 442 | return 0x92; | ||
| 443 | break; | ||
| 444 | case 10: | ||
| 445 | return 0x91; | ||
| 446 | case 11: | ||
| 447 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
| 448 | ADT7462_PIN28_VOLT && | ||
| 449 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
| 450 | return 0x94; | ||
| 451 | break; | ||
| 452 | case 12: | ||
| 453 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
| 454 | ADT7462_PIN28_VOLT && | ||
| 455 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
| 456 | return 0x95; | ||
| 457 | break; | ||
| 458 | } | ||
| 459 | return -ENODEV; | ||
| 460 | } | ||
| 461 | |||
| 462 | /* Provide labels for sysfs */ | ||
| 463 | static const char *voltage_label(struct adt7462_data *data, int which) | ||
| 464 | { | ||
| 465 | switch (which) { | ||
| 466 | case 0: | ||
| 467 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
| 468 | return "+12V1"; | ||
| 469 | break; | ||
| 470 | case 1: | ||
| 471 | switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { | ||
| 472 | case 0: | ||
| 473 | return "Vccp1"; | ||
| 474 | case 1: | ||
| 475 | return "+2.5V"; | ||
| 476 | case 2: | ||
| 477 | return "+1.8V"; | ||
| 478 | case 3: | ||
| 479 | return "+1.5V"; | ||
| 480 | } | ||
| 481 | case 2: | ||
| 482 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
| 483 | return "+12V3"; | ||
| 484 | break; | ||
| 485 | case 3: | ||
| 486 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
| 487 | return "+5V"; | ||
| 488 | break; | ||
| 489 | case 4: | ||
| 490 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { | ||
| 491 | if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) | ||
| 492 | return "+0.9V"; | ||
| 493 | return "+1.25V"; | ||
| 494 | } | ||
| 495 | break; | ||
| 496 | case 5: | ||
| 497 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { | ||
| 498 | if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) | ||
| 499 | return "+1.8V"; | ||
| 500 | return "+2.5V"; | ||
| 501 | } | ||
| 502 | break; | ||
| 503 | case 6: | ||
| 504 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
| 505 | return "+3.3V"; | ||
| 506 | break; | ||
| 507 | case 7: | ||
| 508 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
| 509 | return "+12V2"; | ||
| 510 | break; | ||
| 511 | case 8: | ||
| 512 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { | ||
| 513 | case 0: | ||
| 514 | return "Vbatt"; | ||
| 515 | case 1: | ||
| 516 | return "FSB_Vtt"; | ||
| 517 | } | ||
| 518 | break; | ||
| 519 | case 9: | ||
| 520 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { | ||
| 521 | case 0: | ||
| 522 | return "+3.3V"; | ||
| 523 | case 1: | ||
| 524 | return "+1.2V1"; | ||
| 525 | } | ||
| 526 | break; | ||
| 527 | case 10: | ||
| 528 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { | ||
| 529 | case 0: | ||
| 530 | return "Vccp2"; | ||
| 531 | case 1: | ||
| 532 | return "+2.5V"; | ||
| 533 | case 2: | ||
| 534 | return "+1.8V"; | ||
| 535 | case 3: | ||
| 536 | return "+1.5"; | ||
| 537 | } | ||
| 538 | case 11: | ||
| 539 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
| 540 | ADT7462_PIN28_VOLT && | ||
| 541 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
| 542 | return "+1.5V ICH"; | ||
| 543 | break; | ||
| 544 | case 12: | ||
| 545 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
| 546 | ADT7462_PIN28_VOLT && | ||
| 547 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
| 548 | return "+1.5V 3GPIO"; | ||
| 549 | break; | ||
| 550 | } | ||
| 551 | return "N/A"; | ||
| 552 | } | ||
| 553 | |||
| 554 | /* Multipliers are actually in uV, not mV. */ | ||
| 555 | static int voltage_multiplier(struct adt7462_data *data, int which) | ||
| 556 | { | ||
| 557 | switch (which) { | ||
| 558 | case 0: | ||
| 559 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
| 560 | return 62500; | ||
| 561 | break; | ||
| 562 | case 1: | ||
| 563 | switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { | ||
| 564 | case 0: | ||
| 565 | if (data->pin_cfg[0] & ADT7462_VID_INPUT) | ||
| 566 | return 12500; | ||
| 567 | return 6250; | ||
| 568 | case 1: | ||
| 569 | return 13000; | ||
| 570 | case 2: | ||
| 571 | return 9400; | ||
| 572 | case 3: | ||
| 573 | return 7800; | ||
| 574 | } | ||
| 575 | case 2: | ||
| 576 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
| 577 | return 62500; | ||
| 578 | break; | ||
| 579 | case 3: | ||
| 580 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
| 581 | return 26000; | ||
| 582 | break; | ||
| 583 | case 4: | ||
| 584 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { | ||
| 585 | if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) | ||
| 586 | return 4690; | ||
| 587 | return 6500; | ||
| 588 | } | ||
| 589 | break; | ||
| 590 | case 5: | ||
| 591 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { | ||
| 592 | if (data->pin_cfg[1] & ADT7462_PIN15_INPUT) | ||
| 593 | return 9400; | ||
| 594 | return 13000; | ||
| 595 | } | ||
| 596 | break; | ||
| 597 | case 6: | ||
| 598 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
| 599 | return 17200; | ||
| 600 | break; | ||
| 601 | case 7: | ||
| 602 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
| 603 | return 62500; | ||
| 604 | break; | ||
| 605 | case 8: | ||
| 606 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { | ||
| 607 | case 0: | ||
| 608 | return 15600; | ||
| 609 | case 1: | ||
| 610 | return 6250; | ||
| 611 | } | ||
| 612 | break; | ||
| 613 | case 9: | ||
| 614 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { | ||
| 615 | case 0: | ||
| 616 | return 17200; | ||
| 617 | case 1: | ||
| 618 | return 6250; | ||
| 619 | } | ||
| 620 | break; | ||
| 621 | case 10: | ||
| 622 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { | ||
| 623 | case 0: | ||
| 624 | return 6250; | ||
| 625 | case 1: | ||
| 626 | return 13000; | ||
| 627 | case 2: | ||
| 628 | return 9400; | ||
| 629 | case 3: | ||
| 630 | return 7800; | ||
| 631 | } | ||
| 632 | case 11: | ||
| 633 | case 12: | ||
| 634 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
| 635 | ADT7462_PIN28_VOLT && | ||
| 636 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
| 637 | return 7800; | ||
| 638 | } | ||
| 639 | return 0; | ||
| 640 | } | ||
| 641 | |||
| 642 | static int temp_enabled(struct adt7462_data *data, int which) | ||
| 643 | { | ||
| 644 | switch (which) { | ||
| 645 | case 0: | ||
| 646 | case 2: | ||
| 647 | return 1; | ||
| 648 | case 1: | ||
| 649 | if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) | ||
| 650 | return 1; | ||
| 651 | break; | ||
| 652 | case 3: | ||
| 653 | if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) | ||
| 654 | return 1; | ||
| 655 | break; | ||
| 656 | } | ||
| 657 | return 0; | ||
| 658 | } | ||
| 659 | |||
| 660 | static const char *temp_label(struct adt7462_data *data, int which) | ||
| 661 | { | ||
| 662 | switch (which) { | ||
| 663 | case 0: | ||
| 664 | return "local"; | ||
| 665 | case 1: | ||
| 666 | if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) | ||
| 667 | return "remote1"; | ||
| 668 | break; | ||
| 669 | case 2: | ||
| 670 | return "remote2"; | ||
| 671 | case 3: | ||
| 672 | if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) | ||
| 673 | return "remote3"; | ||
| 674 | break; | ||
| 675 | } | ||
| 676 | return "N/A"; | ||
| 677 | } | ||
| 678 | |||
| 679 | /* Map Trange register values to mC */ | ||
| 680 | #define NUM_TRANGE_VALUES 16 | ||
| 681 | static const int trange_values[NUM_TRANGE_VALUES] = { | ||
| 682 | 2000, | ||
| 683 | 2500, | ||
| 684 | 3300, | ||
| 685 | 4000, | ||
| 686 | 5000, | ||
| 687 | 6700, | ||
| 688 | 8000, | ||
| 689 | 10000, | ||
| 690 | 13300, | ||
| 691 | 16000, | ||
| 692 | 20000, | ||
| 693 | 26700, | ||
| 694 | 32000, | ||
| 695 | 40000, | ||
| 696 | 53300, | ||
| 697 | 80000 | ||
| 698 | }; | ||
| 699 | |||
| 700 | static int find_trange_value(int trange) | ||
| 701 | { | ||
| 702 | int i; | ||
| 703 | |||
| 704 | for (i = 0; i < NUM_TRANGE_VALUES; i++) | ||
| 705 | if (trange_values[i] == trange) | ||
| 706 | return i; | ||
| 707 | |||
| 708 | return -ENODEV; | ||
| 709 | } | ||
| 710 | |||
| 711 | static struct adt7462_data *adt7462_update_device(struct device *dev) | ||
| 712 | { | ||
| 713 | struct i2c_client *client = to_i2c_client(dev); | ||
| 714 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 715 | unsigned long local_jiffies = jiffies; | ||
| 716 | int i; | ||
| 717 | |||
| 718 | mutex_lock(&data->lock); | ||
| 719 | if (time_before(local_jiffies, data->sensors_last_updated + | ||
| 720 | SENSOR_REFRESH_INTERVAL) | ||
| 721 | && data->sensors_valid) | ||
| 722 | goto no_sensor_update; | ||
| 723 | |||
| 724 | for (i = 0; i < ADT7462_TEMP_COUNT; i++) { | ||
| 725 | /* | ||
| 726 | * Reading the fractional register locks the integral | ||
| 727 | * register until both have been read. | ||
| 728 | */ | ||
| 729 | data->temp_frac[i] = i2c_smbus_read_byte_data(client, | ||
| 730 | ADT7462_TEMP_REG(i)); | ||
| 731 | data->temp[i] = i2c_smbus_read_byte_data(client, | ||
| 732 | ADT7462_TEMP_REG(i) + 1); | ||
| 733 | } | ||
| 734 | |||
| 735 | for (i = 0; i < ADT7462_FAN_COUNT; i++) | ||
| 736 | data->fan[i] = adt7462_read_word_data(client, | ||
| 737 | ADT7462_REG_FAN(i)); | ||
| 738 | |||
| 739 | data->fan_enabled = i2c_smbus_read_byte_data(client, | ||
| 740 | ADT7462_REG_FAN_ENABLE); | ||
| 741 | |||
| 742 | for (i = 0; i < ADT7462_PWM_COUNT; i++) | ||
| 743 | data->pwm[i] = i2c_smbus_read_byte_data(client, | ||
| 744 | ADT7462_REG_PWM(i)); | ||
| 745 | |||
| 746 | for (i = 0; i < ADT7462_PIN_CFG_REG_COUNT; i++) | ||
| 747 | data->pin_cfg[i] = i2c_smbus_read_byte_data(client, | ||
| 748 | ADT7462_REG_PIN_CFG(i)); | ||
| 749 | |||
| 750 | for (i = 0; i < ADT7462_VOLT_COUNT; i++) { | ||
| 751 | int reg = ADT7462_REG_VOLT(data, i); | ||
| 752 | if (!reg) | ||
| 753 | data->voltages[i] = 0; | ||
| 754 | else | ||
| 755 | data->voltages[i] = i2c_smbus_read_byte_data(client, | ||
| 756 | reg); | ||
| 757 | } | ||
| 758 | |||
| 759 | data->alarms[0] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM1); | ||
| 760 | data->alarms[1] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM2); | ||
| 761 | data->alarms[2] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM3); | ||
| 762 | data->alarms[3] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM4); | ||
| 763 | |||
| 764 | data->sensors_last_updated = local_jiffies; | ||
| 765 | data->sensors_valid = 1; | ||
| 766 | |||
| 767 | no_sensor_update: | ||
| 768 | if (time_before(local_jiffies, data->limits_last_updated + | ||
| 769 | LIMIT_REFRESH_INTERVAL) | ||
| 770 | && data->limits_valid) | ||
| 771 | goto out; | ||
| 772 | |||
| 773 | for (i = 0; i < ADT7462_TEMP_COUNT; i++) { | ||
| 774 | data->temp_min[i] = i2c_smbus_read_byte_data(client, | ||
| 775 | ADT7462_TEMP_MIN_REG(i)); | ||
| 776 | data->temp_max[i] = i2c_smbus_read_byte_data(client, | ||
| 777 | ADT7462_TEMP_MAX_REG(i)); | ||
| 778 | } | ||
| 779 | |||
| 780 | for (i = 0; i < ADT7462_FAN_COUNT; i++) | ||
| 781 | data->fan_min[i] = i2c_smbus_read_byte_data(client, | ||
| 782 | ADT7462_REG_FAN_MIN(i)); | ||
| 783 | |||
| 784 | for (i = 0; i < ADT7462_VOLT_COUNT; i++) { | ||
| 785 | int reg = ADT7462_REG_VOLT_MAX(data, i); | ||
| 786 | data->volt_max[i] = | ||
| 787 | (reg ? i2c_smbus_read_byte_data(client, reg) : 0); | ||
| 788 | |||
| 789 | reg = ADT7462_REG_VOLT_MIN(data, i); | ||
| 790 | data->volt_min[i] = | ||
| 791 | (reg ? i2c_smbus_read_byte_data(client, reg) : 0); | ||
| 792 | } | ||
| 793 | |||
| 794 | for (i = 0; i < ADT7462_PWM_COUNT; i++) { | ||
| 795 | data->pwm_min[i] = i2c_smbus_read_byte_data(client, | ||
| 796 | ADT7462_REG_PWM_MIN(i)); | ||
| 797 | data->pwm_tmin[i] = i2c_smbus_read_byte_data(client, | ||
| 798 | ADT7462_REG_PWM_TMIN(i)); | ||
| 799 | data->pwm_trange[i] = i2c_smbus_read_byte_data(client, | ||
| 800 | ADT7462_REG_PWM_TRANGE(i)); | ||
| 801 | data->pwm_cfg[i] = i2c_smbus_read_byte_data(client, | ||
| 802 | ADT7462_REG_PWM_CFG(i)); | ||
| 803 | } | ||
| 804 | |||
| 805 | data->pwm_max = i2c_smbus_read_byte_data(client, ADT7462_REG_PWM_MAX); | ||
| 806 | |||
| 807 | data->cfg2 = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); | ||
| 808 | |||
| 809 | data->limits_last_updated = local_jiffies; | ||
| 810 | data->limits_valid = 1; | ||
| 811 | |||
| 812 | out: | ||
| 813 | mutex_unlock(&data->lock); | ||
| 814 | return data; | ||
| 815 | } | ||
| 816 | |||
| 817 | static ssize_t show_temp_min(struct device *dev, | ||
| 818 | struct device_attribute *devattr, | ||
| 819 | char *buf) | ||
| 820 | { | ||
| 821 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 822 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 823 | |||
| 824 | if (!temp_enabled(data, attr->index)) | ||
| 825 | return sprintf(buf, "0\n"); | ||
| 826 | |||
| 827 | return sprintf(buf, "%d\n", 1000 * (data->temp_min[attr->index] - 64)); | ||
| 828 | } | ||
| 829 | |||
| 830 | static ssize_t set_temp_min(struct device *dev, | ||
| 831 | struct device_attribute *devattr, | ||
| 832 | const char *buf, | ||
| 833 | size_t count) | ||
| 834 | { | ||
| 835 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 836 | struct i2c_client *client = to_i2c_client(dev); | ||
| 837 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 838 | long temp; | ||
| 839 | |||
| 840 | if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) | ||
| 841 | return -EINVAL; | ||
| 842 | |||
| 843 | temp = ROUND_DIV(temp, 1000) + 64; | ||
| 844 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 845 | |||
| 846 | mutex_lock(&data->lock); | ||
| 847 | data->temp_min[attr->index] = temp; | ||
| 848 | i2c_smbus_write_byte_data(client, ADT7462_TEMP_MIN_REG(attr->index), | ||
| 849 | temp); | ||
| 850 | mutex_unlock(&data->lock); | ||
| 851 | |||
| 852 | return count; | ||
| 853 | } | ||
| 854 | |||
| 855 | static ssize_t show_temp_max(struct device *dev, | ||
| 856 | struct device_attribute *devattr, | ||
| 857 | char *buf) | ||
| 858 | { | ||
| 859 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 860 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 861 | |||
| 862 | if (!temp_enabled(data, attr->index)) | ||
| 863 | return sprintf(buf, "0\n"); | ||
| 864 | |||
| 865 | return sprintf(buf, "%d\n", 1000 * (data->temp_max[attr->index] - 64)); | ||
| 866 | } | ||
| 867 | |||
| 868 | static ssize_t set_temp_max(struct device *dev, | ||
| 869 | struct device_attribute *devattr, | ||
| 870 | const char *buf, | ||
| 871 | size_t count) | ||
| 872 | { | ||
| 873 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 874 | struct i2c_client *client = to_i2c_client(dev); | ||
| 875 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 876 | long temp; | ||
| 877 | |||
| 878 | if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) | ||
| 879 | return -EINVAL; | ||
| 880 | |||
| 881 | temp = ROUND_DIV(temp, 1000) + 64; | ||
| 882 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 883 | |||
| 884 | mutex_lock(&data->lock); | ||
| 885 | data->temp_max[attr->index] = temp; | ||
| 886 | i2c_smbus_write_byte_data(client, ADT7462_TEMP_MAX_REG(attr->index), | ||
| 887 | temp); | ||
| 888 | mutex_unlock(&data->lock); | ||
| 889 | |||
| 890 | return count; | ||
| 891 | } | ||
| 892 | |||
| 893 | static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, | ||
| 894 | char *buf) | ||
| 895 | { | ||
| 896 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 897 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 898 | u8 frac = data->temp_frac[attr->index] >> TEMP_FRAC_OFFSET; | ||
| 899 | |||
| 900 | if (!temp_enabled(data, attr->index)) | ||
| 901 | return sprintf(buf, "0\n"); | ||
| 902 | |||
| 903 | return sprintf(buf, "%d\n", 1000 * (data->temp[attr->index] - 64) + | ||
| 904 | 250 * frac); | ||
| 905 | } | ||
| 906 | |||
| 907 | static ssize_t show_temp_label(struct device *dev, | ||
| 908 | struct device_attribute *devattr, | ||
| 909 | char *buf) | ||
| 910 | { | ||
| 911 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 912 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 913 | |||
| 914 | return sprintf(buf, "%s\n", temp_label(data, attr->index)); | ||
| 915 | } | ||
| 916 | |||
| 917 | static ssize_t show_volt_max(struct device *dev, | ||
| 918 | struct device_attribute *devattr, | ||
| 919 | char *buf) | ||
| 920 | { | ||
| 921 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 922 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 923 | int x = voltage_multiplier(data, attr->index); | ||
| 924 | |||
| 925 | x *= data->volt_max[attr->index]; | ||
| 926 | x /= 1000; /* convert from uV to mV */ | ||
| 927 | |||
| 928 | return sprintf(buf, "%d\n", x); | ||
| 929 | } | ||
| 930 | |||
| 931 | static ssize_t set_volt_max(struct device *dev, | ||
| 932 | struct device_attribute *devattr, | ||
| 933 | const char *buf, | ||
| 934 | size_t count) | ||
| 935 | { | ||
| 936 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 937 | struct i2c_client *client = to_i2c_client(dev); | ||
| 938 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 939 | int x = voltage_multiplier(data, attr->index); | ||
| 940 | long temp; | ||
| 941 | |||
| 942 | if (strict_strtol(buf, 10, &temp) || !x) | ||
| 943 | return -EINVAL; | ||
| 944 | |||
| 945 | temp *= 1000; /* convert mV to uV */ | ||
| 946 | temp = ROUND_DIV(temp, x); | ||
| 947 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 948 | |||
| 949 | mutex_lock(&data->lock); | ||
| 950 | data->volt_max[attr->index] = temp; | ||
| 951 | i2c_smbus_write_byte_data(client, | ||
| 952 | ADT7462_REG_VOLT_MAX(data, attr->index), | ||
| 953 | temp); | ||
| 954 | mutex_unlock(&data->lock); | ||
| 955 | |||
| 956 | return count; | ||
| 957 | } | ||
| 958 | |||
| 959 | static ssize_t show_volt_min(struct device *dev, | ||
| 960 | struct device_attribute *devattr, | ||
| 961 | char *buf) | ||
| 962 | { | ||
| 963 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 964 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 965 | int x = voltage_multiplier(data, attr->index); | ||
| 966 | |||
| 967 | x *= data->volt_min[attr->index]; | ||
| 968 | x /= 1000; /* convert from uV to mV */ | ||
| 969 | |||
| 970 | return sprintf(buf, "%d\n", x); | ||
| 971 | } | ||
| 972 | |||
| 973 | static ssize_t set_volt_min(struct device *dev, | ||
| 974 | struct device_attribute *devattr, | ||
| 975 | const char *buf, | ||
| 976 | size_t count) | ||
| 977 | { | ||
| 978 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 979 | struct i2c_client *client = to_i2c_client(dev); | ||
| 980 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 981 | int x = voltage_multiplier(data, attr->index); | ||
| 982 | long temp; | ||
| 983 | |||
| 984 | if (strict_strtol(buf, 10, &temp) || !x) | ||
| 985 | return -EINVAL; | ||
| 986 | |||
| 987 | temp *= 1000; /* convert mV to uV */ | ||
| 988 | temp = ROUND_DIV(temp, x); | ||
| 989 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 990 | |||
| 991 | mutex_lock(&data->lock); | ||
| 992 | data->volt_min[attr->index] = temp; | ||
| 993 | i2c_smbus_write_byte_data(client, | ||
| 994 | ADT7462_REG_VOLT_MIN(data, attr->index), | ||
| 995 | temp); | ||
| 996 | mutex_unlock(&data->lock); | ||
| 997 | |||
| 998 | return count; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | static ssize_t show_voltage(struct device *dev, | ||
| 1002 | struct device_attribute *devattr, | ||
| 1003 | char *buf) | ||
| 1004 | { | ||
| 1005 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1006 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1007 | int x = voltage_multiplier(data, attr->index); | ||
| 1008 | |||
| 1009 | x *= data->voltages[attr->index]; | ||
| 1010 | x /= 1000; /* convert from uV to mV */ | ||
| 1011 | |||
| 1012 | return sprintf(buf, "%d\n", x); | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | static ssize_t show_voltage_label(struct device *dev, | ||
| 1016 | struct device_attribute *devattr, | ||
| 1017 | char *buf) | ||
| 1018 | { | ||
| 1019 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1020 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1021 | |||
| 1022 | return sprintf(buf, "%s\n", voltage_label(data, attr->index)); | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | static ssize_t show_alarm(struct device *dev, | ||
| 1026 | struct device_attribute *devattr, | ||
| 1027 | char *buf) | ||
| 1028 | { | ||
| 1029 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1030 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1031 | int reg = attr->index >> ADT7462_ALARM_REG_SHIFT; | ||
| 1032 | int mask = attr->index & ADT7462_ALARM_FLAG_MASK; | ||
| 1033 | |||
| 1034 | if (data->alarms[reg] & mask) | ||
| 1035 | return sprintf(buf, "1\n"); | ||
| 1036 | else | ||
| 1037 | return sprintf(buf, "0\n"); | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | static int fan_enabled(struct adt7462_data *data, int fan) | ||
| 1041 | { | ||
| 1042 | return data->fan_enabled & (1 << fan); | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | static ssize_t show_fan_min(struct device *dev, | ||
| 1046 | struct device_attribute *devattr, | ||
| 1047 | char *buf) | ||
| 1048 | { | ||
| 1049 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1050 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1051 | u16 temp; | ||
| 1052 | |||
| 1053 | /* Only the MSB of the min fan period is stored... */ | ||
| 1054 | temp = data->fan_min[attr->index]; | ||
| 1055 | temp <<= 8; | ||
| 1056 | |||
| 1057 | if (!fan_enabled(data, attr->index) || | ||
| 1058 | !FAN_DATA_VALID(temp)) | ||
| 1059 | return sprintf(buf, "0\n"); | ||
| 1060 | |||
| 1061 | return sprintf(buf, "%d\n", FAN_PERIOD_TO_RPM(temp)); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | static ssize_t set_fan_min(struct device *dev, | ||
| 1065 | struct device_attribute *devattr, | ||
| 1066 | const char *buf, size_t count) | ||
| 1067 | { | ||
| 1068 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1069 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1070 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1071 | long temp; | ||
| 1072 | |||
| 1073 | if (strict_strtol(buf, 10, &temp) || !temp || | ||
| 1074 | !fan_enabled(data, attr->index)) | ||
| 1075 | return -EINVAL; | ||
| 1076 | |||
| 1077 | temp = FAN_RPM_TO_PERIOD(temp); | ||
| 1078 | temp >>= 8; | ||
| 1079 | temp = SENSORS_LIMIT(temp, 1, 255); | ||
| 1080 | |||
| 1081 | mutex_lock(&data->lock); | ||
| 1082 | data->fan_min[attr->index] = temp; | ||
| 1083 | i2c_smbus_write_byte_data(client, ADT7462_REG_FAN_MIN(attr->index), | ||
| 1084 | temp); | ||
| 1085 | mutex_unlock(&data->lock); | ||
| 1086 | |||
| 1087 | return count; | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, | ||
| 1091 | char *buf) | ||
| 1092 | { | ||
| 1093 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1094 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1095 | |||
| 1096 | if (!fan_enabled(data, attr->index) || | ||
| 1097 | !FAN_DATA_VALID(data->fan[attr->index])) | ||
| 1098 | return sprintf(buf, "0\n"); | ||
| 1099 | |||
| 1100 | return sprintf(buf, "%d\n", | ||
| 1101 | FAN_PERIOD_TO_RPM(data->fan[attr->index])); | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | static ssize_t show_force_pwm_max(struct device *dev, | ||
| 1105 | struct device_attribute *devattr, | ||
| 1106 | char *buf) | ||
| 1107 | { | ||
| 1108 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1109 | return sprintf(buf, "%d\n", (data->cfg2 & ADT7462_FSPD_MASK ? 1 : 0)); | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | static ssize_t set_force_pwm_max(struct device *dev, | ||
| 1113 | struct device_attribute *devattr, | ||
| 1114 | const char *buf, | ||
| 1115 | size_t count) | ||
| 1116 | { | ||
| 1117 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1118 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1119 | long temp; | ||
| 1120 | u8 reg; | ||
| 1121 | |||
| 1122 | if (strict_strtol(buf, 10, &temp)) | ||
| 1123 | return -EINVAL; | ||
| 1124 | |||
| 1125 | mutex_lock(&data->lock); | ||
| 1126 | reg = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); | ||
| 1127 | if (temp) | ||
| 1128 | reg |= ADT7462_FSPD_MASK; | ||
| 1129 | else | ||
| 1130 | reg &= ~ADT7462_FSPD_MASK; | ||
| 1131 | data->cfg2 = reg; | ||
| 1132 | i2c_smbus_write_byte_data(client, ADT7462_REG_CFG2, reg); | ||
| 1133 | mutex_unlock(&data->lock); | ||
| 1134 | |||
| 1135 | return count; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, | ||
| 1139 | char *buf) | ||
| 1140 | { | ||
| 1141 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1142 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1143 | return sprintf(buf, "%d\n", data->pwm[attr->index]); | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | ||
| 1147 | const char *buf, size_t count) | ||
| 1148 | { | ||
| 1149 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1150 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1151 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1152 | long temp; | ||
| 1153 | |||
| 1154 | if (strict_strtol(buf, 10, &temp)) | ||
| 1155 | return -EINVAL; | ||
| 1156 | |||
| 1157 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 1158 | |||
| 1159 | mutex_lock(&data->lock); | ||
| 1160 | data->pwm[attr->index] = temp; | ||
| 1161 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM(attr->index), temp); | ||
| 1162 | mutex_unlock(&data->lock); | ||
| 1163 | |||
| 1164 | return count; | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | static ssize_t show_pwm_max(struct device *dev, | ||
| 1168 | struct device_attribute *devattr, | ||
| 1169 | char *buf) | ||
| 1170 | { | ||
| 1171 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1172 | return sprintf(buf, "%d\n", data->pwm_max); | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | static ssize_t set_pwm_max(struct device *dev, | ||
| 1176 | struct device_attribute *devattr, | ||
| 1177 | const char *buf, | ||
| 1178 | size_t count) | ||
| 1179 | { | ||
| 1180 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1181 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1182 | long temp; | ||
| 1183 | |||
| 1184 | if (strict_strtol(buf, 10, &temp)) | ||
| 1185 | return -EINVAL; | ||
| 1186 | |||
| 1187 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 1188 | |||
| 1189 | mutex_lock(&data->lock); | ||
| 1190 | data->pwm_max = temp; | ||
| 1191 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MAX, temp); | ||
| 1192 | mutex_unlock(&data->lock); | ||
| 1193 | |||
| 1194 | return count; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | static ssize_t show_pwm_min(struct device *dev, | ||
| 1198 | struct device_attribute *devattr, | ||
| 1199 | char *buf) | ||
| 1200 | { | ||
| 1201 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1202 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1203 | return sprintf(buf, "%d\n", data->pwm_min[attr->index]); | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | static ssize_t set_pwm_min(struct device *dev, | ||
| 1207 | struct device_attribute *devattr, | ||
| 1208 | const char *buf, | ||
| 1209 | size_t count) | ||
| 1210 | { | ||
| 1211 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1212 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1213 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1214 | long temp; | ||
| 1215 | |||
| 1216 | if (strict_strtol(buf, 10, &temp)) | ||
| 1217 | return -EINVAL; | ||
| 1218 | |||
| 1219 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 1220 | |||
| 1221 | mutex_lock(&data->lock); | ||
| 1222 | data->pwm_min[attr->index] = temp; | ||
| 1223 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MIN(attr->index), | ||
| 1224 | temp); | ||
| 1225 | mutex_unlock(&data->lock); | ||
| 1226 | |||
| 1227 | return count; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | static ssize_t show_pwm_hyst(struct device *dev, | ||
| 1231 | struct device_attribute *devattr, | ||
| 1232 | char *buf) | ||
| 1233 | { | ||
| 1234 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1235 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1236 | return sprintf(buf, "%d\n", 1000 * | ||
| 1237 | (data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK)); | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | static ssize_t set_pwm_hyst(struct device *dev, | ||
| 1241 | struct device_attribute *devattr, | ||
| 1242 | const char *buf, | ||
| 1243 | size_t count) | ||
| 1244 | { | ||
| 1245 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1246 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1247 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1248 | long temp; | ||
| 1249 | |||
| 1250 | if (strict_strtol(buf, 10, &temp)) | ||
| 1251 | return -EINVAL; | ||
| 1252 | |||
| 1253 | temp = ROUND_DIV(temp, 1000); | ||
| 1254 | temp = SENSORS_LIMIT(temp, 0, 15); | ||
| 1255 | |||
| 1256 | /* package things up */ | ||
| 1257 | temp &= ADT7462_PWM_HYST_MASK; | ||
| 1258 | temp |= data->pwm_trange[attr->index] & ADT7462_PWM_RANGE_MASK; | ||
| 1259 | |||
| 1260 | mutex_lock(&data->lock); | ||
| 1261 | data->pwm_trange[attr->index] = temp; | ||
| 1262 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), | ||
| 1263 | temp); | ||
| 1264 | mutex_unlock(&data->lock); | ||
| 1265 | |||
| 1266 | return count; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | static ssize_t show_pwm_tmax(struct device *dev, | ||
| 1270 | struct device_attribute *devattr, | ||
| 1271 | char *buf) | ||
| 1272 | { | ||
| 1273 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1274 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1275 | |||
| 1276 | /* tmax = tmin + trange */ | ||
| 1277 | int trange = trange_values[data->pwm_trange[attr->index] >> | ||
| 1278 | ADT7462_PWM_RANGE_SHIFT]; | ||
| 1279 | int tmin = (data->pwm_tmin[attr->index] - 64) * 1000; | ||
| 1280 | |||
| 1281 | return sprintf(buf, "%d\n", tmin + trange); | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | static ssize_t set_pwm_tmax(struct device *dev, | ||
| 1285 | struct device_attribute *devattr, | ||
| 1286 | const char *buf, | ||
| 1287 | size_t count) | ||
| 1288 | { | ||
| 1289 | int temp; | ||
| 1290 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1291 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1292 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1293 | int tmin, trange_value; | ||
| 1294 | long trange; | ||
| 1295 | |||
| 1296 | if (strict_strtol(buf, 10, &trange)) | ||
| 1297 | return -EINVAL; | ||
| 1298 | |||
| 1299 | /* trange = tmax - tmin */ | ||
| 1300 | tmin = (data->pwm_tmin[attr->index] - 64) * 1000; | ||
| 1301 | trange_value = find_trange_value(trange - tmin); | ||
| 1302 | |||
| 1303 | if (trange_value < 0) | ||
| 1304 | return -EINVAL; | ||
| 1305 | |||
| 1306 | temp = trange_value << ADT7462_PWM_RANGE_SHIFT; | ||
| 1307 | temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK; | ||
| 1308 | |||
| 1309 | mutex_lock(&data->lock); | ||
| 1310 | data->pwm_trange[attr->index] = temp; | ||
| 1311 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), | ||
| 1312 | temp); | ||
| 1313 | mutex_unlock(&data->lock); | ||
| 1314 | |||
| 1315 | return count; | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | static ssize_t show_pwm_tmin(struct device *dev, | ||
| 1319 | struct device_attribute *devattr, | ||
| 1320 | char *buf) | ||
| 1321 | { | ||
| 1322 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1323 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1324 | return sprintf(buf, "%d\n", 1000 * (data->pwm_tmin[attr->index] - 64)); | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | static ssize_t set_pwm_tmin(struct device *dev, | ||
| 1328 | struct device_attribute *devattr, | ||
| 1329 | const char *buf, | ||
| 1330 | size_t count) | ||
| 1331 | { | ||
| 1332 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1333 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1334 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1335 | long temp; | ||
| 1336 | |||
| 1337 | if (strict_strtol(buf, 10, &temp)) | ||
| 1338 | return -EINVAL; | ||
| 1339 | |||
| 1340 | temp = ROUND_DIV(temp, 1000) + 64; | ||
| 1341 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 1342 | |||
| 1343 | mutex_lock(&data->lock); | ||
| 1344 | data->pwm_tmin[attr->index] = temp; | ||
| 1345 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TMIN(attr->index), | ||
| 1346 | temp); | ||
| 1347 | mutex_unlock(&data->lock); | ||
| 1348 | |||
| 1349 | return count; | ||
| 1350 | } | ||
| 1351 | |||
| 1352 | static ssize_t show_pwm_auto(struct device *dev, | ||
| 1353 | struct device_attribute *devattr, | ||
| 1354 | char *buf) | ||
| 1355 | { | ||
| 1356 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1357 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1358 | int cfg = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; | ||
| 1359 | |||
| 1360 | switch (cfg) { | ||
| 1361 | case 4: /* off */ | ||
| 1362 | return sprintf(buf, "0\n"); | ||
| 1363 | case 7: /* manual */ | ||
| 1364 | return sprintf(buf, "1\n"); | ||
| 1365 | default: /* automatic */ | ||
| 1366 | return sprintf(buf, "2\n"); | ||
| 1367 | } | ||
| 1368 | } | ||
| 1369 | |||
| 1370 | static void set_pwm_channel(struct i2c_client *client, | ||
| 1371 | struct adt7462_data *data, | ||
| 1372 | int which, | ||
| 1373 | int value) | ||
| 1374 | { | ||
| 1375 | int temp = data->pwm_cfg[which] & ~ADT7462_PWM_CHANNEL_MASK; | ||
| 1376 | temp |= value << ADT7462_PWM_CHANNEL_SHIFT; | ||
| 1377 | |||
| 1378 | mutex_lock(&data->lock); | ||
| 1379 | data->pwm_cfg[which] = temp; | ||
| 1380 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_CFG(which), temp); | ||
| 1381 | mutex_unlock(&data->lock); | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | static ssize_t set_pwm_auto(struct device *dev, | ||
| 1385 | struct device_attribute *devattr, | ||
| 1386 | const char *buf, | ||
| 1387 | size_t count) | ||
| 1388 | { | ||
| 1389 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1390 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1391 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1392 | long temp; | ||
| 1393 | |||
| 1394 | if (strict_strtol(buf, 10, &temp)) | ||
| 1395 | return -EINVAL; | ||
| 1396 | |||
| 1397 | switch (temp) { | ||
| 1398 | case 0: /* off */ | ||
| 1399 | set_pwm_channel(client, data, attr->index, 4); | ||
| 1400 | return count; | ||
| 1401 | case 1: /* manual */ | ||
| 1402 | set_pwm_channel(client, data, attr->index, 7); | ||
| 1403 | return count; | ||
| 1404 | default: | ||
| 1405 | return -EINVAL; | ||
| 1406 | } | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | static ssize_t show_pwm_auto_temp(struct device *dev, | ||
| 1410 | struct device_attribute *devattr, | ||
| 1411 | char *buf) | ||
| 1412 | { | ||
| 1413 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1414 | struct adt7462_data *data = adt7462_update_device(dev); | ||
| 1415 | int channel = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; | ||
| 1416 | |||
| 1417 | switch (channel) { | ||
| 1418 | case 0: /* temp[1234] only */ | ||
| 1419 | case 1: | ||
| 1420 | case 2: | ||
| 1421 | case 3: | ||
| 1422 | return sprintf(buf, "%d\n", (1 << channel)); | ||
| 1423 | case 5: /* temp1 & temp4 */ | ||
| 1424 | return sprintf(buf, "9\n"); | ||
| 1425 | case 6: | ||
| 1426 | return sprintf(buf, "15\n"); | ||
| 1427 | default: | ||
| 1428 | return sprintf(buf, "0\n"); | ||
| 1429 | } | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | static int cvt_auto_temp(int input) | ||
| 1433 | { | ||
| 1434 | if (input == 0xF) | ||
| 1435 | return 6; | ||
| 1436 | if (input == 0x9) | ||
| 1437 | return 5; | ||
| 1438 | if (input < 1 || !is_power_of_2(input)) | ||
| 1439 | return -EINVAL; | ||
| 1440 | return ilog2(input); | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | static ssize_t set_pwm_auto_temp(struct device *dev, | ||
| 1444 | struct device_attribute *devattr, | ||
| 1445 | const char *buf, | ||
| 1446 | size_t count) | ||
| 1447 | { | ||
| 1448 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 1449 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1450 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1451 | long temp; | ||
| 1452 | |||
| 1453 | if (strict_strtol(buf, 10, &temp)) | ||
| 1454 | return -EINVAL; | ||
| 1455 | |||
| 1456 | temp = cvt_auto_temp(temp); | ||
| 1457 | if (temp < 0) | ||
| 1458 | return temp; | ||
| 1459 | |||
| 1460 | set_pwm_channel(client, data, attr->index, temp); | ||
| 1461 | |||
| 1462 | return count; | ||
| 1463 | } | ||
| 1464 | |||
| 1465 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
| 1466 | set_temp_max, 0); | ||
| 1467 | static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
| 1468 | set_temp_max, 1); | ||
| 1469 | static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
| 1470 | set_temp_max, 2); | ||
| 1471 | static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
| 1472 | set_temp_max, 3); | ||
| 1473 | |||
| 1474 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
| 1475 | set_temp_min, 0); | ||
| 1476 | static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
| 1477 | set_temp_min, 1); | ||
| 1478 | static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
| 1479 | set_temp_min, 2); | ||
| 1480 | static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
| 1481 | set_temp_min, 3); | ||
| 1482 | |||
| 1483 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
| 1484 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | ||
| 1485 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); | ||
| 1486 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); | ||
| 1487 | |||
| 1488 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0); | ||
| 1489 | static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1); | ||
| 1490 | static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2); | ||
| 1491 | static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3); | ||
| 1492 | |||
| 1493 | static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1494 | ADT7462_ALARM1 | ADT7462_LT_ALARM); | ||
| 1495 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1496 | ADT7462_ALARM1 | ADT7462_R1T_ALARM); | ||
| 1497 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1498 | ADT7462_ALARM1 | ADT7462_R2T_ALARM); | ||
| 1499 | static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1500 | ADT7462_ALARM1 | ADT7462_R3T_ALARM); | ||
| 1501 | |||
| 1502 | static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1503 | set_volt_max, 0); | ||
| 1504 | static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1505 | set_volt_max, 1); | ||
| 1506 | static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1507 | set_volt_max, 2); | ||
| 1508 | static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1509 | set_volt_max, 3); | ||
| 1510 | static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1511 | set_volt_max, 4); | ||
| 1512 | static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1513 | set_volt_max, 5); | ||
| 1514 | static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1515 | set_volt_max, 6); | ||
| 1516 | static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1517 | set_volt_max, 7); | ||
| 1518 | static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1519 | set_volt_max, 8); | ||
| 1520 | static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1521 | set_volt_max, 9); | ||
| 1522 | static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1523 | set_volt_max, 10); | ||
| 1524 | static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1525 | set_volt_max, 11); | ||
| 1526 | static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 1527 | set_volt_max, 12); | ||
| 1528 | |||
| 1529 | static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1530 | set_volt_min, 0); | ||
| 1531 | static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1532 | set_volt_min, 1); | ||
| 1533 | static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1534 | set_volt_min, 2); | ||
| 1535 | static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1536 | set_volt_min, 3); | ||
| 1537 | static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1538 | set_volt_min, 4); | ||
| 1539 | static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1540 | set_volt_min, 5); | ||
| 1541 | static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1542 | set_volt_min, 6); | ||
| 1543 | static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1544 | set_volt_min, 7); | ||
| 1545 | static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1546 | set_volt_min, 8); | ||
| 1547 | static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1548 | set_volt_min, 9); | ||
| 1549 | static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1550 | set_volt_min, 10); | ||
| 1551 | static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1552 | set_volt_min, 11); | ||
| 1553 | static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 1554 | set_volt_min, 12); | ||
| 1555 | |||
| 1556 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0); | ||
| 1557 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1); | ||
| 1558 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2); | ||
| 1559 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3); | ||
| 1560 | static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4); | ||
| 1561 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5); | ||
| 1562 | static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6); | ||
| 1563 | static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7); | ||
| 1564 | static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8); | ||
| 1565 | static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9); | ||
| 1566 | static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10); | ||
| 1567 | static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11); | ||
| 1568 | static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12); | ||
| 1569 | |||
| 1570 | static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_voltage_label, NULL, 0); | ||
| 1571 | static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_voltage_label, NULL, 1); | ||
| 1572 | static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_voltage_label, NULL, 2); | ||
| 1573 | static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_voltage_label, NULL, 3); | ||
| 1574 | static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_voltage_label, NULL, 4); | ||
| 1575 | static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_voltage_label, NULL, 5); | ||
| 1576 | static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_voltage_label, NULL, 6); | ||
| 1577 | static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_voltage_label, NULL, 7); | ||
| 1578 | static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_voltage_label, NULL, 8); | ||
| 1579 | static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_voltage_label, NULL, 9); | ||
| 1580 | static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_voltage_label, NULL, 10); | ||
| 1581 | static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_voltage_label, NULL, 11); | ||
| 1582 | static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, show_voltage_label, NULL, 12); | ||
| 1583 | |||
| 1584 | static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1585 | ADT7462_ALARM2 | ADT7462_V0_ALARM); | ||
| 1586 | static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1587 | ADT7462_ALARM2 | ADT7462_V7_ALARM); | ||
| 1588 | static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1589 | ADT7462_ALARM2 | ADT7462_V2_ALARM); | ||
| 1590 | static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1591 | ADT7462_ALARM2 | ADT7462_V6_ALARM); | ||
| 1592 | static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1593 | ADT7462_ALARM2 | ADT7462_V5_ALARM); | ||
| 1594 | static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1595 | ADT7462_ALARM2 | ADT7462_V4_ALARM); | ||
| 1596 | static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1597 | ADT7462_ALARM2 | ADT7462_V3_ALARM); | ||
| 1598 | static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1599 | ADT7462_ALARM2 | ADT7462_V1_ALARM); | ||
| 1600 | static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1601 | ADT7462_ALARM3 | ADT7462_V10_ALARM); | ||
| 1602 | static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1603 | ADT7462_ALARM3 | ADT7462_V9_ALARM); | ||
| 1604 | static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1605 | ADT7462_ALARM3 | ADT7462_V8_ALARM); | ||
| 1606 | static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1607 | ADT7462_ALARM3 | ADT7462_V11_ALARM); | ||
| 1608 | static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1609 | ADT7462_ALARM3 | ADT7462_V12_ALARM); | ||
| 1610 | |||
| 1611 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 1612 | set_fan_min, 0); | ||
| 1613 | static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 1614 | set_fan_min, 1); | ||
| 1615 | static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 1616 | set_fan_min, 2); | ||
| 1617 | static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 1618 | set_fan_min, 3); | ||
| 1619 | static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 1620 | set_fan_min, 4); | ||
| 1621 | static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 1622 | set_fan_min, 5); | ||
| 1623 | static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 1624 | set_fan_min, 6); | ||
| 1625 | static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 1626 | set_fan_min, 7); | ||
| 1627 | |||
| 1628 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); | ||
| 1629 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); | ||
| 1630 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); | ||
| 1631 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); | ||
| 1632 | static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); | ||
| 1633 | static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); | ||
| 1634 | static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); | ||
| 1635 | static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); | ||
| 1636 | |||
| 1637 | static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1638 | ADT7462_ALARM4 | ADT7462_F0_ALARM); | ||
| 1639 | static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1640 | ADT7462_ALARM4 | ADT7462_F1_ALARM); | ||
| 1641 | static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1642 | ADT7462_ALARM4 | ADT7462_F2_ALARM); | ||
| 1643 | static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1644 | ADT7462_ALARM4 | ADT7462_F3_ALARM); | ||
| 1645 | static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1646 | ADT7462_ALARM4 | ADT7462_F4_ALARM); | ||
| 1647 | static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1648 | ADT7462_ALARM4 | ADT7462_F5_ALARM); | ||
| 1649 | static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1650 | ADT7462_ALARM4 | ADT7462_F6_ALARM); | ||
| 1651 | static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, | ||
| 1652 | ADT7462_ALARM4 | ADT7462_F7_ALARM); | ||
| 1653 | |||
| 1654 | static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO, | ||
| 1655 | show_force_pwm_max, set_force_pwm_max, 0); | ||
| 1656 | |||
| 1657 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); | ||
| 1658 | static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); | ||
| 1659 | static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); | ||
| 1660 | static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); | ||
| 1661 | |||
| 1662 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
| 1663 | show_pwm_min, set_pwm_min, 0); | ||
| 1664 | static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
| 1665 | show_pwm_min, set_pwm_min, 1); | ||
| 1666 | static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
| 1667 | show_pwm_min, set_pwm_min, 2); | ||
| 1668 | static SENSOR_DEVICE_ATTR(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
| 1669 | show_pwm_min, set_pwm_min, 3); | ||
| 1670 | |||
| 1671 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
| 1672 | show_pwm_max, set_pwm_max, 0); | ||
| 1673 | static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
| 1674 | show_pwm_max, set_pwm_max, 1); | ||
| 1675 | static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
| 1676 | show_pwm_max, set_pwm_max, 2); | ||
| 1677 | static SENSOR_DEVICE_ATTR(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
| 1678 | show_pwm_max, set_pwm_max, 3); | ||
| 1679 | |||
| 1680 | static SENSOR_DEVICE_ATTR(temp1_auto_point1_hyst, S_IWUSR | S_IRUGO, | ||
| 1681 | show_pwm_hyst, set_pwm_hyst, 0); | ||
| 1682 | static SENSOR_DEVICE_ATTR(temp2_auto_point1_hyst, S_IWUSR | S_IRUGO, | ||
| 1683 | show_pwm_hyst, set_pwm_hyst, 1); | ||
| 1684 | static SENSOR_DEVICE_ATTR(temp3_auto_point1_hyst, S_IWUSR | S_IRUGO, | ||
| 1685 | show_pwm_hyst, set_pwm_hyst, 2); | ||
| 1686 | static SENSOR_DEVICE_ATTR(temp4_auto_point1_hyst, S_IWUSR | S_IRUGO, | ||
| 1687 | show_pwm_hyst, set_pwm_hyst, 3); | ||
| 1688 | |||
| 1689 | static SENSOR_DEVICE_ATTR(temp1_auto_point2_hyst, S_IWUSR | S_IRUGO, | ||
| 1690 | show_pwm_hyst, set_pwm_hyst, 0); | ||
| 1691 | static SENSOR_DEVICE_ATTR(temp2_auto_point2_hyst, S_IWUSR | S_IRUGO, | ||
| 1692 | show_pwm_hyst, set_pwm_hyst, 1); | ||
| 1693 | static SENSOR_DEVICE_ATTR(temp3_auto_point2_hyst, S_IWUSR | S_IRUGO, | ||
| 1694 | show_pwm_hyst, set_pwm_hyst, 2); | ||
| 1695 | static SENSOR_DEVICE_ATTR(temp4_auto_point2_hyst, S_IWUSR | S_IRUGO, | ||
| 1696 | show_pwm_hyst, set_pwm_hyst, 3); | ||
| 1697 | |||
| 1698 | static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
| 1699 | show_pwm_tmin, set_pwm_tmin, 0); | ||
| 1700 | static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
| 1701 | show_pwm_tmin, set_pwm_tmin, 1); | ||
| 1702 | static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
| 1703 | show_pwm_tmin, set_pwm_tmin, 2); | ||
| 1704 | static SENSOR_DEVICE_ATTR(temp4_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
| 1705 | show_pwm_tmin, set_pwm_tmin, 3); | ||
| 1706 | |||
| 1707 | static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
| 1708 | show_pwm_tmax, set_pwm_tmax, 0); | ||
| 1709 | static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
| 1710 | show_pwm_tmax, set_pwm_tmax, 1); | ||
| 1711 | static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
| 1712 | show_pwm_tmax, set_pwm_tmax, 2); | ||
| 1713 | static SENSOR_DEVICE_ATTR(temp4_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
| 1714 | show_pwm_tmax, set_pwm_tmax, 3); | ||
| 1715 | |||
| 1716 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, | ||
| 1717 | set_pwm_auto, 0); | ||
| 1718 | static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, | ||
| 1719 | set_pwm_auto, 1); | ||
| 1720 | static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, | ||
| 1721 | set_pwm_auto, 2); | ||
| 1722 | static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, | ||
| 1723 | set_pwm_auto, 3); | ||
| 1724 | |||
| 1725 | static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
| 1726 | show_pwm_auto_temp, set_pwm_auto_temp, 0); | ||
| 1727 | static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
| 1728 | show_pwm_auto_temp, set_pwm_auto_temp, 1); | ||
| 1729 | static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
| 1730 | show_pwm_auto_temp, set_pwm_auto_temp, 2); | ||
| 1731 | static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
| 1732 | show_pwm_auto_temp, set_pwm_auto_temp, 3); | ||
| 1733 | |||
| 1734 | static struct attribute *adt7462_attr[] = | ||
| 1735 | { | ||
| 1736 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
| 1737 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
| 1738 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
| 1739 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
| 1740 | |||
| 1741 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
| 1742 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
| 1743 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
| 1744 | &sensor_dev_attr_temp4_min.dev_attr.attr, | ||
| 1745 | |||
| 1746 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
| 1747 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
| 1748 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
| 1749 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
| 1750 | |||
| 1751 | &sensor_dev_attr_temp1_label.dev_attr.attr, | ||
| 1752 | &sensor_dev_attr_temp2_label.dev_attr.attr, | ||
| 1753 | &sensor_dev_attr_temp3_label.dev_attr.attr, | ||
| 1754 | &sensor_dev_attr_temp4_label.dev_attr.attr, | ||
| 1755 | |||
| 1756 | &sensor_dev_attr_temp1_alarm.dev_attr.attr, | ||
| 1757 | &sensor_dev_attr_temp2_alarm.dev_attr.attr, | ||
| 1758 | &sensor_dev_attr_temp3_alarm.dev_attr.attr, | ||
| 1759 | &sensor_dev_attr_temp4_alarm.dev_attr.attr, | ||
| 1760 | |||
| 1761 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
| 1762 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
| 1763 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
| 1764 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
| 1765 | &sensor_dev_attr_in5_max.dev_attr.attr, | ||
| 1766 | &sensor_dev_attr_in6_max.dev_attr.attr, | ||
| 1767 | &sensor_dev_attr_in7_max.dev_attr.attr, | ||
| 1768 | &sensor_dev_attr_in8_max.dev_attr.attr, | ||
| 1769 | &sensor_dev_attr_in9_max.dev_attr.attr, | ||
| 1770 | &sensor_dev_attr_in10_max.dev_attr.attr, | ||
| 1771 | &sensor_dev_attr_in11_max.dev_attr.attr, | ||
| 1772 | &sensor_dev_attr_in12_max.dev_attr.attr, | ||
| 1773 | &sensor_dev_attr_in13_max.dev_attr.attr, | ||
| 1774 | |||
| 1775 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
| 1776 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
| 1777 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
| 1778 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
| 1779 | &sensor_dev_attr_in5_min.dev_attr.attr, | ||
| 1780 | &sensor_dev_attr_in6_min.dev_attr.attr, | ||
| 1781 | &sensor_dev_attr_in7_min.dev_attr.attr, | ||
| 1782 | &sensor_dev_attr_in8_min.dev_attr.attr, | ||
| 1783 | &sensor_dev_attr_in9_min.dev_attr.attr, | ||
| 1784 | &sensor_dev_attr_in10_min.dev_attr.attr, | ||
| 1785 | &sensor_dev_attr_in11_min.dev_attr.attr, | ||
| 1786 | &sensor_dev_attr_in12_min.dev_attr.attr, | ||
| 1787 | &sensor_dev_attr_in13_min.dev_attr.attr, | ||
| 1788 | |||
| 1789 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
| 1790 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
| 1791 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
| 1792 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
| 1793 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
| 1794 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
| 1795 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
| 1796 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
| 1797 | &sensor_dev_attr_in9_input.dev_attr.attr, | ||
| 1798 | &sensor_dev_attr_in10_input.dev_attr.attr, | ||
| 1799 | &sensor_dev_attr_in11_input.dev_attr.attr, | ||
| 1800 | &sensor_dev_attr_in12_input.dev_attr.attr, | ||
| 1801 | &sensor_dev_attr_in13_input.dev_attr.attr, | ||
| 1802 | |||
| 1803 | &sensor_dev_attr_in1_label.dev_attr.attr, | ||
| 1804 | &sensor_dev_attr_in2_label.dev_attr.attr, | ||
| 1805 | &sensor_dev_attr_in3_label.dev_attr.attr, | ||
| 1806 | &sensor_dev_attr_in4_label.dev_attr.attr, | ||
| 1807 | &sensor_dev_attr_in5_label.dev_attr.attr, | ||
| 1808 | &sensor_dev_attr_in6_label.dev_attr.attr, | ||
| 1809 | &sensor_dev_attr_in7_label.dev_attr.attr, | ||
| 1810 | &sensor_dev_attr_in8_label.dev_attr.attr, | ||
| 1811 | &sensor_dev_attr_in9_label.dev_attr.attr, | ||
| 1812 | &sensor_dev_attr_in10_label.dev_attr.attr, | ||
| 1813 | &sensor_dev_attr_in11_label.dev_attr.attr, | ||
| 1814 | &sensor_dev_attr_in12_label.dev_attr.attr, | ||
| 1815 | &sensor_dev_attr_in13_label.dev_attr.attr, | ||
| 1816 | |||
| 1817 | &sensor_dev_attr_in1_alarm.dev_attr.attr, | ||
| 1818 | &sensor_dev_attr_in2_alarm.dev_attr.attr, | ||
| 1819 | &sensor_dev_attr_in3_alarm.dev_attr.attr, | ||
| 1820 | &sensor_dev_attr_in4_alarm.dev_attr.attr, | ||
| 1821 | &sensor_dev_attr_in5_alarm.dev_attr.attr, | ||
| 1822 | &sensor_dev_attr_in6_alarm.dev_attr.attr, | ||
| 1823 | &sensor_dev_attr_in7_alarm.dev_attr.attr, | ||
| 1824 | &sensor_dev_attr_in8_alarm.dev_attr.attr, | ||
| 1825 | &sensor_dev_attr_in9_alarm.dev_attr.attr, | ||
| 1826 | &sensor_dev_attr_in10_alarm.dev_attr.attr, | ||
| 1827 | &sensor_dev_attr_in11_alarm.dev_attr.attr, | ||
| 1828 | &sensor_dev_attr_in12_alarm.dev_attr.attr, | ||
| 1829 | &sensor_dev_attr_in13_alarm.dev_attr.attr, | ||
| 1830 | |||
| 1831 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
| 1832 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
| 1833 | &sensor_dev_attr_fan3_min.dev_attr.attr, | ||
| 1834 | &sensor_dev_attr_fan4_min.dev_attr.attr, | ||
| 1835 | &sensor_dev_attr_fan5_min.dev_attr.attr, | ||
| 1836 | &sensor_dev_attr_fan6_min.dev_attr.attr, | ||
| 1837 | &sensor_dev_attr_fan7_min.dev_attr.attr, | ||
| 1838 | &sensor_dev_attr_fan8_min.dev_attr.attr, | ||
| 1839 | |||
| 1840 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
| 1841 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
| 1842 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
| 1843 | &sensor_dev_attr_fan4_input.dev_attr.attr, | ||
| 1844 | &sensor_dev_attr_fan5_input.dev_attr.attr, | ||
| 1845 | &sensor_dev_attr_fan6_input.dev_attr.attr, | ||
| 1846 | &sensor_dev_attr_fan7_input.dev_attr.attr, | ||
| 1847 | &sensor_dev_attr_fan8_input.dev_attr.attr, | ||
| 1848 | |||
| 1849 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
| 1850 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
| 1851 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | ||
| 1852 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | ||
| 1853 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | ||
| 1854 | &sensor_dev_attr_fan6_alarm.dev_attr.attr, | ||
| 1855 | &sensor_dev_attr_fan7_alarm.dev_attr.attr, | ||
| 1856 | &sensor_dev_attr_fan8_alarm.dev_attr.attr, | ||
| 1857 | |||
| 1858 | &sensor_dev_attr_force_pwm_max.dev_attr.attr, | ||
| 1859 | &sensor_dev_attr_pwm1.dev_attr.attr, | ||
| 1860 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
| 1861 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
| 1862 | &sensor_dev_attr_pwm4.dev_attr.attr, | ||
| 1863 | |||
| 1864 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, | ||
| 1865 | &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, | ||
| 1866 | &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, | ||
| 1867 | &sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr, | ||
| 1868 | |||
| 1869 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, | ||
| 1870 | &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, | ||
| 1871 | &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, | ||
| 1872 | &sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr, | ||
| 1873 | |||
| 1874 | &sensor_dev_attr_temp1_auto_point1_hyst.dev_attr.attr, | ||
| 1875 | &sensor_dev_attr_temp2_auto_point1_hyst.dev_attr.attr, | ||
| 1876 | &sensor_dev_attr_temp3_auto_point1_hyst.dev_attr.attr, | ||
| 1877 | &sensor_dev_attr_temp4_auto_point1_hyst.dev_attr.attr, | ||
| 1878 | |||
| 1879 | &sensor_dev_attr_temp1_auto_point2_hyst.dev_attr.attr, | ||
| 1880 | &sensor_dev_attr_temp2_auto_point2_hyst.dev_attr.attr, | ||
| 1881 | &sensor_dev_attr_temp3_auto_point2_hyst.dev_attr.attr, | ||
| 1882 | &sensor_dev_attr_temp4_auto_point2_hyst.dev_attr.attr, | ||
| 1883 | |||
| 1884 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, | ||
| 1885 | &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, | ||
| 1886 | &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, | ||
| 1887 | &sensor_dev_attr_temp4_auto_point1_temp.dev_attr.attr, | ||
| 1888 | |||
| 1889 | &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, | ||
| 1890 | &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, | ||
| 1891 | &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, | ||
| 1892 | &sensor_dev_attr_temp4_auto_point2_temp.dev_attr.attr, | ||
| 1893 | |||
| 1894 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
| 1895 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
| 1896 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
| 1897 | &sensor_dev_attr_pwm4_enable.dev_attr.attr, | ||
| 1898 | |||
| 1899 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, | ||
| 1900 | &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, | ||
| 1901 | &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, | ||
| 1902 | &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, | ||
| 1903 | NULL | ||
| 1904 | }; | ||
| 1905 | |||
| 1906 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
| 1907 | static int adt7462_detect(struct i2c_client *client, int kind, | ||
| 1908 | struct i2c_board_info *info) | ||
| 1909 | { | ||
| 1910 | struct i2c_adapter *adapter = client->adapter; | ||
| 1911 | |||
| 1912 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 1913 | return -ENODEV; | ||
| 1914 | |||
| 1915 | if (kind <= 0) { | ||
| 1916 | int vendor, device, revision; | ||
| 1917 | |||
| 1918 | vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR); | ||
| 1919 | if (vendor != ADT7462_VENDOR) | ||
| 1920 | return -ENODEV; | ||
| 1921 | |||
| 1922 | device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE); | ||
| 1923 | if (device != ADT7462_DEVICE) | ||
| 1924 | return -ENODEV; | ||
| 1925 | |||
| 1926 | revision = i2c_smbus_read_byte_data(client, | ||
| 1927 | ADT7462_REG_REVISION); | ||
| 1928 | if (revision != ADT7462_REVISION) | ||
| 1929 | return -ENODEV; | ||
| 1930 | } else | ||
| 1931 | dev_dbg(&adapter->dev, "detection forced\n"); | ||
| 1932 | |||
| 1933 | strlcpy(info->type, "adt7462", I2C_NAME_SIZE); | ||
| 1934 | |||
| 1935 | return 0; | ||
| 1936 | } | ||
| 1937 | |||
| 1938 | static int adt7462_probe(struct i2c_client *client, | ||
| 1939 | const struct i2c_device_id *id) | ||
| 1940 | { | ||
| 1941 | struct adt7462_data *data; | ||
| 1942 | int err; | ||
| 1943 | |||
| 1944 | data = kzalloc(sizeof(struct adt7462_data), GFP_KERNEL); | ||
| 1945 | if (!data) { | ||
| 1946 | err = -ENOMEM; | ||
| 1947 | goto exit; | ||
| 1948 | } | ||
| 1949 | |||
| 1950 | i2c_set_clientdata(client, data); | ||
| 1951 | mutex_init(&data->lock); | ||
| 1952 | |||
| 1953 | dev_info(&client->dev, "%s chip found\n", client->name); | ||
| 1954 | |||
| 1955 | /* Register sysfs hooks */ | ||
| 1956 | data->attrs.attrs = adt7462_attr; | ||
| 1957 | err = sysfs_create_group(&client->dev.kobj, &data->attrs); | ||
| 1958 | if (err) | ||
| 1959 | goto exit_free; | ||
| 1960 | |||
| 1961 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
| 1962 | if (IS_ERR(data->hwmon_dev)) { | ||
| 1963 | err = PTR_ERR(data->hwmon_dev); | ||
| 1964 | goto exit_remove; | ||
| 1965 | } | ||
| 1966 | |||
| 1967 | return 0; | ||
| 1968 | |||
| 1969 | exit_remove: | ||
| 1970 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
| 1971 | exit_free: | ||
| 1972 | kfree(data); | ||
| 1973 | exit: | ||
| 1974 | return err; | ||
| 1975 | } | ||
| 1976 | |||
| 1977 | static int adt7462_remove(struct i2c_client *client) | ||
| 1978 | { | ||
| 1979 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
| 1980 | |||
| 1981 | hwmon_device_unregister(data->hwmon_dev); | ||
| 1982 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
| 1983 | kfree(data); | ||
| 1984 | return 0; | ||
| 1985 | } | ||
| 1986 | |||
| 1987 | static int __init adt7462_init(void) | ||
| 1988 | { | ||
| 1989 | return i2c_add_driver(&adt7462_driver); | ||
| 1990 | } | ||
| 1991 | |||
| 1992 | static void __exit adt7462_exit(void) | ||
| 1993 | { | ||
| 1994 | i2c_del_driver(&adt7462_driver); | ||
| 1995 | } | ||
| 1996 | |||
| 1997 | MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); | ||
| 1998 | MODULE_DESCRIPTION("ADT7462 driver"); | ||
| 1999 | MODULE_LICENSE("GPL"); | ||
| 2000 | |||
| 2001 | module_init(adt7462_init); | ||
| 2002 | module_exit(adt7462_exit); | ||
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index d368d8f845e1..1311a595147e 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c | |||
| @@ -137,6 +137,8 @@ I2C_CLIENT_INSMOD_1(adt7470); | |||
| 137 | #define FAN_PERIOD_INVALID 65535 | 137 | #define FAN_PERIOD_INVALID 65535 |
| 138 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | 138 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) |
| 139 | 139 | ||
| 140 | #define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) | ||
| 141 | |||
| 140 | struct adt7470_data { | 142 | struct adt7470_data { |
| 141 | struct device *hwmon_dev; | 143 | struct device *hwmon_dev; |
| 142 | struct attribute_group attrs; | 144 | struct attribute_group attrs; |
| @@ -353,7 +355,13 @@ static ssize_t set_temp_min(struct device *dev, | |||
| 353 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 355 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 354 | struct i2c_client *client = to_i2c_client(dev); | 356 | struct i2c_client *client = to_i2c_client(dev); |
| 355 | struct adt7470_data *data = i2c_get_clientdata(client); | 357 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 356 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 358 | long temp; |
| 359 | |||
| 360 | if (strict_strtol(buf, 10, &temp)) | ||
| 361 | return -EINVAL; | ||
| 362 | |||
| 363 | temp = ROUND_DIV(temp, 1000); | ||
| 364 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 357 | 365 | ||
| 358 | mutex_lock(&data->lock); | 366 | mutex_lock(&data->lock); |
| 359 | data->temp_min[attr->index] = temp; | 367 | data->temp_min[attr->index] = temp; |
| @@ -381,7 +389,13 @@ static ssize_t set_temp_max(struct device *dev, | |||
| 381 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 389 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 382 | struct i2c_client *client = to_i2c_client(dev); | 390 | struct i2c_client *client = to_i2c_client(dev); |
| 383 | struct adt7470_data *data = i2c_get_clientdata(client); | 391 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 384 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 392 | long temp; |
| 393 | |||
| 394 | if (strict_strtol(buf, 10, &temp)) | ||
| 395 | return -EINVAL; | ||
| 396 | |||
| 397 | temp = ROUND_DIV(temp, 1000); | ||
| 398 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 385 | 399 | ||
| 386 | mutex_lock(&data->lock); | 400 | mutex_lock(&data->lock); |
| 387 | data->temp_max[attr->index] = temp; | 401 | data->temp_max[attr->index] = temp; |
| @@ -430,11 +444,13 @@ static ssize_t set_fan_max(struct device *dev, | |||
| 430 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 444 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 431 | struct i2c_client *client = to_i2c_client(dev); | 445 | struct i2c_client *client = to_i2c_client(dev); |
| 432 | struct adt7470_data *data = i2c_get_clientdata(client); | 446 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 433 | int temp = simple_strtol(buf, NULL, 10); | 447 | long temp; |
| 434 | 448 | ||
| 435 | if (!temp) | 449 | if (strict_strtol(buf, 10, &temp) || !temp) |
| 436 | return -EINVAL; | 450 | return -EINVAL; |
| 451 | |||
| 437 | temp = FAN_RPM_TO_PERIOD(temp); | 452 | temp = FAN_RPM_TO_PERIOD(temp); |
| 453 | temp = SENSORS_LIMIT(temp, 1, 65534); | ||
| 438 | 454 | ||
| 439 | mutex_lock(&data->lock); | 455 | mutex_lock(&data->lock); |
| 440 | data->fan_max[attr->index] = temp; | 456 | data->fan_max[attr->index] = temp; |
| @@ -465,11 +481,13 @@ static ssize_t set_fan_min(struct device *dev, | |||
| 465 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 481 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 466 | struct i2c_client *client = to_i2c_client(dev); | 482 | struct i2c_client *client = to_i2c_client(dev); |
| 467 | struct adt7470_data *data = i2c_get_clientdata(client); | 483 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 468 | int temp = simple_strtol(buf, NULL, 10); | 484 | long temp; |
| 469 | 485 | ||
| 470 | if (!temp) | 486 | if (strict_strtol(buf, 10, &temp) || !temp) |
| 471 | return -EINVAL; | 487 | return -EINVAL; |
| 488 | |||
| 472 | temp = FAN_RPM_TO_PERIOD(temp); | 489 | temp = FAN_RPM_TO_PERIOD(temp); |
| 490 | temp = SENSORS_LIMIT(temp, 1, 65534); | ||
| 473 | 491 | ||
| 474 | mutex_lock(&data->lock); | 492 | mutex_lock(&data->lock); |
| 475 | data->fan_min[attr->index] = temp; | 493 | data->fan_min[attr->index] = temp; |
| @@ -507,9 +525,12 @@ static ssize_t set_force_pwm_max(struct device *dev, | |||
| 507 | { | 525 | { |
| 508 | struct i2c_client *client = to_i2c_client(dev); | 526 | struct i2c_client *client = to_i2c_client(dev); |
| 509 | struct adt7470_data *data = i2c_get_clientdata(client); | 527 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 510 | int temp = simple_strtol(buf, NULL, 10); | 528 | long temp; |
| 511 | u8 reg; | 529 | u8 reg; |
| 512 | 530 | ||
| 531 | if (strict_strtol(buf, 10, &temp)) | ||
| 532 | return -EINVAL; | ||
| 533 | |||
| 513 | mutex_lock(&data->lock); | 534 | mutex_lock(&data->lock); |
| 514 | data->force_pwm_max = temp; | 535 | data->force_pwm_max = temp; |
| 515 | reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); | 536 | reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); |
| @@ -537,7 +558,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | |||
| 537 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 558 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 538 | struct i2c_client *client = to_i2c_client(dev); | 559 | struct i2c_client *client = to_i2c_client(dev); |
| 539 | struct adt7470_data *data = i2c_get_clientdata(client); | 560 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 540 | int temp = simple_strtol(buf, NULL, 10); | 561 | long temp; |
| 562 | |||
| 563 | if (strict_strtol(buf, 10, &temp)) | ||
| 564 | return -EINVAL; | ||
| 565 | |||
| 566 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 541 | 567 | ||
| 542 | mutex_lock(&data->lock); | 568 | mutex_lock(&data->lock); |
| 543 | data->pwm[attr->index] = temp; | 569 | data->pwm[attr->index] = temp; |
| @@ -564,7 +590,12 @@ static ssize_t set_pwm_max(struct device *dev, | |||
| 564 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 590 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 565 | struct i2c_client *client = to_i2c_client(dev); | 591 | struct i2c_client *client = to_i2c_client(dev); |
| 566 | struct adt7470_data *data = i2c_get_clientdata(client); | 592 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 567 | int temp = simple_strtol(buf, NULL, 10); | 593 | long temp; |
| 594 | |||
| 595 | if (strict_strtol(buf, 10, &temp)) | ||
| 596 | return -EINVAL; | ||
| 597 | |||
| 598 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 568 | 599 | ||
| 569 | mutex_lock(&data->lock); | 600 | mutex_lock(&data->lock); |
| 570 | data->pwm_max[attr->index] = temp; | 601 | data->pwm_max[attr->index] = temp; |
| @@ -592,7 +623,12 @@ static ssize_t set_pwm_min(struct device *dev, | |||
| 592 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 623 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 593 | struct i2c_client *client = to_i2c_client(dev); | 624 | struct i2c_client *client = to_i2c_client(dev); |
| 594 | struct adt7470_data *data = i2c_get_clientdata(client); | 625 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 595 | int temp = simple_strtol(buf, NULL, 10); | 626 | long temp; |
| 627 | |||
| 628 | if (strict_strtol(buf, 10, &temp)) | ||
| 629 | return -EINVAL; | ||
| 630 | |||
| 631 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 596 | 632 | ||
| 597 | mutex_lock(&data->lock); | 633 | mutex_lock(&data->lock); |
| 598 | data->pwm_min[attr->index] = temp; | 634 | data->pwm_min[attr->index] = temp; |
| @@ -630,7 +666,13 @@ static ssize_t set_pwm_tmin(struct device *dev, | |||
| 630 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 666 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 631 | struct i2c_client *client = to_i2c_client(dev); | 667 | struct i2c_client *client = to_i2c_client(dev); |
| 632 | struct adt7470_data *data = i2c_get_clientdata(client); | 668 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 633 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 669 | long temp; |
| 670 | |||
| 671 | if (strict_strtol(buf, 10, &temp)) | ||
| 672 | return -EINVAL; | ||
| 673 | |||
| 674 | temp = ROUND_DIV(temp, 1000); | ||
| 675 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 634 | 676 | ||
| 635 | mutex_lock(&data->lock); | 677 | mutex_lock(&data->lock); |
| 636 | data->pwm_tmin[attr->index] = temp; | 678 | data->pwm_tmin[attr->index] = temp; |
| @@ -658,11 +700,14 @@ static ssize_t set_pwm_auto(struct device *dev, | |||
| 658 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 700 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 659 | struct i2c_client *client = to_i2c_client(dev); | 701 | struct i2c_client *client = to_i2c_client(dev); |
| 660 | struct adt7470_data *data = i2c_get_clientdata(client); | 702 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 661 | int temp = simple_strtol(buf, NULL, 10); | ||
| 662 | int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index); | 703 | int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index); |
| 663 | int pwm_auto_reg_mask; | 704 | int pwm_auto_reg_mask; |
| 705 | long temp; | ||
| 664 | u8 reg; | 706 | u8 reg; |
| 665 | 707 | ||
| 708 | if (strict_strtol(buf, 10, &temp)) | ||
| 709 | return -EINVAL; | ||
| 710 | |||
| 666 | if (attr->index % 2) | 711 | if (attr->index % 2) |
| 667 | pwm_auto_reg_mask = ADT7470_PWM2_AUTO_MASK; | 712 | pwm_auto_reg_mask = ADT7470_PWM2_AUTO_MASK; |
| 668 | else | 713 | else |
| @@ -716,10 +761,14 @@ static ssize_t set_pwm_auto_temp(struct device *dev, | |||
| 716 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 761 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 717 | struct i2c_client *client = to_i2c_client(dev); | 762 | struct i2c_client *client = to_i2c_client(dev); |
| 718 | struct adt7470_data *data = i2c_get_clientdata(client); | 763 | struct adt7470_data *data = i2c_get_clientdata(client); |
| 719 | int temp = cvt_auto_temp(simple_strtol(buf, NULL, 10)); | ||
| 720 | int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index); | 764 | int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index); |
| 765 | long temp; | ||
| 721 | u8 reg; | 766 | u8 reg; |
| 722 | 767 | ||
| 768 | if (strict_strtol(buf, 10, &temp)) | ||
| 769 | return -EINVAL; | ||
| 770 | |||
| 771 | temp = cvt_auto_temp(temp); | ||
| 723 | if (temp < 0) | 772 | if (temp < 0) |
| 724 | return temp; | 773 | return temp; |
| 725 | 774 | ||
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c index b9a8ea30c99c..18aa30866a6c 100644 --- a/drivers/hwmon/adt7473.c +++ b/drivers/hwmon/adt7473.c | |||
| @@ -129,6 +129,8 @@ I2C_CLIENT_INSMOD_1(adt7473); | |||
| 129 | #define FAN_PERIOD_INVALID 65535 | 129 | #define FAN_PERIOD_INVALID 65535 |
| 130 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | 130 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) |
| 131 | 131 | ||
| 132 | #define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) | ||
| 133 | |||
| 132 | struct adt7473_data { | 134 | struct adt7473_data { |
| 133 | struct device *hwmon_dev; | 135 | struct device *hwmon_dev; |
| 134 | struct attribute_group attrs; | 136 | struct attribute_group attrs; |
| @@ -357,7 +359,12 @@ static ssize_t set_volt_min(struct device *dev, | |||
| 357 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 359 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 358 | struct i2c_client *client = to_i2c_client(dev); | 360 | struct i2c_client *client = to_i2c_client(dev); |
| 359 | struct adt7473_data *data = i2c_get_clientdata(client); | 361 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 360 | int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10)); | 362 | long volt; |
| 363 | |||
| 364 | if (strict_strtol(buf, 10, &volt)) | ||
| 365 | return -EINVAL; | ||
| 366 | |||
| 367 | volt = encode_volt(attr->index, volt); | ||
| 361 | 368 | ||
| 362 | mutex_lock(&data->lock); | 369 | mutex_lock(&data->lock); |
| 363 | data->volt_min[attr->index] = volt; | 370 | data->volt_min[attr->index] = volt; |
| @@ -386,7 +393,12 @@ static ssize_t set_volt_max(struct device *dev, | |||
| 386 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 393 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 387 | struct i2c_client *client = to_i2c_client(dev); | 394 | struct i2c_client *client = to_i2c_client(dev); |
| 388 | struct adt7473_data *data = i2c_get_clientdata(client); | 395 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 389 | int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10)); | 396 | long volt; |
| 397 | |||
| 398 | if (strict_strtol(buf, 10, &volt)) | ||
| 399 | return -EINVAL; | ||
| 400 | |||
| 401 | volt = encode_volt(attr->index, volt); | ||
| 390 | 402 | ||
| 391 | mutex_lock(&data->lock); | 403 | mutex_lock(&data->lock); |
| 392 | data->volt_max[attr->index] = volt; | 404 | data->volt_max[attr->index] = volt; |
| @@ -419,7 +431,8 @@ static int decode_temp(u8 twos_complement, u8 raw) | |||
| 419 | 431 | ||
| 420 | static u8 encode_temp(u8 twos_complement, int cooked) | 432 | static u8 encode_temp(u8 twos_complement, int cooked) |
| 421 | { | 433 | { |
| 422 | return twos_complement ? cooked & 0xFF : cooked + 64; | 434 | u8 ret = twos_complement ? cooked & 0xFF : cooked + 64; |
| 435 | return SENSORS_LIMIT(ret, 0, 255); | ||
| 423 | } | 436 | } |
| 424 | 437 | ||
| 425 | static ssize_t show_temp_min(struct device *dev, | 438 | static ssize_t show_temp_min(struct device *dev, |
| @@ -441,7 +454,12 @@ static ssize_t set_temp_min(struct device *dev, | |||
| 441 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 454 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 442 | struct i2c_client *client = to_i2c_client(dev); | 455 | struct i2c_client *client = to_i2c_client(dev); |
| 443 | struct adt7473_data *data = i2c_get_clientdata(client); | 456 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 444 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 457 | long temp; |
| 458 | |||
| 459 | if (strict_strtol(buf, 10, &temp)) | ||
| 460 | return -EINVAL; | ||
| 461 | |||
| 462 | temp = ROUND_DIV(temp, 1000); | ||
| 445 | temp = encode_temp(data->temp_twos_complement, temp); | 463 | temp = encode_temp(data->temp_twos_complement, temp); |
| 446 | 464 | ||
| 447 | mutex_lock(&data->lock); | 465 | mutex_lock(&data->lock); |
| @@ -472,7 +490,12 @@ static ssize_t set_temp_max(struct device *dev, | |||
| 472 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 490 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 473 | struct i2c_client *client = to_i2c_client(dev); | 491 | struct i2c_client *client = to_i2c_client(dev); |
| 474 | struct adt7473_data *data = i2c_get_clientdata(client); | 492 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 475 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 493 | long temp; |
| 494 | |||
| 495 | if (strict_strtol(buf, 10, &temp)) | ||
| 496 | return -EINVAL; | ||
| 497 | |||
| 498 | temp = ROUND_DIV(temp, 1000); | ||
| 476 | temp = encode_temp(data->temp_twos_complement, temp); | 499 | temp = encode_temp(data->temp_twos_complement, temp); |
| 477 | 500 | ||
| 478 | mutex_lock(&data->lock); | 501 | mutex_lock(&data->lock); |
| @@ -515,11 +538,13 @@ static ssize_t set_fan_min(struct device *dev, | |||
| 515 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 538 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 516 | struct i2c_client *client = to_i2c_client(dev); | 539 | struct i2c_client *client = to_i2c_client(dev); |
| 517 | struct adt7473_data *data = i2c_get_clientdata(client); | 540 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 518 | int temp = simple_strtol(buf, NULL, 10); | 541 | long temp; |
| 519 | 542 | ||
| 520 | if (!temp) | 543 | if (strict_strtol(buf, 10, &temp) || !temp) |
| 521 | return -EINVAL; | 544 | return -EINVAL; |
| 545 | |||
| 522 | temp = FAN_RPM_TO_PERIOD(temp); | 546 | temp = FAN_RPM_TO_PERIOD(temp); |
| 547 | temp = SENSORS_LIMIT(temp, 1, 65534); | ||
| 523 | 548 | ||
| 524 | mutex_lock(&data->lock); | 549 | mutex_lock(&data->lock); |
| 525 | data->fan_min[attr->index] = temp; | 550 | data->fan_min[attr->index] = temp; |
| @@ -558,7 +583,10 @@ static ssize_t set_max_duty_at_crit(struct device *dev, | |||
| 558 | u8 reg; | 583 | u8 reg; |
| 559 | struct i2c_client *client = to_i2c_client(dev); | 584 | struct i2c_client *client = to_i2c_client(dev); |
| 560 | struct adt7473_data *data = i2c_get_clientdata(client); | 585 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 561 | int temp = simple_strtol(buf, NULL, 10); | 586 | long temp; |
| 587 | |||
| 588 | if (strict_strtol(buf, 10, &temp)) | ||
| 589 | return -EINVAL; | ||
| 562 | 590 | ||
| 563 | mutex_lock(&data->lock); | 591 | mutex_lock(&data->lock); |
| 564 | data->max_duty_at_overheat = !!temp; | 592 | data->max_duty_at_overheat = !!temp; |
| @@ -587,7 +615,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | |||
| 587 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 615 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 588 | struct i2c_client *client = to_i2c_client(dev); | 616 | struct i2c_client *client = to_i2c_client(dev); |
| 589 | struct adt7473_data *data = i2c_get_clientdata(client); | 617 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 590 | int temp = simple_strtol(buf, NULL, 10); | 618 | long temp; |
| 619 | |||
| 620 | if (strict_strtol(buf, 10, &temp)) | ||
| 621 | return -EINVAL; | ||
| 622 | |||
| 623 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 591 | 624 | ||
| 592 | mutex_lock(&data->lock); | 625 | mutex_lock(&data->lock); |
| 593 | data->pwm[attr->index] = temp; | 626 | data->pwm[attr->index] = temp; |
| @@ -614,7 +647,12 @@ static ssize_t set_pwm_max(struct device *dev, | |||
| 614 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 647 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 615 | struct i2c_client *client = to_i2c_client(dev); | 648 | struct i2c_client *client = to_i2c_client(dev); |
| 616 | struct adt7473_data *data = i2c_get_clientdata(client); | 649 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 617 | int temp = simple_strtol(buf, NULL, 10); | 650 | long temp; |
| 651 | |||
| 652 | if (strict_strtol(buf, 10, &temp)) | ||
| 653 | return -EINVAL; | ||
| 654 | |||
| 655 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 618 | 656 | ||
| 619 | mutex_lock(&data->lock); | 657 | mutex_lock(&data->lock); |
| 620 | data->pwm_max[attr->index] = temp; | 658 | data->pwm_max[attr->index] = temp; |
| @@ -642,7 +680,12 @@ static ssize_t set_pwm_min(struct device *dev, | |||
| 642 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 680 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 643 | struct i2c_client *client = to_i2c_client(dev); | 681 | struct i2c_client *client = to_i2c_client(dev); |
| 644 | struct adt7473_data *data = i2c_get_clientdata(client); | 682 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 645 | int temp = simple_strtol(buf, NULL, 10); | 683 | long temp; |
| 684 | |||
| 685 | if (strict_strtol(buf, 10, &temp)) | ||
| 686 | return -EINVAL; | ||
| 687 | |||
| 688 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 646 | 689 | ||
| 647 | mutex_lock(&data->lock); | 690 | mutex_lock(&data->lock); |
| 648 | data->pwm_min[attr->index] = temp; | 691 | data->pwm_min[attr->index] = temp; |
| @@ -672,7 +715,12 @@ static ssize_t set_temp_tmax(struct device *dev, | |||
| 672 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 715 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 673 | struct i2c_client *client = to_i2c_client(dev); | 716 | struct i2c_client *client = to_i2c_client(dev); |
| 674 | struct adt7473_data *data = i2c_get_clientdata(client); | 717 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 675 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 718 | long temp; |
| 719 | |||
| 720 | if (strict_strtol(buf, 10, &temp)) | ||
| 721 | return -EINVAL; | ||
| 722 | |||
| 723 | temp = ROUND_DIV(temp, 1000); | ||
| 676 | temp = encode_temp(data->temp_twos_complement, temp); | 724 | temp = encode_temp(data->temp_twos_complement, temp); |
| 677 | 725 | ||
| 678 | mutex_lock(&data->lock); | 726 | mutex_lock(&data->lock); |
| @@ -703,7 +751,12 @@ static ssize_t set_temp_tmin(struct device *dev, | |||
| 703 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 751 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 704 | struct i2c_client *client = to_i2c_client(dev); | 752 | struct i2c_client *client = to_i2c_client(dev); |
| 705 | struct adt7473_data *data = i2c_get_clientdata(client); | 753 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 706 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 754 | long temp; |
| 755 | |||
| 756 | if (strict_strtol(buf, 10, &temp)) | ||
| 757 | return -EINVAL; | ||
| 758 | |||
| 759 | temp = ROUND_DIV(temp, 1000); | ||
| 707 | temp = encode_temp(data->temp_twos_complement, temp); | 760 | temp = encode_temp(data->temp_twos_complement, temp); |
| 708 | 761 | ||
| 709 | mutex_lock(&data->lock); | 762 | mutex_lock(&data->lock); |
| @@ -741,7 +794,10 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
| 741 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 794 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 742 | struct i2c_client *client = to_i2c_client(dev); | 795 | struct i2c_client *client = to_i2c_client(dev); |
| 743 | struct adt7473_data *data = i2c_get_clientdata(client); | 796 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 744 | int temp = simple_strtol(buf, NULL, 10); | 797 | long temp; |
| 798 | |||
| 799 | if (strict_strtol(buf, 10, &temp)) | ||
| 800 | return -EINVAL; | ||
| 745 | 801 | ||
| 746 | switch (temp) { | 802 | switch (temp) { |
| 747 | case 0: | 803 | case 0: |
| @@ -805,7 +861,10 @@ static ssize_t set_pwm_auto_temp(struct device *dev, | |||
| 805 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 861 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 806 | struct i2c_client *client = to_i2c_client(dev); | 862 | struct i2c_client *client = to_i2c_client(dev); |
| 807 | struct adt7473_data *data = i2c_get_clientdata(client); | 863 | struct adt7473_data *data = i2c_get_clientdata(client); |
| 808 | int temp = simple_strtol(buf, NULL, 10); | 864 | long temp; |
| 865 | |||
| 866 | if (strict_strtol(buf, 10, &temp)) | ||
| 867 | return -EINVAL; | ||
| 809 | 868 | ||
| 810 | switch (temp) { | 869 | switch (temp) { |
| 811 | case 1: | 870 | case 1: |
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index be3285912cb7..488e45cd43d7 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
| @@ -1280,7 +1280,7 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { | |||
| 1280 | { .accelerometer = 0, .light = 0, .temperature_set = 4 }, | 1280 | { .accelerometer = 0, .light = 0, .temperature_set = 4 }, |
| 1281 | /* iMac: temperature set 5 */ | 1281 | /* iMac: temperature set 5 */ |
| 1282 | { .accelerometer = 0, .light = 0, .temperature_set = 5 }, | 1282 | { .accelerometer = 0, .light = 0, .temperature_set = 5 }, |
| 1283 | /* MacBook3: accelerometer and temperature set 6 */ | 1283 | /* MacBook3, MacBook4: accelerometer and temperature set 6 */ |
| 1284 | { .accelerometer = 1, .light = 0, .temperature_set = 6 }, | 1284 | { .accelerometer = 1, .light = 0, .temperature_set = 6 }, |
| 1285 | /* MacBook Air: accelerometer, backlight and temperature set 7 */ | 1285 | /* MacBook Air: accelerometer, backlight and temperature set 7 */ |
| 1286 | { .accelerometer = 1, .light = 1, .temperature_set = 7 }, | 1286 | { .accelerometer = 1, .light = 1, .temperature_set = 7 }, |
| @@ -1329,6 +1329,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
| 1329 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1329 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
| 1330 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, | 1330 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, |
| 1331 | &applesmc_dmi_data[6]}, | 1331 | &applesmc_dmi_data[6]}, |
| 1332 | { applesmc_dmi_match, "Apple MacBook 4", { | ||
| 1333 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
| 1334 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4") }, | ||
| 1335 | &applesmc_dmi_data[6]}, | ||
| 1332 | { applesmc_dmi_match, "Apple MacBook 5", { | 1336 | { applesmc_dmi_match, "Apple MacBook 5", { |
| 1333 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1337 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1334 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") }, | 1338 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") }, |
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index 7b0ed5dea399..fe74609a7feb 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c | |||
| @@ -88,9 +88,11 @@ | |||
| 88 | static DEFINE_IDR(aem_idr); | 88 | static DEFINE_IDR(aem_idr); |
| 89 | static DEFINE_SPINLOCK(aem_idr_lock); | 89 | static DEFINE_SPINLOCK(aem_idr_lock); |
| 90 | 90 | ||
| 91 | static struct device_driver aem_driver = { | 91 | static struct platform_driver aem_driver = { |
| 92 | .name = DRVNAME, | 92 | .driver = { |
| 93 | .bus = &platform_bus_type, | 93 | .name = DRVNAME, |
| 94 | .bus = &platform_bus_type, | ||
| 95 | } | ||
| 94 | }; | 96 | }; |
| 95 | 97 | ||
| 96 | struct aem_ipmi_data { | 98 | struct aem_ipmi_data { |
| @@ -583,7 +585,7 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle) | |||
| 583 | data->pdev = platform_device_alloc(DRVNAME, data->id); | 585 | data->pdev = platform_device_alloc(DRVNAME, data->id); |
| 584 | if (!data->pdev) | 586 | if (!data->pdev) |
| 585 | goto dev_err; | 587 | goto dev_err; |
| 586 | data->pdev->dev.driver = &aem_driver; | 588 | data->pdev->dev.driver = &aem_driver.driver; |
| 587 | 589 | ||
| 588 | res = platform_device_add(data->pdev); | 590 | res = platform_device_add(data->pdev); |
| 589 | if (res) | 591 | if (res) |
| @@ -716,7 +718,7 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe, | |||
| 716 | data->pdev = platform_device_alloc(DRVNAME, data->id); | 718 | data->pdev = platform_device_alloc(DRVNAME, data->id); |
| 717 | if (!data->pdev) | 719 | if (!data->pdev) |
| 718 | goto dev_err; | 720 | goto dev_err; |
| 719 | data->pdev->dev.driver = &aem_driver; | 721 | data->pdev->dev.driver = &aem_driver.driver; |
| 720 | 722 | ||
| 721 | res = platform_device_add(data->pdev); | 723 | res = platform_device_add(data->pdev); |
| 722 | if (res) | 724 | if (res) |
| @@ -1085,7 +1087,7 @@ static int __init aem_init(void) | |||
| 1085 | { | 1087 | { |
| 1086 | int res; | 1088 | int res; |
| 1087 | 1089 | ||
| 1088 | res = driver_register(&aem_driver); | 1090 | res = driver_register(&aem_driver.driver); |
| 1089 | if (res) { | 1091 | if (res) { |
| 1090 | printk(KERN_ERR "Can't register aem driver\n"); | 1092 | printk(KERN_ERR "Can't register aem driver\n"); |
| 1091 | return res; | 1093 | return res; |
| @@ -1097,7 +1099,7 @@ static int __init aem_init(void) | |||
| 1097 | return 0; | 1099 | return 0; |
| 1098 | 1100 | ||
| 1099 | ipmi_reg_err: | 1101 | ipmi_reg_err: |
| 1100 | driver_unregister(&aem_driver); | 1102 | driver_unregister(&aem_driver.driver); |
| 1101 | return res; | 1103 | return res; |
| 1102 | 1104 | ||
| 1103 | } | 1105 | } |
| @@ -1107,7 +1109,7 @@ static void __exit aem_exit(void) | |||
| 1107 | struct aem_data *p1, *next1; | 1109 | struct aem_data *p1, *next1; |
| 1108 | 1110 | ||
| 1109 | ipmi_smi_watcher_unregister(&driver_data.bmc_events); | 1111 | ipmi_smi_watcher_unregister(&driver_data.bmc_events); |
| 1110 | driver_unregister(&aem_driver); | 1112 | driver_unregister(&aem_driver.driver); |
| 1111 | list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list) | 1113 | list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list) |
| 1112 | aem_delete(p1); | 1114 | aem_delete(p1); |
| 1113 | } | 1115 | } |
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c new file mode 100644 index 000000000000..c002144c76bc --- /dev/null +++ b/drivers/hwmon/lis3lv02d.c | |||
| @@ -0,0 +1,581 @@ | |||
| 1 | /* | ||
| 2 | * lis3lv02d.c - ST LIS3LV02DL accelerometer driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007-2008 Yan Burman | ||
| 5 | * Copyright (C) 2008 Eric Piel | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/kernel.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/dmi.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/types.h> | ||
| 27 | #include <linux/platform_device.h> | ||
| 28 | #include <linux/interrupt.h> | ||
| 29 | #include <linux/input.h> | ||
| 30 | #include <linux/kthread.h> | ||
| 31 | #include <linux/semaphore.h> | ||
| 32 | #include <linux/delay.h> | ||
| 33 | #include <linux/wait.h> | ||
| 34 | #include <linux/poll.h> | ||
| 35 | #include <linux/freezer.h> | ||
| 36 | #include <linux/uaccess.h> | ||
| 37 | #include <acpi/acpi_drivers.h> | ||
| 38 | #include <asm/atomic.h> | ||
| 39 | #include "lis3lv02d.h" | ||
| 40 | |||
| 41 | #define DRIVER_NAME "lis3lv02d" | ||
| 42 | #define ACPI_MDPS_CLASS "accelerometer" | ||
| 43 | |||
| 44 | /* joystick device poll interval in milliseconds */ | ||
| 45 | #define MDPS_POLL_INTERVAL 50 | ||
| 46 | /* | ||
| 47 | * The sensor can also generate interrupts (DRDY) but it's pretty pointless | ||
| 48 | * because their are generated even if the data do not change. So it's better | ||
| 49 | * to keep the interrupt for the free-fall event. The values are updated at | ||
| 50 | * 40Hz (at the lowest frequency), but as it can be pretty time consuming on | ||
| 51 | * some low processor, we poll the sensor only at 20Hz... enough for the | ||
| 52 | * joystick. | ||
| 53 | */ | ||
| 54 | |||
| 55 | /* Maximum value our axis may get for the input device (signed 12 bits) */ | ||
| 56 | #define MDPS_MAX_VAL 2048 | ||
| 57 | |||
| 58 | struct axis_conversion { | ||
| 59 | s8 x; | ||
| 60 | s8 y; | ||
| 61 | s8 z; | ||
| 62 | }; | ||
| 63 | |||
| 64 | struct acpi_lis3lv02d { | ||
| 65 | struct acpi_device *device; /* The ACPI device */ | ||
| 66 | struct input_dev *idev; /* input device */ | ||
| 67 | struct task_struct *kthread; /* kthread for input */ | ||
| 68 | struct mutex lock; | ||
| 69 | struct platform_device *pdev; /* platform device */ | ||
| 70 | atomic_t count; /* interrupt count after last read */ | ||
| 71 | int xcalib; /* calibrated null value for x */ | ||
| 72 | int ycalib; /* calibrated null value for y */ | ||
| 73 | int zcalib; /* calibrated null value for z */ | ||
| 74 | unsigned char is_on; /* whether the device is on or off */ | ||
| 75 | unsigned char usage; /* usage counter */ | ||
| 76 | struct axis_conversion ac; /* hw -> logical axis */ | ||
| 77 | }; | ||
| 78 | |||
| 79 | static struct acpi_lis3lv02d adev; | ||
| 80 | |||
| 81 | static int lis3lv02d_remove_fs(void); | ||
| 82 | static int lis3lv02d_add_fs(struct acpi_device *device); | ||
| 83 | |||
| 84 | /* For automatic insertion of the module */ | ||
| 85 | static struct acpi_device_id lis3lv02d_device_ids[] = { | ||
| 86 | {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ | ||
| 87 | {"", 0}, | ||
| 88 | }; | ||
| 89 | MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); | ||
| 90 | |||
| 91 | /** | ||
| 92 | * lis3lv02d_acpi_init - ACPI _INI method: initialize the device. | ||
| 93 | * @handle: the handle of the device | ||
| 94 | * | ||
| 95 | * Returns AE_OK on success. | ||
| 96 | */ | ||
| 97 | static inline acpi_status lis3lv02d_acpi_init(acpi_handle handle) | ||
| 98 | { | ||
| 99 | return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL); | ||
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * lis3lv02d_acpi_read - ACPI ALRD method: read a register | ||
| 104 | * @handle: the handle of the device | ||
| 105 | * @reg: the register to read | ||
| 106 | * @ret: result of the operation | ||
| 107 | * | ||
| 108 | * Returns AE_OK on success. | ||
| 109 | */ | ||
| 110 | static acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret) | ||
| 111 | { | ||
| 112 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
| 113 | struct acpi_object_list args = { 1, &arg0 }; | ||
| 114 | unsigned long long lret; | ||
| 115 | acpi_status status; | ||
| 116 | |||
| 117 | arg0.integer.value = reg; | ||
| 118 | |||
| 119 | status = acpi_evaluate_integer(handle, "ALRD", &args, &lret); | ||
| 120 | *ret = lret; | ||
| 121 | return status; | ||
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * lis3lv02d_acpi_write - ACPI ALWR method: write to a register | ||
| 126 | * @handle: the handle of the device | ||
| 127 | * @reg: the register to write to | ||
| 128 | * @val: the value to write | ||
| 129 | * | ||
| 130 | * Returns AE_OK on success. | ||
| 131 | */ | ||
| 132 | static acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val) | ||
| 133 | { | ||
| 134 | unsigned long long ret; /* Not used when writting */ | ||
| 135 | union acpi_object in_obj[2]; | ||
| 136 | struct acpi_object_list args = { 2, in_obj }; | ||
| 137 | |||
| 138 | in_obj[0].type = ACPI_TYPE_INTEGER; | ||
| 139 | in_obj[0].integer.value = reg; | ||
| 140 | in_obj[1].type = ACPI_TYPE_INTEGER; | ||
| 141 | in_obj[1].integer.value = val; | ||
| 142 | |||
| 143 | return acpi_evaluate_integer(handle, "ALWR", &args, &ret); | ||
| 144 | } | ||
| 145 | |||
| 146 | static s16 lis3lv02d_read_16(acpi_handle handle, int reg) | ||
| 147 | { | ||
| 148 | u8 lo, hi; | ||
| 149 | |||
| 150 | lis3lv02d_acpi_read(handle, reg, &lo); | ||
| 151 | lis3lv02d_acpi_read(handle, reg + 1, &hi); | ||
| 152 | /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ | ||
| 153 | return (s16)((hi << 8) | lo); | ||
| 154 | } | ||
| 155 | |||
| 156 | /** | ||
| 157 | * lis3lv02d_get_axis - For the given axis, give the value converted | ||
| 158 | * @axis: 1,2,3 - can also be negative | ||
| 159 | * @hw_values: raw values returned by the hardware | ||
| 160 | * | ||
| 161 | * Returns the converted value. | ||
| 162 | */ | ||
| 163 | static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3]) | ||
| 164 | { | ||
| 165 | if (axis > 0) | ||
| 166 | return hw_values[axis - 1]; | ||
| 167 | else | ||
| 168 | return -hw_values[-axis - 1]; | ||
| 169 | } | ||
| 170 | |||
| 171 | /** | ||
| 172 | * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer | ||
| 173 | * @handle: the handle to the device | ||
| 174 | * @x: where to store the X axis value | ||
| 175 | * @y: where to store the Y axis value | ||
| 176 | * @z: where to store the Z axis value | ||
| 177 | * | ||
| 178 | * Note that 40Hz input device can eat up about 10% CPU at 800MHZ | ||
| 179 | */ | ||
| 180 | static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z) | ||
| 181 | { | ||
| 182 | int position[3]; | ||
| 183 | |||
| 184 | position[0] = lis3lv02d_read_16(handle, OUTX_L); | ||
| 185 | position[1] = lis3lv02d_read_16(handle, OUTY_L); | ||
| 186 | position[2] = lis3lv02d_read_16(handle, OUTZ_L); | ||
| 187 | |||
| 188 | *x = lis3lv02d_get_axis(adev.ac.x, position); | ||
| 189 | *y = lis3lv02d_get_axis(adev.ac.y, position); | ||
| 190 | *z = lis3lv02d_get_axis(adev.ac.z, position); | ||
| 191 | } | ||
| 192 | |||
| 193 | static inline void lis3lv02d_poweroff(acpi_handle handle) | ||
| 194 | { | ||
| 195 | adev.is_on = 0; | ||
| 196 | /* disable X,Y,Z axis and power down */ | ||
| 197 | lis3lv02d_acpi_write(handle, CTRL_REG1, 0x00); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void lis3lv02d_poweron(acpi_handle handle) | ||
| 201 | { | ||
| 202 | u8 val; | ||
| 203 | |||
| 204 | adev.is_on = 1; | ||
| 205 | lis3lv02d_acpi_init(handle); | ||
| 206 | lis3lv02d_acpi_write(handle, FF_WU_CFG, 0); | ||
| 207 | /* | ||
| 208 | * BDU: LSB and MSB values are not updated until both have been read. | ||
| 209 | * So the value read will always be correct. | ||
| 210 | * IEN: Interrupt for free-fall and DD, not for data-ready. | ||
| 211 | */ | ||
| 212 | lis3lv02d_acpi_read(handle, CTRL_REG2, &val); | ||
| 213 | val |= CTRL2_BDU | CTRL2_IEN; | ||
| 214 | lis3lv02d_acpi_write(handle, CTRL_REG2, val); | ||
| 215 | } | ||
| 216 | |||
| 217 | #ifdef CONFIG_PM | ||
| 218 | static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) | ||
| 219 | { | ||
| 220 | /* make sure the device is off when we suspend */ | ||
| 221 | lis3lv02d_poweroff(device->handle); | ||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static int lis3lv02d_resume(struct acpi_device *device) | ||
| 226 | { | ||
| 227 | /* put back the device in the right state (ACPI might turn it on) */ | ||
| 228 | mutex_lock(&adev.lock); | ||
| 229 | if (adev.usage > 0) | ||
| 230 | lis3lv02d_poweron(device->handle); | ||
| 231 | else | ||
| 232 | lis3lv02d_poweroff(device->handle); | ||
| 233 | mutex_unlock(&adev.lock); | ||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | #else | ||
| 237 | #define lis3lv02d_suspend NULL | ||
| 238 | #define lis3lv02d_resume NULL | ||
| 239 | #endif | ||
| 240 | |||
| 241 | |||
| 242 | /* | ||
| 243 | * To be called before starting to use the device. It makes sure that the | ||
| 244 | * device will always be on until a call to lis3lv02d_decrease_use(). Not to be | ||
| 245 | * used from interrupt context. | ||
| 246 | */ | ||
| 247 | static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev) | ||
| 248 | { | ||
| 249 | mutex_lock(&dev->lock); | ||
| 250 | dev->usage++; | ||
| 251 | if (dev->usage == 1) { | ||
| 252 | if (!dev->is_on) | ||
| 253 | lis3lv02d_poweron(dev->device->handle); | ||
| 254 | } | ||
| 255 | mutex_unlock(&dev->lock); | ||
| 256 | } | ||
| 257 | |||
| 258 | /* | ||
| 259 | * To be called whenever a usage of the device is stopped. | ||
| 260 | * It will make sure to turn off the device when there is not usage. | ||
| 261 | */ | ||
| 262 | static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev) | ||
| 263 | { | ||
| 264 | mutex_lock(&dev->lock); | ||
| 265 | dev->usage--; | ||
| 266 | if (dev->usage == 0) | ||
| 267 | lis3lv02d_poweroff(dev->device->handle); | ||
| 268 | mutex_unlock(&dev->lock); | ||
| 269 | } | ||
| 270 | |||
| 271 | /** | ||
| 272 | * lis3lv02d_joystick_kthread - Kthread polling function | ||
| 273 | * @data: unused - here to conform to threadfn prototype | ||
| 274 | */ | ||
| 275 | static int lis3lv02d_joystick_kthread(void *data) | ||
| 276 | { | ||
| 277 | int x, y, z; | ||
| 278 | |||
| 279 | while (!kthread_should_stop()) { | ||
| 280 | lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); | ||
| 281 | input_report_abs(adev.idev, ABS_X, x - adev.xcalib); | ||
| 282 | input_report_abs(adev.idev, ABS_Y, y - adev.ycalib); | ||
| 283 | input_report_abs(adev.idev, ABS_Z, z - adev.zcalib); | ||
| 284 | |||
| 285 | input_sync(adev.idev); | ||
| 286 | |||
| 287 | try_to_freeze(); | ||
| 288 | msleep_interruptible(MDPS_POLL_INTERVAL); | ||
| 289 | } | ||
| 290 | |||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int lis3lv02d_joystick_open(struct input_dev *input) | ||
| 295 | { | ||
| 296 | lis3lv02d_increase_use(&adev); | ||
| 297 | adev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d"); | ||
| 298 | if (IS_ERR(adev.kthread)) { | ||
| 299 | lis3lv02d_decrease_use(&adev); | ||
| 300 | return PTR_ERR(adev.kthread); | ||
| 301 | } | ||
| 302 | |||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | static void lis3lv02d_joystick_close(struct input_dev *input) | ||
| 307 | { | ||
| 308 | kthread_stop(adev.kthread); | ||
| 309 | lis3lv02d_decrease_use(&adev); | ||
| 310 | } | ||
| 311 | |||
| 312 | |||
| 313 | static inline void lis3lv02d_calibrate_joystick(void) | ||
| 314 | { | ||
| 315 | lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib); | ||
| 316 | } | ||
| 317 | |||
| 318 | static int lis3lv02d_joystick_enable(void) | ||
| 319 | { | ||
| 320 | int err; | ||
| 321 | |||
| 322 | if (adev.idev) | ||
| 323 | return -EINVAL; | ||
| 324 | |||
| 325 | adev.idev = input_allocate_device(); | ||
| 326 | if (!adev.idev) | ||
| 327 | return -ENOMEM; | ||
| 328 | |||
| 329 | lis3lv02d_calibrate_joystick(); | ||
| 330 | |||
| 331 | adev.idev->name = "ST LIS3LV02DL Accelerometer"; | ||
| 332 | adev.idev->phys = DRIVER_NAME "/input0"; | ||
| 333 | adev.idev->id.bustype = BUS_HOST; | ||
| 334 | adev.idev->id.vendor = 0; | ||
| 335 | adev.idev->dev.parent = &adev.pdev->dev; | ||
| 336 | adev.idev->open = lis3lv02d_joystick_open; | ||
| 337 | adev.idev->close = lis3lv02d_joystick_close; | ||
| 338 | |||
| 339 | set_bit(EV_ABS, adev.idev->evbit); | ||
| 340 | input_set_abs_params(adev.idev, ABS_X, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); | ||
| 341 | input_set_abs_params(adev.idev, ABS_Y, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); | ||
| 342 | input_set_abs_params(adev.idev, ABS_Z, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); | ||
| 343 | |||
| 344 | err = input_register_device(adev.idev); | ||
| 345 | if (err) { | ||
| 346 | input_free_device(adev.idev); | ||
| 347 | adev.idev = NULL; | ||
| 348 | } | ||
| 349 | |||
| 350 | return err; | ||
| 351 | } | ||
| 352 | |||
| 353 | static void lis3lv02d_joystick_disable(void) | ||
| 354 | { | ||
| 355 | if (!adev.idev) | ||
| 356 | return; | ||
| 357 | |||
| 358 | input_unregister_device(adev.idev); | ||
| 359 | adev.idev = NULL; | ||
| 360 | } | ||
| 361 | |||
| 362 | |||
| 363 | /* | ||
| 364 | * Initialise the accelerometer and the various subsystems. | ||
| 365 | * Should be rather independant of the bus system. | ||
| 366 | */ | ||
| 367 | static int lis3lv02d_init_device(struct acpi_lis3lv02d *dev) | ||
| 368 | { | ||
| 369 | mutex_init(&dev->lock); | ||
| 370 | lis3lv02d_add_fs(dev->device); | ||
| 371 | lis3lv02d_increase_use(dev); | ||
| 372 | |||
| 373 | if (lis3lv02d_joystick_enable()) | ||
| 374 | printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); | ||
| 375 | |||
| 376 | lis3lv02d_decrease_use(dev); | ||
| 377 | return 0; | ||
| 378 | } | ||
| 379 | |||
| 380 | static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) | ||
| 381 | { | ||
| 382 | adev.ac = *((struct axis_conversion *)dmi->driver_data); | ||
| 383 | printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); | ||
| 384 | |||
| 385 | return 1; | ||
| 386 | } | ||
| 387 | |||
| 388 | /* Represents, for each axis seen by userspace, the corresponding hw axis (+1). | ||
| 389 | * If the value is negative, the opposite of the hw value is used. */ | ||
| 390 | static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3}; | ||
| 391 | static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3}; | ||
| 392 | static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3}; | ||
| 393 | static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3}; | ||
| 394 | static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3}; | ||
| 395 | static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3}; | ||
| 396 | |||
| 397 | #define AXIS_DMI_MATCH(_ident, _name, _axis) { \ | ||
| 398 | .ident = _ident, \ | ||
| 399 | .callback = lis3lv02d_dmi_matched, \ | ||
| 400 | .matches = { \ | ||
| 401 | DMI_MATCH(DMI_PRODUCT_NAME, _name) \ | ||
| 402 | }, \ | ||
| 403 | .driver_data = &lis3lv02d_axis_##_axis \ | ||
| 404 | } | ||
| 405 | static struct dmi_system_id lis3lv02d_dmi_ids[] = { | ||
| 406 | /* product names are truncated to match all kinds of a same model */ | ||
| 407 | AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), | ||
| 408 | AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), | ||
| 409 | AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted), | ||
| 410 | AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted), | ||
| 411 | AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), | ||
| 412 | AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), | ||
| 413 | AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), | ||
| 414 | { NULL, } | ||
| 415 | /* Laptop models without axis info (yet): | ||
| 416 | * "NC651xx" "HP Compaq 651" | ||
| 417 | * "NC671xx" "HP Compaq 671" | ||
| 418 | * "NC6910" "HP Compaq 6910" | ||
| 419 | * HP Compaq 8710x Notebook PC / Mobile Workstation | ||
| 420 | * "NC2400" "HP Compaq nc2400" | ||
| 421 | * "NX74x0" "HP Compaq nx74" | ||
| 422 | * "NX6325" "HP Compaq nx6325" | ||
| 423 | * "NC4400" "HP Compaq nc4400" | ||
| 424 | */ | ||
| 425 | }; | ||
| 426 | |||
| 427 | static int lis3lv02d_add(struct acpi_device *device) | ||
| 428 | { | ||
| 429 | u8 val; | ||
| 430 | |||
| 431 | if (!device) | ||
| 432 | return -EINVAL; | ||
| 433 | |||
| 434 | adev.device = device; | ||
| 435 | strcpy(acpi_device_name(device), DRIVER_NAME); | ||
| 436 | strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); | ||
| 437 | device->driver_data = &adev; | ||
| 438 | |||
| 439 | lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val); | ||
| 440 | if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) { | ||
| 441 | printk(KERN_ERR DRIVER_NAME | ||
| 442 | ": Accelerometer chip not LIS3LV02D{L,Q}\n"); | ||
| 443 | } | ||
| 444 | |||
| 445 | /* If possible use a "standard" axes order */ | ||
| 446 | if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { | ||
| 447 | printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " | ||
| 448 | "using default axes configuration\n"); | ||
| 449 | adev.ac = lis3lv02d_axis_normal; | ||
| 450 | } | ||
| 451 | |||
| 452 | return lis3lv02d_init_device(&adev); | ||
| 453 | } | ||
| 454 | |||
| 455 | static int lis3lv02d_remove(struct acpi_device *device, int type) | ||
| 456 | { | ||
| 457 | if (!device) | ||
| 458 | return -EINVAL; | ||
| 459 | |||
| 460 | lis3lv02d_joystick_disable(); | ||
| 461 | lis3lv02d_poweroff(device->handle); | ||
| 462 | |||
| 463 | return lis3lv02d_remove_fs(); | ||
| 464 | } | ||
| 465 | |||
| 466 | |||
| 467 | /* Sysfs stuff */ | ||
| 468 | static ssize_t lis3lv02d_position_show(struct device *dev, | ||
| 469 | struct device_attribute *attr, char *buf) | ||
| 470 | { | ||
| 471 | int x, y, z; | ||
| 472 | |||
| 473 | lis3lv02d_increase_use(&adev); | ||
| 474 | lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); | ||
| 475 | lis3lv02d_decrease_use(&adev); | ||
| 476 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); | ||
| 477 | } | ||
| 478 | |||
| 479 | static ssize_t lis3lv02d_calibrate_show(struct device *dev, | ||
| 480 | struct device_attribute *attr, char *buf) | ||
| 481 | { | ||
| 482 | return sprintf(buf, "(%d,%d,%d)\n", adev.xcalib, adev.ycalib, adev.zcalib); | ||
| 483 | } | ||
| 484 | |||
| 485 | static ssize_t lis3lv02d_calibrate_store(struct device *dev, | ||
| 486 | struct device_attribute *attr, | ||
| 487 | const char *buf, size_t count) | ||
| 488 | { | ||
| 489 | lis3lv02d_increase_use(&adev); | ||
| 490 | lis3lv02d_calibrate_joystick(); | ||
| 491 | lis3lv02d_decrease_use(&adev); | ||
| 492 | return count; | ||
| 493 | } | ||
| 494 | |||
| 495 | /* conversion btw sampling rate and the register values */ | ||
| 496 | static int lis3lv02dl_df_val[4] = {40, 160, 640, 2560}; | ||
| 497 | static ssize_t lis3lv02d_rate_show(struct device *dev, | ||
| 498 | struct device_attribute *attr, char *buf) | ||
| 499 | { | ||
| 500 | u8 ctrl; | ||
| 501 | int val; | ||
| 502 | |||
| 503 | lis3lv02d_increase_use(&adev); | ||
| 504 | lis3lv02d_acpi_read(adev.device->handle, CTRL_REG1, &ctrl); | ||
| 505 | lis3lv02d_decrease_use(&adev); | ||
| 506 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; | ||
| 507 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); | ||
| 508 | } | ||
| 509 | |||
| 510 | static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL); | ||
| 511 | static DEVICE_ATTR(calibrate, S_IRUGO|S_IWUSR, lis3lv02d_calibrate_show, | ||
| 512 | lis3lv02d_calibrate_store); | ||
| 513 | static DEVICE_ATTR(rate, S_IRUGO, lis3lv02d_rate_show, NULL); | ||
| 514 | |||
| 515 | static struct attribute *lis3lv02d_attributes[] = { | ||
| 516 | &dev_attr_position.attr, | ||
| 517 | &dev_attr_calibrate.attr, | ||
| 518 | &dev_attr_rate.attr, | ||
| 519 | NULL | ||
| 520 | }; | ||
| 521 | |||
| 522 | static struct attribute_group lis3lv02d_attribute_group = { | ||
| 523 | .attrs = lis3lv02d_attributes | ||
| 524 | }; | ||
| 525 | |||
| 526 | static int lis3lv02d_add_fs(struct acpi_device *device) | ||
| 527 | { | ||
| 528 | adev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); | ||
| 529 | if (IS_ERR(adev.pdev)) | ||
| 530 | return PTR_ERR(adev.pdev); | ||
| 531 | |||
| 532 | return sysfs_create_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); | ||
| 533 | } | ||
| 534 | |||
| 535 | static int lis3lv02d_remove_fs(void) | ||
| 536 | { | ||
| 537 | sysfs_remove_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); | ||
| 538 | platform_device_unregister(adev.pdev); | ||
| 539 | return 0; | ||
| 540 | } | ||
| 541 | |||
| 542 | /* For the HP MDPS aka 3D Driveguard */ | ||
| 543 | static struct acpi_driver lis3lv02d_driver = { | ||
| 544 | .name = DRIVER_NAME, | ||
| 545 | .class = ACPI_MDPS_CLASS, | ||
| 546 | .ids = lis3lv02d_device_ids, | ||
| 547 | .ops = { | ||
| 548 | .add = lis3lv02d_add, | ||
| 549 | .remove = lis3lv02d_remove, | ||
| 550 | .suspend = lis3lv02d_suspend, | ||
| 551 | .resume = lis3lv02d_resume, | ||
| 552 | } | ||
| 553 | }; | ||
| 554 | |||
| 555 | static int __init lis3lv02d_init_module(void) | ||
| 556 | { | ||
| 557 | int ret; | ||
| 558 | |||
| 559 | if (acpi_disabled) | ||
| 560 | return -ENODEV; | ||
| 561 | |||
| 562 | ret = acpi_bus_register_driver(&lis3lv02d_driver); | ||
| 563 | if (ret < 0) | ||
| 564 | return ret; | ||
| 565 | |||
| 566 | printk(KERN_INFO DRIVER_NAME " driver loaded.\n"); | ||
| 567 | |||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | static void __exit lis3lv02d_exit_module(void) | ||
| 572 | { | ||
| 573 | acpi_bus_unregister_driver(&lis3lv02d_driver); | ||
| 574 | } | ||
| 575 | |||
| 576 | MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); | ||
| 577 | MODULE_AUTHOR("Yan Burman and Eric Piel"); | ||
| 578 | MODULE_LICENSE("GPL"); | ||
| 579 | |||
| 580 | module_init(lis3lv02d_init_module); | ||
| 581 | module_exit(lis3lv02d_exit_module); | ||
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h new file mode 100644 index 000000000000..330cfc60e948 --- /dev/null +++ b/drivers/hwmon/lis3lv02d.h | |||
| @@ -0,0 +1,149 @@ | |||
| 1 | /* | ||
| 2 | * lis3lv02d.h - ST LIS3LV02DL accelerometer driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007-2008 Yan Burman | ||
| 5 | * Copyright (C) 2008 Eric Piel | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | /* | ||
| 23 | * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to | ||
| 24 | * be connected via SPI. There exists also several similar chips (such as LIS302DL or | ||
| 25 | * LIS3L02DQ) but not in the HP laptops and they have slightly different registers. | ||
| 26 | * They can also be connected via I²C. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #define LIS3LV02DL_ID 0x3A /* Also the LIS3LV02DQ */ | ||
| 30 | #define LIS302DL_ID 0x3B /* Also the LIS202DL! */ | ||
| 31 | |||
| 32 | enum lis3lv02d_reg { | ||
| 33 | WHO_AM_I = 0x0F, | ||
| 34 | OFFSET_X = 0x16, | ||
| 35 | OFFSET_Y = 0x17, | ||
| 36 | OFFSET_Z = 0x18, | ||
| 37 | GAIN_X = 0x19, | ||
| 38 | GAIN_Y = 0x1A, | ||
| 39 | GAIN_Z = 0x1B, | ||
| 40 | CTRL_REG1 = 0x20, | ||
| 41 | CTRL_REG2 = 0x21, | ||
| 42 | CTRL_REG3 = 0x22, | ||
| 43 | HP_FILTER_RESET = 0x23, | ||
| 44 | STATUS_REG = 0x27, | ||
| 45 | OUTX_L = 0x28, | ||
| 46 | OUTX_H = 0x29, | ||
| 47 | OUTY_L = 0x2A, | ||
| 48 | OUTY_H = 0x2B, | ||
| 49 | OUTZ_L = 0x2C, | ||
| 50 | OUTZ_H = 0x2D, | ||
| 51 | FF_WU_CFG = 0x30, | ||
| 52 | FF_WU_SRC = 0x31, | ||
| 53 | FF_WU_ACK = 0x32, | ||
| 54 | FF_WU_THS_L = 0x34, | ||
| 55 | FF_WU_THS_H = 0x35, | ||
| 56 | FF_WU_DURATION = 0x36, | ||
| 57 | DD_CFG = 0x38, | ||
| 58 | DD_SRC = 0x39, | ||
| 59 | DD_ACK = 0x3A, | ||
| 60 | DD_THSI_L = 0x3C, | ||
| 61 | DD_THSI_H = 0x3D, | ||
| 62 | DD_THSE_L = 0x3E, | ||
| 63 | DD_THSE_H = 0x3F, | ||
| 64 | }; | ||
| 65 | |||
| 66 | enum lis3lv02d_ctrl1 { | ||
| 67 | CTRL1_Xen = 0x01, | ||
| 68 | CTRL1_Yen = 0x02, | ||
| 69 | CTRL1_Zen = 0x04, | ||
| 70 | CTRL1_ST = 0x08, | ||
| 71 | CTRL1_DF0 = 0x10, | ||
| 72 | CTRL1_DF1 = 0x20, | ||
| 73 | CTRL1_PD0 = 0x40, | ||
| 74 | CTRL1_PD1 = 0x80, | ||
| 75 | }; | ||
| 76 | enum lis3lv02d_ctrl2 { | ||
| 77 | CTRL2_DAS = 0x01, | ||
| 78 | CTRL2_SIM = 0x02, | ||
| 79 | CTRL2_DRDY = 0x04, | ||
| 80 | CTRL2_IEN = 0x08, | ||
| 81 | CTRL2_BOOT = 0x10, | ||
| 82 | CTRL2_BLE = 0x20, | ||
| 83 | CTRL2_BDU = 0x40, /* Block Data Update */ | ||
| 84 | CTRL2_FS = 0x80, /* Full Scale selection */ | ||
| 85 | }; | ||
| 86 | |||
| 87 | |||
| 88 | enum lis3lv02d_ctrl3 { | ||
| 89 | CTRL3_CFS0 = 0x01, | ||
| 90 | CTRL3_CFS1 = 0x02, | ||
| 91 | CTRL3_FDS = 0x10, | ||
| 92 | CTRL3_HPFF = 0x20, | ||
| 93 | CTRL3_HPDD = 0x40, | ||
| 94 | CTRL3_ECK = 0x80, | ||
| 95 | }; | ||
| 96 | |||
| 97 | enum lis3lv02d_status_reg { | ||
| 98 | STATUS_XDA = 0x01, | ||
| 99 | STATUS_YDA = 0x02, | ||
| 100 | STATUS_ZDA = 0x04, | ||
| 101 | STATUS_XYZDA = 0x08, | ||
| 102 | STATUS_XOR = 0x10, | ||
| 103 | STATUS_YOR = 0x20, | ||
| 104 | STATUS_ZOR = 0x40, | ||
| 105 | STATUS_XYZOR = 0x80, | ||
| 106 | }; | ||
| 107 | |||
| 108 | enum lis3lv02d_ff_wu_cfg { | ||
| 109 | FF_WU_CFG_XLIE = 0x01, | ||
| 110 | FF_WU_CFG_XHIE = 0x02, | ||
| 111 | FF_WU_CFG_YLIE = 0x04, | ||
| 112 | FF_WU_CFG_YHIE = 0x08, | ||
| 113 | FF_WU_CFG_ZLIE = 0x10, | ||
| 114 | FF_WU_CFG_ZHIE = 0x20, | ||
| 115 | FF_WU_CFG_LIR = 0x40, | ||
| 116 | FF_WU_CFG_AOI = 0x80, | ||
| 117 | }; | ||
| 118 | |||
| 119 | enum lis3lv02d_ff_wu_src { | ||
| 120 | FF_WU_SRC_XL = 0x01, | ||
| 121 | FF_WU_SRC_XH = 0x02, | ||
| 122 | FF_WU_SRC_YL = 0x04, | ||
| 123 | FF_WU_SRC_YH = 0x08, | ||
| 124 | FF_WU_SRC_ZL = 0x10, | ||
| 125 | FF_WU_SRC_ZH = 0x20, | ||
| 126 | FF_WU_SRC_IA = 0x40, | ||
| 127 | }; | ||
| 128 | |||
| 129 | enum lis3lv02d_dd_cfg { | ||
| 130 | DD_CFG_XLIE = 0x01, | ||
| 131 | DD_CFG_XHIE = 0x02, | ||
| 132 | DD_CFG_YLIE = 0x04, | ||
| 133 | DD_CFG_YHIE = 0x08, | ||
| 134 | DD_CFG_ZLIE = 0x10, | ||
| 135 | DD_CFG_ZHIE = 0x20, | ||
| 136 | DD_CFG_LIR = 0x40, | ||
| 137 | DD_CFG_IEND = 0x80, | ||
| 138 | }; | ||
| 139 | |||
| 140 | enum lis3lv02d_dd_src { | ||
| 141 | DD_SRC_XL = 0x01, | ||
| 142 | DD_SRC_XH = 0x02, | ||
| 143 | DD_SRC_YL = 0x04, | ||
| 144 | DD_SRC_YH = 0x08, | ||
| 145 | DD_SRC_ZL = 0x10, | ||
| 146 | DD_SRC_ZH = 0x20, | ||
| 147 | DD_SRC_IA = 0x40, | ||
| 148 | }; | ||
| 149 | |||
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 3ff0285396fa..cfc1ee90f5a3 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c | |||
| @@ -39,7 +39,8 @@ | |||
| 39 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 39 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
| 40 | 40 | ||
| 41 | /* Insmod parameters */ | 41 | /* Insmod parameters */ |
| 42 | I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); | 42 | I2C_CLIENT_INSMOD_7(lm85b, lm85c, adm1027, adt7463, adt7468, emc6d100, |
| 43 | emc6d102); | ||
| 43 | 44 | ||
| 44 | /* The LM85 registers */ | 45 | /* The LM85 registers */ |
| 45 | 46 | ||
| @@ -59,6 +60,12 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); | |||
| 59 | 60 | ||
| 60 | #define LM85_REG_COMPANY 0x3e | 61 | #define LM85_REG_COMPANY 0x3e |
| 61 | #define LM85_REG_VERSTEP 0x3f | 62 | #define LM85_REG_VERSTEP 0x3f |
| 63 | |||
| 64 | #define ADT7468_REG_CFG5 0x7c | ||
| 65 | #define ADT7468_OFF64 0x01 | ||
| 66 | #define IS_ADT7468_OFF64(data) \ | ||
| 67 | ((data)->type == adt7468 && !((data)->cfg5 & ADT7468_OFF64)) | ||
| 68 | |||
| 62 | /* These are the recognized values for the above regs */ | 69 | /* These are the recognized values for the above regs */ |
| 63 | #define LM85_COMPANY_NATIONAL 0x01 | 70 | #define LM85_COMPANY_NATIONAL 0x01 |
| 64 | #define LM85_COMPANY_ANALOG_DEV 0x41 | 71 | #define LM85_COMPANY_ANALOG_DEV 0x41 |
| @@ -70,6 +77,8 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); | |||
| 70 | #define LM85_VERSTEP_ADM1027 0x60 | 77 | #define LM85_VERSTEP_ADM1027 0x60 |
| 71 | #define LM85_VERSTEP_ADT7463 0x62 | 78 | #define LM85_VERSTEP_ADT7463 0x62 |
| 72 | #define LM85_VERSTEP_ADT7463C 0x6A | 79 | #define LM85_VERSTEP_ADT7463C 0x6A |
| 80 | #define LM85_VERSTEP_ADT7468_1 0x71 | ||
| 81 | #define LM85_VERSTEP_ADT7468_2 0x72 | ||
| 73 | #define LM85_VERSTEP_EMC6D100_A0 0x60 | 82 | #define LM85_VERSTEP_EMC6D100_A0 0x60 |
| 74 | #define LM85_VERSTEP_EMC6D100_A1 0x61 | 83 | #define LM85_VERSTEP_EMC6D100_A1 0x61 |
| 75 | #define LM85_VERSTEP_EMC6D102 0x65 | 84 | #define LM85_VERSTEP_EMC6D102 0x65 |
| @@ -306,6 +315,7 @@ struct lm85_data { | |||
| 306 | u8 vid; /* Register value */ | 315 | u8 vid; /* Register value */ |
| 307 | u8 vrm; /* VRM version */ | 316 | u8 vrm; /* VRM version */ |
| 308 | u32 alarms; /* Register encoding, combined */ | 317 | u32 alarms; /* Register encoding, combined */ |
| 318 | u8 cfg5; /* Config Register 5 on ADT7468 */ | ||
| 309 | struct lm85_autofan autofan[3]; | 319 | struct lm85_autofan autofan[3]; |
| 310 | struct lm85_zone zone[3]; | 320 | struct lm85_zone zone[3]; |
| 311 | }; | 321 | }; |
| @@ -685,6 +695,9 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, | |||
| 685 | struct lm85_data *data = i2c_get_clientdata(client); | 695 | struct lm85_data *data = i2c_get_clientdata(client); |
| 686 | long val = simple_strtol(buf, NULL, 10); | 696 | long val = simple_strtol(buf, NULL, 10); |
| 687 | 697 | ||
| 698 | if (IS_ADT7468_OFF64(data)) | ||
| 699 | val += 64; | ||
| 700 | |||
| 688 | mutex_lock(&data->update_lock); | 701 | mutex_lock(&data->update_lock); |
| 689 | data->temp_min[nr] = TEMP_TO_REG(val); | 702 | data->temp_min[nr] = TEMP_TO_REG(val); |
| 690 | lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); | 703 | lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); |
| @@ -708,6 +721,9 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, | |||
| 708 | struct lm85_data *data = i2c_get_clientdata(client); | 721 | struct lm85_data *data = i2c_get_clientdata(client); |
| 709 | long val = simple_strtol(buf, NULL, 10); | 722 | long val = simple_strtol(buf, NULL, 10); |
| 710 | 723 | ||
| 724 | if (IS_ADT7468_OFF64(data)) | ||
| 725 | val += 64; | ||
| 726 | |||
| 711 | mutex_lock(&data->update_lock); | 727 | mutex_lock(&data->update_lock); |
| 712 | data->temp_max[nr] = TEMP_TO_REG(val); | 728 | data->temp_max[nr] = TEMP_TO_REG(val); |
| 713 | lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); | 729 | lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); |
| @@ -1163,6 +1179,10 @@ static int lm85_detect(struct i2c_client *client, int kind, | |||
| 1163 | case LM85_VERSTEP_ADT7463C: | 1179 | case LM85_VERSTEP_ADT7463C: |
| 1164 | kind = adt7463; | 1180 | kind = adt7463; |
| 1165 | break; | 1181 | break; |
| 1182 | case LM85_VERSTEP_ADT7468_1: | ||
| 1183 | case LM85_VERSTEP_ADT7468_2: | ||
| 1184 | kind = adt7468; | ||
| 1185 | break; | ||
| 1166 | } | 1186 | } |
| 1167 | } else if (company == LM85_COMPANY_SMSC) { | 1187 | } else if (company == LM85_COMPANY_SMSC) { |
| 1168 | switch (verstep) { | 1188 | switch (verstep) { |
| @@ -1195,6 +1215,9 @@ static int lm85_detect(struct i2c_client *client, int kind, | |||
| 1195 | case adt7463: | 1215 | case adt7463: |
| 1196 | type_name = "adt7463"; | 1216 | type_name = "adt7463"; |
| 1197 | break; | 1217 | break; |
| 1218 | case adt7468: | ||
| 1219 | type_name = "adt7468"; | ||
| 1220 | break; | ||
| 1198 | case emc6d100: | 1221 | case emc6d100: |
| 1199 | type_name = "emc6d100"; | 1222 | type_name = "emc6d100"; |
| 1200 | break; | 1223 | break; |
| @@ -1246,10 +1269,11 @@ static int lm85_probe(struct i2c_client *client, | |||
| 1246 | if (err) | 1269 | if (err) |
| 1247 | goto err_kfree; | 1270 | goto err_kfree; |
| 1248 | 1271 | ||
| 1249 | /* The ADT7463 has an optional VRM 10 mode where pin 21 is used | 1272 | /* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used |
| 1250 | as a sixth digital VID input rather than an analog input. */ | 1273 | as a sixth digital VID input rather than an analog input. */ |
| 1251 | data->vid = lm85_read_value(client, LM85_REG_VID); | 1274 | data->vid = lm85_read_value(client, LM85_REG_VID); |
| 1252 | if (!(data->type == adt7463 && (data->vid & 0x80))) | 1275 | if (!((data->type == adt7463 || data->type == adt7468) && |
| 1276 | (data->vid & 0x80))) | ||
| 1253 | if ((err = sysfs_create_group(&client->dev.kobj, | 1277 | if ((err = sysfs_create_group(&client->dev.kobj, |
| 1254 | &lm85_group_in4))) | 1278 | &lm85_group_in4))) |
| 1255 | goto err_remove_files; | 1279 | goto err_remove_files; |
| @@ -1357,7 +1381,8 @@ static struct lm85_data *lm85_update_device(struct device *dev) | |||
| 1357 | * There are 2 additional resolution bits per channel and we | 1381 | * There are 2 additional resolution bits per channel and we |
| 1358 | * have room for 4, so we shift them to the left. | 1382 | * have room for 4, so we shift them to the left. |
| 1359 | */ | 1383 | */ |
| 1360 | if (data->type == adm1027 || data->type == adt7463) { | 1384 | if (data->type == adm1027 || data->type == adt7463 || |
| 1385 | data->type == adt7468) { | ||
| 1361 | int ext1 = lm85_read_value(client, | 1386 | int ext1 = lm85_read_value(client, |
| 1362 | ADM1027_REG_EXTEND_ADC1); | 1387 | ADM1027_REG_EXTEND_ADC1); |
| 1363 | int ext2 = lm85_read_value(client, | 1388 | int ext2 = lm85_read_value(client, |
| @@ -1382,16 +1407,23 @@ static struct lm85_data *lm85_update_device(struct device *dev) | |||
| 1382 | lm85_read_value(client, LM85_REG_FAN(i)); | 1407 | lm85_read_value(client, LM85_REG_FAN(i)); |
| 1383 | } | 1408 | } |
| 1384 | 1409 | ||
| 1385 | if (!(data->type == adt7463 && (data->vid & 0x80))) { | 1410 | if (!((data->type == adt7463 || data->type == adt7468) && |
| 1411 | (data->vid & 0x80))) { | ||
| 1386 | data->in[4] = lm85_read_value(client, | 1412 | data->in[4] = lm85_read_value(client, |
| 1387 | LM85_REG_IN(4)); | 1413 | LM85_REG_IN(4)); |
| 1388 | } | 1414 | } |
| 1389 | 1415 | ||
| 1416 | if (data->type == adt7468) | ||
| 1417 | data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); | ||
| 1418 | |||
| 1390 | for (i = 0; i <= 2; ++i) { | 1419 | for (i = 0; i <= 2; ++i) { |
| 1391 | data->temp[i] = | 1420 | data->temp[i] = |
| 1392 | lm85_read_value(client, LM85_REG_TEMP(i)); | 1421 | lm85_read_value(client, LM85_REG_TEMP(i)); |
| 1393 | data->pwm[i] = | 1422 | data->pwm[i] = |
| 1394 | lm85_read_value(client, LM85_REG_PWM(i)); | 1423 | lm85_read_value(client, LM85_REG_PWM(i)); |
| 1424 | |||
| 1425 | if (IS_ADT7468_OFF64(data)) | ||
| 1426 | data->temp[i] -= 64; | ||
| 1395 | } | 1427 | } |
| 1396 | 1428 | ||
| 1397 | data->alarms = lm85_read_value(client, LM85_REG_ALARM1); | 1429 | data->alarms = lm85_read_value(client, LM85_REG_ALARM1); |
| @@ -1446,7 +1478,8 @@ static struct lm85_data *lm85_update_device(struct device *dev) | |||
| 1446 | lm85_read_value(client, LM85_REG_FAN_MIN(i)); | 1478 | lm85_read_value(client, LM85_REG_FAN_MIN(i)); |
| 1447 | } | 1479 | } |
| 1448 | 1480 | ||
| 1449 | if (!(data->type == adt7463 && (data->vid & 0x80))) { | 1481 | if (!((data->type == adt7463 || data->type == adt7468) && |
| 1482 | (data->vid & 0x80))) { | ||
| 1450 | data->in_min[4] = lm85_read_value(client, | 1483 | data->in_min[4] = lm85_read_value(client, |
| 1451 | LM85_REG_IN_MIN(4)); | 1484 | LM85_REG_IN_MIN(4)); |
| 1452 | data->in_max[4] = lm85_read_value(client, | 1485 | data->in_max[4] = lm85_read_value(client, |
| @@ -1481,6 +1514,13 @@ static struct lm85_data *lm85_update_device(struct device *dev) | |||
| 1481 | lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); | 1514 | lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); |
| 1482 | data->zone[i].critical = | 1515 | data->zone[i].critical = |
| 1483 | lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); | 1516 | lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); |
| 1517 | |||
| 1518 | if (IS_ADT7468_OFF64(data)) { | ||
| 1519 | data->temp_min[i] -= 64; | ||
| 1520 | data->temp_max[i] -= 64; | ||
| 1521 | data->zone[i].limit -= 64; | ||
| 1522 | data->zone[i].critical -= 64; | ||
| 1523 | } | ||
| 1484 | } | 1524 | } |
| 1485 | 1525 | ||
| 1486 | i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); | 1526 | i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); |
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 640cbb237328..3384a717fec0 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
| @@ -318,7 +318,8 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd) | |||
| 318 | } else | 318 | } else |
| 319 | data = i2c_op(pd, OP_RX, 0); | 319 | data = i2c_op(pd, OP_RX, 0); |
| 320 | 320 | ||
| 321 | pd->msg->buf[real_pos] = data; | 321 | if (real_pos >= 0) |
| 322 | pd->msg->buf[real_pos] = data; | ||
| 322 | } while (0); | 323 | } while (0); |
| 323 | 324 | ||
| 324 | pd->pos++; | 325 | pd->pos++; |
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index cb199c815b53..f50210fe558f 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c | |||
| @@ -444,6 +444,7 @@ static struct pcmcia_device_id ide_ids[] = { | |||
| 444 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), | 444 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), |
| 445 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), | 445 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), |
| 446 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), | 446 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), |
| 447 | PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506), | ||
| 447 | PCMCIA_DEVICE_NULL, | 448 | PCMCIA_DEVICE_NULL, |
| 448 | }; | 449 | }; |
| 449 | MODULE_DEVICE_TABLE(pcmcia, ide_ids); | 450 | MODULE_DEVICE_TABLE(pcmcia, ide_ids); |
diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig index 108264de0ac9..f15e90a453d1 100644 --- a/drivers/idle/Kconfig +++ b/drivers/idle/Kconfig | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | 1 | ||
| 2 | menu "Memory power savings" | 2 | menu "Memory power savings" |
| 3 | depends on X86_64 | ||
| 3 | 4 | ||
| 4 | config I7300_IDLE_IOAT_CHANNEL | 5 | config I7300_IDLE_IOAT_CHANNEL |
| 5 | bool | 6 | bool |
| @@ -7,7 +8,7 @@ config I7300_IDLE_IOAT_CHANNEL | |||
| 7 | config I7300_IDLE | 8 | config I7300_IDLE |
| 8 | tristate "Intel chipset idle memory power saving driver" | 9 | tristate "Intel chipset idle memory power saving driver" |
| 9 | select I7300_IDLE_IOAT_CHANNEL | 10 | select I7300_IDLE_IOAT_CHANNEL |
| 10 | depends on X86_64 && EXPERIMENTAL | 11 | depends on EXPERIMENTAL |
| 11 | help | 12 | help |
| 12 | Enable memory power savings when idle with certain Intel server | 13 | Enable memory power savings when idle with certain Intel server |
| 13 | chipsets. The chipset must have I/O AT support, such as the | 14 | chipsets. The chipset must have I/O AT support, such as the |
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index ecff98043589..160ef482712d 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c | |||
| @@ -1102,9 +1102,7 @@ static u64 fw_vers_string_to_u64(struct iwch_dev *iwch_dev) | |||
| 1102 | char *cp, *next; | 1102 | char *cp, *next; |
| 1103 | unsigned fw_maj, fw_min, fw_mic; | 1103 | unsigned fw_maj, fw_min, fw_mic; |
| 1104 | 1104 | ||
| 1105 | rtnl_lock(); | ||
| 1106 | lldev->ethtool_ops->get_drvinfo(lldev, &info); | 1105 | lldev->ethtool_ops->get_drvinfo(lldev, &info); |
| 1107 | rtnl_unlock(); | ||
| 1108 | 1106 | ||
| 1109 | next = info.fw_version + 1; | 1107 | next = info.fw_version + 1; |
| 1110 | cp = strsep(&next, "."); | 1108 | cp = strsep(&next, "."); |
| @@ -1192,9 +1190,7 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, ch | |||
| 1192 | struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; | 1190 | struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; |
| 1193 | 1191 | ||
| 1194 | PDBG("%s dev 0x%p\n", __func__, dev); | 1192 | PDBG("%s dev 0x%p\n", __func__, dev); |
| 1195 | rtnl_lock(); | ||
| 1196 | lldev->ethtool_ops->get_drvinfo(lldev, &info); | 1193 | lldev->ethtool_ops->get_drvinfo(lldev, &info); |
| 1197 | rtnl_unlock(); | ||
| 1198 | return sprintf(buf, "%s\n", info.fw_version); | 1194 | return sprintf(buf, "%s\n", info.fw_version); |
| 1199 | } | 1195 | } |
| 1200 | 1196 | ||
| @@ -1207,9 +1203,7 @@ static ssize_t show_hca(struct device *dev, struct device_attribute *attr, | |||
| 1207 | struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; | 1203 | struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; |
| 1208 | 1204 | ||
| 1209 | PDBG("%s dev 0x%p\n", __func__, dev); | 1205 | PDBG("%s dev 0x%p\n", __func__, dev); |
| 1210 | rtnl_lock(); | ||
| 1211 | lldev->ethtool_ops->get_drvinfo(lldev, &info); | 1206 | lldev->ethtool_ops->get_drvinfo(lldev, &info); |
| 1212 | rtnl_unlock(); | ||
| 1213 | return sprintf(buf, "%s\n", info.driver); | 1207 | return sprintf(buf, "%s\n", info.driver); |
| 1214 | } | 1208 | } |
| 1215 | 1209 | ||
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 3e4585c2318a..19661b2f0406 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c | |||
| @@ -745,7 +745,6 @@ int iwch_post_zb_read(struct iwch_qp *qhp) | |||
| 745 | wqe->read.rdmaop = T3_READ_REQ; | 745 | wqe->read.rdmaop = T3_READ_REQ; |
| 746 | wqe->read.reserved[0] = 0; | 746 | wqe->read.reserved[0] = 0; |
| 747 | wqe->read.reserved[1] = 0; | 747 | wqe->read.reserved[1] = 0; |
| 748 | wqe->read.reserved[2] = 0; | ||
| 749 | wqe->read.rem_stag = cpu_to_be32(1); | 748 | wqe->read.rem_stag = cpu_to_be32(1); |
| 750 | wqe->read.rem_to = cpu_to_be64(1); | 749 | wqe->read.rem_to = cpu_to_be64(1); |
| 751 | wqe->read.local_stag = cpu_to_be32(1); | 750 | wqe->read.local_stag = cpu_to_be32(1); |
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index cb55be04442c..757035ea246f 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c | |||
| @@ -359,36 +359,48 @@ static void notify_port_conf_change(struct ehca_shca *shca, int port_num) | |||
| 359 | *old_attr = new_attr; | 359 | *old_attr = new_attr; |
| 360 | } | 360 | } |
| 361 | 361 | ||
| 362 | /* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */ | ||
| 363 | static int replay_modify_qp(struct ehca_sport *sport) | ||
| 364 | { | ||
| 365 | int aqp1_destroyed; | ||
| 366 | unsigned long flags; | ||
| 367 | |||
| 368 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | ||
| 369 | |||
| 370 | aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI]; | ||
| 371 | |||
| 372 | if (sport->ibqp_sqp[IB_QPT_SMI]) | ||
| 373 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); | ||
| 374 | if (!aqp1_destroyed) | ||
| 375 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); | ||
| 376 | |||
| 377 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
| 378 | |||
| 379 | return aqp1_destroyed; | ||
| 380 | } | ||
| 381 | |||
| 362 | static void parse_ec(struct ehca_shca *shca, u64 eqe) | 382 | static void parse_ec(struct ehca_shca *shca, u64 eqe) |
| 363 | { | 383 | { |
| 364 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); | 384 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); |
| 365 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); | 385 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); |
| 366 | u8 spec_event; | 386 | u8 spec_event; |
| 367 | struct ehca_sport *sport = &shca->sport[port - 1]; | 387 | struct ehca_sport *sport = &shca->sport[port - 1]; |
| 368 | unsigned long flags; | ||
| 369 | 388 | ||
| 370 | switch (ec) { | 389 | switch (ec) { |
| 371 | case 0x30: /* port availability change */ | 390 | case 0x30: /* port availability change */ |
| 372 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { | 391 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { |
| 373 | int suppress_event; | 392 | /* only replay modify_qp calls in autodetect mode; |
| 374 | /* replay modify_qp for sqps */ | 393 | * if AQP1 was destroyed, the port is already down |
| 375 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | 394 | * again and we can drop the event. |
| 376 | suppress_event = !sport->ibqp_sqp[IB_QPT_GSI]; | 395 | */ |
| 377 | if (sport->ibqp_sqp[IB_QPT_SMI]) | 396 | if (ehca_nr_ports < 0) |
| 378 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); | 397 | if (replay_modify_qp(sport)) |
| 379 | if (!suppress_event) | 398 | break; |
| 380 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); | ||
| 381 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
| 382 | |||
| 383 | /* AQP1 was destroyed, ignore this event */ | ||
| 384 | if (suppress_event) | ||
| 385 | break; | ||
| 386 | 399 | ||
| 387 | sport->port_state = IB_PORT_ACTIVE; | 400 | sport->port_state = IB_PORT_ACTIVE; |
| 388 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, | 401 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, |
| 389 | "is active"); | 402 | "is active"); |
| 390 | ehca_query_sma_attr(shca, port, | 403 | ehca_query_sma_attr(shca, port, &sport->saved_attr); |
| 391 | &sport->saved_attr); | ||
| 392 | } else { | 404 | } else { |
| 393 | sport->port_state = IB_PORT_DOWN; | 405 | sport->port_state = IB_PORT_DOWN; |
| 394 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, | 406 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, |
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 4d54b9f64567..9e05ee2db39b 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c | |||
| @@ -860,6 +860,11 @@ static struct ehca_qp *internal_create_qp( | |||
| 860 | if (qp_type == IB_QPT_GSI) { | 860 | if (qp_type == IB_QPT_GSI) { |
| 861 | h_ret = ehca_define_sqp(shca, my_qp, init_attr); | 861 | h_ret = ehca_define_sqp(shca, my_qp, init_attr); |
| 862 | if (h_ret != H_SUCCESS) { | 862 | if (h_ret != H_SUCCESS) { |
| 863 | kfree(my_qp->mod_qp_parm); | ||
| 864 | my_qp->mod_qp_parm = NULL; | ||
| 865 | /* the QP pointer is no longer valid */ | ||
| 866 | shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] = | ||
| 867 | NULL; | ||
| 863 | ret = ehca2ib_return_code(h_ret); | 868 | ret = ehca2ib_return_code(h_ret); |
| 864 | goto create_qp_exit6; | 869 | goto create_qp_exit6; |
| 865 | } | 870 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index fc0f6d9e6030..2296832f94da 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c | |||
| @@ -156,7 +156,7 @@ bail: | |||
| 156 | /** | 156 | /** |
| 157 | * ipath_get_rwqe - copy the next RWQE into the QP's RWQE | 157 | * ipath_get_rwqe - copy the next RWQE into the QP's RWQE |
| 158 | * @qp: the QP | 158 | * @qp: the QP |
| 159 | * @wr_id_only: update wr_id only, not SGEs | 159 | * @wr_id_only: update qp->r_wr_id only, not qp->r_sge |
| 160 | * | 160 | * |
| 161 | * Return 0 if no RWQE is available, otherwise return 1. | 161 | * Return 0 if no RWQE is available, otherwise return 1. |
| 162 | * | 162 | * |
| @@ -173,8 +173,6 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) | |||
| 173 | u32 tail; | 173 | u32 tail; |
| 174 | int ret; | 174 | int ret; |
| 175 | 175 | ||
| 176 | qp->r_sge.sg_list = qp->r_sg_list; | ||
| 177 | |||
| 178 | if (qp->ibqp.srq) { | 176 | if (qp->ibqp.srq) { |
| 179 | srq = to_isrq(qp->ibqp.srq); | 177 | srq = to_isrq(qp->ibqp.srq); |
| 180 | handler = srq->ibsrq.event_handler; | 178 | handler = srq->ibsrq.event_handler; |
| @@ -206,8 +204,10 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) | |||
| 206 | wqe = get_rwqe_ptr(rq, tail); | 204 | wqe = get_rwqe_ptr(rq, tail); |
| 207 | if (++tail >= rq->size) | 205 | if (++tail >= rq->size) |
| 208 | tail = 0; | 206 | tail = 0; |
| 209 | } while (!wr_id_only && !ipath_init_sge(qp, wqe, &qp->r_len, | 207 | if (wr_id_only) |
| 210 | &qp->r_sge)); | 208 | break; |
| 209 | qp->r_sge.sg_list = qp->r_sg_list; | ||
| 210 | } while (!ipath_init_sge(qp, wqe, &qp->r_len, &qp->r_sge)); | ||
| 211 | qp->r_wr_id = wqe->wr_id; | 211 | qp->r_wr_id = wqe->wr_id; |
| 212 | wq->tail = tail; | 212 | wq->tail = tail; |
| 213 | 213 | ||
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index 87f5c5a87b98..8e4d26d56a95 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c | |||
| @@ -205,6 +205,7 @@ struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd, | |||
| 205 | goto err_mr; | 205 | goto err_mr; |
| 206 | 206 | ||
| 207 | mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; | 207 | mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; |
| 208 | mr->umem = NULL; | ||
| 208 | 209 | ||
| 209 | return &mr->ibmr; | 210 | return &mr->ibmr; |
| 210 | 211 | ||
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index a2b04d62b1a4..aa1dc41f04c8 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c | |||
| @@ -95,6 +95,10 @@ unsigned int wqm_quanta = 0x10000; | |||
| 95 | module_param(wqm_quanta, int, 0644); | 95 | module_param(wqm_quanta, int, 0644); |
| 96 | MODULE_PARM_DESC(wqm_quanta, "WQM quanta"); | 96 | MODULE_PARM_DESC(wqm_quanta, "WQM quanta"); |
| 97 | 97 | ||
| 98 | static unsigned int limit_maxrdreqsz; | ||
| 99 | module_param(limit_maxrdreqsz, bool, 0644); | ||
| 100 | MODULE_PARM_DESC(limit_maxrdreqsz, "Limit max read request size to 256 Bytes"); | ||
| 101 | |||
| 98 | LIST_HEAD(nes_adapter_list); | 102 | LIST_HEAD(nes_adapter_list); |
| 99 | static LIST_HEAD(nes_dev_list); | 103 | static LIST_HEAD(nes_dev_list); |
| 100 | 104 | ||
| @@ -588,6 +592,18 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i | |||
| 588 | nesdev->nesadapter->port_count; | 592 | nesdev->nesadapter->port_count; |
| 589 | } | 593 | } |
| 590 | 594 | ||
| 595 | if ((limit_maxrdreqsz || | ||
| 596 | ((nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_GLADIUS) && | ||
| 597 | (hw_rev == NE020_REV1))) && | ||
| 598 | (pcie_get_readrq(pcidev) > 256)) { | ||
| 599 | if (pcie_set_readrq(pcidev, 256)) | ||
| 600 | printk(KERN_ERR PFX "Unable to set max read request" | ||
| 601 | " to 256 bytes\n"); | ||
| 602 | else | ||
| 603 | nes_debug(NES_DBG_INIT, "Max read request size set" | ||
| 604 | " to 256 bytes\n"); | ||
| 605 | } | ||
| 606 | |||
| 591 | tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); | 607 | tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); |
| 592 | 608 | ||
| 593 | /* bring up the Control QP */ | 609 | /* bring up the Control QP */ |
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 610b9d859597..bc0b4de04450 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #define NES_PHY_TYPE_ARGUS 4 | 40 | #define NES_PHY_TYPE_ARGUS 4 |
| 41 | #define NES_PHY_TYPE_PUMA_1G 5 | 41 | #define NES_PHY_TYPE_PUMA_1G 5 |
| 42 | #define NES_PHY_TYPE_PUMA_10G 6 | 42 | #define NES_PHY_TYPE_PUMA_10G 6 |
| 43 | #define NES_PHY_TYPE_GLADIUS 7 | ||
| 43 | 44 | ||
| 44 | #define NES_MULTICAST_PF_MAX 8 | 45 | #define NES_MULTICAST_PF_MAX 8 |
| 45 | 46 | ||
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 932e56fcf774..d36c9a0bf1bb 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
| @@ -220,14 +220,14 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, | |||
| 220 | if (nesqp->ibqp_state > IB_QPS_RTS) | 220 | if (nesqp->ibqp_state > IB_QPS_RTS) |
| 221 | return -EINVAL; | 221 | return -EINVAL; |
| 222 | 222 | ||
| 223 | spin_lock_irqsave(&nesqp->lock, flags); | 223 | spin_lock_irqsave(&nesqp->lock, flags); |
| 224 | 224 | ||
| 225 | head = nesqp->hwqp.sq_head; | 225 | head = nesqp->hwqp.sq_head; |
| 226 | qsize = nesqp->hwqp.sq_tail; | 226 | qsize = nesqp->hwqp.sq_tail; |
| 227 | 227 | ||
| 228 | /* Check for SQ overflow */ | 228 | /* Check for SQ overflow */ |
| 229 | if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) { | 229 | if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) { |
| 230 | spin_unlock_irqrestore(&nesqp->lock, flags); | 230 | spin_unlock_irqrestore(&nesqp->lock, flags); |
| 231 | return -EINVAL; | 231 | return -EINVAL; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| @@ -269,7 +269,7 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, | |||
| 269 | nes_write32(nesdev->regs+NES_WQE_ALLOC, | 269 | nes_write32(nesdev->regs+NES_WQE_ALLOC, |
| 270 | (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); | 270 | (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); |
| 271 | 271 | ||
| 272 | spin_unlock_irqrestore(&nesqp->lock, flags); | 272 | spin_unlock_irqrestore(&nesqp->lock, flags); |
| 273 | 273 | ||
| 274 | return 0; | 274 | return 0; |
| 275 | } | 275 | } |
| @@ -349,7 +349,7 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
| 349 | if (nesfmr->nesmr.pbls_used > nesadapter->free_4kpbl) { | 349 | if (nesfmr->nesmr.pbls_used > nesadapter->free_4kpbl) { |
| 350 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 350 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
| 351 | ret = -ENOMEM; | 351 | ret = -ENOMEM; |
| 352 | goto failed_vpbl_alloc; | 352 | goto failed_vpbl_avail; |
| 353 | } else { | 353 | } else { |
| 354 | nesadapter->free_4kpbl -= nesfmr->nesmr.pbls_used; | 354 | nesadapter->free_4kpbl -= nesfmr->nesmr.pbls_used; |
| 355 | } | 355 | } |
| @@ -357,7 +357,7 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
| 357 | if (nesfmr->nesmr.pbls_used > nesadapter->free_256pbl) { | 357 | if (nesfmr->nesmr.pbls_used > nesadapter->free_256pbl) { |
| 358 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 358 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
| 359 | ret = -ENOMEM; | 359 | ret = -ENOMEM; |
| 360 | goto failed_vpbl_alloc; | 360 | goto failed_vpbl_avail; |
| 361 | } else { | 361 | } else { |
| 362 | nesadapter->free_256pbl -= nesfmr->nesmr.pbls_used; | 362 | nesadapter->free_256pbl -= nesfmr->nesmr.pbls_used; |
| 363 | } | 363 | } |
| @@ -391,14 +391,14 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
| 391 | goto failed_vpbl_alloc; | 391 | goto failed_vpbl_alloc; |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_KERNEL); | 394 | nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1; |
| 395 | nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_ATOMIC); | ||
| 395 | if (!nesfmr->root_vpbl.leaf_vpbl) { | 396 | if (!nesfmr->root_vpbl.leaf_vpbl) { |
| 396 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 397 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
| 397 | ret = -ENOMEM; | 398 | ret = -ENOMEM; |
| 398 | goto failed_leaf_vpbl_alloc; | 399 | goto failed_leaf_vpbl_alloc; |
| 399 | } | 400 | } |
| 400 | 401 | ||
| 401 | nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1; | ||
| 402 | nes_debug(NES_DBG_MR, "two level pbl, root_vpbl.pbl_vbase=%p" | 402 | nes_debug(NES_DBG_MR, "two level pbl, root_vpbl.pbl_vbase=%p" |
| 403 | " leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n", | 403 | " leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n", |
| 404 | nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl); | 404 | nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl); |
| @@ -519,6 +519,16 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
| 519 | nesfmr->root_vpbl.pbl_pbase); | 519 | nesfmr->root_vpbl.pbl_pbase); |
| 520 | 520 | ||
| 521 | failed_vpbl_alloc: | 521 | failed_vpbl_alloc: |
| 522 | if (nesfmr->nesmr.pbls_used != 0) { | ||
| 523 | spin_lock_irqsave(&nesadapter->pbl_lock, flags); | ||
| 524 | if (nesfmr->nesmr.pbl_4k) | ||
| 525 | nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used; | ||
| 526 | else | ||
| 527 | nesadapter->free_256pbl += nesfmr->nesmr.pbls_used; | ||
| 528 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | ||
| 529 | } | ||
| 530 | |||
| 531 | failed_vpbl_avail: | ||
| 522 | kfree(nesfmr); | 532 | kfree(nesfmr); |
| 523 | 533 | ||
| 524 | failed_fmr_alloc: | 534 | failed_fmr_alloc: |
| @@ -534,18 +544,14 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
| 534 | */ | 544 | */ |
| 535 | static int nes_dealloc_fmr(struct ib_fmr *ibfmr) | 545 | static int nes_dealloc_fmr(struct ib_fmr *ibfmr) |
| 536 | { | 546 | { |
| 547 | unsigned long flags; | ||
| 537 | struct nes_mr *nesmr = to_nesmr_from_ibfmr(ibfmr); | 548 | struct nes_mr *nesmr = to_nesmr_from_ibfmr(ibfmr); |
| 538 | struct nes_fmr *nesfmr = to_nesfmr(nesmr); | 549 | struct nes_fmr *nesfmr = to_nesfmr(nesmr); |
| 539 | struct nes_vnic *nesvnic = to_nesvnic(ibfmr->device); | 550 | struct nes_vnic *nesvnic = to_nesvnic(ibfmr->device); |
| 540 | struct nes_device *nesdev = nesvnic->nesdev; | 551 | struct nes_device *nesdev = nesvnic->nesdev; |
| 541 | struct nes_mr temp_nesmr = *nesmr; | 552 | struct nes_adapter *nesadapter = nesdev->nesadapter; |
| 542 | int i = 0; | 553 | int i = 0; |
| 543 | 554 | ||
| 544 | temp_nesmr.ibmw.device = ibfmr->device; | ||
| 545 | temp_nesmr.ibmw.pd = ibfmr->pd; | ||
| 546 | temp_nesmr.ibmw.rkey = ibfmr->rkey; | ||
| 547 | temp_nesmr.ibmw.uobject = NULL; | ||
| 548 | |||
| 549 | /* free the resources */ | 555 | /* free the resources */ |
| 550 | if (nesfmr->leaf_pbl_cnt == 0) { | 556 | if (nesfmr->leaf_pbl_cnt == 0) { |
| 551 | /* single PBL case */ | 557 | /* single PBL case */ |
| @@ -561,8 +567,24 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr) | |||
| 561 | pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase, | 567 | pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase, |
| 562 | nesfmr->root_vpbl.pbl_pbase); | 568 | nesfmr->root_vpbl.pbl_pbase); |
| 563 | } | 569 | } |
| 570 | nesmr->ibmw.device = ibfmr->device; | ||
| 571 | nesmr->ibmw.pd = ibfmr->pd; | ||
| 572 | nesmr->ibmw.rkey = ibfmr->rkey; | ||
| 573 | nesmr->ibmw.uobject = NULL; | ||
| 564 | 574 | ||
| 565 | return nes_dealloc_mw(&temp_nesmr.ibmw); | 575 | if (nesfmr->nesmr.pbls_used != 0) { |
| 576 | spin_lock_irqsave(&nesadapter->pbl_lock, flags); | ||
| 577 | if (nesfmr->nesmr.pbl_4k) { | ||
| 578 | nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used; | ||
| 579 | WARN_ON(nesadapter->free_4kpbl > nesadapter->max_4kpbl); | ||
| 580 | } else { | ||
| 581 | nesadapter->free_256pbl += nesfmr->nesmr.pbls_used; | ||
| 582 | WARN_ON(nesadapter->free_256pbl > nesadapter->max_256pbl); | ||
| 583 | } | ||
| 584 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | ||
| 585 | } | ||
| 586 | |||
| 587 | return nes_dealloc_mw(&nesmr->ibmw); | ||
| 566 | } | 588 | } |
| 567 | 589 | ||
| 568 | 590 | ||
| @@ -1595,7 +1617,7 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, | |||
| 1595 | nes_ucontext->mcrqf = req.mcrqf; | 1617 | nes_ucontext->mcrqf = req.mcrqf; |
| 1596 | if (nes_ucontext->mcrqf) { | 1618 | if (nes_ucontext->mcrqf) { |
| 1597 | if (nes_ucontext->mcrqf & 0x80000000) | 1619 | if (nes_ucontext->mcrqf & 0x80000000) |
| 1598 | nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 12 + (nes_ucontext->mcrqf & 0xf) - 1; | 1620 | nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 28 + 2 * ((nes_ucontext->mcrqf & 0xf) - 1); |
| 1599 | else if (nes_ucontext->mcrqf & 0x40000000) | 1621 | else if (nes_ucontext->mcrqf & 0x40000000) |
| 1600 | nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff; | 1622 | nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff; |
| 1601 | else | 1623 | else |
| @@ -3212,7 +3234,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
| 3212 | if (nesqp->ibqp_state > IB_QPS_RTS) | 3234 | if (nesqp->ibqp_state > IB_QPS_RTS) |
| 3213 | return -EINVAL; | 3235 | return -EINVAL; |
| 3214 | 3236 | ||
| 3215 | spin_lock_irqsave(&nesqp->lock, flags); | 3237 | spin_lock_irqsave(&nesqp->lock, flags); |
| 3216 | 3238 | ||
| 3217 | head = nesqp->hwqp.sq_head; | 3239 | head = nesqp->hwqp.sq_head; |
| 3218 | 3240 | ||
| @@ -3337,7 +3359,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
| 3337 | (counter << 24) | 0x00800000 | nesqp->hwqp.qp_id); | 3359 | (counter << 24) | 0x00800000 | nesqp->hwqp.qp_id); |
| 3338 | } | 3360 | } |
| 3339 | 3361 | ||
| 3340 | spin_unlock_irqrestore(&nesqp->lock, flags); | 3362 | spin_unlock_irqrestore(&nesqp->lock, flags); |
| 3341 | 3363 | ||
| 3342 | if (err) | 3364 | if (err) |
| 3343 | *bad_wr = ib_wr; | 3365 | *bad_wr = ib_wr; |
| @@ -3368,7 +3390,7 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, | |||
| 3368 | if (nesqp->ibqp_state > IB_QPS_RTS) | 3390 | if (nesqp->ibqp_state > IB_QPS_RTS) |
| 3369 | return -EINVAL; | 3391 | return -EINVAL; |
| 3370 | 3392 | ||
| 3371 | spin_lock_irqsave(&nesqp->lock, flags); | 3393 | spin_lock_irqsave(&nesqp->lock, flags); |
| 3372 | 3394 | ||
| 3373 | head = nesqp->hwqp.rq_head; | 3395 | head = nesqp->hwqp.rq_head; |
| 3374 | 3396 | ||
| @@ -3421,7 +3443,7 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, | |||
| 3421 | nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter<<24) | nesqp->hwqp.qp_id); | 3443 | nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter<<24) | nesqp->hwqp.qp_id); |
| 3422 | } | 3444 | } |
| 3423 | 3445 | ||
| 3424 | spin_unlock_irqrestore(&nesqp->lock, flags); | 3446 | spin_unlock_irqrestore(&nesqp->lock, flags); |
| 3425 | 3447 | ||
| 3426 | if (err) | 3448 | if (err) |
| 3427 | *bad_wr = ib_wr; | 3449 | *bad_wr = ib_wr; |
| @@ -3453,7 +3475,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
| 3453 | 3475 | ||
| 3454 | nes_debug(NES_DBG_CQ, "\n"); | 3476 | nes_debug(NES_DBG_CQ, "\n"); |
| 3455 | 3477 | ||
| 3456 | spin_lock_irqsave(&nescq->lock, flags); | 3478 | spin_lock_irqsave(&nescq->lock, flags); |
| 3457 | 3479 | ||
| 3458 | head = nescq->hw_cq.cq_head; | 3480 | head = nescq->hw_cq.cq_head; |
| 3459 | cq_size = nescq->hw_cq.cq_size; | 3481 | cq_size = nescq->hw_cq.cq_size; |
| @@ -3562,7 +3584,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
| 3562 | nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n", | 3584 | nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n", |
| 3563 | cqe_count, nescq->hw_cq.cq_number); | 3585 | cqe_count, nescq->hw_cq.cq_number); |
| 3564 | 3586 | ||
| 3565 | spin_unlock_irqrestore(&nescq->lock, flags); | 3587 | spin_unlock_irqrestore(&nescq->lock, flags); |
| 3566 | 3588 | ||
| 3567 | return cqe_count; | 3589 | return cqe_count; |
| 3568 | } | 3590 | } |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index fddded7900d1..85257f6b9576 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
| @@ -106,12 +106,13 @@ int ipoib_open(struct net_device *dev) | |||
| 106 | 106 | ||
| 107 | ipoib_dbg(priv, "bringing up interface\n"); | 107 | ipoib_dbg(priv, "bringing up interface\n"); |
| 108 | 108 | ||
| 109 | napi_enable(&priv->napi); | ||
| 110 | set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); | 109 | set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); |
| 111 | 110 | ||
| 112 | if (ipoib_pkey_dev_delay_open(dev)) | 111 | if (ipoib_pkey_dev_delay_open(dev)) |
| 113 | return 0; | 112 | return 0; |
| 114 | 113 | ||
| 114 | napi_enable(&priv->napi); | ||
| 115 | |||
| 115 | if (ipoib_ib_dev_open(dev)) { | 116 | if (ipoib_ib_dev_open(dev)) { |
| 116 | napi_disable(&priv->napi); | 117 | napi_disable(&priv->napi); |
| 117 | return -EINVAL; | 118 | return -EINVAL; |
| @@ -546,6 +547,7 @@ static int path_rec_start(struct net_device *dev, | |||
| 546 | if (path->query_id < 0) { | 547 | if (path->query_id < 0) { |
| 547 | ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); | 548 | ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); |
| 548 | path->query = NULL; | 549 | path->query = NULL; |
| 550 | complete(&path->done); | ||
| 549 | return path->query_id; | 551 | return path->query_id; |
| 550 | } | 552 | } |
| 551 | 553 | ||
| @@ -662,7 +664,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
| 662 | skb_push(skb, sizeof *phdr); | 664 | skb_push(skb, sizeof *phdr); |
| 663 | __skb_queue_tail(&path->queue, skb); | 665 | __skb_queue_tail(&path->queue, skb); |
| 664 | 666 | ||
| 665 | if (path_rec_start(dev, path)) { | 667 | if (!path->query && path_rec_start(dev, path)) { |
| 666 | spin_unlock_irqrestore(&priv->lock, flags); | 668 | spin_unlock_irqrestore(&priv->lock, flags); |
| 667 | path_free(dev, path); | 669 | path_free(dev, path); |
| 668 | return; | 670 | return; |
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index bb904a0a98bd..1bfc55d7a26c 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c | |||
| @@ -1641,8 +1641,10 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp) | |||
| 1641 | /* slarp reply, send own ip/netmask; if values are nonsense remote | 1641 | /* slarp reply, send own ip/netmask; if values are nonsense remote |
| 1642 | * should think we are unable to provide it with an address via SLARP */ | 1642 | * should think we are unable to provide it with an address via SLARP */ |
| 1643 | p += put_u32(p, CISCO_SLARP_REPLY); | 1643 | p += put_u32(p, CISCO_SLARP_REPLY); |
| 1644 | p += put_u32(p, addr); // address | 1644 | *(__be32 *)p = addr; // address |
| 1645 | p += put_u32(p, mask); // netmask | 1645 | p += 4; |
| 1646 | *(__be32 *)p = mask; // netmask | ||
| 1647 | p += 4; | ||
| 1646 | p += put_u16(p, 0); // unused | 1648 | p += put_u16(p, 0); // unused |
| 1647 | 1649 | ||
| 1648 | isdn_net_write_super(lp, skb); | 1650 | isdn_net_write_super(lp, skb); |
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 4840733cd903..3d7f4923cd13 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
| @@ -441,13 +441,13 @@ static void process_queued_ios(struct work_struct *work) | |||
| 441 | __choose_pgpath(m); | 441 | __choose_pgpath(m); |
| 442 | 442 | ||
| 443 | pgpath = m->current_pgpath; | 443 | pgpath = m->current_pgpath; |
| 444 | m->pgpath_to_activate = m->current_pgpath; | ||
| 445 | 444 | ||
| 446 | if ((pgpath && !m->queue_io) || | 445 | if ((pgpath && !m->queue_io) || |
| 447 | (!pgpath && !m->queue_if_no_path)) | 446 | (!pgpath && !m->queue_if_no_path)) |
| 448 | must_queue = 0; | 447 | must_queue = 0; |
| 449 | 448 | ||
| 450 | if (m->pg_init_required && !m->pg_init_in_progress) { | 449 | if (m->pg_init_required && !m->pg_init_in_progress && pgpath) { |
| 450 | m->pgpath_to_activate = pgpath; | ||
| 451 | m->pg_init_count++; | 451 | m->pg_init_count++; |
| 452 | m->pg_init_required = 0; | 452 | m->pg_init_required = 0; |
| 453 | m->pg_init_in_progress = 1; | 453 | m->pg_init_in_progress = 1; |
| @@ -708,6 +708,10 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m) | |||
| 708 | m->hw_handler_name = NULL; | 708 | m->hw_handler_name = NULL; |
| 709 | return -EINVAL; | 709 | return -EINVAL; |
| 710 | } | 710 | } |
| 711 | |||
| 712 | if (hw_argc > 1) | ||
| 713 | DMWARN("Ignoring user-specified arguments for " | ||
| 714 | "hardware handler \"%s\"", m->hw_handler_name); | ||
| 711 | consume(as, hw_argc - 1); | 715 | consume(as, hw_argc - 1); |
| 712 | 716 | ||
| 713 | return 0; | 717 | return 0; |
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 9d7b53ed75b2..ec43f9fa4b2a 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
| @@ -1032,6 +1032,7 @@ static void mirror_dtr(struct dm_target *ti) | |||
| 1032 | 1032 | ||
| 1033 | del_timer_sync(&ms->timer); | 1033 | del_timer_sync(&ms->timer); |
| 1034 | flush_workqueue(ms->kmirrord_wq); | 1034 | flush_workqueue(ms->kmirrord_wq); |
| 1035 | flush_scheduled_work(); | ||
| 1035 | dm_kcopyd_client_destroy(ms->kcopyd_client); | 1036 | dm_kcopyd_client_destroy(ms->kcopyd_client); |
| 1036 | destroy_workqueue(ms->kmirrord_wq); | 1037 | destroy_workqueue(ms->kmirrord_wq); |
| 1037 | free_context(ms, ti, ms->nr_mirrors); | 1038 | free_context(ms, ti, ms->nr_mirrors); |
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index a2d068dbe9e2..9e4ef88d421e 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
| @@ -320,8 +320,10 @@ int __init dm_stripe_init(void) | |||
| 320 | int r; | 320 | int r; |
| 321 | 321 | ||
| 322 | r = dm_register_target(&stripe_target); | 322 | r = dm_register_target(&stripe_target); |
| 323 | if (r < 0) | 323 | if (r < 0) { |
| 324 | DMWARN("target registration failed"); | 324 | DMWARN("target registration failed"); |
| 325 | return r; | ||
| 326 | } | ||
| 325 | 327 | ||
| 326 | kstriped = create_singlethread_workqueue("kstriped"); | 328 | kstriped = create_singlethread_workqueue("kstriped"); |
| 327 | if (!kstriped) { | 329 | if (!kstriped) { |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 6963ad148408..c99e4728ff41 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -375,7 +375,7 @@ static void start_io_acct(struct dm_io *io) | |||
| 375 | dm_disk(md)->part0.in_flight = atomic_inc_return(&md->pending); | 375 | dm_disk(md)->part0.in_flight = atomic_inc_return(&md->pending); |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | static int end_io_acct(struct dm_io *io) | 378 | static void end_io_acct(struct dm_io *io) |
| 379 | { | 379 | { |
| 380 | struct mapped_device *md = io->md; | 380 | struct mapped_device *md = io->md; |
| 381 | struct bio *bio = io->bio; | 381 | struct bio *bio = io->bio; |
| @@ -391,7 +391,9 @@ static int end_io_acct(struct dm_io *io) | |||
| 391 | dm_disk(md)->part0.in_flight = pending = | 391 | dm_disk(md)->part0.in_flight = pending = |
| 392 | atomic_dec_return(&md->pending); | 392 | atomic_dec_return(&md->pending); |
| 393 | 393 | ||
| 394 | return !pending; | 394 | /* nudge anyone waiting on suspend queue */ |
| 395 | if (!pending) | ||
| 396 | wake_up(&md->wait); | ||
| 395 | } | 397 | } |
| 396 | 398 | ||
| 397 | /* | 399 | /* |
| @@ -499,9 +501,7 @@ static void dec_pending(struct dm_io *io, int error) | |||
| 499 | spin_unlock_irqrestore(&io->md->pushback_lock, flags); | 501 | spin_unlock_irqrestore(&io->md->pushback_lock, flags); |
| 500 | } | 502 | } |
| 501 | 503 | ||
| 502 | if (end_io_acct(io)) | 504 | end_io_acct(io); |
| 503 | /* nudge anyone waiting on suspend queue */ | ||
| 504 | wake_up(&io->md->wait); | ||
| 505 | 505 | ||
| 506 | if (io->error != DM_ENDIO_REQUEUE) { | 506 | if (io->error != DM_ENDIO_REQUEUE) { |
| 507 | blk_add_trace_bio(io->md->queue, io->bio, | 507 | blk_add_trace_bio(io->md->queue, io->bio, |
| @@ -937,16 +937,24 @@ static void dm_unplug_all(struct request_queue *q) | |||
| 937 | 937 | ||
| 938 | static int dm_any_congested(void *congested_data, int bdi_bits) | 938 | static int dm_any_congested(void *congested_data, int bdi_bits) |
| 939 | { | 939 | { |
| 940 | int r; | 940 | int r = bdi_bits; |
| 941 | struct mapped_device *md = (struct mapped_device *) congested_data; | 941 | struct mapped_device *md = congested_data; |
| 942 | struct dm_table *map = dm_get_table(md); | 942 | struct dm_table *map; |
| 943 | 943 | ||
| 944 | if (!map || test_bit(DMF_BLOCK_IO, &md->flags)) | 944 | atomic_inc(&md->pending); |
| 945 | r = bdi_bits; | 945 | |
| 946 | else | 946 | if (!test_bit(DMF_BLOCK_IO, &md->flags)) { |
| 947 | r = dm_table_any_congested(map, bdi_bits); | 947 | map = dm_get_table(md); |
| 948 | if (map) { | ||
| 949 | r = dm_table_any_congested(map, bdi_bits); | ||
| 950 | dm_table_put(map); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | |||
| 954 | if (!atomic_dec_return(&md->pending)) | ||
| 955 | /* nudge anyone waiting on suspend queue */ | ||
| 956 | wake_up(&md->wait); | ||
| 948 | 957 | ||
| 949 | dm_table_put(map); | ||
| 950 | return r; | 958 | return r; |
| 951 | } | 959 | } |
| 952 | 960 | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 5689d1f1d444..8557bf12cfb4 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
| @@ -223,6 +223,8 @@ static void dvb_frontend_init(struct dvb_frontend *fe) | |||
| 223 | if (fe->ops.init) | 223 | if (fe->ops.init) |
| 224 | fe->ops.init(fe); | 224 | fe->ops.init(fe); |
| 225 | if (fe->ops.tuner_ops.init) { | 225 | if (fe->ops.tuner_ops.init) { |
| 226 | if (fe->ops.i2c_gate_ctrl) | ||
| 227 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
| 226 | fe->ops.tuner_ops.init(fe); | 228 | fe->ops.tuner_ops.init(fe); |
| 227 | if (fe->ops.i2c_gate_ctrl) | 229 | if (fe->ops.i2c_gate_ctrl) |
| 228 | fe->ops.i2c_gate_ctrl(fe, 0); | 230 | fe->ops.i2c_gate_ctrl(fe, 0); |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 3c13bcfa6385..62b68c291d99 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
| @@ -261,7 +261,7 @@ config DVB_USB_DW2102 | |||
| 261 | Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers | 261 | Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers |
| 262 | and the TeVii S650. | 262 | and the TeVii S650. |
| 263 | 263 | ||
| 264 | config DVB_USB_CINERGY_T2 | 264 | config DVB_USB_CINERGY_T2 |
| 265 | tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" | 265 | tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" |
| 266 | depends on DVB_USB | 266 | depends on DVB_USB |
| 267 | help | 267 | help |
| @@ -283,6 +283,7 @@ config DVB_USB_ANYSEE | |||
| 283 | config DVB_USB_DTV5100 | 283 | config DVB_USB_DTV5100 |
| 284 | tristate "AME DTV-5100 USB2.0 DVB-T support" | 284 | tristate "AME DTV-5100 USB2.0 DVB-T support" |
| 285 | depends on DVB_USB | 285 | depends on DVB_USB |
| 286 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
| 286 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | 287 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE |
| 287 | help | 288 | help |
| 288 | Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. | 289 | Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. |
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index cb0829c038ce..847d8fdd9ec4 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c | |||
| @@ -31,13 +31,13 @@ | |||
| 31 | #include "mc44s80x.h" | 31 | #include "mc44s80x.h" |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | int dvb_usb_af9015_debug; | 34 | static int dvb_usb_af9015_debug; |
| 35 | module_param_named(debug, dvb_usb_af9015_debug, int, 0644); | 35 | module_param_named(debug, dvb_usb_af9015_debug, int, 0644); |
| 36 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | 36 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); |
| 37 | int dvb_usb_af9015_remote; | 37 | static int dvb_usb_af9015_remote; |
| 38 | module_param_named(remote, dvb_usb_af9015_remote, int, 0644); | 38 | module_param_named(remote, dvb_usb_af9015_remote, int, 0644); |
| 39 | MODULE_PARM_DESC(remote, "select remote"); | 39 | MODULE_PARM_DESC(remote, "select remote"); |
| 40 | int dvb_usb_af9015_dual_mode; | 40 | static int dvb_usb_af9015_dual_mode; |
| 41 | module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644); | 41 | module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644); |
| 42 | MODULE_PARM_DESC(dual_mode, "enable dual mode"); | 42 | MODULE_PARM_DESC(dual_mode, "enable dual mode"); |
| 43 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 43 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| @@ -46,7 +46,7 @@ static DEFINE_MUTEX(af9015_usb_mutex); | |||
| 46 | 46 | ||
| 47 | static struct af9015_config af9015_config; | 47 | static struct af9015_config af9015_config; |
| 48 | static struct dvb_usb_device_properties af9015_properties[2]; | 48 | static struct dvb_usb_device_properties af9015_properties[2]; |
| 49 | int af9015_properties_count = ARRAY_SIZE(af9015_properties); | 49 | static int af9015_properties_count = ARRAY_SIZE(af9015_properties); |
| 50 | 50 | ||
| 51 | static struct af9013_config af9015_af9013_config[] = { | 51 | static struct af9013_config af9015_af9013_config[] = { |
| 52 | { | 52 | { |
| @@ -549,7 +549,7 @@ static int af9015_eeprom_dump(struct dvb_usb_device *d) | |||
| 549 | return 0; | 549 | return 0; |
| 550 | } | 550 | } |
| 551 | 551 | ||
| 552 | int af9015_download_ir_table(struct dvb_usb_device *d) | 552 | static int af9015_download_ir_table(struct dvb_usb_device *d) |
| 553 | { | 553 | { |
| 554 | int i, packets = 0, ret; | 554 | int i, packets = 0, ret; |
| 555 | u16 addr = 0x9a56; /* ir-table start address */ | 555 | u16 addr = 0x9a56; /* ir-table start address */ |
| @@ -999,7 +999,7 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 999 | } | 999 | } |
| 1000 | 1000 | ||
| 1001 | /* init 2nd I2C adapter */ | 1001 | /* init 2nd I2C adapter */ |
| 1002 | int af9015_i2c_init(struct dvb_usb_device *d) | 1002 | static int af9015_i2c_init(struct dvb_usb_device *d) |
| 1003 | { | 1003 | { |
| 1004 | int ret; | 1004 | int ret; |
| 1005 | struct af9015_state *state = d->priv; | 1005 | struct af9015_state *state = d->priv; |
| @@ -1419,7 +1419,7 @@ static int af9015_usb_probe(struct usb_interface *intf, | |||
| 1419 | return ret; | 1419 | return ret; |
| 1420 | } | 1420 | } |
| 1421 | 1421 | ||
| 1422 | void af9015_i2c_exit(struct dvb_usb_device *d) | 1422 | static void af9015_i2c_exit(struct dvb_usb_device *d) |
| 1423 | { | 1423 | { |
| 1424 | struct af9015_state *state = d->priv; | 1424 | struct af9015_state *state = d->priv; |
| 1425 | deb_info("%s: \n", __func__); | 1425 | deb_info("%s: \n", __func__); |
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index 882e8a4b3681..6c3c97293316 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #define DVB_USB_LOG_PREFIX "af9015" | 27 | #define DVB_USB_LOG_PREFIX "af9015" |
| 28 | #include "dvb-usb.h" | 28 | #include "dvb-usb.h" |
| 29 | 29 | ||
| 30 | extern int dvb_usb_af9015_debug; | ||
| 31 | #define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) | 30 | #define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) |
| 32 | #define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) | 31 | #define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) |
| 33 | #define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args) | 32 | #define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args) |
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index c786359fba03..cd2edbcaa097 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c | |||
| @@ -46,7 +46,7 @@ module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644); | |||
| 46 | MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)"); | 46 | MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)"); |
| 47 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 47 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 48 | 48 | ||
| 49 | static struct mutex anysee_usb_mutex; | 49 | static DEFINE_MUTEX(anysee_usb_mutex); |
| 50 | 50 | ||
| 51 | static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, | 51 | static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, |
| 52 | u8 *rbuf, u8 rlen) | 52 | u8 *rbuf, u8 rlen) |
| @@ -456,8 +456,6 @@ static int anysee_probe(struct usb_interface *intf, | |||
| 456 | struct usb_host_interface *alt; | 456 | struct usb_host_interface *alt; |
| 457 | int ret; | 457 | int ret; |
| 458 | 458 | ||
| 459 | mutex_init(&anysee_usb_mutex); | ||
| 460 | |||
| 461 | /* There is one interface with two alternate settings. | 459 | /* There is one interface with two alternate settings. |
| 462 | Alternate setting 0 is for bulk transfer. | 460 | Alternate setting 0 is for bulk transfer. |
| 463 | Alternate setting 1 is for isochronous transfer. | 461 | Alternate setting 1 is for isochronous transfer. |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c index 5cef12a07f72..6fe71c6745eb 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c | |||
| @@ -13,14 +13,14 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, | |||
| 13 | { | 13 | { |
| 14 | int actlen,ret = -ENOMEM; | 14 | int actlen,ret = -ENOMEM; |
| 15 | 15 | ||
| 16 | if (!d || wbuf == NULL || wlen == 0) | ||
| 17 | return -EINVAL; | ||
| 18 | |||
| 16 | if (d->props.generic_bulk_ctrl_endpoint == 0) { | 19 | if (d->props.generic_bulk_ctrl_endpoint == 0) { |
| 17 | err("endpoint for generic control not specified."); | 20 | err("endpoint for generic control not specified."); |
| 18 | return -EINVAL; | 21 | return -EINVAL; |
| 19 | } | 22 | } |
| 20 | 23 | ||
| 21 | if (wbuf == NULL || wlen == 0) | ||
| 22 | return -EINVAL; | ||
| 23 | |||
| 24 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | 24 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) |
| 25 | return ret; | 25 | return ret; |
| 26 | 26 | ||
diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c index 21c1060cf10e..692b68a9e73b 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb/frontends/af9013.c | |||
| @@ -1187,7 +1187,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) | |||
| 1187 | if (tmp) | 1187 | if (tmp) |
| 1188 | *status |= FE_HAS_SYNC | FE_HAS_LOCK; | 1188 | *status |= FE_HAS_SYNC | FE_HAS_LOCK; |
| 1189 | 1189 | ||
| 1190 | if (!*status & FE_HAS_SIGNAL) { | 1190 | if (!(*status & FE_HAS_SIGNAL)) { |
| 1191 | /* AGC lock */ | 1191 | /* AGC lock */ |
| 1192 | ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp); | 1192 | ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp); |
| 1193 | if (ret) | 1193 | if (ret) |
| @@ -1196,7 +1196,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) | |||
| 1196 | *status |= FE_HAS_SIGNAL; | 1196 | *status |= FE_HAS_SIGNAL; |
| 1197 | } | 1197 | } |
| 1198 | 1198 | ||
| 1199 | if (!*status & FE_HAS_CARRIER) { | 1199 | if (!(*status & FE_HAS_CARRIER)) { |
| 1200 | /* CFO lock */ | 1200 | /* CFO lock */ |
| 1201 | ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp); | 1201 | ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp); |
| 1202 | if (ret) | 1202 | if (ret) |
| @@ -1205,7 +1205,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) | |||
| 1205 | *status |= FE_HAS_CARRIER; | 1205 | *status |= FE_HAS_CARRIER; |
| 1206 | } | 1206 | } |
| 1207 | 1207 | ||
| 1208 | if (!*status & FE_HAS_CARRIER) { | 1208 | if (!(*status & FE_HAS_CARRIER)) { |
| 1209 | /* SFOE lock */ | 1209 | /* SFOE lock */ |
| 1210 | ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp); | 1210 | ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp); |
| 1211 | if (ret) | 1211 | if (ret) |
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 04cd7c04bdde..5189c4eb439f 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
| @@ -355,6 +355,20 @@ config USB_SI470X | |||
| 355 | tristate "Silicon Labs Si470x FM Radio Receiver support" | 355 | tristate "Silicon Labs Si470x FM Radio Receiver support" |
| 356 | depends on USB && VIDEO_V4L2 | 356 | depends on USB && VIDEO_V4L2 |
| 357 | ---help--- | 357 | ---help--- |
| 358 | This is a driver for USB devices with the Silicon Labs SI470x | ||
| 359 | chip. Currently these devices are known to work: | ||
| 360 | - 10c4:818a: Silicon Labs USB FM Radio Reference Design | ||
| 361 | - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) | ||
| 362 | - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) | ||
| 363 | |||
| 364 | Sound is provided by the ALSA USB Audio/MIDI driver. Therefore | ||
| 365 | if you don't want to use the device solely for RDS receiving, | ||
| 366 | it is recommended to also select SND_USB_AUDIO. | ||
| 367 | |||
| 368 | Please have a look at the documentation, especially on how | ||
| 369 | to redirect the audio stream from the radio to your sound device: | ||
| 370 | Documentation/video4linux/si470x.txt | ||
| 371 | |||
| 358 | Say Y here if you want to connect this type of radio to your | 372 | Say Y here if you want to connect this type of radio to your |
| 359 | computer's USB port. | 373 | computer's USB port. |
| 360 | 374 | ||
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 5920cd306975..3e1830293de5 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | * Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers: | 4 | * Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers: |
| 5 | * - Silicon Labs USB FM Radio Reference Design | 5 | * - Silicon Labs USB FM Radio Reference Design |
| 6 | * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) | 6 | * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) |
| 7 | * - KWorld USB FM Radio SnapMusic Mobile 700 (FM700) | ||
| 7 | * | 8 | * |
| 8 | * Copyright (c) 2008 Tobias Lorenz <tobias.lorenz@gmx.net> | 9 | * Copyright (c) 2008 Tobias Lorenz <tobias.lorenz@gmx.net> |
| 9 | * | 10 | * |
| @@ -24,19 +25,6 @@ | |||
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | /* | 27 | /* |
| 27 | * User Notes: | ||
| 28 | * - USB Audio is provided by the alsa snd_usb_audio module. | ||
| 29 | * For listing you have to redirect the sound, for example using: | ||
| 30 | * arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B - | ||
| 31 | * - regarding module parameters in /sys/module/radio_si470x/parameters: | ||
| 32 | * the contents of read-only files (0444) are not updated, even if | ||
| 33 | * space, band and de are changed using private video controls | ||
| 34 | * - increase tune_timeout, if you often get -EIO errors | ||
| 35 | * - hw_freq_seek returns -EAGAIN, when timed out or band limit is reached | ||
| 36 | */ | ||
| 37 | |||
| 38 | |||
| 39 | /* | ||
| 40 | * History: | 28 | * History: |
| 41 | * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net> | 29 | * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net> |
| 42 | * Version 1.0.0 | 30 | * Version 1.0.0 |
| @@ -105,6 +93,9 @@ | |||
| 105 | * - afc indication | 93 | * - afc indication |
| 106 | * - more safety checks, let si470x_get_freq return errno | 94 | * - more safety checks, let si470x_get_freq return errno |
| 107 | * - vidioc behavior corrected according to v4l2 spec | 95 | * - vidioc behavior corrected according to v4l2 spec |
| 96 | * 2008-10-20 Alexey Klimov <klimov.linux@gmail.com> | ||
| 97 | * - add support for KWorld USB FM Radio FM700 | ||
| 98 | * - blacklisted KWorld radio in hid-core.c and hid-ids.h | ||
| 108 | * | 99 | * |
| 109 | * ToDo: | 100 | * ToDo: |
| 110 | * - add firmware download/update support | 101 | * - add firmware download/update support |
| @@ -145,6 +136,8 @@ static struct usb_device_id si470x_usb_driver_id_table[] = { | |||
| 145 | { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, | 136 | { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, |
| 146 | /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ | 137 | /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ |
| 147 | { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, | 138 | { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, |
| 139 | /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ | ||
| 140 | { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, | ||
| 148 | /* Terminating entry */ | 141 | /* Terminating entry */ |
| 149 | { } | 142 | { } |
| 150 | }; | 143 | }; |
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index a8c068e1de1c..1740b9ebdcef 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
| @@ -1476,12 +1476,9 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) | |||
| 1476 | { | 1476 | { |
| 1477 | struct cafe_camera *cam; | 1477 | struct cafe_camera *cam; |
| 1478 | 1478 | ||
| 1479 | lock_kernel(); | ||
| 1480 | cam = cafe_find_dev(iminor(inode)); | 1479 | cam = cafe_find_dev(iminor(inode)); |
| 1481 | if (cam == NULL) { | 1480 | if (cam == NULL) |
| 1482 | unlock_kernel(); | ||
| 1483 | return -ENODEV; | 1481 | return -ENODEV; |
| 1484 | } | ||
| 1485 | filp->private_data = cam; | 1482 | filp->private_data = cam; |
| 1486 | 1483 | ||
| 1487 | mutex_lock(&cam->s_mutex); | 1484 | mutex_lock(&cam->s_mutex); |
| @@ -1493,7 +1490,6 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) | |||
| 1493 | } | 1490 | } |
| 1494 | (cam->users)++; | 1491 | (cam->users)++; |
| 1495 | mutex_unlock(&cam->s_mutex); | 1492 | mutex_unlock(&cam->s_mutex); |
| 1496 | unlock_kernel(); | ||
| 1497 | return 0; | 1493 | return 0; |
| 1498 | } | 1494 | } |
| 1499 | 1495 | ||
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c index bd5d9de5a008..e6ca4012b5f0 100644 --- a/drivers/media/video/compat_ioctl32.c +++ b/drivers/media/video/compat_ioctl32.c | |||
| @@ -867,6 +867,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 867 | case VIDIOC_STREAMON32: | 867 | case VIDIOC_STREAMON32: |
| 868 | case VIDIOC_STREAMOFF32: | 868 | case VIDIOC_STREAMOFF32: |
| 869 | case VIDIOC_G_PARM: | 869 | case VIDIOC_G_PARM: |
| 870 | case VIDIOC_S_PARM: | ||
| 870 | case VIDIOC_G_STD: | 871 | case VIDIOC_G_STD: |
| 871 | case VIDIOC_S_STD: | 872 | case VIDIOC_S_STD: |
| 872 | case VIDIOC_G_TUNER: | 873 | case VIDIOC_G_TUNER: |
| @@ -885,6 +886,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 885 | case VIDIOC_S_INPUT32: | 886 | case VIDIOC_S_INPUT32: |
| 886 | case VIDIOC_TRY_FMT32: | 887 | case VIDIOC_TRY_FMT32: |
| 887 | case VIDIOC_S_HW_FREQ_SEEK: | 888 | case VIDIOC_S_HW_FREQ_SEEK: |
| 889 | case VIDIOC_ENUM_FRAMESIZES: | ||
| 890 | case VIDIOC_ENUM_FRAMEINTERVALS: | ||
| 888 | ret = do_video_ioctl(file, cmd, arg); | 891 | ret = do_video_ioctl(file, cmd, arg); |
| 889 | break; | 892 | break; |
| 890 | 893 | ||
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 7a1a7830a6b3..7874d9790a51 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
| @@ -448,7 +448,14 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) | |||
| 448 | mutex_init(&cx->gpio_lock); | 448 | mutex_init(&cx->gpio_lock); |
| 449 | 449 | ||
| 450 | spin_lock_init(&cx->lock); | 450 | spin_lock_init(&cx->lock); |
| 451 | spin_lock_init(&cx->dma_reg_lock); | 451 | |
| 452 | cx->work_queue = create_singlethread_workqueue(cx->name); | ||
| 453 | if (cx->work_queue == NULL) { | ||
| 454 | CX18_ERR("Could not create work queue\n"); | ||
| 455 | return -1; | ||
| 456 | } | ||
| 457 | |||
| 458 | INIT_WORK(&cx->work, cx18_work_handler); | ||
| 452 | 459 | ||
| 453 | /* start counting open_id at 1 */ | 460 | /* start counting open_id at 1 */ |
| 454 | cx->open_id = 1; | 461 | cx->open_id = 1; |
| @@ -581,10 +588,10 @@ static void cx18_load_and_init_modules(struct cx18 *cx) | |||
| 581 | 588 | ||
| 582 | #ifdef MODULE | 589 | #ifdef MODULE |
| 583 | /* load modules */ | 590 | /* load modules */ |
| 584 | #ifndef CONFIG_MEDIA_TUNER | 591 | #ifdef CONFIG_MEDIA_TUNER_MODULE |
| 585 | hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); | 592 | hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); |
| 586 | #endif | 593 | #endif |
| 587 | #ifndef CONFIG_VIDEO_CS5345 | 594 | #ifdef CONFIG_VIDEO_CS5345_MODULE |
| 588 | hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); | 595 | hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); |
| 589 | #endif | 596 | #endif |
| 590 | #endif | 597 | #endif |
| @@ -832,6 +839,7 @@ free_map: | |||
| 832 | free_mem: | 839 | free_mem: |
| 833 | release_mem_region(cx->base_addr, CX18_MEM_SIZE); | 840 | release_mem_region(cx->base_addr, CX18_MEM_SIZE); |
| 834 | free_workqueue: | 841 | free_workqueue: |
| 842 | destroy_workqueue(cx->work_queue); | ||
| 835 | err: | 843 | err: |
| 836 | if (retval == 0) | 844 | if (retval == 0) |
| 837 | retval = -ENODEV; | 845 | retval = -ENODEV; |
| @@ -932,6 +940,9 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
| 932 | 940 | ||
| 933 | cx18_halt_firmware(cx); | 941 | cx18_halt_firmware(cx); |
| 934 | 942 | ||
| 943 | flush_workqueue(cx->work_queue); | ||
| 944 | destroy_workqueue(cx->work_queue); | ||
| 945 | |||
| 935 | cx18_streams_cleanup(cx, 1); | 946 | cx18_streams_cleanup(cx, 1); |
| 936 | 947 | ||
| 937 | exit_cx18_i2c(cx); | 948 | exit_cx18_i2c(cx); |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index a4b1708fafe7..bbdd5f25041d 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
| @@ -199,12 +199,15 @@ struct cx18_options { | |||
| 199 | #define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */ | 199 | #define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */ |
| 200 | 200 | ||
| 201 | /* per-cx18, i_flags */ | 201 | /* per-cx18, i_flags */ |
| 202 | #define CX18_F_I_LOADED_FW 0 /* Loaded the firmware the first time */ | 202 | #define CX18_F_I_LOADED_FW 0 /* Loaded firmware 1st time */ |
| 203 | #define CX18_F_I_EOS 4 /* End of encoder stream reached */ | 203 | #define CX18_F_I_EOS 4 /* End of encoder stream */ |
| 204 | #define CX18_F_I_RADIO_USER 5 /* The radio tuner is selected */ | 204 | #define CX18_F_I_RADIO_USER 5 /* radio tuner is selected */ |
| 205 | #define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */ | 205 | #define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */ |
| 206 | #define CX18_F_I_INITED 21 /* set after first open */ | 206 | #define CX18_F_I_HAVE_WORK 15 /* there is work to be done */ |
| 207 | #define CX18_F_I_FAILED 22 /* set if first open failed */ | 207 | #define CX18_F_I_WORK_HANDLER_DVB 18 /* work to be done for DVB */ |
| 208 | #define CX18_F_I_INITED 21 /* set after first open */ | ||
| 209 | #define CX18_F_I_FAILED 22 /* set if first open failed */ | ||
| 210 | #define CX18_F_I_WORK_INITED 23 /* worker thread initialized */ | ||
| 208 | 211 | ||
| 209 | /* These are the VBI types as they appear in the embedded VBI private packets. */ | 212 | /* These are the VBI types as they appear in the embedded VBI private packets. */ |
| 210 | #define CX18_SLICED_TYPE_TELETEXT_B (1) | 213 | #define CX18_SLICED_TYPE_TELETEXT_B (1) |
| @@ -402,8 +405,6 @@ struct cx18 { | |||
| 402 | spinlock_t lock; /* lock access to this struct */ | 405 | spinlock_t lock; /* lock access to this struct */ |
| 403 | int search_pack_header; | 406 | int search_pack_header; |
| 404 | 407 | ||
| 405 | spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ | ||
| 406 | |||
| 407 | int open_id; /* incremented each time an open occurs, used as | 408 | int open_id; /* incremented each time an open occurs, used as |
| 408 | unique ID. Starts at 1, so 0 can be used as | 409 | unique ID. Starts at 1, so 0 can be used as |
| 409 | uninitialized value in the stream->id. */ | 410 | uninitialized value in the stream->id. */ |
| @@ -433,6 +434,9 @@ struct cx18 { | |||
| 433 | /* when the current DMA is finished this queue is woken up */ | 434 | /* when the current DMA is finished this queue is woken up */ |
| 434 | wait_queue_head_t dma_waitq; | 435 | wait_queue_head_t dma_waitq; |
| 435 | 436 | ||
| 437 | struct workqueue_struct *work_queue; | ||
| 438 | struct work_struct work; | ||
| 439 | |||
| 436 | /* i2c */ | 440 | /* i2c */ |
| 437 | struct i2c_adapter i2c_adap[2]; | 441 | struct i2c_adapter i2c_adap[2]; |
| 438 | struct i2c_algo_bit_data i2c_algo[2]; | 442 | struct i2c_algo_bit_data i2c_algo[2]; |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index afc694e7bdb2..4542e2e5e3d7 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | #include "cx18-dvb.h" | 23 | #include "cx18-dvb.h" |
| 24 | #include "cx18-io.h" | 24 | #include "cx18-io.h" |
| 25 | #include "cx18-streams.h" | 25 | #include "cx18-streams.h" |
| 26 | #include "cx18-queue.h" | ||
| 27 | #include "cx18-scb.h" | ||
| 26 | #include "cx18-cards.h" | 28 | #include "cx18-cards.h" |
| 27 | #include "s5h1409.h" | 29 | #include "s5h1409.h" |
| 28 | #include "mxl5005s.h" | 30 | #include "mxl5005s.h" |
| @@ -300,3 +302,24 @@ static int dvb_register(struct cx18_stream *stream) | |||
| 300 | 302 | ||
| 301 | return ret; | 303 | return ret; |
| 302 | } | 304 | } |
| 305 | |||
| 306 | void cx18_dvb_work_handler(struct cx18 *cx) | ||
| 307 | { | ||
| 308 | struct cx18_buffer *buf; | ||
| 309 | struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_TS]; | ||
| 310 | |||
| 311 | while ((buf = cx18_dequeue(s, &s->q_full)) != NULL) { | ||
| 312 | if (s->dvb.enabled) | ||
| 313 | dvb_dmx_swfilter(&s->dvb.demux, buf->buf, | ||
| 314 | buf->bytesused); | ||
| 315 | |||
| 316 | cx18_enqueue(s, buf, &s->q_free); | ||
| 317 | cx18_buf_sync_for_device(s, buf); | ||
| 318 | if (s->handle == CX18_INVALID_TASK_HANDLE) /* FIXME: improve */ | ||
| 319 | continue; | ||
| 320 | |||
| 321 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | ||
| 322 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | ||
| 323 | 1, buf->id, s->buf_size); | ||
| 324 | } | ||
| 325 | } | ||
diff --git a/drivers/media/video/cx18/cx18-dvb.h b/drivers/media/video/cx18/cx18-dvb.h index bf8d8f6f5455..bbdcefc87f28 100644 --- a/drivers/media/video/cx18/cx18-dvb.h +++ b/drivers/media/video/cx18/cx18-dvb.h | |||
| @@ -23,3 +23,4 @@ | |||
| 23 | 23 | ||
| 24 | int cx18_dvb_register(struct cx18_stream *stream); | 24 | int cx18_dvb_register(struct cx18_stream *stream); |
| 25 | void cx18_dvb_unregister(struct cx18_stream *stream); | 25 | void cx18_dvb_unregister(struct cx18_stream *stream); |
| 26 | void cx18_dvb_work_handler(struct cx18 *cx); | ||
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index 700ab9439c16..220fae8d4ad7 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c | |||
| @@ -88,6 +88,19 @@ void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) | |||
| 88 | cx18_log_write_retries(cx, i, addr); | 88 | cx18_log_write_retries(cx, i, addr); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, | ||
| 92 | u32 eval, u32 mask) | ||
| 93 | { | ||
| 94 | int i; | ||
| 95 | eval &= mask; | ||
| 96 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 97 | cx18_writel_noretry(cx, val, addr); | ||
| 98 | if (eval == (cx18_readl_noretry(cx, addr) & mask)) | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | cx18_log_write_retries(cx, i, addr); | ||
| 102 | } | ||
| 103 | |||
| 91 | void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) | 104 | void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) |
| 92 | { | 105 | { |
| 93 | int i; | 106 | int i; |
| @@ -218,7 +231,7 @@ void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) | |||
| 218 | void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) | 231 | void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) |
| 219 | { | 232 | { |
| 220 | u32 r; | 233 | u32 r; |
| 221 | cx18_write_reg(cx, val, SW1_INT_STATUS); | 234 | cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val); |
| 222 | r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); | 235 | r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); |
| 223 | cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); | 236 | cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); |
| 224 | } | 237 | } |
| @@ -233,7 +246,7 @@ void cx18_sw1_irq_disable(struct cx18 *cx, u32 val) | |||
| 233 | void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) | 246 | void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) |
| 234 | { | 247 | { |
| 235 | u32 r; | 248 | u32 r; |
| 236 | cx18_write_reg(cx, val, SW2_INT_STATUS); | 249 | cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val); |
| 237 | r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); | 250 | r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); |
| 238 | cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); | 251 | cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); |
| 239 | } | 252 | } |
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h index 287a5e8bf67b..425244453ea7 100644 --- a/drivers/media/video/cx18/cx18-io.h +++ b/drivers/media/video/cx18/cx18-io.h | |||
| @@ -133,6 +133,8 @@ static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) | |||
| 133 | cx18_writel_noretry(cx, val, addr); | 133 | cx18_writel_noretry(cx, val, addr); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, | ||
| 137 | u32 eval, u32 mask); | ||
| 136 | 138 | ||
| 137 | static inline | 139 | static inline |
| 138 | void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) | 140 | void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) |
| @@ -271,6 +273,21 @@ static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) | |||
| 271 | cx18_write_reg_noretry(cx, val, reg); | 273 | cx18_write_reg_noretry(cx, val, reg); |
| 272 | } | 274 | } |
| 273 | 275 | ||
| 276 | static inline void _cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg, | ||
| 277 | u32 eval, u32 mask) | ||
| 278 | { | ||
| 279 | _cx18_writel_expect(cx, val, cx->reg_mem + reg, eval, mask); | ||
| 280 | } | ||
| 281 | |||
| 282 | static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg, | ||
| 283 | u32 eval, u32 mask) | ||
| 284 | { | ||
| 285 | if (cx18_retry_mmio) | ||
| 286 | _cx18_write_reg_expect(cx, val, reg, eval, mask); | ||
| 287 | else | ||
| 288 | cx18_write_reg_noretry(cx, val, reg); | ||
| 289 | } | ||
| 290 | |||
| 274 | 291 | ||
| 275 | static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) | 292 | static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) |
| 276 | { | 293 | { |
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 360330f5463f..5fbfbd0f1493 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c | |||
| @@ -29,8 +29,20 @@ | |||
| 29 | #include "cx18-mailbox.h" | 29 | #include "cx18-mailbox.h" |
| 30 | #include "cx18-vbi.h" | 30 | #include "cx18-vbi.h" |
| 31 | #include "cx18-scb.h" | 31 | #include "cx18-scb.h" |
| 32 | #include "cx18-dvb.h" | ||
| 32 | 33 | ||
| 33 | #define DMA_MAGIC_COOKIE 0x000001fe | 34 | void cx18_work_handler(struct work_struct *work) |
| 35 | { | ||
| 36 | struct cx18 *cx = container_of(work, struct cx18, work); | ||
| 37 | if (test_and_clear_bit(CX18_F_I_WORK_INITED, &cx->i_flags)) { | ||
| 38 | struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; | ||
| 39 | /* This thread must use the FIFO scheduler as it | ||
| 40 | * is realtime sensitive. */ | ||
| 41 | sched_setscheduler(current, SCHED_FIFO, ¶m); | ||
| 42 | } | ||
| 43 | if (test_and_clear_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags)) | ||
| 44 | cx18_dvb_work_handler(cx); | ||
| 45 | } | ||
| 34 | 46 | ||
| 35 | static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | 47 | static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) |
| 36 | { | 48 | { |
| @@ -67,17 +79,11 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | |||
| 67 | if (buf) { | 79 | if (buf) { |
| 68 | cx18_buf_sync_for_cpu(s, buf); | 80 | cx18_buf_sync_for_cpu(s, buf); |
| 69 | if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) { | 81 | if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) { |
| 70 | /* process the buffer here */ | 82 | CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n", |
| 71 | CX18_DEBUG_HI_DMA("TS recv and sent bytesused=%d\n", | ||
| 72 | buf->bytesused); | ||
| 73 | |||
| 74 | dvb_dmx_swfilter(&s->dvb.demux, buf->buf, | ||
| 75 | buf->bytesused); | 83 | buf->bytesused); |
| 76 | 84 | ||
| 77 | cx18_buf_sync_for_device(s, buf); | 85 | set_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags); |
| 78 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | 86 | set_bit(CX18_F_I_HAVE_WORK, &cx->i_flags); |
| 79 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | ||
| 80 | 1, buf->id, s->buf_size); | ||
| 81 | } else | 87 | } else |
| 82 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); | 88 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); |
| 83 | } else { | 89 | } else { |
| @@ -109,7 +115,7 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb) | |||
| 109 | CX18_INFO("FW version: %s\n", p - 1); | 115 | CX18_INFO("FW version: %s\n", p - 1); |
| 110 | } | 116 | } |
| 111 | 117 | ||
| 112 | static void hpu_cmd(struct cx18 *cx, u32 sw1) | 118 | static void epu_cmd(struct cx18 *cx, u32 sw1) |
| 113 | { | 119 | { |
| 114 | struct cx18_mailbox mb; | 120 | struct cx18_mailbox mb; |
| 115 | 121 | ||
| @@ -125,12 +131,31 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1) | |||
| 125 | epu_debug(cx, &mb); | 131 | epu_debug(cx, &mb); |
| 126 | break; | 132 | break; |
| 127 | default: | 133 | default: |
| 128 | CX18_WARN("Unexpected mailbox command %08x\n", mb.cmd); | 134 | CX18_WARN("Unknown CPU_TO_EPU mailbox command %#08x\n", |
| 135 | mb.cmd); | ||
| 129 | break; | 136 | break; |
| 130 | } | 137 | } |
| 131 | } | 138 | } |
| 132 | if (sw1 & (IRQ_APU_TO_EPU | IRQ_HPU_TO_EPU)) | 139 | |
| 133 | CX18_WARN("Unexpected interrupt %08x\n", sw1); | 140 | if (sw1 & IRQ_APU_TO_EPU) { |
| 141 | cx18_memcpy_fromio(cx, &mb, &cx->scb->apu2epu_mb, sizeof(mb)); | ||
| 142 | CX18_WARN("Unknown APU_TO_EPU mailbox command %#08x\n", mb.cmd); | ||
| 143 | } | ||
| 144 | |||
| 145 | if (sw1 & IRQ_HPU_TO_EPU) { | ||
| 146 | cx18_memcpy_fromio(cx, &mb, &cx->scb->hpu2epu_mb, sizeof(mb)); | ||
| 147 | CX18_WARN("Unknown HPU_TO_EPU mailbox command %#08x\n", mb.cmd); | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | static void xpu_ack(struct cx18 *cx, u32 sw2) | ||
| 152 | { | ||
| 153 | if (sw2 & IRQ_CPU_TO_EPU_ACK) | ||
| 154 | wake_up(&cx->mb_cpu_waitq); | ||
| 155 | if (sw2 & IRQ_APU_TO_EPU_ACK) | ||
| 156 | wake_up(&cx->mb_apu_waitq); | ||
| 157 | if (sw2 & IRQ_HPU_TO_EPU_ACK) | ||
| 158 | wake_up(&cx->mb_hpu_waitq); | ||
| 134 | } | 159 | } |
| 135 | 160 | ||
| 136 | irqreturn_t cx18_irq_handler(int irq, void *dev_id) | 161 | irqreturn_t cx18_irq_handler(int irq, void *dev_id) |
| @@ -140,43 +165,36 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) | |||
| 140 | u32 sw2, sw2_mask; | 165 | u32 sw2, sw2_mask; |
| 141 | u32 hw2, hw2_mask; | 166 | u32 hw2, hw2_mask; |
| 142 | 167 | ||
| 143 | spin_lock(&cx->dma_reg_lock); | 168 | sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); |
| 144 | 169 | sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; | |
| 170 | sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); | ||
| 171 | sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; | ||
| 145 | hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); | 172 | hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); |
| 146 | hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; | 173 | hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; |
| 147 | sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; | ||
| 148 | sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; | ||
| 149 | sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; | ||
| 150 | sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; | ||
| 151 | 174 | ||
| 152 | cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS); | 175 | if (sw1) |
| 153 | cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS); | 176 | cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1); |
| 154 | cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); | 177 | if (sw2) |
| 178 | cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2); | ||
| 179 | if (hw2) | ||
| 180 | cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2); | ||
| 155 | 181 | ||
| 156 | if (sw1 || sw2 || hw2) | 182 | if (sw1 || sw2 || hw2) |
| 157 | CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); | 183 | CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); |
| 158 | 184 | ||
| 159 | /* To do: interrupt-based I2C handling | 185 | /* To do: interrupt-based I2C handling |
| 160 | if (hw2 & 0x00c00000) { | 186 | if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) { |
| 161 | } | 187 | } |
| 162 | */ | 188 | */ |
| 163 | 189 | ||
| 164 | if (sw2) { | 190 | if (sw2) |
| 165 | if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) | | 191 | xpu_ack(cx, sw2); |
| 166 | cx18_readl(cx, &cx->scb->cpu2epu_irq_ack))) | ||
| 167 | wake_up(&cx->mb_cpu_waitq); | ||
| 168 | if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) | | ||
| 169 | cx18_readl(cx, &cx->scb->apu2epu_irq_ack))) | ||
| 170 | wake_up(&cx->mb_apu_waitq); | ||
| 171 | if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack)) | ||
| 172 | wake_up(&cx->mb_epu_waitq); | ||
| 173 | if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack)) | ||
| 174 | wake_up(&cx->mb_hpu_waitq); | ||
| 175 | } | ||
| 176 | 192 | ||
| 177 | if (sw1) | 193 | if (sw1) |
| 178 | hpu_cmd(cx, sw1); | 194 | epu_cmd(cx, sw1); |
| 179 | spin_unlock(&cx->dma_reg_lock); | 195 | |
| 196 | if (test_and_clear_bit(CX18_F_I_HAVE_WORK, &cx->i_flags)) | ||
| 197 | queue_work(cx->work_queue, &cx->work); | ||
| 180 | 198 | ||
| 181 | return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE; | 199 | return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; |
| 182 | } | 200 | } |
diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/video/cx18/cx18-irq.h index 379f704f5cba..6173ca3bc9e4 100644 --- a/drivers/media/video/cx18/cx18-irq.h +++ b/drivers/media/video/cx18/cx18-irq.h | |||
| @@ -32,6 +32,4 @@ | |||
| 32 | 32 | ||
| 33 | irqreturn_t cx18_irq_handler(int irq, void *dev_id); | 33 | irqreturn_t cx18_irq_handler(int irq, void *dev_id); |
| 34 | 34 | ||
| 35 | void cx18_irq_work_handler(struct work_struct *work); | 35 | void cx18_work_handler(struct work_struct *work); |
| 36 | void cx18_dma_stream_dec_prepare(struct cx18_stream *s, u32 offset, int lock); | ||
| 37 | void cx18_unfinished_dma(unsigned long arg); | ||
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 9d18dd22de76..acff7dfb60df 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
| @@ -83,7 +83,7 @@ static const struct cx18_api_info api_info[] = { | |||
| 83 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), | 83 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), |
| 84 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), | 84 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), |
| 85 | API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), | 85 | API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), |
| 86 | API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, 0), | 86 | API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), |
| 87 | API_ENTRY(0, 0, 0), | 87 | API_ENTRY(0, 0, 0), |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| @@ -176,7 +176,7 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) | |||
| 176 | 176 | ||
| 177 | cx18_setup_page(cx, SCB_OFFSET); | 177 | cx18_setup_page(cx, SCB_OFFSET); |
| 178 | cx18_write_sync(cx, mb->request, &ack_mb->ack); | 178 | cx18_write_sync(cx, mb->request, &ack_mb->ack); |
| 179 | cx18_write_reg(cx, ack_irq, SW2_INT_SET); | 179 | cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq); |
| 180 | return 0; | 180 | return 0; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| @@ -225,7 +225,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
| 225 | } | 225 | } |
| 226 | if (info->flags & API_FAST) | 226 | if (info->flags & API_FAST) |
| 227 | timeout /= 2; | 227 | timeout /= 2; |
| 228 | cx18_write_reg(cx, irq, SW1_INT_SET); | 228 | cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); |
| 229 | 229 | ||
| 230 | while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) | 230 | while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) |
| 231 | && cnt < 660) { | 231 | && cnt < 660) { |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index a33ba04a2686..174682c2582f 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
| @@ -88,15 +88,13 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, | |||
| 88 | 88 | ||
| 89 | if (buf->id != id) | 89 | if (buf->id != id) |
| 90 | continue; | 90 | continue; |
| 91 | |||
| 91 | buf->bytesused = bytesused; | 92 | buf->bytesused = bytesused; |
| 92 | /* the transport buffers are handled differently, | 93 | atomic_dec(&s->q_free.buffers); |
| 93 | they are not moved to the full queue */ | 94 | atomic_inc(&s->q_full.buffers); |
| 94 | if (s->type != CX18_ENC_STREAM_TYPE_TS) { | 95 | s->q_full.bytesused += buf->bytesused; |
| 95 | atomic_dec(&s->q_free.buffers); | 96 | list_move_tail(&buf->list, &s->q_full.list); |
| 96 | atomic_inc(&s->q_full.buffers); | 97 | |
| 97 | s->q_full.bytesused += buf->bytesused; | ||
| 98 | list_move_tail(&buf->list, &s->q_full.list); | ||
| 99 | } | ||
| 100 | spin_unlock(&s->qlock); | 98 | spin_unlock(&s->qlock); |
| 101 | return buf; | 99 | return buf; |
| 102 | } | 100 | } |
diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h index 86b4cb15d163..594713bbed68 100644 --- a/drivers/media/video/cx18/cx18-scb.h +++ b/drivers/media/video/cx18/cx18-scb.h | |||
| @@ -128,22 +128,22 @@ struct cx18_scb { | |||
| 128 | u32 apu2cpu_irq; | 128 | u32 apu2cpu_irq; |
| 129 | /* Value to write to register SW2 register set (0xC7003140) after the | 129 | /* Value to write to register SW2 register set (0xC7003140) after the |
| 130 | command is cleared */ | 130 | command is cleared */ |
| 131 | u32 apu2cpu_irq_ack; | 131 | u32 cpu2apu_irq_ack; |
| 132 | u32 reserved2[13]; | 132 | u32 reserved2[13]; |
| 133 | 133 | ||
| 134 | u32 hpu2cpu_mb_offset; | 134 | u32 hpu2cpu_mb_offset; |
| 135 | u32 hpu2cpu_irq; | 135 | u32 hpu2cpu_irq; |
| 136 | u32 hpu2cpu_irq_ack; | 136 | u32 cpu2hpu_irq_ack; |
| 137 | u32 reserved3[13]; | 137 | u32 reserved3[13]; |
| 138 | 138 | ||
| 139 | u32 ppu2cpu_mb_offset; | 139 | u32 ppu2cpu_mb_offset; |
| 140 | u32 ppu2cpu_irq; | 140 | u32 ppu2cpu_irq; |
| 141 | u32 ppu2cpu_irq_ack; | 141 | u32 cpu2ppu_irq_ack; |
| 142 | u32 reserved4[13]; | 142 | u32 reserved4[13]; |
| 143 | 143 | ||
| 144 | u32 epu2cpu_mb_offset; | 144 | u32 epu2cpu_mb_offset; |
| 145 | u32 epu2cpu_irq; | 145 | u32 epu2cpu_irq; |
| 146 | u32 epu2cpu_irq_ack; | 146 | u32 cpu2epu_irq_ack; |
| 147 | u32 reserved5[13]; | 147 | u32 reserved5[13]; |
| 148 | u32 reserved6[8]; | 148 | u32 reserved6[8]; |
| 149 | 149 | ||
| @@ -153,22 +153,22 @@ struct cx18_scb { | |||
| 153 | u32 reserved11[7]; | 153 | u32 reserved11[7]; |
| 154 | u32 cpu2apu_mb_offset; | 154 | u32 cpu2apu_mb_offset; |
| 155 | u32 cpu2apu_irq; | 155 | u32 cpu2apu_irq; |
| 156 | u32 cpu2apu_irq_ack; | 156 | u32 apu2cpu_irq_ack; |
| 157 | u32 reserved12[13]; | 157 | u32 reserved12[13]; |
| 158 | 158 | ||
| 159 | u32 hpu2apu_mb_offset; | 159 | u32 hpu2apu_mb_offset; |
| 160 | u32 hpu2apu_irq; | 160 | u32 hpu2apu_irq; |
| 161 | u32 hpu2apu_irq_ack; | 161 | u32 apu2hpu_irq_ack; |
| 162 | u32 reserved13[13]; | 162 | u32 reserved13[13]; |
| 163 | 163 | ||
| 164 | u32 ppu2apu_mb_offset; | 164 | u32 ppu2apu_mb_offset; |
| 165 | u32 ppu2apu_irq; | 165 | u32 ppu2apu_irq; |
| 166 | u32 ppu2apu_irq_ack; | 166 | u32 apu2ppu_irq_ack; |
| 167 | u32 reserved14[13]; | 167 | u32 reserved14[13]; |
| 168 | 168 | ||
| 169 | u32 epu2apu_mb_offset; | 169 | u32 epu2apu_mb_offset; |
| 170 | u32 epu2apu_irq; | 170 | u32 epu2apu_irq; |
| 171 | u32 epu2apu_irq_ack; | 171 | u32 apu2epu_irq_ack; |
| 172 | u32 reserved15[13]; | 172 | u32 reserved15[13]; |
| 173 | u32 reserved16[8]; | 173 | u32 reserved16[8]; |
| 174 | 174 | ||
| @@ -178,22 +178,22 @@ struct cx18_scb { | |||
| 178 | u32 reserved21[7]; | 178 | u32 reserved21[7]; |
| 179 | u32 cpu2hpu_mb_offset; | 179 | u32 cpu2hpu_mb_offset; |
| 180 | u32 cpu2hpu_irq; | 180 | u32 cpu2hpu_irq; |
| 181 | u32 cpu2hpu_irq_ack; | 181 | u32 hpu2cpu_irq_ack; |
| 182 | u32 reserved22[13]; | 182 | u32 reserved22[13]; |
| 183 | 183 | ||
| 184 | u32 apu2hpu_mb_offset; | 184 | u32 apu2hpu_mb_offset; |
| 185 | u32 apu2hpu_irq; | 185 | u32 apu2hpu_irq; |
| 186 | u32 apu2hpu_irq_ack; | 186 | u32 hpu2apu_irq_ack; |
| 187 | u32 reserved23[13]; | 187 | u32 reserved23[13]; |
| 188 | 188 | ||
| 189 | u32 ppu2hpu_mb_offset; | 189 | u32 ppu2hpu_mb_offset; |
| 190 | u32 ppu2hpu_irq; | 190 | u32 ppu2hpu_irq; |
| 191 | u32 ppu2hpu_irq_ack; | 191 | u32 hpu2ppu_irq_ack; |
| 192 | u32 reserved24[13]; | 192 | u32 reserved24[13]; |
| 193 | 193 | ||
| 194 | u32 epu2hpu_mb_offset; | 194 | u32 epu2hpu_mb_offset; |
| 195 | u32 epu2hpu_irq; | 195 | u32 epu2hpu_irq; |
| 196 | u32 epu2hpu_irq_ack; | 196 | u32 hpu2epu_irq_ack; |
| 197 | u32 reserved25[13]; | 197 | u32 reserved25[13]; |
| 198 | u32 reserved26[8]; | 198 | u32 reserved26[8]; |
| 199 | 199 | ||
| @@ -203,22 +203,22 @@ struct cx18_scb { | |||
| 203 | u32 reserved31[7]; | 203 | u32 reserved31[7]; |
| 204 | u32 cpu2ppu_mb_offset; | 204 | u32 cpu2ppu_mb_offset; |
| 205 | u32 cpu2ppu_irq; | 205 | u32 cpu2ppu_irq; |
| 206 | u32 cpu2ppu_irq_ack; | 206 | u32 ppu2cpu_irq_ack; |
| 207 | u32 reserved32[13]; | 207 | u32 reserved32[13]; |
| 208 | 208 | ||
| 209 | u32 apu2ppu_mb_offset; | 209 | u32 apu2ppu_mb_offset; |
| 210 | u32 apu2ppu_irq; | 210 | u32 apu2ppu_irq; |
| 211 | u32 apu2ppu_irq_ack; | 211 | u32 ppu2apu_irq_ack; |
| 212 | u32 reserved33[13]; | 212 | u32 reserved33[13]; |
| 213 | 213 | ||
| 214 | u32 hpu2ppu_mb_offset; | 214 | u32 hpu2ppu_mb_offset; |
| 215 | u32 hpu2ppu_irq; | 215 | u32 hpu2ppu_irq; |
| 216 | u32 hpu2ppu_irq_ack; | 216 | u32 ppu2hpu_irq_ack; |
| 217 | u32 reserved34[13]; | 217 | u32 reserved34[13]; |
| 218 | 218 | ||
| 219 | u32 epu2ppu_mb_offset; | 219 | u32 epu2ppu_mb_offset; |
| 220 | u32 epu2ppu_irq; | 220 | u32 epu2ppu_irq; |
| 221 | u32 epu2ppu_irq_ack; | 221 | u32 ppu2epu_irq_ack; |
| 222 | u32 reserved35[13]; | 222 | u32 reserved35[13]; |
| 223 | u32 reserved36[8]; | 223 | u32 reserved36[8]; |
| 224 | 224 | ||
| @@ -228,22 +228,22 @@ struct cx18_scb { | |||
| 228 | u32 reserved41[7]; | 228 | u32 reserved41[7]; |
| 229 | u32 cpu2epu_mb_offset; | 229 | u32 cpu2epu_mb_offset; |
| 230 | u32 cpu2epu_irq; | 230 | u32 cpu2epu_irq; |
| 231 | u32 cpu2epu_irq_ack; | 231 | u32 epu2cpu_irq_ack; |
| 232 | u32 reserved42[13]; | 232 | u32 reserved42[13]; |
| 233 | 233 | ||
| 234 | u32 apu2epu_mb_offset; | 234 | u32 apu2epu_mb_offset; |
| 235 | u32 apu2epu_irq; | 235 | u32 apu2epu_irq; |
| 236 | u32 apu2epu_irq_ack; | 236 | u32 epu2apu_irq_ack; |
| 237 | u32 reserved43[13]; | 237 | u32 reserved43[13]; |
| 238 | 238 | ||
| 239 | u32 hpu2epu_mb_offset; | 239 | u32 hpu2epu_mb_offset; |
| 240 | u32 hpu2epu_irq; | 240 | u32 hpu2epu_irq; |
| 241 | u32 hpu2epu_irq_ack; | 241 | u32 epu2hpu_irq_ack; |
| 242 | u32 reserved44[13]; | 242 | u32 reserved44[13]; |
| 243 | 243 | ||
| 244 | u32 ppu2epu_mb_offset; | 244 | u32 ppu2epu_mb_offset; |
| 245 | u32 ppu2epu_irq; | 245 | u32 ppu2epu_irq; |
| 246 | u32 ppu2epu_irq_ack; | 246 | u32 epu2ppu_irq_ack; |
| 247 | u32 reserved45[13]; | 247 | u32 reserved45[13]; |
| 248 | u32 reserved46[8]; | 248 | u32 reserved46[8]; |
| 249 | 249 | ||
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 078be6319556..d3ae5b4dfca7 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
| @@ -1078,7 +1078,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1078 | } | 1078 | } |
| 1079 | } | 1079 | } |
| 1080 | 1080 | ||
| 1081 | if (blackbird_initialize_codec(dev) < 0) { | 1081 | if (!atomic_read(&dev->core->mpeg_users) && blackbird_initialize_codec(dev) < 0) { |
| 1082 | if (drv) | 1082 | if (drv) |
| 1083 | drv->request_release(drv); | 1083 | drv->request_release(drv); |
| 1084 | unlock_kernel(); | 1084 | unlock_kernel(); |
| @@ -1109,6 +1109,8 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1109 | fh->mpegq.field); | 1109 | fh->mpegq.field); |
| 1110 | unlock_kernel(); | 1110 | unlock_kernel(); |
| 1111 | 1111 | ||
| 1112 | atomic_inc(&dev->core->mpeg_users); | ||
| 1113 | |||
| 1112 | return 0; | 1114 | return 0; |
| 1113 | } | 1115 | } |
| 1114 | 1116 | ||
| @@ -1118,7 +1120,7 @@ static int mpeg_release(struct inode *inode, struct file *file) | |||
| 1118 | struct cx8802_dev *dev = fh->dev; | 1120 | struct cx8802_dev *dev = fh->dev; |
| 1119 | struct cx8802_driver *drv = NULL; | 1121 | struct cx8802_driver *drv = NULL; |
| 1120 | 1122 | ||
| 1121 | if (dev->mpeg_active) | 1123 | if (dev->mpeg_active && atomic_read(&dev->core->mpeg_users) == 1) |
| 1122 | blackbird_stop_codec(dev); | 1124 | blackbird_stop_codec(dev); |
| 1123 | 1125 | ||
| 1124 | cx8802_cancel_buffers(fh->dev); | 1126 | cx8802_cancel_buffers(fh->dev); |
| @@ -1138,6 +1140,8 @@ static int mpeg_release(struct inode *inode, struct file *file) | |||
| 1138 | if (drv) | 1140 | if (drv) |
| 1139 | drv->request_release(drv); | 1141 | drv->request_release(drv); |
| 1140 | 1142 | ||
| 1143 | atomic_dec(&dev->core->mpeg_users); | ||
| 1144 | |||
| 1141 | return 0; | 1145 | return 0; |
| 1142 | } | 1146 | } |
| 1143 | 1147 | ||
| @@ -1158,6 +1162,10 @@ static unsigned int | |||
| 1158 | mpeg_poll(struct file *file, struct poll_table_struct *wait) | 1162 | mpeg_poll(struct file *file, struct poll_table_struct *wait) |
| 1159 | { | 1163 | { |
| 1160 | struct cx8802_fh *fh = file->private_data; | 1164 | struct cx8802_fh *fh = file->private_data; |
| 1165 | struct cx8802_dev *dev = fh->dev; | ||
| 1166 | |||
| 1167 | if (!dev->mpeg_active) | ||
| 1168 | blackbird_start_codec(file, fh); | ||
| 1161 | 1169 | ||
| 1162 | return videobuf_poll_stream(file, &fh->mpegq, wait); | 1170 | return videobuf_poll_stream(file, &fh->mpegq, wait); |
| 1163 | } | 1171 | } |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index cf6c30d4e545..309ca5e68063 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
| @@ -598,6 +598,11 @@ static int dvb_register(struct cx8802_dev *dev) | |||
| 598 | struct videobuf_dvb_frontend *fe0, *fe1 = NULL; | 598 | struct videobuf_dvb_frontend *fe0, *fe1 = NULL; |
| 599 | int mfe_shared = 0; /* bus not shared by default */ | 599 | int mfe_shared = 0; /* bus not shared by default */ |
| 600 | 600 | ||
| 601 | if (0 != core->i2c_rc) { | ||
| 602 | printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); | ||
| 603 | goto frontend_detach; | ||
| 604 | } | ||
| 605 | |||
| 601 | /* Get the first frontend */ | 606 | /* Get the first frontend */ |
| 602 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | 607 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); |
| 603 | if (!fe0) | 608 | if (!fe0) |
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index a1c435b4b1cd..3ebdcd1d83f8 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
| @@ -769,10 +769,6 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, | |||
| 769 | struct cx8802_dev *dev; | 769 | struct cx8802_dev *dev; |
| 770 | struct cx88_core *core; | 770 | struct cx88_core *core; |
| 771 | int err; | 771 | int err; |
| 772 | #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) | ||
| 773 | struct videobuf_dvb_frontend *demod; | ||
| 774 | int i; | ||
| 775 | #endif | ||
| 776 | 772 | ||
| 777 | /* general setup */ | 773 | /* general setup */ |
| 778 | core = cx88_core_get(pci_dev); | 774 | core = cx88_core_get(pci_dev); |
| @@ -803,15 +799,21 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, | |||
| 803 | mutex_init(&dev->frontends.lock); | 799 | mutex_init(&dev->frontends.lock); |
| 804 | INIT_LIST_HEAD(&dev->frontends.felist); | 800 | INIT_LIST_HEAD(&dev->frontends.felist); |
| 805 | 801 | ||
| 806 | if (core->board.num_frontends) | 802 | if (core->board.num_frontends) { |
| 807 | printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends); | 803 | struct videobuf_dvb_frontend *fe; |
| 808 | 804 | int i; | |
| 809 | for (i = 1; i <= core->board.num_frontends; i++) { | 805 | |
| 810 | demod = videobuf_dvb_alloc_frontend(&dev->frontends, i); | 806 | printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, |
| 811 | if(demod == NULL) { | 807 | core->board.num_frontends); |
| 812 | printk(KERN_ERR "%s() failed to alloc\n", __func__); | 808 | for (i = 1; i <= core->board.num_frontends; i++) { |
| 813 | err = -ENOMEM; | 809 | fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); |
| 814 | goto fail_free; | 810 | if(fe == NULL) { |
| 811 | printk(KERN_ERR "%s() failed to alloc\n", | ||
| 812 | __func__); | ||
| 813 | videobuf_dvb_dealloc_frontends(&dev->frontends); | ||
| 814 | err = -ENOMEM; | ||
| 815 | goto fail_free; | ||
| 816 | } | ||
| 815 | } | 817 | } |
| 816 | } | 818 | } |
| 817 | #endif | 819 | #endif |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 61265fd04d56..b96ce991d968 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
| @@ -1216,8 +1216,12 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
| 1216 | struct cx8800_fh *fh = priv; | 1216 | struct cx8800_fh *fh = priv; |
| 1217 | struct cx8800_dev *dev = fh->dev; | 1217 | struct cx8800_dev *dev = fh->dev; |
| 1218 | 1218 | ||
| 1219 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | 1219 | /* We should remember that this driver also supports teletext, */ |
| 1220 | /* so we have to test if the v4l2_buf_type is VBI capture data. */ | ||
| 1221 | if (unlikely((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && | ||
| 1222 | (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))) | ||
| 1220 | return -EINVAL; | 1223 | return -EINVAL; |
| 1224 | |||
| 1221 | if (unlikely(i != fh->type)) | 1225 | if (unlikely(i != fh->type)) |
| 1222 | return -EINVAL; | 1226 | return -EINVAL; |
| 1223 | 1227 | ||
| @@ -1232,8 +1236,10 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
| 1232 | struct cx8800_dev *dev = fh->dev; | 1236 | struct cx8800_dev *dev = fh->dev; |
| 1233 | int err, res; | 1237 | int err, res; |
| 1234 | 1238 | ||
| 1235 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1239 | if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && |
| 1240 | (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
| 1236 | return -EINVAL; | 1241 | return -EINVAL; |
| 1242 | |||
| 1237 | if (i != fh->type) | 1243 | if (i != fh->type) |
| 1238 | return -EINVAL; | 1244 | return -EINVAL; |
| 1239 | 1245 | ||
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 76207c2856b7..f4240965be32 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
| @@ -352,6 +352,7 @@ struct cx88_core { | |||
| 352 | /* various v4l controls */ | 352 | /* various v4l controls */ |
| 353 | u32 freq; | 353 | u32 freq; |
| 354 | atomic_t users; | 354 | atomic_t users; |
| 355 | atomic_t mpeg_users; | ||
| 355 | 356 | ||
| 356 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ | 357 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ |
| 357 | struct cx8802_dev *dvbdev; | 358 | struct cx8802_dev *dvbdev; |
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 4d0817471c9f..6b557c057fac 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
| @@ -3,16 +3,16 @@ menuconfig USB_GSPCA | |||
| 3 | depends on VIDEO_V4L2 | 3 | depends on VIDEO_V4L2 |
| 4 | default m | 4 | default m |
| 5 | ---help--- | 5 | ---help--- |
| 6 | Say Y here if you want to enable selecting webcams based | 6 | Say Y here if you want to enable selecting webcams based |
| 7 | on the GSPCA framework. | 7 | on the GSPCA framework. |
| 8 | 8 | ||
| 9 | See <file:Documentation/video4linux/gspca.txt> for more info. | 9 | See <file:Documentation/video4linux/gspca.txt> for more info. |
| 10 | 10 | ||
| 11 | This driver uses the Video For Linux API. You must say Y or M to | 11 | This driver uses the Video For Linux API. You must say Y or M to |
| 12 | "Video For Linux" to use this driver. | 12 | "Video For Linux" to use this driver. |
| 13 | 13 | ||
| 14 | To compile this driver as modules, choose M here: the | 14 | To compile this driver as modules, choose M here: the |
| 15 | modules will be called gspca_main. | 15 | modules will be called gspca_main. |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | if USB_GSPCA && VIDEO_V4L2 | 18 | if USB_GSPCA && VIDEO_V4L2 |
| @@ -23,190 +23,190 @@ config USB_GSPCA_CONEX | |||
| 23 | tristate "Conexant Camera Driver" | 23 | tristate "Conexant Camera Driver" |
| 24 | depends on VIDEO_V4L2 && USB_GSPCA | 24 | depends on VIDEO_V4L2 && USB_GSPCA |
| 25 | help | 25 | help |
| 26 | Say Y here if you want support for cameras based on the Conexant chip. | 26 | Say Y here if you want support for cameras based on the Conexant chip. |
| 27 | 27 | ||
| 28 | To compile this driver as a module, choose M here: the | 28 | To compile this driver as a module, choose M here: the |
| 29 | module will be called gspca_conex. | 29 | module will be called gspca_conex. |
| 30 | 30 | ||
| 31 | config USB_GSPCA_ETOMS | 31 | config USB_GSPCA_ETOMS |
| 32 | tristate "Etoms USB Camera Driver" | 32 | tristate "Etoms USB Camera Driver" |
| 33 | depends on VIDEO_V4L2 && USB_GSPCA | 33 | depends on VIDEO_V4L2 && USB_GSPCA |
| 34 | help | 34 | help |
| 35 | Say Y here if you want support for cameras based on the Etoms chip. | 35 | Say Y here if you want support for cameras based on the Etoms chip. |
| 36 | 36 | ||
| 37 | To compile this driver as a module, choose M here: the | 37 | To compile this driver as a module, choose M here: the |
| 38 | module will be called gspca_etoms. | 38 | module will be called gspca_etoms. |
| 39 | 39 | ||
| 40 | config USB_GSPCA_FINEPIX | 40 | config USB_GSPCA_FINEPIX |
| 41 | tristate "Fujifilm FinePix USB V4L2 driver" | 41 | tristate "Fujifilm FinePix USB V4L2 driver" |
| 42 | depends on VIDEO_V4L2 && USB_GSPCA | 42 | depends on VIDEO_V4L2 && USB_GSPCA |
| 43 | help | 43 | help |
| 44 | Say Y here if you want support for cameras based on the FinePix chip. | 44 | Say Y here if you want support for cameras based on the FinePix chip. |
| 45 | 45 | ||
| 46 | To compile this driver as a module, choose M here: the | 46 | To compile this driver as a module, choose M here: the |
| 47 | module will be called gspca_finepix. | 47 | module will be called gspca_finepix. |
| 48 | 48 | ||
| 49 | config USB_GSPCA_MARS | 49 | config USB_GSPCA_MARS |
| 50 | tristate "Mars USB Camera Driver" | 50 | tristate "Mars USB Camera Driver" |
| 51 | depends on VIDEO_V4L2 && USB_GSPCA | 51 | depends on VIDEO_V4L2 && USB_GSPCA |
| 52 | help | 52 | help |
| 53 | Say Y here if you want support for cameras based on the Mars chip. | 53 | Say Y here if you want support for cameras based on the Mars chip. |
| 54 | 54 | ||
| 55 | To compile this driver as a module, choose M here: the | 55 | To compile this driver as a module, choose M here: the |
| 56 | module will be called gspca_mars. | 56 | module will be called gspca_mars. |
| 57 | 57 | ||
| 58 | config USB_GSPCA_OV519 | 58 | config USB_GSPCA_OV519 |
| 59 | tristate "OV519 USB Camera Driver" | 59 | tristate "OV519 USB Camera Driver" |
| 60 | depends on VIDEO_V4L2 && USB_GSPCA | 60 | depends on VIDEO_V4L2 && USB_GSPCA |
| 61 | help | 61 | help |
| 62 | Say Y here if you want support for cameras based on the OV519 chip. | 62 | Say Y here if you want support for cameras based on the OV519 chip. |
| 63 | 63 | ||
| 64 | To compile this driver as a module, choose M here: the | 64 | To compile this driver as a module, choose M here: the |
| 65 | module will be called gspca_ov519. | 65 | module will be called gspca_ov519. |
| 66 | 66 | ||
| 67 | config USB_GSPCA_PAC207 | 67 | config USB_GSPCA_PAC207 |
| 68 | tristate "Pixart PAC207 USB Camera Driver" | 68 | tristate "Pixart PAC207 USB Camera Driver" |
| 69 | depends on VIDEO_V4L2 && USB_GSPCA | 69 | depends on VIDEO_V4L2 && USB_GSPCA |
| 70 | help | 70 | help |
| 71 | Say Y here if you want support for cameras based on the PAC207 chip. | 71 | Say Y here if you want support for cameras based on the PAC207 chip. |
| 72 | 72 | ||
| 73 | To compile this driver as a module, choose M here: the | 73 | To compile this driver as a module, choose M here: the |
| 74 | module will be called gspca_pac207. | 74 | module will be called gspca_pac207. |
| 75 | 75 | ||
| 76 | config USB_GSPCA_PAC7311 | 76 | config USB_GSPCA_PAC7311 |
| 77 | tristate "Pixart PAC7311 USB Camera Driver" | 77 | tristate "Pixart PAC7311 USB Camera Driver" |
| 78 | depends on VIDEO_V4L2 && USB_GSPCA | 78 | depends on VIDEO_V4L2 && USB_GSPCA |
| 79 | help | 79 | help |
| 80 | Say Y here if you want support for cameras based on the PAC7311 chip. | 80 | Say Y here if you want support for cameras based on the PAC7311 chip. |
| 81 | 81 | ||
| 82 | To compile this driver as a module, choose M here: the | 82 | To compile this driver as a module, choose M here: the |
| 83 | module will be called gspca_pac7311. | 83 | module will be called gspca_pac7311. |
| 84 | 84 | ||
| 85 | config USB_GSPCA_SONIXB | 85 | config USB_GSPCA_SONIXB |
| 86 | tristate "SN9C102 USB Camera Driver" | 86 | tristate "SN9C102 USB Camera Driver" |
| 87 | depends on VIDEO_V4L2 && USB_GSPCA | 87 | depends on VIDEO_V4L2 && USB_GSPCA |
| 88 | help | 88 | help |
| 89 | Say Y here if you want support for cameras based on the SONIXB chip. | 89 | Say Y here if you want support for cameras based on the SONIXB chip. |
| 90 | 90 | ||
| 91 | To compile this driver as a module, choose M here: the | 91 | To compile this driver as a module, choose M here: the |
| 92 | module will be called gspca_sonixb. | 92 | module will be called gspca_sonixb. |
| 93 | 93 | ||
| 94 | config USB_GSPCA_SONIXJ | 94 | config USB_GSPCA_SONIXJ |
| 95 | tristate "SONIX JPEG USB Camera Driver" | 95 | tristate "SONIX JPEG USB Camera Driver" |
| 96 | depends on VIDEO_V4L2 && USB_GSPCA | 96 | depends on VIDEO_V4L2 && USB_GSPCA |
| 97 | help | 97 | help |
| 98 | Say Y here if you want support for cameras based on the SONIXJ chip. | 98 | Say Y here if you want support for cameras based on the SONIXJ chip. |
| 99 | 99 | ||
| 100 | To compile this driver as a module, choose M here: the | 100 | To compile this driver as a module, choose M here: the |
| 101 | module will be called gspca_sonixj | 101 | module will be called gspca_sonixj |
| 102 | 102 | ||
| 103 | config USB_GSPCA_SPCA500 | 103 | config USB_GSPCA_SPCA500 |
| 104 | tristate "SPCA500 USB Camera Driver" | 104 | tristate "SPCA500 USB Camera Driver" |
| 105 | depends on VIDEO_V4L2 && USB_GSPCA | 105 | depends on VIDEO_V4L2 && USB_GSPCA |
| 106 | help | 106 | help |
| 107 | Say Y here if you want support for cameras based on the SPCA500 chip. | 107 | Say Y here if you want support for cameras based on the SPCA500 chip. |
| 108 | 108 | ||
| 109 | To compile this driver as a module, choose M here: the | 109 | To compile this driver as a module, choose M here: the |
| 110 | module will be called gspca_spca500. | 110 | module will be called gspca_spca500. |
| 111 | 111 | ||
| 112 | config USB_GSPCA_SPCA501 | 112 | config USB_GSPCA_SPCA501 |
| 113 | tristate "SPCA501 USB Camera Driver" | 113 | tristate "SPCA501 USB Camera Driver" |
| 114 | depends on VIDEO_V4L2 && USB_GSPCA | 114 | depends on VIDEO_V4L2 && USB_GSPCA |
| 115 | help | 115 | help |
| 116 | Say Y here if you want support for cameras based on the SPCA501 chip. | 116 | Say Y here if you want support for cameras based on the SPCA501 chip. |
| 117 | 117 | ||
| 118 | To compile this driver as a module, choose M here: the | 118 | To compile this driver as a module, choose M here: the |
| 119 | module will be called gspca_spca501. | 119 | module will be called gspca_spca501. |
| 120 | 120 | ||
| 121 | config USB_GSPCA_SPCA505 | 121 | config USB_GSPCA_SPCA505 |
| 122 | tristate "SPCA505 USB Camera Driver" | 122 | tristate "SPCA505 USB Camera Driver" |
| 123 | depends on VIDEO_V4L2 && USB_GSPCA | 123 | depends on VIDEO_V4L2 && USB_GSPCA |
| 124 | help | 124 | help |
| 125 | Say Y here if you want support for cameras based on the SPCA505 chip. | 125 | Say Y here if you want support for cameras based on the SPCA505 chip. |
| 126 | 126 | ||
| 127 | To compile this driver as a module, choose M here: the | 127 | To compile this driver as a module, choose M here: the |
| 128 | module will be called gspca_spca505. | 128 | module will be called gspca_spca505. |
| 129 | 129 | ||
| 130 | config USB_GSPCA_SPCA506 | 130 | config USB_GSPCA_SPCA506 |
| 131 | tristate "SPCA506 USB Camera Driver" | 131 | tristate "SPCA506 USB Camera Driver" |
| 132 | depends on VIDEO_V4L2 && USB_GSPCA | 132 | depends on VIDEO_V4L2 && USB_GSPCA |
| 133 | help | 133 | help |
| 134 | Say Y here if you want support for cameras based on the SPCA506 chip. | 134 | Say Y here if you want support for cameras based on the SPCA506 chip. |
| 135 | 135 | ||
| 136 | To compile this driver as a module, choose M here: the | 136 | To compile this driver as a module, choose M here: the |
| 137 | module will be called gspca_spca506. | 137 | module will be called gspca_spca506. |
| 138 | 138 | ||
| 139 | config USB_GSPCA_SPCA508 | 139 | config USB_GSPCA_SPCA508 |
| 140 | tristate "SPCA508 USB Camera Driver" | 140 | tristate "SPCA508 USB Camera Driver" |
| 141 | depends on VIDEO_V4L2 && USB_GSPCA | 141 | depends on VIDEO_V4L2 && USB_GSPCA |
| 142 | help | 142 | help |
| 143 | Say Y here if you want support for cameras based on the SPCA508 chip. | 143 | Say Y here if you want support for cameras based on the SPCA508 chip. |
| 144 | 144 | ||
| 145 | To compile this driver as a module, choose M here: the | 145 | To compile this driver as a module, choose M here: the |
| 146 | module will be called gspca_spca508. | 146 | module will be called gspca_spca508. |
| 147 | 147 | ||
| 148 | config USB_GSPCA_SPCA561 | 148 | config USB_GSPCA_SPCA561 |
| 149 | tristate "SPCA561 USB Camera Driver" | 149 | tristate "SPCA561 USB Camera Driver" |
| 150 | depends on VIDEO_V4L2 && USB_GSPCA | 150 | depends on VIDEO_V4L2 && USB_GSPCA |
| 151 | help | 151 | help |
| 152 | Say Y here if you want support for cameras based on the SPCA561 chip. | 152 | Say Y here if you want support for cameras based on the SPCA561 chip. |
| 153 | 153 | ||
| 154 | To compile this driver as a module, choose M here: the | 154 | To compile this driver as a module, choose M here: the |
| 155 | module will be called gspca_spca561. | 155 | module will be called gspca_spca561. |
| 156 | 156 | ||
| 157 | config USB_GSPCA_STK014 | 157 | config USB_GSPCA_STK014 |
| 158 | tristate "Syntek DV4000 (STK014) USB Camera Driver" | 158 | tristate "Syntek DV4000 (STK014) USB Camera Driver" |
| 159 | depends on VIDEO_V4L2 && USB_GSPCA | 159 | depends on VIDEO_V4L2 && USB_GSPCA |
| 160 | help | 160 | help |
| 161 | Say Y here if you want support for cameras based on the STK014 chip. | 161 | Say Y here if you want support for cameras based on the STK014 chip. |
| 162 | 162 | ||
| 163 | To compile this driver as a module, choose M here: the | 163 | To compile this driver as a module, choose M here: the |
| 164 | module will be called gspca_stk014. | 164 | module will be called gspca_stk014. |
| 165 | 165 | ||
| 166 | config USB_GSPCA_SUNPLUS | 166 | config USB_GSPCA_SUNPLUS |
| 167 | tristate "SUNPLUS USB Camera Driver" | 167 | tristate "SUNPLUS USB Camera Driver" |
| 168 | depends on VIDEO_V4L2 && USB_GSPCA | 168 | depends on VIDEO_V4L2 && USB_GSPCA |
| 169 | help | 169 | help |
| 170 | Say Y here if you want support for cameras based on the Sunplus | 170 | Say Y here if you want support for cameras based on the Sunplus |
| 171 | SPCA504(abc) SPCA533 SPCA536 chips. | 171 | SPCA504(abc) SPCA533 SPCA536 chips. |
| 172 | 172 | ||
| 173 | To compile this driver as a module, choose M here: the | 173 | To compile this driver as a module, choose M here: the |
| 174 | module will be called gspca_spca5xx. | 174 | module will be called gspca_spca5xx. |
| 175 | 175 | ||
| 176 | config USB_GSPCA_T613 | 176 | config USB_GSPCA_T613 |
| 177 | tristate "T613 (JPEG Compliance) USB Camera Driver" | 177 | tristate "T613 (JPEG Compliance) USB Camera Driver" |
| 178 | depends on VIDEO_V4L2 && USB_GSPCA | 178 | depends on VIDEO_V4L2 && USB_GSPCA |
| 179 | help | 179 | help |
| 180 | Say Y here if you want support for cameras based on the T613 chip. | 180 | Say Y here if you want support for cameras based on the T613 chip. |
| 181 | 181 | ||
| 182 | To compile this driver as a module, choose M here: the | 182 | To compile this driver as a module, choose M here: the |
| 183 | module will be called gspca_t613. | 183 | module will be called gspca_t613. |
| 184 | 184 | ||
| 185 | config USB_GSPCA_TV8532 | 185 | config USB_GSPCA_TV8532 |
| 186 | tristate "TV8532 USB Camera Driver" | 186 | tristate "TV8532 USB Camera Driver" |
| 187 | depends on VIDEO_V4L2 && USB_GSPCA | 187 | depends on VIDEO_V4L2 && USB_GSPCA |
| 188 | help | 188 | help |
| 189 | Say Y here if you want support for cameras based on the TV8531 chip. | 189 | Say Y here if you want support for cameras based on the TV8531 chip. |
| 190 | 190 | ||
| 191 | To compile this driver as a module, choose M here: the | 191 | To compile this driver as a module, choose M here: the |
| 192 | module will be called gspca_tv8532. | 192 | module will be called gspca_tv8532. |
| 193 | 193 | ||
| 194 | config USB_GSPCA_VC032X | 194 | config USB_GSPCA_VC032X |
| 195 | tristate "VC032X USB Camera Driver" | 195 | tristate "VC032X USB Camera Driver" |
| 196 | depends on VIDEO_V4L2 && USB_GSPCA | 196 | depends on VIDEO_V4L2 && USB_GSPCA |
| 197 | help | 197 | help |
| 198 | Say Y here if you want support for cameras based on the VC032X chip. | 198 | Say Y here if you want support for cameras based on the VC032X chip. |
| 199 | 199 | ||
| 200 | To compile this driver as a module, choose M here: the | 200 | To compile this driver as a module, choose M here: the |
| 201 | module will be called gspca_vc032x. | 201 | module will be called gspca_vc032x. |
| 202 | 202 | ||
| 203 | config USB_GSPCA_ZC3XX | 203 | config USB_GSPCA_ZC3XX |
| 204 | tristate "VC3xx USB Camera Driver" | 204 | tristate "ZC3XX USB Camera Driver" |
| 205 | depends on VIDEO_V4L2 && USB_GSPCA | 205 | depends on VIDEO_V4L2 && USB_GSPCA |
| 206 | help | 206 | help |
| 207 | Say Y here if you want support for cameras based on the ZC3XX chip. | 207 | Say Y here if you want support for cameras based on the ZC3XX chip. |
| 208 | 208 | ||
| 209 | To compile this driver as a module, choose M here: the | 209 | To compile this driver as a module, choose M here: the |
| 210 | module will be called gspca_zc3xx. | 210 | module will be called gspca_zc3xx. |
| 211 | 211 | ||
| 212 | endif | 212 | endif |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d0a4451dc46f..8b3101d347c3 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
| @@ -2266,7 +2266,7 @@ static const struct usb_action hdcs2020b_NoFliker[] = { | |||
| 2266 | {} | 2266 | {} |
| 2267 | }; | 2267 | }; |
| 2268 | 2268 | ||
| 2269 | static const struct usb_action hv7131bxx_Initial[] = { | 2269 | static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */ |
| 2270 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2270 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
| 2271 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 2271 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
| 2272 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 2272 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
| @@ -2290,7 +2290,7 @@ static const struct usb_action hv7131bxx_Initial[] = { | |||
| 2290 | {0xaa, 0x14, 0x0001}, | 2290 | {0xaa, 0x14, 0x0001}, |
| 2291 | {0xaa, 0x15, 0x00e8}, | 2291 | {0xaa, 0x15, 0x00e8}, |
| 2292 | {0xaa, 0x16, 0x0002}, | 2292 | {0xaa, 0x16, 0x0002}, |
| 2293 | {0xaa, 0x17, 0x0086}, | 2293 | {0xaa, 0x17, 0x0086}, /* 00,17,88,aa */ |
| 2294 | {0xaa, 0x31, 0x0038}, | 2294 | {0xaa, 0x31, 0x0038}, |
| 2295 | {0xaa, 0x32, 0x0038}, | 2295 | {0xaa, 0x32, 0x0038}, |
| 2296 | {0xaa, 0x33, 0x0038}, | 2296 | {0xaa, 0x33, 0x0038}, |
| @@ -2309,7 +2309,7 @@ static const struct usb_action hv7131bxx_Initial[] = { | |||
| 2309 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, | 2309 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, |
| 2310 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, | 2310 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, |
| 2311 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 2311 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
| 2312 | {0xaa, 0x02, 0x0080}, /* {0xaa, 0x02, 0x0090}; */ | 2312 | {0xaa, 0x02, 0x0090}, /* 00,02,80,aa */ |
| 2313 | {0xa1, 0x01, 0x0002}, | 2313 | {0xa1, 0x01, 0x0002}, |
| 2314 | {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, | 2314 | {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, |
| 2315 | {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND}, | 2315 | {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND}, |
| @@ -2374,7 +2374,7 @@ static const struct usb_action hv7131bxx_Initial[] = { | |||
| 2374 | {} | 2374 | {} |
| 2375 | }; | 2375 | }; |
| 2376 | 2376 | ||
| 2377 | static const struct usb_action hv7131bxx_InitialScale[] = { | 2377 | static const struct usb_action hv7131bxx_InitialScale[] = { /* 640x480*/ |
| 2378 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2378 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
| 2379 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 2379 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
| 2380 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 2380 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
| @@ -6388,6 +6388,8 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
| 6388 | /*fixme: is it really write to 011d and 018d for all other sensors? */ | 6388 | /*fixme: is it really write to 011d and 018d for all other sensors? */ |
| 6389 | brightness = sd->brightness; | 6389 | brightness = sd->brightness; |
| 6390 | reg_w(gspca_dev->dev, brightness, 0x011d); | 6390 | reg_w(gspca_dev->dev, brightness, 0x011d); |
| 6391 | if (sd->sensor == SENSOR_HV7131B) | ||
| 6392 | return; | ||
| 6391 | if (brightness < 0x70) | 6393 | if (brightness < 0x70) |
| 6392 | brightness += 0x10; | 6394 | brightness += 0x10; |
| 6393 | else | 6395 | else |
| @@ -6529,6 +6531,7 @@ static void setquality(struct gspca_dev *gspca_dev) | |||
| 6529 | 6531 | ||
| 6530 | switch (sd->sensor) { | 6532 | switch (sd->sensor) { |
| 6531 | case SENSOR_GC0305: | 6533 | case SENSOR_GC0305: |
| 6534 | case SENSOR_HV7131B: | ||
| 6532 | case SENSOR_OV7620: | 6535 | case SENSOR_OV7620: |
| 6533 | case SENSOR_PO2030: | 6536 | case SENSOR_PO2030: |
| 6534 | return; | 6537 | return; |
| @@ -7209,7 +7212,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
| 7209 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 7212 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; |
| 7210 | zc3_init = init_tb[(int) sd->sensor][mode]; | 7213 | zc3_init = init_tb[(int) sd->sensor][mode]; |
| 7211 | switch (sd->sensor) { | 7214 | switch (sd->sensor) { |
| 7212 | case SENSOR_HV7131B: | ||
| 7213 | case SENSOR_HV7131C: | 7215 | case SENSOR_HV7131C: |
| 7214 | zcxx_probeSensor(gspca_dev); | 7216 | zcxx_probeSensor(gspca_dev); |
| 7215 | break; | 7217 | break; |
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index 0069898bddab..c46bfb1569e3 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config VIDEO_IVTV | 1 | config VIDEO_IVTV |
| 2 | tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" | 2 | tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" |
| 3 | depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL | 3 | depends on VIDEO_V4L2 && PCI && I2C |
| 4 | depends on INPUT # due to VIDEO_IR | 4 | depends on INPUT # due to VIDEO_IR |
| 5 | select I2C_ALGOBIT | 5 | select I2C_ALGOBIT |
| 6 | select VIDEO_IR | 6 | select VIDEO_IR |
| @@ -12,7 +12,6 @@ config VIDEO_IVTV | |||
| 12 | select VIDEO_SAA711X | 12 | select VIDEO_SAA711X |
| 13 | select VIDEO_SAA717X | 13 | select VIDEO_SAA717X |
| 14 | select VIDEO_SAA7127 | 14 | select VIDEO_SAA7127 |
| 15 | select VIDEO_TVAUDIO | ||
| 16 | select VIDEO_CS53L32A | 15 | select VIDEO_CS53L32A |
| 17 | select VIDEO_M52790 | 16 | select VIDEO_M52790 |
| 18 | select VIDEO_WM8775 | 17 | select VIDEO_WM8775 |
| @@ -32,7 +31,7 @@ config VIDEO_IVTV | |||
| 32 | 31 | ||
| 33 | config VIDEO_FB_IVTV | 32 | config VIDEO_FB_IVTV |
| 34 | tristate "Conexant cx23415 framebuffer support" | 33 | tristate "Conexant cx23415 framebuffer support" |
| 35 | depends on VIDEO_IVTV && FB && EXPERIMENTAL | 34 | depends on VIDEO_IVTV && FB |
| 36 | select FB_CFB_FILLRECT | 35 | select FB_CFB_FILLRECT |
| 37 | select FB_CFB_COPYAREA | 36 | select FB_CFB_COPYAREA |
| 38 | select FB_CFB_IMAGEBLIT | 37 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index d36485023b68..b69cc1d55e5b 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
| @@ -875,43 +875,43 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) | |||
| 875 | 875 | ||
| 876 | #ifdef MODULE | 876 | #ifdef MODULE |
| 877 | /* load modules */ | 877 | /* load modules */ |
| 878 | #ifndef CONFIG_MEDIA_TUNER | 878 | #ifdef CONFIG_MEDIA_TUNER_MODULE |
| 879 | hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER); | 879 | hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER); |
| 880 | #endif | 880 | #endif |
| 881 | #ifndef CONFIG_VIDEO_CX25840 | 881 | #ifdef CONFIG_VIDEO_CX25840_MODULE |
| 882 | hw = ivtv_request_module(itv, hw, "cx25840", IVTV_HW_CX25840); | 882 | hw = ivtv_request_module(itv, hw, "cx25840", IVTV_HW_CX25840); |
| 883 | #endif | 883 | #endif |
| 884 | #ifndef CONFIG_VIDEO_SAA711X | 884 | #ifdef CONFIG_VIDEO_SAA711X_MODULE |
| 885 | hw = ivtv_request_module(itv, hw, "saa7115", IVTV_HW_SAA711X); | 885 | hw = ivtv_request_module(itv, hw, "saa7115", IVTV_HW_SAA711X); |
| 886 | #endif | 886 | #endif |
| 887 | #ifndef CONFIG_VIDEO_SAA7127 | 887 | #ifdef CONFIG_VIDEO_SAA7127_MODULE |
| 888 | hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127); | 888 | hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127); |
| 889 | #endif | 889 | #endif |
| 890 | #ifndef CONFIG_VIDEO_SAA717X | 890 | #ifdef CONFIG_VIDEO_SAA717X_MODULE |
| 891 | hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X); | 891 | hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X); |
| 892 | #endif | 892 | #endif |
| 893 | #ifndef CONFIG_VIDEO_UPD64031A | 893 | #ifdef CONFIG_VIDEO_UPD64031A_MODULE |
| 894 | hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A); | 894 | hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A); |
| 895 | #endif | 895 | #endif |
| 896 | #ifndef CONFIG_VIDEO_UPD64083 | 896 | #ifdef CONFIG_VIDEO_UPD64083_MODULE |
| 897 | hw = ivtv_request_module(itv, hw, "upd64083", IVTV_HW_UPD6408X); | 897 | hw = ivtv_request_module(itv, hw, "upd64083", IVTV_HW_UPD6408X); |
| 898 | #endif | 898 | #endif |
| 899 | #ifndef CONFIG_VIDEO_MSP3400 | 899 | #ifdef CONFIG_VIDEO_MSP3400_MODULE |
| 900 | hw = ivtv_request_module(itv, hw, "msp3400", IVTV_HW_MSP34XX); | 900 | hw = ivtv_request_module(itv, hw, "msp3400", IVTV_HW_MSP34XX); |
| 901 | #endif | 901 | #endif |
| 902 | #ifndef CONFIG_VIDEO_VP27SMPX | 902 | #ifdef CONFIG_VIDEO_VP27SMPX_MODULE |
| 903 | hw = ivtv_request_module(itv, hw, "vp27smpx", IVTV_HW_VP27SMPX); | 903 | hw = ivtv_request_module(itv, hw, "vp27smpx", IVTV_HW_VP27SMPX); |
| 904 | #endif | 904 | #endif |
| 905 | #ifndef CONFIG_VIDEO_WM8775 | 905 | #ifdef CONFIG_VIDEO_WM8775_MODULE |
| 906 | hw = ivtv_request_module(itv, hw, "wm8775", IVTV_HW_WM8775); | 906 | hw = ivtv_request_module(itv, hw, "wm8775", IVTV_HW_WM8775); |
| 907 | #endif | 907 | #endif |
| 908 | #ifndef CONFIG_VIDEO_WM8739 | 908 | #ifdef CONFIG_VIDEO_WM8739_MODULE |
| 909 | hw = ivtv_request_module(itv, hw, "wm8739", IVTV_HW_WM8739); | 909 | hw = ivtv_request_module(itv, hw, "wm8739", IVTV_HW_WM8739); |
| 910 | #endif | 910 | #endif |
| 911 | #ifndef CONFIG_VIDEO_CS53L32A | 911 | #ifdef CONFIG_VIDEO_CS53L32A_MODULE |
| 912 | hw = ivtv_request_module(itv, hw, "cs53l32a", IVTV_HW_CS53L32A); | 912 | hw = ivtv_request_module(itv, hw, "cs53l32a", IVTV_HW_CS53L32A); |
| 913 | #endif | 913 | #endif |
| 914 | #ifndef CONFIG_VIDEO_M52790 | 914 | #ifdef CONFIG_VIDEO_M52790_MODULE |
| 915 | hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790); | 915 | hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790); |
| 916 | #endif | 916 | #endif |
| 917 | #endif | 917 | #endif |
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index adf2ba79496a..37860698f782 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c | |||
| @@ -47,7 +47,7 @@ module_param(debug, int, 0); | |||
| 47 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | 47 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
| 48 | 48 | ||
| 49 | #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */ | 49 | #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */ |
| 50 | #define SAA7110_MAX_OUTPUT 0 /* its a decoder only */ | 50 | #define SAA7110_MAX_OUTPUT 1 /* 1 YUV */ |
| 51 | 51 | ||
| 52 | #define SAA7110_NR_REG 0x35 | 52 | #define SAA7110_NR_REG 0x35 |
| 53 | 53 | ||
| @@ -327,7 +327,7 @@ saa7110_command (struct i2c_client *client, | |||
| 327 | 327 | ||
| 328 | case DECODER_SET_INPUT: | 328 | case DECODER_SET_INPUT: |
| 329 | v = *(int *) arg; | 329 | v = *(int *) arg; |
| 330 | if (v < 0 || v > SAA7110_MAX_INPUT) { | 330 | if (v < 0 || v >= SAA7110_MAX_INPUT) { |
| 331 | v4l_dbg(1, debug, client, "input=%d not available\n", v); | 331 | v4l_dbg(1, debug, client, "input=%d not available\n", v); |
| 332 | return -EINVAL; | 332 | return -EINVAL; |
| 333 | } | 333 | } |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 249184452949..dfbe08a9ad9b 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
| @@ -941,7 +941,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
| 941 | dev->name,(unsigned long long)pci_resource_start(pci_dev,0)); | 941 | dev->name,(unsigned long long)pci_resource_start(pci_dev,0)); |
| 942 | goto fail1; | 942 | goto fail1; |
| 943 | } | 943 | } |
| 944 | dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000); | 944 | dev->lmmio = ioremap(pci_resource_start(pci_dev, 0), |
| 945 | pci_resource_len(pci_dev, 0)); | ||
| 945 | dev->bmmio = (__u8 __iomem *)dev->lmmio; | 946 | dev->bmmio = (__u8 __iomem *)dev->lmmio; |
| 946 | if (NULL == dev->lmmio) { | 947 | if (NULL == dev->lmmio) { |
| 947 | err = -EIO; | 948 | err = -EIO; |
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index b59e47272abf..3720f0e03a16 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * experimental driver for simple i2c audio chips. | 2 | * Driver for simple i2c audio chips. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2000 Gerd Knorr | 4 | * Copyright (c) 2000 Gerd Knorr |
| 5 | * based on code by: | 5 | * based on code by: |
| @@ -7,6 +7,10 @@ | |||
| 7 | * Steve VanDeBogart (vandebo@uclink.berkeley.edu) | 7 | * Steve VanDeBogart (vandebo@uclink.berkeley.edu) |
| 8 | * Greg Alexander (galexand@acm.org) | 8 | * Greg Alexander (galexand@acm.org) |
| 9 | * | 9 | * |
| 10 | * Copyright(c) 2005-2008 Mauro Carvalho Chehab | ||
| 11 | * - Some cleanups, code fixes, etc | ||
| 12 | * - Convert it to V4L2 API | ||
| 13 | * | ||
| 10 | * This code is placed under the terms of the GNU General Public License | 14 | * This code is placed under the terms of the GNU General Public License |
| 11 | * | 15 | * |
| 12 | * OPTIONS: | 16 | * OPTIONS: |
| @@ -30,6 +34,7 @@ | |||
| 30 | 34 | ||
| 31 | #include <media/tvaudio.h> | 35 | #include <media/tvaudio.h> |
| 32 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
| 37 | #include <media/v4l2-ioctl.h> | ||
| 33 | #include <media/v4l2-chip-ident.h> | 38 | #include <media/v4l2-chip-ident.h> |
| 34 | #include <media/v4l2-i2c-drv-legacy.h> | 39 | #include <media/v4l2-i2c-drv-legacy.h> |
| 35 | 40 | ||
| @@ -58,7 +63,6 @@ typedef int (*checkit)(struct CHIPSTATE*); | |||
| 58 | typedef int (*initialize)(struct CHIPSTATE*); | 63 | typedef int (*initialize)(struct CHIPSTATE*); |
| 59 | typedef int (*getmode)(struct CHIPSTATE*); | 64 | typedef int (*getmode)(struct CHIPSTATE*); |
| 60 | typedef void (*setmode)(struct CHIPSTATE*, int mode); | 65 | typedef void (*setmode)(struct CHIPSTATE*, int mode); |
| 61 | typedef void (*checkmode)(struct CHIPSTATE*); | ||
| 62 | 66 | ||
| 63 | /* i2c command */ | 67 | /* i2c command */ |
| 64 | typedef struct AUDIOCMD { | 68 | typedef struct AUDIOCMD { |
| @@ -79,6 +83,7 @@ struct CHIPDESC { | |||
| 79 | #define CHIP_HAS_VOLUME 1 | 83 | #define CHIP_HAS_VOLUME 1 |
| 80 | #define CHIP_HAS_BASSTREBLE 2 | 84 | #define CHIP_HAS_BASSTREBLE 2 |
| 81 | #define CHIP_HAS_INPUTSEL 4 | 85 | #define CHIP_HAS_INPUTSEL 4 |
| 86 | #define CHIP_NEED_CHECKMODE 8 | ||
| 82 | 87 | ||
| 83 | /* various i2c command sequences */ | 88 | /* various i2c command sequences */ |
| 84 | audiocmd init; | 89 | audiocmd init; |
| @@ -96,23 +101,20 @@ struct CHIPDESC { | |||
| 96 | getmode getmode; | 101 | getmode getmode; |
| 97 | setmode setmode; | 102 | setmode setmode; |
| 98 | 103 | ||
| 99 | /* check / autoswitch audio after channel switches */ | ||
| 100 | checkmode checkmode; | ||
| 101 | |||
| 102 | /* input switch register + values for v4l inputs */ | 104 | /* input switch register + values for v4l inputs */ |
| 103 | int inputreg; | 105 | int inputreg; |
| 104 | int inputmap[4]; | 106 | int inputmap[4]; |
| 105 | int inputmute; | 107 | int inputmute; |
| 106 | int inputmask; | 108 | int inputmask; |
| 107 | }; | 109 | }; |
| 108 | static struct CHIPDESC chiplist[]; | ||
| 109 | 110 | ||
| 110 | /* current state of the chip */ | 111 | /* current state of the chip */ |
| 111 | struct CHIPSTATE { | 112 | struct CHIPSTATE { |
| 112 | struct i2c_client *c; | 113 | struct i2c_client *c; |
| 113 | 114 | ||
| 114 | /* index into CHIPDESC array */ | 115 | /* chip-specific description - should point to |
| 115 | int type; | 116 | an entry at CHIPDESC table */ |
| 117 | struct CHIPDESC *desc; | ||
| 116 | 118 | ||
| 117 | /* shadow register set */ | 119 | /* shadow register set */ |
| 118 | audiocmd shadow; | 120 | audiocmd shadow; |
| @@ -152,7 +154,7 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) | |||
| 152 | { | 154 | { |
| 153 | unsigned char buffer[2]; | 155 | unsigned char buffer[2]; |
| 154 | 156 | ||
| 155 | if (-1 == subaddr) { | 157 | if (subaddr < 0) { |
| 156 | v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n", | 158 | v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n", |
| 157 | chip->c->name, val); | 159 | chip->c->name, val); |
| 158 | chip->shadow.bytes[1] = val; | 160 | chip->shadow.bytes[1] = val; |
| @@ -163,6 +165,13 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) | |||
| 163 | return -1; | 165 | return -1; |
| 164 | } | 166 | } |
| 165 | } else { | 167 | } else { |
| 168 | if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { | ||
| 169 | v4l_info(chip->c, | ||
| 170 | "Tried to access a non-existent register: %d\n", | ||
| 171 | subaddr); | ||
| 172 | return -EINVAL; | ||
| 173 | } | ||
| 174 | |||
| 166 | v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n", | 175 | v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n", |
| 167 | chip->c->name, subaddr, val); | 176 | chip->c->name, subaddr, val); |
| 168 | chip->shadow.bytes[subaddr+1] = val; | 177 | chip->shadow.bytes[subaddr+1] = val; |
| @@ -177,12 +186,20 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) | |||
| 177 | return 0; | 186 | return 0; |
| 178 | } | 187 | } |
| 179 | 188 | ||
| 180 | static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask) | 189 | static int chip_write_masked(struct CHIPSTATE *chip, |
| 190 | int subaddr, int val, int mask) | ||
| 181 | { | 191 | { |
| 182 | if (mask != 0) { | 192 | if (mask != 0) { |
| 183 | if (-1 == subaddr) { | 193 | if (subaddr < 0) { |
| 184 | val = (chip->shadow.bytes[1] & ~mask) | (val & mask); | 194 | val = (chip->shadow.bytes[1] & ~mask) | (val & mask); |
| 185 | } else { | 195 | } else { |
| 196 | if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { | ||
| 197 | v4l_info(chip->c, | ||
| 198 | "Tried to access a non-existent register: %d\n", | ||
| 199 | subaddr); | ||
| 200 | return -EINVAL; | ||
| 201 | } | ||
| 202 | |||
| 186 | val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask); | 203 | val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask); |
| 187 | } | 204 | } |
| 188 | } | 205 | } |
| @@ -228,6 +245,15 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) | |||
| 228 | if (0 == cmd->count) | 245 | if (0 == cmd->count) |
| 229 | return 0; | 246 | return 0; |
| 230 | 247 | ||
| 248 | if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) { | ||
| 249 | v4l_info(chip->c, | ||
| 250 | "Tried to access a non-existent register range: %d to %d\n", | ||
| 251 | cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1); | ||
| 252 | return -EINVAL; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* FIXME: it seems that the shadow bytes are wrong bellow !*/ | ||
| 256 | |||
| 231 | /* update our shadow register set; print bytes if (debug > 0) */ | 257 | /* update our shadow register set; print bytes if (debug > 0) */ |
| 232 | v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:", | 258 | v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:", |
| 233 | chip->c->name, name,cmd->bytes[0]); | 259 | chip->c->name, name,cmd->bytes[0]); |
| @@ -263,7 +289,8 @@ static void chip_thread_wake(unsigned long data) | |||
| 263 | static int chip_thread(void *data) | 289 | static int chip_thread(void *data) |
| 264 | { | 290 | { |
| 265 | struct CHIPSTATE *chip = data; | 291 | struct CHIPSTATE *chip = data; |
| 266 | struct CHIPDESC *desc = chiplist + chip->type; | 292 | struct CHIPDESC *desc = chip->desc; |
| 293 | int mode; | ||
| 267 | 294 | ||
| 268 | v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); | 295 | v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); |
| 269 | set_freezable(); | 296 | set_freezable(); |
| @@ -282,7 +309,26 @@ static int chip_thread(void *data) | |||
| 282 | continue; | 309 | continue; |
| 283 | 310 | ||
| 284 | /* have a look what's going on */ | 311 | /* have a look what's going on */ |
| 285 | desc->checkmode(chip); | 312 | mode = desc->getmode(chip); |
| 313 | if (mode == chip->prevmode) | ||
| 314 | continue; | ||
| 315 | |||
| 316 | /* chip detected a new audio mode - set it */ | ||
| 317 | v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", | ||
| 318 | chip->c->name); | ||
| 319 | |||
| 320 | chip->prevmode = mode; | ||
| 321 | |||
| 322 | if (mode & V4L2_TUNER_MODE_STEREO) | ||
| 323 | desc->setmode(chip, V4L2_TUNER_MODE_STEREO); | ||
| 324 | if (mode & V4L2_TUNER_MODE_LANG1_LANG2) | ||
| 325 | desc->setmode(chip, V4L2_TUNER_MODE_STEREO); | ||
| 326 | else if (mode & V4L2_TUNER_MODE_LANG1) | ||
| 327 | desc->setmode(chip, V4L2_TUNER_MODE_LANG1); | ||
| 328 | else if (mode & V4L2_TUNER_MODE_LANG2) | ||
| 329 | desc->setmode(chip, V4L2_TUNER_MODE_LANG2); | ||
| 330 | else | ||
| 331 | desc->setmode(chip, V4L2_TUNER_MODE_MONO); | ||
| 286 | 332 | ||
| 287 | /* schedule next check */ | 333 | /* schedule next check */ |
| 288 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); | 334 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); |
| @@ -292,29 +338,6 @@ static int chip_thread(void *data) | |||
| 292 | return 0; | 338 | return 0; |
| 293 | } | 339 | } |
| 294 | 340 | ||
| 295 | static void generic_checkmode(struct CHIPSTATE *chip) | ||
| 296 | { | ||
| 297 | struct CHIPDESC *desc = chiplist + chip->type; | ||
| 298 | int mode = desc->getmode(chip); | ||
| 299 | |||
| 300 | if (mode == chip->prevmode) | ||
| 301 | return; | ||
| 302 | |||
| 303 | v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", chip->c->name); | ||
| 304 | chip->prevmode = mode; | ||
| 305 | |||
| 306 | if (mode & V4L2_TUNER_MODE_STEREO) | ||
| 307 | desc->setmode(chip,V4L2_TUNER_MODE_STEREO); | ||
| 308 | if (mode & V4L2_TUNER_MODE_LANG1_LANG2) | ||
| 309 | desc->setmode(chip,V4L2_TUNER_MODE_STEREO); | ||
| 310 | else if (mode & V4L2_TUNER_MODE_LANG1) | ||
| 311 | desc->setmode(chip,V4L2_TUNER_MODE_LANG1); | ||
| 312 | else if (mode & V4L2_TUNER_MODE_LANG2) | ||
| 313 | desc->setmode(chip,V4L2_TUNER_MODE_LANG2); | ||
| 314 | else | ||
| 315 | desc->setmode(chip,V4L2_TUNER_MODE_MONO); | ||
| 316 | } | ||
| 317 | |||
| 318 | /* ---------------------------------------------------------------------- */ | 341 | /* ---------------------------------------------------------------------- */ |
| 319 | /* audio chip descriptions - defines+functions for tda9840 */ | 342 | /* audio chip descriptions - defines+functions for tda9840 */ |
| 320 | 343 | ||
| @@ -777,7 +800,7 @@ static struct tda9874a_MODES { | |||
| 777 | char *name; | 800 | char *name; |
| 778 | audiocmd cmd; | 801 | audiocmd cmd; |
| 779 | } tda9874a_modelist[9] = { | 802 | } tda9874a_modelist[9] = { |
| 780 | { "A2, B/G", | 803 | { "A2, B/G", /* default */ |
| 781 | { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} }, | 804 | { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} }, |
| 782 | { "A2, M (Korea)", | 805 | { "A2, M (Korea)", |
| 783 | { 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} }, | 806 | { 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} }, |
| @@ -791,7 +814,7 @@ static struct tda9874a_MODES { | |||
| 791 | { 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} }, | 814 | { 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} }, |
| 792 | { "NICAM, B/G", | 815 | { "NICAM, B/G", |
| 793 | { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} }, | 816 | { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} }, |
| 794 | { "NICAM, D/K", /* default */ | 817 | { "NICAM, D/K", |
| 795 | { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} }, | 818 | { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} }, |
| 796 | { "NICAM, L", | 819 | { "NICAM, L", |
| 797 | { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} } | 820 | { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} } |
| @@ -981,7 +1004,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) | |||
| 981 | { | 1004 | { |
| 982 | if (tda9874a_SIF > 2) | 1005 | if (tda9874a_SIF > 2) |
| 983 | tda9874a_SIF = 1; | 1006 | tda9874a_SIF = 1; |
| 984 | if (tda9874a_STD > 8) | 1007 | if (tda9874a_STD >= ARRAY_SIZE(tda9874a_modelist)) |
| 985 | tda9874a_STD = 0; | 1008 | tda9874a_STD = 0; |
| 986 | if(tda9874a_AMSEL > 1) | 1009 | if(tda9874a_AMSEL > 1) |
| 987 | tda9874a_AMSEL = 0; | 1010 | tda9874a_AMSEL = 0; |
| @@ -1089,7 +1112,7 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; } | |||
| 1089 | 1112 | ||
| 1090 | static int tda8425_initialize(struct CHIPSTATE *chip) | 1113 | static int tda8425_initialize(struct CHIPSTATE *chip) |
| 1091 | { | 1114 | { |
| 1092 | struct CHIPDESC *desc = chiplist + chip->type; | 1115 | struct CHIPDESC *desc = chip->desc; |
| 1093 | int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, | 1116 | int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, |
| 1094 | /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF}; | 1117 | /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF}; |
| 1095 | 1118 | ||
| @@ -1259,27 +1282,28 @@ static struct CHIPDESC chiplist[] = { | |||
| 1259 | .addr_lo = I2C_ADDR_TDA9840 >> 1, | 1282 | .addr_lo = I2C_ADDR_TDA9840 >> 1, |
| 1260 | .addr_hi = I2C_ADDR_TDA9840 >> 1, | 1283 | .addr_hi = I2C_ADDR_TDA9840 >> 1, |
| 1261 | .registers = 5, | 1284 | .registers = 5, |
| 1285 | .flags = CHIP_NEED_CHECKMODE, | ||
| 1262 | 1286 | ||
| 1287 | /* callbacks */ | ||
| 1263 | .checkit = tda9840_checkit, | 1288 | .checkit = tda9840_checkit, |
| 1264 | .getmode = tda9840_getmode, | 1289 | .getmode = tda9840_getmode, |
| 1265 | .setmode = tda9840_setmode, | 1290 | .setmode = tda9840_setmode, |
| 1266 | .checkmode = generic_checkmode, | ||
| 1267 | 1291 | ||
| 1268 | .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN | 1292 | .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN |
| 1269 | /* ,TDA9840_SW, TDA9840_MONO */} } | 1293 | /* ,TDA9840_SW, TDA9840_MONO */} } |
| 1270 | }, | 1294 | }, |
| 1271 | { | 1295 | { |
| 1272 | .name = "tda9873h", | 1296 | .name = "tda9873h", |
| 1273 | .checkit = tda9873_checkit, | ||
| 1274 | .insmodopt = &tda9873, | 1297 | .insmodopt = &tda9873, |
| 1275 | .addr_lo = I2C_ADDR_TDA985x_L >> 1, | 1298 | .addr_lo = I2C_ADDR_TDA985x_L >> 1, |
| 1276 | .addr_hi = I2C_ADDR_TDA985x_H >> 1, | 1299 | .addr_hi = I2C_ADDR_TDA985x_H >> 1, |
| 1277 | .registers = 3, | 1300 | .registers = 3, |
| 1278 | .flags = CHIP_HAS_INPUTSEL, | 1301 | .flags = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE, |
| 1279 | 1302 | ||
| 1303 | /* callbacks */ | ||
| 1304 | .checkit = tda9873_checkit, | ||
| 1280 | .getmode = tda9873_getmode, | 1305 | .getmode = tda9873_getmode, |
| 1281 | .setmode = tda9873_setmode, | 1306 | .setmode = tda9873_setmode, |
| 1282 | .checkmode = generic_checkmode, | ||
| 1283 | 1307 | ||
| 1284 | .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, | 1308 | .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, |
| 1285 | .inputreg = TDA9873_SW, | 1309 | .inputreg = TDA9873_SW, |
| @@ -1290,15 +1314,16 @@ static struct CHIPDESC chiplist[] = { | |||
| 1290 | }, | 1314 | }, |
| 1291 | { | 1315 | { |
| 1292 | .name = "tda9874h/a", | 1316 | .name = "tda9874h/a", |
| 1293 | .checkit = tda9874a_checkit, | ||
| 1294 | .initialize = tda9874a_initialize, | ||
| 1295 | .insmodopt = &tda9874a, | 1317 | .insmodopt = &tda9874a, |
| 1296 | .addr_lo = I2C_ADDR_TDA9874 >> 1, | 1318 | .addr_lo = I2C_ADDR_TDA9874 >> 1, |
| 1297 | .addr_hi = I2C_ADDR_TDA9874 >> 1, | 1319 | .addr_hi = I2C_ADDR_TDA9874 >> 1, |
| 1320 | .flags = CHIP_NEED_CHECKMODE, | ||
| 1298 | 1321 | ||
| 1322 | /* callbacks */ | ||
| 1323 | .initialize = tda9874a_initialize, | ||
| 1324 | .checkit = tda9874a_checkit, | ||
| 1299 | .getmode = tda9874a_getmode, | 1325 | .getmode = tda9874a_getmode, |
| 1300 | .setmode = tda9874a_setmode, | 1326 | .setmode = tda9874a_setmode, |
| 1301 | .checkmode = generic_checkmode, | ||
| 1302 | }, | 1327 | }, |
| 1303 | { | 1328 | { |
| 1304 | .name = "tda9850", | 1329 | .name = "tda9850", |
| @@ -1324,10 +1349,11 @@ static struct CHIPDESC chiplist[] = { | |||
| 1324 | .rightreg = TDA9855_VR, | 1349 | .rightreg = TDA9855_VR, |
| 1325 | .bassreg = TDA9855_BA, | 1350 | .bassreg = TDA9855_BA, |
| 1326 | .treblereg = TDA9855_TR, | 1351 | .treblereg = TDA9855_TR, |
| 1352 | |||
| 1353 | /* callbacks */ | ||
| 1327 | .volfunc = tda9855_volume, | 1354 | .volfunc = tda9855_volume, |
| 1328 | .bassfunc = tda9855_bass, | 1355 | .bassfunc = tda9855_bass, |
| 1329 | .treblefunc = tda9855_treble, | 1356 | .treblefunc = tda9855_treble, |
| 1330 | |||
| 1331 | .getmode = tda985x_getmode, | 1357 | .getmode = tda985x_getmode, |
| 1332 | .setmode = tda985x_setmode, | 1358 | .setmode = tda985x_setmode, |
| 1333 | 1359 | ||
| @@ -1348,6 +1374,8 @@ static struct CHIPDESC chiplist[] = { | |||
| 1348 | .rightreg = TEA6300_VL, | 1374 | .rightreg = TEA6300_VL, |
| 1349 | .bassreg = TEA6300_BA, | 1375 | .bassreg = TEA6300_BA, |
| 1350 | .treblereg = TEA6300_TR, | 1376 | .treblereg = TEA6300_TR, |
| 1377 | |||
| 1378 | /* callbacks */ | ||
| 1351 | .volfunc = tea6300_shift10, | 1379 | .volfunc = tea6300_shift10, |
| 1352 | .bassfunc = tea6300_shift12, | 1380 | .bassfunc = tea6300_shift12, |
| 1353 | .treblefunc = tea6300_shift12, | 1381 | .treblefunc = tea6300_shift12, |
| @@ -1358,7 +1386,6 @@ static struct CHIPDESC chiplist[] = { | |||
| 1358 | }, | 1386 | }, |
| 1359 | { | 1387 | { |
| 1360 | .name = "tea6320", | 1388 | .name = "tea6320", |
| 1361 | .initialize = tea6320_initialize, | ||
| 1362 | .insmodopt = &tea6320, | 1389 | .insmodopt = &tea6320, |
| 1363 | .addr_lo = I2C_ADDR_TEA6300 >> 1, | 1390 | .addr_lo = I2C_ADDR_TEA6300 >> 1, |
| 1364 | .addr_hi = I2C_ADDR_TEA6300 >> 1, | 1391 | .addr_hi = I2C_ADDR_TEA6300 >> 1, |
| @@ -1369,6 +1396,9 @@ static struct CHIPDESC chiplist[] = { | |||
| 1369 | .rightreg = TEA6320_V, | 1396 | .rightreg = TEA6320_V, |
| 1370 | .bassreg = TEA6320_BA, | 1397 | .bassreg = TEA6320_BA, |
| 1371 | .treblereg = TEA6320_TR, | 1398 | .treblereg = TEA6320_TR, |
| 1399 | |||
| 1400 | /* callbacks */ | ||
| 1401 | .initialize = tea6320_initialize, | ||
| 1372 | .volfunc = tea6320_volume, | 1402 | .volfunc = tea6320_volume, |
| 1373 | .bassfunc = tea6320_shift11, | 1403 | .bassfunc = tea6320_shift11, |
| 1374 | .treblefunc = tea6320_shift11, | 1404 | .treblefunc = tea6320_shift11, |
| @@ -1401,16 +1431,18 @@ static struct CHIPDESC chiplist[] = { | |||
| 1401 | .rightreg = TDA8425_VR, | 1431 | .rightreg = TDA8425_VR, |
| 1402 | .bassreg = TDA8425_BA, | 1432 | .bassreg = TDA8425_BA, |
| 1403 | .treblereg = TDA8425_TR, | 1433 | .treblereg = TDA8425_TR, |
| 1434 | |||
| 1435 | /* callbacks */ | ||
| 1436 | .initialize = tda8425_initialize, | ||
| 1404 | .volfunc = tda8425_shift10, | 1437 | .volfunc = tda8425_shift10, |
| 1405 | .bassfunc = tda8425_shift12, | 1438 | .bassfunc = tda8425_shift12, |
| 1406 | .treblefunc = tda8425_shift12, | 1439 | .treblefunc = tda8425_shift12, |
| 1440 | .setmode = tda8425_setmode, | ||
| 1407 | 1441 | ||
| 1408 | .inputreg = TDA8425_S1, | 1442 | .inputreg = TDA8425_S1, |
| 1409 | .inputmap = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 }, | 1443 | .inputmap = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 }, |
| 1410 | .inputmute = TDA8425_S1_OFF, | 1444 | .inputmute = TDA8425_S1_OFF, |
| 1411 | 1445 | ||
| 1412 | .setmode = tda8425_setmode, | ||
| 1413 | .initialize = tda8425_initialize, | ||
| 1414 | }, | 1446 | }, |
| 1415 | { | 1447 | { |
| 1416 | .name = "pic16c54 (PV951)", | 1448 | .name = "pic16c54 (PV951)", |
| @@ -1434,10 +1466,11 @@ static struct CHIPDESC chiplist[] = { | |||
| 1434 | .addr_lo = I2C_ADDR_TDA9840 >> 1, | 1466 | .addr_lo = I2C_ADDR_TDA9840 >> 1, |
| 1435 | .addr_hi = I2C_ADDR_TDA9840 >> 1, | 1467 | .addr_hi = I2C_ADDR_TDA9840 >> 1, |
| 1436 | .registers = 2, | 1468 | .registers = 2, |
| 1469 | .flags = CHIP_NEED_CHECKMODE, | ||
| 1437 | 1470 | ||
| 1471 | /* callbacks */ | ||
| 1438 | .getmode = ta8874z_getmode, | 1472 | .getmode = ta8874z_getmode, |
| 1439 | .setmode = ta8874z_setmode, | 1473 | .setmode = ta8874z_setmode, |
| 1440 | .checkmode = generic_checkmode, | ||
| 1441 | 1474 | ||
| 1442 | .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, | 1475 | .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, |
| 1443 | }, | 1476 | }, |
| @@ -1481,6 +1514,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1481 | } | 1514 | } |
| 1482 | if (desc->name == NULL) { | 1515 | if (desc->name == NULL) { |
| 1483 | v4l_dbg(1, debug, client, "no matching chip description found\n"); | 1516 | v4l_dbg(1, debug, client, "no matching chip description found\n"); |
| 1517 | kfree(chip); | ||
| 1484 | return -EIO; | 1518 | return -EIO; |
| 1485 | } | 1519 | } |
| 1486 | v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); | 1520 | v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); |
| @@ -1494,7 +1528,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1494 | /* fill required data structures */ | 1528 | /* fill required data structures */ |
| 1495 | if (!id) | 1529 | if (!id) |
| 1496 | strlcpy(client->name, desc->name, I2C_NAME_SIZE); | 1530 | strlcpy(client->name, desc->name, I2C_NAME_SIZE); |
| 1497 | chip->type = desc-chiplist; | 1531 | chip->desc = desc; |
| 1498 | chip->shadow.count = desc->registers+1; | 1532 | chip->shadow.count = desc->registers+1; |
| 1499 | chip->prevmode = -1; | 1533 | chip->prevmode = -1; |
| 1500 | chip->audmode = V4L2_TUNER_MODE_LANG1; | 1534 | chip->audmode = V4L2_TUNER_MODE_LANG1; |
| @@ -1506,20 +1540,49 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1506 | chip_cmd(chip,"init",&desc->init); | 1540 | chip_cmd(chip,"init",&desc->init); |
| 1507 | 1541 | ||
| 1508 | if (desc->flags & CHIP_HAS_VOLUME) { | 1542 | if (desc->flags & CHIP_HAS_VOLUME) { |
| 1509 | chip->left = desc->leftinit ? desc->leftinit : 65535; | 1543 | if (!desc->volfunc) { |
| 1510 | chip->right = desc->rightinit ? desc->rightinit : 65535; | 1544 | /* This shouldn't be happen. Warn user, but keep working |
| 1511 | chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); | 1545 | without volume controls |
| 1512 | chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); | 1546 | */ |
| 1547 | v4l_info(chip->c, "volume callback undefined!\n"); | ||
| 1548 | desc->flags &= ~CHIP_HAS_VOLUME; | ||
| 1549 | } else { | ||
| 1550 | chip->left = desc->leftinit ? desc->leftinit : 65535; | ||
| 1551 | chip->right = desc->rightinit ? desc->rightinit : 65535; | ||
| 1552 | chip_write(chip, desc->leftreg, | ||
| 1553 | desc->volfunc(chip->left)); | ||
| 1554 | chip_write(chip, desc->rightreg, | ||
| 1555 | desc->volfunc(chip->right)); | ||
| 1556 | } | ||
| 1513 | } | 1557 | } |
| 1514 | if (desc->flags & CHIP_HAS_BASSTREBLE) { | 1558 | if (desc->flags & CHIP_HAS_BASSTREBLE) { |
| 1515 | chip->treble = desc->trebleinit ? desc->trebleinit : 32768; | 1559 | if (!desc->bassfunc || !desc->treblefunc) { |
| 1516 | chip->bass = desc->bassinit ? desc->bassinit : 32768; | 1560 | /* This shouldn't be happen. Warn user, but keep working |
| 1517 | chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); | 1561 | without bass/treble controls |
| 1518 | chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); | 1562 | */ |
| 1563 | v4l_info(chip->c, "bass/treble callbacks undefined!\n"); | ||
| 1564 | desc->flags &= ~CHIP_HAS_BASSTREBLE; | ||
| 1565 | } else { | ||
| 1566 | chip->treble = desc->trebleinit ? | ||
| 1567 | desc->trebleinit : 32768; | ||
| 1568 | chip->bass = desc->bassinit ? | ||
| 1569 | desc->bassinit : 32768; | ||
| 1570 | chip_write(chip, desc->bassreg, | ||
| 1571 | desc->bassfunc(chip->bass)); | ||
| 1572 | chip_write(chip, desc->treblereg, | ||
| 1573 | desc->treblefunc(chip->treble)); | ||
| 1574 | } | ||
| 1519 | } | 1575 | } |
| 1520 | 1576 | ||
| 1521 | chip->thread = NULL; | 1577 | chip->thread = NULL; |
| 1522 | if (desc->checkmode) { | 1578 | if (desc->flags & CHIP_NEED_CHECKMODE) { |
| 1579 | if (!desc->getmode || !desc->setmode) { | ||
| 1580 | /* This shouldn't be happen. Warn user, but keep working | ||
| 1581 | without kthread | ||
| 1582 | */ | ||
| 1583 | v4l_info(chip->c, "set/get mode callbacks undefined!\n"); | ||
| 1584 | return 0; | ||
| 1585 | } | ||
| 1523 | /* start async thread */ | 1586 | /* start async thread */ |
| 1524 | init_timer(&chip->wt); | 1587 | init_timer(&chip->wt); |
| 1525 | chip->wt.function = chip_thread_wake; | 1588 | chip->wt.function = chip_thread_wake; |
| @@ -1552,7 +1615,7 @@ static int chip_remove(struct i2c_client *client) | |||
| 1552 | static int tvaudio_get_ctrl(struct CHIPSTATE *chip, | 1615 | static int tvaudio_get_ctrl(struct CHIPSTATE *chip, |
| 1553 | struct v4l2_control *ctrl) | 1616 | struct v4l2_control *ctrl) |
| 1554 | { | 1617 | { |
| 1555 | struct CHIPDESC *desc = chiplist + chip->type; | 1618 | struct CHIPDESC *desc = chip->desc; |
| 1556 | 1619 | ||
| 1557 | switch (ctrl->id) { | 1620 | switch (ctrl->id) { |
| 1558 | case V4L2_CID_AUDIO_MUTE: | 1621 | case V4L2_CID_AUDIO_MUTE: |
| @@ -1576,13 +1639,13 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, | |||
| 1576 | return 0; | 1639 | return 0; |
| 1577 | } | 1640 | } |
| 1578 | case V4L2_CID_AUDIO_BASS: | 1641 | case V4L2_CID_AUDIO_BASS: |
| 1579 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1642 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1580 | break; | 1643 | break; |
| 1581 | ctrl->value = chip->bass; | 1644 | ctrl->value = chip->bass; |
| 1582 | return 0; | 1645 | return 0; |
| 1583 | case V4L2_CID_AUDIO_TREBLE: | 1646 | case V4L2_CID_AUDIO_TREBLE: |
| 1584 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1647 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1585 | return -EINVAL; | 1648 | break; |
| 1586 | ctrl->value = chip->treble; | 1649 | ctrl->value = chip->treble; |
| 1587 | return 0; | 1650 | return 0; |
| 1588 | } | 1651 | } |
| @@ -1592,7 +1655,7 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, | |||
| 1592 | static int tvaudio_set_ctrl(struct CHIPSTATE *chip, | 1655 | static int tvaudio_set_ctrl(struct CHIPSTATE *chip, |
| 1593 | struct v4l2_control *ctrl) | 1656 | struct v4l2_control *ctrl) |
| 1594 | { | 1657 | { |
| 1595 | struct CHIPDESC *desc = chiplist + chip->type; | 1658 | struct CHIPDESC *desc = chip->desc; |
| 1596 | 1659 | ||
| 1597 | switch (ctrl->id) { | 1660 | switch (ctrl->id) { |
| 1598 | case V4L2_CID_AUDIO_MUTE: | 1661 | case V4L2_CID_AUDIO_MUTE: |
| @@ -1642,16 +1705,15 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip, | |||
| 1642 | return 0; | 1705 | return 0; |
| 1643 | } | 1706 | } |
| 1644 | case V4L2_CID_AUDIO_BASS: | 1707 | case V4L2_CID_AUDIO_BASS: |
| 1645 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1708 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1646 | break; | 1709 | break; |
| 1647 | chip->bass = ctrl->value; | 1710 | chip->bass = ctrl->value; |
| 1648 | chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); | 1711 | chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); |
| 1649 | 1712 | ||
| 1650 | return 0; | 1713 | return 0; |
| 1651 | case V4L2_CID_AUDIO_TREBLE: | 1714 | case V4L2_CID_AUDIO_TREBLE: |
| 1652 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1715 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1653 | return -EINVAL; | 1716 | break; |
| 1654 | |||
| 1655 | chip->treble = ctrl->value; | 1717 | chip->treble = ctrl->value; |
| 1656 | chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); | 1718 | chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); |
| 1657 | 1719 | ||
| @@ -1668,9 +1730,12 @@ static int chip_command(struct i2c_client *client, | |||
| 1668 | unsigned int cmd, void *arg) | 1730 | unsigned int cmd, void *arg) |
| 1669 | { | 1731 | { |
| 1670 | struct CHIPSTATE *chip = i2c_get_clientdata(client); | 1732 | struct CHIPSTATE *chip = i2c_get_clientdata(client); |
| 1671 | struct CHIPDESC *desc = chiplist + chip->type; | 1733 | struct CHIPDESC *desc = chip->desc; |
| 1672 | 1734 | ||
| 1673 | v4l_dbg(1, debug, chip->c, "%s: chip_command 0x%x\n", chip->c->name, cmd); | 1735 | if (debug > 0) { |
| 1736 | v4l_i2c_print_ioctl(chip->c, cmd); | ||
| 1737 | printk("\n"); | ||
| 1738 | } | ||
| 1674 | 1739 | ||
| 1675 | switch (cmd) { | 1740 | switch (cmd) { |
| 1676 | case AUDC_SET_RADIO: | 1741 | case AUDC_SET_RADIO: |
| @@ -1695,7 +1760,7 @@ static int chip_command(struct i2c_client *client, | |||
| 1695 | break; | 1760 | break; |
| 1696 | case V4L2_CID_AUDIO_BASS: | 1761 | case V4L2_CID_AUDIO_BASS: |
| 1697 | case V4L2_CID_AUDIO_TREBLE: | 1762 | case V4L2_CID_AUDIO_TREBLE: |
| 1698 | if (desc->flags & CHIP_HAS_BASSTREBLE) | 1763 | if (!(desc->flags & CHIP_HAS_BASSTREBLE)) |
| 1699 | return -EINVAL; | 1764 | return -EINVAL; |
| 1700 | break; | 1765 | break; |
| 1701 | default: | 1766 | default: |
| @@ -1792,12 +1857,20 @@ static int chip_command(struct i2c_client *client, | |||
| 1792 | break; | 1857 | break; |
| 1793 | case VIDIOC_S_FREQUENCY: | 1858 | case VIDIOC_S_FREQUENCY: |
| 1794 | chip->mode = 0; /* automatic */ | 1859 | chip->mode = 0; /* automatic */ |
| 1795 | if (desc->checkmode && desc->setmode) { | 1860 | |
| 1861 | /* For chips that provide getmode and setmode, and doesn't | ||
| 1862 | automatically follows the stereo carrier, a kthread is | ||
| 1863 | created to set the audio standard. In this case, when then | ||
| 1864 | the video channel is changed, tvaudio starts on MONO mode. | ||
| 1865 | After waiting for 2 seconds, the kernel thread is called, | ||
| 1866 | to follow whatever audio standard is pointed by the | ||
| 1867 | audio carrier. | ||
| 1868 | */ | ||
| 1869 | if (chip->thread) { | ||
| 1796 | desc->setmode(chip,V4L2_TUNER_MODE_MONO); | 1870 | desc->setmode(chip,V4L2_TUNER_MODE_MONO); |
| 1797 | if (chip->prevmode != V4L2_TUNER_MODE_MONO) | 1871 | if (chip->prevmode != V4L2_TUNER_MODE_MONO) |
| 1798 | chip->prevmode = -1; /* reset previous mode */ | 1872 | chip->prevmode = -1; /* reset previous mode */ |
| 1799 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); | 1873 | mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); |
| 1800 | /* the thread will call checkmode() later */ | ||
| 1801 | } | 1874 | } |
| 1802 | break; | 1875 | break; |
| 1803 | 1876 | ||
| @@ -1836,9 +1909,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { | |||
| 1836 | .legacy_probe = chip_legacy_probe, | 1909 | .legacy_probe = chip_legacy_probe, |
| 1837 | .id_table = chip_id, | 1910 | .id_table = chip_id, |
| 1838 | }; | 1911 | }; |
| 1839 | |||
| 1840 | /* | ||
| 1841 | * Local variables: | ||
| 1842 | * c-basic-offset: 8 | ||
| 1843 | * End: | ||
| 1844 | */ | ||
diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index 28421d386f1e..c710bcd1df48 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c | |||
| @@ -3695,7 +3695,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3695 | unsigned char video_ep = 0; | 3695 | unsigned char video_ep = 0; |
| 3696 | 3696 | ||
| 3697 | if (debug >= 1) | 3697 | if (debug >= 1) |
| 3698 | dev_info(&uvd->dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); | 3698 | dev_info(&dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); |
| 3699 | 3699 | ||
| 3700 | /* We don't handle multi-config cameras */ | 3700 | /* We don't handle multi-config cameras */ |
| 3701 | if (dev->descriptor.bNumConfigurations != 1) | 3701 | if (dev->descriptor.bNumConfigurations != 1) |
| @@ -3746,7 +3746,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3746 | brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ | 3746 | brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ |
| 3747 | break; | 3747 | break; |
| 3748 | } | 3748 | } |
| 3749 | dev_info(&uvd->dev->dev, | 3749 | dev_info(&dev->dev, |
| 3750 | "%s USB camera found (model %d, rev. 0x%04x)\n", | 3750 | "%s USB camera found (model %d, rev. 0x%04x)\n", |
| 3751 | brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); | 3751 | brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); |
| 3752 | } while (0); | 3752 | } while (0); |
| @@ -3754,7 +3754,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3754 | /* Validate found interface: must have one ISO endpoint */ | 3754 | /* Validate found interface: must have one ISO endpoint */ |
| 3755 | nas = intf->num_altsetting; | 3755 | nas = intf->num_altsetting; |
| 3756 | if (debug > 0) | 3756 | if (debug > 0) |
| 3757 | dev_info(&uvd->dev->dev, "Number of alternate settings=%d.\n", | 3757 | dev_info(&dev->dev, "Number of alternate settings=%d.\n", |
| 3758 | nas); | 3758 | nas); |
| 3759 | if (nas < 2) { | 3759 | if (nas < 2) { |
| 3760 | err("Too few alternate settings for this camera!"); | 3760 | err("Too few alternate settings for this camera!"); |
| @@ -3799,7 +3799,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3799 | actInterface = i; | 3799 | actInterface = i; |
| 3800 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); | 3800 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); |
| 3801 | if (debug > 0) | 3801 | if (debug > 0) |
| 3802 | dev_info(&uvd->dev->dev, | 3802 | dev_info(&dev->dev, |
| 3803 | "Active setting=%d. " | 3803 | "Active setting=%d. " |
| 3804 | "maxPS=%d.\n", i, maxPS); | 3804 | "maxPS=%d.\n", i, maxPS); |
| 3805 | } else | 3805 | } else |
| @@ -3840,7 +3840,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3840 | RESTRICT_TO_RANGE(framerate, 0, 5); | 3840 | RESTRICT_TO_RANGE(framerate, 0, 5); |
| 3841 | break; | 3841 | break; |
| 3842 | default: | 3842 | default: |
| 3843 | dev_info(&uvd->dev->dev, "IBM camera: using 320x240\n"); | 3843 | dev_info(&dev->dev, "IBM camera: using 320x240\n"); |
| 3844 | size = SIZE_320x240; | 3844 | size = SIZE_320x240; |
| 3845 | /* No break here */ | 3845 | /* No break here */ |
| 3846 | case SIZE_320x240: | 3846 | case SIZE_320x240: |
| @@ -3869,7 +3869,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3869 | canvasY = 120; | 3869 | canvasY = 120; |
| 3870 | break; | 3870 | break; |
| 3871 | default: | 3871 | default: |
| 3872 | dev_info(&uvd->dev->dev, "IBM NetCamera: using 176x144\n"); | 3872 | dev_info(&dev->dev, "IBM NetCamera: using 176x144\n"); |
| 3873 | size = SIZE_176x144; | 3873 | size = SIZE_176x144; |
| 3874 | /* No break here */ | 3874 | /* No break here */ |
| 3875 | case SIZE_176x144: | 3875 | case SIZE_176x144: |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 9494400e8fd0..fee7304102af 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -227,10 +227,20 @@ config HP_WMI | |||
| 227 | To compile this driver as a module, choose M here: the module will | 227 | To compile this driver as a module, choose M here: the module will |
| 228 | be called hp-wmi. | 228 | be called hp-wmi. |
| 229 | 229 | ||
| 230 | config ICS932S401 | ||
| 231 | tristate "Integrated Circuits ICS932S401" | ||
| 232 | depends on I2C && EXPERIMENTAL | ||
| 233 | help | ||
| 234 | If you say yes here you get support for the Integrated Circuits | ||
| 235 | ICS932S401 clock control chips. | ||
| 236 | |||
| 237 | This driver can also be built as a module. If so, the module | ||
| 238 | will be called ics932s401. | ||
| 239 | |||
| 230 | config MSI_LAPTOP | 240 | config MSI_LAPTOP |
| 231 | tristate "MSI Laptop Extras" | 241 | tristate "MSI Laptop Extras" |
| 232 | depends on X86 | 242 | depends on X86 |
| 233 | depends on ACPI_EC | 243 | depends on ACPI |
| 234 | depends on BACKLIGHT_CLASS_DEVICE | 244 | depends on BACKLIGHT_CLASS_DEVICE |
| 235 | ---help--- | 245 | ---help--- |
| 236 | This is a driver for laptops built by MSI (MICRO-STAR | 246 | This is a driver for laptops built by MSI (MICRO-STAR |
| @@ -260,7 +270,7 @@ config PANASONIC_LAPTOP | |||
| 260 | config COMPAL_LAPTOP | 270 | config COMPAL_LAPTOP |
| 261 | tristate "Compal Laptop Extras" | 271 | tristate "Compal Laptop Extras" |
| 262 | depends on X86 | 272 | depends on X86 |
| 263 | depends on ACPI_EC | 273 | depends on ACPI |
| 264 | depends on BACKLIGHT_CLASS_DEVICE | 274 | depends on BACKLIGHT_CLASS_DEVICE |
| 265 | ---help--- | 275 | ---help--- |
| 266 | This is a driver for laptops built by Compal: | 276 | This is a driver for laptops built by Compal: |
| @@ -488,4 +498,6 @@ config SGI_GRU_DEBUG | |||
| 488 | This option enables addition debugging code for the SGI GRU driver. If | 498 | This option enables addition debugging code for the SGI GRU driver. If |
| 489 | you are unsure, say N. | 499 | you are unsure, say N. |
| 490 | 500 | ||
| 501 | source "drivers/misc/c2port/Kconfig" | ||
| 502 | |||
| 491 | endif # MISC_DEVICES | 503 | endif # MISC_DEVICES |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 909e2468cdc9..817f7f5ab3bd 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
| @@ -14,6 +14,7 @@ obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o | |||
| 14 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o | 14 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o |
| 15 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o | 15 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o |
| 16 | obj-$(CONFIG_HP_WMI) += hp-wmi.o | 16 | obj-$(CONFIG_HP_WMI) += hp-wmi.o |
| 17 | obj-$(CONFIG_ICS932S401) += ics932s401.o | ||
| 17 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o | 18 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o |
| 18 | obj-$(CONFIG_LKDTM) += lkdtm.o | 19 | obj-$(CONFIG_LKDTM) += lkdtm.o |
| 19 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o | 20 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o |
| @@ -31,3 +32,4 @@ obj-$(CONFIG_KGDB_TESTS) += kgdbts.o | |||
| 31 | obj-$(CONFIG_SGI_XP) += sgi-xp/ | 32 | obj-$(CONFIG_SGI_XP) += sgi-xp/ |
| 32 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ | 33 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ |
| 33 | obj-$(CONFIG_HP_ILO) += hpilo.o | 34 | obj-$(CONFIG_HP_ILO) += hpilo.o |
| 35 | obj-$(CONFIG_C2PORT) += c2port/ | ||
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index 0532a2de2ce4..94c9f911824e 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c | |||
| @@ -1297,6 +1297,12 @@ static int __init acer_wmi_init(void) | |||
| 1297 | 1297 | ||
| 1298 | set_quirks(); | 1298 | set_quirks(); |
| 1299 | 1299 | ||
| 1300 | if (!acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { | ||
| 1301 | interface->capability &= ~ACER_CAP_BRIGHTNESS; | ||
| 1302 | printk(ACER_INFO "Brightness must be controlled by " | ||
| 1303 | "generic video driver\n"); | ||
| 1304 | } | ||
| 1305 | |||
| 1300 | if (platform_driver_register(&acer_platform_driver)) { | 1306 | if (platform_driver_register(&acer_platform_driver)) { |
| 1301 | printk(ACER_ERR "Unable to register platform driver.\n"); | 1307 | printk(ACER_ERR "Unable to register platform driver.\n"); |
| 1302 | goto error_platform_register; | 1308 | goto error_platform_register; |
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index a9d5228724a6..8fb8b3591048 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c | |||
| @@ -1208,9 +1208,13 @@ static int __init asus_laptop_init(void) | |||
| 1208 | 1208 | ||
| 1209 | dev = acpi_get_physical_device(hotk->device->handle); | 1209 | dev = acpi_get_physical_device(hotk->device->handle); |
| 1210 | 1210 | ||
| 1211 | result = asus_backlight_init(dev); | 1211 | if (!acpi_video_backlight_support()) { |
| 1212 | if (result) | 1212 | result = asus_backlight_init(dev); |
| 1213 | goto fail_backlight; | 1213 | if (result) |
| 1214 | goto fail_backlight; | ||
| 1215 | } else | ||
| 1216 | printk(ASUS_INFO "Brightness ignored, must be controlled by " | ||
| 1217 | "ACPI video driver\n"); | ||
| 1214 | 1218 | ||
| 1215 | result = asus_led_init(dev); | 1219 | result = asus_led_init(dev); |
| 1216 | if (result) | 1220 | if (result) |
diff --git a/drivers/misc/c2port/Kconfig b/drivers/misc/c2port/Kconfig new file mode 100644 index 000000000000..e46af9a5810d --- /dev/null +++ b/drivers/misc/c2port/Kconfig | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | # | ||
| 2 | # C2 port devices | ||
| 3 | # | ||
| 4 | |||
| 5 | menuconfig C2PORT | ||
| 6 | tristate "Silicon Labs C2 port support (EXPERIMENTAL)" | ||
| 7 | depends on EXPERIMENTAL | ||
| 8 | default no | ||
| 9 | help | ||
| 10 | This option enables support for Silicon Labs C2 port used to | ||
| 11 | program Silicon micro controller chips (and other 8051 compatible). | ||
| 12 | |||
| 13 | If your board have no such micro controllers you don't need this | ||
| 14 | interface at all. | ||
| 15 | |||
| 16 | To compile this driver as a module, choose M here: the module will | ||
| 17 | be called c2port_core. Note that you also need a client module | ||
| 18 | usually called c2port-*. | ||
| 19 | |||
| 20 | If you are not sure, say N here. | ||
| 21 | |||
| 22 | if C2PORT | ||
| 23 | |||
| 24 | config C2PORT_DURAMAR_2150 | ||
| 25 | tristate "C2 port support for Eurotech's Duramar 2150 (EXPERIMENTAL)" | ||
| 26 | depends on X86 && C2PORT | ||
| 27 | default no | ||
| 28 | help | ||
| 29 | This option enables C2 support for the Eurotech's Duramar 2150 | ||
| 30 | on board micro controller. | ||
| 31 | |||
| 32 | To compile this driver as a module, choose M here: the module will | ||
| 33 | be called c2port-duramar2150. | ||
| 34 | |||
| 35 | endif # C2PORT | ||
diff --git a/drivers/misc/c2port/Makefile b/drivers/misc/c2port/Makefile new file mode 100644 index 000000000000..3b2cf43d60f5 --- /dev/null +++ b/drivers/misc/c2port/Makefile | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | obj-$(CONFIG_C2PORT) += core.o | ||
| 2 | |||
| 3 | obj-$(CONFIG_C2PORT_DURAMAR_2150) += c2port-duramar2150.o | ||
diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c new file mode 100644 index 000000000000..338dcc121507 --- /dev/null +++ b/drivers/misc/c2port/c2port-duramar2150.c | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | /* | ||
| 2 | * Silicon Labs C2 port Linux support for Eurotech Duramar 2150 | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Rodolfo Giometti <giometti@linux.it> | ||
| 5 | * Copyright (c) 2008 Eurotech S.p.A. <info@eurotech.it> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License version 2 as published by | ||
| 9 | * the Free Software Foundation | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/errno.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/io.h> | ||
| 18 | #include <linux/c2port.h> | ||
| 19 | |||
| 20 | #define DATA_PORT 0x325 | ||
| 21 | #define DIR_PORT 0x326 | ||
| 22 | #define C2D (1 << 0) | ||
| 23 | #define C2CK (1 << 1) | ||
| 24 | |||
| 25 | static DEFINE_MUTEX(update_lock); | ||
| 26 | |||
| 27 | /* | ||
| 28 | * C2 port operations | ||
| 29 | */ | ||
| 30 | |||
| 31 | static void duramar2150_c2port_access(struct c2port_device *dev, int status) | ||
| 32 | { | ||
| 33 | u8 v; | ||
| 34 | |||
| 35 | mutex_lock(&update_lock); | ||
| 36 | |||
| 37 | v = inb(DIR_PORT); | ||
| 38 | |||
| 39 | /* 0 = input, 1 = output */ | ||
| 40 | if (status) | ||
| 41 | outb(v | (C2D | C2CK), DIR_PORT); | ||
| 42 | else | ||
| 43 | /* When access is "off" is important that both lines are set | ||
| 44 | * as inputs or hi-impedence */ | ||
| 45 | outb(v & ~(C2D | C2CK), DIR_PORT); | ||
| 46 | |||
| 47 | mutex_unlock(&update_lock); | ||
| 48 | } | ||
| 49 | |||
| 50 | static void duramar2150_c2port_c2d_dir(struct c2port_device *dev, int dir) | ||
| 51 | { | ||
| 52 | u8 v; | ||
| 53 | |||
| 54 | mutex_lock(&update_lock); | ||
| 55 | |||
| 56 | v = inb(DIR_PORT); | ||
| 57 | |||
| 58 | if (dir) | ||
| 59 | outb(v & ~C2D, DIR_PORT); | ||
| 60 | else | ||
| 61 | outb(v | C2D, DIR_PORT); | ||
| 62 | |||
| 63 | mutex_unlock(&update_lock); | ||
| 64 | } | ||
| 65 | |||
| 66 | static int duramar2150_c2port_c2d_get(struct c2port_device *dev) | ||
| 67 | { | ||
| 68 | return inb(DATA_PORT) & C2D; | ||
| 69 | } | ||
| 70 | |||
| 71 | static void duramar2150_c2port_c2d_set(struct c2port_device *dev, int status) | ||
| 72 | { | ||
| 73 | u8 v; | ||
| 74 | |||
| 75 | mutex_lock(&update_lock); | ||
| 76 | |||
| 77 | v = inb(DATA_PORT); | ||
| 78 | |||
| 79 | if (status) | ||
| 80 | outb(v | C2D, DATA_PORT); | ||
| 81 | else | ||
| 82 | outb(v & ~C2D, DATA_PORT); | ||
| 83 | |||
| 84 | mutex_unlock(&update_lock); | ||
| 85 | } | ||
| 86 | |||
| 87 | static void duramar2150_c2port_c2ck_set(struct c2port_device *dev, int status) | ||
| 88 | { | ||
| 89 | u8 v; | ||
| 90 | |||
| 91 | mutex_lock(&update_lock); | ||
| 92 | |||
| 93 | v = inb(DATA_PORT); | ||
| 94 | |||
| 95 | if (status) | ||
| 96 | outb(v | C2CK, DATA_PORT); | ||
| 97 | else | ||
| 98 | outb(v & ~C2CK, DATA_PORT); | ||
| 99 | |||
| 100 | mutex_unlock(&update_lock); | ||
| 101 | } | ||
| 102 | |||
| 103 | static struct c2port_ops duramar2150_c2port_ops = { | ||
| 104 | .block_size = 512, /* bytes */ | ||
| 105 | .blocks_num = 30, /* total flash size: 15360 bytes */ | ||
| 106 | |||
| 107 | .access = duramar2150_c2port_access, | ||
| 108 | .c2d_dir = duramar2150_c2port_c2d_dir, | ||
| 109 | .c2d_get = duramar2150_c2port_c2d_get, | ||
| 110 | .c2d_set = duramar2150_c2port_c2d_set, | ||
| 111 | .c2ck_set = duramar2150_c2port_c2ck_set, | ||
| 112 | }; | ||
| 113 | |||
| 114 | static struct c2port_device *duramar2150_c2port_dev; | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Module stuff | ||
| 118 | */ | ||
| 119 | |||
| 120 | static int __init duramar2150_c2port_init(void) | ||
| 121 | { | ||
| 122 | struct resource *res; | ||
| 123 | int ret = 0; | ||
| 124 | |||
| 125 | res = request_region(0x325, 2, "c2port"); | ||
| 126 | if (!res) | ||
| 127 | return -EBUSY; | ||
| 128 | |||
| 129 | duramar2150_c2port_dev = c2port_device_register("uc", | ||
| 130 | &duramar2150_c2port_ops, NULL); | ||
| 131 | if (!duramar2150_c2port_dev) { | ||
| 132 | ret = -ENODEV; | ||
| 133 | goto free_region; | ||
| 134 | } | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | |||
| 138 | free_region: | ||
| 139 | release_region(0x325, 2); | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | static void __exit duramar2150_c2port_exit(void) | ||
| 144 | { | ||
| 145 | /* Setup the GPIOs as input by default (access = 0) */ | ||
| 146 | duramar2150_c2port_access(duramar2150_c2port_dev, 0); | ||
| 147 | |||
| 148 | c2port_device_unregister(duramar2150_c2port_dev); | ||
| 149 | |||
| 150 | release_region(0x325, 2); | ||
| 151 | } | ||
| 152 | |||
| 153 | module_init(duramar2150_c2port_init); | ||
| 154 | module_exit(duramar2150_c2port_exit); | ||
| 155 | |||
| 156 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
| 157 | MODULE_DESCRIPTION("Silicon Labs C2 port Linux support for Duramar 2150"); | ||
| 158 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c new file mode 100644 index 000000000000..0207dd59090d --- /dev/null +++ b/drivers/misc/c2port/core.c | |||
| @@ -0,0 +1,1003 @@ | |||
| 1 | /* | ||
| 2 | * Silicon Labs C2 port core Linux support | ||
| 3 | * | ||
| 4 | * Copyright (c) 2007 Rodolfo Giometti <giometti@linux.it> | ||
| 5 | * Copyright (c) 2007 Eurotech S.p.A. <info@eurotech.it> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License version 2 as published by | ||
| 9 | * the Free Software Foundation | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/ctype.h> | ||
| 19 | #include <linux/delay.h> | ||
| 20 | #include <linux/idr.h> | ||
| 21 | #include <linux/sched.h> | ||
| 22 | |||
| 23 | #include <linux/c2port.h> | ||
| 24 | |||
| 25 | #define DRIVER_NAME "c2port" | ||
| 26 | #define DRIVER_VERSION "0.51.0" | ||
| 27 | |||
| 28 | static DEFINE_SPINLOCK(c2port_idr_lock); | ||
| 29 | static DEFINE_IDR(c2port_idr); | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Local variables | ||
| 33 | */ | ||
| 34 | |||
| 35 | static struct class *c2port_class; | ||
| 36 | |||
| 37 | /* | ||
| 38 | * C2 registers & commands defines | ||
| 39 | */ | ||
| 40 | |||
| 41 | /* C2 registers */ | ||
| 42 | #define C2PORT_DEVICEID 0x00 | ||
| 43 | #define C2PORT_REVID 0x01 | ||
| 44 | #define C2PORT_FPCTL 0x02 | ||
| 45 | #define C2PORT_FPDAT 0xB4 | ||
| 46 | |||
| 47 | /* C2 interface commands */ | ||
| 48 | #define C2PORT_GET_VERSION 0x01 | ||
| 49 | #define C2PORT_DEVICE_ERASE 0x03 | ||
| 50 | #define C2PORT_BLOCK_READ 0x06 | ||
| 51 | #define C2PORT_BLOCK_WRITE 0x07 | ||
| 52 | #define C2PORT_PAGE_ERASE 0x08 | ||
| 53 | |||
| 54 | /* C2 status return codes */ | ||
| 55 | #define C2PORT_INVALID_COMMAND 0x00 | ||
| 56 | #define C2PORT_COMMAND_FAILED 0x02 | ||
| 57 | #define C2PORT_COMMAND_OK 0x0d | ||
| 58 | |||
| 59 | /* | ||
| 60 | * C2 port low level signal managements | ||
| 61 | */ | ||
| 62 | |||
| 63 | static void c2port_reset(struct c2port_device *dev) | ||
| 64 | { | ||
| 65 | struct c2port_ops *ops = dev->ops; | ||
| 66 | |||
| 67 | /* To reset the device we have to keep clock line low for at least | ||
| 68 | * 20us. | ||
| 69 | */ | ||
| 70 | local_irq_disable(); | ||
| 71 | ops->c2ck_set(dev, 0); | ||
| 72 | udelay(25); | ||
| 73 | ops->c2ck_set(dev, 1); | ||
| 74 | local_irq_enable(); | ||
| 75 | |||
| 76 | udelay(1); | ||
| 77 | } | ||
| 78 | |||
| 79 | static void c2port_strobe_ck(struct c2port_device *dev) | ||
| 80 | { | ||
| 81 | struct c2port_ops *ops = dev->ops; | ||
| 82 | |||
| 83 | /* During hi-low-hi transition we disable local IRQs to avoid | ||
| 84 | * interructions since C2 port specification says that it must be | ||
| 85 | * shorter than 5us, otherwise the microcontroller may consider | ||
| 86 | * it as a reset signal! | ||
| 87 | */ | ||
| 88 | local_irq_disable(); | ||
| 89 | ops->c2ck_set(dev, 0); | ||
| 90 | udelay(1); | ||
| 91 | ops->c2ck_set(dev, 1); | ||
| 92 | local_irq_enable(); | ||
| 93 | |||
| 94 | udelay(1); | ||
| 95 | } | ||
| 96 | |||
| 97 | /* | ||
| 98 | * C2 port basic functions | ||
| 99 | */ | ||
| 100 | |||
| 101 | static void c2port_write_ar(struct c2port_device *dev, u8 addr) | ||
| 102 | { | ||
| 103 | struct c2port_ops *ops = dev->ops; | ||
| 104 | int i; | ||
| 105 | |||
| 106 | /* START field */ | ||
| 107 | c2port_strobe_ck(dev); | ||
| 108 | |||
| 109 | /* INS field (11b, LSB first) */ | ||
| 110 | ops->c2d_dir(dev, 0); | ||
| 111 | ops->c2d_set(dev, 1); | ||
| 112 | c2port_strobe_ck(dev); | ||
| 113 | ops->c2d_set(dev, 1); | ||
| 114 | c2port_strobe_ck(dev); | ||
| 115 | |||
| 116 | /* ADDRESS field */ | ||
| 117 | for (i = 0; i < 8; i++) { | ||
| 118 | ops->c2d_set(dev, addr & 0x01); | ||
| 119 | c2port_strobe_ck(dev); | ||
| 120 | |||
| 121 | addr >>= 1; | ||
| 122 | } | ||
| 123 | |||
| 124 | /* STOP field */ | ||
| 125 | ops->c2d_dir(dev, 1); | ||
| 126 | c2port_strobe_ck(dev); | ||
| 127 | } | ||
| 128 | |||
| 129 | static int c2port_read_ar(struct c2port_device *dev, u8 *addr) | ||
| 130 | { | ||
| 131 | struct c2port_ops *ops = dev->ops; | ||
| 132 | int i; | ||
| 133 | |||
| 134 | /* START field */ | ||
| 135 | c2port_strobe_ck(dev); | ||
| 136 | |||
| 137 | /* INS field (10b, LSB first) */ | ||
| 138 | ops->c2d_dir(dev, 0); | ||
| 139 | ops->c2d_set(dev, 0); | ||
| 140 | c2port_strobe_ck(dev); | ||
| 141 | ops->c2d_set(dev, 1); | ||
| 142 | c2port_strobe_ck(dev); | ||
| 143 | |||
| 144 | /* ADDRESS field */ | ||
| 145 | ops->c2d_dir(dev, 1); | ||
| 146 | *addr = 0; | ||
| 147 | for (i = 0; i < 8; i++) { | ||
| 148 | *addr >>= 1; /* shift in 8-bit ADDRESS field LSB first */ | ||
| 149 | |||
| 150 | c2port_strobe_ck(dev); | ||
| 151 | if (ops->c2d_get(dev)) | ||
| 152 | *addr |= 0x80; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* STOP field */ | ||
| 156 | c2port_strobe_ck(dev); | ||
| 157 | |||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int c2port_write_dr(struct c2port_device *dev, u8 data) | ||
| 162 | { | ||
| 163 | struct c2port_ops *ops = dev->ops; | ||
| 164 | int timeout, i; | ||
| 165 | |||
| 166 | /* START field */ | ||
| 167 | c2port_strobe_ck(dev); | ||
| 168 | |||
| 169 | /* INS field (01b, LSB first) */ | ||
| 170 | ops->c2d_dir(dev, 0); | ||
| 171 | ops->c2d_set(dev, 1); | ||
| 172 | c2port_strobe_ck(dev); | ||
| 173 | ops->c2d_set(dev, 0); | ||
| 174 | c2port_strobe_ck(dev); | ||
| 175 | |||
| 176 | /* LENGTH field (00b, LSB first -> 1 byte) */ | ||
| 177 | ops->c2d_set(dev, 0); | ||
| 178 | c2port_strobe_ck(dev); | ||
| 179 | ops->c2d_set(dev, 0); | ||
| 180 | c2port_strobe_ck(dev); | ||
| 181 | |||
| 182 | /* DATA field */ | ||
| 183 | for (i = 0; i < 8; i++) { | ||
| 184 | ops->c2d_set(dev, data & 0x01); | ||
| 185 | c2port_strobe_ck(dev); | ||
| 186 | |||
| 187 | data >>= 1; | ||
| 188 | } | ||
| 189 | |||
| 190 | /* WAIT field */ | ||
| 191 | ops->c2d_dir(dev, 1); | ||
| 192 | timeout = 20; | ||
| 193 | do { | ||
| 194 | c2port_strobe_ck(dev); | ||
| 195 | if (ops->c2d_get(dev)) | ||
| 196 | break; | ||
| 197 | |||
| 198 | udelay(1); | ||
| 199 | } while (--timeout > 0); | ||
| 200 | if (timeout == 0) | ||
| 201 | return -EIO; | ||
| 202 | |||
| 203 | /* STOP field */ | ||
| 204 | c2port_strobe_ck(dev); | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int c2port_read_dr(struct c2port_device *dev, u8 *data) | ||
| 210 | { | ||
| 211 | struct c2port_ops *ops = dev->ops; | ||
| 212 | int timeout, i; | ||
| 213 | |||
| 214 | /* START field */ | ||
| 215 | c2port_strobe_ck(dev); | ||
| 216 | |||
| 217 | /* INS field (00b, LSB first) */ | ||
| 218 | ops->c2d_dir(dev, 0); | ||
| 219 | ops->c2d_set(dev, 0); | ||
| 220 | c2port_strobe_ck(dev); | ||
| 221 | ops->c2d_set(dev, 0); | ||
| 222 | c2port_strobe_ck(dev); | ||
| 223 | |||
| 224 | /* LENGTH field (00b, LSB first -> 1 byte) */ | ||
| 225 | ops->c2d_set(dev, 0); | ||
| 226 | c2port_strobe_ck(dev); | ||
| 227 | ops->c2d_set(dev, 0); | ||
| 228 | c2port_strobe_ck(dev); | ||
| 229 | |||
| 230 | /* WAIT field */ | ||
| 231 | ops->c2d_dir(dev, 1); | ||
| 232 | timeout = 20; | ||
| 233 | do { | ||
| 234 | c2port_strobe_ck(dev); | ||
| 235 | if (ops->c2d_get(dev)) | ||
| 236 | break; | ||
| 237 | |||
| 238 | udelay(1); | ||
| 239 | } while (--timeout > 0); | ||
| 240 | if (timeout == 0) | ||
| 241 | return -EIO; | ||
| 242 | |||
| 243 | /* DATA field */ | ||
| 244 | *data = 0; | ||
| 245 | for (i = 0; i < 8; i++) { | ||
| 246 | *data >>= 1; /* shift in 8-bit DATA field LSB first */ | ||
| 247 | |||
| 248 | c2port_strobe_ck(dev); | ||
| 249 | if (ops->c2d_get(dev)) | ||
| 250 | *data |= 0x80; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* STOP field */ | ||
| 254 | c2port_strobe_ck(dev); | ||
| 255 | |||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | static int c2port_poll_in_busy(struct c2port_device *dev) | ||
| 260 | { | ||
| 261 | u8 addr; | ||
| 262 | int ret, timeout = 20; | ||
| 263 | |||
| 264 | do { | ||
| 265 | ret = (c2port_read_ar(dev, &addr)); | ||
| 266 | if (ret < 0) | ||
| 267 | return -EIO; | ||
| 268 | |||
| 269 | if (!(addr & 0x02)) | ||
| 270 | break; | ||
| 271 | |||
| 272 | udelay(1); | ||
| 273 | } while (--timeout > 0); | ||
| 274 | if (timeout == 0) | ||
| 275 | return -EIO; | ||
| 276 | |||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | static int c2port_poll_out_ready(struct c2port_device *dev) | ||
| 281 | { | ||
| 282 | u8 addr; | ||
| 283 | int ret, timeout = 10000; /* erase flash needs long time... */ | ||
| 284 | |||
| 285 | do { | ||
| 286 | ret = (c2port_read_ar(dev, &addr)); | ||
| 287 | if (ret < 0) | ||
| 288 | return -EIO; | ||
| 289 | |||
| 290 | if (addr & 0x01) | ||
| 291 | break; | ||
| 292 | |||
| 293 | udelay(1); | ||
| 294 | } while (--timeout > 0); | ||
| 295 | if (timeout == 0) | ||
| 296 | return -EIO; | ||
| 297 | |||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | /* | ||
| 302 | * sysfs methods | ||
| 303 | */ | ||
| 304 | |||
| 305 | static ssize_t c2port_show_name(struct device *dev, | ||
| 306 | struct device_attribute *attr, char *buf) | ||
| 307 | { | ||
| 308 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 309 | |||
| 310 | return sprintf(buf, "%s\n", c2dev->name); | ||
| 311 | } | ||
| 312 | |||
| 313 | static ssize_t c2port_show_flash_blocks_num(struct device *dev, | ||
| 314 | struct device_attribute *attr, char *buf) | ||
| 315 | { | ||
| 316 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 317 | struct c2port_ops *ops = c2dev->ops; | ||
| 318 | |||
| 319 | return sprintf(buf, "%d\n", ops->blocks_num); | ||
| 320 | } | ||
| 321 | |||
| 322 | static ssize_t c2port_show_flash_block_size(struct device *dev, | ||
| 323 | struct device_attribute *attr, char *buf) | ||
| 324 | { | ||
| 325 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 326 | struct c2port_ops *ops = c2dev->ops; | ||
| 327 | |||
| 328 | return sprintf(buf, "%d\n", ops->block_size); | ||
| 329 | } | ||
| 330 | |||
| 331 | static ssize_t c2port_show_flash_size(struct device *dev, | ||
| 332 | struct device_attribute *attr, char *buf) | ||
| 333 | { | ||
| 334 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 335 | struct c2port_ops *ops = c2dev->ops; | ||
| 336 | |||
| 337 | return sprintf(buf, "%d\n", ops->blocks_num * ops->block_size); | ||
| 338 | } | ||
| 339 | |||
| 340 | static ssize_t c2port_show_access(struct device *dev, | ||
| 341 | struct device_attribute *attr, char *buf) | ||
| 342 | { | ||
| 343 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 344 | |||
| 345 | return sprintf(buf, "%d\n", c2dev->access); | ||
| 346 | } | ||
| 347 | |||
| 348 | static ssize_t c2port_store_access(struct device *dev, | ||
| 349 | struct device_attribute *attr, | ||
| 350 | const char *buf, size_t count) | ||
| 351 | { | ||
| 352 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 353 | struct c2port_ops *ops = c2dev->ops; | ||
| 354 | int status, ret; | ||
| 355 | |||
| 356 | ret = sscanf(buf, "%d", &status); | ||
| 357 | if (ret != 1) | ||
| 358 | return -EINVAL; | ||
| 359 | |||
| 360 | mutex_lock(&c2dev->mutex); | ||
| 361 | |||
| 362 | c2dev->access = !!status; | ||
| 363 | |||
| 364 | /* If access is "on" clock should be HIGH _before_ setting the line | ||
| 365 | * as output and data line should be set as INPUT anyway */ | ||
| 366 | if (c2dev->access) | ||
| 367 | ops->c2ck_set(c2dev, 1); | ||
| 368 | ops->access(c2dev, c2dev->access); | ||
| 369 | if (c2dev->access) | ||
| 370 | ops->c2d_dir(c2dev, 1); | ||
| 371 | |||
| 372 | mutex_unlock(&c2dev->mutex); | ||
| 373 | |||
| 374 | return count; | ||
| 375 | } | ||
| 376 | |||
| 377 | static ssize_t c2port_store_reset(struct device *dev, | ||
| 378 | struct device_attribute *attr, | ||
| 379 | const char *buf, size_t count) | ||
| 380 | { | ||
| 381 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 382 | |||
| 383 | /* Check the device access status */ | ||
| 384 | if (!c2dev->access) | ||
| 385 | return -EBUSY; | ||
| 386 | |||
| 387 | mutex_lock(&c2dev->mutex); | ||
| 388 | |||
| 389 | c2port_reset(c2dev); | ||
| 390 | c2dev->flash_access = 0; | ||
| 391 | |||
| 392 | mutex_unlock(&c2dev->mutex); | ||
| 393 | |||
| 394 | return count; | ||
| 395 | } | ||
| 396 | |||
| 397 | static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf) | ||
| 398 | { | ||
| 399 | u8 data; | ||
| 400 | int ret; | ||
| 401 | |||
| 402 | /* Select DEVICEID register for C2 data register accesses */ | ||
| 403 | c2port_write_ar(dev, C2PORT_DEVICEID); | ||
| 404 | |||
| 405 | /* Read and return the device ID register */ | ||
| 406 | ret = c2port_read_dr(dev, &data); | ||
| 407 | if (ret < 0) | ||
| 408 | return ret; | ||
| 409 | |||
| 410 | return sprintf(buf, "%d\n", data); | ||
| 411 | } | ||
| 412 | |||
| 413 | static ssize_t c2port_show_dev_id(struct device *dev, | ||
| 414 | struct device_attribute *attr, char *buf) | ||
| 415 | { | ||
| 416 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 417 | ssize_t ret; | ||
| 418 | |||
| 419 | /* Check the device access status */ | ||
| 420 | if (!c2dev->access) | ||
| 421 | return -EBUSY; | ||
| 422 | |||
| 423 | mutex_lock(&c2dev->mutex); | ||
| 424 | ret = __c2port_show_dev_id(c2dev, buf); | ||
| 425 | mutex_unlock(&c2dev->mutex); | ||
| 426 | |||
| 427 | if (ret < 0) | ||
| 428 | dev_err(dev, "cannot read from %s\n", c2dev->name); | ||
| 429 | |||
| 430 | return ret; | ||
| 431 | } | ||
| 432 | |||
| 433 | static ssize_t __c2port_show_rev_id(struct c2port_device *dev, char *buf) | ||
| 434 | { | ||
| 435 | u8 data; | ||
| 436 | int ret; | ||
| 437 | |||
| 438 | /* Select REVID register for C2 data register accesses */ | ||
| 439 | c2port_write_ar(dev, C2PORT_REVID); | ||
| 440 | |||
| 441 | /* Read and return the revision ID register */ | ||
| 442 | ret = c2port_read_dr(dev, &data); | ||
| 443 | if (ret < 0) | ||
| 444 | return ret; | ||
| 445 | |||
| 446 | return sprintf(buf, "%d\n", data); | ||
| 447 | } | ||
| 448 | |||
| 449 | static ssize_t c2port_show_rev_id(struct device *dev, | ||
| 450 | struct device_attribute *attr, char *buf) | ||
| 451 | { | ||
| 452 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 453 | ssize_t ret; | ||
| 454 | |||
| 455 | /* Check the device access status */ | ||
| 456 | if (!c2dev->access) | ||
| 457 | return -EBUSY; | ||
| 458 | |||
| 459 | mutex_lock(&c2dev->mutex); | ||
| 460 | ret = __c2port_show_rev_id(c2dev, buf); | ||
| 461 | mutex_unlock(&c2dev->mutex); | ||
| 462 | |||
| 463 | if (ret < 0) | ||
| 464 | dev_err(c2dev->dev, "cannot read from %s\n", c2dev->name); | ||
| 465 | |||
| 466 | return ret; | ||
| 467 | } | ||
| 468 | |||
| 469 | static ssize_t c2port_show_flash_access(struct device *dev, | ||
| 470 | struct device_attribute *attr, char *buf) | ||
| 471 | { | ||
| 472 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 473 | |||
| 474 | return sprintf(buf, "%d\n", c2dev->flash_access); | ||
| 475 | } | ||
| 476 | |||
| 477 | static ssize_t __c2port_store_flash_access(struct c2port_device *dev, | ||
| 478 | int status) | ||
| 479 | { | ||
| 480 | int ret; | ||
| 481 | |||
| 482 | /* Check the device access status */ | ||
| 483 | if (!dev->access) | ||
| 484 | return -EBUSY; | ||
| 485 | |||
| 486 | dev->flash_access = !!status; | ||
| 487 | |||
| 488 | /* If flash_access is off we have nothing to do... */ | ||
| 489 | if (dev->flash_access == 0) | ||
| 490 | return 0; | ||
| 491 | |||
| 492 | /* Target the C2 flash programming control register for C2 data | ||
| 493 | * register access */ | ||
| 494 | c2port_write_ar(dev, C2PORT_FPCTL); | ||
| 495 | |||
| 496 | /* Write the first keycode to enable C2 Flash programming */ | ||
| 497 | ret = c2port_write_dr(dev, 0x02); | ||
| 498 | if (ret < 0) | ||
| 499 | return ret; | ||
| 500 | |||
| 501 | /* Write the second keycode to enable C2 Flash programming */ | ||
| 502 | ret = c2port_write_dr(dev, 0x01); | ||
| 503 | if (ret < 0) | ||
| 504 | return ret; | ||
| 505 | |||
| 506 | /* Delay for at least 20ms to ensure the target is ready for | ||
| 507 | * C2 flash programming */ | ||
| 508 | mdelay(25); | ||
| 509 | |||
| 510 | return 0; | ||
| 511 | } | ||
| 512 | |||
| 513 | static ssize_t c2port_store_flash_access(struct device *dev, | ||
| 514 | struct device_attribute *attr, | ||
| 515 | const char *buf, size_t count) | ||
| 516 | { | ||
| 517 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 518 | int status; | ||
| 519 | ssize_t ret; | ||
| 520 | |||
| 521 | ret = sscanf(buf, "%d", &status); | ||
| 522 | if (ret != 1) | ||
| 523 | return -EINVAL; | ||
| 524 | |||
| 525 | mutex_lock(&c2dev->mutex); | ||
| 526 | ret = __c2port_store_flash_access(c2dev, status); | ||
| 527 | mutex_unlock(&c2dev->mutex); | ||
| 528 | |||
| 529 | if (ret < 0) { | ||
| 530 | dev_err(c2dev->dev, "cannot enable %s flash programming\n", | ||
| 531 | c2dev->name); | ||
| 532 | return ret; | ||
| 533 | } | ||
| 534 | |||
| 535 | return count; | ||
| 536 | } | ||
| 537 | |||
| 538 | static ssize_t __c2port_write_flash_erase(struct c2port_device *dev) | ||
| 539 | { | ||
| 540 | u8 status; | ||
| 541 | int ret; | ||
| 542 | |||
| 543 | /* Target the C2 flash programming data register for C2 data register | ||
| 544 | * access. | ||
| 545 | */ | ||
| 546 | c2port_write_ar(dev, C2PORT_FPDAT); | ||
| 547 | |||
| 548 | /* Send device erase command */ | ||
| 549 | c2port_write_dr(dev, C2PORT_DEVICE_ERASE); | ||
| 550 | |||
| 551 | /* Wait for input acknowledge */ | ||
| 552 | ret = c2port_poll_in_busy(dev); | ||
| 553 | if (ret < 0) | ||
| 554 | return ret; | ||
| 555 | |||
| 556 | /* Should check status before starting FLASH access sequence */ | ||
| 557 | |||
| 558 | /* Wait for status information */ | ||
| 559 | ret = c2port_poll_out_ready(dev); | ||
| 560 | if (ret < 0) | ||
| 561 | return ret; | ||
| 562 | |||
| 563 | /* Read flash programming interface status */ | ||
| 564 | ret = c2port_read_dr(dev, &status); | ||
| 565 | if (ret < 0) | ||
| 566 | return ret; | ||
| 567 | if (status != C2PORT_COMMAND_OK) | ||
| 568 | return -EBUSY; | ||
| 569 | |||
| 570 | /* Send a three-byte arming sequence to enable the device erase. | ||
| 571 | * If the sequence is not received correctly, the command will be | ||
| 572 | * ignored. | ||
| 573 | * Sequence is: 0xde, 0xad, 0xa5. | ||
| 574 | */ | ||
| 575 | c2port_write_dr(dev, 0xde); | ||
| 576 | ret = c2port_poll_in_busy(dev); | ||
| 577 | if (ret < 0) | ||
| 578 | return ret; | ||
| 579 | c2port_write_dr(dev, 0xad); | ||
| 580 | ret = c2port_poll_in_busy(dev); | ||
| 581 | if (ret < 0) | ||
| 582 | return ret; | ||
| 583 | c2port_write_dr(dev, 0xa5); | ||
| 584 | ret = c2port_poll_in_busy(dev); | ||
| 585 | if (ret < 0) | ||
| 586 | return ret; | ||
| 587 | |||
| 588 | ret = c2port_poll_out_ready(dev); | ||
| 589 | if (ret < 0) | ||
| 590 | return ret; | ||
| 591 | |||
| 592 | return 0; | ||
| 593 | } | ||
| 594 | |||
| 595 | static ssize_t c2port_store_flash_erase(struct device *dev, | ||
| 596 | struct device_attribute *attr, | ||
| 597 | const char *buf, size_t count) | ||
| 598 | { | ||
| 599 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
| 600 | int ret; | ||
| 601 | |||
| 602 | /* Check the device and flash access status */ | ||
| 603 | if (!c2dev->access || !c2dev->flash_access) | ||
| 604 | return -EBUSY; | ||
| 605 | |||
| 606 | mutex_lock(&c2dev->mutex); | ||
| 607 | ret = __c2port_write_flash_erase(c2dev); | ||
| 608 | mutex_unlock(&c2dev->mutex); | ||
| 609 | |||
| 610 | if (ret < 0) { | ||
| 611 | dev_err(c2dev->dev, "cannot erase %s flash\n", c2dev->name); | ||
| 612 | return ret; | ||
| 613 | } | ||
| 614 | |||
| 615 | return count; | ||
| 616 | } | ||
| 617 | |||
| 618 | static ssize_t __c2port_read_flash_data(struct c2port_device *dev, | ||
| 619 | char *buffer, loff_t offset, size_t count) | ||
| 620 | { | ||
| 621 | struct c2port_ops *ops = dev->ops; | ||
| 622 | u8 status, nread = 128; | ||
| 623 | int i, ret; | ||
| 624 | |||
| 625 | /* Check for flash end */ | ||
| 626 | if (offset >= ops->block_size * ops->blocks_num) | ||
| 627 | return 0; | ||
| 628 | |||
| 629 | if (ops->block_size * ops->blocks_num - offset < nread) | ||
| 630 | nread = ops->block_size * ops->blocks_num - offset; | ||
| 631 | if (count < nread) | ||
| 632 | nread = count; | ||
| 633 | if (nread == 0) | ||
| 634 | return nread; | ||
| 635 | |||
| 636 | /* Target the C2 flash programming data register for C2 data register | ||
| 637 | * access */ | ||
| 638 | c2port_write_ar(dev, C2PORT_FPDAT); | ||
| 639 | |||
| 640 | /* Send flash block read command */ | ||
| 641 | c2port_write_dr(dev, C2PORT_BLOCK_READ); | ||
| 642 | |||
| 643 | /* Wait for input acknowledge */ | ||
| 644 | ret = c2port_poll_in_busy(dev); | ||
| 645 | if (ret < 0) | ||
| 646 | return ret; | ||
| 647 | |||
| 648 | /* Should check status before starting FLASH access sequence */ | ||
| 649 | |||
| 650 | /* Wait for status information */ | ||
| 651 | ret = c2port_poll_out_ready(dev); | ||
| 652 | if (ret < 0) | ||
| 653 | return ret; | ||
| 654 | |||
| 655 | /* Read flash programming interface status */ | ||
| 656 | ret = c2port_read_dr(dev, &status); | ||
| 657 | if (ret < 0) | ||
| 658 | return ret; | ||
| 659 | if (status != C2PORT_COMMAND_OK) | ||
| 660 | return -EBUSY; | ||
| 661 | |||
| 662 | /* Send address high byte */ | ||
| 663 | c2port_write_dr(dev, offset >> 8); | ||
| 664 | ret = c2port_poll_in_busy(dev); | ||
| 665 | if (ret < 0) | ||
| 666 | return ret; | ||
| 667 | |||
| 668 | /* Send address low byte */ | ||
| 669 | c2port_write_dr(dev, offset & 0x00ff); | ||
| 670 | ret = c2port_poll_in_busy(dev); | ||
| 671 | if (ret < 0) | ||
| 672 | return ret; | ||
| 673 | |||
| 674 | /* Send address block size */ | ||
| 675 | c2port_write_dr(dev, nread); | ||
| 676 | ret = c2port_poll_in_busy(dev); | ||
| 677 | if (ret < 0) | ||
| 678 | return ret; | ||
| 679 | |||
| 680 | /* Should check status before reading FLASH block */ | ||
| 681 | |||
| 682 | /* Wait for status information */ | ||
| 683 | ret = c2port_poll_out_ready(dev); | ||
| 684 | if (ret < 0) | ||
| 685 | return ret; | ||
| 686 | |||
| 687 | /* Read flash programming interface status */ | ||
| 688 | ret = c2port_read_dr(dev, &status); | ||
| 689 | if (ret < 0) | ||
| 690 | return ret; | ||
| 691 | if (status != C2PORT_COMMAND_OK) | ||
| 692 | return -EBUSY; | ||
| 693 | |||
| 694 | /* Read flash block */ | ||
| 695 | for (i = 0; i < nread; i++) { | ||
| 696 | ret = c2port_poll_out_ready(dev); | ||
| 697 | if (ret < 0) | ||
| 698 | return ret; | ||
| 699 | |||
| 700 | ret = c2port_read_dr(dev, buffer+i); | ||
| 701 | if (ret < 0) | ||
| 702 | return ret; | ||
| 703 | } | ||
| 704 | |||
| 705 | return nread; | ||
| 706 | } | ||
| 707 | |||
| 708 | static ssize_t c2port_read_flash_data(struct kobject *kobj, | ||
| 709 | struct bin_attribute *attr, | ||
| 710 | char *buffer, loff_t offset, size_t count) | ||
| 711 | { | ||
| 712 | struct c2port_device *c2dev = | ||
| 713 | dev_get_drvdata(container_of(kobj, | ||
| 714 | struct device, kobj)); | ||
| 715 | ssize_t ret; | ||
| 716 | |||
| 717 | /* Check the device and flash access status */ | ||
| 718 | if (!c2dev->access || !c2dev->flash_access) | ||
| 719 | return -EBUSY; | ||
| 720 | |||
| 721 | mutex_lock(&c2dev->mutex); | ||
| 722 | ret = __c2port_read_flash_data(c2dev, buffer, offset, count); | ||
| 723 | mutex_unlock(&c2dev->mutex); | ||
| 724 | |||
| 725 | if (ret < 0) | ||
| 726 | dev_err(c2dev->dev, "cannot read %s flash\n", c2dev->name); | ||
| 727 | |||
| 728 | return ret; | ||
| 729 | } | ||
| 730 | |||
| 731 | static ssize_t __c2port_write_flash_data(struct c2port_device *dev, | ||
| 732 | char *buffer, loff_t offset, size_t count) | ||
| 733 | { | ||
| 734 | struct c2port_ops *ops = dev->ops; | ||
| 735 | u8 status, nwrite = 128; | ||
| 736 | int i, ret; | ||
| 737 | |||
| 738 | if (nwrite > count) | ||
| 739 | nwrite = count; | ||
| 740 | if (ops->block_size * ops->blocks_num - offset < nwrite) | ||
| 741 | nwrite = ops->block_size * ops->blocks_num - offset; | ||
| 742 | |||
| 743 | /* Check for flash end */ | ||
| 744 | if (offset >= ops->block_size * ops->blocks_num) | ||
| 745 | return -EINVAL; | ||
| 746 | |||
| 747 | /* Target the C2 flash programming data register for C2 data register | ||
| 748 | * access */ | ||
| 749 | c2port_write_ar(dev, C2PORT_FPDAT); | ||
| 750 | |||
| 751 | /* Send flash block write command */ | ||
| 752 | c2port_write_dr(dev, C2PORT_BLOCK_WRITE); | ||
| 753 | |||
| 754 | /* Wait for input acknowledge */ | ||
| 755 | ret = c2port_poll_in_busy(dev); | ||
| 756 | if (ret < 0) | ||
| 757 | return ret; | ||
| 758 | |||
| 759 | /* Should check status before starting FLASH access sequence */ | ||
| 760 | |||
| 761 | /* Wait for status information */ | ||
| 762 | ret = c2port_poll_out_ready(dev); | ||
| 763 | if (ret < 0) | ||
| 764 | return ret; | ||
| 765 | |||
| 766 | /* Read flash programming interface status */ | ||
| 767 | ret = c2port_read_dr(dev, &status); | ||
| 768 | if (ret < 0) | ||
| 769 | return ret; | ||
| 770 | if (status != C2PORT_COMMAND_OK) | ||
| 771 | return -EBUSY; | ||
| 772 | |||
| 773 | /* Send address high byte */ | ||
| 774 | c2port_write_dr(dev, offset >> 8); | ||
| 775 | ret = c2port_poll_in_busy(dev); | ||
| 776 | if (ret < 0) | ||
| 777 | return ret; | ||
| 778 | |||
| 779 | /* Send address low byte */ | ||
| 780 | c2port_write_dr(dev, offset & 0x00ff); | ||
| 781 | ret = c2port_poll_in_busy(dev); | ||
| 782 | if (ret < 0) | ||
| 783 | return ret; | ||
| 784 | |||
| 785 | /* Send address block size */ | ||
| 786 | c2port_write_dr(dev, nwrite); | ||
| 787 | ret = c2port_poll_in_busy(dev); | ||
| 788 | if (ret < 0) | ||
| 789 | return ret; | ||
| 790 | |||
| 791 | /* Should check status before writing FLASH block */ | ||
| 792 | |||
| 793 | /* Wait for status information */ | ||
| 794 | ret = c2port_poll_out_ready(dev); | ||
| 795 | if (ret < 0) | ||
| 796 | return ret; | ||
| 797 | |||
| 798 | /* Read flash programming interface status */ | ||
| 799 | ret = c2port_read_dr(dev, &status); | ||
| 800 | if (ret < 0) | ||
| 801 | return ret; | ||
| 802 | if (status != C2PORT_COMMAND_OK) | ||
| 803 | return -EBUSY; | ||
| 804 | |||
| 805 | /* Write flash block */ | ||
| 806 | for (i = 0; i < nwrite; i++) { | ||
| 807 | ret = c2port_write_dr(dev, *(buffer+i)); | ||
| 808 | if (ret < 0) | ||
| 809 | return ret; | ||
| 810 | |||
| 811 | ret = c2port_poll_in_busy(dev); | ||
| 812 | if (ret < 0) | ||
| 813 | return ret; | ||
| 814 | |||
| 815 | } | ||
| 816 | |||
| 817 | /* Wait for last flash write to complete */ | ||
| 818 | ret = c2port_poll_out_ready(dev); | ||
| 819 | if (ret < 0) | ||
| 820 | return ret; | ||
| 821 | |||
| 822 | return nwrite; | ||
| 823 | } | ||
| 824 | |||
| 825 | static ssize_t c2port_write_flash_data(struct kobject *kobj, | ||
| 826 | struct bin_attribute *attr, | ||
| 827 | char *buffer, loff_t offset, size_t count) | ||
| 828 | { | ||
| 829 | struct c2port_device *c2dev = | ||
| 830 | dev_get_drvdata(container_of(kobj, | ||
| 831 | struct device, kobj)); | ||
| 832 | int ret; | ||
| 833 | |||
| 834 | /* Check the device access status */ | ||
| 835 | if (!c2dev->access || !c2dev->flash_access) | ||
| 836 | return -EBUSY; | ||
| 837 | |||
| 838 | mutex_lock(&c2dev->mutex); | ||
| 839 | ret = __c2port_write_flash_data(c2dev, buffer, offset, count); | ||
| 840 | mutex_unlock(&c2dev->mutex); | ||
| 841 | |||
| 842 | if (ret < 0) | ||
| 843 | dev_err(c2dev->dev, "cannot write %s flash\n", c2dev->name); | ||
| 844 | |||
| 845 | return ret; | ||
| 846 | } | ||
| 847 | |||
| 848 | /* | ||
| 849 | * Class attributes | ||
| 850 | */ | ||
| 851 | |||
| 852 | static struct device_attribute c2port_attrs[] = { | ||
| 853 | __ATTR(name, 0444, c2port_show_name, NULL), | ||
| 854 | __ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL), | ||
| 855 | __ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL), | ||
| 856 | __ATTR(flash_size, 0444, c2port_show_flash_size, NULL), | ||
| 857 | __ATTR(access, 0644, c2port_show_access, c2port_store_access), | ||
| 858 | __ATTR(reset, 0200, NULL, c2port_store_reset), | ||
| 859 | __ATTR(dev_id, 0444, c2port_show_dev_id, NULL), | ||
| 860 | __ATTR(rev_id, 0444, c2port_show_rev_id, NULL), | ||
| 861 | |||
| 862 | __ATTR(flash_access, 0644, c2port_show_flash_access, | ||
| 863 | c2port_store_flash_access), | ||
| 864 | __ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase), | ||
| 865 | __ATTR_NULL, | ||
| 866 | }; | ||
| 867 | |||
| 868 | static struct bin_attribute c2port_bin_attrs = { | ||
| 869 | .attr = { | ||
| 870 | .name = "flash_data", | ||
| 871 | .mode = 0644 | ||
| 872 | }, | ||
| 873 | .read = c2port_read_flash_data, | ||
| 874 | .write = c2port_write_flash_data, | ||
| 875 | /* .size is computed at run-time */ | ||
| 876 | }; | ||
| 877 | |||
| 878 | /* | ||
| 879 | * Exported functions | ||
| 880 | */ | ||
| 881 | |||
| 882 | struct c2port_device *c2port_device_register(char *name, | ||
| 883 | struct c2port_ops *ops, void *devdata) | ||
| 884 | { | ||
| 885 | struct c2port_device *c2dev; | ||
| 886 | int id, ret; | ||
| 887 | |||
| 888 | if (unlikely(!ops) || unlikely(!ops->access) || \ | ||
| 889 | unlikely(!ops->c2d_dir) || unlikely(!ops->c2ck_set) || \ | ||
| 890 | unlikely(!ops->c2d_get) || unlikely(!ops->c2d_set)) | ||
| 891 | return ERR_PTR(-EINVAL); | ||
| 892 | |||
| 893 | c2dev = kmalloc(sizeof(struct c2port_device), GFP_KERNEL); | ||
| 894 | if (unlikely(!c2dev)) | ||
| 895 | return ERR_PTR(-ENOMEM); | ||
| 896 | |||
| 897 | ret = idr_pre_get(&c2port_idr, GFP_KERNEL); | ||
| 898 | if (!ret) { | ||
| 899 | ret = -ENOMEM; | ||
| 900 | goto error_idr_get_new; | ||
| 901 | } | ||
| 902 | |||
| 903 | spin_lock_irq(&c2port_idr_lock); | ||
| 904 | ret = idr_get_new(&c2port_idr, c2dev, &id); | ||
| 905 | spin_unlock_irq(&c2port_idr_lock); | ||
| 906 | |||
| 907 | if (ret < 0) | ||
| 908 | goto error_idr_get_new; | ||
| 909 | c2dev->id = id; | ||
| 910 | |||
| 911 | c2dev->dev = device_create(c2port_class, NULL, 0, c2dev, | ||
| 912 | "c2port%d", id); | ||
| 913 | if (unlikely(!c2dev->dev)) { | ||
| 914 | ret = -ENOMEM; | ||
| 915 | goto error_device_create; | ||
| 916 | } | ||
| 917 | dev_set_drvdata(c2dev->dev, c2dev); | ||
| 918 | |||
| 919 | strncpy(c2dev->name, name, C2PORT_NAME_LEN); | ||
| 920 | c2dev->ops = ops; | ||
| 921 | mutex_init(&c2dev->mutex); | ||
| 922 | |||
| 923 | /* Create binary file */ | ||
| 924 | c2port_bin_attrs.size = ops->blocks_num * ops->block_size; | ||
| 925 | ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs); | ||
| 926 | if (unlikely(ret)) | ||
| 927 | goto error_device_create_bin_file; | ||
| 928 | |||
| 929 | /* By default C2 port access is off */ | ||
| 930 | c2dev->access = c2dev->flash_access = 0; | ||
| 931 | ops->access(c2dev, 0); | ||
| 932 | |||
| 933 | dev_info(c2dev->dev, "C2 port %s added\n", name); | ||
| 934 | dev_info(c2dev->dev, "%s flash has %d blocks x %d bytes " | ||
| 935 | "(%d bytes total)\n", | ||
| 936 | name, ops->blocks_num, ops->block_size, | ||
| 937 | ops->blocks_num * ops->block_size); | ||
| 938 | |||
| 939 | return c2dev; | ||
| 940 | |||
| 941 | error_device_create_bin_file: | ||
| 942 | device_destroy(c2port_class, 0); | ||
| 943 | |||
| 944 | error_device_create: | ||
| 945 | spin_lock_irq(&c2port_idr_lock); | ||
| 946 | idr_remove(&c2port_idr, id); | ||
| 947 | spin_unlock_irq(&c2port_idr_lock); | ||
| 948 | |||
| 949 | error_idr_get_new: | ||
| 950 | kfree(c2dev); | ||
| 951 | |||
| 952 | return ERR_PTR(ret); | ||
| 953 | } | ||
| 954 | EXPORT_SYMBOL(c2port_device_register); | ||
| 955 | |||
| 956 | void c2port_device_unregister(struct c2port_device *c2dev) | ||
| 957 | { | ||
| 958 | if (!c2dev) | ||
| 959 | return; | ||
| 960 | |||
| 961 | dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name); | ||
| 962 | |||
| 963 | device_remove_bin_file(c2dev->dev, &c2port_bin_attrs); | ||
| 964 | spin_lock_irq(&c2port_idr_lock); | ||
| 965 | idr_remove(&c2port_idr, c2dev->id); | ||
| 966 | spin_unlock_irq(&c2port_idr_lock); | ||
| 967 | |||
| 968 | device_destroy(c2port_class, c2dev->id); | ||
| 969 | |||
| 970 | kfree(c2dev); | ||
| 971 | } | ||
| 972 | EXPORT_SYMBOL(c2port_device_unregister); | ||
| 973 | |||
| 974 | /* | ||
| 975 | * Module stuff | ||
| 976 | */ | ||
| 977 | |||
| 978 | static int __init c2port_init(void) | ||
| 979 | { | ||
| 980 | printk(KERN_INFO "Silicon Labs C2 port support v. " DRIVER_VERSION | ||
| 981 | " - (C) 2007 Rodolfo Giometti\n"); | ||
| 982 | |||
| 983 | c2port_class = class_create(THIS_MODULE, "c2port"); | ||
| 984 | if (!c2port_class) { | ||
| 985 | printk(KERN_ERR "c2port: failed to allocate class\n"); | ||
| 986 | return -ENOMEM; | ||
| 987 | } | ||
| 988 | c2port_class->dev_attrs = c2port_attrs; | ||
| 989 | |||
| 990 | return 0; | ||
| 991 | } | ||
| 992 | |||
| 993 | static void __exit c2port_exit(void) | ||
| 994 | { | ||
| 995 | class_destroy(c2port_class); | ||
| 996 | } | ||
| 997 | |||
| 998 | module_init(c2port_init); | ||
| 999 | module_exit(c2port_exit); | ||
| 1000 | |||
| 1001 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
| 1002 | MODULE_DESCRIPTION("Silicon Labs C2 port support v. " DRIVER_VERSION); | ||
| 1003 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/misc/compal-laptop.c b/drivers/misc/compal-laptop.c index 344b790a6253..11003bba10d3 100644 --- a/drivers/misc/compal-laptop.c +++ b/drivers/misc/compal-laptop.c | |||
| @@ -326,12 +326,14 @@ static int __init compal_init(void) | |||
| 326 | 326 | ||
| 327 | /* Register backlight stuff */ | 327 | /* Register backlight stuff */ |
| 328 | 328 | ||
| 329 | compalbl_device = backlight_device_register("compal-laptop", NULL, NULL, | 329 | if (!acpi_video_backlight_support()) { |
| 330 | &compalbl_ops); | 330 | compalbl_device = backlight_device_register("compal-laptop", NULL, NULL, |
| 331 | if (IS_ERR(compalbl_device)) | 331 | &compalbl_ops); |
| 332 | return PTR_ERR(compalbl_device); | 332 | if (IS_ERR(compalbl_device)) |
| 333 | return PTR_ERR(compalbl_device); | ||
| 333 | 334 | ||
| 334 | compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1; | 335 | compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1; |
| 336 | } | ||
| 335 | 337 | ||
| 336 | ret = platform_driver_register(&compal_driver); | 338 | ret = platform_driver_register(&compal_driver); |
| 337 | if (ret) | 339 | if (ret) |
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index 9ef98b2d5039..02fe2b8b8939 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c | |||
| @@ -825,9 +825,15 @@ static int __init eeepc_laptop_init(void) | |||
| 825 | return -ENODEV; | 825 | return -ENODEV; |
| 826 | } | 826 | } |
| 827 | dev = acpi_get_physical_device(ehotk->device->handle); | 827 | dev = acpi_get_physical_device(ehotk->device->handle); |
| 828 | result = eeepc_backlight_init(dev); | 828 | |
| 829 | if (result) | 829 | if (!acpi_video_backlight_support()) { |
| 830 | goto fail_backlight; | 830 | result = eeepc_backlight_init(dev); |
| 831 | if (result) | ||
| 832 | goto fail_backlight; | ||
| 833 | } else | ||
| 834 | printk(EEEPC_INFO "Backlight controlled by ACPI video " | ||
| 835 | "driver\n"); | ||
| 836 | |||
| 831 | result = eeepc_hwmon_init(dev); | 837 | result = eeepc_hwmon_init(dev); |
| 832 | if (result) | 838 | if (result) |
| 833 | goto fail_hwmon; | 839 | goto fail_hwmon; |
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index d2cf0bfe3163..a7dd3e9fb79d 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c | |||
| @@ -464,6 +464,14 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) | |||
| 464 | return 0; | 464 | return 0; |
| 465 | } | 465 | } |
| 466 | 466 | ||
| 467 | static int dmi_check_cb_s6420(const struct dmi_system_id *id) | ||
| 468 | { | ||
| 469 | dmi_check_cb_common(id); | ||
| 470 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ | ||
| 471 | fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ | ||
| 472 | return 0; | ||
| 473 | } | ||
| 474 | |||
| 467 | static int dmi_check_cb_p8010(const struct dmi_system_id *id) | 475 | static int dmi_check_cb_p8010(const struct dmi_system_id *id) |
| 468 | { | 476 | { |
| 469 | dmi_check_cb_common(id); | 477 | dmi_check_cb_common(id); |
| @@ -473,7 +481,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id) | |||
| 473 | return 0; | 481 | return 0; |
| 474 | } | 482 | } |
| 475 | 483 | ||
| 476 | static struct dmi_system_id __initdata fujitsu_dmi_table[] = { | 484 | static struct dmi_system_id fujitsu_dmi_table[] = { |
| 477 | { | 485 | { |
| 478 | .ident = "Fujitsu Siemens S6410", | 486 | .ident = "Fujitsu Siemens S6410", |
| 479 | .matches = { | 487 | .matches = { |
| @@ -482,6 +490,13 @@ static struct dmi_system_id __initdata fujitsu_dmi_table[] = { | |||
| 482 | }, | 490 | }, |
| 483 | .callback = dmi_check_cb_s6410}, | 491 | .callback = dmi_check_cb_s6410}, |
| 484 | { | 492 | { |
| 493 | .ident = "Fujitsu Siemens S6420", | ||
| 494 | .matches = { | ||
| 495 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
| 496 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"), | ||
| 497 | }, | ||
| 498 | .callback = dmi_check_cb_s6420}, | ||
| 499 | { | ||
| 485 | .ident = "Fujitsu LifeBook P8010", | 500 | .ident = "Fujitsu LifeBook P8010", |
| 486 | .matches = { | 501 | .matches = { |
| 487 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 502 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| @@ -990,16 +1005,16 @@ static int __init fujitsu_init(void) | |||
| 990 | 1005 | ||
| 991 | /* Register backlight stuff */ | 1006 | /* Register backlight stuff */ |
| 992 | 1007 | ||
| 993 | fujitsu->bl_device = | 1008 | if (!acpi_video_backlight_support()) { |
| 994 | backlight_device_register("fujitsu-laptop", NULL, NULL, | 1009 | fujitsu->bl_device = |
| 995 | &fujitsubl_ops); | 1010 | backlight_device_register("fujitsu-laptop", NULL, NULL, |
| 996 | if (IS_ERR(fujitsu->bl_device)) | 1011 | &fujitsubl_ops); |
| 997 | return PTR_ERR(fujitsu->bl_device); | 1012 | if (IS_ERR(fujitsu->bl_device)) |
| 998 | 1013 | return PTR_ERR(fujitsu->bl_device); | |
| 999 | max_brightness = fujitsu->max_brightness; | 1014 | max_brightness = fujitsu->max_brightness; |
| 1000 | 1015 | fujitsu->bl_device->props.max_brightness = max_brightness - 1; | |
| 1001 | fujitsu->bl_device->props.max_brightness = max_brightness - 1; | 1016 | fujitsu->bl_device->props.brightness = fujitsu->brightness_level; |
| 1002 | fujitsu->bl_device->props.brightness = fujitsu->brightness_level; | 1017 | } |
| 1003 | 1018 | ||
| 1004 | ret = platform_driver_register(&fujitsupf_driver); | 1019 | ret = platform_driver_register(&fujitsupf_driver); |
| 1005 | if (ret) | 1020 | if (ret) |
| @@ -1035,7 +1050,8 @@ fail_hotkey: | |||
| 1035 | 1050 | ||
| 1036 | fail_backlight: | 1051 | fail_backlight: |
| 1037 | 1052 | ||
| 1038 | backlight_device_unregister(fujitsu->bl_device); | 1053 | if (fujitsu->bl_device) |
| 1054 | backlight_device_unregister(fujitsu->bl_device); | ||
| 1039 | 1055 | ||
| 1040 | fail_platform_device2: | 1056 | fail_platform_device2: |
| 1041 | 1057 | ||
| @@ -1062,7 +1078,8 @@ static void __exit fujitsu_cleanup(void) | |||
| 1062 | &fujitsupf_attribute_group); | 1078 | &fujitsupf_attribute_group); |
| 1063 | platform_device_unregister(fujitsu->pf_device); | 1079 | platform_device_unregister(fujitsu->pf_device); |
| 1064 | platform_driver_unregister(&fujitsupf_driver); | 1080 | platform_driver_unregister(&fujitsupf_driver); |
| 1065 | backlight_device_unregister(fujitsu->bl_device); | 1081 | if (fujitsu->bl_device) |
| 1082 | backlight_device_unregister(fujitsu->bl_device); | ||
| 1066 | 1083 | ||
| 1067 | acpi_bus_unregister_driver(&acpi_fujitsu_driver); | 1084 | acpi_bus_unregister_driver(&acpi_fujitsu_driver); |
| 1068 | 1085 | ||
diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c new file mode 100644 index 000000000000..6e43ab4231ae --- /dev/null +++ b/drivers/misc/ics932s401.c | |||
| @@ -0,0 +1,515 @@ | |||
| 1 | /* | ||
| 2 | * A driver for the Integrated Circuits ICS932S401 | ||
| 3 | * Copyright (C) 2008 IBM | ||
| 4 | * | ||
| 5 | * Author: Darrick J. Wong <djwong@us.ibm.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/jiffies.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/err.h> | ||
| 26 | #include <linux/mutex.h> | ||
| 27 | #include <linux/delay.h> | ||
| 28 | #include <linux/log2.h> | ||
| 29 | |||
| 30 | /* Addresses to scan */ | ||
| 31 | static const unsigned short normal_i2c[] = { 0x69, I2C_CLIENT_END }; | ||
| 32 | |||
| 33 | /* Insmod parameters */ | ||
| 34 | I2C_CLIENT_INSMOD_1(ics932s401); | ||
| 35 | |||
| 36 | /* ICS932S401 registers */ | ||
| 37 | #define ICS932S401_REG_CFG2 0x01 | ||
| 38 | #define ICS932S401_CFG1_SPREAD 0x01 | ||
| 39 | #define ICS932S401_REG_CFG7 0x06 | ||
| 40 | #define ICS932S401_FS_MASK 0x07 | ||
| 41 | #define ICS932S401_REG_VENDOR_REV 0x07 | ||
| 42 | #define ICS932S401_VENDOR 1 | ||
| 43 | #define ICS932S401_VENDOR_MASK 0x0F | ||
| 44 | #define ICS932S401_REV 4 | ||
| 45 | #define ICS932S401_REV_SHIFT 4 | ||
| 46 | #define ICS932S401_REG_DEVICE 0x09 | ||
| 47 | #define ICS932S401_DEVICE 11 | ||
| 48 | #define ICS932S401_REG_CTRL 0x0A | ||
| 49 | #define ICS932S401_MN_ENABLED 0x80 | ||
| 50 | #define ICS932S401_CPU_ALT 0x04 | ||
| 51 | #define ICS932S401_SRC_ALT 0x08 | ||
| 52 | #define ICS932S401_REG_CPU_M_CTRL 0x0B | ||
| 53 | #define ICS932S401_M_MASK 0x3F | ||
| 54 | #define ICS932S401_REG_CPU_N_CTRL 0x0C | ||
| 55 | #define ICS932S401_REG_CPU_SPREAD1 0x0D | ||
| 56 | #define ICS932S401_REG_CPU_SPREAD2 0x0E | ||
| 57 | #define ICS932S401_SPREAD_MASK 0x7FFF | ||
| 58 | #define ICS932S401_REG_SRC_M_CTRL 0x0F | ||
| 59 | #define ICS932S401_REG_SRC_N_CTRL 0x10 | ||
| 60 | #define ICS932S401_REG_SRC_SPREAD1 0x11 | ||
| 61 | #define ICS932S401_REG_SRC_SPREAD2 0x12 | ||
| 62 | #define ICS932S401_REG_CPU_DIVISOR 0x13 | ||
| 63 | #define ICS932S401_CPU_DIVISOR_SHIFT 4 | ||
| 64 | #define ICS932S401_REG_PCISRC_DIVISOR 0x14 | ||
| 65 | #define ICS932S401_SRC_DIVISOR_MASK 0x0F | ||
| 66 | #define ICS932S401_PCI_DIVISOR_SHIFT 4 | ||
| 67 | |||
| 68 | /* Base clock is 14.318MHz */ | ||
| 69 | #define BASE_CLOCK 14318 | ||
| 70 | |||
| 71 | #define NUM_REGS 21 | ||
| 72 | #define NUM_MIRRORED_REGS 15 | ||
| 73 | |||
| 74 | static int regs_to_copy[NUM_MIRRORED_REGS] = { | ||
| 75 | ICS932S401_REG_CFG2, | ||
| 76 | ICS932S401_REG_CFG7, | ||
| 77 | ICS932S401_REG_VENDOR_REV, | ||
| 78 | ICS932S401_REG_DEVICE, | ||
| 79 | ICS932S401_REG_CTRL, | ||
| 80 | ICS932S401_REG_CPU_M_CTRL, | ||
| 81 | ICS932S401_REG_CPU_N_CTRL, | ||
| 82 | ICS932S401_REG_CPU_SPREAD1, | ||
| 83 | ICS932S401_REG_CPU_SPREAD2, | ||
| 84 | ICS932S401_REG_SRC_M_CTRL, | ||
| 85 | ICS932S401_REG_SRC_N_CTRL, | ||
| 86 | ICS932S401_REG_SRC_SPREAD1, | ||
| 87 | ICS932S401_REG_SRC_SPREAD2, | ||
| 88 | ICS932S401_REG_CPU_DIVISOR, | ||
| 89 | ICS932S401_REG_PCISRC_DIVISOR, | ||
| 90 | }; | ||
| 91 | |||
| 92 | /* How often do we reread sensors values? (In jiffies) */ | ||
| 93 | #define SENSOR_REFRESH_INTERVAL (2 * HZ) | ||
| 94 | |||
| 95 | /* How often do we reread sensor limit values? (In jiffies) */ | ||
| 96 | #define LIMIT_REFRESH_INTERVAL (60 * HZ) | ||
| 97 | |||
| 98 | struct ics932s401_data { | ||
| 99 | struct attribute_group attrs; | ||
| 100 | struct mutex lock; | ||
| 101 | char sensors_valid; | ||
| 102 | unsigned long sensors_last_updated; /* In jiffies */ | ||
| 103 | |||
| 104 | u8 regs[NUM_REGS]; | ||
| 105 | }; | ||
| 106 | |||
| 107 | static int ics932s401_probe(struct i2c_client *client, | ||
| 108 | const struct i2c_device_id *id); | ||
| 109 | static int ics932s401_detect(struct i2c_client *client, int kind, | ||
| 110 | struct i2c_board_info *info); | ||
| 111 | static int ics932s401_remove(struct i2c_client *client); | ||
| 112 | |||
| 113 | static const struct i2c_device_id ics932s401_id[] = { | ||
| 114 | { "ics932s401", ics932s401 }, | ||
| 115 | { } | ||
| 116 | }; | ||
| 117 | MODULE_DEVICE_TABLE(i2c, ics932s401_id); | ||
| 118 | |||
| 119 | static struct i2c_driver ics932s401_driver = { | ||
| 120 | .class = I2C_CLASS_HWMON, | ||
| 121 | .driver = { | ||
| 122 | .name = "ics932s401", | ||
| 123 | }, | ||
| 124 | .probe = ics932s401_probe, | ||
| 125 | .remove = ics932s401_remove, | ||
| 126 | .id_table = ics932s401_id, | ||
| 127 | .detect = ics932s401_detect, | ||
| 128 | .address_data = &addr_data, | ||
| 129 | }; | ||
| 130 | |||
| 131 | static struct ics932s401_data *ics932s401_update_device(struct device *dev) | ||
| 132 | { | ||
| 133 | struct i2c_client *client = to_i2c_client(dev); | ||
| 134 | struct ics932s401_data *data = i2c_get_clientdata(client); | ||
| 135 | unsigned long local_jiffies = jiffies; | ||
| 136 | int i, temp; | ||
| 137 | |||
| 138 | mutex_lock(&data->lock); | ||
| 139 | if (time_before(local_jiffies, data->sensors_last_updated + | ||
| 140 | SENSOR_REFRESH_INTERVAL) | ||
| 141 | && data->sensors_valid) | ||
| 142 | goto out; | ||
| 143 | |||
| 144 | /* | ||
| 145 | * Each register must be read as a word and then right shifted 8 bits. | ||
| 146 | * Not really sure why this is; setting the "byte count programming" | ||
| 147 | * register to 1 does not fix this problem. | ||
| 148 | */ | ||
| 149 | for (i = 0; i < NUM_MIRRORED_REGS; i++) { | ||
| 150 | temp = i2c_smbus_read_word_data(client, regs_to_copy[i]); | ||
| 151 | data->regs[regs_to_copy[i]] = temp >> 8; | ||
| 152 | } | ||
| 153 | |||
| 154 | data->sensors_last_updated = local_jiffies; | ||
| 155 | data->sensors_valid = 1; | ||
| 156 | |||
| 157 | out: | ||
| 158 | mutex_unlock(&data->lock); | ||
| 159 | return data; | ||
| 160 | } | ||
| 161 | |||
| 162 | static ssize_t show_spread_enabled(struct device *dev, | ||
| 163 | struct device_attribute *devattr, | ||
| 164 | char *buf) | ||
| 165 | { | ||
| 166 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
| 167 | |||
| 168 | if (data->regs[ICS932S401_REG_CFG2] & ICS932S401_CFG1_SPREAD) | ||
| 169 | return sprintf(buf, "1\n"); | ||
| 170 | |||
| 171 | return sprintf(buf, "0\n"); | ||
| 172 | } | ||
| 173 | |||
| 174 | /* bit to cpu khz map */ | ||
| 175 | static const int fs_speeds[] = { | ||
| 176 | 266666, | ||
| 177 | 133333, | ||
| 178 | 200000, | ||
| 179 | 166666, | ||
| 180 | 333333, | ||
| 181 | 100000, | ||
| 182 | 400000, | ||
| 183 | 0, | ||
| 184 | }; | ||
| 185 | |||
| 186 | /* clock divisor map */ | ||
| 187 | static const int divisors[] = {2, 3, 5, 15, 4, 6, 10, 30, 8, 12, 20, 60, 16, | ||
| 188 | 24, 40, 120}; | ||
| 189 | |||
| 190 | /* Calculate CPU frequency from the M/N registers. */ | ||
| 191 | static int calculate_cpu_freq(struct ics932s401_data *data) | ||
| 192 | { | ||
| 193 | int m, n, freq; | ||
| 194 | |||
| 195 | m = data->regs[ICS932S401_REG_CPU_M_CTRL] & ICS932S401_M_MASK; | ||
| 196 | n = data->regs[ICS932S401_REG_CPU_N_CTRL]; | ||
| 197 | |||
| 198 | /* Pull in bits 8 & 9 from the M register */ | ||
| 199 | n |= ((int)data->regs[ICS932S401_REG_CPU_M_CTRL] & 0x80) << 1; | ||
| 200 | n |= ((int)data->regs[ICS932S401_REG_CPU_M_CTRL] & 0x40) << 3; | ||
| 201 | |||
| 202 | freq = BASE_CLOCK * (n + 8) / (m + 2); | ||
| 203 | freq /= divisors[data->regs[ICS932S401_REG_CPU_DIVISOR] >> | ||
| 204 | ICS932S401_CPU_DIVISOR_SHIFT]; | ||
| 205 | |||
| 206 | return freq; | ||
| 207 | } | ||
| 208 | |||
| 209 | static ssize_t show_cpu_clock(struct device *dev, | ||
| 210 | struct device_attribute *devattr, | ||
| 211 | char *buf) | ||
| 212 | { | ||
| 213 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
| 214 | |||
| 215 | return sprintf(buf, "%d\n", calculate_cpu_freq(data)); | ||
| 216 | } | ||
| 217 | |||
| 218 | static ssize_t show_cpu_clock_sel(struct device *dev, | ||
| 219 | struct device_attribute *devattr, | ||
| 220 | char *buf) | ||
| 221 | { | ||
| 222 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
| 223 | int freq; | ||
| 224 | |||
| 225 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED) | ||
| 226 | freq = calculate_cpu_freq(data); | ||
| 227 | else { | ||
| 228 | /* Freq is neatly wrapped up for us */ | ||
| 229 | int fid = data->regs[ICS932S401_REG_CFG7] & ICS932S401_FS_MASK; | ||
| 230 | freq = fs_speeds[fid]; | ||
| 231 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_CPU_ALT) { | ||
| 232 | switch (freq) { | ||
| 233 | case 166666: | ||
| 234 | freq = 160000; | ||
| 235 | break; | ||
| 236 | case 333333: | ||
| 237 | freq = 320000; | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | return sprintf(buf, "%d\n", freq); | ||
| 244 | } | ||
| 245 | |||
| 246 | /* Calculate SRC frequency from the M/N registers. */ | ||
| 247 | static int calculate_src_freq(struct ics932s401_data *data) | ||
| 248 | { | ||
| 249 | int m, n, freq; | ||
| 250 | |||
| 251 | m = data->regs[ICS932S401_REG_SRC_M_CTRL] & ICS932S401_M_MASK; | ||
| 252 | n = data->regs[ICS932S401_REG_SRC_N_CTRL]; | ||
| 253 | |||
| 254 | /* Pull in bits 8 & 9 from the M register */ | ||
| 255 | n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x80) << 1; | ||
| 256 | n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x40) << 3; | ||
| 257 | |||
| 258 | freq = BASE_CLOCK * (n + 8) / (m + 2); | ||
| 259 | freq /= divisors[data->regs[ICS932S401_REG_PCISRC_DIVISOR] & | ||
| 260 | ICS932S401_SRC_DIVISOR_MASK]; | ||
| 261 | |||
| 262 | return freq; | ||
| 263 | } | ||
| 264 | |||
| 265 | static ssize_t show_src_clock(struct device *dev, | ||
| 266 | struct device_attribute *devattr, | ||
| 267 | char *buf) | ||
| 268 | { | ||
| 269 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
| 270 | |||
| 271 | return sprintf(buf, "%d\n", calculate_src_freq(data)); | ||
| 272 | } | ||
| 273 | |||
| 274 | static ssize_t show_src_clock_sel(struct device *dev, | ||
| 275 | struct device_attribute *devattr, | ||
| 276 | char *buf) | ||
| 277 | { | ||
| 278 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
| 279 | int freq; | ||
| 280 | |||
| 281 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED) | ||
| 282 | freq = calculate_src_freq(data); | ||
| 283 | else | ||
| 284 | /* Freq is neatly wrapped up for us */ | ||
| 285 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_CPU_ALT && | ||
| 286 | data->regs[ICS932S401_REG_CTRL] & ICS932S401_SRC_ALT) | ||
| 287 | freq = 96000; | ||
| 288 | else | ||
| 289 | freq = 100000; | ||
| 290 | |||
| 291 | return sprintf(buf, "%d\n", freq); | ||
| 292 | } | ||
| 293 | |||
| 294 | /* Calculate PCI frequency from the SRC M/N registers. */ | ||
| 295 | static int calculate_pci_freq(struct ics932s401_data *data) | ||
| 296 | { | ||
| 297 | int m, n, freq; | ||
| 298 | |||
| 299 | m = data->regs[ICS932S401_REG_SRC_M_CTRL] & ICS932S401_M_MASK; | ||
| 300 | n = data->regs[ICS932S401_REG_SRC_N_CTRL]; | ||
| 301 | |||
| 302 | /* Pull in bits 8 & 9 from the M register */ | ||
| 303 | n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x80) << 1; | ||
| 304 | n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x40) << 3; | ||
| 305 | |||
| 306 | freq = BASE_CLOCK * (n + 8) / (m + 2); | ||
| 307 | freq /= divisors[data->regs[ICS932S401_REG_PCISRC_DIVISOR] >> | ||
| 308 | ICS932S401_PCI_DIVISOR_SHIFT]; | ||
| 309 | |||
| 310 | return freq; | ||
| 311 | } | ||
| 312 | |||
| 313 | static ssize_t show_pci_clock(struct device *dev, | ||
| 314 | struct device_attribute *devattr, | ||
| 315 | char *buf) | ||
| 316 | { | ||
| 317 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
| 318 | |||
| 319 | return sprintf(buf, "%d\n", calculate_pci_freq(data)); | ||
| 320 | } | ||
| 321 | |||
| 322 | static ssize_t show_pci_clock_sel(struct device *dev, | ||
| 323 | struct device_attribute *devattr, | ||
| 324 | char *buf) | ||
| 325 | { | ||
| 326 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
| 327 | int freq; | ||
| 328 | |||
| 329 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED) | ||
| 330 | freq = calculate_pci_freq(data); | ||
| 331 | else | ||
| 332 | freq = 33333; | ||
| 333 | |||
| 334 | return sprintf(buf, "%d\n", freq); | ||
| 335 | } | ||
| 336 | |||
| 337 | static ssize_t show_value(struct device *dev, | ||
| 338 | struct device_attribute *devattr, | ||
| 339 | char *buf); | ||
| 340 | |||
| 341 | static ssize_t show_spread(struct device *dev, | ||
| 342 | struct device_attribute *devattr, | ||
| 343 | char *buf); | ||
| 344 | |||
| 345 | static DEVICE_ATTR(spread_enabled, S_IRUGO, show_spread_enabled, NULL); | ||
| 346 | static DEVICE_ATTR(cpu_clock_selection, S_IRUGO, show_cpu_clock_sel, NULL); | ||
| 347 | static DEVICE_ATTR(cpu_clock, S_IRUGO, show_cpu_clock, NULL); | ||
| 348 | static DEVICE_ATTR(src_clock_selection, S_IRUGO, show_src_clock_sel, NULL); | ||
| 349 | static DEVICE_ATTR(src_clock, S_IRUGO, show_src_clock, NULL); | ||
| 350 | static DEVICE_ATTR(pci_clock_selection, S_IRUGO, show_pci_clock_sel, NULL); | ||
| 351 | static DEVICE_ATTR(pci_clock, S_IRUGO, show_pci_clock, NULL); | ||
| 352 | static DEVICE_ATTR(usb_clock, S_IRUGO, show_value, NULL); | ||
| 353 | static DEVICE_ATTR(ref_clock, S_IRUGO, show_value, NULL); | ||
| 354 | static DEVICE_ATTR(cpu_spread, S_IRUGO, show_spread, NULL); | ||
| 355 | static DEVICE_ATTR(src_spread, S_IRUGO, show_spread, NULL); | ||
| 356 | |||
| 357 | static struct attribute *ics932s401_attr[] = | ||
| 358 | { | ||
| 359 | &dev_attr_spread_enabled.attr, | ||
| 360 | &dev_attr_cpu_clock_selection.attr, | ||
| 361 | &dev_attr_cpu_clock.attr, | ||
| 362 | &dev_attr_src_clock_selection.attr, | ||
| 363 | &dev_attr_src_clock.attr, | ||
| 364 | &dev_attr_pci_clock_selection.attr, | ||
| 365 | &dev_attr_pci_clock.attr, | ||
| 366 | &dev_attr_usb_clock.attr, | ||
| 367 | &dev_attr_ref_clock.attr, | ||
| 368 | &dev_attr_cpu_spread.attr, | ||
| 369 | &dev_attr_src_spread.attr, | ||
| 370 | NULL | ||
| 371 | }; | ||
| 372 | |||
| 373 | static ssize_t show_value(struct device *dev, | ||
| 374 | struct device_attribute *devattr, | ||
| 375 | char *buf) | ||
| 376 | { | ||
| 377 | int x; | ||
| 378 | |||
| 379 | if (devattr == &dev_attr_usb_clock) | ||
| 380 | x = 48000; | ||
| 381 | else if (devattr == &dev_attr_ref_clock) | ||
| 382 | x = BASE_CLOCK; | ||
| 383 | else | ||
| 384 | BUG(); | ||
| 385 | |||
| 386 | return sprintf(buf, "%d\n", x); | ||
| 387 | } | ||
| 388 | |||
| 389 | static ssize_t show_spread(struct device *dev, | ||
| 390 | struct device_attribute *devattr, | ||
| 391 | char *buf) | ||
| 392 | { | ||
| 393 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
| 394 | int reg; | ||
| 395 | unsigned long val; | ||
| 396 | |||
| 397 | if (!(data->regs[ICS932S401_REG_CFG2] & ICS932S401_CFG1_SPREAD)) | ||
| 398 | return sprintf(buf, "0%%\n"); | ||
| 399 | |||
| 400 | if (devattr == &dev_attr_src_spread) | ||
| 401 | reg = ICS932S401_REG_SRC_SPREAD1; | ||
| 402 | else if (devattr == &dev_attr_cpu_spread) | ||
| 403 | reg = ICS932S401_REG_CPU_SPREAD1; | ||
| 404 | else | ||
| 405 | BUG(); | ||
| 406 | |||
| 407 | val = data->regs[reg] | (data->regs[reg + 1] << 8); | ||
| 408 | val &= ICS932S401_SPREAD_MASK; | ||
| 409 | |||
| 410 | /* Scale 0..2^14 to -0.5. */ | ||
| 411 | val = 500000 * val / 16384; | ||
| 412 | return sprintf(buf, "-0.%lu%%\n", val); | ||
| 413 | } | ||
| 414 | |||
| 415 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
| 416 | static int ics932s401_detect(struct i2c_client *client, int kind, | ||
| 417 | struct i2c_board_info *info) | ||
| 418 | { | ||
| 419 | struct i2c_adapter *adapter = client->adapter; | ||
| 420 | |||
| 421 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 422 | return -ENODEV; | ||
| 423 | |||
| 424 | if (kind <= 0) { | ||
| 425 | int vendor, device, revision; | ||
| 426 | |||
| 427 | vendor = i2c_smbus_read_word_data(client, | ||
| 428 | ICS932S401_REG_VENDOR_REV); | ||
| 429 | vendor >>= 8; | ||
| 430 | revision = vendor >> ICS932S401_REV_SHIFT; | ||
| 431 | vendor &= ICS932S401_VENDOR_MASK; | ||
| 432 | if (vendor != ICS932S401_VENDOR) | ||
| 433 | return -ENODEV; | ||
| 434 | |||
| 435 | device = i2c_smbus_read_word_data(client, | ||
| 436 | ICS932S401_REG_DEVICE); | ||
| 437 | device >>= 8; | ||
| 438 | if (device != ICS932S401_DEVICE) | ||
| 439 | return -ENODEV; | ||
| 440 | |||
| 441 | if (revision != ICS932S401_REV) | ||
| 442 | dev_info(&adapter->dev, "Unknown revision %d\n", | ||
| 443 | revision); | ||
| 444 | } else | ||
| 445 | dev_dbg(&adapter->dev, "detection forced\n"); | ||
| 446 | |||
| 447 | strlcpy(info->type, "ics932s401", I2C_NAME_SIZE); | ||
| 448 | |||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | |||
| 452 | static int ics932s401_probe(struct i2c_client *client, | ||
| 453 | const struct i2c_device_id *id) | ||
| 454 | { | ||
| 455 | struct ics932s401_data *data; | ||
| 456 | int err; | ||
| 457 | |||
| 458 | data = kzalloc(sizeof(struct ics932s401_data), GFP_KERNEL); | ||
| 459 | if (!data) { | ||
| 460 | err = -ENOMEM; | ||
| 461 | goto exit; | ||
| 462 | } | ||
| 463 | |||
| 464 | i2c_set_clientdata(client, data); | ||
| 465 | mutex_init(&data->lock); | ||
| 466 | |||
| 467 | dev_info(&client->dev, "%s chip found\n", client->name); | ||
| 468 | |||
| 469 | /* Register sysfs hooks */ | ||
| 470 | data->attrs.attrs = ics932s401_attr; | ||
| 471 | err = sysfs_create_group(&client->dev.kobj, &data->attrs); | ||
| 472 | if (err) | ||
| 473 | goto exit_free; | ||
| 474 | |||
| 475 | return 0; | ||
| 476 | |||
| 477 | exit_free: | ||
| 478 | kfree(data); | ||
| 479 | exit: | ||
| 480 | return err; | ||
| 481 | } | ||
| 482 | |||
| 483 | static int ics932s401_remove(struct i2c_client *client) | ||
| 484 | { | ||
| 485 | struct ics932s401_data *data = i2c_get_clientdata(client); | ||
| 486 | |||
| 487 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
| 488 | kfree(data); | ||
| 489 | return 0; | ||
| 490 | } | ||
| 491 | |||
| 492 | static int __init ics932s401_init(void) | ||
| 493 | { | ||
| 494 | return i2c_add_driver(&ics932s401_driver); | ||
| 495 | } | ||
| 496 | |||
| 497 | static void __exit ics932s401_exit(void) | ||
| 498 | { | ||
| 499 | i2c_del_driver(&ics932s401_driver); | ||
| 500 | } | ||
| 501 | |||
| 502 | MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); | ||
| 503 | MODULE_DESCRIPTION("ICS932S401 driver"); | ||
| 504 | MODULE_LICENSE("GPL"); | ||
| 505 | |||
| 506 | module_init(ics932s401_init); | ||
| 507 | module_exit(ics932s401_exit); | ||
| 508 | |||
| 509 | /* IBM IntelliStation Z30 */ | ||
| 510 | MODULE_ALIAS("dmi:bvnIBM:*:rn9228:*"); | ||
| 511 | MODULE_ALIAS("dmi:bvnIBM:*:rn9232:*"); | ||
| 512 | |||
| 513 | /* IBM x3650/x3550 */ | ||
| 514 | MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650*"); | ||
| 515 | MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550*"); | ||
diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c index e00a2756e97e..27b7662955bb 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c | |||
| @@ -52,6 +52,11 @@ MODULE_LICENSE("GPL"); | |||
| 52 | #define MEMORY_ARG_CUR_BANDWIDTH 1 | 52 | #define MEMORY_ARG_CUR_BANDWIDTH 1 |
| 53 | #define MEMORY_ARG_MAX_BANDWIDTH 0 | 53 | #define MEMORY_ARG_MAX_BANDWIDTH 0 |
| 54 | 54 | ||
| 55 | /* | ||
| 56 | * GTHS returning 'n' would mean that [0,n-1] states are supported | ||
| 57 | * In that case max_cstate would be n-1 | ||
| 58 | * GTHS returning '0' would mean that no bandwidth control states are supported | ||
| 59 | */ | ||
| 55 | static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, | 60 | static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, |
| 56 | unsigned long *max_state) | 61 | unsigned long *max_state) |
| 57 | { | 62 | { |
| @@ -71,6 +76,9 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, | |||
| 71 | if (ACPI_FAILURE(status)) | 76 | if (ACPI_FAILURE(status)) |
| 72 | return -EFAULT; | 77 | return -EFAULT; |
| 73 | 78 | ||
| 79 | if (!value) | ||
| 80 | return -EINVAL; | ||
| 81 | |||
| 74 | *max_state = value - 1; | 82 | *max_state = value - 1; |
| 75 | return 0; | 83 | return 0; |
| 76 | } | 84 | } |
| @@ -121,7 +129,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, | |||
| 121 | if (memory_get_int_max_bandwidth(cdev, &max_state)) | 129 | if (memory_get_int_max_bandwidth(cdev, &max_state)) |
| 122 | return -EFAULT; | 130 | return -EFAULT; |
| 123 | 131 | ||
| 124 | if (max_state < 0 || state > max_state) | 132 | if (state > max_state) |
| 125 | return -EINVAL; | 133 | return -EINVAL; |
| 126 | 134 | ||
| 127 | arg_list.count = 1; | 135 | arg_list.count = 1; |
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c index de898c6938f3..759763d18e4c 100644 --- a/drivers/misc/msi-laptop.c +++ b/drivers/misc/msi-laptop.c | |||
| @@ -347,12 +347,16 @@ static int __init msi_init(void) | |||
| 347 | 347 | ||
| 348 | /* Register backlight stuff */ | 348 | /* Register backlight stuff */ |
| 349 | 349 | ||
| 350 | msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL, | 350 | if (acpi_video_backlight_support()) { |
| 351 | &msibl_ops); | 351 | printk(KERN_INFO "MSI: Brightness ignored, must be controlled " |
| 352 | if (IS_ERR(msibl_device)) | 352 | "by ACPI video driver\n"); |
| 353 | return PTR_ERR(msibl_device); | 353 | } else { |
| 354 | 354 | msibl_device = backlight_device_register("msi-laptop-bl", NULL, | |
| 355 | msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1; | 355 | NULL, &msibl_ops); |
| 356 | if (IS_ERR(msibl_device)) | ||
| 357 | return PTR_ERR(msibl_device); | ||
| 358 | msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1; | ||
| 359 | } | ||
| 356 | 360 | ||
| 357 | ret = platform_driver_register(&msipf_driver); | 361 | ret = platform_driver_register(&msipf_driver); |
| 358 | if (ret) | 362 | if (ret) |
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 06f07e19dc70..7bcb81002dcf 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
| @@ -1038,7 +1038,11 @@ static int sony_nc_add(struct acpi_device *device) | |||
| 1038 | goto outinput; | 1038 | goto outinput; |
| 1039 | } | 1039 | } |
| 1040 | 1040 | ||
| 1041 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) { | 1041 | if (!acpi_video_backlight_support()) { |
| 1042 | printk(KERN_INFO DRV_PFX "Sony: Brightness ignored, must be " | ||
| 1043 | "controlled by ACPI video driver\n"); | ||
| 1044 | } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", | ||
| 1045 | &handle))) { | ||
| 1042 | sony_backlight_device = backlight_device_register("sony", NULL, | 1046 | sony_backlight_device = backlight_device_register("sony", NULL, |
| 1043 | NULL, | 1047 | NULL, |
| 1044 | &sony_backlight_ops); | 1048 | &sony_backlight_ops); |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 4db1cf9078d9..7a4a26b0edd2 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -4932,16 +4932,25 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
| 4932 | */ | 4932 | */ |
| 4933 | b = tpacpi_check_std_acpi_brightness_support(); | 4933 | b = tpacpi_check_std_acpi_brightness_support(); |
| 4934 | if (b > 0) { | 4934 | if (b > 0) { |
| 4935 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { | 4935 | |
| 4936 | printk(TPACPI_NOTICE | 4936 | if (acpi_video_backlight_support()) { |
| 4937 | "Lenovo BIOS switched to ACPI backlight " | 4937 | if (brightness_enable > 1) { |
| 4938 | "control mode\n"); | 4938 | printk(TPACPI_NOTICE |
| 4939 | } | 4939 | "Standard ACPI backlight interface " |
| 4940 | if (brightness_enable > 1) { | 4940 | "available, not loading native one.\n"); |
| 4941 | printk(TPACPI_NOTICE | 4941 | return 1; |
| 4942 | "standard ACPI backlight interface " | 4942 | } else if (brightness_enable == 1) { |
| 4943 | "available, not loading native one...\n"); | 4943 | printk(TPACPI_NOTICE |
| 4944 | return 1; | 4944 | "Backlight control force enabled, even if standard " |
| 4945 | "ACPI backlight interface is available\n"); | ||
| 4946 | } | ||
| 4947 | } else { | ||
| 4948 | if (brightness_enable > 1) { | ||
| 4949 | printk(TPACPI_NOTICE | ||
| 4950 | "Standard ACPI backlight interface not " | ||
| 4951 | "available, thinkpad_acpi native " | ||
| 4952 | "brightness control enabled\n"); | ||
| 4953 | } | ||
| 4945 | } | 4954 | } |
| 4946 | } | 4955 | } |
| 4947 | 4956 | ||
diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c index e5059aa3c724..8d92d8db9a98 100644 --- a/drivers/mtd/maps/cdb89712.c +++ b/drivers/mtd/maps/cdb89712.c | |||
| @@ -14,7 +14,18 @@ | |||
| 14 | #include <linux/mtd/map.h> | 14 | #include <linux/mtd/map.h> |
| 15 | #include <linux/mtd/partitions.h> | 15 | #include <linux/mtd/partitions.h> |
| 16 | 16 | ||
| 17 | 17 | /* dynamic ioremap() areas */ | |
| 18 | #define FLASH_START 0x00000000 | ||
| 19 | #define FLASH_SIZE 0x800000 | ||
| 20 | #define FLASH_WIDTH 4 | ||
| 21 | |||
| 22 | #define SRAM_START 0x60000000 | ||
| 23 | #define SRAM_SIZE 0xc000 | ||
| 24 | #define SRAM_WIDTH 4 | ||
| 25 | |||
| 26 | #define BOOTROM_START 0x70000000 | ||
| 27 | #define BOOTROM_SIZE 0x80 | ||
| 28 | #define BOOTROM_WIDTH 4 | ||
| 18 | 29 | ||
| 19 | 30 | ||
| 20 | static struct mtd_info *flash_mtd; | 31 | static struct mtd_info *flash_mtd; |
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c index 35fef655ccc4..3b959fad1c4e 100644 --- a/drivers/mtd/maps/h720x-flash.c +++ b/drivers/mtd/maps/h720x-flash.c | |||
| @@ -24,8 +24,8 @@ static struct mtd_info *mymtd; | |||
| 24 | static struct map_info h720x_map = { | 24 | static struct map_info h720x_map = { |
| 25 | .name = "H720X", | 25 | .name = "H720X", |
| 26 | .bankwidth = 4, | 26 | .bankwidth = 4, |
| 27 | .size = FLASH_SIZE, | 27 | .size = H720X_FLASH_SIZE, |
| 28 | .phys = FLASH_PHYS, | 28 | .phys = H720X_FLASH_PHYS, |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static struct mtd_partition h720x_partitions[] = { | 31 | static struct mtd_partition h720x_partitions[] = { |
| @@ -70,7 +70,7 @@ int __init h720x_mtd_init(void) | |||
| 70 | 70 | ||
| 71 | char *part_type = NULL; | 71 | char *part_type = NULL; |
| 72 | 72 | ||
| 73 | h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE); | 73 | h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size); |
| 74 | 74 | ||
| 75 | if (!h720x_map.virt) { | 75 | if (!h720x_map.virt) { |
| 76 | printk(KERN_ERR "H720x-MTD: ioremap failed\n"); | 76 | printk(KERN_ERR "H720x-MTD: ioremap failed\n"); |
diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c index 8cbc1b59bd62..4a7700620119 100644 --- a/drivers/net/atl1e/atl1e_hw.c +++ b/drivers/net/atl1e/atl1e_hw.c | |||
| @@ -163,9 +163,6 @@ int atl1e_read_mac_addr(struct atl1e_hw *hw) | |||
| 163 | * atl1e_hash_mc_addr | 163 | * atl1e_hash_mc_addr |
| 164 | * purpose | 164 | * purpose |
| 165 | * set hash value for a multicast address | 165 | * set hash value for a multicast address |
| 166 | * hash calcu processing : | ||
| 167 | * 1. calcu 32bit CRC for multicast address | ||
| 168 | * 2. reverse crc with MSB to LSB | ||
| 169 | */ | 166 | */ |
| 170 | u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) | 167 | u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) |
| 171 | { | 168 | { |
| @@ -174,7 +171,6 @@ u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) | |||
| 174 | int i; | 171 | int i; |
| 175 | 172 | ||
| 176 | crc32 = ether_crc_le(6, mc_addr); | 173 | crc32 = ether_crc_le(6, mc_addr); |
| 177 | crc32 = ~crc32; | ||
| 178 | for (i = 0; i < 32; i++) | 174 | for (i = 0; i < 32; i++) |
| 179 | value |= (((crc32 >> i) & 1) << (31 - i)); | 175 | value |= (((crc32 >> i) & 1) << (31 - i)); |
| 180 | 176 | ||
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 246d92b42636..aef403d299ee 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c | |||
| @@ -3404,14 +3404,8 @@ static void atl1_get_wol(struct net_device *netdev, | |||
| 3404 | { | 3404 | { |
| 3405 | struct atl1_adapter *adapter = netdev_priv(netdev); | 3405 | struct atl1_adapter *adapter = netdev_priv(netdev); |
| 3406 | 3406 | ||
| 3407 | wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; | 3407 | wol->supported = WAKE_MAGIC; |
| 3408 | wol->wolopts = 0; | 3408 | wol->wolopts = 0; |
| 3409 | if (adapter->wol & ATLX_WUFC_EX) | ||
| 3410 | wol->wolopts |= WAKE_UCAST; | ||
| 3411 | if (adapter->wol & ATLX_WUFC_MC) | ||
| 3412 | wol->wolopts |= WAKE_MCAST; | ||
| 3413 | if (adapter->wol & ATLX_WUFC_BC) | ||
| 3414 | wol->wolopts |= WAKE_BCAST; | ||
| 3415 | if (adapter->wol & ATLX_WUFC_MAG) | 3409 | if (adapter->wol & ATLX_WUFC_MAG) |
| 3416 | wol->wolopts |= WAKE_MAGIC; | 3410 | wol->wolopts |= WAKE_MAGIC; |
| 3417 | return; | 3411 | return; |
| @@ -3422,15 +3416,10 @@ static int atl1_set_wol(struct net_device *netdev, | |||
| 3422 | { | 3416 | { |
| 3423 | struct atl1_adapter *adapter = netdev_priv(netdev); | 3417 | struct atl1_adapter *adapter = netdev_priv(netdev); |
| 3424 | 3418 | ||
| 3425 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) | 3419 | if (wol->wolopts & (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | |
| 3420 | WAKE_ARP | WAKE_MAGICSECURE)) | ||
| 3426 | return -EOPNOTSUPP; | 3421 | return -EOPNOTSUPP; |
| 3427 | adapter->wol = 0; | 3422 | adapter->wol = 0; |
| 3428 | if (wol->wolopts & WAKE_UCAST) | ||
| 3429 | adapter->wol |= ATLX_WUFC_EX; | ||
| 3430 | if (wol->wolopts & WAKE_MCAST) | ||
| 3431 | adapter->wol |= ATLX_WUFC_MC; | ||
| 3432 | if (wol->wolopts & WAKE_BCAST) | ||
| 3433 | adapter->wol |= ATLX_WUFC_BC; | ||
| 3434 | if (wol->wolopts & WAKE_MAGIC) | 3423 | if (wol->wolopts & WAKE_MAGIC) |
| 3435 | adapter->wol |= ATLX_WUFC_MAG; | 3424 | adapter->wol |= ATLX_WUFC_MAG; |
| 3436 | return 0; | 3425 | return 0; |
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 430d430bce29..d07e3f148951 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
| @@ -7204,10 +7204,13 @@ static void | |||
| 7204 | poll_bnx2(struct net_device *dev) | 7204 | poll_bnx2(struct net_device *dev) |
| 7205 | { | 7205 | { |
| 7206 | struct bnx2 *bp = netdev_priv(dev); | 7206 | struct bnx2 *bp = netdev_priv(dev); |
| 7207 | int i; | ||
| 7207 | 7208 | ||
| 7208 | disable_irq(bp->pdev->irq); | 7209 | for (i = 0; i < bp->irq_nvecs; i++) { |
| 7209 | bnx2_interrupt(bp->pdev->irq, dev); | 7210 | disable_irq(bp->irq_tbl[i].vector); |
| 7210 | enable_irq(bp->pdev->irq); | 7211 | bnx2_interrupt(bp->irq_tbl[i].vector, &bp->bnx2_napi[i]); |
| 7212 | enable_irq(bp->irq_tbl[i].vector); | ||
| 7213 | } | ||
| 7211 | } | 7214 | } |
| 7212 | #endif | 7215 | #endif |
| 7213 | 7216 | ||
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 1ace41a13ac3..2c341f83d327 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
| @@ -1307,8 +1307,10 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | |||
| 1307 | u32 fw_vers = 0; | 1307 | u32 fw_vers = 0; |
| 1308 | u32 tp_vers = 0; | 1308 | u32 tp_vers = 0; |
| 1309 | 1309 | ||
| 1310 | spin_lock(&adapter->stats_lock); | ||
| 1310 | t3_get_fw_version(adapter, &fw_vers); | 1311 | t3_get_fw_version(adapter, &fw_vers); |
| 1311 | t3_get_tp_version(adapter, &tp_vers); | 1312 | t3_get_tp_version(adapter, &tp_vers); |
| 1313 | spin_unlock(&adapter->stats_lock); | ||
| 1312 | 1314 | ||
| 1313 | strcpy(info->driver, DRV_NAME); | 1315 | strcpy(info->driver, DRV_NAME); |
| 1314 | strcpy(info->version, DRV_VERSION); | 1316 | strcpy(info->version, DRV_VERSION); |
| @@ -2699,7 +2701,7 @@ static void set_nqsets(struct adapter *adap) | |||
| 2699 | int hwports = adap->params.nports; | 2701 | int hwports = adap->params.nports; |
| 2700 | int nqsets = SGE_QSETS; | 2702 | int nqsets = SGE_QSETS; |
| 2701 | 2703 | ||
| 2702 | if (adap->params.rev > 0) { | 2704 | if (adap->params.rev > 0 && adap->flags & USING_MSIX) { |
| 2703 | if (hwports == 2 && | 2705 | if (hwports == 2 && |
| 2704 | (hwports * nqsets > SGE_QSETS || | 2706 | (hwports * nqsets > SGE_QSETS || |
| 2705 | num_cpus >= nqsets / hwports)) | 2707 | num_cpus >= nqsets / hwports)) |
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 968f64be3743..9a0898b0dbce 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c | |||
| @@ -572,7 +572,7 @@ struct t3_vpd { | |||
| 572 | u32 pad; /* for multiple-of-4 sizing and alignment */ | 572 | u32 pad; /* for multiple-of-4 sizing and alignment */ |
| 573 | }; | 573 | }; |
| 574 | 574 | ||
| 575 | #define EEPROM_MAX_POLL 4 | 575 | #define EEPROM_MAX_POLL 40 |
| 576 | #define EEPROM_STAT_ADDR 0x4000 | 576 | #define EEPROM_STAT_ADDR 0x4000 |
| 577 | #define VPD_BASE 0xc00 | 577 | #define VPD_BASE 0xc00 |
| 578 | 578 | ||
| @@ -3690,6 +3690,12 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | |||
| 3690 | ; | 3690 | ; |
| 3691 | 3691 | ||
| 3692 | pti = &port_types[adapter->params.vpd.port_type[j]]; | 3692 | pti = &port_types[adapter->params.vpd.port_type[j]]; |
| 3693 | if (!pti->phy_prep) { | ||
| 3694 | CH_ALERT(adapter, "Invalid port type index %d\n", | ||
| 3695 | adapter->params.vpd.port_type[j]); | ||
| 3696 | return -EINVAL; | ||
| 3697 | } | ||
| 3698 | |||
| 3693 | ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, | 3699 | ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, |
| 3694 | ai->mdio_ops); | 3700 | ai->mdio_ops); |
| 3695 | if (ret) | 3701 | if (ret) |
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 3d69fae781cf..e8bfcce6b319 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
| @@ -166,7 +166,7 @@ | |||
| 166 | 166 | ||
| 167 | #define DRV_NAME "e100" | 167 | #define DRV_NAME "e100" |
| 168 | #define DRV_EXT "-NAPI" | 168 | #define DRV_EXT "-NAPI" |
| 169 | #define DRV_VERSION "3.5.23-k4"DRV_EXT | 169 | #define DRV_VERSION "3.5.23-k6"DRV_EXT |
| 170 | #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" | 170 | #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" |
| 171 | #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" | 171 | #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" |
| 172 | #define PFX DRV_NAME ": " | 172 | #define PFX DRV_NAME ": " |
| @@ -1804,7 +1804,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) | |||
| 1804 | struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; | 1804 | struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; |
| 1805 | put_unaligned_le32(rx->dma_addr, &prev_rfd->link); | 1805 | put_unaligned_le32(rx->dma_addr, &prev_rfd->link); |
| 1806 | pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, | 1806 | pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, |
| 1807 | sizeof(struct rfd), PCI_DMA_TODEVICE); | 1807 | sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); |
| 1808 | } | 1808 | } |
| 1809 | 1809 | ||
| 1810 | return 0; | 1810 | return 0; |
| @@ -1823,7 +1823,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
| 1823 | 1823 | ||
| 1824 | /* Need to sync before taking a peek at cb_complete bit */ | 1824 | /* Need to sync before taking a peek at cb_complete bit */ |
| 1825 | pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, | 1825 | pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, |
| 1826 | sizeof(struct rfd), PCI_DMA_FROMDEVICE); | 1826 | sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); |
| 1827 | rfd_status = le16_to_cpu(rfd->status); | 1827 | rfd_status = le16_to_cpu(rfd->status); |
| 1828 | 1828 | ||
| 1829 | DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); | 1829 | DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); |
| @@ -1850,7 +1850,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
| 1850 | 1850 | ||
| 1851 | /* Get data */ | 1851 | /* Get data */ |
| 1852 | pci_unmap_single(nic->pdev, rx->dma_addr, | 1852 | pci_unmap_single(nic->pdev, rx->dma_addr, |
| 1853 | RFD_BUF_LEN, PCI_DMA_FROMDEVICE); | 1853 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); |
| 1854 | 1854 | ||
| 1855 | /* If this buffer has the el bit, but we think the receiver | 1855 | /* If this buffer has the el bit, but we think the receiver |
| 1856 | * is still running, check to see if it really stopped while | 1856 | * is still running, check to see if it really stopped while |
| @@ -1943,7 +1943,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, | |||
| 1943 | new_before_last_rfd->command |= cpu_to_le16(cb_el); | 1943 | new_before_last_rfd->command |= cpu_to_le16(cb_el); |
| 1944 | pci_dma_sync_single_for_device(nic->pdev, | 1944 | pci_dma_sync_single_for_device(nic->pdev, |
| 1945 | new_before_last_rx->dma_addr, sizeof(struct rfd), | 1945 | new_before_last_rx->dma_addr, sizeof(struct rfd), |
| 1946 | PCI_DMA_TODEVICE); | 1946 | PCI_DMA_BIDIRECTIONAL); |
| 1947 | 1947 | ||
| 1948 | /* Now that we have a new stopping point, we can clear the old | 1948 | /* Now that we have a new stopping point, we can clear the old |
| 1949 | * stopping point. We must sync twice to get the proper | 1949 | * stopping point. We must sync twice to get the proper |
| @@ -1951,11 +1951,11 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, | |||
| 1951 | old_before_last_rfd->command &= ~cpu_to_le16(cb_el); | 1951 | old_before_last_rfd->command &= ~cpu_to_le16(cb_el); |
| 1952 | pci_dma_sync_single_for_device(nic->pdev, | 1952 | pci_dma_sync_single_for_device(nic->pdev, |
| 1953 | old_before_last_rx->dma_addr, sizeof(struct rfd), | 1953 | old_before_last_rx->dma_addr, sizeof(struct rfd), |
| 1954 | PCI_DMA_TODEVICE); | 1954 | PCI_DMA_BIDIRECTIONAL); |
| 1955 | old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); | 1955 | old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); |
| 1956 | pci_dma_sync_single_for_device(nic->pdev, | 1956 | pci_dma_sync_single_for_device(nic->pdev, |
| 1957 | old_before_last_rx->dma_addr, sizeof(struct rfd), | 1957 | old_before_last_rx->dma_addr, sizeof(struct rfd), |
| 1958 | PCI_DMA_TODEVICE); | 1958 | PCI_DMA_BIDIRECTIONAL); |
| 1959 | } | 1959 | } |
| 1960 | 1960 | ||
| 1961 | if(restart_required) { | 1961 | if(restart_required) { |
| @@ -1978,7 +1978,7 @@ static void e100_rx_clean_list(struct nic *nic) | |||
| 1978 | for(rx = nic->rxs, i = 0; i < count; rx++, i++) { | 1978 | for(rx = nic->rxs, i = 0; i < count; rx++, i++) { |
| 1979 | if(rx->skb) { | 1979 | if(rx->skb) { |
| 1980 | pci_unmap_single(nic->pdev, rx->dma_addr, | 1980 | pci_unmap_single(nic->pdev, rx->dma_addr, |
| 1981 | RFD_BUF_LEN, PCI_DMA_FROMDEVICE); | 1981 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); |
| 1982 | dev_kfree_skb(rx->skb); | 1982 | dev_kfree_skb(rx->skb); |
| 1983 | } | 1983 | } |
| 1984 | } | 1984 | } |
| @@ -2021,7 +2021,7 @@ static int e100_rx_alloc_list(struct nic *nic) | |||
| 2021 | before_last->command |= cpu_to_le16(cb_el); | 2021 | before_last->command |= cpu_to_le16(cb_el); |
| 2022 | before_last->size = 0; | 2022 | before_last->size = 0; |
| 2023 | pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, | 2023 | pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, |
| 2024 | sizeof(struct rfd), PCI_DMA_TODEVICE); | 2024 | sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); |
| 2025 | 2025 | ||
| 2026 | nic->rx_to_use = nic->rx_to_clean = nic->rxs; | 2026 | nic->rx_to_use = nic->rx_to_clean = nic->rxs; |
| 2027 | nic->ru_running = RU_SUSPENDED; | 2027 | nic->ru_running = RU_SUSPENDED; |
| @@ -2222,7 +2222,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) | |||
| 2222 | msleep(10); | 2222 | msleep(10); |
| 2223 | 2223 | ||
| 2224 | pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, | 2224 | pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, |
| 2225 | RFD_BUF_LEN, PCI_DMA_FROMDEVICE); | 2225 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); |
| 2226 | 2226 | ||
| 2227 | if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), | 2227 | if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), |
| 2228 | skb->data, ETH_DATA_LEN)) | 2228 | skb->data, ETH_DATA_LEN)) |
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 6a3893acfe04..c854c96f5ab3 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c | |||
| @@ -1774,7 +1774,8 @@ static void e1000_get_wol(struct net_device *netdev, | |||
| 1774 | 1774 | ||
| 1775 | /* this function will set ->supported = 0 and return 1 if wol is not | 1775 | /* this function will set ->supported = 0 and return 1 if wol is not |
| 1776 | * supported by this hardware */ | 1776 | * supported by this hardware */ |
| 1777 | if (e1000_wol_exclusion(adapter, wol)) | 1777 | if (e1000_wol_exclusion(adapter, wol) || |
| 1778 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1778 | return; | 1779 | return; |
| 1779 | 1780 | ||
| 1780 | /* apply any specific unsupported masks here */ | 1781 | /* apply any specific unsupported masks here */ |
| @@ -1811,7 +1812,8 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1811 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) | 1812 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) |
| 1812 | return -EOPNOTSUPP; | 1813 | return -EOPNOTSUPP; |
| 1813 | 1814 | ||
| 1814 | if (e1000_wol_exclusion(adapter, wol)) | 1815 | if (e1000_wol_exclusion(adapter, wol) || |
| 1816 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1815 | return wol->wolopts ? -EOPNOTSUPP : 0; | 1817 | return wol->wolopts ? -EOPNOTSUPP : 0; |
| 1816 | 1818 | ||
| 1817 | switch (hw->device_id) { | 1819 | switch (hw->device_id) { |
| @@ -1838,6 +1840,8 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1838 | if (wol->wolopts & WAKE_MAGIC) | 1840 | if (wol->wolopts & WAKE_MAGIC) |
| 1839 | adapter->wol |= E1000_WUFC_MAG; | 1841 | adapter->wol |= E1000_WUFC_MAG; |
| 1840 | 1842 | ||
| 1843 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1844 | |||
| 1841 | return 0; | 1845 | return 0; |
| 1842 | } | 1846 | } |
| 1843 | 1847 | ||
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index fac82152e4c8..872799b746f5 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -1179,6 +1179,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
| 1179 | 1179 | ||
| 1180 | /* initialize the wol settings based on the eeprom settings */ | 1180 | /* initialize the wol settings based on the eeprom settings */ |
| 1181 | adapter->wol = adapter->eeprom_wol; | 1181 | adapter->wol = adapter->eeprom_wol; |
| 1182 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1182 | 1183 | ||
| 1183 | /* print bus type/speed/width info */ | 1184 | /* print bus type/speed/width info */ |
| 1184 | DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ", | 1185 | DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ", |
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index c55de1c027af..c55fd6fdb91c 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
| @@ -299,6 +299,7 @@ struct e1000_adapter { | |||
| 299 | unsigned long led_status; | 299 | unsigned long led_status; |
| 300 | 300 | ||
| 301 | unsigned int flags; | 301 | unsigned int flags; |
| 302 | unsigned int flags2; | ||
| 302 | struct work_struct downshift_task; | 303 | struct work_struct downshift_task; |
| 303 | struct work_struct update_phy_task; | 304 | struct work_struct update_phy_task; |
| 304 | }; | 305 | }; |
| @@ -306,6 +307,7 @@ struct e1000_adapter { | |||
| 306 | struct e1000_info { | 307 | struct e1000_info { |
| 307 | enum e1000_mac_type mac; | 308 | enum e1000_mac_type mac; |
| 308 | unsigned int flags; | 309 | unsigned int flags; |
| 310 | unsigned int flags2; | ||
| 309 | u32 pba; | 311 | u32 pba; |
| 310 | s32 (*get_variants)(struct e1000_adapter *); | 312 | s32 (*get_variants)(struct e1000_adapter *); |
| 311 | struct e1000_mac_operations *mac_ops; | 313 | struct e1000_mac_operations *mac_ops; |
| @@ -347,6 +349,9 @@ struct e1000_info { | |||
| 347 | #define FLAG_RX_RESTART_NOW (1 << 30) | 349 | #define FLAG_RX_RESTART_NOW (1 << 30) |
| 348 | #define FLAG_MSI_TEST_FAILED (1 << 31) | 350 | #define FLAG_MSI_TEST_FAILED (1 << 31) |
| 349 | 351 | ||
| 352 | /* CRC Stripping defines */ | ||
| 353 | #define FLAG2_CRC_STRIPPING (1 << 0) | ||
| 354 | |||
| 350 | #define E1000_RX_DESC_PS(R, i) \ | 355 | #define E1000_RX_DESC_PS(R, i) \ |
| 351 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) | 356 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) |
| 352 | #define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) | 357 | #define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) |
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 70c11c811a08..62421ce96311 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c | |||
| @@ -1713,7 +1713,8 @@ static void e1000_get_wol(struct net_device *netdev, | |||
| 1713 | wol->supported = 0; | 1713 | wol->supported = 0; |
| 1714 | wol->wolopts = 0; | 1714 | wol->wolopts = 0; |
| 1715 | 1715 | ||
| 1716 | if (!(adapter->flags & FLAG_HAS_WOL)) | 1716 | if (!(adapter->flags & FLAG_HAS_WOL) || |
| 1717 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1717 | return; | 1718 | return; |
| 1718 | 1719 | ||
| 1719 | wol->supported = WAKE_UCAST | WAKE_MCAST | | 1720 | wol->supported = WAKE_UCAST | WAKE_MCAST | |
| @@ -1751,7 +1752,8 @@ static int e1000_set_wol(struct net_device *netdev, | |||
| 1751 | if (wol->wolopts & WAKE_MAGICSECURE) | 1752 | if (wol->wolopts & WAKE_MAGICSECURE) |
| 1752 | return -EOPNOTSUPP; | 1753 | return -EOPNOTSUPP; |
| 1753 | 1754 | ||
| 1754 | if (!(adapter->flags & FLAG_HAS_WOL)) | 1755 | if (!(adapter->flags & FLAG_HAS_WOL) || |
| 1756 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1755 | return wol->wolopts ? -EOPNOTSUPP : 0; | 1757 | return wol->wolopts ? -EOPNOTSUPP : 0; |
| 1756 | 1758 | ||
| 1757 | /* these settings will always override what we currently have */ | 1759 | /* these settings will always override what we currently have */ |
| @@ -1770,6 +1772,8 @@ static int e1000_set_wol(struct net_device *netdev, | |||
| 1770 | if (wol->wolopts & WAKE_ARP) | 1772 | if (wol->wolopts & WAKE_ARP) |
| 1771 | adapter->wol |= E1000_WUFC_ARP; | 1773 | adapter->wol |= E1000_WUFC_ARP; |
| 1772 | 1774 | ||
| 1775 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1776 | |||
| 1773 | return 0; | 1777 | return 0; |
| 1774 | } | 1778 | } |
| 1775 | 1779 | ||
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index abd492b7336d..91795f78c3e4 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
| @@ -499,6 +499,10 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, | |||
| 499 | goto next_desc; | 499 | goto next_desc; |
| 500 | } | 500 | } |
| 501 | 501 | ||
| 502 | /* adjust length to remove Ethernet CRC */ | ||
| 503 | if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) | ||
| 504 | length -= 4; | ||
| 505 | |||
| 502 | total_rx_bytes += length; | 506 | total_rx_bytes += length; |
| 503 | total_rx_packets++; | 507 | total_rx_packets++; |
| 504 | 508 | ||
| @@ -804,6 +808,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
| 804 | pci_dma_sync_single_for_device(pdev, ps_page->dma, | 808 | pci_dma_sync_single_for_device(pdev, ps_page->dma, |
| 805 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | 809 | PAGE_SIZE, PCI_DMA_FROMDEVICE); |
| 806 | 810 | ||
| 811 | /* remove the CRC */ | ||
| 812 | if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) | ||
| 813 | l1 -= 4; | ||
| 814 | |||
| 807 | skb_put(skb, l1); | 815 | skb_put(skb, l1); |
| 808 | goto copydone; | 816 | goto copydone; |
| 809 | } /* if */ | 817 | } /* if */ |
| @@ -825,6 +833,12 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
| 825 | skb->truesize += length; | 833 | skb->truesize += length; |
| 826 | } | 834 | } |
| 827 | 835 | ||
| 836 | /* strip the ethernet crc, problem is we're using pages now so | ||
| 837 | * this whole operation can get a little cpu intensive | ||
| 838 | */ | ||
| 839 | if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) | ||
| 840 | pskb_trim(skb, skb->len - 4); | ||
| 841 | |||
| 828 | copydone: | 842 | copydone: |
| 829 | total_rx_bytes += skb->len; | 843 | total_rx_bytes += skb->len; |
| 830 | total_rx_packets++; | 844 | total_rx_packets++; |
| @@ -2301,8 +2315,12 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) | |||
| 2301 | else | 2315 | else |
| 2302 | rctl |= E1000_RCTL_LPE; | 2316 | rctl |= E1000_RCTL_LPE; |
| 2303 | 2317 | ||
| 2304 | /* Enable hardware CRC frame stripping */ | 2318 | /* Some systems expect that the CRC is included in SMBUS traffic. The |
| 2305 | rctl |= E1000_RCTL_SECRC; | 2319 | * hardware strips the CRC before sending to both SMBUS (BMC) and to |
| 2320 | * host memory when this is enabled | ||
| 2321 | */ | ||
| 2322 | if (adapter->flags2 & FLAG2_CRC_STRIPPING) | ||
| 2323 | rctl |= E1000_RCTL_SECRC; | ||
| 2306 | 2324 | ||
| 2307 | /* Setup buffer sizes */ | 2325 | /* Setup buffer sizes */ |
| 2308 | rctl &= ~E1000_RCTL_SZ_4096; | 2326 | rctl &= ~E1000_RCTL_SZ_4096; |
| @@ -4766,6 +4784,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
| 4766 | adapter->ei = ei; | 4784 | adapter->ei = ei; |
| 4767 | adapter->pba = ei->pba; | 4785 | adapter->pba = ei->pba; |
| 4768 | adapter->flags = ei->flags; | 4786 | adapter->flags = ei->flags; |
| 4787 | adapter->flags2 = ei->flags2; | ||
| 4769 | adapter->hw.adapter = adapter; | 4788 | adapter->hw.adapter = adapter; |
| 4770 | adapter->hw.mac.type = ei->mac; | 4789 | adapter->hw.mac.type = ei->mac; |
| 4771 | adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; | 4790 | adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; |
| @@ -4970,6 +4989,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
| 4970 | 4989 | ||
| 4971 | /* initialize the wol settings based on the eeprom settings */ | 4990 | /* initialize the wol settings based on the eeprom settings */ |
| 4972 | adapter->wol = adapter->eeprom_wol; | 4991 | adapter->wol = adapter->eeprom_wol; |
| 4992 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 4973 | 4993 | ||
| 4974 | /* reset the hardware with the new settings */ | 4994 | /* reset the hardware with the new settings */ |
| 4975 | e1000e_reset(adapter); | 4995 | e1000e_reset(adapter); |
| @@ -5008,6 +5028,7 @@ err_hw_init: | |||
| 5008 | err_sw_init: | 5028 | err_sw_init: |
| 5009 | if (adapter->hw.flash_address) | 5029 | if (adapter->hw.flash_address) |
| 5010 | iounmap(adapter->hw.flash_address); | 5030 | iounmap(adapter->hw.flash_address); |
| 5031 | e1000e_reset_interrupt_capability(adapter); | ||
| 5011 | err_flashmap: | 5032 | err_flashmap: |
| 5012 | iounmap(adapter->hw.hw_addr); | 5033 | iounmap(adapter->hw.hw_addr); |
| 5013 | err_ioremap: | 5034 | err_ioremap: |
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index 77a3d7207a5f..e909f96698e8 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c | |||
| @@ -151,6 +151,16 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); | |||
| 151 | */ | 151 | */ |
| 152 | E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); | 152 | E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); |
| 153 | 153 | ||
| 154 | /* | ||
| 155 | * Enable CRC Stripping | ||
| 156 | * | ||
| 157 | * Valid Range: 0, 1 | ||
| 158 | * | ||
| 159 | * Default Value: 1 (enabled) | ||
| 160 | */ | ||
| 161 | E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \ | ||
| 162 | "the CRC"); | ||
| 163 | |||
| 154 | struct e1000_option { | 164 | struct e1000_option { |
| 155 | enum { enable_option, range_option, list_option } type; | 165 | enum { enable_option, range_option, list_option } type; |
| 156 | const char *name; | 166 | const char *name; |
| @@ -404,6 +414,21 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) | |||
| 404 | adapter->flags |= FLAG_SMART_POWER_DOWN; | 414 | adapter->flags |= FLAG_SMART_POWER_DOWN; |
| 405 | } | 415 | } |
| 406 | } | 416 | } |
| 417 | { /* CRC Stripping */ | ||
| 418 | const struct e1000_option opt = { | ||
| 419 | .type = enable_option, | ||
| 420 | .name = "CRC Stripping", | ||
| 421 | .err = "defaulting to enabled", | ||
| 422 | .def = OPTION_ENABLED | ||
| 423 | }; | ||
| 424 | |||
| 425 | if (num_CrcStripping > bd) { | ||
| 426 | unsigned int crc_stripping = CrcStripping[bd]; | ||
| 427 | e1000_validate_option(&crc_stripping, &opt, adapter); | ||
| 428 | if (crc_stripping == OPTION_ENABLED) | ||
| 429 | adapter->flags2 |= FLAG2_CRC_STRIPPING; | ||
| 430 | } | ||
| 431 | } | ||
| 407 | { /* Kumeran Lock Loss Workaround */ | 432 | { /* Kumeran Lock Loss Workaround */ |
| 408 | const struct e1000_option opt = { | 433 | const struct e1000_option opt = { |
| 409 | .type = enable_option, | 434 | .type = enable_option, |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 83a5cb6aa23b..c4af949bf860 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -1407,6 +1407,10 @@ static int gfar_clean_tx_ring(struct net_device *dev) | |||
| 1407 | if (bdp->status & TXBD_DEF) | 1407 | if (bdp->status & TXBD_DEF) |
| 1408 | dev->stats.collisions++; | 1408 | dev->stats.collisions++; |
| 1409 | 1409 | ||
| 1410 | /* Unmap the DMA memory */ | ||
| 1411 | dma_unmap_single(&priv->dev->dev, bdp->bufPtr, | ||
| 1412 | bdp->length, DMA_TO_DEVICE); | ||
| 1413 | |||
| 1410 | /* Free the sk buffer associated with this TxBD */ | 1414 | /* Free the sk buffer associated with this TxBD */ |
| 1411 | dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]); | 1415 | dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]); |
| 1412 | 1416 | ||
| @@ -1666,6 +1670,9 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
| 1666 | 1670 | ||
| 1667 | skb = priv->rx_skbuff[priv->skb_currx]; | 1671 | skb = priv->rx_skbuff[priv->skb_currx]; |
| 1668 | 1672 | ||
| 1673 | dma_unmap_single(&priv->dev->dev, bdp->bufPtr, | ||
| 1674 | priv->rx_buffer_size, DMA_FROM_DEVICE); | ||
| 1675 | |||
| 1669 | /* We drop the frame if we failed to allocate a new buffer */ | 1676 | /* We drop the frame if we failed to allocate a new buffer */ |
| 1670 | if (unlikely(!newskb || !(bdp->status & RXBD_LAST) || | 1677 | if (unlikely(!newskb || !(bdp->status & RXBD_LAST) || |
| 1671 | bdp->status & RXBD_ERR)) { | 1678 | bdp->status & RXBD_ERR)) { |
| @@ -1674,14 +1681,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
| 1674 | if (unlikely(!newskb)) | 1681 | if (unlikely(!newskb)) |
| 1675 | newskb = skb; | 1682 | newskb = skb; |
| 1676 | 1683 | ||
| 1677 | if (skb) { | 1684 | if (skb) |
| 1678 | dma_unmap_single(&priv->dev->dev, | ||
| 1679 | bdp->bufPtr, | ||
| 1680 | priv->rx_buffer_size, | ||
| 1681 | DMA_FROM_DEVICE); | ||
| 1682 | |||
| 1683 | dev_kfree_skb_any(skb); | 1685 | dev_kfree_skb_any(skb); |
| 1684 | } | ||
| 1685 | } else { | 1686 | } else { |
| 1686 | /* Increment the number of packets */ | 1687 | /* Increment the number of packets */ |
| 1687 | dev->stats.rx_packets++; | 1688 | dev->stats.rx_packets++; |
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 58906c984be9..89964fa739a0 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c | |||
| @@ -1776,7 +1776,8 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1776 | 1776 | ||
| 1777 | /* this function will set ->supported = 0 and return 1 if wol is not | 1777 | /* this function will set ->supported = 0 and return 1 if wol is not |
| 1778 | * supported by this hardware */ | 1778 | * supported by this hardware */ |
| 1779 | if (igb_wol_exclusion(adapter, wol)) | 1779 | if (igb_wol_exclusion(adapter, wol) || |
| 1780 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1780 | return; | 1781 | return; |
| 1781 | 1782 | ||
| 1782 | /* apply any specific unsupported masks here */ | 1783 | /* apply any specific unsupported masks here */ |
| @@ -1805,7 +1806,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1805 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) | 1806 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) |
| 1806 | return -EOPNOTSUPP; | 1807 | return -EOPNOTSUPP; |
| 1807 | 1808 | ||
| 1808 | if (igb_wol_exclusion(adapter, wol)) | 1809 | if (igb_wol_exclusion(adapter, wol) || |
| 1810 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1809 | return wol->wolopts ? -EOPNOTSUPP : 0; | 1811 | return wol->wolopts ? -EOPNOTSUPP : 0; |
| 1810 | 1812 | ||
| 1811 | switch (hw->device_id) { | 1813 | switch (hw->device_id) { |
| @@ -1825,6 +1827,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1825 | if (wol->wolopts & WAKE_MAGIC) | 1827 | if (wol->wolopts & WAKE_MAGIC) |
| 1826 | adapter->wol |= E1000_WUFC_MAG; | 1828 | adapter->wol |= E1000_WUFC_MAG; |
| 1827 | 1829 | ||
| 1830 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1831 | |||
| 1828 | return 0; | 1832 | return 0; |
| 1829 | } | 1833 | } |
| 1830 | 1834 | ||
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 1f397cd99414..1cbae85b1426 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
| @@ -1019,10 +1019,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
| 1019 | state &= ~PCIE_LINK_STATE_L0S; | 1019 | state &= ~PCIE_LINK_STATE_L0S; |
| 1020 | pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL, | 1020 | pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL, |
| 1021 | state); | 1021 | state); |
| 1022 | printk(KERN_INFO "Disabling ASPM L0s upstream switch " | 1022 | dev_info(&pdev->dev, |
| 1023 | "port %x:%x.%x\n", us_dev->bus->number, | 1023 | "Disabling ASPM L0s upstream switch port %s\n", |
| 1024 | PCI_SLOT(us_dev->devfn), | 1024 | pci_name(us_dev)); |
| 1025 | PCI_FUNC(us_dev->devfn)); | ||
| 1026 | } | 1025 | } |
| 1027 | default: | 1026 | default: |
| 1028 | break; | 1027 | break; |
| @@ -1244,6 +1243,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
| 1244 | 1243 | ||
| 1245 | /* initialize the wol settings based on the eeprom settings */ | 1244 | /* initialize the wol settings based on the eeprom settings */ |
| 1246 | adapter->wol = adapter->eeprom_wol; | 1245 | adapter->wol = adapter->eeprom_wol; |
| 1246 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1247 | 1247 | ||
| 1248 | /* reset the hardware with the new settings */ | 1248 | /* reset the hardware with the new settings */ |
| 1249 | igb_reset(adapter); | 1249 | igb_reset(adapter); |
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index a339afbeed38..96e709d6440a 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c | |||
| @@ -656,10 +656,10 @@ static int mlx4_en_start_port(struct net_device *dev) | |||
| 656 | /* Configure port */ | 656 | /* Configure port */ |
| 657 | err = mlx4_SET_PORT_general(mdev->dev, priv->port, | 657 | err = mlx4_SET_PORT_general(mdev->dev, priv->port, |
| 658 | priv->rx_skb_size + ETH_FCS_LEN, | 658 | priv->rx_skb_size + ETH_FCS_LEN, |
| 659 | mdev->profile.tx_pause, | 659 | priv->prof->tx_pause, |
| 660 | mdev->profile.tx_ppp, | 660 | priv->prof->tx_ppp, |
| 661 | mdev->profile.rx_pause, | 661 | priv->prof->rx_pause, |
| 662 | mdev->profile.rx_ppp); | 662 | priv->prof->rx_ppp); |
| 663 | if (err) { | 663 | if (err) { |
| 664 | mlx4_err(mdev, "Failed setting port general configurations" | 664 | mlx4_err(mdev, "Failed setting port general configurations" |
| 665 | " for port %d, with error %d\n", priv->port, err); | 665 | " for port %d, with error %d\n", priv->port, err); |
| @@ -706,7 +706,7 @@ tx_err: | |||
| 706 | mlx4_en_release_rss_steer(priv); | 706 | mlx4_en_release_rss_steer(priv); |
| 707 | rx_err: | 707 | rx_err: |
| 708 | for (i = 0; i < priv->rx_ring_num; i++) | 708 | for (i = 0; i < priv->rx_ring_num; i++) |
| 709 | mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[rx_index]); | 709 | mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); |
| 710 | cq_err: | 710 | cq_err: |
| 711 | while (rx_index--) | 711 | while (rx_index--) |
| 712 | mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); | 712 | mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); |
diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_params.c index c2e69b1bcd0a..95706ee1c019 100644 --- a/drivers/net/mlx4/en_params.c +++ b/drivers/net/mlx4/en_params.c | |||
| @@ -90,6 +90,7 @@ MLX4_EN_PARM_INT(rx_ring_size2, MLX4_EN_AUTO_CONF, "Rx ring size for port 2"); | |||
| 90 | int mlx4_en_get_profile(struct mlx4_en_dev *mdev) | 90 | int mlx4_en_get_profile(struct mlx4_en_dev *mdev) |
| 91 | { | 91 | { |
| 92 | struct mlx4_en_profile *params = &mdev->profile; | 92 | struct mlx4_en_profile *params = &mdev->profile; |
| 93 | int i; | ||
| 93 | 94 | ||
| 94 | params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF); | 95 | params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF); |
| 95 | params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF); | 96 | params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF); |
| @@ -97,11 +98,13 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev) | |||
| 97 | params->rss_xor = (rss_xor != 0); | 98 | params->rss_xor = (rss_xor != 0); |
| 98 | params->rss_mask = rss_mask & 0x1f; | 99 | params->rss_mask = rss_mask & 0x1f; |
| 99 | params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS); | 100 | params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS); |
| 100 | params->rx_pause = pprx; | 101 | for (i = 1; i <= MLX4_MAX_PORTS; i++) { |
| 101 | params->rx_ppp = pfcrx; | 102 | params->prof[i].rx_pause = pprx; |
| 102 | params->tx_pause = pptx; | 103 | params->prof[i].rx_ppp = pfcrx; |
| 103 | params->tx_ppp = pfctx; | 104 | params->prof[i].tx_pause = pptx; |
| 104 | if (params->rx_ppp || params->tx_ppp) { | 105 | params->prof[i].tx_ppp = pfctx; |
| 106 | } | ||
| 107 | if (pfcrx || pfctx) { | ||
| 105 | params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM; | 108 | params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM; |
| 106 | params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM; | 109 | params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM; |
| 107 | } else { | 110 | } else { |
| @@ -407,14 +410,14 @@ static int mlx4_en_set_pauseparam(struct net_device *dev, | |||
| 407 | struct mlx4_en_dev *mdev = priv->mdev; | 410 | struct mlx4_en_dev *mdev = priv->mdev; |
| 408 | int err; | 411 | int err; |
| 409 | 412 | ||
| 410 | mdev->profile.tx_pause = pause->tx_pause != 0; | 413 | priv->prof->tx_pause = pause->tx_pause != 0; |
| 411 | mdev->profile.rx_pause = pause->rx_pause != 0; | 414 | priv->prof->rx_pause = pause->rx_pause != 0; |
| 412 | err = mlx4_SET_PORT_general(mdev->dev, priv->port, | 415 | err = mlx4_SET_PORT_general(mdev->dev, priv->port, |
| 413 | priv->rx_skb_size + ETH_FCS_LEN, | 416 | priv->rx_skb_size + ETH_FCS_LEN, |
| 414 | mdev->profile.tx_pause, | 417 | priv->prof->tx_pause, |
| 415 | mdev->profile.tx_ppp, | 418 | priv->prof->tx_ppp, |
| 416 | mdev->profile.rx_pause, | 419 | priv->prof->rx_pause, |
| 417 | mdev->profile.rx_ppp); | 420 | priv->prof->rx_ppp); |
| 418 | if (err) | 421 | if (err) |
| 419 | mlx4_err(mdev, "Failed setting pause params to\n"); | 422 | mlx4_err(mdev, "Failed setting pause params to\n"); |
| 420 | 423 | ||
| @@ -425,10 +428,9 @@ static void mlx4_en_get_pauseparam(struct net_device *dev, | |||
| 425 | struct ethtool_pauseparam *pause) | 428 | struct ethtool_pauseparam *pause) |
| 426 | { | 429 | { |
| 427 | struct mlx4_en_priv *priv = netdev_priv(dev); | 430 | struct mlx4_en_priv *priv = netdev_priv(dev); |
| 428 | struct mlx4_en_dev *mdev = priv->mdev; | ||
| 429 | 431 | ||
| 430 | pause->tx_pause = mdev->profile.tx_pause; | 432 | pause->tx_pause = priv->prof->tx_pause; |
| 431 | pause->rx_pause = mdev->profile.rx_pause; | 433 | pause->rx_pause = priv->prof->rx_pause; |
| 432 | } | 434 | } |
| 433 | 435 | ||
| 434 | static void mlx4_en_get_ringparam(struct net_device *dev, | 436 | static void mlx4_en_get_ringparam(struct net_device *dev, |
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index fa431fad0eec..56a2e213fe62 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h | |||
| @@ -87,6 +87,9 @@ enum { | |||
| 87 | 87 | ||
| 88 | #ifdef CONFIG_MLX4_DEBUG | 88 | #ifdef CONFIG_MLX4_DEBUG |
| 89 | extern int mlx4_debug_level; | 89 | extern int mlx4_debug_level; |
| 90 | #else /* CONFIG_MLX4_DEBUG */ | ||
| 91 | #define mlx4_debug_level (0) | ||
| 92 | #endif /* CONFIG_MLX4_DEBUG */ | ||
| 90 | 93 | ||
| 91 | #define mlx4_dbg(mdev, format, arg...) \ | 94 | #define mlx4_dbg(mdev, format, arg...) \ |
| 92 | do { \ | 95 | do { \ |
| @@ -94,12 +97,6 @@ extern int mlx4_debug_level; | |||
| 94 | dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \ | 97 | dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \ |
| 95 | } while (0) | 98 | } while (0) |
| 96 | 99 | ||
| 97 | #else /* CONFIG_MLX4_DEBUG */ | ||
| 98 | |||
| 99 | #define mlx4_dbg(mdev, format, arg...) do { (void) mdev; } while (0) | ||
| 100 | |||
| 101 | #endif /* CONFIG_MLX4_DEBUG */ | ||
| 102 | |||
| 103 | #define mlx4_err(mdev, format, arg...) \ | 100 | #define mlx4_err(mdev, format, arg...) \ |
| 104 | dev_err(&mdev->pdev->dev, format, ## arg) | 101 | dev_err(&mdev->pdev->dev, format, ## arg) |
| 105 | #define mlx4_info(mdev, format, arg...) \ | 102 | #define mlx4_info(mdev, format, arg...) \ |
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 11fb17c6e97b..98ddc0811f93 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h | |||
| @@ -322,6 +322,10 @@ struct mlx4_en_port_profile { | |||
| 322 | u32 rx_ring_num; | 322 | u32 rx_ring_num; |
| 323 | u32 tx_ring_size; | 323 | u32 tx_ring_size; |
| 324 | u32 rx_ring_size; | 324 | u32 rx_ring_size; |
| 325 | u8 rx_pause; | ||
| 326 | u8 rx_ppp; | ||
| 327 | u8 tx_pause; | ||
| 328 | u8 tx_ppp; | ||
| 325 | }; | 329 | }; |
| 326 | 330 | ||
| 327 | struct mlx4_en_profile { | 331 | struct mlx4_en_profile { |
| @@ -333,10 +337,6 @@ struct mlx4_en_profile { | |||
| 333 | int rx_moder_cnt; | 337 | int rx_moder_cnt; |
| 334 | int rx_moder_time; | 338 | int rx_moder_time; |
| 335 | int auto_moder; | 339 | int auto_moder; |
| 336 | u8 rx_pause; | ||
| 337 | u8 rx_ppp; | ||
| 338 | u8 tx_pause; | ||
| 339 | u8 tx_ppp; | ||
| 340 | u8 no_reset; | 340 | u8 no_reset; |
| 341 | struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1]; | 341 | struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1]; |
| 342 | }; | 342 | }; |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index a5f428bcc0eb..b37867097308 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
| @@ -75,7 +75,7 @@ | |||
| 75 | #include "myri10ge_mcp.h" | 75 | #include "myri10ge_mcp.h" |
| 76 | #include "myri10ge_mcp_gen_header.h" | 76 | #include "myri10ge_mcp_gen_header.h" |
| 77 | 77 | ||
| 78 | #define MYRI10GE_VERSION_STR "1.4.3-1.375" | 78 | #define MYRI10GE_VERSION_STR "1.4.3-1.378" |
| 79 | 79 | ||
| 80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); | 80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); |
| 81 | MODULE_AUTHOR("Maintainer: help@myri.com"); | 81 | MODULE_AUTHOR("Maintainer: help@myri.com"); |
| @@ -1393,6 +1393,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index) | |||
| 1393 | if (tx->req == tx->done) { | 1393 | if (tx->req == tx->done) { |
| 1394 | tx->queue_active = 0; | 1394 | tx->queue_active = 0; |
| 1395 | put_be32(htonl(1), tx->send_stop); | 1395 | put_be32(htonl(1), tx->send_stop); |
| 1396 | mb(); | ||
| 1396 | mmiowb(); | 1397 | mmiowb(); |
| 1397 | } | 1398 | } |
| 1398 | __netif_tx_unlock(dev_queue); | 1399 | __netif_tx_unlock(dev_queue); |
| @@ -2865,6 +2866,7 @@ again: | |||
| 2865 | if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) { | 2866 | if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) { |
| 2866 | tx->queue_active = 1; | 2867 | tx->queue_active = 1; |
| 2867 | put_be32(htonl(1), tx->send_go); | 2868 | put_be32(htonl(1), tx->send_go); |
| 2869 | mb(); | ||
| 2868 | mmiowb(); | 2870 | mmiowb(); |
| 2869 | } | 2871 | } |
| 2870 | tx->pkt_start++; | 2872 | tx->pkt_start++; |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 9acb5d70a3ae..1b6f548c4411 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
| @@ -33,8 +33,8 @@ | |||
| 33 | 33 | ||
| 34 | #define DRV_MODULE_NAME "niu" | 34 | #define DRV_MODULE_NAME "niu" |
| 35 | #define PFX DRV_MODULE_NAME ": " | 35 | #define PFX DRV_MODULE_NAME ": " |
| 36 | #define DRV_MODULE_VERSION "0.9" | 36 | #define DRV_MODULE_VERSION "1.0" |
| 37 | #define DRV_MODULE_RELDATE "May 4, 2008" | 37 | #define DRV_MODULE_RELDATE "Nov 14, 2008" |
| 38 | 38 | ||
| 39 | static char version[] __devinitdata = | 39 | static char version[] __devinitdata = |
| 40 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 40 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
| @@ -51,8 +51,7 @@ MODULE_VERSION(DRV_MODULE_VERSION); | |||
| 51 | #ifndef readq | 51 | #ifndef readq |
| 52 | static u64 readq(void __iomem *reg) | 52 | static u64 readq(void __iomem *reg) |
| 53 | { | 53 | { |
| 54 | return (((u64)readl(reg + 0x4UL) << 32) | | 54 | return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32); |
| 55 | (u64)readl(reg)); | ||
| 56 | } | 55 | } |
| 57 | 56 | ||
| 58 | static void writeq(u64 val, void __iomem *reg) | 57 | static void writeq(u64 val, void __iomem *reg) |
| @@ -407,7 +406,7 @@ static int esr2_set_rx_cfg(struct niu *np, unsigned long channel, u32 val) | |||
| 407 | } | 406 | } |
| 408 | 407 | ||
| 409 | /* Mode is always 10G fiber. */ | 408 | /* Mode is always 10G fiber. */ |
| 410 | static int serdes_init_niu(struct niu *np) | 409 | static int serdes_init_niu_10g_fiber(struct niu *np) |
| 411 | { | 410 | { |
| 412 | struct niu_link_config *lp = &np->link_config; | 411 | struct niu_link_config *lp = &np->link_config; |
| 413 | u32 tx_cfg, rx_cfg; | 412 | u32 tx_cfg, rx_cfg; |
| @@ -444,6 +443,223 @@ static int serdes_init_niu(struct niu *np) | |||
| 444 | return 0; | 443 | return 0; |
| 445 | } | 444 | } |
| 446 | 445 | ||
| 446 | static int serdes_init_niu_1g_serdes(struct niu *np) | ||
| 447 | { | ||
| 448 | struct niu_link_config *lp = &np->link_config; | ||
| 449 | u16 pll_cfg, pll_sts; | ||
| 450 | int max_retry = 100; | ||
| 451 | u64 sig, mask, val; | ||
| 452 | u32 tx_cfg, rx_cfg; | ||
| 453 | unsigned long i; | ||
| 454 | int err; | ||
| 455 | |||
| 456 | tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV | | ||
| 457 | PLL_TX_CFG_RATE_HALF); | ||
| 458 | rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT | | ||
| 459 | PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH | | ||
| 460 | PLL_RX_CFG_RATE_HALF); | ||
| 461 | |||
| 462 | if (np->port == 0) | ||
| 463 | rx_cfg |= PLL_RX_CFG_EQ_LP_ADAPTIVE; | ||
| 464 | |||
| 465 | if (lp->loopback_mode == LOOPBACK_PHY) { | ||
| 466 | u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS; | ||
| 467 | |||
| 468 | mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 469 | ESR2_TI_PLL_TEST_CFG_L, test_cfg); | ||
| 470 | |||
| 471 | tx_cfg |= PLL_TX_CFG_ENTEST; | ||
| 472 | rx_cfg |= PLL_RX_CFG_ENTEST; | ||
| 473 | } | ||
| 474 | |||
| 475 | /* Initialize PLL for 1G */ | ||
| 476 | pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_8X); | ||
| 477 | |||
| 478 | err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 479 | ESR2_TI_PLL_CFG_L, pll_cfg); | ||
| 480 | if (err) { | ||
| 481 | dev_err(np->device, PFX "NIU Port %d " | ||
| 482 | "serdes_init_niu_1g_serdes: " | ||
| 483 | "mdio write to ESR2_TI_PLL_CFG_L failed", np->port); | ||
| 484 | return err; | ||
| 485 | } | ||
| 486 | |||
| 487 | pll_sts = PLL_CFG_ENPLL; | ||
| 488 | |||
| 489 | err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 490 | ESR2_TI_PLL_STS_L, pll_sts); | ||
| 491 | if (err) { | ||
| 492 | dev_err(np->device, PFX "NIU Port %d " | ||
| 493 | "serdes_init_niu_1g_serdes: " | ||
| 494 | "mdio write to ESR2_TI_PLL_STS_L failed", np->port); | ||
| 495 | return err; | ||
| 496 | } | ||
| 497 | |||
| 498 | udelay(200); | ||
| 499 | |||
| 500 | /* Initialize all 4 lanes of the SERDES. */ | ||
| 501 | for (i = 0; i < 4; i++) { | ||
| 502 | err = esr2_set_tx_cfg(np, i, tx_cfg); | ||
| 503 | if (err) | ||
| 504 | return err; | ||
| 505 | } | ||
| 506 | |||
| 507 | for (i = 0; i < 4; i++) { | ||
| 508 | err = esr2_set_rx_cfg(np, i, rx_cfg); | ||
| 509 | if (err) | ||
| 510 | return err; | ||
| 511 | } | ||
| 512 | |||
| 513 | switch (np->port) { | ||
| 514 | case 0: | ||
| 515 | val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0); | ||
| 516 | mask = val; | ||
| 517 | break; | ||
| 518 | |||
| 519 | case 1: | ||
| 520 | val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1); | ||
| 521 | mask = val; | ||
| 522 | break; | ||
| 523 | |||
| 524 | default: | ||
| 525 | return -EINVAL; | ||
| 526 | } | ||
| 527 | |||
| 528 | while (max_retry--) { | ||
| 529 | sig = nr64(ESR_INT_SIGNALS); | ||
| 530 | if ((sig & mask) == val) | ||
| 531 | break; | ||
| 532 | |||
| 533 | mdelay(500); | ||
| 534 | } | ||
| 535 | |||
| 536 | if ((sig & mask) != val) { | ||
| 537 | dev_err(np->device, PFX "Port %u signal bits [%08x] are not " | ||
| 538 | "[%08x]\n", np->port, (int) (sig & mask), (int) val); | ||
| 539 | return -ENODEV; | ||
| 540 | } | ||
| 541 | |||
| 542 | return 0; | ||
| 543 | } | ||
| 544 | |||
| 545 | static int serdes_init_niu_10g_serdes(struct niu *np) | ||
| 546 | { | ||
| 547 | struct niu_link_config *lp = &np->link_config; | ||
| 548 | u32 tx_cfg, rx_cfg, pll_cfg, pll_sts; | ||
| 549 | int max_retry = 100; | ||
| 550 | u64 sig, mask, val; | ||
| 551 | unsigned long i; | ||
| 552 | int err; | ||
| 553 | |||
| 554 | tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV); | ||
| 555 | rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT | | ||
| 556 | PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH | | ||
| 557 | PLL_RX_CFG_EQ_LP_ADAPTIVE); | ||
| 558 | |||
| 559 | if (lp->loopback_mode == LOOPBACK_PHY) { | ||
| 560 | u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS; | ||
| 561 | |||
| 562 | mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 563 | ESR2_TI_PLL_TEST_CFG_L, test_cfg); | ||
| 564 | |||
| 565 | tx_cfg |= PLL_TX_CFG_ENTEST; | ||
| 566 | rx_cfg |= PLL_RX_CFG_ENTEST; | ||
| 567 | } | ||
| 568 | |||
| 569 | /* Initialize PLL for 10G */ | ||
| 570 | pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_10X); | ||
| 571 | |||
| 572 | err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 573 | ESR2_TI_PLL_CFG_L, pll_cfg & 0xffff); | ||
| 574 | if (err) { | ||
| 575 | dev_err(np->device, PFX "NIU Port %d " | ||
| 576 | "serdes_init_niu_10g_serdes: " | ||
| 577 | "mdio write to ESR2_TI_PLL_CFG_L failed", np->port); | ||
| 578 | return err; | ||
| 579 | } | ||
| 580 | |||
| 581 | pll_sts = PLL_CFG_ENPLL; | ||
| 582 | |||
| 583 | err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 584 | ESR2_TI_PLL_STS_L, pll_sts & 0xffff); | ||
| 585 | if (err) { | ||
| 586 | dev_err(np->device, PFX "NIU Port %d " | ||
| 587 | "serdes_init_niu_10g_serdes: " | ||
| 588 | "mdio write to ESR2_TI_PLL_STS_L failed", np->port); | ||
| 589 | return err; | ||
| 590 | } | ||
| 591 | |||
| 592 | udelay(200); | ||
| 593 | |||
| 594 | /* Initialize all 4 lanes of the SERDES. */ | ||
| 595 | for (i = 0; i < 4; i++) { | ||
| 596 | err = esr2_set_tx_cfg(np, i, tx_cfg); | ||
| 597 | if (err) | ||
| 598 | return err; | ||
| 599 | } | ||
| 600 | |||
| 601 | for (i = 0; i < 4; i++) { | ||
| 602 | err = esr2_set_rx_cfg(np, i, rx_cfg); | ||
| 603 | if (err) | ||
| 604 | return err; | ||
| 605 | } | ||
| 606 | |||
| 607 | /* check if serdes is ready */ | ||
| 608 | |||
| 609 | switch (np->port) { | ||
| 610 | case 0: | ||
| 611 | mask = ESR_INT_SIGNALS_P0_BITS; | ||
| 612 | val = (ESR_INT_SRDY0_P0 | | ||
| 613 | ESR_INT_DET0_P0 | | ||
| 614 | ESR_INT_XSRDY_P0 | | ||
| 615 | ESR_INT_XDP_P0_CH3 | | ||
| 616 | ESR_INT_XDP_P0_CH2 | | ||
| 617 | ESR_INT_XDP_P0_CH1 | | ||
| 618 | ESR_INT_XDP_P0_CH0); | ||
| 619 | break; | ||
| 620 | |||
| 621 | case 1: | ||
| 622 | mask = ESR_INT_SIGNALS_P1_BITS; | ||
| 623 | val = (ESR_INT_SRDY0_P1 | | ||
| 624 | ESR_INT_DET0_P1 | | ||
| 625 | ESR_INT_XSRDY_P1 | | ||
| 626 | ESR_INT_XDP_P1_CH3 | | ||
| 627 | ESR_INT_XDP_P1_CH2 | | ||
| 628 | ESR_INT_XDP_P1_CH1 | | ||
| 629 | ESR_INT_XDP_P1_CH0); | ||
| 630 | break; | ||
| 631 | |||
| 632 | default: | ||
| 633 | return -EINVAL; | ||
| 634 | } | ||
| 635 | |||
| 636 | while (max_retry--) { | ||
| 637 | sig = nr64(ESR_INT_SIGNALS); | ||
| 638 | if ((sig & mask) == val) | ||
| 639 | break; | ||
| 640 | |||
| 641 | mdelay(500); | ||
| 642 | } | ||
| 643 | |||
| 644 | if ((sig & mask) != val) { | ||
| 645 | pr_info(PFX "NIU Port %u signal bits [%08x] are not " | ||
| 646 | "[%08x] for 10G...trying 1G\n", | ||
| 647 | np->port, (int) (sig & mask), (int) val); | ||
| 648 | |||
| 649 | /* 10G failed, try initializing at 1G */ | ||
| 650 | err = serdes_init_niu_1g_serdes(np); | ||
| 651 | if (!err) { | ||
| 652 | np->flags &= ~NIU_FLAGS_10G; | ||
| 653 | np->mac_xcvr = MAC_XCVR_PCS; | ||
| 654 | } else { | ||
| 655 | dev_err(np->device, PFX "Port %u 10G/1G SERDES " | ||
| 656 | "Link Failed \n", np->port); | ||
| 657 | return -ENODEV; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | |||
| 447 | static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val) | 663 | static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val) |
| 448 | { | 664 | { |
| 449 | int err; | 665 | int err; |
| @@ -1955,13 +2171,23 @@ static const struct niu_phy_ops phy_ops_10g_serdes = { | |||
| 1955 | .link_status = link_status_10g_serdes, | 2171 | .link_status = link_status_10g_serdes, |
| 1956 | }; | 2172 | }; |
| 1957 | 2173 | ||
| 2174 | static const struct niu_phy_ops phy_ops_10g_serdes_niu = { | ||
| 2175 | .serdes_init = serdes_init_niu_10g_serdes, | ||
| 2176 | .link_status = link_status_10g_serdes, | ||
| 2177 | }; | ||
| 2178 | |||
| 2179 | static const struct niu_phy_ops phy_ops_1g_serdes_niu = { | ||
| 2180 | .serdes_init = serdes_init_niu_1g_serdes, | ||
| 2181 | .link_status = link_status_1g_serdes, | ||
| 2182 | }; | ||
| 2183 | |||
| 1958 | static const struct niu_phy_ops phy_ops_1g_rgmii = { | 2184 | static const struct niu_phy_ops phy_ops_1g_rgmii = { |
| 1959 | .xcvr_init = xcvr_init_1g_rgmii, | 2185 | .xcvr_init = xcvr_init_1g_rgmii, |
| 1960 | .link_status = link_status_1g_rgmii, | 2186 | .link_status = link_status_1g_rgmii, |
| 1961 | }; | 2187 | }; |
| 1962 | 2188 | ||
| 1963 | static const struct niu_phy_ops phy_ops_10g_fiber_niu = { | 2189 | static const struct niu_phy_ops phy_ops_10g_fiber_niu = { |
| 1964 | .serdes_init = serdes_init_niu, | 2190 | .serdes_init = serdes_init_niu_10g_fiber, |
| 1965 | .xcvr_init = xcvr_init_10g, | 2191 | .xcvr_init = xcvr_init_10g, |
| 1966 | .link_status = link_status_10g, | 2192 | .link_status = link_status_10g, |
| 1967 | }; | 2193 | }; |
| @@ -1999,11 +2225,21 @@ struct niu_phy_template { | |||
| 1999 | u32 phy_addr_base; | 2225 | u32 phy_addr_base; |
| 2000 | }; | 2226 | }; |
| 2001 | 2227 | ||
| 2002 | static const struct niu_phy_template phy_template_niu = { | 2228 | static const struct niu_phy_template phy_template_niu_10g_fiber = { |
| 2003 | .ops = &phy_ops_10g_fiber_niu, | 2229 | .ops = &phy_ops_10g_fiber_niu, |
| 2004 | .phy_addr_base = 16, | 2230 | .phy_addr_base = 16, |
| 2005 | }; | 2231 | }; |
| 2006 | 2232 | ||
| 2233 | static const struct niu_phy_template phy_template_niu_10g_serdes = { | ||
| 2234 | .ops = &phy_ops_10g_serdes_niu, | ||
| 2235 | .phy_addr_base = 0, | ||
| 2236 | }; | ||
| 2237 | |||
| 2238 | static const struct niu_phy_template phy_template_niu_1g_serdes = { | ||
| 2239 | .ops = &phy_ops_1g_serdes_niu, | ||
| 2240 | .phy_addr_base = 0, | ||
| 2241 | }; | ||
| 2242 | |||
| 2007 | static const struct niu_phy_template phy_template_10g_fiber = { | 2243 | static const struct niu_phy_template phy_template_10g_fiber = { |
| 2008 | .ops = &phy_ops_10g_fiber, | 2244 | .ops = &phy_ops_10g_fiber, |
| 2009 | .phy_addr_base = 8, | 2245 | .phy_addr_base = 8, |
| @@ -2183,8 +2419,25 @@ static int niu_determine_phy_disposition(struct niu *np) | |||
| 2183 | u32 phy_addr_off = 0; | 2419 | u32 phy_addr_off = 0; |
| 2184 | 2420 | ||
| 2185 | if (plat_type == PLAT_TYPE_NIU) { | 2421 | if (plat_type == PLAT_TYPE_NIU) { |
| 2186 | tp = &phy_template_niu; | 2422 | switch (np->flags & |
| 2187 | phy_addr_off += np->port; | 2423 | (NIU_FLAGS_10G | |
| 2424 | NIU_FLAGS_FIBER | | ||
| 2425 | NIU_FLAGS_XCVR_SERDES)) { | ||
| 2426 | case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES: | ||
| 2427 | /* 10G Serdes */ | ||
| 2428 | tp = &phy_template_niu_10g_serdes; | ||
| 2429 | break; | ||
| 2430 | case NIU_FLAGS_XCVR_SERDES: | ||
| 2431 | /* 1G Serdes */ | ||
| 2432 | tp = &phy_template_niu_1g_serdes; | ||
| 2433 | break; | ||
| 2434 | case NIU_FLAGS_10G | NIU_FLAGS_FIBER: | ||
| 2435 | /* 10G Fiber */ | ||
| 2436 | default: | ||
| 2437 | tp = &phy_template_niu_10g_fiber; | ||
| 2438 | phy_addr_off += np->port; | ||
| 2439 | break; | ||
| 2440 | } | ||
| 2188 | } else { | 2441 | } else { |
| 2189 | switch (np->flags & | 2442 | switch (np->flags & |
| 2190 | (NIU_FLAGS_10G | | 2443 | (NIU_FLAGS_10G | |
| @@ -7214,6 +7467,12 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np, | |||
| 7214 | np->flags |= NIU_FLAGS_10G; | 7467 | np->flags |= NIU_FLAGS_10G; |
| 7215 | np->flags &= ~NIU_FLAGS_FIBER; | 7468 | np->flags &= ~NIU_FLAGS_FIBER; |
| 7216 | np->mac_xcvr = MAC_XCVR_XPCS; | 7469 | np->mac_xcvr = MAC_XCVR_XPCS; |
| 7470 | } else if (!strcmp(phy_prop, "xgsd") || !strcmp(phy_prop, "gsd")) { | ||
| 7471 | /* 10G Serdes or 1G Serdes, default to 10G */ | ||
| 7472 | np->flags |= NIU_FLAGS_10G; | ||
| 7473 | np->flags &= ~NIU_FLAGS_FIBER; | ||
| 7474 | np->flags |= NIU_FLAGS_XCVR_SERDES; | ||
| 7475 | np->mac_xcvr = MAC_XCVR_XPCS; | ||
| 7217 | } else { | 7476 | } else { |
| 7218 | return -EINVAL; | 7477 | return -EINVAL; |
| 7219 | } | 7478 | } |
| @@ -7742,6 +8001,8 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) | |||
| 7742 | u32 val; | 8001 | u32 val; |
| 7743 | int err; | 8002 | int err; |
| 7744 | 8003 | ||
| 8004 | num_10g = num_1g = 0; | ||
| 8005 | |||
| 7745 | if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) || | 8006 | if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) || |
| 7746 | !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) { | 8007 | !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) { |
| 7747 | num_10g = 0; | 8008 | num_10g = 0; |
| @@ -7758,6 +8019,16 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) | |||
| 7758 | parent->num_ports = 2; | 8019 | parent->num_ports = 2; |
| 7759 | val = (phy_encode(PORT_TYPE_10G, 0) | | 8020 | val = (phy_encode(PORT_TYPE_10G, 0) | |
| 7760 | phy_encode(PORT_TYPE_10G, 1)); | 8021 | phy_encode(PORT_TYPE_10G, 1)); |
| 8022 | } else if ((np->flags & NIU_FLAGS_XCVR_SERDES) && | ||
| 8023 | (parent->plat_type == PLAT_TYPE_NIU)) { | ||
| 8024 | /* this is the Monza case */ | ||
| 8025 | if (np->flags & NIU_FLAGS_10G) { | ||
| 8026 | val = (phy_encode(PORT_TYPE_10G, 0) | | ||
| 8027 | phy_encode(PORT_TYPE_10G, 1)); | ||
| 8028 | } else { | ||
| 8029 | val = (phy_encode(PORT_TYPE_1G, 0) | | ||
| 8030 | phy_encode(PORT_TYPE_1G, 1)); | ||
| 8031 | } | ||
| 7761 | } else { | 8032 | } else { |
| 7762 | err = fill_phy_probe_info(np, parent, info); | 8033 | err = fill_phy_probe_info(np, parent, info); |
| 7763 | if (err) | 8034 | if (err) |
| @@ -8657,7 +8928,9 @@ static void __devinit niu_device_announce(struct niu *np) | |||
| 8657 | dev->name, | 8928 | dev->name, |
| 8658 | (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"), | 8929 | (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"), |
| 8659 | (np->flags & NIU_FLAGS_10G ? "10G" : "1G"), | 8930 | (np->flags & NIU_FLAGS_10G ? "10G" : "1G"), |
| 8660 | (np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"), | 8931 | (np->flags & NIU_FLAGS_FIBER ? "FIBER" : |
| 8932 | (np->flags & NIU_FLAGS_XCVR_SERDES ? "SERDES" : | ||
| 8933 | "COPPER")), | ||
| 8661 | (np->mac_xcvr == MAC_XCVR_MII ? "MII" : | 8934 | (np->mac_xcvr == MAC_XCVR_MII ? "MII" : |
| 8662 | (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")), | 8935 | (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")), |
| 8663 | np->vpd.phy_type); | 8936 | np->vpd.phy_type); |
diff --git a/drivers/net/niu.h b/drivers/net/niu.h index c6fa883daa22..180ca8ae93de 100644 --- a/drivers/net/niu.h +++ b/drivers/net/niu.h | |||
| @@ -1048,6 +1048,13 @@ | |||
| 1048 | #define PLL_CFG_LD_SHIFT 8 | 1048 | #define PLL_CFG_LD_SHIFT 8 |
| 1049 | #define PLL_CFG_MPY 0x0000001e | 1049 | #define PLL_CFG_MPY 0x0000001e |
| 1050 | #define PLL_CFG_MPY_SHIFT 1 | 1050 | #define PLL_CFG_MPY_SHIFT 1 |
| 1051 | #define PLL_CFG_MPY_4X 0x0 | ||
| 1052 | #define PLL_CFG_MPY_5X 0x00000002 | ||
| 1053 | #define PLL_CFG_MPY_6X 0x00000004 | ||
| 1054 | #define PLL_CFG_MPY_8X 0x00000008 | ||
| 1055 | #define PLL_CFG_MPY_10X 0x0000000a | ||
| 1056 | #define PLL_CFG_MPY_12X 0x0000000c | ||
| 1057 | #define PLL_CFG_MPY_12P5X 0x0000000e | ||
| 1051 | #define PLL_CFG_ENPLL 0x00000001 | 1058 | #define PLL_CFG_ENPLL 0x00000001 |
| 1052 | 1059 | ||
| 1053 | #define ESR2_TI_PLL_STS_L (ESR2_BASE + 0x002) | 1060 | #define ESR2_TI_PLL_STS_L (ESR2_BASE + 0x002) |
| @@ -1093,6 +1100,9 @@ | |||
| 1093 | #define PLL_TX_CFG_INVPAIR 0x00000080 | 1100 | #define PLL_TX_CFG_INVPAIR 0x00000080 |
| 1094 | #define PLL_TX_CFG_RATE 0x00000060 | 1101 | #define PLL_TX_CFG_RATE 0x00000060 |
| 1095 | #define PLL_TX_CFG_RATE_SHIFT 5 | 1102 | #define PLL_TX_CFG_RATE_SHIFT 5 |
| 1103 | #define PLL_TX_CFG_RATE_FULL 0x0 | ||
| 1104 | #define PLL_TX_CFG_RATE_HALF 0x20 | ||
| 1105 | #define PLL_TX_CFG_RATE_QUAD 0x40 | ||
| 1096 | #define PLL_TX_CFG_BUSWIDTH 0x0000001c | 1106 | #define PLL_TX_CFG_BUSWIDTH 0x0000001c |
| 1097 | #define PLL_TX_CFG_BUSWIDTH_SHIFT 2 | 1107 | #define PLL_TX_CFG_BUSWIDTH_SHIFT 2 |
| 1098 | #define PLL_TX_CFG_ENTEST 0x00000002 | 1108 | #define PLL_TX_CFG_ENTEST 0x00000002 |
| @@ -1132,6 +1142,9 @@ | |||
| 1132 | #define PLL_RX_CFG_INVPAIR 0x00000080 | 1142 | #define PLL_RX_CFG_INVPAIR 0x00000080 |
| 1133 | #define PLL_RX_CFG_RATE 0x00000060 | 1143 | #define PLL_RX_CFG_RATE 0x00000060 |
| 1134 | #define PLL_RX_CFG_RATE_SHIFT 5 | 1144 | #define PLL_RX_CFG_RATE_SHIFT 5 |
| 1145 | #define PLL_RX_CFG_RATE_FULL 0x0 | ||
| 1146 | #define PLL_RX_CFG_RATE_HALF 0x20 | ||
| 1147 | #define PLL_RX_CFG_RATE_QUAD 0x40 | ||
| 1135 | #define PLL_RX_CFG_BUSWIDTH 0x0000001c | 1148 | #define PLL_RX_CFG_BUSWIDTH 0x0000001c |
| 1136 | #define PLL_RX_CFG_BUSWIDTH_SHIFT 2 | 1149 | #define PLL_RX_CFG_BUSWIDTH_SHIFT 2 |
| 1137 | #define PLL_RX_CFG_ENTEST 0x00000002 | 1150 | #define PLL_RX_CFG_ENTEST 0x00000002 |
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 4aa547947040..eb6411c4694f 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c | |||
| @@ -227,6 +227,59 @@ static int m88e1111_config_init(struct phy_device *phydev) | |||
| 227 | return 0; | 227 | return 0; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | static int m88e1118_config_aneg(struct phy_device *phydev) | ||
| 231 | { | ||
| 232 | int err; | ||
| 233 | |||
| 234 | err = phy_write(phydev, MII_BMCR, BMCR_RESET); | ||
| 235 | if (err < 0) | ||
| 236 | return err; | ||
| 237 | |||
| 238 | err = phy_write(phydev, MII_M1011_PHY_SCR, | ||
| 239 | MII_M1011_PHY_SCR_AUTO_CROSS); | ||
| 240 | if (err < 0) | ||
| 241 | return err; | ||
| 242 | |||
| 243 | err = genphy_config_aneg(phydev); | ||
| 244 | return 0; | ||
| 245 | } | ||
| 246 | |||
| 247 | static int m88e1118_config_init(struct phy_device *phydev) | ||
| 248 | { | ||
| 249 | int err; | ||
| 250 | |||
| 251 | /* Change address */ | ||
| 252 | err = phy_write(phydev, 0x16, 0x0002); | ||
| 253 | if (err < 0) | ||
| 254 | return err; | ||
| 255 | |||
| 256 | /* Enable 1000 Mbit */ | ||
| 257 | err = phy_write(phydev, 0x15, 0x1070); | ||
| 258 | if (err < 0) | ||
| 259 | return err; | ||
| 260 | |||
| 261 | /* Change address */ | ||
| 262 | err = phy_write(phydev, 0x16, 0x0003); | ||
| 263 | if (err < 0) | ||
| 264 | return err; | ||
| 265 | |||
| 266 | /* Adjust LED Control */ | ||
| 267 | err = phy_write(phydev, 0x10, 0x021e); | ||
| 268 | if (err < 0) | ||
| 269 | return err; | ||
| 270 | |||
| 271 | /* Reset address */ | ||
| 272 | err = phy_write(phydev, 0x16, 0x0); | ||
| 273 | if (err < 0) | ||
| 274 | return err; | ||
| 275 | |||
| 276 | err = phy_write(phydev, MII_BMCR, BMCR_RESET); | ||
| 277 | if (err < 0) | ||
| 278 | return err; | ||
| 279 | |||
| 280 | return 0; | ||
| 281 | } | ||
| 282 | |||
| 230 | static int m88e1145_config_init(struct phy_device *phydev) | 283 | static int m88e1145_config_init(struct phy_device *phydev) |
| 231 | { | 284 | { |
| 232 | int err; | 285 | int err; |
| @@ -416,6 +469,19 @@ static struct phy_driver marvell_drivers[] = { | |||
| 416 | .driver = { .owner = THIS_MODULE }, | 469 | .driver = { .owner = THIS_MODULE }, |
| 417 | }, | 470 | }, |
| 418 | { | 471 | { |
| 472 | .phy_id = 0x01410e10, | ||
| 473 | .phy_id_mask = 0xfffffff0, | ||
| 474 | .name = "Marvell 88E1118", | ||
| 475 | .features = PHY_GBIT_FEATURES, | ||
| 476 | .flags = PHY_HAS_INTERRUPT, | ||
| 477 | .config_init = &m88e1118_config_init, | ||
| 478 | .config_aneg = &m88e1118_config_aneg, | ||
| 479 | .read_status = &genphy_read_status, | ||
| 480 | .ack_interrupt = &marvell_ack_interrupt, | ||
| 481 | .config_intr = &marvell_config_intr, | ||
| 482 | .driver = {.owner = THIS_MODULE,}, | ||
| 483 | }, | ||
| 484 | { | ||
| 419 | .phy_id = 0x01410cd0, | 485 | .phy_id = 0x01410cd0, |
| 420 | .phy_id_mask = 0xfffffff0, | 486 | .phy_id_mask = 0xfffffff0, |
| 421 | .name = "Marvell 88E1145", | 487 | .name = "Marvell 88E1145", |
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index d0ed1ef284a8..536bda1f428b 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
| @@ -136,7 +136,7 @@ void mdiobus_unregister(struct mii_bus *bus) | |||
| 136 | BUG_ON(bus->state != MDIOBUS_REGISTERED); | 136 | BUG_ON(bus->state != MDIOBUS_REGISTERED); |
| 137 | bus->state = MDIOBUS_UNREGISTERED; | 137 | bus->state = MDIOBUS_UNREGISTERED; |
| 138 | 138 | ||
| 139 | device_unregister(&bus->dev); | 139 | device_del(&bus->dev); |
| 140 | for (i = 0; i < PHY_MAX_ADDR; i++) { | 140 | for (i = 0; i < PHY_MAX_ADDR; i++) { |
| 141 | if (bus->phy_map[i]) | 141 | if (bus->phy_map[i]) |
| 142 | device_unregister(&bus->phy_map[i]->dev); | 142 | device_unregister(&bus->phy_map[i]->dev); |
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e11b03b2b25a..8fb1faca883a 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
| @@ -227,8 +227,8 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr) | |||
| 227 | if (r) | 227 | if (r) |
| 228 | return ERR_PTR(r); | 228 | return ERR_PTR(r); |
| 229 | 229 | ||
| 230 | /* If the phy_id is all Fs, there is no device there */ | 230 | /* If the phy_id is all Fs or all 0s, there is no device there */ |
| 231 | if (0xffffffff == phy_id) | 231 | if ((0xffff == phy_id) || (0x00 == phy_id)) |
| 232 | return NULL; | 232 | return NULL; |
| 233 | 233 | ||
| 234 | dev = phy_device_create(bus, addr, phy_id); | 234 | dev = phy_device_create(bus, addr, phy_id); |
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 3cdd07c45b6d..508452c02151 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c | |||
| @@ -1515,9 +1515,6 @@ static u32 ql_get_link_state(struct ql3_adapter *qdev) | |||
| 1515 | linkState = LS_UP; | 1515 | linkState = LS_UP; |
| 1516 | } else { | 1516 | } else { |
| 1517 | linkState = LS_DOWN; | 1517 | linkState = LS_DOWN; |
| 1518 | if (netif_msg_link(qdev)) | ||
| 1519 | printk(KERN_WARNING PFX | ||
| 1520 | "%s: Link is down.\n", qdev->ndev->name); | ||
| 1521 | } | 1518 | } |
| 1522 | return linkState; | 1519 | return linkState; |
| 1523 | } | 1520 | } |
| @@ -1581,10 +1578,6 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev) | |||
| 1581 | ql_mac_enable(qdev, 1); | 1578 | ql_mac_enable(qdev, 1); |
| 1582 | } | 1579 | } |
| 1583 | 1580 | ||
| 1584 | if (netif_msg_link(qdev)) | ||
| 1585 | printk(KERN_DEBUG PFX | ||
| 1586 | "%s: Change port_link_state LS_DOWN to LS_UP.\n", | ||
| 1587 | qdev->ndev->name); | ||
| 1588 | qdev->port_link_state = LS_UP; | 1581 | qdev->port_link_state = LS_UP; |
| 1589 | netif_start_queue(qdev->ndev); | 1582 | netif_start_queue(qdev->ndev); |
| 1590 | netif_carrier_on(qdev->ndev); | 1583 | netif_carrier_on(qdev->ndev); |
| @@ -1655,14 +1648,9 @@ static void ql_link_state_machine_work(struct work_struct *work) | |||
| 1655 | /* Fall Through */ | 1648 | /* Fall Through */ |
| 1656 | 1649 | ||
| 1657 | case LS_DOWN: | 1650 | case LS_DOWN: |
| 1658 | if (netif_msg_link(qdev)) | ||
| 1659 | printk(KERN_DEBUG PFX | ||
| 1660 | "%s: port_link_state = LS_DOWN.\n", | ||
| 1661 | qdev->ndev->name); | ||
| 1662 | if (curr_link_state == LS_UP) { | 1651 | if (curr_link_state == LS_UP) { |
| 1663 | if (netif_msg_link(qdev)) | 1652 | if (netif_msg_link(qdev)) |
| 1664 | printk(KERN_DEBUG PFX | 1653 | printk(KERN_INFO PFX "%s: Link is up.\n", |
| 1665 | "%s: curr_link_state = LS_UP.\n", | ||
| 1666 | qdev->ndev->name); | 1654 | qdev->ndev->name); |
| 1667 | if (ql_is_auto_neg_complete(qdev)) | 1655 | if (ql_is_auto_neg_complete(qdev)) |
| 1668 | ql_finish_auto_neg(qdev); | 1656 | ql_finish_auto_neg(qdev); |
| @@ -1670,6 +1658,7 @@ static void ql_link_state_machine_work(struct work_struct *work) | |||
| 1670 | if (qdev->port_link_state == LS_UP) | 1658 | if (qdev->port_link_state == LS_UP) |
| 1671 | ql_link_down_detect_clear(qdev); | 1659 | ql_link_down_detect_clear(qdev); |
| 1672 | 1660 | ||
| 1661 | qdev->port_link_state = LS_UP; | ||
| 1673 | } | 1662 | } |
| 1674 | break; | 1663 | break; |
| 1675 | 1664 | ||
| @@ -1678,12 +1667,14 @@ static void ql_link_state_machine_work(struct work_struct *work) | |||
| 1678 | * See if the link is currently down or went down and came | 1667 | * See if the link is currently down or went down and came |
| 1679 | * back up | 1668 | * back up |
| 1680 | */ | 1669 | */ |
| 1681 | if ((curr_link_state == LS_DOWN) || ql_link_down_detect(qdev)) { | 1670 | if (curr_link_state == LS_DOWN) { |
| 1682 | if (netif_msg_link(qdev)) | 1671 | if (netif_msg_link(qdev)) |
| 1683 | printk(KERN_INFO PFX "%s: Link is down.\n", | 1672 | printk(KERN_INFO PFX "%s: Link is down.\n", |
| 1684 | qdev->ndev->name); | 1673 | qdev->ndev->name); |
| 1685 | qdev->port_link_state = LS_DOWN; | 1674 | qdev->port_link_state = LS_DOWN; |
| 1686 | } | 1675 | } |
| 1676 | if (ql_link_down_detect(qdev)) | ||
| 1677 | qdev->port_link_state = LS_DOWN; | ||
| 1687 | break; | 1678 | break; |
| 1688 | } | 1679 | } |
| 1689 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); | 1680 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); |
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index fa98af58223e..cd0d0873d978 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
| @@ -174,8 +174,8 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = { | |||
| 174 | 174 | ||
| 175 | /* EEPROM range with gPXE configuration */ | 175 | /* EEPROM range with gPXE configuration */ |
| 176 | #define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB | 176 | #define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB |
| 177 | #define EFX_ETHTOOL_EEPROM_MIN 0x100U | 177 | #define EFX_ETHTOOL_EEPROM_MIN 0x800U |
| 178 | #define EFX_ETHTOOL_EEPROM_MAX 0x400U | 178 | #define EFX_ETHTOOL_EEPROM_MAX 0x1800U |
| 179 | 179 | ||
| 180 | /************************************************************************** | 180 | /************************************************************************** |
| 181 | * | 181 | * |
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 5051554ff05b..1f26ab0e7986 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c | |||
| @@ -2050,7 +2050,9 @@ err_out: | |||
| 2050 | */ | 2050 | */ |
| 2051 | static int smc911x_drv_probe(struct platform_device *pdev) | 2051 | static int smc911x_drv_probe(struct platform_device *pdev) |
| 2052 | { | 2052 | { |
| 2053 | #ifdef SMC_DYNAMIC_BUS_CONFIG | ||
| 2053 | struct smc911x_platdata *pd = pdev->dev.platform_data; | 2054 | struct smc911x_platdata *pd = pdev->dev.platform_data; |
| 2055 | #endif | ||
| 2054 | struct net_device *ndev; | 2056 | struct net_device *ndev; |
| 2055 | struct resource *res; | 2057 | struct resource *res; |
| 2056 | struct smc911x_local *lp; | 2058 | struct smc911x_local *lp; |
| @@ -2182,9 +2184,9 @@ static int smc911x_drv_resume(struct platform_device *dev) | |||
| 2182 | 2184 | ||
| 2183 | if (netif_running(ndev)) { | 2185 | if (netif_running(ndev)) { |
| 2184 | smc911x_reset(ndev); | 2186 | smc911x_reset(ndev); |
| 2185 | smc911x_enable(ndev); | ||
| 2186 | if (lp->phy_type != 0) | 2187 | if (lp->phy_type != 0) |
| 2187 | smc911x_phy_configure(&lp->phy_configure); | 2188 | smc911x_phy_configure(&lp->phy_configure); |
| 2189 | smc911x_enable(ndev); | ||
| 2188 | netif_device_attach(ndev); | 2190 | netif_device_attach(ndev); |
| 2189 | } | 2191 | } |
| 2190 | } | 2192 | } |
diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c index 85f38a6b6a49..68a7f5414133 100644 --- a/drivers/net/ucc_geth_ethtool.c +++ b/drivers/net/ucc_geth_ethtool.c | |||
| @@ -323,17 +323,17 @@ static void uec_get_ethtool_stats(struct net_device *netdev, | |||
| 323 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { | 323 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { |
| 324 | base = (u32 __iomem *)&ugeth->ug_regs->tx64; | 324 | base = (u32 __iomem *)&ugeth->ug_regs->tx64; |
| 325 | for (i = 0; i < UEC_HW_STATS_LEN; i++) | 325 | for (i = 0; i < UEC_HW_STATS_LEN; i++) |
| 326 | data[j++] = (u64)in_be32(&base[i]); | 326 | data[j++] = in_be32(&base[i]); |
| 327 | } | 327 | } |
| 328 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { | 328 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { |
| 329 | base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram; | 329 | base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram; |
| 330 | for (i = 0; i < UEC_TX_FW_STATS_LEN; i++) | 330 | for (i = 0; i < UEC_TX_FW_STATS_LEN; i++) |
| 331 | data[j++] = (u64)in_be32(&base[i]); | 331 | data[j++] = base ? in_be32(&base[i]) : 0; |
| 332 | } | 332 | } |
| 333 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { | 333 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { |
| 334 | base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram; | 334 | base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram; |
| 335 | for (i = 0; i < UEC_RX_FW_STATS_LEN; i++) | 335 | for (i = 0; i < UEC_RX_FW_STATS_LEN; i++) |
| 336 | data[j++] = (u64)in_be32(&base[i]); | 336 | data[j++] = base ? in_be32(&base[i]) : 0; |
| 337 | } | 337 | } |
| 338 | } | 338 | } |
| 339 | 339 | ||
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 37ecf845edfe..e12cdb4543b4 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
| @@ -1444,6 +1444,10 @@ static const struct usb_device_id products [] = { | |||
| 1444 | // Apple USB Ethernet Adapter | 1444 | // Apple USB Ethernet Adapter |
| 1445 | USB_DEVICE(0x05ac, 0x1402), | 1445 | USB_DEVICE(0x05ac, 0x1402), |
| 1446 | .driver_info = (unsigned long) &ax88772_info, | 1446 | .driver_info = (unsigned long) &ax88772_info, |
| 1447 | }, { | ||
| 1448 | // Cables-to-Go USB Ethernet Adapter | ||
| 1449 | USB_DEVICE(0x0b95, 0x772a), | ||
| 1450 | .driver_info = (unsigned long) &ax88772_info, | ||
| 1447 | }, | 1451 | }, |
| 1448 | { }, // END | 1452 | { }, // END |
| 1449 | }; | 1453 | }; |
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 1164c52e2c0a..8e90891f0e42 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
| @@ -2184,19 +2184,20 @@ static void hso_create_rfkill(struct hso_device *hso_dev, | |||
| 2184 | struct usb_interface *interface) | 2184 | struct usb_interface *interface) |
| 2185 | { | 2185 | { |
| 2186 | struct hso_net *hso_net = dev2net(hso_dev); | 2186 | struct hso_net *hso_net = dev2net(hso_dev); |
| 2187 | struct device *dev = hso_dev->dev; | 2187 | struct device *dev = &hso_net->net->dev; |
| 2188 | char *rfkn; | 2188 | char *rfkn; |
| 2189 | 2189 | ||
| 2190 | hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev, | 2190 | hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev, |
| 2191 | RFKILL_TYPE_WLAN); | 2191 | RFKILL_TYPE_WWAN); |
| 2192 | if (!hso_net->rfkill) { | 2192 | if (!hso_net->rfkill) { |
| 2193 | dev_err(dev, "%s - Out of memory", __func__); | 2193 | dev_err(dev, "%s - Out of memory\n", __func__); |
| 2194 | return; | 2194 | return; |
| 2195 | } | 2195 | } |
| 2196 | rfkn = kzalloc(20, GFP_KERNEL); | 2196 | rfkn = kzalloc(20, GFP_KERNEL); |
| 2197 | if (!rfkn) { | 2197 | if (!rfkn) { |
| 2198 | rfkill_free(hso_net->rfkill); | 2198 | rfkill_free(hso_net->rfkill); |
| 2199 | dev_err(dev, "%s - Out of memory", __func__); | 2199 | hso_net->rfkill = NULL; |
| 2200 | dev_err(dev, "%s - Out of memory\n", __func__); | ||
| 2200 | return; | 2201 | return; |
| 2201 | } | 2202 | } |
| 2202 | snprintf(rfkn, 20, "hso-%d", | 2203 | snprintf(rfkn, 20, "hso-%d", |
| @@ -2209,7 +2210,8 @@ static void hso_create_rfkill(struct hso_device *hso_dev, | |||
| 2209 | kfree(rfkn); | 2210 | kfree(rfkn); |
| 2210 | hso_net->rfkill->name = NULL; | 2211 | hso_net->rfkill->name = NULL; |
| 2211 | rfkill_free(hso_net->rfkill); | 2212 | rfkill_free(hso_net->rfkill); |
| 2212 | dev_err(dev, "%s - Failed to register rfkill", __func__); | 2213 | hso_net->rfkill = NULL; |
| 2214 | dev_err(dev, "%s - Failed to register rfkill\n", __func__); | ||
| 2213 | return; | 2215 | return; |
| 2214 | } | 2216 | } |
| 2215 | } | 2217 | } |
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 3590ea5a902d..11cb3e504e1c 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
| @@ -2296,7 +2296,7 @@ static void velocity_set_multi(struct net_device *dev) | |||
| 2296 | } | 2296 | } |
| 2297 | 2297 | ||
| 2298 | mac_set_cam_mask(regs, vptr->mCAMmask); | 2298 | mac_set_cam_mask(regs, vptr->mCAMmask); |
| 2299 | rx_mode = (RCR_AM | RCR_AB); | 2299 | rx_mode = RCR_AM | RCR_AB | RCR_AP; |
| 2300 | } | 2300 | } |
| 2301 | if (dev->mtu > 1500) | 2301 | if (dev->mtu > 1500) |
| 2302 | rx_mode |= RCR_AL; | 2302 | rx_mode |= RCR_AL; |
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index ffdf4876121b..a68f97c39359 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h | |||
| @@ -918,9 +918,12 @@ struct hostap_interface { | |||
| 918 | 918 | ||
| 919 | /* | 919 | /* |
| 920 | * TX meta data - stored in skb->cb buffer, so this must not be increased over | 920 | * TX meta data - stored in skb->cb buffer, so this must not be increased over |
| 921 | * the 40-byte limit | 921 | * the 48-byte limit. |
| 922 | * THE PADDING THIS STARTS WITH IS A HORRIBLE HACK THAT SHOULD NOT LIVE | ||
| 923 | * TO SEE THE DAY. | ||
| 922 | */ | 924 | */ |
| 923 | struct hostap_skb_tx_data { | 925 | struct hostap_skb_tx_data { |
| 926 | unsigned int __padding_for_default_qdiscs; | ||
| 924 | u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */ | 927 | u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */ |
| 925 | u8 rate; /* transmit rate */ | 928 | u8 rate; /* transmit rate */ |
| 926 | #define HOSTAP_TX_FLAGS_WDS BIT(0) | 929 | #define HOSTAP_TX_FLAGS_WDS BIT(0) |
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 431e3c78bf27..69eb0132593b 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c | |||
| @@ -48,6 +48,9 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { | |||
| 48 | {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, | 48 | {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, |
| 49 | /* Sitecom */ | 49 | /* Sitecom */ |
| 50 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, | 50 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, |
| 51 | {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, | ||
| 52 | /* Abocom */ | ||
| 53 | {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, | ||
| 51 | {} | 54 | {} |
| 52 | }; | 55 | }; |
| 53 | 56 | ||
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index b3a63edb6901..ae5ec76dca77 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
| @@ -63,7 +63,7 @@ static acpi_status acpi_run_osc(acpi_handle handle, | |||
| 63 | union acpi_object in_params[4]; | 63 | union acpi_object in_params[4]; |
| 64 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | 64 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; |
| 65 | union acpi_object *out_obj; | 65 | union acpi_object *out_obj; |
| 66 | u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE]; | 66 | u32 errors, flags = osc_args->capbuf[OSC_QUERY_TYPE]; |
| 67 | 67 | ||
| 68 | /* Setting up input parameters */ | 68 | /* Setting up input parameters */ |
| 69 | input.count = 4; | 69 | input.count = 4; |
| @@ -92,15 +92,16 @@ static acpi_status acpi_run_osc(acpi_handle handle, | |||
| 92 | status = AE_TYPE; | 92 | status = AE_TYPE; |
| 93 | goto out_kfree; | 93 | goto out_kfree; |
| 94 | } | 94 | } |
| 95 | osc_dw0 = *((u32 *)out_obj->buffer.pointer); | 95 | /* Need to ignore the bit0 in result code */ |
| 96 | if (osc_dw0) { | 96 | errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); |
| 97 | if (osc_dw0 & OSC_REQUEST_ERROR) | 97 | if (errors) { |
| 98 | if (errors & OSC_REQUEST_ERROR) | ||
| 98 | printk(KERN_DEBUG "_OSC request fails\n"); | 99 | printk(KERN_DEBUG "_OSC request fails\n"); |
| 99 | if (osc_dw0 & OSC_INVALID_UUID_ERROR) | 100 | if (errors & OSC_INVALID_UUID_ERROR) |
| 100 | printk(KERN_DEBUG "_OSC invalid UUID\n"); | 101 | printk(KERN_DEBUG "_OSC invalid UUID\n"); |
| 101 | if (osc_dw0 & OSC_INVALID_REVISION_ERROR) | 102 | if (errors & OSC_INVALID_REVISION_ERROR) |
| 102 | printk(KERN_DEBUG "_OSC invalid revision\n"); | 103 | printk(KERN_DEBUG "_OSC invalid revision\n"); |
| 103 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { | 104 | if (errors & OSC_CAPABILITIES_MASK_ERROR) { |
| 104 | if (flags & OSC_QUERY_ENABLE) | 105 | if (flags & OSC_QUERY_ENABLE) |
| 105 | goto out_success; | 106 | goto out_success; |
| 106 | printk(KERN_DEBUG "_OSC FW not grant req. control\n"); | 107 | printk(KERN_DEBUG "_OSC FW not grant req. control\n"); |
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index dcce9f5d8465..4a110b7b2673 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
| @@ -351,10 +351,11 @@ int verify_cis_cache(struct pcmcia_socket *s) | |||
| 351 | char *buf; | 351 | char *buf; |
| 352 | 352 | ||
| 353 | buf = kmalloc(256, GFP_KERNEL); | 353 | buf = kmalloc(256, GFP_KERNEL); |
| 354 | if (buf == NULL) | 354 | if (buf == NULL) { |
| 355 | dev_printk(KERN_WARNING, &s->dev, | 355 | dev_printk(KERN_WARNING, &s->dev, |
| 356 | "no memory for verifying CIS\n"); | 356 | "no memory for verifying CIS\n"); |
| 357 | return -ENOMEM; | 357 | return -ENOMEM; |
| 358 | } | ||
| 358 | list_for_each_entry(cis, &s->cis_cache, node) { | 359 | list_for_each_entry(cis, &s->cis_cache, node) { |
| 359 | int len = cis->len; | 360 | int len = cis->len; |
| 360 | 361 | ||
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index c68c5d338285..0660ad182589 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
| @@ -186,12 +186,6 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) | |||
| 186 | 186 | ||
| 187 | spin_lock_init(&socket->lock); | 187 | spin_lock_init(&socket->lock); |
| 188 | 188 | ||
| 189 | if (socket->resource_ops->init) { | ||
| 190 | ret = socket->resource_ops->init(socket); | ||
| 191 | if (ret) | ||
| 192 | return (ret); | ||
| 193 | } | ||
| 194 | |||
| 195 | /* try to obtain a socket number [yes, it gets ugly if we | 189 | /* try to obtain a socket number [yes, it gets ugly if we |
| 196 | * register more than 2^sizeof(unsigned int) pcmcia | 190 | * register more than 2^sizeof(unsigned int) pcmcia |
| 197 | * sockets... but the socket number is deprecated | 191 | * sockets... but the socket number is deprecated |
| @@ -226,7 +220,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) | |||
| 226 | /* set proper values in socket->dev */ | 220 | /* set proper values in socket->dev */ |
| 227 | dev_set_drvdata(&socket->dev, socket); | 221 | dev_set_drvdata(&socket->dev, socket); |
| 228 | socket->dev.class = &pcmcia_socket_class; | 222 | socket->dev.class = &pcmcia_socket_class; |
| 229 | snprintf(socket->dev.bus_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock); | 223 | dev_set_name(&socket->dev, "pcmcia_socket%u", socket->sock); |
| 230 | 224 | ||
| 231 | /* base address = 0, map = 0 */ | 225 | /* base address = 0, map = 0 */ |
| 232 | socket->cis_mem.flags = 0; | 226 | socket->cis_mem.flags = 0; |
| @@ -239,6 +233,12 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) | |||
| 239 | mutex_init(&socket->skt_mutex); | 233 | mutex_init(&socket->skt_mutex); |
| 240 | spin_lock_init(&socket->thread_lock); | 234 | spin_lock_init(&socket->thread_lock); |
| 241 | 235 | ||
| 236 | if (socket->resource_ops->init) { | ||
| 237 | ret = socket->resource_ops->init(socket); | ||
| 238 | if (ret) | ||
| 239 | goto err; | ||
| 240 | } | ||
| 241 | |||
| 242 | tsk = kthread_run(pccardd, socket, "pccardd"); | 242 | tsk = kthread_run(pccardd, socket, "pccardd"); |
| 243 | if (IS_ERR(tsk)) { | 243 | if (IS_ERR(tsk)) { |
| 244 | ret = PTR_ERR(tsk); | 244 | ret = PTR_ERR(tsk); |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 795660255490..47cab31ff6e4 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
| @@ -622,7 +622,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
| 622 | { | 622 | { |
| 623 | struct pcmcia_device *p_dev, *tmp_dev; | 623 | struct pcmcia_device *p_dev, *tmp_dev; |
| 624 | unsigned long flags; | 624 | unsigned long flags; |
| 625 | int bus_id_len; | ||
| 626 | 625 | ||
| 627 | s = pcmcia_get_socket(s); | 626 | s = pcmcia_get_socket(s); |
| 628 | if (!s) | 627 | if (!s) |
| @@ -650,12 +649,12 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
| 650 | /* by default don't allow DMA */ | 649 | /* by default don't allow DMA */ |
| 651 | p_dev->dma_mask = DMA_MASK_NONE; | 650 | p_dev->dma_mask = DMA_MASK_NONE; |
| 652 | p_dev->dev.dma_mask = &p_dev->dma_mask; | 651 | p_dev->dev.dma_mask = &p_dev->dma_mask; |
| 653 | bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); | 652 | dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no); |
| 654 | 653 | if (!dev_name(&p_dev->dev)) | |
| 655 | p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL); | 654 | goto err_free; |
| 655 | p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev)); | ||
| 656 | if (!p_dev->devname) | 656 | if (!p_dev->devname) |
| 657 | goto err_free; | 657 | goto err_free; |
| 658 | sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); | ||
| 659 | ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname); | 658 | ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname); |
| 660 | 659 | ||
| 661 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 660 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
| @@ -668,6 +667,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
| 668 | list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) | 667 | list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) |
| 669 | if (p_dev->func == tmp_dev->func) { | 668 | if (p_dev->func == tmp_dev->func) { |
| 670 | p_dev->function_config = tmp_dev->function_config; | 669 | p_dev->function_config = tmp_dev->function_config; |
| 670 | p_dev->io = tmp_dev->io; | ||
| 671 | p_dev->irq = tmp_dev->irq; | ||
| 671 | kref_get(&p_dev->function_config->ref); | 672 | kref_get(&p_dev->function_config->ref); |
| 672 | } | 673 | } |
| 673 | 674 | ||
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 76d4a98f0955..f5d0ba8e22d5 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
| @@ -302,9 +302,10 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 302 | /* We only allow changing Vpp1 and Vpp2 to the same value */ | 302 | /* We only allow changing Vpp1 and Vpp2 to the same value */ |
| 303 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && | 303 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && |
| 304 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 304 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
| 305 | if (mod->Vpp1 != mod->Vpp2) | 305 | if (mod->Vpp1 != mod->Vpp2) { |
| 306 | ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n"); | 306 | ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n"); |
| 307 | return -EINVAL; | 307 | return -EINVAL; |
| 308 | } | ||
| 308 | s->socket.Vpp = mod->Vpp1; | 309 | s->socket.Vpp = mod->Vpp1; |
| 309 | if (s->ops->set_socket(s, &s->socket)) { | 310 | if (s->ops->set_socket(s, &s->socket)) { |
| 310 | dev_printk(KERN_WARNING, &s->dev, | 311 | dev_printk(KERN_WARNING, &s->dev, |
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 17f4ecf1c0c5..9ca22c7aafb2 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
| @@ -71,7 +71,7 @@ static DEFINE_MUTEX(rsrc_mutex); | |||
| 71 | ======================================================================*/ | 71 | ======================================================================*/ |
| 72 | 72 | ||
| 73 | static struct resource * | 73 | static struct resource * |
| 74 | make_resource(resource_size_t b, resource_size_t n, int flags, char *name) | 74 | make_resource(resource_size_t b, resource_size_t n, int flags, const char *name) |
| 75 | { | 75 | { |
| 76 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); | 76 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); |
| 77 | 77 | ||
| @@ -624,7 +624,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star | |||
| 624 | static struct resource *nonstatic_find_io_region(unsigned long base, int num, | 624 | static struct resource *nonstatic_find_io_region(unsigned long base, int num, |
| 625 | unsigned long align, struct pcmcia_socket *s) | 625 | unsigned long align, struct pcmcia_socket *s) |
| 626 | { | 626 | { |
| 627 | struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.bus_id); | 627 | struct resource *res = make_resource(0, num, IORESOURCE_IO, dev_name(&s->dev)); |
| 628 | struct socket_data *s_data = s->resource_data; | 628 | struct socket_data *s_data = s->resource_data; |
| 629 | struct pcmcia_align_data data; | 629 | struct pcmcia_align_data data; |
| 630 | unsigned long min = base; | 630 | unsigned long min = base; |
| @@ -658,7 +658,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, | |||
| 658 | static struct resource * nonstatic_find_mem_region(u_long base, u_long num, | 658 | static struct resource * nonstatic_find_mem_region(u_long base, u_long num, |
| 659 | u_long align, int low, struct pcmcia_socket *s) | 659 | u_long align, int low, struct pcmcia_socket *s) |
| 660 | { | 660 | { |
| 661 | struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.bus_id); | 661 | struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev)); |
| 662 | struct socket_data *s_data = s->resource_data; | 662 | struct socket_data *s_data = s->resource_data; |
| 663 | struct pcmcia_align_data data; | 663 | struct pcmcia_align_data data; |
| 664 | unsigned long min, max; | 664 | unsigned long min, max; |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8abbb2020af9..123092d8a984 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -277,6 +277,14 @@ config RTC_DRV_FM3130 | |||
| 277 | This driver can also be built as a module. If so the module | 277 | This driver can also be built as a module. If so the module |
| 278 | will be called rtc-fm3130. | 278 | will be called rtc-fm3130. |
| 279 | 279 | ||
| 280 | config RTC_DRV_RX8581 | ||
| 281 | tristate "Epson RX-8581" | ||
| 282 | help | ||
| 283 | If you say yes here you will get support for the Epson RX-8581. | ||
| 284 | |||
| 285 | This driver can also be built as a module. If so the module | ||
| 286 | will be called rtc-rx8581. | ||
| 287 | |||
| 280 | endif # I2C | 288 | endif # I2C |
| 281 | 289 | ||
| 282 | comment "SPI RTC drivers" | 290 | comment "SPI RTC drivers" |
| @@ -302,6 +310,17 @@ config RTC_DRV_DS1305 | |||
| 302 | This driver can also be built as a module. If so, the module | 310 | This driver can also be built as a module. If so, the module |
| 303 | will be called rtc-ds1305. | 311 | will be called rtc-ds1305. |
| 304 | 312 | ||
| 313 | config RTC_DRV_DS1390 | ||
| 314 | tristate "Dallas/Maxim DS1390/93/94" | ||
| 315 | help | ||
| 316 | If you say yes here you get support for the DS1390/93/94 chips. | ||
| 317 | |||
| 318 | This driver only supports the RTC feature, and not other chip | ||
| 319 | features such as alarms and trickle charging. | ||
| 320 | |||
| 321 | This driver can also be built as a module. If so, the module | ||
| 322 | will be called rtc-ds1390. | ||
| 323 | |||
| 305 | config RTC_DRV_MAX6902 | 324 | config RTC_DRV_MAX6902 |
| 306 | tristate "Maxim MAX6902" | 325 | tristate "Maxim MAX6902" |
| 307 | help | 326 | help |
| @@ -468,6 +487,16 @@ config RTC_DRV_V3020 | |||
| 468 | This driver can also be built as a module. If so, the module | 487 | This driver can also be built as a module. If so, the module |
| 469 | will be called rtc-v3020. | 488 | will be called rtc-v3020. |
| 470 | 489 | ||
| 490 | config RTC_DRV_WM8350 | ||
| 491 | tristate "Wolfson Microelectronics WM8350 RTC" | ||
| 492 | depends on MFD_WM8350 | ||
| 493 | help | ||
| 494 | If you say yes here you will get support for the RTC subsystem | ||
| 495 | of the Wolfson Microelectronics WM8350. | ||
| 496 | |||
| 497 | This driver can also be built as a module. If so, the module | ||
| 498 | will be called "rtc-wm8350". | ||
| 499 | |||
| 471 | comment "on-CPU RTC drivers" | 500 | comment "on-CPU RTC drivers" |
| 472 | 501 | ||
| 473 | config RTC_DRV_OMAP | 502 | config RTC_DRV_OMAP |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e9e8474cc8fe..6e79c912bf9e 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -28,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | |||
| 28 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o | 28 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o |
| 29 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 29 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
| 30 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o | 30 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o |
| 31 | obj-$(CONFIG_RTC_DRV_DS1390) += rtc-ds1390.o | ||
| 31 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | 32 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o |
| 32 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 33 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
| 33 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 34 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
| @@ -57,6 +58,7 @@ obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o | |||
| 57 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 58 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
| 58 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 59 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
| 59 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 60 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
| 61 | obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o | ||
| 60 | obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o | 62 | obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o |
| 61 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o | 63 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o |
| 62 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o | 64 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o |
| @@ -66,4 +68,5 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | |||
| 66 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o | 68 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o |
| 67 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 69 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
| 68 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 70 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
| 71 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o | ||
| 69 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 72 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c new file mode 100644 index 000000000000..599e976bf014 --- /dev/null +++ b/drivers/rtc/rtc-ds1390.c | |||
| @@ -0,0 +1,220 @@ | |||
| 1 | /* | ||
| 2 | * rtc-ds1390.c -- driver for DS1390/93/94 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Mercury IMC Ltd | ||
| 5 | * Written by Mark Jackson <mpfj@mimc.co.uk> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * NOTE : Currently this driver only supports the bare minimum for read | ||
| 12 | * and write the RTC. The extra features provided by the chip family | ||
| 13 | * (alarms, trickle charger, different control registers) are unavailable. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/rtc.h> | ||
| 18 | #include <linux/spi/spi.h> | ||
| 19 | #include <linux/bcd.h> | ||
| 20 | |||
| 21 | #define DS1390_REG_100THS 0x00 | ||
| 22 | #define DS1390_REG_SECONDS 0x01 | ||
| 23 | #define DS1390_REG_MINUTES 0x02 | ||
| 24 | #define DS1390_REG_HOURS 0x03 | ||
| 25 | #define DS1390_REG_DAY 0x04 | ||
| 26 | #define DS1390_REG_DATE 0x05 | ||
| 27 | #define DS1390_REG_MONTH_CENT 0x06 | ||
| 28 | #define DS1390_REG_YEAR 0x07 | ||
| 29 | |||
| 30 | #define DS1390_REG_ALARM_100THS 0x08 | ||
| 31 | #define DS1390_REG_ALARM_SECONDS 0x09 | ||
| 32 | #define DS1390_REG_ALARM_MINUTES 0x0A | ||
| 33 | #define DS1390_REG_ALARM_HOURS 0x0B | ||
| 34 | #define DS1390_REG_ALARM_DAY_DATE 0x0C | ||
| 35 | |||
| 36 | #define DS1390_REG_CONTROL 0x0D | ||
| 37 | #define DS1390_REG_STATUS 0x0E | ||
| 38 | #define DS1390_REG_TRICKLE 0x0F | ||
| 39 | |||
| 40 | struct ds1390 { | ||
| 41 | struct rtc_device *rtc; | ||
| 42 | u8 txrx_buf[9]; /* cmd + 8 registers */ | ||
| 43 | }; | ||
| 44 | |||
| 45 | static void ds1390_set_reg(struct device *dev, unsigned char address, | ||
| 46 | unsigned char data) | ||
| 47 | { | ||
| 48 | struct spi_device *spi = to_spi_device(dev); | ||
| 49 | struct ds1390 *chip = dev_get_drvdata(dev); | ||
| 50 | |||
| 51 | /* Set MSB to indicate write */ | ||
| 52 | chip->txrx_buf[0] = address | 0x80; | ||
| 53 | chip->txrx_buf[1] = data; | ||
| 54 | |||
| 55 | /* do the i/o */ | ||
| 56 | spi_write_then_read(spi, chip->txrx_buf, 2, NULL, 0); | ||
| 57 | } | ||
| 58 | |||
| 59 | static int ds1390_get_reg(struct device *dev, unsigned char address, | ||
| 60 | unsigned char *data) | ||
| 61 | { | ||
| 62 | struct spi_device *spi = to_spi_device(dev); | ||
| 63 | struct ds1390 *chip = dev_get_drvdata(dev); | ||
| 64 | int status; | ||
| 65 | |||
| 66 | if (!data) | ||
| 67 | return -EINVAL; | ||
| 68 | |||
| 69 | /* Clear MSB to indicate read */ | ||
| 70 | chip->txrx_buf[0] = address & 0x7f; | ||
| 71 | /* do the i/o */ | ||
| 72 | status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 1); | ||
| 73 | if (status != 0) | ||
| 74 | return status; | ||
| 75 | |||
| 76 | *data = chip->txrx_buf[1]; | ||
| 77 | |||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | static int ds1390_get_datetime(struct device *dev, struct rtc_time *dt) | ||
| 82 | { | ||
| 83 | struct spi_device *spi = to_spi_device(dev); | ||
| 84 | struct ds1390 *chip = dev_get_drvdata(dev); | ||
| 85 | int status; | ||
| 86 | |||
| 87 | /* build the message */ | ||
| 88 | chip->txrx_buf[0] = DS1390_REG_SECONDS; | ||
| 89 | |||
| 90 | /* do the i/o */ | ||
| 91 | status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 8); | ||
| 92 | if (status != 0) | ||
| 93 | return status; | ||
| 94 | |||
| 95 | /* The chip sends data in this order: | ||
| 96 | * Seconds, Minutes, Hours, Day, Date, Month / Century, Year */ | ||
| 97 | dt->tm_sec = bcd2bin(chip->txrx_buf[0]); | ||
| 98 | dt->tm_min = bcd2bin(chip->txrx_buf[1]); | ||
| 99 | dt->tm_hour = bcd2bin(chip->txrx_buf[2]); | ||
| 100 | dt->tm_wday = bcd2bin(chip->txrx_buf[3]); | ||
| 101 | dt->tm_mday = bcd2bin(chip->txrx_buf[4]); | ||
| 102 | /* mask off century bit */ | ||
| 103 | dt->tm_mon = bcd2bin(chip->txrx_buf[5] & 0x7f) - 1; | ||
| 104 | /* adjust for century bit */ | ||
| 105 | dt->tm_year = bcd2bin(chip->txrx_buf[6]) + ((chip->txrx_buf[5] & 0x80) ? 100 : 0); | ||
| 106 | |||
| 107 | return rtc_valid_tm(dt); | ||
| 108 | } | ||
| 109 | |||
| 110 | static int ds1390_set_datetime(struct device *dev, struct rtc_time *dt) | ||
| 111 | { | ||
| 112 | struct spi_device *spi = to_spi_device(dev); | ||
| 113 | struct ds1390 *chip = dev_get_drvdata(dev); | ||
| 114 | |||
| 115 | /* build the message */ | ||
| 116 | chip->txrx_buf[0] = DS1390_REG_SECONDS | 0x80; | ||
| 117 | chip->txrx_buf[1] = bin2bcd(dt->tm_sec); | ||
| 118 | chip->txrx_buf[2] = bin2bcd(dt->tm_min); | ||
| 119 | chip->txrx_buf[3] = bin2bcd(dt->tm_hour); | ||
| 120 | chip->txrx_buf[4] = bin2bcd(dt->tm_wday); | ||
| 121 | chip->txrx_buf[5] = bin2bcd(dt->tm_mday); | ||
| 122 | chip->txrx_buf[6] = bin2bcd(dt->tm_mon + 1) | | ||
| 123 | ((dt->tm_year > 99) ? 0x80 : 0x00); | ||
| 124 | chip->txrx_buf[7] = bin2bcd(dt->tm_year % 100); | ||
| 125 | |||
| 126 | /* do the i/o */ | ||
| 127 | return spi_write_then_read(spi, chip->txrx_buf, 8, NULL, 0); | ||
| 128 | } | ||
| 129 | |||
| 130 | static int ds1390_read_time(struct device *dev, struct rtc_time *tm) | ||
| 131 | { | ||
| 132 | return ds1390_get_datetime(dev, tm); | ||
| 133 | } | ||
| 134 | |||
| 135 | static int ds1390_set_time(struct device *dev, struct rtc_time *tm) | ||
| 136 | { | ||
| 137 | return ds1390_set_datetime(dev, tm); | ||
| 138 | } | ||
| 139 | |||
| 140 | static const struct rtc_class_ops ds1390_rtc_ops = { | ||
| 141 | .read_time = ds1390_read_time, | ||
| 142 | .set_time = ds1390_set_time, | ||
| 143 | }; | ||
| 144 | |||
| 145 | static int __devinit ds1390_probe(struct spi_device *spi) | ||
| 146 | { | ||
| 147 | struct rtc_device *rtc; | ||
| 148 | unsigned char tmp; | ||
| 149 | struct ds1390 *chip; | ||
| 150 | int res; | ||
| 151 | |||
| 152 | printk(KERN_DEBUG "DS1390 SPI RTC driver\n"); | ||
| 153 | |||
| 154 | rtc = rtc_device_register("ds1390", | ||
| 155 | &spi->dev, &ds1390_rtc_ops, THIS_MODULE); | ||
| 156 | if (IS_ERR(rtc)) { | ||
| 157 | printk(KERN_ALERT "RTC : unable to register device\n"); | ||
| 158 | return PTR_ERR(rtc); | ||
| 159 | } | ||
| 160 | |||
| 161 | spi->mode = SPI_MODE_3; | ||
| 162 | spi->bits_per_word = 8; | ||
| 163 | spi_setup(spi); | ||
| 164 | |||
| 165 | chip = kzalloc(sizeof *chip, GFP_KERNEL); | ||
| 166 | if (!chip) { | ||
| 167 | printk(KERN_ALERT "RTC : unable to allocate device memory\n"); | ||
| 168 | rtc_device_unregister(rtc); | ||
| 169 | return -ENOMEM; | ||
| 170 | } | ||
| 171 | chip->rtc = rtc; | ||
| 172 | dev_set_drvdata(&spi->dev, chip); | ||
| 173 | |||
| 174 | res = ds1390_get_reg(&spi->dev, DS1390_REG_SECONDS, &tmp); | ||
| 175 | if (res) { | ||
| 176 | printk(KERN_ALERT "RTC : unable to read device\n"); | ||
| 177 | rtc_device_unregister(rtc); | ||
| 178 | return res; | ||
| 179 | } | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int __devexit ds1390_remove(struct spi_device *spi) | ||
| 185 | { | ||
| 186 | struct ds1390 *chip = platform_get_drvdata(spi); | ||
| 187 | struct rtc_device *rtc = chip->rtc; | ||
| 188 | |||
| 189 | if (rtc) | ||
| 190 | rtc_device_unregister(rtc); | ||
| 191 | |||
| 192 | kfree(chip); | ||
| 193 | |||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static struct spi_driver ds1390_driver = { | ||
| 198 | .driver = { | ||
| 199 | .name = "rtc-ds1390", | ||
| 200 | .owner = THIS_MODULE, | ||
| 201 | }, | ||
| 202 | .probe = ds1390_probe, | ||
| 203 | .remove = __devexit_p(ds1390_remove), | ||
| 204 | }; | ||
| 205 | |||
| 206 | static __init int ds1390_init(void) | ||
| 207 | { | ||
| 208 | return spi_register_driver(&ds1390_driver); | ||
| 209 | } | ||
| 210 | module_init(ds1390_init); | ||
| 211 | |||
| 212 | static __exit void ds1390_exit(void) | ||
| 213 | { | ||
| 214 | spi_unregister_driver(&ds1390_driver); | ||
| 215 | } | ||
| 216 | module_exit(ds1390_exit); | ||
| 217 | |||
| 218 | MODULE_DESCRIPTION("DS1390/93/94 SPI RTC driver"); | ||
| 219 | MODULE_AUTHOR("Mark Jackson <mpfj@mimc.co.uk>"); | ||
| 220 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c new file mode 100644 index 000000000000..c9522f3bc21c --- /dev/null +++ b/drivers/rtc/rtc-rx8581.c | |||
| @@ -0,0 +1,281 @@ | |||
| 1 | /* | ||
| 2 | * An I2C driver for the Epson RX8581 RTC | ||
| 3 | * | ||
| 4 | * Author: Martyn Welch <martyn.welch@gefanuc.com> | ||
| 5 | * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC) | ||
| 12 | * Copyright 2005-06 Tower Technologies | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/i2c.h> | ||
| 17 | #include <linux/bcd.h> | ||
| 18 | #include <linux/rtc.h> | ||
| 19 | #include <linux/log2.h> | ||
| 20 | |||
| 21 | #define DRV_VERSION "0.1" | ||
| 22 | |||
| 23 | #define RX8581_REG_SC 0x00 /* Second in BCD */ | ||
| 24 | #define RX8581_REG_MN 0x01 /* Minute in BCD */ | ||
| 25 | #define RX8581_REG_HR 0x02 /* Hour in BCD */ | ||
| 26 | #define RX8581_REG_DW 0x03 /* Day of Week */ | ||
| 27 | #define RX8581_REG_DM 0x04 /* Day of Month in BCD */ | ||
| 28 | #define RX8581_REG_MO 0x05 /* Month in BCD */ | ||
| 29 | #define RX8581_REG_YR 0x06 /* Year in BCD */ | ||
| 30 | #define RX8581_REG_RAM 0x07 /* RAM */ | ||
| 31 | #define RX8581_REG_AMN 0x08 /* Alarm Min in BCD*/ | ||
| 32 | #define RX8581_REG_AHR 0x09 /* Alarm Hour in BCD */ | ||
| 33 | #define RX8581_REG_ADM 0x0A | ||
| 34 | #define RX8581_REG_ADW 0x0A | ||
| 35 | #define RX8581_REG_TMR0 0x0B | ||
| 36 | #define RX8581_REG_TMR1 0x0C | ||
| 37 | #define RX8581_REG_EXT 0x0D /* Extension Register */ | ||
| 38 | #define RX8581_REG_FLAG 0x0E /* Flag Register */ | ||
| 39 | #define RX8581_REG_CTRL 0x0F /* Control Register */ | ||
| 40 | |||
| 41 | |||
| 42 | /* Flag Register bit definitions */ | ||
| 43 | #define RX8581_FLAG_UF 0x20 /* Update */ | ||
| 44 | #define RX8581_FLAG_TF 0x10 /* Timer */ | ||
| 45 | #define RX8581_FLAG_AF 0x08 /* Alarm */ | ||
| 46 | #define RX8581_FLAG_VLF 0x02 /* Voltage Low */ | ||
| 47 | |||
| 48 | /* Control Register bit definitions */ | ||
| 49 | #define RX8581_CTRL_UIE 0x20 /* Update Interrupt Enable */ | ||
| 50 | #define RX8581_CTRL_TIE 0x10 /* Timer Interrupt Enable */ | ||
| 51 | #define RX8581_CTRL_AIE 0x08 /* Alarm Interrupt Enable */ | ||
| 52 | #define RX8581_CTRL_STOP 0x02 /* STOP bit */ | ||
| 53 | #define RX8581_CTRL_RESET 0x01 /* RESET bit */ | ||
| 54 | |||
| 55 | static struct i2c_driver rx8581_driver; | ||
| 56 | |||
| 57 | /* | ||
| 58 | * In the routines that deal directly with the rx8581 hardware, we use | ||
| 59 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
| 60 | */ | ||
| 61 | static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 62 | { | ||
| 63 | unsigned char date[7]; | ||
| 64 | int data, err; | ||
| 65 | |||
| 66 | /* First we ensure that the "update flag" is not set, we read the | ||
| 67 | * time and date then re-read the "update flag". If the update flag | ||
| 68 | * has been set, we know that the time has changed during the read so | ||
| 69 | * we repeat the whole process again. | ||
| 70 | */ | ||
| 71 | data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); | ||
| 72 | if (data < 0) { | ||
| 73 | dev_err(&client->dev, "Unable to read device flags\n"); | ||
| 74 | return -EIO; | ||
| 75 | } | ||
| 76 | |||
| 77 | do { | ||
| 78 | /* If update flag set, clear it */ | ||
| 79 | if (data & RX8581_FLAG_UF) { | ||
| 80 | err = i2c_smbus_write_byte_data(client, | ||
| 81 | RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF)); | ||
| 82 | if (err != 0) { | ||
| 83 | dev_err(&client->dev, "Unable to write device " | ||
| 84 | "flags\n"); | ||
| 85 | return -EIO; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | /* Now read time and date */ | ||
| 90 | err = i2c_smbus_read_i2c_block_data(client, RX8581_REG_SC, | ||
| 91 | 7, date); | ||
| 92 | if (err < 0) { | ||
| 93 | dev_err(&client->dev, "Unable to read date\n"); | ||
| 94 | return -EIO; | ||
| 95 | } | ||
| 96 | |||
| 97 | /* Check flag register */ | ||
| 98 | data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); | ||
| 99 | if (data < 0) { | ||
| 100 | dev_err(&client->dev, "Unable to read device flags\n"); | ||
| 101 | return -EIO; | ||
| 102 | } | ||
| 103 | } while (data & RX8581_FLAG_UF); | ||
| 104 | |||
| 105 | if (data & RX8581_FLAG_VLF) | ||
| 106 | dev_info(&client->dev, | ||
| 107 | "low voltage detected, date/time is not reliable.\n"); | ||
| 108 | |||
| 109 | dev_dbg(&client->dev, | ||
| 110 | "%s: raw data is sec=%02x, min=%02x, hr=%02x, " | ||
| 111 | "wday=%02x, mday=%02x, mon=%02x, year=%02x\n", | ||
| 112 | __func__, | ||
| 113 | date[0], date[1], date[2], date[3], date[4], date[5], date[6]); | ||
| 114 | |||
| 115 | tm->tm_sec = bcd2bin(date[RX8581_REG_SC] & 0x7F); | ||
| 116 | tm->tm_min = bcd2bin(date[RX8581_REG_MN] & 0x7F); | ||
| 117 | tm->tm_hour = bcd2bin(date[RX8581_REG_HR] & 0x3F); /* rtc hr 0-23 */ | ||
| 118 | tm->tm_wday = ilog2(date[RX8581_REG_DW] & 0x7F); | ||
| 119 | tm->tm_mday = bcd2bin(date[RX8581_REG_DM] & 0x3F); | ||
| 120 | tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ | ||
| 121 | tm->tm_year = bcd2bin(date[RX8581_REG_YR]); | ||
| 122 | if (tm->tm_year < 70) | ||
| 123 | tm->tm_year += 100; /* assume we are in 1970...2069 */ | ||
| 124 | |||
| 125 | |||
| 126 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
| 127 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 128 | __func__, | ||
| 129 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
| 130 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 131 | |||
| 132 | err = rtc_valid_tm(tm); | ||
| 133 | if (err < 0) | ||
| 134 | dev_err(&client->dev, "retrieved date/time is not valid.\n"); | ||
| 135 | |||
| 136 | return err; | ||
| 137 | } | ||
| 138 | |||
| 139 | static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 140 | { | ||
| 141 | int data, err; | ||
| 142 | unsigned char buf[7]; | ||
| 143 | |||
| 144 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
| 145 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 146 | __func__, | ||
| 147 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
| 148 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 149 | |||
| 150 | /* hours, minutes and seconds */ | ||
| 151 | buf[RX8581_REG_SC] = bin2bcd(tm->tm_sec); | ||
| 152 | buf[RX8581_REG_MN] = bin2bcd(tm->tm_min); | ||
| 153 | buf[RX8581_REG_HR] = bin2bcd(tm->tm_hour); | ||
| 154 | |||
| 155 | buf[RX8581_REG_DM] = bin2bcd(tm->tm_mday); | ||
| 156 | |||
| 157 | /* month, 1 - 12 */ | ||
| 158 | buf[RX8581_REG_MO] = bin2bcd(tm->tm_mon + 1); | ||
| 159 | |||
| 160 | /* year and century */ | ||
| 161 | buf[RX8581_REG_YR] = bin2bcd(tm->tm_year % 100); | ||
| 162 | buf[RX8581_REG_DW] = (0x1 << tm->tm_wday); | ||
| 163 | |||
| 164 | /* Stop the clock */ | ||
| 165 | data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); | ||
| 166 | if (data < 0) { | ||
| 167 | dev_err(&client->dev, "Unable to read control register\n"); | ||
| 168 | return -EIO; | ||
| 169 | } | ||
| 170 | |||
| 171 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | ||
| 172 | (data | RX8581_CTRL_STOP)); | ||
| 173 | if (err < 0) { | ||
| 174 | dev_err(&client->dev, "Unable to write control register\n"); | ||
| 175 | return -EIO; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* write register's data */ | ||
| 179 | err = i2c_smbus_write_i2c_block_data(client, RX8581_REG_SC, 7, buf); | ||
| 180 | if (err < 0) { | ||
| 181 | dev_err(&client->dev, "Unable to write to date registers\n"); | ||
| 182 | return -EIO; | ||
| 183 | } | ||
| 184 | |||
| 185 | /* Restart the clock */ | ||
| 186 | data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); | ||
| 187 | if (data < 0) { | ||
| 188 | dev_err(&client->dev, "Unable to read control register\n"); | ||
| 189 | return -EIO; | ||
| 190 | } | ||
| 191 | |||
| 192 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | ||
| 193 | (data | ~(RX8581_CTRL_STOP))); | ||
| 194 | if (err != 0) { | ||
| 195 | dev_err(&client->dev, "Unable to write control register\n"); | ||
| 196 | return -EIO; | ||
| 197 | } | ||
| 198 | |||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 203 | { | ||
| 204 | return rx8581_get_datetime(to_i2c_client(dev), tm); | ||
| 205 | } | ||
| 206 | |||
| 207 | static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 208 | { | ||
| 209 | return rx8581_set_datetime(to_i2c_client(dev), tm); | ||
| 210 | } | ||
| 211 | |||
| 212 | static const struct rtc_class_ops rx8581_rtc_ops = { | ||
| 213 | .read_time = rx8581_rtc_read_time, | ||
| 214 | .set_time = rx8581_rtc_set_time, | ||
| 215 | }; | ||
| 216 | |||
| 217 | static int __devinit rx8581_probe(struct i2c_client *client, | ||
| 218 | const struct i2c_device_id *id) | ||
| 219 | { | ||
| 220 | struct rtc_device *rtc; | ||
| 221 | |||
| 222 | dev_dbg(&client->dev, "%s\n", __func__); | ||
| 223 | |||
| 224 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
| 225 | return -ENODEV; | ||
| 226 | |||
| 227 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
| 228 | |||
| 229 | rtc = rtc_device_register(rx8581_driver.driver.name, | ||
| 230 | &client->dev, &rx8581_rtc_ops, THIS_MODULE); | ||
| 231 | |||
| 232 | if (IS_ERR(rtc)) | ||
| 233 | return PTR_ERR(rtc); | ||
| 234 | |||
| 235 | i2c_set_clientdata(client, rtc); | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | static int __devexit rx8581_remove(struct i2c_client *client) | ||
| 241 | { | ||
| 242 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
| 243 | |||
| 244 | rtc_device_unregister(rtc); | ||
| 245 | |||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | static const struct i2c_device_id rx8581_id[] = { | ||
| 250 | { "rx8581", 0 }, | ||
| 251 | { } | ||
| 252 | }; | ||
| 253 | MODULE_DEVICE_TABLE(i2c, rx8581_id); | ||
| 254 | |||
| 255 | static struct i2c_driver rx8581_driver = { | ||
| 256 | .driver = { | ||
| 257 | .name = "rtc-rx8581", | ||
| 258 | .owner = THIS_MODULE, | ||
| 259 | }, | ||
| 260 | .probe = rx8581_probe, | ||
| 261 | .remove = __devexit_p(rx8581_remove), | ||
| 262 | .id_table = rx8581_id, | ||
| 263 | }; | ||
| 264 | |||
| 265 | static int __init rx8581_init(void) | ||
| 266 | { | ||
| 267 | return i2c_add_driver(&rx8581_driver); | ||
| 268 | } | ||
| 269 | |||
| 270 | static void __exit rx8581_exit(void) | ||
| 271 | { | ||
| 272 | i2c_del_driver(&rx8581_driver); | ||
| 273 | } | ||
| 274 | |||
| 275 | MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>"); | ||
| 276 | MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); | ||
| 277 | MODULE_LICENSE("GPL"); | ||
| 278 | MODULE_VERSION(DRV_VERSION); | ||
| 279 | |||
| 280 | module_init(rx8581_init); | ||
| 281 | module_exit(rx8581_exit); | ||
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c new file mode 100644 index 000000000000..5c5e3aa91385 --- /dev/null +++ b/drivers/rtc/rtc-wm8350.c | |||
| @@ -0,0 +1,514 @@ | |||
| 1 | /* | ||
| 2 | * Real Time Clock driver for Wolfson Microelectronics WM8350 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. | ||
| 5 | * | ||
| 6 | * Author: Liam Girdwood | ||
| 7 | * linux@wolfsonmicro.com | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 12 | * option) any later version. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/time.h> | ||
| 19 | #include <linux/rtc.h> | ||
| 20 | #include <linux/bcd.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/ioctl.h> | ||
| 23 | #include <linux/completion.h> | ||
| 24 | #include <linux/mfd/wm8350/rtc.h> | ||
| 25 | #include <linux/mfd/wm8350/core.h> | ||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/platform_device.h> | ||
| 28 | |||
| 29 | #define WM8350_SET_ALM_RETRIES 5 | ||
| 30 | #define WM8350_SET_TIME_RETRIES 5 | ||
| 31 | #define WM8350_GET_TIME_RETRIES 5 | ||
| 32 | |||
| 33 | #define to_wm8350_from_rtc_dev(d) container_of(d, struct wm8350, rtc.pdev.dev) | ||
| 34 | |||
| 35 | /* | ||
| 36 | * Read current time and date in RTC | ||
| 37 | */ | ||
| 38 | static int wm8350_rtc_readtime(struct device *dev, struct rtc_time *tm) | ||
| 39 | { | ||
| 40 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
| 41 | u16 time1[4], time2[4]; | ||
| 42 | int retries = WM8350_GET_TIME_RETRIES, ret; | ||
| 43 | |||
| 44 | /* | ||
| 45 | * Read the time twice and compare. | ||
| 46 | * If time1 == time2, then time is valid else retry. | ||
| 47 | */ | ||
| 48 | do { | ||
| 49 | ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES, | ||
| 50 | 4, time1); | ||
| 51 | if (ret < 0) | ||
| 52 | return ret; | ||
| 53 | ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES, | ||
| 54 | 4, time2); | ||
| 55 | if (ret < 0) | ||
| 56 | return ret; | ||
| 57 | |||
| 58 | if (memcmp(time1, time2, sizeof(time1)) == 0) { | ||
| 59 | tm->tm_sec = time1[0] & WM8350_RTC_SECS_MASK; | ||
| 60 | |||
| 61 | tm->tm_min = (time1[0] & WM8350_RTC_MINS_MASK) | ||
| 62 | >> WM8350_RTC_MINS_SHIFT; | ||
| 63 | |||
| 64 | tm->tm_hour = time1[1] & WM8350_RTC_HRS_MASK; | ||
| 65 | |||
| 66 | tm->tm_wday = ((time1[1] >> WM8350_RTC_DAY_SHIFT) | ||
| 67 | & 0x7) - 1; | ||
| 68 | |||
| 69 | tm->tm_mon = ((time1[2] & WM8350_RTC_MTH_MASK) | ||
| 70 | >> WM8350_RTC_MTH_SHIFT) - 1; | ||
| 71 | |||
| 72 | tm->tm_mday = (time1[2] & WM8350_RTC_DATE_MASK); | ||
| 73 | |||
| 74 | tm->tm_year = ((time1[3] & WM8350_RTC_YHUNDREDS_MASK) | ||
| 75 | >> WM8350_RTC_YHUNDREDS_SHIFT) * 100; | ||
| 76 | tm->tm_year += time1[3] & WM8350_RTC_YUNITS_MASK; | ||
| 77 | |||
| 78 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, | ||
| 79 | tm->tm_year); | ||
| 80 | tm->tm_year -= 1900; | ||
| 81 | |||
| 82 | dev_dbg(dev, "Read (%d left): %04x %04x %04x %04x\n", | ||
| 83 | retries, | ||
| 84 | time1[0], time1[1], time1[2], time1[3]); | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | } while (retries--); | ||
| 89 | |||
| 90 | dev_err(dev, "timed out reading RTC time\n"); | ||
| 91 | return -EIO; | ||
| 92 | } | ||
| 93 | |||
| 94 | /* | ||
| 95 | * Set current time and date in RTC | ||
| 96 | */ | ||
| 97 | static int wm8350_rtc_settime(struct device *dev, struct rtc_time *tm) | ||
| 98 | { | ||
| 99 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
| 100 | u16 time[4]; | ||
| 101 | u16 rtc_ctrl; | ||
| 102 | int ret, retries = WM8350_SET_TIME_RETRIES; | ||
| 103 | |||
| 104 | time[0] = tm->tm_sec; | ||
| 105 | time[0] |= tm->tm_min << WM8350_RTC_MINS_SHIFT; | ||
| 106 | time[1] = tm->tm_hour; | ||
| 107 | time[1] |= (tm->tm_wday + 1) << WM8350_RTC_DAY_SHIFT; | ||
| 108 | time[2] = tm->tm_mday; | ||
| 109 | time[2] |= (tm->tm_mon + 1) << WM8350_RTC_MTH_SHIFT; | ||
| 110 | time[3] = ((tm->tm_year + 1900) / 100) << WM8350_RTC_YHUNDREDS_SHIFT; | ||
| 111 | time[3] |= (tm->tm_year + 1900) % 100; | ||
| 112 | |||
| 113 | dev_dbg(dev, "Setting: %04x %04x %04x %04x\n", | ||
| 114 | time[0], time[1], time[2], time[3]); | ||
| 115 | |||
| 116 | /* Set RTC_SET to stop the clock */ | ||
| 117 | ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, WM8350_RTC_SET); | ||
| 118 | if (ret < 0) | ||
| 119 | return ret; | ||
| 120 | |||
| 121 | /* Wait until confirmation of stopping */ | ||
| 122 | do { | ||
| 123 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
| 124 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | ||
| 125 | } while (retries-- && !(rtc_ctrl & WM8350_RTC_STS)); | ||
| 126 | |||
| 127 | if (!retries) { | ||
| 128 | dev_err(dev, "timed out on set confirmation\n"); | ||
| 129 | return -EIO; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* Write time to RTC */ | ||
| 133 | ret = wm8350_block_write(wm8350, WM8350_RTC_SECONDS_MINUTES, 4, time); | ||
| 134 | if (ret < 0) | ||
| 135 | return ret; | ||
| 136 | |||
| 137 | /* Clear RTC_SET to start the clock */ | ||
| 138 | ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
| 139 | WM8350_RTC_SET); | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Read alarm time and date in RTC | ||
| 145 | */ | ||
| 146 | static int wm8350_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 147 | { | ||
| 148 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
| 149 | struct rtc_time *tm = &alrm->time; | ||
| 150 | u16 time[4]; | ||
| 151 | int ret; | ||
| 152 | |||
| 153 | ret = wm8350_block_read(wm8350, WM8350_ALARM_SECONDS_MINUTES, 4, time); | ||
| 154 | if (ret < 0) | ||
| 155 | return ret; | ||
| 156 | |||
| 157 | tm->tm_sec = time[0] & WM8350_RTC_ALMSECS_MASK; | ||
| 158 | if (tm->tm_sec == WM8350_RTC_ALMSECS_MASK) | ||
| 159 | tm->tm_sec = -1; | ||
| 160 | |||
| 161 | tm->tm_min = time[0] & WM8350_RTC_ALMMINS_MASK; | ||
| 162 | if (tm->tm_min == WM8350_RTC_ALMMINS_MASK) | ||
| 163 | tm->tm_min = -1; | ||
| 164 | else | ||
| 165 | tm->tm_min >>= WM8350_RTC_ALMMINS_SHIFT; | ||
| 166 | |||
| 167 | tm->tm_hour = time[1] & WM8350_RTC_ALMHRS_MASK; | ||
| 168 | if (tm->tm_hour == WM8350_RTC_ALMHRS_MASK) | ||
| 169 | tm->tm_hour = -1; | ||
| 170 | |||
| 171 | tm->tm_wday = ((time[1] >> WM8350_RTC_ALMDAY_SHIFT) & 0x7) - 1; | ||
| 172 | if (tm->tm_wday > 7) | ||
| 173 | tm->tm_wday = -1; | ||
| 174 | |||
| 175 | tm->tm_mon = time[2] & WM8350_RTC_ALMMTH_MASK; | ||
| 176 | if (tm->tm_mon == WM8350_RTC_ALMMTH_MASK) | ||
| 177 | tm->tm_mon = -1; | ||
| 178 | else | ||
| 179 | tm->tm_mon = (tm->tm_mon >> WM8350_RTC_ALMMTH_SHIFT) - 1; | ||
| 180 | |||
| 181 | tm->tm_mday = (time[2] & WM8350_RTC_ALMDATE_MASK); | ||
| 182 | if (tm->tm_mday == WM8350_RTC_ALMDATE_MASK) | ||
| 183 | tm->tm_mday = -1; | ||
| 184 | |||
| 185 | tm->tm_year = -1; | ||
| 186 | |||
| 187 | alrm->enabled = !(time[3] & WM8350_RTC_ALMSTS); | ||
| 188 | |||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int wm8350_rtc_stop_alarm(struct wm8350 *wm8350) | ||
| 193 | { | ||
| 194 | int retries = WM8350_SET_ALM_RETRIES; | ||
| 195 | u16 rtc_ctrl; | ||
| 196 | int ret; | ||
| 197 | |||
| 198 | /* Set RTC_SET to stop the clock */ | ||
| 199 | ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
| 200 | WM8350_RTC_ALMSET); | ||
| 201 | if (ret < 0) | ||
| 202 | return ret; | ||
| 203 | |||
| 204 | /* Wait until confirmation of stopping */ | ||
| 205 | do { | ||
| 206 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
| 207 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | ||
| 208 | } while (retries-- && !(rtc_ctrl & WM8350_RTC_ALMSTS)); | ||
| 209 | |||
| 210 | if (!(rtc_ctrl & WM8350_RTC_ALMSTS)) | ||
| 211 | return -ETIMEDOUT; | ||
| 212 | |||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | static int wm8350_rtc_start_alarm(struct wm8350 *wm8350) | ||
| 217 | { | ||
| 218 | int ret; | ||
| 219 | int retries = WM8350_SET_ALM_RETRIES; | ||
| 220 | u16 rtc_ctrl; | ||
| 221 | |||
| 222 | ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
| 223 | WM8350_RTC_ALMSET); | ||
| 224 | if (ret < 0) | ||
| 225 | return ret; | ||
| 226 | |||
| 227 | /* Wait until confirmation */ | ||
| 228 | do { | ||
| 229 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
| 230 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | ||
| 231 | } while (retries-- && rtc_ctrl & WM8350_RTC_ALMSTS); | ||
| 232 | |||
| 233 | if (rtc_ctrl & WM8350_RTC_ALMSTS) | ||
| 234 | return -ETIMEDOUT; | ||
| 235 | |||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 240 | { | ||
| 241 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
| 242 | struct rtc_time *tm = &alrm->time; | ||
| 243 | u16 time[3]; | ||
| 244 | int ret; | ||
| 245 | |||
| 246 | memset(time, 0, sizeof(time)); | ||
| 247 | |||
| 248 | if (tm->tm_sec != -1) | ||
| 249 | time[0] |= tm->tm_sec; | ||
| 250 | else | ||
| 251 | time[0] |= WM8350_RTC_ALMSECS_MASK; | ||
| 252 | |||
| 253 | if (tm->tm_min != -1) | ||
| 254 | time[0] |= tm->tm_min << WM8350_RTC_ALMMINS_SHIFT; | ||
| 255 | else | ||
| 256 | time[0] |= WM8350_RTC_ALMMINS_MASK; | ||
| 257 | |||
| 258 | if (tm->tm_hour != -1) | ||
| 259 | time[1] |= tm->tm_hour; | ||
| 260 | else | ||
| 261 | time[1] |= WM8350_RTC_ALMHRS_MASK; | ||
| 262 | |||
| 263 | if (tm->tm_wday != -1) | ||
| 264 | time[1] |= (tm->tm_wday + 1) << WM8350_RTC_ALMDAY_SHIFT; | ||
| 265 | else | ||
| 266 | time[1] |= WM8350_RTC_ALMDAY_MASK; | ||
| 267 | |||
| 268 | if (tm->tm_mday != -1) | ||
| 269 | time[2] |= tm->tm_mday; | ||
| 270 | else | ||
| 271 | time[2] |= WM8350_RTC_ALMDATE_MASK; | ||
| 272 | |||
| 273 | if (tm->tm_mon != -1) | ||
| 274 | time[2] |= (tm->tm_mon + 1) << WM8350_RTC_ALMMTH_SHIFT; | ||
| 275 | else | ||
| 276 | time[2] |= WM8350_RTC_ALMMTH_MASK; | ||
| 277 | |||
| 278 | ret = wm8350_rtc_stop_alarm(wm8350); | ||
| 279 | if (ret < 0) | ||
| 280 | return ret; | ||
| 281 | |||
| 282 | /* Write time to RTC */ | ||
| 283 | ret = wm8350_block_write(wm8350, WM8350_ALARM_SECONDS_MINUTES, | ||
| 284 | 3, time); | ||
| 285 | if (ret < 0) | ||
| 286 | return ret; | ||
| 287 | |||
| 288 | if (alrm->enabled) | ||
| 289 | ret = wm8350_rtc_start_alarm(wm8350); | ||
| 290 | |||
| 291 | return ret; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 295 | * Handle commands from user-space | ||
| 296 | */ | ||
| 297 | static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
| 298 | unsigned long arg) | ||
| 299 | { | ||
| 300 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
| 301 | |||
| 302 | switch (cmd) { | ||
| 303 | case RTC_AIE_OFF: | ||
| 304 | return wm8350_rtc_stop_alarm(wm8350); | ||
| 305 | case RTC_AIE_ON: | ||
| 306 | return wm8350_rtc_start_alarm(wm8350); | ||
| 307 | |||
| 308 | case RTC_UIE_OFF: | ||
| 309 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
| 310 | break; | ||
| 311 | case RTC_UIE_ON: | ||
| 312 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
| 313 | break; | ||
| 314 | |||
| 315 | default: | ||
| 316 | return -ENOIOCTLCMD; | ||
| 317 | } | ||
| 318 | |||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | |||
| 322 | static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, | ||
| 323 | void *data) | ||
| 324 | { | ||
| 325 | struct rtc_device *rtc = wm8350->rtc.rtc; | ||
| 326 | int ret; | ||
| 327 | |||
| 328 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); | ||
| 329 | |||
| 330 | /* Make it one shot */ | ||
| 331 | ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
| 332 | WM8350_RTC_ALMSET); | ||
| 333 | if (ret != 0) { | ||
| 334 | dev_err(&(wm8350->rtc.pdev->dev), | ||
| 335 | "Failed to disable alarm: %d\n", ret); | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, | ||
| 340 | void *data) | ||
| 341 | { | ||
| 342 | struct rtc_device *rtc = wm8350->rtc.rtc; | ||
| 343 | |||
| 344 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); | ||
| 345 | } | ||
| 346 | |||
| 347 | static const struct rtc_class_ops wm8350_rtc_ops = { | ||
| 348 | .ioctl = wm8350_rtc_ioctl, | ||
| 349 | .read_time = wm8350_rtc_readtime, | ||
| 350 | .set_time = wm8350_rtc_settime, | ||
| 351 | .read_alarm = wm8350_rtc_readalarm, | ||
| 352 | .set_alarm = wm8350_rtc_setalarm, | ||
| 353 | }; | ||
| 354 | |||
| 355 | #ifdef CONFIG_PM | ||
| 356 | static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 357 | { | ||
| 358 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | ||
| 359 | int ret = 0; | ||
| 360 | u16 reg; | ||
| 361 | |||
| 362 | reg = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
| 363 | |||
| 364 | if (device_may_wakeup(&wm8350->rtc.pdev->dev) && | ||
| 365 | reg & WM8350_RTC_ALMSTS) { | ||
| 366 | ret = wm8350_rtc_stop_alarm(wm8350); | ||
| 367 | if (ret != 0) | ||
| 368 | dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n", | ||
| 369 | ret); | ||
| 370 | } | ||
| 371 | |||
| 372 | return ret; | ||
| 373 | } | ||
| 374 | |||
| 375 | static int wm8350_rtc_resume(struct platform_device *pdev) | ||
| 376 | { | ||
| 377 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | ||
| 378 | int ret; | ||
| 379 | |||
| 380 | if (wm8350->rtc.alarm_enabled) { | ||
| 381 | ret = wm8350_rtc_start_alarm(wm8350); | ||
| 382 | if (ret != 0) | ||
| 383 | dev_err(&pdev->dev, | ||
| 384 | "Failed to restart RTC alarm: %d\n", ret); | ||
| 385 | } | ||
| 386 | |||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | #else | ||
| 391 | #define wm8350_rtc_suspend NULL | ||
| 392 | #define wm8350_rtc_resume NULL | ||
| 393 | #endif | ||
| 394 | |||
| 395 | static int wm8350_rtc_probe(struct platform_device *pdev) | ||
| 396 | { | ||
| 397 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | ||
| 398 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; | ||
| 399 | int ret = 0; | ||
| 400 | u16 timectl, power5; | ||
| 401 | |||
| 402 | timectl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
| 403 | if (timectl & WM8350_RTC_BCD) { | ||
| 404 | dev_err(&pdev->dev, "RTC BCD mode not supported\n"); | ||
| 405 | return -EINVAL; | ||
| 406 | } | ||
| 407 | if (timectl & WM8350_RTC_12HR) { | ||
| 408 | dev_err(&pdev->dev, "RTC 12 hour mode not supported\n"); | ||
| 409 | return -EINVAL; | ||
| 410 | } | ||
| 411 | |||
| 412 | /* enable the RTC if it's not already enabled */ | ||
| 413 | power5 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); | ||
| 414 | if (!(power5 & WM8350_RTC_TICK_ENA)) { | ||
| 415 | dev_info(wm8350->dev, "Starting RTC\n"); | ||
| 416 | |||
| 417 | wm8350_reg_unlock(wm8350); | ||
| 418 | |||
| 419 | ret = wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, | ||
| 420 | WM8350_RTC_TICK_ENA); | ||
| 421 | if (ret < 0) { | ||
| 422 | dev_err(&pdev->dev, "failed to enable RTC: %d\n", ret); | ||
| 423 | return ret; | ||
| 424 | } | ||
| 425 | |||
| 426 | wm8350_reg_lock(wm8350); | ||
| 427 | } | ||
| 428 | |||
| 429 | if (timectl & WM8350_RTC_STS) { | ||
| 430 | int retries; | ||
| 431 | |||
| 432 | ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
| 433 | WM8350_RTC_SET); | ||
| 434 | if (ret < 0) { | ||
| 435 | dev_err(&pdev->dev, "failed to start: %d\n", ret); | ||
| 436 | return ret; | ||
| 437 | } | ||
| 438 | |||
| 439 | retries = WM8350_SET_TIME_RETRIES; | ||
| 440 | do { | ||
| 441 | timectl = wm8350_reg_read(wm8350, | ||
| 442 | WM8350_RTC_TIME_CONTROL); | ||
| 443 | } while (timectl & WM8350_RTC_STS && retries--); | ||
| 444 | |||
| 445 | if (retries == 0) { | ||
| 446 | dev_err(&pdev->dev, "failed to start: timeout\n"); | ||
| 447 | return -ENODEV; | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | device_init_wakeup(&pdev->dev, 1); | ||
| 452 | |||
| 453 | wm_rtc->rtc = rtc_device_register("wm8350", &pdev->dev, | ||
| 454 | &wm8350_rtc_ops, THIS_MODULE); | ||
| 455 | if (IS_ERR(wm_rtc->rtc)) { | ||
| 456 | ret = PTR_ERR(wm_rtc->rtc); | ||
| 457 | dev_err(&pdev->dev, "failed to register RTC: %d\n", ret); | ||
| 458 | return ret; | ||
| 459 | } | ||
| 460 | |||
| 461 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
| 462 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER); | ||
| 463 | |||
| 464 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, | ||
| 465 | wm8350_rtc_update_handler, NULL); | ||
| 466 | |||
| 467 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, | ||
| 468 | wm8350_rtc_alarm_handler, NULL); | ||
| 469 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); | ||
| 470 | |||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | static int __devexit wm8350_rtc_remove(struct platform_device *pdev) | ||
| 475 | { | ||
| 476 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | ||
| 477 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; | ||
| 478 | |||
| 479 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
| 480 | |||
| 481 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
| 482 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); | ||
| 483 | |||
| 484 | rtc_device_unregister(wm_rtc->rtc); | ||
| 485 | |||
| 486 | return 0; | ||
| 487 | } | ||
| 488 | |||
| 489 | static struct platform_driver wm8350_rtc_driver = { | ||
| 490 | .probe = wm8350_rtc_probe, | ||
| 491 | .remove = __devexit_p(wm8350_rtc_remove), | ||
| 492 | .suspend = wm8350_rtc_suspend, | ||
| 493 | .resume = wm8350_rtc_resume, | ||
| 494 | .driver = { | ||
| 495 | .name = "wm8350-rtc", | ||
| 496 | }, | ||
| 497 | }; | ||
| 498 | |||
| 499 | static int __init wm8350_rtc_init(void) | ||
| 500 | { | ||
| 501 | return platform_driver_register(&wm8350_rtc_driver); | ||
| 502 | } | ||
| 503 | module_init(wm8350_rtc_init); | ||
| 504 | |||
| 505 | static void __exit wm8350_rtc_exit(void) | ||
| 506 | { | ||
| 507 | platform_driver_unregister(&wm8350_rtc_driver); | ||
| 508 | } | ||
| 509 | module_exit(wm8350_rtc_exit); | ||
| 510 | |||
| 511 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
| 512 | MODULE_DESCRIPTION("RTC driver for the WM8350"); | ||
| 513 | MODULE_LICENSE("GPL"); | ||
| 514 | MODULE_ALIAS("platform:wm8350-rtc"); | ||
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 4b76fca64a6f..363bd1303d21 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -1746,6 +1746,11 @@ restart: | |||
| 1746 | goto restart; | 1746 | goto restart; |
| 1747 | } | 1747 | } |
| 1748 | 1748 | ||
| 1749 | /* log sense for fatal error */ | ||
| 1750 | if (cqr->status == DASD_CQR_FAILED) { | ||
| 1751 | dasd_log_sense(cqr, &cqr->irb); | ||
| 1752 | } | ||
| 1753 | |||
| 1749 | /* First of all call extended error reporting. */ | 1754 | /* First of all call extended error reporting. */ |
| 1750 | if (dasd_eer_enabled(base) && | 1755 | if (dasd_eer_enabled(base) && |
| 1751 | cqr->status == DASD_CQR_FAILED) { | 1756 | cqr->status == DASD_CQR_FAILED) { |
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index eb5f1b8bc57f..ec9c0bcf66ee 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
| @@ -324,6 +324,9 @@ static int do_assign_storage(sclp_cmdw_t cmd, u16 rn) | |||
| 324 | case 0x0120: | 324 | case 0x0120: |
| 325 | break; | 325 | break; |
| 326 | default: | 326 | default: |
| 327 | pr_warning("assign storage failed (cmd=0x%08x, " | ||
| 328 | "response=0x%04x, rn=0x%04x)\n", cmd, | ||
| 329 | sccb->header.response_code, rn); | ||
| 327 | rc = -EIO; | 330 | rc = -EIO; |
| 328 | break; | 331 | break; |
| 329 | } | 332 | } |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 4e78c82194b4..4e4008325e28 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -874,11 +874,15 @@ void ccw_device_move_to_orphanage(struct work_struct *work) | |||
| 874 | replacing_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev); | 874 | replacing_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev); |
| 875 | if (replacing_cdev) { | 875 | if (replacing_cdev) { |
| 876 | sch_attach_disconnected_device(sch, replacing_cdev); | 876 | sch_attach_disconnected_device(sch, replacing_cdev); |
| 877 | /* Release reference from get_disc_ccwdev_by_dev_id() */ | ||
| 878 | put_device(&cdev->dev); | ||
| 877 | return; | 879 | return; |
| 878 | } | 880 | } |
| 879 | replacing_cdev = get_orphaned_ccwdev_by_dev_id(css, &dev_id); | 881 | replacing_cdev = get_orphaned_ccwdev_by_dev_id(css, &dev_id); |
| 880 | if (replacing_cdev) { | 882 | if (replacing_cdev) { |
| 881 | sch_attach_orphaned_device(sch, replacing_cdev); | 883 | sch_attach_orphaned_device(sch, replacing_cdev); |
| 884 | /* Release reference from get_orphaned_ccwdev_by_dev_id() */ | ||
| 885 | put_device(&cdev->dev); | ||
| 882 | return; | 886 | return; |
| 883 | } | 887 | } |
| 884 | sch_create_and_recog_new_device(sch); | 888 | sch_create_and_recog_new_device(sch); |
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index ff4a6931bb8e..3d442444c618 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
| @@ -322,13 +322,13 @@ static int __init kvm_devices_init(void) | |||
| 322 | return rc; | 322 | return rc; |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE); | 325 | rc = vmem_add_mapping(real_memory_size, PAGE_SIZE); |
| 326 | if (rc) { | 326 | if (rc) { |
| 327 | s390_root_dev_unregister(kvm_root); | 327 | s390_root_dev_unregister(kvm_root); |
| 328 | return rc; | 328 | return rc; |
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | kvm_devices = (void *) PFN_PHYS(max_pfn); | 331 | kvm_devices = (void *) real_memory_size; |
| 332 | 332 | ||
| 333 | ctl_set_bit(0, 9); | 333 | ctl_set_bit(0, 9); |
| 334 | register_external_interrupt(0x2603, kvm_extint_handler); | 334 | register_external_interrupt(0x2603, kvm_extint_handler); |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 3b56220fb900..3d4e3e3f3fc0 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
| @@ -610,7 +610,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
| 610 | atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); | 610 | atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); |
| 611 | atomic_set(&port->refcount, 0); | 611 | atomic_set(&port->refcount, 0); |
| 612 | 612 | ||
| 613 | dev_set_name(&port->sysfs_device, "0x%016llx", wwpn); | 613 | dev_set_name(&port->sysfs_device, "0x%016llx", |
| 614 | (unsigned long long)wwpn); | ||
| 614 | port->sysfs_device.parent = &adapter->ccw_device->dev; | 615 | port->sysfs_device.parent = &adapter->ccw_device->dev; |
| 615 | 616 | ||
| 616 | port->sysfs_device.release = zfcp_sysfs_port_release; | 617 | port->sysfs_device.release = zfcp_sysfs_port_release; |
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index b04038c74786..951a8d409d1d 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
| @@ -116,7 +116,9 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device) | |||
| 116 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85, | 116 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85, |
| 117 | NULL); | 117 | NULL); |
| 118 | zfcp_erp_wait(adapter); | 118 | zfcp_erp_wait(adapter); |
| 119 | goto out; | 119 | up(&zfcp_data.config_sema); |
| 120 | flush_work(&adapter->scan_work); | ||
| 121 | return 0; | ||
| 120 | 122 | ||
| 121 | out_scsi_register: | 123 | out_scsi_register: |
| 122 | zfcp_erp_thread_kill(adapter); | 124 | zfcp_erp_thread_kill(adapter); |
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 060f5f2352ec..31012d58cfb7 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
| @@ -30,7 +30,7 @@ static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len, | |||
| 30 | dump->offset = offset; | 30 | dump->offset = offset; |
| 31 | dump->size = min(from_len - offset, room); | 31 | dump->size = min(from_len - offset, room); |
| 32 | memcpy(dump->data, from + offset, dump->size); | 32 | memcpy(dump->data, from + offset, dump->size); |
| 33 | debug_event(dbf, level, dump, dump->size); | 33 | debug_event(dbf, level, dump, dump->size + sizeof(*dump)); |
| 34 | } | 34 | } |
| 35 | } | 35 | } |
| 36 | 36 | ||
| @@ -108,7 +108,7 @@ static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view, | |||
| 108 | t.tv_sec, t.tv_nsec); | 108 | t.tv_sec, t.tv_nsec); |
| 109 | zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid); | 109 | zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid); |
| 110 | } else { | 110 | } else { |
| 111 | zfcp_dbf_outd(&p, NULL, dump->data, dump->size, dump->offset, | 111 | zfcp_dbf_outd(&p, "", dump->data, dump->size, dump->offset, |
| 112 | dump->total_size); | 112 | dump->total_size); |
| 113 | if ((dump->offset + dump->size) == dump->total_size) | 113 | if ((dump->offset + dump->size) == dump->total_size) |
| 114 | p += sprintf(p, "\n"); | 114 | p += sprintf(p, "\n"); |
| @@ -366,6 +366,7 @@ static void zfcp_hba_dbf_view_response(char **p, | |||
| 366 | break; | 366 | break; |
| 367 | zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd); | 367 | zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd); |
| 368 | zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial); | 368 | zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial); |
| 369 | p += sprintf(*p, "\n"); | ||
| 369 | break; | 370 | break; |
| 370 | 371 | ||
| 371 | case FSF_QTCB_OPEN_PORT_WITH_DID: | 372 | case FSF_QTCB_OPEN_PORT_WITH_DID: |
| @@ -465,7 +466,8 @@ static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view, | |||
| 465 | else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0) | 466 | else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0) |
| 466 | zfcp_hba_dbf_view_berr(&p, &r->u.berr); | 467 | zfcp_hba_dbf_view_berr(&p, &r->u.berr); |
| 467 | 468 | ||
| 468 | p += sprintf(p, "\n"); | 469 | if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) != 0) |
| 470 | p += sprintf(p, "\n"); | ||
| 469 | return p - out_buf; | 471 | return p - out_buf; |
| 470 | } | 472 | } |
| 471 | 473 | ||
| @@ -880,6 +882,7 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) | |||
| 880 | struct ct_hdr *hdr = sg_virt(ct->req); | 882 | struct ct_hdr *hdr = sg_virt(ct->req); |
| 881 | struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; | 883 | struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; |
| 882 | struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req; | 884 | struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req; |
| 885 | int level = 3; | ||
| 883 | unsigned long flags; | 886 | unsigned long flags; |
| 884 | 887 | ||
| 885 | spin_lock_irqsave(&adapter->san_dbf_lock, flags); | 888 | spin_lock_irqsave(&adapter->san_dbf_lock, flags); |
| @@ -896,9 +899,10 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) | |||
| 896 | oct->options = hdr->options; | 899 | oct->options = hdr->options; |
| 897 | oct->max_res_size = hdr->max_res_size; | 900 | oct->max_res_size = hdr->max_res_size; |
| 898 | oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr), | 901 | oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr), |
| 899 | ZFCP_DBF_CT_PAYLOAD); | 902 | ZFCP_DBF_SAN_MAX_PAYLOAD); |
| 900 | memcpy(oct->payload, (void *)hdr + sizeof(struct ct_hdr), oct->len); | 903 | debug_event(adapter->san_dbf, level, r, sizeof(*r)); |
| 901 | debug_event(adapter->san_dbf, 3, r, sizeof(*r)); | 904 | zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level, |
| 905 | (void *)hdr + sizeof(struct ct_hdr), oct->len); | ||
| 902 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); | 906 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); |
| 903 | } | 907 | } |
| 904 | 908 | ||
| @@ -914,6 +918,7 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) | |||
| 914 | struct ct_hdr *hdr = sg_virt(ct->resp); | 918 | struct ct_hdr *hdr = sg_virt(ct->resp); |
| 915 | struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; | 919 | struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; |
| 916 | struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp; | 920 | struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp; |
| 921 | int level = 3; | ||
| 917 | unsigned long flags; | 922 | unsigned long flags; |
| 918 | 923 | ||
| 919 | spin_lock_irqsave(&adapter->san_dbf_lock, flags); | 924 | spin_lock_irqsave(&adapter->san_dbf_lock, flags); |
| @@ -929,9 +934,10 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) | |||
| 929 | rct->expl = hdr->reason_code_expl; | 934 | rct->expl = hdr->reason_code_expl; |
| 930 | rct->vendor_unique = hdr->vendor_unique; | 935 | rct->vendor_unique = hdr->vendor_unique; |
| 931 | rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr), | 936 | rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr), |
| 932 | ZFCP_DBF_CT_PAYLOAD); | 937 | ZFCP_DBF_SAN_MAX_PAYLOAD); |
| 933 | memcpy(rct->payload, (void *)hdr + sizeof(struct ct_hdr), rct->len); | 938 | debug_event(adapter->san_dbf, level, r, sizeof(*r)); |
| 934 | debug_event(adapter->san_dbf, 3, r, sizeof(*r)); | 939 | zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level, |
| 940 | (void *)hdr + sizeof(struct ct_hdr), rct->len); | ||
| 935 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); | 941 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); |
| 936 | } | 942 | } |
| 937 | 943 | ||
| @@ -954,7 +960,7 @@ static void zfcp_san_dbf_event_els(const char *tag, int level, | |||
| 954 | rec->u.els.ls_code = ls_code; | 960 | rec->u.els.ls_code = ls_code; |
| 955 | debug_event(adapter->san_dbf, level, rec, sizeof(*rec)); | 961 | debug_event(adapter->san_dbf, level, rec, sizeof(*rec)); |
| 956 | zfcp_dbf_hexdump(adapter->san_dbf, rec, sizeof(*rec), level, | 962 | zfcp_dbf_hexdump(adapter->san_dbf, rec, sizeof(*rec), level, |
| 957 | buffer, min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD)); | 963 | buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD)); |
| 958 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); | 964 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); |
| 959 | } | 965 | } |
| 960 | 966 | ||
| @@ -1008,8 +1014,6 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view, | |||
| 1008 | char *out_buf, const char *in_buf) | 1014 | char *out_buf, const char *in_buf) |
| 1009 | { | 1015 | { |
| 1010 | struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf; | 1016 | struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf; |
| 1011 | char *buffer = NULL; | ||
| 1012 | int buflen = 0, total = 0; | ||
| 1013 | char *p = out_buf; | 1017 | char *p = out_buf; |
| 1014 | 1018 | ||
| 1015 | if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) | 1019 | if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) |
| @@ -1029,9 +1033,6 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view, | |||
| 1029 | zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype); | 1033 | zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype); |
| 1030 | zfcp_dbf_out(&p, "options", "0x%02x", ct->options); | 1034 | zfcp_dbf_out(&p, "options", "0x%02x", ct->options); |
| 1031 | zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size); | 1035 | zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size); |
| 1032 | total = ct->len; | ||
| 1033 | buffer = ct->payload; | ||
| 1034 | buflen = min(total, ZFCP_DBF_CT_PAYLOAD); | ||
| 1035 | } else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) { | 1036 | } else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) { |
| 1036 | struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp; | 1037 | struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp; |
| 1037 | zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code); | 1038 | zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code); |
| @@ -1039,23 +1040,12 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view, | |||
| 1039 | zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code); | 1040 | zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code); |
| 1040 | zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl); | 1041 | zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl); |
| 1041 | zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique); | 1042 | zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique); |
| 1042 | total = ct->len; | ||
| 1043 | buffer = ct->payload; | ||
| 1044 | buflen = min(total, ZFCP_DBF_CT_PAYLOAD); | ||
| 1045 | } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 || | 1043 | } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 || |
| 1046 | strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || | 1044 | strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || |
| 1047 | strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { | 1045 | strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { |
| 1048 | struct zfcp_san_dbf_record_els *els = &r->u.els; | 1046 | struct zfcp_san_dbf_record_els *els = &r->u.els; |
| 1049 | zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code); | 1047 | zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code); |
| 1050 | total = els->len; | ||
| 1051 | buffer = els->payload; | ||
| 1052 | buflen = min(total, ZFCP_DBF_ELS_PAYLOAD); | ||
| 1053 | } | 1048 | } |
| 1054 | |||
| 1055 | zfcp_dbf_outd(&p, "payload", buffer, buflen, 0, total); | ||
| 1056 | if (buflen == total) | ||
| 1057 | p += sprintf(p, "\n"); | ||
| 1058 | |||
| 1059 | return p - out_buf; | 1049 | return p - out_buf; |
| 1060 | } | 1050 | } |
| 1061 | 1051 | ||
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index e8f450801fea..5d6b2dff855b 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h | |||
| @@ -163,8 +163,6 @@ struct zfcp_san_dbf_record_ct_request { | |||
| 163 | u8 options; | 163 | u8 options; |
| 164 | u16 max_res_size; | 164 | u16 max_res_size; |
| 165 | u32 len; | 165 | u32 len; |
| 166 | #define ZFCP_DBF_CT_PAYLOAD 24 | ||
| 167 | u8 payload[ZFCP_DBF_CT_PAYLOAD]; | ||
| 168 | } __attribute__ ((packed)); | 166 | } __attribute__ ((packed)); |
| 169 | 167 | ||
| 170 | struct zfcp_san_dbf_record_ct_response { | 168 | struct zfcp_san_dbf_record_ct_response { |
| @@ -174,15 +172,11 @@ struct zfcp_san_dbf_record_ct_response { | |||
| 174 | u8 expl; | 172 | u8 expl; |
| 175 | u8 vendor_unique; | 173 | u8 vendor_unique; |
| 176 | u32 len; | 174 | u32 len; |
| 177 | u8 payload[ZFCP_DBF_CT_PAYLOAD]; | ||
| 178 | } __attribute__ ((packed)); | 175 | } __attribute__ ((packed)); |
| 179 | 176 | ||
| 180 | struct zfcp_san_dbf_record_els { | 177 | struct zfcp_san_dbf_record_els { |
| 181 | u8 ls_code; | 178 | u8 ls_code; |
| 182 | u32 len; | 179 | u32 len; |
| 183 | #define ZFCP_DBF_ELS_PAYLOAD 32 | ||
| 184 | #define ZFCP_DBF_ELS_MAX_PAYLOAD 1024 | ||
| 185 | u8 payload[ZFCP_DBF_ELS_PAYLOAD]; | ||
| 186 | } __attribute__ ((packed)); | 180 | } __attribute__ ((packed)); |
| 187 | 181 | ||
| 188 | struct zfcp_san_dbf_record { | 182 | struct zfcp_san_dbf_record { |
| @@ -196,6 +190,8 @@ struct zfcp_san_dbf_record { | |||
| 196 | struct zfcp_san_dbf_record_ct_response ct_resp; | 190 | struct zfcp_san_dbf_record_ct_response ct_resp; |
| 197 | struct zfcp_san_dbf_record_els els; | 191 | struct zfcp_san_dbf_record_els els; |
| 198 | } u; | 192 | } u; |
| 193 | #define ZFCP_DBF_SAN_MAX_PAYLOAD 1024 | ||
| 194 | u8 payload[32]; | ||
| 199 | } __attribute__ ((packed)); | 195 | } __attribute__ ((packed)); |
| 200 | 196 | ||
| 201 | struct zfcp_scsi_dbf_record { | 197 | struct zfcp_scsi_dbf_record { |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 9040f738ff33..35364f64da7f 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
| @@ -472,6 +472,7 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) | |||
| 472 | ZFCP_STATUS_ERP_TIMEDOUT)) { | 472 | ZFCP_STATUS_ERP_TIMEDOUT)) { |
| 473 | act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; | 473 | act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; |
| 474 | zfcp_rec_dbf_event_action(142, act); | 474 | zfcp_rec_dbf_event_action(142, act); |
| 475 | act->fsf_req->erp_action = NULL; | ||
| 475 | } | 476 | } |
| 476 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) | 477 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) |
| 477 | zfcp_rec_dbf_event_action(143, act); | 478 | zfcp_rec_dbf_event_action(143, act); |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 5ae1d497e5ed..d024442ee128 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
| @@ -683,6 +683,7 @@ static struct zfcp_fsf_req *zfcp_fsf_alloc_noqtcb(mempool_t *pool) | |||
| 683 | if (!req) | 683 | if (!req) |
| 684 | return NULL; | 684 | return NULL; |
| 685 | memset(req, 0, sizeof(*req)); | 685 | memset(req, 0, sizeof(*req)); |
| 686 | req->pool = pool; | ||
| 686 | return req; | 687 | return req; |
| 687 | } | 688 | } |
| 688 | 689 | ||
| @@ -769,28 +770,24 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, | |||
| 769 | static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) | 770 | static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) |
| 770 | { | 771 | { |
| 771 | struct zfcp_adapter *adapter = req->adapter; | 772 | struct zfcp_adapter *adapter = req->adapter; |
| 772 | struct zfcp_qdio_queue *req_q = &adapter->req_q; | 773 | unsigned long flags; |
| 773 | int idx; | 774 | int idx; |
| 774 | 775 | ||
| 775 | /* put allocated FSF request into hash table */ | 776 | /* put allocated FSF request into hash table */ |
| 776 | spin_lock(&adapter->req_list_lock); | 777 | spin_lock_irqsave(&adapter->req_list_lock, flags); |
| 777 | idx = zfcp_reqlist_hash(req->req_id); | 778 | idx = zfcp_reqlist_hash(req->req_id); |
| 778 | list_add_tail(&req->list, &adapter->req_list[idx]); | 779 | list_add_tail(&req->list, &adapter->req_list[idx]); |
| 779 | spin_unlock(&adapter->req_list_lock); | 780 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); |
| 780 | 781 | ||
| 781 | req->qdio_outb_usage = atomic_read(&req_q->count); | 782 | req->qdio_outb_usage = atomic_read(&adapter->req_q.count); |
| 782 | req->issued = get_clock(); | 783 | req->issued = get_clock(); |
| 783 | if (zfcp_qdio_send(req)) { | 784 | if (zfcp_qdio_send(req)) { |
| 784 | /* Queues are down..... */ | ||
| 785 | del_timer(&req->timer); | 785 | del_timer(&req->timer); |
| 786 | spin_lock(&adapter->req_list_lock); | 786 | spin_lock_irqsave(&adapter->req_list_lock, flags); |
| 787 | zfcp_reqlist_remove(adapter, req); | 787 | /* lookup request again, list might have changed */ |
| 788 | spin_unlock(&adapter->req_list_lock); | 788 | if (zfcp_reqlist_find_safe(adapter, req)) |
| 789 | /* undo changes in request queue made for this request */ | 789 | zfcp_reqlist_remove(adapter, req); |
| 790 | atomic_add(req->sbal_number, &req_q->count); | 790 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); |
| 791 | req_q->first -= req->sbal_number; | ||
| 792 | req_q->first += QDIO_MAX_BUFFERS_PER_Q; | ||
| 793 | req_q->first %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ | ||
| 794 | zfcp_erp_adapter_reopen(adapter, 0, 116, req); | 791 | zfcp_erp_adapter_reopen(adapter, 0, 116, req); |
| 795 | return -EIO; | 792 | return -EIO; |
| 796 | } | 793 | } |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index ca8f85f3dad4..e46fd3e9f68f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
| @@ -24,14 +24,10 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu) | |||
| 24 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | 24 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) |
| 25 | { | 25 | { |
| 26 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; | 26 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; |
| 27 | WARN_ON(!unit); | 27 | atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); |
| 28 | if (unit) { | 28 | unit->device = NULL; |
| 29 | atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); | 29 | zfcp_erp_unit_failed(unit, 12, NULL); |
| 30 | sdpnt->hostdata = NULL; | 30 | zfcp_unit_put(unit); |
| 31 | unit->device = NULL; | ||
| 32 | zfcp_erp_unit_failed(unit, 12, NULL); | ||
| 33 | zfcp_unit_put(unit); | ||
| 34 | } | ||
| 35 | } | 31 | } |
| 36 | 32 | ||
| 37 | static int zfcp_scsi_slave_configure(struct scsi_device *sdp) | 33 | static int zfcp_scsi_slave_configure(struct scsi_device *sdp) |
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 8aba4fdfb522..6194ed5d02c4 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c | |||
| @@ -2445,7 +2445,7 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) | |||
| 2445 | hba_status = detailed_status >> 8; | 2445 | hba_status = detailed_status >> 8; |
| 2446 | 2446 | ||
| 2447 | // calculate resid for sg | 2447 | // calculate resid for sg |
| 2448 | scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+5)); | 2448 | scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+20)); |
| 2449 | 2449 | ||
| 2450 | pHba = (adpt_hba*) cmd->device->host->hostdata[0]; | 2450 | pHba = (adpt_hba*) cmd->device->host->hostdata[0]; |
| 2451 | 2451 | ||
| @@ -2456,7 +2456,7 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) | |||
| 2456 | case I2O_SCSI_DSC_SUCCESS: | 2456 | case I2O_SCSI_DSC_SUCCESS: |
| 2457 | cmd->result = (DID_OK << 16); | 2457 | cmd->result = (DID_OK << 16); |
| 2458 | // handle underflow | 2458 | // handle underflow |
| 2459 | if(readl(reply+5) < cmd->underflow ) { | 2459 | if (readl(reply+20) < cmd->underflow) { |
| 2460 | cmd->result = (DID_ERROR <<16); | 2460 | cmd->result = (DID_ERROR <<16); |
| 2461 | printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name); | 2461 | printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name); |
| 2462 | } | 2462 | } |
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 28c9da7d4a5c..7dc62deb4087 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
| @@ -4402,6 +4402,10 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) | |||
| 4402 | scb_t *scb; | 4402 | scb_t *scb; |
| 4403 | int rval; | 4403 | int rval; |
| 4404 | 4404 | ||
| 4405 | scmd = scsi_allocate_command(GFP_KERNEL); | ||
| 4406 | if (!scmd) | ||
| 4407 | return -ENOMEM; | ||
| 4408 | |||
| 4405 | /* | 4409 | /* |
| 4406 | * The internal commands share one command id and hence are | 4410 | * The internal commands share one command id and hence are |
| 4407 | * serialized. This is so because we want to reserve maximum number of | 4411 | * serialized. This is so because we want to reserve maximum number of |
| @@ -4412,12 +4416,11 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) | |||
| 4412 | scb = &adapter->int_scb; | 4416 | scb = &adapter->int_scb; |
| 4413 | memset(scb, 0, sizeof(scb_t)); | 4417 | memset(scb, 0, sizeof(scb_t)); |
| 4414 | 4418 | ||
| 4415 | scmd = &adapter->int_scmd; | ||
| 4416 | memset(scmd, 0, sizeof(Scsi_Cmnd)); | ||
| 4417 | |||
| 4418 | sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); | 4419 | sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); |
| 4419 | scmd->device = sdev; | 4420 | scmd->device = sdev; |
| 4420 | 4421 | ||
| 4422 | memset(adapter->int_cdb, 0, sizeof(adapter->int_cdb)); | ||
| 4423 | scmd->cmnd = adapter->int_cdb; | ||
| 4421 | scmd->device->host = adapter->host; | 4424 | scmd->device->host = adapter->host; |
| 4422 | scmd->host_scribble = (void *)scb; | 4425 | scmd->host_scribble = (void *)scb; |
| 4423 | scmd->cmnd[0] = MEGA_INTERNAL_CMD; | 4426 | scmd->cmnd[0] = MEGA_INTERNAL_CMD; |
| @@ -4456,6 +4459,8 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) | |||
| 4456 | 4459 | ||
| 4457 | mutex_unlock(&adapter->int_mtx); | 4460 | mutex_unlock(&adapter->int_mtx); |
| 4458 | 4461 | ||
| 4462 | scsi_free_command(GFP_KERNEL, scmd); | ||
| 4463 | |||
| 4459 | return rval; | 4464 | return rval; |
| 4460 | } | 4465 | } |
| 4461 | 4466 | ||
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h index ee70bd4ae4ba..795201fa0b48 100644 --- a/drivers/scsi/megaraid.h +++ b/drivers/scsi/megaraid.h | |||
| @@ -888,8 +888,8 @@ typedef struct { | |||
| 888 | 888 | ||
| 889 | u8 sglen; /* f/w supported scatter-gather list length */ | 889 | u8 sglen; /* f/w supported scatter-gather list length */ |
| 890 | 890 | ||
| 891 | unsigned char int_cdb[MAX_COMMAND_SIZE]; | ||
| 891 | scb_t int_scb; | 892 | scb_t int_scb; |
| 892 | Scsi_Cmnd int_scmd; | ||
| 893 | struct mutex int_mtx; /* To synchronize the internal | 893 | struct mutex int_mtx; /* To synchronize the internal |
| 894 | commands */ | 894 | commands */ |
| 895 | struct completion int_waitq; /* wait queue for internal | 895 | struct completion int_waitq; /* wait queue for internal |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index f25f41a499e5..b97194096d8e 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
| @@ -2547,7 +2547,6 @@ typedef struct scsi_qla_host { | |||
| 2547 | uint8_t fcode_revision[16]; | 2547 | uint8_t fcode_revision[16]; |
| 2548 | uint32_t fw_revision[4]; | 2548 | uint32_t fw_revision[4]; |
| 2549 | 2549 | ||
| 2550 | uint16_t fdt_odd_index; | ||
| 2551 | uint32_t fdt_wrt_disable; | 2550 | uint32_t fdt_wrt_disable; |
| 2552 | uint32_t fdt_erase_cmd; | 2551 | uint32_t fdt_erase_cmd; |
| 2553 | uint32_t fdt_block_size; | 2552 | uint32_t fdt_block_size; |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a470f2d3270d..4218f20f5ed5 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
| @@ -140,7 +140,6 @@ int | |||
| 140 | qla2100_pci_config(scsi_qla_host_t *ha) | 140 | qla2100_pci_config(scsi_qla_host_t *ha) |
| 141 | { | 141 | { |
| 142 | uint16_t w; | 142 | uint16_t w; |
| 143 | uint32_t d; | ||
| 144 | unsigned long flags; | 143 | unsigned long flags; |
| 145 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 144 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
| 146 | 145 | ||
| @@ -151,10 +150,7 @@ qla2100_pci_config(scsi_qla_host_t *ha) | |||
| 151 | w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | 150 | w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); |
| 152 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); | 151 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); |
| 153 | 152 | ||
| 154 | /* Reset expansion ROM address decode enable */ | 153 | pci_disable_rom(ha->pdev); |
| 155 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); | ||
| 156 | d &= ~PCI_ROM_ADDRESS_ENABLE; | ||
| 157 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); | ||
| 158 | 154 | ||
| 159 | /* Get PCI bus information. */ | 155 | /* Get PCI bus information. */ |
| 160 | spin_lock_irqsave(&ha->hardware_lock, flags); | 156 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| @@ -174,7 +170,6 @@ int | |||
| 174 | qla2300_pci_config(scsi_qla_host_t *ha) | 170 | qla2300_pci_config(scsi_qla_host_t *ha) |
| 175 | { | 171 | { |
| 176 | uint16_t w; | 172 | uint16_t w; |
| 177 | uint32_t d; | ||
| 178 | unsigned long flags = 0; | 173 | unsigned long flags = 0; |
| 179 | uint32_t cnt; | 174 | uint32_t cnt; |
| 180 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 175 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
| @@ -236,10 +231,7 @@ qla2300_pci_config(scsi_qla_host_t *ha) | |||
| 236 | 231 | ||
| 237 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); | 232 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); |
| 238 | 233 | ||
| 239 | /* Reset expansion ROM address decode enable */ | 234 | pci_disable_rom(ha->pdev); |
| 240 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); | ||
| 241 | d &= ~PCI_ROM_ADDRESS_ENABLE; | ||
| 242 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); | ||
| 243 | 235 | ||
| 244 | /* Get PCI bus information. */ | 236 | /* Get PCI bus information. */ |
| 245 | spin_lock_irqsave(&ha->hardware_lock, flags); | 237 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| @@ -259,7 +251,6 @@ int | |||
| 259 | qla24xx_pci_config(scsi_qla_host_t *ha) | 251 | qla24xx_pci_config(scsi_qla_host_t *ha) |
| 260 | { | 252 | { |
| 261 | uint16_t w; | 253 | uint16_t w; |
| 262 | uint32_t d; | ||
| 263 | unsigned long flags = 0; | 254 | unsigned long flags = 0; |
| 264 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 255 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
| 265 | 256 | ||
| @@ -281,10 +272,7 @@ qla24xx_pci_config(scsi_qla_host_t *ha) | |||
| 281 | if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) | 272 | if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) |
| 282 | pcie_set_readrq(ha->pdev, 2048); | 273 | pcie_set_readrq(ha->pdev, 2048); |
| 283 | 274 | ||
| 284 | /* Reset expansion ROM address decode enable */ | 275 | pci_disable_rom(ha->pdev); |
| 285 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); | ||
| 286 | d &= ~PCI_ROM_ADDRESS_ENABLE; | ||
| 287 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); | ||
| 288 | 276 | ||
| 289 | ha->chip_revision = ha->pdev->revision; | 277 | ha->chip_revision = ha->pdev->revision; |
| 290 | 278 | ||
| @@ -306,7 +294,6 @@ int | |||
| 306 | qla25xx_pci_config(scsi_qla_host_t *ha) | 294 | qla25xx_pci_config(scsi_qla_host_t *ha) |
| 307 | { | 295 | { |
| 308 | uint16_t w; | 296 | uint16_t w; |
| 309 | uint32_t d; | ||
| 310 | 297 | ||
| 311 | pci_set_master(ha->pdev); | 298 | pci_set_master(ha->pdev); |
| 312 | pci_try_set_mwi(ha->pdev); | 299 | pci_try_set_mwi(ha->pdev); |
| @@ -320,10 +307,7 @@ qla25xx_pci_config(scsi_qla_host_t *ha) | |||
| 320 | if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) | 307 | if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) |
| 321 | pcie_set_readrq(ha->pdev, 2048); | 308 | pcie_set_readrq(ha->pdev, 2048); |
| 322 | 309 | ||
| 323 | /* Reset expansion ROM address decode enable */ | 310 | pci_disable_rom(ha->pdev); |
| 324 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); | ||
| 325 | d &= ~PCI_ROM_ADDRESS_ENABLE; | ||
| 326 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); | ||
| 327 | 311 | ||
| 328 | ha->chip_revision = ha->pdev->revision; | 312 | ha->chip_revision = ha->pdev->revision; |
| 329 | 313 | ||
| @@ -980,7 +964,6 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) | |||
| 980 | &ha->fw_minor_version, | 964 | &ha->fw_minor_version, |
| 981 | &ha->fw_subminor_version, | 965 | &ha->fw_subminor_version, |
| 982 | &ha->fw_attributes, &ha->fw_memory_size); | 966 | &ha->fw_attributes, &ha->fw_memory_size); |
| 983 | qla2x00_resize_request_q(ha); | ||
| 984 | ha->flags.npiv_supported = 0; | 967 | ha->flags.npiv_supported = 0; |
| 985 | if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) || | 968 | if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) || |
| 986 | IS_QLA84XX(ha)) && | 969 | IS_QLA84XX(ha)) && |
| @@ -992,6 +975,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) | |||
| 992 | ha->max_npiv_vports = | 975 | ha->max_npiv_vports = |
| 993 | MIN_MULTI_ID_FABRIC - 1; | 976 | MIN_MULTI_ID_FABRIC - 1; |
| 994 | } | 977 | } |
| 978 | qla2x00_resize_request_q(ha); | ||
| 995 | 979 | ||
| 996 | if (ql2xallocfwdump) | 980 | if (ql2xallocfwdump) |
| 997 | qla2x00_alloc_fw_dump(ha); | 981 | qla2x00_alloc_fw_dump(ha); |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 36bc6851e23d..3402746ec128 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
| @@ -1964,7 +1964,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, | |||
| 1964 | *cur_iocb_cnt = mcp->mb[7]; | 1964 | *cur_iocb_cnt = mcp->mb[7]; |
| 1965 | if (orig_iocb_cnt) | 1965 | if (orig_iocb_cnt) |
| 1966 | *orig_iocb_cnt = mcp->mb[10]; | 1966 | *orig_iocb_cnt = mcp->mb[10]; |
| 1967 | if (max_npiv_vports) | 1967 | if (ha->flags.npiv_supported && max_npiv_vports) |
| 1968 | *max_npiv_vports = mcp->mb[11]; | 1968 | *max_npiv_vports = mcp->mb[11]; |
| 1969 | } | 1969 | } |
| 1970 | 1970 | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 21dd182ad512..35567203ef61 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
| @@ -728,6 +728,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
| 728 | if (ha->isp_ops->abort_command(ha, sp)) { | 728 | if (ha->isp_ops->abort_command(ha, sp)) { |
| 729 | DEBUG2(printk("%s(%ld): abort_command " | 729 | DEBUG2(printk("%s(%ld): abort_command " |
| 730 | "mbx failed.\n", __func__, ha->host_no)); | 730 | "mbx failed.\n", __func__, ha->host_no)); |
| 731 | ret = FAILED; | ||
| 731 | } else { | 732 | } else { |
| 732 | DEBUG3(printk("%s(%ld): abort_command " | 733 | DEBUG3(printk("%s(%ld): abort_command " |
| 733 | "mbx success.\n", __func__, ha->host_no)); | 734 | "mbx success.\n", __func__, ha->host_no)); |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 90a13211717f..e4af678eb2d6 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
| @@ -722,6 +722,7 @@ done: | |||
| 722 | static void | 722 | static void |
| 723 | qla2xxx_get_fdt_info(scsi_qla_host_t *ha) | 723 | qla2xxx_get_fdt_info(scsi_qla_host_t *ha) |
| 724 | { | 724 | { |
| 725 | #define FLASH_BLK_SIZE_4K 0x1000 | ||
| 725 | #define FLASH_BLK_SIZE_32K 0x8000 | 726 | #define FLASH_BLK_SIZE_32K 0x8000 |
| 726 | #define FLASH_BLK_SIZE_64K 0x10000 | 727 | #define FLASH_BLK_SIZE_64K 0x10000 |
| 727 | const char *loc, *locations[] = { "MID", "FDT" }; | 728 | const char *loc, *locations[] = { "MID", "FDT" }; |
| @@ -755,7 +756,6 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *ha) | |||
| 755 | loc = locations[1]; | 756 | loc = locations[1]; |
| 756 | mid = le16_to_cpu(fdt->man_id); | 757 | mid = le16_to_cpu(fdt->man_id); |
| 757 | fid = le16_to_cpu(fdt->id); | 758 | fid = le16_to_cpu(fdt->id); |
| 758 | ha->fdt_odd_index = mid == 0x1f; | ||
| 759 | ha->fdt_wrt_disable = fdt->wrt_disable_bits; | 759 | ha->fdt_wrt_disable = fdt->wrt_disable_bits; |
| 760 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); | 760 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); |
| 761 | ha->fdt_block_size = le32_to_cpu(fdt->block_size); | 761 | ha->fdt_block_size = le32_to_cpu(fdt->block_size); |
| @@ -788,8 +788,7 @@ no_flash_data: | |||
| 788 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; | 788 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; |
| 789 | break; | 789 | break; |
| 790 | case 0x1f: /* Atmel 26DF081A. */ | 790 | case 0x1f: /* Atmel 26DF081A. */ |
| 791 | ha->fdt_odd_index = 1; | 791 | ha->fdt_block_size = FLASH_BLK_SIZE_4K; |
| 792 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; | ||
| 793 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0320); | 792 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0320); |
| 794 | ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0339); | 793 | ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0339); |
| 795 | ha->fdt_protect_sec_cmd = flash_conf_to_access_addr(0x0336); | 794 | ha->fdt_protect_sec_cmd = flash_conf_to_access_addr(0x0336); |
| @@ -801,9 +800,9 @@ no_flash_data: | |||
| 801 | } | 800 | } |
| 802 | done: | 801 | done: |
| 803 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " | 802 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " |
| 804 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", loc, mid, fid, | 803 | "pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid, |
| 805 | ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, | 804 | ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, |
| 806 | ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable, | 805 | ha->fdt_unprotect_sec_cmd, ha->fdt_wrt_disable, |
| 807 | ha->fdt_block_size)); | 806 | ha->fdt_block_size)); |
| 808 | } | 807 | } |
| 809 | 808 | ||
| @@ -987,13 +986,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
| 987 | qla24xx_unprotect_flash(ha); | 986 | qla24xx_unprotect_flash(ha); |
| 988 | 987 | ||
| 989 | for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { | 988 | for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { |
| 990 | if (ha->fdt_odd_index) { | 989 | |
| 991 | findex = faddr << 2; | 990 | findex = faddr; |
| 992 | fdata = findex & sec_mask; | 991 | fdata = (findex & sec_mask) << 2; |
| 993 | } else { | ||
| 994 | findex = faddr; | ||
| 995 | fdata = (findex & sec_mask) << 2; | ||
| 996 | } | ||
| 997 | 992 | ||
| 998 | /* Are we at the beginning of a sector? */ | 993 | /* Are we at the beginning of a sector? */ |
| 999 | if ((findex & rest_addr) == 0) { | 994 | if ((findex & rest_addr) == 0) { |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index be5e299df528..eea6720adf16 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | /* | 7 | /* |
| 8 | * Driver version | 8 | * Driver version |
| 9 | */ | 9 | */ |
| 10 | #define QLA2XXX_VERSION "8.02.01-k8" | 10 | #define QLA2XXX_VERSION "8.02.01-k9" |
| 11 | 11 | ||
| 12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
| 13 | #define QLA_DRIVER_MINOR_VER 2 | 13 | #define QLA_DRIVER_MINOR_VER 2 |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 94ed262bdf0c..386361778ebb 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
| @@ -1340,9 +1340,10 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) | |||
| 1340 | * LLD/transport was disrupted during processing of the IO. | 1340 | * LLD/transport was disrupted during processing of the IO. |
| 1341 | * The transport class is now blocked/blocking, | 1341 | * The transport class is now blocked/blocking, |
| 1342 | * and the transport will decide what to do with the IO | 1342 | * and the transport will decide what to do with the IO |
| 1343 | * based on its timers and recovery capablilities. | 1343 | * based on its timers and recovery capablilities if |
| 1344 | * there are enough retries. | ||
| 1344 | */ | 1345 | */ |
| 1345 | return ADD_TO_MLQUEUE; | 1346 | goto maybe_retry; |
| 1346 | case DID_TRANSPORT_FAILFAST: | 1347 | case DID_TRANSPORT_FAILFAST: |
| 1347 | /* | 1348 | /* |
| 1348 | * The transport decided to failfast the IO (most likely | 1349 | * The transport decided to failfast the IO (most likely |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 5c0f32c7fbf6..165fc010978c 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
| @@ -144,9 +144,9 @@ static void put_char(struct uart_port *port, char c) | |||
| 144 | status = sci_in(port, SCxSR); | 144 | status = sci_in(port, SCxSR); |
| 145 | } while (!(status & SCxSR_TDxE(port))); | 145 | } while (!(status & SCxSR_TDxE(port))); |
| 146 | 146 | ||
| 147 | sci_out(port, SCxTDR, c); | ||
| 148 | sci_in(port, SCxSR); /* Dummy read */ | 147 | sci_in(port, SCxSR); /* Dummy read */ |
| 149 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); | 148 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); |
| 149 | sci_out(port, SCxTDR, c); | ||
| 150 | 150 | ||
| 151 | spin_unlock_irqrestore(&port->lock, flags); | 151 | spin_unlock_irqrestore(&port->lock, flags); |
| 152 | } | 152 | } |
| @@ -478,10 +478,10 @@ static void sci_transmit_chars(struct uart_port *port) | |||
| 478 | return; | 478 | return; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | if (port->type == PORT_SCIF) | 481 | if (port->type == PORT_SCI) |
| 482 | count = scif_txroom(port); | ||
| 483 | else | ||
| 484 | count = sci_txroom(port); | 482 | count = sci_txroom(port); |
| 483 | else | ||
| 484 | count = scif_txroom(port); | ||
| 485 | 485 | ||
| 486 | do { | 486 | do { |
| 487 | unsigned char c; | 487 | unsigned char c; |
| @@ -510,7 +510,7 @@ static void sci_transmit_chars(struct uart_port *port) | |||
| 510 | } else { | 510 | } else { |
| 511 | ctrl = sci_in(port, SCSCR); | 511 | ctrl = sci_in(port, SCSCR); |
| 512 | 512 | ||
| 513 | if (port->type == PORT_SCIF) { | 513 | if (port->type != PORT_SCI) { |
| 514 | sci_in(port, SCxSR); /* Dummy read */ | 514 | sci_in(port, SCxSR); /* Dummy read */ |
| 515 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); | 515 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); |
| 516 | } | 516 | } |
| @@ -536,10 +536,10 @@ static inline void sci_receive_chars(struct uart_port *port) | |||
| 536 | return; | 536 | return; |
| 537 | 537 | ||
| 538 | while (1) { | 538 | while (1) { |
| 539 | if (port->type == PORT_SCIF) | 539 | if (port->type == PORT_SCI) |
| 540 | count = scif_rxroom(port); | ||
| 541 | else | ||
| 542 | count = sci_rxroom(port); | 540 | count = sci_rxroom(port); |
| 541 | else | ||
| 542 | count = scif_rxroom(port); | ||
| 543 | 543 | ||
| 544 | /* Don't copy more bytes than there is room for in the buffer */ | 544 | /* Don't copy more bytes than there is room for in the buffer */ |
| 545 | count = tty_buffer_request_room(tty, count); | 545 | count = tty_buffer_request_room(tty, count); |
| @@ -714,7 +714,7 @@ static inline int sci_handle_breaks(struct uart_port *port) | |||
| 714 | 714 | ||
| 715 | #if defined(SCIF_ORER) | 715 | #if defined(SCIF_ORER) |
| 716 | /* XXX: Handle SCIF overrun error */ | 716 | /* XXX: Handle SCIF overrun error */ |
| 717 | if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { | 717 | if (port->type != PORT_SCI && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { |
| 718 | sci_out(port, SCLSR, 0); | 718 | sci_out(port, SCLSR, 0); |
| 719 | if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) { | 719 | if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) { |
| 720 | copied++; | 720 | copied++; |
| @@ -1042,7 +1042,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1042 | 1042 | ||
| 1043 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ | 1043 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ |
| 1044 | 1044 | ||
| 1045 | if (port->type == PORT_SCIF) | 1045 | if (port->type != PORT_SCI) |
| 1046 | sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); | 1046 | sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); |
| 1047 | 1047 | ||
| 1048 | smr_val = sci_in(port, SCSMR) & 3; | 1048 | smr_val = sci_in(port, SCSMR) & 3; |
| @@ -1085,6 +1085,7 @@ static const char *sci_type(struct uart_port *port) | |||
| 1085 | case PORT_SCI: return "sci"; | 1085 | case PORT_SCI: return "sci"; |
| 1086 | case PORT_SCIF: return "scif"; | 1086 | case PORT_SCIF: return "scif"; |
| 1087 | case PORT_IRDA: return "irda"; | 1087 | case PORT_IRDA: return "irda"; |
| 1088 | case PORT_SCIFA: return "scifa"; | ||
| 1088 | } | 1089 | } |
| 1089 | 1090 | ||
| 1090 | return NULL; | 1091 | return NULL; |
| @@ -1112,6 +1113,7 @@ static void sci_config_port(struct uart_port *port, int flags) | |||
| 1112 | s->init_pins = sci_init_pins_sci; | 1113 | s->init_pins = sci_init_pins_sci; |
| 1113 | break; | 1114 | break; |
| 1114 | case PORT_SCIF: | 1115 | case PORT_SCIF: |
| 1116 | case PORT_SCIFA: | ||
| 1115 | s->init_pins = sci_init_pins_scif; | 1117 | s->init_pins = sci_init_pins_scif; |
| 1116 | break; | 1118 | break; |
| 1117 | case PORT_IRDA: | 1119 | case PORT_IRDA: |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 6163a45f968f..9f33b064172e 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
| @@ -289,18 +289,18 @@ | |||
| 289 | #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ | 289 | #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ |
| 290 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ | 290 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ |
| 291 | { \ | 291 | { \ |
| 292 | if (port->type == PORT_SCI) { \ | 292 | if (port->type == PORT_SCIF) { \ |
| 293 | SCI_IN(sci_size, sci_offset) \ | 293 | SCI_IN(scif_size, scif_offset) \ |
| 294 | } else { \ | 294 | } else { /* PORT_SCI or PORT_SCIFA */ \ |
| 295 | SCI_IN(scif_size, scif_offset); \ | 295 | SCI_IN(sci_size, sci_offset); \ |
| 296 | } \ | 296 | } \ |
| 297 | } \ | 297 | } \ |
| 298 | static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ | 298 | static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ |
| 299 | { \ | 299 | { \ |
| 300 | if (port->type == PORT_SCI) { \ | 300 | if (port->type == PORT_SCIF) { \ |
| 301 | SCI_OUT(sci_size, sci_offset, value) \ | 301 | SCI_OUT(scif_size, scif_offset, value) \ |
| 302 | } else { \ | 302 | } else { /* PORT_SCI or PORT_SCIFA */ \ |
| 303 | SCI_OUT(scif_size, scif_offset, value); \ | 303 | SCI_OUT(sci_size, sci_offset, value); \ |
| 304 | } \ | 304 | } \ |
| 305 | } | 305 | } |
| 306 | 306 | ||
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 02f9320f3efc..8abae4ad0fa5 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c | |||
| @@ -766,6 +766,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev) | |||
| 766 | /* Initialize the hardware */ | 766 | /* Initialize the hardware */ |
| 767 | clk_enable(clk); | 767 | clk_enable(clk); |
| 768 | spi_writel(as, CR, SPI_BIT(SWRST)); | 768 | spi_writel(as, CR, SPI_BIT(SWRST)); |
| 769 | spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ | ||
| 769 | spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS)); | 770 | spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS)); |
| 770 | spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); | 771 | spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); |
| 771 | spi_writel(as, CR, SPI_BIT(SPIEN)); | 772 | spi_writel(as, CR, SPI_BIT(SPIEN)); |
| @@ -782,6 +783,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev) | |||
| 782 | 783 | ||
| 783 | out_reset_hw: | 784 | out_reset_hw: |
| 784 | spi_writel(as, CR, SPI_BIT(SWRST)); | 785 | spi_writel(as, CR, SPI_BIT(SWRST)); |
| 786 | spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ | ||
| 785 | clk_disable(clk); | 787 | clk_disable(clk); |
| 786 | free_irq(irq, master); | 788 | free_irq(irq, master); |
| 787 | out_unmap_regs: | 789 | out_unmap_regs: |
| @@ -805,6 +807,7 @@ static int __exit atmel_spi_remove(struct platform_device *pdev) | |||
| 805 | spin_lock_irq(&as->lock); | 807 | spin_lock_irq(&as->lock); |
| 806 | as->stopping = 1; | 808 | as->stopping = 1; |
| 807 | spi_writel(as, CR, SPI_BIT(SWRST)); | 809 | spi_writel(as, CR, SPI_BIT(SWRST)); |
| 810 | spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ | ||
| 808 | spi_readl(as, SR); | 811 | spi_readl(as, SR); |
| 809 | spin_unlock_irq(&as->lock); | 812 | spin_unlock_irq(&as->lock); |
| 810 | 813 | ||
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index 307b1f62d949..b1b947edcf01 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig | |||
| @@ -1,10 +1,11 @@ | |||
| 1 | menu "Sonics Silicon Backplane" | ||
| 2 | |||
| 3 | config SSB_POSSIBLE | 1 | config SSB_POSSIBLE |
| 4 | bool | 2 | bool |
| 5 | depends on HAS_IOMEM && HAS_DMA | 3 | depends on HAS_IOMEM && HAS_DMA |
| 6 | default y | 4 | default y |
| 7 | 5 | ||
| 6 | menu "Sonics Silicon Backplane" | ||
| 7 | depends on SSB_POSSIBLE | ||
| 8 | |||
| 8 | config SSB | 9 | config SSB |
| 9 | tristate "Sonics Silicon Backplane support" | 10 | tristate "Sonics Silicon Backplane support" |
| 10 | depends on SSB_POSSIBLE | 11 | depends on SSB_POSSIBLE |
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c index 37caf4d69037..b52cc830c0b4 100644 --- a/drivers/telephony/phonedev.c +++ b/drivers/telephony/phonedev.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
| 9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
| 10 | * | 10 | * |
| 11 | * Author: Alan Cox, <alan@redhat.com> | 11 | * Author: Alan Cox, <alan@lxorguk.ukuu.org.uk> |
| 12 | * | 12 | * |
| 13 | * Fixes: Mar 01 2000 Thomas Sparr, <thomas.l.sparr@telia.com> | 13 | * Fixes: Mar 01 2000 Thomas Sparr, <thomas.l.sparr@telia.com> |
| 14 | * phone_register_device now works with unit!=PHONE_UNIT_ANY | 14 | * phone_register_device now works with unit!=PHONE_UNIT_ANY |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 20104443081a..d50a99f70aee 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
| @@ -158,16 +158,12 @@ static int acm_wb_is_avail(struct acm *acm) | |||
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | /* | 160 | /* |
| 161 | * Finish write. | 161 | * Finish write. Caller must hold acm->write_lock |
| 162 | */ | 162 | */ |
| 163 | static void acm_write_done(struct acm *acm, struct acm_wb *wb) | 163 | static void acm_write_done(struct acm *acm, struct acm_wb *wb) |
| 164 | { | 164 | { |
| 165 | unsigned long flags; | ||
| 166 | |||
| 167 | spin_lock_irqsave(&acm->write_lock, flags); | ||
| 168 | wb->use = 0; | 165 | wb->use = 0; |
| 169 | acm->transmitting--; | 166 | acm->transmitting--; |
| 170 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
| 171 | } | 167 | } |
| 172 | 168 | ||
| 173 | /* | 169 | /* |
| @@ -482,6 +478,7 @@ static void acm_write_bulk(struct urb *urb) | |||
| 482 | { | 478 | { |
| 483 | struct acm_wb *wb = urb->context; | 479 | struct acm_wb *wb = urb->context; |
| 484 | struct acm *acm = wb->instance; | 480 | struct acm *acm = wb->instance; |
| 481 | unsigned long flags; | ||
| 485 | 482 | ||
| 486 | if (verbose || urb->status | 483 | if (verbose || urb->status |
| 487 | || (urb->actual_length != urb->transfer_buffer_length)) | 484 | || (urb->actual_length != urb->transfer_buffer_length)) |
| @@ -490,7 +487,9 @@ static void acm_write_bulk(struct urb *urb) | |||
| 490 | urb->transfer_buffer_length, | 487 | urb->transfer_buffer_length, |
| 491 | urb->status); | 488 | urb->status); |
| 492 | 489 | ||
| 490 | spin_lock_irqsave(&acm->write_lock, flags); | ||
| 493 | acm_write_done(acm, wb); | 491 | acm_write_done(acm, wb); |
| 492 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
| 494 | if (ACM_READY(acm)) | 493 | if (ACM_READY(acm)) |
| 495 | schedule_work(&acm->work); | 494 | schedule_work(&acm->work); |
| 496 | else | 495 | else |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 887738577b28..6d1048faf08e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -1091,6 +1091,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
| 1091 | continue; | 1091 | continue; |
| 1092 | dev_dbg(&dev->dev, "unregistering interface %s\n", | 1092 | dev_dbg(&dev->dev, "unregistering interface %s\n", |
| 1093 | dev_name(&interface->dev)); | 1093 | dev_name(&interface->dev)); |
| 1094 | interface->unregistering = 1; | ||
| 1094 | usb_remove_sysfs_intf_files(interface); | 1095 | usb_remove_sysfs_intf_files(interface); |
| 1095 | device_del(&interface->dev); | 1096 | device_del(&interface->dev); |
| 1096 | } | 1097 | } |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index f66fba11fbd5..4fb65fdc9dc3 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
| @@ -840,7 +840,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) | |||
| 840 | struct usb_host_interface *alt = intf->cur_altsetting; | 840 | struct usb_host_interface *alt = intf->cur_altsetting; |
| 841 | int retval; | 841 | int retval; |
| 842 | 842 | ||
| 843 | if (intf->sysfs_files_created) | 843 | if (intf->sysfs_files_created || intf->unregistering) |
| 844 | return 0; | 844 | return 0; |
| 845 | 845 | ||
| 846 | /* The interface string may be present in some altsettings | 846 | /* The interface string may be present in some altsettings |
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 4342bd9c3bb6..1f68af9db3f7 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
| @@ -85,8 +85,8 @@ EXPORT_SYMBOL_GPL(usb_alloc_urb); | |||
| 85 | * Must be called when a user of a urb is finished with it. When the last user | 85 | * Must be called when a user of a urb is finished with it. When the last user |
| 86 | * of the urb calls this function, the memory of the urb is freed. | 86 | * of the urb calls this function, the memory of the urb is freed. |
| 87 | * | 87 | * |
| 88 | * Note: The transfer buffer associated with the urb is not freed, that must be | 88 | * Note: The transfer buffer associated with the urb is not freed unless the |
| 89 | * done elsewhere. | 89 | * URB_FREE_BUFFER transfer flag is set. |
| 90 | */ | 90 | */ |
| 91 | void usb_free_urb(struct urb *urb) | 91 | void usb_free_urb(struct urb *urb) |
| 92 | { | 92 | { |
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index 5ee1590b8e9c..c1d34df0b157 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c | |||
| @@ -463,7 +463,11 @@ static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value, | |||
| 463 | notify->wLength = cpu_to_le16(length); | 463 | notify->wLength = cpu_to_le16(length); |
| 464 | memcpy(buf, data, length); | 464 | memcpy(buf, data, length); |
| 465 | 465 | ||
| 466 | /* ep_queue() can complete immediately if it fills the fifo... */ | ||
| 467 | spin_unlock(&acm->lock); | ||
| 466 | status = usb_ep_queue(ep, req, GFP_ATOMIC); | 468 | status = usb_ep_queue(ep, req, GFP_ATOMIC); |
| 469 | spin_lock(&acm->lock); | ||
| 470 | |||
| 467 | if (status < 0) { | 471 | if (status < 0) { |
| 468 | ERROR(acm->port.func.config->cdev, | 472 | ERROR(acm->port.func.config->cdev, |
| 469 | "acm ttyGS%d can't notify serial state, %d\n", | 473 | "acm ttyGS%d can't notify serial state, %d\n", |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 56f592dc0b36..f3a75a929e0a 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
| @@ -110,29 +110,18 @@ config USB_ISP116X_HCD | |||
| 110 | 110 | ||
| 111 | config USB_ISP1760_HCD | 111 | config USB_ISP1760_HCD |
| 112 | tristate "ISP 1760 HCD support" | 112 | tristate "ISP 1760 HCD support" |
| 113 | depends on USB && EXPERIMENTAL | 113 | depends on USB && EXPERIMENTAL && (PCI || PPC_OF) |
| 114 | ---help--- | 114 | ---help--- |
| 115 | The ISP1760 chip is a USB 2.0 host controller. | 115 | The ISP1760 chip is a USB 2.0 host controller. |
| 116 | 116 | ||
| 117 | This driver does not support isochronous transfers or OTG. | 117 | This driver does not support isochronous transfers or OTG. |
| 118 | This USB controller is usually attached to a non-DMA-Master | ||
| 119 | capable bus. NXP's eval kit brings this chip on PCI card | ||
| 120 | where the chip itself is behind a PLB to simulate such | ||
| 121 | a bus. | ||
| 118 | 122 | ||
| 119 | To compile this driver as a module, choose M here: the | 123 | To compile this driver as a module, choose M here: the |
| 120 | module will be called isp1760-hcd. | 124 | module will be called isp1760. |
| 121 | |||
| 122 | config USB_ISP1760_PCI | ||
| 123 | bool "Support for the PCI bus" | ||
| 124 | depends on USB_ISP1760_HCD && PCI | ||
| 125 | ---help--- | ||
| 126 | Enables support for the device present on the PCI bus. | ||
| 127 | This should only be required if you happen to have the eval kit from | ||
| 128 | NXP and you are going to test it. | ||
| 129 | |||
| 130 | config USB_ISP1760_OF | ||
| 131 | bool "Support for the OF platform bus" | ||
| 132 | depends on USB_ISP1760_HCD && PPC_OF | ||
| 133 | ---help--- | ||
| 134 | Enables support for the device present on the PowerPC | ||
| 135 | OpenFirmware platform bus. | ||
| 136 | 125 | ||
| 137 | config USB_OHCI_HCD | 126 | config USB_OHCI_HCD |
| 138 | tristate "OHCI HCD support" | 127 | tristate "OHCI HCD support" |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 15a803b206b8..4725d15d096f 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
| @@ -643,7 +643,7 @@ static int ehci_run (struct usb_hcd *hcd) | |||
| 643 | static irqreturn_t ehci_irq (struct usb_hcd *hcd) | 643 | static irqreturn_t ehci_irq (struct usb_hcd *hcd) |
| 644 | { | 644 | { |
| 645 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 645 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
| 646 | u32 status, pcd_status = 0, cmd; | 646 | u32 status, masked_status, pcd_status = 0, cmd; |
| 647 | int bh; | 647 | int bh; |
| 648 | 648 | ||
| 649 | spin_lock (&ehci->lock); | 649 | spin_lock (&ehci->lock); |
| @@ -656,14 +656,14 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
| 656 | goto dead; | 656 | goto dead; |
| 657 | } | 657 | } |
| 658 | 658 | ||
| 659 | status &= INTR_MASK; | 659 | masked_status = status & INTR_MASK; |
| 660 | if (!status) { /* irq sharing? */ | 660 | if (!masked_status) { /* irq sharing? */ |
| 661 | spin_unlock(&ehci->lock); | 661 | spin_unlock(&ehci->lock); |
| 662 | return IRQ_NONE; | 662 | return IRQ_NONE; |
| 663 | } | 663 | } |
| 664 | 664 | ||
| 665 | /* clear (just) interrupts */ | 665 | /* clear (just) interrupts */ |
| 666 | ehci_writel(ehci, status, &ehci->regs->status); | 666 | ehci_writel(ehci, masked_status, &ehci->regs->status); |
| 667 | cmd = ehci_readl(ehci, &ehci->regs->command); | 667 | cmd = ehci_readl(ehci, &ehci->regs->command); |
| 668 | bh = 0; | 668 | bh = 0; |
| 669 | 669 | ||
| @@ -734,18 +734,17 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
| 734 | 734 | ||
| 735 | /* PCI errors [4.15.2.4] */ | 735 | /* PCI errors [4.15.2.4] */ |
| 736 | if (unlikely ((status & STS_FATAL) != 0)) { | 736 | if (unlikely ((status & STS_FATAL) != 0)) { |
| 737 | ehci_err(ehci, "fatal error\n"); | ||
| 737 | dbg_cmd(ehci, "fatal", cmd); | 738 | dbg_cmd(ehci, "fatal", cmd); |
| 738 | dbg_status(ehci, "fatal", status); | 739 | dbg_status(ehci, "fatal", status); |
| 739 | if (status & STS_HALT) { | 740 | ehci_halt(ehci); |
| 740 | ehci_err (ehci, "fatal error\n"); | ||
| 741 | dead: | 741 | dead: |
| 742 | ehci_reset (ehci); | 742 | ehci_reset(ehci); |
| 743 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); | 743 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
| 744 | /* generic layer kills/unlinks all urbs, then | 744 | /* generic layer kills/unlinks all urbs, then |
| 745 | * uses ehci_stop to clean up the rest | 745 | * uses ehci_stop to clean up the rest |
| 746 | */ | 746 | */ |
| 747 | bh = 1; | 747 | bh = 1; |
| 748 | } | ||
| 749 | } | 748 | } |
| 750 | 749 | ||
| 751 | if (bh) | 750 | if (bh) |
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 0eba894bcb01..9c9da35abc6c 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c | |||
| @@ -205,6 +205,7 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev) | |||
| 205 | 205 | ||
| 206 | tmp = hcd->irq; | 206 | tmp = hcd->irq; |
| 207 | 207 | ||
| 208 | ehci_shutdown(hcd); | ||
| 208 | usb_remove_hcd(hcd); | 209 | usb_remove_hcd(hcd); |
| 209 | 210 | ||
| 210 | ps3_system_bus_set_driver_data(dev, NULL); | 211 | ps3_system_bus_set_driver_data(dev, NULL); |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 4a0c5a78b2ed..a081ee65bde6 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
| @@ -918,7 +918,7 @@ iso_stream_init ( | |||
| 918 | */ | 918 | */ |
| 919 | stream->usecs = HS_USECS_ISO (maxp); | 919 | stream->usecs = HS_USECS_ISO (maxp); |
| 920 | bandwidth = stream->usecs * 8; | 920 | bandwidth = stream->usecs * 8; |
| 921 | bandwidth /= 1 << (interval - 1); | 921 | bandwidth /= interval; |
| 922 | 922 | ||
| 923 | } else { | 923 | } else { |
| 924 | u32 addr; | 924 | u32 addr; |
| @@ -951,7 +951,7 @@ iso_stream_init ( | |||
| 951 | } else | 951 | } else |
| 952 | stream->raw_mask = smask_out [hs_transfers - 1]; | 952 | stream->raw_mask = smask_out [hs_transfers - 1]; |
| 953 | bandwidth = stream->usecs + stream->c_usecs; | 953 | bandwidth = stream->usecs + stream->c_usecs; |
| 954 | bandwidth /= 1 << (interval + 2); | 954 | bandwidth /= interval << 3; |
| 955 | 955 | ||
| 956 | /* stream->splits gets created from raw_mask later */ | 956 | /* stream->splits gets created from raw_mask later */ |
| 957 | stream->address = cpu_to_hc32(ehci, addr); | 957 | stream->address = cpu_to_hc32(ehci, addr); |
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index af849f596135..b87ca7cf4b37 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
| @@ -14,16 +14,16 @@ | |||
| 14 | #include "../core/hcd.h" | 14 | #include "../core/hcd.h" |
| 15 | #include "isp1760-hcd.h" | 15 | #include "isp1760-hcd.h" |
| 16 | 16 | ||
| 17 | #ifdef CONFIG_USB_ISP1760_OF | 17 | #ifdef CONFIG_PPC_OF |
| 18 | #include <linux/of.h> | 18 | #include <linux/of.h> |
| 19 | #include <linux/of_platform.h> | 19 | #include <linux/of_platform.h> |
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | #ifdef CONFIG_USB_ISP1760_PCI | 22 | #ifdef CONFIG_PCI |
| 23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
| 24 | #endif | 24 | #endif |
| 25 | 25 | ||
| 26 | #ifdef CONFIG_USB_ISP1760_OF | 26 | #ifdef CONFIG_PPC_OF |
| 27 | static int of_isp1760_probe(struct of_device *dev, | 27 | static int of_isp1760_probe(struct of_device *dev, |
| 28 | const struct of_device_id *match) | 28 | const struct of_device_id *match) |
| 29 | { | 29 | { |
| @@ -128,7 +128,7 @@ static struct of_platform_driver isp1760_of_driver = { | |||
| 128 | }; | 128 | }; |
| 129 | #endif | 129 | #endif |
| 130 | 130 | ||
| 131 | #ifdef CONFIG_USB_ISP1760_PCI | 131 | #ifdef CONFIG_PCI |
| 132 | static u32 nxp_pci_io_base; | 132 | static u32 nxp_pci_io_base; |
| 133 | static u32 iolength; | 133 | static u32 iolength; |
| 134 | static u32 pci_mem_phy0; | 134 | static u32 pci_mem_phy0; |
| @@ -288,28 +288,28 @@ static struct pci_driver isp1761_pci_driver = { | |||
| 288 | 288 | ||
| 289 | static int __init isp1760_init(void) | 289 | static int __init isp1760_init(void) |
| 290 | { | 290 | { |
| 291 | int ret = -ENODEV; | 291 | int ret; |
| 292 | 292 | ||
| 293 | init_kmem_once(); | 293 | init_kmem_once(); |
| 294 | 294 | ||
| 295 | #ifdef CONFIG_USB_ISP1760_OF | 295 | #ifdef CONFIG_PPC_OF |
| 296 | ret = of_register_platform_driver(&isp1760_of_driver); | 296 | ret = of_register_platform_driver(&isp1760_of_driver); |
| 297 | if (ret) { | 297 | if (ret) { |
| 298 | deinit_kmem_cache(); | 298 | deinit_kmem_cache(); |
| 299 | return ret; | 299 | return ret; |
| 300 | } | 300 | } |
| 301 | #endif | 301 | #endif |
| 302 | #ifdef CONFIG_USB_ISP1760_PCI | 302 | #ifdef CONFIG_PCI |
| 303 | ret = pci_register_driver(&isp1761_pci_driver); | 303 | ret = pci_register_driver(&isp1761_pci_driver); |
| 304 | if (ret) | 304 | if (ret) |
| 305 | goto unreg_of; | 305 | goto unreg_of; |
| 306 | #endif | 306 | #endif |
| 307 | return ret; | 307 | return ret; |
| 308 | 308 | ||
| 309 | #ifdef CONFIG_USB_ISP1760_PCI | 309 | #ifdef CONFIG_PCI |
| 310 | unreg_of: | 310 | unreg_of: |
| 311 | #endif | 311 | #endif |
| 312 | #ifdef CONFIG_USB_ISP1760_OF | 312 | #ifdef CONFIG_PPC_OF |
| 313 | of_unregister_platform_driver(&isp1760_of_driver); | 313 | of_unregister_platform_driver(&isp1760_of_driver); |
| 314 | #endif | 314 | #endif |
| 315 | deinit_kmem_cache(); | 315 | deinit_kmem_cache(); |
| @@ -319,10 +319,10 @@ module_init(isp1760_init); | |||
| 319 | 319 | ||
| 320 | static void __exit isp1760_exit(void) | 320 | static void __exit isp1760_exit(void) |
| 321 | { | 321 | { |
| 322 | #ifdef CONFIG_USB_ISP1760_OF | 322 | #ifdef CONFIG_PPC_OF |
| 323 | of_unregister_platform_driver(&isp1760_of_driver); | 323 | of_unregister_platform_driver(&isp1760_of_driver); |
| 324 | #endif | 324 | #endif |
| 325 | #ifdef CONFIG_USB_ISP1760_PCI | 325 | #ifdef CONFIG_PCI |
| 326 | pci_unregister_driver(&isp1761_pci_driver); | 326 | pci_unregister_driver(&isp1761_pci_driver); |
| 327 | #endif | 327 | #endif |
| 328 | deinit_kmem_cache(); | 328 | deinit_kmem_cache(); |
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index 2089d8a46c4b..3c1a3b5f89f1 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c | |||
| @@ -192,7 +192,7 @@ fail_start: | |||
| 192 | return result; | 192 | return result; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | static int ps3_ohci_remove (struct ps3_system_bus_device *dev) | 195 | static int ps3_ohci_remove(struct ps3_system_bus_device *dev) |
| 196 | { | 196 | { |
| 197 | unsigned int tmp; | 197 | unsigned int tmp; |
| 198 | struct usb_hcd *hcd = | 198 | struct usb_hcd *hcd = |
| @@ -205,6 +205,7 @@ static int ps3_ohci_remove (struct ps3_system_bus_device *dev) | |||
| 205 | 205 | ||
| 206 | tmp = hcd->irq; | 206 | tmp = hcd->irq; |
| 207 | 207 | ||
| 208 | ohci_shutdown(hcd); | ||
| 208 | usb_remove_hcd(hcd); | 209 | usb_remove_hcd(hcd); |
| 209 | 210 | ||
| 210 | ps3_system_bus_set_driver_data(dev, NULL); | 211 | ps3_system_bus_set_driver_data(dev, NULL); |
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index c18d8790c410..2376f24f3c83 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
| @@ -1763,11 +1763,12 @@ static void r8a66597_timer(unsigned long _r8a66597) | |||
| 1763 | { | 1763 | { |
| 1764 | struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; | 1764 | struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; |
| 1765 | unsigned long flags; | 1765 | unsigned long flags; |
| 1766 | int port; | ||
| 1766 | 1767 | ||
| 1767 | spin_lock_irqsave(&r8a66597->lock, flags); | 1768 | spin_lock_irqsave(&r8a66597->lock, flags); |
| 1768 | 1769 | ||
| 1769 | r8a66597_root_hub_control(r8a66597, 0); | 1770 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) |
| 1770 | r8a66597_root_hub_control(r8a66597, 1); | 1771 | r8a66597_root_hub_control(r8a66597, port); |
| 1771 | 1772 | ||
| 1772 | spin_unlock_irqrestore(&r8a66597->lock, flags); | 1773 | spin_unlock_irqrestore(&r8a66597->lock, flags); |
| 1773 | } | 1774 | } |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 69c34a58e205..b4ec716de7da 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c | |||
| @@ -3270,6 +3270,7 @@ static struct usb_device_id sisusb_table [] = { | |||
| 3270 | { USB_DEVICE(0x0711, 0x0900) }, | 3270 | { USB_DEVICE(0x0711, 0x0900) }, |
| 3271 | { USB_DEVICE(0x0711, 0x0901) }, | 3271 | { USB_DEVICE(0x0711, 0x0901) }, |
| 3272 | { USB_DEVICE(0x0711, 0x0902) }, | 3272 | { USB_DEVICE(0x0711, 0x0902) }, |
| 3273 | { USB_DEVICE(0x0711, 0x0903) }, | ||
| 3273 | { USB_DEVICE(0x0711, 0x0918) }, | 3274 | { USB_DEVICE(0x0711, 0x0918) }, |
| 3274 | { USB_DEVICE(0x182d, 0x021c) }, | 3275 | { USB_DEVICE(0x182d, 0x021c) }, |
| 3275 | { USB_DEVICE(0x182d, 0x0269) }, | 3276 | { USB_DEVICE(0x182d, 0x0269) }, |
diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c index 8648470c81ca..63dff9ba73c5 100644 --- a/drivers/usb/misc/vstusb.c +++ b/drivers/usb/misc/vstusb.c | |||
| @@ -620,7 +620,7 @@ static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 620 | __func__); | 620 | __func__); |
| 621 | retval = -EFAULT; | 621 | retval = -EFAULT; |
| 622 | } else { | 622 | } else { |
| 623 | dev_dbg(&dev->dev, "%s: recv %d bytes from pipe %d\n", | 623 | dev_dbg(&dev->dev, "%s: recv %zd bytes from pipe %d\n", |
| 624 | __func__, usb_data.count, usb_data.pipe); | 624 | __func__, usb_data.count, usb_data.pipe); |
| 625 | } | 625 | } |
| 626 | 626 | ||
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 4a35745b30be..5280dba9b1fb 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
| @@ -114,8 +114,8 @@ | |||
| 114 | 114 | ||
| 115 | 115 | ||
| 116 | 116 | ||
| 117 | unsigned debug; | 117 | unsigned musb_debug; |
| 118 | module_param(debug, uint, S_IRUGO | S_IWUSR); | 118 | module_param(musb_debug, uint, S_IRUGO | S_IWUSR); |
| 119 | MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); | 119 | MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); |
| 120 | 120 | ||
| 121 | #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" | 121 | #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" |
| @@ -2248,7 +2248,7 @@ static int __init musb_init(void) | |||
| 2248 | "host" | 2248 | "host" |
| 2249 | #endif | 2249 | #endif |
| 2250 | ", debug=%d\n", | 2250 | ", debug=%d\n", |
| 2251 | musb_driver_name, debug); | 2251 | musb_driver_name, musb_debug); |
| 2252 | return platform_driver_probe(&musb_driver, musb_probe); | 2252 | return platform_driver_probe(&musb_driver, musb_probe); |
| 2253 | } | 2253 | } |
| 2254 | 2254 | ||
diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h index 4d2794441b15..9fc1db44c72c 100644 --- a/drivers/usb/musb/musb_debug.h +++ b/drivers/usb/musb/musb_debug.h | |||
| @@ -48,11 +48,11 @@ | |||
| 48 | __func__, __LINE__ , ## args); \ | 48 | __func__, __LINE__ , ## args); \ |
| 49 | } } while (0) | 49 | } } while (0) |
| 50 | 50 | ||
| 51 | extern unsigned debug; | 51 | extern unsigned musb_debug; |
| 52 | 52 | ||
| 53 | static inline int _dbg_level(unsigned l) | 53 | static inline int _dbg_level(unsigned l) |
| 54 | { | 54 | { |
| 55 | return debug >= l; | 55 | return musb_debug >= l; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | #define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args) | 58 | #define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args) |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 3133990f04ec..e45e70bcc5e2 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
| @@ -378,6 +378,19 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) | |||
| 378 | 378 | ||
| 379 | switch (qh->type) { | 379 | switch (qh->type) { |
| 380 | 380 | ||
| 381 | case USB_ENDPOINT_XFER_CONTROL: | ||
| 382 | case USB_ENDPOINT_XFER_BULK: | ||
| 383 | /* fifo policy for these lists, except that NAKing | ||
| 384 | * should rotate a qh to the end (for fairness). | ||
| 385 | */ | ||
| 386 | if (qh->mux == 1) { | ||
| 387 | head = qh->ring.prev; | ||
| 388 | list_del(&qh->ring); | ||
| 389 | kfree(qh); | ||
| 390 | qh = first_qh(head); | ||
| 391 | break; | ||
| 392 | } | ||
| 393 | |||
| 381 | case USB_ENDPOINT_XFER_ISOC: | 394 | case USB_ENDPOINT_XFER_ISOC: |
| 382 | case USB_ENDPOINT_XFER_INT: | 395 | case USB_ENDPOINT_XFER_INT: |
| 383 | /* this is where periodic bandwidth should be | 396 | /* this is where periodic bandwidth should be |
| @@ -388,17 +401,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) | |||
| 388 | kfree(qh); | 401 | kfree(qh); |
| 389 | qh = NULL; | 402 | qh = NULL; |
| 390 | break; | 403 | break; |
| 391 | |||
| 392 | case USB_ENDPOINT_XFER_CONTROL: | ||
| 393 | case USB_ENDPOINT_XFER_BULK: | ||
| 394 | /* fifo policy for these lists, except that NAKing | ||
| 395 | * should rotate a qh to the end (for fairness). | ||
| 396 | */ | ||
| 397 | head = qh->ring.prev; | ||
| 398 | list_del(&qh->ring); | ||
| 399 | kfree(qh); | ||
| 400 | qh = first_qh(head); | ||
| 401 | break; | ||
| 402 | } | 404 | } |
| 403 | } | 405 | } |
| 404 | return qh; | 406 | return qh; |
| @@ -1507,10 +1509,29 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
| 1507 | musb_writew(hw_ep->regs, MUSB_RXCSR, val); | 1509 | musb_writew(hw_ep->regs, MUSB_RXCSR, val); |
| 1508 | 1510 | ||
| 1509 | #ifdef CONFIG_USB_INVENTRA_DMA | 1511 | #ifdef CONFIG_USB_INVENTRA_DMA |
| 1512 | if (usb_pipeisoc(pipe)) { | ||
| 1513 | struct usb_iso_packet_descriptor *d; | ||
| 1514 | |||
| 1515 | d = urb->iso_frame_desc + qh->iso_idx; | ||
| 1516 | d->actual_length = xfer_len; | ||
| 1517 | |||
| 1518 | /* even if there was an error, we did the dma | ||
| 1519 | * for iso_frame_desc->length | ||
| 1520 | */ | ||
| 1521 | if (d->status != EILSEQ && d->status != -EOVERFLOW) | ||
| 1522 | d->status = 0; | ||
| 1523 | |||
| 1524 | if (++qh->iso_idx >= urb->number_of_packets) | ||
| 1525 | done = true; | ||
| 1526 | else | ||
| 1527 | done = false; | ||
| 1528 | |||
| 1529 | } else { | ||
| 1510 | /* done if urb buffer is full or short packet is recd */ | 1530 | /* done if urb buffer is full or short packet is recd */ |
| 1511 | done = (urb->actual_length + xfer_len >= | 1531 | done = (urb->actual_length + xfer_len >= |
| 1512 | urb->transfer_buffer_length | 1532 | urb->transfer_buffer_length |
| 1513 | || dma->actual_len < qh->maxpacket); | 1533 | || dma->actual_len < qh->maxpacket); |
| 1534 | } | ||
| 1514 | 1535 | ||
| 1515 | /* send IN token for next packet, without AUTOREQ */ | 1536 | /* send IN token for next packet, without AUTOREQ */ |
| 1516 | if (!done) { | 1537 | if (!done) { |
| @@ -1547,7 +1568,8 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
| 1547 | if (dma) { | 1568 | if (dma) { |
| 1548 | struct dma_controller *c; | 1569 | struct dma_controller *c; |
| 1549 | u16 rx_count; | 1570 | u16 rx_count; |
| 1550 | int ret; | 1571 | int ret, length; |
| 1572 | dma_addr_t buf; | ||
| 1551 | 1573 | ||
| 1552 | rx_count = musb_readw(epio, MUSB_RXCOUNT); | 1574 | rx_count = musb_readw(epio, MUSB_RXCOUNT); |
| 1553 | 1575 | ||
| @@ -1560,6 +1582,35 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
| 1560 | 1582 | ||
| 1561 | c = musb->dma_controller; | 1583 | c = musb->dma_controller; |
| 1562 | 1584 | ||
| 1585 | if (usb_pipeisoc(pipe)) { | ||
| 1586 | int status = 0; | ||
| 1587 | struct usb_iso_packet_descriptor *d; | ||
| 1588 | |||
| 1589 | d = urb->iso_frame_desc + qh->iso_idx; | ||
| 1590 | |||
| 1591 | if (iso_err) { | ||
| 1592 | status = -EILSEQ; | ||
| 1593 | urb->error_count++; | ||
| 1594 | } | ||
| 1595 | if (rx_count > d->length) { | ||
| 1596 | if (status == 0) { | ||
| 1597 | status = -EOVERFLOW; | ||
| 1598 | urb->error_count++; | ||
| 1599 | } | ||
| 1600 | DBG(2, "** OVERFLOW %d into %d\n",\ | ||
| 1601 | rx_count, d->length); | ||
| 1602 | |||
| 1603 | length = d->length; | ||
| 1604 | } else | ||
| 1605 | length = rx_count; | ||
| 1606 | d->status = status; | ||
| 1607 | buf = urb->transfer_dma + d->offset; | ||
| 1608 | } else { | ||
| 1609 | length = rx_count; | ||
| 1610 | buf = urb->transfer_dma + | ||
| 1611 | urb->actual_length; | ||
| 1612 | } | ||
| 1613 | |||
| 1563 | dma->desired_mode = 0; | 1614 | dma->desired_mode = 0; |
| 1564 | #ifdef USE_MODE1 | 1615 | #ifdef USE_MODE1 |
| 1565 | /* because of the issue below, mode 1 will | 1616 | /* because of the issue below, mode 1 will |
| @@ -1571,6 +1622,12 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
| 1571 | urb->actual_length) | 1622 | urb->actual_length) |
| 1572 | > qh->maxpacket) | 1623 | > qh->maxpacket) |
| 1573 | dma->desired_mode = 1; | 1624 | dma->desired_mode = 1; |
| 1625 | if (rx_count < hw_ep->max_packet_sz_rx) { | ||
| 1626 | length = rx_count; | ||
| 1627 | dma->bDesiredMode = 0; | ||
| 1628 | } else { | ||
| 1629 | length = urb->transfer_buffer_length; | ||
| 1630 | } | ||
| 1574 | #endif | 1631 | #endif |
| 1575 | 1632 | ||
| 1576 | /* Disadvantage of using mode 1: | 1633 | /* Disadvantage of using mode 1: |
| @@ -1608,12 +1665,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
| 1608 | */ | 1665 | */ |
| 1609 | ret = c->channel_program( | 1666 | ret = c->channel_program( |
| 1610 | dma, qh->maxpacket, | 1667 | dma, qh->maxpacket, |
| 1611 | dma->desired_mode, | 1668 | dma->desired_mode, buf, length); |
| 1612 | urb->transfer_dma | ||
| 1613 | + urb->actual_length, | ||
| 1614 | (dma->desired_mode == 0) | ||
| 1615 | ? rx_count | ||
| 1616 | : urb->transfer_buffer_length); | ||
| 1617 | 1669 | ||
| 1618 | if (!ret) { | 1670 | if (!ret) { |
| 1619 | c->channel_release(dma); | 1671 | c->channel_release(dma); |
| @@ -1631,19 +1683,6 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
| 1631 | } | 1683 | } |
| 1632 | } | 1684 | } |
| 1633 | 1685 | ||
| 1634 | if (dma && usb_pipeisoc(pipe)) { | ||
| 1635 | struct usb_iso_packet_descriptor *d; | ||
| 1636 | int iso_stat = status; | ||
| 1637 | |||
| 1638 | d = urb->iso_frame_desc + qh->iso_idx; | ||
| 1639 | d->actual_length += xfer_len; | ||
| 1640 | if (iso_err) { | ||
| 1641 | iso_stat = -EILSEQ; | ||
| 1642 | urb->error_count++; | ||
| 1643 | } | ||
| 1644 | d->status = iso_stat; | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | finish: | 1686 | finish: |
| 1648 | urb->actual_length += xfer_len; | 1687 | urb->actual_length += xfer_len; |
| 1649 | qh->offset += xfer_len; | 1688 | qh->offset += xfer_len; |
| @@ -1671,22 +1710,9 @@ static int musb_schedule( | |||
| 1671 | struct list_head *head = NULL; | 1710 | struct list_head *head = NULL; |
| 1672 | 1711 | ||
| 1673 | /* use fixed hardware for control and bulk */ | 1712 | /* use fixed hardware for control and bulk */ |
| 1674 | switch (qh->type) { | 1713 | if (qh->type == USB_ENDPOINT_XFER_CONTROL) { |
| 1675 | case USB_ENDPOINT_XFER_CONTROL: | ||
| 1676 | head = &musb->control; | 1714 | head = &musb->control; |
| 1677 | hw_ep = musb->control_ep; | 1715 | hw_ep = musb->control_ep; |
| 1678 | break; | ||
| 1679 | case USB_ENDPOINT_XFER_BULK: | ||
| 1680 | hw_ep = musb->bulk_ep; | ||
| 1681 | if (is_in) | ||
| 1682 | head = &musb->in_bulk; | ||
| 1683 | else | ||
| 1684 | head = &musb->out_bulk; | ||
| 1685 | break; | ||
| 1686 | } | ||
| 1687 | if (head) { | ||
| 1688 | idle = list_empty(head); | ||
| 1689 | list_add_tail(&qh->ring, head); | ||
| 1690 | goto success; | 1716 | goto success; |
| 1691 | } | 1717 | } |
| 1692 | 1718 | ||
| @@ -1725,19 +1751,34 @@ static int musb_schedule( | |||
| 1725 | else | 1751 | else |
| 1726 | diff = hw_ep->max_packet_sz_tx - qh->maxpacket; | 1752 | diff = hw_ep->max_packet_sz_tx - qh->maxpacket; |
| 1727 | 1753 | ||
| 1728 | if (diff > 0 && best_diff > diff) { | 1754 | if (diff >= 0 && best_diff > diff) { |
| 1729 | best_diff = diff; | 1755 | best_diff = diff; |
| 1730 | best_end = epnum; | 1756 | best_end = epnum; |
| 1731 | } | 1757 | } |
| 1732 | } | 1758 | } |
| 1733 | if (best_end < 0) | 1759 | /* use bulk reserved ep1 if no other ep is free */ |
| 1760 | if (best_end > 0 && qh->type == USB_ENDPOINT_XFER_BULK) { | ||
| 1761 | hw_ep = musb->bulk_ep; | ||
| 1762 | if (is_in) | ||
| 1763 | head = &musb->in_bulk; | ||
| 1764 | else | ||
| 1765 | head = &musb->out_bulk; | ||
| 1766 | goto success; | ||
| 1767 | } else if (best_end < 0) { | ||
| 1734 | return -ENOSPC; | 1768 | return -ENOSPC; |
| 1769 | } | ||
| 1735 | 1770 | ||
| 1736 | idle = 1; | 1771 | idle = 1; |
| 1772 | qh->mux = 0; | ||
| 1737 | hw_ep = musb->endpoints + best_end; | 1773 | hw_ep = musb->endpoints + best_end; |
| 1738 | musb->periodic[best_end] = qh; | 1774 | musb->periodic[best_end] = qh; |
| 1739 | DBG(4, "qh %p periodic slot %d\n", qh, best_end); | 1775 | DBG(4, "qh %p periodic slot %d\n", qh, best_end); |
| 1740 | success: | 1776 | success: |
| 1777 | if (head) { | ||
| 1778 | idle = list_empty(head); | ||
| 1779 | list_add_tail(&qh->ring, head); | ||
| 1780 | qh->mux = 1; | ||
| 1781 | } | ||
| 1741 | qh->hw_ep = hw_ep; | 1782 | qh->hw_ep = hw_ep; |
| 1742 | qh->hep->hcpriv = qh; | 1783 | qh->hep->hcpriv = qh; |
| 1743 | if (idle) | 1784 | if (idle) |
| @@ -2015,11 +2056,13 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
| 2015 | sched = &musb->control; | 2056 | sched = &musb->control; |
| 2016 | break; | 2057 | break; |
| 2017 | case USB_ENDPOINT_XFER_BULK: | 2058 | case USB_ENDPOINT_XFER_BULK: |
| 2018 | if (usb_pipein(urb->pipe)) | 2059 | if (qh->mux == 1) { |
| 2019 | sched = &musb->in_bulk; | 2060 | if (usb_pipein(urb->pipe)) |
| 2020 | else | 2061 | sched = &musb->in_bulk; |
| 2021 | sched = &musb->out_bulk; | 2062 | else |
| 2022 | break; | 2063 | sched = &musb->out_bulk; |
| 2064 | break; | ||
| 2065 | } | ||
| 2023 | default: | 2066 | default: |
| 2024 | /* REVISIT when we get a schedule tree, periodic | 2067 | /* REVISIT when we get a schedule tree, periodic |
| 2025 | * transfers won't always be at the head of a | 2068 | * transfers won't always be at the head of a |
| @@ -2067,11 +2110,13 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) | |||
| 2067 | sched = &musb->control; | 2110 | sched = &musb->control; |
| 2068 | break; | 2111 | break; |
| 2069 | case USB_ENDPOINT_XFER_BULK: | 2112 | case USB_ENDPOINT_XFER_BULK: |
| 2070 | if (is_in) | 2113 | if (qh->mux == 1) { |
| 2071 | sched = &musb->in_bulk; | 2114 | if (is_in) |
| 2072 | else | 2115 | sched = &musb->in_bulk; |
| 2073 | sched = &musb->out_bulk; | 2116 | else |
| 2074 | break; | 2117 | sched = &musb->out_bulk; |
| 2118 | break; | ||
| 2119 | } | ||
| 2075 | default: | 2120 | default: |
| 2076 | /* REVISIT when we get a schedule tree, periodic transfers | 2121 | /* REVISIT when we get a schedule tree, periodic transfers |
| 2077 | * won't always be at the head of a singleton queue... | 2122 | * won't always be at the head of a singleton queue... |
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index 77bcdb9d5b32..0b7fbcd21963 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h | |||
| @@ -53,6 +53,7 @@ struct musb_qh { | |||
| 53 | 53 | ||
| 54 | struct list_head ring; /* of musb_qh */ | 54 | struct list_head ring; /* of musb_qh */ |
| 55 | /* struct musb_qh *next; */ /* for periodic tree */ | 55 | /* struct musb_qh *next; */ /* for periodic tree */ |
| 56 | u8 mux; /* qh multiplexed to hw_ep */ | ||
| 56 | 57 | ||
| 57 | unsigned offset; /* in urb->transfer_buffer */ | 58 | unsigned offset; /* in urb->transfer_buffer */ |
| 58 | unsigned segsize; /* current xfer fragment */ | 59 | unsigned segsize; /* current xfer fragment */ |
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 9d2dcb121c5e..ce6c162920f7 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
| @@ -53,7 +53,9 @@ static void musb_do_idle(unsigned long _musb) | |||
| 53 | { | 53 | { |
| 54 | struct musb *musb = (void *)_musb; | 54 | struct musb *musb = (void *)_musb; |
| 55 | unsigned long flags; | 55 | unsigned long flags; |
| 56 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
| 56 | u8 power; | 57 | u8 power; |
| 58 | #endif | ||
| 57 | u8 devctl; | 59 | u8 devctl; |
| 58 | 60 | ||
| 59 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | 61 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); |
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index b73b036f3d77..ee8fca92a4ac 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c | |||
| @@ -605,7 +605,7 @@ void musb_platform_set_mode(struct musb *musb, u8 musb_mode) | |||
| 605 | 605 | ||
| 606 | if (musb->board_mode != MUSB_OTG) { | 606 | if (musb->board_mode != MUSB_OTG) { |
| 607 | ERR("Changing mode currently only supported in OTG mode\n"); | 607 | ERR("Changing mode currently only supported in OTG mode\n"); |
| 608 | return; | 608 | return -EINVAL; |
| 609 | } | 609 | } |
| 610 | 610 | ||
| 611 | otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); | 611 | otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); |
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 8008d0bc80ad..9035d7256b03 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c | |||
| @@ -67,6 +67,7 @@ static struct usb_device_id id_table [] = { | |||
| 67 | { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ | 67 | { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ |
| 68 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ | 68 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ |
| 69 | { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ | 69 | { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ |
| 70 | { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */ | ||
| 70 | { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ | 71 | { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ |
| 71 | { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ | 72 | { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ |
| 72 | { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ | 73 | { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ |
| @@ -85,6 +86,7 @@ static struct usb_device_id id_table [] = { | |||
| 85 | { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ | 86 | { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ |
| 86 | { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ | 87 | { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ |
| 87 | { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ | 88 | { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ |
| 89 | { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ | ||
| 88 | { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ | 90 | { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ |
| 89 | { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ | 91 | { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ |
| 90 | { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ | 92 | { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index b679a556b98d..4e2cda93da59 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | * Introduced common header to be used also in USB Gadget Framework. | 26 | * Introduced common header to be used also in USB Gadget Framework. |
| 27 | * Still needs some other style fixes. | 27 | * Still needs some other style fixes. |
| 28 | * | 28 | * |
| 29 | * 2007_Jun_21 Alan Cox <alan@redhat.com> | 29 | * 2007_Jun_21 Alan Cox <alan@lxorguk.ukuu.org.uk> |
| 30 | * Minimal cleanups for some of the driver problens and tty layer abuse. | 30 | * Minimal cleanups for some of the driver problens and tty layer abuse. |
| 31 | * Still needs fixing to allow multiple dongles. | 31 | * Still needs fixing to allow multiple dongles. |
| 32 | * | 32 | * |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index bd07eaa300b9..6fa1ec441b61 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
| @@ -160,6 +160,11 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po | |||
| 160 | 160 | ||
| 161 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 | 161 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 |
| 162 | 162 | ||
| 163 | /* YISO PRODUCTS */ | ||
| 164 | |||
| 165 | #define YISO_VENDOR_ID 0x0EAB | ||
| 166 | #define YISO_PRODUCT_U893 0xC893 | ||
| 167 | |||
| 163 | /* MERLIN EVDO PRODUCTS */ | 168 | /* MERLIN EVDO PRODUCTS */ |
| 164 | #define NOVATELWIRELESS_PRODUCT_V640 0x1100 | 169 | #define NOVATELWIRELESS_PRODUCT_V640 0x1100 |
| 165 | #define NOVATELWIRELESS_PRODUCT_V620 0x1110 | 170 | #define NOVATELWIRELESS_PRODUCT_V620 0x1110 |
| @@ -408,6 +413,7 @@ static struct usb_device_id option_ids[] = { | |||
| 408 | { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, | 413 | { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, |
| 409 | { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) }, | 414 | { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) }, |
| 410 | { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, | 415 | { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, |
| 416 | { USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) }, | ||
| 411 | { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, | 417 | { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, |
| 412 | { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, | 418 | { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, |
| 413 | { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) }, | 419 | { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) }, |
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 3d9249632ae1..c68b738900bd 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | # USB Storage driver configuration | 2 | # USB Storage driver configuration |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'" | 5 | comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;" |
| 6 | comment "may also be needed; see USB_STORAGE Help for more information" | 6 | comment "see USB_STORAGE Help for more information" |
| 7 | depends on USB | 7 | depends on USB |
| 8 | 8 | ||
| 9 | config USB_STORAGE | 9 | config USB_STORAGE |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index fb9e20e624c1..d4e5fc86e43c 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
| @@ -253,6 +253,14 @@ UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591, | |||
| 253 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 253 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 254 | US_FL_FIX_CAPACITY ), | 254 | US_FL_FIX_CAPACITY ), |
| 255 | 255 | ||
| 256 | /* Submitted by Ricky Wong Yung Fei <evilbladewarrior@gmail.com> */ | ||
| 257 | /* Nokia 7610 Supernova - Too many sectors reported in usb storage mode */ | ||
| 258 | UNUSUAL_DEV( 0x0421, 0x00f5, 0x0000, 0x0470, | ||
| 259 | "Nokia", | ||
| 260 | "7610 Supernova", | ||
| 261 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 262 | US_FL_FIX_CAPACITY ), | ||
| 263 | |||
| 256 | /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */ | 264 | /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */ |
| 257 | UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, | 265 | UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, |
| 258 | "SMSC", | 266 | "SMSC", |
| @@ -418,6 +426,13 @@ UNUSUAL_DEV( 0x04b0, 0x0417, 0x0100, 0x0100, | |||
| 418 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 426 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 419 | US_FL_FIX_CAPACITY), | 427 | US_FL_FIX_CAPACITY), |
| 420 | 428 | ||
| 429 | /* Reported by paul ready <lxtwin@homecall.co.uk> */ | ||
| 430 | UNUSUAL_DEV( 0x04b0, 0x0419, 0x0100, 0x0200, | ||
| 431 | "NIKON", | ||
| 432 | "NIKON DSC D300", | ||
| 433 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 434 | US_FL_FIX_CAPACITY), | ||
| 435 | |||
| 421 | /* Reported by Doug Maxey (dwm@austin.ibm.com) */ | 436 | /* Reported by Doug Maxey (dwm@austin.ibm.com) */ |
| 422 | UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, | 437 | UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, |
| 423 | "IBM", | 438 | "IBM", |
| @@ -1258,6 +1273,13 @@ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, | |||
| 1258 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1273 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 1259 | US_FL_FIX_INQUIRY), | 1274 | US_FL_FIX_INQUIRY), |
| 1260 | 1275 | ||
| 1276 | /* Reported by Luciano Rocha <luciano@eurotux.com> */ | ||
| 1277 | UNUSUAL_DEV( 0x0840, 0x0082, 0x0001, 0x0001, | ||
| 1278 | "Argosy", | ||
| 1279 | "Storage", | ||
| 1280 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 1281 | US_FL_FIX_CAPACITY), | ||
| 1282 | |||
| 1261 | /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>. | 1283 | /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>. |
| 1262 | * Flag will support Bulk devices which use a standards-violating 32-byte | 1284 | * Flag will support Bulk devices which use a standards-violating 32-byte |
| 1263 | * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with | 1285 | * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with |
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index c4493091c655..a14d5b6e4c7c 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig | |||
| @@ -52,5 +52,12 @@ config W1_MASTER_GPIO | |||
| 52 | This support is also available as a module. If so, the module | 52 | This support is also available as a module. If so, the module |
| 53 | will be called w1-gpio.ko. | 53 | will be called w1-gpio.ko. |
| 54 | 54 | ||
| 55 | config HDQ_MASTER_OMAP | ||
| 56 | tristate "OMAP HDQ driver" | ||
| 57 | depends on ARCH_OMAP2430 || ARCH_OMAP34XX | ||
| 58 | help | ||
| 59 | Say Y here if you want support for the 1-wire or HDQ Interface | ||
| 60 | on an OMAP processor. | ||
| 61 | |||
| 55 | endmenu | 62 | endmenu |
| 56 | 63 | ||
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 1420b5bbdda8..bc4714a75f3a 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile | |||
| @@ -7,3 +7,4 @@ obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o | |||
| 7 | obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o | 7 | obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o |
| 8 | obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o | 8 | obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o |
| 9 | obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o | 9 | obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o |
| 10 | obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o | ||
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c new file mode 100644 index 000000000000..1295625c4825 --- /dev/null +++ b/drivers/w1/masters/omap_hdq.c | |||
| @@ -0,0 +1,725 @@ | |||
| 1 | /* | ||
| 2 | * drivers/w1/masters/omap_hdq.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Texas Instruments, Inc. | ||
| 5 | * | ||
| 6 | * This file is licensed under the terms of the GNU General Public License | ||
| 7 | * version 2. This program is licensed "as is" without any warranty of any | ||
| 8 | * kind, whether express or implied. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/clk.h> | ||
| 17 | #include <linux/io.h> | ||
| 18 | |||
| 19 | #include <asm/irq.h> | ||
| 20 | #include <mach/hardware.h> | ||
| 21 | |||
| 22 | #include "../w1.h" | ||
| 23 | #include "../w1_int.h" | ||
| 24 | |||
| 25 | #define MOD_NAME "OMAP_HDQ:" | ||
| 26 | |||
| 27 | #define OMAP_HDQ_REVISION 0x00 | ||
| 28 | #define OMAP_HDQ_TX_DATA 0x04 | ||
| 29 | #define OMAP_HDQ_RX_DATA 0x08 | ||
| 30 | #define OMAP_HDQ_CTRL_STATUS 0x0c | ||
| 31 | #define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK (1<<6) | ||
| 32 | #define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE (1<<5) | ||
| 33 | #define OMAP_HDQ_CTRL_STATUS_GO (1<<4) | ||
| 34 | #define OMAP_HDQ_CTRL_STATUS_INITIALIZATION (1<<2) | ||
| 35 | #define OMAP_HDQ_CTRL_STATUS_DIR (1<<1) | ||
| 36 | #define OMAP_HDQ_CTRL_STATUS_MODE (1<<0) | ||
| 37 | #define OMAP_HDQ_INT_STATUS 0x10 | ||
| 38 | #define OMAP_HDQ_INT_STATUS_TXCOMPLETE (1<<2) | ||
| 39 | #define OMAP_HDQ_INT_STATUS_RXCOMPLETE (1<<1) | ||
| 40 | #define OMAP_HDQ_INT_STATUS_TIMEOUT (1<<0) | ||
| 41 | #define OMAP_HDQ_SYSCONFIG 0x14 | ||
| 42 | #define OMAP_HDQ_SYSCONFIG_SOFTRESET (1<<1) | ||
| 43 | #define OMAP_HDQ_SYSCONFIG_AUTOIDLE (1<<0) | ||
| 44 | #define OMAP_HDQ_SYSSTATUS 0x18 | ||
| 45 | #define OMAP_HDQ_SYSSTATUS_RESETDONE (1<<0) | ||
| 46 | |||
| 47 | #define OMAP_HDQ_FLAG_CLEAR 0 | ||
| 48 | #define OMAP_HDQ_FLAG_SET 1 | ||
| 49 | #define OMAP_HDQ_TIMEOUT (HZ/5) | ||
| 50 | |||
| 51 | #define OMAP_HDQ_MAX_USER 4 | ||
| 52 | |||
| 53 | static DECLARE_WAIT_QUEUE_HEAD(hdq_wait_queue); | ||
| 54 | static int w1_id; | ||
| 55 | |||
| 56 | struct hdq_data { | ||
| 57 | struct device *dev; | ||
| 58 | void __iomem *hdq_base; | ||
| 59 | /* lock status update */ | ||
| 60 | struct mutex hdq_mutex; | ||
| 61 | int hdq_usecount; | ||
| 62 | struct clk *hdq_ick; | ||
| 63 | struct clk *hdq_fck; | ||
| 64 | u8 hdq_irqstatus; | ||
| 65 | /* device lock */ | ||
| 66 | spinlock_t hdq_spinlock; | ||
| 67 | /* | ||
| 68 | * Used to control the call to omap_hdq_get and omap_hdq_put. | ||
| 69 | * HDQ Protocol: Write the CMD|REG_address first, followed by | ||
| 70 | * the data wrire or read. | ||
| 71 | */ | ||
| 72 | int init_trans; | ||
| 73 | }; | ||
| 74 | |||
| 75 | static int __init omap_hdq_probe(struct platform_device *pdev); | ||
| 76 | static int omap_hdq_remove(struct platform_device *pdev); | ||
| 77 | |||
| 78 | static struct platform_driver omap_hdq_driver = { | ||
| 79 | .probe = omap_hdq_probe, | ||
| 80 | .remove = omap_hdq_remove, | ||
| 81 | .driver = { | ||
| 82 | .name = "omap_hdq", | ||
| 83 | }, | ||
| 84 | }; | ||
| 85 | |||
| 86 | static u8 omap_w1_read_byte(void *_hdq); | ||
| 87 | static void omap_w1_write_byte(void *_hdq, u8 byte); | ||
| 88 | static u8 omap_w1_reset_bus(void *_hdq); | ||
| 89 | static void omap_w1_search_bus(void *_hdq, u8 search_type, | ||
| 90 | w1_slave_found_callback slave_found); | ||
| 91 | |||
| 92 | |||
| 93 | static struct w1_bus_master omap_w1_master = { | ||
| 94 | .read_byte = omap_w1_read_byte, | ||
| 95 | .write_byte = omap_w1_write_byte, | ||
| 96 | .reset_bus = omap_w1_reset_bus, | ||
| 97 | .search = omap_w1_search_bus, | ||
| 98 | }; | ||
| 99 | |||
| 100 | /* HDQ register I/O routines */ | ||
| 101 | static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset) | ||
| 102 | { | ||
| 103 | return __raw_readb(hdq_data->hdq_base + offset); | ||
| 104 | } | ||
| 105 | |||
| 106 | static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val) | ||
| 107 | { | ||
| 108 | __raw_writeb(val, hdq_data->hdq_base + offset); | ||
| 109 | } | ||
| 110 | |||
| 111 | static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset, | ||
| 112 | u8 val, u8 mask) | ||
| 113 | { | ||
| 114 | u8 new_val = (__raw_readb(hdq_data->hdq_base + offset) & ~mask) | ||
| 115 | | (val & mask); | ||
| 116 | __raw_writeb(new_val, hdq_data->hdq_base + offset); | ||
| 117 | |||
| 118 | return new_val; | ||
| 119 | } | ||
| 120 | |||
| 121 | /* | ||
| 122 | * Wait for one or more bits in flag change. | ||
| 123 | * HDQ_FLAG_SET: wait until any bit in the flag is set. | ||
| 124 | * HDQ_FLAG_CLEAR: wait until all bits in the flag are cleared. | ||
| 125 | * return 0 on success and -ETIMEDOUT in the case of timeout. | ||
| 126 | */ | ||
| 127 | static int hdq_wait_for_flag(struct hdq_data *hdq_data, u32 offset, | ||
| 128 | u8 flag, u8 flag_set, u8 *status) | ||
| 129 | { | ||
| 130 | int ret = 0; | ||
| 131 | unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT; | ||
| 132 | |||
| 133 | if (flag_set == OMAP_HDQ_FLAG_CLEAR) { | ||
| 134 | /* wait for the flag clear */ | ||
| 135 | while (((*status = hdq_reg_in(hdq_data, offset)) & flag) | ||
| 136 | && time_before(jiffies, timeout)) { | ||
| 137 | schedule_timeout_uninterruptible(1); | ||
| 138 | } | ||
| 139 | if (*status & flag) | ||
| 140 | ret = -ETIMEDOUT; | ||
| 141 | } else if (flag_set == OMAP_HDQ_FLAG_SET) { | ||
| 142 | /* wait for the flag set */ | ||
| 143 | while (!((*status = hdq_reg_in(hdq_data, offset)) & flag) | ||
| 144 | && time_before(jiffies, timeout)) { | ||
| 145 | schedule_timeout_uninterruptible(1); | ||
| 146 | } | ||
| 147 | if (!(*status & flag)) | ||
| 148 | ret = -ETIMEDOUT; | ||
| 149 | } else | ||
| 150 | return -EINVAL; | ||
| 151 | |||
| 152 | return ret; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* write out a byte and fill *status with HDQ_INT_STATUS */ | ||
| 156 | static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status) | ||
| 157 | { | ||
| 158 | int ret; | ||
| 159 | u8 tmp_status; | ||
| 160 | unsigned long irqflags; | ||
| 161 | |||
| 162 | *status = 0; | ||
| 163 | |||
| 164 | spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags); | ||
| 165 | /* clear interrupt flags via a dummy read */ | ||
| 166 | hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); | ||
| 167 | /* ISR loads it with new INT_STATUS */ | ||
| 168 | hdq_data->hdq_irqstatus = 0; | ||
| 169 | spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags); | ||
| 170 | |||
| 171 | hdq_reg_out(hdq_data, OMAP_HDQ_TX_DATA, val); | ||
| 172 | |||
| 173 | /* set the GO bit */ | ||
| 174 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, OMAP_HDQ_CTRL_STATUS_GO, | ||
| 175 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO); | ||
| 176 | /* wait for the TXCOMPLETE bit */ | ||
| 177 | ret = wait_event_timeout(hdq_wait_queue, | ||
| 178 | hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT); | ||
| 179 | if (ret == 0) { | ||
| 180 | dev_dbg(hdq_data->dev, "TX wait elapsed\n"); | ||
| 181 | goto out; | ||
| 182 | } | ||
| 183 | |||
| 184 | *status = hdq_data->hdq_irqstatus; | ||
| 185 | /* check irqstatus */ | ||
| 186 | if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) { | ||
| 187 | dev_dbg(hdq_data->dev, "timeout waiting for" | ||
| 188 | "TXCOMPLETE/RXCOMPLETE, %x", *status); | ||
| 189 | ret = -ETIMEDOUT; | ||
| 190 | goto out; | ||
| 191 | } | ||
| 192 | |||
| 193 | /* wait for the GO bit return to zero */ | ||
| 194 | ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
| 195 | OMAP_HDQ_CTRL_STATUS_GO, | ||
| 196 | OMAP_HDQ_FLAG_CLEAR, &tmp_status); | ||
| 197 | if (ret) { | ||
| 198 | dev_dbg(hdq_data->dev, "timeout waiting GO bit" | ||
| 199 | "return to zero, %x", tmp_status); | ||
| 200 | } | ||
| 201 | |||
| 202 | out: | ||
| 203 | return ret; | ||
| 204 | } | ||
| 205 | |||
| 206 | /* HDQ Interrupt service routine */ | ||
| 207 | static irqreturn_t hdq_isr(int irq, void *_hdq) | ||
| 208 | { | ||
| 209 | struct hdq_data *hdq_data = _hdq; | ||
| 210 | unsigned long irqflags; | ||
| 211 | |||
| 212 | spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags); | ||
| 213 | hdq_data->hdq_irqstatus = hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); | ||
| 214 | spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags); | ||
| 215 | dev_dbg(hdq_data->dev, "hdq_isr: %x", hdq_data->hdq_irqstatus); | ||
| 216 | |||
| 217 | if (hdq_data->hdq_irqstatus & | ||
| 218 | (OMAP_HDQ_INT_STATUS_TXCOMPLETE | OMAP_HDQ_INT_STATUS_RXCOMPLETE | ||
| 219 | | OMAP_HDQ_INT_STATUS_TIMEOUT)) { | ||
| 220 | /* wake up sleeping process */ | ||
| 221 | wake_up(&hdq_wait_queue); | ||
| 222 | } | ||
| 223 | |||
| 224 | return IRQ_HANDLED; | ||
| 225 | } | ||
| 226 | |||
| 227 | /* HDQ Mode: always return success */ | ||
| 228 | static u8 omap_w1_reset_bus(void *_hdq) | ||
| 229 | { | ||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | /* W1 search callback function */ | ||
| 234 | static void omap_w1_search_bus(void *_hdq, u8 search_type, | ||
| 235 | w1_slave_found_callback slave_found) | ||
| 236 | { | ||
| 237 | u64 module_id, rn_le, cs, id; | ||
| 238 | |||
| 239 | if (w1_id) | ||
| 240 | module_id = w1_id; | ||
| 241 | else | ||
| 242 | module_id = 0x1; | ||
| 243 | |||
| 244 | rn_le = cpu_to_le64(module_id); | ||
| 245 | /* | ||
| 246 | * HDQ might not obey truly the 1-wire spec. | ||
| 247 | * So calculate CRC based on module parameter. | ||
| 248 | */ | ||
| 249 | cs = w1_calc_crc8((u8 *)&rn_le, 7); | ||
| 250 | id = (cs << 56) | module_id; | ||
| 251 | |||
| 252 | slave_found(_hdq, id); | ||
| 253 | } | ||
| 254 | |||
| 255 | static int _omap_hdq_reset(struct hdq_data *hdq_data) | ||
| 256 | { | ||
| 257 | int ret; | ||
| 258 | u8 tmp_status; | ||
| 259 | |||
| 260 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, OMAP_HDQ_SYSCONFIG_SOFTRESET); | ||
| 261 | /* | ||
| 262 | * Select HDQ mode & enable clocks. | ||
| 263 | * It is observed that INT flags can't be cleared via a read and GO/INIT | ||
| 264 | * won't return to zero if interrupt is disabled. So we always enable | ||
| 265 | * interrupt. | ||
| 266 | */ | ||
| 267 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
| 268 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | | ||
| 269 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); | ||
| 270 | |||
| 271 | /* wait for reset to complete */ | ||
| 272 | ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_SYSSTATUS, | ||
| 273 | OMAP_HDQ_SYSSTATUS_RESETDONE, OMAP_HDQ_FLAG_SET, &tmp_status); | ||
| 274 | if (ret) | ||
| 275 | dev_dbg(hdq_data->dev, "timeout waiting HDQ reset, %x", | ||
| 276 | tmp_status); | ||
| 277 | else { | ||
| 278 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
| 279 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | | ||
| 280 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); | ||
| 281 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, | ||
| 282 | OMAP_HDQ_SYSCONFIG_AUTOIDLE); | ||
| 283 | } | ||
| 284 | |||
| 285 | return ret; | ||
| 286 | } | ||
| 287 | |||
| 288 | /* Issue break pulse to the device */ | ||
| 289 | static int omap_hdq_break(struct hdq_data *hdq_data) | ||
| 290 | { | ||
| 291 | int ret = 0; | ||
| 292 | u8 tmp_status; | ||
| 293 | unsigned long irqflags; | ||
| 294 | |||
| 295 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
| 296 | if (ret < 0) { | ||
| 297 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
| 298 | ret = -EINTR; | ||
| 299 | goto rtn; | ||
| 300 | } | ||
| 301 | |||
| 302 | spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags); | ||
| 303 | /* clear interrupt flags via a dummy read */ | ||
| 304 | hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); | ||
| 305 | /* ISR loads it with new INT_STATUS */ | ||
| 306 | hdq_data->hdq_irqstatus = 0; | ||
| 307 | spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags); | ||
| 308 | |||
| 309 | /* set the INIT and GO bit */ | ||
| 310 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
| 311 | OMAP_HDQ_CTRL_STATUS_INITIALIZATION | OMAP_HDQ_CTRL_STATUS_GO, | ||
| 312 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_INITIALIZATION | | ||
| 313 | OMAP_HDQ_CTRL_STATUS_GO); | ||
| 314 | |||
| 315 | /* wait for the TIMEOUT bit */ | ||
| 316 | ret = wait_event_timeout(hdq_wait_queue, | ||
| 317 | hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT); | ||
| 318 | if (ret == 0) { | ||
| 319 | dev_dbg(hdq_data->dev, "break wait elapsed\n"); | ||
| 320 | ret = -EINTR; | ||
| 321 | goto out; | ||
| 322 | } | ||
| 323 | |||
| 324 | tmp_status = hdq_data->hdq_irqstatus; | ||
| 325 | /* check irqstatus */ | ||
| 326 | if (!(tmp_status & OMAP_HDQ_INT_STATUS_TIMEOUT)) { | ||
| 327 | dev_dbg(hdq_data->dev, "timeout waiting for TIMEOUT, %x", | ||
| 328 | tmp_status); | ||
| 329 | ret = -ETIMEDOUT; | ||
| 330 | goto out; | ||
| 331 | } | ||
| 332 | /* | ||
| 333 | * wait for both INIT and GO bits rerurn to zero. | ||
| 334 | * zero wait time expected for interrupt mode. | ||
| 335 | */ | ||
| 336 | ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
| 337 | OMAP_HDQ_CTRL_STATUS_INITIALIZATION | | ||
| 338 | OMAP_HDQ_CTRL_STATUS_GO, OMAP_HDQ_FLAG_CLEAR, | ||
| 339 | &tmp_status); | ||
| 340 | if (ret) | ||
| 341 | dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits" | ||
| 342 | "return to zero, %x", tmp_status); | ||
| 343 | |||
| 344 | out: | ||
| 345 | mutex_unlock(&hdq_data->hdq_mutex); | ||
| 346 | rtn: | ||
| 347 | return ret; | ||
| 348 | } | ||
| 349 | |||
| 350 | static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) | ||
| 351 | { | ||
| 352 | int ret = 0; | ||
| 353 | u8 status; | ||
| 354 | unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT; | ||
| 355 | |||
| 356 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
| 357 | if (ret < 0) { | ||
| 358 | ret = -EINTR; | ||
| 359 | goto rtn; | ||
| 360 | } | ||
| 361 | |||
| 362 | if (!hdq_data->hdq_usecount) { | ||
| 363 | ret = -EINVAL; | ||
| 364 | goto out; | ||
| 365 | } | ||
| 366 | |||
| 367 | if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { | ||
| 368 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
| 369 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO, | ||
| 370 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO); | ||
| 371 | /* | ||
| 372 | * The RX comes immediately after TX. It | ||
| 373 | * triggers another interrupt before we | ||
| 374 | * sleep. So we have to wait for RXCOMPLETE bit. | ||
| 375 | */ | ||
| 376 | while (!(hdq_data->hdq_irqstatus | ||
| 377 | & OMAP_HDQ_INT_STATUS_RXCOMPLETE) | ||
| 378 | && time_before(jiffies, timeout)) { | ||
| 379 | schedule_timeout_uninterruptible(1); | ||
| 380 | } | ||
| 381 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0, | ||
| 382 | OMAP_HDQ_CTRL_STATUS_DIR); | ||
| 383 | status = hdq_data->hdq_irqstatus; | ||
| 384 | /* check irqstatus */ | ||
| 385 | if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { | ||
| 386 | dev_dbg(hdq_data->dev, "timeout waiting for" | ||
| 387 | "RXCOMPLETE, %x", status); | ||
| 388 | ret = -ETIMEDOUT; | ||
| 389 | goto out; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | /* the data is ready. Read it in! */ | ||
| 393 | *val = hdq_reg_in(hdq_data, OMAP_HDQ_RX_DATA); | ||
| 394 | out: | ||
| 395 | mutex_unlock(&hdq_data->hdq_mutex); | ||
| 396 | rtn: | ||
| 397 | return 0; | ||
| 398 | |||
| 399 | } | ||
| 400 | |||
| 401 | /* Enable clocks and set the controller to HDQ mode */ | ||
| 402 | static int omap_hdq_get(struct hdq_data *hdq_data) | ||
| 403 | { | ||
| 404 | int ret = 0; | ||
| 405 | |||
| 406 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
| 407 | if (ret < 0) { | ||
| 408 | ret = -EINTR; | ||
| 409 | goto rtn; | ||
| 410 | } | ||
| 411 | |||
| 412 | if (OMAP_HDQ_MAX_USER == hdq_data->hdq_usecount) { | ||
| 413 | dev_dbg(hdq_data->dev, "attempt to exceed the max use count"); | ||
| 414 | ret = -EINVAL; | ||
| 415 | goto out; | ||
| 416 | } else { | ||
| 417 | hdq_data->hdq_usecount++; | ||
| 418 | try_module_get(THIS_MODULE); | ||
| 419 | if (1 == hdq_data->hdq_usecount) { | ||
| 420 | if (clk_enable(hdq_data->hdq_ick)) { | ||
| 421 | dev_dbg(hdq_data->dev, "Can not enable ick\n"); | ||
| 422 | ret = -ENODEV; | ||
| 423 | goto clk_err; | ||
| 424 | } | ||
| 425 | if (clk_enable(hdq_data->hdq_fck)) { | ||
| 426 | dev_dbg(hdq_data->dev, "Can not enable fck\n"); | ||
| 427 | clk_disable(hdq_data->hdq_ick); | ||
| 428 | ret = -ENODEV; | ||
| 429 | goto clk_err; | ||
| 430 | } | ||
| 431 | |||
| 432 | /* make sure HDQ is out of reset */ | ||
| 433 | if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) & | ||
| 434 | OMAP_HDQ_SYSSTATUS_RESETDONE)) { | ||
| 435 | ret = _omap_hdq_reset(hdq_data); | ||
| 436 | if (ret) | ||
| 437 | /* back up the count */ | ||
| 438 | hdq_data->hdq_usecount--; | ||
| 439 | } else { | ||
| 440 | /* select HDQ mode & enable clocks */ | ||
| 441 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
| 442 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | | ||
| 443 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); | ||
| 444 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, | ||
| 445 | OMAP_HDQ_SYSCONFIG_AUTOIDLE); | ||
| 446 | hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); | ||
| 447 | } | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | clk_err: | ||
| 452 | clk_put(hdq_data->hdq_ick); | ||
| 453 | clk_put(hdq_data->hdq_fck); | ||
| 454 | out: | ||
| 455 | mutex_unlock(&hdq_data->hdq_mutex); | ||
| 456 | rtn: | ||
| 457 | return ret; | ||
| 458 | } | ||
| 459 | |||
| 460 | /* Disable clocks to the module */ | ||
| 461 | static int omap_hdq_put(struct hdq_data *hdq_data) | ||
| 462 | { | ||
| 463 | int ret = 0; | ||
| 464 | |||
| 465 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
| 466 | if (ret < 0) | ||
| 467 | return -EINTR; | ||
| 468 | |||
| 469 | if (0 == hdq_data->hdq_usecount) { | ||
| 470 | dev_dbg(hdq_data->dev, "attempt to decrement use count" | ||
| 471 | "when it is zero"); | ||
| 472 | ret = -EINVAL; | ||
| 473 | } else { | ||
| 474 | hdq_data->hdq_usecount--; | ||
| 475 | module_put(THIS_MODULE); | ||
| 476 | if (0 == hdq_data->hdq_usecount) { | ||
| 477 | clk_disable(hdq_data->hdq_ick); | ||
| 478 | clk_disable(hdq_data->hdq_fck); | ||
| 479 | } | ||
| 480 | } | ||
| 481 | mutex_unlock(&hdq_data->hdq_mutex); | ||
| 482 | |||
| 483 | return ret; | ||
| 484 | } | ||
| 485 | |||
| 486 | /* Read a byte of data from the device */ | ||
| 487 | static u8 omap_w1_read_byte(void *_hdq) | ||
| 488 | { | ||
| 489 | struct hdq_data *hdq_data = _hdq; | ||
| 490 | u8 val = 0; | ||
| 491 | int ret; | ||
| 492 | |||
| 493 | ret = hdq_read_byte(hdq_data, &val); | ||
| 494 | if (ret) { | ||
| 495 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
| 496 | if (ret < 0) { | ||
| 497 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
| 498 | return -EINTR; | ||
| 499 | } | ||
| 500 | hdq_data->init_trans = 0; | ||
| 501 | mutex_unlock(&hdq_data->hdq_mutex); | ||
| 502 | omap_hdq_put(hdq_data); | ||
| 503 | return -1; | ||
| 504 | } | ||
| 505 | |||
| 506 | /* Write followed by a read, release the module */ | ||
| 507 | if (hdq_data->init_trans) { | ||
| 508 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
| 509 | if (ret < 0) { | ||
| 510 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
| 511 | return -EINTR; | ||
| 512 | } | ||
| 513 | hdq_data->init_trans = 0; | ||
| 514 | mutex_unlock(&hdq_data->hdq_mutex); | ||
| 515 | omap_hdq_put(hdq_data); | ||
| 516 | } | ||
| 517 | |||
| 518 | return val; | ||
| 519 | } | ||
| 520 | |||
| 521 | /* Write a byte of data to the device */ | ||
| 522 | static void omap_w1_write_byte(void *_hdq, u8 byte) | ||
| 523 | { | ||
| 524 | struct hdq_data *hdq_data = _hdq; | ||
| 525 | int ret; | ||
| 526 | u8 status; | ||
| 527 | |||
| 528 | /* First write to initialize the transfer */ | ||
| 529 | if (hdq_data->init_trans == 0) | ||
| 530 | omap_hdq_get(hdq_data); | ||
| 531 | |||
| 532 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
| 533 | if (ret < 0) { | ||
| 534 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
| 535 | return; | ||
| 536 | } | ||
| 537 | hdq_data->init_trans++; | ||
| 538 | mutex_unlock(&hdq_data->hdq_mutex); | ||
| 539 | |||
| 540 | ret = hdq_write_byte(hdq_data, byte, &status); | ||
| 541 | if (ret == 0) { | ||
| 542 | dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status); | ||
| 543 | return; | ||
| 544 | } | ||
| 545 | |||
| 546 | /* Second write, data transfered. Release the module */ | ||
| 547 | if (hdq_data->init_trans > 1) { | ||
| 548 | omap_hdq_put(hdq_data); | ||
| 549 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
| 550 | if (ret < 0) { | ||
| 551 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
| 552 | return; | ||
| 553 | } | ||
| 554 | hdq_data->init_trans = 0; | ||
| 555 | mutex_unlock(&hdq_data->hdq_mutex); | ||
| 556 | } | ||
| 557 | |||
| 558 | return; | ||
| 559 | } | ||
| 560 | |||
| 561 | static int __init omap_hdq_probe(struct platform_device *pdev) | ||
| 562 | { | ||
| 563 | struct hdq_data *hdq_data; | ||
| 564 | struct resource *res; | ||
| 565 | int ret, irq; | ||
| 566 | u8 rev; | ||
| 567 | |||
| 568 | hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL); | ||
| 569 | if (!hdq_data) { | ||
| 570 | dev_dbg(&pdev->dev, "unable to allocate memory\n"); | ||
| 571 | ret = -ENOMEM; | ||
| 572 | goto err_kmalloc; | ||
| 573 | } | ||
| 574 | |||
| 575 | hdq_data->dev = &pdev->dev; | ||
| 576 | platform_set_drvdata(pdev, hdq_data); | ||
| 577 | |||
| 578 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 579 | if (!res) { | ||
| 580 | dev_dbg(&pdev->dev, "unable to get resource\n"); | ||
| 581 | ret = -ENXIO; | ||
| 582 | goto err_resource; | ||
| 583 | } | ||
| 584 | |||
| 585 | hdq_data->hdq_base = ioremap(res->start, SZ_4K); | ||
| 586 | if (!hdq_data->hdq_base) { | ||
| 587 | dev_dbg(&pdev->dev, "ioremap failed\n"); | ||
| 588 | ret = -EINVAL; | ||
| 589 | goto err_ioremap; | ||
| 590 | } | ||
| 591 | |||
| 592 | /* get interface & functional clock objects */ | ||
| 593 | hdq_data->hdq_ick = clk_get(&pdev->dev, "hdq_ick"); | ||
| 594 | hdq_data->hdq_fck = clk_get(&pdev->dev, "hdq_fck"); | ||
| 595 | |||
| 596 | if (IS_ERR(hdq_data->hdq_ick) || IS_ERR(hdq_data->hdq_fck)) { | ||
| 597 | dev_dbg(&pdev->dev, "Can't get HDQ clock objects\n"); | ||
| 598 | if (IS_ERR(hdq_data->hdq_ick)) { | ||
| 599 | ret = PTR_ERR(hdq_data->hdq_ick); | ||
| 600 | goto err_clk; | ||
| 601 | } | ||
| 602 | if (IS_ERR(hdq_data->hdq_fck)) { | ||
| 603 | ret = PTR_ERR(hdq_data->hdq_fck); | ||
| 604 | clk_put(hdq_data->hdq_ick); | ||
| 605 | goto err_clk; | ||
| 606 | } | ||
| 607 | } | ||
| 608 | |||
| 609 | hdq_data->hdq_usecount = 0; | ||
| 610 | mutex_init(&hdq_data->hdq_mutex); | ||
| 611 | |||
| 612 | if (clk_enable(hdq_data->hdq_ick)) { | ||
| 613 | dev_dbg(&pdev->dev, "Can not enable ick\n"); | ||
| 614 | ret = -ENODEV; | ||
| 615 | goto err_intfclk; | ||
| 616 | } | ||
| 617 | |||
| 618 | if (clk_enable(hdq_data->hdq_fck)) { | ||
| 619 | dev_dbg(&pdev->dev, "Can not enable fck\n"); | ||
| 620 | ret = -ENODEV; | ||
| 621 | goto err_fnclk; | ||
| 622 | } | ||
| 623 | |||
| 624 | rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION); | ||
| 625 | dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n", | ||
| 626 | (rev >> 4) + '0', (rev & 0x0f) + '0', "Interrupt"); | ||
| 627 | |||
| 628 | spin_lock_init(&hdq_data->hdq_spinlock); | ||
| 629 | |||
| 630 | irq = platform_get_irq(pdev, 0); | ||
| 631 | if (irq < 0) { | ||
| 632 | ret = -ENXIO; | ||
| 633 | goto err_irq; | ||
| 634 | } | ||
| 635 | |||
| 636 | ret = request_irq(irq, hdq_isr, IRQF_DISABLED, "omap_hdq", hdq_data); | ||
| 637 | if (ret < 0) { | ||
| 638 | dev_dbg(&pdev->dev, "could not request irq\n"); | ||
| 639 | goto err_irq; | ||
| 640 | } | ||
| 641 | |||
| 642 | omap_hdq_break(hdq_data); | ||
| 643 | |||
| 644 | /* don't clock the HDQ until it is needed */ | ||
| 645 | clk_disable(hdq_data->hdq_ick); | ||
| 646 | clk_disable(hdq_data->hdq_fck); | ||
| 647 | |||
| 648 | omap_w1_master.data = hdq_data; | ||
| 649 | |||
| 650 | ret = w1_add_master_device(&omap_w1_master); | ||
| 651 | if (ret) { | ||
| 652 | dev_dbg(&pdev->dev, "Failure in registering w1 master\n"); | ||
| 653 | goto err_w1; | ||
| 654 | } | ||
| 655 | |||
| 656 | return 0; | ||
| 657 | |||
| 658 | err_w1: | ||
| 659 | err_irq: | ||
| 660 | clk_disable(hdq_data->hdq_fck); | ||
| 661 | |||
| 662 | err_fnclk: | ||
| 663 | clk_disable(hdq_data->hdq_ick); | ||
| 664 | |||
| 665 | err_intfclk: | ||
| 666 | clk_put(hdq_data->hdq_ick); | ||
| 667 | clk_put(hdq_data->hdq_fck); | ||
| 668 | |||
| 669 | err_clk: | ||
| 670 | iounmap(hdq_data->hdq_base); | ||
| 671 | |||
| 672 | err_ioremap: | ||
| 673 | err_resource: | ||
| 674 | platform_set_drvdata(pdev, NULL); | ||
| 675 | kfree(hdq_data); | ||
| 676 | |||
| 677 | err_kmalloc: | ||
| 678 | return ret; | ||
| 679 | |||
| 680 | } | ||
| 681 | |||
| 682 | static int omap_hdq_remove(struct platform_device *pdev) | ||
| 683 | { | ||
| 684 | struct hdq_data *hdq_data = platform_get_drvdata(pdev); | ||
| 685 | |||
| 686 | mutex_lock(&hdq_data->hdq_mutex); | ||
| 687 | |||
| 688 | if (hdq_data->hdq_usecount) { | ||
| 689 | dev_dbg(&pdev->dev, "removed when use count is not zero\n"); | ||
| 690 | return -EBUSY; | ||
| 691 | } | ||
| 692 | |||
| 693 | mutex_unlock(&hdq_data->hdq_mutex); | ||
| 694 | |||
| 695 | /* remove module dependency */ | ||
| 696 | clk_put(hdq_data->hdq_ick); | ||
| 697 | clk_put(hdq_data->hdq_fck); | ||
| 698 | free_irq(INT_24XX_HDQ_IRQ, hdq_data); | ||
| 699 | platform_set_drvdata(pdev, NULL); | ||
| 700 | iounmap(hdq_data->hdq_base); | ||
| 701 | kfree(hdq_data); | ||
| 702 | |||
| 703 | return 0; | ||
| 704 | } | ||
| 705 | |||
| 706 | static int __init | ||
| 707 | omap_hdq_init(void) | ||
| 708 | { | ||
| 709 | return platform_driver_register(&omap_hdq_driver); | ||
| 710 | } | ||
| 711 | module_init(omap_hdq_init); | ||
| 712 | |||
| 713 | static void __exit | ||
| 714 | omap_hdq_exit(void) | ||
| 715 | { | ||
| 716 | platform_driver_unregister(&omap_hdq_driver); | ||
| 717 | } | ||
| 718 | module_exit(omap_hdq_exit); | ||
| 719 | |||
| 720 | module_param(w1_id, int, S_IRUSR); | ||
| 721 | MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection"); | ||
| 722 | |||
| 723 | MODULE_AUTHOR("Texas Instruments"); | ||
| 724 | MODULE_DESCRIPTION("HDQ driver Library"); | ||
| 725 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index 3df29a122f84..8d0b1fb1e52e 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig | |||
| @@ -44,4 +44,11 @@ config W1_SLAVE_DS2760 | |||
| 44 | 44 | ||
| 45 | If you are unsure, say N. | 45 | If you are unsure, say N. |
| 46 | 46 | ||
| 47 | config W1_SLAVE_BQ27000 | ||
| 48 | tristate "BQ27000 slave support" | ||
| 49 | depends on W1 | ||
| 50 | help | ||
| 51 | Say Y here if you want to use a hdq | ||
| 52 | bq27000 slave support. | ||
| 53 | |||
| 47 | endmenu | 54 | endmenu |
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index a8eb7524df1d..990f400b6d22 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile | |||
| @@ -6,4 +6,4 @@ obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o | |||
| 6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o | 6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o |
| 7 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o | 7 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o |
| 8 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o | 8 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o |
| 9 | 9 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o | |
diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c new file mode 100644 index 000000000000..8f4c91f6c680 --- /dev/null +++ b/drivers/w1/slaves/w1_bq27000.c | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | /* | ||
| 2 | * drivers/w1/slaves/w1_bq27000.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Texas Instruments, Inc. | ||
| 5 | * | ||
| 6 | * This file is licensed under the terms of the GNU General Public License | ||
| 7 | * version 2. This program is licensed "as is" without any warranty of any | ||
| 8 | * kind, whether express or implied. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/types.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/mutex.h> | ||
| 18 | |||
| 19 | #include "../w1.h" | ||
| 20 | #include "../w1_int.h" | ||
| 21 | #include "../w1_family.h" | ||
| 22 | |||
| 23 | #define HDQ_CMD_READ (0) | ||
| 24 | #define HDQ_CMD_WRITE (1<<7) | ||
| 25 | |||
| 26 | static int F_ID; | ||
| 27 | |||
| 28 | void w1_bq27000_write(struct device *dev, u8 buf, u8 reg) | ||
| 29 | { | ||
| 30 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
| 31 | |||
| 32 | if (!dev) { | ||
| 33 | pr_info("Could not obtain slave dev ptr\n"); | ||
| 34 | return; | ||
| 35 | } | ||
| 36 | |||
| 37 | w1_write_8(sl->master, HDQ_CMD_WRITE | reg); | ||
| 38 | w1_write_8(sl->master, buf); | ||
| 39 | } | ||
| 40 | EXPORT_SYMBOL(w1_bq27000_write); | ||
| 41 | |||
| 42 | int w1_bq27000_read(struct device *dev, u8 reg) | ||
| 43 | { | ||
| 44 | u8 val; | ||
| 45 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
| 46 | |||
| 47 | if (!dev) | ||
| 48 | return 0; | ||
| 49 | |||
| 50 | w1_write_8(sl->master, HDQ_CMD_READ | reg); | ||
| 51 | val = w1_read_8(sl->master); | ||
| 52 | |||
| 53 | return val; | ||
| 54 | } | ||
| 55 | EXPORT_SYMBOL(w1_bq27000_read); | ||
| 56 | |||
| 57 | static int w1_bq27000_add_slave(struct w1_slave *sl) | ||
| 58 | { | ||
| 59 | int ret; | ||
| 60 | int id = 1; | ||
| 61 | struct platform_device *pdev; | ||
| 62 | |||
| 63 | pdev = platform_device_alloc("bq27000-battery", id); | ||
| 64 | if (!pdev) { | ||
| 65 | ret = -ENOMEM; | ||
| 66 | return ret; | ||
| 67 | } | ||
| 68 | pdev->dev.parent = &sl->dev; | ||
| 69 | |||
| 70 | ret = platform_device_add(pdev); | ||
| 71 | if (ret) | ||
| 72 | goto pdev_add_failed; | ||
| 73 | |||
| 74 | dev_set_drvdata(&sl->dev, pdev); | ||
| 75 | |||
| 76 | goto success; | ||
| 77 | |||
| 78 | pdev_add_failed: | ||
| 79 | platform_device_unregister(pdev); | ||
| 80 | success: | ||
| 81 | return ret; | ||
| 82 | } | ||
| 83 | |||
| 84 | static void w1_bq27000_remove_slave(struct w1_slave *sl) | ||
| 85 | { | ||
| 86 | struct platform_device *pdev = dev_get_drvdata(&sl->dev); | ||
| 87 | |||
| 88 | platform_device_unregister(pdev); | ||
| 89 | } | ||
| 90 | |||
| 91 | static struct w1_family_ops w1_bq27000_fops = { | ||
| 92 | .add_slave = w1_bq27000_add_slave, | ||
| 93 | .remove_slave = w1_bq27000_remove_slave, | ||
| 94 | }; | ||
| 95 | |||
| 96 | static struct w1_family w1_bq27000_family = { | ||
| 97 | .fid = 1, | ||
| 98 | .fops = &w1_bq27000_fops, | ||
| 99 | }; | ||
| 100 | |||
| 101 | static int __init w1_bq27000_init(void) | ||
| 102 | { | ||
| 103 | if (F_ID) | ||
| 104 | w1_bq27000_family.fid = F_ID; | ||
| 105 | |||
| 106 | return w1_register_family(&w1_bq27000_family); | ||
| 107 | } | ||
| 108 | |||
| 109 | static void __exit w1_bq27000_exit(void) | ||
| 110 | { | ||
| 111 | w1_unregister_family(&w1_bq27000_family); | ||
| 112 | } | ||
| 113 | |||
| 114 | |||
| 115 | module_init(w1_bq27000_init); | ||
| 116 | module_exit(w1_bq27000_exit); | ||
| 117 | |||
| 118 | module_param(F_ID, int, S_IRUSR); | ||
| 119 | MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ device"); | ||
| 120 | |||
| 121 | MODULE_LICENSE("GPL"); | ||
| 122 | MODULE_AUTHOR("Texas Instruments Ltd"); | ||
| 123 | MODULE_DESCRIPTION("HDQ/1-wire slave driver bq27000 battery monitor chip"); | ||
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index cdaa6fffbfc7..97304bd83ec9 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h | |||
| @@ -206,6 +206,7 @@ void w1_slave_detach(struct w1_slave *sl); | |||
| 206 | 206 | ||
| 207 | u8 w1_triplet(struct w1_master *dev, int bdir); | 207 | u8 w1_triplet(struct w1_master *dev, int bdir); |
| 208 | void w1_write_8(struct w1_master *, u8); | 208 | void w1_write_8(struct w1_master *, u8); |
| 209 | u8 w1_read_8(struct w1_master *); | ||
| 209 | int w1_reset_bus(struct w1_master *); | 210 | int w1_reset_bus(struct w1_master *); |
| 210 | u8 w1_calc_crc8(u8 *, int); | 211 | u8 w1_calc_crc8(u8 *, int); |
| 211 | void w1_write_block(struct w1_master *, const u8 *, int); | 212 | void w1_write_block(struct w1_master *, const u8 *, int); |
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index f4f82f1f486e..0d15b0eaf79a 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c | |||
| @@ -217,7 +217,7 @@ u8 w1_triplet(struct w1_master *dev, int bdir) | |||
| 217 | * @param dev the master device | 217 | * @param dev the master device |
| 218 | * @return the byte read | 218 | * @return the byte read |
| 219 | */ | 219 | */ |
| 220 | static u8 w1_read_8(struct w1_master * dev) | 220 | u8 w1_read_8(struct w1_master *dev) |
| 221 | { | 221 | { |
| 222 | int i; | 222 | int i; |
| 223 | u8 res = 0; | 223 | u8 res = 0; |
| @@ -230,6 +230,7 @@ static u8 w1_read_8(struct w1_master * dev) | |||
| 230 | 230 | ||
| 231 | return res; | 231 | return res; |
| 232 | } | 232 | } |
| 233 | EXPORT_SYMBOL_GPL(w1_read_8); | ||
| 233 | 234 | ||
| 234 | /** | 235 | /** |
| 235 | * Writes a series of bytes. | 236 | * Writes a series of bytes. |
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index c3b78a76f173..225398fd5049 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c | |||
| @@ -42,8 +42,10 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT; | |||
| 42 | 42 | ||
| 43 | #ifdef CONFIG_FSL_BOOKE | 43 | #ifdef CONFIG_FSL_BOOKE |
| 44 | #define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15)) | 44 | #define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15)) |
| 45 | #define WDTP_MASK (WDTP(0)) | ||
| 45 | #else | 46 | #else |
| 46 | #define WDTP(x) (TCR_WP(x)) | 47 | #define WDTP(x) (TCR_WP(x)) |
| 48 | #define WDTP_MASK (TCR_WP_MASK) | ||
| 47 | #endif | 49 | #endif |
| 48 | 50 | ||
| 49 | static DEFINE_SPINLOCK(booke_wdt_lock); | 51 | static DEFINE_SPINLOCK(booke_wdt_lock); |
| @@ -65,6 +67,7 @@ static void __booke_wdt_enable(void *data) | |||
| 65 | /* clear status before enabling watchdog */ | 67 | /* clear status before enabling watchdog */ |
| 66 | __booke_wdt_ping(NULL); | 68 | __booke_wdt_ping(NULL); |
| 67 | val = mfspr(SPRN_TCR); | 69 | val = mfspr(SPRN_TCR); |
| 70 | val &= ~WDTP_MASK; | ||
| 68 | val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); | 71 | val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); |
| 69 | 72 | ||
| 70 | mtspr(SPRN_TCR, val); | 73 | mtspr(SPRN_TCR, val); |
| @@ -114,7 +117,7 @@ static long booke_wdt_ioctl(struct file *file, | |||
| 114 | case WDIOC_SETTIMEOUT: | 117 | case WDIOC_SETTIMEOUT: |
| 115 | if (get_user(booke_wdt_period, p)) | 118 | if (get_user(booke_wdt_period, p)) |
| 116 | return -EFAULT; | 119 | return -EFAULT; |
| 117 | mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP(0)) | | 120 | mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP_MASK) | |
| 118 | WDTP(booke_wdt_period)); | 121 | WDTP(booke_wdt_period)); |
| 119 | return 0; | 122 | return 0; |
| 120 | case WDIOC_GETTIMEOUT: | 123 | case WDIOC_GETTIMEOUT: |
