svn commit: r316087 - stable/10/sys/dev/isp

Alexander Motin mav at FreeBSD.org
Tue Mar 28 10:22:57 UTC 2017


Author: mav
Date: Tue Mar 28 10:22:55 2017
New Revision: 316087
URL: https://svnweb.freebsd.org/changeset/base/316087

Log:
  MFC r315234: Improvements around attach, reset and detach.
  
  This change fixes DMA resource leak on driver unload.  Also it removes
  DMA resources allocation for hardcoded number of requests before fetching
  the real number from firmware.  Also it prepares ground for more flexible
  IRQs allocation according to firmware capabilities.

Modified:
  stable/10/sys/dev/isp/isp.c
  stable/10/sys/dev/isp/isp_freebsd.c
  stable/10/sys/dev/isp/isp_freebsd.h
  stable/10/sys/dev/isp/isp_library.c
  stable/10/sys/dev/isp/isp_library.h
  stable/10/sys/dev/isp/isp_pci.c
  stable/10/sys/dev/isp/isp_sbus.c
  stable/10/sys/dev/isp/ispvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/isp/isp.c
==============================================================================
--- stable/10/sys/dev/isp/isp.c	Tue Mar 28 10:19:52 2017	(r316086)
+++ stable/10/sys/dev/isp/isp.c	Tue Mar 28 10:22:55 2017	(r316087)
@@ -178,13 +178,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	const char *btype = "????";
 	static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
 
-	isp->isp_state = ISP_NILSTATE;
-	if (isp->isp_dead) {
-		isp_shutdown(isp);
-		ISP_DISABLE_INTS(isp);
-		return;
-	}
-
 	/*
 	 * Basic types (SCSI, FibreChannel and PCI or SBus)
 	 * have been set in the MD code. We figure out more
@@ -195,56 +188,10 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	 * for SCSI adapters and do other settings for the 2100.
 	 */
 
+	isp->isp_state = ISP_NILSTATE;
 	ISP_DISABLE_INTS(isp);
 
 	/*
-	 * Pick an initial maxcmds value which will be used
-	 * to allocate xflist pointer space. It may be changed
-	 * later by the firmware.
-	 */
-	if (IS_24XX(isp)) {
-		isp->isp_maxcmds = 4096;
-	} else if (IS_2322(isp)) {
-		isp->isp_maxcmds = 2048;
-	} else if (IS_23XX(isp) || IS_2200(isp)) {
-		isp->isp_maxcmds = 1024;
- 	} else {
-		isp->isp_maxcmds = 512;
-	}
-
-	/*
-	 * Set up DMA for the request and response queues.
-	 *
-	 * We do this now so we can use the request queue
-	 * for dma to load firmware from.
-	 */
-	if (ISP_MBOXDMASETUP(isp) != 0) {
-		isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
-		return;
-	}
-
-	/*
-	 * Set up default request/response queue in-pointer/out-pointer
-	 * register indices.
-	 */
-	if (IS_24XX(isp)) {
-		isp->isp_rqstinrp = BIU2400_REQINP;
-		isp->isp_rqstoutrp = BIU2400_REQOUTP;
-		isp->isp_respinrp = BIU2400_RSPINP;
-		isp->isp_respoutrp = BIU2400_RSPOUTP;
-	} else if (IS_23XX(isp)) {
-		isp->isp_rqstinrp = BIU_REQINP;
-		isp->isp_rqstoutrp = BIU_REQOUTP;
-		isp->isp_respinrp = BIU_RSPINP;
-		isp->isp_respoutrp = BIU_RSPOUTP;
-	} else {
-		isp->isp_rqstinrp = INMAILBOX4;
-		isp->isp_rqstoutrp = OUTMAILBOX4;
-		isp->isp_respinrp = OUTMAILBOX5;
-		isp->isp_respoutrp = INMAILBOX5;
-	}
-
-	/*
 	 * Put the board into PAUSE mode (so we can read the SXP registers
 	 * or write FPM/FBM registers).
 	 */
@@ -468,7 +415,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 				isp->isp_clock = isp->isp_mdvec->dv_clock;
 			}
 		}
-
 	}
 
 	/*
@@ -477,11 +423,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	isp->isp_intcnt = isp->isp_intbogus = 0;
 
 	/*
-	 * Do MD specific pre initialization
-	 */
-	ISP_RESET0(isp);
-
-	/*
 	 * Hit the chip over the head with hammer,
 	 * and give it a chance to recover.
 	 */
@@ -513,7 +454,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 			}
 		}
 		if (val & BIU2400_DMA_ACTIVE) {
-			ISP_RESET0(isp);
 			isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
 			return;
 		}
