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);
}
Exemple #2
0
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);
		}
	}
}