From c92f222e1f14588171e63b550ca8c85fa9130061 Mon Sep 17 00:00:00 2001
From: James Bottomley <James.Bottomley@steeleye.com>
Date: Wed, 1 Mar 2006 09:02:49 -0600
Subject: [SCSI] mptspi: Add transport class Domain Validation

This is the first half of a patch to add the generic domain validation
to mptspi.  It also creates a secondary "virtual" channel for raid
component devices since these are now exported with no_uld_attach.

What Eric and I would have really liked is to export all physical
components on channel 0 and all raid components on channel 1.
Unfortunately, this would result in device renumbering on platforms with
mixed RAID/Physical devices which was considered unacceptable for
userland stability reasons.

Still to be done is to plug back the extra parameter setting and DV
pieces on reset and hotplug.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
---
 drivers/message/fusion/mptbase.h | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)

(limited to 'drivers/message/fusion/mptbase.h')

diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 723d5430095..f4197a9962a 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -331,6 +331,7 @@ typedef struct _SYSIF_REGS
  *	VirtDevice - FC LUN device or SCSI target device
  */
 typedef struct _VirtTarget {
+	struct scsi_target	*starget;
 	u8			 tflags;
 	u8			 ioc_id;
 	u8			 target_id;
@@ -343,7 +344,6 @@ typedef struct _VirtTarget {
 	u8			 type;		/* byte 0 of Inquiry data */
 	u32			 num_luns;
 	u32			 luns[8];		/* Max LUNs is 256 */
-	u8			 inq_data[8];
 } VirtTarget;
 
 typedef struct _VirtDevice {
@@ -364,6 +364,7 @@ typedef struct _VirtDevice {
 #define MPT_TARGET_FLAGS_Q_YES		0x08
 #define MPT_TARGET_FLAGS_VALID_56	0x10
 #define MPT_TARGET_FLAGS_SAF_TE_ISSUED	0x20
+#define MPT_TARGET_FLAGS_RAID_COMPONENT	0x40
 
 /*
  *	/proc/mpt interface
@@ -447,13 +448,6 @@ typedef struct _mpt_ioctl_events {
  *	Substructure to store SCSI specific configuration page data
  */
 						/* dvStatus defines: */
-#define MPT_SCSICFG_NEGOTIATE		0x01	/* Negotiate on next IO */
-#define MPT_SCSICFG_NEED_DV		0x02	/* Schedule DV */
-#define MPT_SCSICFG_DV_PENDING		0x04	/* DV on this physical id pending */
-#define MPT_SCSICFG_DV_NOT_DONE		0x08	/* DV has not been performed */
-#define MPT_SCSICFG_BLK_NEGO		0x10	/* WriteSDP1 with WDTR and SDTR disabled */
-#define MPT_SCSICFG_RELOAD_IOC_PG3	0x20	/* IOC Pg 3 data is obsolete */
-						/* Args passed to writeSDP1: */
 #define MPT_SCSICFG_USE_NVRAM		0x01	/* WriteSDP1 using NVRAM */
 #define MPT_SCSICFG_ALL_IDS		0x02	/* WriteSDP1 to all IDS */
 /* #define MPT_SCSICFG_BLK_NEGO		0x10	   WriteSDP1 with WDTR and SDTR disabled */
@@ -464,7 +458,6 @@ typedef	struct _SpiCfgData {
 	IOCPage4_t	*pIocPg4;		/* SEP devices addressing */
 	dma_addr_t	 IocPg4_dma;		/* Phys Addr of IOCPage4 data */
 	int		 IocPg4Sz;		/* IOCPage4 size */
-	u8		 dvStatus[MPT_MAX_SCSI_DEVICES];
 	u8		 minSyncFactor;		/* 0xFF if async */
 	u8		 maxSyncOffset;		/* 0 if async */
 	u8		 maxBusWidth;		/* 0 if narrow, 1 if wide */
@@ -474,13 +467,11 @@ typedef	struct _SpiCfgData {
 	u8		 sdp0version;		/* SDP0 version */
 	u8		 sdp0length;		/* SDP0 length  */
 	u8		 dvScheduled;		/* 1 if scheduled */
-	u8		 forceDv;		/* 1 to force DV scheduling */
 	u8		 noQas;			/* Disable QAS for this adapter */
 	u8		 Saf_Te;		/* 1 to force all Processors as
 						 * SAF-TE if Inquiry data length
 						 * is too short to check for SAF-TE
 						 */
-	u8		 mpt_dv;		/* command line option: enhanced=1, basic=0 */
 	u8		 bus_reset;		/* 1 to allow bus reset */
 	u8		 rsvd[1];
 }SpiCfgData;
@@ -1033,7 +1024,6 @@ extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int	 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 extern int	 mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
-extern int	 mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
 
 /*
  *  Public data decl's...
-- 
cgit v1.2.3-70-g09d2


From 3a892bef3f7e94c4d6c2c20b9a1b546f43679fd3 Mon Sep 17 00:00:00 2001
From: "Moore, Eric" <Eric.Moore@lsil.com>
Date: Tue, 14 Mar 2006 09:14:03 -0700
Subject: [SCSI] fusion - move some debug firmware event debug msgs to verbose
 level

Created a debug level MPT_DEBUG_VERBOSE_EVENTS.
Moving some of the more vebose debug messages
for firwmare events into new debug level.  Also
added some more firmware events descriptions.

Signed-off-by: Eric Moore <Eric.Moore@lsil.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
---
 drivers/message/fusion/Makefile   |   1 +
 drivers/message/fusion/mptbase.c  | 125 ++++++++++++++++++++++++++++++++------
 drivers/message/fusion/mptbase.h  |   8 ++-
 drivers/message/fusion/mptctl.c   |   6 +-
 drivers/message/fusion/mptfc.c    |   2 +-
 drivers/message/fusion/mptsas.c   |   2 +-
 drivers/message/fusion/mptscsih.c |   2 +-
 drivers/message/fusion/mptspi.c   |   2 +-
 8 files changed, 122 insertions(+), 26 deletions(-)

(limited to 'drivers/message/fusion/mptbase.h')

diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index 33ace373241..51740b34622 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -4,6 +4,7 @@
 #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME
 #EXTRA_CFLAGS += -DMPT_DEBUG_SG
 #EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS
+#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE_EVENTS
 #EXTRA_CFLAGS += -DMPT_DEBUG_INIT
 #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
 #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 39c0b16d8d0..9960ef10366 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -428,7 +428,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 		results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
 		if (results != evHandlers) {
 			/* CHECKME! Any special handling needed here? */
-			devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
+			devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
 					ioc->name, evHandlers, results));
 		}
 
@@ -438,10 +438,10 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 		 */
 		if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
 			freereq = 0;
-			devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
+			devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
 				ioc->name, pEvReply));
 		} else {
-			devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
+			devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
 				ioc->name, pEvReply));
 		}
 
