Commit c6df7102 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

scsi: split command_complete callback in two



Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
parent 3944966d
Loading
Loading
Loading
Loading
+34 −28
Original line number Diff line number Diff line
@@ -395,19 +395,20 @@ static void esp_do_dma(ESPState *s)
    esp_dma_done(s);
}

static void esp_command_complete(SCSIRequest *req, int reason, uint32_t arg)
static void esp_command_complete(SCSIRequest *req, uint32_t arg)
{
    ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);

    if (reason == SCSI_REASON_DONE) {
    DPRINTF("SCSI Command complete\n");
        if (s->ti_size != 0)
    if (s->ti_size != 0) {
        DPRINTF("SCSI command completed unexpectedly\n");
    }
    s->ti_size = 0;
    s->dma_left = 0;
    s->async_len = 0;
        if (arg)
    if (arg) {
        DPRINTF("Command failed\n");
    }
    s->status = arg;
    s->rregs[ESP_RSTAT] = STAT_ST;
    esp_dma_done(s);
@@ -416,7 +417,12 @@ static void esp_command_complete(SCSIRequest *req, int reason, uint32_t arg)
        s->current_req = NULL;
        s->current_dev = NULL;
    }
    } else {
}

static void esp_transfer_data(SCSIRequest *req, uint32_t arg)
{
    ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);

    DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
    s->async_len = arg;
    s->async_buf = scsi_req_get_buf(req);
@@ -428,7 +434,6 @@ static void esp_command_complete(SCSIRequest *req, int reason, uint32_t arg)
        esp_dma_done(s);
    }
}
}

static void handle_ti(ESPState *s)
{
@@ -725,6 +730,7 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
}

static const struct SCSIBusOps esp_scsi_ops = {
    .transfer_data = esp_transfer_data,
    .complete = esp_command_complete,
    .cancel = esp_request_cancelled
};
+33 −25
Original line number Diff line number Diff line
@@ -711,14 +711,14 @@ static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
        return 1;
    }
}
 /* Callback to indicate that the SCSI layer has completed a transfer.  */
static void lsi_command_complete(SCSIRequest *req, int reason, uint32_t arg)

 /* Callback to indicate that the SCSI layer has completed a command.  */
static void lsi_command_complete(SCSIRequest *req, uint32_t arg)
{
    LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
    int out;

    out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
    if (reason == SCSI_REASON_DONE) {
    DPRINTF("Command complete status=%d\n", (int)arg);
    s->status = arg;
    s->command_complete = 2;
@@ -735,9 +735,14 @@ static void lsi_command_complete(SCSIRequest *req, int reason, uint32_t arg)
        s->current = NULL;
    }
    lsi_resume_script(s);
        return;
}

 /* Callback to indicate that the SCSI layer has completed a transfer.  */
static void lsi_transfer_data(SCSIRequest *req, uint32_t arg)
{
    LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
    int out;

    if (s->waiting == 1 || !s->current || req->tag != s->current->tag ||
        (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
        if (lsi_queue_tag(s, req->tag, arg)) {
@@ -745,18 +750,20 @@ static void lsi_command_complete(SCSIRequest *req, int reason, uint32_t arg)
        }
    }

    out = (s->sstat1 & PHASE_MASK) == PHASE_DO;

    /* host adapter (re)connected */
    DPRINTF("Data ready tag=0x%x len=%d\n", req->tag, arg);
    s->current->dma_len = arg;
    s->command_complete = 1;
    if (!s->waiting)
        return;
    if (s->waiting) {
        if (s->waiting == 1 || s->dbc == 0) {
            lsi_resume_script(s);
        } else {
            lsi_do_dma(s, out);
        }
    }
}

static void lsi_do_command(LSIState *s)
{
@@ -2239,6 +2246,7 @@ static int lsi_scsi_uninit(PCIDevice *d)
}

static const struct SCSIBusOps lsi_scsi_ops = {
    .transfer_data = lsi_transfer_data,
    .complete = lsi_command_complete,
    .cancel = lsi_request_cancelled
};
+2 −2
Original line number Diff line number Diff line
@@ -634,7 +634,7 @@ void scsi_req_continue(SCSIRequest *req)
void scsi_req_data(SCSIRequest *req, int len)
{
    trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
    req->bus->ops->complete(req, SCSI_REASON_DATA, len);
    req->bus->ops->transfer_data(req, len);
}

void scsi_req_print(SCSIRequest *req)
@@ -670,7 +670,7 @@ void scsi_req_complete(SCSIRequest *req)
    assert(req->status != -1);
    scsi_req_ref(req);
    scsi_req_dequeue(req);
    req->bus->ops->complete(req, SCSI_REASON_DONE, req->status);
    req->bus->ops->complete(req, req->status);
    scsi_req_unref(req);
}

