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); }
/* * 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); }
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); }
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); }