@@ -5079,13 +5079,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
 
 	evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
 	if (evnp == NULL) {
-		devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
+		devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
 				ioc->name));
 		return 0;
 	}
 	memset(evnp, 0, sizeof(*evnp));
 
-	devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
+	devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
 
 	evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
 	evnp->ChainOffset = 0;
@@ -5840,24 +5840,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 		break;
 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
 	{
+		char buf[50];
+		u8 id = (u8)(evData0);
 		u8 ReasonCode = (u8)(evData0 >> 16);
 		switch (ReasonCode) {
 		case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
-			ds = "SAS Device Status Change: Added";
+			sprintf(buf,"SAS Device Status Change: Added: id=%d", id);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
-			ds = "SAS Device Status Change: Deleted";
+			sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
-			ds = "SAS Device Status Change: SMART Data";
+			sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
-			ds = "SAS Device Status Change: No Persistancy Added";
+			sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id);
 			break;
 		default:
-			ds = "SAS Device Status Change: Unknown";
+			sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id);
 		break;
 		}
+		ds = buf;
 		break;
 	}
 	case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
@@ -5873,11 +5876,97 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 		ds = "Persistent Table Full";
 		break;
 	case MPI_EVENT_SAS_PHY_LINK_STATUS:
-		ds = "SAS PHY Link Status";
+	{
+		char buf[50];
+		u8 LinkRates = (u8)(evData0 >> 8);
+		u8 PhyNumber = (u8)(evData0);
+		LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
+			MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
+		switch (LinkRates) {
+		case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
+			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			   " Rate Unknown",PhyNumber);
+			break;
+		case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
+			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			   " Phy Disabled",PhyNumber);
+			break;
+		case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
+			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			   " Failed Speed Nego",PhyNumber);
+			break;
+		case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
+			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			   " Sata OOB Completed",PhyNumber);
+			break;
+		case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
+			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			   " Rate 1.5 Gbps",PhyNumber);
+			break;
+		case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
+			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			   " Rate 3.0 Gpbs",PhyNumber);
+			break;
+		default:
+			sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber);
+			break;
+		}
+		ds = buf;
 		break;
+	}
 	case MPI_EVENT_SAS_DISCOVERY_ERROR:
 		ds = "SAS Discovery Error";
 		break;
+	case MPI_EVENT_IR_RESYNC_UPDATE:
+	{
+		u8 resync_complete = (u8)(evData0 >> 16);
+		char buf[40];
+		sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete);
+		ds = buf;
+		break;
+	}
+	case MPI_EVENT_IR2:
+	{
+		u8 ReasonCode = (u8)(evData0 >> 16);
+		switch (ReasonCode) {
+		case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
+			ds = "IR2: LD State Changed";
+			break;
+		case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
+			ds = "IR2: PD State Changed";
+			break;
+		case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
+			ds = "IR2: Bad Block Table Full";
+			break;
+		case MPI_EVENT_IR2_RC_PD_INSERTED:
+			ds = "IR2: PD Inserted";
+			break;
+		case MPI_EVENT_IR2_RC_PD_REMOVED:
+			ds = "IR2: PD Removed";
+			break;
+		case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
+			ds = "IR2: Foreign CFG Detected";
+			break;
+		case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
+			ds = "IR2: Rebuild Medium Error";
+			break;
+		default:
+			ds = "IR2";
+		break;
+		}
+		break;
+	}
+	case MPI_EVENT_SAS_DISCOVERY:
+	{
+		if (evData0)
+			ds = "SAS Discovery: Start";
+		else
+			ds = "SAS Discovery: Stop";
+		break;
+	}
+	case MPI_EVENT_LOG_ENTRY_ADDED:
+		ds = "SAS Log Entry Added";
+		break;
 
 	/*
 	 *  MPT base "custom" events may be added here...
@@ -5922,12 +6011,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 	}
 
 	EventDescriptionStr(event, evData0, evStr);
-	devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
+	devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
 			ioc->name,
-			evStr,
-			event));
+			event,
+			evStr));
 
-#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
+#if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
 	printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
 	for (ii = 0; ii < evDataLen; ii++)
 		printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
@@ -5986,7 +6075,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 	 */
 	for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
 		if (MptEvHandlers[ii]) {
-			devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
+			devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
 					ioc->name, ii));
 			r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
 			handlers++;
@@ -5998,10 +6087,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 	 *  If needed, send (a single) EventAck.
 	 */
 	if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
