All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch 1/3] libata: check for AN support
       [not found] <20070321004740.939006166@intel.com>
@ 2007-03-21  0:52 ` Kristen Carlson Accardi
  2007-03-21  0:52 ` [patch 2/3] libata: expose AN support to user space via sysfs Kristen Carlson Accardi
  2007-03-21  0:52 ` [patch 3/3] libata: handle AN interrupt Kristen Carlson Accardi
  2 siblings, 0 replies; 8+ messages in thread
From: Kristen Carlson Accardi @ 2007-03-21  0:52 UTC (permalink / raw)
  To: linux-ide; +Cc: jgarzik, Kristen Carlson Accardi

[-- Attachment #1: Type: text/plain, Size: 4199 bytes --]

Check to see if an ATAPI device supports Asynchronous Notification.
If so, enable it.

Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>

Index: 2.6-git/drivers/ata/libata-core.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-core.c	2007-03-21 00:37:11.000000000 -0700
+++ 2.6-git/drivers/ata/libata-core.c	2007-03-21 01:26:08.000000000 -0700
@@ -67,6 +67,7 @@
 static unsigned int ata_dev_init_params(struct ata_device *dev,
 					u16 heads, u16 sectors);
 static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
+static unsigned int ata_dev_set_an(struct ata_device *dev);
 static void ata_dev_xfermask(struct ata_device *dev);
 
 static unsigned int ata_unique_id = 1;
@@ -1739,6 +1740,23 @@
 		}
 		dev->cdb_len = (unsigned int) rc;
 
+		/*
+		 * check to see if this ATAPI device supports
+		 * Asynchronous Notification
+		 */
+		if (ata_id_has_an(id))
+		{
+			/* issue SET feature command to turn this on */
+			rc = ata_dev_set_an(dev);
+			if (rc) {
+				ata_dev_printk(dev, KERN_ERR,
+						"unable to set AN\n");
+				rc = -EINVAL;
+				goto err_out_nosup;
+			}
+			dev->flags |= ATA_DFLAG_AN;
+		}
+
 		if (ata_id_cdb_intr(dev->id)) {
 			dev->flags |= ATA_DFLAG_CDB_INTR;
 			cdb_intr_string = ", CDB intr";
@@ -3479,6 +3497,42 @@
 }
 
 /**
+ *	ata_dev_set_an - Issue SET FEATURES - SATA FEATURES
+ *                       with sector count set to indicate
+ *                       Asynchronous Notification feature
+ *	@dev: Device to which command will be sent
+ *
+ *	Issue SET FEATURES - SATA FEATURES command to device @dev
+ *	on port @ap.
+ *
+ *	LOCKING:
+ *	PCI/etc. bus probe sem.
+ *
+ *	RETURNS:
+ *	0 on success, AC_ERR_* mask otherwise.
+ */
+static unsigned int ata_dev_set_an(struct ata_device *dev)
+{
+	struct ata_taskfile tf;
+	unsigned int err_mask;
+
+	/* set up set-features taskfile */
+	DPRINTK("set features - SATA features\n");
+
+	ata_tf_init(dev, &tf);
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = SETFEATURES_SATA_ENABLE;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = SATA_AN;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
+
+	DPRINTK("EXIT, err_mask=%x\n", err_mask);
+	return err_mask;
+}
+
+/**
  *	ata_dev_init_params - Issue INIT DEV PARAMS command
  *	@dev: Device to which command will be sent
  *	@heads: Number of heads (taskfile parameter)
Index: 2.6-git/include/linux/ata.h
===================================================================
--- 2.6-git.orig/include/linux/ata.h	2007-03-21 00:37:16.000000000 -0700
+++ 2.6-git/include/linux/ata.h	2007-03-21 00:40:59.000000000 -0700
@@ -190,6 +190,12 @@
 	SETFEATURES_WC_ON	= 0x02, /* Enable write cache */
 	SETFEATURES_WC_OFF	= 0x82, /* Disable write cache */
 
+	SETFEATURES_SATA_ENABLE = 0x10, /* Enable use of SATA feature */
+	SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */
+
+	/* SETFEATURE Sector counts for SATA features */
+	SATA_AN			= 0x05,  /* Asynchronous Notification */
+
 	/* ATAPI stuff */
 	ATAPI_PKT_DMA		= (1 << 0),
 	ATAPI_DMADIR		= (1 << 2),	/* ATAPI data dir:
@@ -296,6 +302,8 @@
 #define ata_id_queue_depth(id)	(((id)[75] & 0x1f) + 1)
 #define ata_id_removeable(id)	((id)[0] & (1 << 7))
 #define ata_id_has_dword_io(id)	((id)[50] & (1 << 0))
+#define ata_id_has_an(id)	\
+	((id[76] && (~id[76])) & ((id)[78] & (1 << 5)))
 #define ata_id_u32(id,n)	\
 	(((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)]))
 #define ata_id_u64(id,n)	\
Index: 2.6-git/include/linux/libata.h
===================================================================
--- 2.6-git.orig/include/linux/libata.h	2007-03-21 00:37:17.000000000 -0700
+++ 2.6-git/include/linux/libata.h	2007-03-21 01:26:08.000000000 -0700
@@ -141,6 +141,7 @@
 	ATA_DFLAG_CDB_INTR	= (1 << 2), /* device asserts INTRQ when ready for CDB */
 	ATA_DFLAG_NCQ		= (1 << 3), /* device supports NCQ */
 	ATA_DFLAG_FLUSH_EXT	= (1 << 4), /* do FLUSH_EXT instead of FLUSH */
+	ATA_DFLAG_AN		= (1 << 5), /* device supports Async notification */
 	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
 
 	ATA_DFLAG_PIO		= (1 << 8), /* device limited to PIO mode */

-- 

[-- Attachment #2: libata-check-for-an --]
[-- Type: text/plain, Size: 4199 bytes --]

Check to see if an ATAPI device supports Asynchronous Notification.
If so, enable it.

Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>

Index: 2.6-git/drivers/ata/libata-core.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-core.c	2007-03-21 00:37:11.000000000 -0700
+++ 2.6-git/drivers/ata/libata-core.c	2007-03-21 01:26:08.000000000 -0700
@@ -67,6 +67,7 @@
 static unsigned int ata_dev_init_params(struct ata_device *dev,
 					u16 heads, u16 sectors);
 static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
+static unsigned int ata_dev_set_an(struct ata_device *dev);
 static void ata_dev_xfermask(struct ata_device *dev);
 
 static unsigned int ata_unique_id = 1;
@@ -1739,6 +1740,23 @@
 		}
 		dev->cdb_len = (unsigned int) rc;
 
+		/*
+		 * check to see if this ATAPI device supports
+		 * Asynchronous Notification
+		 */
+		if (ata_id_has_an(id))
+		{
+			/* issue SET feature command to turn this on */
+			rc = ata_dev_set_an(dev);
+			if (rc) {
+				ata_dev_printk(dev, KERN_ERR,
+						"unable to set AN\n");
+				rc = -EINVAL;
+				goto err_out_nosup;
+			}
+			dev->flags |= ATA_DFLAG_AN;
+		}
+
 		if (ata_id_cdb_intr(dev->id)) {
 			dev->flags |= ATA_DFLAG_CDB_INTR;
 			cdb_intr_string = ", CDB intr";
@@ -3479,6 +3497,42 @@
 }
 
 /**
+ *	ata_dev_set_an - Issue SET FEATURES - SATA FEATURES
+ *                       with sector count set to indicate
+ *                       Asynchronous Notification feature
+ *	@dev: Device to which command will be sent
+ *
+ *	Issue SET FEATURES - SATA FEATURES command to device @dev
+ *	on port @ap.
+ *
+ *	LOCKING:
+ *	PCI/etc. bus probe sem.
+ *
+ *	RETURNS:
+ *	0 on success, AC_ERR_* mask otherwise.
+ */
+static unsigned int ata_dev_set_an(struct ata_device *dev)
+{
+	struct ata_taskfile tf;
+	unsigned int err_mask;
+
+	/* set up set-features taskfile */
+	DPRINTK("set features - SATA features\n");
+
+	ata_tf_init(dev, &tf);
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = SETFEATURES_SATA_ENABLE;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = SATA_AN;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
+
+	DPRINTK("EXIT, err_mask=%x\n", err_mask);
+	return err_mask;
+}
+
+/**
  *	ata_dev_init_params - Issue INIT DEV PARAMS command
  *	@dev: Device to which command will be sent
  *	@heads: Number of heads (taskfile parameter)
Index: 2.6-git/include/linux/ata.h
===================================================================
--- 2.6-git.orig/include/linux/ata.h	2007-03-21 00:37:16.000000000 -0700
+++ 2.6-git/include/linux/ata.h	2007-03-21 00:40:59.000000000 -0700
@@ -190,6 +190,12 @@
 	SETFEATURES_WC_ON	= 0x02, /* Enable write cache */
 	SETFEATURES_WC_OFF	= 0x82, /* Disable write cache */
 
+	SETFEATURES_SATA_ENABLE = 0x10, /* Enable use of SATA feature */
+	SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */
+
+	/* SETFEATURE Sector counts for SATA features */
+	SATA_AN			= 0x05,  /* Asynchronous Notification */
+
 	/* ATAPI stuff */
 	ATAPI_PKT_DMA		= (1 << 0),
 	ATAPI_DMADIR		= (1 << 2),	/* ATAPI data dir:
@@ -296,6 +302,8 @@
 #define ata_id_queue_depth(id)	(((id)[75] & 0x1f) + 1)
 #define ata_id_removeable(id)	((id)[0] & (1 << 7))
 #define ata_id_has_dword_io(id)	((id)[50] & (1 << 0))
+#define ata_id_has_an(id)	\
+	((id[76] && (~id[76])) & ((id)[78] & (1 << 5)))
 #define ata_id_u32(id,n)	\
 	(((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)]))
 #define ata_id_u64(id,n)	\
Index: 2.6-git/include/linux/libata.h
===================================================================
--- 2.6-git.orig/include/linux/libata.h	2007-03-21 00:37:17.000000000 -0700
+++ 2.6-git/include/linux/libata.h	2007-03-21 01:26:08.000000000 -0700
@@ -141,6 +141,7 @@
 	ATA_DFLAG_CDB_INTR	= (1 << 2), /* device asserts INTRQ when ready for CDB */
 	ATA_DFLAG_NCQ		= (1 << 3), /* device supports NCQ */
 	ATA_DFLAG_FLUSH_EXT	= (1 << 4), /* do FLUSH_EXT instead of FLUSH */
+	ATA_DFLAG_AN		= (1 << 5), /* device supports Async notification */
 	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
 
 	ATA_DFLAG_PIO		= (1 << 8), /* device limited to PIO mode */

-- 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 2/3] libata: expose AN support to user space via sysfs
       [not found] <20070321004740.939006166@intel.com>
  2007-03-21  0:52 ` [patch 1/3] libata: check for AN support Kristen Carlson Accardi
