Author: mjacob
Date: Sat Aug 13 23:34:17 2011
New Revision: 224856
URL: http://svn.freebsd.org/changeset/base/224856

Log:
  Most of these changes to isp are to allow for isp.ko unloading.
  We also revive loop down freezes. We also externaliz within isp
  isp_prt_endcmd so something outside the core module can print
  something about a command completing. Also some work in progress to
  assist in handling timed out commands better.
  
  Partially Sponsored by: Panasas
  Approved by:  re (kib)
  MFC after:    1 month

Modified:
  head/sys/dev/isp/isp.c
  head/sys/dev/isp/isp_freebsd.c
  head/sys/dev/isp/isp_freebsd.h
  head/sys/dev/isp/isp_pci.c
  head/sys/dev/isp/ispvar.h

Modified: head/sys/dev/isp/isp.c
==============================================================================
--- head/sys/dev/isp/isp.c      Sat Aug 13 21:35:22 2011        (r224855)
+++ head/sys/dev/isp/isp.c      Sat Aug 13 23:34:17 2011        (r224856)
@@ -102,7 +102,6 @@ static const uint8_t alpa_map[] = {
 /*
  * Local function prototypes.
  */
-static void isp_prt_endcmd(ispsoftc_t *, XS_T *);
 static int isp_parse_async(ispsoftc_t *, uint16_t);
 static int isp_parse_async_fc(ispsoftc_t *, uint16_t);
 static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, uint32_t 
*);
@@ -5391,7 +5390,7 @@ out:
  * Support routines.
  */
 