-		devtprintk((MYIOC_s_WARN_FMT
+		devtverboseprintk((MYIOC_s_WARN_FMT
 			"EventAck required\n",ioc->name));
 		if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
-			devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
+			devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
 					ioc->name, ii));
 		}
 	}
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index f4197a9962a..fb22b28d1ab 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -719,12 +719,18 @@ typedef struct _mpt_sge {
 #define dhsprintk(x)
 #endif
 
-#ifdef MPT_DEBUG_EVENTS
+#if defined(MPT_DEBUG_EVENTS) || defined(MPT_DEBUG_VERBOSE_EVENTS)
 #define devtprintk(x)  printk x
 #else
 #define devtprintk(x)
 #endif
 
+#ifdef MPT_DEBUG_VERBOSE_EVENTS
+#define devtverboseprintk(x)  printk x
+#else
+#define devtverboseprintk(x)
+#endif
+
 #ifdef MPT_DEBUG_RESET
 #define drsprintk(x)  printk x
 #else
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 9b64e07400d..3d555b724ed 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -497,7 +497,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 	 if (event == 0x21 ) {
 		ioc->aen_event_read_flag=1;
 		dctlprintk(("Raised SIGIO to application\n"));
-		devtprintk(("Raised SIGIO to application\n"));
+		devtverboseprintk(("Raised SIGIO to application\n"));
 		kill_fasync(&async_queue, SIGIO, POLL_IN);
 		return 1;
 	 }
@@ -515,7 +515,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 	if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
 		ioc->aen_event_read_flag=1;
 		dctlprintk(("Raised SIGIO to application\n"));
-		devtprintk(("Raised SIGIO to application\n"));
+		devtverboseprintk(("Raised SIGIO to application\n"));
 		kill_fasync(&async_queue, SIGIO, POLL_IN);
 	}
 	return 1;
@@ -2968,7 +2968,7 @@ static int __init mptctl_init(void)
 	}
 
 	if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
-		devtprintk((KERN_INFO MYNAM
+		devtverboseprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
 	}
 
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 8ea12ea652a..5a30621051c 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -941,7 +941,7 @@ mptfc_init(void)
 	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
 
 	if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
-		devtprintk((KERN_INFO MYNAM
+		devtverboseprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
 	}
 
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 74f4368c79a..ba93ef13a41 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1993,7 +1993,7 @@ mptsas_init(void)
 	mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
 
 	if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
-		devtprintk((KERN_INFO MYNAM
+		devtverboseprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
 	}
 
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index a2183103b8c..77289fd07fe 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -2531,7 +2531,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 	int work_count;
 	unsigned long flags;
 
-	devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
+	devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
 			ioc->name, event));
 
 	if (ioc->sh == NULL ||
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 437189f871b..9af69dd66f8 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -1057,7 +1057,7 @@ mptspi_init(void)
 	mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
 
 	if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) {
-		devtprintk((KERN_INFO MYNAM
+		devtverboseprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
 	}
 
-- 
cgit v1.2.3-70-g09d2


From c972c70fa03097be4235fc441658290a3b7af06f Mon Sep 17 00:00:00 2001
From: "Moore, Eric" <Eric.Moore@lsil.com>
Date: Tue, 14 Mar 2006 09:14:06 -0700
Subject: [SCSI] fusion - static fix's

Patch previously provided from Adrian Bunk <bunk@stusta.de>,
moving some functions to static.  This is already in
the -mm tree.

Signed-off-by: Eric Moore <Eric.Moore@lsil.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
---
 drivers/message/fusion/mptbase.c | 4 ++--
 drivers/message/fusion/mptbase.h | 1 -
 drivers/message/fusion/mptctl.c  | 2 +-
 3 files changed, 3 insertions(+), 4 deletions(-)

(limited to 'drivers/message/fusion/mptbase.h')

diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 9960ef10366..266414ca281 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -180,6 +180,7 @@ static void	mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
 static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static int	mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 
 /* module entry point */
 static int  __init    fusion_init  (void);
@@ -4871,7 +4872,7 @@ done_and_free:
 	return rc;
 }
 
-int
+static int
 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
 {
 	IOCPage3_t		*pIoc3;
@@ -6453,7 +6454,6 @@ EXPORT_SYMBOL(mpt_stm_index);
 EXPORT_SYMBOL(mpt_HardResetHandler);
 EXPORT_SYMBOL(mpt_config);
 EXPORT_SYMBOL(mpt_findImVolumes);
-EXPORT_SYMBOL(mpt_read_ioc_pg_3);
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
 EXPORT_SYMBOL(mptbase_sas_persist_operation);
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index fb22b28d1ab..2b9c8b5522f 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -1027,7 +1027,6 @@ extern int	 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
 extern void	 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
 extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc);
 extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
-extern int	 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 extern int	 mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
 
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 3d555b724ed..b4967bb8a7d 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -140,7 +140,7 @@ static int  mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
  * Event Handler function
  */
 static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
-struct fasync_struct *async_queue=NULL;
+static struct fasync_struct *async_queue=NULL;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
-- 
cgit v1.2.3-70-g09d2


From 914c2d8e597798d62c2e0a3cba737bf6f611eecf Mon Sep 17 00:00:00 2001
From: "Moore, Eric" <Eric.Moore@lsil.com>
Date: Tue, 14 Mar 2006 09:19:36 -0700
Subject: [SCSI] fusion - removing target_id/bus_id from the VirtDevice
 structure

It makes no sense in keeping the target_id and bus_id
in the VirtDevice structure, when it can be obtained
from the VirtTarget structure.

In addition, this patch fix's couple compilation bugs
in mptfc.c when MPT_DEBUG_FC is enabled. This
provided by Micheal Reed.

Signed-off-by: Eric Moore <Eric.Moore@lsil.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
---
 drivers/message/fusion/mptbase.h  |  5 +----
 drivers/message/fusion/mptfc.c    | 33 ++++++++-------------------------
 drivers/message/fusion/mptsas.c   | 24 +++++++++++-------------
 drivers/message/fusion/mptscsih.c | 19 ++++++++-----------
 drivers/message/fusion/mptspi.c   |  4 ++--
 5 files changed, 30 insertions(+), 55 deletions(-)

(limited to 'drivers/message/fusion/mptbase.h')

diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 2b9c8b5522f..9b58234add3 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -347,10 +347,7 @@ typedef struct _VirtTarget {
 } VirtTarget;
 
 typedef struct _VirtDevice {
-	VirtTarget	 	*vtarget;
-	u8			 ioc_id;
-	u8			 bus_id;
-	u8			 target_id;
+	VirtTarget		*vtarget;
 	u8			 configured_lun;
 	u32			 lun;
 } VirtDevice;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 5a30621051c..b343f2a68b1 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -348,24 +348,6 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
 	return 0;
 }
 
-static void
-mptfc_remap_sdev(struct scsi_device *sdev, void *arg)
-{
-	VirtDevice		*vdev;
-	VirtTarget		*vtarget;
-	struct scsi_target	*starget;
-
-	starget = scsi_target(sdev);
-	if (starget->hostdata == arg) {
-		vtarget = arg;
-		vdev = sdev->hostdata;
-		if (vdev) {
-			vdev->bus_id = vtarget->bus_id;
-			vdev->target_id = vtarget->target_id;
-		}
-	}
-}
-
 static void
 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 {
@@ -423,8 +405,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 				if (vtarget) {
 					vtarget->target_id = pg0->CurrentTargetID;
 					vtarget->bus_id = pg0->CurrentBus;
-					starget_for_each_device(ri->starget,
-						vtarget,mptfc_remap_sdev);
 				}
 				ri->remap_needed = 0;
 			}
@@ -432,7 +412,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 				"mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
 				"rport tid %d, tmo %d\n",
 					ioc->name,
-					oc->sh->host_no,
+					ioc->sh->host_no,
 					pg0->PortIdentifier,
 					pg0->WWNN,
 					pg0->WWPN,
@@ -553,23 +533,26 @@ mptfc_slave_alloc(struct scsi_device *sdev)
 	}
 
 	vdev->vtarget = vtarget;
