diff options
Diffstat (limited to 'drivers')
117 files changed, 6059 insertions, 2557 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 08e0140920e1..b811f2173f6f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -54,17 +54,10 @@ config ACPI_PROCFS | |||
54 | they have been replaced by functions in /sys. | 54 | they have been replaced by functions in /sys. |
55 | The deprecated files (and their replacements) include: | 55 | The deprecated files (and their replacements) include: |
56 | 56 | ||
57 | /proc/acpi/sleep (/sys/power/state) | ||
58 | /proc/acpi/info (/sys/module/acpi/parameters/acpica_version) | ||
59 | /proc/acpi/dsdt (/sys/firmware/acpi/tables/DSDT) | ||
60 | /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) | ||
61 | /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) | ||
62 | /proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level) | ||
63 | /proc/acpi/processor/*/power (/sys/devices/system/cpu/*/cpuidle/*) | ||
64 | /proc/acpi/processor/*/performance (/sys/devices/system/cpu/*/ | ||
65 | cpufreq/*) | ||
66 | /proc/acpi/processor/*/throttling (/sys/class/thermal/ | 57 | /proc/acpi/processor/*/throttling (/sys/class/thermal/ |
67 | cooling_device*/*) | 58 | cooling_device*/*) |
59 | /proc/acpi/video/*/brightness (/sys/class/backlight/) | ||
60 | /proc/acpi/thermal_zone/*/* (/sys/class/thermal/) | ||
68 | This option has no effect on /proc/acpi/ files | 61 | This option has no effect on /proc/acpi/ files |
69 | and functions which do not yet exist in /sys. | 62 | and functions which do not yet exist in /sys. |
70 | 63 | ||
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 833b582d1762..3d031d02e54b 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -37,8 +37,9 @@ acpi-y += ec.o | |||
37 | acpi-$(CONFIG_ACPI_DOCK) += dock.o | 37 | acpi-$(CONFIG_ACPI_DOCK) += dock.o |
38 | acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o | 38 | acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o |
39 | acpi-y += power.o | 39 | acpi-y += power.o |
40 | acpi-y += system.o event.o | 40 | acpi-y += event.o |
41 | acpi-$(CONFIG_ACPI_DEBUG) += debug.o | 41 | acpi-y += sysfs.o |
42 | acpi-$(CONFIG_DEBUG_FS) += debugfs.o | ||
42 | acpi-$(CONFIG_ACPI_NUMA) += numa.o | 43 | acpi-$(CONFIG_ACPI_NUMA) += numa.o |
43 | acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o | 44 | acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o |
44 | ifdef CONFIG_ACPI_VIDEO | 45 | ifdef CONFIG_ACPI_VIDEO |
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index e0e6affb0d80..36867cd70eac 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h | |||
@@ -82,6 +82,10 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info); | |||
82 | 82 | ||
83 | acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); | 83 | acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); |
84 | 84 | ||
85 | acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); | ||
86 | |||
87 | acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); | ||
88 | |||
85 | struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, | 89 | struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, |
86 | u32 gpe_number); | 90 | u32 gpe_number); |
87 | 91 | ||
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 18e796fe4295..1d192142c691 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h | |||
@@ -108,7 +108,7 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE); | |||
108 | /* | 108 | /* |
109 | * Optionally enable output from the AML Debug Object. | 109 | * Optionally enable output from the AML Debug Object. |
110 | */ | 110 | */ |
111 | u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE); | 111 | u32 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE); |
112 | 112 | ||
113 | /* | 113 | /* |
114 | * Optionally copy the entire DSDT to local memory (instead of simply | 114 | * Optionally copy the entire DSDT to local memory (instead of simply |
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 1ee0bcf399aa..df85b53a674f 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
@@ -412,6 +412,7 @@ struct acpi_handler_info { | |||
412 | acpi_event_handler address; /* Address of handler, if any */ | 412 | acpi_event_handler address; /* Address of handler, if any */ |
413 | void *context; /* Context to be passed to handler */ | 413 | void *context; /* Context to be passed to handler */ |
414 | struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ | 414 | struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ |
415 | u8 orig_flags; /* Original misc info about this GPE */ | ||
415 | }; | 416 | }; |
416 | 417 | ||
417 | union acpi_gpe_dispatch_info { | 418 | union acpi_gpe_dispatch_info { |
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 7a6a3e6f4be0..f226eac314db 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
@@ -137,6 +137,79 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
137 | 137 | ||
138 | /******************************************************************************* | 138 | /******************************************************************************* |
139 | * | 139 | * |
140 | * FUNCTION: acpi_raw_enable_gpe | ||
141 | * | ||
142 | * PARAMETERS: gpe_event_info - GPE to enable | ||
143 | * | ||
144 | * RETURN: Status | ||
145 | * | ||
146 | * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is | ||
147 | * hardware-enabled. | ||
148 | * | ||
149 | ******************************************************************************/ | ||
150 | |||
151 | acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | ||
152 | { | ||
153 | acpi_status status = AE_OK; | ||
154 | |||
155 | if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) { | ||
156 | return_ACPI_STATUS(AE_LIMIT); | ||
157 | } | ||
158 | |||
159 | gpe_event_info->runtime_count++; | ||
160 | if (gpe_event_info->runtime_count == 1) { | ||
161 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); | ||
162 | if (ACPI_SUCCESS(status)) { | ||
163 | status = acpi_ev_enable_gpe(gpe_event_info); | ||
164 | } | ||
165 | |||
166 | if (ACPI_FAILURE(status)) { | ||
167 | gpe_event_info->runtime_count--; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | return_ACPI_STATUS(status); | ||
172 | } | ||
173 | |||
174 | /******************************************************************************* | ||
175 | * | ||
176 | * FUNCTION: acpi_raw_disable_gpe | ||
177 | * | ||
178 | * PARAMETERS: gpe_event_info - GPE to disable | ||
179 | * | ||
180 | * RETURN: Status | ||
181 | * | ||
182 | * DESCRIPTION: Remove a reference to a GPE. When the last reference is | ||
183 | * removed, the GPE is hardware-disabled. | ||
184 | * | ||
185 | ******************************************************************************/ | ||
186 | |||
187 | acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | ||
188 | { | ||
189 | acpi_status status = AE_OK; | ||
190 | |||
191 | if (!gpe_event_info->runtime_count) { | ||
192 | return_ACPI_STATUS(AE_LIMIT); | ||
193 | } | ||
194 | |||
195 | gpe_event_info->runtime_count--; | ||
196 | if (!gpe_event_info->runtime_count) { | ||
197 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); | ||
198 | if (ACPI_SUCCESS(status)) { | ||
199 | status = acpi_hw_low_set_gpe(gpe_event_info, | ||
200 | ACPI_GPE_DISABLE); | ||
201 | } | ||
202 | |||
203 | if (ACPI_FAILURE(status)) { | ||
204 | gpe_event_info->runtime_count++; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | return_ACPI_STATUS(status); | ||
209 | } | ||
210 | |||
211 | /******************************************************************************* | ||
212 | * | ||
140 | * FUNCTION: acpi_ev_low_get_gpe_info | 213 | * FUNCTION: acpi_ev_low_get_gpe_info |
141 | * | 214 | * |
142 | * PARAMETERS: gpe_number - Raw GPE number | 215 | * PARAMETERS: gpe_number - Raw GPE number |
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 4a531cdf7942..14e48add32fa 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c | |||
@@ -691,12 +691,22 @@ acpi_install_gpe_handler(acpi_handle gpe_device, | |||
691 | return_ACPI_STATUS(status); | 691 | return_ACPI_STATUS(status); |
692 | } | 692 | } |
693 | 693 | ||
694 | /* Allocate memory for the handler object */ | ||
695 | |||
696 | handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info)); | ||
697 | if (!handler) { | ||
698 | status = AE_NO_MEMORY; | ||
699 | goto unlock_and_exit; | ||
700 | } | ||
701 | |||
702 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
703 | |||
694 | /* Ensure that we have a valid GPE number */ | 704 | /* Ensure that we have a valid GPE number */ |
695 | 705 | ||
696 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 706 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
697 | if (!gpe_event_info) { | 707 | if (!gpe_event_info) { |
698 | status = AE_BAD_PARAMETER; | 708 | status = AE_BAD_PARAMETER; |
699 | goto unlock_and_exit; | 709 | goto free_and_exit; |
700 | } | 710 | } |
701 | 711 | ||
702 | /* Make sure that there isn't a handler there already */ | 712 | /* Make sure that there isn't a handler there already */ |
@@ -704,24 +714,30 @@ acpi_install_gpe_handler(acpi_handle gpe_device, | |||
704 | if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | 714 | if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == |
705 | ACPI_GPE_DISPATCH_HANDLER) { | 715 | ACPI_GPE_DISPATCH_HANDLER) { |
706 | status = AE_ALREADY_EXISTS; | 716 | status = AE_ALREADY_EXISTS; |
707 | goto unlock_and_exit; | 717 | goto free_and_exit; |
708 | } | 718 | } |
709 | 719 | ||
710 | /* Allocate and init handler object */ | 720 | /* Allocate and init handler object */ |
711 | 721 | ||
712 | handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info)); | ||
713 | if (!handler) { | ||
714 | status = AE_NO_MEMORY; | ||
715 | goto unlock_and_exit; | ||
716 | } | ||
717 | |||
718 | handler->address = address; | 722 | handler->address = address; |
719 | handler->context = context; | 723 | handler->context = context; |
720 | handler->method_node = gpe_event_info->dispatch.method_node; | 724 | handler->method_node = gpe_event_info->dispatch.method_node; |
725 | handler->orig_flags = gpe_event_info->flags & | ||
726 | (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); | ||
727 | |||
728 | /* | ||
729 | * If the GPE is associated with a method and it cannot wake up the | ||
730 | * system from sleep states, it was enabled automatically during | ||
731 | * initialization, so it has to be disabled now to avoid spurious | ||
732 | * execution of the handler. | ||
733 | */ | ||
734 | |||
735 | if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) | ||
736 | && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) | ||
737 | (void)acpi_raw_disable_gpe(gpe_event_info); | ||
721 | 738 | ||
722 | /* Install the handler */ | 739 | /* Install the handler */ |
723 | 740 | ||
724 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
725 | gpe_event_info->dispatch.handler = handler; | 741 | gpe_event_info->dispatch.handler = handler; |
726 | 742 | ||
727 | /* Setup up dispatch flags to indicate handler (vs. method) */ | 743 | /* Setup up dispatch flags to indicate handler (vs. method) */ |
@@ -735,6 +751,11 @@ acpi_install_gpe_handler(acpi_handle gpe_device, | |||
735 | unlock_and_exit: | 751 | unlock_and_exit: |
736 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | 752 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
737 | return_ACPI_STATUS(status); | 753 | return_ACPI_STATUS(status); |
754 | |||
755 | free_and_exit: | ||
756 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
757 | ACPI_FREE(handler); | ||
758 | goto unlock_and_exit; | ||
738 | } | 759 | } |
739 | 760 | ||
740 | ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) | 761 | ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) |
@@ -770,11 +791,17 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, | |||
770 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 791 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
771 | } | 792 | } |
772 | 793 | ||
794 | /* Make sure all deferred tasks are completed */ | ||
795 | |||
796 | acpi_os_wait_events_complete(NULL); | ||
797 | |||
773 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | 798 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); |
774 | if (ACPI_FAILURE(status)) { | 799 | if (ACPI_FAILURE(status)) { |
775 | return_ACPI_STATUS(status); | 800 | return_ACPI_STATUS(status); |
776 | } | 801 | } |
777 | 802 | ||
803 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
804 | |||
778 | /* Ensure that we have a valid GPE number */ | 805 | /* Ensure that we have a valid GPE number */ |
779 | 806 | ||
780 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 807 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
@@ -798,34 +825,34 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, | |||
798 | goto unlock_and_exit; | 825 | goto unlock_and_exit; |
799 | } | 826 | } |
800 | 827 | ||
801 | /* Make sure all deferred tasks are completed */ | ||
802 | |||
803 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
804 | acpi_os_wait_events_complete(NULL); | ||
805 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
806 | if (ACPI_FAILURE(status)) { | ||
807 | return_ACPI_STATUS(status); | ||
808 | } | ||
809 | |||
810 | /* Remove the handler */ | 828 | /* Remove the handler */ |
811 | 829 | ||
812 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
813 | handler = gpe_event_info->dispatch.handler; | 830 | handler = gpe_event_info->dispatch.handler; |
814 | 831 | ||
815 | /* Restore Method node (if any), set dispatch flags */ | 832 | /* Restore Method node (if any), set dispatch flags */ |
816 | 833 | ||
817 | gpe_event_info->dispatch.method_node = handler->method_node; | 834 | gpe_event_info->dispatch.method_node = handler->method_node; |
818 | gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ | 835 | gpe_event_info->flags &= |
819 | if (handler->method_node) { | 836 | ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); |
820 | gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD; | 837 | gpe_event_info->flags |= handler->orig_flags; |
821 | } | 838 | |
822 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 839 | /* |
840 | * If the GPE was previously associated with a method and it cannot wake | ||
841 | * up the system from sleep states, it should be enabled at this point | ||
842 | * to restore the post-initialization configuration. | ||
843 | */ | ||
844 | |||
845 | if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) | ||
846 | && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) | ||
847 | (void)acpi_raw_enable_gpe(gpe_event_info); | ||
823 | 848 | ||
824 | /* Now we can free the handler object */ | 849 | /* Now we can free the handler object */ |
825 | 850 | ||
826 | ACPI_FREE(handler); | 851 | ACPI_FREE(handler); |
827 | 852 | ||
828 | unlock_and_exit: | 853 | unlock_and_exit: |
854 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
855 | |||
829 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | 856 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
830 | return_ACPI_STATUS(status); | 857 | return_ACPI_STATUS(status); |
831 | } | 858 | } |
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 0ec900da5794..304825528d48 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c | |||
@@ -294,7 +294,7 @@ ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup) | |||
294 | ******************************************************************************/ | 294 | ******************************************************************************/ |
295 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) | 295 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) |
296 | { | 296 | { |
297 | acpi_status status = AE_OK; | 297 | acpi_status status = AE_BAD_PARAMETER; |
298 | struct acpi_gpe_event_info *gpe_event_info; | 298 | struct acpi_gpe_event_info *gpe_event_info; |
299 | acpi_cpu_flags flags; | 299 | acpi_cpu_flags flags; |
300 | 300 | ||
@@ -305,28 +305,10 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) | |||
305 | /* Ensure that we have a valid GPE number */ | 305 | /* Ensure that we have a valid GPE number */ |
306 | 306 | ||
307 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 307 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
308 | if (!gpe_event_info) { | 308 | if (gpe_event_info) { |
309 | status = AE_BAD_PARAMETER; | 309 | status = acpi_raw_enable_gpe(gpe_event_info); |
310 | goto unlock_and_exit; | ||
311 | } | 310 | } |
312 | 311 | ||
313 | if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) { | ||
314 | status = AE_LIMIT; /* Too many references */ | ||
315 | goto unlock_and_exit; | ||
316 | } | ||
317 | |||
318 | gpe_event_info->runtime_count++; | ||
319 | if (gpe_event_info->runtime_count == 1) { | ||
320 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); | ||
321 | if (ACPI_SUCCESS(status)) { | ||
322 | status = acpi_ev_enable_gpe(gpe_event_info); | ||
323 | } | ||
324 | if (ACPI_FAILURE(status)) { | ||
325 | gpe_event_info->runtime_count--; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | unlock_and_exit: | ||
330 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 312 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
331 | return_ACPI_STATUS(status); | 313 | return_ACPI_STATUS(status); |
332 | } | 314 | } |
@@ -348,7 +330,7 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | |||
348 | ******************************************************************************/ | 330 | ******************************************************************************/ |
349 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) | 331 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) |
350 | { | 332 | { |
351 | acpi_status status = AE_OK; | 333 | acpi_status status = AE_BAD_PARAMETER; |
352 | struct acpi_gpe_event_info *gpe_event_info; | 334 | struct acpi_gpe_event_info *gpe_event_info; |
353 | acpi_cpu_flags flags; | 335 | acpi_cpu_flags flags; |
354 | 336 | ||
@@ -359,32 +341,10 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) | |||
359 | /* Ensure that we have a valid GPE number */ | 341 | /* Ensure that we have a valid GPE number */ |
360 | 342 | ||
361 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 343 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
362 | if (!gpe_event_info) { | 344 | if (gpe_event_info) { |
363 | status = AE_BAD_PARAMETER; | 345 | status = acpi_raw_disable_gpe(gpe_event_info) ; |
364 | goto unlock_and_exit; | ||
365 | } | ||
366 | |||
367 | /* Hardware-disable a runtime GPE on removal of the last reference */ | ||
368 | |||
369 | if (!gpe_event_info->runtime_count) { | ||
370 | status = AE_LIMIT; /* There are no references to remove */ | ||
371 | goto unlock_and_exit; | ||
372 | } | 346 | } |
373 | 347 | ||
374 | gpe_event_info->runtime_count--; | ||
375 | if (!gpe_event_info->runtime_count) { | ||
376 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); | ||
377 | if (ACPI_SUCCESS(status)) { | ||
378 | status = | ||
379 | acpi_hw_low_set_gpe(gpe_event_info, | ||
380 | ACPI_GPE_DISABLE); | ||
381 | } | ||
382 | if (ACPI_FAILURE(status)) { | ||
383 | gpe_event_info->runtime_count++; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | unlock_and_exit: | ||
388 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 348 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
389 | return_ACPI_STATUS(status); | 349 | return_ACPI_STATUS(status); |
390 | } | 350 | } |
@@ -411,7 +371,6 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number) | |||
411 | acpi_status status = AE_OK; | 371 | acpi_status status = AE_OK; |
412 | struct acpi_gpe_event_info *gpe_event_info; | 372 | struct acpi_gpe_event_info *gpe_event_info; |
413 | acpi_cpu_flags flags; | 373 | acpi_cpu_flags flags; |
414 | u8 disable = 0; | ||
415 | 374 | ||
416 | ACPI_FUNCTION_TRACE(acpi_gpe_can_wake); | 375 | ACPI_FUNCTION_TRACE(acpi_gpe_can_wake); |
417 | 376 | ||
@@ -430,15 +389,12 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number) | |||
430 | } | 389 | } |
431 | 390 | ||
432 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | 391 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; |
433 | disable = (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) | 392 | if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) { |
434 | && gpe_event_info->runtime_count; | 393 | (void)acpi_raw_disable_gpe(gpe_event_info); |
394 | } | ||
435 | 395 | ||
436 | unlock_and_exit: | 396 | unlock_and_exit: |
437 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 397 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
438 | |||
439 | if (disable) | ||
440 | status = acpi_disable_gpe(gpe_device, gpe_number); | ||
441 | |||
442 | return_ACPI_STATUS(status); | 398 | return_ACPI_STATUS(status); |
443 | } | 399 | } |
444 | ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake) | 400 | ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake) |
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index 058b3df48271..f5cca3a1300c 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c | |||
@@ -279,13 +279,10 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) | |||
279 | 279 | ||
280 | acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) | 280 | acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) |
281 | { | 281 | { |
282 | acpi_thread_id this_thread_id; | ||
283 | |||
284 | ACPI_FUNCTION_NAME(ut_release_mutex); | 282 | ACPI_FUNCTION_NAME(ut_release_mutex); |
285 | 283 | ||
286 | this_thread_id = acpi_os_get_thread_id(); | ||
287 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n", | 284 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n", |
288 | ACPI_CAST_PTR(void, this_thread_id), | 285 | ACPI_CAST_PTR(void, acpi_os_get_thread_id()), |
289 | acpi_ut_get_mutex_name(mutex_id))); | 286 | acpi_ut_get_mutex_name(mutex_id))); |
290 | 287 | ||
291 | if (mutex_id > ACPI_MAX_MUTEX) { | 288 | if (mutex_id > ACPI_MAX_MUTEX) { |
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index f8c668f27b5a..907e350f1c7d 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig | |||
@@ -28,3 +28,12 @@ config ACPI_APEI_EINJ | |||
28 | EINJ provides a hardware error injection mechanism, it is | 28 | EINJ provides a hardware error injection mechanism, it is |
29 | mainly used for debugging and testing the other parts of | 29 | mainly used for debugging and testing the other parts of |
30 | APEI and some other RAS features. | 30 | APEI and some other RAS features. |
31 | |||
32 | config ACPI_APEI_ERST_DEBUG | ||
33 | tristate "APEI Error Record Serialization Table (ERST) Debug Support" | ||
34 | depends on ACPI_APEI | ||
35 | help | ||
36 | ERST is a way provided by APEI to save and retrieve hardware | ||
37 | error infomation to and from a persistent store. Enable this | ||
38 | if you want to debugging and testing the ERST kernel support | ||
39 | and firmware implementation. | ||
diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile index b13b03a17789..d1d1bc0a4ee1 100644 --- a/drivers/acpi/apei/Makefile +++ b/drivers/acpi/apei/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-$(CONFIG_ACPI_APEI) += apei.o | 1 | obj-$(CONFIG_ACPI_APEI) += apei.o |
2 | obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o | 2 | obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o |
3 | obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o | 3 | obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o |
4 | obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o | ||
4 | 5 | ||
5 | apei-y := apei-base.o hest.o cper.o erst.o | 6 | apei-y := apei-base.o hest.o cper.o erst.o |
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 216e1e948ff6..73fd0c7487c1 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -482,14 +482,14 @@ err_unmap_ioport: | |||
482 | list_for_each_entry(res, &resources->ioport, list) { | 482 | list_for_each_entry(res, &resources->ioport, list) { |
483 | if (res == res_bak) | 483 | if (res == res_bak) |
484 | break; | 484 | break; |
485 | release_mem_region(res->start, res->end - res->start); | 485 | release_region(res->start, res->end - res->start); |
486 | } | 486 | } |
487 | res_bak = NULL; | 487 | res_bak = NULL; |
488 | err_unmap_iomem: | 488 | err_unmap_iomem: |
489 | list_for_each_entry(res, &resources->iomem, list) { | 489 | list_for_each_entry(res, &resources->iomem, list) { |
490 | if (res == res_bak) | 490 | if (res == res_bak) |
491 | break; | 491 | break; |
492 | release_region(res->start, res->end - res->start); | 492 | release_mem_region(res->start, res->end - res->start); |
493 | } | 493 | } |
494 | return -EINVAL; | 494 | return -EINVAL; |
495 | } | 495 | } |
diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c new file mode 100644 index 000000000000..5281ddda2777 --- /dev/null +++ b/drivers/acpi/apei/erst-dbg.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * APEI Error Record Serialization Table debug support | ||
3 | * | ||
4 | * ERST is a way provided by APEI to save and retrieve hardware error | ||
5 | * infomation to and from a persistent store. This file provide the | ||
6 | * debugging/testing support for ERST kernel support and firmware | ||
7 | * implementation. | ||
8 | * | ||
9 | * Copyright 2010 Intel Corp. | ||
10 | * Author: Huang Ying <ying.huang@intel.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License version | ||
14 | * 2 as published by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/uaccess.h> | ||
29 | #include <acpi/apei.h> | ||
30 | #include <linux/miscdevice.h> | ||
31 | |||
32 | #include "apei-internal.h" | ||
33 | |||
34 | #define ERST_DBG_PFX "ERST DBG: " | ||
35 | |||
36 | #define ERST_DBG_RECORD_LEN_MAX 4096 | ||
37 | |||
38 | static void *erst_dbg_buf; | ||
39 | static unsigned int erst_dbg_buf_len; | ||
40 | |||
41 | /* Prevent erst_dbg_read/write from being invoked concurrently */ | ||
42 | static DEFINE_MUTEX(erst_dbg_mutex); | ||
43 | |||
44 | static int erst_dbg_open(struct inode *inode, struct file *file) | ||
45 | { | ||
46 | if (erst_disable) | ||
47 | return -ENODEV; | ||
48 | |||
49 | return nonseekable_open(inode, file); | ||
50 | } | ||
51 | |||
52 | static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | ||
53 | { | ||
54 | int rc; | ||
55 | u64 record_id; | ||
56 | u32 record_count; | ||
57 | |||
58 | switch (cmd) { | ||
59 | case APEI_ERST_CLEAR_RECORD: | ||
60 | rc = copy_from_user(&record_id, (void __user *)arg, | ||
61 | sizeof(record_id)); | ||
62 | if (rc) | ||
63 | return -EFAULT; | ||
64 | return erst_clear(record_id); | ||
65 | case APEI_ERST_GET_RECORD_COUNT: | ||
66 | rc = erst_get_record_count(); | ||
67 | if (rc < 0) | ||
68 | return rc; | ||
69 | record_count = rc; | ||
70 | rc = put_user(record_count, (u32 __user *)arg); | ||
71 | if (rc) | ||
72 | return rc; | ||
73 | return 0; | ||
74 | default: | ||
75 | return -ENOTTY; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf, | ||
80 | size_t usize, loff_t *off) | ||
81 | { | ||
82 | int rc; | ||
83 | ssize_t len = 0; | ||
84 | u64 id; | ||
85 | |||
86 | if (*off != 0) | ||
87 | return -EINVAL; | ||
88 | |||
89 | if (mutex_lock_interruptible(&erst_dbg_mutex) != 0) | ||
90 | return -EINTR; | ||
91 | |||
92 | retry_next: | ||
93 | rc = erst_get_next_record_id(&id); | ||
94 | if (rc) | ||
95 | goto out; | ||
96 | /* no more record */ | ||
97 | if (id == APEI_ERST_INVALID_RECORD_ID) | ||
98 | goto out; | ||
99 | retry: | ||
100 | rc = len = erst_read(id, erst_dbg_buf, erst_dbg_buf_len); | ||
101 | /* The record may be cleared by others, try read next record */ | ||
102 | if (rc == -ENOENT) | ||
103 | goto retry_next; | ||
104 | if (rc < 0) | ||
105 | goto out; | ||
106 | if (len > ERST_DBG_RECORD_LEN_MAX) { | ||
107 | pr_warning(ERST_DBG_PFX | ||
108 | "Record (ID: 0x%llx) length is too long: %zd\n", | ||
109 | id, len); | ||
110 | rc = -EIO; | ||
111 | goto out; | ||
112 | } | ||
113 | if (len > erst_dbg_buf_len) { | ||
114 | kfree(erst_dbg_buf); | ||
115 | rc = -ENOMEM; | ||
116 | erst_dbg_buf = kmalloc(len, GFP_KERNEL); | ||
117 | if (!erst_dbg_buf) | ||
118 | goto out; | ||
119 | erst_dbg_buf_len = len; | ||
120 | goto retry; | ||
121 | } | ||
122 | |||
123 | rc = -EINVAL; | ||
124 | if (len > usize) | ||
125 | goto out; | ||
126 | |||
127 | rc = -EFAULT; | ||
128 | if (copy_to_user(ubuf, erst_dbg_buf, len)) | ||
129 | goto out; | ||
130 | rc = 0; | ||
131 | out: | ||
132 | mutex_unlock(&erst_dbg_mutex); | ||
133 | return rc ? rc : len; | ||
134 | } | ||
135 | |||
136 | static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf, | ||
137 | size_t usize, loff_t *off) | ||
138 | { | ||
139 | int rc; | ||
140 | struct cper_record_header *rcd; | ||
141 | |||
142 | if (!capable(CAP_SYS_ADMIN)) | ||
143 | return -EPERM; | ||
144 | |||
145 | if (usize > ERST_DBG_RECORD_LEN_MAX) { | ||
146 | pr_err(ERST_DBG_PFX "Too long record to be written\n"); | ||
147 | return -EINVAL; | ||
148 | } | ||
149 | |||
150 | if (mutex_lock_interruptible(&erst_dbg_mutex)) | ||
151 | return -EINTR; | ||
152 | if (usize > erst_dbg_buf_len) { | ||
153 | kfree(erst_dbg_buf); | ||
154 | rc = -ENOMEM; | ||
155 | erst_dbg_buf = kmalloc(usize, GFP_KERNEL); | ||
156 | if (!erst_dbg_buf) | ||
157 | goto out; | ||
158 | erst_dbg_buf_len = usize; | ||
159 | } | ||
160 | rc = copy_from_user(erst_dbg_buf, ubuf, usize); | ||
161 | if (rc) { | ||
162 | rc = -EFAULT; | ||
163 | goto out; | ||
164 | } | ||
165 | rcd = erst_dbg_buf; | ||
166 | rc = -EINVAL; | ||
167 | if (rcd->record_length != usize) | ||
168 | goto out; | ||
169 | |||
170 | rc = erst_write(erst_dbg_buf); | ||
171 | |||
172 | out: | ||
173 | mutex_unlock(&erst_dbg_mutex); | ||
174 | return rc < 0 ? rc : usize; | ||
175 | } | ||
176 | |||
177 | static const struct file_operations erst_dbg_ops = { | ||
178 | .owner = THIS_MODULE, | ||
179 | .open = erst_dbg_open, | ||
180 | .read = erst_dbg_read, | ||
181 | .write = erst_dbg_write, | ||
182 | .unlocked_ioctl = erst_dbg_ioctl, | ||
183 | }; | ||
184 | |||
185 | static struct miscdevice erst_dbg_dev = { | ||
186 | .minor = MISC_DYNAMIC_MINOR, | ||
187 | .name = "erst_dbg", | ||
188 | .fops = &erst_dbg_ops, | ||
189 | }; | ||
190 | |||
191 | static __init int erst_dbg_init(void) | ||
192 | { | ||
193 | return misc_register(&erst_dbg_dev); | ||
194 | } | ||
195 | |||
196 | static __exit void erst_dbg_exit(void) | ||
197 | { | ||
198 | misc_deregister(&erst_dbg_dev); | ||
199 | kfree(erst_dbg_buf); | ||
200 | } | ||
201 | |||
202 | module_init(erst_dbg_init); | ||
203 | module_exit(erst_dbg_exit); | ||
204 | |||
205 | MODULE_AUTHOR("Huang Ying"); | ||
206 | MODULE_DESCRIPTION("APEI Error Record Serialization Table debug support"); | ||
207 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index fd0cc016a099..385a6059714a 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -41,6 +41,8 @@ | |||
41 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
42 | #include <linux/cper.h> | 42 | #include <linux/cper.h> |
43 | #include <linux/kdebug.h> | 43 | #include <linux/kdebug.h> |
44 | #include <linux/platform_device.h> | ||
45 | #include <linux/mutex.h> | ||
44 | #include <acpi/apei.h> | 46 | #include <acpi/apei.h> |
45 | #include <acpi/atomicio.h> | 47 | #include <acpi/atomicio.h> |
46 | #include <acpi/hed.h> | 48 | #include <acpi/hed.h> |
@@ -87,6 +89,7 @@ struct ghes { | |||
87 | * used for that. | 89 | * used for that. |
88 | */ | 90 | */ |
89 | static LIST_HEAD(ghes_sci); | 91 | static LIST_HEAD(ghes_sci); |
92 | static DEFINE_MUTEX(ghes_list_mutex); | ||
90 | 93 | ||
91 | static struct ghes *ghes_new(struct acpi_hest_generic *generic) | 94 | static struct ghes *ghes_new(struct acpi_hest_generic *generic) |
92 | { | 95 | { |
@@ -132,26 +135,26 @@ static void ghes_fini(struct ghes *ghes) | |||
132 | } | 135 | } |
133 | 136 | ||
134 | enum { | 137 | enum { |
135 | GHES_SER_NO = 0x0, | 138 | GHES_SEV_NO = 0x0, |
136 | GHES_SER_CORRECTED = 0x1, | 139 | GHES_SEV_CORRECTED = 0x1, |
137 | GHES_SER_RECOVERABLE = 0x2, | 140 | GHES_SEV_RECOVERABLE = 0x2, |
138 | GHES_SER_PANIC = 0x3, | 141 | GHES_SEV_PANIC = 0x3, |
139 | }; | 142 | }; |
140 | 143 | ||
141 | static inline int ghes_severity(int severity) | 144 | static inline int ghes_severity(int severity) |
142 | { | 145 | { |
143 | switch (severity) { | 146 | switch (severity) { |
144 | case CPER_SER_INFORMATIONAL: | 147 | case CPER_SEV_INFORMATIONAL: |
145 | return GHES_SER_NO; | 148 | return GHES_SEV_NO; |
146 | case CPER_SER_CORRECTED: | 149 | case CPER_SEV_CORRECTED: |
147 | return GHES_SER_CORRECTED; | 150 | return GHES_SEV_CORRECTED; |
148 | case CPER_SER_RECOVERABLE: | 151 | case CPER_SEV_RECOVERABLE: |
149 | return GHES_SER_RECOVERABLE; | 152 | return GHES_SEV_RECOVERABLE; |
150 | case CPER_SER_FATAL: | 153 | case CPER_SEV_FATAL: |
151 | return GHES_SER_PANIC; | 154 | return GHES_SEV_PANIC; |
152 | default: | 155 | default: |
153 | /* Unkown, go panic */ | 156 | /* Unkown, go panic */ |
154 | return GHES_SER_PANIC; | 157 | return GHES_SEV_PANIC; |
155 | } | 158 | } |
156 | } | 159 | } |
157 | 160 | ||
@@ -237,16 +240,16 @@ static void ghes_clear_estatus(struct ghes *ghes) | |||
237 | 240 | ||
238 | static void ghes_do_proc(struct ghes *ghes) | 241 | static void ghes_do_proc(struct ghes *ghes) |
239 | { | 242 | { |
240 | int ser, processed = 0; | 243 | int sev, processed = 0; |
241 | struct acpi_hest_generic_data *gdata; | 244 | struct acpi_hest_generic_data *gdata; |
242 | 245 | ||
243 | ser = ghes_severity(ghes->estatus->error_severity); | 246 | sev = ghes_severity(ghes->estatus->error_severity); |
244 | apei_estatus_for_each_section(ghes->estatus, gdata) { | 247 | apei_estatus_for_each_section(ghes->estatus, gdata) { |
245 | #ifdef CONFIG_X86_MCE | 248 | #ifdef CONFIG_X86_MCE |
246 | if (!uuid_le_cmp(*(uuid_le *)gdata->section_type, | 249 | if (!uuid_le_cmp(*(uuid_le *)gdata->section_type, |
247 | CPER_SEC_PLATFORM_MEM)) { | 250 | CPER_SEC_PLATFORM_MEM)) { |
248 | apei_mce_report_mem_error( | 251 | apei_mce_report_mem_error( |
249 | ser == GHES_SER_CORRECTED, | 252 | sev == GHES_SEV_CORRECTED, |
250 | (struct cper_sec_mem_err *)(gdata+1)); | 253 | (struct cper_sec_mem_err *)(gdata+1)); |
251 | processed = 1; | 254 | processed = 1; |
252 | } | 255 | } |
@@ -293,18 +296,15 @@ static struct notifier_block ghes_notifier_sci = { | |||
293 | .notifier_call = ghes_notify_sci, | 296 | .notifier_call = ghes_notify_sci, |
294 | }; | 297 | }; |
295 | 298 | ||
296 | static int hest_ghes_parse(struct acpi_hest_header *hest_hdr, void *data) | 299 | static int __devinit ghes_probe(struct platform_device *ghes_dev) |
297 | { | 300 | { |
298 | struct acpi_hest_generic *generic; | 301 | struct acpi_hest_generic *generic; |
299 | struct ghes *ghes = NULL; | 302 | struct ghes *ghes = NULL; |
300 | int rc = 0; | 303 | int rc = -EINVAL; |
301 | 304 | ||
302 | if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR) | 305 | generic = ghes_dev->dev.platform_data; |
303 | return 0; | ||
304 | |||
305 | generic = (struct acpi_hest_generic *)hest_hdr; | ||
306 | if (!generic->enabled) | 306 | if (!generic->enabled) |
307 | return 0; | 307 | return -ENODEV; |
308 | 308 | ||
309 | if (generic->error_block_length < | 309 | if (generic->error_block_length < |
310 | sizeof(struct acpi_hest_generic_status)) { | 310 | sizeof(struct acpi_hest_generic_status)) { |
@@ -327,62 +327,91 @@ static int hest_ghes_parse(struct acpi_hest_header *hest_hdr, void *data) | |||
327 | ghes = NULL; | 327 | ghes = NULL; |
328 | goto err; | 328 | goto err; |
329 | } | 329 | } |
330 | switch (generic->notify.type) { | 330 | if (generic->notify.type == ACPI_HEST_NOTIFY_SCI) { |
331 | case ACPI_HEST_NOTIFY_POLLED: | 331 | mutex_lock(&ghes_list_mutex); |
332 | pr_warning(GHES_PFX | ||
333 | "Generic hardware error source: %d notified via POLL is not supported!\n", | ||
334 | generic->header.source_id); | ||
335 | break; | ||
336 | case ACPI_HEST_NOTIFY_EXTERNAL: | ||
337 | case ACPI_HEST_NOTIFY_LOCAL: | ||
338 | pr_warning(GHES_PFX | ||
339 | "Generic hardware error source: %d notified via IRQ is not supported!\n", | ||
340 | generic->header.source_id); | ||
341 | break; | ||
342 | case ACPI_HEST_NOTIFY_SCI: | ||
343 | if (list_empty(&ghes_sci)) | 332 | if (list_empty(&ghes_sci)) |
344 | register_acpi_hed_notifier(&ghes_notifier_sci); | 333 | register_acpi_hed_notifier(&ghes_notifier_sci); |
345 | list_add_rcu(&ghes->list, &ghes_sci); | 334 | list_add_rcu(&ghes->list, &ghes_sci); |
346 | break; | 335 | mutex_unlock(&ghes_list_mutex); |
347 | case ACPI_HEST_NOTIFY_NMI: | 336 | } else { |
348 | pr_warning(GHES_PFX | 337 | unsigned char *notify = NULL; |
349 | "Generic hardware error source: %d notified via NMI is not supported!\n", | 338 | |
350 | generic->header.source_id); | 339 | switch (generic->notify.type) { |
351 | break; | 340 | case ACPI_HEST_NOTIFY_POLLED: |
352 | default: | 341 | notify = "POLL"; |
353 | pr_warning(FW_WARN GHES_PFX | 342 | break; |
354 | "Unknown notification type: %u for generic hardware error source: %d\n", | 343 | case ACPI_HEST_NOTIFY_EXTERNAL: |
355 | generic->notify.type, generic->header.source_id); | 344 | case ACPI_HEST_NOTIFY_LOCAL: |
356 | break; | 345 | notify = "IRQ"; |
346 | break; | ||
347 | case ACPI_HEST_NOTIFY_NMI: | ||
348 | notify = "NMI"; | ||
349 | break; | ||
350 | } | ||
351 | if (notify) { | ||
352 | pr_warning(GHES_PFX | ||
353 | "Generic hardware error source: %d notified via %s is not supported!\n", | ||
354 | generic->header.source_id, notify); | ||
355 | } else { | ||
356 | pr_warning(FW_WARN GHES_PFX | ||
357 | "Unknown notification type: %u for generic hardware error source: %d\n", | ||
358 | generic->notify.type, generic->header.source_id); | ||
359 | } | ||
360 | rc = -ENODEV; | ||
361 | goto err; | ||
357 | } | 362 | } |
363 | platform_set_drvdata(ghes_dev, ghes); | ||
358 | 364 | ||
359 | return 0; | 365 | return 0; |
360 | err: | 366 | err: |
361 | if (ghes) | 367 | if (ghes) { |
362 | ghes_fini(ghes); | 368 | ghes_fini(ghes); |
369 | kfree(ghes); | ||
370 | } | ||
363 | return rc; | 371 | return rc; |
364 | } | 372 | } |
365 | 373 | ||
366 | static void ghes_cleanup(void) | 374 | static int __devexit ghes_remove(struct platform_device *ghes_dev) |
367 | { | 375 | { |
368 | struct ghes *ghes, *nghes; | 376 | struct ghes *ghes; |
377 | struct acpi_hest_generic *generic; | ||
369 | 378 | ||
370 | if (!list_empty(&ghes_sci)) | 379 | ghes = platform_get_drvdata(ghes_dev); |
371 | unregister_acpi_hed_notifier(&ghes_notifier_sci); | 380 | generic = ghes->generic; |
381 | |||
382 | switch (generic->notify.type) { | ||
383 | case ACPI_HEST_NOTIFY_SCI: | ||
384 | mutex_lock(&ghes_list_mutex); | ||
385 | list_del_rcu(&ghes->list); | ||
386 | if (list_empty(&ghes_sci)) | ||
387 | unregister_acpi_hed_notifier(&ghes_notifier_sci); | ||
388 | mutex_unlock(&ghes_list_mutex); | ||
389 | break; | ||
390 | default: | ||
391 | BUG(); | ||
392 | break; | ||
393 | } | ||
372 | 394 | ||
373 | synchronize_rcu(); | 395 | synchronize_rcu(); |
396 | ghes_fini(ghes); | ||
397 | kfree(ghes); | ||
374 | 398 | ||
375 | list_for_each_entry_safe(ghes, nghes, &ghes_sci, list) { | 399 | platform_set_drvdata(ghes_dev, NULL); |
376 | list_del(&ghes->list); | 400 | |
377 | ghes_fini(ghes); | 401 | return 0; |
378 | kfree(ghes); | ||
379 | } | ||
380 | } | 402 | } |
381 | 403 | ||
404 | static struct platform_driver ghes_platform_driver = { | ||
405 | .driver = { | ||
406 | .name = "GHES", | ||
407 | .owner = THIS_MODULE, | ||
408 | }, | ||
409 | .probe = ghes_probe, | ||
410 | .remove = ghes_remove, | ||
411 | }; | ||
412 | |||
382 | static int __init ghes_init(void) | 413 | static int __init ghes_init(void) |
383 | { | 414 | { |
384 | int rc; | ||
385 | |||
386 | if (acpi_disabled) | 415 | if (acpi_disabled) |
387 | return -ENODEV; | 416 | return -ENODEV; |
388 | 417 | ||
@@ -391,32 +420,12 @@ static int __init ghes_init(void) | |||
391 | return -EINVAL; | 420 | return -EINVAL; |
392 | } | 421 | } |
393 | 422 | ||
394 | rc = apei_hest_parse(hest_ghes_parse, NULL); | 423 | return platform_driver_register(&ghes_platform_driver); |
395 | if (rc) { | ||
396 | pr_err(GHES_PFX | ||
397 | "Error during parsing HEST generic hardware error sources.\n"); | ||
398 | goto err_cleanup; | ||
399 | } | ||
400 | |||
401 | if (list_empty(&ghes_sci)) { | ||
402 | pr_info(GHES_PFX | ||
403 | "No functional generic hardware error sources.\n"); | ||
404 | rc = -ENODEV; | ||
405 | goto err_cleanup; | ||
406 | } | ||
407 | |||
408 | pr_info(GHES_PFX | ||
409 | "Generic Hardware Error Source support is initialized.\n"); | ||
410 | |||
411 | return 0; | ||
412 | err_cleanup: | ||
413 | ghes_cleanup(); | ||
414 | return rc; | ||
415 | } | 424 | } |
416 | 425 | ||
417 | static void __exit ghes_exit(void) | 426 | static void __exit ghes_exit(void) |
418 | { | 427 | { |
419 | ghes_cleanup(); | 428 | platform_driver_unregister(&ghes_platform_driver); |
420 | } | 429 | } |
421 | 430 | ||
422 | module_init(ghes_init); | 431 | module_init(ghes_init); |
@@ -425,3 +434,4 @@ module_exit(ghes_exit); | |||
425 | MODULE_AUTHOR("Huang Ying"); | 434 | MODULE_AUTHOR("Huang Ying"); |
426 | MODULE_DESCRIPTION("APEI Generic Hardware Error Source support"); | 435 | MODULE_DESCRIPTION("APEI Generic Hardware Error Source support"); |
427 | MODULE_LICENSE("GPL"); | 436 | MODULE_LICENSE("GPL"); |
437 | MODULE_ALIAS("platform:GHES"); | ||
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index e7f40d362cb3..343168d18266 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/kdebug.h> | 34 | #include <linux/kdebug.h> |
35 | #include <linux/highmem.h> | 35 | #include <linux/highmem.h> |
36 | #include <linux/io.h> | 36 | #include <linux/io.h> |
37 | #include <linux/platform_device.h> | ||
37 | #include <acpi/apei.h> | 38 | #include <acpi/apei.h> |
38 | 39 | ||
39 | #include "apei-internal.h" | 40 | #include "apei-internal.h" |
@@ -47,11 +48,6 @@ EXPORT_SYMBOL_GPL(hest_disable); | |||
47 | 48 | ||
48 | static struct acpi_table_hest *hest_tab; | 49 | static struct acpi_table_hest *hest_tab; |
49 | 50 | ||
50 | static int hest_void_parse(struct acpi_hest_header *hest_hdr, void *data) | ||
51 | { | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = { | 51 | static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = { |
56 | [ACPI_HEST_TYPE_IA32_CHECK] = -1, /* need further calculation */ | 52 | [ACPI_HEST_TYPE_IA32_CHECK] = -1, /* need further calculation */ |
57 | [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1, | 53 | [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1, |
@@ -125,6 +121,69 @@ int apei_hest_parse(apei_hest_func_t func, void *data) | |||
125 | } | 121 | } |
126 | EXPORT_SYMBOL_GPL(apei_hest_parse); | 122 | EXPORT_SYMBOL_GPL(apei_hest_parse); |
127 | 123 | ||
124 | struct ghes_arr { | ||
125 | struct platform_device **ghes_devs; | ||
126 | unsigned int count; | ||
127 | }; | ||
128 | |||
129 | static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data) | ||
130 | { | ||
131 | int *count = data; | ||
132 | |||
133 | if (hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR) | ||
134 | (*count)++; | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data) | ||
139 | { | ||
140 | struct acpi_hest_generic *generic; | ||
141 | struct platform_device *ghes_dev; | ||
142 | struct ghes_arr *ghes_arr = data; | ||
143 | int rc; | ||
144 | |||
145 | if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR) | ||
146 | return 0; | ||
147 | generic = (struct acpi_hest_generic *)hest_hdr; | ||
148 | if (!generic->enabled) | ||
149 | return 0; | ||
150 | ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id); | ||
151 | if (!ghes_dev) | ||
152 | return -ENOMEM; | ||
153 | ghes_dev->dev.platform_data = generic; | ||
154 | rc = platform_device_add(ghes_dev); | ||
155 | if (rc) | ||
156 | goto err; | ||
157 | ghes_arr->ghes_devs[ghes_arr->count++] = ghes_dev; | ||
158 | |||
159 | return 0; | ||
160 | err: | ||
161 | platform_device_put(ghes_dev); | ||
162 | return rc; | ||
163 | } | ||
164 | |||
165 | static int hest_ghes_dev_register(unsigned int ghes_count) | ||
166 | { | ||
167 | int rc, i; | ||
168 | struct ghes_arr ghes_arr; | ||
169 | |||
170 | ghes_arr.count = 0; | ||
171 | ghes_arr.ghes_devs = kmalloc(sizeof(void *) * ghes_count, GFP_KERNEL); | ||
172 | if (!ghes_arr.ghes_devs) | ||
173 | return -ENOMEM; | ||
174 | |||
175 | rc = apei_hest_parse(hest_parse_ghes, &ghes_arr); | ||
176 | if (rc) | ||
177 | goto err; | ||
178 | out: | ||
179 | kfree(ghes_arr.ghes_devs); | ||
180 | return rc; | ||
181 | err: | ||
182 | for (i = 0; i < ghes_arr.count; i++) | ||
183 | platform_device_unregister(ghes_arr.ghes_devs[i]); | ||
184 | goto out; | ||
185 | } | ||
186 | |||
128 | static int __init setup_hest_disable(char *str) | 187 | static int __init setup_hest_disable(char *str) |
129 | { | 188 | { |
130 | hest_disable = 1; | 189 | hest_disable = 1; |
@@ -137,6 +196,7 @@ static int __init hest_init(void) | |||
137 | { | 196 | { |
138 | acpi_status status; | 197 | acpi_status status; |
139 | int rc = -ENODEV; | 198 | int rc = -ENODEV; |
199 | unsigned int ghes_count = 0; | ||
140 | 200 | ||
141 | if (acpi_disabled) | 201 | if (acpi_disabled) |
142 | goto err; | 202 | goto err; |
@@ -158,7 +218,11 @@ static int __init hest_init(void) | |||
158 | goto err; | 218 | goto err; |
159 | } | 219 | } |
160 | 220 | ||
161 | rc = apei_hest_parse(hest_void_parse, NULL); | 221 | rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count); |
222 | if (rc) | ||
223 | goto err; | ||
224 | |||
225 | rc = hest_ghes_dev_register(ghes_count); | ||
162 | if (rc) | 226 | if (rc) |
163 | goto err; | 227 | goto err; |
164 | 228 | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c1d23cd71652..5c221ab535d5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -1034,8 +1034,8 @@ static int __init acpi_init(void) | |||
1034 | acpi_scan_init(); | 1034 | acpi_scan_init(); |
1035 | acpi_ec_init(); | 1035 | acpi_ec_init(); |
1036 | acpi_power_init(); | 1036 | acpi_power_init(); |
1037 | acpi_system_init(); | 1037 | acpi_sysfs_init(); |
1038 | acpi_debug_init(); | 1038 | acpi_debugfs_init(); |
1039 | acpi_sleep_proc_init(); | 1039 | acpi_sleep_proc_init(); |
1040 | acpi_wakeup_device_init(); | 1040 | acpi_wakeup_device_init(); |
1041 | return result; | 1041 | return result; |
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c deleted file mode 100644 index 295dbfa2db9c..000000000000 --- a/drivers/acpi/debug.c +++ /dev/null | |||
@@ -1,422 +0,0 @@ | |||
1 | /* | ||
2 | * debug.c - ACPI debug interface to userspace. | ||
3 | */ | ||
4 | |||
5 | #include <linux/proc_fs.h> | ||
6 | #include <linux/seq_file.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/moduleparam.h> | ||
11 | #include <linux/debugfs.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <asm/uaccess.h> | ||
14 | #include <acpi/acpi_drivers.h> | ||
15 | |||
16 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | ||
17 | ACPI_MODULE_NAME("debug"); | ||
18 | |||
19 | struct acpi_dlayer { | ||
20 | const char *name; | ||
21 | unsigned long value; | ||
22 | }; | ||
23 | struct acpi_dlevel { | ||
24 | const char *name; | ||
25 | unsigned long value; | ||
26 | }; | ||
27 | #define ACPI_DEBUG_INIT(v) { .name = #v, .value = v } | ||
28 | |||
29 | static const struct acpi_dlayer acpi_debug_layers[] = { | ||
30 | ACPI_DEBUG_INIT(ACPI_UTILITIES), | ||
31 | ACPI_DEBUG_INIT(ACPI_HARDWARE), | ||
32 | ACPI_DEBUG_INIT(ACPI_EVENTS), | ||
33 | ACPI_DEBUG_INIT(ACPI_TABLES), | ||
34 | ACPI_DEBUG_INIT(ACPI_NAMESPACE), | ||
35 | ACPI_DEBUG_INIT(ACPI_PARSER), | ||
36 | ACPI_DEBUG_INIT(ACPI_DISPATCHER), | ||
37 | ACPI_DEBUG_INIT(ACPI_EXECUTER), | ||
38 | ACPI_DEBUG_INIT(ACPI_RESOURCES), | ||
39 | ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER), | ||
40 | ACPI_DEBUG_INIT(ACPI_OS_SERVICES), | ||
41 | ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), | ||
42 | ACPI_DEBUG_INIT(ACPI_COMPILER), | ||
43 | ACPI_DEBUG_INIT(ACPI_TOOLS), | ||
44 | |||
45 | ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), | ||
46 | ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), | ||
47 | ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), | ||
48 | ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), | ||
49 | ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), | ||
50 | ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), | ||
51 | ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), | ||
52 | ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), | ||
53 | ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), | ||
54 | ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), | ||
55 | ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), | ||
56 | ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), | ||
57 | ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), | ||
58 | ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), | ||
59 | }; | ||
60 | |||
61 | static const struct acpi_dlevel acpi_debug_levels[] = { | ||
62 | ACPI_DEBUG_INIT(ACPI_LV_INIT), | ||
63 | ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), | ||
64 | ACPI_DEBUG_INIT(ACPI_LV_INFO), | ||
65 | |||
66 | ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES), | ||
67 | ACPI_DEBUG_INIT(ACPI_LV_PARSE), | ||
68 | ACPI_DEBUG_INIT(ACPI_LV_LOAD), | ||
69 | ACPI_DEBUG_INIT(ACPI_LV_DISPATCH), | ||
70 | ACPI_DEBUG_INIT(ACPI_LV_EXEC), | ||
71 | ACPI_DEBUG_INIT(ACPI_LV_NAMES), | ||
72 | ACPI_DEBUG_INIT(ACPI_LV_OPREGION), | ||
73 | ACPI_DEBUG_INIT(ACPI_LV_BFIELD), | ||
74 | ACPI_DEBUG_INIT(ACPI_LV_TABLES), | ||
75 | ACPI_DEBUG_INIT(ACPI_LV_VALUES), | ||
76 | ACPI_DEBUG_INIT(ACPI_LV_OBJECTS), | ||
77 | ACPI_DEBUG_INIT(ACPI_LV_RESOURCES), | ||
78 | ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS), | ||
79 | ACPI_DEBUG_INIT(ACPI_LV_PACKAGE), | ||
80 | |||
81 | ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS), | ||
82 | ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS), | ||
83 | ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS), | ||
84 | |||
85 | ACPI_DEBUG_INIT(ACPI_LV_MUTEX), | ||
86 | ACPI_DEBUG_INIT(ACPI_LV_THREADS), | ||
87 | ACPI_DEBUG_INIT(ACPI_LV_IO), | ||
88 | ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS), | ||
89 | |||
90 | ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE), | ||
91 | ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO), | ||
92 | ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES), | ||
93 | ACPI_DEBUG_INIT(ACPI_LV_EVENTS), | ||
94 | }; | ||
95 | |||
96 | /* -------------------------------------------------------------------------- | ||
97 | FS Interface (/sys) | ||
98 | -------------------------------------------------------------------------- */ | ||
99 | static int param_get_debug_layer(char *buffer, const struct kernel_param *kp) | ||
100 | { | ||
101 | int result = 0; | ||
102 | int i; | ||
103 | |||
104 | result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); | ||
105 | |||
106 | for(i = 0; i <ARRAY_SIZE(acpi_debug_layers); i++) { | ||
107 | result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n", | ||
108 | acpi_debug_layers[i].name, | ||
109 | acpi_debug_layers[i].value, | ||
110 | (acpi_dbg_layer & acpi_debug_layers[i].value) ? '*' : ' '); | ||
111 | } | ||
112 | result += sprintf(buffer+result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", | ||
113 | ACPI_ALL_DRIVERS, | ||
114 | (acpi_dbg_layer & ACPI_ALL_DRIVERS) == | ||
115 | ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & | ||
116 | ACPI_ALL_DRIVERS) == 0 ? ' ' : '-'); | ||
117 | result += sprintf(buffer+result, "--\ndebug_layer = 0x%08X ( * = enabled)\n", acpi_dbg_layer); | ||
118 | |||
119 | return result; | ||
120 | } | ||
121 | |||
122 | static int param_get_debug_level(char *buffer, const struct kernel_param *kp) | ||
123 | { | ||
124 | int result = 0; | ||
125 | int i; | ||
126 | |||
127 | result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); | ||
128 | |||
129 | for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { | ||
130 | result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n", | ||
131 | acpi_debug_levels[i].name, | ||
132 | acpi_debug_levels[i].value, | ||
133 | (acpi_dbg_level & acpi_debug_levels[i]. | ||
134 | value) ? '*' : ' '); | ||
135 | } | ||
136 | result += sprintf(buffer+result, "--\ndebug_level = 0x%08X (* = enabled)\n", | ||
137 | acpi_dbg_level); | ||
138 | |||
139 | return result; | ||
140 | } | ||
141 | |||
142 | static struct kernel_param_ops acpi_debug_layer_ops = { | ||
143 | .set = param_set_uint, | ||
144 | .get = param_get_debug_layer, | ||
145 | }; | ||
146 | |||
147 | static struct kernel_param_ops acpi_debug_level_ops = { | ||
148 | .set = param_set_uint, | ||
149 | .get = param_get_debug_level, | ||
150 | }; | ||
151 | |||
152 | module_param_cb(debug_layer, &acpi_debug_layer_ops, &acpi_dbg_layer, 0644); | ||
153 | module_param_cb(debug_level, &acpi_debug_level_ops, &acpi_dbg_level, 0644); | ||
154 | |||
155 | static char trace_method_name[6]; | ||
156 | module_param_string(trace_method_name, trace_method_name, 6, 0644); | ||
157 | static unsigned int trace_debug_layer; | ||
158 | module_param(trace_debug_layer, uint, 0644); | ||
159 | static unsigned int trace_debug_level; | ||
160 | module_param(trace_debug_level, uint, 0644); | ||
161 | |||
162 | static int param_set_trace_state(const char *val, const struct kernel_param *kp) | ||
163 | { | ||
164 | int result = 0; | ||
165 | |||
166 | if (!strncmp(val, "enable", strlen("enable") - 1)) { | ||
167 | result = acpi_debug_trace(trace_method_name, trace_debug_level, | ||
168 | trace_debug_layer, 0); | ||
169 | if (result) | ||
170 | result = -EBUSY; | ||
171 | goto exit; | ||
172 | } | ||
173 | |||
174 | if (!strncmp(val, "disable", strlen("disable") - 1)) { | ||
175 | int name = 0; | ||
176 | result = acpi_debug_trace((char *)&name, trace_debug_level, | ||
177 | trace_debug_layer, 0); | ||
178 | if (result) | ||
179 | result = -EBUSY; | ||
180 | goto exit; | ||
181 | } | ||
182 | |||
183 | if (!strncmp(val, "1", 1)) { | ||
184 | result = acpi_debug_trace(trace_method_name, trace_debug_level, | ||
185 | trace_debug_layer, 1); | ||
186 | if (result) | ||
187 | result = -EBUSY; | ||
188 | goto exit; | ||
189 | } | ||
190 | |||
191 | result = -EINVAL; | ||
192 | exit: | ||
193 | return result; | ||
194 | } | ||
195 | |||
196 | static int param_get_trace_state(char *buffer, const struct kernel_param *kp) | ||
197 | { | ||
198 | if (!acpi_gbl_trace_method_name) | ||
199 | return sprintf(buffer, "disable"); | ||
200 | else { | ||
201 | if (acpi_gbl_trace_flags & 1) | ||
202 | return sprintf(buffer, "1"); | ||
203 | else | ||
204 | return sprintf(buffer, "enable"); | ||
205 | } | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static struct kernel_param_ops param_ops_trace_state = { | ||
210 | .set = param_set_trace_state, | ||
211 | .get = param_get_trace_state, | ||
212 | }; | ||
213 | |||
214 | module_param_cb(trace_state, ¶m_ops_trace_state, NULL, 0644); | ||
215 | |||
216 | /* -------------------------------------------------------------------------- | ||
217 | DebugFS Interface | ||
218 | -------------------------------------------------------------------------- */ | ||
219 | |||
220 | static ssize_t cm_write(struct file *file, const char __user *user_buf, | ||
221 | size_t count, loff_t *ppos) | ||
222 | { | ||
223 | static char *buf; | ||
224 | static int uncopied_bytes; | ||
225 | struct acpi_table_header table; | ||
226 | acpi_status status; | ||
227 | |||
228 | if (!(*ppos)) { | ||
229 | /* parse the table header to get the table length */ | ||
230 | if (count <= sizeof(struct acpi_table_header)) | ||
231 | return -EINVAL; | ||
232 | if (copy_from_user(&table, user_buf, | ||
233 | sizeof(struct acpi_table_header))) | ||
234 | return -EFAULT; | ||
235 | uncopied_bytes = table.length; | ||
236 | buf = kzalloc(uncopied_bytes, GFP_KERNEL); | ||
237 | if (!buf) | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | |||
241 | if (uncopied_bytes < count) { | ||
242 | kfree(buf); | ||
243 | return -EINVAL; | ||
244 | } | ||
245 | |||
246 | if (copy_from_user(buf + (*ppos), user_buf, count)) { | ||
247 | kfree(buf); | ||
248 | return -EFAULT; | ||
249 | } | ||
250 | |||
251 | uncopied_bytes -= count; | ||
252 | *ppos += count; | ||
253 | |||
254 | if (!uncopied_bytes) { | ||
255 | status = acpi_install_method(buf); | ||
256 | kfree(buf); | ||
257 | if (ACPI_FAILURE(status)) | ||
258 | return -EINVAL; | ||
259 | add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); | ||
260 | } | ||
261 | |||
262 | return count; | ||
263 | } | ||
264 | |||
265 | static const struct file_operations cm_fops = { | ||
266 | .write = cm_write, | ||
267 | }; | ||
268 | |||
269 | static int acpi_debugfs_init(void) | ||
270 | { | ||
271 | struct dentry *acpi_dir, *cm_dentry; | ||
272 | |||
273 | acpi_dir = debugfs_create_dir("acpi", NULL); | ||
274 | if (!acpi_dir) | ||
275 | goto err; | ||
276 | |||
277 | cm_dentry = debugfs_create_file("custom_method", S_IWUGO, | ||
278 | acpi_dir, NULL, &cm_fops); | ||
279 | if (!cm_dentry) | ||
280 | goto err; | ||
281 | |||
282 | return 0; | ||
283 | |||
284 | err: | ||
285 | if (acpi_dir) | ||
286 | debugfs_remove(acpi_dir); | ||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
290 | /* -------------------------------------------------------------------------- | ||
291 | FS Interface (/proc) | ||
292 | -------------------------------------------------------------------------- */ | ||
293 | #ifdef CONFIG_ACPI_PROCFS | ||
294 | #define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" | ||
295 | #define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" | ||
296 | |||
297 | static int acpi_system_debug_proc_show(struct seq_file *m, void *v) | ||
298 | { | ||
299 | unsigned int i; | ||
300 | |||
301 | seq_printf(m, "%-25s\tHex SET\n", "Description"); | ||
302 | |||
303 | switch ((unsigned long)m->private) { | ||
304 | case 0: | ||
305 | for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) { | ||
306 | seq_printf(m, "%-25s\t0x%08lX [%c]\n", | ||
307 | acpi_debug_layers[i].name, | ||
308 | acpi_debug_layers[i].value, | ||
309 | (acpi_dbg_layer & acpi_debug_layers[i]. | ||
310 | value) ? '*' : ' '); | ||
311 | } | ||
312 | seq_printf(m, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", | ||
313 | ACPI_ALL_DRIVERS, | ||
314 | (acpi_dbg_layer & ACPI_ALL_DRIVERS) == | ||
315 | ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & | ||
316 | ACPI_ALL_DRIVERS) == | ||
317 | 0 ? ' ' : '-'); | ||
318 | seq_printf(m, | ||
319 | "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n", | ||
320 | acpi_dbg_layer); | ||
321 | break; | ||
322 | case 1: | ||
323 | for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { | ||
324 | seq_printf(m, "%-25s\t0x%08lX [%c]\n", | ||
325 | acpi_debug_levels[i].name, | ||
326 | acpi_debug_levels[i].value, | ||
327 | (acpi_dbg_level & acpi_debug_levels[i]. | ||
328 | value) ? '*' : ' '); | ||
329 | } | ||
330 | seq_printf(m, "--\ndebug_level = 0x%08X (* = enabled)\n", | ||
331 | acpi_dbg_level); | ||
332 | break; | ||
333 | } | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static int acpi_system_debug_proc_open(struct inode *inode, struct file *file) | ||
338 | { | ||
339 | return single_open(file, acpi_system_debug_proc_show, PDE(inode)->data); | ||
340 | } | ||
341 | |||
342 | static ssize_t acpi_system_debug_proc_write(struct file *file, | ||
343 | const char __user * buffer, | ||
344 | size_t count, loff_t *pos) | ||
345 | { | ||
346 | char debug_string[12] = { '\0' }; | ||
347 | |||
348 | |||
349 | if (count > sizeof(debug_string) - 1) | ||
350 | return -EINVAL; | ||
351 | |||
352 | if (copy_from_user(debug_string, buffer, count)) | ||
353 | return -EFAULT; | ||
354 | |||
355 | debug_string[count] = '\0'; | ||
356 | |||
357 | switch ((unsigned long)PDE(file->f_path.dentry->d_inode)->data) { | ||
358 | case 0: | ||
359 | acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0); | ||
360 | break; | ||
361 | case 1: | ||
362 | acpi_dbg_level = simple_strtoul(debug_string, NULL, 0); | ||
363 | break; | ||
364 | default: | ||
365 | return -EINVAL; | ||
366 | } | ||
367 | |||
368 | return count; | ||
369 | } | ||
370 | |||
371 | static const struct file_operations acpi_system_debug_proc_fops = { | ||
372 | .owner = THIS_MODULE, | ||
373 | .open = acpi_system_debug_proc_open, | ||
374 | .read = seq_read, | ||
375 | .llseek = seq_lseek, | ||
376 | .release = single_release, | ||
377 | .write = acpi_system_debug_proc_write, | ||
378 | }; | ||
379 | #endif | ||
380 | |||
381 | int __init acpi_procfs_init(void) | ||
382 | { | ||
383 | #ifdef CONFIG_ACPI_PROCFS | ||
384 | struct proc_dir_entry *entry; | ||
385 | int error = 0; | ||
386 | char *name; | ||
387 | |||
388 | /* 'debug_layer' [R/W] */ | ||
389 | name = ACPI_SYSTEM_FILE_DEBUG_LAYER; | ||
390 | entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, | ||
391 | acpi_root_dir, &acpi_system_debug_proc_fops, | ||
392 | (void *)0); | ||
393 | if (!entry) | ||
394 | goto Error; | ||
395 | |||
396 | /* 'debug_level' [R/W] */ | ||
397 | name = ACPI_SYSTEM_FILE_DEBUG_LEVEL; | ||
398 | entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, | ||
399 | acpi_root_dir, &acpi_system_debug_proc_fops, | ||
400 | (void *)1); | ||
401 | if (!entry) | ||
402 | goto Error; | ||
403 | |||
404 | Done: | ||
405 | return error; | ||
406 | |||
407 | Error: | ||
408 | remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, acpi_root_dir); | ||
409 | remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir); | ||
410 | error = -ENODEV; | ||
411 | goto Done; | ||
412 | #else | ||
413 | return 0; | ||
414 | #endif | ||
415 | } | ||
416 | |||
417 | int __init acpi_debug_init(void) | ||
418 | { | ||
419 | acpi_debugfs_init(); | ||
420 | acpi_procfs_init(); | ||
421 | return 0; | ||
422 | } | ||
diff --git a/drivers/acpi/debugfs.c b/drivers/acpi/debugfs.c new file mode 100644 index 000000000000..7de27d49c4b9 --- /dev/null +++ b/drivers/acpi/debugfs.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * debugfs.c - ACPI debugfs interface to userspace. | ||
3 | */ | ||
4 | |||
5 | #include <linux/init.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/uaccess.h> | ||
9 | #include <linux/debugfs.h> | ||
10 | #include <acpi/acpi_drivers.h> | ||
11 | |||
12 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | ||
13 | ACPI_MODULE_NAME("debugfs"); | ||
14 | |||
15 | |||
16 | /* /sys/modules/acpi/parameters/aml_debug_output */ | ||
17 | |||
18 | module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object, | ||
19 | bool, 0644); | ||
20 | MODULE_PARM_DESC(aml_debug_output, | ||
21 | "To enable/disable the ACPI Debug Object output."); | ||
22 | |||
23 | /* /sys/kernel/debug/acpi/custom_method */ | ||
24 | |||
25 | static ssize_t cm_write(struct file *file, const char __user * user_buf, | ||
26 | size_t count, loff_t *ppos) | ||
27 | { | ||
28 | static char *buf; | ||
29 | static int uncopied_bytes; | ||
30 | struct acpi_table_header table; | ||
31 | acpi_status status; | ||
32 | |||
33 | if (!(*ppos)) { | ||
34 | /* parse the table header to get the table length */ | ||
35 | if (count <= sizeof(struct acpi_table_header)) | ||
36 | return -EINVAL; | ||
37 | if (copy_from_user(&table, user_buf, | ||
38 | sizeof(struct acpi_table_header))) | ||
39 | return -EFAULT; | ||
40 | uncopied_bytes = table.length; | ||
41 | buf = kzalloc(uncopied_bytes, GFP_KERNEL); | ||
42 | if (!buf) | ||
43 | return -ENOMEM; | ||
44 | } | ||
45 | |||
46 | if (uncopied_bytes < count) { | ||
47 | kfree(buf); | ||
48 | return -EINVAL; | ||
49 | } | ||
50 | |||
51 | if (copy_from_user(buf + (*ppos), user_buf, count)) { | ||
52 | kfree(buf); | ||
53 | return -EFAULT; | ||
54 | } | ||
55 | |||
56 | uncopied_bytes -= count; | ||
57 | *ppos += count; | ||
58 | |||
59 | if (!uncopied_bytes) { | ||
60 | status = acpi_install_method(buf); | ||
61 | kfree(buf); | ||
62 | if (ACPI_FAILURE(status)) | ||
63 | return -EINVAL; | ||
64 | add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); | ||
65 | } | ||
66 | |||
67 | return count; | ||
68 | } | ||
69 | |||
70 | static const struct file_operations cm_fops = { | ||
71 | .write = cm_write, | ||
72 | }; | ||
73 | |||
74 | int __init acpi_debugfs_init(void) | ||
75 | { | ||
76 | struct dentry *acpi_dir, *cm_dentry; | ||
77 | |||
78 | acpi_dir = debugfs_create_dir("acpi", NULL); | ||
79 | if (!acpi_dir) | ||
80 | goto err; | ||
81 | |||
82 | cm_dentry = debugfs_create_file("custom_method", S_IWUGO, | ||
83 | acpi_dir, NULL, &cm_fops); | ||
84 | if (!cm_dentry) | ||
85 | goto err; | ||
86 | |||
87 | return 0; | ||
88 | |||
89 | err: | ||
90 | if (acpi_dir) | ||
91 | debugfs_remove(acpi_dir); | ||
92 | return -EINVAL; | ||
93 | } | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 4af6301601e7..78b0164c35b2 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -100,7 +100,8 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
100 | 100 | ||
101 | status = acpi_get_object_info(handle, &info); | 101 | status = acpi_get_object_info(handle, &info); |
102 | if (ACPI_SUCCESS(status)) { | 102 | if (ACPI_SUCCESS(status)) { |
103 | if (info->address == find->address) | 103 | if ((info->address == find->address) |
104 | && (info->valid & ACPI_VALID_ADR)) | ||
104 | find->handle = handle; | 105 | find->handle = handle; |
105 | kfree(info); | 106 | kfree(info); |
106 | } | 107 | } |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 8ae27264a00e..a212bfeddf8c 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -27,12 +27,12 @@ | |||
27 | 27 | ||
28 | int init_acpi_device_notify(void); | 28 | int init_acpi_device_notify(void); |
29 | int acpi_scan_init(void); | 29 | int acpi_scan_init(void); |
30 | int acpi_system_init(void); | 30 | int acpi_sysfs_init(void); |
31 | 31 | ||
32 | #ifdef CONFIG_ACPI_DEBUG | 32 | #ifdef CONFIG_DEBUG_FS |
33 | int acpi_debug_init(void); | 33 | int acpi_debugfs_init(void); |
34 | #else | 34 | #else |
35 | static inline int acpi_debug_init(void) { return 0; } | 35 | static inline int acpi_debugfs_init(void) { return 0; } |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | /* -------------------------------------------------------------------------- | 38 | /* -------------------------------------------------------------------------- |
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index b0337d314604..5718566e00f9 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
@@ -255,12 +255,10 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header, | |||
255 | 255 | ||
256 | static int __init acpi_parse_srat(struct acpi_table_header *table) | 256 | static int __init acpi_parse_srat(struct acpi_table_header *table) |
257 | { | 257 | { |
258 | struct acpi_table_srat *srat; | ||
259 | |||
260 | if (!table) | 258 | if (!table) |
261 | return -EINVAL; | 259 | return -EINVAL; |
262 | 260 | ||
263 | srat = (struct acpi_table_srat *)table; | 261 | /* Real work done in acpi_table_parse_srat below. */ |
264 | 262 | ||
265 | return 0; | 263 | return 0; |
266 | } | 264 | } |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index f14d3f251d26..65b25a303b86 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -141,15 +141,14 @@ static struct osi_linux { | |||
141 | static void __init acpi_request_region (struct acpi_generic_address *addr, | 141 | static void __init acpi_request_region (struct acpi_generic_address *addr, |
142 | unsigned int length, char *desc) | 142 | unsigned int length, char *desc) |
143 | { | 143 | { |
144 | struct resource *res; | ||
145 | |||
146 | if (!addr->address || !length) | 144 | if (!addr->address || !length) |
147 | return; | 145 | return; |
148 | 146 | ||
147 | /* Resources are never freed */ | ||
149 | if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO) | 148 | if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO) |
150 | res = request_region(addr->address, length, desc); | 149 | request_region(addr->address, length, desc); |
151 | else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) | 150 | else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) |
152 | res = request_mem_region(addr->address, length, desc); | 151 | request_mem_region(addr->address, length, desc); |
153 | } | 152 | } |
154 | 153 | ||
155 | static int __init acpi_reserve_resources(void) | 154 | static int __init acpi_reserve_resources(void) |
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index f74d3b31e5c9..844c155aeb0f 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -40,8 +40,6 @@ | |||
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/types.h> | 41 | #include <linux/types.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/proc_fs.h> | ||
44 | #include <linux/seq_file.h> | ||
45 | #include <acpi/acpi_bus.h> | 43 | #include <acpi/acpi_bus.h> |
46 | #include <acpi/acpi_drivers.h> | 44 | #include <acpi/acpi_drivers.h> |
47 | #include "sleep.h" | 45 | #include "sleep.h" |
@@ -64,7 +62,6 @@ module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); | |||
64 | static int acpi_power_add(struct acpi_device *device); | 62 | static int acpi_power_add(struct acpi_device *device); |
65 | static int acpi_power_remove(struct acpi_device *device, int type); | 63 | static int acpi_power_remove(struct acpi_device *device, int type); |
66 | static int acpi_power_resume(struct acpi_device *device); | 64 | static int acpi_power_resume(struct acpi_device *device); |
67 | static int acpi_power_open_fs(struct inode *inode, struct file *file); | ||
68 | 65 | ||
69 | static const struct acpi_device_id power_device_ids[] = { | 66 | static const struct acpi_device_id power_device_ids[] = { |
70 | {ACPI_POWER_HID, 0}, | 67 | {ACPI_POWER_HID, 0}, |
@@ -99,14 +96,6 @@ struct acpi_power_resource { | |||
99 | 96 | ||
100 | static struct list_head acpi_power_resource_list; | 97 | static struct list_head acpi_power_resource_list; |
101 | 98 | ||
102 | static const struct file_operations acpi_power_fops = { | ||
103 | .owner = THIS_MODULE, | ||
104 | .open = acpi_power_open_fs, | ||
105 | .read = seq_read, | ||
106 | .llseek = seq_lseek, | ||
107 | .release = single_release, | ||
108 | }; | ||
109 | |||
110 | /* -------------------------------------------------------------------------- | 99 | /* -------------------------------------------------------------------------- |
111 | Power Resource Management | 100 | Power Resource Management |
112 | -------------------------------------------------------------------------- */ | 101 | -------------------------------------------------------------------------- */ |
@@ -255,7 +244,6 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | |||
255 | struct list_head *node, *next; | 244 | struct list_head *node, *next; |
256 | struct acpi_power_reference *ref; | 245 | struct acpi_power_reference *ref; |
257 | 246 | ||
258 | |||
259 | result = acpi_power_get_context(handle, &resource); | 247 | result = acpi_power_get_context(handle, &resource); |
260 | if (result) | 248 | if (result) |
261 | return result; | 249 | return result; |
@@ -542,102 +530,6 @@ int acpi_power_transition(struct acpi_device *device, int state) | |||
542 | } | 530 | } |
543 | 531 | ||
544 | /* -------------------------------------------------------------------------- | 532 | /* -------------------------------------------------------------------------- |
545 | FS Interface (/proc) | ||
546 | -------------------------------------------------------------------------- */ | ||
547 | |||
548 | static struct proc_dir_entry *acpi_power_dir; | ||
549 | |||
550 | static int acpi_power_seq_show(struct seq_file *seq, void *offset) | ||
551 | { | ||
552 | int count = 0; | ||
553 | int result = 0, state; | ||
554 | struct acpi_power_resource *resource = NULL; | ||
555 | struct list_head *node, *next; | ||
556 | struct acpi_power_reference *ref; | ||
557 | |||
558 | |||
559 | resource = seq->private; | ||
560 | |||
561 | if (!resource) | ||
562 | goto end; | ||
563 | |||
564 | result = acpi_power_get_state(resource->device->handle, &state); | ||
565 | if (result) | ||
566 | goto end; | ||
567 | |||
568 | seq_puts(seq, "state: "); | ||
569 | switch (state) { | ||
570 | case ACPI_POWER_RESOURCE_STATE_ON: | ||
571 | seq_puts(seq, "on\n"); | ||
572 | break; | ||
573 | case ACPI_POWER_RESOURCE_STATE_OFF: | ||
574 | seq_puts(seq, "off\n"); | ||
575 | break; | ||
576 | default: | ||
577 | seq_puts(seq, "unknown\n"); | ||
578 | break; | ||
579 | } | ||
580 | |||
581 | mutex_lock(&resource->resource_lock); | ||
582 | list_for_each_safe(node, next, &resource->reference) { | ||
583 | ref = container_of(node, struct acpi_power_reference, node); | ||
584 | count++; | ||
585 | } | ||
586 | mutex_unlock(&resource->resource_lock); | ||
587 | |||
588 | seq_printf(seq, "system level: S%d\n" | ||
589 | "order: %d\n" | ||
590 | "reference count: %d\n", | ||
591 | resource->system_level, | ||
592 | resource->order, count); | ||
593 | |||
594 | end: | ||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static int acpi_power_open_fs(struct inode *inode, struct file *file) | ||
599 | { | ||
600 | return single_open(file, acpi_power_seq_show, PDE(inode)->data); | ||
601 | } | ||
602 | |||
603 | static int acpi_power_add_fs(struct acpi_device *device) | ||
604 | { | ||
605 | struct proc_dir_entry *entry = NULL; | ||
606 | |||
607 | |||
608 | if (!device) | ||
609 | return -EINVAL; | ||
610 | |||
611 | if (!acpi_device_dir(device)) { | ||
612 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | ||
613 | acpi_power_dir); | ||
614 | if (!acpi_device_dir(device)) | ||
615 | return -ENODEV; | ||
616 | } | ||
617 | |||
618 | /* 'status' [R] */ | ||
619 | entry = proc_create_data(ACPI_POWER_FILE_STATUS, | ||
620 | S_IRUGO, acpi_device_dir(device), | ||
621 | &acpi_power_fops, acpi_driver_data(device)); | ||
622 | if (!entry) | ||
623 | return -EIO; | ||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | static int acpi_power_remove_fs(struct acpi_device *device) | ||
628 | { | ||
629 | |||
630 | if (acpi_device_dir(device)) { | ||
631 | remove_proc_entry(ACPI_POWER_FILE_STATUS, | ||
632 | acpi_device_dir(device)); | ||
633 | remove_proc_entry(acpi_device_bid(device), acpi_power_dir); | ||
634 | acpi_device_dir(device) = NULL; | ||
635 | } | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | /* -------------------------------------------------------------------------- | ||
641 | Driver Interface | 533 | Driver Interface |
642 | -------------------------------------------------------------------------- */ | 534 | -------------------------------------------------------------------------- */ |
643 | 535 | ||
@@ -690,10 +582,6 @@ static int acpi_power_add(struct acpi_device *device) | |||
690 | break; | 582 | break; |
691 | } | 583 | } |
692 | 584 | ||
693 | result = acpi_power_add_fs(device); | ||
694 | if (result) | ||
695 | goto end; | ||
696 | |||
697 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), | 585 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), |
698 | acpi_device_bid(device), state ? "on" : "off"); | 586 | acpi_device_bid(device), state ? "on" : "off"); |
699 | 587 | ||
@@ -715,8 +603,6 @@ static int acpi_power_remove(struct acpi_device *device, int type) | |||
715 | 603 | ||
716 | resource = acpi_driver_data(device); | 604 | resource = acpi_driver_data(device); |
717 | 605 | ||
718 | acpi_power_remove_fs(device); | ||
719 | |||
720 | mutex_lock(&resource->resource_lock); | 606 | mutex_lock(&resource->resource_lock); |
721 | list_for_each_safe(node, next, &resource->reference) { | 607 | list_for_each_safe(node, next, &resource->reference) { |
722 | struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node); | 608 | struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node); |
@@ -760,19 +646,6 @@ static int acpi_power_resume(struct acpi_device *device) | |||
760 | 646 | ||
761 | int __init acpi_power_init(void) | 647 | int __init acpi_power_init(void) |
762 | { | 648 | { |
763 | int result = 0; | ||
764 | |||
765 | INIT_LIST_HEAD(&acpi_power_resource_list); | 649 | INIT_LIST_HEAD(&acpi_power_resource_list); |
766 | 650 | return acpi_bus_register_driver(&acpi_power_driver); | |
767 | acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir); | ||
768 | if (!acpi_power_dir) | ||
769 | return -ENODEV; | ||
770 | |||
771 | result = acpi_bus_register_driver(&acpi_power_driver); | ||
772 | if (result < 0) { | ||
773 | remove_proc_entry(ACPI_POWER_CLASS, acpi_root_dir); | ||
774 | return -ENODEV; | ||
775 | } | ||
776 | |||
777 | return 0; | ||
778 | } | 651 | } |
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 1ac678d2c51c..afad67769db6 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c | |||
@@ -17,64 +17,11 @@ | |||
17 | 17 | ||
18 | /* | 18 | /* |
19 | * this file provides support for: | 19 | * this file provides support for: |
20 | * /proc/acpi/sleep | ||
21 | * /proc/acpi/alarm | 20 | * /proc/acpi/alarm |
22 | * /proc/acpi/wakeup | 21 | * /proc/acpi/wakeup |
23 | */ | 22 | */ |
24 | 23 | ||
25 | ACPI_MODULE_NAME("sleep") | 24 | ACPI_MODULE_NAME("sleep") |
26 | #ifdef CONFIG_ACPI_PROCFS | ||
27 | static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset) | ||
28 | { | ||
29 | int i; | ||
30 | |||
31 | for (i = 0; i <= ACPI_STATE_S5; i++) { | ||
32 | if (sleep_states[i]) { | ||
33 | seq_printf(seq, "S%d ", i); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | seq_puts(seq, "\n"); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file) | ||
43 | { | ||
44 | return single_open(file, acpi_system_sleep_seq_show, PDE(inode)->data); | ||
45 | } | ||
46 | |||
47 | static ssize_t | ||
48 | acpi_system_write_sleep(struct file *file, | ||
49 | const char __user * buffer, size_t count, loff_t * ppos) | ||
50 | { | ||
51 | char str[12]; | ||
52 | u32 state = 0; | ||
53 | int error = 0; | ||
54 | |||
55 | if (count > sizeof(str) - 1) | ||
56 | goto Done; | ||
57 | memset(str, 0, sizeof(str)); | ||
58 | if (copy_from_user(str, buffer, count)) | ||
59 | return -EFAULT; | ||
60 | |||
61 | /* Check for S4 bios request */ | ||
62 | if (!strcmp(str, "4b")) { | ||
63 | error = acpi_suspend(4); | ||
64 | goto Done; | ||
65 | } | ||
66 | state = simple_strtoul(str, NULL, 0); | ||
67 | #ifdef CONFIG_HIBERNATION | ||
68 | if (state == 4) { | ||
69 | error = hibernate(); | ||
70 | goto Done; | ||
71 | } | ||
72 | #endif | ||
73 | error = acpi_suspend(state); | ||
74 | Done: | ||
75 | return error ? error : count; | ||
76 | } | ||
77 | #endif /* CONFIG_ACPI_PROCFS */ | ||
78 | 25 | ||
79 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86) | 26 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86) |
80 | /* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ | 27 | /* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ |
@@ -463,17 +410,6 @@ static const struct file_operations acpi_system_wakeup_device_fops = { | |||
463 | .release = single_release, | 410 | .release = single_release, |
464 | }; | 411 | }; |
465 | 412 | ||
466 | #ifdef CONFIG_ACPI_PROCFS | ||
467 | static const struct file_operations acpi_system_sleep_fops = { | ||
468 | .owner = THIS_MODULE, | ||
469 | .open = acpi_system_sleep_open_fs, | ||
470 | .read = seq_read, | ||
471 | .write = acpi_system_write_sleep, | ||
472 | .llseek = seq_lseek, | ||
473 | .release = single_release, | ||
474 | }; | ||
475 | #endif /* CONFIG_ACPI_PROCFS */ | ||
476 | |||
477 | #ifdef HAVE_ACPI_LEGACY_ALARM | 413 | #ifdef HAVE_ACPI_LEGACY_ALARM |
478 | static const struct file_operations acpi_system_alarm_fops = { | 414 | static const struct file_operations acpi_system_alarm_fops = { |
479 | .owner = THIS_MODULE, | 415 | .owner = THIS_MODULE, |
@@ -495,12 +431,6 @@ static u32 rtc_handler(void *context) | |||
495 | 431 | ||
496 | int __init acpi_sleep_proc_init(void) | 432 | int __init acpi_sleep_proc_init(void) |
497 | { | 433 | { |
498 | #ifdef CONFIG_ACPI_PROCFS | ||
499 | /* 'sleep' [R/W] */ | ||
500 | proc_create("sleep", S_IFREG | S_IRUGO | S_IWUSR, | ||
501 | acpi_root_dir, &acpi_system_sleep_fops); | ||
502 | #endif /* CONFIG_ACPI_PROCFS */ | ||
503 | |||
504 | #ifdef HAVE_ACPI_LEGACY_ALARM | 434 | #ifdef HAVE_ACPI_LEGACY_ALARM |
505 | /* 'alarm' [R/W] */ | 435 | /* 'alarm' [R/W] */ |
506 | proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR, | 436 | proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR, |
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 38ea0cc6dc49..156021892389 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -83,9 +83,6 @@ MODULE_LICENSE("GPL"); | |||
83 | 83 | ||
84 | static int acpi_processor_add(struct acpi_device *device); | 84 | static int acpi_processor_add(struct acpi_device *device); |
85 | static int acpi_processor_remove(struct acpi_device *device, int type); | 85 | static int acpi_processor_remove(struct acpi_device *device, int type); |
86 | #ifdef CONFIG_ACPI_PROCFS | ||
87 | static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); | ||
88 | #endif | ||
89 | static void acpi_processor_notify(struct acpi_device *device, u32 event); | 86 | static void acpi_processor_notify(struct acpi_device *device, u32 event); |
90 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); | 87 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); |
91 | static int acpi_processor_handle_eject(struct acpi_processor *pr); | 88 | static int acpi_processor_handle_eject(struct acpi_processor *pr); |
@@ -113,15 +110,6 @@ static struct acpi_driver acpi_processor_driver = { | |||
113 | 110 | ||
114 | #define INSTALL_NOTIFY_HANDLER 1 | 111 | #define INSTALL_NOTIFY_HANDLER 1 |
115 | #define UNINSTALL_NOTIFY_HANDLER 2 | 112 | #define UNINSTALL_NOTIFY_HANDLER 2 |
116 | #ifdef CONFIG_ACPI_PROCFS | ||
117 | static const struct file_operations acpi_processor_info_fops = { | ||
118 | .owner = THIS_MODULE, | ||
119 | .open = acpi_processor_info_open_fs, | ||
120 | .read = seq_read, | ||
121 | .llseek = seq_lseek, | ||
122 | .release = single_release, | ||
123 | }; | ||
124 | #endif | ||
125 | 113 | ||
126 | DEFINE_PER_CPU(struct acpi_processor *, processors); | 114 | DEFINE_PER_CPU(struct acpi_processor *, processors); |
127 | EXPORT_PER_CPU_SYMBOL(processors); | 115 | EXPORT_PER_CPU_SYMBOL(processors); |
@@ -256,44 +244,8 @@ static int acpi_processor_errata(struct acpi_processor *pr) | |||
256 | return result; | 244 | return result; |
257 | } | 245 | } |
258 | 246 | ||
259 | /* -------------------------------------------------------------------------- | ||
260 | FS Interface (/proc) | ||
261 | -------------------------------------------------------------------------- */ | ||
262 | |||
263 | #ifdef CONFIG_ACPI_PROCFS | ||
264 | static struct proc_dir_entry *acpi_processor_dir = NULL; | 247 | static struct proc_dir_entry *acpi_processor_dir = NULL; |
265 | 248 | ||
266 | static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) | ||
267 | { | ||
268 | struct acpi_processor *pr = seq->private; | ||
269 | |||
270 | |||
271 | if (!pr) | ||
272 | goto end; | ||
273 | |||
274 | seq_printf(seq, "processor id: %d\n" | ||
275 | "acpi id: %d\n" | ||
276 | "bus mastering control: %s\n" | ||
277 | "power management: %s\n" | ||
278 | "throttling control: %s\n" | ||
279 | "limit interface: %s\n", | ||
280 | pr->id, | ||
281 | pr->acpi_id, | ||
282 | pr->flags.bm_control ? "yes" : "no", | ||
283 | pr->flags.power ? "yes" : "no", | ||
284 | pr->flags.throttling ? "yes" : "no", | ||
285 | pr->flags.limit ? "yes" : "no"); | ||
286 | |||
287 | end: | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int acpi_processor_info_open_fs(struct inode *inode, struct file *file) | ||
292 | { | ||
293 | return single_open(file, acpi_processor_info_seq_show, | ||
294 | PDE(inode)->data); | ||
295 | } | ||
296 | |||
297 | static int __cpuinit acpi_processor_add_fs(struct acpi_device *device) | 249 | static int __cpuinit acpi_processor_add_fs(struct acpi_device *device) |
298 | { | 250 | { |
299 | struct proc_dir_entry *entry = NULL; | 251 | struct proc_dir_entry *entry = NULL; |
@@ -306,14 +258,6 @@ static int __cpuinit acpi_processor_add_fs(struct acpi_device *device) | |||
306 | return -ENODEV; | 258 | return -ENODEV; |
307 | } | 259 | } |
308 | 260 | ||
309 | /* 'info' [R] */ | ||
310 | entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO, | ||
311 | S_IRUGO, acpi_device_dir(device), | ||
312 | &acpi_processor_info_fops, | ||
313 | acpi_driver_data(device)); | ||
314 | if (!entry) | ||
315 | return -EIO; | ||
316 | |||
317 | /* 'throttling' [R/W] */ | 261 | /* 'throttling' [R/W] */ |
318 | entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING, | 262 | entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING, |
319 | S_IFREG | S_IRUGO | S_IWUSR, | 263 | S_IFREG | S_IRUGO | S_IWUSR, |
@@ -322,43 +266,20 @@ static int __cpuinit acpi_processor_add_fs(struct acpi_device *device) | |||
322 | acpi_driver_data(device)); | 266 | acpi_driver_data(device)); |
323 | if (!entry) | 267 | if (!entry) |
324 | return -EIO; | 268 | return -EIO; |
325 | |||
326 | /* 'limit' [R/W] */ | ||
327 | entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT, | ||
328 | S_IFREG | S_IRUGO | S_IWUSR, | ||
329 | acpi_device_dir(device), | ||
330 | &acpi_processor_limit_fops, | ||
331 | acpi_driver_data(device)); | ||
332 | if (!entry) | ||
333 | return -EIO; | ||
334 | return 0; | 269 | return 0; |
335 | } | 270 | } |
336 | static int acpi_processor_remove_fs(struct acpi_device *device) | 271 | static int acpi_processor_remove_fs(struct acpi_device *device) |
337 | { | 272 | { |
338 | 273 | ||
339 | if (acpi_device_dir(device)) { | 274 | if (acpi_device_dir(device)) { |
340 | remove_proc_entry(ACPI_PROCESSOR_FILE_INFO, | ||
341 | acpi_device_dir(device)); | ||
342 | remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING, | 275 | remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING, |
343 | acpi_device_dir(device)); | 276 | acpi_device_dir(device)); |
344 | remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT, | ||
345 | acpi_device_dir(device)); | ||
346 | remove_proc_entry(acpi_device_bid(device), acpi_processor_dir); | 277 | remove_proc_entry(acpi_device_bid(device), acpi_processor_dir); |
347 | acpi_device_dir(device) = NULL; | 278 | acpi_device_dir(device) = NULL; |
348 | } | 279 | } |
349 | 280 | ||
350 | return 0; | 281 | return 0; |
351 | } | 282 | } |
352 | #else | ||
353 | static inline int acpi_processor_add_fs(struct acpi_device *device) | ||
354 | { | ||
355 | return 0; | ||
356 | } | ||
357 | static inline int acpi_processor_remove_fs(struct acpi_device *device) | ||
358 | { | ||
359 | return 0; | ||
360 | } | ||
361 | #endif | ||
362 | 283 | ||
363 | /* -------------------------------------------------------------------------- | 284 | /* -------------------------------------------------------------------------- |
364 | Driver Interface | 285 | Driver Interface |
@@ -921,11 +842,9 @@ static int __init acpi_processor_init(void) | |||
921 | 842 | ||
922 | memset(&errata, 0, sizeof(errata)); | 843 | memset(&errata, 0, sizeof(errata)); |
923 | 844 | ||
924 | #ifdef CONFIG_ACPI_PROCFS | ||
925 | acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); | 845 | acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); |
926 | if (!acpi_processor_dir) | 846 | if (!acpi_processor_dir) |
927 | return -ENOMEM; | 847 | return -ENOMEM; |
928 | #endif | ||
929 | 848 | ||
930 | if (!cpuidle_register_driver(&acpi_idle_driver)) { | 849 | if (!cpuidle_register_driver(&acpi_idle_driver)) { |
931 | printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n", | 850 | printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n", |
@@ -952,9 +871,7 @@ static int __init acpi_processor_init(void) | |||
952 | out_cpuidle: | 871 | out_cpuidle: |
953 | cpuidle_unregister_driver(&acpi_idle_driver); | 872 | cpuidle_unregister_driver(&acpi_idle_driver); |
954 | 873 | ||
955 | #ifdef CONFIG_ACPI_PROCFS | ||
956 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); | 874 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); |
957 | #endif | ||
958 | 875 | ||
959 | return result; | 876 | return result; |
960 | } | 877 | } |
@@ -974,9 +891,7 @@ static void __exit acpi_processor_exit(void) | |||
974 | 891 | ||
975 | cpuidle_unregister_driver(&acpi_idle_driver); | 892 | cpuidle_unregister_driver(&acpi_idle_driver); |
976 | 893 | ||
977 | #ifdef CONFIG_ACPI_PROCFS | ||
978 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); | 894 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); |
979 | #endif | ||
980 | 895 | ||
981 | return; | 896 | return; |
982 | } | 897 | } |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index b4c2f3bdadeb..f4428e82b352 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -33,8 +33,6 @@ | |||
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/cpufreq.h> | 34 | #include <linux/cpufreq.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/proc_fs.h> | ||
37 | #include <linux/seq_file.h> | ||
38 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
39 | #include <linux/dmi.h> | 37 | #include <linux/dmi.h> |
40 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
@@ -82,13 +80,6 @@ module_param(bm_check_disable, uint, 0000); | |||
82 | static unsigned int latency_factor __read_mostly = 2; | 80 | static unsigned int latency_factor __read_mostly = 2; |
83 | module_param(latency_factor, uint, 0644); | 81 | module_param(latency_factor, uint, 0644); |
84 | 82 | ||
85 | #ifdef CONFIG_ACPI_PROCFS | ||
86 | static u64 us_to_pm_timer_ticks(s64 t) | ||
87 | { | ||
88 | return div64_u64(t * PM_TIMER_FREQUENCY, 1000000); | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | /* | 83 | /* |
93 | * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. | 84 | * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. |
94 | * For now disable this. Probably a bug somewhere else. | 85 | * For now disable this. Probably a bug somewhere else. |
@@ -689,78 +680,6 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) | |||
689 | return 0; | 680 | return 0; |
690 | } | 681 | } |
691 | 682 | ||
692 | #ifdef CONFIG_ACPI_PROCFS | ||
693 | static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) | ||
694 | { | ||
695 | struct acpi_processor *pr = seq->private; | ||
696 | unsigned int i; | ||
697 | |||
698 | |||
699 | if (!pr) | ||
700 | goto end; | ||
701 | |||
702 | seq_printf(seq, "active state: C%zd\n" | ||
703 | "max_cstate: C%d\n" | ||
704 | "maximum allowed latency: %d usec\n", | ||
705 | pr->power.state ? pr->power.state - pr->power.states : 0, | ||
706 | max_cstate, pm_qos_request(PM_QOS_CPU_DMA_LATENCY)); | ||
707 | |||
708 | seq_puts(seq, "states:\n"); | ||
709 | |||
710 | for (i = 1; i <= pr->power.count; i++) { | ||
711 | seq_printf(seq, " %cC%d: ", | ||
712 | (&pr->power.states[i] == | ||
713 | pr->power.state ? '*' : ' '), i); | ||
714 | |||
715 | if (!pr->power.states[i].valid) { | ||
716 | seq_puts(seq, "<not supported>\n"); | ||
717 | continue; | ||
718 | } | ||
719 | |||
720 | switch (pr->power.states[i].type) { | ||
721 | case ACPI_STATE_C1: | ||
722 | seq_printf(seq, "type[C1] "); | ||
723 | break; | ||
724 | case ACPI_STATE_C2: | ||
725 | seq_printf(seq, "type[C2] "); | ||
726 | break; | ||
727 | case ACPI_STATE_C3: | ||
728 | seq_printf(seq, "type[C3] "); | ||
729 | break; | ||
730 | default: | ||
731 | seq_printf(seq, "type[--] "); | ||
732 | break; | ||
733 | } | ||
734 | |||
735 | seq_puts(seq, "promotion[--] "); | ||
736 | |||
737 | seq_puts(seq, "demotion[--] "); | ||
738 | |||
739 | seq_printf(seq, "latency[%03d] usage[%08d] duration[%020Lu]\n", | ||
740 | pr->power.states[i].latency, | ||
741 | pr->power.states[i].usage, | ||
742 | us_to_pm_timer_ticks(pr->power.states[i].time)); | ||
743 | } | ||
744 | |||
745 | end: | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static int acpi_processor_power_open_fs(struct inode *inode, struct file *file) | ||
750 | { | ||
751 | return single_open(file, acpi_processor_power_seq_show, | ||
752 | PDE(inode)->data); | ||
753 | } | ||
754 | |||
755 | static const struct file_operations acpi_processor_power_fops = { | ||
756 | .owner = THIS_MODULE, | ||
757 | .open = acpi_processor_power_open_fs, | ||
758 | .read = seq_read, | ||
759 | .llseek = seq_lseek, | ||
760 | .release = single_release, | ||
761 | }; | ||
762 | #endif | ||
763 | |||
764 | /** | 683 | /** |
765 | * acpi_idle_bm_check - checks if bus master activity was detected | 684 | * acpi_idle_bm_check - checks if bus master activity was detected |
766 | */ | 685 | */ |
@@ -803,13 +722,12 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) | |||
803 | } else if (cx->entry_method == ACPI_CSTATE_HALT) { | 722 | } else if (cx->entry_method == ACPI_CSTATE_HALT) { |
804 | acpi_safe_halt(); | 723 | acpi_safe_halt(); |
805 | } else { | 724 | } else { |
806 | int unused; | ||
807 | /* IO port based C-state */ | 725 | /* IO port based C-state */ |
808 | inb(cx->address); | 726 | inb(cx->address); |
809 | /* Dummy wait op - must do something useless after P_LVL2 read | 727 | /* Dummy wait op - must do something useless after P_LVL2 read |
810 | because chipsets cannot guarantee that STPCLK# signal | 728 | because chipsets cannot guarantee that STPCLK# signal |
811 | gets asserted in time to freeze execution properly. */ | 729 | gets asserted in time to freeze execution properly. */ |
812 | unused = inl(acpi_gbl_FADT.xpm_timer_block.address); | 730 | inl(acpi_gbl_FADT.xpm_timer_block.address); |
813 | } | 731 | } |
814 | start_critical_timings(); | 732 | start_critical_timings(); |
815 | } | 733 | } |
@@ -1172,9 +1090,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1172 | { | 1090 | { |
1173 | acpi_status status = 0; | 1091 | acpi_status status = 0; |
1174 | static int first_run; | 1092 | static int first_run; |
1175 | #ifdef CONFIG_ACPI_PROCFS | ||
1176 | struct proc_dir_entry *entry = NULL; | ||
1177 | #endif | ||
1178 | 1093 | ||
1179 | if (boot_option_idle_override) | 1094 | if (boot_option_idle_override) |
1180 | return 0; | 1095 | return 0; |
@@ -1223,15 +1138,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1223 | if (cpuidle_register_device(&pr->power.dev)) | 1138 | if (cpuidle_register_device(&pr->power.dev)) |
1224 | return -EIO; | 1139 | return -EIO; |
1225 | } | 1140 | } |
1226 | #ifdef CONFIG_ACPI_PROCFS | ||
1227 | /* 'power' [R] */ | ||
1228 | entry = proc_create_data(ACPI_PROCESSOR_FILE_POWER, | ||
1229 | S_IRUGO, acpi_device_dir(device), | ||
1230 | &acpi_processor_power_fops, | ||
1231 | acpi_driver_data(device)); | ||
1232 | if (!entry) | ||
1233 | return -EIO; | ||
1234 | #endif | ||
1235 | return 0; | 1141 | return 0; |
1236 | } | 1142 | } |
1237 | 1143 | ||
@@ -1244,11 +1150,5 @@ int acpi_processor_power_exit(struct acpi_processor *pr, | |||
1244 | cpuidle_unregister_device(&pr->power.dev); | 1150 | cpuidle_unregister_device(&pr->power.dev); |
1245 | pr->flags.power_setup_done = 0; | 1151 | pr->flags.power_setup_done = 0; |
1246 | 1152 | ||
1247 | #ifdef CONFIG_ACPI_PROCFS | ||
1248 | if (acpi_device_dir(device)) | ||
1249 | remove_proc_entry(ACPI_PROCESSOR_FILE_POWER, | ||
1250 | acpi_device_dir(device)); | ||
1251 | #endif | ||
1252 | |||
1253 | return 0; | 1153 | return 0; |
1254 | } | 1154 | } |
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 6deafb4aa0da..953b25fb9869 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/cpufreq.h> | 32 | #include <linux/cpufreq.h> |
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/seq_file.h> | ||
35 | #include <linux/sysdev.h> | 33 | #include <linux/sysdev.h> |
36 | 34 | ||
37 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
@@ -438,84 +436,3 @@ struct thermal_cooling_device_ops processor_cooling_ops = { | |||
438 | .get_cur_state = processor_get_cur_state, | 436 | .get_cur_state = processor_get_cur_state, |
439 | .set_cur_state = processor_set_cur_state, | 437 | .set_cur_state = processor_set_cur_state, |
440 | }; | 438 | }; |
441 | |||
442 | /* /proc interface */ | ||
443 | #ifdef CONFIG_ACPI_PROCFS | ||
444 | static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) | ||
445 | { | ||
446 | struct acpi_processor *pr = seq->private; | ||
447 | |||
448 | if (!pr) | ||
449 | goto end; | ||
450 | |||
451 | if (!pr->flags.limit) { | ||
452 | seq_puts(seq, "<not supported>\n"); | ||
453 | goto end; | ||
454 | } | ||
455 | |||
456 | seq_printf(seq, "active limit: P%d:T%d\n" | ||
457 | "user limit: P%d:T%d\n" | ||
458 | "thermal limit: P%d:T%d\n", | ||
459 | pr->limit.state.px, pr->limit.state.tx, | ||
460 | pr->limit.user.px, pr->limit.user.tx, | ||
461 | pr->limit.thermal.px, pr->limit.thermal.tx); | ||
462 | |||
463 | end: | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file) | ||
468 | { | ||
469 | return single_open(file, acpi_processor_limit_seq_show, | ||
470 | PDE(inode)->data); | ||
471 | } | ||
472 | |||
473 | static ssize_t acpi_processor_write_limit(struct file * file, | ||
474 | const char __user * buffer, | ||
475 | size_t count, loff_t * data) | ||
476 | { | ||
477 | int result = 0; | ||
478 | struct seq_file *m = file->private_data; | ||
479 | struct acpi_processor *pr = m->private; | ||
480 | char limit_string[25] = { '\0' }; | ||
481 | int px = 0; | ||
482 | int tx = 0; | ||
483 | |||
484 | |||
485 | if (!pr || (count > sizeof(limit_string) - 1)) { | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
489 | if (copy_from_user(limit_string, buffer, count)) { | ||
490 | return -EFAULT; | ||
491 | } | ||
492 | |||
493 | limit_string[count] = '\0'; | ||
494 | |||
495 | if (sscanf(limit_string, "%d:%d", &px, &tx) != 2) { | ||
496 | printk(KERN_ERR PREFIX "Invalid data format\n"); | ||
497 | return -EINVAL; | ||
498 | } | ||
499 | |||
500 | if (pr->flags.throttling) { | ||
501 | if ((tx < 0) || (tx > (pr->throttling.state_count - 1))) { | ||
502 | printk(KERN_ERR PREFIX "Invalid tx\n"); | ||
503 | return -EINVAL; | ||
504 | } | ||
505 | pr->limit.user.tx = tx; | ||
506 | } | ||
507 | |||
508 | result = acpi_processor_apply_limit(pr); | ||
509 | |||
510 | return count; | ||
511 | } | ||
512 | |||
513 | const struct file_operations acpi_processor_limit_fops = { | ||
514 | .owner = THIS_MODULE, | ||
515 | .open = acpi_processor_limit_open_fs, | ||
516 | .read = seq_read, | ||
517 | .write = acpi_processor_write_limit, | ||
518 | .llseek = seq_lseek, | ||
519 | .release = single_release, | ||
520 | }; | ||
521 | #endif | ||
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 9ade1a5b32ed..730863855ed5 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
@@ -1215,7 +1215,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | /* proc interface */ | 1217 | /* proc interface */ |
1218 | #ifdef CONFIG_ACPI_PROCFS | ||
1219 | static int acpi_processor_throttling_seq_show(struct seq_file *seq, | 1218 | static int acpi_processor_throttling_seq_show(struct seq_file *seq, |
1220 | void *offset) | 1219 | void *offset) |
1221 | { | 1220 | { |
@@ -1323,4 +1322,3 @@ const struct file_operations acpi_processor_throttling_fops = { | |||
1323 | .llseek = seq_lseek, | 1322 | .llseek = seq_lseek, |
1324 | .release = single_release, | 1323 | .release = single_release, |
1325 | }; | 1324 | }; |
1326 | #endif | ||
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index e143203254a4..cf82989ae756 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -70,10 +70,10 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
70 | 70 | ||
71 | } | 71 | } |
72 | ACPI_FLUSH_CPU_CACHE(); | 72 | ACPI_FLUSH_CPU_CACHE(); |
73 | acpi_enable_wakeup_device_prep(acpi_state); | ||
74 | #endif | 73 | #endif |
75 | printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n", | 74 | printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n", |
76 | acpi_state); | 75 | acpi_state); |
76 | acpi_enable_wakeup_devices(acpi_state); | ||
77 | acpi_enter_sleep_state_prep(acpi_state); | 77 | acpi_enter_sleep_state_prep(acpi_state); |
78 | return 0; | 78 | return 0; |
79 | } | 79 | } |
@@ -119,6 +119,16 @@ static int acpi_pm_freeze(void) | |||
119 | } | 119 | } |
120 | 120 | ||
121 | /** | 121 | /** |
122 | * acpi_pre_suspend - Enable wakeup devices, "freeze" EC and save NVS. | ||
123 | */ | ||
124 | static int acpi_pm_pre_suspend(void) | ||
125 | { | ||
126 | acpi_pm_freeze(); | ||
127 | suspend_nvs_save(); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | /** | ||
122 | * __acpi_pm_prepare - Prepare the platform to enter the target state. | 132 | * __acpi_pm_prepare - Prepare the platform to enter the target state. |
123 | * | 133 | * |
124 | * If necessary, set the firmware waking vector and do arch-specific | 134 | * If necessary, set the firmware waking vector and do arch-specific |
@@ -127,11 +137,9 @@ static int acpi_pm_freeze(void) | |||
127 | static int __acpi_pm_prepare(void) | 137 | static int __acpi_pm_prepare(void) |
128 | { | 138 | { |
129 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | 139 | int error = acpi_sleep_prepare(acpi_target_sleep_state); |
130 | |||
131 | suspend_nvs_save(); | ||
132 | |||
133 | if (error) | 140 | if (error) |
134 | acpi_target_sleep_state = ACPI_STATE_S0; | 141 | acpi_target_sleep_state = ACPI_STATE_S0; |
142 | |||
135 | return error; | 143 | return error; |
136 | } | 144 | } |
137 | 145 | ||
@@ -142,9 +150,8 @@ static int __acpi_pm_prepare(void) | |||
142 | static int acpi_pm_prepare(void) | 150 | static int acpi_pm_prepare(void) |
143 | { | 151 | { |
144 | int error = __acpi_pm_prepare(); | 152 | int error = __acpi_pm_prepare(); |
145 | |||
146 | if (!error) | 153 | if (!error) |
147 | acpi_pm_freeze(); | 154 | acpi_pm_pre_suspend(); |
148 | 155 | ||
149 | return error; | 156 | return error; |
150 | } | 157 | } |
@@ -159,7 +166,6 @@ static void acpi_pm_finish(void) | |||
159 | { | 166 | { |
160 | u32 acpi_state = acpi_target_sleep_state; | 167 | u32 acpi_state = acpi_target_sleep_state; |
161 | 168 | ||
162 | suspend_nvs_free(); | ||
163 | acpi_ec_unblock_transactions(); | 169 | acpi_ec_unblock_transactions(); |
164 | 170 | ||
165 | if (acpi_state == ACPI_STATE_S0) | 171 | if (acpi_state == ACPI_STATE_S0) |
@@ -167,7 +173,7 @@ static void acpi_pm_finish(void) | |||
167 | 173 | ||
168 | printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n", | 174 | printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n", |
169 | acpi_state); | 175 | acpi_state); |
170 | acpi_disable_wakeup_device(acpi_state); | 176 | acpi_disable_wakeup_devices(acpi_state); |
171 | acpi_leave_sleep_state(acpi_state); | 177 | acpi_leave_sleep_state(acpi_state); |
172 | 178 | ||
173 | /* reset firmware waking vector */ | 179 | /* reset firmware waking vector */ |
@@ -181,6 +187,7 @@ static void acpi_pm_finish(void) | |||
181 | */ | 187 | */ |
182 | static void acpi_pm_end(void) | 188 | static void acpi_pm_end(void) |
183 | { | 189 | { |
190 | suspend_nvs_free(); | ||
184 | /* | 191 | /* |
185 | * This is necessary in case acpi_pm_finish() is not called during a | 192 | * This is necessary in case acpi_pm_finish() is not called during a |
186 | * failing transition to a sleep state. | 193 | * failing transition to a sleep state. |
@@ -251,7 +258,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
251 | } | 258 | } |
252 | 259 | ||
253 | local_irq_save(flags); | 260 | local_irq_save(flags); |
254 | acpi_enable_wakeup_device(acpi_state); | ||
255 | switch (acpi_state) { | 261 | switch (acpi_state) { |
256 | case ACPI_STATE_S1: | 262 | case ACPI_STATE_S1: |
257 | barrier(); | 263 | barrier(); |
@@ -297,11 +303,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
297 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 303 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
298 | } | 304 | } |
299 | 305 | ||
300 | static void acpi_suspend_finish(void) | ||
301 | { | ||
302 | acpi_pm_finish(); | ||
303 | } | ||
304 | |||
305 | static int acpi_suspend_state_valid(suspend_state_t pm_state) | 306 | static int acpi_suspend_state_valid(suspend_state_t pm_state) |
306 | { | 307 | { |
307 | u32 acpi_state; | 308 | u32 acpi_state; |
@@ -323,7 +324,7 @@ static struct platform_suspend_ops acpi_suspend_ops = { | |||
323 | .begin = acpi_suspend_begin, | 324 | .begin = acpi_suspend_begin, |
324 | .prepare_late = acpi_pm_prepare, | 325 | .prepare_late = acpi_pm_prepare, |
325 | .enter = acpi_suspend_enter, | 326 | .enter = acpi_suspend_enter, |
326 | .wake = acpi_suspend_finish, | 327 | .wake = acpi_pm_finish, |
327 | .end = acpi_pm_end, | 328 | .end = acpi_pm_end, |
328 | }; | 329 | }; |
329 | 330 | ||
@@ -336,9 +337,9 @@ static struct platform_suspend_ops acpi_suspend_ops = { | |||
336 | static int acpi_suspend_begin_old(suspend_state_t pm_state) | 337 | static int acpi_suspend_begin_old(suspend_state_t pm_state) |
337 | { | 338 | { |
338 | int error = acpi_suspend_begin(pm_state); | 339 | int error = acpi_suspend_begin(pm_state); |
339 | |||
340 | if (!error) | 340 | if (!error) |
341 | error = __acpi_pm_prepare(); | 341 | error = __acpi_pm_prepare(); |
342 | |||
342 | return error; | 343 | return error; |
343 | } | 344 | } |
344 | 345 | ||
@@ -349,9 +350,9 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state) | |||
349 | static struct platform_suspend_ops acpi_suspend_ops_old = { | 350 | static struct platform_suspend_ops acpi_suspend_ops_old = { |
350 | .valid = acpi_suspend_state_valid, | 351 | .valid = acpi_suspend_state_valid, |
351 | .begin = acpi_suspend_begin_old, | 352 | .begin = acpi_suspend_begin_old, |
352 | .prepare_late = acpi_pm_freeze, | 353 | .prepare_late = acpi_pm_pre_suspend, |
353 | .enter = acpi_suspend_enter, | 354 | .enter = acpi_suspend_enter, |
354 | .wake = acpi_suspend_finish, | 355 | .wake = acpi_pm_finish, |
355 | .end = acpi_pm_end, | 356 | .end = acpi_pm_end, |
356 | .recover = acpi_pm_finish, | 357 | .recover = acpi_pm_finish, |
357 | }; | 358 | }; |
@@ -423,16 +424,6 @@ static int acpi_hibernation_begin(void) | |||
423 | return error; | 424 | return error; |
424 | } | 425 | } |
425 | 426 | ||
426 | static int acpi_hibernation_pre_snapshot(void) | ||
427 | { | ||
428 | int error = acpi_pm_prepare(); | ||
429 | |||
430 | if (!error) | ||
431 | suspend_nvs_save(); | ||
432 | |||
433 | return error; | ||
434 | } | ||
435 | |||
436 | static int acpi_hibernation_enter(void) | 427 | static int acpi_hibernation_enter(void) |
437 | { | 428 | { |
438 | acpi_status status = AE_OK; | 429 | acpi_status status = AE_OK; |
@@ -441,7 +432,6 @@ static int acpi_hibernation_enter(void) | |||
441 | ACPI_FLUSH_CPU_CACHE(); | 432 | ACPI_FLUSH_CPU_CACHE(); |
442 | 433 | ||
443 | local_irq_save(flags); | 434 | local_irq_save(flags); |
444 | acpi_enable_wakeup_device(ACPI_STATE_S4); | ||
445 | /* This shouldn't return. If it returns, we have a problem */ | 435 | /* This shouldn't return. If it returns, we have a problem */ |
446 | status = acpi_enter_sleep_state(ACPI_STATE_S4); | 436 | status = acpi_enter_sleep_state(ACPI_STATE_S4); |
447 | /* Reprogram control registers and execute _BFS */ | 437 | /* Reprogram control registers and execute _BFS */ |
@@ -481,7 +471,7 @@ static void acpi_pm_thaw(void) | |||
481 | static struct platform_hibernation_ops acpi_hibernation_ops = { | 471 | static struct platform_hibernation_ops acpi_hibernation_ops = { |
482 | .begin = acpi_hibernation_begin, | 472 | .begin = acpi_hibernation_begin, |
483 | .end = acpi_pm_end, | 473 | .end = acpi_pm_end, |
484 | .pre_snapshot = acpi_hibernation_pre_snapshot, | 474 | .pre_snapshot = acpi_pm_prepare, |
485 | .finish = acpi_pm_finish, | 475 | .finish = acpi_pm_finish, |
486 | .prepare = acpi_pm_prepare, | 476 | .prepare = acpi_pm_prepare, |
487 | .enter = acpi_hibernation_enter, | 477 | .enter = acpi_hibernation_enter, |
@@ -517,13 +507,6 @@ static int acpi_hibernation_begin_old(void) | |||
517 | return error; | 507 | return error; |
518 | } | 508 | } |
519 | 509 | ||
520 | static int acpi_hibernation_pre_snapshot_old(void) | ||
521 | { | ||
522 | acpi_pm_freeze(); | ||
523 | suspend_nvs_save(); | ||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | /* | 510 | /* |
528 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has | 511 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has |
529 | * been requested. | 512 | * been requested. |
@@ -531,7 +514,7 @@ static int acpi_hibernation_pre_snapshot_old(void) | |||
531 | static struct platform_hibernation_ops acpi_hibernation_ops_old = { | 514 | static struct platform_hibernation_ops acpi_hibernation_ops_old = { |
532 | .begin = acpi_hibernation_begin_old, | 515 | .begin = acpi_hibernation_begin_old, |
533 | .end = acpi_pm_end, | 516 | .end = acpi_pm_end, |
534 | .pre_snapshot = acpi_hibernation_pre_snapshot_old, | 517 | .pre_snapshot = acpi_pm_pre_suspend, |
535 | .prepare = acpi_pm_freeze, | 518 | .prepare = acpi_pm_freeze, |
536 | .finish = acpi_pm_finish, | 519 | .finish = acpi_pm_finish, |
537 | .enter = acpi_hibernation_enter, | 520 | .enter = acpi_hibernation_enter, |
@@ -686,7 +669,6 @@ static void acpi_power_off(void) | |||
686 | /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ | 669 | /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ |
687 | printk(KERN_DEBUG "%s called\n", __func__); | 670 | printk(KERN_DEBUG "%s called\n", __func__); |
688 | local_irq_disable(); | 671 | local_irq_disable(); |
689 | acpi_enable_wakeup_device(ACPI_STATE_S5); | ||
690 | acpi_enter_sleep_state(ACPI_STATE_S5); | 672 | acpi_enter_sleep_state(ACPI_STATE_S5); |
691 | } | 673 | } |
692 | 674 | ||
diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h index 25b8bd149284..d8821805c3bc 100644 --- a/drivers/acpi/sleep.h +++ b/drivers/acpi/sleep.h | |||
@@ -2,9 +2,8 @@ | |||
2 | extern u8 sleep_states[]; | 2 | extern u8 sleep_states[]; |
3 | extern int acpi_suspend(u32 state); | 3 | extern int acpi_suspend(u32 state); |
4 | 4 | ||
5 | extern void acpi_enable_wakeup_device_prep(u8 sleep_state); | 5 | extern void acpi_enable_wakeup_devices(u8 sleep_state); |
6 | extern void acpi_enable_wakeup_device(u8 sleep_state); | 6 | extern void acpi_disable_wakeup_devices(u8 sleep_state); |
7 | extern void acpi_disable_wakeup_device(u8 sleep_state); | ||
8 | 7 | ||
9 | extern struct list_head acpi_wakeup_device_list; | 8 | extern struct list_head acpi_wakeup_device_list; |
10 | extern struct mutex acpi_device_lock; | 9 | extern struct mutex acpi_device_lock; |
diff --git a/drivers/acpi/system.c b/drivers/acpi/sysfs.c index 5981bd07e20e..68e2e4582fa2 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/sysfs.c | |||
@@ -1,51 +1,218 @@ | |||
1 | /* | 1 | /* |
2 | * acpi_system.c - ACPI System Driver ($Revision: 63 $) | 2 | * sysfs.c - ACPI sysfs interface to userspace. |
3 | * | ||
4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | ||
5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | ||
6 | * | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or (at | ||
12 | * your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
22 | * | ||
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
24 | */ | 3 | */ |
25 | 4 | ||
26 | #include <linux/proc_fs.h> | ||
27 | #include <linux/seq_file.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/init.h> | 5 | #include <linux/init.h> |
30 | #include <linux/string.h> | 6 | #include <linux/kernel.h> |
31 | #include <asm/uaccess.h> | 7 | #include <linux/moduleparam.h> |
32 | |||
33 | #include <acpi/acpi_drivers.h> | 8 | #include <acpi/acpi_drivers.h> |
34 | 9 | ||
35 | #define PREFIX "ACPI: " | ||
36 | |||
37 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | 10 | #define _COMPONENT ACPI_SYSTEM_COMPONENT |
38 | ACPI_MODULE_NAME("system"); | 11 | ACPI_MODULE_NAME("sysfs"); |
39 | |||
40 | #define ACPI_SYSTEM_CLASS "system" | ||
41 | #define ACPI_SYSTEM_DEVICE_NAME "System" | ||
42 | 12 | ||
43 | u32 acpi_irq_handled; | 13 | #define PREFIX "ACPI: " |
44 | u32 acpi_irq_not_handled; | ||
45 | 14 | ||
15 | #ifdef CONFIG_ACPI_DEBUG | ||
46 | /* | 16 | /* |
47 | * Make ACPICA version work as module param | 17 | * ACPI debug sysfs I/F, including: |
18 | * /sys/modules/acpi/parameters/debug_layer | ||
19 | * /sys/modules/acpi/parameters/debug_level | ||
20 | * /sys/modules/acpi/parameters/trace_method_name | ||
21 | * /sys/modules/acpi/parameters/trace_state | ||
22 | * /sys/modules/acpi/parameters/trace_debug_layer | ||
23 | * /sys/modules/acpi/parameters/trace_debug_level | ||
48 | */ | 24 | */ |
25 | |||
26 | struct acpi_dlayer { | ||
27 | const char *name; | ||
28 | unsigned long value; | ||
29 | }; | ||
30 | struct acpi_dlevel { | ||
31 | const char *name; | ||
32 | unsigned long value; | ||
33 | }; | ||
34 | #define ACPI_DEBUG_INIT(v) { .name = #v, .value = v } | ||
35 | |||
36 | static const struct acpi_dlayer acpi_debug_layers[] = { | ||
37 | ACPI_DEBUG_INIT(ACPI_UTILITIES), | ||
38 | ACPI_DEBUG_INIT(ACPI_HARDWARE), | ||
39 | ACPI_DEBUG_INIT(ACPI_EVENTS), | ||
40 | ACPI_DEBUG_INIT(ACPI_TABLES), | ||
41 | ACPI_DEBUG_INIT(ACPI_NAMESPACE), | ||
42 | ACPI_DEBUG_INIT(ACPI_PARSER), | ||
43 | ACPI_DEBUG_INIT(ACPI_DISPATCHER), | ||
44 | ACPI_DEBUG_INIT(ACPI_EXECUTER), | ||
45 | ACPI_DEBUG_INIT(ACPI_RESOURCES), | ||
46 | ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER), | ||
47 | ACPI_DEBUG_INIT(ACPI_OS_SERVICES), | ||
48 | ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), | ||
49 | ACPI_DEBUG_INIT(ACPI_COMPILER), | ||
50 | ACPI_DEBUG_INIT(ACPI_TOOLS), | ||
51 | |||
52 | ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), | ||
53 | ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), | ||
54 | ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), | ||
55 | ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), | ||
56 | ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), | ||
57 | ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), | ||
58 | ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), | ||
59 | ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), | ||
60 | ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), | ||
61 | ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), | ||
62 | ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), | ||
63 | ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), | ||
64 | ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), | ||
65 | ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), | ||
66 | }; | ||
67 | |||
68 | static const struct acpi_dlevel acpi_debug_levels[] = { | ||
69 | ACPI_DEBUG_INIT(ACPI_LV_INIT), | ||
70 | ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), | ||
71 | ACPI_DEBUG_INIT(ACPI_LV_INFO), | ||
72 | |||
73 | ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES), | ||
74 | ACPI_DEBUG_INIT(ACPI_LV_PARSE), | ||
75 | ACPI_DEBUG_INIT(ACPI_LV_LOAD), | ||
76 | ACPI_DEBUG_INIT(ACPI_LV_DISPATCH), | ||
77 | ACPI_DEBUG_INIT(ACPI_LV_EXEC), | ||
78 | ACPI_DEBUG_INIT(ACPI_LV_NAMES), | ||
79 | ACPI_DEBUG_INIT(ACPI_LV_OPREGION), | ||
80 | ACPI_DEBUG_INIT(ACPI_LV_BFIELD), | ||
81 | ACPI_DEBUG_INIT(ACPI_LV_TABLES), | ||
82 | ACPI_DEBUG_INIT(ACPI_LV_VALUES), | ||
83 | ACPI_DEBUG_INIT(ACPI_LV_OBJECTS), | ||
84 | ACPI_DEBUG_INIT(ACPI_LV_RESOURCES), | ||
85 | ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS), | ||
86 | ACPI_DEBUG_INIT(ACPI_LV_PACKAGE), | ||
87 | |||
88 | ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS), | ||
89 | ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS), | ||
90 | ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS), | ||
91 | |||
92 | ACPI_DEBUG_INIT(ACPI_LV_MUTEX), | ||
93 | ACPI_DEBUG_INIT(ACPI_LV_THREADS), | ||
94 | ACPI_DEBUG_INIT(ACPI_LV_IO), | ||
95 | ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS), | ||
96 | |||
97 | ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE), | ||
98 | ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO), | ||
99 | ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES), | ||
100 | ACPI_DEBUG_INIT(ACPI_LV_EVENTS), | ||
101 | }; | ||
102 | |||
103 | static int param_get_debug_layer(char *buffer, struct kernel_param *kp) | ||
104 | { | ||
105 | int result = 0; | ||
106 | int i; | ||
107 | |||
108 | result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); | ||
109 | |||
110 | for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) { | ||
111 | result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n", | ||
112 | acpi_debug_layers[i].name, | ||
113 | acpi_debug_layers[i].value, | ||
114 | (acpi_dbg_layer & acpi_debug_layers[i].value) | ||
115 | ? '*' : ' '); | ||
116 | } | ||
117 | result += | ||
118 | sprintf(buffer + result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", | ||
119 | ACPI_ALL_DRIVERS, | ||
120 | (acpi_dbg_layer & ACPI_ALL_DRIVERS) == | ||
121 | ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) | ||
122 | == 0 ? ' ' : '-'); | ||
123 | result += | ||
124 | sprintf(buffer + result, | ||
125 | "--\ndebug_layer = 0x%08X ( * = enabled)\n", | ||
126 | acpi_dbg_layer); | ||
127 | |||
128 | return result; | ||
129 | } | ||
130 | |||
131 | static int param_get_debug_level(char *buffer, struct kernel_param *kp) | ||
132 | { | ||
133 | int result = 0; | ||
134 | int i; | ||
135 | |||
136 | result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); | ||
137 | |||
138 | for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { | ||
139 | result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n", | ||
140 | acpi_debug_levels[i].name, | ||
141 | acpi_debug_levels[i].value, | ||
142 | (acpi_dbg_level & acpi_debug_levels[i].value) | ||
143 | ? '*' : ' '); | ||
144 | } | ||
145 | result += | ||
146 | sprintf(buffer + result, "--\ndebug_level = 0x%08X (* = enabled)\n", | ||
147 | acpi_dbg_level); | ||
148 | |||
149 | return result; | ||
150 | } | ||
151 | |||
152 | module_param_call(debug_layer, param_set_uint, param_get_debug_layer, | ||
153 | &acpi_dbg_layer, 0644); | ||
154 | module_param_call(debug_level, param_set_uint, param_get_debug_level, | ||
155 | &acpi_dbg_level, 0644); | ||
156 | |||
157 | static char trace_method_name[6]; | ||
158 | module_param_string(trace_method_name, trace_method_name, 6, 0644); | ||
159 | static unsigned int trace_debug_layer; | ||
160 | module_param(trace_debug_layer, uint, 0644); | ||
161 | static unsigned int trace_debug_level; | ||
162 | module_param(trace_debug_level, uint, 0644); | ||
163 | |||
164 | static int param_set_trace_state(const char *val, struct kernel_param *kp) | ||
165 | { | ||
166 | int result = 0; | ||
167 | |||
168 | if (!strncmp(val, "enable", strlen("enable") - 1)) { | ||
169 | result = acpi_debug_trace(trace_method_name, trace_debug_level, | ||
170 | trace_debug_layer, 0); | ||
171 | if (result) | ||
172 | result = -EBUSY; | ||
173 | goto exit; | ||
174 | } | ||
175 | |||
176 | if (!strncmp(val, "disable", strlen("disable") - 1)) { | ||
177 | int name = 0; | ||
178 | result = acpi_debug_trace((char *)&name, trace_debug_level, | ||
179 | trace_debug_layer, 0); | ||
180 | if (result) | ||
181 | result = -EBUSY; | ||
182 | goto exit; | ||
183 | } | ||
184 | |||
185 | if (!strncmp(val, "1", 1)) { | ||
186 | result = acpi_debug_trace(trace_method_name, trace_debug_level, | ||
187 | trace_debug_layer, 1); | ||
188 | if (result) | ||
189 | result = -EBUSY; | ||
190 | goto exit; | ||
191 | } | ||
192 | |||
193 | result = -EINVAL; | ||
194 | exit: | ||
195 | return result; | ||
196 | } | ||
197 | |||
198 | static int param_get_trace_state(char *buffer, struct kernel_param *kp) | ||
199 | { | ||
200 | if (!acpi_gbl_trace_method_name) | ||
201 | return sprintf(buffer, "disable"); | ||
202 | else { | ||
203 | if (acpi_gbl_trace_flags & 1) | ||
204 | return sprintf(buffer, "1"); | ||
205 | else | ||
206 | return sprintf(buffer, "enable"); | ||
207 | } | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | module_param_call(trace_state, param_set_trace_state, param_get_trace_state, | ||
212 | NULL, 0644); | ||
213 | #endif /* CONFIG_ACPI_DEBUG */ | ||
214 | |||
215 | /* /sys/module/acpi/parameters/acpica_version */ | ||
49 | static int param_get_acpica_version(char *buffer, struct kernel_param *kp) | 216 | static int param_get_acpica_version(char *buffer, struct kernel_param *kp) |
50 | { | 217 | { |
51 | int result; | 218 | int result; |
@@ -57,9 +224,12 @@ static int param_get_acpica_version(char *buffer, struct kernel_param *kp) | |||
57 | 224 | ||
58 | module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); | 225 | module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); |
59 | 226 | ||
60 | /* -------------------------------------------------------------------------- | 227 | /* |
61 | FS Interface (/sys) | 228 | * ACPI table sysfs I/F: |
62 | -------------------------------------------------------------------------- */ | 229 | * /sys/firmware/acpi/tables/ |
230 | * /sys/firmware/acpi/tables/dynamic/ | ||
231 | */ | ||
232 | |||
63 | static LIST_HEAD(acpi_table_attr_list); | 233 | static LIST_HEAD(acpi_table_attr_list); |
64 | static struct kobject *tables_kobj; | 234 | static struct kobject *tables_kobj; |
65 | static struct kobject *dynamic_tables_kobj; | 235 | static struct kobject *dynamic_tables_kobj; |
@@ -86,14 +256,12 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, | |||
86 | else | 256 | else |
87 | memcpy(name, "\0\0\0\0", 4); | 257 | memcpy(name, "\0\0\0\0", 4); |
88 | 258 | ||
89 | status = | 259 | status = acpi_get_table(name, table_attr->instance, &table_header); |
90 | acpi_get_table(name, table_attr->instance, | ||
91 | &table_header); | ||
92 | if (ACPI_FAILURE(status)) | 260 | if (ACPI_FAILURE(status)) |
93 | return -ENODEV; | 261 | return -ENODEV; |
94 | 262 | ||
95 | return memory_read_from_buffer(buf, count, &offset, | 263 | return memory_read_from_buffer(buf, count, &offset, |
96 | table_header, table_header->length); | 264 | table_header, table_header->length); |
97 | } | 265 | } |
98 | 266 | ||
99 | static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | 267 | static void acpi_table_attr_init(struct acpi_table_attr *table_attr, |
@@ -105,7 +273,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | |||
105 | sysfs_attr_init(&table_attr->attr.attr); | 273 | sysfs_attr_init(&table_attr->attr.attr); |
106 | if (table_header->signature[0] != '\0') | 274 | if (table_header->signature[0] != '\0') |
107 | memcpy(table_attr->name, table_header->signature, | 275 | memcpy(table_attr->name, table_header->signature, |
108 | ACPI_NAME_SIZE); | 276 | ACPI_NAME_SIZE); |
109 | else | 277 | else |
110 | memcpy(table_attr->name, "NULL", 4); | 278 | memcpy(table_attr->name, "NULL", 4); |
111 | 279 | ||
@@ -117,8 +285,8 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | |||
117 | table_attr->instance++; | 285 | table_attr->instance++; |
118 | 286 | ||
119 | if (table_attr->instance > 1 || (table_attr->instance == 1 && | 287 | if (table_attr->instance > 1 || (table_attr->instance == 1 && |
120 | !acpi_get_table | 288 | !acpi_get_table |
121 | (table_header->signature, 2, &header))) | 289 | (table_header->signature, 2, &header))) |
122 | sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", | 290 | sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", |
123 | table_attr->instance); | 291 | table_attr->instance); |
124 | 292 | ||
@@ -138,18 +306,17 @@ acpi_sysfs_table_handler(u32 event, void *table, void *context) | |||
138 | switch (event) { | 306 | switch (event) { |
139 | case ACPI_TABLE_EVENT_LOAD: | 307 | case ACPI_TABLE_EVENT_LOAD: |
140 | table_attr = | 308 | table_attr = |
141 | kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); | 309 | kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); |
142 | if (!table_attr) | 310 | if (!table_attr) |
143 | return AE_NO_MEMORY; | 311 | return AE_NO_MEMORY; |
144 | 312 | ||
145 | acpi_table_attr_init(table_attr, table); | 313 | acpi_table_attr_init(table_attr, table); |
146 | if (sysfs_create_bin_file(dynamic_tables_kobj, | 314 | if (sysfs_create_bin_file(dynamic_tables_kobj, |
147 | &table_attr->attr)) { | 315 | &table_attr->attr)) { |
148 | kfree(table_attr); | 316 | kfree(table_attr); |
149 | return AE_ERROR; | 317 | return AE_ERROR; |
150 | } else | 318 | } else |
151 | list_add_tail(&table_attr->node, | 319 | list_add_tail(&table_attr->node, &acpi_table_attr_list); |
152 | &acpi_table_attr_list); | ||
153 | break; | 320 | break; |
154 | case ACPI_TABLE_EVENT_UNLOAD: | 321 | case ACPI_TABLE_EVENT_UNLOAD: |
155 | /* | 322 | /* |
@@ -164,7 +331,7 @@ acpi_sysfs_table_handler(u32 event, void *table, void *context) | |||
164 | return AE_OK; | 331 | return AE_OK; |
165 | } | 332 | } |
166 | 333 | ||
167 | static int acpi_system_sysfs_init(void) | 334 | static int acpi_tables_sysfs_init(void) |
168 | { | 335 | { |
169 | struct acpi_table_attr *table_attr; | 336 | struct acpi_table_attr *table_attr; |
170 | struct acpi_table_header *table_header = NULL; | 337 | struct acpi_table_header *table_header = NULL; |
@@ -213,14 +380,17 @@ err: | |||
213 | } | 380 | } |
214 | 381 | ||
215 | /* | 382 | /* |
216 | * Detailed ACPI IRQ counters in /sys/firmware/acpi/interrupts/ | 383 | * Detailed ACPI IRQ counters: |
217 | * See Documentation/ABI/testing/sysfs-firmware-acpi | 384 | * /sys/firmware/acpi/interrupts/ |
218 | */ | 385 | */ |
219 | 386 | ||
387 | u32 acpi_irq_handled; | ||
388 | u32 acpi_irq_not_handled; | ||
389 | |||
220 | #define COUNT_GPE 0 | 390 | #define COUNT_GPE 0 |
221 | #define COUNT_SCI 1 /* acpi_irq_handled */ | 391 | #define COUNT_SCI 1 /* acpi_irq_handled */ |
222 | #define COUNT_SCI_NOT 2 /* acpi_irq_not_handled */ | 392 | #define COUNT_SCI_NOT 2 /* acpi_irq_not_handled */ |
223 | #define COUNT_ERROR 3 /* other */ | 393 | #define COUNT_ERROR 3 /* other */ |
224 | #define NUM_COUNTERS_EXTRA 4 | 394 | #define NUM_COUNTERS_EXTRA 4 |
225 | 395 | ||
226 | struct event_counter { | 396 | struct event_counter { |
@@ -237,6 +407,7 @@ static u32 acpi_gpe_count; | |||
237 | static struct attribute_group interrupt_stats_attr_group = { | 407 | static struct attribute_group interrupt_stats_attr_group = { |
238 | .name = "interrupts", | 408 | .name = "interrupts", |
239 | }; | 409 | }; |
410 | |||
240 | static struct kobj_attribute *counter_attrs; | 411 | static struct kobj_attribute *counter_attrs; |
241 | 412 | ||
242 | static void delete_gpe_attr_array(void) | 413 | static void delete_gpe_attr_array(void) |
@@ -269,8 +440,8 @@ void acpi_os_gpe_count(u32 gpe_number) | |||
269 | if (gpe_number < num_gpes) | 440 | if (gpe_number < num_gpes) |
270 | all_counters[gpe_number].count++; | 441 | all_counters[gpe_number].count++; |
271 | else | 442 | else |
272 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]. | 443 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + |
273 | count++; | 444 | COUNT_ERROR].count++; |
274 | 445 | ||
275 | return; | 446 | return; |
276 | } | 447 | } |
@@ -283,13 +454,14 @@ void acpi_os_fixed_event_count(u32 event_number) | |||
283 | if (event_number < ACPI_NUM_FIXED_EVENTS) | 454 | if (event_number < ACPI_NUM_FIXED_EVENTS) |
284 | all_counters[num_gpes + event_number].count++; | 455 | all_counters[num_gpes + event_number].count++; |
285 | else | 456 | else |
286 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]. | 457 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + |
287 | count++; | 458 | COUNT_ERROR].count++; |
288 | 459 | ||
289 | return; | 460 | return; |
290 | } | 461 | } |
291 | 462 | ||
292 | static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) | 463 | static int get_status(u32 index, acpi_event_status *status, |
464 | acpi_handle *handle) | ||
293 | { | 465 | { |
294 | int result = 0; | 466 | int result = 0; |
295 | 467 | ||
@@ -300,7 +472,7 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) | |||
300 | result = acpi_get_gpe_device(index, handle); | 472 | result = acpi_get_gpe_device(index, handle); |
301 | if (result) { | 473 | if (result) { |
302 | ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, | 474 | ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, |
303 | "Invalid GPE 0x%x\n", index)); | 475 | "Invalid GPE 0x%x\n", index)); |
304 | goto end; | 476 | goto end; |
305 | } | 477 | } |
306 | result = acpi_get_gpe_status(*handle, index, status); | 478 | result = acpi_get_gpe_status(*handle, index, status); |
@@ -312,7 +484,7 @@ end: | |||
312 | } | 484 | } |
313 | 485 | ||
314 | static ssize_t counter_show(struct kobject *kobj, | 486 | static ssize_t counter_show(struct kobject *kobj, |
315 | struct kobj_attribute *attr, char *buf) | 487 | struct kobj_attribute *attr, char *buf) |
316 | { | 488 | { |
317 | int index = attr - counter_attrs; | 489 | int index = attr - counter_attrs; |
318 | int size; | 490 | int size; |
@@ -321,12 +493,11 @@ static ssize_t counter_show(struct kobject *kobj, | |||
321 | int result = 0; | 493 | int result = 0; |
322 | 494 | ||
323 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count = | 495 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count = |
324 | acpi_irq_handled; | 496 | acpi_irq_handled; |
325 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count = | 497 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count = |
326 | acpi_irq_not_handled; | 498 | acpi_irq_not_handled; |
327 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count = | 499 | all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count = |
328 | acpi_gpe_count; | 500 | acpi_gpe_count; |
329 | |||
330 | size = sprintf(buf, "%8d", all_counters[index].count); | 501 | size = sprintf(buf, "%8d", all_counters[index].count); |
331 | 502 | ||
332 | /* "gpe_all" or "sci" */ | 503 | /* "gpe_all" or "sci" */ |
@@ -338,13 +509,13 @@ static ssize_t counter_show(struct kobject *kobj, | |||
338 | goto end; | 509 | goto end; |
339 | 510 | ||
340 | if (!(status & ACPI_EVENT_FLAG_HANDLE)) | 511 | if (!(status & ACPI_EVENT_FLAG_HANDLE)) |
341 | size += sprintf(buf + size, " invalid"); | 512 | size += sprintf(buf + size, " invalid"); |
342 | else if (status & ACPI_EVENT_FLAG_ENABLED) | 513 | else if (status & ACPI_EVENT_FLAG_ENABLED) |
343 | size += sprintf(buf + size, " enabled"); | 514 | size += sprintf(buf + size, " enabled"); |
344 | else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) | 515 | else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) |
345 | size += sprintf(buf + size, " wake_enabled"); | 516 | size += sprintf(buf + size, " wake_enabled"); |
346 | else | 517 | else |
347 | size += sprintf(buf + size, " disabled"); | 518 | size += sprintf(buf + size, " disabled"); |
348 | 519 | ||
349 | end: | 520 | end: |
350 | size += sprintf(buf + size, "\n"); | 521 | size += sprintf(buf + size, "\n"); |
@@ -357,7 +528,8 @@ end: | |||
357 | * enable/disable/clear a gpe/fixed event in user space. | 528 | * enable/disable/clear a gpe/fixed event in user space. |
358 | */ | 529 | */ |
359 | static ssize_t counter_set(struct kobject *kobj, | 530 | static ssize_t counter_set(struct kobject *kobj, |
360 | struct kobj_attribute *attr, const char *buf, size_t size) | 531 | struct kobj_attribute *attr, const char *buf, |
532 | size_t size) | ||
361 | { | 533 | { |
362 | int index = attr - counter_attrs; | 534 | int index = attr - counter_attrs; |
363 | acpi_event_status status; | 535 | acpi_event_status status; |
@@ -381,32 +553,32 @@ static ssize_t counter_set(struct kobject *kobj, | |||
381 | 553 | ||
382 | if (!(status & ACPI_EVENT_FLAG_HANDLE)) { | 554 | if (!(status & ACPI_EVENT_FLAG_HANDLE)) { |
383 | printk(KERN_WARNING PREFIX | 555 | printk(KERN_WARNING PREFIX |
384 | "Can not change Invalid GPE/Fixed Event status\n"); | 556 | "Can not change Invalid GPE/Fixed Event status\n"); |
385 | return -EINVAL; | 557 | return -EINVAL; |
386 | } | 558 | } |
387 | 559 | ||
388 | if (index < num_gpes) { | 560 | if (index < num_gpes) { |
389 | if (!strcmp(buf, "disable\n") && | 561 | if (!strcmp(buf, "disable\n") && |
390 | (status & ACPI_EVENT_FLAG_ENABLED)) | 562 | (status & ACPI_EVENT_FLAG_ENABLED)) |
391 | result = acpi_disable_gpe(handle, index); | 563 | result = acpi_disable_gpe(handle, index); |
392 | else if (!strcmp(buf, "enable\n") && | 564 | else if (!strcmp(buf, "enable\n") && |
393 | !(status & ACPI_EVENT_FLAG_ENABLED)) | 565 | !(status & ACPI_EVENT_FLAG_ENABLED)) |
394 | result = acpi_enable_gpe(handle, index); | 566 | result = acpi_enable_gpe(handle, index); |
395 | else if (!strcmp(buf, "clear\n") && | 567 | else if (!strcmp(buf, "clear\n") && |
396 | (status & ACPI_EVENT_FLAG_SET)) | 568 | (status & ACPI_EVENT_FLAG_SET)) |
397 | result = acpi_clear_gpe(handle, index); | 569 | result = acpi_clear_gpe(handle, index); |
398 | else | 570 | else |
399 | all_counters[index].count = strtoul(buf, NULL, 0); | 571 | all_counters[index].count = strtoul(buf, NULL, 0); |
400 | } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { | 572 | } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { |
401 | int event = index - num_gpes; | 573 | int event = index - num_gpes; |
402 | if (!strcmp(buf, "disable\n") && | 574 | if (!strcmp(buf, "disable\n") && |
403 | (status & ACPI_EVENT_FLAG_ENABLED)) | 575 | (status & ACPI_EVENT_FLAG_ENABLED)) |
404 | result = acpi_disable_event(event, ACPI_NOT_ISR); | 576 | result = acpi_disable_event(event, ACPI_NOT_ISR); |
405 | else if (!strcmp(buf, "enable\n") && | 577 | else if (!strcmp(buf, "enable\n") && |
406 | !(status & ACPI_EVENT_FLAG_ENABLED)) | 578 | !(status & ACPI_EVENT_FLAG_ENABLED)) |
407 | result = acpi_enable_event(event, ACPI_NOT_ISR); | 579 | result = acpi_enable_event(event, ACPI_NOT_ISR); |
408 | else if (!strcmp(buf, "clear\n") && | 580 | else if (!strcmp(buf, "clear\n") && |
409 | (status & ACPI_EVENT_FLAG_SET)) | 581 | (status & ACPI_EVENT_FLAG_SET)) |
410 | result = acpi_clear_event(event); | 582 | result = acpi_clear_event(event); |
411 | else | 583 | else |
412 | all_counters[index].count = strtoul(buf, NULL, 0); | 584 | all_counters[index].count = strtoul(buf, NULL, 0); |
@@ -430,17 +602,17 @@ void acpi_irq_stats_init(void) | |||
430 | num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA; | 602 | num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA; |
431 | 603 | ||
432 | all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1), | 604 | all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1), |
433 | GFP_KERNEL); | 605 | GFP_KERNEL); |
434 | if (all_attrs == NULL) | 606 | if (all_attrs == NULL) |
435 | return; | 607 | return; |
436 | 608 | ||
437 | all_counters = kzalloc(sizeof(struct event_counter) * (num_counters), | 609 | all_counters = kzalloc(sizeof(struct event_counter) * (num_counters), |
438 | GFP_KERNEL); | 610 | GFP_KERNEL); |
439 | if (all_counters == NULL) | 611 | if (all_counters == NULL) |
440 | goto fail; | 612 | goto fail; |
441 | 613 | ||
442 | counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), | 614 | counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), |
443 | GFP_KERNEL); | 615 | GFP_KERNEL); |
444 | if (counter_attrs == NULL) | 616 | if (counter_attrs == NULL) |
445 | goto fail; | 617 | goto fail; |
446 | 618 | ||
@@ -503,135 +675,11 @@ static void __exit interrupt_stats_exit(void) | |||
503 | return; | 675 | return; |
504 | } | 676 | } |
505 | 677 | ||
506 | /* -------------------------------------------------------------------------- | 678 | int __init acpi_sysfs_init(void) |
507 | FS Interface (/proc) | ||
508 | -------------------------------------------------------------------------- */ | ||
509 | #ifdef CONFIG_ACPI_PROCFS | ||
510 | #define ACPI_SYSTEM_FILE_INFO "info" | ||
511 | #define ACPI_SYSTEM_FILE_EVENT "event" | ||
512 | #define ACPI_SYSTEM_FILE_DSDT "dsdt" | ||
513 | #define ACPI_SYSTEM_FILE_FADT "fadt" | ||
514 | |||
515 | static int acpi_system_read_info(struct seq_file *seq, void *offset) | ||
516 | { | ||
517 | |||
518 | seq_printf(seq, "version: %x\n", ACPI_CA_VERSION); | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int acpi_system_info_open_fs(struct inode *inode, struct file *file) | ||
523 | { | ||
524 | return single_open(file, acpi_system_read_info, PDE(inode)->data); | ||
525 | } | ||
526 | |||
527 | static const struct file_operations acpi_system_info_ops = { | ||
528 | .owner = THIS_MODULE, | ||
529 | .open = acpi_system_info_open_fs, | ||
530 | .read = seq_read, | ||
531 | .llseek = seq_lseek, | ||
532 | .release = single_release, | ||
533 | }; | ||
534 | |||
535 | static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t, | ||
536 | loff_t *); | ||
537 | |||
538 | static const struct file_operations acpi_system_dsdt_ops = { | ||
539 | .owner = THIS_MODULE, | ||
540 | .read = acpi_system_read_dsdt, | ||
541 | }; | ||
542 | |||
543 | static ssize_t | ||
544 | acpi_system_read_dsdt(struct file *file, | ||
545 | char __user * buffer, size_t count, loff_t * ppos) | ||
546 | { | ||
547 | acpi_status status = AE_OK; | ||
548 | struct acpi_table_header *dsdt = NULL; | ||
549 | ssize_t res; | ||
550 | |||
551 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt); | ||
552 | if (ACPI_FAILURE(status)) | ||
553 | return -ENODEV; | ||
554 | |||
555 | res = simple_read_from_buffer(buffer, count, ppos, dsdt, dsdt->length); | ||
556 | |||
557 | return res; | ||
558 | } | ||
559 | |||
560 | static ssize_t acpi_system_read_fadt(struct file *, char __user *, size_t, | ||
561 | loff_t *); | ||
562 | |||
563 | static const struct file_operations acpi_system_fadt_ops = { | ||
564 | .owner = THIS_MODULE, | ||
565 | .read = acpi_system_read_fadt, | ||
566 | }; | ||
567 | |||
568 | static ssize_t | ||
569 | acpi_system_read_fadt(struct file *file, | ||
570 | char __user * buffer, size_t count, loff_t * ppos) | ||
571 | { | ||
572 | acpi_status status = AE_OK; | ||
573 | struct acpi_table_header *fadt = NULL; | ||
574 | ssize_t res; | ||
575 | |||
576 | status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt); | ||
577 | if (ACPI_FAILURE(status)) | ||
578 | return -ENODEV; | ||
579 | |||
580 | res = simple_read_from_buffer(buffer, count, ppos, fadt, fadt->length); | ||
581 | |||
582 | return res; | ||
583 | } | ||
584 | |||
585 | static int acpi_system_procfs_init(void) | ||
586 | { | ||
587 | struct proc_dir_entry *entry; | ||
588 | int error = 0; | ||
589 | |||
590 | /* 'info' [R] */ | ||
591 | entry = proc_create(ACPI_SYSTEM_FILE_INFO, S_IRUGO, acpi_root_dir, | ||
592 | &acpi_system_info_ops); | ||
593 | if (!entry) | ||
594 | goto Error; | ||
595 | |||
596 | /* 'dsdt' [R] */ | ||
597 | entry = proc_create(ACPI_SYSTEM_FILE_DSDT, S_IRUSR, acpi_root_dir, | ||
598 | &acpi_system_dsdt_ops); | ||
599 | if (!entry) | ||
600 | goto Error; | ||
601 | |||
602 | /* 'fadt' [R] */ | ||
603 | entry = proc_create(ACPI_SYSTEM_FILE_FADT, S_IRUSR, acpi_root_dir, | ||
604 | &acpi_system_fadt_ops); | ||
605 | if (!entry) | ||
606 | goto Error; | ||
607 | |||
608 | Done: | ||
609 | return error; | ||
610 | |||
611 | Error: | ||
612 | remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir); | ||
613 | remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir); | ||
614 | remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir); | ||
615 | |||
616 | error = -EFAULT; | ||
617 | goto Done; | ||
618 | } | ||
619 | #else | ||
620 | static int acpi_system_procfs_init(void) | ||
621 | { | ||
622 | return 0; | ||
623 | } | ||
624 | #endif | ||
625 | |||
626 | int __init acpi_system_init(void) | ||
627 | { | 679 | { |
628 | int result; | 680 | int result; |
629 | 681 | ||
630 | result = acpi_system_procfs_init(); | 682 | result = acpi_tables_sysfs_init(); |
631 | if (result) | ||
632 | return result; | ||
633 | |||
634 | result = acpi_system_sysfs_init(); | ||
635 | 683 | ||
636 | return result; | 684 | return result; |
637 | } | 685 | } |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index efad1f33aeb5..2f8f17131d9f 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -37,10 +37,14 @@ | |||
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/types.h> | 39 | #include <linux/types.h> |
40 | |||
41 | #ifdef CONFIG_ACPI_PROCFS | ||
40 | #include <linux/proc_fs.h> | 42 | #include <linux/proc_fs.h> |
43 | #include <linux/seq_file.h> | ||
44 | #endif | ||
45 | |||
41 | #include <linux/jiffies.h> | 46 | #include <linux/jiffies.h> |
42 | #include <linux/kmod.h> | 47 | #include <linux/kmod.h> |
43 | #include <linux/seq_file.h> | ||
44 | #include <linux/reboot.h> | 48 | #include <linux/reboot.h> |
45 | #include <linux/device.h> | 49 | #include <linux/device.h> |
46 | #include <asm/uaccess.h> | 50 | #include <asm/uaccess.h> |
@@ -102,16 +106,6 @@ static int acpi_thermal_add(struct acpi_device *device); | |||
102 | static int acpi_thermal_remove(struct acpi_device *device, int type); | 106 | static int acpi_thermal_remove(struct acpi_device *device, int type); |
103 | static int acpi_thermal_resume(struct acpi_device *device); | 107 | static int acpi_thermal_resume(struct acpi_device *device); |
104 | static void acpi_thermal_notify(struct acpi_device *device, u32 event); | 108 | static void acpi_thermal_notify(struct acpi_device *device, u32 event); |
105 | static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); | ||
106 | static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); | ||
107 | static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); | ||
108 | static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); | ||
109 | static ssize_t acpi_thermal_write_cooling_mode(struct file *, | ||
110 | const char __user *, size_t, | ||
111 | loff_t *); | ||
112 | static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file); | ||
113 | static ssize_t acpi_thermal_write_polling(struct file *, const char __user *, | ||
114 | size_t, loff_t *); | ||
115 | 109 | ||
116 | static const struct acpi_device_id thermal_device_ids[] = { | 110 | static const struct acpi_device_id thermal_device_ids[] = { |
117 | {ACPI_THERMAL_HID, 0}, | 111 | {ACPI_THERMAL_HID, 0}, |
@@ -201,6 +195,18 @@ struct acpi_thermal { | |||
201 | struct mutex lock; | 195 | struct mutex lock; |
202 | }; | 196 | }; |
203 | 197 | ||
198 | #ifdef CONFIG_ACPI_PROCFS | ||
199 | static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); | ||
200 | static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); | ||
201 | static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); | ||
202 | static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); | ||
203 | static ssize_t acpi_thermal_write_cooling_mode(struct file *, | ||
204 | const char __user *, size_t, | ||
205 | loff_t *); | ||
206 | static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file); | ||
207 | static ssize_t acpi_thermal_write_polling(struct file *, const char __user *, | ||
208 | size_t, loff_t *); | ||
209 | |||
204 | static const struct file_operations acpi_thermal_state_fops = { | 210 | static const struct file_operations acpi_thermal_state_fops = { |
205 | .owner = THIS_MODULE, | 211 | .owner = THIS_MODULE, |
206 | .open = acpi_thermal_state_open_fs, | 212 | .open = acpi_thermal_state_open_fs, |
@@ -242,6 +248,7 @@ static const struct file_operations acpi_thermal_polling_fops = { | |||
242 | .llseek = seq_lseek, | 248 | .llseek = seq_lseek, |
243 | .release = single_release, | 249 | .release = single_release, |
244 | }; | 250 | }; |
251 | #endif /* CONFIG_ACPI_PROCFS*/ | ||
245 | 252 | ||
246 | /* -------------------------------------------------------------------------- | 253 | /* -------------------------------------------------------------------------- |
247 | Thermal Zone Management | 254 | Thermal Zone Management |
@@ -287,26 +294,6 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz) | |||
287 | return 0; | 294 | return 0; |
288 | } | 295 | } |
289 | 296 | ||
290 | static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds) | ||
291 | { | ||
292 | |||
293 | if (!tz) | ||
294 | return -EINVAL; | ||
295 | |||
296 | tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */ | ||
297 | |||
298 | tz->thermal_zone->polling_delay = seconds * 1000; | ||
299 | |||
300 | if (tz->tz_enabled) | ||
301 | thermal_zone_device_update(tz->thermal_zone); | ||
302 | |||
303 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
304 | "Polling frequency set to %lu seconds\n", | ||
305 | tz->polling_frequency/10)); | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) | 297 | static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) |
311 | { | 298 | { |
312 | acpi_status status = AE_OK; | 299 | acpi_status status = AE_OK; |
@@ -973,7 +960,7 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) | |||
973 | /* -------------------------------------------------------------------------- | 960 | /* -------------------------------------------------------------------------- |
974 | FS Interface (/proc) | 961 | FS Interface (/proc) |
975 | -------------------------------------------------------------------------- */ | 962 | -------------------------------------------------------------------------- */ |
976 | 963 | #ifdef CONFIG_ACPI_PROCFS | |
977 | static struct proc_dir_entry *acpi_thermal_dir; | 964 | static struct proc_dir_entry *acpi_thermal_dir; |
978 | 965 | ||
979 | static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) | 966 | static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) |
@@ -1187,6 +1174,26 @@ static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file) | |||
1187 | PDE(inode)->data); | 1174 | PDE(inode)->data); |
1188 | } | 1175 | } |
1189 | 1176 | ||
1177 | static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds) | ||
1178 | { | ||
1179 | if (!tz) | ||
1180 | return -EINVAL; | ||
1181 | |||
1182 | /* Convert value to deci-seconds */ | ||
1183 | tz->polling_frequency = seconds * 10; | ||
1184 | |||
1185 | tz->thermal_zone->polling_delay = seconds * 1000; | ||
1186 | |||
1187 | if (tz->tz_enabled) | ||
1188 | thermal_zone_device_update(tz->thermal_zone); | ||
1189 | |||
1190 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
1191 | "Polling frequency set to %lu seconds\n", | ||
1192 | tz->polling_frequency/10)); | ||
1193 | |||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1190 | static ssize_t | 1197 | static ssize_t |
1191 | acpi_thermal_write_polling(struct file *file, | 1198 | acpi_thermal_write_polling(struct file *file, |
1192 | const char __user * buffer, | 1199 | const char __user * buffer, |
@@ -1295,7 +1302,13 @@ static int acpi_thermal_remove_fs(struct acpi_device *device) | |||
1295 | 1302 | ||
1296 | return 0; | 1303 | return 0; |
1297 | } | 1304 | } |
1298 | 1305 | #else | |
1306 | static inline int acpi_thermal_add_fs(struct acpi_device *device) { return 0; } | ||
1307 | static inline int acpi_thermal_remove_fs(struct acpi_device *device) | ||
1308 | { | ||
1309 | return 0; | ||
1310 | } | ||
1311 | #endif /* CONFIG_ACPI_PROCFS */ | ||
1299 | /* -------------------------------------------------------------------------- | 1312 | /* -------------------------------------------------------------------------- |
1300 | Driver Interface | 1313 | Driver Interface |
1301 | -------------------------------------------------------------------------- */ | 1314 | -------------------------------------------------------------------------- */ |
@@ -1566,13 +1579,18 @@ static int __init acpi_thermal_init(void) | |||
1566 | printk(KERN_NOTICE "ACPI: thermal control disabled\n"); | 1579 | printk(KERN_NOTICE "ACPI: thermal control disabled\n"); |
1567 | return -ENODEV; | 1580 | return -ENODEV; |
1568 | } | 1581 | } |
1582 | |||
1583 | #ifdef CONFIG_ACPI_PROCFS | ||
1569 | acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); | 1584 | acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); |
1570 | if (!acpi_thermal_dir) | 1585 | if (!acpi_thermal_dir) |
1571 | return -ENODEV; | 1586 | return -ENODEV; |
1587 | #endif | ||
1572 | 1588 | ||
1573 | result = acpi_bus_register_driver(&acpi_thermal_driver); | 1589 | result = acpi_bus_register_driver(&acpi_thermal_driver); |
1574 | if (result < 0) { | 1590 | if (result < 0) { |
1591 | #ifdef CONFIG_ACPI_PROCFS | ||
1575 | remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); | 1592 | remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); |
1593 | #endif | ||
1576 | return -ENODEV; | 1594 | return -ENODEV; |
1577 | } | 1595 | } |
1578 | 1596 | ||
@@ -1584,7 +1602,9 @@ static void __exit acpi_thermal_exit(void) | |||
1584 | 1602 | ||
1585 | acpi_bus_unregister_driver(&acpi_thermal_driver); | 1603 | acpi_bus_unregister_driver(&acpi_thermal_driver); |
1586 | 1604 | ||
1605 | #ifdef CONFIG_ACPI_PROCFS | ||
1587 | remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); | 1606 | remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); |
1607 | #endif | ||
1588 | 1608 | ||
1589 | return; | 1609 | return; |
1590 | } | 1610 | } |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 9865d46f49a8..67dec0c675aa 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -152,7 +152,9 @@ struct acpi_video_bus { | |||
152 | struct acpi_video_bus_flags flags; | 152 | struct acpi_video_bus_flags flags; |
153 | struct list_head video_device_list; | 153 | struct list_head video_device_list; |
154 | struct mutex device_list_lock; /* protects video_device_list */ | 154 | struct mutex device_list_lock; /* protects video_device_list */ |
155 | #ifdef CONFIG_ACPI_PROCFS | ||
155 | struct proc_dir_entry *dir; | 156 | struct proc_dir_entry *dir; |
157 | #endif | ||
156 | struct input_dev *input; | 158 | struct input_dev *input; |
157 | char phys[32]; /* for input device */ | 159 | char phys[32]; /* for input device */ |
158 | struct notifier_block pm_nb; | 160 | struct notifier_block pm_nb; |
@@ -208,6 +210,7 @@ struct acpi_video_device { | |||
208 | struct output_device *output_dev; | 210 | struct output_device *output_dev; |
209 | }; | 211 | }; |
210 | 212 | ||
213 | #ifdef CONFIG_ACPI_PROCFS | ||
211 | /* bus */ | 214 | /* bus */ |
212 | static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file); | 215 | static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file); |
213 | static const struct file_operations acpi_video_bus_info_fops = { | 216 | static const struct file_operations acpi_video_bus_info_fops = { |
@@ -307,6 +310,7 @@ static const struct file_operations acpi_video_device_EDID_fops = { | |||
307 | .llseek = seq_lseek, | 310 | .llseek = seq_lseek, |
308 | .release = single_release, | 311 | .release = single_release, |
309 | }; | 312 | }; |
313 | #endif /* CONFIG_ACPI_PROCFS */ | ||
310 | 314 | ||
311 | static const char device_decode[][30] = { | 315 | static const char device_decode[][30] = { |
312 | "motherboard VGA device", | 316 | "motherboard VGA device", |
@@ -450,16 +454,6 @@ static struct thermal_cooling_device_ops video_cooling_ops = { | |||
450 | /* device */ | 454 | /* device */ |
451 | 455 | ||
452 | static int | 456 | static int |
453 | acpi_video_device_query(struct acpi_video_device *device, unsigned long long *state) | ||
454 | { | ||
455 | int status; | ||
456 | |||
457 | status = acpi_evaluate_integer(device->dev->handle, "_DGS", NULL, state); | ||
458 | |||
459 | return status; | ||
460 | } | ||
461 | |||
462 | static int | ||
463 | acpi_video_device_get_state(struct acpi_video_device *device, | 457 | acpi_video_device_get_state(struct acpi_video_device *device, |
464 | unsigned long long *state) | 458 | unsigned long long *state) |
465 | { | 459 | { |
@@ -698,46 +692,6 @@ acpi_video_device_EDID(struct acpi_video_device *device, | |||
698 | 692 | ||
699 | /* bus */ | 693 | /* bus */ |
700 | 694 | ||
701 | static int | ||
702 | acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) | ||
703 | { | ||
704 | int status; | ||
705 | unsigned long long tmp; | ||
706 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
707 | struct acpi_object_list args = { 1, &arg0 }; | ||
708 | |||
709 | |||
710 | arg0.integer.value = option; | ||
711 | |||
712 | status = acpi_evaluate_integer(video->device->handle, "_SPD", &args, &tmp); | ||
713 | if (ACPI_SUCCESS(status)) | ||
714 | status = tmp ? (-EINVAL) : (AE_OK); | ||
715 | |||
716 | return status; | ||
717 | } | ||
718 | |||
719 | static int | ||
720 | acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id) | ||
721 | { | ||
722 | int status; | ||
723 | |||
724 | status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id); | ||
725 | |||
726 | return status; | ||
727 | } | ||
728 | |||
729 | static int | ||
730 | acpi_video_bus_POST_options(struct acpi_video_bus *video, | ||
731 | unsigned long long *options) | ||
732 | { | ||
733 | int status; | ||
734 | |||
735 | status = acpi_evaluate_integer(video->device->handle, "_VPO", NULL, options); | ||
736 | *options &= 3; | ||
737 | |||
738 | return status; | ||
739 | } | ||
740 | |||
741 | /* | 695 | /* |
742 | * Arg: | 696 | * Arg: |
743 | * video : video bus device pointer | 697 | * video : video bus device pointer |
@@ -1159,6 +1113,7 @@ static int acpi_video_bus_check(struct acpi_video_bus *video) | |||
1159 | /* -------------------------------------------------------------------------- | 1113 | /* -------------------------------------------------------------------------- |
1160 | FS Interface (/proc) | 1114 | FS Interface (/proc) |
1161 | -------------------------------------------------------------------------- */ | 1115 | -------------------------------------------------------------------------- */ |
1116 | #ifdef CONFIG_ACPI_PROCFS | ||
1162 | 1117 | ||
1163 | static struct proc_dir_entry *acpi_video_dir; | 1118 | static struct proc_dir_entry *acpi_video_dir; |
1164 | 1119 | ||
@@ -1198,6 +1153,18 @@ acpi_video_device_info_open_fs(struct inode *inode, struct file *file) | |||
1198 | PDE(inode)->data); | 1153 | PDE(inode)->data); |
1199 | } | 1154 | } |
1200 | 1155 | ||
1156 | static int | ||
1157 | acpi_video_device_query(struct acpi_video_device *device, | ||
1158 | unsigned long long *state) | ||
1159 | { | ||
1160 | int status; | ||
1161 | |||
1162 | status = acpi_evaluate_integer(device->dev->handle, "_DGS", | ||
1163 | NULL, state); | ||
1164 | |||
1165 | return status; | ||
1166 | } | ||
1167 | |||
1201 | static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) | 1168 | static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) |
1202 | { | 1169 | { |
1203 | int status; | 1170 | int status; |
@@ -1492,6 +1459,19 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file) | |||
1492 | return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data); | 1459 | return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data); |
1493 | } | 1460 | } |
1494 | 1461 | ||
1462 | static int | ||
1463 | acpi_video_bus_POST_options(struct acpi_video_bus *video, | ||
1464 | unsigned long long *options) | ||
1465 | { | ||
1466 | int status; | ||
1467 | |||
1468 | status = acpi_evaluate_integer(video->device->handle, "_VPO", | ||
1469 | NULL, options); | ||
1470 | *options &= 3; | ||
1471 | |||
1472 | return status; | ||
1473 | } | ||
1474 | |||
1495 | static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) | 1475 | static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) |
1496 | { | 1476 | { |
1497 | struct acpi_video_bus *video = seq->private; | 1477 | struct acpi_video_bus *video = seq->private; |
@@ -1530,6 +1510,16 @@ acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file) | |||
1530 | PDE(inode)->data); | 1510 | PDE(inode)->data); |
1531 | } | 1511 | } |
1532 | 1512 | ||
1513 | static int | ||
1514 | acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id) | ||
1515 | { | ||
1516 | int status; | ||
1517 | |||
1518 | status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id); | ||
1519 | |||
1520 | return status; | ||
1521 | } | ||
1522 | |||
1533 | static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) | 1523 | static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) |
1534 | { | 1524 | { |
1535 | struct acpi_video_bus *video = seq->private; | 1525 | struct acpi_video_bus *video = seq->private; |
@@ -1572,6 +1562,25 @@ static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file) | |||
1572 | return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data); | 1562 | return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data); |
1573 | } | 1563 | } |
1574 | 1564 | ||
1565 | static int | ||
1566 | acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) | ||
1567 | { | ||
1568 | int status; | ||
1569 | unsigned long long tmp; | ||
1570 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
1571 | struct acpi_object_list args = { 1, &arg0 }; | ||
1572 | |||
1573 | |||
1574 | arg0.integer.value = option; | ||
1575 | |||
1576 | status = acpi_evaluate_integer(video->device->handle, "_SPD", | ||
1577 | &args, &tmp); | ||
1578 | if (ACPI_SUCCESS(status)) | ||
1579 | status = tmp ? (-EINVAL) : (AE_OK); | ||
1580 | |||
1581 | return status; | ||
1582 | } | ||
1583 | |||
1575 | static ssize_t | 1584 | static ssize_t |
1576 | acpi_video_bus_write_POST(struct file *file, | 1585 | acpi_video_bus_write_POST(struct file *file, |
1577 | const char __user * buffer, | 1586 | const char __user * buffer, |
@@ -1722,6 +1731,24 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device) | |||
1722 | 1731 | ||
1723 | return 0; | 1732 | return 0; |
1724 | } | 1733 | } |
1734 | #else | ||
1735 | static inline int acpi_video_device_add_fs(struct acpi_device *device) | ||
1736 | { | ||
1737 | return 0; | ||
1738 | } | ||
1739 | static inline int acpi_video_device_remove_fs(struct acpi_device *device) | ||
1740 | { | ||
1741 | return 0; | ||
1742 | } | ||
1743 | static inline int acpi_video_bus_add_fs(struct acpi_device *device) | ||
1744 | { | ||
1745 | return 0; | ||
1746 | } | ||
1747 | static inline int acpi_video_bus_remove_fs(struct acpi_device *device) | ||
1748 | { | ||
1749 | return 0; | ||
1750 | } | ||
1751 | #endif /* CONFIG_ACPI_PROCFS */ | ||
1725 | 1752 | ||
1726 | /* -------------------------------------------------------------------------- | 1753 | /* -------------------------------------------------------------------------- |
1727 | Driver Interface | 1754 | Driver Interface |
@@ -2140,7 +2167,7 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, | |||
2140 | status = acpi_video_bus_get_one_device(dev, video); | 2167 | status = acpi_video_bus_get_one_device(dev, video); |
2141 | if (ACPI_FAILURE(status)) { | 2168 | if (ACPI_FAILURE(status)) { |
2142 | printk(KERN_WARNING PREFIX | 2169 | printk(KERN_WARNING PREFIX |
2143 | "Cant attach device"); | 2170 | "Cant attach device\n"); |
2144 | continue; | 2171 | continue; |
2145 | } | 2172 | } |
2146 | } | 2173 | } |
@@ -2150,19 +2177,19 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, | |||
2150 | static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | 2177 | static int acpi_video_bus_put_one_device(struct acpi_video_device *device) |
2151 | { | 2178 | { |
2152 | acpi_status status; | 2179 | acpi_status status; |
2153 | struct acpi_video_bus *video; | ||
2154 | |||
2155 | 2180 | ||
2156 | if (!device || !device->video) | 2181 | if (!device || !device->video) |
2157 | return -ENOENT; | 2182 | return -ENOENT; |
2158 | 2183 | ||
2159 | video = device->video; | ||
2160 | |||
2161 | acpi_video_device_remove_fs(device->dev); | 2184 | acpi_video_device_remove_fs(device->dev); |
2162 | 2185 | ||
2163 | status = acpi_remove_notify_handler(device->dev->handle, | 2186 | status = acpi_remove_notify_handler(device->dev->handle, |
2164 | ACPI_DEVICE_NOTIFY, | 2187 | ACPI_DEVICE_NOTIFY, |
2165 | acpi_video_device_notify); | 2188 | acpi_video_device_notify); |
2189 | if (ACPI_FAILURE(status)) { | ||
2190 | printk(KERN_WARNING PREFIX | ||
2191 | "Cant remove video notify handler\n"); | ||
2192 | } | ||
2166 | if (device->backlight) { | 2193 | if (device->backlight) { |
2167 | sysfs_remove_link(&device->backlight->dev.kobj, "device"); | 2194 | sysfs_remove_link(&device->backlight->dev.kobj, "device"); |
2168 | backlight_device_unregister(device->backlight); | 2195 | backlight_device_unregister(device->backlight); |
@@ -2557,9 +2584,11 @@ int acpi_video_register(void) | |||
2557 | return 0; | 2584 | return 0; |
2558 | } | 2585 | } |
2559 | 2586 | ||
2587 | #ifdef CONFIG_ACPI_PROCFS | ||
2560 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); | 2588 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); |
2561 | if (!acpi_video_dir) | 2589 | if (!acpi_video_dir) |
2562 | return -ENODEV; | 2590 | return -ENODEV; |
2591 | #endif | ||
2563 | 2592 | ||
2564 | result = acpi_bus_register_driver(&acpi_video_bus); | 2593 | result = acpi_bus_register_driver(&acpi_video_bus); |
2565 | if (result < 0) { | 2594 | if (result < 0) { |
@@ -2588,7 +2617,9 @@ void acpi_video_unregister(void) | |||
2588 | } | 2617 | } |
2589 | acpi_bus_unregister_driver(&acpi_video_bus); | 2618 | acpi_bus_unregister_driver(&acpi_video_bus); |
2590 | 2619 | ||
2620 | #ifdef CONFIG_ACPI_PROCFS | ||
2591 | remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); | 2621 | remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); |
2622 | #endif | ||
2592 | 2623 | ||
2593 | register_count = 0; | 2624 | register_count = 0; |
2594 | 2625 | ||
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index c80537bc3234..f62a50c3ed34 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c | |||
@@ -21,46 +21,18 @@ | |||
21 | ACPI_MODULE_NAME("wakeup_devices") | 21 | ACPI_MODULE_NAME("wakeup_devices") |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * acpi_enable_wakeup_device_prep - Prepare wake-up devices. | 24 | * acpi_enable_wakeup_devices - Enable wake-up device GPEs. |
25 | * @sleep_state: ACPI system sleep state. | 25 | * @sleep_state: ACPI system sleep state. |
26 | * | 26 | * |
27 | * Enable all wake-up devices' power, unless the requested system sleep state is | 27 | * Enable wakeup device power of devices with the state.enable flag set and set |
28 | * too deep. | 28 | * the wakeup enable mask bits in the GPE registers that correspond to wakeup |
29 | * devices. | ||
29 | */ | 30 | */ |
30 | void acpi_enable_wakeup_device_prep(u8 sleep_state) | 31 | void acpi_enable_wakeup_devices(u8 sleep_state) |
31 | { | 32 | { |
32 | struct list_head *node, *next; | 33 | struct list_head *node, *next; |
33 | 34 | ||
34 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | 35 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
35 | struct acpi_device *dev = container_of(node, | ||
36 | struct acpi_device, | ||
37 | wakeup_list); | ||
38 | |||
39 | if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled | ||
40 | || (sleep_state > (u32) dev->wakeup.sleep_state)) | ||
41 | continue; | ||
42 | |||
43 | acpi_enable_wakeup_device_power(dev, sleep_state); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * acpi_enable_wakeup_device - Enable wake-up device GPEs. | ||
49 | * @sleep_state: ACPI system sleep state. | ||
50 | * | ||
51 | * Enable all wake-up devices' GPEs, with the assumption that | ||
52 | * acpi_disable_all_gpes() was executed before, so we don't need to disable any | ||
53 | * GPEs here. | ||
54 | */ | ||
55 | void acpi_enable_wakeup_device(u8 sleep_state) | ||
56 | { | ||
57 | struct list_head *node, *next; | ||
58 | |||
59 | /* | ||
60 | * Caution: this routine must be invoked when interrupt is disabled | ||
61 | * Refer ACPI2.0: P212 | ||
62 | */ | ||
63 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | ||
64 | struct acpi_device *dev = | 36 | struct acpi_device *dev = |
65 | container_of(node, struct acpi_device, wakeup_list); | 37 | container_of(node, struct acpi_device, wakeup_list); |
66 | 38 | ||
@@ -69,6 +41,9 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
69 | || sleep_state > (u32) dev->wakeup.sleep_state) | 41 | || sleep_state > (u32) dev->wakeup.sleep_state) |
70 | continue; | 42 | continue; |
71 | 43 | ||
44 | if (dev->wakeup.state.enabled) | ||
45 | acpi_enable_wakeup_device_power(dev, sleep_state); | ||
46 | |||
72 | /* The wake-up power should have been enabled already. */ | 47 | /* The wake-up power should have been enabled already. */ |
73 | acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number, | 48 | acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
74 | ACPI_GPE_ENABLE); | 49 | ACPI_GPE_ENABLE); |
@@ -76,13 +51,10 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
76 | } | 51 | } |
77 | 52 | ||
78 | /** | 53 | /** |
79 | * acpi_disable_wakeup_device - Disable devices' wakeup capability. | 54 | * acpi_disable_wakeup_devices - Disable devices' wakeup capability. |
80 | * @sleep_state: ACPI system sleep state. | 55 | * @sleep_state: ACPI system sleep state. |
81 | * | ||
82 | * This function only affects devices with wakeup.state.enabled set, which means | ||
83 | * that it reverses the changes made by acpi_enable_wakeup_device_prep(). | ||
84 | */ | 56 | */ |
85 | void acpi_disable_wakeup_device(u8 sleep_state) | 57 | void acpi_disable_wakeup_devices(u8 sleep_state) |
86 | { | 58 | { |
87 | struct list_head *node, *next; | 59 | struct list_head *node, *next; |
88 | 60 | ||
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 7b5eea7e01dc..8b5ea399a4f4 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -145,12 +145,6 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, | |||
145 | struct ata_eh_info *ehi = &ap->link.eh_info; | 145 | struct ata_eh_info *ehi = &ap->link.eh_info; |
146 | int wait = 0; | 146 | int wait = 0; |
147 | unsigned long flags; | 147 | unsigned long flags; |
148 | acpi_handle handle; | ||
149 | |||
150 | if (dev) | ||
151 | handle = dev->acpi_handle; | ||
152 | else | ||
153 | handle = ap->acpi_handle; | ||
154 | 148 | ||
155 | spin_lock_irqsave(ap->lock, flags); | 149 | spin_lock_irqsave(ap->lock, flags); |
156 | /* | 150 | /* |
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index d4ed8e98edf7..280c9b5ad9e3 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig | |||
@@ -122,14 +122,6 @@ config ISCSI_IBFT_FIND | |||
122 | is necessary for iSCSI Boot Firmware Table Attributes module to work | 122 | is necessary for iSCSI Boot Firmware Table Attributes module to work |
123 | properly. | 123 | properly. |
124 | 124 | ||
125 | config ISCSI_BOOT_SYSFS | ||
126 | tristate "iSCSI Boot Sysfs Interface" | ||
127 | default n | ||
128 | help | ||
129 | This option enables support for exposing iSCSI boot information | ||
130 | via sysfs to userspace. If you wish to export this information, | ||
131 | say Y. Otherwise, say N. | ||
132 | |||
133 | config ISCSI_IBFT | 125 | config ISCSI_IBFT |
134 | tristate "iSCSI Boot Firmware Table Attributes module" | 126 | tristate "iSCSI Boot Firmware Table Attributes module" |
135 | select ISCSI_BOOT_SYSFS | 127 | select ISCSI_BOOT_SYSFS |
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 5fe7e1662922..1c3c17343dbe 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile | |||
@@ -10,5 +10,4 @@ obj-$(CONFIG_DCDBAS) += dcdbas.o | |||
10 | obj-$(CONFIG_DMIID) += dmi-id.o | 10 | obj-$(CONFIG_DMIID) += dmi-id.o |
11 | obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o | 11 | obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o |
12 | obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o | 12 | obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o |
13 | obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o | ||
14 | obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o | 13 | obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index f3adf18bfa05..0fba82943125 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -465,6 +465,7 @@ config SENSORS_JZ4740 | |||
465 | 465 | ||
466 | config SENSORS_JC42 | 466 | config SENSORS_JC42 |
467 | tristate "JEDEC JC42.4 compliant temperature sensors" | 467 | tristate "JEDEC JC42.4 compliant temperature sensors" |
468 | depends on I2C | ||
468 | help | 469 | help |
469 | If you say yes here you get support for Jedec JC42.4 compliant | 470 | If you say yes here you get support for Jedec JC42.4 compliant |
470 | temperature sensors. Support will include, but not be limited to, | 471 | temperature sensors. Support will include, but not be limited to, |
@@ -711,7 +712,8 @@ config SENSORS_PC87427 | |||
711 | functions of the National Semiconductor PC87427 Super-I/O chip. | 712 | functions of the National Semiconductor PC87427 Super-I/O chip. |
712 | The chip has two distinct logical devices, one for fan speed | 713 | The chip has two distinct logical devices, one for fan speed |
713 | monitoring and control, and one for voltage and temperature | 714 | monitoring and control, and one for voltage and temperature |
714 | monitoring. Only fan speed monitoring is supported right now. | 715 | monitoring. Fan speed monitoring and control are supported, as |
716 | well as temperature monitoring. Voltages aren't supported yet. | ||
715 | 717 | ||
716 | This driver can also be built as a module. If so, the module | 718 | This driver can also be built as a module. If so, the module |
717 | will be called pc87427. | 719 | will be called pc87427. |
@@ -804,6 +806,16 @@ config SENSORS_EMC1403 | |||
804 | Threshold values can be configured using sysfs. | 806 | Threshold values can be configured using sysfs. |
805 | Data from the different diodes are accessible via sysfs. | 807 | Data from the different diodes are accessible via sysfs. |
806 | 808 | ||
809 | config SENSORS_EMC2103 | ||
810 | tristate "SMSC EMC2103" | ||
811 | depends on I2C | ||
812 | help | ||
813 | If you say yes here you get support for the temperature | ||
814 | and fan sensors of the SMSC EMC2103 chips. | ||
815 | |||
816 | This driver can also be built as a module. If so, the module | ||
817 | will be called emc2103. | ||
818 | |||
807 | config SENSORS_SMSC47M1 | 819 | config SENSORS_SMSC47M1 |
808 | tristate "SMSC LPC47M10x and compatibles" | 820 | tristate "SMSC LPC47M10x and compatibles" |
809 | help | 821 | help |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 13d913e34dbf..e3c2484f6c5f 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -43,6 +43,7 @@ obj-$(CONFIG_SENSORS_PKGTEMP) += pkgtemp.o | |||
43 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o | 43 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o |
44 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o | 44 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o |
45 | obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o | 45 | obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o |
46 | obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o | ||
46 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o | 47 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o |
47 | obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o | 48 | obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o |
48 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o | 49 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o |
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index 3b973f30b1f6..89b4f3babe87 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c | |||
@@ -1150,9 +1150,6 @@ static int asc7621_detect(struct i2c_client *client, | |||
1150 | { | 1150 | { |
1151 | struct i2c_adapter *adapter = client->adapter; | 1151 | struct i2c_adapter *adapter = client->adapter; |
1152 | int company, verstep, chip_index; | 1152 | int company, verstep, chip_index; |
1153 | struct device *dev; | ||
1154 | |||
1155 | dev = &client->dev; | ||
1156 | 1153 | ||
1157 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 1154 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
1158 | return -ENODEV; | 1155 | return -ENODEV; |
@@ -1169,13 +1166,11 @@ static int asc7621_detect(struct i2c_client *client, | |||
1169 | 1166 | ||
1170 | if (company == asc7621_chips[chip_index].company_id && | 1167 | if (company == asc7621_chips[chip_index].company_id && |
1171 | verstep == asc7621_chips[chip_index].verstep_id) { | 1168 | verstep == asc7621_chips[chip_index].verstep_id) { |
1172 | strlcpy(client->name, asc7621_chips[chip_index].name, | ||
1173 | I2C_NAME_SIZE); | ||
1174 | strlcpy(info->type, asc7621_chips[chip_index].name, | 1169 | strlcpy(info->type, asc7621_chips[chip_index].name, |
1175 | I2C_NAME_SIZE); | 1170 | I2C_NAME_SIZE); |
1176 | 1171 | ||
1177 | dev_info(&adapter->dev, "Matched %s\n", | 1172 | dev_info(&adapter->dev, "Matched %s at 0x%02x\n", |
1178 | asc7621_chips[chip_index].name); | 1173 | asc7621_chips[chip_index].name, client->addr); |
1179 | return 0; | 1174 | return 0; |
1180 | } | 1175 | } |
1181 | } | 1176 | } |
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 0e4b5642638d..5b58b20dead1 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c | |||
@@ -89,6 +89,35 @@ static ssize_t store_temp(struct device *dev, | |||
89 | return count; | 89 | return count; |
90 | } | 90 | } |
91 | 91 | ||
92 | static ssize_t store_bit(struct device *dev, | ||
93 | struct device_attribute *attr, const char *buf, size_t count) | ||
94 | { | ||
95 | struct i2c_client *client = to_i2c_client(dev); | ||
96 | struct thermal_data *data = i2c_get_clientdata(client); | ||
97 | struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); | ||
98 | unsigned long val; | ||
99 | int retval; | ||
100 | |||
101 | if (strict_strtoul(buf, 10, &val)) | ||
102 | return -EINVAL; | ||
103 | |||
104 | mutex_lock(&data->mutex); | ||
105 | retval = i2c_smbus_read_byte_data(client, sda->nr); | ||
106 | if (retval < 0) | ||
107 | goto fail; | ||
108 | |||
109 | retval &= ~sda->index; | ||
110 | if (val) | ||
111 | retval |= sda->index; | ||
112 | |||
113 | retval = i2c_smbus_write_byte_data(client, sda->index, retval); | ||
114 | if (retval == 0) | ||
115 | retval = count; | ||
116 | fail: | ||
117 | mutex_unlock(&data->mutex); | ||
118 | return retval; | ||
119 | } | ||
120 | |||
92 | static ssize_t show_hyst(struct device *dev, | 121 | static ssize_t show_hyst(struct device *dev, |
93 | struct device_attribute *attr, char *buf) | 122 | struct device_attribute *attr, char *buf) |
94 | { | 123 | { |
@@ -200,6 +229,9 @@ static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO, | |||
200 | static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR, | 229 | static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR, |
201 | show_hyst, store_hyst, 0x1A); | 230 | show_hyst, store_hyst, 0x1A); |
202 | 231 | ||
232 | static SENSOR_DEVICE_ATTR_2(power_state, S_IRUGO | S_IWUSR, | ||
233 | show_bit, store_bit, 0x03, 0x40); | ||
234 | |||
203 | static struct attribute *mid_att_thermal[] = { | 235 | static struct attribute *mid_att_thermal[] = { |
204 | &sensor_dev_attr_temp1_min.dev_attr.attr, | 236 | &sensor_dev_attr_temp1_min.dev_attr.attr, |
205 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 237 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
@@ -225,6 +257,7 @@ static struct attribute *mid_att_thermal[] = { | |||
225 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | 257 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, |
226 | &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, | 258 | &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, |
227 | &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, | 259 | &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, |
260 | &sensor_dev_attr_power_state.dev_attr.attr, | ||
228 | NULL | 261 | NULL |
229 | }; | 262 | }; |
230 | 263 | ||
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c new file mode 100644 index 000000000000..af914ad93ece --- /dev/null +++ b/drivers/hwmon/emc2103.c | |||
@@ -0,0 +1,740 @@ | |||
1 | /* | ||
2 | emc2103.c - Support for SMSC EMC2103 | ||
3 | Copyright (c) 2010 SMSC | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/slab.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 | |||
30 | /* Addresses scanned */ | ||
31 | static const unsigned short normal_i2c[] = { 0x2E, I2C_CLIENT_END }; | ||
32 | |||
33 | static const u8 REG_TEMP[4] = { 0x00, 0x02, 0x04, 0x06 }; | ||
34 | static const u8 REG_TEMP_MIN[4] = { 0x3c, 0x38, 0x39, 0x3a }; | ||
35 | static const u8 REG_TEMP_MAX[4] = { 0x34, 0x30, 0x31, 0x32 }; | ||
36 | |||
37 | #define REG_CONF1 0x20 | ||
38 | #define REG_TEMP_MAX_ALARM 0x24 | ||
39 | #define REG_TEMP_MIN_ALARM 0x25 | ||
40 | #define REG_FAN_CONF1 0x42 | ||
41 | #define REG_FAN_TARGET_LO 0x4c | ||
42 | #define REG_FAN_TARGET_HI 0x4d | ||
43 | #define REG_FAN_TACH_HI 0x4e | ||
44 | #define REG_FAN_TACH_LO 0x4f | ||
45 | #define REG_PRODUCT_ID 0xfd | ||
46 | #define REG_MFG_ID 0xfe | ||
47 | |||
48 | /* equation 4 from datasheet: rpm = (3932160 * multipler) / count */ | ||
49 | #define FAN_RPM_FACTOR 3932160 | ||
50 | |||
51 | /* 2103-2 and 2103-4's 3rd temperature sensor can be connected to two diodes | ||
52 | * in anti-parallel mode, and in this configuration both can be read | ||
53 | * independently (so we have 4 temperature inputs). The device can't | ||
54 | * detect if it's connected in this mode, so we have to manually enable | ||
55 | * it. Default is to leave the device in the state it's already in (-1). | ||
56 | * This parameter allows APD mode to be optionally forced on or off */ | ||
57 | static int apd = -1; | ||
58 | module_param(apd, bool, 0); | ||
59 | MODULE_PARM_DESC(init, "Set to zero to disable anti-parallel diode mode"); | ||
60 | |||
61 | struct temperature { | ||
62 | s8 degrees; | ||
63 | u8 fraction; /* 0-7 multiples of 0.125 */ | ||
64 | }; | ||
65 | |||
66 | struct emc2103_data { | ||
67 | struct device *hwmon_dev; | ||
68 | struct mutex update_lock; | ||
69 | bool valid; /* registers are valid */ | ||
70 | bool fan_rpm_control; | ||
71 | int temp_count; /* num of temp sensors */ | ||
72 | unsigned long last_updated; /* in jiffies */ | ||
73 | struct temperature temp[4]; /* internal + 3 external */ | ||
74 | s8 temp_min[4]; /* no fractional part */ | ||
75 | s8 temp_max[4]; /* no fractional part */ | ||
76 | u8 temp_min_alarm; | ||
77 | u8 temp_max_alarm; | ||
78 | u8 fan_multiplier; | ||
79 | u16 fan_tach; | ||
80 | u16 fan_target; | ||
81 | }; | ||
82 | |||
83 | static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) | ||
84 | { | ||
85 | int status = i2c_smbus_read_byte_data(client, i2c_reg); | ||
86 | if (status < 0) { | ||
87 | dev_warn(&client->dev, "reg 0x%02x, err %d\n", | ||
88 | i2c_reg, status); | ||
89 | } else { | ||
90 | *output = status; | ||
91 | } | ||
92 | return status; | ||
93 | } | ||
94 | |||
95 | static void read_temp_from_i2c(struct i2c_client *client, u8 i2c_reg, | ||
96 | struct temperature *temp) | ||
97 | { | ||
98 | u8 degrees, fractional; | ||
99 | |||
100 | if (read_u8_from_i2c(client, i2c_reg, °rees) < 0) | ||
101 | return; | ||
102 | |||
103 | if (read_u8_from_i2c(client, i2c_reg + 1, &fractional) < 0) | ||
104 | return; | ||
105 | |||
106 | temp->degrees = degrees; | ||
107 | temp->fraction = (fractional & 0xe0) >> 5; | ||
108 | } | ||
109 | |||
110 | static void read_fan_from_i2c(struct i2c_client *client, u16 *output, | ||
111 | u8 hi_addr, u8 lo_addr) | ||
112 | { | ||
113 | u8 high_byte, lo_byte; | ||
114 | |||
115 | if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) | ||
116 | return; | ||
117 | |||
118 | if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) | ||
119 | return; | ||
120 | |||
121 | *output = ((u16)high_byte << 5) | (lo_byte >> 3); | ||
122 | } | ||
123 | |||
124 | static void write_fan_target_to_i2c(struct i2c_client *client, u16 new_target) | ||
125 | { | ||
126 | u8 high_byte = (new_target & 0x1fe0) >> 5; | ||
127 | u8 low_byte = (new_target & 0x001f) << 3; | ||
128 | i2c_smbus_write_byte_data(client, REG_FAN_TARGET_LO, low_byte); | ||
129 | i2c_smbus_write_byte_data(client, REG_FAN_TARGET_HI, high_byte); | ||
130 | } | ||
131 | |||
132 | static void read_fan_config_from_i2c(struct i2c_client *client) | ||
133 | |||
134 | { | ||
135 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
136 | u8 conf1; | ||
137 | |||
138 | if (read_u8_from_i2c(client, REG_FAN_CONF1, &conf1) < 0) | ||
139 | return; | ||
140 | |||
141 | data->fan_multiplier = 1 << ((conf1 & 0x60) >> 5); | ||
142 | data->fan_rpm_control = (conf1 & 0x80) != 0; | ||
143 | } | ||
144 | |||
145 | static struct emc2103_data *emc2103_update_device(struct device *dev) | ||
146 | { | ||
147 | struct i2c_client *client = to_i2c_client(dev); | ||
148 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
149 | |||
150 | mutex_lock(&data->update_lock); | ||
151 | |||
152 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | ||
153 | || !data->valid) { | ||
154 | int i; | ||
155 | |||
156 | for (i = 0; i < data->temp_count; i++) { | ||
157 | read_temp_from_i2c(client, REG_TEMP[i], &data->temp[i]); | ||
158 | read_u8_from_i2c(client, REG_TEMP_MIN[i], | ||
159 | &data->temp_min[i]); | ||
160 | read_u8_from_i2c(client, REG_TEMP_MAX[i], | ||
161 | &data->temp_max[i]); | ||
162 | } | ||
163 | |||
164 | read_u8_from_i2c(client, REG_TEMP_MIN_ALARM, | ||
165 | &data->temp_min_alarm); | ||
166 | read_u8_from_i2c(client, REG_TEMP_MAX_ALARM, | ||
167 | &data->temp_max_alarm); | ||
168 | |||
169 | read_fan_from_i2c(client, &data->fan_tach, | ||
170 | REG_FAN_TACH_HI, REG_FAN_TACH_LO); | ||
171 | read_fan_from_i2c(client, &data->fan_target, | ||
172 | REG_FAN_TARGET_HI, REG_FAN_TARGET_LO); | ||
173 | read_fan_config_from_i2c(client); | ||
174 | |||
175 | data->last_updated = jiffies; | ||
176 | data->valid = true; | ||
177 | } | ||
178 | |||
179 | mutex_unlock(&data->update_lock); | ||
180 | |||
181 | return data; | ||
182 | } | ||
183 | |||
184 | static ssize_t | ||
185 | show_temp(struct device *dev, struct device_attribute *da, char *buf) | ||
186 | { | ||
187 | int nr = to_sensor_dev_attr(da)->index; | ||
188 | struct emc2103_data *data = emc2103_update_device(dev); | ||
189 | int millidegrees = data->temp[nr].degrees * 1000 | ||
190 | + data->temp[nr].fraction * 125; | ||
191 | return sprintf(buf, "%d\n", millidegrees); | ||
192 | } | ||
193 | |||
194 | static ssize_t | ||
195 | show_temp_min(struct device *dev, struct device_attribute *da, char *buf) | ||
196 | { | ||
197 | int nr = to_sensor_dev_attr(da)->index; | ||
198 | struct emc2103_data *data = emc2103_update_device(dev); | ||
199 | int millidegrees = data->temp_min[nr] * 1000; | ||
200 | return sprintf(buf, "%d\n", millidegrees); | ||
201 | } | ||
202 | |||
203 | static ssize_t | ||
204 | show_temp_max(struct device *dev, struct device_attribute *da, char *buf) | ||
205 | { | ||
206 | int nr = to_sensor_dev_attr(da)->index; | ||
207 | struct emc2103_data *data = emc2103_update_device(dev); | ||
208 | int millidegrees = data->temp_max[nr] * 1000; | ||
209 | return sprintf(buf, "%d\n", millidegrees); | ||
210 | } | ||
211 | |||
212 | static ssize_t | ||
213 | show_temp_fault(struct device *dev, struct device_attribute *da, char *buf) | ||
214 | { | ||
215 | int nr = to_sensor_dev_attr(da)->index; | ||
216 | struct emc2103_data *data = emc2103_update_device(dev); | ||
217 | bool fault = (data->temp[nr].degrees == -128); | ||
218 | return sprintf(buf, "%d\n", fault ? 1 : 0); | ||
219 | } | ||
220 | |||
221 | static ssize_t | ||
222 | show_temp_min_alarm(struct device *dev, struct device_attribute *da, char *buf) | ||
223 | { | ||
224 | int nr = to_sensor_dev_attr(da)->index; | ||
225 | struct emc2103_data *data = emc2103_update_device(dev); | ||
226 | bool alarm = data->temp_min_alarm & (1 << nr); | ||
227 | return sprintf(buf, "%d\n", alarm ? 1 : 0); | ||
228 | } | ||
229 | |||
230 | static ssize_t | ||
231 | show_temp_max_alarm(struct device *dev, struct device_attribute *da, char *buf) | ||
232 | { | ||
233 | int nr = to_sensor_dev_attr(da)->index; | ||
234 | struct emc2103_data *data = emc2103_update_device(dev); | ||
235 | bool alarm = data->temp_max_alarm & (1 << nr); | ||
236 | return sprintf(buf, "%d\n", alarm ? 1 : 0); | ||
237 | } | ||
238 | |||
239 | static ssize_t set_temp_min(struct device *dev, struct device_attribute *da, | ||
240 | const char *buf, size_t count) | ||
241 | { | ||
242 | int nr = to_sensor_dev_attr(da)->index; | ||
243 | struct i2c_client *client = to_i2c_client(dev); | ||
244 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
245 | long val; | ||
246 | |||
247 | int result = strict_strtol(buf, 10, &val); | ||
248 | if (result < 0) | ||
249 | return -EINVAL; | ||
250 | |||
251 | val = DIV_ROUND_CLOSEST(val, 1000); | ||
252 | if ((val < -63) || (val > 127)) | ||
253 | return -EINVAL; | ||
254 | |||
255 | mutex_lock(&data->update_lock); | ||
256 | data->temp_min[nr] = val; | ||
257 | i2c_smbus_write_byte_data(client, REG_TEMP_MIN[nr], val); | ||
258 | mutex_unlock(&data->update_lock); | ||
259 | |||
260 | return count; | ||
261 | } | ||
262 | |||
263 | static ssize_t set_temp_max(struct device *dev, struct device_attribute *da, | ||
264 | const char *buf, size_t count) | ||
265 | { | ||
266 | int nr = to_sensor_dev_attr(da)->index; | ||
267 | struct i2c_client *client = to_i2c_client(dev); | ||
268 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
269 | long val; | ||
270 | |||
271 | int result = strict_strtol(buf, 10, &val); | ||
272 | if (result < 0) | ||
273 | return -EINVAL; | ||
274 | |||
275 | val = DIV_ROUND_CLOSEST(val, 1000); | ||
276 | if ((val < -63) || (val > 127)) | ||
277 | return -EINVAL; | ||
278 | |||
279 | mutex_lock(&data->update_lock); | ||
280 | data->temp_max[nr] = val; | ||
281 | i2c_smbus_write_byte_data(client, REG_TEMP_MAX[nr], val); | ||
282 | mutex_unlock(&data->update_lock); | ||
283 | |||
284 | return count; | ||
285 | } | ||
286 | |||
287 | static ssize_t | ||
288 | show_fan(struct device *dev, struct device_attribute *da, char *buf) | ||
289 | { | ||
290 | struct emc2103_data *data = emc2103_update_device(dev); | ||
291 | int rpm = 0; | ||
292 | if (data->fan_tach != 0) | ||
293 | rpm = (FAN_RPM_FACTOR * data->fan_multiplier) / data->fan_tach; | ||
294 | return sprintf(buf, "%d\n", rpm); | ||
295 | } | ||
296 | |||
297 | static ssize_t | ||
298 | show_fan_div(struct device *dev, struct device_attribute *da, char *buf) | ||
299 | { | ||
300 | struct emc2103_data *data = emc2103_update_device(dev); | ||
301 | int fan_div = 8 / data->fan_multiplier; | ||
302 | return sprintf(buf, "%d\n", fan_div); | ||
303 | } | ||
304 | |||
305 | /* Note: we also update the fan target here, because its value is | ||
306 | determined in part by the fan clock divider. This follows the principle | ||
307 | of least surprise; the user doesn't expect the fan target to change just | ||
308 | because the divider changed. */ | ||
309 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, | ||
310 | const char *buf, size_t count) | ||
311 | { | ||
312 | struct emc2103_data *data = emc2103_update_device(dev); | ||
313 | struct i2c_client *client = to_i2c_client(dev); | ||
314 | int new_range_bits, old_div = 8 / data->fan_multiplier; | ||
315 | long new_div; | ||
316 | |||
317 | int status = strict_strtol(buf, 10, &new_div); | ||
318 | if (status < 0) | ||
319 | return -EINVAL; | ||
320 | |||
321 | if (new_div == old_div) /* No change */ | ||
322 | return count; | ||
323 | |||
324 | switch (new_div) { | ||
325 | case 1: | ||
326 | new_range_bits = 3; | ||
327 | break; | ||
328 | case 2: | ||
329 | new_range_bits = 2; | ||
330 | break; | ||
331 | case 4: | ||
332 | new_range_bits = 1; | ||
333 | break; | ||
334 | case 8: | ||
335 | new_range_bits = 0; | ||
336 | break; | ||
337 | default: | ||
338 | return -EINVAL; | ||
339 | } | ||
340 | |||
341 | mutex_lock(&data->update_lock); | ||
342 | |||
343 | status = i2c_smbus_read_byte_data(client, REG_FAN_CONF1); | ||
344 | if (status < 0) { | ||
345 | dev_dbg(&client->dev, "reg 0x%02x, err %d\n", | ||
346 | REG_FAN_CONF1, status); | ||
347 | mutex_unlock(&data->update_lock); | ||
348 | return -EIO; | ||
349 | } | ||
350 | status &= 0x9F; | ||
351 | status |= (new_range_bits << 5); | ||
352 | i2c_smbus_write_byte_data(client, REG_FAN_CONF1, status); | ||
353 | |||
354 | data->fan_multiplier = 8 / new_div; | ||
355 | |||
356 | /* update fan target if high byte is not disabled */ | ||
357 | if ((data->fan_target & 0x1fe0) != 0x1fe0) { | ||
358 | u16 new_target = (data->fan_target * old_div) / new_div; | ||
359 | data->fan_target = min(new_target, (u16)0x1fff); | ||
360 | write_fan_target_to_i2c(client, data->fan_target); | ||
361 | } | ||
362 | |||
363 | /* invalidate data to force re-read from hardware */ | ||
364 | data->valid = false; | ||
365 | |||
366 | mutex_unlock(&data->update_lock); | ||
367 | return count; | ||
368 | } | ||
369 | |||
370 | static ssize_t | ||
371 | show_fan_target(struct device *dev, struct device_attribute *da, char *buf) | ||
372 | { | ||
373 | struct emc2103_data *data = emc2103_update_device(dev); | ||
374 | int rpm = 0; | ||
375 | |||
376 | /* high byte of 0xff indicates disabled so return 0 */ | ||
377 | if ((data->fan_target != 0) && ((data->fan_target & 0x1fe0) != 0x1fe0)) | ||
378 | rpm = (FAN_RPM_FACTOR * data->fan_multiplier) | ||
379 | / data->fan_target; | ||
380 | |||
381 | return sprintf(buf, "%d\n", rpm); | ||
382 | } | ||
383 | |||
384 | static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, | ||
385 | const char *buf, size_t count) | ||
386 | { | ||
387 | struct emc2103_data *data = emc2103_update_device(dev); | ||
388 | struct i2c_client *client = to_i2c_client(dev); | ||
389 | long rpm_target; | ||
390 | |||
391 | int result = strict_strtol(buf, 10, &rpm_target); | ||
392 | if (result < 0) | ||
393 | return -EINVAL; | ||
394 | |||
395 | /* Datasheet states 16384 as maximum RPM target (table 3.2) */ | ||
396 | if ((rpm_target < 0) || (rpm_target > 16384)) | ||
397 | return -EINVAL; | ||
398 | |||
399 | mutex_lock(&data->update_lock); | ||
400 | |||
401 | if (rpm_target == 0) | ||
402 | data->fan_target = 0x1fff; | ||
403 | else | ||
404 | data->fan_target = SENSORS_LIMIT( | ||
405 | (FAN_RPM_FACTOR * data->fan_multiplier) / rpm_target, | ||
406 | 0, 0x1fff); | ||
407 | |||
408 | write_fan_target_to_i2c(client, data->fan_target); | ||
409 | |||
410 | mutex_unlock(&data->update_lock); | ||
411 | return count; | ||
412 | } | ||
413 | |||
414 | static ssize_t | ||
415 | show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) | ||
416 | { | ||
417 | struct emc2103_data *data = emc2103_update_device(dev); | ||
418 | bool fault = ((data->fan_tach & 0x1fe0) == 0x1fe0); | ||
419 | return sprintf(buf, "%d\n", fault ? 1 : 0); | ||
420 | } | ||
421 | |||
422 | static ssize_t | ||
423 | show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) | ||
424 | { | ||
425 | struct emc2103_data *data = emc2103_update_device(dev); | ||
426 | return sprintf(buf, "%d\n", data->fan_rpm_control ? 3 : 0); | ||
427 | } | ||
428 | |||
429 | static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, | ||
430 | const char *buf, size_t count) | ||
431 | { | ||
432 | struct i2c_client *client = to_i2c_client(dev); | ||
433 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
434 | long new_value; | ||
435 | u8 conf_reg; | ||
436 | |||
437 | int result = strict_strtol(buf, 10, &new_value); | ||
438 | if (result < 0) | ||
439 | return -EINVAL; | ||
440 | |||
441 | mutex_lock(&data->update_lock); | ||
442 | switch (new_value) { | ||
443 | case 0: | ||
444 | data->fan_rpm_control = false; | ||
445 | break; | ||
446 | case 3: | ||
447 | data->fan_rpm_control = true; | ||
448 | break; | ||
449 | default: | ||
450 | mutex_unlock(&data->update_lock); | ||
451 | return -EINVAL; | ||
452 | } | ||
453 | |||
454 | read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg); | ||
455 | |||
456 | if (data->fan_rpm_control) | ||
457 | conf_reg |= 0x80; | ||
458 | else | ||
459 | conf_reg &= ~0x80; | ||
460 | |||
461 | i2c_smbus_write_byte_data(client, REG_FAN_CONF1, conf_reg); | ||
462 | |||
463 | mutex_unlock(&data->update_lock); | ||
464 | return count; | ||
465 | } | ||
466 | |||
467 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
468 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp_min, | ||
469 | set_temp_min, 0); | ||
470 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp_max, | ||
471 | set_temp_max, 0); | ||
472 | static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); | ||
473 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_temp_min_alarm, | ||
474 | NULL, 0); | ||
475 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, | ||
476 | NULL, 0); | ||
477 | |||
478 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | ||
479 | static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, show_temp_min, | ||
480 | set_temp_min, 1); | ||
481 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, | ||
482 | set_temp_max, 1); | ||
483 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); | ||
484 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, | ||
485 | NULL, 1); | ||
486 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, | ||
487 | NULL, 1); | ||
488 | |||
489 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); | ||
490 | static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO | S_IWUSR, show_temp_min, | ||
491 | set_temp_min, 2); | ||
492 | static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, | ||
493 | set_temp_max, 2); | ||
494 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); | ||
495 | static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, | ||
496 | NULL, 2); | ||
497 | static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, | ||
498 | NULL, 2); | ||
499 | |||
500 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); | ||
501 | static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO | S_IWUSR, show_temp_min, | ||
502 | set_temp_min, 3); | ||
503 | static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO | S_IWUSR, show_temp_max, | ||
504 | set_temp_max, 3); | ||
505 | static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); | ||
506 | static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_temp_min_alarm, | ||
507 | NULL, 3); | ||
508 | static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_temp_max_alarm, | ||
509 | NULL, 3); | ||
510 | |||
511 | static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL); | ||
512 | static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, show_fan_div, set_fan_div); | ||
513 | static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_fan_target, | ||
514 | set_fan_target); | ||
515 | static DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL); | ||
516 | |||
517 | static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, | ||
518 | set_pwm_enable); | ||
519 | |||
520 | /* sensors present on all models */ | ||
521 | static struct attribute *emc2103_attributes[] = { | ||
522 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
523 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
524 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
525 | &sensor_dev_attr_temp1_fault.dev_attr.attr, | ||
526 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
527 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
528 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
529 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
530 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
531 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
532 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
533 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
534 | &dev_attr_fan1_input.attr, | ||
535 | &dev_attr_fan1_div.attr, | ||
536 | &dev_attr_fan1_target.attr, | ||
537 | &dev_attr_fan1_fault.attr, | ||
538 | &dev_attr_pwm1_enable.attr, | ||
539 | NULL | ||
540 | }; | ||
541 | |||
542 | /* extra temperature sensors only present on 2103-2 and 2103-4 */ | ||
543 | static struct attribute *emc2103_attributes_temp3[] = { | ||
544 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
545 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
546 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
547 | &sensor_dev_attr_temp3_fault.dev_attr.attr, | ||
548 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, | ||
549 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | ||
550 | NULL | ||
551 | }; | ||
552 | |||
553 | /* extra temperature sensors only present on 2103-2 and 2103-4 in APD mode */ | ||
554 | static struct attribute *emc2103_attributes_temp4[] = { | ||
555 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
556 | &sensor_dev_attr_temp4_min.dev_attr.attr, | ||
557 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
558 | &sensor_dev_attr_temp4_fault.dev_attr.attr, | ||
559 | &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, | ||
560 | &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, | ||
561 | NULL | ||
562 | }; | ||
563 | |||
564 | static const struct attribute_group emc2103_group = { | ||
565 | .attrs = emc2103_attributes, | ||
566 | }; | ||
567 | |||
568 | static const struct attribute_group emc2103_temp3_group = { | ||
569 | .attrs = emc2103_attributes_temp3, | ||
570 | }; | ||
571 | |||
572 | static const struct attribute_group emc2103_temp4_group = { | ||
573 | .attrs = emc2103_attributes_temp4, | ||
574 | }; | ||
575 | |||
576 | static int | ||
577 | emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
578 | { | ||
579 | struct emc2103_data *data; | ||
580 | int status; | ||
581 | |||
582 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
583 | return -EIO; | ||
584 | |||
585 | data = kzalloc(sizeof(struct emc2103_data), GFP_KERNEL); | ||
586 | if (!data) | ||
587 | return -ENOMEM; | ||
588 | |||
589 | i2c_set_clientdata(client, data); | ||
590 | mutex_init(&data->update_lock); | ||
591 | |||
592 | /* 2103-2 and 2103-4 have 3 external diodes, 2103-1 has 1 */ | ||
593 | status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); | ||
594 | if (status == 0x24) { | ||
595 | /* 2103-1 only has 1 external diode */ | ||
596 | data->temp_count = 2; | ||
597 | } else { | ||
598 | /* 2103-2 and 2103-4 have 3 or 4 external diodes */ | ||
599 | status = i2c_smbus_read_byte_data(client, REG_CONF1); | ||
600 | if (status < 0) { | ||
601 | dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_CONF1, | ||
602 | status); | ||
603 | goto exit_free; | ||
604 | } | ||
605 | |||
606 | /* detect current state of hardware */ | ||
607 | data->temp_count = (status & 0x01) ? 4 : 3; | ||
608 | |||
609 | /* force APD state if module parameter is set */ | ||
610 | if (apd == 0) { | ||
611 | /* force APD mode off */ | ||
612 | data->temp_count = 3; | ||
613 | status &= ~(0x01); | ||
614 | i2c_smbus_write_byte_data(client, REG_CONF1, status); | ||
615 | } else if (apd == 1) { | ||
616 | /* force APD mode on */ | ||
617 | data->temp_count = 4; | ||
618 | status |= 0x01; | ||
619 | i2c_smbus_write_byte_data(client, REG_CONF1, status); | ||
620 | } | ||
621 | } | ||
622 | |||
623 | /* Register sysfs hooks */ | ||
624 | status = sysfs_create_group(&client->dev.kobj, &emc2103_group); | ||
625 | if (status) | ||
626 | goto exit_free; | ||
627 | |||
628 | if (data->temp_count >= 3) { | ||
629 | status = sysfs_create_group(&client->dev.kobj, | ||
630 | &emc2103_temp3_group); | ||
631 | if (status) | ||
632 | goto exit_remove; | ||
633 | } | ||
634 | |||
635 | if (data->temp_count == 4) { | ||
636 | status = sysfs_create_group(&client->dev.kobj, | ||
637 | &emc2103_temp4_group); | ||
638 | if (status) | ||
639 | goto exit_remove_temp3; | ||
640 | } | ||
641 | |||
642 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
643 | if (IS_ERR(data->hwmon_dev)) { | ||
644 | status = PTR_ERR(data->hwmon_dev); | ||
645 | goto exit_remove_temp4; | ||
646 | } | ||
647 | |||
648 | dev_info(&client->dev, "%s: sensor '%s'\n", | ||
649 | dev_name(data->hwmon_dev), client->name); | ||
650 | |||
651 | return 0; | ||
652 | |||
653 | exit_remove_temp4: | ||
654 | if (data->temp_count == 4) | ||
655 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group); | ||
656 | exit_remove_temp3: | ||
657 | if (data->temp_count >= 3) | ||
658 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); | ||
659 | exit_remove: | ||
660 | sysfs_remove_group(&client->dev.kobj, &emc2103_group); | ||
661 | exit_free: | ||
662 | kfree(data); | ||
663 | return status; | ||
664 | } | ||
665 | |||
666 | static int emc2103_remove(struct i2c_client *client) | ||
667 | { | ||
668 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
669 | |||
670 | hwmon_device_unregister(data->hwmon_dev); | ||
671 | |||
672 | if (data->temp_count == 4) | ||
673 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group); | ||
674 | |||
675 | if (data->temp_count >= 3) | ||
676 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); | ||
677 | |||
678 | sysfs_remove_group(&client->dev.kobj, &emc2103_group); | ||
679 | |||
680 | kfree(data); | ||
681 | return 0; | ||
682 | } | ||
683 | |||
684 | static const struct i2c_device_id emc2103_ids[] = { | ||
685 | { "emc2103", 0, }, | ||
686 | { /* LIST END */ } | ||
687 | }; | ||
688 | MODULE_DEVICE_TABLE(i2c, emc2103_ids); | ||
689 | |||
690 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
691 | static int | ||
692 | emc2103_detect(struct i2c_client *new_client, struct i2c_board_info *info) | ||
693 | { | ||
694 | struct i2c_adapter *adapter = new_client->adapter; | ||
695 | int manufacturer, product; | ||
696 | |||
697 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
698 | return -ENODEV; | ||
699 | |||
700 | manufacturer = i2c_smbus_read_byte_data(new_client, REG_MFG_ID); | ||
701 | if (manufacturer != 0x5D) | ||
702 | return -ENODEV; | ||
703 | |||
704 | product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); | ||
705 | if ((product != 0x24) && (product != 0x26)) | ||
706 | return -ENODEV; | ||
707 | |||
708 | strlcpy(info->type, "emc2103", I2C_NAME_SIZE); | ||
709 | |||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | static struct i2c_driver emc2103_driver = { | ||
714 | .class = I2C_CLASS_HWMON, | ||
715 | .driver = { | ||
716 | .name = "emc2103", | ||
717 | }, | ||
718 | .probe = emc2103_probe, | ||
719 | .remove = emc2103_remove, | ||
720 | .id_table = emc2103_ids, | ||
721 | .detect = emc2103_detect, | ||
722 | .address_list = normal_i2c, | ||
723 | }; | ||
724 | |||
725 | static int __init sensors_emc2103_init(void) | ||
726 | { | ||
727 | return i2c_add_driver(&emc2103_driver); | ||
728 | } | ||
729 | |||
730 | static void __exit sensors_emc2103_exit(void) | ||
731 | { | ||
732 | i2c_del_driver(&emc2103_driver); | ||
733 | } | ||
734 | |||
735 | MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>"); | ||
736 | MODULE_DESCRIPTION("SMSC EMC2103 hwmon driver"); | ||
737 | MODULE_LICENSE("GPL"); | ||
738 | |||
739 | module_init(sensors_emc2103_init); | ||
740 | module_exit(sensors_emc2103_exit); | ||
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 25763d2223b6..f7701295937d 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -259,6 +259,7 @@ struct it87_sio_data { | |||
259 | u8 revision; | 259 | u8 revision; |
260 | u8 vid_value; | 260 | u8 vid_value; |
261 | u8 beep_pin; | 261 | u8 beep_pin; |
262 | u8 internal; /* Internal sensors can be labeled */ | ||
262 | /* Features skipped based on config or DMI */ | 263 | /* Features skipped based on config or DMI */ |
263 | u8 skip_vid; | 264 | u8 skip_vid; |
264 | u8 skip_fan; | 265 | u8 skip_fan; |
@@ -1194,6 +1195,22 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, | |||
1194 | } | 1195 | } |
1195 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); | 1196 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); |
1196 | 1197 | ||
1198 | static ssize_t show_label(struct device *dev, struct device_attribute *attr, | ||
1199 | char *buf) | ||
1200 | { | ||
1201 | static const char *labels[] = { | ||
1202 | "+5V", | ||
1203 | "5VSB", | ||
1204 | "Vbat", | ||
1205 | }; | ||
1206 | int nr = to_sensor_dev_attr(attr)->index; | ||
1207 | |||
1208 | return sprintf(buf, "%s\n", labels[nr]); | ||
1209 | } | ||
1210 | static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); | ||
1211 | static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); | ||
1212 | static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2); | ||
1213 | |||
1197 | static ssize_t show_name(struct device *dev, struct device_attribute | 1214 | static ssize_t show_name(struct device *dev, struct device_attribute |
1198 | *devattr, char *buf) | 1215 | *devattr, char *buf) |
1199 | { | 1216 | { |
@@ -1434,6 +1451,17 @@ static const struct attribute_group it87_group_vid = { | |||
1434 | .attrs = it87_attributes_vid, | 1451 | .attrs = it87_attributes_vid, |
1435 | }; | 1452 | }; |
1436 | 1453 | ||
1454 | static struct attribute *it87_attributes_label[] = { | ||
1455 | &sensor_dev_attr_in3_label.dev_attr.attr, | ||
1456 | &sensor_dev_attr_in7_label.dev_attr.attr, | ||
1457 | &sensor_dev_attr_in8_label.dev_attr.attr, | ||
1458 | NULL | ||
1459 | }; | ||
1460 | |||
1461 | static const struct attribute_group it87_group_label = { | ||
1462 | .attrs = it87_attributes_vid, | ||
1463 | }; | ||
1464 | |||
1437 | /* SuperIO detection - will change isa_address if a chip is found */ | 1465 | /* SuperIO detection - will change isa_address if a chip is found */ |
1438 | static int __init it87_find(unsigned short *address, | 1466 | static int __init it87_find(unsigned short *address, |
1439 | struct it87_sio_data *sio_data) | 1467 | struct it87_sio_data *sio_data) |
@@ -1487,6 +1515,9 @@ static int __init it87_find(unsigned short *address, | |||
1487 | pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", | 1515 | pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", |
1488 | chip_type, *address, sio_data->revision); | 1516 | chip_type, *address, sio_data->revision); |
1489 | 1517 | ||
1518 | /* in8 (Vbat) is always internal */ | ||
1519 | sio_data->internal = (1 << 2); | ||
1520 | |||
1490 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ | 1521 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ |
1491 | if (sio_data->type == it87) { | 1522 | if (sio_data->type == it87) { |
1492 | /* The IT8705F doesn't have VID pins at all */ | 1523 | /* The IT8705F doesn't have VID pins at all */ |
@@ -1540,9 +1571,9 @@ static int __init it87_find(unsigned short *address, | |||
1540 | pr_notice("it87: Routing internal VCCH to in7\n"); | 1571 | pr_notice("it87: Routing internal VCCH to in7\n"); |
1541 | } | 1572 | } |
1542 | if (reg & (1 << 0)) | 1573 | if (reg & (1 << 0)) |
1543 | pr_info("it87: in3 is VCC (+5V)\n"); | 1574 | sio_data->internal |= (1 << 0); |
1544 | if (reg & (1 << 1)) | 1575 | if (reg & (1 << 1)) |
1545 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); | 1576 | sio_data->internal |= (1 << 1); |
1546 | 1577 | ||
1547 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | 1578 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; |
1548 | } | 1579 | } |
@@ -1600,6 +1631,7 @@ static void it87_remove_files(struct device *dev) | |||
1600 | } | 1631 | } |
1601 | if (!sio_data->skip_vid) | 1632 | if (!sio_data->skip_vid) |
1602 | sysfs_remove_group(&dev->kobj, &it87_group_vid); | 1633 | sysfs_remove_group(&dev->kobj, &it87_group_vid); |
1634 | sysfs_remove_group(&dev->kobj, &it87_group_label); | ||
1603 | } | 1635 | } |
1604 | 1636 | ||
1605 | static int __devinit it87_probe(struct platform_device *pdev) | 1637 | static int __devinit it87_probe(struct platform_device *pdev) |
@@ -1725,6 +1757,16 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1725 | goto ERROR4; | 1757 | goto ERROR4; |
1726 | } | 1758 | } |
1727 | 1759 | ||
1760 | /* Export labels for internal sensors */ | ||
1761 | for (i = 0; i < 3; i++) { | ||
1762 | if (!(sio_data->internal & (1 << i))) | ||
1763 | continue; | ||
1764 | err = sysfs_create_file(&dev->kobj, | ||
1765 | it87_attributes_label[i]); | ||
1766 | if (err) | ||
1767 | goto ERROR4; | ||
1768 | } | ||
1769 | |||
1728 | data->hwmon_dev = hwmon_device_register(dev); | 1770 | data->hwmon_dev = hwmon_device_register(dev); |
1729 | if (IS_ERR(data->hwmon_dev)) { | 1771 | if (IS_ERR(data->hwmon_dev)) { |
1730 | err = PTR_ERR(data->hwmon_dev); | 1772 | err = PTR_ERR(data->hwmon_dev); |
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 8bdf80d91598..b9bb3e0ca530 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c | |||
@@ -252,12 +252,13 @@ static int __devinit k8temp_probe(struct pci_dev *pdev, | |||
252 | &sensor_dev_attr_temp3_input.dev_attr); | 252 | &sensor_dev_attr_temp3_input.dev_attr); |
253 | if (err) | 253 | if (err) |
254 | goto exit_remove; | 254 | goto exit_remove; |
255 | if (data->sensorsp & SEL_PLACE) | 255 | if (data->sensorsp & SEL_PLACE) { |
256 | err = device_create_file(&pdev->dev, | 256 | err = device_create_file(&pdev->dev, |
257 | &sensor_dev_attr_temp4_input. | 257 | &sensor_dev_attr_temp4_input. |
258 | dev_attr); | 258 | dev_attr); |
259 | if (err) | 259 | if (err) |
260 | goto exit_remove; | 260 | goto exit_remove; |
261 | } | ||
261 | } | 262 | } |
262 | 263 | ||
263 | err = device_create_file(&pdev->dev, &dev_attr_name); | 264 | err = device_create_file(&pdev->dev, &dev_attr_name); |
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 393f354f92a4..ab5b87a81677 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c | |||
@@ -280,10 +280,49 @@ static int lm75_detect(struct i2c_client *new_client, | |||
280 | return 0; | 280 | return 0; |
281 | } | 281 | } |
282 | 282 | ||
283 | #ifdef CONFIG_PM | ||
284 | static int lm75_suspend(struct device *dev) | ||
285 | { | ||
286 | int status; | ||
287 | struct i2c_client *client = to_i2c_client(dev); | ||
288 | status = lm75_read_value(client, LM75_REG_CONF); | ||
289 | if (status < 0) { | ||
290 | dev_dbg(&client->dev, "Can't read config? %d\n", status); | ||
291 | return status; | ||
292 | } | ||
293 | status = status | LM75_SHUTDOWN; | ||
294 | lm75_write_value(client, LM75_REG_CONF, status); | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int lm75_resume(struct device *dev) | ||
299 | { | ||
300 | int status; | ||
301 | struct i2c_client *client = to_i2c_client(dev); | ||
302 | status = lm75_read_value(client, LM75_REG_CONF); | ||
303 | if (status < 0) { | ||
304 | dev_dbg(&client->dev, "Can't read config? %d\n", status); | ||
305 | return status; | ||
306 | } | ||
307 | status = status & ~LM75_SHUTDOWN; | ||
308 | lm75_write_value(client, LM75_REG_CONF, status); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static const struct dev_pm_ops lm75_dev_pm_ops = { | ||
313 | .suspend = lm75_suspend, | ||
314 | .resume = lm75_resume, | ||
315 | }; | ||
316 | #define LM75_DEV_PM_OPS (&lm75_dev_pm_ops) | ||
317 | #else | ||
318 | #define LM75_DEV_PM_OPS NULL | ||
319 | #endif /* CONFIG_PM */ | ||
320 | |||
283 | static struct i2c_driver lm75_driver = { | 321 | static struct i2c_driver lm75_driver = { |
284 | .class = I2C_CLASS_HWMON, | 322 | .class = I2C_CLASS_HWMON, |
285 | .driver = { | 323 | .driver = { |
286 | .name = "lm75", | 324 | .name = "lm75", |
325 | .pm = LM75_DEV_PM_OPS, | ||
287 | }, | 326 | }, |
288 | .probe = lm75_probe, | 327 | .probe = lm75_probe, |
289 | .remove = lm75_remove, | 328 | .remove = lm75_remove, |
diff --git a/drivers/hwmon/lm75.h b/drivers/hwmon/lm75.h index 7c93454bb4e3..e547a3eb4de3 100644 --- a/drivers/hwmon/lm75.h +++ b/drivers/hwmon/lm75.h | |||
@@ -30,6 +30,7 @@ | |||
30 | /* straight from the datasheet */ | 30 | /* straight from the datasheet */ |
31 | #define LM75_TEMP_MIN (-55000) | 31 | #define LM75_TEMP_MIN (-55000) |
32 | #define LM75_TEMP_MAX 125000 | 32 | #define LM75_TEMP_MAX 125000 |
33 | #define LM75_SHUTDOWN 0x01 | ||
33 | 34 | ||
34 | /* TEMP: 0.001C/bit (-55C to +125C) | 35 | /* TEMP: 0.001C/bit (-55C to +125C) |
35 | REG: (0.5C/bit, two's complement) << 7 */ | 36 | REG: (0.5C/bit, two's complement) << 7 */ |
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index 21d201befc2c..659308329308 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/hwmon.h> | 22 | #include <linux/hwmon.h> |
23 | #include <linux/hwmon-sysfs.h> | 23 | #include <linux/hwmon-sysfs.h> |
24 | #include <linux/i2c/ltc4245.h> | ||
24 | 25 | ||
25 | /* Here are names of the chip's registers (a.k.a. commands) */ | 26 | /* Here are names of the chip's registers (a.k.a. commands) */ |
26 | enum ltc4245_cmd { | 27 | enum ltc4245_cmd { |
@@ -60,8 +61,72 @@ struct ltc4245_data { | |||
60 | 61 | ||
61 | /* Voltage registers */ | 62 | /* Voltage registers */ |
62 | u8 vregs[0x0d]; | 63 | u8 vregs[0x0d]; |
64 | |||
65 | /* GPIO ADC registers */ | ||
66 | bool use_extra_gpios; | ||
67 | int gpios[3]; | ||
63 | }; | 68 | }; |
64 | 69 | ||
70 | /* | ||
71 | * Update the readings from the GPIO pins. If the driver has been configured to | ||
72 | * sample all GPIO's as analog voltages, a round-robin sampling method is used. | ||
73 | * Otherwise, only the configured GPIO pin is sampled. | ||
74 | * | ||
75 | * LOCKING: must hold data->update_lock | ||
76 | */ | ||
77 | static void ltc4245_update_gpios(struct device *dev) | ||
78 | { | ||
79 | struct i2c_client *client = to_i2c_client(dev); | ||
80 | struct ltc4245_data *data = i2c_get_clientdata(client); | ||
81 | u8 gpio_curr, gpio_next, gpio_reg; | ||
82 | int i; | ||
83 | |||
84 | /* no extra gpio support, we're basically done */ | ||
85 | if (!data->use_extra_gpios) { | ||
86 | data->gpios[0] = data->vregs[LTC4245_GPIOADC - 0x10]; | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * If the last reading was too long ago, then we mark all old GPIO | ||
92 | * readings as stale by setting them to -EAGAIN | ||
93 | */ | ||
94 | if (time_after(jiffies, data->last_updated + 5 * HZ)) { | ||
95 | dev_dbg(&client->dev, "Marking GPIOs invalid\n"); | ||
96 | for (i = 0; i < ARRAY_SIZE(data->gpios); i++) | ||
97 | data->gpios[i] = -EAGAIN; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * Get the current GPIO pin | ||
102 | * | ||
103 | * The datasheet calls these GPIO[1-3], but we'll calculate the zero | ||
104 | * based array index instead, and call them GPIO[0-2]. This is much | ||
105 | * easier to think about. | ||
106 | */ | ||
107 | gpio_curr = (data->cregs[LTC4245_GPIO] & 0xc0) >> 6; | ||
108 | if (gpio_curr > 0) | ||
109 | gpio_curr -= 1; | ||
110 | |||
111 | /* Read the GPIO voltage from the GPIOADC register */ | ||
112 | data->gpios[gpio_curr] = data->vregs[LTC4245_GPIOADC - 0x10]; | ||
113 | |||
114 | /* Find the next GPIO pin to read */ | ||
115 | gpio_next = (gpio_curr + 1) % ARRAY_SIZE(data->gpios); | ||
116 | |||
117 | /* | ||
118 | * Calculate the correct setting for the GPIO register so it will | ||
119 | * sample the next GPIO pin | ||
120 | */ | ||
121 | gpio_reg = (data->cregs[LTC4245_GPIO] & 0x3f) | ((gpio_next + 1) << 6); | ||
122 | |||
123 | /* Update the GPIO register */ | ||
124 | i2c_smbus_write_byte_data(client, LTC4245_GPIO, gpio_reg); | ||
125 | |||
126 | /* Update saved data */ | ||
127 | data->cregs[LTC4245_GPIO] = gpio_reg; | ||
128 | } | ||
129 | |||
65 | static struct ltc4245_data *ltc4245_update_device(struct device *dev) | 130 | static struct ltc4245_data *ltc4245_update_device(struct device *dev) |
66 | { | 131 | { |
67 | struct i2c_client *client = to_i2c_client(dev); | 132 | struct i2c_client *client = to_i2c_client(dev); |
@@ -93,6 +158,9 @@ static struct ltc4245_data *ltc4245_update_device(struct device *dev) | |||
93 | data->vregs[i] = val; | 158 | data->vregs[i] = val; |
94 | } | 159 | } |
95 | 160 | ||
161 | /* Update GPIO readings */ | ||
162 | ltc4245_update_gpios(dev); | ||
163 | |||
96 | data->last_updated = jiffies; | 164 | data->last_updated = jiffies; |
97 | data->valid = 1; | 165 | data->valid = 1; |
98 | } | 166 | } |
@@ -233,6 +301,22 @@ static ssize_t ltc4245_show_alarm(struct device *dev, | |||
233 | return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); | 301 | return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); |
234 | } | 302 | } |
235 | 303 | ||
304 | static ssize_t ltc4245_show_gpio(struct device *dev, | ||
305 | struct device_attribute *da, | ||
306 | char *buf) | ||
307 | { | ||
308 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
309 | struct ltc4245_data *data = ltc4245_update_device(dev); | ||
310 | int val = data->gpios[attr->index]; | ||
311 | |||
312 | /* handle stale GPIO's */ | ||
313 | if (val < 0) | ||
314 | return val; | ||
315 | |||
316 | /* Convert to millivolts and print */ | ||
317 | return snprintf(buf, PAGE_SIZE, "%u\n", val * 10); | ||
318 | } | ||
319 | |||
236 | /* These macros are used below in constructing device attribute objects | 320 | /* These macros are used below in constructing device attribute objects |
237 | * for use with sysfs_create_group() to make a sysfs device file | 321 | * for use with sysfs_create_group() to make a sysfs device file |
238 | * for each register. | 322 | * for each register. |
@@ -254,6 +338,10 @@ static ssize_t ltc4245_show_alarm(struct device *dev, | |||
254 | static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \ | 338 | static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \ |
255 | ltc4245_show_alarm, NULL, (mask), reg) | 339 | ltc4245_show_alarm, NULL, (mask), reg) |
256 | 340 | ||
341 | #define LTC4245_GPIO_VOLTAGE(name, gpio_num) \ | ||
342 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
343 | ltc4245_show_gpio, NULL, gpio_num) | ||
344 | |||
257 | /* Construct a sensor_device_attribute structure for each register */ | 345 | /* Construct a sensor_device_attribute structure for each register */ |
258 | 346 | ||
259 | /* Input voltages */ | 347 | /* Input voltages */ |
@@ -293,7 +381,9 @@ LTC4245_ALARM(in7_min_alarm, (1 << 2), LTC4245_FAULT2); | |||
293 | LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2); | 381 | LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2); |
294 | 382 | ||
295 | /* GPIO voltages */ | 383 | /* GPIO voltages */ |
296 | LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC); | 384 | LTC4245_GPIO_VOLTAGE(in9_input, 0); |
385 | LTC4245_GPIO_VOLTAGE(in10_input, 1); | ||
386 | LTC4245_GPIO_VOLTAGE(in11_input, 2); | ||
297 | 387 | ||
298 | /* Power Consumption (virtual) */ | 388 | /* Power Consumption (virtual) */ |
299 | LTC4245_POWER(power1_input, LTC4245_12VSENSE); | 389 | LTC4245_POWER(power1_input, LTC4245_12VSENSE); |
@@ -304,7 +394,7 @@ LTC4245_POWER(power4_input, LTC4245_VEESENSE); | |||
304 | /* Finally, construct an array of pointers to members of the above objects, | 394 | /* Finally, construct an array of pointers to members of the above objects, |
305 | * as required for sysfs_create_group() | 395 | * as required for sysfs_create_group() |
306 | */ | 396 | */ |
307 | static struct attribute *ltc4245_attributes[] = { | 397 | static struct attribute *ltc4245_std_attributes[] = { |
308 | &sensor_dev_attr_in1_input.dev_attr.attr, | 398 | &sensor_dev_attr_in1_input.dev_attr.attr, |
309 | &sensor_dev_attr_in2_input.dev_attr.attr, | 399 | &sensor_dev_attr_in2_input.dev_attr.attr, |
310 | &sensor_dev_attr_in3_input.dev_attr.attr, | 400 | &sensor_dev_attr_in3_input.dev_attr.attr, |
@@ -345,10 +435,77 @@ static struct attribute *ltc4245_attributes[] = { | |||
345 | NULL, | 435 | NULL, |
346 | }; | 436 | }; |
347 | 437 | ||
348 | static const struct attribute_group ltc4245_group = { | 438 | static struct attribute *ltc4245_gpio_attributes[] = { |
349 | .attrs = ltc4245_attributes, | 439 | &sensor_dev_attr_in10_input.dev_attr.attr, |
440 | &sensor_dev_attr_in11_input.dev_attr.attr, | ||
441 | NULL, | ||
442 | }; | ||
443 | |||
444 | static const struct attribute_group ltc4245_std_group = { | ||
445 | .attrs = ltc4245_std_attributes, | ||
446 | }; | ||
447 | |||
448 | static const struct attribute_group ltc4245_gpio_group = { | ||
449 | .attrs = ltc4245_gpio_attributes, | ||
350 | }; | 450 | }; |
351 | 451 | ||
452 | static int ltc4245_sysfs_create_groups(struct i2c_client *client) | ||
453 | { | ||
454 | struct ltc4245_data *data = i2c_get_clientdata(client); | ||
455 | struct device *dev = &client->dev; | ||
456 | int ret; | ||
457 | |||
458 | /* register the standard sysfs attributes */ | ||
459 | ret = sysfs_create_group(&dev->kobj, <c4245_std_group); | ||
460 | if (ret) { | ||
461 | dev_err(dev, "unable to register standard attributes\n"); | ||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | /* if we're using the extra gpio support, register it's attributes */ | ||
466 | if (data->use_extra_gpios) { | ||
467 | ret = sysfs_create_group(&dev->kobj, <c4245_gpio_group); | ||
468 | if (ret) { | ||
469 | dev_err(dev, "unable to register gpio attributes\n"); | ||
470 | sysfs_remove_group(&dev->kobj, <c4245_std_group); | ||
471 | return ret; | ||
472 | } | ||
473 | } | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static void ltc4245_sysfs_remove_groups(struct i2c_client *client) | ||
479 | { | ||
480 | struct ltc4245_data *data = i2c_get_clientdata(client); | ||
481 | struct device *dev = &client->dev; | ||
482 | |||
483 | if (data->use_extra_gpios) | ||
484 | sysfs_remove_group(&dev->kobj, <c4245_gpio_group); | ||
485 | |||
486 | sysfs_remove_group(&dev->kobj, <c4245_std_group); | ||
487 | } | ||
488 | |||
489 | static bool ltc4245_use_extra_gpios(struct i2c_client *client) | ||
490 | { | ||
491 | struct ltc4245_platform_data *pdata = dev_get_platdata(&client->dev); | ||
492 | #ifdef CONFIG_OF | ||
493 | struct device_node *np = client->dev.of_node; | ||
494 | #endif | ||
495 | |||
496 | /* prefer platform data */ | ||
497 | if (pdata) | ||
498 | return pdata->use_extra_gpios; | ||
499 | |||
500 | #ifdef CONFIG_OF | ||
501 | /* fallback on OF */ | ||
502 | if (of_find_property(np, "ltc4245,use-extra-gpios", NULL)) | ||
503 | return true; | ||
504 | #endif | ||
505 | |||
506 | return false; | ||
507 | } | ||
508 | |||
352 | static int ltc4245_probe(struct i2c_client *client, | 509 | static int ltc4245_probe(struct i2c_client *client, |
353 | const struct i2c_device_id *id) | 510 | const struct i2c_device_id *id) |
354 | { | 511 | { |
@@ -367,15 +524,16 @@ static int ltc4245_probe(struct i2c_client *client, | |||
367 | 524 | ||
368 | i2c_set_clientdata(client, data); | 525 | i2c_set_clientdata(client, data); |
369 | mutex_init(&data->update_lock); | 526 | mutex_init(&data->update_lock); |
527 | data->use_extra_gpios = ltc4245_use_extra_gpios(client); | ||
370 | 528 | ||
371 | /* Initialize the LTC4245 chip */ | 529 | /* Initialize the LTC4245 chip */ |
372 | i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00); | 530 | i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00); |
373 | i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00); | 531 | i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00); |
374 | 532 | ||
375 | /* Register sysfs hooks */ | 533 | /* Register sysfs hooks */ |
376 | ret = sysfs_create_group(&client->dev.kobj, <c4245_group); | 534 | ret = ltc4245_sysfs_create_groups(client); |
377 | if (ret) | 535 | if (ret) |
378 | goto out_sysfs_create_group; | 536 | goto out_sysfs_create_groups; |
379 | 537 | ||
380 | data->hwmon_dev = hwmon_device_register(&client->dev); | 538 | data->hwmon_dev = hwmon_device_register(&client->dev); |
381 | if (IS_ERR(data->hwmon_dev)) { | 539 | if (IS_ERR(data->hwmon_dev)) { |
@@ -386,8 +544,8 @@ static int ltc4245_probe(struct i2c_client *client, | |||
386 | return 0; | 544 | return 0; |
387 | 545 | ||
388 | out_hwmon_device_register: | 546 | out_hwmon_device_register: |
389 | sysfs_remove_group(&client->dev.kobj, <c4245_group); | 547 | ltc4245_sysfs_remove_groups(client); |
390 | out_sysfs_create_group: | 548 | out_sysfs_create_groups: |
391 | kfree(data); | 549 | kfree(data); |
392 | out_kzalloc: | 550 | out_kzalloc: |
393 | return ret; | 551 | return ret; |
@@ -398,8 +556,7 @@ static int ltc4245_remove(struct i2c_client *client) | |||
398 | struct ltc4245_data *data = i2c_get_clientdata(client); | 556 | struct ltc4245_data *data = i2c_get_clientdata(client); |
399 | 557 | ||
400 | hwmon_device_unregister(data->hwmon_dev); | 558 | hwmon_device_unregister(data->hwmon_dev); |
401 | sysfs_remove_group(&client->dev.kobj, <c4245_group); | 559 | ltc4245_sysfs_remove_groups(client); |
402 | |||
403 | kfree(data); | 560 | kfree(data); |
404 | 561 | ||
405 | return 0; | 562 | return 0; |
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 4a64b85d4ec9..68e69a49633c 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c | |||
@@ -1610,11 +1610,8 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) | |||
1610 | 1610 | ||
1611 | static int __init pc87360_device_add(unsigned short address) | 1611 | static int __init pc87360_device_add(unsigned short address) |
1612 | { | 1612 | { |
1613 | struct resource res = { | 1613 | struct resource res[3]; |
1614 | .name = "pc87360", | 1614 | int err, i, res_count; |
1615 | .flags = IORESOURCE_IO, | ||
1616 | }; | ||
1617 | int err, i; | ||
1618 | 1615 | ||
1619 | pdev = platform_device_alloc("pc87360", address); | 1616 | pdev = platform_device_alloc("pc87360", address); |
1620 | if (!pdev) { | 1617 | if (!pdev) { |
@@ -1623,22 +1620,28 @@ static int __init pc87360_device_add(unsigned short address) | |||
1623 | goto exit; | 1620 | goto exit; |
1624 | } | 1621 | } |
1625 | 1622 | ||
1623 | memset(res, 0, 3 * sizeof(struct resource)); | ||
1624 | res_count = 0; | ||
1626 | for (i = 0; i < 3; i++) { | 1625 | for (i = 0; i < 3; i++) { |
1627 | if (!extra_isa[i]) | 1626 | if (!extra_isa[i]) |
1628 | continue; | 1627 | continue; |
1629 | res.start = extra_isa[i]; | 1628 | res[res_count].start = extra_isa[i]; |
1630 | res.end = extra_isa[i] + PC87360_EXTENT - 1; | 1629 | res[res_count].end = extra_isa[i] + PC87360_EXTENT - 1; |
1630 | res[res_count].name = "pc87360", | ||
1631 | res[res_count].flags = IORESOURCE_IO, | ||
1631 | 1632 | ||
1632 | err = acpi_check_resource_conflict(&res); | 1633 | err = acpi_check_resource_conflict(&res[res_count]); |
1633 | if (err) | 1634 | if (err) |
1634 | goto exit_device_put; | 1635 | goto exit_device_put; |
1635 | 1636 | ||
1636 | err = platform_device_add_resources(pdev, &res, 1); | 1637 | res_count++; |
1637 | if (err) { | 1638 | } |
1638 | printk(KERN_ERR "pc87360: Device resource[%d] " | 1639 | |
1639 | "addition failed (%d)\n", i, err); | 1640 | err = platform_device_add_resources(pdev, res, res_count); |
1640 | goto exit_device_put; | 1641 | if (err) { |
1641 | } | 1642 | printk(KERN_ERR "pc87360: Device resources addition failed " |
1643 | "(%d)\n", err); | ||
1644 | goto exit_device_put; | ||
1642 | } | 1645 | } |
1643 | 1646 | ||
1644 | err = platform_device_add(pdev); | 1647 | err = platform_device_add(pdev); |
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index 3170b26d2443..9ec4daaf6ca6 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * pc87427.c - hardware monitoring driver for the | 2 | * pc87427.c - hardware monitoring driver for the |
3 | * National Semiconductor PC87427 Super-I/O chip | 3 | * National Semiconductor PC87427 Super-I/O chip |
4 | * Copyright (C) 2006 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2006, 2008, 2010 Jean Delvare <khali@linux-fr.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 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 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -15,10 +15,11 @@ | |||
15 | * Supports the following chips: | 15 | * Supports the following chips: |
16 | * | 16 | * |
17 | * Chip #vin #fan #pwm #temp devid | 17 | * Chip #vin #fan #pwm #temp devid |
18 | * PC87427 - 8 - - 0xF2 | 18 | * PC87427 - 8 4 6 0xF2 |
19 | * | 19 | * |
20 | * This driver assumes that no more than one chip is present. | 20 | * This driver assumes that no more than one chip is present. |
21 | * Only fan inputs are supported so far, although the chip can do much more. | 21 | * Only fans are fully supported so far. Temperatures are in read-only |
22 | * mode, and voltages aren't supported at all. | ||
22 | */ | 23 | */ |
23 | 24 | ||
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
@@ -57,6 +58,25 @@ struct pc87427_data { | |||
57 | u16 fan[8]; /* register values */ | 58 | u16 fan[8]; /* register values */ |
58 | u16 fan_min[8]; /* register values */ | 59 | u16 fan_min[8]; /* register values */ |
59 | u8 fan_status[8]; /* register values */ | 60 | u8 fan_status[8]; /* register values */ |
61 | |||
62 | u8 pwm_enabled; /* bit vector */ | ||
63 | u8 pwm_auto_ok; /* bit vector */ | ||
64 | u8 pwm_enable[4]; /* register values */ | ||
65 | u8 pwm[4]; /* register values */ | ||
66 | |||
67 | u8 temp_enabled; /* bit vector */ | ||
68 | s16 temp[6]; /* register values */ | ||
69 | s8 temp_min[6]; /* register values */ | ||
70 | s8 temp_max[6]; /* register values */ | ||
71 | s8 temp_crit[6]; /* register values */ | ||
72 | u8 temp_status[6]; /* register values */ | ||
73 | u8 temp_type[6]; /* register values */ | ||
74 | }; | ||
75 | |||
76 | struct pc87427_sio_data { | ||
77 | unsigned short address[2]; | ||
78 | u8 has_fanin; | ||
79 | u8 has_fanout; | ||
60 | }; | 80 | }; |
61 | 81 | ||
62 | /* | 82 | /* |
@@ -65,6 +85,13 @@ struct pc87427_data { | |||
65 | 85 | ||
66 | #define SIOREG_LDSEL 0x07 /* Logical device select */ | 86 | #define SIOREG_LDSEL 0x07 /* Logical device select */ |
67 | #define SIOREG_DEVID 0x20 /* Device ID */ | 87 | #define SIOREG_DEVID 0x20 /* Device ID */ |
88 | #define SIOREG_CF2 0x22 /* Configuration 2 */ | ||
89 | #define SIOREG_CF3 0x23 /* Configuration 3 */ | ||
90 | #define SIOREG_CF4 0x24 /* Configuration 4 */ | ||
91 | #define SIOREG_CF5 0x25 /* Configuration 5 */ | ||
92 | #define SIOREG_CFB 0x2B /* Configuration B */ | ||
93 | #define SIOREG_CFC 0x2C /* Configuration C */ | ||
94 | #define SIOREG_CFD 0x2D /* Configuration D */ | ||
68 | #define SIOREG_ACT 0x30 /* Device activation */ | 95 | #define SIOREG_ACT 0x30 /* Device activation */ |
69 | #define SIOREG_MAP 0x50 /* I/O or memory mapping */ | 96 | #define SIOREG_MAP 0x50 /* I/O or memory mapping */ |
70 | #define SIOREG_IOBASE 0x60 /* I/O base address */ | 97 | #define SIOREG_IOBASE 0x60 /* I/O base address */ |
@@ -102,6 +129,8 @@ static inline void superio_exit(int sioaddr) | |||
102 | #define BANK_FM(nr) (nr) | 129 | #define BANK_FM(nr) (nr) |
103 | #define BANK_FT(nr) (0x08 + (nr)) | 130 | #define BANK_FT(nr) (0x08 + (nr)) |
104 | #define BANK_FC(nr) (0x10 + (nr) * 2) | 131 | #define BANK_FC(nr) (0x10 + (nr) * 2) |
132 | #define BANK_TM(nr) (nr) | ||
133 | #define BANK_VM(nr) (0x08 + (nr)) | ||
105 | 134 | ||
106 | /* | 135 | /* |
107 | * I/O access functions | 136 | * I/O access functions |
@@ -179,6 +208,127 @@ static inline u16 fan_to_reg(unsigned long val) | |||
179 | } | 208 | } |
180 | 209 | ||
181 | /* | 210 | /* |
211 | * PWM registers and conversions | ||
212 | */ | ||
213 | |||
214 | #define PC87427_REG_PWM_ENABLE 0x10 | ||
215 | #define PC87427_REG_PWM_DUTY 0x12 | ||
216 | |||
217 | #define PWM_ENABLE_MODE_MASK (7 << 4) | ||
218 | #define PWM_ENABLE_CTLEN (1 << 0) | ||
219 | |||
220 | #define PWM_MODE_MANUAL (0 << 4) | ||
221 | #define PWM_MODE_AUTO (1 << 4) | ||
222 | #define PWM_MODE_OFF (2 << 4) | ||
223 | #define PWM_MODE_ON (7 << 4) | ||
224 | |||
225 | /* Dedicated function to read all registers related to a given PWM output. | ||
226 | This saves us quite a few locks and bank selections. | ||
227 | Must be called with data->lock held. | ||
228 | nr is from 0 to 3 */ | ||
229 | static void pc87427_readall_pwm(struct pc87427_data *data, u8 nr) | ||
230 | { | ||
231 | int iobase = data->address[LD_FAN]; | ||
232 | |||
233 | outb(BANK_FC(nr), iobase + PC87427_REG_BANK); | ||
234 | data->pwm_enable[nr] = inb(iobase + PC87427_REG_PWM_ENABLE); | ||
235 | data->pwm[nr] = inb(iobase + PC87427_REG_PWM_DUTY); | ||
236 | } | ||
237 | |||
238 | static inline int pwm_enable_from_reg(u8 reg) | ||
239 | { | ||
240 | switch (reg & PWM_ENABLE_MODE_MASK) { | ||
241 | case PWM_MODE_ON: | ||
242 | return 0; | ||
243 | case PWM_MODE_MANUAL: | ||
244 | case PWM_MODE_OFF: | ||
245 | return 1; | ||
246 | case PWM_MODE_AUTO: | ||
247 | return 2; | ||
248 | default: | ||
249 | return -EPROTO; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | static inline u8 pwm_enable_to_reg(unsigned long val, u8 pwmval) | ||
254 | { | ||
255 | switch (val) { | ||
256 | default: | ||
257 | return PWM_MODE_ON; | ||
258 | case 1: | ||
259 | return pwmval ? PWM_MODE_MANUAL : PWM_MODE_OFF; | ||
260 | case 2: | ||
261 | return PWM_MODE_AUTO; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Temperature registers and conversions | ||
267 | */ | ||
268 | |||
269 | #define PC87427_REG_TEMP_STATUS 0x10 | ||
270 | #define PC87427_REG_TEMP 0x14 | ||
271 | #define PC87427_REG_TEMP_MAX 0x18 | ||
272 | #define PC87427_REG_TEMP_MIN 0x19 | ||
273 | #define PC87427_REG_TEMP_CRIT 0x1a | ||
274 | #define PC87427_REG_TEMP_TYPE 0x1d | ||
275 | |||
276 | #define TEMP_STATUS_CHANEN (1 << 0) | ||
277 | #define TEMP_STATUS_LOWFLG (1 << 1) | ||
278 | #define TEMP_STATUS_HIGHFLG (1 << 2) | ||
279 | #define TEMP_STATUS_CRITFLG (1 << 3) | ||
280 | #define TEMP_STATUS_SENSERR (1 << 5) | ||
281 | #define TEMP_TYPE_MASK (3 << 5) | ||
282 | |||
283 | #define TEMP_TYPE_THERMISTOR (1 << 5) | ||
284 | #define TEMP_TYPE_REMOTE_DIODE (2 << 5) | ||
285 | #define TEMP_TYPE_LOCAL_DIODE (3 << 5) | ||
286 | |||
287 | /* Dedicated function to read all registers related to a given temperature | ||
288 | input. This saves us quite a few locks and bank selections. | ||
289 | Must be called with data->lock held. | ||
290 | nr is from 0 to 5 */ | ||
291 | static void pc87427_readall_temp(struct pc87427_data *data, u8 nr) | ||
292 | { | ||
293 | int iobase = data->address[LD_TEMP]; | ||
294 | |||
295 | outb(BANK_TM(nr), iobase + PC87427_REG_BANK); | ||
296 | data->temp[nr] = le16_to_cpu(inw(iobase + PC87427_REG_TEMP)); | ||
297 | data->temp_max[nr] = inb(iobase + PC87427_REG_TEMP_MAX); | ||
298 | data->temp_min[nr] = inb(iobase + PC87427_REG_TEMP_MIN); | ||
299 | data->temp_crit[nr] = inb(iobase + PC87427_REG_TEMP_CRIT); | ||
300 | data->temp_type[nr] = inb(iobase + PC87427_REG_TEMP_TYPE); | ||
301 | data->temp_status[nr] = inb(iobase + PC87427_REG_TEMP_STATUS); | ||
302 | /* Clear fan alarm bits */ | ||
303 | outb(data->temp_status[nr], iobase + PC87427_REG_TEMP_STATUS); | ||
304 | } | ||
305 | |||
306 | static inline unsigned int temp_type_from_reg(u8 reg) | ||
307 | { | ||
308 | switch (reg & TEMP_TYPE_MASK) { | ||
309 | case TEMP_TYPE_THERMISTOR: | ||
310 | return 4; | ||
311 | case TEMP_TYPE_REMOTE_DIODE: | ||
312 | case TEMP_TYPE_LOCAL_DIODE: | ||
313 | return 3; | ||
314 | default: | ||
315 | return 0; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /* We assume 8-bit thermal sensors; 9-bit thermal sensors are possible | ||
320 | too, but I have no idea how to figure out when they are used. */ | ||
321 | static inline long temp_from_reg(s16 reg) | ||
322 | { | ||
323 | return reg * 1000 / 256; | ||
324 | } | ||
325 | |||
326 | static inline long temp_from_reg8(s8 reg) | ||
327 | { | ||
328 | return reg * 1000; | ||
329 | } | ||
330 | |||
331 | /* | ||
182 | * Data interface | 332 | * Data interface |
183 | */ | 333 | */ |
184 | 334 | ||
@@ -198,6 +348,21 @@ static struct pc87427_data *pc87427_update_device(struct device *dev) | |||
198 | continue; | 348 | continue; |
199 | pc87427_readall_fan(data, i); | 349 | pc87427_readall_fan(data, i); |
200 | } | 350 | } |
351 | |||
352 | /* PWM outputs */ | ||
353 | for (i = 0; i < 4; i++) { | ||
354 | if (!(data->pwm_enabled & (1 << i))) | ||
355 | continue; | ||
356 | pc87427_readall_pwm(data, i); | ||
357 | } | ||
358 | |||
359 | /* Temperature channels */ | ||
360 | for (i = 0; i < 6; i++) { | ||
361 | if (!(data->temp_enabled & (1 << i))) | ||
362 | continue; | ||
363 | pc87427_readall_temp(data, i); | ||
364 | } | ||
365 | |||
201 | data->last_updated = jiffies; | 366 | data->last_updated = jiffies; |
202 | 367 | ||
203 | done: | 368 | done: |
@@ -208,9 +373,8 @@ done: | |||
208 | static ssize_t show_fan_input(struct device *dev, struct device_attribute | 373 | static ssize_t show_fan_input(struct device *dev, struct device_attribute |
209 | *devattr, char *buf) | 374 | *devattr, char *buf) |
210 | { | 375 | { |
211 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
212 | struct pc87427_data *data = pc87427_update_device(dev); | 376 | struct pc87427_data *data = pc87427_update_device(dev); |
213 | int nr = attr->index; | 377 | int nr = to_sensor_dev_attr(devattr)->index; |
214 | 378 | ||
215 | return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr])); | 379 | return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr])); |
216 | } | 380 | } |
@@ -218,9 +382,8 @@ static ssize_t show_fan_input(struct device *dev, struct device_attribute | |||
218 | static ssize_t show_fan_min(struct device *dev, struct device_attribute | 382 | static ssize_t show_fan_min(struct device *dev, struct device_attribute |
219 | *devattr, char *buf) | 383 | *devattr, char *buf) |
220 | { | 384 | { |
221 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
222 | struct pc87427_data *data = pc87427_update_device(dev); | 385 | struct pc87427_data *data = pc87427_update_device(dev); |
223 | int nr = attr->index; | 386 | int nr = to_sensor_dev_attr(devattr)->index; |
224 | 387 | ||
225 | return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr])); | 388 | return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr])); |
226 | } | 389 | } |
@@ -228,9 +391,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute | |||
228 | static ssize_t show_fan_alarm(struct device *dev, struct device_attribute | 391 | static ssize_t show_fan_alarm(struct device *dev, struct device_attribute |
229 | *devattr, char *buf) | 392 | *devattr, char *buf) |
230 | { | 393 | { |
231 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
232 | struct pc87427_data *data = pc87427_update_device(dev); | 394 | struct pc87427_data *data = pc87427_update_device(dev); |
233 | int nr = attr->index; | 395 | int nr = to_sensor_dev_attr(devattr)->index; |
234 | 396 | ||
235 | return sprintf(buf, "%d\n", !!(data->fan_status[nr] | 397 | return sprintf(buf, "%d\n", !!(data->fan_status[nr] |
236 | & FAN_STATUS_LOSPD)); | 398 | & FAN_STATUS_LOSPD)); |
@@ -239,9 +401,8 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute | |||
239 | static ssize_t show_fan_fault(struct device *dev, struct device_attribute | 401 | static ssize_t show_fan_fault(struct device *dev, struct device_attribute |
240 | *devattr, char *buf) | 402 | *devattr, char *buf) |
241 | { | 403 | { |
242 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
243 | struct pc87427_data *data = pc87427_update_device(dev); | 404 | struct pc87427_data *data = pc87427_update_device(dev); |
244 | int nr = attr->index; | 405 | int nr = to_sensor_dev_attr(devattr)->index; |
245 | 406 | ||
246 | return sprintf(buf, "%d\n", !!(data->fan_status[nr] | 407 | return sprintf(buf, "%d\n", !!(data->fan_status[nr] |
247 | & FAN_STATUS_STALL)); | 408 | & FAN_STATUS_STALL)); |
@@ -251,11 +412,13 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute | |||
251 | *devattr, const char *buf, size_t count) | 412 | *devattr, const char *buf, size_t count) |
252 | { | 413 | { |
253 | struct pc87427_data *data = dev_get_drvdata(dev); | 414 | struct pc87427_data *data = dev_get_drvdata(dev); |
254 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 415 | int nr = to_sensor_dev_attr(devattr)->index; |
255 | int nr = attr->index; | 416 | unsigned long val; |
256 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
257 | int iobase = data->address[LD_FAN]; | 417 | int iobase = data->address[LD_FAN]; |
258 | 418 | ||
419 | if (strict_strtoul(buf, 10, &val) < 0) | ||
420 | return -EINVAL; | ||
421 | |||
259 | mutex_lock(&data->lock); | 422 | mutex_lock(&data->lock); |
260 | outb(BANK_FM(nr), iobase + PC87427_REG_BANK); | 423 | outb(BANK_FM(nr), iobase + PC87427_REG_BANK); |
261 | /* The low speed limit registers are read-only while monitoring | 424 | /* The low speed limit registers are read-only while monitoring |
@@ -377,6 +540,390 @@ static const struct attribute_group pc87427_group_fan[8] = { | |||
377 | { .attrs = pc87427_attributes_fan[7] }, | 540 | { .attrs = pc87427_attributes_fan[7] }, |
378 | }; | 541 | }; |
379 | 542 | ||
543 | /* Must be called with data->lock held and pc87427_readall_pwm() freshly | ||
544 | called */ | ||
545 | static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode) | ||
546 | { | ||
547 | int iobase = data->address[LD_FAN]; | ||
548 | data->pwm_enable[nr] &= ~PWM_ENABLE_MODE_MASK; | ||
549 | data->pwm_enable[nr] |= mode; | ||
550 | outb(data->pwm_enable[nr], iobase + PC87427_REG_PWM_ENABLE); | ||
551 | } | ||
552 | |||
553 | static ssize_t show_pwm_enable(struct device *dev, struct device_attribute | ||
554 | *devattr, char *buf) | ||
555 | { | ||
556 | struct pc87427_data *data = pc87427_update_device(dev); | ||
557 | int nr = to_sensor_dev_attr(devattr)->index; | ||
558 | int pwm_enable; | ||
559 | |||
560 | pwm_enable = pwm_enable_from_reg(data->pwm_enable[nr]); | ||
561 | if (pwm_enable < 0) | ||
562 | return pwm_enable; | ||
563 | return sprintf(buf, "%d\n", pwm_enable); | ||
564 | } | ||
565 | |||
566 | static ssize_t set_pwm_enable(struct device *dev, struct device_attribute | ||
567 | *devattr, const char *buf, size_t count) | ||
568 | { | ||
569 | struct pc87427_data *data = dev_get_drvdata(dev); | ||
570 | int nr = to_sensor_dev_attr(devattr)->index; | ||
571 | unsigned long val; | ||
572 | |||
573 | if (strict_strtoul(buf, 10, &val) < 0 || val > 2) | ||
574 | return -EINVAL; | ||
575 | /* Can't go to automatic mode if it isn't configured */ | ||
576 | if (val == 2 && !(data->pwm_auto_ok & (1 << nr))) | ||
577 | return -EINVAL; | ||
578 | |||
579 | mutex_lock(&data->lock); | ||
580 | pc87427_readall_pwm(data, nr); | ||
581 | update_pwm_enable(data, nr, pwm_enable_to_reg(val, data->pwm[nr])); | ||
582 | mutex_unlock(&data->lock); | ||
583 | |||
584 | return count; | ||
585 | } | ||
586 | |||
587 | static ssize_t show_pwm(struct device *dev, struct device_attribute | ||
588 | *devattr, char *buf) | ||
589 | { | ||
590 | struct pc87427_data *data = pc87427_update_device(dev); | ||
591 | int nr = to_sensor_dev_attr(devattr)->index; | ||
592 | |||
593 | return sprintf(buf, "%d\n", (int)data->pwm[nr]); | ||
594 | } | ||
595 | |||
596 | static ssize_t set_pwm(struct device *dev, struct device_attribute | ||
597 | *devattr, const char *buf, size_t count) | ||
598 | { | ||
599 | struct pc87427_data *data = dev_get_drvdata(dev); | ||
600 | int nr = to_sensor_dev_attr(devattr)->index; | ||
601 | unsigned long val; | ||
602 | int iobase = data->address[LD_FAN]; | ||
603 | u8 mode; | ||
604 | |||
605 | if (strict_strtoul(buf, 10, &val) < 0 || val > 0xff) | ||
606 | return -EINVAL; | ||
607 | |||
608 | mutex_lock(&data->lock); | ||
609 | pc87427_readall_pwm(data, nr); | ||
610 | mode = data->pwm_enable[nr] & PWM_ENABLE_MODE_MASK; | ||
611 | if (mode != PWM_MODE_MANUAL && mode != PWM_MODE_OFF) { | ||
612 | dev_notice(dev, "Can't set PWM%d duty cycle while not in " | ||
613 | "manual mode\n", nr + 1); | ||
614 | mutex_unlock(&data->lock); | ||
615 | return -EPERM; | ||
616 | } | ||
617 | |||
618 | /* We may have to change the mode */ | ||
619 | if (mode == PWM_MODE_MANUAL && val == 0) { | ||
620 | /* Transition from Manual to Off */ | ||
621 | update_pwm_enable(data, nr, PWM_MODE_OFF); | ||
622 | mode = PWM_MODE_OFF; | ||
623 | dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1, | ||
624 | "manual", "off"); | ||
625 | } else if (mode == PWM_MODE_OFF && val != 0) { | ||
626 | /* Transition from Off to Manual */ | ||
627 | update_pwm_enable(data, nr, PWM_MODE_MANUAL); | ||
628 | mode = PWM_MODE_MANUAL; | ||
629 | dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1, | ||
630 | "off", "manual"); | ||
631 | } | ||
632 | |||
633 | data->pwm[nr] = val; | ||
634 | if (mode == PWM_MODE_MANUAL) | ||
635 | outb(val, iobase + PC87427_REG_PWM_DUTY); | ||
636 | mutex_unlock(&data->lock); | ||
637 | |||
638 | return count; | ||
639 | } | ||
640 | |||
641 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | ||
642 | show_pwm_enable, set_pwm_enable, 0); | ||
643 | static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, | ||
644 | show_pwm_enable, set_pwm_enable, 1); | ||
645 | static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, | ||
646 | show_pwm_enable, set_pwm_enable, 2); | ||
647 | static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, | ||
648 | show_pwm_enable, set_pwm_enable, 3); | ||
649 | |||
650 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); | ||
651 | static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); | ||
652 | static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); | ||
653 | static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); | ||
654 | |||
655 | static struct attribute *pc87427_attributes_pwm[4][3] = { | ||
656 | { | ||
657 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
658 | &sensor_dev_attr_pwm1.dev_attr.attr, | ||
659 | NULL | ||
660 | }, { | ||
661 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
662 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
663 | NULL | ||
664 | }, { | ||
665 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
666 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
667 | NULL | ||
668 | }, { | ||
669 | &sensor_dev_attr_pwm4_enable.dev_attr.attr, | ||
670 | &sensor_dev_attr_pwm4.dev_attr.attr, | ||
671 | NULL | ||
672 | } | ||
673 | }; | ||
674 | |||
675 | static const struct attribute_group pc87427_group_pwm[4] = { | ||
676 | { .attrs = pc87427_attributes_pwm[0] }, | ||
677 | { .attrs = pc87427_attributes_pwm[1] }, | ||
678 | { .attrs = pc87427_attributes_pwm[2] }, | ||
679 | { .attrs = pc87427_attributes_pwm[3] }, | ||
680 | }; | ||
681 | |||
682 | static ssize_t show_temp_input(struct device *dev, struct device_attribute | ||
683 | *devattr, char *buf) | ||
684 | { | ||
685 | struct pc87427_data *data = pc87427_update_device(dev); | ||
686 | int nr = to_sensor_dev_attr(devattr)->index; | ||
687 | |||
688 | return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr])); | ||
689 | } | ||
690 | |||
691 | static ssize_t show_temp_min(struct device *dev, struct device_attribute | ||
692 | *devattr, char *buf) | ||
693 | { | ||
694 | struct pc87427_data *data = pc87427_update_device(dev); | ||
695 | int nr = to_sensor_dev_attr(devattr)->index; | ||
696 | |||
697 | return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_min[nr])); | ||
698 | } | ||
699 | |||
700 | static ssize_t show_temp_max(struct device *dev, struct device_attribute | ||
701 | *devattr, char *buf) | ||
702 | { | ||
703 | struct pc87427_data *data = pc87427_update_device(dev); | ||
704 | int nr = to_sensor_dev_attr(devattr)->index; | ||
705 | |||
706 | return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_max[nr])); | ||
707 | } | ||
708 | |||
709 | static ssize_t show_temp_crit(struct device *dev, struct device_attribute | ||
710 | *devattr, char *buf) | ||
711 | { | ||
712 | struct pc87427_data *data = pc87427_update_device(dev); | ||
713 | int nr = to_sensor_dev_attr(devattr)->index; | ||
714 | |||
715 | return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_crit[nr])); | ||
716 | } | ||
717 | |||
718 | static ssize_t show_temp_type(struct device *dev, struct device_attribute | ||
719 | *devattr, char *buf) | ||
720 | { | ||
721 | struct pc87427_data *data = pc87427_update_device(dev); | ||
722 | int nr = to_sensor_dev_attr(devattr)->index; | ||
723 | |||
724 | return sprintf(buf, "%u\n", temp_type_from_reg(data->temp_type[nr])); | ||
725 | } | ||
726 | |||
727 | static ssize_t show_temp_min_alarm(struct device *dev, struct device_attribute | ||
728 | *devattr, char *buf) | ||
729 | { | ||
730 | struct pc87427_data *data = pc87427_update_device(dev); | ||
731 | int nr = to_sensor_dev_attr(devattr)->index; | ||
732 | |||
733 | return sprintf(buf, "%d\n", !!(data->temp_status[nr] | ||
734 | & TEMP_STATUS_LOWFLG)); | ||
735 | } | ||
736 | |||
737 | static ssize_t show_temp_max_alarm(struct device *dev, struct device_attribute | ||
738 | *devattr, char *buf) | ||
739 | { | ||
740 | struct pc87427_data *data = pc87427_update_device(dev); | ||
741 | int nr = to_sensor_dev_attr(devattr)->index; | ||
742 | |||
743 | return sprintf(buf, "%d\n", !!(data->temp_status[nr] | ||
744 | & TEMP_STATUS_HIGHFLG)); | ||
745 | } | ||
746 | |||
747 | static ssize_t show_temp_crit_alarm(struct device *dev, struct device_attribute | ||
748 | *devattr, char *buf) | ||
749 | { | ||
750 | struct pc87427_data *data = pc87427_update_device(dev); | ||
751 | int nr = to_sensor_dev_attr(devattr)->index; | ||
752 | |||
753 | return sprintf(buf, "%d\n", !!(data->temp_status[nr] | ||
754 | & TEMP_STATUS_CRITFLG)); | ||
755 | } | ||
756 | |||
757 | static ssize_t show_temp_fault(struct device *dev, struct device_attribute | ||
758 | *devattr, char *buf) | ||
759 | { | ||
760 | struct pc87427_data *data = pc87427_update_device(dev); | ||
761 | int nr = to_sensor_dev_attr(devattr)->index; | ||
762 | |||
763 | return sprintf(buf, "%d\n", !!(data->temp_status[nr] | ||
764 | & TEMP_STATUS_SENSERR)); | ||
765 | } | ||
766 | |||
767 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); | ||
768 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); | ||
769 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2); | ||
770 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3); | ||
771 | static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4); | ||
772 | static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5); | ||
773 | |||
774 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min, NULL, 0); | ||
775 | static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min, NULL, 1); | ||
776 | static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min, NULL, 2); | ||
777 | static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min, NULL, 3); | ||
778 | static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min, NULL, 4); | ||
779 | static SENSOR_DEVICE_ATTR(temp6_min, S_IRUGO, show_temp_min, NULL, 5); | ||
780 | |||
781 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0); | ||
782 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1); | ||
783 | static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2); | ||
784 | static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3); | ||
785 | static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4); | ||
786 | static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5); | ||
787 | |||
788 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); | ||
789 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1); | ||
790 | static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2); | ||
791 | static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3); | ||
792 | static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4); | ||
793 | static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5); | ||
794 | |||
795 | static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0); | ||
796 | static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1); | ||
797 | static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2); | ||
798 | static SENSOR_DEVICE_ATTR(temp4_type, S_IRUGO, show_temp_type, NULL, 3); | ||
799 | static SENSOR_DEVICE_ATTR(temp5_type, S_IRUGO, show_temp_type, NULL, 4); | ||
800 | static SENSOR_DEVICE_ATTR(temp6_type, S_IRUGO, show_temp_type, NULL, 5); | ||
801 | |||
802 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, | ||
803 | show_temp_min_alarm, NULL, 0); | ||
804 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, | ||
805 | show_temp_min_alarm, NULL, 1); | ||
806 | static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, | ||
807 | show_temp_min_alarm, NULL, 2); | ||
808 | static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, | ||
809 | show_temp_min_alarm, NULL, 3); | ||
810 | static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, | ||
811 | show_temp_min_alarm, NULL, 4); | ||
812 | static SENSOR_DEVICE_ATTR(temp6_min_alarm, S_IRUGO, | ||
813 | show_temp_min_alarm, NULL, 5); | ||
814 | |||
815 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, | ||
816 | show_temp_max_alarm, NULL, 0); | ||
817 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, | ||
818 | show_temp_max_alarm, NULL, 1); | ||
819 | static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, | ||
820 | show_temp_max_alarm, NULL, 2); | ||
821 | static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, | ||
822 | show_temp_max_alarm, NULL, 3); | ||
823 | static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, | ||
824 | show_temp_max_alarm, NULL, 4); | ||
825 | static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, | ||
826 | show_temp_max_alarm, NULL, 5); | ||
827 | |||
828 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, | ||
829 | show_temp_crit_alarm, NULL, 0); | ||
830 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, | ||
831 | show_temp_crit_alarm, NULL, 1); | ||
832 | static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, | ||
833 | show_temp_crit_alarm, NULL, 2); | ||
834 | static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, | ||
835 | show_temp_crit_alarm, NULL, 3); | ||
836 | static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, | ||
837 | show_temp_crit_alarm, NULL, 4); | ||
838 | static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, | ||
839 | show_temp_crit_alarm, NULL, 5); | ||
840 | |||
841 | static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); | ||
842 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); | ||
843 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); | ||
844 | static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); | ||
845 | static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4); | ||
846 | static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5); | ||
847 | |||
848 | static struct attribute *pc87427_attributes_temp[6][10] = { | ||
849 | { | ||
850 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
851 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
852 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
853 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
854 | &sensor_dev_attr_temp1_type.dev_attr.attr, | ||
855 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
856 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
857 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
858 | &sensor_dev_attr_temp1_fault.dev_attr.attr, | ||
859 | NULL | ||
860 | }, { | ||
861 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
862 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
863 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
864 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
865 | &sensor_dev_attr_temp2_type.dev_attr.attr, | ||
866 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
867 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
868 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
869 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
870 | NULL | ||
871 | }, { | ||
872 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
873 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
874 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
875 | &sensor_dev_attr_temp3_crit.dev_attr.attr, | ||
876 | &sensor_dev_attr_temp3_type.dev_attr.attr, | ||
877 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, | ||
878 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | ||
879 | &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, | ||
880 | &sensor_dev_attr_temp3_fault.dev_attr.attr, | ||
881 | NULL | ||
882 | }, { | ||
883 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
884 | &sensor_dev_attr_temp4_min.dev_attr.attr, | ||
885 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
886 | &sensor_dev_attr_temp4_crit.dev_attr.attr, | ||
887 | &sensor_dev_attr_temp4_type.dev_attr.attr, | ||
888 | &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, | ||
889 | &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, | ||
890 | &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, | ||
891 | &sensor_dev_attr_temp4_fault.dev_attr.attr, | ||
892 | NULL | ||
893 | }, { | ||
894 | &sensor_dev_attr_temp5_input.dev_attr.attr, | ||
895 | &sensor_dev_attr_temp5_min.dev_attr.attr, | ||
896 | &sensor_dev_attr_temp5_max.dev_attr.attr, | ||
897 | &sensor_dev_attr_temp5_crit.dev_attr.attr, | ||
898 | &sensor_dev_attr_temp5_type.dev_attr.attr, | ||
899 | &sensor_dev_attr_temp5_min_alarm.dev_attr.attr, | ||
900 | &sensor_dev_attr_temp5_max_alarm.dev_attr.attr, | ||
901 | &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, | ||
902 | &sensor_dev_attr_temp5_fault.dev_attr.attr, | ||
903 | NULL | ||
904 | }, { | ||
905 | &sensor_dev_attr_temp6_input.dev_attr.attr, | ||
906 | &sensor_dev_attr_temp6_min.dev_attr.attr, | ||
907 | &sensor_dev_attr_temp6_max.dev_attr.attr, | ||
908 | &sensor_dev_attr_temp6_crit.dev_attr.attr, | ||
909 | &sensor_dev_attr_temp6_type.dev_attr.attr, | ||
910 | &sensor_dev_attr_temp6_min_alarm.dev_attr.attr, | ||
911 | &sensor_dev_attr_temp6_max_alarm.dev_attr.attr, | ||
912 | &sensor_dev_attr_temp6_crit_alarm.dev_attr.attr, | ||
913 | &sensor_dev_attr_temp6_fault.dev_attr.attr, | ||
914 | NULL | ||
915 | } | ||
916 | }; | ||
917 | |||
918 | static const struct attribute_group pc87427_group_temp[6] = { | ||
919 | { .attrs = pc87427_attributes_temp[0] }, | ||
920 | { .attrs = pc87427_attributes_temp[1] }, | ||
921 | { .attrs = pc87427_attributes_temp[2] }, | ||
922 | { .attrs = pc87427_attributes_temp[3] }, | ||
923 | { .attrs = pc87427_attributes_temp[4] }, | ||
924 | { .attrs = pc87427_attributes_temp[5] }, | ||
925 | }; | ||
926 | |||
380 | static ssize_t show_name(struct device *dev, struct device_attribute | 927 | static ssize_t show_name(struct device *dev, struct device_attribute |
381 | *devattr, char *buf) | 928 | *devattr, char *buf) |
382 | { | 929 | { |
@@ -391,8 +938,49 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | |||
391 | * Device detection, attach and detach | 938 | * Device detection, attach and detach |
392 | */ | 939 | */ |
393 | 940 | ||
941 | static void pc87427_release_regions(struct platform_device *pdev, int count) | ||
942 | { | ||
943 | struct resource *res; | ||
944 | int i; | ||
945 | |||
946 | for (i = 0; i < count; i++) { | ||
947 | res = platform_get_resource(pdev, IORESOURCE_IO, i); | ||
948 | release_region(res->start, resource_size(res)); | ||
949 | } | ||
950 | } | ||
951 | |||
952 | static int __devinit pc87427_request_regions(struct platform_device *pdev, | ||
953 | int count) | ||
954 | { | ||
955 | struct resource *res; | ||
956 | int i, err = 0; | ||
957 | |||
958 | for (i = 0; i < count; i++) { | ||
959 | res = platform_get_resource(pdev, IORESOURCE_IO, i); | ||
960 | if (!res) { | ||
961 | err = -ENOENT; | ||
962 | dev_err(&pdev->dev, "Missing resource #%d\n", i); | ||
963 | break; | ||
964 | } | ||
965 | if (!request_region(res->start, resource_size(res), DRVNAME)) { | ||
966 | err = -EBUSY; | ||
967 | dev_err(&pdev->dev, | ||
968 | "Failed to request region 0x%lx-0x%lx\n", | ||
969 | (unsigned long)res->start, | ||
970 | (unsigned long)res->end); | ||
971 | break; | ||
972 | } | ||
973 | } | ||
974 | |||
975 | if (err && i) | ||
976 | pc87427_release_regions(pdev, i); | ||
977 | |||
978 | return err; | ||
979 | } | ||
980 | |||
394 | static void __devinit pc87427_init_device(struct device *dev) | 981 | static void __devinit pc87427_init_device(struct device *dev) |
395 | { | 982 | { |
983 | struct pc87427_sio_data *sio_data = dev->platform_data; | ||
396 | struct pc87427_data *data = dev_get_drvdata(dev); | 984 | struct pc87427_data *data = dev_get_drvdata(dev); |
397 | int i; | 985 | int i; |
398 | u8 reg; | 986 | u8 reg; |
@@ -400,10 +988,12 @@ static void __devinit pc87427_init_device(struct device *dev) | |||
400 | /* The FMC module should be ready */ | 988 | /* The FMC module should be ready */ |
401 | reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK); | 989 | reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK); |
402 | if (!(reg & 0x80)) | 990 | if (!(reg & 0x80)) |
403 | dev_warn(dev, "FMC module not ready!\n"); | 991 | dev_warn(dev, "%s module not ready!\n", "FMC"); |
404 | 992 | ||
405 | /* Check which fans are enabled */ | 993 | /* Check which fans are enabled */ |
406 | for (i = 0; i < 8; i++) { | 994 | for (i = 0; i < 8; i++) { |
995 | if (!(sio_data->has_fanin & (1 << i))) /* Not wired */ | ||
996 | continue; | ||
407 | reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i), | 997 | reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i), |
408 | PC87427_REG_FAN_STATUS); | 998 | PC87427_REG_FAN_STATUS); |
409 | if (reg & FAN_STATUS_MONEN) | 999 | if (reg & FAN_STATUS_MONEN) |
@@ -411,37 +1001,93 @@ static void __devinit pc87427_init_device(struct device *dev) | |||
411 | } | 1001 | } |
412 | 1002 | ||
413 | if (!data->fan_enabled) { | 1003 | if (!data->fan_enabled) { |
414 | dev_dbg(dev, "Enabling all fan inputs\n"); | 1004 | dev_dbg(dev, "Enabling monitoring of all fans\n"); |
415 | for (i = 0; i < 8; i++) | 1005 | for (i = 0; i < 8; i++) { |
1006 | if (!(sio_data->has_fanin & (1 << i))) /* Not wired */ | ||
1007 | continue; | ||
416 | pc87427_write8_bank(data, LD_FAN, BANK_FM(i), | 1008 | pc87427_write8_bank(data, LD_FAN, BANK_FM(i), |
417 | PC87427_REG_FAN_STATUS, | 1009 | PC87427_REG_FAN_STATUS, |
418 | FAN_STATUS_MONEN); | 1010 | FAN_STATUS_MONEN); |
419 | data->fan_enabled = 0xff; | 1011 | } |
1012 | data->fan_enabled = sio_data->has_fanin; | ||
1013 | } | ||
1014 | |||
1015 | /* Check which PWM outputs are enabled */ | ||
1016 | for (i = 0; i < 4; i++) { | ||
1017 | if (!(sio_data->has_fanout & (1 << i))) /* Not wired */ | ||
1018 | continue; | ||
1019 | reg = pc87427_read8_bank(data, LD_FAN, BANK_FC(i), | ||
1020 | PC87427_REG_PWM_ENABLE); | ||
1021 | if (reg & PWM_ENABLE_CTLEN) | ||
1022 | data->pwm_enabled |= (1 << i); | ||
1023 | |||
1024 | /* We don't expose an interface to reconfigure the automatic | ||
1025 | fan control mode, so only allow to return to this mode if | ||
1026 | it was originally set. */ | ||
1027 | if ((reg & PWM_ENABLE_MODE_MASK) == PWM_MODE_AUTO) { | ||
1028 | dev_dbg(dev, "PWM%d is in automatic control mode\n", | ||
1029 | i + 1); | ||
1030 | data->pwm_auto_ok |= (1 << i); | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | /* The HMC module should be ready */ | ||
1035 | reg = pc87427_read8(data, LD_TEMP, PC87427_REG_BANK); | ||
1036 | if (!(reg & 0x80)) | ||
1037 | dev_warn(dev, "%s module not ready!\n", "HMC"); | ||
1038 | |||
1039 | /* Check which temperature channels are enabled */ | ||
1040 | for (i = 0; i < 6; i++) { | ||
1041 | reg = pc87427_read8_bank(data, LD_TEMP, BANK_TM(i), | ||
1042 | PC87427_REG_TEMP_STATUS); | ||
1043 | if (reg & TEMP_STATUS_CHANEN) | ||
1044 | data->temp_enabled |= (1 << i); | ||
1045 | } | ||
1046 | } | ||
1047 | |||
1048 | static void pc87427_remove_files(struct device *dev) | ||
1049 | { | ||
1050 | struct pc87427_data *data = dev_get_drvdata(dev); | ||
1051 | int i; | ||
1052 | |||
1053 | device_remove_file(dev, &dev_attr_name); | ||
1054 | for (i = 0; i < 8; i++) { | ||
1055 | if (!(data->fan_enabled & (1 << i))) | ||
1056 | continue; | ||
1057 | sysfs_remove_group(&dev->kobj, &pc87427_group_fan[i]); | ||
1058 | } | ||
1059 | for (i = 0; i < 4; i++) { | ||
1060 | if (!(data->pwm_enabled & (1 << i))) | ||
1061 | continue; | ||
1062 | sysfs_remove_group(&dev->kobj, &pc87427_group_pwm[i]); | ||
1063 | } | ||
1064 | for (i = 0; i < 6; i++) { | ||
1065 | if (!(data->temp_enabled & (1 << i))) | ||
1066 | continue; | ||
1067 | sysfs_remove_group(&dev->kobj, &pc87427_group_temp[i]); | ||
420 | } | 1068 | } |
421 | } | 1069 | } |
422 | 1070 | ||
423 | static int __devinit pc87427_probe(struct platform_device *pdev) | 1071 | static int __devinit pc87427_probe(struct platform_device *pdev) |
424 | { | 1072 | { |
1073 | struct pc87427_sio_data *sio_data = pdev->dev.platform_data; | ||
425 | struct pc87427_data *data; | 1074 | struct pc87427_data *data; |
426 | struct resource *res; | 1075 | int i, err, res_count; |
427 | int i, err; | ||
428 | 1076 | ||
429 | if (!(data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL))) { | 1077 | data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL); |
1078 | if (!data) { | ||
430 | err = -ENOMEM; | 1079 | err = -ENOMEM; |
431 | printk(KERN_ERR DRVNAME ": Out of memory\n"); | 1080 | printk(KERN_ERR DRVNAME ": Out of memory\n"); |
432 | goto exit; | 1081 | goto exit; |
433 | } | 1082 | } |
434 | 1083 | ||
435 | /* This will need to be revisited when we add support for | 1084 | data->address[0] = sio_data->address[0]; |
436 | temperature and voltage monitoring. */ | 1085 | data->address[1] = sio_data->address[1]; |
437 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1086 | res_count = (data->address[0] != 0) + (data->address[1] != 0); |
438 | if (!request_region(res->start, resource_size(res), DRVNAME)) { | 1087 | |
439 | err = -EBUSY; | 1088 | err = pc87427_request_regions(pdev, res_count); |
440 | dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", | 1089 | if (err) |
441 | (unsigned long)res->start, (unsigned long)res->end); | ||
442 | goto exit_kfree; | 1090 | goto exit_kfree; |
443 | } | ||
444 | data->address[0] = res->start; | ||
445 | 1091 | ||
446 | mutex_init(&data->lock); | 1092 | mutex_init(&data->lock); |
447 | data->name = "pc87427"; | 1093 | data->name = "pc87427"; |
@@ -449,13 +1095,31 @@ static int __devinit pc87427_probe(struct platform_device *pdev) | |||
449 | pc87427_init_device(&pdev->dev); | 1095 | pc87427_init_device(&pdev->dev); |
450 | 1096 | ||
451 | /* Register sysfs hooks */ | 1097 | /* Register sysfs hooks */ |
452 | if ((err = device_create_file(&pdev->dev, &dev_attr_name))) | 1098 | err = device_create_file(&pdev->dev, &dev_attr_name); |
1099 | if (err) | ||
453 | goto exit_release_region; | 1100 | goto exit_release_region; |
454 | for (i = 0; i < 8; i++) { | 1101 | for (i = 0; i < 8; i++) { |
455 | if (!(data->fan_enabled & (1 << i))) | 1102 | if (!(data->fan_enabled & (1 << i))) |
456 | continue; | 1103 | continue; |
457 | if ((err = sysfs_create_group(&pdev->dev.kobj, | 1104 | err = sysfs_create_group(&pdev->dev.kobj, |
458 | &pc87427_group_fan[i]))) | 1105 | &pc87427_group_fan[i]); |
1106 | if (err) | ||
1107 | goto exit_remove_files; | ||
1108 | } | ||
1109 | for (i = 0; i < 4; i++) { | ||
1110 | if (!(data->pwm_enabled & (1 << i))) | ||
1111 | continue; | ||
1112 | err = sysfs_create_group(&pdev->dev.kobj, | ||
1113 | &pc87427_group_pwm[i]); | ||
1114 | if (err) | ||
1115 | goto exit_remove_files; | ||
1116 | } | ||
1117 | for (i = 0; i < 6; i++) { | ||
1118 | if (!(data->temp_enabled & (1 << i))) | ||
1119 | continue; | ||
1120 | err = sysfs_create_group(&pdev->dev.kobj, | ||
1121 | &pc87427_group_temp[i]); | ||
1122 | if (err) | ||
459 | goto exit_remove_files; | 1123 | goto exit_remove_files; |
460 | } | 1124 | } |
461 | 1125 | ||
@@ -469,13 +1133,9 @@ static int __devinit pc87427_probe(struct platform_device *pdev) | |||
469 | return 0; | 1133 | return 0; |
470 | 1134 | ||
471 | exit_remove_files: | 1135 | exit_remove_files: |
472 | for (i = 0; i < 8; i++) { | 1136 | pc87427_remove_files(&pdev->dev); |
473 | if (!(data->fan_enabled & (1 << i))) | ||
474 | continue; | ||
475 | sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); | ||
476 | } | ||
477 | exit_release_region: | 1137 | exit_release_region: |
478 | release_region(res->start, resource_size(res)); | 1138 | pc87427_release_regions(pdev, res_count); |
479 | exit_kfree: | 1139 | exit_kfree: |
480 | platform_set_drvdata(pdev, NULL); | 1140 | platform_set_drvdata(pdev, NULL); |
481 | kfree(data); | 1141 | kfree(data); |
@@ -486,21 +1146,16 @@ exit: | |||
486 | static int __devexit pc87427_remove(struct platform_device *pdev) | 1146 | static int __devexit pc87427_remove(struct platform_device *pdev) |
487 | { | 1147 | { |
488 | struct pc87427_data *data = platform_get_drvdata(pdev); | 1148 | struct pc87427_data *data = platform_get_drvdata(pdev); |
489 | struct resource *res; | 1149 | int res_count; |
490 | int i; | 1150 | |
1151 | res_count = (data->address[0] != 0) + (data->address[1] != 0); | ||
491 | 1152 | ||
492 | hwmon_device_unregister(data->hwmon_dev); | 1153 | hwmon_device_unregister(data->hwmon_dev); |
493 | device_remove_file(&pdev->dev, &dev_attr_name); | 1154 | pc87427_remove_files(&pdev->dev); |
494 | for (i = 0; i < 8; i++) { | ||
495 | if (!(data->fan_enabled & (1 << i))) | ||
496 | continue; | ||
497 | sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); | ||
498 | } | ||
499 | platform_set_drvdata(pdev, NULL); | 1155 | platform_set_drvdata(pdev, NULL); |
500 | kfree(data); | 1156 | kfree(data); |
501 | 1157 | ||
502 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1158 | pc87427_release_regions(pdev, res_count); |
503 | release_region(res->start, resource_size(res)); | ||
504 | 1159 | ||
505 | return 0; | 1160 | return 0; |
506 | } | 1161 | } |
@@ -515,34 +1170,50 @@ static struct platform_driver pc87427_driver = { | |||
515 | .remove = __devexit_p(pc87427_remove), | 1170 | .remove = __devexit_p(pc87427_remove), |
516 | }; | 1171 | }; |
517 | 1172 | ||
518 | static int __init pc87427_device_add(unsigned short address) | 1173 | static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data) |
519 | { | 1174 | { |
520 | struct resource res = { | 1175 | struct resource res[2] = { |
521 | .start = address, | 1176 | { .flags = IORESOURCE_IO }, |
522 | .end = address + REGION_LENGTH - 1, | 1177 | { .flags = IORESOURCE_IO }, |
523 | .name = logdev_str[0], | ||
524 | .flags = IORESOURCE_IO, | ||
525 | }; | 1178 | }; |
526 | int err; | 1179 | int err, i, res_count; |
527 | 1180 | ||
528 | err = acpi_check_resource_conflict(&res); | 1181 | res_count = 0; |
529 | if (err) | 1182 | for (i = 0; i < 2; i++) { |
530 | goto exit; | 1183 | if (!sio_data->address[i]) |
1184 | continue; | ||
1185 | res[res_count].start = sio_data->address[i]; | ||
1186 | res[res_count].end = sio_data->address[i] + REGION_LENGTH - 1; | ||
1187 | res[res_count].name = logdev_str[i]; | ||
531 | 1188 | ||
532 | pdev = platform_device_alloc(DRVNAME, address); | 1189 | err = acpi_check_resource_conflict(&res[res_count]); |
1190 | if (err) | ||
1191 | goto exit; | ||
1192 | |||
1193 | res_count++; | ||
1194 | } | ||
1195 | |||
1196 | pdev = platform_device_alloc(DRVNAME, res[0].start); | ||
533 | if (!pdev) { | 1197 | if (!pdev) { |
534 | err = -ENOMEM; | 1198 | err = -ENOMEM; |
535 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | 1199 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); |
536 | goto exit; | 1200 | goto exit; |
537 | } | 1201 | } |
538 | 1202 | ||
539 | err = platform_device_add_resources(pdev, &res, 1); | 1203 | err = platform_device_add_resources(pdev, res, res_count); |
540 | if (err) { | 1204 | if (err) { |
541 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | 1205 | printk(KERN_ERR DRVNAME ": Device resource addition failed " |
542 | "(%d)\n", err); | 1206 | "(%d)\n", err); |
543 | goto exit_device_put; | 1207 | goto exit_device_put; |
544 | } | 1208 | } |
545 | 1209 | ||
1210 | err = platform_device_add_data(pdev, sio_data, | ||
1211 | sizeof(struct pc87427_sio_data)); | ||
1212 | if (err) { | ||
1213 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | ||
1214 | goto exit_device_put; | ||
1215 | } | ||
1216 | |||
546 | err = platform_device_add(pdev); | 1217 | err = platform_device_add(pdev); |
547 | if (err) { | 1218 | if (err) { |
548 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | 1219 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", |
@@ -558,9 +1229,10 @@ exit: | |||
558 | return err; | 1229 | return err; |
559 | } | 1230 | } |
560 | 1231 | ||
561 | static int __init pc87427_find(int sioaddr, unsigned short *address) | 1232 | static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data) |
562 | { | 1233 | { |
563 | u16 val; | 1234 | u16 val; |
1235 | u8 cfg, cfg_b; | ||
564 | int i, err = 0; | 1236 | int i, err = 0; |
565 | 1237 | ||
566 | /* Identify device */ | 1238 | /* Identify device */ |
@@ -571,7 +1243,7 @@ static int __init pc87427_find(int sioaddr, unsigned short *address) | |||
571 | } | 1243 | } |
572 | 1244 | ||
573 | for (i = 0; i < 2; i++) { | 1245 | for (i = 0; i < 2; i++) { |
574 | address[i] = 0; | 1246 | sio_data->address[i] = 0; |
575 | /* Select logical device */ | 1247 | /* Select logical device */ |
576 | superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]); | 1248 | superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]); |
577 | 1249 | ||
@@ -596,9 +1268,58 @@ static int __init pc87427_find(int sioaddr, unsigned short *address) | |||
596 | "for logical device 0x%02x\n", logdev[i]); | 1268 | "for logical device 0x%02x\n", logdev[i]); |
597 | continue; | 1269 | continue; |
598 | } | 1270 | } |
599 | address[i] = val; | 1271 | sio_data->address[i] = val; |
600 | } | 1272 | } |
601 | 1273 | ||
1274 | /* No point in loading the driver if everything is disabled */ | ||
1275 | if (!sio_data->address[0] && !sio_data->address[1]) { | ||
1276 | err = -ENODEV; | ||
1277 | goto exit; | ||
1278 | } | ||
1279 | |||
1280 | /* Check which fan inputs are wired */ | ||
1281 | sio_data->has_fanin = (1 << 2) | (1 << 3); /* FANIN2, FANIN3 */ | ||
1282 | |||
1283 | cfg = superio_inb(sioaddr, SIOREG_CF2); | ||
1284 | if (!(cfg & (1 << 3))) | ||
1285 | sio_data->has_fanin |= (1 << 0); /* FANIN0 */ | ||
1286 | if (!(cfg & (1 << 2))) | ||
1287 | sio_data->has_fanin |= (1 << 4); /* FANIN4 */ | ||
1288 | |||
1289 | cfg = superio_inb(sioaddr, SIOREG_CFD); | ||
1290 | if (!(cfg & (1 << 0))) | ||
1291 | sio_data->has_fanin |= (1 << 1); /* FANIN1 */ | ||
1292 | |||
1293 | cfg = superio_inb(sioaddr, SIOREG_CF4); | ||
1294 | if (!(cfg & (1 << 0))) | ||
1295 | sio_data->has_fanin |= (1 << 7); /* FANIN7 */ | ||
1296 | cfg_b = superio_inb(sioaddr, SIOREG_CFB); | ||
1297 | if (!(cfg & (1 << 1)) && (cfg_b & (1 << 3))) | ||
1298 | sio_data->has_fanin |= (1 << 5); /* FANIN5 */ | ||
1299 | cfg = superio_inb(sioaddr, SIOREG_CF3); | ||
1300 | if ((cfg & (1 << 3)) && !(cfg_b & (1 << 5))) | ||
1301 | sio_data->has_fanin |= (1 << 6); /* FANIN6 */ | ||
1302 | |||
1303 | /* Check which fan outputs are wired */ | ||
1304 | sio_data->has_fanout = (1 << 0); /* FANOUT0 */ | ||
1305 | if (cfg_b & (1 << 0)) | ||
1306 | sio_data->has_fanout |= (1 << 3); /* FANOUT3 */ | ||
1307 | |||
1308 | cfg = superio_inb(sioaddr, SIOREG_CFC); | ||
1309 | if (!(cfg & (1 << 4))) { | ||
1310 | if (cfg_b & (1 << 1)) | ||
1311 | sio_data->has_fanout |= (1 << 1); /* FANOUT1 */ | ||
1312 | if (cfg_b & (1 << 2)) | ||
1313 | sio_data->has_fanout |= (1 << 2); /* FANOUT2 */ | ||
1314 | } | ||
1315 | |||
1316 | /* FANOUT1 and FANOUT2 can each be routed to 2 different pins */ | ||
1317 | cfg = superio_inb(sioaddr, SIOREG_CF5); | ||
1318 | if (cfg & (1 << 6)) | ||
1319 | sio_data->has_fanout |= (1 << 1); /* FANOUT1 */ | ||
1320 | if (cfg & (1 << 5)) | ||
1321 | sio_data->has_fanout |= (1 << 2); /* FANOUT2 */ | ||
1322 | |||
602 | exit: | 1323 | exit: |
603 | superio_exit(sioaddr); | 1324 | superio_exit(sioaddr); |
604 | return err; | 1325 | return err; |
@@ -607,15 +1328,10 @@ exit: | |||
607 | static int __init pc87427_init(void) | 1328 | static int __init pc87427_init(void) |
608 | { | 1329 | { |
609 | int err; | 1330 | int err; |
610 | unsigned short address[2]; | 1331 | struct pc87427_sio_data sio_data; |
611 | |||
612 | if (pc87427_find(0x2e, address) | ||
613 | && pc87427_find(0x4e, address)) | ||
614 | return -ENODEV; | ||
615 | 1332 | ||
616 | /* For now the driver only handles fans so we only care about the | 1333 | if (pc87427_find(0x2e, &sio_data) |
617 | first address. */ | 1334 | && pc87427_find(0x4e, &sio_data)) |
618 | if (!address[0]) | ||
619 | return -ENODEV; | 1335 | return -ENODEV; |
620 | 1336 | ||
621 | err = platform_driver_register(&pc87427_driver); | 1337 | err = platform_driver_register(&pc87427_driver); |
@@ -623,7 +1339,7 @@ static int __init pc87427_init(void) | |||
623 | goto exit; | 1339 | goto exit; |
624 | 1340 | ||
625 | /* Sets global pdev as a side effect */ | 1341 | /* Sets global pdev as a side effect */ |
626 | err = pc87427_device_add(address[0]); | 1342 | err = pc87427_device_add(&sio_data); |
627 | if (err) | 1343 | if (err) |
628 | goto exit_driver; | 1344 | goto exit_driver; |
629 | 1345 | ||
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 7442cf754856..ffb793af680b 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c | |||
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | #define DRVNAME "via_cputemp" | 40 | #define DRVNAME "via_cputemp" |
41 | 41 | ||
42 | enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME } SHOW; | 42 | enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME }; |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * Functions declaration | 45 | * Functions declaration |
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 0dcaba9b7189..e96e69dd36fb 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
@@ -39,6 +39,7 @@ | |||
39 | w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 | 39 | w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 |
40 | w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3 | 40 | w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3 |
41 | w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3 | 41 | w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3 |
42 | w83667hg-b 9 5 3 3 0xb350 0xc1 0x5ca3 | ||
42 | */ | 43 | */ |
43 | 44 | ||
44 | #include <linux/module.h> | 45 | #include <linux/module.h> |
@@ -55,7 +56,7 @@ | |||
55 | #include <linux/io.h> | 56 | #include <linux/io.h> |
56 | #include "lm75.h" | 57 | #include "lm75.h" |
57 | 58 | ||
58 | enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg }; | 59 | enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b }; |
59 | 60 | ||
60 | /* used to set data->name = w83627ehf_device_names[data->sio_kind] */ | 61 | /* used to set data->name = w83627ehf_device_names[data->sio_kind] */ |
61 | static const char * w83627ehf_device_names[] = { | 62 | static const char * w83627ehf_device_names[] = { |
@@ -63,6 +64,7 @@ static const char * w83627ehf_device_names[] = { | |||
63 | "w83627dhg", | 64 | "w83627dhg", |
64 | "w83627dhg", | 65 | "w83627dhg", |
65 | "w83667hg", | 66 | "w83667hg", |
67 | "w83667hg", | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | static unsigned short force_id; | 70 | static unsigned short force_id; |
@@ -91,6 +93,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID"); | |||
91 | #define SIO_W83627DHG_ID 0xa020 | 93 | #define SIO_W83627DHG_ID 0xa020 |
92 | #define SIO_W83627DHG_P_ID 0xb070 | 94 | #define SIO_W83627DHG_P_ID 0xb070 |
93 | #define SIO_W83667HG_ID 0xa510 | 95 | #define SIO_W83667HG_ID 0xa510 |
96 | #define SIO_W83667HG_B_ID 0xb350 | ||
94 | #define SIO_ID_MASK 0xFFF0 | 97 | #define SIO_ID_MASK 0xFFF0 |
95 | 98 | ||
96 | static inline void | 99 | static inline void |
@@ -201,8 +204,14 @@ static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 }; | |||
201 | static const u8 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 }; | 204 | static const u8 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 }; |
202 | static const u8 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 }; | 205 | static const u8 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 }; |
203 | static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 }; | 206 | static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 }; |
204 | static const u8 W83627EHF_REG_FAN_MAX_OUTPUT[] = { 0xff, 0x67, 0xff, 0x69 }; | 207 | |
205 | static const u8 W83627EHF_REG_FAN_STEP_OUTPUT[] = { 0xff, 0x68, 0xff, 0x6a }; | 208 | static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON[] |
209 | = { 0xff, 0x67, 0xff, 0x69 }; | ||
210 | static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[] | ||
211 | = { 0xff, 0x68, 0xff, 0x6a }; | ||
212 | |||
213 | static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b }; | ||
214 | static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] = { 0x68, 0x6a, 0x6c }; | ||
206 | 215 | ||
207 | /* | 216 | /* |
208 | * Conversions | 217 | * Conversions |
@@ -277,6 +286,11 @@ struct w83627ehf_data { | |||
277 | struct device *hwmon_dev; | 286 | struct device *hwmon_dev; |
278 | struct mutex lock; | 287 | struct mutex lock; |
279 | 288 | ||
289 | const u8 *REG_FAN_START_OUTPUT; | ||
290 | const u8 *REG_FAN_STOP_OUTPUT; | ||
291 | const u8 *REG_FAN_MAX_OUTPUT; | ||
292 | const u8 *REG_FAN_STEP_OUTPUT; | ||
293 | |||
280 | struct mutex update_lock; | 294 | struct mutex update_lock; |
281 | char valid; /* !=0 if following fields are valid */ | 295 | char valid; /* !=0 if following fields are valid */ |
282 | unsigned long last_updated; /* In jiffies */ | 296 | unsigned long last_updated; /* In jiffies */ |
@@ -524,7 +538,10 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
524 | } | 538 | } |
525 | } | 539 | } |
526 | 540 | ||
527 | for (i = 0; i < 4; i++) { | 541 | for (i = 0; i < data->pwm_num; i++) { |
542 | if (!(data->has_fan & (1 << i))) | ||
543 | continue; | ||
544 | |||
528 | /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */ | 545 | /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */ |
529 | if (i != 1) { | 546 | if (i != 1) { |
530 | pwmcfg = w83627ehf_read_value(data, | 547 | pwmcfg = w83627ehf_read_value(data, |
@@ -546,6 +563,17 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
546 | W83627EHF_REG_FAN_STOP_OUTPUT[i]); | 563 | W83627EHF_REG_FAN_STOP_OUTPUT[i]); |
547 | data->fan_stop_time[i] = w83627ehf_read_value(data, | 564 | data->fan_stop_time[i] = w83627ehf_read_value(data, |
548 | W83627EHF_REG_FAN_STOP_TIME[i]); | 565 | W83627EHF_REG_FAN_STOP_TIME[i]); |
566 | |||
567 | if (data->REG_FAN_MAX_OUTPUT[i] != 0xff) | ||
568 | data->fan_max_output[i] = | ||
569 | w83627ehf_read_value(data, | ||
570 | data->REG_FAN_MAX_OUTPUT[i]); | ||
571 | |||
572 | if (data->REG_FAN_STEP_OUTPUT[i] != 0xff) | ||
573 | data->fan_step_output[i] = | ||
574 | w83627ehf_read_value(data, | ||
575 | data->REG_FAN_STEP_OUTPUT[i]); | ||
576 | |||
549 | data->target_temp[i] = | 577 | data->target_temp[i] = |
550 | w83627ehf_read_value(data, | 578 | w83627ehf_read_value(data, |
551 | W83627EHF_REG_TARGET[i]) & | 579 | W83627EHF_REG_TARGET[i]) & |
@@ -1126,7 +1154,7 @@ store_##reg(struct device *dev, struct device_attribute *attr, \ | |||
1126 | u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \ | 1154 | u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \ |
1127 | mutex_lock(&data->update_lock); \ | 1155 | mutex_lock(&data->update_lock); \ |
1128 | data->reg[nr] = val; \ | 1156 | data->reg[nr] = val; \ |
1129 | w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \ | 1157 | w83627ehf_write_value(data, data->REG_##REG[nr], val); \ |
1130 | mutex_unlock(&data->update_lock); \ | 1158 | mutex_unlock(&data->update_lock); \ |
1131 | return count; \ | 1159 | return count; \ |
1132 | } | 1160 | } |
@@ -1206,12 +1234,26 @@ static struct sensor_device_attribute sda_sf3_arrays[] = { | |||
1206 | store_fan_stop_output, 1), | 1234 | store_fan_stop_output, 1), |
1207 | SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, | 1235 | SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, |
1208 | store_fan_stop_output, 2), | 1236 | store_fan_stop_output, 2), |
1237 | }; | ||
1209 | 1238 | ||
1210 | /* pwm1 and pwm3 don't support max and step settings */ | 1239 | |
1240 | /* | ||
1241 | * pwm1 and pwm3 don't support max and step settings on all chips. | ||
1242 | * Need to check support while generating/removing attribute files. | ||
1243 | */ | ||
1244 | static struct sensor_device_attribute sda_sf3_max_step_arrays[] = { | ||
1245 | SENSOR_ATTR(pwm1_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, | ||
1246 | store_fan_max_output, 0), | ||
1247 | SENSOR_ATTR(pwm1_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, | ||
1248 | store_fan_step_output, 0), | ||
1211 | SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, | 1249 | SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, |
1212 | store_fan_max_output, 1), | 1250 | store_fan_max_output, 1), |
1213 | SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, | 1251 | SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, |
1214 | store_fan_step_output, 1), | 1252 | store_fan_step_output, 1), |
1253 | SENSOR_ATTR(pwm3_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, | ||
1254 | store_fan_max_output, 2), | ||
1255 | SENSOR_ATTR(pwm3_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, | ||
1256 | store_fan_step_output, 2), | ||
1215 | }; | 1257 | }; |
1216 | 1258 | ||
1217 | static ssize_t | 1259 | static ssize_t |
@@ -1235,6 +1277,12 @@ static void w83627ehf_device_remove_files(struct device *dev) | |||
1235 | 1277 | ||
1236 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) | 1278 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) |
1237 | device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); | 1279 | device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); |
1280 | for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) { | ||
1281 | struct sensor_device_attribute *attr = | ||
1282 | &sda_sf3_max_step_arrays[i]; | ||
1283 | if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) | ||
1284 | device_remove_file(dev, &attr->dev_attr); | ||
1285 | } | ||
1238 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) | 1286 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) |
1239 | device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); | 1287 | device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); |
1240 | for (i = 0; i < data->in_num; i++) { | 1288 | for (i = 0; i < data->in_num; i++) { |
@@ -1343,22 +1391,37 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1343 | /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ | 1391 | /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ |
1344 | data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9; | 1392 | data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9; |
1345 | /* 667HG has 3 pwms */ | 1393 | /* 667HG has 3 pwms */ |
1346 | data->pwm_num = (sio_data->kind == w83667hg) ? 3 : 4; | 1394 | data->pwm_num = (sio_data->kind == w83667hg |
1395 | || sio_data->kind == w83667hg_b) ? 3 : 4; | ||
1347 | 1396 | ||
1348 | /* Check temp3 configuration bit for 667HG */ | 1397 | /* Check temp3 configuration bit for 667HG */ |
1349 | if (sio_data->kind == w83667hg) { | 1398 | if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { |
1350 | data->temp3_disable = w83627ehf_read_value(data, | 1399 | data->temp3_disable = w83627ehf_read_value(data, |
1351 | W83627EHF_REG_TEMP_CONFIG[1]) & 0x01; | 1400 | W83627EHF_REG_TEMP_CONFIG[1]) & 0x01; |
1352 | data->in6_skip = !data->temp3_disable; | 1401 | data->in6_skip = !data->temp3_disable; |
1353 | } | 1402 | } |
1354 | 1403 | ||
1404 | data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT; | ||
1405 | data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT; | ||
1406 | if (sio_data->kind == w83667hg_b) { | ||
1407 | data->REG_FAN_MAX_OUTPUT = | ||
1408 | W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B; | ||
1409 | data->REG_FAN_STEP_OUTPUT = | ||
1410 | W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B; | ||
1411 | } else { | ||
1412 | data->REG_FAN_MAX_OUTPUT = | ||
1413 | W83627EHF_REG_FAN_MAX_OUTPUT_COMMON; | ||
1414 | data->REG_FAN_STEP_OUTPUT = | ||
1415 | W83627EHF_REG_FAN_STEP_OUTPUT_COMMON; | ||
1416 | } | ||
1417 | |||
1355 | /* Initialize the chip */ | 1418 | /* Initialize the chip */ |
1356 | w83627ehf_init_device(data); | 1419 | w83627ehf_init_device(data); |
1357 | 1420 | ||
1358 | data->vrm = vid_which_vrm(); | 1421 | data->vrm = vid_which_vrm(); |
1359 | superio_enter(sio_data->sioreg); | 1422 | superio_enter(sio_data->sioreg); |
1360 | /* Read VID value */ | 1423 | /* Read VID value */ |
1361 | if (sio_data->kind == w83667hg) { | 1424 | if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { |
1362 | /* W83667HG has different pins for VID input and output, so | 1425 | /* W83667HG has different pins for VID input and output, so |
1363 | we can get the VID input values directly at logical device D | 1426 | we can get the VID input values directly at logical device D |
1364 | 0xe3. */ | 1427 | 0xe3. */ |
@@ -1409,7 +1472,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1409 | } | 1472 | } |
1410 | 1473 | ||
1411 | /* fan4 and fan5 share some pins with the GPIO and serial flash */ | 1474 | /* fan4 and fan5 share some pins with the GPIO and serial flash */ |
1412 | if (sio_data->kind == w83667hg) { | 1475 | if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { |
1413 | fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20; | 1476 | fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20; |
1414 | fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40; | 1477 | fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40; |
1415 | } else { | 1478 | } else { |
@@ -1440,6 +1503,15 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1440 | &sda_sf3_arrays[i].dev_attr))) | 1503 | &sda_sf3_arrays[i].dev_attr))) |
1441 | goto exit_remove; | 1504 | goto exit_remove; |
1442 | 1505 | ||
1506 | for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) { | ||
1507 | struct sensor_device_attribute *attr = | ||
1508 | &sda_sf3_max_step_arrays[i]; | ||
1509 | if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) { | ||
1510 | err = device_create_file(dev, &attr->dev_attr); | ||
1511 | if (err) | ||
1512 | goto exit_remove; | ||
1513 | } | ||
1514 | } | ||
1443 | /* if fan4 is enabled create the sf3 files for it */ | 1515 | /* if fan4 is enabled create the sf3 files for it */ |
1444 | if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4) | 1516 | if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4) |
1445 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) { | 1517 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) { |
@@ -1556,6 +1628,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, | |||
1556 | static const char __initdata sio_name_W83627DHG[] = "W83627DHG"; | 1628 | static const char __initdata sio_name_W83627DHG[] = "W83627DHG"; |
1557 | static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P"; | 1629 | static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P"; |
1558 | static const char __initdata sio_name_W83667HG[] = "W83667HG"; | 1630 | static const char __initdata sio_name_W83667HG[] = "W83667HG"; |
1631 | static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B"; | ||
1559 | 1632 | ||
1560 | u16 val; | 1633 | u16 val; |
1561 | const char *sio_name; | 1634 | const char *sio_name; |
@@ -1588,6 +1661,10 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, | |||
1588 | sio_data->kind = w83667hg; | 1661 | sio_data->kind = w83667hg; |
1589 | sio_name = sio_name_W83667HG; | 1662 | sio_name = sio_name_W83667HG; |
1590 | break; | 1663 | break; |
1664 | case SIO_W83667HG_B_ID: | ||
1665 | sio_data->kind = w83667hg_b; | ||
1666 | sio_name = sio_name_W83667HG_B; | ||
1667 | break; | ||
1591 | default: | 1668 | default: |
1592 | if (val != 0xffff) | 1669 | if (val != 0xffff) |
1593 | pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n", | 1670 | pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n", |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 15a9702e2941..6539ac2907e9 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -448,6 +448,13 @@ config I2C_NOMADIK | |||
448 | If you say yes to this option, support will be included for the | 448 | If you say yes to this option, support will be included for the |
449 | I2C interface from ST-Ericsson's Nomadik and Ux500 architectures. | 449 | I2C interface from ST-Ericsson's Nomadik and Ux500 architectures. |
450 | 450 | ||
451 | config I2C_NUC900 | ||
452 | tristate "NUC900 I2C Driver" | ||
453 | depends on ARCH_W90X900 | ||
454 | help | ||
455 | Say Y here to include support for I2C controller in the | ||
456 | Winbond/Nuvoton NUC900 based System-on-Chip devices. | ||
457 | |||
451 | config I2C_OCORES | 458 | config I2C_OCORES |
452 | tristate "OpenCores I2C Controller" | 459 | tristate "OpenCores I2C Controller" |
453 | depends on EXPERIMENTAL | 460 | depends on EXPERIMENTAL |
@@ -496,8 +503,8 @@ config I2C_PMCMSP | |||
496 | will be called i2c-pmcmsp. | 503 | will be called i2c-pmcmsp. |
497 | 504 | ||
498 | config I2C_PNX | 505 | config I2C_PNX |
499 | tristate "I2C bus support for Philips PNX targets" | 506 | tristate "I2C bus support for Philips PNX and NXP LPC targets" |
500 | depends on ARCH_PNX4008 | 507 | depends on ARCH_PNX4008 || ARCH_LPC32XX |
501 | help | 508 | help |
502 | This driver supports the Philips IP3204 I2C IP block master and/or | 509 | This driver supports the Philips IP3204 I2C IP block master and/or |
503 | slave controller | 510 | slave controller |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 936880bd1dc5..c3ef49230cba 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -43,6 +43,7 @@ obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o | |||
43 | obj-$(CONFIG_I2C_MPC) += i2c-mpc.o | 43 | obj-$(CONFIG_I2C_MPC) += i2c-mpc.o |
44 | obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o | 44 | obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o |
45 | obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o | 45 | obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o |
46 | obj-$(CONFIG_I2C_NUC900) += i2c-nuc900.o | ||
46 | obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o | 47 | obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o |
47 | obj-$(CONFIG_I2C_OMAP) += i2c-omap.o | 48 | obj-$(CONFIG_I2C_OMAP) += i2c-omap.o |
48 | obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o | 49 | obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o |
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 4523364e6722..2222c87876b9 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c | |||
@@ -36,14 +36,16 @@ | |||
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/cpufreq.h> | ||
40 | #include <linux/gpio.h> | ||
39 | 41 | ||
40 | #include <mach/hardware.h> | 42 | #include <mach/hardware.h> |
41 | |||
42 | #include <mach/i2c.h> | 43 | #include <mach/i2c.h> |
43 | 44 | ||
44 | /* ----- global defines ----------------------------------------------- */ | 45 | /* ----- global defines ----------------------------------------------- */ |
45 | 46 | ||
46 | #define DAVINCI_I2C_TIMEOUT (1*HZ) | 47 | #define DAVINCI_I2C_TIMEOUT (1*HZ) |
48 | #define DAVINCI_I2C_MAX_TRIES 2 | ||
47 | #define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \ | 49 | #define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \ |
48 | DAVINCI_I2C_IMR_SCD | \ | 50 | DAVINCI_I2C_IMR_SCD | \ |
49 | DAVINCI_I2C_IMR_ARDY | \ | 51 | DAVINCI_I2C_IMR_ARDY | \ |
@@ -72,37 +74,29 @@ | |||
72 | #define DAVINCI_I2C_IVR_NACK 0x02 | 74 | #define DAVINCI_I2C_IVR_NACK 0x02 |
73 | #define DAVINCI_I2C_IVR_AL 0x01 | 75 | #define DAVINCI_I2C_IVR_AL 0x01 |
74 | 76 | ||
75 | #define DAVINCI_I2C_STR_BB (1 << 12) | 77 | #define DAVINCI_I2C_STR_BB BIT(12) |
76 | #define DAVINCI_I2C_STR_RSFULL (1 << 11) | 78 | #define DAVINCI_I2C_STR_RSFULL BIT(11) |
77 | #define DAVINCI_I2C_STR_SCD (1 << 5) | 79 | #define DAVINCI_I2C_STR_SCD BIT(5) |
78 | #define DAVINCI_I2C_STR_ARDY (1 << 2) | 80 | #define DAVINCI_I2C_STR_ARDY BIT(2) |
79 | #define DAVINCI_I2C_STR_NACK (1 << 1) | 81 | #define DAVINCI_I2C_STR_NACK BIT(1) |
80 | #define DAVINCI_I2C_STR_AL (1 << 0) | 82 | #define DAVINCI_I2C_STR_AL BIT(0) |
81 | 83 | ||
82 | #define DAVINCI_I2C_MDR_NACK (1 << 15) | 84 | #define DAVINCI_I2C_MDR_NACK BIT(15) |
83 | #define DAVINCI_I2C_MDR_STT (1 << 13) | 85 | #define DAVINCI_I2C_MDR_STT BIT(13) |
84 | #define DAVINCI_I2C_MDR_STP (1 << 11) | 86 | #define DAVINCI_I2C_MDR_STP BIT(11) |
85 | #define DAVINCI_I2C_MDR_MST (1 << 10) | 87 | #define DAVINCI_I2C_MDR_MST BIT(10) |
86 | #define DAVINCI_I2C_MDR_TRX (1 << 9) | 88 | #define DAVINCI_I2C_MDR_TRX BIT(9) |
87 | #define DAVINCI_I2C_MDR_XA (1 << 8) | 89 | #define DAVINCI_I2C_MDR_XA BIT(8) |
88 | #define DAVINCI_I2C_MDR_RM (1 << 7) | 90 | #define DAVINCI_I2C_MDR_RM BIT(7) |
89 | #define DAVINCI_I2C_MDR_IRS (1 << 5) | 91 | #define DAVINCI_I2C_MDR_IRS BIT(5) |
90 | 92 | ||
91 | #define DAVINCI_I2C_IMR_AAS (1 << 6) | 93 | #define DAVINCI_I2C_IMR_AAS BIT(6) |
92 | #define DAVINCI_I2C_IMR_SCD (1 << 5) | 94 | #define DAVINCI_I2C_IMR_SCD BIT(5) |
93 | #define DAVINCI_I2C_IMR_XRDY (1 << 4) | 95 | #define DAVINCI_I2C_IMR_XRDY BIT(4) |
94 | #define DAVINCI_I2C_IMR_RRDY (1 << 3) | 96 | #define DAVINCI_I2C_IMR_RRDY BIT(3) |
95 | #define DAVINCI_I2C_IMR_ARDY (1 << 2) | 97 | #define DAVINCI_I2C_IMR_ARDY BIT(2) |
96 | #define DAVINCI_I2C_IMR_NACK (1 << 1) | 98 | #define DAVINCI_I2C_IMR_NACK BIT(1) |
97 | #define DAVINCI_I2C_IMR_AL (1 << 0) | 99 | #define DAVINCI_I2C_IMR_AL BIT(0) |
98 | |||
99 | #define MOD_REG_BIT(val, mask, set) do { \ | ||
100 | if (set) { \ | ||
101 | val |= mask; \ | ||
102 | } else { \ | ||
103 | val &= ~mask; \ | ||
104 | } \ | ||
105 | } while (0) | ||
106 | 100 | ||
107 | struct davinci_i2c_dev { | 101 | struct davinci_i2c_dev { |
108 | struct device *dev; | 102 | struct device *dev; |
@@ -113,8 +107,13 @@ struct davinci_i2c_dev { | |||
113 | u8 *buf; | 107 | u8 *buf; |
114 | size_t buf_len; | 108 | size_t buf_len; |
115 | int irq; | 109 | int irq; |
110 | int stop; | ||
116 | u8 terminate; | 111 | u8 terminate; |
117 | struct i2c_adapter adapter; | 112 | struct i2c_adapter adapter; |
113 | #ifdef CONFIG_CPU_FREQ | ||
114 | struct completion xfr_complete; | ||
115 | struct notifier_block freq_transition; | ||
116 | #endif | ||
118 | }; | 117 | }; |
119 | 118 | ||
120 | /* default platform data to use if not supplied in the platform_device */ | 119 | /* default platform data to use if not supplied in the platform_device */ |
@@ -134,12 +133,59 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg) | |||
134 | return __raw_readw(i2c_dev->base + reg); | 133 | return __raw_readw(i2c_dev->base + reg); |
135 | } | 134 | } |
136 | 135 | ||
137 | /* | 136 | /* Generate a pulse on the i2c clock pin. */ |
138 | * This functions configures I2C and brings I2C out of reset. | 137 | static void generic_i2c_clock_pulse(unsigned int scl_pin) |
139 | * This function is called during I2C init function. This function | 138 | { |
140 | * also gets called if I2C encounters any errors. | 139 | u16 i; |
140 | |||
141 | if (scl_pin) { | ||
142 | /* Send high and low on the SCL line */ | ||
143 | for (i = 0; i < 9; i++) { | ||
144 | gpio_set_value(scl_pin, 0); | ||
145 | udelay(20); | ||
146 | gpio_set_value(scl_pin, 1); | ||
147 | udelay(20); | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /* This routine does i2c bus recovery as specified in the | ||
153 | * i2c protocol Rev. 03 section 3.16 titled "Bus clear" | ||
141 | */ | 154 | */ |
142 | static int i2c_davinci_init(struct davinci_i2c_dev *dev) | 155 | static void i2c_recover_bus(struct davinci_i2c_dev *dev) |
156 | { | ||
157 | u32 flag = 0; | ||
158 | struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; | ||
159 | |||
160 | dev_err(dev->dev, "initiating i2c bus recovery\n"); | ||
161 | /* Send NACK to the slave */ | ||
162 | flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); | ||
163 | flag |= DAVINCI_I2C_MDR_NACK; | ||
164 | /* write the data into mode register */ | ||
165 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); | ||
166 | if (pdata) | ||
167 | generic_i2c_clock_pulse(pdata->scl_pin); | ||
168 | /* Send STOP */ | ||
169 | flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); | ||
170 | flag |= DAVINCI_I2C_MDR_STP; | ||
171 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); | ||
172 | } | ||
173 | |||
174 | static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, | ||
175 | int val) | ||
176 | { | ||
177 | u16 w; | ||
178 | |||
179 | w = davinci_i2c_read_reg(i2c_dev, DAVINCI_I2C_MDR_REG); | ||
180 | if (!val) /* put I2C into reset */ | ||
181 | w &= ~DAVINCI_I2C_MDR_IRS; | ||
182 | else /* take I2C out of reset */ | ||
183 | w |= DAVINCI_I2C_MDR_IRS; | ||
184 | |||
185 | davinci_i2c_write_reg(i2c_dev, DAVINCI_I2C_MDR_REG, w); | ||
186 | } | ||
187 | |||
188 | static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) | ||
143 | { | 189 | { |
144 | struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; | 190 | struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; |
145 | u16 psc; | 191 | u16 psc; |
@@ -148,15 +194,6 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) | |||
148 | u32 clkh; | 194 | u32 clkh; |
149 | u32 clkl; | 195 | u32 clkl; |
150 | u32 input_clock = clk_get_rate(dev->clk); | 196 | u32 input_clock = clk_get_rate(dev->clk); |
151 | u16 w; | ||
152 | |||
153 | if (!pdata) | ||
154 | pdata = &davinci_i2c_platform_data_default; | ||
155 | |||
156 | /* put I2C into reset */ | ||
157 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); | ||
158 | MOD_REG_BIT(w, DAVINCI_I2C_MDR_IRS, 0); | ||
159 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); | ||
160 | 197 | ||
161 | /* NOTE: I2C Clock divider programming info | 198 | /* NOTE: I2C Clock divider programming info |
162 | * As per I2C specs the following formulas provide prescaler | 199 | * As per I2C specs the following formulas provide prescaler |
@@ -188,12 +225,32 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) | |||
188 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); | 225 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); |
189 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); | 226 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); |
190 | 227 | ||
228 | dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * This function configures I2C and brings I2C out of reset. | ||
233 | * This function is called during I2C init function. This function | ||
234 | * also gets called if I2C encounters any errors. | ||
235 | */ | ||
236 | static int i2c_davinci_init(struct davinci_i2c_dev *dev) | ||
237 | { | ||
238 | struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; | ||
239 | |||
240 | if (!pdata) | ||
241 | pdata = &davinci_i2c_platform_data_default; | ||
242 | |||
243 | /* put I2C into reset */ | ||
244 | davinci_i2c_reset_ctrl(dev, 0); | ||
245 | |||
246 | /* compute clock dividers */ | ||
247 | i2c_davinci_calc_clk_dividers(dev); | ||
248 | |||
191 | /* Respond at reserved "SMBus Host" slave address" (and zero); | 249 | /* Respond at reserved "SMBus Host" slave address" (and zero); |
192 | * we seem to have no option to not respond... | 250 | * we seem to have no option to not respond... |
193 | */ | 251 | */ |
194 | davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); | 252 | davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); |
195 | 253 | ||
196 | dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); | ||
197 | dev_dbg(dev->dev, "PSC = %d\n", | 254 | dev_dbg(dev->dev, "PSC = %d\n", |
198 | davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); | 255 | davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); |
199 | dev_dbg(dev->dev, "CLKL = %d\n", | 256 | dev_dbg(dev->dev, "CLKL = %d\n", |
@@ -204,9 +261,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) | |||
204 | pdata->bus_freq, pdata->bus_delay); | 261 | pdata->bus_freq, pdata->bus_delay); |
205 | 262 | ||
206 | /* Take the I2C module out of reset: */ | 263 | /* Take the I2C module out of reset: */ |
207 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); | 264 | davinci_i2c_reset_ctrl(dev, 1); |
208 | MOD_REG_BIT(w, DAVINCI_I2C_MDR_IRS, 1); | ||
209 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); | ||
210 | 265 | ||
211 | /* Enable interrupts */ | 266 | /* Enable interrupts */ |
212 | davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL); | 267 | davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL); |
@@ -221,14 +276,22 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, | |||
221 | char allow_sleep) | 276 | char allow_sleep) |
222 | { | 277 | { |
223 | unsigned long timeout; | 278 | unsigned long timeout; |
279 | static u16 to_cnt; | ||
224 | 280 | ||
225 | timeout = jiffies + dev->adapter.timeout; | 281 | timeout = jiffies + dev->adapter.timeout; |
226 | while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) | 282 | while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) |
227 | & DAVINCI_I2C_STR_BB) { | 283 | & DAVINCI_I2C_STR_BB) { |
228 | if (time_after(jiffies, timeout)) { | 284 | if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { |
229 | dev_warn(dev->dev, | 285 | if (time_after(jiffies, timeout)) { |
230 | "timeout waiting for bus ready\n"); | 286 | dev_warn(dev->dev, |
231 | return -ETIMEDOUT; | 287 | "timeout waiting for bus ready\n"); |
288 | to_cnt++; | ||
289 | return -ETIMEDOUT; | ||
290 | } else { | ||
291 | to_cnt = 0; | ||
292 | i2c_recover_bus(dev); | ||
293 | i2c_davinci_init(dev); | ||
294 | } | ||
232 | } | 295 | } |
233 | if (allow_sleep) | 296 | if (allow_sleep) |
234 | schedule_timeout(1); | 297 | schedule_timeout(1); |
@@ -250,9 +313,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) | |||
250 | u16 w; | 313 | u16 w; |
251 | int r; | 314 | int r; |
252 | 315 | ||
253 | if (msg->len == 0) | ||
254 | return -EINVAL; | ||
255 | |||
256 | if (!pdata) | 316 | if (!pdata) |
257 | pdata = &davinci_i2c_platform_data_default; | 317 | pdata = &davinci_i2c_platform_data_default; |
258 | /* Introduce a delay, required for some boards (e.g Davinci EVM) */ | 318 | /* Introduce a delay, required for some boards (e.g Davinci EVM) */ |
@@ -264,6 +324,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) | |||
264 | 324 | ||
265 | dev->buf = msg->buf; | 325 | dev->buf = msg->buf; |
266 | dev->buf_len = msg->len; | 326 | dev->buf_len = msg->len; |
327 | dev->stop = stop; | ||
267 | 328 | ||
268 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len); | 329 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len); |
269 | 330 | ||
@@ -281,23 +342,40 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) | |||
281 | flag |= DAVINCI_I2C_MDR_TRX; | 342 | flag |= DAVINCI_I2C_MDR_TRX; |
282 | if (stop) | 343 | if (stop) |
283 | flag |= DAVINCI_I2C_MDR_STP; | 344 | flag |= DAVINCI_I2C_MDR_STP; |
345 | if (msg->len == 0) { | ||
346 | flag |= DAVINCI_I2C_MDR_RM; | ||
347 | flag &= ~DAVINCI_I2C_MDR_STP; | ||
348 | } | ||
284 | 349 | ||
285 | /* Enable receive or transmit interrupts */ | 350 | /* Enable receive or transmit interrupts */ |
286 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); | 351 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); |
287 | if (msg->flags & I2C_M_RD) | 352 | if (msg->flags & I2C_M_RD) |
288 | MOD_REG_BIT(w, DAVINCI_I2C_IMR_RRDY, 1); | 353 | w |= DAVINCI_I2C_IMR_RRDY; |
289 | else | 354 | else |
290 | MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 1); | 355 | w |= DAVINCI_I2C_IMR_XRDY; |
291 | davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); | 356 | davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); |
292 | 357 | ||
293 | dev->terminate = 0; | 358 | dev->terminate = 0; |
359 | |||
294 | /* write the data into mode register */ | 360 | /* write the data into mode register */ |
295 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); | 361 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); |
296 | 362 | ||
363 | /* | ||
364 | * First byte should be set here, not after interrupt, | ||
365 | * because transmit-data-ready interrupt can come before | ||
366 | * NACK-interrupt during sending of previous message and | ||
367 | * ICDXR may have wrong data | ||
368 | */ | ||
369 | if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { | ||
370 | davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); | ||
371 | dev->buf_len--; | ||
372 | } | ||
373 | |||
297 | r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, | 374 | r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, |
298 | dev->adapter.timeout); | 375 | dev->adapter.timeout); |
299 | if (r == 0) { | 376 | if (r == 0) { |
300 | dev_err(dev->dev, "controller timed out\n"); | 377 | dev_err(dev->dev, "controller timed out\n"); |
378 | i2c_recover_bus(dev); | ||
301 | i2c_davinci_init(dev); | 379 | i2c_davinci_init(dev); |
302 | dev->buf_len = 0; | 380 | dev->buf_len = 0; |
303 | return -ETIMEDOUT; | 381 | return -ETIMEDOUT; |
@@ -334,7 +412,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) | |||
334 | return msg->len; | 412 | return msg->len; |
335 | if (stop) { | 413 | if (stop) { |
336 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); | 414 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); |
337 | MOD_REG_BIT(w, DAVINCI_I2C_MDR_STP, 1); | 415 | w |= DAVINCI_I2C_MDR_STP; |
338 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); | 416 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); |
339 | } | 417 | } |
340 | return -EREMOTEIO; | 418 | return -EREMOTEIO; |
@@ -367,12 +445,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
367 | if (ret < 0) | 445 | if (ret < 0) |
368 | return ret; | 446 | return ret; |
369 | } | 447 | } |
448 | |||
449 | #ifdef CONFIG_CPU_FREQ | ||
450 | complete(&dev->xfr_complete); | ||
451 | #endif | ||
452 | |||
370 | return num; | 453 | return num; |
371 | } | 454 | } |
372 | 455 | ||
373 | static u32 i2c_davinci_func(struct i2c_adapter *adap) | 456 | static u32 i2c_davinci_func(struct i2c_adapter *adap) |
374 | { | 457 | { |
375 | return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); | 458 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
376 | } | 459 | } |
377 | 460 | ||
378 | static void terminate_read(struct davinci_i2c_dev *dev) | 461 | static void terminate_read(struct davinci_i2c_dev *dev) |
@@ -431,6 +514,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) | |||
431 | case DAVINCI_I2C_IVR_ARDY: | 514 | case DAVINCI_I2C_IVR_ARDY: |
432 | davinci_i2c_write_reg(dev, | 515 | davinci_i2c_write_reg(dev, |
433 | DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY); | 516 | DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY); |
517 | if (((dev->buf_len == 0) && (dev->stop != 0)) || | ||
518 | (dev->cmd_err & DAVINCI_I2C_STR_NACK)) { | ||
519 | w = davinci_i2c_read_reg(dev, | ||
520 | DAVINCI_I2C_MDR_REG); | ||
521 | w |= DAVINCI_I2C_MDR_STP; | ||
522 | davinci_i2c_write_reg(dev, | ||
523 | DAVINCI_I2C_MDR_REG, w); | ||
524 | } | ||
434 | complete(&dev->cmd_complete); | 525 | complete(&dev->cmd_complete); |
435 | break; | 526 | break; |
436 | 527 | ||
@@ -462,7 +553,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) | |||
462 | 553 | ||
463 | w = davinci_i2c_read_reg(dev, | 554 | w = davinci_i2c_read_reg(dev, |
464 | DAVINCI_I2C_IMR_REG); | 555 | DAVINCI_I2C_IMR_REG); |
465 | MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 0); | 556 | w &= ~DAVINCI_I2C_IMR_XRDY; |
466 | davinci_i2c_write_reg(dev, | 557 | davinci_i2c_write_reg(dev, |
467 | DAVINCI_I2C_IMR_REG, | 558 | DAVINCI_I2C_IMR_REG, |
468 | w); | 559 | w); |
@@ -491,6 +582,48 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) | |||
491 | return count ? IRQ_HANDLED : IRQ_NONE; | 582 | return count ? IRQ_HANDLED : IRQ_NONE; |
492 | } | 583 | } |
493 | 584 | ||
585 | #ifdef CONFIG_CPU_FREQ | ||
586 | static int i2c_davinci_cpufreq_transition(struct notifier_block *nb, | ||
587 | unsigned long val, void *data) | ||
588 | { | ||
589 | struct davinci_i2c_dev *dev; | ||
590 | |||
591 | dev = container_of(nb, struct davinci_i2c_dev, freq_transition); | ||
592 | if (val == CPUFREQ_PRECHANGE) { | ||
593 | wait_for_completion(&dev->xfr_complete); | ||
594 | davinci_i2c_reset_ctrl(dev, 0); | ||
595 | } else if (val == CPUFREQ_POSTCHANGE) { | ||
596 | i2c_davinci_calc_clk_dividers(dev); | ||
597 | davinci_i2c_reset_ctrl(dev, 1); | ||
598 | } | ||
599 | |||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev) | ||
604 | { | ||
605 | dev->freq_transition.notifier_call = i2c_davinci_cpufreq_transition; | ||
606 | |||
607 | return cpufreq_register_notifier(&dev->freq_transition, | ||
608 | CPUFREQ_TRANSITION_NOTIFIER); | ||
609 | } | ||
610 | |||
611 | static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) | ||
612 | { | ||
613 | cpufreq_unregister_notifier(&dev->freq_transition, | ||
614 | CPUFREQ_TRANSITION_NOTIFIER); | ||
615 | } | ||
616 | #else | ||
617 | static inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev) | ||
618 | { | ||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) | ||
623 | { | ||
624 | } | ||
625 | #endif | ||
626 | |||
494 | static struct i2c_algorithm i2c_davinci_algo = { | 627 | static struct i2c_algorithm i2c_davinci_algo = { |
495 | .master_xfer = i2c_davinci_xfer, | 628 | .master_xfer = i2c_davinci_xfer, |
496 | .functionality = i2c_davinci_func, | 629 | .functionality = i2c_davinci_func, |
@@ -530,6 +663,9 @@ static int davinci_i2c_probe(struct platform_device *pdev) | |||
530 | } | 663 | } |
531 | 664 | ||
532 | init_completion(&dev->cmd_complete); | 665 | init_completion(&dev->cmd_complete); |
666 | #ifdef CONFIG_CPU_FREQ | ||
667 | init_completion(&dev->xfr_complete); | ||
668 | #endif | ||
533 | dev->dev = get_device(&pdev->dev); | 669 | dev->dev = get_device(&pdev->dev); |
534 | dev->irq = irq->start; | 670 | dev->irq = irq->start; |
535 | platform_set_drvdata(pdev, dev); | 671 | platform_set_drvdata(pdev, dev); |
@@ -541,7 +677,12 @@ static int davinci_i2c_probe(struct platform_device *pdev) | |||
541 | } | 677 | } |
542 | clk_enable(dev->clk); | 678 | clk_enable(dev->clk); |
543 | 679 | ||
544 | dev->base = (void __iomem *)IO_ADDRESS(mem->start); | 680 | dev->base = ioremap(mem->start, resource_size(mem)); |
681 | if (!dev->base) { | ||
682 | r = -EBUSY; | ||
683 | goto err_mem_ioremap; | ||
684 | } | ||
685 | |||
545 | i2c_davinci_init(dev); | 686 | i2c_davinci_init(dev); |
546 | 687 | ||
547 | r = request_irq(dev->irq, i2c_davinci_isr, 0, pdev->name, dev); | 688 | r = request_irq(dev->irq, i2c_davinci_isr, 0, pdev->name, dev); |
@@ -550,6 +691,12 @@ static int davinci_i2c_probe(struct platform_device *pdev) | |||
550 | goto err_unuse_clocks; | 691 | goto err_unuse_clocks; |
551 | } | 692 | } |
552 | 693 | ||
694 | r = i2c_davinci_cpufreq_register(dev); | ||
695 | if (r) { | ||
696 | dev_err(&pdev->dev, "failed to register cpufreq\n"); | ||
697 | goto err_free_irq; | ||
698 | } | ||
699 | |||
553 | adap = &dev->adapter; | 700 | adap = &dev->adapter; |
554 | i2c_set_adapdata(adap, dev); | 701 | i2c_set_adapdata(adap, dev); |
555 | adap->owner = THIS_MODULE; | 702 | adap->owner = THIS_MODULE; |
@@ -571,6 +718,8 @@ static int davinci_i2c_probe(struct platform_device *pdev) | |||
571 | err_free_irq: | 718 | err_free_irq: |
572 | free_irq(dev->irq, dev); | 719 | free_irq(dev->irq, dev); |
573 | err_unuse_clocks: | 720 | err_unuse_clocks: |
721 | iounmap(dev->base); | ||
722 | err_mem_ioremap: | ||
574 | clk_disable(dev->clk); | 723 | clk_disable(dev->clk); |
575 | clk_put(dev->clk); | 724 | clk_put(dev->clk); |
576 | dev->clk = NULL; | 725 | dev->clk = NULL; |
@@ -589,6 +738,8 @@ static int davinci_i2c_remove(struct platform_device *pdev) | |||
589 | struct davinci_i2c_dev *dev = platform_get_drvdata(pdev); | 738 | struct davinci_i2c_dev *dev = platform_get_drvdata(pdev); |
590 | struct resource *mem; | 739 | struct resource *mem; |
591 | 740 | ||
741 | i2c_davinci_cpufreq_deregister(dev); | ||
742 | |||
592 | platform_set_drvdata(pdev, NULL); | 743 | platform_set_drvdata(pdev, NULL); |
593 | i2c_del_adapter(&dev->adapter); | 744 | i2c_del_adapter(&dev->adapter); |
594 | put_device(&pdev->dev); | 745 | put_device(&pdev->dev); |
@@ -599,6 +750,7 @@ static int davinci_i2c_remove(struct platform_device *pdev) | |||
599 | 750 | ||
600 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); | 751 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); |
601 | free_irq(IRQ_I2C, dev); | 752 | free_irq(IRQ_I2C, dev); |
753 | iounmap(dev->base); | ||
602 | kfree(dev); | 754 | kfree(dev); |
603 | 755 | ||
604 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 756 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -606,6 +758,41 @@ static int davinci_i2c_remove(struct platform_device *pdev) | |||
606 | return 0; | 758 | return 0; |
607 | } | 759 | } |
608 | 760 | ||
761 | #ifdef CONFIG_PM | ||
762 | static int davinci_i2c_suspend(struct device *dev) | ||
763 | { | ||
764 | struct platform_device *pdev = to_platform_device(dev); | ||
765 | struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev); | ||
766 | |||
767 | /* put I2C into reset */ | ||
768 | davinci_i2c_reset_ctrl(i2c_dev, 0); | ||
769 | clk_disable(i2c_dev->clk); | ||
770 | |||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | static int davinci_i2c_resume(struct device *dev) | ||
775 | { | ||
776 | struct platform_device *pdev = to_platform_device(dev); | ||
777 | struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev); | ||
778 | |||
779 | clk_enable(i2c_dev->clk); | ||
780 | /* take I2C out of reset */ | ||
781 | davinci_i2c_reset_ctrl(i2c_dev, 1); | ||
782 | |||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | static const struct dev_pm_ops davinci_i2c_pm = { | ||
787 | .suspend = davinci_i2c_suspend, | ||
788 | .resume = davinci_i2c_resume, | ||
789 | }; | ||
790 | |||
791 | #define davinci_i2c_pm_ops (&davinci_i2c_pm) | ||
792 | #else | ||
793 | #define davinci_i2c_pm_ops NULL | ||
794 | #endif | ||
795 | |||
609 | /* work with hotplug and coldplug */ | 796 | /* work with hotplug and coldplug */ |
610 | MODULE_ALIAS("platform:i2c_davinci"); | 797 | MODULE_ALIAS("platform:i2c_davinci"); |
611 | 798 | ||
@@ -615,6 +802,7 @@ static struct platform_driver davinci_i2c_driver = { | |||
615 | .driver = { | 802 | .driver = { |
616 | .name = "i2c_davinci", | 803 | .name = "i2c_davinci", |
617 | .owner = THIS_MODULE, | 804 | .owner = THIS_MODULE, |
805 | .pm = davinci_i2c_pm_ops, | ||
618 | }, | 806 | }, |
619 | }; | 807 | }; |
620 | 808 | ||
diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c new file mode 100644 index 000000000000..92d770d7bbc2 --- /dev/null +++ b/drivers/i2c/busses/i2c-nuc900.c | |||
@@ -0,0 +1,709 @@ | |||
1 | /* | ||
2 | * linux/drivers/i2c/busses/i2c-nuc900.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Nuvoton technology corporation. | ||
5 | * | ||
6 | * This driver based on S3C2410 I2C driver of Ben Dooks <ben-Y5A6D6n0/KfQXOPxS62xeg@public.gmane.org>. | ||
7 | * Written by Wan ZongShun <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation;version 2 of the License. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | |||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/i2c-id.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/clk.h> | ||
28 | #include <linux/cpufreq.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/io.h> | ||
31 | |||
32 | #include <mach/mfp.h> | ||
33 | #include <mach/i2c.h> | ||
34 | |||
35 | /* nuc900 i2c registers offset */ | ||
36 | |||
37 | #define CSR 0x00 | ||
38 | #define DIVIDER 0x04 | ||
39 | #define CMDR 0x08 | ||
40 | #define SWR 0x0C | ||
41 | #define RXR 0x10 | ||
42 | #define TXR 0x14 | ||
43 | |||
44 | /* nuc900 i2c CSR register bits */ | ||
45 | |||
46 | #define IRQEN 0x003 | ||
47 | #define I2CBUSY 0x400 | ||
48 | #define I2CSTART 0x018 | ||
49 | #define IRQFLAG 0x004 | ||
50 | #define ARBIT_LOST 0x200 | ||
51 | #define SLAVE_ACK 0x800 | ||
52 | |||
53 | /* nuc900 i2c CMDR register bits */ | ||
54 | |||
55 | #define I2C_CMD_START 0x10 | ||
56 | #define I2C_CMD_STOP 0x08 | ||
57 | #define I2C_CMD_READ 0x04 | ||
58 | #define I2C_CMD_WRITE 0x02 | ||
59 | #define I2C_CMD_NACK 0x01 | ||
60 | |||
61 | /* i2c controller state */ | ||
62 | |||
63 | enum nuc900_i2c_state { | ||
64 | STATE_IDLE, | ||
65 | STATE_START, | ||
66 | STATE_READ, | ||
67 | STATE_WRITE, | ||
68 | STATE_STOP | ||
69 | }; | ||
70 | |||
71 | /* i2c controller private data */ | ||
72 | |||
73 | struct nuc900_i2c { | ||
74 | spinlock_t lock; | ||
75 | wait_queue_head_t wait; | ||
76 | |||
77 | struct i2c_msg *msg; | ||
78 | unsigned int msg_num; | ||
79 | unsigned int msg_idx; | ||
80 | unsigned int msg_ptr; | ||
81 | unsigned int irq; | ||
82 | |||
83 | enum nuc900_i2c_state state; | ||
84 | |||
85 | void __iomem *regs; | ||
86 | struct clk *clk; | ||
87 | struct device *dev; | ||
88 | struct resource *ioarea; | ||
89 | struct i2c_adapter adap; | ||
90 | }; | ||
91 | |||
92 | /* nuc900_i2c_master_complete | ||
93 | * | ||
94 | * complete the message and wake up the caller, using the given return code, | ||
95 | * or zero to mean ok. | ||
96 | */ | ||
97 | |||
98 | static inline void nuc900_i2c_master_complete(struct nuc900_i2c *i2c, int ret) | ||
99 | { | ||
100 | dev_dbg(i2c->dev, "master_complete %d\n", ret); | ||
101 | |||
102 | i2c->msg_ptr = 0; | ||
103 | i2c->msg = NULL; | ||
104 | i2c->msg_idx++; | ||
105 | i2c->msg_num = 0; | ||
106 | if (ret) | ||
107 | i2c->msg_idx = ret; | ||
108 | |||
109 | wake_up(&i2c->wait); | ||
110 | } | ||
111 | |||
112 | /* irq enable/disable functions */ | ||
113 | |||
114 | static inline void nuc900_i2c_disable_irq(struct nuc900_i2c *i2c) | ||
115 | { | ||
116 | unsigned long tmp; | ||
117 | |||
118 | tmp = readl(i2c->regs + CSR); | ||
119 | writel(tmp & ~IRQEN, i2c->regs + CSR); | ||
120 | } | ||
121 | |||
122 | static inline void nuc900_i2c_enable_irq(struct nuc900_i2c *i2c) | ||
123 | { | ||
124 | unsigned long tmp; | ||
125 | |||
126 | tmp = readl(i2c->regs + CSR); | ||
127 | writel(tmp | IRQEN, i2c->regs + CSR); | ||
128 | } | ||
129 | |||
130 | |||
131 | /* nuc900_i2c_message_start | ||
132 | * | ||
133 | * put the start of a message onto the bus | ||
134 | */ | ||
135 | |||
136 | static void nuc900_i2c_message_start(struct nuc900_i2c *i2c, | ||
137 | struct i2c_msg *msg) | ||
138 | { | ||
139 | unsigned int addr = (msg->addr & 0x7f) << 1; | ||
140 | |||
141 | if (msg->flags & I2C_M_RD) | ||
142 | addr |= 0x1; | ||
143 | writel(addr & 0xff, i2c->regs + TXR); | ||
144 | writel(I2C_CMD_START | I2C_CMD_WRITE, i2c->regs + CMDR); | ||
145 | } | ||
146 | |||
147 | static inline void nuc900_i2c_stop(struct nuc900_i2c *i2c, int ret) | ||
148 | { | ||
149 | |||
150 | dev_dbg(i2c->dev, "STOP\n"); | ||
151 | |||
152 | /* stop the transfer */ | ||
153 | i2c->state = STATE_STOP; | ||
154 | writel(I2C_CMD_STOP, i2c->regs + CMDR); | ||
155 | |||
156 | nuc900_i2c_master_complete(i2c, ret); | ||
157 | nuc900_i2c_disable_irq(i2c); | ||
158 | } | ||
159 | |||
160 | /* helper functions to determine the current state in the set of | ||
161 | * messages we are sending | ||
162 | */ | ||
163 | |||
164 | /* is_lastmsg() | ||
165 | * | ||
166 | * returns TRUE if the current message is the last in the set | ||
167 | */ | ||
168 | |||
169 | static inline int is_lastmsg(struct nuc900_i2c *i2c) | ||
170 | { | ||
171 | return i2c->msg_idx >= (i2c->msg_num - 1); | ||
172 | } | ||
173 | |||
174 | /* is_msglast | ||
175 | * | ||
176 | * returns TRUE if we this is the last byte in the current message | ||
177 | */ | ||
178 | |||
179 | static inline int is_msglast(struct nuc900_i2c *i2c) | ||
180 | { | ||
181 | return i2c->msg_ptr == i2c->msg->len-1; | ||
182 | } | ||
183 | |||
184 | /* is_msgend | ||
185 | * | ||
186 | * returns TRUE if we reached the end of the current message | ||
187 | */ | ||
188 | |||
189 | static inline int is_msgend(struct nuc900_i2c *i2c) | ||
190 | { | ||
191 | return i2c->msg_ptr >= i2c->msg->len; | ||
192 | } | ||
193 | |||
194 | /* i2c_nuc900_irq_nextbyte | ||
195 | * | ||
196 | * process an interrupt and work out what to do | ||
197 | */ | ||
198 | |||
199 | static void i2c_nuc900_irq_nextbyte(struct nuc900_i2c *i2c, | ||
200 | unsigned long iicstat) | ||
201 | { | ||
202 | unsigned char byte; | ||
203 | |||
204 | switch (i2c->state) { | ||
205 | |||
206 | case STATE_IDLE: | ||
207 | dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__); | ||
208 | break; | ||
209 | |||
210 | case STATE_STOP: | ||
211 | dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); | ||
212 | nuc900_i2c_disable_irq(i2c); | ||
213 | break; | ||
214 | |||
215 | case STATE_START: | ||
216 | /* last thing we did was send a start condition on the | ||
217 | * bus, or started a new i2c message | ||
218 | */ | ||
219 | |||
220 | if (iicstat & SLAVE_ACK && | ||
221 | !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { | ||
222 | /* ack was not received... */ | ||
223 | |||
224 | dev_dbg(i2c->dev, "ack was not received\n"); | ||
225 | nuc900_i2c_stop(i2c, -ENXIO); | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | if (i2c->msg->flags & I2C_M_RD) | ||
230 | i2c->state = STATE_READ; | ||
231 | else | ||
232 | i2c->state = STATE_WRITE; | ||
233 | |||
234 | /* terminate the transfer if there is nothing to do | ||
235 | * as this is used by the i2c probe to find devices. | ||
236 | */ | ||
237 | |||
238 | if (is_lastmsg(i2c) && i2c->msg->len == 0) { | ||
239 | nuc900_i2c_stop(i2c, 0); | ||
240 | break; | ||
241 | } | ||
242 | |||
243 | if (i2c->state == STATE_READ) | ||
244 | goto prepare_read; | ||
245 | |||
246 | /* fall through to the write state, as we will need to | ||
247 | * send a byte as well | ||
248 | */ | ||
249 | |||
250 | case STATE_WRITE: | ||
251 | /* we are writing data to the device... check for the | ||
252 | * end of the message, and if so, work out what to do | ||
253 | */ | ||
254 | |||
255 | if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { | ||
256 | if (iicstat & SLAVE_ACK) { | ||
257 | dev_dbg(i2c->dev, "WRITE: No Ack\n"); | ||
258 | |||
259 | nuc900_i2c_stop(i2c, -ECONNREFUSED); | ||
260 | break; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | retry_write: | ||
265 | |||
266 | if (!is_msgend(i2c)) { | ||
267 | byte = i2c->msg->buf[i2c->msg_ptr++]; | ||
268 | writeb(byte, i2c->regs + TXR); | ||
269 | writel(I2C_CMD_WRITE, i2c->regs + CMDR); | ||
270 | |||
271 | } else if (!is_lastmsg(i2c)) { | ||
272 | /* we need to go to the next i2c message */ | ||
273 | |||
274 | dev_dbg(i2c->dev, "WRITE: Next Message\n"); | ||
275 | |||
276 | i2c->msg_ptr = 0; | ||
277 | i2c->msg_idx++; | ||
278 | i2c->msg++; | ||
279 | |||
280 | /* check to see if we need to do another message */ | ||
281 | if (i2c->msg->flags & I2C_M_NOSTART) { | ||
282 | |||
283 | if (i2c->msg->flags & I2C_M_RD) { | ||
284 | /* cannot do this, the controller | ||
285 | * forces us to send a new START | ||
286 | * when we change direction | ||
287 | */ | ||
288 | |||
289 | nuc900_i2c_stop(i2c, -EINVAL); | ||
290 | } | ||
291 | |||
292 | goto retry_write; | ||
293 | } else { | ||
294 | /* send the new start */ | ||
295 | nuc900_i2c_message_start(i2c, i2c->msg); | ||
296 | i2c->state = STATE_START; | ||
297 | } | ||
298 | |||
299 | } else { | ||
300 | /* send stop */ | ||
301 | |||
302 | nuc900_i2c_stop(i2c, 0); | ||
303 | } | ||
304 | break; | ||
305 | |||
306 | case STATE_READ: | ||
307 | /* we have a byte of data in the data register, do | ||
308 | * something with it, and then work out wether we are | ||
309 | * going to do any more read/write | ||
310 | */ | ||
311 | |||
312 | byte = readb(i2c->regs + RXR); | ||
313 | i2c->msg->buf[i2c->msg_ptr++] = byte; | ||
314 | |||
315 | prepare_read: | ||
316 | if (is_msglast(i2c)) { | ||
317 | /* last byte of buffer */ | ||
318 | |||
319 | if (is_lastmsg(i2c)) | ||
320 | writel(I2C_CMD_READ | I2C_CMD_NACK, | ||
321 | i2c->regs + CMDR); | ||
322 | |||
323 | } else if (is_msgend(i2c)) { | ||
324 | /* ok, we've read the entire buffer, see if there | ||
325 | * is anything else we need to do | ||
326 | */ | ||
327 | |||
328 | if (is_lastmsg(i2c)) { | ||
329 | /* last message, send stop and complete */ | ||
330 | dev_dbg(i2c->dev, "READ: Send Stop\n"); | ||
331 | |||
332 | nuc900_i2c_stop(i2c, 0); | ||
333 | } else { | ||
334 | /* go to the next transfer */ | ||
335 | dev_dbg(i2c->dev, "READ: Next Transfer\n"); | ||
336 | |||
337 | i2c->msg_ptr = 0; | ||
338 | i2c->msg_idx++; | ||
339 | i2c->msg++; | ||
340 | |||
341 | writel(I2C_CMD_READ, i2c->regs + CMDR); | ||
342 | } | ||
343 | |||
344 | } else { | ||
345 | writel(I2C_CMD_READ, i2c->regs + CMDR); | ||
346 | } | ||
347 | |||
348 | break; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | /* nuc900_i2c_irq | ||
353 | * | ||
354 | * top level IRQ servicing routine | ||
355 | */ | ||
356 | |||
357 | static irqreturn_t nuc900_i2c_irq(int irqno, void *dev_id) | ||
358 | { | ||
359 | struct nuc900_i2c *i2c = dev_id; | ||
360 | unsigned long status; | ||
361 | |||
362 | status = readl(i2c->regs + CSR); | ||
363 | writel(status | IRQFLAG, i2c->regs + CSR); | ||
364 | |||
365 | if (status & ARBIT_LOST) { | ||
366 | /* deal with arbitration loss */ | ||
367 | dev_err(i2c->dev, "deal with arbitration loss\n"); | ||
368 | goto out; | ||
369 | } | ||
370 | |||
371 | if (i2c->state == STATE_IDLE) { | ||
372 | dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); | ||
373 | goto out; | ||
374 | } | ||
375 | |||
376 | /* pretty much this leaves us with the fact that we've | ||
377 | * transmitted or received whatever byte we last sent | ||
378 | */ | ||
379 | |||
380 | i2c_nuc900_irq_nextbyte(i2c, status); | ||
381 | |||
382 | out: | ||
383 | return IRQ_HANDLED; | ||
384 | } | ||
385 | |||
386 | |||
387 | /* nuc900_i2c_set_master | ||
388 | * | ||
389 | * get the i2c bus for a master transaction | ||
390 | */ | ||
391 | |||
392 | static int nuc900_i2c_set_master(struct nuc900_i2c *i2c) | ||
393 | { | ||
394 | int timeout = 400; | ||
395 | |||
396 | while (timeout-- > 0) { | ||
397 | if (((readl(i2c->regs + SWR) & I2CSTART) == I2CSTART) && | ||
398 | ((readl(i2c->regs + CSR) & I2CBUSY) == 0)) { | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | msleep(1); | ||
403 | } | ||
404 | |||
405 | return -ETIMEDOUT; | ||
406 | } | ||
407 | |||
408 | /* nuc900_i2c_doxfer | ||
409 | * | ||
410 | * this starts an i2c transfer | ||
411 | */ | ||
412 | |||
413 | static int nuc900_i2c_doxfer(struct nuc900_i2c *i2c, | ||
414 | struct i2c_msg *msgs, int num) | ||
415 | { | ||
416 | unsigned long iicstat, timeout; | ||
417 | int spins = 20; | ||
418 | int ret; | ||
419 | |||
420 | ret = nuc900_i2c_set_master(i2c); | ||
421 | if (ret != 0) { | ||
422 | dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); | ||
423 | ret = -EAGAIN; | ||
424 | goto out; | ||
425 | } | ||
426 | |||
427 | spin_lock_irq(&i2c->lock); | ||
428 | |||
429 | i2c->msg = msgs; | ||
430 | i2c->msg_num = num; | ||
431 | i2c->msg_ptr = 0; | ||
432 | i2c->msg_idx = 0; | ||
433 | i2c->state = STATE_START; | ||
434 | |||
435 | nuc900_i2c_message_start(i2c, msgs); | ||
436 | spin_unlock_irq(&i2c->lock); | ||
437 | |||
438 | timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); | ||
439 | |||
440 | ret = i2c->msg_idx; | ||
441 | |||
442 | /* having these next two as dev_err() makes life very | ||
443 | * noisy when doing an i2cdetect | ||
444 | */ | ||
445 | |||
446 | if (timeout == 0) | ||
447 | dev_dbg(i2c->dev, "timeout\n"); | ||
448 | else if (ret != num) | ||
449 | dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); | ||
450 | |||
451 | /* ensure the stop has been through the bus */ | ||
452 | |||
453 | dev_dbg(i2c->dev, "waiting for bus idle\n"); | ||
454 | |||
455 | /* first, try busy waiting briefly */ | ||
456 | do { | ||
457 | iicstat = readl(i2c->regs + CSR); | ||
458 | } while ((iicstat & I2CBUSY) && --spins); | ||
459 | |||
460 | /* if that timed out sleep */ | ||
461 | if (!spins) { | ||
462 | msleep(1); | ||
463 | iicstat = readl(i2c->regs + CSR); | ||
464 | } | ||
465 | |||
466 | if (iicstat & I2CBUSY) | ||
467 | dev_warn(i2c->dev, "timeout waiting for bus idle\n"); | ||
468 | |||
469 | out: | ||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | /* nuc900_i2c_xfer | ||
474 | * | ||
475 | * first port of call from the i2c bus code when an message needs | ||
476 | * transferring across the i2c bus. | ||
477 | */ | ||
478 | |||
479 | static int nuc900_i2c_xfer(struct i2c_adapter *adap, | ||
480 | struct i2c_msg *msgs, int num) | ||
481 | { | ||
482 | struct nuc900_i2c *i2c = (struct nuc900_i2c *)adap->algo_data; | ||
483 | int retry; | ||
484 | int ret; | ||
485 | |||
486 | nuc900_i2c_enable_irq(i2c); | ||
487 | |||
488 | for (retry = 0; retry < adap->retries; retry++) { | ||
489 | |||
490 | ret = nuc900_i2c_doxfer(i2c, msgs, num); | ||
491 | |||
492 | if (ret != -EAGAIN) | ||
493 | return ret; | ||
494 | |||
495 | dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); | ||
496 | |||
497 | udelay(100); | ||
498 | } | ||
499 | |||
500 | return -EREMOTEIO; | ||
501 | } | ||
502 | |||
503 | /* declare our i2c functionality */ | ||
504 | static u32 nuc900_i2c_func(struct i2c_adapter *adap) | ||
505 | { | ||
506 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; | ||
507 | } | ||
508 | |||
509 | /* i2c bus registration info */ | ||
510 | |||
511 | static const struct i2c_algorithm nuc900_i2c_algorithm = { | ||
512 | .master_xfer = nuc900_i2c_xfer, | ||
513 | .functionality = nuc900_i2c_func, | ||
514 | }; | ||
515 | |||
516 | /* nuc900_i2c_probe | ||
517 | * | ||
518 | * called by the bus driver when a suitable device is found | ||
519 | */ | ||
520 | |||
521 | static int __devinit nuc900_i2c_probe(struct platform_device *pdev) | ||
522 | { | ||
523 | struct nuc900_i2c *i2c; | ||
524 | struct nuc900_platform_i2c *pdata; | ||
525 | struct resource *res; | ||
526 | int ret; | ||
527 | |||
528 | pdata = pdev->dev.platform_data; | ||
529 | if (!pdata) { | ||
530 | dev_err(&pdev->dev, "no platform data\n"); | ||
531 | return -EINVAL; | ||
532 | } | ||
533 | |||
534 | i2c = kzalloc(sizeof(struct nuc900_i2c), GFP_KERNEL); | ||
535 | if (!i2c) { | ||
536 | dev_err(&pdev->dev, "no memory for state\n"); | ||
537 | return -ENOMEM; | ||
538 | } | ||
539 | |||
540 | strlcpy(i2c->adap.name, "nuc900-i2c0", sizeof(i2c->adap.name)); | ||
541 | i2c->adap.owner = THIS_MODULE; | ||
542 | i2c->adap.algo = &nuc900_i2c_algorithm; | ||
543 | i2c->adap.retries = 2; | ||
544 | i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; | ||
545 | |||
546 | spin_lock_init(&i2c->lock); | ||
547 | init_waitqueue_head(&i2c->wait); | ||
548 | |||
549 | /* find the clock and enable it */ | ||
550 | |||
551 | i2c->dev = &pdev->dev; | ||
552 | i2c->clk = clk_get(&pdev->dev, NULL); | ||
553 | if (IS_ERR(i2c->clk)) { | ||
554 | dev_err(&pdev->dev, "cannot get clock\n"); | ||
555 | ret = -ENOENT; | ||
556 | goto err_noclk; | ||
557 | } | ||
558 | |||
559 | dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); | ||
560 | |||
561 | clk_enable(i2c->clk); | ||
562 | |||
563 | /* map the registers */ | ||
564 | |||
565 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
566 | if (res == NULL) { | ||
567 | dev_err(&pdev->dev, "cannot find IO resource\n"); | ||
568 | ret = -ENOENT; | ||
569 | goto err_clk; | ||
570 | } | ||
571 | |||
572 | i2c->ioarea = request_mem_region(res->start, resource_size(res), | ||
573 | pdev->name); | ||
574 | |||
575 | if (i2c->ioarea == NULL) { | ||
576 | dev_err(&pdev->dev, "cannot request IO\n"); | ||
577 | ret = -ENXIO; | ||
578 | goto err_clk; | ||
579 | } | ||
580 | |||
581 | i2c->regs = ioremap(res->start, resource_size(res)); | ||
582 | |||
583 | if (i2c->regs == NULL) { | ||
584 | dev_err(&pdev->dev, "cannot map IO\n"); | ||
585 | ret = -ENXIO; | ||
586 | goto err_ioarea; | ||
587 | } | ||
588 | |||
589 | dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", | ||
590 | i2c->regs, i2c->ioarea, res); | ||
591 | |||
592 | /* setup info block for the i2c core */ | ||
593 | |||
594 | i2c->adap.algo_data = i2c; | ||
595 | i2c->adap.dev.parent = &pdev->dev; | ||
596 | |||
597 | mfp_set_groupg(&pdev->dev); | ||
598 | |||
599 | clk_get_rate(i2c->clk); | ||
600 | |||
601 | ret = (i2c->clk.apbfreq)/(pdata->bus_freq * 5) - 1; | ||
602 | writel(ret & 0xffff, i2c->regs + DIVIDER); | ||
603 | |||
604 | /* find the IRQ for this unit (note, this relies on the init call to | ||
605 | * ensure no current IRQs pending | ||
606 | */ | ||
607 | |||
608 | i2c->irq = ret = platform_get_irq(pdev, 0); | ||
609 | if (ret <= 0) { | ||
610 | dev_err(&pdev->dev, "cannot find IRQ\n"); | ||
611 | goto err_iomap; | ||
612 | } | ||
613 | |||
614 | ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_DISABLED | IRQF_SHARED, | ||
615 | dev_name(&pdev->dev), i2c); | ||
616 | |||
617 | if (ret != 0) { | ||
618 | dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); | ||
619 | goto err_iomap; | ||
620 | } | ||
621 | |||
622 | /* Note, previous versions of the driver used i2c_add_adapter() | ||
623 | * to add the bus at any number. We now pass the bus number via | ||
624 | * the platform data, so if unset it will now default to always | ||
625 | * being bus 0. | ||
626 | */ | ||
627 | |||
628 | i2c->adap.nr = pdata->bus_num; | ||
629 | |||
630 | ret = i2c_add_numbered_adapter(&i2c->adap); | ||
631 | if (ret < 0) { | ||
632 | dev_err(&pdev->dev, "failed to add bus to i2c core\n"); | ||
633 | goto err_irq; | ||
634 | } | ||
635 | |||
636 | platform_set_drvdata(pdev, i2c); | ||
637 | |||
638 | dev_info(&pdev->dev, "%s: NUC900 I2C adapter\n", | ||
639 | dev_name(&i2c->adap.dev)); | ||
640 | return 0; | ||
641 | |||
642 | err_irq: | ||
643 | free_irq(i2c->irq, i2c); | ||
644 | |||
645 | err_iomap: | ||
646 | iounmap(i2c->regs); | ||
647 | |||
648 | err_ioarea: | ||
649 | release_resource(i2c->ioarea); | ||
650 | kfree(i2c->ioarea); | ||
651 | |||
652 | err_clk: | ||
653 | clk_disable(i2c->clk); | ||
654 | clk_put(i2c->clk); | ||
655 | |||
656 | err_noclk: | ||
657 | kfree(i2c); | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | /* nuc900_i2c_remove | ||
662 | * | ||
663 | * called when device is removed from the bus | ||
664 | */ | ||
665 | |||
666 | static int __devexit nuc900_i2c_remove(struct platform_device *pdev) | ||
667 | { | ||
668 | struct nuc900_i2c *i2c = platform_get_drvdata(pdev); | ||
669 | |||
670 | i2c_del_adapter(&i2c->adap); | ||
671 | free_irq(i2c->irq, i2c); | ||
672 | |||
673 | clk_disable(i2c->clk); | ||
674 | clk_put(i2c->clk); | ||
675 | |||
676 | iounmap(i2c->regs); | ||
677 | |||
678 | release_resource(i2c->ioarea); | ||
679 | kfree(i2c->ioarea); | ||
680 | kfree(i2c); | ||
681 | |||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static struct platform_driver nuc900_i2c_driver = { | ||
686 | .probe = nuc900_i2c_probe, | ||
687 | .remove = __devexit_p(nuc900_i2c_remove), | ||
688 | .driver = { | ||
689 | .owner = THIS_MODULE, | ||
690 | .name = "nuc900-i2c0", | ||
691 | }, | ||
692 | }; | ||
693 | |||
694 | static int __init i2c_adap_nuc900_init(void) | ||
695 | { | ||
696 | return platform_driver_register(&nuc900_i2c_driver); | ||
697 | } | ||
698 | |||
699 | static void __exit i2c_adap_nuc900_exit(void) | ||
700 | { | ||
701 | platform_driver_unregister(&nuc900_i2c_driver); | ||
702 | } | ||
703 | subsys_initcall(i2c_adap_nuc900_init); | ||
704 | module_exit(i2c_adap_nuc900_exit); | ||
705 | |||
706 | MODULE_DESCRIPTION("NUC900 I2C Bus driver"); | ||
707 | MODULE_AUTHOR("Wan ZongShun, <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>"); | ||
708 | MODULE_LICENSE("GPL"); | ||
709 | MODULE_ALIAS("platform:nuc900-i2c0"); | ||
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 020ff23d762f..c94e51b2651e 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -1001,7 +1001,7 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
1001 | struct pxa_i2c *i2c; | 1001 | struct pxa_i2c *i2c; |
1002 | struct resource *res; | 1002 | struct resource *res; |
1003 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; | 1003 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; |
1004 | struct platform_device_id *id = platform_get_device_id(dev); | 1004 | const struct platform_device_id *id = platform_get_device_id(dev); |
1005 | int ret; | 1005 | int ret; |
1006 | int irq; | 1006 | int irq; |
1007 | 1007 | ||
diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig index fb5c5186d4aa..8489eb58a52c 100644 --- a/drivers/idle/Kconfig +++ b/drivers/idle/Kconfig | |||
@@ -1,9 +1,8 @@ | |||
1 | config INTEL_IDLE | 1 | config INTEL_IDLE |
2 | tristate "Cpuidle Driver for Intel Processors" | 2 | bool "Cpuidle Driver for Intel Processors" |
3 | depends on CPU_IDLE | 3 | depends on CPU_IDLE |
4 | depends on X86 | 4 | depends on X86 |
5 | depends on CPU_SUP_INTEL | 5 | depends on CPU_SUP_INTEL |
6 | depends on EXPERIMENTAL | ||
7 | help | 6 | help |
8 | Enable intel_idle, a cpuidle driver that includes knowledge of | 7 | Enable intel_idle, a cpuidle driver that includes knowledge of |
9 | native Intel hardware idle features. The acpi_idle driver | 8 | native Intel hardware idle features. The acpi_idle driver |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 03d202b1ff27..a10152bb1427 100755 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -77,10 +77,8 @@ static struct cpuidle_driver intel_idle_driver = { | |||
77 | }; | 77 | }; |
78 | /* intel_idle.max_cstate=0 disables driver */ | 78 | /* intel_idle.max_cstate=0 disables driver */ |
79 | static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1; | 79 | static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1; |
80 | static int power_policy = 7; /* 0 = max perf; 15 = max powersave */ | ||
81 | 80 | ||
82 | static unsigned int substates; | 81 | static unsigned int mwait_substates; |
83 | static int (*choose_substate)(int); | ||
84 | 82 | ||
85 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ | 83 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ |
86 | static unsigned int lapic_timer_reliable_states; | 84 | static unsigned int lapic_timer_reliable_states; |
@@ -168,41 +166,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { | |||
168 | .enter = NULL }, /* disabled */ | 166 | .enter = NULL }, /* disabled */ |
169 | }; | 167 | }; |
170 | 168 | ||
171 | /* | ||
172 | * choose_tunable_substate() | ||
173 | * | ||
174 | * Run-time decision on which C-state substate to invoke | ||
175 | * If power_policy = 0, choose shallowest substate (0) | ||
176 | * If power_policy = 15, choose deepest substate | ||
177 | * If power_policy = middle, choose middle substate etc. | ||
178 | */ | ||
179 | static int choose_tunable_substate(int cstate) | ||
180 | { | ||
181 | unsigned int num_substates; | ||
182 | unsigned int substate_choice; | ||
183 | |||
184 | power_policy &= 0xF; /* valid range: 0-15 */ | ||
185 | cstate &= 7; /* valid range: 0-7 */ | ||
186 | |||
187 | num_substates = (substates >> ((cstate) * 4)) & MWAIT_SUBSTATE_MASK; | ||
188 | |||
189 | if (num_substates <= 1) | ||
190 | return 0; | ||
191 | |||
192 | substate_choice = ((power_policy + (power_policy + 1) * | ||
193 | (num_substates - 1)) / 16); | ||
194 | |||
195 | return substate_choice; | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * choose_zero_substate() | ||
200 | */ | ||
201 | static int choose_zero_substate(int cstate) | ||
202 | { | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /** | 169 | /** |
207 | * intel_idle | 170 | * intel_idle |
208 | * @dev: cpuidle_device | 171 | * @dev: cpuidle_device |
@@ -220,8 +183,6 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state) | |||
220 | 183 | ||
221 | cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1; | 184 | cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1; |
222 | 185 | ||
223 | eax = eax + (choose_substate)(cstate); | ||
224 | |||
225 | local_irq_disable(); | 186 | local_irq_disable(); |
226 | 187 | ||
227 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) | 188 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) |
@@ -259,7 +220,7 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state) | |||
259 | */ | 220 | */ |
260 | static int intel_idle_probe(void) | 221 | static int intel_idle_probe(void) |
261 | { | 222 | { |
262 | unsigned int eax, ebx, ecx, edx; | 223 | unsigned int eax, ebx, ecx; |
263 | 224 | ||
264 | if (max_cstate == 0) { | 225 | if (max_cstate == 0) { |
265 | pr_debug(PREFIX "disabled\n"); | 226 | pr_debug(PREFIX "disabled\n"); |
@@ -275,17 +236,13 @@ static int intel_idle_probe(void) | |||
275 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) | 236 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) |
276 | return -ENODEV; | 237 | return -ENODEV; |
277 | 238 | ||
278 | cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx); | 239 | cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates); |
279 | 240 | ||
280 | if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) || | 241 | if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) || |
281 | !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) | 242 | !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) |
282 | return -ENODEV; | 243 | return -ENODEV; |
283 | #ifdef DEBUG | ||
284 | if (substates == 0) /* can over-ride via modparam */ | ||
285 | #endif | ||
286 | substates = edx; | ||
287 | 244 | ||
288 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", substates); | 245 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); |
289 | 246 | ||
290 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ | 247 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ |
291 | lapic_timer_reliable_states = 0xFFFFFFFF; | 248 | lapic_timer_reliable_states = 0xFFFFFFFF; |
@@ -299,18 +256,18 @@ static int intel_idle_probe(void) | |||
299 | case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ | 256 | case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ |
300 | case 0x1F: /* Core i7 and i5 Processor - Nehalem */ | 257 | case 0x1F: /* Core i7 and i5 Processor - Nehalem */ |
301 | case 0x2E: /* Nehalem-EX Xeon */ | 258 | case 0x2E: /* Nehalem-EX Xeon */ |
259 | case 0x2F: /* Westmere-EX Xeon */ | ||
302 | lapic_timer_reliable_states = (1 << 1); /* C1 */ | 260 | lapic_timer_reliable_states = (1 << 1); /* C1 */ |
303 | 261 | ||
304 | case 0x25: /* Westmere */ | 262 | case 0x25: /* Westmere */ |
305 | case 0x2C: /* Westmere */ | 263 | case 0x2C: /* Westmere */ |
306 | cpuidle_state_table = nehalem_cstates; | 264 | cpuidle_state_table = nehalem_cstates; |
307 | choose_substate = choose_tunable_substate; | ||
308 | break; | 265 | break; |
309 | 266 | ||
310 | case 0x1C: /* 28 - Atom Processor */ | 267 | case 0x1C: /* 28 - Atom Processor */ |
268 | case 0x26: /* 38 - Lincroft Atom Processor */ | ||
311 | lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ | 269 | lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ |
312 | cpuidle_state_table = atom_cstates; | 270 | cpuidle_state_table = atom_cstates; |
313 | choose_substate = choose_zero_substate; | ||
314 | break; | 271 | break; |
315 | #ifdef FUTURE_USE | 272 | #ifdef FUTURE_USE |
316 | case 0x17: /* 23 - Core 2 Duo */ | 273 | case 0x17: /* 23 - Core 2 Duo */ |
@@ -376,7 +333,7 @@ static int intel_idle_cpuidle_devices_init(void) | |||
376 | } | 333 | } |
377 | 334 | ||
378 | /* does the state exist in CPUID.MWAIT? */ | 335 | /* does the state exist in CPUID.MWAIT? */ |
379 | num_substates = (substates >> ((cstate) * 4)) | 336 | num_substates = (mwait_substates >> ((cstate) * 4)) |
380 | & MWAIT_SUBSTATE_MASK; | 337 | & MWAIT_SUBSTATE_MASK; |
381 | if (num_substates == 0) | 338 | if (num_substates == 0) |
382 | continue; | 339 | continue; |
@@ -450,11 +407,7 @@ static void __exit intel_idle_exit(void) | |||
450 | module_init(intel_idle_init); | 407 | module_init(intel_idle_init); |
451 | module_exit(intel_idle_exit); | 408 | module_exit(intel_idle_exit); |
452 | 409 | ||
453 | module_param(power_policy, int, 0644); | ||
454 | module_param(max_cstate, int, 0444); | 410 | module_param(max_cstate, int, 0444); |
455 | #ifdef DEBUG | ||
456 | module_param(substates, int, 0444); | ||
457 | #endif | ||
458 | 411 | ||
459 | MODULE_AUTHOR("Len Brown <len.brown@intel.com>"); | 412 | MODULE_AUTHOR("Len Brown <len.brown@intel.com>"); |
460 | MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION); | 413 | MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION); |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index b8f1719d7c02..6837a8ef9371 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -626,6 +626,7 @@ mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) | |||
626 | * mpt_register - Register protocol-specific main callback handler. | 626 | * mpt_register - Register protocol-specific main callback handler. |
627 | * @cbfunc: callback function pointer | 627 | * @cbfunc: callback function pointer |
628 | * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value) | 628 | * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value) |
629 | * @func_name: call function's name | ||
629 | * | 630 | * |
630 | * This routine is called by a protocol-specific driver (SCSI host, | 631 | * This routine is called by a protocol-specific driver (SCSI host, |
631 | * LAN, SCSI target) to register its reply callback routine. Each | 632 | * LAN, SCSI target) to register its reply callback routine. Each |
@@ -6559,7 +6560,7 @@ procmpt_destroy(void) | |||
6559 | } | 6560 | } |
6560 | 6561 | ||
6561 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6562 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
6562 | /** | 6563 | /* |
6563 | * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary. | 6564 | * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary. |
6564 | */ | 6565 | */ |
6565 | static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan); | 6566 | static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan); |
@@ -8003,6 +8004,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) | |||
8003 | * mpt_sas_log_info - Log information returned from SAS IOC. | 8004 | * mpt_sas_log_info - Log information returned from SAS IOC. |
8004 | * @ioc: Pointer to MPT_ADAPTER structure | 8005 | * @ioc: Pointer to MPT_ADAPTER structure |
8005 | * @log_info: U32 LogInfo reply word from the IOC | 8006 | * @log_info: U32 LogInfo reply word from the IOC |
8007 | * @cb_idx: callback function's handle | ||
8006 | * | 8008 | * |
8007 | * Refer to lsi/mpi_log_sas.h. | 8009 | * Refer to lsi/mpi_log_sas.h. |
8008 | **/ | 8010 | **/ |
@@ -8049,7 +8051,7 @@ union loginfo_type { | |||
8049 | code_desc = ir_code_str[sas_loginfo.dw.code]; | 8051 | code_desc = ir_code_str[sas_loginfo.dw.code]; |
8050 | if (sas_loginfo.dw.subcode >= | 8052 | if (sas_loginfo.dw.subcode >= |
8051 | ARRAY_SIZE(raid_sub_code_str)) | 8053 | ARRAY_SIZE(raid_sub_code_str)) |
8052 | break; | 8054 | break; |
8053 | if (sas_loginfo.dw.code == 0) | 8055 | if (sas_loginfo.dw.code == 0) |
8054 | sub_code_desc = | 8056 | sub_code_desc = |
8055 | raid_sub_code_str[sas_loginfo.dw.subcode]; | 8057 | raid_sub_code_str[sas_loginfo.dw.subcode]; |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 1145ea0792e6..62a35822003e 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -182,7 +182,7 @@ mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len) | |||
182 | host->data_dma, sizeof(*host->data), | 182 | host->data_dma, sizeof(*host->data), |
183 | DMA_FROM_DEVICE); | 183 | DMA_FROM_DEVICE); |
184 | 184 | ||
185 | status = spi_sync(host->spi, &host->readback); | 185 | status = spi_sync_locked(host->spi, &host->readback); |
186 | 186 | ||
187 | if (host->dma_dev) | 187 | if (host->dma_dev) |
188 | dma_sync_single_for_cpu(host->dma_dev, | 188 | dma_sync_single_for_cpu(host->dma_dev, |
@@ -541,7 +541,7 @@ mmc_spi_command_send(struct mmc_spi_host *host, | |||
541 | host->data_dma, sizeof(*host->data), | 541 | host->data_dma, sizeof(*host->data), |
542 | DMA_BIDIRECTIONAL); | 542 | DMA_BIDIRECTIONAL); |
543 | } | 543 | } |
544 | status = spi_sync(host->spi, &host->m); | 544 | status = spi_sync_locked(host->spi, &host->m); |
545 | 545 | ||
546 | if (host->dma_dev) | 546 | if (host->dma_dev) |
547 | dma_sync_single_for_cpu(host->dma_dev, | 547 | dma_sync_single_for_cpu(host->dma_dev, |
@@ -685,7 +685,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, | |||
685 | host->data_dma, sizeof(*scratch), | 685 | host->data_dma, sizeof(*scratch), |
686 | DMA_BIDIRECTIONAL); | 686 | DMA_BIDIRECTIONAL); |
687 | 687 | ||
688 | status = spi_sync(spi, &host->m); | 688 | status = spi_sync_locked(spi, &host->m); |
689 | 689 | ||
690 | if (status != 0) { | 690 | if (status != 0) { |
691 | dev_dbg(&spi->dev, "write error (%d)\n", status); | 691 | dev_dbg(&spi->dev, "write error (%d)\n", status); |
@@ -822,7 +822,7 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t, | |||
822 | DMA_FROM_DEVICE); | 822 | DMA_FROM_DEVICE); |
823 | } | 823 | } |
824 | 824 | ||
825 | status = spi_sync(spi, &host->m); | 825 | status = spi_sync_locked(spi, &host->m); |
826 | 826 | ||
827 | if (host->dma_dev) { | 827 | if (host->dma_dev) { |
828 | dma_sync_single_for_cpu(host->dma_dev, | 828 | dma_sync_single_for_cpu(host->dma_dev, |
@@ -1018,7 +1018,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, | |||
1018 | host->data_dma, sizeof(*scratch), | 1018 | host->data_dma, sizeof(*scratch), |
1019 | DMA_BIDIRECTIONAL); | 1019 | DMA_BIDIRECTIONAL); |
1020 | 1020 | ||
1021 | tmp = spi_sync(spi, &host->m); | 1021 | tmp = spi_sync_locked(spi, &host->m); |
1022 | 1022 | ||
1023 | if (host->dma_dev) | 1023 | if (host->dma_dev) |
1024 | dma_sync_single_for_cpu(host->dma_dev, | 1024 | dma_sync_single_for_cpu(host->dma_dev, |
@@ -1084,6 +1084,9 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1084 | } | 1084 | } |
1085 | #endif | 1085 | #endif |
1086 | 1086 | ||
1087 | /* request exclusive bus access */ | ||
1088 | spi_bus_lock(host->spi->master); | ||
1089 | |||
1087 | /* issue command; then optionally data and stop */ | 1090 | /* issue command; then optionally data and stop */ |
1088 | status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL); | 1091 | status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL); |
1089 | if (status == 0 && mrq->data) { | 1092 | if (status == 0 && mrq->data) { |
@@ -1094,6 +1097,9 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1094 | mmc_cs_off(host); | 1097 | mmc_cs_off(host); |
1095 | } | 1098 | } |
1096 | 1099 | ||
1100 | /* release the bus */ | ||
1101 | spi_bus_unlock(host->spi->master); | ||
1102 | |||
1097 | mmc_request_done(host->mmc, mrq); | 1103 | mmc_request_done(host->mmc, mrq); |
1098 | } | 1104 | } |
1099 | 1105 | ||
@@ -1290,23 +1296,6 @@ mmc_spi_detect_irq(int irq, void *mmc) | |||
1290 | return IRQ_HANDLED; | 1296 | return IRQ_HANDLED; |
1291 | } | 1297 | } |
1292 | 1298 | ||
1293 | struct count_children { | ||
1294 | unsigned n; | ||
1295 | struct bus_type *bus; | ||
1296 | }; | ||
1297 | |||
1298 | static int maybe_count_child(struct device *dev, void *c) | ||
1299 | { | ||
1300 | struct count_children *ccp = c; | ||
1301 | |||
1302 | if (dev->bus == ccp->bus) { | ||
1303 | if (ccp->n) | ||
1304 | return -EBUSY; | ||
1305 | ccp->n++; | ||
1306 | } | ||
1307 | return 0; | ||
1308 | } | ||
1309 | |||
1310 | static int mmc_spi_probe(struct spi_device *spi) | 1299 | static int mmc_spi_probe(struct spi_device *spi) |
1311 | { | 1300 | { |
1312 | void *ones; | 1301 | void *ones; |
@@ -1338,32 +1327,6 @@ static int mmc_spi_probe(struct spi_device *spi) | |||
1338 | return status; | 1327 | return status; |
1339 | } | 1328 | } |
1340 | 1329 | ||
1341 | /* We can use the bus safely iff nobody else will interfere with us. | ||
1342 | * Most commands consist of one SPI message to issue a command, then | ||
1343 | * several more to collect its response, then possibly more for data | ||
1344 | * transfer. Clocking access to other devices during that period will | ||
1345 | * corrupt the command execution. | ||
1346 | * | ||
1347 | * Until we have software primitives which guarantee non-interference, | ||
1348 | * we'll aim for a hardware-level guarantee. | ||
1349 | * | ||
1350 | * REVISIT we can't guarantee another device won't be added later... | ||
1351 | */ | ||
1352 | if (spi->master->num_chipselect > 1) { | ||
1353 | struct count_children cc; | ||
1354 | |||
1355 | cc.n = 0; | ||
1356 | cc.bus = spi->dev.bus; | ||
1357 | status = device_for_each_child(spi->dev.parent, &cc, | ||
1358 | maybe_count_child); | ||
1359 | if (status < 0) { | ||
1360 | dev_err(&spi->dev, "can't share SPI bus\n"); | ||
1361 | return status; | ||
1362 | } | ||
1363 | |||
1364 | dev_warn(&spi->dev, "ASSUMING SPI bus stays unshared!\n"); | ||
1365 | } | ||
1366 | |||
1367 | /* We need a supply of ones to transmit. This is the only time | 1330 | /* We need a supply of ones to transmit. This is the only time |
1368 | * the CPU touches these, so cache coherency isn't a concern. | 1331 | * the CPU touches these, so cache coherency isn't a concern. |
1369 | * | 1332 | * |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index f90941a785e4..6f512b5c117b 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -347,8 +347,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
347 | spi_message_add_tail(&t[1], &m); | 347 | spi_message_add_tail(&t[1], &m); |
348 | 348 | ||
349 | /* Byte count starts at zero. */ | 349 | /* Byte count starts at zero. */ |
350 | if (retlen) | 350 | *retlen = 0; |
351 | *retlen = 0; | ||
352 | 351 | ||
353 | mutex_lock(&flash->lock); | 352 | mutex_lock(&flash->lock); |
354 | 353 | ||
@@ -394,8 +393,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
394 | dev_name(&flash->spi->dev), __func__, "to", | 393 | dev_name(&flash->spi->dev), __func__, "to", |
395 | (u32)to, len); | 394 | (u32)to, len); |
396 | 395 | ||
397 | if (retlen) | 396 | *retlen = 0; |
398 | *retlen = 0; | ||
399 | 397 | ||
400 | /* sanity checks */ | 398 | /* sanity checks */ |
401 | if (!len) | 399 | if (!len) |
@@ -466,8 +464,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
466 | 464 | ||
467 | spi_sync(flash->spi, &m); | 465 | spi_sync(flash->spi, &m); |
468 | 466 | ||
469 | if (retlen) | 467 | *retlen += m.actual_length - m25p_cmdsz(flash); |
470 | *retlen += m.actual_length - m25p_cmdsz(flash); | ||
471 | } | 468 | } |
472 | } | 469 | } |
473 | 470 | ||
@@ -485,8 +482,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
485 | size_t actual; | 482 | size_t actual; |
486 | int cmd_sz, ret; | 483 | int cmd_sz, ret; |
487 | 484 | ||
488 | if (retlen) | 485 | *retlen = 0; |
489 | *retlen = 0; | ||
490 | 486 | ||
491 | /* sanity checks */ | 487 | /* sanity checks */ |
492 | if (!len) | 488 | if (!len) |
@@ -797,7 +793,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
797 | break; | 793 | break; |
798 | } | 794 | } |
799 | 795 | ||
800 | if (plat_id) | 796 | if (i < ARRAY_SIZE(m25p_ids) - 1) |
801 | id = plat_id; | 797 | id = plat_id; |
802 | else | 798 | else |
803 | dev_warn(&spi->dev, "unrecognized id %s\n", data->type); | 799 | dev_warn(&spi->dev, "unrecognized id %s\n", data->type); |
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 618fb42b86b0..532fe07cf886 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -56,7 +56,7 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting." | |||
56 | INTR_STATUS0__ERASE_COMP) | 56 | INTR_STATUS0__ERASE_COMP) |
57 | 57 | ||
58 | /* indicates whether or not the internal value for the flash bank is | 58 | /* indicates whether or not the internal value for the flash bank is |
59 | valid or not */ | 59 | * valid or not */ |
60 | #define CHIP_SELECT_INVALID -1 | 60 | #define CHIP_SELECT_INVALID -1 |
61 | 61 | ||
62 | #define SUPPORT_8BITECC 1 | 62 | #define SUPPORT_8BITECC 1 |
@@ -71,7 +71,7 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting." | |||
71 | #define mtd_to_denali(m) container_of(m, struct denali_nand_info, mtd) | 71 | #define mtd_to_denali(m) container_of(m, struct denali_nand_info, mtd) |
72 | 72 | ||
73 | /* These constants are defined by the driver to enable common driver | 73 | /* These constants are defined by the driver to enable common driver |
74 | configuration options. */ | 74 | * configuration options. */ |
75 | #define SPARE_ACCESS 0x41 | 75 | #define SPARE_ACCESS 0x41 |
76 | #define MAIN_ACCESS 0x42 | 76 | #define MAIN_ACCESS 0x42 |
77 | #define MAIN_SPARE_ACCESS 0x43 | 77 | #define MAIN_SPARE_ACCESS 0x43 |
@@ -97,7 +97,7 @@ static const struct pci_device_id denali_pci_ids[] = { | |||
97 | 97 | ||
98 | 98 | ||
99 | /* these are static lookup tables that give us easy access to | 99 | /* these are static lookup tables that give us easy access to |
100 | registers in the NAND controller. | 100 | * registers in the NAND controller. |
101 | */ | 101 | */ |
102 | static const uint32_t intr_status_addresses[4] = {INTR_STATUS0, | 102 | static const uint32_t intr_status_addresses[4] = {INTR_STATUS0, |
103 | INTR_STATUS1, | 103 | INTR_STATUS1, |
@@ -119,9 +119,6 @@ static const uint32_t reset_complete[4] = {INTR_STATUS0__RST_COMP, | |||
119 | INTR_STATUS2__RST_COMP, | 119 | INTR_STATUS2__RST_COMP, |
120 | INTR_STATUS3__RST_COMP}; | 120 | INTR_STATUS3__RST_COMP}; |
121 | 121 | ||
122 | /* specifies the debug level of the driver */ | ||
123 | static int nand_debug_level; | ||
124 | |||
125 | /* forward declarations */ | 122 | /* forward declarations */ |
126 | static void clear_interrupts(struct denali_nand_info *denali); | 123 | static void clear_interrupts(struct denali_nand_info *denali); |
127 | static uint32_t wait_for_irq(struct denali_nand_info *denali, | 124 | static uint32_t wait_for_irq(struct denali_nand_info *denali, |
@@ -130,22 +127,6 @@ static void denali_irq_enable(struct denali_nand_info *denali, | |||
130 | uint32_t int_mask); | 127 | uint32_t int_mask); |
131 | static uint32_t read_interrupt_status(struct denali_nand_info *denali); | 128 | static uint32_t read_interrupt_status(struct denali_nand_info *denali); |
132 | 129 | ||
133 | #define DEBUG_DENALI 0 | ||
134 | |||
135 | /* This is a wrapper for writing to the denali registers. | ||
136 | * this allows us to create debug information so we can | ||
137 | * observe how the driver is programming the device. | ||
138 | * it uses standard linux convention for (val, addr) */ | ||
139 | static void denali_write32(uint32_t value, void *addr) | ||
140 | { | ||
141 | iowrite32(value, addr); | ||
142 | |||
143 | #if DEBUG_DENALI | ||
144 | printk(KERN_INFO "wrote: 0x%x -> 0x%x\n", value, | ||
145 | (uint32_t)((uint32_t)addr & 0x1fff)); | ||
146 | #endif | ||
147 | } | ||
148 | |||
149 | /* Certain operations for the denali NAND controller use | 130 | /* Certain operations for the denali NAND controller use |
150 | * an indexed mode to read/write data. The operation is | 131 | * an indexed mode to read/write data. The operation is |
151 | * performed by writing the address value of the command | 132 | * performed by writing the address value of the command |
@@ -155,15 +136,15 @@ static void denali_write32(uint32_t value, void *addr) | |||
155 | static void index_addr(struct denali_nand_info *denali, | 136 | static void index_addr(struct denali_nand_info *denali, |
156 | uint32_t address, uint32_t data) | 137 | uint32_t address, uint32_t data) |
157 | { | 138 | { |
158 | denali_write32(address, denali->flash_mem); | 139 | iowrite32(address, denali->flash_mem); |
159 | denali_write32(data, denali->flash_mem + 0x10); | 140 | iowrite32(data, denali->flash_mem + 0x10); |
160 | } | 141 | } |
161 | 142 | ||
162 | /* Perform an indexed read of the device */ | 143 | /* Perform an indexed read of the device */ |
163 | static void index_addr_read_data(struct denali_nand_info *denali, | 144 | static void index_addr_read_data(struct denali_nand_info *denali, |
164 | uint32_t address, uint32_t *pdata) | 145 | uint32_t address, uint32_t *pdata) |
165 | { | 146 | { |
166 | denali_write32(address, denali->flash_mem); | 147 | iowrite32(address, denali->flash_mem); |
167 | *pdata = ioread32(denali->flash_mem + 0x10); | 148 | *pdata = ioread32(denali->flash_mem + 0x10); |
168 | } | 149 | } |
169 | 150 | ||
@@ -188,18 +169,11 @@ static void read_status(struct denali_nand_info *denali) | |||
188 | /* initialize the data buffer to store status */ | 169 | /* initialize the data buffer to store status */ |
189 | reset_buf(denali); | 170 | reset_buf(denali); |
190 | 171 | ||
191 | /* initiate a device status read */ | 172 | cmd = ioread32(denali->flash_reg + WRITE_PROTECT); |
192 | cmd = MODE_11 | BANK(denali->flash_bank); | 173 | if (cmd) |
193 | index_addr(denali, cmd | COMMAND_CYCLE, 0x70); | 174 | write_byte_to_buf(denali, NAND_STATUS_WP); |
194 | denali_write32(cmd | STATUS_CYCLE, denali->flash_mem); | 175 | else |
195 | 176 | write_byte_to_buf(denali, 0); | |
196 | /* update buffer with status value */ | ||
197 | write_byte_to_buf(denali, ioread32(denali->flash_mem + 0x10)); | ||
198 | |||
199 | #if DEBUG_DENALI | ||
200 | printk(KERN_INFO "device reporting status value of 0x%2x\n", | ||
201 | denali->buf.buf[0]); | ||
202 | #endif | ||
203 | } | 177 | } |
204 | 178 | ||
205 | /* resets a specific device connected to the core */ | 179 | /* resets a specific device connected to the core */ |
@@ -213,12 +187,12 @@ static void reset_bank(struct denali_nand_info *denali) | |||
213 | clear_interrupts(denali); | 187 | clear_interrupts(denali); |
214 | 188 | ||
215 | bank = device_reset_banks[denali->flash_bank]; | 189 | bank = device_reset_banks[denali->flash_bank]; |
216 | denali_write32(bank, denali->flash_reg + DEVICE_RESET); | 190 | iowrite32(bank, denali->flash_reg + DEVICE_RESET); |
217 | 191 | ||
218 | irq_status = wait_for_irq(denali, irq_mask); | 192 | irq_status = wait_for_irq(denali, irq_mask); |
219 | 193 | ||
220 | if (irq_status & operation_timeout[denali->flash_bank]) | 194 | if (irq_status & operation_timeout[denali->flash_bank]) |
221 | printk(KERN_ERR "reset bank failed.\n"); | 195 | dev_err(&denali->dev->dev, "reset bank failed.\n"); |
222 | } | 196 | } |
223 | 197 | ||
224 | /* Reset the flash controller */ | 198 | /* Reset the flash controller */ |
@@ -226,28 +200,28 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali) | |||
226 | { | 200 | { |
227 | uint32_t i; | 201 | uint32_t i; |
228 | 202 | ||
229 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | 203 | dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n", |
230 | __FILE__, __LINE__, __func__); | 204 | __FILE__, __LINE__, __func__); |
231 | 205 | ||
232 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) | 206 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) |
233 | denali_write32(reset_complete[i] | operation_timeout[i], | 207 | iowrite32(reset_complete[i] | operation_timeout[i], |
234 | denali->flash_reg + intr_status_addresses[i]); | 208 | denali->flash_reg + intr_status_addresses[i]); |
235 | 209 | ||
236 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { | 210 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { |
237 | denali_write32(device_reset_banks[i], | 211 | iowrite32(device_reset_banks[i], |
238 | denali->flash_reg + DEVICE_RESET); | 212 | denali->flash_reg + DEVICE_RESET); |
239 | while (!(ioread32(denali->flash_reg + | 213 | while (!(ioread32(denali->flash_reg + |
240 | intr_status_addresses[i]) & | 214 | intr_status_addresses[i]) & |
241 | (reset_complete[i] | operation_timeout[i]))) | 215 | (reset_complete[i] | operation_timeout[i]))) |
242 | ; | 216 | cpu_relax(); |
243 | if (ioread32(denali->flash_reg + intr_status_addresses[i]) & | 217 | if (ioread32(denali->flash_reg + intr_status_addresses[i]) & |
244 | operation_timeout[i]) | 218 | operation_timeout[i]) |
245 | nand_dbg_print(NAND_DBG_WARN, | 219 | dev_dbg(&denali->dev->dev, |
246 | "NAND Reset operation timed out on bank %d\n", i); | 220 | "NAND Reset operation timed out on bank %d\n", i); |
247 | } | 221 | } |
248 | 222 | ||
249 | for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) | 223 | for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) |
250 | denali_write32(reset_complete[i] | operation_timeout[i], | 224 | iowrite32(reset_complete[i] | operation_timeout[i], |
251 | denali->flash_reg + intr_status_addresses[i]); | 225 | denali->flash_reg + intr_status_addresses[i]); |
252 | 226 | ||
253 | return PASS; | 227 | return PASS; |
@@ -280,7 +254,7 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali, | |||
280 | uint16_t acc_clks; | 254 | uint16_t acc_clks; |
281 | uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt; | 255 | uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt; |
282 | 256 | ||
283 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | 257 | dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n", |
284 | __FILE__, __LINE__, __func__); | 258 | __FILE__, __LINE__, __func__); |
285 | 259 | ||
286 | en_lo = CEIL_DIV(Trp[mode], CLK_X); | 260 | en_lo = CEIL_DIV(Trp[mode], CLK_X); |
@@ -317,7 +291,7 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali, | |||
317 | acc_clks++; | 291 | acc_clks++; |
318 | 292 | ||
319 | if ((data_invalid - acc_clks * CLK_X) < 2) | 293 | if ((data_invalid - acc_clks * CLK_X) < 2) |
320 | nand_dbg_print(NAND_DBG_WARN, "%s, Line %d: Warning!\n", | 294 | dev_warn(&denali->dev->dev, "%s, Line %d: Warning!\n", |
321 | __FILE__, __LINE__); | 295 | __FILE__, __LINE__); |
322 | 296 | ||
323 | addr_2_data = CEIL_DIV(Tadl[mode], CLK_X); | 297 | addr_2_data = CEIL_DIV(Tadl[mode], CLK_X); |
@@ -345,14 +319,14 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali, | |||
345 | (ioread32(denali->flash_reg + DEVICE_ID) == 0x88)) | 319 | (ioread32(denali->flash_reg + DEVICE_ID) == 0x88)) |
346 | acc_clks = 6; | 320 | acc_clks = 6; |
347 | 321 | ||
348 | denali_write32(acc_clks, denali->flash_reg + ACC_CLKS); | 322 | iowrite32(acc_clks, denali->flash_reg + ACC_CLKS); |
349 | denali_write32(re_2_we, denali->flash_reg + RE_2_WE); | 323 | iowrite32(re_2_we, denali->flash_reg + RE_2_WE); |
350 | denali_write32(re_2_re, denali->flash_reg + RE_2_RE); | 324 | iowrite32(re_2_re, denali->flash_reg + RE_2_RE); |
351 | denali_write32(we_2_re, denali->flash_reg + WE_2_RE); | 325 | iowrite32(we_2_re, denali->flash_reg + WE_2_RE); |
352 | denali_write32(addr_2_data, denali->flash_reg + ADDR_2_DATA); | 326 | iowrite32(addr_2_data, denali->flash_reg + ADDR_2_DATA); |
353 | denali_write32(en_lo, denali->flash_reg + RDWR_EN_LO_CNT); | 327 | iowrite32(en_lo, denali->flash_reg + RDWR_EN_LO_CNT); |
354 | denali_write32(en_hi, denali->flash_reg + RDWR_EN_HI_CNT); | 328 | iowrite32(en_hi, denali->flash_reg + RDWR_EN_HI_CNT); |
355 | denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT); | 329 | iowrite32(cs_cnt, denali->flash_reg + CS_SETUP_CNT); |
356 | } | 330 | } |
357 | 331 | ||
358 | /* queries the NAND device to see what ONFI modes it supports. */ | 332 | /* queries the NAND device to see what ONFI modes it supports. */ |
@@ -387,13 +361,13 @@ static void get_samsung_nand_para(struct denali_nand_info *denali, | |||
387 | { | 361 | { |
388 | if (device_id == 0xd3) { /* Samsung K9WAG08U1A */ | 362 | if (device_id == 0xd3) { /* Samsung K9WAG08U1A */ |
389 | /* Set timing register values according to datasheet */ | 363 | /* Set timing register values according to datasheet */ |
390 | denali_write32(5, denali->flash_reg + ACC_CLKS); | 364 | iowrite32(5, denali->flash_reg + ACC_CLKS); |
391 | denali_write32(20, denali->flash_reg + RE_2_WE); | 365 | iowrite32(20, denali->flash_reg + RE_2_WE); |
392 | denali_write32(12, denali->flash_reg + WE_2_RE); | 366 | iowrite32(12, denali->flash_reg + WE_2_RE); |
393 | denali_write32(14, denali->flash_reg + ADDR_2_DATA); | 367 | iowrite32(14, denali->flash_reg + ADDR_2_DATA); |
394 | denali_write32(3, denali->flash_reg + RDWR_EN_LO_CNT); | 368 | iowrite32(3, denali->flash_reg + RDWR_EN_LO_CNT); |
395 | denali_write32(2, denali->flash_reg + RDWR_EN_HI_CNT); | 369 | iowrite32(2, denali->flash_reg + RDWR_EN_HI_CNT); |
396 | denali_write32(2, denali->flash_reg + CS_SETUP_CNT); | 370 | iowrite32(2, denali->flash_reg + CS_SETUP_CNT); |
397 | } | 371 | } |
398 | } | 372 | } |
399 | 373 | ||
@@ -405,15 +379,15 @@ static void get_toshiba_nand_para(struct denali_nand_info *denali) | |||
405 | /* spare area size for some kind of Toshiba NAND device */ | 379 | /* spare area size for some kind of Toshiba NAND device */ |
406 | if ((ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE) == 4096) && | 380 | if ((ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE) == 4096) && |
407 | (ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE) == 64)) { | 381 | (ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE) == 64)) { |
408 | denali_write32(216, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | 382 | iowrite32(216, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); |
409 | tmp = ioread32(denali->flash_reg + DEVICES_CONNECTED) * | 383 | tmp = ioread32(denali->flash_reg + DEVICES_CONNECTED) * |
410 | ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | 384 | ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE); |
411 | denali_write32(tmp, | 385 | iowrite32(tmp, |
412 | denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | 386 | denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); |
413 | #if SUPPORT_15BITECC | 387 | #if SUPPORT_15BITECC |
414 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); | 388 | iowrite32(15, denali->flash_reg + ECC_CORRECTION); |
415 | #elif SUPPORT_8BITECC | 389 | #elif SUPPORT_8BITECC |
416 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | 390 | iowrite32(8, denali->flash_reg + ECC_CORRECTION); |
417 | #endif | 391 | #endif |
418 | } | 392 | } |
419 | } | 393 | } |
@@ -426,26 +400,26 @@ static void get_hynix_nand_para(struct denali_nand_info *denali, | |||
426 | switch (device_id) { | 400 | switch (device_id) { |
427 | case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ | 401 | case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ |
428 | case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ | 402 | case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ |
429 | denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK); | 403 | iowrite32(128, denali->flash_reg + PAGES_PER_BLOCK); |
430 | denali_write32(4096, denali->flash_reg + DEVICE_MAIN_AREA_SIZE); | 404 | iowrite32(4096, denali->flash_reg + DEVICE_MAIN_AREA_SIZE); |
431 | denali_write32(224, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | 405 | iowrite32(224, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); |
432 | main_size = 4096 * | 406 | main_size = 4096 * |
433 | ioread32(denali->flash_reg + DEVICES_CONNECTED); | 407 | ioread32(denali->flash_reg + DEVICES_CONNECTED); |
434 | spare_size = 224 * | 408 | spare_size = 224 * |
435 | ioread32(denali->flash_reg + DEVICES_CONNECTED); | 409 | ioread32(denali->flash_reg + DEVICES_CONNECTED); |
436 | denali_write32(main_size, | 410 | iowrite32(main_size, |
437 | denali->flash_reg + LOGICAL_PAGE_DATA_SIZE); | 411 | denali->flash_reg + LOGICAL_PAGE_DATA_SIZE); |
438 | denali_write32(spare_size, | 412 | iowrite32(spare_size, |
439 | denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | 413 | denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); |
440 | denali_write32(0, denali->flash_reg + DEVICE_WIDTH); | 414 | iowrite32(0, denali->flash_reg + DEVICE_WIDTH); |
441 | #if SUPPORT_15BITECC | 415 | #if SUPPORT_15BITECC |
442 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); | 416 | iowrite32(15, denali->flash_reg + ECC_CORRECTION); |
443 | #elif SUPPORT_8BITECC | 417 | #elif SUPPORT_8BITECC |
444 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | 418 | iowrite32(8, denali->flash_reg + ECC_CORRECTION); |
445 | #endif | 419 | #endif |
446 | break; | 420 | break; |
447 | default: | 421 | default: |
448 | nand_dbg_print(NAND_DBG_WARN, | 422 | dev_warn(&denali->dev->dev, |
449 | "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." | 423 | "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." |
450 | "Will use default parameter values instead.\n", | 424 | "Will use default parameter values instead.\n", |
451 | device_id); | 425 | device_id); |
@@ -453,7 +427,7 @@ static void get_hynix_nand_para(struct denali_nand_info *denali, | |||
453 | } | 427 | } |
454 | 428 | ||
455 | /* determines how many NAND chips are connected to the controller. Note for | 429 | /* determines how many NAND chips are connected to the controller. Note for |
456 | Intel CE4100 devices we don't support more than one device. | 430 | * Intel CE4100 devices we don't support more than one device. |
457 | */ | 431 | */ |
458 | static void find_valid_banks(struct denali_nand_info *denali) | 432 | static void find_valid_banks(struct denali_nand_info *denali) |
459 | { | 433 | { |
@@ -467,7 +441,7 @@ static void find_valid_banks(struct denali_nand_info *denali) | |||
467 | index_addr_read_data(denali, | 441 | index_addr_read_data(denali, |
468 | (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]); | 442 | (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]); |
469 | 443 | ||
470 | nand_dbg_print(NAND_DBG_DEBUG, | 444 | dev_dbg(&denali->dev->dev, |
471 | "Return 1st ID for bank[%d]: %x\n", i, id[i]); | 445 | "Return 1st ID for bank[%d]: %x\n", i, id[i]); |
472 | 446 | ||
473 | if (i == 0) { | 447 | if (i == 0) { |
@@ -487,12 +461,13 @@ static void find_valid_banks(struct denali_nand_info *denali) | |||
487 | * Multichip support is not enabled. | 461 | * Multichip support is not enabled. |
488 | */ | 462 | */ |
489 | if (denali->total_used_banks != 1) { | 463 | if (denali->total_used_banks != 1) { |
490 | printk(KERN_ERR "Sorry, Intel CE4100 only supports " | 464 | dev_err(&denali->dev->dev, |
465 | "Sorry, Intel CE4100 only supports " | ||
491 | "a single NAND device.\n"); | 466 | "a single NAND device.\n"); |
492 | BUG(); | 467 | BUG(); |
493 | } | 468 | } |
494 | } | 469 | } |
495 | nand_dbg_print(NAND_DBG_DEBUG, | 470 | dev_dbg(&denali->dev->dev, |
496 | "denali->total_used_banks: %d\n", denali->total_used_banks); | 471 | "denali->total_used_banks: %d\n", denali->total_used_banks); |
497 | } | 472 | } |
498 | 473 | ||
@@ -526,8 +501,9 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) | |||
526 | uint32_t id_bytes[5], addr; | 501 | uint32_t id_bytes[5], addr; |
527 | uint8_t i, maf_id, device_id; | 502 | uint8_t i, maf_id, device_id; |
528 | 503 | ||
529 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | 504 | dev_dbg(&denali->dev->dev, |
530 | __FILE__, __LINE__, __func__); | 505 | "%s, Line %d, Function: %s\n", |
506 | __FILE__, __LINE__, __func__); | ||
531 | 507 | ||
532 | /* Use read id method to get device ID and other | 508 | /* Use read id method to get device ID and other |
533 | * params. For some NAND chips, controller can't | 509 | * params. For some NAND chips, controller can't |
@@ -554,12 +530,14 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) | |||
554 | get_hynix_nand_para(denali, device_id); | 530 | get_hynix_nand_para(denali, device_id); |
555 | } | 531 | } |
556 | 532 | ||
557 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" | 533 | dev_info(&denali->dev->dev, |
558 | "acc_clks: %d, re_2_we: %d, we_2_re: %d," | 534 | "Dump timing register values:" |
559 | "addr_2_data: %d, rdwr_en_lo_cnt: %d, " | 535 | "acc_clks: %d, re_2_we: %d, re_2_re: %d\n" |
536 | "we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n" | ||
560 | "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", | 537 | "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", |
561 | ioread32(denali->flash_reg + ACC_CLKS), | 538 | ioread32(denali->flash_reg + ACC_CLKS), |
562 | ioread32(denali->flash_reg + RE_2_WE), | 539 | ioread32(denali->flash_reg + RE_2_WE), |
540 | ioread32(denali->flash_reg + RE_2_RE), | ||
563 | ioread32(denali->flash_reg + WE_2_RE), | 541 | ioread32(denali->flash_reg + WE_2_RE), |
564 | ioread32(denali->flash_reg + ADDR_2_DATA), | 542 | ioread32(denali->flash_reg + ADDR_2_DATA), |
565 | ioread32(denali->flash_reg + RDWR_EN_LO_CNT), | 543 | ioread32(denali->flash_reg + RDWR_EN_LO_CNT), |
@@ -582,17 +560,17 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) | |||
582 | static void denali_set_intr_modes(struct denali_nand_info *denali, | 560 | static void denali_set_intr_modes(struct denali_nand_info *denali, |
583 | uint16_t INT_ENABLE) | 561 | uint16_t INT_ENABLE) |
584 | { | 562 | { |
585 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | 563 | dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n", |
586 | __FILE__, __LINE__, __func__); | 564 | __FILE__, __LINE__, __func__); |
587 | 565 | ||
588 | if (INT_ENABLE) | 566 | if (INT_ENABLE) |
589 | denali_write32(1, denali->flash_reg + GLOBAL_INT_ENABLE); | 567 | iowrite32(1, denali->flash_reg + GLOBAL_INT_ENABLE); |
590 | else | 568 | else |
591 | denali_write32(0, denali->flash_reg + GLOBAL_INT_ENABLE); | 569 | iowrite32(0, denali->flash_reg + GLOBAL_INT_ENABLE); |
592 | } | 570 | } |
593 | 571 | ||
594 | /* validation function to verify that the controlling software is making | 572 | /* validation function to verify that the controlling software is making |
595 | a valid request | 573 | * a valid request |
596 | */ | 574 | */ |
597 | static inline bool is_flash_bank_valid(int flash_bank) | 575 | static inline bool is_flash_bank_valid(int flash_bank) |
598 | { | 576 | { |
@@ -609,10 +587,10 @@ static void denali_irq_init(struct denali_nand_info *denali) | |||
609 | int_mask = DENALI_IRQ_ALL; | 587 | int_mask = DENALI_IRQ_ALL; |
610 | 588 | ||
611 | /* Clear all status bits */ | 589 | /* Clear all status bits */ |
612 | denali_write32(0xFFFF, denali->flash_reg + INTR_STATUS0); | 590 | iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS0); |
613 | denali_write32(0xFFFF, denali->flash_reg + INTR_STATUS1); | 591 | iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS1); |
614 | denali_write32(0xFFFF, denali->flash_reg + INTR_STATUS2); | 592 | iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS2); |
615 | denali_write32(0xFFFF, denali->flash_reg + INTR_STATUS3); | 593 | iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS3); |
616 | 594 | ||
617 | denali_irq_enable(denali, int_mask); | 595 | denali_irq_enable(denali, int_mask); |
618 | } | 596 | } |
@@ -626,10 +604,10 @@ static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali) | |||
626 | static void denali_irq_enable(struct denali_nand_info *denali, | 604 | static void denali_irq_enable(struct denali_nand_info *denali, |
627 | uint32_t int_mask) | 605 | uint32_t int_mask) |
628 | { | 606 | { |
629 | denali_write32(int_mask, denali->flash_reg + INTR_EN0); | 607 | iowrite32(int_mask, denali->flash_reg + INTR_EN0); |
630 | denali_write32(int_mask, denali->flash_reg + INTR_EN1); | 608 | iowrite32(int_mask, denali->flash_reg + INTR_EN1); |
631 | denali_write32(int_mask, denali->flash_reg + INTR_EN2); | 609 | iowrite32(int_mask, denali->flash_reg + INTR_EN2); |
632 | denali_write32(int_mask, denali->flash_reg + INTR_EN3); | 610 | iowrite32(int_mask, denali->flash_reg + INTR_EN3); |
633 | } | 611 | } |
634 | 612 | ||
635 | /* This function only returns when an interrupt that this driver cares about | 613 | /* This function only returns when an interrupt that this driver cares about |
@@ -648,7 +626,7 @@ static inline void clear_interrupt(struct denali_nand_info *denali, | |||
648 | 626 | ||
649 | intr_status_reg = intr_status_addresses[denali->flash_bank]; | 627 | intr_status_reg = intr_status_addresses[denali->flash_bank]; |
650 | 628 | ||
651 | denali_write32(irq_mask, denali->flash_reg + intr_status_reg); | 629 | iowrite32(irq_mask, denali->flash_reg + intr_status_reg); |
652 | } | 630 | } |
653 | 631 | ||
654 | static void clear_interrupts(struct denali_nand_info *denali) | 632 | static void clear_interrupts(struct denali_nand_info *denali) |
@@ -657,11 +635,7 @@ static void clear_interrupts(struct denali_nand_info *denali) | |||
657 | spin_lock_irq(&denali->irq_lock); | 635 | spin_lock_irq(&denali->irq_lock); |
658 | 636 | ||
659 | status = read_interrupt_status(denali); | 637 | status = read_interrupt_status(denali); |
660 | 638 | clear_interrupt(denali, status); | |
661 | #if DEBUG_DENALI | ||
662 | denali->irq_debug_array[denali->idx++] = 0x30000000 | status; | ||
663 | denali->idx %= 32; | ||
664 | #endif | ||
665 | 639 | ||
666 | denali->irq_status = 0x0; | 640 | denali->irq_status = 0x0; |
667 | spin_unlock_irq(&denali->irq_lock); | 641 | spin_unlock_irq(&denali->irq_lock); |
@@ -676,17 +650,6 @@ static uint32_t read_interrupt_status(struct denali_nand_info *denali) | |||
676 | return ioread32(denali->flash_reg + intr_status_reg); | 650 | return ioread32(denali->flash_reg + intr_status_reg); |
677 | } | 651 | } |
678 | 652 | ||
679 | #if DEBUG_DENALI | ||
680 | static void print_irq_log(struct denali_nand_info *denali) | ||
681 | { | ||
682 | int i = 0; | ||
683 | |||
684 | printk(KERN_INFO "ISR debug log index = %X\n", denali->idx); | ||
685 | for (i = 0; i < 32; i++) | ||
686 | printk(KERN_INFO "%08X: %08X\n", i, denali->irq_debug_array[i]); | ||
687 | } | ||
688 | #endif | ||
689 | |||
690 | /* This is the interrupt service routine. It handles all interrupts | 653 | /* This is the interrupt service routine. It handles all interrupts |
691 | * sent to this device. Note that on CE4100, this is a shared | 654 | * sent to this device. Note that on CE4100, this is a shared |
692 | * interrupt. | 655 | * interrupt. |
@@ -707,13 +670,6 @@ static irqreturn_t denali_isr(int irq, void *dev_id) | |||
707 | * the interrupt, since this is a shared interrupt */ | 670 | * the interrupt, since this is a shared interrupt */ |
708 | irq_status = denali_irq_detected(denali); | 671 | irq_status = denali_irq_detected(denali); |
709 | if (irq_status != 0) { | 672 | if (irq_status != 0) { |
710 | #if DEBUG_DENALI | ||
711 | denali->irq_debug_array[denali->idx++] = | ||
712 | 0x10000000 | irq_status; | ||
713 | denali->idx %= 32; | ||
714 | |||
715 | printk(KERN_INFO "IRQ status = 0x%04x\n", irq_status); | ||
716 | #endif | ||
717 | /* handle interrupt */ | 673 | /* handle interrupt */ |
718 | /* first acknowledge it */ | 674 | /* first acknowledge it */ |
719 | clear_interrupt(denali, irq_status); | 675 | clear_interrupt(denali, irq_status); |
@@ -739,41 +695,20 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask) | |||
739 | unsigned long timeout = msecs_to_jiffies(1000); | 695 | unsigned long timeout = msecs_to_jiffies(1000); |
740 | 696 | ||
741 | do { | 697 | do { |
742 | #if DEBUG_DENALI | ||
743 | printk(KERN_INFO "waiting for 0x%x\n", irq_mask); | ||
744 | #endif | ||
745 | comp_res = | 698 | comp_res = |
746 | wait_for_completion_timeout(&denali->complete, timeout); | 699 | wait_for_completion_timeout(&denali->complete, timeout); |
747 | spin_lock_irq(&denali->irq_lock); | 700 | spin_lock_irq(&denali->irq_lock); |
748 | intr_status = denali->irq_status; | 701 | intr_status = denali->irq_status; |
749 | 702 | ||
750 | #if DEBUG_DENALI | ||
751 | denali->irq_debug_array[denali->idx++] = | ||
752 | 0x20000000 | (irq_mask << 16) | intr_status; | ||
753 | denali->idx %= 32; | ||
754 | #endif | ||
755 | |||
756 | if (intr_status & irq_mask) { | 703 | if (intr_status & irq_mask) { |
757 | denali->irq_status &= ~irq_mask; | 704 | denali->irq_status &= ~irq_mask; |
758 | spin_unlock_irq(&denali->irq_lock); | 705 | spin_unlock_irq(&denali->irq_lock); |
759 | #if DEBUG_DENALI | ||
760 | if (retry) | ||
761 | printk(KERN_INFO "status on retry = 0x%x\n", | ||
762 | intr_status); | ||
763 | #endif | ||
764 | /* our interrupt was detected */ | 706 | /* our interrupt was detected */ |
765 | break; | 707 | break; |
766 | } else { | 708 | } else { |
767 | /* these are not the interrupts you are looking for - | 709 | /* these are not the interrupts you are looking for - |
768 | * need to wait again */ | 710 | * need to wait again */ |
769 | spin_unlock_irq(&denali->irq_lock); | 711 | spin_unlock_irq(&denali->irq_lock); |
770 | #if DEBUG_DENALI | ||
771 | print_irq_log(denali); | ||
772 | printk(KERN_INFO "received irq nobody cared:" | ||
773 | " irq_status = 0x%x, irq_mask = 0x%x," | ||
774 | " timeout = %ld\n", intr_status, | ||
775 | irq_mask, comp_res); | ||
776 | #endif | ||
777 | retry = true; | 712 | retry = true; |
778 | } | 713 | } |
779 | } while (comp_res != 0); | 714 | } while (comp_res != 0); |
@@ -789,7 +724,7 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask) | |||
789 | } | 724 | } |
790 | 725 | ||
791 | /* This helper function setups the registers for ECC and whether or not | 726 | /* This helper function setups the registers for ECC and whether or not |
792 | the spare area will be transfered. */ | 727 | * the spare area will be transfered. */ |
793 | static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, | 728 | static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, |
794 | bool transfer_spare) | 729 | bool transfer_spare) |
795 | { | 730 | { |
@@ -800,13 +735,13 @@ static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, | |||
800 | transfer_spare_flag = transfer_spare ? TRANSFER_SPARE_REG__FLAG : 0; | 735 | transfer_spare_flag = transfer_spare ? TRANSFER_SPARE_REG__FLAG : 0; |
801 | 736 | ||
802 | /* Enable spare area/ECC per user's request. */ | 737 | /* Enable spare area/ECC per user's request. */ |
803 | denali_write32(ecc_en_flag, denali->flash_reg + ECC_ENABLE); | 738 | iowrite32(ecc_en_flag, denali->flash_reg + ECC_ENABLE); |
804 | denali_write32(transfer_spare_flag, | 739 | iowrite32(transfer_spare_flag, |
805 | denali->flash_reg + TRANSFER_SPARE_REG); | 740 | denali->flash_reg + TRANSFER_SPARE_REG); |
806 | } | 741 | } |
807 | 742 | ||
808 | /* sends a pipeline command operation to the controller. See the Denali NAND | 743 | /* sends a pipeline command operation to the controller. See the Denali NAND |
809 | controller's user guide for more information (section 4.2.3.6). | 744 | * controller's user guide for more information (section 4.2.3.6). |
810 | */ | 745 | */ |
811 | static int denali_send_pipeline_cmd(struct denali_nand_info *denali, | 746 | static int denali_send_pipeline_cmd(struct denali_nand_info *denali, |
812 | bool ecc_en, | 747 | bool ecc_en, |
@@ -827,16 +762,6 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, | |||
827 | 762 | ||
828 | setup_ecc_for_xfer(denali, ecc_en, transfer_spare); | 763 | setup_ecc_for_xfer(denali, ecc_en, transfer_spare); |
829 | 764 | ||
830 | #if DEBUG_DENALI | ||
831 | spin_lock_irq(&denali->irq_lock); | ||
832 | denali->irq_debug_array[denali->idx++] = | ||
833 | 0x40000000 | ioread32(denali->flash_reg + ECC_ENABLE) | | ||
834 | (access_type << 4); | ||
835 | denali->idx %= 32; | ||
836 | spin_unlock_irq(&denali->irq_lock); | ||
837 | #endif | ||
838 | |||
839 | |||
840 | /* clear interrupts */ | 765 | /* clear interrupts */ |
841 | clear_interrupts(denali); | 766 | clear_interrupts(denali); |
842 | 767 | ||
@@ -844,14 +769,14 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, | |||
844 | 769 | ||
845 | if (op == DENALI_WRITE && access_type != SPARE_ACCESS) { | 770 | if (op == DENALI_WRITE && access_type != SPARE_ACCESS) { |
846 | cmd = MODE_01 | addr; | 771 | cmd = MODE_01 | addr; |
847 | denali_write32(cmd, denali->flash_mem); | 772 | iowrite32(cmd, denali->flash_mem); |
848 | } else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) { | 773 | } else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) { |
849 | /* read spare area */ | 774 | /* read spare area */ |
850 | cmd = MODE_10 | addr; | 775 | cmd = MODE_10 | addr; |
851 | index_addr(denali, (uint32_t)cmd, access_type); | 776 | index_addr(denali, (uint32_t)cmd, access_type); |
852 | 777 | ||
853 | cmd = MODE_01 | addr; | 778 | cmd = MODE_01 | addr; |
854 | denali_write32(cmd, denali->flash_mem); | 779 | iowrite32(cmd, denali->flash_mem); |
855 | } else if (op == DENALI_READ) { | 780 | } else if (op == DENALI_READ) { |
856 | /* setup page read request for access type */ | 781 | /* setup page read request for access type */ |
857 | cmd = MODE_10 | addr; | 782 | cmd = MODE_10 | addr; |
@@ -863,7 +788,7 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, | |||
863 | */ | 788 | */ |
864 | if (access_type == SPARE_ACCESS) { | 789 | if (access_type == SPARE_ACCESS) { |
865 | cmd = MODE_01 | addr; | 790 | cmd = MODE_01 | addr; |
866 | denali_write32(cmd, denali->flash_mem); | 791 | iowrite32(cmd, denali->flash_mem); |
867 | } else { | 792 | } else { |
868 | index_addr(denali, (uint32_t)cmd, | 793 | index_addr(denali, (uint32_t)cmd, |
869 | 0x2000 | op | page_count); | 794 | 0x2000 | op | page_count); |
@@ -875,13 +800,14 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, | |||
875 | irq_status = wait_for_irq(denali, irq_mask); | 800 | irq_status = wait_for_irq(denali, irq_mask); |
876 | 801 | ||
877 | if (irq_status == 0) { | 802 | if (irq_status == 0) { |
878 | printk(KERN_ERR "cmd, page, addr on timeout " | 803 | dev_err(&denali->dev->dev, |
879 | "(0x%x, 0x%x, 0x%x)\n", cmd, | 804 | "cmd, page, addr on timeout " |
880 | denali->page, addr); | 805 | "(0x%x, 0x%x, 0x%x)\n", |
806 | cmd, denali->page, addr); | ||
881 | status = FAIL; | 807 | status = FAIL; |
882 | } else { | 808 | } else { |
883 | cmd = MODE_01 | addr; | 809 | cmd = MODE_01 | addr; |
884 | denali_write32(cmd, denali->flash_mem); | 810 | iowrite32(cmd, denali->flash_mem); |
885 | } | 811 | } |
886 | } | 812 | } |
887 | } | 813 | } |
@@ -902,7 +828,7 @@ static int write_data_to_flash_mem(struct denali_nand_info *denali, | |||
902 | /* write the data to the flash memory */ | 828 | /* write the data to the flash memory */ |
903 | buf32 = (uint32_t *)buf; | 829 | buf32 = (uint32_t *)buf; |
904 | for (i = 0; i < len / 4; i++) | 830 | for (i = 0; i < len / 4; i++) |
905 | denali_write32(*buf32++, denali->flash_mem + 0x10); | 831 | iowrite32(*buf32++, denali->flash_mem + 0x10); |
906 | return i*4; /* intent is to return the number of bytes read */ | 832 | return i*4; /* intent is to return the number of bytes read */ |
907 | } | 833 | } |
908 | 834 | ||
@@ -945,24 +871,15 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
945 | DENALI_WRITE) == PASS) { | 871 | DENALI_WRITE) == PASS) { |
946 | write_data_to_flash_mem(denali, buf, mtd->oobsize); | 872 | write_data_to_flash_mem(denali, buf, mtd->oobsize); |
947 | 873 | ||
948 | #if DEBUG_DENALI | ||
949 | spin_lock_irq(&denali->irq_lock); | ||
950 | denali->irq_debug_array[denali->idx++] = | ||
951 | 0x80000000 | mtd->oobsize; | ||
952 | denali->idx %= 32; | ||
953 | spin_unlock_irq(&denali->irq_lock); | ||
954 | #endif | ||
955 | |||
956 | |||
957 | /* wait for operation to complete */ | 874 | /* wait for operation to complete */ |
958 | irq_status = wait_for_irq(denali, irq_mask); | 875 | irq_status = wait_for_irq(denali, irq_mask); |
959 | 876 | ||
960 | if (irq_status == 0) { | 877 | if (irq_status == 0) { |
961 | printk(KERN_ERR "OOB write failed\n"); | 878 | dev_err(&denali->dev->dev, "OOB write failed\n"); |
962 | status = -EIO; | 879 | status = -EIO; |
963 | } | 880 | } |
964 | } else { | 881 | } else { |
965 | printk(KERN_ERR "unable to send pipeline command\n"); | 882 | dev_err(&denali->dev->dev, "unable to send pipeline command\n"); |
966 | status = -EIO; | 883 | status = -EIO; |
967 | } | 884 | } |
968 | return status; | 885 | return status; |
@@ -977,9 +894,6 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
977 | 894 | ||
978 | denali->page = page; | 895 | denali->page = page; |
979 | 896 | ||
980 | #if DEBUG_DENALI | ||
981 | printk(KERN_INFO "read_oob %d\n", page); | ||
982 | #endif | ||
983 | if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS, | 897 | if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS, |
984 | DENALI_READ) == PASS) { | 898 | DENALI_READ) == PASS) { |
985 | read_data_from_flash_mem(denali, buf, mtd->oobsize); | 899 | read_data_from_flash_mem(denali, buf, mtd->oobsize); |
@@ -990,7 +904,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
990 | irq_status = wait_for_irq(denali, irq_mask); | 904 | irq_status = wait_for_irq(denali, irq_mask); |
991 | 905 | ||
992 | if (irq_status == 0) | 906 | if (irq_status == 0) |
993 | printk(KERN_ERR "page on OOB timeout %d\n", | 907 | dev_err(&denali->dev->dev, "page on OOB timeout %d\n", |
994 | denali->page); | 908 | denali->page); |
995 | 909 | ||
996 | /* We set the device back to MAIN_ACCESS here as I observed | 910 | /* We set the device back to MAIN_ACCESS here as I observed |
@@ -1002,14 +916,6 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
1002 | addr = BANK(denali->flash_bank) | denali->page; | 916 | addr = BANK(denali->flash_bank) | denali->page; |
1003 | cmd = MODE_10 | addr; | 917 | cmd = MODE_10 | addr; |
1004 | index_addr(denali, (uint32_t)cmd, MAIN_ACCESS); | 918 | index_addr(denali, (uint32_t)cmd, MAIN_ACCESS); |
1005 | |||
1006 | #if DEBUG_DENALI | ||
1007 | spin_lock_irq(&denali->irq_lock); | ||
1008 | denali->irq_debug_array[denali->idx++] = | ||
1009 | 0x60000000 | mtd->oobsize; | ||
1010 | denali->idx %= 32; | ||
1011 | spin_unlock_irq(&denali->irq_lock); | ||
1012 | #endif | ||
1013 | } | 919 | } |
1014 | } | 920 | } |
1015 | 921 | ||
@@ -1029,12 +935,12 @@ bool is_erased(uint8_t *buf, int len) | |||
1029 | #define ECC_SECTOR(x) (((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12) | 935 | #define ECC_SECTOR(x) (((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12) |
1030 | #define ECC_BYTE(x) (((x) & ECC_ERROR_ADDRESS__OFFSET)) | 936 | #define ECC_BYTE(x) (((x) & ECC_ERROR_ADDRESS__OFFSET)) |
1031 | #define ECC_CORRECTION_VALUE(x) ((x) & ERR_CORRECTION_INFO__BYTEMASK) | 937 | #define ECC_CORRECTION_VALUE(x) ((x) & ERR_CORRECTION_INFO__BYTEMASK) |
1032 | #define ECC_ERROR_CORRECTABLE(x) (!((x) & ERR_CORRECTION_INFO)) | 938 | #define ECC_ERROR_CORRECTABLE(x) (!((x) & ERR_CORRECTION_INFO__ERROR_TYPE)) |
1033 | #define ECC_ERR_DEVICE(x) ((x) & ERR_CORRECTION_INFO__DEVICE_NR >> 8) | 939 | #define ECC_ERR_DEVICE(x) (((x) & ERR_CORRECTION_INFO__DEVICE_NR) >> 8) |
1034 | #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) | 940 | #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) |
1035 | 941 | ||
1036 | static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | 942 | static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, |
1037 | uint8_t *oobbuf, uint32_t irq_status) | 943 | uint32_t irq_status) |
1038 | { | 944 | { |
1039 | bool check_erased_page = false; | 945 | bool check_erased_page = false; |
1040 | 946 | ||
@@ -1043,6 +949,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | |||
1043 | uint32_t err_address = 0, err_correction_info = 0; | 949 | uint32_t err_address = 0, err_correction_info = 0; |
1044 | uint32_t err_byte = 0, err_sector = 0, err_device = 0; | 950 | uint32_t err_byte = 0, err_sector = 0, err_device = 0; |
1045 | uint32_t err_correction_value = 0; | 951 | uint32_t err_correction_value = 0; |
952 | denali_set_intr_modes(denali, false); | ||
1046 | 953 | ||
1047 | do { | 954 | do { |
1048 | err_address = ioread32(denali->flash_reg + | 955 | err_address = ioread32(denali->flash_reg + |
@@ -1050,7 +957,6 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | |||
1050 | err_sector = ECC_SECTOR(err_address); | 957 | err_sector = ECC_SECTOR(err_address); |
1051 | err_byte = ECC_BYTE(err_address); | 958 | err_byte = ECC_BYTE(err_address); |
1052 | 959 | ||
1053 | |||
1054 | err_correction_info = ioread32(denali->flash_reg + | 960 | err_correction_info = ioread32(denali->flash_reg + |
1055 | ERR_CORRECTION_INFO); | 961 | ERR_CORRECTION_INFO); |
1056 | err_correction_value = | 962 | err_correction_value = |
@@ -1058,20 +964,23 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | |||
1058 | err_device = ECC_ERR_DEVICE(err_correction_info); | 964 | err_device = ECC_ERR_DEVICE(err_correction_info); |
1059 | 965 | ||
1060 | if (ECC_ERROR_CORRECTABLE(err_correction_info)) { | 966 | if (ECC_ERROR_CORRECTABLE(err_correction_info)) { |
1061 | /* offset in our buffer is computed as: | 967 | /* If err_byte is larger than ECC_SECTOR_SIZE, |
1062 | sector number * sector size + offset in | 968 | * means error happend in OOB, so we ignore |
1063 | sector | 969 | * it. It's no need for us to correct it |
1064 | */ | 970 | * err_device is represented the NAND error |
1065 | int offset = err_sector * ECC_SECTOR_SIZE + | 971 | * bits are happened in if there are more |
1066 | err_byte; | 972 | * than one NAND connected. |
1067 | if (offset < denali->mtd.writesize) { | 973 | * */ |
974 | if (err_byte < ECC_SECTOR_SIZE) { | ||
975 | int offset; | ||
976 | offset = (err_sector * | ||
977 | ECC_SECTOR_SIZE + | ||
978 | err_byte) * | ||
979 | denali->devnum + | ||
980 | err_device; | ||
1068 | /* correct the ECC error */ | 981 | /* correct the ECC error */ |
1069 | buf[offset] ^= err_correction_value; | 982 | buf[offset] ^= err_correction_value; |
1070 | denali->mtd.ecc_stats.corrected++; | 983 | denali->mtd.ecc_stats.corrected++; |
1071 | } else { | ||
1072 | /* bummer, couldn't correct the error */ | ||
1073 | printk(KERN_ERR "ECC offset invalid\n"); | ||
1074 | denali->mtd.ecc_stats.failed++; | ||
1075 | } | 984 | } |
1076 | } else { | 985 | } else { |
1077 | /* if the error is not correctable, need to | 986 | /* if the error is not correctable, need to |
@@ -1080,14 +989,16 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | |||
1080 | * */ | 989 | * */ |
1081 | check_erased_page = true; | 990 | check_erased_page = true; |
1082 | } | 991 | } |
1083 | |||
1084 | #if DEBUG_DENALI | ||
1085 | printk(KERN_INFO "Detected ECC error in page %d:" | ||
1086 | " err_addr = 0x%08x, info to fix is" | ||
1087 | " 0x%08x\n", denali->page, err_address, | ||
1088 | err_correction_info); | ||
1089 | #endif | ||
1090 | } while (!ECC_LAST_ERR(err_correction_info)); | 992 | } while (!ECC_LAST_ERR(err_correction_info)); |
993 | /* Once handle all ecc errors, controller will triger | ||
994 | * a ECC_TRANSACTION_DONE interrupt, so here just wait | ||
995 | * for a while for this interrupt | ||
996 | * */ | ||
997 | while (!(read_interrupt_status(denali) & | ||
998 | INTR_STATUS0__ECC_TRANSACTION_DONE)) | ||
999 | cpu_relax(); | ||
1000 | clear_interrupts(denali); | ||
1001 | denali_set_intr_modes(denali, true); | ||
1091 | } | 1002 | } |
1092 | return check_erased_page; | 1003 | return check_erased_page; |
1093 | } | 1004 | } |
@@ -1100,7 +1011,7 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en) | |||
1100 | if (en) | 1011 | if (en) |
1101 | reg_val = DMA_ENABLE__FLAG; | 1012 | reg_val = DMA_ENABLE__FLAG; |
1102 | 1013 | ||
1103 | denali_write32(reg_val, denali->flash_reg + DMA_ENABLE); | 1014 | iowrite32(reg_val, denali->flash_reg + DMA_ENABLE); |
1104 | ioread32(denali->flash_reg + DMA_ENABLE); | 1015 | ioread32(denali->flash_reg + DMA_ENABLE); |
1105 | } | 1016 | } |
1106 | 1017 | ||
@@ -1129,7 +1040,7 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op) | |||
1129 | } | 1040 | } |
1130 | 1041 | ||
1131 | /* writes a page. user specifies type, and this function handles the | 1042 | /* writes a page. user specifies type, and this function handles the |
1132 | configuration details. */ | 1043 | * configuration details. */ |
1133 | static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | 1044 | static void write_page(struct mtd_info *mtd, struct nand_chip *chip, |
1134 | const uint8_t *buf, bool raw_xfer) | 1045 | const uint8_t *buf, bool raw_xfer) |
1135 | { | 1046 | { |
@@ -1171,8 +1082,9 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1171 | irq_status = wait_for_irq(denali, irq_mask); | 1082 | irq_status = wait_for_irq(denali, irq_mask); |
1172 | 1083 | ||
1173 | if (irq_status == 0) { | 1084 | if (irq_status == 0) { |
1174 | printk(KERN_ERR "timeout on write_page" | 1085 | dev_err(&denali->dev->dev, |
1175 | " (type = %d)\n", raw_xfer); | 1086 | "timeout on write_page (type = %d)\n", |
1087 | raw_xfer); | ||
1176 | denali->status = | 1088 | denali->status = |
1177 | (irq_status & INTR_STATUS0__PROGRAM_FAIL) ? | 1089 | (irq_status & INTR_STATUS0__PROGRAM_FAIL) ? |
1178 | NAND_STATUS_FAIL : PASS; | 1090 | NAND_STATUS_FAIL : PASS; |
@@ -1185,8 +1097,9 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1185 | /* NAND core entry points */ | 1097 | /* NAND core entry points */ |
1186 | 1098 | ||
1187 | /* this is the callback that the NAND core calls to write a page. Since | 1099 | /* this is the callback that the NAND core calls to write a page. Since |
1188 | writing a page with ECC or without is similar, all the work is done | 1100 | * writing a page with ECC or without is similar, all the work is done |
1189 | by write_page above. */ | 1101 | * by write_page above. |
1102 | * */ | ||
1190 | static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 1103 | static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
1191 | const uint8_t *buf) | 1104 | const uint8_t *buf) |
1192 | { | 1105 | { |
@@ -1196,8 +1109,8 @@ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1196 | } | 1109 | } |
1197 | 1110 | ||
1198 | /* This is the callback that the NAND core calls to write a page without ECC. | 1111 | /* This is the callback that the NAND core calls to write a page without ECC. |
1199 | raw access is similiar to ECC page writes, so all the work is done in the | 1112 | * raw access is similiar to ECC page writes, so all the work is done in the |
1200 | write_page() function above. | 1113 | * write_page() function above. |
1201 | */ | 1114 | */ |
1202 | static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1115 | static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1203 | const uint8_t *buf) | 1116 | const uint8_t *buf) |
@@ -1236,6 +1149,13 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1236 | INTR_STATUS0__ECC_ERR; | 1149 | INTR_STATUS0__ECC_ERR; |
1237 | bool check_erased_page = false; | 1150 | bool check_erased_page = false; |
1238 | 1151 | ||
1152 | if (page != denali->page) { | ||
1153 | dev_err(&denali->dev->dev, "IN %s: page %d is not" | ||
1154 | " equal to denali->page %d, investigate!!", | ||
1155 | __func__, page, denali->page); | ||
1156 | BUG(); | ||
1157 | } | ||
1158 | |||
1239 | setup_ecc_for_xfer(denali, true, false); | 1159 | setup_ecc_for_xfer(denali, true, false); |
1240 | 1160 | ||
1241 | denali_enable_dma(denali, true); | 1161 | denali_enable_dma(denali, true); |
@@ -1251,7 +1171,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1251 | 1171 | ||
1252 | memcpy(buf, denali->buf.buf, mtd->writesize); | 1172 | memcpy(buf, denali->buf.buf, mtd->writesize); |
1253 | 1173 | ||
1254 | check_erased_page = handle_ecc(denali, buf, chip->oob_poi, irq_status); | 1174 | check_erased_page = handle_ecc(denali, buf, irq_status); |
1255 | denali_enable_dma(denali, false); | 1175 | denali_enable_dma(denali, false); |
1256 | 1176 | ||
1257 | if (check_erased_page) { | 1177 | if (check_erased_page) { |
@@ -1280,6 +1200,13 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1280 | uint32_t irq_status = 0; | 1200 | uint32_t irq_status = 0; |
1281 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP; | 1201 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP; |
1282 | 1202 | ||
1203 | if (page != denali->page) { | ||
1204 | dev_err(&denali->dev->dev, "IN %s: page %d is not" | ||
1205 | " equal to denali->page %d, investigate!!", | ||
1206 | __func__, page, denali->page); | ||
1207 | BUG(); | ||
1208 | } | ||
1209 | |||
1283 | setup_ecc_for_xfer(denali, false, true); | 1210 | setup_ecc_for_xfer(denali, false, true); |
1284 | denali_enable_dma(denali, true); | 1211 | denali_enable_dma(denali, true); |
1285 | 1212 | ||
@@ -1309,18 +1236,13 @@ static uint8_t denali_read_byte(struct mtd_info *mtd) | |||
1309 | if (denali->buf.head < denali->buf.tail) | 1236 | if (denali->buf.head < denali->buf.tail) |
1310 | result = denali->buf.buf[denali->buf.head++]; | 1237 | result = denali->buf.buf[denali->buf.head++]; |
1311 | 1238 | ||
1312 | #if DEBUG_DENALI | ||
1313 | printk(KERN_INFO "read byte -> 0x%02x\n", result); | ||
1314 | #endif | ||
1315 | return result; | 1239 | return result; |
1316 | } | 1240 | } |
1317 | 1241 | ||
1318 | static void denali_select_chip(struct mtd_info *mtd, int chip) | 1242 | static void denali_select_chip(struct mtd_info *mtd, int chip) |
1319 | { | 1243 | { |
1320 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1244 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1321 | #if DEBUG_DENALI | 1245 | |
1322 | printk(KERN_INFO "denali select chip %d\n", chip); | ||
1323 | #endif | ||
1324 | spin_lock_irq(&denali->irq_lock); | 1246 | spin_lock_irq(&denali->irq_lock); |
1325 | denali->flash_bank = chip; | 1247 | denali->flash_bank = chip; |
1326 | spin_unlock_irq(&denali->irq_lock); | 1248 | spin_unlock_irq(&denali->irq_lock); |
@@ -1332,9 +1254,6 @@ static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) | |||
1332 | int status = denali->status; | 1254 | int status = denali->status; |
1333 | denali->status = 0; | 1255 | denali->status = 0; |
1334 | 1256 | ||
1335 | #if DEBUG_DENALI | ||
1336 | printk(KERN_INFO "waitfunc %d\n", status); | ||
1337 | #endif | ||
1338 | return status; | 1257 | return status; |
1339 | } | 1258 | } |
1340 | 1259 | ||
@@ -1344,9 +1263,6 @@ static void denali_erase(struct mtd_info *mtd, int page) | |||
1344 | 1263 | ||
1345 | uint32_t cmd = 0x0, irq_status = 0; | 1264 | uint32_t cmd = 0x0, irq_status = 0; |
1346 | 1265 | ||
1347 | #if DEBUG_DENALI | ||
1348 | printk(KERN_INFO "erase page: %d\n", page); | ||
1349 | #endif | ||
1350 | /* clear interrupts */ | 1266 | /* clear interrupts */ |
1351 | clear_interrupts(denali); | 1267 | clear_interrupts(denali); |
1352 | 1268 | ||
@@ -1369,9 +1285,6 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
1369 | uint32_t addr, id; | 1285 | uint32_t addr, id; |
1370 | int i; | 1286 | int i; |
1371 | 1287 | ||
1372 | #if DEBUG_DENALI | ||
1373 | printk(KERN_INFO "cmdfunc: 0x%x %d %d\n", cmd, col, page); | ||
1374 | #endif | ||
1375 | switch (cmd) { | 1288 | switch (cmd) { |
1376 | case NAND_CMD_PAGEPROG: | 1289 | case NAND_CMD_PAGEPROG: |
1377 | break; | 1290 | break; |
@@ -1415,7 +1328,9 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
1415 | static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, | 1328 | static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, |
1416 | uint8_t *ecc_code) | 1329 | uint8_t *ecc_code) |
1417 | { | 1330 | { |
1418 | printk(KERN_ERR "denali_ecc_calculate called unexpectedly\n"); | 1331 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1332 | dev_err(&denali->dev->dev, | ||
1333 | "denali_ecc_calculate called unexpectedly\n"); | ||
1419 | BUG(); | 1334 | BUG(); |
1420 | return -EIO; | 1335 | return -EIO; |
1421 | } | 1336 | } |
@@ -1423,14 +1338,18 @@ static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, | |||
1423 | static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, | 1338 | static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, |
1424 | uint8_t *read_ecc, uint8_t *calc_ecc) | 1339 | uint8_t *read_ecc, uint8_t *calc_ecc) |
1425 | { | 1340 | { |
1426 | printk(KERN_ERR "denali_ecc_correct called unexpectedly\n"); | 1341 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1342 | dev_err(&denali->dev->dev, | ||
1343 | "denali_ecc_correct called unexpectedly\n"); | ||
1427 | BUG(); | 1344 | BUG(); |
1428 | return -EIO; | 1345 | return -EIO; |
1429 | } | 1346 | } |
1430 | 1347 | ||
1431 | static void denali_ecc_hwctl(struct mtd_info *mtd, int mode) | 1348 | static void denali_ecc_hwctl(struct mtd_info *mtd, int mode) |
1432 | { | 1349 | { |
1433 | printk(KERN_ERR "denali_ecc_hwctl called unexpectedly\n"); | 1350 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1351 | dev_err(&denali->dev->dev, | ||
1352 | "denali_ecc_hwctl called unexpectedly\n"); | ||
1434 | BUG(); | 1353 | BUG(); |
1435 | } | 1354 | } |
1436 | /* end NAND core entry points */ | 1355 | /* end NAND core entry points */ |
@@ -1445,18 +1364,18 @@ static void denali_hw_init(struct denali_nand_info *denali) | |||
1445 | * */ | 1364 | * */ |
1446 | denali->bbtskipbytes = ioread32(denali->flash_reg + | 1365 | denali->bbtskipbytes = ioread32(denali->flash_reg + |
1447 | SPARE_AREA_SKIP_BYTES); | 1366 | SPARE_AREA_SKIP_BYTES); |
1448 | denali_irq_init(denali); | ||
1449 | denali_nand_reset(denali); | 1367 | denali_nand_reset(denali); |
1450 | denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED); | 1368 | iowrite32(0x0F, denali->flash_reg + RB_PIN_ENABLED); |
1451 | denali_write32(CHIP_EN_DONT_CARE__FLAG, | 1369 | iowrite32(CHIP_EN_DONT_CARE__FLAG, |
1452 | denali->flash_reg + CHIP_ENABLE_DONT_CARE); | 1370 | denali->flash_reg + CHIP_ENABLE_DONT_CARE); |
1453 | 1371 | ||
1454 | denali_write32(0x0, denali->flash_reg + SPARE_AREA_SKIP_BYTES); | 1372 | iowrite32(0xffff, denali->flash_reg + SPARE_AREA_MARKER); |
1455 | denali_write32(0xffff, denali->flash_reg + SPARE_AREA_MARKER); | ||
1456 | 1373 | ||
1457 | /* Should set value for these registers when init */ | 1374 | /* Should set value for these registers when init */ |
1458 | denali_write32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES); | 1375 | iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES); |
1459 | denali_write32(1, denali->flash_reg + ECC_ENABLE); | 1376 | iowrite32(1, denali->flash_reg + ECC_ENABLE); |
1377 | denali_nand_timing_set(denali); | ||
1378 | denali_irq_init(denali); | ||
1460 | } | 1379 | } |
1461 | 1380 | ||
1462 | /* Althogh controller spec said SLC ECC is forceb to be 4bit, | 1381 | /* Althogh controller spec said SLC ECC is forceb to be 4bit, |
@@ -1526,9 +1445,6 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1526 | unsigned long csr_len, mem_len; | 1445 | unsigned long csr_len, mem_len; |
1527 | struct denali_nand_info *denali; | 1446 | struct denali_nand_info *denali; |
1528 | 1447 | ||
1529 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | ||
1530 | __FILE__, __LINE__, __func__); | ||
1531 | |||
1532 | denali = kzalloc(sizeof(*denali), GFP_KERNEL); | 1448 | denali = kzalloc(sizeof(*denali), GFP_KERNEL); |
1533 | if (!denali) | 1449 | if (!denali) |
1534 | return -ENOMEM; | 1450 | return -ENOMEM; |
@@ -1536,7 +1452,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1536 | ret = pci_enable_device(dev); | 1452 | ret = pci_enable_device(dev); |
1537 | if (ret) { | 1453 | if (ret) { |
1538 | printk(KERN_ERR "Spectra: pci_enable_device failed.\n"); | 1454 | printk(KERN_ERR "Spectra: pci_enable_device failed.\n"); |
1539 | goto failed_enable; | 1455 | goto failed_alloc_memery; |
1540 | } | 1456 | } |
1541 | 1457 | ||
1542 | if (id->driver_data == INTEL_CE4100) { | 1458 | if (id->driver_data == INTEL_CE4100) { |
@@ -1547,7 +1463,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1547 | printk(KERN_ERR "Intel CE4100 only supports" | 1463 | printk(KERN_ERR "Intel CE4100 only supports" |
1548 | " ONFI timing mode 1 or below\n"); | 1464 | " ONFI timing mode 1 or below\n"); |
1549 | ret = -EINVAL; | 1465 | ret = -EINVAL; |
1550 | goto failed_enable; | 1466 | goto failed_enable_dev; |
1551 | } | 1467 | } |
1552 | denali->platform = INTEL_CE4100; | 1468 | denali->platform = INTEL_CE4100; |
1553 | mem_base = pci_resource_start(dev, 0); | 1469 | mem_base = pci_resource_start(dev, 0); |
@@ -1557,17 +1473,12 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1557 | } else { | 1473 | } else { |
1558 | denali->platform = INTEL_MRST; | 1474 | denali->platform = INTEL_MRST; |
1559 | csr_base = pci_resource_start(dev, 0); | 1475 | csr_base = pci_resource_start(dev, 0); |
1560 | csr_len = pci_resource_start(dev, 0); | 1476 | csr_len = pci_resource_len(dev, 0); |
1561 | mem_base = pci_resource_start(dev, 1); | 1477 | mem_base = pci_resource_start(dev, 1); |
1562 | mem_len = pci_resource_len(dev, 1); | 1478 | mem_len = pci_resource_len(dev, 1); |
1563 | if (!mem_len) { | 1479 | if (!mem_len) { |
1564 | mem_base = csr_base + csr_len; | 1480 | mem_base = csr_base + csr_len; |
1565 | mem_len = csr_len; | 1481 | mem_len = csr_len; |
1566 | nand_dbg_print(NAND_DBG_WARN, | ||
1567 | "Spectra: No second" | ||
1568 | " BAR for PCI device;" | ||
1569 | " assuming %08Lx\n", | ||
1570 | (uint64_t)csr_base); | ||
1571 | } | 1482 | } |
1572 | } | 1483 | } |
1573 | 1484 | ||
@@ -1576,7 +1487,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1576 | 1487 | ||
1577 | if (ret) { | 1488 | if (ret) { |
1578 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); | 1489 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); |
1579 | goto failed_enable; | 1490 | goto failed_enable_dev; |
1580 | } | 1491 | } |
1581 | denali->buf.dma_buf = | 1492 | denali->buf.dma_buf = |
1582 | pci_map_single(dev, denali->buf.buf, | 1493 | pci_map_single(dev, denali->buf.buf, |
@@ -1584,50 +1495,44 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1584 | PCI_DMA_BIDIRECTIONAL); | 1495 | PCI_DMA_BIDIRECTIONAL); |
1585 | 1496 | ||
1586 | if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) { | 1497 | if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) { |
1587 | printk(KERN_ERR "Spectra: failed to map DMA buffer\n"); | 1498 | dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n"); |
1588 | goto failed_enable; | 1499 | goto failed_enable_dev; |
1589 | } | 1500 | } |
1590 | 1501 | ||
1591 | pci_set_master(dev); | 1502 | pci_set_master(dev); |
1592 | denali->dev = dev; | 1503 | denali->dev = dev; |
1504 | denali->mtd.dev.parent = &dev->dev; | ||
1593 | 1505 | ||
1594 | ret = pci_request_regions(dev, DENALI_NAND_NAME); | 1506 | ret = pci_request_regions(dev, DENALI_NAND_NAME); |
1595 | if (ret) { | 1507 | if (ret) { |
1596 | printk(KERN_ERR "Spectra: Unable to request memory regions\n"); | 1508 | printk(KERN_ERR "Spectra: Unable to request memory regions\n"); |
1597 | goto failed_req_csr; | 1509 | goto failed_dma_map; |
1598 | } | 1510 | } |
1599 | 1511 | ||
1600 | denali->flash_reg = ioremap_nocache(csr_base, csr_len); | 1512 | denali->flash_reg = ioremap_nocache(csr_base, csr_len); |
1601 | if (!denali->flash_reg) { | 1513 | if (!denali->flash_reg) { |
1602 | printk(KERN_ERR "Spectra: Unable to remap memory region\n"); | 1514 | printk(KERN_ERR "Spectra: Unable to remap memory region\n"); |
1603 | ret = -ENOMEM; | 1515 | ret = -ENOMEM; |
1604 | goto failed_remap_csr; | 1516 | goto failed_req_regions; |
1605 | } | 1517 | } |
1606 | nand_dbg_print(NAND_DBG_DEBUG, "Spectra: CSR 0x%08Lx -> 0x%p (0x%lx)\n", | ||
1607 | (uint64_t)csr_base, denali->flash_reg, csr_len); | ||
1608 | 1518 | ||
1609 | denali->flash_mem = ioremap_nocache(mem_base, mem_len); | 1519 | denali->flash_mem = ioremap_nocache(mem_base, mem_len); |
1610 | if (!denali->flash_mem) { | 1520 | if (!denali->flash_mem) { |
1611 | printk(KERN_ERR "Spectra: ioremap_nocache failed!"); | 1521 | printk(KERN_ERR "Spectra: ioremap_nocache failed!"); |
1612 | iounmap(denali->flash_reg); | ||
1613 | ret = -ENOMEM; | 1522 | ret = -ENOMEM; |
1614 | goto failed_remap_csr; | 1523 | goto failed_remap_reg; |
1615 | } | 1524 | } |
1616 | 1525 | ||
1617 | nand_dbg_print(NAND_DBG_WARN, | ||
1618 | "Spectra: Remapped flash base address: " | ||
1619 | "0x%p, len: %ld\n", | ||
1620 | denali->flash_mem, csr_len); | ||
1621 | |||
1622 | denali_hw_init(denali); | 1526 | denali_hw_init(denali); |
1623 | denali_drv_init(denali); | 1527 | denali_drv_init(denali); |
1624 | 1528 | ||
1625 | nand_dbg_print(NAND_DBG_DEBUG, "Spectra: IRQ %d\n", dev->irq); | 1529 | /* denali_isr register is done after all the hardware |
1530 | * initilization is finished*/ | ||
1626 | if (request_irq(dev->irq, denali_isr, IRQF_SHARED, | 1531 | if (request_irq(dev->irq, denali_isr, IRQF_SHARED, |
1627 | DENALI_NAND_NAME, denali)) { | 1532 | DENALI_NAND_NAME, denali)) { |
1628 | printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); | 1533 | printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); |
1629 | ret = -ENODEV; | 1534 | ret = -ENODEV; |
1630 | goto failed_request_irq; | 1535 | goto failed_remap_mem; |
1631 | } | 1536 | } |
1632 | 1537 | ||
1633 | /* now that our ISR is registered, we can enable interrupts */ | 1538 | /* now that our ISR is registered, we can enable interrupts */ |
@@ -1635,21 +1540,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1635 | 1540 | ||
1636 | pci_set_drvdata(dev, denali); | 1541 | pci_set_drvdata(dev, denali); |
1637 | 1542 | ||
1638 | denali_nand_timing_set(denali); | 1543 | denali->mtd.name = "denali-nand"; |
1639 | |||
1640 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" | ||
1641 | "acc_clks: %d, re_2_we: %d, we_2_re: %d," | ||
1642 | "addr_2_data: %d, rdwr_en_lo_cnt: %d, " | ||
1643 | "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", | ||
1644 | ioread32(denali->flash_reg + ACC_CLKS), | ||
1645 | ioread32(denali->flash_reg + RE_2_WE), | ||
1646 | ioread32(denali->flash_reg + WE_2_RE), | ||
1647 | ioread32(denali->flash_reg + ADDR_2_DATA), | ||
1648 | ioread32(denali->flash_reg + RDWR_EN_LO_CNT), | ||
1649 | ioread32(denali->flash_reg + RDWR_EN_HI_CNT), | ||
1650 | ioread32(denali->flash_reg + CS_SETUP_CNT)); | ||
1651 | |||
1652 | denali->mtd.name = "Denali NAND"; | ||
1653 | denali->mtd.owner = THIS_MODULE; | 1544 | denali->mtd.owner = THIS_MODULE; |
1654 | denali->mtd.priv = &denali->nand; | 1545 | denali->mtd.priv = &denali->nand; |
1655 | 1546 | ||
@@ -1664,7 +1555,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1664 | * with the nand subsystem */ | 1555 | * with the nand subsystem */ |
1665 | if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) { | 1556 | if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) { |
1666 | ret = -ENXIO; | 1557 | ret = -ENXIO; |
1667 | goto failed_nand; | 1558 | goto failed_req_irq; |
1668 | } | 1559 | } |
1669 | 1560 | ||
1670 | /* MTD supported page sizes vary by kernel. We validate our | 1561 | /* MTD supported page sizes vary by kernel. We validate our |
@@ -1674,7 +1565,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1674 | ret = -ENODEV; | 1565 | ret = -ENODEV; |
1675 | printk(KERN_ERR "Spectra: device size not supported by this " | 1566 | printk(KERN_ERR "Spectra: device size not supported by this " |
1676 | "version of MTD."); | 1567 | "version of MTD."); |
1677 | goto failed_nand; | 1568 | goto failed_req_irq; |
1678 | } | 1569 | } |
1679 | 1570 | ||
1680 | /* support for multi nand | 1571 | /* support for multi nand |
@@ -1719,17 +1610,17 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1719 | /* if MLC OOB size is large enough, use 15bit ECC*/ | 1610 | /* if MLC OOB size is large enough, use 15bit ECC*/ |
1720 | denali->nand.ecc.layout = &nand_15bit_oob; | 1611 | denali->nand.ecc.layout = &nand_15bit_oob; |
1721 | denali->nand.ecc.bytes = ECC_15BITS; | 1612 | denali->nand.ecc.bytes = ECC_15BITS; |
1722 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); | 1613 | iowrite32(15, denali->flash_reg + ECC_CORRECTION); |
1723 | } else if (denali->mtd.oobsize < (denali->bbtskipbytes + | 1614 | } else if (denali->mtd.oobsize < (denali->bbtskipbytes + |
1724 | ECC_8BITS * (denali->mtd.writesize / | 1615 | ECC_8BITS * (denali->mtd.writesize / |
1725 | ECC_SECTOR_SIZE))) { | 1616 | ECC_SECTOR_SIZE))) { |
1726 | printk(KERN_ERR "Your NAND chip OOB is not large enough to" | 1617 | printk(KERN_ERR "Your NAND chip OOB is not large enough to" |
1727 | " contain 8bit ECC correction codes"); | 1618 | " contain 8bit ECC correction codes"); |
1728 | goto failed_nand; | 1619 | goto failed_req_irq; |
1729 | } else { | 1620 | } else { |
1730 | denali->nand.ecc.layout = &nand_8bit_oob; | 1621 | denali->nand.ecc.layout = &nand_8bit_oob; |
1731 | denali->nand.ecc.bytes = ECC_8BITS; | 1622 | denali->nand.ecc.bytes = ECC_8BITS; |
1732 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | 1623 | iowrite32(8, denali->flash_reg + ECC_CORRECTION); |
1733 | } | 1624 | } |
1734 | 1625 | ||
1735 | denali->nand.ecc.bytes *= denali->devnum; | 1626 | denali->nand.ecc.bytes *= denali->devnum; |
@@ -1769,28 +1660,31 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1769 | 1660 | ||
1770 | if (nand_scan_tail(&denali->mtd)) { | 1661 | if (nand_scan_tail(&denali->mtd)) { |
1771 | ret = -ENXIO; | 1662 | ret = -ENXIO; |
1772 | goto failed_nand; | 1663 | goto failed_req_irq; |
1773 | } | 1664 | } |
1774 | 1665 | ||
1775 | ret = add_mtd_device(&denali->mtd); | 1666 | ret = add_mtd_device(&denali->mtd); |
1776 | if (ret) { | 1667 | if (ret) { |
1777 | printk(KERN_ERR "Spectra: Failed to register" | 1668 | dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n", |
1778 | " MTD device: %d\n", ret); | 1669 | ret); |
1779 | goto failed_nand; | 1670 | goto failed_req_irq; |
1780 | } | 1671 | } |
1781 | return 0; | 1672 | return 0; |
1782 | 1673 | ||
1783 | failed_nand: | 1674 | failed_req_irq: |
1784 | denali_irq_cleanup(dev->irq, denali); | 1675 | denali_irq_cleanup(dev->irq, denali); |
1785 | failed_request_irq: | 1676 | failed_remap_mem: |
1786 | iounmap(denali->flash_reg); | ||
1787 | iounmap(denali->flash_mem); | 1677 | iounmap(denali->flash_mem); |
1788 | failed_remap_csr: | 1678 | failed_remap_reg: |
1679 | iounmap(denali->flash_reg); | ||
1680 | failed_req_regions: | ||
1789 | pci_release_regions(dev); | 1681 | pci_release_regions(dev); |
1790 | failed_req_csr: | 1682 | failed_dma_map: |
1791 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | 1683 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, |
1792 | PCI_DMA_BIDIRECTIONAL); | 1684 | PCI_DMA_BIDIRECTIONAL); |
1793 | failed_enable: | 1685 | failed_enable_dev: |
1686 | pci_disable_device(dev); | ||
1687 | failed_alloc_memery: | ||
1794 | kfree(denali); | 1688 | kfree(denali); |
1795 | return ret; | 1689 | return ret; |
1796 | } | 1690 | } |
@@ -1800,9 +1694,6 @@ static void denali_pci_remove(struct pci_dev *dev) | |||
1800 | { | 1694 | { |
1801 | struct denali_nand_info *denali = pci_get_drvdata(dev); | 1695 | struct denali_nand_info *denali = pci_get_drvdata(dev); |
1802 | 1696 | ||
1803 | nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", | ||
1804 | __FILE__, __LINE__, __func__); | ||
1805 | |||
1806 | nand_release(&denali->mtd); | 1697 | nand_release(&denali->mtd); |
1807 | del_mtd_device(&denali->mtd); | 1698 | del_mtd_device(&denali->mtd); |
1808 | 1699 | ||
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index b680474e6333..3918bcb1561e 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h | |||
@@ -635,24 +635,6 @@ | |||
635 | #define CLK_X 5 | 635 | #define CLK_X 5 |
636 | #define CLK_MULTI 4 | 636 | #define CLK_MULTI 4 |
637 | 637 | ||
638 | /* ffsport.h */ | ||
639 | #define VERBOSE 1 | ||
640 | |||
641 | #define NAND_DBG_WARN 1 | ||
642 | #define NAND_DBG_DEBUG 2 | ||
643 | #define NAND_DBG_TRACE 3 | ||
644 | |||
645 | #ifdef VERBOSE | ||
646 | #define nand_dbg_print(level, args...) \ | ||
647 | do { \ | ||
648 | if (level <= nand_debug_level) \ | ||
649 | printk(KERN_ALERT args); \ | ||
650 | } while (0) | ||
651 | #else | ||
652 | #define nand_dbg_print(level, args...) | ||
653 | #endif | ||
654 | |||
655 | |||
656 | /* spectraswconfig.h */ | 638 | /* spectraswconfig.h */ |
657 | #define CMD_DMA 0 | 639 | #define CMD_DMA 0 |
658 | 640 | ||
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index a04b89105b65..c65f19074bc8 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -112,7 +112,7 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
112 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, | 112 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, |
113 | 113 | ||
114 | /* 32 Gigabit */ | 114 | /* 32 Gigabit */ |
115 | {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS16}, | 115 | {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS}, |
116 | 116 | ||
117 | /* | 117 | /* |
118 | * Renesas AND 1 Gigabit. Those chips do not support extended id and | 118 | * Renesas AND 1 Gigabit. Those chips do not support extended id and |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 90e143e5ad3e..317aff428e42 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -37,6 +37,11 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
37 | struct resource *res; | 37 | struct resource *res; |
38 | int err = 0; | 38 | int err = 0; |
39 | 39 | ||
40 | if (pdata->chip.nr_chips < 1) { | ||
41 | dev_err(&pdev->dev, "invalid number of chips specified\n"); | ||
42 | return -EINVAL; | ||
43 | } | ||
44 | |||
40 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 45 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
41 | if (!res) | 46 | if (!res) |
42 | return -ENXIO; | 47 | return -ENXIO; |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index b0de57947189..c3ceebb5be84 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -236,7 +236,7 @@ static inline u64 dma_pte_addr(struct dma_pte *pte) | |||
236 | return pte->val & VTD_PAGE_MASK; | 236 | return pte->val & VTD_PAGE_MASK; |
237 | #else | 237 | #else |
238 | /* Must have a full atomic 64-bit read */ | 238 | /* Must have a full atomic 64-bit read */ |
239 | return __cmpxchg64(pte, 0ULL, 0ULL) & VTD_PAGE_MASK; | 239 | return __cmpxchg64(&pte->val, 0ULL, 0ULL) & VTD_PAGE_MASK; |
240 | #endif | 240 | #endif |
241 | } | 241 | } |
242 | 242 | ||
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 1694a0e2845b..fd1d2867cdcc 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
@@ -21,6 +21,8 @@ static int ir_ioapic_num, ir_hpet_num; | |||
21 | int intr_remapping_enabled; | 21 | int intr_remapping_enabled; |
22 | 22 | ||
23 | static int disable_intremap; | 23 | static int disable_intremap; |
24 | static int disable_sourceid_checking; | ||
25 | |||
24 | static __init int setup_nointremap(char *str) | 26 | static __init int setup_nointremap(char *str) |
25 | { | 27 | { |
26 | disable_intremap = 1; | 28 | disable_intremap = 1; |
@@ -28,6 +30,22 @@ static __init int setup_nointremap(char *str) | |||
28 | } | 30 | } |
29 | early_param("nointremap", setup_nointremap); | 31 | early_param("nointremap", setup_nointremap); |
30 | 32 | ||
33 | static __init int setup_intremap(char *str) | ||
34 | { | ||
35 | if (!str) | ||
36 | return -EINVAL; | ||
37 | |||
38 | if (!strncmp(str, "on", 2)) | ||
39 | disable_intremap = 0; | ||
40 | else if (!strncmp(str, "off", 3)) | ||
41 | disable_intremap = 1; | ||
42 | else if (!strncmp(str, "nosid", 5)) | ||
43 | disable_sourceid_checking = 1; | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | early_param("intremap", setup_intremap); | ||
48 | |||
31 | struct irq_2_iommu { | 49 | struct irq_2_iommu { |
32 | struct intel_iommu *iommu; | 50 | struct intel_iommu *iommu; |
33 | u16 irte_index; | 51 | u16 irte_index; |
@@ -453,6 +471,8 @@ int free_irte(int irq) | |||
453 | static void set_irte_sid(struct irte *irte, unsigned int svt, | 471 | static void set_irte_sid(struct irte *irte, unsigned int svt, |
454 | unsigned int sq, unsigned int sid) | 472 | unsigned int sq, unsigned int sid) |
455 | { | 473 | { |
474 | if (disable_sourceid_checking) | ||
475 | svt = SVT_NO_VERIFY; | ||
456 | irte->svt = svt; | 476 | irte->svt = svt; |
457 | irte->sq = sq; | 477 | irte->sq = sq; |
458 | irte->sid = sid; | 478 | irte->sid = sid; |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 6466231f338b..bbf91aec64f5 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -370,6 +370,14 @@ config ISCSI_TCP | |||
370 | 370 | ||
371 | http://open-iscsi.org | 371 | http://open-iscsi.org |
372 | 372 | ||
373 | config ISCSI_BOOT_SYSFS | ||
374 | tristate "iSCSI Boot Sysfs Interface" | ||
375 | default n | ||
376 | help | ||
377 | This option enables support for exposing iSCSI boot information | ||
378 | via sysfs to userspace. If you wish to export this information, | ||
379 | say Y. Otherwise, say N. | ||
380 | |||
373 | source "drivers/scsi/cxgb3i/Kconfig" | 381 | source "drivers/scsi/cxgb3i/Kconfig" |
374 | source "drivers/scsi/bnx2i/Kconfig" | 382 | source "drivers/scsi/bnx2i/Kconfig" |
375 | source "drivers/scsi/be2iscsi/Kconfig" | 383 | source "drivers/scsi/be2iscsi/Kconfig" |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 2a3fca2eca6a..2703c6ec5e36 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -42,6 +42,7 @@ obj-$(CONFIG_FCOE) += fcoe/ | |||
42 | obj-$(CONFIG_FCOE_FNIC) += fnic/ | 42 | obj-$(CONFIG_FCOE_FNIC) += fnic/ |
43 | obj-$(CONFIG_ISCSI_TCP) += libiscsi.o libiscsi_tcp.o iscsi_tcp.o | 43 | obj-$(CONFIG_ISCSI_TCP) += libiscsi.o libiscsi_tcp.o iscsi_tcp.o |
44 | obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o | 44 | obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o |
45 | obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o | ||
45 | obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o | 46 | obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o |
46 | obj-$(CONFIG_SCSI_ZORRO7XX) += 53c700.o zorro7xx.o | 47 | obj-$(CONFIG_SCSI_ZORRO7XX) += 53c700.o zorro7xx.o |
47 | obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o | 48 | obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o |
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 95a895dd4f13..c8dc392edd57 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/delay.h> | 56 | #include <linux/delay.h> |
57 | #include <linux/dma-mapping.h> | 57 | #include <linux/dma-mapping.h> |
58 | #include <linux/timer.h> | 58 | #include <linux/timer.h> |
59 | #include <linux/slab.h> | ||
59 | #include <linux/pci.h> | 60 | #include <linux/pci.h> |
60 | #include <linux/aer.h> | 61 | #include <linux/aer.h> |
61 | #include <asm/dma.h> | 62 | #include <asm/dma.h> |
diff --git a/drivers/scsi/be2iscsi/Kconfig b/drivers/scsi/be2iscsi/Kconfig index 84c275fb9f6b..ceaca32e788d 100644 --- a/drivers/scsi/be2iscsi/Kconfig +++ b/drivers/scsi/be2iscsi/Kconfig | |||
@@ -2,6 +2,7 @@ config BE2ISCSI | |||
2 | tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2" | 2 | tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2" |
3 | depends on PCI && SCSI && NET | 3 | depends on PCI && SCSI && NET |
4 | select SCSI_ISCSI_ATTRS | 4 | select SCSI_ISCSI_ATTRS |
5 | select ISCSI_BOOT_SYSFS | ||
5 | 6 | ||
6 | help | 7 | help |
7 | This driver implements the iSCSI functionality for ServerEngines' | 8 | This driver implements the iSCSI functionality for ServerEngines' |
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 40641d0845f4..5218de4ab35a 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h | |||
@@ -162,6 +162,13 @@ struct be_mcc_mailbox { | |||
162 | #define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2 | 162 | #define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2 |
163 | #define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3 | 163 | #define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3 |
164 | #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7 | 164 | #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7 |
165 | #define OPCODE_COMMON_ISCSI_NTWK_SET_VLAN 14 | ||
166 | #define OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR 17 | ||
167 | #define OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR 21 | ||
168 | #define OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY 22 | ||
169 | #define OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY 23 | ||
170 | #define OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID 24 | ||
171 | #define OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO 25 | ||
165 | #define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61 | 172 | #define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61 |
166 | #define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64 | 173 | #define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64 |
167 | #define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65 | 174 | #define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65 |
@@ -237,11 +244,109 @@ struct be_cmd_resp_eq_create { | |||
237 | u16 rsvd0; /* sword */ | 244 | u16 rsvd0; /* sword */ |
238 | } __packed; | 245 | } __packed; |
239 | 246 | ||
247 | struct mgmt_chap_format { | ||
248 | u32 flags; | ||
249 | u8 intr_chap_name[256]; | ||
250 | u8 intr_secret[16]; | ||
251 | u8 target_chap_name[256]; | ||
252 | u8 target_secret[16]; | ||
253 | u16 intr_chap_name_length; | ||
254 | u16 intr_secret_length; | ||
255 | u16 target_chap_name_length; | ||
256 | u16 target_secret_length; | ||
257 | } __packed; | ||
258 | |||
259 | struct mgmt_auth_method_format { | ||
260 | u8 auth_method_type; | ||
261 | u8 padding[3]; | ||
262 | struct mgmt_chap_format chap; | ||
263 | } __packed; | ||
264 | |||
265 | struct mgmt_conn_login_options { | ||
266 | u8 flags; | ||
267 | u8 header_digest; | ||
268 | u8 data_digest; | ||
269 | u8 rsvd0; | ||
270 | u32 max_recv_datasegment_len_ini; | ||
271 | u32 max_recv_datasegment_len_tgt; | ||
272 | u32 tcp_mss; | ||
273 | u32 tcp_window_size; | ||
274 | struct mgmt_auth_method_format auth_data; | ||
275 | } __packed; | ||
276 | |||
277 | struct ip_address_format { | ||
278 | u16 size_of_structure; | ||
279 | u8 reserved; | ||
280 | u8 ip_type; | ||
281 | u8 ip_address[16]; | ||
282 | u32 rsvd0; | ||
283 | } __packed; | ||
284 | |||
285 | struct mgmt_conn_info { | ||
286 | u32 connection_handle; | ||
287 | u32 connection_status; | ||
288 | u16 src_port; | ||
289 | u16 dest_port; | ||
290 | u16 dest_port_redirected; | ||
291 | u16 cid; | ||
292 | u32 estimated_throughput; | ||
293 | struct ip_address_format src_ipaddr; | ||
294 | struct ip_address_format dest_ipaddr; | ||
295 | struct ip_address_format dest_ipaddr_redirected; | ||
296 | struct mgmt_conn_login_options negotiated_login_options; | ||
297 | } __packed; | ||
298 | |||
299 | struct mgmt_session_login_options { | ||
300 | u8 flags; | ||
301 | u8 error_recovery_level; | ||
302 | u16 rsvd0; | ||
303 | u32 first_burst_length; | ||
304 | u32 max_burst_length; | ||
305 | u16 max_connections; | ||
306 | u16 max_outstanding_r2t; | ||
307 | u16 default_time2wait; | ||
308 | u16 default_time2retain; | ||
309 | } __packed; | ||
310 | |||
311 | struct mgmt_session_info { | ||
312 | u32 session_handle; | ||
313 | u32 status; | ||
314 | u8 isid[6]; | ||
315 | u16 tsih; | ||
316 | u32 session_flags; | ||
317 | u16 conn_count; | ||
318 | u16 pad; | ||
319 | u8 target_name[224]; | ||
320 | u8 initiator_iscsiname[224]; | ||
321 | struct mgmt_session_login_options negotiated_login_options; | ||
322 | struct mgmt_conn_info conn_list[1]; | ||
323 | } __packed; | ||
324 | |||
325 | struct be_cmd_req_get_session { | ||
326 | struct be_cmd_req_hdr hdr; | ||
327 | u32 session_handle; | ||
328 | } __packed; | ||
329 | |||
330 | struct be_cmd_resp_get_session { | ||
331 | struct be_cmd_resp_hdr hdr; | ||
332 | struct mgmt_session_info session_info; | ||
333 | } __packed; | ||
334 | |||
240 | struct mac_addr { | 335 | struct mac_addr { |
241 | u16 size_of_struct; | 336 | u16 size_of_struct; |
242 | u8 addr[ETH_ALEN]; | 337 | u8 addr[ETH_ALEN]; |
243 | } __packed; | 338 | } __packed; |
244 | 339 | ||
340 | struct be_cmd_req_get_boot_target { | ||
341 | struct be_cmd_req_hdr hdr; | ||
342 | } __packed; | ||
343 | |||
344 | struct be_cmd_resp_get_boot_target { | ||
345 | struct be_cmd_resp_hdr hdr; | ||
346 | u32 boot_session_count; | ||
347 | int boot_session_handle; | ||
348 | }; | ||
349 | |||
245 | struct be_cmd_req_mac_query { | 350 | struct be_cmd_req_mac_query { |
246 | struct be_cmd_req_hdr hdr; | 351 | struct be_cmd_req_hdr hdr; |
247 | u8 type; | 352 | u8 type; |
@@ -426,6 +531,11 @@ int be_poll_mcc(struct be_ctrl_info *ctrl); | |||
426 | int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, | 531 | int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, |
427 | struct beiscsi_hba *phba); | 532 | struct beiscsi_hba *phba); |
428 | unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba); | 533 | unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba); |
534 | unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba); | ||
535 | unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba, | ||
536 | u32 boot_session_handle, | ||
537 | struct be_dma_mem *nonemb_cmd); | ||
538 | |||
429 | void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); | 539 | void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); |
430 | /*ISCSI Functuions */ | 540 | /*ISCSI Functuions */ |
431 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); | 541 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); |
@@ -601,14 +711,6 @@ struct be_eq_delay_params_in { | |||
601 | struct eq_delay delay[8]; | 711 | struct eq_delay delay[8]; |
602 | } __packed; | 712 | } __packed; |
603 | 713 | ||
604 | struct ip_address_format { | ||
605 | u16 size_of_structure; | ||
606 | u8 reserved; | ||
607 | u8 ip_type; | ||
608 | u8 ip_address[16]; | ||
609 | u32 rsvd0; | ||
610 | } __packed; | ||
611 | |||
612 | struct tcp_connect_and_offload_in { | 714 | struct tcp_connect_and_offload_in { |
613 | struct be_cmd_req_hdr hdr; | 715 | struct be_cmd_req_hdr hdr; |
614 | struct ip_address_format ip_address; | 716 | struct ip_address_format ip_address; |
@@ -688,18 +790,29 @@ struct be_fw_cfg { | |||
688 | u32 function_caps; | 790 | u32 function_caps; |
689 | } __packed; | 791 | } __packed; |
690 | 792 | ||
691 | #define CMD_ISCSI_COMMAND_INVALIDATE 1 | 793 | struct be_all_if_id { |
692 | #define ISCSI_OPCODE_SCSI_DATA_OUT 5 | 794 | struct be_cmd_req_hdr hdr; |
795 | u32 if_count; | ||
796 | u32 if_hndl_list[1]; | ||
797 | } __packed; | ||
798 | |||
799 | #define ISCSI_OPCODE_SCSI_DATA_OUT 5 | ||
800 | #define OPCODE_COMMON_MODIFY_EQ_DELAY 41 | ||
801 | #define OPCODE_COMMON_ISCSI_CLEANUP 59 | ||
802 | #define OPCODE_COMMON_TCP_UPLOAD 56 | ||
693 | #define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70 | 803 | #define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70 |
694 | #define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 | ||
695 | #define OPCODE_COMMON_MODIFY_EQ_DELAY 41 | ||
696 | #define OPCODE_COMMON_ISCSI_CLEANUP 59 | ||
697 | #define OPCODE_COMMON_TCP_UPLOAD 56 | ||
698 | #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1 | 804 | #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1 |
699 | /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ | 805 | #define OPCODE_ISCSI_INI_CFG_GET_HBA_NAME 6 |
700 | #define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 | 806 | #define OPCODE_ISCSI_INI_CFG_SET_HBA_NAME 7 |
701 | #define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 | 807 | #define OPCODE_ISCSI_INI_SESSION_GET_A_SESSION 14 |
808 | #define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 | ||
702 | #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 | 809 | #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 |
810 | #define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52 | ||
811 | |||
812 | /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ | ||
813 | #define CMD_ISCSI_COMMAND_INVALIDATE 1 | ||
814 | #define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 | ||
815 | #define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 | ||
703 | 816 | ||
704 | #define INI_WR_CMD 1 /* Initiator write command */ | 817 | #define INI_WR_CMD 1 /* Initiator write command */ |
705 | #define INI_TMF_CMD 2 /* Initiator TMF command */ | 818 | #define INI_TMF_CMD 2 /* Initiator TMF command */ |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 6d63e7b312cf..7d4d2275573c 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
@@ -300,40 +300,16 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
300 | enum iscsi_host_param param, char *buf) | 300 | enum iscsi_host_param param, char *buf) |
301 | { | 301 | { |
302 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); | 302 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); |
303 | struct be_cmd_resp_get_mac_addr *resp; | ||
304 | struct be_mcc_wrb *wrb; | ||
305 | unsigned int tag, wrb_num; | ||
306 | int len = 0; | 303 | int len = 0; |
307 | unsigned short status, extd_status; | 304 | int status; |
308 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
309 | 305 | ||
310 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); | 306 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); |
311 | switch (param) { | 307 | switch (param) { |
312 | case ISCSI_HOST_PARAM_HWADDRESS: | 308 | case ISCSI_HOST_PARAM_HWADDRESS: |
313 | tag = be_cmd_get_mac_addr(phba); | 309 | status = beiscsi_get_macaddr(buf, phba); |
314 | if (!tag) { | 310 | if (status < 0) { |
315 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); | 311 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); |
316 | return -EAGAIN; | 312 | return status; |
317 | } else | ||
318 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
319 | phba->ctrl.mcc_numtag[tag]); | ||
320 | |||
321 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
322 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
323 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
324 | if (status || extd_status) { | ||
325 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" | ||
326 | " status = %d extd_status = %d\n", | ||
327 | status, extd_status); | ||
328 | free_mcc_tag(&phba->ctrl, tag); | ||
329 | return -EAGAIN; | ||
330 | } else { | ||
331 | wrb = queue_get_wrb(mccq, wrb_num); | ||
332 | free_mcc_tag(&phba->ctrl, tag); | ||
333 | resp = embedded_payload(wrb); | ||
334 | memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); | ||
335 | len = sysfs_format_mac(buf, phba->mac_address, | ||
336 | ETH_ALEN); | ||
337 | } | 313 | } |
338 | break; | 314 | break; |
339 | default: | 315 | default: |
@@ -342,6 +318,48 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
342 | return len; | 318 | return len; |
343 | } | 319 | } |
344 | 320 | ||
321 | int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) | ||
322 | { | ||
323 | struct be_cmd_resp_get_mac_addr *resp; | ||
324 | struct be_mcc_wrb *wrb; | ||
325 | unsigned int tag, wrb_num; | ||
326 | unsigned short status, extd_status; | ||
327 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
328 | int rc; | ||
329 | |||
330 | if (phba->read_mac_address) | ||
331 | return sysfs_format_mac(buf, phba->mac_address, | ||
332 | ETH_ALEN); | ||
333 | |||
334 | tag = be_cmd_get_mac_addr(phba); | ||
335 | if (!tag) { | ||
336 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); | ||
337 | return -EBUSY; | ||
338 | } else | ||
339 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
340 | phba->ctrl.mcc_numtag[tag]); | ||
341 | |||
342 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
343 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
344 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
345 | if (status || extd_status) { | ||
346 | SE_DEBUG(DBG_LVL_1, "Failed to get be_cmd_get_mac_addr" | ||
347 | " status = %d extd_status = %d\n", | ||
348 | status, extd_status); | ||
349 | free_mcc_tag(&phba->ctrl, tag); | ||
350 | return -EAGAIN; | ||
351 | } | ||
352 | wrb = queue_get_wrb(mccq, wrb_num); | ||
353 | free_mcc_tag(&phba->ctrl, tag); | ||
354 | resp = embedded_payload(wrb); | ||
355 | memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); | ||
356 | rc = sysfs_format_mac(buf, phba->mac_address, | ||
357 | ETH_ALEN); | ||
358 | phba->read_mac_address = 1; | ||
359 | return rc; | ||
360 | } | ||
361 | |||
362 | |||
345 | /** | 363 | /** |
346 | * beiscsi_conn_get_stats - get the iscsi stats | 364 | * beiscsi_conn_get_stats - get the iscsi stats |
347 | * @cls_conn: pointer to iscsi cls conn | 365 | * @cls_conn: pointer to iscsi cls conn |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h index 870cdb2a73e4..8950a702b9f4 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.h +++ b/drivers/scsi/be2iscsi/be_iscsi.h | |||
@@ -54,6 +54,8 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
54 | int beiscsi_get_host_param(struct Scsi_Host *shost, | 54 | int beiscsi_get_host_param(struct Scsi_Host *shost, |
55 | enum iscsi_host_param param, char *buf); | 55 | enum iscsi_host_param param, char *buf); |
56 | 56 | ||
57 | int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba); | ||
58 | |||
57 | int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | 59 | int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, |
58 | enum iscsi_param param, char *buf, int buflen); | 60 | enum iscsi_param param, char *buf, int buflen); |
59 | 61 | ||
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 7436c5ad5697..8220bde6c04c 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/semaphore.h> | 28 | #include <linux/semaphore.h> |
29 | #include <linux/iscsi_boot_sysfs.h> | ||
29 | 30 | ||
30 | #include <scsi/libiscsi.h> | 31 | #include <scsi/libiscsi.h> |
31 | #include <scsi/scsi_transport_iscsi.h> | 32 | #include <scsi/scsi_transport_iscsi.h> |
@@ -211,6 +212,218 @@ unlock: | |||
211 | return rc; | 212 | return rc; |
212 | } | 213 | } |
213 | 214 | ||
215 | static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) | ||
216 | { | ||
217 | struct beiscsi_hba *phba = data; | ||
218 | char *str = buf; | ||
219 | int rc; | ||
220 | |||
221 | switch (type) { | ||
222 | case ISCSI_BOOT_TGT_NAME: | ||
223 | rc = sprintf(buf, "%.*s\n", | ||
224 | (int)strlen(phba->boot_sess.target_name), | ||
225 | (char *)&phba->boot_sess.target_name); | ||
226 | break; | ||
227 | case ISCSI_BOOT_TGT_IP_ADDR: | ||
228 | if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1) | ||
229 | rc = sprintf(buf, "%pI4\n", | ||
230 | (char *)&phba->boot_sess.conn_list[0]. | ||
231 | dest_ipaddr.ip_address); | ||
232 | else | ||
233 | rc = sprintf(str, "%pI6\n", | ||
234 | (char *)&phba->boot_sess.conn_list[0]. | ||
235 | dest_ipaddr.ip_address); | ||
236 | break; | ||
237 | case ISCSI_BOOT_TGT_PORT: | ||
238 | rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0]. | ||
239 | dest_port); | ||
240 | break; | ||
241 | |||
242 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
243 | rc = sprintf(str, "%.*s\n", | ||
244 | phba->boot_sess.conn_list[0]. | ||
245 | negotiated_login_options.auth_data.chap. | ||
246 | target_chap_name_length, | ||
247 | (char *)&phba->boot_sess.conn_list[0]. | ||
248 | negotiated_login_options.auth_data.chap. | ||
249 | target_chap_name); | ||
250 | break; | ||
251 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
252 | rc = sprintf(str, "%.*s\n", | ||
253 | phba->boot_sess.conn_list[0]. | ||
254 | negotiated_login_options.auth_data.chap. | ||
255 | target_secret_length, | ||
256 | (char *)&phba->boot_sess.conn_list[0]. | ||
257 | negotiated_login_options.auth_data.chap. | ||
258 | target_secret); | ||
259 | |||
260 | break; | ||
261 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
262 | rc = sprintf(str, "%.*s\n", | ||
263 | phba->boot_sess.conn_list[0]. | ||
264 | negotiated_login_options.auth_data.chap. | ||
265 | intr_chap_name_length, | ||
266 | (char *)&phba->boot_sess.conn_list[0]. | ||
267 | negotiated_login_options.auth_data.chap. | ||
268 | intr_chap_name); | ||
269 | |||
270 | break; | ||
271 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
272 | rc = sprintf(str, "%.*s\n", | ||
273 | phba->boot_sess.conn_list[0]. | ||
274 | negotiated_login_options.auth_data.chap. | ||
275 | intr_secret_length, | ||
276 | (char *)&phba->boot_sess.conn_list[0]. | ||
277 | negotiated_login_options.auth_data.chap. | ||
278 | intr_secret); | ||
279 | break; | ||
280 | case ISCSI_BOOT_TGT_FLAGS: | ||
281 | rc = sprintf(str, "2\n"); | ||
282 | break; | ||
283 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
284 | rc = sprintf(str, "0\n"); | ||
285 | break; | ||
286 | default: | ||
287 | rc = -ENOSYS; | ||
288 | break; | ||
289 | } | ||
290 | return rc; | ||
291 | } | ||
292 | |||
293 | static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf) | ||
294 | { | ||
295 | struct beiscsi_hba *phba = data; | ||
296 | char *str = buf; | ||
297 | int rc; | ||
298 | |||
299 | switch (type) { | ||
300 | case ISCSI_BOOT_INI_INITIATOR_NAME: | ||
301 | rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname); | ||
302 | break; | ||
303 | default: | ||
304 | rc = -ENOSYS; | ||
305 | break; | ||
306 | } | ||
307 | return rc; | ||
308 | } | ||
309 | |||
310 | static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf) | ||
311 | { | ||
312 | struct beiscsi_hba *phba = data; | ||
313 | char *str = buf; | ||
314 | int rc; | ||
315 | |||
316 | switch (type) { | ||
317 | case ISCSI_BOOT_ETH_FLAGS: | ||
318 | rc = sprintf(str, "2\n"); | ||
319 | break; | ||
320 | case ISCSI_BOOT_ETH_INDEX: | ||
321 | rc = sprintf(str, "0\n"); | ||
322 | break; | ||
323 | case ISCSI_BOOT_ETH_MAC: | ||
324 | rc = beiscsi_get_macaddr(buf, phba); | ||
325 | if (rc < 0) { | ||
326 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); | ||
327 | return rc; | ||
328 | } | ||
329 | break; | ||
330 | default: | ||
331 | rc = -ENOSYS; | ||
332 | break; | ||
333 | } | ||
334 | return rc; | ||
335 | } | ||
336 | |||
337 | |||
338 | static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type) | ||
339 | { | ||
340 | int rc; | ||
341 | |||
342 | switch (type) { | ||
343 | case ISCSI_BOOT_TGT_NAME: | ||
344 | case ISCSI_BOOT_TGT_IP_ADDR: | ||
345 | case ISCSI_BOOT_TGT_PORT: | ||
346 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
347 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
348 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
349 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
350 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
351 | case ISCSI_BOOT_TGT_FLAGS: | ||
352 | rc = S_IRUGO; | ||
353 | break; | ||
354 | default: | ||
355 | rc = 0; | ||
356 | break; | ||
357 | } | ||
358 | return rc; | ||
359 | } | ||
360 | |||
361 | static mode_t beiscsi_ini_get_attr_visibility(void *data, int type) | ||
362 | { | ||
363 | int rc; | ||
364 | |||
365 | switch (type) { | ||
366 | case ISCSI_BOOT_INI_INITIATOR_NAME: | ||
367 | rc = S_IRUGO; | ||
368 | break; | ||
369 | default: | ||
370 | rc = 0; | ||
371 | break; | ||
372 | } | ||
373 | return rc; | ||
374 | } | ||
375 | |||
376 | |||
377 | static mode_t beiscsi_eth_get_attr_visibility(void *data, int type) | ||
378 | { | ||
379 | int rc; | ||
380 | |||
381 | switch (type) { | ||
382 | case ISCSI_BOOT_ETH_FLAGS: | ||
383 | case ISCSI_BOOT_ETH_MAC: | ||
384 | case ISCSI_BOOT_ETH_INDEX: | ||
385 | rc = S_IRUGO; | ||
386 | break; | ||
387 | default: | ||
388 | rc = 0; | ||
389 | break; | ||
390 | } | ||
391 | return rc; | ||
392 | } | ||
393 | |||
394 | static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) | ||
395 | { | ||
396 | struct iscsi_boot_kobj *boot_kobj; | ||
397 | |||
398 | phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); | ||
399 | if (!phba->boot_kset) | ||
400 | return -ENOMEM; | ||
401 | |||
402 | /* get boot info using mgmt cmd */ | ||
403 | boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, | ||
404 | beiscsi_show_boot_tgt_info, | ||
405 | beiscsi_tgt_get_attr_visibility); | ||
406 | if (!boot_kobj) | ||
407 | goto free_kset; | ||
408 | |||
409 | boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, | ||
410 | beiscsi_show_boot_ini_info, | ||
411 | beiscsi_ini_get_attr_visibility); | ||
412 | if (!boot_kobj) | ||
413 | goto free_kset; | ||
414 | |||
415 | boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, | ||
416 | beiscsi_show_boot_eth_info, | ||
417 | beiscsi_eth_get_attr_visibility); | ||
418 | if (!boot_kobj) | ||
419 | goto free_kset; | ||
420 | return 0; | ||
421 | |||
422 | free_kset: | ||
423 | iscsi_boot_destroy_kset(phba->boot_kset); | ||
424 | return -ENOMEM; | ||
425 | } | ||
426 | |||
214 | /*------------------- PCI Driver operations and data ----------------- */ | 427 | /*------------------- PCI Driver operations and data ----------------- */ |
215 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { | 428 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { |
216 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | 429 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, |
@@ -268,6 +481,15 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) | |||
268 | 481 | ||
269 | if (iscsi_host_add(shost, &phba->pcidev->dev)) | 482 | if (iscsi_host_add(shost, &phba->pcidev->dev)) |
270 | goto free_devices; | 483 | goto free_devices; |
484 | |||
485 | if (beiscsi_setup_boot_info(phba)) | ||
486 | /* | ||
487 | * log error but continue, because we may not be using | ||
488 | * iscsi boot. | ||
489 | */ | ||
490 | shost_printk(KERN_ERR, phba->shost, "Could not set up " | ||
491 | "iSCSI boot info."); | ||
492 | |||
271 | return phba; | 493 | return phba; |
272 | 494 | ||
273 | free_devices: | 495 | free_devices: |
@@ -3279,6 +3501,89 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) | |||
3279 | "In hwi_disable_intr, Already Disabled\n"); | 3501 | "In hwi_disable_intr, Already Disabled\n"); |
3280 | } | 3502 | } |
3281 | 3503 | ||
3504 | static int beiscsi_get_boot_info(struct beiscsi_hba *phba) | ||
3505 | { | ||
3506 | struct be_cmd_resp_get_boot_target *boot_resp; | ||
3507 | struct be_cmd_resp_get_session *session_resp; | ||
3508 | struct be_mcc_wrb *wrb; | ||
3509 | struct be_dma_mem nonemb_cmd; | ||
3510 | unsigned int tag, wrb_num; | ||
3511 | unsigned short status, extd_status; | ||
3512 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
3513 | |||
3514 | tag = beiscsi_get_boot_target(phba); | ||
3515 | if (!tag) { | ||
3516 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); | ||
3517 | return -EAGAIN; | ||
3518 | } else | ||
3519 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
3520 | phba->ctrl.mcc_numtag[tag]); | ||
3521 | |||
3522 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
3523 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
3524 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
3525 | if (status || extd_status) { | ||
3526 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" | ||
3527 | " status = %d extd_status = %d\n", | ||
3528 | status, extd_status); | ||
3529 | free_mcc_tag(&phba->ctrl, tag); | ||
3530 | return -EBUSY; | ||
3531 | } | ||
3532 | wrb = queue_get_wrb(mccq, wrb_num); | ||
3533 | free_mcc_tag(&phba->ctrl, tag); | ||
3534 | boot_resp = embedded_payload(wrb); | ||
3535 | |||
3536 | if (boot_resp->boot_session_handle < 0) { | ||
3537 | printk(KERN_ERR "No Boot Session for this pci_func," | ||
3538 | "session Hndl = %d\n", boot_resp->boot_session_handle); | ||
3539 | return -ENXIO; | ||
3540 | } | ||
3541 | |||
3542 | nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | ||
3543 | sizeof(*session_resp), | ||
3544 | &nonemb_cmd.dma); | ||
3545 | if (nonemb_cmd.va == NULL) { | ||
3546 | SE_DEBUG(DBG_LVL_1, | ||
3547 | "Failed to allocate memory for" | ||
3548 | "beiscsi_get_session_info\n"); | ||
3549 | return -ENOMEM; | ||
3550 | } | ||
3551 | |||
3552 | memset(nonemb_cmd.va, 0, sizeof(*session_resp)); | ||
3553 | tag = beiscsi_get_session_info(phba, | ||
3554 | boot_resp->boot_session_handle, &nonemb_cmd); | ||
3555 | if (!tag) { | ||
3556 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info" | ||
3557 | " Failed\n"); | ||
3558 | goto boot_freemem; | ||
3559 | } else | ||
3560 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
3561 | phba->ctrl.mcc_numtag[tag]); | ||
3562 | |||
3563 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
3564 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
3565 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
3566 | if (status || extd_status) { | ||
3567 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info Failed" | ||
3568 | " status = %d extd_status = %d\n", | ||
3569 | status, extd_status); | ||
3570 | free_mcc_tag(&phba->ctrl, tag); | ||
3571 | goto boot_freemem; | ||
3572 | } | ||
3573 | wrb = queue_get_wrb(mccq, wrb_num); | ||
3574 | free_mcc_tag(&phba->ctrl, tag); | ||
3575 | session_resp = nonemb_cmd.va ; | ||
3576 | memcpy(&phba->boot_sess, &session_resp->session_info, | ||
3577 | sizeof(struct mgmt_session_info)); | ||
3578 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
3579 | nonemb_cmd.va, nonemb_cmd.dma); | ||
3580 | return 0; | ||
3581 | boot_freemem: | ||
3582 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
3583 | nonemb_cmd.va, nonemb_cmd.dma); | ||
3584 | return -ENOMEM; | ||
3585 | } | ||
3586 | |||
3282 | static int beiscsi_init_port(struct beiscsi_hba *phba) | 3587 | static int beiscsi_init_port(struct beiscsi_hba *phba) |
3283 | { | 3588 | { |
3284 | int ret; | 3589 | int ret; |
@@ -3841,6 +4146,7 @@ static void beiscsi_remove(struct pci_dev *pcidev) | |||
3841 | iscsi_host_remove(phba->shost); | 4146 | iscsi_host_remove(phba->shost); |
3842 | pci_dev_put(phba->pcidev); | 4147 | pci_dev_put(phba->pcidev); |
3843 | iscsi_host_free(phba->shost); | 4148 | iscsi_host_free(phba->shost); |
4149 | iscsi_boot_destroy_kset(phba->boot_kset); | ||
3844 | } | 4150 | } |
3845 | 4151 | ||
3846 | static void beiscsi_msix_enable(struct beiscsi_hba *phba) | 4152 | static void beiscsi_msix_enable(struct beiscsi_hba *phba) |
@@ -3996,6 +4302,11 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
3996 | goto free_blkenbld; | 4302 | goto free_blkenbld; |
3997 | } | 4303 | } |
3998 | hwi_enable_intr(phba); | 4304 | hwi_enable_intr(phba); |
4305 | ret = beiscsi_get_boot_info(phba); | ||
4306 | if (ret < 0) { | ||
4307 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | ||
4308 | "No Boot Devices !!!!!\n"); | ||
4309 | } | ||
3999 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); | 4310 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); |
4000 | return 0; | 4311 | return 0; |
4001 | 4312 | ||
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index c643bb3736fc..90eb74f6bcab 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | #include "be.h" | 36 | #include "be.h" |
37 | #define DRV_NAME "be2iscsi" | 37 | #define DRV_NAME "be2iscsi" |
38 | #define BUILD_STR "2.0.527.0" | 38 | #define BUILD_STR "2.0.549.0" |
39 | #define BE_NAME "ServerEngines BladeEngine2" \ | 39 | #define BE_NAME "ServerEngines BladeEngine2" \ |
40 | "Linux iSCSI Driver version" BUILD_STR | 40 | "Linux iSCSI Driver version" BUILD_STR |
41 | #define DRV_DESC BE_NAME " " "Driver" | 41 | #define DRV_DESC BE_NAME " " "Driver" |
@@ -63,7 +63,7 @@ | |||
63 | #define BEISCSI_SGLIST_ELEMENTS 30 | 63 | #define BEISCSI_SGLIST_ELEMENTS 30 |
64 | 64 | ||
65 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ | 65 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ |
66 | #define BEISCSI_MAX_SECTORS 256 /* scsi_host->max_sectors */ | 66 | #define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ |
67 | 67 | ||
68 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ | 68 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ |
69 | #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ | 69 | #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ |
@@ -312,6 +312,7 @@ struct beiscsi_hba { | |||
312 | struct list_head hba_queue; | 312 | struct list_head hba_queue; |
313 | unsigned short *cid_array; | 313 | unsigned short *cid_array; |
314 | struct iscsi_endpoint **ep_array; | 314 | struct iscsi_endpoint **ep_array; |
315 | struct iscsi_boot_kset *boot_kset; | ||
315 | struct Scsi_Host *shost; | 316 | struct Scsi_Host *shost; |
316 | struct { | 317 | struct { |
317 | /** | 318 | /** |
@@ -342,6 +343,8 @@ struct beiscsi_hba { | |||
342 | struct work_struct work_cqs; /* The work being queued */ | 343 | struct work_struct work_cqs; /* The work being queued */ |
343 | struct be_ctrl_info ctrl; | 344 | struct be_ctrl_info ctrl; |
344 | unsigned int generation; | 345 | unsigned int generation; |
346 | unsigned int read_mac_address; | ||
347 | struct mgmt_session_info boot_sess; | ||
345 | struct invalidate_command_table inv_tbl[128]; | 348 | struct invalidate_command_table inv_tbl[128]; |
346 | 349 | ||
347 | }; | 350 | }; |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 3f3fab91a7d1..26350e470bcc 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -20,6 +20,77 @@ | |||
20 | 20 | ||
21 | #include "be_mgmt.h" | 21 | #include "be_mgmt.h" |
22 | #include "be_iscsi.h" | 22 | #include "be_iscsi.h" |
23 | #include <scsi/scsi_transport_iscsi.h> | ||
24 | |||
25 | unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba) | ||
26 | { | ||
27 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
28 | struct be_mcc_wrb *wrb; | ||
29 | struct be_cmd_req_get_mac_addr *req; | ||
30 | unsigned int tag = 0; | ||
31 | |||
32 | SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n"); | ||
33 | spin_lock(&ctrl->mbox_lock); | ||
34 | tag = alloc_mcc_tag(phba); | ||
35 | if (!tag) { | ||
36 | spin_unlock(&ctrl->mbox_lock); | ||
37 | return tag; | ||
38 | } | ||
39 | |||
40 | wrb = wrb_from_mccq(phba); | ||
41 | req = embedded_payload(wrb); | ||
42 | wrb->tag0 |= tag; | ||
43 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
44 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
45 | OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, | ||
46 | sizeof(*req)); | ||
47 | |||
48 | be_mcc_notify(phba); | ||
49 | spin_unlock(&ctrl->mbox_lock); | ||
50 | return tag; | ||
51 | } | ||
52 | |||
53 | unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba, | ||
54 | u32 boot_session_handle, | ||
55 | struct be_dma_mem *nonemb_cmd) | ||
56 | { | ||
57 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
58 | struct be_mcc_wrb *wrb; | ||
59 | unsigned int tag = 0; | ||
60 | struct be_cmd_req_get_session *req; | ||
61 | struct be_cmd_resp_get_session *resp; | ||
62 | struct be_sge *sge; | ||
63 | |||
64 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_session_info\n"); | ||
65 | spin_lock(&ctrl->mbox_lock); | ||
66 | tag = alloc_mcc_tag(phba); | ||
67 | if (!tag) { | ||
68 | spin_unlock(&ctrl->mbox_lock); | ||
69 | return tag; | ||
70 | } | ||
71 | |||
72 | nonemb_cmd->size = sizeof(*resp); | ||
73 | req = nonemb_cmd->va; | ||
74 | memset(req, 0, sizeof(*req)); | ||
75 | wrb = wrb_from_mccq(phba); | ||
76 | sge = nonembedded_sgl(wrb); | ||
77 | wrb->tag0 |= tag; | ||
78 | |||
79 | |||
80 | wrb->tag0 |= tag; | ||
81 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | ||
82 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
83 | OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, | ||
84 | sizeof(*resp)); | ||
85 | req->session_handle = boot_session_handle; | ||
86 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | ||
87 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | ||
88 | sge->len = cpu_to_le32(nonemb_cmd->size); | ||
89 | |||
90 | be_mcc_notify(phba); | ||
91 | spin_unlock(&ctrl->mbox_lock); | ||
92 | return tag; | ||
93 | } | ||
23 | 94 | ||
24 | int mgmt_get_fw_config(struct be_ctrl_info *ctrl, | 95 | int mgmt_get_fw_config(struct be_ctrl_info *ctrl, |
25 | struct beiscsi_hba *phba) | 96 | struct beiscsi_hba *phba) |
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index bd96cecaa619..9f75a6d519a2 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
@@ -433,6 +433,9 @@ static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, | |||
433 | { | 433 | { |
434 | switch (tgt->action) { | 434 | switch (tgt->action) { |
435 | case IBMVFC_TGT_ACTION_DEL_RPORT: | 435 | case IBMVFC_TGT_ACTION_DEL_RPORT: |
436 | if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) | ||
437 | tgt->action = action; | ||
438 | case IBMVFC_TGT_ACTION_DELETED_RPORT: | ||
436 | break; | 439 | break; |
437 | default: | 440 | default: |
438 | if (action == IBMVFC_TGT_ACTION_DEL_RPORT) | 441 | if (action == IBMVFC_TGT_ACTION_DEL_RPORT) |
@@ -2036,95 +2039,108 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) | |||
2036 | } | 2039 | } |
2037 | 2040 | ||
2038 | /** | 2041 | /** |
2039 | * ibmvfc_abort_task_set - Abort outstanding commands to the device | 2042 | * ibmvfc_match_rport - Match function for specified remote port |
2040 | * @sdev: scsi device to abort commands | 2043 | * @evt: ibmvfc event struct |
2041 | * | 2044 | * @device: device to match (rport) |
2042 | * This sends an Abort Task Set to the VIOS for the specified device. This does | ||
2043 | * NOT send any cancel to the VIOS. That must be done separately. | ||
2044 | * | 2045 | * |
2045 | * Returns: | 2046 | * Returns: |
2046 | * 0 on success / other on failure | 2047 | * 1 if event matches rport / 0 if event does not match rport |
2047 | **/ | 2048 | **/ |
2048 | static int ibmvfc_abort_task_set(struct scsi_device *sdev) | 2049 | static int ibmvfc_match_rport(struct ibmvfc_event *evt, void *rport) |
2049 | { | 2050 | { |
2050 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2051 | struct fc_rport *cmd_rport; |
2051 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); | ||
2052 | struct ibmvfc_cmd *tmf; | ||
2053 | struct ibmvfc_event *evt, *found_evt; | ||
2054 | union ibmvfc_iu rsp_iu; | ||
2055 | struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; | ||
2056 | int rsp_rc = -EBUSY; | ||
2057 | unsigned long flags; | ||
2058 | int rsp_code = 0; | ||
2059 | 2052 | ||
2060 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2053 | if (evt->cmnd) { |
2061 | found_evt = NULL; | 2054 | cmd_rport = starget_to_rport(scsi_target(evt->cmnd->device)); |
2062 | list_for_each_entry(evt, &vhost->sent, queue) { | 2055 | if (cmd_rport == rport) |
2063 | if (evt->cmnd && evt->cmnd->device == sdev) { | 2056 | return 1; |
2064 | found_evt = evt; | ||
2065 | break; | ||
2066 | } | ||
2067 | } | ||
2068 | |||
2069 | if (!found_evt) { | ||
2070 | if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) | ||
2071 | sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); | ||
2072 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2073 | return 0; | ||
2074 | } | ||
2075 | |||
2076 | if (vhost->state == IBMVFC_ACTIVE) { | ||
2077 | evt = ibmvfc_get_event(vhost); | ||
2078 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); | ||
2079 | |||
2080 | tmf = &evt->iu.cmd; | ||
2081 | memset(tmf, 0, sizeof(*tmf)); | ||
2082 | tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); | ||
2083 | tmf->resp.len = sizeof(tmf->rsp); | ||
2084 | tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; | ||
2085 | tmf->payload_len = sizeof(tmf->iu); | ||
2086 | tmf->resp_len = sizeof(tmf->rsp); | ||
2087 | tmf->cancel_key = (unsigned long)sdev->hostdata; | ||
2088 | tmf->tgt_scsi_id = rport->port_id; | ||
2089 | int_to_scsilun(sdev->lun, &tmf->iu.lun); | ||
2090 | tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); | ||
2091 | tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; | ||
2092 | evt->sync_iu = &rsp_iu; | ||
2093 | |||
2094 | init_completion(&evt->comp); | ||
2095 | rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); | ||
2096 | } | 2057 | } |
2058 | return 0; | ||
2059 | } | ||
2097 | 2060 | ||
2098 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2061 | /** |
2062 | * ibmvfc_match_target - Match function for specified target | ||
2063 | * @evt: ibmvfc event struct | ||
2064 | * @device: device to match (starget) | ||
2065 | * | ||
2066 | * Returns: | ||
2067 | * 1 if event matches starget / 0 if event does not match starget | ||
2068 | **/ | ||
2069 | static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) | ||
2070 | { | ||
2071 | if (evt->cmnd && scsi_target(evt->cmnd->device) == device) | ||
2072 | return 1; | ||
2073 | return 0; | ||
2074 | } | ||
2099 | 2075 | ||
2100 | if (rsp_rc != 0) { | 2076 | /** |
2101 | sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); | 2077 | * ibmvfc_match_lun - Match function for specified LUN |
2102 | return -EIO; | 2078 | * @evt: ibmvfc event struct |
2103 | } | 2079 | * @device: device to match (sdev) |
2080 | * | ||
2081 | * Returns: | ||
2082 | * 1 if event matches sdev / 0 if event does not match sdev | ||
2083 | **/ | ||
2084 | static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) | ||
2085 | { | ||
2086 | if (evt->cmnd && evt->cmnd->device == device) | ||
2087 | return 1; | ||
2088 | return 0; | ||
2089 | } | ||
2104 | 2090 | ||
2105 | sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); | 2091 | /** |
2106 | wait_for_completion(&evt->comp); | 2092 | * ibmvfc_wait_for_ops - Wait for ops to complete |
2093 | * @vhost: ibmvfc host struct | ||
2094 | * @device: device to match (starget or sdev) | ||
2095 | * @match: match function | ||
2096 | * | ||
2097 | * Returns: | ||
2098 | * SUCCESS / FAILED | ||
2099 | **/ | ||
2100 | static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, | ||
2101 | int (*match) (struct ibmvfc_event *, void *)) | ||
2102 | { | ||
2103 | struct ibmvfc_event *evt; | ||
2104 | DECLARE_COMPLETION_ONSTACK(comp); | ||
2105 | int wait; | ||
2106 | unsigned long flags; | ||
2107 | signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; | ||
2107 | 2108 | ||
2108 | if (rsp_iu.cmd.status) | 2109 | ENTER; |
2109 | rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); | 2110 | do { |
2111 | wait = 0; | ||
2112 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
2113 | list_for_each_entry(evt, &vhost->sent, queue) { | ||
2114 | if (match(evt, device)) { | ||
2115 | evt->eh_comp = ∁ | ||
2116 | wait++; | ||
2117 | } | ||
2118 | } | ||
2119 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2110 | 2120 | ||
2111 | if (rsp_code) { | 2121 | if (wait) { |
2112 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) | 2122 | timeout = wait_for_completion_timeout(&comp, timeout); |
2113 | rsp_code = fc_rsp->data.info.rsp_code; | ||
2114 | 2123 | ||
2115 | sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " | 2124 | if (!timeout) { |
2116 | "flags: %x fcp_rsp: %x, scsi_status: %x\n", | 2125 | wait = 0; |
2117 | ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), | 2126 | spin_lock_irqsave(vhost->host->host_lock, flags); |
2118 | rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, | 2127 | list_for_each_entry(evt, &vhost->sent, queue) { |
2119 | fc_rsp->scsi_status); | 2128 | if (match(evt, device)) { |
2120 | rsp_rc = -EIO; | 2129 | evt->eh_comp = NULL; |
2121 | } else | 2130 | wait++; |
2122 | sdev_printk(KERN_INFO, sdev, "Abort successful\n"); | 2131 | } |
2132 | } | ||
2133 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2134 | if (wait) | ||
2135 | dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); | ||
2136 | LEAVE; | ||
2137 | return wait ? FAILED : SUCCESS; | ||
2138 | } | ||
2139 | } | ||
2140 | } while (wait); | ||
2123 | 2141 | ||
2124 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2142 | LEAVE; |
2125 | ibmvfc_free_event(evt); | 2143 | return SUCCESS; |
2126 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2127 | return rsp_rc; | ||
2128 | } | 2144 | } |
2129 | 2145 | ||
2130 | /** | 2146 | /** |
@@ -2212,88 +2228,130 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) | |||
2212 | } | 2228 | } |
2213 | 2229 | ||
2214 | /** | 2230 | /** |
2215 | * ibmvfc_match_target - Match function for specified target | 2231 | * ibmvfc_match_key - Match function for specified cancel key |
2216 | * @evt: ibmvfc event struct | 2232 | * @evt: ibmvfc event struct |
2217 | * @device: device to match (starget) | 2233 | * @key: cancel key to match |
2218 | * | 2234 | * |
2219 | * Returns: | 2235 | * Returns: |
2220 | * 1 if event matches starget / 0 if event does not match starget | 2236 | * 1 if event matches key / 0 if event does not match key |
2221 | **/ | 2237 | **/ |
2222 | static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) | 2238 | static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) |
2223 | { | 2239 | { |
2224 | if (evt->cmnd && scsi_target(evt->cmnd->device) == device) | 2240 | unsigned long cancel_key = (unsigned long)key; |
2225 | return 1; | ||
2226 | return 0; | ||
2227 | } | ||
2228 | 2241 | ||
2229 | /** | 2242 | if (evt->crq.format == IBMVFC_CMD_FORMAT && |
2230 | * ibmvfc_match_lun - Match function for specified LUN | 2243 | evt->iu.cmd.cancel_key == cancel_key) |
2231 | * @evt: ibmvfc event struct | ||
2232 | * @device: device to match (sdev) | ||
2233 | * | ||
2234 | * Returns: | ||
2235 | * 1 if event matches sdev / 0 if event does not match sdev | ||
2236 | **/ | ||
2237 | static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) | ||
2238 | { | ||
2239 | if (evt->cmnd && evt->cmnd->device == device) | ||
2240 | return 1; | 2244 | return 1; |
2241 | return 0; | 2245 | return 0; |
2242 | } | 2246 | } |
2243 | 2247 | ||
2244 | /** | 2248 | /** |
2245 | * ibmvfc_wait_for_ops - Wait for ops to complete | 2249 | * ibmvfc_abort_task_set - Abort outstanding commands to the device |
2246 | * @vhost: ibmvfc host struct | 2250 | * @sdev: scsi device to abort commands |
2247 | * @device: device to match (starget or sdev) | 2251 | * |
2248 | * @match: match function | 2252 | * This sends an Abort Task Set to the VIOS for the specified device. This does |
2253 | * NOT send any cancel to the VIOS. That must be done separately. | ||
2249 | * | 2254 | * |
2250 | * Returns: | 2255 | * Returns: |
2251 | * SUCCESS / FAILED | 2256 | * 0 on success / other on failure |
2252 | **/ | 2257 | **/ |
2253 | static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, | 2258 | static int ibmvfc_abort_task_set(struct scsi_device *sdev) |
2254 | int (*match) (struct ibmvfc_event *, void *)) | ||
2255 | { | 2259 | { |
2256 | struct ibmvfc_event *evt; | 2260 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
2257 | DECLARE_COMPLETION_ONSTACK(comp); | 2261 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); |
2258 | int wait; | 2262 | struct ibmvfc_cmd *tmf; |
2259 | unsigned long flags; | 2263 | struct ibmvfc_event *evt, *found_evt; |
2260 | signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; | 2264 | union ibmvfc_iu rsp_iu; |
2265 | struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; | ||
2266 | int rc, rsp_rc = -EBUSY; | ||
2267 | unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT; | ||
2268 | int rsp_code = 0; | ||
2261 | 2269 | ||
2262 | ENTER; | 2270 | spin_lock_irqsave(vhost->host->host_lock, flags); |
2263 | do { | 2271 | found_evt = NULL; |
2264 | wait = 0; | 2272 | list_for_each_entry(evt, &vhost->sent, queue) { |
2265 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2273 | if (evt->cmnd && evt->cmnd->device == sdev) { |
2266 | list_for_each_entry(evt, &vhost->sent, queue) { | 2274 | found_evt = evt; |
2267 | if (match(evt, device)) { | 2275 | break; |
2268 | evt->eh_comp = ∁ | ||
2269 | wait++; | ||
2270 | } | ||
2271 | } | 2276 | } |
2277 | } | ||
2278 | |||
2279 | if (!found_evt) { | ||
2280 | if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) | ||
2281 | sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); | ||
2272 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2282 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
2283 | return 0; | ||
2284 | } | ||
2273 | 2285 | ||
2274 | if (wait) { | 2286 | if (vhost->state == IBMVFC_ACTIVE) { |
2275 | timeout = wait_for_completion_timeout(&comp, timeout); | 2287 | evt = ibmvfc_get_event(vhost); |
2288 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); | ||
2276 | 2289 | ||
2277 | if (!timeout) { | 2290 | tmf = &evt->iu.cmd; |
2278 | wait = 0; | 2291 | memset(tmf, 0, sizeof(*tmf)); |
2279 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2292 | tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); |
2280 | list_for_each_entry(evt, &vhost->sent, queue) { | 2293 | tmf->resp.len = sizeof(tmf->rsp); |
2281 | if (match(evt, device)) { | 2294 | tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; |
2282 | evt->eh_comp = NULL; | 2295 | tmf->payload_len = sizeof(tmf->iu); |
2283 | wait++; | 2296 | tmf->resp_len = sizeof(tmf->rsp); |
2284 | } | 2297 | tmf->cancel_key = (unsigned long)sdev->hostdata; |
2285 | } | 2298 | tmf->tgt_scsi_id = rport->port_id; |
2286 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2299 | int_to_scsilun(sdev->lun, &tmf->iu.lun); |
2287 | if (wait) | 2300 | tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); |
2288 | dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); | 2301 | tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; |
2289 | LEAVE; | 2302 | evt->sync_iu = &rsp_iu; |
2290 | return wait ? FAILED : SUCCESS; | 2303 | |
2291 | } | 2304 | init_completion(&evt->comp); |
2305 | rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); | ||
2306 | } | ||
2307 | |||
2308 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2309 | |||
2310 | if (rsp_rc != 0) { | ||
2311 | sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); | ||
2312 | return -EIO; | ||
2313 | } | ||
2314 | |||
2315 | sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); | ||
2316 | timeout = wait_for_completion_timeout(&evt->comp, timeout); | ||
2317 | |||
2318 | if (!timeout) { | ||
2319 | rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
2320 | if (!rc) { | ||
2321 | rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); | ||
2322 | if (rc == SUCCESS) | ||
2323 | rc = 0; | ||
2292 | } | 2324 | } |
2293 | } while (wait); | ||
2294 | 2325 | ||
2295 | LEAVE; | 2326 | if (rc) { |
2296 | return SUCCESS; | 2327 | sdev_printk(KERN_INFO, sdev, "Cancel failed, resetting host\n"); |
2328 | ibmvfc_reset_host(vhost); | ||
2329 | rsp_rc = 0; | ||
2330 | goto out; | ||
2331 | } | ||
2332 | } | ||
2333 | |||
2334 | if (rsp_iu.cmd.status) | ||
2335 | rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); | ||
2336 | |||
2337 | if (rsp_code) { | ||
2338 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) | ||
2339 | rsp_code = fc_rsp->data.info.rsp_code; | ||
2340 | |||
2341 | sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " | ||
2342 | "flags: %x fcp_rsp: %x, scsi_status: %x\n", | ||
2343 | ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), | ||
2344 | rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, | ||
2345 | fc_rsp->scsi_status); | ||
2346 | rsp_rc = -EIO; | ||
2347 | } else | ||
2348 | sdev_printk(KERN_INFO, sdev, "Abort successful\n"); | ||
2349 | |||
2350 | out: | ||
2351 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
2352 | ibmvfc_free_event(evt); | ||
2353 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2354 | return rsp_rc; | ||
2297 | } | 2355 | } |
2298 | 2356 | ||
2299 | /** | 2357 | /** |
@@ -2351,18 +2409,6 @@ static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
2351 | } | 2409 | } |
2352 | 2410 | ||
2353 | /** | 2411 | /** |
2354 | * ibmvfc_dev_cancel_all_abts - Device iterated cancel all function | ||
2355 | * @sdev: scsi device struct | ||
2356 | * @data: return code | ||
2357 | * | ||
2358 | **/ | ||
2359 | static void ibmvfc_dev_cancel_all_abts(struct scsi_device *sdev, void *data) | ||
2360 | { | ||
2361 | unsigned long *rc = data; | ||
2362 | *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
2363 | } | ||
2364 | |||
2365 | /** | ||
2366 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function | 2412 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function |
2367 | * @sdev: scsi device struct | 2413 | * @sdev: scsi device struct |
2368 | * @data: return code | 2414 | * @data: return code |
@@ -2375,18 +2421,6 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data) | |||
2375 | } | 2421 | } |
2376 | 2422 | ||
2377 | /** | 2423 | /** |
2378 | * ibmvfc_dev_abort_all - Device iterated abort task set function | ||
2379 | * @sdev: scsi device struct | ||
2380 | * @data: return code | ||
2381 | * | ||
2382 | **/ | ||
2383 | static void ibmvfc_dev_abort_all(struct scsi_device *sdev, void *data) | ||
2384 | { | ||
2385 | unsigned long *rc = data; | ||
2386 | *rc |= ibmvfc_abort_task_set(sdev); | ||
2387 | } | ||
2388 | |||
2389 | /** | ||
2390 | * ibmvfc_eh_target_reset_handler - Reset the target | 2424 | * ibmvfc_eh_target_reset_handler - Reset the target |
2391 | * @cmd: scsi command struct | 2425 | * @cmd: scsi command struct |
2392 | * | 2426 | * |
@@ -2440,19 +2474,22 @@ static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) | |||
2440 | **/ | 2474 | **/ |
2441 | static void ibmvfc_terminate_rport_io(struct fc_rport *rport) | 2475 | static void ibmvfc_terminate_rport_io(struct fc_rport *rport) |
2442 | { | 2476 | { |
2443 | struct scsi_target *starget = to_scsi_target(&rport->dev); | 2477 | struct Scsi_Host *shost = rport_to_shost(rport); |
2444 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2445 | struct ibmvfc_host *vhost = shost_priv(shost); | 2478 | struct ibmvfc_host *vhost = shost_priv(shost); |
2446 | unsigned long cancel_rc = 0; | 2479 | struct fc_rport *dev_rport; |
2447 | unsigned long abort_rc = 0; | 2480 | struct scsi_device *sdev; |
2448 | int rc = FAILED; | 2481 | unsigned long rc; |
2449 | 2482 | ||
2450 | ENTER; | 2483 | ENTER; |
2451 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_abts); | 2484 | shost_for_each_device(sdev, shost) { |
2452 | starget_for_each_device(starget, &abort_rc, ibmvfc_dev_abort_all); | 2485 | dev_rport = starget_to_rport(scsi_target(sdev)); |
2486 | if (dev_rport != rport) | ||
2487 | continue; | ||
2488 | ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
2489 | ibmvfc_abort_task_set(sdev); | ||
2490 | } | ||
2453 | 2491 | ||
2454 | if (!cancel_rc && !abort_rc) | 2492 | rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport); |
2455 | rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); | ||
2456 | 2493 | ||
2457 | if (rc == FAILED) | 2494 | if (rc == FAILED) |
2458 | ibmvfc_issue_fc_host_lip(shost); | 2495 | ibmvfc_issue_fc_host_lip(shost); |
@@ -4193,11 +4230,15 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) | |||
4193 | if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { | 4230 | if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { |
4194 | tgt_dbg(tgt, "Deleting rport\n"); | 4231 | tgt_dbg(tgt, "Deleting rport\n"); |
4195 | list_del(&tgt->queue); | 4232 | list_del(&tgt->queue); |
4233 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); | ||
4196 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 4234 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
4197 | fc_remote_port_delete(rport); | 4235 | fc_remote_port_delete(rport); |
4198 | del_timer_sync(&tgt->timer); | 4236 | del_timer_sync(&tgt->timer); |
4199 | kref_put(&tgt->kref, ibmvfc_release_tgt); | 4237 | kref_put(&tgt->kref, ibmvfc_release_tgt); |
4200 | return; | 4238 | return; |
4239 | } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) { | ||
4240 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
4241 | return; | ||
4201 | } | 4242 | } |
4202 | 4243 | ||
4203 | if (rport) { | 4244 | if (rport) { |
@@ -4297,6 +4338,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) | |||
4297 | rport = tgt->rport; | 4338 | rport = tgt->rport; |
4298 | tgt->rport = NULL; | 4339 | tgt->rport = NULL; |
4299 | list_del(&tgt->queue); | 4340 | list_del(&tgt->queue); |
4341 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); | ||
4300 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 4342 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
4301 | if (rport) | 4343 | if (rport) |
4302 | fc_remote_port_delete(rport); | 4344 | fc_remote_port_delete(rport); |
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index d7e8dcd90650..608af394c8cf 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h | |||
@@ -29,8 +29,8 @@ | |||
29 | #include "viosrp.h" | 29 | #include "viosrp.h" |
30 | 30 | ||
31 | #define IBMVFC_NAME "ibmvfc" | 31 | #define IBMVFC_NAME "ibmvfc" |
32 | #define IBMVFC_DRIVER_VERSION "1.0.8" | 32 | #define IBMVFC_DRIVER_VERSION "1.0.9" |
33 | #define IBMVFC_DRIVER_DATE "(June 17, 2010)" | 33 | #define IBMVFC_DRIVER_DATE "(August 5, 2010)" |
34 | 34 | ||
35 | #define IBMVFC_DEFAULT_TIMEOUT 60 | 35 | #define IBMVFC_DEFAULT_TIMEOUT 60 |
36 | #define IBMVFC_ADISC_CANCEL_TIMEOUT 45 | 36 | #define IBMVFC_ADISC_CANCEL_TIMEOUT 45 |
@@ -38,6 +38,7 @@ | |||
38 | #define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \ | 38 | #define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \ |
39 | (IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT) | 39 | (IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT) |
40 | #define IBMVFC_INIT_TIMEOUT 120 | 40 | #define IBMVFC_INIT_TIMEOUT 120 |
41 | #define IBMVFC_ABORT_TIMEOUT 8 | ||
41 | #define IBMVFC_ABORT_WAIT_TIMEOUT 40 | 42 | #define IBMVFC_ABORT_WAIT_TIMEOUT 40 |
42 | #define IBMVFC_MAX_REQUESTS_DEFAULT 100 | 43 | #define IBMVFC_MAX_REQUESTS_DEFAULT 100 |
43 | 44 | ||
@@ -597,6 +598,7 @@ enum ibmvfc_target_action { | |||
597 | IBMVFC_TGT_ACTION_INIT, | 598 | IBMVFC_TGT_ACTION_INIT, |
598 | IBMVFC_TGT_ACTION_INIT_WAIT, | 599 | IBMVFC_TGT_ACTION_INIT_WAIT, |
599 | IBMVFC_TGT_ACTION_DEL_RPORT, | 600 | IBMVFC_TGT_ACTION_DEL_RPORT, |
601 | IBMVFC_TGT_ACTION_DELETED_RPORT, | ||
600 | }; | 602 | }; |
601 | 603 | ||
602 | struct ibmvfc_target { | 604 | struct ibmvfc_target { |
diff --git a/drivers/firmware/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c index df6bff7366cf..df6bff7366cf 100644 --- a/drivers/firmware/iscsi_boot_sysfs.c +++ b/drivers/scsi/iscsi_boot_sysfs.c | |||
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index eac4d09314eb..c797f6b48f05 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
@@ -1765,14 +1765,14 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) | |||
1765 | struct fcoe_dev_stats *stats; | 1765 | struct fcoe_dev_stats *stats; |
1766 | 1766 | ||
1767 | lport = shost_priv(sc_cmd->device->host); | 1767 | lport = shost_priv(sc_cmd->device->host); |
1768 | spin_unlock_irq(lport->host->host_lock); | ||
1769 | 1768 | ||
1770 | rval = fc_remote_port_chkready(rport); | 1769 | rval = fc_remote_port_chkready(rport); |
1771 | if (rval) { | 1770 | if (rval) { |
1772 | sc_cmd->result = rval; | 1771 | sc_cmd->result = rval; |
1773 | done(sc_cmd); | 1772 | done(sc_cmd); |
1774 | goto out; | 1773 | return 0; |
1775 | } | 1774 | } |
1775 | spin_unlock_irq(lport->host->host_lock); | ||
1776 | 1776 | ||
1777 | if (!*(struct fc_remote_port **)rport->dd_data) { | 1777 | if (!*(struct fc_remote_port **)rport->dd_data) { |
1778 | /* | 1778 | /* |
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 3482d5a5aed2..a50aa03b8ac1 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -775,6 +775,7 @@ struct lpfc_hba { | |||
775 | uint8_t temp_sensor_support; | 775 | uint8_t temp_sensor_support; |
776 | /* Fields used for heart beat. */ | 776 | /* Fields used for heart beat. */ |
777 | unsigned long last_completion_time; | 777 | unsigned long last_completion_time; |
778 | unsigned long skipped_hb; | ||
778 | struct timer_list hb_tmofunc; | 779 | struct timer_list hb_tmofunc; |
779 | uint8_t hb_outstanding; | 780 | uint8_t hb_outstanding; |
780 | enum hba_temp_state over_temp_state; | 781 | enum hba_temp_state over_temp_state; |
@@ -817,6 +818,8 @@ struct lpfc_hba { | |||
817 | uint32_t iocb_cnt; | 818 | uint32_t iocb_cnt; |
818 | uint32_t iocb_max; | 819 | uint32_t iocb_max; |
819 | atomic_t sdev_cnt; | 820 | atomic_t sdev_cnt; |
821 | uint8_t fips_spec_rev; | ||
822 | uint8_t fips_level; | ||
820 | }; | 823 | }; |
821 | 824 | ||
822 | static inline struct Scsi_Host * | 825 | static inline struct Scsi_Host * |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index ad05b266e950..23ce45708335 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -1240,6 +1240,44 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr, | |||
1240 | } | 1240 | } |
1241 | 1241 | ||
1242 | /** | 1242 | /** |
1243 | * lpfc_fips_level_show - Return the current FIPS level for the HBA | ||
1244 | * @dev: class unused variable. | ||
1245 | * @attr: device attribute, not used. | ||
1246 | * @buf: on return contains the module description text. | ||
1247 | * | ||
1248 | * Returns: size of formatted string. | ||
1249 | **/ | ||
1250 | static ssize_t | ||
1251 | lpfc_fips_level_show(struct device *dev, struct device_attribute *attr, | ||
1252 | char *buf) | ||
1253 | { | ||
1254 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1255 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
1256 | struct lpfc_hba *phba = vport->phba; | ||
1257 | |||
1258 | return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level); | ||
1259 | } | ||
1260 | |||
1261 | /** | ||
1262 | * lpfc_fips_rev_show - Return the FIPS Spec revision for the HBA | ||
1263 | * @dev: class unused variable. | ||
1264 | * @attr: device attribute, not used. | ||
1265 | * @buf: on return contains the module description text. | ||
1266 | * | ||
1267 | * Returns: size of formatted string. | ||
1268 | **/ | ||
1269 | static ssize_t | ||
1270 | lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr, | ||
1271 | char *buf) | ||
1272 | { | ||
1273 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1274 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
1275 | struct lpfc_hba *phba = vport->phba; | ||
1276 | |||
1277 | return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev); | ||
1278 | } | ||
1279 | |||
1280 | /** | ||
1243 | * lpfc_param_show - Return a cfg attribute value in decimal | 1281 | * lpfc_param_show - Return a cfg attribute value in decimal |
1244 | * | 1282 | * |
1245 | * Description: | 1283 | * Description: |
@@ -1677,6 +1715,8 @@ static DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); | |||
1677 | static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); | 1715 | static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); |
1678 | static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); | 1716 | static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); |
1679 | static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); | 1717 | static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); |
1718 | static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); | ||
1719 | static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); | ||
1680 | 1720 | ||
1681 | 1721 | ||
1682 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; | 1722 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; |
@@ -3278,7 +3318,7 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); | |||
3278 | # - Default will result in registering capabilities for all profiles. | 3318 | # - Default will result in registering capabilities for all profiles. |
3279 | # | 3319 | # |
3280 | */ | 3320 | */ |
3281 | unsigned int lpfc_prot_mask = SHOST_DIX_TYPE0_PROTECTION; | 3321 | unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION; |
3282 | 3322 | ||
3283 | module_param(lpfc_prot_mask, uint, 0); | 3323 | module_param(lpfc_prot_mask, uint, 0); |
3284 | MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); | 3324 | MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); |
@@ -3383,6 +3423,8 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
3383 | &dev_attr_iocb_hw, | 3423 | &dev_attr_iocb_hw, |
3384 | &dev_attr_txq_hw, | 3424 | &dev_attr_txq_hw, |
3385 | &dev_attr_txcmplq_hw, | 3425 | &dev_attr_txcmplq_hw, |
3426 | &dev_attr_lpfc_fips_level, | ||
3427 | &dev_attr_lpfc_fips_rev, | ||
3386 | NULL, | 3428 | NULL, |
3387 | }; | 3429 | }; |
3388 | 3430 | ||
@@ -3409,6 +3451,8 @@ struct device_attribute *lpfc_vport_attrs[] = { | |||
3409 | &dev_attr_lpfc_max_scsicmpl_time, | 3451 | &dev_attr_lpfc_max_scsicmpl_time, |
3410 | &dev_attr_lpfc_stat_data_ctrl, | 3452 | &dev_attr_lpfc_stat_data_ctrl, |
3411 | &dev_attr_lpfc_static_vport, | 3453 | &dev_attr_lpfc_static_vport, |
3454 | &dev_attr_lpfc_fips_level, | ||
3455 | &dev_attr_lpfc_fips_rev, | ||
3412 | NULL, | 3456 | NULL, |
3413 | }; | 3457 | }; |
3414 | 3458 | ||
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index d521569e6620..49d0cf99c24c 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -2724,15 +2724,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2724 | 2724 | ||
2725 | pmboxq->context2 = ext; | 2725 | pmboxq->context2 = ext; |
2726 | pmboxq->in_ext_byte_len = | 2726 | pmboxq->in_ext_byte_len = |
2727 | mbox_req->inExtWLen * | ||
2728 | sizeof(uint32_t); | ||
2729 | pmboxq->out_ext_byte_len = | ||
2730 | mbox_req->outExtWLen * | ||
2731 | sizeof(uint32_t); | ||
2732 | pmboxq->mbox_offset_word = | ||
2733 | mbox_req->mbOffset; | ||
2734 | pmboxq->context2 = ext; | ||
2735 | pmboxq->in_ext_byte_len = | ||
2736 | mbox_req->inExtWLen * sizeof(uint32_t); | 2727 | mbox_req->inExtWLen * sizeof(uint32_t); |
2737 | pmboxq->out_ext_byte_len = | 2728 | pmboxq->out_ext_byte_len = |
2738 | mbox_req->outExtWLen * sizeof(uint32_t); | 2729 | mbox_req->outExtWLen * sizeof(uint32_t); |
diff --git a/drivers/scsi/lpfc/lpfc_compat.h b/drivers/scsi/lpfc/lpfc_compat.h index a11f1ae7b98e..75e2e569dede 100644 --- a/drivers/scsi/lpfc/lpfc_compat.h +++ b/drivers/scsi/lpfc/lpfc_compat.h | |||
@@ -82,8 +82,7 @@ lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes) | |||
82 | static inline void | 82 | static inline void |
83 | lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes) | 83 | lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes) |
84 | { | 84 | { |
85 | /* actually returns 1 byte past dest */ | 85 | __iowrite32_copy(dest, src, bytes); |
86 | memcpy_toio( dest, src, bytes); | ||
87 | } | 86 | } |
88 | 87 | ||
89 | static inline void | 88 | static inline void |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index afbed6bc31f0..8d09191c327e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -600,6 +600,14 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
600 | vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | 600 | vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; |
601 | spin_unlock_irq(shost->host_lock); | 601 | spin_unlock_irq(shost->host_lock); |
602 | } | 602 | } |
603 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
604 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { | ||
605 | /* | ||
606 | * Driver needs to re-reg VPI in order for f/w | ||
607 | * to update the MAC address. | ||
608 | */ | ||
609 | lpfc_register_new_vport(phba, vport, ndlp); | ||
610 | return 0; | ||
603 | } | 611 | } |
604 | 612 | ||
605 | if (phba->sli_rev < LPFC_SLI_REV4) { | 613 | if (phba->sli_rev < LPFC_SLI_REV4) { |
@@ -801,9 +809,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
801 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) { | 809 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) { |
802 | lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, | 810 | lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, |
803 | "2611 FLOGI failed on registered " | 811 | "2611 FLOGI failed on registered " |
804 | "FCF record fcf_index:%d, trying " | 812 | "FCF record fcf_index(%d), status: " |
805 | "to perform round robin failover\n", | 813 | "x%x/x%x, tmo:x%x, trying to perform " |
806 | phba->fcf.current_rec.fcf_indx); | 814 | "round robin failover\n", |
815 | phba->fcf.current_rec.fcf_indx, | ||
816 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
817 | irsp->ulpTimeout); | ||
807 | fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba); | 818 | fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba); |
808 | if (fcf_index == LPFC_FCOE_FCF_NEXT_NONE) { | 819 | if (fcf_index == LPFC_FCOE_FCF_NEXT_NONE) { |
809 | /* | 820 | /* |
@@ -841,6 +852,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
841 | } | 852 | } |
842 | } | 853 | } |
843 | 854 | ||
855 | /* FLOGI failure */ | ||
856 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
857 | "2858 FLOGI failure Status:x%x/x%x TMO:x%x\n", | ||
858 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
859 | irsp->ulpTimeout); | ||
860 | |||
844 | /* Check for retry */ | 861 | /* Check for retry */ |
845 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) | 862 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
846 | goto out; | 863 | goto out; |
@@ -1291,6 +1308,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1291 | struct serv_parm *sp; | 1308 | struct serv_parm *sp; |
1292 | uint8_t name[sizeof(struct lpfc_name)]; | 1309 | uint8_t name[sizeof(struct lpfc_name)]; |
1293 | uint32_t rc, keepDID = 0; | 1310 | uint32_t rc, keepDID = 0; |
1311 | int put_node; | ||
1312 | int put_rport; | ||
1294 | 1313 | ||
1295 | /* Fabric nodes can have the same WWPN so we don't bother searching | 1314 | /* Fabric nodes can have the same WWPN so we don't bother searching |
1296 | * by WWPN. Just return the ndlp that was given to us. | 1315 | * by WWPN. Just return the ndlp that was given to us. |
@@ -1379,6 +1398,28 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1379 | /* Two ndlps cannot have the same did */ | 1398 | /* Two ndlps cannot have the same did */ |
1380 | ndlp->nlp_DID = keepDID; | 1399 | ndlp->nlp_DID = keepDID; |
1381 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 1400 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1401 | /* Since we are swapping the ndlp passed in with the new one | ||
1402 | * and the did has already been swapped, copy over the | ||
1403 | * state and names. | ||
1404 | */ | ||
1405 | memcpy(&new_ndlp->nlp_portname, &ndlp->nlp_portname, | ||
1406 | sizeof(struct lpfc_name)); | ||
1407 | memcpy(&new_ndlp->nlp_nodename, &ndlp->nlp_nodename, | ||
1408 | sizeof(struct lpfc_name)); | ||
1409 | new_ndlp->nlp_state = ndlp->nlp_state; | ||
1410 | /* Fix up the rport accordingly */ | ||
1411 | rport = ndlp->rport; | ||
1412 | if (rport) { | ||
1413 | rdata = rport->dd_data; | ||
1414 | put_node = rdata->pnode != NULL; | ||
1415 | put_rport = ndlp->rport != NULL; | ||
1416 | rdata->pnode = NULL; | ||
1417 | ndlp->rport = NULL; | ||
1418 | if (put_node) | ||
1419 | lpfc_nlp_put(ndlp); | ||
1420 | if (put_rport) | ||
1421 | put_device(&rport->dev); | ||
1422 | } | ||
1382 | } | 1423 | } |
1383 | return new_ndlp; | 1424 | return new_ndlp; |
1384 | } | 1425 | } |
@@ -2880,6 +2921,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2880 | retry = 0; | 2921 | retry = 0; |
2881 | 2922 | ||
2882 | if (retry) { | 2923 | if (retry) { |
2924 | if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_FDISC)) { | ||
2925 | /* Stop retrying PLOGI and FDISC if in FCF discovery */ | ||
2926 | if (phba->fcf.fcf_flag & FCF_DISCOVERY) { | ||
2927 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
2928 | "2849 Stop retry ELS command " | ||
2929 | "x%x to remote NPORT x%x, " | ||
2930 | "Data: x%x x%x\n", cmd, did, | ||
2931 | cmdiocb->retry, delay); | ||
2932 | return 0; | ||
2933 | } | ||
2934 | } | ||
2883 | 2935 | ||
2884 | /* Retry ELS command <elsCmd> to remote NPORT <did> */ | 2936 | /* Retry ELS command <elsCmd> to remote NPORT <did> */ |
2885 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2937 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
@@ -6076,8 +6128,12 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
6076 | 6128 | ||
6077 | if (mb->mbxStatus) { | 6129 | if (mb->mbxStatus) { |
6078 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, | 6130 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, |
6079 | "0915 Register VPI failed: 0x%x\n", | 6131 | "0915 Register VPI failed : Status: x%x" |
6080 | mb->mbxStatus); | 6132 | " upd bit: x%x \n", mb->mbxStatus, |
6133 | mb->un.varRegVpi.upd); | ||
6134 | if (phba->sli_rev == LPFC_SLI_REV4 && | ||
6135 | mb->un.varRegVpi.upd) | ||
6136 | goto mbox_err_exit ; | ||
6081 | 6137 | ||
6082 | switch (mb->mbxStatus) { | 6138 | switch (mb->mbxStatus) { |
6083 | case 0x11: /* unsupported feature */ | 6139 | case 0x11: /* unsupported feature */ |
@@ -6142,7 +6198,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
6142 | } else | 6198 | } else |
6143 | lpfc_do_scr_ns_plogi(phba, vport); | 6199 | lpfc_do_scr_ns_plogi(phba, vport); |
6144 | } | 6200 | } |
6145 | 6201 | mbox_err_exit: | |
6146 | /* Now, we decrement the ndlp reference count held for this | 6202 | /* Now, we decrement the ndlp reference count held for this |
6147 | * callback function | 6203 | * callback function |
6148 | */ | 6204 | */ |
@@ -6387,6 +6443,14 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6387 | else | 6443 | else |
6388 | vport->fc_flag |= FC_LOGO_RCVD_DID_CHNG; | 6444 | vport->fc_flag |= FC_LOGO_RCVD_DID_CHNG; |
6389 | spin_unlock_irq(shost->host_lock); | 6445 | spin_unlock_irq(shost->host_lock); |
6446 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
6447 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { | ||
6448 | /* | ||
6449 | * Driver needs to re-reg VPI in order for f/w | ||
6450 | * to update the MAC address. | ||
6451 | */ | ||
6452 | lpfc_register_new_vport(phba, vport, ndlp); | ||
6453 | return ; | ||
6390 | } | 6454 | } |
6391 | 6455 | ||
6392 | if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) | 6456 | if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 0639c994349c..1f62ea8c165d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -588,7 +588,7 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
588 | (status & | 588 | (status & |
589 | HA_RXMASK)); | 589 | HA_RXMASK)); |
590 | } | 590 | } |
591 | if (pring->txq_cnt) | 591 | if ((phba->sli_rev == LPFC_SLI_REV4) && pring->txq_cnt) |
592 | lpfc_drain_txq(phba); | 592 | lpfc_drain_txq(phba); |
593 | /* | 593 | /* |
594 | * Turn on Ring interrupts | 594 | * Turn on Ring interrupts |
@@ -1852,8 +1852,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1852 | __lpfc_sli4_stop_fcf_redisc_wait_timer(phba); | 1852 | __lpfc_sli4_stop_fcf_redisc_wait_timer(phba); |
1853 | else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) | 1853 | else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) |
1854 | /* If in fast failover, mark it's completed */ | 1854 | /* If in fast failover, mark it's completed */ |
1855 | phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | | 1855 | phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; |
1856 | FCF_DISCOVERY); | ||
1857 | spin_unlock_irq(&phba->hbalock); | 1856 | spin_unlock_irq(&phba->hbalock); |
1858 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP, | 1857 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP, |
1859 | "2836 The new FCF record (x%x) " | 1858 | "2836 The new FCF record (x%x) " |
@@ -2651,7 +2650,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
2651 | spin_unlock_irq(&phba->hbalock); | 2650 | spin_unlock_irq(&phba->hbalock); |
2652 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, | 2651 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, |
2653 | "2778 Start FCF table scan at linkup\n"); | 2652 | "2778 Start FCF table scan at linkup\n"); |
2654 | |||
2655 | rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, | 2653 | rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, |
2656 | LPFC_FCOE_FCF_GET_FIRST); | 2654 | LPFC_FCOE_FCF_GET_FIRST); |
2657 | if (rc) { | 2655 | if (rc) { |
@@ -2660,6 +2658,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
2660 | spin_unlock_irq(&phba->hbalock); | 2658 | spin_unlock_irq(&phba->hbalock); |
2661 | goto out; | 2659 | goto out; |
2662 | } | 2660 | } |
2661 | /* Reset FCF roundrobin bmask for new discovery */ | ||
2662 | memset(phba->fcf.fcf_rr_bmask, 0, | ||
2663 | sizeof(*phba->fcf.fcf_rr_bmask)); | ||
2663 | } | 2664 | } |
2664 | 2665 | ||
2665 | return; | 2666 | return; |
@@ -5097,6 +5098,7 @@ static void | |||
5097 | lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | 5098 | lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) |
5098 | { | 5099 | { |
5099 | struct lpfc_vport *vport = mboxq->vport; | 5100 | struct lpfc_vport *vport = mboxq->vport; |
5101 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
5100 | 5102 | ||
5101 | if (mboxq->u.mb.mbxStatus) { | 5103 | if (mboxq->u.mb.mbxStatus) { |
5102 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, | 5104 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, |
@@ -5104,6 +5106,9 @@ lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
5104 | "HBA state x%x\n", | 5106 | "HBA state x%x\n", |
5105 | mboxq->u.mb.mbxStatus, vport->port_state); | 5107 | mboxq->u.mb.mbxStatus, vport->port_state); |
5106 | } | 5108 | } |
5109 | spin_lock_irq(shost->host_lock); | ||
5110 | phba->pport->fc_flag &= ~FC_VFI_REGISTERED; | ||
5111 | spin_unlock_irq(shost->host_lock); | ||
5107 | mempool_free(mboxq, phba->mbox_mem_pool); | 5112 | mempool_free(mboxq, phba->mbox_mem_pool); |
5108 | return; | 5113 | return; |
5109 | } | 5114 | } |
@@ -5285,6 +5290,10 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba) | |||
5285 | spin_lock_irq(&phba->hbalock); | 5290 | spin_lock_irq(&phba->hbalock); |
5286 | phba->fcf.fcf_flag |= FCF_INIT_DISC; | 5291 | phba->fcf.fcf_flag |= FCF_INIT_DISC; |
5287 | spin_unlock_irq(&phba->hbalock); | 5292 | spin_unlock_irq(&phba->hbalock); |
5293 | |||
5294 | /* Reset FCF roundrobin bmask for new discovery */ | ||
5295 | memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask)); | ||
5296 | |||
5288 | rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); | 5297 | rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); |
5289 | 5298 | ||
5290 | if (rc) { | 5299 | if (rc) { |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index f5dbf2be3eab..1676f61291e7 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -2291,7 +2291,8 @@ typedef struct { | |||
2291 | typedef struct { | 2291 | typedef struct { |
2292 | #ifdef __BIG_ENDIAN_BITFIELD | 2292 | #ifdef __BIG_ENDIAN_BITFIELD |
2293 | uint32_t rsvd1; | 2293 | uint32_t rsvd1; |
2294 | uint32_t rsvd2:8; | 2294 | uint32_t rsvd2:7; |
2295 | uint32_t upd:1; | ||
2295 | uint32_t sid:24; | 2296 | uint32_t sid:24; |
2296 | uint32_t wwn[2]; | 2297 | uint32_t wwn[2]; |
2297 | uint32_t rsvd5; | 2298 | uint32_t rsvd5; |
@@ -2300,7 +2301,8 @@ typedef struct { | |||
2300 | #else /* __LITTLE_ENDIAN */ | 2301 | #else /* __LITTLE_ENDIAN */ |
2301 | uint32_t rsvd1; | 2302 | uint32_t rsvd1; |
2302 | uint32_t sid:24; | 2303 | uint32_t sid:24; |
2303 | uint32_t rsvd2:8; | 2304 | uint32_t upd:1; |
2305 | uint32_t rsvd2:7; | ||
2304 | uint32_t wwn[2]; | 2306 | uint32_t wwn[2]; |
2305 | uint32_t rsvd5; | 2307 | uint32_t rsvd5; |
2306 | uint16_t vpi; | 2308 | uint16_t vpi; |
@@ -2806,11 +2808,15 @@ typedef struct { | |||
2806 | uint32_t rsvd6; /* Reserved */ | 2808 | uint32_t rsvd6; /* Reserved */ |
2807 | 2809 | ||
2808 | #ifdef __BIG_ENDIAN_BITFIELD | 2810 | #ifdef __BIG_ENDIAN_BITFIELD |
2809 | uint32_t rsvd7 : 16; /* Reserved */ | 2811 | uint32_t fips_rev : 3; /* FIPS Spec Revision */ |
2812 | uint32_t fips_level : 4; /* FIPS Level */ | ||
2813 | uint32_t sec_err : 9; /* security crypto error */ | ||
2810 | uint32_t max_vpi : 16; /* Max number of virt N-Ports */ | 2814 | uint32_t max_vpi : 16; /* Max number of virt N-Ports */ |
2811 | #else /* __LITTLE_ENDIAN */ | 2815 | #else /* __LITTLE_ENDIAN */ |
2812 | uint32_t max_vpi : 16; /* Max number of virt N-Ports */ | 2816 | uint32_t max_vpi : 16; /* Max number of virt N-Ports */ |
2813 | uint32_t rsvd7 : 16; /* Reserved */ | 2817 | uint32_t sec_err : 9; /* security crypto error */ |
2818 | uint32_t fips_level : 4; /* FIPS Level */ | ||
2819 | uint32_t fips_rev : 3; /* FIPS Spec Revision */ | ||
2814 | #endif | 2820 | #endif |
2815 | 2821 | ||
2816 | } CONFIG_PORT_VAR; | 2822 | } CONFIG_PORT_VAR; |
@@ -3441,63 +3447,63 @@ struct sli3_bg_fields { | |||
3441 | static inline uint32_t | 3447 | static inline uint32_t |
3442 | lpfc_bgs_get_bidir_bg_prof(uint32_t bgstat) | 3448 | lpfc_bgs_get_bidir_bg_prof(uint32_t bgstat) |
3443 | { | 3449 | { |
3444 | return (le32_to_cpu(bgstat) & BGS_BIDIR_BG_PROF_MASK) >> | 3450 | return (bgstat & BGS_BIDIR_BG_PROF_MASK) >> |
3445 | BGS_BIDIR_BG_PROF_SHIFT; | 3451 | BGS_BIDIR_BG_PROF_SHIFT; |
3446 | } | 3452 | } |
3447 | 3453 | ||
3448 | static inline uint32_t | 3454 | static inline uint32_t |
3449 | lpfc_bgs_get_bidir_err_cond(uint32_t bgstat) | 3455 | lpfc_bgs_get_bidir_err_cond(uint32_t bgstat) |
3450 | { | 3456 | { |
3451 | return (le32_to_cpu(bgstat) & BGS_BIDIR_ERR_COND_FLAGS_MASK) >> | 3457 | return (bgstat & BGS_BIDIR_ERR_COND_FLAGS_MASK) >> |
3452 | BGS_BIDIR_ERR_COND_SHIFT; | 3458 | BGS_BIDIR_ERR_COND_SHIFT; |
3453 | } | 3459 | } |
3454 | 3460 | ||
3455 | static inline uint32_t | 3461 | static inline uint32_t |
3456 | lpfc_bgs_get_bg_prof(uint32_t bgstat) | 3462 | lpfc_bgs_get_bg_prof(uint32_t bgstat) |
3457 | { | 3463 | { |
3458 | return (le32_to_cpu(bgstat) & BGS_BG_PROFILE_MASK) >> | 3464 | return (bgstat & BGS_BG_PROFILE_MASK) >> |
3459 | BGS_BG_PROFILE_SHIFT; | 3465 | BGS_BG_PROFILE_SHIFT; |
3460 | } | 3466 | } |
3461 | 3467 | ||
3462 | static inline uint32_t | 3468 | static inline uint32_t |
3463 | lpfc_bgs_get_invalid_prof(uint32_t bgstat) | 3469 | lpfc_bgs_get_invalid_prof(uint32_t bgstat) |
3464 | { | 3470 | { |
3465 | return (le32_to_cpu(bgstat) & BGS_INVALID_PROF_MASK) >> | 3471 | return (bgstat & BGS_INVALID_PROF_MASK) >> |
3466 | BGS_INVALID_PROF_SHIFT; | 3472 | BGS_INVALID_PROF_SHIFT; |
3467 | } | 3473 | } |
3468 | 3474 | ||
3469 | static inline uint32_t | 3475 | static inline uint32_t |
3470 | lpfc_bgs_get_uninit_dif_block(uint32_t bgstat) | 3476 | lpfc_bgs_get_uninit_dif_block(uint32_t bgstat) |
3471 | { | 3477 | { |
3472 | return (le32_to_cpu(bgstat) & BGS_UNINIT_DIF_BLOCK_MASK) >> | 3478 | return (bgstat & BGS_UNINIT_DIF_BLOCK_MASK) >> |
3473 | BGS_UNINIT_DIF_BLOCK_SHIFT; | 3479 | BGS_UNINIT_DIF_BLOCK_SHIFT; |
3474 | } | 3480 | } |
3475 | 3481 | ||
3476 | static inline uint32_t | 3482 | static inline uint32_t |
3477 | lpfc_bgs_get_hi_water_mark_present(uint32_t bgstat) | 3483 | lpfc_bgs_get_hi_water_mark_present(uint32_t bgstat) |
3478 | { | 3484 | { |
3479 | return (le32_to_cpu(bgstat) & BGS_HI_WATER_MARK_PRESENT_MASK) >> | 3485 | return (bgstat & BGS_HI_WATER_MARK_PRESENT_MASK) >> |
3480 | BGS_HI_WATER_MARK_PRESENT_SHIFT; | 3486 | BGS_HI_WATER_MARK_PRESENT_SHIFT; |
3481 | } | 3487 | } |
3482 | 3488 | ||
3483 | static inline uint32_t | 3489 | static inline uint32_t |
3484 | lpfc_bgs_get_reftag_err(uint32_t bgstat) | 3490 | lpfc_bgs_get_reftag_err(uint32_t bgstat) |
3485 | { | 3491 | { |
3486 | return (le32_to_cpu(bgstat) & BGS_REFTAG_ERR_MASK) >> | 3492 | return (bgstat & BGS_REFTAG_ERR_MASK) >> |
3487 | BGS_REFTAG_ERR_SHIFT; | 3493 | BGS_REFTAG_ERR_SHIFT; |
3488 | } | 3494 | } |
3489 | 3495 | ||
3490 | static inline uint32_t | 3496 | static inline uint32_t |
3491 | lpfc_bgs_get_apptag_err(uint32_t bgstat) | 3497 | lpfc_bgs_get_apptag_err(uint32_t bgstat) |
3492 | { | 3498 | { |
3493 | return (le32_to_cpu(bgstat) & BGS_APPTAG_ERR_MASK) >> | 3499 | return (bgstat & BGS_APPTAG_ERR_MASK) >> |
3494 | BGS_APPTAG_ERR_SHIFT; | 3500 | BGS_APPTAG_ERR_SHIFT; |
3495 | } | 3501 | } |
3496 | 3502 | ||
3497 | static inline uint32_t | 3503 | static inline uint32_t |
3498 | lpfc_bgs_get_guard_err(uint32_t bgstat) | 3504 | lpfc_bgs_get_guard_err(uint32_t bgstat) |
3499 | { | 3505 | { |
3500 | return (le32_to_cpu(bgstat) & BGS_GUARD_ERR_MASK) >> | 3506 | return (bgstat & BGS_GUARD_ERR_MASK) >> |
3501 | BGS_GUARD_ERR_SHIFT; | 3507 | BGS_GUARD_ERR_SHIFT; |
3502 | } | 3508 | } |
3503 | 3509 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 2786ee3b605d..da9ba06ad583 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1032,27 +1032,46 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
1032 | /* If there is no heart beat outstanding, issue a heartbeat command */ | 1032 | /* If there is no heart beat outstanding, issue a heartbeat command */ |
1033 | if (phba->cfg_enable_hba_heartbeat) { | 1033 | if (phba->cfg_enable_hba_heartbeat) { |
1034 | if (!phba->hb_outstanding) { | 1034 | if (!phba->hb_outstanding) { |
1035 | pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); | 1035 | if ((!(psli->sli_flag & LPFC_SLI_MBOX_ACTIVE)) && |
1036 | if (!pmboxq) { | 1036 | (list_empty(&psli->mboxq))) { |
1037 | mod_timer(&phba->hb_tmofunc, | 1037 | pmboxq = mempool_alloc(phba->mbox_mem_pool, |
1038 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | 1038 | GFP_KERNEL); |
1039 | return; | 1039 | if (!pmboxq) { |
1040 | } | 1040 | mod_timer(&phba->hb_tmofunc, |
1041 | jiffies + | ||
1042 | HZ * LPFC_HB_MBOX_INTERVAL); | ||
1043 | return; | ||
1044 | } | ||
1041 | 1045 | ||
1042 | lpfc_heart_beat(phba, pmboxq); | 1046 | lpfc_heart_beat(phba, pmboxq); |
1043 | pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; | 1047 | pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; |
1044 | pmboxq->vport = phba->pport; | 1048 | pmboxq->vport = phba->pport; |
1045 | retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | 1049 | retval = lpfc_sli_issue_mbox(phba, pmboxq, |
1050 | MBX_NOWAIT); | ||
1051 | |||
1052 | if (retval != MBX_BUSY && | ||
1053 | retval != MBX_SUCCESS) { | ||
1054 | mempool_free(pmboxq, | ||
1055 | phba->mbox_mem_pool); | ||
1056 | mod_timer(&phba->hb_tmofunc, | ||
1057 | jiffies + | ||
1058 | HZ * LPFC_HB_MBOX_INTERVAL); | ||
1059 | return; | ||
1060 | } | ||
1061 | phba->skipped_hb = 0; | ||
1062 | phba->hb_outstanding = 1; | ||
1063 | } else if (time_before_eq(phba->last_completion_time, | ||
1064 | phba->skipped_hb)) { | ||
1065 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
1066 | "2857 Last completion time not " | ||
1067 | " updated in %d ms\n", | ||
1068 | jiffies_to_msecs(jiffies | ||
1069 | - phba->last_completion_time)); | ||
1070 | } else | ||
1071 | phba->skipped_hb = jiffies; | ||
1046 | 1072 | ||
1047 | if (retval != MBX_BUSY && retval != MBX_SUCCESS) { | ||
1048 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
1049 | mod_timer(&phba->hb_tmofunc, | ||
1050 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
1051 | return; | ||
1052 | } | ||
1053 | mod_timer(&phba->hb_tmofunc, | 1073 | mod_timer(&phba->hb_tmofunc, |
1054 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | 1074 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); |
1055 | phba->hb_outstanding = 1; | ||
1056 | return; | 1075 | return; |
1057 | } else { | 1076 | } else { |
1058 | /* | 1077 | /* |
@@ -3281,10 +3300,10 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport) | |||
3281 | if (!ndlp) | 3300 | if (!ndlp) |
3282 | return 0; | 3301 | return 0; |
3283 | } | 3302 | } |
3284 | if (phba->pport->port_state <= LPFC_FLOGI) | 3303 | if (phba->pport->port_state < LPFC_FLOGI) |
3285 | return NULL; | 3304 | return NULL; |
3286 | /* If virtual link is not yet instantiated ignore CVL */ | 3305 | /* If virtual link is not yet instantiated ignore CVL */ |
3287 | if (vport->port_state <= LPFC_FDISC) | 3306 | if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC)) |
3288 | return NULL; | 3307 | return NULL; |
3289 | shost = lpfc_shost_from_vport(vport); | 3308 | shost = lpfc_shost_from_vport(vport); |
3290 | if (!shost) | 3309 | if (!shost) |
@@ -3357,21 +3376,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
3357 | "evt_tag:x%x, fcf_index:x%x\n", | 3376 | "evt_tag:x%x, fcf_index:x%x\n", |
3358 | acqe_fcoe->event_tag, | 3377 | acqe_fcoe->event_tag, |
3359 | acqe_fcoe->index); | 3378 | acqe_fcoe->index); |
3360 | /* If the FCF discovery is in progress, do nothing. */ | 3379 | if (phba->fcf.fcf_flag & FCF_DISCOVERY) { |
3361 | spin_lock_irq(&phba->hbalock); | ||
3362 | if (phba->hba_flag & FCF_DISC_INPROGRESS) { | ||
3363 | spin_unlock_irq(&phba->hbalock); | ||
3364 | break; | ||
3365 | } | ||
3366 | /* If fast FCF failover rescan event is pending, do nothing */ | ||
3367 | if (phba->fcf.fcf_flag & FCF_REDISC_EVT) { | ||
3368 | spin_unlock_irq(&phba->hbalock); | ||
3369 | break; | ||
3370 | } | ||
3371 | spin_unlock_irq(&phba->hbalock); | ||
3372 | |||
3373 | if ((phba->fcf.fcf_flag & FCF_DISCOVERY) && | ||
3374 | !(phba->fcf.fcf_flag & FCF_REDISC_FOV)) { | ||
3375 | /* | 3380 | /* |
3376 | * During period of FCF discovery, read the FCF | 3381 | * During period of FCF discovery, read the FCF |
3377 | * table record indexed by the event to update | 3382 | * table record indexed by the event to update |
@@ -3385,13 +3390,26 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
3385 | acqe_fcoe->index); | 3390 | acqe_fcoe->index); |
3386 | rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index); | 3391 | rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index); |
3387 | } | 3392 | } |
3388 | /* If the FCF has been in discovered state, do nothing. */ | 3393 | |
3394 | /* If the FCF discovery is in progress, do nothing. */ | ||
3389 | spin_lock_irq(&phba->hbalock); | 3395 | spin_lock_irq(&phba->hbalock); |
3396 | if (phba->hba_flag & FCF_DISC_INPROGRESS) { | ||
3397 | spin_unlock_irq(&phba->hbalock); | ||
3398 | break; | ||
3399 | } | ||
3400 | /* If fast FCF failover rescan event is pending, do nothing */ | ||
3401 | if (phba->fcf.fcf_flag & FCF_REDISC_EVT) { | ||
3402 | spin_unlock_irq(&phba->hbalock); | ||
3403 | break; | ||
3404 | } | ||
3405 | |||
3406 | /* If the FCF has been in discovered state, do nothing. */ | ||
3390 | if (phba->fcf.fcf_flag & FCF_SCAN_DONE) { | 3407 | if (phba->fcf.fcf_flag & FCF_SCAN_DONE) { |
3391 | spin_unlock_irq(&phba->hbalock); | 3408 | spin_unlock_irq(&phba->hbalock); |
3392 | break; | 3409 | break; |
3393 | } | 3410 | } |
3394 | spin_unlock_irq(&phba->hbalock); | 3411 | spin_unlock_irq(&phba->hbalock); |
3412 | |||
3395 | /* Otherwise, scan the entire FCF table and re-discover SAN */ | 3413 | /* Otherwise, scan the entire FCF table and re-discover SAN */ |
3396 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, | 3414 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, |
3397 | "2770 Start FCF table scan due to new FCF " | 3415 | "2770 Start FCF table scan due to new FCF " |
@@ -3417,13 +3435,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
3417 | "2549 FCF disconnected from network index 0x%x" | 3435 | "2549 FCF disconnected from network index 0x%x" |
3418 | " tag 0x%x\n", acqe_fcoe->index, | 3436 | " tag 0x%x\n", acqe_fcoe->index, |
3419 | acqe_fcoe->event_tag); | 3437 | acqe_fcoe->event_tag); |
3420 | /* If the event is not for currently used fcf do nothing */ | 3438 | /* |
3421 | if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) | 3439 | * If we are in the middle of FCF failover process, clear |
3422 | break; | 3440 | * the corresponding FCF bit in the roundrobin bitmap. |
3423 | /* We request port to rediscover the entire FCF table for | ||
3424 | * a fast recovery from case that the current FCF record | ||
3425 | * is no longer valid if we are not in the middle of FCF | ||
3426 | * failover process already. | ||
3427 | */ | 3441 | */ |
3428 | spin_lock_irq(&phba->hbalock); | 3442 | spin_lock_irq(&phba->hbalock); |
3429 | if (phba->fcf.fcf_flag & FCF_DISCOVERY) { | 3443 | if (phba->fcf.fcf_flag & FCF_DISCOVERY) { |
@@ -3432,9 +3446,23 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
3432 | lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index); | 3446 | lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index); |
3433 | break; | 3447 | break; |
3434 | } | 3448 | } |
3449 | spin_unlock_irq(&phba->hbalock); | ||
3450 | |||
3451 | /* If the event is not for currently used fcf do nothing */ | ||
3452 | if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) | ||
3453 | break; | ||
3454 | |||
3455 | /* | ||
3456 | * Otherwise, request the port to rediscover the entire FCF | ||
3457 | * table for a fast recovery from case that the current FCF | ||
3458 | * is no longer valid as we are not in the middle of FCF | ||
3459 | * failover process already. | ||
3460 | */ | ||
3461 | spin_lock_irq(&phba->hbalock); | ||
3435 | /* Mark the fast failover process in progress */ | 3462 | /* Mark the fast failover process in progress */ |
3436 | phba->fcf.fcf_flag |= FCF_DEAD_DISC; | 3463 | phba->fcf.fcf_flag |= FCF_DEAD_DISC; |
3437 | spin_unlock_irq(&phba->hbalock); | 3464 | spin_unlock_irq(&phba->hbalock); |
3465 | |||
3438 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, | 3466 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, |
3439 | "2771 Start FCF fast failover process due to " | 3467 | "2771 Start FCF fast failover process due to " |
3440 | "FCF DEAD event: evt_tag:x%x, fcf_index:x%x " | 3468 | "FCF DEAD event: evt_tag:x%x, fcf_index:x%x " |
@@ -3454,12 +3482,16 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
3454 | * as a link down to FCF registration. | 3482 | * as a link down to FCF registration. |
3455 | */ | 3483 | */ |
3456 | lpfc_sli4_fcf_dead_failthrough(phba); | 3484 | lpfc_sli4_fcf_dead_failthrough(phba); |
3457 | } else | 3485 | } else { |
3458 | /* Handling fast FCF failover to a DEAD FCF event | 3486 | /* Reset FCF roundrobin bmask for new discovery */ |
3459 | * is considered equalivant to receiving CVL to all | 3487 | memset(phba->fcf.fcf_rr_bmask, 0, |
3460 | * vports. | 3488 | sizeof(*phba->fcf.fcf_rr_bmask)); |
3489 | /* | ||
3490 | * Handling fast FCF failover to a DEAD FCF event is | ||
3491 | * considered equalivant to receiving CVL to all vports. | ||
3461 | */ | 3492 | */ |
3462 | lpfc_sli4_perform_all_vport_cvl(phba); | 3493 | lpfc_sli4_perform_all_vport_cvl(phba); |
3494 | } | ||
3463 | break; | 3495 | break; |
3464 | case LPFC_FCOE_EVENT_TYPE_CVL: | 3496 | case LPFC_FCOE_EVENT_TYPE_CVL: |
3465 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, | 3497 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, |
@@ -3534,7 +3566,13 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
3534 | * the current registered FCF entry. | 3566 | * the current registered FCF entry. |
3535 | */ | 3567 | */ |
3536 | lpfc_retry_pport_discovery(phba); | 3568 | lpfc_retry_pport_discovery(phba); |
3537 | } | 3569 | } else |
3570 | /* | ||
3571 | * Reset FCF roundrobin bmask for new | ||
3572 | * discovery. | ||
3573 | */ | ||
3574 | memset(phba->fcf.fcf_rr_bmask, 0, | ||
3575 | sizeof(*phba->fcf.fcf_rr_bmask)); | ||
3538 | } | 3576 | } |
3539 | break; | 3577 | break; |
3540 | default: | 3578 | default: |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 9c2c7c7140c7..0dfa310cd609 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -815,9 +815,15 @@ void | |||
815 | lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb) | 815 | lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb) |
816 | { | 816 | { |
817 | MAILBOX_t *mb = &pmb->u.mb; | 817 | MAILBOX_t *mb = &pmb->u.mb; |
818 | struct lpfc_hba *phba = vport->phba; | ||
818 | 819 | ||
819 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 820 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
820 | 821 | /* | |
822 | * Set the re-reg VPI bit for f/w to update the MAC address. | ||
823 | */ | ||
824 | if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
825 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) | ||
826 | mb->un.varRegVpi.upd = 1; | ||
821 | mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base; | 827 | mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base; |
822 | mb->un.varRegVpi.sid = vport->fc_myDID; | 828 | mb->un.varRegVpi.sid = vport->fc_myDID; |
823 | mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; | 829 | mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c818a7255962..2e51aa6b45b3 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -1325,7 +1325,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1325 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); | 1325 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); |
1326 | pde5->reftag = reftag; | 1326 | pde5->reftag = reftag; |
1327 | 1327 | ||
1328 | /* Endian convertion if necessary for PDE5 */ | 1328 | /* Endianness conversion if necessary for PDE5 */ |
1329 | pde5->word0 = cpu_to_le32(pde5->word0); | 1329 | pde5->word0 = cpu_to_le32(pde5->word0); |
1330 | pde5->reftag = cpu_to_le32(pde5->reftag); | 1330 | pde5->reftag = cpu_to_le32(pde5->reftag); |
1331 | 1331 | ||
@@ -1347,7 +1347,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1347 | bf_set(pde6_ai, pde6, 1); | 1347 | bf_set(pde6_ai, pde6, 1); |
1348 | bf_set(pde6_apptagval, pde6, apptagval); | 1348 | bf_set(pde6_apptagval, pde6, apptagval); |
1349 | 1349 | ||
1350 | /* Endian convertion if necessary for PDE6 */ | 1350 | /* Endianness conversion if necessary for PDE6 */ |
1351 | pde6->word0 = cpu_to_le32(pde6->word0); | 1351 | pde6->word0 = cpu_to_le32(pde6->word0); |
1352 | pde6->word1 = cpu_to_le32(pde6->word1); | 1352 | pde6->word1 = cpu_to_le32(pde6->word1); |
1353 | pde6->word2 = cpu_to_le32(pde6->word2); | 1353 | pde6->word2 = cpu_to_le32(pde6->word2); |
@@ -1459,7 +1459,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1459 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); | 1459 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); |
1460 | pde5->reftag = reftag; | 1460 | pde5->reftag = reftag; |
1461 | 1461 | ||
1462 | /* Endian convertion if necessary for PDE5 */ | 1462 | /* Endianness conversion if necessary for PDE5 */ |
1463 | pde5->word0 = cpu_to_le32(pde5->word0); | 1463 | pde5->word0 = cpu_to_le32(pde5->word0); |
1464 | pde5->reftag = cpu_to_le32(pde5->reftag); | 1464 | pde5->reftag = cpu_to_le32(pde5->reftag); |
1465 | 1465 | ||
@@ -1479,7 +1479,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1479 | bf_set(pde6_ai, pde6, 1); | 1479 | bf_set(pde6_ai, pde6, 1); |
1480 | bf_set(pde6_apptagval, pde6, apptagval); | 1480 | bf_set(pde6_apptagval, pde6, apptagval); |
1481 | 1481 | ||
1482 | /* Endian convertion if necessary for PDE6 */ | 1482 | /* Endianness conversion if necessary for PDE6 */ |
1483 | pde6->word0 = cpu_to_le32(pde6->word0); | 1483 | pde6->word0 = cpu_to_le32(pde6->word0); |
1484 | pde6->word1 = cpu_to_le32(pde6->word1); | 1484 | pde6->word1 = cpu_to_le32(pde6->word1); |
1485 | pde6->word2 = cpu_to_le32(pde6->word2); | 1485 | pde6->word2 = cpu_to_le32(pde6->word2); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e758eae0d0fd..fb8905f893f5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -1046,7 +1046,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
1046 | } else | 1046 | } else |
1047 | spin_unlock_irq(&phba->hbalock); | 1047 | spin_unlock_irq(&phba->hbalock); |
1048 | 1048 | ||
1049 | lpfc_printf_log(phba, KERN_ERR,LOG_SLI, | 1049 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, |
1050 | "0318 Failed to allocate IOTAG.last IOTAG is %d\n", | 1050 | "0318 Failed to allocate IOTAG.last IOTAG is %d\n", |
1051 | psli->last_iotag); | 1051 | psli->last_iotag); |
1052 | 1052 | ||
@@ -3914,7 +3914,8 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) | |||
3914 | phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED | | 3914 | phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED | |
3915 | LPFC_SLI3_HBQ_ENABLED | | 3915 | LPFC_SLI3_HBQ_ENABLED | |
3916 | LPFC_SLI3_CRP_ENABLED | | 3916 | LPFC_SLI3_CRP_ENABLED | |
3917 | LPFC_SLI3_BG_ENABLED); | 3917 | LPFC_SLI3_BG_ENABLED | |
3918 | LPFC_SLI3_DSS_ENABLED); | ||
3918 | if (rc != MBX_SUCCESS) { | 3919 | if (rc != MBX_SUCCESS) { |
3919 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 3920 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
3920 | "0442 Adapter failed to init, mbxCmd x%x " | 3921 | "0442 Adapter failed to init, mbxCmd x%x " |
@@ -3949,8 +3950,23 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) | |||
3949 | 3950 | ||
3950 | } else | 3951 | } else |
3951 | phba->max_vpi = 0; | 3952 | phba->max_vpi = 0; |
3952 | if (pmb->u.mb.un.varCfgPort.gdss) | 3953 | phba->fips_level = 0; |
3954 | phba->fips_spec_rev = 0; | ||
3955 | if (pmb->u.mb.un.varCfgPort.gdss) { | ||
3953 | phba->sli3_options |= LPFC_SLI3_DSS_ENABLED; | 3956 | phba->sli3_options |= LPFC_SLI3_DSS_ENABLED; |
3957 | phba->fips_level = pmb->u.mb.un.varCfgPort.fips_level; | ||
3958 | phba->fips_spec_rev = pmb->u.mb.un.varCfgPort.fips_rev; | ||
3959 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
3960 | "2850 Security Crypto Active. FIPS x%d " | ||
3961 | "(Spec Rev: x%d)", | ||
3962 | phba->fips_level, phba->fips_spec_rev); | ||
3963 | } | ||
3964 | if (pmb->u.mb.un.varCfgPort.sec_err) { | ||
3965 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
3966 | "2856 Config Port Security Crypto " | ||
3967 | "Error: x%x ", | ||
3968 | pmb->u.mb.un.varCfgPort.sec_err); | ||
3969 | } | ||
3954 | if (pmb->u.mb.un.varCfgPort.gerbm) | 3970 | if (pmb->u.mb.un.varCfgPort.gerbm) |
3955 | phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED; | 3971 | phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED; |
3956 | if (pmb->u.mb.un.varCfgPort.gcrp) | 3972 | if (pmb->u.mb.un.varCfgPort.gcrp) |
@@ -9040,6 +9056,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
9040 | switch (bf_get(lpfc_cqe_code, &cqevt)) { | 9056 | switch (bf_get(lpfc_cqe_code, &cqevt)) { |
9041 | case CQE_CODE_COMPL_WQE: | 9057 | case CQE_CODE_COMPL_WQE: |
9042 | /* Process the WQ/RQ complete event */ | 9058 | /* Process the WQ/RQ complete event */ |
9059 | phba->last_completion_time = jiffies; | ||
9043 | workposted = lpfc_sli4_sp_handle_els_wcqe(phba, | 9060 | workposted = lpfc_sli4_sp_handle_els_wcqe(phba, |
9044 | (struct lpfc_wcqe_complete *)&cqevt); | 9061 | (struct lpfc_wcqe_complete *)&cqevt); |
9045 | break; | 9062 | break; |
@@ -9050,11 +9067,13 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
9050 | break; | 9067 | break; |
9051 | case CQE_CODE_XRI_ABORTED: | 9068 | case CQE_CODE_XRI_ABORTED: |
9052 | /* Process the WQ XRI abort event */ | 9069 | /* Process the WQ XRI abort event */ |
9070 | phba->last_completion_time = jiffies; | ||
9053 | workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, | 9071 | workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, |
9054 | (struct sli4_wcqe_xri_aborted *)&cqevt); | 9072 | (struct sli4_wcqe_xri_aborted *)&cqevt); |
9055 | break; | 9073 | break; |
9056 | case CQE_CODE_RECEIVE: | 9074 | case CQE_CODE_RECEIVE: |
9057 | /* Process the RQ event */ | 9075 | /* Process the RQ event */ |
9076 | phba->last_completion_time = jiffies; | ||
9058 | workposted = lpfc_sli4_sp_handle_rcqe(phba, | 9077 | workposted = lpfc_sli4_sp_handle_rcqe(phba, |
9059 | (struct lpfc_rcqe *)&cqevt); | 9078 | (struct lpfc_rcqe *)&cqevt); |
9060 | break; | 9079 | break; |
@@ -9276,7 +9295,6 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
9276 | { | 9295 | { |
9277 | struct lpfc_wcqe_release wcqe; | 9296 | struct lpfc_wcqe_release wcqe; |
9278 | bool workposted = false; | 9297 | bool workposted = false; |
9279 | unsigned long iflag; | ||
9280 | 9298 | ||
9281 | /* Copy the work queue CQE and convert endian order if needed */ | 9299 | /* Copy the work queue CQE and convert endian order if needed */ |
9282 | lpfc_sli_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe)); | 9300 | lpfc_sli_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe)); |
@@ -9285,9 +9303,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
9285 | switch (bf_get(lpfc_wcqe_c_code, &wcqe)) { | 9303 | switch (bf_get(lpfc_wcqe_c_code, &wcqe)) { |
9286 | case CQE_CODE_COMPL_WQE: | 9304 | case CQE_CODE_COMPL_WQE: |
9287 | /* Process the WQ complete event */ | 9305 | /* Process the WQ complete event */ |
9288 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
9289 | phba->last_completion_time = jiffies; | 9306 | phba->last_completion_time = jiffies; |
9290 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
9291 | lpfc_sli4_fp_handle_fcp_wcqe(phba, | 9307 | lpfc_sli4_fp_handle_fcp_wcqe(phba, |
9292 | (struct lpfc_wcqe_complete *)&wcqe); | 9308 | (struct lpfc_wcqe_complete *)&wcqe); |
9293 | break; | 9309 | break; |
@@ -9298,6 +9314,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
9298 | break; | 9314 | break; |
9299 | case CQE_CODE_XRI_ABORTED: | 9315 | case CQE_CODE_XRI_ABORTED: |
9300 | /* Process the WQ XRI abort event */ | 9316 | /* Process the WQ XRI abort event */ |
9317 | phba->last_completion_time = jiffies; | ||
9301 | workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, | 9318 | workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, |
9302 | (struct sli4_wcqe_xri_aborted *)&wcqe); | 9319 | (struct sli4_wcqe_xri_aborted *)&wcqe); |
9303 | break; | 9320 | break; |
@@ -12278,12 +12295,9 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) | |||
12278 | spin_lock_irq(&phba->hbalock); | 12295 | spin_lock_irq(&phba->hbalock); |
12279 | phba->hba_flag |= FCF_DISC_INPROGRESS; | 12296 | phba->hba_flag |= FCF_DISC_INPROGRESS; |
12280 | spin_unlock_irq(&phba->hbalock); | 12297 | spin_unlock_irq(&phba->hbalock); |
12281 | /* Reset FCF round robin index bmask for new scan */ | 12298 | /* Reset eligible FCF count for new scan */ |
12282 | if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) { | 12299 | if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) |
12283 | memset(phba->fcf.fcf_rr_bmask, 0, | ||
12284 | sizeof(*phba->fcf.fcf_rr_bmask)); | ||
12285 | phba->fcf.eligible_fcf_cnt = 0; | 12300 | phba->fcf.eligible_fcf_cnt = 0; |
12286 | } | ||
12287 | error = 0; | 12301 | error = 0; |
12288 | } | 12302 | } |
12289 | fail_fcf_scan: | 12303 | fail_fcf_scan: |
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index d28830af71d8..61afb3420a96 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h | |||
@@ -18,7 +18,7 @@ | |||
18 | * included with this package. * | 18 | * included with this package. * |
19 | *******************************************************************/ | 19 | *******************************************************************/ |
20 | 20 | ||
21 | #define LPFC_DRIVER_VERSION "8.3.15" | 21 | #define LPFC_DRIVER_VERSION "8.3.16" |
22 | #define LPFC_DRIVER_NAME "lpfc" | 22 | #define LPFC_DRIVER_NAME "lpfc" |
23 | #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" | 23 | #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" |
24 | #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" | 24 | #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" |
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 58d1134935ef..9793aa6afb10 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -4199,8 +4199,10 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
4199 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4199 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
4200 | memset(&nvmd_req, 0, sizeof(nvmd_req)); | 4200 | memset(&nvmd_req, 0, sizeof(nvmd_req)); |
4201 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4201 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
4202 | if (rc) | 4202 | if (rc) { |
4203 | kfree(fw_control_context); | ||
4203 | return rc; | 4204 | return rc; |
4205 | } | ||
4204 | ccb = &pm8001_ha->ccb_info[tag]; | 4206 | ccb = &pm8001_ha->ccb_info[tag]; |
4205 | ccb->ccb_tag = tag; | 4207 | ccb->ccb_tag = tag; |
4206 | ccb->fw_control_context = fw_control_context; | 4208 | ccb->fw_control_context = fw_control_context; |
@@ -4276,8 +4278,10 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
4276 | ioctl_payload->length); | 4278 | ioctl_payload->length); |
4277 | memset(&nvmd_req, 0, sizeof(nvmd_req)); | 4279 | memset(&nvmd_req, 0, sizeof(nvmd_req)); |
4278 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4280 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
4279 | if (rc) | 4281 | if (rc) { |
4282 | kfree(fw_control_context); | ||
4280 | return rc; | 4283 | return rc; |
4284 | } | ||
4281 | ccb = &pm8001_ha->ccb_info[tag]; | 4285 | ccb = &pm8001_ha->ccb_info[tag]; |
4282 | ccb->fw_control_context = fw_control_context; | 4286 | ccb->fw_control_context = fw_control_context; |
4283 | ccb->ccb_tag = tag; | 4287 | ccb->ccb_tag = tag; |
@@ -4387,6 +4391,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
4387 | fw_control->len, 0) != 0) { | 4391 | fw_control->len, 0) != 0) { |
4388 | PM8001_FAIL_DBG(pm8001_ha, | 4392 | PM8001_FAIL_DBG(pm8001_ha, |
4389 | pm8001_printk("Mem alloc failure\n")); | 4393 | pm8001_printk("Mem alloc failure\n")); |
4394 | kfree(fw_control_context); | ||
4390 | return -ENOMEM; | 4395 | return -ENOMEM; |
4391 | } | 4396 | } |
4392 | } | 4397 | } |
@@ -4401,8 +4406,10 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
4401 | fw_control_context->virtAddr = buffer; | 4406 | fw_control_context->virtAddr = buffer; |
4402 | fw_control_context->len = fw_control->len; | 4407 | fw_control_context->len = fw_control->len; |
4403 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4408 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
4404 | if (rc) | 4409 | if (rc) { |
4410 | kfree(fw_control_context); | ||
4405 | return rc; | 4411 | return rc; |
4412 | } | ||
4406 | ccb = &pm8001_ha->ccb_info[tag]; | 4413 | ccb = &pm8001_ha->ccb_info[tag]; |
4407 | ccb->fw_control_context = fw_control_context; | 4414 | ccb->fw_control_context = fw_control_context; |
4408 | ccb->ccb_tag = tag; | 4415 | ccb->ccb_tag = tag; |
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index a79da8dd2064..9dc0a6616edd 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -36,6 +36,24 @@ | |||
36 | #include "ql4_dbg.h" | 36 | #include "ql4_dbg.h" |
37 | #include "ql4_nx.h" | 37 | #include "ql4_nx.h" |
38 | 38 | ||
39 | #if defined(CONFIG_PCIEAER) | ||
40 | #include <linux/aer.h> | ||
41 | #else | ||
42 | /* AER releated */ | ||
43 | static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) | ||
44 | { | ||
45 | return -EINVAL; | ||
46 | } | ||
47 | static inline int pci_disable_pcie_error_reporting(struct pci_dev *dev) | ||
48 | { | ||
49 | return -EINVAL; | ||
50 | } | ||
51 | static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) | ||
52 | { | ||
53 | return -EINVAL; | ||
54 | } | ||
55 | #endif | ||
56 | |||
39 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP4010 | 57 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP4010 |
40 | #define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010 | 58 | #define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010 |
41 | #endif | 59 | #endif |
@@ -137,6 +155,9 @@ | |||
137 | #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ | 155 | #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ |
138 | #define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ | 156 | #define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ |
139 | 157 | ||
158 | #define QL4_SESS_RECOVERY_TMO 30 /* iSCSI session */ | ||
159 | /* recovery timeout */ | ||
160 | |||
140 | #define LSDW(x) ((u32)((u64)(x))) | 161 | #define LSDW(x) ((u32)((u64)(x))) |
141 | #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) | 162 | #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) |
142 | 163 | ||
@@ -249,7 +270,6 @@ struct ddb_entry { | |||
249 | uint32_t default_time2wait; /* Default Min time between | 270 | uint32_t default_time2wait; /* Default Min time between |
250 | * relogins (+aens) */ | 271 | * relogins (+aens) */ |
251 | 272 | ||
252 | atomic_t port_down_timer; /* Device connection timer */ | ||
253 | atomic_t retry_relogin_timer; /* Min Time between relogins | 273 | atomic_t retry_relogin_timer; /* Min Time between relogins |
254 | * (4000 only) */ | 274 | * (4000 only) */ |
255 | atomic_t relogin_timer; /* Max Time to wait for relogin to complete */ | 275 | atomic_t relogin_timer; /* Max Time to wait for relogin to complete */ |
@@ -378,7 +398,9 @@ struct scsi_qla_host { | |||
378 | #define AF_MSI_ENABLED 16 /* 0x00010000 */ | 398 | #define AF_MSI_ENABLED 16 /* 0x00010000 */ |
379 | #define AF_MSIX_ENABLED 17 /* 0x00020000 */ | 399 | #define AF_MSIX_ENABLED 17 /* 0x00020000 */ |
380 | #define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ | 400 | #define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ |
381 | 401 | #define AF_FW_RECOVERY 19 /* 0x00080000 */ | |
402 | #define AF_EEH_BUSY 20 /* 0x00100000 */ | ||
403 | #define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ | ||
382 | 404 | ||
383 | unsigned long dpc_flags; | 405 | unsigned long dpc_flags; |
384 | 406 | ||
@@ -474,7 +496,6 @@ struct scsi_qla_host { | |||
474 | uint32_t timer_active; | 496 | uint32_t timer_active; |
475 | 497 | ||
476 | /* Recovery Timers */ | 498 | /* Recovery Timers */ |
477 | uint32_t port_down_retry_count; | ||
478 | uint32_t discovery_wait; | 499 | uint32_t discovery_wait; |
479 | atomic_t check_relogin_timeouts; | 500 | atomic_t check_relogin_timeouts; |
480 | uint32_t retry_reset_ha_cnt; | 501 | uint32_t retry_reset_ha_cnt; |
@@ -615,6 +636,15 @@ static inline int is_qla8022(struct scsi_qla_host *ha) | |||
615 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; | 636 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; |
616 | } | 637 | } |
617 | 638 | ||
639 | /* Note: Currently AER/EEH is now supported only for 8022 cards | ||
640 | * This function needs to be updated when AER/EEH is enabled | ||
641 | * for other cards. | ||
642 | */ | ||
643 | static inline int is_aer_supported(struct scsi_qla_host *ha) | ||
644 | { | ||
645 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; | ||
646 | } | ||
647 | |||
618 | static inline int adapter_up(struct scsi_qla_host *ha) | 648 | static inline int adapter_up(struct scsi_qla_host *ha) |
619 | { | 649 | { |
620 | return (test_bit(AF_ONLINE, &ha->flags) != 0) && | 650 | return (test_bit(AF_ONLINE, &ha->flags) != 0) && |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index c94c9ddfb3a6..0336c6db8cb3 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -673,17 +673,17 @@ struct flash_sys_info { | |||
673 | }; /* 200 */ | 673 | }; /* 200 */ |
674 | 674 | ||
675 | struct mbx_sys_info { | 675 | struct mbx_sys_info { |
676 | uint8_t board_id_str[16]; /* Keep board ID string first */ | 676 | uint8_t board_id_str[16]; /* 0-f Keep board ID string first */ |
677 | /* in this structure for GUI. */ | 677 | /* in this structure for GUI. */ |
678 | uint16_t board_id; /* board ID code */ | 678 | uint16_t board_id; /* 10-11 board ID code */ |
679 | uint16_t phys_port_cnt; /* number of physical network ports */ | 679 | uint16_t phys_port_cnt; /* 12-13 number of physical network ports */ |
680 | uint16_t port_num; /* network port for this PCI function */ | 680 | uint16_t port_num; /* 14-15 network port for this PCI function */ |
681 | /* (port 0 is first port) */ | 681 | /* (port 0 is first port) */ |
682 | uint8_t mac_addr[6]; /* MAC address for this PCI function */ | 682 | uint8_t mac_addr[6]; /* 16-1b MAC address for this PCI function */ |
683 | uint32_t iscsi_pci_func_cnt; /* number of iSCSI PCI functions */ | 683 | uint32_t iscsi_pci_func_cnt; /* 1c-1f number of iSCSI PCI functions */ |
684 | uint32_t pci_func; /* this PCI function */ | 684 | uint32_t pci_func; /* 20-23 this PCI function */ |
685 | unsigned char serial_number[16]; /* serial number string */ | 685 | unsigned char serial_number[16]; /* 24-33 serial number string */ |
686 | uint8_t reserved[16]; | 686 | uint8_t reserved[12]; /* 34-3f */ |
687 | }; | 687 | }; |
688 | 688 | ||
689 | struct crash_record { | 689 | struct crash_record { |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index c9cd5d6db982..f065204e401b 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -93,6 +93,7 @@ void qla4xxx_free_irqs(struct scsi_qla_host *ha); | |||
93 | void qla4xxx_process_response_queue(struct scsi_qla_host *ha); | 93 | void qla4xxx_process_response_queue(struct scsi_qla_host *ha); |
94 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha); | 94 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha); |
95 | void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha); | 95 | void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha); |
96 | void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha); | ||
96 | 97 | ||
97 | void qla4_8xxx_pci_config(struct scsi_qla_host *); | 98 | void qla4_8xxx_pci_config(struct scsi_qla_host *); |
98 | int qla4_8xxx_iospace_config(struct scsi_qla_host *ha); | 99 | int qla4_8xxx_iospace_config(struct scsi_qla_host *ha); |
@@ -131,6 +132,7 @@ void qla4_8xxx_idc_unlock(struct scsi_qla_host *ha); | |||
131 | int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha); | 132 | int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha); |
132 | void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha); | 133 | void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha); |
133 | void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha); | 134 | void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha); |
135 | inline void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha); | ||
134 | 136 | ||
135 | extern int ql4xextended_error_logging; | 137 | extern int ql4xextended_error_logging; |
136 | extern int ql4xdiscoverywait; | 138 | extern int ql4xdiscoverywait; |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 30073577c3a4..4c9be77ee70b 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -308,7 +308,6 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) | |||
308 | DEBUG2(printk("scsi%ld: %s: unable to get firmware " | 308 | DEBUG2(printk("scsi%ld: %s: unable to get firmware " |
309 | "state\n", ha->host_no, __func__)); | 309 | "state\n", ha->host_no, __func__)); |
310 | break; | 310 | break; |
311 | |||
312 | } | 311 | } |
313 | 312 | ||
314 | if (ha->firmware_state & FW_STATE_ERROR) { | 313 | if (ha->firmware_state & FW_STATE_ERROR) { |
@@ -445,6 +444,16 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha) | |||
445 | { | 444 | { |
446 | int status = QLA_ERROR; | 445 | int status = QLA_ERROR; |
447 | 446 | ||
447 | if (is_aer_supported(ha) && | ||
448 | test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) | ||
449 | return status; | ||
450 | |||
451 | /* For 82xx, stop firmware before initializing because if BIOS | ||
452 | * has previously initialized firmware, then driver's initialize | ||
453 | * firmware will fail. */ | ||
454 | if (is_qla8022(ha)) | ||
455 | qla4_8xxx_stop_firmware(ha); | ||
456 | |||
448 | ql4_printk(KERN_INFO, ha, "Initializing firmware..\n"); | 457 | ql4_printk(KERN_INFO, ha, "Initializing firmware..\n"); |
449 | if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) { | 458 | if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) { |
450 | DEBUG2(printk("scsi%ld: %s: Failed to initialize firmware " | 459 | DEBUG2(printk("scsi%ld: %s: Failed to initialize firmware " |
@@ -669,7 +678,6 @@ static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, | |||
669 | } | 678 | } |
670 | 679 | ||
671 | ddb_entry->fw_ddb_index = fw_ddb_index; | 680 | ddb_entry->fw_ddb_index = fw_ddb_index; |
672 | atomic_set(&ddb_entry->port_down_timer, ha->port_down_retry_count); | ||
673 | atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); | 681 | atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); |
674 | atomic_set(&ddb_entry->relogin_timer, 0); | 682 | atomic_set(&ddb_entry->relogin_timer, 0); |
675 | atomic_set(&ddb_entry->relogin_retry_count, 0); | 683 | atomic_set(&ddb_entry->relogin_retry_count, 0); |
@@ -1556,8 +1564,6 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
1556 | /* Device is back online. */ | 1564 | /* Device is back online. */ |
1557 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { | 1565 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { |
1558 | atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); | 1566 | atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); |
1559 | atomic_set(&ddb_entry->port_down_timer, | ||
1560 | ha->port_down_retry_count); | ||
1561 | atomic_set(&ddb_entry->relogin_retry_count, 0); | 1567 | atomic_set(&ddb_entry->relogin_retry_count, 0); |
1562 | atomic_set(&ddb_entry->relogin_timer, 0); | 1568 | atomic_set(&ddb_entry->relogin_timer, 0); |
1563 | clear_bit(DF_RELOGIN, &ddb_entry->flags); | 1569 | clear_bit(DF_RELOGIN, &ddb_entry->flags); |
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index f89973deac5b..4ef9ba112ee8 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c | |||
@@ -19,7 +19,7 @@ qla4xxx_space_in_req_ring(struct scsi_qla_host *ha, uint16_t req_cnt) | |||
19 | 19 | ||
20 | /* Calculate number of free request entries. */ | 20 | /* Calculate number of free request entries. */ |
21 | if ((req_cnt + 2) >= ha->req_q_count) { | 21 | if ((req_cnt + 2) >= ha->req_q_count) { |
22 | cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); | 22 | cnt = (uint16_t) ha->isp_ops->rd_shdw_req_q_out(ha); |
23 | if (ha->request_in < cnt) | 23 | if (ha->request_in < cnt) |
24 | ha->req_q_count = cnt - ha->request_in; | 24 | ha->req_q_count = cnt - ha->request_in; |
25 | else | 25 | else |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index aa65697a86b4..2a1ab63f3eb0 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -816,6 +816,9 @@ irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id) | |||
816 | unsigned long flags = 0; | 816 | unsigned long flags = 0; |
817 | uint8_t reqs_count = 0; | 817 | uint8_t reqs_count = 0; |
818 | 818 | ||
819 | if (unlikely(pci_channel_offline(ha->pdev))) | ||
820 | return IRQ_HANDLED; | ||
821 | |||
819 | ha->isr_count++; | 822 | ha->isr_count++; |
820 | status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); | 823 | status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); |
821 | if (!(status & ha->nx_legacy_intr.int_vec_bit)) | 824 | if (!(status & ha->nx_legacy_intr.int_vec_bit)) |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 940ee561ee0a..90021704d8ca 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -39,6 +39,22 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
39 | "pointer\n", ha->host_no, __func__)); | 39 | "pointer\n", ha->host_no, __func__)); |
40 | return status; | 40 | return status; |
41 | } | 41 | } |
42 | |||
43 | if (is_qla8022(ha) && | ||
44 | test_bit(AF_FW_RECOVERY, &ha->flags)) { | ||
45 | DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: prematurely " | ||
46 | "completing mbx cmd as firmware recovery detected\n", | ||
47 | ha->host_no, __func__)); | ||
48 | return status; | ||
49 | } | ||
50 | |||
51 | if ((is_aer_supported(ha)) && | ||
52 | (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { | ||
53 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " | ||
54 | "timeout MBX Exiting.\n", ha->host_no, __func__)); | ||
55 | return status; | ||
56 | } | ||
57 | |||
42 | /* Mailbox code active */ | 58 | /* Mailbox code active */ |
43 | wait_count = MBOX_TOV * 100; | 59 | wait_count = MBOX_TOV * 100; |
44 | 60 | ||
@@ -150,6 +166,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
150 | while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { | 166 | while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { |
151 | if (time_after_eq(jiffies, wait_count)) | 167 | if (time_after_eq(jiffies, wait_count)) |
152 | break; | 168 | break; |
169 | |||
153 | /* | 170 | /* |
154 | * Service the interrupt. | 171 | * Service the interrupt. |
155 | * The ISR will save the mailbox status registers | 172 | * The ISR will save the mailbox status registers |
@@ -196,6 +213,14 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
196 | 213 | ||
197 | /* Check for mailbox timeout. */ | 214 | /* Check for mailbox timeout. */ |
198 | if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { | 215 | if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { |
216 | if (is_qla8022(ha) && | ||
217 | test_bit(AF_FW_RECOVERY, &ha->flags)) { | ||
218 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
219 | "scsi%ld: %s: prematurely completing mbx cmd as " | ||
220 | "firmware recovery detected\n", | ||
221 | ha->host_no, __func__)); | ||
222 | goto mbox_exit; | ||
223 | } | ||
199 | DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...," | 224 | DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...," |
200 | " Scheduling Adapter Reset\n", ha->host_no, | 225 | " Scheduling Adapter Reset\n", ha->host_no, |
201 | mbx_cmd[0])); | 226 | mbx_cmd[0])); |
@@ -246,6 +271,28 @@ mbox_exit: | |||
246 | return status; | 271 | return status; |
247 | } | 272 | } |
248 | 273 | ||
274 | void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) | ||
275 | { | ||
276 | set_bit(AF_FW_RECOVERY, &ha->flags); | ||
277 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n", | ||
278 | ha->host_no, __func__); | ||
279 | |||
280 | if (test_bit(AF_MBOX_COMMAND, &ha->flags)) { | ||
281 | if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) { | ||
282 | complete(&ha->mbx_intr_comp); | ||
283 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " | ||
284 | "recovery, doing premature completion of " | ||
285 | "mbx cmd\n", ha->host_no, __func__); | ||
286 | |||
287 | } else { | ||
288 | set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); | ||
289 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " | ||
290 | "recovery, doing premature completion of " | ||
291 | "polling mbx cmd\n", ha->host_no, __func__); | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
249 | static uint8_t | 296 | static uint8_t |
250 | qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, | 297 | qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, |
251 | uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) | 298 | uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) |
@@ -361,7 +408,6 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, | |||
361 | min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ | 408 | min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ |
362 | 409 | ||
363 | /* Save Command Line Paramater info */ | 410 | /* Save Command Line Paramater info */ |
364 | ha->port_down_retry_count = le16_to_cpu(init_fw_cb->conn_ka_timeout); | ||
365 | ha->discovery_wait = ql4xdiscoverywait; | 411 | ha->discovery_wait = ql4xdiscoverywait; |
366 | 412 | ||
367 | if (ha->acb_version == ACB_SUPPORTED) { | 413 | if (ha->acb_version == ACB_SUPPORTED) { |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 3e119ae78397..e031a734836e 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -1418,7 +1418,7 @@ static int qla4_8xxx_rcvpeg_ready(struct scsi_qla_host *ha) | |||
1418 | return QLA_SUCCESS; | 1418 | return QLA_SUCCESS; |
1419 | } | 1419 | } |
1420 | 1420 | ||
1421 | static inline void | 1421 | inline void |
1422 | qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) | 1422 | qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) |
1423 | { | 1423 | { |
1424 | uint32_t drv_active; | 1424 | uint32_t drv_active; |
@@ -1441,11 +1441,15 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) | |||
1441 | static inline int | 1441 | static inline int |
1442 | qla4_8xxx_need_reset(struct scsi_qla_host *ha) | 1442 | qla4_8xxx_need_reset(struct scsi_qla_host *ha) |
1443 | { | 1443 | { |
1444 | uint32_t drv_state; | 1444 | uint32_t drv_state, drv_active; |
1445 | int rval; | 1445 | int rval; |
1446 | 1446 | ||
1447 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
1447 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | 1448 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); |
1448 | rval = drv_state & (1 << (ha->func_num * 4)); | 1449 | rval = drv_state & (1 << (ha->func_num * 4)); |
1450 | if ((test_bit(AF_EEH_BUSY, &ha->flags)) && drv_active) | ||
1451 | rval = 1; | ||
1452 | |||
1449 | return rval; | 1453 | return rval; |
1450 | } | 1454 | } |
1451 | 1455 | ||
@@ -1949,7 +1953,8 @@ qla4_8xxx_get_fdt_info(struct scsi_qla_host *ha) | |||
1949 | uint16_t cnt, chksum; | 1953 | uint16_t cnt, chksum; |
1950 | uint16_t *wptr; | 1954 | uint16_t *wptr; |
1951 | struct qla_fdt_layout *fdt; | 1955 | struct qla_fdt_layout *fdt; |
1952 | uint16_t mid, fid; | 1956 | uint16_t mid = 0; |
1957 | uint16_t fid = 0; | ||
1953 | struct ql82xx_hw_data *hw = &ha->hw; | 1958 | struct ql82xx_hw_data *hw = &ha->hw; |
1954 | 1959 | ||
1955 | hw->flash_conf_off = FARX_ACCESS_FLASH_CONF; | 1960 | hw->flash_conf_off = FARX_ACCESS_FLASH_CONF; |
@@ -2105,6 +2110,9 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) | |||
2105 | qla4_8xxx_clear_rst_ready(ha); | 2110 | qla4_8xxx_clear_rst_ready(ha); |
2106 | qla4_8xxx_idc_unlock(ha); | 2111 | qla4_8xxx_idc_unlock(ha); |
2107 | 2112 | ||
2113 | if (rval == QLA_SUCCESS) | ||
2114 | clear_bit(AF_FW_RECOVERY, &ha->flags); | ||
2115 | |||
2108 | return rval; | 2116 | return rval; |
2109 | } | 2117 | } |
2110 | 2118 | ||
@@ -2145,7 +2153,8 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha) | |||
2145 | goto exit_validate_mac82; | 2153 | goto exit_validate_mac82; |
2146 | } | 2154 | } |
2147 | 2155 | ||
2148 | if (mbox_sts[4] < sizeof(*sys_info)) { | 2156 | /* Make sure we receive the minimum required data to cache internally */ |
2157 | if (mbox_sts[4] < offsetof(struct mbx_sys_info, reserved)) { | ||
2149 | DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive" | 2158 | DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive" |
2150 | " error (%x)\n", ha->host_no, __func__, mbox_sts[4])); | 2159 | " error (%x)\n", ha->host_no, __func__, mbox_sts[4])); |
2151 | goto exit_validate_mac82; | 2160 | goto exit_validate_mac82; |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 5529b2a39741..370d40ff1529 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -163,10 +163,10 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) | |||
163 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { | 163 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { |
164 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); | 164 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); |
165 | 165 | ||
166 | DEBUG2(printk("scsi%ld: %s: ddb [%d] port down retry count " | 166 | DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout " |
167 | "of (%d) secs exhausted, marking device DEAD.\n", | 167 | "of (%d) secs exhausted, marking device DEAD.\n", |
168 | ha->host_no, __func__, ddb_entry->fw_ddb_index, | 168 | ha->host_no, __func__, ddb_entry->fw_ddb_index, |
169 | ha->port_down_retry_count)); | 169 | QL4_SESS_RECOVERY_TMO)); |
170 | 170 | ||
171 | qla4xxx_wake_dpc(ha); | 171 | qla4xxx_wake_dpc(ha); |
172 | } | 172 | } |
@@ -298,7 +298,8 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry) | |||
298 | { | 298 | { |
299 | int err; | 299 | int err; |
300 | 300 | ||
301 | ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count; | 301 | ddb_entry->sess->recovery_tmo = QL4_SESS_RECOVERY_TMO; |
302 | |||
302 | err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index); | 303 | err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index); |
303 | if (err) { | 304 | if (err) { |
304 | DEBUG2(printk(KERN_ERR "Could not add session.\n")); | 305 | DEBUG2(printk(KERN_ERR "Could not add session.\n")); |
@@ -474,6 +475,14 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, | |||
474 | struct srb *srb; | 475 | struct srb *srb; |
475 | int rval; | 476 | int rval; |
476 | 477 | ||
478 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { | ||
479 | if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) | ||
480 | cmd->result = DID_NO_CONNECT << 16; | ||
481 | else | ||
482 | cmd->result = DID_REQUEUE << 16; | ||
483 | goto qc_fail_command; | ||
484 | } | ||
485 | |||
477 | if (!sess) { | 486 | if (!sess) { |
478 | cmd->result = DID_IMM_RETRY << 16; | 487 | cmd->result = DID_IMM_RETRY << 16; |
479 | goto qc_fail_command; | 488 | goto qc_fail_command; |
@@ -654,6 +663,13 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
654 | uint32_t fw_heartbeat_counter, halt_status; | 663 | uint32_t fw_heartbeat_counter, halt_status; |
655 | 664 | ||
656 | fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | 665 | fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); |
666 | /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */ | ||
667 | if (fw_heartbeat_counter == 0xffffffff) { | ||
668 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen " | ||
669 | "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n", | ||
670 | ha->host_no, __func__)); | ||
671 | return; | ||
672 | } | ||
657 | 673 | ||
658 | if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { | 674 | if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { |
659 | ha->seconds_since_last_heartbeat++; | 675 | ha->seconds_since_last_heartbeat++; |
@@ -662,6 +678,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
662 | ha->seconds_since_last_heartbeat = 0; | 678 | ha->seconds_since_last_heartbeat = 0; |
663 | halt_status = qla4_8xxx_rd_32(ha, | 679 | halt_status = qla4_8xxx_rd_32(ha, |
664 | QLA82XX_PEG_HALT_STATUS1); | 680 | QLA82XX_PEG_HALT_STATUS1); |
681 | |||
665 | /* Since we cannot change dev_state in interrupt | 682 | /* Since we cannot change dev_state in interrupt |
666 | * context, set appropriate DPC flag then wakeup | 683 | * context, set appropriate DPC flag then wakeup |
667 | * DPC */ | 684 | * DPC */ |
@@ -673,6 +690,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
673 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 690 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
674 | } | 691 | } |
675 | qla4xxx_wake_dpc(ha); | 692 | qla4xxx_wake_dpc(ha); |
693 | qla4xxx_mailbox_premature_completion(ha); | ||
676 | } | 694 | } |
677 | } | 695 | } |
678 | ha->fw_heartbeat_counter = fw_heartbeat_counter; | 696 | ha->fw_heartbeat_counter = fw_heartbeat_counter; |
@@ -698,6 +716,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | |||
698 | ha->host_no, __func__); | 716 | ha->host_no, __func__); |
699 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 717 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
700 | qla4xxx_wake_dpc(ha); | 718 | qla4xxx_wake_dpc(ha); |
719 | qla4xxx_mailbox_premature_completion(ha); | ||
701 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && | 720 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && |
702 | !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { | 721 | !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { |
703 | printk("scsi%ld: %s: HW State: NEED QUIES!\n", | 722 | printk("scsi%ld: %s: HW State: NEED QUIES!\n", |
@@ -719,6 +738,19 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
719 | { | 738 | { |
720 | struct ddb_entry *ddb_entry, *dtemp; | 739 | struct ddb_entry *ddb_entry, *dtemp; |
721 | int start_dpc = 0; | 740 | int start_dpc = 0; |
741 | uint16_t w; | ||
742 | |||
743 | /* If we are in the middle of AER/EEH processing | ||
744 | * skip any processing and reschedule the timer | ||
745 | */ | ||
746 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { | ||
747 | mod_timer(&ha->timer, jiffies + HZ); | ||
748 | return; | ||
749 | } | ||
750 | |||
751 | /* Hardware read to trigger an EEH error during mailbox waits. */ | ||
752 | if (!pci_channel_offline(ha->pdev)) | ||
753 | pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); | ||
722 | 754 | ||
723 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { | 755 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { |
724 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", | 756 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", |
@@ -1207,7 +1239,13 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1207 | 1239 | ||
1208 | /* Initialization not yet finished. Don't do anything yet. */ | 1240 | /* Initialization not yet finished. Don't do anything yet. */ |
1209 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | 1241 | if (!test_bit(AF_INIT_DONE, &ha->flags)) |
1210 | return; | 1242 | goto do_dpc_exit; |
1243 | |||
1244 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { | ||
1245 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n", | ||
1246 | ha->host_no, __func__, ha->flags)); | ||
1247 | goto do_dpc_exit; | ||
1248 | } | ||
1211 | 1249 | ||
1212 | /* HBA is in the process of being permanently disabled. | 1250 | /* HBA is in the process of being permanently disabled. |
1213 | * Don't process anything */ | 1251 | * Don't process anything */ |
@@ -1346,6 +1384,8 @@ dpc_post_reset_ha: | |||
1346 | } | 1384 | } |
1347 | } | 1385 | } |
1348 | } | 1386 | } |
1387 | |||
1388 | do_dpc_exit: | ||
1349 | clear_bit(AF_DPC_SCHEDULED, &ha->flags); | 1389 | clear_bit(AF_DPC_SCHEDULED, &ha->flags); |
1350 | } | 1390 | } |
1351 | 1391 | ||
@@ -1612,6 +1652,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1612 | ha->host = host; | 1652 | ha->host = host; |
1613 | ha->host_no = host->host_no; | 1653 | ha->host_no = host->host_no; |
1614 | 1654 | ||
1655 | pci_enable_pcie_error_reporting(pdev); | ||
1656 | |||
1615 | /* Setup Runtime configurable options */ | 1657 | /* Setup Runtime configurable options */ |
1616 | if (is_qla8022(ha)) { | 1658 | if (is_qla8022(ha)) { |
1617 | ha->isp_ops = &qla4_8xxx_isp_ops; | 1659 | ha->isp_ops = &qla4_8xxx_isp_ops; |
@@ -1630,6 +1672,10 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1630 | ha->isp_ops = &qla4xxx_isp_ops; | 1672 | ha->isp_ops = &qla4xxx_isp_ops; |
1631 | } | 1673 | } |
1632 | 1674 | ||
1675 | /* Set EEH reset type to fundamental if required by hba */ | ||
1676 | if (is_qla8022(ha)) | ||
1677 | pdev->needs_freset = 1; | ||
1678 | |||
1633 | /* Configure PCI I/O space. */ | 1679 | /* Configure PCI I/O space. */ |
1634 | ret = ha->isp_ops->iospace_config(ha); | 1680 | ret = ha->isp_ops->iospace_config(ha); |
1635 | if (ret) | 1681 | if (ret) |
@@ -1726,6 +1772,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1726 | } | 1772 | } |
1727 | } | 1773 | } |
1728 | 1774 | ||
1775 | pci_save_state(ha->pdev); | ||
1729 | ha->isp_ops->enable_intrs(ha); | 1776 | ha->isp_ops->enable_intrs(ha); |
1730 | 1777 | ||
1731 | /* Start timer thread. */ | 1778 | /* Start timer thread. */ |
@@ -1752,6 +1799,7 @@ probe_failed: | |||
1752 | qla4xxx_free_adapter(ha); | 1799 | qla4xxx_free_adapter(ha); |
1753 | 1800 | ||
1754 | probe_failed_ioconfig: | 1801 | probe_failed_ioconfig: |
1802 | pci_disable_pcie_error_reporting(pdev); | ||
1755 | scsi_host_put(ha->host); | 1803 | scsi_host_put(ha->host); |
1756 | 1804 | ||
1757 | probe_disable_device: | 1805 | probe_disable_device: |
@@ -1781,6 +1829,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
1781 | 1829 | ||
1782 | scsi_host_put(ha->host); | 1830 | scsi_host_put(ha->host); |
1783 | 1831 | ||
1832 | pci_disable_pcie_error_reporting(pdev); | ||
1784 | pci_disable_device(pdev); | 1833 | pci_disable_device(pdev); |
1785 | pci_set_drvdata(pdev, NULL); | 1834 | pci_set_drvdata(pdev, NULL); |
1786 | } | 1835 | } |
@@ -1877,6 +1926,17 @@ static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha, | |||
1877 | int done = 0; | 1926 | int done = 0; |
1878 | struct srb *rp; | 1927 | struct srb *rp; |
1879 | uint32_t max_wait_time = EH_WAIT_CMD_TOV; | 1928 | uint32_t max_wait_time = EH_WAIT_CMD_TOV; |
1929 | int ret = SUCCESS; | ||
1930 | |||
1931 | /* Dont wait on command if PCI error is being handled | ||
1932 | * by PCI AER driver | ||
1933 | */ | ||
1934 | if (unlikely(pci_channel_offline(ha->pdev)) || | ||
1935 | (test_bit(AF_EEH_BUSY, &ha->flags))) { | ||
1936 | ql4_printk(KERN_WARNING, ha, "scsi%ld: Return from %s\n", | ||
1937 | ha->host_no, __func__); | ||
1938 | return ret; | ||
1939 | } | ||
1880 | 1940 | ||
1881 | do { | 1941 | do { |
1882 | /* Checking to see if its returned to OS */ | 1942 | /* Checking to see if its returned to OS */ |
@@ -2172,6 +2232,252 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
2172 | return return_status; | 2232 | return return_status; |
2173 | } | 2233 | } |
2174 | 2234 | ||
2235 | /* PCI AER driver recovers from all correctable errors w/o | ||
2236 | * driver intervention. For uncorrectable errors PCI AER | ||
2237 | * driver calls the following device driver's callbacks | ||
2238 | * | ||
2239 | * - Fatal Errors - link_reset | ||
2240 | * - Non-Fatal Errors - driver's pci_error_detected() which | ||
2241 | * returns CAN_RECOVER, NEED_RESET or DISCONNECT. | ||
2242 | * | ||
2243 | * PCI AER driver calls | ||
2244 | * CAN_RECOVER - driver's pci_mmio_enabled(), mmio_enabled | ||
2245 | * returns RECOVERED or NEED_RESET if fw_hung | ||
2246 | * NEED_RESET - driver's slot_reset() | ||
2247 | * DISCONNECT - device is dead & cannot recover | ||
2248 | * RECOVERED - driver's pci_resume() | ||
2249 | */ | ||
2250 | static pci_ers_result_t | ||
2251 | qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | ||
2252 | { | ||
2253 | struct scsi_qla_host *ha = pci_get_drvdata(pdev); | ||
2254 | |||
2255 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: error detected:state %x\n", | ||
2256 | ha->host_no, __func__, state); | ||
2257 | |||
2258 | if (!is_aer_supported(ha)) | ||
2259 | return PCI_ERS_RESULT_NONE; | ||
2260 | |||
2261 | switch (state) { | ||
2262 | case pci_channel_io_normal: | ||
2263 | clear_bit(AF_EEH_BUSY, &ha->flags); | ||
2264 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
2265 | case pci_channel_io_frozen: | ||
2266 | set_bit(AF_EEH_BUSY, &ha->flags); | ||
2267 | qla4xxx_mailbox_premature_completion(ha); | ||
2268 | qla4xxx_free_irqs(ha); | ||
2269 | pci_disable_device(pdev); | ||
2270 | return PCI_ERS_RESULT_NEED_RESET; | ||
2271 | case pci_channel_io_perm_failure: | ||
2272 | set_bit(AF_EEH_BUSY, &ha->flags); | ||
2273 | set_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags); | ||
2274 | qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); | ||
2275 | return PCI_ERS_RESULT_DISCONNECT; | ||
2276 | } | ||
2277 | return PCI_ERS_RESULT_NEED_RESET; | ||
2278 | } | ||
2279 | |||
2280 | /** | ||
2281 | * qla4xxx_pci_mmio_enabled() gets called if | ||
2282 | * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER | ||
2283 | * and read/write to the device still works. | ||
2284 | **/ | ||
2285 | static pci_ers_result_t | ||
2286 | qla4xxx_pci_mmio_enabled(struct pci_dev *pdev) | ||
2287 | { | ||
2288 | struct scsi_qla_host *ha = pci_get_drvdata(pdev); | ||
2289 | |||
2290 | if (!is_aer_supported(ha)) | ||
2291 | return PCI_ERS_RESULT_NONE; | ||
2292 | |||
2293 | if (test_bit(AF_FW_RECOVERY, &ha->flags)) { | ||
2294 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: firmware hang -- " | ||
2295 | "mmio_enabled\n", ha->host_no, __func__); | ||
2296 | return PCI_ERS_RESULT_NEED_RESET; | ||
2297 | } else | ||
2298 | return PCI_ERS_RESULT_RECOVERED; | ||
2299 | } | ||
2300 | |||
2301 | uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha) | ||
2302 | { | ||
2303 | uint32_t rval = QLA_ERROR; | ||
2304 | int fn; | ||
2305 | struct pci_dev *other_pdev = NULL; | ||
2306 | |||
2307 | ql4_printk(KERN_WARNING, ha, "scsi%ld: In %s\n", ha->host_no, __func__); | ||
2308 | |||
2309 | set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); | ||
2310 | |||
2311 | if (test_bit(AF_ONLINE, &ha->flags)) { | ||
2312 | clear_bit(AF_ONLINE, &ha->flags); | ||
2313 | qla4xxx_mark_all_devices_missing(ha); | ||
2314 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | ||
2315 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); | ||
2316 | } | ||
2317 | |||
2318 | fn = PCI_FUNC(ha->pdev->devfn); | ||
2319 | while (fn > 0) { | ||
2320 | fn--; | ||
2321 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Finding PCI device at " | ||
2322 | "func %x\n", ha->host_no, __func__, fn); | ||
2323 | /* Get the pci device given the domain, bus, | ||
2324 | * slot/function number */ | ||
2325 | other_pdev = | ||
2326 | pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus), | ||
2327 | ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn), | ||
2328 | fn)); | ||
2329 | |||
2330 | if (!other_pdev) | ||
2331 | continue; | ||
2332 | |||
2333 | if (atomic_read(&other_pdev->enable_cnt)) { | ||
2334 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Found PCI " | ||
2335 | "func in enabled state%x\n", ha->host_no, | ||
2336 | __func__, fn); | ||
2337 | pci_dev_put(other_pdev); | ||
2338 | break; | ||
2339 | } | ||
2340 | pci_dev_put(other_pdev); | ||
2341 | } | ||
2342 | |||
2343 | /* The first function on the card, the reset owner will | ||
2344 | * start & initialize the firmware. The other functions | ||
2345 | * on the card will reset the firmware context | ||
2346 | */ | ||
2347 | if (!fn) { | ||
2348 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn being reset " | ||
2349 | "0x%x is the owner\n", ha->host_no, __func__, | ||
2350 | ha->pdev->devfn); | ||
2351 | |||
2352 | qla4_8xxx_idc_lock(ha); | ||
2353 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
2354 | QLA82XX_DEV_COLD); | ||
2355 | |||
2356 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, | ||
2357 | QLA82XX_IDC_VERSION); | ||
2358 | |||
2359 | qla4_8xxx_idc_unlock(ha); | ||
2360 | clear_bit(AF_FW_RECOVERY, &ha->flags); | ||
2361 | rval = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); | ||
2362 | qla4_8xxx_idc_lock(ha); | ||
2363 | |||
2364 | if (rval != QLA_SUCCESS) { | ||
2365 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " | ||
2366 | "FAILED\n", ha->host_no, __func__); | ||
2367 | qla4_8xxx_clear_drv_active(ha); | ||
2368 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
2369 | QLA82XX_DEV_FAILED); | ||
2370 | } else { | ||
2371 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " | ||
2372 | "READY\n", ha->host_no, __func__); | ||
2373 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
2374 | QLA82XX_DEV_READY); | ||
2375 | /* Clear driver state register */ | ||
2376 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0); | ||
2377 | qla4_8xxx_set_drv_active(ha); | ||
2378 | ha->isp_ops->enable_intrs(ha); | ||
2379 | } | ||
2380 | qla4_8xxx_idc_unlock(ha); | ||
2381 | } else { | ||
2382 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not " | ||
2383 | "the reset owner\n", ha->host_no, __func__, | ||
2384 | ha->pdev->devfn); | ||
2385 | if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) == | ||
2386 | QLA82XX_DEV_READY)) { | ||
2387 | clear_bit(AF_FW_RECOVERY, &ha->flags); | ||
2388 | rval = qla4xxx_initialize_adapter(ha, | ||
2389 | PRESERVE_DDB_LIST); | ||
2390 | if (rval == QLA_SUCCESS) | ||
2391 | ha->isp_ops->enable_intrs(ha); | ||
2392 | qla4_8xxx_idc_lock(ha); | ||
2393 | qla4_8xxx_set_drv_active(ha); | ||
2394 | qla4_8xxx_idc_unlock(ha); | ||
2395 | } | ||
2396 | } | ||
2397 | clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); | ||
2398 | return rval; | ||
2399 | } | ||
2400 | |||
2401 | static pci_ers_result_t | ||
2402 | qla4xxx_pci_slot_reset(struct pci_dev *pdev) | ||
2403 | { | ||
2404 | pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; | ||
2405 | struct scsi_qla_host *ha = pci_get_drvdata(pdev); | ||
2406 | int rc; | ||
2407 | |||
2408 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: slot_reset\n", | ||
2409 | ha->host_no, __func__); | ||
2410 | |||
2411 | if (!is_aer_supported(ha)) | ||
2412 | return PCI_ERS_RESULT_NONE; | ||
2413 | |||
2414 | /* Restore the saved state of PCIe device - | ||
2415 | * BAR registers, PCI Config space, PCIX, MSI, | ||
2416 | * IOV states | ||
2417 | */ | ||
2418 | pci_restore_state(pdev); | ||
2419 | |||
2420 | /* pci_restore_state() clears the saved_state flag of the device | ||
2421 | * save restored state which resets saved_state flag | ||
2422 | */ | ||
2423 | pci_save_state(pdev); | ||
2424 | |||
2425 | /* Initialize device or resume if in suspended state */ | ||
2426 | rc = pci_enable_device(pdev); | ||
2427 | if (rc) { | ||
2428 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cant re-enable " | ||
2429 | "device after reset\n", ha->host_no, __func__); | ||
2430 | goto exit_slot_reset; | ||
2431 | } | ||
2432 | |||
2433 | ret = qla4xxx_request_irqs(ha); | ||
2434 | if (ret) { | ||
2435 | ql4_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d" | ||
2436 | " already in use.\n", pdev->irq); | ||
2437 | goto exit_slot_reset; | ||
2438 | } | ||
2439 | |||
2440 | if (is_qla8022(ha)) { | ||
2441 | if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) { | ||
2442 | ret = PCI_ERS_RESULT_RECOVERED; | ||
2443 | goto exit_slot_reset; | ||
2444 | } else | ||
2445 | goto exit_slot_reset; | ||
2446 | } | ||
2447 | |||
2448 | exit_slot_reset: | ||
2449 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Return=%x\n" | ||
2450 | "device after reset\n", ha->host_no, __func__, ret); | ||
2451 | return ret; | ||
2452 | } | ||
2453 | |||
2454 | static void | ||
2455 | qla4xxx_pci_resume(struct pci_dev *pdev) | ||
2456 | { | ||
2457 | struct scsi_qla_host *ha = pci_get_drvdata(pdev); | ||
2458 | int ret; | ||
2459 | |||
2460 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: pci_resume\n", | ||
2461 | ha->host_no, __func__); | ||
2462 | |||
2463 | ret = qla4xxx_wait_for_hba_online(ha); | ||
2464 | if (ret != QLA_SUCCESS) { | ||
2465 | ql4_printk(KERN_ERR, ha, "scsi%ld: %s: the device failed to " | ||
2466 | "resume I/O from slot/link_reset\n", ha->host_no, | ||
2467 | __func__); | ||
2468 | } | ||
2469 | |||
2470 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
2471 | clear_bit(AF_EEH_BUSY, &ha->flags); | ||
2472 | } | ||
2473 | |||
2474 | static struct pci_error_handlers qla4xxx_err_handler = { | ||
2475 | .error_detected = qla4xxx_pci_error_detected, | ||
2476 | .mmio_enabled = qla4xxx_pci_mmio_enabled, | ||
2477 | .slot_reset = qla4xxx_pci_slot_reset, | ||
2478 | .resume = qla4xxx_pci_resume, | ||
2479 | }; | ||
2480 | |||
2175 | static struct pci_device_id qla4xxx_pci_tbl[] = { | 2481 | static struct pci_device_id qla4xxx_pci_tbl[] = { |
2176 | { | 2482 | { |
2177 | .vendor = PCI_VENDOR_ID_QLOGIC, | 2483 | .vendor = PCI_VENDOR_ID_QLOGIC, |
@@ -2206,6 +2512,7 @@ static struct pci_driver qla4xxx_pci_driver = { | |||
2206 | .id_table = qla4xxx_pci_tbl, | 2512 | .id_table = qla4xxx_pci_tbl, |
2207 | .probe = qla4xxx_probe_adapter, | 2513 | .probe = qla4xxx_probe_adapter, |
2208 | .remove = qla4xxx_remove_adapter, | 2514 | .remove = qla4xxx_remove_adapter, |
2515 | .err_handler = &qla4xxx_err_handler, | ||
2209 | }; | 2516 | }; |
2210 | 2517 | ||
2211 | static int __init qla4xxx_module_init(void) | 2518 | static int __init qla4xxx_module_init(void) |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index c905dbd75331..a77b973f2cbc 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
@@ -5,4 +5,4 @@ | |||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k2" | 8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k3" |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index bbbc186dbc1a..1de30eb83bb0 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -473,14 +473,17 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd) | |||
473 | */ | 473 | */ |
474 | return SUCCESS; | 474 | return SUCCESS; |
475 | case RESERVATION_CONFLICT: | 475 | case RESERVATION_CONFLICT: |
476 | /* | 476 | if (scmd->cmnd[0] == TEST_UNIT_READY) |
477 | * let issuer deal with this, it could be just fine | 477 | /* it is a success, we probed the device and |
478 | */ | 478 | * found it */ |
479 | return SUCCESS; | 479 | return SUCCESS; |
480 | /* otherwise, we failed to send the command */ | ||
481 | return FAILED; | ||
480 | case QUEUE_FULL: | 482 | case QUEUE_FULL: |
481 | scsi_handle_queue_full(scmd->device); | 483 | scsi_handle_queue_full(scmd->device); |
482 | /* fall through */ | 484 | /* fall through */ |
483 | case BUSY: | 485 | case BUSY: |
486 | return NEEDS_RETRY; | ||
484 | default: | 487 | default: |
485 | return FAILED; | 488 | return FAILED; |
486 | } | 489 | } |
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 66241dd525ae..c399be979921 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c | |||
@@ -185,6 +185,7 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work) | |||
185 | dprintk("cmd %p %d %u\n", cmd, cmd->sc_data_direction, | 185 | dprintk("cmd %p %d %u\n", cmd, cmd->sc_data_direction, |
186 | rq_data_dir(cmd->request)); | 186 | rq_data_dir(cmd->request)); |
187 | scsi_unmap_user_pages(tcmd); | 187 | scsi_unmap_user_pages(tcmd); |
188 | tcmd->rq->bio = NULL; | ||
188 | scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); | 189 | scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); |
189 | } | 190 | } |
190 | 191 | ||
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index f0a1418ce660..acd35d1ebd12 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
@@ -1723,7 +1723,7 @@ static void pl022_cleanup(struct spi_device *spi) | |||
1723 | } | 1723 | } |
1724 | 1724 | ||
1725 | 1725 | ||
1726 | static int __init | 1726 | static int __devinit |
1727 | pl022_probe(struct amba_device *adev, struct amba_id *id) | 1727 | pl022_probe(struct amba_device *adev, struct amba_id *id) |
1728 | { | 1728 | { |
1729 | struct device *dev = &adev->dev; | 1729 | struct device *dev = &adev->dev; |
@@ -1838,7 +1838,7 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) | |||
1838 | return status; | 1838 | return status; |
1839 | } | 1839 | } |
1840 | 1840 | ||
1841 | static int __exit | 1841 | static int __devexit |
1842 | pl022_remove(struct amba_device *adev) | 1842 | pl022_remove(struct amba_device *adev) |
1843 | { | 1843 | { |
1844 | struct pl022 *pl022 = amba_get_drvdata(adev); | 1844 | struct pl022 *pl022 = amba_get_drvdata(adev); |
@@ -1970,7 +1970,7 @@ static struct amba_driver pl022_driver = { | |||
1970 | }, | 1970 | }, |
1971 | .id_table = pl022_ids, | 1971 | .id_table = pl022_ids, |
1972 | .probe = pl022_probe, | 1972 | .probe = pl022_probe, |
1973 | .remove = __exit_p(pl022_remove), | 1973 | .remove = __devexit_p(pl022_remove), |
1974 | .suspend = pl022_suspend, | 1974 | .suspend = pl022_suspend, |
1975 | .resume = pl022_resume, | 1975 | .resume = pl022_resume, |
1976 | }; | 1976 | }; |
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c index cddbfceb324f..77d9e7ee8b27 100644 --- a/drivers/spi/mpc512x_psc_spi.c +++ b/drivers/spi/mpc512x_psc_spi.c | |||
@@ -406,9 +406,9 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id) | |||
406 | } | 406 | } |
407 | 407 | ||
408 | /* bus_num is used only for the case dev->platform_data == NULL */ | 408 | /* bus_num is used only for the case dev->platform_data == NULL */ |
409 | static int __init mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, | 409 | static int __devinit mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, |
410 | u32 size, unsigned int irq, | 410 | u32 size, unsigned int irq, |
411 | s16 bus_num) | 411 | s16 bus_num) |
412 | { | 412 | { |
413 | struct fsl_spi_platform_data *pdata = dev->platform_data; | 413 | struct fsl_spi_platform_data *pdata = dev->platform_data; |
414 | struct mpc512x_psc_spi *mps; | 414 | struct mpc512x_psc_spi *mps; |
@@ -492,7 +492,7 @@ free_master: | |||
492 | return ret; | 492 | return ret; |
493 | } | 493 | } |
494 | 494 | ||
495 | static int __exit mpc512x_psc_spi_do_remove(struct device *dev) | 495 | static int __devexit mpc512x_psc_spi_do_remove(struct device *dev) |
496 | { | 496 | { |
497 | struct spi_master *master = dev_get_drvdata(dev); | 497 | struct spi_master *master = dev_get_drvdata(dev); |
498 | struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); | 498 | struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); |
@@ -507,8 +507,8 @@ static int __exit mpc512x_psc_spi_do_remove(struct device *dev) | |||
507 | return 0; | 507 | return 0; |
508 | } | 508 | } |
509 | 509 | ||
510 | static int __init mpc512x_psc_spi_of_probe(struct platform_device *op, | 510 | static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op, |
511 | const struct of_device_id *match) | 511 | const struct of_device_id *match) |
512 | { | 512 | { |
513 | const u32 *regaddr_p; | 513 | const u32 *regaddr_p; |
514 | u64 regaddr64, size64; | 514 | u64 regaddr64, size64; |
@@ -539,7 +539,7 @@ static int __init mpc512x_psc_spi_of_probe(struct platform_device *op, | |||
539 | irq_of_parse_and_map(op->dev.of_node, 0), id); | 539 | irq_of_parse_and_map(op->dev.of_node, 0), id); |
540 | } | 540 | } |
541 | 541 | ||
542 | static int __exit mpc512x_psc_spi_of_remove(struct platform_device *op) | 542 | static int __devexit mpc512x_psc_spi_of_remove(struct platform_device *op) |
543 | { | 543 | { |
544 | return mpc512x_psc_spi_do_remove(&op->dev); | 544 | return mpc512x_psc_spi_do_remove(&op->dev); |
545 | } | 545 | } |
@@ -553,7 +553,7 @@ MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match); | |||
553 | 553 | ||
554 | static struct of_platform_driver mpc512x_psc_spi_of_driver = { | 554 | static struct of_platform_driver mpc512x_psc_spi_of_driver = { |
555 | .probe = mpc512x_psc_spi_of_probe, | 555 | .probe = mpc512x_psc_spi_of_probe, |
556 | .remove = __exit_p(mpc512x_psc_spi_of_remove), | 556 | .remove = __devexit_p(mpc512x_psc_spi_of_remove), |
557 | .driver = { | 557 | .driver = { |
558 | .name = "mpc512x-psc-spi", | 558 | .name = "mpc512x-psc-spi", |
559 | .owner = THIS_MODULE, | 559 | .owner = THIS_MODULE, |
diff --git a/drivers/spi/omap_spi_100k.c b/drivers/spi/omap_spi_100k.c index 24668b30a52d..9bd1c92ad96e 100644 --- a/drivers/spi/omap_spi_100k.c +++ b/drivers/spi/omap_spi_100k.c | |||
@@ -141,7 +141,12 @@ static void spi100k_write_data(struct spi_master *master, int len, int data) | |||
141 | { | 141 | { |
142 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | 142 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); |
143 | 143 | ||
144 | /* write 16-bit word */ | 144 | /* write 16-bit word, shifting 8-bit data if necessary */ |
145 | if (len <= 8) { | ||
146 | data <<= 8; | ||
147 | len = 16; | ||
148 | } | ||
149 | |||
145 | spi100k_enable_clock(master); | 150 | spi100k_enable_clock(master); |
146 | writew( data , spi100k->base + SPI_TX_MSB); | 151 | writew( data , spi100k->base + SPI_TX_MSB); |
147 | 152 | ||
@@ -162,6 +167,10 @@ static int spi100k_read_data(struct spi_master *master, int len) | |||
162 | int dataH,dataL; | 167 | int dataH,dataL; |
163 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | 168 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); |
164 | 169 | ||
170 | /* Always do at least 16 bits */ | ||
171 | if (len <= 8) | ||
172 | len = 16; | ||
173 | |||
165 | spi100k_enable_clock(master); | 174 | spi100k_enable_clock(master); |
166 | writew(SPI_CTRL_SEN(0) | | 175 | writew(SPI_CTRL_SEN(0) | |
167 | SPI_CTRL_WORD_SIZE(len) | | 176 | SPI_CTRL_WORD_SIZE(len) | |
@@ -214,10 +223,6 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
214 | c = count; | 223 | c = count; |
215 | word_len = cs->word_len; | 224 | word_len = cs->word_len; |
216 | 225 | ||
217 | /* RX_ONLY mode needs dummy data in TX reg */ | ||
218 | if (xfer->tx_buf == NULL) | ||
219 | spi100k_write_data(spi->master,word_len, 0); | ||
220 | |||
221 | if (word_len <= 8) { | 226 | if (word_len <= 8) { |
222 | u8 *rx; | 227 | u8 *rx; |
223 | const u8 *tx; | 228 | const u8 *tx; |
@@ -227,9 +232,9 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
227 | do { | 232 | do { |
228 | c-=1; | 233 | c-=1; |
229 | if (xfer->tx_buf != NULL) | 234 | if (xfer->tx_buf != NULL) |
230 | spi100k_write_data(spi->master,word_len, *tx); | 235 | spi100k_write_data(spi->master, word_len, *tx++); |
231 | if (xfer->rx_buf != NULL) | 236 | if (xfer->rx_buf != NULL) |
232 | *rx = spi100k_read_data(spi->master,word_len); | 237 | *rx++ = spi100k_read_data(spi->master, word_len); |
233 | } while(c); | 238 | } while(c); |
234 | } else if (word_len <= 16) { | 239 | } else if (word_len <= 16) { |
235 | u16 *rx; | 240 | u16 *rx; |
@@ -380,10 +385,6 @@ static void omap1_spi100k_work(struct work_struct *work) | |||
380 | if (t->len) { | 385 | if (t->len) { |
381 | unsigned count; | 386 | unsigned count; |
382 | 387 | ||
383 | /* RX_ONLY mode needs dummy data in TX reg */ | ||
384 | if (t->tx_buf == NULL) | ||
385 | spi100k_write_data(spi->master, 8, 0); | ||
386 | |||
387 | count = omap1_spi100k_txrx_pio(spi, t); | 388 | count = omap1_spi100k_txrx_pio(spi, t); |
388 | m->actual_length += count; | 389 | m->actual_length += count; |
389 | 390 | ||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 1bb1b88780ce..a9e5c79ae52a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -528,6 +528,10 @@ int spi_register_master(struct spi_master *master) | |||
528 | dynamic = 1; | 528 | dynamic = 1; |
529 | } | 529 | } |
530 | 530 | ||
531 | spin_lock_init(&master->bus_lock_spinlock); | ||
532 | mutex_init(&master->bus_lock_mutex); | ||
533 | master->bus_lock_flag = 0; | ||
534 | |||
531 | /* register the device, then userspace will see it. | 535 | /* register the device, then userspace will see it. |
532 | * registration fails if the bus ID is in use. | 536 | * registration fails if the bus ID is in use. |
533 | */ | 537 | */ |
@@ -670,6 +674,35 @@ int spi_setup(struct spi_device *spi) | |||
670 | } | 674 | } |
671 | EXPORT_SYMBOL_GPL(spi_setup); | 675 | EXPORT_SYMBOL_GPL(spi_setup); |
672 | 676 | ||
677 | static int __spi_async(struct spi_device *spi, struct spi_message *message) | ||
678 | { | ||
679 | struct spi_master *master = spi->master; | ||
680 | |||
681 | /* Half-duplex links include original MicroWire, and ones with | ||
682 | * only one data pin like SPI_3WIRE (switches direction) or where | ||
683 | * either MOSI or MISO is missing. They can also be caused by | ||
684 | * software limitations. | ||
685 | */ | ||
686 | if ((master->flags & SPI_MASTER_HALF_DUPLEX) | ||
687 | || (spi->mode & SPI_3WIRE)) { | ||
688 | struct spi_transfer *xfer; | ||
689 | unsigned flags = master->flags; | ||
690 | |||
691 | list_for_each_entry(xfer, &message->transfers, transfer_list) { | ||
692 | if (xfer->rx_buf && xfer->tx_buf) | ||
693 | return -EINVAL; | ||
694 | if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf) | ||
695 | return -EINVAL; | ||
696 | if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf) | ||
697 | return -EINVAL; | ||
698 | } | ||
699 | } | ||
700 | |||
701 | message->spi = spi; | ||
702 | message->status = -EINPROGRESS; | ||
703 | return master->transfer(spi, message); | ||
704 | } | ||
705 | |||
673 | /** | 706 | /** |
674 | * spi_async - asynchronous SPI transfer | 707 | * spi_async - asynchronous SPI transfer |
675 | * @spi: device with which data will be exchanged | 708 | * @spi: device with which data will be exchanged |
@@ -702,33 +735,68 @@ EXPORT_SYMBOL_GPL(spi_setup); | |||
702 | int spi_async(struct spi_device *spi, struct spi_message *message) | 735 | int spi_async(struct spi_device *spi, struct spi_message *message) |
703 | { | 736 | { |
704 | struct spi_master *master = spi->master; | 737 | struct spi_master *master = spi->master; |
738 | int ret; | ||
739 | unsigned long flags; | ||
705 | 740 | ||
706 | /* Half-duplex links include original MicroWire, and ones with | 741 | spin_lock_irqsave(&master->bus_lock_spinlock, flags); |
707 | * only one data pin like SPI_3WIRE (switches direction) or where | ||
708 | * either MOSI or MISO is missing. They can also be caused by | ||
709 | * software limitations. | ||
710 | */ | ||
711 | if ((master->flags & SPI_MASTER_HALF_DUPLEX) | ||
712 | || (spi->mode & SPI_3WIRE)) { | ||
713 | struct spi_transfer *xfer; | ||
714 | unsigned flags = master->flags; | ||
715 | 742 | ||
716 | list_for_each_entry(xfer, &message->transfers, transfer_list) { | 743 | if (master->bus_lock_flag) |
717 | if (xfer->rx_buf && xfer->tx_buf) | 744 | ret = -EBUSY; |
718 | return -EINVAL; | 745 | else |
719 | if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf) | 746 | ret = __spi_async(spi, message); |
720 | return -EINVAL; | ||
721 | if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf) | ||
722 | return -EINVAL; | ||
723 | } | ||
724 | } | ||
725 | 747 | ||
726 | message->spi = spi; | 748 | spin_unlock_irqrestore(&master->bus_lock_spinlock, flags); |
727 | message->status = -EINPROGRESS; | 749 | |
728 | return master->transfer(spi, message); | 750 | return ret; |
729 | } | 751 | } |
730 | EXPORT_SYMBOL_GPL(spi_async); | 752 | EXPORT_SYMBOL_GPL(spi_async); |
731 | 753 | ||
754 | /** | ||
755 | * spi_async_locked - version of spi_async with exclusive bus usage | ||
756 | * @spi: device with which data will be exchanged | ||
757 | * @message: describes the data transfers, including completion callback | ||
758 | * Context: any (irqs may be blocked, etc) | ||
759 | * | ||
760 | * This call may be used in_irq and other contexts which can't sleep, | ||
761 | * as well as from task contexts which can sleep. | ||
762 | * | ||
763 | * The completion callback is invoked in a context which can't sleep. | ||
764 | * Before that invocation, the value of message->status is undefined. | ||
765 | * When the callback is issued, message->status holds either zero (to | ||
766 | * indicate complete success) or a negative error code. After that | ||
767 | * callback returns, the driver which issued the transfer request may | ||
768 | * deallocate the associated memory; it's no longer in use by any SPI | ||
769 | * core or controller driver code. | ||
770 | * | ||
771 | * Note that although all messages to a spi_device are handled in | ||
772 | * FIFO order, messages may go to different devices in other orders. | ||
773 | * Some device might be higher priority, or have various "hard" access | ||
774 | * time requirements, for example. | ||
775 | * | ||
776 | * On detection of any fault during the transfer, processing of | ||
777 | * the entire message is aborted, and the device is deselected. | ||
778 | * Until returning from the associated message completion callback, | ||
779 | * no other spi_message queued to that device will be processed. | ||
780 | * (This rule applies equally to all the synchronous transfer calls, | ||
781 | * which are wrappers around this core asynchronous primitive.) | ||
782 | */ | ||
783 | int spi_async_locked(struct spi_device *spi, struct spi_message *message) | ||
784 | { | ||
785 | struct spi_master *master = spi->master; | ||
786 | int ret; | ||
787 | unsigned long flags; | ||
788 | |||
789 | spin_lock_irqsave(&master->bus_lock_spinlock, flags); | ||
790 | |||
791 | ret = __spi_async(spi, message); | ||
792 | |||
793 | spin_unlock_irqrestore(&master->bus_lock_spinlock, flags); | ||
794 | |||
795 | return ret; | ||
796 | |||
797 | } | ||
798 | EXPORT_SYMBOL_GPL(spi_async_locked); | ||
799 | |||
732 | 800 | ||
733 | /*-------------------------------------------------------------------------*/ | 801 | /*-------------------------------------------------------------------------*/ |
734 | 802 | ||
@@ -742,6 +810,32 @@ static void spi_complete(void *arg) | |||
742 | complete(arg); | 810 | complete(arg); |
743 | } | 811 | } |
744 | 812 | ||
813 | static int __spi_sync(struct spi_device *spi, struct spi_message *message, | ||
814 | int bus_locked) | ||
815 | { | ||
816 | DECLARE_COMPLETION_ONSTACK(done); | ||
817 | int status; | ||
818 | struct spi_master *master = spi->master; | ||
819 | |||
820 | message->complete = spi_complete; | ||
821 | message->context = &done; | ||
822 | |||
823 | if (!bus_locked) | ||
824 | mutex_lock(&master->bus_lock_mutex); | ||
825 | |||
826 | status = spi_async_locked(spi, message); | ||
827 | |||
828 | if (!bus_locked) | ||
829 | mutex_unlock(&master->bus_lock_mutex); | ||
830 | |||
831 | if (status == 0) { | ||
832 | wait_for_completion(&done); | ||
833 | status = message->status; | ||
834 | } | ||
835 | message->context = NULL; | ||
836 | return status; | ||
837 | } | ||
838 | |||
745 | /** | 839 | /** |
746 | * spi_sync - blocking/synchronous SPI data transfers | 840 | * spi_sync - blocking/synchronous SPI data transfers |
747 | * @spi: device with which data will be exchanged | 841 | * @spi: device with which data will be exchanged |
@@ -765,21 +859,86 @@ static void spi_complete(void *arg) | |||
765 | */ | 859 | */ |
766 | int spi_sync(struct spi_device *spi, struct spi_message *message) | 860 | int spi_sync(struct spi_device *spi, struct spi_message *message) |
767 | { | 861 | { |
768 | DECLARE_COMPLETION_ONSTACK(done); | 862 | return __spi_sync(spi, message, 0); |
769 | int status; | ||
770 | |||
771 | message->complete = spi_complete; | ||
772 | message->context = &done; | ||
773 | status = spi_async(spi, message); | ||
774 | if (status == 0) { | ||
775 | wait_for_completion(&done); | ||
776 | status = message->status; | ||
777 | } | ||
778 | message->context = NULL; | ||
779 | return status; | ||
780 | } | 863 | } |
781 | EXPORT_SYMBOL_GPL(spi_sync); | 864 | EXPORT_SYMBOL_GPL(spi_sync); |
782 | 865 | ||
866 | /** | ||
867 | * spi_sync_locked - version of spi_sync with exclusive bus usage | ||
868 | * @spi: device with which data will be exchanged | ||
869 | * @message: describes the data transfers | ||
870 | * Context: can sleep | ||
871 | * | ||
872 | * This call may only be used from a context that may sleep. The sleep | ||
873 | * is non-interruptible, and has no timeout. Low-overhead controller | ||
874 | * drivers may DMA directly into and out of the message buffers. | ||
875 | * | ||
876 | * This call should be used by drivers that require exclusive access to the | ||
877 | * SPI bus. It has to be preceeded by a spi_bus_lock call. The SPI bus must | ||
878 | * be released by a spi_bus_unlock call when the exclusive access is over. | ||
879 | * | ||
880 | * It returns zero on success, else a negative error code. | ||
881 | */ | ||
882 | int spi_sync_locked(struct spi_device *spi, struct spi_message *message) | ||
883 | { | ||
884 | return __spi_sync(spi, message, 1); | ||
885 | } | ||
886 | EXPORT_SYMBOL_GPL(spi_sync_locked); | ||
887 | |||
888 | /** | ||
889 | * spi_bus_lock - obtain a lock for exclusive SPI bus usage | ||
890 | * @master: SPI bus master that should be locked for exclusive bus access | ||
891 | * Context: can sleep | ||
892 | * | ||
893 | * This call may only be used from a context that may sleep. The sleep | ||
894 | * is non-interruptible, and has no timeout. | ||
895 | * | ||
896 | * This call should be used by drivers that require exclusive access to the | ||
897 | * SPI bus. The SPI bus must be released by a spi_bus_unlock call when the | ||
898 | * exclusive access is over. Data transfer must be done by spi_sync_locked | ||
899 | * and spi_async_locked calls when the SPI bus lock is held. | ||
900 | * | ||
901 | * It returns zero on success, else a negative error code. | ||
902 | */ | ||
903 | int spi_bus_lock(struct spi_master *master) | ||
904 | { | ||
905 | unsigned long flags; | ||
906 | |||
907 | mutex_lock(&master->bus_lock_mutex); | ||
908 | |||
909 | spin_lock_irqsave(&master->bus_lock_spinlock, flags); | ||
910 | master->bus_lock_flag = 1; | ||
911 | spin_unlock_irqrestore(&master->bus_lock_spinlock, flags); | ||
912 | |||
913 | /* mutex remains locked until spi_bus_unlock is called */ | ||
914 | |||
915 | return 0; | ||
916 | } | ||
917 | EXPORT_SYMBOL_GPL(spi_bus_lock); | ||
918 | |||
919 | /** | ||
920 | * spi_bus_unlock - release the lock for exclusive SPI bus usage | ||
921 | * @master: SPI bus master that was locked for exclusive bus access | ||
922 | * Context: can sleep | ||
923 | * | ||
924 | * This call may only be used from a context that may sleep. The sleep | ||
925 | * is non-interruptible, and has no timeout. | ||
926 | * | ||
927 | * This call releases an SPI bus lock previously obtained by an spi_bus_lock | ||
928 | * call. | ||
929 | * | ||
930 | * It returns zero on success, else a negative error code. | ||
931 | */ | ||
932 | int spi_bus_unlock(struct spi_master *master) | ||
933 | { | ||
934 | master->bus_lock_flag = 0; | ||
935 | |||
936 | mutex_unlock(&master->bus_lock_mutex); | ||
937 | |||
938 | return 0; | ||
939 | } | ||
940 | EXPORT_SYMBOL_GPL(spi_bus_unlock); | ||
941 | |||
783 | /* portable code must never pass more than 32 bytes */ | 942 | /* portable code must never pass more than 32 bytes */ |
784 | #define SPI_BUFSIZ max(32,SMP_CACHE_BYTES) | 943 | #define SPI_BUFSIZ max(32,SMP_CACHE_BYTES) |
785 | 944 | ||
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 5265330a528f..8b55724d5f39 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c | |||
@@ -259,7 +259,6 @@ static void bitbang_work(struct work_struct *work) | |||
259 | struct spi_bitbang *bitbang = | 259 | struct spi_bitbang *bitbang = |
260 | container_of(work, struct spi_bitbang, work); | 260 | container_of(work, struct spi_bitbang, work); |
261 | unsigned long flags; | 261 | unsigned long flags; |
262 | int do_setup = -1; | ||
263 | int (*setup_transfer)(struct spi_device *, | 262 | int (*setup_transfer)(struct spi_device *, |
264 | struct spi_transfer *); | 263 | struct spi_transfer *); |
265 | 264 | ||
@@ -275,6 +274,7 @@ static void bitbang_work(struct work_struct *work) | |||
275 | unsigned tmp; | 274 | unsigned tmp; |
276 | unsigned cs_change; | 275 | unsigned cs_change; |
277 | int status; | 276 | int status; |
277 | int do_setup = -1; | ||
278 | 278 | ||
279 | m = container_of(bitbang->queue.next, struct spi_message, | 279 | m = container_of(bitbang->queue.next, struct spi_message, |
280 | queue); | 280 | queue); |
@@ -307,6 +307,8 @@ static void bitbang_work(struct work_struct *work) | |||
307 | status = setup_transfer(spi, t); | 307 | status = setup_transfer(spi, t); |
308 | if (status < 0) | 308 | if (status < 0) |
309 | break; | 309 | break; |
310 | if (do_setup == -1) | ||
311 | do_setup = 0; | ||
310 | } | 312 | } |
311 | 313 | ||
312 | /* set up default clock polarity, and activate chip; | 314 | /* set up default clock polarity, and activate chip; |
@@ -367,11 +369,6 @@ static void bitbang_work(struct work_struct *work) | |||
367 | m->status = status; | 369 | m->status = status; |
368 | m->complete(m->context); | 370 | m->complete(m->context); |
369 | 371 | ||
370 | /* restore speed and wordsize if it was overridden */ | ||
371 | if (do_setup == 1) | ||
372 | setup_transfer(spi, NULL); | ||
373 | do_setup = 0; | ||
374 | |||
375 | /* normally deactivate chipselect ... unless no error and | 372 | /* normally deactivate chipselect ... unless no error and |
376 | * cs_change has hinted that the next message will probably | 373 | * cs_change has hinted that the next message will probably |
377 | * be for this chip too. | 374 | * be for this chip too. |
diff --git a/drivers/spi/spi_bitbang_txrx.h b/drivers/spi/spi_bitbang_txrx.h index fc033bbf9180..c16bf853c3eb 100644 --- a/drivers/spi/spi_bitbang_txrx.h +++ b/drivers/spi/spi_bitbang_txrx.h | |||
@@ -44,7 +44,7 @@ | |||
44 | 44 | ||
45 | static inline u32 | 45 | static inline u32 |
46 | bitbang_txrx_be_cpha0(struct spi_device *spi, | 46 | bitbang_txrx_be_cpha0(struct spi_device *spi, |
47 | unsigned nsecs, unsigned cpol, | 47 | unsigned nsecs, unsigned cpol, unsigned flags, |
48 | u32 word, u8 bits) | 48 | u32 word, u8 bits) |
49 | { | 49 | { |
50 | /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ | 50 | /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ |
@@ -53,7 +53,8 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, | |||
53 | for (word <<= (32 - bits); likely(bits); bits--) { | 53 | for (word <<= (32 - bits); likely(bits); bits--) { |
54 | 54 | ||
55 | /* setup MSB (to slave) on trailing edge */ | 55 | /* setup MSB (to slave) on trailing edge */ |
56 | setmosi(spi, word & (1 << 31)); | 56 | if ((flags & SPI_MASTER_NO_TX) == 0) |
57 | setmosi(spi, word & (1 << 31)); | ||
57 | spidelay(nsecs); /* T(setup) */ | 58 | spidelay(nsecs); /* T(setup) */ |
58 | 59 | ||
59 | setsck(spi, !cpol); | 60 | setsck(spi, !cpol); |
@@ -61,7 +62,8 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, | |||
61 | 62 | ||
62 | /* sample MSB (from slave) on leading edge */ | 63 | /* sample MSB (from slave) on leading edge */ |
63 | word <<= 1; | 64 | word <<= 1; |
64 | word |= getmiso(spi); | 65 | if ((flags & SPI_MASTER_NO_RX) == 0) |
66 | word |= getmiso(spi); | ||
65 | setsck(spi, cpol); | 67 | setsck(spi, cpol); |
66 | } | 68 | } |
67 | return word; | 69 | return word; |
@@ -69,7 +71,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, | |||
69 | 71 | ||
70 | static inline u32 | 72 | static inline u32 |
71 | bitbang_txrx_be_cpha1(struct spi_device *spi, | 73 | bitbang_txrx_be_cpha1(struct spi_device *spi, |
72 | unsigned nsecs, unsigned cpol, | 74 | unsigned nsecs, unsigned cpol, unsigned flags, |
73 | u32 word, u8 bits) | 75 | u32 word, u8 bits) |
74 | { | 76 | { |
75 | /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ | 77 | /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ |
@@ -79,7 +81,8 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, | |||
79 | 81 | ||
80 | /* setup MSB (to slave) on leading edge */ | 82 | /* setup MSB (to slave) on leading edge */ |
81 | setsck(spi, !cpol); | 83 | setsck(spi, !cpol); |
82 | setmosi(spi, word & (1 << 31)); | 84 | if ((flags & SPI_MASTER_NO_TX) == 0) |
85 | setmosi(spi, word & (1 << 31)); | ||
83 | spidelay(nsecs); /* T(setup) */ | 86 | spidelay(nsecs); /* T(setup) */ |
84 | 87 | ||
85 | setsck(spi, cpol); | 88 | setsck(spi, cpol); |
@@ -87,7 +90,8 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, | |||
87 | 90 | ||
88 | /* sample MSB (from slave) on trailing edge */ | 91 | /* sample MSB (from slave) on trailing edge */ |
89 | word <<= 1; | 92 | word <<= 1; |
90 | word |= getmiso(spi); | 93 | if ((flags & SPI_MASTER_NO_RX) == 0) |
94 | word |= getmiso(spi); | ||
91 | } | 95 | } |
92 | return word; | 96 | return word; |
93 | } | 97 | } |
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c index 8b5281281111..0d4ceba3b590 100644 --- a/drivers/spi/spi_butterfly.c +++ b/drivers/spi/spi_butterfly.c | |||
@@ -156,7 +156,7 @@ butterfly_txrx_word_mode0(struct spi_device *spi, | |||
156 | unsigned nsecs, | 156 | unsigned nsecs, |
157 | u32 word, u8 bits) | 157 | u32 word, u8 bits) |
158 | { | 158 | { |
159 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | 159 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); |
160 | } | 160 | } |
161 | 161 | ||
162 | /*----------------------------------------------------------------------*/ | 162 | /*----------------------------------------------------------------------*/ |
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c index 7edbd5807e0e..e24a63498acb 100644 --- a/drivers/spi/spi_gpio.c +++ b/drivers/spi/spi_gpio.c | |||
@@ -146,25 +146,63 @@ static inline int getmiso(const struct spi_device *spi) | |||
146 | static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi, | 146 | static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi, |
147 | unsigned nsecs, u32 word, u8 bits) | 147 | unsigned nsecs, u32 word, u8 bits) |
148 | { | 148 | { |
149 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | 149 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); |
150 | } | 150 | } |
151 | 151 | ||
152 | static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi, | 152 | static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi, |
153 | unsigned nsecs, u32 word, u8 bits) | 153 | unsigned nsecs, u32 word, u8 bits) |
154 | { | 154 | { |
155 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); | 155 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); |
156 | } | 156 | } |
157 | 157 | ||
158 | static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi, | 158 | static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi, |
159 | unsigned nsecs, u32 word, u8 bits) | 159 | unsigned nsecs, u32 word, u8 bits) |
160 | { | 160 | { |
161 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); | 161 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); |
162 | } | 162 | } |
163 | 163 | ||
164 | static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, | 164 | static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, |
165 | unsigned nsecs, u32 word, u8 bits) | 165 | unsigned nsecs, u32 word, u8 bits) |
166 | { | 166 | { |
167 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); | 167 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); |
168 | } | ||
169 | |||
170 | /* | ||
171 | * These functions do not call setmosi or getmiso if respective flag | ||
172 | * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to | ||
173 | * call when such pin is not present or defined in the controller. | ||
174 | * A separate set of callbacks is defined to get highest possible | ||
175 | * speed in the generic case (when both MISO and MOSI lines are | ||
176 | * available), as optimiser will remove the checks when argument is | ||
177 | * constant. | ||
178 | */ | ||
179 | |||
180 | static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi, | ||
181 | unsigned nsecs, u32 word, u8 bits) | ||
182 | { | ||
183 | unsigned flags = spi->master->flags; | ||
184 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); | ||
185 | } | ||
186 | |||
187 | static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi, | ||
188 | unsigned nsecs, u32 word, u8 bits) | ||
189 | { | ||
190 | unsigned flags = spi->master->flags; | ||
191 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); | ||
192 | } | ||
193 | |||
194 | static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi, | ||
195 | unsigned nsecs, u32 word, u8 bits) | ||
196 | { | ||
197 | unsigned flags = spi->master->flags; | ||
198 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); | ||
199 | } | ||
200 | |||
201 | static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, | ||
202 | unsigned nsecs, u32 word, u8 bits) | ||
203 | { | ||
204 | unsigned flags = spi->master->flags; | ||
205 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); | ||
168 | } | 206 | } |
169 | 207 | ||
170 | /*----------------------------------------------------------------------*/ | 208 | /*----------------------------------------------------------------------*/ |
@@ -232,19 +270,30 @@ static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) | |||
232 | } | 270 | } |
233 | 271 | ||
234 | static int __init | 272 | static int __init |
235 | spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) | 273 | spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label, |
274 | u16 *res_flags) | ||
236 | { | 275 | { |
237 | int value; | 276 | int value; |
238 | 277 | ||
239 | /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ | 278 | /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ |
240 | 279 | ||
241 | value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); | 280 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) { |
242 | if (value) | 281 | value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); |
243 | goto done; | 282 | if (value) |
283 | goto done; | ||
284 | } else { | ||
285 | /* HW configuration without MOSI pin */ | ||
286 | *res_flags |= SPI_MASTER_NO_TX; | ||
287 | } | ||
244 | 288 | ||
245 | value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); | 289 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) { |
246 | if (value) | 290 | value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); |
247 | goto free_mosi; | 291 | if (value) |
292 | goto free_mosi; | ||
293 | } else { | ||
294 | /* HW configuration without MISO pin */ | ||
295 | *res_flags |= SPI_MASTER_NO_RX; | ||
296 | } | ||
248 | 297 | ||
249 | value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); | 298 | value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); |
250 | if (value) | 299 | if (value) |
@@ -253,9 +302,11 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) | |||
253 | goto done; | 302 | goto done; |
254 | 303 | ||
255 | free_miso: | 304 | free_miso: |
256 | gpio_free(SPI_MISO_GPIO); | 305 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) |
306 | gpio_free(SPI_MISO_GPIO); | ||
257 | free_mosi: | 307 | free_mosi: |
258 | gpio_free(SPI_MOSI_GPIO); | 308 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) |
309 | gpio_free(SPI_MOSI_GPIO); | ||
259 | done: | 310 | done: |
260 | return value; | 311 | return value; |
261 | } | 312 | } |
@@ -266,6 +317,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
266 | struct spi_master *master; | 317 | struct spi_master *master; |
267 | struct spi_gpio *spi_gpio; | 318 | struct spi_gpio *spi_gpio; |
268 | struct spi_gpio_platform_data *pdata; | 319 | struct spi_gpio_platform_data *pdata; |
320 | u16 master_flags = 0; | ||
269 | 321 | ||
270 | pdata = pdev->dev.platform_data; | 322 | pdata = pdev->dev.platform_data; |
271 | #ifdef GENERIC_BITBANG | 323 | #ifdef GENERIC_BITBANG |
@@ -273,7 +325,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
273 | return -ENODEV; | 325 | return -ENODEV; |
274 | #endif | 326 | #endif |
275 | 327 | ||
276 | status = spi_gpio_request(pdata, dev_name(&pdev->dev)); | 328 | status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags); |
277 | if (status < 0) | 329 | if (status < 0) |
278 | return status; | 330 | return status; |
279 | 331 | ||
@@ -289,6 +341,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
289 | if (pdata) | 341 | if (pdata) |
290 | spi_gpio->pdata = *pdata; | 342 | spi_gpio->pdata = *pdata; |
291 | 343 | ||
344 | master->flags = master_flags; | ||
292 | master->bus_num = pdev->id; | 345 | master->bus_num = pdev->id; |
293 | master->num_chipselect = SPI_N_CHIPSEL; | 346 | master->num_chipselect = SPI_N_CHIPSEL; |
294 | master->setup = spi_gpio_setup; | 347 | master->setup = spi_gpio_setup; |
@@ -296,10 +349,18 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
296 | 349 | ||
297 | spi_gpio->bitbang.master = spi_master_get(master); | 350 | spi_gpio->bitbang.master = spi_master_get(master); |
298 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; | 351 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; |
299 | spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; | 352 | |
300 | spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; | 353 | if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) { |
301 | spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; | 354 | spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; |
302 | spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; | 355 | spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; |
356 | spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; | ||
357 | spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; | ||
358 | } else { | ||
359 | spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0; | ||
360 | spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1; | ||
361 | spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2; | ||
362 | spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3; | ||
363 | } | ||
303 | spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; | 364 | spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; |
304 | spi_gpio->bitbang.flags = SPI_CS_HIGH; | 365 | spi_gpio->bitbang.flags = SPI_CS_HIGH; |
305 | 366 | ||
@@ -307,8 +368,10 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
307 | if (status < 0) { | 368 | if (status < 0) { |
308 | spi_master_put(spi_gpio->bitbang.master); | 369 | spi_master_put(spi_gpio->bitbang.master); |
309 | gpio_free: | 370 | gpio_free: |
310 | gpio_free(SPI_MISO_GPIO); | 371 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) |
311 | gpio_free(SPI_MOSI_GPIO); | 372 | gpio_free(SPI_MISO_GPIO); |
373 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) | ||
374 | gpio_free(SPI_MOSI_GPIO); | ||
312 | gpio_free(SPI_SCK_GPIO); | 375 | gpio_free(SPI_SCK_GPIO); |
313 | spi_master_put(master); | 376 | spi_master_put(master); |
314 | } | 377 | } |
@@ -331,8 +394,10 @@ static int __exit spi_gpio_remove(struct platform_device *pdev) | |||
331 | 394 | ||
332 | platform_set_drvdata(pdev, NULL); | 395 | platform_set_drvdata(pdev, NULL); |
333 | 396 | ||
334 | gpio_free(SPI_MISO_GPIO); | 397 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) |
335 | gpio_free(SPI_MOSI_GPIO); | 398 | gpio_free(SPI_MISO_GPIO); |
399 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) | ||
400 | gpio_free(SPI_MOSI_GPIO); | ||
336 | gpio_free(SPI_SCK_GPIO); | 401 | gpio_free(SPI_SCK_GPIO); |
337 | 402 | ||
338 | return status; | 403 | return status; |
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi_lm70llp.c index 86fb7b5993db..7746a41ab6d6 100644 --- a/drivers/spi/spi_lm70llp.c +++ b/drivers/spi/spi_lm70llp.c | |||
@@ -191,7 +191,7 @@ static void lm70_chipselect(struct spi_device *spi, int value) | |||
191 | */ | 191 | */ |
192 | static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits) | 192 | static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits) |
193 | { | 193 | { |
194 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | 194 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); |
195 | } | 195 | } |
196 | 196 | ||
197 | static void spi_lm70llp_attach(struct parport *p) | 197 | static void spi_lm70llp_attach(struct parport *p) |
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index 8979a75dbd7b..be991359bf92 100644 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c | |||
@@ -64,25 +64,25 @@ static inline u32 getmiso(struct spi_device *dev) | |||
64 | static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi, | 64 | static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi, |
65 | unsigned nsecs, u32 word, u8 bits) | 65 | unsigned nsecs, u32 word, u8 bits) |
66 | { | 66 | { |
67 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | 67 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); |
68 | } | 68 | } |
69 | 69 | ||
70 | static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi, | 70 | static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi, |
71 | unsigned nsecs, u32 word, u8 bits) | 71 | unsigned nsecs, u32 word, u8 bits) |
72 | { | 72 | { |
73 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); | 73 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); |
74 | } | 74 | } |
75 | 75 | ||
76 | static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi, | 76 | static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi, |
77 | unsigned nsecs, u32 word, u8 bits) | 77 | unsigned nsecs, u32 word, u8 bits) |
78 | { | 78 | { |
79 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); | 79 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); |
80 | } | 80 | } |
81 | 81 | ||
82 | static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi, | 82 | static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi, |
83 | unsigned nsecs, u32 word, u8 bits) | 83 | unsigned nsecs, u32 word, u8 bits) |
84 | { | 84 | { |
85 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); | 85 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); |
86 | } | 86 | } |
87 | 87 | ||
88 | 88 | ||
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi_sh_sci.c index a511be7961a0..5c6439161199 100644 --- a/drivers/spi/spi_sh_sci.c +++ b/drivers/spi/spi_sh_sci.c | |||
@@ -83,25 +83,25 @@ static inline u32 getmiso(struct spi_device *dev) | |||
83 | static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi, | 83 | static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi, |
84 | unsigned nsecs, u32 word, u8 bits) | 84 | unsigned nsecs, u32 word, u8 bits) |
85 | { | 85 | { |
86 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | 86 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); |
87 | } | 87 | } |
88 | 88 | ||
89 | static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi, | 89 | static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi, |
90 | unsigned nsecs, u32 word, u8 bits) | 90 | unsigned nsecs, u32 word, u8 bits) |
91 | { | 91 | { |
92 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); | 92 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); |
93 | } | 93 | } |
94 | 94 | ||
95 | static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi, | 95 | static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi, |
96 | unsigned nsecs, u32 word, u8 bits) | 96 | unsigned nsecs, u32 word, u8 bits) |
97 | { | 97 | { |
98 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); | 98 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); |
99 | } | 99 | } |
100 | 100 | ||
101 | static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi, | 101 | static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi, |
102 | unsigned nsecs, u32 word, u8 bits) | 102 | unsigned nsecs, u32 word, u8 bits) |
103 | { | 103 | { |
104 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); | 104 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); |
105 | } | 105 | } |
106 | 106 | ||
107 | static void sh_sci_spi_chipselect(struct spi_device *dev, int value) | 107 | static void sh_sci_spi_chipselect(struct spi_device *dev, int value) |