From patchwork Tue May 18 06:57:13 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Reinecke X-Patchwork-Id: 52844 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id BAFCAB7D1E for ; Tue, 18 May 2010 18:18:20 +1000 (EST) Received: from localhost ([127.0.0.1]:43970 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OEI0G-0000xi-Ow for incoming@patchwork.ozlabs.org; Tue, 18 May 2010 04:18:16 -0400 Received: from [140.186.70.92] (port=60490 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OEHxf-00024E-KQ for qemu-devel@nongnu.org; Tue, 18 May 2010 04:17:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OEGjq-0002h0-DY for qemu-devel@nongnu.org; Tue, 18 May 2010 03:01:14 -0400 Received: from cantor2.suse.de ([195.135.220.15]:59143 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OEGjq-0002ge-1o for qemu-devel@nongnu.org; Tue, 18 May 2010 02:57:14 -0400 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id 4D1F487104; Tue, 18 May 2010 08:57:13 +0200 (CEST) Date: Tue, 18 May 2010 08:57:13 +0200 To: Nicholas A.Bellinger User-Agent: Heirloom mailx 12.2 01/07/07 MIME-Version: 1.0 Message-Id: <20100518065713.352E22A371@ochil.suse.de> From: hare@suse.de (Hannes Reinecke) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 4/4] megasas: Implement ABORT_CMD X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Win7 is impatient during shutdown and is sending 'ABORT_CMD' frames. Haven't tried to figure out _why_, but we should be handling them nevertheless. Signed-off-by: Hannes Reinecke --- hw/megasas.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- hw/mfi.h | 2 +- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/hw/megasas.c b/hw/megasas.c index e91c96b..c249914 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -241,13 +241,13 @@ static inline int megasas_next_index(MPTState *s, int index) return index; } -static inline struct megasas_cmd_t *megasas_next_frame(MPTState *s, +static inline struct megasas_cmd_t *megasas_lookup_frame(MPTState *s, target_phys_addr_t frame) { struct megasas_cmd_t *cmd = NULL; - int num = 0, tail, index; + int num = 0, index; - tail = index = s->reply_queue_index; + index = s->reply_queue_index; while (num < MEGASAS_MAX_FRAMES) { if (s->frames[index].pa && s->frames[index].pa == frame) { @@ -257,14 +257,25 @@ static inline struct megasas_cmd_t *megasas_next_frame(MPTState *s, index = megasas_next_index(s, index); num++; } + + return cmd; +} + +static inline struct megasas_cmd_t *megasas_next_frame(MPTState *s, + target_phys_addr_t frame) +{ + struct megasas_cmd_t *cmd = NULL; + int num = 0, index; + + cmd = megasas_lookup_frame(s, frame); if (cmd) { #ifdef DEBUG_MEGASAS_QUEUE - DPRINTF("Found mapped frame %x context %x pa %lx\n", index, + DPRINTF("Found mapped frame %x context %x pa %lx\n", cmd->index, cmd->frame->header.context, cmd->pa); #endif return cmd; } - index = tail; + index = s->reply_queue_index; num = 0; while (num < MEGASAS_MAX_FRAMES) { if (!s->frames[index].pa) { @@ -1067,6 +1078,31 @@ static void megasas_command_complete(SCSIRequest *req) megasas_dequeue_frame(cmd->state, context); } +static int megasas_handle_abort(MPTState *s, struct megasas_cmd_t *cmd) +{ + uint32_t abort_ctx = le32_to_cpu(cmd->frame->abort.abort_context); + target_phys_addr_t abort_addr, addr_hi, addr_lo; + struct megasas_cmd_t *abort_cmd; + + addr_hi = le32_to_cpu(cmd->frame->abort.abort_mfi_addr_hi); + addr_lo = le32_to_cpu(cmd->frame->abort.abort_mfi_addr_lo); + abort_addr = (addr_hi << 32) | addr_lo; + + abort_cmd = megasas_lookup_frame(s, abort_addr); + if (!abort_cmd) { + DPRINTF("No active command for frame context %x\n", abort_ctx); + return MFI_STAT_OK; + } + if (abort_cmd->frame->header.context != abort_ctx) { + DPRINTF("abort frame %x: invalid context %x\n", abort_cmd->index, + abort_cmd->frame->header.context); + return MFI_STAT_ABORT_NOT_POSSIBLE; + } + DPRINTF("aborting frame context %x\n", abort_ctx); + megasas_abort_command(abort_cmd); + return MFI_STAT_OK; +} + static void megasas_handle_frame(MPTState *s, target_phys_addr_t frame_addr, uint32_t frame_count) { @@ -1098,6 +1134,9 @@ static void megasas_handle_frame(MPTState *s, target_phys_addr_t frame_addr, case MFI_CMD_DCMD: frame_status = megasas_handle_dcmd(s, cmd); break; + case MFI_CMD_ABORT: + frame_status = megasas_handle_abort(s, cmd); + break; case MFI_CMD_PD_SCSI_IO: case MFI_CMD_LD_SCSI_IO: frame_status = megasas_handle_scsi(s, cmd); diff --git a/hw/mfi.h b/hw/mfi.h index 0beb1b6..f73cda7 100644 --- a/hw/mfi.h +++ b/hw/mfi.h @@ -125,7 +125,7 @@ #define MFI_FWSTATE_MAXSGL_MASK 0x00ff0000 #define MFI_FWSTATE_MAXCMD_MASK 0x0000ffff #define MFI_FWSTATE_HOSTMEMREQD_MASK 0x08000000 -#define MFI_FWSTATE_BOOT_MESSAGE_PENDING 0x90000000 + /* * Control bits to drive the card to ready state. These go into the IDB * register.