win-pvdrivers

changeset 575:b162a1156e3f

Made the interrupt ack logic per-cpu to fix 'unacknowledged irq' errors and hangs in SMP
author James Harper <james.harper@bendigoit.com.au>
date Wed May 20 21:41:21 2009 +1000 (2009-05-20)
parents 1570a4c43a62
children dc0a293c870c
files xenpci/evtchn.c xenpci/xenpci.h xenscsi/xenscsi.c xenvbd/xenvbd.c
line diff
     1.1 --- a/xenpci/evtchn.c	Wed May 20 21:40:35 2009 +1000
     1.2 +++ b/xenpci/evtchn.c	Wed May 20 21:41:21 2009 +1000
     1.3 @@ -60,6 +60,7 @@ BOOLEAN
     1.4  EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
     1.5  {
     1.6    PXENPCI_DEVICE_DATA xpdd = context;
     1.7 +  ULONG pcpu = KeGetCurrentProcessorNumber() & 0xff;
     1.8    ULONG evt_word;
     1.9    ULONG evt_bit;
    1.10    xen_ulong_t val;
    1.11 @@ -68,13 +69,13 @@ EvtChn_AckEvent(PVOID context, evtchn_po
    1.12    evt_bit = port & (BITS_PER_LONG - 1);
    1.13    evt_word = port >> BITS_PER_LONG_SHIFT;
    1.14  
    1.15 -  val = synch_clear_bit(evt_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[evt_word]);
    1.16 -  *last_interrupt = FALSE;
    1.17 +  val = synch_clear_bit(evt_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[pcpu][evt_word]);
    1.18 +  *last_interrupt = TRUE;
    1.19    for (i = 0; i < sizeof(xen_ulong_t) * 8; i++)
    1.20    {
    1.21 -    if (xpdd->evtchn_pending_pvt[i])
    1.22 +    if (xpdd->evtchn_pending_pvt[pcpu][i])
    1.23      {
    1.24 -      *last_interrupt = TRUE;
    1.25 +      *last_interrupt = FALSE;
    1.26        break;
    1.27      }
    1.28    }
    1.29 @@ -82,6 +83,8 @@ EvtChn_AckEvent(PVOID context, evtchn_po
    1.30    return (BOOLEAN)!!val;
    1.31  }
    1.32  
    1.33 +volatile ULONG in_inq = 0;
    1.34 +
    1.35  BOOLEAN
    1.36  EvtChn_EvtInterruptIsr(WDFINTERRUPT interrupt, ULONG message_id)
    1.37  {
    1.38 @@ -90,7 +93,8 @@ For HVM domains, Xen always triggers the
    1.39  interrupt is delivered via the virtual PCI device it might get delivered
    1.40  to CPU != 0, but we should always use vcpu_info[0]
    1.41  */
    1.42 -  int cpu = 0;
    1.43 +  int vcpu = 0;
    1.44 +  ULONG pcpu = KeGetCurrentProcessorNumber() & 0xff;
    1.45    vcpu_info_t *vcpu_info;
    1.46    PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfInterruptGetDevice(interrupt));
    1.47    shared_info_t *shared_info_area = xpdd->shared_info_area;
    1.48 @@ -115,16 +119,16 @@ to CPU != 0, but we should always use vc
    1.49      KdPrint((__DRIVER_NAME "     interrupt while hibernated\n"));
    1.50    }
    1.51  
    1.52 -  for (i = 0; i < ARRAY_SIZE(xpdd->evtchn_pending_pvt); i++)
    1.53 +  for (i = 0; i < ARRAY_SIZE(xpdd->evtchn_pending_pvt[pcpu]); i++)
    1.54    {
    1.55 -    if (xpdd->evtchn_pending_pvt[i])
    1.56 +    if (xpdd->evtchn_pending_pvt[pcpu][i])
    1.57      {
    1.58 -      KdPrint((__DRIVER_NAME "     Unacknowledged event word = %d, val = %p\n", i, xpdd->evtchn_pending_pvt[i]));
    1.59 -      xpdd->evtchn_pending_pvt[i] = 0;
    1.60 +      KdPrint((__DRIVER_NAME "     Unacknowledged event word = %d, val = %p\n", i, xpdd->evtchn_pending_pvt[pcpu][i]));
    1.61 +      xpdd->evtchn_pending_pvt[pcpu][i] = 0;
    1.62      }
    1.63    }
    1.64    
    1.65 -  vcpu_info = &shared_info_area->vcpu_info[cpu];
    1.66 +  vcpu_info = &shared_info_area->vcpu_info[vcpu];
    1.67  
    1.68    vcpu_info->evtchn_upcall_pending = 0;
    1.69  
    1.70 @@ -153,7 +157,7 @@ to CPU != 0, but we should always use vc
    1.71          break;
    1.72        case EVT_ACTION_TYPE_IRQ:
    1.73          //KdPrint((__DRIVER_NAME "     EVT_ACTION_TYPE_IRQ\n"));
    1.74 -        synch_set_bit(evt_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[evt_word]);
    1.75 +        synch_set_bit(evt_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[pcpu][evt_word]);
    1.76          deferred = TRUE;
    1.77          break;
    1.78        case EVT_ACTION_TYPE_DPC:
    1.79 @@ -162,13 +166,13 @@ to CPU != 0, but we should always use vc
    1.80          break;
    1.81        case EVT_ACTION_TYPE_SUSPEND:
    1.82          KdPrint((__DRIVER_NAME "     EVT_ACTION_TYPE_SUSPEND\n"));
    1.83 -        for (i = 0; i < ARRAY_SIZE(xpdd->evtchn_pending_pvt); i++)
    1.84 +        for (i = 0; i < ARRAY_SIZE(xpdd->evtchn_pending_pvt[pcpu]); i++)
    1.85          {
    1.86            if (xpdd->ev_actions[i].type == EVT_ACTION_TYPE_IRQ)
    1.87            {
    1.88              int suspend_bit = i & (BITS_PER_LONG - 1);
    1.89              int suspend_word = i >> BITS_PER_LONG_SHIFT;
    1.90 -            synch_set_bit(suspend_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[suspend_word]);
    1.91 +            synch_set_bit(suspend_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[pcpu][suspend_word]);
    1.92            }
    1.93            else if (xpdd->ev_actions[i].type == EVT_ACTION_TYPE_NORMAL && xpdd->ev_actions[i].ServiceRoutine)
    1.94            {
     2.1 --- a/xenpci/xenpci.h	Wed May 20 21:40:35 2009 +1000
     2.2 +++ b/xenpci/xenpci.h	Wed May 20 21:41:21 2009 +1000
     2.3 @@ -130,7 +130,7 @@ typedef struct {
     2.4    
     2.5    PHYSICAL_ADDRESS shared_info_area_unmapped;
     2.6    shared_info_t *shared_info_area;
     2.7 -  xen_ulong_t evtchn_pending_pvt[sizeof(xen_ulong_t) * 8];
     2.8 +  xen_ulong_t evtchn_pending_pvt[MAX_VIRT_CPUS][sizeof(xen_ulong_t) * 8];
     2.9    xen_ulong_t evtchn_pending_suspend[sizeof(xen_ulong_t) * 8];
    2.10    evtchn_port_t pdo_event_channel;
    2.11    KEVENT pdo_suspend_event;
     3.1 --- a/xenscsi/xenscsi.c	Wed May 20 21:40:35 2009 +1000
     3.2 +++ b/xenscsi/xenscsi.c	Wed May 20 21:41:21 2009 +1000
     3.3 @@ -197,7 +197,7 @@ XenScsi_HwScsiInterrupt(PVOID DeviceExte
     3.4  
     3.5    //FUNCTION_EXIT();
     3.6    
     3.7 -  return !last_interrupt;
     3.8 +  return last_interrupt;
     3.9  }
    3.10  
    3.11  static VOID
     4.1 --- a/xenvbd/xenvbd.c	Wed May 20 21:40:35 2009 +1000
     4.2 +++ b/xenvbd/xenvbd.c	Wed May 20 21:41:21 2009 +1000
     4.3 @@ -791,7 +791,7 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
     4.4  
     4.5    if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
     4.6    {
     4.7 -    return !last_interrupt;
     4.8 +    return last_interrupt;
     4.9    }
    4.10  
    4.11    while (more_to_do)
    4.12 @@ -897,7 +897,7 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
    4.13      FUNCTION_EXIT();
    4.14    }
    4.15  
    4.16 -  return !last_interrupt;
    4.17 +  return last_interrupt;
    4.18  }
    4.19  
    4.20  static BOOLEAN DDKAPI