@ 2007-03-21  0:52 ` Kristen Carlson Accardi
  2007-03-21  0:52 ` [patch 3/3] libata: handle AN interrupt Kristen Carlson Accardi
  2 siblings, 0 replies; 8+ messages in thread
From: Kristen Carlson Accardi @ 2007-03-21  0:52 UTC (permalink / raw)
  To: linux-ide; +Cc: jgarzik, Kristen Carlson Accardi

[-- Attachment #1: Type: text/plain, Size: 3662 bytes --]

Allow user space to determine if an ATAPI device supports
async notification (AN) of media changes.  This is done by
adding a new sysfs file "async_notification" to genhd.
If the file reads 1, then the device supports async 
notification.  If the file reads 0, it does not.  

A flag is set in the generic disk to indicate whether
or not AN is supported.  This flag is set by the SCSI
subsystem when it registers with add_disk.  The SCSI
system gets information from libata on whether the
device supports AN during dev_configure. 

Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>

Index: 2.6-git/block/genhd.c
===================================================================
--- 2.6-git.orig/block/genhd.c	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/block/genhd.c	2007-03-21 01:23:46.000000000 -0700
@@ -369,6 +369,11 @@
 {
 	return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk));
 }
+static ssize_t disk_an_read(struct gendisk * disk, char *page)
+{
+	return sprintf(page, "%d\n",
+		(disk->flags & GENHD_FL_ASYNC_NOTIFICATION ? 1 : 0));
+}
 
 static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
