From owner-svn-src-all@freebsd.org Tue Mar 28 10:11:02 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7B563D1F477; Tue, 28 Mar 2017 10:11:02 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4385D6AD; Tue, 28 Mar 2017 10:11:02 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v2SAB17s012128; Tue, 28 Mar 2017 10:11:01 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v2SAB0ke012119; Tue, 28 Mar 2017 10:11:00 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201703281011.v2SAB0ke012119@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Tue, 28 Mar 2017 10:11:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r316084 - stable/11/sys/dev/isp X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Mar 2017 10:11:02 -0000 Author: mav Date: Tue Mar 28 10:11:00 2017 New Revision: 316084 URL: https://svnweb.freebsd.org/changeset/base/316084 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/11/sys/dev/isp/isp.c stable/11/sys/dev/isp/isp_freebsd.c stable/11/sys/dev/isp/isp_freebsd.h stable/11/sys/dev/isp/isp_library.c stable/11/sys/dev/isp/isp_library.h stable/11/sys/dev/isp/isp_pci.c stable/11/sys/dev/isp/isp_sbus.c stable/11/sys/dev/isp/ispvar.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/dev/isp/isp.c ============================================================================== --- stable/11/sys/dev/isp/isp.c Tue Mar 28 09:58:54 2017 (r316083) +++ stable/11/sys/dev/isp/isp.c Tue Mar 28 10:11:00 2017 (r316084) @@ -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/11/sys/dev/isp/isp_freebsd.c ============================================================================== --- stable/11/sys/dev/isp/isp_freebsd.c Tue Mar 28 09:58:54 2017 (r316083) +++ stable/11/sys/dev/isp/isp_freebsd.c Tue Mar 28 10:11:00 2017 (r316084) @@ -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; @@ -4304,21 +4304,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/11/sys/dev/isp/isp_freebsd.h ============================================================================== --- stable/11/sys/dev/isp/isp_freebsd.h Tue Mar 28 09:58:54 2017 (r316083) +++ stable/11/sys/dev/isp/isp_freebsd.h Tue Mar 28 10:11:00 2017 (r316084) @@ -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/11/sys/dev/isp/isp_library.c ============================================================================== --- stable/11/sys/dev/isp/isp_library.c Tue Mar 28 09:58:54 2017 (r316083) +++ stable/11/sys/dev/isp/isp_library.c Tue Mar 28 10:11:00 2017 (r316084) @@ -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/11/sys/dev/isp/isp_library.h ============================================================================== --- stable/11/sys/dev/isp/isp_library.h Tue Mar 28 09:58:54 2017 (r316083) +++ stable/11/sys/dev/isp/isp_library.h Tue Mar 28 10:11:00 2017 (r316084) @@ -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/11/sys/dev/isp/isp_pci.c ============================================================================== --- stable/11/sys/dev/isp/isp_pci.c Tue Mar 28 09:58:54 2017 (r316083) +++ stable/11/sys/dev/isp/isp_pci.c Tue Mar 28 10:11:00 2017 (r316084) @@ -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 ***