win-pvdrivers

changeset 871:babee70630ad

More scsiport reset updates. Also added warnings to vbd requests that took >5 seconds to complete
author James Harper <james.harper@bendigoit.com.au>
date Thu Mar 03 17:28:23 2011 +1100 (2011-03-03)
parents bc0658d4bcee
children e476e0b66aa6
files xenvbd/xenvbd_scsiport.c xenvbd/xenvbd_scsiport.h
line diff
     1.1 --- a/xenvbd/xenvbd_scsiport.c	Wed Mar 02 22:48:07 2011 +1100
     1.2 +++ b/xenvbd/xenvbd_scsiport.c	Thu Mar 03 17:28:23 2011 +1100
     1.3 @@ -77,6 +77,7 @@ put_shadow_on_freelist(PXENVBD_DEVICE_DA
     1.4  {
     1.5    xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
     1.6    shadow->srb = NULL;
     1.7 +  shadow->reset = FALSE;
     1.8    xvdd->shadow_free++;
     1.9  }
    1.10  
    1.11 @@ -365,9 +366,16 @@ XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVIC
    1.12    PUCHAR ptr;
    1.13    int notify;
    1.14    int i;
    1.15 +  #if DBG
    1.16 +  LARGE_INTEGER current_time;
    1.17 +  #endif
    1.18  
    1.19    //FUNCTION_ENTER();
    1.20  
    1.21 +  #if DBG
    1.22 +  ScsiPortQuerySystemTime(&current_time);
    1.23 +  #endif
    1.24 +  
    1.25    while(!xvdd->aligned_buffer_in_use && xvdd->shadow_free && (srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list)
    1.26    {
    1.27      srb = srb_entry->srb;
    1.28 @@ -521,6 +529,9 @@ XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVIC
    1.29      //KdPrint((__DRIVER_NAME "     nr_segments = %d\n", shadow->req.nr_segments));
    1.30  
    1.31      XenVbd_PutRequest(xvdd, &shadow->req);
    1.32 +    #if DBG
    1.33 +    shadow->ring_submit_time = current_time;
    1.34 +    #endif
    1.35  
    1.36      RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
    1.37      if (notify)
    1.38 @@ -897,6 +908,12 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
    1.39    ULONG suspend_resume_state_pdo;
    1.40    BOOLEAN last_interrupt = FALSE;
    1.41    ULONG start_ring_detect_state = xvdd->ring_detect_state;
    1.42 +  #if DBG
    1.43 +  srb_list_entry_t *srb_entry;
    1.44 +  ULONG elapsed;
    1.45 +  LARGE_INTEGER current_time;
    1.46 +  
    1.47 +  #endif
    1.48  
    1.49    /* in dump mode I think we get called on a timer, not by an actual IRQ */
    1.50    if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel, &last_interrupt))
    1.51 @@ -938,6 +955,10 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
    1.52      return last_interrupt;
    1.53    }
    1.54  
    1.55 +  #if DBG
    1.56 +  ScsiPortQuerySystemTime(&current_time);
    1.57 +  #endif
    1.58 +
    1.59    while (more_to_do)
    1.60    {
    1.61      rp = xvdd->ring.sring->rsp_prod;
    1.62 @@ -988,47 +1009,55 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
    1.63          ASSERT(srb != NULL);
    1.64          block_count = decode_cdb_length(srb);
    1.65          block_count *= xvdd->bytes_per_sector / 512;
    1.66 -        /* a few errors occur in dump mode because Xen refuses to allow us to map pages we are using for other stuff. Just ignore them */
    1.67 -        if (srb->SrbStatus == SRB_STATUS_BUS_RESET)
    1.68 +        #if DBG
    1.69 +        srb_entry = srb->SrbExtension;
    1.70 +        elapsed = (ULONG)((current_time.QuadPart - shadow->ring_submit_time.QuadPart) / 10000L);
    1.71 +        if (elapsed > 5000)
    1.72 +          KdPrint((__DRIVER_NAME "     WARNING: SRB completion time %dms\n", elapsed));
    1.73 +        #endif
    1.74 +        if (shadow->reset)
    1.75          {
    1.76 -          KdPrint((__DRIVER_NAME "     completing SRB %p with status SRB_STATUS_BUS_RESET\n", srb));
    1.77 +          KdPrint((__DRIVER_NAME "     discarding reset SRB %p\n", srb));
    1.78          }
    1.79 -        else if (rep->status == BLKIF_RSP_OKAY || (dump_mode &&  dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT))
    1.80 -          srb->SrbStatus = SRB_STATUS_SUCCESS;
    1.81          else
    1.82          {
    1.83 -          KdPrint((__DRIVER_NAME "     Xen Operation returned error\n"));
    1.84 -          if (decode_cdb_is_read(srb))
    1.85 -            KdPrint((__DRIVER_NAME "     Operation = Read\n"));
    1.86 +          if (rep->status == BLKIF_RSP_OKAY || (dump_mode &&  dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT))
    1.87 +            /* a few errors occur in dump mode because Xen refuses to allow us to map pages we are using for other stuff. Just ignore them */
    1.88 +            srb->SrbStatus = SRB_STATUS_SUCCESS;
    1.89            else
    1.90 -            KdPrint((__DRIVER_NAME "     Operation = Write\n"));
    1.91 -          if (dump_mode)
    1.92            {
    1.93 -            KdPrint((__DRIVER_NAME "     Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
    1.94 -            KdPrint((__DRIVER_NAME "     DataBuffer = %p, aligned_buffer = %p\n", srb->DataBuffer, xvdd->aligned_buffer));
    1.95 -            KdPrint((__DRIVER_NAME "     Physical = %08x%08x\n", MmGetPhysicalAddress(srb->DataBuffer).HighPart, MmGetPhysicalAddress(srb->DataBuffer).LowPart));
    1.96 -            KdPrint((__DRIVER_NAME "     PFN = %08x\n", (ULONG)(MmGetPhysicalAddress(srb->DataBuffer).QuadPart >> PAGE_SHIFT)));
    1.97 -
    1.98 -            for (j = 0; j < shadow->req.nr_segments; j++)
    1.99 +            KdPrint((__DRIVER_NAME "     Xen Operation returned error\n"));
   1.100 +            if (decode_cdb_is_read(srb))
   1.101 +              KdPrint((__DRIVER_NAME "     Operation = Read\n"));
   1.102 +            else
   1.103 +              KdPrint((__DRIVER_NAME "     Operation = Write\n"));
   1.104 +            if (dump_mode)
   1.105              {
   1.106 -              KdPrint((__DRIVER_NAME "     gref = %d\n", shadow->req.seg[j].gref));
   1.107 -              KdPrint((__DRIVER_NAME "     first_sect = %d\n", shadow->req.seg[j].first_sect));
   1.108 -              KdPrint((__DRIVER_NAME "     last_sect = %d\n", shadow->req.seg[j].last_sect));
   1.109 +              KdPrint((__DRIVER_NAME "     Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
   1.110 +              KdPrint((__DRIVER_NAME "     DataBuffer = %p, aligned_buffer = %p\n", srb->DataBuffer, xvdd->aligned_buffer));
   1.111 +              KdPrint((__DRIVER_NAME "     Physical = %08x%08x\n", MmGetPhysicalAddress(srb->DataBuffer).HighPart, MmGetPhysicalAddress(srb->DataBuffer).LowPart));
   1.112 +              KdPrint((__DRIVER_NAME "     PFN = %08x\n", (ULONG)(MmGetPhysicalAddress(srb->DataBuffer).QuadPart >> PAGE_SHIFT)));
   1.113 +
   1.114 +              for (j = 0; j < shadow->req.nr_segments; j++)
   1.115 +              {
   1.116 +                KdPrint((__DRIVER_NAME "     gref = %d\n", shadow->req.seg[j].gref));
   1.117 +                KdPrint((__DRIVER_NAME "     first_sect = %d\n", shadow->req.seg[j].first_sect));
   1.118 +                KdPrint((__DRIVER_NAME "     last_sect = %d\n", shadow->req.seg[j].last_sect));
   1.119 +              }
   1.120              }
   1.121 +            srb->SrbStatus = SRB_STATUS_ERROR;
   1.122 +            srb->ScsiStatus = 0x02;
   1.123 +            xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
   1.124 +            xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
   1.125 +            XenVbd_MakeAutoSense(xvdd, srb);
   1.126            }
   1.127 -          srb->SrbStatus = SRB_STATUS_ERROR;
   1.128 -          srb->ScsiStatus = 0x02;
   1.129 -          xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
   1.130 -          xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
   1.131 -          XenVbd_MakeAutoSense(xvdd, srb);
   1.132 -        }
   1.133 -        if (srb->SrbStatus == SRB_STATUS_SUCCESS && shadow->aligned_buffer_in_use)
   1.134 -        {
   1.135 -          ASSERT(xvdd->aligned_buffer_in_use);
   1.136 -          xvdd->aligned_buffer_in_use = FALSE;
   1.137 -          if (decode_cdb_is_read(srb))
   1.138 -            memcpy(srb->DataBuffer, xvdd->aligned_buffer, block_count * 512);
   1.139 -//KdPrint((__DRIVER_NAME "     Completed use of buffer\n"));
   1.140 +          if (srb->SrbStatus == SRB_STATUS_SUCCESS && shadow->aligned_buffer_in_use)
   1.141 +          {
   1.142 +            ASSERT(xvdd->aligned_buffer_in_use);
   1.143 +            xvdd->aligned_buffer_in_use = FALSE;
   1.144 +            if (decode_cdb_is_read(srb))
   1.145 +              memcpy(srb->DataBuffer, xvdd->aligned_buffer, block_count * 512);
   1.146 +          }
   1.147          }
   1.148          
   1.149          for (j = 0; j < shadow->req.nr_segments; j++)
   1.150 @@ -1044,11 +1073,12 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
   1.151                shadow->req.seg[j].gref, FALSE, (ULONG)'SCSI');
   1.152            }
   1.153          }
   1.154 +        if (!shadow->reset)
   1.155 +          ScsiPortNotification(RequestComplete, xvdd, srb);
   1.156          shadow->aligned_buffer_in_use = FALSE;
   1.157 +        shadow->reset = FALSE;
   1.158          shadow->srb = NULL;
   1.159          put_shadow_on_freelist(xvdd, shadow);
   1.160 -        //KdPrint((__DRIVER_NAME "     B RequestComplete srb = %p\n", srb));
   1.161 -        ScsiPortNotification(RequestComplete, xvdd, srb);
   1.162          break;
   1.163        }
   1.164      }
   1.165 @@ -1513,33 +1543,34 @@ XenVbd_HwScsiResetBus(PVOID DeviceExtens
   1.166  
   1.167    KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   1.168  
   1.169 -  while((srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list)
   1.170 -  {
   1.171 -    srb = srb_entry->srb;
   1.172 -    srb->SrbStatus = SRB_STATUS_BUS_RESET;
   1.173 -    KdPrint((__DRIVER_NAME "     completing queued SRB %p with status SRB_STATUS_BUS_RESET\n", srb));
   1.174 -    ScsiPortNotification(RequestComplete, xvdd, srb);
   1.175 -  }
   1.176 -  
   1.177 -  for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
   1.178 -  {
   1.179 -    if (xvdd->shadows[i].srb)
   1.180 -    {
   1.181 -      KdPrint((__DRIVER_NAME "     setting status SRB_STATUS_BUS_RESET for in-flight srb %p\n", xvdd->shadows[i].srb));
   1.182 -      xvdd->shadows[i].srb->SrbStatus = SRB_STATUS_BUS_RESET;
   1.183 -      /* can't complete now. It will have to be completed when it comes off the ring */
   1.184 -    }
   1.185 -  }
   1.186 -
   1.187 -  /* send a notify to Dom0 just in case it was missed for some reason (which should _never_ happen) */
   1.188 -  xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   1.189 -  
   1.190 -/*
   1.191    if (xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
   1.192    {
   1.193 +    while((srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list)
   1.194 +    {
   1.195 +      srb = srb_entry->srb;
   1.196 +      srb->SrbStatus = SRB_STATUS_BUS_RESET;
   1.197 +      KdPrint((__DRIVER_NAME "     completing queued SRB %p with status SRB_STATUS_BUS_RESET\n", srb));
   1.198 +      ScsiPortNotification(RequestComplete, xvdd, srb);
   1.199 +    }
   1.200 +    
   1.201 +    for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
   1.202 +    {
   1.203 +      if (xvdd->shadows[i].srb)
   1.204 +      {
   1.205 +        KdPrint((__DRIVER_NAME "     Completing in-flight srb %p with status SRB_STATUS_BUS_RESET\n", xvdd->shadows[i].srb));
   1.206 +        /* set reset here so that the interrupt won't do anything with the srb but will dispose of the shadow entry correctly */
   1.207 +        xvdd->shadows[i].reset = TRUE;
   1.208 +        xvdd->shadows[i].srb->SrbStatus = SRB_STATUS_BUS_RESET;
   1.209 +        ScsiPortNotification(RequestComplete, xvdd, xvdd->shadows[i].srb);
   1.210 +        xvdd->shadows[i].srb = NULL;
   1.211 +      }
   1.212 +    }
   1.213 +
   1.214 +    /* send a notify to Dom0 just in case it was missed for some reason (which should _never_ happen) */
   1.215 +    xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   1.216 +  
   1.217      ScsiPortNotification(NextRequest, DeviceExtension);
   1.218    }
   1.219 -*/
   1.220  
   1.221    FUNCTION_EXIT();
   1.222  
     2.1 --- a/xenvbd/xenvbd_scsiport.h	Wed Mar 02 22:48:07 2011 +1100
     2.2 +++ b/xenvbd/xenvbd_scsiport.h	Thu Mar 03 17:28:23 2011 +1100
     2.3 @@ -88,6 +88,10 @@ typedef struct {
     2.4    blkif_request_t req;
     2.5    PSCSI_REQUEST_BLOCK srb;
     2.6    BOOLEAN aligned_buffer_in_use;
     2.7 +  BOOLEAN reset;
     2.8 +  #if DBG
     2.9 +  LARGE_INTEGER ring_submit_time;
    2.10 +  #endif
    2.11  } blkif_shadow_t;
    2.12  
    2.13  #define MAX_SHADOW_ENTRIES 64