Browse Source

[SCSI] aacraid: respond to enclosure service events

Added support to respond to enclosure service events
(controller AIFs) to add, online or offline physical targets
reported to sg. Also added online and offlining of arrays.
Removed an automatic variable definition in a sub block that
hid an earlier definition, determined to be inert as the
sub-block use did not interfere. Bumped the driver versioning
to stamp the addition of this feature.

Signed-off-by: Mark Salyzyn <aacraid@adaptec.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Salyzyn, Mark 17 years ago
parent
commit
0995ad382d
2 changed files with 79 additions and 22 deletions
  1. 4 1
      drivers/scsi/aacraid/aacraid.h
  2. 75 21
      drivers/scsi/aacraid/commsup.c

+ 4 - 1
drivers/scsi/aacraid/aacraid.h

@@ -12,7 +12,7 @@
  *----------------------------------------------------------------------------*/
  *----------------------------------------------------------------------------*/
 
 
 #ifndef AAC_DRIVER_BUILD
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 2449
+# define AAC_DRIVER_BUILD 2454
 # define AAC_DRIVER_BRANCH "-ms"
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #endif
 #define MAXIMUM_NUM_CONTAINERS	32
 #define MAXIMUM_NUM_CONTAINERS	32
@@ -1772,6 +1772,9 @@ extern struct aac_common aac_config;
 #define			AifEnConfigChange	3	/* Adapter configuration change */
 #define			AifEnConfigChange	3	/* Adapter configuration change */
 #define			AifEnContainerChange	4	/* Container configuration change */
 #define			AifEnContainerChange	4	/* Container configuration change */
 #define			AifEnDeviceFailure	5	/* SCSI device failed */
 #define			AifEnDeviceFailure	5	/* SCSI device failed */
+#define			AifEnEnclosureManagement 13	/* EM_DRIVE_* */
+#define				EM_DRIVE_INSERTION	31
+#define				EM_DRIVE_REMOVAL	32
 #define			AifEnBatteryEvent	14	/* Change in Battery State */
 #define			AifEnBatteryEvent	14	/* Change in Battery State */
 #define			AifEnAddContainer	15	/* A new array was created */
 #define			AifEnAddContainer	15	/* A new array was created */
 #define			AifEnDeleteContainer	16	/* A container was deleted */
 #define			AifEnDeleteContainer	16	/* A container was deleted */

+ 75 - 21
drivers/scsi/aacraid/commsup.c

@@ -775,20 +775,20 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 {
 {
 	struct hw_fib * hw_fib = fibptr->hw_fib_va;
 	struct hw_fib * hw_fib = fibptr->hw_fib_va;
 	struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;
 	struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;
-	u32 container;
+	u32 channel, id, lun, container;
 	struct scsi_device *device;
 	struct scsi_device *device;
 	enum {
 	enum {
 		NOTHING,
 		NOTHING,
 		DELETE,
 		DELETE,
 		ADD,
 		ADD,
 		CHANGE
 		CHANGE
-	} device_config_needed;
+	} device_config_needed = NOTHING;
 
 
 	/* Sniff for container changes */
 	/* Sniff for container changes */
 
 
 	if (!dev || !dev->fsa_dev)
 	if (!dev || !dev->fsa_dev)
 		return;
 		return;
-	container = (u32)-1;
+	container = channel = id = lun = (u32)-1;
 
 
 	/*
 	/*
 	 *	We have set this up to try and minimize the number of
 	 *	We have set this up to try and minimize the number of
@@ -901,6 +901,36 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 		case AifEnConfigChange:
 		case AifEnConfigChange:
 			break;
 			break;
 
 
+		case AifEnEnclosureManagement:
+			switch (le32_to_cpu(((__le32 *)aifcmd->data)[3])) {
+			case EM_DRIVE_INSERTION:
+			case EM_DRIVE_REMOVAL:
+				container = le32_to_cpu(
+					((__le32 *)aifcmd->data)[2]);
+				if ((container >> 28))
+					break;
+				channel = (container >> 24) & 0xF;
+				if (channel >= dev->maximum_num_channels)
+					break;
+				id = container & 0xFFFF;
+				lun = (container >> 16) & 0xFF;
+				if (id >= dev->maximum_num_physicals) {
+					/* legacy dev_t ? */
+					if ((0x2000 <= id) || lun || channel ||
+					  ((channel = (id >> 7) & 0x3F) >=
+					  dev->maximum_num_channels))
+						break;
+					lun = (id >> 4) & 7;
+					id &= 0xF;
+				}
+				channel = aac_phys_to_logical(channel);
+				device_config_needed =
+				  (((__le32 *)aifcmd->data)[3]
+				    == cpu_to_le32(EM_DRIVE_INSERTION)) ?
+				  ADD : DELETE;
+				break;
+			}
+			break;
 		}
 		}
 
 
 		/*
 		/*
@@ -969,7 +999,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 		break;
 		break;
 	}
 	}
 
 
-	device_config_needed = NOTHING;
+	if (device_config_needed == NOTHING)
 	for (container = 0; container < dev->maximum_num_containers;
 	for (container = 0; container < dev->maximum_num_containers;
 	    ++container) {
 	    ++container) {
 		if ((dev->fsa_dev[container].config_waiting_on == 0) &&
 		if ((dev->fsa_dev[container].config_waiting_on == 0) &&
@@ -978,6 +1008,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 			device_config_needed =
 			device_config_needed =
 				dev->fsa_dev[container].config_needed;
 				dev->fsa_dev[container].config_needed;
 			dev->fsa_dev[container].config_needed = NOTHING;
 			dev->fsa_dev[container].config_needed = NOTHING;
+			channel = CONTAINER_TO_CHANNEL(container);
+			id = CONTAINER_TO_ID(container);
+			lun = CONTAINER_TO_LUN(container);
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -1001,34 +1034,56 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 	/*
 	/*
 	 * force reload of disk info via aac_probe_container
 	 * force reload of disk info via aac_probe_container
 	 */
 	 */
