[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/4] megasas: Implement ABORT_CMD
From: |
Hannes Reinecke |
Subject: |
[Qemu-devel] [PATCH 4/4] megasas: Implement ABORT_CMD |
Date: |
Tue, 18 May 2010 08:57:13 +0200 |
User-agent: |
Heirloom mailx 12.2 01/07/07 |
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 <address@hidden>
---
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.
--
1.6.0.2
- [Qemu-devel] [PATCH 4/4] megasas: Implement ABORT_CMD,
Hannes Reinecke <=