diff options
Diffstat (limited to 'drivers/ata/libata-acpi.c')
-rw-r--r-- | drivers/ata/libata-acpi.c | 77 |
1 files changed, 50 insertions, 27 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 70b77e0899a8..865a552c91e6 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -118,8 +118,8 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap) | |||
118 | ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; | 118 | ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; |
119 | } | 119 | } |
120 | 120 | ||
121 | static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, | 121 | static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device |
122 | u32 event) | 122 | *dev, u32 event) |
123 | { | 123 | { |
124 | char event_string[12]; | 124 | char event_string[12]; |
125 | char *envp[] = { event_string, NULL }; | 125 | char *envp[] = { event_string, NULL }; |
@@ -127,39 +127,67 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, | |||
127 | struct kobject *kobj = NULL; | 127 | struct kobject *kobj = NULL; |
128 | int wait = 0; | 128 | int wait = 0; |
129 | unsigned long flags; | 129 | unsigned long flags; |
130 | 130 | acpi_handle handle, tmphandle; | |
131 | unsigned long sta; | ||
132 | acpi_status status; | ||
133 | |||
131 | if (!ap) | 134 | if (!ap) |
132 | ap = dev->link->ap; | 135 | ap = dev->link->ap; |
133 | ehi = &ap->link.eh_info; | 136 | ehi = &ap->link.eh_info; |
134 | 137 | ||
135 | spin_lock_irqsave(ap->lock, flags); | 138 | spin_lock_irqsave(ap->lock, flags); |
136 | 139 | ||
140 | if (dev) | ||
141 | handle = dev->acpi_handle; | ||
142 | else | ||
143 | handle = ap->acpi_handle; | ||
144 | |||
145 | status = acpi_get_handle(handle, "_EJ0", &tmphandle); | ||
146 | if (ACPI_FAILURE(status)) { | ||
147 | /* This device is not ejectable */ | ||
148 | spin_unlock_irqrestore(ap->lock, flags); | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | ||
153 | if (ACPI_FAILURE(status)) { | ||
154 | printk ("Unable to determine bay status\n"); | ||
155 | spin_unlock_irqrestore(ap->lock, flags); | ||
156 | return; | ||
157 | } | ||
158 | |||
137 | switch (event) { | 159 | switch (event) { |
138 | case ACPI_NOTIFY_BUS_CHECK: | 160 | case ACPI_NOTIFY_BUS_CHECK: |
139 | case ACPI_NOTIFY_DEVICE_CHECK: | 161 | case ACPI_NOTIFY_DEVICE_CHECK: |
140 | ata_ehi_push_desc(ehi, "ACPI event"); | 162 | ata_ehi_push_desc(ehi, "ACPI event"); |
141 | ata_ehi_hotplugged(ehi); | 163 | if (!sta) { |
142 | ata_port_freeze(ap); | 164 | /* Device has been unplugged */ |
143 | break; | 165 | if (dev) |
144 | 166 | dev->flags |= ATA_DFLAG_DETACH; | |
145 | case ACPI_NOTIFY_EJECT_REQUEST: | 167 | else { |
146 | ata_ehi_push_desc(ehi, "ACPI event"); | 168 | struct ata_link *tlink; |
147 | if (dev) | 169 | struct ata_device *tdev; |
148 | dev->flags |= ATA_DFLAG_DETACH; | 170 | |
149 | else { | 171 | ata_port_for_each_link(tlink, ap) { |
150 | struct ata_link *tlink; | 172 | ata_link_for_each_dev(tdev, tlink) { |
151 | struct ata_device *tdev; | 173 | tdev->flags |= |
152 | 174 | ATA_DFLAG_DETACH; | |
153 | ata_port_for_each_link(tlink, ap) | 175 | } |
154 | ata_link_for_each_dev(tdev, tlink) | 176 | } |
155 | tdev->flags |= ATA_DFLAG_DETACH; | 177 | } |
178 | ata_port_schedule_eh(ap); | ||
179 | wait = 1; | ||
180 | } else { | ||
181 | ata_ehi_hotplugged(ehi); | ||
182 | ata_port_freeze(ap); | ||
156 | } | 183 | } |
157 | |||
158 | ata_port_schedule_eh(ap); | ||
159 | wait = 1; | ||
160 | break; | ||
161 | } | 184 | } |
162 | 185 | ||
186 | spin_unlock_irqrestore(ap->lock, flags); | ||
187 | |||
188 | if (wait) | ||
189 | ata_port_wait_eh(ap); | ||
190 | |||
163 | if (dev) { | 191 | if (dev) { |
164 | if (dev->sdev) | 192 | if (dev->sdev) |
165 | kobj = &dev->sdev->sdev_gendev.kobj; | 193 | kobj = &dev->sdev->sdev_gendev.kobj; |
@@ -170,11 +198,6 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, | |||
170 | sprintf(event_string, "BAY_EVENT=%d", event); | 198 | sprintf(event_string, "BAY_EVENT=%d", event); |
171 | kobject_uevent_env(kobj, KOBJ_CHANGE, envp); | 199 | kobject_uevent_env(kobj, KOBJ_CHANGE, envp); |
172 | } | 200 | } |
173 | |||
174 | spin_unlock_irqrestore(ap->lock, flags); | ||
175 | |||
176 | if (wait) | ||
177 | ata_port_wait_eh(ap); | ||
178 | } | 201 | } |
179 | 202 | ||
180 | static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data) | 203 | static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data) |