1 /******************************************************************************
2 * arch/xen/drivers/blkif/backend/interface.c
4 * Block-device interface management.
6 * Copyright (c) 2004, Keir Fraser
10 #include <xen/evtchn.h>
12 static kmem_cache_t *blkif_cachep;
14 blkif_t *alloc_blkif(domid_t domid)
18 blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
20 return ERR_PTR(-ENOMEM);
22 memset(blkif, 0, sizeof(*blkif));
24 blkif->status = DISCONNECTED;
25 spin_lock_init(&blkif->blk_ring_lock);
26 atomic_set(&blkif->refcnt, 1);
31 static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
33 struct gnttab_map_grant_ref op;
36 op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
37 op.flags = GNTMAP_host_map;
39 op.dom = blkif->domid;
41 lock_vm_area(blkif->blk_ring_area);
42 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
43 unlock_vm_area(blkif->blk_ring_area);
47 DPRINTK(" Grant table operation failure !\n");
51 blkif->shmem_ref = shared_page;
52 blkif->shmem_handle = op.handle;
57 static void unmap_frontend_page(blkif_t *blkif)
59 struct gnttab_unmap_grant_ref op;
62 op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
63 op.handle = blkif->shmem_handle;
66 lock_vm_area(blkif->blk_ring_area);
67 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
68 unlock_vm_area(blkif->blk_ring_area);
72 int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
77 .cmd = EVTCHNOP_bind_interdomain,
78 .u.bind_interdomain.remote_dom = blkif->domid,
79 .u.bind_interdomain.remote_port = evtchn };
81 if ((blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
84 err = map_frontend_page(blkif, shared_page);
86 free_vm_area(blkif->blk_ring_area);
90 err = HYPERVISOR_event_channel_op(&op);
92 unmap_frontend_page(blkif);
93 free_vm_area(blkif->blk_ring_area);
97 blkif->evtchn = op.u.bind_interdomain.local_port;
99 sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
100 BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
102 blkif->irq = bind_evtchn_to_irqhandler(
103 blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
105 blkif->status = CONNECTED;
110 static void free_blkif(void *arg)
112 blkif_t *blkif = (blkif_t *)arg;
115 unbind_from_irqhandler(blkif->irq, blkif);
117 if (blkif->blk_ring.sring) {
118 unmap_frontend_page(blkif);
119 free_vm_area(blkif->blk_ring_area);
120 blkif->blk_ring.sring = NULL;
123 kmem_cache_free(blkif_cachep, blkif);
126 void free_blkif_callback(blkif_t *blkif)
128 INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
129 schedule_work(&blkif->free_work);
132 void __init blkif_interface_init(void)
134 blkif_cachep = kmem_cache_create(
135 "blkif_cache", sizeof(blkif_t), 0, 0, NULL, NULL);
140 * c-file-style: "linux"
141 * indent-tabs-mode: t