-	vdev->ioc_id = hd->ioc->id;
 	vdev->lun = sdev->lun;
-	vdev->target_id = vtarget->target_id;
-	vdev->bus_id = vtarget->bus_id;
 
 	spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
 
 	vtarget->num_luns++;
 
+#ifdef DMPT_DEBUG_FC
+	 {
+	struct mptfc_rport_info *ri;
+	ri = *((struct mptfc_rport_info **)rport->dd_data);
 	dfcprintk ((MYIOC_s_INFO_FMT
 		"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
 	        "CurrentTargetID %d, %x %llx %llx\n",
-		ioc->name,
+		hd->ioc->name,
 		sdev->host->host_no,
 		vtarget->num_luns,
 		sdev->id, ri->pg0.CurrentTargetID,
 		ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
+	}
+#endif
 
 	return 0;
 }
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index ba93ef13a41..ba555a60bf7 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -350,6 +350,7 @@ mptsas_slave_alloc(struct scsi_device *sdev)
 	VirtTarget		*vtarget;
 	VirtDevice		*vdev;
 	struct scsi_target 	*starget;
+	u32			target_id;
 	int i;
 
 	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
@@ -358,10 +359,10 @@ mptsas_slave_alloc(struct scsi_device *sdev)
 				hd->ioc->name, sizeof(VirtDevice));
 		return -ENOMEM;
 	}
-	vdev->ioc_id = hd->ioc->id;
 	sdev->hostdata = vdev;
 	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
+	vtarget->ioc_id = hd->ioc->id;
 	vdev->vtarget = vtarget;
 	if (vtarget->num_luns == 0) {
 		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
@@ -372,8 +373,8 @@ mptsas_slave_alloc(struct scsi_device *sdev)
 	  RAID volumes placed beyond the last expected port.
 	*/
 	if (sdev->channel == hd->ioc->num_ports) {
-		vdev->target_id = sdev->id;
-		vdev->bus_id = 0;
+		target_id = sdev->id;
+		vtarget->bus_id = 0;
 		vdev->lun = 0;
 		goto out;
 	}
@@ -384,11 +385,10 @@ mptsas_slave_alloc(struct scsi_device *sdev)
 		for (i = 0; i < p->num_phys; i++) {
 			if (p->phy_info[i].attached.sas_address ==
 					rphy->identify.sas_address) {
-				vdev->target_id =
-					p->phy_info[i].attached.id;
-				vdev->bus_id = p->phy_info[i].attached.channel;
+				target_id = p->phy_info[i].attached.id;
+				vtarget->bus_id = p->phy_info[i].attached.channel;
 				vdev->lun = sdev->lun;
- 	mutex_unlock(&hd->ioc->sas_topology_mutex);
+				mutex_unlock(&hd->ioc->sas_topology_mutex);
 				goto out;
 			}
 		}
@@ -399,9 +399,7 @@ mptsas_slave_alloc(struct scsi_device *sdev)
 	return -ENXIO;
 
  out:
-	vtarget->ioc_id = vdev->ioc_id;
-	vtarget->target_id = vdev->target_id;
-	vtarget->bus_id = vdev->bus_id;
+	vtarget->target_id = target_id;
 	vtarget->num_luns++;
 	return 0;
 }
