diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index b50595a..73e73ef 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -48,6 +48,7 @@ parameter is applicable: ISAPNP ISA PnP code is enabled. ISDN Appropriate ISDN support is enabled. JOY Appropriate joystick support is enabled. + LIBATA Libata driver is enabled. LP Printer support is enabled. LOOP Loopback device support is enabled. M68k M68k architecture is enabled. @@ -257,6 +258,10 @@ running once the system is up. arcrimi= [HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards Format: ,, + ata_acpi= [LIBATA] Disables use of ACPI in libata suspend/resume + when set. + Format: + ataflop= [HW,M68k] atarimouse= [HW,MOUSE] Atari Mouse diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 13027d5..4b90b2d 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -145,6 +145,19 @@ config SATA_INTEL_COMBINED depends on IDE=y && !BLK_DEV_IDE_SATA && (SATA_AHCI || ATA_PIIX) default y +config ATA_ACPI + bool "Handle ATA-related ACPI objects" + depends on ACPI && PCI + default y + help + This option adds support for ATA-related ACPI objects. + These ACPI objects add the ability to retrieve taskfiles + from the ACPI BIOS and write them to the disk controller. + These objects may be related to performance, security, + power management, or other areas. + You can disable this at kernel boot time by using the + option 'libata.ata_acpi=0'. + endif endmenu diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index e260e3f..875b5d9 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -18,4 +18,5 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_PDC_ADMA) += pdc_adma.o libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o +libata-$(CONFIG_ATA_ACPI) += libata-acpi.o diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 1c93154..c914e94 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -90,6 +90,12 @@ static int ata_probe_timeout = ATA_TMOUT module_param(ata_probe_timeout, int, 0444); MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)"); +#ifdef CONFIG_ATA_ACPI +int libata_acpi = 0x73; +module_param_named(ata_acpi, libata_acpi, int, 0444); +MODULE_PARM_DESC(ata_acpi, "Controls use of ACPI objects"); +#endif + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); @@ -1396,10 +1402,10 @@ int ata_dev_configure(struct ata_device if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x " - "85:%04x 86:%04x 87:%04x 88:%04x\n", + "85:%04x 86:%04x 87:%04x 88:%04x 93:%04x\n", __FUNCTION__, - id[49], id[82], id[83], id[84], - id[85], id[86], id[87], id[88]); + id[49], id[82], id[83], id[84], id[85], + id[86], id[87], id[88], id[93]); /* initialize to-be-configured parameters */ dev->flags &= ~ATA_DFLAG_CFG_MASK; @@ -1623,6 +1629,32 @@ int ata_bus_probe(struct ata_port *ap) goto fail; } +#ifdef CONFIG_ATA_ACPI + if (!(ap->flags & ATA_FLAG_SATA)) { + /* Call _GTM for PATA ports*/ + ata_acpi_get_timing(ap); + /* Call _STM for PATA ports + * required as _STM may modify _GTF information */ + ata_acpi_push_timing(ap); + } + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + if (!ata_dev_enabled(dev)) + continue; + + if (ata_id_is_sata(dev->id)) { + /* Send down drive data via _SDD */ + ata_acpi_push_id(dev); + } + + /* retrieve and execute the ATA task file of _GTF */ + ata_acpi_exec_tfs(dev); + + } +#endif + for (i = 0; i < ATA_MAX_DEVICES; i++) if (ata_dev_enabled(&ap->device[i])) return 0; @@ -2186,6 +2218,11 @@ int ata_set_mode(struct ata_port *ap, st break; } } +#ifdef CONFIG_ATA_ACPI + /* Call _GTM for PATA ports */ + if (!(ap->flags & ATA_FLAG_SATA)) + ata_acpi_get_timing(ap); +#endif return 0; } @@ -2265,6 +2302,11 @@ int ata_set_mode(struct ata_port *ap, st /* step5: chip specific finalisation */ if (ap->ops->post_set_mode) ap->ops->post_set_mode(ap); +#ifdef CONFIG_ATA_ACPI + /* step6: Call _GTM for PATA ports */ + if (!(ap->flags & ATA_FLAG_SATA)) + ata_acpi_get_timing(ap); +#endif out: if (rc) @@ -5476,6 +5518,7 @@ int ata_device_add(const struct ata_prob /* print per-port info to dmesg */ ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX " "ctl 0x%lX bmdma 0x%lX irq %d\n", + ap->flags & ATA_FLAG_PATA_MODE ? 'P' : ap->flags & ATA_FLAG_SATA ? 'S' : 'P', ata_mode_string(xfer_mode_mask), ap->ioaddr.cmd_addr, diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index b1b5104..93723c1 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1991,6 +1991,21 @@ static int ata_eh_recover(struct ata_por down_xfermask = 1; goto dev_fail; } + +#ifdef CONFIG_ATA_ACPI + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + if (!ata_dev_enabled(dev)) + continue; + + /* Send down drive data via _SDD */ + ata_acpi_push_id(dev); + + /* retrieve and execute the ATA task file of _GTF */ + ata_acpi_exec_tfs(dev); + } +#endif } /* suspend devices */ @@ -2215,6 +2230,12 @@ static void ata_eh_handle_port_resume(st if (!(ap->pflags & ATA_PFLAG_SUSPENDED)) goto done; +#ifdef CONFIG_ATA_ACPI + if (!(ap->flags & ATA_FLAG_SATA)) { + /* Call _STM for PATA ports */ + ata_acpi_push_timing(ap); + } +#endif if (ap->ops->port_resume) rc = ap->ops->port_resume(ap); diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 7605028..c8aee20 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -959,6 +959,10 @@ int ata_pci_init_one (struct pci_dev *pd if ((port[0]->flags & ATA_FLAG_NO_LEGACY) == 0 && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + printk(KERN_DEBUG "%s: NO_LEGACY == 0\n", __FUNCTION__); + port[0]->flags |= ATA_FLAG_PATA_MODE; + port[0]->flags &= ~ATA_FLAG_SATA; + /* TODO: What if one channel is in native mode ... */ pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); mask = (1 << 2) | (1 << 0); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index a5ecb71..0b826eb 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -43,6 +43,9 @@ extern struct workqueue_struct *ata_aux_ extern int atapi_enabled; extern int atapi_dmadir; extern int libata_fua; +#ifdef CONFIG_ATA_ACPI +extern int libata_acpi; +#endif extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern void ata_dev_disable(struct ata_device *dev); @@ -119,4 +122,12 @@ extern void ata_scsi_error(struct Scsi_H extern void ata_port_wait_eh(struct ata_port *ap); extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); +/* libata-acpi.c */ +#ifdef CONFIG_ATA_ACPI +extern int ata_acpi_push_id(struct ata_device *atadev); +extern int ata_acpi_exec_tfs(struct ata_device *atadev); +extern void ata_acpi_get_timing(struct ata_port *ap); +extern void ata_acpi_push_timing(struct ata_port *ap); +#endif + #endif /* __LIBATA_H__ */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 0ddf16c..d9104c1 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -35,6 +35,9 @@ #include #include #include #include +#ifdef CONFIG_ATA_ACPI +#include +#endif #include @@ -46,7 +49,7 @@ #undef ATA_DEBUG /* debugging output */ #undef ATA_VERBOSE_DEBUG /* yet more debugging output */ #undef ATA_IRQ_TRAP /* define to ack screaming irqs */ #undef ATA_NDEBUG /* define to disable quick runtime checks */ -#undef ATA_ENABLE_PATA /* define to enable PATA support in some +#define ATA_ENABLE_PATA /* define to enable PATA support in some * low-level drivers */ @@ -97,6 +100,25 @@ static inline u32 ata_msg_init(int dval, return (1 << dval) - 1; } +#ifdef CONFIG_ATA_ACPI +enum { + ATA_ACPI_SATA_MASK = 0xf0, + ATA_ACPI_SATA_SDD = 0x10, /* Execute _SDD method */ + ATA_ACPI_SATA_GTF = 0x20, /* Execute _GTF method */ + ATA_ACPI_SATA_TFX = 0x40, /* Execute tf registers received via _GTF */ + ATA_ACPI_PATA_MASK = 0x0f, + ATA_ACPI_PATA_GTM = 0x01, /* Execute _GTM & _STM method */ + ATA_ACPI_PATA_GTF = 0x02, /* Execute _GTF method */ + ATA_ACPI_PATA_TFX = 0x04, /* Execute tf registers received via _GTF */ + + ATA_ACPI_GTF = 0x02, /* Execute _GTF method */ + ATA_ACPI_TFX = 0x04, /* Execute tf registers received via _GTF */ +}; + +#define ata_acpi_flags(a,f) ata_id_is_sata((a)->id)?((f)>>4):(f) + +#endif + /* defines only for the constants which don't work well as enums */ #define ATA_TAG_POISON 0xfafbfcfdU @@ -162,6 +184,7 @@ enum { ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H * Register FIS clearing BSY */ ATA_FLAG_DEBUGMSG = (1 << 13), + ATA_FLAG_PATA_MODE = (1 << 14), /* port in PATA mode */ /* The following flag belongs to ap->pflags but is kept in * ap->flags because it's referenced in many LLDs and will be @@ -318,6 +341,7 @@ struct scsi_device; struct ata_port_operations; struct ata_port; struct ata_queued_cmd; +struct GTM_buffer; /* typedefs */ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); @@ -468,6 +492,11 @@ struct ata_device { /* error history */ struct ata_ering ering; + +#ifdef CONFIG_ATA_ACPI + /* ACPI objects info */ + acpi_handle obj_handle; +#endif }; /* Offset into struct ata_device. Fields above it are maintained @@ -554,6 +583,11 @@ struct ata_port { pm_message_t pm_mesg; int *pm_result; +#ifdef CONFIG_ATA_ACPI + struct GTM_buffer *gtm; + void *gtm_object_area; +#endif + void *private_data; u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */