linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 1/4] libata: check for AN support
       [not found] <20070808190613.616085010@localhost.localdomain>
@ 2007-08-08 19:08 ` Kristen Carlson Accardi
  2007-08-08 19:24   ` Andrew Morton
  2007-08-15  7:59   ` Jeff Garzik
  2007-08-08 19:08 ` [patch 2/4] scsi: expose AN support to user space Kristen Carlson Accardi
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 12+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-08 19:08 UTC (permalink / raw)
  To: jeff
  Cc: James.Bottomley, linux-ide, linux-scsi, linux-kernel, akpm,
	Kristen Carlson Accardi

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
+++ 2.6-git/drivers/ata/libata-core.c
@@ -70,6 +70,7 @@ const unsigned long sata_deb_timing_long
 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, u8 enable);
 static void ata_dev_xfermask(struct ata_device *dev);
 static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
 
@@ -1974,6 +1975,22 @@ int ata_dev_configure(struct ata_device 
 		}
 		dev->cdb_len = (unsigned int) rc;
 
+		/*
+		 * check to see if this ATAPI device supports
+		 * Asynchronous Notification
+		 */
+		if ((ap->flags & ATA_FLAG_AN) && ata_id_has_AN(id)) {
+			int err;
+			/* issue SET feature command to turn this on */
+			err = ata_dev_set_AN(dev, SETFEATURES_SATA_ENABLE);
+			if (err)
+				ata_dev_printk(dev, KERN_ERR,
+						"unable to set AN, err %x\n",
+						err);
+			else
+				dev->flags |= ATA_DFLAG_AN;
+		}
+
 		if (ata_id_cdb_intr(dev->id)) {
 			dev->flags |= ATA_DFLAG_CDB_INTR;
 			cdb_intr_string = ", CDB intr";
@@ -3948,6 +3965,42 @@ static unsigned int ata_dev_set_xfermode
 }
 
 /**
+ *	ata_dev_set_AN - Issue SET FEATURES - SATA FEATURES
+ *	@dev: Device to which command will be sent
+ *	@enable: Whether to enable or disable the feature
+ *
+ *	Issue SET FEATURES - SATA FEATURES command to device @dev
+ *	on port @ap with sector count set to indicate Asynchronous
+ *	Notification feature
+ *
+ *	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, u8 enable)
+{
+	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 = 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
+++ 2.6-git/include/linux/ata.h
@@ -217,6 +217,12 @@ enum {
 
 	SETFEATURES_SPINUP	= 0x07, /* Spin-up drive */
 
+	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:
@@ -344,6 +350,9 @@ struct ata_taskfile {
 #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] != 0x0000) && ((id)[76] != 0xffff)) && \
+	  ((id)[78] & (1 << 5)) )
 #define ata_id_iordy_disable(id) ((id)[49] & (1 << 10))
 #define ata_id_has_iordy(id) ((id)[49] & (1 << 9))
 #define ata_id_u32(id,n)	\
Index: 2.6-git/include/linux/libata.h
===================================================================
--- 2.6-git.orig/include/linux/libata.h
+++ 2.6-git/include/linux/libata.h
@@ -139,7 +139,8 @@ enum {
 	ATA_DFLAG_FLUSH_EXT	= (1 << 4), /* do FLUSH_EXT instead of FLUSH */
 	ATA_DFLAG_ACPI_PENDING	= (1 << 5), /* ACPI resume action pending */
 	ATA_DFLAG_ACPI_FAILED	= (1 << 6), /* ACPI on devcfg has failed */
-	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
+	ATA_DFLAG_AN		= (1 << 7), /* device supports AN */
+	ATA_DFLAG_CFG_MASK	= (1 << 12) - 1,
 
 	ATA_DFLAG_PIO		= (1 << 8), /* device limited to PIO mode */
 	ATA_DFLAG_NCQ_OFF	= (1 << 9), /* device limited to non-NCQ mode */
@@ -177,6 +178,7 @@ enum {
 	ATA_FLAG_IGN_SIMPLEX	= (1 << 15), /* ignore SIMPLEX */
 	ATA_FLAG_NO_IORDY	= (1 << 16), /* controller lacks iordy */
 	ATA_FLAG_ACPI_SATA	= (1 << 17), /* need native SATA ACPI layout */
+	ATA_FLAG_AN		= (1 << 18), /* controller supports AN */
 
 	/* The following flag belongs to ap->pflags but is kept in
 	 * ap->flags because it's referenced in many LLDs and will be
Index: 2.6-git/drivers/ata/ahci.c
===================================================================
--- 2.6-git.orig/drivers/ata/ahci.c
+++ 2.6-git/drivers/ata/ahci.c
@@ -332,14 +332,15 @@ static const struct ata_port_operations 
 static const struct ata_port_info ahci_port_info[] = {
 	/* board_ahci */
 	{
-		.flags		= AHCI_FLAG_COMMON,
+		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_AN,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
 	/* board_ahci_pi */
 	{
-		.flags		= AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI,
+		.flags		= AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI |
+				  ATA_FLAG_AN,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,

-- 

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

* [patch 2/4] scsi: expose AN support to user space
       [not found] <20070808190613.616085010@localhost.localdomain>
  2007-08-08 19:08 ` [patch 1/4] libata: check for AN support Kristen Carlson Accardi
@ 2007-08-08 19:08 ` Kristen Carlson Accardi
  2007-08-15  8:13   ` Jeff Garzik
  2007-08-08 19:08 ` [patch 3/4] libata: expose AN " Kristen Carlson Accardi
  2007-08-08 19:08 ` [patch 4/4] libata: send event when AN received Kristen Carlson Accardi
  3 siblings, 1 reply; 12+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-08 19:08 UTC (permalink / raw)
  To: jeff
  Cc: James.Bottomley, linux-ide, linux-scsi, linux-kernel, akpm,
	Kristen Carlson Accardi

If a scsi_device supports async notification for media change, then
let user space know this capability exists by creating a new sysfs
entry "media_change_notify", which will be 1 if it is supported, and
0 if not supported.  Create a routine which allows scsi devices to
send a uevent when media change events occur.

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

Index: 2.6-git/include/scsi/scsi_device.h
===================================================================
--- 2.6-git.orig/include/scsi/scsi_device.h
+++ 2.6-git/include/scsi/scsi_device.h
@@ -46,6 +46,16 @@ enum scsi_device_state {
 				 * to the scsi lld. */
 };
 
+/* must match scsi_device_event_strings in scsi_lib.c */
+enum scsi_device_event {
+	SDEV_MEDIA_CHANGE = 1,	/* media has changed */
+};
+
+struct scsi_device_event_info {
+	enum scsi_device_event event;
+	struct list_head link;
+};
+
 struct scsi_device {
 	struct Scsi_Host *host;
 	struct request_queue *request_queue;
@@ -126,7 +136,7 @@ struct scsi_device {
 	unsigned fix_capacity:1;	/* READ_CAPACITY is too high by 1 */
 	unsigned guess_capacity:1;	/* READ_CAPACITY might be too high by 1 */
 	unsigned retry_hwerror:1;	/* Retry HARDWARE_ERROR */
-
+	unsigned media_change_notify:1; /* dev supports async media notify */
 	unsigned int device_blocked;	/* Device returned QUEUE_FULL. */
 
 	unsigned int max_device_blocked; /* what device_blocked counts down from  */
@@ -144,6 +154,7 @@ struct scsi_device {
 	struct execute_work	ew; /* used to get process context on put */
 
 	enum scsi_device_state sdev_state;
+	struct list_head	sdev_event_list;
 	unsigned long		sdev_data[0];
 } __attribute__((aligned(sizeof(unsigned long))));
 #define	to_scsi_device(d)	\
@@ -275,6 +286,8 @@ extern int scsi_test_unit_ready(struct s
 				int retries);
 extern int scsi_device_set_state(struct scsi_device *sdev,
 				 enum scsi_device_state state);
+extern int scsi_device_event_notify(struct scsi_device *sdev,
+				enum scsi_device_event event);
 extern int scsi_device_quiesce(struct scsi_device *sdev);
 extern void scsi_device_resume(struct scsi_device *sdev);
 extern void scsi_target_quiesce(struct scsi_target *);
Index: 2.6-git/drivers/scsi/scsi_lib.c
===================================================================
--- 2.6-git.orig/drivers/scsi/scsi_lib.c
+++ 2.6-git/drivers/scsi/scsi_lib.c
@@ -64,6 +64,11 @@ static struct scsi_host_sg_pool scsi_sg_
 }; 	
 #undef SP
 
+/* must match scsi_device_event enum in scsi_device.h */
+static char * scsi_device_event_strings[] = {
+	"MEDIA_CHANGE=1",
+};
+
 static void scsi_run_queue(struct request_queue *q);
 
 /*
@@ -2007,6 +2012,84 @@ scsi_device_set_state(struct scsi_device
 EXPORT_SYMBOL(scsi_device_set_state);
 
 /**
+ * 	scsi_device_set_event - Add a new Async event to the event list
+ *	@sdev: scsi_device event occurred on
+ *	@event: the scsi device event
+ *
+ * 	Add a new scsi_device_event_info struct to the scsi_device_event_list
+ * 	queue.  This may be called from interrupt context.
+ *
+ * 	Returns 0 if successful, -ENOMEM otherwise.
+ */
+static int
+scsi_device_set_event(struct scsi_device *sdev, enum scsi_device_event event)
+{
+	struct scsi_device_event_info *scsi_event;
+	unsigned long flags;
+
+	scsi_event = kzalloc(sizeof(*scsi_event), GFP_ATOMIC);
+	if (!scsi_event)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&scsi_event->link);
+	scsi_event->event = event;
+	spin_lock_irqsave(&sdev->list_lock, flags);
+	list_add_tail(&scsi_event->link, &sdev->sdev_event_list);
+	spin_unlock_irqrestore(&sdev->list_lock, flags);
+	return 0;
+}
+
+/**
+ * 	scsi_device_event_notify_thread - send a uevent for each scsi event
+ *	@work: work struct for scsi_device
+ *
+ * 	Traverse the queue of scsi device events, dequeue each event and
+ * 	send a uevent.  Frees event.  May not be called from interrupt.
+ */
+static void scsi_event_notify_thread(struct work_struct *work)
+{
+	struct scsi_device *sdev;
+	char *envp[] = { NULL, NULL };
+	struct list_head *tmp;
+	struct list_head *next;
+	struct scsi_device_event_info *sdev_event;
+	unsigned long flags;
+
+	sdev = container_of(work, struct scsi_device, ew.work);
+	list_for_each_safe(tmp, next, &sdev->sdev_event_list) {
+		sdev_event = list_entry(tmp, struct scsi_device_event_info,
+					link);
+		spin_lock_irqsave(&sdev->list_lock, flags);
+		list_del(&sdev_event->link);
+		spin_unlock_irqrestore(&sdev->list_lock, flags);
+		envp[0] = scsi_device_event_strings[sdev_event->event-1];
+		kobject_uevent_env(&sdev->sdev_gendev.kobj, KOBJ_CHANGE, envp);
+		kfree(sdev_event);
+	}
+}
+
+/**
+ * 	scsi_device_event_notify - store event info and send an event
+ *	@sdev: scsi_device event occurred on
+ *	@event: the scsi device event
+ *
+ * 	Store the event information and then switch process context
+ * 	so that the event may be sent to user space.
+ * 	This may be called from interrupt context.
+ *
+ * 	Returns 0 if successful, -ENOMEM otherwise.
+ */
+int scsi_device_event_notify(struct scsi_device *sdev, enum scsi_device_event event)
+{
+	int rc;
+
+	rc = scsi_device_set_event(sdev, event);
+	if (!rc)
+		execute_in_process_context(scsi_event_notify_thread, &sdev->ew);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(scsi_device_event_notify);
+
+/**
  *	scsi_device_quiesce - Block user issued commands.
  *	@sdev:	scsi device to quiesce.
  *
Index: 2.6-git/drivers/scsi/scsi_scan.c
===================================================================
--- 2.6-git.orig/drivers/scsi/scsi_scan.c
+++ 2.6-git/drivers/scsi/scsi_scan.c
@@ -253,6 +253,7 @@ static struct scsi_device *scsi_alloc_sd
 	INIT_LIST_HEAD(&sdev->same_target_siblings);
 	INIT_LIST_HEAD(&sdev->cmd_list);
 	INIT_LIST_HEAD(&sdev->starved_entry);
+	INIT_LIST_HEAD(&sdev->sdev_event_list);
 	spin_lock_init(&sdev->list_lock);
 
 	sdev->sdev_gendev.parent = get_device(&starget->dev);
Index: 2.6-git/drivers/scsi/scsi_sysfs.c
===================================================================
--- 2.6-git.orig/drivers/scsi/scsi_sysfs.c
+++ 2.6-git/drivers/scsi/scsi_sysfs.c
@@ -575,6 +575,18 @@ sdev_show_modalias(struct device *dev, s
 }
 static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
 
+static ssize_t
+sdev_show_media_change_notify(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	if (sdev->media_change_notify)
+		return snprintf(buf, 20, "%d\n", 1);
+	else
+		return snprintf(buf, 20, "%d\n", 0);
+}
+static DEVICE_ATTR(media_change_notify, S_IRUGO, sdev_show_media_change_notify, NULL);
+
 /* Default template for device attributes.  May NOT be modified */
 static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
 	&dev_attr_device_blocked,
@@ -594,6 +606,7 @@ static struct device_attribute *scsi_sys
 	&dev_attr_iodone_cnt,
 	&dev_attr_ioerr_cnt,
 	&dev_attr_modalias,
+	&dev_attr_media_change_notify,
 	NULL
 };
 

-- 

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

* [patch 3/4] libata: expose AN to user space
       [not found] <20070808190613.616085010@localhost.localdomain>
  2007-08-08 19:08 ` [patch 1/4] libata: check for AN support Kristen Carlson Accardi
  2007-08-08 19:08 ` [patch 2/4] scsi: expose AN support to user space Kristen Carlson Accardi
@ 2007-08-08 19:08 ` Kristen Carlson Accardi
  2007-08-08 19:08 ` [patch 4/4] libata: send event when AN received Kristen Carlson Accardi
  3 siblings, 0 replies; 12+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-08 19:08 UTC (permalink / raw)
  To: jeff
  Cc: James.Bottomley, linux-ide, linux-scsi, linux-kernel, akpm,
	Kristen Carlson Accardi

If Asynchronous Notification of media change events is supported,
pass that information up to the SCSI layer.

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

Index: 2.6-git/drivers/ata/libata-scsi.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-scsi.c
+++ 2.6-git/drivers/ata/libata-scsi.c
@@ -771,6 +771,9 @@ static void ata_scsi_dev_config(struct s
 		blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
 	}
 
+	if (dev->flags & ATA_DFLAG_AN)
+		sdev->media_change_notify = 1;
+
 	if (dev->flags & ATA_DFLAG_NCQ) {
 		int depth;
 

-- 

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

* [patch 4/4] libata: send event when AN received
       [not found] <20070808190613.616085010@localhost.localdomain>
                   ` (2 preceding siblings ...)
  2007-08-08 19:08 ` [patch 3/4] libata: expose AN " Kristen Carlson Accardi
@ 2007-08-08 19:08 ` Kristen Carlson Accardi
  2007-08-15  8:12   ` Jeff Garzik
  3 siblings, 1 reply; 12+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-08 19:08 UTC (permalink / raw)
  To: jeff
  Cc: James.Bottomley, linux-ide, linux-scsi, linux-kernel, akpm,
	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.  This will be done via the scsi device. 

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
+++ 2.6-git/drivers/ata/ahci.c
@@ -1359,6 +1359,28 @@ static void ahci_port_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;
+			if (port_addr < ATA_MAX_DEVICES) {
+				adev = &ap->device[port_addr];
+				if (adev->flags & ATA_DFLAG_AN)
+					ata_scsi_media_change_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
+++ 2.6-git/include/linux/libata.h
@@ -737,6 +737,7 @@ extern void ata_host_init(struct ata_hos
 extern int ata_scsi_detect(struct scsi_host_template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
+extern void ata_scsi_media_change_notify(struct ata_device *atadev);
 extern void ata_sas_port_destroy(struct ata_port *);
 extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
 					   struct ata_port_info *, struct Scsi_Host *);
Index: 2.6-git/drivers/ata/libata-scsi.c
===================================================================
--- 2.6-git.orig/drivers/ata/libata-scsi.c
+++ 2.6-git/drivers/ata/libata-scsi.c
@@ -3099,6 +3099,22 @@ static void ata_scsi_remove_dev(struct a
 }
 
 /**
+ *	ata_scsi_media_change_notify - send media change event
+ *	@atadev: Pointer to the disk device with media change event
+ *
+ *	Tell the block layer to send a media change notification
+ *	event.
+ *
+ * 	LOCKING:
+ * 	interrupt context, may not sleep.
+ */
+void ata_scsi_media_change_notify(struct ata_device *atadev)
+{
+	scsi_device_event_notify(atadev->sdev, SDEV_MEDIA_CHANGE);
+}
+EXPORT_SYMBOL_GPL(ata_scsi_media_change_notify);
+
+/**
  *	ata_scsi_hotplug - SCSI part of hotplug
  *	@work: Pointer to ATA port to perform SCSI hotplug on
  *

-- 

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

* Re: [patch 1/4] libata: check for AN support
  2007-08-08 19:08 ` [patch 1/4] libata: check for AN support Kristen Carlson Accardi
@ 2007-08-08 19:24   ` Andrew Morton
  2007-08-15  7:59   ` Jeff Garzik
  1 sibling, 0 replies; 12+ messages in thread
From: Andrew Morton @ 2007-08-08 19:24 UTC (permalink / raw)
  To: Kristen Carlson Accardi
  Cc: jeff, James.Bottomley, linux-ide, linux-scsi, linux-kernel

On Wed, 8 Aug 2007 12:08:10 -0700
Kristen Carlson Accardi <kristen.c.accardi@intel.com> wrote:

> ===================================================================
> --- 2.6-git.orig/include/linux/libata.h
> +++ 2.6-git/include/linux/libata.h
> @@ -139,7 +139,8 @@ enum {
>  	ATA_DFLAG_FLUSH_EXT	= (1 << 4), /* do FLUSH_EXT instead of FLUSH */
>  	ATA_DFLAG_ACPI_PENDING	= (1 << 5), /* ACPI resume action pending */
>  	ATA_DFLAG_ACPI_FAILED	= (1 << 6), /* ACPI on devcfg has failed */
> -	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
> +	ATA_DFLAG_AN		= (1 << 7), /* device supports AN */
> +	ATA_DFLAG_CFG_MASK	= (1 << 12) - 1,
>  
>  	ATA_DFLAG_PIO		= (1 << 8), /* device limited to PIO mode */
>  	ATA_DFLAG_NCQ_OFF	= (1 << 9), /* device limited to non-NCQ mode */
> @@ -177,6 +178,7 @@ enum {
>  	ATA_FLAG_IGN_SIMPLEX	= (1 << 15), /* ignore SIMPLEX */
>  	ATA_FLAG_NO_IORDY	= (1 << 16), /* controller lacks iordy */
>  	ATA_FLAG_ACPI_SATA	= (1 << 17), /* need native SATA ACPI layout */
> +	ATA_FLAG_AN		= (1 << 18), /* controller supports AN */
>  

It would be nice to at least get bits like this upstream.

<goes off and fixes it again>

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

* Re: [patch 1/4] libata: check for AN support
  2007-08-08 19:08 ` [patch 1/4] libata: check for AN support Kristen Carlson Accardi
  2007-08-08 19:24   ` Andrew Morton
@ 2007-08-15  7:59   ` Jeff Garzik
  2007-08-15 16:21     ` Kristen Carlson Accardi
  1 sibling, 1 reply; 12+ messages in thread
From: Jeff Garzik @ 2007-08-15  7:59 UTC (permalink / raw)
  To: Kristen Carlson Accardi
  Cc: James.Bottomley, linux-ide, linux-scsi, linux-kernel, akpm

Kristen Carlson Accardi wrote:
> 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
> +++ 2.6-git/drivers/ata/libata-core.c
> @@ -70,6 +70,7 @@ const unsigned long sata_deb_timing_long
>  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, u8 enable);
>  static void ata_dev_xfermask(struct ata_device *dev);
>  static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
>  
> @@ -1974,6 +1975,22 @@ int ata_dev_configure(struct ata_device 
>  		}
>  		dev->cdb_len = (unsigned int) rc;
>  
> +		/*
> +		 * check to see if this ATAPI device supports
> +		 * Asynchronous Notification
> +		 */
> +		if ((ap->flags & ATA_FLAG_AN) && ata_id_has_AN(id)) {
> +			int err;
> +			/* issue SET feature command to turn this on */
> +			err = ata_dev_set_AN(dev, SETFEATURES_SATA_ENABLE);
> +			if (err)
> +				ata_dev_printk(dev, KERN_ERR,
> +						"unable to set AN, err %x\n",
> +						err);
> +			else
> +				dev->flags |= ATA_DFLAG_AN;
> +		}
> +
>  		if (ata_id_cdb_intr(dev->id)) {
>  			dev->flags |= ATA_DFLAG_CDB_INTR;
>  			cdb_intr_string = ", CDB intr";
> @@ -3948,6 +3965,42 @@ static unsigned int ata_dev_set_xfermode
>  }
>  
>  /**
> + *	ata_dev_set_AN - Issue SET FEATURES - SATA FEATURES
> + *	@dev: Device to which command will be sent
> + *	@enable: Whether to enable or disable the feature
> + *
> + *	Issue SET FEATURES - SATA FEATURES command to device @dev
> + *	on port @ap with sector count set to indicate Asynchronous
> + *	Notification feature
> + *
> + *	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, u8 enable)
> +{
> +	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 = 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
> +++ 2.6-git/include/linux/ata.h
> @@ -217,6 +217,12 @@ enum {
>  
>  	SETFEATURES_SPINUP	= 0x07, /* Spin-up drive */
>  
> +	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:
> @@ -344,6 +350,9 @@ struct ata_taskfile {
>  #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] != 0x0000) && ((id)[76] != 0xffff)) && \
> +	  ((id)[78] & (1 << 5)) )
>  #define ata_id_iordy_disable(id) ((id)[49] & (1 << 10))
>  #define ata_id_has_iordy(id) ((id)[49] & (1 << 9))
>  #define ata_id_u32(id,n)	\
> Index: 2.6-git/include/linux/libata.h
> ===================================================================
> --- 2.6-git.orig/include/linux/libata.h
> +++ 2.6-git/include/linux/libata.h
> @@ -139,7 +139,8 @@ enum {
>  	ATA_DFLAG_FLUSH_EXT	= (1 << 4), /* do FLUSH_EXT instead of FLUSH */
>  	ATA_DFLAG_ACPI_PENDING	= (1 << 5), /* ACPI resume action pending */
>  	ATA_DFLAG_ACPI_FAILED	= (1 << 6), /* ACPI on devcfg has failed */
> -	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
> +	ATA_DFLAG_AN		= (1 << 7), /* device supports AN */
> +	ATA_DFLAG_CFG_MASK	= (1 << 12) - 1,
>  
>  	ATA_DFLAG_PIO		= (1 << 8), /* device limited to PIO mode */
>  	ATA_DFLAG_NCQ_OFF	= (1 << 9), /* device limited to non-NCQ mode */
> @@ -177,6 +178,7 @@ enum {
>  	ATA_FLAG_IGN_SIMPLEX	= (1 << 15), /* ignore SIMPLEX */
>  	ATA_FLAG_NO_IORDY	= (1 << 16), /* controller lacks iordy */
>  	ATA_FLAG_ACPI_SATA	= (1 << 17), /* need native SATA ACPI layout */
> +	ATA_FLAG_AN		= (1 << 18), /* controller supports AN */


I applied the above changes, in order to move AN forward


>  	/* The following flag belongs to ap->pflags but is kept in
>  	 * ap->flags because it's referenced in many LLDs and will be
> Index: 2.6-git/drivers/ata/ahci.c
> ===================================================================
> --- 2.6-git.orig/drivers/ata/ahci.c
> +++ 2.6-git/drivers/ata/ahci.c
> @@ -332,14 +332,15 @@ static const struct ata_port_operations 
>  static const struct ata_port_info ahci_port_info[] = {
>  	/* board_ahci */
>  	{
> -		.flags		= AHCI_FLAG_COMMON,
> +		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_AN,
>  		.pio_mask	= 0x1f, /* pio0-4 */
>  		.udma_mask	= ATA_UDMA6,
>  		.port_ops	= &ahci_ops,
>  	},
>  	/* board_ahci_pi */
>  	{
> -		.flags		= AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI,
> +		.flags		= AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI |
> +				  ATA_FLAG_AN,
>  		.pio_mask	= 0x1f, /* pio0-4 */
>  		.udma_mask	= ATA_UDMA6,
>  		.port_ops	= &ahci_ops,
> 

Since I wanted to get in Tejun's ata_link changes before this, this will 
require a rediff.

But more importantly, as I was going to apply it I noticed another 
problem:  we need to verify that SiS and NVIDIA both support AN support 
turning this on, since this patch affects not only Intel but also those 
vendors' AHCI hardware as well.

It's a bit annoying but this is a cross-vendor driver after all...

	Jeff



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

* Re: [patch 4/4] libata: send event when AN received
  2007-08-08 19:08 ` [patch 4/4] libata: send event when AN received Kristen Carlson Accardi
@ 2007-08-15  8:12   ` Jeff Garzik
  0 siblings, 0 replies; 12+ messages in thread
From: Jeff Garzik @ 2007-08-15  8:12 UTC (permalink / raw)
  To: Kristen Carlson Accardi
  Cc: James.Bottomley, linux-ide, linux-scsi, linux-kernel, akpm

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

applied the attached slightly modified patch.  main changes:

* SCSI stuff has not been applied yet, so libata's notify is a no-op for now

* fixed endian bug in SDB FIS handling



[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 2545 bytes --]

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 757369e..c41bd2c 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1366,6 +1366,30 @@ static void ahci_port_intr(struct ata_port *ap)
 		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 __le32 *f = pp->rx_fis + RX_FIS_SDB;
+		u32 f0 = le32_to_cpu(f[0]);
+
+		/* check the 'N' bit in word 0 of the FIS */
+		if (f0 & (1 << 15)) {
+			int port_addr = ((f0 & 0x00000f00) >> 8);
+			struct ata_device *adev;
+			if (port_addr < ATA_MAX_DEVICES) {
+				adev = &ap->link.device[port_addr];
+				if (adev->flags & ATA_DFLAG_AN)
+					ata_scsi_media_change_notify(adev);
+			}
+		}
+	}
+
 	if (ap->link.sactive)
 		qc_active = readl(port_mmio + PORT_SCR_ACT);
 	else
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 7d66c98..f0f586b 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3160,6 +3160,24 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)
 }
 
 /**
+ *	ata_scsi_media_change_notify - send media change event
+ *	@atadev: Pointer to the disk device with media change event
+ *
+ *	Tell the block layer to send a media change notification
+ *	event.
+ *
+ * 	LOCKING:
+ * 	interrupt context, may not sleep.
+ */
+void ata_scsi_media_change_notify(struct ata_device *atadev)
+{
+#ifdef OTHER_AN_PATCHES_HAVE_BEEN_APPLIED
+	scsi_device_event_notify(atadev->sdev, SDEV_MEDIA_CHANGE);
+#endif
+}
+EXPORT_SYMBOL_GPL(ata_scsi_media_change_notify);
+
+/**
  *	ata_scsi_hotplug - SCSI part of hotplug
  *	@work: Pointer to ATA port to perform SCSI hotplug on
  *
diff --git a/include/linux/libata.h b/include/linux/libata.h
index d1bd9f5..08d6a9a 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -754,6 +754,7 @@ extern void ata_host_init(struct ata_host *, struct device *,
 extern int ata_scsi_detect(struct scsi_host_template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
+extern void ata_scsi_media_change_notify(struct ata_device *atadev);
 extern void ata_sas_port_destroy(struct ata_port *);
 extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
 					   struct ata_port_info *, struct Scsi_Host *);

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

* Re: [patch 2/4] scsi: expose AN support to user space
  2007-08-08 19:08 ` [patch 2/4] scsi: expose AN support to user space Kristen Carlson Accardi
@ 2007-08-15  8:13   ` Jeff Garzik
  2007-08-15 14:01     ` James Bottomley
  0 siblings, 1 reply; 12+ messages in thread
From: Jeff Garzik @ 2007-08-15  8:13 UTC (permalink / raw)
  To: Kristen Carlson Accardi
  Cc: James.Bottomley, linux-ide, linux-scsi, linux-kernel, akpm

Kristen Carlson Accardi wrote:
> If a scsi_device supports async notification for media change, then
> let user space know this capability exists by creating a new sysfs
> entry "media_change_notify", which will be 1 if it is supported, and
> 0 if not supported.  Create a routine which allows scsi devices to
> send a uevent when media change events occur.
> 
> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>

if James is happy with this patch, I'm happy with patch #2 and #3



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

* Re: [patch 2/4] scsi: expose AN support to user space
  2007-08-15  8:13   ` Jeff Garzik
@ 2007-08-15 14:01     ` James Bottomley
  2007-08-15 16:27       ` Kristen Carlson Accardi
  2007-08-15 23:37       ` Moore, Eric
  0 siblings, 2 replies; 12+ messages in thread
From: James Bottomley @ 2007-08-15 14:01 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Kristen Carlson Accardi, linux-ide, linux-scsi, linux-kernel,
	akpm

On Wed, 2007-08-15 at 04:13 -0400, Jeff Garzik wrote:
> Kristen Carlson Accardi wrote:
> > If a scsi_device supports async notification for media change, then
> > let user space know this capability exists by creating a new sysfs
> > entry "media_change_notify", which will be 1 if it is supported, and
> > 0 if not supported.  Create a routine which allows scsi devices to
> > send a uevent when media change events occur.
> > 
> > Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
> 
> if James is happy with this patch, I'm happy with patch #2 and #3

Actually, we just got a second potential consumer ... although I'll
reprod to have the reporter send it to the list.  It's a device that
needs notice of report luns data changing.  The proposed mechanism looks
a bit narrow now (too tied to media change).  I'll see if I can propose
a more generic update.

James



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

* Re: [patch 1/4] libata: check for AN support
  2007-08-15  7:59   ` Jeff Garzik
@ 2007-08-15 16:21     ` Kristen Carlson Accardi
  0 siblings, 0 replies; 12+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-15 16:21 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: James.Bottomley, linux-ide, linux-scsi, linux-kernel, akpm

On Wed, 15 Aug 2007 03:59:10 -0400
Jeff Garzik <jeff@garzik.org> wrote:

> Since I wanted to get in Tejun's ata_link changes before this, this will 
> require a rediff.
> 
> But more importantly, as I was going to apply it I noticed another 
> problem:  we need to verify that SiS and NVIDIA both support AN support 
> turning this on, since this patch affects not only Intel but also those 
> vendors' AHCI hardware as well.
> 
> It's a bit annoying but this is a cross-vendor driver after all...
> 
> 	Jeff

Got a link to their public docs?  I'm happy to look in their specs to confirm.
Otherwise, maybe you can forward to people there to have them check, or find
someone under NDA with them who can.

Kristen

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

* Re: [patch 2/4] scsi: expose AN support to user space
  2007-08-15 14:01     ` James Bottomley
@ 2007-08-15 16:27       ` Kristen Carlson Accardi
  2007-08-15 23:37       ` Moore, Eric
  1 sibling, 0 replies; 12+ messages in thread
From: Kristen Carlson Accardi @ 2007-08-15 16:27 UTC (permalink / raw)
  To: James Bottomley; +Cc: Jeff Garzik, linux-ide, linux-scsi, linux-kernel, akpm

On Wed, 15 Aug 2007 09:01:49 -0500
James Bottomley <James.Bottomley@SteelEye.com> wrote:

> On Wed, 2007-08-15 at 04:13 -0400, Jeff Garzik wrote:
> > Kristen Carlson Accardi wrote:
> > > If a scsi_device supports async notification for media change, then
> > > let user space know this capability exists by creating a new sysfs
> > > entry "media_change_notify", which will be 1 if it is supported, and
> > > 0 if not supported.  Create a routine which allows scsi devices to
> > > send a uevent when media change events occur.
> > > 
> > > Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
> > 
> > if James is happy with this patch, I'm happy with patch #2 and #3
> 
> Actually, we just got a second potential consumer ... although I'll
> reprod to have the reporter send it to the list.  It's a device that
> needs notice of report luns data changing.  The proposed mechanism looks
> a bit narrow now (too tied to media change).  I'll see if I can propose
> a more generic update.
> 
> James
> 

Too narrow because it's tied to scsi_device?  Obviously it'd be easy
to expand the scsi_device_event enum to include LUNS_DATA_CHANGE or 
something, and even the scsi_device_event_info struct can easily be 
expanded if you need more info attached to the event.  Let me know if 
there's something specific I can help with.

Kristen

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

* RE: [patch 2/4] scsi: expose AN support to user space
  2007-08-15 14:01     ` James Bottomley
  2007-08-15 16:27       ` Kristen Carlson Accardi
@ 2007-08-15 23:37       ` Moore, Eric
  1 sibling, 0 replies; 12+ messages in thread
From: Moore, Eric @ 2007-08-15 23:37 UTC (permalink / raw)
  To: James Bottomley, Jeff Garzik
  Cc: Kristen Carlson Accardi, linux-ide, linux-scsi, linux-kernel,
	akpm, venkatr, vimal.nakum

On Wednesday, August 15, 2007 8:02 AM, James Bottomley wrote: 
> Actually, we just got a second potential consumer ... although I'll
> reprod to have the reporter send it to the list.  It's a device that
> needs notice of report luns data changing.  The proposed 
> mechanism looks
> a bit narrow now (too tied to media change).  I'll see if I 
> can propose
> a more generic update.
> 

I believe James is referring to my Promise issue. That is -  the
customers mutipath enclosure our SAS controller.  They have alternating
luns mapped to each path.  The odd luns mapped to a single path, and the
even luns to the other.  When a cable is pulled, a check condition is
generated (0x6, 0x3F, 0xE),  means report_luns data has changed.  What
the enclosure does it move the luns over to the alternate path.    Our
driver is not reporting the new luns because no event is generated to
mpt fusion driver from controller firmware (firmware only reports when a
target has been added/removed, not lun).     The mpt fusion driver
reports to the sas transport layer, the libata layer is not involved.
Shouldn't someone above sscsi lld be snooping that sence, and then
sending REPORT_LUNS to find out what changed.       

I've added some Promise contacts,  I hope they include the interested
partied to this discussion.

Eric

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

end of thread, other threads:[~2007-08-15 23:37 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20070808190613.616085010@localhost.localdomain>
2007-08-08 19:08 ` [patch 1/4] libata: check for AN support Kristen Carlson Accardi
2007-08-08 19:24   ` Andrew Morton
2007-08-15  7:59   ` Jeff Garzik
2007-08-15 16:21     ` Kristen Carlson Accardi
2007-08-08 19:08 ` [patch 2/4] scsi: expose AN support to user space Kristen Carlson Accardi
2007-08-15  8:13   ` Jeff Garzik
2007-08-15 14:01     ` James Bottomley
2007-08-15 16:27       ` Kristen Carlson Accardi
2007-08-15 23:37       ` Moore, Eric
2007-08-08 19:08 ` [patch 3/4] libata: expose AN " Kristen Carlson Accardi
2007-08-08 19:08 ` [patch 4/4] libata: send event when AN received Kristen Carlson Accardi
2007-08-15  8:12   ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).