diff options
-rw-r--r-- | drivers/ata/libata-acpi.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index a276c06dda95..5ebbf16f3af1 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> |
@@ -95,6 +96,47 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap) | |||
95 | } | 96 | } |
96 | } | 97 | } |
97 | 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 | |||
98 | /** | 140 | /** |
99 | * ata_acpi_associate - associate ATA host with ACPI objects | 141 | * ata_acpi_associate - associate ATA host with ACPI objects |
100 | * @host: target ATA host | 142 | * @host: target ATA host |
@@ -110,7 +152,7 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap) | |||
110 | */ | 152 | */ |
111 | void ata_acpi_associate(struct ata_host *host) | 153 | void ata_acpi_associate(struct ata_host *host) |
112 | { | 154 | { |
113 | int i; | 155 | int i, j; |
114 | 156 | ||
115 | if (!is_pci_dev(host->dev) || libata_noacpi) | 157 | if (!is_pci_dev(host->dev) || libata_noacpi) |
116 | return; | 158 | return; |
@@ -126,6 +168,22 @@ void ata_acpi_associate(struct ata_host *host) | |||
126 | ata_acpi_associate_sata_port(ap); | 168 | ata_acpi_associate_sata_port(ap); |
127 | else | 169 | else |
128 | 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 | } | ||
129 | } | 187 | } |
130 | } | 188 | } |
131 | 189 | ||