@@ -444,8 +442,8 @@ mptsas_slave_destroy(struct scsi_device *sdev)
 	if (vdev->configured_lun){
 		if (mptscsih_TMHandler(hd,
 		     MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-		     vdev->bus_id,
-		     vdev->target_id,
+		     vdev->vtarget->bus_id,
+		     vdev->vtarget->target_id,
 		     0, 0, 5 /* 5 second timeout */)
 		     < 0){
 
@@ -455,7 +453,7 @@ mptsas_slave_destroy(struct scsi_device *sdev)
 			printk(MYIOC_s_WARN_FMT
 		       "Error processing TaskMgmt id=%d TARGET_RESET\n",
 				hd->ioc->name,
-				vdev->target_id);
+				vdev->vtarget->target_id);
 
 			hd->tmPending = 0;
 			hd->tmState = TM_STATE_NONE;
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 77289fd07fe..c99a918feb5 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -887,7 +887,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 			dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
 					hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
 
-			if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
+			if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
 				continue;
 
 			/* Cleanup
@@ -1285,8 +1285,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 
 	/* Use the above information to set up the message frame
 	 */
-	pScsiReq->TargetID = (u8) vdev->target_id;
-	pScsiReq->Bus = vdev->bus_id;
+	pScsiReq->TargetID = (u8) vdev->vtarget->target_id;
+	pScsiReq->Bus = vdev->vtarget->bus_id;
 	pScsiReq->ChainOffset = 0;
 	if (vdev->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)
 		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
@@ -1701,7 +1701,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-		vdev->bus_id, vdev->target_id, vdev->lun,
+		vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
 		ctx2abort, mptscsih_get_tm_timeout(ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
@@ -1752,7 +1752,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-		vdev->bus_id, vdev->target_id,
+		vdev->vtarget->bus_id, vdev->vtarget->target_id,
 		0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
@@ -1803,7 +1803,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-		vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
+		vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -2162,9 +2162,6 @@ mptscsih_slave_alloc(struct scsi_device *sdev)
 		return -ENOMEM;
 	}
 
-	vdev->ioc_id = hd->ioc->id;
-	vdev->target_id = sdev->id;
-	vdev->bus_id = sdev->channel;
 	vdev->lun = sdev->lun;
 	sdev->hostdata = vdev;
 
@@ -3366,8 +3363,8 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 	iocmd.data_dma = -1;
 	iocmd.size = 0;
 	iocmd.rsvd = iocmd.rsvd2 = 0;
-	iocmd.bus = vdevice->bus_id;
-	iocmd.id = vdevice->target_id;
+	iocmd.bus = vdevice->vtarget->bus_id;
+	iocmd.id = vdevice->vtarget->target_id;
 	iocmd.lun = (u8)vdevice->lun;
 
 	if ((vdevice->vtarget->type == TYPE_DISK) &&
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 9af69dd66f8..09c745b19cc 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -343,9 +343,9 @@ static int mptspi_slave_alloc(struct scsi_device *sdev)
 		sdev->no_uld_attach = 1;
 		vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
 		/* The real channel for this device is zero */
-		vdev->bus_id = 0;
+		vdev->vtarget->bus_id = 0;
 		/* The actual physdisknum (for RAID passthrough) */
-		vdev->target_id = physdisknum;
+		vdev->vtarget->target_id = physdisknum;
 	}
 
 	return 0;
-- 
cgit v1.2.3-70-g09d2


From e6b2d76a49f0ee48527691867d8af2b8f9c10452 Mon Sep 17 00:00:00 2001
From: "Moore, Eric" <Eric.Moore@lsil.com>
Date: Tue, 14 Mar 2006 09:14:24 -0700
Subject: [SCSI] fusion - expander hotplug suport in mptsas module

This adds support for hot adding and removing
expanders, and its associated attached devices.
When there is a change in topology,
the fusion firmware sends the
MPI_EVENT_SAS_DISCOVERY event to the driver.
The driver will read firmware config pages
to determine what changes took place, and refresh
drivers view of the world stored in ioc->sas_topology.

Here is the details of the action the driver does:

(1) Expander Added :  The mptsas_discovery_work
workqueue is called.  Config pages read, and
ioc->sas_topology is refreshed.  The sas_phy_add()
is called for each phy of the expander.  The
expanders attached devices are added via
sas_rphy_add().  Added end devices are handled within
the MPT_ADD_DEVICE logic in  mptsas_hotplug_work
workqueue.

(2) Expander Delete : The sas_rphy_delete() will be
called for the top most compenent of the parent that the
expander is attached to.  The sas_rphy_delete call
will delete all the children phys, rphys, and end devices.
This is handled from mptsas_discovery_work workqueue.

Signed-off-by: Eric Moore <Eric.Moore@lsil.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
---
 drivers/message/fusion/mptbase.h |   4 +
 drivers/message/fusion/mptsas.c  | 354 +++++++++++++++++++++++++++++++--------
 2 files changed, 289 insertions(+), 69 deletions(-)

(limited to 'drivers/message/fusion/mptbase.h')

diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 9b58234add3..892af47cb91 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -619,6 +619,10 @@ typedef struct _MPT_ADAPTER
 	struct net_device	*netdev;
 	struct list_head	 sas_topology;
 	struct mutex		 sas_topology_mutex;
+	struct mutex		 sas_discovery_mutex;
+	u8			 sas_discovery_runtime;
+	u8			 sas_discovery_ignore_events;
+	int			 sas_index; /* index refrencing */
 	MPT_SAS_MGMT		 sas_mgmt;
 	int			 num_ports;
 	struct work_struct	 mptscsih_persistTask;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 289fcdbe89b..be4eb8a308b 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -108,6 +108,11 @@ struct mptsas_hotplug_event {
 	u8			phys_disk_num_valid;
 };
 
+struct mptsas_discovery_event {
+	struct work_struct	work;
+	MPT_ADAPTER		*ioc;
+};
+
 /*
  * SAS topology structures
  *
@@ -163,7 +168,6 @@ struct mptsas_enclosure {
 	u8	sep_channel;		/* SEP channel logical channel id */
 };
 
-
 #ifdef SASDEBUG
 static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
 {
@@ -273,6 +277,27 @@ static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
 	return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
 }
 
