From patchwork Mon May 23 16:08:55 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 96996 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A511FB6FB6 for ; Tue, 24 May 2011 02:14:29 +1000 (EST) Received: from localhost ([::1]:46308 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QOXly-0000PY-V5 for incoming@patchwork.ozlabs.org; Mon, 23 May 2011 12:14:26 -0400 Received: from eggs.gnu.org ([140.186.70.92]:57464) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QOXhf-0001l7-BE for qemu-devel@nongnu.org; Mon, 23 May 2011 12:10:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QOXhd-0001HM-Ux for qemu-devel@nongnu.org; Mon, 23 May 2011 12:09:59 -0400 Received: from mail-pv0-f173.google.com ([74.125.83.173]:50127) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QOXhd-0001DU-Jj for qemu-devel@nongnu.org; Mon, 23 May 2011 12:09:57 -0400 Received: by mail-pv0-f173.google.com with SMTP id 3so3215837pvg.4 for ; Mon, 23 May 2011 09:09:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:sender:from:to:cc:subject:date:message-id :x-mailer:in-reply-to:references; bh=9ZcSTp9Lfb4EfWyy55G+YMkvzpzCui+SiXM7K9vxRHo=; b=oEl5Gszl1xuLXd/BHhi30RsHkdjfYdVTCMtUKzYU1rMlhJWZTr4ewmiLyqJbaOfpRR wsPDGUgOQoWghznNVj7cuRQIeEEOIV3m1FBnVCB9oWgOYY+aqaBib77ph4YezoiLMSqz LVCCzHD3pMIEyGCtqk5AtbjGfTm7qVUhBw5OE= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; b=lMOToPxdOD9AMaWXwPJ1t7vaIaSlGv4k6Gups7gNGVOhfmT99tlmpqOut+VdOLKoA+ v2s/T2muPR0eP5jzLvUmxxVYhbR1d2wwqH7wHc6sKZwA768lxB0GUteFzKMrn1euOEZU 8Bw4qvw0UupKyVud9f9cQHCGQpCV06a3yAvKg= Received: by 10.143.79.3 with SMTP id g3mr935515wfl.73.1306166997210; Mon, 23 May 2011 09:09:57 -0700 (PDT) Received: from localhost.localdomain (93-34-184-88.ip51.fastwebnet.it [93.34.184.88]) by mx.google.com with ESMTPS id x12sm5946194wfd.6.2011.05.23.09.09.54 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 23 May 2011 09:09:55 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Mon, 23 May 2011 18:08:55 +0200 Message-Id: <1306166949-19698-11-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.4.4 In-Reply-To: <1306166949-19698-1-git-send-email-pbonzini@redhat.com> References: <1306166949-19698-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 74.125.83.173 Cc: hch@lst.de Subject: [Qemu-devel] [PATCH v4 10/24] scsi: introduce scsi_req_cancel X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This is for when the request must be dropped in the void, but still memory should be freed. To this end, the devices register a second callback in SCSIBusOps. Signed-off-by: Paolo Bonzini Reviewed-by: Christoph Hellwig --- hw/esp.c | 16 ++++++++++++++-- hw/lsi53c895a.c | 30 +++++++++++++++++++++++++----- hw/scsi-bus.c | 17 ++++++++++++++--- hw/scsi-disk.c | 1 - hw/scsi-generic.c | 1 - hw/scsi.h | 2 ++ hw/spapr_vscsi.c | 11 ++++++++++- hw/usb-msd.c | 19 +++++++++++++++---- 8 files changed, 80 insertions(+), 17 deletions(-) diff --git a/hw/esp.c b/hw/esp.c index 096f4dc..46157a8 100644 --- a/hw/esp.c +++ b/hw/esp.c @@ -188,6 +188,17 @@ static void esp_dma_enable(void *opaque, int irq, int level) } } +static void esp_request_cancelled(SCSIRequest *req) +{ + ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent); + + if (req == s->current_req) { + scsi_req_unref(s->current_req); + s->current_req = NULL; + s->current_dev = NULL; + } +} + static uint32_t get_cmd(ESPState *s, uint8_t *buf) { uint32_t dmalen; @@ -210,7 +221,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf) if (s->current_dev) { /* Started a new command before the old one finished. Cancel it. */ - s->current_dev->info->cancel_io(s->current_req); + scsi_req_cancel(s->current_req); s->async_len = 0; } @@ -720,7 +731,8 @@ void esp_init(target_phys_addr_t espaddr, int it_shift, } static struct SCSIBusOps esp_scsi_ops = { - .complete = esp_command_complete + .complete = esp_command_complete, + .cancel = esp_request_cancelled }; static int esp_init1(SysBusDevice *dev) diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index b9febae..fc2b352 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -664,6 +664,26 @@ static lsi_request *lsi_find_by_tag(LSIState *s, uint32_t tag) return NULL; } +static void lsi_request_cancelled(SCSIRequest *req) +{ + LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent); + lsi_request *p; + + if (req == s->current->req) { + scsi_req_unref(req); + qemu_free(s->current); + s->current = NULL; + return; + } + + p = lsi_find_by_tag(s, req->tag); + if (p) { + QTAILQ_REMOVE(&s->queue, p, next); + scsi_req_unref(req); + qemu_free(p); + } +} + /* Record that data is available for a queued command. Returns zero if the device was reselected, nonzero if the IO is deferred. */ static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg) @@ -931,7 +951,7 @@ static void lsi_do_msgout(LSIState *s) /* The ABORT TAG message clears the current I/O process only. */ DPRINTF("MSG: ABORT TAG tag=0x%x\n", current_tag); if (current_req) { - current_dev->info->cancel_io(current_req->req); + scsi_req_cancel(current_req->req); } lsi_disconnect(s); break; @@ -956,7 +976,7 @@ static void lsi_do_msgout(LSIState *s) /* clear the current I/O process */ if (s->current) { - current_dev->info->cancel_io(s->current->req); + scsi_req_cancel(s->current->req); } /* As the current implemented devices scsi_disk and scsi_generic @@ -969,8 +989,7 @@ static void lsi_do_msgout(LSIState *s) id = current_tag & 0x0000ff00; QTAILQ_FOREACH_SAFE(p, &s->queue, next, p_next) { if ((p->tag & 0x0000ff00) == id) { - current_dev->info->cancel_io(p->req); - QTAILQ_REMOVE(&s->queue, p, next); + scsi_req_cancel(p->req); } } @@ -2227,7 +2246,8 @@ static int lsi_scsi_uninit(PCIDevice *d) } static struct SCSIBusOps lsi_scsi_ops = { - .complete = lsi_command_complete + .complete = lsi_command_complete, + .cancel = lsi_request_cancelled }; static int lsi_scsi_init(PCIDevice *dev) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index b4ba8cd..c0ab4a6 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -549,6 +549,19 @@ void scsi_req_complete(SCSIRequest *req) scsi_req_unref(req); } +void scsi_req_cancel(SCSIRequest *req) +{ + if (req->dev && req->dev->info->cancel_io) { + req->dev->info->cancel_io(req); + } + scsi_req_ref(req); + scsi_req_dequeue(req); + if (req->bus->ops->cancel) { + req->bus->ops->cancel(req); + } + scsi_req_unref(req); +} + void scsi_req_abort(SCSIRequest *req, int status) { req->status = status; @@ -564,9 +577,7 @@ void scsi_device_purge_requests(SCSIDevice *sdev) while (!QTAILQ_EMPTY(&sdev->requests)) { req = QTAILQ_FIRST(&sdev->requests); - sdev->info->cancel_io(req); - scsi_req_dequeue(req); - scsi_req_unref(req); + scsi_req_cancel(req); } } diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 4b39f46..1592c58 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -140,7 +140,6 @@ static void scsi_cancel_io(SCSIRequest *req) bdrv_aio_cancel(r->req.aiocb); } r->req.aiocb = NULL; - scsi_req_dequeue(&r->req); } static void scsi_read_complete(void * opaque, int ret) diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index b0b6ae7..16bf185 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -120,7 +120,6 @@ static void scsi_cancel_io(SCSIRequest *req) bdrv_aio_cancel(r->req.aiocb); } r->req.aiocb = NULL; - scsi_req_dequeue(&r->req); } static int execute_command(BlockDriverState *bdrv, diff --git a/hw/scsi.h b/hw/scsi.h index e915ef8..87a368a 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -78,6 +78,7 @@ struct SCSIDeviceInfo { struct SCSIBusOps { void (*complete)(SCSIRequest *req, int reason, uint32_t arg); + void (*cancel)(SCSIRequest *req); }; struct SCSIBus { @@ -115,6 +116,7 @@ void scsi_req_print(SCSIRequest *req); void scsi_req_data(SCSIRequest *req, int len); void scsi_req_complete(SCSIRequest *req); void scsi_req_abort(SCSIRequest *req, int status); +void scsi_req_cancel(SCSIRequest *req); void scsi_device_purge_requests(SCSIDevice *sdev); #endif diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c index 678cd00..5b97a83 100644 --- a/hw/spapr_vscsi.c +++ b/hw/spapr_vscsi.c @@ -559,6 +559,14 @@ static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg) } } +static void vscsi_request_cancelled(SCSIRequest *sreq) +{ + VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent); + vscsi_req *req = vscsi_find_req(s, sreq); + + vscsi_put_req(s, req); +} + static void vscsi_process_login(VSCSIState *s, vscsi_req *req) { union viosrp_iu *iu = &req->iu; @@ -910,7 +918,8 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data) } static struct SCSIBusOps vscsi_scsi_ops = { - .complete = vscsi_command_complete + .complete = vscsi_command_complete, + .cancel = vscsi_request_cancelled }; static int spapr_vscsi_init(VIOsPAPRDevice *dev) diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 38f97d0..9b238e8 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -264,6 +264,18 @@ static void usb_msd_command_complete(SCSIRequest *req, int reason, uint32_t arg) } } +static void usb_msd_request_cancelled(SCSIRequest *req) +{ + MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); + + if (req == s->req) { + scsi_req_unref(s->req); + s->req = NULL; + s->packet = NULL; + s->scsi_len = 0; + } +} + static void usb_msd_handle_reset(USBDevice *dev) { MSDState *s = (MSDState *)dev; @@ -318,9 +330,7 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value, static void usb_msd_cancel_io(USBPacket *p, void *opaque) { MSDState *s = opaque; - s->scsi_dev->info->cancel_io(s->req); - s->packet = NULL; - s->scsi_len = 0; + scsi_req_cancel(s->req); } static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) @@ -491,7 +501,8 @@ static void usb_msd_password_cb(void *opaque, int err) } static struct SCSIBusOps usb_msd_scsi_ops = { - .complete = usb_msd_command_complete + .complete = usb_msd_command_complete, + .cancel = usb_msd_request_cancelled }; static int usb_msd_initfn(USBDevice *dev)