drivers/ata/libata-acpi.c

Source file repositories/reference/linux-study-clean/drivers/ata/libata-acpi.c

File Facts

System
Linux kernel
Corpus path
drivers/ata/libata-acpi.c
Extension
.c
Size
28108 bytes
Lines
1104
Domain
Driver Families
Bucket
drivers/ata
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ata_acpi_gtf {
	u8	tf[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
} __packed;

static void ata_acpi_clear_gtf(struct ata_device *dev)
{
	kfree(dev->gtf_cache);
	dev->gtf_cache = NULL;
}

struct ata_acpi_hotplug_context {
	struct acpi_hotplug_context hp;
	union {
		struct ata_port *ap;
		struct ata_device *dev;
	} data;
};

#define ata_hotplug_data(context) (container_of((context), struct ata_acpi_hotplug_context, hp)->data)

/**
 * ata_dev_acpi_handle - provide the acpi_handle for an ata_device
 * @dev: the acpi_handle returned will correspond to this device
 *
 * Returns the acpi_handle for the ACPI namespace object corresponding to
 * the ata_device passed into the function, or NULL if no such object exists
 * or ACPI is disabled for this device due to consecutive errors.
 */
acpi_handle ata_dev_acpi_handle(struct ata_device *dev)
{
	return dev->flags & ATA_DFLAG_ACPI_DISABLED ?
			NULL : ACPI_HANDLE(&dev->tdev);
}

/* @ap and @dev are the same as ata_acpi_handle_hotplug() */
static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
{
	if (dev)
		dev->flags |= ATA_DFLAG_DETACH;
	else {
		struct ata_link *tlink;
		struct ata_device *tdev;

		ata_for_each_link(tlink, ap, EDGE)
			ata_for_each_dev(tdev, tlink, ALL)
				tdev->flags |= ATA_DFLAG_DETACH;
	}

	ata_port_schedule_eh(ap);
}

/**
 * ata_acpi_handle_hotplug - ACPI event handler backend
 * @ap: ATA port ACPI event occurred
 * @dev: ATA device ACPI event occurred (can be NULL)
 * @event: ACPI event which occurred
 *
 * All ACPI bay / device related events end up in this function.  If
 * the event is port-wide @dev is NULL.  If the event is specific to a
 * device, @dev points to it.
 *
 * Hotplug (as opposed to unplug) notification is always handled as
 * port-wide while unplug only kills the target device on device-wide
 * event.
 *
 * LOCKING:
 * ACPI notify handler context.  May sleep.
 */
static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
				    u32 event)
{
	struct ata_eh_info *ehi = &ap->link.eh_info;
	int wait = 0;
	unsigned long flags;

	spin_lock_irqsave(ap->lock, flags);
	/*
	 * When dock driver calls into the routine, it will always use
	 * ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
	 * ACPI_NOTIFY_EJECT_REQUEST for remove
	 */
	switch (event) {
	case ACPI_NOTIFY_BUS_CHECK:
	case ACPI_NOTIFY_DEVICE_CHECK:
		ata_ehi_push_desc(ehi, "ACPI event");

		ata_ehi_hotplugged(ehi);
		ata_port_freeze(ap);
		break;
	case ACPI_NOTIFY_EJECT_REQUEST:

Annotation

Implementation Notes