|
Lines 118-125
Link Here
|
| 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_eject_device(acpi_handle handle) |
| 122 |
{ |
| 123 |
struct acpi_object_list arg_list; |
| 124 |
union acpi_object arg; |
| 125 |
|
| 126 |
arg_list.count = 1; |
| 127 |
arg_list.pointer = &arg; |
| 128 |
arg.type = ACPI_TYPE_INTEGER; |
| 129 |
arg.integer.value = 1; |
| 130 |
|
| 131 |
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0", |
| 132 |
&arg_list, NULL))) |
| 133 |
printk(KERN_ERR "Failed to evaluate _EJ0!\n"); |
| 134 |
} |
| 135 |
|
| 136 |
static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) |
| 137 |
{ |
| 138 |
if (dev) |
| 139 |
dev->flags |= ATA_DFLAG_DETACH; |
| 140 |
else { |
| 141 |
struct ata_link *tlink; |
| 142 |
struct ata_device *tdev; |
| 143 |
|
| 144 |
ata_port_for_each_link(tlink, ap) |
| 145 |
ata_link_for_each_dev(tdev, tlink) |
| 146 |
tdev->flags |= ATA_DFLAG_DETACH; |
| 147 |
} |
| 148 |
|
| 149 |
ata_port_freeze(ap); |
| 150 |
ata_port_schedule_eh(ap); |
| 151 |
} |
| 152 |
|
| 121 |
static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, |
153 |
static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, |
| 122 |
u32 event) |
154 |
u32 event, int is_dock_event) |
| 123 |
{ |
155 |
{ |
| 124 |
char event_string[12]; |
156 |
char event_string[12]; |
| 125 |
char *envp[] = { event_string, NULL }; |
157 |
char *envp[] = { event_string, NULL }; |
|
Lines 127-194
Link Here
|
| 127 |
struct kobject *kobj = NULL; |
159 |
struct kobject *kobj = NULL; |
| 128 |
int wait = 0; |
160 |
int wait = 0; |
| 129 |
unsigned long flags; |
161 |
unsigned long flags; |
|
|
162 |
acpi_handle handle, tmphandle; |
| 163 |
unsigned long sta; |
| 164 |
acpi_status status; |
| 130 |
|
165 |
|
| 131 |
if (!ap) |
166 |
if (!ap) |
| 132 |
ap = dev->link->ap; |
167 |
ap = dev->link->ap; |
| 133 |
ehi = &ap->link.eh_info; |
168 |
ehi = &ap->link.eh_info; |
| 134 |
|
169 |
|
|
|
170 |
if (dev) { |
| 171 |
if (dev->sdev) |
| 172 |
kobj = &dev->sdev->sdev_gendev.kobj; |
| 173 |
handle = dev->acpi_handle; |
| 174 |
} else { |
| 175 |
kobj = &ap->dev->kobj; |
| 176 |
handle = ap->acpi_handle; |
| 177 |
} |
| 178 |
|
| 179 |
status = acpi_get_handle(handle, "_EJ0", &tmphandle); |
| 180 |
if (ACPI_FAILURE(status)) |
| 181 |
/* This device does not support hotplug */ |
| 182 |
return; |
| 183 |
|
| 135 |
spin_lock_irqsave(ap->lock, flags); |
184 |
spin_lock_irqsave(ap->lock, flags); |
| 136 |
|
185 |
|
| 137 |
switch (event) { |
186 |
switch (event) { |
| 138 |
case ACPI_NOTIFY_BUS_CHECK: |
187 |
case ACPI_NOTIFY_BUS_CHECK: |
| 139 |
case ACPI_NOTIFY_DEVICE_CHECK: |
188 |
case ACPI_NOTIFY_DEVICE_CHECK: |
| 140 |
ata_ehi_push_desc(ehi, "ACPI event"); |
189 |
ata_ehi_push_desc(ehi, "ACPI event"); |
| 141 |
ata_ehi_hotplugged(ehi); |
|
|
| 142 |
ata_port_freeze(ap); |
| 143 |
break; |
| 144 |
|
190 |
|
|
|
191 |
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
| 192 |
if (ACPI_FAILURE(status)) { |
| 193 |
printk(KERN_ERR "Unable to determine bay status\n"); |
| 194 |
break; |
| 195 |
} |
| 196 |
|
| 197 |
if (sta) { |
| 198 |
ata_ehi_hotplugged(ehi); |
| 199 |
ata_port_freeze(ap); |
| 200 |
} else { |
| 201 |
/* The device has gone - unplug it */ |
| 202 |
ata_acpi_detach_device(ap, dev); |
| 203 |
wait = 1; |
| 204 |
} |
| 205 |
break; |
| 145 |
case ACPI_NOTIFY_EJECT_REQUEST: |
206 |
case ACPI_NOTIFY_EJECT_REQUEST: |
| 146 |
ata_ehi_push_desc(ehi, "ACPI event"); |
207 |
ata_ehi_push_desc(ehi, "ACPI event"); |
| 147 |
if (dev) |
|
|
| 148 |
dev->flags |= ATA_DFLAG_DETACH; |
| 149 |
else { |
| 150 |
struct ata_link *tlink; |
| 151 |
struct ata_device *tdev; |
| 152 |
|
| 153 |
ata_port_for_each_link(tlink, ap) |
| 154 |
ata_link_for_each_dev(tdev, tlink) |
| 155 |
tdev->flags |= ATA_DFLAG_DETACH; |
| 156 |
} |
| 157 |
|
208 |
|
| 158 |
ata_port_schedule_eh(ap); |
209 |
if (!is_dock_event) |
|
|
210 |
break; |
| 211 |
|
| 212 |
/* undock event - immediate unplug */ |
| 213 |
ata_acpi_detach_device(ap, dev); |
| 159 |
wait = 1; |
214 |
wait = 1; |
| 160 |
break; |
215 |
break; |
| 161 |
} |
216 |
} |
| 162 |
|
217 |
|
| 163 |
if (dev) { |
218 |
/* make sure kobj doesn't go away while ap->lock is released */ |
| 164 |
if (dev->sdev) |
219 |
kobject_get(kobj); |
| 165 |
kobj = &dev->sdev->sdev_gendev.kobj; |
|
|
| 166 |
} else |
| 167 |
kobj = &ap->dev->kobj; |
| 168 |
|
220 |
|
| 169 |
if (kobj) { |
221 |
spin_unlock_irqrestore(ap->lock, flags); |
|
|
222 |
|
| 223 |
if (kobj && !is_dock_event) { |
| 170 |
sprintf(event_string, "BAY_EVENT=%d", event); |
224 |
sprintf(event_string, "BAY_EVENT=%d", event); |
| 171 |
kobject_uevent_env(kobj, KOBJ_CHANGE, envp); |
225 |
kobject_uevent_env(kobj, KOBJ_CHANGE, envp); |
| 172 |
} |
226 |
} |
| 173 |
|
227 |
|
| 174 |
spin_unlock_irqrestore(ap->lock, flags); |
228 |
kobject_put(kobj); |
| 175 |
|
229 |
|
| 176 |
if (wait) |
230 |
if (wait) { |
| 177 |
ata_port_wait_eh(ap); |
231 |
ata_port_wait_eh(ap); |
|
|
232 |
ata_acpi_eject_device(handle); |
| 233 |
} |
| 234 |
} |
| 235 |
|
| 236 |
static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) |
| 237 |
{ |
| 238 |
struct ata_device *dev = data; |
| 239 |
|
| 240 |
ata_acpi_handle_hotplug(NULL, dev, event, 1); |
| 241 |
} |
| 242 |
|
| 243 |
static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data) |
| 244 |
{ |
| 245 |
struct ata_port *ap = data; |
| 246 |
|
| 247 |
ata_acpi_handle_hotplug(ap, NULL, event, 1); |
| 178 |
} |
248 |
} |
| 179 |
|
249 |
|
| 180 |
static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data) |
250 |
static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data) |
| 181 |
{ |
251 |
{ |
| 182 |
struct ata_device *dev = data; |
252 |
struct ata_device *dev = data; |
| 183 |
|
253 |
|
| 184 |
ata_acpi_handle_hotplug(NULL, dev, event); |
254 |
ata_acpi_handle_hotplug(NULL, dev, event, 0); |
| 185 |
} |
255 |
} |
| 186 |
|
256 |
|
| 187 |
static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data) |
257 |
static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data) |
| 188 |
{ |
258 |
{ |
| 189 |
struct ata_port *ap = data; |
259 |
struct ata_port *ap = data; |
| 190 |
|
260 |
|
| 191 |
ata_acpi_handle_hotplug(ap, NULL, event); |
261 |
ata_acpi_handle_hotplug(ap, NULL, event, 0); |
| 192 |
} |
262 |
} |
| 193 |
|
263 |
|
| 194 |
/** |
264 |
/** |
|
Lines 230-236
Link Here
|
| 230 |
#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) |
300 |
#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) |
| 231 |
/* we might be on a docking station */ |
301 |
/* we might be on a docking station */ |
| 232 |
register_hotplug_dock_device(ap->acpi_handle, |
302 |
register_hotplug_dock_device(ap->acpi_handle, |
| 233 |
ata_acpi_ap_notify, ap); |
303 |
ata_acpi_ap_notify_dock, ap); |
| 234 |
#endif |
304 |
#endif |
| 235 |
} |
305 |
} |
| 236 |
|
306 |
|
|
Lines 244-250
Link Here
|
| 244 |
#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) |
314 |
#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) |
| 245 |
/* we might be on a docking station */ |
315 |
/* we might be on a docking station */ |
| 246 |
register_hotplug_dock_device(dev->acpi_handle, |
316 |
register_hotplug_dock_device(dev->acpi_handle, |
| 247 |
ata_acpi_dev_notify, dev); |
317 |
ata_acpi_dev_notify_dock, dev); |
| 248 |
#endif |
318 |
#endif |
| 249 |
} |
319 |
} |
| 250 |
} |
320 |
} |