@@ -416,6 +421,10 @@
 	.attr = {.name = "stat", .mode = S_IRUGO },
 	.show	= disk_stats_read
 };
+static struct disk_attribute disk_attr_an = {
+	.attr = {.name = "async_notification", .mode = S_IRUGO },
+	.show	= disk_an_read
+};
 
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 
@@ -452,6 +461,7 @@
 	&disk_attr_removable.attr,
 	&disk_attr_size.attr,
 	&disk_attr_stat.attr,
+	&disk_attr_an.attr,
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 	&disk_attr_fail.attr,
 #endif
Index: 2.6-git/include/linux/genhd.h
===================================================================
--- 2.6-git.orig/include/linux/genhd.h	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/include/linux/genhd.h	2007-03-21 01:23:46.000000000 -0700
@@ -90,6 +90,7 @@
 
 #define GENHD_FL_REMOVABLE			1
 #define GENHD_FL_DRIVERFS			2
+#define GENHD_FL_ASYNC_NOTIFICATION		4
 #define GENHD_FL_CD				8
 #define GENHD_FL_UP				16
 #define GENHD_FL_SUPPRESS_PARTITION_INFO	32
Index: 2.6-git/include/scsi/scsi_device.h
===================================================================
--- 2.6-git.orig/include/scsi/scsi_device.h	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/include/scsi/scsi_device.h	2007-03-21 01:23:46.000000000 -0700
@@ -123,7 +123,7 @@
 	unsigned select_no_atn:1;
 	unsigned fix_capacity:1;	/* READ_CAPACITY is too high by 1 */
 	unsigned retry_hwerror:1;	/* Retry HARDWARE_ERROR */
-
+	unsigned async_notification:1;	/* device supports async notification */
 	unsigned int device_blocked;	/* Device returned QUEUE_FULL. */
 
 	unsigned int max_device_blocked; /* what device_blocked counts down from  */
Index: 2.6-git/drivers/ata/libata-scsi.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-scsi.c	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/drivers/ata/libata-scsi.c	2007-03-21 01:23:46.000000000 -0700
@@ -855,6 +855,9 @@
 		blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
 	}
 
+	if (dev->flags & ATA_DFLAG_AN)
+		sdev->async_notification = 1;
+
 	if (dev->flags & ATA_DFLAG_NCQ) {
 		int depth;
 
Index: 2.6-git/drivers/scsi/sr.c
===================================================================
--- 2.6-git.orig/drivers/scsi/sr.c	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/drivers/scsi/sr.c	2007-03-21 01:23:46.000000000 -0700
@@ -602,6 +602,8 @@
 
 	dev_set_drvdata(dev, cd);
 	disk->flags |= GENHD_FL_REMOVABLE;
+	if (sdev->async_notification)
+		disk->flags |= GENHD_FL_ASYNC_NOTIFICATION;
 	add_disk(disk);
 
 	sdev_printk(KERN_DEBUG, sdev,

-- 

[-- Attachment #2: libata-expose-an-to-users --]
[-- Type: text/plain, Size: 3662 bytes --]

Allow user space to determine if an ATAPI device supports
async notification (AN) of media changes.  This is done by
adding a new sysfs file "async_notification" to genhd.
If the file reads 1, then the device supports async 
notification.  If the file reads 0, it does not.  

A flag is set in the generic disk to indicate whether
or not AN is supported.  This flag is set by the SCSI
subsystem when it registers with add_disk.  The SCSI
system gets information from libata on whether the
device supports AN during dev_configure. 

Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>

Index: 2.6-git/block/genhd.c
===================================================================
--- 2.6-git.orig/block/genhd.c	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/block/genhd.c	2007-03-21 01:23:46.000000000 -0700
@@ -369,6 +369,11 @@
 {
 	return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk));
 }
+static ssize_t disk_an_read(struct gendisk * disk, char *page)
+{
+	return sprintf(page, "%d\n",
+		(disk->flags & GENHD_FL_ASYNC_NOTIFICATION ? 1 : 0));
+}
 
 static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
@@ -416,6 +421,10 @@
 	.attr = {.name = "stat", .mode = S_IRUGO },
 	.show	= disk_stats_read
 };
