Patchwork [4/4] megasas: Implement ABORT_CMD

login
register
mail settings
Submitter Hannes Reinecke
Date May 18, 2010, 6:57 a.m.
Message ID <20100518065713.352E22A371@ochil.suse.de>
Download mbox | patch
Permalink /patch/52844/
State New
Headers show

Comments

Hannes Reinecke - May 18, 2010, 6:57 a.m.
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 <hare@suse.de>
---
 hw/megasas.c |   49 ++++++++++++++++++++++++++++++++++++++++++++-----
 hw/mfi.h     |    2 +-
 2 files changed, 45 insertions(+), 6 deletions(-)
Nicholas A. Bellinger - May 18, 2010, 8:49 a.m.
On Tue, 2010-05-18 at 08:57 +0200, Hannes Reinecke wrote:
> 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 <hare@suse.de>
> ---
>  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.

Thanks, commited as 07d41aed0de

Best,

--nab

Patch

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.