@@ -533,7 +473,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 			}
 		}
 		if (val & BIU2400_SOFT_RESET) {
-			ISP_RESET0(isp);
 			isp_prt(isp, ISP_LOGERR, "Failed to come out of reset");
 			return;
 		}
@@ -572,7 +511,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 		ISP_DELAY(100);
 		if (--loops < 0) {
 			ISP_DUMPREGS(isp, "chip reset timed out");
-			ISP_RESET0(isp);
 			return;
 		}
 	}
@@ -613,7 +551,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 			}
 		}
 		if (val != 0) {
-			ISP_RESET0(isp);
 			isp_prt(isp, ISP_LOGERR, "reset didn't clear");
 			return;
 		}
@@ -655,6 +592,26 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 		ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
 	}
 
+	/*
+	 * Set up default request/response queue in-pointer/out-pointer
+	 * register indices.
+	 */
+	if (IS_24XX(isp)) {
+		isp->isp_rqstinrp = BIU2400_REQINP;
+		isp->isp_rqstoutrp = BIU2400_REQOUTP;
+		isp->isp_respinrp = BIU2400_RSPINP;
+		isp->isp_respoutrp = BIU2400_RSPOUTP;
+	} else if (IS_23XX(isp)) {
+		isp->isp_rqstinrp = BIU_REQINP;
+		isp->isp_rqstoutrp = BIU_REQOUTP;
+		isp->isp_respinrp = BIU_RSPINP;
+		isp->isp_respoutrp = BIU_RSPOUTP;
+	} else {
+		isp->isp_rqstinrp = INMAILBOX4;
+		isp->isp_rqstoutrp = OUTMAILBOX4;
+		isp->isp_respinrp = OUTMAILBOX5;
+		isp->isp_respoutrp = INMAILBOX5;
+	}
 	ISP_WRITE(isp, isp->isp_rqstinrp, 0);
 	ISP_WRITE(isp, isp->isp_rqstoutrp, 0);
 	ISP_WRITE(isp, isp->isp_respinrp, 0);
@@ -668,10 +625,10 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 		ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
 	}
 
-	/*
-	 * Do MD specific post initialization
-	 */
-	ISP_RESET1(isp);
+	if (!IS_24XX(isp) && isp->isp_bustype == ISP_BT_PCI) {
+		/* Make sure the BIOS is disabled */
+		ISP_WRITE(isp, HCCR, PCI_HCCR_CMD_BIOS);
+	}
 
 	/*
 	 * Wait for everything to finish firing up.
@@ -686,7 +643,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 		while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) {
 			ISP_DELAY(100);
 			if (--loops < 0) {
-				ISP_RESET0(isp);
 				isp_prt(isp, ISP_LOGERR, "MBOX_BUSY never cleared on reset");
 				return;
 			}
@@ -707,14 +663,12 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]);
-		ISP_RESET0(isp);
 		return;
 	}
 
 	/*
 	 * Do some operational tests
 	 */
-
 	if (IS_SCSI(isp) || IS_24XX(isp)) {
 		static const uint16_t patterns[MAX_MAILBOX] = {
 			0x0000, 0xdead, 0xbeef, 0xffff,
@@ -735,12 +689,10 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 		}
 		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-			ISP_RESET0(isp);
 			return;
 		}
 		for (i = 1; i < nmbox; i++) {
 			if (mbs.param[i] != patterns[i]) {
-				ISP_RESET0(isp);
 				isp_prt(isp, ISP_LOGERR, "Register Test Failed at Register %d: should have 0x%04x but got 0x%04x", i, patterns[i], mbs.param[i]);
 				return;
 			}
@@ -758,6 +710,17 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	 */
 	if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
 		dodnld = 0;
+	} else {
+
+		/*
+		 * Set up DMA for the request and response queues.
+		 * We do this now so we can use the request queue
+		 * for dma to load firmware from.
+		 */
+		if (ISP_MBOXDMASETUP(isp) != 0) {
+			isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
+			return;
+		}
 	}
 
 	if (IS_24XX(isp)) {
@@ -849,7 +812,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 						goto again;
 					}
 					isp_prt(isp, ISP_LOGERR, "F/W Risc Ram Load Failed");
-					ISP_RESET0(isp);
 					return;
 				}
 				la += nw;
@@ -918,7 +880,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 				isp_mboxcmd(isp, &mbs);
 				if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 					isp_prt(isp, ISP_LOGERR, "F/W Risc Ram Load Failed");
-					ISP_RESET0(isp);
 					return;
 				}
 				la += nw;