+static struct disk_attribute disk_attr_an = {
+	.attr = {.name = "async_notification", .mode = S_IRUGO },
+	.show	= disk_an_read
+};
 
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 
@@ -452,6 +461,7 @@
 	&disk_attr_removable.attr,
 	&disk_attr_size.attr,
 	&disk_attr_stat.attr,
+	&disk_attr_an.attr,
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 	&disk_attr_fail.attr,
 #endif
Index: 2.6-git/include/linux/genhd.h
===================================================================
--- 2.6-git.orig/include/linux/genhd.h	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/include/linux/genhd.h	2007-03-21 01:23:46.000000000 -0700
@@ -90,6 +90,7 @@
 
 #define GENHD_FL_REMOVABLE			1
 #define GENHD_FL_DRIVERFS			2
+#define GENHD_FL_ASYNC_NOTIFICATION		4
 #define GENHD_FL_CD				8
 #define GENHD_FL_UP				16
 #define GENHD_FL_SUPPRESS_PARTITION_INFO	32
Index: 2.6-git/include/scsi/scsi_device.h
===================================================================
--- 2.6-git.orig/include/scsi/scsi_device.h	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/include/scsi/scsi_device.h	2007-03-21 01:23:46.000000000 -0700
@@ -123,7 +123,7 @@
 	unsigned select_no_atn:1;
 	unsigned fix_capacity:1;	/* READ_CAPACITY is too high by 1 */
 	unsigned retry_hwerror:1;	/* Retry HARDWARE_ERROR */
-
+	unsigned async_notification:1;	/* device supports async notification */
 	unsigned int device_blocked;	/* Device returned QUEUE_FULL. */
 
 	unsigned int max_device_blocked; /* what device_blocked counts down from  */
Index: 2.6-git/drivers/ata/libata-scsi.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-scsi.c	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/drivers/ata/libata-scsi.c	2007-03-21 01:23:46.000000000 -0700
@@ -855,6 +855,9 @@
 		blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
 	}
 