-	if ((device_config_needed == CHANGE)
-	 && (dev->fsa_dev[container].valid == 1))
-		dev->fsa_dev[container].valid = 2;
-	if ((device_config_needed == CHANGE) ||
-			(device_config_needed == ADD))
+	if ((channel == CONTAINER_CHANNEL) &&
+	  (device_config_needed != NOTHING)) {
+		if (dev->fsa_dev[container].valid == 1)
+			dev->fsa_dev[container].valid = 2;
 		aac_probe_container(dev, container);
 		aac_probe_container(dev, container);
-	device = scsi_device_lookup(dev->scsi_host_ptr, 
-		CONTAINER_TO_CHANNEL(container), 
-		CONTAINER_TO_ID(container), 
-		CONTAINER_TO_LUN(container));
+	}
+	device = scsi_device_lookup(dev->scsi_host_ptr, channel, id, lun);
 	if (device) {
 	if (device) {
 		switch (device_config_needed) {
 		switch (device_config_needed) {
 		case DELETE:
 		case DELETE:
+			if (scsi_device_online(device)) {
+				scsi_device_set_state(device, SDEV_OFFLINE);
+				sdev_printk(KERN_INFO, device,
+					"Device offlined - %s\n",
+					(channel == CONTAINER_CHANNEL) ?
+						"array deleted" :
+						"enclosure services event");
+			}
+			break;
+		case ADD:
+			if (!scsi_device_online(device)) {
+				sdev_printk(KERN_INFO, device,
+					"Device online - %s\n",
+					(channel == CONTAINER_CHANNEL) ?
+						"array created" :
+						"enclosure services event");
+				scsi_device_set_state(device, SDEV_RUNNING);
+			}
+			/* FALLTHRU */
 		case CHANGE:
 		case CHANGE:
+			if ((channel == CONTAINER_CHANNEL)
+			 && (!dev->fsa_dev[container].valid)) {
+				if (!scsi_device_online(device))
+					break;
+				scsi_device_set_state(device, SDEV_OFFLINE);
+				sdev_printk(KERN_INFO, device,
+					"Device offlined - %s\n",
+					"array failed");
+				break;
+			}
 			scsi_rescan_device(&device->sdev_gendev);
 			scsi_rescan_device(&device->sdev_gendev);
 
 
 		default:
 		default:
 			break;
 			break;
 		}
 		}
 		scsi_device_put(device);
 		scsi_device_put(device);
+		device_config_needed = NOTHING;
 	}
 	}
-	if (device_config_needed == ADD) {
-		scsi_add_device(dev->scsi_host_ptr,
-		  CONTAINER_TO_CHANNEL(container),
-		  CONTAINER_TO_ID(container),
-		  CONTAINER_TO_LUN(container));
-	}
-
+	if (device_config_needed == ADD)
+		scsi_add_device(dev->scsi_host_ptr, channel, id, lun);
 }
 }
 
 
 static int _aac_reset_adapter(struct aac_dev *aac, int forced)
 static int _aac_reset_adapter(struct aac_dev *aac, int forced)
@@ -1469,7 +1524,6 @@ int aac_command_thread(void *data)
 				*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
 				*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
 				aac_fib_adapter_complete(fib, (u16)sizeof(u32));
 				aac_fib_adapter_complete(fib, (u16)sizeof(u32));
 			} else {
 			} else {
-				struct list_head *entry;
 				/* The u32 here is important and intended. We are using
 				/* The u32 here is important and intended. We are using
 				   32bit wrapping time to fit the adapter field */
 				   32bit wrapping time to fit the adapter field */