+/*
+ * mptsas_find_portinfo_by_handle
+ *
+ * This function should be called with the sas_topology_mutex already held
+ */
+static struct mptsas_portinfo *
+mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
+{
+	struct mptsas_portinfo *port_info, *rc=NULL;
+	int i;
+
+	list_for_each_entry(port_info, &ioc->sas_topology, list)
+		for (i = 0; i < port_info->num_phys; i++)
+			if (port_info->phy_info[i].identify.handle == handle) {
+				rc = port_info;
+				goto out;
+			}
+ out:
+	return rc;
+}
+
 static int
 mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
 		u32 form, u32 form_specific)
@@ -423,32 +448,8 @@ mptsas_slave_destroy(struct scsi_device *sdev)
 {
 	struct Scsi_Host *host = sdev->host;
 	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
-	struct sas_rphy *rphy;
-	struct mptsas_portinfo *p;
-	int i;
 	VirtDevice *vdev;
 
-	/*
-	 * Handle hotplug removal case.
-	 * We need to clear out attached data structure.
-	 */
-	rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
-
-	mutex_lock(&hd->ioc->sas_topology_mutex);
-	list_for_each_entry(p, &hd->ioc->sas_topology, list) {
-		for (i = 0; i < p->num_phys; i++) {
-			if (p->phy_info[i].attached.sas_address ==
-					rphy->identify.sas_address) {
-				memset(&p->phy_info[i].attached, 0,
-				    sizeof(struct mptsas_devinfo));
-				p->phy_info[i].rphy = NULL;
-				goto out;
-			}
-		}
-	}
-
- out:
-	mutex_unlock(&hd->ioc->sas_topology_mutex);
 	/*
 	 * Issue target reset to flush firmware outstanding commands.
 	 */
@@ -1044,7 +1045,6 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
 	phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
 	phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
 
-
  out_free_consistent:
 	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
 			    buffer, dma_handle);
