PERFORCE change 118630 for review
Matt Jacob
mjacob at FreeBSD.org
Mon Apr 23 02:52:04 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=118630
Change 118630 by mjacob at 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) <<<
More information about the p4-projects
mailing list