Date: Mon, 23 Apr 2007 02:52:03 GMT From: Matt Jacob <mjacob@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 118630 for review Message-ID: <200704230252.l3N2q3ap001249@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=118630 Change 118630 by mjacob@mjexp on 2007/04/23 02:51:22 First blush at MPSAFE isp. Affected files ... .. //depot/projects/mjexp/sys/dev/isp/isp_freebsd.c#20 edit .. //depot/projects/mjexp/sys/dev/isp/isp_freebsd.h#13 edit .. //depot/projects/mjexp/sys/dev/isp/isp_pci.c#23 edit .. //depot/projects/mjexp/sys/dev/isp/isp_sbus.c#12 edit Differences ... ==== //depot/projects/mjexp/sys/dev/isp/isp_freebsd.c#20 (text+ko) ==== @@ -99,7 +99,9 @@ #else static struct cdevsw isp_cdevsw = { .d_version = D_VERSION, +#if __FreeBSD_version < 700037 .d_flags = D_NEEDGIANT, +#endif .d_ioctl = ispioctl, .d_name = "isp", }; @@ -172,39 +174,6 @@ xpt_action((union ccb *)&csa); isp->isp_sim = sim; isp->isp_path = path; - /* - * Create a kernel thread for fibre channel instances. We - * don't have dual channel FC cards. - */ - if (IS_FC(isp)) { -#if __FreeBSD_version >= 500000 - if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc, - RFHIGHPID, 0, "%s: fc_thrd", - device_get_nameunit(isp->isp_dev))) -#else - if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc, - "%s: fc_thrd", device_get_nameunit(isp->isp_dev))) -#endif - { - xpt_bus_deregister(cam_sim_path(sim)); - cam_sim_free(sim, TRUE); - config_intrhook_disestablish(&isp->isp_osinfo.ehook); - isp_prt(isp, ISP_LOGERR, "could not create kthread"); - return; - } - /* - * We start by being "loop down" if we have an initiator role - */ - if (isp->isp_role & ISP_ROLE_INITIATOR) { - isp_freeze_loopdown(isp, "isp_attach"); - isp->isp_osinfo.ldt = - timeout(isp_ldt, isp, isp_quickboot_time * hz); - isp->isp_osinfo.ldt_running = 1; - isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, - "Starting Initial Loop Down Timer"); - } - } - /* * If we have a second channel, construct SIM entry for that. @@ -266,7 +235,46 @@ } tmp->isp_osinfo.next = isp; } + ISP_UNLOCK(isp); isp_sysctl_update(isp); + ISP_LOCK(isp); + + /* + * Create a kernel thread for fibre channel instances. + */ + if (IS_FC(isp)) { + isp_callout_init(&isp->isp_osinfo.ldt); + isp_callout_init(&isp->isp_osinfo.gdt); + ISP_UNLOCK(isp); +#if __FreeBSD_version >= 500000 + if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc, + RFHIGHPID, 0, "%s: fc_thrd", + device_get_nameunit(isp->isp_dev))) +#else + if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc, + "%s: fc_thrd", device_get_nameunit(isp->isp_dev))) +#endif + { + ISP_LOCK(isp); + xpt_bus_deregister(cam_sim_path(sim)); + cam_sim_free(sim, TRUE); + config_intrhook_disestablish(&isp->isp_osinfo.ehook); + isp_prt(isp, ISP_LOGERR, "could not create kthread"); + return; + } + ISP_LOCK(isp); + /* + * We start by being "loop down" if we have an initiator role + */ + if (isp->isp_role & ISP_ROLE_INITIATOR) { + isp_freeze_loopdown(isp, "isp_attach"); + isp->isp_osinfo.ldt_running = 1; + callout_reset(&isp->isp_osinfo.ldt, + isp_quickboot_time * hz, isp_ldt, isp); + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + "Starting Initial Loop Down Timer"); + } + } } static void @@ -677,9 +685,11 @@ isp_intr_enable(void *arg) { ispsoftc_t *isp = arg; + ISP_LOCK(isp); if (isp->isp_role != ISP_ROLE_NONE) { ISP_ENABLE_INTS(isp); } + ISP_UNLOCK(isp); /* Release our hook so that the boot can continue. */ config_intrhook_disestablish(&isp->isp_osinfo.ehook); } @@ -2078,10 +2088,12 @@ { ispsoftc_t *isp; XS_T *xs = arg; - for (isp = isplist; isp != NULL; isp = isp->isp_osinfo.next) { - if (isp_watchdog_work(isp, xs)) { - break; - } + int r; + + for (r = 0, isp = isplist; r && isp; isp = isp->isp_osinfo.next) { + ISP_LOCK(isp); + r = isp_watchdog_work(isp, xs); + ISP_UNLOCK(isp); } if (isp == NULL) { printf("isp_watchdog: nobody had %p active\n", arg); @@ -2145,6 +2157,7 @@ fcportdb_t *lp; int dbidx, tgt, more_to_do = 0; + ISP_LOCK(isp); isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired"); for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { lp = &FCPARAM(isp)->portdb[dbidx]; @@ -2172,12 +2185,14 @@ isp_make_gone(isp, tgt); } if (more_to_do) { - isp->isp_osinfo.gdt = timeout(isp_gdt, isp, hz); + isp->isp_osinfo.gdt_running = 1; + callout_reset(&isp->isp_osinfo.gdt, hz, isp_gdt, isp); } else { isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "stopping Gone Device Timer"); isp->isp_osinfo.gdt_running = 0; } + ISP_UNLOCK(isp); } /* @@ -2196,6 +2211,8 @@ fcportdb_t *lp; int dbidx, tgt; + ISP_LOCK(isp); + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired"); /* @@ -2240,7 +2257,8 @@ * to notice that fact (or make it false). */ isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1; - wakeup(&isp->isp_osinfo.kproc); + wakeup(ISP_KT_WCHAN(isp)); + ISP_UNLOCK(isp); } static void @@ -2250,8 +2268,10 @@ int slp = 0; #if __FreeBSD_version < 500000 int s = splcam(); +#elif __FreeBSD_version < 700037 + mtx_lock(&Giant); #else - mtx_lock(&Giant); + mtx_lock(&isp->isp_osinfo.lock); #endif /* * The first loop is for our usage where we have yet to have @@ -2330,7 +2350,12 @@ } isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "isp_kthread: sleep time %d", slp); - tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf", slp * hz); +#if __FreeBSD_version < 700037 + tsleep(ISP_KT_WCHAN(isp), PRIBIO, "ispf", slp * hz); +#else + msleep(ISP_KT_WCHAN(isp), &isp->isp_osinfo.lock, + PRIBIO, "ispf", slp * hz); +#endif /* * If slp is zero, we're waking up for the first time after * things have been okay. In this case, we set a deferral state @@ -2342,29 +2367,35 @@ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "isp_kthread: sleep hysteresis tick time %d", isp->isp_osinfo.hysteresis * hz); +#if __FreeBSD_version < 700037 (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT", (isp->isp_osinfo.hysteresis * hz)); +#else + (void) msleep(&isp_fabric_hysteresis, + &isp->isp_osinfo.lock, PRIBIO, "ispT", + (isp->isp_osinfo.hysteresis * hz)); +#endif } } #if __FreeBSD_version < 500000 splx(s); +#elif __FreeBSD_version < 700037 + mtx_unlock(&Giant); #else - mtx_unlock(&Giant); + mtx_unlock(&isp->isp_osinfo.lock); #endif } static void isp_action(struct cam_sim *sim, union ccb *ccb) { - int bus, tgt, error, lim; + int bus, tgt, ts, error, lim; ispsoftc_t *isp; struct ccb_trans_settings *cts; CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n")); isp = (ispsoftc_t *)cam_sim_softc(sim); - ccb->ccb_h.sim_priv.entries[0].field = 0; - ccb->ccb_h.sim_priv.entries[1].ptr = isp; if (isp->isp_state != ISP_RUNSTATE && ccb->ccb_h.func_code == XPT_SCSI_IO) { isp_init(isp); @@ -2380,7 +2411,7 @@ isp->isp_state = ISP_RUNSTATE; } isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code); - + ISP_PCMD(ccb) = NULL; switch (ccb->ccb_h.func_code) { case XPT_SCSI_IO: /* Execute the requested I/O operation */ @@ -2407,30 +2438,34 @@ break; } #endif - ((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK; + ccb->csio.scsi_status = SCSI_STATUS_OK; + if (isp_get_pcmd(isp, ccb)) { + isp_prt(isp, ISP_LOGWARN, "out of PCMDs"); + cam_freeze_devq(ccb->ccb_h.path); + cam_release_devq(ccb->ccb_h.path, + RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0); + xpt_done(ccb); + break; + } error = isp_start((XS_T *) ccb); switch (error) { case CMD_QUEUED: XS_CMD_S_CLEAR(ccb); ccb->ccb_h.status |= CAM_SIM_QUEUED; - if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { - int ms = ccb->ccb_h.timeout; - if (ms == CAM_TIME_DEFAULT) { - ms = 60*1000; - } - ccb->ccb_h.timeout_ch = - timeout(isp_watchdog, ccb, isp_mstohz(ms)); - } else { - callout_handle_init(&ccb->ccb_h.timeout_ch); + if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) { + break; + } + ts = ccb->ccb_h.timeout; + if (ts == CAM_TIME_DEFAULT) { + ts = 60*1000; } + ts = isp_mstohz(ts); + callout_reset(&PISP_PCMD(ccb)->wdog, ts, + isp_watchdog, ccb); break; case CMD_RQLATER: + isp_free_pcmd(isp, ccb); /* - * This can only happen for Fibre Channel - */ - KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only")); - - /* * Handle initial and subsequent loop down cases */ if (FCPARAM(isp)->loop_seen_once == 0) { @@ -2461,15 +2496,15 @@ xpt_done(ccb); break; case CMD_EAGAIN: - cam_freeze_devq(ccb->ccb_h.path); - cam_release_devq(ccb->ccb_h.path, - RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0); + isp_free_pcmd(isp, ccb); + XS_SETERR(ccb, CAM_REQUEUE_REQ); xpt_done(ccb); break; case CMD_COMPLETE: isp_done((struct ccb_scsiio *) ccb); break; default: + isp_free_pcmd(isp, ccb); isp_prt(isp, ISP_LOGERR, "What's this? 0x%x at %d in file %s", error, __LINE__, __FILE__); @@ -2916,6 +2951,9 @@ if (error) ccb->ccb_h.status = CAM_REQ_CMP_ERR; else { + if (bootverbose) { + xpt_print(ccb->ccb_h.path, "reset bus\n"); + } if (cam_sim_bus(sim) && isp->isp_path2 != NULL) xpt_async(AC_BUS_RESET, isp->isp_path2, NULL); else if (isp->isp_path != NULL) @@ -3045,6 +3083,7 @@ "finished command on borrowed time"); } XS_CMD_S_CLEAR(sccb); + isp_free_pcmd(isp, (union ccb *) sccb); xpt_done((union ccb *) sccb); } } @@ -3177,9 +3216,9 @@ isp_freeze_loopdown(isp, msg); } if (isp->isp_osinfo.ldt_running == 0) { - isp->isp_osinfo.ldt = timeout(isp_ldt, isp, - isp->isp_osinfo.loop_down_limit * hz); isp->isp_osinfo.ldt_running = 1; + callout_reset(&isp->isp_osinfo.ldt, + isp->isp_osinfo.loop_down_limit * hz, isp_ldt, isp); isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "starting Loop Down Timer"); } @@ -3323,8 +3362,9 @@ if (isp->isp_osinfo.gdt_running == 0) { isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "starting Gone Device Timer"); - isp->isp_osinfo.gdt = timeout(isp_gdt, isp, hz); isp->isp_osinfo.gdt_running = 1; + callout_reset(&isp->isp_osinfo.gdt, hz, + isp_gdt, isp); } tgt = lp->ini_map_idx - 1; isp_prt(isp, ISP_LOGCONFIG, prom2, @@ -3361,12 +3401,11 @@ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Stopping Loop Down Timer"); isp->isp_osinfo.ldt_running = 0; - untimeout(isp_ldt, isp, isp->isp_osinfo.ldt); - callout_handle_init(&isp->isp_osinfo.ldt); + callout_stop(&isp->isp_osinfo.ldt); } isp_prt(isp, ISP_LOGINFO, msg); isp_freeze_loopdown(isp, msg); - wakeup(&isp->isp_osinfo.kproc); + wakeup(ISP_KT_WCHAN(isp)); break; } #ifdef ISP_TARGET_MODE @@ -3517,8 +3556,13 @@ isp->isp_osinfo.mbox_sleep_ok = 0; isp->isp_osinfo.mbox_sleeping = 1; for (olim = 0; olim < max; olim++) { +#if __FreeBSD_version < 700037 tsleep(&isp->isp_mbxworkp, PRIBIO, "ispmbx_sleep", isp_mstohz(ms)); +#else + msleep(&isp->isp_mbxworkp, &isp->isp_osinfo.lock, + PRIBIO, "ispmbx_sleep", isp_mstohz(ms)); +#endif if (isp->isp_osinfo.mboxcmd_done) { break; } @@ -3587,3 +3631,20 @@ } return (hz); } + +void +isp_platform_intr(void *arg) +{ + ispsoftc_t *isp = arg; + uint32_t isr; + uint16_t sema, mbox; + + ISP_LOCK(isp); + isp->isp_intcnt++; + if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) { + isp->isp_intbogus++; + } else { + isp_intr(isp, isr, sema, mbox); + } + ISP_UNLOCK(isp); +} ==== //depot/projects/mjexp/sys/dev/isp/isp_freebsd.h#13 (text+ko) ==== @@ -87,8 +87,10 @@ #if __FreeBSD_version < 500000 #define ISP_IFLAGS INTR_TYPE_CAM +#elif __FreeBSD_version < 700037 +#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY #else -#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY +#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE #endif #if __FreeBSD_version < 700000 @@ -132,10 +134,23 @@ ((lun) & (LUN_HASH_SIZE - 1))) #endif +/* + * Per command info. + */ +struct isp_pcmd { + struct isp_pcmd * next; + bus_dmamap_t dmap; /* dma map for this command */ + struct ispsoftc * isp; /* containing isp */ + struct callout wdog; /* watchdog timer */ +}; +#define ISP_PCMD(ccb) (ccb)->ccb_h.spriv_ptr1 +#define PISP_PCMD(ccb) ((struct isp_pcmd *)ISP_PCMD(ccb)) + struct isposinfo { struct ispsoftc * next; bus_space_tag_t bus_tag; bus_space_handle_t bus_handle; + bus_dma_tag_t dmat; uint64_t default_port_wwn; uint64_t default_node_wwn; uint32_t default_id; @@ -159,11 +174,14 @@ mbox_sleep_ok : 1, mboxcmd_done : 1, mboxbsy : 1; - struct callout_handle ldt; /* loop down timer */ - struct callout_handle gdt; /* gone device timer */ -#if __FreeBSD_version >= 500000 + struct callout ldt; /* loop down timer */ + struct callout gdt; /* gone device timer */ +#if __FreeBSD_version < 500000 + uint32_t splcount; + uint32_t splsaved; +#else + struct mtx lock; const struct firmware * fw; - struct mtx lock; union { struct { char wwnn[17]; @@ -176,6 +194,12 @@ bus_dmamap_t cdmap; #define isp_cdmat isp_osinfo.cdmat #define isp_cdmap isp_osinfo.cdmap + /* + * Per command information. + */ + struct isp_pcmd * pcmd_pool; + struct isp_pcmd * pcmd_free; + #ifdef ISP_TARGET_MODE #define TM_WILDCARD_ENABLED 0x02 #define TM_TMODE_ENABLED 0x01 @@ -187,6 +211,7 @@ atio_private_data_t atpdp[ATPDPSIZE]; #endif }; +#define ISP_KT_WCHAN(isp) (&(isp)->isp_osinfo.kproc) #define isp_lock isp_osinfo.lock #define isp_bus_tag isp_osinfo.bus_tag @@ -195,6 +220,25 @@ /* * Locking macros... */ +#if __FreeBSD_version < 500000 +#define ISP_LOCK(isp) \ + if (isp->isp_osinfo.splcount++ == 0) { \ + isp->isp_osinfo.splsaved = splcam(); \ + } +#define ISP_UNLOCK(isp) \ + if (isp->isp_osinfo.splcount > 1) { \ + isp->isp_osinfo.splcount--; \ + } else { \ + isp->isp_osinfo.splcount = 0; \ + splx(isp->isp_osinfo.splsaved); \ + } +#elif __FreeBSD_version < 700037 +#define ISP_LOCK(isp) do {} while (0) +#define ISP_UNLOCK(isp) do {} while (0) +#else +#define ISP_LOCK(isp) mtx_lock(&isp->isp_osinfo.lock) +#define ISP_UNLOCK(isp) mtx_unlock(&isp->isp_osinfo.lock) +#endif /* * Required Macros/Defines @@ -264,7 +308,7 @@ #define XS_T struct ccb_scsiio #define XS_DMA_ADDR_T bus_addr_t -#define XS_ISP(ccb) ((ispsoftc_t *) (ccb)->ccb_h.spriv_ptr1) +#define XS_ISP(ccb) cam_sim_softc(xpt_path_sim((ccb)->ccb_h.path)) #define XS_CHANNEL(ccb) cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path)) #define XS_TGT(ccb) (ccb)->ccb_h.target_id #define XS_LUN(ccb) (ccb)->ccb_h.target_lun @@ -465,6 +509,7 @@ void isp_mbox_notify_done(ispsoftc_t *); void isp_mbox_release(ispsoftc_t *); int isp_mstohz(int); +void isp_platform_intr(void *); /* * Platform Version specific defines @@ -478,11 +523,16 @@ #define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \ bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \ busdma_lock_mutex, &Giant, z) +#elif __FreeBSD_version < 700037 +#define BUS_DMA_ROOTARG(x) bus_get_dma_tag(x) +#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \ + bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \ + busdma_lock_mutex, &Giant, z) #else #define BUS_DMA_ROOTARG(x) bus_get_dma_tag(x) #define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \ bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \ - busdma_lock_mutex, &Giant, z) + busdma_lock_mutex, &isp->isp_osinfo.lock, z) #endif #if __FreeBSD_version < 700031 @@ -494,11 +544,14 @@ #if __FreeBSD_version < 500000 #define isp_sim_alloc cam_sim_alloc +#define isp_callout_init(x) callout_init(x) #elif __FreeBSD_version < 700037 +#define isp_callout_init(x) callout_init(x, 0) #define isp_sim_alloc cam_sim_alloc #else +#define isp_callout_init(x) callout_init(x, 1) #define isp_sim_alloc(a, b, c, d, e, f, g, h) \ - cam_sim_alloc(a, b, c, d, e, &Giant, f, g, h) + cam_sim_alloc(a, b, c, d, e, &(d)->isp_osinfo.lock, f, g, h) #endif /* Should be BUS_SPACE_MAXSIZE, but MAXPHYS is larger than BUS_SPACE_MAXSIZE */ @@ -507,6 +560,28 @@ /* * Platform specific inline functions */ +static inline int isp_get_pcmd(ispsoftc_t *, union ccb *); +static inline void isp_free_pcmd(ispsoftc_t *, union ccb *); + +static inline int +isp_get_pcmd(ispsoftc_t *isp, union ccb *ccb) +{ + ISP_PCMD(ccb) = isp->isp_osinfo.pcmd_free; + if (ISP_PCMD(ccb) == NULL) { + return (-1); + } + isp->isp_osinfo.pcmd_free = ((struct isp_pcmd *)ISP_PCMD(ccb))->next; + return (0); +} + +static inline void +isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb) +{ + ((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free; + isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb); + ISP_PCMD(ccb) = NULL; +} + /* * ISP General Library functions @@ -514,10 +589,4 @@ #include <dev/isp/isp_library.h> -/* - * XXX: Temp - */ -#if ISP_DEFAULT_ROLES == ISP_ROLE_BOTH -#error "Dual Role Temporarily Unsupported" -#endif #endif /* _ISP_FREEBSD_H */ ==== //depot/projects/mjexp/sys/dev/isp/isp_pci.c#23 (text+ko) ==== @@ -338,7 +338,6 @@ void * ih; int16_t pci_poff[_NREG_BLKS]; bus_dma_tag_t dmat; - bus_dmamap_t *dmaps; #if __FreeBSD_version > 700025 int msicount; #endif @@ -352,7 +351,6 @@ DEVMETHOD(device_detach, isp_pci_detach), { 0, 0 } }; -static void isp_pci_intr(void *); static driver_t isp_pci_driver = { "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) @@ -704,9 +702,6 @@ } } - callout_handle_init(&isp->isp_osinfo.ldt); - callout_handle_init(&isp->isp_osinfo.gdt); - if (IS_SCSI(isp)) { return; } @@ -1180,7 +1175,7 @@ locksetup++; #endif - if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_pci_intr, isp, + if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) { device_printf(dev, "could not setup interrupt\n"); goto bad; @@ -1203,53 +1198,47 @@ /* * Make sure we're in reset state. */ + ISP_LOCK(isp); isp_reset(isp); if (isp->isp_state != ISP_RESETSTATE) { + ISP_UNLOCK(isp); goto bad; } isp_init(isp); if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) { isp_uninit(isp); + ISP_UNLOCK(isp); goto bad; } isp_attach(isp); if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) { isp_uninit(isp); + ISP_UNLOCK(isp); goto bad; } - /* - * XXXX: Here is where we might unload the f/w module - * XXXX: (or decrease the reference count to it). - */ - + ISP_UNLOCK(isp); return (0); bad: - if (pcs && pcs->ih) { (void) bus_teardown_intr(dev, irq, pcs->ih); } - #if __FreeBSD_version >= 500000 if (locksetup && isp) { mtx_destroy(&isp->isp_osinfo.lock); } #endif - if (irq) { (void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq); } - #if __FreeBSD_version > 700025 if (pcs && pcs->msicount) { pci_release_msi(dev); } #endif - if (regs) { (void) bus_release_resource(dev, rtp, rgd, regs); } - if (pcs) { if (pcs->pci_isp.isp_param) { #ifdef ISP_FW_CRASH_DUMP @@ -1260,11 +1249,6 @@ free(pcs->pci_isp.isp_param, M_DEVBUF); } } - - /* - * XXXX: Here is where we might unload the f/w module - * XXXX: (or decrease the reference count to it). - */ return (ENXIO); } @@ -1283,22 +1267,6 @@ return (0); } -static void -isp_pci_intr(void *arg) -{ - ispsoftc_t *isp = arg; - uint32_t isr; - uint16_t sema, mbox; - - isp->isp_intcnt++; - if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) { - isp->isp_intbogus++; - } else { - isp_intr(isp, isr, sema, mbox); - } -} - - #define IspVirt2Off(a, x) \ (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \ _BLK_REG_SHFT] + ((x) & 0xfff)) @@ -1331,8 +1299,7 @@ } static int -isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp, - uint16_t *semap, uint16_t *mbp) +isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp) { uint16_t isr, sema; @@ -1739,9 +1706,11 @@ if (isp->isp_rquest) { return (0); } + ISP_UNLOCK(isp); if (isp->isp_maxcmds == 0) { isp_prt(isp, ISP_LOGERR, "maxcmds not set"); + ISP_LOCK(isp); return (1); } @@ -1754,11 +1723,22 @@ slim = (1 << 24); } + 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.pcmd_pool == NULL) { + isp_prt(isp, ISP_LOGERR, "cannot allocate pcmds"); + ISP_LOCK(isp); + return (1); + } + /* * XXX: We don't really support 64 bit target mode for parallel scsi yet */ #ifdef ISP_TARGET_MODE if (IS_SCSI(isp) && sizeof (bus_addr_t) > 4) { + free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); + ISP_LOCK(isp); isp_prt(isp, ISP_LOGERR, "we cannot do DAC for SPI cards yet"); return (1); } @@ -1766,7 +1746,9 @@ if (isp_dma_tag_create(BUS_DMA_ROOTARG(pcs->pci_dev), 1, slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, ISP_NSEGS, slim, 0, - &pcs->dmat)) { + &isp->isp_osinfo.dmat)) { + free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); + ISP_LOCK(isp); isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); return (1); } @@ -1775,6 +1757,8 @@ len = sizeof (XS_T **) * isp->isp_maxcmds; isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); if (isp->isp_xflist == NULL) { + free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); + ISP_LOCK(isp); isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array"); return (1); } @@ -1782,20 +1766,13 @@ len = sizeof (void **) * isp->isp_maxcmds; isp->isp_tgtlist = (void **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); if (isp->isp_tgtlist == NULL) { + free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); + free(isp->isp_xflist, M_DEVBUF); + ISP_LOCK(isp); isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array"); return (1); } #endif - len = sizeof (bus_dmamap_t) * isp->isp_maxcmds; - pcs->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK); - if (pcs->dmaps == NULL) { - isp_prt(isp, ISP_LOGERR, "can't alloc dma map storage"); - free(isp->isp_xflist, M_DEVBUF); -#ifdef ISP_TARGET_MODE - free(isp->isp_tgtlist, M_DEVBUF); -#endif - return (1); - } /* * Allocate and map the request, result queues, plus FC scratch area. @@ -1810,16 +1787,17 @@ /* * Create a tag for the control spaces- force it to within 32 bits. */ - if (isp_dma_tag_create(pcs->dmat, QENTRY_LEN, slim, + if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, ns, slim, 0, &isp->isp_cdmat)) { isp_prt(isp, ISP_LOGERR, "cannot create a dma tag for control spaces"); - free(pcs->dmaps, M_DEVBUF); + free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); free(isp->isp_xflist, M_DEVBUF); #ifdef ISP_TARGET_MODE free(isp->isp_tgtlist, M_DEVBUF); #endif + ISP_LOCK(isp); return (1); } @@ -1828,25 +1806,35 @@ isp_prt(isp, ISP_LOGERR, "cannot allocate %d bytes of CCB memory", len); bus_dma_tag_destroy(isp->isp_cdmat); + free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); free(isp->isp_xflist, M_DEVBUF); #ifdef ISP_TARGET_MODE free(isp->isp_tgtlist, M_DEVBUF); #endif - free(pcs->dmaps, M_DEVBUF); + ISP_LOCK(isp); return (1); } for (i = 0; i < isp->isp_maxcmds; i++) { - error = bus_dmamap_create(pcs->dmat, 0, &pcs->dmaps[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(pcs->dmat, pcs->dmaps[i]); + bus_dmamap_destroy(isp->isp_osinfo.dmat, + isp->isp_osinfo.pcmd_pool[i].dmap); } goto bad; } + isp_callout_init(&pcmd->wdog); + if (i == isp->isp_maxcmds-1) { + pcmd->next = NULL; + } else { + pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1]; + } } + isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; im.isp = isp; im.error = 0; @@ -1864,6 +1852,7 @@ base += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); FCPARAM(isp)->isp_scratch = base; } + ISP_LOCK(isp); return (0); bad: @@ -1873,8 +1862,9 @@ #ifdef ISP_TARGET_MODE free(isp->isp_tgtlist, M_DEVBUF); #endif - free(pcs->dmaps, M_DEVBUF); + free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); isp->isp_rquest = NULL; + ISP_LOCK(isp); return (1); } @@ -1917,7 +1907,6 @@ mush_t *mp; struct ccb_scsiio *csio; ispsoftc_t *isp; - struct isp_pcisoftc *pcs; bus_dmamap_t *dp; ct_entry_t *cto, *qe; uint8_t scsi_status; @@ -1998,12 +1987,12 @@ cto->ct_resid = 0; cto->ct_scsi_status = 0; - pcs = (struct isp_pcisoftc *)isp; - dp = &pcs->dmaps[isp_handle_index(handle & ISP_HANDLE_MASK)]; + dp = &ISP_PCMD(csio)->dmap; if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD); + bus_dmamap_sync(isp->isp_osinfo.dmat, *dp, BUS_DMASYNC_PREREAD); } else { - bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(isp->isp_osinfo.dmat, + *dp, BUS_DMASYNC_PREWRITE); } nxti = *mp->nxtip; @@ -2369,7 +2358,6 @@ mush_t *mp; ispsoftc_t *isp; struct ccb_scsiio *csio; - struct isp_pcisoftc *pcs; bus_dmamap_t *dp; bus_dma_segment_t *eseg; ispreqt7_t *rq; @@ -2391,14 +2379,14 @@ csio = mp->cmd_token; isp = mp->isp; rq = mp->rq; - pcs = (struct isp_pcisoftc *)mp->isp; - dp = &pcs->dmaps[isp_handle_index(rq->req_handle & ISP_HANDLE_MASK)]; + dp = &PISP_PCMD(csio)->dmap; nxti = *mp->nxtip; if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD); + bus_dmamap_sync(isp->isp_osinfo.dmat, *dp, BUS_DMASYNC_PREREAD); } else { - bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(isp->isp_osinfo.dmat, + *dp, BUS_DMASYNC_PREWRITE); } datalen = XS_XFRLEN(csio); @@ -2476,7 +2464,6 @@ mush_t *mp; ispsoftc_t *isp; struct ccb_scsiio *csio; - struct isp_pcisoftc *pcs; bus_dmamap_t *dp; bus_dma_segment_t *eseg; ispreq64_t *rq; @@ -2497,14 +2484,14 @@ csio = mp->cmd_token; isp = mp->isp; rq = mp->rq; - pcs = (struct isp_pcisoftc *)mp->isp; - dp = &pcs->dmaps[isp_handle_index(rq->req_handle & ISP_HANDLE_MASK)]; + dp = &PISP_PCMD(csio)->dmap; nxti = *mp->nxtip; if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD); + bus_dmamap_sync(isp->isp_osinfo.dmat, *dp, BUS_DMASYNC_PREREAD); } else { - bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(isp->isp_osinfo.dmat, + *dp, BUS_DMASYNC_PREWRITE); } datalen = XS_XFRLEN(csio); @@ -2610,7 +2597,6 @@ mush_t *mp; ispsoftc_t *isp; struct ccb_scsiio *csio; - struct isp_pcisoftc *pcs; bus_dmamap_t *dp; bus_dma_segment_t *eseg; >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704230252.l3N2q3ap001249>
