diff options
Diffstat (limited to 'drivers/ata/libata-acpi.c')
-rw-r--r-- | drivers/ata/libata-acpi.c | 165 |
1 files changed, 147 insertions, 18 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index c059f78ad944..3f7533589041 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
15 | #include <linux/libata.h> | 15 | #include <linux/libata.h> |
16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
17 | #include <scsi/scsi_device.h> | ||
17 | #include "libata.h" | 18 | #include "libata.h" |
18 | 19 | ||
19 | #include <acpi/acpi_bus.h> | 20 | #include <acpi/acpi_bus.h> |
@@ -40,11 +41,40 @@ static int is_pci_dev(struct device *dev) | |||
40 | return (dev->bus == &pci_bus_type); | 41 | return (dev->bus == &pci_bus_type); |
41 | } | 42 | } |
42 | 43 | ||
43 | static void ata_acpi_associate_sata_port(struct ata_port *ap) | 44 | /** |
45 | * ata_acpi_associate_sata_port - associate SATA port with ACPI objects | ||
46 | * @ap: target SATA port | ||
47 | * | ||
48 | * Look up ACPI objects associated with @ap and initialize acpi_handle | ||
49 | * fields of @ap, the port and devices accordingly. | ||
50 | * | ||
51 | * LOCKING: | ||
52 | * EH context. | ||
53 | * | ||
54 | * RETURNS: | ||
55 | * 0 on success, -errno on failure. | ||
56 | */ | ||
57 | void ata_acpi_associate_sata_port(struct ata_port *ap) | ||
44 | { | 58 | { |
45 | acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT); | 59 | WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA)); |
60 | |||
61 | if (!ap->nr_pmp_links) { | ||
62 | acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT); | ||
63 | |||
64 | ap->link.device->acpi_handle = | ||
65 | acpi_get_child(ap->host->acpi_handle, adr); | ||
66 | } else { | ||
67 | struct ata_link *link; | ||
68 | |||
69 | ap->link.device->acpi_handle = NULL; | ||
46 | 70 | ||
47 | ap->device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr); | 71 | ata_port_for_each_link(link, ap) { |
72 | acpi_integer adr = SATA_ADR(ap->port_no, link->pmp); | ||
73 | |||
74 | link->device->acpi_handle = | ||
75 | acpi_get_child(ap->host->acpi_handle, adr); | ||
76 | } | ||
77 | } | ||
48 | } | 78 | } |
49 | 79 | ||
50 | static void ata_acpi_associate_ide_port(struct ata_port *ap) | 80 | static void ata_acpi_associate_ide_port(struct ata_port *ap) |
@@ -60,12 +90,53 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap) | |||
60 | max_devices++; | 90 | max_devices++; |
61 | 91 | ||
62 | for (i = 0; i < max_devices; i++) { | 92 | for (i = 0; i < max_devices; i++) { |
63 | struct ata_device *dev = &ap->device[i]; | 93 | struct ata_device *dev = &ap->link.device[i]; |
64 | 94 | ||
65 | dev->acpi_handle = acpi_get_child(ap->acpi_handle, i); | 95 | dev->acpi_handle = acpi_get_child(ap->acpi_handle, i); |
66 | } | 96 | } |
67 | } | 97 | } |
68 | 98 | ||
99 | static void ata_acpi_handle_hotplug (struct ata_port *ap, struct kobject *kobj, | ||
100 | u32 event) | ||
101 | { | ||
102 | char event_string[12]; | ||
103 | char *envp[] = { event_string, NULL }; | ||
104 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
105 | |||
106 | if (event == 0 || event == 1) { | ||
107 | unsigned long flags; | ||
108 | spin_lock_irqsave(ap->lock, flags); | ||
109 | ata_ehi_clear_desc(ehi); | ||
110 | ata_ehi_push_desc(ehi, "ACPI event"); | ||
111 | ata_ehi_hotplugged(ehi); | ||
112 | ata_port_freeze(ap); | ||
113 | spin_unlock_irqrestore(ap->lock, flags); | ||
114 | } | ||
115 | |||
116 | if (kobj) { | ||
117 | sprintf(event_string, "BAY_EVENT=%d", event); | ||
118 | kobject_uevent_env(kobj, KOBJ_CHANGE, envp); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data) | ||
123 | { | ||
124 | struct ata_device *dev = data; | ||
125 | struct kobject *kobj = NULL; | ||
126 | |||
127 | if (dev->sdev) | ||
128 | kobj = &dev->sdev->sdev_gendev.kobj; | ||
129 | |||
130 | ata_acpi_handle_hotplug (dev->link->ap, kobj, event); | ||
131 | } | ||
132 | |||
133 | static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data) | ||
134 | { | ||
135 | struct ata_port *ap = data; | ||
136 | |||
137 | ata_acpi_handle_hotplug (ap, &ap->dev->kobj, event); | ||
138 | } | ||
139 | |||
69 | /** | 140 | /** |
70 | * ata_acpi_associate - associate ATA host with ACPI objects | 141 | * ata_acpi_associate - associate ATA host with ACPI objects |
71 | * @host: target ATA host | 142 | * @host: target ATA host |
@@ -81,7 +152,7 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap) | |||
81 | */ | 152 | */ |
82 | void ata_acpi_associate(struct ata_host *host) | 153 | void ata_acpi_associate(struct ata_host *host) |
83 | { | 154 | { |
84 | int i; | 155 | int i, j; |
85 | 156 | ||
86 | if (!is_pci_dev(host->dev) || libata_noacpi) | 157 | if (!is_pci_dev(host->dev) || libata_noacpi) |
87 | return; | 158 | return; |
@@ -97,6 +168,22 @@ void ata_acpi_associate(struct ata_host *host) | |||
97 | ata_acpi_associate_sata_port(ap); | 168 | ata_acpi_associate_sata_port(ap); |
98 | else | 169 | else |
99 | ata_acpi_associate_ide_port(ap); | 170 | ata_acpi_associate_ide_port(ap); |
171 | |||
172 | if (ap->acpi_handle) | ||
173 | acpi_install_notify_handler (ap->acpi_handle, | ||
174 | ACPI_SYSTEM_NOTIFY, | ||
175 | ata_acpi_ap_notify, | ||
176 | ap); | ||
177 | |||
178 | for (j = 0; j < ata_link_max_devices(&ap->link); j++) { | ||
179 | struct ata_device *dev = &ap->link.device[j]; | ||
180 | |||
181 | if (dev->acpi_handle) | ||
182 | acpi_install_notify_handler (dev->acpi_handle, | ||
183 | ACPI_SYSTEM_NOTIFY, | ||
184 | ata_acpi_dev_notify, | ||
185 | dev); | ||
186 | } | ||
100 | } | 187 | } |
101 | } | 188 | } |
102 | 189 | ||
@@ -113,7 +200,7 @@ void ata_acpi_associate(struct ata_host *host) | |||
113 | * RETURNS: | 200 | * RETURNS: |
114 | * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure. | 201 | * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure. |
115 | */ | 202 | */ |
116 | static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm) | 203 | int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm) |
117 | { | 204 | { |
118 | struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER }; | 205 | struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER }; |
119 | union acpi_object *out_obj; | 206 | union acpi_object *out_obj; |
@@ -157,6 +244,8 @@ static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm) | |||
157 | return rc; | 244 | return rc; |
158 | } | 245 | } |
159 | 246 | ||
247 | EXPORT_SYMBOL_GPL(ata_acpi_gtm); | ||
248 | |||
160 | /** | 249 | /** |
161 | * ata_acpi_stm - execute _STM | 250 | * ata_acpi_stm - execute _STM |
162 | * @ap: target ATA port | 251 | * @ap: target ATA port |
@@ -170,7 +259,7 @@ static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm) | |||
170 | * RETURNS: | 259 | * RETURNS: |
171 | * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure. | 260 | * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure. |
172 | */ | 261 | */ |
173 | static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm) | 262 | int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm) |
174 | { | 263 | { |
175 | acpi_status status; | 264 | acpi_status status; |
176 | struct acpi_object_list input; | 265 | struct acpi_object_list input; |
@@ -182,10 +271,10 @@ static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm) | |||
182 | /* Buffers for id may need byteswapping ? */ | 271 | /* Buffers for id may need byteswapping ? */ |
183 | in_params[1].type = ACPI_TYPE_BUFFER; | 272 | in_params[1].type = ACPI_TYPE_BUFFER; |
184 | in_params[1].buffer.length = 512; | 273 | in_params[1].buffer.length = 512; |
185 | in_params[1].buffer.pointer = (u8 *)ap->device[0].id; | 274 | in_params[1].buffer.pointer = (u8 *)ap->link.device[0].id; |
186 | in_params[2].type = ACPI_TYPE_BUFFER; | 275 | in_params[2].type = ACPI_TYPE_BUFFER; |
187 | in_params[2].buffer.length = 512; | 276 | in_params[2].buffer.length = 512; |
188 | in_params[2].buffer.pointer = (u8 *)ap->device[1].id; | 277 | in_params[2].buffer.pointer = (u8 *)ap->link.device[1].id; |
189 | 278 | ||
190 | input.count = 3; | 279 | input.count = 3; |
191 | input.pointer = in_params; | 280 | input.pointer = in_params; |
@@ -202,6 +291,8 @@ static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm) | |||
202 | return 0; | 291 | return 0; |
203 | } | 292 | } |
204 | 293 | ||
294 | EXPORT_SYMBOL_GPL(ata_acpi_stm); | ||
295 | |||
205 | /** | 296 | /** |
206 | * ata_dev_get_GTF - get the drive bootup default taskfile settings | 297 | * ata_dev_get_GTF - get the drive bootup default taskfile settings |
207 | * @dev: target ATA device | 298 | * @dev: target ATA device |
@@ -226,7 +317,7 @@ static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm) | |||
226 | static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, | 317 | static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, |
227 | void **ptr_to_free) | 318 | void **ptr_to_free) |
228 | { | 319 | { |
229 | struct ata_port *ap = dev->ap; | 320 | struct ata_port *ap = dev->link->ap; |
230 | acpi_status status; | 321 | acpi_status status; |
231 | struct acpi_buffer output; | 322 | struct acpi_buffer output; |
232 | union acpi_object *out_obj; | 323 | union acpi_object *out_obj; |
@@ -296,6 +387,44 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, | |||
296 | } | 387 | } |
297 | 388 | ||
298 | /** | 389 | /** |
390 | * ata_acpi_cbl_80wire - Check for 80 wire cable | ||
391 | * @ap: Port to check | ||
392 | * | ||
393 | * Return 1 if the ACPI mode data for this port indicates the BIOS selected | ||
394 | * an 80wire mode. | ||
395 | */ | ||
396 | |||
397 | int ata_acpi_cbl_80wire(struct ata_port *ap) | ||
398 | { | ||
399 | struct ata_acpi_gtm gtm; | ||
400 | int valid = 0; | ||
401 | |||
402 | /* No _GTM data, no information */ | ||
403 | if (ata_acpi_gtm(ap, >m) < 0) | ||
404 | return 0; | ||
405 | |||
406 | /* Split timing, DMA enabled */ | ||
407 | if ((gtm.flags & 0x11) == 0x11 && gtm.drive[0].dma < 55) | ||
408 | valid |= 1; | ||
409 | if ((gtm.flags & 0x14) == 0x14 && gtm.drive[1].dma < 55) | ||
410 | valid |= 2; | ||
411 | /* Shared timing, DMA enabled */ | ||
412 | if ((gtm.flags & 0x11) == 0x01 && gtm.drive[0].dma < 55) | ||
413 | valid |= 1; | ||
414 | if ((gtm.flags & 0x14) == 0x04 && gtm.drive[0].dma < 55) | ||
415 | valid |= 2; | ||
416 | |||
417 | /* Drive check */ | ||
418 | if ((valid & 1) && ata_dev_enabled(&ap->link.device[0])) | ||
419 | return 1; | ||
420 | if ((valid & 2) && ata_dev_enabled(&ap->link.device[1])) | ||
421 | return 1; | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire); | ||
426 | |||
427 | /** | ||
299 | * taskfile_load_raw - send taskfile registers to host controller | 428 | * taskfile_load_raw - send taskfile registers to host controller |
300 | * @dev: target ATA device | 429 | * @dev: target ATA device |
301 | * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) | 430 | * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) |
@@ -320,7 +449,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, | |||
320 | static int taskfile_load_raw(struct ata_device *dev, | 449 | static int taskfile_load_raw(struct ata_device *dev, |
321 | const struct ata_acpi_gtf *gtf) | 450 | const struct ata_acpi_gtf *gtf) |
322 | { | 451 | { |
323 | struct ata_port *ap = dev->ap; | 452 | struct ata_port *ap = dev->link->ap; |
324 | struct ata_taskfile tf, rtf; | 453 | struct ata_taskfile tf, rtf; |
325 | unsigned int err_mask; | 454 | unsigned int err_mask; |
326 | 455 | ||
@@ -349,7 +478,7 @@ static int taskfile_load_raw(struct ata_device *dev, | |||
349 | tf.lbal, tf.lbam, tf.lbah, tf.device); | 478 | tf.lbal, tf.lbam, tf.lbah, tf.device); |
350 | 479 | ||
351 | rtf = tf; | 480 | rtf = tf; |
352 | err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0); | 481 | err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0, 0); |
353 | if (err_mask) { | 482 | if (err_mask) { |
354 | ata_dev_printk(dev, KERN_ERR, | 483 | ata_dev_printk(dev, KERN_ERR, |
355 | "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed " | 484 | "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed " |
@@ -424,7 +553,7 @@ static int ata_acpi_exec_tfs(struct ata_device *dev) | |||
424 | */ | 553 | */ |
425 | static int ata_acpi_push_id(struct ata_device *dev) | 554 | static int ata_acpi_push_id(struct ata_device *dev) |
426 | { | 555 | { |
427 | struct ata_port *ap = dev->ap; | 556 | struct ata_port *ap = dev->link->ap; |
428 | int err; | 557 | int err; |
429 | acpi_status status; | 558 | acpi_status status; |
430 | struct acpi_object_list input; | 559 | struct acpi_object_list input; |
@@ -508,7 +637,7 @@ int ata_acpi_on_suspend(struct ata_port *ap) | |||
508 | */ | 637 | */ |
509 | void ata_acpi_on_resume(struct ata_port *ap) | 638 | void ata_acpi_on_resume(struct ata_port *ap) |
510 | { | 639 | { |
511 | int i; | 640 | struct ata_device *dev; |
512 | 641 | ||
513 | if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) { | 642 | if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) { |
514 | BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA); | 643 | BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA); |
@@ -518,8 +647,8 @@ void ata_acpi_on_resume(struct ata_port *ap) | |||
518 | } | 647 | } |
519 | 648 | ||
520 | /* schedule _GTF */ | 649 | /* schedule _GTF */ |
521 | for (i = 0; i < ATA_MAX_DEVICES; i++) | 650 | ata_link_for_each_dev(dev, &ap->link) |
522 | ap->device[i].flags |= ATA_DFLAG_ACPI_PENDING; | 651 | dev->flags |= ATA_DFLAG_ACPI_PENDING; |
523 | } | 652 | } |
524 | 653 | ||
525 | /** | 654 | /** |
@@ -538,8 +667,8 @@ void ata_acpi_on_resume(struct ata_port *ap) | |||
538 | */ | 667 | */ |
539 | int ata_acpi_on_devcfg(struct ata_device *dev) | 668 | int ata_acpi_on_devcfg(struct ata_device *dev) |
540 | { | 669 | { |
541 | struct ata_port *ap = dev->ap; | 670 | struct ata_port *ap = dev->link->ap; |
542 | struct ata_eh_context *ehc = &ap->eh_context; | 671 | struct ata_eh_context *ehc = &ap->link.eh_context; |
543 | int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA; | 672 | int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA; |
544 | int rc; | 673 | int rc; |
545 | 674 | ||