8000 libata-acpi: add back ACPI based hotplug functionality · codeguru85/linux@4452152 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4452152

Browse files
Aaron Lurafaeljw
authored andcommitted
libata-acpi: add back ACPI based hotplug functionality
Commit 30dcf76 "libata: migrate ACPI code over to new bindings" mistakenly dropped the code to register hotplug notificaion handler for ATA port/devices, causing regression for people using ATA bay, as kernel bug #59871 shows. Fix this by adding back the hotplug notification handler registration code. Since this code has to be run once and notification needs to be installed on every ATA port/devices handle no matter if there is actual device attached, we can't do this in binding time for ATA device ACPI handle, as the binding only occurs when a SCSI device is created, i.e. there is device attached. So introduce the ata_acpi_hotplug_init() function to loop scan all ATA ACPI handles and if it is available, install the notificaion handler for it during ATA init time. With the ATA ACPI handle binding to SCSI device tree, it is possible now that when the SCSI hotplug work removes the SCSI device, the ACPI unbind function will find that the corresponding ACPI device has already been deleted by dock driver, causing a scaring message like: [ 128.263966] scsi 4:0:0:0: Oops, 'acpi_handle' corrupt Fix this by waiting for SCSI hotplug task finish in our notificaion handler, so that the removal of ACPI device done in ACPI unbind function triggered by the removal of SCSI device is run earlier when ACPI device is still available. [rjw: Rebased] References: https://bugzilla.kernel.org/show_bug.cgi?id=59871 Reported-bisected-and-tested-by: Dirk Griesbach <spamthis@freenet.de> Signed-off-by: Aaron Lu <aaron.lu@intel.com> Acked-by: Tejun Heo <tj@kernel.org> Cc: 3.6+ <stable@vger.kernel.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 21a3101 commit 4452152

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

drivers/ata/libata-acpi.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,10 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
156156

157157
spin_unlock_irqrestore(ap->lock, flags);
158158

159-
if (wait)
159+
if (wait) {
160160
ata_port_wait_eh(ap);
161+
flush_work(&ap->hotplug_task.work);
162+
}
161163
}
162164

163165
static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
@@ -214,6 +216,39 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = {
214216
.uevent = ata_acpi_ap_uevent,
215217
};
216218

219+
void ata_acpi_hotplug_init(struct ata_host *host)
220+
{
221+
int i;
222+
223+
for (i = 0; i < host->n_ports; i++) {
224+
struct ata_port *ap = host->ports[i];
225+
acpi_handle handle;
226+
struct ata_device *dev;
227+
228+
if (!ap)
229+
continue;
230+
231+
handle = ata_ap_acpi_handle(ap);
232+
if (handle) {
233+
/* we might be on a docking station */
234+
register_hotplug_dock_device(handle,
235+
&ata_acpi_ap_dock_ops, ap,
236+
NULL, NULL);
237+
}
238+
239+
ata_for_each_dev(dev, &ap->link, ALL) {
240+
handle = ata_dev_acpi_handle(dev);
241+
if (!handle)
242+
continue;
243+
244+
/* we might be on a docking station */
245+
register_hotplug_dock_device(handle,
246+
&ata_acpi_dev_dock_ops,
247+
dev, NULL, NULL);
248+
}
249+
}
250+
}
251+
217252
/**
218253
* ata_acpi_dissociate - dissociate ATA host from ACPI objects
219254
* @host: target ATA host

drivers/ata/libata-core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6148,6 +6148,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
61486148
if (rc)
61496149
goto err_tadd;
61506150

6151+
ata_acpi_hotplug_init(host);
6152+
61516153
/* set cable, sata_spd_limit and report */
61526154
for (i = 0; i < host->n_ports; i++) {
61536155
struct ata_port *ap = host->ports[i];

drivers/ata/libata.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ extern int ata_acpi_register(void);
122122
extern void ata_acpi_unregister(void);
123123
extern void ata_acpi_bind(struct ata_device *dev);
124124
extern void ata_acpi_unbind(struct ata_device *dev);
125+
extern void ata_acpi_hotplug_init(struct ata_host *host);
125126
#else
126127
static inline void ata_acpi_dissociate(struct ata_host *host) { }
127128
static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
@@ -134,6 +135,7 @@ static inline int ata_acpi_register(void) { return 0; }
134135
static inline void ata_acpi_unregister(void) { }
135136
static inline void ata_acpi_bind(struct ata_device *dev) { }
136137
static inline void ata_acpi_unbind(struct ata_device *dev) { }
138+
static inline void ata_acpi_hotplug_init(struct ata_host *host) {}
137139
#endif
138140

139141
/* libata-scsi.c */

0 commit comments

Comments
 (0)
0