@@ -961,7 +922,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			isp_prt(isp, ISP_LOGERR, "F/W download failed at word %d", isp->isp_mbxwrk1 - code_org);
-			ISP_RESET0(isp);
 			return;
 		}
 	} else if (IS_26XX(isp)) {
@@ -971,7 +931,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			isp_prt(isp, ISP_LOGERR, "Flash F/W load failed");
-			ISP_RESET0(isp);
 			return;
 		}
 	} else {
@@ -992,7 +951,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			isp_prt(isp, ISP_LOGERR, dcrc);
-			ISP_RESET0(isp);
 			return;
 		}
 	}
@@ -1003,8 +961,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	 * If we didn't actually download f/w,
 	 * we still need to (re)start it.
 	 */
-
-
 	MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000);
 	if (IS_24XX(isp)) {
 		mbs.param[1] = code_org >> 16;
@@ -1027,7 +983,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	isp_mboxcmd(isp, &mbs);
 	if (IS_2322(isp) || IS_24XX(isp)) {
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-			ISP_RESET0(isp);
 			return;
 		}
 	}
@@ -1051,7 +1006,6 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 0);
 	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-		ISP_RESET0(isp);
 		return;
 	}
 
@@ -1249,22 +1203,16 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 		MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
 		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-			ISP_RESET0(isp);
 			return;
 		}
-		if (isp->isp_maxcmds >= mbs.param[3]) {
-			isp->isp_maxcmds = mbs.param[3];
-		}
+		isp->isp_maxcmds = mbs.param[3];
 	} else {
 		MBSINIT(&mbs, MBOX_GET_FIRMWARE_STATUS, MBLOGALL, 0);
 		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-			ISP_RESET0(isp);
 			return;
 		}
-		if (isp->isp_maxcmds >= mbs.param[2]) {
-			isp->isp_maxcmds = mbs.param[2];
-		}
+		isp->isp_maxcmds = mbs.param[2];
 	}
 	isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds);
 
@@ -1284,15 +1232,28 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 			isp->isp_nchan = 1;
 		}
 	}
+
+	/*
+	 * Final DMA setup after we got isp_maxcmds.
+	 */
+	if (ISP_MBOXDMASETUP(isp) != 0) {
+		isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
+		return;
+	}
+
+	/*
+	 * Setup interrupts.
+	 */
+	if (ISP_IRQSETUP(isp) != 0) {
+		isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ");
+		return;
+	}
+	ISP_ENABLE_INTS(isp);
+
 	if (IS_FC(isp)) {
 		for (i = 0; i < isp->isp_nchan; i++)
 			isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
 	}
-	if (isp->isp_dead) {
-		isp_shutdown(isp);
-		ISP_DISABLE_INTS(isp);
-		return;
-	}
 
 	isp->isp_state = ISP_RESETSTATE;
 
@@ -1303,7 +1264,7 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	 * of knowing how many luns we support.
 	 *
 	 * Expanded lun firmware gives you 32 luns for SCSI cards and
-	 * 16384 luns for Fibre Channel cards.
+	 * unlimited luns for Fibre Channel cards.
 	 *
 	 * It turns out that even for QLogic 2100s with ROM 1.10 and above
 	 * we do get a firmware attributes word returned in mailbox register 6.
@@ -1351,7 +1312,7 @@ isp_reset(ispsoftc_t *isp, int do_load_d
  * Clean firmware shutdown.
  */
 static int
-isp_deinit(ispsoftc_t *isp)
+isp_stop(ispsoftc_t *isp)
 {
 	mbreg_t mbs;
 
@@ -1370,6 +1331,35 @@ isp_deinit(ispsoftc_t *isp)
 }
 
 /*
+ * Hardware shutdown.
+ */
+void
+isp_shutdown(ispsoftc_t *isp)
+{
+
+	if (isp->isp_state >= ISP_RESETSTATE)
+		isp_stop(isp);
+	ISP_DISABLE_INTS(isp);
+	if (IS_FC(isp)) {
+		if (IS_24XX(isp)) {
+			ISP_WRITE(isp, BIU2400_ICR, 0);
+			ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
+		} else {
+			ISP_WRITE(isp, BIU_ICR, 0);
+			ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+			ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
+			ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
+			ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
+			ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
+			ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
+		}
+	} else {
+		ISP_WRITE(isp, BIU_ICR, 0);
+		ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+	}
+}
+
+/*
  * Initialize Parameters of Hardware to a known state.
  *
  * Locks are held before coming here.
@@ -5599,7 +5589,6 @@ isp_parse_async(ispsoftc_t *isp, uint16_
 		isp_async(isp, ISPASYNC_BUS_RESET, chan);
 		break;
 	case ASYNC_SYSTEM_ERROR:
-		isp->isp_dead = 1;
 		isp->isp_state = ISP_CRASHED;
 		/*
 		 * Were we waiting for a mailbox command to complete?
@@ -5770,7 +5759,6 @@ isp_parse_async_fc(ispsoftc_t *isp, uint
 
 	switch (mbox) {
 	case ASYNC_SYSTEM_ERROR:
-		isp->isp_dead = 1;
 		isp->isp_state = ISP_CRASHED;
 		FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
 		isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
@@ -6052,7 +6040,6 @@ isp_parse_async_fc(ispsoftc_t *isp, uint
 			    "Point-to-Point -> Loop mode (BAD LIP)");
 			break;
 		case ISP_CONN_FATAL:
-			isp->isp_dead = 1;
 			isp->isp_state = ISP_CRASHED;
 			isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR");
 			isp_async(isp, ISPASYNC_FW_CRASH);
@@ -7895,14 +7882,13 @@ isp_reinit(ispsoftc_t *isp, int do_load_
 {
 	int i, res = 0;
 
-	if (isp->isp_state == ISP_RUNSTATE)
-		isp_deinit(isp);
+	if (isp->isp_state > ISP_RESETSTATE)
+		isp_stop(isp);
 	if (isp->isp_state != ISP_RESETSTATE)
 		isp_reset(isp, do_load_defaults);
 	if (isp->isp_state != ISP_RESETSTATE) {
 		res = EIO;
 		isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
-		ISP_DISABLE_INTS(isp);
 		goto cleanup;
 	}
 

Modified: stable/10/sys/dev/isp/isp_freebsd.c
==============================================================================
--- stable/10/sys/dev/isp/isp_freebsd.c	Tue Mar 28 10:19:52 2017	(r316086)
+++ stable/10/sys/dev/isp/isp_freebsd.c	Tue Mar 28 10:22:55 2017	(r316087)
@@ -1529,7 +1529,7 @@ isp_target_start_ctio(ispsoftc_t *isp, u
 					isp_prt(isp, ISP_LOGTDEBUG0, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests,
 					    (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length);
 					cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length;
-					if (isp->isp_osinfo.sixtyfourbit) {
+					if (cto->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
 						cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_base = DMA_LO32(addr);
 						cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_basehi = DMA_HI32(addr);
 						cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
@@ -4303,21 +4303,6 @@ changed:
 	}
 }
 
-
-/*
- * Locks are held before coming here.
- */
-void
-isp_uninit(ispsoftc_t *isp)
-{
-	if (IS_24XX(isp)) {
-		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
-	} else {
-		ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
-	}
-	ISP_DISABLE_INTS(isp);
-}
-
 uint64_t
 isp_default_wwn(ispsoftc_t * isp, int chan, int isactive, int iswwnn)
 {

Modified: stable/10/sys/dev/isp/isp_freebsd.h
==============================================================================
--- stable/10/sys/dev/isp/isp_freebsd.h	Tue Mar 28 10:19:52 2017	(r316086)
+++ stable/10/sys/dev/isp/isp_freebsd.h	Tue Mar 28 10:22:55 2017	(r316087)
@@ -697,7 +697,6 @@ default:							\
  */
 extern int isp_attach(ispsoftc_t *);
 extern int isp_detach(ispsoftc_t *);
-extern void isp_uninit(ispsoftc_t *);
 extern uint64_t isp_default_wwn(ispsoftc_t *, int, int, int);
 
 /*

Modified: stable/10/sys/dev/isp/isp_library.c
==============================================================================
--- stable/10/sys/dev/isp/isp_library.c	Tue Mar 28 10:19:52 2017	(r316086)
+++ stable/10/sys/dev/isp/isp_library.c	Tue Mar 28 10:22:55 2017	(r316087)
@@ -632,28 +632,6 @@ isp_clear_commands(ispsoftc_t *isp)
 #endif
 }
 
-void
-isp_shutdown(ispsoftc_t *isp)
-{
-	if (IS_FC(isp)) {
-		if (IS_24XX(isp)) {
-			ISP_WRITE(isp, BIU2400_ICR, 0);
-			ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
-		} else {
-			ISP_WRITE(isp, BIU_ICR, 0);
-			ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
-			ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
-			ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
-			ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
-			ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
-			ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
-		}
-	} else {
-		ISP_WRITE(isp, BIU_ICR, 0);
-		ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
-	}
-}
-
 /*
  * Functions to move stuff to a form that the QLogic RISC engine understands
  * and functions to move stuff back to a form the processor understands.

Modified: stable/10/sys/dev/isp/isp_library.h
==============================================================================
--- stable/10/sys/dev/isp/isp_library.h	Tue Mar 28 10:19:52 2017	(r316086)
+++ stable/10/sys/dev/isp/isp_library.h	Tue Mar 28 10:22:55 2017	(r316087)
@@ -77,11 +77,6 @@ const char *isp_fc_toponame(fcparam *);
 void isp_clear_commands(ispsoftc_t *);
 
 /*
- * Common chip shutdown function
- */
-void isp_shutdown(ispsoftc_t *);
-
-/*
  * Put/Get routines to push from CPU view to device view
  * or to pull from device view to CPU view for various
  * data structures (IOCB)

Modified: stable/10/sys/dev/isp/isp_pci.c
==============================================================================
--- stable/10/sys/dev/isp/isp_pci.c	Tue Mar 28 10:19:52 2017	(r316086)
+++ stable/10/sys/dev/isp/isp_pci.c	Tue Mar 28 10:22:55 2017	(r316087)
@@ -65,11 +65,9 @@ static int isp_pci_rd_isr(ispsoftc_t *, 
 static int isp_pci_rd_isr_2300(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
 static int isp_pci_rd_isr_2400(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
 static int isp_pci_mbxdma(ispsoftc_t *);
+static void isp_pci_mbxdmafree(ispsoftc_t *);
 static int isp_pci_dmasetup(ispsoftc_t *, XS_T *, void *);
-
-
-static void isp_pci_reset0(ispsoftc_t *);
-static void isp_pci_reset1(ispsoftc_t *);
+static int isp_pci_irqsetup(ispsoftc_t *);
 static void isp_pci_dumpregs(ispsoftc_t *, const char *);
 
 static struct ispmdvec mdvec = {
@@ -79,8 +77,7 @@ static struct ispmdvec mdvec = {
 	isp_pci_mbxdma,
 	isp_pci_dmasetup,
 	isp_common_dmateardown,
-	isp_pci_reset0,
-	isp_pci_reset1,
+	isp_pci_irqsetup,
 	isp_pci_dumpregs,
 	NULL,
 	BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
@@ -93,8 +90,7 @@ static struct ispmdvec mdvec_1080 = {
 	isp_pci_mbxdma,
 	isp_pci_dmasetup,
 	isp_common_dmateardown,
-	isp_pci_reset0,
-	isp_pci_reset1,
+	isp_pci_irqsetup,
 	isp_pci_dumpregs,
 	NULL,
 	BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
@@ -107,8 +103,7 @@ static struct ispmdvec mdvec_12160 = {
 	isp_pci_mbxdma,
 	isp_pci_dmasetup,
 	isp_common_dmateardown,
-	isp_pci_reset0,
-	isp_pci_reset1,
+	isp_pci_irqsetup,
 	isp_pci_dumpregs,
 	NULL,
 	BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
@@ -121,8 +116,7 @@ static struct ispmdvec mdvec_2100 = {
 	isp_pci_mbxdma,
 	isp_pci_dmasetup,
 	isp_common_dmateardown,
-	isp_pci_reset0,
-	isp_pci_reset1,
+	isp_pci_irqsetup,
 	isp_pci_dumpregs
 };
 
@@ -133,8 +127,7 @@ static struct ispmdvec mdvec_2200 = {
 	isp_pci_mbxdma,
 	isp_pci_dmasetup,
 	isp_common_dmateardown,
-	isp_pci_reset0,
-	isp_pci_reset1,
+	isp_pci_irqsetup,
 	isp_pci_dumpregs
 };
 
@@ -145,8 +138,7 @@ static struct ispmdvec mdvec_2300 = {
 	isp_pci_mbxdma,
 	isp_pci_dmasetup,
 	isp_common_dmateardown,
-	isp_pci_reset0,
-	isp_pci_reset1,
+	isp_pci_irqsetup,
 	isp_pci_dumpregs
 };
 
@@ -157,8 +149,7 @@ static struct ispmdvec mdvec_2400 = {
 	isp_pci_mbxdma,
 	isp_pci_dmasetup,
 	isp_common_dmateardown,
-	isp_pci_reset0,
-	isp_pci_reset1,
+	isp_pci_irqsetup,
 	NULL
 };
 
@@ -169,8 +160,7 @@ static struct ispmdvec mdvec_2500 = {
 	isp_pci_mbxdma,
 	isp_pci_dmasetup,
 	isp_common_dmateardown,
-	isp_pci_reset0,
-	isp_pci_reset1,
+	isp_pci_irqsetup,
 	NULL
 };
 
@@ -181,8 +171,7 @@ static struct ispmdvec mdvec_2600 = {
 	isp_pci_mbxdma,
 	isp_pci_dmasetup,
 	isp_common_dmateardown,
-	isp_pci_reset0,
-	isp_pci_reset1,
+	isp_pci_irqsetup,
 	NULL
 };
 
@@ -681,26 +670,19 @@ isp_get_specific_options(device_t dev, i
 static int
 isp_pci_attach(device_t dev)
 {
-	int i, locksetup = 0;
+	struct isp_pcisoftc *pcs = device_get_softc(dev);
+	ispsoftc_t *isp = &pcs->pci_isp;
+	int i;
 	uint32_t data, cmd, linesz, did;
-	struct isp_pcisoftc *pcs;
-	ispsoftc_t *isp;
 	size_t psize, xsize;
 	char fwname[32];
 
-	pcs = device_get_softc(dev);
-	if (pcs == NULL) {
-		device_printf(dev, "cannot get softc\n");
-		return (ENOMEM);
-	}
-	memset(pcs, 0, sizeof (*pcs));
-
 	pcs->pci_dev = dev;
-	isp = &pcs->pci_isp;
 	isp->isp_dev = dev;
 	isp->isp_nchan = 1;
 	if (sizeof (bus_addr_t) > 4)
 		isp->isp_osinfo.sixtyfourbit = 1;
+	mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
 
 	/*
 	 * Get Generic Options
@@ -980,10 +962,6 @@ isp_pci_attach(device_t dev)
 		goto bad;
 	}
 
-	/* Make sure the lock is set up. */
-	mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
-	locksetup++;
-
 	if (isp_setup_intr(dev, pcs->irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) {
 		device_printf(dev, "could not setup interrupt\n");
 		goto bad;
@@ -1007,7 +985,7 @@ isp_pci_attach(device_t dev)
 	ISP_UNLOCK(isp);
 	if (isp_attach(isp)) {
 		ISP_LOCK(isp);
-		isp_uninit(isp);
+		isp_shutdown(isp);
 		ISP_UNLOCK(isp);
 		goto bad;
 	}
@@ -1017,9 +995,6 @@ bad:
 	if (pcs->ih) {
 		(void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
 	}
-	if (locksetup) {
-		mtx_destroy(&isp->isp_osinfo.lock);
-	}
 	if (pcs->irq) {
 		(void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq);
 	}
@@ -1040,43 +1015,34 @@ bad:
 		free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF);
 		pcs->pci_isp.isp_osinfo.pc.ptr = NULL;
 	}
+	mtx_destroy(&isp->isp_osinfo.lock);
 	return (ENXIO);
 }
 
 static int
 isp_pci_detach(device_t dev)
 {
-	struct isp_pcisoftc *pcs;
-	ispsoftc_t *isp;
+	struct isp_pcisoftc *pcs = device_get_softc(dev);
+	ispsoftc_t *isp = &pcs->pci_isp;
 	int status;
 
-	pcs = device_get_softc(dev);
-	if (pcs == NULL) {
-		return (ENXIO);
-	}
-	isp = (ispsoftc_t *) pcs;
 	status = isp_detach(isp);
 	if (status)
 		return (status);
 	ISP_LOCK(isp);
-	isp_uninit(isp);
-	if (pcs->ih) {
-		(void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
-	}
+	isp_shutdown(isp);
 	ISP_UNLOCK(isp);
-	mtx_destroy(&isp->isp_osinfo.lock);
+	if (pcs->ih)
+		(void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
 	(void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq);
-	if (pcs->msicount) {
+	if (pcs->msicount)
 		pci_release_msi(dev);
-	}
 	(void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
 	if (pcs->regs1)
 		(void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1);
 	if (pcs->regs2)
 		(void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2);
-	/*
-	 * XXX: THERE IS A LOT OF LEAKAGE HERE
-	 */
+	isp_pci_mbxdmafree(isp);
 	if (pcs->pci_isp.isp_param) {
 		free(pcs->pci_isp.isp_param, M_DEVBUF);
 		pcs->pci_isp.isp_param = NULL;
@@ -1085,6 +1051,7 @@ isp_pci_detach(device_t dev)
 		free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF);
 		pcs->pci_isp.isp_osinfo.pc.ptr = NULL;
 	}
+	mtx_destroy(&isp->isp_osinfo.lock);
 	return (0);
 }
 
@@ -1571,56 +1538,39 @@ isp_pci_mbxdma(ispsoftc_t *isp)
 	struct imush im;
 	isp_ecmd_t *ecmd;
 
-	/*
-	 * Already been here? If so, leave...
-	 */
-	if (isp->isp_rquest) {
+	/* Already been here? If so, leave... */
+	if (isp->isp_xflist != NULL)
+		return (0);
+	if (isp->isp_rquest != NULL && isp->isp_maxcmds == 0)
 		return (0);
-	}
 	ISP_UNLOCK(isp);
-
-	if (isp->isp_maxcmds == 0) {
-		isp_prt(isp, ISP_LOGERR, "maxcmds not set");
-		ISP_LOCK(isp);
-		return (1);
-	}
+	if (isp->isp_rquest != NULL)
+		goto gotmaxcmds;
 
 	hlim = BUS_SPACE_MAXADDR;
 	if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) {
-		if (sizeof (bus_size_t) > 4) {
+		if (sizeof (bus_size_t) > 4)
 			slim = (bus_size_t) (1ULL << 32);
-		} else {
+		else
 			slim = (bus_size_t) (1UL << 31);
-		}
 		llim = BUS_SPACE_MAXADDR;
 	} else {
-		llim = BUS_SPACE_MAXADDR_32BIT;
 		slim = (1UL << 24);
+		llim = BUS_SPACE_MAXADDR_32BIT;
 	}
-
-	len = isp->isp_maxcmds * sizeof (struct isp_pcmd);
-	isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
-
-	if (isp->isp_osinfo.sixtyfourbit) {
+	if (isp->isp_osinfo.sixtyfourbit)
 		nsegs = ISP_NSEG64_MAX;
-	} else {
+	else
 		nsegs = ISP_NSEG_MAX;
-	}
 
-	if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_PCD(isp)), 1, slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, nsegs, slim, 0, &isp->isp_osinfo.dmat)) {
-		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
+	if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_PCD(isp)), 1,
+	    slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, nsegs, slim, 0,
+	    &isp->isp_osinfo.dmat)) {
 		ISP_LOCK(isp);
 		isp_prt(isp, ISP_LOGERR, "could not create master dma tag");
 		return (1);
 	}
 