-static void
+void
 isp_prt_endcmd(ispsoftc_t *isp, XS_T *xs)
 {
        char cdbstr[16 * 5 + 1];

Modified: head/sys/dev/isp/isp_freebsd.c
==============================================================================
--- head/sys/dev/isp/isp_freebsd.c      Sat Aug 13 21:35:22 2011        
(r224855)
+++ head/sys/dev/isp/isp_freebsd.c      Sat Aug 13 23:34:17 2011        
(r224856)
@@ -108,15 +108,13 @@ isp_attach_chan(ispsoftc_t *isp, struct 
                return (EIO);
        }
        ISP_UNLOCK(isp);
-
-       if (xpt_create_path(&path, NULL, cam_sim_path(sim), 
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+       if (xpt_create_path_unlocked(&path, NULL, cam_sim_path(sim), 
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
                ISP_LOCK(isp);
                xpt_bus_deregister(cam_sim_path(sim));
                ISP_UNLOCK(isp);
                cam_sim_free(sim, FALSE);
                return (ENXIO);
        }
-
        xpt_setup_ccb(&csa.ccb_h, path, 5);
        csa.ccb_h.func_code = XPT_SASYNC_CB;
        csa.event_enable = AC_LOST_DEVICE;
@@ -190,12 +188,16 @@ isp_attach(ispsoftc_t *isp)
 
        isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
        isp->isp_osinfo.ehook.ich_arg = isp;
+       /*
+        * Haha. Set this first, because if we're loaded as a module 
isp_intr_enable
+        * will be called right awawy, which will clear isp_osinfo.ehook_active,
+        * which would be unwise to then set again later.
+        */
+       isp->isp_osinfo.ehook_active = 1;
        if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
                isp_prt(isp, ISP_LOGERR, "could not establish interrupt enable 
hook");
                return (-EIO);
        }
-       isp->isp_osinfo.ehook_active = 1;
-
 
        /*
         * Create the device queue for our SIM(s).
@@ -252,20 +254,33 @@ unwind:
        return (-1);
 }
 
-void
+int
 isp_detach(ispsoftc_t *isp)
 {
+       struct cam_sim *sim;
+       struct cam_path *path;
+       struct ccb_setasync csa;
        int chan;
 
        ISP_LOCK(isp);
+       for (chan = isp->isp_nchan - 1; chan >= 0; chan -= 1) {
+               if (IS_FC(isp)) {
+                       sim = ISP_FC_PC(isp, chan)->sim;
+                       path = ISP_FC_PC(isp, chan)->path;
+               } else {
+                       sim = ISP_SPI_PC(isp, chan)->sim;
+                       path = ISP_SPI_PC(isp, chan)->path;
+               }
+               if (sim->refcount > 2) {
+                       ISP_UNLOCK(isp);
+                       return (EBUSY);
+               }
+       }
        if (isp->isp_osinfo.timer_active) {
                callout_stop(&isp->isp_osinfo.tmo);
                isp->isp_osinfo.timer_active = 0;
        }
-       ISP_UNLOCK(isp);
        for (chan = isp->isp_nchan - 1; chan >= 0; chan -= 1) {
-               struct cam_sim *sim;
-               struct cam_path *path;
                if (IS_FC(isp)) {
                        sim = ISP_FC_PC(isp, chan)->sim;
                        path = ISP_FC_PC(isp, chan)->path;
@@ -273,12 +288,17 @@ isp_detach(ispsoftc_t *isp)
                        sim = ISP_SPI_PC(isp, chan)->sim;
                        path = ISP_SPI_PC(isp, chan)->path;
                }
+               xpt_setup_ccb(&csa.ccb_h, path, 5);
+               csa.ccb_h.func_code = XPT_SASYNC_CB;
+               csa.event_enable = 0;
+               csa.callback = isp_cam_async;
+               csa.callback_arg = sim;
+               xpt_action((union ccb *)&csa);
                xpt_free_path(path);
-               ISP_LOCK(isp);
                xpt_bus_deregister(cam_sim_path(sim));
-               ISP_UNLOCK(isp);
                cam_sim_free(sim, FALSE);
        }
+       ISP_UNLOCK(isp);
        if (isp->isp_osinfo.cdev) {
                destroy_dev(isp->isp_osinfo.cdev);
                isp->isp_osinfo.cdev = NULL;
@@ -291,6 +311,7 @@ isp_detach(ispsoftc_t *isp)
                cam_simq_free(isp->isp_osinfo.devq);
                isp->isp_osinfo.devq = NULL;
        }
+       return (0);
 }
 
 static void
@@ -309,6 +330,20 @@ isp_freeze_loopdown(ispsoftc_t *isp, int
        }
 }
 
+static void
+isp_unfreeze_loopdown(ispsoftc_t *isp, int chan)
+{
+       if (IS_FC(isp)) {
+               struct isp_fc *fc = ISP_FC_PC(isp, chan);
+               int wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN;
+               fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN;
+               if (wasfrozen && fc->simqfrozen == 0) {
+                       isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d 
releasing simq", __func__, chan);
+                       xpt_release_simq(fc->sim, 1);
+               }
+       }
+}
+
 
 static int
 ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread 
*td)
@@ -702,6 +737,7 @@ isp_intr_enable(void *arg)
                        }
                }
        }
+       isp->isp_osinfo.ehook_active = 0;
        ISP_UNLOCK(isp);
        /* Release our hook so that the boot can continue. */
        config_intrhook_disestablish(&isp->isp_osinfo.ehook);
@@ -1308,7 +1344,7 @@ done:
                xpt_print(ccb->ccb_h.path, "now disabled for target mode\n");
        }
        if (tptr) {
-               rls_lun_statep(isp, tptr);
+               destroy_lun_state(isp, tptr);
        }
        isp->isp_osinfo.rptr = NULL;
        isp->isp_osinfo.tmbusy = 0;
@@ -3787,19 +3823,20 @@ static void
 isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
 {
        struct cam_sim *sim;
+       int bus, tgt;
        ispsoftc_t *isp;
 
        sim = (struct cam_sim *)cbarg;
        isp = (ispsoftc_t *) cam_sim_softc(sim);
+       bus = cam_sim_bus(sim);
+       tgt = xpt_path_target_id(path);
+
        switch (code) {
        case AC_LOST_DEVICE:
                if (IS_SCSI(isp)) {
                        uint16_t oflags, nflags;
-                       int bus = cam_sim_bus(sim);
                        sdparam *sdp = SDPARAM(isp, bus);
-                       int tgt;
 
-                       tgt = xpt_path_target_id(path);
                        if (tgt >= 0) {
                                nflags = sdp->isp_devparam[tgt].nvrm_flags;
 #ifndef        ISP_TARGET_MODE
@@ -3843,11 +3880,32 @@ isp_watchdog(void *arg)
 {
        struct ccb_scsiio *xs = arg;
        ispsoftc_t *isp;
-       uint32_t handle;
+       uint32_t ohandle = ISP_HANDLE_FREE, handle;
 
        isp = XS_ISP(xs);
 
        handle = isp_find_handle(isp, xs);
+
+       if (handle != ISP_HANDLE_FREE && !XS_CMD_WPEND_P(xs)) {
+               isp_xs_prt(isp, xs, ISP_LOGWARN, "first watchdog (handle 0x%x) 
timed out- deferring for grace period", handle);
+               callout_reset(&PISP_PCMD(xs)->wdog, 2 * hz, isp_watchdog, xs);
+               XS_CMD_S_WPEND(xs);
+               return;
+       }
+       XS_C_TACTIVE(xs);
+
+       /*
+        * Hand crank the interrupt code just to be sure the command isn't 
stuck somewhere.
+        */
+       if (handle != ISP_HANDLE_FREE) {
+               uint32_t isr;
+               uint16_t sema, mbox;
+               if (ISP_READ_ISR(isp, &isr, &sema, &mbox) != 0) {
+                       isp_intr(isp, isr, sema, mbox);
+               }
+               ohandle = handle;
+               handle = isp_find_handle(isp, xs);
+       }
        if (handle != ISP_HANDLE_FREE) {
                /*
                 * Try and make sure the command is really dead before
@@ -3884,7 +3942,14 @@ isp_watchdog(void *arg)
                isp_destroy_handle(isp, handle);
                isp_prt(isp, ISP_LOGERR, "%s: timeout for handle 0x%x", 
__func__, handle);
                XS_SETERR(xs, CAM_CMD_TIMEOUT);
+               isp_prt_endcmd(isp, xs);
                isp_done(xs);
+       } else {
+               if (ohandle != ISP_HANDLE_FREE) {
+                       isp_prt(isp, ISP_LOGWARN, "%s: timeout for handle 0x%x, 
recovered during interrupt", __func__, ohandle);
+               } else {
+                       isp_prt(isp, ISP_LOGWARN, "%s: timeout for handle 
already free", __func__);
+               }
        }
 }
 
@@ -4013,7 +4078,7 @@ isp_ldt_task(void *arg, int pending)
        ispsoftc_t *isp = fc->isp;
        int chan = fc - isp->isp_osinfo.pc.fc;
        fcportdb_t *lp;
-       int dbidx, tgt;
+       int dbidx, tgt, i;
 
        ISP_LOCK(isp);
        isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d Loop Down Timer 
expired @ %lu", chan, (unsigned long) time_uptime);
@@ -4035,6 +4100,23 @@ isp_ldt_task(void *arg, int pending)
                /*
                 * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST!
                 */
+               
+
+               for (i = 0; i < isp->isp_maxcmds; i++) {
+                       struct ccb_scsiio *xs;
+
+                       if (!ISP_VALID_HANDLE(isp, isp->isp_xflist[i].handle)) {
+                               continue;
+                       }
+                       if ((xs = isp->isp_xflist[i].cmd) == NULL) {
+                               continue;
+                        }
+                       if (dbidx != (FCPARAM(isp, 
chan)->isp_dev_map[XS_TGT(xs)] - 1)) {
+                               continue;
+                       }
+                       isp_prt(isp, ISP_LOGWARN, "command handle 0x%08x for 
%d.%d.%d orphaned by loop down timeout",
+                           isp->isp_xflist[i].handle, chan, XS_TGT(xs), 
XS_LUN(xs));
+               }
 
                /*
                 * Mark that we've announced that this device is gone....
@@ -4056,6 +4138,9 @@ isp_ldt_task(void *arg, int pending)
                isp_make_gone(isp, chan, tgt);
        }
 
+       if (FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR) {
+               isp_unfreeze_loopdown(isp, chan);
+       }
        /*
         * The loop down timer has expired. Wake up the kthread
         * to notice that fact (or make it false).
@@ -4063,6 +4148,7 @@ isp_ldt_task(void *arg, int pending)
        fc->loop_dead = 1;
        fc->loop_down_time = fc->loop_down_limit+1;
        wakeup(fc);
+       ISP_UNLOCK(isp);
 }
 
 static void
@@ -4076,7 +4162,7 @@ isp_kthread(void *arg)
        mtx_lock(&isp->isp_osinfo.lock);
 
        for (;;) {
-               int wasfrozen, lb, lim;
+               int lb, lim;
 
                isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d checking 
FC state", __func__, chan);
                lb = isp_fc_runstate(isp, chan, 250000);
@@ -4147,12 +4233,7 @@ isp_kthread(void *arg)
                 */
 
                if (FCPARAM(isp, chan)->loop_seen_once || fc->loop_dead) {
-                       wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN;
-                       fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN;
-                       if (wasfrozen && fc->simqfrozen == 0) {
-                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: 
Chan %d releasing simq", __func__, chan);
-                               xpt_release_simq(fc->sim, 1);
-                       }
+                       isp_unfreeze_loopdown(isp, chan);
                }
 
                isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep 
time %d", __func__, chan, slp);
@@ -4251,6 +4332,7 @@ isp_action(struct cam_sim *sim, union cc
                                ts = 60*1000;
                        }
                        ts = isp_mstohz(ts);
+                       XS_S_TACTIVE(ccb);
                        callout_reset(&PISP_PCMD(ccb)->wdog, ts, isp_watchdog, 
ccb);
                        break;
                case CMD_RQLATER:
@@ -4777,7 +4859,9 @@ isp_action(struct cam_sim *sim, union cc
                        /*
                         * Set base transfer capabilities for Fibre Channel, 
for this HBA.
                         */
-                       if (IS_24XX(isp)) {
+                       if (IS_25XX(isp)) {
+                               cpi->base_transfer_speed = 8000000;
+                       } else if (IS_24XX(isp)) {
                                cpi->base_transfer_speed = 4000000;
                        } else if (IS_23XX(isp)) {
                                cpi->base_transfer_speed = 2000000;
@@ -4823,6 +4907,7 @@ void
 isp_done(XS_T *sccb)
 {
        ispsoftc_t *isp = XS_ISP(sccb);
+       uint32_t status;
 
        if (XS_NOERR(sccb))
                XS_SETERR(sccb, CAM_REQ_CMP);
@@ -4837,8 +4922,10 @@ isp_done(XS_T *sccb)
        }
 
        sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
-       if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
-               isp_prt(isp, ISP_LOGDEBUG0, "target %d lun %d CAM status 0x%x 
SCSI status 0x%x", XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status, 
sccb->scsi_status);
+       status = sccb->ccb_h.status & CAM_STATUS_MASK;
+       if (status != CAM_REQ_CMP) {
+               if (status != CAM_SEL_TIMEOUT)
+                       isp_prt(isp, ISP_LOGDEBUG0, "target %d lun %d CAM 
status 0x%x SCSI status 0x%x", XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status, 
sccb->scsi_status);
                if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
                        sccb->ccb_h.status |= CAM_DEV_QFRZN;
                        xpt_freeze_devq(sccb->ccb_h.path, 1);
@@ -4850,7 +4937,8 @@ isp_done(XS_T *sccb)
        }
 
        XS_CMD_S_DONE(sccb);
-       callout_stop(&PISP_PCMD(sccb)->wdog);
+       if (XS_TACTIVE_P(sccb))
+               callout_stop(&PISP_PCMD(sccb)->wdog);
        XS_CMD_S_CLEAR(sccb);
        isp_free_pcmd(isp, (union ccb *) sccb);
        xpt_done((union ccb *) sccb);

Modified: head/sys/dev/isp/isp_freebsd.h
==============================================================================
--- head/sys/dev/isp/isp_freebsd.h      Sat Aug 13 21:35:22 2011        
(r224855)
+++ head/sys/dev/isp/isp_freebsd.h      Sat Aug 13 23:34:17 2011        
(r224856)
@@ -582,7 +582,7 @@ default:                                                    
\
  * prototypes for isp_pci && isp_freebsd to share
  */
 extern int isp_attach(ispsoftc_t *);
-extern void isp_detach(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);
 
@@ -600,12 +600,23 @@ extern int isp_autoconfig;
  * Platform private flags
  */
 #define        ISP_SPRIV_ERRSET        0x1
+#define        ISP_SPRIV_TACTIVE       0x2
 #define        ISP_SPRIV_DONE          0x8
+#define        ISP_SPRIV_WPEND         0x10
+
+#define        XS_S_TACTIVE(sccb)      (sccb)->ccb_h.spriv_field0 |= 
ISP_SPRIV_TACTIVE
+#define        XS_C_TACTIVE(sccb)      (sccb)->ccb_h.spriv_field0 &= 
~ISP_SPRIV_TACTIVE
+#define        XS_TACTIVE_P(sccb)      ((sccb)->ccb_h.spriv_field0 & 
ISP_SPRIV_TACTIVE)
 
 #define        XS_CMD_S_DONE(sccb)     (sccb)->ccb_h.spriv_field0 |= 
ISP_SPRIV_DONE
 #define        XS_CMD_C_DONE(sccb)     (sccb)->ccb_h.spriv_field0 &= 
~ISP_SPRIV_DONE
 #define        XS_CMD_DONE_P(sccb)     ((sccb)->ccb_h.spriv_field0 & 
ISP_SPRIV_DONE)
 
+#define        XS_CMD_S_WPEND(sccb)    (sccb)->ccb_h.spriv_field0 |= 
ISP_SPRIV_WPEND
+#define        XS_CMD_C_WPEND(sccb)    (sccb)->ccb_h.spriv_field0 &= 
~ISP_SPRIV_WPEND
+#define        XS_CMD_WPEND_P(sccb)    ((sccb)->ccb_h.spriv_field0 & 
ISP_SPRIV_WPEND)
+
+
 #define        XS_CMD_S_CLEAR(sccb)    (sccb)->ccb_h.spriv_field0 = 0
 
 /*

Modified: head/sys/dev/isp/isp_pci.c
==============================================================================
--- head/sys/dev/isp/isp_pci.c  Sat Aug 13 21:35:22 2011        (r224855)
+++ head/sys/dev/isp/isp_pci.c  Sat Aug 13 23:34:17 2011        (r224856)
@@ -347,7 +347,11 @@ static int isp_pci_detach (device_t);
 struct isp_pcisoftc {
        ispsoftc_t                      pci_isp;
        device_t                        pci_dev;
-       struct resource *               pci_reg;
+       struct resource *               regs;
+       void *                          irq;
+       int                             iqd;
+       int                             rtp;
+       int                             rgd;
        void *                          ih;
        int16_t                         pci_poff[_NREG_BLKS];
        bus_dma_tag_t                   dmat;
@@ -645,8 +649,7 @@ isp_get_specific_options(device_t dev, i
 static int
 isp_pci_attach(device_t dev)
 {
-       struct resource *regs, *irq;
-       int rtp, rgd, iqd, i, m1, m2, locksetup = 0;
+       int i, m1, m2, locksetup = 0;
        int isp_nvports = 0;
        uint32_t data, cmd, linesz, did;
        struct isp_pcisoftc *pcs;
@@ -687,32 +690,31 @@ isp_pci_attach(device_t dev)
        isp_get_pci_options(dev, &m1, &m2);
 
        linesz = PCI_DFLT_LNSZ;
-       irq = regs = NULL;
-       rgd = rtp = iqd = 0;
+       pcs->irq = pcs->regs = NULL;
+       pcs->rgd = pcs->rtp = pcs->iqd = 0;
 
        cmd = pci_read_config(dev, PCIR_COMMAND, 2);
        if (cmd & m1) {
-               rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
-               rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
-               regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE);
-       }
-       if (regs == NULL && (cmd & m2)) {
-               rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
-               rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
-               regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE);
+               pcs->rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : 
SYS_RES_IOPORT;
+               pcs->rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
+               pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 
RF_ACTIVE);
+       }
+       if (pcs->regs == NULL && (cmd & m2)) {
+               pcs->rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : 
SYS_RES_IOPORT;
+               pcs->rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
+               pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 
RF_ACTIVE);
        }
-       if (regs == NULL) {
+       if (pcs->regs == NULL) {
                device_printf(dev, "unable to map any ports\n");
                goto bad;
        }
        if (bootverbose) {
-               device_printf(dev, "using %s space register mapping\n", (rgd == 
IO_MAP_REG)? "I/O" : "Memory");
+               device_printf(dev, "using %s space register mapping\n", 
(pcs->rgd == IO_MAP_REG)? "I/O" : "Memory");
        }
-       isp->isp_bus_tag = rman_get_bustag(regs);
-       isp->isp_bus_handle = rman_get_bushandle(regs);
+       isp->isp_bus_tag = rman_get_bustag(pcs->regs);
+       isp->isp_bus_handle = rman_get_bushandle(pcs->regs);
 
        pcs->pci_dev = dev;
-       pcs->pci_reg = regs;
        pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
        pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
        pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
@@ -931,13 +933,13 @@ isp_pci_attach(device_t dev)
                        pcs->msicount = 1;
                }
                if (pci_alloc_msi(dev, &pcs->msicount) == 0) {
-                       iqd = 1;
+                       pcs->iqd = 1;
                } else {
-                       iqd = 0;
+                       pcs->iqd = 0;
                }
        }
-       irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, RF_ACTIVE | 
RF_SHAREABLE);
-       if (irq == NULL) {
+       pcs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &pcs->iqd, 
RF_ACTIVE | RF_SHAREABLE);
+       if (pcs->irq == NULL) {
                device_printf(dev, "could not allocate interrupt\n");
                goto bad;
        }
@@ -946,7 +948,7 @@ isp_pci_attach(device_t dev)
        mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
        locksetup++;
 
-       if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, 
&pcs->ih)) {
+       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;
        }
@@ -982,19 +984,19 @@ isp_pci_attach(device_t dev)
 
 bad:
        if (pcs->ih) {
-               (void) bus_teardown_intr(dev, irq, pcs->ih);
+               (void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
        }
        if (locksetup) {
                mtx_destroy(&isp->isp_osinfo.lock);
        }
-       if (irq) {
-               (void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq);
+       if (pcs->irq) {
+               (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, 
pcs->irq);
        }
        if (pcs->msicount) {
                pci_release_msi(dev);
        }
-       if (regs) {
-               (void) bus_release_resource(dev, rtp, rgd, regs);
+       if (pcs->regs) {
+               (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
        }
        if (pcs->pci_isp.isp_param) {
                free(pcs->pci_isp.isp_param, M_DEVBUF);
@@ -1012,14 +1014,36 @@ isp_pci_detach(device_t dev)
 {
        struct isp_pcisoftc *pcs;
        ispsoftc_t *isp;
+       int status;
 
        pcs = device_get_softc(dev);
        if (pcs == NULL) {
                return (ENXIO);
        }
        isp = (ispsoftc_t *) pcs;
-       ISP_DISABLE_INTS(isp);
+       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_UNLOCK(isp);
        mtx_destroy(&isp->isp_osinfo.lock);
+       (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq);
+       if (pcs->msicount) {
+               pci_release_msi(dev);
+       }
+       (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
+       if (pcs->pci_isp.isp_param) {
+               free(pcs->pci_isp.isp_param, M_DEVBUF);
+               pcs->pci_isp.isp_param = NULL;
+       }
+       if (pcs->pci_isp.isp_osinfo.pc.ptr) {
+               free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF);
+               pcs->pci_isp.isp_osinfo.pc.ptr = NULL;
+       }
        return (0);
 }
 

Modified: head/sys/dev/isp/ispvar.h
==============================================================================
--- head/sys/dev/isp/ispvar.h   Sat Aug 13 21:35:22 2011        (r224855)
+++ head/sys/dev/isp/ispvar.h   Sat Aug 13 23:34:17 2011        (r224856)
@@ -953,6 +953,11 @@ void isp_async(ispsoftc_t *, ispasync_t,
 #define        ISPASYNC_CHANGE_OTHER   2
 
 /*
+ * Platform Independent Error Prinout
+ */
+void isp_prt_endcmd(ispsoftc_t *, XS_T *);
+
+/*
  * Platform Dependent Error and Debug Printout
  *
  * Two required functions for each platform must be provided:
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to