+	if (dev->flags & ATA_DFLAG_AN)
+		sdev->async_notification = 1;
+
 	if (dev->flags & ATA_DFLAG_NCQ) {
 		int depth;
 
Index: 2.6-git/drivers/scsi/sr.c
===================================================================
--- 2.6-git.orig/drivers/scsi/sr.c	2007-03-21 01:22:04.000000000 -0700
+++ 2.6-git/drivers/scsi/sr.c	2007-03-21 01:23:46.000000000 -0700
@@ -602,6 +602,8 @@
 
 	dev_set_drvdata(dev, cd);
 	disk->flags |= GENHD_FL_REMOVABLE;
+	if (sdev->async_notification)
+		disk->flags |= GENHD_FL_ASYNC_NOTIFICATION;
 	add_disk(disk);
 
 	sdev_printk(KERN_DEBUG, sdev,

-- 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 3/3] libata: handle AN interrupt
       [not found] <20070321004740.939006166@intel.com>
  2007-03-21  0:52 ` [patch 1/3] libata: check for AN support Kristen Carlson Accardi
  2007-03-21  0:52 ` [patch 2/3] libata: expose AN support to user space via sysfs Kristen Carlson Accardi
@ 2007-03-21  0:52 ` Kristen Carlson Accardi
  2 siblings, 0 replies; 8+ messages in thread
From: Kristen Carlson Accardi @ 2007-03-21  0:52 UTC (permalink / raw)
  To: linux-ide; +Cc: jgarzik, Kristen Carlson Accardi

[-- Attachment #1: Type: text/plain, Size: 3324 bytes --]

When we get an SDB FIS with the 'N' bit set, we should send
an event to user space to indicate that there has been a
media change.  The ahci host controller will send the
event via KOBJ_CHANGE uevent.

Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-git/drivers/ata/ahci.c
===================================================================
--- 2.6-git.orig/drivers/ata/ahci.c	2007-03-21 01:25:24.000000000 -0700
+++ 2.6-git/drivers/ata/ahci.c	2007-03-21 01:25:43.000000000 -0700
@@ -1126,6 +1126,26 @@
 		return;
 	}
 
+	if (status & PORT_IRQ_SDB_FIS) {
+		/*
+		 * if this is an ATAPI device with AN turned on,
+		 * then we should interrogate the device to
+		 * determine the cause of the interrupt
+		 *
+		 * for AN - this we should check the SDB FIS
+		 * and find the I and N bits set
+		 */
+		const u32 *f = pp->rx_fis + RX_FIS_SDB;
+
+		/* check the 'N' bit in word 0 of the FIS */
+		if (f[0] & (1 << 15)) {
+			int port_addr =  ((f[0] & 0x00000f00) >> 8);
+			struct ata_device *adev = &ap->device[port_addr];
+			ata_port_printk(ap, KERN_INFO, "N bit set on SDB FIS!\n");
+			if (adev->flags & ATA_DFLAG_AN)
+				ata_async_notify(adev);
+		}
+	}
 	if (ap->sactive)
 		qc_active = readl(port_mmio + PORT_SCR_ACT);
 	else
Index: 2.6-git/include/linux/libata.h
===================================================================
--- 2.6-git.orig/include/linux/libata.h	2007-03-21 01:25:24.000000000 -0700
+++ 2.6-git/include/linux/libata.h	2007-03-21 01:25:43.000000000 -0700
@@ -504,6 +504,7 @@
 	/* error history */
 	struct ata_ering	ering;
 	unsigned int		horkage;	/* List of broken features */
+	struct work_struct	async_notify;
 };
 
 /* Offset into struct ata_device.  Fields above it are maintained
@@ -827,6 +828,7 @@
 extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
 				       int queue_depth);
 extern struct ata_device *ata_dev_pair(struct ata_device *adev);
+extern void ata_async_notify(struct ata_device *atadev);
 
 /*
  * Timing helpers
Index: 2.6-git/drivers/ata/libata-core.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-core.c	2007-03-21 01:25:24.000000000 -0700
+++ 2.6-git/drivers/ata/libata-core.c	2007-03-21 01:25:43.000000000 -0700
@@ -1589,6 +1589,26 @@
 	}
 }
 
+static void async_notify_thread(struct work_struct *work)
+{
+	struct ata_device *atadev =
+		container_of(work, struct ata_device, async_notify);
+
+	/*
+	 * TBD - who should send this event?  I couldn't find an
+	 * easy way to map an ata_device to a genhd device, so
+	 * decided maybe the ata host should send the event and
+	 * allow user space to figure out what happened?
+	 */
+	kobject_uevent(&atadev->ap->host->dev->kobj, KOBJ_CHANGE);
+}
+
+void ata_async_notify(struct ata_device *atadev)
+{
+	schedule_work(&atadev->async_notify);
+}
+
+
 /**
  *	ata_dev_configure - Configure the specified ATA/ATAPI device
  *	@dev: Target device to configure
@@ -1755,6 +1775,7 @@
 				goto err_out_nosup;
 			}
 			dev->flags |= ATA_DFLAG_AN;
+			INIT_WORK(&dev->async_notify, async_notify_thread);
 		}
 
 		if (ata_id_cdb_intr(dev->id)) {
@@ -6545,3 +6566,4 @@
 EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
 EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
 EXPORT_SYMBOL_GPL(ata_do_eh);
+EXPORT_SYMBOL_GPL(ata_async_notify);

-- 

[-- Attachment #2: libata-send-async-event-on-media-change --]
[-- Type: text/plain, Size: 3324 bytes --]

When we get an SDB FIS with the 'N' bit set, we should send
an event to user space to indicate that there has been a
media change.  The ahci host controller will send the
event via KOBJ_CHANGE uevent.

Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-git/drivers/ata/ahci.c
===================================================================
--- 2.6-git.orig/drivers/ata/ahci.c	2007-03-21 01:25:24.000000000 -0700
+++ 2.6-git/drivers/ata/ahci.c	2007-03-21 01:25:43.000000000 -0700
@@ -1126,6 +1126,26 @@
 		return;
 	}
 
+	if (status & PORT_IRQ_SDB_FIS) {
+		/*
+		 * if this is an ATAPI device with AN turned on,
+		 * then we should interrogate the device to
+		 * determine the cause of the interrupt
+		 *
+		 * for AN - this we should check the SDB FIS
+		 * and find the I and N bits set
+		 */
+		const u32 *f = pp->rx_fis + RX_FIS_SDB;
+
+		/* check the 'N' bit in word 0 of the FIS */
+		if (f[0] & (1 << 15)) {
+			int port_addr =  ((f[0] & 0x00000f00) >> 8);
+			struct ata_device *adev = &ap->device[port_addr];
+			ata_port_printk(ap, KERN_INFO, "N bit set on SDB FIS!\n");
+			if (adev->flags & ATA_DFLAG_AN)
+				ata_async_notify(adev);
+		}
+	}
 	if (ap->sactive)
 		qc_active = readl(port_mmio + PORT_SCR_ACT);
 	else
Index: 2.6-git/include/linux/libata.h
===================================================================
--- 2.6-git.orig/include/linux/libata.h	2007-03-21 01:25:24.000000000 -0700
+++ 2.6-git/include/linux/libata.h	2007-03-21 01:25:43.000000000 -0700
@@ -504,6 +504,7 @@
 	/* error history */
 	struct ata_ering	ering;
 	unsigned int		horkage;	/* List of broken features */
+	struct work_struct	async_notify;
 };
 
 /* Offset into struct ata_device.  Fields above it are maintained
@@ -827,6 +828,7 @@
 extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
 				       int queue_depth);
 extern struct ata_device *ata_dev_pair(struct ata_device *adev);
+extern void ata_async_notify(struct ata_device *atadev);
 
 /*
  * Timing helpers
Index: 2.6-git/drivers/ata/libata-core.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-core.c	2007-03-21 01:25:24.000000000 -0700
+++ 2.6-git/drivers/ata/libata-core.c	2007-03-21 01:25:43.000000000 -0700
@@ -1589,6 +1589,26 @@
 	}
 }
 
+static void async_notify_thread(struct work_struct *work)
+{
+	struct ata_device *atadev =
+		container_of(work, struct ata_device, async_notify);
+
+	/*
+	 * TBD - who should send this event?  I couldn't find an
+	 * easy way to map an ata_device to a genhd device, so
+	 * decided maybe the ata host should send the event and
+	 * allow user space to figure out what happened?
+	 */
+	kobject_uevent(&atadev->ap->host->dev->kobj, KOBJ_CHANGE);
+}
+
+void ata_async_notify(struct ata_device *atadev)
+{
+	schedule_work(&atadev->async_notify);
+}
+
+
 /**
  *	ata_dev_configure - Configure the specified ATA/ATAPI device
  *	@dev: Target device to configure
@@ -1755,6 +1775,7 @@
 				goto err_out_nosup;
 			}
 			dev->flags |= ATA_DFLAG_AN;
+			INIT_WORK(&dev->async_notify, async_notify_thread);
 		}
 
 		if (ata_id_cdb_intr(dev->id)) {
@@ -6545,3 +6566,4 @@
 EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
 EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
 EXPORT_SYMBOL_GPL(ata_do_eh);
+EXPORT_SYMBOL_GPL(ata_async_notify);

-- 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 3/3] libata: handle AN interrupt
  2007-03-29 12:43 ` Jeff Garzik
@ 2007-03-29 13:04   ` James Smart
  0 siblings, 0 replies; 8+ messages in thread
From: James Smart @ 2007-03-29 13:04 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Kristen Carlson Accardi, linux-kernel, akpm, linux-ide, linux-scsi



Jeff Garzik wrote:
> Fair enough, though I definitely lean towards some use of sysfs / device 
> model for AN-style events specifically.  The media change events are 
> generated by the device, not the transport, and we should definitely 
> have an object in the device model that represents the device (if we 
> don't already).
> 
> I could see transport-based events being delivered to a different 
> endpoint, because transport events differ from device events.
> 
>     Jeff

Sure... although what object the event relates to is really a component of
either the socket (1 per object) or an object identifier within the event
message (1 socket with message headers). The transport, as we use it, really
isn't the object and isn't the one generating the events, it's just a well-known
listening point and serves as a nice library to insulate drivers from the
implementation.

Granted, what's being proposed now is fairly simple, so sysfs works fine.
But if you grow at all, you'll be confronted with the multiple-readers
and payload issues that we had.

-- james

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 3/3] libata: handle AN interrupt
  2007-03-29 12:38 James Smart
@ 2007-03-29 12:43 ` Jeff Garzik
  2007-03-29 13:04   ` James Smart
  0 siblings, 1 reply; 8+ messages in thread
From: Jeff Garzik @ 2007-03-29 12:43 UTC (permalink / raw)
  To: James.Smart
  Cc: Kristen Carlson Accardi, linux-kernel, akpm, linux-ide, linux-scsi

James Smart wrote:
> For FC, we have several async events, and allow for LLDDs to send their own
> data or augment the generic transport event w/ additional LLDD-data. The
> infrastructure is implemented generically within the scsi midlayer.
> We are using Netlink w/ broadcasts to deliver the events rather than 
> kobject_uevent().
> We considered using a variant of kobject events, but the general 
> consensus was
> we didn't want to wrap transport events into the kobject infrastructure, 
> and using
> netlink natively allowed for transport data to be sent with the event. 
> Additionally,
> with the broadcast, we could support any number of tools concurrently 
> listening for
> change events. To date, this has worked very well. You may want to 
> consider this,
> especially if the types of events is expected to grow beyond the simple 
> "change"
> notification.


Fair enough, though I definitely lean towards some use of sysfs / device 
model for AN-style events specifically.  The media change events are 
generated by the device, not the transport, and we should definitely 
have an object in the device model that represents the device (if we 
don't already).

I could see transport-based events being delivered to a different 
endpoint, because transport events differ from device events.

	Jeff



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 3/3] libata: handle AN interrupt
@ 2007-03-29 12:38 James Smart
  2007-03-29 12:43 ` Jeff Garzik
  0 siblings, 1 reply; 8+ messages in thread
From: James Smart @ 2007-03-29 12:38 UTC (permalink / raw)
  To: Kristen Carlson Accardi; +Cc: linux-kernel, akpm, linux-ide, linux-scsi

fyi...

For FC, we have several async events, and allow for LLDDs to send their own
data or augment the generic transport event w/ additional LLDD-data. The
infrastructure is implemented generically within the scsi midlayer.
We are using Netlink w/ broadcasts to deliver the events rather than kobject_uevent().
We considered using a variant of kobject events, but the general consensus was
we didn't want to wrap transport events into the kobject infrastructure, and using
netlink natively allowed for transport data to be sent with the event. Additionally,
with the broadcast, we could support any number of tools concurrently listening for
change events. To date, this has worked very well. You may want to consider this,
especially if the types of events is expected to grow beyond the simple "change"
notification.

-- james s



 >List:       linux-kernel
 >Subject:    [patch 3/3] libata: handle AN interrupt
 >From:       Kristen Carlson Accardi <kristen.c.accardi () intel ! com>
 >Date:       2007-03-28 23:44:57
 >Message-ID: 20070328164457.a675a7d2.kristen.c.accardi () intel ! com
 >[Download message RAW]
 >
 >When we get an SDB FIS with the 'N' bit set, we should send
 >an event to user space to indicate that there has been a
 >media change.  The ahci host controller will send the
 >event via KOBJ_CHANGE uevent.
 >
 >Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
 >Index: 2.6-mm/drivers/ata/ahci.c
 >===================================================================
 >--- 2.6-mm.orig/drivers/ata/ahci.c
 >+++ 2.6-mm/drivers/ata/ahci.c
 >@@ -1164,6 +1164,26 @@ static void ahci_host_intr(struct ata_po
 > 		return;
 > 	}
 >
 >+	if (status & PORT_IRQ_SDB_FIS) {
 >+		/*
 >+		 * if this is an ATAPI device with AN turned on,
 >+		 * then we should interrogate the device to
 >+		 * determine the cause of the interrupt
 >+		 *
 >+		 * for AN - this we should check the SDB FIS
 >+		 * and find the I and N bits set
 >+		 */
 >+		const u32 *f = pp->rx_fis + RX_FIS_SDB;
 >+
 >+		/* check the 'N' bit in word 0 of the FIS */
 >+		if (f[0] & (1 << 15)) {
 >+			int port_addr =  ((f[0] & 0x00000f00) >> 8);
 >+			struct ata_device *adev = &ap->device[port_addr];
 >+			ata_port_printk(ap, KERN_INFO, "N bit set on SDB FIS!\n");
 >+			if (adev->flags & ATA_DFLAG_AN)
 >+				ata_async_notify(adev);
 >+		}
 >+	}
 > 	if (ap->sactive)
 > 		qc_active = readl(port_mmio + PORT_SCR_ACT);
 > 	else
 >Index: 2.6-mm/include/linux/libata.h
 >===================================================================
 >--- 2.6-mm.orig/include/linux/libata.h
 >+++ 2.6-mm/include/linux/libata.h
 >@@ -492,6 +492,7 @@ struct ata_device {
 > 	/* ACPI objects info */
 > 	acpi_handle obj_handle;
 > #endif
 >+	struct work_struct	async_notify;
 > };
 >
 > /* Offset into struct ata_device.  Fields above it are maintained
 >@@ -826,6 +827,7 @@ extern void ata_scsi_slave_destroy(struc
 > extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
 > 				       int queue_depth);
 > extern struct ata_device *ata_dev_pair(struct ata_device *adev);
 >+extern void ata_async_notify(struct ata_device *atadev);
 > extern int ata_do_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
 > extern u8 ata_irq_on(struct ata_port *ap);
 > extern u8 ata_dummy_irq_on(struct ata_port *ap);
 >Index: 2.6-mm/drivers/ata/libata-core.c
 >===================================================================
 >--- 2.6-mm.orig/drivers/ata/libata-core.c
 >+++ 2.6-mm/drivers/ata/libata-core.c
 >@@ -1576,6 +1576,26 @@ static void ata_dev_config_ncq(struct at
 > 		snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
 > }
 >
 >+static void async_notify_thread(struct work_struct *work)
 >+{
 >+	struct ata_device *atadev =
 >+		container_of(work, struct ata_device, async_notify);
 >+
 >+	/*
 >+	 * TBD - who should send this event?  I couldn't find an
 >+	 * easy way to map an ata_device to a genhd device, so
 >+	 * decided maybe the ata host should send the event and
 >+	 * allow user space to figure out what happened?
 >+	 */
 >+	kobject_uevent(&atadev->ap->host->dev->kobj, KOBJ_CHANGE);
 >+}
 >+
 >+void ata_async_notify(struct ata_device *atadev)
 >+{
 >+	schedule_work(&atadev->async_notify);
 >+}
 >+
 >+
 > /**
 >  *	ata_dev_configure - Configure the specified ATA/ATAPI device
 >  *	@dev: Target device to configure
 >@@ -1761,6 +1781,7 @@ int ata_dev_configure(struct ata_device
 > 				goto err_out_nosup;
 > 			}
 > 			dev->flags |= ATA_DFLAG_AN;
 >+			INIT_WORK(&dev->async_notify, async_notify_thread);
 > 		}
 >
 > 		if (ata_id_cdb_intr(dev->id)) {
 >@@ -6650,6 +6671,7 @@ EXPORT_SYMBOL_GPL(ata_dummy_irq_on);
 > EXPORT_SYMBOL_GPL(ata_irq_ack);
 > EXPORT_SYMBOL_GPL(ata_dummy_irq_ack);
 > EXPORT_SYMBOL_GPL(ata_dev_try_classify);
 >+EXPORT_SYMBOL_GPL(ata_async_notify);
 >
 > EXPORT_SYMBOL_GPL(ata_cable_40wire);
 > EXPORT_SYMBOL_GPL(ata_cable_80wire);
 >
-- 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 3/3] libata: handle AN interrupt
  2007-03-28 23:44 ` Kristen Carlson Accardi
@ 2007-03-29  2:13   ` Tejun Heo
  0 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2007-03-29  2:13 UTC (permalink / raw)
  To: Kristen Carlson Accardi; +Cc: linux-kernel, akpm, linux-ide, jgarzik

Kristen Carlson Accardi wrote:
> When we get an SDB FIS with the 'N' bit set, we should send
> an event to user space to indicate that there has been a
> media change.  The ahci host controller will send the
> event via KOBJ_CHANGE uevent.
> 
> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
>  
> +static void async_notify_thread(struct work_struct *work)
> +{
> +	struct ata_device *atadev =
> +		container_of(work, struct ata_device, async_notify);
> +
> +	/*
> +	 * TBD - who should send this event?  I couldn't find an
> +	 * easy way to map an ata_device to a genhd device, so
> +	 * decided maybe the ata host should send the event and
> +	 * allow user space to figure out what happened?
> +	 */
> +	kobject_uevent(&atadev->ap->host->dev->kobj, KOBJ_CHANGE);
> +}