+2 −7
Original line number Diff line number Diff line
@@ -9,12 +9,6 @@

#define SCSI_CMD_BUF_SIZE     16

/* scsi-disk.c */
enum scsi_reason {
    SCSI_REASON_DONE, /* Command complete.  */
    SCSI_REASON_DATA  /* Transfer complete, more data required.  */
};

typedef struct SCSIBus SCSIBus;
typedef struct SCSIBusOps SCSIBusOps;
typedef struct SCSIDevice SCSIDevice;
@@ -84,7 +78,8 @@ struct SCSIDeviceInfo {
};

struct SCSIBusOps {
    void (*complete)(SCSIRequest *req, int reason, uint32_t arg);
    void (*transfer_data)(SCSIRequest *req, uint32_t arg);
    void (*complete)(SCSIRequest *req, uint32_t arg);
    void (*cancel)(SCSIRequest *req);
};

+56 −45
Original line number Diff line number Diff line
@@ -480,27 +480,21 @@ static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
}

/* Callback to indicate that the SCSI layer has completed a transfer.  */
static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg)
static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t arg)
{
    VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
    vscsi_req *req = vscsi_find_req(s, sreq);
    uint8_t *buf;
    int32_t res_in = 0, res_out = 0;
    int len, rc = 0;

    dprintf("VSCSI: SCSI cmd complete, r=0x%x tag=0x%x arg=0x%x, req=%p\n",
            reason, sreq->tag, arg, req);
    dprintf("VSCSI: SCSI xfer complete tag=0x%x arg=0x%x, req=%p\n",
            sreq->tag, arg, req);
    if (req == NULL) {
        fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
        return;
    }

    if (req->sensing) {
        if (reason == SCSI_REASON_DONE) {
            dprintf("VSCSI: Sense done !\n");
            vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
            vscsi_put_req(s, req);
        } else {
        uint8_t *buf = scsi_req_get_buf(sreq);

        len = MIN(arg, SCSI_SENSE_BUF_SIZE);
@@ -514,29 +508,6 @@ static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg)
        memcpy(req->sense, buf, len);
        req->senselen = len;
        scsi_req_continue(req->sreq);
        }
        return;
    }

    if (reason == SCSI_REASON_DONE) {
        dprintf("VSCSI: Command complete err=%d\n", arg);
        if (arg == 0) {
            /* We handle overflows, not underflows for normal commands,
             * but hopefully nobody cares
             */
            if (req->writing) {
                res_out = req->data_len;
            } else {
                res_in = req->data_len;
            }
            vscsi_send_rsp(s, req, 0, res_in, res_out);
        } else if (arg == CHECK_CONDITION) {
            vscsi_send_request_sense(s, req);
            return;
        } else {
            vscsi_send_rsp(s, req, arg, 0, 0);
        }
        vscsi_put_req(s, req);
        return;
    }

@@ -559,6 +530,45 @@ static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg)
    scsi_req_continue(sreq);
}

/* Callback to indicate that the SCSI layer has completed a transfer.  */
static void vscsi_command_complete(SCSIRequest *sreq, uint32_t arg)
{
    VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
    vscsi_req *req = vscsi_find_req(s, sreq);
    int32_t res_in = 0, res_out = 0;

    dprintf("VSCSI: SCSI cmd complete, r=0x%x tag=0x%x arg=0x%x, req=%p\n",
            reason, sreq->tag, arg, req);
    if (req == NULL) {
        fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
        return;
    }

    if (!req->sensing && arg == CHECK_CONDITION) {
        vscsi_send_request_sense(s, req);
        return;
    }

    if (req->sensing) {
        dprintf("VSCSI: Sense done !\n");
        arg = CHECK_CONDITION;
    } else {
        dprintf("VSCSI: Command complete err=%d\n", arg);
        if (arg == 0) {
            /* We handle overflows, not underflows for normal commands,
             * but hopefully nobody cares
             */
            if (req->writing) {
                res_out = req->data_len;
            } else {
                res_in = req->data_len;
            }
        }
    }
    vscsi_send_rsp(s, req, 0, res_in, res_out);
    vscsi_put_req(s, req);
}

static void vscsi_request_cancelled(SCSIRequest *sreq)
{
    VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
@@ -916,6 +926,7 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
}

static const struct SCSIBusOps vscsi_scsi_ops = {
    .transfer_data = vscsi_transfer_data,
    .complete = vscsi_command_complete,
    .cancel = vscsi_request_cancelled
};
Loading