@@ -1134,12 +1134,19 @@ mptsas_parse_device_info(struct sas_identify *identify,
 static int mptsas_probe_one_phy(struct device *dev,
 		struct mptsas_phyinfo *phy_info, int index, int local)
 {
+	MPT_ADAPTER *ioc;
 	struct sas_phy *phy;
 	int error;
 
-	phy = sas_phy_alloc(dev, index);
-	if (!phy)
-		return -ENOMEM;
+	if (!dev)
+		return -ENODEV;
+
+	if (!phy_info->phy) {
+		phy = sas_phy_alloc(dev, index);
+		if (!phy)
+			return -ENOMEM;
+	} else
+		phy = phy_info->phy;
 
 	phy->port_identifier = phy_info->port_id;
 	mptsas_parse_device_info(&phy->identify, &phy_info->identify);
@@ -1225,19 +1232,35 @@ static int mptsas_probe_one_phy(struct device *dev,
 		break;
 	}
 
-	if (local)
-		phy->local_attached = 1;
+	if (!phy_info->phy) {
 
-	error = sas_phy_add(phy);
-	if (error) {
-		sas_phy_free(phy);
-		return error;
+		if (local)
+			phy->local_attached = 1;
+
+		error = sas_phy_add(phy);
+		if (error) {
+			sas_phy_free(phy);
+			return error;
+		}
+		phy_info->phy = phy;
 	}
-	phy_info->phy = phy;
 
-	if (phy_info->attached.handle) {
+	if ((phy_info->attached.handle) &&
+	    (!phy_info->rphy)) {
+
 		struct sas_rphy *rphy;
 
+		ioc = phy_to_ioc(phy_info->phy);
+
+		/*
+		 * Let the hotplug_work thread handle processing
+		 * the adding/removing of devices that occur
+		 * after start of day.
+		 */
+		if (ioc->sas_discovery_runtime &&
+			mptsas_is_end_device(&phy_info->attached))
+			return 0;
+
 		rphy = sas_rphy_alloc(phy);
 		if (!rphy)
 			return 0; /* non-fatal: an rphy can be added later */
@@ -1256,24 +1279,37 @@ static int mptsas_probe_one_phy(struct device *dev,
 }
 
 static int
-mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
+mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
 {
-	struct mptsas_portinfo *port_info;
+	struct mptsas_portinfo *port_info, *hba;
 	u32 handle = 0xFFFF;
 	int error = -ENOMEM, i;
 
-	port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
-	if (!port_info)
+	hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
+	if (! hba)
 		goto out;
 
-	error = mptsas_sas_io_unit_pg0(ioc, port_info);
+	error = mptsas_sas_io_unit_pg0(ioc, hba);
 	if (error)
 		goto out_free_port_info;
 
-	ioc->num_ports = port_info->num_phys;
 	mutex_lock(&ioc->sas_topology_mutex);
-	list_add_tail(&port_info->list, &ioc->sas_topology);
+	port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
+	if (!port_info) {
+		port_info = hba;
+		list_add_tail(&port_info->list, &ioc->sas_topology);
+	} else {
+		port_info->handle = hba->handle;
+		for (i = 0; i < hba->num_phys; i++)
+			port_info->phy_info[i].negotiated_link_rate =
+				hba->phy_info[i].negotiated_link_rate;
+		if (hba->phy_info)
+			kfree(hba->phy_info);
+		kfree(hba);
+		hba = NULL;
+	}
 	mutex_unlock(&ioc->sas_topology_mutex);
+	ioc->num_ports = port_info->num_phys;
 
 	for (i = 0; i < port_info->num_phys; i++) {
 		mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
@@ -1296,38 +1332,49 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
 		}
 
 		mptsas_probe_one_phy(&ioc->sh->shost_gendev,
-				     &port_info->phy_info[i], *index, 1);
-		(*index)++;
+		    &port_info->phy_info[i], ioc->sas_index, 1);
+		ioc->sas_index++;
 	}
 
 	return 0;
 
  out_free_port_info:
-	kfree(port_info);
+	if (hba)
+		kfree(hba);
  out:
 	return error;
 }
 
 static int
-mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
+mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
 {
-	struct mptsas_portinfo *port_info, *p;
+	struct mptsas_portinfo *port_info, *p, *ex;
 	int error = -ENOMEM, i, j;
 
-	port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
-	if (!port_info)
+	ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
+	if (!ex)
 		goto out;
 
-	error = mptsas_sas_expander_pg0(ioc, port_info,
+	error = mptsas_sas_expander_pg0(ioc, ex,
 		(MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
 		 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
 	if (error)
 		goto out_free_port_info;
 
-	*handle = port_info->handle;
+	*handle = ex->handle;
 
 	mutex_lock(&ioc->sas_topology_mutex);
-	list_add_tail(&port_info->list, &ioc->sas_topology);
+	port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
+	if (!port_info) {
+		port_info = ex;
+		list_add_tail(&port_info->list, &ioc->sas_topology);
+	} else {
+		port_info->handle = ex->handle;
+		if (ex->phy_info)
+			kfree(ex->phy_info);
+		kfree(ex);
+		ex = NULL;
+	}
 	mutex_unlock(&ioc->sas_topology_mutex);
 
 	for (i = 0; i < port_info->num_phys; i++) {
@@ -1374,28 +1421,101 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
 		mutex_unlock(&ioc->sas_topology_mutex);
 
 		mptsas_probe_one_phy(parent, &port_info->phy_info[i],
-				     *index, 0);
-		(*index)++;
+		    ioc->sas_index, 0);
+		ioc->sas_index++;
 	}
 
 	return 0;
 
  out_free_port_info:
-	kfree(port_info->phy_info);
-	kfree(port_info);
+	if (ex) {
+		if (ex->phy_info)
+			kfree(ex->phy_info);
+		kfree(ex);
+	}
  out:
 	return error;
 }
 
+/*
+ * mptsas_delete_expander_phys
+ *
+ *
+ * This will traverse topology, and remove expanders
+ * that are no longer present
+ */
+static void
+mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
+{
+	struct mptsas_portinfo buffer;
+	struct mptsas_portinfo *port_info, *n, *parent;
+	int i;
+
+	mutex_lock(&ioc->sas_topology_mutex);
+	list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
+
+		if (port_info->phy_info &&
+		    (!(port_info->phy_info[0].identify.device_info &
+		    MPI_SAS_DEVICE_INFO_SMP_TARGET)))
+			continue;
+
+		if (mptsas_sas_expander_pg0(ioc, &buffer,
+		     (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
+		     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
+
+			/*
+			 * Obtain the port_info instance to the parent port
+			 */
+			parent = mptsas_find_portinfo_by_handle(ioc,
+			    port_info->phy_info[0].identify.handle_parent);
+
+			if (!parent)
+				goto next_port;
+
+			/*
+			 * Delete rphys in the parent that point
+			 * to this expander.  The transport layer will
+			 * cleanup all the children.
+			 */
+			for (i = 0; i < parent->num_phys; i++) {
+				if ((!parent->phy_info[i].rphy) ||
+				    (parent->phy_info[i].attached.sas_address !=
+				   port_info->phy_info[i].identify.sas_address))
+					continue;
+				sas_rphy_delete(parent->phy_info[i].rphy);
+				memset(&parent->phy_info[i].attached, 0,
+				    sizeof(struct mptsas_devinfo));
+				parent->phy_info[i].rphy = NULL;
+				parent->phy_info[i].starget = NULL;
+			}
+ next_port:
+			list_del(&port_info->list);
+			if (port_info->phy_info)
+				kfree(port_info->phy_info);
+			kfree(port_info);
+		}
+		/*
+		* Free this memory allocated from inside
+		* mptsas_sas_expander_pg0
+		*/
+		if (buffer.phy_info)
+			kfree(buffer.phy_info);
+	}
+	mutex_unlock(&ioc->sas_topology_mutex);
+}
+
+/*
+ * Start of day discovery
+ */
 static void
 mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
 {
 	u32 handle = 0xFFFF;
-	int index = 0;
 	int i;
 
-	mptsas_probe_hba_phys(ioc, &index);
-	while (!mptsas_probe_expander_phys(ioc, &handle, &index))
+	mutex_lock(&ioc->sas_discovery_mutex);
+	mptsas_probe_hba_phys(ioc);
+	while (!mptsas_probe_expander_phys(ioc, &handle))
 		;
 	/*
 	  Reporting RAID volumes.
@@ -1409,7 +1529,29 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
 		    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
 	}
  out:
-	return;
+	mutex_unlock(&ioc->sas_discovery_mutex);
+}
+
+/*
+ * Work queue thread to handle Runtime discovery
+ * Mere purpose is the hot add/delete of expanders
+ */
+static void
+mptscsih_discovery_work(void * arg)
+{
+	struct mptsas_discovery_event *ev = arg;
+	MPT_ADAPTER *ioc = ev->ioc;
+	u32 handle = 0xFFFF;
+
+	mutex_lock(&ioc->sas_discovery_mutex);
+	ioc->sas_discovery_runtime=1;
+	mptsas_delete_expander_phys(ioc);
+	mptsas_probe_hba_phys(ioc);
+	while (!mptsas_probe_expander_phys(ioc, &handle))
+		;
+	kfree(ev);
+	ioc->sas_discovery_runtime=0;
+	mutex_unlock(&ioc->sas_discovery_mutex);
 }
 
 static struct mptsas_phyinfo *
@@ -1427,10 +1569,8 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
 		(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
 		 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
 		parent_handle);
-	if (error) {
-		printk("mptsas: failed to retrieve device page\n");
+	if (error)
 		return NULL;
-	}
 
 	/*
 	 * The phy_info structures are never deallocated during lifetime of
@@ -1502,6 +1642,10 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
 			mptsas_reprobe_lun);
 }
 
+
+/*
+ * Work queue thread to handle SAS hotplug events
+ */
 static void
 mptsas_hotplug_work(void *arg)
 {
@@ -1514,10 +1658,13 @@ mptsas_hotplug_work(void *arg)
 	struct mptsas_devinfo sas_device;
 	VirtTarget *vtarget;
 
+	mutex_lock(&ioc->sas_discovery_mutex);
+
 	switch (ev->event_type) {
 	case MPTSAS_DEL_DEVICE:
 
 		phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
+
 		/*
 		 * Sanity checks, for non-existing phys and remote rphys.
 		 */
@@ -1569,8 +1716,36 @@ mptsas_hotplug_work(void *arg)
 
 		phy_info = mptsas_find_phyinfo_by_parent(ioc,
 				sas_device.handle_parent, sas_device.phy_id);
-		if (!phy_info)
-			break;
+
+		if (!phy_info) {
+			u32 handle = 0xFFFF;
+
+			/*
+			* Its possible when an expander has been hot added
+			* containing attached devices, the sas firmware
+			* may send a RC_ADDED event prior to the
+			* DISCOVERY STOP event. If that occurs, our
+			* view of the topology in the driver in respect to this
+			* expander might of not been setup, and we hit this
+			* condition.
+			* Therefore, this code kicks off discovery to
+			* refresh the data.
+			* Then again, we check whether the parent phy has
+			* been created.
+			*/
+			ioc->sas_discovery_runtime=1;
+			mptsas_delete_expander_phys(ioc);
+			mptsas_probe_hba_phys(ioc);
+			while (!mptsas_probe_expander_phys(ioc, &handle))
+				;
+			ioc->sas_discovery_runtime=0;
+
+			phy_info = mptsas_find_phyinfo_by_parent(ioc,
+				sas_device.handle_parent, sas_device.phy_id);
+			if (!phy_info)
+				break;
+		}
+
 		if (phy_info->starget) {
 			vtarget = phy_info->starget->hostdata;
 
@@ -1604,7 +1779,6 @@ mptsas_hotplug_work(void *arg)
 		       "attaching %s device, channel %d, id %d, phy %d\n",
 		       ioc->name, ds, ev->channel, ev->id, ev->phy_id);
 
-
 		rphy = sas_rphy_alloc(phy_info->phy);
 		if (!rphy)
 			break; /* non-fatal: an rphy can be added later */
@@ -1654,6 +1828,7 @@ mptsas_hotplug_work(void *arg)
 	}
 
 	kfree(ev);
+	mutex_unlock(&ioc->sas_discovery_mutex);
 }
 
 static void
@@ -1767,6 +1942,32 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
 	schedule_work(&ev->work);
 }
 
+static void
+mptscsih_send_discovery(MPT_ADAPTER *ioc,
+	EVENT_DATA_SAS_DISCOVERY *discovery_data)
+{
+	struct mptsas_discovery_event *ev;
+
+	/*
+	 * DiscoveryStatus
+	 *
+	 * This flag will be non-zero when firmware
+	 * kicks off discovery, and return to zero
+	 * once its completed.
+	 */
+	if (discovery_data->DiscoveryStatus)
+		return;
+
+	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev)
+		return;
+	memset(ev,0,sizeof(struct mptsas_discovery_event));
+	INIT_WORK(&ev->work, mptscsih_discovery_work, ev);
+	ev->ioc = ioc;
+	schedule_work(&ev->work);
+};
+
+
 static int
 mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 {
@@ -1776,6 +1977,17 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 	if (!ioc->sh)
 		goto out;
 
+	/*
+	 * sas_discovery_ignore_events
+	 *
+	 * This flag is to prevent anymore processing of
+	 * sas events once mptsas_remove function is called.
+	 */
+	if (ioc->sas_discovery_ignore_events) {
+		rc = mptscsih_event_process(ioc, reply);
+		goto out;
+	}
+
 	switch (event) {
 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
 		mptscsih_send_sas_event(ioc,
@@ -1792,6 +2004,9 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 		schedule_work(&ioc->mptscsih_persistTask);
 		break;
 	 case MPI_EVENT_SAS_DISCOVERY:
+		mptscsih_send_discovery(ioc,
+			(EVENT_DATA_SAS_DISCOVERY *)reply->Data);
+		break;
 	default:
 		rc = mptscsih_event_process(ioc, reply);
 		break;
@@ -1893,7 +2108,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	INIT_LIST_HEAD(&ioc->sas_topology);
 	mutex_init(&ioc->sas_topology_mutex);
-
+	mutex_init(&ioc->sas_discovery_mutex);
 	mutex_init(&ioc->sas_mgmt.mutex);
 	init_completion(&ioc->sas_mgmt.done);
 
@@ -2019,6 +2234,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
 	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 	struct mptsas_portinfo *p, *n;
 
+	ioc->sas_discovery_ignore_events=1;
 	sas_remove_host(ioc->sh);
 
 	mutex_lock(&ioc->sas_topology_mutex);
-- 
cgit v1.2.3-70-g09d2


From 9dec70e053613c31e8feab9e14607eaaed99d77c Mon Sep 17 00:00:00 2001
From: "Moore, Eric" <Eric.Moore@lsil.com>
Date: Tue, 14 Mar 2006 09:14:26 -0700
Subject: [SCSI] fusion - bump version

version bump

Signed-off-by: Eric Moore <Eric.Moore@lsil.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
---
 drivers/message/fusion/mptbase.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'drivers/message/fusion/mptbase.h')

diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 892af47cb91..be7e8501b53 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.03.07"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.07"
+#define MPT_LINUX_VERSION_COMMON	"3.03.08"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.08"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
-- 
cgit v1.2.3-70-g09d2