-	len = sizeof (isp_hdl_t) * isp->isp_maxcmds;
-	isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
-	for (len = 0; len < isp->isp_maxcmds - 1; len++) {
-		isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1];
-	}
-	isp->isp_xffree = isp->isp_xflist;
-
 	/*
 	 * Allocate and map the request queue and a region for external
 	 * DMA addressable command/status structures (22XX and later).
@@ -1632,20 +1582,20 @@ isp_pci_mbxdma(ispsoftc_t *isp)
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
 	    len, 1, len, 0, &isp->isp_osinfo.reqdmat)) {
 		isp_prt(isp, ISP_LOGERR, "cannot create request DMA tag");
-		goto bad1;
+		goto bad;
 	}
 	if (bus_dmamem_alloc(isp->isp_osinfo.reqdmat, (void **)&base,
 	    BUS_DMA_COHERENT, &isp->isp_osinfo.reqmap) != 0) {
 		isp_prt(isp, ISP_LOGERR, "cannot allocate request DMA memory");
 		bus_dma_tag_destroy(isp->isp_osinfo.reqdmat);
-		goto bad1;
+		goto bad;
 	}
 	isp->isp_rquest = base;
 	im.error = 0;
 	if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap,
 	    base, len, imc, &im, 0) || im.error) {
 		isp_prt(isp, ISP_LOGERR, "error loading request DMA map %d", im.error);
-		goto bad1;
+		goto bad;
 	}
 	isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx",
 	    (uintmax_t)im.maddr, (uintmax_t)len);
@@ -1673,20 +1623,20 @@ isp_pci_mbxdma(ispsoftc_t *isp)
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
 	    len, 1, len, 0, &isp->isp_osinfo.respdmat)) {
 		isp_prt(isp, ISP_LOGERR, "cannot create response DMA tag");
-		goto bad1;
+		goto bad;
 	}
 	if (bus_dmamem_alloc(isp->isp_osinfo.respdmat, (void **)&base,
 	    BUS_DMA_COHERENT, &isp->isp_osinfo.respmap) != 0) {
 		isp_prt(isp, ISP_LOGERR, "cannot allocate response DMA memory");
 		bus_dma_tag_destroy(isp->isp_osinfo.respdmat);
-		goto bad1;
+		goto bad;
 	}
 	isp->isp_result = base;
 	im.error = 0;
 	if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap,
 	    base, len, imc, &im, 0) || im.error) {
 		isp_prt(isp, ISP_LOGERR, "error loading response DMA map %d", im.error);
-		goto bad1;
+		goto bad;
 	}
 	isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx",
 	    (uintmax_t)im.maddr, (uintmax_t)len);
@@ -1702,13 +1652,13 @@ isp_pci_mbxdma(ispsoftc_t *isp)
 		    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
 		    len, 1, len, 0, &isp->isp_osinfo.atiodmat)) {
 			isp_prt(isp, ISP_LOGERR, "cannot create ATIO DMA tag");
-			goto bad1;
+			goto bad;
 		}
 		if (bus_dmamem_alloc(isp->isp_osinfo.atiodmat, (void **)&base,
 		    BUS_DMA_COHERENT, &isp->isp_osinfo.atiomap) != 0) {
 			isp_prt(isp, ISP_LOGERR, "cannot allocate ATIO DMA memory");
 			bus_dma_tag_destroy(isp->isp_osinfo.atiodmat);
-			goto bad1;
+			goto bad;
 		}
 		isp->isp_atioq = base;
 		im.error = 0;
@@ -1754,6 +1704,7 @@ isp_pci_mbxdma(ispsoftc_t *isp)
 			    base, ISP_FC_SCRLEN, imc, &im, 0) || im.error) {
 				bus_dmamem_free(isp->isp_osinfo.scdmat,
 				    base, fc->scmap);
+				FCPARAM(isp, cmap)->isp_scratch = NULL;
 				goto bad;
 			}
 			FCPARAM(isp, cmap)->isp_scdma = im.maddr;
@@ -1775,83 +1726,134 @@ isp_pci_mbxdma(ispsoftc_t *isp)
 		}
 	}
 
+	if (isp->isp_maxcmds == 0) {
+		ISP_LOCK(isp);
+		return (0);
+	}
+
+gotmaxcmds:
+	len = isp->isp_maxcmds * sizeof (struct isp_pcmd);
+	isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *)
+	    malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
 	for (i = 0; i < isp->isp_maxcmds; i++) {
 		struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i];
 		error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap);
 		if (error) {
 			isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error);
 			while (--i >= 0) {
-				bus_dmamap_destroy(isp->isp_osinfo.dmat, isp->isp_osinfo.pcmd_pool[i].dmap);
+				bus_dmamap_destroy(isp->isp_osinfo.dmat,
+				    isp->isp_osinfo.pcmd_pool[i].dmap);
 			}
 			goto bad;
 		}
 		callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0);
-		if (i == isp->isp_maxcmds-1) {
+		if (i == isp->isp_maxcmds-1)
 			pcmd->next = NULL;
-		} else {
+		else
 			pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1];
-		}
 	}
 	isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0];
+
+	len = sizeof (isp_hdl_t) * isp->isp_maxcmds;
+	isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+	for (len = 0; len < isp->isp_maxcmds - 1; len++)
+		isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1];
+	isp->isp_xffree = isp->isp_xflist;
+
 	ISP_LOCK(isp);
 	return (0);
 
 bad:
+	isp_pci_mbxdmafree(isp);
+	ISP_LOCK(isp);
+	return (1);
+}
+
+static void
+isp_pci_mbxdmafree(ispsoftc_t *isp)
+{
+	int i;
+
+	if (isp->isp_xflist != NULL) {
+		free(isp->isp_xflist, M_DEVBUF);
+		isp->isp_xflist = NULL;
+	}
+	if (isp->isp_osinfo.pcmd_pool != NULL) {
+		for (i = 0; i < isp->isp_maxcmds; i++) {
+			bus_dmamap_destroy(isp->isp_osinfo.dmat,
+			    isp->isp_osinfo.pcmd_pool[i].dmap);
+		}
+		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
+		isp->isp_osinfo.pcmd_pool = NULL;
+	}
 	if (IS_FC(isp)) {
-		while (--cmap >= 0) {
-			struct isp_fc *fc = ISP_FC_PC(isp, cmap);
-			bus_dmamap_unload(isp->isp_osinfo.scdmat, fc->scmap);
-			bus_dmamem_free(isp->isp_osinfo.scdmat,
-			    FCPARAM(isp, cmap)->isp_scratch, fc->scmap);
+		for (i = 0; i < isp->isp_nchan; i++) {
+			struct isp_fc *fc = ISP_FC_PC(isp, i);
+			if (FCPARAM(isp, i)->isp_scdma != 0) {
+				bus_dmamap_unload(isp->isp_osinfo.scdmat,
+				    fc->scmap);
+				FCPARAM(isp, i)->isp_scdma = 0;
+			}
+			if (FCPARAM(isp, i)->isp_scratch != NULL) {
+				bus_dmamem_free(isp->isp_osinfo.scdmat,
+				    FCPARAM(isp, i)->isp_scratch, fc->scmap);
+				FCPARAM(isp, i)->isp_scratch = NULL;
+			}
 			while (fc->nexus_free_list) {
 				struct isp_nexus *n = fc->nexus_free_list;
 				fc->nexus_free_list = n->next;
 				free(n, M_DEVBUF);
 			}
 		}
-		bus_dma_tag_destroy(isp->isp_osinfo.scdmat);
-		bus_dmamap_unload(isp->isp_osinfo.iocbdmat, isp->isp_osinfo.iocbmap);
-		bus_dmamem_free(isp->isp_osinfo.iocbdmat, isp->isp_iocb,
-		    isp->isp_osinfo.iocbmap);
-		bus_dma_tag_destroy(isp->isp_osinfo.iocbdmat);
-	}
-bad1:
-	if (isp->isp_rquest_dma != 0) {
-		bus_dmamap_unload(isp->isp_osinfo.reqdmat,

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list