diff options
Diffstat (limited to 'drivers')
163 files changed, 9207 insertions, 2537 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 139f41f033d8..408b45168aba 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
| @@ -2,16 +2,12 @@ | |||
| 2 | # ACPI Configuration | 2 | # ACPI Configuration |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | menu "ACPI (Advanced Configuration and Power Interface) Support" | 5 | menuconfig ACPI |
| 6 | bool "ACPI Support (Advanced Configuration and Power Interface) Support" | ||
| 6 | depends on !X86_NUMAQ | 7 | depends on !X86_NUMAQ |
| 7 | depends on !X86_VISWS | 8 | depends on !X86_VISWS |
| 8 | depends on !IA64_HP_SIM | 9 | depends on !IA64_HP_SIM |
| 9 | depends on IA64 || X86 | 10 | depends on IA64 || X86 |
| 10 | depends on PM | ||
| 11 | |||
| 12 | config ACPI | ||
| 13 | bool "ACPI Support" | ||
| 14 | depends on IA64 || X86 | ||
| 15 | depends on PCI | 11 | depends on PCI |
| 16 | depends on PM | 12 | depends on PM |
| 17 | select PNP | 13 | select PNP |
| @@ -49,7 +45,6 @@ if ACPI | |||
| 49 | config ACPI_SLEEP | 45 | config ACPI_SLEEP |
| 50 | bool "Sleep States" | 46 | bool "Sleep States" |
| 51 | depends on X86 && (!SMP || SUSPEND_SMP) | 47 | depends on X86 && (!SMP || SUSPEND_SMP) |
| 52 | depends on PM | ||
| 53 | default y | 48 | default y |
| 54 | ---help--- | 49 | ---help--- |
| 55 | This option adds support for ACPI suspend states. | 50 | This option adds support for ACPI suspend states. |
| @@ -82,7 +77,6 @@ config ACPI_SLEEP_PROC_SLEEP | |||
| 82 | 77 | ||
| 83 | config ACPI_PROCFS | 78 | config ACPI_PROCFS |
| 84 | bool "Procfs interface (deprecated)" | 79 | bool "Procfs interface (deprecated)" |
| 85 | depends on ACPI | ||
| 86 | default y | 80 | default y |
| 87 | ---help--- | 81 | ---help--- |
| 88 | The Procfs interface for ACPI is made optional for backward compatibility. | 82 | The Procfs interface for ACPI is made optional for backward compatibility. |
| @@ -124,7 +118,7 @@ config ACPI_BUTTON | |||
| 124 | 118 | ||
| 125 | config ACPI_VIDEO | 119 | config ACPI_VIDEO |
| 126 | tristate "Video" | 120 | tristate "Video" |
| 127 | depends on X86 && BACKLIGHT_CLASS_DEVICE | 121 | depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL |
| 128 | help | 122 | help |
| 129 | This driver implement the ACPI Extensions For Display Adapters | 123 | This driver implement the ACPI Extensions For Display Adapters |
| 130 | for integrated graphics devices on motherboard, as specified in | 124 | for integrated graphics devices on motherboard, as specified in |
| @@ -280,6 +274,14 @@ config ACPI_DEBUG | |||
| 280 | of verbosity. Saying Y enables these statements. This will increase | 274 | of verbosity. Saying Y enables these statements. This will increase |
| 281 | your kernel size by around 50K. | 275 | your kernel size by around 50K. |
| 282 | 276 | ||
| 277 | config ACPI_DEBUG_FUNC_TRACE | ||
| 278 | bool "Additionally enable ACPI function tracing" | ||
| 279 | default n | ||
| 280 | depends on ACPI_DEBUG | ||
| 281 | help | ||
| 282 | ACPI Debug Statements slow down ACPI processing. Function trace | ||
| 283 | is about half of the penalty and is rarely useful. | ||
| 284 | |||
| 283 | config ACPI_EC | 285 | config ACPI_EC |
| 284 | bool | 286 | bool |
| 285 | default y | 287 | default y |
| @@ -330,7 +332,6 @@ config ACPI_CONTAINER | |||
| 330 | 332 | ||
| 331 | config ACPI_HOTPLUG_MEMORY | 333 | config ACPI_HOTPLUG_MEMORY |
| 332 | tristate "Memory Hotplug" | 334 | tristate "Memory Hotplug" |
| 333 | depends on ACPI | ||
| 334 | depends on MEMORY_HOTPLUG | 335 | depends on MEMORY_HOTPLUG |
| 335 | default n | 336 | default n |
| 336 | help | 337 | help |
| @@ -359,5 +360,3 @@ config ACPI_SBS | |||
| 359 | to today's ACPI "Control Method" battery. | 360 | to today's ACPI "Control Method" battery. |
| 360 | 361 | ||
| 361 | endif # ACPI | 362 | endif # ACPI |
| 362 | |||
| 363 | endmenu | ||
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index e64c76c8b726..cad932de383d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
| @@ -43,21 +43,30 @@ | |||
| 43 | #define ACPI_BATTERY_CLASS "battery" | 43 | #define ACPI_BATTERY_CLASS "battery" |
| 44 | #define ACPI_BATTERY_HID "PNP0C0A" | 44 | #define ACPI_BATTERY_HID "PNP0C0A" |
| 45 | #define ACPI_BATTERY_DEVICE_NAME "Battery" | 45 | #define ACPI_BATTERY_DEVICE_NAME "Battery" |
| 46 | #define ACPI_BATTERY_FILE_INFO "info" | ||
| 47 | #define ACPI_BATTERY_FILE_STATUS "state" | ||
| 48 | #define ACPI_BATTERY_FILE_ALARM "alarm" | ||
| 49 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 | 46 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 |
| 50 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 | 47 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 |
| 51 | #define ACPI_BATTERY_UNITS_WATTS "mW" | 48 | #define ACPI_BATTERY_UNITS_WATTS "mW" |
| 52 | #define ACPI_BATTERY_UNITS_AMPS "mA" | 49 | #define ACPI_BATTERY_UNITS_AMPS "mA" |
| 53 | 50 | ||
| 54 | #define _COMPONENT ACPI_BATTERY_COMPONENT | 51 | #define _COMPONENT ACPI_BATTERY_COMPONENT |
| 52 | |||
| 53 | #define ACPI_BATTERY_UPDATE_TIME 0 | ||
| 54 | |||
| 55 | #define ACPI_BATTERY_NONE_UPDATE 0 | ||
| 56 | #define ACPI_BATTERY_EASY_UPDATE 1 | ||
| 57 | #define ACPI_BATTERY_INIT_UPDATE 2 | ||
| 58 | |||
| 55 | ACPI_MODULE_NAME("battery"); | 59 | ACPI_MODULE_NAME("battery"); |
| 56 | 60 | ||
| 57 | MODULE_AUTHOR("Paul Diefenbaugh"); | 61 | MODULE_AUTHOR("Paul Diefenbaugh"); |
| 58 | MODULE_DESCRIPTION("ACPI Battery Driver"); | 62 | MODULE_DESCRIPTION("ACPI Battery Driver"); |
| 59 | MODULE_LICENSE("GPL"); | 63 | MODULE_LICENSE("GPL"); |
| 60 | 64 | ||
| 65 | static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME; | ||
| 66 | |||
| 67 | /* 0 - every time, > 0 - by update_time */ | ||
| 68 | module_param(update_time, uint, 0644); | ||
| 69 | |||
| 61 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); | 70 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); |
| 62 | extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); | 71 | extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); |
| 63 | 72 | ||
| @@ -76,7 +85,7 @@ static struct acpi_driver acpi_battery_driver = { | |||
| 76 | }, | 85 | }, |
| 77 | }; | 86 | }; |
| 78 | 87 | ||
| 79 | struct acpi_battery_status { | 88 | struct acpi_battery_state { |
| 80 | acpi_integer state; | 89 | acpi_integer state; |
| 81 | acpi_integer present_rate; | 90 | acpi_integer present_rate; |
| 82 | acpi_integer remaining_capacity; | 91 | acpi_integer remaining_capacity; |
| @@ -99,33 +108,111 @@ struct acpi_battery_info { | |||
| 99 | acpi_string oem_info; | 108 | acpi_string oem_info; |
| 100 | }; | 109 | }; |
| 101 | 110 | ||
| 102 | struct acpi_battery_flags { | 111 | enum acpi_battery_files{ |
| 103 | u8 present:1; /* Bay occupied? */ | 112 | ACPI_BATTERY_INFO = 0, |
| 104 | u8 power_unit:1; /* 0=watts, 1=apms */ | 113 | ACPI_BATTERY_STATE, |
| 105 | u8 alarm:1; /* _BTP present? */ | 114 | ACPI_BATTERY_ALARM, |
| 106 | u8 reserved:5; | 115 | ACPI_BATTERY_NUMFILES, |
| 107 | }; | 116 | }; |
| 108 | 117 | ||
| 109 | struct acpi_battery_trips { | 118 | struct acpi_battery_flags { |
| 110 | unsigned long warning; | 119 | u8 battery_present_prev; |
| 111 | unsigned long low; | 120 | u8 alarm_present; |
| 121 | u8 init_update; | ||
| 122 | u8 update[ACPI_BATTERY_NUMFILES]; | ||
| 123 | u8 power_unit; | ||
| 112 | }; | 124 | }; |
| 113 | 125 | ||
| 114 | struct acpi_battery { | 126 | struct acpi_battery { |
| 115 | struct acpi_device * device; | 127 | struct mutex mutex; |
| 128 | struct acpi_device *device; | ||
| 116 | struct acpi_battery_flags flags; | 129 | struct acpi_battery_flags flags; |
| 117 | struct acpi_battery_trips trips; | 130 | struct acpi_buffer bif_data; |
| 131 | struct acpi_buffer bst_data; | ||
| 118 | unsigned long alarm; | 132 | unsigned long alarm; |
| 119 | struct acpi_battery_info *info; | 133 | unsigned long update_time[ACPI_BATTERY_NUMFILES]; |
| 120 | }; | 134 | }; |
| 121 | 135 | ||
| 136 | inline int acpi_battery_present(struct acpi_battery *battery) | ||
| 137 | { | ||
| 138 | return battery->device->status.battery_present; | ||
| 139 | } | ||
| 140 | inline char *acpi_battery_power_units(struct acpi_battery *battery) | ||
| 141 | { | ||
| 142 | if (battery->flags.power_unit) | ||
| 143 | return ACPI_BATTERY_UNITS_AMPS; | ||
| 144 | else | ||
| 145 | return ACPI_BATTERY_UNITS_WATTS; | ||
| 146 | } | ||
| 147 | |||
| 148 | inline acpi_handle acpi_battery_handle(struct acpi_battery *battery) | ||
| 149 | { | ||
| 150 | return battery->device->handle; | ||
| 151 | } | ||
| 152 | |||
| 122 | /* -------------------------------------------------------------------------- | 153 | /* -------------------------------------------------------------------------- |
| 123 | Battery Management | 154 | Battery Management |
| 124 | -------------------------------------------------------------------------- */ | 155 | -------------------------------------------------------------------------- */ |
| 125 | 156 | ||
| 126 | static int | 157 | static void acpi_battery_check_result(struct acpi_battery *battery, int result) |
| 127 | acpi_battery_get_info(struct acpi_battery *battery, | 158 | { |
| 128 | struct acpi_battery_info **bif) | 159 | if (!battery) |
| 160 | return; | ||
| 161 | |||
| 162 | if (result) { | ||
| 163 | battery->flags.init_update = 1; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | static int acpi_battery_extract_package(struct acpi_battery *battery, | ||
| 168 | union acpi_object *package, | ||
| 169 | struct acpi_buffer *format, | ||
| 170 | struct acpi_buffer *data, | ||
| 171 | char *package_name) | ||
| 172 | { | ||
| 173 | acpi_status status = AE_OK; | ||
| 174 | struct acpi_buffer data_null = { 0, NULL }; | ||
| 175 | |||
| 176 | status = acpi_extract_package(package, format, &data_null); | ||
| 177 | if (status != AE_BUFFER_OVERFLOW) { | ||
| 178 | ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s", | ||
| 179 | package_name)); | ||
| 180 | return -ENODEV; | ||
| 181 | } | ||
| 182 | |||
| 183 | if (data_null.length != data->length) { | ||
| 184 | kfree(data->pointer); | ||
| 185 | data->pointer = kzalloc(data_null.length, GFP_KERNEL); | ||
| 186 | if (!data->pointer) { | ||
| 187 | ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()")); | ||
| 188 | return -ENOMEM; | ||
| 189 | } | ||
| 190 | data->length = data_null.length; | ||
| 191 | } | ||
| 192 | |||
| 193 | status = acpi_extract_package(package, format, data); | ||
| 194 | if (ACPI_FAILURE(status)) { | ||
| 195 | ACPI_EXCEPTION((AE_INFO, status, "Extracting %s", | ||
| 196 | package_name)); | ||
| 197 | return -ENODEV; | ||
| 198 | } | ||
| 199 | |||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | static int acpi_battery_get_status(struct acpi_battery *battery) | ||
| 204 | { | ||
| 205 | int result = 0; | ||
| 206 | |||
| 207 | result = acpi_bus_get_status(battery->device); | ||
| 208 | if (result) { | ||
| 209 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA")); | ||
| 210 | return -ENODEV; | ||
| 211 | } | ||
| 212 | return result; | ||
| 213 | } | ||
| 214 | |||
| 215 | static int acpi_battery_get_info(struct acpi_battery *battery) | ||
| 129 | { | 216 | { |
| 130 | int result = 0; | 217 | int result = 0; |
| 131 | acpi_status status = 0; | 218 | acpi_status status = 0; |
| @@ -133,16 +220,20 @@ acpi_battery_get_info(struct acpi_battery *battery, | |||
| 133 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), | 220 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), |
| 134 | ACPI_BATTERY_FORMAT_BIF | 221 | ACPI_BATTERY_FORMAT_BIF |
| 135 | }; | 222 | }; |
| 136 | struct acpi_buffer data = { 0, NULL }; | ||
| 137 | union acpi_object *package = NULL; | 223 | union acpi_object *package = NULL; |
| 224 | struct acpi_buffer *data = NULL; | ||
| 225 | struct acpi_battery_info *bif = NULL; | ||
| 138 | 226 | ||
| 227 | battery->update_time[ACPI_BATTERY_INFO] = get_seconds(); | ||
| 139 | 228 | ||
| 140 | if (!battery || !bif) | 229 | if (!acpi_battery_present(battery)) |
| 141 | return -EINVAL; | 230 | return 0; |
| 142 | 231 | ||
| 143 | /* Evalute _BIF */ | 232 | /* Evaluate _BIF */ |
| 144 | 233 | ||
| 145 | status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer); | 234 | status = |
| 235 | acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, | ||
| 236 | &buffer); | ||
| 146 | if (ACPI_FAILURE(status)) { | 237 | if (ACPI_FAILURE(status)) { |
| 147 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); | 238 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); |
| 148 | return -ENODEV; | 239 | return -ENODEV; |
| @@ -150,41 +241,29 @@ acpi_battery_get_info(struct acpi_battery *battery, | |||
| 150 | 241 | ||
| 151 | package = buffer.pointer; | 242 | package = buffer.pointer; |
| 152 | 243 | ||
| 153 | /* Extract Package Data */ | 244 | data = &battery->bif_data; |
| 154 | |||
| 155 | status = acpi_extract_package(package, &format, &data); | ||
| 156 | if (status != AE_BUFFER_OVERFLOW) { | ||
| 157 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF")); | ||
| 158 | result = -ENODEV; | ||
| 159 | goto end; | ||
| 160 | } | ||
| 161 | 245 | ||
| 162 | data.pointer = kzalloc(data.length, GFP_KERNEL); | 246 | /* Extract Package Data */ |
| 163 | if (!data.pointer) { | ||
| 164 | result = -ENOMEM; | ||
| 165 | goto end; | ||
| 166 | } | ||
| 167 | 247 | ||
| 168 | status = acpi_extract_package(package, &format, &data); | 248 | result = |
| 169 | if (ACPI_FAILURE(status)) { | 249 | acpi_battery_extract_package(battery, package, &format, data, |
| 170 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF")); | 250 | "_BIF"); |
| 171 | kfree(data.pointer); | 251 | if (result) |
| 172 | result = -ENODEV; | ||
| 173 | goto end; | 252 | goto end; |
| 174 | } | ||
| 175 | 253 | ||
| 176 | end: | 254 | end: |
| 255 | |||
| 177 | kfree(buffer.pointer); | 256 | kfree(buffer.pointer); |
| 178 | 257 | ||
| 179 | if (!result) | 258 | if (!result) { |
| 180 | (*bif) = data.pointer; | 259 | bif = data->pointer; |
| 260 | battery->flags.power_unit = bif->power_unit; | ||
| 261 | } | ||
| 181 | 262 | ||
| 182 | return result; | 263 | return result; |
| 183 | } | 264 | } |
| 184 | 265 | ||
| 185 | static int | 266 | static int acpi_battery_get_state(struct acpi_battery *battery) |
| 186 | acpi_battery_get_status(struct acpi_battery *battery, | ||
| 187 | struct acpi_battery_status **bst) | ||
| 188 | { | 267 | { |
| 189 | int result = 0; | 268 | int result = 0; |
| 190 | acpi_status status = 0; | 269 | acpi_status status = 0; |
| @@ -192,16 +271,19 @@ acpi_battery_get_status(struct acpi_battery *battery, | |||
| 192 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), | 271 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), |
| 193 | ACPI_BATTERY_FORMAT_BST | 272 | ACPI_BATTERY_FORMAT_BST |
| 194 | }; | 273 | }; |
| 195 | struct acpi_buffer data = { 0, NULL }; | ||
| 196 | union acpi_object *package = NULL; | 274 | union acpi_object *package = NULL; |
| 275 | struct acpi_buffer *data = NULL; | ||
| 197 | 276 | ||
| 277 | battery->update_time[ACPI_BATTERY_STATE] = get_seconds(); | ||
| 198 | 278 | ||
| 199 | if (!battery || !bst) | 279 | if (!acpi_battery_present(battery)) |
| 200 | return -EINVAL; | 280 | return 0; |
| 201 | 281 | ||
| 202 | /* Evalute _BST */ | 282 | /* Evaluate _BST */ |
| 203 | 283 | ||
| 204 | status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer); | 284 | status = |
| 285 | acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, | ||
| 286 | &buffer); | ||
| 205 | if (ACPI_FAILURE(status)) { | 287 | if (ACPI_FAILURE(status)) { |
| 206 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); | 288 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); |
| 207 | return -ENODEV; | 289 | return -ENODEV; |
| @@ -209,55 +291,49 @@ acpi_battery_get_status(struct acpi_battery *battery, | |||
| 209 | 291 | ||
| 210 | package = buffer.pointer; | 292 | package = buffer.pointer; |
| 211 | 293 | ||
| 212 | /* Extract Package Data */ | 294 | data = &battery->bst_data; |
| 213 | |||
| 214 | status = acpi_extract_package(package, &format, &data); | ||
| 215 | if (status != AE_BUFFER_OVERFLOW) { | ||
| 216 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); | ||
| 217 | result = -ENODEV; | ||
| 218 | goto end; | ||
| 219 | } | ||
| 220 | 295 | ||
| 221 | data.pointer = kzalloc(data.length, GFP_KERNEL); | 296 | /* Extract Package Data */ |
| 222 | if (!data.pointer) { | ||
| 223 | result = -ENOMEM; | ||
| 224 | goto end; | ||
| 225 | } | ||
| 226 | 297 | ||
| 227 | status = acpi_extract_package(package, &format, &data); | 298 | result = |
| 228 | if (ACPI_FAILURE(status)) { | 299 | acpi_battery_extract_package(battery, package, &format, data, |
| 229 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); | 300 | "_BST"); |
| 230 | kfree(data.pointer); | 301 | if (result) |
| 231 | result = -ENODEV; | ||
| 232 | goto end; | 302 | goto end; |
| 233 | } | ||
| 234 | 303 | ||
| 235 | end: | 304 | end: |
| 236 | kfree(buffer.pointer); | 305 | kfree(buffer.pointer); |
| 237 | 306 | ||
| 238 | if (!result) | ||
| 239 | (*bst) = data.pointer; | ||
| 240 | |||
| 241 | return result; | 307 | return result; |
| 242 | } | 308 | } |
| 243 | 309 | ||
| 244 | static int | 310 | static int acpi_battery_get_alarm(struct acpi_battery *battery) |
| 245 | acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) | 311 | { |
| 312 | battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); | ||
| 313 | |||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | static int acpi_battery_set_alarm(struct acpi_battery *battery, | ||
| 318 | unsigned long alarm) | ||
| 246 | { | 319 | { |
| 247 | acpi_status status = 0; | 320 | acpi_status status = 0; |
| 248 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | 321 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; |
| 249 | struct acpi_object_list arg_list = { 1, &arg0 }; | 322 | struct acpi_object_list arg_list = { 1, &arg0 }; |
| 250 | 323 | ||
| 324 | battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); | ||
| 251 | 325 | ||
| 252 | if (!battery) | 326 | if (!acpi_battery_present(battery)) |
| 253 | return -EINVAL; | 327 | return -ENODEV; |
| 254 | 328 | ||
| 255 | if (!battery->flags.alarm) | 329 | if (!battery->flags.alarm_present) |
| 256 | return -ENODEV; | 330 | return -ENODEV; |
| 257 | 331 | ||
| 258 | arg0.integer.value = alarm; | 332 | arg0.integer.value = alarm; |
| 259 | 333 | ||
| 260 | status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL); | 334 | status = |
| 335 | acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", | ||
| 336 | &arg_list, NULL); | ||
| 261 | if (ACPI_FAILURE(status)) | 337 | if (ACPI_FAILURE(status)) |
| 262 | return -ENODEV; | 338 | return -ENODEV; |
| 263 | 339 | ||
| @@ -268,65 +344,114 @@ acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) | |||
| 268 | return 0; | 344 | return 0; |
| 269 | } | 345 | } |
| 270 | 346 | ||
| 271 | static int acpi_battery_check(struct acpi_battery *battery) | 347 | static int acpi_battery_init_alarm(struct acpi_battery *battery) |
| 272 | { | 348 | { |
| 273 | int result = 0; | 349 | int result = 0; |
| 274 | acpi_status status = AE_OK; | 350 | acpi_status status = AE_OK; |
| 275 | acpi_handle handle = NULL; | 351 | acpi_handle handle = NULL; |
| 276 | struct acpi_device *device = NULL; | 352 | struct acpi_battery_info *bif = battery->bif_data.pointer; |
| 277 | struct acpi_battery_info *bif = NULL; | 353 | unsigned long alarm = battery->alarm; |
| 278 | 354 | ||
| 355 | /* See if alarms are supported, and if so, set default */ | ||
| 279 | 356 | ||
| 280 | if (!battery) | 357 | status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle); |
| 281 | return -EINVAL; | 358 | if (ACPI_SUCCESS(status)) { |
| 282 | 359 | battery->flags.alarm_present = 1; | |
| 283 | device = battery->device; | 360 | if (!alarm && bif) { |
| 361 | alarm = bif->design_capacity_warning; | ||
| 362 | } | ||
| 363 | result = acpi_battery_set_alarm(battery, alarm); | ||
| 364 | if (result) | ||
| 365 | goto end; | ||
| 366 | } else { | ||
| 367 | battery->flags.alarm_present = 0; | ||
| 368 | } | ||
| 284 | 369 | ||
| 285 | result = acpi_bus_get_status(device); | 370 | end: |
| 286 | if (result) | ||
| 287 | return result; | ||
| 288 | 371 | ||
| 289 | /* Insertion? */ | 372 | return result; |
| 373 | } | ||
| 290 | 374 | ||
| 291 | if (!battery->flags.present && device->status.battery_present) { | 375 | static int acpi_battery_init_update(struct acpi_battery *battery) |
| 376 | { | ||
| 377 | int result = 0; | ||
| 292 | 378 | ||
| 293 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); | 379 | result = acpi_battery_get_status(battery); |
| 380 | if (result) | ||
| 381 | return result; | ||
| 294 | 382 | ||
| 295 | /* Evalute _BIF to get certain static information */ | 383 | battery->flags.battery_present_prev = acpi_battery_present(battery); |
| 296 | 384 | ||
| 297 | result = acpi_battery_get_info(battery, &bif); | 385 | if (acpi_battery_present(battery)) { |
| 386 | result = acpi_battery_get_info(battery); | ||
| 387 | if (result) | ||
| 388 | return result; | ||
| 389 | result = acpi_battery_get_state(battery); | ||
| 298 | if (result) | 390 | if (result) |
| 299 | return result; | 391 | return result; |
| 300 | 392 | ||
| 301 | battery->flags.power_unit = bif->power_unit; | 393 | acpi_battery_init_alarm(battery); |
| 302 | battery->trips.warning = bif->design_capacity_warning; | 394 | } |
| 303 | battery->trips.low = bif->design_capacity_low; | 395 | |
| 304 | kfree(bif); | 396 | return result; |
| 397 | } | ||
| 305 | 398 | ||
| 306 | /* See if alarms are supported, and if so, set default */ | 399 | static int acpi_battery_update(struct acpi_battery *battery, |
| 400 | int update, int *update_result_ptr) | ||
| 401 | { | ||
| 402 | int result = 0; | ||
| 403 | int update_result = ACPI_BATTERY_NONE_UPDATE; | ||
| 404 | |||
| 405 | if (!acpi_battery_present(battery)) { | ||
| 406 | update = 1; | ||
| 407 | } | ||
| 307 | 408 | ||
| 308 | status = acpi_get_handle(battery->device->handle, "_BTP", &handle); | 409 | if (battery->flags.init_update) { |
| 309 | if (ACPI_SUCCESS(status)) { | 410 | result = acpi_battery_init_update(battery); |
| 310 | battery->flags.alarm = 1; | 411 | if (result) |
| 311 | acpi_battery_set_alarm(battery, battery->trips.warning); | 412 | goto end; |
| 413 | update_result = ACPI_BATTERY_INIT_UPDATE; | ||
| 414 | } else if (update) { | ||
| 415 | result = acpi_battery_get_status(battery); | ||
| 416 | if (result) | ||
| 417 | goto end; | ||
| 418 | if ((!battery->flags.battery_present_prev & acpi_battery_present(battery)) | ||
| 419 | || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) { | ||
| 420 | result = acpi_battery_init_update(battery); | ||
| 421 | if (result) | ||
| 422 | goto end; | ||
| 423 | update_result = ACPI_BATTERY_INIT_UPDATE; | ||
| 424 | } else { | ||
| 425 | update_result = ACPI_BATTERY_EASY_UPDATE; | ||
| 312 | } | 426 | } |
| 313 | } | 427 | } |
| 314 | 428 | ||
| 315 | /* Removal? */ | 429 | end: |
| 316 | 430 | ||
| 317 | else if (battery->flags.present && !device->status.battery_present) { | 431 | battery->flags.init_update = (result != 0); |
| 318 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); | ||
| 319 | } | ||
| 320 | 432 | ||
| 321 | battery->flags.present = device->status.battery_present; | 433 | *update_result_ptr = update_result; |
| 322 | 434 | ||
| 323 | return result; | 435 | return result; |
| 324 | } | 436 | } |
| 325 | 437 | ||
| 326 | static void acpi_battery_check_present(struct acpi_battery *battery) | 438 | static void acpi_battery_notify_update(struct acpi_battery *battery) |
| 327 | { | 439 | { |
| 328 | if (!battery->flags.present) { | 440 | acpi_battery_get_status(battery); |
| 329 | acpi_battery_check(battery); | 441 | |
| 442 | if (battery->flags.init_update) { | ||
| 443 | return; | ||
| 444 | } | ||
| 445 | |||
| 446 | if ((!battery->flags.battery_present_prev & | ||
| 447 | acpi_battery_present(battery)) || | ||
| 448 | (battery->flags.battery_present_prev & | ||
| 449 | !acpi_battery_present(battery))) { | ||
| 450 | battery->flags.init_update = 1; | ||
| 451 | } else { | ||
| 452 | battery->flags.update[ACPI_BATTERY_INFO] = 1; | ||
| 453 | battery->flags.update[ACPI_BATTERY_STATE] = 1; | ||
| 454 | battery->flags.update[ACPI_BATTERY_ALARM] = 1; | ||
| 330 | } | 455 | } |
| 331 | } | 456 | } |
| 332 | 457 | ||
| @@ -335,37 +460,33 @@ static void acpi_battery_check_present(struct acpi_battery *battery) | |||
| 335 | -------------------------------------------------------------------------- */ | 460 | -------------------------------------------------------------------------- */ |
| 336 | 461 | ||
| 337 | static struct proc_dir_entry *acpi_battery_dir; | 462 | static struct proc_dir_entry *acpi_battery_dir; |
| 338 | static int acpi_battery_read_info(struct seq_file *seq, void *offset) | 463 | |
| 464 | static int acpi_battery_print_info(struct seq_file *seq, int result) | ||
| 339 | { | 465 | { |
| 340 | int result = 0; | ||
| 341 | struct acpi_battery *battery = seq->private; | 466 | struct acpi_battery *battery = seq->private; |
| 342 | struct acpi_battery_info *bif = NULL; | 467 | struct acpi_battery_info *bif = NULL; |
| 343 | char *units = "?"; | 468 | char *units = "?"; |
| 344 | 469 | ||
| 345 | 470 | if (result) | |
| 346 | if (!battery) | ||
| 347 | goto end; | 471 | goto end; |
| 348 | 472 | ||
| 349 | acpi_battery_check_present(battery); | 473 | if (acpi_battery_present(battery)) |
| 350 | |||
| 351 | if (battery->flags.present) | ||
| 352 | seq_printf(seq, "present: yes\n"); | 474 | seq_printf(seq, "present: yes\n"); |
| 353 | else { | 475 | else { |
| 354 | seq_printf(seq, "present: no\n"); | 476 | seq_printf(seq, "present: no\n"); |
| 355 | goto end; | 477 | goto end; |
| 356 | } | 478 | } |
| 357 | 479 | ||
| 358 | /* Battery Info (_BIF) */ | 480 | bif = battery->bif_data.pointer; |
| 359 | 481 | if (!bif) { | |
| 360 | result = acpi_battery_get_info(battery, &bif); | 482 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL")); |
| 361 | if (result || !bif) { | 483 | result = -ENODEV; |
| 362 | seq_printf(seq, "ERROR: Unable to read battery information\n"); | ||
| 363 | goto end; | 484 | goto end; |
| 364 | } | 485 | } |
| 365 | 486 | ||
| 366 | units = | 487 | /* Battery Units */ |
| 367 | bif-> | 488 | |
| 368 | power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; | 489 | units = acpi_battery_power_units(battery); |
| 369 | 490 | ||
| 370 | if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) | 491 | if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) |
| 371 | seq_printf(seq, "design capacity: unknown\n"); | 492 | seq_printf(seq, "design capacity: unknown\n"); |
| @@ -396,7 +517,6 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) | |||
| 396 | else | 517 | else |
| 397 | seq_printf(seq, "design voltage: %d mV\n", | 518 | seq_printf(seq, "design voltage: %d mV\n", |
| 398 | (u32) bif->design_voltage); | 519 | (u32) bif->design_voltage); |
| 399 | |||
| 400 | seq_printf(seq, "design capacity warning: %d %sh\n", | 520 | seq_printf(seq, "design capacity warning: %d %sh\n", |
| 401 | (u32) bif->design_capacity_warning, units); | 521 | (u32) bif->design_capacity_warning, units); |
| 402 | seq_printf(seq, "design capacity low: %d %sh\n", | 522 | seq_printf(seq, "design capacity low: %d %sh\n", |
| @@ -411,50 +531,40 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) | |||
| 411 | seq_printf(seq, "OEM info: %s\n", bif->oem_info); | 531 | seq_printf(seq, "OEM info: %s\n", bif->oem_info); |
| 412 | 532 | ||
| 413 | end: | 533 | end: |
| 414 | kfree(bif); | ||
| 415 | 534 | ||
| 416 | return 0; | 535 | if (result) |
| 417 | } | 536 | seq_printf(seq, "ERROR: Unable to read battery info\n"); |
| 418 | 537 | ||
| 419 | static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) | 538 | return result; |
| 420 | { | ||
| 421 | return single_open(file, acpi_battery_read_info, PDE(inode)->data); | ||
| 422 | } | 539 | } |
| 423 | 540 | ||
| 424 | static int acpi_battery_read_state(struct seq_file *seq, void *offset) | 541 | static int acpi_battery_print_state(struct seq_file *seq, int result) |
| 425 | { | 542 | { |
| 426 | int result = 0; | ||
| 427 | struct acpi_battery *battery = seq->private; | 543 | struct acpi_battery *battery = seq->private; |
| 428 | struct acpi_battery_status *bst = NULL; | 544 | struct acpi_battery_state *bst = NULL; |
| 429 | char *units = "?"; | 545 | char *units = "?"; |
| 430 | 546 | ||
| 431 | 547 | if (result) | |
| 432 | if (!battery) | ||
| 433 | goto end; | 548 | goto end; |
| 434 | 549 | ||
| 435 | acpi_battery_check_present(battery); | 550 | if (acpi_battery_present(battery)) |
| 436 | |||
| 437 | if (battery->flags.present) | ||
| 438 | seq_printf(seq, "present: yes\n"); | 551 | seq_printf(seq, "present: yes\n"); |
| 439 | else { | 552 | else { |
| 440 | seq_printf(seq, "present: no\n"); | 553 | seq_printf(seq, "present: no\n"); |
| 441 | goto end; | 554 | goto end; |
| 442 | } | 555 | } |
| 443 | 556 | ||
| 444 | /* Battery Units */ | 557 | bst = battery->bst_data.pointer; |
| 445 | 558 | if (!bst) { | |
| 446 | units = | 559 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL")); |
| 447 | battery->flags. | 560 | result = -ENODEV; |
| 448 | power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; | ||
| 449 | |||
| 450 | /* Battery Status (_BST) */ | ||
| 451 | |||
| 452 | result = acpi_battery_get_status(battery, &bst); | ||
| 453 | if (result || !bst) { | ||
| 454 | seq_printf(seq, "ERROR: Unable to read battery status\n"); | ||
| 455 | goto end; | 561 | goto end; |
| 456 | } | 562 | } |
| 457 | 563 | ||
| 564 | /* Battery Units */ | ||
| 565 | |||
| 566 | units = acpi_battery_power_units(battery); | ||
| 567 | |||
| 458 | if (!(bst->state & 0x04)) | 568 | if (!(bst->state & 0x04)) |
| 459 | seq_printf(seq, "capacity state: ok\n"); | 569 | seq_printf(seq, "capacity state: ok\n"); |
| 460 | else | 570 | else |
| @@ -490,48 +600,43 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) | |||
| 490 | (u32) bst->present_voltage); | 600 | (u32) bst->present_voltage); |
| 491 | 601 | ||
| 492 | end: | 602 | end: |
| 493 | kfree(bst); | ||
| 494 | 603 | ||
| 495 | return 0; | 604 | if (result) { |
| 496 | } | 605 | seq_printf(seq, "ERROR: Unable to read battery state\n"); |
| 606 | } | ||
| 497 | 607 | ||
| 498 | static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) | 608 | return result; |
| 499 | { | ||
| 500 | return single_open(file, acpi_battery_read_state, PDE(inode)->data); | ||
| 501 | } | 609 | } |
| 502 | 610 | ||
| 503 | static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) | 611 | static int acpi_battery_print_alarm(struct seq_file *seq, int result) |
| 504 | { | 612 | { |
| 505 | struct acpi_battery *battery = seq->private; | 613 | struct acpi_battery *battery = seq->private; |
| 506 | char *units = "?"; | 614 | char *units = "?"; |
| 507 | 615 | ||
| 508 | 616 | if (result) | |
| 509 | if (!battery) | ||
| 510 | goto end; | 617 | goto end; |
| 511 | 618 | ||
| 512 | acpi_battery_check_present(battery); | 619 | if (!acpi_battery_present(battery)) { |
| 513 | |||
| 514 | if (!battery->flags.present) { | ||
| 515 | seq_printf(seq, "present: no\n"); | 620 | seq_printf(seq, "present: no\n"); |
| 516 | goto end; | 621 | goto end; |
| 517 | } | 622 | } |
| 518 | 623 | ||
| 519 | /* Battery Units */ | 624 | /* Battery Units */ |
| 520 | 625 | ||
| 521 | units = | 626 | units = acpi_battery_power_units(battery); |
| 522 | battery->flags. | ||
| 523 | power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; | ||
| 524 | |||
| 525 | /* Battery Alarm */ | ||
| 526 | 627 | ||
| 527 | seq_printf(seq, "alarm: "); | 628 | seq_printf(seq, "alarm: "); |
| 528 | if (!battery->alarm) | 629 | if (!battery->alarm) |
| 529 | seq_printf(seq, "unsupported\n"); | 630 | seq_printf(seq, "unsupported\n"); |
| 530 | else | 631 | else |
| 531 | seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units); | 632 | seq_printf(seq, "%lu %sh\n", battery->alarm, units); |
| 532 | 633 | ||
| 533 | end: | 634 | end: |
| 534 | return 0; | 635 | |
| 636 | if (result) | ||
| 637 | seq_printf(seq, "ERROR: Unable to read battery alarm\n"); | ||
| 638 | |||
| 639 | return result; | ||
| 535 | } | 640 | } |
| 536 | 641 | ||
| 537 | static ssize_t | 642 | static ssize_t |
| @@ -543,27 +648,113 @@ acpi_battery_write_alarm(struct file *file, | |||
| 543 | char alarm_string[12] = { '\0' }; | 648 | char alarm_string[12] = { '\0' }; |
| 544 | struct seq_file *m = file->private_data; | 649 | struct seq_file *m = file->private_data; |
| 545 | struct acpi_battery *battery = m->private; | 650 | struct acpi_battery *battery = m->private; |
| 546 | 651 | int update_result = ACPI_BATTERY_NONE_UPDATE; | |
| 547 | 652 | ||
| 548 | if (!battery || (count > sizeof(alarm_string) - 1)) | 653 | if (!battery || (count > sizeof(alarm_string) - 1)) |
| 549 | return -EINVAL; | 654 | return -EINVAL; |
| 550 | 655 | ||
| 551 | acpi_battery_check_present(battery); | 656 | mutex_lock(&battery->mutex); |
| 552 | 657 | ||
| 553 | if (!battery->flags.present) | 658 | result = acpi_battery_update(battery, 1, &update_result); |
| 554 | return -ENODEV; | 659 | if (result) { |
| 660 | result = -ENODEV; | ||
| 661 | goto end; | ||
| 662 | } | ||
| 663 | |||
| 664 | if (!acpi_battery_present(battery)) { | ||
| 665 | result = -ENODEV; | ||
| 666 | goto end; | ||
| 667 | } | ||
| 555 | 668 | ||
| 556 | if (copy_from_user(alarm_string, buffer, count)) | 669 | if (copy_from_user(alarm_string, buffer, count)) { |
| 557 | return -EFAULT; | 670 | result = -EFAULT; |
| 671 | goto end; | ||
| 672 | } | ||
| 558 | 673 | ||
| 559 | alarm_string[count] = '\0'; | 674 | alarm_string[count] = '\0'; |
| 560 | 675 | ||
| 561 | result = acpi_battery_set_alarm(battery, | 676 | result = acpi_battery_set_alarm(battery, |
| 562 | simple_strtoul(alarm_string, NULL, 0)); | 677 | simple_strtoul(alarm_string, NULL, 0)); |
| 563 | if (result) | 678 | if (result) |
| 564 | return result; | 679 | goto end; |
| 680 | |||
| 681 | end: | ||
| 565 | 682 | ||
| 566 | return count; | 683 | acpi_battery_check_result(battery, result); |
| 684 | |||
| 685 | if (!result) | ||
| 686 | result = count; | ||
| 687 | |||
| 688 | mutex_unlock(&battery->mutex); | ||
| 689 | |||
| 690 | return result; | ||
| 691 | } | ||
| 692 | |||
| 693 | typedef int(*print_func)(struct seq_file *seq, int result); | ||
| 694 | typedef int(*get_func)(struct acpi_battery *battery); | ||
| 695 | |||
| 696 | static struct acpi_read_mux { | ||
| 697 | print_func print; | ||
| 698 | get_func get; | ||
| 699 | } acpi_read_funcs[ACPI_BATTERY_NUMFILES] = { | ||
| 700 | {.get = acpi_battery_get_info, .print = acpi_battery_print_info}, | ||
| 701 | {.get = acpi_battery_get_state, .print = acpi_battery_print_state}, | ||
| 702 | {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm}, | ||
| 703 | }; | ||
| 704 | |||
| 705 | static int acpi_battery_read(int fid, struct seq_file *seq) | ||
| 706 | { | ||
| 707 | struct acpi_battery *battery = seq->private; | ||
| 708 | int result = 0; | ||
| 709 | int update_result = ACPI_BATTERY_NONE_UPDATE; | ||
| 710 | int update = 0; | ||
| 711 | |||
| 712 | mutex_lock(&battery->mutex); | ||
| 713 | |||
| 714 | update = (get_seconds() - battery->update_time[fid] >= update_time); | ||
| 715 | update = (update | battery->flags.update[fid]); | ||
| 716 | |||
| 717 | result = acpi_battery_update(battery, update, &update_result); | ||
| 718 | if (result) | ||
| 719 | goto end; | ||
| 720 | |||
| 721 | if (update_result == ACPI_BATTERY_EASY_UPDATE) { | ||
| 722 | result = acpi_read_funcs[fid].get(battery); | ||
| 723 | if (result) | ||
| 724 | goto end; | ||
| 725 | } | ||
| 726 | |||
| 727 | end: | ||
| 728 | result = acpi_read_funcs[fid].print(seq, result); | ||
| 729 | acpi_battery_check_result(battery, result); | ||
| 730 | battery->flags.update[fid] = result; | ||
| 731 | mutex_unlock(&battery->mutex); | ||
| 732 | return result; | ||
| 733 | } | ||
| 734 | |||
| 735 | static int acpi_battery_read_info(struct seq_file *seq, void *offset) | ||
| 736 | { | ||
| 737 | return acpi_battery_read(ACPI_BATTERY_INFO, seq); | ||
| 738 | } | ||
| 739 | |||
| 740 | static int acpi_battery_read_state(struct seq_file *seq, void *offset) | ||
| 741 | { | ||
| 742 | return acpi_battery_read(ACPI_BATTERY_STATE, seq); | ||
| 743 | } | ||
| 744 | |||
| 745 | static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) | ||
| 746 | { | ||
| 747 | return acpi_battery_read(ACPI_BATTERY_ALARM, seq); | ||
| 748 | } | ||
| 749 | |||
| 750 | static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) | ||
| 751 | { | ||
| 752 | return single_open(file, acpi_battery_read_info, PDE(inode)->data); | ||
| 753 | } | ||
| 754 | |||
| 755 | static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) | ||
| 756 | { | ||
| 757 | return single_open(file, acpi_battery_read_state, PDE(inode)->data); | ||
| 567 | } | 758 | } |
| 568 | 759 | ||
| 569 | static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) | 760 | static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) |
| @@ -571,35 +762,51 @@ static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) | |||
| 571 | return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); | 762 | return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); |
| 572 | } | 763 | } |
| 573 | 764 | ||
| 574 | static const struct file_operations acpi_battery_info_ops = { | 765 | static struct battery_file { |
| 766 | struct file_operations ops; | ||
| 767 | mode_t mode; | ||
| 768 | char *name; | ||
| 769 | } acpi_battery_file[] = { | ||
| 770 | { | ||
| 771 | .name = "info", | ||
| 772 | .mode = S_IRUGO, | ||
| 773 | .ops = { | ||
| 575 | .open = acpi_battery_info_open_fs, | 774 | .open = acpi_battery_info_open_fs, |
| 576 | .read = seq_read, | 775 | .read = seq_read, |
| 577 | .llseek = seq_lseek, | 776 | .llseek = seq_lseek, |
| 578 | .release = single_release, | 777 | .release = single_release, |
| 579 | .owner = THIS_MODULE, | 778 | .owner = THIS_MODULE, |
| 580 | }; | 779 | }, |
| 581 | 780 | }, | |
| 582 | static const struct file_operations acpi_battery_state_ops = { | 781 | { |
| 782 | .name = "state", | ||
| 783 | .mode = S_IRUGO, | ||
| 784 | .ops = { | ||
| 583 | .open = acpi_battery_state_open_fs, | 785 | .open = acpi_battery_state_open_fs, |
| 584 | .read = seq_read, | 786 | .read = seq_read, |
| 585 | .llseek = seq_lseek, | 787 | .llseek = seq_lseek, |
| 586 | .release = single_release, | 788 | .release = single_release, |
| 587 | .owner = THIS_MODULE, | 789 | .owner = THIS_MODULE, |
| 588 | }; | 790 | }, |
| 589 | 791 | }, | |
| 590 | static const struct file_operations acpi_battery_alarm_ops = { | 792 | { |
| 793 | .name = "alarm", | ||
| 794 | .mode = S_IFREG | S_IRUGO | S_IWUSR, | ||
| 795 | .ops = { | ||
| 591 | .open = acpi_battery_alarm_open_fs, | 796 | .open = acpi_battery_alarm_open_fs, |
| 592 | .read = seq_read, | 797 | .read = seq_read, |
| 593 | .write = acpi_battery_write_alarm, | 798 | .write = acpi_battery_write_alarm, |
| 594 | .llseek = seq_lseek, | 799 | .llseek = seq_lseek, |
| 595 | .release = single_release, | 800 | .release = single_release, |
| 596 | .owner = THIS_MODULE, | 801 | .owner = THIS_MODULE, |
| 802 | }, | ||
| 803 | }, | ||
| 597 | }; | 804 | }; |
| 598 | 805 | ||
| 599 | static int acpi_battery_add_fs(struct acpi_device *device) | 806 | static int acpi_battery_add_fs(struct acpi_device *device) |
| 600 | { | 807 | { |
| 601 | struct proc_dir_entry *entry = NULL; | 808 | struct proc_dir_entry *entry = NULL; |
| 602 | 809 | int i; | |
| 603 | 810 | ||
| 604 | if (!acpi_device_dir(device)) { | 811 | if (!acpi_device_dir(device)) { |
| 605 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | 812 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), |
| @@ -609,38 +816,16 @@ static int acpi_battery_add_fs(struct acpi_device *device) | |||
| 609 | acpi_device_dir(device)->owner = THIS_MODULE; | 816 | acpi_device_dir(device)->owner = THIS_MODULE; |
| 610 | } | 817 | } |
| 611 | 818 | ||
| 612 | /* 'info' [R] */ | 819 | for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { |
| 613 | entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, | 820 | entry = create_proc_entry(acpi_battery_file[i].name, |
| 614 | S_IRUGO, acpi_device_dir(device)); | 821 | acpi_battery_file[i].mode, acpi_device_dir(device)); |
| 615 | if (!entry) | 822 | if (!entry) |
| 616 | return -ENODEV; | 823 | return -ENODEV; |
| 617 | else { | 824 | else { |
| 618 | entry->proc_fops = &acpi_battery_info_ops; | 825 | entry->proc_fops = &acpi_battery_file[i].ops; |
| 619 | entry->data = acpi_driver_data(device); | 826 | entry->data = acpi_driver_data(device); |
| 620 | entry->owner = THIS_MODULE; | 827 | entry->owner = THIS_MODULE; |
| 621 | } | 828 | } |
| 622 | |||
| 623 | /* 'status' [R] */ | ||
| 624 | entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS, | ||
| 625 | S_IRUGO, acpi_device_dir(device)); | ||
| 626 | if (!entry) | ||
| 627 | return -ENODEV; | ||
| 628 | else { | ||
| 629 | entry->proc_fops = &acpi_battery_state_ops; | ||
| 630 | entry->data = acpi_driver_data(device); | ||
| 631 | entry->owner = THIS_MODULE; | ||
| 632 | } | ||
| 633 | |||
| 634 | /* 'alarm' [R/W] */ | ||
| 635 | entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM, | ||
| 636 | S_IFREG | S_IRUGO | S_IWUSR, | ||
| 637 | acpi_device_dir(device)); | ||
| 638 | if (!entry) | ||
| 639 | return -ENODEV; | ||
| 640 | else { | ||
| 641 | entry->proc_fops = &acpi_battery_alarm_ops; | ||
| 642 | entry->data = acpi_driver_data(device); | ||
| 643 | entry->owner = THIS_MODULE; | ||
| 644 | } | 829 | } |
| 645 | 830 | ||
| 646 | return 0; | 831 | return 0; |
| @@ -648,15 +833,12 @@ static int acpi_battery_add_fs(struct acpi_device *device) | |||
| 648 | 833 | ||
| 649 | static int acpi_battery_remove_fs(struct acpi_device *device) | 834 | static int acpi_battery_remove_fs(struct acpi_device *device) |
| 650 | { | 835 | { |
| 651 | 836 | int i; | |
| 652 | if (acpi_device_dir(device)) { | 837 | if (acpi_device_dir(device)) { |
| 653 | remove_proc_entry(ACPI_BATTERY_FILE_ALARM, | 838 | for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { |
| 839 | remove_proc_entry(acpi_battery_file[i].name, | ||
| 654 | acpi_device_dir(device)); | 840 | acpi_device_dir(device)); |
| 655 | remove_proc_entry(ACPI_BATTERY_FILE_STATUS, | 841 | } |
| 656 | acpi_device_dir(device)); | ||
| 657 | remove_proc_entry(ACPI_BATTERY_FILE_INFO, | ||
| 658 | acpi_device_dir(device)); | ||
| 659 | |||
| 660 | remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); | 842 | remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); |
| 661 | acpi_device_dir(device) = NULL; | 843 | acpi_device_dir(device) = NULL; |
| 662 | } | 844 | } |
| @@ -673,7 +855,6 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
| 673 | struct acpi_battery *battery = data; | 855 | struct acpi_battery *battery = data; |
| 674 | struct acpi_device *device = NULL; | 856 | struct acpi_device *device = NULL; |
| 675 | 857 | ||
| 676 | |||
| 677 | if (!battery) | 858 | if (!battery) |
| 678 | return; | 859 | return; |
| 679 | 860 | ||
| @@ -684,8 +865,10 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
| 684 | case ACPI_BATTERY_NOTIFY_INFO: | 865 | case ACPI_BATTERY_NOTIFY_INFO: |
| 685 | case ACPI_NOTIFY_BUS_CHECK: | 866 | case ACPI_NOTIFY_BUS_CHECK: |
| 686 | case ACPI_NOTIFY_DEVICE_CHECK: | 867 | case ACPI_NOTIFY_DEVICE_CHECK: |
| 687 | acpi_battery_check(battery); | 868 | device = battery->device; |
| 688 | acpi_bus_generate_event(device, event, battery->flags.present); | 869 | acpi_battery_notify_update(battery); |
| 870 | acpi_bus_generate_event(device, event, | ||
| 871 | acpi_battery_present(battery)); | ||
| 689 | break; | 872 | break; |
| 690 | default: | 873 | default: |
| 691 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 874 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| @@ -702,7 +885,6 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 702 | acpi_status status = 0; | 885 | acpi_status status = 0; |
| 703 | struct acpi_battery *battery = NULL; | 886 | struct acpi_battery *battery = NULL; |
| 704 | 887 | ||
| 705 | |||
| 706 | if (!device) | 888 | if (!device) |
| 707 | return -EINVAL; | 889 | return -EINVAL; |
| 708 | 890 | ||
| @@ -710,15 +892,21 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 710 | if (!battery) | 892 | if (!battery) |
| 711 | return -ENOMEM; | 893 | return -ENOMEM; |
| 712 | 894 | ||
| 895 | mutex_init(&battery->mutex); | ||
| 896 | |||
| 897 | mutex_lock(&battery->mutex); | ||
| 898 | |||
| 713 | battery->device = device; | 899 | battery->device = device; |
| 714 | strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); | 900 | strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); |
| 715 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); | 901 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); |
| 716 | acpi_driver_data(device) = battery; | 902 | acpi_driver_data(device) = battery; |
| 717 | 903 | ||
| 718 | result = acpi_battery_check(battery); | 904 | result = acpi_battery_get_status(battery); |
| 719 | if (result) | 905 | if (result) |
| 720 | goto end; | 906 | goto end; |
| 721 | 907 | ||
| 908 | battery->flags.init_update = 1; | ||
| 909 | |||
| 722 | result = acpi_battery_add_fs(device); | 910 | result = acpi_battery_add_fs(device); |
| 723 | if (result) | 911 | if (result) |
| 724 | goto end; | 912 | goto end; |
| @@ -727,6 +915,7 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 727 | ACPI_ALL_NOTIFY, | 915 | ACPI_ALL_NOTIFY, |
| 728 | acpi_battery_notify, battery); | 916 | acpi_battery_notify, battery); |
| 729 | if (ACPI_FAILURE(status)) { | 917 | if (ACPI_FAILURE(status)) { |
| 918 | ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler")); | ||
| 730 | result = -ENODEV; | 919 | result = -ENODEV; |
| 731 | goto end; | 920 | goto end; |
| 732 | } | 921 | } |
| @@ -736,11 +925,14 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 736 | device->status.battery_present ? "present" : "absent"); | 925 | device->status.battery_present ? "present" : "absent"); |
| 737 | 926 | ||
| 738 | end: | 927 | end: |
| 928 | |||
| 739 | if (result) { | 929 | if (result) { |
| 740 | acpi_battery_remove_fs(device); | 930 | acpi_battery_remove_fs(device); |
| 741 | kfree(battery); | 931 | kfree(battery); |
| 742 | } | 932 | } |
| 743 | 933 | ||
| 934 | mutex_unlock(&battery->mutex); | ||
| 935 | |||
| 744 | return result; | 936 | return result; |
| 745 | } | 937 | } |
| 746 | 938 | ||
| @@ -749,18 +941,27 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
| 749 | acpi_status status = 0; | 941 | acpi_status status = 0; |
| 750 | struct acpi_battery *battery = NULL; | 942 | struct acpi_battery *battery = NULL; |
| 751 | 943 | ||
| 752 | |||
| 753 | if (!device || !acpi_driver_data(device)) | 944 | if (!device || !acpi_driver_data(device)) |
| 754 | return -EINVAL; | 945 | return -EINVAL; |
| 755 | 946 | ||
| 756 | battery = acpi_driver_data(device); | 947 | battery = acpi_driver_data(device); |
| 757 | 948 | ||
| 949 | mutex_lock(&battery->mutex); | ||
| 950 | |||
| 758 | status = acpi_remove_notify_handler(device->handle, | 951 | status = acpi_remove_notify_handler(device->handle, |
| 759 | ACPI_ALL_NOTIFY, | 952 | ACPI_ALL_NOTIFY, |
| 760 | acpi_battery_notify); | 953 | acpi_battery_notify); |
| 761 | 954 | ||
| 762 | acpi_battery_remove_fs(device); | 955 | acpi_battery_remove_fs(device); |
| 763 | 956 | ||
| 957 | kfree(battery->bif_data.pointer); | ||
| 958 | |||
| 959 | kfree(battery->bst_data.pointer); | ||
| 960 | |||
| 961 | mutex_unlock(&battery->mutex); | ||
| 962 | |||
| 963 | mutex_destroy(&battery->mutex); | ||
| 964 | |||
| 764 | kfree(battery); | 965 | kfree(battery); |
| 765 | 966 | ||
| 766 | return 0; | 967 | return 0; |
| @@ -775,7 +976,10 @@ static int acpi_battery_resume(struct acpi_device *device) | |||
| 775 | return -EINVAL; | 976 | return -EINVAL; |
| 776 | 977 | ||
| 777 | battery = device->driver_data; | 978 | battery = device->driver_data; |
| 778 | return acpi_battery_check(battery); | 979 | |
| 980 | battery->flags.init_update = 1; | ||
| 981 | |||
| 982 | return 0; | ||
| 779 | } | 983 | } |
| 780 | 984 | ||
| 781 | static int __init acpi_battery_init(void) | 985 | static int __init acpi_battery_init(void) |
| @@ -800,7 +1004,6 @@ static int __init acpi_battery_init(void) | |||
| 800 | 1004 | ||
| 801 | static void __exit acpi_battery_exit(void) | 1005 | static void __exit acpi_battery_exit(void) |
| 802 | { | 1006 | { |
| 803 | |||
| 804 | acpi_bus_unregister_driver(&acpi_battery_driver); | 1007 | acpi_bus_unregister_driver(&acpi_battery_driver); |
| 805 | 1008 | ||
| 806 | acpi_unlock_battery_dir(acpi_battery_dir); | 1009 | acpi_unlock_battery_dir(acpi_battery_dir); |
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index fb3f31b5e69f..56a5b3fffeb3 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c | |||
| @@ -288,6 +288,11 @@ static int bay_add(acpi_handle handle, int id) | |||
| 288 | new_bay->pdev = pdev; | 288 | new_bay->pdev = pdev; |
| 289 | platform_set_drvdata(pdev, new_bay); | 289 | platform_set_drvdata(pdev, new_bay); |
| 290 | 290 | ||
| 291 | /* | ||
| 292 | * we want the bay driver to be able to send uevents | ||
| 293 | */ | ||
| 294 | pdev->dev.uevent_suppress = 0; | ||
| 295 | |||
| 291 | if (acpi_bay_add_fs(new_bay)) { | 296 | if (acpi_bay_add_fs(new_bay)) { |
| 292 | platform_device_unregister(new_bay->pdev); | 297 | platform_device_unregister(new_bay->pdev); |
| 293 | goto bay_add_err; | 298 | goto bay_add_err; |
| @@ -328,18 +333,12 @@ static void bay_notify(acpi_handle handle, u32 event, void *data) | |||
| 328 | { | 333 | { |
| 329 | struct bay *bay_dev = (struct bay *)data; | 334 | struct bay *bay_dev = (struct bay *)data; |
| 330 | struct device *dev = &bay_dev->pdev->dev; | 335 | struct device *dev = &bay_dev->pdev->dev; |
| 336 | char event_string[12]; | ||
| 337 | char *envp[] = { event_string, NULL }; | ||
| 331 | 338 | ||
| 332 | bay_dprintk(handle, "Bay event"); | 339 | bay_dprintk(handle, "Bay event"); |
| 333 | 340 | sprintf(event_string, "BAY_EVENT=%d\n", event); | |
| 334 | switch(event) { | 341 | kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); |
| 335 | case ACPI_NOTIFY_BUS_CHECK: | ||
| 336 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
| 337 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
| 338 | kobject_uevent(&dev->kobj, KOBJ_CHANGE); | ||
| 339 | break; | ||
| 340 | default: | ||
| 341 | printk(KERN_ERR PREFIX "Bay: unknown event %d\n", event); | ||
| 342 | } | ||
| 343 | } | 342 | } |
| 344 | 343 | ||
| 345 | static acpi_status | 344 | static acpi_status |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index e5084ececb6f..6b2658c96242 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -292,6 +292,10 @@ int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data) | |||
| 292 | if (!device) | 292 | if (!device) |
| 293 | return -EINVAL; | 293 | return -EINVAL; |
| 294 | 294 | ||
| 295 | if (acpi_bus_generate_genetlink_event(device, type, data)) | ||
| 296 | printk(KERN_WARNING PREFIX | ||
| 297 | "Failed to generate an ACPI event via genetlink!\n"); | ||
| 298 | |||
| 295 | /* drop event on the floor if no one's listening */ | 299 | /* drop event on the floor if no one's listening */ |
| 296 | if (!event_is_open) | 300 | if (!event_is_open) |
| 297 | return 0; | 301 | return 0; |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 4546bf873aea..6192c8be66df 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
| @@ -40,8 +40,15 @@ MODULE_AUTHOR("Kristen Carlson Accardi"); | |||
| 40 | MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); | 40 | MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); |
| 41 | MODULE_LICENSE("GPL"); | 41 | MODULE_LICENSE("GPL"); |
| 42 | 42 | ||
| 43 | static int immediate_undock = 1; | ||
| 44 | module_param(immediate_undock, bool, 0644); | ||
| 45 | MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to " | ||
| 46 | "undock immediately when the undock button is pressed, 0 will cause" | ||
| 47 | " the driver to wait for userspace to write the undock sysfs file " | ||
| 48 | " before undocking"); | ||
| 49 | |||
| 43 | static struct atomic_notifier_head dock_notifier_list; | 50 | static struct atomic_notifier_head dock_notifier_list; |
| 44 | static struct platform_device dock_device; | 51 | static struct platform_device *dock_device; |
| 45 | static char dock_device_name[] = "dock"; | 52 | static char dock_device_name[] = "dock"; |
| 46 | 53 | ||
| 47 | struct dock_station { | 54 | struct dock_station { |
| @@ -63,6 +70,7 @@ struct dock_dependent_device { | |||
| 63 | }; | 70 | }; |
| 64 | 71 | ||
| 65 | #define DOCK_DOCKING 0x00000001 | 72 | #define DOCK_DOCKING 0x00000001 |
| 73 | #define DOCK_UNDOCKING 0x00000002 | ||
| 66 | #define DOCK_EVENT 3 | 74 | #define DOCK_EVENT 3 |
| 67 | #define UNDOCK_EVENT 2 | 75 | #define UNDOCK_EVENT 2 |
| 68 | 76 | ||
| @@ -327,12 +335,20 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) | |||
| 327 | 335 | ||
| 328 | static void dock_event(struct dock_station *ds, u32 event, int num) | 336 | static void dock_event(struct dock_station *ds, u32 event, int num) |
| 329 | { | 337 | { |
| 330 | struct device *dev = &dock_device.dev; | 338 | struct device *dev = &dock_device->dev; |
| 339 | char event_string[7]; | ||
| 340 | char *envp[] = { event_string, NULL }; | ||
| 341 | |||
| 342 | if (num == UNDOCK_EVENT) | ||
| 343 | sprintf(event_string, "UNDOCK"); | ||
| 344 | else | ||
| 345 | sprintf(event_string, "DOCK"); | ||
| 346 | |||
| 331 | /* | 347 | /* |
| 332 | * Indicate that the status of the dock station has | 348 | * Indicate that the status of the dock station has |
| 333 | * changed. | 349 | * changed. |
| 334 | */ | 350 | */ |
| 335 | kobject_uevent(&dev->kobj, KOBJ_CHANGE); | 351 | kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); |
| 336 | } | 352 | } |
| 337 | 353 | ||
| 338 | /** | 354 | /** |
| @@ -380,12 +396,11 @@ static void handle_dock(struct dock_station *ds, int dock) | |||
| 380 | union acpi_object arg; | 396 | union acpi_object arg; |
| 381 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 397 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 382 | struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 398 | struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 383 | union acpi_object *obj; | ||
| 384 | 399 | ||
| 385 | acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer); | 400 | acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer); |
| 386 | obj = name_buffer.pointer; | ||
| 387 | 401 | ||
| 388 | printk(KERN_INFO PREFIX "%s\n", dock ? "docking" : "undocking"); | 402 | printk(KERN_INFO PREFIX "%s - %s\n", |
| 403 | (char *)name_buffer.pointer, dock ? "docking" : "undocking"); | ||
| 389 | 404 | ||
| 390 | /* _DCK method has one argument */ | 405 | /* _DCK method has one argument */ |
| 391 | arg_list.count = 1; | 406 | arg_list.count = 1; |
| @@ -394,7 +409,8 @@ static void handle_dock(struct dock_station *ds, int dock) | |||
| 394 | arg.integer.value = dock; | 409 | arg.integer.value = dock; |
| 395 | status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); | 410 | status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); |
| 396 | if (ACPI_FAILURE(status)) | 411 | if (ACPI_FAILURE(status)) |
| 397 | pr_debug("%s: failed to execute _DCK\n", obj->string.pointer); | 412 | printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n", |
| 413 | (char *)name_buffer.pointer); | ||
| 398 | kfree(buffer.pointer); | 414 | kfree(buffer.pointer); |
| 399 | kfree(name_buffer.pointer); | 415 | kfree(name_buffer.pointer); |
| 400 | } | 416 | } |
| @@ -420,6 +436,16 @@ static inline void complete_dock(struct dock_station *ds) | |||
| 420 | ds->last_dock_time = jiffies; | 436 | ds->last_dock_time = jiffies; |
| 421 | } | 437 | } |
| 422 | 438 | ||
| 439 | static inline void begin_undock(struct dock_station *ds) | ||
| 440 | { | ||
| 441 | ds->flags |= DOCK_UNDOCKING; | ||
| 442 | } | ||
| 443 | |||
| 444 | static inline void complete_undock(struct dock_station *ds) | ||
| 445 | { | ||
| 446 | ds->flags &= ~(DOCK_UNDOCKING); | ||
| 447 | } | ||
| 448 | |||
| 423 | /** | 449 | /** |
| 424 | * dock_in_progress - see if we are in the middle of handling a dock event | 450 | * dock_in_progress - see if we are in the middle of handling a dock event |
| 425 | * @ds: the dock station | 451 | * @ds: the dock station |
| @@ -550,7 +576,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event) | |||
| 550 | printk(KERN_ERR PREFIX "Unable to undock!\n"); | 576 | printk(KERN_ERR PREFIX "Unable to undock!\n"); |
| 551 | return -EBUSY; | 577 | return -EBUSY; |
| 552 | } | 578 | } |
| 553 | 579 | complete_undock(ds); | |
| 554 | return 0; | 580 | return 0; |
| 555 | } | 581 | } |
| 556 | 582 | ||
| @@ -594,7 +620,11 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) | |||
| 594 | * to the driver who wish to hotplug. | 620 | * to the driver who wish to hotplug. |
| 595 | */ | 621 | */ |
| 596 | case ACPI_NOTIFY_EJECT_REQUEST: | 622 | case ACPI_NOTIFY_EJECT_REQUEST: |
| 597 | handle_eject_request(ds, event); | 623 | begin_undock(ds); |
| 624 | if (immediate_undock) | ||
| 625 | handle_eject_request(ds, event); | ||
| 626 | else | ||
| 627 | dock_event(ds, event, UNDOCK_EVENT); | ||
| 598 | break; | 628 | break; |
| 599 | default: | 629 | default: |
| 600 | printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); | 630 | printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); |
| @@ -653,6 +683,17 @@ static ssize_t show_docked(struct device *dev, | |||
| 653 | DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); | 683 | DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); |
| 654 | 684 | ||
| 655 | /* | 685 | /* |
| 686 | * show_flags - read method for flags file in sysfs | ||
| 687 | */ | ||
| 688 | static ssize_t show_flags(struct device *dev, | ||
| 689 | struct device_attribute *attr, char *buf) | ||
| 690 | { | ||
| 691 | return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); | ||
| 692 | |||
| 693 | } | ||
| 694 | DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL); | ||
| 695 | |||
| 696 | /* | ||
| 656 | * write_undock - write method for "undock" file in sysfs | 697 | * write_undock - write method for "undock" file in sysfs |
| 657 | */ | 698 | */ |
| 658 | static ssize_t write_undock(struct device *dev, struct device_attribute *attr, | 699 | static ssize_t write_undock(struct device *dev, struct device_attribute *attr, |
| @@ -675,16 +716,15 @@ static ssize_t show_dock_uid(struct device *dev, | |||
| 675 | struct device_attribute *attr, char *buf) | 716 | struct device_attribute *attr, char *buf) |
| 676 | { | 717 | { |
| 677 | unsigned long lbuf; | 718 | unsigned long lbuf; |
| 678 | acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf); | 719 | acpi_status status = acpi_evaluate_integer(dock_station->handle, |
| 679 | if(ACPI_FAILURE(status)) { | 720 | "_UID", NULL, &lbuf); |
| 721 | if (ACPI_FAILURE(status)) | ||
| 680 | return 0; | 722 | return 0; |
| 681 | } | 723 | |
| 682 | return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf); | 724 | return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf); |
| 683 | } | 725 | } |
| 684 | DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); | 726 | DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); |
| 685 | 727 | ||
| 686 | |||
| 687 | |||
| 688 | /** | 728 | /** |
| 689 | * dock_add - add a new dock station | 729 | * dock_add - add a new dock station |
| 690 | * @handle: the dock station handle | 730 | * @handle: the dock station handle |
| @@ -711,33 +751,53 @@ static int dock_add(acpi_handle handle) | |||
| 711 | ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); | 751 | ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); |
| 712 | 752 | ||
| 713 | /* initialize platform device stuff */ | 753 | /* initialize platform device stuff */ |
| 714 | dock_device.name = dock_device_name; | 754 | dock_device = |
| 715 | ret = platform_device_register(&dock_device); | 755 | platform_device_register_simple(dock_device_name, 0, NULL, 0); |
| 756 | if (IS_ERR(dock_device)) { | ||
| 757 | kfree(dock_station); | ||
| 758 | dock_station = NULL; | ||
| 759 | return PTR_ERR(dock_device); | ||
| 760 | } | ||
| 761 | |||
| 762 | /* we want the dock device to send uevents */ | ||
| 763 | dock_device->dev.uevent_suppress = 0; | ||
| 764 | |||
| 765 | ret = device_create_file(&dock_device->dev, &dev_attr_docked); | ||
| 716 | if (ret) { | 766 | if (ret) { |
| 717 | printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret); | 767 | printk("Error %d adding sysfs file\n", ret); |
| 768 | platform_device_unregister(dock_device); | ||
| 718 | kfree(dock_station); | 769 | kfree(dock_station); |
| 770 | dock_station = NULL; | ||
| 719 | return ret; | 771 | return ret; |
| 720 | } | 772 | } |
| 721 | ret = device_create_file(&dock_device.dev, &dev_attr_docked); | 773 | ret = device_create_file(&dock_device->dev, &dev_attr_undock); |
| 722 | if (ret) { | 774 | if (ret) { |
| 723 | printk("Error %d adding sysfs file\n", ret); | 775 | printk("Error %d adding sysfs file\n", ret); |
| 724 | platform_device_unregister(&dock_device); | 776 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 777 | platform_device_unregister(dock_device); | ||
| 725 | kfree(dock_station); | 778 | kfree(dock_station); |
| 779 | dock_station = NULL; | ||
| 726 | return ret; | 780 | return ret; |
| 727 | } | 781 | } |
| 728 | ret = device_create_file(&dock_device.dev, &dev_attr_undock); | 782 | ret = device_create_file(&dock_device->dev, &dev_attr_uid); |
| 729 | if (ret) { | 783 | if (ret) { |
| 730 | printk("Error %d adding sysfs file\n", ret); | 784 | printk("Error %d adding sysfs file\n", ret); |
| 731 | device_remove_file(&dock_device.dev, &dev_attr_docked); | 785 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 732 | platform_device_unregister(&dock_device); | 786 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
| 787 | platform_device_unregister(dock_device); | ||
| 733 | kfree(dock_station); | 788 | kfree(dock_station); |
| 789 | dock_station = NULL; | ||
| 734 | return ret; | 790 | return ret; |
| 735 | } | 791 | } |
| 736 | ret = device_create_file(&dock_device.dev, &dev_attr_uid); | 792 | ret = device_create_file(&dock_device->dev, &dev_attr_flags); |
| 737 | if (ret) { | 793 | if (ret) { |
| 738 | printk("Error %d adding sysfs file\n", ret); | 794 | printk("Error %d adding sysfs file\n", ret); |
| 739 | platform_device_unregister(&dock_device); | 795 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 796 | device_remove_file(&dock_device->dev, &dev_attr_undock); | ||
| 797 | device_remove_file(&dock_device->dev, &dev_attr_uid); | ||
| 798 | platform_device_unregister(dock_device); | ||
| 740 | kfree(dock_station); | 799 | kfree(dock_station); |
| 800 | dock_station = NULL; | ||
| 741 | return ret; | 801 | return ret; |
| 742 | } | 802 | } |
| 743 | 803 | ||
| @@ -750,6 +810,7 @@ static int dock_add(acpi_handle handle) | |||
| 750 | dd = alloc_dock_dependent_device(handle); | 810 | dd = alloc_dock_dependent_device(handle); |
| 751 | if (!dd) { | 811 | if (!dd) { |
| 752 | kfree(dock_station); | 812 | kfree(dock_station); |
| 813 | dock_station = NULL; | ||
| 753 | ret = -ENOMEM; | 814 | ret = -ENOMEM; |
| 754 | goto dock_add_err_unregister; | 815 | goto dock_add_err_unregister; |
| 755 | } | 816 | } |
| @@ -773,10 +834,13 @@ static int dock_add(acpi_handle handle) | |||
| 773 | dock_add_err: | 834 | dock_add_err: |
| 774 | kfree(dd); | 835 | kfree(dd); |
| 775 | dock_add_err_unregister: | 836 | dock_add_err_unregister: |
| 776 | device_remove_file(&dock_device.dev, &dev_attr_docked); | 837 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 777 | device_remove_file(&dock_device.dev, &dev_attr_undock); | 838 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
| 778 | platform_device_unregister(&dock_device); | 839 | device_remove_file(&dock_device->dev, &dev_attr_uid); |
| 840 | device_remove_file(&dock_device->dev, &dev_attr_flags); | ||
| 841 | platform_device_unregister(dock_device); | ||
| 779 | kfree(dock_station); | 842 | kfree(dock_station); |
| 843 | dock_station = NULL; | ||
| 780 | return ret; | 844 | return ret; |
| 781 | } | 845 | } |
| 782 | 846 | ||
| @@ -804,12 +868,15 @@ static int dock_remove(void) | |||
| 804 | printk(KERN_ERR "Error removing notify handler\n"); | 868 | printk(KERN_ERR "Error removing notify handler\n"); |
| 805 | 869 | ||
| 806 | /* cleanup sysfs */ | 870 | /* cleanup sysfs */ |
| 807 | device_remove_file(&dock_device.dev, &dev_attr_docked); | 871 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 808 | device_remove_file(&dock_device.dev, &dev_attr_undock); | 872 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
| 809 | platform_device_unregister(&dock_device); | 873 | device_remove_file(&dock_device->dev, &dev_attr_uid); |
| 874 | device_remove_file(&dock_device->dev, &dev_attr_flags); | ||
| 875 | platform_device_unregister(dock_device); | ||
| 810 | 876 | ||
| 811 | /* free dock station memory */ | 877 | /* free dock station memory */ |
| 812 | kfree(dock_station); | 878 | kfree(dock_station); |
| 879 | dock_station = NULL; | ||
| 813 | return 0; | 880 | return 0; |
| 814 | } | 881 | } |
| 815 | 882 | ||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 82f496c07675..10e851021eca 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -34,25 +34,26 @@ | |||
| 34 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
| 35 | #include <linux/seq_file.h> | 35 | #include <linux/seq_file.h> |
| 36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
| 37 | #include <linux/list.h> | ||
| 37 | #include <asm/io.h> | 38 | #include <asm/io.h> |
| 38 | #include <acpi/acpi_bus.h> | 39 | #include <acpi/acpi_bus.h> |
| 39 | #include <acpi/acpi_drivers.h> | 40 | #include <acpi/acpi_drivers.h> |
| 40 | #include <acpi/actypes.h> | 41 | #include <acpi/actypes.h> |
| 41 | 42 | ||
| 42 | #define _COMPONENT ACPI_EC_COMPONENT | ||
| 43 | ACPI_MODULE_NAME("ec"); | ||
| 44 | #define ACPI_EC_COMPONENT 0x00100000 | ||
| 45 | #define ACPI_EC_CLASS "embedded_controller" | 43 | #define ACPI_EC_CLASS "embedded_controller" |
| 46 | #define ACPI_EC_HID "PNP0C09" | 44 | #define ACPI_EC_HID "PNP0C09" |
| 47 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" | 45 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" |
| 48 | #define ACPI_EC_FILE_INFO "info" | 46 | #define ACPI_EC_FILE_INFO "info" |
| 47 | |||
| 49 | #undef PREFIX | 48 | #undef PREFIX |
| 50 | #define PREFIX "ACPI: EC: " | 49 | #define PREFIX "ACPI: EC: " |
| 50 | |||
| 51 | /* EC status register */ | 51 | /* EC status register */ |
| 52 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ | 52 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ |
| 53 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ | 53 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ |
| 54 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ | 54 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ |
| 55 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ | 55 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ |
| 56 | |||
| 56 | /* EC commands */ | 57 | /* EC commands */ |
| 57 | enum ec_command { | 58 | enum ec_command { |
| 58 | ACPI_EC_COMMAND_READ = 0x80, | 59 | ACPI_EC_COMMAND_READ = 0x80, |
| @@ -61,6 +62,7 @@ enum ec_command { | |||
| 61 | ACPI_EC_BURST_DISABLE = 0x83, | 62 | ACPI_EC_BURST_DISABLE = 0x83, |
| 62 | ACPI_EC_COMMAND_QUERY = 0x84, | 63 | ACPI_EC_COMMAND_QUERY = 0x84, |
| 63 | }; | 64 | }; |
| 65 | |||
| 64 | /* EC events */ | 66 | /* EC events */ |
| 65 | enum ec_event { | 67 | enum ec_event { |
| 66 | ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ | 68 | ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ |
| @@ -94,6 +96,16 @@ static struct acpi_driver acpi_ec_driver = { | |||
| 94 | 96 | ||
| 95 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ | 97 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ |
| 96 | /* External interfaces use first EC only, so remember */ | 98 | /* External interfaces use first EC only, so remember */ |
| 99 | typedef int (*acpi_ec_query_func) (void *data); | ||
| 100 | |||
| 101 | struct acpi_ec_query_handler { | ||
| 102 | struct list_head node; | ||
| 103 | acpi_ec_query_func func; | ||
| 104 | acpi_handle handle; | ||
| 105 | void *data; | ||
| 106 | u8 query_bit; | ||
| 107 | }; | ||
| 108 | |||
| 97 | static struct acpi_ec { | 109 | static struct acpi_ec { |
| 98 | acpi_handle handle; | 110 | acpi_handle handle; |
| 99 | unsigned long gpe; | 111 | unsigned long gpe; |
| @@ -104,6 +116,7 @@ static struct acpi_ec { | |||
| 104 | atomic_t query_pending; | 116 | atomic_t query_pending; |
| 105 | atomic_t event_count; | 117 | atomic_t event_count; |
| 106 | wait_queue_head_t wait; | 118 | wait_queue_head_t wait; |
| 119 | struct list_head list; | ||
| 107 | } *boot_ec, *first_ec; | 120 | } *boot_ec, *first_ec; |
| 108 | 121 | ||
| 109 | /* -------------------------------------------------------------------------- | 122 | /* -------------------------------------------------------------------------- |
| @@ -245,7 +258,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, | |||
| 245 | 258 | ||
| 246 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); | 259 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); |
| 247 | if (status) { | 260 | if (status) { |
| 248 | printk(KERN_DEBUG PREFIX | 261 | printk(KERN_ERR PREFIX |
| 249 | "input buffer is not empty, aborting transaction\n"); | 262 | "input buffer is not empty, aborting transaction\n"); |
| 250 | goto end; | 263 | goto end; |
| 251 | } | 264 | } |
| @@ -394,21 +407,67 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) | |||
| 394 | /* -------------------------------------------------------------------------- | 407 | /* -------------------------------------------------------------------------- |
| 395 | Event Management | 408 | Event Management |
| 396 | -------------------------------------------------------------------------- */ | 409 | -------------------------------------------------------------------------- */ |
| 410 | int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, | ||
| 411 | acpi_handle handle, acpi_ec_query_func func, | ||
| 412 | void *data) | ||
| 413 | { | ||
| 414 | struct acpi_ec_query_handler *handler = | ||
| 415 | kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL); | ||
| 416 | if (!handler) | ||
| 417 | return -ENOMEM; | ||
| 418 | |||
| 419 | handler->query_bit = query_bit; | ||
| 420 | handler->handle = handle; | ||
| 421 | handler->func = func; | ||
| 422 | handler->data = data; | ||
| 423 | mutex_lock(&ec->lock); | ||
| 424 | list_add_tail(&handler->node, &ec->list); | ||
| 425 | mutex_unlock(&ec->lock); | ||
| 426 | return 0; | ||
| 427 | } | ||
| 428 | |||
| 429 | EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler); | ||
| 430 | |||
| 431 | void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) | ||
| 432 | { | ||
| 433 | struct acpi_ec_query_handler *handler; | ||
| 434 | mutex_lock(&ec->lock); | ||
| 435 | list_for_each_entry(handler, &ec->list, node) { | ||
| 436 | if (query_bit == handler->query_bit) { | ||
| 437 | list_del(&handler->node); | ||
| 438 | kfree(handler); | ||
| 439 | break; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | mutex_unlock(&ec->lock); | ||
| 443 | } | ||
| 444 | |||
| 445 | EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); | ||
| 397 | 446 | ||
| 398 | static void acpi_ec_gpe_query(void *ec_cxt) | 447 | static void acpi_ec_gpe_query(void *ec_cxt) |
| 399 | { | 448 | { |
| 400 | struct acpi_ec *ec = ec_cxt; | 449 | struct acpi_ec *ec = ec_cxt; |
| 401 | u8 value = 0; | 450 | u8 value = 0; |
| 402 | char object_name[8]; | 451 | struct acpi_ec_query_handler *handler, copy; |
| 403 | 452 | ||
| 404 | if (!ec || acpi_ec_query(ec, &value)) | 453 | if (!ec || acpi_ec_query(ec, &value)) |
| 405 | return; | 454 | return; |
| 406 | 455 | mutex_lock(&ec->lock); | |
| 407 | snprintf(object_name, 8, "_Q%2.2X", value); | 456 | list_for_each_entry(handler, &ec->list, node) { |
| 408 | 457 | if (value == handler->query_bit) { | |
| 409 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); | 458 | /* have custom handler for this bit */ |
| 410 | 459 | memcpy(©, handler, sizeof(copy)); | |
| 411 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); | 460 | mutex_unlock(&ec->lock); |
| 461 | if (copy.func) { | ||
| 462 | copy.func(copy.data); | ||
| 463 | } else if (copy.handle) { | ||
| 464 | acpi_evaluate_object(copy.handle, NULL, NULL, NULL); | ||
| 465 | } | ||
| 466 | return; | ||
| 467 | } | ||
| 468 | } | ||
| 469 | mutex_unlock(&ec->lock); | ||
| 470 | printk(KERN_ERR PREFIX "Handler for query 0x%x is not found!\n", value); | ||
| 412 | } | 471 | } |
| 413 | 472 | ||
| 414 | static u32 acpi_ec_gpe_handler(void *data) | 473 | static u32 acpi_ec_gpe_handler(void *data) |
| @@ -427,8 +486,7 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
| 427 | if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) { | 486 | if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) { |
| 428 | atomic_set(&ec->query_pending, 1); | 487 | atomic_set(&ec->query_pending, 1); |
| 429 | status = | 488 | status = |
| 430 | acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, | 489 | acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); |
| 431 | ec); | ||
| 432 | } | 490 | } |
| 433 | 491 | ||
| 434 | return status == AE_OK ? | 492 | return status == AE_OK ? |
| @@ -454,57 +512,35 @@ acpi_ec_space_setup(acpi_handle region_handle, | |||
| 454 | } | 512 | } |
| 455 | 513 | ||
| 456 | static acpi_status | 514 | static acpi_status |
| 457 | acpi_ec_space_handler(u32 function, | 515 | acpi_ec_space_handler(u32 function, acpi_physical_address address, |
| 458 | acpi_physical_address address, | 516 | u32 bits, acpi_integer *value, |
| 459 | u32 bit_width, | ||
| 460 | acpi_integer * value, | ||
| 461 | void *handler_context, void *region_context) | 517 | void *handler_context, void *region_context) |
| 462 | { | 518 | { |
| 463 | int result = 0; | ||
| 464 | struct acpi_ec *ec = handler_context; | 519 | struct acpi_ec *ec = handler_context; |
| 465 | u64 temp = *value; | 520 | int result = 0, i = 0; |
| 466 | acpi_integer f_v = 0; | 521 | u8 temp = 0; |
| 467 | int i = 0; | ||
| 468 | 522 | ||
| 469 | if ((address > 0xFF) || !value || !handler_context) | 523 | if ((address > 0xFF) || !value || !handler_context) |
| 470 | return AE_BAD_PARAMETER; | 524 | return AE_BAD_PARAMETER; |
| 471 | 525 | ||
| 472 | if (bit_width != 8 && acpi_strict) { | 526 | if (function != ACPI_READ && function != ACPI_WRITE) |
| 473 | return AE_BAD_PARAMETER; | 527 | return AE_BAD_PARAMETER; |
| 474 | } | ||
| 475 | |||
| 476 | next_byte: | ||
| 477 | switch (function) { | ||
| 478 | case ACPI_READ: | ||
| 479 | temp = 0; | ||
| 480 | result = acpi_ec_read(ec, (u8) address, (u8 *) & temp); | ||
| 481 | break; | ||
| 482 | case ACPI_WRITE: | ||
| 483 | result = acpi_ec_write(ec, (u8) address, (u8) temp); | ||
| 484 | break; | ||
| 485 | default: | ||
| 486 | result = -EINVAL; | ||
| 487 | goto out; | ||
| 488 | break; | ||
| 489 | } | ||
| 490 | 528 | ||
| 491 | bit_width -= 8; | 529 | if (bits != 8 && acpi_strict) |
| 492 | if (bit_width) { | 530 | return AE_BAD_PARAMETER; |
| 493 | if (function == ACPI_READ) | ||
| 494 | f_v |= temp << 8 * i; | ||
| 495 | if (function == ACPI_WRITE) | ||
| 496 | temp >>= 8; | ||
| 497 | i++; | ||
| 498 | address++; | ||
| 499 | goto next_byte; | ||
| 500 | } | ||
| 501 | 531 | ||
| 502 | if (function == ACPI_READ) { | 532 | while (bits - i > 0) { |
| 503 | f_v |= temp << 8 * i; | 533 | if (function == ACPI_READ) { |
| 504 | *value = f_v; | 534 | result = acpi_ec_read(ec, address, &temp); |
| 535 | (*value) |= ((acpi_integer)temp) << i; | ||
| 536 | } else { | ||
| 537 | temp = 0xff & ((*value) >> i); | ||
| 538 | result = acpi_ec_write(ec, address, temp); | ||
| 539 | } | ||
| 540 | i += 8; | ||
| 541 | ++address; | ||
| 505 | } | 542 | } |
| 506 | 543 | ||
| 507 | out: | ||
| 508 | switch (result) { | 544 | switch (result) { |
| 509 | case -EINVAL: | 545 | case -EINVAL: |
| 510 | return AE_BAD_PARAMETER; | 546 | return AE_BAD_PARAMETER; |
| @@ -597,9 +633,6 @@ static int acpi_ec_remove_fs(struct acpi_device *device) | |||
| 597 | static acpi_status | 633 | static acpi_status |
| 598 | ec_parse_io_ports(struct acpi_resource *resource, void *context); | 634 | ec_parse_io_ports(struct acpi_resource *resource, void *context); |
| 599 | 635 | ||
| 600 | static acpi_status | ||
| 601 | ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval); | ||
| 602 | |||
| 603 | static struct acpi_ec *make_acpi_ec(void) | 636 | static struct acpi_ec *make_acpi_ec(void) |
| 604 | { | 637 | { |
| 605 | struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); | 638 | struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); |
| @@ -610,13 +643,52 @@ static struct acpi_ec *make_acpi_ec(void) | |||
| 610 | atomic_set(&ec->event_count, 1); | 643 | atomic_set(&ec->event_count, 1); |
| 611 | mutex_init(&ec->lock); | 644 | mutex_init(&ec->lock); |
| 612 | init_waitqueue_head(&ec->wait); | 645 | init_waitqueue_head(&ec->wait); |
| 646 | INIT_LIST_HEAD(&ec->list); | ||
| 613 | 647 | ||
| 614 | return ec; | 648 | return ec; |
| 615 | } | 649 | } |
| 616 | 650 | ||
| 651 | static acpi_status | ||
| 652 | acpi_ec_register_query_methods(acpi_handle handle, u32 level, | ||
| 653 | void *context, void **return_value) | ||
| 654 | { | ||
| 655 | struct acpi_namespace_node *node = handle; | ||
| 656 | struct acpi_ec *ec = context; | ||
| 657 | int value = 0; | ||
| 658 | if (sscanf(node->name.ascii, "_Q%x", &value) == 1) { | ||
| 659 | acpi_ec_add_query_handler(ec, value, handle, NULL, NULL); | ||
| 660 | } | ||
| 661 | return AE_OK; | ||
| 662 | } | ||
| 663 | |||
| 664 | static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle) | ||
| 665 | { | ||
| 666 | if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS, | ||
| 667 | ec_parse_io_ports, ec))) | ||
| 668 | return -EINVAL; | ||
| 669 | |||
| 670 | /* Get GPE bit assignment (EC events). */ | ||
| 671 | /* TODO: Add support for _GPE returning a package */ | ||
| 672 | if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe))) | ||
| 673 | return -EINVAL; | ||
| 674 | |||
| 675 | /* Use the global lock for all EC transactions? */ | ||
| 676 | acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); | ||
| 677 | |||
| 678 | /* Find and register all query methods */ | ||
| 679 | acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1, | ||
| 680 | acpi_ec_register_query_methods, ec, NULL); | ||
| 681 | |||
| 682 | ec->handle = handle; | ||
| 683 | |||
| 684 | printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx", | ||
| 685 | ec->gpe, ec->command_addr, ec->data_addr); | ||
| 686 | |||
| 687 | return 0; | ||
| 688 | } | ||
| 689 | |||
| 617 | static int acpi_ec_add(struct acpi_device *device) | 690 | static int acpi_ec_add(struct acpi_device *device) |
| 618 | { | 691 | { |
| 619 | acpi_status status = AE_OK; | ||
| 620 | struct acpi_ec *ec = NULL; | 692 | struct acpi_ec *ec = NULL; |
| 621 | 693 | ||
| 622 | if (!device) | 694 | if (!device) |
| @@ -629,8 +701,7 @@ static int acpi_ec_add(struct acpi_device *device) | |||
| 629 | if (!ec) | 701 | if (!ec) |
| 630 | return -ENOMEM; | 702 | return -ENOMEM; |
| 631 | 703 | ||
| 632 | status = ec_parse_device(device->handle, 0, ec, NULL); | 704 | if (ec_parse_device(ec, device->handle)) { |
| 633 | if (status != AE_CTRL_TERMINATE) { | ||
| 634 | kfree(ec); | 705 | kfree(ec); |
| 635 | return -EINVAL; | 706 | return -EINVAL; |
| 636 | } | 707 | } |
| @@ -641,6 +712,8 @@ static int acpi_ec_add(struct acpi_device *device) | |||
| 641 | /* We might have incorrect info for GL at boot time */ | 712 | /* We might have incorrect info for GL at boot time */ |
| 642 | mutex_lock(&boot_ec->lock); | 713 | mutex_lock(&boot_ec->lock); |
| 643 | boot_ec->global_lock = ec->global_lock; | 714 | boot_ec->global_lock = ec->global_lock; |
| 715 | /* Copy handlers from new ec into boot ec */ | ||
| 716 | list_splice(&ec->list, &boot_ec->list); | ||
| 644 | mutex_unlock(&boot_ec->lock); | 717 | mutex_unlock(&boot_ec->lock); |
| 645 | kfree(ec); | 718 | kfree(ec); |
| 646 | ec = boot_ec; | 719 | ec = boot_ec; |
| @@ -651,22 +724,24 @@ static int acpi_ec_add(struct acpi_device *device) | |||
| 651 | acpi_driver_data(device) = ec; | 724 | acpi_driver_data(device) = ec; |
| 652 | 725 | ||
| 653 | acpi_ec_add_fs(device); | 726 | acpi_ec_add_fs(device); |
| 654 | |||
| 655 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.", | ||
| 656 | acpi_device_name(device), acpi_device_bid(device), | ||
| 657 | (u32) ec->gpe)); | ||
| 658 | |||
| 659 | return 0; | 727 | return 0; |
| 660 | } | 728 | } |
| 661 | 729 | ||
| 662 | static int acpi_ec_remove(struct acpi_device *device, int type) | 730 | static int acpi_ec_remove(struct acpi_device *device, int type) |
| 663 | { | 731 | { |
| 664 | struct acpi_ec *ec; | 732 | struct acpi_ec *ec; |
| 733 | struct acpi_ec_query_handler *handler; | ||
| 665 | 734 | ||
| 666 | if (!device) | 735 | if (!device) |
| 667 | return -EINVAL; | 736 | return -EINVAL; |
| 668 | 737 | ||
| 669 | ec = acpi_driver_data(device); | 738 | ec = acpi_driver_data(device); |
| 739 | mutex_lock(&ec->lock); | ||
| 740 | list_for_each_entry(handler, &ec->list, node) { | ||
| 741 | list_del(&handler->node); | ||
| 742 | kfree(handler); | ||
| 743 | } | ||
| 744 | mutex_unlock(&ec->lock); | ||
| 670 | acpi_ec_remove_fs(device); | 745 | acpi_ec_remove_fs(device); |
| 671 | acpi_driver_data(device) = NULL; | 746 | acpi_driver_data(device) = NULL; |
| 672 | if (ec == first_ec) | 747 | if (ec == first_ec) |
| @@ -722,15 +797,13 @@ static int ec_install_handlers(struct acpi_ec *ec) | |||
| 722 | return -ENODEV; | 797 | return -ENODEV; |
| 723 | } | 798 | } |
| 724 | 799 | ||
| 725 | /* EC is fully operational, allow queries */ | ||
| 726 | atomic_set(&ec->query_pending, 0); | ||
| 727 | |||
| 728 | return 0; | 800 | return 0; |
| 729 | } | 801 | } |
| 730 | 802 | ||
| 731 | static int acpi_ec_start(struct acpi_device *device) | 803 | static int acpi_ec_start(struct acpi_device *device) |
| 732 | { | 804 | { |
| 733 | struct acpi_ec *ec; | 805 | struct acpi_ec *ec; |
| 806 | int ret = 0; | ||
| 734 | 807 | ||
| 735 | if (!device) | 808 | if (!device) |
| 736 | return -EINVAL; | 809 | return -EINVAL; |
| @@ -740,14 +813,14 @@ static int acpi_ec_start(struct acpi_device *device) | |||
| 740 | if (!ec) | 813 | if (!ec) |
| 741 | return -EINVAL; | 814 | return -EINVAL; |
| 742 | 815 | ||
| 743 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx", | ||
| 744 | ec->gpe, ec->command_addr, ec->data_addr)); | ||
| 745 | |||
| 746 | /* Boot EC is already working */ | 816 | /* Boot EC is already working */ |
| 747 | if (ec == boot_ec) | 817 | if (ec != boot_ec) |
| 748 | return 0; | 818 | ret = ec_install_handlers(ec); |
| 819 | |||
| 820 | /* EC is fully operational, allow queries */ | ||
| 821 | atomic_set(&ec->query_pending, 0); | ||
| 749 | 822 | ||
| 750 | return ec_install_handlers(ec); | 823 | return ret; |
| 751 | } | 824 | } |
| 752 | 825 | ||
| 753 | static int acpi_ec_stop(struct acpi_device *device, int type) | 826 | static int acpi_ec_stop(struct acpi_device *device, int type) |
| @@ -779,34 +852,6 @@ static int acpi_ec_stop(struct acpi_device *device, int type) | |||
| 779 | return 0; | 852 | return 0; |
| 780 | } | 853 | } |
| 781 | 854 | ||
| 782 | static acpi_status | ||
| 783 | ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) | ||
| 784 | { | ||
| 785 | acpi_status status; | ||
| 786 | |||
| 787 | struct acpi_ec *ec = context; | ||
| 788 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | ||
| 789 | ec_parse_io_ports, ec); | ||
| 790 | if (ACPI_FAILURE(status)) | ||
| 791 | return status; | ||
| 792 | |||
| 793 | /* Get GPE bit assignment (EC events). */ | ||
| 794 | /* TODO: Add support for _GPE returning a package */ | ||
| 795 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); | ||
| 796 | if (ACPI_FAILURE(status)) | ||
| 797 | return status; | ||
| 798 | |||
| 799 | /* Use the global lock for all EC transactions? */ | ||
| 800 | acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); | ||
| 801 | |||
| 802 | ec->handle = handle; | ||
| 803 | |||
| 804 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx", | ||
| 805 | ec->gpe, ec->command_addr, ec->data_addr)); | ||
| 806 | |||
| 807 | return AE_CTRL_TERMINATE; | ||
| 808 | } | ||
| 809 | |||
| 810 | int __init acpi_ec_ecdt_probe(void) | 855 | int __init acpi_ec_ecdt_probe(void) |
| 811 | { | 856 | { |
| 812 | int ret; | 857 | int ret; |
| @@ -825,7 +870,7 @@ int __init acpi_ec_ecdt_probe(void) | |||
| 825 | if (ACPI_FAILURE(status)) | 870 | if (ACPI_FAILURE(status)) |
| 826 | goto error; | 871 | goto error; |
| 827 | 872 | ||
| 828 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT")); | 873 | printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n"); |
| 829 | 874 | ||
| 830 | boot_ec->command_addr = ecdt_ptr->control.address; | 875 | boot_ec->command_addr = ecdt_ptr->control.address; |
| 831 | boot_ec->data_addr = ecdt_ptr->data.address; | 876 | boot_ec->data_addr = ecdt_ptr->data.address; |
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 3b23562e6f92..dfa5853b17f0 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/poll.h> | 12 | #include <linux/poll.h> |
| 13 | #include <acpi/acpi_drivers.h> | 13 | #include <acpi/acpi_drivers.h> |
| 14 | #include <net/netlink.h> | ||
| 15 | #include <net/genetlink.h> | ||
| 14 | 16 | ||
| 15 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | 17 | #define _COMPONENT ACPI_SYSTEM_COMPONENT |
| 16 | ACPI_MODULE_NAME("event"); | 18 | ACPI_MODULE_NAME("event"); |
| @@ -48,7 +50,6 @@ acpi_system_read_event(struct file *file, char __user * buffer, size_t count, | |||
| 48 | static int chars_remaining = 0; | 50 | static int chars_remaining = 0; |
| 49 | static char *ptr; | 51 | static char *ptr; |
| 50 | 52 | ||
| 51 | |||
| 52 | if (!chars_remaining) { | 53 | if (!chars_remaining) { |
| 53 | memset(&event, 0, sizeof(struct acpi_bus_event)); | 54 | memset(&event, 0, sizeof(struct acpi_bus_event)); |
| 54 | 55 | ||
| @@ -106,23 +107,161 @@ static const struct file_operations acpi_system_event_ops = { | |||
| 106 | .poll = acpi_system_poll_event, | 107 | .poll = acpi_system_poll_event, |
| 107 | }; | 108 | }; |
| 108 | 109 | ||
| 110 | #ifdef CONFIG_NET | ||
| 111 | unsigned int acpi_event_seqnum; | ||
| 112 | struct acpi_genl_event { | ||
| 113 | acpi_device_class device_class; | ||
| 114 | char bus_id[15]; | ||
| 115 | u32 type; | ||
| 116 | u32 data; | ||
| 117 | }; | ||
| 118 | |||
| 119 | /* attributes of acpi_genl_family */ | ||
| 120 | enum { | ||
| 121 | ACPI_GENL_ATTR_UNSPEC, | ||
| 122 | ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */ | ||
| 123 | __ACPI_GENL_ATTR_MAX, | ||
| 124 | }; | ||
| 125 | #define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1) | ||
| 126 | |||
| 127 | /* commands supported by the acpi_genl_family */ | ||
| 128 | enum { | ||
| 129 | ACPI_GENL_CMD_UNSPEC, | ||
| 130 | ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */ | ||
| 131 | __ACPI_GENL_CMD_MAX, | ||
| 132 | }; | ||
| 133 | #define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) | ||
| 134 | |||
| 135 | #define ACPI_GENL_FAMILY_NAME "acpi_event" | ||
| 136 | #define ACPI_GENL_VERSION 0x01 | ||
| 137 | #define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group" | ||
| 138 | |||
| 139 | static struct genl_family acpi_event_genl_family = { | ||
| 140 | .id = GENL_ID_GENERATE, | ||
| 141 | .name = ACPI_GENL_FAMILY_NAME, | ||
| 142 | .version = ACPI_GENL_VERSION, | ||
| 143 | .maxattr = ACPI_GENL_ATTR_MAX, | ||
| 144 | }; | ||
| 145 | |||
| 146 | static struct genl_multicast_group acpi_event_mcgrp = { | ||
| 147 | .name = ACPI_GENL_MCAST_GROUP_NAME, | ||
| 148 | }; | ||
| 149 | |||
| 150 | int acpi_bus_generate_genetlink_event(struct acpi_device *device, | ||
| 151 | u8 type, int data) | ||
| 152 | { | ||
| 153 | struct sk_buff *skb; | ||
| 154 | struct nlattr *attr; | ||
| 155 | struct acpi_genl_event *event; | ||
| 156 | void *msg_header; | ||
| 157 | int size; | ||
| 158 | int result; | ||
| 159 | |||
| 160 | /* allocate memory */ | ||
| 161 | size = nla_total_size(sizeof(struct acpi_genl_event)) + | ||
| 162 | nla_total_size(0); | ||
| 163 | |||
| 164 | skb = genlmsg_new(size, GFP_ATOMIC); | ||
| 165 | if (!skb) | ||
| 166 | return -ENOMEM; | ||
| 167 | |||
| 168 | /* add the genetlink message header */ | ||
| 169 | msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++, | ||
| 170 | &acpi_event_genl_family, 0, | ||
| 171 | ACPI_GENL_CMD_EVENT); | ||
| 172 | if (!msg_header) { | ||
| 173 | nlmsg_free(skb); | ||
| 174 | return -ENOMEM; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* fill the data */ | ||
| 178 | attr = | ||
| 179 | nla_reserve(skb, ACPI_GENL_ATTR_EVENT, | ||
| 180 | sizeof(struct acpi_genl_event)); | ||
| 181 | if (!attr) { | ||
| 182 | nlmsg_free(skb); | ||
| 183 | return -EINVAL; | ||
| 184 | } | ||
| 185 | |||
| 186 | event = nla_data(attr); | ||
| 187 | if (!event) { | ||
| 188 | nlmsg_free(skb); | ||
| 189 | return -EINVAL; | ||
| 190 | } | ||
| 191 | |||
| 192 | memset(event, 0, sizeof(struct acpi_genl_event)); | ||
| 193 | |||
| 194 | strcpy(event->device_class, device->pnp.device_class); | ||
| 195 | strcpy(event->bus_id, device->dev.bus_id); | ||
| 196 | event->type = type; | ||
| 197 | event->data = data; | ||
| 198 | |||
| 199 | /* send multicast genetlink message */ | ||
| 200 | result = genlmsg_end(skb, msg_header); | ||
| 201 | if (result < 0) { | ||
| 202 | nlmsg_free(skb); | ||
| 203 | return result; | ||
| 204 | } | ||
| 205 | |||
| 206 | result = | ||
| 207 | genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); | ||
| 208 | if (result) | ||
| 209 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 210 | "Failed to send a Genetlink message!\n")); | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static int acpi_event_genetlink_init(void) | ||
| 215 | { | ||
| 216 | int result; | ||
| 217 | |||
| 218 | result = genl_register_family(&acpi_event_genl_family); | ||
| 219 | if (result) | ||
| 220 | return result; | ||
| 221 | |||
| 222 | result = genl_register_mc_group(&acpi_event_genl_family, | ||
| 223 | &acpi_event_mcgrp); | ||
| 224 | if (result) | ||
| 225 | genl_unregister_family(&acpi_event_genl_family); | ||
| 226 | |||
| 227 | return result; | ||
| 228 | } | ||
| 229 | |||
| 230 | #else | ||
| 231 | int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type, | ||
| 232 | int data) | ||
| 233 | { | ||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int acpi_event_genetlink_init(void) | ||
| 238 | { | ||
| 239 | return -ENODEV; | ||
| 240 | } | ||
| 241 | #endif | ||
| 242 | |||
| 109 | static int __init acpi_event_init(void) | 243 | static int __init acpi_event_init(void) |
| 110 | { | 244 | { |
| 111 | struct proc_dir_entry *entry; | 245 | struct proc_dir_entry *entry; |
| 112 | int error = 0; | 246 | int error = 0; |
| 113 | 247 | ||
| 114 | |||
| 115 | if (acpi_disabled) | 248 | if (acpi_disabled) |
| 116 | return 0; | 249 | return 0; |
| 117 | 250 | ||
| 251 | /* create genetlink for acpi event */ | ||
| 252 | error = acpi_event_genetlink_init(); | ||
| 253 | if (error) | ||
| 254 | printk(KERN_WARNING PREFIX | ||
| 255 | "Failed to create genetlink family for ACPI event\n"); | ||
| 256 | |||
| 118 | /* 'event' [R] */ | 257 | /* 'event' [R] */ |
| 119 | entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); | 258 | entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); |
| 120 | if (entry) | 259 | if (entry) |
| 121 | entry->proc_fops = &acpi_system_event_ops; | 260 | entry->proc_fops = &acpi_system_event_ops; |
| 122 | else { | 261 | else |
| 123 | error = -ENODEV; | 262 | return -ENODEV; |
| 124 | } | 263 | |
| 125 | return error; | 264 | return 0; |
| 126 | } | 265 | } |
| 127 | 266 | ||
| 128 | subsys_initcall(acpi_event_init); | 267 | fs_initcall(acpi_event_init); |
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 902c287b3a4f..361ebe6c4a6f 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c | |||
| @@ -586,6 +586,10 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) | |||
| 586 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 586 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
| 587 | if (gpe_xrupt->previous) { | 587 | if (gpe_xrupt->previous) { |
| 588 | gpe_xrupt->previous->next = gpe_xrupt->next; | 588 | gpe_xrupt->previous->next = gpe_xrupt->next; |
| 589 | } else { | ||
| 590 | /* No previous, update list head */ | ||
| 591 | |||
| 592 | acpi_gbl_gpe_xrupt_list_head = gpe_xrupt->next; | ||
| 589 | } | 593 | } |
| 590 | 594 | ||
| 591 | if (gpe_xrupt->next) { | 595 | if (gpe_xrupt->next) { |
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index 400d90fca966..23ee7bc4a705 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c | |||
| @@ -284,6 +284,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, | |||
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | if (!pci_device_node) { | 286 | if (!pci_device_node) { |
| 287 | ACPI_FREE(pci_id); | ||
| 287 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 288 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
| 288 | } | 289 | } |
| 289 | 290 | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 41427a41f620..4893e256e399 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #if ACPI_GLUE_DEBUG | 16 | #if ACPI_GLUE_DEBUG |
| 17 | #define DBG(x...) printk(PREFIX x) | 17 | #define DBG(x...) printk(PREFIX x) |
| 18 | #else | 18 | #else |
| 19 | #define DBG(x...) | 19 | #define DBG(x...) do { } while(0) |
| 20 | #endif | 20 | #endif |
| 21 | static LIST_HEAD(bus_type_list); | 21 | static LIST_HEAD(bus_type_list); |
| 22 | static DECLARE_RWSEM(bus_type_sem); | 22 | static DECLARE_RWSEM(bus_type_sem); |
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 0c9f15c54e8c..ab04d848b19d 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
| @@ -36,13 +36,11 @@ | |||
| 36 | ACPI_MODULE_NAME("numa"); | 36 | ACPI_MODULE_NAME("numa"); |
| 37 | 37 | ||
| 38 | static nodemask_t nodes_found_map = NODE_MASK_NONE; | 38 | static nodemask_t nodes_found_map = NODE_MASK_NONE; |
| 39 | #define PXM_INVAL -1 | ||
| 40 | #define NID_INVAL -1 | ||
| 41 | 39 | ||
| 42 | /* maps to convert between proximity domain and logical node ID */ | 40 | /* maps to convert between proximity domain and logical node ID */ |
| 43 | static int pxm_to_node_map[MAX_PXM_DOMAINS] | 41 | static int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] |
| 44 | = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; | 42 | = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; |
| 45 | static int node_to_pxm_map[MAX_NUMNODES] | 43 | static int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] |
| 46 | = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; | 44 | = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; |
| 47 | 45 | ||
| 48 | int pxm_to_node(int pxm) | 46 | int pxm_to_node(int pxm) |
| @@ -59,6 +57,12 @@ int node_to_pxm(int node) | |||
| 59 | return node_to_pxm_map[node]; | 57 | return node_to_pxm_map[node]; |
| 60 | } | 58 | } |
| 61 | 59 | ||
| 60 | void __acpi_map_pxm_to_node(int pxm, int node) | ||
| 61 | { | ||
| 62 | pxm_to_node_map[pxm] = node; | ||
| 63 | node_to_pxm_map[node] = pxm; | ||
| 64 | } | ||
| 65 | |||
| 62 | int acpi_map_pxm_to_node(int pxm) | 66 | int acpi_map_pxm_to_node(int pxm) |
| 63 | { | 67 | { |
| 64 | int node = pxm_to_node_map[pxm]; | 68 | int node = pxm_to_node_map[pxm]; |
| @@ -67,8 +71,7 @@ int acpi_map_pxm_to_node(int pxm) | |||
| 67 | if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) | 71 | if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) |
| 68 | return NID_INVAL; | 72 | return NID_INVAL; |
| 69 | node = first_unset_node(nodes_found_map); | 73 | node = first_unset_node(nodes_found_map); |
| 70 | pxm_to_node_map[pxm] = node; | 74 | __acpi_map_pxm_to_node(pxm, node); |
| 71 | node_to_pxm_map[node] = pxm; | ||
| 72 | node_set(node, nodes_found_map); | 75 | node_set(node, nodes_found_map); |
| 73 | } | 76 | } |
| 74 | 77 | ||
| @@ -83,7 +86,8 @@ void __cpuinit acpi_unmap_pxm_to_node(int node) | |||
| 83 | node_clear(node, nodes_found_map); | 86 | node_clear(node, nodes_found_map); |
| 84 | } | 87 | } |
| 85 | 88 | ||
| 86 | void __init acpi_table_print_srat_entry(struct acpi_subtable_header * header) | 89 | static void __init |
| 90 | acpi_table_print_srat_entry(struct acpi_subtable_header *header) | ||
| 87 | { | 91 | { |
| 88 | 92 | ||
| 89 | ACPI_FUNCTION_NAME("acpi_table_print_srat_entry"); | 93 | ACPI_FUNCTION_NAME("acpi_table_print_srat_entry"); |
| @@ -200,7 +204,7 @@ static int __init acpi_parse_srat(struct acpi_table_header *table) | |||
| 200 | return 0; | 204 | return 0; |
| 201 | } | 205 | } |
| 202 | 206 | ||
| 203 | int __init | 207 | static int __init |
| 204 | acpi_table_parse_srat(enum acpi_srat_type id, | 208 | acpi_table_parse_srat(enum acpi_srat_type id, |
| 205 | acpi_table_entry_handler handler, unsigned int max_entries) | 209 | acpi_table_entry_handler handler, unsigned int max_entries) |
| 206 | { | 210 | { |
| @@ -211,14 +215,13 @@ acpi_table_parse_srat(enum acpi_srat_type id, | |||
| 211 | 215 | ||
| 212 | int __init acpi_numa_init(void) | 216 | int __init acpi_numa_init(void) |
| 213 | { | 217 | { |
| 214 | int result; | ||
| 215 | |||
| 216 | /* SRAT: Static Resource Affinity Table */ | 218 | /* SRAT: Static Resource Affinity Table */ |
| 217 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { | 219 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { |
| 218 | result = acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, | 220 | acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, |
| 219 | acpi_parse_processor_affinity, | 221 | acpi_parse_processor_affinity, NR_CPUS); |
| 220 | NR_CPUS); | 222 | acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, |
| 221 | result = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, acpi_parse_memory_affinity, NR_NODE_MEMBLKS); // IA64 specific | 223 | acpi_parse_memory_affinity, |
| 224 | NR_NODE_MEMBLKS); | ||
| 222 | } | 225 | } |
| 223 | 226 | ||
| 224 | /* SLIT: System Locality Information Table */ | 227 | /* SLIT: System Locality Information Table */ |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 00d53c2fd1e8..12c09fafce9a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -77,13 +77,7 @@ static struct workqueue_struct *kacpi_notify_wq; | |||
| 77 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ | 77 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ |
| 78 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; | 78 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; |
| 79 | 79 | ||
| 80 | #define OSI_LINUX_ENABLED | 80 | static int osi_linux; /* disable _OSI(Linux) by default */ |
| 81 | #ifdef OSI_LINUX_ENABLED | ||
| 82 | int osi_linux = 1; /* enable _OSI(Linux) by default */ | ||
| 83 | #else | ||
| 84 | int osi_linux; /* disable _OSI(Linux) by default */ | ||
| 85 | #endif | ||
| 86 | |||
| 87 | 81 | ||
| 88 | #ifdef CONFIG_DMI | 82 | #ifdef CONFIG_DMI |
| 89 | static struct __initdata dmi_system_id acpi_osl_dmi_table[]; | 83 | static struct __initdata dmi_system_id acpi_osl_dmi_table[]; |
| @@ -1183,17 +1177,10 @@ acpi_os_validate_interface (char *interface) | |||
| 1183 | if (!strcmp("Linux", interface)) { | 1177 | if (!strcmp("Linux", interface)) { |
| 1184 | printk(KERN_WARNING PREFIX | 1178 | printk(KERN_WARNING PREFIX |
| 1185 | "System BIOS is requesting _OSI(Linux)\n"); | 1179 | "System BIOS is requesting _OSI(Linux)\n"); |
| 1186 | #ifdef OSI_LINUX_ENABLED | ||
| 1187 | printk(KERN_WARNING PREFIX | ||
| 1188 | "Please test with \"acpi_osi=!Linux\"\n" | ||
| 1189 | "Please send dmidecode " | ||
| 1190 | "to linux-acpi@vger.kernel.org\n"); | ||
| 1191 | #else | ||
| 1192 | printk(KERN_WARNING PREFIX | 1180 | printk(KERN_WARNING PREFIX |
| 1193 | "If \"acpi_osi=Linux\" works better,\n" | 1181 | "If \"acpi_osi=Linux\" works better,\n" |
| 1194 | "Please send dmidecode " | 1182 | "Please send dmidecode " |
| 1195 | "to linux-acpi@vger.kernel.org\n"); | 1183 | "to linux-acpi@vger.kernel.org\n"); |
| 1196 | #endif | ||
| 1197 | if(osi_linux) | 1184 | if(osi_linux) |
| 1198 | return AE_OK; | 1185 | return AE_OK; |
| 1199 | } | 1186 | } |
| @@ -1227,36 +1214,14 @@ acpi_os_validate_address ( | |||
| 1227 | } | 1214 | } |
| 1228 | 1215 | ||
| 1229 | #ifdef CONFIG_DMI | 1216 | #ifdef CONFIG_DMI |
| 1230 | #ifdef OSI_LINUX_ENABLED | ||
| 1231 | static int dmi_osi_not_linux(struct dmi_system_id *d) | ||
| 1232 | { | ||
| 1233 | printk(KERN_NOTICE "%s detected: requires not _OSI(Linux)\n", d->ident); | ||
| 1234 | enable_osi_linux(0); | ||
| 1235 | return 0; | ||
| 1236 | } | ||
| 1237 | #else | ||
| 1238 | static int dmi_osi_linux(struct dmi_system_id *d) | 1217 | static int dmi_osi_linux(struct dmi_system_id *d) |
| 1239 | { | 1218 | { |
| 1240 | printk(KERN_NOTICE "%s detected: requires _OSI(Linux)\n", d->ident); | 1219 | printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident); |
| 1241 | enable_osi_linux(1); | 1220 | enable_osi_linux(1); |
| 1242 | return 0; | 1221 | return 0; |
| 1243 | } | 1222 | } |
| 1244 | #endif | ||
| 1245 | 1223 | ||
| 1246 | static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { | 1224 | static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { |
| 1247 | #ifdef OSI_LINUX_ENABLED | ||
| 1248 | /* | ||
| 1249 | * Boxes that need NOT _OSI(Linux) | ||
| 1250 | */ | ||
| 1251 | { | ||
| 1252 | .callback = dmi_osi_not_linux, | ||
| 1253 | .ident = "Toshiba Satellite P100", | ||
| 1254 | .matches = { | ||
| 1255 | DMI_MATCH(DMI_BOARD_VENDOR, "TOSHIBA"), | ||
| 1256 | DMI_MATCH(DMI_BOARD_NAME, "Satellite P100"), | ||
| 1257 | }, | ||
| 1258 | }, | ||
| 1259 | #else | ||
| 1260 | /* | 1225 | /* |
| 1261 | * Boxes that need _OSI(Linux) | 1226 | * Boxes that need _OSI(Linux) |
| 1262 | */ | 1227 | */ |
| @@ -1268,7 +1233,6 @@ static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { | |||
| 1268 | DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"), | 1233 | DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"), |
| 1269 | }, | 1234 | }, |
| 1270 | }, | 1235 | }, |
| 1271 | #endif | ||
| 1272 | {} | 1236 | {} |
| 1273 | }; | 1237 | }; |
| 1274 | #endif /* CONFIG_DMI */ | 1238 | #endif /* CONFIG_DMI */ |
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index acc594771379..3448edd61dc4 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
| @@ -733,7 +733,7 @@ static int acpi_pci_link_add(struct acpi_device *device) | |||
| 733 | /* query and set link->irq.active */ | 733 | /* query and set link->irq.active */ |
| 734 | acpi_pci_link_get_current(link); | 734 | acpi_pci_link_get_current(link); |
| 735 | 735 | ||
| 736 | printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), | 736 | printk(KERN_INFO PREFIX "%s [%s] (IRQs", acpi_device_name(device), |
| 737 | acpi_device_bid(device)); | 737 | acpi_device_bid(device)); |
| 738 | for (i = 0; i < link->irq.possible_count; i++) { | 738 | for (i = 0; i < link->irq.possible_count; i++) { |
| 739 | if (link->irq.active == link->irq.possible[i]) { | 739 | if (link->irq.active == link->irq.possible[i]) { |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e1ca86dfdd66..81aceb5da7c7 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | #define ACPI_PROCESSOR_FILE_LIMIT "limit" | 66 | #define ACPI_PROCESSOR_FILE_LIMIT "limit" |
| 67 | #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 | 67 | #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 |
| 68 | #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 | 68 | #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 |
| 69 | #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 | ||
| 69 | 70 | ||
| 70 | #define ACPI_PROCESSOR_LIMIT_USER 0 | 71 | #define ACPI_PROCESSOR_LIMIT_USER 0 |
| 71 | #define ACPI_PROCESSOR_LIMIT_THERMAL 1 | 72 | #define ACPI_PROCESSOR_LIMIT_THERMAL 1 |
| @@ -84,6 +85,8 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); | |||
| 84 | static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); | 85 | static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); |
| 85 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); | 86 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); |
| 86 | static int acpi_processor_handle_eject(struct acpi_processor *pr); | 87 | static int acpi_processor_handle_eject(struct acpi_processor *pr); |
| 88 | extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr); | ||
| 89 | |||
| 87 | 90 | ||
| 88 | static struct acpi_driver acpi_processor_driver = { | 91 | static struct acpi_driver acpi_processor_driver = { |
| 89 | .name = "processor", | 92 | .name = "processor", |
| @@ -696,6 +699,9 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) | |||
| 696 | acpi_processor_cst_has_changed(pr); | 699 | acpi_processor_cst_has_changed(pr); |
| 697 | acpi_bus_generate_event(device, event, 0); | 700 | acpi_bus_generate_event(device, event, 0); |
| 698 | break; | 701 | break; |
| 702 | case ACPI_PROCESSOR_NOTIFY_THROTTLING: | ||
| 703 | acpi_processor_tstate_has_changed(pr); | ||
| 704 | acpi_bus_generate_event(device, event, 0); | ||
| 699 | default: | 705 | default: |
| 700 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 706 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 701 | "Unsupported event [0x%x]\n", event)); | 707 | "Unsupported event [0x%x]\n", event)); |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index bb5d23be4260..a898991f77cb 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -490,7 +490,17 @@ static void acpi_processor_idle(void) | |||
| 490 | 490 | ||
| 491 | case ACPI_STATE_C3: | 491 | case ACPI_STATE_C3: |
| 492 | 492 | ||
| 493 | if (pr->flags.bm_check) { | 493 | /* |
| 494 | * disable bus master | ||
| 495 | * bm_check implies we need ARB_DIS | ||
| 496 | * !bm_check implies we need cache flush | ||
| 497 | * bm_control implies whether we can do ARB_DIS | ||
| 498 | * | ||
| 499 | * That leaves a case where bm_check is set and bm_control is | ||
| 500 | * not set. In that case we cannot do much, we enter C3 | ||
| 501 | * without doing anything. | ||
| 502 | */ | ||
| 503 | if (pr->flags.bm_check && pr->flags.bm_control) { | ||
| 494 | if (atomic_inc_return(&c3_cpu_count) == | 504 | if (atomic_inc_return(&c3_cpu_count) == |
| 495 | num_online_cpus()) { | 505 | num_online_cpus()) { |
| 496 | /* | 506 | /* |
| @@ -499,7 +509,7 @@ static void acpi_processor_idle(void) | |||
| 499 | */ | 509 | */ |
| 500 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); | 510 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); |
| 501 | } | 511 | } |
| 502 | } else { | 512 | } else if (!pr->flags.bm_check) { |
| 503 | /* SMP with no shared cache... Invalidate cache */ | 513 | /* SMP with no shared cache... Invalidate cache */ |
| 504 | ACPI_FLUSH_CPU_CACHE(); | 514 | ACPI_FLUSH_CPU_CACHE(); |
| 505 | } | 515 | } |
| @@ -511,7 +521,7 @@ static void acpi_processor_idle(void) | |||
| 511 | acpi_cstate_enter(cx); | 521 | acpi_cstate_enter(cx); |
| 512 | /* Get end time (ticks) */ | 522 | /* Get end time (ticks) */ |
| 513 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 523 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); |
| 514 | if (pr->flags.bm_check) { | 524 | if (pr->flags.bm_check && pr->flags.bm_control) { |
| 515 | /* Enable bus master arbitration */ | 525 | /* Enable bus master arbitration */ |
| 516 | atomic_dec(&c3_cpu_count); | 526 | atomic_dec(&c3_cpu_count); |
| 517 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); | 527 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); |
| @@ -961,9 +971,9 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | |||
| 961 | if (pr->flags.bm_check) { | 971 | if (pr->flags.bm_check) { |
| 962 | /* bus mastering control is necessary */ | 972 | /* bus mastering control is necessary */ |
| 963 | if (!pr->flags.bm_control) { | 973 | if (!pr->flags.bm_control) { |
| 974 | /* In this case we enter C3 without bus mastering */ | ||
| 964 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 975 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 965 | "C3 support requires bus mastering control\n")); | 976 | "C3 support without bus mastering control\n")); |
| 966 | return; | ||
| 967 | } | 977 | } |
| 968 | } else { | 978 | } else { |
| 969 | /* | 979 | /* |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index b33486009f41..3f55d1f90c11 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
| @@ -44,17 +44,231 @@ | |||
| 44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 45 | ACPI_MODULE_NAME("processor_throttling"); | 45 | ACPI_MODULE_NAME("processor_throttling"); |
| 46 | 46 | ||
| 47 | static int acpi_processor_get_throttling(struct acpi_processor *pr); | ||
| 48 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state); | ||
| 49 | |||
| 50 | static int acpi_processor_get_platform_limit(struct acpi_processor *pr) | ||
| 51 | { | ||
| 52 | acpi_status status = 0; | ||
| 53 | unsigned long tpc = 0; | ||
| 54 | |||
| 55 | if (!pr) | ||
| 56 | return -EINVAL; | ||
| 57 | status = acpi_evaluate_integer(pr->handle, "_TPC", NULL, &tpc); | ||
| 58 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
| 59 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC")); | ||
| 60 | return -ENODEV; | ||
| 61 | } | ||
| 62 | pr->throttling_platform_limit = (int)tpc; | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | int acpi_processor_tstate_has_changed(struct acpi_processor *pr) | ||
| 67 | { | ||
| 68 | return acpi_processor_get_platform_limit(pr); | ||
| 69 | } | ||
| 70 | |||
| 71 | /* -------------------------------------------------------------------------- | ||
| 72 | _PTC, _TSS, _TSD support | ||
| 73 | -------------------------------------------------------------------------- */ | ||
| 74 | static int acpi_processor_get_throttling_control(struct acpi_processor *pr) | ||
| 75 | { | ||
| 76 | int result = 0; | ||
| 77 | acpi_status status = 0; | ||
| 78 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 79 | union acpi_object *ptc = NULL; | ||
| 80 | union acpi_object obj = { 0 }; | ||
| 81 | |||
| 82 | status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); | ||
| 83 | if (ACPI_FAILURE(status)) { | ||
| 84 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC")); | ||
| 85 | return -ENODEV; | ||
| 86 | } | ||
| 87 | |||
| 88 | ptc = (union acpi_object *)buffer.pointer; | ||
| 89 | if (!ptc || (ptc->type != ACPI_TYPE_PACKAGE) | ||
| 90 | || (ptc->package.count != 2)) { | ||
| 91 | printk(KERN_ERR PREFIX "Invalid _PTC data\n"); | ||
| 92 | result = -EFAULT; | ||
| 93 | goto end; | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | ||
| 97 | * control_register | ||
| 98 | */ | ||
| 99 | |||
| 100 | obj = ptc->package.elements[0]; | ||
| 101 | |||
| 102 | if ((obj.type != ACPI_TYPE_BUFFER) | ||
| 103 | || (obj.buffer.length < sizeof(struct acpi_ptc_register)) | ||
| 104 | || (obj.buffer.pointer == NULL)) { | ||
| 105 | printk(KERN_ERR PREFIX | ||
| 106 | "Invalid _PTC data (control_register)\n"); | ||
| 107 | result = -EFAULT; | ||
| 108 | goto end; | ||
| 109 | } | ||
| 110 | memcpy(&pr->throttling.control_register, obj.buffer.pointer, | ||
| 111 | sizeof(struct acpi_ptc_register)); | ||
| 112 | |||
| 113 | /* | ||
| 114 | * status_register | ||
| 115 | */ | ||
| 116 | |||
| 117 | obj = ptc->package.elements[1]; | ||
| 118 | |||
| 119 | if ((obj.type != ACPI_TYPE_BUFFER) | ||
| 120 | || (obj.buffer.length < sizeof(struct acpi_ptc_register)) | ||
| 121 | || (obj.buffer.pointer == NULL)) { | ||
| 122 | printk(KERN_ERR PREFIX "Invalid _PTC data (status_register)\n"); | ||
| 123 | result = -EFAULT; | ||
| 124 | goto end; | ||
| 125 | } | ||
| 126 | |||
| 127 | memcpy(&pr->throttling.status_register, obj.buffer.pointer, | ||
| 128 | sizeof(struct acpi_ptc_register)); | ||
| 129 | |||
| 130 | end: | ||
| 131 | kfree(buffer.pointer); | ||
| 132 | |||
| 133 | return result; | ||
| 134 | } | ||
| 135 | static int acpi_processor_get_throttling_states(struct acpi_processor *pr) | ||
| 136 | { | ||
| 137 | int result = 0; | ||
| 138 | acpi_status status = AE_OK; | ||
| 139 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 140 | struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" }; | ||
| 141 | struct acpi_buffer state = { 0, NULL }; | ||
| 142 | union acpi_object *tss = NULL; | ||
| 143 | int i; | ||
| 144 | |||
| 145 | status = acpi_evaluate_object(pr->handle, "_TSS", NULL, &buffer); | ||
| 146 | if (ACPI_FAILURE(status)) { | ||
| 147 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS")); | ||
| 148 | return -ENODEV; | ||
| 149 | } | ||
| 150 | |||
| 151 | tss = buffer.pointer; | ||
| 152 | if (!tss || (tss->type != ACPI_TYPE_PACKAGE)) { | ||
| 153 | printk(KERN_ERR PREFIX "Invalid _TSS data\n"); | ||
| 154 | result = -EFAULT; | ||
| 155 | goto end; | ||
| 156 | } | ||
| 157 | |||
| 158 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", | ||
| 159 | tss->package.count)); | ||
| 160 | |||
| 161 | pr->throttling.state_count = tss->package.count; | ||
| 162 | pr->throttling.states_tss = | ||
| 163 | kmalloc(sizeof(struct acpi_processor_tx_tss) * tss->package.count, | ||
| 164 | GFP_KERNEL); | ||
| 165 | if (!pr->throttling.states_tss) { | ||
| 166 | result = -ENOMEM; | ||
| 167 | goto end; | ||
| 168 | } | ||
| 169 | |||
| 170 | for (i = 0; i < pr->throttling.state_count; i++) { | ||
| 171 | |||
| 172 | struct acpi_processor_tx_tss *tx = | ||
| 173 | (struct acpi_processor_tx_tss *)&(pr->throttling. | ||
| 174 | states_tss[i]); | ||
| 175 | |||
| 176 | state.length = sizeof(struct acpi_processor_tx_tss); | ||
| 177 | state.pointer = tx; | ||
| 178 | |||
| 179 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i)); | ||
| 180 | |||
| 181 | status = acpi_extract_package(&(tss->package.elements[i]), | ||
| 182 | &format, &state); | ||
| 183 | if (ACPI_FAILURE(status)) { | ||
| 184 | ACPI_EXCEPTION((AE_INFO, status, "Invalid _TSS data")); | ||
| 185 | result = -EFAULT; | ||
| 186 | kfree(pr->throttling.states_tss); | ||
| 187 | goto end; | ||
| 188 | } | ||
| 189 | |||
| 190 | if (!tx->freqpercentage) { | ||
| 191 | printk(KERN_ERR PREFIX | ||
| 192 | "Invalid _TSS data: freq is zero\n"); | ||
| 193 | result = -EFAULT; | ||
| 194 | kfree(pr->throttling.states_tss); | ||
| 195 | goto end; | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | end: | ||
| 200 | kfree(buffer.pointer); | ||
| 201 | |||
| 202 | return result; | ||
| 203 | } | ||
| 204 | static int acpi_processor_get_tsd(struct acpi_processor *pr) | ||
| 205 | { | ||
| 206 | int result = 0; | ||
| 207 | acpi_status status = AE_OK; | ||
| 208 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 209 | struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" }; | ||
| 210 | struct acpi_buffer state = { 0, NULL }; | ||
| 211 | union acpi_object *tsd = NULL; | ||
| 212 | struct acpi_tsd_package *pdomain; | ||
| 213 | |||
| 214 | status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer); | ||
| 215 | if (ACPI_FAILURE(status)) { | ||
| 216 | return -ENODEV; | ||
| 217 | } | ||
| 218 | |||
| 219 | tsd = buffer.pointer; | ||
| 220 | if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) { | ||
| 221 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); | ||
| 222 | result = -EFAULT; | ||
| 223 | goto end; | ||
| 224 | } | ||
| 225 | |||
| 226 | if (tsd->package.count != 1) { | ||
| 227 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); | ||
| 228 | result = -EFAULT; | ||
| 229 | goto end; | ||
| 230 | } | ||
| 231 | |||
| 232 | pdomain = &(pr->throttling.domain_info); | ||
| 233 | |||
| 234 | state.length = sizeof(struct acpi_tsd_package); | ||
| 235 | state.pointer = pdomain; | ||
| 236 | |||
| 237 | status = acpi_extract_package(&(tsd->package.elements[0]), | ||
| 238 | &format, &state); | ||
| 239 | if (ACPI_FAILURE(status)) { | ||
| 240 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); | ||
| 241 | result = -EFAULT; | ||
| 242 | goto end; | ||
| 243 | } | ||
| 244 | |||
| 245 | if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) { | ||
| 246 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n")); | ||
| 247 | result = -EFAULT; | ||
| 248 | goto end; | ||
| 249 | } | ||
| 250 | |||
| 251 | if (pdomain->revision != ACPI_TSD_REV0_REVISION) { | ||
| 252 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n")); | ||
| 253 | result = -EFAULT; | ||
| 254 | goto end; | ||
| 255 | } | ||
| 256 | |||
| 257 | end: | ||
| 258 | kfree(buffer.pointer); | ||
| 259 | return result; | ||
| 260 | } | ||
| 261 | |||
| 47 | /* -------------------------------------------------------------------------- | 262 | /* -------------------------------------------------------------------------- |
| 48 | Throttling Control | 263 | Throttling Control |
| 49 | -------------------------------------------------------------------------- */ | 264 | -------------------------------------------------------------------------- */ |
| 50 | static int acpi_processor_get_throttling(struct acpi_processor *pr) | 265 | static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) |
| 51 | { | 266 | { |
| 52 | int state = 0; | 267 | int state = 0; |
| 53 | u32 value = 0; | 268 | u32 value = 0; |
| 54 | u32 duty_mask = 0; | 269 | u32 duty_mask = 0; |
| 55 | u32 duty_value = 0; | 270 | u32 duty_value = 0; |
| 56 | 271 | ||
| 57 | |||
| 58 | if (!pr) | 272 | if (!pr) |
| 59 | return -EINVAL; | 273 | return -EINVAL; |
| 60 | 274 | ||
| @@ -94,13 +308,115 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr) | |||
| 94 | return 0; | 308 | return 0; |
| 95 | } | 309 | } |
| 96 | 310 | ||
| 97 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | 311 | static int acpi_read_throttling_status(struct acpi_processor_throttling |
| 312 | *throttling) | ||
| 313 | { | ||
| 314 | int value = -1; | ||
| 315 | switch (throttling->status_register.space_id) { | ||
| 316 | case ACPI_ADR_SPACE_SYSTEM_IO: | ||
| 317 | acpi_os_read_port((acpi_io_address) throttling->status_register. | ||
| 318 | address, &value, | ||
| 319 | (u32) throttling->status_register.bit_width * | ||
| 320 | 8); | ||
| 321 | break; | ||
| 322 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | ||
| 323 | printk(KERN_ERR PREFIX | ||
| 324 | "HARDWARE addr space,NOT supported yet\n"); | ||
| 325 | break; | ||
| 326 | default: | ||
| 327 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", | ||
| 328 | (u32) (throttling->status_register.space_id)); | ||
| 329 | } | ||
| 330 | return value; | ||
| 331 | } | ||
| 332 | |||
| 333 | static int acpi_write_throttling_state(struct acpi_processor_throttling | ||
| 334 | *throttling, int value) | ||
| 335 | { | ||
| 336 | int ret = -1; | ||
| 337 | |||
| 338 | switch (throttling->control_register.space_id) { | ||
| 339 | case ACPI_ADR_SPACE_SYSTEM_IO: | ||
| 340 | acpi_os_write_port((acpi_io_address) throttling-> | ||
| 341 | control_register.address, value, | ||
| 342 | (u32) throttling->control_register. | ||
| 343 | bit_width * 8); | ||
| 344 | ret = 0; | ||
| 345 | break; | ||
| 346 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | ||
| 347 | printk(KERN_ERR PREFIX | ||
| 348 | "HARDWARE addr space,NOT supported yet\n"); | ||
| 349 | break; | ||
| 350 | default: | ||
| 351 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", | ||
| 352 | (u32) (throttling->control_register.space_id)); | ||
| 353 | } | ||
| 354 | return ret; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int acpi_get_throttling_state(struct acpi_processor *pr, int value) | ||
| 358 | { | ||
| 359 | int i; | ||
| 360 | |||
| 361 | for (i = 0; i < pr->throttling.state_count; i++) { | ||
| 362 | struct acpi_processor_tx_tss *tx = | ||
| 363 | (struct acpi_processor_tx_tss *)&(pr->throttling. | ||
| 364 | states_tss[i]); | ||
| 365 | if (tx->control == value) | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | if (i > pr->throttling.state_count) | ||
| 369 | i = -1; | ||
| 370 | return i; | ||
| 371 | } | ||
| 372 | |||
| 373 | static int acpi_get_throttling_value(struct acpi_processor *pr, int state) | ||
| 374 | { | ||
| 375 | int value = -1; | ||
| 376 | if (state >= 0 && state <= pr->throttling.state_count) { | ||
| 377 | struct acpi_processor_tx_tss *tx = | ||
| 378 | (struct acpi_processor_tx_tss *)&(pr->throttling. | ||
| 379 | states_tss[state]); | ||
| 380 | value = tx->control; | ||
| 381 | } | ||
| 382 | return value; | ||
| 383 | } | ||
| 384 | |||
| 385 | static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) | ||
| 386 | { | ||
| 387 | int state = 0; | ||
| 388 | u32 value = 0; | ||
| 389 | |||
| 390 | if (!pr) | ||
| 391 | return -EINVAL; | ||
| 392 | |||
| 393 | if (!pr->flags.throttling) | ||
| 394 | return -ENODEV; | ||
| 395 | |||
| 396 | pr->throttling.state = 0; | ||
| 397 | local_irq_disable(); | ||
| 398 | value = acpi_read_throttling_status(&pr->throttling); | ||
| 399 | if (value >= 0) { | ||
| 400 | state = acpi_get_throttling_state(pr, value); | ||
| 401 | pr->throttling.state = state; | ||
| 402 | } | ||
| 403 | local_irq_enable(); | ||
| 404 | |||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 408 | static int acpi_processor_get_throttling(struct acpi_processor *pr) | ||
| 409 | { | ||
| 410 | return pr->throttling.acpi_processor_get_throttling(pr); | ||
| 411 | } | ||
| 412 | |||
| 413 | static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, | ||
| 414 | int state) | ||
| 98 | { | 415 | { |
| 99 | u32 value = 0; | 416 | u32 value = 0; |
| 100 | u32 duty_mask = 0; | 417 | u32 duty_mask = 0; |
| 101 | u32 duty_value = 0; | 418 | u32 duty_value = 0; |
| 102 | 419 | ||
| 103 | |||
| 104 | if (!pr) | 420 | if (!pr) |
| 105 | return -EINVAL; | 421 | return -EINVAL; |
| 106 | 422 | ||
| @@ -113,6 +429,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | |||
| 113 | if (state == pr->throttling.state) | 429 | if (state == pr->throttling.state) |
| 114 | return 0; | 430 | return 0; |
| 115 | 431 | ||
| 432 | if (state < pr->throttling_platform_limit) | ||
| 433 | return -EPERM; | ||
| 116 | /* | 434 | /* |
| 117 | * Calculate the duty_value and duty_mask. | 435 | * Calculate the duty_value and duty_mask. |
| 118 | */ | 436 | */ |
| @@ -165,12 +483,51 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | |||
| 165 | return 0; | 483 | return 0; |
| 166 | } | 484 | } |
| 167 | 485 | ||
| 486 | static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, | ||
| 487 | int state) | ||
| 488 | { | ||
| 489 | u32 value = 0; | ||
| 490 | |||
| 491 | if (!pr) | ||
| 492 | return -EINVAL; | ||
| 493 | |||
| 494 | if ((state < 0) || (state > (pr->throttling.state_count - 1))) | ||
| 495 | return -EINVAL; | ||
| 496 | |||
| 497 | if (!pr->flags.throttling) | ||
| 498 | return -ENODEV; | ||
| 499 | |||
| 500 | if (state == pr->throttling.state) | ||
| 501 | return 0; | ||
| 502 | |||
| 503 | if (state < pr->throttling_platform_limit) | ||
| 504 | return -EPERM; | ||
| 505 | |||
| 506 | local_irq_disable(); | ||
| 507 | |||
| 508 | value = acpi_get_throttling_value(pr, state); | ||
| 509 | if (value >= 0) { | ||
| 510 | acpi_write_throttling_state(&pr->throttling, value); | ||
| 511 | pr->throttling.state = state; | ||
| 512 | } | ||
| 513 | local_irq_enable(); | ||
| 514 | |||
| 515 | return 0; | ||
| 516 | } | ||
| 517 | |||
| 518 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | ||
| 519 | { | ||
| 520 | return pr->throttling.acpi_processor_set_throttling(pr, state); | ||
| 521 | } | ||
| 522 | |||
| 168 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) | 523 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) |
| 169 | { | 524 | { |
| 170 | int result = 0; | 525 | int result = 0; |
| 171 | int step = 0; | 526 | int step = 0; |
| 172 | int i = 0; | 527 | int i = 0; |
| 173 | 528 | int no_ptc = 0; | |
| 529 | int no_tss = 0; | ||
| 530 | int no_tsd = 0; | ||
| 174 | 531 | ||
| 175 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 532 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 176 | "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", | 533 | "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", |
| @@ -182,6 +539,21 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
| 182 | return -EINVAL; | 539 | return -EINVAL; |
| 183 | 540 | ||
| 184 | /* TBD: Support ACPI 2.0 objects */ | 541 | /* TBD: Support ACPI 2.0 objects */ |
| 542 | no_ptc = acpi_processor_get_throttling_control(pr); | ||
| 543 | no_tss = acpi_processor_get_throttling_states(pr); | ||
| 544 | no_tsd = acpi_processor_get_tsd(pr); | ||
| 545 | |||
| 546 | if (no_ptc || no_tss) { | ||
| 547 | pr->throttling.acpi_processor_get_throttling = | ||
| 548 | &acpi_processor_get_throttling_fadt; | ||
| 549 | pr->throttling.acpi_processor_set_throttling = | ||
| 550 | &acpi_processor_set_throttling_fadt; | ||
| 551 | } else { | ||
| 552 | pr->throttling.acpi_processor_get_throttling = | ||
| 553 | &acpi_processor_get_throttling_ptc; | ||
| 554 | pr->throttling.acpi_processor_set_throttling = | ||
| 555 | &acpi_processor_set_throttling_ptc; | ||
| 556 | } | ||
| 185 | 557 | ||
| 186 | if (!pr->throttling.address) { | 558 | if (!pr->throttling.address) { |
| 187 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); | 559 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); |
| @@ -262,7 +634,6 @@ static int acpi_processor_throttling_seq_show(struct seq_file *seq, | |||
| 262 | int i = 0; | 634 | int i = 0; |
| 263 | int result = 0; | 635 | int result = 0; |
| 264 | 636 | ||
| 265 | |||
| 266 | if (!pr) | 637 | if (!pr) |
| 267 | goto end; | 638 | goto end; |
| 268 | 639 | ||
| @@ -280,15 +651,25 @@ static int acpi_processor_throttling_seq_show(struct seq_file *seq, | |||
| 280 | } | 651 | } |
| 281 | 652 | ||
| 282 | seq_printf(seq, "state count: %d\n" | 653 | seq_printf(seq, "state count: %d\n" |
| 283 | "active state: T%d\n", | 654 | "active state: T%d\n" |
| 284 | pr->throttling.state_count, pr->throttling.state); | 655 | "state available: T%d to T%d\n", |
| 656 | pr->throttling.state_count, pr->throttling.state, | ||
| 657 | pr->throttling_platform_limit, | ||
| 658 | pr->throttling.state_count - 1); | ||
| 285 | 659 | ||
| 286 | seq_puts(seq, "states:\n"); | 660 | seq_puts(seq, "states:\n"); |
| 287 | for (i = 0; i < pr->throttling.state_count; i++) | 661 | if (acpi_processor_get_throttling == acpi_processor_get_throttling_fadt) |
| 288 | seq_printf(seq, " %cT%d: %02d%%\n", | 662 | for (i = 0; i < pr->throttling.state_count; i++) |
| 289 | (i == pr->throttling.state ? '*' : ' '), i, | 663 | seq_printf(seq, " %cT%d: %02d%%\n", |
| 290 | (pr->throttling.states[i].performance ? pr-> | 664 | (i == pr->throttling.state ? '*' : ' '), i, |
| 291 | throttling.states[i].performance / 10 : 0)); | 665 | (pr->throttling.states[i].performance ? pr-> |
| 666 | throttling.states[i].performance / 10 : 0)); | ||
| 667 | else | ||
| 668 | for (i = 0; i < pr->throttling.state_count; i++) | ||
| 669 | seq_printf(seq, " %cT%d: %02d%%\n", | ||
| 670 | (i == pr->throttling.state ? '*' : ' '), i, | ||
| 671 | (int)pr->throttling.states_tss[i]. | ||
| 672 | freqpercentage); | ||
| 292 | 673 | ||
| 293 | end: | 674 | end: |
| 294 | return 0; | 675 | return 0; |
| @@ -301,7 +682,7 @@ static int acpi_processor_throttling_open_fs(struct inode *inode, | |||
| 301 | PDE(inode)->data); | 682 | PDE(inode)->data); |
| 302 | } | 683 | } |
| 303 | 684 | ||
| 304 | static ssize_t acpi_processor_write_throttling(struct file * file, | 685 | static ssize_t acpi_processor_write_throttling(struct file *file, |
| 305 | const char __user * buffer, | 686 | const char __user * buffer, |
| 306 | size_t count, loff_t * data) | 687 | size_t count, loff_t * data) |
| 307 | { | 688 | { |
| @@ -310,7 +691,6 @@ static ssize_t acpi_processor_write_throttling(struct file * file, | |||
| 310 | struct acpi_processor *pr = m->private; | 691 | struct acpi_processor *pr = m->private; |
| 311 | char state_string[12] = { '\0' }; | 692 | char state_string[12] = { '\0' }; |
| 312 | 693 | ||
| 313 | |||
| 314 | if (!pr || (count > sizeof(state_string) - 1)) | 694 | if (!pr || (count > sizeof(state_string) - 1)) |
| 315 | return -EINVAL; | 695 | return -EINVAL; |
| 316 | 696 | ||
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index c1bae106833c..974d00ccfe84 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
| @@ -127,7 +127,7 @@ static int acpi_sbs_resume(struct acpi_device *device); | |||
| 127 | static struct acpi_driver acpi_sbs_driver = { | 127 | static struct acpi_driver acpi_sbs_driver = { |
| 128 | .name = "sbs", | 128 | .name = "sbs", |
| 129 | .class = ACPI_SBS_CLASS, | 129 | .class = ACPI_SBS_CLASS, |
| 130 | .ids = ACPI_SBS_HID, | 130 | .ids = "ACPI0001,ACPI0005", |
| 131 | .ops = { | 131 | .ops = { |
| 132 | .add = acpi_sbs_add, | 132 | .add = acpi_sbs_add, |
| 133 | .remove = acpi_sbs_remove, | 133 | .remove = acpi_sbs_remove, |
| @@ -176,10 +176,8 @@ struct acpi_battery { | |||
| 176 | }; | 176 | }; |
| 177 | 177 | ||
| 178 | struct acpi_sbs { | 178 | struct acpi_sbs { |
| 179 | acpi_handle handle; | ||
| 180 | int base; | 179 | int base; |
| 181 | struct acpi_device *device; | 180 | struct acpi_device *device; |
| 182 | struct acpi_ec_smbus *smbus; | ||
| 183 | struct mutex mutex; | 181 | struct mutex mutex; |
| 184 | int sbsm_present; | 182 | int sbsm_present; |
| 185 | int sbsm_batteries_supported; | 183 | int sbsm_batteries_supported; |
| @@ -511,7 +509,7 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs) | |||
| 511 | "acpi_sbs_read_word() failed")); | 509 | "acpi_sbs_read_word() failed")); |
| 512 | goto end; | 510 | goto end; |
| 513 | } | 511 | } |
| 514 | 512 | sbs->sbsm_present = 1; | |
| 515 | sbs->sbsm_batteries_supported = battery_system_info & 0x000f; | 513 | sbs->sbsm_batteries_supported = battery_system_info & 0x000f; |
| 516 | 514 | ||
| 517 | end: | 515 | end: |
| @@ -1630,13 +1628,12 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
| 1630 | { | 1628 | { |
| 1631 | struct acpi_sbs *sbs = NULL; | 1629 | struct acpi_sbs *sbs = NULL; |
| 1632 | int result = 0, remove_result = 0; | 1630 | int result = 0, remove_result = 0; |
| 1633 | unsigned long sbs_obj; | ||
| 1634 | int id; | 1631 | int id; |
| 1635 | acpi_status status = AE_OK; | 1632 | acpi_status status = AE_OK; |
| 1636 | unsigned long val; | 1633 | unsigned long val; |
| 1637 | 1634 | ||
| 1638 | status = | 1635 | status = |
| 1639 | acpi_evaluate_integer(device->parent->handle, "_EC", NULL, &val); | 1636 | acpi_evaluate_integer(device->handle, "_EC", NULL, &val); |
| 1640 | if (ACPI_FAILURE(status)) { | 1637 | if (ACPI_FAILURE(status)) { |
| 1641 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC")); | 1638 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC")); |
| 1642 | return -EIO; | 1639 | return -EIO; |
| @@ -1653,7 +1650,7 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
| 1653 | 1650 | ||
| 1654 | sbs_mutex_lock(sbs); | 1651 | sbs_mutex_lock(sbs); |
| 1655 | 1652 | ||
| 1656 | sbs->base = (val & 0xff00ull) >> 8; | 1653 | sbs->base = 0xff & (val >> 8); |
| 1657 | sbs->device = device; | 1654 | sbs->device = device; |
| 1658 | 1655 | ||
| 1659 | strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); | 1656 | strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); |
| @@ -1665,24 +1662,10 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
| 1665 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed")); | 1662 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed")); |
| 1666 | goto end; | 1663 | goto end; |
| 1667 | } | 1664 | } |
| 1668 | status = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj); | ||
| 1669 | if (status) { | ||
| 1670 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 1671 | "acpi_evaluate_integer() failed")); | ||
| 1672 | result = -EIO; | ||
| 1673 | goto end; | ||
| 1674 | } | ||
| 1675 | if (sbs_obj > 0) { | ||
| 1676 | result = acpi_sbsm_get_info(sbs); | ||
| 1677 | if (result) { | ||
| 1678 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1679 | "acpi_sbsm_get_info() failed")); | ||
| 1680 | goto end; | ||
| 1681 | } | ||
| 1682 | sbs->sbsm_present = 1; | ||
| 1683 | } | ||
| 1684 | 1665 | ||
| 1685 | if (sbs->sbsm_present == 0) { | 1666 | acpi_sbsm_get_info(sbs); |
| 1667 | |||
| 1668 | if (!sbs->sbsm_present) { | ||
| 1686 | result = acpi_battery_add(sbs, 0); | 1669 | result = acpi_battery_add(sbs, 0); |
| 1687 | if (result) { | 1670 | if (result) { |
| 1688 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1671 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
| @@ -1702,8 +1685,6 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
| 1702 | } | 1685 | } |
| 1703 | } | 1686 | } |
| 1704 | 1687 | ||
| 1705 | sbs->handle = device->handle; | ||
| 1706 | |||
| 1707 | init_timer(&sbs->update_timer); | 1688 | init_timer(&sbs->update_timer); |
| 1708 | result = acpi_check_update_proc(sbs); | 1689 | result = acpi_check_update_proc(sbs); |
| 1709 | if (result) | 1690 | if (result) |
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 42127c0d612c..3279e72a94f8 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
| @@ -210,11 +210,6 @@ static void acpi_hibernation_finish(void) | |||
| 210 | 210 | ||
| 211 | /* reset firmware waking vector */ | 211 | /* reset firmware waking vector */ |
| 212 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | 212 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); |
| 213 | |||
| 214 | if (init_8259A_after_S1) { | ||
| 215 | printk("Broken toshiba laptop -> kicking interrupts\n"); | ||
| 216 | init_8259A(0); | ||
| 217 | } | ||
| 218 | } | 213 | } |
| 219 | 214 | ||
| 220 | static int acpi_hibernation_pre_restore(void) | 215 | static int acpi_hibernation_pre_restore(void) |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 83a8d3097904..edee2806e37b 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
| @@ -39,15 +39,12 @@ ACPI_MODULE_NAME("system"); | |||
| 39 | 39 | ||
| 40 | #define ACPI_SYSTEM_CLASS "system" | 40 | #define ACPI_SYSTEM_CLASS "system" |
| 41 | #define ACPI_SYSTEM_DEVICE_NAME "System" | 41 | #define ACPI_SYSTEM_DEVICE_NAME "System" |
| 42 | #define ACPI_SYSTEM_FILE_INFO "info" | ||
| 43 | #define ACPI_SYSTEM_FILE_EVENT "event" | ||
| 44 | #define ACPI_SYSTEM_FILE_DSDT "dsdt" | ||
| 45 | #define ACPI_SYSTEM_FILE_FADT "fadt" | ||
| 46 | 42 | ||
| 47 | /* | 43 | /* |
| 48 | * Make ACPICA version work as module param | 44 | * Make ACPICA version work as module param |
| 49 | */ | 45 | */ |
| 50 | static int param_get_acpica_version(char *buffer, struct kernel_param *kp) { | 46 | static int param_get_acpica_version(char *buffer, struct kernel_param *kp) |
| 47 | { | ||
| 51 | int result; | 48 | int result; |
| 52 | 49 | ||
| 53 | result = sprintf(buffer, "%x", ACPI_CA_VERSION); | 50 | result = sprintf(buffer, "%x", ACPI_CA_VERSION); |
| @@ -58,9 +55,126 @@ static int param_get_acpica_version(char *buffer, struct kernel_param *kp) { | |||
| 58 | module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); | 55 | module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); |
| 59 | 56 | ||
| 60 | /* -------------------------------------------------------------------------- | 57 | /* -------------------------------------------------------------------------- |
| 58 | FS Interface (/sys) | ||
| 59 | -------------------------------------------------------------------------- */ | ||
| 60 | static LIST_HEAD(acpi_table_attr_list); | ||
| 61 | static struct kobject tables_kobj; | ||
| 62 | |||
| 63 | struct acpi_table_attr { | ||
| 64 | struct bin_attribute attr; | ||
| 65 | char name[8]; | ||
| 66 | int instance; | ||
| 67 | struct list_head node; | ||
| 68 | }; | ||
| 69 | |||
| 70 | static ssize_t acpi_table_show(struct kobject *kobj, | ||
| 71 | struct bin_attribute *bin_attr, char *buf, | ||
| 72 | loff_t offset, size_t count) | ||
| 73 | { | ||
| 74 | struct acpi_table_attr *table_attr = | ||
| 75 | container_of(bin_attr, struct acpi_table_attr, attr); | ||
| 76 | struct acpi_table_header *table_header = NULL; | ||
| 77 | acpi_status status; | ||
| 78 | ssize_t ret_count = count; | ||
| 79 | |||
| 80 | status = | ||
| 81 | acpi_get_table(table_attr->name, table_attr->instance, | ||
| 82 | &table_header); | ||
| 83 | if (ACPI_FAILURE(status)) | ||
| 84 | return -ENODEV; | ||
| 85 | |||
| 86 | if (offset >= table_header->length) { | ||
| 87 | ret_count = 0; | ||
| 88 | goto end; | ||
| 89 | } | ||
| 90 | |||
| 91 | if (offset + ret_count > table_header->length) | ||
| 92 | ret_count = table_header->length - offset; | ||
| 93 | |||
| 94 | memcpy(buf, ((char *)table_header) + offset, ret_count); | ||
| 95 | |||
| 96 | end: | ||
| 97 | return ret_count; | ||
| 98 | } | ||
| 99 | |||
| 100 | static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | ||
| 101 | struct acpi_table_header *table_header) | ||
| 102 | { | ||
| 103 | struct acpi_table_header *header = NULL; | ||
| 104 | struct acpi_table_attr *attr = NULL; | ||
| 105 | |||
| 106 | memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE); | ||
| 107 | |||
| 108 | list_for_each_entry(attr, &acpi_table_attr_list, node) { | ||
| 109 | if (!memcmp(table_header->signature, attr->name, | ||
| 110 | ACPI_NAME_SIZE)) | ||
| 111 | if (table_attr->instance < attr->instance) | ||
| 112 | table_attr->instance = attr->instance; | ||
| 113 | } | ||
| 114 | table_attr->instance++; | ||
| 115 | |||
| 116 | if (table_attr->instance > 1 || (table_attr->instance == 1 && | ||
| 117 | !acpi_get_table(table_header-> | ||
| 118 | signature, 2, | ||
| 119 | &header))) | ||
| 120 | sprintf(table_attr->name + 4, "%d", table_attr->instance); | ||
| 121 | |||
| 122 | table_attr->attr.size = 0; | ||
| 123 | table_attr->attr.read = acpi_table_show; | ||
| 124 | table_attr->attr.attr.name = table_attr->name; | ||
| 125 | table_attr->attr.attr.mode = 0444; | ||
| 126 | table_attr->attr.attr.owner = THIS_MODULE; | ||
| 127 | |||
| 128 | return; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int acpi_system_sysfs_init(void) | ||
| 132 | { | ||
| 133 | struct acpi_table_attr *table_attr; | ||
| 134 | struct acpi_table_header *table_header = NULL; | ||
| 135 | int table_index = 0; | ||
| 136 | int result; | ||
| 137 | |||
| 138 | tables_kobj.parent = &acpi_subsys.kobj; | ||
| 139 | kobject_set_name(&tables_kobj, "tables"); | ||
| 140 | result = kobject_register(&tables_kobj); | ||
| 141 | if (result) | ||
| 142 | return result; | ||
| 143 | |||
| 144 | do { | ||
| 145 | result = acpi_get_table_by_index(table_index, &table_header); | ||
| 146 | if (!result) { | ||
| 147 | table_index++; | ||
| 148 | table_attr = NULL; | ||
| 149 | table_attr = | ||
| 150 | kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); | ||
| 151 | if (!table_attr) | ||
| 152 | return -ENOMEM; | ||
| 153 | |||
| 154 | acpi_table_attr_init(table_attr, table_header); | ||
| 155 | result = | ||
| 156 | sysfs_create_bin_file(&tables_kobj, | ||
| 157 | &table_attr->attr); | ||
| 158 | if (result) { | ||
| 159 | kfree(table_attr); | ||
| 160 | return result; | ||
| 161 | } else | ||
| 162 | list_add_tail(&table_attr->node, | ||
| 163 | &acpi_table_attr_list); | ||
| 164 | } | ||
| 165 | } while (!result); | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | /* -------------------------------------------------------------------------- | ||
| 61 | FS Interface (/proc) | 171 | FS Interface (/proc) |
| 62 | -------------------------------------------------------------------------- */ | 172 | -------------------------------------------------------------------------- */ |
| 63 | #ifdef CONFIG_ACPI_PROCFS | 173 | #ifdef CONFIG_ACPI_PROCFS |
| 174 | #define ACPI_SYSTEM_FILE_INFO "info" | ||
| 175 | #define ACPI_SYSTEM_FILE_EVENT "event" | ||
| 176 | #define ACPI_SYSTEM_FILE_DSDT "dsdt" | ||
| 177 | #define ACPI_SYSTEM_FILE_FADT "fadt" | ||
| 64 | 178 | ||
| 65 | static int acpi_system_read_info(struct seq_file *seq, void *offset) | 179 | static int acpi_system_read_info(struct seq_file *seq, void *offset) |
| 66 | { | 180 | { |
| @@ -80,7 +194,6 @@ static const struct file_operations acpi_system_info_ops = { | |||
| 80 | .llseek = seq_lseek, | 194 | .llseek = seq_lseek, |
| 81 | .release = single_release, | 195 | .release = single_release, |
| 82 | }; | 196 | }; |
| 83 | #endif | ||
| 84 | 197 | ||
| 85 | static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t, | 198 | static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t, |
| 86 | loff_t *); | 199 | loff_t *); |
| @@ -97,13 +210,11 @@ acpi_system_read_dsdt(struct file *file, | |||
| 97 | struct acpi_table_header *dsdt = NULL; | 210 | struct acpi_table_header *dsdt = NULL; |
| 98 | ssize_t res; | 211 | ssize_t res; |
| 99 | 212 | ||
| 100 | |||
| 101 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt); | 213 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt); |
| 102 | if (ACPI_FAILURE(status)) | 214 | if (ACPI_FAILURE(status)) |
| 103 | return -ENODEV; | 215 | return -ENODEV; |
| 104 | 216 | ||
| 105 | res = simple_read_from_buffer(buffer, count, ppos, | 217 | res = simple_read_from_buffer(buffer, count, ppos, dsdt, dsdt->length); |
| 106 | dsdt, dsdt->length); | ||
| 107 | 218 | ||
| 108 | return res; | 219 | return res; |
| 109 | } | 220 | } |
| @@ -123,28 +234,21 @@ acpi_system_read_fadt(struct file *file, | |||
| 123 | struct acpi_table_header *fadt = NULL; | 234 | struct acpi_table_header *fadt = NULL; |
| 124 | ssize_t res; | 235 | ssize_t res; |
| 125 | 236 | ||
| 126 | |||
| 127 | status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt); | 237 | status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt); |
| 128 | if (ACPI_FAILURE(status)) | 238 | if (ACPI_FAILURE(status)) |
| 129 | return -ENODEV; | 239 | return -ENODEV; |
| 130 | 240 | ||
| 131 | res = simple_read_from_buffer(buffer, count, ppos, | 241 | res = simple_read_from_buffer(buffer, count, ppos, fadt, fadt->length); |
| 132 | fadt, fadt->length); | ||
| 133 | 242 | ||
| 134 | return res; | 243 | return res; |
| 135 | } | 244 | } |
| 136 | 245 | ||
| 137 | static int __init acpi_system_init(void) | 246 | static int acpi_system_procfs_init(void) |
| 138 | { | 247 | { |
| 139 | struct proc_dir_entry *entry; | 248 | struct proc_dir_entry *entry; |
| 140 | int error = 0; | 249 | int error = 0; |
| 141 | char *name; | 250 | char *name; |
| 142 | 251 | ||
| 143 | |||
| 144 | if (acpi_disabled) | ||
| 145 | return 0; | ||
| 146 | |||
| 147 | #ifdef CONFIG_ACPI_PROCFS | ||
| 148 | /* 'info' [R] */ | 252 | /* 'info' [R] */ |
| 149 | name = ACPI_SYSTEM_FILE_INFO; | 253 | name = ACPI_SYSTEM_FILE_INFO; |
| 150 | entry = create_proc_entry(name, S_IRUGO, acpi_root_dir); | 254 | entry = create_proc_entry(name, S_IRUGO, acpi_root_dir); |
| @@ -153,7 +257,6 @@ static int __init acpi_system_init(void) | |||
| 153 | else { | 257 | else { |
| 154 | entry->proc_fops = &acpi_system_info_ops; | 258 | entry->proc_fops = &acpi_system_info_ops; |
| 155 | } | 259 | } |
| 156 | #endif | ||
| 157 | 260 | ||
| 158 | /* 'dsdt' [R] */ | 261 | /* 'dsdt' [R] */ |
| 159 | name = ACPI_SYSTEM_FILE_DSDT; | 262 | name = ACPI_SYSTEM_FILE_DSDT; |
| @@ -177,12 +280,32 @@ static int __init acpi_system_init(void) | |||
| 177 | Error: | 280 | Error: |
| 178 | remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir); | 281 | remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir); |
| 179 | remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir); | 282 | remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir); |
| 180 | #ifdef CONFIG_ACPI_PROCFS | ||
| 181 | remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir); | 283 | remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir); |
| 182 | #endif | ||
| 183 | 284 | ||
| 184 | error = -EFAULT; | 285 | error = -EFAULT; |
| 185 | goto Done; | 286 | goto Done; |
| 186 | } | 287 | } |
| 288 | #else | ||
| 289 | static int acpi_system_procfs_init(void) | ||
| 290 | { | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | #endif | ||
| 294 | |||
| 295 | static int __init acpi_system_init(void) | ||
| 296 | { | ||
| 297 | int result = 0; | ||
| 298 | |||
| 299 | if (acpi_disabled) | ||
| 300 | return 0; | ||
| 301 | |||
| 302 | result = acpi_system_procfs_init(); | ||
| 303 | if (result) | ||
| 304 | return result; | ||
| 305 | |||
| 306 | result = acpi_system_sysfs_init(); | ||
| 307 | |||
| 308 | return result; | ||
| 309 | } | ||
| 187 | 310 | ||
| 188 | subsys_initcall(acpi_system_init); | 311 | subsys_initcall(acpi_system_init); |
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 1285e91474fb..002bb33003af 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c | |||
| @@ -211,14 +211,17 @@ void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) | |||
| 211 | * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. | 211 | * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. |
| 212 | * Performs validation on some important FADT fields. | 212 | * Performs validation on some important FADT fields. |
| 213 | * | 213 | * |
| 214 | * NOTE: We create a local copy of the FADT regardless of the version. | ||
| 215 | * | ||
| 214 | ******************************************************************************/ | 216 | ******************************************************************************/ |
| 215 | 217 | ||
| 216 | void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) | 218 | void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) |
| 217 | { | 219 | { |
| 218 | 220 | ||
| 219 | /* | 221 | /* |
| 220 | * Check if the FADT is larger than what we know about (ACPI 2.0 version). | 222 | * Check if the FADT is larger than the largest table that we expect |
| 221 | * Truncate the table, but make some noise. | 223 | * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue |
| 224 | * a warning. | ||
| 222 | */ | 225 | */ |
| 223 | if (length > sizeof(struct acpi_table_fadt)) { | 226 | if (length > sizeof(struct acpi_table_fadt)) { |
| 224 | ACPI_WARNING((AE_INFO, | 227 | ACPI_WARNING((AE_INFO, |
| @@ -227,10 +230,12 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) | |||
| 227 | sizeof(struct acpi_table_fadt))); | 230 | sizeof(struct acpi_table_fadt))); |
| 228 | } | 231 | } |
| 229 | 232 | ||
| 230 | /* Copy the entire FADT locally. Zero first for tb_convert_fadt */ | 233 | /* Clear the entire local FADT */ |
| 231 | 234 | ||
| 232 | ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); | 235 | ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); |
| 233 | 236 | ||
| 237 | /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */ | ||
| 238 | |||
| 234 | ACPI_MEMCPY(&acpi_gbl_FADT, table, | 239 | ACPI_MEMCPY(&acpi_gbl_FADT, table, |
| 235 | ACPI_MIN(length, sizeof(struct acpi_table_fadt))); | 240 | ACPI_MIN(length, sizeof(struct acpi_table_fadt))); |
| 236 | 241 | ||
| @@ -251,7 +256,7 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) | |||
| 251 | * RETURN: None | 256 | * RETURN: None |
| 252 | * | 257 | * |
| 253 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. | 258 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. |
| 254 | * -> Expand all 32-bit addresses to 64-bit. | 259 | * Expand all 32-bit addresses to 64-bit. |
| 255 | * | 260 | * |
| 256 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), | 261 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), |
| 257 | * and must contain a copy of the actual FADT. | 262 | * and must contain a copy of the actual FADT. |
| @@ -292,8 +297,23 @@ static void acpi_tb_convert_fadt(void) | |||
| 292 | } | 297 | } |
| 293 | 298 | ||
| 294 | /* | 299 | /* |
| 295 | * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address | 300 | * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which |
| 296 | * structures as necessary. | 301 | * should be zero are indeed zero. This will workaround BIOSs that |
| 302 | * inadvertently place values in these fields. | ||
| 303 | * | ||
| 304 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at | ||
| 305 | * offset 45, 55, 95, and the word located at offset 109, 110. | ||
| 306 | */ | ||
| 307 | if (acpi_gbl_FADT.header.revision < 3) { | ||
| 308 | acpi_gbl_FADT.preferred_profile = 0; | ||
| 309 | acpi_gbl_FADT.pstate_control = 0; | ||
| 310 | acpi_gbl_FADT.cst_control = 0; | ||
| 311 | acpi_gbl_FADT.boot_flags = 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | /* | ||
| 315 | * Expand the ACPI 1.0 32-bit V1.0 addresses to the ACPI 2.0 64-bit "X" | ||
| 316 | * generic address structures as necessary. | ||
| 297 | */ | 317 | */ |
| 298 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { | 318 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { |
| 299 | target = | 319 | target = |
| @@ -349,18 +369,6 @@ static void acpi_tb_convert_fadt(void) | |||
| 349 | acpi_gbl_FADT.xpm1a_event_block.space_id; | 369 | acpi_gbl_FADT.xpm1a_event_block.space_id; |
| 350 | 370 | ||
| 351 | } | 371 | } |
| 352 | |||
| 353 | /* | ||
| 354 | * For ACPI 1.0 FADTs, ensure that reserved fields (which should be zero) | ||
| 355 | * are indeed zero. This will workaround BIOSs that inadvertently placed | ||
| 356 | * values in these fields. | ||
| 357 | */ | ||
| 358 | if (acpi_gbl_FADT.header.revision < 3) { | ||
| 359 | acpi_gbl_FADT.preferred_profile = 0; | ||
| 360 | acpi_gbl_FADT.pstate_control = 0; | ||
| 361 | acpi_gbl_FADT.cst_control = 0; | ||
| 362 | acpi_gbl_FADT.boot_flags = 0; | ||
| 363 | } | ||
| 364 | } | 372 | } |
| 365 | 373 | ||
| 366 | /****************************************************************************** | 374 | /****************************************************************************** |
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 8ec6f8e48138..f112af433e36 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c | |||
| @@ -62,16 +62,13 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, | |||
| 62 | static char *acpi_interfaces_supported[] = { | 62 | static char *acpi_interfaces_supported[] = { |
| 63 | /* Operating System Vendor Strings */ | 63 | /* Operating System Vendor Strings */ |
| 64 | 64 | ||
| 65 | "Windows 2000", | 65 | "Windows 2000", /* Windows 2000 */ |
| 66 | "Windows 2001", | 66 | "Windows 2001", /* Windows XP */ |
| 67 | "Windows 2001 SP0", | 67 | "Windows 2001 SP1", /* Windows XP SP1 */ |
| 68 | "Windows 2001 SP1", | 68 | "Windows 2001 SP2", /* Windows XP SP2 */ |
| 69 | "Windows 2001 SP2", | 69 | "Windows 2001.1", /* Windows Server 2003 */ |
| 70 | "Windows 2001 SP3", | 70 | "Windows 2001.1 SP1", /* Windows Server 2003 SP1 - Added 03/2006 */ |
| 71 | "Windows 2001 SP4", | 71 | "Windows 2006", /* Windows Vista - Added 03/2006 */ |
| 72 | "Windows 2001.1", | ||
| 73 | "Windows 2001.1 SP1", /* Added 03/2006 */ | ||
| 74 | "Windows 2006", /* Added 03/2006 */ | ||
| 75 | 72 | ||
| 76 | /* Feature Group Strings */ | 73 | /* Feature Group Strings */ |
| 77 | 74 | ||
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 00d25b347255..04ea697f72bf 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
| 34 | 34 | ||
| 35 | #include <linux/backlight.h> | 35 | #include <linux/backlight.h> |
| 36 | #include <linux/video_output.h> | ||
| 36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| 37 | 38 | ||
| 38 | #include <acpi/acpi_bus.h> | 39 | #include <acpi/acpi_bus.h> |
| @@ -169,6 +170,7 @@ struct acpi_video_device { | |||
| 169 | struct acpi_device *dev; | 170 | struct acpi_device *dev; |
| 170 | struct acpi_video_device_brightness *brightness; | 171 | struct acpi_video_device_brightness *brightness; |
| 171 | struct backlight_device *backlight; | 172 | struct backlight_device *backlight; |
| 173 | struct output_device *output_dev; | ||
| 172 | }; | 174 | }; |
| 173 | 175 | ||
| 174 | /* bus */ | 176 | /* bus */ |
| @@ -272,13 +274,17 @@ static int acpi_video_get_next_level(struct acpi_video_device *device, | |||
| 272 | u32 level_current, u32 event); | 274 | u32 level_current, u32 event); |
| 273 | static void acpi_video_switch_brightness(struct acpi_video_device *device, | 275 | static void acpi_video_switch_brightness(struct acpi_video_device *device, |
| 274 | int event); | 276 | int event); |
| 277 | static int acpi_video_device_get_state(struct acpi_video_device *device, | ||
| 278 | unsigned long *state); | ||
| 279 | static int acpi_video_output_get(struct output_device *od); | ||
| 280 | static int acpi_video_device_set_state(struct acpi_video_device *device, int state); | ||
| 275 | 281 | ||
| 276 | /*backlight device sysfs support*/ | 282 | /*backlight device sysfs support*/ |
| 277 | static int acpi_video_get_brightness(struct backlight_device *bd) | 283 | static int acpi_video_get_brightness(struct backlight_device *bd) |
| 278 | { | 284 | { |
| 279 | unsigned long cur_level; | 285 | unsigned long cur_level; |
| 280 | struct acpi_video_device *vd = | 286 | struct acpi_video_device *vd = |
| 281 | (struct acpi_video_device *)class_get_devdata(&bd->class_dev); | 287 | (struct acpi_video_device *)bl_get_data(bd); |
| 282 | acpi_video_device_lcd_get_level_current(vd, &cur_level); | 288 | acpi_video_device_lcd_get_level_current(vd, &cur_level); |
| 283 | return (int) cur_level; | 289 | return (int) cur_level; |
| 284 | } | 290 | } |
| @@ -287,7 +293,7 @@ static int acpi_video_set_brightness(struct backlight_device *bd) | |||
| 287 | { | 293 | { |
| 288 | int request_level = bd->props.brightness; | 294 | int request_level = bd->props.brightness; |
| 289 | struct acpi_video_device *vd = | 295 | struct acpi_video_device *vd = |
| 290 | (struct acpi_video_device *)class_get_devdata(&bd->class_dev); | 296 | (struct acpi_video_device *)bl_get_data(bd); |
| 291 | acpi_video_device_lcd_set_level(vd, request_level); | 297 | acpi_video_device_lcd_set_level(vd, request_level); |
| 292 | return 0; | 298 | return 0; |
| 293 | } | 299 | } |
| @@ -297,6 +303,28 @@ static struct backlight_ops acpi_backlight_ops = { | |||
| 297 | .update_status = acpi_video_set_brightness, | 303 | .update_status = acpi_video_set_brightness, |
| 298 | }; | 304 | }; |
| 299 | 305 | ||
| 306 | /*video output device sysfs support*/ | ||
| 307 | static int acpi_video_output_get(struct output_device *od) | ||
| 308 | { | ||
| 309 | unsigned long state; | ||
| 310 | struct acpi_video_device *vd = | ||
| 311 | (struct acpi_video_device *)class_get_devdata(&od->class_dev); | ||
| 312 | acpi_video_device_get_state(vd, &state); | ||
| 313 | return (int)state; | ||
| 314 | } | ||
| 315 | |||
| 316 | static int acpi_video_output_set(struct output_device *od) | ||
| 317 | { | ||
| 318 | unsigned long state = od->request_state; | ||
| 319 | struct acpi_video_device *vd= | ||
| 320 | (struct acpi_video_device *)class_get_devdata(&od->class_dev); | ||
| 321 | return acpi_video_device_set_state(vd, state); | ||
| 322 | } | ||
| 323 | |||
| 324 | static struct output_properties acpi_output_properties = { | ||
| 325 | .set_state = acpi_video_output_set, | ||
| 326 | .get_status = acpi_video_output_get, | ||
| 327 | }; | ||
| 300 | /* -------------------------------------------------------------------------- | 328 | /* -------------------------------------------------------------------------- |
| 301 | Video Management | 329 | Video Management |
| 302 | -------------------------------------------------------------------------- */ | 330 | -------------------------------------------------------------------------- */ |
| @@ -531,7 +559,6 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) | |||
| 531 | 559 | ||
| 532 | static void acpi_video_device_find_cap(struct acpi_video_device *device) | 560 | static void acpi_video_device_find_cap(struct acpi_video_device *device) |
| 533 | { | 561 | { |
| 534 | acpi_integer status; | ||
| 535 | acpi_handle h_dummy1; | 562 | acpi_handle h_dummy1; |
| 536 | int i; | 563 | int i; |
| 537 | u32 max_level = 0; | 564 | u32 max_level = 0; |
| @@ -565,50 +592,55 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 565 | device->cap._DSS = 1; | 592 | device->cap._DSS = 1; |
| 566 | } | 593 | } |
| 567 | 594 | ||
| 568 | status = acpi_video_device_lcd_query_levels(device, &obj); | 595 | if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { |
| 569 | 596 | ||
| 570 | if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) { | 597 | if (obj->package.count >= 2) { |
| 571 | int count = 0; | 598 | int count = 0; |
| 572 | union acpi_object *o; | 599 | union acpi_object *o; |
| 573 | 600 | ||
| 574 | br = kzalloc(sizeof(*br), GFP_KERNEL); | 601 | br = kzalloc(sizeof(*br), GFP_KERNEL); |
| 575 | if (!br) { | 602 | if (!br) { |
| 576 | printk(KERN_ERR "can't allocate memory\n"); | 603 | printk(KERN_ERR "can't allocate memory\n"); |
| 577 | } else { | ||
| 578 | br->levels = kmalloc(obj->package.count * | ||
| 579 | sizeof *(br->levels), GFP_KERNEL); | ||
| 580 | if (!br->levels) | ||
| 581 | goto out; | ||
| 582 | |||
| 583 | for (i = 0; i < obj->package.count; i++) { | ||
| 584 | o = (union acpi_object *)&obj->package. | ||
| 585 | elements[i]; | ||
| 586 | if (o->type != ACPI_TYPE_INTEGER) { | ||
| 587 | printk(KERN_ERR PREFIX "Invalid data\n"); | ||
| 588 | continue; | ||
| 589 | } | ||
| 590 | br->levels[count] = (u32) o->integer.value; | ||
| 591 | if (br->levels[count] > max_level) | ||
| 592 | max_level = br->levels[count]; | ||
| 593 | count++; | ||
| 594 | } | ||
| 595 | out: | ||
| 596 | if (count < 2) { | ||
| 597 | kfree(br->levels); | ||
| 598 | kfree(br); | ||
| 599 | } else { | 604 | } else { |
| 600 | br->count = count; | 605 | br->levels = kmalloc(obj->package.count * |
| 601 | device->brightness = br; | 606 | sizeof *(br->levels), GFP_KERNEL); |
| 602 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 607 | if (!br->levels) |
| 603 | "found %d brightness levels\n", | 608 | goto out; |
| 604 | count)); | 609 | |
| 610 | for (i = 0; i < obj->package.count; i++) { | ||
| 611 | o = (union acpi_object *)&obj->package. | ||
| 612 | elements[i]; | ||
| 613 | if (o->type != ACPI_TYPE_INTEGER) { | ||
| 614 | printk(KERN_ERR PREFIX "Invalid data\n"); | ||
| 615 | continue; | ||
| 616 | } | ||
| 617 | br->levels[count] = (u32) o->integer.value; | ||
| 618 | |||
| 619 | if (br->levels[count] > max_level) | ||
| 620 | max_level = br->levels[count]; | ||
| 621 | count++; | ||
| 622 | } | ||
| 623 | out: | ||
| 624 | if (count < 2) { | ||
| 625 | kfree(br->levels); | ||
| 626 | kfree(br); | ||
| 627 | } else { | ||
| 628 | br->count = count; | ||
| 629 | device->brightness = br; | ||
| 630 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 631 | "found %d brightness levels\n", | ||
| 632 | count)); | ||
| 633 | } | ||
| 605 | } | 634 | } |
| 606 | } | 635 | } |
| 636 | |||
| 637 | } else { | ||
| 638 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n")); | ||
| 607 | } | 639 | } |
| 608 | 640 | ||
| 609 | kfree(obj); | 641 | kfree(obj); |
| 610 | 642 | ||
| 611 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC){ | 643 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ |
| 612 | unsigned long tmp; | 644 | unsigned long tmp; |
| 613 | static int count = 0; | 645 | static int count = 0; |
| 614 | char *name; | 646 | char *name; |
| @@ -626,6 +658,17 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 626 | 658 | ||
| 627 | kfree(name); | 659 | kfree(name); |
| 628 | } | 660 | } |
| 661 | if (device->cap._DCS && device->cap._DSS){ | ||
| 662 | static int count = 0; | ||
| 663 | char *name; | ||
| 664 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | ||
| 665 | if (!name) | ||
| 666 | return; | ||
| 667 | sprintf(name, "acpi_video%d", count++); | ||
| 668 | device->output_dev = video_output_register(name, | ||
| 669 | NULL, device, &acpi_output_properties); | ||
| 670 | kfree(name); | ||
| 671 | } | ||
| 629 | return; | 672 | return; |
| 630 | } | 673 | } |
| 631 | 674 | ||
| @@ -1669,6 +1712,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
| 1669 | ACPI_DEVICE_NOTIFY, | 1712 | ACPI_DEVICE_NOTIFY, |
| 1670 | acpi_video_device_notify); | 1713 | acpi_video_device_notify); |
| 1671 | backlight_device_unregister(device->backlight); | 1714 | backlight_device_unregister(device->backlight); |
| 1715 | video_output_unregister(device->output_dev); | ||
| 1672 | return 0; | 1716 | return 0; |
| 1673 | } | 1717 | } |
| 1674 | 1718 | ||
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c index a9ab30fefffc..2b0c601e422e 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c | |||
| @@ -142,6 +142,7 @@ void set_trace_device(struct device *dev) | |||
| 142 | { | 142 | { |
| 143 | dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH); | 143 | dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH); |
| 144 | } | 144 | } |
| 145 | EXPORT_SYMBOL(set_trace_device); | ||
| 145 | 146 | ||
| 146 | /* | 147 | /* |
| 147 | * We could just take the "tracedata" index into the .tracedata | 148 | * We could just take the "tracedata" index into the .tracedata |
| @@ -162,6 +163,7 @@ void generate_resume_trace(void *tracedata, unsigned int user) | |||
| 162 | file_hash_value = hash_string(lineno, file, FILEHASH); | 163 | file_hash_value = hash_string(lineno, file, FILEHASH); |
| 163 | set_magic_time(user_hash_value, file_hash_value, dev_hash_value); | 164 | set_magic_time(user_hash_value, file_hash_value, dev_hash_value); |
| 164 | } | 165 | } |
| 166 | EXPORT_SYMBOL(generate_resume_trace); | ||
| 165 | 167 | ||
| 166 | extern char __tracedata_start, __tracedata_end; | 168 | extern char __tracedata_start, __tracedata_end; |
| 167 | static int show_file_hash(unsigned int value) | 169 | static int show_file_hash(unsigned int value) |
| @@ -170,7 +172,8 @@ static int show_file_hash(unsigned int value) | |||
| 170 | char *tracedata; | 172 | char *tracedata; |
| 171 | 173 | ||
| 172 | match = 0; | 174 | match = 0; |
| 173 | for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; tracedata += 6) { | 175 | for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; |
| 176 | tracedata += 2 + sizeof(unsigned long)) { | ||
| 174 | unsigned short lineno = *(unsigned short *)tracedata; | 177 | unsigned short lineno = *(unsigned short *)tracedata; |
| 175 | const char *file = *(const char **)(tracedata + 2); | 178 | const char *file = *(const char **)(tracedata + 2); |
| 176 | unsigned int hash = hash_string(lineno, file, FILEHASH); | 179 | unsigned int hash = hash_string(lineno, file, FILEHASH); |
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 819c829125fb..a7a099027fca 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | obj-$(CONFIG_MAC_FLOPPY) += swim3.o | 8 | obj-$(CONFIG_MAC_FLOPPY) += swim3.o |
| 9 | obj-$(CONFIG_BLK_DEV_FD) += floppy.o | 9 | obj-$(CONFIG_BLK_DEV_FD) += floppy.o |
| 10 | obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o | 10 | obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o |
| 11 | obj-$(CONFIG_PS3_DISK) += ps3disk.o | ||
| 11 | obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o | 12 | obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o |
| 12 | obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o | 13 | obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o |
| 13 | obj-$(CONFIG_BLK_DEV_RAM) += rd.o | 14 | obj-$(CONFIG_BLK_DEV_RAM) += rd.o |
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c new file mode 100644 index 000000000000..170fb33dba97 --- /dev/null +++ b/drivers/block/ps3disk.c | |||
| @@ -0,0 +1,630 @@ | |||
| 1 | /* | ||
| 2 | * PS3 Disk Storage Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published | ||
| 9 | * by the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but | ||
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/ata.h> | ||
| 22 | #include <linux/blkdev.h> | ||
| 23 | |||
| 24 | #include <asm/lv1call.h> | ||
| 25 | #include <asm/ps3stor.h> | ||
| 26 | #include <asm/firmware.h> | ||
| 27 | |||
| 28 | |||
| 29 | #define DEVICE_NAME "ps3disk" | ||
| 30 | |||
| 31 | #define BOUNCE_SIZE (64*1024) | ||
| 32 | |||
| 33 | #define PS3DISK_MAX_DISKS 16 | ||
| 34 | #define PS3DISK_MINORS 16 | ||
| 35 | |||
| 36 | |||
| 37 | #define PS3DISK_NAME "ps3d%c" | ||
| 38 | |||
| 39 | |||
| 40 | struct ps3disk_private { | ||
| 41 | spinlock_t lock; /* Request queue spinlock */ | ||
| 42 | struct request_queue *queue; | ||
| 43 | struct gendisk *gendisk; | ||
| 44 | unsigned int blocking_factor; | ||
| 45 | struct request *req; | ||
| 46 | u64 raw_capacity; | ||
| 47 | unsigned char model[ATA_ID_PROD_LEN+1]; | ||
| 48 | }; | ||
| 49 | |||
| 50 | |||
| 51 | #define LV1_STORAGE_SEND_ATA_COMMAND (2) | ||
| 52 | #define LV1_STORAGE_ATA_HDDOUT (0x23) | ||
| 53 | |||
| 54 | struct lv1_ata_cmnd_block { | ||
| 55 | u16 features; | ||
| 56 | u16 sector_count; | ||
| 57 | u16 LBA_low; | ||
| 58 | u16 LBA_mid; | ||
| 59 | u16 LBA_high; | ||
| 60 | u8 device; | ||
| 61 | u8 command; | ||
| 62 | u32 is_ext; | ||
| 63 | u32 proto; | ||
| 64 | u32 in_out; | ||
| 65 | u32 size; | ||
| 66 | u64 buffer; | ||
| 67 | u32 arglen; | ||
| 68 | }; | ||
| 69 | |||
| 70 | enum lv1_ata_proto { | ||
| 71 | NON_DATA_PROTO = 0, | ||
| 72 | PIO_DATA_IN_PROTO = 1, | ||
| 73 | PIO_DATA_OUT_PROTO = 2, | ||
| 74 | DMA_PROTO = 3 | ||
| 75 | }; | ||
| 76 | |||
| 77 | enum lv1_ata_in_out { | ||
| 78 | DIR_WRITE = 0, /* memory -> device */ | ||
| 79 | DIR_READ = 1 /* device -> memory */ | ||
| 80 | }; | ||
| 81 | |||
| 82 | static int ps3disk_major; | ||
| 83 | |||
| 84 | |||
| 85 | static struct block_device_operations ps3disk_fops = { | ||
| 86 | .owner = THIS_MODULE, | ||
| 87 | }; | ||
| 88 | |||
| 89 | |||
| 90 | static void ps3disk_scatter_gather(struct ps3_storage_device *dev, | ||
| 91 | struct request *req, int gather) | ||
| 92 | { | ||
| 93 | unsigned int offset = 0; | ||
| 94 | struct bio *bio; | ||
| 95 | sector_t sector; | ||
| 96 | struct bio_vec *bvec; | ||
| 97 | unsigned int i = 0, j; | ||
| 98 | size_t size; | ||
| 99 | void *buf; | ||
| 100 | |||
| 101 | rq_for_each_bio(bio, req) { | ||
| 102 | sector = bio->bi_sector; | ||
| 103 | dev_dbg(&dev->sbd.core, | ||
| 104 | "%s:%u: bio %u: %u segs %u sectors from %lu\n", | ||
| 105 | __func__, __LINE__, i, bio_segments(bio), | ||
| 106 | bio_sectors(bio), sector); | ||
| 107 | bio_for_each_segment(bvec, bio, j) { | ||
| 108 | size = bvec->bv_len; | ||
| 109 | buf = __bio_kmap_atomic(bio, j, KM_IRQ0); | ||
| 110 | if (gather) | ||
| 111 | memcpy(dev->bounce_buf+offset, buf, size); | ||
| 112 | else | ||
| 113 | memcpy(buf, dev->bounce_buf+offset, size); | ||
| 114 | offset += size; | ||
| 115 | flush_kernel_dcache_page(bio_iovec_idx(bio, j)->bv_page); | ||
| 116 | __bio_kunmap_atomic(bio, KM_IRQ0); | ||
| 117 | } | ||
| 118 | i++; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, | ||
| 123 | struct request *req) | ||
| 124 | { | ||
| 125 | struct ps3disk_private *priv = dev->sbd.core.driver_data; | ||
| 126 | int write = rq_data_dir(req), res; | ||
| 127 | const char *op = write ? "write" : "read"; | ||
| 128 | u64 start_sector, sectors; | ||
| 129 | unsigned int region_id = dev->regions[dev->region_idx].id; | ||
| 130 | |||
| 131 | #ifdef DEBUG | ||
| 132 | unsigned int n = 0; | ||
| 133 | struct bio *bio; | ||
| 134 | |||
| 135 | rq_for_each_bio(bio, req) | ||
| 136 | n++; | ||
| 137 | dev_dbg(&dev->sbd.core, | ||
| 138 | "%s:%u: %s req has %u bios for %lu sectors %lu hard sectors\n", | ||
| 139 | __func__, __LINE__, op, n, req->nr_sectors, | ||
| 140 | req->hard_nr_sectors); | ||
| 141 | #endif | ||
| 142 | |||
| 143 | start_sector = req->sector * priv->blocking_factor; | ||
| 144 | sectors = req->nr_sectors * priv->blocking_factor; | ||
| 145 | dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n", | ||
| 146 | __func__, __LINE__, op, sectors, start_sector); | ||
| 147 | |||
| 148 | if (write) { | ||
| 149 | ps3disk_scatter_gather(dev, req, 1); | ||
| 150 | |||
| 151 | res = lv1_storage_write(dev->sbd.dev_id, region_id, | ||
| 152 | start_sector, sectors, 0, | ||
| 153 | dev->bounce_lpar, &dev->tag); | ||
| 154 | } else { | ||
| 155 | res = lv1_storage_read(dev->sbd.dev_id, region_id, | ||
| 156 | start_sector, sectors, 0, | ||
| 157 | dev->bounce_lpar, &dev->tag); | ||
| 158 | } | ||
| 159 | if (res) { | ||
| 160 | dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__, | ||
| 161 | __LINE__, op, res); | ||
| 162 | end_request(req, 0); | ||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | priv->req = req; | ||
| 167 | return 1; | ||
| 168 | } | ||
| 169 | |||
| 170 | static int ps3disk_submit_flush_request(struct ps3_storage_device *dev, | ||
| 171 | struct request *req) | ||
| 172 | { | ||
| 173 | struct ps3disk_private *priv = dev->sbd.core.driver_data; | ||
| 174 | u64 res; | ||
| 175 | |||
| 176 | dev_dbg(&dev->sbd.core, "%s:%u: flush request\n", __func__, __LINE__); | ||
| 177 | |||
| 178 | res = lv1_storage_send_device_command(dev->sbd.dev_id, | ||
| 179 | LV1_STORAGE_ATA_HDDOUT, 0, 0, 0, | ||
| 180 | 0, &dev->tag); | ||
| 181 | if (res) { | ||
| 182 | dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%lx\n", | ||
| 183 | __func__, __LINE__, res); | ||
| 184 | end_request(req, 0); | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | priv->req = req; | ||
| 189 | return 1; | ||
| 190 | } | ||
| 191 | |||
| 192 | static void ps3disk_do_request(struct ps3_storage_device *dev, | ||
| 193 | request_queue_t *q) | ||
| 194 | { | ||
| 195 | struct request *req; | ||
| 196 | |||
| 197 | dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); | ||
| 198 | |||
| 199 | while ((req = elv_next_request(q))) { | ||
| 200 | if (blk_fs_request(req)) { | ||
| 201 | if (ps3disk_submit_request_sg(dev, req)) | ||
| 202 | break; | ||
| 203 | } else if (req->cmd_type == REQ_TYPE_FLUSH) { | ||
| 204 | if (ps3disk_submit_flush_request(dev, req)) | ||
| 205 | break; | ||
| 206 | } else { | ||
| 207 | blk_dump_rq_flags(req, DEVICE_NAME " bad request"); | ||
| 208 | end_request(req, 0); | ||
| 209 | continue; | ||
| 210 | } | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | static void ps3disk_request(request_queue_t *q) | ||
| 215 | { | ||
| 216 | struct ps3_storage_device *dev = q->queuedata; | ||
| 217 | struct ps3disk_private *priv = dev->sbd.core.driver_data; | ||
| 218 | |||
| 219 | if (priv->req) { | ||
| 220 | dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__); | ||
| 221 | return; | ||
| 222 | } | ||
| 223 | |||
| 224 | ps3disk_do_request(dev, q); | ||
| 225 | } | ||
| 226 | |||
| 227 | static irqreturn_t ps3disk_interrupt(int irq, void *data) | ||
| 228 | { | ||
| 229 | struct ps3_storage_device *dev = data; | ||
| 230 | struct ps3disk_private *priv; | ||
| 231 | struct request *req; | ||
| 232 | int res, read, uptodate; | ||
| 233 | u64 tag, status; | ||
| 234 | unsigned long num_sectors; | ||
| 235 | const char *op; | ||
| 236 | |||
| 237 | res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status); | ||
| 238 | |||
| 239 | if (tag != dev->tag) | ||
| 240 | dev_err(&dev->sbd.core, | ||
| 241 | "%s:%u: tag mismatch, got %lx, expected %lx\n", | ||
| 242 | __func__, __LINE__, tag, dev->tag); | ||
| 243 | |||
| 244 | if (res) { | ||
| 245 | dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n", | ||
| 246 | __func__, __LINE__, res, status); | ||
| 247 | return IRQ_HANDLED; | ||
| 248 | } | ||
| 249 | |||
| 250 | priv = dev->sbd.core.driver_data; | ||
| 251 | req = priv->req; | ||
| 252 | if (!req) { | ||
| 253 | dev_dbg(&dev->sbd.core, | ||
| 254 | "%s:%u non-block layer request completed\n", __func__, | ||
| 255 | __LINE__); | ||
| 256 | dev->lv1_status = status; | ||
| 257 | complete(&dev->done); | ||
| 258 | return IRQ_HANDLED; | ||
| 259 | } | ||
| 260 | |||
| 261 | if (req->cmd_type == REQ_TYPE_FLUSH) { | ||
| 262 | read = 0; | ||
| 263 | num_sectors = req->hard_cur_sectors; | ||
| 264 | op = "flush"; | ||
| 265 | } else { | ||
| 266 | read = !rq_data_dir(req); | ||
| 267 | num_sectors = req->nr_sectors; | ||
| 268 | op = read ? "read" : "write"; | ||
| 269 | } | ||
| 270 | if (status) { | ||
| 271 | dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__, | ||
| 272 | __LINE__, op, status); | ||
| 273 | uptodate = 0; | ||
| 274 | } else { | ||
| 275 | dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__, | ||
| 276 | __LINE__, op); | ||
| 277 | uptodate = 1; | ||
| 278 | if (read) | ||
| 279 | ps3disk_scatter_gather(dev, req, 0); | ||
| 280 | } | ||
| 281 | |||
| 282 | spin_lock(&priv->lock); | ||
| 283 | if (!end_that_request_first(req, uptodate, num_sectors)) { | ||
| 284 | add_disk_randomness(req->rq_disk); | ||
| 285 | blkdev_dequeue_request(req); | ||
| 286 | end_that_request_last(req, uptodate); | ||
| 287 | } | ||
| 288 | priv->req = NULL; | ||
| 289 | ps3disk_do_request(dev, priv->queue); | ||
| 290 | spin_unlock(&priv->lock); | ||
| 291 | |||
| 292 | return IRQ_HANDLED; | ||
| 293 | } | ||
| 294 | |||
| 295 | static int ps3disk_sync_cache(struct ps3_storage_device *dev) | ||
| 296 | { | ||
| 297 | u64 res; | ||
| 298 | |||
| 299 | dev_dbg(&dev->sbd.core, "%s:%u: sync cache\n", __func__, __LINE__); | ||
| 300 | |||
| 301 | res = ps3stor_send_command(dev, LV1_STORAGE_ATA_HDDOUT, 0, 0, 0, 0); | ||
| 302 | if (res) { | ||
| 303 | dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%lx\n", | ||
| 304 | __func__, __LINE__, res); | ||
| 305 | return -EIO; | ||
| 306 | } | ||
| 307 | return 0; | ||
| 308 | } | ||
| 309 | |||
| 310 | |||
| 311 | /* ATA helpers copied from drivers/ata/libata-core.c */ | ||
| 312 | |||
| 313 | static void swap_buf_le16(u16 *buf, unsigned int buf_words) | ||
| 314 | { | ||
| 315 | #ifdef __BIG_ENDIAN | ||
| 316 | unsigned int i; | ||
| 317 | |||
| 318 | for (i = 0; i < buf_words; i++) | ||
| 319 | buf[i] = le16_to_cpu(buf[i]); | ||
| 320 | #endif /* __BIG_ENDIAN */ | ||
| 321 | } | ||
| 322 | |||
| 323 | static u64 ata_id_n_sectors(const u16 *id) | ||
| 324 | { | ||
| 325 | if (ata_id_has_lba(id)) { | ||
| 326 | if (ata_id_has_lba48(id)) | ||
| 327 | return ata_id_u64(id, 100); | ||
| 328 | else | ||
| 329 | return ata_id_u32(id, 60); | ||
| 330 | } else { | ||
| 331 | if (ata_id_current_chs_valid(id)) | ||
| 332 | return ata_id_u32(id, 57); | ||
| 333 | else | ||
| 334 | return id[1] * id[3] * id[6]; | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | static void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs, | ||
| 339 | unsigned int len) | ||
| 340 | { | ||
| 341 | unsigned int c; | ||
| 342 | |||
| 343 | while (len > 0) { | ||
| 344 | c = id[ofs] >> 8; | ||
| 345 | *s = c; | ||
| 346 | s++; | ||
| 347 | |||
| 348 | c = id[ofs] & 0xff; | ||
| 349 | *s = c; | ||
| 350 | s++; | ||
| 351 | |||
| 352 | ofs++; | ||
| 353 | len -= 2; | ||
| 354 | } | ||
| 355 | } | ||
| 356 | |||
| 357 | static void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs, | ||
| 358 | unsigned int len) | ||
| 359 | { | ||
| 360 | unsigned char *p; | ||
| 361 | |||
| 362 | WARN_ON(!(len & 1)); | ||
| 363 | |||
| 364 | ata_id_string(id, s, ofs, len - 1); | ||
| 365 | |||
| 366 | p = s + strnlen(s, len - 1); | ||
| 367 | while (p > s && p[-1] == ' ') | ||
| 368 | p--; | ||
| 369 | *p = '\0'; | ||
| 370 | } | ||
| 371 | |||
| 372 | static int ps3disk_identify(struct ps3_storage_device *dev) | ||
| 373 | { | ||
| 374 | struct ps3disk_private *priv = dev->sbd.core.driver_data; | ||
| 375 | struct lv1_ata_cmnd_block ata_cmnd; | ||
| 376 | u16 *id = dev->bounce_buf; | ||
| 377 | u64 res; | ||
| 378 | |||
| 379 | dev_dbg(&dev->sbd.core, "%s:%u: identify disk\n", __func__, __LINE__); | ||
| 380 | |||
| 381 | memset(&ata_cmnd, 0, sizeof(struct lv1_ata_cmnd_block)); | ||
| 382 | ata_cmnd.command = ATA_CMD_ID_ATA; | ||
| 383 | ata_cmnd.sector_count = 1; | ||
| 384 | ata_cmnd.size = ata_cmnd.arglen = ATA_ID_WORDS * 2; | ||
| 385 | ata_cmnd.buffer = dev->bounce_lpar; | ||
| 386 | ata_cmnd.proto = PIO_DATA_IN_PROTO; | ||
| 387 | ata_cmnd.in_out = DIR_READ; | ||
| 388 | |||
| 389 | res = ps3stor_send_command(dev, LV1_STORAGE_SEND_ATA_COMMAND, | ||
| 390 | ps3_mm_phys_to_lpar(__pa(&ata_cmnd)), | ||
| 391 | sizeof(ata_cmnd), ata_cmnd.buffer, | ||
| 392 | ata_cmnd.arglen); | ||
| 393 | if (res) { | ||
| 394 | dev_err(&dev->sbd.core, "%s:%u: identify disk failed 0x%lx\n", | ||
| 395 | __func__, __LINE__, res); | ||
| 396 | return -EIO; | ||
| 397 | } | ||
| 398 | |||
| 399 | swap_buf_le16(id, ATA_ID_WORDS); | ||
| 400 | |||
| 401 | /* All we're interested in are raw capacity and model name */ | ||
| 402 | priv->raw_capacity = ata_id_n_sectors(id); | ||
| 403 | ata_id_c_string(id, priv->model, ATA_ID_PROD, sizeof(priv->model)); | ||
| 404 | return 0; | ||
| 405 | } | ||
| 406 | |||
| 407 | static void ps3disk_prepare_flush(request_queue_t *q, struct request *req) | ||
| 408 | { | ||
| 409 | struct ps3_storage_device *dev = q->queuedata; | ||
| 410 | |||
| 411 | dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); | ||
| 412 | |||
| 413 | memset(req->cmd, 0, sizeof(req->cmd)); | ||
| 414 | req->cmd_type = REQ_TYPE_FLUSH; | ||
| 415 | } | ||
| 416 | |||
| 417 | static int ps3disk_issue_flush(request_queue_t *q, struct gendisk *gendisk, | ||
| 418 | sector_t *sector) | ||
| 419 | { | ||
| 420 | struct ps3_storage_device *dev = q->queuedata; | ||
| 421 | struct request *req; | ||
| 422 | int res; | ||
| 423 | |||
| 424 | dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); | ||
| 425 | |||
| 426 | req = blk_get_request(q, WRITE, __GFP_WAIT); | ||
| 427 | ps3disk_prepare_flush(q, req); | ||
| 428 | res = blk_execute_rq(q, gendisk, req, 0); | ||
| 429 | if (res) | ||
| 430 | dev_err(&dev->sbd.core, "%s:%u: flush request failed %d\n", | ||
| 431 | __func__, __LINE__, res); | ||
| 432 | blk_put_request(req); | ||
| 433 | return res; | ||
| 434 | } | ||
| 435 | |||
| 436 | |||
| 437 | static unsigned long ps3disk_mask; | ||
| 438 | |||
| 439 | static DEFINE_MUTEX(ps3disk_mask_mutex); | ||
| 440 | |||
| 441 | static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev) | ||
| 442 | { | ||
| 443 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); | ||
| 444 | struct ps3disk_private *priv; | ||
| 445 | int error; | ||
| 446 | unsigned int devidx; | ||
| 447 | struct request_queue *queue; | ||
| 448 | struct gendisk *gendisk; | ||
| 449 | |||
| 450 | if (dev->blk_size < 512) { | ||
| 451 | dev_err(&dev->sbd.core, | ||
| 452 | "%s:%u: cannot handle block size %lu\n", __func__, | ||
| 453 | __LINE__, dev->blk_size); | ||
| 454 | return -EINVAL; | ||
| 455 | } | ||
| 456 | |||
| 457 | BUILD_BUG_ON(PS3DISK_MAX_DISKS > BITS_PER_LONG); | ||
| 458 | mutex_lock(&ps3disk_mask_mutex); | ||
| 459 | devidx = find_first_zero_bit(&ps3disk_mask, PS3DISK_MAX_DISKS); | ||
| 460 | if (devidx >= PS3DISK_MAX_DISKS) { | ||
| 461 | dev_err(&dev->sbd.core, "%s:%u: Too many disks\n", __func__, | ||
| 462 | __LINE__); | ||
| 463 | mutex_unlock(&ps3disk_mask_mutex); | ||
| 464 | return -ENOSPC; | ||
| 465 | } | ||
| 466 | __set_bit(devidx, &ps3disk_mask); | ||
| 467 | mutex_unlock(&ps3disk_mask_mutex); | ||
| 468 | |||
| 469 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 470 | if (!priv) { | ||
| 471 | error = -ENOMEM; | ||
| 472 | goto fail; | ||
| 473 | } | ||
| 474 | |||
| 475 | dev->sbd.core.driver_data = priv; | ||
| 476 | spin_lock_init(&priv->lock); | ||
| 477 | |||
| 478 | dev->bounce_size = BOUNCE_SIZE; | ||
| 479 | dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA); | ||
| 480 | if (!dev->bounce_buf) { | ||
| 481 | error = -ENOMEM; | ||
| 482 | goto fail_free_priv; | ||
| 483 | } | ||
| 484 | |||
| 485 | error = ps3stor_setup(dev, ps3disk_interrupt); | ||
| 486 | if (error) | ||
| 487 | goto fail_free_bounce; | ||
| 488 | |||
| 489 | ps3disk_identify(dev); | ||
| 490 | |||
| 491 | queue = blk_init_queue(ps3disk_request, &priv->lock); | ||
| 492 | if (!queue) { | ||
| 493 | dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n", | ||
| 494 | __func__, __LINE__); | ||
| 495 | error = -ENOMEM; | ||
| 496 | goto fail_teardown; | ||
| 497 | } | ||
| 498 | |||
| 499 | priv->queue = queue; | ||
| 500 | queue->queuedata = dev; | ||
| 501 | |||
| 502 | blk_queue_bounce_limit(queue, BLK_BOUNCE_HIGH); | ||
| 503 | |||
| 504 | blk_queue_max_sectors(queue, dev->bounce_size >> 9); | ||
| 505 | blk_queue_segment_boundary(queue, -1UL); | ||
| 506 | blk_queue_dma_alignment(queue, dev->blk_size-1); | ||
| 507 | blk_queue_hardsect_size(queue, dev->blk_size); | ||
| 508 | |||
| 509 | blk_queue_issue_flush_fn(queue, ps3disk_issue_flush); | ||
| 510 | blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH, | ||
| 511 | ps3disk_prepare_flush); | ||
| 512 | |||
| 513 | blk_queue_max_phys_segments(queue, -1); | ||
| 514 | blk_queue_max_hw_segments(queue, -1); | ||
| 515 | blk_queue_max_segment_size(queue, dev->bounce_size); | ||
| 516 | |||
| 517 | gendisk = alloc_disk(PS3DISK_MINORS); | ||
| 518 | if (!gendisk) { | ||
| 519 | dev_err(&dev->sbd.core, "%s:%u: alloc_disk failed\n", __func__, | ||
| 520 | __LINE__); | ||
| 521 | error = -ENOMEM; | ||
| 522 | goto fail_cleanup_queue; | ||
| 523 | } | ||
| 524 | |||
| 525 | priv->gendisk = gendisk; | ||
| 526 | gendisk->major = ps3disk_major; | ||
| 527 | gendisk->first_minor = devidx * PS3DISK_MINORS; | ||
| 528 | gendisk->fops = &ps3disk_fops; | ||
| 529 | gendisk->queue = queue; | ||
| 530 | gendisk->private_data = dev; | ||
| 531 | gendisk->driverfs_dev = &dev->sbd.core; | ||
| 532 | snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME, | ||
| 533 | devidx+'a'); | ||
| 534 | priv->blocking_factor = dev->blk_size >> 9; | ||
| 535 | set_capacity(gendisk, | ||
| 536 | dev->regions[dev->region_idx].size*priv->blocking_factor); | ||
| 537 | |||
| 538 | dev_info(&dev->sbd.core, | ||
| 539 | "%s is a %s (%lu MiB total, %lu MiB for OtherOS)\n", | ||
| 540 | gendisk->disk_name, priv->model, priv->raw_capacity >> 11, | ||
| 541 | get_capacity(gendisk) >> 11); | ||
| 542 | |||
| 543 | add_disk(gendisk); | ||
| 544 | return 0; | ||
| 545 | |||
| 546 | fail_cleanup_queue: | ||
| 547 | blk_cleanup_queue(queue); | ||
| 548 | fail_teardown: | ||
| 549 | ps3stor_teardown(dev); | ||
| 550 | fail_free_bounce: | ||
| 551 | kfree(dev->bounce_buf); | ||
| 552 | fail_free_priv: | ||
| 553 | kfree(priv); | ||
| 554 | dev->sbd.core.driver_data = NULL; | ||
| 555 | fail: | ||
| 556 | mutex_lock(&ps3disk_mask_mutex); | ||
| 557 | __clear_bit(devidx, &ps3disk_mask); | ||
| 558 | mutex_unlock(&ps3disk_mask_mutex); | ||
| 559 | return error; | ||
| 560 | } | ||
| 561 | |||
| 562 | static int ps3disk_remove(struct ps3_system_bus_device *_dev) | ||
| 563 | { | ||
| 564 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); | ||
| 565 | struct ps3disk_private *priv = dev->sbd.core.driver_data; | ||
| 566 | |||
| 567 | mutex_lock(&ps3disk_mask_mutex); | ||
| 568 | __clear_bit(priv->gendisk->first_minor / PS3DISK_MINORS, | ||
| 569 | &ps3disk_mask); | ||
| 570 | mutex_unlock(&ps3disk_mask_mutex); | ||
| 571 | del_gendisk(priv->gendisk); | ||
| 572 | blk_cleanup_queue(priv->queue); | ||
| 573 | put_disk(priv->gendisk); | ||
| 574 | dev_notice(&dev->sbd.core, "Synchronizing disk cache\n"); | ||
| 575 | ps3disk_sync_cache(dev); | ||
| 576 | ps3stor_teardown(dev); | ||
| 577 | kfree(dev->bounce_buf); | ||
| 578 | kfree(priv); | ||
| 579 | dev->sbd.core.driver_data = NULL; | ||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | static struct ps3_system_bus_driver ps3disk = { | ||
| 584 | .match_id = PS3_MATCH_ID_STOR_DISK, | ||
| 585 | .core.name = DEVICE_NAME, | ||
| 586 | .core.owner = THIS_MODULE, | ||
| 587 | .probe = ps3disk_probe, | ||
| 588 | .remove = ps3disk_remove, | ||
| 589 | .shutdown = ps3disk_remove, | ||
| 590 | }; | ||
| 591 | |||
| 592 | |||
| 593 | static int __init ps3disk_init(void) | ||
| 594 | { | ||
| 595 | int error; | ||
| 596 | |||
| 597 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
| 598 | return -ENODEV; | ||
| 599 | |||
| 600 | error = register_blkdev(0, DEVICE_NAME); | ||
| 601 | if (error <= 0) { | ||
| 602 | printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__, | ||
| 603 | __LINE__, error); | ||
| 604 | return error; | ||
| 605 | } | ||
| 606 | ps3disk_major = error; | ||
| 607 | |||
| 608 | pr_info("%s:%u: registered block device major %d\n", __func__, | ||
| 609 | __LINE__, ps3disk_major); | ||
| 610 | |||
| 611 | error = ps3_system_bus_driver_register(&ps3disk); | ||
| 612 | if (error) | ||
| 613 | unregister_blkdev(ps3disk_major, DEVICE_NAME); | ||
| 614 | |||
| 615 | return error; | ||
| 616 | } | ||
| 617 | |||
| 618 | static void __exit ps3disk_exit(void) | ||
| 619 | { | ||
| 620 | ps3_system_bus_driver_unregister(&ps3disk); | ||
| 621 | unregister_blkdev(ps3disk_major, DEVICE_NAME); | ||
| 622 | } | ||
| 623 | |||
| 624 | module_init(ps3disk_init); | ||
| 625 | module_exit(ps3disk_exit); | ||
| 626 | |||
| 627 | MODULE_LICENSE("GPL"); | ||
| 628 | MODULE_DESCRIPTION("PS3 Disk Storage Driver"); | ||
| 629 | MODULE_AUTHOR("Sony Corporation"); | ||
| 630 | MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_DISK); | ||
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 4e6f387fd189..8fecaf4010b1 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
| @@ -107,6 +107,8 @@ obj-$(CONFIG_IPMI_HANDLER) += ipmi/ | |||
| 107 | obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o | 107 | obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o |
| 108 | obj-$(CONFIG_TCG_TPM) += tpm/ | 108 | obj-$(CONFIG_TCG_TPM) += tpm/ |
| 109 | 109 | ||
| 110 | obj-$(CONFIG_PS3_FLASH) += ps3flash.o | ||
| 111 | |||
| 110 | # Files generated that shall be removed upon make clean | 112 | # Files generated that shall be removed upon make clean |
| 111 | clean-files := consolemap_deftbl.c defkeymap.c | 113 | clean-files := consolemap_deftbl.c defkeymap.c |
| 112 | 114 | ||
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index b37f1d5a5be6..a08f8f981c11 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c | |||
| @@ -472,7 +472,7 @@ static void hvc_handle_event(struct HvLpEvent *event) | |||
| 472 | } | 472 | } |
| 473 | } | 473 | } |
| 474 | 474 | ||
| 475 | static int send_open(HvLpIndex remoteLp, void *sem) | 475 | static int __init send_open(HvLpIndex remoteLp, void *sem) |
| 476 | { | 476 | { |
| 477 | return HvCallEvent_signalLpEventFast(remoteLp, | 477 | return HvCallEvent_signalLpEventFast(remoteLp, |
| 478 | HvLpEvent_Type_VirtualIo, | 478 | HvLpEvent_Type_VirtualIo, |
| @@ -484,7 +484,7 @@ static int send_open(HvLpIndex remoteLp, void *sem) | |||
| 484 | 0, 0, 0, 0); | 484 | 0, 0, 0, 0); |
| 485 | } | 485 | } |
| 486 | 486 | ||
| 487 | static int hvc_vio_init(void) | 487 | static int __init hvc_vio_init(void) |
| 488 | { | 488 | { |
| 489 | atomic_t wait_flag; | 489 | atomic_t wait_flag; |
| 490 | int rc; | 490 | int rc; |
| @@ -552,14 +552,14 @@ static int hvc_vio_init(void) | |||
| 552 | } | 552 | } |
| 553 | module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ | 553 | module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ |
| 554 | 554 | ||
| 555 | static void hvc_vio_exit(void) | 555 | static void __exit hvc_vio_exit(void) |
| 556 | { | 556 | { |
| 557 | vio_unregister_driver(&hvc_vio_driver); | 557 | vio_unregister_driver(&hvc_vio_driver); |
| 558 | } | 558 | } |
| 559 | module_exit(hvc_vio_exit); | 559 | module_exit(hvc_vio_exit); |
| 560 | 560 | ||
| 561 | /* the device tree order defines our numbering */ | 561 | /* the device tree order defines our numbering */ |
| 562 | static int hvc_find_vtys(void) | 562 | static int __init hvc_find_vtys(void) |
| 563 | { | 563 | { |
| 564 | struct device_node *vty; | 564 | struct device_node *vty; |
| 565 | int num_found = 0; | 565 | int num_found = 0; |
diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c index 4b97eaf18602..bb09413d5a21 100644 --- a/drivers/char/hvc_rtas.c +++ b/drivers/char/hvc_rtas.c | |||
| @@ -115,7 +115,7 @@ static void __exit hvc_rtas_exit(void) | |||
| 115 | module_exit(hvc_rtas_exit); | 115 | module_exit(hvc_rtas_exit); |
| 116 | 116 | ||
| 117 | /* This will happen prior to module init. There is no tty at this time? */ | 117 | /* This will happen prior to module init. There is no tty at this time? */ |
| 118 | static int hvc_rtas_console_init(void) | 118 | static int __init hvc_rtas_console_init(void) |
| 119 | { | 119 | { |
| 120 | rtascons_put_char_token = rtas_token("put-term-char"); | 120 | rtascons_put_char_token = rtas_token("put-term-char"); |
| 121 | if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) | 121 | if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) |
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 17f96e04266f..69d8866de783 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
| @@ -210,9 +210,9 @@ static struct ktermios hvcs_tty_termios = { | |||
| 210 | static int hvcs_parm_num_devs = -1; | 210 | static int hvcs_parm_num_devs = -1; |
| 211 | module_param(hvcs_parm_num_devs, int, 0); | 211 | module_param(hvcs_parm_num_devs, int, 0); |
| 212 | 212 | ||
| 213 | char hvcs_driver_name[] = "hvcs"; | 213 | static const char hvcs_driver_name[] = "hvcs"; |
| 214 | char hvcs_device_node[] = "hvcs"; | 214 | static const char hvcs_device_node[] = "hvcs"; |
| 215 | char hvcs_driver_string[] | 215 | static const char hvcs_driver_string[] |
| 216 | = "IBM hvcs (Hypervisor Virtual Console Server) Driver"; | 216 | = "IBM hvcs (Hypervisor Virtual Console Server) Driver"; |
| 217 | 217 | ||
| 218 | /* Status of partner info rescan triggered via sysfs. */ | 218 | /* Status of partner info rescan triggered via sysfs. */ |
| @@ -1092,7 +1092,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, | |||
| 1092 | * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when | 1092 | * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when |
| 1093 | * calling this function or you will get deadlock. | 1093 | * calling this function or you will get deadlock. |
| 1094 | */ | 1094 | */ |
| 1095 | struct hvcs_struct *hvcs_get_by_index(int index) | 1095 | static struct hvcs_struct *hvcs_get_by_index(int index) |
| 1096 | { | 1096 | { |
| 1097 | struct hvcs_struct *hvcsd = NULL; | 1097 | struct hvcs_struct *hvcsd = NULL; |
| 1098 | unsigned long flags; | 1098 | unsigned long flags; |
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 7cda04b33534..2d7cd486e025 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
| @@ -41,7 +41,7 @@ config HW_RANDOM_AMD | |||
| 41 | 41 | ||
| 42 | config HW_RANDOM_GEODE | 42 | config HW_RANDOM_GEODE |
| 43 | tristate "AMD Geode HW Random Number Generator support" | 43 | tristate "AMD Geode HW Random Number Generator support" |
| 44 | depends on HW_RANDOM && X86 && PCI | 44 | depends on HW_RANDOM && X86_32 && PCI |
| 45 | default HW_RANDOM | 45 | default HW_RANDOM |
| 46 | ---help--- | 46 | ---help--- |
| 47 | This driver provides kernel-side support for the Random Number | 47 | This driver provides kernel-side support for the Random Number |
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c new file mode 100644 index 000000000000..79b6f461be75 --- /dev/null +++ b/drivers/char/ps3flash.c | |||
| @@ -0,0 +1,440 @@ | |||
| 1 | /* | ||
| 2 | * PS3 FLASH ROM Storage Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published | ||
| 9 | * by the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but | ||
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/fs.h> | ||
| 22 | #include <linux/miscdevice.h> | ||
| 23 | #include <linux/uaccess.h> | ||
| 24 | |||
| 25 | #include <asm/lv1call.h> | ||
| 26 | #include <asm/ps3stor.h> | ||
| 27 | |||
| 28 | |||
| 29 | #define DEVICE_NAME "ps3flash" | ||
| 30 | |||
| 31 | #define FLASH_BLOCK_SIZE (256*1024) | ||
| 32 | |||
| 33 | |||
| 34 | struct ps3flash_private { | ||
| 35 | struct mutex mutex; /* Bounce buffer mutex */ | ||
| 36 | }; | ||
| 37 | |||
| 38 | static struct ps3_storage_device *ps3flash_dev; | ||
| 39 | |||
| 40 | static ssize_t ps3flash_read_write_sectors(struct ps3_storage_device *dev, | ||
| 41 | u64 lpar, u64 start_sector, | ||
| 42 | u64 sectors, int write) | ||
| 43 | { | ||
| 44 | u64 res = ps3stor_read_write_sectors(dev, lpar, start_sector, sectors, | ||
| 45 | write); | ||
| 46 | if (res) { | ||
| 47 | dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__, | ||
| 48 | __LINE__, write ? "write" : "read", res); | ||
| 49 | return -EIO; | ||
| 50 | } | ||
| 51 | return sectors; | ||
| 52 | } | ||
| 53 | |||
| 54 | static ssize_t ps3flash_read_sectors(struct ps3_storage_device *dev, | ||
| 55 | u64 start_sector, u64 sectors, | ||
| 56 | unsigned int sector_offset) | ||
| 57 | { | ||
| 58 | u64 max_sectors, lpar; | ||
| 59 | |||
| 60 | max_sectors = dev->bounce_size / dev->blk_size; | ||
| 61 | if (sectors > max_sectors) { | ||
| 62 | dev_dbg(&dev->sbd.core, "%s:%u Limiting sectors to %lu\n", | ||
| 63 | __func__, __LINE__, max_sectors); | ||
| 64 | sectors = max_sectors; | ||
| 65 | } | ||
| 66 | |||
| 67 | lpar = dev->bounce_lpar + sector_offset * dev->blk_size; | ||
| 68 | return ps3flash_read_write_sectors(dev, lpar, start_sector, sectors, | ||
| 69 | 0); | ||
| 70 | } | ||
| 71 | |||
| 72 | static ssize_t ps3flash_write_chunk(struct ps3_storage_device *dev, | ||
| 73 | u64 start_sector) | ||
| 74 | { | ||
| 75 | u64 sectors = dev->bounce_size / dev->blk_size; | ||
| 76 | return ps3flash_read_write_sectors(dev, dev->bounce_lpar, start_sector, | ||
| 77 | sectors, 1); | ||
| 78 | } | ||
| 79 | |||
| 80 | static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin) | ||
| 81 | { | ||
| 82 | struct ps3_storage_device *dev = ps3flash_dev; | ||
| 83 | loff_t res; | ||
| 84 | |||
| 85 | mutex_lock(&file->f_mapping->host->i_mutex); | ||
| 86 | switch (origin) { | ||
| 87 | case 1: | ||
| 88 | offset += file->f_pos; | ||
| 89 | break; | ||
| 90 | case 2: | ||
| 91 | offset += dev->regions[dev->region_idx].size*dev->blk_size; | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | if (offset < 0) { | ||
| 95 | res = -EINVAL; | ||
| 96 | goto out; | ||
| 97 | } | ||
| 98 | |||
| 99 | file->f_pos = offset; | ||
| 100 | res = file->f_pos; | ||
| 101 | |||
| 102 | out: | ||
| 103 | mutex_unlock(&file->f_mapping->host->i_mutex); | ||
| 104 | return res; | ||
| 105 | } | ||
| 106 | |||
| 107 | static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count, | ||
| 108 | loff_t *pos) | ||
| 109 | { | ||
| 110 | struct ps3_storage_device *dev = ps3flash_dev; | ||
| 111 | struct ps3flash_private *priv = dev->sbd.core.driver_data; | ||
| 112 | u64 size, start_sector, end_sector, offset; | ||
| 113 | ssize_t sectors_read; | ||
| 114 | size_t remaining, n; | ||
| 115 | |||
| 116 | dev_dbg(&dev->sbd.core, | ||
| 117 | "%s:%u: Reading %zu bytes at position %lld to user 0x%p\n", | ||
| 118 | __func__, __LINE__, count, *pos, buf); | ||
| 119 | |||
| 120 | size = dev->regions[dev->region_idx].size*dev->blk_size; | ||
| 121 | if (*pos >= size || !count) | ||
| 122 | return 0; | ||
| 123 | |||
| 124 | if (*pos + count > size) { | ||
| 125 | dev_dbg(&dev->sbd.core, | ||
| 126 | "%s:%u Truncating count from %zu to %llu\n", __func__, | ||
| 127 | __LINE__, count, size - *pos); | ||
| 128 | count = size - *pos; | ||
| 129 | } | ||
| 130 | |||
| 131 | start_sector = *pos / dev->blk_size; | ||
| 132 | offset = *pos % dev->blk_size; | ||
| 133 | end_sector = DIV_ROUND_UP(*pos + count, dev->blk_size); | ||
| 134 | |||
| 135 | remaining = count; | ||
| 136 | do { | ||
| 137 | mutex_lock(&priv->mutex); | ||
| 138 | |||
| 139 | sectors_read = ps3flash_read_sectors(dev, start_sector, | ||
| 140 | end_sector-start_sector, | ||
| 141 | 0); | ||
| 142 | if (sectors_read < 0) { | ||
| 143 | mutex_unlock(&priv->mutex); | ||
| 144 | goto fail; | ||
| 145 | } | ||
| 146 | |||
| 147 | n = min(remaining, sectors_read*dev->blk_size-offset); | ||
| 148 | dev_dbg(&dev->sbd.core, | ||
| 149 | "%s:%u: copy %lu bytes from 0x%p to user 0x%p\n", | ||
| 150 | __func__, __LINE__, n, dev->bounce_buf+offset, buf); | ||
| 151 | if (copy_to_user(buf, dev->bounce_buf+offset, n)) { | ||
| 152 | mutex_unlock(&priv->mutex); | ||
| 153 | sectors_read = -EFAULT; | ||
| 154 | goto fail; | ||
| 155 | } | ||
| 156 | |||
| 157 | mutex_unlock(&priv->mutex); | ||
| 158 | |||
| 159 | *pos += n; | ||
| 160 | buf += n; | ||
| 161 | remaining -= n; | ||
| 162 | start_sector += sectors_read; | ||
| 163 | offset = 0; | ||
| 164 | } while (remaining > 0); | ||
| 165 | |||
| 166 | return count; | ||
| 167 | |||
| 168 | fail: | ||
| 169 | return sectors_read; | ||
| 170 | } | ||
| 171 | |||
| 172 | static ssize_t ps3flash_write(struct file *file, const char __user *buf, | ||
| 173 | size_t count, loff_t *pos) | ||
| 174 | { | ||
| 175 | struct ps3_storage_device *dev = ps3flash_dev; | ||
| 176 | struct ps3flash_private *priv = dev->sbd.core.driver_data; | ||
| 177 | u64 size, chunk_sectors, start_write_sector, end_write_sector, | ||
| 178 | end_read_sector, start_read_sector, head, tail, offset; | ||
| 179 | ssize_t res; | ||
| 180 | size_t remaining, n; | ||
| 181 | unsigned int sec_off; | ||
| 182 | |||
| 183 | dev_dbg(&dev->sbd.core, | ||
| 184 | "%s:%u: Writing %zu bytes at position %lld from user 0x%p\n", | ||
| 185 | __func__, __LINE__, count, *pos, buf); | ||
| 186 | |||
| 187 | size = dev->regions[dev->region_idx].size*dev->blk_size; | ||
| 188 | if (*pos >= size || !count) | ||
| 189 | return 0; | ||
| 190 | |||
| 191 | if (*pos + count > size) { | ||
| 192 | dev_dbg(&dev->sbd.core, | ||
| 193 | "%s:%u Truncating count from %zu to %llu\n", __func__, | ||
| 194 | __LINE__, count, size - *pos); | ||
| 195 | count = size - *pos; | ||
| 196 | } | ||
| 197 | |||
| 198 | chunk_sectors = dev->bounce_size / dev->blk_size; | ||
| 199 | |||
| 200 | start_write_sector = *pos / dev->bounce_size * chunk_sectors; | ||
| 201 | offset = *pos % dev->bounce_size; | ||
| 202 | end_write_sector = DIV_ROUND_UP(*pos + count, dev->bounce_size) * | ||
| 203 | chunk_sectors; | ||
| 204 | |||
| 205 | end_read_sector = DIV_ROUND_UP(*pos, dev->blk_size); | ||
| 206 | start_read_sector = (*pos + count) / dev->blk_size; | ||
| 207 | |||
| 208 | /* | ||
| 209 | * As we have to write in 256 KiB chunks, while we can read in blk_size | ||
| 210 | * (usually 512 bytes) chunks, we perform the following steps: | ||
| 211 | * 1. Read from start_write_sector to end_read_sector ("head") | ||
| 212 | * 2. Read from start_read_sector to end_write_sector ("tail") | ||
| 213 | * 3. Copy data to buffer | ||
| 214 | * 4. Write from start_write_sector to end_write_sector | ||
| 215 | * All of this is complicated by using only one 256 KiB bounce buffer. | ||
| 216 | */ | ||
| 217 | |||
| 218 | head = end_read_sector - start_write_sector; | ||
| 219 | tail = end_write_sector - start_read_sector; | ||
| 220 | |||
| 221 | remaining = count; | ||
| 222 | do { | ||
| 223 | mutex_lock(&priv->mutex); | ||
| 224 | |||
| 225 | if (end_read_sector >= start_read_sector) { | ||
| 226 | /* Merge head and tail */ | ||
| 227 | dev_dbg(&dev->sbd.core, | ||
| 228 | "Merged head and tail: %lu sectors at %lu\n", | ||
| 229 | chunk_sectors, start_write_sector); | ||
| 230 | res = ps3flash_read_sectors(dev, start_write_sector, | ||
| 231 | chunk_sectors, 0); | ||
| 232 | if (res < 0) | ||
| 233 | goto fail; | ||
| 234 | } else { | ||
| 235 | if (head) { | ||
| 236 | /* Read head */ | ||
| 237 | dev_dbg(&dev->sbd.core, | ||
| 238 | "head: %lu sectors at %lu\n", head, | ||
| 239 | start_write_sector); | ||
| 240 | res = ps3flash_read_sectors(dev, | ||
| 241 | start_write_sector, | ||
| 242 | head, 0); | ||
| 243 | if (res < 0) | ||
| 244 | goto fail; | ||
| 245 | } | ||
| 246 | if (start_read_sector < | ||
| 247 | start_write_sector+chunk_sectors) { | ||
| 248 | /* Read tail */ | ||
| 249 | dev_dbg(&dev->sbd.core, | ||
| 250 | "tail: %lu sectors at %lu\n", tail, | ||
| 251 | start_read_sector); | ||
| 252 | sec_off = start_read_sector-start_write_sector; | ||
| 253 | res = ps3flash_read_sectors(dev, | ||
| 254 | start_read_sector, | ||
| 255 | tail, sec_off); | ||
| 256 | if (res < 0) | ||
| 257 | goto fail; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | n = min(remaining, dev->bounce_size-offset); | ||
| 262 | dev_dbg(&dev->sbd.core, | ||
| 263 | "%s:%u: copy %lu bytes from user 0x%p to 0x%p\n", | ||
| 264 | __func__, __LINE__, n, buf, dev->bounce_buf+offset); | ||
| 265 | if (copy_from_user(dev->bounce_buf+offset, buf, n)) { | ||
| 266 | res = -EFAULT; | ||
| 267 | goto fail; | ||
| 268 | } | ||
| 269 | |||
| 270 | res = ps3flash_write_chunk(dev, start_write_sector); | ||
| 271 | if (res < 0) | ||
| 272 | goto fail; | ||
| 273 | |||
| 274 | mutex_unlock(&priv->mutex); | ||
| 275 | |||
| 276 | *pos += n; | ||
| 277 | buf += n; | ||
| 278 | remaining -= n; | ||
| 279 | start_write_sector += chunk_sectors; | ||
| 280 | head = 0; | ||
| 281 | offset = 0; | ||
| 282 | } while (remaining > 0); | ||
| 283 | |||
| 284 | return count; | ||
| 285 | |||
| 286 | fail: | ||
| 287 | mutex_unlock(&priv->mutex); | ||
| 288 | return res; | ||
| 289 | } | ||
| 290 | |||
| 291 | |||
| 292 | static irqreturn_t ps3flash_interrupt(int irq, void *data) | ||
| 293 | { | ||
| 294 | struct ps3_storage_device *dev = data; | ||
| 295 | int res; | ||
| 296 | u64 tag, status; | ||
| 297 | |||
| 298 | res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status); | ||
| 299 | |||
| 300 | if (tag != dev->tag) | ||
| 301 | dev_err(&dev->sbd.core, | ||
| 302 | "%s:%u: tag mismatch, got %lx, expected %lx\n", | ||
| 303 | __func__, __LINE__, tag, dev->tag); | ||
| 304 | |||
| 305 | if (res) { | ||
| 306 | dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n", | ||
| 307 | __func__, __LINE__, res, status); | ||
| 308 | } else { | ||
| 309 | dev->lv1_status = status; | ||
| 310 | complete(&dev->done); | ||
| 311 | } | ||
| 312 | return IRQ_HANDLED; | ||
| 313 | } | ||
| 314 | |||
| 315 | |||
| 316 | static const struct file_operations ps3flash_fops = { | ||
| 317 | .owner = THIS_MODULE, | ||
| 318 | .llseek = ps3flash_llseek, | ||
| 319 | .read = ps3flash_read, | ||
| 320 | .write = ps3flash_write, | ||
| 321 | }; | ||
| 322 | |||
| 323 | static struct miscdevice ps3flash_misc = { | ||
| 324 | .minor = MISC_DYNAMIC_MINOR, | ||
| 325 | .name = DEVICE_NAME, | ||
| 326 | .fops = &ps3flash_fops, | ||
| 327 | }; | ||
| 328 | |||
| 329 | static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev) | ||
| 330 | { | ||
| 331 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); | ||
| 332 | struct ps3flash_private *priv; | ||
| 333 | int error; | ||
| 334 | unsigned long tmp; | ||
| 335 | |||
| 336 | tmp = dev->regions[dev->region_idx].start*dev->blk_size; | ||
| 337 | if (tmp % FLASH_BLOCK_SIZE) { | ||
| 338 | dev_err(&dev->sbd.core, | ||
| 339 | "%s:%u region start %lu is not aligned\n", __func__, | ||
| 340 | __LINE__, tmp); | ||
| 341 | return -EINVAL; | ||
| 342 | } | ||
| 343 | tmp = dev->regions[dev->region_idx].size*dev->blk_size; | ||
| 344 | if (tmp % FLASH_BLOCK_SIZE) { | ||
| 345 | dev_err(&dev->sbd.core, | ||
| 346 | "%s:%u region size %lu is not aligned\n", __func__, | ||
| 347 | __LINE__, tmp); | ||
| 348 | return -EINVAL; | ||
| 349 | } | ||
| 350 | |||
| 351 | /* use static buffer, kmalloc cannot allocate 256 KiB */ | ||
| 352 | if (!ps3flash_bounce_buffer.address) | ||
| 353 | return -ENODEV; | ||
| 354 | |||
| 355 | if (ps3flash_dev) { | ||
| 356 | dev_err(&dev->sbd.core, | ||
| 357 | "Only one FLASH device is supported\n"); | ||
| 358 | return -EBUSY; | ||
| 359 | } | ||
| 360 | |||
| 361 | ps3flash_dev = dev; | ||
| 362 | |||
| 363 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 364 | if (!priv) { | ||
| 365 | error = -ENOMEM; | ||
| 366 | goto fail; | ||
| 367 | } | ||
| 368 | |||
| 369 | dev->sbd.core.driver_data = priv; | ||
| 370 | mutex_init(&priv->mutex); | ||
| 371 | |||
| 372 | dev->bounce_size = ps3flash_bounce_buffer.size; | ||
| 373 | dev->bounce_buf = ps3flash_bounce_buffer.address; | ||
| 374 | |||
| 375 | error = ps3stor_setup(dev, ps3flash_interrupt); | ||
| 376 | if (error) | ||
| 377 | goto fail_free_priv; | ||
| 378 | |||
| 379 | ps3flash_misc.parent = &dev->sbd.core; | ||
| 380 | error = misc_register(&ps3flash_misc); | ||
| 381 | if (error) { | ||
| 382 | dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n", | ||
| 383 | __func__, __LINE__, error); | ||
| 384 | goto fail_teardown; | ||
| 385 | } | ||
| 386 | |||
| 387 | dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n", | ||
| 388 | __func__, __LINE__, ps3flash_misc.minor); | ||
| 389 | return 0; | ||
| 390 | |||
| 391 | fail_teardown: | ||
| 392 | ps3stor_teardown(dev); | ||
| 393 | fail_free_priv: | ||
| 394 | kfree(priv); | ||
| 395 | dev->sbd.core.driver_data = NULL; | ||
| 396 | fail: | ||
| 397 | ps3flash_dev = NULL; | ||
| 398 | return error; | ||
| 399 | } | ||
| 400 | |||
| 401 | static int ps3flash_remove(struct ps3_system_bus_device *_dev) | ||
| 402 | { | ||
| 403 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); | ||
| 404 | |||
| 405 | misc_deregister(&ps3flash_misc); | ||
| 406 | ps3stor_teardown(dev); | ||
| 407 | kfree(dev->sbd.core.driver_data); | ||
| 408 | dev->sbd.core.driver_data = NULL; | ||
| 409 | ps3flash_dev = NULL; | ||
| 410 | return 0; | ||
| 411 | } | ||
| 412 | |||
| 413 | |||
| 414 | static struct ps3_system_bus_driver ps3flash = { | ||
| 415 | .match_id = PS3_MATCH_ID_STOR_FLASH, | ||
| 416 | .core.name = DEVICE_NAME, | ||
| 417 | .core.owner = THIS_MODULE, | ||
| 418 | .probe = ps3flash_probe, | ||
| 419 | .remove = ps3flash_remove, | ||
| 420 | .shutdown = ps3flash_remove, | ||
| 421 | }; | ||
| 422 | |||
| 423 | |||
| 424 | static int __init ps3flash_init(void) | ||
| 425 | { | ||
| 426 | return ps3_system_bus_driver_register(&ps3flash); | ||
| 427 | } | ||
| 428 | |||
| 429 | static void __exit ps3flash_exit(void) | ||
| 430 | { | ||
| 431 | ps3_system_bus_driver_unregister(&ps3flash); | ||
| 432 | } | ||
| 433 | |||
| 434 | module_init(ps3flash_init); | ||
| 435 | module_exit(ps3flash_exit); | ||
| 436 | |||
| 437 | MODULE_LICENSE("GPL"); | ||
| 438 | MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver"); | ||
| 439 | MODULE_AUTHOR("Sony Corporation"); | ||
| 440 | MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH); | ||
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 30c3f54c7666..ec6b65ec69ea 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
| @@ -82,7 +82,7 @@ | |||
| 82 | #include <asm/uaccess.h> | 82 | #include <asm/uaccess.h> |
| 83 | #include <asm/system.h> | 83 | #include <asm/system.h> |
| 84 | 84 | ||
| 85 | #if defined(__i386__) | 85 | #ifdef CONFIG_X86 |
| 86 | #include <asm/hpet.h> | 86 | #include <asm/hpet.h> |
| 87 | #endif | 87 | #endif |
| 88 | 88 | ||
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index ad5cc5f6862f..16fb23125e96 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
| @@ -187,6 +187,22 @@ config PNX4008_WATCHDOG | |||
| 187 | 187 | ||
| 188 | Say N if you are unsure. | 188 | Say N if you are unsure. |
| 189 | 189 | ||
| 190 | config IOP_WATCHDOG | ||
| 191 | tristate "IOP Watchdog" | ||
| 192 | depends on WATCHDOG && PLAT_IOP | ||
| 193 | select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X) | ||
| 194 | help | ||
| 195 | Say Y here if to include support for the watchdog timer | ||
| 196 | in the Intel IOP3XX & IOP13XX I/O Processors. This driver can | ||
| 197 | be built as a module by choosing M. The module will | ||
| 198 | be called iop_wdt. | ||
| 199 | |||
| 200 | Note: The IOP13XX watchdog does an Internal Bus Reset which will | ||
| 201 | affect both cores and the peripherals of the IOP. The ATU-X | ||
| 202 | and/or ATUe configuration registers will remain intact, but if | ||
| 203 | operating as an Root Complex and/or Central Resource, the PCI-X | ||
| 204 | and/or PCIe busses will also be reset. THIS IS A VERY BIG HAMMER. | ||
| 205 | |||
| 190 | # AVR32 Architecture | 206 | # AVR32 Architecture |
| 191 | 207 | ||
| 192 | config AT32AP700X_WDT | 208 | config AT32AP700X_WDT |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 3907ec04a4e5..bdb9d5e3bb41 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
| @@ -35,6 +35,7 @@ obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o | |||
| 35 | obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o | 35 | obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o |
| 36 | obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o | 36 | obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o |
| 37 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o | 37 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o |
| 38 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o | ||
| 38 | 39 | ||
| 39 | # AVR32 Architecture | 40 | # AVR32 Architecture |
| 40 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o | 41 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o |
diff --git a/drivers/char/watchdog/iop_wdt.c b/drivers/char/watchdog/iop_wdt.c new file mode 100644 index 000000000000..bbbd91af754d --- /dev/null +++ b/drivers/char/watchdog/iop_wdt.c | |||
| @@ -0,0 +1,262 @@ | |||
| 1 | /* | ||
| 2 | * drivers/char/watchdog/iop_wdt.c | ||
| 3 | * | ||
| 4 | * WDT driver for Intel I/O Processors | ||
| 5 | * Copyright (C) 2005, Intel Corporation. | ||
| 6 | * | ||
| 7 | * Based on ixp4xx driver, Copyright 2004 (c) MontaVista, Software, Inc. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms and conditions of the GNU General Public License, | ||
| 11 | * version 2, as published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 16 | * more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along with | ||
| 19 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
| 20 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
| 21 | * | ||
| 22 | * Curt E Bruns <curt.e.bruns@intel.com> | ||
| 23 | * Peter Milne <peter.milne@d-tacq.com> | ||
| 24 | * Dan Williams <dan.j.williams@intel.com> | ||
| 25 | */ | ||
| 26 | |||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/kernel.h> | ||
| 29 | #include <linux/fs.h> | ||
| 30 | #include <linux/init.h> | ||
| 31 | #include <linux/device.h> | ||
| 32 | #include <linux/miscdevice.h> | ||
| 33 | #include <linux/watchdog.h> | ||
| 34 | #include <linux/uaccess.h> | ||
| 35 | #include <asm/hardware.h> | ||
| 36 | |||
| 37 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
| 38 | static unsigned long wdt_status; | ||
| 39 | static unsigned long boot_status; | ||
| 40 | |||
| 41 | #define WDT_IN_USE 0 | ||
| 42 | #define WDT_OK_TO_CLOSE 1 | ||
| 43 | #define WDT_ENABLED 2 | ||
| 44 | |||
| 45 | static unsigned long iop_watchdog_timeout(void) | ||
| 46 | { | ||
| 47 | return (0xffffffffUL / get_iop_tick_rate()); | ||
| 48 | } | ||
| 49 | |||
| 50 | /** | ||
| 51 | * wdt_supports_disable - determine if we are accessing a iop13xx watchdog | ||
| 52 | * or iop3xx by whether it has a disable command | ||
| 53 | */ | ||
| 54 | static int wdt_supports_disable(void) | ||
| 55 | { | ||
| 56 | int can_disable; | ||
| 57 | |||
| 58 | if (IOP_WDTCR_EN_ARM != IOP_WDTCR_DIS_ARM) | ||
| 59 | can_disable = 1; | ||
| 60 | else | ||
| 61 | can_disable = 0; | ||
| 62 | |||
| 63 | return can_disable; | ||
| 64 | } | ||
| 65 | |||
| 66 | static void wdt_enable(void) | ||
| 67 | { | ||
| 68 | /* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF | ||
| 69 | * Takes approx. 10.7s to timeout | ||
| 70 | */ | ||
| 71 | write_wdtcr(IOP_WDTCR_EN_ARM); | ||
| 72 | write_wdtcr(IOP_WDTCR_EN); | ||
| 73 | } | ||
| 74 | |||
| 75 | /* returns 0 if the timer was successfully disabled */ | ||
| 76 | static int wdt_disable(void) | ||
| 77 | { | ||
| 78 | /* Stop Counting */ | ||
| 79 | if (wdt_supports_disable()) { | ||
| 80 | write_wdtcr(IOP_WDTCR_DIS_ARM); | ||
| 81 | write_wdtcr(IOP_WDTCR_DIS); | ||
| 82 | clear_bit(WDT_ENABLED, &wdt_status); | ||
| 83 | printk(KERN_INFO "WATCHDOG: Disabled\n"); | ||
| 84 | return 0; | ||
| 85 | } else | ||
| 86 | return 1; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int iop_wdt_open(struct inode *inode, struct file *file) | ||
| 90 | { | ||
| 91 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | ||
| 92 | return -EBUSY; | ||
| 93 | |||
| 94 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
| 95 | |||
| 96 | wdt_enable(); | ||
| 97 | |||
| 98 | set_bit(WDT_ENABLED, &wdt_status); | ||
| 99 | |||
| 100 | return nonseekable_open(inode, file); | ||
| 101 | } | ||
| 102 | |||
| 103 | static ssize_t | ||
| 104 | iop_wdt_write(struct file *file, const char *data, size_t len, | ||
| 105 | loff_t *ppos) | ||
| 106 | { | ||
| 107 | if (len) { | ||
| 108 | if (!nowayout) { | ||
| 109 | size_t i; | ||
| 110 | |||
| 111 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
| 112 | |||
| 113 | for (i = 0; i != len; i++) { | ||
| 114 | char c; | ||
| 115 | |||
| 116 | if (get_user(c, data + i)) | ||
| 117 | return -EFAULT; | ||
| 118 | if (c == 'V') | ||
| 119 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | wdt_enable(); | ||
| 123 | } | ||
| 124 | |||
| 125 | return len; | ||
| 126 | } | ||
| 127 | |||
| 128 | static struct watchdog_info ident = { | ||
| 129 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | ||
| 130 | .identity = "iop watchdog", | ||
| 131 | }; | ||
| 132 | |||
| 133 | static int | ||
| 134 | iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
| 135 | unsigned long arg) | ||
| 136 | { | ||
| 137 | int options; | ||
| 138 | int ret = -ENOTTY; | ||
| 139 | |||
| 140 | switch (cmd) { | ||
| 141 | case WDIOC_GETSUPPORT: | ||
| 142 | if (copy_to_user | ||
| 143 | ((struct watchdog_info *)arg, &ident, sizeof ident)) | ||
| 144 | ret = -EFAULT; | ||
| 145 | else | ||
| 146 | ret = 0; | ||
| 147 | break; | ||
| 148 | |||
| 149 | case WDIOC_GETSTATUS: | ||
| 150 | ret = put_user(0, (int *)arg); | ||
| 151 | break; | ||
| 152 | |||
| 153 | case WDIOC_GETBOOTSTATUS: | ||
| 154 | ret = put_user(boot_status, (int *)arg); | ||
| 155 | break; | ||
| 156 | |||
| 157 | case WDIOC_GETTIMEOUT: | ||
| 158 | ret = put_user(iop_watchdog_timeout(), (int *)arg); | ||
| 159 | break; | ||
| 160 | |||
| 161 | case WDIOC_KEEPALIVE: | ||
| 162 | wdt_enable(); | ||
| 163 | ret = 0; | ||
| 164 | break; | ||
| 165 | |||
| 166 | case WDIOC_SETOPTIONS: | ||
| 167 | if (get_user(options, (int *)arg)) | ||
| 168 | return -EFAULT; | ||
| 169 | |||
| 170 | if (options & WDIOS_DISABLECARD) { | ||
| 171 | if (!nowayout) { | ||
| 172 | if (wdt_disable() == 0) { | ||
| 173 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
| 174 | ret = 0; | ||
| 175 | } else | ||
| 176 | ret = -ENXIO; | ||
| 177 | } else | ||
| 178 | ret = 0; | ||
| 179 | } | ||
| 180 | |||
| 181 | if (options & WDIOS_ENABLECARD) { | ||
| 182 | wdt_enable(); | ||
| 183 | ret = 0; | ||
| 184 | } | ||
| 185 | break; | ||
| 186 | } | ||
| 187 | |||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | static int iop_wdt_release(struct inode *inode, struct file *file) | ||
| 192 | { | ||
| 193 | int state = 1; | ||
| 194 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | ||
| 195 | if (test_bit(WDT_ENABLED, &wdt_status)) | ||
| 196 | state = wdt_disable(); | ||
| 197 | |||
| 198 | /* if the timer is not disbaled reload and notify that we are still | ||
| 199 | * going down | ||
| 200 | */ | ||
| 201 | if (state != 0) { | ||
| 202 | wdt_enable(); | ||
| 203 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | ||
| 204 | "reset in %lu seconds\n", iop_watchdog_timeout()); | ||
| 205 | } | ||
| 206 | |||
| 207 | clear_bit(WDT_IN_USE, &wdt_status); | ||
| 208 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
| 209 | |||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | static const struct file_operations iop_wdt_fops = { | ||
| 214 | .owner = THIS_MODULE, | ||
| 215 | .llseek = no_llseek, | ||
| 216 | .write = iop_wdt_write, | ||
| 217 | .ioctl = iop_wdt_ioctl, | ||
| 218 | .open = iop_wdt_open, | ||
| 219 | .release = iop_wdt_release, | ||
| 220 | }; | ||
| 221 | |||
| 222 | static struct miscdevice iop_wdt_miscdev = { | ||
| 223 | .minor = WATCHDOG_MINOR, | ||
| 224 | .name = "watchdog", | ||
| 225 | .fops = &iop_wdt_fops, | ||
| 226 | }; | ||
| 227 | |||
| 228 | static int __init iop_wdt_init(void) | ||
| 229 | { | ||
| 230 | int ret; | ||
| 231 | |||
| 232 | ret = misc_register(&iop_wdt_miscdev); | ||
| 233 | if (ret == 0) | ||
| 234 | printk("iop watchdog timer: timeout %lu sec\n", | ||
| 235 | iop_watchdog_timeout()); | ||
| 236 | |||
| 237 | /* check if the reset was caused by the watchdog timer */ | ||
| 238 | boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0; | ||
| 239 | |||
| 240 | /* Configure Watchdog Timeout to cause an Internal Bus (IB) Reset | ||
| 241 | * NOTE: An IB Reset will Reset both cores in the IOP342 | ||
| 242 | */ | ||
| 243 | write_wdtsr(IOP13XX_WDTCR_IB_RESET); | ||
| 244 | |||
| 245 | return ret; | ||
| 246 | } | ||
| 247 | |||
| 248 | static void __exit iop_wdt_exit(void) | ||
| 249 | { | ||
| 250 | misc_deregister(&iop_wdt_miscdev); | ||
| 251 | } | ||
| 252 | |||
| 253 | module_init(iop_wdt_init); | ||
| 254 | module_exit(iop_wdt_exit); | ||
| 255 | |||
| 256 | module_param(nowayout, int, 0); | ||
| 257 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
| 258 | |||
| 259 | MODULE_AUTHOR("Curt E Bruns <curt.e.bruns@intel.com>"); | ||
| 260 | MODULE_DESCRIPTION("iop watchdog timer driver"); | ||
| 261 | MODULE_LICENSE("GPL"); | ||
| 262 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index e783dbf0f162..7b46faf22318 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c | |||
| @@ -71,7 +71,7 @@ static struct clocksource clocksource_acpi_pm = { | |||
| 71 | .rating = 200, | 71 | .rating = 200, |
| 72 | .read = acpi_pm_read, | 72 | .read = acpi_pm_read, |
| 73 | .mask = (cycle_t)ACPI_PM_MASK, | 73 | .mask = (cycle_t)ACPI_PM_MASK, |
| 74 | .mult = 0, /*to be caluclated*/ | 74 | .mult = 0, /*to be calculated*/ |
| 75 | .shift = 22, | 75 | .shift = 22, |
| 76 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 76 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
| 77 | 77 | ||
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index fc984474162c..3e4a369d0057 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c | |||
| @@ -1160,7 +1160,7 @@ static struct device_attribute *sbp2_scsi_sysfs_attrs[] = { | |||
| 1160 | static struct scsi_host_template scsi_driver_template = { | 1160 | static struct scsi_host_template scsi_driver_template = { |
| 1161 | .module = THIS_MODULE, | 1161 | .module = THIS_MODULE, |
| 1162 | .name = "SBP-2 IEEE-1394", | 1162 | .name = "SBP-2 IEEE-1394", |
| 1163 | .proc_name = (char *)sbp2_driver_name, | 1163 | .proc_name = sbp2_driver_name, |
| 1164 | .queuecommand = sbp2_scsi_queuecommand, | 1164 | .queuecommand = sbp2_scsi_queuecommand, |
| 1165 | .slave_alloc = sbp2_scsi_slave_alloc, | 1165 | .slave_alloc = sbp2_scsi_slave_alloc, |
| 1166 | .slave_configure = sbp2_scsi_slave_configure, | 1166 | .slave_configure = sbp2_scsi_slave_configure, |
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 31989dcd922c..906bf5e8de89 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
| @@ -24,7 +24,12 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
| 24 | MODULE_DESCRIPTION("PC Speaker beeper driver"); | 24 | MODULE_DESCRIPTION("PC Speaker beeper driver"); |
| 25 | MODULE_LICENSE("GPL"); | 25 | MODULE_LICENSE("GPL"); |
| 26 | 26 | ||
| 27 | static DEFINE_SPINLOCK(i8253_beep_lock); | 27 | #ifdef CONFIG_X86 |
| 28 | /* Use the global PIT lock ! */ | ||
| 29 | #include <asm/i8253.h> | ||
| 30 | #else | ||
| 31 | static DEFINE_SPINLOCK(i8253_lock); | ||
| 32 | #endif | ||
| 28 | 33 | ||
| 29 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 34 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
| 30 | { | 35 | { |
| @@ -43,7 +48,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
| 43 | if (value > 20 && value < 32767) | 48 | if (value > 20 && value < 32767) |
| 44 | count = PIT_TICK_RATE / value; | 49 | count = PIT_TICK_RATE / value; |
| 45 | 50 | ||
| 46 | spin_lock_irqsave(&i8253_beep_lock, flags); | 51 | spin_lock_irqsave(&i8253_lock, flags); |
| 47 | 52 | ||
| 48 | if (count) { | 53 | if (count) { |
| 49 | /* enable counter 2 */ | 54 | /* enable counter 2 */ |
| @@ -58,7 +63,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
| 58 | outb(inb_p(0x61) & 0xFC, 0x61); | 63 | outb(inb_p(0x61) & 0xFC, 0x61); |
| 59 | } | 64 | } |
| 60 | 65 | ||
| 61 | spin_unlock_irqrestore(&i8253_beep_lock, flags); | 66 | spin_unlock_irqrestore(&i8253_lock, flags); |
| 62 | 67 | ||
| 63 | return 0; | 68 | return 0; |
| 64 | } | 69 | } |
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig index cf906c8cee4d..66f946aa30b3 100644 --- a/drivers/isdn/Kconfig +++ b/drivers/isdn/Kconfig | |||
| @@ -21,9 +21,7 @@ menuconfig ISDN | |||
| 21 | 21 | ||
| 22 | if ISDN | 22 | if ISDN |
| 23 | 23 | ||
| 24 | menu "Old ISDN4Linux" | 24 | menuconfig ISDN_I4L |
| 25 | |||
| 26 | config ISDN_I4L | ||
| 27 | tristate "Old ISDN4Linux (deprecated)" | 25 | tristate "Old ISDN4Linux (deprecated)" |
| 28 | ---help--- | 26 | ---help--- |
| 29 | This driver allows you to use an ISDN adapter for networking | 27 | This driver allows you to use an ISDN adapter for networking |
| @@ -45,12 +43,8 @@ if ISDN_I4L | |||
| 45 | source "drivers/isdn/i4l/Kconfig" | 43 | source "drivers/isdn/i4l/Kconfig" |
| 46 | endif | 44 | endif |
| 47 | 45 | ||
| 48 | endmenu | 46 | menuconfig ISDN_CAPI |
| 49 | 47 | tristate "CAPI 2.0 subsystem" | |
| 50 | comment "CAPI subsystem" | ||
| 51 | |||
| 52 | config ISDN_CAPI | ||
| 53 | tristate "CAPI2.0 support" | ||
| 54 | help | 48 | help |
| 55 | This provides the CAPI (Common ISDN Application Programming | 49 | This provides the CAPI (Common ISDN Application Programming |
| 56 | Interface, a standard making it easy for programs to access ISDN | 50 | Interface, a standard making it easy for programs to access ISDN |
diff --git a/drivers/isdn/act2000/Kconfig b/drivers/isdn/act2000/Kconfig index 78e6ad8d57c5..3fc1a5434ef7 100644 --- a/drivers/isdn/act2000/Kconfig +++ b/drivers/isdn/act2000/Kconfig | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | config ISDN_DRV_ACT2000 | 4 | config ISDN_DRV_ACT2000 |
| 5 | tristate "IBM Active 2000 support" | 5 | tristate "IBM Active 2000 support" |
| 6 | depends on ISDN_I4L && ISA | 6 | depends on ISA |
| 7 | help | 7 | help |
| 8 | Say Y here if you have an IBM Active 2000 ISDN card. In order to use | 8 | Say Y here if you have an IBM Active 2000 ISDN card. In order to use |
| 9 | this card, additional firmware is necessary, which has to be loaded | 9 | this card, additional firmware is necessary, which has to be loaded |
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index bcbb6502a773..0017e50c6948 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig | |||
| @@ -1,9 +1,5 @@ | |||
| 1 | menu "Siemens Gigaset" | 1 | menuconfig ISDN_DRV_GIGASET |
| 2 | depends on ISDN_I4L | ||
| 3 | |||
| 4 | config ISDN_DRV_GIGASET | ||
| 5 | tristate "Siemens Gigaset support (isdn)" | 2 | tristate "Siemens Gigaset support (isdn)" |
| 6 | depends on ISDN_I4L | ||
| 7 | select CRC_CCITT | 3 | select CRC_CCITT |
| 8 | select BITREVERSE | 4 | select BITREVERSE |
| 9 | help | 5 | help |
| @@ -55,6 +51,4 @@ config GIGASET_UNDOCREQ | |||
| 55 | features like configuration mode of M105, say yes. If you | 51 | features like configuration mode of M105, say yes. If you |
| 56 | care about your device, say no. | 52 | care about your device, say no. |
| 57 | 53 | ||
| 58 | endif | 54 | endif # ISDN_DRV_GIGASET != n |
| 59 | |||
| 60 | endmenu | ||
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 12d91fb9f8cb..a3b945ac3256 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | 1 | ||
| 2 | menu "Passive cards" | 2 | menu "Passive cards" |
| 3 | depends on ISDN_I4L | ||
| 4 | 3 | ||
| 5 | config ISDN_DRV_HISAX | 4 | config ISDN_DRV_HISAX |
| 6 | tristate "HiSax SiemensChipSet driver support" | 5 | tristate "HiSax SiemensChipSet driver support" |
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index e91c187992dd..36778b270c30 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig | |||
| @@ -99,7 +99,6 @@ config ISDN_DRV_LOOP | |||
| 99 | 99 | ||
| 100 | config ISDN_DIVERSION | 100 | config ISDN_DIVERSION |
| 101 | tristate "Support isdn diversion services" | 101 | tristate "Support isdn diversion services" |
| 102 | depends on ISDN_I4L | ||
| 103 | help | 102 | help |
| 104 | This option allows you to use some supplementary diversion | 103 | This option allows you to use some supplementary diversion |
| 105 | services in conjunction with the HiSax driver on an EURO/DSS1 | 104 | services in conjunction with the HiSax driver on an EURO/DSS1 |
| @@ -119,13 +118,11 @@ config ISDN_DIVERSION | |||
| 119 | endmenu | 118 | endmenu |
| 120 | 119 | ||
| 121 | comment "ISDN4Linux hardware drivers" | 120 | comment "ISDN4Linux hardware drivers" |
| 122 | depends on ISDN_I4L | ||
| 123 | 121 | ||
| 124 | source "drivers/isdn/hisax/Kconfig" | 122 | source "drivers/isdn/hisax/Kconfig" |
| 125 | 123 | ||
| 126 | 124 | ||
| 127 | menu "Active cards" | 125 | menu "Active cards" |
| 128 | depends on ISDN_I4L!=n | ||
| 129 | 126 | ||
| 130 | source "drivers/isdn/icn/Kconfig" | 127 | source "drivers/isdn/icn/Kconfig" |
| 131 | 128 | ||
diff --git a/drivers/isdn/icn/Kconfig b/drivers/isdn/icn/Kconfig index fcb99f5f0b26..89d15eed765e 100644 --- a/drivers/isdn/icn/Kconfig +++ b/drivers/isdn/icn/Kconfig | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | config ISDN_DRV_ICN | 4 | config ISDN_DRV_ICN |
| 5 | tristate "ICN 2B and 4B support" | 5 | tristate "ICN 2B and 4B support" |
| 6 | depends on ISDN_I4L && ISA | 6 | depends on ISA |
| 7 | help | 7 | help |
| 8 | This enables support for two kinds of ISDN-cards made by a German | 8 | This enables support for two kinds of ISDN-cards made by a German |
| 9 | company called ICN. 2B is the standard version for a single ISDN | 9 | company called ICN. 2B is the standard version for a single ISDN |
diff --git a/drivers/isdn/pcbit/Kconfig b/drivers/isdn/pcbit/Kconfig index 0933881ab0c2..ffba6eca1244 100644 --- a/drivers/isdn/pcbit/Kconfig +++ b/drivers/isdn/pcbit/Kconfig | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | config ISDN_DRV_PCBIT | 4 | config ISDN_DRV_PCBIT |
| 5 | tristate "PCBIT-D support" | 5 | tristate "PCBIT-D support" |
| 6 | depends on ISDN_I4L && ISA && (BROKEN || X86) | 6 | depends on ISA && (BROKEN || X86) |
| 7 | help | 7 | help |
| 8 | This enables support for the PCBIT ISDN-card. This card is | 8 | This enables support for the PCBIT ISDN-card. This card is |
| 9 | manufactured in Portugal by Octal. For running this card, | 9 | manufactured in Portugal by Octal. For running this card, |
diff --git a/drivers/isdn/sc/Kconfig b/drivers/isdn/sc/Kconfig index 5346e33d816c..e6510ca7bf43 100644 --- a/drivers/isdn/sc/Kconfig +++ b/drivers/isdn/sc/Kconfig | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | config ISDN_DRV_SC | 4 | config ISDN_DRV_SC |
| 5 | tristate "Spellcaster support" | 5 | tristate "Spellcaster support" |
| 6 | depends on ISDN_I4L && ISA | 6 | depends on ISA |
| 7 | help | 7 | help |
| 8 | This enables support for the Spellcaster BRI ISDN boards. This | 8 | This enables support for the Spellcaster BRI ISDN boards. This |
| 9 | driver currently builds only in a modularized version. | 9 | driver currently builds only in a modularized version. |
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig index 2f661e5f0dae..6cecc396e040 100644 --- a/drivers/kvm/Kconfig +++ b/drivers/kvm/Kconfig | |||
| @@ -11,6 +11,7 @@ if VIRTUALIZATION | |||
| 11 | config KVM | 11 | config KVM |
| 12 | tristate "Kernel-based Virtual Machine (KVM) support" | 12 | tristate "Kernel-based Virtual Machine (KVM) support" |
| 13 | depends on X86 && EXPERIMENTAL | 13 | depends on X86 && EXPERIMENTAL |
| 14 | select ANON_INODES | ||
| 14 | ---help--- | 15 | ---help--- |
| 15 | Support hosting fully virtualized guest machines using hardware | 16 | Support hosting fully virtualized guest machines using hardware |
| 16 | virtualization extensions. You will need a fairly recent | 17 | virtualization extensions. You will need a fairly recent |
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index d99d2fe53dca..1a87ba9d5156 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c | |||
| @@ -244,7 +244,7 @@ static int mmu_topup_memory_cache_page(struct kvm_mmu_memory_cache *cache, | |||
| 244 | static void mmu_free_memory_cache_page(struct kvm_mmu_memory_cache *mc) | 244 | static void mmu_free_memory_cache_page(struct kvm_mmu_memory_cache *mc) |
| 245 | { | 245 | { |
| 246 | while (mc->nobjs) | 246 | while (mc->nobjs) |
| 247 | __free_page(mc->objects[--mc->nobjs]); | 247 | free_page((unsigned long)mc->objects[--mc->nobjs]); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | static int __mmu_topup_memory_caches(struct kvm_vcpu *vcpu, gfp_t gfp_flags) | 250 | static int __mmu_topup_memory_caches(struct kvm_vcpu *vcpu, gfp_t gfp_flags) |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 87d2046f866c..4468cb3a8d24 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
| @@ -1,9 +1,6 @@ | |||
| 1 | 1 | menuconfig NEW_LEDS | |
| 2 | menu "LED devices" | ||
| 3 | depends on HAS_IOMEM | ||
| 4 | |||
| 5 | config NEW_LEDS | ||
| 6 | bool "LED Support" | 2 | bool "LED Support" |
| 3 | depends on HAS_IOMEM | ||
| 7 | help | 4 | help |
| 8 | Say Y to enable Linux LED support. This allows control of supported | 5 | Say Y to enable Linux LED support. This allows control of supported |
| 9 | LEDs from both userspace and optionally, by kernel events (triggers). | 6 | LEDs from both userspace and optionally, by kernel events (triggers). |
| @@ -11,9 +8,10 @@ config NEW_LEDS | |||
| 11 | This is not related to standard keyboard LEDs which are controlled | 8 | This is not related to standard keyboard LEDs which are controlled |
| 12 | via the input system. | 9 | via the input system. |
| 13 | 10 | ||
| 11 | if NEW_LEDS | ||
| 12 | |||
| 14 | config LEDS_CLASS | 13 | config LEDS_CLASS |
| 15 | tristate "LED Class Support" | 14 | tristate "LED Class Support" |
| 16 | depends on NEW_LEDS | ||
| 17 | help | 15 | help |
| 18 | This option enables the led sysfs class in /sys/class/leds. You'll | 16 | This option enables the led sysfs class in /sys/class/leds. You'll |
| 19 | need this to do anything useful with LEDs. If unsure, say N. | 17 | need this to do anything useful with LEDs. If unsure, say N. |
| @@ -95,11 +93,18 @@ config LEDS_COBALT | |||
| 95 | help | 93 | help |
| 96 | This option enables support for the front LED on Cobalt Server | 94 | This option enables support for the front LED on Cobalt Server |
| 97 | 95 | ||
| 96 | config LEDS_GPIO | ||
| 97 | tristate "LED Support for GPIO connected LEDs" | ||
| 98 | depends on LEDS_CLASS && GENERIC_GPIO | ||
| 99 | help | ||
| 100 | This option enables support for the LEDs connected to GPIO | ||
| 101 | outputs. To be useful the particular board must have LEDs | ||
| 102 | and they must be connected to the GPIO lines. | ||
| 103 | |||
| 98 | comment "LED Triggers" | 104 | comment "LED Triggers" |
| 99 | 105 | ||
| 100 | config LEDS_TRIGGERS | 106 | config LEDS_TRIGGERS |
| 101 | bool "LED Trigger support" | 107 | bool "LED Trigger support" |
| 102 | depends on NEW_LEDS | ||
| 103 | help | 108 | help |
| 104 | This option enables trigger support for the leds class. | 109 | This option enables trigger support for the leds class. |
| 105 | These triggers allow kernel events to drive the LEDs and can | 110 | These triggers allow kernel events to drive the LEDs and can |
| @@ -128,5 +133,4 @@ config LEDS_TRIGGER_HEARTBEAT | |||
| 128 | load average. | 133 | load average. |
| 129 | If unsure, say Y. | 134 | If unsure, say Y. |
| 130 | 135 | ||
| 131 | endmenu | 136 | endif # NEW_LEDS |
| 132 | |||
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index aa2c18efa5b2..f8995c9bc2ea 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
| @@ -16,6 +16,7 @@ obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o | |||
| 16 | obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o | 16 | obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o |
| 17 | obj-$(CONFIG_LEDS_H1940) += leds-h1940.o | 17 | obj-$(CONFIG_LEDS_H1940) += leds-h1940.o |
| 18 | obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o | 18 | obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o |
| 19 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o | ||
| 19 | 20 | ||
| 20 | # LED Triggers | 21 | # LED Triggers |
| 21 | obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o | 22 | obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o |
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 3c1711210e38..4211293ce862 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * LED Class Core | 2 | * LED Class Core |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> | 4 | * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> |
| 5 | * Copyright (C) 2005-2006 Richard Purdie <rpurdie@openedhand.com> | 5 | * Copyright (C) 2005-2007 Richard Purdie <rpurdie@openedhand.com> |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
| @@ -24,9 +24,10 @@ | |||
| 24 | 24 | ||
| 25 | static struct class *leds_class; | 25 | static struct class *leds_class; |
| 26 | 26 | ||
| 27 | static ssize_t led_brightness_show(struct class_device *dev, char *buf) | 27 | static ssize_t led_brightness_show(struct device *dev, |
| 28 | struct device_attribute *attr, char *buf) | ||
| 28 | { | 29 | { |
| 29 | struct led_classdev *led_cdev = class_get_devdata(dev); | 30 | struct led_classdev *led_cdev = dev_get_drvdata(dev); |
| 30 | ssize_t ret = 0; | 31 | ssize_t ret = 0; |
| 31 | 32 | ||
| 32 | /* no lock needed for this */ | 33 | /* no lock needed for this */ |
| @@ -36,10 +37,10 @@ static ssize_t led_brightness_show(struct class_device *dev, char *buf) | |||
| 36 | return ret; | 37 | return ret; |
| 37 | } | 38 | } |
| 38 | 39 | ||
| 39 | static ssize_t led_brightness_store(struct class_device *dev, | 40 | static ssize_t led_brightness_store(struct device *dev, |
| 40 | const char *buf, size_t size) | 41 | struct device_attribute *attr, const char *buf, size_t size) |
| 41 | { | 42 | { |
| 42 | struct led_classdev *led_cdev = class_get_devdata(dev); | 43 | struct led_classdev *led_cdev = dev_get_drvdata(dev); |
| 43 | ssize_t ret = -EINVAL; | 44 | ssize_t ret = -EINVAL; |
| 44 | char *after; | 45 | char *after; |
| 45 | unsigned long state = simple_strtoul(buf, &after, 10); | 46 | unsigned long state = simple_strtoul(buf, &after, 10); |
| @@ -56,10 +57,9 @@ static ssize_t led_brightness_store(struct class_device *dev, | |||
| 56 | return ret; | 57 | return ret; |
| 57 | } | 58 | } |
| 58 | 59 | ||
| 59 | static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show, | 60 | static DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store); |
| 60 | led_brightness_store); | ||
| 61 | #ifdef CONFIG_LEDS_TRIGGERS | 61 | #ifdef CONFIG_LEDS_TRIGGERS |
| 62 | static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); | 62 | static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); |
| 63 | #endif | 63 | #endif |
| 64 | 64 | ||
| 65 | /** | 65 | /** |
| @@ -93,16 +93,15 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) | |||
| 93 | { | 93 | { |
| 94 | int rc; | 94 | int rc; |
| 95 | 95 | ||
| 96 | led_cdev->class_dev = class_device_create(leds_class, NULL, 0, | 96 | led_cdev->dev = device_create(leds_class, parent, 0, "%s", |
| 97 | parent, "%s", led_cdev->name); | 97 | led_cdev->name); |
| 98 | if (unlikely(IS_ERR(led_cdev->class_dev))) | 98 | if (unlikely(IS_ERR(led_cdev->dev))) |
| 99 | return PTR_ERR(led_cdev->class_dev); | 99 | return PTR_ERR(led_cdev->dev); |
| 100 | 100 | ||
| 101 | class_set_devdata(led_cdev->class_dev, led_cdev); | 101 | dev_set_drvdata(led_cdev->dev, led_cdev); |
| 102 | 102 | ||
| 103 | /* register the attributes */ | 103 | /* register the attributes */ |
| 104 | rc = class_device_create_file(led_cdev->class_dev, | 104 | rc = device_create_file(led_cdev->dev, &dev_attr_brightness); |
| 105 | &class_device_attr_brightness); | ||
| 106 | if (rc) | 105 | if (rc) |
| 107 | goto err_out; | 106 | goto err_out; |
| 108 | 107 | ||
| @@ -114,8 +113,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) | |||
| 114 | #ifdef CONFIG_LEDS_TRIGGERS | 113 | #ifdef CONFIG_LEDS_TRIGGERS |
| 115 | rwlock_init(&led_cdev->trigger_lock); | 114 | rwlock_init(&led_cdev->trigger_lock); |
| 116 | 115 | ||
| 117 | rc = class_device_create_file(led_cdev->class_dev, | 116 | rc = device_create_file(led_cdev->dev, &dev_attr_trigger); |
| 118 | &class_device_attr_trigger); | ||
| 119 | if (rc) | 117 | if (rc) |
| 120 | goto err_out_led_list; | 118 | goto err_out_led_list; |
| 121 | 119 | ||
| @@ -123,18 +121,17 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) | |||
| 123 | #endif | 121 | #endif |
| 124 | 122 | ||
| 125 | printk(KERN_INFO "Registered led device: %s\n", | 123 | printk(KERN_INFO "Registered led device: %s\n", |
| 126 | led_cdev->class_dev->class_id); | 124 | led_cdev->name); |
| 127 | 125 | ||
| 128 | return 0; | 126 | return 0; |
| 129 | 127 | ||
| 130 | #ifdef CONFIG_LEDS_TRIGGERS | 128 | #ifdef CONFIG_LEDS_TRIGGERS |
| 131 | err_out_led_list: | 129 | err_out_led_list: |
| 132 | class_device_remove_file(led_cdev->class_dev, | 130 | device_remove_file(led_cdev->dev, &dev_attr_brightness); |
| 133 | &class_device_attr_brightness); | ||
| 134 | list_del(&led_cdev->node); | 131 | list_del(&led_cdev->node); |
| 135 | #endif | 132 | #endif |
| 136 | err_out: | 133 | err_out: |
| 137 | class_device_unregister(led_cdev->class_dev); | 134 | device_unregister(led_cdev->dev); |
| 138 | return rc; | 135 | return rc; |
| 139 | } | 136 | } |
| 140 | EXPORT_SYMBOL_GPL(led_classdev_register); | 137 | EXPORT_SYMBOL_GPL(led_classdev_register); |
| @@ -147,18 +144,16 @@ EXPORT_SYMBOL_GPL(led_classdev_register); | |||
| 147 | */ | 144 | */ |
| 148 | void led_classdev_unregister(struct led_classdev *led_cdev) | 145 | void led_classdev_unregister(struct led_classdev *led_cdev) |
| 149 | { | 146 | { |
| 150 | class_device_remove_file(led_cdev->class_dev, | 147 | device_remove_file(led_cdev->dev, &dev_attr_brightness); |
| 151 | &class_device_attr_brightness); | ||
| 152 | #ifdef CONFIG_LEDS_TRIGGERS | 148 | #ifdef CONFIG_LEDS_TRIGGERS |
| 153 | class_device_remove_file(led_cdev->class_dev, | 149 | device_remove_file(led_cdev->dev, &dev_attr_trigger); |
| 154 | &class_device_attr_trigger); | ||
| 155 | write_lock(&led_cdev->trigger_lock); | 150 | write_lock(&led_cdev->trigger_lock); |
| 156 | if (led_cdev->trigger) | 151 | if (led_cdev->trigger) |
| 157 | led_trigger_set(led_cdev, NULL); | 152 | led_trigger_set(led_cdev, NULL); |
| 158 | write_unlock(&led_cdev->trigger_lock); | 153 | write_unlock(&led_cdev->trigger_lock); |
| 159 | #endif | 154 | #endif |
| 160 | 155 | ||
| 161 | class_device_unregister(led_cdev->class_dev); | 156 | device_unregister(led_cdev->dev); |
| 162 | 157 | ||
| 163 | write_lock(&leds_list_lock); | 158 | write_lock(&leds_list_lock); |
| 164 | list_del(&led_cdev->node); | 159 | list_del(&led_cdev->node); |
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 454fb0901f82..575368c2b100 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * LED Triggers Core | 2 | * LED Triggers Core |
| 3 | * | 3 | * |
| 4 | * Copyright 2005-2006 Openedhand Ltd. | 4 | * Copyright 2005-2007 Openedhand Ltd. |
| 5 | * | 5 | * |
| 6 | * Author: Richard Purdie <rpurdie@openedhand.com> | 6 | * Author: Richard Purdie <rpurdie@openedhand.com> |
| 7 | * | 7 | * |
| @@ -28,10 +28,10 @@ | |||
| 28 | static DEFINE_RWLOCK(triggers_list_lock); | 28 | static DEFINE_RWLOCK(triggers_list_lock); |
| 29 | static LIST_HEAD(trigger_list); | 29 | static LIST_HEAD(trigger_list); |
| 30 | 30 | ||
| 31 | ssize_t led_trigger_store(struct class_device *dev, const char *buf, | 31 | ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, |
| 32 | size_t count) | 32 | const char *buf, size_t count) |
| 33 | { | 33 | { |
| 34 | struct led_classdev *led_cdev = class_get_devdata(dev); | 34 | struct led_classdev *led_cdev = dev_get_drvdata(dev); |
| 35 | char trigger_name[TRIG_NAME_MAX]; | 35 | char trigger_name[TRIG_NAME_MAX]; |
| 36 | struct led_trigger *trig; | 36 | struct led_trigger *trig; |
| 37 | size_t len; | 37 | size_t len; |
| @@ -67,9 +67,10 @@ ssize_t led_trigger_store(struct class_device *dev, const char *buf, | |||
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | 69 | ||
| 70 | ssize_t led_trigger_show(struct class_device *dev, char *buf) | 70 | ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, |
| 71 | char *buf) | ||
| 71 | { | 72 | { |
| 72 | struct led_classdev *led_cdev = class_get_devdata(dev); | 73 | struct led_classdev *led_cdev = dev_get_drvdata(dev); |
| 73 | struct led_trigger *trig; | 74 | struct led_trigger *trig; |
| 74 | int len = 0; | 75 | int len = 0; |
| 75 | 76 | ||
| @@ -183,13 +184,20 @@ int led_trigger_register(struct led_trigger *trigger) | |||
| 183 | void led_trigger_register_simple(const char *name, struct led_trigger **tp) | 184 | void led_trigger_register_simple(const char *name, struct led_trigger **tp) |
| 184 | { | 185 | { |
| 185 | struct led_trigger *trigger; | 186 | struct led_trigger *trigger; |
| 187 | int err; | ||
| 186 | 188 | ||
| 187 | trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 189 | trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); |
| 188 | 190 | ||
| 189 | if (trigger) { | 191 | if (trigger) { |
| 190 | trigger->name = name; | 192 | trigger->name = name; |
| 191 | led_trigger_register(trigger); | 193 | err = led_trigger_register(trigger); |
| 192 | } | 194 | if (err < 0) |
| 195 | printk(KERN_WARNING "LED trigger %s failed to register" | ||
| 196 | " (%d)\n", name, err); | ||
| 197 | } else | ||
| 198 | printk(KERN_WARNING "LED trigger %s failed to register" | ||
| 199 | " (no memory)\n", name); | ||
| 200 | |||
| 193 | *tp = trigger; | 201 | *tp = trigger; |
| 194 | } | 202 | } |
| 195 | 203 | ||
| @@ -215,7 +223,8 @@ void led_trigger_unregister(struct led_trigger *trigger) | |||
| 215 | 223 | ||
| 216 | void led_trigger_unregister_simple(struct led_trigger *trigger) | 224 | void led_trigger_unregister_simple(struct led_trigger *trigger) |
| 217 | { | 225 | { |
| 218 | led_trigger_unregister(trigger); | 226 | if (trigger) |
| 227 | led_trigger_unregister(trigger); | ||
| 219 | kfree(trigger); | 228 | kfree(trigger); |
| 220 | } | 229 | } |
| 221 | 230 | ||
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c new file mode 100644 index 000000000000..47d90db280ce --- /dev/null +++ b/drivers/leds/leds-gpio.c | |||
| @@ -0,0 +1,199 @@ | |||
| 1 | /* | ||
| 2 | * LEDs driver for GPIOs | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 8D Technologies inc. | ||
| 5 | * Raphael Assenat <raph@8d.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/leds.h> | ||
| 16 | #include <linux/workqueue.h> | ||
| 17 | |||
| 18 | #include <asm/gpio.h> | ||
| 19 | |||
| 20 | struct gpio_led_data { | ||
| 21 | struct led_classdev cdev; | ||
| 22 | unsigned gpio; | ||
| 23 | struct work_struct work; | ||
| 24 | u8 new_level; | ||
| 25 | u8 can_sleep; | ||
| 26 | u8 active_low; | ||
| 27 | }; | ||
| 28 | |||
| 29 | static void gpio_led_work(struct work_struct *work) | ||
| 30 | { | ||
| 31 | struct gpio_led_data *led_dat = | ||
| 32 | container_of(work, struct gpio_led_data, work); | ||
| 33 | |||
| 34 | gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); | ||
| 35 | } | ||
| 36 | |||
| 37 | static void gpio_led_set(struct led_classdev *led_cdev, | ||
| 38 | enum led_brightness value) | ||
| 39 | { | ||
| 40 | struct gpio_led_data *led_dat = | ||
| 41 | container_of(led_cdev, struct gpio_led_data, cdev); | ||
| 42 | int level; | ||
| 43 | |||
| 44 | if (value == LED_OFF) | ||
| 45 | level = 0; | ||
| 46 | else | ||
| 47 | level = 1; | ||
| 48 | |||
| 49 | if (led_dat->active_low) | ||
| 50 | level = !level; | ||
| 51 | |||
| 52 | /* setting GPIOs with I2C/etc requires a preemptible task context */ | ||
| 53 | if (led_dat->can_sleep) { | ||
| 54 | if (preempt_count()) { | ||
| 55 | led_dat->new_level = level; | ||
| 56 | schedule_work(&led_dat->work); | ||
| 57 | } else | ||
| 58 | gpio_set_value_cansleep(led_dat->gpio, level); | ||
| 59 | } else | ||
| 60 | gpio_set_value(led_dat->gpio, level); | ||
| 61 | } | ||
| 62 | |||
| 63 | static int __init gpio_led_probe(struct platform_device *pdev) | ||
| 64 | { | ||
| 65 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | ||
| 66 | struct gpio_led *cur_led; | ||
| 67 | struct gpio_led_data *leds_data, *led_dat; | ||
| 68 | int i, ret = 0; | ||
| 69 | |||
| 70 | if (!pdata) | ||
| 71 | return -EBUSY; | ||
| 72 | |||
| 73 | leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds, | ||
| 74 | GFP_KERNEL); | ||
| 75 | if (!leds_data) | ||
| 76 | return -ENOMEM; | ||
| 77 | |||
| 78 | for (i = 0; i < pdata->num_leds; i++) { | ||
| 79 | cur_led = &pdata->leds[i]; | ||
| 80 | led_dat = &leds_data[i]; | ||
| 81 | |||
| 82 | led_dat->cdev.name = cur_led->name; | ||
| 83 | led_dat->cdev.default_trigger = cur_led->default_trigger; | ||
| 84 | led_dat->gpio = cur_led->gpio; | ||
| 85 | led_dat->can_sleep = gpio_cansleep(cur_led->gpio); | ||
| 86 | led_dat->active_low = cur_led->active_low; | ||
| 87 | led_dat->cdev.brightness_set = gpio_led_set; | ||
| 88 | led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF; | ||
| 89 | |||
| 90 | ret = gpio_request(led_dat->gpio, led_dat->cdev.name); | ||
| 91 | if (ret < 0) | ||
| 92 | goto err; | ||
| 93 | |||
| 94 | gpio_direction_output(led_dat->gpio, led_dat->active_low); | ||
| 95 | |||
| 96 | ret = led_classdev_register(&pdev->dev, &led_dat->cdev); | ||
| 97 | if (ret < 0) { | ||
| 98 | gpio_free(led_dat->gpio); | ||
| 99 | goto err; | ||
| 100 | } | ||
| 101 | |||
| 102 | INIT_WORK(&led_dat->work, gpio_led_work); | ||
| 103 | } | ||
| 104 | |||
| 105 | platform_set_drvdata(pdev, leds_data); | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | |||
| 109 | err: | ||
| 110 | if (i > 0) { | ||
| 111 | for (i = i - 1; i >= 0; i--) { | ||
| 112 | led_classdev_unregister(&leds_data[i].cdev); | ||
| 113 | gpio_free(leds_data[i].gpio); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | flush_scheduled_work(); | ||
| 118 | kfree(leds_data); | ||
| 119 | |||
| 120 | return ret; | ||
| 121 | } | ||
| 122 | |||
| 123 | static int __exit gpio_led_remove(struct platform_device *pdev) | ||
| 124 | { | ||
| 125 | int i; | ||
| 126 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | ||
| 127 | struct gpio_led_data *leds_data; | ||
| 128 | |||
| 129 | leds_data = platform_get_drvdata(pdev); | ||
| 130 | |||
| 131 | for (i = 0; i < pdata->num_leds; i++) { | ||
| 132 | led_classdev_unregister(&leds_data[i].cdev); | ||
| 133 | gpio_free(leds_data[i].gpio); | ||
| 134 | } | ||
| 135 | |||
| 136 | kfree(leds_data); | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | #ifdef CONFIG_PM | ||
| 142 | static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 143 | { | ||
| 144 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | ||
| 145 | struct gpio_led_data *leds_data; | ||
| 146 | int i; | ||
| 147 | |||
| 148 | leds_data = platform_get_drvdata(pdev); | ||
| 149 | |||
| 150 | for (i = 0; i < pdata->num_leds; i++) | ||
| 151 | led_classdev_suspend(&leds_data[i].cdev); | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static int gpio_led_resume(struct platform_device *pdev) | ||
| 157 | { | ||
| 158 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | ||
| 159 | struct gpio_led_data *leds_data; | ||
| 160 | int i; | ||
| 161 | |||
| 162 | leds_data = platform_get_drvdata(pdev); | ||
| 163 | |||
| 164 | for (i = 0; i < pdata->num_leds; i++) | ||
| 165 | led_classdev_resume(&leds_data[i].cdev); | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | #else | ||
| 170 | #define gpio_led_suspend NULL | ||
| 171 | #define gpio_led_resume NULL | ||
| 172 | #endif | ||
| 173 | |||
| 174 | static struct platform_driver gpio_led_driver = { | ||
| 175 | .remove = __exit_p(gpio_led_remove), | ||
| 176 | .suspend = gpio_led_suspend, | ||
| 177 | .resume = gpio_led_resume, | ||
| 178 | .driver = { | ||
| 179 | .name = "leds-gpio", | ||
| 180 | .owner = THIS_MODULE, | ||
| 181 | }, | ||
| 182 | }; | ||
| 183 | |||
| 184 | static int __init gpio_led_init(void) | ||
| 185 | { | ||
| 186 | return platform_driver_probe(&gpio_led_driver, gpio_led_probe); | ||
| 187 | } | ||
| 188 | |||
| 189 | static void __exit gpio_led_exit(void) | ||
| 190 | { | ||
| 191 | platform_driver_unregister(&gpio_led_driver); | ||
| 192 | } | ||
| 193 | |||
| 194 | module_init(gpio_led_init); | ||
| 195 | module_exit(gpio_led_exit); | ||
| 196 | |||
| 197 | MODULE_AUTHOR("Raphael Assenat <raph@8d.com>"); | ||
| 198 | MODULE_DESCRIPTION("GPIO LED driver"); | ||
| 199 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c index 6f2d449ba983..bfac499f3258 100644 --- a/drivers/leds/leds-locomo.c +++ b/drivers/leds/leds-locomo.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | static void locomoled_brightness_set(struct led_classdev *led_cdev, | 19 | static void locomoled_brightness_set(struct led_classdev *led_cdev, |
| 20 | enum led_brightness value, int offset) | 20 | enum led_brightness value, int offset) |
| 21 | { | 21 | { |
| 22 | struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev); | 22 | struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->dev); |
| 23 | unsigned long flags; | 23 | unsigned long flags; |
| 24 | 24 | ||
| 25 | local_irq_save(flags); | 25 | local_irq_save(flags); |
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index a715c4ed93ff..f2f3884fe063 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #ifndef __LEDS_H_INCLUDED | 13 | #ifndef __LEDS_H_INCLUDED |
| 14 | #define __LEDS_H_INCLUDED | 14 | #define __LEDS_H_INCLUDED |
| 15 | 15 | ||
| 16 | #include <linux/device.h> | ||
| 16 | #include <linux/leds.h> | 17 | #include <linux/leds.h> |
| 17 | 18 | ||
| 18 | static inline void led_set_brightness(struct led_classdev *led_cdev, | 19 | static inline void led_set_brightness(struct led_classdev *led_cdev, |
| @@ -37,8 +38,9 @@ void led_trigger_set(struct led_classdev *led_cdev, | |||
| 37 | #define led_trigger_set(x, y) do {} while(0) | 38 | #define led_trigger_set(x, y) do {} while(0) |
| 38 | #endif | 39 | #endif |
| 39 | 40 | ||
| 40 | ssize_t led_trigger_store(struct class_device *dev, const char *buf, | 41 | ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, |
| 41 | size_t count); | 42 | const char *buf, size_t count); |
| 42 | ssize_t led_trigger_show(struct class_device *dev, char *buf); | 43 | ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, |
| 44 | char *buf); | ||
| 43 | 45 | ||
| 44 | #endif /* __LEDS_H_INCLUDED */ | 46 | #endif /* __LEDS_H_INCLUDED */ |
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c index d756bdb01c59..ed9ff02c77ea 100644 --- a/drivers/leds/ledtrig-timer.c +++ b/drivers/leds/ledtrig-timer.c | |||
| @@ -52,9 +52,10 @@ static void led_timer_function(unsigned long data) | |||
| 52 | mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); | 52 | mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | static ssize_t led_delay_on_show(struct class_device *dev, char *buf) | 55 | static ssize_t led_delay_on_show(struct device *dev, |
| 56 | struct device_attribute *attr, char *buf) | ||
| 56 | { | 57 | { |
| 57 | struct led_classdev *led_cdev = class_get_devdata(dev); | 58 | struct led_classdev *led_cdev = dev_get_drvdata(dev); |
| 58 | struct timer_trig_data *timer_data = led_cdev->trigger_data; | 59 | struct timer_trig_data *timer_data = led_cdev->trigger_data; |
| 59 | 60 | ||
| 60 | sprintf(buf, "%lu\n", timer_data->delay_on); | 61 | sprintf(buf, "%lu\n", timer_data->delay_on); |
| @@ -62,10 +63,10 @@ static ssize_t led_delay_on_show(struct class_device *dev, char *buf) | |||
| 62 | return strlen(buf) + 1; | 63 | return strlen(buf) + 1; |
| 63 | } | 64 | } |
| 64 | 65 | ||
| 65 | static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, | 66 | static ssize_t led_delay_on_store(struct device *dev, |
| 66 | size_t size) | 67 | struct device_attribute *attr, const char *buf, size_t size) |
| 67 | { | 68 | { |
| 68 | struct led_classdev *led_cdev = class_get_devdata(dev); | 69 | struct led_classdev *led_cdev = dev_get_drvdata(dev); |
| 69 | struct timer_trig_data *timer_data = led_cdev->trigger_data; | 70 | struct timer_trig_data *timer_data = led_cdev->trigger_data; |
| 70 | int ret = -EINVAL; | 71 | int ret = -EINVAL; |
| 71 | char *after; | 72 | char *after; |
| @@ -84,9 +85,10 @@ static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, | |||
| 84 | return ret; | 85 | return ret; |
| 85 | } | 86 | } |
| 86 | 87 | ||
| 87 | static ssize_t led_delay_off_show(struct class_device *dev, char *buf) | 88 | static ssize_t led_delay_off_show(struct device *dev, |
| 89 | struct device_attribute *attr, char *buf) | ||
| 88 | { | 90 | { |
| 89 | struct led_classdev *led_cdev = class_get_devdata(dev); | 91 | struct led_classdev *led_cdev = dev_get_drvdata(dev); |
| 90 | struct timer_trig_data *timer_data = led_cdev->trigger_data; | 92 | struct timer_trig_data *timer_data = led_cdev->trigger_data; |
| 91 | 93 | ||
| 92 | sprintf(buf, "%lu\n", timer_data->delay_off); | 94 | sprintf(buf, "%lu\n", timer_data->delay_off); |
| @@ -94,10 +96,10 @@ static ssize_t led_delay_off_show(struct class_device *dev, char *buf) | |||
| 94 | return strlen(buf) + 1; | 96 | return strlen(buf) + 1; |
| 95 | } | 97 | } |
| 96 | 98 | ||
| 97 | static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, | 99 | static ssize_t led_delay_off_store(struct device *dev, |
| 98 | size_t size) | 100 | struct device_attribute *attr, const char *buf, size_t size) |
| 99 | { | 101 | { |
| 100 | struct led_classdev *led_cdev = class_get_devdata(dev); | 102 | struct led_classdev *led_cdev = dev_get_drvdata(dev); |
| 101 | struct timer_trig_data *timer_data = led_cdev->trigger_data; | 103 | struct timer_trig_data *timer_data = led_cdev->trigger_data; |
| 102 | int ret = -EINVAL; | 104 | int ret = -EINVAL; |
| 103 | char *after; | 105 | char *after; |
| @@ -116,10 +118,8 @@ static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, | |||
| 116 | return ret; | 118 | return ret; |
| 117 | } | 119 | } |
| 118 | 120 | ||
| 119 | static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show, | 121 | static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); |
| 120 | led_delay_on_store); | 122 | static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); |
| 121 | static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show, | ||
| 122 | led_delay_off_store); | ||
| 123 | 123 | ||
| 124 | static void timer_trig_activate(struct led_classdev *led_cdev) | 124 | static void timer_trig_activate(struct led_classdev *led_cdev) |
| 125 | { | 125 | { |
| @@ -136,18 +136,17 @@ static void timer_trig_activate(struct led_classdev *led_cdev) | |||
| 136 | timer_data->timer.function = led_timer_function; | 136 | timer_data->timer.function = led_timer_function; |
| 137 | timer_data->timer.data = (unsigned long) led_cdev; | 137 | timer_data->timer.data = (unsigned long) led_cdev; |
| 138 | 138 | ||
| 139 | rc = class_device_create_file(led_cdev->class_dev, | 139 | rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); |
| 140 | &class_device_attr_delay_on); | 140 | if (rc) |
| 141 | if (rc) goto err_out; | 141 | goto err_out; |
| 142 | rc = class_device_create_file(led_cdev->class_dev, | 142 | rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); |
| 143 | &class_device_attr_delay_off); | 143 | if (rc) |
| 144 | if (rc) goto err_out_delayon; | 144 | goto err_out_delayon; |
| 145 | 145 | ||
| 146 | return; | 146 | return; |
| 147 | 147 | ||
| 148 | err_out_delayon: | 148 | err_out_delayon: |
| 149 | class_device_remove_file(led_cdev->class_dev, | 149 | device_remove_file(led_cdev->dev, &dev_attr_delay_on); |
| 150 | &class_device_attr_delay_on); | ||
| 151 | err_out: | 150 | err_out: |
| 152 | led_cdev->trigger_data = NULL; | 151 | led_cdev->trigger_data = NULL; |
| 153 | kfree(timer_data); | 152 | kfree(timer_data); |
| @@ -158,10 +157,8 @@ static void timer_trig_deactivate(struct led_classdev *led_cdev) | |||
| 158 | struct timer_trig_data *timer_data = led_cdev->trigger_data; | 157 | struct timer_trig_data *timer_data = led_cdev->trigger_data; |
| 159 | 158 | ||
| 160 | if (timer_data) { | 159 | if (timer_data) { |
| 161 | class_device_remove_file(led_cdev->class_dev, | 160 | device_remove_file(led_cdev->dev, &dev_attr_delay_on); |
| 162 | &class_device_attr_delay_on); | 161 | device_remove_file(led_cdev->dev, &dev_attr_delay_off); |
| 163 | class_device_remove_file(led_cdev->class_dev, | ||
| 164 | &class_device_attr_delay_off); | ||
| 165 | del_timer_sync(&timer_data->timer); | 162 | del_timer_sync(&timer_data->timer); |
| 166 | kfree(timer_data); | 163 | kfree(timer_data); |
| 167 | } | 164 | } |
diff --git a/drivers/lguest/lguest.c b/drivers/lguest/lguest.c index 434fea1e82f7..18dade06d4a9 100644 --- a/drivers/lguest/lguest.c +++ b/drivers/lguest/lguest.c | |||
| @@ -398,6 +398,8 @@ static void lguest_clockevent_set_mode(enum clock_event_mode mode, | |||
| 398 | break; | 398 | break; |
| 399 | case CLOCK_EVT_MODE_PERIODIC: | 399 | case CLOCK_EVT_MODE_PERIODIC: |
| 400 | BUG(); | 400 | BUG(); |
| 401 | case CLOCK_EVT_MODE_RESUME: | ||
| 402 | break; | ||
| 401 | } | 403 | } |
| 402 | } | 404 | } |
| 403 | 405 | ||
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index 4177ff004753..2c21d4f25cc8 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <asm/machdep.h> | 30 | #include <asm/machdep.h> |
| 31 | #include <asm/pmac_feature.h> | 31 | #include <asm/pmac_feature.h> |
| 32 | #include <asm/dbdma.h> | 32 | #include <asm/dbdma.h> |
| 33 | #include <asm/dbdma.h> | ||
| 34 | #include <asm/macio.h> | 33 | #include <asm/macio.h> |
| 35 | #include <asm/keylargo.h> | 34 | #include <asm/keylargo.h> |
| 36 | 35 | ||
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ba952a032598..bdc52d6922b7 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
| @@ -920,6 +920,8 @@ static void crypt_dtr(struct dm_target *ti) | |||
| 920 | { | 920 | { |
| 921 | struct crypt_config *cc = (struct crypt_config *) ti->private; | 921 | struct crypt_config *cc = (struct crypt_config *) ti->private; |
| 922 | 922 | ||
| 923 | flush_workqueue(_kcryptd_workqueue); | ||
| 924 | |||
| 923 | bioset_free(cc->bs); | 925 | bioset_free(cc->bs); |
| 924 | mempool_destroy(cc->page_pool); | 926 | mempool_destroy(cc->page_pool); |
| 925 | mempool_destroy(cc->io_pool); | 927 | mempool_destroy(cc->io_pool); |
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index c88cc75ab49b..4494e0fd36c6 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig | |||
| @@ -37,6 +37,7 @@ config FUSION_FC | |||
| 37 | LSIFC929 | 37 | LSIFC929 |
| 38 | LSIFC929X | 38 | LSIFC929X |
| 39 | LSIFC929XL | 39 | LSIFC929XL |
| 40 | Brocade FC 410/420 | ||
| 40 | 41 | ||
| 41 | config FUSION_SAS | 42 | config FUSION_SAS |
| 42 | tristate "Fusion MPT ScsiHost drivers for SAS" | 43 | tristate "Fusion MPT ScsiHost drivers for SAS" |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 5a10c87239c2..04f75e24dcec 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
| @@ -161,6 +161,7 @@ static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); | |||
| 161 | static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); | 161 | static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); |
| 162 | static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); | 162 | static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); |
| 163 | static void mpt_timer_expired(unsigned long data); | 163 | static void mpt_timer_expired(unsigned long data); |
| 164 | static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc); | ||
| 164 | static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); | 165 | static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); |
| 165 | static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); | 166 | static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); |
| 166 | static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); | 167 | static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); |
| @@ -1131,6 +1132,248 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) | |||
| 1131 | return -1; | 1132 | return -1; |
| 1132 | } | 1133 | } |
| 1133 | 1134 | ||
| 1135 | /** | ||
| 1136 | * mpt_get_product_name - returns product string | ||
| 1137 | * @vendor: pci vendor id | ||
| 1138 | * @device: pci device id | ||
| 1139 | * @revision: pci revision id | ||
| 1140 | * @prod_name: string returned | ||
| 1141 | * | ||
| 1142 | * Returns product string displayed when driver loads, | ||
| 1143 | * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product | ||
| 1144 | * | ||
| 1145 | **/ | ||
| 1146 | static void | ||
| 1147 | mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name) | ||
| 1148 | { | ||
| 1149 | char *product_str = NULL; | ||
| 1150 | |||
| 1151 | if (vendor == PCI_VENDOR_ID_BROCADE) { | ||
| 1152 | switch (device) | ||
| 1153 | { | ||
| 1154 | case MPI_MANUFACTPAGE_DEVICEID_FC949E: | ||
| 1155 | switch (revision) | ||
| 1156 | { | ||
| 1157 | case 0x00: | ||
| 1158 | product_str = "BRE040 A0"; | ||
| 1159 | break; | ||
| 1160 | case 0x01: | ||
| 1161 | product_str = "BRE040 A1"; | ||
| 1162 | break; | ||
| 1163 | default: | ||
| 1164 | product_str = "BRE040"; | ||
| 1165 | break; | ||
| 1166 | } | ||
| 1167 | break; | ||
| 1168 | } | ||
| 1169 | goto out; | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | switch (device) | ||
| 1173 | { | ||
| 1174 | case MPI_MANUFACTPAGE_DEVICEID_FC909: | ||
| 1175 | product_str = "LSIFC909 B1"; | ||
| 1176 | break; | ||
| 1177 | case MPI_MANUFACTPAGE_DEVICEID_FC919: | ||
| 1178 | product_str = "LSIFC919 B0"; | ||
| 1179 | break; | ||
| 1180 | case MPI_MANUFACTPAGE_DEVICEID_FC929: | ||
| 1181 | product_str = "LSIFC929 B0"; | ||
| 1182 | break; | ||
| 1183 | case MPI_MANUFACTPAGE_DEVICEID_FC919X: | ||
| 1184 | if (revision < 0x80) | ||
| 1185 | product_str = "LSIFC919X A0"; | ||
| 1186 | else | ||
| 1187 | product_str = "LSIFC919XL A1"; | ||
| 1188 | break; | ||
| 1189 | case MPI_MANUFACTPAGE_DEVICEID_FC929X: | ||
| 1190 | if (revision < 0x80) | ||
| 1191 | product_str = "LSIFC929X A0"; | ||
| 1192 | else | ||
| 1193 | product_str = "LSIFC929XL A1"; | ||
| 1194 | break; | ||
| 1195 | case MPI_MANUFACTPAGE_DEVICEID_FC939X: | ||
| 1196 | product_str = "LSIFC939X A1"; | ||
| 1197 | break; | ||
| 1198 | case MPI_MANUFACTPAGE_DEVICEID_FC949X: | ||
| 1199 | product_str = "LSIFC949X A1"; | ||
| 1200 | break; | ||
| 1201 | case MPI_MANUFACTPAGE_DEVICEID_FC949E: | ||
| 1202 | switch (revision) | ||
| 1203 | { | ||
| 1204 | case 0x00: | ||
| 1205 | product_str = "LSIFC949E A0"; | ||
| 1206 | break; | ||
| 1207 | case 0x01: | ||
| 1208 | product_str = "LSIFC949E A1"; | ||
| 1209 | break; | ||
| 1210 | default: | ||
| 1211 | product_str = "LSIFC949E"; | ||
| 1212 | break; | ||
| 1213 | } | ||
| 1214 | break; | ||
| 1215 | case MPI_MANUFACTPAGE_DEVID_53C1030: | ||
| 1216 | switch (revision) | ||
| 1217 | { | ||
| 1218 | case 0x00: | ||
| 1219 | product_str = "LSI53C1030 A0"; | ||
| 1220 | break; | ||
| 1221 | case 0x01: | ||
| 1222 | product_str = "LSI53C1030 B0"; | ||
| 1223 | break; | ||
| 1224 | case 0x03: | ||
| 1225 | product_str = "LSI53C1030 B1"; | ||
| 1226 | break; | ||
| 1227 | case 0x07: | ||
| 1228 | product_str = "LSI53C1030 B2"; | ||
| 1229 | break; | ||
| 1230 | case 0x08: | ||
| 1231 | product_str = "LSI53C1030 C0"; | ||
| 1232 | break; | ||
| 1233 | case 0x80: | ||
| 1234 | product_str = "LSI53C1030T A0"; | ||
| 1235 | break; | ||
| 1236 | case 0x83: | ||
| 1237 | product_str = "LSI53C1030T A2"; | ||
| 1238 | break; | ||
| 1239 | case 0x87: | ||
| 1240 | product_str = "LSI53C1030T A3"; | ||
| 1241 | break; | ||
| 1242 | case 0xc1: | ||
| 1243 | product_str = "LSI53C1020A A1"; | ||
| 1244 | break; | ||
| 1245 | default: | ||
| 1246 | product_str = "LSI53C1030"; | ||
| 1247 | break; | ||
| 1248 | } | ||
| 1249 | break; | ||
| 1250 | case MPI_MANUFACTPAGE_DEVID_1030_53C1035: | ||
| 1251 | switch (revision) | ||
| 1252 | { | ||
| 1253 | case 0x03: | ||
| 1254 | product_str = "LSI53C1035 A2"; | ||
| 1255 | break; | ||
| 1256 | case 0x04: | ||
| 1257 | product_str = "LSI53C1035 B0"; | ||
| 1258 | break; | ||
| 1259 | default: | ||
| 1260 | product_str = "LSI53C1035"; | ||
| 1261 | break; | ||
| 1262 | } | ||
| 1263 | break; | ||
| 1264 | case MPI_MANUFACTPAGE_DEVID_SAS1064: | ||
| 1265 | switch (revision) | ||
| 1266 | { | ||
| 1267 | case 0x00: | ||
| 1268 | product_str = "LSISAS1064 A1"; | ||
| 1269 | break; | ||
| 1270 | case 0x01: | ||
| 1271 | product_str = "LSISAS1064 A2"; | ||
| 1272 | break; | ||
| 1273 | case 0x02: | ||
| 1274 | product_str = "LSISAS1064 A3"; | ||
| 1275 | break; | ||
| 1276 | case 0x03: | ||
| 1277 | product_str = "LSISAS1064 A4"; | ||
| 1278 | break; | ||
| 1279 | default: | ||
| 1280 | product_str = "LSISAS1064"; | ||
| 1281 | break; | ||
| 1282 | } | ||
| 1283 | break; | ||
| 1284 | case MPI_MANUFACTPAGE_DEVID_SAS1064E: | ||
| 1285 | switch (revision) | ||
| 1286 | { | ||
| 1287 | case 0x00: | ||
| 1288 | product_str = "LSISAS1064E A0"; | ||
| 1289 | break; | ||
| 1290 | case 0x01: | ||
| 1291 | product_str = "LSISAS1064E B0"; | ||
| 1292 | break; | ||
| 1293 | case 0x02: | ||
| 1294 | product_str = "LSISAS1064E B1"; | ||
| 1295 | break; | ||
| 1296 | case 0x04: | ||
| 1297 | product_str = "LSISAS1064E B2"; | ||
| 1298 | break; | ||
| 1299 | case 0x08: | ||
| 1300 | product_str = "LSISAS1064E B3"; | ||
| 1301 | break; | ||
| 1302 | default: | ||
| 1303 | product_str = "LSISAS1064E"; | ||
| 1304 | break; | ||
| 1305 | } | ||
| 1306 | break; | ||
| 1307 | case MPI_MANUFACTPAGE_DEVID_SAS1068: | ||
| 1308 | switch (revision) | ||
| 1309 | { | ||
| 1310 | case 0x00: | ||
| 1311 | product_str = "LSISAS1068 A0"; | ||
| 1312 | break; | ||
| 1313 | case 0x01: | ||
| 1314 | product_str = "LSISAS1068 B0"; | ||
| 1315 | break; | ||
| 1316 | case 0x02: | ||
| 1317 | product_str = "LSISAS1068 B1"; | ||
| 1318 | break; | ||
| 1319 | default: | ||
| 1320 | product_str = "LSISAS1068"; | ||
| 1321 | break; | ||
| 1322 | } | ||
| 1323 | break; | ||
| 1324 | case MPI_MANUFACTPAGE_DEVID_SAS1068E: | ||
| 1325 | switch (revision) | ||
| 1326 | { | ||
| 1327 | case 0x00: | ||
| 1328 | product_str = "LSISAS1068E A0"; | ||
| 1329 | break; | ||
| 1330 | case 0x01: | ||
| 1331 | product_str = "LSISAS1068E B0"; | ||
| 1332 | break; | ||
| 1333 | case 0x02: | ||
| 1334 | product_str = "LSISAS1068E B1"; | ||
| 1335 | break; | ||
| 1336 | case 0x04: | ||
| 1337 | product_str = "LSISAS1068E B2"; | ||
| 1338 | break; | ||
| 1339 | case 0x08: | ||
| 1340 | product_str = "LSISAS1068E B3"; | ||
| 1341 | break; | ||
| 1342 | default: | ||
| 1343 | product_str = "LSISAS1068E"; | ||
| 1344 | break; | ||
| 1345 | } | ||
| 1346 | break; | ||
| 1347 | case MPI_MANUFACTPAGE_DEVID_SAS1078: | ||
| 1348 | switch (revision) | ||
| 1349 | { | ||
| 1350 | case 0x00: | ||
| 1351 | product_str = "LSISAS1078 A0"; | ||
| 1352 | break; | ||
| 1353 | case 0x01: | ||
| 1354 | product_str = "LSISAS1078 B0"; | ||
| 1355 | break; | ||
| 1356 | case 0x02: | ||
| 1357 | product_str = "LSISAS1078 C0"; | ||
| 1358 | break; | ||
| 1359 | case 0x03: | ||
| 1360 | product_str = "LSISAS1078 C1"; | ||
| 1361 | break; | ||
| 1362 | case 0x04: | ||
| 1363 | product_str = "LSISAS1078 C2"; | ||
| 1364 | break; | ||
| 1365 | default: | ||
| 1366 | product_str = "LSISAS1078"; | ||
| 1367 | break; | ||
| 1368 | } | ||
| 1369 | break; | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | out: | ||
| 1373 | if (product_str) | ||
| 1374 | sprintf(prod_name, "%s", product_str); | ||
| 1375 | } | ||
| 1376 | |||
| 1134 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1377 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 1135 | /** | 1378 | /** |
| 1136 | * mpt_attach - Install a PCI intelligent MPT adapter. | 1379 | * mpt_attach - Install a PCI intelligent MPT adapter. |
| @@ -1274,23 +1517,23 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1274 | ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; | 1517 | ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; |
| 1275 | } | 1518 | } |
| 1276 | 1519 | ||
| 1277 | if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) { | 1520 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); |
| 1278 | ioc->prod_name = "LSIFC909"; | 1521 | mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name); |
| 1279 | ioc->bus_type = FC; | 1522 | |
| 1280 | } | 1523 | switch (pdev->device) |
| 1281 | else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { | 1524 | { |
| 1282 | ioc->prod_name = "LSIFC929"; | 1525 | case MPI_MANUFACTPAGE_DEVICEID_FC939X: |
| 1283 | ioc->bus_type = FC; | 1526 | case MPI_MANUFACTPAGE_DEVICEID_FC949X: |
| 1284 | } | 1527 | ioc->errata_flag_1064 = 1; |
| 1285 | else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) { | 1528 | case MPI_MANUFACTPAGE_DEVICEID_FC909: |
| 1286 | ioc->prod_name = "LSIFC919"; | 1529 | case MPI_MANUFACTPAGE_DEVICEID_FC929: |
| 1287 | ioc->bus_type = FC; | 1530 | case MPI_MANUFACTPAGE_DEVICEID_FC919: |
| 1288 | } | 1531 | case MPI_MANUFACTPAGE_DEVICEID_FC949E: |
| 1289 | else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) { | ||
| 1290 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); | ||
| 1291 | ioc->bus_type = FC; | 1532 | ioc->bus_type = FC; |
| 1533 | break; | ||
| 1534 | |||
| 1535 | case MPI_MANUFACTPAGE_DEVICEID_FC929X: | ||
| 1292 | if (revision < XL_929) { | 1536 | if (revision < XL_929) { |
| 1293 | ioc->prod_name = "LSIFC929X"; | ||
| 1294 | /* 929X Chip Fix. Set Split transactions level | 1537 | /* 929X Chip Fix. Set Split transactions level |
| 1295 | * for PCIX. Set MOST bits to zero. | 1538 | * for PCIX. Set MOST bits to zero. |
| 1296 | */ | 1539 | */ |
| @@ -1298,75 +1541,46 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1298 | pcixcmd &= 0x8F; | 1541 | pcixcmd &= 0x8F; |
| 1299 | pci_write_config_byte(pdev, 0x6a, pcixcmd); | 1542 | pci_write_config_byte(pdev, 0x6a, pcixcmd); |
| 1300 | } else { | 1543 | } else { |
| 1301 | ioc->prod_name = "LSIFC929XL"; | ||
| 1302 | /* 929XL Chip Fix. Set MMRBC to 0x08. | 1544 | /* 929XL Chip Fix. Set MMRBC to 0x08. |
| 1303 | */ | 1545 | */ |
| 1304 | pci_read_config_byte(pdev, 0x6a, &pcixcmd); | 1546 | pci_read_config_byte(pdev, 0x6a, &pcixcmd); |
| 1305 | pcixcmd |= 0x08; | 1547 | pcixcmd |= 0x08; |
| 1306 | pci_write_config_byte(pdev, 0x6a, pcixcmd); | 1548 | pci_write_config_byte(pdev, 0x6a, pcixcmd); |
| 1307 | } | 1549 | } |
| 1308 | } | ||
| 1309 | else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) { | ||
| 1310 | ioc->prod_name = "LSIFC919X"; | ||
| 1311 | ioc->bus_type = FC; | 1550 | ioc->bus_type = FC; |
| 1551 | break; | ||
| 1552 | |||
| 1553 | case MPI_MANUFACTPAGE_DEVICEID_FC919X: | ||
| 1312 | /* 919X Chip Fix. Set Split transactions level | 1554 | /* 919X Chip Fix. Set Split transactions level |
| 1313 | * for PCIX. Set MOST bits to zero. | 1555 | * for PCIX. Set MOST bits to zero. |
| 1314 | */ | 1556 | */ |
| 1315 | pci_read_config_byte(pdev, 0x6a, &pcixcmd); | 1557 | pci_read_config_byte(pdev, 0x6a, &pcixcmd); |
| 1316 | pcixcmd &= 0x8F; | 1558 | pcixcmd &= 0x8F; |
| 1317 | pci_write_config_byte(pdev, 0x6a, pcixcmd); | 1559 | pci_write_config_byte(pdev, 0x6a, pcixcmd); |
| 1318 | } | ||
| 1319 | else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) { | ||
| 1320 | ioc->prod_name = "LSIFC939X"; | ||
| 1321 | ioc->bus_type = FC; | ||
| 1322 | ioc->errata_flag_1064 = 1; | ||
| 1323 | } | ||
| 1324 | else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) { | ||
| 1325 | ioc->prod_name = "LSIFC949X"; | ||
| 1326 | ioc->bus_type = FC; | 1560 | ioc->bus_type = FC; |
| 1327 | ioc->errata_flag_1064 = 1; | 1561 | break; |
| 1328 | } | 1562 | |
| 1329 | else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) { | 1563 | case MPI_MANUFACTPAGE_DEVID_53C1030: |
| 1330 | ioc->prod_name = "LSIFC949E"; | ||
| 1331 | ioc->bus_type = FC; | ||
| 1332 | } | ||
| 1333 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { | ||
| 1334 | ioc->prod_name = "LSI53C1030"; | ||
| 1335 | ioc->bus_type = SPI; | ||
| 1336 | /* 1030 Chip Fix. Disable Split transactions | 1564 | /* 1030 Chip Fix. Disable Split transactions |
| 1337 | * for PCIX. Set MOST bits to zero if Rev < C0( = 8). | 1565 | * for PCIX. Set MOST bits to zero if Rev < C0( = 8). |
| 1338 | */ | 1566 | */ |
| 1339 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); | ||
| 1340 | if (revision < C0_1030) { | 1567 | if (revision < C0_1030) { |
| 1341 | pci_read_config_byte(pdev, 0x6a, &pcixcmd); | 1568 | pci_read_config_byte(pdev, 0x6a, &pcixcmd); |
| 1342 | pcixcmd &= 0x8F; | 1569 | pcixcmd &= 0x8F; |
| 1343 | pci_write_config_byte(pdev, 0x6a, pcixcmd); | 1570 | pci_write_config_byte(pdev, 0x6a, pcixcmd); |
| 1344 | } | 1571 | } |
| 1345 | } | 1572 | |
| 1346 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { | 1573 | case MPI_MANUFACTPAGE_DEVID_1030_53C1035: |
| 1347 | ioc->prod_name = "LSI53C1035"; | ||
| 1348 | ioc->bus_type = SPI; | 1574 | ioc->bus_type = SPI; |
| 1349 | } | 1575 | break; |
| 1350 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) { | 1576 | |
| 1351 | ioc->prod_name = "LSISAS1064"; | 1577 | case MPI_MANUFACTPAGE_DEVID_SAS1064: |
| 1352 | ioc->bus_type = SAS; | 1578 | case MPI_MANUFACTPAGE_DEVID_SAS1068: |
| 1353 | ioc->errata_flag_1064 = 1; | ||
| 1354 | } | ||
| 1355 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) { | ||
| 1356 | ioc->prod_name = "LSISAS1068"; | ||
| 1357 | ioc->bus_type = SAS; | ||
| 1358 | ioc->errata_flag_1064 = 1; | 1579 | ioc->errata_flag_1064 = 1; |
| 1359 | } | 1580 | |
| 1360 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) { | 1581 | case MPI_MANUFACTPAGE_DEVID_SAS1064E: |
| 1361 | ioc->prod_name = "LSISAS1064E"; | 1582 | case MPI_MANUFACTPAGE_DEVID_SAS1068E: |
| 1362 | ioc->bus_type = SAS; | 1583 | case MPI_MANUFACTPAGE_DEVID_SAS1078: |
| 1363 | } | ||
| 1364 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) { | ||
| 1365 | ioc->prod_name = "LSISAS1068E"; | ||
| 1366 | ioc->bus_type = SAS; | ||
| 1367 | } | ||
| 1368 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { | ||
| 1369 | ioc->prod_name = "LSISAS1078"; | ||
| 1370 | ioc->bus_type = SAS; | 1584 | ioc->bus_type = SAS; |
| 1371 | } | 1585 | } |
| 1372 | 1586 | ||
| @@ -1880,6 +2094,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 1880 | } | 2094 | } |
| 1881 | 2095 | ||
| 1882 | GetIoUnitPage2(ioc); | 2096 | GetIoUnitPage2(ioc); |
| 2097 | mpt_get_manufacturing_pg_0(ioc); | ||
| 1883 | } | 2098 | } |
| 1884 | 2099 | ||
| 1885 | /* | 2100 | /* |
| @@ -2138,8 +2353,8 @@ MptDisplayIocCapabilities(MPT_ADAPTER *ioc) | |||
| 2138 | int i = 0; | 2353 | int i = 0; |
| 2139 | 2354 | ||
| 2140 | printk(KERN_INFO "%s: ", ioc->name); | 2355 | printk(KERN_INFO "%s: ", ioc->name); |
| 2141 | if (ioc->prod_name && strlen(ioc->prod_name) > 3) | 2356 | if (ioc->prod_name) |
| 2142 | printk("%s: ", ioc->prod_name+3); | 2357 | printk("%s: ", ioc->prod_name); |
| 2143 | printk("Capabilities={"); | 2358 | printk("Capabilities={"); |
| 2144 | 2359 | ||
| 2145 | if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { | 2360 | if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { |
| @@ -5190,6 +5405,49 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) | |||
| 5190 | return; | 5405 | return; |
| 5191 | } | 5406 | } |
| 5192 | 5407 | ||
| 5408 | static void | ||
| 5409 | mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc) | ||
| 5410 | { | ||
| 5411 | CONFIGPARMS cfg; | ||
| 5412 | ConfigPageHeader_t hdr; | ||
| 5413 | dma_addr_t buf_dma; | ||
| 5414 | ManufacturingPage0_t *pbuf = NULL; | ||
| 5415 | |||
| 5416 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
| 5417 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
| 5418 | |||
| 5419 | hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING; | ||
| 5420 | cfg.cfghdr.hdr = &hdr; | ||
| 5421 | cfg.physAddr = -1; | ||
| 5422 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 5423 | cfg.timeout = 10; | ||
| 5424 | |||
| 5425 | if (mpt_config(ioc, &cfg) != 0) | ||
| 5426 | goto out; | ||
| 5427 | |||
| 5428 | if (!cfg.cfghdr.hdr->PageLength) | ||
| 5429 | goto out; | ||
| 5430 | |||
| 5431 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 5432 | pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma); | ||
| 5433 | if (!pbuf) | ||
| 5434 | goto out; | ||
| 5435 | |||
| 5436 | cfg.physAddr = buf_dma; | ||
| 5437 | |||
| 5438 | if (mpt_config(ioc, &cfg) != 0) | ||
| 5439 | goto out; | ||
| 5440 | |||
| 5441 | memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name)); | ||
| 5442 | memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly)); | ||
| 5443 | memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer)); | ||
| 5444 | |||
| 5445 | out: | ||
| 5446 | |||
| 5447 | if (pbuf) | ||
| 5448 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma); | ||
| 5449 | } | ||
| 5450 | |||
| 5193 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 5451 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 5194 | /** | 5452 | /** |
| 5195 | * SendEventNotification - Send EventNotification (on or off) request to adapter | 5453 | * SendEventNotification - Send EventNotification (on or off) request to adapter |
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 05eb6e528753..98eb9c688e17 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
| @@ -537,7 +537,14 @@ typedef struct _MPT_ADAPTER | |||
| 537 | int id; /* Unique adapter id N {0,1,2,...} */ | 537 | int id; /* Unique adapter id N {0,1,2,...} */ |
| 538 | int pci_irq; /* This irq */ | 538 | int pci_irq; /* This irq */ |
| 539 | char name[MPT_NAME_LENGTH]; /* "iocN" */ | 539 | char name[MPT_NAME_LENGTH]; /* "iocN" */ |
| 540 | char *prod_name; /* "LSIFC9x9" */ | 540 | char prod_name[MPT_NAME_LENGTH]; /* "LSIFC9x9" */ |
| 541 | char board_name[16]; | ||
| 542 | char board_assembly[16]; | ||
| 543 | char board_tracer[16]; | ||
| 544 | u16 nvdata_version_persistent; | ||
| 545 | u16 nvdata_version_default; | ||
| 546 | u8 io_missing_delay; | ||
| 547 | u8 device_missing_delay; | ||
| 541 | SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */ | 548 | SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */ |
| 542 | SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */ | 549 | SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */ |
| 543 | u8 bus_type; | 550 | u8 bus_type; |
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index b766445f19aa..f2ebaa9992fe 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
| @@ -130,6 +130,7 @@ static struct scsi_host_template mptfc_driver_template = { | |||
| 130 | .max_sectors = 8192, | 130 | .max_sectors = 8192, |
| 131 | .cmd_per_lun = 7, | 131 | .cmd_per_lun = 7, |
| 132 | .use_clustering = ENABLE_CLUSTERING, | 132 | .use_clustering = ENABLE_CLUSTERING, |
| 133 | .shost_attrs = mptscsih_host_attrs, | ||
| 133 | }; | 134 | }; |
| 134 | 135 | ||
| 135 | /**************************************************************************** | 136 | /**************************************************************************** |
| @@ -153,6 +154,8 @@ static struct pci_device_id mptfc_pci_table[] = { | |||
| 153 | PCI_ANY_ID, PCI_ANY_ID }, | 154 | PCI_ANY_ID, PCI_ANY_ID }, |
| 154 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E, | 155 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E, |
| 155 | PCI_ANY_ID, PCI_ANY_ID }, | 156 | PCI_ANY_ID, PCI_ANY_ID }, |
| 157 | { PCI_VENDOR_ID_BROCADE, MPI_MANUFACTPAGE_DEVICEID_FC949E, | ||
| 158 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 156 | {0} /* Terminating entry */ | 159 | {0} /* Terminating entry */ |
| 157 | }; | 160 | }; |
| 158 | MODULE_DEVICE_TABLE(pci, mptfc_pci_table); | 161 | MODULE_DEVICE_TABLE(pci, mptfc_pci_table); |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 9e5424e1871f..d50664640512 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
| @@ -1119,6 +1119,7 @@ static struct scsi_host_template mptsas_driver_template = { | |||
| 1119 | .max_sectors = 8192, | 1119 | .max_sectors = 8192, |
| 1120 | .cmd_per_lun = 7, | 1120 | .cmd_per_lun = 7, |
| 1121 | .use_clustering = ENABLE_CLUSTERING, | 1121 | .use_clustering = ENABLE_CLUSTERING, |
| 1122 | .shost_attrs = mptscsih_host_attrs, | ||
| 1122 | }; | 1123 | }; |
| 1123 | 1124 | ||
| 1124 | static int mptsas_get_linkerrors(struct sas_phy *phy) | 1125 | static int mptsas_get_linkerrors(struct sas_phy *phy) |
| @@ -1390,6 +1391,11 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) | |||
| 1390 | goto out_free_consistent; | 1391 | goto out_free_consistent; |
| 1391 | } | 1392 | } |
| 1392 | 1393 | ||
| 1394 | ioc->nvdata_version_persistent = | ||
| 1395 | le16_to_cpu(buffer->NvdataVersionPersistent); | ||
| 1396 | ioc->nvdata_version_default = | ||
| 1397 | le16_to_cpu(buffer->NvdataVersionDefault); | ||
| 1398 | |||
| 1393 | for (i = 0; i < port_info->num_phys; i++) { | 1399 | for (i = 0; i < port_info->num_phys; i++) { |
| 1394 | mptsas_print_phy_data(&buffer->PhyData[i]); | 1400 | mptsas_print_phy_data(&buffer->PhyData[i]); |
| 1395 | port_info->phy_info[i].phy_id = i; | 1401 | port_info->phy_info[i].phy_id = i; |
| @@ -1410,6 +1416,63 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) | |||
| 1410 | } | 1416 | } |
| 1411 | 1417 | ||
| 1412 | static int | 1418 | static int |
| 1419 | mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc) | ||
| 1420 | { | ||
| 1421 | ConfigExtendedPageHeader_t hdr; | ||
| 1422 | CONFIGPARMS cfg; | ||
| 1423 | SasIOUnitPage1_t *buffer; | ||
| 1424 | dma_addr_t dma_handle; | ||
| 1425 | int error; | ||
| 1426 | u16 device_missing_delay; | ||
| 1427 | |||
| 1428 | memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t)); | ||
| 1429 | memset(&cfg, 0, sizeof(CONFIGPARMS)); | ||
| 1430 | |||
| 1431 | cfg.cfghdr.ehdr = &hdr; | ||
| 1432 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 1433 | cfg.timeout = 10; | ||
| 1434 | cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | ||
| 1435 | cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
| 1436 | cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION; | ||
| 1437 | cfg.cfghdr.ehdr->PageNumber = 1; | ||
| 1438 | |||
| 1439 | error = mpt_config(ioc, &cfg); | ||
| 1440 | if (error) | ||
| 1441 | goto out; | ||
| 1442 | if (!hdr.ExtPageLength) { | ||
| 1443 | error = -ENXIO; | ||
| 1444 | goto out; | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
| 1448 | &dma_handle); | ||
| 1449 | if (!buffer) { | ||
| 1450 | error = -ENOMEM; | ||
| 1451 | goto out; | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | cfg.physAddr = dma_handle; | ||
| 1455 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1456 | |||
| 1457 | error = mpt_config(ioc, &cfg); | ||
| 1458 | if (error) | ||
| 1459 | goto out_free_consistent; | ||
| 1460 | |||
| 1461 | ioc->io_missing_delay = | ||
| 1462 | le16_to_cpu(buffer->IODeviceMissingDelay); | ||
| 1463 | device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay); | ||
| 1464 | ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ? | ||
| 1465 | (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 : | ||
| 1466 | device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK; | ||
| 1467 | |||
| 1468 | out_free_consistent: | ||
| 1469 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
| 1470 | buffer, dma_handle); | ||
| 1471 | out: | ||
| 1472 | return error; | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | static int | ||
| 1413 | mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, | 1476 | mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, |
| 1414 | u32 form, u32 form_specific) | 1477 | u32 form, u32 form_specific) |
| 1415 | { | 1478 | { |
| @@ -1990,6 +2053,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) | |||
| 1990 | if (error) | 2053 | if (error) |
| 1991 | goto out_free_port_info; | 2054 | goto out_free_port_info; |
| 1992 | 2055 | ||
| 2056 | mptsas_sas_io_unit_pg1(ioc); | ||
| 1993 | mutex_lock(&ioc->sas_topology_mutex); | 2057 | mutex_lock(&ioc->sas_topology_mutex); |
| 1994 | ioc->handle = hba->phy_info[0].handle; | 2058 | ioc->handle = hba->phy_info[0].handle; |
| 1995 | port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle); | 2059 | port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle); |
| @@ -3237,6 +3301,8 @@ static struct pci_driver mptsas_driver = { | |||
| 3237 | static int __init | 3301 | static int __init |
| 3238 | mptsas_init(void) | 3302 | mptsas_init(void) |
| 3239 | { | 3303 | { |
| 3304 | int error; | ||
| 3305 | |||
| 3240 | show_mptmod_ver(my_NAME, my_VERSION); | 3306 | show_mptmod_ver(my_NAME, my_VERSION); |
| 3241 | 3307 | ||
| 3242 | mptsas_transport_template = | 3308 | mptsas_transport_template = |
| @@ -3260,7 +3326,11 @@ mptsas_init(void) | |||
| 3260 | ": Registered for IOC reset notifications\n")); | 3326 | ": Registered for IOC reset notifications\n")); |
| 3261 | } | 3327 | } |
| 3262 | 3328 | ||
| 3263 | return pci_register_driver(&mptsas_driver); | 3329 | error = pci_register_driver(&mptsas_driver); |
| 3330 | if (error) | ||
| 3331 | sas_release_transport(mptsas_transport_template); | ||
| 3332 | |||
| 3333 | return error; | ||
| 3264 | } | 3334 | } |
| 3265 | 3335 | ||
| 3266 | static void __exit | 3336 | static void __exit |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index d35617376f87..fd3aa2619f42 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
| @@ -3187,6 +3187,159 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | |||
| 3187 | mptscsih_do_cmd(hd, &iocmd); | 3187 | mptscsih_do_cmd(hd, &iocmd); |
| 3188 | } | 3188 | } |
| 3189 | 3189 | ||
| 3190 | static ssize_t | ||
| 3191 | mptscsih_version_fw_show(struct class_device *cdev, char *buf) | ||
| 3192 | { | ||
| 3193 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3194 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3195 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3196 | |||
| 3197 | return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", | ||
| 3198 | (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, | ||
| 3199 | (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, | ||
| 3200 | (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, | ||
| 3201 | ioc->facts.FWVersion.Word & 0x000000FF); | ||
| 3202 | } | ||
| 3203 | static CLASS_DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL); | ||
| 3204 | |||
| 3205 | static ssize_t | ||
| 3206 | mptscsih_version_bios_show(struct class_device *cdev, char *buf) | ||
| 3207 | { | ||
| 3208 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3209 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3210 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3211 | |||
| 3212 | return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", | ||
| 3213 | (ioc->biosVersion & 0xFF000000) >> 24, | ||
| 3214 | (ioc->biosVersion & 0x00FF0000) >> 16, | ||
| 3215 | (ioc->biosVersion & 0x0000FF00) >> 8, | ||
| 3216 | ioc->biosVersion & 0x000000FF); | ||
| 3217 | } | ||
| 3218 | static CLASS_DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL); | ||
| 3219 | |||
| 3220 | static ssize_t | ||
| 3221 | mptscsih_version_mpi_show(struct class_device *cdev, char *buf) | ||
| 3222 | { | ||
| 3223 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3224 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3225 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3226 | |||
| 3227 | return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion); | ||
| 3228 | } | ||
| 3229 | static CLASS_DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL); | ||
| 3230 | |||
| 3231 | static ssize_t | ||
| 3232 | mptscsih_version_product_show(struct class_device *cdev, char *buf) | ||
| 3233 | { | ||
| 3234 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3235 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3236 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3237 | |||
| 3238 | return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name); | ||
| 3239 | } | ||
| 3240 | static CLASS_DEVICE_ATTR(version_product, S_IRUGO, | ||
| 3241 | mptscsih_version_product_show, NULL); | ||
| 3242 | |||
| 3243 | static ssize_t | ||
| 3244 | mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf) | ||
| 3245 | { | ||
| 3246 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3247 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3248 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3249 | |||
| 3250 | return snprintf(buf, PAGE_SIZE, "%02xh\n", | ||
| 3251 | ioc->nvdata_version_persistent); | ||
| 3252 | } | ||
| 3253 | static CLASS_DEVICE_ATTR(version_nvdata_persistent, S_IRUGO, | ||
| 3254 | mptscsih_version_nvdata_persistent_show, NULL); | ||
| 3255 | |||
| 3256 | static ssize_t | ||
| 3257 | mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf) | ||
| 3258 | { | ||
| 3259 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3260 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3261 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3262 | |||
| 3263 | return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default); | ||
| 3264 | } | ||
| 3265 | static CLASS_DEVICE_ATTR(version_nvdata_default, S_IRUGO, | ||
| 3266 | mptscsih_version_nvdata_default_show, NULL); | ||
| 3267 | |||
| 3268 | static ssize_t | ||
| 3269 | mptscsih_board_name_show(struct class_device *cdev, char *buf) | ||
| 3270 | { | ||
| 3271 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3272 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3273 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3274 | |||
| 3275 | return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name); | ||
| 3276 | } | ||
| 3277 | static CLASS_DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL); | ||
| 3278 | |||
| 3279 | static ssize_t | ||
| 3280 | mptscsih_board_assembly_show(struct class_device *cdev, char *buf) | ||
| 3281 | { | ||
| 3282 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3283 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3284 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3285 | |||
| 3286 | return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly); | ||
| 3287 | } | ||
| 3288 | static CLASS_DEVICE_ATTR(board_assembly, S_IRUGO, | ||
| 3289 | mptscsih_board_assembly_show, NULL); | ||
| 3290 | |||
| 3291 | static ssize_t | ||
| 3292 | mptscsih_board_tracer_show(struct class_device *cdev, char *buf) | ||
| 3293 | { | ||
| 3294 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3295 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3296 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3297 | |||
| 3298 | return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer); | ||
| 3299 | } | ||
| 3300 | static CLASS_DEVICE_ATTR(board_tracer, S_IRUGO, | ||
| 3301 | mptscsih_board_tracer_show, NULL); | ||
| 3302 | |||
| 3303 | static ssize_t | ||
| 3304 | mptscsih_io_delay_show(struct class_device *cdev, char *buf) | ||
| 3305 | { | ||
| 3306 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3307 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3308 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3309 | |||
| 3310 | return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); | ||
| 3311 | } | ||
| 3312 | static CLASS_DEVICE_ATTR(io_delay, S_IRUGO, | ||
| 3313 | mptscsih_io_delay_show, NULL); | ||
| 3314 | |||
| 3315 | static ssize_t | ||
| 3316 | mptscsih_device_delay_show(struct class_device *cdev, char *buf) | ||
| 3317 | { | ||
| 3318 | struct Scsi_Host *host = class_to_shost(cdev); | ||
| 3319 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 3320 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 3321 | |||
| 3322 | return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); | ||
| 3323 | } | ||
| 3324 | static CLASS_DEVICE_ATTR(device_delay, S_IRUGO, | ||
| 3325 | mptscsih_device_delay_show, NULL); | ||
| 3326 | |||
| 3327 | struct class_device_attribute *mptscsih_host_attrs[] = { | ||
| 3328 | &class_device_attr_version_fw, | ||
| 3329 | &class_device_attr_version_bios, | ||
| 3330 | &class_device_attr_version_mpi, | ||
| 3331 | &class_device_attr_version_product, | ||
| 3332 | &class_device_attr_version_nvdata_persistent, | ||
| 3333 | &class_device_attr_version_nvdata_default, | ||
| 3334 | &class_device_attr_board_name, | ||
| 3335 | &class_device_attr_board_assembly, | ||
| 3336 | &class_device_attr_board_tracer, | ||
| 3337 | &class_device_attr_io_delay, | ||
| 3338 | &class_device_attr_device_delay, | ||
| 3339 | NULL, | ||
| 3340 | }; | ||
| 3341 | EXPORT_SYMBOL(mptscsih_host_attrs); | ||
| 3342 | |||
| 3190 | EXPORT_SYMBOL(mptscsih_remove); | 3343 | EXPORT_SYMBOL(mptscsih_remove); |
| 3191 | EXPORT_SYMBOL(mptscsih_shutdown); | 3344 | EXPORT_SYMBOL(mptscsih_shutdown); |
| 3192 | #ifdef CONFIG_PM | 3345 | #ifdef CONFIG_PM |
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 8eccdfe5701a..67b088db2f10 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h | |||
| @@ -129,3 +129,4 @@ extern void mptscsih_timer_expired(unsigned long data); | |||
| 129 | extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); | 129 | extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); |
| 130 | extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); | 130 | extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); |
| 131 | extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); | 131 | extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); |
| 132 | extern struct class_device_attribute *mptscsih_host_attrs[]; | ||
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 6b3e0c00952b..947fe2901800 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c | |||
| @@ -821,6 +821,7 @@ static struct scsi_host_template mptspi_driver_template = { | |||
| 821 | .max_sectors = 8192, | 821 | .max_sectors = 8192, |
| 822 | .cmd_per_lun = 7, | 822 | .cmd_per_lun = 7, |
| 823 | .use_clustering = ENABLE_CLUSTERING, | 823 | .use_clustering = ENABLE_CLUSTERING, |
| 824 | .shost_attrs = mptscsih_host_attrs, | ||
| 824 | }; | 825 | }; |
| 825 | 826 | ||
| 826 | static int mptspi_write_spi_device_pg1(struct scsi_target *starget, | 827 | static int mptspi_write_spi_device_pg1(struct scsi_target *starget, |
| @@ -1523,6 +1524,8 @@ static struct pci_driver mptspi_driver = { | |||
| 1523 | static int __init | 1524 | static int __init |
| 1524 | mptspi_init(void) | 1525 | mptspi_init(void) |
| 1525 | { | 1526 | { |
| 1527 | int error; | ||
| 1528 | |||
| 1526 | show_mptmod_ver(my_NAME, my_VERSION); | 1529 | show_mptmod_ver(my_NAME, my_VERSION); |
| 1527 | 1530 | ||
| 1528 | mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions); | 1531 | mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions); |
| @@ -1543,7 +1546,11 @@ mptspi_init(void) | |||
| 1543 | ": Registered for IOC reset notifications\n")); | 1546 | ": Registered for IOC reset notifications\n")); |
| 1544 | } | 1547 | } |
| 1545 | 1548 | ||
| 1546 | return pci_register_driver(&mptspi_driver); | 1549 | error = pci_register_driver(&mptspi_driver); |
| 1550 | if (error) | ||
| 1551 | spi_release_transport(mptspi_transport_template); | ||
| 1552 | |||
| 1553 | return error; | ||
| 1547 | } | 1554 | } |
| 1548 | 1555 | ||
| 1549 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1556 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1d516f24ba53..aaaa61ea4217 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -150,6 +150,7 @@ config THINKPAD_ACPI | |||
| 150 | depends on X86 && ACPI | 150 | depends on X86 && ACPI |
| 151 | select BACKLIGHT_CLASS_DEVICE | 151 | select BACKLIGHT_CLASS_DEVICE |
| 152 | select HWMON | 152 | select HWMON |
| 153 | select NVRAM | ||
| 153 | ---help--- | 154 | ---help--- |
| 154 | This is a driver for the IBM and Lenovo ThinkPad laptops. It adds | 155 | This is a driver for the IBM and Lenovo ThinkPad laptops. It adds |
| 155 | support for Fn-Fx key combinations, Bluetooth control, video | 156 | support for Fn-Fx key combinations, Bluetooth control, video |
| @@ -196,4 +197,17 @@ config THINKPAD_ACPI_BAY | |||
| 196 | 197 | ||
| 197 | If you are not sure, say Y here. | 198 | If you are not sure, say Y here. |
| 198 | 199 | ||
| 200 | config THINKPAD_ACPI_INPUT_ENABLED | ||
| 201 | bool "Enable input layer support by default" | ||
| 202 | depends on THINKPAD_ACPI | ||
| 203 | default y | ||
| 204 | ---help--- | ||
| 205 | Enables hot key handling over the input layer by default. If unset, | ||
| 206 | the driver does not enable any hot key handling by default, and also | ||
| 207 | starts up with a mostly empty keymap. | ||
| 208 | |||
| 209 | If you are not sure, say Y here. Say N to retain the deprecated | ||
| 210 | behavior of ibm-acpi, and thinkpad-acpi for kernels up to 2.6.21. | ||
| 211 | |||
| 212 | |||
| 199 | endif # MISC_DEVICES | 213 | endif # MISC_DEVICES |
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 9623eaf4f89f..303e48ca0e8a 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
| @@ -142,43 +142,124 @@ struct sony_laptop_keypress { | |||
| 142 | int key; | 142 | int key; |
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | /* Correspondance table between sonypi events and input layer events */ | 145 | /* Correspondance table between sonypi events |
| 146 | static struct { | 146 | * and input layer indexes in the keymap |
| 147 | int sonypiev; | 147 | */ |
| 148 | int inputev; | 148 | static int sony_laptop_input_index[] = { |
| 149 | } sony_laptop_inputkeys[] = { | 149 | -1, /* no event */ |
| 150 | { SONYPI_EVENT_CAPTURE_PRESSED, KEY_CAMERA }, | 150 | -1, /* SONYPI_EVENT_JOGDIAL_DOWN */ |
| 151 | { SONYPI_EVENT_FNKEY_ONLY, KEY_FN }, | 151 | -1, /* SONYPI_EVENT_JOGDIAL_UP */ |
| 152 | { SONYPI_EVENT_FNKEY_ESC, KEY_FN_ESC }, | 152 | -1, /* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ |
| 153 | { SONYPI_EVENT_FNKEY_F1, KEY_FN_F1 }, | 153 | -1, /* SONYPI_EVENT_JOGDIAL_UP_PRESSED */ |
| 154 | { SONYPI_EVENT_FNKEY_F2, KEY_FN_F2 }, | 154 | -1, /* SONYPI_EVENT_JOGDIAL_PRESSED */ |
| 155 | { SONYPI_EVENT_FNKEY_F3, KEY_FN_F3 }, | 155 | -1, /* SONYPI_EVENT_JOGDIAL_RELEASED */ |
| 156 | { SONYPI_EVENT_FNKEY_F4, KEY_FN_F4 }, | 156 | 0, /* SONYPI_EVENT_CAPTURE_PRESSED */ |
| 157 | { SONYPI_EVENT_FNKEY_F5, KEY_FN_F5 }, | 157 | 1, /* SONYPI_EVENT_CAPTURE_RELEASED */ |
| 158 | { SONYPI_EVENT_FNKEY_F6, KEY_FN_F6 }, | 158 | 2, /* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ |
| 159 | { SONYPI_EVENT_FNKEY_F7, KEY_FN_F7 }, | 159 | 3, /* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ |
| 160 | { SONYPI_EVENT_FNKEY_F8, KEY_FN_F8 }, | 160 | 4, /* SONYPI_EVENT_FNKEY_ESC */ |
| 161 | { SONYPI_EVENT_FNKEY_F9, KEY_FN_F9 }, | 161 | 5, /* SONYPI_EVENT_FNKEY_F1 */ |
| 162 | { SONYPI_EVENT_FNKEY_F10, KEY_FN_F10 }, | 162 | 6, /* SONYPI_EVENT_FNKEY_F2 */ |
| 163 | { SONYPI_EVENT_FNKEY_F11, KEY_FN_F11 }, | 163 | 7, /* SONYPI_EVENT_FNKEY_F3 */ |
| 164 | { SONYPI_EVENT_FNKEY_F12, KEY_FN_F12 }, | 164 | 8, /* SONYPI_EVENT_FNKEY_F4 */ |
| 165 | { SONYPI_EVENT_FNKEY_1, KEY_FN_1 }, | 165 | 9, /* SONYPI_EVENT_FNKEY_F5 */ |
| 166 | { SONYPI_EVENT_FNKEY_2, KEY_FN_2 }, | 166 | 10, /* SONYPI_EVENT_FNKEY_F6 */ |
| 167 | { SONYPI_EVENT_FNKEY_D, KEY_FN_D }, | 167 | 11, /* SONYPI_EVENT_FNKEY_F7 */ |
| 168 | { SONYPI_EVENT_FNKEY_E, KEY_FN_E }, | 168 | 12, /* SONYPI_EVENT_FNKEY_F8 */ |
| 169 | { SONYPI_EVENT_FNKEY_F, KEY_FN_F }, | 169 | 13, /* SONYPI_EVENT_FNKEY_F9 */ |
| 170 | { SONYPI_EVENT_FNKEY_S, KEY_FN_S }, | 170 | 14, /* SONYPI_EVENT_FNKEY_F10 */ |
| 171 | { SONYPI_EVENT_FNKEY_B, KEY_FN_B }, | 171 | 15, /* SONYPI_EVENT_FNKEY_F11 */ |
| 172 | { SONYPI_EVENT_BLUETOOTH_PRESSED, KEY_BLUE }, | 172 | 16, /* SONYPI_EVENT_FNKEY_F12 */ |
| 173 | { SONYPI_EVENT_BLUETOOTH_ON, KEY_BLUE }, | 173 | 17, /* SONYPI_EVENT_FNKEY_1 */ |
| 174 | { SONYPI_EVENT_PKEY_P1, KEY_PROG1 }, | 174 | 18, /* SONYPI_EVENT_FNKEY_2 */ |
| 175 | { SONYPI_EVENT_PKEY_P2, KEY_PROG2 }, | 175 | 19, /* SONYPI_EVENT_FNKEY_D */ |
| 176 | { SONYPI_EVENT_PKEY_P3, KEY_PROG3 }, | 176 | 20, /* SONYPI_EVENT_FNKEY_E */ |
| 177 | { SONYPI_EVENT_BACK_PRESSED, KEY_BACK }, | 177 | 21, /* SONYPI_EVENT_FNKEY_F */ |
| 178 | { SONYPI_EVENT_HELP_PRESSED, KEY_HELP }, | 178 | 22, /* SONYPI_EVENT_FNKEY_S */ |
| 179 | { SONYPI_EVENT_ZOOM_PRESSED, KEY_ZOOM }, | 179 | 23, /* SONYPI_EVENT_FNKEY_B */ |
| 180 | { SONYPI_EVENT_THUMBPHRASE_PRESSED, BTN_THUMB }, | 180 | 24, /* SONYPI_EVENT_BLUETOOTH_PRESSED */ |
| 181 | { 0, 0 }, | 181 | 25, /* SONYPI_EVENT_PKEY_P1 */ |
| 182 | 26, /* SONYPI_EVENT_PKEY_P2 */ | ||
| 183 | 27, /* SONYPI_EVENT_PKEY_P3 */ | ||
| 184 | 28, /* SONYPI_EVENT_BACK_PRESSED */ | ||
| 185 | -1, /* SONYPI_EVENT_LID_CLOSED */ | ||
| 186 | -1, /* SONYPI_EVENT_LID_OPENED */ | ||
| 187 | 29, /* SONYPI_EVENT_BLUETOOTH_ON */ | ||
| 188 | 30, /* SONYPI_EVENT_BLUETOOTH_OFF */ | ||
| 189 | 31, /* SONYPI_EVENT_HELP_PRESSED */ | ||
| 190 | 32, /* SONYPI_EVENT_FNKEY_ONLY */ | ||
| 191 | 33, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN */ | ||
| 192 | 34, /* SONYPI_EVENT_JOGDIAL_FAST_UP */ | ||
| 193 | 35, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ | ||
| 194 | 36, /* SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ | ||
| 195 | 37, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ | ||
| 196 | 38, /* SONYPI_EVENT_JOGDIAL_VFAST_UP */ | ||
| 197 | 39, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ | ||
| 198 | 40, /* SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ | ||
| 199 | 41, /* SONYPI_EVENT_ZOOM_PRESSED */ | ||
| 200 | 42, /* SONYPI_EVENT_THUMBPHRASE_PRESSED */ | ||
| 201 | 43, /* SONYPI_EVENT_MEYE_FACE */ | ||
| 202 | 44, /* SONYPI_EVENT_MEYE_OPPOSITE */ | ||
| 203 | 45, /* SONYPI_EVENT_MEMORYSTICK_INSERT */ | ||
| 204 | 46, /* SONYPI_EVENT_MEMORYSTICK_EJECT */ | ||
| 205 | -1, /* SONYPI_EVENT_ANYBUTTON_RELEASED */ | ||
| 206 | -1, /* SONYPI_EVENT_BATTERY_INSERT */ | ||
| 207 | -1, /* SONYPI_EVENT_BATTERY_REMOVE */ | ||
| 208 | -1, /* SONYPI_EVENT_FNKEY_RELEASED */ | ||
| 209 | 47, /* SONYPI_EVENT_WIRELESS_ON */ | ||
| 210 | 48, /* SONYPI_EVENT_WIRELESS_OFF */ | ||
| 211 | }; | ||
| 212 | |||
| 213 | static int sony_laptop_input_keycode_map[] = { | ||
| 214 | KEY_CAMERA, /* 0 SONYPI_EVENT_CAPTURE_PRESSED */ | ||
| 215 | KEY_RESERVED, /* 1 SONYPI_EVENT_CAPTURE_RELEASED */ | ||
| 216 | KEY_RESERVED, /* 2 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ | ||
| 217 | KEY_RESERVED, /* 3 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ | ||
| 218 | KEY_FN_ESC, /* 4 SONYPI_EVENT_FNKEY_ESC */ | ||
| 219 | KEY_FN_F1, /* 5 SONYPI_EVENT_FNKEY_F1 */ | ||
| 220 | KEY_FN_F2, /* 6 SONYPI_EVENT_FNKEY_F2 */ | ||
| 221 | KEY_FN_F3, /* 7 SONYPI_EVENT_FNKEY_F3 */ | ||
| 222 | KEY_FN_F4, /* 8 SONYPI_EVENT_FNKEY_F4 */ | ||
| 223 | KEY_FN_F5, /* 9 SONYPI_EVENT_FNKEY_F5 */ | ||
| 224 | KEY_FN_F6, /* 10 SONYPI_EVENT_FNKEY_F6 */ | ||
| 225 | KEY_FN_F7, /* 11 SONYPI_EVENT_FNKEY_F7 */ | ||
| 226 | KEY_FN_F8, /* 12 SONYPI_EVENT_FNKEY_F8 */ | ||
| 227 | KEY_FN_F9, /* 13 SONYPI_EVENT_FNKEY_F9 */ | ||
| 228 | KEY_FN_F10, /* 14 SONYPI_EVENT_FNKEY_F10 */ | ||
| 229 | KEY_FN_F11, /* 15 SONYPI_EVENT_FNKEY_F11 */ | ||
| 230 | KEY_FN_F12, /* 16 SONYPI_EVENT_FNKEY_F12 */ | ||
| 231 | KEY_FN_F1, /* 17 SONYPI_EVENT_FNKEY_1 */ | ||
| 232 | KEY_FN_F2, /* 18 SONYPI_EVENT_FNKEY_2 */ | ||
| 233 | KEY_FN_D, /* 19 SONYPI_EVENT_FNKEY_D */ | ||
| 234 | KEY_FN_E, /* 20 SONYPI_EVENT_FNKEY_E */ | ||
| 235 | KEY_FN_F, /* 21 SONYPI_EVENT_FNKEY_F */ | ||
| 236 | KEY_FN_S, /* 22 SONYPI_EVENT_FNKEY_S */ | ||
| 237 | KEY_FN_B, /* 23 SONYPI_EVENT_FNKEY_B */ | ||
| 238 | KEY_BLUETOOTH, /* 24 SONYPI_EVENT_BLUETOOTH_PRESSED */ | ||
| 239 | KEY_PROG1, /* 25 SONYPI_EVENT_PKEY_P1 */ | ||
| 240 | KEY_PROG2, /* 26 SONYPI_EVENT_PKEY_P2 */ | ||
| 241 | KEY_PROG3, /* 27 SONYPI_EVENT_PKEY_P3 */ | ||
| 242 | KEY_BACK, /* 28 SONYPI_EVENT_BACK_PRESSED */ | ||
| 243 | KEY_BLUETOOTH, /* 29 SONYPI_EVENT_BLUETOOTH_ON */ | ||
| 244 | KEY_BLUETOOTH, /* 30 SONYPI_EVENT_BLUETOOTH_OFF */ | ||
| 245 | KEY_HELP, /* 31 SONYPI_EVENT_HELP_PRESSED */ | ||
| 246 | KEY_FN, /* 32 SONYPI_EVENT_FNKEY_ONLY */ | ||
| 247 | KEY_RESERVED, /* 33 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ | ||
| 248 | KEY_RESERVED, /* 34 SONYPI_EVENT_JOGDIAL_FAST_UP */ | ||
| 249 | KEY_RESERVED, /* 35 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ | ||
| 250 | KEY_RESERVED, /* 36 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ | ||
| 251 | KEY_RESERVED, /* 37 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ | ||
| 252 | KEY_RESERVED, /* 38 SONYPI_EVENT_JOGDIAL_VFAST_UP */ | ||
| 253 | KEY_RESERVED, /* 39 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ | ||
| 254 | KEY_RESERVED, /* 40 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ | ||
| 255 | KEY_ZOOM, /* 41 SONYPI_EVENT_ZOOM_PRESSED */ | ||
| 256 | BTN_THUMB, /* 42 SONYPI_EVENT_THUMBPHRASE_PRESSED */ | ||
| 257 | KEY_RESERVED, /* 43 SONYPI_EVENT_MEYE_FACE */ | ||
| 258 | KEY_RESERVED, /* 44 SONYPI_EVENT_MEYE_OPPOSITE */ | ||
| 259 | KEY_RESERVED, /* 45 SONYPI_EVENT_MEMORYSTICK_INSERT */ | ||
| 260 | KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */ | ||
| 261 | KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ | ||
| 262 | KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ | ||
| 182 | }; | 263 | }; |
| 183 | 264 | ||
| 184 | /* release buttons after a short delay if pressed */ | 265 | /* release buttons after a short delay if pressed */ |
| @@ -202,7 +283,6 @@ static void sony_laptop_report_input_event(u8 event) | |||
| 202 | struct input_dev *jog_dev = sony_laptop_input.jog_dev; | 283 | struct input_dev *jog_dev = sony_laptop_input.jog_dev; |
| 203 | struct input_dev *key_dev = sony_laptop_input.key_dev; | 284 | struct input_dev *key_dev = sony_laptop_input.key_dev; |
| 204 | struct sony_laptop_keypress kp = { NULL }; | 285 | struct sony_laptop_keypress kp = { NULL }; |
| 205 | int i; | ||
| 206 | 286 | ||
| 207 | if (event == SONYPI_EVENT_FNKEY_RELEASED) { | 287 | if (event == SONYPI_EVENT_FNKEY_RELEASED) { |
| 208 | /* Nothing, not all VAIOs generate this event */ | 288 | /* Nothing, not all VAIOs generate this event */ |
| @@ -231,17 +311,22 @@ static void sony_laptop_report_input_event(u8 event) | |||
| 231 | break; | 311 | break; |
| 232 | 312 | ||
| 233 | default: | 313 | default: |
| 234 | for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) | 314 | if (event > ARRAY_SIZE (sony_laptop_input_keycode_map)) { |
| 235 | if (event == sony_laptop_inputkeys[i].sonypiev) { | 315 | dprintk("sony_laptop_report_input_event, event not known: %d\n", event); |
| 316 | break; | ||
| 317 | } | ||
| 318 | if (sony_laptop_input_index[event] != -1) { | ||
| 319 | kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]]; | ||
| 320 | if (kp.key != KEY_UNKNOWN) | ||
| 236 | kp.dev = key_dev; | 321 | kp.dev = key_dev; |
| 237 | kp.key = sony_laptop_inputkeys[i].inputev; | 322 | } |
| 238 | break; | ||
| 239 | } | ||
| 240 | break; | 323 | break; |
| 241 | } | 324 | } |
| 242 | 325 | ||
| 243 | if (kp.dev) { | 326 | if (kp.dev) { |
| 244 | input_report_key(kp.dev, kp.key, 1); | 327 | input_report_key(kp.dev, kp.key, 1); |
| 328 | /* we emit the scancode so we can always remap the key */ | ||
| 329 | input_event(kp.dev, EV_MSC, MSC_SCAN, event); | ||
| 245 | input_sync(kp.dev); | 330 | input_sync(kp.dev); |
| 246 | kfifo_put(sony_laptop_input.fifo, | 331 | kfifo_put(sony_laptop_input.fifo, |
| 247 | (unsigned char *)&kp, sizeof(kp)); | 332 | (unsigned char *)&kp, sizeof(kp)); |
| @@ -296,11 +381,18 @@ static int sony_laptop_setup_input(void) | |||
| 296 | key_dev->id.vendor = PCI_VENDOR_ID_SONY; | 381 | key_dev->id.vendor = PCI_VENDOR_ID_SONY; |
| 297 | 382 | ||
| 298 | /* Initialize the Input Drivers: special keys */ | 383 | /* Initialize the Input Drivers: special keys */ |
| 299 | key_dev->evbit[0] = BIT(EV_KEY); | 384 | set_bit(EV_KEY, key_dev->evbit); |
| 300 | for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) | 385 | set_bit(EV_MSC, key_dev->evbit); |
| 301 | if (sony_laptop_inputkeys[i].inputev) | 386 | set_bit(MSC_SCAN, key_dev->mscbit); |
| 302 | set_bit(sony_laptop_inputkeys[i].inputev, | 387 | key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); |
| 303 | key_dev->keybit); | 388 | key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); |
| 389 | key_dev->keycode = &sony_laptop_input_keycode_map; | ||
| 390 | for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { | ||
| 391 | if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { | ||
| 392 | set_bit(sony_laptop_input_keycode_map[i], | ||
| 393 | key_dev->keybit); | ||
| 394 | } | ||
| 395 | } | ||
| 304 | 396 | ||
| 305 | error = input_register_device(key_dev); | 397 | error = input_register_device(key_dev); |
| 306 | if (error) | 398 | if (error) |
| @@ -487,6 +579,14 @@ SNC_HANDLE_NAMES(audiopower_set, "AZPW"); | |||
| 487 | SNC_HANDLE_NAMES(lanpower_get, "GLNP"); | 579 | SNC_HANDLE_NAMES(lanpower_get, "GLNP"); |
| 488 | SNC_HANDLE_NAMES(lanpower_set, "LNPW"); | 580 | SNC_HANDLE_NAMES(lanpower_set, "LNPW"); |
| 489 | 581 | ||
| 582 | SNC_HANDLE_NAMES(lidstate_get, "GLID"); | ||
| 583 | |||
| 584 | SNC_HANDLE_NAMES(indicatorlamp_get, "GILS"); | ||
| 585 | SNC_HANDLE_NAMES(indicatorlamp_set, "SILS"); | ||
| 586 | |||
| 587 | SNC_HANDLE_NAMES(gainbass_get, "GMGB"); | ||
| 588 | SNC_HANDLE_NAMES(gainbass_set, "CMGB"); | ||
| 589 | |||
| 490 | SNC_HANDLE_NAMES(PID_get, "GPID"); | 590 | SNC_HANDLE_NAMES(PID_get, "GPID"); |
| 491 | 591 | ||
| 492 | SNC_HANDLE_NAMES(CTR_get, "GCTR"); | 592 | SNC_HANDLE_NAMES(CTR_get, "GCTR"); |
| @@ -507,6 +607,12 @@ static struct sony_nc_value sony_nc_values[] = { | |||
| 507 | boolean_validate, 0), | 607 | boolean_validate, 0), |
| 508 | SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set, | 608 | SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set, |
| 509 | boolean_validate, 1), | 609 | boolean_validate, 1), |
| 610 | SNC_HANDLE(lidstate, snc_lidstate_get, NULL, | ||
| 611 | boolean_validate, 0), | ||
| 612 | SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set, | ||
| 613 | boolean_validate, 0), | ||
| 614 | SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set, | ||
| 615 | boolean_validate, 0), | ||
| 510 | /* unknown methods */ | 616 | /* unknown methods */ |
| 511 | SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1), | 617 | SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1), |
| 512 | SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), | 618 | SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), |
| @@ -689,13 +795,116 @@ static struct backlight_ops sony_backlight_ops = { | |||
| 689 | }; | 795 | }; |
| 690 | 796 | ||
| 691 | /* | 797 | /* |
| 798 | * New SNC-only Vaios event mapping to driver known keys | ||
| 799 | */ | ||
| 800 | struct sony_nc_event { | ||
| 801 | u8 data; | ||
| 802 | u8 event; | ||
| 803 | }; | ||
| 804 | |||
| 805 | static struct sony_nc_event *sony_nc_events; | ||
| 806 | |||
| 807 | /* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence | ||
| 808 | * for Fn keys | ||
| 809 | */ | ||
| 810 | static int sony_nc_C_enable(struct dmi_system_id *id) | ||
| 811 | { | ||
| 812 | int result = 0; | ||
| 813 | |||
| 814 | printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); | ||
| 815 | |||
| 816 | sony_nc_events = id->driver_data; | ||
| 817 | |||
| 818 | if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 | ||
| 819 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 | ||
| 820 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 | ||
| 821 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 | ||
| 822 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 | ||
| 823 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { | ||
| 824 | printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " | ||
| 825 | "functionalities may be missing\n"); | ||
| 826 | return 1; | ||
| 827 | } | ||
| 828 | return 0; | ||
| 829 | } | ||
| 830 | |||
| 831 | static struct sony_nc_event sony_C_events[] = { | ||
| 832 | { 0x81, SONYPI_EVENT_FNKEY_F1 }, | ||
| 833 | { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 834 | { 0x85, SONYPI_EVENT_FNKEY_F5 }, | ||
| 835 | { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 836 | { 0x86, SONYPI_EVENT_FNKEY_F6 }, | ||
| 837 | { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 838 | { 0x87, SONYPI_EVENT_FNKEY_F7 }, | ||
| 839 | { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 840 | { 0x8A, SONYPI_EVENT_FNKEY_F10 }, | ||
| 841 | { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 842 | { 0x8C, SONYPI_EVENT_FNKEY_F12 }, | ||
| 843 | { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 844 | { 0, 0 }, | ||
| 845 | }; | ||
| 846 | |||
| 847 | /* SNC-only model map */ | ||
| 848 | struct dmi_system_id sony_nc_ids[] = { | ||
| 849 | { | ||
| 850 | .ident = "Sony Vaio FE Series", | ||
| 851 | .callback = sony_nc_C_enable, | ||
| 852 | .driver_data = sony_C_events, | ||
| 853 | .matches = { | ||
| 854 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
| 855 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), | ||
| 856 | }, | ||
| 857 | }, | ||
| 858 | { | ||
| 859 | .ident = "Sony Vaio C Series", | ||
| 860 | .callback = sony_nc_C_enable, | ||
| 861 | .driver_data = sony_C_events, | ||
| 862 | .matches = { | ||
| 863 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
| 864 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), | ||
| 865 | }, | ||
| 866 | }, | ||
| 867 | { } | ||
| 868 | }; | ||
| 869 | |||
| 870 | /* | ||
| 692 | * ACPI callbacks | 871 | * ACPI callbacks |
| 693 | */ | 872 | */ |
| 694 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) | 873 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) |
| 695 | { | 874 | { |
| 696 | dprintk("sony_acpi_notify, event: %d\n", event); | 875 | struct sony_nc_event *evmap; |
| 697 | sony_laptop_report_input_event(event); | 876 | u32 ev = event; |
| 698 | acpi_bus_generate_event(sony_nc_acpi_device, 1, event); | 877 | int result; |
| 878 | |||
| 879 | if (ev == 0x92) { | ||
| 880 | /* read the key pressed from EC.GECR | ||
| 881 | * A call to SN07 with 0x0202 will do it as well respecting | ||
| 882 | * the current protocol on different OSes | ||
| 883 | * | ||
| 884 | * Note: the path for GECR may be | ||
| 885 | * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) | ||
| 886 | * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) | ||
| 887 | * | ||
| 888 | * TODO: we may want to do the same for the older GHKE -need | ||
| 889 | * dmi list- so this snippet may become one more callback. | ||
| 890 | */ | ||
| 891 | if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) | ||
| 892 | dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); | ||
| 893 | else | ||
| 894 | ev = result & 0xFF; | ||
| 895 | } | ||
| 896 | |||
| 897 | if (sony_nc_events) | ||
| 898 | for (evmap = sony_nc_events; evmap->event; evmap++) { | ||
| 899 | if (evmap->data == ev) { | ||
| 900 | ev = evmap->event; | ||
| 901 | break; | ||
| 902 | } | ||
| 903 | } | ||
| 904 | |||
| 905 | dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); | ||
| 906 | sony_laptop_report_input_event(ev); | ||
| 907 | acpi_bus_generate_event(sony_nc_acpi_device, 1, ev); | ||
| 699 | } | 908 | } |
| 700 | 909 | ||
| 701 | static acpi_status sony_walk_callback(acpi_handle handle, u32 level, | 910 | static acpi_status sony_walk_callback(acpi_handle handle, u32 level, |
| @@ -732,6 +941,10 @@ static int sony_nc_resume(struct acpi_device *device) | |||
| 732 | break; | 941 | break; |
| 733 | } | 942 | } |
| 734 | } | 943 | } |
| 944 | |||
| 945 | /* re-initialize models with specific requirements */ | ||
| 946 | dmi_check_system(sony_nc_ids); | ||
| 947 | |||
| 735 | return 0; | 948 | return 0; |
| 736 | } | 949 | } |
| 737 | 950 | ||
| @@ -750,6 +963,15 @@ static int sony_nc_add(struct acpi_device *device) | |||
| 750 | 963 | ||
| 751 | sony_nc_acpi_handle = device->handle; | 964 | sony_nc_acpi_handle = device->handle; |
| 752 | 965 | ||
| 966 | /* read device status */ | ||
| 967 | result = acpi_bus_get_status(device); | ||
| 968 | /* bail IFF the above call was successful and the device is not present */ | ||
| 969 | if (!result && !device->status.present) { | ||
| 970 | dprintk("Device not present\n"); | ||
| 971 | result = -ENODEV; | ||
| 972 | goto outwalk; | ||
| 973 | } | ||
| 974 | |||
| 753 | if (debug) { | 975 | if (debug) { |
| 754 | status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, | 976 | status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, |
| 755 | 1, sony_walk_callback, NULL, NULL); | 977 | 1, sony_walk_callback, NULL, NULL); |
| @@ -760,6 +982,15 @@ static int sony_nc_add(struct acpi_device *device) | |||
| 760 | } | 982 | } |
| 761 | } | 983 | } |
| 762 | 984 | ||
| 985 | /* try to _INI the device if such method exists (ACPI spec 3.0-6.5.1 | ||
| 986 | * should be respected as we already checked for the device presence above */ | ||
| 987 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, METHOD_NAME__INI, &handle))) { | ||
| 988 | dprintk("Invoking _INI\n"); | ||
| 989 | if (ACPI_FAILURE(acpi_evaluate_object(sony_nc_acpi_handle, METHOD_NAME__INI, | ||
| 990 | NULL, NULL))) | ||
| 991 | dprintk("_INI Method failed\n"); | ||
| 992 | } | ||
| 993 | |||
| 763 | /* setup input devices and helper fifo */ | 994 | /* setup input devices and helper fifo */ |
| 764 | result = sony_laptop_setup_input(); | 995 | result = sony_laptop_setup_input(); |
| 765 | if (result) { | 996 | if (result) { |
| @@ -772,7 +1003,7 @@ static int sony_nc_add(struct acpi_device *device) | |||
| 772 | ACPI_DEVICE_NOTIFY, | 1003 | ACPI_DEVICE_NOTIFY, |
| 773 | sony_acpi_notify, NULL); | 1004 | sony_acpi_notify, NULL); |
| 774 | if (ACPI_FAILURE(status)) { | 1005 | if (ACPI_FAILURE(status)) { |
| 775 | printk(KERN_WARNING DRV_PFX "unable to install notify handler\n"); | 1006 | printk(KERN_WARNING DRV_PFX "unable to install notify handler (%u)\n", status); |
| 776 | result = -ENODEV; | 1007 | result = -ENODEV; |
| 777 | goto outinput; | 1008 | goto outinput; |
| 778 | } | 1009 | } |
| @@ -795,6 +1026,9 @@ static int sony_nc_add(struct acpi_device *device) | |||
| 795 | 1026 | ||
| 796 | } | 1027 | } |
| 797 | 1028 | ||
| 1029 | /* initialize models with specific requirements */ | ||
| 1030 | dmi_check_system(sony_nc_ids); | ||
| 1031 | |||
| 798 | result = sony_pf_add(); | 1032 | result = sony_pf_add(); |
| 799 | if (result) | 1033 | if (result) |
| 800 | goto outbacklight; | 1034 | goto outbacklight; |
| @@ -908,7 +1142,9 @@ static struct acpi_driver sony_nc_driver = { | |||
| 908 | #define SONYPI_DEVICE_TYPE2 0x00000002 | 1142 | #define SONYPI_DEVICE_TYPE2 0x00000002 |
| 909 | #define SONYPI_DEVICE_TYPE3 0x00000004 | 1143 | #define SONYPI_DEVICE_TYPE3 0x00000004 |
| 910 | 1144 | ||
| 911 | #define SONY_PIC_EV_MASK 0xff | 1145 | #define SONYPI_TYPE1_OFFSET 0x04 |
| 1146 | #define SONYPI_TYPE2_OFFSET 0x12 | ||
| 1147 | #define SONYPI_TYPE3_OFFSET 0x12 | ||
| 912 | 1148 | ||
| 913 | struct sony_pic_ioport { | 1149 | struct sony_pic_ioport { |
| 914 | struct acpi_resource_io io; | 1150 | struct acpi_resource_io io; |
| @@ -922,6 +1158,7 @@ struct sony_pic_irq { | |||
| 922 | 1158 | ||
| 923 | struct sony_pic_dev { | 1159 | struct sony_pic_dev { |
| 924 | int model; | 1160 | int model; |
| 1161 | u16 evport_offset; | ||
| 925 | u8 camera_power; | 1162 | u8 camera_power; |
| 926 | u8 bluetooth_power; | 1163 | u8 bluetooth_power; |
| 927 | u8 wwan_power; | 1164 | u8 wwan_power; |
| @@ -1999,20 +2236,17 @@ end: | |||
| 1999 | static irqreturn_t sony_pic_irq(int irq, void *dev_id) | 2236 | static irqreturn_t sony_pic_irq(int irq, void *dev_id) |
| 2000 | { | 2237 | { |
| 2001 | int i, j; | 2238 | int i, j; |
| 2002 | u32 port_val = 0; | ||
| 2003 | u8 ev = 0; | 2239 | u8 ev = 0; |
| 2004 | u8 data_mask = 0; | 2240 | u8 data_mask = 0; |
| 2005 | u8 device_event = 0; | 2241 | u8 device_event = 0; |
| 2006 | 2242 | ||
| 2007 | struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; | 2243 | struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; |
| 2008 | 2244 | ||
| 2009 | acpi_os_read_port(dev->cur_ioport->io.minimum, &port_val, | 2245 | ev = inb_p(dev->cur_ioport->io.minimum); |
| 2010 | dev->cur_ioport->io.address_length); | 2246 | data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset); |
| 2011 | ev = port_val & SONY_PIC_EV_MASK; | ||
| 2012 | data_mask = 0xff & (port_val >> (dev->cur_ioport->io.address_length - 8)); | ||
| 2013 | 2247 | ||
| 2014 | dprintk("event (0x%.8x [%.2x] [%.2x]) at port 0x%.4x\n", | 2248 | dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", |
| 2015 | port_val, ev, data_mask, dev->cur_ioport->io.minimum); | 2249 | ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset); |
| 2016 | 2250 | ||
| 2017 | if (ev == 0x00 || ev == 0xff) | 2251 | if (ev == 0x00 || ev == 0xff) |
| 2018 | return IRQ_HANDLED; | 2252 | return IRQ_HANDLED; |
| @@ -2103,6 +2337,20 @@ static int sony_pic_add(struct acpi_device *device) | |||
| 2103 | spic_dev.model = sony_pic_detect_device_type(); | 2337 | spic_dev.model = sony_pic_detect_device_type(); |
| 2104 | mutex_init(&spic_dev.lock); | 2338 | mutex_init(&spic_dev.lock); |
| 2105 | 2339 | ||
| 2340 | /* model specific characteristics */ | ||
| 2341 | switch(spic_dev.model) { | ||
| 2342 | case SONYPI_DEVICE_TYPE1: | ||
| 2343 | spic_dev.evport_offset = SONYPI_TYPE1_OFFSET; | ||
| 2344 | break; | ||
| 2345 | case SONYPI_DEVICE_TYPE3: | ||
| 2346 | spic_dev.evport_offset = SONYPI_TYPE3_OFFSET; | ||
| 2347 | break; | ||
| 2348 | case SONYPI_DEVICE_TYPE2: | ||
| 2349 | default: | ||
| 2350 | spic_dev.evport_offset = SONYPI_TYPE2_OFFSET; | ||
| 2351 | break; | ||
| 2352 | } | ||
| 2353 | |||
| 2106 | /* read _PRS resources */ | 2354 | /* read _PRS resources */ |
| 2107 | result = sony_pic_possible_resources(device); | 2355 | result = sony_pic_possible_resources(device); |
| 2108 | if (result) { | 2356 | if (result) { |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 95c0b96e83f2..f15a58f7403f 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -21,8 +21,8 @@ | |||
| 21 | * 02110-1301, USA. | 21 | * 02110-1301, USA. |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #define IBM_VERSION "0.14" | 24 | #define IBM_VERSION "0.15" |
| 25 | #define TPACPI_SYSFS_VERSION 0x000100 | 25 | #define TPACPI_SYSFS_VERSION 0x010000 |
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| 28 | * Changelog: | 28 | * Changelog: |
| @@ -92,6 +92,29 @@ MODULE_LICENSE("GPL"); | |||
| 92 | /* Please remove this in year 2009 */ | 92 | /* Please remove this in year 2009 */ |
| 93 | MODULE_ALIAS("ibm_acpi"); | 93 | MODULE_ALIAS("ibm_acpi"); |
| 94 | 94 | ||
| 95 | /* | ||
| 96 | * DMI matching for module autoloading | ||
| 97 | * | ||
| 98 | * See http://thinkwiki.org/wiki/List_of_DMI_IDs | ||
| 99 | * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads | ||
| 100 | * | ||
| 101 | * Only models listed in thinkwiki will be supported, so add yours | ||
| 102 | * if it is not there yet. | ||
| 103 | */ | ||
| 104 | #define IBM_BIOS_MODULE_ALIAS(__type) \ | ||
| 105 | MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") | ||
| 106 | |||
| 107 | /* Non-ancient thinkpads */ | ||
| 108 | MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); | ||
| 109 | MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); | ||
| 110 | |||
| 111 | /* Ancient thinkpad BIOSes have to be identified by | ||
| 112 | * BIOS type or model number, and there are far less | ||
| 113 | * BIOS types than model numbers... */ | ||
| 114 | IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]"); | ||
| 115 | IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); | ||
| 116 | IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); | ||
| 117 | |||
| 95 | #define __unused __attribute__ ((unused)) | 118 | #define __unused __attribute__ ((unused)) |
| 96 | 119 | ||
| 97 | /**************************************************************************** | 120 | /**************************************************************************** |
| @@ -106,7 +129,7 @@ MODULE_ALIAS("ibm_acpi"); | |||
| 106 | * ACPI basic handles | 129 | * ACPI basic handles |
| 107 | */ | 130 | */ |
| 108 | 131 | ||
| 109 | static acpi_handle root_handle = NULL; | 132 | static acpi_handle root_handle; |
| 110 | 133 | ||
| 111 | #define IBM_HANDLE(object, parent, paths...) \ | 134 | #define IBM_HANDLE(object, parent, paths...) \ |
| 112 | static acpi_handle object##_handle; \ | 135 | static acpi_handle object##_handle; \ |
| @@ -487,19 +510,36 @@ static char *next_cmd(char **cmds) | |||
| 487 | /**************************************************************************** | 510 | /**************************************************************************** |
| 488 | **************************************************************************** | 511 | **************************************************************************** |
| 489 | * | 512 | * |
| 490 | * Device model: hwmon and platform | 513 | * Device model: input, hwmon and platform |
| 491 | * | 514 | * |
| 492 | **************************************************************************** | 515 | **************************************************************************** |
| 493 | ****************************************************************************/ | 516 | ****************************************************************************/ |
| 494 | 517 | ||
| 495 | static struct platform_device *tpacpi_pdev = NULL; | 518 | static struct platform_device *tpacpi_pdev; |
| 496 | static struct class_device *tpacpi_hwmon = NULL; | 519 | static struct class_device *tpacpi_hwmon; |
| 520 | static struct input_dev *tpacpi_inputdev; | ||
| 521 | |||
| 522 | |||
| 523 | static int tpacpi_resume_handler(struct platform_device *pdev) | ||
| 524 | { | ||
| 525 | struct ibm_struct *ibm, *itmp; | ||
| 526 | |||
| 527 | list_for_each_entry_safe(ibm, itmp, | ||
| 528 | &tpacpi_all_drivers, | ||
| 529 | all_drivers) { | ||
| 530 | if (ibm->resume) | ||
| 531 | (ibm->resume)(); | ||
| 532 | } | ||
| 533 | |||
| 534 | return 0; | ||
| 535 | } | ||
| 497 | 536 | ||
| 498 | static struct platform_driver tpacpi_pdriver = { | 537 | static struct platform_driver tpacpi_pdriver = { |
| 499 | .driver = { | 538 | .driver = { |
| 500 | .name = IBM_DRVR_NAME, | 539 | .name = IBM_DRVR_NAME, |
| 501 | .owner = THIS_MODULE, | 540 | .owner = THIS_MODULE, |
| 502 | }, | 541 | }, |
| 542 | .resume = tpacpi_resume_handler, | ||
| 503 | }; | 543 | }; |
| 504 | 544 | ||
| 505 | 545 | ||
| @@ -677,9 +717,19 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) | |||
| 677 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); | 717 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); |
| 678 | printk(IBM_INFO "%s\n", IBM_URL); | 718 | printk(IBM_INFO "%s\n", IBM_URL); |
| 679 | 719 | ||
| 680 | if (ibm_thinkpad_ec_found) | 720 | printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n", |
| 681 | printk(IBM_INFO "ThinkPad EC firmware %s\n", | 721 | (thinkpad_id.bios_version_str) ? |
| 682 | ibm_thinkpad_ec_found); | 722 | thinkpad_id.bios_version_str : "unknown", |
| 723 | (thinkpad_id.ec_version_str) ? | ||
| 724 | thinkpad_id.ec_version_str : "unknown"); | ||
| 725 | |||
| 726 | if (thinkpad_id.vendor && thinkpad_id.model_str) | ||
| 727 | printk(IBM_INFO "%s %s\n", | ||
| 728 | (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? | ||
| 729 | "IBM" : ((thinkpad_id.vendor == | ||
| 730 | PCI_VENDOR_ID_LENOVO) ? | ||
| 731 | "Lenovo" : "Unknown vendor"), | ||
| 732 | thinkpad_id.model_str); | ||
| 683 | 733 | ||
| 684 | return 0; | 734 | return 0; |
| 685 | } | 735 | } |
| @@ -704,16 +754,28 @@ static struct ibm_struct thinkpad_acpi_driver_data = { | |||
| 704 | */ | 754 | */ |
| 705 | 755 | ||
| 706 | static int hotkey_orig_status; | 756 | static int hotkey_orig_status; |
| 707 | static int hotkey_orig_mask; | 757 | static u32 hotkey_orig_mask; |
| 758 | static u32 hotkey_all_mask; | ||
| 759 | static u32 hotkey_reserved_mask; | ||
| 760 | |||
| 761 | static u16 *hotkey_keycode_map; | ||
| 708 | 762 | ||
| 709 | static struct attribute_set *hotkey_dev_attributes = NULL; | 763 | static struct attribute_set *hotkey_dev_attributes; |
| 764 | |||
| 765 | static int hotkey_get_wlsw(int *status) | ||
| 766 | { | ||
| 767 | if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) | ||
| 768 | return -EIO; | ||
| 769 | return 0; | ||
| 770 | } | ||
| 710 | 771 | ||
| 711 | /* sysfs hotkey enable ------------------------------------------------- */ | 772 | /* sysfs hotkey enable ------------------------------------------------- */ |
| 712 | static ssize_t hotkey_enable_show(struct device *dev, | 773 | static ssize_t hotkey_enable_show(struct device *dev, |
| 713 | struct device_attribute *attr, | 774 | struct device_attribute *attr, |
| 714 | char *buf) | 775 | char *buf) |
| 715 | { | 776 | { |
| 716 | int res, status, mask; | 777 | int res, status; |
| 778 | u32 mask; | ||
| 717 | 779 | ||
| 718 | res = hotkey_get(&status, &mask); | 780 | res = hotkey_get(&status, &mask); |
| 719 | if (res) | 781 | if (res) |
| @@ -727,7 +789,8 @@ static ssize_t hotkey_enable_store(struct device *dev, | |||
| 727 | const char *buf, size_t count) | 789 | const char *buf, size_t count) |
| 728 | { | 790 | { |
| 729 | unsigned long t; | 791 | unsigned long t; |
| 730 | int res, status, mask; | 792 | int res, status; |
| 793 | u32 mask; | ||
| 731 | 794 | ||
| 732 | if (parse_strtoul(buf, 1, &t)) | 795 | if (parse_strtoul(buf, 1, &t)) |
| 733 | return -EINVAL; | 796 | return -EINVAL; |
| @@ -748,13 +811,14 @@ static ssize_t hotkey_mask_show(struct device *dev, | |||
| 748 | struct device_attribute *attr, | 811 | struct device_attribute *attr, |
| 749 | char *buf) | 812 | char *buf) |
| 750 | { | 813 | { |
| 751 | int res, status, mask; | 814 | int res, status; |
| 815 | u32 mask; | ||
| 752 | 816 | ||
| 753 | res = hotkey_get(&status, &mask); | 817 | res = hotkey_get(&status, &mask); |
| 754 | if (res) | 818 | if (res) |
| 755 | return res; | 819 | return res; |
| 756 | 820 | ||
| 757 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", mask); | 821 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask); |
| 758 | } | 822 | } |
| 759 | 823 | ||
| 760 | static ssize_t hotkey_mask_store(struct device *dev, | 824 | static ssize_t hotkey_mask_store(struct device *dev, |
| @@ -762,9 +826,10 @@ static ssize_t hotkey_mask_store(struct device *dev, | |||
| 762 | const char *buf, size_t count) | 826 | const char *buf, size_t count) |
| 763 | { | 827 | { |
| 764 | unsigned long t; | 828 | unsigned long t; |
| 765 | int res, status, mask; | 829 | int res, status; |
| 830 | u32 mask; | ||
| 766 | 831 | ||
| 767 | if (parse_strtoul(buf, 0xffff, &t)) | 832 | if (parse_strtoul(buf, 0xffffffffUL, &t)) |
| 768 | return -EINVAL; | 833 | return -EINVAL; |
| 769 | 834 | ||
| 770 | res = hotkey_get(&status, &mask); | 835 | res = hotkey_get(&status, &mask); |
| @@ -794,26 +859,123 @@ static ssize_t hotkey_bios_mask_show(struct device *dev, | |||
| 794 | struct device_attribute *attr, | 859 | struct device_attribute *attr, |
| 795 | char *buf) | 860 | char *buf) |
| 796 | { | 861 | { |
| 797 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", hotkey_orig_mask); | 862 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); |
| 798 | } | 863 | } |
| 799 | 864 | ||
| 800 | static struct device_attribute dev_attr_hotkey_bios_mask = | 865 | static struct device_attribute dev_attr_hotkey_bios_mask = |
| 801 | __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL); | 866 | __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL); |
| 802 | 867 | ||
| 868 | /* sysfs hotkey all_mask ----------------------------------------------- */ | ||
| 869 | static ssize_t hotkey_all_mask_show(struct device *dev, | ||
| 870 | struct device_attribute *attr, | ||
| 871 | char *buf) | ||
| 872 | { | ||
| 873 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_all_mask); | ||
| 874 | } | ||
| 875 | |||
| 876 | static struct device_attribute dev_attr_hotkey_all_mask = | ||
| 877 | __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL); | ||
| 878 | |||
| 879 | /* sysfs hotkey recommended_mask --------------------------------------- */ | ||
| 880 | static ssize_t hotkey_recommended_mask_show(struct device *dev, | ||
| 881 | struct device_attribute *attr, | ||
| 882 | char *buf) | ||
| 883 | { | ||
| 884 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", | ||
| 885 | hotkey_all_mask & ~hotkey_reserved_mask); | ||
| 886 | } | ||
| 887 | |||
| 888 | static struct device_attribute dev_attr_hotkey_recommended_mask = | ||
| 889 | __ATTR(hotkey_recommended_mask, S_IRUGO, | ||
| 890 | hotkey_recommended_mask_show, NULL); | ||
| 891 | |||
| 892 | /* sysfs hotkey radio_sw ----------------------------------------------- */ | ||
| 893 | static ssize_t hotkey_radio_sw_show(struct device *dev, | ||
| 894 | struct device_attribute *attr, | ||
| 895 | char *buf) | ||
| 896 | { | ||
| 897 | int res, s; | ||
| 898 | res = hotkey_get_wlsw(&s); | ||
| 899 | if (res < 0) | ||
| 900 | return res; | ||
| 901 | |||
| 902 | return snprintf(buf, PAGE_SIZE, "%d\n", !!s); | ||
| 903 | } | ||
| 904 | |||
| 905 | static struct device_attribute dev_attr_hotkey_radio_sw = | ||
| 906 | __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL); | ||
| 907 | |||
| 803 | /* --------------------------------------------------------------------- */ | 908 | /* --------------------------------------------------------------------- */ |
| 804 | 909 | ||
| 805 | static struct attribute *hotkey_mask_attributes[] = { | 910 | static struct attribute *hotkey_mask_attributes[] = { |
| 806 | &dev_attr_hotkey_mask.attr, | 911 | &dev_attr_hotkey_mask.attr, |
| 807 | &dev_attr_hotkey_bios_enabled.attr, | 912 | &dev_attr_hotkey_bios_enabled.attr, |
| 808 | &dev_attr_hotkey_bios_mask.attr, | 913 | &dev_attr_hotkey_bios_mask.attr, |
| 914 | &dev_attr_hotkey_all_mask.attr, | ||
| 915 | &dev_attr_hotkey_recommended_mask.attr, | ||
| 809 | }; | 916 | }; |
| 810 | 917 | ||
| 811 | static int __init hotkey_init(struct ibm_init_struct *iibm) | 918 | static int __init hotkey_init(struct ibm_init_struct *iibm) |
| 812 | { | 919 | { |
| 813 | int res; | 920 | |
| 921 | static u16 ibm_keycode_map[] __initdata = { | ||
| 922 | /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ | ||
| 923 | KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP, | ||
| 924 | KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, | ||
| 925 | KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, | ||
| 926 | /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ | ||
| 927 | KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ | ||
| 928 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ | ||
| 929 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ | ||
| 930 | KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ | ||
| 931 | /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ | ||
| 932 | KEY_RESERVED, /* 0x10: FN+END (brightness down) */ | ||
| 933 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ | ||
| 934 | KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ | ||
| 935 | KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ | ||
| 936 | KEY_RESERVED, /* 0x14: VOLUME UP */ | ||
| 937 | KEY_RESERVED, /* 0x15: VOLUME DOWN */ | ||
| 938 | KEY_RESERVED, /* 0x16: MUTE */ | ||
| 939 | KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ | ||
| 940 | /* (assignments unknown, please report if found) */ | ||
| 941 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
| 942 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
| 943 | }; | ||
| 944 | static u16 lenovo_keycode_map[] __initdata = { | ||
| 945 | /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ | ||
| 946 | KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, | ||
| 947 | KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, | ||
| 948 | KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, | ||
| 949 | /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ | ||
| 950 | KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ | ||
| 951 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ | ||
| 952 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ | ||
| 953 | KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */ | ||
| 954 | /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ | ||
| 955 | KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */ | ||
| 956 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ | ||
| 957 | KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ | ||
| 958 | KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ | ||
| 959 | KEY_RESERVED, /* 0x14: VOLUME UP */ | ||
| 960 | KEY_RESERVED, /* 0x15: VOLUME DOWN */ | ||
| 961 | KEY_RESERVED, /* 0x16: MUTE */ | ||
| 962 | KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ | ||
| 963 | /* (assignments unknown, please report if found) */ | ||
| 964 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
| 965 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
| 966 | }; | ||
| 967 | |||
| 968 | #define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map) | ||
| 969 | #define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map) | ||
| 970 | #define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0]) | ||
| 971 | |||
| 972 | int res, i; | ||
| 973 | int status; | ||
| 814 | 974 | ||
| 815 | vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); | 975 | vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); |
| 816 | 976 | ||
| 977 | BUG_ON(!tpacpi_inputdev); | ||
| 978 | |||
| 817 | IBM_ACPIHANDLE_INIT(hkey); | 979 | IBM_ACPIHANDLE_INIT(hkey); |
| 818 | mutex_init(&hotkey_mutex); | 980 | mutex_init(&hotkey_mutex); |
| 819 | 981 | ||
| @@ -824,7 +986,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 824 | str_supported(tp_features.hotkey)); | 986 | str_supported(tp_features.hotkey)); |
| 825 | 987 | ||
| 826 | if (tp_features.hotkey) { | 988 | if (tp_features.hotkey) { |
| 827 | hotkey_dev_attributes = create_attr_set(4, NULL); | 989 | hotkey_dev_attributes = create_attr_set(7, NULL); |
| 828 | if (!hotkey_dev_attributes) | 990 | if (!hotkey_dev_attributes) |
| 829 | return -ENOMEM; | 991 | return -ENOMEM; |
| 830 | res = add_to_attr_set(hotkey_dev_attributes, | 992 | res = add_to_attr_set(hotkey_dev_attributes, |
| @@ -840,19 +1002,92 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 840 | vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", | 1002 | vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", |
| 841 | str_supported(tp_features.hotkey_mask)); | 1003 | str_supported(tp_features.hotkey_mask)); |
| 842 | 1004 | ||
| 1005 | if (tp_features.hotkey_mask) { | ||
| 1006 | /* MHKA available in A31, R40, R40e, T4x, X31, and later */ | ||
| 1007 | if (!acpi_evalf(hkey_handle, &hotkey_all_mask, | ||
| 1008 | "MHKA", "qd")) | ||
| 1009 | hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */ | ||
| 1010 | } | ||
| 1011 | |||
| 843 | res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); | 1012 | res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); |
| 844 | if (!res && tp_features.hotkey_mask) { | 1013 | if (!res && tp_features.hotkey_mask) { |
| 845 | res = add_many_to_attr_set(hotkey_dev_attributes, | 1014 | res = add_many_to_attr_set(hotkey_dev_attributes, |
| 846 | hotkey_mask_attributes, | 1015 | hotkey_mask_attributes, |
| 847 | ARRAY_SIZE(hotkey_mask_attributes)); | 1016 | ARRAY_SIZE(hotkey_mask_attributes)); |
| 848 | } | 1017 | } |
| 1018 | |||
| 1019 | /* Not all thinkpads have a hardware radio switch */ | ||
| 1020 | if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { | ||
| 1021 | tp_features.hotkey_wlsw = 1; | ||
| 1022 | printk(IBM_INFO | ||
| 1023 | "radio switch found; radios are %s\n", | ||
| 1024 | enabled(status, 0)); | ||
| 1025 | res = add_to_attr_set(hotkey_dev_attributes, | ||
| 1026 | &dev_attr_hotkey_radio_sw.attr); | ||
| 1027 | } | ||
| 1028 | |||
| 849 | if (!res) | 1029 | if (!res) |
| 850 | res = register_attr_set_with_sysfs( | 1030 | res = register_attr_set_with_sysfs( |
| 851 | hotkey_dev_attributes, | 1031 | hotkey_dev_attributes, |
| 852 | &tpacpi_pdev->dev.kobj); | 1032 | &tpacpi_pdev->dev.kobj); |
| 1033 | if (res) | ||
| 1034 | return res; | ||
| 1035 | |||
| 1036 | /* Set up key map */ | ||
| 1037 | |||
| 1038 | hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, | ||
| 1039 | GFP_KERNEL); | ||
| 1040 | if (!hotkey_keycode_map) { | ||
| 1041 | printk(IBM_ERR "failed to allocate memory for key map\n"); | ||
| 1042 | return -ENOMEM; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { | ||
| 1046 | dbg_printk(TPACPI_DBG_INIT, | ||
| 1047 | "using Lenovo default hot key map\n"); | ||
| 1048 | memcpy(hotkey_keycode_map, &lenovo_keycode_map, | ||
| 1049 | TPACPI_HOTKEY_MAP_SIZE); | ||
| 1050 | } else { | ||
| 1051 | dbg_printk(TPACPI_DBG_INIT, | ||
| 1052 | "using IBM default hot key map\n"); | ||
| 1053 | memcpy(hotkey_keycode_map, &ibm_keycode_map, | ||
| 1054 | TPACPI_HOTKEY_MAP_SIZE); | ||
| 1055 | } | ||
| 853 | 1056 | ||
| 1057 | #ifndef CONFIG_THINKPAD_ACPI_INPUT_ENABLED | ||
| 1058 | for (i = 0; i < 12; i++) | ||
| 1059 | hotkey_keycode_map[i] = KEY_UNKNOWN; | ||
| 1060 | #endif /* ! CONFIG_THINKPAD_ACPI_INPUT_ENABLED */ | ||
| 1061 | |||
| 1062 | set_bit(EV_KEY, tpacpi_inputdev->evbit); | ||
| 1063 | set_bit(EV_MSC, tpacpi_inputdev->evbit); | ||
| 1064 | set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); | ||
| 1065 | tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; | ||
| 1066 | tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; | ||
| 1067 | tpacpi_inputdev->keycode = hotkey_keycode_map; | ||
| 1068 | for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { | ||
| 1069 | if (hotkey_keycode_map[i] != KEY_RESERVED) { | ||
| 1070 | set_bit(hotkey_keycode_map[i], | ||
| 1071 | tpacpi_inputdev->keybit); | ||
| 1072 | } else { | ||
| 1073 | if (i < sizeof(hotkey_reserved_mask)*8) | ||
| 1074 | hotkey_reserved_mask |= 1 << i; | ||
| 1075 | } | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | if (tp_features.hotkey_wlsw) { | ||
| 1079 | set_bit(EV_SW, tpacpi_inputdev->evbit); | ||
| 1080 | set_bit(SW_RADIO, tpacpi_inputdev->swbit); | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | #ifdef CONFIG_THINKPAD_ACPI_INPUT_ENABLED | ||
| 1084 | dbg_printk(TPACPI_DBG_INIT, | ||
| 1085 | "enabling hot key handling\n"); | ||
| 1086 | res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask) | ||
| 1087 | | hotkey_orig_mask); | ||
| 854 | if (res) | 1088 | if (res) |
| 855 | return res; | 1089 | return res; |
| 1090 | #endif /* CONFIG_THINKPAD_ACPI_INPUT_ENABLED */ | ||
| 856 | } | 1091 | } |
| 857 | 1092 | ||
| 858 | return (tp_features.hotkey)? 0 : 1; | 1093 | return (tp_features.hotkey)? 0 : 1; |
| @@ -875,22 +1110,101 @@ static void hotkey_exit(void) | |||
| 875 | } | 1110 | } |
| 876 | } | 1111 | } |
| 877 | 1112 | ||
| 1113 | static void tpacpi_input_send_key(unsigned int scancode, | ||
| 1114 | unsigned int keycode) | ||
| 1115 | { | ||
| 1116 | if (keycode != KEY_RESERVED) { | ||
| 1117 | input_report_key(tpacpi_inputdev, keycode, 1); | ||
| 1118 | if (keycode == KEY_UNKNOWN) | ||
| 1119 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, | ||
| 1120 | scancode); | ||
| 1121 | input_sync(tpacpi_inputdev); | ||
| 1122 | |||
| 1123 | input_report_key(tpacpi_inputdev, keycode, 0); | ||
| 1124 | if (keycode == KEY_UNKNOWN) | ||
| 1125 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, | ||
| 1126 | scancode); | ||
| 1127 | input_sync(tpacpi_inputdev); | ||
| 1128 | } | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | static void tpacpi_input_send_radiosw(void) | ||
| 1132 | { | ||
| 1133 | int wlsw; | ||
| 1134 | |||
| 1135 | if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) | ||
| 1136 | input_report_switch(tpacpi_inputdev, | ||
| 1137 | SW_RADIO, !!wlsw); | ||
| 1138 | } | ||
| 1139 | |||
| 878 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) | 1140 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) |
| 879 | { | 1141 | { |
| 880 | int hkey; | 1142 | u32 hkey; |
| 1143 | unsigned int keycode, scancode; | ||
| 1144 | int sendacpi = 1; | ||
| 1145 | |||
| 1146 | if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { | ||
| 1147 | if (tpacpi_inputdev->users > 0) { | ||
| 1148 | switch (hkey >> 12) { | ||
| 1149 | case 1: | ||
| 1150 | /* 0x1000-0x1FFF: key presses */ | ||
| 1151 | scancode = hkey & 0xfff; | ||
| 1152 | if (scancode > 0 && scancode < 0x21) { | ||
| 1153 | scancode--; | ||
| 1154 | keycode = hotkey_keycode_map[scancode]; | ||
| 1155 | tpacpi_input_send_key(scancode, keycode); | ||
| 1156 | sendacpi = (keycode == KEY_RESERVED | ||
| 1157 | || keycode == KEY_UNKNOWN); | ||
| 1158 | } else { | ||
| 1159 | printk(IBM_ERR | ||
| 1160 | "hotkey 0x%04x out of range for keyboard map\n", | ||
| 1161 | hkey); | ||
| 1162 | } | ||
| 1163 | break; | ||
| 1164 | case 5: | ||
| 1165 | /* 0x5000-0x5FFF: LID */ | ||
| 1166 | /* we don't handle it through this path, just | ||
| 1167 | * eat up known LID events */ | ||
| 1168 | if (hkey != 0x5001 && hkey != 0x5002) { | ||
| 1169 | printk(IBM_ERR | ||
| 1170 | "unknown LID-related hotkey event: 0x%04x\n", | ||
| 1171 | hkey); | ||
| 1172 | } | ||
| 1173 | break; | ||
| 1174 | case 7: | ||
| 1175 | /* 0x7000-0x7FFF: misc */ | ||
| 1176 | if (tp_features.hotkey_wlsw && hkey == 0x7000) { | ||
| 1177 | tpacpi_input_send_radiosw(); | ||
| 1178 | sendacpi = 0; | ||
| 1179 | break; | ||
| 1180 | } | ||
| 1181 | /* fallthrough to default */ | ||
| 1182 | default: | ||
| 1183 | /* case 2: dock-related */ | ||
| 1184 | /* 0x2305 - T43 waking up due to bay lever eject while aslept */ | ||
| 1185 | /* case 3: ultra-bay related. maybe bay in dock? */ | ||
| 1186 | /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */ | ||
| 1187 | printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey); | ||
| 1188 | } | ||
| 1189 | } | ||
| 881 | 1190 | ||
| 882 | if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) | 1191 | if (sendacpi) |
| 883 | acpi_bus_generate_event(ibm->acpi->device, event, hkey); | 1192 | acpi_bus_generate_event(ibm->acpi->device, event, hkey); |
| 884 | else { | 1193 | } else { |
| 885 | printk(IBM_ERR "unknown hotkey event %d\n", event); | 1194 | printk(IBM_ERR "unknown hotkey notification event %d\n", event); |
| 886 | acpi_bus_generate_event(ibm->acpi->device, event, 0); | 1195 | acpi_bus_generate_event(ibm->acpi->device, event, 0); |
| 887 | } | 1196 | } |
| 888 | } | 1197 | } |
| 889 | 1198 | ||
| 1199 | static void hotkey_resume(void) | ||
| 1200 | { | ||
| 1201 | tpacpi_input_send_radiosw(); | ||
| 1202 | } | ||
| 1203 | |||
| 890 | /* | 1204 | /* |
| 891 | * Call with hotkey_mutex held | 1205 | * Call with hotkey_mutex held |
| 892 | */ | 1206 | */ |
| 893 | static int hotkey_get(int *status, int *mask) | 1207 | static int hotkey_get(int *status, u32 *mask) |
| 894 | { | 1208 | { |
| 895 | if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) | 1209 | if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) |
| 896 | return -EIO; | 1210 | return -EIO; |
| @@ -905,7 +1219,7 @@ static int hotkey_get(int *status, int *mask) | |||
| 905 | /* | 1219 | /* |
| 906 | * Call with hotkey_mutex held | 1220 | * Call with hotkey_mutex held |
| 907 | */ | 1221 | */ |
| 908 | static int hotkey_set(int status, int mask) | 1222 | static int hotkey_set(int status, u32 mask) |
| 909 | { | 1223 | { |
| 910 | int i; | 1224 | int i; |
| 911 | 1225 | ||
| @@ -926,7 +1240,8 @@ static int hotkey_set(int status, int mask) | |||
| 926 | /* procfs -------------------------------------------------------------- */ | 1240 | /* procfs -------------------------------------------------------------- */ |
| 927 | static int hotkey_read(char *p) | 1241 | static int hotkey_read(char *p) |
| 928 | { | 1242 | { |
| 929 | int res, status, mask; | 1243 | int res, status; |
| 1244 | u32 mask; | ||
| 930 | int len = 0; | 1245 | int len = 0; |
| 931 | 1246 | ||
| 932 | if (!tp_features.hotkey) { | 1247 | if (!tp_features.hotkey) { |
| @@ -944,7 +1259,7 @@ static int hotkey_read(char *p) | |||
| 944 | 1259 | ||
| 945 | len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); | 1260 | len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); |
| 946 | if (tp_features.hotkey_mask) { | 1261 | if (tp_features.hotkey_mask) { |
| 947 | len += sprintf(p + len, "mask:\t\t0x%04x\n", mask); | 1262 | len += sprintf(p + len, "mask:\t\t0x%08x\n", mask); |
| 948 | len += sprintf(p + len, | 1263 | len += sprintf(p + len, |
| 949 | "commands:\tenable, disable, reset, <mask>\n"); | 1264 | "commands:\tenable, disable, reset, <mask>\n"); |
| 950 | } else { | 1265 | } else { |
| @@ -957,7 +1272,8 @@ static int hotkey_read(char *p) | |||
| 957 | 1272 | ||
| 958 | static int hotkey_write(char *buf) | 1273 | static int hotkey_write(char *buf) |
| 959 | { | 1274 | { |
| 960 | int res, status, mask; | 1275 | int res, status; |
| 1276 | u32 mask; | ||
| 961 | char *cmd; | 1277 | char *cmd; |
| 962 | int do_cmd = 0; | 1278 | int do_cmd = 0; |
| 963 | 1279 | ||
| @@ -1012,6 +1328,7 @@ static struct ibm_struct hotkey_driver_data = { | |||
| 1012 | .read = hotkey_read, | 1328 | .read = hotkey_read, |
| 1013 | .write = hotkey_write, | 1329 | .write = hotkey_write, |
| 1014 | .exit = hotkey_exit, | 1330 | .exit = hotkey_exit, |
| 1331 | .resume = hotkey_resume, | ||
| 1015 | .acpi = &ibm_hotkey_acpidriver, | 1332 | .acpi = &ibm_hotkey_acpidriver, |
| 1016 | }; | 1333 | }; |
| 1017 | 1334 | ||
| @@ -1770,7 +2087,10 @@ static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = { | |||
| 1770 | .type = ACPI_SYSTEM_NOTIFY, | 2087 | .type = ACPI_SYSTEM_NOTIFY, |
| 1771 | }, | 2088 | }, |
| 1772 | { | 2089 | { |
| 1773 | .hid = IBM_PCI_HID, | 2090 | /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING. |
| 2091 | * We just use it to get notifications of dock hotplug | ||
| 2092 | * in very old thinkpads */ | ||
| 2093 | .hid = PCI_ROOT_HID_STRING, | ||
| 1774 | .notify = dock_notify, | 2094 | .notify = dock_notify, |
| 1775 | .handle = &pci_handle, | 2095 | .handle = &pci_handle, |
| 1776 | .type = ACPI_SYSTEM_NOTIFY, | 2096 | .type = ACPI_SYSTEM_NOTIFY, |
| @@ -1829,7 +2149,7 @@ static int __init dock_init2(struct ibm_init_struct *iibm) | |||
| 1829 | static void dock_notify(struct ibm_struct *ibm, u32 event) | 2149 | static void dock_notify(struct ibm_struct *ibm, u32 event) |
| 1830 | { | 2150 | { |
| 1831 | int docked = dock_docked(); | 2151 | int docked = dock_docked(); |
| 1832 | int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, IBM_PCI_HID); | 2152 | int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, PCI_ROOT_HID_STRING); |
| 1833 | 2153 | ||
| 1834 | if (event == 1 && !pci) /* 570 */ | 2154 | if (event == 1 && !pci) /* 570 */ |
| 1835 | acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ | 2155 | acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ |
| @@ -2389,7 +2709,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) | |||
| 2389 | 2709 | ||
| 2390 | acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); | 2710 | acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); |
| 2391 | 2711 | ||
| 2392 | if (ibm_thinkpad_ec_found && experimental) { | 2712 | if (thinkpad_id.ec_model) { |
| 2393 | /* | 2713 | /* |
| 2394 | * Direct EC access mode: sensors at registers | 2714 | * Direct EC access mode: sensors at registers |
| 2395 | * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for | 2715 | * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for |
| @@ -2533,6 +2853,8 @@ static int thermal_get_sensor(int idx, s32 *value) | |||
| 2533 | snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); | 2853 | snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); |
| 2534 | if (!acpi_evalf(ec_handle, &t, tmpi, "d")) | 2854 | if (!acpi_evalf(ec_handle, &t, tmpi, "d")) |
| 2535 | return -EIO; | 2855 | return -EIO; |
| 2856 | if (t > 127 || t < -127) | ||
| 2857 | t = TP_EC_THERMAL_TMP_NA; | ||
| 2536 | *value = t * 1000; | 2858 | *value = t * 1000; |
| 2537 | return 0; | 2859 | return 0; |
| 2538 | } | 2860 | } |
| @@ -2671,22 +2993,39 @@ static struct ibm_struct ecdump_driver_data = { | |||
| 2671 | * Backlight/brightness subdriver | 2993 | * Backlight/brightness subdriver |
| 2672 | */ | 2994 | */ |
| 2673 | 2995 | ||
| 2674 | static struct backlight_device *ibm_backlight_device = NULL; | 2996 | static struct backlight_device *ibm_backlight_device; |
| 2675 | 2997 | ||
| 2676 | static struct backlight_ops ibm_backlight_data = { | 2998 | static struct backlight_ops ibm_backlight_data = { |
| 2677 | .get_brightness = brightness_get, | 2999 | .get_brightness = brightness_get, |
| 2678 | .update_status = brightness_update_status, | 3000 | .update_status = brightness_update_status, |
| 2679 | }; | 3001 | }; |
| 2680 | 3002 | ||
| 3003 | static struct mutex brightness_mutex; | ||
| 3004 | |||
| 2681 | static int __init brightness_init(struct ibm_init_struct *iibm) | 3005 | static int __init brightness_init(struct ibm_init_struct *iibm) |
| 2682 | { | 3006 | { |
| 2683 | int b; | 3007 | int b; |
| 2684 | 3008 | ||
| 2685 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); | 3009 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); |
| 2686 | 3010 | ||
| 3011 | mutex_init(&brightness_mutex); | ||
| 3012 | |||
| 3013 | if (!brightness_mode) { | ||
| 3014 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) | ||
| 3015 | brightness_mode = 2; | ||
| 3016 | else | ||
| 3017 | brightness_mode = 3; | ||
| 3018 | |||
| 3019 | dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n", | ||
| 3020 | brightness_mode); | ||
| 3021 | } | ||
| 3022 | |||
| 3023 | if (brightness_mode > 3) | ||
| 3024 | return -EINVAL; | ||
| 3025 | |||
| 2687 | b = brightness_get(NULL); | 3026 | b = brightness_get(NULL); |
| 2688 | if (b < 0) | 3027 | if (b < 0) |
| 2689 | return b; | 3028 | return 1; |
| 2690 | 3029 | ||
| 2691 | ibm_backlight_device = backlight_device_register( | 3030 | ibm_backlight_device = backlight_device_register( |
| 2692 | TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, | 3031 | TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, |
| @@ -2722,34 +3061,79 @@ static int brightness_update_status(struct backlight_device *bd) | |||
| 2722 | bd->props.brightness : 0); | 3061 | bd->props.brightness : 0); |
| 2723 | } | 3062 | } |
| 2724 | 3063 | ||
| 3064 | /* | ||
| 3065 | * ThinkPads can read brightness from two places: EC 0x31, or | ||
| 3066 | * CMOS NVRAM byte 0x5E, bits 0-3. | ||
| 3067 | */ | ||
| 2725 | static int brightness_get(struct backlight_device *bd) | 3068 | static int brightness_get(struct backlight_device *bd) |
| 2726 | { | 3069 | { |
| 2727 | u8 level; | 3070 | u8 lec = 0, lcmos = 0, level = 0; |
| 2728 | if (!acpi_ec_read(brightness_offset, &level)) | ||
| 2729 | return -EIO; | ||
| 2730 | 3071 | ||
| 2731 | level &= 0x7; | 3072 | if (brightness_mode & 1) { |
| 3073 | if (!acpi_ec_read(brightness_offset, &lec)) | ||
| 3074 | return -EIO; | ||
| 3075 | lec &= 7; | ||
| 3076 | level = lec; | ||
| 3077 | }; | ||
| 3078 | if (brightness_mode & 2) { | ||
| 3079 | lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) | ||
| 3080 | & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) | ||
| 3081 | >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; | ||
| 3082 | level = lcmos; | ||
| 3083 | } | ||
| 3084 | |||
| 3085 | if (brightness_mode == 3 && lec != lcmos) { | ||
| 3086 | printk(IBM_ERR | ||
| 3087 | "CMOS NVRAM (%u) and EC (%u) do not agree " | ||
| 3088 | "on display brightness level\n", | ||
| 3089 | (unsigned int) lcmos, | ||
| 3090 | (unsigned int) lec); | ||
| 3091 | return -EIO; | ||
| 3092 | } | ||
| 2732 | 3093 | ||
| 2733 | return level; | 3094 | return level; |
| 2734 | } | 3095 | } |
| 2735 | 3096 | ||
| 2736 | static int brightness_set(int value) | 3097 | static int brightness_set(int value) |
| 2737 | { | 3098 | { |
| 2738 | int cmos_cmd, inc, i; | 3099 | int cmos_cmd, inc, i, res; |
| 2739 | int current_value = brightness_get(NULL); | 3100 | int current_value; |
| 3101 | |||
| 3102 | if (value > 7) | ||
| 3103 | return -EINVAL; | ||
| 2740 | 3104 | ||
| 2741 | value &= 7; | 3105 | res = mutex_lock_interruptible(&brightness_mutex); |
| 3106 | if (res < 0) | ||
| 3107 | return res; | ||
| 3108 | |||
| 3109 | current_value = brightness_get(NULL); | ||
| 3110 | if (current_value < 0) { | ||
| 3111 | res = current_value; | ||
| 3112 | goto errout; | ||
| 3113 | } | ||
| 2742 | 3114 | ||
| 2743 | cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN; | 3115 | cmos_cmd = value > current_value ? |
| 3116 | TP_CMOS_BRIGHTNESS_UP : | ||
| 3117 | TP_CMOS_BRIGHTNESS_DOWN; | ||
| 2744 | inc = value > current_value ? 1 : -1; | 3118 | inc = value > current_value ? 1 : -1; |
| 3119 | |||
| 3120 | res = 0; | ||
| 2745 | for (i = current_value; i != value; i += inc) { | 3121 | for (i = current_value; i != value; i += inc) { |
| 2746 | if (issue_thinkpad_cmos_command(cmos_cmd)) | 3122 | if ((brightness_mode & 2) && |
| 2747 | return -EIO; | 3123 | issue_thinkpad_cmos_command(cmos_cmd)) { |
| 2748 | if (!acpi_ec_write(brightness_offset, i + inc)) | 3124 | res = -EIO; |
| 2749 | return -EIO; | 3125 | goto errout; |
| 3126 | } | ||
| 3127 | if ((brightness_mode & 1) && | ||
| 3128 | !acpi_ec_write(brightness_offset, i + inc)) { | ||
| 3129 | res = -EIO; | ||
| 3130 | goto errout;; | ||
| 3131 | } | ||
| 2750 | } | 3132 | } |
| 2751 | 3133 | ||
| 2752 | return 0; | 3134 | errout: |
| 3135 | mutex_unlock(&brightness_mutex); | ||
| 3136 | return res; | ||
| 2753 | } | 3137 | } |
| 2754 | 3138 | ||
| 2755 | static int brightness_read(char *p) | 3139 | static int brightness_read(char *p) |
| @@ -3273,20 +3657,19 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
| 3273 | * Enable for TP-1Y (T43), TP-78 (R51e), | 3657 | * Enable for TP-1Y (T43), TP-78 (R51e), |
| 3274 | * TP-76 (R52), TP-70 (T43, R52), which are known | 3658 | * TP-76 (R52), TP-70 (T43, R52), which are known |
| 3275 | * to be buggy. */ | 3659 | * to be buggy. */ |
| 3276 | if (fan_control_initial_status == 0x07 && | 3660 | if (fan_control_initial_status == 0x07) { |
| 3277 | ibm_thinkpad_ec_found && | 3661 | switch (thinkpad_id.ec_model) { |
| 3278 | ((ibm_thinkpad_ec_found[0] == '1' && | 3662 | case 0x5931: /* TP-1Y */ |
| 3279 | ibm_thinkpad_ec_found[1] == 'Y') || | 3663 | case 0x3837: /* TP-78 */ |
| 3280 | (ibm_thinkpad_ec_found[0] == '7' && | 3664 | case 0x3637: /* TP-76 */ |
| 3281 | (ibm_thinkpad_ec_found[1] == '6' || | 3665 | case 0x3037: /* TP-70 */ |
| 3282 | ibm_thinkpad_ec_found[1] == '8' || | 3666 | printk(IBM_NOTICE |
| 3283 | ibm_thinkpad_ec_found[1] == '0')) | 3667 | "fan_init: initial fan status is " |
| 3284 | )) { | 3668 | "unknown, assuming it is in auto " |
| 3285 | printk(IBM_NOTICE | 3669 | "mode\n"); |
| 3286 | "fan_init: initial fan status is " | 3670 | tp_features.fan_ctrl_status_undef = 1; |
| 3287 | "unknown, assuming it is in auto " | 3671 | ;; |
| 3288 | "mode\n"); | 3672 | } |
| 3289 | tp_features.fan_ctrl_status_undef = 1; | ||
| 3290 | } | 3673 | } |
| 3291 | } else { | 3674 | } else { |
| 3292 | printk(IBM_ERR | 3675 | printk(IBM_ERR |
| @@ -3474,7 +3857,7 @@ static void fan_watchdog_fire(struct work_struct *ignored) | |||
| 3474 | 3857 | ||
| 3475 | static void fan_watchdog_reset(void) | 3858 | static void fan_watchdog_reset(void) |
| 3476 | { | 3859 | { |
| 3477 | static int fan_watchdog_active = 0; | 3860 | static int fan_watchdog_active; |
| 3478 | 3861 | ||
| 3479 | if (fan_control_access_mode == TPACPI_FAN_WR_NONE) | 3862 | if (fan_control_access_mode == TPACPI_FAN_WR_NONE) |
| 3480 | return; | 3863 | return; |
| @@ -3877,7 +4260,7 @@ static struct ibm_struct fan_driver_data = { | |||
| 3877 | ****************************************************************************/ | 4260 | ****************************************************************************/ |
| 3878 | 4261 | ||
| 3879 | /* /proc support */ | 4262 | /* /proc support */ |
| 3880 | static struct proc_dir_entry *proc_dir = NULL; | 4263 | static struct proc_dir_entry *proc_dir; |
| 3881 | 4264 | ||
| 3882 | /* Subdriver registry */ | 4265 | /* Subdriver registry */ |
| 3883 | static LIST_HEAD(tpacpi_all_drivers); | 4266 | static LIST_HEAD(tpacpi_all_drivers); |
| @@ -4020,13 +4403,30 @@ static void ibm_exit(struct ibm_struct *ibm) | |||
| 4020 | 4403 | ||
| 4021 | /* Probing */ | 4404 | /* Probing */ |
| 4022 | 4405 | ||
| 4023 | static char *ibm_thinkpad_ec_found = NULL; | 4406 | static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) |
| 4024 | |||
| 4025 | static char* __init check_dmi_for_ec(void) | ||
| 4026 | { | 4407 | { |
| 4027 | struct dmi_device *dev = NULL; | 4408 | struct dmi_device *dev = NULL; |
| 4028 | char ec_fw_string[18]; | 4409 | char ec_fw_string[18]; |
| 4029 | 4410 | ||
| 4411 | if (!tp) | ||
| 4412 | return; | ||
| 4413 | |||
| 4414 | memset(tp, 0, sizeof(*tp)); | ||
| 4415 | |||
| 4416 | if (dmi_name_in_vendors("IBM")) | ||
| 4417 | tp->vendor = PCI_VENDOR_ID_IBM; | ||
| 4418 | else if (dmi_name_in_vendors("LENOVO")) | ||
| 4419 | tp->vendor = PCI_VENDOR_ID_LENOVO; | ||
| 4420 | else | ||
| 4421 | return; | ||
| 4422 | |||
| 4423 | tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION), | ||
| 4424 | GFP_KERNEL); | ||
| 4425 | if (!tp->bios_version_str) | ||
| 4426 | return; | ||
| 4427 | tp->bios_model = tp->bios_version_str[0] | ||
| 4428 | | (tp->bios_version_str[1] << 8); | ||
| 4429 | |||
| 4030 | /* | 4430 | /* |
| 4031 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, | 4431 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, |
| 4032 | * X32 or newer, all Z series; Some models must have an | 4432 | * X32 or newer, all Z series; Some models must have an |
| @@ -4040,10 +4440,20 @@ static char* __init check_dmi_for_ec(void) | |||
| 4040 | ec_fw_string) == 1) { | 4440 | ec_fw_string) == 1) { |
| 4041 | ec_fw_string[sizeof(ec_fw_string) - 1] = 0; | 4441 | ec_fw_string[sizeof(ec_fw_string) - 1] = 0; |
| 4042 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; | 4442 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; |
| 4043 | return kstrdup(ec_fw_string, GFP_KERNEL); | 4443 | |
| 4444 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); | ||
| 4445 | tp->ec_model = ec_fw_string[0] | ||
| 4446 | | (ec_fw_string[1] << 8); | ||
| 4447 | break; | ||
| 4044 | } | 4448 | } |
| 4045 | } | 4449 | } |
| 4046 | return NULL; | 4450 | |
| 4451 | tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), | ||
| 4452 | GFP_KERNEL); | ||
| 4453 | if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) { | ||
| 4454 | kfree(tp->model_str); | ||
| 4455 | tp->model_str = NULL; | ||
| 4456 | } | ||
| 4047 | } | 4457 | } |
| 4048 | 4458 | ||
| 4049 | static int __init probe_for_thinkpad(void) | 4459 | static int __init probe_for_thinkpad(void) |
| @@ -4057,7 +4467,7 @@ static int __init probe_for_thinkpad(void) | |||
| 4057 | * Non-ancient models have better DMI tagging, but very old models | 4467 | * Non-ancient models have better DMI tagging, but very old models |
| 4058 | * don't. | 4468 | * don't. |
| 4059 | */ | 4469 | */ |
| 4060 | is_thinkpad = dmi_name_in_vendors("ThinkPad"); | 4470 | is_thinkpad = (thinkpad_id.model_str != NULL); |
| 4061 | 4471 | ||
| 4062 | /* ec is required because many other handles are relative to it */ | 4472 | /* ec is required because many other handles are relative to it */ |
| 4063 | IBM_ACPIHANDLE_INIT(ec); | 4473 | IBM_ACPIHANDLE_INIT(ec); |
| @@ -4073,7 +4483,7 @@ static int __init probe_for_thinkpad(void) | |||
| 4073 | * false positives a damn great deal | 4483 | * false positives a damn great deal |
| 4074 | */ | 4484 | */ |
| 4075 | if (!is_thinkpad) | 4485 | if (!is_thinkpad) |
| 4076 | is_thinkpad = dmi_name_in_vendors("IBM"); | 4486 | is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM); |
| 4077 | 4487 | ||
| 4078 | if (!is_thinkpad && !force_load) | 4488 | if (!is_thinkpad && !force_load) |
| 4079 | return -ENODEV; | 4489 | return -ENODEV; |
| @@ -4185,10 +4595,13 @@ static u32 dbg_level; | |||
| 4185 | module_param_named(debug, dbg_level, uint, 0); | 4595 | module_param_named(debug, dbg_level, uint, 0); |
| 4186 | 4596 | ||
| 4187 | static int force_load; | 4597 | static int force_load; |
| 4188 | module_param(force_load, int, 0); | 4598 | module_param(force_load, bool, 0); |
| 4189 | 4599 | ||
| 4190 | static int fan_control_allowed; | 4600 | static int fan_control_allowed; |
| 4191 | module_param_named(fan_control, fan_control_allowed, int, 0); | 4601 | module_param_named(fan_control, fan_control_allowed, bool, 0); |
| 4602 | |||
| 4603 | static int brightness_mode; | ||
| 4604 | module_param_named(brightness_mode, brightness_mode, int, 0); | ||
| 4192 | 4605 | ||
| 4193 | #define IBM_PARAM(feature) \ | 4606 | #define IBM_PARAM(feature) \ |
| 4194 | module_param_call(feature, set_ibm_param, NULL, NULL, 0) | 4607 | module_param_call(feature, set_ibm_param, NULL, NULL, 0) |
| @@ -4216,12 +4629,16 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4216 | int ret, i; | 4629 | int ret, i; |
| 4217 | 4630 | ||
| 4218 | /* Driver-level probe */ | 4631 | /* Driver-level probe */ |
| 4632 | |||
| 4633 | get_thinkpad_model_data(&thinkpad_id); | ||
| 4219 | ret = probe_for_thinkpad(); | 4634 | ret = probe_for_thinkpad(); |
| 4220 | if (ret) | 4635 | if (ret) { |
| 4636 | thinkpad_acpi_module_exit(); | ||
| 4221 | return ret; | 4637 | return ret; |
| 4638 | } | ||
| 4222 | 4639 | ||
| 4223 | /* Driver initialization */ | 4640 | /* Driver initialization */ |
| 4224 | ibm_thinkpad_ec_found = check_dmi_for_ec(); | 4641 | |
| 4225 | IBM_ACPIHANDLE_INIT(ecrd); | 4642 | IBM_ACPIHANDLE_INIT(ecrd); |
| 4226 | IBM_ACPIHANDLE_INIT(ecwr); | 4643 | IBM_ACPIHANDLE_INIT(ecwr); |
| 4227 | 4644 | ||
| @@ -4265,6 +4682,22 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4265 | thinkpad_acpi_module_exit(); | 4682 | thinkpad_acpi_module_exit(); |
| 4266 | return ret; | 4683 | return ret; |
| 4267 | } | 4684 | } |
| 4685 | tpacpi_inputdev = input_allocate_device(); | ||
| 4686 | if (!tpacpi_inputdev) { | ||
| 4687 | printk(IBM_ERR "unable to allocate input device\n"); | ||
| 4688 | thinkpad_acpi_module_exit(); | ||
| 4689 | return -ENOMEM; | ||
| 4690 | } else { | ||
| 4691 | /* Prepare input device, but don't register */ | ||
| 4692 | tpacpi_inputdev->name = "ThinkPad Extra Buttons"; | ||
| 4693 | tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0"; | ||
| 4694 | tpacpi_inputdev->id.bustype = BUS_HOST; | ||
| 4695 | tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ? | ||
| 4696 | thinkpad_id.vendor : | ||
| 4697 | PCI_VENDOR_ID_IBM; | ||
| 4698 | tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; | ||
| 4699 | tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; | ||
| 4700 | } | ||
| 4268 | for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { | 4701 | for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { |
| 4269 | ret = ibm_init(&ibms_init[i]); | 4702 | ret = ibm_init(&ibms_init[i]); |
| 4270 | if (ret >= 0 && *ibms_init[i].param) | 4703 | if (ret >= 0 && *ibms_init[i].param) |
| @@ -4274,6 +4707,14 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4274 | return ret; | 4707 | return ret; |
| 4275 | } | 4708 | } |
| 4276 | } | 4709 | } |
| 4710 | ret = input_register_device(tpacpi_inputdev); | ||
| 4711 | if (ret < 0) { | ||
| 4712 | printk(IBM_ERR "unable to register input device\n"); | ||
| 4713 | thinkpad_acpi_module_exit(); | ||
| 4714 | return ret; | ||
| 4715 | } else { | ||
| 4716 | tp_features.input_device_registered = 1; | ||
| 4717 | } | ||
| 4277 | 4718 | ||
| 4278 | return 0; | 4719 | return 0; |
| 4279 | } | 4720 | } |
| @@ -4290,6 +4731,13 @@ static void thinkpad_acpi_module_exit(void) | |||
| 4290 | 4731 | ||
| 4291 | dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); | 4732 | dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); |
| 4292 | 4733 | ||
| 4734 | if (tpacpi_inputdev) { | ||
| 4735 | if (tp_features.input_device_registered) | ||
| 4736 | input_unregister_device(tpacpi_inputdev); | ||
| 4737 | else | ||
| 4738 | input_free_device(tpacpi_inputdev); | ||
| 4739 | } | ||
| 4740 | |||
| 4293 | if (tpacpi_hwmon) | 4741 | if (tpacpi_hwmon) |
| 4294 | hwmon_device_unregister(tpacpi_hwmon); | 4742 | hwmon_device_unregister(tpacpi_hwmon); |
| 4295 | 4743 | ||
| @@ -4302,7 +4750,9 @@ static void thinkpad_acpi_module_exit(void) | |||
| 4302 | if (proc_dir) | 4750 | if (proc_dir) |
| 4303 | remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); | 4751 | remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); |
| 4304 | 4752 | ||
| 4305 | kfree(ibm_thinkpad_ec_found); | 4753 | kfree(thinkpad_id.bios_version_str); |
| 4754 | kfree(thinkpad_id.ec_version_str); | ||
| 4755 | kfree(thinkpad_id.model_str); | ||
| 4306 | } | 4756 | } |
| 4307 | 4757 | ||
| 4308 | module_init(thinkpad_acpi_module_init); | 4758 | module_init(thinkpad_acpi_module_init); |
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index 72d62f2dabb9..b7a4a888cc8b 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
| 33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 34 | 34 | ||
| 35 | #include <linux/nvram.h> | ||
| 35 | #include <linux/proc_fs.h> | 36 | #include <linux/proc_fs.h> |
| 36 | #include <linux/sysfs.h> | 37 | #include <linux/sysfs.h> |
| 37 | #include <linux/backlight.h> | 38 | #include <linux/backlight.h> |
| @@ -39,6 +40,7 @@ | |||
| 39 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
| 40 | #include <linux/hwmon.h> | 41 | #include <linux/hwmon.h> |
| 41 | #include <linux/hwmon-sysfs.h> | 42 | #include <linux/hwmon-sysfs.h> |
| 43 | #include <linux/input.h> | ||
| 42 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
| 43 | 45 | ||
| 44 | #include <linux/dmi.h> | 46 | #include <linux/dmi.h> |
| @@ -48,6 +50,7 @@ | |||
| 48 | #include <acpi/acpi_drivers.h> | 50 | #include <acpi/acpi_drivers.h> |
| 49 | #include <acpi/acnamesp.h> | 51 | #include <acpi/acnamesp.h> |
| 50 | 52 | ||
| 53 | #include <linux/pci_ids.h> | ||
| 51 | 54 | ||
| 52 | /**************************************************************************** | 55 | /**************************************************************************** |
| 53 | * Main driver | 56 | * Main driver |
| @@ -78,6 +81,11 @@ | |||
| 78 | #define TP_CMOS_BRIGHTNESS_UP 4 | 81 | #define TP_CMOS_BRIGHTNESS_UP 4 |
| 79 | #define TP_CMOS_BRIGHTNESS_DOWN 5 | 82 | #define TP_CMOS_BRIGHTNESS_DOWN 5 |
| 80 | 83 | ||
| 84 | /* ThinkPad CMOS NVRAM constants */ | ||
| 85 | #define TP_NVRAM_ADDR_BRIGHTNESS 0x5e | ||
| 86 | #define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x07 | ||
| 87 | #define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0 | ||
| 88 | |||
| 81 | #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") | 89 | #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") |
| 82 | #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") | 90 | #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") |
| 83 | #define strlencmp(a,b) (strncmp((a), (b), strlen(b))) | 91 | #define strlencmp(a,b) (strncmp((a), (b), strlen(b))) |
| @@ -98,9 +106,13 @@ static const char *str_supported(int is_supported); | |||
| 98 | #define vdbg_printk(a_dbg_level, format, arg...) | 106 | #define vdbg_printk(a_dbg_level, format, arg...) |
| 99 | #endif | 107 | #endif |
| 100 | 108 | ||
| 109 | /* Input IDs */ | ||
| 110 | #define TPACPI_HKEY_INPUT_VENDOR PCI_VENDOR_ID_IBM | ||
| 111 | #define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */ | ||
| 112 | #define TPACPI_HKEY_INPUT_VERSION 0x4101 | ||
| 113 | |||
| 101 | /* ACPI HIDs */ | 114 | /* ACPI HIDs */ |
| 102 | #define IBM_HKEY_HID "IBM0068" | 115 | #define IBM_HKEY_HID "IBM0068" |
| 103 | #define IBM_PCI_HID "PNP0A03" | ||
| 104 | 116 | ||
| 105 | /* ACPI helpers */ | 117 | /* ACPI helpers */ |
| 106 | static int __must_check acpi_evalf(acpi_handle handle, | 118 | static int __must_check acpi_evalf(acpi_handle handle, |
| @@ -161,6 +173,7 @@ static int parse_strtoul(const char *buf, unsigned long max, | |||
| 161 | static struct platform_device *tpacpi_pdev; | 173 | static struct platform_device *tpacpi_pdev; |
| 162 | static struct class_device *tpacpi_hwmon; | 174 | static struct class_device *tpacpi_hwmon; |
| 163 | static struct platform_driver tpacpi_pdriver; | 175 | static struct platform_driver tpacpi_pdriver; |
| 176 | static struct input_dev *tpacpi_inputdev; | ||
| 164 | static int tpacpi_create_driver_attributes(struct device_driver *drv); | 177 | static int tpacpi_create_driver_attributes(struct device_driver *drv); |
| 165 | static void tpacpi_remove_driver_attributes(struct device_driver *drv); | 178 | static void tpacpi_remove_driver_attributes(struct device_driver *drv); |
| 166 | 179 | ||
| @@ -168,9 +181,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv); | |||
| 168 | static int experimental; | 181 | static int experimental; |
| 169 | static u32 dbg_level; | 182 | static u32 dbg_level; |
| 170 | static int force_load; | 183 | static int force_load; |
| 171 | static char *ibm_thinkpad_ec_found; | ||
| 172 | 184 | ||
| 173 | static char* check_dmi_for_ec(void); | ||
| 174 | static int thinkpad_acpi_module_init(void); | 185 | static int thinkpad_acpi_module_init(void); |
| 175 | static void thinkpad_acpi_module_exit(void); | 186 | static void thinkpad_acpi_module_exit(void); |
| 176 | 187 | ||
| @@ -197,6 +208,7 @@ struct ibm_struct { | |||
| 197 | int (*read) (char *); | 208 | int (*read) (char *); |
| 198 | int (*write) (char *); | 209 | int (*write) (char *); |
| 199 | void (*exit) (void); | 210 | void (*exit) (void); |
| 211 | void (*resume) (void); | ||
| 200 | 212 | ||
| 201 | struct list_head all_drivers; | 213 | struct list_head all_drivers; |
| 202 | 214 | ||
| @@ -228,12 +240,29 @@ static struct { | |||
| 228 | u16 bluetooth:1; | 240 | u16 bluetooth:1; |
| 229 | u16 hotkey:1; | 241 | u16 hotkey:1; |
| 230 | u16 hotkey_mask:1; | 242 | u16 hotkey_mask:1; |
| 243 | u16 hotkey_wlsw:1; | ||
| 231 | u16 light:1; | 244 | u16 light:1; |
| 232 | u16 light_status:1; | 245 | u16 light_status:1; |
| 233 | u16 wan:1; | 246 | u16 wan:1; |
| 234 | u16 fan_ctrl_status_undef:1; | 247 | u16 fan_ctrl_status_undef:1; |
| 248 | u16 input_device_registered:1; | ||
| 235 | } tp_features; | 249 | } tp_features; |
| 236 | 250 | ||
| 251 | struct thinkpad_id_data { | ||
| 252 | unsigned int vendor; /* ThinkPad vendor: | ||
| 253 | * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ | ||
| 254 | |||
| 255 | char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ | ||
| 256 | char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ | ||
| 257 | |||
| 258 | u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ | ||
| 259 | u16 ec_model; | ||
| 260 | |||
| 261 | char *model_str; | ||
| 262 | }; | ||
| 263 | |||
| 264 | static struct thinkpad_id_data thinkpad_id; | ||
| 265 | |||
| 237 | static struct list_head tpacpi_all_drivers; | 266 | static struct list_head tpacpi_all_drivers; |
| 238 | 267 | ||
| 239 | static struct ibm_init_struct ibms_init[]; | 268 | static struct ibm_init_struct ibms_init[]; |
| @@ -300,6 +329,7 @@ static int bluetooth_write(char *buf); | |||
| 300 | 329 | ||
| 301 | static struct backlight_device *ibm_backlight_device; | 330 | static struct backlight_device *ibm_backlight_device; |
| 302 | static int brightness_offset = 0x31; | 331 | static int brightness_offset = 0x31; |
| 332 | static int brightness_mode; | ||
| 303 | 333 | ||
| 304 | static int brightness_init(struct ibm_init_struct *iibm); | 334 | static int brightness_init(struct ibm_init_struct *iibm); |
| 305 | static void brightness_exit(void); | 335 | static void brightness_exit(void); |
| @@ -415,14 +445,14 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc); | |||
| 415 | */ | 445 | */ |
| 416 | 446 | ||
| 417 | static int hotkey_orig_status; | 447 | static int hotkey_orig_status; |
| 418 | static int hotkey_orig_mask; | 448 | static u32 hotkey_orig_mask; |
| 419 | 449 | ||
| 420 | static struct mutex hotkey_mutex; | 450 | static struct mutex hotkey_mutex; |
| 421 | 451 | ||
| 422 | static int hotkey_init(struct ibm_init_struct *iibm); | 452 | static int hotkey_init(struct ibm_init_struct *iibm); |
| 423 | static void hotkey_exit(void); | 453 | static void hotkey_exit(void); |
| 424 | static int hotkey_get(int *status, int *mask); | 454 | static int hotkey_get(int *status, u32 *mask); |
| 425 | static int hotkey_set(int status, int mask); | 455 | static int hotkey_set(int status, u32 mask); |
| 426 | static void hotkey_notify(struct ibm_struct *ibm, u32 event); | 456 | static void hotkey_notify(struct ibm_struct *ibm, u32 event); |
| 427 | static int hotkey_read(char *p); | 457 | static int hotkey_read(char *p); |
| 428 | static int hotkey_write(char *buf); | 458 | static int hotkey_write(char *buf); |
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 28c881895ab7..15aab374127e 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
| @@ -903,8 +903,10 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 903 | /* | 903 | /* |
| 904 | * Add host to MMC layer | 904 | * Add host to MMC layer |
| 905 | */ | 905 | */ |
| 906 | if (host->board->det_pin) | 906 | if (host->board->det_pin) { |
| 907 | host->present = !at91_get_gpio_value(host->board->det_pin); | 907 | host->present = !at91_get_gpio_value(host->board->det_pin); |
| 908 | device_init_wakeup(&pdev->dev, 1); | ||
| 909 | } | ||
| 908 | else | 910 | else |
| 909 | host->present = -1; | 911 | host->present = -1; |
| 910 | 912 | ||
| @@ -940,6 +942,7 @@ static int __exit at91_mci_remove(struct platform_device *pdev) | |||
| 940 | host = mmc_priv(mmc); | 942 | host = mmc_priv(mmc); |
| 941 | 943 | ||
| 942 | if (host->present != -1) { | 944 | if (host->present != -1) { |
| 945 | device_init_wakeup(&pdev->dev, 0); | ||
| 943 | free_irq(host->board->det_pin, host); | 946 | free_irq(host->board->det_pin, host); |
| 944 | cancel_delayed_work(&host->mmc->detect); | 947 | cancel_delayed_work(&host->mmc->detect); |
| 945 | } | 948 | } |
| @@ -966,8 +969,12 @@ static int __exit at91_mci_remove(struct platform_device *pdev) | |||
| 966 | static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state) | 969 | static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state) |
| 967 | { | 970 | { |
| 968 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 971 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 972 | struct at91mci_host *host = mmc_priv(mmc); | ||
| 969 | int ret = 0; | 973 | int ret = 0; |
| 970 | 974 | ||
| 975 | if (device_may_wakeup(&pdev->dev)) | ||
| 976 | enable_irq_wake(host->board->det_pin); | ||
| 977 | |||
| 971 | if (mmc) | 978 | if (mmc) |
| 972 | ret = mmc_suspend_host(mmc, state); | 979 | ret = mmc_suspend_host(mmc, state); |
| 973 | 980 | ||
| @@ -977,8 +984,12 @@ static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 977 | static int at91_mci_resume(struct platform_device *pdev) | 984 | static int at91_mci_resume(struct platform_device *pdev) |
| 978 | { | 985 | { |
| 979 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 986 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 987 | struct at91mci_host *host = mmc_priv(mmc); | ||
| 980 | int ret = 0; | 988 | int ret = 0; |
| 981 | 989 | ||
| 990 | if (device_may_wakeup(&pdev->dev)) | ||
| 991 | disable_irq_wake(host->board->det_pin); | ||
| 992 | |||
| 982 | if (mmc) | 993 | if (mmc) |
| 983 | ret = mmc_resume_host(mmc); | 994 | ret = mmc_resume_host(mmc); |
| 984 | 995 | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 10d15c39d003..4a24db028d87 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -1024,6 +1024,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) | |||
| 1024 | 1024 | ||
| 1025 | intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); | 1025 | intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); |
| 1026 | 1026 | ||
| 1027 | intmask &= ~SDHCI_INT_ERROR; | ||
| 1028 | |||
| 1027 | if (intmask & SDHCI_INT_BUS_POWER) { | 1029 | if (intmask & SDHCI_INT_BUS_POWER) { |
| 1028 | printk(KERN_ERR "%s: Card is consuming too much power!\n", | 1030 | printk(KERN_ERR "%s: Card is consuming too much power!\n", |
| 1029 | mmc_hostname(host->mmc)); | 1031 | mmc_hostname(host->mmc)); |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 7400f4bc114f..a6c870480b8a 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
| @@ -107,6 +107,7 @@ | |||
| 107 | #define SDHCI_INT_CARD_INSERT 0x00000040 | 107 | #define SDHCI_INT_CARD_INSERT 0x00000040 |
| 108 | #define SDHCI_INT_CARD_REMOVE 0x00000080 | 108 | #define SDHCI_INT_CARD_REMOVE 0x00000080 |
| 109 | #define SDHCI_INT_CARD_INT 0x00000100 | 109 | #define SDHCI_INT_CARD_INT 0x00000100 |
| 110 | #define SDHCI_INT_ERROR 0x00008000 | ||
| 110 | #define SDHCI_INT_TIMEOUT 0x00010000 | 111 | #define SDHCI_INT_TIMEOUT 0x00010000 |
| 111 | #define SDHCI_INT_CRC 0x00020000 | 112 | #define SDHCI_INT_CRC 0x00020000 |
| 112 | #define SDHCI_INT_END_BIT 0x00040000 | 113 | #define SDHCI_INT_END_BIT 0x00040000 |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 3073f679584b..f8a602caabcb 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | menuconfig NETDEVICES | 6 | menuconfig NETDEVICES |
| 7 | default y if UML | 7 | default y if UML |
| 8 | depends on NET | ||
| 8 | bool "Network device support" | 9 | bool "Network device support" |
| 9 | ---help--- | 10 | ---help--- |
| 10 | You can say N here if you don't intend to connect your Linux box to | 11 | You can say N here if you don't intend to connect your Linux box to |
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c index f21148e7b579..80f33b6d5713 100644 --- a/drivers/net/arm/ether1.c +++ b/drivers/net/arm/ether1.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
| 37 | #include <linux/fcntl.h> | 37 | #include <linux/fcntl.h> |
| 38 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
| 39 | #include <linux/ptrace.h> | ||
| 40 | #include <linux/ioport.h> | 39 | #include <linux/ioport.h> |
| 41 | #include <linux/in.h> | 40 | #include <linux/in.h> |
| 42 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
| @@ -75,7 +74,7 @@ static void ether1_timeout(struct net_device *dev); | |||
| 75 | 74 | ||
| 76 | /* ------------------------------------------------------------------------- */ | 75 | /* ------------------------------------------------------------------------- */ |
| 77 | 76 | ||
| 78 | static char version[] __initdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; | 77 | static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; |
| 79 | 78 | ||
| 80 | #define BUS_16 16 | 79 | #define BUS_16 16 |
| 81 | #define BUS_8 8 | 80 | #define BUS_8 8 |
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index a7cac695a9bd..3805506a3ab8 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c | |||
| @@ -51,7 +51,6 @@ | |||
| 51 | #include <linux/types.h> | 51 | #include <linux/types.h> |
| 52 | #include <linux/fcntl.h> | 52 | #include <linux/fcntl.h> |
| 53 | #include <linux/interrupt.h> | 53 | #include <linux/interrupt.h> |
| 54 | #include <linux/ptrace.h> | ||
| 55 | #include <linux/ioport.h> | 54 | #include <linux/ioport.h> |
| 56 | #include <linux/in.h> | 55 | #include <linux/in.h> |
| 57 | #include <linux/slab.h> | 56 | #include <linux/slab.h> |
| @@ -69,7 +68,7 @@ | |||
| 69 | #include <asm/ecard.h> | 68 | #include <asm/ecard.h> |
| 70 | #include <asm/io.h> | 69 | #include <asm/io.h> |
| 71 | 70 | ||
| 72 | static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; | 71 | static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; |
| 73 | 72 | ||
| 74 | #include "ether3.h" | 73 | #include "ether3.h" |
| 75 | 74 | ||
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 769ba69451f4..0d37d9d1fd78 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 32 | #include <linux/fcntl.h> | 32 | #include <linux/fcntl.h> |
| 33 | #include <linux/interrupt.h> | 33 | #include <linux/interrupt.h> |
| 34 | #include <linux/ptrace.h> | ||
| 35 | #include <linux/ioport.h> | 34 | #include <linux/ioport.h> |
| 36 | #include <linux/in.h> | 35 | #include <linux/in.h> |
| 37 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index 829da9a1d113..2098d0af8ff5 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig | |||
| @@ -155,6 +155,15 @@ config KINGSUN_DONGLE | |||
| 155 | To compile it as a module, choose M here: the module will be called | 155 | To compile it as a module, choose M here: the module will be called |
| 156 | kingsun-sir. | 156 | kingsun-sir. |
| 157 | 157 | ||
| 158 | config EP7211_DONGLE | ||
| 159 | tristate "EP7211 I/R support" | ||
| 160 | depends on IRTTY_SIR && ARCH_EP7211 && IRDA && EXPERIMENTAL | ||
| 161 | help | ||
| 162 | Say Y here if you want to build support for the Cirrus logic | ||
| 163 | EP7211 chipset's infrared module. | ||
| 164 | |||
| 165 | |||
| 166 | |||
| 158 | comment "Old SIR device drivers" | 167 | comment "Old SIR device drivers" |
| 159 | 168 | ||
| 160 | config IRPORT_SIR | 169 | config IRPORT_SIR |
| @@ -355,7 +364,7 @@ config WINBOND_FIR | |||
| 355 | 364 | ||
| 356 | config TOSHIBA_FIR | 365 | config TOSHIBA_FIR |
| 357 | tristate "Toshiba Type-O IR Port" | 366 | tristate "Toshiba Type-O IR Port" |
| 358 | depends on IRDA && PCI && !64BIT | 367 | depends on IRDA && PCI && !64BIT && VIRT_TO_BUS |
| 359 | help | 368 | help |
| 360 | Say Y here if you want to build support for the Toshiba Type-O IR | 369 | Say Y here if you want to build support for the Toshiba Type-O IR |
| 361 | and Donau oboe chipsets. These chipsets are used by the Toshiba | 370 | and Donau oboe chipsets. These chipsets are used by the Toshiba |
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index 233a2f923730..2808ef5c7b79 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile | |||
| @@ -45,6 +45,7 @@ obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o | |||
| 45 | obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o | 45 | obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o |
| 46 | obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o | 46 | obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o |
| 47 | obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o | 47 | obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o |
| 48 | obj-$(CONFIG_EP7211_DONGLE) += ep7211-sir.o | ||
| 48 | obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o | 49 | obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o |
| 49 | 50 | ||
| 50 | # The SIR helper module | 51 | # The SIR helper module |
diff --git a/drivers/net/irda/ep7211-sir.c b/drivers/net/irda/ep7211-sir.c new file mode 100644 index 000000000000..831572429bb9 --- /dev/null +++ b/drivers/net/irda/ep7211-sir.c | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | /* | ||
| 2 | * IR port driver for the Cirrus Logic EP7211 processor. | ||
| 3 | * | ||
| 4 | * Copyright 2001, Blue Mug Inc. All rights reserved. | ||
| 5 | * Copyright 2007, Samuel Ortiz <samuel@sortiz.org> | ||
| 6 | */ | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/tty.h> | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/spinlock.h> | ||
| 12 | |||
| 13 | #include <net/irda/irda.h> | ||
| 14 | #include <net/irda/irda_device.h> | ||
| 15 | |||
| 16 | #include <asm/io.h> | ||
| 17 | #include <asm/hardware.h> | ||
| 18 | |||
| 19 | #include "sir-dev.h" | ||
| 20 | |||
| 21 | #define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */ | ||
| 22 | #define MAX_DELAY 10000 /* 1 ms */ | ||
| 23 | |||
| 24 | static int ep7211_open(struct sir_dev *dev); | ||
| 25 | static int ep7211_close(struct sir_dev *dev); | ||
| 26 | static int ep7211_change_speed(struct sir_dev *dev, unsigned speed); | ||
| 27 | static int ep7211_reset(struct sir_dev *dev); | ||
| 28 | |||
| 29 | static struct dongle_driver ep7211 = { | ||
| 30 | .owner = THIS_MODULE, | ||
| 31 | .driver_name = "EP7211 IR driver", | ||
| 32 | .type = IRDA_EP7211_DONGLE, | ||
| 33 | .open = ep7211_open, | ||
| 34 | .close = ep7211_close, | ||
| 35 | .reset = ep7211_reset, | ||
| 36 | .set_speed = ep7211_change_speed, | ||
| 37 | }; | ||
| 38 | |||
| 39 | static int __init ep7211_sir_init(void) | ||
| 40 | { | ||
| 41 | return irda_register_dongle(&ep7211); | ||
| 42 | } | ||
| 43 | |||
| 44 | static void __exit ep7211_sir_cleanup(void) | ||
| 45 | { | ||
| 46 | irda_unregister_dongle(&ep7211); | ||
| 47 | } | ||
| 48 | |||
| 49 | static int ep7211_open(struct sir_dev *dev) | ||
| 50 | { | ||
| 51 | unsigned int syscon; | ||
| 52 | |||
| 53 | /* Turn on the SIR encoder. */ | ||
| 54 | syscon = clps_readl(SYSCON1); | ||
| 55 | syscon |= SYSCON1_SIREN; | ||
| 56 | clps_writel(syscon, SYSCON1); | ||
| 57 | |||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | static int ep7211_close(struct sir_dev *dev) | ||
| 62 | { | ||
| 63 | unsigned int syscon; | ||
| 64 | |||
| 65 | /* Turn off the SIR encoder. */ | ||
| 66 | syscon = clps_readl(SYSCON1); | ||
| 67 | syscon &= ~SYSCON1_SIREN; | ||
| 68 | clps_writel(syscon, SYSCON1); | ||
| 69 | |||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static int ep7211_change_speed(struct sir_dev *dev, unsigned speed) | ||
| 74 | { | ||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | static int ep7211_reset(struct sir_dev *dev) | ||
| 79 | { | ||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | MODULE_AUTHOR("Samuel Ortiz <samuel@sortiz.org>"); | ||
| 84 | MODULE_DESCRIPTION("EP7211 IR dongle driver"); | ||
| 85 | MODULE_LICENSE("GPL"); | ||
| 86 | MODULE_ALIAS("irda-dongle-13"); /* IRDA_EP7211_DONGLE */ | ||
| 87 | |||
| 88 | module_init(ep7211_sir_init); | ||
| 89 | module_exit(ep7211_sir_cleanup); | ||
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index 3c45142c40b2..b01985498460 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
| @@ -1316,7 +1316,7 @@ static struct of_device_id m8xx_pcmcia_match[] = { | |||
| 1316 | MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); | 1316 | MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); |
| 1317 | 1317 | ||
| 1318 | static struct of_platform_driver m8xx_pcmcia_driver = { | 1318 | static struct of_platform_driver m8xx_pcmcia_driver = { |
| 1319 | .name = (char *)driver_name, | 1319 | .name = driver_name, |
| 1320 | .match_table = m8xx_pcmcia_match, | 1320 | .match_table = m8xx_pcmcia_match, |
| 1321 | .probe = m8xx_probe, | 1321 | .probe = m8xx_probe, |
| 1322 | .remove = m8xx_remove, | 1322 | .remove = m8xx_remove, |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 35f34665e3c4..9d8d40d5c8f7 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -38,6 +38,9 @@ config RTC_HCTOSYS_DEVICE | |||
| 38 | clock, usually rtc0. Initialization is done when the system | 38 | clock, usually rtc0. Initialization is done when the system |
| 39 | starts up, and when it resumes from a low power state. | 39 | starts up, and when it resumes from a low power state. |
| 40 | 40 | ||
| 41 | The driver for this RTC device must be loaded before late_initcall | ||
| 42 | functions run, so it must usually be statically linked. | ||
| 43 | |||
| 41 | This clock should be battery-backed, so that it reads the correct | 44 | This clock should be battery-backed, so that it reads the correct |
| 42 | time when the system boots from a power-off state. Otherwise, your | 45 | time when the system boots from a power-off state. Otherwise, your |
| 43 | system will need an external clock source (like an NTP server). | 46 | system will need an external clock source (like an NTP server). |
| @@ -305,6 +308,16 @@ config RTC_DRV_DS1553 | |||
| 305 | This driver can also be built as a module. If so, the module | 308 | This driver can also be built as a module. If so, the module |
| 306 | will be called rtc-ds1553. | 309 | will be called rtc-ds1553. |
| 307 | 310 | ||
| 311 | config RTC_DRV_STK17TA8 | ||
| 312 | tristate "Simtek STK17TA8" | ||
| 313 | depends on RTC_CLASS | ||
| 314 | help | ||
| 315 | If you say yes here you get support for the | ||
| 316 | Simtek STK17TA8 timekeeping chip. | ||
| 317 | |||
| 318 | This driver can also be built as a module. If so, the module | ||
| 319 | will be called rtc-stk17ta8. | ||
| 320 | |||
| 308 | config RTC_DRV_DS1742 | 321 | config RTC_DRV_DS1742 |
| 309 | tristate "Dallas DS1742/1743" | 322 | tristate "Dallas DS1742/1743" |
| 310 | depends on RTC_CLASS | 323 | depends on RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 3109af9a1651..7ede9e725360 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -32,6 +32,7 @@ obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | |||
| 32 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 32 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
| 33 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 33 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
| 34 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 34 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
| 35 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o | ||
| 35 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 36 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
| 36 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 37 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
| 37 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o | 38 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o |
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index f98a83a11aae..46da5714932c 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
| @@ -407,7 +407,7 @@ static __init int ds1553_init(void) | |||
| 407 | 407 | ||
| 408 | static __exit void ds1553_exit(void) | 408 | static __exit void ds1553_exit(void) |
| 409 | { | 409 | { |
| 410 | return platform_driver_unregister(&ds1553_rtc_driver); | 410 | platform_driver_unregister(&ds1553_rtc_driver); |
| 411 | } | 411 | } |
| 412 | 412 | ||
| 413 | module_init(ds1553_init); | 413 | module_init(ds1553_init); |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index d1778ae8bca5..b2e5481ba3b6 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
| @@ -263,7 +263,7 @@ static __init int ds1742_init(void) | |||
| 263 | 263 | ||
| 264 | static __exit void ds1742_exit(void) | 264 | static __exit void ds1742_exit(void) |
| 265 | { | 265 | { |
| 266 | return platform_driver_unregister(&ds1742_rtc_driver); | 266 | platform_driver_unregister(&ds1742_rtc_driver); |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | module_init(ds1742_init); | 269 | module_init(ds1742_init); |
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index eee4ee5bb75a..a1cd448639c9 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c | |||
| @@ -31,17 +31,24 @@ | |||
| 31 | #define MAX6900_REG_DW 5 /* day of week 1-7 */ | 31 | #define MAX6900_REG_DW 5 /* day of week 1-7 */ |
| 32 | #define MAX6900_REG_YR 6 /* year 00-99 */ | 32 | #define MAX6900_REG_YR 6 /* year 00-99 */ |
| 33 | #define MAX6900_REG_CT 7 /* control */ | 33 | #define MAX6900_REG_CT 7 /* control */ |
| 34 | #define MAX6900_REG_LEN 8 | 34 | /* register 8 is undocumented */ |
| 35 | #define MAX6900_REG_CENTURY 9 /* century */ | ||
| 36 | #define MAX6900_REG_LEN 10 | ||
| 37 | |||
| 38 | #define MAX6900_BURST_LEN 8 /* can burst r/w first 8 regs */ | ||
| 35 | 39 | ||
| 36 | #define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */ | 40 | #define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */ |
| 37 | 41 | ||
| 42 | |||
| 38 | /* | 43 | /* |
| 39 | * register read/write commands | 44 | * register read/write commands |
| 40 | */ | 45 | */ |
| 41 | #define MAX6900_REG_CONTROL_WRITE 0x8e | 46 | #define MAX6900_REG_CONTROL_WRITE 0x8e |
| 42 | #define MAX6900_REG_BURST_READ 0xbf | 47 | #define MAX6900_REG_CENTURY_WRITE 0x92 |
| 43 | #define MAX6900_REG_BURST_WRITE 0xbe | 48 | #define MAX6900_REG_CENTURY_READ 0x93 |
| 44 | #define MAX6900_REG_RESERVED_READ 0x96 | 49 | #define MAX6900_REG_RESERVED_READ 0x96 |
| 50 | #define MAX6900_REG_BURST_WRITE 0xbe | ||
| 51 | #define MAX6900_REG_BURST_READ 0xbf | ||
| 45 | 52 | ||
| 46 | #define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ | 53 | #define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ |
| 47 | 54 | ||
| @@ -58,19 +65,32 @@ static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind); | |||
| 58 | 65 | ||
| 59 | static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) | 66 | static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) |
| 60 | { | 67 | { |
| 61 | u8 reg_addr[1] = { MAX6900_REG_BURST_READ }; | 68 | u8 reg_burst_read[1] = { MAX6900_REG_BURST_READ }; |
| 62 | struct i2c_msg msgs[2] = { | 69 | u8 reg_century_read[1] = { MAX6900_REG_CENTURY_READ }; |
| 70 | struct i2c_msg msgs[4] = { | ||
| 63 | { | 71 | { |
| 64 | .addr = client->addr, | 72 | .addr = client->addr, |
| 65 | .flags = 0, /* write */ | 73 | .flags = 0, /* write */ |
| 66 | .len = sizeof(reg_addr), | 74 | .len = sizeof(reg_burst_read), |
| 67 | .buf = reg_addr | 75 | .buf = reg_burst_read |
| 68 | }, | 76 | }, |
| 69 | { | 77 | { |
| 70 | .addr = client->addr, | 78 | .addr = client->addr, |
| 71 | .flags = I2C_M_RD, | 79 | .flags = I2C_M_RD, |
| 72 | .len = MAX6900_REG_LEN, | 80 | .len = MAX6900_BURST_LEN, |
| 73 | .buf = buf | 81 | .buf = buf |
| 82 | }, | ||
| 83 | { | ||
| 84 | .addr = client->addr, | ||
| 85 | .flags = 0, /* write */ | ||
| 86 | .len = sizeof(reg_century_read), | ||
| 87 | .buf = reg_century_read | ||
| 88 | }, | ||
| 89 | { | ||
| 90 | .addr = client->addr, | ||
| 91 | .flags = I2C_M_RD, | ||
| 92 | .len = sizeof(buf[MAX6900_REG_CENTURY]), | ||
| 93 | .buf = &buf[MAX6900_REG_CENTURY] | ||
| 74 | } | 94 | } |
| 75 | }; | 95 | }; |
| 76 | int rc; | 96 | int rc; |
| @@ -86,33 +106,58 @@ static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) | |||
| 86 | 106 | ||
| 87 | static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | 107 | static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) |
| 88 | { | 108 | { |
| 89 | u8 i2c_buf[MAX6900_REG_LEN + 1] = { MAX6900_REG_BURST_WRITE }; | 109 | u8 i2c_century_buf[1 + 1] = { MAX6900_REG_CENTURY_WRITE }; |
| 90 | struct i2c_msg msgs[1] = { | 110 | struct i2c_msg century_msgs[1] = { |
| 91 | { | 111 | { |
| 92 | .addr = client->addr, | 112 | .addr = client->addr, |
| 93 | .flags = 0, /* write */ | 113 | .flags = 0, /* write */ |
| 94 | .len = MAX6900_REG_LEN + 1, | 114 | .len = sizeof(i2c_century_buf), |
| 95 | .buf = i2c_buf | 115 | .buf = i2c_century_buf |
| 116 | } | ||
| 117 | }; | ||
| 118 | u8 i2c_burst_buf[MAX6900_BURST_LEN + 1] = { MAX6900_REG_BURST_WRITE }; | ||
| 119 | struct i2c_msg burst_msgs[1] = { | ||
| 120 | { | ||
| 121 | .addr = client->addr, | ||
| 122 | .flags = 0, /* write */ | ||
| 123 | .len = sizeof(i2c_burst_buf), | ||
| 124 | .buf = i2c_burst_buf | ||
| 96 | } | 125 | } |
| 97 | }; | 126 | }; |
| 98 | int rc; | 127 | int rc; |
| 99 | 128 | ||
| 100 | memcpy(&i2c_buf[1], buf, MAX6900_REG_LEN); | 129 | /* |
| 130 | * We have to make separate calls to i2c_transfer because of | ||
| 131 | * the need to delay after each write to the chip. Also, | ||
| 132 | * we write the century byte first, since we set the write-protect | ||
| 133 | * bit as part of the burst write. | ||
| 134 | */ | ||
| 135 | i2c_century_buf[1] = buf[MAX6900_REG_CENTURY]; | ||
| 136 | rc = i2c_transfer(client->adapter, century_msgs, | ||
| 137 | ARRAY_SIZE(century_msgs)); | ||
| 138 | if (rc != ARRAY_SIZE(century_msgs)) | ||
| 139 | goto write_failed; | ||
| 140 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); | ||
| 101 | 141 | ||
| 102 | rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | 142 | memcpy(&i2c_burst_buf[1], buf, MAX6900_BURST_LEN); |
| 103 | if (rc != ARRAY_SIZE(msgs)) { | 143 | |
| 104 | dev_err(&client->dev, "%s: register write failed\n", | 144 | rc = i2c_transfer(client->adapter, burst_msgs, ARRAY_SIZE(burst_msgs)); |
| 105 | __FUNCTION__); | 145 | if (rc != ARRAY_SIZE(burst_msgs)) |
| 106 | return -EIO; | 146 | goto write_failed; |
| 107 | } | ||
| 108 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); | 147 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); |
| 148 | |||
| 109 | return 0; | 149 | return 0; |
| 150 | |||
| 151 | write_failed: | ||
| 152 | dev_err(&client->dev, "%s: register write failed\n", | ||
| 153 | __FUNCTION__); | ||
| 154 | return -EIO; | ||
| 110 | } | 155 | } |
| 111 | 156 | ||
| 112 | static int max6900_i2c_validate_client(struct i2c_client *client) | 157 | static int max6900_i2c_validate_client(struct i2c_client *client) |
| 113 | { | 158 | { |
| 114 | u8 regs[MAX6900_REG_LEN]; | 159 | u8 regs[MAX6900_REG_LEN]; |
| 115 | u8 zero_mask[MAX6900_REG_LEN] = { | 160 | u8 zero_mask[] = { |
| 116 | 0x80, /* seconds */ | 161 | 0x80, /* seconds */ |
| 117 | 0x80, /* minutes */ | 162 | 0x80, /* minutes */ |
| 118 | 0x40, /* hours */ | 163 | 0x40, /* hours */ |
| @@ -134,7 +179,7 @@ static int max6900_i2c_validate_client(struct i2c_client *client) | |||
| 134 | if (rc < 0) | 179 | if (rc < 0) |
| 135 | return rc; | 180 | return rc; |
| 136 | 181 | ||
| 137 | for (i = 0; i < MAX6900_REG_LEN; ++i) { | 182 | for (i = 0; i < ARRAY_SIZE(zero_mask); ++i) { |
| 138 | if (regs[i] & zero_mask[i]) | 183 | if (regs[i] & zero_mask[i]) |
| 139 | return -ENODEV; | 184 | return -ENODEV; |
| 140 | } | 185 | } |
| @@ -156,7 +201,8 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
| 156 | tm->tm_hour = BCD2BIN(regs[MAX6900_REG_HR] & 0x3f); | 201 | tm->tm_hour = BCD2BIN(regs[MAX6900_REG_HR] & 0x3f); |
| 157 | tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]); | 202 | tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]); |
| 158 | tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1; | 203 | tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1; |
| 159 | tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) + 100; | 204 | tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) + |
| 205 | BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900; | ||
| 160 | tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]); | 206 | tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]); |
| 161 | 207 | ||
| 162 | return 0; | 208 | return 0; |
| @@ -189,9 +235,11 @@ static int max6900_i2c_set_time(struct i2c_client *client, | |||
| 189 | regs[MAX6900_REG_HR] = BIN2BCD(tm->tm_hour); | 235 | regs[MAX6900_REG_HR] = BIN2BCD(tm->tm_hour); |
| 190 | regs[MAX6900_REG_DT] = BIN2BCD(tm->tm_mday); | 236 | regs[MAX6900_REG_DT] = BIN2BCD(tm->tm_mday); |
| 191 | regs[MAX6900_REG_MO] = BIN2BCD(tm->tm_mon + 1); | 237 | regs[MAX6900_REG_MO] = BIN2BCD(tm->tm_mon + 1); |
| 192 | regs[MAX6900_REG_YR] = BIN2BCD(tm->tm_year - 100); | ||
| 193 | regs[MAX6900_REG_DW] = BIN2BCD(tm->tm_wday); | 238 | regs[MAX6900_REG_DW] = BIN2BCD(tm->tm_wday); |
| 194 | regs[MAX6900_REG_CT] = MAX6900_REG_CT_WP; /* set write protect */ | 239 | regs[MAX6900_REG_YR] = BIN2BCD(tm->tm_year % 100); |
| 240 | regs[MAX6900_REG_CENTURY] = BIN2BCD((tm->tm_year + 1900) / 100); | ||
| 241 | /* set write protect */ | ||
| 242 | regs[MAX6900_REG_CT] = MAX6900_REG_CT_WP; | ||
| 195 | 243 | ||
| 196 | rc = max6900_i2c_write_regs(client, regs); | 244 | rc = max6900_i2c_write_regs(client, regs); |
| 197 | if (rc < 0) | 245 | if (rc < 0) |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c new file mode 100644 index 000000000000..f10d3facecbe --- /dev/null +++ b/drivers/rtc/rtc-stk17ta8.c | |||
| @@ -0,0 +1,420 @@ | |||
| 1 | /* | ||
| 2 | * A RTC driver for the Simtek STK17TA8 | ||
| 3 | * | ||
| 4 | * By Thomas Hommel <thomas.hommel@gefanuc.com> | ||
| 5 | * | ||
| 6 | * Based on the DS1553 driver from | ||
| 7 | * Atsushi Nemoto <anemo@mba.ocn.ne.jp> | ||
| 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 version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/bcd.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/jiffies.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/rtc.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/io.h> | ||
| 23 | |||
| 24 | #define DRV_VERSION "0.1" | ||
| 25 | |||
| 26 | #define RTC_REG_SIZE 0x20000 | ||
| 27 | #define RTC_OFFSET 0x1fff0 | ||
| 28 | |||
| 29 | #define RTC_FLAGS (RTC_OFFSET + 0) | ||
| 30 | #define RTC_CENTURY (RTC_OFFSET + 1) | ||
| 31 | #define RTC_SECONDS_ALARM (RTC_OFFSET + 2) | ||
| 32 | #define RTC_MINUTES_ALARM (RTC_OFFSET + 3) | ||
| 33 | #define RTC_HOURS_ALARM (RTC_OFFSET + 4) | ||
| 34 | #define RTC_DATE_ALARM (RTC_OFFSET + 5) | ||
| 35 | #define RTC_INTERRUPTS (RTC_OFFSET + 6) | ||
| 36 | #define RTC_WATCHDOG (RTC_OFFSET + 7) | ||
| 37 | #define RTC_CALIBRATION (RTC_OFFSET + 8) | ||
| 38 | #define RTC_SECONDS (RTC_OFFSET + 9) | ||
| 39 | #define RTC_MINUTES (RTC_OFFSET + 10) | ||
| 40 | #define RTC_HOURS (RTC_OFFSET + 11) | ||
| 41 | #define RTC_DAY (RTC_OFFSET + 12) | ||
| 42 | #define RTC_DATE (RTC_OFFSET + 13) | ||
| 43 | #define RTC_MONTH (RTC_OFFSET + 14) | ||
| 44 | #define RTC_YEAR (RTC_OFFSET + 15) | ||
| 45 | |||
| 46 | #define RTC_SECONDS_MASK 0x7f | ||
| 47 | #define RTC_DAY_MASK 0x07 | ||
| 48 | #define RTC_CAL_MASK 0x3f | ||
| 49 | |||
| 50 | /* Bits in the Calibration register */ | ||
| 51 | #define RTC_STOP 0x80 | ||
| 52 | |||
| 53 | /* Bits in the Flags register */ | ||
| 54 | #define RTC_FLAGS_AF 0x40 | ||
| 55 | #define RTC_FLAGS_PF 0x20 | ||
| 56 | #define RTC_WRITE 0x02 | ||
| 57 | #define RTC_READ 0x01 | ||
| 58 | |||
| 59 | /* Bits in the Interrupts register */ | ||
| 60 | #define RTC_INTS_AIE 0x40 | ||
| 61 | |||
| 62 | struct rtc_plat_data { | ||
| 63 | struct rtc_device *rtc; | ||
| 64 | void __iomem *ioaddr; | ||
| 65 | unsigned long baseaddr; | ||
| 66 | unsigned long last_jiffies; | ||
| 67 | int irq; | ||
| 68 | unsigned int irqen; | ||
| 69 | int alrm_sec; | ||
| 70 | int alrm_min; | ||
| 71 | int alrm_hour; | ||
| 72 | int alrm_mday; | ||
| 73 | }; | ||
| 74 | |||
| 75 | static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 76 | { | ||
| 77 | struct platform_device *pdev = to_platform_device(dev); | ||
| 78 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 79 | void __iomem *ioaddr = pdata->ioaddr; | ||
| 80 | u8 flags; | ||
| 81 | |||
| 82 | flags = readb(pdata->ioaddr + RTC_FLAGS); | ||
| 83 | writeb(flags | RTC_WRITE, pdata->ioaddr + RTC_FLAGS); | ||
| 84 | |||
| 85 | writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR); | ||
| 86 | writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH); | ||
| 87 | writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); | ||
| 88 | writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE); | ||
| 89 | writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS); | ||
| 90 | writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES); | ||
| 91 | writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); | ||
| 92 | writeb(BIN2BCD((tm->tm_year + 1900) / 100), ioaddr + RTC_CENTURY); | ||
| 93 | |||
| 94 | writeb(flags & ~RTC_WRITE, pdata->ioaddr + RTC_FLAGS); | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int stk17ta8_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 99 | { | ||
| 100 | struct platform_device *pdev = to_platform_device(dev); | ||
| 101 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 102 | void __iomem *ioaddr = pdata->ioaddr; | ||
| 103 | unsigned int year, month, day, hour, minute, second, week; | ||
| 104 | unsigned int century; | ||
| 105 | u8 flags; | ||
| 106 | |||
| 107 | /* give enough time to update RTC in case of continuous read */ | ||
| 108 | if (pdata->last_jiffies == jiffies) | ||
| 109 | msleep(1); | ||
| 110 | pdata->last_jiffies = jiffies; | ||
| 111 | |||
| 112 | flags = readb(pdata->ioaddr + RTC_FLAGS); | ||
| 113 | writeb(flags | RTC_READ, ioaddr + RTC_FLAGS); | ||
| 114 | second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK; | ||
| 115 | minute = readb(ioaddr + RTC_MINUTES); | ||
| 116 | hour = readb(ioaddr + RTC_HOURS); | ||
| 117 | day = readb(ioaddr + RTC_DATE); | ||
| 118 | week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK; | ||
| 119 | month = readb(ioaddr + RTC_MONTH); | ||
| 120 | year = readb(ioaddr + RTC_YEAR); | ||
| 121 | century = readb(ioaddr + RTC_CENTURY); | ||
| 122 | writeb(flags & ~RTC_READ, ioaddr + RTC_FLAGS); | ||
| 123 | tm->tm_sec = BCD2BIN(second); | ||
| 124 | tm->tm_min = BCD2BIN(minute); | ||
| 125 | tm->tm_hour = BCD2BIN(hour); | ||
| 126 | tm->tm_mday = BCD2BIN(day); | ||
| 127 | tm->tm_wday = BCD2BIN(week); | ||
| 128 | tm->tm_mon = BCD2BIN(month) - 1; | ||
| 129 | /* year is 1900 + tm->tm_year */ | ||
| 130 | tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900; | ||
| 131 | |||
| 132 | if (rtc_valid_tm(tm) < 0) { | ||
| 133 | dev_err(dev, "retrieved date/time is not valid.\n"); | ||
| 134 | rtc_time_to_tm(0, tm); | ||
| 135 | } | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata) | ||
| 140 | { | ||
| 141 | void __iomem *ioaddr = pdata->ioaddr; | ||
| 142 | unsigned long irqflags; | ||
| 143 | u8 flags; | ||
| 144 | |||
| 145 | spin_lock_irqsave(&pdata->rtc->irq_lock, irqflags); | ||
| 146 | |||
| 147 | flags = readb(ioaddr + RTC_FLAGS); | ||
| 148 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); | ||
| 149 | |||
| 150 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | ||
| 151 | 0x80 : BIN2BCD(pdata->alrm_mday), | ||
| 152 | ioaddr + RTC_DATE_ALARM); | ||
| 153 | writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? | ||
| 154 | 0x80 : BIN2BCD(pdata->alrm_hour), | ||
| 155 | ioaddr + RTC_HOURS_ALARM); | ||
| 156 | writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? | ||
| 157 | 0x80 : BIN2BCD(pdata->alrm_min), | ||
| 158 | ioaddr + RTC_MINUTES_ALARM); | ||
| 159 | writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? | ||
| 160 | 0x80 : BIN2BCD(pdata->alrm_sec), | ||
| 161 | ioaddr + RTC_SECONDS_ALARM); | ||
| 162 | writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); | ||
| 163 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ | ||
| 164 | writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS); | ||
| 165 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, irqflags); | ||
| 166 | } | ||
| 167 | |||
| 168 | static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 169 | { | ||
| 170 | struct platform_device *pdev = to_platform_device(dev); | ||
| 171 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 172 | |||
| 173 | if (pdata->irq < 0) | ||
| 174 | return -EINVAL; | ||
| 175 | pdata->alrm_mday = alrm->time.tm_mday; | ||
| 176 | pdata->alrm_hour = alrm->time.tm_hour; | ||
| 177 | pdata->alrm_min = alrm->time.tm_min; | ||
| 178 | pdata->alrm_sec = alrm->time.tm_sec; | ||
| 179 | if (alrm->enabled) | ||
| 180 | pdata->irqen |= RTC_AF; | ||
| 181 | stk17ta8_rtc_update_alarm(pdata); | ||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | static int stk17ta8_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 186 | { | ||
| 187 | struct platform_device *pdev = to_platform_device(dev); | ||
| 188 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 189 | |||
| 190 | if (pdata->irq < 0) | ||
| 191 | return -EINVAL; | ||
| 192 | alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday; | ||
| 193 | alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour; | ||
| 194 | alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min; | ||
| 195 | alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec; | ||
| 196 | alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0; | ||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id) | ||
| 201 | { | ||
| 202 | struct platform_device *pdev = dev_id; | ||
| 203 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 204 | void __iomem *ioaddr = pdata->ioaddr; | ||
| 205 | unsigned long events = RTC_IRQF; | ||
| 206 | |||
| 207 | /* read and clear interrupt */ | ||
| 208 | if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) | ||
| 209 | return IRQ_NONE; | ||
| 210 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) | ||
| 211 | events |= RTC_UF; | ||
| 212 | else | ||
| 213 | events |= RTC_AF; | ||
| 214 | rtc_update_irq(pdata->rtc, 1, events); | ||
| 215 | return IRQ_HANDLED; | ||
| 216 | } | ||
| 217 | |||
| 218 | static void stk17ta8_rtc_release(struct device *dev) | ||
| 219 | { | ||
| 220 | struct platform_device *pdev = to_platform_device(dev); | ||
| 221 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 222 | |||
| 223 | if (pdata->irq >= 0) { | ||
| 224 | pdata->irqen = 0; | ||
| 225 | stk17ta8_rtc_update_alarm(pdata); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
| 230 | unsigned long arg) | ||
| 231 | { | ||
| 232 | struct platform_device *pdev = to_platform_device(dev); | ||
| 233 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 234 | |||
| 235 | if (pdata->irq < 0) | ||
| 236 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | ||
| 237 | switch (cmd) { | ||
| 238 | case RTC_AIE_OFF: | ||
| 239 | pdata->irqen &= ~RTC_AF; | ||
| 240 | stk17ta8_rtc_update_alarm(pdata); | ||
| 241 | break; | ||
| 242 | case RTC_AIE_ON: | ||
| 243 | pdata->irqen |= RTC_AF; | ||
| 244 | stk17ta8_rtc_update_alarm(pdata); | ||
| 245 | break; | ||
| 246 | default: | ||
| 247 | return -ENOIOCTLCMD; | ||
| 248 | } | ||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | static const struct rtc_class_ops stk17ta8_rtc_ops = { | ||
| 253 | .read_time = stk17ta8_rtc_read_time, | ||
| 254 | .set_time = stk17ta8_rtc_set_time, | ||
| 255 | .read_alarm = stk17ta8_rtc_read_alarm, | ||
| 256 | .set_alarm = stk17ta8_rtc_set_alarm, | ||
| 257 | .release = stk17ta8_rtc_release, | ||
| 258 | .ioctl = stk17ta8_rtc_ioctl, | ||
| 259 | }; | ||
| 260 | |||
| 261 | static ssize_t stk17ta8_nvram_read(struct kobject *kobj, char *buf, | ||
| 262 | loff_t pos, size_t size) | ||
| 263 | { | ||
| 264 | struct platform_device *pdev = | ||
| 265 | to_platform_device(container_of(kobj, struct device, kobj)); | ||
| 266 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 267 | void __iomem *ioaddr = pdata->ioaddr; | ||
| 268 | ssize_t count; | ||
| 269 | |||
| 270 | for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) | ||
| 271 | *buf++ = readb(ioaddr + pos++); | ||
| 272 | return count; | ||
| 273 | } | ||
| 274 | |||
| 275 | static ssize_t stk17ta8_nvram_write(struct kobject *kobj, char *buf, | ||
| 276 | loff_t pos, size_t size) | ||
| 277 | { | ||
| 278 | struct platform_device *pdev = | ||
| 279 | to_platform_device(container_of(kobj, struct device, kobj)); | ||
| 280 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 281 | void __iomem *ioaddr = pdata->ioaddr; | ||
| 282 | ssize_t count; | ||
| 283 | |||
| 284 | for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) | ||
| 285 | writeb(*buf++, ioaddr + pos++); | ||
| 286 | return count; | ||
| 287 | } | ||
| 288 | |||
| 289 | static struct bin_attribute stk17ta8_nvram_attr = { | ||
| 290 | .attr = { | ||
| 291 | .name = "nvram", | ||
| 292 | .mode = S_IRUGO | S_IWUGO, | ||
| 293 | .owner = THIS_MODULE, | ||
| 294 | }, | ||
| 295 | .size = RTC_OFFSET, | ||
| 296 | .read = stk17ta8_nvram_read, | ||
| 297 | .write = stk17ta8_nvram_write, | ||
| 298 | }; | ||
| 299 | |||
| 300 | static int __init stk17ta8_rtc_probe(struct platform_device *pdev) | ||
| 301 | { | ||
| 302 | struct rtc_device *rtc; | ||
| 303 | struct resource *res; | ||
| 304 | unsigned int cal; | ||
| 305 | unsigned int flags; | ||
| 306 | struct rtc_plat_data *pdata; | ||
| 307 | void __iomem *ioaddr = NULL; | ||
| 308 | int ret = 0; | ||
| 309 | |||
| 310 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 311 | if (!res) | ||
| 312 | return -ENODEV; | ||
| 313 | |||
| 314 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
| 315 | if (!pdata) | ||
| 316 | return -ENOMEM; | ||
| 317 | pdata->irq = -1; | ||
| 318 | if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { | ||
| 319 | ret = -EBUSY; | ||
| 320 | goto out; | ||
| 321 | } | ||
| 322 | pdata->baseaddr = res->start; | ||
| 323 | ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); | ||
| 324 | if (!ioaddr) { | ||
| 325 | ret = -ENOMEM; | ||
| 326 | goto out; | ||
| 327 | } | ||
| 328 | pdata->ioaddr = ioaddr; | ||
| 329 | pdata->irq = platform_get_irq(pdev, 0); | ||
| 330 | |||
| 331 | /* turn RTC on if it was not on */ | ||
| 332 | cal = readb(ioaddr + RTC_CALIBRATION); | ||
| 333 | if (cal & RTC_STOP) { | ||
| 334 | cal &= RTC_CAL_MASK; | ||
| 335 | flags = readb(ioaddr + RTC_FLAGS); | ||
| 336 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); | ||
| 337 | writeb(cal, ioaddr + RTC_CALIBRATION); | ||
| 338 | writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS); | ||
| 339 | } | ||
| 340 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF) | ||
| 341 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | ||
| 342 | |||
| 343 | if (pdata->irq >= 0) { | ||
| 344 | writeb(0, ioaddr + RTC_INTERRUPTS); | ||
| 345 | if (request_irq(pdata->irq, stk17ta8_rtc_interrupt, | ||
| 346 | IRQF_DISABLED | IRQF_SHARED, | ||
| 347 | pdev->name, pdev) < 0) { | ||
| 348 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
| 349 | pdata->irq = -1; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
| 354 | &stk17ta8_rtc_ops, THIS_MODULE); | ||
| 355 | if (IS_ERR(rtc)) { | ||
| 356 | ret = PTR_ERR(rtc); | ||
| 357 | goto out; | ||
| 358 | } | ||
| 359 | pdata->rtc = rtc; | ||
| 360 | pdata->last_jiffies = jiffies; | ||
| 361 | platform_set_drvdata(pdev, pdata); | ||
| 362 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); | ||
| 363 | if (ret) | ||
| 364 | goto out; | ||
| 365 | return 0; | ||
| 366 | out: | ||
| 367 | if (pdata->rtc) | ||
| 368 | rtc_device_unregister(pdata->rtc); | ||
| 369 | if (pdata->irq >= 0) | ||
| 370 | free_irq(pdata->irq, pdev); | ||
| 371 | if (ioaddr) | ||
| 372 | iounmap(ioaddr); | ||
| 373 | if (pdata->baseaddr) | ||
| 374 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
| 375 | kfree(pdata); | ||
| 376 | return ret; | ||
| 377 | } | ||
| 378 | |||
| 379 | static int __devexit stk17ta8_rtc_remove(struct platform_device *pdev) | ||
| 380 | { | ||
| 381 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 382 | |||
| 383 | sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); | ||
| 384 | rtc_device_unregister(pdata->rtc); | ||
| 385 | if (pdata->irq >= 0) { | ||
| 386 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); | ||
| 387 | free_irq(pdata->irq, pdev); | ||
| 388 | } | ||
| 389 | iounmap(pdata->ioaddr); | ||
| 390 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
| 391 | kfree(pdata); | ||
| 392 | return 0; | ||
| 393 | } | ||
| 394 | |||
| 395 | static struct platform_driver stk17ta8_rtc_driver = { | ||
| 396 | .probe = stk17ta8_rtc_probe, | ||
| 397 | .remove = __devexit_p(stk17ta8_rtc_remove), | ||
| 398 | .driver = { | ||
| 399 | .name = "stk17ta8", | ||
| 400 | .owner = THIS_MODULE, | ||
| 401 | }, | ||
| 402 | }; | ||
| 403 | |||
| 404 | static __init int stk17ta8_init(void) | ||
| 405 | { | ||
| 406 | return platform_driver_register(&stk17ta8_rtc_driver); | ||
| 407 | } | ||
| 408 | |||
| 409 | static __exit void stk17ta8_exit(void) | ||
| 410 | { | ||
| 411 | return platform_driver_unregister(&stk17ta8_rtc_driver); | ||
| 412 | } | ||
| 413 | |||
| 414 | module_init(stk17ta8_init); | ||
| 415 | module_exit(stk17ta8_exit); | ||
| 416 | |||
| 417 | MODULE_AUTHOR("Thomas Hommel <thomas.hommel@gefanuc.com>"); | ||
| 418 | MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); | ||
| 419 | MODULE_LICENSE("GPL"); | ||
| 420 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 9726261c367d..ab5ec1feaf4e 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
| @@ -1526,15 +1526,12 @@ zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool) | |||
| 1526 | * zfcp_gid_pn_buffers_free - free buffers for GID_PN nameserver request | 1526 | * zfcp_gid_pn_buffers_free - free buffers for GID_PN nameserver request |
| 1527 | * @gid_pn: pointer to struct zfcp_gid_pn_data which has to be freed | 1527 | * @gid_pn: pointer to struct zfcp_gid_pn_data which has to be freed |
| 1528 | */ | 1528 | */ |
| 1529 | static void | 1529 | static void zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn) |
| 1530 | zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn) | ||
| 1531 | { | 1530 | { |
| 1532 | if ((gid_pn->ct.pool != 0)) | 1531 | if (gid_pn->ct.pool) |
| 1533 | mempool_free(gid_pn, gid_pn->ct.pool); | 1532 | mempool_free(gid_pn, gid_pn->ct.pool); |
| 1534 | else | 1533 | else |
| 1535 | kfree(gid_pn); | 1534 | kfree(gid_pn); |
| 1536 | |||
| 1537 | return; | ||
| 1538 | } | 1535 | } |
| 1539 | 1536 | ||
| 1540 | /** | 1537 | /** |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 22649639230b..b36dfc40d9fa 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
| @@ -126,6 +126,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list) | |||
| 126 | #define ZFCP_MIN_OUTPUT_THRESHOLD 1 /* ignored by QDIO layer */ | 126 | #define ZFCP_MIN_OUTPUT_THRESHOLD 1 /* ignored by QDIO layer */ |
| 127 | 127 | ||
| 128 | #define QDIO_SCSI_QFMT 1 /* 1 for FSF */ | 128 | #define QDIO_SCSI_QFMT 1 /* 1 for FSF */ |
| 129 | #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) | ||
| 129 | 130 | ||
| 130 | /********************* FSF SPECIFIC DEFINES *********************************/ | 131 | /********************* FSF SPECIFIC DEFINES *********************************/ |
| 131 | 132 | ||
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 4e7cb6dc4d34..d8cd75ce2d9a 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
| @@ -1626,7 +1626,7 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit) | |||
| 1626 | { | 1626 | { |
| 1627 | struct zfcp_erp_add_work *p; | 1627 | struct zfcp_erp_add_work *p; |
| 1628 | 1628 | ||
| 1629 | p = kmalloc(sizeof(*p), GFP_KERNEL); | 1629 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 1630 | if (!p) { | 1630 | if (!p) { |
| 1631 | ZFCP_LOG_NORMAL("error: Out of resources. Could not register " | 1631 | ZFCP_LOG_NORMAL("error: Out of resources. Could not register " |
| 1632 | "the FCP-LUN 0x%Lx connected to " | 1632 | "the FCP-LUN 0x%Lx connected to " |
| @@ -1639,7 +1639,6 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit) | |||
| 1639 | } | 1639 | } |
| 1640 | 1640 | ||
| 1641 | zfcp_unit_get(unit); | 1641 | zfcp_unit_get(unit); |
| 1642 | memset(p, 0, sizeof(*p)); | ||
| 1643 | atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | 1642 | atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); |
| 1644 | INIT_WORK(&p->work, zfcp_erp_scsi_scan); | 1643 | INIT_WORK(&p->work, zfcp_erp_scsi_scan); |
| 1645 | p->unit = unit; | 1644 | p->unit = unit; |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 0eb31e162b15..b240800b78d7 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
| @@ -1930,7 +1930,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) | |||
| 1930 | skip_fsfstatus: | 1930 | skip_fsfstatus: |
| 1931 | send_els->status = retval; | 1931 | send_els->status = retval; |
| 1932 | 1932 | ||
| 1933 | if (send_els->handler != 0) | 1933 | if (send_els->handler) |
| 1934 | send_els->handler(send_els->handler_data); | 1934 | send_els->handler(send_els->handler_data); |
| 1935 | 1935 | ||
| 1936 | return retval; | 1936 | return retval; |
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index bdf5782b8a7a..c408badd2ae9 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
| @@ -47,103 +47,56 @@ static int zfcp_qdio_handler_error_check(struct zfcp_adapter *, | |||
| 47 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO | 47 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO |
| 48 | 48 | ||
| 49 | /* | 49 | /* |
| 50 | * Allocates BUFFER memory to each of the pointers of the qdio_buffer_t | 50 | * Frees BUFFER memory for each of the pointers of the struct qdio_buffer array |
| 51 | * array in the adapter struct. | 51 | * in the adapter struct sbuf is the pointer array. |
| 52 | * Cur_buf is the pointer array and count can be any number of required | ||
| 53 | * buffers, the page-fitting arithmetic is done entirely within this funciton. | ||
| 54 | * | 52 | * |
| 55 | * returns: number of buffers allocated | ||
| 56 | * locks: must only be called with zfcp_data.config_sema taken | 53 | * locks: must only be called with zfcp_data.config_sema taken |
| 57 | */ | 54 | */ |
| 58 | static int | 55 | static void |
| 59 | zfcp_qdio_buffers_enqueue(struct qdio_buffer **cur_buf, int count) | 56 | zfcp_qdio_buffers_dequeue(struct qdio_buffer **sbuf) |
| 60 | { | 57 | { |
| 61 | int buf_pos; | 58 | int pos; |
| 62 | int qdio_buffers_per_page; | ||
| 63 | int page_pos = 0; | ||
| 64 | struct qdio_buffer *first_in_page = NULL; | ||
| 65 | |||
| 66 | qdio_buffers_per_page = PAGE_SIZE / sizeof (struct qdio_buffer); | ||
| 67 | ZFCP_LOG_TRACE("buffers_per_page=%d\n", qdio_buffers_per_page); | ||
| 68 | |||
| 69 | for (buf_pos = 0; buf_pos < count; buf_pos++) { | ||
| 70 | if (page_pos == 0) { | ||
| 71 | cur_buf[buf_pos] = (struct qdio_buffer *) | ||
| 72 | get_zeroed_page(GFP_KERNEL); | ||
| 73 | if (cur_buf[buf_pos] == NULL) { | ||
| 74 | ZFCP_LOG_INFO("error: allocation of " | ||
| 75 | "QDIO buffer failed \n"); | ||
| 76 | goto out; | ||
| 77 | } | ||
| 78 | first_in_page = cur_buf[buf_pos]; | ||
| 79 | } else { | ||
| 80 | cur_buf[buf_pos] = first_in_page + page_pos; | ||
| 81 | 59 | ||
| 82 | } | 60 | for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE) |
| 83 | /* was initialised to zero */ | 61 | free_page((unsigned long) sbuf[pos]); |
| 84 | page_pos++; | ||
| 85 | page_pos %= qdio_buffers_per_page; | ||
| 86 | } | ||
| 87 | out: | ||
| 88 | return buf_pos; | ||
| 89 | } | 62 | } |
| 90 | 63 | ||
| 91 | /* | 64 | /* |
| 92 | * Frees BUFFER memory for each of the pointers of the struct qdio_buffer array | 65 | * Allocates BUFFER memory to each of the pointers of the qdio_buffer_t |
| 93 | * in the adapter struct cur_buf is the pointer array and count can be any | 66 | * array in the adapter struct. |
| 94 | * number of buffers in the array that should be freed starting from buffer 0 | 67 | * Cur_buf is the pointer array |
| 95 | * | 68 | * |
| 69 | * returns: zero on success else -ENOMEM | ||
| 96 | * locks: must only be called with zfcp_data.config_sema taken | 70 | * locks: must only be called with zfcp_data.config_sema taken |
| 97 | */ | 71 | */ |
| 98 | static void | 72 | static int |
| 99 | zfcp_qdio_buffers_dequeue(struct qdio_buffer **cur_buf, int count) | 73 | zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbuf) |
| 100 | { | 74 | { |
| 101 | int buf_pos; | 75 | int pos; |
| 102 | int qdio_buffers_per_page; | ||
| 103 | |||
| 104 | qdio_buffers_per_page = PAGE_SIZE / sizeof (struct qdio_buffer); | ||
| 105 | ZFCP_LOG_TRACE("buffers_per_page=%d\n", qdio_buffers_per_page); | ||
| 106 | 76 | ||
| 107 | for (buf_pos = 0; buf_pos < count; buf_pos += qdio_buffers_per_page) | 77 | for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE) { |
| 108 | free_page((unsigned long) cur_buf[buf_pos]); | 78 | sbuf[pos] = (struct qdio_buffer *) get_zeroed_page(GFP_KERNEL); |
| 109 | return; | 79 | if (!sbuf[pos]) { |
| 80 | zfcp_qdio_buffers_dequeue(sbuf); | ||
| 81 | return -ENOMEM; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos++) | ||
| 85 | if (pos % QBUFF_PER_PAGE) | ||
| 86 | sbuf[pos] = sbuf[pos - 1] + 1; | ||
| 87 | return 0; | ||
| 110 | } | 88 | } |
| 111 | 89 | ||
| 112 | /* locks: must only be called with zfcp_data.config_sema taken */ | 90 | /* locks: must only be called with zfcp_data.config_sema taken */ |
| 113 | int | 91 | int |
| 114 | zfcp_qdio_allocate_queues(struct zfcp_adapter *adapter) | 92 | zfcp_qdio_allocate_queues(struct zfcp_adapter *adapter) |
| 115 | { | 93 | { |
| 116 | int buffer_count; | 94 | int ret; |
| 117 | int retval = 0; | ||
| 118 | 95 | ||
| 119 | buffer_count = | 96 | ret = zfcp_qdio_buffers_enqueue(adapter->request_queue.buffer); |
| 120 | zfcp_qdio_buffers_enqueue(&(adapter->request_queue.buffer[0]), | 97 | if (ret) |
| 121 | QDIO_MAX_BUFFERS_PER_Q); | 98 | return ret; |
| 122 | if (buffer_count < QDIO_MAX_BUFFERS_PER_Q) { | 99 | return zfcp_qdio_buffers_enqueue(adapter->response_queue.buffer); |
| 123 | ZFCP_LOG_DEBUG("only %d QDIO buffers allocated for request " | ||
| 124 | "queue\n", buffer_count); | ||
| 125 | zfcp_qdio_buffers_dequeue(&(adapter->request_queue.buffer[0]), | ||
| 126 | buffer_count); | ||
| 127 | retval = -ENOMEM; | ||
| 128 | goto out; | ||
| 129 | } | ||
| 130 | |||
| 131 | buffer_count = | ||
| 132 | zfcp_qdio_buffers_enqueue(&(adapter->response_queue.buffer[0]), | ||
| 133 | QDIO_MAX_BUFFERS_PER_Q); | ||
| 134 | if (buffer_count < QDIO_MAX_BUFFERS_PER_Q) { | ||
| 135 | ZFCP_LOG_DEBUG("only %d QDIO buffers allocated for response " | ||
| 136 | "queue", buffer_count); | ||
| 137 | zfcp_qdio_buffers_dequeue(&(adapter->response_queue.buffer[0]), | ||
| 138 | buffer_count); | ||
| 139 | ZFCP_LOG_TRACE("freeing request_queue buffers\n"); | ||
| 140 | zfcp_qdio_buffers_dequeue(&(adapter->request_queue.buffer[0]), | ||
| 141 | QDIO_MAX_BUFFERS_PER_Q); | ||
| 142 | retval = -ENOMEM; | ||
| 143 | goto out; | ||
| 144 | } | ||
| 145 | out: | ||
| 146 | return retval; | ||
| 147 | } | 100 | } |
| 148 | 101 | ||
| 149 | /* locks: must only be called with zfcp_data.config_sema taken */ | 102 | /* locks: must only be called with zfcp_data.config_sema taken */ |
| @@ -151,12 +104,10 @@ void | |||
| 151 | zfcp_qdio_free_queues(struct zfcp_adapter *adapter) | 104 | zfcp_qdio_free_queues(struct zfcp_adapter *adapter) |
| 152 | { | 105 | { |
| 153 | ZFCP_LOG_TRACE("freeing request_queue buffers\n"); | 106 | ZFCP_LOG_TRACE("freeing request_queue buffers\n"); |
| 154 | zfcp_qdio_buffers_dequeue(&(adapter->request_queue.buffer[0]), | 107 | zfcp_qdio_buffers_dequeue(adapter->request_queue.buffer); |
| 155 | QDIO_MAX_BUFFERS_PER_Q); | ||
| 156 | 108 | ||
| 157 | ZFCP_LOG_TRACE("freeing response_queue buffers\n"); | 109 | ZFCP_LOG_TRACE("freeing response_queue buffers\n"); |
| 158 | zfcp_qdio_buffers_dequeue(&(adapter->response_queue.buffer[0]), | 110 | zfcp_qdio_buffers_dequeue(adapter->response_queue.buffer); |
| 159 | QDIO_MAX_BUFFERS_PER_Q); | ||
| 160 | } | 111 | } |
| 161 | 112 | ||
| 162 | int | 113 | int |
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 6b49f6a2524d..efd9d8d3a890 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | Written By: Adam Radford <linuxraid@amcc.com> | 4 | Written By: Adam Radford <linuxraid@amcc.com> |
| 5 | Modifications By: Tom Couch <linuxraid@amcc.com> | 5 | Modifications By: Tom Couch <linuxraid@amcc.com> |
| 6 | 6 | ||
| 7 | Copyright (C) 2004-2006 Applied Micro Circuits Corporation. | 7 | Copyright (C) 2004-2007 Applied Micro Circuits Corporation. |
| 8 | 8 | ||
| 9 | This program is free software; you can redistribute it and/or modify | 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 | 10 | it under the terms of the GNU General Public License as published by |
| @@ -69,6 +69,8 @@ | |||
| 69 | 2.26.02.008 - Free irq handler in __twa_shutdown(). | 69 | 2.26.02.008 - Free irq handler in __twa_shutdown(). |
| 70 | Serialize reset code. | 70 | Serialize reset code. |
| 71 | Add support for 9650SE controllers. | 71 | Add support for 9650SE controllers. |
| 72 | 2.26.02.009 - Fix dma mask setting to fallback to 32-bit if 64-bit fails. | ||
| 73 | 2.26.02.010 - Add support for 9690SA controllers. | ||
| 72 | */ | 74 | */ |
| 73 | 75 | ||
| 74 | #include <linux/module.h> | 76 | #include <linux/module.h> |
| @@ -92,7 +94,7 @@ | |||
| 92 | #include "3w-9xxx.h" | 94 | #include "3w-9xxx.h" |
| 93 | 95 | ||
| 94 | /* Globals */ | 96 | /* Globals */ |
| 95 | #define TW_DRIVER_VERSION "2.26.02.008" | 97 | #define TW_DRIVER_VERSION "2.26.02.010" |
| 96 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; | 98 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; |
| 97 | static unsigned int twa_device_extension_count; | 99 | static unsigned int twa_device_extension_count; |
| 98 | static int twa_major = -1; | 100 | static int twa_major = -1; |
| @@ -124,11 +126,11 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, | |||
| 124 | unsigned short *fw_on_ctlr_branch, | 126 | unsigned short *fw_on_ctlr_branch, |
| 125 | unsigned short *fw_on_ctlr_build, | 127 | unsigned short *fw_on_ctlr_build, |
| 126 | u32 *init_connect_result); | 128 | u32 *init_connect_result); |
| 127 | static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); | 129 | static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); |
| 128 | static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds); | 130 | static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds); |
| 129 | static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); | 131 | static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); |
| 130 | static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); | 132 | static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); |
| 131 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset); | 133 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev); |
| 132 | static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); | 134 | static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); |
| 133 | static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); | 135 | static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); |
| 134 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); | 136 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); |
| @@ -683,7 +685,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int | |||
| 683 | full_command_packet = &tw_ioctl->firmware_command; | 685 | full_command_packet = &tw_ioctl->firmware_command; |
| 684 | 686 | ||
| 685 | /* Load request id and sglist for both command types */ | 687 | /* Load request id and sglist for both command types */ |
| 686 | twa_load_sgl(full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); | 688 | twa_load_sgl(tw_dev, full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); |
| 687 | 689 | ||
| 688 | memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full)); | 690 | memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full)); |
| 689 | 691 | ||
| @@ -700,10 +702,10 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int | |||
| 700 | if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { | 702 | if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { |
| 701 | /* Now we need to reset the board */ | 703 | /* Now we need to reset the board */ |
| 702 | printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n", | 704 | printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n", |
| 703 | tw_dev->host->host_no, TW_DRIVER, 0xc, | 705 | tw_dev->host->host_no, TW_DRIVER, 0x37, |
| 704 | cmd); | 706 | cmd); |
| 705 | retval = TW_IOCTL_ERROR_OS_EIO; | 707 | retval = TW_IOCTL_ERROR_OS_EIO; |
| 706 | twa_reset_device_extension(tw_dev, 1); | 708 | twa_reset_device_extension(tw_dev); |
| 707 | goto out3; | 709 | goto out3; |
| 708 | } | 710 | } |
| 709 | 711 | ||
| @@ -890,7 +892,9 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) | |||
| 890 | } | 892 | } |
| 891 | 893 | ||
| 892 | if (status_reg_value & TW_STATUS_QUEUE_ERROR) { | 894 | if (status_reg_value & TW_STATUS_QUEUE_ERROR) { |
| 893 | if ((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) || (!test_bit(TW_IN_RESET, &tw_dev->flags))) | 895 | if (((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) && |
| 896 | (tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9690SA)) || | ||
| 897 | (!test_bit(TW_IN_RESET, &tw_dev->flags))) | ||
| 894 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); | 898 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); |
| 895 | writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); | 899 | writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); |
| 896 | } | 900 | } |
| @@ -935,8 +939,7 @@ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) | |||
| 935 | unsigned long before; | 939 | unsigned long before; |
| 936 | int retval = 1; | 940 | int retval = 1; |
| 937 | 941 | ||
| 938 | if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) || | 942 | if (tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9000) { |
| 939 | (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) { | ||
| 940 | before = jiffies; | 943 | before = jiffies; |
| 941 | while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { | 944 | while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { |
| 942 | response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); | 945 | response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); |
| @@ -1195,7 +1198,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) | |||
| 1195 | u32 status_reg_value; | 1198 | u32 status_reg_value; |
| 1196 | TW_Response_Queue response_que; | 1199 | TW_Response_Queue response_que; |
| 1197 | TW_Command_Full *full_command_packet; | 1200 | TW_Command_Full *full_command_packet; |
| 1198 | TW_Command *command_packet; | ||
| 1199 | TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; | 1201 | TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; |
| 1200 | int handled = 0; | 1202 | int handled = 0; |
| 1201 | 1203 | ||
| @@ -1273,7 +1275,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) | |||
| 1273 | request_id = TW_RESID_OUT(response_que.response_id); | 1275 | request_id = TW_RESID_OUT(response_que.response_id); |
| 1274 | full_command_packet = tw_dev->command_packet_virt[request_id]; | 1276 | full_command_packet = tw_dev->command_packet_virt[request_id]; |
| 1275 | error = 0; | 1277 | error = 0; |
| 1276 | command_packet = &full_command_packet->command.oldcommand; | ||
| 1277 | /* Check for command packet errors */ | 1278 | /* Check for command packet errors */ |
| 1278 | if (full_command_packet->command.newcommand.status != 0) { | 1279 | if (full_command_packet->command.newcommand.status != 0) { |
| 1279 | if (tw_dev->srb[request_id] != 0) { | 1280 | if (tw_dev->srb[request_id] != 0) { |
| @@ -1352,11 +1353,15 @@ twa_interrupt_bail: | |||
| 1352 | } /* End twa_interrupt() */ | 1353 | } /* End twa_interrupt() */ |
| 1353 | 1354 | ||
| 1354 | /* This function will load the request id and various sgls for ioctls */ | 1355 | /* This function will load the request id and various sgls for ioctls */ |
| 1355 | static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) | 1356 | static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) |
| 1356 | { | 1357 | { |
| 1357 | TW_Command *oldcommand; | 1358 | TW_Command *oldcommand; |
| 1358 | TW_Command_Apache *newcommand; | 1359 | TW_Command_Apache *newcommand; |
| 1359 | TW_SG_Entry *sgl; | 1360 | TW_SG_Entry *sgl; |
| 1361 | unsigned int pae = 0; | ||
| 1362 | |||
| 1363 | if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) | ||
| 1364 | pae = 1; | ||
| 1360 | 1365 | ||
| 1361 | if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { | 1366 | if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { |
| 1362 | newcommand = &full_command_packet->command.newcommand; | 1367 | newcommand = &full_command_packet->command.newcommand; |
| @@ -1372,12 +1377,14 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d | |||
| 1372 | 1377 | ||
| 1373 | if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { | 1378 | if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { |
| 1374 | /* Load the sg list */ | 1379 | /* Load the sg list */ |
| 1375 | sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); | 1380 | if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA) |
| 1381 | sgl = (TW_SG_Entry *)((u32 *)oldcommand+oldcommand->size - (sizeof(TW_SG_Entry)/4) + pae); | ||
| 1382 | else | ||
| 1383 | sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); | ||
| 1376 | sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); | 1384 | sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); |
| 1377 | sgl->length = cpu_to_le32(length); | 1385 | sgl->length = cpu_to_le32(length); |
| 1378 | 1386 | ||
| 1379 | if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) | 1387 | oldcommand->size += pae; |
| 1380 | oldcommand->size += 1; | ||
| 1381 | } | 1388 | } |
| 1382 | } | 1389 | } |
| 1383 | } /* End twa_load_sgl() */ | 1390 | } /* End twa_load_sgl() */ |
| @@ -1506,7 +1513,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, | |||
| 1506 | command_que_value = tw_dev->command_packet_phys[request_id]; | 1513 | command_que_value = tw_dev->command_packet_phys[request_id]; |
| 1507 | 1514 | ||
| 1508 | /* For 9650SE write low 4 bytes first */ | 1515 | /* For 9650SE write low 4 bytes first */ |
| 1509 | if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { | 1516 | if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) || |
| 1517 | (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) { | ||
| 1510 | command_que_value += TW_COMMAND_OFFSET; | 1518 | command_que_value += TW_COMMAND_OFFSET; |
| 1511 | writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); | 1519 | writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); |
| 1512 | } | 1520 | } |
| @@ -1537,7 +1545,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, | |||
| 1537 | TW_UNMASK_COMMAND_INTERRUPT(tw_dev); | 1545 | TW_UNMASK_COMMAND_INTERRUPT(tw_dev); |
| 1538 | goto out; | 1546 | goto out; |
| 1539 | } else { | 1547 | } else { |
| 1540 | if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { | 1548 | if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) || |
| 1549 | (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) { | ||
| 1541 | /* Now write upper 4 bytes */ | 1550 | /* Now write upper 4 bytes */ |
| 1542 | writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); | 1551 | writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); |
| 1543 | } else { | 1552 | } else { |
| @@ -1561,7 +1570,7 @@ out: | |||
| 1561 | } /* End twa_post_command_packet() */ | 1570 | } /* End twa_post_command_packet() */ |
| 1562 | 1571 | ||
| 1563 | /* This function will reset a device extension */ | 1572 | /* This function will reset a device extension */ |
| 1564 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset) | 1573 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev) |
| 1565 | { | 1574 | { |
| 1566 | int i = 0; | 1575 | int i = 0; |
| 1567 | int retval = 1; | 1576 | int retval = 1; |
| @@ -1719,7 +1728,7 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt) | |||
| 1719 | mutex_lock(&tw_dev->ioctl_lock); | 1728 | mutex_lock(&tw_dev->ioctl_lock); |
| 1720 | 1729 | ||
| 1721 | /* Now reset the card and some of the device extension data */ | 1730 | /* Now reset the card and some of the device extension data */ |
| 1722 | if (twa_reset_device_extension(tw_dev, 0)) { | 1731 | if (twa_reset_device_extension(tw_dev)) { |
| 1723 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); | 1732 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); |
| 1724 | goto out; | 1733 | goto out; |
| 1725 | } | 1734 | } |
| @@ -2001,11 +2010,14 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id | |||
| 2001 | 2010 | ||
| 2002 | pci_set_master(pdev); | 2011 | pci_set_master(pdev); |
| 2003 | 2012 | ||
| 2004 | retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK); | 2013 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) |
| 2005 | if (retval) { | 2014 | || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) |
| 2006 | TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); | 2015 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) |
| 2007 | goto out_disable_device; | 2016 | || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { |
| 2008 | } | 2017 | TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); |
| 2018 | retval = -ENODEV; | ||
| 2019 | goto out_disable_device; | ||
| 2020 | } | ||
| 2009 | 2021 | ||
| 2010 | host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); | 2022 | host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); |
| 2011 | if (!host) { | 2023 | if (!host) { |
| @@ -2053,7 +2065,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id | |||
| 2053 | goto out_iounmap; | 2065 | goto out_iounmap; |
| 2054 | 2066 | ||
| 2055 | /* Set host specific parameters */ | 2067 | /* Set host specific parameters */ |
| 2056 | if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE) | 2068 | if ((pdev->device == PCI_DEVICE_ID_3WARE_9650SE) || |
| 2069 | (pdev->device == PCI_DEVICE_ID_3WARE_9690SA)) | ||
| 2057 | host->max_id = TW_MAX_UNITS_9650SE; | 2070 | host->max_id = TW_MAX_UNITS_9650SE; |
| 2058 | else | 2071 | else |
| 2059 | host->max_id = TW_MAX_UNITS; | 2072 | host->max_id = TW_MAX_UNITS; |
| @@ -2160,6 +2173,8 @@ static struct pci_device_id twa_pci_tbl[] __devinitdata = { | |||
| 2160 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 2173 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
| 2161 | { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, | 2174 | { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, |
| 2162 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 2175 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
| 2176 | { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9690SA, | ||
| 2177 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
| 2163 | { } | 2178 | { } |
| 2164 | }; | 2179 | }; |
| 2165 | MODULE_DEVICE_TABLE(pci, twa_pci_tbl); | 2180 | MODULE_DEVICE_TABLE(pci, twa_pci_tbl); |
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 7901517d4513..d14a9479e389 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | Written By: Adam Radford <linuxraid@amcc.com> | 4 | Written By: Adam Radford <linuxraid@amcc.com> |
| 5 | Modifications By: Tom Couch <linuxraid@amcc.com> | 5 | Modifications By: Tom Couch <linuxraid@amcc.com> |
| 6 | 6 | ||
| 7 | Copyright (C) 2004-2006 Applied Micro Circuits Corporation. | 7 | Copyright (C) 2004-2007 Applied Micro Circuits Corporation. |
| 8 | 8 | ||
| 9 | This program is free software; you can redistribute it and/or modify | 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 | 10 | it under the terms of the GNU General Public License as published by |
| @@ -419,6 +419,9 @@ static twa_message_type twa_error_table[] = { | |||
| 419 | #ifndef PCI_DEVICE_ID_3WARE_9650SE | 419 | #ifndef PCI_DEVICE_ID_3WARE_9650SE |
| 420 | #define PCI_DEVICE_ID_3WARE_9650SE 0x1004 | 420 | #define PCI_DEVICE_ID_3WARE_9650SE 0x1004 |
| 421 | #endif | 421 | #endif |
| 422 | #ifndef PCI_DEVICE_ID_3WARE_9690SA | ||
| 423 | #define PCI_DEVICE_ID_3WARE_9690SA 0x1005 | ||
| 424 | #endif | ||
| 422 | 425 | ||
| 423 | /* Bitmask macros to eliminate bitfields */ | 426 | /* Bitmask macros to eliminate bitfields */ |
| 424 | 427 | ||
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index a947257b8964..d2b3898b750a 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -282,7 +282,7 @@ config SCSI_ISCSI_ATTRS | |||
| 282 | 282 | ||
| 283 | config SCSI_SAS_ATTRS | 283 | config SCSI_SAS_ATTRS |
| 284 | tristate "SAS Transport Attributes" | 284 | tristate "SAS Transport Attributes" |
| 285 | depends on SCSI | 285 | depends on SCSI && BLK_DEV_BSG |
| 286 | help | 286 | help |
| 287 | If you wish to export transport-specific information about | 287 | If you wish to export transport-specific information about |
| 288 | each attached SAS device to sysfs, say Y. | 288 | each attached SAS device to sysfs, say Y. |
| @@ -291,8 +291,12 @@ source "drivers/scsi/libsas/Kconfig" | |||
| 291 | 291 | ||
| 292 | endmenu | 292 | endmenu |
| 293 | 293 | ||
| 294 | menu "SCSI low-level drivers" | 294 | menuconfig SCSI_LOWLEVEL |
| 295 | bool "SCSI low-level drivers" | ||
| 295 | depends on SCSI!=n | 296 | depends on SCSI!=n |
| 297 | default y | ||
| 298 | |||
| 299 | if SCSI_LOWLEVEL | ||
| 296 | 300 | ||
| 297 | config ISCSI_TCP | 301 | config ISCSI_TCP |
| 298 | tristate "iSCSI Initiator over TCP/IP" | 302 | tristate "iSCSI Initiator over TCP/IP" |
| @@ -1800,7 +1804,7 @@ config SCSI_SRP | |||
| 1800 | To compile this driver as a module, choose M here: the | 1804 | To compile this driver as a module, choose M here: the |
| 1801 | module will be called libsrp. | 1805 | module will be called libsrp. |
| 1802 | 1806 | ||
| 1803 | endmenu | 1807 | endif # SCSI_LOWLEVEL |
| 1804 | 1808 | ||
| 1805 | source "drivers/scsi/pcmcia/Kconfig" | 1809 | source "drivers/scsi/pcmcia/Kconfig" |
| 1806 | 1810 | ||
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 0f8689557158..86a7ba7bad63 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
| @@ -132,6 +132,7 @@ obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ | |||
| 132 | obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/ | 132 | obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/ |
| 133 | obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o | 133 | obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o |
| 134 | obj-$(CONFIG_SCSI_STEX) += stex.o | 134 | obj-$(CONFIG_SCSI_STEX) += stex.o |
| 135 | obj-$(CONFIG_PS3_ROM) += ps3rom.o | ||
| 135 | 136 | ||
| 136 | obj-$(CONFIG_ARM) += arm/ | 137 | obj-$(CONFIG_ARM) += arm/ |
| 137 | 138 | ||
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 6a5784683ed3..0c758d1452ba 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c | |||
| @@ -79,6 +79,7 @@ static int __devinit a4000t_probe(struct device *dev) | |||
| 79 | goto out_put_host; | 79 | goto out_put_host; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | dev_set_drvdata(dev, host); | ||
| 82 | scsi_scan_host(host); | 83 | scsi_scan_host(host); |
| 83 | 84 | ||
| 84 | return 0; | 85 | return 0; |
| @@ -95,7 +96,7 @@ static int __devinit a4000t_probe(struct device *dev) | |||
| 95 | 96 | ||
| 96 | static __devexit int a4000t_device_remove(struct device *dev) | 97 | static __devexit int a4000t_device_remove(struct device *dev) |
| 97 | { | 98 | { |
| 98 | struct Scsi_Host *host = dev_to_shost(dev); | 99 | struct Scsi_Host *host = dev_get_drvdata(dev); |
| 99 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); | 100 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); |
| 100 | 101 | ||
| 101 | scsi_remove_host(host); | 102 | scsi_remove_host(host); |
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 0b6fd0b654d2..a26baab09dbf 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
| @@ -751,6 +751,101 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex) | |||
| 751 | inqstrcpy ("V1.0", str->prl); | 751 | inqstrcpy ("V1.0", str->prl); |
| 752 | } | 752 | } |
| 753 | 753 | ||
| 754 | static void get_container_serial_callback(void *context, struct fib * fibptr) | ||
| 755 | { | ||
| 756 | struct aac_get_serial_resp * get_serial_reply; | ||
| 757 | struct scsi_cmnd * scsicmd; | ||
| 758 | |||
| 759 | BUG_ON(fibptr == NULL); | ||
| 760 | |||
| 761 | scsicmd = (struct scsi_cmnd *) context; | ||
| 762 | if (!aac_valid_context(scsicmd, fibptr)) | ||
| 763 | return; | ||
| 764 | |||
| 765 | get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); | ||
| 766 | /* Failure is irrelevant, using default value instead */ | ||
| 767 | if (le32_to_cpu(get_serial_reply->status) == CT_OK) { | ||
| 768 | char sp[13]; | ||
| 769 | /* EVPD bit set */ | ||
| 770 | sp[0] = INQD_PDT_DA; | ||
| 771 | sp[1] = scsicmd->cmnd[2]; | ||
| 772 | sp[2] = 0; | ||
| 773 | sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", | ||
| 774 | le32_to_cpu(get_serial_reply->uid)); | ||
| 775 | aac_internal_transfer(scsicmd, sp, 0, sizeof(sp)); | ||
| 776 | } | ||
| 777 | |||
| 778 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | ||
| 779 | |||
| 780 | aac_fib_complete(fibptr); | ||
| 781 | aac_fib_free(fibptr); | ||
| 782 | scsicmd->scsi_done(scsicmd); | ||
| 783 | } | ||
| 784 | |||
| 785 | /** | ||
| 786 | * aac_get_container_serial - get container serial, none blocking. | ||
| 787 | */ | ||
| 788 | static int aac_get_container_serial(struct scsi_cmnd * scsicmd) | ||
| 789 | { | ||
| 790 | int status; | ||
| 791 | struct aac_get_serial *dinfo; | ||
| 792 | struct fib * cmd_fibcontext; | ||
| 793 | struct aac_dev * dev; | ||
| 794 | |||
| 795 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; | ||
| 796 | |||
| 797 | if (!(cmd_fibcontext = aac_fib_alloc(dev))) | ||
| 798 | return -ENOMEM; | ||
| 799 | |||
| 800 | aac_fib_init(cmd_fibcontext); | ||
| 801 | dinfo = (struct aac_get_serial *) fib_data(cmd_fibcontext); | ||
| 802 | |||
| 803 | dinfo->command = cpu_to_le32(VM_ContainerConfig); | ||
| 804 | dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID); | ||
| 805 | dinfo->cid = cpu_to_le32(scmd_id(scsicmd)); | ||
| 806 | |||
| 807 | status = aac_fib_send(ContainerCommand, | ||
| 808 | cmd_fibcontext, | ||
| 809 | sizeof (struct aac_get_serial), | ||
| 810 | FsaNormal, | ||
| 811 | 0, 1, | ||
| 812 | (fib_callback) get_container_serial_callback, | ||
| 813 | (void *) scsicmd); | ||
| 814 | |||
| 815 | /* | ||
| 816 | * Check that the command queued to the controller | ||
| 817 | */ | ||
| 818 | if (status == -EINPROGRESS) { | ||
| 819 | scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; | ||
| 820 | return 0; | ||
| 821 | } | ||
| 822 | |||
| 823 | printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status); | ||
| 824 | aac_fib_complete(cmd_fibcontext); | ||
| 825 | aac_fib_free(cmd_fibcontext); | ||
| 826 | return -1; | ||
| 827 | } | ||
| 828 | |||
| 829 | /* Function: setinqserial | ||
| 830 | * | ||
| 831 | * Arguments: [1] pointer to void [1] int | ||
| 832 | * | ||
| 833 | * Purpose: Sets SCSI Unit Serial number. | ||
| 834 | * This is a fake. We should read a proper | ||
| 835 | * serial number from the container. <SuSE>But | ||
| 836 | * without docs it's quite hard to do it :-) | ||
| 837 | * So this will have to do in the meantime.</SuSE> | ||
| 838 | */ | ||
| 839 | |||
| 840 | static int setinqserial(struct aac_dev *dev, void *data, int cid) | ||
| 841 | { | ||
| 842 | /* | ||
| 843 | * This breaks array migration. | ||
| 844 | */ | ||
| 845 | return snprintf((char *)(data), sizeof(struct scsi_inq) - 4, "%08X%02X", | ||
| 846 | le32_to_cpu(dev->adapter_info.serial[0]), cid); | ||
| 847 | } | ||
| 848 | |||
| 754 | static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, | 849 | static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, |
| 755 | u8 a_sense_code, u8 incorrect_length, | 850 | u8 a_sense_code, u8 incorrect_length, |
| 756 | u8 bit_pointer, u16 field_pointer, | 851 | u8 bit_pointer, u16 field_pointer, |
| @@ -1798,6 +1893,49 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 1798 | dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid)); | 1893 | dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid)); |
| 1799 | memset(&inq_data, 0, sizeof (struct inquiry_data)); | 1894 | memset(&inq_data, 0, sizeof (struct inquiry_data)); |
| 1800 | 1895 | ||
| 1896 | if (scsicmd->cmnd[1] & 0x1 ) { | ||
| 1897 | char *arr = (char *)&inq_data; | ||
| 1898 | |||
| 1899 | /* EVPD bit set */ | ||
| 1900 | arr[0] = (scmd_id(scsicmd) == host->this_id) ? | ||
| 1901 | INQD_PDT_PROC : INQD_PDT_DA; | ||
| 1902 | if (scsicmd->cmnd[2] == 0) { | ||
| 1903 | /* supported vital product data pages */ | ||
| 1904 | arr[3] = 2; | ||
| 1905 | arr[4] = 0x0; | ||
| 1906 | arr[5] = 0x80; | ||
| 1907 | arr[1] = scsicmd->cmnd[2]; | ||
| 1908 | aac_internal_transfer(scsicmd, &inq_data, 0, | ||
| 1909 | sizeof(inq_data)); | ||
| 1910 | scsicmd->result = DID_OK << 16 | | ||
| 1911 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | ||
| 1912 | } else if (scsicmd->cmnd[2] == 0x80) { | ||
| 1913 | /* unit serial number page */ | ||
| 1914 | arr[3] = setinqserial(dev, &arr[4], | ||
| 1915 | scmd_id(scsicmd)); | ||
| 1916 | arr[1] = scsicmd->cmnd[2]; | ||
| 1917 | aac_internal_transfer(scsicmd, &inq_data, 0, | ||
| 1918 | sizeof(inq_data)); | ||
| 1919 | return aac_get_container_serial(scsicmd); | ||
| 1920 | } else { | ||
| 1921 | /* vpd page not implemented */ | ||
| 1922 | scsicmd->result = DID_OK << 16 | | ||
| 1923 | COMMAND_COMPLETE << 8 | | ||
| 1924 | SAM_STAT_CHECK_CONDITION; | ||
| 1925 | set_sense((u8 *) &dev->fsa_dev[cid].sense_data, | ||
| 1926 | ILLEGAL_REQUEST, | ||
| 1927 | SENCODE_INVALID_CDB_FIELD, | ||
| 1928 | ASENCODE_NO_SENSE, 0, 7, 2, 0); | ||
| 1929 | memcpy(scsicmd->sense_buffer, | ||
| 1930 | &dev->fsa_dev[cid].sense_data, | ||
| 1931 | (sizeof(dev->fsa_dev[cid].sense_data) > | ||
| 1932 | sizeof(scsicmd->sense_buffer)) | ||
| 1933 | ? sizeof(scsicmd->sense_buffer) | ||
| 1934 | : sizeof(dev->fsa_dev[cid].sense_data)); | ||
| 1935 | } | ||
| 1936 | scsicmd->scsi_done(scsicmd); | ||
| 1937 | return 0; | ||
| 1938 | } | ||
| 1801 | inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ | 1939 | inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ |
| 1802 | inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ | 1940 | inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ |
| 1803 | inq_data.inqd_len = 31; | 1941 | inq_data.inqd_len = 31; |
| @@ -2070,7 +2208,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg) | |||
| 2070 | } | 2208 | } |
| 2071 | else return -EINVAL; | 2209 | else return -EINVAL; |
| 2072 | 2210 | ||
| 2073 | qd.valid = fsa_dev_ptr[qd.cnum].valid; | 2211 | qd.valid = fsa_dev_ptr[qd.cnum].valid != 0; |
| 2074 | qd.locked = fsa_dev_ptr[qd.cnum].locked; | 2212 | qd.locked = fsa_dev_ptr[qd.cnum].locked; |
| 2075 | qd.deleted = fsa_dev_ptr[qd.cnum].deleted; | 2213 | qd.deleted = fsa_dev_ptr[qd.cnum].deleted; |
| 2076 | 2214 | ||
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index f1d3b66af879..400d03403cd5 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
| @@ -1567,6 +1567,20 @@ struct aac_get_name_resp { | |||
| 1567 | u8 data[16]; | 1567 | u8 data[16]; |
| 1568 | }; | 1568 | }; |
| 1569 | 1569 | ||
| 1570 | #define CT_CID_TO_32BITS_UID 165 | ||
| 1571 | struct aac_get_serial { | ||
| 1572 | __le32 command; /* VM_ContainerConfig */ | ||
| 1573 | __le32 type; /* CT_CID_TO_32BITS_UID */ | ||
| 1574 | __le32 cid; | ||
| 1575 | }; | ||
| 1576 | |||
| 1577 | struct aac_get_serial_resp { | ||
| 1578 | __le32 dummy0; | ||
| 1579 | __le32 dummy1; | ||
| 1580 | __le32 status; /* CT_OK */ | ||
| 1581 | __le32 uid; | ||
| 1582 | }; | ||
| 1583 | |||
| 1570 | /* | 1584 | /* |
| 1571 | * The following command is sent to shut down each container. | 1585 | * The following command is sent to shut down each container. |
| 1572 | */ | 1586 | */ |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index d510839c0bb2..bb870906b4cf 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
| @@ -80,7 +80,11 @@ static int fib_map_alloc(struct aac_dev *dev) | |||
| 80 | 80 | ||
| 81 | void aac_fib_map_free(struct aac_dev *dev) | 81 | void aac_fib_map_free(struct aac_dev *dev) |
| 82 | { | 82 | { |
| 83 | pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa); | 83 | pci_free_consistent(dev->pdev, |
| 84 | dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), | ||
| 85 | dev->hw_fib_va, dev->hw_fib_pa); | ||
| 86 | dev->hw_fib_va = NULL; | ||
| 87 | dev->hw_fib_pa = 0; | ||
| 84 | } | 88 | } |
| 85 | 89 | ||
| 86 | /** | 90 | /** |
| @@ -1087,8 +1091,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) | |||
| 1087 | * case. | 1091 | * case. |
| 1088 | */ | 1092 | */ |
| 1089 | aac_fib_map_free(aac); | 1093 | aac_fib_map_free(aac); |
| 1090 | aac->hw_fib_va = NULL; | ||
| 1091 | aac->hw_fib_pa = 0; | ||
| 1092 | pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); | 1094 | pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); |
| 1093 | aac->comm_addr = NULL; | 1095 | aac->comm_addr = NULL; |
| 1094 | aac->comm_phys = 0; | 1096 | aac->comm_phys = 0; |
| @@ -1098,12 +1100,12 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) | |||
| 1098 | kfree(aac->fsa_dev); | 1100 | kfree(aac->fsa_dev); |
| 1099 | aac->fsa_dev = NULL; | 1101 | aac->fsa_dev = NULL; |
| 1100 | if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) { | 1102 | if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) { |
| 1101 | if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) || | 1103 | if (((retval = pci_set_dma_mask(aac->pdev, DMA_31BIT_MASK))) || |
| 1102 | ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK)))) | 1104 | ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_31BIT_MASK)))) |
| 1103 | goto out; | 1105 | goto out; |
| 1104 | } else { | 1106 | } else { |
| 1105 | if (((retval = pci_set_dma_mask(aac->pdev, 0x7FFFFFFFULL))) || | 1107 | if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) || |
| 1106 | ((retval = pci_set_consistent_dma_mask(aac->pdev, 0x7FFFFFFFULL)))) | 1108 | ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK)))) |
| 1107 | goto out; | 1109 | goto out; |
| 1108 | } | 1110 | } |
| 1109 | if ((retval = (*(aac_get_driver_ident(index)->init))(aac))) | 1111 | if ((retval = (*(aac_get_driver_ident(index)->init))(aac))) |
diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c index c520e5b41fb5..3dce618bf414 100644 --- a/drivers/scsi/aic94xx/aic94xx_dev.c +++ b/drivers/scsi/aic94xx/aic94xx_dev.c | |||
| @@ -126,7 +126,7 @@ static inline int asd_init_sata(struct domain_device *dev) | |||
| 126 | if (w76 & 0x100) /* NCQ? */ | 126 | if (w76 & 0x100) /* NCQ? */ |
| 127 | qdepth = (w75 & 0x1F) + 1; | 127 | qdepth = (w75 & 0x1F) + 1; |
| 128 | asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, | 128 | asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, |
| 129 | (1<<qdepth)-1); | 129 | (1ULL<<qdepth)-1); |
| 130 | asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth); | 130 | asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth); |
| 131 | } | 131 | } |
| 132 | if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM || | 132 | if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM || |
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index b8c6810090d5..ab00aecc5466 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c | |||
| @@ -81,6 +81,9 @@ static struct scsi_host_template aic94xx_sht = { | |||
| 81 | .use_clustering = ENABLE_CLUSTERING, | 81 | .use_clustering = ENABLE_CLUSTERING, |
| 82 | .eh_device_reset_handler = sas_eh_device_reset_handler, | 82 | .eh_device_reset_handler = sas_eh_device_reset_handler, |
| 83 | .eh_bus_reset_handler = sas_eh_bus_reset_handler, | 83 | .eh_bus_reset_handler = sas_eh_bus_reset_handler, |
| 84 | .slave_alloc = sas_slave_alloc, | ||
| 85 | .target_destroy = sas_target_destroy, | ||
| 86 | .ioctl = sas_ioctl, | ||
| 84 | }; | 87 | }; |
| 85 | 88 | ||
| 86 | static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha) | 89 | static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha) |
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index e2ad5bed9403..d5d8caba3560 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c | |||
| @@ -74,8 +74,13 @@ static inline int asd_map_scatterlist(struct sas_task *task, | |||
| 74 | return 0; | 74 | return 0; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | num_sg = pci_map_sg(asd_ha->pcidev, task->scatter, task->num_scatter, | 77 | /* STP tasks come from libata which has already mapped |
| 78 | task->data_dir); | 78 | * the SG list */ |
| 79 | if (sas_protocol_ata(task->task_proto)) | ||
| 80 | num_sg = task->num_scatter; | ||
| 81 | else | ||
| 82 | num_sg = pci_map_sg(asd_ha->pcidev, task->scatter, | ||
| 83 | task->num_scatter, task->data_dir); | ||
| 79 | if (num_sg == 0) | 84 | if (num_sg == 0) |
| 80 | return -ENOMEM; | 85 | return -ENOMEM; |
| 81 | 86 | ||
| @@ -120,8 +125,9 @@ static inline int asd_map_scatterlist(struct sas_task *task, | |||
| 120 | 125 | ||
| 121 | return 0; | 126 | return 0; |
| 122 | err_unmap: | 127 | err_unmap: |
| 123 | pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, | 128 | if (sas_protocol_ata(task->task_proto)) |
| 124 | task->data_dir); | 129 | pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, |
| 130 | task->data_dir); | ||
| 125 | return res; | 131 | return res; |
| 126 | } | 132 | } |
| 127 | 133 | ||
| @@ -142,8 +148,9 @@ static inline void asd_unmap_scatterlist(struct asd_ascb *ascb) | |||
| 142 | } | 148 | } |
| 143 | 149 | ||
| 144 | asd_free_coherent(asd_ha, ascb->sg_arr); | 150 | asd_free_coherent(asd_ha, ascb->sg_arr); |
| 145 | pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, | 151 | if (task->task_proto != SAS_PROTOCOL_STP) |
| 146 | task->data_dir); | 152 | pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, |
| 153 | task->data_dir); | ||
| 147 | } | 154 | } |
| 148 | 155 | ||
| 149 | /* ---------- Task complete tasklet ---------- */ | 156 | /* ---------- Task complete tasklet ---------- */ |
| @@ -391,7 +398,6 @@ static int asd_build_ata_ascb(struct asd_ascb *ascb, struct sas_task *task, | |||
| 391 | 398 | ||
| 392 | scb->ata_task.total_xfer_len = cpu_to_le32(task->total_xfer_len); | 399 | scb->ata_task.total_xfer_len = cpu_to_le32(task->total_xfer_len); |
| 393 | scb->ata_task.fis = task->ata_task.fis; | 400 | scb->ata_task.fis = task->ata_task.fis; |
| 394 | scb->ata_task.fis.fis_type = 0x27; | ||
| 395 | if (likely(!task->ata_task.device_control_reg_update)) | 401 | if (likely(!task->ata_task.device_control_reg_update)) |
| 396 | scb->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */ | 402 | scb->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */ |
| 397 | scb->ata_task.fis.flags &= 0xF0; /* PM_PORT field shall be 0 */ | 403 | scb->ata_task.fis.flags &= 0xF0; /* PM_PORT field shall be 0 */ |
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index cf9a21cea6d9..49d838e90a24 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | #define CUMANASCSI_PUBLIC_RELEASE 1 | 25 | #define CUMANASCSI_PUBLIC_RELEASE 1 |
| 26 | 26 | ||
| 27 | #define NCR5380_implementation_fields int port, ctrl | 27 | #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) |
| 28 | #define NCR5380_local_declare() struct Scsi_Host *_instance | 28 | #define NCR5380_local_declare() struct Scsi_Host *_instance |
| 29 | #define NCR5380_setup(instance) _instance = instance | 29 | #define NCR5380_setup(instance) _instance = instance |
| 30 | #define NCR5380_read(reg) cumanascsi_read(_instance, reg) | 30 | #define NCR5380_read(reg) cumanascsi_read(_instance, reg) |
| @@ -33,6 +33,11 @@ | |||
| 33 | #define NCR5380_queue_command cumanascsi_queue_command | 33 | #define NCR5380_queue_command cumanascsi_queue_command |
| 34 | #define NCR5380_proc_info cumanascsi_proc_info | 34 | #define NCR5380_proc_info cumanascsi_proc_info |
| 35 | 35 | ||
| 36 | #define NCR5380_implementation_fields \ | ||
| 37 | unsigned ctrl; \ | ||
| 38 | void __iomem *base; \ | ||
| 39 | void __iomem *dma | ||
| 40 | |||
| 36 | #define BOARD_NORMAL 0 | 41 | #define BOARD_NORMAL 0 |
| 37 | #define BOARD_NCR53C400 1 | 42 | #define BOARD_NCR53C400 1 |
| 38 | 43 | ||
| @@ -47,192 +52,162 @@ const char *cumanascsi_info(struct Scsi_Host *spnt) | |||
| 47 | return ""; | 52 | return ""; |
| 48 | } | 53 | } |
| 49 | 54 | ||
| 50 | #ifdef NOT_EFFICIENT | 55 | #define CTRL 0x16fc |
| 51 | #define CTRL(p,v) outb(*ctrl = (v), (p) - 577) | 56 | #define STAT 0x2004 |
| 52 | #define STAT(p) inb((p)+1) | 57 | #define L(v) (((v)<<16)|((v) & 0x0000ffff)) |
| 53 | #define IN(p) inb((p)) | 58 | #define H(v) (((v)>>16)|((v) & 0xffff0000)) |
| 54 | #define OUT(v,p) outb((v), (p)) | ||
| 55 | #else | ||
| 56 | #define CTRL(p,v) (p[-2308] = (*ctrl = (v))) | ||
| 57 | #define STAT(p) (p[4]) | ||
| 58 | #define IN(p) (*(p)) | ||
| 59 | #define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p))) | ||
| 60 | #define OUT(v,p) (*(p) = (v)) | ||
| 61 | #define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v)) | ||
| 62 | #endif | ||
| 63 | #define L(v) (((v)<<16)|((v) & 0x0000ffff)) | ||
| 64 | #define H(v) (((v)>>16)|((v) & 0xffff0000)) | ||
| 65 | 59 | ||
| 66 | static inline int | 60 | static inline int |
| 67 | NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len) | 61 | NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, int len) |
| 68 | { | 62 | { |
| 69 | int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; | ||
| 70 | int oldctrl = *ctrl; | ||
| 71 | unsigned long *laddr; | 63 | unsigned long *laddr; |
| 72 | #ifdef NOT_EFFICIENT | 64 | void __iomem *dma = priv(host)->dma + 0x2000; |
| 73 | int iobase = instance->io_port; | ||
| 74 | int dma_io = iobase & ~(0x3C0000>>2); | ||
| 75 | #else | ||
| 76 | volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); | ||
| 77 | volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000); | ||
| 78 | #endif | ||
| 79 | 65 | ||
| 80 | if(!len) return 0; | 66 | if(!len) return 0; |
| 81 | 67 | ||
| 82 | CTRL(iobase, 0x02); | 68 | writeb(0x02, priv(host)->base + CTRL); |
| 83 | laddr = (unsigned long *)addr; | 69 | laddr = (unsigned long *)addr; |
| 84 | while(len >= 32) | 70 | while(len >= 32) |
| 85 | { | 71 | { |
| 86 | int status; | 72 | unsigned int status; |
| 87 | unsigned long v; | 73 | unsigned long v; |
| 88 | status = STAT(iobase); | 74 | status = readb(priv(host)->base + STAT); |
| 89 | if(status & 0x80) | 75 | if(status & 0x80) |
| 90 | goto end; | 76 | goto end; |
| 91 | if(!(status & 0x40)) | 77 | if(!(status & 0x40)) |
| 92 | continue; | 78 | continue; |
| 93 | v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); | 79 | v=*laddr++; writew(L(v), dma); writew(H(v), dma); |
| 94 | v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); | 80 | v=*laddr++; writew(L(v), dma); writew(H(v), dma); |
| 95 | v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); | 81 | v=*laddr++; writew(L(v), dma); writew(H(v), dma); |
| 96 | v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); | 82 | v=*laddr++; writew(L(v), dma); writew(H(v), dma); |
| 97 | v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); | 83 | v=*laddr++; writew(L(v), dma); writew(H(v), dma); |
| 98 | v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); | 84 | v=*laddr++; writew(L(v), dma); writew(H(v), dma); |
| 99 | v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); | 85 | v=*laddr++; writew(L(v), dma); writew(H(v), dma); |
| 100 | v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); | 86 | v=*laddr++; writew(L(v), dma); writew(H(v), dma); |
| 101 | len -= 32; | 87 | len -= 32; |
| 102 | if(len == 0) | 88 | if(len == 0) |
| 103 | break; | 89 | break; |
| 104 | } | 90 | } |
| 105 | 91 | ||
| 106 | addr = (unsigned char *)laddr; | 92 | addr = (unsigned char *)laddr; |
| 107 | CTRL(iobase, 0x12); | 93 | writeb(0x12, priv(host)->base + CTRL); |
| 94 | |||
| 108 | while(len > 0) | 95 | while(len > 0) |
| 109 | { | 96 | { |
| 110 | int status; | 97 | unsigned int status; |
| 111 | status = STAT(iobase); | 98 | status = readb(priv(host)->base + STAT); |
| 112 | if(status & 0x80) | 99 | if(status & 0x80) |
| 113 | goto end; | 100 | goto end; |
| 114 | if(status & 0x40) | 101 | if(status & 0x40) |
| 115 | { | 102 | { |
| 116 | OUT(*addr++, dma_io); | 103 | writeb(*addr++, dma); |
| 117 | if(--len == 0) | 104 | if(--len == 0) |
| 118 | break; | 105 | break; |
| 119 | } | 106 | } |
| 120 | 107 | ||
| 121 | status = STAT(iobase); | 108 | status = readb(priv(host)->base + STAT); |
| 122 | if(status & 0x80) | 109 | if(status & 0x80) |
| 123 | goto end; | 110 | goto end; |
| 124 | if(status & 0x40) | 111 | if(status & 0x40) |
| 125 | { | 112 | { |
| 126 | OUT(*addr++, dma_io); | 113 | writeb(*addr++, dma); |
| 127 | if(--len == 0) | 114 | if(--len == 0) |
| 128 | break; | 115 | break; |
| 129 | } | 116 | } |
| 130 | } | 117 | } |
| 131 | end: | 118 | end: |
| 132 | CTRL(iobase, oldctrl|0x40); | 119 | writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); |
| 133 | return len; | 120 | return len; |
| 134 | } | 121 | } |
| 135 | 122 | ||
| 136 | static inline int | 123 | static inline int |
| 137 | NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, int len) | 124 | NCR5380_pread(struct Scsi_Host *host, unsigned char *addr, int len) |
| 138 | { | 125 | { |
| 139 | int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; | ||
| 140 | int oldctrl = *ctrl; | ||
| 141 | unsigned long *laddr; | 126 | unsigned long *laddr; |
| 142 | #ifdef NOT_EFFICIENT | 127 | void __iomem *dma = priv(host)->dma + 0x2000; |
| 143 | int iobase = instance->io_port; | ||
| 144 | int dma_io = iobase & ~(0x3C0000>>2); | ||
| 145 | #else | ||
| 146 | volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); | ||
| 147 | volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000); | ||
| 148 | #endif | ||
| 149 | 128 | ||
| 150 | if(!len) return 0; | 129 | if(!len) return 0; |
| 151 | 130 | ||
| 152 | CTRL(iobase, 0x00); | 131 | writeb(0x00, priv(host)->base + CTRL); |
| 153 | laddr = (unsigned long *)addr; | 132 | laddr = (unsigned long *)addr; |
| 154 | while(len >= 32) | 133 | while(len >= 32) |
| 155 | { | 134 | { |
| 156 | int status; | 135 | unsigned int status; |
| 157 | status = STAT(iobase); | 136 | status = readb(priv(host)->base + STAT); |
| 158 | if(status & 0x80) | 137 | if(status & 0x80) |
| 159 | goto end; | 138 | goto end; |
| 160 | if(!(status & 0x40)) | 139 | if(!(status & 0x40)) |
| 161 | continue; | 140 | continue; |
| 162 | *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); | 141 | *laddr++ = readw(dma) | (readw(dma) << 16); |
| 163 | *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); | 142 | *laddr++ = readw(dma) | (readw(dma) << 16); |
| 164 | *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); | 143 | *laddr++ = readw(dma) | (readw(dma) << 16); |
| 165 | *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); | 144 | *laddr++ = readw(dma) | (readw(dma) << 16); |
| 166 | *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); | 145 | *laddr++ = readw(dma) | (readw(dma) << 16); |
| 167 | *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); | 146 | *laddr++ = readw(dma) | (readw(dma) << 16); |
| 168 | *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); | 147 | *laddr++ = readw(dma) | (readw(dma) << 16); |
| 169 | *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); | 148 | *laddr++ = readw(dma) | (readw(dma) << 16); |
| 170 | len -= 32; | 149 | len -= 32; |
| 171 | if(len == 0) | 150 | if(len == 0) |
| 172 | break; | 151 | break; |
| 173 | } | 152 | } |
| 174 | 153 | ||
| 175 | addr = (unsigned char *)laddr; | 154 | addr = (unsigned char *)laddr; |
| 176 | CTRL(iobase, 0x10); | 155 | writeb(0x10, priv(host)->base + CTRL); |
| 156 | |||
| 177 | while(len > 0) | 157 | while(len > 0) |
| 178 | { | 158 | { |
| 179 | int status; | 159 | unsigned int status; |
| 180 | status = STAT(iobase); | 160 | status = readb(priv(host)->base + STAT); |
| 181 | if(status & 0x80) | 161 | if(status & 0x80) |
| 182 | goto end; | 162 | goto end; |
| 183 | if(status & 0x40) | 163 | if(status & 0x40) |
| 184 | { | 164 | { |
| 185 | *addr++ = IN(dma_io); | 165 | *addr++ = readb(dma); |
| 186 | if(--len == 0) | 166 | if(--len == 0) |
| 187 | break; | 167 | break; |
| 188 | } | 168 | } |
| 189 | 169 | ||
| 190 | status = STAT(iobase); | 170 | status = readb(priv(host)->base + STAT); |
| 191 | if(status & 0x80) | 171 | if(status & 0x80) |
| 192 | goto end; | 172 | goto end; |
| 193 | if(status & 0x40) | 173 | if(status & 0x40) |
| 194 | { | 174 | { |
| 195 | *addr++ = IN(dma_io); | 175 | *addr++ = readb(dma); |
| 196 | if(--len == 0) | 176 | if(--len == 0) |
| 197 | break; | 177 | break; |
| 198 | } | 178 | } |
| 199 | } | 179 | } |
| 200 | end: | 180 | end: |
| 201 | CTRL(iobase, oldctrl|0x40); | 181 | writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); |
| 202 | return len; | 182 | return len; |
| 203 | } | 183 | } |
| 204 | 184 | ||
| 205 | #undef STAT | 185 | static unsigned char cumanascsi_read(struct Scsi_Host *host, unsigned int reg) |
| 206 | #undef CTRL | 186 | { |
| 207 | #undef IN | 187 | void __iomem *base = priv(host)->base; |
| 208 | #undef OUT | 188 | unsigned char val; |
| 209 | 189 | ||
| 210 | #define CTRL(p,v) outb(*ctrl = (v), (p) - 577) | 190 | writeb(0, base + CTRL); |
| 211 | 191 | ||
| 212 | static char cumanascsi_read(struct Scsi_Host *instance, int reg) | 192 | val = readb(base + 0x2100 + (reg << 2)); |
| 213 | { | ||
| 214 | unsigned int iobase = instance->io_port; | ||
| 215 | int i; | ||
| 216 | int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; | ||
| 217 | 193 | ||
| 218 | CTRL(iobase, 0); | 194 | priv(host)->ctrl = 0x40; |
| 219 | i = inb(iobase + 64 + reg); | 195 | writeb(0x40, base + CTRL); |
| 220 | CTRL(iobase, 0x40); | ||
| 221 | 196 | ||
| 222 | return i; | 197 | return val; |
| 223 | } | 198 | } |
| 224 | 199 | ||
| 225 | static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value) | 200 | static void cumanascsi_write(struct Scsi_Host *host, unsigned int reg, unsigned int value) |
| 226 | { | 201 | { |
| 227 | int iobase = instance->io_port; | 202 | void __iomem *base = priv(host)->base; |
| 228 | int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; | ||
| 229 | 203 | ||
| 230 | CTRL(iobase, 0); | 204 | writeb(0, base + CTRL); |
| 231 | outb(value, iobase + 64 + reg); | ||
| 232 | CTRL(iobase, 0x40); | ||
| 233 | } | ||
| 234 | 205 | ||
| 235 | #undef CTRL | 206 | writeb(value, base + 0x2100 + (reg << 2)); |
| 207 | |||
| 208 | priv(host)->ctrl = 0x40; | ||
| 209 | writeb(0x40, base + CTRL); | ||
| 210 | } | ||
| 236 | 211 | ||
| 237 | #include "../NCR5380.c" | 212 | #include "../NCR5380.c" |
| 238 | 213 | ||
| @@ -256,32 +231,46 @@ static int __devinit | |||
| 256 | cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id) | 231 | cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id) |
| 257 | { | 232 | { |
| 258 | struct Scsi_Host *host; | 233 | struct Scsi_Host *host; |
| 259 | int ret = -ENOMEM; | 234 | int ret; |
| 260 | 235 | ||
| 261 | host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata)); | 236 | ret = ecard_request_resources(ec); |
| 262 | if (!host) | 237 | if (ret) |
| 263 | goto out; | 238 | goto out; |
| 264 | 239 | ||
| 265 | host->io_port = ecard_address(ec, ECARD_IOC, ECARD_SLOW) + 0x800; | 240 | host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata)); |
| 241 | if (!host) { | ||
| 242 | ret = -ENOMEM; | ||
| 243 | goto out_release; | ||
| 244 | } | ||
| 245 | |||
| 246 | priv(host)->base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCSLOW), | ||
| 247 | ecard_resource_len(ec, ECARD_RES_IOCSLOW)); | ||
| 248 | priv(host)->dma = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), | ||
| 249 | ecard_resource_len(ec, ECARD_RES_MEMC)); | ||
| 250 | if (!priv(host)->base || !priv(host)->dma) { | ||
| 251 | ret = -ENOMEM; | ||
| 252 | goto out_unmap; | ||
| 253 | } | ||
| 254 | |||
| 266 | host->irq = ec->irq; | 255 | host->irq = ec->irq; |
| 267 | 256 | ||
| 268 | NCR5380_init(host, 0); | 257 | NCR5380_init(host, 0); |
| 269 | 258 | ||
| 259 | priv(host)->ctrl = 0; | ||
| 260 | writeb(0, priv(host)->base + CTRL); | ||
| 261 | |||
| 270 | host->n_io_port = 255; | 262 | host->n_io_port = 255; |
| 271 | if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) { | 263 | if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) { |
| 272 | ret = -EBUSY; | 264 | ret = -EBUSY; |
| 273 | goto out_free; | 265 | goto out_unmap; |
| 274 | } | 266 | } |
| 275 | 267 | ||
| 276 | ((struct NCR5380_hostdata *)host->hostdata)->ctrl = 0; | ||
| 277 | outb(0x00, host->io_port - 577); | ||
| 278 | |||
| 279 | ret = request_irq(host->irq, cumanascsi_intr, IRQF_DISABLED, | 268 | ret = request_irq(host->irq, cumanascsi_intr, IRQF_DISABLED, |
| 280 | "CumanaSCSI-1", host); | 269 | "CumanaSCSI-1", host); |
| 281 | if (ret) { | 270 | if (ret) { |
| 282 | printk("scsi%d: IRQ%d not free: %d\n", | 271 | printk("scsi%d: IRQ%d not free: %d\n", |
| 283 | host->host_no, host->irq, ret); | 272 | host->host_no, host->irq, ret); |
| 284 | goto out_release; | 273 | goto out_unmap; |
| 285 | } | 274 | } |
| 286 | 275 | ||
| 287 | printk("scsi%d: at port 0x%08lx irq %d", | 276 | printk("scsi%d: at port 0x%08lx irq %d", |
| @@ -301,10 +290,12 @@ cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id) | |||
| 301 | 290 | ||
| 302 | out_free_irq: | 291 | out_free_irq: |
| 303 | free_irq(host->irq, host); | 292 | free_irq(host->irq, host); |
| 304 | out_release: | 293 | out_unmap: |
| 305 | release_region(host->io_port, host->n_io_port); | 294 | iounmap(priv(host)->base); |
| 306 | out_free: | 295 | iounmap(priv(host)->dma); |
| 307 | scsi_host_put(host); | 296 | scsi_host_put(host); |
| 297 | out_release: | ||
| 298 | ecard_release_resources(ec); | ||
| 308 | out: | 299 | out: |
| 309 | return ret; | 300 | return ret; |
| 310 | } | 301 | } |
| @@ -318,8 +309,10 @@ static void __devexit cumanascsi1_remove(struct expansion_card *ec) | |||
| 318 | scsi_remove_host(host); | 309 | scsi_remove_host(host); |
| 319 | free_irq(host->irq, host); | 310 | free_irq(host->irq, host); |
| 320 | NCR5380_exit(host); | 311 | NCR5380_exit(host); |
| 321 | release_region(host->io_port, host->n_io_port); | 312 | iounmap(priv(host)->base); |
| 313 | iounmap(priv(host)->dma); | ||
| 322 | scsi_host_put(host); | 314 | scsi_host_put(host); |
| 315 | ecard_release_resources(ec); | ||
| 323 | } | 316 | } |
| 324 | 317 | ||
| 325 | static const struct ecard_id cumanascsi1_cids[] = { | 318 | static const struct ecard_id cumanascsi1_cids[] = { |
diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c index 378e7af0c5d6..5265a9884338 100644 --- a/drivers/scsi/arm/ecoscsi.c +++ b/drivers/scsi/arm/ecoscsi.c | |||
| @@ -34,35 +34,25 @@ | |||
| 34 | #include "../scsi.h" | 34 | #include "../scsi.h" |
| 35 | #include <scsi/scsi_host.h> | 35 | #include <scsi/scsi_host.h> |
| 36 | 36 | ||
| 37 | #define NCR5380_implementation_fields int port, ctrl | 37 | #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) |
| 38 | #define NCR5380_local_declare() struct Scsi_Host *_instance | ||
| 39 | #define NCR5380_setup(instance) _instance = instance | ||
| 40 | 38 | ||
| 41 | #define NCR5380_read(reg) ecoscsi_read(_instance, reg) | 39 | #define NCR5380_local_declare() void __iomem *_base |
| 42 | #define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value) | 40 | #define NCR5380_setup(host) _base = priv(host)->base |
| 41 | |||
| 42 | #define NCR5380_read(reg) ({ writeb(reg | 8, _base); readb(_base + 4); }) | ||
| 43 | #define NCR5380_write(reg, value) ({ writeb(reg | 8, _base); writeb(value, _base + 4); }) | ||
| 43 | 44 | ||
| 44 | #define NCR5380_intr ecoscsi_intr | 45 | #define NCR5380_intr ecoscsi_intr |
| 45 | #define NCR5380_queue_command ecoscsi_queue_command | 46 | #define NCR5380_queue_command ecoscsi_queue_command |
| 46 | #define NCR5380_proc_info ecoscsi_proc_info | 47 | #define NCR5380_proc_info ecoscsi_proc_info |
| 47 | 48 | ||
| 49 | #define NCR5380_implementation_fields \ | ||
| 50 | void __iomem *base | ||
| 51 | |||
| 48 | #include "../NCR5380.h" | 52 | #include "../NCR5380.h" |
| 49 | 53 | ||
| 50 | #define ECOSCSI_PUBLIC_RELEASE 1 | 54 | #define ECOSCSI_PUBLIC_RELEASE 1 |
| 51 | 55 | ||
| 52 | static char ecoscsi_read(struct Scsi_Host *instance, int reg) | ||
| 53 | { | ||
| 54 | int iobase = instance->io_port; | ||
| 55 | outb(reg | 8, iobase); | ||
| 56 | return inb(iobase + 1); | ||
| 57 | } | ||
| 58 | |||
| 59 | static void ecoscsi_write(struct Scsi_Host *instance, int reg, int value) | ||
| 60 | { | ||
| 61 | int iobase = instance->io_port; | ||
| 62 | outb(reg | 8, iobase); | ||
| 63 | outb(value, iobase + 1); | ||
| 64 | } | ||
| 65 | |||
| 66 | /* | 56 | /* |
| 67 | * Function : ecoscsi_setup(char *str, int *ints) | 57 | * Function : ecoscsi_setup(char *str, int *ints) |
| 68 | * | 58 | * |
| @@ -82,73 +72,6 @@ const char * ecoscsi_info (struct Scsi_Host *spnt) | |||
| 82 | return ""; | 72 | return ""; |
| 83 | } | 73 | } |
| 84 | 74 | ||
| 85 | #if 0 | ||
| 86 | #define STAT(p) inw(p + 144) | ||
| 87 | |||
| 88 | static inline int NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, | ||
| 89 | int len) | ||
| 90 | { | ||
| 91 | int iobase = host->io_port; | ||
| 92 | printk("writing %p len %d\n",addr, len); | ||
| 93 | if(!len) return -1; | ||
| 94 | |||
| 95 | while(1) | ||
| 96 | { | ||
| 97 | int status; | ||
| 98 | while(((status = STAT(iobase)) & 0x100)==0); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | static inline int NCR5380_pread(struct Scsi_Host *host, unsigned char *addr, | ||
| 103 | int len) | ||
| 104 | { | ||
| 105 | int iobase = host->io_port; | ||
| 106 | int iobase2= host->io_port + 0x100; | ||
| 107 | unsigned char *start = addr; | ||
| 108 | int s; | ||
| 109 | printk("reading %p len %d\n",addr, len); | ||
| 110 | outb(inb(iobase + 128), iobase + 135); | ||
| 111 | while(len > 0) | ||
| 112 | { | ||
| 113 | int status,b,i, timeout; | ||
| 114 | timeout = 0x07FFFFFF; | ||
| 115 | while(((status = STAT(iobase)) & 0x100)==0) | ||
| 116 | { | ||
| 117 | timeout--; | ||
| 118 | if(status & 0x200 || !timeout) | ||
| 119 | { | ||
| 120 | printk("status = %p\n",status); | ||
| 121 | outb(0, iobase + 135); | ||
| 122 | return 1; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | if(len >= 128) | ||
| 126 | { | ||
| 127 | for(i=0; i<64; i++) | ||
| 128 | { | ||
| 129 | b = inw(iobase + 136); | ||
| 130 | *addr++ = b; | ||
| 131 | *addr++ = b>>8; | ||
| 132 | } | ||
| 133 | len -= 128; | ||
| 134 | } | ||
| 135 | else | ||
| 136 | { | ||
| 137 | b = inw(iobase + 136); | ||
| 138 | *addr ++ = b; | ||
| 139 | len -= 1; | ||
| 140 | if(len) | ||
| 141 | *addr ++ = b>>8; | ||
| 142 | len -= 1; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | outb(0, iobase + 135); | ||
| 146 | printk("first bytes = %02X %02X %02X %20X %02X %02X %02X\n",*start, start[1], start[2], start[3], start[4], start[5], start[6]); | ||
| 147 | return 1; | ||
| 148 | } | ||
| 149 | #endif | ||
| 150 | #undef STAT | ||
| 151 | |||
| 152 | #define BOARD_NORMAL 0 | 75 | #define BOARD_NORMAL 0 |
| 153 | #define BOARD_NCR53C400 1 | 76 | #define BOARD_NCR53C400 1 |
| 154 | 77 | ||
| @@ -173,25 +96,36 @@ static struct Scsi_Host *host; | |||
| 173 | 96 | ||
| 174 | static int __init ecoscsi_init(void) | 97 | static int __init ecoscsi_init(void) |
| 175 | { | 98 | { |
| 99 | void __iomem *_base; | ||
| 100 | int ret; | ||
| 176 | 101 | ||
| 177 | host = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata)); | 102 | if (!request_mem_region(0x33a0000, 4096, "ecoscsi")) { |
| 178 | if (!host) | 103 | ret = -EBUSY; |
| 179 | return 0; | 104 | goto out; |
| 105 | } | ||
| 180 | 106 | ||
| 181 | host->io_port = 0x80ce8000; | 107 | _base = ioremap(0x33a0000, 4096); |
| 182 | host->n_io_port = 144; | 108 | if (!_base) { |
| 183 | host->irq = IRQ_NONE; | 109 | ret = -ENOMEM; |
| 110 | goto out_release; | ||
| 111 | } | ||
| 184 | 112 | ||
| 185 | if (!(request_region(host->io_port, host->n_io_port, "ecoscsi")) ) | 113 | NCR5380_write(MODE_REG, 0x20); /* Is it really SCSI? */ |
| 186 | goto unregister_scsi; | 114 | if (NCR5380_read(MODE_REG) != 0x20) /* Write to a reg. */ |
| 115 | goto out_unmap; | ||
| 187 | 116 | ||
| 188 | ecoscsi_write(host, MODE_REG, 0x20); /* Is it really SCSI? */ | 117 | NCR5380_write(MODE_REG, 0x00); /* it back. */ |
| 189 | if (ecoscsi_read(host, MODE_REG) != 0x20) /* Write to a reg. */ | 118 | if (NCR5380_read(MODE_REG) != 0x00) |
| 190 | goto release_reg; | 119 | goto out_unmap; |
| 191 | 120 | ||
| 192 | ecoscsi_write(host, MODE_REG, 0x00 ); /* it back. */ | 121 | host = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata)); |
| 193 | if (ecoscsi_read(host, MODE_REG) != 0x00) | 122 | if (!host) { |
| 194 | goto release_reg; | 123 | ret = -ENOMEM; |
| 124 | goto out_unmap; | ||
| 125 | } | ||
| 126 | |||
| 127 | priv(host)->base = _base; | ||
| 128 | host->irq = IRQ_NONE; | ||
| 195 | 129 | ||
| 196 | NCR5380_init(host, 0); | 130 | NCR5380_init(host, 0); |
| 197 | 131 | ||
| @@ -206,24 +140,20 @@ static int __init ecoscsi_init(void) | |||
| 206 | scsi_scan_host(host); | 140 | scsi_scan_host(host); |
| 207 | return 0; | 141 | return 0; |
| 208 | 142 | ||
| 209 | release_reg: | 143 | out_unmap: |
| 210 | release_region(host->io_port, host->n_io_port); | 144 | iounmap(_base); |
| 211 | unregister_scsi: | 145 | out_release: |
| 212 | scsi_host_put(host); | 146 | release_mem_region(0x33a0000, 4096); |
| 213 | return -ENODEV; | 147 | out: |
| 148 | return ret; | ||
| 214 | } | 149 | } |
| 215 | 150 | ||
| 216 | static void __exit ecoscsi_exit(void) | 151 | static void __exit ecoscsi_exit(void) |
| 217 | { | 152 | { |
| 218 | scsi_remove_host(host); | 153 | scsi_remove_host(host); |
| 219 | |||
| 220 | if (shpnt->irq != IRQ_NONE) | ||
| 221 | free_irq(shpnt->irq, NULL); | ||
| 222 | NCR5380_exit(host); | 154 | NCR5380_exit(host); |
| 223 | if (shpnt->io_port) | ||
| 224 | release_region(shpnt->io_port, shpnt->n_io_port); | ||
| 225 | |||
| 226 | scsi_host_put(host); | 155 | scsi_host_put(host); |
| 156 | release_mem_region(0x33a0000, 4096); | ||
| 227 | return 0; | 157 | return 0; |
| 228 | } | 158 | } |
| 229 | 159 | ||
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index c21b8392c928..849cdf89f7bb 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c | |||
| @@ -23,15 +23,18 @@ | |||
| 23 | 23 | ||
| 24 | #define OAKSCSI_PUBLIC_RELEASE 1 | 24 | #define OAKSCSI_PUBLIC_RELEASE 1 |
| 25 | 25 | ||
| 26 | #define NCR5380_read(reg) oakscsi_read(_instance, reg) | 26 | #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) |
| 27 | #define NCR5380_write(reg, value) oakscsi_write(_instance, reg, value) | 27 | #define NCR5380_local_declare() void __iomem *_base |
| 28 | #define NCR5380_setup(host) _base = priv(host)->base | ||
| 29 | |||
| 30 | #define NCR5380_read(reg) readb(_base + ((reg) << 2)) | ||
| 31 | #define NCR5380_write(reg, value) writeb(value, _base + ((reg) << 2)) | ||
| 28 | #define NCR5380_intr oakscsi_intr | 32 | #define NCR5380_intr oakscsi_intr |
| 29 | #define NCR5380_queue_command oakscsi_queue_command | 33 | #define NCR5380_queue_command oakscsi_queue_command |
| 30 | #define NCR5380_proc_info oakscsi_proc_info | 34 | #define NCR5380_proc_info oakscsi_proc_info |
| 31 | 35 | ||
| 32 | #define NCR5380_implementation_fields int port, ctrl | 36 | #define NCR5380_implementation_fields \ |
| 33 | #define NCR5380_local_declare() struct Scsi_Host *_instance | 37 | void __iomem *base |
| 34 | #define NCR5380_setup(instance) _instance = instance | ||
| 35 | 38 | ||
| 36 | #define BOARD_NORMAL 0 | 39 | #define BOARD_NORMAL 0 |
| 37 | #define BOARD_NCR53C400 1 | 40 | #define BOARD_NCR53C400 1 |
| @@ -39,60 +42,62 @@ | |||
| 39 | #include "../NCR5380.h" | 42 | #include "../NCR5380.h" |
| 40 | 43 | ||
| 41 | #undef START_DMA_INITIATOR_RECEIVE_REG | 44 | #undef START_DMA_INITIATOR_RECEIVE_REG |
| 42 | #define START_DMA_INITIATOR_RECEIVE_REG (7 + 128) | 45 | #define START_DMA_INITIATOR_RECEIVE_REG (128 + 7) |
| 43 | 46 | ||
| 44 | const char * oakscsi_info (struct Scsi_Host *spnt) | 47 | const char * oakscsi_info (struct Scsi_Host *spnt) |
| 45 | { | 48 | { |
| 46 | return ""; | 49 | return ""; |
| 47 | } | 50 | } |
| 48 | 51 | ||
| 49 | #define STAT(p) inw(p + 144) | 52 | #define STAT ((128 + 16) << 2) |
| 50 | extern void inswb(int from, void *to, int len); | 53 | #define DATA ((128 + 8) << 2) |
| 51 | 54 | ||
| 52 | static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, | 55 | static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, |
| 53 | int len) | 56 | int len) |
| 54 | { | 57 | { |
| 55 | int iobase = instance->io_port; | 58 | void __iomem *base = priv(instance)->base; |
| 59 | |||
| 56 | printk("writing %p len %d\n",addr, len); | 60 | printk("writing %p len %d\n",addr, len); |
| 57 | if(!len) return -1; | 61 | if(!len) return -1; |
| 58 | 62 | ||
| 59 | while(1) | 63 | while(1) |
| 60 | { | 64 | { |
| 61 | int status; | 65 | int status; |
| 62 | while(((status = STAT(iobase)) & 0x100)==0); | 66 | while (((status = readw(base + STAT)) & 0x100)==0); |
| 63 | } | 67 | } |
| 64 | } | 68 | } |
| 65 | 69 | ||
| 66 | static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, | 70 | static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, |
| 67 | int len) | 71 | int len) |
| 68 | { | 72 | { |
| 69 | int iobase = instance->io_port; | 73 | void __iomem *base = priv(instance)->base; |
| 70 | printk("reading %p len %d\n", addr, len); | 74 | printk("reading %p len %d\n", addr, len); |
| 71 | while(len > 0) | 75 | while(len > 0) |
| 72 | { | 76 | { |
| 73 | int status, timeout; | 77 | unsigned int status, timeout; |
| 74 | unsigned long b; | 78 | unsigned long b; |
| 75 | 79 | ||
| 76 | timeout = 0x01FFFFFF; | 80 | timeout = 0x01FFFFFF; |
| 77 | 81 | ||
| 78 | while(((status = STAT(iobase)) & 0x100)==0) | 82 | while (((status = readw(base + STAT)) & 0x100)==0) |
| 79 | { | 83 | { |
| 80 | timeout--; | 84 | timeout--; |
| 81 | if(status & 0x200 || !timeout) | 85 | if(status & 0x200 || !timeout) |
| 82 | { | 86 | { |
| 83 | printk("status = %08X\n",status); | 87 | printk("status = %08X\n", status); |
| 84 | return 1; | 88 | return 1; |
| 85 | } | 89 | } |
| 86 | } | 90 | } |
| 91 | |||
| 87 | if(len >= 128) | 92 | if(len >= 128) |
| 88 | { | 93 | { |
| 89 | inswb(iobase + 136, addr, 128); | 94 | readsw(base + DATA, addr, 128); |
| 90 | addr += 128; | 95 | addr += 128; |
| 91 | len -= 128; | 96 | len -= 128; |
| 92 | } | 97 | } |
| 93 | else | 98 | else |
| 94 | { | 99 | { |
| 95 | b = (unsigned long) inw(iobase + 136); | 100 | b = (unsigned long) readw(base + DATA); |
| 96 | *addr ++ = b; | 101 | *addr ++ = b; |
| 97 | len -= 1; | 102 | len -= 1; |
| 98 | if(len) | 103 | if(len) |
| @@ -103,10 +108,8 @@ printk("reading %p len %d\n", addr, len); | |||
| 103 | return 0; | 108 | return 0; |
| 104 | } | 109 | } |
| 105 | 110 | ||
| 106 | #define oakscsi_read(instance,reg) (inb((instance)->io_port + (reg))) | ||
| 107 | #define oakscsi_write(instance,reg,val) (outb((val), (instance)->io_port + (reg))) | ||
| 108 | |||
| 109 | #undef STAT | 111 | #undef STAT |
| 112 | #undef DATA | ||
| 110 | 113 | ||
| 111 | #include "../NCR5380.c" | 114 | #include "../NCR5380.c" |
| 112 | 115 | ||
| @@ -132,18 +135,26 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) | |||
| 132 | struct Scsi_Host *host; | 135 | struct Scsi_Host *host; |
| 133 | int ret = -ENOMEM; | 136 | int ret = -ENOMEM; |
| 134 | 137 | ||
| 135 | host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata)); | 138 | ret = ecard_request_resources(ec); |
| 136 | if (!host) | 139 | if (ret) |
| 137 | goto out; | 140 | goto out; |
| 138 | 141 | ||
| 139 | host->io_port = ecard_address(ec, ECARD_MEMC, 0); | 142 | host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata)); |
| 143 | if (!host) { | ||
| 144 | ret = -ENOMEM; | ||
| 145 | goto release; | ||
| 146 | } | ||
| 147 | |||
| 148 | priv(host)->base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), | ||
| 149 | ecard_resource_len(ec, ECARD_RES_MEMC)); | ||
| 150 | if (!priv(host)->base) { | ||
| 151 | ret = -ENOMEM; | ||
| 152 | goto unreg; | ||
| 153 | } | ||
| 154 | |||
| 140 | host->irq = IRQ_NONE; | 155 | host->irq = IRQ_NONE; |
| 141 | host->n_io_port = 255; | 156 | host->n_io_port = 255; |
| 142 | 157 | ||
| 143 | ret = -EBUSY; | ||
| 144 | if (!request_region (host->io_port, host->n_io_port, "Oak SCSI")) | ||
| 145 | goto unreg; | ||
| 146 | |||
| 147 | NCR5380_init(host, 0); | 158 | NCR5380_init(host, 0); |
| 148 | 159 | ||
| 149 | printk("scsi%d: at port 0x%08lx irqs disabled", | 160 | printk("scsi%d: at port 0x%08lx irqs disabled", |
| @@ -156,15 +167,17 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) | |||
| 156 | 167 | ||
| 157 | ret = scsi_add_host(host, &ec->dev); | 168 | ret = scsi_add_host(host, &ec->dev); |
| 158 | if (ret) | 169 | if (ret) |
| 159 | goto out_release; | 170 | goto out_unmap; |
| 160 | 171 | ||
| 161 | scsi_scan_host(host); | 172 | scsi_scan_host(host); |
| 162 | goto out; | 173 | goto out; |
| 163 | 174 | ||
| 164 | out_release: | 175 | out_unmap: |
| 165 | release_region(host->io_port, host->n_io_port); | 176 | iounmap(priv(host)->base); |
| 166 | unreg: | 177 | unreg: |
| 167 | scsi_host_put(host); | 178 | scsi_host_put(host); |
| 179 | release: | ||
| 180 | ecard_release_resources(ec); | ||
| 168 | out: | 181 | out: |
| 169 | return ret; | 182 | return ret; |
| 170 | } | 183 | } |
| @@ -177,8 +190,9 @@ static void __devexit oakscsi_remove(struct expansion_card *ec) | |||
| 177 | scsi_remove_host(host); | 190 | scsi_remove_host(host); |
| 178 | 191 | ||
| 179 | NCR5380_exit(host); | 192 | NCR5380_exit(host); |
| 180 | release_region(host->io_port, host->n_io_port); | 193 | iounmap(priv(host)->base); |
| 181 | scsi_host_put(host); | 194 | scsi_host_put(host); |
| 195 | ecard_release_resources(ec); | ||
| 182 | } | 196 | } |
| 183 | 197 | ||
| 184 | static const struct ecard_id oakscsi_cids[] = { | 198 | static const struct ecard_id oakscsi_cids[] = { |
diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c index 012cdea7946d..cac354086737 100644 --- a/drivers/scsi/bvme6000_scsi.c +++ b/drivers/scsi/bvme6000_scsi.c | |||
| @@ -74,6 +74,7 @@ bvme6000_probe(struct device *dev) | |||
| 74 | goto out_put_host; | 74 | goto out_put_host; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | dev_set_drvdata(dev, host); | ||
| 77 | scsi_scan_host(host); | 78 | scsi_scan_host(host); |
| 78 | 79 | ||
| 79 | return 0; | 80 | return 0; |
| @@ -89,7 +90,7 @@ bvme6000_probe(struct device *dev) | |||
| 89 | static __devexit int | 90 | static __devexit int |
| 90 | bvme6000_device_remove(struct device *dev) | 91 | bvme6000_device_remove(struct device *dev) |
| 91 | { | 92 | { |
| 92 | struct Scsi_Host *host = dev_to_shost(dev); | 93 | struct Scsi_Host *host = dev_get_drvdata(dev); |
| 93 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); | 94 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); |
| 94 | 95 | ||
| 95 | scsi_remove_host(host); | 96 | scsi_remove_host(host); |
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h index d5576d54ce76..856e38b14861 100644 --- a/drivers/scsi/esp_scsi.h +++ b/drivers/scsi/esp_scsi.h | |||
| @@ -220,7 +220,7 @@ | |||
| 220 | #define ESP_BUSID_RESELID 0x10 | 220 | #define ESP_BUSID_RESELID 0x10 |
| 221 | #define ESP_BUSID_CTR32BIT 0x40 | 221 | #define ESP_BUSID_CTR32BIT 0x40 |
| 222 | 222 | ||
| 223 | #define ESP_BUS_TIMEOUT 250 /* In milli-seconds */ | 223 | #define ESP_BUS_TIMEOUT 275 /* In milli-seconds */ |
| 224 | #define ESP_TIMEO_CONST 8192 | 224 | #define ESP_TIMEO_CONST 8192 |
| 225 | #define ESP_NEG_DEFP(mhz, cfact) \ | 225 | #define ESP_NEG_DEFP(mhz, cfact) \ |
| 226 | ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact))) | 226 | ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact))) |
diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig index aafdc92f8312..3a3c1ac9c6cd 100644 --- a/drivers/scsi/libsas/Kconfig +++ b/drivers/scsi/libsas/Kconfig | |||
| @@ -30,6 +30,13 @@ config SCSI_SAS_LIBSAS | |||
| 30 | This provides transport specific helpers for SAS drivers which | 30 | This provides transport specific helpers for SAS drivers which |
| 31 | use the domain device construct (like the aic94xxx). | 31 | use the domain device construct (like the aic94xxx). |
| 32 | 32 | ||
| 33 | config SCSI_SAS_ATA | ||
| 34 | bool "ATA support for libsas (requires libata)" | ||
| 35 | depends on SCSI_SAS_LIBSAS && ATA | ||
| 36 | help | ||
| 37 | Builds in ATA support into libsas. Will necessitate | ||
| 38 | the loading of libata along with libsas. | ||
| 39 | |||
| 33 | config SCSI_SAS_LIBSAS_DEBUG | 40 | config SCSI_SAS_LIBSAS_DEBUG |
| 34 | bool "Compile the SAS Domain Transport Attributes in debug mode" | 41 | bool "Compile the SAS Domain Transport Attributes in debug mode" |
| 35 | default y | 42 | default y |
diff --git a/drivers/scsi/libsas/Makefile b/drivers/scsi/libsas/Makefile index 44d972a3b4bd..fd387b91856e 100644 --- a/drivers/scsi/libsas/Makefile +++ b/drivers/scsi/libsas/Makefile | |||
| @@ -34,3 +34,4 @@ libsas-y += sas_init.o \ | |||
| 34 | sas_discover.o \ | 34 | sas_discover.o \ |
| 35 | sas_expander.o \ | 35 | sas_expander.o \ |
| 36 | sas_scsi_host.o | 36 | sas_scsi_host.o |
| 37 | libsas-$(CONFIG_SCSI_SAS_ATA) += sas_ata.o | ||
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c new file mode 100644 index 000000000000..ced2de32c511 --- /dev/null +++ b/drivers/scsi/libsas/sas_ata.c | |||
| @@ -0,0 +1,817 @@ | |||
| 1 | /* | ||
| 2 | * Support for SATA devices on Serial Attached SCSI (SAS) controllers | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 IBM Corporation | ||
| 5 | * | ||
| 6 | * Written by: Darrick J. Wong <djwong@us.ibm.com>, IBM Corporation | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License as | ||
| 10 | * published by the Free Software Foundation; either version 2 of the | ||
| 11 | * License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but | ||
| 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 21 | * USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/scatterlist.h> | ||
| 25 | |||
| 26 | #include <scsi/sas_ata.h> | ||
| 27 | #include "sas_internal.h" | ||
| 28 | #include <scsi/scsi_host.h> | ||
| 29 | #include <scsi/scsi_device.h> | ||
| 30 | #include <scsi/scsi_tcq.h> | ||
| 31 | #include <scsi/scsi.h> | ||
| 32 | #include <scsi/scsi_transport.h> | ||
| 33 | #include <scsi/scsi_transport_sas.h> | ||
| 34 | #include "../scsi_sas_internal.h" | ||
| 35 | #include "../scsi_transport_api.h" | ||
| 36 | #include <scsi/scsi_eh.h> | ||
| 37 | |||
| 38 | static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts) | ||
| 39 | { | ||
| 40 | /* Cheesy attempt to translate SAS errors into ATA. Hah! */ | ||
| 41 | |||
| 42 | /* transport error */ | ||
| 43 | if (ts->resp == SAS_TASK_UNDELIVERED) | ||
| 44 | return AC_ERR_ATA_BUS; | ||
| 45 | |||
| 46 | /* ts->resp == SAS_TASK_COMPLETE */ | ||
| 47 | /* task delivered, what happened afterwards? */ | ||
| 48 | switch (ts->stat) { | ||
| 49 | case SAS_DEV_NO_RESPONSE: | ||
| 50 | return AC_ERR_TIMEOUT; | ||
| 51 | |||
| 52 | case SAS_INTERRUPTED: | ||
| 53 | case SAS_PHY_DOWN: | ||
| 54 | case SAS_NAK_R_ERR: | ||
| 55 | return AC_ERR_ATA_BUS; | ||
| 56 | |||
| 57 | |||
| 58 | case SAS_DATA_UNDERRUN: | ||
| 59 | /* | ||
| 60 | * Some programs that use the taskfile interface | ||
| 61 | * (smartctl in particular) can cause underrun | ||
| 62 | * problems. Ignore these errors, perhaps at our | ||
| 63 | * peril. | ||
| 64 | */ | ||
| 65 | return 0; | ||
| 66 | |||
| 67 | case SAS_DATA_OVERRUN: | ||
| 68 | case SAS_QUEUE_FULL: | ||
| 69 | case SAS_DEVICE_UNKNOWN: | ||
| 70 | case SAS_SG_ERR: | ||
| 71 | return AC_ERR_INVALID; | ||
| 72 | |||
| 73 | case SAM_CHECK_COND: | ||
| 74 | case SAS_OPEN_TO: | ||
| 75 | case SAS_OPEN_REJECT: | ||
| 76 | SAS_DPRINTK("%s: Saw error %d. What to do?\n", | ||
| 77 | __FUNCTION__, ts->stat); | ||
| 78 | return AC_ERR_OTHER; | ||
| 79 | |||
| 80 | case SAS_ABORTED_TASK: | ||
| 81 | return AC_ERR_DEV; | ||
| 82 | |||
| 83 | case SAS_PROTO_RESPONSE: | ||
| 84 | /* This means the ending_fis has the error | ||
| 85 | * value; return 0 here to collect it */ | ||
| 86 | return 0; | ||
| 87 | default: | ||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | static void sas_ata_task_done(struct sas_task *task) | ||
| 93 | { | ||
| 94 | struct ata_queued_cmd *qc = task->uldd_task; | ||
| 95 | struct domain_device *dev; | ||
| 96 | struct task_status_struct *stat = &task->task_status; | ||
| 97 | struct ata_task_resp *resp = (struct ata_task_resp *)stat->buf; | ||
| 98 | struct sas_ha_struct *sas_ha; | ||
| 99 | enum ata_completion_errors ac; | ||
| 100 | unsigned long flags; | ||
| 101 | |||
| 102 | if (!qc) | ||
| 103 | goto qc_already_gone; | ||
| 104 | |||
| 105 | dev = qc->ap->private_data; | ||
| 106 | sas_ha = dev->port->ha; | ||
| 107 | |||
| 108 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); | ||
| 109 | if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_GOOD) { | ||
| 110 | ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); | ||
| 111 | qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); | ||
| 112 | dev->sata_dev.sstatus = resp->sstatus; | ||
| 113 | dev->sata_dev.serror = resp->serror; | ||
| 114 | dev->sata_dev.scontrol = resp->scontrol; | ||
| 115 | } else if (stat->stat != SAM_STAT_GOOD) { | ||
| 116 | ac = sas_to_ata_err(stat); | ||
| 117 | if (ac) { | ||
| 118 | SAS_DPRINTK("%s: SAS error %x\n", __FUNCTION__, | ||
| 119 | stat->stat); | ||
| 120 | /* We saw a SAS error. Send a vague error. */ | ||
| 121 | qc->err_mask = ac; | ||
| 122 | dev->sata_dev.tf.feature = 0x04; /* status err */ | ||
| 123 | dev->sata_dev.tf.command = ATA_ERR; | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | qc->lldd_task = NULL; | ||
| 128 | if (qc->scsicmd) | ||
| 129 | ASSIGN_SAS_TASK(qc->scsicmd, NULL); | ||
| 130 | ata_qc_complete(qc); | ||
| 131 | spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags); | ||
| 132 | |||
| 133 | /* | ||
| 134 | * If the sas_task has an ata qc, a scsi_cmnd and the aborted | ||
| 135 | * flag is set, then we must have come in via the libsas EH | ||
| 136 | * functions. When we exit this function, we need to put the | ||
| 137 | * scsi_cmnd on the list of finished errors. The ata_qc_complete | ||
| 138 | * call cleans up the libata side of things but we're protected | ||
| 139 | * from the scsi_cmnd going away because the scsi_cmnd is owned | ||
| 140 | * by the EH, making libata's call to scsi_done a NOP. | ||
| 141 | */ | ||
| 142 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
| 143 | if (qc->scsicmd && task->task_state_flags & SAS_TASK_STATE_ABORTED) | ||
| 144 | scsi_eh_finish_cmd(qc->scsicmd, &sas_ha->eh_done_q); | ||
| 145 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
| 146 | |||
| 147 | qc_already_gone: | ||
| 148 | list_del_init(&task->list); | ||
| 149 | sas_free_task(task); | ||
| 150 | } | ||
| 151 | |||
| 152 | static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) | ||
| 153 | { | ||
| 154 | int res; | ||
| 155 | struct sas_task *task; | ||
| 156 | struct domain_device *dev = qc->ap->private_data; | ||
| 157 | struct sas_ha_struct *sas_ha = dev->port->ha; | ||
| 158 | struct Scsi_Host *host = sas_ha->core.shost; | ||
| 159 | struct sas_internal *i = to_sas_internal(host->transportt); | ||
| 160 | struct scatterlist *sg; | ||
| 161 | unsigned int num = 0; | ||
| 162 | unsigned int xfer = 0; | ||
| 163 | |||
| 164 | task = sas_alloc_task(GFP_ATOMIC); | ||
| 165 | if (!task) | ||
| 166 | return AC_ERR_SYSTEM; | ||
| 167 | task->dev = dev; | ||
| 168 | task->task_proto = SAS_PROTOCOL_STP; | ||
| 169 | task->task_done = sas_ata_task_done; | ||
| 170 | |||
| 171 | if (qc->tf.command == ATA_CMD_FPDMA_WRITE || | ||
| 172 | qc->tf.command == ATA_CMD_FPDMA_READ) { | ||
| 173 | /* Need to zero out the tag libata assigned us */ | ||
| 174 | qc->tf.nsect = 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); | ||
| 178 | task->uldd_task = qc; | ||
| 179 | if (is_atapi_taskfile(&qc->tf)) { | ||
| 180 | memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); | ||
| 181 | task->total_xfer_len = qc->nbytes + qc->pad_len; | ||
| 182 | task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem; | ||
| 183 | } else { | ||
| 184 | ata_for_each_sg(sg, qc) { | ||
| 185 | num++; | ||
| 186 | xfer += sg->length; | ||
| 187 | } | ||
| 188 | |||
| 189 | task->total_xfer_len = xfer; | ||
| 190 | task->num_scatter = num; | ||
| 191 | } | ||
| 192 | |||
| 193 | task->data_dir = qc->dma_dir; | ||
| 194 | task->scatter = qc->__sg; | ||
| 195 | task->ata_task.retry_count = 1; | ||
| 196 | task->task_state_flags = SAS_TASK_STATE_PENDING; | ||
| 197 | qc->lldd_task = task; | ||
| 198 | |||
| 199 | switch (qc->tf.protocol) { | ||
| 200 | case ATA_PROT_NCQ: | ||
| 201 | task->ata_task.use_ncq = 1; | ||
| 202 | /* fall through */ | ||
| 203 | case ATA_PROT_ATAPI_DMA: | ||
| 204 | case ATA_PROT_DMA: | ||
| 205 | task->ata_task.dma_xfer = 1; | ||
| 206 | break; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (qc->scsicmd) | ||
| 210 | ASSIGN_SAS_TASK(qc->scsicmd, task); | ||
| 211 | |||
| 212 | if (sas_ha->lldd_max_execute_num < 2) | ||
| 213 | res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC); | ||
| 214 | else | ||
| 215 | res = sas_queue_up(task); | ||
| 216 | |||
| 217 | /* Examine */ | ||
| 218 | if (res) { | ||
| 219 | SAS_DPRINTK("lldd_execute_task returned: %d\n", res); | ||
| 220 | |||
| 221 | if (qc->scsicmd) | ||
| 222 | ASSIGN_SAS_TASK(qc->scsicmd, NULL); | ||
| 223 | sas_free_task(task); | ||
| 224 | return AC_ERR_SYSTEM; | ||
| 225 | } | ||
| 226 | |||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | static u8 sas_ata_check_status(struct ata_port *ap) | ||
| 231 | { | ||
| 232 | struct domain_device *dev = ap->private_data; | ||
| 233 | return dev->sata_dev.tf.command; | ||
| 234 | } | ||
| 235 | |||
| 236 | static void sas_ata_phy_reset(struct ata_port *ap) | ||
| 237 | { | ||
| 238 | struct domain_device *dev = ap->private_data; | ||
| 239 | struct sas_internal *i = | ||
| 240 | to_sas_internal(dev->port->ha->core.shost->transportt); | ||
| 241 | int res = 0; | ||
| 242 | |||
| 243 | if (i->dft->lldd_I_T_nexus_reset) | ||
| 244 | res = i->dft->lldd_I_T_nexus_reset(dev); | ||
| 245 | |||
| 246 | if (res) | ||
| 247 | SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__); | ||
| 248 | |||
| 249 | switch (dev->sata_dev.command_set) { | ||
| 250 | case ATA_COMMAND_SET: | ||
| 251 | SAS_DPRINTK("%s: Found ATA device.\n", __FUNCTION__); | ||
| 252 | ap->device[0].class = ATA_DEV_ATA; | ||
| 253 | break; | ||
| 254 | case ATAPI_COMMAND_SET: | ||
| 255 | SAS_DPRINTK("%s: Found ATAPI device.\n", __FUNCTION__); | ||
| 256 | ap->device[0].class = ATA_DEV_ATAPI; | ||
| 257 | break; | ||
| 258 | default: | ||
| 259 | SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", | ||
| 260 | __FUNCTION__, | ||
| 261 | dev->sata_dev.command_set); | ||
| 262 | ap->device[0].class = ATA_DEV_UNKNOWN; | ||
| 263 | break; | ||
| 264 | } | ||
| 265 | |||
| 266 | ap->cbl = ATA_CBL_SATA; | ||
| 267 | } | ||
| 268 | |||
| 269 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) | ||
| 270 | { | ||
| 271 | if (qc->flags & ATA_QCFLAG_FAILED) | ||
| 272 | qc->err_mask |= AC_ERR_OTHER; | ||
| 273 | |||
| 274 | if (qc->err_mask) { | ||
| 275 | /* | ||
| 276 | * Find the sas_task and kill it. By this point, | ||
| 277 | * libata has decided to kill the qc, so we needn't | ||
| 278 | * bother with sas_ata_task_done. But we still | ||
| 279 | * ought to abort the task. | ||
| 280 | */ | ||
| 281 | struct sas_task *task = qc->lldd_task; | ||
| 282 | unsigned long flags; | ||
| 283 | |||
| 284 | qc->lldd_task = NULL; | ||
| 285 | if (task) { | ||
| 286 | /* Should this be a AT(API) device reset? */ | ||
| 287 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
| 288 | task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; | ||
| 289 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
| 290 | |||
| 291 | task->uldd_task = NULL; | ||
| 292 | __sas_task_abort(task); | ||
| 293 | } | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | static void sas_ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | ||
| 298 | { | ||
| 299 | struct domain_device *dev = ap->private_data; | ||
| 300 | memcpy(tf, &dev->sata_dev.tf, sizeof (*tf)); | ||
| 301 | } | ||
| 302 | |||
| 303 | static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in, | ||
| 304 | u32 val) | ||
| 305 | { | ||
| 306 | struct domain_device *dev = ap->private_data; | ||
| 307 | |||
| 308 | SAS_DPRINTK("STUB %s\n", __FUNCTION__); | ||
| 309 | switch (sc_reg_in) { | ||
| 310 | case SCR_STATUS: | ||
| 311 | dev->sata_dev.sstatus = val; | ||
| 312 | break; | ||
| 313 | case SCR_CONTROL: | ||
| 314 | dev->sata_dev.scontrol = val; | ||
| 315 | break; | ||
| 316 | case SCR_ERROR: | ||
| 317 | dev->sata_dev.serror = val; | ||
| 318 | break; | ||
| 319 | case SCR_ACTIVE: | ||
| 320 | dev->sata_dev.ap->sactive = val; | ||
| 321 | break; | ||
| 322 | default: | ||
| 323 | return -EINVAL; | ||
| 324 | } | ||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in, | ||
| 329 | u32 *val) | ||
| 330 | { | ||
| 331 | struct domain_device *dev = ap->private_data; | ||
| 332 | |||
| 333 | SAS_DPRINTK("STUB %s\n", __FUNCTION__); | ||
| 334 | switch (sc_reg_in) { | ||
| 335 | case SCR_STATUS: | ||
| 336 | *val = dev->sata_dev.sstatus; | ||
| 337 | return 0; | ||
| 338 | case SCR_CONTROL: | ||
| 339 | *val = dev->sata_dev.scontrol; | ||
| 340 | return 0; | ||
| 341 | case SCR_ERROR: | ||
| 342 | *val = dev->sata_dev.serror; | ||
| 343 | return 0; | ||
| 344 | case SCR_ACTIVE: | ||
| 345 | *val = dev->sata_dev.ap->sactive; | ||
| 346 | return 0; | ||
| 347 | default: | ||
| 348 | return -EINVAL; | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | static struct ata_port_operations sas_sata_ops = { | ||
| 353 | .port_disable = ata_port_disable, | ||
| 354 | .check_status = sas_ata_check_status, | ||
| 355 | .check_altstatus = sas_ata_check_status, | ||
| 356 | .dev_select = ata_noop_dev_select, | ||
| 357 | .phy_reset = sas_ata_phy_reset, | ||
| 358 | .post_internal_cmd = sas_ata_post_internal, | ||
| 359 | .tf_read = sas_ata_tf_read, | ||
| 360 | .qc_prep = ata_noop_qc_prep, | ||
| 361 | .qc_issue = sas_ata_qc_issue, | ||
| 362 | .port_start = ata_sas_port_start, | ||
| 363 | .port_stop = ata_sas_port_stop, | ||
| 364 | .scr_read = sas_ata_scr_read, | ||
| 365 | .scr_write = sas_ata_scr_write | ||
| 366 | }; | ||
| 367 | |||
| 368 | static struct ata_port_info sata_port_info = { | ||
| 369 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | | ||
| 370 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ, | ||
| 371 | .pio_mask = 0x1f, /* PIO0-4 */ | ||
| 372 | .mwdma_mask = 0x07, /* MWDMA0-2 */ | ||
| 373 | .udma_mask = ATA_UDMA6, | ||
| 374 | .port_ops = &sas_sata_ops | ||
| 375 | }; | ||
| 376 | |||
| 377 | int sas_ata_init_host_and_port(struct domain_device *found_dev, | ||
| 378 | struct scsi_target *starget) | ||
| 379 | { | ||
| 380 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
| 381 | struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); | ||
| 382 | struct ata_port *ap; | ||
| 383 | |||
| 384 | ata_host_init(&found_dev->sata_dev.ata_host, | ||
| 385 | &ha->pcidev->dev, | ||
| 386 | sata_port_info.flags, | ||
| 387 | &sas_sata_ops); | ||
| 388 | ap = ata_sas_port_alloc(&found_dev->sata_dev.ata_host, | ||
| 389 | &sata_port_info, | ||
| 390 | shost); | ||
| 391 | if (!ap) { | ||
| 392 | SAS_DPRINTK("ata_sas_port_alloc failed.\n"); | ||
| 393 | return -ENODEV; | ||
| 394 | } | ||
| 395 | |||
| 396 | ap->private_data = found_dev; | ||
| 397 | ap->cbl = ATA_CBL_SATA; | ||
| 398 | ap->scsi_host = shost; | ||
| 399 | found_dev->sata_dev.ap = ap; | ||
| 400 | |||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | |||
| 404 | void sas_ata_task_abort(struct sas_task *task) | ||
| 405 | { | ||
| 406 | struct ata_queued_cmd *qc = task->uldd_task; | ||
| 407 | struct completion *waiting; | ||
| 408 | |||
| 409 | /* Bounce SCSI-initiated commands to the SCSI EH */ | ||
| 410 | if (qc->scsicmd) { | ||
| 411 | scsi_req_abort_cmd(qc->scsicmd); | ||
| 412 | scsi_schedule_eh(qc->scsicmd->device->host); | ||
| 413 | return; | ||
| 414 | } | ||
| 415 | |||
| 416 | /* Internal command, fake a timeout and complete. */ | ||
| 417 | qc->flags &= ~ATA_QCFLAG_ACTIVE; | ||
| 418 | qc->flags |= ATA_QCFLAG_FAILED; | ||
| 419 | qc->err_mask |= AC_ERR_TIMEOUT; | ||
| 420 | waiting = qc->private_data; | ||
| 421 | complete(waiting); | ||
| 422 | } | ||
| 423 | |||
| 424 | static void sas_task_timedout(unsigned long _task) | ||
| 425 | { | ||
| 426 | struct sas_task *task = (void *) _task; | ||
| 427 | unsigned long flags; | ||
| 428 | |||
| 429 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
| 430 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) | ||
| 431 | task->task_state_flags |= SAS_TASK_STATE_ABORTED; | ||
| 432 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
| 433 | |||
| 434 | complete(&task->completion); | ||
| 435 | } | ||
| 436 | |||
| 437 | static void sas_disc_task_done(struct sas_task *task) | ||
| 438 | { | ||
| 439 | if (!del_timer(&task->timer)) | ||
| 440 | return; | ||
| 441 | complete(&task->completion); | ||
| 442 | } | ||
| 443 | |||
| 444 | #define SAS_DEV_TIMEOUT 10 | ||
| 445 | |||
| 446 | /** | ||
| 447 | * sas_execute_task -- Basic task processing for discovery | ||
| 448 | * @task: the task to be executed | ||
| 449 | * @buffer: pointer to buffer to do I/O | ||
| 450 | * @size: size of @buffer | ||
| 451 | * @pci_dma_dir: PCI_DMA_... | ||
| 452 | */ | ||
| 453 | static int sas_execute_task(struct sas_task *task, void *buffer, int size, | ||
| 454 | int pci_dma_dir) | ||
| 455 | { | ||
| 456 | int res = 0; | ||
| 457 | struct scatterlist *scatter = NULL; | ||
| 458 | struct task_status_struct *ts = &task->task_status; | ||
| 459 | int num_scatter = 0; | ||
| 460 | int retries = 0; | ||
| 461 | struct sas_internal *i = | ||
| 462 | to_sas_internal(task->dev->port->ha->core.shost->transportt); | ||
| 463 | |||
| 464 | if (pci_dma_dir != PCI_DMA_NONE) { | ||
| 465 | scatter = kzalloc(sizeof(*scatter), GFP_KERNEL); | ||
| 466 | if (!scatter) | ||
| 467 | goto out; | ||
| 468 | |||
| 469 | sg_init_one(scatter, buffer, size); | ||
| 470 | num_scatter = 1; | ||
| 471 | } | ||
| 472 | |||
| 473 | task->task_proto = task->dev->tproto; | ||
| 474 | task->scatter = scatter; | ||
| 475 | task->num_scatter = num_scatter; | ||
| 476 | task->total_xfer_len = size; | ||
| 477 | task->data_dir = pci_dma_dir; | ||
| 478 | task->task_done = sas_disc_task_done; | ||
| 479 | if (pci_dma_dir != PCI_DMA_NONE && | ||
| 480 | sas_protocol_ata(task->task_proto)) { | ||
| 481 | task->num_scatter = pci_map_sg(task->dev->port->ha->pcidev, | ||
| 482 | task->scatter, | ||
| 483 | task->num_scatter, | ||
| 484 | task->data_dir); | ||
| 485 | } | ||
| 486 | |||
| 487 | for (retries = 0; retries < 5; retries++) { | ||
| 488 | task->task_state_flags = SAS_TASK_STATE_PENDING; | ||
| 489 | init_completion(&task->completion); | ||
| 490 | |||
| 491 | task->timer.data = (unsigned long) task; | ||
| 492 | task->timer.function = sas_task_timedout; | ||
| 493 | task->timer.expires = jiffies + SAS_DEV_TIMEOUT*HZ; | ||
| 494 | add_timer(&task->timer); | ||
| 495 | |||
| 496 | res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); | ||
| 497 | if (res) { | ||
| 498 | del_timer(&task->timer); | ||
| 499 | SAS_DPRINTK("executing SAS discovery task failed:%d\n", | ||
| 500 | res); | ||
| 501 | goto ex_err; | ||
| 502 | } | ||
| 503 | wait_for_completion(&task->completion); | ||
| 504 | res = -ETASK; | ||
| 505 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { | ||
| 506 | int res2; | ||
| 507 | SAS_DPRINTK("task aborted, flags:0x%x\n", | ||
| 508 | task->task_state_flags); | ||
| 509 | res2 = i->dft->lldd_abort_task(task); | ||
| 510 | SAS_DPRINTK("came back from abort task\n"); | ||
| 511 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | ||
| 512 | if (res2 == TMF_RESP_FUNC_COMPLETE) | ||
| 513 | continue; /* Retry the task */ | ||
| 514 | else | ||
| 515 | goto ex_err; | ||
| 516 | } | ||
| 517 | } | ||
| 518 | if (task->task_status.stat == SAM_BUSY || | ||
| 519 | task->task_status.stat == SAM_TASK_SET_FULL || | ||
| 520 | task->task_status.stat == SAS_QUEUE_FULL) { | ||
| 521 | SAS_DPRINTK("task: q busy, sleeping...\n"); | ||
| 522 | schedule_timeout_interruptible(HZ); | ||
| 523 | } else if (task->task_status.stat == SAM_CHECK_COND) { | ||
| 524 | struct scsi_sense_hdr shdr; | ||
| 525 | |||
| 526 | if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size, | ||
| 527 | &shdr)) { | ||
| 528 | SAS_DPRINTK("couldn't normalize sense\n"); | ||
| 529 | continue; | ||
| 530 | } | ||
| 531 | if ((shdr.sense_key == 6 && shdr.asc == 0x29) || | ||
| 532 | (shdr.sense_key == 2 && shdr.asc == 4 && | ||
| 533 | shdr.ascq == 1)) { | ||
| 534 | SAS_DPRINTK("device %016llx LUN: %016llx " | ||
| 535 | "powering up or not ready yet, " | ||
| 536 | "sleeping...\n", | ||
| 537 | SAS_ADDR(task->dev->sas_addr), | ||
| 538 | SAS_ADDR(task->ssp_task.LUN)); | ||
| 539 | |||
| 540 | schedule_timeout_interruptible(5*HZ); | ||
| 541 | } else if (shdr.sense_key == 1) { | ||
| 542 | res = 0; | ||
| 543 | break; | ||
| 544 | } else if (shdr.sense_key == 5) { | ||
| 545 | break; | ||
| 546 | } else { | ||
| 547 | SAS_DPRINTK("dev %016llx LUN: %016llx " | ||
| 548 | "sense key:0x%x ASC:0x%x ASCQ:0x%x" | ||
| 549 | "\n", | ||
| 550 | SAS_ADDR(task->dev->sas_addr), | ||
| 551 | SAS_ADDR(task->ssp_task.LUN), | ||
| 552 | shdr.sense_key, | ||
| 553 | shdr.asc, shdr.ascq); | ||
| 554 | } | ||
| 555 | } else if (task->task_status.resp != SAS_TASK_COMPLETE || | ||
| 556 | task->task_status.stat != SAM_GOOD) { | ||
| 557 | SAS_DPRINTK("task finished with resp:0x%x, " | ||
| 558 | "stat:0x%x\n", | ||
| 559 | task->task_status.resp, | ||
| 560 | task->task_status.stat); | ||
| 561 | goto ex_err; | ||
| 562 | } else { | ||
| 563 | res = 0; | ||
| 564 | break; | ||
| 565 | } | ||
| 566 | } | ||
| 567 | ex_err: | ||
| 568 | if (pci_dma_dir != PCI_DMA_NONE) { | ||
| 569 | if (sas_protocol_ata(task->task_proto)) | ||
| 570 | pci_unmap_sg(task->dev->port->ha->pcidev, | ||
| 571 | task->scatter, task->num_scatter, | ||
| 572 | task->data_dir); | ||
| 573 | kfree(scatter); | ||
| 574 | } | ||
| 575 | out: | ||
| 576 | return res; | ||
| 577 | } | ||
| 578 | |||
| 579 | /* ---------- SATA ---------- */ | ||
| 580 | |||
| 581 | static void sas_get_ata_command_set(struct domain_device *dev) | ||
| 582 | { | ||
| 583 | struct dev_to_host_fis *fis = | ||
| 584 | (struct dev_to_host_fis *) dev->frame_rcvd; | ||
| 585 | |||
| 586 | if ((fis->sector_count == 1 && /* ATA */ | ||
| 587 | fis->lbal == 1 && | ||
| 588 | fis->lbam == 0 && | ||
| 589 | fis->lbah == 0 && | ||
| 590 | fis->device == 0) | ||
| 591 | || | ||
| 592 | (fis->sector_count == 0 && /* CE-ATA (mATA) */ | ||
| 593 | fis->lbal == 0 && | ||
| 594 | fis->lbam == 0xCE && | ||
| 595 | fis->lbah == 0xAA && | ||
| 596 | (fis->device & ~0x10) == 0)) | ||
| 597 | |||
| 598 | dev->sata_dev.command_set = ATA_COMMAND_SET; | ||
| 599 | |||
| 600 | else if ((fis->interrupt_reason == 1 && /* ATAPI */ | ||
| 601 | fis->lbal == 1 && | ||
| 602 | fis->byte_count_low == 0x14 && | ||
| 603 | fis->byte_count_high == 0xEB && | ||
| 604 | (fis->device & ~0x10) == 0)) | ||
| 605 | |||
| 606 | dev->sata_dev.command_set = ATAPI_COMMAND_SET; | ||
| 607 | |||
| 608 | else if ((fis->sector_count == 1 && /* SEMB */ | ||
| 609 | fis->lbal == 1 && | ||
| 610 | fis->lbam == 0x3C && | ||
| 611 | fis->lbah == 0xC3 && | ||
| 612 | fis->device == 0) | ||
| 613 | || | ||
| 614 | (fis->interrupt_reason == 1 && /* SATA PM */ | ||
| 615 | fis->lbal == 1 && | ||
| 616 | fis->byte_count_low == 0x69 && | ||
| 617 | fis->byte_count_high == 0x96 && | ||
| 618 | (fis->device & ~0x10) == 0)) | ||
| 619 | |||
| 620 | /* Treat it as a superset? */ | ||
| 621 | dev->sata_dev.command_set = ATAPI_COMMAND_SET; | ||
| 622 | } | ||
| 623 | |||
| 624 | /** | ||
| 625 | * sas_issue_ata_cmd -- Basic SATA command processing for discovery | ||
| 626 | * @dev: the device to send the command to | ||
| 627 | * @command: the command register | ||
| 628 | * @features: the features register | ||
| 629 | * @buffer: pointer to buffer to do I/O | ||
| 630 | * @size: size of @buffer | ||
| 631 | * @pci_dma_dir: PCI_DMA_... | ||
| 632 | */ | ||
| 633 | static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, | ||
| 634 | u8 features, void *buffer, int size, | ||
| 635 | int pci_dma_dir) | ||
| 636 | { | ||
| 637 | int res = 0; | ||
| 638 | struct sas_task *task; | ||
| 639 | struct dev_to_host_fis *d2h_fis = (struct dev_to_host_fis *) | ||
| 640 | &dev->frame_rcvd[0]; | ||
| 641 | |||
| 642 | res = -ENOMEM; | ||
| 643 | task = sas_alloc_task(GFP_KERNEL); | ||
| 644 | if (!task) | ||
| 645 | goto out; | ||
| 646 | |||
| 647 | task->dev = dev; | ||
| 648 | |||
| 649 | task->ata_task.fis.fis_type = 0x27; | ||
| 650 | task->ata_task.fis.command = command; | ||
| 651 | task->ata_task.fis.features = features; | ||
| 652 | task->ata_task.fis.device = d2h_fis->device; | ||
| 653 | task->ata_task.retry_count = 1; | ||
| 654 | |||
| 655 | res = sas_execute_task(task, buffer, size, pci_dma_dir); | ||
| 656 | |||
| 657 | sas_free_task(task); | ||
| 658 | out: | ||
| 659 | return res; | ||
| 660 | } | ||
| 661 | |||
| 662 | static void sas_sata_propagate_sas_addr(struct domain_device *dev) | ||
| 663 | { | ||
| 664 | unsigned long flags; | ||
| 665 | struct asd_sas_port *port = dev->port; | ||
| 666 | struct asd_sas_phy *phy; | ||
| 667 | |||
| 668 | BUG_ON(dev->parent); | ||
| 669 | |||
| 670 | memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | ||
| 671 | spin_lock_irqsave(&port->phy_list_lock, flags); | ||
| 672 | list_for_each_entry(phy, &port->phy_list, port_phy_el) | ||
| 673 | memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | ||
| 674 | spin_unlock_irqrestore(&port->phy_list_lock, flags); | ||
| 675 | } | ||
| 676 | |||
| 677 | #define ATA_IDENTIFY_DEV 0xEC | ||
| 678 | #define ATA_IDENTIFY_PACKET_DEV 0xA1 | ||
| 679 | #define ATA_SET_FEATURES 0xEF | ||
| 680 | #define ATA_FEATURE_PUP_STBY_SPIN_UP 0x07 | ||
| 681 | |||
| 682 | /** | ||
| 683 | * sas_discover_sata_dev -- discover a STP/SATA device (SATA_DEV) | ||
| 684 | * @dev: STP/SATA device of interest (ATA/ATAPI) | ||
| 685 | * | ||
| 686 | * The LLDD has already been notified of this device, so that we can | ||
| 687 | * send FISes to it. Here we try to get IDENTIFY DEVICE or IDENTIFY | ||
| 688 | * PACKET DEVICE, if ATAPI device, so that the LLDD can fine-tune its | ||
| 689 | * performance for this device. | ||
| 690 | */ | ||
| 691 | static int sas_discover_sata_dev(struct domain_device *dev) | ||
| 692 | { | ||
| 693 | int res; | ||
| 694 | __le16 *identify_x; | ||
| 695 | u8 command; | ||
| 696 | |||
| 697 | identify_x = kzalloc(512, GFP_KERNEL); | ||
| 698 | if (!identify_x) | ||
| 699 | return -ENOMEM; | ||
| 700 | |||
| 701 | if (dev->sata_dev.command_set == ATA_COMMAND_SET) { | ||
| 702 | dev->sata_dev.identify_device = identify_x; | ||
| 703 | command = ATA_IDENTIFY_DEV; | ||
| 704 | } else { | ||
| 705 | dev->sata_dev.identify_packet_device = identify_x; | ||
| 706 | command = ATA_IDENTIFY_PACKET_DEV; | ||
| 707 | } | ||
| 708 | |||
| 709 | res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, | ||
| 710 | PCI_DMA_FROMDEVICE); | ||
| 711 | if (res) | ||
| 712 | goto out_err; | ||
| 713 | |||
| 714 | /* lives on the media? */ | ||
| 715 | if (le16_to_cpu(identify_x[0]) & 4) { | ||
| 716 | /* incomplete response */ | ||
| 717 | SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to " | ||
| 718 | "dev %llx\n", SAS_ADDR(dev->sas_addr)); | ||
| 719 | if (!le16_to_cpu(identify_x[83] & (1<<6))) | ||
| 720 | goto cont1; | ||
| 721 | res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES, | ||
| 722 | ATA_FEATURE_PUP_STBY_SPIN_UP, | ||
| 723 | NULL, 0, PCI_DMA_NONE); | ||
| 724 | if (res) | ||
| 725 | goto cont1; | ||
| 726 | |||
| 727 | schedule_timeout_interruptible(5*HZ); /* More time? */ | ||
| 728 | res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, | ||
| 729 | PCI_DMA_FROMDEVICE); | ||
| 730 | if (res) | ||
| 731 | goto out_err; | ||
| 732 | } | ||
| 733 | cont1: | ||
| 734 | /* Get WWN */ | ||
| 735 | if (dev->port->oob_mode != SATA_OOB_MODE) { | ||
| 736 | memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, | ||
| 737 | SAS_ADDR_SIZE); | ||
| 738 | } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && | ||
| 739 | (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) | ||
| 740 | == 0x5000) { | ||
| 741 | int i; | ||
| 742 | |||
| 743 | for (i = 0; i < 4; i++) { | ||
| 744 | dev->sas_addr[2*i] = | ||
| 745 | (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; | ||
| 746 | dev->sas_addr[2*i+1] = | ||
| 747 | le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; | ||
| 748 | } | ||
| 749 | } | ||
| 750 | sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); | ||
| 751 | if (!dev->parent) | ||
| 752 | sas_sata_propagate_sas_addr(dev); | ||
| 753 | |||
| 754 | /* XXX Hint: register this SATA device with SATL. | ||
| 755 | When this returns, dev->sata_dev->lu is alive and | ||
| 756 | present. | ||
| 757 | sas_satl_register_dev(dev); | ||
| 758 | */ | ||
| 759 | |||
| 760 | sas_fill_in_rphy(dev, dev->rphy); | ||
| 761 | |||
| 762 | return 0; | ||
| 763 | out_err: | ||
| 764 | dev->sata_dev.identify_packet_device = NULL; | ||
| 765 | dev->sata_dev.identify_device = NULL; | ||
| 766 | kfree(identify_x); | ||
| 767 | return res; | ||
| 768 | } | ||
| 769 | |||
| 770 | static int sas_discover_sata_pm(struct domain_device *dev) | ||
| 771 | { | ||
| 772 | return -ENODEV; | ||
| 773 | } | ||
| 774 | |||
| 775 | /** | ||
| 776 | * sas_discover_sata -- discover an STP/SATA domain device | ||
| 777 | * @dev: pointer to struct domain_device of interest | ||
| 778 | * | ||
| 779 | * First we notify the LLDD of this device, so we can send frames to | ||
| 780 | * it. Then depending on the type of device we call the appropriate | ||
| 781 | * discover functions. Once device discover is done, we notify the | ||
| 782 | * LLDD so that it can fine-tune its parameters for the device, by | ||
| 783 | * removing it and then adding it. That is, the second time around, | ||
| 784 | * the driver would have certain fields, that it is looking at, set. | ||
| 785 | * Finally we initialize the kobj so that the device can be added to | ||
| 786 | * the system at registration time. Devices directly attached to a HA | ||
| 787 | * port, have no parents. All other devices do, and should have their | ||
| 788 | * "parent" pointer set appropriately before calling this function. | ||
| 789 | */ | ||
| 790 | int sas_discover_sata(struct domain_device *dev) | ||
| 791 | { | ||
| 792 | int res; | ||
| 793 | |||
| 794 | sas_get_ata_command_set(dev); | ||
| 795 | |||
| 796 | res = sas_notify_lldd_dev_found(dev); | ||
| 797 | if (res) | ||
| 798 | return res; | ||
| 799 | |||
| 800 | switch (dev->dev_type) { | ||
| 801 | case SATA_DEV: | ||
| 802 | res = sas_discover_sata_dev(dev); | ||
| 803 | break; | ||
| 804 | case SATA_PM: | ||
| 805 | res = sas_discover_sata_pm(dev); | ||
| 806 | break; | ||
| 807 | default: | ||
| 808 | break; | ||
| 809 | } | ||
| 810 | sas_notify_lldd_dev_gone(dev); | ||
| 811 | if (!res) { | ||
| 812 | sas_notify_lldd_dev_found(dev); | ||
| 813 | res = sas_rphy_add(dev->rphy); | ||
| 814 | } | ||
| 815 | |||
| 816 | return res; | ||
| 817 | } | ||
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index a65598b1e536..6ac9f61d006a 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c | |||
| @@ -55,149 +55,6 @@ void sas_init_dev(struct domain_device *dev) | |||
| 55 | } | 55 | } |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | static void sas_task_timedout(unsigned long _task) | ||
| 59 | { | ||
| 60 | struct sas_task *task = (void *) _task; | ||
| 61 | unsigned long flags; | ||
| 62 | |||
| 63 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
| 64 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) | ||
| 65 | task->task_state_flags |= SAS_TASK_STATE_ABORTED; | ||
| 66 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
| 67 | |||
| 68 | complete(&task->completion); | ||
| 69 | } | ||
| 70 | |||
| 71 | static void sas_disc_task_done(struct sas_task *task) | ||
| 72 | { | ||
| 73 | if (!del_timer(&task->timer)) | ||
| 74 | return; | ||
| 75 | complete(&task->completion); | ||
| 76 | } | ||
| 77 | |||
| 78 | #define SAS_DEV_TIMEOUT 10 | ||
| 79 | |||
| 80 | /** | ||
| 81 | * sas_execute_task -- Basic task processing for discovery | ||
| 82 | * @task: the task to be executed | ||
| 83 | * @buffer: pointer to buffer to do I/O | ||
| 84 | * @size: size of @buffer | ||
| 85 | * @pci_dma_dir: PCI_DMA_... | ||
| 86 | */ | ||
| 87 | static int sas_execute_task(struct sas_task *task, void *buffer, int size, | ||
| 88 | int pci_dma_dir) | ||
| 89 | { | ||
| 90 | int res = 0; | ||
| 91 | struct scatterlist *scatter = NULL; | ||
| 92 | struct task_status_struct *ts = &task->task_status; | ||
| 93 | int num_scatter = 0; | ||
| 94 | int retries = 0; | ||
| 95 | struct sas_internal *i = | ||
| 96 | to_sas_internal(task->dev->port->ha->core.shost->transportt); | ||
| 97 | |||
| 98 | if (pci_dma_dir != PCI_DMA_NONE) { | ||
| 99 | scatter = kzalloc(sizeof(*scatter), GFP_KERNEL); | ||
| 100 | if (!scatter) | ||
| 101 | goto out; | ||
| 102 | |||
| 103 | sg_init_one(scatter, buffer, size); | ||
| 104 | num_scatter = 1; | ||
| 105 | } | ||
| 106 | |||
| 107 | task->task_proto = task->dev->tproto; | ||
| 108 | task->scatter = scatter; | ||
| 109 | task->num_scatter = num_scatter; | ||
| 110 | task->total_xfer_len = size; | ||
| 111 | task->data_dir = pci_dma_dir; | ||
| 112 | task->task_done = sas_disc_task_done; | ||
| 113 | |||
| 114 | for (retries = 0; retries < 5; retries++) { | ||
| 115 | task->task_state_flags = SAS_TASK_STATE_PENDING; | ||
| 116 | init_completion(&task->completion); | ||
| 117 | |||
| 118 | task->timer.data = (unsigned long) task; | ||
| 119 | task->timer.function = sas_task_timedout; | ||
| 120 | task->timer.expires = jiffies + SAS_DEV_TIMEOUT*HZ; | ||
| 121 | add_timer(&task->timer); | ||
| 122 | |||
| 123 | res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); | ||
| 124 | if (res) { | ||
| 125 | del_timer(&task->timer); | ||
| 126 | SAS_DPRINTK("executing SAS discovery task failed:%d\n", | ||
| 127 | res); | ||
| 128 | goto ex_err; | ||
| 129 | } | ||
| 130 | wait_for_completion(&task->completion); | ||
| 131 | res = -ETASK; | ||
| 132 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { | ||
| 133 | int res2; | ||
| 134 | SAS_DPRINTK("task aborted, flags:0x%x\n", | ||
| 135 | task->task_state_flags); | ||
| 136 | res2 = i->dft->lldd_abort_task(task); | ||
| 137 | SAS_DPRINTK("came back from abort task\n"); | ||
| 138 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | ||
| 139 | if (res2 == TMF_RESP_FUNC_COMPLETE) | ||
| 140 | continue; /* Retry the task */ | ||
| 141 | else | ||
| 142 | goto ex_err; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | if (task->task_status.stat == SAM_BUSY || | ||
| 146 | task->task_status.stat == SAM_TASK_SET_FULL || | ||
| 147 | task->task_status.stat == SAS_QUEUE_FULL) { | ||
| 148 | SAS_DPRINTK("task: q busy, sleeping...\n"); | ||
| 149 | schedule_timeout_interruptible(HZ); | ||
| 150 | } else if (task->task_status.stat == SAM_CHECK_COND) { | ||
| 151 | struct scsi_sense_hdr shdr; | ||
| 152 | |||
| 153 | if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size, | ||
| 154 | &shdr)) { | ||
| 155 | SAS_DPRINTK("couldn't normalize sense\n"); | ||
| 156 | continue; | ||
| 157 | } | ||
| 158 | if ((shdr.sense_key == 6 && shdr.asc == 0x29) || | ||
| 159 | (shdr.sense_key == 2 && shdr.asc == 4 && | ||
| 160 | shdr.ascq == 1)) { | ||
| 161 | SAS_DPRINTK("device %016llx LUN: %016llx " | ||
| 162 | "powering up or not ready yet, " | ||
| 163 | "sleeping...\n", | ||
| 164 | SAS_ADDR(task->dev->sas_addr), | ||
| 165 | SAS_ADDR(task->ssp_task.LUN)); | ||
| 166 | |||
| 167 | schedule_timeout_interruptible(5*HZ); | ||
| 168 | } else if (shdr.sense_key == 1) { | ||
| 169 | res = 0; | ||
| 170 | break; | ||
| 171 | } else if (shdr.sense_key == 5) { | ||
| 172 | break; | ||
| 173 | } else { | ||
| 174 | SAS_DPRINTK("dev %016llx LUN: %016llx " | ||
| 175 | "sense key:0x%x ASC:0x%x ASCQ:0x%x" | ||
| 176 | "\n", | ||
| 177 | SAS_ADDR(task->dev->sas_addr), | ||
| 178 | SAS_ADDR(task->ssp_task.LUN), | ||
| 179 | shdr.sense_key, | ||
| 180 | shdr.asc, shdr.ascq); | ||
| 181 | } | ||
| 182 | } else if (task->task_status.resp != SAS_TASK_COMPLETE || | ||
| 183 | task->task_status.stat != SAM_GOOD) { | ||
| 184 | SAS_DPRINTK("task finished with resp:0x%x, " | ||
| 185 | "stat:0x%x\n", | ||
| 186 | task->task_status.resp, | ||
| 187 | task->task_status.stat); | ||
| 188 | goto ex_err; | ||
| 189 | } else { | ||
| 190 | res = 0; | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | ex_err: | ||
| 195 | if (pci_dma_dir != PCI_DMA_NONE) | ||
| 196 | kfree(scatter); | ||
| 197 | out: | ||
| 198 | return res; | ||
| 199 | } | ||
| 200 | |||
| 201 | /* ---------- Domain device discovery ---------- */ | 58 | /* ---------- Domain device discovery ---------- */ |
| 202 | 59 | ||
| 203 | /** | 60 | /** |
| @@ -255,6 +112,7 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 255 | 112 | ||
| 256 | switch (dev->dev_type) { | 113 | switch (dev->dev_type) { |
| 257 | case SAS_END_DEV: | 114 | case SAS_END_DEV: |
| 115 | case SATA_DEV: | ||
| 258 | rphy = sas_end_device_alloc(port->port); | 116 | rphy = sas_end_device_alloc(port->port); |
| 259 | break; | 117 | break; |
| 260 | case EDGE_DEV: | 118 | case EDGE_DEV: |
| @@ -265,7 +123,6 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 265 | rphy = sas_expander_alloc(port->port, | 123 | rphy = sas_expander_alloc(port->port, |
| 266 | SAS_FANOUT_EXPANDER_DEVICE); | 124 | SAS_FANOUT_EXPANDER_DEVICE); |
| 267 | break; | 125 | break; |
| 268 | case SATA_DEV: | ||
| 269 | default: | 126 | default: |
| 270 | printk("ERROR: Unidentified device type %d\n", dev->dev_type); | 127 | printk("ERROR: Unidentified device type %d\n", dev->dev_type); |
| 271 | rphy = NULL; | 128 | rphy = NULL; |
| @@ -292,207 +149,15 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 292 | port->disc.max_level = 0; | 149 | port->disc.max_level = 0; |
| 293 | 150 | ||
| 294 | dev->rphy = rphy; | 151 | dev->rphy = rphy; |
| 295 | spin_lock(&port->dev_list_lock); | 152 | spin_lock_irq(&port->dev_list_lock); |
| 296 | list_add_tail(&dev->dev_list_node, &port->dev_list); | 153 | list_add_tail(&dev->dev_list_node, &port->dev_list); |
| 297 | spin_unlock(&port->dev_list_lock); | 154 | spin_unlock_irq(&port->dev_list_lock); |
| 298 | 155 | ||
| 299 | return 0; | 156 | return 0; |
| 300 | } | 157 | } |
| 301 | 158 | ||
| 302 | /* ---------- Discover and Revalidate ---------- */ | 159 | /* ---------- Discover and Revalidate ---------- */ |
| 303 | 160 | ||
| 304 | /* ---------- SATA ---------- */ | ||
| 305 | |||
| 306 | static void sas_get_ata_command_set(struct domain_device *dev) | ||
| 307 | { | ||
| 308 | struct dev_to_host_fis *fis = | ||
| 309 | (struct dev_to_host_fis *) dev->frame_rcvd; | ||
| 310 | |||
| 311 | if ((fis->sector_count == 1 && /* ATA */ | ||
| 312 | fis->lbal == 1 && | ||
| 313 | fis->lbam == 0 && | ||
| 314 | fis->lbah == 0 && | ||
| 315 | fis->device == 0) | ||
| 316 | || | ||
| 317 | (fis->sector_count == 0 && /* CE-ATA (mATA) */ | ||
| 318 | fis->lbal == 0 && | ||
| 319 | fis->lbam == 0xCE && | ||
| 320 | fis->lbah == 0xAA && | ||
| 321 | (fis->device & ~0x10) == 0)) | ||
| 322 | |||
| 323 | dev->sata_dev.command_set = ATA_COMMAND_SET; | ||
| 324 | |||
| 325 | else if ((fis->interrupt_reason == 1 && /* ATAPI */ | ||
| 326 | fis->lbal == 1 && | ||
| 327 | fis->byte_count_low == 0x14 && | ||
| 328 | fis->byte_count_high == 0xEB && | ||
| 329 | (fis->device & ~0x10) == 0)) | ||
| 330 | |||
| 331 | dev->sata_dev.command_set = ATAPI_COMMAND_SET; | ||
| 332 | |||
| 333 | else if ((fis->sector_count == 1 && /* SEMB */ | ||
| 334 | fis->lbal == 1 && | ||
| 335 | fis->lbam == 0x3C && | ||
| 336 | fis->lbah == 0xC3 && | ||
| 337 | fis->device == 0) | ||
| 338 | || | ||
| 339 | (fis->interrupt_reason == 1 && /* SATA PM */ | ||
| 340 | fis->lbal == 1 && | ||
| 341 | fis->byte_count_low == 0x69 && | ||
| 342 | fis->byte_count_high == 0x96 && | ||
| 343 | (fis->device & ~0x10) == 0)) | ||
| 344 | |||
| 345 | /* Treat it as a superset? */ | ||
| 346 | dev->sata_dev.command_set = ATAPI_COMMAND_SET; | ||
| 347 | } | ||
| 348 | |||
| 349 | /** | ||
| 350 | * sas_issue_ata_cmd -- Basic SATA command processing for discovery | ||
| 351 | * @dev: the device to send the command to | ||
| 352 | * @command: the command register | ||
| 353 | * @features: the features register | ||
| 354 | * @buffer: pointer to buffer to do I/O | ||
| 355 | * @size: size of @buffer | ||
| 356 | * @pci_dma_dir: PCI_DMA_... | ||
| 357 | */ | ||
| 358 | static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, | ||
| 359 | u8 features, void *buffer, int size, | ||
| 360 | int pci_dma_dir) | ||
| 361 | { | ||
| 362 | int res = 0; | ||
| 363 | struct sas_task *task; | ||
| 364 | struct dev_to_host_fis *d2h_fis = (struct dev_to_host_fis *) | ||
| 365 | &dev->frame_rcvd[0]; | ||
| 366 | |||
| 367 | res = -ENOMEM; | ||
| 368 | task = sas_alloc_task(GFP_KERNEL); | ||
| 369 | if (!task) | ||
| 370 | goto out; | ||
| 371 | |||
| 372 | task->dev = dev; | ||
| 373 | |||
| 374 | task->ata_task.fis.command = command; | ||
| 375 | task->ata_task.fis.features = features; | ||
| 376 | task->ata_task.fis.device = d2h_fis->device; | ||
| 377 | task->ata_task.retry_count = 1; | ||
| 378 | |||
| 379 | res = sas_execute_task(task, buffer, size, pci_dma_dir); | ||
| 380 | |||
| 381 | sas_free_task(task); | ||
| 382 | out: | ||
| 383 | return res; | ||
| 384 | } | ||
| 385 | |||
| 386 | static void sas_sata_propagate_sas_addr(struct domain_device *dev) | ||
| 387 | { | ||
| 388 | unsigned long flags; | ||
| 389 | struct asd_sas_port *port = dev->port; | ||
| 390 | struct asd_sas_phy *phy; | ||
| 391 | |||
| 392 | BUG_ON(dev->parent); | ||
| 393 | |||
| 394 | memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | ||
| 395 | spin_lock_irqsave(&port->phy_list_lock, flags); | ||
| 396 | list_for_each_entry(phy, &port->phy_list, port_phy_el) | ||
| 397 | memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | ||
| 398 | spin_unlock_irqrestore(&port->phy_list_lock, flags); | ||
| 399 | } | ||
| 400 | |||
| 401 | #define ATA_IDENTIFY_DEV 0xEC | ||
| 402 | #define ATA_IDENTIFY_PACKET_DEV 0xA1 | ||
| 403 | #define ATA_SET_FEATURES 0xEF | ||
| 404 | #define ATA_FEATURE_PUP_STBY_SPIN_UP 0x07 | ||
| 405 | |||
| 406 | /** | ||
| 407 | * sas_discover_sata_dev -- discover a STP/SATA device (SATA_DEV) | ||
| 408 | * @dev: STP/SATA device of interest (ATA/ATAPI) | ||
| 409 | * | ||
| 410 | * The LLDD has already been notified of this device, so that we can | ||
| 411 | * send FISes to it. Here we try to get IDENTIFY DEVICE or IDENTIFY | ||
| 412 | * PACKET DEVICE, if ATAPI device, so that the LLDD can fine-tune its | ||
| 413 | * performance for this device. | ||
| 414 | */ | ||
| 415 | static int sas_discover_sata_dev(struct domain_device *dev) | ||
| 416 | { | ||
| 417 | int res; | ||
| 418 | __le16 *identify_x; | ||
| 419 | u8 command; | ||
| 420 | |||
| 421 | identify_x = kzalloc(512, GFP_KERNEL); | ||
| 422 | if (!identify_x) | ||
| 423 | return -ENOMEM; | ||
| 424 | |||
| 425 | if (dev->sata_dev.command_set == ATA_COMMAND_SET) { | ||
| 426 | dev->sata_dev.identify_device = identify_x; | ||
| 427 | command = ATA_IDENTIFY_DEV; | ||
| 428 | } else { | ||
| 429 | dev->sata_dev.identify_packet_device = identify_x; | ||
| 430 | command = ATA_IDENTIFY_PACKET_DEV; | ||
| 431 | } | ||
| 432 | |||
| 433 | res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, | ||
| 434 | PCI_DMA_FROMDEVICE); | ||
| 435 | if (res) | ||
| 436 | goto out_err; | ||
| 437 | |||
| 438 | /* lives on the media? */ | ||
| 439 | if (le16_to_cpu(identify_x[0]) & 4) { | ||
| 440 | /* incomplete response */ | ||
| 441 | SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to " | ||
| 442 | "dev %llx\n", SAS_ADDR(dev->sas_addr)); | ||
| 443 | if (!le16_to_cpu(identify_x[83] & (1<<6))) | ||
| 444 | goto cont1; | ||
| 445 | res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES, | ||
| 446 | ATA_FEATURE_PUP_STBY_SPIN_UP, | ||
| 447 | NULL, 0, PCI_DMA_NONE); | ||
| 448 | if (res) | ||
| 449 | goto cont1; | ||
| 450 | |||
| 451 | schedule_timeout_interruptible(5*HZ); /* More time? */ | ||
| 452 | res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, | ||
| 453 | PCI_DMA_FROMDEVICE); | ||
| 454 | if (res) | ||
| 455 | goto out_err; | ||
| 456 | } | ||
| 457 | cont1: | ||
| 458 | /* Get WWN */ | ||
| 459 | if (dev->port->oob_mode != SATA_OOB_MODE) { | ||
| 460 | memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, | ||
| 461 | SAS_ADDR_SIZE); | ||
| 462 | } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && | ||
| 463 | (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) | ||
| 464 | == 0x5000) { | ||
| 465 | int i; | ||
| 466 | |||
| 467 | for (i = 0; i < 4; i++) { | ||
| 468 | dev->sas_addr[2*i] = | ||
| 469 | (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; | ||
| 470 | dev->sas_addr[2*i+1] = | ||
| 471 | le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); | ||
| 475 | if (!dev->parent) | ||
| 476 | sas_sata_propagate_sas_addr(dev); | ||
| 477 | |||
| 478 | /* XXX Hint: register this SATA device with SATL. | ||
| 479 | When this returns, dev->sata_dev->lu is alive and | ||
| 480 | present. | ||
| 481 | sas_satl_register_dev(dev); | ||
| 482 | */ | ||
| 483 | return 0; | ||
| 484 | out_err: | ||
| 485 | dev->sata_dev.identify_packet_device = NULL; | ||
| 486 | dev->sata_dev.identify_device = NULL; | ||
| 487 | kfree(identify_x); | ||
| 488 | return res; | ||
| 489 | } | ||
| 490 | |||
| 491 | static int sas_discover_sata_pm(struct domain_device *dev) | ||
| 492 | { | ||
| 493 | return -ENODEV; | ||
| 494 | } | ||
| 495 | |||
| 496 | int sas_notify_lldd_dev_found(struct domain_device *dev) | 161 | int sas_notify_lldd_dev_found(struct domain_device *dev) |
| 497 | { | 162 | { |
| 498 | int res = 0; | 163 | int res = 0; |
| @@ -525,60 +190,6 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev) | |||
| 525 | 190 | ||
| 526 | /* ---------- Common/dispatchers ---------- */ | 191 | /* ---------- Common/dispatchers ---------- */ |
| 527 | 192 | ||
| 528 | /** | ||
| 529 | * sas_discover_sata -- discover an STP/SATA domain device | ||
| 530 | * @dev: pointer to struct domain_device of interest | ||
| 531 | * | ||
| 532 | * First we notify the LLDD of this device, so we can send frames to | ||
| 533 | * it. Then depending on the type of device we call the appropriate | ||
| 534 | * discover functions. Once device discover is done, we notify the | ||
| 535 | * LLDD so that it can fine-tune its parameters for the device, by | ||
| 536 | * removing it and then adding it. That is, the second time around, | ||
| 537 | * the driver would have certain fields, that it is looking at, set. | ||
| 538 | * Finally we initialize the kobj so that the device can be added to | ||
| 539 | * the system at registration time. Devices directly attached to a HA | ||
| 540 | * port, have no parents. All other devices do, and should have their | ||
| 541 | * "parent" pointer set appropriately before calling this function. | ||
| 542 | */ | ||
| 543 | int sas_discover_sata(struct domain_device *dev) | ||
| 544 | { | ||
| 545 | int res; | ||
| 546 | |||
| 547 | sas_get_ata_command_set(dev); | ||
| 548 | |||
| 549 | res = sas_notify_lldd_dev_found(dev); | ||
| 550 | if (res) | ||
| 551 | goto out_err2; | ||
| 552 | |||
| 553 | switch (dev->dev_type) { | ||
| 554 | case SATA_DEV: | ||
| 555 | res = sas_discover_sata_dev(dev); | ||
| 556 | break; | ||
| 557 | case SATA_PM: | ||
| 558 | res = sas_discover_sata_pm(dev); | ||
| 559 | break; | ||
| 560 | default: | ||
| 561 | break; | ||
| 562 | } | ||
| 563 | if (res) | ||
| 564 | goto out_err; | ||
| 565 | |||
| 566 | sas_notify_lldd_dev_gone(dev); | ||
| 567 | res = sas_notify_lldd_dev_found(dev); | ||
| 568 | if (res) | ||
| 569 | goto out_err2; | ||
| 570 | |||
| 571 | res = sas_rphy_add(dev->rphy); | ||
| 572 | if (res) | ||
| 573 | goto out_err; | ||
| 574 | |||
| 575 | return res; | ||
| 576 | |||
| 577 | out_err: | ||
| 578 | sas_notify_lldd_dev_gone(dev); | ||
| 579 | out_err2: | ||
| 580 | return res; | ||
| 581 | } | ||
| 582 | 193 | ||
| 583 | /** | 194 | /** |
| 584 | * sas_discover_end_dev -- discover an end device (SSP, etc) | 195 | * sas_discover_end_dev -- discover an end device (SSP, etc) |
| @@ -685,11 +296,14 @@ static void sas_discover_domain(struct work_struct *work) | |||
| 685 | case FANOUT_DEV: | 296 | case FANOUT_DEV: |
| 686 | error = sas_discover_root_expander(dev); | 297 | error = sas_discover_root_expander(dev); |
| 687 | break; | 298 | break; |
| 299 | #ifdef CONFIG_SCSI_SAS_ATA | ||
| 688 | case SATA_DEV: | 300 | case SATA_DEV: |
| 689 | case SATA_PM: | 301 | case SATA_PM: |
| 690 | error = sas_discover_sata(dev); | 302 | error = sas_discover_sata(dev); |
| 691 | break; | 303 | break; |
| 304 | #endif | ||
| 692 | default: | 305 | default: |
| 306 | error = -ENXIO; | ||
| 693 | SAS_DPRINTK("unhandled device %d\n", dev->dev_type); | 307 | SAS_DPRINTK("unhandled device %d\n", dev->dev_type); |
| 694 | break; | 308 | break; |
| 695 | } | 309 | } |
| @@ -698,9 +312,9 @@ static void sas_discover_domain(struct work_struct *work) | |||
| 698 | sas_rphy_free(dev->rphy); | 312 | sas_rphy_free(dev->rphy); |
| 699 | dev->rphy = NULL; | 313 | dev->rphy = NULL; |
| 700 | 314 | ||
| 701 | spin_lock(&port->dev_list_lock); | 315 | spin_lock_irq(&port->dev_list_lock); |
| 702 | list_del_init(&dev->dev_list_node); | 316 | list_del_init(&dev->dev_list_node); |
| 703 | spin_unlock(&port->dev_list_lock); | 317 | spin_unlock_irq(&port->dev_list_lock); |
| 704 | 318 | ||
| 705 | kfree(dev); /* not kobject_register-ed yet */ | 319 | kfree(dev); /* not kobject_register-ed yet */ |
| 706 | port->port_dev = NULL; | 320 | port->port_dev = NULL; |
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 23e90c5f8f35..b500f0c1449c 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | #include <linux/scatterlist.h> | 25 | #include <linux/scatterlist.h> |
| 26 | #include <linux/blkdev.h> | ||
| 26 | 27 | ||
| 27 | #include "sas_internal.h" | 28 | #include "sas_internal.h" |
| 28 | 29 | ||
| @@ -36,14 +37,6 @@ static int sas_configure_phy(struct domain_device *dev, int phy_id, | |||
| 36 | u8 *sas_addr, int include); | 37 | u8 *sas_addr, int include); |
| 37 | static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); | 38 | static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); |
| 38 | 39 | ||
| 39 | #if 0 | ||
| 40 | /* FIXME: smp needs to migrate into the sas class */ | ||
| 41 | static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *, | ||
| 42 | char *, loff_t, size_t); | ||
| 43 | static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *, | ||
| 44 | char *, loff_t, size_t); | ||
| 45 | #endif | ||
| 46 | |||
| 47 | /* ---------- SMP task management ---------- */ | 40 | /* ---------- SMP task management ---------- */ |
| 48 | 41 | ||
| 49 | static void smp_task_timedout(unsigned long _task) | 42 | static void smp_task_timedout(unsigned long _task) |
| @@ -220,6 +213,36 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, | |||
| 220 | #define DISCOVER_REQ_SIZE 16 | 213 | #define DISCOVER_REQ_SIZE 16 |
| 221 | #define DISCOVER_RESP_SIZE 56 | 214 | #define DISCOVER_RESP_SIZE 56 |
| 222 | 215 | ||
| 216 | static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req, | ||
| 217 | u8 *disc_resp, int single) | ||
| 218 | { | ||
| 219 | int i, res; | ||
| 220 | |||
| 221 | disc_req[9] = single; | ||
| 222 | for (i = 1 ; i < 3; i++) { | ||
| 223 | struct discover_resp *dr; | ||
| 224 | |||
| 225 | res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE, | ||
| 226 | disc_resp, DISCOVER_RESP_SIZE); | ||
| 227 | if (res) | ||
| 228 | return res; | ||
| 229 | /* This is detecting a failure to transmit inital | ||
| 230 | * dev to host FIS as described in section G.5 of | ||
| 231 | * sas-2 r 04b */ | ||
| 232 | dr = &((struct smp_resp *)disc_resp)->disc; | ||
| 233 | if (!(dr->attached_dev_type == 0 && | ||
| 234 | dr->attached_sata_dev)) | ||
| 235 | break; | ||
| 236 | /* In order to generate the dev to host FIS, we | ||
| 237 | * send a link reset to the expander port */ | ||
| 238 | sas_smp_phy_control(dev, single, PHY_FUNC_LINK_RESET, NULL); | ||
| 239 | /* Wait for the reset to trigger the negotiation */ | ||
| 240 | msleep(500); | ||
| 241 | } | ||
| 242 | sas_set_ex_phy(dev, single, disc_resp); | ||
| 243 | return 0; | ||
| 244 | } | ||
| 245 | |||
| 223 | static int sas_ex_phy_discover(struct domain_device *dev, int single) | 246 | static int sas_ex_phy_discover(struct domain_device *dev, int single) |
| 224 | { | 247 | { |
| 225 | struct expander_device *ex = &dev->ex_dev; | 248 | struct expander_device *ex = &dev->ex_dev; |
| @@ -240,23 +263,15 @@ static int sas_ex_phy_discover(struct domain_device *dev, int single) | |||
| 240 | disc_req[1] = SMP_DISCOVER; | 263 | disc_req[1] = SMP_DISCOVER; |
| 241 | 264 | ||
| 242 | if (0 <= single && single < ex->num_phys) { | 265 | if (0 <= single && single < ex->num_phys) { |
| 243 | disc_req[9] = single; | 266 | res = sas_ex_phy_discover_helper(dev, disc_req, disc_resp, single); |
| 244 | res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE, | ||
| 245 | disc_resp, DISCOVER_RESP_SIZE); | ||
| 246 | if (res) | ||
| 247 | goto out_err; | ||
| 248 | sas_set_ex_phy(dev, single, disc_resp); | ||
| 249 | } else { | 267 | } else { |
| 250 | int i; | 268 | int i; |
| 251 | 269 | ||
| 252 | for (i = 0; i < ex->num_phys; i++) { | 270 | for (i = 0; i < ex->num_phys; i++) { |
| 253 | disc_req[9] = i; | 271 | res = sas_ex_phy_discover_helper(dev, disc_req, |
| 254 | res = smp_execute_task(dev, disc_req, | 272 | disc_resp, i); |
| 255 | DISCOVER_REQ_SIZE, disc_resp, | ||
| 256 | DISCOVER_RESP_SIZE); | ||
| 257 | if (res) | 273 | if (res) |
| 258 | goto out_err; | 274 | goto out_err; |
| 259 | sas_set_ex_phy(dev, i, disc_resp); | ||
| 260 | } | 275 | } |
| 261 | } | 276 | } |
| 262 | out_err: | 277 | out_err: |
| @@ -520,6 +535,8 @@ int sas_smp_get_phy_events(struct sas_phy *phy) | |||
| 520 | 535 | ||
| 521 | } | 536 | } |
| 522 | 537 | ||
| 538 | #ifdef CONFIG_SCSI_SAS_ATA | ||
| 539 | |||
| 523 | #define RPS_REQ_SIZE 16 | 540 | #define RPS_REQ_SIZE 16 |
| 524 | #define RPS_RESP_SIZE 60 | 541 | #define RPS_RESP_SIZE 60 |
| 525 | 542 | ||
| @@ -529,6 +546,7 @@ static int sas_get_report_phy_sata(struct domain_device *dev, | |||
| 529 | { | 546 | { |
| 530 | int res; | 547 | int res; |
| 531 | u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE); | 548 | u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE); |
| 549 | u8 *resp = (u8 *)rps_resp; | ||
| 532 | 550 | ||
| 533 | if (!rps_req) | 551 | if (!rps_req) |
| 534 | return -ENOMEM; | 552 | return -ENOMEM; |
| @@ -539,9 +557,30 @@ static int sas_get_report_phy_sata(struct domain_device *dev, | |||
| 539 | res = smp_execute_task(dev, rps_req, RPS_REQ_SIZE, | 557 | res = smp_execute_task(dev, rps_req, RPS_REQ_SIZE, |
| 540 | rps_resp, RPS_RESP_SIZE); | 558 | rps_resp, RPS_RESP_SIZE); |
| 541 | 559 | ||
| 560 | /* 0x34 is the FIS type for the D2H fis. There's a potential | ||
| 561 | * standards cockup here. sas-2 explicitly specifies the FIS | ||
| 562 | * should be encoded so that FIS type is in resp[24]. | ||
| 563 | * However, some expanders endian reverse this. Undo the | ||
| 564 | * reversal here */ | ||
| 565 | if (!res && resp[27] == 0x34 && resp[24] != 0x34) { | ||
| 566 | int i; | ||
| 567 | |||
| 568 | for (i = 0; i < 5; i++) { | ||
| 569 | int j = 24 + (i*4); | ||
| 570 | u8 a, b; | ||
| 571 | a = resp[j + 0]; | ||
| 572 | b = resp[j + 1]; | ||
| 573 | resp[j + 0] = resp[j + 3]; | ||
| 574 | resp[j + 1] = resp[j + 2]; | ||
| 575 | resp[j + 2] = b; | ||
| 576 | resp[j + 3] = a; | ||
| 577 | } | ||
| 578 | } | ||
| 579 | |||
| 542 | kfree(rps_req); | 580 | kfree(rps_req); |
| 543 | return 0; | 581 | return res; |
| 544 | } | 582 | } |
| 583 | #endif | ||
| 545 | 584 | ||
| 546 | static void sas_ex_get_linkrate(struct domain_device *parent, | 585 | static void sas_ex_get_linkrate(struct domain_device *parent, |
| 547 | struct domain_device *child, | 586 | struct domain_device *child, |
| @@ -609,6 +648,7 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
| 609 | } | 648 | } |
| 610 | sas_ex_get_linkrate(parent, child, phy); | 649 | sas_ex_get_linkrate(parent, child, phy); |
| 611 | 650 | ||
| 651 | #ifdef CONFIG_SCSI_SAS_ATA | ||
| 612 | if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { | 652 | if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { |
| 613 | child->dev_type = SATA_DEV; | 653 | child->dev_type = SATA_DEV; |
| 614 | if (phy->attached_tproto & SAS_PROTO_STP) | 654 | if (phy->attached_tproto & SAS_PROTO_STP) |
| @@ -625,16 +665,30 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
| 625 | } | 665 | } |
| 626 | memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, | 666 | memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, |
| 627 | sizeof(struct dev_to_host_fis)); | 667 | sizeof(struct dev_to_host_fis)); |
| 668 | |||
| 669 | rphy = sas_end_device_alloc(phy->port); | ||
| 670 | if (unlikely(!rphy)) | ||
| 671 | goto out_free; | ||
| 672 | |||
| 628 | sas_init_dev(child); | 673 | sas_init_dev(child); |
| 674 | |||
| 675 | child->rphy = rphy; | ||
| 676 | |||
| 677 | spin_lock_irq(&parent->port->dev_list_lock); | ||
| 678 | list_add_tail(&child->dev_list_node, &parent->port->dev_list); | ||
| 679 | spin_unlock_irq(&parent->port->dev_list_lock); | ||
| 680 | |||
| 629 | res = sas_discover_sata(child); | 681 | res = sas_discover_sata(child); |
| 630 | if (res) { | 682 | if (res) { |
| 631 | SAS_DPRINTK("sas_discover_sata() for device %16llx at " | 683 | SAS_DPRINTK("sas_discover_sata() for device %16llx at " |
| 632 | "%016llx:0x%x returned 0x%x\n", | 684 | "%016llx:0x%x returned 0x%x\n", |
| 633 | SAS_ADDR(child->sas_addr), | 685 | SAS_ADDR(child->sas_addr), |
| 634 | SAS_ADDR(parent->sas_addr), phy_id, res); | 686 | SAS_ADDR(parent->sas_addr), phy_id, res); |
| 635 | goto out_free; | 687 | goto out_list_del; |
| 636 | } | 688 | } |
| 637 | } else if (phy->attached_tproto & SAS_PROTO_SSP) { | 689 | } else |
| 690 | #endif | ||
| 691 | if (phy->attached_tproto & SAS_PROTO_SSP) { | ||
| 638 | child->dev_type = SAS_END_DEV; | 692 | child->dev_type = SAS_END_DEV; |
| 639 | rphy = sas_end_device_alloc(phy->port); | 693 | rphy = sas_end_device_alloc(phy->port); |
| 640 | /* FIXME: error handling */ | 694 | /* FIXME: error handling */ |
| @@ -646,9 +700,9 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
| 646 | child->rphy = rphy; | 700 | child->rphy = rphy; |
| 647 | sas_fill_in_rphy(child, rphy); | 701 | sas_fill_in_rphy(child, rphy); |
| 648 | 702 | ||
| 649 | spin_lock(&parent->port->dev_list_lock); | 703 | spin_lock_irq(&parent->port->dev_list_lock); |
| 650 | list_add_tail(&child->dev_list_node, &parent->port->dev_list); | 704 | list_add_tail(&child->dev_list_node, &parent->port->dev_list); |
| 651 | spin_unlock(&parent->port->dev_list_lock); | 705 | spin_unlock_irq(&parent->port->dev_list_lock); |
| 652 | 706 | ||
| 653 | res = sas_discover_end_dev(child); | 707 | res = sas_discover_end_dev(child); |
| 654 | if (res) { | 708 | if (res) { |
| @@ -662,6 +716,7 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
| 662 | SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", | 716 | SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", |
| 663 | phy->attached_tproto, SAS_ADDR(parent->sas_addr), | 717 | phy->attached_tproto, SAS_ADDR(parent->sas_addr), |
| 664 | phy_id); | 718 | phy_id); |
| 719 | goto out_free; | ||
| 665 | } | 720 | } |
| 666 | 721 | ||
| 667 | list_add_tail(&child->siblings, &parent_ex->children); | 722 | list_add_tail(&child->siblings, &parent_ex->children); |
| @@ -761,9 +816,9 @@ static struct domain_device *sas_ex_discover_expander( | |||
| 761 | sas_fill_in_rphy(child, rphy); | 816 | sas_fill_in_rphy(child, rphy); |
| 762 | sas_rphy_add(rphy); | 817 | sas_rphy_add(rphy); |
| 763 | 818 | ||
| 764 | spin_lock(&parent->port->dev_list_lock); | 819 | spin_lock_irq(&parent->port->dev_list_lock); |
| 765 | list_add_tail(&child->dev_list_node, &parent->port->dev_list); | 820 | list_add_tail(&child->dev_list_node, &parent->port->dev_list); |
| 766 | spin_unlock(&parent->port->dev_list_lock); | 821 | spin_unlock_irq(&parent->port->dev_list_lock); |
| 767 | 822 | ||
| 768 | res = sas_discover_expander(child); | 823 | res = sas_discover_expander(child); |
| 769 | if (res) { | 824 | if (res) { |
| @@ -1359,30 +1414,6 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr) | |||
| 1359 | return 0; | 1414 | return 0; |
| 1360 | } | 1415 | } |
| 1361 | 1416 | ||
| 1362 | #if 0 | ||
| 1363 | #define SMP_BIN_ATTR_NAME "smp_portal" | ||
| 1364 | |||
| 1365 | static void sas_ex_smp_hook(struct domain_device *dev) | ||
| 1366 | { | ||
| 1367 | struct expander_device *ex_dev = &dev->ex_dev; | ||
| 1368 | struct bin_attribute *bin_attr = &ex_dev->smp_bin_attr; | ||
| 1369 | |||
| 1370 | memset(bin_attr, 0, sizeof(*bin_attr)); | ||
| 1371 | |||
| 1372 | bin_attr->attr.name = SMP_BIN_ATTR_NAME; | ||
| 1373 | bin_attr->attr.mode = 0600; | ||
| 1374 | |||
| 1375 | bin_attr->size = 0; | ||
| 1376 | bin_attr->private = NULL; | ||
| 1377 | bin_attr->read = smp_portal_read; | ||
| 1378 | bin_attr->write= smp_portal_write; | ||
| 1379 | bin_attr->mmap = NULL; | ||
| 1380 | |||
| 1381 | ex_dev->smp_portal_pid = -1; | ||
| 1382 | init_MUTEX(&ex_dev->smp_sema); | ||
| 1383 | } | ||
| 1384 | #endif | ||
| 1385 | |||
| 1386 | /** | 1417 | /** |
| 1387 | * sas_discover_expander -- expander discovery | 1418 | * sas_discover_expander -- expander discovery |
| 1388 | * @ex: pointer to expander domain device | 1419 | * @ex: pointer to expander domain device |
| @@ -1844,76 +1875,49 @@ out: | |||
| 1844 | return res; | 1875 | return res; |
| 1845 | } | 1876 | } |
| 1846 | 1877 | ||
| 1847 | #if 0 | 1878 | int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, |
| 1848 | /* ---------- SMP portal ---------- */ | 1879 | struct request *req) |
| 1849 | |||
| 1850 | static ssize_t smp_portal_write(struct kobject *kobj, | ||
| 1851 | struct bin_attribute *bin_attr, | ||
| 1852 | char *buf, loff_t offs, size_t size) | ||
| 1853 | { | 1880 | { |
| 1854 | struct domain_device *dev = to_dom_device(kobj); | 1881 | struct domain_device *dev; |
| 1855 | struct expander_device *ex = &dev->ex_dev; | 1882 | int ret, type = rphy->identify.device_type; |
| 1856 | 1883 | struct request *rsp = req->next_rq; | |
| 1857 | if (offs != 0) | ||
| 1858 | return -EFBIG; | ||
| 1859 | else if (size == 0) | ||
| 1860 | return 0; | ||
| 1861 | 1884 | ||
| 1862 | down_interruptible(&ex->smp_sema); | 1885 | if (!rsp) { |
| 1863 | if (ex->smp_req) | 1886 | printk("%s: space for a smp response is missing\n", |
| 1864 | kfree(ex->smp_req); | 1887 | __FUNCTION__); |
| 1865 | ex->smp_req = kzalloc(size, GFP_USER); | 1888 | return -EINVAL; |
| 1866 | if (!ex->smp_req) { | ||
| 1867 | up(&ex->smp_sema); | ||
| 1868 | return -ENOMEM; | ||
| 1869 | } | 1889 | } |
| 1870 | memcpy(ex->smp_req, buf, size); | ||
| 1871 | ex->smp_req_size = size; | ||
| 1872 | ex->smp_portal_pid = current->pid; | ||
| 1873 | up(&ex->smp_sema); | ||
| 1874 | 1890 | ||
| 1875 | return size; | 1891 | /* seems aic94xx doesn't support */ |
| 1876 | } | 1892 | if (!rphy) { |
| 1877 | 1893 | printk("%s: can we send a smp request to a host?\n", | |
| 1878 | static ssize_t smp_portal_read(struct kobject *kobj, | 1894 | __FUNCTION__); |
| 1879 | struct bin_attribute *bin_attr, | 1895 | return -EINVAL; |
| 1880 | char *buf, loff_t offs, size_t size) | 1896 | } |
| 1881 | { | ||
| 1882 | struct domain_device *dev = to_dom_device(kobj); | ||
| 1883 | struct expander_device *ex = &dev->ex_dev; | ||
| 1884 | u8 *smp_resp; | ||
| 1885 | int res = -EINVAL; | ||
| 1886 | |||
| 1887 | /* XXX: sysfs gives us an offset of 0x10 or 0x8 while in fact | ||
| 1888 | * it should be 0. | ||
| 1889 | */ | ||
| 1890 | 1897 | ||
| 1891 | down_interruptible(&ex->smp_sema); | 1898 | if (type != SAS_EDGE_EXPANDER_DEVICE && |
| 1892 | if (!ex->smp_req || ex->smp_portal_pid != current->pid) | 1899 | type != SAS_FANOUT_EXPANDER_DEVICE) { |
| 1893 | goto out; | 1900 | printk("%s: can we send a smp request to a device?\n", |
| 1901 | __FUNCTION__); | ||
| 1902 | return -EINVAL; | ||
| 1903 | } | ||
| 1894 | 1904 | ||
| 1895 | res = 0; | 1905 | dev = sas_find_dev_by_rphy(rphy); |
| 1896 | if (size == 0) | 1906 | if (!dev) { |
| 1897 | goto out; | 1907 | printk("%s: fail to find a domain_device?\n", __FUNCTION__); |
| 1908 | return -EINVAL; | ||
| 1909 | } | ||
| 1898 | 1910 | ||
| 1899 | res = -ENOMEM; | 1911 | /* do we need to support multiple segments? */ |
| 1900 | smp_resp = alloc_smp_resp(size); | 1912 | if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { |
| 1901 | if (!smp_resp) | 1913 | printk("%s: multiple segments req %u %u, rsp %u %u\n", |
| 1902 | goto out; | 1914 | __FUNCTION__, req->bio->bi_vcnt, req->data_len, |
| 1903 | res = smp_execute_task(dev, ex->smp_req, ex->smp_req_size, | 1915 | rsp->bio->bi_vcnt, rsp->data_len); |
| 1904 | smp_resp, size); | 1916 | return -EINVAL; |
| 1905 | if (!res) { | ||
| 1906 | memcpy(buf, smp_resp, size); | ||
| 1907 | res = size; | ||
| 1908 | } | 1917 | } |
| 1909 | 1918 | ||
| 1910 | kfree(smp_resp); | 1919 | ret = smp_execute_task(dev, bio_data(req->bio), req->data_len, |
| 1911 | out: | 1920 | bio_data(rsp->bio), rsp->data_len); |
| 1912 | kfree(ex->smp_req); | 1921 | |
| 1913 | ex->smp_req = NULL; | 1922 | return ret; |
| 1914 | ex->smp_req_size = 0; | ||
| 1915 | ex->smp_portal_pid = -1; | ||
| 1916 | up(&ex->smp_sema); | ||
| 1917 | return res; | ||
| 1918 | } | 1923 | } |
| 1919 | #endif | ||
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 1396c83b0c9c..9cd5abe9e714 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c | |||
| @@ -259,6 +259,7 @@ static struct sas_function_template sft = { | |||
| 259 | .phy_reset = sas_phy_reset, | 259 | .phy_reset = sas_phy_reset, |
| 260 | .set_phy_speed = sas_set_phy_speed, | 260 | .set_phy_speed = sas_set_phy_speed, |
| 261 | .get_linkerrors = sas_get_linkerrors, | 261 | .get_linkerrors = sas_get_linkerrors, |
| 262 | .smp_handler = sas_smp_handler, | ||
| 262 | }; | 263 | }; |
| 263 | 264 | ||
| 264 | struct scsi_transport_template * | 265 | struct scsi_transport_template * |
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index a78638df2018..2b8213b1832d 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h | |||
| @@ -39,6 +39,9 @@ | |||
| 39 | #define SAS_DPRINTK(fmt, ...) | 39 | #define SAS_DPRINTK(fmt, ...) |
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | #define TO_SAS_TASK(_scsi_cmd) ((void *)(_scsi_cmd)->host_scribble) | ||
| 43 | #define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0) | ||
| 44 | |||
| 42 | void sas_scsi_recover_host(struct Scsi_Host *shost); | 45 | void sas_scsi_recover_host(struct Scsi_Host *shost); |
| 43 | 46 | ||
| 44 | int sas_show_class(enum sas_class class, char *buf); | 47 | int sas_show_class(enum sas_class class, char *buf); |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 9c5342e7a69c..7663841eb4cf 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <scsi/scsi_eh.h> | 34 | #include <scsi/scsi_eh.h> |
| 35 | #include <scsi/scsi_transport.h> | 35 | #include <scsi/scsi_transport.h> |
| 36 | #include <scsi/scsi_transport_sas.h> | 36 | #include <scsi/scsi_transport_sas.h> |
| 37 | #include <scsi/sas_ata.h> | ||
| 37 | #include "../scsi_sas_internal.h" | 38 | #include "../scsi_sas_internal.h" |
| 38 | #include "../scsi_transport_api.h" | 39 | #include "../scsi_transport_api.h" |
| 39 | #include "../scsi_priv.h" | 40 | #include "../scsi_priv.h" |
| @@ -42,12 +43,10 @@ | |||
| 42 | #include <linux/blkdev.h> | 43 | #include <linux/blkdev.h> |
| 43 | #include <linux/freezer.h> | 44 | #include <linux/freezer.h> |
| 44 | #include <linux/scatterlist.h> | 45 | #include <linux/scatterlist.h> |
| 46 | #include <linux/libata.h> | ||
| 45 | 47 | ||
| 46 | /* ---------- SCSI Host glue ---------- */ | 48 | /* ---------- SCSI Host glue ---------- */ |
| 47 | 49 | ||
| 48 | #define TO_SAS_TASK(_scsi_cmd) ((void *)(_scsi_cmd)->host_scribble) | ||
| 49 | #define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0) | ||
| 50 | |||
| 51 | static void sas_scsi_task_done(struct sas_task *task) | 50 | static void sas_scsi_task_done(struct sas_task *task) |
| 52 | { | 51 | { |
| 53 | struct task_status_struct *ts = &task->task_status; | 52 | struct task_status_struct *ts = &task->task_status; |
| @@ -172,7 +171,7 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd, | |||
| 172 | return task; | 171 | return task; |
| 173 | } | 172 | } |
| 174 | 173 | ||
| 175 | static int sas_queue_up(struct sas_task *task) | 174 | int sas_queue_up(struct sas_task *task) |
| 176 | { | 175 | { |
| 177 | struct sas_ha_struct *sas_ha = task->dev->port->ha; | 176 | struct sas_ha_struct *sas_ha = task->dev->port->ha; |
| 178 | struct scsi_core *core = &sas_ha->core; | 177 | struct scsi_core *core = &sas_ha->core; |
| @@ -213,6 +212,16 @@ int sas_queuecommand(struct scsi_cmnd *cmd, | |||
| 213 | struct sas_ha_struct *sas_ha = dev->port->ha; | 212 | struct sas_ha_struct *sas_ha = dev->port->ha; |
| 214 | struct sas_task *task; | 213 | struct sas_task *task; |
| 215 | 214 | ||
| 215 | if (dev_is_sata(dev)) { | ||
| 216 | unsigned long flags; | ||
| 217 | |||
| 218 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); | ||
| 219 | res = ata_sas_queuecmd(cmd, scsi_done, | ||
| 220 | dev->sata_dev.ap); | ||
| 221 | spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags); | ||
| 222 | goto out; | ||
| 223 | } | ||
| 224 | |||
| 216 | res = -ENOMEM; | 225 | res = -ENOMEM; |
| 217 | task = sas_create_task(cmd, dev, GFP_ATOMIC); | 226 | task = sas_create_task(cmd, dev, GFP_ATOMIC); |
| 218 | if (!task) | 227 | if (!task) |
| @@ -684,6 +693,16 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) | |||
| 684 | return EH_NOT_HANDLED; | 693 | return EH_NOT_HANDLED; |
| 685 | } | 694 | } |
| 686 | 695 | ||
| 696 | int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | ||
| 697 | { | ||
| 698 | struct domain_device *dev = sdev_to_domain_dev(sdev); | ||
| 699 | |||
| 700 | if (dev_is_sata(dev)) | ||
| 701 | return ata_scsi_ioctl(sdev, cmd, arg); | ||
| 702 | |||
| 703 | return -EINVAL; | ||
| 704 | } | ||
| 705 | |||
| 687 | struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy) | 706 | struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy) |
| 688 | { | 707 | { |
| 689 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent); | 708 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent); |
| @@ -723,10 +742,17 @@ static inline struct domain_device *sas_find_target(struct scsi_target *starget) | |||
| 723 | int sas_target_alloc(struct scsi_target *starget) | 742 | int sas_target_alloc(struct scsi_target *starget) |
| 724 | { | 743 | { |
| 725 | struct domain_device *found_dev = sas_find_target(starget); | 744 | struct domain_device *found_dev = sas_find_target(starget); |
| 745 | int res; | ||
| 726 | 746 | ||
| 727 | if (!found_dev) | 747 | if (!found_dev) |
| 728 | return -ENODEV; | 748 | return -ENODEV; |
| 729 | 749 | ||
| 750 | if (dev_is_sata(found_dev)) { | ||
| 751 | res = sas_ata_init_host_and_port(found_dev, starget); | ||
| 752 | if (res) | ||
| 753 | return res; | ||
| 754 | } | ||
| 755 | |||
| 730 | starget->hostdata = found_dev; | 756 | starget->hostdata = found_dev; |
| 731 | return 0; | 757 | return 0; |
| 732 | } | 758 | } |
| @@ -741,6 +767,11 @@ int sas_slave_configure(struct scsi_device *scsi_dev) | |||
| 741 | 767 | ||
| 742 | BUG_ON(dev->rphy->identify.device_type != SAS_END_DEVICE); | 768 | BUG_ON(dev->rphy->identify.device_type != SAS_END_DEVICE); |
| 743 | 769 | ||
| 770 | if (dev_is_sata(dev)) { | ||
| 771 | ata_sas_slave_configure(scsi_dev, dev->sata_dev.ap); | ||
| 772 | return 0; | ||
| 773 | } | ||
| 774 | |||
| 744 | sas_ha = dev->port->ha; | 775 | sas_ha = dev->port->ha; |
| 745 | 776 | ||
| 746 | sas_read_port_mode_page(scsi_dev); | 777 | sas_read_port_mode_page(scsi_dev); |
| @@ -764,6 +795,10 @@ int sas_slave_configure(struct scsi_device *scsi_dev) | |||
| 764 | 795 | ||
| 765 | void sas_slave_destroy(struct scsi_device *scsi_dev) | 796 | void sas_slave_destroy(struct scsi_device *scsi_dev) |
| 766 | { | 797 | { |
| 798 | struct domain_device *dev = sdev_to_domain_dev(scsi_dev); | ||
| 799 | |||
| 800 | if (dev_is_sata(dev)) | ||
| 801 | ata_port_disable(dev->sata_dev.ap); | ||
| 767 | } | 802 | } |
| 768 | 803 | ||
| 769 | int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth) | 804 | int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth) |
| @@ -980,10 +1015,38 @@ void sas_task_abort(struct sas_task *task) | |||
| 980 | return; | 1015 | return; |
| 981 | } | 1016 | } |
| 982 | 1017 | ||
| 1018 | if (dev_is_sata(task->dev)) { | ||
| 1019 | sas_ata_task_abort(task); | ||
| 1020 | return; | ||
| 1021 | } | ||
| 1022 | |||
| 983 | scsi_req_abort_cmd(sc); | 1023 | scsi_req_abort_cmd(sc); |
| 984 | scsi_schedule_eh(sc->device->host); | 1024 | scsi_schedule_eh(sc->device->host); |
| 985 | } | 1025 | } |
| 986 | 1026 | ||
| 1027 | int sas_slave_alloc(struct scsi_device *scsi_dev) | ||
| 1028 | { | ||
| 1029 | struct domain_device *dev = sdev_to_domain_dev(scsi_dev); | ||
| 1030 | |||
| 1031 | if (dev_is_sata(dev)) | ||
| 1032 | return ata_sas_port_init(dev->sata_dev.ap); | ||
| 1033 | |||
| 1034 | return 0; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | void sas_target_destroy(struct scsi_target *starget) | ||
| 1038 | { | ||
| 1039 | struct domain_device *found_dev = sas_find_target(starget); | ||
| 1040 | |||
| 1041 | if (!found_dev) | ||
| 1042 | return; | ||
| 1043 | |||
| 1044 | if (dev_is_sata(found_dev)) | ||
| 1045 | ata_sas_port_destroy(found_dev->sata_dev.ap); | ||
| 1046 | |||
| 1047 | return; | ||
| 1048 | } | ||
| 1049 | |||
| 987 | EXPORT_SYMBOL_GPL(sas_queuecommand); | 1050 | EXPORT_SYMBOL_GPL(sas_queuecommand); |
| 988 | EXPORT_SYMBOL_GPL(sas_target_alloc); | 1051 | EXPORT_SYMBOL_GPL(sas_target_alloc); |
| 989 | EXPORT_SYMBOL_GPL(sas_slave_configure); | 1052 | EXPORT_SYMBOL_GPL(sas_slave_configure); |
| @@ -997,3 +1060,6 @@ EXPORT_SYMBOL_GPL(sas_phy_reset); | |||
| 997 | EXPORT_SYMBOL_GPL(sas_phy_enable); | 1060 | EXPORT_SYMBOL_GPL(sas_phy_enable); |
| 998 | EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); | 1061 | EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); |
| 999 | EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); | 1062 | EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); |
| 1063 | EXPORT_SYMBOL_GPL(sas_slave_alloc); | ||
| 1064 | EXPORT_SYMBOL_GPL(sas_target_destroy); | ||
| 1065 | EXPORT_SYMBOL_GPL(sas_ioctl); | ||
diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c index d6ef22a941c4..1bdddad48571 100644 --- a/drivers/scsi/mvme16x_scsi.c +++ b/drivers/scsi/mvme16x_scsi.c | |||
| @@ -89,6 +89,7 @@ mvme16x_probe(struct device *dev) | |||
| 89 | out_be32(0xfff4202c, v); | 89 | out_be32(0xfff4202c, v); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | dev_set_drvdata(dev, host); | ||
| 92 | scsi_scan_host(host); | 93 | scsi_scan_host(host); |
| 93 | 94 | ||
| 94 | return 0; | 95 | return 0; |
| @@ -104,7 +105,7 @@ mvme16x_probe(struct device *dev) | |||
| 104 | static __devexit int | 105 | static __devexit int |
| 105 | mvme16x_device_remove(struct device *dev) | 106 | mvme16x_device_remove(struct device *dev) |
| 106 | { | 107 | { |
| 107 | struct Scsi_Host *host = dev_to_shost(dev); | 108 | struct Scsi_Host *host = dev_get_drvdata(dev); |
| 108 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); | 109 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); |
| 109 | 110 | ||
| 110 | /* Disable scsi chip ints */ | 111 | /* Disable scsi chip ints */ |
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index 7dd787f6ab27..fa481b515ead 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig | |||
| @@ -2,9 +2,12 @@ | |||
| 2 | # PCMCIA SCSI adapter configuration | 2 | # PCMCIA SCSI adapter configuration |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | menu "PCMCIA SCSI adapter support" | 5 | menuconfig SCSI_LOWLEVEL_PCMCIA |
| 6 | bool "PCMCIA SCSI adapter support" | ||
| 6 | depends on SCSI!=n && PCMCIA!=n | 7 | depends on SCSI!=n && PCMCIA!=n |
| 7 | 8 | ||
| 9 | if SCSI_LOWLEVEL_PCMCIA && SCSI && PCMCIA | ||
| 10 | |||
| 8 | config PCMCIA_AHA152X | 11 | config PCMCIA_AHA152X |
| 9 | tristate "Adaptec AHA152X PCMCIA support" | 12 | tristate "Adaptec AHA152X PCMCIA support" |
| 10 | depends on !64BIT | 13 | depends on !64BIT |
| @@ -77,4 +80,4 @@ config PCMCIA_SYM53C500 | |||
| 77 | To compile this driver as a module, choose M here: the | 80 | To compile this driver as a module, choose M here: the |
| 78 | module will be called sym53c500_cs. | 81 | module will be called sym53c500_cs. |
| 79 | 82 | ||
| 80 | endmenu | 83 | endif # SCSI_LOWLEVEL_PCMCIA |
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c new file mode 100644 index 000000000000..b50f1e14f2a5 --- /dev/null +++ b/drivers/scsi/ps3rom.c | |||
| @@ -0,0 +1,533 @@ | |||
| 1 | /* | ||
| 2 | * PS3 BD/DVD/CD-ROM Storage Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
| 5 | * Copyright 2007 Sony Corp. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published | ||
| 9 | * by the Free Software Foundation; version 2 of the License. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but | ||
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/cdrom.h> | ||
| 22 | #include <linux/highmem.h> | ||
| 23 | |||
| 24 | #include <scsi/scsi.h> | ||
| 25 | #include <scsi/scsi_cmnd.h> | ||
| 26 | #include <scsi/scsi_dbg.h> | ||
| 27 | #include <scsi/scsi_device.h> | ||
| 28 | #include <scsi/scsi_host.h> | ||
| 29 | |||
| 30 | #include <asm/lv1call.h> | ||
| 31 | #include <asm/ps3stor.h> | ||
| 32 | |||
| 33 | |||
| 34 | #define DEVICE_NAME "ps3rom" | ||
| 35 | |||
| 36 | #define BOUNCE_SIZE (64*1024) | ||
| 37 | |||
| 38 | #define PS3ROM_MAX_SECTORS (BOUNCE_SIZE / CD_FRAMESIZE) | ||
| 39 | |||
| 40 | |||
| 41 | struct ps3rom_private { | ||
| 42 | struct ps3_storage_device *dev; | ||
| 43 | struct scsi_cmnd *curr_cmd; | ||
| 44 | }; | ||
| 45 | |||
| 46 | |||
| 47 | #define LV1_STORAGE_SEND_ATAPI_COMMAND (1) | ||
| 48 | |||
| 49 | struct lv1_atapi_cmnd_block { | ||
| 50 | u8 pkt[32]; /* packet command block */ | ||
| 51 | u32 pktlen; /* should be 12 for ATAPI 8020 */ | ||
| 52 | u32 blocks; | ||
| 53 | u32 block_size; | ||
| 54 | u32 proto; /* transfer mode */ | ||
| 55 | u32 in_out; /* transfer direction */ | ||
| 56 | u64 buffer; /* parameter except command block */ | ||
| 57 | u32 arglen; /* length above */ | ||
| 58 | }; | ||
| 59 | |||
| 60 | enum lv1_atapi_proto { | ||
| 61 | NON_DATA_PROTO = 0, | ||
| 62 | PIO_DATA_IN_PROTO = 1, | ||
| 63 | PIO_DATA_OUT_PROTO = 2, | ||
| 64 | DMA_PROTO = 3 | ||
| 65 | }; | ||
| 66 | |||
| 67 | enum lv1_atapi_in_out { | ||
| 68 | DIR_WRITE = 0, /* memory -> device */ | ||
| 69 | DIR_READ = 1 /* device -> memory */ | ||
| 70 | }; | ||
| 71 | |||
| 72 | |||
| 73 | static int ps3rom_slave_configure(struct scsi_device *scsi_dev) | ||
| 74 | { | ||
| 75 | struct ps3rom_private *priv = shost_priv(scsi_dev->host); | ||
| 76 | struct ps3_storage_device *dev = priv->dev; | ||
| 77 | |||
| 78 | dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %u, channel %u\n", __func__, | ||
| 79 | __LINE__, scsi_dev->id, scsi_dev->lun, scsi_dev->channel); | ||
| 80 | |||
| 81 | /* | ||
| 82 | * ATAPI SFF8020 devices use MODE_SENSE_10, | ||
| 83 | * so we can prohibit MODE_SENSE_6 | ||
| 84 | */ | ||
| 85 | scsi_dev->use_10_for_ms = 1; | ||
| 86 | |||
| 87 | /* we don't support {READ,WRITE}_6 */ | ||
| 88 | scsi_dev->use_10_for_rw = 1; | ||
| 89 | |||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | /* | ||
| 94 | * copy data from device into scatter/gather buffer | ||
| 95 | */ | ||
| 96 | static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) | ||
| 97 | { | ||
| 98 | int k, req_len, act_len, len, active; | ||
| 99 | void *kaddr; | ||
| 100 | struct scatterlist *sgpnt; | ||
| 101 | unsigned int buflen; | ||
| 102 | |||
| 103 | buflen = cmd->request_bufflen; | ||
| 104 | if (!buflen) | ||
| 105 | return 0; | ||
| 106 | |||
| 107 | if (!cmd->request_buffer) | ||
| 108 | return -1; | ||
| 109 | |||
| 110 | sgpnt = cmd->request_buffer; | ||
| 111 | active = 1; | ||
| 112 | for (k = 0, req_len = 0, act_len = 0; k < cmd->use_sg; ++k, ++sgpnt) { | ||
| 113 | if (active) { | ||
| 114 | kaddr = kmap_atomic(sgpnt->page, KM_IRQ0); | ||
| 115 | len = sgpnt->length; | ||
| 116 | if ((req_len + len) > buflen) { | ||
| 117 | active = 0; | ||
| 118 | len = buflen - req_len; | ||
| 119 | } | ||
| 120 | memcpy(kaddr + sgpnt->offset, buf + req_len, len); | ||
| 121 | flush_kernel_dcache_page(sgpnt->page); | ||
| 122 | kunmap_atomic(kaddr, KM_IRQ0); | ||
| 123 | act_len += len; | ||
| 124 | } | ||
| 125 | req_len += sgpnt->length; | ||
| 126 | } | ||
| 127 | cmd->resid = req_len - act_len; | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* | ||
| 132 | * copy data from scatter/gather into device's buffer | ||
| 133 | */ | ||
| 134 | static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf) | ||
| 135 | { | ||
| 136 | int k, req_len, len, fin; | ||
| 137 | void *kaddr; | ||
| 138 | struct scatterlist *sgpnt; | ||
| 139 | unsigned int buflen; | ||
| 140 | |||
| 141 | buflen = cmd->request_bufflen; | ||
| 142 | if (!buflen) | ||
| 143 | return 0; | ||
| 144 | |||
| 145 | if (!cmd->request_buffer) | ||
| 146 | return -1; | ||
| 147 | |||
| 148 | sgpnt = cmd->request_buffer; | ||
| 149 | for (k = 0, req_len = 0, fin = 0; k < cmd->use_sg; ++k, ++sgpnt) { | ||
| 150 | kaddr = kmap_atomic(sgpnt->page, KM_IRQ0); | ||
| 151 | len = sgpnt->length; | ||
| 152 | if ((req_len + len) > buflen) { | ||
| 153 | len = buflen - req_len; | ||
| 154 | fin = 1; | ||
| 155 | } | ||
| 156 | memcpy(buf + req_len, kaddr + sgpnt->offset, len); | ||
| 157 | kunmap_atomic(kaddr, KM_IRQ0); | ||
| 158 | if (fin) | ||
| 159 | return req_len + len; | ||
| 160 | req_len += sgpnt->length; | ||
| 161 | } | ||
| 162 | return req_len; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int ps3rom_atapi_request(struct ps3_storage_device *dev, | ||
| 166 | struct scsi_cmnd *cmd) | ||
| 167 | { | ||
| 168 | struct lv1_atapi_cmnd_block atapi_cmnd; | ||
| 169 | unsigned char opcode = cmd->cmnd[0]; | ||
| 170 | int res; | ||
| 171 | u64 lpar; | ||
| 172 | |||
| 173 | dev_dbg(&dev->sbd.core, "%s:%u: send ATAPI command 0x%02x\n", __func__, | ||
| 174 | __LINE__, opcode); | ||
| 175 | |||
| 176 | memset(&atapi_cmnd, 0, sizeof(struct lv1_atapi_cmnd_block)); | ||
| 177 | memcpy(&atapi_cmnd.pkt, cmd->cmnd, 12); | ||
| 178 | atapi_cmnd.pktlen = 12; | ||
| 179 | atapi_cmnd.block_size = 1; /* transfer size is block_size * blocks */ | ||
| 180 | atapi_cmnd.blocks = atapi_cmnd.arglen = cmd->request_bufflen; | ||
| 181 | atapi_cmnd.buffer = dev->bounce_lpar; | ||
| 182 | |||
| 183 | switch (cmd->sc_data_direction) { | ||
| 184 | case DMA_FROM_DEVICE: | ||
| 185 | if (cmd->request_bufflen >= CD_FRAMESIZE) | ||
| 186 | atapi_cmnd.proto = DMA_PROTO; | ||
| 187 | else | ||
| 188 | atapi_cmnd.proto = PIO_DATA_IN_PROTO; | ||
| 189 | atapi_cmnd.in_out = DIR_READ; | ||
| 190 | break; | ||
| 191 | |||
| 192 | case DMA_TO_DEVICE: | ||
| 193 | if (cmd->request_bufflen >= CD_FRAMESIZE) | ||
| 194 | atapi_cmnd.proto = DMA_PROTO; | ||
| 195 | else | ||
| 196 | atapi_cmnd.proto = PIO_DATA_OUT_PROTO; | ||
| 197 | atapi_cmnd.in_out = DIR_WRITE; | ||
| 198 | res = fetch_to_dev_buffer(cmd, dev->bounce_buf); | ||
| 199 | if (res < 0) | ||
| 200 | return DID_ERROR << 16; | ||
| 201 | break; | ||
| 202 | |||
| 203 | default: | ||
| 204 | atapi_cmnd.proto = NON_DATA_PROTO; | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | |||
| 208 | lpar = ps3_mm_phys_to_lpar(__pa(&atapi_cmnd)); | ||
| 209 | res = lv1_storage_send_device_command(dev->sbd.dev_id, | ||
| 210 | LV1_STORAGE_SEND_ATAPI_COMMAND, | ||
| 211 | lpar, sizeof(atapi_cmnd), | ||
| 212 | atapi_cmnd.buffer, | ||
| 213 | atapi_cmnd.arglen, &dev->tag); | ||
| 214 | if (res == LV1_DENIED_BY_POLICY) { | ||
| 215 | dev_dbg(&dev->sbd.core, | ||
| 216 | "%s:%u: ATAPI command 0x%02x denied by policy\n", | ||
| 217 | __func__, __LINE__, opcode); | ||
| 218 | return DID_ERROR << 16; | ||
| 219 | } | ||
| 220 | |||
| 221 | if (res) { | ||
| 222 | dev_err(&dev->sbd.core, | ||
| 223 | "%s:%u: ATAPI command 0x%02x failed %d\n", __func__, | ||
| 224 | __LINE__, opcode, res); | ||
| 225 | return DID_ERROR << 16; | ||
| 226 | } | ||
| 227 | |||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | static inline unsigned int srb10_lba(const struct scsi_cmnd *cmd) | ||
| 232 | { | ||
| 233 | return cmd->cmnd[2] << 24 | cmd->cmnd[3] << 16 | cmd->cmnd[4] << 8 | | ||
| 234 | cmd->cmnd[5]; | ||
| 235 | } | ||
| 236 | |||
| 237 | static inline unsigned int srb10_len(const struct scsi_cmnd *cmd) | ||
| 238 | { | ||
| 239 | return cmd->cmnd[7] << 8 | cmd->cmnd[8]; | ||
| 240 | } | ||
| 241 | |||
| 242 | static int ps3rom_read_request(struct ps3_storage_device *dev, | ||
| 243 | struct scsi_cmnd *cmd, u32 start_sector, | ||
| 244 | u32 sectors) | ||
| 245 | { | ||
| 246 | int res; | ||
| 247 | |||
| 248 | dev_dbg(&dev->sbd.core, "%s:%u: read %u sectors starting at %u\n", | ||
| 249 | __func__, __LINE__, sectors, start_sector); | ||
| 250 | |||
| 251 | res = lv1_storage_read(dev->sbd.dev_id, | ||
| 252 | dev->regions[dev->region_idx].id, start_sector, | ||
| 253 | sectors, 0, dev->bounce_lpar, &dev->tag); | ||
| 254 | if (res) { | ||
| 255 | dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__, | ||
| 256 | __LINE__, res); | ||
| 257 | return DID_ERROR << 16; | ||
| 258 | } | ||
| 259 | |||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int ps3rom_write_request(struct ps3_storage_device *dev, | ||
| 264 | struct scsi_cmnd *cmd, u32 start_sector, | ||
| 265 | u32 sectors) | ||
| 266 | { | ||
| 267 | int res; | ||
| 268 | |||
| 269 | dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n", | ||
| 270 | __func__, __LINE__, sectors, start_sector); | ||
| 271 | |||
| 272 | res = fetch_to_dev_buffer(cmd, dev->bounce_buf); | ||
| 273 | if (res < 0) | ||
| 274 | return DID_ERROR << 16; | ||
| 275 | |||
| 276 | res = lv1_storage_write(dev->sbd.dev_id, | ||
| 277 | dev->regions[dev->region_idx].id, start_sector, | ||
| 278 | sectors, 0, dev->bounce_lpar, &dev->tag); | ||
| 279 | if (res) { | ||
| 280 | dev_err(&dev->sbd.core, "%s:%u: write failed %d\n", __func__, | ||
| 281 | __LINE__, res); | ||
| 282 | return DID_ERROR << 16; | ||
| 283 | } | ||
| 284 | |||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int ps3rom_queuecommand(struct scsi_cmnd *cmd, | ||
| 289 | void (*done)(struct scsi_cmnd *)) | ||
| 290 | { | ||
| 291 | struct ps3rom_private *priv = shost_priv(cmd->device->host); | ||
| 292 | struct ps3_storage_device *dev = priv->dev; | ||
| 293 | unsigned char opcode; | ||
| 294 | int res; | ||
| 295 | |||
| 296 | #ifdef DEBUG | ||
| 297 | scsi_print_command(cmd); | ||
| 298 | #endif | ||
| 299 | |||
| 300 | priv->curr_cmd = cmd; | ||
| 301 | cmd->scsi_done = done; | ||
| 302 | |||
| 303 | opcode = cmd->cmnd[0]; | ||
| 304 | /* | ||
| 305 | * While we can submit READ/WRITE SCSI commands as ATAPI commands, | ||
| 306 | * it's recommended for various reasons (performance, error handling, | ||
| 307 | * ...) to use lv1_storage_{read,write}() instead | ||
| 308 | */ | ||
| 309 | switch (opcode) { | ||
| 310 | case READ_10: | ||
| 311 | res = ps3rom_read_request(dev, cmd, srb10_lba(cmd), | ||
| 312 | srb10_len(cmd)); | ||
| 313 | break; | ||
| 314 | |||
| 315 | case WRITE_10: | ||
| 316 | res = ps3rom_write_request(dev, cmd, srb10_lba(cmd), | ||
| 317 | srb10_len(cmd)); | ||
| 318 | break; | ||
| 319 | |||
| 320 | default: | ||
| 321 | res = ps3rom_atapi_request(dev, cmd); | ||
| 322 | break; | ||
| 323 | } | ||
| 324 | |||
| 325 | if (res) { | ||
| 326 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | ||
| 327 | cmd->result = res; | ||
| 328 | cmd->sense_buffer[0] = 0x70; | ||
| 329 | cmd->sense_buffer[2] = ILLEGAL_REQUEST; | ||
| 330 | priv->curr_cmd = NULL; | ||
| 331 | cmd->scsi_done(cmd); | ||
| 332 | } | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | static int decode_lv1_status(u64 status, unsigned char *sense_key, | ||
| 338 | unsigned char *asc, unsigned char *ascq) | ||
| 339 | { | ||
| 340 | if (((status >> 24) & 0xff) != SAM_STAT_CHECK_CONDITION) | ||
| 341 | return -1; | ||
| 342 | |||
| 343 | *sense_key = (status >> 16) & 0xff; | ||
| 344 | *asc = (status >> 8) & 0xff; | ||
| 345 | *ascq = status & 0xff; | ||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | static irqreturn_t ps3rom_interrupt(int irq, void *data) | ||
| 350 | { | ||
| 351 | struct ps3_storage_device *dev = data; | ||
| 352 | struct Scsi_Host *host; | ||
| 353 | struct ps3rom_private *priv; | ||
| 354 | struct scsi_cmnd *cmd; | ||
| 355 | int res; | ||
| 356 | u64 tag, status; | ||
| 357 | unsigned char sense_key, asc, ascq; | ||
| 358 | |||
| 359 | res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status); | ||
| 360 | /* | ||
| 361 | * status = -1 may mean that ATAPI transport completed OK, but | ||
| 362 | * ATAPI command itself resulted CHECK CONDITION | ||
| 363 | * so, upper layer should issue REQUEST_SENSE to check the sense data | ||
| 364 | */ | ||
| 365 | |||
| 366 | if (tag != dev->tag) | ||
| 367 | dev_err(&dev->sbd.core, | ||
| 368 | "%s:%u: tag mismatch, got %lx, expected %lx\n", | ||
| 369 | __func__, __LINE__, tag, dev->tag); | ||
| 370 | |||
| 371 | if (res) { | ||
| 372 | dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n", | ||
| 373 | __func__, __LINE__, res, status); | ||
| 374 | return IRQ_HANDLED; | ||
| 375 | } | ||
| 376 | |||
| 377 | host = dev->sbd.core.driver_data; | ||
| 378 | priv = shost_priv(host); | ||
| 379 | cmd = priv->curr_cmd; | ||
| 380 | |||
| 381 | if (!status) { | ||
| 382 | /* OK, completed */ | ||
| 383 | if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
| 384 | res = fill_from_dev_buffer(cmd, dev->bounce_buf); | ||
| 385 | if (res) { | ||
| 386 | cmd->result = DID_ERROR << 16; | ||
| 387 | goto done; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | cmd->result = DID_OK << 16; | ||
| 391 | goto done; | ||
| 392 | } | ||
| 393 | |||
| 394 | if (cmd->cmnd[0] == REQUEST_SENSE) { | ||
| 395 | /* SCSI spec says request sense should never get error */ | ||
| 396 | dev_err(&dev->sbd.core, "%s:%u: end error without autosense\n", | ||
| 397 | __func__, __LINE__); | ||
| 398 | cmd->result = DID_ERROR << 16 | SAM_STAT_CHECK_CONDITION; | ||
| 399 | goto done; | ||
| 400 | } | ||
| 401 | |||
| 402 | if (decode_lv1_status(status, &sense_key, &asc, &ascq)) { | ||
| 403 | cmd->result = DID_ERROR << 16; | ||
| 404 | goto done; | ||
| 405 | } | ||
| 406 | |||
| 407 | cmd->sense_buffer[0] = 0x70; | ||
| 408 | cmd->sense_buffer[2] = sense_key; | ||
| 409 | cmd->sense_buffer[7] = 16 - 6; | ||
| 410 | cmd->sense_buffer[12] = asc; | ||
| 411 | cmd->sense_buffer[13] = ascq; | ||
| 412 | cmd->result = SAM_STAT_CHECK_CONDITION; | ||
| 413 | |||
| 414 | done: | ||
| 415 | priv->curr_cmd = NULL; | ||
| 416 | cmd->scsi_done(cmd); | ||
| 417 | return IRQ_HANDLED; | ||
| 418 | } | ||
| 419 | |||
| 420 | static struct scsi_host_template ps3rom_host_template = { | ||
| 421 | .name = DEVICE_NAME, | ||
| 422 | .slave_configure = ps3rom_slave_configure, | ||
| 423 | .queuecommand = ps3rom_queuecommand, | ||
| 424 | .can_queue = 1, | ||
| 425 | .this_id = 7, | ||
| 426 | .sg_tablesize = SG_ALL, | ||
| 427 | .cmd_per_lun = 1, | ||
| 428 | .emulated = 1, /* only sg driver uses this */ | ||
| 429 | .max_sectors = PS3ROM_MAX_SECTORS, | ||
| 430 | .use_clustering = ENABLE_CLUSTERING, | ||
| 431 | .module = THIS_MODULE, | ||
| 432 | }; | ||
| 433 | |||
| 434 | |||
| 435 | static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev) | ||
| 436 | { | ||
| 437 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); | ||
| 438 | int error; | ||
| 439 | struct Scsi_Host *host; | ||
| 440 | struct ps3rom_private *priv; | ||
| 441 | |||
| 442 | if (dev->blk_size != CD_FRAMESIZE) { | ||
| 443 | dev_err(&dev->sbd.core, | ||
| 444 | "%s:%u: cannot handle block size %lu\n", __func__, | ||
| 445 | __LINE__, dev->blk_size); | ||
| 446 | return -EINVAL; | ||
| 447 | } | ||
| 448 | |||
| 449 | dev->bounce_size = BOUNCE_SIZE; | ||
| 450 | dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA); | ||
| 451 | if (!dev->bounce_buf) | ||
| 452 | return -ENOMEM; | ||
| 453 | |||
| 454 | error = ps3stor_setup(dev, ps3rom_interrupt); | ||
| 455 | if (error) | ||
| 456 | goto fail_free_bounce; | ||
| 457 | |||
| 458 | host = scsi_host_alloc(&ps3rom_host_template, | ||
| 459 | sizeof(struct ps3rom_private)); | ||
| 460 | if (!host) { | ||
| 461 | dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed\n", | ||
| 462 | __func__, __LINE__); | ||
| 463 | goto fail_teardown; | ||
| 464 | } | ||
| 465 | |||
| 466 | priv = shost_priv(host); | ||
| 467 | dev->sbd.core.driver_data = host; | ||
| 468 | priv->dev = dev; | ||
| 469 | |||
| 470 | /* One device/LUN per SCSI bus */ | ||
| 471 | host->max_id = 1; | ||
| 472 | host->max_lun = 1; | ||
| 473 | |||
| 474 | error = scsi_add_host(host, &dev->sbd.core); | ||
| 475 | if (error) { | ||
| 476 | dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed %d\n", | ||
| 477 | __func__, __LINE__, error); | ||
| 478 | error = -ENODEV; | ||
| 479 | goto fail_host_put; | ||
| 480 | } | ||
| 481 | |||
| 482 | scsi_scan_host(host); | ||
| 483 | return 0; | ||
| 484 | |||
| 485 | fail_host_put: | ||
| 486 | scsi_host_put(host); | ||
| 487 | dev->sbd.core.driver_data = NULL; | ||
| 488 | fail_teardown: | ||
| 489 | ps3stor_teardown(dev); | ||
| 490 | fail_free_bounce: | ||
| 491 | kfree(dev->bounce_buf); | ||
| 492 | return error; | ||
| 493 | } | ||
| 494 | |||
| 495 | static int ps3rom_remove(struct ps3_system_bus_device *_dev) | ||
| 496 | { | ||
| 497 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); | ||
| 498 | struct Scsi_Host *host = dev->sbd.core.driver_data; | ||
| 499 | |||
| 500 | scsi_remove_host(host); | ||
| 501 | ps3stor_teardown(dev); | ||
| 502 | scsi_host_put(host); | ||
| 503 | dev->sbd.core.driver_data = NULL; | ||
| 504 | kfree(dev->bounce_buf); | ||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 508 | static struct ps3_system_bus_driver ps3rom = { | ||
| 509 | .match_id = PS3_MATCH_ID_STOR_ROM, | ||
| 510 | .core.name = DEVICE_NAME, | ||
| 511 | .core.owner = THIS_MODULE, | ||
| 512 | .probe = ps3rom_probe, | ||
| 513 | .remove = ps3rom_remove | ||
| 514 | }; | ||
| 515 | |||
| 516 | |||
| 517 | static int __init ps3rom_init(void) | ||
| 518 | { | ||
| 519 | return ps3_system_bus_driver_register(&ps3rom); | ||
| 520 | } | ||
| 521 | |||
| 522 | static void __exit ps3rom_exit(void) | ||
| 523 | { | ||
| 524 | ps3_system_bus_driver_unregister(&ps3rom); | ||
| 525 | } | ||
| 526 | |||
| 527 | module_init(ps3rom_init); | ||
| 528 | module_exit(ps3rom_exit); | ||
| 529 | |||
| 530 | MODULE_LICENSE("GPL"); | ||
| 531 | MODULE_DESCRIPTION("PS3 BD/DVD/CD-ROM Storage Driver"); | ||
| 532 | MODULE_AUTHOR("Sony Corporation"); | ||
| 533 | MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_ROM); | ||
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 3eb2208675ae..1612f9200a52 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
| @@ -98,7 +98,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, | |||
| 98 | 98 | ||
| 99 | /* Read NVRAM. */ | 99 | /* Read NVRAM. */ |
| 100 | spin_lock_irqsave(&ha->hardware_lock, flags); | 100 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 101 | ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->nvram_base, | 101 | ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->nvram_base, |
| 102 | ha->nvram_size); | 102 | ha->nvram_size); |
| 103 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 103 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 104 | 104 | ||
| @@ -119,7 +119,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, | |||
| 119 | return 0; | 119 | return 0; |
| 120 | 120 | ||
| 121 | /* Checksum NVRAM. */ | 121 | /* Checksum NVRAM. */ |
| 122 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 122 | if (IS_FWI2_CAPABLE(ha)) { |
| 123 | uint32_t *iter; | 123 | uint32_t *iter; |
| 124 | uint32_t chksum; | 124 | uint32_t chksum; |
| 125 | 125 | ||
| @@ -143,7 +143,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, | |||
| 143 | 143 | ||
| 144 | /* Write NVRAM. */ | 144 | /* Write NVRAM. */ |
| 145 | spin_lock_irqsave(&ha->hardware_lock, flags); | 145 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 146 | ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); | 146 | ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); |
| 147 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 147 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 148 | 148 | ||
| 149 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 149 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
| @@ -206,7 +206,7 @@ static struct bin_attribute sysfs_optrom_attr = { | |||
| 206 | .name = "optrom", | 206 | .name = "optrom", |
| 207 | .mode = S_IRUSR | S_IWUSR, | 207 | .mode = S_IRUSR | S_IWUSR, |
| 208 | }, | 208 | }, |
| 209 | .size = OPTROM_SIZE_24XX, | 209 | .size = 0, |
| 210 | .read = qla2x00_sysfs_read_optrom, | 210 | .read = qla2x00_sysfs_read_optrom, |
| 211 | .write = qla2x00_sysfs_write_optrom, | 211 | .write = qla2x00_sysfs_write_optrom, |
| 212 | }; | 212 | }; |
| @@ -252,7 +252,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | memset(ha->optrom_buffer, 0, ha->optrom_size); | 254 | memset(ha->optrom_buffer, 0, ha->optrom_size); |
| 255 | ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0, | 255 | ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0, |
| 256 | ha->optrom_size); | 256 | ha->optrom_size); |
| 257 | break; | 257 | break; |
| 258 | case 2: | 258 | case 2: |
| @@ -275,7 +275,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
| 275 | if (ha->optrom_state != QLA_SWRITING) | 275 | if (ha->optrom_state != QLA_SWRITING) |
| 276 | break; | 276 | break; |
| 277 | 277 | ||
| 278 | ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0, | 278 | ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0, |
| 279 | ha->optrom_size); | 279 | ha->optrom_size); |
| 280 | break; | 280 | break; |
| 281 | } | 281 | } |
| @@ -305,7 +305,8 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, | |||
| 305 | 305 | ||
| 306 | /* Read NVRAM. */ | 306 | /* Read NVRAM. */ |
| 307 | spin_lock_irqsave(&ha->hardware_lock, flags); | 307 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 308 | ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size); | 308 | ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->vpd_base, |
| 309 | ha->vpd_size); | ||
| 309 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 310 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 310 | 311 | ||
| 311 | return ha->vpd_size; | 312 | return ha->vpd_size; |
| @@ -325,7 +326,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, | |||
| 325 | 326 | ||
| 326 | /* Write NVRAM. */ | 327 | /* Write NVRAM. */ |
| 327 | spin_lock_irqsave(&ha->hardware_lock, flags); | 328 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 328 | ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); | 329 | ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); |
| 329 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 330 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 330 | 331 | ||
| 331 | return count; | 332 | return count; |
| @@ -410,7 +411,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) | |||
| 410 | int ret; | 411 | int ret; |
| 411 | 412 | ||
| 412 | for (iter = bin_file_entries; iter->name; iter++) { | 413 | for (iter = bin_file_entries; iter->name; iter++) { |
| 413 | if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) | 414 | if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) |
| 414 | continue; | 415 | continue; |
| 415 | 416 | ||
| 416 | ret = sysfs_create_bin_file(&host->shost_gendev.kobj, | 417 | ret = sysfs_create_bin_file(&host->shost_gendev.kobj, |
| @@ -429,7 +430,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) | |||
| 429 | struct sysfs_entry *iter; | 430 | struct sysfs_entry *iter; |
| 430 | 431 | ||
| 431 | for (iter = bin_file_entries; iter->name; iter++) { | 432 | for (iter = bin_file_entries; iter->name; iter++) { |
| 432 | if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) | 433 | if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) |
| 433 | continue; | 434 | continue; |
| 434 | 435 | ||
| 435 | sysfs_remove_bin_file(&host->shost_gendev.kobj, | 436 | sysfs_remove_bin_file(&host->shost_gendev.kobj, |
| @@ -437,7 +438,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) | |||
| 437 | } | 438 | } |
| 438 | 439 | ||
| 439 | if (ha->beacon_blink_led == 1) | 440 | if (ha->beacon_blink_led == 1) |
| 440 | ha->isp_ops.beacon_off(ha); | 441 | ha->isp_ops->beacon_off(ha); |
| 441 | } | 442 | } |
| 442 | 443 | ||
| 443 | /* Scsi_Host attributes. */ | 444 | /* Scsi_Host attributes. */ |
| @@ -455,7 +456,7 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf) | |||
| 455 | char fw_str[30]; | 456 | char fw_str[30]; |
| 456 | 457 | ||
| 457 | return snprintf(buf, PAGE_SIZE, "%s\n", | 458 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 458 | ha->isp_ops.fw_version_str(ha, fw_str)); | 459 | ha->isp_ops->fw_version_str(ha, fw_str)); |
| 459 | } | 460 | } |
| 460 | 461 | ||
| 461 | static ssize_t | 462 | static ssize_t |
| @@ -507,7 +508,7 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf) | |||
| 507 | char pci_info[30]; | 508 | char pci_info[30]; |
| 508 | 509 | ||
| 509 | return snprintf(buf, PAGE_SIZE, "%s\n", | 510 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 510 | ha->isp_ops.pci_info_str(ha, pci_info)); | 511 | ha->isp_ops->pci_info_str(ha, pci_info)); |
| 511 | } | 512 | } |
| 512 | 513 | ||
| 513 | static ssize_t | 514 | static ssize_t |
| @@ -652,9 +653,9 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf, | |||
| 652 | return -EINVAL; | 653 | return -EINVAL; |
| 653 | 654 | ||
| 654 | if (val) | 655 | if (val) |
| 655 | rval = ha->isp_ops.beacon_on(ha); | 656 | rval = ha->isp_ops->beacon_on(ha); |
| 656 | else | 657 | else |
| 657 | rval = ha->isp_ops.beacon_off(ha); | 658 | rval = ha->isp_ops->beacon_off(ha); |
| 658 | 659 | ||
| 659 | if (rval != QLA_SUCCESS) | 660 | if (rval != QLA_SUCCESS) |
| 660 | count = 0; | 661 | count = 0; |
| @@ -898,7 +899,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) | |||
| 898 | pfc_host_stat = &ha->fc_host_stat; | 899 | pfc_host_stat = &ha->fc_host_stat; |
| 899 | memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); | 900 | memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); |
| 900 | 901 | ||
| 901 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 902 | if (IS_FWI2_CAPABLE(ha)) { |
| 902 | rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, | 903 | rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, |
| 903 | sizeof(stat_buf) / 4, mb_stat); | 904 | sizeof(stat_buf) / 4, mb_stat); |
| 904 | } else if (atomic_read(&ha->loop_state) == LOOP_READY && | 905 | } else if (atomic_read(&ha->loop_state) == LOOP_READY && |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 996c47a63074..563d18f4ff50 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
| @@ -37,6 +37,121 @@ qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr) | |||
| 37 | return ptr + (ha->response_q_length * sizeof(response_t)); | 37 | return ptr + (ha->response_q_length * sizeof(response_t)); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | static int | ||
| 41 | qla2xxx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, | ||
| 42 | uint32_t cram_size, uint32_t *ext_mem, void **nxt) | ||
| 43 | { | ||
| 44 | int rval; | ||
| 45 | uint32_t cnt, stat, timer, risc_address, ext_mem_cnt; | ||
| 46 | uint16_t mb[4]; | ||
| 47 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
| 48 | |||
| 49 | rval = QLA_SUCCESS; | ||
| 50 | risc_address = ext_mem_cnt = 0; | ||
| 51 | memset(mb, 0, sizeof(mb)); | ||
| 52 | |||
| 53 | /* Code RAM. */ | ||
| 54 | risc_address = 0x20000; | ||
| 55 | WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED); | ||
| 56 | clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
| 57 | |||
| 58 | for (cnt = 0; cnt < cram_size / 4 && rval == QLA_SUCCESS; | ||
| 59 | cnt++, risc_address++) { | ||
| 60 | WRT_REG_WORD(®->mailbox1, LSW(risc_address)); | ||
| 61 | WRT_REG_WORD(®->mailbox8, MSW(risc_address)); | ||
| 62 | RD_REG_WORD(®->mailbox8); | ||
| 63 | WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); | ||
| 64 | |||
| 65 | for (timer = 6000000; timer; timer--) { | ||
| 66 | /* Check for pending interrupts. */ | ||
| 67 | stat = RD_REG_DWORD(®->host_status); | ||
| 68 | if (stat & HSRX_RISC_INT) { | ||
| 69 | stat &= 0xff; | ||
| 70 | |||
| 71 | if (stat == 0x1 || stat == 0x2 || | ||
| 72 | stat == 0x10 || stat == 0x11) { | ||
| 73 | set_bit(MBX_INTERRUPT, | ||
| 74 | &ha->mbx_cmd_flags); | ||
| 75 | |||
| 76 | mb[0] = RD_REG_WORD(®->mailbox0); | ||
| 77 | mb[2] = RD_REG_WORD(®->mailbox2); | ||
| 78 | mb[3] = RD_REG_WORD(®->mailbox3); | ||
| 79 | |||
| 80 | WRT_REG_DWORD(®->hccr, | ||
| 81 | HCCRX_CLR_RISC_INT); | ||
| 82 | RD_REG_DWORD(®->hccr); | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | |||
| 86 | /* Clear this intr; it wasn't a mailbox intr */ | ||
| 87 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | ||
| 88 | RD_REG_DWORD(®->hccr); | ||
| 89 | } | ||
| 90 | udelay(5); | ||
| 91 | } | ||
| 92 | |||
| 93 | if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { | ||
| 94 | rval = mb[0] & MBS_MASK; | ||
| 95 | code_ram[cnt] = htonl((mb[3] << 16) | mb[2]); | ||
| 96 | } else { | ||
| 97 | rval = QLA_FUNCTION_FAILED; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | if (rval == QLA_SUCCESS) { | ||
| 102 | /* External Memory. */ | ||
| 103 | risc_address = 0x100000; | ||
| 104 | ext_mem_cnt = ha->fw_memory_size - 0x100000 + 1; | ||
| 105 | WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED); | ||
| 106 | clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
| 107 | } | ||
| 108 | for (cnt = 0; cnt < ext_mem_cnt && rval == QLA_SUCCESS; | ||
| 109 | cnt++, risc_address++) { | ||
| 110 | WRT_REG_WORD(®->mailbox1, LSW(risc_address)); | ||
| 111 | WRT_REG_WORD(®->mailbox8, MSW(risc_address)); | ||
| 112 | RD_REG_WORD(®->mailbox8); | ||
| 113 | WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); | ||
| 114 | |||
| 115 | for (timer = 6000000; timer; timer--) { | ||
| 116 | /* Check for pending interrupts. */ | ||
| 117 | stat = RD_REG_DWORD(®->host_status); | ||
| 118 | if (stat & HSRX_RISC_INT) { | ||
| 119 | stat &= 0xff; | ||
| 120 | |||
| 121 | if (stat == 0x1 || stat == 0x2 || | ||
| 122 | stat == 0x10 || stat == 0x11) { | ||
| 123 | set_bit(MBX_INTERRUPT, | ||
| 124 | &ha->mbx_cmd_flags); | ||
| 125 | |||
| 126 | mb[0] = RD_REG_WORD(®->mailbox0); | ||
| 127 | mb[2] = RD_REG_WORD(®->mailbox2); | ||
| 128 | mb[3] = RD_REG_WORD(®->mailbox3); | ||
| 129 | |||
| 130 | WRT_REG_DWORD(®->hccr, | ||
| 131 | HCCRX_CLR_RISC_INT); | ||
| 132 | RD_REG_DWORD(®->hccr); | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | |||
| 136 | /* Clear this intr; it wasn't a mailbox intr */ | ||
| 137 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | ||
| 138 | RD_REG_DWORD(®->hccr); | ||
| 139 | } | ||
| 140 | udelay(5); | ||
| 141 | } | ||
| 142 | |||
| 143 | if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { | ||
| 144 | rval = mb[0] & MBS_MASK; | ||
| 145 | ext_mem[cnt] = htonl((mb[3] << 16) | mb[2]); | ||
| 146 | } else { | ||
| 147 | rval = QLA_FUNCTION_FAILED; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | *nxt = rval == QLA_SUCCESS ? &ext_mem[cnt]: NULL; | ||
| 152 | return rval; | ||
| 153 | } | ||
| 154 | |||
| 40 | /** | 155 | /** |
| 41 | * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. | 156 | * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. |
| 42 | * @ha: HA context | 157 | * @ha: HA context |
| @@ -633,11 +748,10 @@ void | |||
| 633 | qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | 748 | qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) |
| 634 | { | 749 | { |
| 635 | int rval; | 750 | int rval; |
| 636 | uint32_t cnt, timer; | 751 | uint32_t cnt; |
| 637 | uint32_t risc_address; | 752 | uint32_t risc_address; |
| 638 | uint16_t mb[4], wd; | 753 | uint16_t mb0, wd; |
| 639 | 754 | ||
| 640 | uint32_t stat; | ||
| 641 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 755 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
| 642 | uint32_t __iomem *dmp_reg; | 756 | uint32_t __iomem *dmp_reg; |
| 643 | uint32_t *iter_reg; | 757 | uint32_t *iter_reg; |
| @@ -645,10 +759,9 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
| 645 | unsigned long flags; | 759 | unsigned long flags; |
| 646 | struct qla24xx_fw_dump *fw; | 760 | struct qla24xx_fw_dump *fw; |
| 647 | uint32_t ext_mem_cnt; | 761 | uint32_t ext_mem_cnt; |
| 648 | void *eft; | 762 | void *nxt; |
| 649 | 763 | ||
| 650 | risc_address = ext_mem_cnt = 0; | 764 | risc_address = ext_mem_cnt = 0; |
| 651 | memset(mb, 0, sizeof(mb)); | ||
| 652 | flags = 0; | 765 | flags = 0; |
| 653 | 766 | ||
| 654 | if (!hardware_locked) | 767 | if (!hardware_locked) |
| @@ -701,250 +814,236 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
| 701 | /* Shadow registers. */ | 814 | /* Shadow registers. */ |
| 702 | WRT_REG_DWORD(®->iobase_addr, 0x0F70); | 815 | WRT_REG_DWORD(®->iobase_addr, 0x0F70); |
| 703 | RD_REG_DWORD(®->iobase_addr); | 816 | RD_REG_DWORD(®->iobase_addr); |
| 704 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | 817 | WRT_REG_DWORD(®->iobase_select, 0xB0000000); |
| 705 | WRT_REG_DWORD(dmp_reg, 0xB0000000); | 818 | fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); |
| 706 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | 819 | |
| 707 | fw->shadow_reg[0] = htonl(RD_REG_DWORD(dmp_reg)); | 820 | WRT_REG_DWORD(®->iobase_select, 0xB0100000); |
| 708 | 821 | fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); | |
| 709 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | 822 | |
| 710 | WRT_REG_DWORD(dmp_reg, 0xB0100000); | 823 | WRT_REG_DWORD(®->iobase_select, 0xB0200000); |
| 711 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | 824 | fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); |
| 712 | fw->shadow_reg[1] = htonl(RD_REG_DWORD(dmp_reg)); | 825 | |
| 713 | 826 | WRT_REG_DWORD(®->iobase_select, 0xB0300000); | |
| 714 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | 827 | fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); |
| 715 | WRT_REG_DWORD(dmp_reg, 0xB0200000); | 828 | |
| 716 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | 829 | WRT_REG_DWORD(®->iobase_select, 0xB0400000); |
| 717 | fw->shadow_reg[2] = htonl(RD_REG_DWORD(dmp_reg)); | 830 | fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); |
| 718 | 831 | ||
| 719 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | 832 | WRT_REG_DWORD(®->iobase_select, 0xB0500000); |
| 720 | WRT_REG_DWORD(dmp_reg, 0xB0300000); | 833 | fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); |
| 721 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | 834 | |
| 722 | fw->shadow_reg[3] = htonl(RD_REG_DWORD(dmp_reg)); | 835 | WRT_REG_DWORD(®->iobase_select, 0xB0600000); |
| 723 | 836 | fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); | |
| 724 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 725 | WRT_REG_DWORD(dmp_reg, 0xB0400000); | ||
| 726 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 727 | fw->shadow_reg[4] = htonl(RD_REG_DWORD(dmp_reg)); | ||
| 728 | |||
| 729 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 730 | WRT_REG_DWORD(dmp_reg, 0xB0500000); | ||
| 731 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 732 | fw->shadow_reg[5] = htonl(RD_REG_DWORD(dmp_reg)); | ||
| 733 | |||
| 734 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 735 | WRT_REG_DWORD(dmp_reg, 0xB0600000); | ||
| 736 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 737 | fw->shadow_reg[6] = htonl(RD_REG_DWORD(dmp_reg)); | ||
| 738 | 837 | ||
| 739 | /* Mailbox registers. */ | 838 | /* Mailbox registers. */ |
| 740 | mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); | 839 | mbx_reg = ®->mailbox0; |
| 741 | for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) | 840 | for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) |
| 742 | fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); | 841 | fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); |
| 743 | 842 | ||
| 744 | /* Transfer sequence registers. */ | 843 | /* Transfer sequence registers. */ |
| 745 | iter_reg = fw->xseq_gp_reg; | 844 | iter_reg = fw->xseq_gp_reg; |
| 746 | WRT_REG_DWORD(®->iobase_addr, 0xBF00); | 845 | WRT_REG_DWORD(®->iobase_addr, 0xBF00); |
| 747 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 846 | dmp_reg = ®->iobase_window; |
| 748 | for (cnt = 0; cnt < 16; cnt++) | 847 | for (cnt = 0; cnt < 16; cnt++) |
| 749 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 848 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 750 | 849 | ||
| 751 | WRT_REG_DWORD(®->iobase_addr, 0xBF10); | 850 | WRT_REG_DWORD(®->iobase_addr, 0xBF10); |
| 752 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 851 | dmp_reg = ®->iobase_window; |
| 753 | for (cnt = 0; cnt < 16; cnt++) | 852 | for (cnt = 0; cnt < 16; cnt++) |
| 754 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 853 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 755 | 854 | ||
| 756 | WRT_REG_DWORD(®->iobase_addr, 0xBF20); | 855 | WRT_REG_DWORD(®->iobase_addr, 0xBF20); |
| 757 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 856 | dmp_reg = ®->iobase_window; |
| 758 | for (cnt = 0; cnt < 16; cnt++) | 857 | for (cnt = 0; cnt < 16; cnt++) |
| 759 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 858 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 760 | 859 | ||
| 761 | WRT_REG_DWORD(®->iobase_addr, 0xBF30); | 860 | WRT_REG_DWORD(®->iobase_addr, 0xBF30); |
| 762 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 861 | dmp_reg = ®->iobase_window; |
| 763 | for (cnt = 0; cnt < 16; cnt++) | 862 | for (cnt = 0; cnt < 16; cnt++) |
| 764 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 863 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 765 | 864 | ||
| 766 | WRT_REG_DWORD(®->iobase_addr, 0xBF40); | 865 | WRT_REG_DWORD(®->iobase_addr, 0xBF40); |
| 767 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 866 | dmp_reg = ®->iobase_window; |
| 768 | for (cnt = 0; cnt < 16; cnt++) | 867 | for (cnt = 0; cnt < 16; cnt++) |
| 769 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 868 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 770 | 869 | ||
| 771 | WRT_REG_DWORD(®->iobase_addr, 0xBF50); | 870 | WRT_REG_DWORD(®->iobase_addr, 0xBF50); |
| 772 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 871 | dmp_reg = ®->iobase_window; |
| 773 | for (cnt = 0; cnt < 16; cnt++) | 872 | for (cnt = 0; cnt < 16; cnt++) |
| 774 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 873 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 775 | 874 | ||
| 776 | WRT_REG_DWORD(®->iobase_addr, 0xBF60); | 875 | WRT_REG_DWORD(®->iobase_addr, 0xBF60); |
| 777 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 876 | dmp_reg = ®->iobase_window; |
| 778 | for (cnt = 0; cnt < 16; cnt++) | 877 | for (cnt = 0; cnt < 16; cnt++) |
| 779 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 878 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 780 | 879 | ||
| 781 | WRT_REG_DWORD(®->iobase_addr, 0xBF70); | 880 | WRT_REG_DWORD(®->iobase_addr, 0xBF70); |
| 782 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 881 | dmp_reg = ®->iobase_window; |
| 783 | for (cnt = 0; cnt < 16; cnt++) | 882 | for (cnt = 0; cnt < 16; cnt++) |
| 784 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 883 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 785 | 884 | ||
| 786 | WRT_REG_DWORD(®->iobase_addr, 0xBFE0); | 885 | WRT_REG_DWORD(®->iobase_addr, 0xBFE0); |
| 787 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 886 | dmp_reg = ®->iobase_window; |
| 788 | for (cnt = 0; cnt < sizeof(fw->xseq_0_reg) / 4; cnt++) | 887 | for (cnt = 0; cnt < sizeof(fw->xseq_0_reg) / 4; cnt++) |
| 789 | fw->xseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | 888 | fw->xseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); |
| 790 | 889 | ||
| 791 | WRT_REG_DWORD(®->iobase_addr, 0xBFF0); | 890 | WRT_REG_DWORD(®->iobase_addr, 0xBFF0); |
| 792 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 891 | dmp_reg = ®->iobase_window; |
| 793 | for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) | 892 | for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) |
| 794 | fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | 893 | fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); |
| 795 | 894 | ||
| 796 | /* Receive sequence registers. */ | 895 | /* Receive sequence registers. */ |
| 797 | iter_reg = fw->rseq_gp_reg; | 896 | iter_reg = fw->rseq_gp_reg; |
| 798 | WRT_REG_DWORD(®->iobase_addr, 0xFF00); | 897 | WRT_REG_DWORD(®->iobase_addr, 0xFF00); |
| 799 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 898 | dmp_reg = ®->iobase_window; |
| 800 | for (cnt = 0; cnt < 16; cnt++) | 899 | for (cnt = 0; cnt < 16; cnt++) |
| 801 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 900 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 802 | 901 | ||
| 803 | WRT_REG_DWORD(®->iobase_addr, 0xFF10); | 902 | WRT_REG_DWORD(®->iobase_addr, 0xFF10); |
| 804 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 903 | dmp_reg = ®->iobase_window; |
| 805 | for (cnt = 0; cnt < 16; cnt++) | 904 | for (cnt = 0; cnt < 16; cnt++) |
| 806 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 905 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 807 | 906 | ||
| 808 | WRT_REG_DWORD(®->iobase_addr, 0xFF20); | 907 | WRT_REG_DWORD(®->iobase_addr, 0xFF20); |
| 809 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 908 | dmp_reg = ®->iobase_window; |
| 810 | for (cnt = 0; cnt < 16; cnt++) | 909 | for (cnt = 0; cnt < 16; cnt++) |
| 811 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 910 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 812 | 911 | ||
| 813 | WRT_REG_DWORD(®->iobase_addr, 0xFF30); | 912 | WRT_REG_DWORD(®->iobase_addr, 0xFF30); |
| 814 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 913 | dmp_reg = ®->iobase_window; |
| 815 | for (cnt = 0; cnt < 16; cnt++) | 914 | for (cnt = 0; cnt < 16; cnt++) |
| 816 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 915 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 817 | 916 | ||
| 818 | WRT_REG_DWORD(®->iobase_addr, 0xFF40); | 917 | WRT_REG_DWORD(®->iobase_addr, 0xFF40); |
| 819 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 918 | dmp_reg = ®->iobase_window; |
| 820 | for (cnt = 0; cnt < 16; cnt++) | 919 | for (cnt = 0; cnt < 16; cnt++) |
| 821 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 920 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 822 | 921 | ||
| 823 | WRT_REG_DWORD(®->iobase_addr, 0xFF50); | 922 | WRT_REG_DWORD(®->iobase_addr, 0xFF50); |
| 824 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 923 | dmp_reg = ®->iobase_window; |
| 825 | for (cnt = 0; cnt < 16; cnt++) | 924 | for (cnt = 0; cnt < 16; cnt++) |
| 826 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 925 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 827 | 926 | ||
| 828 | WRT_REG_DWORD(®->iobase_addr, 0xFF60); | 927 | WRT_REG_DWORD(®->iobase_addr, 0xFF60); |
| 829 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 928 | dmp_reg = ®->iobase_window; |
| 830 | for (cnt = 0; cnt < 16; cnt++) | 929 | for (cnt = 0; cnt < 16; cnt++) |
| 831 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 930 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 832 | 931 | ||
| 833 | WRT_REG_DWORD(®->iobase_addr, 0xFF70); | 932 | WRT_REG_DWORD(®->iobase_addr, 0xFF70); |
| 834 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 933 | dmp_reg = ®->iobase_window; |
| 835 | for (cnt = 0; cnt < 16; cnt++) | 934 | for (cnt = 0; cnt < 16; cnt++) |
| 836 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 935 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 837 | 936 | ||
| 838 | WRT_REG_DWORD(®->iobase_addr, 0xFFD0); | 937 | WRT_REG_DWORD(®->iobase_addr, 0xFFD0); |
| 839 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 938 | dmp_reg = ®->iobase_window; |
| 840 | for (cnt = 0; cnt < sizeof(fw->rseq_0_reg) / 4; cnt++) | 939 | for (cnt = 0; cnt < sizeof(fw->rseq_0_reg) / 4; cnt++) |
| 841 | fw->rseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | 940 | fw->rseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); |
| 842 | 941 | ||
| 843 | WRT_REG_DWORD(®->iobase_addr, 0xFFE0); | 942 | WRT_REG_DWORD(®->iobase_addr, 0xFFE0); |
| 844 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 943 | dmp_reg = ®->iobase_window; |
| 845 | for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) | 944 | for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) |
| 846 | fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | 945 | fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); |
| 847 | 946 | ||
| 848 | WRT_REG_DWORD(®->iobase_addr, 0xFFF0); | 947 | WRT_REG_DWORD(®->iobase_addr, 0xFFF0); |
| 849 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 948 | dmp_reg = ®->iobase_window; |
| 850 | for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) | 949 | for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) |
| 851 | fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | 950 | fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); |
| 852 | 951 | ||
| 853 | /* Command DMA registers. */ | 952 | /* Command DMA registers. */ |
| 854 | WRT_REG_DWORD(®->iobase_addr, 0x7100); | 953 | WRT_REG_DWORD(®->iobase_addr, 0x7100); |
| 855 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 954 | dmp_reg = ®->iobase_window; |
| 856 | for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) | 955 | for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) |
| 857 | fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | 956 | fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); |
| 858 | 957 | ||
| 859 | /* Queues. */ | 958 | /* Queues. */ |
| 860 | iter_reg = fw->req0_dma_reg; | 959 | iter_reg = fw->req0_dma_reg; |
| 861 | WRT_REG_DWORD(®->iobase_addr, 0x7200); | 960 | WRT_REG_DWORD(®->iobase_addr, 0x7200); |
| 862 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 961 | dmp_reg = ®->iobase_window; |
| 863 | for (cnt = 0; cnt < 8; cnt++) | 962 | for (cnt = 0; cnt < 8; cnt++) |
| 864 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 963 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 865 | 964 | ||
| 866 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xE4); | 965 | dmp_reg = ®->iobase_q; |
| 867 | for (cnt = 0; cnt < 7; cnt++) | 966 | for (cnt = 0; cnt < 7; cnt++) |
| 868 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 967 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 869 | 968 | ||
| 870 | iter_reg = fw->resp0_dma_reg; | 969 | iter_reg = fw->resp0_dma_reg; |
| 871 | WRT_REG_DWORD(®->iobase_addr, 0x7300); | 970 | WRT_REG_DWORD(®->iobase_addr, 0x7300); |
| 872 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 971 | dmp_reg = ®->iobase_window; |
| 873 | for (cnt = 0; cnt < 8; cnt++) | 972 | for (cnt = 0; cnt < 8; cnt++) |
| 874 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 973 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 875 | 974 | ||
| 876 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xE4); | 975 | dmp_reg = ®->iobase_q; |
| 877 | for (cnt = 0; cnt < 7; cnt++) | 976 | for (cnt = 0; cnt < 7; cnt++) |
| 878 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 977 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 879 | 978 | ||
| 880 | iter_reg = fw->req1_dma_reg; | 979 | iter_reg = fw->req1_dma_reg; |
| 881 | WRT_REG_DWORD(®->iobase_addr, 0x7400); | 980 | WRT_REG_DWORD(®->iobase_addr, 0x7400); |
| 882 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 981 | dmp_reg = ®->iobase_window; |
| 883 | for (cnt = 0; cnt < 8; cnt++) | 982 | for (cnt = 0; cnt < 8; cnt++) |
| 884 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 983 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 885 | 984 | ||
| 886 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xE4); | 985 | dmp_reg = ®->iobase_q; |
| 887 | for (cnt = 0; cnt < 7; cnt++) | 986 | for (cnt = 0; cnt < 7; cnt++) |
| 888 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 987 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 889 | 988 | ||
| 890 | /* Transmit DMA registers. */ | 989 | /* Transmit DMA registers. */ |
| 891 | iter_reg = fw->xmt0_dma_reg; | 990 | iter_reg = fw->xmt0_dma_reg; |
| 892 | WRT_REG_DWORD(®->iobase_addr, 0x7600); | 991 | WRT_REG_DWORD(®->iobase_addr, 0x7600); |
| 893 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 992 | dmp_reg = ®->iobase_window; |
| 894 | for (cnt = 0; cnt < 16; cnt++) | 993 | for (cnt = 0; cnt < 16; cnt++) |
| 895 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 994 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 896 | 995 | ||
| 897 | WRT_REG_DWORD(®->iobase_addr, 0x7610); | 996 | WRT_REG_DWORD(®->iobase_addr, 0x7610); |
| 898 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 997 | dmp_reg = ®->iobase_window; |
| 899 | for (cnt = 0; cnt < 16; cnt++) | 998 | for (cnt = 0; cnt < 16; cnt++) |
| 900 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 999 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 901 | 1000 | ||
| 902 | iter_reg = fw->xmt1_dma_reg; | 1001 | iter_reg = fw->xmt1_dma_reg; |
| 903 | WRT_REG_DWORD(®->iobase_addr, 0x7620); | 1002 | WRT_REG_DWORD(®->iobase_addr, 0x7620); |
| 904 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1003 | dmp_reg = ®->iobase_window; |
| 905 | for (cnt = 0; cnt < 16; cnt++) | 1004 | for (cnt = 0; cnt < 16; cnt++) |
| 906 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1005 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 907 | 1006 | ||
| 908 | WRT_REG_DWORD(®->iobase_addr, 0x7630); | 1007 | WRT_REG_DWORD(®->iobase_addr, 0x7630); |
| 909 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1008 | dmp_reg = ®->iobase_window; |
| 910 | for (cnt = 0; cnt < 16; cnt++) | 1009 | for (cnt = 0; cnt < 16; cnt++) |
| 911 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1010 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 912 | 1011 | ||
| 913 | iter_reg = fw->xmt2_dma_reg; | 1012 | iter_reg = fw->xmt2_dma_reg; |
| 914 | WRT_REG_DWORD(®->iobase_addr, 0x7640); | 1013 | WRT_REG_DWORD(®->iobase_addr, 0x7640); |
| 915 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1014 | dmp_reg = ®->iobase_window; |
| 916 | for (cnt = 0; cnt < 16; cnt++) | 1015 | for (cnt = 0; cnt < 16; cnt++) |
| 917 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1016 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 918 | 1017 | ||
| 919 | WRT_REG_DWORD(®->iobase_addr, 0x7650); | 1018 | WRT_REG_DWORD(®->iobase_addr, 0x7650); |
| 920 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1019 | dmp_reg = ®->iobase_window; |
| 921 | for (cnt = 0; cnt < 16; cnt++) | 1020 | for (cnt = 0; cnt < 16; cnt++) |
| 922 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1021 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 923 | 1022 | ||
| 924 | iter_reg = fw->xmt3_dma_reg; | 1023 | iter_reg = fw->xmt3_dma_reg; |
| 925 | WRT_REG_DWORD(®->iobase_addr, 0x7660); | 1024 | WRT_REG_DWORD(®->iobase_addr, 0x7660); |
| 926 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1025 | dmp_reg = ®->iobase_window; |
| 927 | for (cnt = 0; cnt < 16; cnt++) | 1026 | for (cnt = 0; cnt < 16; cnt++) |
| 928 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1027 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 929 | 1028 | ||
| 930 | WRT_REG_DWORD(®->iobase_addr, 0x7670); | 1029 | WRT_REG_DWORD(®->iobase_addr, 0x7670); |
| 931 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1030 | dmp_reg = ®->iobase_window; |
| 932 | for (cnt = 0; cnt < 16; cnt++) | 1031 | for (cnt = 0; cnt < 16; cnt++) |
| 933 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1032 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 934 | 1033 | ||
| 935 | iter_reg = fw->xmt4_dma_reg; | 1034 | iter_reg = fw->xmt4_dma_reg; |
| 936 | WRT_REG_DWORD(®->iobase_addr, 0x7680); | 1035 | WRT_REG_DWORD(®->iobase_addr, 0x7680); |
| 937 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1036 | dmp_reg = ®->iobase_window; |
| 938 | for (cnt = 0; cnt < 16; cnt++) | 1037 | for (cnt = 0; cnt < 16; cnt++) |
| 939 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1038 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 940 | 1039 | ||
| 941 | WRT_REG_DWORD(®->iobase_addr, 0x7690); | 1040 | WRT_REG_DWORD(®->iobase_addr, 0x7690); |
| 942 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1041 | dmp_reg = ®->iobase_window; |
| 943 | for (cnt = 0; cnt < 16; cnt++) | 1042 | for (cnt = 0; cnt < 16; cnt++) |
| 944 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1043 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 945 | 1044 | ||
| 946 | WRT_REG_DWORD(®->iobase_addr, 0x76A0); | 1045 | WRT_REG_DWORD(®->iobase_addr, 0x76A0); |
| 947 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1046 | dmp_reg = ®->iobase_window; |
| 948 | for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) | 1047 | for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) |
| 949 | fw->xmt_data_dma_reg[cnt] = | 1048 | fw->xmt_data_dma_reg[cnt] = |
| 950 | htonl(RD_REG_DWORD(dmp_reg++)); | 1049 | htonl(RD_REG_DWORD(dmp_reg++)); |
| @@ -952,221 +1051,221 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
| 952 | /* Receive DMA registers. */ | 1051 | /* Receive DMA registers. */ |
| 953 | iter_reg = fw->rcvt0_data_dma_reg; | 1052 | iter_reg = fw->rcvt0_data_dma_reg; |
| 954 | WRT_REG_DWORD(®->iobase_addr, 0x7700); | 1053 | WRT_REG_DWORD(®->iobase_addr, 0x7700); |
| 955 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1054 | dmp_reg = ®->iobase_window; |
| 956 | for (cnt = 0; cnt < 16; cnt++) | 1055 | for (cnt = 0; cnt < 16; cnt++) |
| 957 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1056 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 958 | 1057 | ||
| 959 | WRT_REG_DWORD(®->iobase_addr, 0x7710); | 1058 | WRT_REG_DWORD(®->iobase_addr, 0x7710); |
| 960 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1059 | dmp_reg = ®->iobase_window; |
| 961 | for (cnt = 0; cnt < 16; cnt++) | 1060 | for (cnt = 0; cnt < 16; cnt++) |
| 962 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1061 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 963 | 1062 | ||
| 964 | iter_reg = fw->rcvt1_data_dma_reg; | 1063 | iter_reg = fw->rcvt1_data_dma_reg; |
| 965 | WRT_REG_DWORD(®->iobase_addr, 0x7720); | 1064 | WRT_REG_DWORD(®->iobase_addr, 0x7720); |
| 966 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1065 | dmp_reg = ®->iobase_window; |
| 967 | for (cnt = 0; cnt < 16; cnt++) | 1066 | for (cnt = 0; cnt < 16; cnt++) |
| 968 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1067 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 969 | 1068 | ||
| 970 | WRT_REG_DWORD(®->iobase_addr, 0x7730); | 1069 | WRT_REG_DWORD(®->iobase_addr, 0x7730); |
| 971 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1070 | dmp_reg = ®->iobase_window; |
| 972 | for (cnt = 0; cnt < 16; cnt++) | 1071 | for (cnt = 0; cnt < 16; cnt++) |
| 973 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1072 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 974 | 1073 | ||
| 975 | /* RISC registers. */ | 1074 | /* RISC registers. */ |
| 976 | iter_reg = fw->risc_gp_reg; | 1075 | iter_reg = fw->risc_gp_reg; |
| 977 | WRT_REG_DWORD(®->iobase_addr, 0x0F00); | 1076 | WRT_REG_DWORD(®->iobase_addr, 0x0F00); |
| 978 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1077 | dmp_reg = ®->iobase_window; |
| 979 | for (cnt = 0; cnt < 16; cnt++) | 1078 | for (cnt = 0; cnt < 16; cnt++) |
| 980 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1079 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 981 | 1080 | ||
| 982 | WRT_REG_DWORD(®->iobase_addr, 0x0F10); | 1081 | WRT_REG_DWORD(®->iobase_addr, 0x0F10); |
| 983 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1082 | dmp_reg = ®->iobase_window; |
| 984 | for (cnt = 0; cnt < 16; cnt++) | 1083 | for (cnt = 0; cnt < 16; cnt++) |
| 985 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1084 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 986 | 1085 | ||
| 987 | WRT_REG_DWORD(®->iobase_addr, 0x0F20); | 1086 | WRT_REG_DWORD(®->iobase_addr, 0x0F20); |
| 988 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1087 | dmp_reg = ®->iobase_window; |
| 989 | for (cnt = 0; cnt < 16; cnt++) | 1088 | for (cnt = 0; cnt < 16; cnt++) |
| 990 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1089 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 991 | 1090 | ||
| 992 | WRT_REG_DWORD(®->iobase_addr, 0x0F30); | 1091 | WRT_REG_DWORD(®->iobase_addr, 0x0F30); |
| 993 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1092 | dmp_reg = ®->iobase_window; |
| 994 | for (cnt = 0; cnt < 16; cnt++) | 1093 | for (cnt = 0; cnt < 16; cnt++) |
| 995 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1094 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 996 | 1095 | ||
| 997 | WRT_REG_DWORD(®->iobase_addr, 0x0F40); | 1096 | WRT_REG_DWORD(®->iobase_addr, 0x0F40); |
| 998 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1097 | dmp_reg = ®->iobase_window; |
| 999 | for (cnt = 0; cnt < 16; cnt++) | 1098 | for (cnt = 0; cnt < 16; cnt++) |
| 1000 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1099 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1001 | 1100 | ||
| 1002 | WRT_REG_DWORD(®->iobase_addr, 0x0F50); | 1101 | WRT_REG_DWORD(®->iobase_addr, 0x0F50); |
| 1003 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1102 | dmp_reg = ®->iobase_window; |
| 1004 | for (cnt = 0; cnt < 16; cnt++) | 1103 | for (cnt = 0; cnt < 16; cnt++) |
| 1005 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1104 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1006 | 1105 | ||
| 1007 | WRT_REG_DWORD(®->iobase_addr, 0x0F60); | 1106 | WRT_REG_DWORD(®->iobase_addr, 0x0F60); |
| 1008 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1107 | dmp_reg = ®->iobase_window; |
| 1009 | for (cnt = 0; cnt < 16; cnt++) | 1108 | for (cnt = 0; cnt < 16; cnt++) |
| 1010 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1109 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1011 | 1110 | ||
| 1012 | WRT_REG_DWORD(®->iobase_addr, 0x0F70); | 1111 | WRT_REG_DWORD(®->iobase_addr, 0x0F70); |
| 1013 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1112 | dmp_reg = ®->iobase_window; |
| 1014 | for (cnt = 0; cnt < 16; cnt++) | 1113 | for (cnt = 0; cnt < 16; cnt++) |
| 1015 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1114 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1016 | 1115 | ||
| 1017 | /* Local memory controller registers. */ | 1116 | /* Local memory controller registers. */ |
| 1018 | iter_reg = fw->lmc_reg; | 1117 | iter_reg = fw->lmc_reg; |
| 1019 | WRT_REG_DWORD(®->iobase_addr, 0x3000); | 1118 | WRT_REG_DWORD(®->iobase_addr, 0x3000); |
| 1020 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1119 | dmp_reg = ®->iobase_window; |
| 1021 | for (cnt = 0; cnt < 16; cnt++) | 1120 | for (cnt = 0; cnt < 16; cnt++) |
| 1022 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1121 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1023 | 1122 | ||
| 1024 | WRT_REG_DWORD(®->iobase_addr, 0x3010); | 1123 | WRT_REG_DWORD(®->iobase_addr, 0x3010); |
| 1025 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1124 | dmp_reg = ®->iobase_window; |
| 1026 | for (cnt = 0; cnt < 16; cnt++) | 1125 | for (cnt = 0; cnt < 16; cnt++) |
| 1027 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1126 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1028 | 1127 | ||
| 1029 | WRT_REG_DWORD(®->iobase_addr, 0x3020); | 1128 | WRT_REG_DWORD(®->iobase_addr, 0x3020); |
| 1030 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1129 | dmp_reg = ®->iobase_window; |
| 1031 | for (cnt = 0; cnt < 16; cnt++) | 1130 | for (cnt = 0; cnt < 16; cnt++) |
| 1032 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1131 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1033 | 1132 | ||
| 1034 | WRT_REG_DWORD(®->iobase_addr, 0x3030); | 1133 | WRT_REG_DWORD(®->iobase_addr, 0x3030); |
| 1035 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1134 | dmp_reg = ®->iobase_window; |
| 1036 | for (cnt = 0; cnt < 16; cnt++) | 1135 | for (cnt = 0; cnt < 16; cnt++) |
| 1037 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1136 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1038 | 1137 | ||
| 1039 | WRT_REG_DWORD(®->iobase_addr, 0x3040); | 1138 | WRT_REG_DWORD(®->iobase_addr, 0x3040); |
| 1040 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1139 | dmp_reg = ®->iobase_window; |
| 1041 | for (cnt = 0; cnt < 16; cnt++) | 1140 | for (cnt = 0; cnt < 16; cnt++) |
| 1042 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1141 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1043 | 1142 | ||
| 1044 | WRT_REG_DWORD(®->iobase_addr, 0x3050); | 1143 | WRT_REG_DWORD(®->iobase_addr, 0x3050); |
| 1045 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1144 | dmp_reg = ®->iobase_window; |
| 1046 | for (cnt = 0; cnt < 16; cnt++) | 1145 | for (cnt = 0; cnt < 16; cnt++) |
| 1047 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1146 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1048 | 1147 | ||
| 1049 | WRT_REG_DWORD(®->iobase_addr, 0x3060); | 1148 | WRT_REG_DWORD(®->iobase_addr, 0x3060); |
| 1050 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1149 | dmp_reg = ®->iobase_window; |
| 1051 | for (cnt = 0; cnt < 16; cnt++) | 1150 | for (cnt = 0; cnt < 16; cnt++) |
| 1052 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1151 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1053 | 1152 | ||
| 1054 | /* Fibre Protocol Module registers. */ | 1153 | /* Fibre Protocol Module registers. */ |
| 1055 | iter_reg = fw->fpm_hdw_reg; | 1154 | iter_reg = fw->fpm_hdw_reg; |
| 1056 | WRT_REG_DWORD(®->iobase_addr, 0x4000); | 1155 | WRT_REG_DWORD(®->iobase_addr, 0x4000); |
| 1057 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1156 | dmp_reg = ®->iobase_window; |
| 1058 | for (cnt = 0; cnt < 16; cnt++) | 1157 | for (cnt = 0; cnt < 16; cnt++) |
| 1059 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1158 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1060 | 1159 | ||
| 1061 | WRT_REG_DWORD(®->iobase_addr, 0x4010); | 1160 | WRT_REG_DWORD(®->iobase_addr, 0x4010); |
| 1062 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1161 | dmp_reg = ®->iobase_window; |
| 1063 | for (cnt = 0; cnt < 16; cnt++) | 1162 | for (cnt = 0; cnt < 16; cnt++) |
| 1064 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1163 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1065 | 1164 | ||
| 1066 | WRT_REG_DWORD(®->iobase_addr, 0x4020); | 1165 | WRT_REG_DWORD(®->iobase_addr, 0x4020); |
| 1067 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1166 | dmp_reg = ®->iobase_window; |
| 1068 | for (cnt = 0; cnt < 16; cnt++) | 1167 | for (cnt = 0; cnt < 16; cnt++) |
| 1069 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1168 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1070 | 1169 | ||
| 1071 | WRT_REG_DWORD(®->iobase_addr, 0x4030); | 1170 | WRT_REG_DWORD(®->iobase_addr, 0x4030); |
| 1072 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1171 | dmp_reg = ®->iobase_window; |
| 1073 | for (cnt = 0; cnt < 16; cnt++) | 1172 | for (cnt = 0; cnt < 16; cnt++) |
| 1074 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1173 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1075 | 1174 | ||
| 1076 | WRT_REG_DWORD(®->iobase_addr, 0x4040); | 1175 | WRT_REG_DWORD(®->iobase_addr, 0x4040); |
| 1077 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1176 | dmp_reg = ®->iobase_window; |
| 1078 | for (cnt = 0; cnt < 16; cnt++) | 1177 | for (cnt = 0; cnt < 16; cnt++) |
| 1079 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1178 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1080 | 1179 | ||
| 1081 | WRT_REG_DWORD(®->iobase_addr, 0x4050); | 1180 | WRT_REG_DWORD(®->iobase_addr, 0x4050); |
| 1082 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1181 | dmp_reg = ®->iobase_window; |
| 1083 | for (cnt = 0; cnt < 16; cnt++) | 1182 | for (cnt = 0; cnt < 16; cnt++) |
| 1084 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1183 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1085 | 1184 | ||
| 1086 | WRT_REG_DWORD(®->iobase_addr, 0x4060); | 1185 | WRT_REG_DWORD(®->iobase_addr, 0x4060); |
| 1087 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1186 | dmp_reg = ®->iobase_window; |
| 1088 | for (cnt = 0; cnt < 16; cnt++) | 1187 | for (cnt = 0; cnt < 16; cnt++) |
| 1089 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1188 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1090 | 1189 | ||
| 1091 | WRT_REG_DWORD(®->iobase_addr, 0x4070); | 1190 | WRT_REG_DWORD(®->iobase_addr, 0x4070); |
| 1092 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1191 | dmp_reg = ®->iobase_window; |
| 1093 | for (cnt = 0; cnt < 16; cnt++) | 1192 | for (cnt = 0; cnt < 16; cnt++) |
| 1094 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1193 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1095 | 1194 | ||
| 1096 | WRT_REG_DWORD(®->iobase_addr, 0x4080); | 1195 | WRT_REG_DWORD(®->iobase_addr, 0x4080); |
| 1097 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1196 | dmp_reg = ®->iobase_window; |
| 1098 | for (cnt = 0; cnt < 16; cnt++) | 1197 | for (cnt = 0; cnt < 16; cnt++) |
| 1099 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1198 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1100 | 1199 | ||
| 1101 | WRT_REG_DWORD(®->iobase_addr, 0x4090); | 1200 | WRT_REG_DWORD(®->iobase_addr, 0x4090); |
| 1102 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1201 | dmp_reg = ®->iobase_window; |
| 1103 | for (cnt = 0; cnt < 16; cnt++) | 1202 | for (cnt = 0; cnt < 16; cnt++) |
| 1104 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1203 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1105 | 1204 | ||
| 1106 | WRT_REG_DWORD(®->iobase_addr, 0x40A0); | 1205 | WRT_REG_DWORD(®->iobase_addr, 0x40A0); |
| 1107 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1206 | dmp_reg = ®->iobase_window; |
| 1108 | for (cnt = 0; cnt < 16; cnt++) | 1207 | for (cnt = 0; cnt < 16; cnt++) |
| 1109 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1208 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1110 | 1209 | ||
| 1111 | WRT_REG_DWORD(®->iobase_addr, 0x40B0); | 1210 | WRT_REG_DWORD(®->iobase_addr, 0x40B0); |
| 1112 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1211 | dmp_reg = ®->iobase_window; |
| 1113 | for (cnt = 0; cnt < 16; cnt++) | 1212 | for (cnt = 0; cnt < 16; cnt++) |
| 1114 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1213 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1115 | 1214 | ||
| 1116 | /* Frame Buffer registers. */ | 1215 | /* Frame Buffer registers. */ |
| 1117 | iter_reg = fw->fb_hdw_reg; | 1216 | iter_reg = fw->fb_hdw_reg; |
| 1118 | WRT_REG_DWORD(®->iobase_addr, 0x6000); | 1217 | WRT_REG_DWORD(®->iobase_addr, 0x6000); |
| 1119 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1218 | dmp_reg = ®->iobase_window; |
| 1120 | for (cnt = 0; cnt < 16; cnt++) | 1219 | for (cnt = 0; cnt < 16; cnt++) |
| 1121 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1220 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1122 | 1221 | ||
| 1123 | WRT_REG_DWORD(®->iobase_addr, 0x6010); | 1222 | WRT_REG_DWORD(®->iobase_addr, 0x6010); |
| 1124 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1223 | dmp_reg = ®->iobase_window; |
| 1125 | for (cnt = 0; cnt < 16; cnt++) | 1224 | for (cnt = 0; cnt < 16; cnt++) |
| 1126 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1225 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1127 | 1226 | ||
| 1128 | WRT_REG_DWORD(®->iobase_addr, 0x6020); | 1227 | WRT_REG_DWORD(®->iobase_addr, 0x6020); |
| 1129 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1228 | dmp_reg = ®->iobase_window; |
| 1130 | for (cnt = 0; cnt < 16; cnt++) | 1229 | for (cnt = 0; cnt < 16; cnt++) |
| 1131 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1230 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1132 | 1231 | ||
| 1133 | WRT_REG_DWORD(®->iobase_addr, 0x6030); | 1232 | WRT_REG_DWORD(®->iobase_addr, 0x6030); |
| 1134 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1233 | dmp_reg = ®->iobase_window; |
| 1135 | for (cnt = 0; cnt < 16; cnt++) | 1234 | for (cnt = 0; cnt < 16; cnt++) |
| 1136 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1235 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1137 | 1236 | ||
| 1138 | WRT_REG_DWORD(®->iobase_addr, 0x6040); | 1237 | WRT_REG_DWORD(®->iobase_addr, 0x6040); |
| 1139 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1238 | dmp_reg = ®->iobase_window; |
| 1140 | for (cnt = 0; cnt < 16; cnt++) | 1239 | for (cnt = 0; cnt < 16; cnt++) |
| 1141 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1240 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1142 | 1241 | ||
| 1143 | WRT_REG_DWORD(®->iobase_addr, 0x6100); | 1242 | WRT_REG_DWORD(®->iobase_addr, 0x6100); |
| 1144 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1243 | dmp_reg = ®->iobase_window; |
| 1145 | for (cnt = 0; cnt < 16; cnt++) | 1244 | for (cnt = 0; cnt < 16; cnt++) |
| 1146 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1245 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1147 | 1246 | ||
| 1148 | WRT_REG_DWORD(®->iobase_addr, 0x6130); | 1247 | WRT_REG_DWORD(®->iobase_addr, 0x6130); |
| 1149 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1248 | dmp_reg = ®->iobase_window; |
| 1150 | for (cnt = 0; cnt < 16; cnt++) | 1249 | for (cnt = 0; cnt < 16; cnt++) |
| 1151 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1250 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1152 | 1251 | ||
| 1153 | WRT_REG_DWORD(®->iobase_addr, 0x6150); | 1252 | WRT_REG_DWORD(®->iobase_addr, 0x6150); |
| 1154 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1253 | dmp_reg = ®->iobase_window; |
| 1155 | for (cnt = 0; cnt < 16; cnt++) | 1254 | for (cnt = 0; cnt < 16; cnt++) |
| 1156 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1255 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1157 | 1256 | ||
| 1158 | WRT_REG_DWORD(®->iobase_addr, 0x6170); | 1257 | WRT_REG_DWORD(®->iobase_addr, 0x6170); |
| 1159 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1258 | dmp_reg = ®->iobase_window; |
| 1160 | for (cnt = 0; cnt < 16; cnt++) | 1259 | for (cnt = 0; cnt < 16; cnt++) |
| 1161 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1260 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1162 | 1261 | ||
| 1163 | WRT_REG_DWORD(®->iobase_addr, 0x6190); | 1262 | WRT_REG_DWORD(®->iobase_addr, 0x6190); |
| 1164 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1263 | dmp_reg = ®->iobase_window; |
| 1165 | for (cnt = 0; cnt < 16; cnt++) | 1264 | for (cnt = 0; cnt < 16; cnt++) |
| 1166 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1265 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1167 | 1266 | ||
| 1168 | WRT_REG_DWORD(®->iobase_addr, 0x61B0); | 1267 | WRT_REG_DWORD(®->iobase_addr, 0x61B0); |
| 1169 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); | 1268 | dmp_reg = ®->iobase_window; |
| 1170 | for (cnt = 0; cnt < 16; cnt++) | 1269 | for (cnt = 0; cnt < 16; cnt++) |
| 1171 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | 1270 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1172 | 1271 | ||
| @@ -1187,10 +1286,10 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
| 1187 | 1286 | ||
| 1188 | udelay(100); | 1287 | udelay(100); |
| 1189 | /* Wait for firmware to complete NVRAM accesses. */ | 1288 | /* Wait for firmware to complete NVRAM accesses. */ |
| 1190 | mb[0] = (uint32_t) RD_REG_WORD(®->mailbox0); | 1289 | mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); |
| 1191 | for (cnt = 10000 ; cnt && mb[0]; cnt--) { | 1290 | for (cnt = 10000 ; cnt && mb0; cnt--) { |
| 1192 | udelay(5); | 1291 | udelay(5); |
| 1193 | mb[0] = (uint32_t) RD_REG_WORD(®->mailbox0); | 1292 | mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); |
| 1194 | barrier(); | 1293 | barrier(); |
| 1195 | } | 1294 | } |
| 1196 | 1295 | ||
| @@ -1214,110 +1313,717 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
| 1214 | rval = QLA_FUNCTION_TIMEOUT; | 1313 | rval = QLA_FUNCTION_TIMEOUT; |
| 1215 | } | 1314 | } |
| 1216 | 1315 | ||
| 1217 | /* Memory. */ | 1316 | if (rval == QLA_SUCCESS) |
| 1317 | rval = qla2xxx_dump_memory(ha, fw->code_ram, | ||
| 1318 | sizeof(fw->code_ram), fw->ext_mem, &nxt); | ||
| 1319 | |||
| 1218 | if (rval == QLA_SUCCESS) { | 1320 | if (rval == QLA_SUCCESS) { |
| 1219 | /* Code RAM. */ | 1321 | nxt = qla2xxx_copy_queues(ha, nxt); |
| 1220 | risc_address = 0x20000; | 1322 | if (ha->eft) |
| 1221 | WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED); | 1323 | memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); |
| 1222 | clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
| 1223 | } | 1324 | } |
| 1224 | for (cnt = 0; cnt < sizeof(fw->code_ram) / 4 && rval == QLA_SUCCESS; | ||
| 1225 | cnt++, risc_address++) { | ||
| 1226 | WRT_REG_WORD(®->mailbox1, LSW(risc_address)); | ||
| 1227 | WRT_REG_WORD(®->mailbox8, MSW(risc_address)); | ||
| 1228 | RD_REG_WORD(®->mailbox8); | ||
| 1229 | WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); | ||
| 1230 | 1325 | ||
| 1231 | for (timer = 6000000; timer; timer--) { | 1326 | if (rval != QLA_SUCCESS) { |
| 1232 | /* Check for pending interrupts. */ | 1327 | qla_printk(KERN_WARNING, ha, |
| 1233 | stat = RD_REG_DWORD(®->host_status); | 1328 | "Failed to dump firmware (%x)!!!\n", rval); |
| 1234 | if (stat & HSRX_RISC_INT) { | 1329 | ha->fw_dumped = 0; |
| 1235 | stat &= 0xff; | ||
| 1236 | 1330 | ||
| 1237 | if (stat == 0x1 || stat == 0x2 || | 1331 | } else { |
| 1238 | stat == 0x10 || stat == 0x11) { | 1332 | qla_printk(KERN_INFO, ha, |
| 1239 | set_bit(MBX_INTERRUPT, | 1333 | "Firmware dump saved to temp buffer (%ld/%p).\n", |
| 1240 | &ha->mbx_cmd_flags); | 1334 | ha->host_no, ha->fw_dump); |
| 1335 | ha->fw_dumped = 1; | ||
| 1336 | } | ||
| 1241 | 1337 | ||
| 1242 | mb[0] = RD_REG_WORD(®->mailbox0); | 1338 | qla24xx_fw_dump_failed: |
| 1243 | mb[2] = RD_REG_WORD(®->mailbox2); | 1339 | if (!hardware_locked) |
| 1244 | mb[3] = RD_REG_WORD(®->mailbox3); | 1340 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 1341 | } | ||
| 1245 | 1342 | ||
| 1246 | WRT_REG_DWORD(®->hccr, | 1343 | void |
| 1247 | HCCRX_CLR_RISC_INT); | 1344 | qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) |
| 1248 | RD_REG_DWORD(®->hccr); | 1345 | { |
| 1249 | break; | 1346 | int rval; |
| 1250 | } | 1347 | uint32_t cnt; |
| 1348 | uint32_t risc_address; | ||
| 1349 | uint16_t mb0, wd; | ||
| 1251 | 1350 | ||
| 1252 | /* Clear this intr; it wasn't a mailbox intr */ | 1351 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
| 1253 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | 1352 | uint32_t __iomem *dmp_reg; |
| 1254 | RD_REG_DWORD(®->hccr); | 1353 | uint32_t *iter_reg; |
| 1255 | } | 1354 | uint16_t __iomem *mbx_reg; |
| 1256 | udelay(5); | 1355 | unsigned long flags; |
| 1257 | } | 1356 | struct qla25xx_fw_dump *fw; |
| 1357 | uint32_t ext_mem_cnt; | ||
| 1358 | void *nxt; | ||
| 1258 | 1359 | ||
| 1259 | if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { | 1360 | risc_address = ext_mem_cnt = 0; |
| 1260 | rval = mb[0] & MBS_MASK; | 1361 | flags = 0; |
| 1261 | fw->code_ram[cnt] = htonl((mb[3] << 16) | mb[2]); | 1362 | |
| 1262 | } else { | 1363 | if (!hardware_locked) |
| 1263 | rval = QLA_FUNCTION_FAILED; | 1364 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 1365 | |||
| 1366 | if (!ha->fw_dump) { | ||
| 1367 | qla_printk(KERN_WARNING, ha, | ||
| 1368 | "No buffer available for dump!!!\n"); | ||
| 1369 | goto qla25xx_fw_dump_failed; | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | if (ha->fw_dumped) { | ||
| 1373 | qla_printk(KERN_WARNING, ha, | ||
| 1374 | "Firmware has been previously dumped (%p) -- ignoring " | ||
| 1375 | "request...\n", ha->fw_dump); | ||
| 1376 | goto qla25xx_fw_dump_failed; | ||
| 1377 | } | ||
| 1378 | fw = &ha->fw_dump->isp.isp25; | ||
| 1379 | qla2xxx_prep_dump(ha, ha->fw_dump); | ||
| 1380 | |||
| 1381 | rval = QLA_SUCCESS; | ||
| 1382 | fw->host_status = htonl(RD_REG_DWORD(®->host_status)); | ||
| 1383 | |||
| 1384 | /* Pause RISC. */ | ||
| 1385 | if ((RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0) { | ||
| 1386 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET | | ||
| 1387 | HCCRX_CLR_HOST_INT); | ||
| 1388 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
| 1389 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); | ||
| 1390 | for (cnt = 30000; | ||
| 1391 | (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0 && | ||
| 1392 | rval == QLA_SUCCESS; cnt--) { | ||
| 1393 | if (cnt) | ||
| 1394 | udelay(100); | ||
| 1395 | else | ||
| 1396 | rval = QLA_FUNCTION_TIMEOUT; | ||
| 1264 | } | 1397 | } |
| 1265 | } | 1398 | } |
| 1266 | 1399 | ||
| 1267 | if (rval == QLA_SUCCESS) { | 1400 | if (rval == QLA_SUCCESS) { |
| 1268 | /* External Memory. */ | 1401 | /* Host interface registers. */ |
| 1269 | risc_address = 0x100000; | 1402 | dmp_reg = (uint32_t __iomem *)(reg + 0); |
| 1270 | ext_mem_cnt = ha->fw_memory_size - 0x100000 + 1; | 1403 | for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) |
| 1271 | WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED); | 1404 | fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); |
| 1272 | clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
| 1273 | } | ||
| 1274 | for (cnt = 0; cnt < ext_mem_cnt && rval == QLA_SUCCESS; | ||
| 1275 | cnt++, risc_address++) { | ||
| 1276 | WRT_REG_WORD(®->mailbox1, LSW(risc_address)); | ||
| 1277 | WRT_REG_WORD(®->mailbox8, MSW(risc_address)); | ||
| 1278 | RD_REG_WORD(®->mailbox8); | ||
| 1279 | WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); | ||
| 1280 | 1405 | ||
| 1281 | for (timer = 6000000; timer; timer--) { | 1406 | /* Disable interrupts. */ |
| 1282 | /* Check for pending interrupts. */ | 1407 | WRT_REG_DWORD(®->ictrl, 0); |
| 1283 | stat = RD_REG_DWORD(®->host_status); | 1408 | RD_REG_DWORD(®->ictrl); |
| 1284 | if (stat & HSRX_RISC_INT) { | ||
| 1285 | stat &= 0xff; | ||
| 1286 | 1409 | ||
| 1287 | if (stat == 0x1 || stat == 0x2 || | 1410 | /* Shadow registers. */ |
| 1288 | stat == 0x10 || stat == 0x11) { | 1411 | WRT_REG_DWORD(®->iobase_addr, 0x0F70); |
| 1289 | set_bit(MBX_INTERRUPT, | 1412 | RD_REG_DWORD(®->iobase_addr); |
| 1290 | &ha->mbx_cmd_flags); | 1413 | WRT_REG_DWORD(®->iobase_select, 0xB0000000); |
| 1414 | fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
| 1291 | 1415 | ||
| 1292 | mb[0] = RD_REG_WORD(®->mailbox0); | 1416 | WRT_REG_DWORD(®->iobase_select, 0xB0100000); |
| 1293 | mb[2] = RD_REG_WORD(®->mailbox2); | 1417 | fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); |
| 1294 | mb[3] = RD_REG_WORD(®->mailbox3); | ||
| 1295 | 1418 | ||
| 1296 | WRT_REG_DWORD(®->hccr, | 1419 | WRT_REG_DWORD(®->iobase_select, 0xB0200000); |
| 1297 | HCCRX_CLR_RISC_INT); | 1420 | fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); |
| 1298 | RD_REG_DWORD(®->hccr); | ||
| 1299 | break; | ||
| 1300 | } | ||
| 1301 | 1421 | ||
| 1302 | /* Clear this intr; it wasn't a mailbox intr */ | 1422 | WRT_REG_DWORD(®->iobase_select, 0xB0300000); |
| 1303 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | 1423 | fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); |
| 1304 | RD_REG_DWORD(®->hccr); | 1424 | |
| 1305 | } | 1425 | WRT_REG_DWORD(®->iobase_select, 0xB0400000); |
| 1426 | fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
| 1427 | |||
| 1428 | WRT_REG_DWORD(®->iobase_select, 0xB0500000); | ||
| 1429 | fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
| 1430 | |||
| 1431 | WRT_REG_DWORD(®->iobase_select, 0xB0600000); | ||
| 1432 | fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
| 1433 | |||
| 1434 | WRT_REG_DWORD(®->iobase_select, 0xB0700000); | ||
| 1435 | fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
| 1436 | |||
| 1437 | WRT_REG_DWORD(®->iobase_select, 0xB0800000); | ||
| 1438 | fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
| 1439 | |||
| 1440 | WRT_REG_DWORD(®->iobase_select, 0xB0900000); | ||
| 1441 | fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
| 1442 | |||
| 1443 | WRT_REG_DWORD(®->iobase_select, 0xB0A00000); | ||
| 1444 | fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
| 1445 | |||
| 1446 | /* RISC I/O register. */ | ||
| 1447 | WRT_REG_DWORD(®->iobase_addr, 0x0010); | ||
| 1448 | RD_REG_DWORD(®->iobase_addr); | ||
| 1449 | fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window)); | ||
| 1450 | |||
| 1451 | /* Mailbox registers. */ | ||
| 1452 | mbx_reg = ®->mailbox0; | ||
| 1453 | for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) | ||
| 1454 | fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); | ||
| 1455 | |||
| 1456 | /* Transfer sequence registers. */ | ||
| 1457 | iter_reg = fw->xseq_gp_reg; | ||
| 1458 | WRT_REG_DWORD(®->iobase_addr, 0xBF00); | ||
| 1459 | dmp_reg = ®->iobase_window; | ||
| 1460 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1461 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1462 | |||
| 1463 | WRT_REG_DWORD(®->iobase_addr, 0xBF10); | ||
| 1464 | dmp_reg = ®->iobase_window; | ||
| 1465 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1466 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1467 | |||
| 1468 | WRT_REG_DWORD(®->iobase_addr, 0xBF20); | ||
| 1469 | dmp_reg = ®->iobase_window; | ||
| 1470 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1471 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1472 | |||
| 1473 | WRT_REG_DWORD(®->iobase_addr, 0xBF30); | ||
| 1474 | dmp_reg = ®->iobase_window; | ||
| 1475 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1476 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1477 | |||
| 1478 | WRT_REG_DWORD(®->iobase_addr, 0xBF40); | ||
| 1479 | dmp_reg = ®->iobase_window; | ||
| 1480 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1481 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1482 | |||
| 1483 | WRT_REG_DWORD(®->iobase_addr, 0xBF50); | ||
| 1484 | dmp_reg = ®->iobase_window; | ||
| 1485 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1486 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1487 | |||
| 1488 | WRT_REG_DWORD(®->iobase_addr, 0xBF60); | ||
| 1489 | dmp_reg = ®->iobase_window; | ||
| 1490 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1491 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1492 | |||
| 1493 | WRT_REG_DWORD(®->iobase_addr, 0xBF70); | ||
| 1494 | dmp_reg = ®->iobase_window; | ||
| 1495 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1496 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1497 | |||
| 1498 | iter_reg = fw->xseq_0_reg; | ||
| 1499 | WRT_REG_DWORD(®->iobase_addr, 0xBFC0); | ||
| 1500 | dmp_reg = ®->iobase_window; | ||
| 1501 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1502 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1503 | |||
| 1504 | WRT_REG_DWORD(®->iobase_addr, 0xBFD0); | ||
| 1505 | dmp_reg = ®->iobase_window; | ||
| 1506 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1507 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1508 | |||
| 1509 | WRT_REG_DWORD(®->iobase_addr, 0xBFE0); | ||
| 1510 | dmp_reg = ®->iobase_window; | ||
| 1511 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1512 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1513 | |||
| 1514 | WRT_REG_DWORD(®->iobase_addr, 0xBFF0); | ||
| 1515 | dmp_reg = ®->iobase_window; | ||
| 1516 | for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) | ||
| 1517 | fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1518 | |||
| 1519 | /* Receive sequence registers. */ | ||
| 1520 | iter_reg = fw->rseq_gp_reg; | ||
| 1521 | WRT_REG_DWORD(®->iobase_addr, 0xFF00); | ||
| 1522 | dmp_reg = ®->iobase_window; | ||
| 1523 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1524 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1525 | |||
| 1526 | WRT_REG_DWORD(®->iobase_addr, 0xFF10); | ||
| 1527 | dmp_reg = ®->iobase_window; | ||
| 1528 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1529 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1530 | |||
| 1531 | WRT_REG_DWORD(®->iobase_addr, 0xFF20); | ||
| 1532 | dmp_reg = ®->iobase_window; | ||
| 1533 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1534 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1535 | |||
| 1536 | WRT_REG_DWORD(®->iobase_addr, 0xFF30); | ||
| 1537 | dmp_reg = ®->iobase_window; | ||
| 1538 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1539 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1540 | |||
| 1541 | WRT_REG_DWORD(®->iobase_addr, 0xFF40); | ||
| 1542 | dmp_reg = ®->iobase_window; | ||
| 1543 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1544 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1545 | |||
| 1546 | WRT_REG_DWORD(®->iobase_addr, 0xFF50); | ||
| 1547 | dmp_reg = ®->iobase_window; | ||
| 1548 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1549 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1550 | |||
| 1551 | WRT_REG_DWORD(®->iobase_addr, 0xFF60); | ||
| 1552 | dmp_reg = ®->iobase_window; | ||
| 1553 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1554 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1555 | |||
| 1556 | WRT_REG_DWORD(®->iobase_addr, 0xFF70); | ||
| 1557 | dmp_reg = ®->iobase_window; | ||
| 1558 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1559 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1560 | |||
| 1561 | iter_reg = fw->rseq_0_reg; | ||
| 1562 | WRT_REG_DWORD(®->iobase_addr, 0xFFC0); | ||
| 1563 | dmp_reg = ®->iobase_window; | ||
| 1564 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1565 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1566 | |||
| 1567 | WRT_REG_DWORD(®->iobase_addr, 0xFFD0); | ||
| 1568 | dmp_reg = ®->iobase_window; | ||
| 1569 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1570 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1571 | |||
| 1572 | WRT_REG_DWORD(®->iobase_addr, 0xFFE0); | ||
| 1573 | dmp_reg = ®->iobase_window; | ||
| 1574 | for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) | ||
| 1575 | fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1576 | |||
| 1577 | WRT_REG_DWORD(®->iobase_addr, 0xFFF0); | ||
| 1578 | dmp_reg = ®->iobase_window; | ||
| 1579 | for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) | ||
| 1580 | fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1581 | |||
| 1582 | /* Auxiliary sequence registers. */ | ||
| 1583 | iter_reg = fw->aseq_gp_reg; | ||
| 1584 | WRT_REG_DWORD(®->iobase_addr, 0xB000); | ||
| 1585 | dmp_reg = ®->iobase_window; | ||
| 1586 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1587 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1588 | |||
| 1589 | WRT_REG_DWORD(®->iobase_addr, 0xB010); | ||
| 1590 | dmp_reg = ®->iobase_window; | ||
| 1591 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1592 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1593 | |||
| 1594 | WRT_REG_DWORD(®->iobase_addr, 0xB020); | ||
| 1595 | dmp_reg = ®->iobase_window; | ||
| 1596 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1597 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1598 | |||
| 1599 | WRT_REG_DWORD(®->iobase_addr, 0xB030); | ||
| 1600 | dmp_reg = ®->iobase_window; | ||
| 1601 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1602 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1603 | |||
| 1604 | WRT_REG_DWORD(®->iobase_addr, 0xB040); | ||
| 1605 | dmp_reg = ®->iobase_window; | ||
| 1606 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1607 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1608 | |||
| 1609 | WRT_REG_DWORD(®->iobase_addr, 0xB050); | ||
| 1610 | dmp_reg = ®->iobase_window; | ||
| 1611 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1612 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1613 | |||
| 1614 | WRT_REG_DWORD(®->iobase_addr, 0xB060); | ||
| 1615 | dmp_reg = ®->iobase_window; | ||
| 1616 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1617 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1618 | |||
| 1619 | WRT_REG_DWORD(®->iobase_addr, 0xB070); | ||
| 1620 | dmp_reg = ®->iobase_window; | ||
| 1621 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1622 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1623 | |||
| 1624 | iter_reg = fw->aseq_0_reg; | ||
| 1625 | WRT_REG_DWORD(®->iobase_addr, 0xB0C0); | ||
| 1626 | dmp_reg = ®->iobase_window; | ||
| 1627 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1628 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1629 | |||
| 1630 | WRT_REG_DWORD(®->iobase_addr, 0xB0D0); | ||
| 1631 | dmp_reg = ®->iobase_window; | ||
| 1632 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1633 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1634 | |||
| 1635 | WRT_REG_DWORD(®->iobase_addr, 0xB0E0); | ||
| 1636 | dmp_reg = ®->iobase_window; | ||
| 1637 | for (cnt = 0; cnt < sizeof(fw->aseq_1_reg) / 4; cnt++) | ||
| 1638 | fw->aseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1639 | |||
| 1640 | WRT_REG_DWORD(®->iobase_addr, 0xB0F0); | ||
| 1641 | dmp_reg = ®->iobase_window; | ||
| 1642 | for (cnt = 0; cnt < sizeof(fw->aseq_2_reg) / 4; cnt++) | ||
| 1643 | fw->aseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1644 | |||
| 1645 | /* Command DMA registers. */ | ||
| 1646 | WRT_REG_DWORD(®->iobase_addr, 0x7100); | ||
| 1647 | dmp_reg = ®->iobase_window; | ||
| 1648 | for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) | ||
| 1649 | fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1650 | |||
| 1651 | /* Queues. */ | ||
| 1652 | iter_reg = fw->req0_dma_reg; | ||
| 1653 | WRT_REG_DWORD(®->iobase_addr, 0x7200); | ||
| 1654 | dmp_reg = ®->iobase_window; | ||
| 1655 | for (cnt = 0; cnt < 8; cnt++) | ||
| 1656 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1657 | |||
| 1658 | dmp_reg = ®->iobase_q; | ||
| 1659 | for (cnt = 0; cnt < 7; cnt++) | ||
| 1660 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1661 | |||
| 1662 | iter_reg = fw->resp0_dma_reg; | ||
| 1663 | WRT_REG_DWORD(®->iobase_addr, 0x7300); | ||
| 1664 | dmp_reg = ®->iobase_window; | ||
| 1665 | for (cnt = 0; cnt < 8; cnt++) | ||
| 1666 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1667 | |||
| 1668 | dmp_reg = ®->iobase_q; | ||
| 1669 | for (cnt = 0; cnt < 7; cnt++) | ||
| 1670 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1671 | |||
| 1672 | iter_reg = fw->req1_dma_reg; | ||
| 1673 | WRT_REG_DWORD(®->iobase_addr, 0x7400); | ||
| 1674 | dmp_reg = ®->iobase_window; | ||
| 1675 | for (cnt = 0; cnt < 8; cnt++) | ||
| 1676 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1677 | |||
| 1678 | dmp_reg = ®->iobase_q; | ||
| 1679 | for (cnt = 0; cnt < 7; cnt++) | ||
| 1680 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1681 | |||
| 1682 | /* Transmit DMA registers. */ | ||
| 1683 | iter_reg = fw->xmt0_dma_reg; | ||
| 1684 | WRT_REG_DWORD(®->iobase_addr, 0x7600); | ||
| 1685 | dmp_reg = ®->iobase_window; | ||
| 1686 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1687 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1688 | |||
| 1689 | WRT_REG_DWORD(®->iobase_addr, 0x7610); | ||
| 1690 | dmp_reg = ®->iobase_window; | ||
| 1691 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1692 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1693 | |||
| 1694 | iter_reg = fw->xmt1_dma_reg; | ||
| 1695 | WRT_REG_DWORD(®->iobase_addr, 0x7620); | ||
| 1696 | dmp_reg = ®->iobase_window; | ||
| 1697 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1698 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1699 | |||
| 1700 | WRT_REG_DWORD(®->iobase_addr, 0x7630); | ||
| 1701 | dmp_reg = ®->iobase_window; | ||
| 1702 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1703 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1704 | |||
| 1705 | iter_reg = fw->xmt2_dma_reg; | ||
| 1706 | WRT_REG_DWORD(®->iobase_addr, 0x7640); | ||
| 1707 | dmp_reg = ®->iobase_window; | ||
| 1708 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1709 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1710 | |||
| 1711 | WRT_REG_DWORD(®->iobase_addr, 0x7650); | ||
| 1712 | dmp_reg = ®->iobase_window; | ||
| 1713 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1714 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1715 | |||
| 1716 | iter_reg = fw->xmt3_dma_reg; | ||
| 1717 | WRT_REG_DWORD(®->iobase_addr, 0x7660); | ||
| 1718 | dmp_reg = ®->iobase_window; | ||
| 1719 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1720 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1721 | |||
| 1722 | WRT_REG_DWORD(®->iobase_addr, 0x7670); | ||
| 1723 | dmp_reg = ®->iobase_window; | ||
| 1724 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1725 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1726 | |||
| 1727 | iter_reg = fw->xmt4_dma_reg; | ||
| 1728 | WRT_REG_DWORD(®->iobase_addr, 0x7680); | ||
| 1729 | dmp_reg = ®->iobase_window; | ||
| 1730 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1731 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1732 | |||
| 1733 | WRT_REG_DWORD(®->iobase_addr, 0x7690); | ||
| 1734 | dmp_reg = ®->iobase_window; | ||
| 1735 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1736 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1737 | |||
| 1738 | WRT_REG_DWORD(®->iobase_addr, 0x76A0); | ||
| 1739 | dmp_reg = ®->iobase_window; | ||
| 1740 | for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) | ||
| 1741 | fw->xmt_data_dma_reg[cnt] = | ||
| 1742 | htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1743 | |||
| 1744 | /* Receive DMA registers. */ | ||
| 1745 | iter_reg = fw->rcvt0_data_dma_reg; | ||
| 1746 | WRT_REG_DWORD(®->iobase_addr, 0x7700); | ||
| 1747 | dmp_reg = ®->iobase_window; | ||
| 1748 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1749 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1750 | |||
| 1751 | WRT_REG_DWORD(®->iobase_addr, 0x7710); | ||
| 1752 | dmp_reg = ®->iobase_window; | ||
| 1753 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1754 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1755 | |||
| 1756 | iter_reg = fw->rcvt1_data_dma_reg; | ||
| 1757 | WRT_REG_DWORD(®->iobase_addr, 0x7720); | ||
| 1758 | dmp_reg = ®->iobase_window; | ||
| 1759 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1760 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1761 | |||
| 1762 | WRT_REG_DWORD(®->iobase_addr, 0x7730); | ||
| 1763 | dmp_reg = ®->iobase_window; | ||
| 1764 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1765 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1766 | |||
| 1767 | /* RISC registers. */ | ||
| 1768 | iter_reg = fw->risc_gp_reg; | ||
| 1769 | WRT_REG_DWORD(®->iobase_addr, 0x0F00); | ||
| 1770 | dmp_reg = ®->iobase_window; | ||
| 1771 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1772 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1773 | |||
| 1774 | WRT_REG_DWORD(®->iobase_addr, 0x0F10); | ||
| 1775 | dmp_reg = ®->iobase_window; | ||
| 1776 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1777 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1778 | |||
| 1779 | WRT_REG_DWORD(®->iobase_addr, 0x0F20); | ||
| 1780 | dmp_reg = ®->iobase_window; | ||
| 1781 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1782 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1783 | |||
| 1784 | WRT_REG_DWORD(®->iobase_addr, 0x0F30); | ||
| 1785 | dmp_reg = ®->iobase_window; | ||
| 1786 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1787 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1788 | |||
| 1789 | WRT_REG_DWORD(®->iobase_addr, 0x0F40); | ||
| 1790 | dmp_reg = ®->iobase_window; | ||
| 1791 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1792 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1793 | |||
| 1794 | WRT_REG_DWORD(®->iobase_addr, 0x0F50); | ||
| 1795 | dmp_reg = ®->iobase_window; | ||
| 1796 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1797 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1798 | |||
| 1799 | WRT_REG_DWORD(®->iobase_addr, 0x0F60); | ||
| 1800 | dmp_reg = ®->iobase_window; | ||
| 1801 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1802 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1803 | |||
| 1804 | WRT_REG_DWORD(®->iobase_addr, 0x0F70); | ||
| 1805 | dmp_reg = ®->iobase_window; | ||
| 1806 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1807 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1808 | |||
| 1809 | /* Local memory controller registers. */ | ||
| 1810 | iter_reg = fw->lmc_reg; | ||
| 1811 | WRT_REG_DWORD(®->iobase_addr, 0x3000); | ||
| 1812 | dmp_reg = ®->iobase_window; | ||
| 1813 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1814 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1815 | |||
| 1816 | WRT_REG_DWORD(®->iobase_addr, 0x3010); | ||
| 1817 | dmp_reg = ®->iobase_window; | ||
| 1818 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1819 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1820 | |||
| 1821 | WRT_REG_DWORD(®->iobase_addr, 0x3020); | ||
| 1822 | dmp_reg = ®->iobase_window; | ||
| 1823 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1824 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1825 | |||
| 1826 | WRT_REG_DWORD(®->iobase_addr, 0x3030); | ||
| 1827 | dmp_reg = ®->iobase_window; | ||
| 1828 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1829 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1830 | |||
| 1831 | WRT_REG_DWORD(®->iobase_addr, 0x3040); | ||
| 1832 | dmp_reg = ®->iobase_window; | ||
| 1833 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1834 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1835 | |||
| 1836 | WRT_REG_DWORD(®->iobase_addr, 0x3050); | ||
| 1837 | dmp_reg = ®->iobase_window; | ||
| 1838 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1839 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1840 | |||
| 1841 | WRT_REG_DWORD(®->iobase_addr, 0x3060); | ||
| 1842 | dmp_reg = ®->iobase_window; | ||
| 1843 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1844 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1845 | |||
| 1846 | WRT_REG_DWORD(®->iobase_addr, 0x3070); | ||
| 1847 | dmp_reg = ®->iobase_window; | ||
| 1848 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1849 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1850 | |||
| 1851 | /* Fibre Protocol Module registers. */ | ||
| 1852 | iter_reg = fw->fpm_hdw_reg; | ||
| 1853 | WRT_REG_DWORD(®->iobase_addr, 0x4000); | ||
| 1854 | dmp_reg = ®->iobase_window; | ||
| 1855 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1856 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1857 | |||
| 1858 | WRT_REG_DWORD(®->iobase_addr, 0x4010); | ||
| 1859 | dmp_reg = ®->iobase_window; | ||
| 1860 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1861 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1862 | |||
| 1863 | WRT_REG_DWORD(®->iobase_addr, 0x4020); | ||
| 1864 | dmp_reg = ®->iobase_window; | ||
| 1865 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1866 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1867 | |||
| 1868 | WRT_REG_DWORD(®->iobase_addr, 0x4030); | ||
| 1869 | dmp_reg = ®->iobase_window; | ||
| 1870 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1871 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1872 | |||
| 1873 | WRT_REG_DWORD(®->iobase_addr, 0x4040); | ||
| 1874 | dmp_reg = ®->iobase_window; | ||
| 1875 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1876 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1877 | |||
| 1878 | WRT_REG_DWORD(®->iobase_addr, 0x4050); | ||
| 1879 | dmp_reg = ®->iobase_window; | ||
| 1880 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1881 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1882 | |||
| 1883 | WRT_REG_DWORD(®->iobase_addr, 0x4060); | ||
| 1884 | dmp_reg = ®->iobase_window; | ||
| 1885 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1886 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1887 | |||
| 1888 | WRT_REG_DWORD(®->iobase_addr, 0x4070); | ||
| 1889 | dmp_reg = ®->iobase_window; | ||
| 1890 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1891 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1892 | |||
| 1893 | WRT_REG_DWORD(®->iobase_addr, 0x4080); | ||
| 1894 | dmp_reg = ®->iobase_window; | ||
| 1895 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1896 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1897 | |||
| 1898 | WRT_REG_DWORD(®->iobase_addr, 0x4090); | ||
| 1899 | dmp_reg = ®->iobase_window; | ||
| 1900 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1901 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1902 | |||
| 1903 | WRT_REG_DWORD(®->iobase_addr, 0x40A0); | ||
| 1904 | dmp_reg = ®->iobase_window; | ||
| 1905 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1906 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1907 | |||
| 1908 | WRT_REG_DWORD(®->iobase_addr, 0x40B0); | ||
| 1909 | dmp_reg = ®->iobase_window; | ||
| 1910 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1911 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1912 | |||
| 1913 | /* Frame Buffer registers. */ | ||
| 1914 | iter_reg = fw->fb_hdw_reg; | ||
| 1915 | WRT_REG_DWORD(®->iobase_addr, 0x6000); | ||
| 1916 | dmp_reg = ®->iobase_window; | ||
| 1917 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1918 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1919 | |||
| 1920 | WRT_REG_DWORD(®->iobase_addr, 0x6010); | ||
| 1921 | dmp_reg = ®->iobase_window; | ||
| 1922 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1923 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1924 | |||
| 1925 | WRT_REG_DWORD(®->iobase_addr, 0x6020); | ||
| 1926 | dmp_reg = ®->iobase_window; | ||
| 1927 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1928 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1929 | |||
| 1930 | WRT_REG_DWORD(®->iobase_addr, 0x6030); | ||
| 1931 | dmp_reg = ®->iobase_window; | ||
| 1932 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1933 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1934 | |||
| 1935 | WRT_REG_DWORD(®->iobase_addr, 0x6040); | ||
| 1936 | dmp_reg = ®->iobase_window; | ||
| 1937 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1938 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1939 | |||
| 1940 | WRT_REG_DWORD(®->iobase_addr, 0x6100); | ||
| 1941 | dmp_reg = ®->iobase_window; | ||
| 1942 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1943 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1944 | |||
| 1945 | WRT_REG_DWORD(®->iobase_addr, 0x6130); | ||
| 1946 | dmp_reg = ®->iobase_window; | ||
| 1947 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1948 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1949 | |||
| 1950 | WRT_REG_DWORD(®->iobase_addr, 0x6150); | ||
| 1951 | dmp_reg = ®->iobase_window; | ||
| 1952 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1953 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1954 | |||
| 1955 | WRT_REG_DWORD(®->iobase_addr, 0x6170); | ||
| 1956 | dmp_reg = ®->iobase_window; | ||
| 1957 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1958 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1959 | |||
| 1960 | WRT_REG_DWORD(®->iobase_addr, 0x6190); | ||
| 1961 | dmp_reg = ®->iobase_window; | ||
| 1962 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1963 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1964 | |||
| 1965 | WRT_REG_DWORD(®->iobase_addr, 0x61B0); | ||
| 1966 | dmp_reg = ®->iobase_window; | ||
| 1967 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1968 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1969 | |||
| 1970 | WRT_REG_DWORD(®->iobase_addr, 0x6F00); | ||
| 1971 | dmp_reg = ®->iobase_window; | ||
| 1972 | for (cnt = 0; cnt < 16; cnt++) | ||
| 1973 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
| 1974 | |||
| 1975 | /* Reset RISC. */ | ||
| 1976 | WRT_REG_DWORD(®->ctrl_status, | ||
| 1977 | CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); | ||
| 1978 | for (cnt = 0; cnt < 30000; cnt++) { | ||
| 1979 | if ((RD_REG_DWORD(®->ctrl_status) & | ||
| 1980 | CSRX_DMA_ACTIVE) == 0) | ||
| 1981 | break; | ||
| 1982 | |||
| 1983 | udelay(10); | ||
| 1984 | } | ||
| 1985 | |||
| 1986 | WRT_REG_DWORD(®->ctrl_status, | ||
| 1987 | CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); | ||
| 1988 | pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); | ||
| 1989 | |||
| 1990 | udelay(100); | ||
| 1991 | /* Wait for firmware to complete NVRAM accesses. */ | ||
| 1992 | mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); | ||
| 1993 | for (cnt = 10000 ; cnt && mb0; cnt--) { | ||
| 1306 | udelay(5); | 1994 | udelay(5); |
| 1995 | mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); | ||
| 1996 | barrier(); | ||
| 1307 | } | 1997 | } |
| 1308 | 1998 | ||
| 1309 | if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { | 1999 | /* Wait for soft-reset to complete. */ |
| 1310 | rval = mb[0] & MBS_MASK; | 2000 | for (cnt = 0; cnt < 30000; cnt++) { |
| 1311 | fw->ext_mem[cnt] = htonl((mb[3] << 16) | mb[2]); | 2001 | if ((RD_REG_DWORD(®->ctrl_status) & |
| 1312 | } else { | 2002 | CSRX_ISP_SOFT_RESET) == 0) |
| 1313 | rval = QLA_FUNCTION_FAILED; | 2003 | break; |
| 2004 | |||
| 2005 | udelay(10); | ||
| 1314 | } | 2006 | } |
| 2007 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); | ||
| 2008 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
| 1315 | } | 2009 | } |
| 1316 | 2010 | ||
| 2011 | for (cnt = 30000; RD_REG_WORD(®->mailbox0) != 0 && | ||
| 2012 | rval == QLA_SUCCESS; cnt--) { | ||
| 2013 | if (cnt) | ||
| 2014 | udelay(100); | ||
| 2015 | else | ||
| 2016 | rval = QLA_FUNCTION_TIMEOUT; | ||
| 2017 | } | ||
| 2018 | |||
| 2019 | if (rval == QLA_SUCCESS) | ||
| 2020 | rval = qla2xxx_dump_memory(ha, fw->code_ram, | ||
| 2021 | sizeof(fw->code_ram), fw->ext_mem, &nxt); | ||
| 2022 | |||
| 1317 | if (rval == QLA_SUCCESS) { | 2023 | if (rval == QLA_SUCCESS) { |
| 1318 | eft = qla2xxx_copy_queues(ha, &fw->ext_mem[cnt]); | 2024 | nxt = qla2xxx_copy_queues(ha, nxt); |
| 1319 | if (ha->eft) | 2025 | if (ha->eft) |
| 1320 | memcpy(eft, ha->eft, ntohl(ha->fw_dump->eft_size)); | 2026 | memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); |
| 1321 | } | 2027 | } |
| 1322 | 2028 | ||
| 1323 | if (rval != QLA_SUCCESS) { | 2029 | if (rval != QLA_SUCCESS) { |
| @@ -1332,7 +2038,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
| 1332 | ha->fw_dumped = 1; | 2038 | ha->fw_dumped = 1; |
| 1333 | } | 2039 | } |
| 1334 | 2040 | ||
| 1335 | qla24xx_fw_dump_failed: | 2041 | qla25xx_fw_dump_failed: |
| 1336 | if (!hardware_locked) | 2042 | if (!hardware_locked) |
| 1337 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 2043 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 1338 | } | 2044 | } |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 49dffeb78512..cca4b0d8253e 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
| @@ -213,6 +213,43 @@ struct qla24xx_fw_dump { | |||
| 213 | uint32_t ext_mem[1]; | 213 | uint32_t ext_mem[1]; |
| 214 | }; | 214 | }; |
| 215 | 215 | ||
| 216 | struct qla25xx_fw_dump { | ||
| 217 | uint32_t host_status; | ||
| 218 | uint32_t host_reg[32]; | ||
| 219 | uint32_t shadow_reg[11]; | ||
| 220 | uint32_t risc_io_reg; | ||
| 221 | uint16_t mailbox_reg[32]; | ||
| 222 | uint32_t xseq_gp_reg[128]; | ||
| 223 | uint32_t xseq_0_reg[48]; | ||
| 224 | uint32_t xseq_1_reg[16]; | ||
| 225 | uint32_t rseq_gp_reg[128]; | ||
| 226 | uint32_t rseq_0_reg[32]; | ||
| 227 | uint32_t rseq_1_reg[16]; | ||
| 228 | uint32_t rseq_2_reg[16]; | ||
| 229 | uint32_t aseq_gp_reg[128]; | ||
| 230 | uint32_t aseq_0_reg[32]; | ||
| 231 | uint32_t aseq_1_reg[16]; | ||
| 232 | uint32_t aseq_2_reg[16]; | ||
| 233 | uint32_t cmd_dma_reg[16]; | ||
| 234 | uint32_t req0_dma_reg[15]; | ||
| 235 | uint32_t resp0_dma_reg[15]; | ||
| 236 | uint32_t req1_dma_reg[15]; | ||
| 237 | uint32_t xmt0_dma_reg[32]; | ||
| 238 | uint32_t xmt1_dma_reg[32]; | ||
| 239 | uint32_t xmt2_dma_reg[32]; | ||
| 240 | uint32_t xmt3_dma_reg[32]; | ||
| 241 | uint32_t xmt4_dma_reg[32]; | ||
| 242 | uint32_t xmt_data_dma_reg[16]; | ||
| 243 | uint32_t rcvt0_data_dma_reg[32]; | ||
| 244 | uint32_t rcvt1_data_dma_reg[32]; | ||
| 245 | uint32_t risc_gp_reg[128]; | ||
| 246 | uint32_t lmc_reg[128]; | ||
| 247 | uint32_t fpm_hdw_reg[192]; | ||
| 248 | uint32_t fb_hdw_reg[192]; | ||
| 249 | uint32_t code_ram[0x2000]; | ||
| 250 | uint32_t ext_mem[1]; | ||
| 251 | }; | ||
| 252 | |||
| 216 | #define EFT_NUM_BUFFERS 4 | 253 | #define EFT_NUM_BUFFERS 4 |
| 217 | #define EFT_BYTES_PER_BUFFER 0x4000 | 254 | #define EFT_BYTES_PER_BUFFER 0x4000 |
| 218 | #define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS)) | 255 | #define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS)) |
| @@ -246,5 +283,6 @@ struct qla2xxx_fw_dump { | |||
| 246 | struct qla2100_fw_dump isp21; | 283 | struct qla2100_fw_dump isp21; |
| 247 | struct qla2300_fw_dump isp23; | 284 | struct qla2300_fw_dump isp23; |
| 248 | struct qla24xx_fw_dump isp24; | 285 | struct qla24xx_fw_dump isp24; |
| 286 | struct qla25xx_fw_dump isp25; | ||
| 249 | } isp; | 287 | } isp; |
| 250 | }; | 288 | }; |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index a1ca590ba447..0c9f36c8a248 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
| @@ -1711,6 +1711,14 @@ struct ct_fdmi_hba_attributes { | |||
| 1711 | #define FDMI_PORT_OS_DEVICE_NAME 5 | 1711 | #define FDMI_PORT_OS_DEVICE_NAME 5 |
| 1712 | #define FDMI_PORT_HOST_NAME 6 | 1712 | #define FDMI_PORT_HOST_NAME 6 |
| 1713 | 1713 | ||
| 1714 | #define FDMI_PORT_SPEED_1GB 0x1 | ||
| 1715 | #define FDMI_PORT_SPEED_2GB 0x2 | ||
| 1716 | #define FDMI_PORT_SPEED_10GB 0x4 | ||
| 1717 | #define FDMI_PORT_SPEED_4GB 0x8 | ||
| 1718 | #define FDMI_PORT_SPEED_8GB 0x10 | ||
| 1719 | #define FDMI_PORT_SPEED_16GB 0x20 | ||
| 1720 | #define FDMI_PORT_SPEED_UNKNOWN 0x8000 | ||
| 1721 | |||
| 1714 | struct ct_fdmi_port_attr { | 1722 | struct ct_fdmi_port_attr { |
| 1715 | uint16_t type; | 1723 | uint16_t type; |
| 1716 | uint16_t len; | 1724 | uint16_t len; |
| @@ -2201,6 +2209,7 @@ typedef struct scsi_qla_host { | |||
| 2201 | #define SWITCH_FOUND BIT_3 | 2209 | #define SWITCH_FOUND BIT_3 |
| 2202 | #define DFLG_NO_CABLE BIT_4 | 2210 | #define DFLG_NO_CABLE BIT_4 |
| 2203 | 2211 | ||
| 2212 | #define PCI_DEVICE_ID_QLOGIC_ISP2532 0x2532 | ||
| 2204 | uint32_t device_type; | 2213 | uint32_t device_type; |
| 2205 | #define DT_ISP2100 BIT_0 | 2214 | #define DT_ISP2100 BIT_0 |
| 2206 | #define DT_ISP2200 BIT_1 | 2215 | #define DT_ISP2200 BIT_1 |
| @@ -2213,8 +2222,11 @@ typedef struct scsi_qla_host { | |||
| 2213 | #define DT_ISP2432 BIT_8 | 2222 | #define DT_ISP2432 BIT_8 |
| 2214 | #define DT_ISP5422 BIT_9 | 2223 | #define DT_ISP5422 BIT_9 |
| 2215 | #define DT_ISP5432 BIT_10 | 2224 | #define DT_ISP5432 BIT_10 |
| 2216 | #define DT_ISP_LAST (DT_ISP5432 << 1) | 2225 | #define DT_ISP2532 BIT_11 |
| 2226 | #define DT_ISP_LAST (DT_ISP2532 << 1) | ||
| 2217 | 2227 | ||
| 2228 | #define DT_IIDMA BIT_26 | ||
| 2229 | #define DT_FWI2 BIT_27 | ||
| 2218 | #define DT_ZIO_SUPPORTED BIT_28 | 2230 | #define DT_ZIO_SUPPORTED BIT_28 |
| 2219 | #define DT_OEM_001 BIT_29 | 2231 | #define DT_OEM_001 BIT_29 |
| 2220 | #define DT_ISP2200A BIT_30 | 2232 | #define DT_ISP2200A BIT_30 |
| @@ -2232,12 +2244,16 @@ typedef struct scsi_qla_host { | |||
| 2232 | #define IS_QLA2432(ha) (DT_MASK(ha) & DT_ISP2432) | 2244 | #define IS_QLA2432(ha) (DT_MASK(ha) & DT_ISP2432) |
| 2233 | #define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422) | 2245 | #define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422) |
| 2234 | #define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432) | 2246 | #define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432) |
| 2247 | #define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532) | ||
| 2235 | 2248 | ||
| 2236 | #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ | 2249 | #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ |
| 2237 | IS_QLA6312(ha) || IS_QLA6322(ha)) | 2250 | IS_QLA6312(ha) || IS_QLA6322(ha)) |
| 2238 | #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) | 2251 | #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) |
| 2239 | #define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha)) | 2252 | #define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha)) |
| 2253 | #define IS_QLA25XX(ha) (IS_QLA2532(ha)) | ||
| 2240 | 2254 | ||
| 2255 | #define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA) | ||
| 2256 | #define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2) | ||
| 2241 | #define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED) | 2257 | #define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED) |
| 2242 | #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001) | 2258 | #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001) |
| 2243 | #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) | 2259 | #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) |
| @@ -2274,7 +2290,7 @@ typedef struct scsi_qla_host { | |||
| 2274 | uint16_t rsp_ring_index; /* Current index. */ | 2290 | uint16_t rsp_ring_index; /* Current index. */ |
| 2275 | uint16_t response_q_length; | 2291 | uint16_t response_q_length; |
| 2276 | 2292 | ||
| 2277 | struct isp_operations isp_ops; | 2293 | struct isp_operations *isp_ops; |
| 2278 | 2294 | ||
| 2279 | /* Outstandings ISP commands. */ | 2295 | /* Outstandings ISP commands. */ |
| 2280 | srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; | 2296 | srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; |
| @@ -2298,6 +2314,7 @@ typedef struct scsi_qla_host { | |||
| 2298 | #define PORT_SPEED_1GB 0x00 | 2314 | #define PORT_SPEED_1GB 0x00 |
| 2299 | #define PORT_SPEED_2GB 0x01 | 2315 | #define PORT_SPEED_2GB 0x01 |
| 2300 | #define PORT_SPEED_4GB 0x03 | 2316 | #define PORT_SPEED_4GB 0x03 |
| 2317 | #define PORT_SPEED_8GB 0x04 | ||
| 2301 | uint16_t link_data_rate; /* F/W operating speed */ | 2318 | uint16_t link_data_rate; /* F/W operating speed */ |
| 2302 | 2319 | ||
| 2303 | uint8_t current_topology; | 2320 | uint8_t current_topology; |
| @@ -2564,6 +2581,7 @@ typedef struct scsi_qla_host { | |||
| 2564 | #define OPTROM_SIZE_2300 0x20000 | 2581 | #define OPTROM_SIZE_2300 0x20000 |
| 2565 | #define OPTROM_SIZE_2322 0x100000 | 2582 | #define OPTROM_SIZE_2322 0x100000 |
| 2566 | #define OPTROM_SIZE_24XX 0x100000 | 2583 | #define OPTROM_SIZE_24XX 0x100000 |
| 2584 | #define OPTROM_SIZE_25XX 0x200000 | ||
| 2567 | 2585 | ||
| 2568 | #include "qla_gbl.h" | 2586 | #include "qla_gbl.h" |
| 2569 | #include "qla_dbg.h" | 2587 | #include "qla_dbg.h" |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 63a11fef5d1b..99fe49618d61 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
| @@ -8,14 +8,17 @@ | |||
| 8 | #define __QLA_FW_H | 8 | #define __QLA_FW_H |
| 9 | 9 | ||
| 10 | #define MBS_CHECKSUM_ERROR 0x4010 | 10 | #define MBS_CHECKSUM_ERROR 0x4010 |
| 11 | #define MBS_INVALID_PRODUCT_KEY 0x4020 | ||
| 11 | 12 | ||
| 12 | /* | 13 | /* |
| 13 | * Firmware Options. | 14 | * Firmware Options. |
| 14 | */ | 15 | */ |
| 15 | #define FO1_ENABLE_PUREX BIT_10 | 16 | #define FO1_ENABLE_PUREX BIT_10 |
| 16 | #define FO1_DISABLE_LED_CTRL BIT_6 | 17 | #define FO1_DISABLE_LED_CTRL BIT_6 |
| 18 | #define FO1_ENABLE_8016 BIT_0 | ||
| 17 | #define FO2_ENABLE_SEL_CLASS2 BIT_5 | 19 | #define FO2_ENABLE_SEL_CLASS2 BIT_5 |
| 18 | #define FO3_NO_ABTS_ON_LINKDOWN BIT_14 | 20 | #define FO3_NO_ABTS_ON_LINKDOWN BIT_14 |
| 21 | #define FO3_HOLD_STS_IOCB BIT_12 | ||
| 19 | 22 | ||
| 20 | /* | 23 | /* |
| 21 | * Port Database structure definition for ISP 24xx. | 24 | * Port Database structure definition for ISP 24xx. |
| @@ -341,7 +344,9 @@ struct init_cb_24xx { | |||
| 341 | * BIT 10 = Reserved | 344 | * BIT 10 = Reserved |
| 342 | * BIT 11 = Enable FC-SP Security | 345 | * BIT 11 = Enable FC-SP Security |
| 343 | * BIT 12 = FC Tape Enable | 346 | * BIT 12 = FC Tape Enable |
| 344 | * BIT 13-31 = Reserved | 347 | * BIT 13 = Reserved |
| 348 | * BIT 14 = Enable Target PRLI Control | ||
| 349 | * BIT 15-31 = Reserved | ||
| 345 | */ | 350 | */ |
| 346 | uint32_t firmware_options_2; | 351 | uint32_t firmware_options_2; |
| 347 | 352 | ||
| @@ -363,7 +368,8 @@ struct init_cb_24xx { | |||
| 363 | * BIT 13 = Data Rate bit 0 | 368 | * BIT 13 = Data Rate bit 0 |
| 364 | * BIT 14 = Data Rate bit 1 | 369 | * BIT 14 = Data Rate bit 1 |
| 365 | * BIT 15 = Data Rate bit 2 | 370 | * BIT 15 = Data Rate bit 2 |
| 366 | * BIT 16-31 = Reserved | 371 | * BIT 16 = Enable 75 ohm Termination Select |
| 372 | * BIT 17-31 = Reserved | ||
| 367 | */ | 373 | */ |
| 368 | uint32_t firmware_options_3; | 374 | uint32_t firmware_options_3; |
| 369 | 375 | ||
| @@ -435,6 +441,7 @@ struct cmd_type_7 { | |||
| 435 | #define TMF_LUN_RESET BIT_12 | 441 | #define TMF_LUN_RESET BIT_12 |
| 436 | #define TMF_CLEAR_TASK_SET BIT_10 | 442 | #define TMF_CLEAR_TASK_SET BIT_10 |
| 437 | #define TMF_ABORT_TASK_SET BIT_9 | 443 | #define TMF_ABORT_TASK_SET BIT_9 |
| 444 | #define TMF_DSD_LIST_ENABLE BIT_2 | ||
| 438 | #define TMF_READ_DATA BIT_1 | 445 | #define TMF_READ_DATA BIT_1 |
| 439 | #define TMF_WRITE_DATA BIT_0 | 446 | #define TMF_WRITE_DATA BIT_0 |
| 440 | 447 | ||
| @@ -589,7 +596,7 @@ struct els_entry_24xx { | |||
| 589 | #define EST_SOFI3 (1 << 4) | 596 | #define EST_SOFI3 (1 << 4) |
| 590 | #define EST_SOFI2 (3 << 4) | 597 | #define EST_SOFI2 (3 << 4) |
| 591 | 598 | ||
| 592 | uint32_t rx_xchg_address[2]; /* Receive exchange address. */ | 599 | uint32_t rx_xchg_address; /* Receive exchange address. */ |
| 593 | uint16_t rx_dsd_count; | 600 | uint16_t rx_dsd_count; |
| 594 | 601 | ||
| 595 | uint8_t opcode; | 602 | uint8_t opcode; |
| @@ -650,6 +657,7 @@ struct logio_entry_24xx { | |||
| 650 | 657 | ||
| 651 | uint16_t control_flags; /* Control flags. */ | 658 | uint16_t control_flags; /* Control flags. */ |
| 652 | /* Modifiers. */ | 659 | /* Modifiers. */ |
| 660 | #define LCF_INCLUDE_SNS BIT_10 /* Include SNS (FFFFFC) during LOGO. */ | ||
| 653 | #define LCF_FCP2_OVERRIDE BIT_9 /* Set/Reset word 3 of PRLI. */ | 661 | #define LCF_FCP2_OVERRIDE BIT_9 /* Set/Reset word 3 of PRLI. */ |
| 654 | #define LCF_CLASS_2 BIT_8 /* Enable class 2 during PLOGI. */ | 662 | #define LCF_CLASS_2 BIT_8 /* Enable class 2 during PLOGI. */ |
| 655 | #define LCF_FREE_NPORT BIT_7 /* Release NPORT handle after LOGO. */ | 663 | #define LCF_FREE_NPORT BIT_7 /* Release NPORT handle after LOGO. */ |
| @@ -779,6 +787,15 @@ struct device_reg_24xx { | |||
| 779 | #define FA_RISC_CODE_ADDR 0x20000 | 787 | #define FA_RISC_CODE_ADDR 0x20000 |
| 780 | #define FA_RISC_CODE_SEGMENTS 2 | 788 | #define FA_RISC_CODE_SEGMENTS 2 |
| 781 | 789 | ||
| 790 | #define FA_FW_AREA_ADDR 0x40000 | ||
| 791 | #define FA_VPD_NVRAM_ADDR 0x48000 | ||
| 792 | #define FA_FEATURE_ADDR 0x4C000 | ||
| 793 | #define FA_FLASH_DESCR_ADDR 0x50000 | ||
| 794 | #define FA_HW_EVENT_ADDR 0x54000 | ||
| 795 | #define FA_BOOT_LOG_ADDR 0x58000 | ||
| 796 | #define FA_FW_DUMP0_ADDR 0x60000 | ||
| 797 | #define FA_FW_DUMP1_ADDR 0x70000 | ||
| 798 | |||
| 782 | uint32_t flash_data; /* Flash/NVRAM BIOS data. */ | 799 | uint32_t flash_data; /* Flash/NVRAM BIOS data. */ |
| 783 | 800 | ||
| 784 | uint32_t ctrl_status; /* Control/Status. */ | 801 | uint32_t ctrl_status; /* Control/Status. */ |
| @@ -859,10 +876,13 @@ struct device_reg_24xx { | |||
| 859 | #define HCCRX_CLR_RISC_INT 0xA0000000 | 876 | #define HCCRX_CLR_RISC_INT 0xA0000000 |
| 860 | 877 | ||
| 861 | uint32_t gpiod; /* GPIO Data register. */ | 878 | uint32_t gpiod; /* GPIO Data register. */ |
| 879 | |||
| 862 | /* LED update mask. */ | 880 | /* LED update mask. */ |
| 863 | #define GPDX_LED_UPDATE_MASK (BIT_20|BIT_19|BIT_18) | 881 | #define GPDX_LED_UPDATE_MASK (BIT_20|BIT_19|BIT_18) |
| 864 | /* Data update mask. */ | 882 | /* Data update mask. */ |
| 865 | #define GPDX_DATA_UPDATE_MASK (BIT_17|BIT_16) | 883 | #define GPDX_DATA_UPDATE_MASK (BIT_17|BIT_16) |
| 884 | /* Data update mask. */ | ||
| 885 | #define GPDX_DATA_UPDATE_2_MASK (BIT_28|BIT_27|BIT_26|BIT_17|BIT_16) | ||
| 866 | /* LED control mask. */ | 886 | /* LED control mask. */ |
| 867 | #define GPDX_LED_COLOR_MASK (BIT_4|BIT_3|BIT_2) | 887 | #define GPDX_LED_COLOR_MASK (BIT_4|BIT_3|BIT_2) |
| 868 | /* LED bit values. Color names as | 888 | /* LED bit values. Color names as |
| @@ -877,6 +897,8 @@ struct device_reg_24xx { | |||
| 877 | uint32_t gpioe; /* GPIO Enable register. */ | 897 | uint32_t gpioe; /* GPIO Enable register. */ |
| 878 | /* Enable update mask. */ | 898 | /* Enable update mask. */ |
| 879 | #define GPEX_ENABLE_UPDATE_MASK (BIT_17|BIT_16) | 899 | #define GPEX_ENABLE_UPDATE_MASK (BIT_17|BIT_16) |
| 900 | /* Enable update mask. */ | ||
| 901 | #define GPEX_ENABLE_UPDATE_2_MASK (BIT_28|BIT_27|BIT_26|BIT_17|BIT_16) | ||
| 880 | /* Enable. */ | 902 | /* Enable. */ |
| 881 | #define GPEX_ENABLE (BIT_1|BIT_0) | 903 | #define GPEX_ENABLE (BIT_1|BIT_0) |
| 882 | 904 | ||
| @@ -916,6 +938,14 @@ struct device_reg_24xx { | |||
| 916 | uint16_t mailbox29; | 938 | uint16_t mailbox29; |
| 917 | uint16_t mailbox30; | 939 | uint16_t mailbox30; |
| 918 | uint16_t mailbox31; | 940 | uint16_t mailbox31; |
| 941 | |||
| 942 | uint32_t iobase_window; | ||
| 943 | uint32_t unused_4[8]; /* Gap. */ | ||
| 944 | uint32_t iobase_q; | ||
| 945 | uint32_t unused_5[2]; /* Gap. */ | ||
| 946 | uint32_t iobase_select; | ||
| 947 | uint32_t unused_6[2]; /* Gap. */ | ||
| 948 | uint32_t iobase_sdata; | ||
| 919 | }; | 949 | }; |
| 920 | 950 | ||
| 921 | /* MID Support ***************************************************************/ | 951 | /* MID Support ***************************************************************/ |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index b44eff2803ce..aa1e41152283 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
| @@ -17,6 +17,7 @@ extern int qla2x00_initialize_adapter(scsi_qla_host_t *); | |||
| 17 | extern int qla2100_pci_config(struct scsi_qla_host *); | 17 | extern int qla2100_pci_config(struct scsi_qla_host *); |
| 18 | extern int qla2300_pci_config(struct scsi_qla_host *); | 18 | extern int qla2300_pci_config(struct scsi_qla_host *); |
| 19 | extern int qla24xx_pci_config(scsi_qla_host_t *); | 19 | extern int qla24xx_pci_config(scsi_qla_host_t *); |
| 20 | extern int qla25xx_pci_config(scsi_qla_host_t *); | ||
| 20 | extern void qla2x00_reset_chip(struct scsi_qla_host *); | 21 | extern void qla2x00_reset_chip(struct scsi_qla_host *); |
| 21 | extern void qla24xx_reset_chip(struct scsi_qla_host *); | 22 | extern void qla24xx_reset_chip(struct scsi_qla_host *); |
| 22 | extern int qla2x00_chip_diag(struct scsi_qla_host *); | 23 | extern int qla2x00_chip_diag(struct scsi_qla_host *); |
| @@ -281,6 +282,10 @@ extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, | |||
| 281 | uint32_t); | 282 | uint32_t); |
| 282 | extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, | 283 | extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, |
| 283 | uint32_t); | 284 | uint32_t); |
| 285 | extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, | ||
| 286 | uint32_t); | ||
| 287 | extern int qla25xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, | ||
| 288 | uint32_t); | ||
| 284 | 289 | ||
| 285 | extern int qla2x00_beacon_on(struct scsi_qla_host *); | 290 | extern int qla2x00_beacon_on(struct scsi_qla_host *); |
| 286 | extern int qla2x00_beacon_off(struct scsi_qla_host *); | 291 | extern int qla2x00_beacon_off(struct scsi_qla_host *); |
| @@ -307,6 +312,7 @@ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); | |||
| 307 | extern void qla2100_fw_dump(scsi_qla_host_t *, int); | 312 | extern void qla2100_fw_dump(scsi_qla_host_t *, int); |
| 308 | extern void qla2300_fw_dump(scsi_qla_host_t *, int); | 313 | extern void qla2300_fw_dump(scsi_qla_host_t *, int); |
| 309 | extern void qla24xx_fw_dump(scsi_qla_host_t *, int); | 314 | extern void qla24xx_fw_dump(scsi_qla_host_t *, int); |
| 315 | extern void qla25xx_fw_dump(scsi_qla_host_t *, int); | ||
| 310 | extern void qla2x00_dump_regs(scsi_qla_host_t *); | 316 | extern void qla2x00_dump_regs(scsi_qla_host_t *); |
| 311 | extern void qla2x00_dump_buffer(uint8_t *, uint32_t); | 317 | extern void qla2x00_dump_buffer(uint8_t *, uint32_t); |
| 312 | extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *); | 318 | extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *); |
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index a086b3f0df65..b06cbb8580d3 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c | |||
| @@ -127,7 +127,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt, | |||
| 127 | DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n", | 127 | DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n", |
| 128 | ha->host_no, routine, ms_pkt->entry_status)); | 128 | ha->host_no, routine, ms_pkt->entry_status)); |
| 129 | } else { | 129 | } else { |
| 130 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 130 | if (IS_FWI2_CAPABLE(ha)) |
| 131 | comp_status = le16_to_cpu( | 131 | comp_status = le16_to_cpu( |
| 132 | ((struct ct_entry_24xx *)ms_pkt)->comp_status); | 132 | ((struct ct_entry_24xx *)ms_pkt)->comp_status); |
| 133 | else | 133 | else |
| @@ -180,7 +180,8 @@ qla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport) | |||
| 180 | 180 | ||
| 181 | /* Issue GA_NXT */ | 181 | /* Issue GA_NXT */ |
| 182 | /* Prepare common MS IOCB */ | 182 | /* Prepare common MS IOCB */ |
| 183 | ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GA_NXT_REQ_SIZE, GA_NXT_RSP_SIZE); | 183 | ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GA_NXT_REQ_SIZE, |
| 184 | GA_NXT_RSP_SIZE); | ||
| 184 | 185 | ||
| 185 | /* Prepare CT request */ | 186 | /* Prepare CT request */ |
| 186 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD, | 187 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD, |
| @@ -266,7 +267,8 @@ qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list) | |||
| 266 | 267 | ||
| 267 | /* Issue GID_PT */ | 268 | /* Issue GID_PT */ |
| 268 | /* Prepare common MS IOCB */ | 269 | /* Prepare common MS IOCB */ |
| 269 | ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GID_PT_REQ_SIZE, GID_PT_RSP_SIZE); | 270 | ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GID_PT_REQ_SIZE, |
| 271 | GID_PT_RSP_SIZE); | ||
| 270 | 272 | ||
| 271 | /* Prepare CT request */ | 273 | /* Prepare CT request */ |
| 272 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD, | 274 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD, |
| @@ -338,7 +340,7 @@ qla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list) | |||
| 338 | for (i = 0; i < MAX_FIBRE_DEVICES; i++) { | 340 | for (i = 0; i < MAX_FIBRE_DEVICES; i++) { |
| 339 | /* Issue GPN_ID */ | 341 | /* Issue GPN_ID */ |
| 340 | /* Prepare common MS IOCB */ | 342 | /* Prepare common MS IOCB */ |
| 341 | ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GPN_ID_REQ_SIZE, | 343 | ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GPN_ID_REQ_SIZE, |
| 342 | GPN_ID_RSP_SIZE); | 344 | GPN_ID_RSP_SIZE); |
| 343 | 345 | ||
| 344 | /* Prepare CT request */ | 346 | /* Prepare CT request */ |
| @@ -399,7 +401,7 @@ qla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list) | |||
| 399 | for (i = 0; i < MAX_FIBRE_DEVICES; i++) { | 401 | for (i = 0; i < MAX_FIBRE_DEVICES; i++) { |
| 400 | /* Issue GNN_ID */ | 402 | /* Issue GNN_ID */ |
| 401 | /* Prepare common MS IOCB */ | 403 | /* Prepare common MS IOCB */ |
| 402 | ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GNN_ID_REQ_SIZE, | 404 | ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GNN_ID_REQ_SIZE, |
| 403 | GNN_ID_RSP_SIZE); | 405 | GNN_ID_RSP_SIZE); |
| 404 | 406 | ||
| 405 | /* Prepare CT request */ | 407 | /* Prepare CT request */ |
| @@ -473,7 +475,8 @@ qla2x00_rft_id(scsi_qla_host_t *ha) | |||
| 473 | 475 | ||
| 474 | /* Issue RFT_ID */ | 476 | /* Issue RFT_ID */ |
| 475 | /* Prepare common MS IOCB */ | 477 | /* Prepare common MS IOCB */ |
| 476 | ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFT_ID_REQ_SIZE, RFT_ID_RSP_SIZE); | 478 | ms_pkt = ha->isp_ops->prep_ms_iocb(ha, RFT_ID_REQ_SIZE, |
| 479 | RFT_ID_RSP_SIZE); | ||
| 477 | 480 | ||
| 478 | /* Prepare CT request */ | 481 | /* Prepare CT request */ |
| 479 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD, | 482 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD, |
| @@ -528,7 +531,8 @@ qla2x00_rff_id(scsi_qla_host_t *ha) | |||
| 528 | 531 | ||
| 529 | /* Issue RFF_ID */ | 532 | /* Issue RFF_ID */ |
| 530 | /* Prepare common MS IOCB */ | 533 | /* Prepare common MS IOCB */ |
| 531 | ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFF_ID_REQ_SIZE, RFF_ID_RSP_SIZE); | 534 | ms_pkt = ha->isp_ops->prep_ms_iocb(ha, RFF_ID_REQ_SIZE, |
| 535 | RFF_ID_RSP_SIZE); | ||
| 532 | 536 | ||
| 533 | /* Prepare CT request */ | 537 | /* Prepare CT request */ |
| 534 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD, | 538 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD, |
| @@ -582,7 +586,8 @@ qla2x00_rnn_id(scsi_qla_host_t *ha) | |||
| 582 | 586 | ||
| 583 | /* Issue RNN_ID */ | 587 | /* Issue RNN_ID */ |
| 584 | /* Prepare common MS IOCB */ | 588 | /* Prepare common MS IOCB */ |
| 585 | ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RNN_ID_REQ_SIZE, RNN_ID_RSP_SIZE); | 589 | ms_pkt = ha->isp_ops->prep_ms_iocb(ha, RNN_ID_REQ_SIZE, |
| 590 | RNN_ID_RSP_SIZE); | ||
| 586 | 591 | ||
| 587 | /* Prepare CT request */ | 592 | /* Prepare CT request */ |
| 588 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD, | 593 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD, |
| @@ -645,7 +650,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *ha) | |||
| 645 | /* Issue RSNN_NN */ | 650 | /* Issue RSNN_NN */ |
| 646 | /* Prepare common MS IOCB */ | 651 | /* Prepare common MS IOCB */ |
| 647 | /* Request size adjusted after CT preparation */ | 652 | /* Request size adjusted after CT preparation */ |
| 648 | ms_pkt = ha->isp_ops.prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE); | 653 | ms_pkt = ha->isp_ops->prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE); |
| 649 | 654 | ||
| 650 | /* Prepare CT request */ | 655 | /* Prepare CT request */ |
| 651 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD, | 656 | ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD, |
| @@ -1102,7 +1107,7 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *ha) | |||
| 1102 | if (ha->flags.management_server_logged_in) | 1107 | if (ha->flags.management_server_logged_in) |
| 1103 | return ret; | 1108 | return ret; |
| 1104 | 1109 | ||
| 1105 | ha->isp_ops.fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa, | 1110 | ha->isp_ops->fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa, |
| 1106 | mb, BIT_1); | 1111 | mb, BIT_1); |
| 1107 | if (mb[0] != MBS_COMMAND_COMPLETE) { | 1112 | if (mb[0] != MBS_COMMAND_COMPLETE) { |
| 1108 | DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: " | 1113 | DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: " |
| @@ -1198,7 +1203,7 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size) | |||
| 1198 | ms_iocb_entry_t *ms_pkt = ha->ms_iocb; | 1203 | ms_iocb_entry_t *ms_pkt = ha->ms_iocb; |
| 1199 | struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; | 1204 | struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; |
| 1200 | 1205 | ||
| 1201 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1206 | if (IS_FWI2_CAPABLE(ha)) { |
| 1202 | ct_pkt->cmd_byte_count = cpu_to_le32(req_size); | 1207 | ct_pkt->cmd_byte_count = cpu_to_le32(req_size); |
| 1203 | ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; | 1208 | ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; |
| 1204 | } else { | 1209 | } else { |
| @@ -1253,7 +1258,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *ha) | |||
| 1253 | /* Issue RHBA */ | 1258 | /* Issue RHBA */ |
| 1254 | /* Prepare common MS IOCB */ | 1259 | /* Prepare common MS IOCB */ |
| 1255 | /* Request size adjusted after CT preparation */ | 1260 | /* Request size adjusted after CT preparation */ |
| 1256 | ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE); | 1261 | ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE); |
| 1257 | 1262 | ||
| 1258 | /* Prepare CT request */ | 1263 | /* Prepare CT request */ |
| 1259 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD, | 1264 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD, |
| @@ -1373,7 +1378,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *ha) | |||
| 1373 | /* Firmware version */ | 1378 | /* Firmware version */ |
| 1374 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | 1379 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); |
| 1375 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); | 1380 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); |
| 1376 | ha->isp_ops.fw_version_str(ha, eiter->a.fw_version); | 1381 | ha->isp_ops->fw_version_str(ha, eiter->a.fw_version); |
| 1377 | alen = strlen(eiter->a.fw_version); | 1382 | alen = strlen(eiter->a.fw_version); |
| 1378 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | 1383 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; |
| 1379 | eiter->len = cpu_to_be16(4 + alen); | 1384 | eiter->len = cpu_to_be16(4 + alen); |
| @@ -1439,7 +1444,7 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *ha) | |||
| 1439 | 1444 | ||
| 1440 | /* Issue RPA */ | 1445 | /* Issue RPA */ |
| 1441 | /* Prepare common MS IOCB */ | 1446 | /* Prepare common MS IOCB */ |
| 1442 | ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE, | 1447 | ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE, |
| 1443 | DHBA_RSP_SIZE); | 1448 | DHBA_RSP_SIZE); |
| 1444 | 1449 | ||
| 1445 | /* Prepare CT request */ | 1450 | /* Prepare CT request */ |
| @@ -1497,7 +1502,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) | |||
| 1497 | /* Issue RPA */ | 1502 | /* Issue RPA */ |
| 1498 | /* Prepare common MS IOCB */ | 1503 | /* Prepare common MS IOCB */ |
| 1499 | /* Request size adjusted after CT preparation */ | 1504 | /* Request size adjusted after CT preparation */ |
| 1500 | ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE); | 1505 | ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE); |
| 1501 | 1506 | ||
| 1502 | /* Prepare CT request */ | 1507 | /* Prepare CT request */ |
| 1503 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD, | 1508 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD, |
| @@ -1527,12 +1532,20 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) | |||
| 1527 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | 1532 | eiter = (struct ct_fdmi_port_attr *) (entries + size); |
| 1528 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); | 1533 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); |
| 1529 | eiter->len = __constant_cpu_to_be16(4 + 4); | 1534 | eiter->len = __constant_cpu_to_be16(4 + 4); |
| 1530 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 1535 | if (IS_QLA25XX(ha)) |
| 1531 | eiter->a.sup_speed = __constant_cpu_to_be32(4); | 1536 | eiter->a.sup_speed = __constant_cpu_to_be32( |
| 1537 | FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB| | ||
| 1538 | FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB); | ||
| 1539 | else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | ||
| 1540 | eiter->a.sup_speed = __constant_cpu_to_be32( | ||
| 1541 | FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB| | ||
| 1542 | FDMI_PORT_SPEED_4GB); | ||
| 1532 | else if (IS_QLA23XX(ha)) | 1543 | else if (IS_QLA23XX(ha)) |
| 1533 | eiter->a.sup_speed = __constant_cpu_to_be32(2); | 1544 | eiter->a.sup_speed =__constant_cpu_to_be32( |
| 1545 | FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB); | ||
| 1534 | else | 1546 | else |
| 1535 | eiter->a.sup_speed = __constant_cpu_to_be32(1); | 1547 | eiter->a.sup_speed = __constant_cpu_to_be32( |
| 1548 | FDMI_PORT_SPEED_1GB); | ||
| 1536 | size += 4 + 4; | 1549 | size += 4 + 4; |
| 1537 | 1550 | ||
| 1538 | DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no, | 1551 | DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no, |
| @@ -1543,14 +1556,25 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) | |||
| 1543 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED); | 1556 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED); |
| 1544 | eiter->len = __constant_cpu_to_be16(4 + 4); | 1557 | eiter->len = __constant_cpu_to_be16(4 + 4); |
| 1545 | switch (ha->link_data_rate) { | 1558 | switch (ha->link_data_rate) { |
| 1546 | case 0: | 1559 | case PORT_SPEED_1GB: |
| 1547 | eiter->a.cur_speed = __constant_cpu_to_be32(1); | 1560 | eiter->a.cur_speed = |
| 1561 | __constant_cpu_to_be32(FDMI_PORT_SPEED_1GB); | ||
| 1562 | break; | ||
| 1563 | case PORT_SPEED_2GB: | ||
| 1564 | eiter->a.cur_speed = | ||
| 1565 | __constant_cpu_to_be32(FDMI_PORT_SPEED_2GB); | ||
| 1566 | break; | ||
| 1567 | case PORT_SPEED_4GB: | ||
| 1568 | eiter->a.cur_speed = | ||
| 1569 | __constant_cpu_to_be32(FDMI_PORT_SPEED_4GB); | ||
| 1548 | break; | 1570 | break; |
| 1549 | case 1: | 1571 | case PORT_SPEED_8GB: |
| 1550 | eiter->a.cur_speed = __constant_cpu_to_be32(2); | 1572 | eiter->a.cur_speed = |
| 1573 | __constant_cpu_to_be32(FDMI_PORT_SPEED_8GB); | ||
| 1551 | break; | 1574 | break; |
| 1552 | case 3: | 1575 | default: |
| 1553 | eiter->a.cur_speed = __constant_cpu_to_be32(4); | 1576 | eiter->a.cur_speed = |
| 1577 | __constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); | ||
| 1554 | break; | 1578 | break; |
| 1555 | } | 1579 | } |
| 1556 | size += 4 + 4; | 1580 | size += 4 + 4; |
| @@ -1562,7 +1586,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) | |||
| 1562 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | 1586 | eiter = (struct ct_fdmi_port_attr *) (entries + size); |
| 1563 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); | 1587 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); |
| 1564 | eiter->len = __constant_cpu_to_be16(4 + 4); | 1588 | eiter->len = __constant_cpu_to_be16(4 + 4); |
| 1565 | max_frame_size = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? | 1589 | max_frame_size = IS_FWI2_CAPABLE(ha) ? |
| 1566 | (uint32_t) icb24->frame_payload_size: | 1590 | (uint32_t) icb24->frame_payload_size: |
| 1567 | (uint32_t) ha->init_cb->frame_payload_size; | 1591 | (uint32_t) ha->init_cb->frame_payload_size; |
| 1568 | eiter->a.max_frame_size = cpu_to_be32(max_frame_size); | 1592 | eiter->a.max_frame_size = cpu_to_be32(max_frame_size); |
| @@ -1678,7 +1702,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list) | |||
| 1678 | struct ct_sns_req *ct_req; | 1702 | struct ct_sns_req *ct_req; |
| 1679 | struct ct_sns_rsp *ct_rsp; | 1703 | struct ct_sns_rsp *ct_rsp; |
| 1680 | 1704 | ||
| 1681 | if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | 1705 | if (!IS_IIDMA_CAPABLE(ha)) |
| 1682 | return QLA_FUNCTION_FAILED; | 1706 | return QLA_FUNCTION_FAILED; |
| 1683 | 1707 | ||
| 1684 | for (i = 0; i < MAX_FIBRE_DEVICES; i++) { | 1708 | for (i = 0; i < MAX_FIBRE_DEVICES; i++) { |
| @@ -1686,7 +1710,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list) | |||
| 1686 | memset(list[i].fabric_port_name, 0, WWN_SIZE); | 1710 | memset(list[i].fabric_port_name, 0, WWN_SIZE); |
| 1687 | 1711 | ||
| 1688 | /* Prepare common MS IOCB */ | 1712 | /* Prepare common MS IOCB */ |
| 1689 | ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GFPN_ID_REQ_SIZE, | 1713 | ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GFPN_ID_REQ_SIZE, |
| 1690 | GFPN_ID_RSP_SIZE); | 1714 | GFPN_ID_RSP_SIZE); |
| 1691 | 1715 | ||
| 1692 | /* Prepare CT request */ | 1716 | /* Prepare CT request */ |
| @@ -1786,7 +1810,7 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list) | |||
| 1786 | struct ct_sns_req *ct_req; | 1810 | struct ct_sns_req *ct_req; |
| 1787 | struct ct_sns_rsp *ct_rsp; | 1811 | struct ct_sns_rsp *ct_rsp; |
| 1788 | 1812 | ||
| 1789 | if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | 1813 | if (!IS_IIDMA_CAPABLE(ha)) |
| 1790 | return QLA_FUNCTION_FAILED; | 1814 | return QLA_FUNCTION_FAILED; |
| 1791 | if (!ha->flags.gpsc_supported) | 1815 | if (!ha->flags.gpsc_supported) |
| 1792 | return QLA_FUNCTION_FAILED; | 1816 | return QLA_FUNCTION_FAILED; |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index cc6ebb609e98..5ec798c2bf13 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
| @@ -79,20 +79,20 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
| 79 | set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); | 79 | set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); |
| 80 | 80 | ||
| 81 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); | 81 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); |
| 82 | rval = ha->isp_ops.pci_config(ha); | 82 | rval = ha->isp_ops->pci_config(ha); |
| 83 | if (rval) { | 83 | if (rval) { |
| 84 | DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n", | 84 | DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n", |
| 85 | ha->host_no)); | 85 | ha->host_no)); |
| 86 | return (rval); | 86 | return (rval); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | ha->isp_ops.reset_chip(ha); | 89 | ha->isp_ops->reset_chip(ha); |
| 90 | 90 | ||
| 91 | ha->isp_ops.get_flash_version(ha, ha->request_ring); | 91 | ha->isp_ops->get_flash_version(ha, ha->request_ring); |
| 92 | 92 | ||
| 93 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); | 93 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); |
| 94 | 94 | ||
| 95 | ha->isp_ops.nvram_config(ha); | 95 | ha->isp_ops->nvram_config(ha); |
| 96 | 96 | ||
| 97 | if (ha->flags.disable_serdes) { | 97 | if (ha->flags.disable_serdes) { |
| 98 | /* Mask HBA via NVRAM settings? */ | 98 | /* Mask HBA via NVRAM settings? */ |
| @@ -108,7 +108,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
| 108 | qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); | 108 | qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); |
| 109 | 109 | ||
| 110 | if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { | 110 | if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { |
| 111 | rval = ha->isp_ops.chip_diag(ha); | 111 | rval = ha->isp_ops->chip_diag(ha); |
| 112 | if (rval) | 112 | if (rval) |
| 113 | return (rval); | 113 | return (rval); |
| 114 | rval = qla2x00_setup_chip(ha); | 114 | rval = qla2x00_setup_chip(ha); |
| @@ -129,14 +129,13 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
| 129 | int | 129 | int |
| 130 | qla2100_pci_config(scsi_qla_host_t *ha) | 130 | qla2100_pci_config(scsi_qla_host_t *ha) |
| 131 | { | 131 | { |
| 132 | int ret; | ||
| 133 | uint16_t w; | 132 | uint16_t w; |
| 134 | uint32_t d; | 133 | uint32_t d; |
| 135 | unsigned long flags; | 134 | unsigned long flags; |
| 136 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 135 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
| 137 | 136 | ||
| 138 | pci_set_master(ha->pdev); | 137 | pci_set_master(ha->pdev); |
| 139 | ret = pci_set_mwi(ha->pdev); | 138 | pci_try_set_mwi(ha->pdev); |
| 140 | 139 | ||
| 141 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); | 140 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); |
| 142 | w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | 141 | w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); |
| @@ -164,7 +163,6 @@ qla2100_pci_config(scsi_qla_host_t *ha) | |||
| 164 | int | 163 | int |
| 165 | qla2300_pci_config(scsi_qla_host_t *ha) | 164 | qla2300_pci_config(scsi_qla_host_t *ha) |
| 166 | { | 165 | { |
| 167 | int ret; | ||
| 168 | uint16_t w; | 166 | uint16_t w; |
| 169 | uint32_t d; | 167 | uint32_t d; |
| 170 | unsigned long flags = 0; | 168 | unsigned long flags = 0; |
| @@ -172,7 +170,7 @@ qla2300_pci_config(scsi_qla_host_t *ha) | |||
| 172 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 170 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
| 173 | 171 | ||
| 174 | pci_set_master(ha->pdev); | 172 | pci_set_master(ha->pdev); |
| 175 | ret = pci_set_mwi(ha->pdev); | 173 | pci_try_set_mwi(ha->pdev); |
| 176 | 174 | ||
| 177 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); | 175 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); |
| 178 | w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | 176 | w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); |
| @@ -250,15 +248,13 @@ qla2300_pci_config(scsi_qla_host_t *ha) | |||
| 250 | int | 248 | int |
| 251 | qla24xx_pci_config(scsi_qla_host_t *ha) | 249 | qla24xx_pci_config(scsi_qla_host_t *ha) |
| 252 | { | 250 | { |
| 253 | int ret; | ||
| 254 | uint16_t w; | 251 | uint16_t w; |
| 255 | uint32_t d; | 252 | uint32_t d; |
| 256 | unsigned long flags = 0; | 253 | unsigned long flags = 0; |
| 257 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 254 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
| 258 | int pcix_cmd_reg, pcie_dctl_reg; | ||
| 259 | 255 | ||
| 260 | pci_set_master(ha->pdev); | 256 | pci_set_master(ha->pdev); |
| 261 | ret = pci_set_mwi(ha->pdev); | 257 | pci_try_set_mwi(ha->pdev); |
| 262 | 258 | ||
| 263 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); | 259 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); |
| 264 | w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | 260 | w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); |
| @@ -268,28 +264,12 @@ qla24xx_pci_config(scsi_qla_host_t *ha) | |||
| 268 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); | 264 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); |
| 269 | 265 | ||
| 270 | /* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */ | 266 | /* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */ |
| 271 | pcix_cmd_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX); | 267 | if (pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX)) |
| 272 | if (pcix_cmd_reg) { | 268 | pcix_set_mmrbc(ha->pdev, 2048); |
| 273 | uint16_t pcix_cmd; | ||
| 274 | |||
| 275 | pcix_cmd_reg += PCI_X_CMD; | ||
| 276 | pci_read_config_word(ha->pdev, pcix_cmd_reg, &pcix_cmd); | ||
| 277 | pcix_cmd &= ~PCI_X_CMD_MAX_READ; | ||
| 278 | pcix_cmd |= 0x0008; | ||
| 279 | pci_write_config_word(ha->pdev, pcix_cmd_reg, pcix_cmd); | ||
| 280 | } | ||
| 281 | 269 | ||
| 282 | /* PCIe -- adjust Maximum Read Request Size (2048). */ | 270 | /* PCIe -- adjust Maximum Read Request Size (2048). */ |
| 283 | pcie_dctl_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); | 271 | if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) |
| 284 | if (pcie_dctl_reg) { | 272 | pcie_set_readrq(ha->pdev, 2048); |
| 285 | uint16_t pcie_dctl; | ||
| 286 | |||
| 287 | pcie_dctl_reg += PCI_EXP_DEVCTL; | ||
| 288 | pci_read_config_word(ha->pdev, pcie_dctl_reg, &pcie_dctl); | ||
| 289 | pcie_dctl &= ~PCI_EXP_DEVCTL_READRQ; | ||
| 290 | pcie_dctl |= 0x4000; | ||
| 291 | pci_write_config_word(ha->pdev, pcie_dctl_reg, pcie_dctl); | ||
| 292 | } | ||
| 293 | 273 | ||
| 294 | /* Reset expansion ROM address decode enable */ | 274 | /* Reset expansion ROM address decode enable */ |
| 295 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); | 275 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); |
| @@ -307,6 +287,40 @@ qla24xx_pci_config(scsi_qla_host_t *ha) | |||
| 307 | } | 287 | } |
| 308 | 288 | ||
| 309 | /** | 289 | /** |
| 290 | * qla25xx_pci_config() - Setup ISP25xx PCI configuration registers. | ||
| 291 | * @ha: HA context | ||
| 292 | * | ||
| 293 | * Returns 0 on success. | ||
| 294 | */ | ||
| 295 | int | ||
| 296 | qla25xx_pci_config(scsi_qla_host_t *ha) | ||
| 297 | { | ||
| 298 | uint16_t w; | ||
| 299 | uint32_t d; | ||
| 300 | |||
| 301 | pci_set_master(ha->pdev); | ||
| 302 | pci_try_set_mwi(ha->pdev); | ||
| 303 | |||
| 304 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); | ||
| 305 | w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | ||
| 306 | w &= ~PCI_COMMAND_INTX_DISABLE; | ||
| 307 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); | ||
| 308 | |||
| 309 | /* PCIe -- adjust Maximum Read Request Size (2048). */ | ||
| 310 | if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) | ||
| 311 | pcie_set_readrq(ha->pdev, 2048); | ||
| 312 | |||
| 313 | /* Reset expansion ROM address decode enable */ | ||
| 314 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); | ||
| 315 | d &= ~PCI_ROM_ADDRESS_ENABLE; | ||
| 316 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); | ||
| 317 | |||
| 318 | ha->chip_revision = ha->pdev->revision; | ||
| 319 | |||
| 320 | return QLA_SUCCESS; | ||
| 321 | } | ||
| 322 | |||
| 323 | /** | ||
| 310 | * qla2x00_isp_firmware() - Choose firmware image. | 324 | * qla2x00_isp_firmware() - Choose firmware image. |
| 311 | * @ha: HA context | 325 | * @ha: HA context |
| 312 | * | 326 | * |
| @@ -351,7 +365,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) | |||
| 351 | uint32_t cnt; | 365 | uint32_t cnt; |
| 352 | uint16_t cmd; | 366 | uint16_t cmd; |
| 353 | 367 | ||
| 354 | ha->isp_ops.disable_intrs(ha); | 368 | ha->isp_ops->disable_intrs(ha); |
| 355 | 369 | ||
| 356 | spin_lock_irqsave(&ha->hardware_lock, flags); | 370 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 357 | 371 | ||
| @@ -551,7 +565,7 @@ qla24xx_reset_risc(scsi_qla_host_t *ha) | |||
| 551 | void | 565 | void |
| 552 | qla24xx_reset_chip(scsi_qla_host_t *ha) | 566 | qla24xx_reset_chip(scsi_qla_host_t *ha) |
| 553 | { | 567 | { |
| 554 | ha->isp_ops.disable_intrs(ha); | 568 | ha->isp_ops->disable_intrs(ha); |
| 555 | 569 | ||
| 556 | /* Perform RISC reset. */ | 570 | /* Perform RISC reset. */ |
| 557 | qla24xx_reset_risc(ha); | 571 | qla24xx_reset_risc(ha); |
| @@ -736,8 +750,10 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) | |||
| 736 | fixed_size = offsetof(struct qla2300_fw_dump, data_ram); | 750 | fixed_size = offsetof(struct qla2300_fw_dump, data_ram); |
| 737 | mem_size = (ha->fw_memory_size - 0x11000 + 1) * | 751 | mem_size = (ha->fw_memory_size - 0x11000 + 1) * |
| 738 | sizeof(uint16_t); | 752 | sizeof(uint16_t); |
| 739 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 753 | } else if (IS_FWI2_CAPABLE(ha)) { |
| 740 | fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); | 754 | fixed_size = IS_QLA25XX(ha) ? |
| 755 | offsetof(struct qla25xx_fw_dump, ext_mem): | ||
| 756 | offsetof(struct qla24xx_fw_dump, ext_mem); | ||
| 741 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * | 757 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * |
| 742 | sizeof(uint32_t); | 758 | sizeof(uint32_t); |
| 743 | 759 | ||
| @@ -879,7 +895,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) | |||
| 879 | uint32_t srisc_address = 0; | 895 | uint32_t srisc_address = 0; |
| 880 | 896 | ||
| 881 | /* Load firmware sequences */ | 897 | /* Load firmware sequences */ |
| 882 | rval = ha->isp_ops.load_risc(ha, &srisc_address); | 898 | rval = ha->isp_ops->load_risc(ha, &srisc_address); |
| 883 | if (rval == QLA_SUCCESS) { | 899 | if (rval == QLA_SUCCESS) { |
| 884 | DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC " | 900 | DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC " |
| 885 | "code.\n", ha->host_no)); | 901 | "code.\n", ha->host_no)); |
| @@ -1130,12 +1146,12 @@ qla2x00_init_rings(scsi_qla_host_t *ha) | |||
| 1130 | /* Initialize response queue entries */ | 1146 | /* Initialize response queue entries */ |
| 1131 | qla2x00_init_response_q_entries(ha); | 1147 | qla2x00_init_response_q_entries(ha); |
| 1132 | 1148 | ||
| 1133 | ha->isp_ops.config_rings(ha); | 1149 | ha->isp_ops->config_rings(ha); |
| 1134 | 1150 | ||
| 1135 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1151 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 1136 | 1152 | ||
| 1137 | /* Update any ISP specific firmware options before initialization. */ | 1153 | /* Update any ISP specific firmware options before initialization. */ |
| 1138 | ha->isp_ops.update_fw_options(ha); | 1154 | ha->isp_ops->update_fw_options(ha); |
| 1139 | 1155 | ||
| 1140 | DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); | 1156 | DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); |
| 1141 | 1157 | ||
| @@ -1459,7 +1475,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
| 1459 | ha->nvram_base = 0x80; | 1475 | ha->nvram_base = 0x80; |
| 1460 | 1476 | ||
| 1461 | /* Get NVRAM data and calculate checksum. */ | 1477 | /* Get NVRAM data and calculate checksum. */ |
| 1462 | ha->isp_ops.read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size); | 1478 | ha->isp_ops->read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size); |
| 1463 | for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++) | 1479 | for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++) |
| 1464 | chksum += *ptr++; | 1480 | chksum += *ptr++; |
| 1465 | 1481 | ||
| @@ -2119,7 +2135,7 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) | |||
| 2119 | int rval; | 2135 | int rval; |
| 2120 | uint16_t port_speed, mb[6]; | 2136 | uint16_t port_speed, mb[6]; |
| 2121 | 2137 | ||
| 2122 | if (!IS_QLA24XX(ha)) | 2138 | if (!IS_IIDMA_CAPABLE(ha)) |
| 2123 | return; | 2139 | return; |
| 2124 | 2140 | ||
| 2125 | switch (be16_to_cpu(fcport->fp_speed)) { | 2141 | switch (be16_to_cpu(fcport->fp_speed)) { |
| @@ -2267,7 +2283,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
| 2267 | scsi_qla_host_t *pha = to_qla_parent(ha); | 2283 | scsi_qla_host_t *pha = to_qla_parent(ha); |
| 2268 | 2284 | ||
| 2269 | /* If FL port exists, then SNS is present */ | 2285 | /* If FL port exists, then SNS is present */ |
| 2270 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 2286 | if (IS_FWI2_CAPABLE(ha)) |
| 2271 | loop_id = NPH_F_PORT; | 2287 | loop_id = NPH_F_PORT; |
| 2272 | else | 2288 | else |
| 2273 | loop_id = SNS_FL_PORT; | 2289 | loop_id = SNS_FL_PORT; |
| @@ -2294,11 +2310,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
| 2294 | qla2x00_fdmi_register(ha); | 2310 | qla2x00_fdmi_register(ha); |
| 2295 | 2311 | ||
| 2296 | /* Ensure we are logged into the SNS. */ | 2312 | /* Ensure we are logged into the SNS. */ |
| 2297 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 2313 | if (IS_FWI2_CAPABLE(ha)) |
| 2298 | loop_id = NPH_SNS; | 2314 | loop_id = NPH_SNS; |
| 2299 | else | 2315 | else |
| 2300 | loop_id = SIMPLE_NAME_SERVER; | 2316 | loop_id = SIMPLE_NAME_SERVER; |
| 2301 | ha->isp_ops.fabric_login(ha, loop_id, 0xff, 0xff, | 2317 | ha->isp_ops->fabric_login(ha, loop_id, 0xff, 0xff, |
| 2302 | 0xfc, mb, BIT_1 | BIT_0); | 2318 | 0xfc, mb, BIT_1 | BIT_0); |
| 2303 | if (mb[0] != MBS_COMMAND_COMPLETE) { | 2319 | if (mb[0] != MBS_COMMAND_COMPLETE) { |
| 2304 | DEBUG2(qla_printk(KERN_INFO, ha, | 2320 | DEBUG2(qla_printk(KERN_INFO, ha, |
| @@ -2355,7 +2371,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
| 2355 | (fcport->flags & FCF_TAPE_PRESENT) == 0 && | 2371 | (fcport->flags & FCF_TAPE_PRESENT) == 0 && |
| 2356 | fcport->port_type != FCT_INITIATOR && | 2372 | fcport->port_type != FCT_INITIATOR && |
| 2357 | fcport->port_type != FCT_BROADCAST) { | 2373 | fcport->port_type != FCT_BROADCAST) { |
| 2358 | ha->isp_ops.fabric_logout(ha, | 2374 | ha->isp_ops->fabric_logout(ha, |
| 2359 | fcport->loop_id, | 2375 | fcport->loop_id, |
| 2360 | fcport->d_id.b.domain, | 2376 | fcport->d_id.b.domain, |
| 2361 | fcport->d_id.b.area, | 2377 | fcport->d_id.b.area, |
| @@ -2664,7 +2680,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
| 2664 | (fcport->flags & FCF_TAPE_PRESENT) == 0 && | 2680 | (fcport->flags & FCF_TAPE_PRESENT) == 0 && |
| 2665 | fcport->port_type != FCT_INITIATOR && | 2681 | fcport->port_type != FCT_INITIATOR && |
| 2666 | fcport->port_type != FCT_BROADCAST) { | 2682 | fcport->port_type != FCT_BROADCAST) { |
| 2667 | ha->isp_ops.fabric_logout(ha, fcport->loop_id, | 2683 | ha->isp_ops->fabric_logout(ha, fcport->loop_id, |
| 2668 | fcport->d_id.b.domain, fcport->d_id.b.area, | 2684 | fcport->d_id.b.domain, fcport->d_id.b.area, |
| 2669 | fcport->d_id.b.al_pa); | 2685 | fcport->d_id.b.al_pa); |
| 2670 | fcport->loop_id = FC_NO_LOOP_ID; | 2686 | fcport->loop_id = FC_NO_LOOP_ID; |
| @@ -2919,7 +2935,7 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
| 2919 | opts |= BIT_1; | 2935 | opts |= BIT_1; |
| 2920 | rval = qla2x00_get_port_database(ha, fcport, opts); | 2936 | rval = qla2x00_get_port_database(ha, fcport, opts); |
| 2921 | if (rval != QLA_SUCCESS) { | 2937 | if (rval != QLA_SUCCESS) { |
| 2922 | ha->isp_ops.fabric_logout(ha, fcport->loop_id, | 2938 | ha->isp_ops->fabric_logout(ha, fcport->loop_id, |
| 2923 | fcport->d_id.b.domain, fcport->d_id.b.area, | 2939 | fcport->d_id.b.domain, fcport->d_id.b.area, |
| 2924 | fcport->d_id.b.al_pa); | 2940 | fcport->d_id.b.al_pa); |
| 2925 | qla2x00_mark_device_lost(ha, fcport, 1, 0); | 2941 | qla2x00_mark_device_lost(ha, fcport, 1, 0); |
| @@ -2964,7 +2980,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
| 2964 | fcport->d_id.b.area, fcport->d_id.b.al_pa)); | 2980 | fcport->d_id.b.area, fcport->d_id.b.al_pa)); |
| 2965 | 2981 | ||
| 2966 | /* Login fcport on switch. */ | 2982 | /* Login fcport on switch. */ |
| 2967 | ha->isp_ops.fabric_login(ha, fcport->loop_id, | 2983 | ha->isp_ops->fabric_login(ha, fcport->loop_id, |
| 2968 | fcport->d_id.b.domain, fcport->d_id.b.area, | 2984 | fcport->d_id.b.domain, fcport->d_id.b.area, |
| 2969 | fcport->d_id.b.al_pa, mb, BIT_0); | 2985 | fcport->d_id.b.al_pa, mb, BIT_0); |
| 2970 | if (mb[0] == MBS_PORT_ID_USED) { | 2986 | if (mb[0] == MBS_PORT_ID_USED) { |
| @@ -3032,7 +3048,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
| 3032 | * dead. | 3048 | * dead. |
| 3033 | */ | 3049 | */ |
| 3034 | *next_loopid = fcport->loop_id; | 3050 | *next_loopid = fcport->loop_id; |
| 3035 | ha->isp_ops.fabric_logout(ha, fcport->loop_id, | 3051 | ha->isp_ops->fabric_logout(ha, fcport->loop_id, |
| 3036 | fcport->d_id.b.domain, fcport->d_id.b.area, | 3052 | fcport->d_id.b.domain, fcport->d_id.b.area, |
| 3037 | fcport->d_id.b.al_pa); | 3053 | fcport->d_id.b.al_pa); |
| 3038 | qla2x00_mark_device_lost(ha, fcport, 1, 0); | 3054 | qla2x00_mark_device_lost(ha, fcport, 1, 0); |
| @@ -3050,7 +3066,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
| 3050 | fcport->d_id.b.al_pa, fcport->loop_id, jiffies)); | 3066 | fcport->d_id.b.al_pa, fcport->loop_id, jiffies)); |
| 3051 | 3067 | ||
| 3052 | *next_loopid = fcport->loop_id; | 3068 | *next_loopid = fcport->loop_id; |
| 3053 | ha->isp_ops.fabric_logout(ha, fcport->loop_id, | 3069 | ha->isp_ops->fabric_logout(ha, fcport->loop_id, |
| 3054 | fcport->d_id.b.domain, fcport->d_id.b.area, | 3070 | fcport->d_id.b.domain, fcport->d_id.b.area, |
| 3055 | fcport->d_id.b.al_pa); | 3071 | fcport->d_id.b.al_pa); |
| 3056 | fcport->loop_id = FC_NO_LOOP_ID; | 3072 | fcport->loop_id = FC_NO_LOOP_ID; |
| @@ -3206,7 +3222,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
| 3206 | 3222 | ||
| 3207 | qla_printk(KERN_INFO, ha, | 3223 | qla_printk(KERN_INFO, ha, |
| 3208 | "Performing ISP error recovery - ha= %p.\n", ha); | 3224 | "Performing ISP error recovery - ha= %p.\n", ha); |
| 3209 | ha->isp_ops.reset_chip(ha); | 3225 | ha->isp_ops->reset_chip(ha); |
| 3210 | 3226 | ||
| 3211 | atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); | 3227 | atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); |
| 3212 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { | 3228 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { |
| @@ -3232,9 +3248,9 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
| 3232 | } | 3248 | } |
| 3233 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 3249 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 3234 | 3250 | ||
| 3235 | ha->isp_ops.get_flash_version(ha, ha->request_ring); | 3251 | ha->isp_ops->get_flash_version(ha, ha->request_ring); |
| 3236 | 3252 | ||
| 3237 | ha->isp_ops.nvram_config(ha); | 3253 | ha->isp_ops->nvram_config(ha); |
| 3238 | 3254 | ||
| 3239 | if (!qla2x00_restart_isp(ha)) { | 3255 | if (!qla2x00_restart_isp(ha)) { |
| 3240 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | 3256 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); |
| @@ -3249,7 +3265,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
| 3249 | 3265 | ||
| 3250 | ha->flags.online = 1; | 3266 | ha->flags.online = 1; |
| 3251 | 3267 | ||
| 3252 | ha->isp_ops.enable_intrs(ha); | 3268 | ha->isp_ops->enable_intrs(ha); |
| 3253 | 3269 | ||
| 3254 | ha->isp_abort_cnt = 0; | 3270 | ha->isp_abort_cnt = 0; |
| 3255 | clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); | 3271 | clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); |
| @@ -3274,7 +3290,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
| 3274 | * The next call disables the board | 3290 | * The next call disables the board |
| 3275 | * completely. | 3291 | * completely. |
| 3276 | */ | 3292 | */ |
| 3277 | ha->isp_ops.reset_adapter(ha); | 3293 | ha->isp_ops->reset_adapter(ha); |
| 3278 | ha->flags.online = 0; | 3294 | ha->flags.online = 0; |
| 3279 | clear_bit(ISP_ABORT_RETRY, | 3295 | clear_bit(ISP_ABORT_RETRY, |
| 3280 | &ha->dpc_flags); | 3296 | &ha->dpc_flags); |
| @@ -3331,7 +3347,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) | |||
| 3331 | /* If firmware needs to be loaded */ | 3347 | /* If firmware needs to be loaded */ |
| 3332 | if (qla2x00_isp_firmware(ha)) { | 3348 | if (qla2x00_isp_firmware(ha)) { |
| 3333 | ha->flags.online = 0; | 3349 | ha->flags.online = 0; |
| 3334 | if (!(status = ha->isp_ops.chip_diag(ha))) { | 3350 | if (!(status = ha->isp_ops->chip_diag(ha))) { |
| 3335 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 3351 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
| 3336 | status = qla2x00_setup_chip(ha); | 3352 | status = qla2x00_setup_chip(ha); |
| 3337 | goto done; | 3353 | goto done; |
| @@ -3423,7 +3439,7 @@ qla2x00_reset_adapter(scsi_qla_host_t *ha) | |||
| 3423 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 3439 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
| 3424 | 3440 | ||
| 3425 | ha->flags.online = 0; | 3441 | ha->flags.online = 0; |
| 3426 | ha->isp_ops.disable_intrs(ha); | 3442 | ha->isp_ops->disable_intrs(ha); |
| 3427 | 3443 | ||
| 3428 | spin_lock_irqsave(&ha->hardware_lock, flags); | 3444 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 3429 | WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); | 3445 | WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); |
| @@ -3440,7 +3456,7 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha) | |||
| 3440 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 3456 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
| 3441 | 3457 | ||
| 3442 | ha->flags.online = 0; | 3458 | ha->flags.online = 0; |
| 3443 | ha->isp_ops.disable_intrs(ha); | 3459 | ha->isp_ops->disable_intrs(ha); |
| 3444 | 3460 | ||
| 3445 | spin_lock_irqsave(&ha->hardware_lock, flags); | 3461 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 3446 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET); | 3462 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET); |
| @@ -3498,7 +3514,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
| 3498 | 3514 | ||
| 3499 | /* Get NVRAM data and calculate checksum. */ | 3515 | /* Get NVRAM data and calculate checksum. */ |
| 3500 | dptr = (uint32_t *)nv; | 3516 | dptr = (uint32_t *)nv; |
| 3501 | ha->isp_ops.read_nvram(ha, (uint8_t *)dptr, ha->nvram_base, | 3517 | ha->isp_ops->read_nvram(ha, (uint8_t *)dptr, ha->nvram_base, |
| 3502 | ha->nvram_size); | 3518 | ha->nvram_size); |
| 3503 | for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) | 3519 | for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) |
| 3504 | chksum += le32_to_cpu(*dptr++); | 3520 | chksum += le32_to_cpu(*dptr++); |
| @@ -4012,7 +4028,7 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) | |||
| 4012 | { | 4028 | { |
| 4013 | int ret, retries; | 4029 | int ret, retries; |
| 4014 | 4030 | ||
| 4015 | if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | 4031 | if (!IS_FWI2_CAPABLE(ha)) |
| 4016 | return; | 4032 | return; |
| 4017 | if (!ha->fw_major_version) | 4033 | if (!ha->fw_major_version) |
| 4018 | return; | 4034 | return; |
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index d3023338628f..8e3b04464cff 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h | |||
| @@ -104,7 +104,7 @@ static __inline__ void qla2x00_poll(scsi_qla_host_t *); | |||
| 104 | static inline void | 104 | static inline void |
| 105 | qla2x00_poll(scsi_qla_host_t *ha) | 105 | qla2x00_poll(scsi_qla_host_t *ha) |
| 106 | { | 106 | { |
| 107 | ha->isp_ops.intr_handler(0, ha); | 107 | ha->isp_ops->intr_handler(0, ha); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *); | 110 | static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *); |
| @@ -163,7 +163,7 @@ static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t); | |||
| 163 | static inline int | 163 | static inline int |
| 164 | qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id) | 164 | qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id) |
| 165 | { | 165 | { |
| 166 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 166 | if (IS_FWI2_CAPABLE(ha)) |
| 167 | return (loop_id > NPH_LAST_HANDLE); | 167 | return (loop_id > NPH_LAST_HANDLE); |
| 168 | 168 | ||
| 169 | return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) || | 169 | return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) || |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index c71863ff5489..3a5e78cb6b3f 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
| @@ -326,7 +326,7 @@ qla2x00_start_scsi(srb_t *sp) | |||
| 326 | tot_dsds = nseg; | 326 | tot_dsds = nseg; |
| 327 | 327 | ||
| 328 | /* Calculate the number of request entries needed. */ | 328 | /* Calculate the number of request entries needed. */ |
| 329 | req_cnt = ha->isp_ops.calc_req_entries(tot_dsds); | 329 | req_cnt = ha->isp_ops->calc_req_entries(tot_dsds); |
| 330 | if (ha->req_q_cnt < (req_cnt + 2)) { | 330 | if (ha->req_q_cnt < (req_cnt + 2)) { |
| 331 | cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg)); | 331 | cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg)); |
| 332 | if (ha->req_ring_index < cnt) | 332 | if (ha->req_ring_index < cnt) |
| @@ -364,7 +364,7 @@ qla2x00_start_scsi(srb_t *sp) | |||
| 364 | cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); | 364 | cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); |
| 365 | 365 | ||
| 366 | /* Build IOCB segments */ | 366 | /* Build IOCB segments */ |
| 367 | ha->isp_ops.build_iocbs(sp, cmd_pkt, tot_dsds); | 367 | ha->isp_ops->build_iocbs(sp, cmd_pkt, tot_dsds); |
| 368 | 368 | ||
| 369 | /* Set total data segment count. */ | 369 | /* Set total data segment count. */ |
| 370 | cmd_pkt->entry_count = (uint8_t)req_cnt; | 370 | cmd_pkt->entry_count = (uint8_t)req_cnt; |
| @@ -432,7 +432,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, | |||
| 432 | mrk->entry_type = MARKER_TYPE; | 432 | mrk->entry_type = MARKER_TYPE; |
| 433 | mrk->modifier = type; | 433 | mrk->modifier = type; |
| 434 | if (type != MK_SYNC_ALL) { | 434 | if (type != MK_SYNC_ALL) { |
| 435 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 435 | if (IS_FWI2_CAPABLE(ha)) { |
| 436 | mrk24 = (struct mrk_entry_24xx *) mrk; | 436 | mrk24 = (struct mrk_entry_24xx *) mrk; |
| 437 | mrk24->nport_handle = cpu_to_le16(loop_id); | 437 | mrk24->nport_handle = cpu_to_le16(loop_id); |
| 438 | mrk24->lun[1] = LSB(lun); | 438 | mrk24->lun[1] = LSB(lun); |
| @@ -487,7 +487,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha) | |||
| 487 | for (timer = HZ; timer; timer--) { | 487 | for (timer = HZ; timer; timer--) { |
| 488 | if ((req_cnt + 2) >= ha->req_q_cnt) { | 488 | if ((req_cnt + 2) >= ha->req_q_cnt) { |
| 489 | /* Calculate number of free request entries. */ | 489 | /* Calculate number of free request entries. */ |
| 490 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 490 | if (IS_FWI2_CAPABLE(ha)) |
| 491 | cnt = (uint16_t)RD_REG_DWORD( | 491 | cnt = (uint16_t)RD_REG_DWORD( |
| 492 | ®->isp24.req_q_out); | 492 | ®->isp24.req_q_out); |
| 493 | else | 493 | else |
| @@ -561,7 +561,7 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha) | |||
| 561 | ha->request_ring_ptr++; | 561 | ha->request_ring_ptr++; |
| 562 | 562 | ||
| 563 | /* Set chip new ring index. */ | 563 | /* Set chip new ring index. */ |
| 564 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 564 | if (IS_FWI2_CAPABLE(ha)) { |
| 565 | WRT_REG_DWORD(®->isp24.req_q_in, ha->req_ring_index); | 565 | WRT_REG_DWORD(®->isp24.req_q_in, ha->req_ring_index); |
| 566 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); | 566 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); |
| 567 | } else { | 567 | } else { |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 0ba4c8d37879..b8f226ae2633 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
| @@ -143,7 +143,7 @@ qla2300_intr_handler(int irq, void *dev_id) | |||
| 143 | WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); | 143 | WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); |
| 144 | RD_REG_WORD(®->hccr); | 144 | RD_REG_WORD(®->hccr); |
| 145 | 145 | ||
| 146 | ha->isp_ops.fw_dump(ha, 1); | 146 | ha->isp_ops->fw_dump(ha, 1); |
| 147 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 147 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
| 148 | break; | 148 | break; |
| 149 | } else if ((stat & HSR_RISC_INT) == 0) | 149 | } else if ((stat & HSR_RISC_INT) == 0) |
| @@ -247,7 +247,7 @@ void | |||
| 247 | qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | 247 | qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) |
| 248 | { | 248 | { |
| 249 | #define LS_UNKNOWN 2 | 249 | #define LS_UNKNOWN 2 |
| 250 | static char *link_speeds[5] = { "1", "2", "?", "4", "10" }; | 250 | static char *link_speeds[5] = { "1", "2", "?", "4", "8" }; |
| 251 | char *link_speed; | 251 | char *link_speed; |
| 252 | uint16_t handle_cnt; | 252 | uint16_t handle_cnt; |
| 253 | uint16_t cnt; | 253 | uint16_t cnt; |
| @@ -334,9 +334,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
| 334 | "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", | 334 | "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", |
| 335 | mb[1], mb[2], mb[3]); | 335 | mb[1], mb[2], mb[3]); |
| 336 | 336 | ||
| 337 | ha->isp_ops.fw_dump(ha, 1); | 337 | ha->isp_ops->fw_dump(ha, 1); |
| 338 | 338 | ||
| 339 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 339 | if (IS_FWI2_CAPABLE(ha)) { |
| 340 | if (mb[1] == 0 && mb[2] == 0) { | 340 | if (mb[1] == 0 && mb[2] == 0) { |
| 341 | qla_printk(KERN_ERR, ha, | 341 | qla_printk(KERN_ERR, ha, |
| 342 | "Unrecoverable Hardware Error: adapter " | 342 | "Unrecoverable Hardware Error: adapter " |
| @@ -601,7 +601,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
| 601 | "scsi(%ld): [R|Z]IO update completion.\n", | 601 | "scsi(%ld): [R|Z]IO update completion.\n", |
| 602 | ha->host_no)); | 602 | ha->host_no)); |
| 603 | 603 | ||
| 604 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 604 | if (IS_FWI2_CAPABLE(ha)) |
| 605 | qla24xx_process_response_queue(ha); | 605 | qla24xx_process_response_queue(ha); |
| 606 | else | 606 | else |
| 607 | qla2x00_process_response_queue(ha); | 607 | qla2x00_process_response_queue(ha); |
| @@ -823,7 +823,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
| 823 | 823 | ||
| 824 | sts = (sts_entry_t *) pkt; | 824 | sts = (sts_entry_t *) pkt; |
| 825 | sts24 = (struct sts_entry_24xx *) pkt; | 825 | sts24 = (struct sts_entry_24xx *) pkt; |
| 826 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 826 | if (IS_FWI2_CAPABLE(ha)) { |
| 827 | comp_status = le16_to_cpu(sts24->comp_status); | 827 | comp_status = le16_to_cpu(sts24->comp_status); |
| 828 | scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; | 828 | scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; |
| 829 | } else { | 829 | } else { |
| @@ -872,7 +872,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
| 872 | fcport = sp->fcport; | 872 | fcport = sp->fcport; |
| 873 | 873 | ||
| 874 | sense_len = rsp_info_len = resid_len = fw_resid_len = 0; | 874 | sense_len = rsp_info_len = resid_len = fw_resid_len = 0; |
| 875 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 875 | if (IS_FWI2_CAPABLE(ha)) { |
| 876 | sense_len = le32_to_cpu(sts24->sense_len); | 876 | sense_len = le32_to_cpu(sts24->sense_len); |
| 877 | rsp_info_len = le32_to_cpu(sts24->rsp_data_len); | 877 | rsp_info_len = le32_to_cpu(sts24->rsp_data_len); |
| 878 | resid_len = le32_to_cpu(sts24->rsp_residual_count); | 878 | resid_len = le32_to_cpu(sts24->rsp_residual_count); |
| @@ -891,7 +891,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
| 891 | /* Check for any FCP transport errors. */ | 891 | /* Check for any FCP transport errors. */ |
| 892 | if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { | 892 | if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { |
| 893 | /* Sense data lies beyond any FCP RESPONSE data. */ | 893 | /* Sense data lies beyond any FCP RESPONSE data. */ |
| 894 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 894 | if (IS_FWI2_CAPABLE(ha)) |
| 895 | sense_data += rsp_info_len; | 895 | sense_data += rsp_info_len; |
| 896 | if (rsp_info_len > 3 && rsp_info[3]) { | 896 | if (rsp_info_len > 3 && rsp_info[3]) { |
| 897 | DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " | 897 | DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " |
| @@ -990,7 +990,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
| 990 | case CS_DATA_UNDERRUN: | 990 | case CS_DATA_UNDERRUN: |
| 991 | resid = resid_len; | 991 | resid = resid_len; |
| 992 | /* Use F/W calculated residual length. */ | 992 | /* Use F/W calculated residual length. */ |
| 993 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 993 | if (IS_FWI2_CAPABLE(ha)) |
| 994 | resid = fw_resid_len; | 994 | resid = fw_resid_len; |
| 995 | 995 | ||
| 996 | if (scsi_status & SS_RESIDUAL_UNDER) { | 996 | if (scsi_status & SS_RESIDUAL_UNDER) { |
| @@ -1062,6 +1062,25 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
| 1062 | cp->device->id, cp->device->lun, cp, | 1062 | cp->device->id, cp->device->lun, cp, |
| 1063 | cp->serial_number)); | 1063 | cp->serial_number)); |
| 1064 | 1064 | ||
| 1065 | /* | ||
| 1066 | * In case of a Underrun condition, set both the lscsi | ||
| 1067 | * status and the completion status to appropriate | ||
| 1068 | * values. | ||
| 1069 | */ | ||
| 1070 | if (resid && | ||
| 1071 | ((unsigned)(cp->request_bufflen - resid) < | ||
| 1072 | cp->underflow)) { | ||
| 1073 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
| 1074 | "scsi(%ld:%d:%d:%d): Mid-layer underflow " | ||
| 1075 | "detected (%x of %x bytes)...returning " | ||
| 1076 | "error status.\n", ha->host_no, | ||
| 1077 | cp->device->channel, cp->device->id, | ||
| 1078 | cp->device->lun, resid, | ||
| 1079 | cp->request_bufflen)); | ||
| 1080 | |||
| 1081 | cp->result = DID_ERROR << 16 | lscsi_status; | ||
| 1082 | } | ||
| 1083 | |||
| 1065 | if (sense_len) | 1084 | if (sense_len) |
| 1066 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, | 1085 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, |
| 1067 | CMD_ACTUAL_SNSLEN(cp))); | 1086 | CMD_ACTUAL_SNSLEN(cp))); |
| @@ -1166,7 +1185,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
| 1166 | case CS_TIMEOUT: | 1185 | case CS_TIMEOUT: |
| 1167 | cp->result = DID_BUS_BUSY << 16; | 1186 | cp->result = DID_BUS_BUSY << 16; |
| 1168 | 1187 | ||
| 1169 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1188 | if (IS_FWI2_CAPABLE(ha)) { |
| 1170 | DEBUG2(printk(KERN_INFO | 1189 | DEBUG2(printk(KERN_INFO |
| 1171 | "scsi(%ld:%d:%d:%d): TIMEOUT status detected " | 1190 | "scsi(%ld:%d:%d:%d): TIMEOUT status detected " |
| 1172 | "0x%x-0x%x\n", ha->host_no, cp->device->channel, | 1191 | "0x%x-0x%x\n", ha->host_no, cp->device->channel, |
| @@ -1235,7 +1254,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) | |||
| 1235 | } | 1254 | } |
| 1236 | 1255 | ||
| 1237 | /* Move sense data. */ | 1256 | /* Move sense data. */ |
| 1238 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 1257 | if (IS_FWI2_CAPABLE(ha)) |
| 1239 | host_to_fcp_swap(pkt->data, sizeof(pkt->data)); | 1258 | host_to_fcp_swap(pkt->data, sizeof(pkt->data)); |
| 1240 | memcpy(sp->request_sense_ptr, pkt->data, sense_sz); | 1259 | memcpy(sp->request_sense_ptr, pkt->data, sense_sz); |
| 1241 | DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); | 1260 | DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); |
| @@ -1483,7 +1502,7 @@ qla24xx_intr_handler(int irq, void *dev_id) | |||
| 1483 | 1502 | ||
| 1484 | qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " | 1503 | qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " |
| 1485 | "Dumping firmware!\n", hccr); | 1504 | "Dumping firmware!\n", hccr); |
| 1486 | ha->isp_ops.fw_dump(ha, 1); | 1505 | ha->isp_ops->fw_dump(ha, 1); |
| 1487 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 1506 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
| 1488 | break; | 1507 | break; |
| 1489 | } else if ((stat & HSRX_RISC_INT) == 0) | 1508 | } else if ((stat & HSRX_RISC_INT) == 0) |
| @@ -1617,7 +1636,7 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
| 1617 | 1636 | ||
| 1618 | qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " | 1637 | qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " |
| 1619 | "Dumping firmware!\n", hccr); | 1638 | "Dumping firmware!\n", hccr); |
| 1620 | ha->isp_ops.fw_dump(ha, 1); | 1639 | ha->isp_ops->fw_dump(ha, 1); |
| 1621 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 1640 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
| 1622 | break; | 1641 | break; |
| 1623 | } else if ((stat & HSRX_RISC_INT) == 0) | 1642 | } else if ((stat & HSRX_RISC_INT) == 0) |
| @@ -1739,11 +1758,11 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) | |||
| 1739 | int ret; | 1758 | int ret; |
| 1740 | 1759 | ||
| 1741 | /* If possible, enable MSI-X. */ | 1760 | /* If possible, enable MSI-X. */ |
| 1742 | if (!IS_QLA2432(ha)) | 1761 | if (!IS_QLA2432(ha) && !IS_QLA2532(ha)) |
| 1743 | goto skip_msix; | 1762 | goto skip_msix; |
| 1744 | 1763 | ||
| 1745 | if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX || | 1764 | if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX || |
| 1746 | !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) { | 1765 | !QLA_MSIX_FW_MODE_1(ha->fw_attributes))) { |
| 1747 | DEBUG2(qla_printk(KERN_WARNING, ha, | 1766 | DEBUG2(qla_printk(KERN_WARNING, ha, |
| 1748 | "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n", | 1767 | "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n", |
| 1749 | ha->chip_revision, ha->fw_attributes)); | 1768 | ha->chip_revision, ha->fw_attributes)); |
| @@ -1762,7 +1781,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) | |||
| 1762 | "MSI-X: Falling back-to INTa mode -- %d.\n", ret); | 1781 | "MSI-X: Falling back-to INTa mode -- %d.\n", ret); |
| 1763 | skip_msix: | 1782 | skip_msix: |
| 1764 | 1783 | ||
| 1765 | if (!IS_QLA24XX(ha)) | 1784 | if (!IS_QLA24XX(ha) && !IS_QLA2532(ha)) |
| 1766 | goto skip_msi; | 1785 | goto skip_msi; |
| 1767 | 1786 | ||
| 1768 | ret = pci_enable_msi(ha->pdev); | 1787 | ret = pci_enable_msi(ha->pdev); |
| @@ -1772,7 +1791,7 @@ skip_msix: | |||
| 1772 | } | 1791 | } |
| 1773 | skip_msi: | 1792 | skip_msi: |
| 1774 | 1793 | ||
| 1775 | ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler, | 1794 | ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, |
| 1776 | IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); | 1795 | IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); |
| 1777 | if (!ret) { | 1796 | if (!ret) { |
| 1778 | ha->flags.inta_enabled = 1; | 1797 | ha->flags.inta_enabled = 1; |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 2cd0cff25928..d3746ec80a85 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
| @@ -90,7 +90,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) | |||
| 90 | spin_lock_irqsave(&ha->hardware_lock, flags); | 90 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 91 | 91 | ||
| 92 | /* Load mailbox registers. */ | 92 | /* Load mailbox registers. */ |
| 93 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 93 | if (IS_FWI2_CAPABLE(ha)) |
| 94 | optr = (uint16_t __iomem *)®->isp24.mailbox0; | 94 | optr = (uint16_t __iomem *)®->isp24.mailbox0; |
| 95 | else | 95 | else |
| 96 | optr = (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 0); | 96 | optr = (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 0); |
| @@ -154,7 +154,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) | |||
| 154 | 154 | ||
| 155 | set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); | 155 | set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); |
| 156 | 156 | ||
| 157 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 157 | if (IS_FWI2_CAPABLE(ha)) |
| 158 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); | 158 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); |
| 159 | else | 159 | else |
| 160 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); | 160 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); |
| @@ -175,7 +175,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) | |||
| 175 | DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, | 175 | DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, |
| 176 | ha->host_no, command)); | 176 | ha->host_no, command)); |
| 177 | 177 | ||
| 178 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 178 | if (IS_FWI2_CAPABLE(ha)) |
| 179 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); | 179 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); |
| 180 | else | 180 | else |
| 181 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); | 181 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); |
| @@ -228,7 +228,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) | |||
| 228 | uint16_t mb0; | 228 | uint16_t mb0; |
| 229 | uint32_t ictrl; | 229 | uint32_t ictrl; |
| 230 | 230 | ||
| 231 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 231 | if (IS_FWI2_CAPABLE(ha)) { |
| 232 | mb0 = RD_REG_WORD(®->isp24.mailbox0); | 232 | mb0 = RD_REG_WORD(®->isp24.mailbox0); |
| 233 | ictrl = RD_REG_DWORD(®->isp24.ictrl); | 233 | ictrl = RD_REG_DWORD(®->isp24.ictrl); |
| 234 | } else { | 234 | } else { |
| @@ -322,7 +322,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, | |||
| 322 | 322 | ||
| 323 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 323 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
| 324 | 324 | ||
| 325 | if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 325 | if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) { |
| 326 | mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; | 326 | mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; |
| 327 | mcp->mb[8] = MSW(risc_addr); | 327 | mcp->mb[8] = MSW(risc_addr); |
| 328 | mcp->out_mb = MBX_8|MBX_0; | 328 | mcp->out_mb = MBX_8|MBX_0; |
| @@ -336,7 +336,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, | |||
| 336 | mcp->mb[6] = MSW(MSD(req_dma)); | 336 | mcp->mb[6] = MSW(MSD(req_dma)); |
| 337 | mcp->mb[7] = LSW(MSD(req_dma)); | 337 | mcp->mb[7] = LSW(MSD(req_dma)); |
| 338 | mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; | 338 | mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; |
| 339 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 339 | if (IS_FWI2_CAPABLE(ha)) { |
| 340 | mcp->mb[4] = MSW(risc_code_size); | 340 | mcp->mb[4] = MSW(risc_code_size); |
| 341 | mcp->mb[5] = LSW(risc_code_size); | 341 | mcp->mb[5] = LSW(risc_code_size); |
| 342 | mcp->out_mb |= MBX_5|MBX_4; | 342 | mcp->out_mb |= MBX_5|MBX_4; |
| @@ -387,7 +387,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) | |||
| 387 | mcp->mb[0] = MBC_EXECUTE_FIRMWARE; | 387 | mcp->mb[0] = MBC_EXECUTE_FIRMWARE; |
| 388 | mcp->out_mb = MBX_0; | 388 | mcp->out_mb = MBX_0; |
| 389 | mcp->in_mb = MBX_0; | 389 | mcp->in_mb = MBX_0; |
| 390 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 390 | if (IS_FWI2_CAPABLE(ha)) { |
| 391 | mcp->mb[1] = MSW(risc_addr); | 391 | mcp->mb[1] = MSW(risc_addr); |
| 392 | mcp->mb[2] = LSW(risc_addr); | 392 | mcp->mb[2] = LSW(risc_addr); |
| 393 | mcp->mb[3] = 0; | 393 | mcp->mb[3] = 0; |
| @@ -410,7 +410,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) | |||
| 410 | DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, | 410 | DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, |
| 411 | ha->host_no, rval, mcp->mb[0])); | 411 | ha->host_no, rval, mcp->mb[0])); |
| 412 | } else { | 412 | } else { |
| 413 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 413 | if (IS_FWI2_CAPABLE(ha)) { |
| 414 | DEBUG11(printk("%s(%ld): done exchanges=%x.\n", | 414 | DEBUG11(printk("%s(%ld): done exchanges=%x.\n", |
| 415 | __func__, ha->host_no, mcp->mb[1])); | 415 | __func__, ha->host_no, mcp->mb[1])); |
| 416 | } else { | 416 | } else { |
| @@ -551,7 +551,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts) | |||
| 551 | mcp->mb[3] = fwopts[3]; | 551 | mcp->mb[3] = fwopts[3]; |
| 552 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; | 552 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; |
| 553 | mcp->in_mb = MBX_0; | 553 | mcp->in_mb = MBX_0; |
| 554 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 554 | if (IS_FWI2_CAPABLE(ha)) { |
| 555 | mcp->in_mb |= MBX_1; | 555 | mcp->in_mb |= MBX_1; |
| 556 | } else { | 556 | } else { |
| 557 | mcp->mb[10] = fwopts[10]; | 557 | mcp->mb[10] = fwopts[10]; |
| @@ -664,7 +664,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) | |||
| 664 | mcp->mb[0] = MBC_VERIFY_CHECKSUM; | 664 | mcp->mb[0] = MBC_VERIFY_CHECKSUM; |
| 665 | mcp->out_mb = MBX_0; | 665 | mcp->out_mb = MBX_0; |
| 666 | mcp->in_mb = MBX_0; | 666 | mcp->in_mb = MBX_0; |
| 667 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 667 | if (IS_FWI2_CAPABLE(ha)) { |
| 668 | mcp->mb[1] = MSW(risc_addr); | 668 | mcp->mb[1] = MSW(risc_addr); |
| 669 | mcp->mb[2] = LSW(risc_addr); | 669 | mcp->mb[2] = LSW(risc_addr); |
| 670 | mcp->out_mb |= MBX_2|MBX_1; | 670 | mcp->out_mb |= MBX_2|MBX_1; |
| @@ -681,8 +681,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) | |||
| 681 | 681 | ||
| 682 | if (rval != QLA_SUCCESS) { | 682 | if (rval != QLA_SUCCESS) { |
| 683 | DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__, | 683 | DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__, |
| 684 | ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? | 684 | ha->host_no, rval, IS_FWI2_CAPABLE(ha) ? |
| 685 | (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]))); | 685 | (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1])); |
| 686 | } else { | 686 | } else { |
| 687 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); | 687 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); |
| 688 | } | 688 | } |
| @@ -739,7 +739,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, | |||
| 739 | 739 | ||
| 740 | /* Mask reserved bits. */ | 740 | /* Mask reserved bits. */ |
| 741 | sts_entry->entry_status &= | 741 | sts_entry->entry_status &= |
| 742 | IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RF_MASK_24XX :RF_MASK; | 742 | IS_FWI2_CAPABLE(ha) ? RF_MASK_24XX :RF_MASK; |
| 743 | } | 743 | } |
| 744 | 744 | ||
| 745 | return rval; | 745 | return rval; |
| @@ -1085,7 +1085,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) | |||
| 1085 | memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); | 1085 | memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); |
| 1086 | 1086 | ||
| 1087 | mcp->mb[0] = MBC_GET_PORT_DATABASE; | 1087 | mcp->mb[0] = MBC_GET_PORT_DATABASE; |
| 1088 | if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | 1088 | if (opt != 0 && !IS_FWI2_CAPABLE(ha)) |
| 1089 | mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; | 1089 | mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; |
| 1090 | mcp->mb[2] = MSW(pd_dma); | 1090 | mcp->mb[2] = MSW(pd_dma); |
| 1091 | mcp->mb[3] = LSW(pd_dma); | 1091 | mcp->mb[3] = LSW(pd_dma); |
| @@ -1094,7 +1094,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) | |||
| 1094 | mcp->mb[9] = ha->vp_idx; | 1094 | mcp->mb[9] = ha->vp_idx; |
| 1095 | mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | 1095 | mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; |
| 1096 | mcp->in_mb = MBX_0; | 1096 | mcp->in_mb = MBX_0; |
| 1097 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1097 | if (IS_FWI2_CAPABLE(ha)) { |
| 1098 | mcp->mb[1] = fcport->loop_id; | 1098 | mcp->mb[1] = fcport->loop_id; |
| 1099 | mcp->mb[10] = opt; | 1099 | mcp->mb[10] = opt; |
| 1100 | mcp->out_mb |= MBX_10|MBX_1; | 1100 | mcp->out_mb |= MBX_10|MBX_1; |
| @@ -1107,15 +1107,15 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) | |||
| 1107 | mcp->mb[1] = fcport->loop_id << 8 | opt; | 1107 | mcp->mb[1] = fcport->loop_id << 8 | opt; |
| 1108 | mcp->out_mb |= MBX_1; | 1108 | mcp->out_mb |= MBX_1; |
| 1109 | } | 1109 | } |
| 1110 | mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? | 1110 | mcp->buf_size = IS_FWI2_CAPABLE(ha) ? |
| 1111 | PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE); | 1111 | PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE; |
| 1112 | mcp->flags = MBX_DMA_IN; | 1112 | mcp->flags = MBX_DMA_IN; |
| 1113 | mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); | 1113 | mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); |
| 1114 | rval = qla2x00_mailbox_command(ha, mcp); | 1114 | rval = qla2x00_mailbox_command(ha, mcp); |
| 1115 | if (rval != QLA_SUCCESS) | 1115 | if (rval != QLA_SUCCESS) |
| 1116 | goto gpd_error_out; | 1116 | goto gpd_error_out; |
| 1117 | 1117 | ||
| 1118 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1118 | if (IS_FWI2_CAPABLE(ha)) { |
| 1119 | pd24 = (struct port_database_24xx *) pd; | 1119 | pd24 = (struct port_database_24xx *) pd; |
| 1120 | 1120 | ||
| 1121 | /* Check for logged in state. */ | 1121 | /* Check for logged in state. */ |
| @@ -1333,7 +1333,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha) | |||
| 1333 | 1333 | ||
| 1334 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 1334 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
| 1335 | 1335 | ||
| 1336 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1336 | if (IS_FWI2_CAPABLE(ha)) { |
| 1337 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; | 1337 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; |
| 1338 | mcp->mb[1] = BIT_6; | 1338 | mcp->mb[1] = BIT_6; |
| 1339 | mcp->mb[2] = 0; | 1339 | mcp->mb[2] = 0; |
| @@ -1637,7 +1637,7 @@ qla2x00_login_local_device(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
| 1637 | mbx_cmd_t mc; | 1637 | mbx_cmd_t mc; |
| 1638 | mbx_cmd_t *mcp = &mc; | 1638 | mbx_cmd_t *mcp = &mc; |
| 1639 | 1639 | ||
| 1640 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 1640 | if (IS_FWI2_CAPABLE(ha)) |
| 1641 | return qla24xx_login_fabric(ha, fcport->loop_id, | 1641 | return qla24xx_login_fabric(ha, fcport->loop_id, |
| 1642 | fcport->d_id.b.domain, fcport->d_id.b.area, | 1642 | fcport->d_id.b.domain, fcport->d_id.b.area, |
| 1643 | fcport->d_id.b.al_pa, mb_ret, opt); | 1643 | fcport->d_id.b.al_pa, mb_ret, opt); |
| @@ -1821,7 +1821,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha) | |||
| 1821 | ha->host_no)); | 1821 | ha->host_no)); |
| 1822 | 1822 | ||
| 1823 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; | 1823 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; |
| 1824 | mcp->mb[1] = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? BIT_3: 0; | 1824 | mcp->mb[1] = IS_FWI2_CAPABLE(ha) ? BIT_3: 0; |
| 1825 | mcp->mb[2] = 0; | 1825 | mcp->mb[2] = 0; |
| 1826 | mcp->mb[3] = 0; | 1826 | mcp->mb[3] = 0; |
| 1827 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; | 1827 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; |
| @@ -1871,7 +1871,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, | |||
| 1871 | 1871 | ||
| 1872 | mcp->mb[0] = MBC_GET_ID_LIST; | 1872 | mcp->mb[0] = MBC_GET_ID_LIST; |
| 1873 | mcp->out_mb = MBX_0; | 1873 | mcp->out_mb = MBX_0; |
| 1874 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1874 | if (IS_FWI2_CAPABLE(ha)) { |
| 1875 | mcp->mb[2] = MSW(id_list_dma); | 1875 | mcp->mb[2] = MSW(id_list_dma); |
| 1876 | mcp->mb[3] = LSW(id_list_dma); | 1876 | mcp->mb[3] = LSW(id_list_dma); |
| 1877 | mcp->mb[6] = MSW(MSD(id_list_dma)); | 1877 | mcp->mb[6] = MSW(MSD(id_list_dma)); |
| @@ -2063,7 +2063,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, | |||
| 2063 | mcp->mb[7] = LSW(MSD(stat_buf_dma)); | 2063 | mcp->mb[7] = LSW(MSD(stat_buf_dma)); |
| 2064 | mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | 2064 | mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; |
| 2065 | mcp->in_mb = MBX_0; | 2065 | mcp->in_mb = MBX_0; |
| 2066 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 2066 | if (IS_FWI2_CAPABLE(ha)) { |
| 2067 | mcp->mb[1] = loop_id; | 2067 | mcp->mb[1] = loop_id; |
| 2068 | mcp->mb[4] = 0; | 2068 | mcp->mb[4] = 0; |
| 2069 | mcp->mb[10] = 0; | 2069 | mcp->mb[10] = 0; |
| @@ -2334,7 +2334,7 @@ qla2x00_system_error(scsi_qla_host_t *ha) | |||
| 2334 | mbx_cmd_t mc; | 2334 | mbx_cmd_t mc; |
| 2335 | mbx_cmd_t *mcp = &mc; | 2335 | mbx_cmd_t *mcp = &mc; |
| 2336 | 2336 | ||
| 2337 | if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | 2337 | if (!IS_FWI2_CAPABLE(ha)) |
| 2338 | return QLA_FUNCTION_FAILED; | 2338 | return QLA_FUNCTION_FAILED; |
| 2339 | 2339 | ||
| 2340 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 2340 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
| @@ -2444,7 +2444,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha) | |||
| 2444 | mbx_cmd_t mc; | 2444 | mbx_cmd_t mc; |
| 2445 | mbx_cmd_t *mcp = &mc; | 2445 | mbx_cmd_t *mcp = &mc; |
| 2446 | 2446 | ||
| 2447 | if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | 2447 | if (!IS_FWI2_CAPABLE(ha)) |
| 2448 | return QLA_FUNCTION_FAILED; | 2448 | return QLA_FUNCTION_FAILED; |
| 2449 | 2449 | ||
| 2450 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 2450 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
| @@ -2474,7 +2474,7 @@ qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma, | |||
| 2474 | mbx_cmd_t mc; | 2474 | mbx_cmd_t mc; |
| 2475 | mbx_cmd_t *mcp = &mc; | 2475 | mbx_cmd_t *mcp = &mc; |
| 2476 | 2476 | ||
| 2477 | if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | 2477 | if (!IS_FWI2_CAPABLE(ha)) |
| 2478 | return QLA_FUNCTION_FAILED; | 2478 | return QLA_FUNCTION_FAILED; |
| 2479 | 2479 | ||
| 2480 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 2480 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
| @@ -2514,7 +2514,7 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr, | |||
| 2514 | mbx_cmd_t mc; | 2514 | mbx_cmd_t mc; |
| 2515 | mbx_cmd_t *mcp = &mc; | 2515 | mbx_cmd_t *mcp = &mc; |
| 2516 | 2516 | ||
| 2517 | if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | 2517 | if (!IS_FWI2_CAPABLE(ha)) |
| 2518 | return QLA_FUNCTION_FAILED; | 2518 | return QLA_FUNCTION_FAILED; |
| 2519 | 2519 | ||
| 2520 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 2520 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
| @@ -2552,7 +2552,7 @@ qla2x00_get_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, | |||
| 2552 | mbx_cmd_t mc; | 2552 | mbx_cmd_t mc; |
| 2553 | mbx_cmd_t *mcp = &mc; | 2553 | mbx_cmd_t *mcp = &mc; |
| 2554 | 2554 | ||
| 2555 | if (!IS_QLA24XX(ha)) | 2555 | if (!IS_IIDMA_CAPABLE(ha)) |
| 2556 | return QLA_FUNCTION_FAILED; | 2556 | return QLA_FUNCTION_FAILED; |
| 2557 | 2557 | ||
| 2558 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 2558 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
| @@ -2595,7 +2595,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, | |||
| 2595 | mbx_cmd_t mc; | 2595 | mbx_cmd_t mc; |
| 2596 | mbx_cmd_t *mcp = &mc; | 2596 | mbx_cmd_t *mcp = &mc; |
| 2597 | 2597 | ||
| 2598 | if (!IS_QLA24XX(ha)) | 2598 | if (!IS_IIDMA_CAPABLE(ha)) |
| 2599 | return QLA_FUNCTION_FAILED; | 2599 | return QLA_FUNCTION_FAILED; |
| 2600 | 2600 | ||
| 2601 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 2601 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 92376f9dfdd5..c488996cb958 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
| @@ -265,6 +265,8 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str) | |||
| 265 | strcpy(str, "PCIe ("); | 265 | strcpy(str, "PCIe ("); |
| 266 | if (lspeed == 1) | 266 | if (lspeed == 1) |
| 267 | strcat(str, "2.5Gb/s "); | 267 | strcat(str, "2.5Gb/s "); |
| 268 | else if (lspeed == 2) | ||
| 269 | strcat(str, "5.0Gb/s "); | ||
| 268 | else | 270 | else |
| 269 | strcat(str, "<unknown> "); | 271 | strcat(str, "<unknown> "); |
| 270 | snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth); | 272 | snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth); |
| @@ -343,6 +345,12 @@ qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str) | |||
| 343 | strcat(str, "[IP] "); | 345 | strcat(str, "[IP] "); |
| 344 | if (ha->fw_attributes & BIT_2) | 346 | if (ha->fw_attributes & BIT_2) |
| 345 | strcat(str, "[Multi-ID] "); | 347 | strcat(str, "[Multi-ID] "); |
| 348 | if (ha->fw_attributes & BIT_3) | ||
| 349 | strcat(str, "[SB-2] "); | ||
| 350 | if (ha->fw_attributes & BIT_4) | ||
| 351 | strcat(str, "[T10 CRC] "); | ||
| 352 | if (ha->fw_attributes & BIT_5) | ||
| 353 | strcat(str, "[VI] "); | ||
| 346 | if (ha->fw_attributes & BIT_13) | 354 | if (ha->fw_attributes & BIT_13) |
| 347 | strcat(str, "[Experimental]"); | 355 | strcat(str, "[Experimental]"); |
| 348 | return str; | 356 | return str; |
| @@ -681,7 +689,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
| 681 | DEBUG3(qla2x00_print_scsi_cmd(cmd)); | 689 | DEBUG3(qla2x00_print_scsi_cmd(cmd)); |
| 682 | 690 | ||
| 683 | spin_unlock_irqrestore(&pha->hardware_lock, flags); | 691 | spin_unlock_irqrestore(&pha->hardware_lock, flags); |
| 684 | if (ha->isp_ops.abort_command(ha, sp)) { | 692 | if (ha->isp_ops->abort_command(ha, sp)) { |
| 685 | DEBUG2(printk("%s(%ld): abort_command " | 693 | DEBUG2(printk("%s(%ld): abort_command " |
| 686 | "mbx failed.\n", __func__, ha->host_no)); | 694 | "mbx failed.\n", __func__, ha->host_no)); |
| 687 | } else { | 695 | } else { |
| @@ -813,7 +821,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
| 813 | #if defined(LOGOUT_AFTER_DEVICE_RESET) | 821 | #if defined(LOGOUT_AFTER_DEVICE_RESET) |
| 814 | if (ret == SUCCESS) { | 822 | if (ret == SUCCESS) { |
| 815 | if (fcport->flags & FC_FABRIC_DEVICE) { | 823 | if (fcport->flags & FC_FABRIC_DEVICE) { |
| 816 | ha->isp_ops.fabric_logout(ha, fcport->loop_id); | 824 | ha->isp_ops->fabric_logout(ha, fcport->loop_id); |
| 817 | qla2x00_mark_device_lost(ha, fcport, 0, 0); | 825 | qla2x00_mark_device_lost(ha, fcport, 0, 0); |
| 818 | } | 826 | } |
| 819 | } | 827 | } |
| @@ -1105,7 +1113,7 @@ static int | |||
| 1105 | qla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport) | 1113 | qla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport) |
| 1106 | { | 1114 | { |
| 1107 | /* Abort Target command will clear Reservation */ | 1115 | /* Abort Target command will clear Reservation */ |
| 1108 | return ha->isp_ops.abort_target(reset_fcport); | 1116 | return ha->isp_ops->abort_target(reset_fcport); |
| 1109 | } | 1117 | } |
| 1110 | 1118 | ||
| 1111 | static int | 1119 | static int |
| @@ -1184,8 +1192,8 @@ qla2x00_config_dma_addressing(scsi_qla_host_t *ha) | |||
| 1184 | !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) { | 1192 | !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) { |
| 1185 | /* Ok, a 64bit DMA mask is applicable. */ | 1193 | /* Ok, a 64bit DMA mask is applicable. */ |
| 1186 | ha->flags.enable_64bit_addressing = 1; | 1194 | ha->flags.enable_64bit_addressing = 1; |
| 1187 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64; | 1195 | ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64; |
| 1188 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64; | 1196 | ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64; |
| 1189 | return; | 1197 | return; |
| 1190 | } | 1198 | } |
| 1191 | } | 1199 | } |
| @@ -1194,6 +1202,193 @@ qla2x00_config_dma_addressing(scsi_qla_host_t *ha) | |||
| 1194 | pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK); | 1202 | pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK); |
| 1195 | } | 1203 | } |
| 1196 | 1204 | ||
| 1205 | static void | ||
| 1206 | qla2x00_enable_intrs(scsi_qla_host_t *ha) | ||
| 1207 | { | ||
| 1208 | unsigned long flags = 0; | ||
| 1209 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | ||
| 1210 | |||
| 1211 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 1212 | ha->interrupts_on = 1; | ||
| 1213 | /* enable risc and host interrupts */ | ||
| 1214 | WRT_REG_WORD(®->ictrl, ICR_EN_INT | ICR_EN_RISC); | ||
| 1215 | RD_REG_WORD(®->ictrl); | ||
| 1216 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 1217 | |||
| 1218 | } | ||
| 1219 | |||
| 1220 | static void | ||
| 1221 | qla2x00_disable_intrs(scsi_qla_host_t *ha) | ||
| 1222 | { | ||
| 1223 | unsigned long flags = 0; | ||
| 1224 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | ||
| 1225 | |||
| 1226 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 1227 | ha->interrupts_on = 0; | ||
| 1228 | /* disable risc and host interrupts */ | ||
| 1229 | WRT_REG_WORD(®->ictrl, 0); | ||
| 1230 | RD_REG_WORD(®->ictrl); | ||
| 1231 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | static void | ||
| 1235 | qla24xx_enable_intrs(scsi_qla_host_t *ha) | ||
| 1236 | { | ||
| 1237 | unsigned long flags = 0; | ||
| 1238 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
| 1239 | |||
| 1240 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 1241 | ha->interrupts_on = 1; | ||
| 1242 | WRT_REG_DWORD(®->ictrl, ICRX_EN_RISC_INT); | ||
| 1243 | RD_REG_DWORD(®->ictrl); | ||
| 1244 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | static void | ||
| 1248 | qla24xx_disable_intrs(scsi_qla_host_t *ha) | ||
| 1249 | { | ||
| 1250 | unsigned long flags = 0; | ||
| 1251 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
| 1252 | |||
| 1253 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 1254 | ha->interrupts_on = 0; | ||
| 1255 | WRT_REG_DWORD(®->ictrl, 0); | ||
| 1256 | RD_REG_DWORD(®->ictrl); | ||
| 1257 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | static struct isp_operations qla2100_isp_ops = { | ||
| 1261 | .pci_config = qla2100_pci_config, | ||
| 1262 | .reset_chip = qla2x00_reset_chip, | ||
| 1263 | .chip_diag = qla2x00_chip_diag, | ||
| 1264 | .config_rings = qla2x00_config_rings, | ||
| 1265 | .reset_adapter = qla2x00_reset_adapter, | ||
| 1266 | .nvram_config = qla2x00_nvram_config, | ||
| 1267 | .update_fw_options = qla2x00_update_fw_options, | ||
| 1268 | .load_risc = qla2x00_load_risc, | ||
| 1269 | .pci_info_str = qla2x00_pci_info_str, | ||
| 1270 | .fw_version_str = qla2x00_fw_version_str, | ||
| 1271 | .intr_handler = qla2100_intr_handler, | ||
| 1272 | .enable_intrs = qla2x00_enable_intrs, | ||
| 1273 | .disable_intrs = qla2x00_disable_intrs, | ||
| 1274 | .abort_command = qla2x00_abort_command, | ||
| 1275 | .abort_target = qla2x00_abort_target, | ||
| 1276 | .fabric_login = qla2x00_login_fabric, | ||
| 1277 | .fabric_logout = qla2x00_fabric_logout, | ||
| 1278 | .calc_req_entries = qla2x00_calc_iocbs_32, | ||
| 1279 | .build_iocbs = qla2x00_build_scsi_iocbs_32, | ||
| 1280 | .prep_ms_iocb = qla2x00_prep_ms_iocb, | ||
| 1281 | .prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb, | ||
| 1282 | .read_nvram = qla2x00_read_nvram_data, | ||
| 1283 | .write_nvram = qla2x00_write_nvram_data, | ||
| 1284 | .fw_dump = qla2100_fw_dump, | ||
| 1285 | .beacon_on = NULL, | ||
| 1286 | .beacon_off = NULL, | ||
| 1287 | .beacon_blink = NULL, | ||
| 1288 | .read_optrom = qla2x00_read_optrom_data, | ||
| 1289 | .write_optrom = qla2x00_write_optrom_data, | ||
| 1290 | .get_flash_version = qla2x00_get_flash_version, | ||
| 1291 | }; | ||
| 1292 | |||
| 1293 | static struct isp_operations qla2300_isp_ops = { | ||
| 1294 | .pci_config = qla2300_pci_config, | ||
| 1295 | .reset_chip = qla2x00_reset_chip, | ||
| 1296 | .chip_diag = qla2x00_chip_diag, | ||
| 1297 | .config_rings = qla2x00_config_rings, | ||
| 1298 | .reset_adapter = qla2x00_reset_adapter, | ||
| 1299 | .nvram_config = qla2x00_nvram_config, | ||
| 1300 | .update_fw_options = qla2x00_update_fw_options, | ||
| 1301 | .load_risc = qla2x00_load_risc, | ||
| 1302 | .pci_info_str = qla2x00_pci_info_str, | ||
| 1303 | .fw_version_str = qla2x00_fw_version_str, | ||
| 1304 | .intr_handler = qla2300_intr_handler, | ||
| 1305 | .enable_intrs = qla2x00_enable_intrs, | ||
| 1306 | .disable_intrs = qla2x00_disable_intrs, | ||
| 1307 | .abort_command = qla2x00_abort_command, | ||
| 1308 | .abort_target = qla2x00_abort_target, | ||
| 1309 | .fabric_login = qla2x00_login_fabric, | ||
| 1310 | .fabric_logout = qla2x00_fabric_logout, | ||
| 1311 | .calc_req_entries = qla2x00_calc_iocbs_32, | ||
| 1312 | .build_iocbs = qla2x00_build_scsi_iocbs_32, | ||
| 1313 | .prep_ms_iocb = qla2x00_prep_ms_iocb, | ||
| 1314 | .prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb, | ||
| 1315 | .read_nvram = qla2x00_read_nvram_data, | ||
| 1316 | .write_nvram = qla2x00_write_nvram_data, | ||
| 1317 | .fw_dump = qla2300_fw_dump, | ||
| 1318 | .beacon_on = qla2x00_beacon_on, | ||
| 1319 | .beacon_off = qla2x00_beacon_off, | ||
| 1320 | .beacon_blink = qla2x00_beacon_blink, | ||
| 1321 | .read_optrom = qla2x00_read_optrom_data, | ||
| 1322 | .write_optrom = qla2x00_write_optrom_data, | ||
| 1323 | .get_flash_version = qla2x00_get_flash_version, | ||
| 1324 | }; | ||
| 1325 | |||
| 1326 | static struct isp_operations qla24xx_isp_ops = { | ||
| 1327 | .pci_config = qla24xx_pci_config, | ||
| 1328 | .reset_chip = qla24xx_reset_chip, | ||
| 1329 | .chip_diag = qla24xx_chip_diag, | ||
| 1330 | .config_rings = qla24xx_config_rings, | ||
| 1331 | .reset_adapter = qla24xx_reset_adapter, | ||
| 1332 | .nvram_config = qla24xx_nvram_config, | ||
| 1333 | .update_fw_options = qla24xx_update_fw_options, | ||
| 1334 | .load_risc = qla24xx_load_risc, | ||
| 1335 | .pci_info_str = qla24xx_pci_info_str, | ||
| 1336 | .fw_version_str = qla24xx_fw_version_str, | ||
| 1337 | .intr_handler = qla24xx_intr_handler, | ||
| 1338 | .enable_intrs = qla24xx_enable_intrs, | ||
| 1339 | .disable_intrs = qla24xx_disable_intrs, | ||
| 1340 | .abort_command = qla24xx_abort_command, | ||
| 1341 | .abort_target = qla24xx_abort_target, | ||
| 1342 | .fabric_login = qla24xx_login_fabric, | ||
| 1343 | .fabric_logout = qla24xx_fabric_logout, | ||
| 1344 | .calc_req_entries = NULL, | ||
| 1345 | .build_iocbs = NULL, | ||
| 1346 | .prep_ms_iocb = qla24xx_prep_ms_iocb, | ||
| 1347 | .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, | ||
| 1348 | .read_nvram = qla24xx_read_nvram_data, | ||
| 1349 | .write_nvram = qla24xx_write_nvram_data, | ||
| 1350 | .fw_dump = qla24xx_fw_dump, | ||
| 1351 | .beacon_on = qla24xx_beacon_on, | ||
| 1352 | .beacon_off = qla24xx_beacon_off, | ||
| 1353 | .beacon_blink = qla24xx_beacon_blink, | ||
| 1354 | .read_optrom = qla24xx_read_optrom_data, | ||
| 1355 | .write_optrom = qla24xx_write_optrom_data, | ||
| 1356 | .get_flash_version = qla24xx_get_flash_version, | ||
| 1357 | }; | ||
| 1358 | |||
| 1359 | static struct isp_operations qla25xx_isp_ops = { | ||
| 1360 | .pci_config = qla25xx_pci_config, | ||
| 1361 | .reset_chip = qla24xx_reset_chip, | ||
| 1362 | .chip_diag = qla24xx_chip_diag, | ||
| 1363 | .config_rings = qla24xx_config_rings, | ||
| 1364 | .reset_adapter = qla24xx_reset_adapter, | ||
| 1365 | .nvram_config = qla24xx_nvram_config, | ||
| 1366 | .update_fw_options = qla24xx_update_fw_options, | ||
| 1367 | .load_risc = qla24xx_load_risc, | ||
| 1368 | .pci_info_str = qla24xx_pci_info_str, | ||
| 1369 | .fw_version_str = qla24xx_fw_version_str, | ||
| 1370 | .intr_handler = qla24xx_intr_handler, | ||
| 1371 | .enable_intrs = qla24xx_enable_intrs, | ||
| 1372 | .disable_intrs = qla24xx_disable_intrs, | ||
| 1373 | .abort_command = qla24xx_abort_command, | ||
| 1374 | .abort_target = qla24xx_abort_target, | ||
| 1375 | .fabric_login = qla24xx_login_fabric, | ||
| 1376 | .fabric_logout = qla24xx_fabric_logout, | ||
| 1377 | .calc_req_entries = NULL, | ||
| 1378 | .build_iocbs = NULL, | ||
| 1379 | .prep_ms_iocb = qla24xx_prep_ms_iocb, | ||
| 1380 | .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, | ||
| 1381 | .read_nvram = qla25xx_read_nvram_data, | ||
| 1382 | .write_nvram = qla25xx_write_nvram_data, | ||
| 1383 | .fw_dump = qla25xx_fw_dump, | ||
| 1384 | .beacon_on = qla24xx_beacon_on, | ||
| 1385 | .beacon_off = qla24xx_beacon_off, | ||
| 1386 | .beacon_blink = qla24xx_beacon_blink, | ||
| 1387 | .read_optrom = qla24xx_read_optrom_data, | ||
| 1388 | .write_optrom = qla24xx_write_optrom_data, | ||
| 1389 | .get_flash_version = qla24xx_get_flash_version, | ||
| 1390 | }; | ||
| 1391 | |||
| 1197 | static inline void | 1392 | static inline void |
| 1198 | qla2x00_set_isp_flags(scsi_qla_host_t *ha) | 1393 | qla2x00_set_isp_flags(scsi_qla_host_t *ha) |
| 1199 | { | 1394 | { |
| @@ -1238,19 +1433,32 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) | |||
| 1238 | case PCI_DEVICE_ID_QLOGIC_ISP2422: | 1433 | case PCI_DEVICE_ID_QLOGIC_ISP2422: |
| 1239 | ha->device_type |= DT_ISP2422; | 1434 | ha->device_type |= DT_ISP2422; |
| 1240 | ha->device_type |= DT_ZIO_SUPPORTED; | 1435 | ha->device_type |= DT_ZIO_SUPPORTED; |
| 1436 | ha->device_type |= DT_FWI2; | ||
| 1437 | ha->device_type |= DT_IIDMA; | ||
| 1241 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; | 1438 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; |
| 1242 | break; | 1439 | break; |
| 1243 | case PCI_DEVICE_ID_QLOGIC_ISP2432: | 1440 | case PCI_DEVICE_ID_QLOGIC_ISP2432: |
| 1244 | ha->device_type |= DT_ISP2432; | 1441 | ha->device_type |= DT_ISP2432; |
| 1245 | ha->device_type |= DT_ZIO_SUPPORTED; | 1442 | ha->device_type |= DT_ZIO_SUPPORTED; |
| 1443 | ha->device_type |= DT_FWI2; | ||
| 1444 | ha->device_type |= DT_IIDMA; | ||
| 1246 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; | 1445 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; |
| 1247 | break; | 1446 | break; |
| 1248 | case PCI_DEVICE_ID_QLOGIC_ISP5422: | 1447 | case PCI_DEVICE_ID_QLOGIC_ISP5422: |
| 1249 | ha->device_type |= DT_ISP5422; | 1448 | ha->device_type |= DT_ISP5422; |
| 1449 | ha->device_type |= DT_FWI2; | ||
| 1250 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; | 1450 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; |
| 1251 | break; | 1451 | break; |
| 1252 | case PCI_DEVICE_ID_QLOGIC_ISP5432: | 1452 | case PCI_DEVICE_ID_QLOGIC_ISP5432: |
| 1253 | ha->device_type |= DT_ISP5432; | 1453 | ha->device_type |= DT_ISP5432; |
| 1454 | ha->device_type |= DT_FWI2; | ||
| 1455 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; | ||
| 1456 | break; | ||
| 1457 | case PCI_DEVICE_ID_QLOGIC_ISP2532: | ||
| 1458 | ha->device_type |= DT_ISP2532; | ||
| 1459 | ha->device_type |= DT_ZIO_SUPPORTED; | ||
| 1460 | ha->device_type |= DT_FWI2; | ||
| 1461 | ha->device_type |= DT_IIDMA; | ||
| 1254 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; | 1462 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; |
| 1255 | break; | 1463 | break; |
| 1256 | } | 1464 | } |
| @@ -1323,61 +1531,6 @@ iospace_error_exit: | |||
| 1323 | } | 1531 | } |
| 1324 | 1532 | ||
| 1325 | static void | 1533 | static void |
| 1326 | qla2x00_enable_intrs(scsi_qla_host_t *ha) | ||
| 1327 | { | ||
| 1328 | unsigned long flags = 0; | ||
| 1329 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | ||
| 1330 | |||
| 1331 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 1332 | ha->interrupts_on = 1; | ||
| 1333 | /* enable risc and host interrupts */ | ||
| 1334 | WRT_REG_WORD(®->ictrl, ICR_EN_INT | ICR_EN_RISC); | ||
| 1335 | RD_REG_WORD(®->ictrl); | ||
| 1336 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 1337 | |||
| 1338 | } | ||
| 1339 | |||
| 1340 | static void | ||
| 1341 | qla2x00_disable_intrs(scsi_qla_host_t *ha) | ||
| 1342 | { | ||
| 1343 | unsigned long flags = 0; | ||
| 1344 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | ||
| 1345 | |||
| 1346 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 1347 | ha->interrupts_on = 0; | ||
| 1348 | /* disable risc and host interrupts */ | ||
| 1349 | WRT_REG_WORD(®->ictrl, 0); | ||
| 1350 | RD_REG_WORD(®->ictrl); | ||
| 1351 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | static void | ||
| 1355 | qla24xx_enable_intrs(scsi_qla_host_t *ha) | ||
| 1356 | { | ||
| 1357 | unsigned long flags = 0; | ||
| 1358 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
| 1359 | |||
| 1360 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 1361 | ha->interrupts_on = 1; | ||
| 1362 | WRT_REG_DWORD(®->ictrl, ICRX_EN_RISC_INT); | ||
| 1363 | RD_REG_DWORD(®->ictrl); | ||
| 1364 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | static void | ||
| 1368 | qla24xx_disable_intrs(scsi_qla_host_t *ha) | ||
| 1369 | { | ||
| 1370 | unsigned long flags = 0; | ||
| 1371 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
| 1372 | |||
| 1373 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 1374 | ha->interrupts_on = 0; | ||
| 1375 | WRT_REG_DWORD(®->ictrl, 0); | ||
| 1376 | RD_REG_DWORD(®->ictrl); | ||
| 1377 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | static void | ||
| 1381 | qla2xxx_scan_start(struct Scsi_Host *shost) | 1534 | qla2xxx_scan_start(struct Scsi_Host *shost) |
| 1382 | { | 1535 | { |
| 1383 | scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; | 1536 | scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; |
| @@ -1422,7 +1575,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1422 | if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || | 1575 | if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || |
| 1423 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || | 1576 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || |
| 1424 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 || | 1577 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 || |
| 1425 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432) | 1578 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 || |
| 1579 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) | ||
| 1426 | sht = &qla24xx_driver_template; | 1580 | sht = &qla24xx_driver_template; |
| 1427 | host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t)); | 1581 | host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t)); |
| 1428 | if (host == NULL) { | 1582 | if (host == NULL) { |
| @@ -1466,33 +1620,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1466 | ha->max_q_depth = ql2xmaxqdepth; | 1620 | ha->max_q_depth = ql2xmaxqdepth; |
| 1467 | 1621 | ||
| 1468 | /* Assign ISP specific operations. */ | 1622 | /* Assign ISP specific operations. */ |
| 1469 | ha->isp_ops.pci_config = qla2100_pci_config; | ||
| 1470 | ha->isp_ops.reset_chip = qla2x00_reset_chip; | ||
| 1471 | ha->isp_ops.chip_diag = qla2x00_chip_diag; | ||
| 1472 | ha->isp_ops.config_rings = qla2x00_config_rings; | ||
| 1473 | ha->isp_ops.reset_adapter = qla2x00_reset_adapter; | ||
| 1474 | ha->isp_ops.nvram_config = qla2x00_nvram_config; | ||
| 1475 | ha->isp_ops.update_fw_options = qla2x00_update_fw_options; | ||
| 1476 | ha->isp_ops.load_risc = qla2x00_load_risc; | ||
| 1477 | ha->isp_ops.pci_info_str = qla2x00_pci_info_str; | ||
| 1478 | ha->isp_ops.fw_version_str = qla2x00_fw_version_str; | ||
| 1479 | ha->isp_ops.intr_handler = qla2100_intr_handler; | ||
| 1480 | ha->isp_ops.enable_intrs = qla2x00_enable_intrs; | ||
| 1481 | ha->isp_ops.disable_intrs = qla2x00_disable_intrs; | ||
| 1482 | ha->isp_ops.abort_command = qla2x00_abort_command; | ||
| 1483 | ha->isp_ops.abort_target = qla2x00_abort_target; | ||
| 1484 | ha->isp_ops.fabric_login = qla2x00_login_fabric; | ||
| 1485 | ha->isp_ops.fabric_logout = qla2x00_fabric_logout; | ||
| 1486 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32; | ||
| 1487 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32; | ||
| 1488 | ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb; | ||
| 1489 | ha->isp_ops.prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb; | ||
| 1490 | ha->isp_ops.read_nvram = qla2x00_read_nvram_data; | ||
| 1491 | ha->isp_ops.write_nvram = qla2x00_write_nvram_data; | ||
| 1492 | ha->isp_ops.fw_dump = qla2100_fw_dump; | ||
| 1493 | ha->isp_ops.read_optrom = qla2x00_read_optrom_data; | ||
| 1494 | ha->isp_ops.write_optrom = qla2x00_write_optrom_data; | ||
| 1495 | ha->isp_ops.get_flash_version = qla2x00_get_flash_version; | ||
| 1496 | if (IS_QLA2100(ha)) { | 1623 | if (IS_QLA2100(ha)) { |
| 1497 | host->max_id = MAX_TARGETS_2100; | 1624 | host->max_id = MAX_TARGETS_2100; |
| 1498 | ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; | 1625 | ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; |
| @@ -1501,6 +1628,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1501 | ha->last_loop_id = SNS_LAST_LOOP_ID_2100; | 1628 | ha->last_loop_id = SNS_LAST_LOOP_ID_2100; |
| 1502 | host->sg_tablesize = 32; | 1629 | host->sg_tablesize = 32; |
| 1503 | ha->gid_list_info_size = 4; | 1630 | ha->gid_list_info_size = 4; |
| 1631 | ha->isp_ops = &qla2100_isp_ops; | ||
| 1504 | } else if (IS_QLA2200(ha)) { | 1632 | } else if (IS_QLA2200(ha)) { |
| 1505 | host->max_id = MAX_TARGETS_2200; | 1633 | host->max_id = MAX_TARGETS_2200; |
| 1506 | ha->mbx_count = MAILBOX_REGISTER_COUNT; | 1634 | ha->mbx_count = MAILBOX_REGISTER_COUNT; |
| @@ -1508,21 +1636,17 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1508 | ha->response_q_length = RESPONSE_ENTRY_CNT_2100; | 1636 | ha->response_q_length = RESPONSE_ENTRY_CNT_2100; |
| 1509 | ha->last_loop_id = SNS_LAST_LOOP_ID_2100; | 1637 | ha->last_loop_id = SNS_LAST_LOOP_ID_2100; |
| 1510 | ha->gid_list_info_size = 4; | 1638 | ha->gid_list_info_size = 4; |
| 1639 | ha->isp_ops = &qla2100_isp_ops; | ||
| 1511 | } else if (IS_QLA23XX(ha)) { | 1640 | } else if (IS_QLA23XX(ha)) { |
| 1512 | host->max_id = MAX_TARGETS_2200; | 1641 | host->max_id = MAX_TARGETS_2200; |
| 1513 | ha->mbx_count = MAILBOX_REGISTER_COUNT; | 1642 | ha->mbx_count = MAILBOX_REGISTER_COUNT; |
| 1514 | ha->request_q_length = REQUEST_ENTRY_CNT_2200; | 1643 | ha->request_q_length = REQUEST_ENTRY_CNT_2200; |
| 1515 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; | 1644 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; |
| 1516 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; | 1645 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; |
| 1517 | ha->isp_ops.pci_config = qla2300_pci_config; | ||
| 1518 | ha->isp_ops.intr_handler = qla2300_intr_handler; | ||
| 1519 | ha->isp_ops.fw_dump = qla2300_fw_dump; | ||
| 1520 | ha->isp_ops.beacon_on = qla2x00_beacon_on; | ||
| 1521 | ha->isp_ops.beacon_off = qla2x00_beacon_off; | ||
| 1522 | ha->isp_ops.beacon_blink = qla2x00_beacon_blink; | ||
| 1523 | ha->gid_list_info_size = 6; | 1646 | ha->gid_list_info_size = 6; |
| 1524 | if (IS_QLA2322(ha) || IS_QLA6322(ha)) | 1647 | if (IS_QLA2322(ha) || IS_QLA6322(ha)) |
| 1525 | ha->optrom_size = OPTROM_SIZE_2322; | 1648 | ha->optrom_size = OPTROM_SIZE_2322; |
| 1649 | ha->isp_ops = &qla2300_isp_ops; | ||
| 1526 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1650 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { |
| 1527 | host->max_id = MAX_TARGETS_2200; | 1651 | host->max_id = MAX_TARGETS_2200; |
| 1528 | ha->mbx_count = MAILBOX_REGISTER_COUNT; | 1652 | ha->mbx_count = MAILBOX_REGISTER_COUNT; |
| @@ -1531,36 +1655,20 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1531 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; | 1655 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; |
| 1532 | ha->init_cb_size = sizeof(struct mid_init_cb_24xx); | 1656 | ha->init_cb_size = sizeof(struct mid_init_cb_24xx); |
| 1533 | ha->mgmt_svr_loop_id = 10 + ha->vp_idx; | 1657 | ha->mgmt_svr_loop_id = 10 + ha->vp_idx; |
| 1534 | ha->isp_ops.pci_config = qla24xx_pci_config; | ||
| 1535 | ha->isp_ops.reset_chip = qla24xx_reset_chip; | ||
| 1536 | ha->isp_ops.chip_diag = qla24xx_chip_diag; | ||
| 1537 | ha->isp_ops.config_rings = qla24xx_config_rings; | ||
| 1538 | ha->isp_ops.reset_adapter = qla24xx_reset_adapter; | ||
| 1539 | ha->isp_ops.nvram_config = qla24xx_nvram_config; | ||
| 1540 | ha->isp_ops.update_fw_options = qla24xx_update_fw_options; | ||
| 1541 | ha->isp_ops.load_risc = qla24xx_load_risc; | ||
| 1542 | ha->isp_ops.pci_info_str = qla24xx_pci_info_str; | ||
| 1543 | ha->isp_ops.fw_version_str = qla24xx_fw_version_str; | ||
| 1544 | ha->isp_ops.intr_handler = qla24xx_intr_handler; | ||
| 1545 | ha->isp_ops.enable_intrs = qla24xx_enable_intrs; | ||
| 1546 | ha->isp_ops.disable_intrs = qla24xx_disable_intrs; | ||
| 1547 | ha->isp_ops.abort_command = qla24xx_abort_command; | ||
| 1548 | ha->isp_ops.abort_target = qla24xx_abort_target; | ||
| 1549 | ha->isp_ops.fabric_login = qla24xx_login_fabric; | ||
| 1550 | ha->isp_ops.fabric_logout = qla24xx_fabric_logout; | ||
| 1551 | ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb; | ||
| 1552 | ha->isp_ops.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb; | ||
| 1553 | ha->isp_ops.read_nvram = qla24xx_read_nvram_data; | ||
| 1554 | ha->isp_ops.write_nvram = qla24xx_write_nvram_data; | ||
| 1555 | ha->isp_ops.fw_dump = qla24xx_fw_dump; | ||
| 1556 | ha->isp_ops.read_optrom = qla24xx_read_optrom_data; | ||
| 1557 | ha->isp_ops.write_optrom = qla24xx_write_optrom_data; | ||
| 1558 | ha->isp_ops.beacon_on = qla24xx_beacon_on; | ||
| 1559 | ha->isp_ops.beacon_off = qla24xx_beacon_off; | ||
| 1560 | ha->isp_ops.beacon_blink = qla24xx_beacon_blink; | ||
| 1561 | ha->isp_ops.get_flash_version = qla24xx_get_flash_version; | ||
| 1562 | ha->gid_list_info_size = 8; | 1658 | ha->gid_list_info_size = 8; |
| 1563 | ha->optrom_size = OPTROM_SIZE_24XX; | 1659 | ha->optrom_size = OPTROM_SIZE_24XX; |
| 1660 | ha->isp_ops = &qla24xx_isp_ops; | ||
| 1661 | } else if (IS_QLA25XX(ha)) { | ||
| 1662 | host->max_id = MAX_TARGETS_2200; | ||
| 1663 | ha->mbx_count = MAILBOX_REGISTER_COUNT; | ||
| 1664 | ha->request_q_length = REQUEST_ENTRY_CNT_24XX; | ||
| 1665 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; | ||
| 1666 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; | ||
| 1667 | ha->init_cb_size = sizeof(struct mid_init_cb_24xx); | ||
| 1668 | ha->mgmt_svr_loop_id = 10 + ha->vp_idx; | ||
| 1669 | ha->gid_list_info_size = 8; | ||
| 1670 | ha->optrom_size = OPTROM_SIZE_25XX; | ||
| 1671 | ha->isp_ops = &qla25xx_isp_ops; | ||
| 1564 | } | 1672 | } |
| 1565 | host->can_queue = ha->request_q_length + 128; | 1673 | host->can_queue = ha->request_q_length + 128; |
| 1566 | 1674 | ||
| @@ -1628,11 +1736,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1628 | DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", | 1736 | DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", |
| 1629 | ha->host_no, ha)); | 1737 | ha->host_no, ha)); |
| 1630 | 1738 | ||
| 1631 | ha->isp_ops.disable_intrs(ha); | 1739 | ha->isp_ops->disable_intrs(ha); |
| 1632 | 1740 | ||
| 1633 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1741 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 1634 | reg = ha->iobase; | 1742 | reg = ha->iobase; |
| 1635 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1743 | if (IS_FWI2_CAPABLE(ha)) { |
| 1636 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT); | 1744 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT); |
| 1637 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT); | 1745 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT); |
| 1638 | } else { | 1746 | } else { |
| @@ -1654,7 +1762,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1654 | } | 1762 | } |
| 1655 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1763 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 1656 | 1764 | ||
| 1657 | ha->isp_ops.enable_intrs(ha); | 1765 | ha->isp_ops->enable_intrs(ha); |
| 1658 | 1766 | ||
| 1659 | pci_set_drvdata(pdev, ha); | 1767 | pci_set_drvdata(pdev, ha); |
| 1660 | 1768 | ||
| @@ -1679,9 +1787,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1679 | " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n", | 1787 | " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n", |
| 1680 | qla2x00_version_str, ha->model_number, | 1788 | qla2x00_version_str, ha->model_number, |
| 1681 | ha->model_desc ? ha->model_desc: "", pdev->device, | 1789 | ha->model_desc ? ha->model_desc: "", pdev->device, |
| 1682 | ha->isp_ops.pci_info_str(ha, pci_info), pci_name(pdev), | 1790 | ha->isp_ops->pci_info_str(ha, pci_info), pci_name(pdev), |
| 1683 | ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, | 1791 | ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, |
| 1684 | ha->isp_ops.fw_version_str(ha, fw_str)); | 1792 | ha->isp_ops->fw_version_str(ha, fw_str)); |
| 1685 | 1793 | ||
| 1686 | return 0; | 1794 | return 0; |
| 1687 | 1795 | ||
| @@ -1747,7 +1855,7 @@ qla2x00_free_device(scsi_qla_host_t *ha) | |||
| 1747 | 1855 | ||
| 1748 | /* turn-off interrupts on the card */ | 1856 | /* turn-off interrupts on the card */ |
| 1749 | if (ha->interrupts_on) | 1857 | if (ha->interrupts_on) |
| 1750 | ha->isp_ops.disable_intrs(ha); | 1858 | ha->isp_ops->disable_intrs(ha); |
| 1751 | 1859 | ||
| 1752 | qla2x00_mem_free(ha); | 1860 | qla2x00_mem_free(ha); |
| 1753 | 1861 | ||
| @@ -2025,7 +2133,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) | |||
| 2025 | } | 2133 | } |
| 2026 | memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); | 2134 | memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); |
| 2027 | 2135 | ||
| 2028 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 2136 | if (IS_FWI2_CAPABLE(ha)) { |
| 2029 | /* | 2137 | /* |
| 2030 | * Get consistent memory allocated for SFP | 2138 | * Get consistent memory allocated for SFP |
| 2031 | * block. | 2139 | * block. |
| @@ -2305,7 +2413,7 @@ qla2x00_do_dpc(void *data) | |||
| 2305 | if (fcport->flags & FCF_FABRIC_DEVICE) { | 2413 | if (fcport->flags & FCF_FABRIC_DEVICE) { |
| 2306 | if (fcport->flags & | 2414 | if (fcport->flags & |
| 2307 | FCF_TAPE_PRESENT) | 2415 | FCF_TAPE_PRESENT) |
| 2308 | ha->isp_ops.fabric_logout( | 2416 | ha->isp_ops->fabric_logout( |
| 2309 | ha, fcport->loop_id, | 2417 | ha, fcport->loop_id, |
| 2310 | fcport->d_id.b.domain, | 2418 | fcport->d_id.b.domain, |
| 2311 | fcport->d_id.b.area, | 2419 | fcport->d_id.b.area, |
| @@ -2385,10 +2493,10 @@ qla2x00_do_dpc(void *data) | |||
| 2385 | } | 2493 | } |
| 2386 | 2494 | ||
| 2387 | if (!ha->interrupts_on) | 2495 | if (!ha->interrupts_on) |
| 2388 | ha->isp_ops.enable_intrs(ha); | 2496 | ha->isp_ops->enable_intrs(ha); |
| 2389 | 2497 | ||
| 2390 | if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) | 2498 | if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) |
| 2391 | ha->isp_ops.beacon_blink(ha); | 2499 | ha->isp_ops->beacon_blink(ha); |
| 2392 | 2500 | ||
| 2393 | qla2x00_do_dpc_all_vps(ha); | 2501 | qla2x00_do_dpc_all_vps(ha); |
| 2394 | 2502 | ||
| @@ -2617,18 +2725,20 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) | |||
| 2617 | 2725 | ||
| 2618 | /* Firmware interface routines. */ | 2726 | /* Firmware interface routines. */ |
| 2619 | 2727 | ||
| 2620 | #define FW_BLOBS 5 | 2728 | #define FW_BLOBS 6 |
| 2621 | #define FW_ISP21XX 0 | 2729 | #define FW_ISP21XX 0 |
| 2622 | #define FW_ISP22XX 1 | 2730 | #define FW_ISP22XX 1 |
| 2623 | #define FW_ISP2300 2 | 2731 | #define FW_ISP2300 2 |
| 2624 | #define FW_ISP2322 3 | 2732 | #define FW_ISP2322 3 |
| 2625 | #define FW_ISP24XX 4 | 2733 | #define FW_ISP24XX 4 |
| 2734 | #define FW_ISP25XX 5 | ||
| 2626 | 2735 | ||
| 2627 | #define FW_FILE_ISP21XX "ql2100_fw.bin" | 2736 | #define FW_FILE_ISP21XX "ql2100_fw.bin" |
| 2628 | #define FW_FILE_ISP22XX "ql2200_fw.bin" | 2737 | #define FW_FILE_ISP22XX "ql2200_fw.bin" |
| 2629 | #define FW_FILE_ISP2300 "ql2300_fw.bin" | 2738 | #define FW_FILE_ISP2300 "ql2300_fw.bin" |
| 2630 | #define FW_FILE_ISP2322 "ql2322_fw.bin" | 2739 | #define FW_FILE_ISP2322 "ql2322_fw.bin" |
| 2631 | #define FW_FILE_ISP24XX "ql2400_fw.bin" | 2740 | #define FW_FILE_ISP24XX "ql2400_fw.bin" |
| 2741 | #define FW_FILE_ISP25XX "ql2500_fw.bin" | ||
| 2632 | 2742 | ||
| 2633 | static DECLARE_MUTEX(qla_fw_lock); | 2743 | static DECLARE_MUTEX(qla_fw_lock); |
| 2634 | 2744 | ||
| @@ -2638,6 +2748,7 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = { | |||
| 2638 | { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, }, | 2748 | { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, }, |
| 2639 | { .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, | 2749 | { .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, |
| 2640 | { .name = FW_FILE_ISP24XX, }, | 2750 | { .name = FW_FILE_ISP24XX, }, |
| 2751 | { .name = FW_FILE_ISP25XX, }, | ||
| 2641 | }; | 2752 | }; |
| 2642 | 2753 | ||
| 2643 | struct fw_blob * | 2754 | struct fw_blob * |
| @@ -2656,6 +2767,8 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) | |||
| 2656 | blob = &qla_fw_blobs[FW_ISP2322]; | 2767 | blob = &qla_fw_blobs[FW_ISP2322]; |
| 2657 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 2768 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { |
| 2658 | blob = &qla_fw_blobs[FW_ISP24XX]; | 2769 | blob = &qla_fw_blobs[FW_ISP24XX]; |
| 2770 | } else if (IS_QLA25XX(ha)) { | ||
| 2771 | blob = &qla_fw_blobs[FW_ISP25XX]; | ||
| 2659 | } | 2772 | } |
| 2660 | 2773 | ||
| 2661 | down(&qla_fw_lock); | 2774 | down(&qla_fw_lock); |
| @@ -2699,6 +2812,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { | |||
| 2699 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) }, | 2812 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) }, |
| 2700 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) }, | 2813 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) }, |
| 2701 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) }, | 2814 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) }, |
| 2815 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) }, | ||
| 2702 | { 0 }, | 2816 | { 0 }, |
| 2703 | }; | 2817 | }; |
| 2704 | MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); | 2818 | MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 206bda093da2..a925a3f179f9 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
| @@ -766,6 +766,29 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
| 766 | return ret; | 766 | return ret; |
| 767 | } | 767 | } |
| 768 | 768 | ||
| 769 | uint8_t * | ||
| 770 | qla25xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | ||
| 771 | uint32_t bytes) | ||
| 772 | { | ||
| 773 | uint32_t i; | ||
| 774 | uint32_t *dwptr; | ||
| 775 | |||
| 776 | /* Dword reads to flash. */ | ||
| 777 | dwptr = (uint32_t *)buf; | ||
| 778 | for (i = 0; i < bytes >> 2; i++, naddr++) | ||
| 779 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, | ||
| 780 | flash_data_to_access_addr(FA_VPD_NVRAM_ADDR | naddr))); | ||
| 781 | |||
| 782 | return buf; | ||
| 783 | } | ||
| 784 | |||
| 785 | int | ||
| 786 | qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | ||
| 787 | uint32_t bytes) | ||
| 788 | { | ||
| 789 | return qla24xx_write_flash_data(ha, (uint32_t *)buf, | ||
| 790 | FA_VPD_NVRAM_ADDR | naddr, bytes >> 2); | ||
| 791 | } | ||
| 769 | 792 | ||
| 770 | static inline void | 793 | static inline void |
| 771 | qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags) | 794 | qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags) |
| @@ -919,7 +942,7 @@ qla2x00_beacon_off(struct scsi_qla_host *ha) | |||
| 919 | else | 942 | else |
| 920 | ha->beacon_color_state = QLA_LED_GRN_ON; | 943 | ha->beacon_color_state = QLA_LED_GRN_ON; |
| 921 | 944 | ||
| 922 | ha->isp_ops.beacon_blink(ha); /* This turns green LED off */ | 945 | ha->isp_ops->beacon_blink(ha); /* This turns green LED off */ |
| 923 | 946 | ||
| 924 | ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING; | 947 | ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING; |
| 925 | ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7; | 948 | ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7; |
| @@ -1031,7 +1054,7 @@ qla24xx_beacon_off(struct scsi_qla_host *ha) | |||
| 1031 | ha->beacon_blink_led = 0; | 1054 | ha->beacon_blink_led = 0; |
| 1032 | ha->beacon_color_state = QLA_LED_ALL_ON; | 1055 | ha->beacon_color_state = QLA_LED_ALL_ON; |
| 1033 | 1056 | ||
| 1034 | ha->isp_ops.beacon_blink(ha); /* Will flip to all off. */ | 1057 | ha->isp_ops->beacon_blink(ha); /* Will flip to all off. */ |
| 1035 | 1058 | ||
| 1036 | /* Give control back to firmware. */ | 1059 | /* Give control back to firmware. */ |
| 1037 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1060 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| @@ -1419,7 +1442,7 @@ qla2x00_suspend_hba(struct scsi_qla_host *ha) | |||
| 1419 | 1442 | ||
| 1420 | /* Suspend HBA. */ | 1443 | /* Suspend HBA. */ |
| 1421 | scsi_block_requests(ha->host); | 1444 | scsi_block_requests(ha->host); |
| 1422 | ha->isp_ops.disable_intrs(ha); | 1445 | ha->isp_ops->disable_intrs(ha); |
| 1423 | set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); | 1446 | set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); |
| 1424 | 1447 | ||
| 1425 | /* Pause RISC. */ | 1448 | /* Pause RISC. */ |
| @@ -1705,7 +1728,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, | |||
| 1705 | { | 1728 | { |
| 1706 | /* Suspend HBA. */ | 1729 | /* Suspend HBA. */ |
| 1707 | scsi_block_requests(ha->host); | 1730 | scsi_block_requests(ha->host); |
| 1708 | ha->isp_ops.disable_intrs(ha); | 1731 | ha->isp_ops->disable_intrs(ha); |
| 1709 | set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); | 1732 | set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); |
| 1710 | 1733 | ||
| 1711 | /* Go with read. */ | 1734 | /* Go with read. */ |
| @@ -1713,7 +1736,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, | |||
| 1713 | 1736 | ||
| 1714 | /* Resume HBA. */ | 1737 | /* Resume HBA. */ |
| 1715 | clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); | 1738 | clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); |
| 1716 | ha->isp_ops.enable_intrs(ha); | 1739 | ha->isp_ops->enable_intrs(ha); |
| 1717 | scsi_unblock_requests(ha->host); | 1740 | scsi_unblock_requests(ha->host); |
| 1718 | 1741 | ||
| 1719 | return buf; | 1742 | return buf; |
| @@ -1727,7 +1750,7 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, | |||
| 1727 | 1750 | ||
| 1728 | /* Suspend HBA. */ | 1751 | /* Suspend HBA. */ |
| 1729 | scsi_block_requests(ha->host); | 1752 | scsi_block_requests(ha->host); |
| 1730 | ha->isp_ops.disable_intrs(ha); | 1753 | ha->isp_ops->disable_intrs(ha); |
| 1731 | set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); | 1754 | set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); |
| 1732 | 1755 | ||
| 1733 | /* Go with write. */ | 1756 | /* Go with write. */ |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index fd2f10a25348..dd1f8ceb79c4 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | /* | 7 | /* |
| 8 | * Driver version | 8 | * Driver version |
| 9 | */ | 9 | */ |
| 10 | #define QLA2XXX_VERSION "8.02.00-k1" | 10 | #define QLA2XXX_VERSION "8.02.00-k2" |
| 11 | 11 | ||
| 12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
| 13 | #define QLA_DRIVER_MINOR_VER 2 | 13 | #define QLA_DRIVER_MINOR_VER 2 |
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 4cd9c58efef1..4947dfe625a6 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
| @@ -2875,7 +2875,7 @@ static int __init scsi_debug_init(void) | |||
| 2875 | 2875 | ||
| 2876 | init_all_queued(); | 2876 | init_all_queued(); |
| 2877 | 2877 | ||
| 2878 | sdebug_driver_template.proc_name = (char *)sdebug_proc_name; | 2878 | sdebug_driver_template.proc_name = sdebug_proc_name; |
| 2879 | 2879 | ||
| 2880 | host_to_add = scsi_debug_add_host; | 2880 | host_to_add = scsi_debug_add_host; |
| 2881 | scsi_debug_add_host = 0; | 2881 | scsi_debug_add_host = 0; |
diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c index 6cfaaa2d0c81..63a30f566f3a 100644 --- a/drivers/scsi/scsi_sysctl.c +++ b/drivers/scsi/scsi_sysctl.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <linux/sysctl.h> | 9 | #include <linux/sysctl.h> |
| 10 | 10 | ||
| 11 | #include "scsi_logging.h" | 11 | #include "scsi_logging.h" |
| 12 | #include "scsi_priv.h" | ||
| 12 | 13 | ||
| 13 | 14 | ||
| 14 | static ctl_table scsi_table[] = { | 15 | static ctl_table scsi_table[] = { |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ed720863ab97..34cdce6738a6 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <scsi/scsi_host.h> | 16 | #include <scsi/scsi_host.h> |
| 17 | #include <scsi/scsi_tcq.h> | 17 | #include <scsi/scsi_tcq.h> |
| 18 | #include <scsi/scsi_transport.h> | 18 | #include <scsi/scsi_transport.h> |
| 19 | #include <scsi/scsi_driver.h> | ||
| 19 | 20 | ||
| 20 | #include "scsi_priv.h" | 21 | #include "scsi_priv.h" |
| 21 | #include "scsi_logging.h" | 22 | #include "scsi_logging.h" |
| @@ -714,6 +715,7 @@ static int attr_add(struct device *dev, struct device_attribute *attr) | |||
| 714 | int scsi_sysfs_add_sdev(struct scsi_device *sdev) | 715 | int scsi_sysfs_add_sdev(struct scsi_device *sdev) |
| 715 | { | 716 | { |
| 716 | int error, i; | 717 | int error, i; |
| 718 | struct request_queue *rq = sdev->request_queue; | ||
| 717 | 719 | ||
| 718 | if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0) | 720 | if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0) |
| 719 | return error; | 721 | return error; |
| @@ -733,6 +735,17 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
| 733 | /* take a reference for the sdev_classdev; this is | 735 | /* take a reference for the sdev_classdev; this is |
| 734 | * released by the sdev_class .release */ | 736 | * released by the sdev_class .release */ |
| 735 | get_device(&sdev->sdev_gendev); | 737 | get_device(&sdev->sdev_gendev); |
| 738 | |||
| 739 | error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL); | ||
| 740 | |||
| 741 | if (error) | ||
| 742 | sdev_printk(KERN_INFO, sdev, | ||
| 743 | "Failed to register bsg queue, errno=%d\n", error); | ||
| 744 | |||
| 745 | /* we're treating error on bsg register as non-fatal, so pretend | ||
| 746 | * nothing went wrong */ | ||
| 747 | error = 0; | ||
| 748 | |||
| 736 | if (sdev->host->hostt->sdev_attrs) { | 749 | if (sdev->host->hostt->sdev_attrs) { |
| 737 | for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) { | 750 | for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) { |
| 738 | error = attr_add(&sdev->sdev_gendev, | 751 | error = attr_add(&sdev->sdev_gendev, |
| @@ -779,6 +792,7 @@ void __scsi_remove_device(struct scsi_device *sdev) | |||
| 779 | if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0) | 792 | if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0) |
| 780 | return; | 793 | return; |
| 781 | 794 | ||
| 795 | bsg_unregister_queue(sdev->request_queue); | ||
| 782 | class_device_unregister(&sdev->sdev_classdev); | 796 | class_device_unregister(&sdev->sdev_classdev); |
| 783 | transport_remove_device(dev); | 797 | transport_remove_device(dev); |
| 784 | device_del(dev); | 798 | device_del(dev); |
| @@ -803,7 +817,7 @@ void scsi_remove_device(struct scsi_device *sdev) | |||
| 803 | } | 817 | } |
| 804 | EXPORT_SYMBOL(scsi_remove_device); | 818 | EXPORT_SYMBOL(scsi_remove_device); |
| 805 | 819 | ||
| 806 | void __scsi_remove_target(struct scsi_target *starget) | 820 | static void __scsi_remove_target(struct scsi_target *starget) |
| 807 | { | 821 | { |
| 808 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 822 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
| 809 | unsigned long flags; | 823 | unsigned long flags; |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index e8825709797e..47057254850d 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
| @@ -2358,7 +2358,7 @@ fc_rport_final_delete(struct work_struct *work) | |||
| 2358 | * Notes: | 2358 | * Notes: |
| 2359 | * This routine assumes no locks are held on entry. | 2359 | * This routine assumes no locks are held on entry. |
| 2360 | **/ | 2360 | **/ |
| 2361 | struct fc_rport * | 2361 | static struct fc_rport * |
| 2362 | fc_rport_create(struct Scsi_Host *shost, int channel, | 2362 | fc_rport_create(struct Scsi_Host *shost, int channel, |
| 2363 | struct fc_rport_identifiers *ids) | 2363 | struct fc_rport_identifiers *ids) |
| 2364 | { | 2364 | { |
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index b2ef71a86292..3120f4b3a11a 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/err.h> | 29 | #include <linux/err.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
| 32 | #include <linux/blkdev.h> | ||
| 33 | #include <linux/bsg.h> | ||
| 32 | 34 | ||
| 33 | #include <scsi/scsi.h> | 35 | #include <scsi/scsi.h> |
| 34 | #include <scsi/scsi_device.h> | 36 | #include <scsi/scsi_device.h> |
| @@ -40,6 +42,7 @@ | |||
| 40 | struct sas_host_attrs { | 42 | struct sas_host_attrs { |
| 41 | struct list_head rphy_list; | 43 | struct list_head rphy_list; |
| 42 | struct mutex lock; | 44 | struct mutex lock; |
| 45 | struct request_queue *q; | ||
| 43 | u32 next_target_id; | 46 | u32 next_target_id; |
| 44 | u32 next_expander_id; | 47 | u32 next_expander_id; |
| 45 | int next_port_id; | 48 | int next_port_id; |
| @@ -152,6 +155,106 @@ static struct { | |||
| 152 | sas_bitfield_name_search(linkspeed, sas_linkspeed_names) | 155 | sas_bitfield_name_search(linkspeed, sas_linkspeed_names) |
| 153 | sas_bitfield_name_set(linkspeed, sas_linkspeed_names) | 156 | sas_bitfield_name_set(linkspeed, sas_linkspeed_names) |
| 154 | 157 | ||
| 158 | static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, | ||
| 159 | struct sas_rphy *rphy) | ||
| 160 | { | ||
| 161 | struct request *req; | ||
| 162 | int ret; | ||
| 163 | int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *); | ||
| 164 | |||
| 165 | while (!blk_queue_plugged(q)) { | ||
| 166 | req = elv_next_request(q); | ||
| 167 | if (!req) | ||
| 168 | break; | ||
| 169 | |||
| 170 | blkdev_dequeue_request(req); | ||
| 171 | |||
| 172 | spin_unlock_irq(q->queue_lock); | ||
| 173 | |||
| 174 | handler = to_sas_internal(shost->transportt)->f->smp_handler; | ||
| 175 | ret = handler(shost, rphy, req); | ||
| 176 | |||
| 177 | spin_lock_irq(q->queue_lock); | ||
| 178 | |||
| 179 | req->end_io(req, ret); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | static void sas_host_smp_request(struct request_queue *q) | ||
| 184 | { | ||
| 185 | sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL); | ||
| 186 | } | ||
| 187 | |||
| 188 | static void sas_non_host_smp_request(struct request_queue *q) | ||
| 189 | { | ||
| 190 | struct sas_rphy *rphy = q->queuedata; | ||
| 191 | sas_smp_request(q, rphy_to_shost(rphy), rphy); | ||
| 192 | } | ||
| 193 | |||
| 194 | static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) | ||
| 195 | { | ||
| 196 | struct request_queue *q; | ||
| 197 | int error; | ||
| 198 | struct device *dev; | ||
| 199 | char namebuf[BUS_ID_SIZE]; | ||
| 200 | const char *name; | ||
| 201 | |||
| 202 | if (!to_sas_internal(shost->transportt)->f->smp_handler) { | ||
| 203 | printk("%s can't handle SMP requests\n", shost->hostt->name); | ||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | if (rphy) { | ||
| 208 | q = blk_init_queue(sas_non_host_smp_request, NULL); | ||
| 209 | dev = &rphy->dev; | ||
| 210 | name = dev->bus_id; | ||
| 211 | } else { | ||
| 212 | q = blk_init_queue(sas_host_smp_request, NULL); | ||
| 213 | dev = &shost->shost_gendev; | ||
| 214 | snprintf(namebuf, sizeof(namebuf), | ||
| 215 | "sas_host%d", shost->host_no); | ||
| 216 | name = namebuf; | ||
| 217 | } | ||
| 218 | if (!q) | ||
| 219 | return -ENOMEM; | ||
| 220 | |||
| 221 | error = bsg_register_queue(q, dev, name); | ||
| 222 | if (error) { | ||
| 223 | blk_cleanup_queue(q); | ||
| 224 | return -ENOMEM; | ||
| 225 | } | ||
| 226 | |||
| 227 | if (rphy) | ||
| 228 | rphy->q = q; | ||
| 229 | else | ||
| 230 | to_sas_host_attrs(shost)->q = q; | ||
| 231 | |||
| 232 | if (rphy) | ||
| 233 | q->queuedata = rphy; | ||
| 234 | else | ||
| 235 | q->queuedata = shost; | ||
| 236 | |||
| 237 | set_bit(QUEUE_FLAG_BIDI, &q->queue_flags); | ||
| 238 | |||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy) | ||
| 243 | { | ||
| 244 | struct request_queue *q; | ||
| 245 | |||
| 246 | if (rphy) | ||
| 247 | q = rphy->q; | ||
| 248 | else | ||
| 249 | q = to_sas_host_attrs(shost)->q; | ||
| 250 | |||
| 251 | if (!q) | ||
| 252 | return; | ||
| 253 | |||
| 254 | bsg_unregister_queue(q); | ||
| 255 | blk_cleanup_queue(q); | ||
| 256 | } | ||
| 257 | |||
| 155 | /* | 258 | /* |
| 156 | * SAS host attributes | 259 | * SAS host attributes |
| 157 | */ | 260 | */ |
| @@ -167,11 +270,26 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, | |||
| 167 | sas_host->next_target_id = 0; | 270 | sas_host->next_target_id = 0; |
| 168 | sas_host->next_expander_id = 0; | 271 | sas_host->next_expander_id = 0; |
| 169 | sas_host->next_port_id = 0; | 272 | sas_host->next_port_id = 0; |
| 273 | |||
| 274 | if (sas_bsg_initialize(shost, NULL)) | ||
| 275 | dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n", | ||
| 276 | shost->host_no); | ||
| 277 | |||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | static int sas_host_remove(struct transport_container *tc, struct device *dev, | ||
| 282 | struct class_device *cdev) | ||
| 283 | { | ||
| 284 | struct Scsi_Host *shost = dev_to_shost(dev); | ||
| 285 | |||
| 286 | sas_bsg_remove(shost, NULL); | ||
| 287 | |||
| 170 | return 0; | 288 | return 0; |
| 171 | } | 289 | } |
| 172 | 290 | ||
| 173 | static DECLARE_TRANSPORT_CLASS(sas_host_class, | 291 | static DECLARE_TRANSPORT_CLASS(sas_host_class, |
| 174 | "sas_host", sas_host_setup, NULL, NULL); | 292 | "sas_host", sas_host_setup, sas_host_remove, NULL); |
| 175 | 293 | ||
| 176 | static int sas_host_match(struct attribute_container *cont, | 294 | static int sas_host_match(struct attribute_container *cont, |
| 177 | struct device *dev) | 295 | struct device *dev) |
| @@ -1287,6 +1405,9 @@ int sas_rphy_add(struct sas_rphy *rphy) | |||
| 1287 | return error; | 1405 | return error; |
| 1288 | transport_add_device(&rphy->dev); | 1406 | transport_add_device(&rphy->dev); |
| 1289 | transport_configure_device(&rphy->dev); | 1407 | transport_configure_device(&rphy->dev); |
| 1408 | if (sas_bsg_initialize(shost, rphy)) | ||
| 1409 | printk("fail to a bsg device %s\n", rphy->dev.bus_id); | ||
| 1410 | |||
| 1290 | 1411 | ||
| 1291 | mutex_lock(&sas_host->lock); | 1412 | mutex_lock(&sas_host->lock); |
| 1292 | list_add_tail(&rphy->list, &sas_host->rphy_list); | 1413 | list_add_tail(&rphy->list, &sas_host->rphy_list); |
| @@ -1329,6 +1450,8 @@ void sas_rphy_free(struct sas_rphy *rphy) | |||
| 1329 | list_del(&rphy->list); | 1450 | list_del(&rphy->list); |
| 1330 | mutex_unlock(&sas_host->lock); | 1451 | mutex_unlock(&sas_host->lock); |
| 1331 | 1452 | ||
| 1453 | sas_bsg_remove(shost, rphy); | ||
| 1454 | |||
| 1332 | transport_destroy_device(dev); | 1455 | transport_destroy_device(dev); |
| 1333 | 1456 | ||
| 1334 | put_device(dev); | 1457 | put_device(dev); |
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index ff62e9708e1c..ce80fa9ad815 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c | |||
| @@ -420,7 +420,7 @@ static inline void borken_wait (void) | |||
| 420 | #define ULOOP( i ) for (clock = i*8;;) | 420 | #define ULOOP( i ) for (clock = i*8;;) |
| 421 | #define TIMEOUT (!(clock--)) | 421 | #define TIMEOUT (!(clock--)) |
| 422 | 422 | ||
| 423 | int __init seagate_st0x_detect (struct scsi_host_template * tpnt) | 423 | static int __init seagate_st0x_detect (struct scsi_host_template * tpnt) |
| 424 | { | 424 | { |
| 425 | struct Scsi_Host *instance; | 425 | struct Scsi_Host *instance; |
| 426 | int i, j; | 426 | int i, j; |
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c index 710f19de3d40..d63d229e2323 100644 --- a/drivers/scsi/sim710.c +++ b/drivers/scsi/sim710.c | |||
| @@ -138,6 +138,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, | |||
| 138 | goto out_put_host; | 138 | goto out_put_host; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | dev_set_drvdata(dev, host); | ||
| 141 | scsi_scan_host(host); | 142 | scsi_scan_host(host); |
| 142 | 143 | ||
| 143 | return 0; | 144 | return 0; |
| @@ -155,7 +156,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, | |||
| 155 | static __devexit int | 156 | static __devexit int |
| 156 | sim710_device_remove(struct device *dev) | 157 | sim710_device_remove(struct device *dev) |
| 157 | { | 158 | { |
| 158 | struct Scsi_Host *host = dev_to_shost(dev); | 159 | struct Scsi_Host *host = dev_get_drvdata(dev); |
| 159 | struct NCR_700_Host_Parameters *hostdata = | 160 | struct NCR_700_Host_Parameters *hostdata = |
| 160 | (struct NCR_700_Host_Parameters *)host->hostdata[0]; | 161 | (struct NCR_700_Host_Parameters *)host->hostdata[0]; |
| 161 | 162 | ||
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 5143c8990845..e7b6a7fde1cb 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c | |||
| @@ -175,7 +175,7 @@ static void scsi_cd_put(struct scsi_cd *cd) | |||
| 175 | * an inode for that to work, and we do not always have one. | 175 | * an inode for that to work, and we do not always have one. |
| 176 | */ | 176 | */ |
| 177 | 177 | ||
| 178 | int sr_media_change(struct cdrom_device_info *cdi, int slot) | 178 | static int sr_media_change(struct cdrom_device_info *cdi, int slot) |
| 179 | { | 179 | { |
| 180 | struct scsi_cd *cd = cdi->handle; | 180 | struct scsi_cd *cd = cdi->handle; |
| 181 | int retval; | 181 | int retval; |
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index fa4e08e508ad..b92ff047af38 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c | |||
| @@ -89,6 +89,8 @@ | |||
| 89 | #include <scsi/scsi_device.h> | 89 | #include <scsi/scsi_device.h> |
| 90 | #include <scsi/scsi_host.h> | 90 | #include <scsi/scsi_host.h> |
| 91 | 91 | ||
| 92 | #include <asm/irq.h> | ||
| 93 | |||
| 92 | #include "wd33c93.h" | 94 | #include "wd33c93.h" |
| 93 | 95 | ||
| 94 | #define optimum_sx_per(hostdata) (hostdata)->sx_table[1].period_ns | 96 | #define optimum_sx_per(hostdata) (hostdata)->sx_table[1].period_ns |
| @@ -1762,7 +1764,7 @@ static char setup_buffer[SETUP_BUFFER_SIZE]; | |||
| 1762 | static char setup_used[MAX_SETUP_ARGS]; | 1764 | static char setup_used[MAX_SETUP_ARGS]; |
| 1763 | static int done_setup = 0; | 1765 | static int done_setup = 0; |
| 1764 | 1766 | ||
| 1765 | int | 1767 | static int |
| 1766 | wd33c93_setup(char *str) | 1768 | wd33c93_setup(char *str) |
| 1767 | { | 1769 | { |
| 1768 | int i; | 1770 | int i; |
diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index 50703877a585..c822debc2668 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c | |||
| @@ -130,6 +130,7 @@ static int __devinit zorro7xx_init_one(struct zorro_dev *z, | |||
| 130 | goto out_put_host; | 130 | goto out_put_host; |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | zorro_set_drvdata(z, host); | ||
| 133 | scsi_scan_host(host); | 134 | scsi_scan_host(host); |
| 134 | 135 | ||
| 135 | return 0; | 136 | return 0; |
| @@ -148,7 +149,7 @@ static int __devinit zorro7xx_init_one(struct zorro_dev *z, | |||
| 148 | 149 | ||
| 149 | static __devexit void zorro7xx_remove_one(struct zorro_dev *z) | 150 | static __devexit void zorro7xx_remove_one(struct zorro_dev *z) |
| 150 | { | 151 | { |
| 151 | struct Scsi_Host *host = dev_to_shost(&z->dev); | 152 | struct Scsi_Host *host = zorro_get_drvdata(z); |
| 152 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); | 153 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); |
| 153 | 154 | ||
| 154 | scsi_remove_host(host); | 155 | scsi_remove_host(host); |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index e42faa4e4282..dc1967176fe2 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
| @@ -1114,8 +1114,8 @@ static int __init imx_serial_init(void) | |||
| 1114 | 1114 | ||
| 1115 | static void __exit imx_serial_exit(void) | 1115 | static void __exit imx_serial_exit(void) |
| 1116 | { | 1116 | { |
| 1117 | uart_unregister_driver(&imx_reg); | ||
| 1118 | platform_driver_unregister(&serial_imx_driver); | 1117 | platform_driver_unregister(&serial_imx_driver); |
| 1118 | uart_unregister_driver(&imx_reg); | ||
| 1119 | } | 1119 | } |
| 1120 | 1120 | ||
| 1121 | module_init(imx_serial_init); | 1121 | module_init(imx_serial_init); |
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 10bc0209cd66..3f26c4b2f322 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c | |||
| @@ -78,7 +78,7 @@ | |||
| 78 | 78 | ||
| 79 | #include <asm/hardware.h> | 79 | #include <asm/hardware.h> |
| 80 | 80 | ||
| 81 | #include <asm/arch/regs-serial.h> | 81 | #include <asm/plat-s3c/regs-serial.h> |
| 82 | #include <asm/arch/regs-gpio.h> | 82 | #include <asm/arch/regs-gpio.h> |
| 83 | 83 | ||
| 84 | /* structures */ | 84 | /* structures */ |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 018884d7a5fa..b05de30b5d9b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
| @@ -303,8 +303,7 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) | |||
| 303 | * creates board info from kernel command lines | 303 | * creates board info from kernel command lines |
| 304 | */ | 304 | */ |
| 305 | 305 | ||
| 306 | static void __init_or_module | 306 | static void scan_boardinfo(struct spi_master *master) |
| 307 | scan_boardinfo(struct spi_master *master) | ||
| 308 | { | 307 | { |
| 309 | struct boardinfo *bi; | 308 | struct boardinfo *bi; |
| 310 | struct device *dev = master->cdev.dev; | 309 | struct device *dev = master->cdev.dev; |
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index b09c83568c1a..1cb56f2d5c84 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c | |||
| @@ -138,7 +138,7 @@ exit: | |||
| 138 | 138 | ||
| 139 | static int appledisplay_bl_update_status(struct backlight_device *bd) | 139 | static int appledisplay_bl_update_status(struct backlight_device *bd) |
| 140 | { | 140 | { |
| 141 | struct appledisplay *pdata = class_get_devdata(&bd->class_dev); | 141 | struct appledisplay *pdata = bl_get_data(bd); |
| 142 | int retval; | 142 | int retval; |
| 143 | 143 | ||
| 144 | pdata->msgdata[0] = 0x10; | 144 | pdata->msgdata[0] = 0x10; |
| @@ -159,7 +159,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd) | |||
| 159 | 159 | ||
| 160 | static int appledisplay_bl_get_brightness(struct backlight_device *bd) | 160 | static int appledisplay_bl_get_brightness(struct backlight_device *bd) |
| 161 | { | 161 | { |
| 162 | struct appledisplay *pdata = class_get_devdata(&bd->class_dev); | 162 | struct appledisplay *pdata = bl_get_data(bd); |
| 163 | int retval; | 163 | int retval; |
| 164 | 164 | ||
| 165 | retval = usb_control_msg( | 165 | retval = usb_control_msg( |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 0c5644bb59af..564cc9b51822 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -12,6 +12,13 @@ config VGASTATE | |||
| 12 | tristate | 12 | tristate |
| 13 | default n | 13 | default n |
| 14 | 14 | ||
| 15 | config VIDEO_OUTPUT_CONTROL | ||
| 16 | tristate "Lowlevel video output switch controls" | ||
| 17 | default m | ||
| 18 | help | ||
| 19 | This framework adds support for low-level control of the video | ||
| 20 | output switch. | ||
| 21 | |||
| 15 | config FB | 22 | config FB |
| 16 | tristate "Support for frame buffer devices" | 23 | tristate "Support for frame buffer devices" |
| 17 | ---help--- | 24 | ---help--- |
| @@ -849,6 +856,16 @@ config FB_INTSRAM | |||
| 849 | Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want | 856 | Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want |
| 850 | to let frame buffer in external SDRAM. | 857 | to let frame buffer in external SDRAM. |
| 851 | 858 | ||
| 859 | config FB_ATMEL_STN | ||
| 860 | bool "Use a STN display with AT91/AT32 LCD Controller" | ||
| 861 | depends on FB_ATMEL && MACH_AT91SAM9261EK | ||
| 862 | default n | ||
| 863 | help | ||
| 864 | Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD | ||
| 865 | Controller. Say N if you want to connect a TFT. | ||
| 866 | |||
| 867 | If unsure, say N. | ||
| 868 | |||
| 852 | config FB_NVIDIA | 869 | config FB_NVIDIA |
| 853 | tristate "nVidia Framebuffer Support" | 870 | tristate "nVidia Framebuffer Support" |
| 854 | depends on FB && PCI | 871 | depends on FB && PCI |
| @@ -1796,13 +1813,14 @@ config FB_PS3 | |||
| 1796 | select FB_SYS_COPYAREA | 1813 | select FB_SYS_COPYAREA |
| 1797 | select FB_SYS_IMAGEBLIT | 1814 | select FB_SYS_IMAGEBLIT |
| 1798 | select FB_SYS_FOPS | 1815 | select FB_SYS_FOPS |
| 1816 | select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE | ||
| 1799 | ---help--- | 1817 | ---help--- |
| 1800 | Include support for the virtual frame buffer in the PS3 platform. | 1818 | Include support for the virtual frame buffer in the PS3 platform. |
| 1801 | 1819 | ||
| 1802 | config FB_PS3_DEFAULT_SIZE_M | 1820 | config FB_PS3_DEFAULT_SIZE_M |
| 1803 | int "PS3 default frame buffer size (in MiB)" | 1821 | int "PS3 default frame buffer size (in MiB)" |
| 1804 | depends on FB_PS3 | 1822 | depends on FB_PS3 |
| 1805 | default 18 | 1823 | default 9 |
| 1806 | ---help--- | 1824 | ---help--- |
| 1807 | This is the default size (in MiB) of the virtual frame buffer in | 1825 | This is the default size (in MiB) of the virtual frame buffer in |
| 1808 | the PS3. | 1826 | the PS3. |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index a562f9d69d2c..518933d4905f 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
| @@ -123,3 +123,6 @@ obj-$(CONFIG_FB_OF) += offb.o | |||
| 123 | 123 | ||
| 124 | # the test framebuffer is last | 124 | # the test framebuffer is last |
| 125 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o | 125 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o |
| 126 | |||
| 127 | #video output switch sysfs driver | ||
| 128 | obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o | ||
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index e1d5bd0c98c4..235b618b4117 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
| @@ -79,6 +79,29 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { | |||
| 79 | .accel = FB_ACCEL_NONE, | 79 | .accel = FB_ACCEL_NONE, |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) | ||
| 83 | { | ||
| 84 | unsigned long value; | ||
| 85 | |||
| 86 | if (!(cpu_is_at91sam9261() || cpu_is_at32ap7000())) | ||
| 87 | return xres; | ||
| 88 | |||
| 89 | value = xres; | ||
| 90 | if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) { | ||
| 91 | /* STN display */ | ||
| 92 | if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) { | ||
| 93 | value *= 3; | ||
| 94 | } | ||
| 95 | if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4 | ||
| 96 | || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8 | ||
| 97 | && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL )) | ||
| 98 | value = DIV_ROUND_UP(value, 4); | ||
| 99 | else | ||
| 100 | value = DIV_ROUND_UP(value, 8); | ||
| 101 | } | ||
| 102 | |||
| 103 | return value; | ||
| 104 | } | ||
| 82 | 105 | ||
| 83 | static void atmel_lcdfb_update_dma(struct fb_info *info, | 106 | static void atmel_lcdfb_update_dma(struct fb_info *info, |
| 84 | struct fb_var_screeninfo *var) | 107 | struct fb_var_screeninfo *var) |
| @@ -181,6 +204,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
| 181 | var->xoffset = var->yoffset = 0; | 204 | var->xoffset = var->yoffset = 0; |
| 182 | 205 | ||
| 183 | switch (var->bits_per_pixel) { | 206 | switch (var->bits_per_pixel) { |
| 207 | case 1: | ||
| 184 | case 2: | 208 | case 2: |
| 185 | case 4: | 209 | case 4: |
| 186 | case 8: | 210 | case 8: |
| @@ -195,8 +219,11 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
| 195 | var->blue.offset = 10; | 219 | var->blue.offset = 10; |
| 196 | var->red.length = var->green.length = var->blue.length = 5; | 220 | var->red.length = var->green.length = var->blue.length = 5; |
| 197 | break; | 221 | break; |
| 198 | case 24: | ||
| 199 | case 32: | 222 | case 32: |
| 223 | var->transp.offset = 24; | ||
| 224 | var->transp.length = 8; | ||
| 225 | /* fall through */ | ||
| 226 | case 24: | ||
| 200 | var->red.offset = 0; | 227 | var->red.offset = 0; |
| 201 | var->green.offset = 8; | 228 | var->green.offset = 8; |
| 202 | var->blue.offset = 16; | 229 | var->blue.offset = 16; |
| @@ -228,8 +255,10 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
| 228 | static int atmel_lcdfb_set_par(struct fb_info *info) | 255 | static int atmel_lcdfb_set_par(struct fb_info *info) |
| 229 | { | 256 | { |
| 230 | struct atmel_lcdfb_info *sinfo = info->par; | 257 | struct atmel_lcdfb_info *sinfo = info->par; |
| 258 | unsigned long hozval_linesz; | ||
| 231 | unsigned long value; | 259 | unsigned long value; |
| 232 | unsigned long clk_value_khz; | 260 | unsigned long clk_value_khz; |
| 261 | unsigned long bits_per_line; | ||
| 233 | 262 | ||
| 234 | dev_dbg(info->device, "%s:\n", __func__); | 263 | dev_dbg(info->device, "%s:\n", __func__); |
| 235 | dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", | 264 | dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", |
| @@ -241,12 +270,15 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
| 241 | 270 | ||
| 242 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); | 271 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); |
| 243 | 272 | ||
| 244 | if (info->var.bits_per_pixel <= 8) | 273 | if (info->var.bits_per_pixel == 1) |
| 274 | info->fix.visual = FB_VISUAL_MONO01; | ||
| 275 | else if (info->var.bits_per_pixel <= 8) | ||
| 245 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | 276 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; |
| 246 | else | 277 | else |
| 247 | info->fix.visual = FB_VISUAL_TRUECOLOR; | 278 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
| 248 | 279 | ||
| 249 | info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8); | 280 | bits_per_line = info->var.xres_virtual * info->var.bits_per_pixel; |
| 281 | info->fix.line_length = DIV_ROUND_UP(bits_per_line, 8); | ||
| 250 | 282 | ||
| 251 | /* Re-initialize the DMA engine... */ | 283 | /* Re-initialize the DMA engine... */ |
| 252 | dev_dbg(info->device, " * update DMA engine\n"); | 284 | dev_dbg(info->device, " * update DMA engine\n"); |
| @@ -262,18 +294,21 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
| 262 | /* Set pixel clock */ | 294 | /* Set pixel clock */ |
| 263 | clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; | 295 | clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; |
| 264 | 296 | ||
| 265 | value = clk_value_khz / PICOS2KHZ(info->var.pixclock); | 297 | value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock)); |
| 266 | |||
| 267 | if (clk_value_khz % PICOS2KHZ(info->var.pixclock)) | ||
| 268 | value++; | ||
| 269 | 298 | ||
| 270 | value = (value / 2) - 1; | 299 | value = (value / 2) - 1; |
| 300 | dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n", value); | ||
| 271 | 301 | ||
| 272 | if (value <= 0) { | 302 | if (value <= 0) { |
| 273 | dev_notice(info->device, "Bypassing pixel clock divider\n"); | 303 | dev_notice(info->device, "Bypassing pixel clock divider\n"); |
| 274 | lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS); | 304 | lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS); |
| 275 | } else | 305 | } else { |
| 276 | lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET); | 306 | lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET); |
| 307 | info->var.pixclock = KHZ2PICOS(clk_value_khz / (2 * (value + 1))); | ||
| 308 | dev_dbg(info->device, " updated pixclk: %lu KHz\n", | ||
| 309 | PICOS2KHZ(info->var.pixclock)); | ||
| 310 | } | ||
| 311 | |||
| 277 | 312 | ||
| 278 | /* Initialize control register 2 */ | 313 | /* Initialize control register 2 */ |
| 279 | value = sinfo->default_lcdcon2; | 314 | value = sinfo->default_lcdcon2; |
| @@ -311,9 +346,14 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
| 311 | dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value); | 346 | dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value); |
| 312 | lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); | 347 | lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); |
| 313 | 348 | ||
| 349 | /* Horizontal value (aka line size) */ | ||
| 350 | hozval_linesz = compute_hozval(info->var.xres, | ||
| 351 | lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2)); | ||
| 352 | |||
| 314 | /* Display size */ | 353 | /* Display size */ |
| 315 | value = (info->var.xres - 1) << ATMEL_LCDC_HOZVAL_OFFSET; | 354 | value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET; |
| 316 | value |= info->var.yres - 1; | 355 | value |= info->var.yres - 1; |
| 356 | dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value); | ||
| 317 | lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value); | 357 | lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value); |
| 318 | 358 | ||
| 319 | /* FIFO Threshold: Use formula from data sheet */ | 359 | /* FIFO Threshold: Use formula from data sheet */ |
| @@ -421,6 +461,15 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, | |||
| 421 | ret = 0; | 461 | ret = 0; |
| 422 | } | 462 | } |
| 423 | break; | 463 | break; |
| 464 | |||
| 465 | case FB_VISUAL_MONO01: | ||
| 466 | if (regno < 2) { | ||
| 467 | val = (regno == 0) ? 0x00 : 0x1F; | ||
| 468 | lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); | ||
| 469 | ret = 0; | ||
| 470 | } | ||
| 471 | break; | ||
| 472 | |||
| 424 | } | 473 | } |
| 425 | 474 | ||
| 426 | return ret; | 475 | return ret; |
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 7fea4d8ae8e2..cfcbe37d2d70 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
| @@ -1733,7 +1733,7 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par, | |||
| 1733 | 1733 | ||
| 1734 | static int aty128_bl_update_status(struct backlight_device *bd) | 1734 | static int aty128_bl_update_status(struct backlight_device *bd) |
| 1735 | { | 1735 | { |
| 1736 | struct aty128fb_par *par = class_get_devdata(&bd->class_dev); | 1736 | struct aty128fb_par *par = bl_get_data(bd); |
| 1737 | unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); | 1737 | unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); |
| 1738 | int level; | 1738 | int level; |
| 1739 | 1739 | ||
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 13990697b5c1..bc6f0096aa04 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
| @@ -2141,7 +2141,7 @@ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level) | |||
| 2141 | 2141 | ||
| 2142 | static int aty_bl_update_status(struct backlight_device *bd) | 2142 | static int aty_bl_update_status(struct backlight_device *bd) |
| 2143 | { | 2143 | { |
| 2144 | struct atyfb_par *par = class_get_devdata(&bd->class_dev); | 2144 | struct atyfb_par *par = bl_get_data(bd); |
| 2145 | unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); | 2145 | unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); |
| 2146 | int level; | 2146 | int level; |
| 2147 | 2147 | ||
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c index 0be25fa5540c..1a056adb61c8 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c | |||
| @@ -47,7 +47,7 @@ static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata, | |||
| 47 | 47 | ||
| 48 | static int radeon_bl_update_status(struct backlight_device *bd) | 48 | static int radeon_bl_update_status(struct backlight_device *bd) |
| 49 | { | 49 | { |
| 50 | struct radeon_bl_privdata *pdata = class_get_devdata(&bd->class_dev); | 50 | struct radeon_bl_privdata *pdata = bl_get_data(bd); |
| 51 | struct radeonfb_info *rinfo = pdata->rinfo; | 51 | struct radeonfb_info *rinfo = pdata->rinfo; |
| 52 | u32 lvds_gen_cntl, tmpPixclksCntl; | 52 | u32 lvds_gen_cntl, tmpPixclksCntl; |
| 53 | int level; | 53 | int level; |
| @@ -206,7 +206,7 @@ void radeonfb_bl_exit(struct radeonfb_info *rinfo) | |||
| 206 | if (bd) { | 206 | if (bd) { |
| 207 | struct radeon_bl_privdata *pdata; | 207 | struct radeon_bl_privdata *pdata; |
| 208 | 208 | ||
| 209 | pdata = class_get_devdata(&bd->class_dev); | 209 | pdata = bl_get_data(bd); |
| 210 | backlight_device_unregister(bd); | 210 | backlight_device_unregister(bd); |
| 211 | kfree(pdata); | 211 | kfree(pdata); |
| 212 | rinfo->info->bl_dev = NULL; | 212 | rinfo->info->bl_dev = NULL; |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index fbef663fc057..2580f5fa2486 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
| @@ -8,26 +8,32 @@ menuconfig BACKLIGHT_LCD_SUPPORT | |||
| 8 | Enable this to be able to choose the drivers for controlling the | 8 | Enable this to be able to choose the drivers for controlling the |
| 9 | backlight and the LCD panel on some platforms, for example on PDAs. | 9 | backlight and the LCD panel on some platforms, for example on PDAs. |
| 10 | 10 | ||
| 11 | config BACKLIGHT_CLASS_DEVICE | 11 | # |
| 12 | tristate "Lowlevel Backlight controls" | 12 | # LCD |
| 13 | # | ||
| 14 | config LCD_CLASS_DEVICE | ||
| 15 | tristate "Lowlevel LCD controls" | ||
| 13 | depends on BACKLIGHT_LCD_SUPPORT | 16 | depends on BACKLIGHT_LCD_SUPPORT |
| 14 | default m | 17 | default m |
| 15 | help | 18 | help |
| 16 | This framework adds support for low-level control of the LCD | 19 | This framework adds support for low-level control of LCD. |
| 17 | backlight. This includes support for brightness and power. | 20 | Some framebuffer devices connect to platform-specific LCD modules |
| 21 | in order to have a platform-specific way to control the flat panel | ||
| 22 | (contrast and applying power to the LCD (not to the backlight!)). | ||
| 18 | 23 | ||
| 19 | To have support for your specific LCD panel you will have to | 24 | To have support for your specific LCD panel you will have to |
| 20 | select the proper drivers which depend on this option. | 25 | select the proper drivers which depend on this option. |
| 21 | 26 | ||
| 22 | config LCD_CLASS_DEVICE | 27 | # |
| 23 | tristate "Lowlevel LCD controls" | 28 | # Backlight |
| 29 | # | ||
| 30 | config BACKLIGHT_CLASS_DEVICE | ||
| 31 | tristate "Lowlevel Backlight controls" | ||
| 24 | depends on BACKLIGHT_LCD_SUPPORT | 32 | depends on BACKLIGHT_LCD_SUPPORT |
| 25 | default m | 33 | default m |
| 26 | help | 34 | help |
| 27 | This framework adds support for low-level control of LCD. | 35 | This framework adds support for low-level control of the LCD |
| 28 | Some framebuffer devices connect to platform-specific LCD modules | 36 | backlight. This includes support for brightness and power. |
| 29 | in order to have a platform-specific way to control the flat panel | ||
| 30 | (contrast and applying power to the LCD (not to the backlight!)). | ||
| 31 | 37 | ||
| 32 | To have support for your specific LCD panel you will have to | 38 | To have support for your specific LCD panel you will have to |
| 33 | select the proper drivers which depend on this option. | 39 | select the proper drivers which depend on this option. |
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 7e06223bca94..b26de8cf3112 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
| @@ -69,18 +69,20 @@ static inline void backlight_unregister_fb(struct backlight_device *bd) | |||
| 69 | } | 69 | } |
| 70 | #endif /* CONFIG_FB */ | 70 | #endif /* CONFIG_FB */ |
| 71 | 71 | ||
| 72 | static ssize_t backlight_show_power(struct class_device *cdev, char *buf) | 72 | static ssize_t backlight_show_power(struct device *dev, |
| 73 | struct device_attribute *attr,char *buf) | ||
| 73 | { | 74 | { |
| 74 | struct backlight_device *bd = to_backlight_device(cdev); | 75 | struct backlight_device *bd = to_backlight_device(dev); |
| 75 | 76 | ||
| 76 | return sprintf(buf, "%d\n", bd->props.power); | 77 | return sprintf(buf, "%d\n", bd->props.power); |
| 77 | } | 78 | } |
| 78 | 79 | ||
| 79 | static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count) | 80 | static ssize_t backlight_store_power(struct device *dev, |
| 81 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 80 | { | 82 | { |
| 81 | int rc = -ENXIO; | 83 | int rc = -ENXIO; |
| 82 | char *endp; | 84 | char *endp; |
| 83 | struct backlight_device *bd = to_backlight_device(cdev); | 85 | struct backlight_device *bd = to_backlight_device(dev); |
| 84 | int power = simple_strtoul(buf, &endp, 0); | 86 | int power = simple_strtoul(buf, &endp, 0); |
| 85 | size_t size = endp - buf; | 87 | size_t size = endp - buf; |
| 86 | 88 | ||
| @@ -101,18 +103,20 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, | |||
| 101 | return rc; | 103 | return rc; |
| 102 | } | 104 | } |
| 103 | 105 | ||
| 104 | static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) | 106 | static ssize_t backlight_show_brightness(struct device *dev, |
| 107 | struct device_attribute *attr, char *buf) | ||
| 105 | { | 108 | { |
| 106 | struct backlight_device *bd = to_backlight_device(cdev); | 109 | struct backlight_device *bd = to_backlight_device(dev); |
| 107 | 110 | ||
| 108 | return sprintf(buf, "%d\n", bd->props.brightness); | 111 | return sprintf(buf, "%d\n", bd->props.brightness); |
| 109 | } | 112 | } |
| 110 | 113 | ||
| 111 | static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count) | 114 | static ssize_t backlight_store_brightness(struct device *dev, |
| 115 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 112 | { | 116 | { |
| 113 | int rc = -ENXIO; | 117 | int rc = -ENXIO; |
| 114 | char *endp; | 118 | char *endp; |
| 115 | struct backlight_device *bd = to_backlight_device(cdev); | 119 | struct backlight_device *bd = to_backlight_device(dev); |
| 116 | int brightness = simple_strtoul(buf, &endp, 0); | 120 | int brightness = simple_strtoul(buf, &endp, 0); |
| 117 | size_t size = endp - buf; | 121 | size_t size = endp - buf; |
| 118 | 122 | ||
| @@ -138,18 +142,19 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char | |||
| 138 | return rc; | 142 | return rc; |
| 139 | } | 143 | } |
| 140 | 144 | ||
| 141 | static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf) | 145 | static ssize_t backlight_show_max_brightness(struct device *dev, |
| 146 | struct device_attribute *attr, char *buf) | ||
| 142 | { | 147 | { |
| 143 | struct backlight_device *bd = to_backlight_device(cdev); | 148 | struct backlight_device *bd = to_backlight_device(dev); |
| 144 | 149 | ||
| 145 | return sprintf(buf, "%d\n", bd->props.max_brightness); | 150 | return sprintf(buf, "%d\n", bd->props.max_brightness); |
| 146 | } | 151 | } |
| 147 | 152 | ||
| 148 | static ssize_t backlight_show_actual_brightness(struct class_device *cdev, | 153 | static ssize_t backlight_show_actual_brightness(struct device *dev, |
| 149 | char *buf) | 154 | struct device_attribute *attr, char *buf) |
| 150 | { | 155 | { |
| 151 | int rc = -ENXIO; | 156 | int rc = -ENXIO; |
| 152 | struct backlight_device *bd = to_backlight_device(cdev); | 157 | struct backlight_device *bd = to_backlight_device(dev); |
| 153 | 158 | ||
| 154 | mutex_lock(&bd->ops_lock); | 159 | mutex_lock(&bd->ops_lock); |
| 155 | if (bd->ops && bd->ops->get_brightness) | 160 | if (bd->ops && bd->ops->get_brightness) |
| @@ -159,31 +164,22 @@ static ssize_t backlight_show_actual_brightness(struct class_device *cdev, | |||
| 159 | return rc; | 164 | return rc; |
| 160 | } | 165 | } |
| 161 | 166 | ||
| 162 | static void backlight_class_release(struct class_device *dev) | 167 | struct class *backlight_class; |
| 168 | |||
| 169 | static void bl_device_release(struct device *dev) | ||
| 163 | { | 170 | { |
| 164 | struct backlight_device *bd = to_backlight_device(dev); | 171 | struct backlight_device *bd = to_backlight_device(dev); |
| 165 | kfree(bd); | 172 | kfree(bd); |
| 166 | } | 173 | } |
| 167 | 174 | ||
| 168 | static struct class backlight_class = { | 175 | static struct device_attribute bl_device_attributes[] = { |
| 169 | .name = "backlight", | 176 | __ATTR(bl_power, 0644, backlight_show_power, backlight_store_power), |
| 170 | .release = backlight_class_release, | 177 | __ATTR(brightness, 0644, backlight_show_brightness, |
| 171 | }; | ||
| 172 | |||
| 173 | #define DECLARE_ATTR(_name,_mode,_show,_store) \ | ||
| 174 | { \ | ||
| 175 | .attr = { .name = __stringify(_name), .mode = _mode }, \ | ||
| 176 | .show = _show, \ | ||
| 177 | .store = _store, \ | ||
| 178 | } | ||
| 179 | |||
| 180 | static const struct class_device_attribute bl_class_device_attributes[] = { | ||
| 181 | DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power), | ||
| 182 | DECLARE_ATTR(brightness, 0644, backlight_show_brightness, | ||
| 183 | backlight_store_brightness), | 178 | backlight_store_brightness), |
| 184 | DECLARE_ATTR(actual_brightness, 0444, backlight_show_actual_brightness, | 179 | __ATTR(actual_brightness, 0444, backlight_show_actual_brightness, |
| 185 | NULL), | 180 | NULL), |
| 186 | DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), | 181 | __ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), |
| 182 | __ATTR_NULL, | ||
| 187 | }; | 183 | }; |
| 188 | 184 | ||
| 189 | /** | 185 | /** |
| @@ -191,22 +187,20 @@ static const struct class_device_attribute bl_class_device_attributes[] = { | |||
| 191 | * backlight_device class. | 187 | * backlight_device class. |
| 192 | * @name: the name of the new object(must be the same as the name of the | 188 | * @name: the name of the new object(must be the same as the name of the |
| 193 | * respective framebuffer device). | 189 | * respective framebuffer device). |
| 194 | * @devdata: an optional pointer to be stored in the class_device. The | 190 | * @devdata: an optional pointer to be stored for private driver use. The |
| 195 | * methods may retrieve it by using class_get_devdata(&bd->class_dev). | 191 | * methods may retrieve it by using bl_get_data(bd). |
| 196 | * @ops: the backlight operations structure. | 192 | * @ops: the backlight operations structure. |
| 197 | * | 193 | * |
| 198 | * Creates and registers new backlight class_device. Returns either an | 194 | * Creates and registers new backlight device. Returns either an |
| 199 | * ERR_PTR() or a pointer to the newly allocated device. | 195 | * ERR_PTR() or a pointer to the newly allocated device. |
| 200 | */ | 196 | */ |
| 201 | struct backlight_device *backlight_device_register(const char *name, | 197 | struct backlight_device *backlight_device_register(const char *name, |
| 202 | struct device *dev, | 198 | struct device *parent, void *devdata, struct backlight_ops *ops) |
| 203 | void *devdata, | ||
| 204 | struct backlight_ops *ops) | ||
| 205 | { | 199 | { |
| 206 | int i, rc; | ||
| 207 | struct backlight_device *new_bd; | 200 | struct backlight_device *new_bd; |
| 201 | int rc; | ||
| 208 | 202 | ||
| 209 | pr_debug("backlight_device_alloc: name=%s\n", name); | 203 | pr_debug("backlight_device_register: name=%s\n", name); |
| 210 | 204 | ||
| 211 | new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL); | 205 | new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL); |
| 212 | if (!new_bd) | 206 | if (!new_bd) |
| @@ -214,13 +208,14 @@ struct backlight_device *backlight_device_register(const char *name, | |||
| 214 | 208 | ||
| 215 | mutex_init(&new_bd->update_lock); | 209 | mutex_init(&new_bd->update_lock); |
| 216 | mutex_init(&new_bd->ops_lock); | 210 | mutex_init(&new_bd->ops_lock); |
| 217 | new_bd->ops = ops; | ||
| 218 | new_bd->class_dev.class = &backlight_class; | ||
| 219 | new_bd->class_dev.dev = dev; | ||
| 220 | strlcpy(new_bd->class_dev.class_id, name, KOBJ_NAME_LEN); | ||
| 221 | class_set_devdata(&new_bd->class_dev, devdata); | ||
| 222 | 211 | ||
| 223 | rc = class_device_register(&new_bd->class_dev); | 212 | new_bd->dev.class = backlight_class; |
| 213 | new_bd->dev.parent = parent; | ||
| 214 | new_bd->dev.release = bl_device_release; | ||
| 215 | strlcpy(new_bd->dev.bus_id, name, BUS_ID_SIZE); | ||
| 216 | dev_set_drvdata(&new_bd->dev, devdata); | ||
| 217 | |||
| 218 | rc = device_register(&new_bd->dev); | ||
| 224 | if (rc) { | 219 | if (rc) { |
| 225 | kfree(new_bd); | 220 | kfree(new_bd); |
| 226 | return ERR_PTR(rc); | 221 | return ERR_PTR(rc); |
| @@ -228,23 +223,11 @@ struct backlight_device *backlight_device_register(const char *name, | |||
| 228 | 223 | ||
| 229 | rc = backlight_register_fb(new_bd); | 224 | rc = backlight_register_fb(new_bd); |
| 230 | if (rc) { | 225 | if (rc) { |
| 231 | class_device_unregister(&new_bd->class_dev); | 226 | device_unregister(&new_bd->dev); |
| 232 | return ERR_PTR(rc); | 227 | return ERR_PTR(rc); |
| 233 | } | 228 | } |
| 234 | 229 | ||
| 235 | 230 | new_bd->ops = ops; | |
| 236 | for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++) { | ||
| 237 | rc = class_device_create_file(&new_bd->class_dev, | ||
| 238 | &bl_class_device_attributes[i]); | ||
| 239 | if (rc) { | ||
| 240 | while (--i >= 0) | ||
| 241 | class_device_remove_file(&new_bd->class_dev, | ||
| 242 | &bl_class_device_attributes[i]); | ||
| 243 | class_device_unregister(&new_bd->class_dev); | ||
| 244 | /* No need to kfree(new_bd) since release() method was called */ | ||
| 245 | return ERR_PTR(rc); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | 231 | ||
| 249 | #ifdef CONFIG_PMAC_BACKLIGHT | 232 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 250 | mutex_lock(&pmac_backlight_mutex); | 233 | mutex_lock(&pmac_backlight_mutex); |
| @@ -265,42 +248,40 @@ EXPORT_SYMBOL(backlight_device_register); | |||
| 265 | */ | 248 | */ |
| 266 | void backlight_device_unregister(struct backlight_device *bd) | 249 | void backlight_device_unregister(struct backlight_device *bd) |
| 267 | { | 250 | { |
| 268 | int i; | ||
| 269 | |||
| 270 | if (!bd) | 251 | if (!bd) |
| 271 | return; | 252 | return; |
| 272 | 253 | ||
| 273 | pr_debug("backlight_device_unregister: name=%s\n", bd->class_dev.class_id); | ||
| 274 | |||
| 275 | #ifdef CONFIG_PMAC_BACKLIGHT | 254 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 276 | mutex_lock(&pmac_backlight_mutex); | 255 | mutex_lock(&pmac_backlight_mutex); |
| 277 | if (pmac_backlight == bd) | 256 | if (pmac_backlight == bd) |
| 278 | pmac_backlight = NULL; | 257 | pmac_backlight = NULL; |
| 279 | mutex_unlock(&pmac_backlight_mutex); | 258 | mutex_unlock(&pmac_backlight_mutex); |
| 280 | #endif | 259 | #endif |
| 281 | |||
| 282 | for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++) | ||
| 283 | class_device_remove_file(&bd->class_dev, | ||
| 284 | &bl_class_device_attributes[i]); | ||
| 285 | |||
| 286 | mutex_lock(&bd->ops_lock); | 260 | mutex_lock(&bd->ops_lock); |
| 287 | bd->ops = NULL; | 261 | bd->ops = NULL; |
| 288 | mutex_unlock(&bd->ops_lock); | 262 | mutex_unlock(&bd->ops_lock); |
| 289 | 263 | ||
| 290 | backlight_unregister_fb(bd); | 264 | backlight_unregister_fb(bd); |
| 291 | 265 | device_unregister(&bd->dev); | |
| 292 | class_device_unregister(&bd->class_dev); | ||
| 293 | } | 266 | } |
| 294 | EXPORT_SYMBOL(backlight_device_unregister); | 267 | EXPORT_SYMBOL(backlight_device_unregister); |
| 295 | 268 | ||
| 296 | static void __exit backlight_class_exit(void) | 269 | static void __exit backlight_class_exit(void) |
| 297 | { | 270 | { |
| 298 | class_unregister(&backlight_class); | 271 | class_destroy(backlight_class); |
| 299 | } | 272 | } |
| 300 | 273 | ||
| 301 | static int __init backlight_class_init(void) | 274 | static int __init backlight_class_init(void) |
| 302 | { | 275 | { |
| 303 | return class_register(&backlight_class); | 276 | backlight_class = class_create(THIS_MODULE, "backlight"); |
| 277 | if (IS_ERR(backlight_class)) { | ||
| 278 | printk(KERN_WARNING "Unable to create backlight class; errno = %ld\n", | ||
| 279 | PTR_ERR(backlight_class)); | ||
| 280 | return PTR_ERR(backlight_class); | ||
| 281 | } | ||
| 282 | |||
| 283 | backlight_class->dev_attrs = bl_device_attributes; | ||
| 284 | return 0; | ||
| 304 | } | 285 | } |
| 305 | 286 | ||
| 306 | /* | 287 | /* |
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c index 1b3f6586bc9f..b7904da51b23 100644 --- a/drivers/video/backlight/cr_bllcd.c +++ b/drivers/video/backlight/cr_bllcd.c | |||
| @@ -202,7 +202,7 @@ static int cr_backlight_probe(struct platform_device *pdev) | |||
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | crp->cr_lcd_device = lcd_device_register("cr-lcd", | 204 | crp->cr_lcd_device = lcd_device_register("cr-lcd", |
| 205 | &pdev->dev, | 205 | &pdev->dev, NULL, |
| 206 | &cr_lcd_ops); | 206 | &cr_lcd_ops); |
| 207 | 207 | ||
| 208 | if (IS_ERR(crp->cr_lcd_device)) { | 208 | if (IS_ERR(crp->cr_lcd_device)) { |
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 648b53c1fdea..6f652c65fae1 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
| @@ -61,10 +61,11 @@ static inline void lcd_unregister_fb(struct lcd_device *ld) | |||
| 61 | } | 61 | } |
| 62 | #endif /* CONFIG_FB */ | 62 | #endif /* CONFIG_FB */ |
| 63 | 63 | ||
| 64 | static ssize_t lcd_show_power(struct class_device *cdev, char *buf) | 64 | static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr, |
| 65 | char *buf) | ||
| 65 | { | 66 | { |
| 66 | int rc; | 67 | int rc; |
| 67 | struct lcd_device *ld = to_lcd_device(cdev); | 68 | struct lcd_device *ld = to_lcd_device(dev); |
| 68 | 69 | ||
| 69 | mutex_lock(&ld->ops_lock); | 70 | mutex_lock(&ld->ops_lock); |
| 70 | if (ld->ops && ld->ops->get_power) | 71 | if (ld->ops && ld->ops->get_power) |
| @@ -76,11 +77,12 @@ static ssize_t lcd_show_power(struct class_device *cdev, char *buf) | |||
| 76 | return rc; | 77 | return rc; |
| 77 | } | 78 | } |
| 78 | 79 | ||
| 79 | static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_t count) | 80 | static ssize_t lcd_store_power(struct device *dev, |
| 81 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 80 | { | 82 | { |
| 81 | int rc = -ENXIO; | 83 | int rc = -ENXIO; |
| 82 | char *endp; | 84 | char *endp; |
| 83 | struct lcd_device *ld = to_lcd_device(cdev); | 85 | struct lcd_device *ld = to_lcd_device(dev); |
| 84 | int power = simple_strtoul(buf, &endp, 0); | 86 | int power = simple_strtoul(buf, &endp, 0); |
| 85 | size_t size = endp - buf; | 87 | size_t size = endp - buf; |
| 86 | 88 | ||
| @@ -100,10 +102,11 @@ static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_ | |||
| 100 | return rc; | 102 | return rc; |
| 101 | } | 103 | } |
| 102 | 104 | ||
| 103 | static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf) | 105 | static ssize_t lcd_show_contrast(struct device *dev, |
| 106 | struct device_attribute *attr, char *buf) | ||
| 104 | { | 107 | { |
| 105 | int rc = -ENXIO; | 108 | int rc = -ENXIO; |
| 106 | struct lcd_device *ld = to_lcd_device(cdev); | 109 | struct lcd_device *ld = to_lcd_device(dev); |
| 107 | 110 | ||
| 108 | mutex_lock(&ld->ops_lock); | 111 | mutex_lock(&ld->ops_lock); |
| 109 | if (ld->ops && ld->ops->get_contrast) | 112 | if (ld->ops && ld->ops->get_contrast) |
| @@ -113,11 +116,12 @@ static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf) | |||
| 113 | return rc; | 116 | return rc; |
| 114 | } | 117 | } |
| 115 | 118 | ||
| 116 | static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, size_t count) | 119 | static ssize_t lcd_store_contrast(struct device *dev, |
| 120 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 117 | { | 121 | { |
| 118 | int rc = -ENXIO; | 122 | int rc = -ENXIO; |
| 119 | char *endp; | 123 | char *endp; |
| 120 | struct lcd_device *ld = to_lcd_device(cdev); | 124 | struct lcd_device *ld = to_lcd_device(dev); |
| 121 | int contrast = simple_strtoul(buf, &endp, 0); | 125 | int contrast = simple_strtoul(buf, &endp, 0); |
| 122 | size_t size = endp - buf; | 126 | size_t size = endp - buf; |
| 123 | 127 | ||
| @@ -137,53 +141,45 @@ static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, si | |||
| 137 | return rc; | 141 | return rc; |
| 138 | } | 142 | } |
| 139 | 143 | ||
| 140 | static ssize_t lcd_show_max_contrast(struct class_device *cdev, char *buf) | 144 | static ssize_t lcd_show_max_contrast(struct device *dev, |
| 145 | struct device_attribute *attr, char *buf) | ||
| 141 | { | 146 | { |
| 142 | struct lcd_device *ld = to_lcd_device(cdev); | 147 | struct lcd_device *ld = to_lcd_device(dev); |
| 143 | 148 | ||
| 144 | return sprintf(buf, "%d\n", ld->props.max_contrast); | 149 | return sprintf(buf, "%d\n", ld->props.max_contrast); |
| 145 | } | 150 | } |
| 146 | 151 | ||
| 147 | static void lcd_class_release(struct class_device *dev) | 152 | struct class *lcd_class; |
| 153 | |||
| 154 | static void lcd_device_release(struct device *dev) | ||
| 148 | { | 155 | { |
| 149 | struct lcd_device *ld = to_lcd_device(dev); | 156 | struct lcd_device *ld = to_lcd_device(dev); |
| 150 | kfree(ld); | 157 | kfree(ld); |
| 151 | } | 158 | } |
| 152 | 159 | ||
| 153 | static struct class lcd_class = { | 160 | static struct device_attribute lcd_device_attributes[] = { |
| 154 | .name = "lcd", | 161 | __ATTR(lcd_power, 0644, lcd_show_power, lcd_store_power), |
| 155 | .release = lcd_class_release, | 162 | __ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast), |
| 156 | }; | 163 | __ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL), |
| 157 | 164 | __ATTR_NULL, | |
| 158 | #define DECLARE_ATTR(_name,_mode,_show,_store) \ | ||
| 159 | { \ | ||
| 160 | .attr = { .name = __stringify(_name), .mode = _mode }, \ | ||
| 161 | .show = _show, \ | ||
| 162 | .store = _store, \ | ||
| 163 | } | ||
| 164 | |||
| 165 | static const struct class_device_attribute lcd_class_device_attributes[] = { | ||
| 166 | DECLARE_ATTR(power, 0644, lcd_show_power, lcd_store_power), | ||
| 167 | DECLARE_ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast), | ||
| 168 | DECLARE_ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL), | ||
| 169 | }; | 165 | }; |
| 170 | 166 | ||
| 171 | /** | 167 | /** |
| 172 | * lcd_device_register - register a new object of lcd_device class. | 168 | * lcd_device_register - register a new object of lcd_device class. |
| 173 | * @name: the name of the new object(must be the same as the name of the | 169 | * @name: the name of the new object(must be the same as the name of the |
| 174 | * respective framebuffer device). | 170 | * respective framebuffer device). |
| 175 | * @devdata: an optional pointer to be stored in the class_device. The | 171 | * @devdata: an optional pointer to be stored in the device. The |
| 176 | * methods may retrieve it by using class_get_devdata(ld->class_dev). | 172 | * methods may retrieve it by using lcd_get_data(ld). |
| 177 | * @ops: the lcd operations structure. | 173 | * @ops: the lcd operations structure. |
| 178 | * | 174 | * |
| 179 | * Creates and registers a new lcd class_device. Returns either an ERR_PTR() | 175 | * Creates and registers a new lcd device. Returns either an ERR_PTR() |
| 180 | * or a pointer to the newly allocated device. | 176 | * or a pointer to the newly allocated device. |
| 181 | */ | 177 | */ |
| 182 | struct lcd_device *lcd_device_register(const char *name, void *devdata, | 178 | struct lcd_device *lcd_device_register(const char *name, struct device *parent, |
| 183 | struct lcd_ops *ops) | 179 | void *devdata, struct lcd_ops *ops) |
| 184 | { | 180 | { |
| 185 | int i, rc; | ||
| 186 | struct lcd_device *new_ld; | 181 | struct lcd_device *new_ld; |
| 182 | int rc; | ||
| 187 | 183 | ||
| 188 | pr_debug("lcd_device_register: name=%s\n", name); | 184 | pr_debug("lcd_device_register: name=%s\n", name); |
| 189 | 185 | ||
| @@ -193,12 +189,14 @@ struct lcd_device *lcd_device_register(const char *name, void *devdata, | |||
| 193 | 189 | ||
| 194 | mutex_init(&new_ld->ops_lock); | 190 | mutex_init(&new_ld->ops_lock); |
| 195 | mutex_init(&new_ld->update_lock); | 191 | mutex_init(&new_ld->update_lock); |
| 196 | new_ld->ops = ops; | ||
| 197 | new_ld->class_dev.class = &lcd_class; | ||
| 198 | strlcpy(new_ld->class_dev.class_id, name, KOBJ_NAME_LEN); | ||
| 199 | class_set_devdata(&new_ld->class_dev, devdata); | ||
| 200 | 192 | ||
| 201 | rc = class_device_register(&new_ld->class_dev); | 193 | new_ld->dev.class = lcd_class; |
| 194 | new_ld->dev.parent = parent; | ||
| 195 | new_ld->dev.release = lcd_device_release; | ||
| 196 | strlcpy(new_ld->dev.bus_id, name, BUS_ID_SIZE); | ||
| 197 | dev_set_drvdata(&new_ld->dev, devdata); | ||
| 198 | |||
| 199 | rc = device_register(&new_ld->dev); | ||
| 202 | if (rc) { | 200 | if (rc) { |
| 203 | kfree(new_ld); | 201 | kfree(new_ld); |
| 204 | return ERR_PTR(rc); | 202 | return ERR_PTR(rc); |
| @@ -206,22 +204,11 @@ struct lcd_device *lcd_device_register(const char *name, void *devdata, | |||
| 206 | 204 | ||
| 207 | rc = lcd_register_fb(new_ld); | 205 | rc = lcd_register_fb(new_ld); |
| 208 | if (rc) { | 206 | if (rc) { |
| 209 | class_device_unregister(&new_ld->class_dev); | 207 | device_unregister(&new_ld->dev); |
| 210 | return ERR_PTR(rc); | 208 | return ERR_PTR(rc); |
| 211 | } | 209 | } |
| 212 | 210 | ||
| 213 | for (i = 0; i < ARRAY_SIZE(lcd_class_device_attributes); i++) { | 211 | new_ld->ops = ops; |
| 214 | rc = class_device_create_file(&new_ld->class_dev, | ||
| 215 | &lcd_class_device_attributes[i]); | ||
| 216 | if (rc) { | ||
| 217 | while (--i >= 0) | ||
| 218 | class_device_remove_file(&new_ld->class_dev, | ||
| 219 | &lcd_class_device_attributes[i]); | ||
| 220 | class_device_unregister(&new_ld->class_dev); | ||
| 221 | /* No need to kfree(new_ld) since release() method was called */ | ||
| 222 | return ERR_PTR(rc); | ||
| 223 | } | ||
| 224 | } | ||
| 225 | 212 | ||
| 226 | return new_ld; | 213 | return new_ld; |
| 227 | } | 214 | } |
| @@ -235,33 +222,34 @@ EXPORT_SYMBOL(lcd_device_register); | |||
| 235 | */ | 222 | */ |
| 236 | void lcd_device_unregister(struct lcd_device *ld) | 223 | void lcd_device_unregister(struct lcd_device *ld) |
| 237 | { | 224 | { |
| 238 | int i; | ||
| 239 | |||
| 240 | if (!ld) | 225 | if (!ld) |
| 241 | return; | 226 | return; |
| 242 | 227 | ||
| 243 | pr_debug("lcd_device_unregister: name=%s\n", ld->class_dev.class_id); | ||
| 244 | |||
| 245 | for (i = 0; i < ARRAY_SIZE(lcd_class_device_attributes); i++) | ||
| 246 | class_device_remove_file(&ld->class_dev, | ||
| 247 | &lcd_class_device_attributes[i]); | ||
| 248 | |||
| 249 | mutex_lock(&ld->ops_lock); | 228 | mutex_lock(&ld->ops_lock); |
| 250 | ld->ops = NULL; | 229 | ld->ops = NULL; |
| 251 | mutex_unlock(&ld->ops_lock); | 230 | mutex_unlock(&ld->ops_lock); |
| 252 | lcd_unregister_fb(ld); | 231 | lcd_unregister_fb(ld); |
| 253 | class_device_unregister(&ld->class_dev); | 232 | |
| 233 | device_unregister(&ld->dev); | ||
| 254 | } | 234 | } |
| 255 | EXPORT_SYMBOL(lcd_device_unregister); | 235 | EXPORT_SYMBOL(lcd_device_unregister); |
| 256 | 236 | ||
| 257 | static void __exit lcd_class_exit(void) | 237 | static void __exit lcd_class_exit(void) |
| 258 | { | 238 | { |
| 259 | class_unregister(&lcd_class); | 239 | class_destroy(lcd_class); |
| 260 | } | 240 | } |
| 261 | 241 | ||
| 262 | static int __init lcd_class_init(void) | 242 | static int __init lcd_class_init(void) |
| 263 | { | 243 | { |
| 264 | return class_register(&lcd_class); | 244 | lcd_class = class_create(THIS_MODULE, "lcd"); |
| 245 | if (IS_ERR(lcd_class)) { | ||
| 246 | printk(KERN_WARNING "Unable to create backlight class; errno = %ld\n", | ||
| 247 | PTR_ERR(lcd_class)); | ||
| 248 | return PTR_ERR(lcd_class); | ||
| 249 | } | ||
| 250 | |||
| 251 | lcd_class->dev_attrs = lcd_device_attributes; | ||
| 252 | return 0; | ||
| 265 | } | 253 | } |
| 266 | 254 | ||
| 267 | /* | 255 | /* |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index f46fe95f69fb..d18b73aafa0d 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
| @@ -187,7 +187,11 @@ static void vgacon_scrollback_init(int pitch) | |||
| 187 | } | 187 | } |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | static void vgacon_scrollback_startup(void) | 190 | /* |
| 191 | * Called only duing init so call of alloc_bootmen is ok. | ||
| 192 | * Marked __init_refok to silence modpost. | ||
| 193 | */ | ||
| 194 | static void __init_refok vgacon_scrollback_startup(void) | ||
| 191 | { | 195 | { |
| 192 | vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE | 196 | vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE |
| 193 | * 1024); | 197 | * 1024); |
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c index 43f62d8ee41d..443e3c85a9a0 100644 --- a/drivers/video/nvidia/nv_backlight.c +++ b/drivers/video/nvidia/nv_backlight.c | |||
| @@ -50,7 +50,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par, | |||
| 50 | 50 | ||
| 51 | static int nvidia_bl_update_status(struct backlight_device *bd) | 51 | static int nvidia_bl_update_status(struct backlight_device *bd) |
| 52 | { | 52 | { |
| 53 | struct nvidia_par *par = class_get_devdata(&bd->class_dev); | 53 | struct nvidia_par *par = bl_get_data(bd); |
| 54 | u32 tmp_pcrt, tmp_pmc, fpcontrol; | 54 | u32 tmp_pcrt, tmp_pmc, fpcontrol; |
| 55 | int level; | 55 | int level; |
| 56 | 56 | ||
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 3972aa8cf859..646ec823c168 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
| @@ -1067,7 +1067,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
| 1067 | info->fix.smem_len = ps3fb_videomemory.size - offset; | 1067 | info->fix.smem_len = ps3fb_videomemory.size - offset; |
| 1068 | info->pseudo_palette = info->par; | 1068 | info->pseudo_palette = info->par; |
| 1069 | info->par = NULL; | 1069 | info->par = NULL; |
| 1070 | info->flags = FBINFO_FLAG_DEFAULT; | 1070 | info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST; |
| 1071 | 1071 | ||
| 1072 | retval = fb_alloc_cmap(&info->cmap, 256, 0); | 1072 | retval = fb_alloc_cmap(&info->cmap, 256, 0); |
| 1073 | if (retval < 0) | 1073 | if (retval < 0) |
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 0fe547842c64..5c47968e7f21 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c | |||
| @@ -307,7 +307,7 @@ static int riva_bl_get_level_brightness(struct riva_par *par, | |||
| 307 | 307 | ||
| 308 | static int riva_bl_update_status(struct backlight_device *bd) | 308 | static int riva_bl_update_status(struct backlight_device *bd) |
| 309 | { | 309 | { |
| 310 | struct riva_par *par = class_get_devdata(&bd->class_dev); | 310 | struct riva_par *par = bl_get_data(bd); |
| 311 | U032 tmp_pcrt, tmp_pmc; | 311 | U032 tmp_pcrt, tmp_pmc; |
| 312 | int level; | 312 | int level; |
| 313 | 313 | ||
| @@ -2146,7 +2146,7 @@ static void __devexit rivafb_remove(struct pci_dev *pd) | |||
| 2146 | * ------------------------------------------------------------------------- */ | 2146 | * ------------------------------------------------------------------------- */ |
| 2147 | 2147 | ||
| 2148 | #ifndef MODULE | 2148 | #ifndef MODULE |
| 2149 | static int __init rivafb_setup(char *options) | 2149 | static int __devinit rivafb_setup(char *options) |
| 2150 | { | 2150 | { |
| 2151 | char *this_opt; | 2151 | char *this_opt; |
| 2152 | 2152 | ||
