xen/scsiback: use lateeoi irq binding
[sfrench/cifs-2.6.git] / drivers / xen / xen-scsiback.c
index 1e8cfd80a4e6b45c066811156b82a9f63ea4c725..4acc4e899600cf09bc91af36463fc8c4940aa114 100644 (file)
@@ -91,7 +91,6 @@ struct vscsibk_info {
        unsigned int irq;
 
        struct vscsiif_back_ring ring;
-       int ring_error;
 
        spinlock_t ring_lock;
        atomic_t nr_unreplied_reqs;
@@ -722,7 +721,8 @@ static struct vscsibk_pend *prepare_pending_reqs(struct vscsibk_info *info,
        return pending_req;
 }
 
-static int scsiback_do_cmd_fn(struct vscsibk_info *info)
+static int scsiback_do_cmd_fn(struct vscsibk_info *info,
+                             unsigned int *eoi_flags)
 {
        struct vscsiif_back_ring *ring = &info->ring;
        struct vscsiif_request ring_req;
@@ -739,11 +739,12 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
                rc = ring->rsp_prod_pvt;
                pr_warn("Dom%d provided bogus ring requests (%#x - %#x = %u). Halting ring processing\n",
                           info->domid, rp, rc, rp - rc);
-               info->ring_error = 1;
-               return 0;
+               return -EINVAL;
        }
 
        while ((rc != rp)) {
+               *eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS;
+
                if (RING_REQUEST_CONS_OVERFLOW(ring, rc))
                        break;
 
@@ -802,13 +803,16 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
 static irqreturn_t scsiback_irq_fn(int irq, void *dev_id)
 {
        struct vscsibk_info *info = dev_id;
+       int rc;
+       unsigned int eoi_flags = XEN_EOI_FLAG_SPURIOUS;
 
-       if (info->ring_error)
-               return IRQ_HANDLED;
-
-       while (scsiback_do_cmd_fn(info))
+       while ((rc = scsiback_do_cmd_fn(info, &eoi_flags)) > 0)
                cond_resched();
 
+       /* In case of a ring error we keep the event channel masked. */
+       if (!rc)
+               xen_irq_lateeoi(irq, eoi_flags);
+
        return IRQ_HANDLED;
 }
 
@@ -829,7 +833,7 @@ static int scsiback_init_sring(struct vscsibk_info *info, grant_ref_t ring_ref,
        sring = (struct vscsiif_sring *)area;
        BACK_RING_INIT(&info->ring, sring, PAGE_SIZE);
 
-       err = bind_interdomain_evtchn_to_irq(info->domid, evtchn);
+       err = bind_interdomain_evtchn_to_irq_lateeoi(info->domid, evtchn);
        if (err < 0)
                goto unmap_page;
 
@@ -1253,7 +1257,6 @@ static int scsiback_probe(struct xenbus_device *dev,
 
        info->domid = dev->otherend_id;
        spin_lock_init(&info->ring_lock);
-       info->ring_error = 0;
        atomic_set(&info->nr_unreplied_reqs, 0);
        init_waitqueue_head(&info->waiting_to_free);
        info->dev = dev;