I don't think this is right.  If you're gonna make media_change_event 
capability generic, you gotta make event delivery generic too.  You can 
make it a genhd event and make genhd supply the interface function, say, 
genhd_notify_media_change() which is then forwarded by SCSI layer.

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 3/3] libata: handle AN interrupt
       [not found] <20070328230108.597741522@intel.com>
@ 2007-03-28 23:44 ` Kristen Carlson Accardi
  2007-03-29  2:13   ` Tejun Heo
  0 siblings, 1 reply; 8+ messages in thread
From: Kristen Carlson Accardi @ 2007-03-28 23:44 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, linux-ide, jgarzik, Kristen Carlson Accardi

When we get an SDB FIS with the 'N' bit set, we should send
an event to user space to indicate that there has been a
media change.  The ahci host controller will send the
event via KOBJ_CHANGE uevent.

Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Index: 2.6-mm/drivers/ata/ahci.c
===================================================================
--- 2.6-mm.orig/drivers/ata/ahci.c
+++ 2.6-mm/drivers/ata/ahci.c
@@ -1164,6 +1164,26 @@ static void ahci_host_intr(struct ata_po
 		return;
 	}
 
+	if (status & PORT_IRQ_SDB_FIS) {
+		/*
+		 * if this is an ATAPI device with AN turned on,
+		 * then we should interrogate the device to
+		 * determine the cause of the interrupt
+		 *
+		 * for AN - this we should check the SDB FIS
+		 * and find the I and N bits set
+		 */
+		const u32 *f = pp->rx_fis + RX_FIS_SDB;
+
+		/* check the 'N' bit in word 0 of the FIS */
+		if (f[0] & (1 << 15)) {
+			int port_addr =  ((f[0] & 0x00000f00) >> 8);
+			struct ata_device *adev = &ap->device[port_addr];
+			ata_port_printk(ap, KERN_INFO, "N bit set on SDB FIS!\n");
+			if (adev->flags & ATA_DFLAG_AN)
+				ata_async_notify(adev);
+		}
+	}
 	if (ap->sactive)
 		qc_active = readl(port_mmio + PORT_SCR_ACT);
 	else
