win-pvdrivers

changeset 701:c3e410ac288f

Fix a few cases where a failure to allocate a gref did not result in the expected outcome.
Allocate gref's in AllocateAdapterChannel not in MapTransfer. This may have been causing a leak of grefs with a slowdown and eventual crash over time
author James Harper <james.harper@bendigoit.com.au>
date Wed Nov 25 21:41:03 2009 +1100 (2009-11-25)
parents 377647b4097a
children 93b98effc8e7
files xenpci/xenpci_dma.c
line diff
     1.1 --- a/xenpci/xenpci_dma.c	Wed Nov 25 21:39:51 2009 +1100
     1.2 +++ b/xenpci/xenpci_dma.c	Wed Nov 25 21:41:03 2009 +1100
     1.3 @@ -161,10 +161,12 @@ XenPci_DOP_AllocateAdapterChannel(
     1.4      IN PVOID Context
     1.5      )
     1.6  {
     1.7 -  //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
     1.8 -  //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
     1.9 +  xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
    1.10 +  PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
    1.11 +  ULONG i;
    1.12    IO_ALLOCATION_ACTION action;
    1.13    map_register_base_t *map_register_base;
    1.14 +  grant_ref_t gref;
    1.15    
    1.16    UNREFERENCED_PARAMETER(dma_adapter);
    1.17    
    1.18 @@ -183,6 +185,24 @@ XenPci_DOP_AllocateAdapterChannel(
    1.19    map_register_base->total_map_registers = NumberOfMapRegisters;
    1.20    map_register_base->count = 0;
    1.21    
    1.22 +  for (i = 0; i < NumberOfMapRegisters; i++)
    1.23 +  {
    1.24 +    gref = GntTbl_GetRef(xpdd);
    1.25 +    if (gref == INVALID_GRANT_REF)
    1.26 +    {
    1.27 +      /* go back through the list and free the ones we allocated */
    1.28 +      NumberOfMapRegisters = i;
    1.29 +      for (i = 0; i < NumberOfMapRegisters; i++)
    1.30 +      {
    1.31 +        gref = (grant_ref_t)(map_register_base->regs[i].logical.QuadPart >> PAGE_SHIFT);
    1.32 +        GntTbl_PutRef(xpdd, gref);
    1.33 +      }
    1.34 +      ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
    1.35 +      return STATUS_INSUFFICIENT_RESOURCES;
    1.36 +    }
    1.37 +    map_register_base->regs[i].logical.QuadPart = ((LONGLONG)gref << PAGE_SHIFT);
    1.38 +  }
    1.39 +  
    1.40    action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
    1.41    
    1.42    switch (action)
    1.43 @@ -264,6 +284,8 @@ XenPci_DOP_FreeMapRegisters(
    1.44    ULONG i;
    1.45    grant_ref_t gref;
    1.46  
    1.47 +  UNREFERENCED_PARAMETER(NumberOfMapRegisters);
    1.48 +  
    1.49    //FUNCTION_ENTER();
    1.50    if (!map_register_base)
    1.51    {
    1.52 @@ -311,7 +333,7 @@ XenPci_DOP_MapTransfer(
    1.53    PDEVICE_OBJECT device_object = map_register_base->device_object;
    1.54    ULONG page_offset;
    1.55    PFN_NUMBER pfn;
    1.56 -  grant_ref_t gref;
    1.57 +  //grant_ref_t gref;
    1.58    PUCHAR ptr;
    1.59    ULONG mdl_offset;
    1.60    ULONG pfn_index;
    1.61 @@ -368,9 +390,10 @@ XenPci_DOP_MapTransfer(
    1.62      //  mdl_offset, page_offset, *Length, pfn_index));
    1.63      pfn = MmGetMdlPfnArray(mdl)[pfn_index];
    1.64      //KdPrint((__DRIVER_NAME "     B Requesting Grant Ref\n"));
    1.65 -    gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
    1.66 +    GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT));
    1.67      //KdPrint((__DRIVER_NAME "     B Got Grant Ref %d\n", gref));
    1.68 -    map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | page_offset;
    1.69 +    map_register->logical.QuadPart &= ~(LONGLONG)(PAGE_SIZE - 1);
    1.70 +    map_register->logical.QuadPart |= page_offset;
    1.71      map_register_base->count++;
    1.72      break;
    1.73    case MAP_TYPE_REMAPPED:
    1.74 @@ -389,9 +412,9 @@ XenPci_DOP_MapTransfer(
    1.75        memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
    1.76      pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
    1.77      //KdPrint((__DRIVER_NAME "     C Requesting Grant Ref\n"));
    1.78 -    gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
    1.79 +    GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT));
    1.80      //KdPrint((__DRIVER_NAME "     C Got Grant Ref %d\n", gref));
    1.81 -    map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT);
    1.82 +    map_register->logical.QuadPart &= ~(LONGLONG)(PAGE_SIZE - 1);
    1.83      map_register_base->count++;
    1.84      break;
    1.85    case MAP_TYPE_VIRTUAL:
    1.86 @@ -718,6 +741,26 @@ XenPci_DOP_BuildScatterGatherListButDont
    1.87      //  sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t)));
    1.88      return STATUS_BUFFER_TOO_SMALL;
    1.89    }
    1.90 +
    1.91 +  if (map_type != MAP_TYPE_VIRTUAL)
    1.92 +  {
    1.93 +    for (sg_element = 0; sg_element < sglist->NumberOfElements; sg_element++)
    1.94 +    {
    1.95 +      gref = GntTbl_GetRef(xpdd);
    1.96 +      if (gref == INVALID_GRANT_REF)
    1.97 +      {
    1.98 +        /* go back through the list and free the ones we allocated */
    1.99 +        sglist->NumberOfElements = sg_element;
   1.100 +        for (sg_element = 0; sg_element < sglist->NumberOfElements; sg_element++)
   1.101 +        {
   1.102 +          gref = (grant_ref_t)(sglist->Elements[sg_element].Address.QuadPart >> PAGE_SHIFT);
   1.103 +          GntTbl_PutRef(xpdd, gref);
   1.104 +        }
   1.105 +        return STATUS_INSUFFICIENT_RESOURCES;
   1.106 +      }
   1.107 +      sglist->Elements[sg_element].Address.QuadPart = ((LONGLONG)gref << PAGE_SHIFT);
   1.108 +    }
   1.109 +  }
   1.110    
   1.111    sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
   1.112      (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
   1.113 @@ -752,10 +795,9 @@ XenPci_DOP_BuildScatterGatherListButDont
   1.114          for (i = 0; remaining > 0; i++)
   1.115          {
   1.116            pfn = MmGetMdlPfnArray(curr_mdl)[pfn_offset + i];
   1.117 -          ASSERT(pfn);
   1.118 -          gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
   1.119 -          ASSERT(gref != INVALID_GRANT_REF);
   1.120 -          sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
   1.121 +          GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE,
   1.122 +            (grant_ref_t)(sglist->Elements[sg_element].Address.QuadPart >> PAGE_SHIFT));
   1.123 +          sglist->Elements[sg_element].Address.QuadPart |= (LONGLONG)offset;
   1.124            sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
   1.125            total_remaining -= sglist->Elements[sg_element].Length;
   1.126            remaining -= sglist->Elements[sg_element].Length;
   1.127 @@ -823,10 +865,8 @@ for (curr_mdl = Mdl; curr_mdl; curr_mdl 
   1.128        sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, remapped_bytes); sg_element++)
   1.129      {
   1.130        pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
   1.131 -      ASSERT(pfn);
   1.132 -      gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
   1.133 -      ASSERT(gref != INVALID_GRANT_REF);
   1.134 -      sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
   1.135 +      GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE,
   1.136 +        (grant_ref_t)(sglist->Elements[sg_element].Address.QuadPart >> PAGE_SHIFT));
   1.137        sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
   1.138        remaining -= sglist->Elements[sg_element].Length;
   1.139      }
   1.140 @@ -908,6 +948,8 @@ XenPci_DOP_GetScatterGatherList(
   1.141    
   1.142    if (NT_SUCCESS(status))
   1.143      ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, sg_list, Context);
   1.144 +  else
   1.145 +    ExFreePoolWithTag(sg_list, XENPCI_POOL_TAG);
   1.146    
   1.147    //FUNCTION_EXIT();
   1.148