|
@@ -14,6 +14,7 @@
|
|
|
#include <linux/acpi.h>
|
|
|
#include <linux/libata.h>
|
|
|
#include <linux/pci.h>
|
|
|
+#include <scsi/scsi_device.h>
|
|
|
#include "libata.h"
|
|
|
|
|
|
#include <acpi/acpi_bus.h>
|
|
@@ -95,6 +96,47 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void ata_acpi_handle_hotplug (struct ata_port *ap, struct kobject *kobj,
|
|
|
+ u32 event)
|
|
|
+{
|
|
|
+ char event_string[12];
|
|
|
+ char *envp[] = { event_string, NULL };
|
|
|
+ struct ata_eh_info *ehi = &ap->link.eh_info;
|
|
|
+
|
|
|
+ if (event == 0 || event == 1) {
|
|
|
+ unsigned long flags;
|
|
|
+ spin_lock_irqsave(ap->lock, flags);
|
|
|
+ ata_ehi_clear_desc(ehi);
|
|
|
+ ata_ehi_push_desc(ehi, "ACPI event");
|
|
|
+ ata_ehi_hotplugged(ehi);
|
|
|
+ ata_port_freeze(ap);
|
|
|
+ spin_unlock_irqrestore(ap->lock, flags);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (kobj) {
|
|
|
+ sprintf(event_string, "BAY_EVENT=%d", event);
|
|
|
+ kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
|
|
|
+{
|
|
|
+ struct ata_device *dev = data;
|
|
|
+ struct kobject *kobj = NULL;
|
|
|
+
|
|
|
+ if (dev->sdev)
|
|
|
+ kobj = &dev->sdev->sdev_gendev.kobj;
|
|
|
+
|
|
|
+ ata_acpi_handle_hotplug (dev->link->ap, kobj, event);
|
|
|
+}
|
|
|
+
|
|
|
+static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
|
|
|
+{
|
|
|
+ struct ata_port *ap = data;
|
|
|
+
|
|
|
+ ata_acpi_handle_hotplug (ap, &ap->dev->kobj, event);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ata_acpi_associate - associate ATA host with ACPI objects
|
|
|
* @host: target ATA host
|
|
@@ -110,7 +152,7 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
|
|
|
*/
|
|
|
void ata_acpi_associate(struct ata_host *host)
|
|
|
{
|
|
|
- int i;
|
|
|
+ int i, j;
|
|
|
|
|
|
if (!is_pci_dev(host->dev) || libata_noacpi)
|
|
|
return;
|
|
@@ -126,6 +168,22 @@ void ata_acpi_associate(struct ata_host *host)
|
|
|
ata_acpi_associate_sata_port(ap);
|
|
|
else
|
|
|
ata_acpi_associate_ide_port(ap);
|
|
|
+
|
|
|
+ if (ap->acpi_handle)
|
|
|
+ acpi_install_notify_handler (ap->acpi_handle,
|
|
|
+ ACPI_SYSTEM_NOTIFY,
|
|
|
+ ata_acpi_ap_notify,
|
|
|
+ ap);
|
|
|
+
|
|
|
+ for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
|
|
|
+ struct ata_device *dev = &ap->link.device[j];
|
|
|
+
|
|
|
+ if (dev->acpi_handle)
|
|
|
+ acpi_install_notify_handler (dev->acpi_handle,
|
|
|
+ ACPI_SYSTEM_NOTIFY,
|
|
|
+ ata_acpi_dev_notify,
|
|
|
+ dev);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|