static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, unsigned int evtchn) { int err; /* Already connected through? */ if (blkif->irq) return 0; blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE); if (!blkif->blk_ring_area) return -ENOMEM; err = map_frontend_page(blkif, shared_page); if (err) { free_vm_area(blkif->blk_ring_area); return err; } switch (blkif->blk_protocol) { case BLKIF_PROTOCOL_NATIVE: { struct blkif_sring *sring; sring = (struct blkif_sring *)blkif->blk_ring_area->addr; BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE); break; } case BLKIF_PROTOCOL_X86_32: { struct blkif_x86_32_sring *sring_x86_32; sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr; BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); break; } case BLKIF_PROTOCOL_X86_64: { struct blkif_x86_64_sring *sring_x86_64; sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr; BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); break; } default: BUG(); } err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn, xen_blkif_be_int, 0, "blkif-backend", blkif); if (err < 0) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); blkif->blk_rings.common.sring = NULL; return err; } blkif->irq = err; return 0; }
static void free_blkif(void *arg) { blkif_t *blkif = (blkif_t *)arg; if (blkif->irq) unbind_from_irqhandler(blkif->irq, blkif); if (blkif->blk_ring.sring) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); blkif->blk_ring.sring = NULL; } kmem_cache_free(blkif_cachep, blkif); }
void scsiback_disconnect(struct vscsibk_info *info) { if (info->kthread) { kthread_stop(info->kthread); info->kthread = NULL; } wait_event(info->waiting_to_free, atomic_read(&info->nr_unreplied_reqs) == 0); if (info->irq) { unbind_from_irqhandler(info->irq, info); info->irq = 0; } if (info->ring.sring) { unmap_frontend_page(info); free_vm_area(info->ring_area); info->ring.sring = NULL; } }
int scsiback_init_sring(struct vscsibk_info *info, unsigned long ring_ref, unsigned int evtchn) { struct vscsiif_sring *sring; int err; if (info->irq) { printk(KERN_ERR "scsiback: Already connected through?\n"); return -1; } info->ring_area = alloc_vm_area(PAGE_SIZE); if (!info) return -ENOMEM; err = map_frontend_page(info, ring_ref); if (err) goto free_vm; sring = (struct vscsiif_sring *) info->ring_area->addr; BACK_RING_INIT(&info->ring, sring, PAGE_SIZE); err = bind_interdomain_evtchn_to_irqhandler( info->domid, evtchn, scsiback_intr, 0, "vscsiif-backend", info); if (err < 0) goto unmap_page; info->irq = err; return 0; unmap_page: unmap_frontend_page(info); free_vm: free_vm_area(info->ring_area); return err; }
static void xen_blkif_disconnect(struct xen_blkif *blkif) { if (blkif->xenblkd) { kthread_stop(blkif->xenblkd); blkif->xenblkd = NULL; } atomic_dec(&blkif->refcnt); wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0); atomic_inc(&blkif->refcnt); if (blkif->irq) { unbind_from_irqhandler(blkif->irq, blkif); blkif->irq = 0; } if (blkif->blk_rings.common.sring) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); blkif->blk_rings.common.sring = NULL; } }
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) { blkif_sring_t *sring; int err; struct evtchn_bind_interdomain bind_interdomain; if ((blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL) return -ENOMEM; err = map_frontend_page(blkif, shared_page); if (err) { free_vm_area(blkif->blk_ring_area); return err; } bind_interdomain.remote_dom = blkif->domid; bind_interdomain.remote_port = evtchn; err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &bind_interdomain); if (err) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); return err; } blkif->evtchn = bind_interdomain.local_port; sring = (blkif_sring_t *)blkif->blk_ring_area->addr; BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); blkif->irq = bind_evtchn_to_irqhandler( blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); blkif->status = CONNECTED; return 0; }