qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v5 3/4] s390x/virtio-ccw: reference-counted indi


From: Christian Borntraeger
Subject: Re: [Qemu-devel] [PATCH v5 3/4] s390x/virtio-ccw: reference-counted indicators
Date: Mon, 12 May 2014 10:17:39 +0200
User-agent: Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Thunderbird/24.5.0

On 08/05/14 15:03, Cornelia Huck wrote:
> Make code using the same indicators point to a single allocated structure
> that is freed when the last user goes away.
> 
> This will be used by the irqfd code to unmap addresses after the last user
> is gone.
> 
> Reviewed-by: Thomas Huth <address@hidden>
> Signed-off-by: Cornelia Huck <address@hidden>
Reviewed-by: Christian Borntraeger <address@hidden>

> ---
>  hw/s390x/virtio-ccw.c |   80 
> ++++++++++++++++++++++++++++++++++++++-----------
>  hw/s390x/virtio-ccw.h |   13 ++++++--
>  2 files changed, 73 insertions(+), 20 deletions(-)
> 
> diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
> index e3b7120..d11a783 100644
> --- a/hw/s390x/virtio-ccw.c
> +++ b/hw/s390x/virtio-ccw.c
> @@ -27,6 +27,38 @@
>  #include "virtio-ccw.h"
>  #include "trace.h"
> 
> +static QTAILQ_HEAD(, IndAddr) indicator_addresses =
> +    QTAILQ_HEAD_INITIALIZER(indicator_addresses);
> +
> +static IndAddr *get_indicator(hwaddr ind_addr, int len)
> +{
> +    IndAddr *indicator;
> +
> +    QTAILQ_FOREACH(indicator, &indicator_addresses, sibling) {
> +        if (indicator->addr == ind_addr) {
> +            indicator->refcnt++;
> +            return indicator;
> +        }
> +    }
> +    indicator = g_new0(IndAddr, 1);
> +    indicator->addr = ind_addr;
> +    indicator->len = len;
> +    indicator->refcnt = 1;
> +    QTAILQ_INSERT_TAIL(&indicator_addresses, indicator, sibling);
> +    return indicator;
> +}
> +
> +static void release_indicator(IndAddr *indicator)
> +{
> +    assert(indicator->refcnt > 0);
> +    indicator->refcnt--;
> +    if (indicator->refcnt > 0) {
> +        return;
> +    }
> +    QTAILQ_REMOVE(&indicator_addresses, indicator, sibling);
> +    g_free(indicator);
> +}
> +
>  static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
>                                 VirtioCcwDevice *dev);
> 
> @@ -445,7 +477,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>              ret = -EFAULT;
>          } else {
>              indicators = ldq_phys(&address_space_memory, ccw.cda);
> -            dev->indicators = indicators;
> +            dev->indicators = get_indicator(indicators, sizeof(uint64_t));
>              sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
>              ret = 0;
>          }
> @@ -465,7 +497,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>              ret = -EFAULT;
>          } else {
>              indicators = ldq_phys(&address_space_memory, ccw.cda);
> -            dev->indicators2 = indicators;
> +            dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
>              sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
>              ret = 0;
>          }
> @@ -517,8 +549,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>                  ret = -EFAULT;
>              } else {
>                  len = hw_len;
> -                dev->summary_indicator = thinint->summary_indicator;
> -                dev->indicators = thinint->device_indicator;
> +                dev->summary_indicator =
> +                    get_indicator(thinint->summary_indicator, 
> sizeof(uint8_t));
> +                dev->indicators = get_indicator(thinint->device_indicator,
> +                                                thinint->ind_bit / 8 + 1);
>                  dev->thinint_isc = thinint->isc;
>                  dev->ind_bit = thinint->ind_bit;
>                  cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len);
> @@ -526,8 +560,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>                                                dev->thinint_isc, true, false,
>                                                &dev->adapter_id);
>                  assert(ret == 0);
> -                sch->thinint_active = ((dev->indicators != 0) &&
> -                                       (dev->summary_indicator != 0));
> +                sch->thinint_active = ((dev->indicators != NULL) &&
> +                                       (dev->summary_indicator != NULL));
>                  sch->curr_status.scsw.count = ccw.count - len;
>                  ret = 0;
>              }
> @@ -558,7 +592,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, 
> VirtIODevice *vdev)
>      sch->driver_data = dev;
>      dev->sch = sch;
> 
> -    dev->indicators = 0;
> +    dev->indicators = NULL;
> 
>      /* Initialize subchannel structure. */
>      sch->channel_prog = 0x0;
> @@ -697,7 +731,10 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
>          css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, 
> NULL);
>          g_free(sch);
>      }
> -    dev->indicators = 0;
> +    if (dev->indicators) {
> +        release_indicator(dev->indicators);
> +        dev->indicators = NULL;
> +    }
>      return 0;
>  }
> 
> @@ -954,17 +991,17 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t 
> vector)
>               * ind_bit indicates the start of the indicators in a big
>               * endian notation.
>               */
> -            virtio_set_ind_atomic(sch, dev->indicators +
> +            virtio_set_ind_atomic(sch, dev->indicators->addr +
>                                    (dev->ind_bit + vector) / 8,
>                                    0x80 >> ((dev->ind_bit + vector) % 8));
> -            if (!virtio_set_ind_atomic(sch, dev->summary_indicator,
> +            if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr,
>                                         0x01)) {
>                  css_adapter_interrupt(dev->thinint_isc);
>              }
>          } else {
> -            indicators = ldq_phys(&address_space_memory, dev->indicators);
> +            indicators = ldq_phys(&address_space_memory, 
> dev->indicators->addr);
>              indicators |= 1ULL << vector;
> -            stq_phys(&address_space_memory, dev->indicators, indicators);
> +            stq_phys(&address_space_memory, dev->indicators->addr, 
> indicators);
>              css_conditional_io_interrupt(sch);
>          }
>      } else {
> @@ -972,9 +1009,9 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t 
> vector)
>              return;
>          }
>          vector = 0;
> -        indicators = ldq_phys(&address_space_memory, dev->indicators2);
> +        indicators = ldq_phys(&address_space_memory, dev->indicators2->addr);
>          indicators |= 1ULL << vector;
> -        stq_phys(&address_space_memory, dev->indicators2, indicators);
> +        stq_phys(&address_space_memory, dev->indicators2->addr, indicators);
>          css_conditional_io_interrupt(sch);
>      }
>  }
> @@ -995,9 +1032,18 @@ static void virtio_ccw_reset(DeviceState *d)
>      virtio_ccw_stop_ioeventfd(dev);
>      virtio_reset(vdev);
>      css_reset_sch(dev->sch);
> -    dev->indicators = 0;
> -    dev->indicators2 = 0;
> -    dev->summary_indicator = 0;
> +    if (dev->indicators) {
> +        release_indicator(dev->indicators);
> +        dev->indicators = NULL;
> +    }
> +    if (dev->indicators2) {
> +        release_indicator(dev->indicators2);
> +        dev->indicators2 = NULL;
> +    }
> +    if (dev->summary_indicator) {
> +        release_indicator(dev->summary_indicator);
> +        dev->summary_indicator = NULL;
> +    }
>  }
> 
>  static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
> diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
> index 0b70b91..d340bf4 100644
> --- a/hw/s390x/virtio-ccw.h
> +++ b/hw/s390x/virtio-ccw.h
> @@ -75,6 +75,13 @@ typedef struct VirtIOCCWDeviceClass {
>  #define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1
>  #define VIRTIO_CCW_FLAG_USE_IOEVENTFD   (1 << 
> VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT)
> 
> +typedef struct IndAddr {
> +    hwaddr addr;
> +    unsigned long refcnt;
> +    int len;
> +    QTAILQ_ENTRY(IndAddr) sibling;
> +} IndAddr;
> +
>  struct VirtioCcwDevice {
>      DeviceState parent_obj;
>      SubchDev *sch;
> @@ -87,9 +94,9 @@ struct VirtioCcwDevice {
>      uint8_t thinint_isc;
>      uint32_t adapter_id;
>      /* Guest provided values: */
> -    hwaddr indicators;
> -    hwaddr indicators2;
> -    hwaddr summary_indicator;
> +    IndAddr *indicators;
> +    IndAddr *indicators2;
> +    IndAddr *summary_indicator;
>      uint64_t ind_bit;
>  };
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]