int
mpt_intr(void *arg)
{
	mpt_softc_t *mpt = arg;
	int nrepl = 0;
	uint32_t reply;

	if ((mpt_read(mpt, MPT_OFFSET_INTR_STATUS) & MPT_INTR_REPLY_READY) == 0)
		return (0);

	reply = mpt_pop_reply_queue(mpt);
	while (reply != MPT_REPLY_EMPTY) {
		nrepl++;
		if (mpt->verbose > 1) {
			if ((reply & MPT_CONTEXT_REPLY) != 0) {
				/* Address reply; IOC has something to say */
				mpt_print_reply(MPT_REPLY_PTOV(mpt, reply));
			} else {
				/* Context reply; all went well */
				mpt_prt(mpt, "context %u reply OK", reply);
			}
		}
		mpt_done(mpt, reply);
		reply = mpt_pop_reply_queue(mpt);
	}
	return (nrepl != 0);
}
예제 #2
0
파일: mpt_freebsd.c 프로젝트: MarginC/kame
/*
 * This routine is called if the 9x9 does not return completion status
 * for a command after a CAM specified time.
 */
static void
mpttimeout(void *arg)
{
	request_t *req;
	union ccb *ccb = arg;
	u_int32_t oseq;
	mpt_softc_t *mpt;

	mpt = ccb->ccb_h.ccb_mpt_ptr;
	MPT_LOCK(mpt);
	req = ccb->ccb_h.ccb_req_ptr;
	oseq = req->sequence;
	mpt->timeouts++;
	if (mpt_intr(mpt)) {
		if (req->sequence != oseq) {
			mpt_prt(mpt, "bullet missed in timeout");
			MPT_UNLOCK(mpt);
			return;
		}
		mpt_prt(mpt, "bullet U-turned in timeout: got us");
	}
	mpt_prt(mpt,
	    "time out on request index = 0x%02x sequence = 0x%08x",
	    req->index, req->sequence);
        mpt_check_doorbell(mpt);
	mpt_prt(mpt, "Status %08x; Mask %08x; Doorbell %08x",
		mpt_read(mpt, MPT_OFFSET_INTR_STATUS),
		mpt_read(mpt, MPT_OFFSET_INTR_MASK),
		mpt_read(mpt, MPT_OFFSET_DOORBELL) );
	printf("request state %s\n", mpt_req_state(req->debug)); 
	if (ccb != req->ccb) {
		printf("time out: ccb %p != req->ccb %p\n",
			ccb,req->ccb);
	}
	mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
	req->debug = REQ_TIMEOUT;
	req->ccb = NULL;
	req->link.sle_next = (void *) mpt;
	(void) timeout(mpttimeout2, (caddr_t)req, hz / 10);
	ccb->ccb_h.status = CAM_CMD_TIMEOUT;
	ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
	mpt->outofbeer = 0;
	MPTLOCK_2_CAMLOCK(mpt);
	xpt_done(ccb);
	CAMLOCK_2_MPTLOCK(mpt);
	MPT_UNLOCK(mpt);
}
static void
mpt_timeout(void *arg)
{
	request_t *req = arg;
	struct scsipi_xfer *xs = req->xfer;
	struct scsipi_periph *periph = xs->xs_periph;
	mpt_softc_t *mpt = DEV_TO_MPT(
	    periph->periph_channel->chan_adapter->adapt_dev);
	uint32_t oseq;
	int s;

	scsipi_printaddr(periph);
	printf("command timeout\n");

	s = splbio();

	oseq = req->sequence;
	mpt->timeouts++;
	if (mpt_intr(mpt)) {
		if (req->sequence != oseq) {
			mpt_prt(mpt, "recovered from command timeout");
			splx(s);
			return;
		}
	}
	mpt_prt(mpt,
	    "timeout on request index = 0x%x, seq = 0x%08x",
	    req->index, req->sequence);
	mpt_check_doorbell(mpt);
	mpt_prt(mpt, "Status 0x%08x, Mask 0x%08x, Doorbell 0x%08x",
	    mpt_read(mpt, MPT_OFFSET_INTR_STATUS),
	    mpt_read(mpt, MPT_OFFSET_INTR_MASK),
	    mpt_read(mpt, MPT_OFFSET_DOORBELL));
	mpt_prt(mpt, "request state: %s", mpt_req_state(req->debug));
	if (mpt->verbose > 1)
		mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);

	/* XXX WHAT IF THE IOC IS STILL USING IT?? */
	req->xfer = NULL;
	mpt_free_request(mpt, req);

	xs->error = XS_TIMEOUT;
	scsipi_done(xs);

	splx(s);
}
예제 #4
0
int
mpt_intr(void *arg)
{
	mpt_softc_t *mpt = arg;
	int nrepl = 0;

	if ((mpt_read(mpt, MPT_OFFSET_INTR_STATUS) & MPT_INTR_REPLY_READY) == 0)
		return (0);

	nrepl = mpt_drain_queue(mpt);
	return (nrepl != 0);
}
예제 #5
0
static void
mpt_timeout(void *arg)
{
	request_t *req = arg;
	struct scsipi_xfer *xs;
	struct scsipi_periph *periph;
	mpt_softc_t *mpt;
 	uint32_t oseq;
	int s, nrepl = 0;
 
	if (req->xfer  == NULL) {
		printf("mpt_timeout: NULL xfer for request index 0x%x, sequenc 0x%x\n",
		req->index, req->sequence);
		return;
	}
	xs = req->xfer;
	periph = xs->xs_periph;
	mpt = (void *) periph->periph_channel->chan_adapter->adapt_dev;
	scsipi_printaddr(periph);
	printf("command timeout\n");

	s = splbio();

	oseq = req->sequence;
	mpt->timeouts++;
	if (mpt_intr(mpt)) {
		if (req->sequence != oseq) {
			mpt->success++;
			mpt_prt(mpt, "recovered from command timeout");
			splx(s);
			return;
		}
	}

	/*
	 * Ensure the IOC is really done giving us data since it appears it can
	 * sometimes fail to give us interrupts under heavy load.
	 */
	nrepl = mpt_drain_queue(mpt);
	if (nrepl ) {
		mpt_prt(mpt, "mpt_timeout: recovered %d commands",nrepl);
	}

	if (req->sequence != oseq) {
		mpt->success++;
		splx(s);
		return;
	}

	mpt_prt(mpt,
	    "timeout on request index = 0x%x, seq = 0x%08x",
	    req->index, req->sequence);
	mpt_check_doorbell(mpt);
	mpt_prt(mpt, "Status 0x%08x, Mask 0x%08x, Doorbell 0x%08x",
	    mpt_read(mpt, MPT_OFFSET_INTR_STATUS),
	    mpt_read(mpt, MPT_OFFSET_INTR_MASK),
	    mpt_read(mpt, MPT_OFFSET_DOORBELL));
	mpt_prt(mpt, "request state: %s", mpt_req_state(req->debug));
	if (mpt->verbose > 1)
		mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);

	xs->error = XS_TIMEOUT;
	splx(s);
	mpt_restart(mpt, req);
}