Various cleanups and fixes:

- Switch from timeout() to callout_*() for per-request timers.
- Use device_find_child() in the identify routine.
- Use device_printf() instead of passing device_get_nameunit() to
  printf().
- Expand the SBP_LOCK coverage simplifying the locking.
- Uninline STAILQ_FOREACH_SAFE().

Tested by:	sbruno
This commit is contained in:
John Baldwin 2014-05-27 19:56:02 +00:00
parent 2bdf7f79bc
commit 2cc18341a1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=266772

View File

@ -177,7 +177,7 @@ struct sbp_ocb {
struct sbp_dev *sdev;
int flags; /* XXX should be removed */
bus_dmamap_t dmamap;
struct callout_handle timeout_ch;
struct callout timer;
};
#define OCB_ACT_MGM 0
@ -250,8 +250,9 @@ struct sbp_softc {
int flags;
struct mtx mtx;
};
#define SBP_LOCK(sbp) mtx_lock(&(sbp)->mtx)
#define SBP_UNLOCK(sbp) mtx_unlock(&(sbp)->mtx)
#define SBP_LOCK(sbp) mtx_lock(&(sbp)->mtx)
#define SBP_UNLOCK(sbp) mtx_unlock(&(sbp)->mtx)
#define SBP_LOCK_ASSERT(sbp) mtx_assert(&(sbp)->mtx, MA_OWNED)
static void sbp_post_explore (void *);
static void sbp_recv (struct fw_xfer *);
@ -265,7 +266,6 @@ static void sbp_execute_ocb (void *, bus_dma_segment_t *, int, int);
static void sbp_free_ocb (struct sbp_dev *, struct sbp_ocb *);
static void sbp_abort_ocb (struct sbp_ocb *, int);
static void sbp_abort_all_ocbs (struct sbp_dev *, int);
static struct fw_xfer * sbp_write_cmd_locked (struct sbp_dev *, int, int);
static struct fw_xfer * sbp_write_cmd (struct sbp_dev *, int, int);
static struct sbp_ocb * sbp_get_ocb (struct sbp_dev *);
static struct sbp_ocb * sbp_enqueue_ocb (struct sbp_dev *, struct sbp_ocb *);
@ -337,7 +337,8 @@ SBP_DEBUG(0)
printf("sbp_identify\n");
END_DEBUG
BUS_ADD_CHILD(parent, 0, "sbp", device_get_unit(parent));
if (device_find_child(parent, "sbp", -1) == NULL)
BUS_ADD_CHILD(parent, 0, "sbp", -1);
}
/*
@ -346,17 +347,11 @@ END_DEBUG
static int
sbp_probe(device_t dev)
{
device_t pa;
SBP_DEBUG(0)
printf("sbp_probe\n");
END_DEBUG
pa = device_get_parent(dev);
if(device_get_unit(dev) != device_get_unit(pa)){
return(ENXIO);
}
device_set_desc(dev, "SBP-2/SCSI over FireWire");
#if 0
@ -460,6 +455,7 @@ sbp_alloc_lun(struct sbp_target *target)
int maxlun, lun, i;
sbp = target->sbp;
SBP_LOCK_ASSERT(sbp);
crom_init_context(&cc, target->fwdev->csrrom);
/* XXX shoud parse appropriate unit directories only */
maxlun = -1;
@ -476,8 +472,7 @@ END_DEBUG
crom_next(&cc);
}
if (maxlun < 0)
printf("%s:%d no LUN found\n",
device_get_nameunit(target->sbp->fd.dev),
device_printf(target->sbp->fd.dev, "%d no LUN found\n",
target->target_id);
maxlun ++;
@ -548,7 +543,7 @@ END_DEBUG
sdev->lun_id = lun;
sdev->target = target;
STAILQ_INIT(&sdev->ocbs);
CALLOUT_INIT(&sdev->login_callout);
callout_init_mtx(&sdev->login_callout, &sbp->mtx, 0);
sdev->status = SBP_DEV_RESET;
new = 1;
snprintf(sdev->bustgtlun, 32, "%s:%d:%d",
@ -592,7 +587,7 @@ END_DEBUG
/* XXX */
goto next;
}
callout_handle_init(&ocb->timeout_ch);
callout_init_mtx(&ocb->timer, &sbp->mtx, 0);
sbp_free_ocb(sdev, ocb);
}
next:
@ -648,8 +643,8 @@ END_DEBUG
STAILQ_INIT(&target->xferlist);
target->n_xfer = 0;
STAILQ_INIT(&target->mgm_ocb_queue);
CALLOUT_INIT(&target->mgm_ocb_timeout);
CALLOUT_INIT(&target->scan_callout);
callout_init_mtx(&target->mgm_ocb_timeout, &sbp->mtx, 0);
callout_init_mtx(&target->scan_callout, &sbp->mtx, 0);
target->luns = NULL;
target->num_lun = 0;
@ -693,6 +688,7 @@ static void
sbp_login_callout(void *arg)
{
struct sbp_dev *sdev = (struct sbp_dev *)arg;
SBP_LOCK_ASSERT(sdev->target->sbp);
sbp_mgm_orb(sdev, ORB_FUN_LGI, NULL);
}
@ -737,6 +733,7 @@ SBP_DEBUG(1)
END_DEBUG
sbp = target->sbp;
SBP_LOCK_ASSERT(sbp);
sbp_alloc_lun(target);
/* XXX untimeout mgm_ocb and dequeue */
@ -746,10 +743,8 @@ END_DEBUG
continue;
if (alive && (sdev->status != SBP_DEV_DEAD)) {
if (sdev->path != NULL) {
SBP_LOCK(sbp);
xpt_freeze_devq(sdev->path, 1);
sdev->freeze ++;
SBP_UNLOCK(sbp);
}
sbp_probe_lun(sdev);
sbp_show_sdev_info(sdev);
@ -778,10 +773,8 @@ SBP_DEBUG(0)
__func__);
END_DEBUG
if (sdev->path) {
SBP_LOCK(sbp);
xpt_freeze_devq(sdev->path, 1);
sdev->freeze ++;
SBP_UNLOCK(sbp);
}
sdev->status = SBP_DEV_RETRY;
sbp_cam_detach_sdev(sdev);
@ -810,13 +803,13 @@ sbp_post_busreset(void *arg)
SBP_DEBUG(0)
printf("sbp_post_busreset\n");
END_DEBUG
SBP_LOCK(sbp);
if ((sbp->sim->flags & SIMQ_FREEZED) == 0) {
SBP_LOCK(sbp);
xpt_freeze_simq(sbp->sim, /*count*/1);
sbp->sim->flags |= SIMQ_FREEZED;
SBP_UNLOCK(sbp);
}
microtime(&sbp->last_busreset);
SBP_UNLOCK(sbp);
}
static void
@ -837,6 +830,7 @@ END_DEBUG
if (sbp_cold > 0)
sbp_cold --;
SBP_LOCK(sbp);
#if 0
/*
* XXX don't let CAM the bus rest.
@ -887,7 +881,6 @@ END_DEBUG
if (target->num_lun == 0)
sbp_free_target(target);
}
SBP_LOCK(sbp);
xpt_release_simq(sbp->sim, /*run queue*/TRUE);
sbp->sim->flags &= ~SIMQ_FREEZED;
SBP_UNLOCK(sbp);
@ -896,16 +889,15 @@ END_DEBUG
#if NEED_RESPONSE
static void
sbp_loginres_callback(struct fw_xfer *xfer){
int s;
struct sbp_dev *sdev;
sdev = (struct sbp_dev *)xfer->sc;
SBP_DEBUG(1)
device_printf(sdev->target->sbp->fd.dev,"%s\n", __func__);
END_DEBUG
/* recycle */
s = splfw();
SBP_LOCK(sdev->target->sbp);
STAILQ_INSERT_TAIL(&sdev->target->sbp->fwb.xferlist, xfer, link);
splx(s);
SBP_UNLOCK(sdev->target->sbp);
return;
}
#endif
@ -914,15 +906,11 @@ static __inline void
sbp_xfer_free(struct fw_xfer *xfer)
{
struct sbp_dev *sdev;
int s;
sdev = (struct sbp_dev *)xfer->sc;
fw_xfer_unload(xfer);
s = splfw();
SBP_LOCK(sdev->target->sbp);
SBP_LOCK_ASSERT(sdev->target->sbp);
STAILQ_INSERT_TAIL(&sdev->target->xferlist, xfer, link);
SBP_UNLOCK(sdev->target->sbp);
splx(s);
}
static void
@ -937,11 +925,13 @@ sbp_reset_start_callback(struct fw_xfer *xfer)
"%s: %s failed: resp=%d\n", __func__, sdev->bustgtlun, xfer->resp);
}
SBP_LOCK(target->sbp);
for (i = 0; i < target->num_lun; i++) {
tsdev = target->luns[i];
if (tsdev != NULL && tsdev->status == SBP_DEV_LOGIN)
sbp_login(tsdev);
}
SBP_UNLOCK(target->sbp);
}
static void
@ -977,8 +967,9 @@ SBP_DEBUG(1)
"%s:%s\n", __func__, sdev->bustgtlun);
END_DEBUG
resp = xfer->resp;
SBP_LOCK(sdev->target->sbp);
sbp_xfer_free(xfer);
return;
SBP_UNLOCK(sdev->target->sbp);
}
static struct sbp_dev *
@ -1003,6 +994,7 @@ sbp_cam_scan_lun(struct cam_periph *periph, union ccb *ccb)
sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr;
target = sdev->target;
SBP_LOCK_ASSERT(target->sbp);
SBP_DEBUG(0)
device_printf(sdev->target->sbp->fd.dev,
"%s:%s\n", __func__, sdev->bustgtlun);
@ -1033,6 +1025,7 @@ sbp_cam_scan_target(void *arg)
struct sbp_dev *sdev;
union ccb *ccb;
SBP_LOCK_ASSERT(target->sbp);
sdev = sbp_next_dev(target, 0);
if (sdev == NULL) {
printf("sbp_cam_scan_target: nothing to do for target%d\n",
@ -1056,11 +1049,9 @@ END_DEBUG
ccb->ccb_h.ccb_sdev_ptr = sdev;
/* The scan is in progress now. */
SBP_LOCK(target->sbp);
xpt_action(ccb);
xpt_release_devq(sdev->path, sdev->freeze, TRUE);
sdev->freeze = 1;
SBP_UNLOCK(target->sbp);
}
static __inline void
@ -1081,6 +1072,7 @@ sbp_do_attach(struct fw_xfer *xfer)
sdev = (struct sbp_dev *)xfer->sc;
target = sdev->target;
sbp = target->sbp;
SBP_LOCK(sbp);
SBP_DEBUG(0)
device_printf(sdev->target->sbp->fd.dev,
"%s:%s\n", __func__, sdev->bustgtlun);
@ -1095,15 +1087,16 @@ END_DEBUG
/*
* Let CAM scan the bus if we are in the boot process.
* XXX xpt_scan_bus cannot detect LUN larger than 0
* if LUN 0 doesn't exists.
* if LUN 0 doesn't exist.
*/
if (sbp_cold > 0) {
sdev->status = SBP_DEV_ATTACHED;
SBP_UNLOCK(sbp);
return;
}
sbp_scan_dev(sdev);
return;
SBP_UNLOCK(sbp);
}
static void
@ -1121,13 +1114,13 @@ END_DEBUG
"%s:%s resp=%d\n", __func__, sdev->bustgtlun, xfer->resp);
}
SBP_LOCK(sdev->target->sbp);
sbp_xfer_free(xfer);
if (sdev->path) {
SBP_LOCK(sdev->target->sbp);
xpt_release_devq(sdev->path, sdev->freeze, TRUE);
sdev->freeze = 0;
SBP_UNLOCK(sdev->target->sbp);
}
SBP_UNLOCK(sdev->target->sbp);
}
static void
@ -1136,6 +1129,7 @@ sbp_agent_reset(struct sbp_dev *sdev)
struct fw_xfer *xfer;
struct fw_pkt *fp;
SBP_LOCK_ASSERT(sdev->target->sbp);
SBP_DEBUG(0)
device_printf(sdev->target->sbp->fd.dev,
"%s:%s\n", __func__, sdev->bustgtlun);
@ -1163,8 +1157,10 @@ SBP_DEBUG(1)
device_printf(sdev->target->sbp->fd.dev,
"%s:%s\n", __func__, sdev->bustgtlun);
END_DEBUG
SBP_LOCK(sdev->target->sbp);
sbp_xfer_free(xfer);
sbp_agent_reset(sdev);
SBP_UNLOCK(sdev->target->sbp);
}
static void
@ -1200,9 +1196,9 @@ END_DEBUG
/* XXX */
printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
}
SBP_LOCK(sdev->target->sbp);
sbp_xfer_free(xfer);
SBP_LOCK(sdev->target->sbp);
sdev->flags &= ~ORB_POINTER_ACTIVE;
if ((sdev->flags & ORB_POINTER_NEED) != 0) {
@ -1229,7 +1225,7 @@ SBP_DEBUG(1)
(uint32_t)ocb->bus_addr);
END_DEBUG
mtx_assert(&sdev->target->sbp->mtx, MA_OWNED);
SBP_LOCK_ASSERT(sdev->target->sbp);
if ((sdev->flags & ORB_POINTER_ACTIVE) != 0) {
SBP_DEBUG(0)
@ -1240,7 +1236,7 @@ END_DEBUG
}
sdev->flags |= ORB_POINTER_ACTIVE;
xfer = sbp_write_cmd_locked(sdev, FWTCODE_WREQB, 0x08);
xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0x08);
if (xfer == NULL)
return;
xfer->hand = sbp_orb_pointer_callback;
@ -1252,18 +1248,11 @@ END_DEBUG
htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16));
xfer->send.payload[1] = htonl((uint32_t)ocb->bus_addr);
/*
* sbp_xfer_free() will attempt to acquire
* the SBP lock on entrance. Also, this removes
* a LOR between the firewire layer and sbp
*/
SBP_UNLOCK(sdev->target->sbp);
if(fw_asyreq(xfer->fc, -1, xfer) != 0){
sbp_xfer_free(xfer);
ocb->ccb->ccb_h.status = CAM_REQ_INVALID;
xpt_done(ocb->ccb);
if (fw_asyreq(xfer->fc, -1, xfer) != 0) {
sbp_xfer_free(xfer);
ocb->ccb->ccb_h.status = CAM_REQ_INVALID;
xpt_done(ocb->ccb);
}
SBP_LOCK(sdev->target->sbp);
}
static void
@ -1281,15 +1270,14 @@ END_DEBUG
device_printf(sdev->target->sbp->fd.dev,
"%s: xfer->resp = %d\n", __func__, xfer->resp);
}
SBP_LOCK(sdev->target->sbp);
sbp_xfer_free(xfer);
sdev->flags &= ~ORB_DOORBELL_ACTIVE;
if ((sdev->flags & ORB_DOORBELL_NEED) != 0) {
sdev->flags &= ~ORB_DOORBELL_NEED;
SBP_LOCK(sdev->target->sbp);
sbp_doorbell(sdev);
SBP_UNLOCK(sdev->target->sbp);
}
return;
SBP_UNLOCK(sdev->target->sbp);
}
static void
@ -1307,7 +1295,7 @@ END_DEBUG
return;
}
sdev->flags |= ORB_DOORBELL_ACTIVE;
xfer = sbp_write_cmd_locked(sdev, FWTCODE_WREQQ, 0x10);
xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x10);
if (xfer == NULL)
return;
xfer->hand = sbp_doorbell_callback;
@ -1317,28 +1305,25 @@ END_DEBUG
}
static struct fw_xfer *
sbp_write_cmd_locked(struct sbp_dev *sdev, int tcode, int offset)
sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
{
struct fw_xfer *xfer;
struct fw_pkt *fp;
struct sbp_target *target;
int s, new = 0;
int new = 0;
mtx_assert(&sdev->target->sbp->mtx, MA_OWNED);
SBP_LOCK_ASSERT(sdev->target->sbp);
target = sdev->target;
s = splfw();
xfer = STAILQ_FIRST(&target->xferlist);
if (xfer == NULL) {
if (target->n_xfer > 5 /* XXX */) {
printf("sbp: no more xfer for this target\n");
splx(s);
return(NULL);
}
xfer = fw_xfer_alloc_buf(M_SBP, 8, 0);
if(xfer == NULL){
printf("sbp: fw_xfer_alloc_buf failed\n");
splx(s);
return NULL;
}
target->n_xfer ++;
@ -1348,7 +1333,6 @@ sbp_write_cmd_locked(struct sbp_dev *sdev, int tcode, int offset)
} else {
STAILQ_REMOVE_HEAD(&target->xferlist, link);
}
splx(s);
if (new) {
xfer->recv.pay_len = 0;
@ -1371,20 +1355,6 @@ sbp_write_cmd_locked(struct sbp_dev *sdev, int tcode, int offset)
fp->mode.wreqq.dst = FWLOCALBUS | sdev->target->fwdev->dst;
return xfer;
}
static struct fw_xfer *
sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
{
struct sbp_softc *sbp = sdev->target->sbp;
struct fw_xfer *xfer;
SBP_LOCK(sbp);
xfer = sbp_write_cmd_locked(sdev, tcode, offset);
SBP_UNLOCK(sbp);
return (xfer);
}
static void
@ -1394,31 +1364,24 @@ sbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb)
struct fw_pkt *fp;
struct sbp_ocb *ocb;
struct sbp_target *target;
int s, nid;
int nid;
target = sdev->target;
nid = target->sbp->fd.fc->nodeid | FWLOCALBUS;
s = splfw();
SBP_LOCK(target->sbp);
SBP_LOCK_ASSERT(target->sbp);
if (func == ORB_FUN_RUNQUEUE) {
ocb = STAILQ_FIRST(&target->mgm_ocb_queue);
if (target->mgm_ocb_cur != NULL || ocb == NULL) {
SBP_UNLOCK(target->sbp);
splx(s);
return;
}
STAILQ_REMOVE_HEAD(&target->mgm_ocb_queue, ocb);
SBP_UNLOCK(target->sbp);
goto start;
}
if ((ocb = sbp_get_ocb(sdev)) == NULL) {
SBP_UNLOCK(target->sbp);
splx(s);
/* XXX */
return;
}
SBP_UNLOCK(target->sbp);
ocb->flags = OCB_ACT_MGM;
ocb->sdev = sdev;
@ -1458,15 +1421,11 @@ END_DEBUG
if (target->mgm_ocb_cur != NULL) {
/* there is a standing ORB */
SBP_LOCK(target->sbp);
STAILQ_INSERT_TAIL(&sdev->target->mgm_ocb_queue, ocb, ocb);
SBP_UNLOCK(target->sbp);
splx(s);
return;
}
start:
target->mgm_ocb_cur = ocb;
splx(s);
callout_reset(&target->mgm_ocb_timeout, 5*hz,
sbp_mgm_timeout, (caddr_t)ocb);
@ -1677,6 +1636,7 @@ printf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), nt
printf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11]));
*/
sbp = (struct sbp_softc *)xfer->sc;
SBP_LOCK_ASSERT(sbp);
if (xfer->resp != 0){
printf("sbp_recv: xfer->resp = %d\n", xfer->resp);
goto done0;
@ -1796,10 +1756,8 @@ END_DEBUG
/* we have to reset the fetch agent if it's dead */
if (sbp_status->dead) {
if (sdev->path) {
SBP_LOCK(sbp);
xpt_freeze_devq(sdev->path, 1);
sdev->freeze ++;
SBP_UNLOCK(sbp);
}
reset_agent = 1;
}
@ -1904,9 +1862,7 @@ END_DEBUG
/* fix up inq data */
if (ccb->csio.cdb_io.cdb_bytes[0] == INQUIRY)
sbp_fix_inq_data(ocb);
SBP_LOCK(sbp);
xpt_done(ccb);
SBP_UNLOCK(sbp);
}
break;
default:
@ -1945,22 +1901,19 @@ END_DEBUG
fw_asyreq(xfer->fc, -1, xfer);
#else
/* recycle */
/* we don't need a lock here because bottom half is serialized */
STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link);
#endif
return;
}
static void
sbp_recv(struct fw_xfer *xfer)
{
int s;
struct sbp_softc *sbp;
s = splcam();
sbp = (struct sbp_softc *)xfer->sc;
SBP_LOCK(sbp);
sbp_recv1(xfer);
splx(s);
SBP_UNLOCK(sbp);
}
/*
* sbp_attach()
@ -1971,7 +1924,7 @@ sbp_attach(device_t dev)
struct sbp_softc *sbp;
struct cam_devq *devq;
struct firewire_comm *fc;
int i, s, error;
int i, error;
if (DFLTPHYS > SBP_MAXPHYS)
device_printf(dev, "Warning, DFLTPHYS(%dKB) is larger than "
@ -1987,8 +1940,7 @@ END_DEBUG
if (cold)
sbp_cold ++;
sbp = ((struct sbp_softc *)device_get_softc(dev));
bzero(sbp, sizeof(struct sbp_softc));
sbp = device_get_softc(dev);
sbp->fd.dev = dev;
sbp->fd.fc = fc = device_get_ivars(dev);
mtx_init(&sbp->mtx, "sbp", NULL, MTX_DEF);
@ -2064,10 +2016,8 @@ END_DEBUG
sbp->fd.post_explore = sbp_post_explore;
if (fc->status != -1) {
s = splfw();
sbp_post_busreset((void *)sbp);
sbp_post_explore((void *)sbp);
splx(s);
}
SBP_LOCK(sbp);
xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL);
@ -2090,6 +2040,7 @@ sbp_logout_all(struct sbp_softc *sbp)
SBP_DEBUG(0)
printf("sbp_logout_all\n");
END_DEBUG
SBP_LOCK_ASSERT(sbp);
for (i = 0 ; i < SBP_NUM_TARGETS ; i ++) {
target = &sbp->targets[i];
if (target->luns == NULL)
@ -2113,23 +2064,30 @@ sbp_shutdown(device_t dev)
{
struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev));
SBP_LOCK(sbp);
sbp_logout_all(sbp);
SBP_UNLOCK(sbp);
return (0);
}
static void
sbp_free_sdev(struct sbp_dev *sdev)
{
struct sbp_softc *sbp;
int i;
if (sdev == NULL)
return;
for (i = 0; i < SBP_QUEUE_LEN; i++)
bus_dmamap_destroy(sdev->target->sbp->dmat,
sdev->ocb[i].dmamap);
fwdma_free(sdev->target->sbp->fd.fc, &sdev->dma);
sbp = sdev->target->sbp;
SBP_UNLOCK(sbp);
callout_drain(&sdev->login_callout);
for (i = 0; i < SBP_QUEUE_LEN; i++) {
callout_drain(&sdev->ocb[i].timer);
bus_dmamap_destroy(sbp->dmat, sdev->ocb[i].dmamap);
}
fwdma_free(sbp->fd.fc, &sdev->dma);
free(sdev, M_SBP);
sdev = NULL;
SBP_LOCK(sbp);
}
static void
@ -2141,14 +2099,16 @@ sbp_free_target(struct sbp_target *target)
if (target->luns == NULL)
return;
callout_stop(&target->mgm_ocb_timeout);
sbp = target->sbp;
SBP_LOCK_ASSERT(sbp);
SBP_UNLOCK(sbp);
callout_drain(&target->mgm_ocb_timeout);
callout_drain(&target->scan_callout);
SBP_LOCK(sbp);
for (i = 0; i < target->num_lun; i++)
sbp_free_sdev(target->luns[i]);
for (xfer = STAILQ_FIRST(&target->xferlist);
xfer != NULL; xfer = next) {
next = STAILQ_NEXT(xfer, link);
STAILQ_FOREACH_SAFE(xfer, &target->xferlist, link, next) {
fw_xfer_free_buf(xfer);
}
STAILQ_INIT(&target->xferlist);
@ -2169,23 +2129,25 @@ SBP_DEBUG(0)
printf("sbp_detach\n");
END_DEBUG
SBP_LOCK(sbp);
for (i = 0; i < SBP_NUM_TARGETS; i ++)
sbp_cam_detach_target(&sbp->targets[i]);
SBP_LOCK(sbp);
xpt_async(AC_LOST_DEVICE, sbp->path, NULL);
xpt_free_path(sbp->path);
xpt_bus_deregister(cam_sim_path(sbp->sim));
cam_sim_free(sbp->sim, /*free_devq*/ TRUE);
SBP_UNLOCK(sbp);
sbp_logout_all(sbp);
SBP_UNLOCK(sbp);
/* XXX wait for logout completion */
pause("sbpdtc", hz/2);
SBP_LOCK(sbp);
for (i = 0 ; i < SBP_NUM_TARGETS ; i ++)
sbp_free_target(&sbp->targets[i]);
SBP_UNLOCK(sbp);
fw_bindremove(fc, &sbp->fwb);
fw_xferlist_remove(&sbp->fwb.xferlist);
@ -2205,16 +2167,15 @@ sbp_cam_detach_sdev(struct sbp_dev *sdev)
return;
if (sdev->status == SBP_DEV_RESET)
return;
SBP_LOCK_ASSERT(sdev->target->sbp);
sbp_abort_all_ocbs(sdev, CAM_DEV_NOT_THERE);
if (sdev->path) {
SBP_LOCK(sdev->target->sbp);
xpt_release_devq(sdev->path,
sdev->freeze, TRUE);
sdev->freeze = 0;
xpt_async(AC_LOST_DEVICE, sdev->path, NULL);
xpt_free_path(sdev->path);
sdev->path = NULL;
SBP_UNLOCK(sdev->target->sbp);
}
}
@ -2223,6 +2184,7 @@ sbp_cam_detach_target(struct sbp_target *target)
{
int i;
SBP_LOCK_ASSERT(target->sbp);
if (target->luns != NULL) {
SBP_DEBUG(0)
printf("sbp_detach_target %d\n", target->target_id);
@ -2240,6 +2202,7 @@ sbp_target_reset(struct sbp_dev *sdev, int method)
struct sbp_target *target = sdev->target;
struct sbp_dev *tsdev;
SBP_LOCK_ASSERT(target->sbp);
for (i = 0; i < target->num_lun; i++) {
tsdev = target->luns[i];
if (tsdev == NULL)
@ -2248,10 +2211,8 @@ sbp_target_reset(struct sbp_dev *sdev, int method)
continue;
if (tsdev->status == SBP_DEV_RESET)
continue;
SBP_LOCK(target->sbp);
xpt_freeze_devq(tsdev->path, 1);
tsdev->freeze ++;
SBP_UNLOCK(target->sbp);
sbp_abort_all_ocbs(tsdev, CAM_CMD_TIMEOUT);
if (method == 2)
tsdev->status = SBP_DEV_LOGIN;
@ -2276,6 +2237,7 @@ sbp_mgm_timeout(void *arg)
struct sbp_dev *sdev = ocb->sdev;
struct sbp_target *target = sdev->target;
SBP_LOCK_ASSERT(target->sbp);
device_printf(sdev->target->sbp->fd.dev,
"%s:%s request timeout(mgm orb:0x%08x)\n",
__func__, sdev->bustgtlun, (uint32_t)ocb->bus_addr);
@ -2302,14 +2264,13 @@ sbp_timeout(void *arg)
"%s:%s request timeout(cmd orb:0x%08x) ... ",
__func__, sdev->bustgtlun, (uint32_t)ocb->bus_addr);
SBP_LOCK_ASSERT(sdev->target->sbp);
sdev->timeout ++;
switch(sdev->timeout) {
case 1:
printf("agent reset\n");
SBP_LOCK(sdev->target->sbp);
xpt_freeze_devq(sdev->path, 1);
sdev->freeze ++;
SBP_UNLOCK(sdev->target->sbp);
sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT);
sbp_agent_reset(sdev);
break;
@ -2331,13 +2292,15 @@ sbp_timeout(void *arg)
}
static void
sbp_action1(struct cam_sim *sim, union ccb *ccb)
sbp_action(struct cam_sim *sim, union ccb *ccb)
{
struct sbp_softc *sbp = (struct sbp_softc *)sim->softc;
struct sbp_target *target = NULL;
struct sbp_dev *sdev = NULL;
if (sbp != NULL)
SBP_LOCK_ASSERT(sbp);
/* target:lun -> sdev mapping */
if (sbp != NULL
&& ccb->ccb_h.target_id != CAM_TARGET_WILDCARD
@ -2459,10 +2422,8 @@ END_DEBUG
if ((ocb = sbp_get_ocb(sdev)) == NULL) {
ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
if (sdev->freeze == 0) {
SBP_LOCK(sdev->target->sbp);
xpt_freeze_devq(sdev->path, 1);
sdev->freeze ++;
SBP_UNLOCK(sdev->target->sbp);
}
xpt_done(ccb);
return;
@ -2518,7 +2479,7 @@ printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntoh
ccg = &ccb->ccg;
if (ccg->block_size == 0) {
printf("sbp_action1: block_size is 0.\n");
printf("sbp_action: block_size is 0.\n");
ccb->ccb_h.status = CAM_REQ_INVALID;
xpt_done(ccb);
break;
@ -2642,16 +2603,6 @@ END_DEBUG
return;
}
static void
sbp_action(struct cam_sim *sim, union ccb *ccb)
{
int s;
s = splfw();
sbp_action1(sim, ccb);
splx(s);
}
static void
sbp_execute_ocb(void *arg, bus_dma_segment_t *segments, int seg, int error)
{
@ -2747,7 +2698,7 @@ sbp_dequeue_ocb(struct sbp_dev *sdev, struct sbp_status *sbp_status)
{
struct sbp_ocb *ocb;
struct sbp_ocb *next;
int s = splfw(), order = 0;
int order = 0;
SBP_DEBUG(1)
device_printf(sdev->target->sbp->fd.dev,
@ -2758,15 +2709,13 @@ SBP_DEBUG(1)
#endif
__func__, sdev->bustgtlun, ntohl(sbp_status->orb_lo), sbp_status->src);
END_DEBUG
SBP_LOCK(sdev->target->sbp);
for (ocb = STAILQ_FIRST(&sdev->ocbs); ocb != NULL; ocb = next) {
next = STAILQ_NEXT(ocb, ocb);
SBP_LOCK_ASSERT(sdev->target->sbp);
STAILQ_FOREACH_SAFE(ocb, &sdev->ocbs, ocb, next) {
if (OCB_MATCH(ocb, sbp_status)) {
/* found */
STAILQ_REMOVE(&sdev->ocbs, ocb, sbp_ocb, ocb);
if (ocb->ccb != NULL)
untimeout(sbp_timeout, (caddr_t)ocb,
ocb->timeout_ch);
callout_stop(&ocb->timer);
if (ntohl(ocb->orb[4]) & 0xffff) {
bus_dmamap_sync(sdev->target->sbp->dmat,
ocb->dmamap,
@ -2795,9 +2744,7 @@ END_DEBUG
* execution.
*/
if (sdev->last_ocb != NULL) {
SBP_UNLOCK(sdev->target->sbp);
sbp_free_ocb(sdev, sdev->last_ocb);
SBP_LOCK(sdev->target->sbp);
}
sdev->last_ocb = ocb;
if (next != NULL &&
@ -2808,8 +2755,6 @@ END_DEBUG
} else
order ++;
}
SBP_UNLOCK(sdev->target->sbp);
splx(s);
SBP_DEBUG(0)
if (ocb && order > 0) {
device_printf(sdev->target->sbp->fd.dev,
@ -2823,10 +2768,9 @@ END_DEBUG
static struct sbp_ocb *
sbp_enqueue_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb)
{
int s = splfw();
struct sbp_ocb *prev, *prev2;
mtx_assert(&sdev->target->sbp->mtx, MA_OWNED);
SBP_LOCK_ASSERT(sdev->target->sbp);
SBP_DEBUG(1)
device_printf(sdev->target->sbp->fd.dev,
#if defined(__DragonFly__) || __FreeBSD_version < 500000
@ -2839,8 +2783,8 @@ END_DEBUG
STAILQ_INSERT_TAIL(&sdev->ocbs, ocb, ocb);
if (ocb->ccb != NULL)
ocb->timeout_ch = timeout(sbp_timeout, (caddr_t)ocb,
(ocb->ccb->ccb_h.timeout * hz) / 1000);
callout_reset(&ocb->timer, (ocb->ccb->ccb_h.timeout * hz) / 1000,
sbp_timeout, ocb);
if (use_doorbell && prev == NULL)
prev2 = sdev->last_ocb;
@ -2863,7 +2807,6 @@ END_DEBUG
*(volatile uint32_t *)&prev2->orb[1] = htonl(ocb->bus_addr);
*(volatile uint32_t *)&prev2->orb[0] = 0;
}
splx(s);
return prev;
}
@ -2872,18 +2815,15 @@ static struct sbp_ocb *
sbp_get_ocb(struct sbp_dev *sdev)
{
struct sbp_ocb *ocb;
int s = splfw();
mtx_assert(&sdev->target->sbp->mtx, MA_OWNED);
SBP_LOCK_ASSERT(sdev->target->sbp);
ocb = STAILQ_FIRST(&sdev->free_ocbs);
if (ocb == NULL) {
sdev->flags |= ORB_SHORTAGE;
printf("ocb shortage!!!\n");
splx(s);
return NULL;
}
STAILQ_REMOVE_HEAD(&sdev->free_ocbs, ocb);
splx(s);
ocb->ccb = NULL;
return (ocb);
}
@ -2894,7 +2834,7 @@ sbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb)
ocb->flags = 0;
ocb->ccb = NULL;
SBP_LOCK(sdev->target->sbp);
SBP_LOCK_ASSERT(sdev->target->sbp);
STAILQ_INSERT_TAIL(&sdev->free_ocbs, ocb, ocb);
if ((sdev->flags & ORB_SHORTAGE) != 0) {
int count;
@ -2904,7 +2844,6 @@ sbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb)
sdev->freeze = 0;
xpt_release_devq(sdev->path, count, TRUE);
}
SBP_UNLOCK(sdev->target->sbp);
}
static void
@ -2913,6 +2852,7 @@ sbp_abort_ocb(struct sbp_ocb *ocb, int status)
struct sbp_dev *sdev;
sdev = ocb->sdev;
SBP_LOCK_ASSERT(sdev->target->sbp);
SBP_DEBUG(0)
device_printf(sdev->target->sbp->fd.dev,
#if defined(__DragonFly__) || __FreeBSD_version < 500000
@ -2932,12 +2872,9 @@ END_DEBUG
bus_dmamap_unload(sdev->target->sbp->dmat, ocb->dmamap);
}
if (ocb->ccb != NULL) {
untimeout(sbp_timeout, (caddr_t)ocb,
ocb->timeout_ch);
callout_stop(&ocb->timer);
ocb->ccb->ccb_h.status = status;
SBP_LOCK(sdev->target->sbp);
xpt_done(ocb->ccb);
SBP_UNLOCK(sdev->target->sbp);
}
sbp_free_ocb(sdev, ocb);
}
@ -2945,28 +2882,21 @@ END_DEBUG
static void
sbp_abort_all_ocbs(struct sbp_dev *sdev, int status)
{
int s;
struct sbp_ocb *ocb, *next;
STAILQ_HEAD(, sbp_ocb) temp;
s = splfw();
STAILQ_INIT(&temp);
SBP_LOCK(sdev->target->sbp);
SBP_LOCK_ASSERT(sdev->target->sbp);
STAILQ_CONCAT(&temp, &sdev->ocbs);
STAILQ_INIT(&sdev->ocbs);
SBP_UNLOCK(sdev->target->sbp);
for (ocb = STAILQ_FIRST(&temp); ocb != NULL; ocb = next) {
next = STAILQ_NEXT(ocb, ocb);
STAILQ_FOREACH_SAFE(ocb, &temp, ocb, next) {
sbp_abort_ocb(ocb, status);
}
if (sdev->last_ocb != NULL) {
sbp_free_ocb(sdev, sdev->last_ocb);
sdev->last_ocb = NULL;
}
splx(s);
}
static devclass_t sbp_devclass;