Skip to contentSkip to conversation

Export ahci eSATA attribute

PATCH In review Phillip Susi 2 participants 8 messages Nov 11, 2010 – Jan 20, 2011 libata

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Export ahci eSATA attribute

Not subscribed, please CC.

Quoted 1 line

From 8b079f9f7111a21251df110db81bd2540ec73058 Mon Sep 17 00:00:00 2001

From: Phillip Susi <psusi@faldara.(none)>
Date: Wed, 10 Nov 2010 22:01:35 -0500
Subject: [PATCH] Export ahci eSATA attribute

The AHCI standard defines a port bit that indicates that port is an eSATA external port. Detect and export this bit as a sysfs attribute named ahci_port_external. It is intended that this information be used by udisks to auto mount external eSATA drives when they are hot plugged.

---
 drivers/ata/ahci.h     |    1 +
 drivers/ata/libahci.c  |   16 ++++++++++++++++
 include/linux/libata.h |    1 +
 3 files changed, 18 insertions(+), 0 deletions(-)
drivers/ata/ahci.h +1 -0
index 329cbbb..421c523 100644
@@ -172,6 +172,7 @@ enum {
 	PORT_CMD_ALPE		= (1 << 26), /* Aggressive Link PM enable */
 	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
 	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
+	PORT_CMD_ESP 		= (1 << 21), /* eSATA Port */
 	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
 	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
 	PORT_CMD_FIS_ON		= (1 << 14), /* FIS DMA engine running */
drivers/ata/libahci.c +16 -0
index ebc08d6..8e4a363 100644
@@ -107,6 +107,8 @@ static ssize_t ahci_show_host_version(struct device *dev,
 				      struct device_attribute *attr, char *buf);
 static ssize_t ahci_show_port_cmd(struct device *dev,
 				  struct device_attribute *attr, char *buf);
+static ssize_t ahci_show_port_external(struct device *dev,
+				  struct device_attribute *attr, char *buf);
 static ssize_t ahci_read_em_buffer(struct device *dev,
 				   struct device_attribute *attr, char *buf);
 static ssize_t ahci_store_em_buffer(struct device *dev,
@@ -117,6 +119,7 @@ static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
 static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
 static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
 static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
+static DEVICE_ATTR(ahci_port_external, S_IRUGO, ahci_show_port_external, NULL);
 static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
 		   ahci_read_em_buffer, ahci_store_em_buffer);
 
@@ -128,6 +131,7 @@ struct device_attribute *ahci_shost_attrs[] = {
 	&dev_attr_ahci_host_cap2,
 	&dev_attr_ahci_host_version,
 	&dev_attr_ahci_port_cmd,
+	&dev_attr_ahci_port_external,
 	&dev_attr_em_buffer,
 	NULL
 };
@@ -250,6 +254,15 @@ static ssize_t ahci_show_port_cmd(struct device *dev,
 	return sprintf(buf, "%x\n", readl(port_mmio + PORT_CMD));
 }
 
+static ssize_t ahci_show_port_external(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct ata_port *ap = ata_shost_to_port(shost);
+
+	return sprintf(buf, "%x\n", ap->flags & ATA_FLAG_EXTERN ? 1 : 0);
+}
+
 static ssize_t ahci_read_em_buffer(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
@@ -1079,6 +1092,9 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
 		writel(tmp, port_mmio + PORT_IRQ_STAT);
 
 	writel(1 << port_no, mmio + HOST_IRQ_STAT);
+	tmp = readl(port_mmio + PORT_CMD);
+	if (tmp & PORT_CMD_ESP)
+		ap->flags |= ATA_FLAG_EXTERN;
 }
 
 void ahci_init_controller(struct ata_host *host)
include/linux/libata.h +1 -0
index 15b77b8..1c5ffa7 100644
@@ -203,6 +203,7 @@ enum {
 					      * management */
 	ATA_FLAG_SW_ACTIVITY	= (1 << 22), /* driver supports sw activity
 					      * led */
+	ATA_FLAG_EXTERN		= (1 << 23), /* eSATA external port */
 
 	/* bits 24:31 of ap->flags are reserved for LLD specific flags */
 
Signature · 1 line
1.7.1
#1 lore raw

include/linux/libata.h enum { · line 208

Quoted 8 lines

+++ b/include/linux/libata.h

include/linux/libata.h +1 -0
@@ -203,6 +203,7 @@ enum {
 					      * management */
 	ATA_FLAG_SW_ACTIVITY	= (1 << 22), /* driver supports sw activity
 					      * led */
+	ATA_FLAG_EXTERN		= (1 << 23), /* eSATA external port */
 
 	/* bits 24:31 of ap->flags are reserved for LLD specific flags */

hmmm, I don't think we need a libata-wide flag just for an AHCI-specific attribute. Certainly eSATA exists elsewhere, but so far this is just for print-out purposes, and so, seems wasteful.

Jeff

#2 lore raw
Quoted 3 lines · Jeff Garzik

hmmm, I don't think we need a libata-wide flag just for an AHCI-specific attribute. Certainly eSATA exists elsewhere, but so far this is just for print-out purposes, and so, seems wasteful.

Good point, and I actually realized that the bit in question is already exposed via the ahci_port_cmd attribute, so never mind about the patch.
I just need to figure out how to get udev to look at that bit in that
attribute and flag the disk as external in the udevdb now.

#3 lore raw
In reply to Jeff Garzik

How about this one?

Quoted 1 line

From d5636730ab4fa52d64c7e530518bf25c68a590de Mon Sep 17 00:00:00 2001

From: Phillip Susi <psusi@faldara.(none)>
Date: Sat, 13 Nov 2010 00:20:53 -0500
Subject: [PATCH] [PATCH] Export ahci eSATA attribute

The AHCI standard defines a port bit that indicates that port is an eSATA external port. Detect and export this bit as a sysfs attribute named ahci_port_external. It is intended that this information be used by udisks to auto mount external eSATA drives when they are hot plugged.

---
 drivers/ata/ahci.h    |    1 +
 drivers/ata/libahci.c |   15 +++++++++++++++
 2 files changed, 16 insertions(+), 0 deletions(-)
drivers/ata/ahci.h +1 -0
index 329cbbb..421c523 100644
@@ -172,6 +172,7 @@ enum {
 	PORT_CMD_ALPE		= (1 << 26), /* Aggressive Link PM enable */
 	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
 	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
+	PORT_CMD_ESP 		= (1 << 21), /* eSATA Port */
 	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
 	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
 	PORT_CMD_FIS_ON		= (1 << 14), /* FIS DMA engine running */
drivers/ata/libahci.c +15 -0
index ebc08d6..c5b71ad 100644
@@ -43,6 +43,7 @@
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
 #include <linux/libata.h>
 #include "ahci.h"
 
@@ -107,6 +108,8 @@ static ssize_t ahci_show_host_version(struct device *dev,
 				      struct device_attribute *attr, char *buf);
 static ssize_t ahci_show_port_cmd(struct device *dev,
 				  struct device_attribute *attr, char *buf);
+static ssize_t ahci_show_port_external(struct device *dev,
+			  struct device_attribute *attr, char *buf);
 static ssize_t ahci_read_em_buffer(struct device *dev,
 				   struct device_attribute *attr, char *buf);
 static ssize_t ahci_store_em_buffer(struct device *dev,
@@ -117,6 +120,7 @@ static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
 static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
 static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
 static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
+static DEVICE_ATTR(ahci_port_external, S_IRUGO, ahci_show_port_external, NULL);
 static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
 		   ahci_read_em_buffer, ahci_store_em_buffer);
 
@@ -136,6 +140,7 @@ EXPORT_SYMBOL_GPL(ahci_shost_attrs);
 struct device_attribute *ahci_sdev_attrs[] = {
 	&dev_attr_sw_activity,
 	&dev_attr_unload_heads,
+	&dev_attr_ahci_port_external,
 	NULL
 };
 EXPORT_SYMBOL_GPL(ahci_sdev_attrs);
@@ -250,6 +255,16 @@ static ssize_t ahci_show_port_cmd(struct device *dev,
 	return sprintf(buf, "%x\n", readl(port_mmio + PORT_CMD));
 }
 
+static ssize_t ahci_show_port_external(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+	void __iomem *port_mmio = ahci_port_base(ap);
+
+	return sprintf(buf, "%x\n", readl(port_mmio + PORT_CMD) & PORT_CMD_ESP ? 1 : 0);
+}
+
 static ssize_t ahci_read_em_buffer(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
Signature · 1 line
1.7.1
#4 lore raw
Quoted 1 line · Phillip Susi

How about this one?

As you noted in your previous mail, the entire PORT_CMD is already exported as a attribute. I don't see much point in exporting this information a second time.

One way or another, userspace must handle AHCI-specific hardware details.

Jeff

#5 lore raw
Quoted 3 lines · Jeff Garzik

As you noted in your previous mail, the entire PORT_CMD is already exported as a attribute. I don't see much point in exporting this information a second time.

Unfortunately it is not exported in a way that udev can make use of it.
Firstly because udev can only compare on specific value matches rather
than an individual bit, and secondly because it is in the weird scsi_host device rather than the host device, so the attribute is not in an ancestor device of the disk device. Placing this attribute this way puts it in the ancestry of the disk device so it can be matched by a udev ATTRS rule.

#6 lore raw

I never got any comment back on this. In order for udev to use the existing attribute, it needs to be moved out of the scsi_host device, and udev needs patched to handle bitwise comparisons, or my simple patch adding the new attribute can be applied.

Are you certain you do not want to add a new attribute, and if so, would you accept a patch moving the existing one out of the scsi_host device so it will be a proper ancestor of the disk device?

Quoted 12 lines · Phillip Susi
Quoted 3 lines · Jeff Garzik

As you noted in your previous mail, the entire PORT_CMD is already exported as a attribute. I don't see much point in exporting this information a second time.

Unfortunately it is not exported in a way that udev can make use of it.
Firstly because udev can only compare on specific value matches rather
than an individual bit, and secondly because it is in the weird scsi_host device rather than the host device, so the attribute is not in an ancestor device of the disk device. Placing this attribute this way puts it in the ancestry of the disk device so it can be matched by a udev ATTRS rule.

#7 lore raw
In reply to Phillip Susi

I never got any comment back on this. In order for udev to use the existing attribute, it needs to be moved out of the scsi_host device, and udev needs patched to handle bitwise comparisons, or my simple patch adding the new attribute can be applied.

Are you certain you do not want to add a new attribute, and if so, would you accept a patch moving the existing one out of the scsi_host device so it will be a proper ancestor of the disk device? Kay Sievers thinks that the current location of scsi_host is broken should be fixed, but I think that involves significant changes to the scsi layer so I found that this patch was much simpler.

Quoted 12 lines · Phillip Susi
Quoted 3 lines · Jeff Garzik

As you noted in your previous mail, the entire PORT_CMD is already exported as a attribute. I don't see much point in exporting this information a second time.

Unfortunately it is not exported in a way that udev can make use of it.
Firstly because udev can only compare on specific value matches rather
than an individual bit, and secondly because it is in the weird scsi_host device rather than the host device, so the attribute is not in an ancestor device of the disk device. Placing this attribute this way puts it in the ancestry of the disk device so it can be matched by a udev ATTRS rule.