Index: 2.6-mm/include/linux/libata.h
===================================================================
--- 2.6-mm.orig/include/linux/libata.h
+++ 2.6-mm/include/linux/libata.h
@@ -492,6 +492,7 @@ struct ata_device {
 	/* ACPI objects info */
 	acpi_handle obj_handle;
 #endif
+	struct work_struct	async_notify;
 };
 
 /* Offset into struct ata_device.  Fields above it are maintained
@@ -826,6 +827,7 @@ extern void ata_scsi_slave_destroy(struc
 extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
 				       int queue_depth);
 extern struct ata_device *ata_dev_pair(struct ata_device *adev);
+extern void ata_async_notify(struct ata_device *atadev);
 extern int ata_do_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
 extern u8 ata_irq_on(struct ata_port *ap);
 extern u8 ata_dummy_irq_on(struct ata_port *ap);
Index: 2.6-mm/drivers/ata/libata-core.c
===================================================================
--- 2.6-mm.orig/drivers/ata/libata-core.c
+++ 2.6-mm/drivers/ata/libata-core.c
@@ -1576,6 +1576,26 @@ static void ata_dev_config_ncq(struct at
 		snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
 }
 
+static void async_notify_thread(struct work_struct *work)
+{
+	struct ata_device *atadev =
+		container_of(work, struct ata_device, async_notify);
+
+	/*
+	 * TBD - who should send this event?  I couldn't find an
+	 * easy way to map an ata_device to a genhd device, so
+	 * decided maybe the ata host should send the event and
+	 * allow user space to figure out what happened?
+	 */
+	kobject_uevent(&atadev->ap->host->dev->kobj, KOBJ_CHANGE);
+}
+
+void ata_async_notify(struct ata_device *atadev)
+{
+	schedule_work(&atadev->async_notify);
+}
+
+
 /**
  *	ata_dev_configure - Configure the specified ATA/ATAPI device
  *	@dev: Target device to configure
@@ -1761,6 +1781,7 @@ int ata_dev_configure(struct ata_device 
 				goto err_out_nosup;
 			}
 			dev->flags |= ATA_DFLAG_AN;
+			INIT_WORK(&dev->async_notify, async_notify_thread);
 		}
 
 		if (ata_id_cdb_intr(dev->id)) {
@@ -6650,6 +6671,7 @@ EXPORT_SYMBOL_GPL(ata_dummy_irq_on);
 EXPORT_SYMBOL_GPL(ata_irq_ack);
 EXPORT_SYMBOL_GPL(ata_dummy_irq_ack);
 EXPORT_SYMBOL_GPL(ata_dev_try_classify);
+EXPORT_SYMBOL_GPL(ata_async_notify);
 
 EXPORT_SYMBOL_GPL(ata_cable_40wire);
 EXPORT_SYMBOL_GPL(ata_cable_80wire);

-- 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2007-03-29 13:04 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20070321004740.939006166@intel.com>
2007-03-21  0:52 ` [patch 1/3] libata: check for AN support Kristen Carlson Accardi
2007-03-21  0:52 ` [patch 2/3] libata: expose AN support to user space via sysfs Kristen Carlson Accardi
2007-03-21  0:52 ` [patch 3/3] libata: handle AN interrupt Kristen Carlson Accardi
     [not found] <20070328230108.597741522@intel.com>
2007-03-28 23:44 ` Kristen Carlson Accardi
2007-03-29  2:13   ` Tejun Heo
2007-03-29 12:38 James Smart
2007-03-29 12:43 ` Jeff Garzik
2007-03-29 13:04   ` James Smart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.