[PATCH] too late: updated version of the ACPI patches

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jeff,

argl. Appearently I'm in Yeltsin mode.

Anyway: I'm also have finished an updated version of the ACPI patches.
They are also based upon the patches by Randy Dunlap but with some improvements:

- Omit the namespace walk for SATA devices. We can really trust the ACPI layer to find out the correct device. If not the ACPI is buggered anyway and we shouldn't even try to continue. - Make the control over the ACPI execution more finegrained as some methods (most notably _GTF) are downright disastrous on PATA devices, whereas you really want to call _GTM / _STM on these to have them properly resumed after suspend to RAM.
- Only export the symbols we really have to :-)
- Proper integration with the new EH code. This is actually an error in the patch by Kristen; for new-style EH the ACPI functions will never be called :-(

If you consider this a duplicate I'm happy to rebase my patch on top of Kristens.

Comments etc are welcome.

Cheers,

Hannes
--
Dr. Hannes Reinecke			hare@xxxxxxx
SuSE Linux Products GmbH		S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de
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: <io>,<irq>,<nodeID>
 
+	ata_acpi=	[LIBATA] Disables use of ACPI in libata suspend/resume
+			when set.
+			Format: <int>
+
 	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 <asm/io.h>
 #include <linux/ata.h>
 #include <linux/workqueue.h>
 #include <scsi/scsi_host.h>
+#ifdef CONFIG_ATA_ACPI
+#include <acpi/acpi.h>
+#endif
 
 #include <asm/libata-portmap.h>
 
@@ -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 */

[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux