void mfi_disk_complete(struct bio *bio) { struct mfi_disk *sc; struct mfi_frame_header *hdr; sc = bio->bio_disk->d_drv1; hdr = bio->bio_driver1; if (bio->bio_flags & BIO_ERROR) { if (bio->bio_error == 0) bio->bio_error = EIO; disk_err(bio, "hard error", -1, 1); } else { bio->bio_resid = 0; } biodone(bio); }
static void htif_blk_task(void *arg) { struct htif_blk_request req __aligned(HTIF_ALIGN); struct htif_blk_softc *sc; uint64_t req_paddr; struct bio *bp; uint64_t paddr; uint64_t resp; uint64_t cmd; int i; sc = (struct htif_blk_softc *)arg; while (1) { HTIF_BLK_LOCK(sc); do { bp = bioq_takefirst(&sc->bio_queue); if (bp == NULL) msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0); } while (bp == NULL); HTIF_BLK_UNLOCK(sc); if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) { HTIF_BLK_LOCK(sc); rmb(); req.offset = (bp->bio_pblkno * sc->disk->d_sectorsize); req.size = bp->bio_bcount; paddr = vtophys(bp->bio_data); KASSERT(paddr != 0, ("paddr is 0")); req.addr = paddr; sc->curtag++; req.tag = sc->curtag; cmd = sc->index; cmd <<= HTIF_DEV_ID_SHIFT; if (bp->bio_cmd == BIO_READ) cmd |= (HTIF_CMD_READ << HTIF_CMD_SHIFT); else cmd |= (HTIF_CMD_WRITE << HTIF_CMD_SHIFT); req_paddr = vtophys(&req); KASSERT(req_paddr != 0, ("req_paddr is 0")); cmd |= req_paddr; sc->cmd_done = 0; resp = htif_command(cmd); htif_blk_intr(sc, resp); /* Wait for interrupt */ i = 0; while (sc->cmd_done == 0) { msleep(&sc->intr_chan, &sc->sc_mtx, PRIBIO, "intr", hz/2); if (i++ > 2) { /* TODO: try to re-issue operation on timeout ? */ bp->bio_error = EIO; bp->bio_flags |= BIO_ERROR; disk_err(bp, "hard error", -1, 1); break; } } HTIF_BLK_UNLOCK(sc); biodone(bp); } else { printf("unknown op %d\n", bp->bio_cmd); } } }