14d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk/*  Xenbus code for blkif backend
24d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
34d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    Copyright (C) 2005 XenSource Ltd
44d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
54d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    This program is free software; you can redistribute it and/or modify
64d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    it under the terms of the GNU General Public License as published by
74d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    the Free Software Foundation; either version 2 of the License, or
84d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    (at your option) any later version.
94d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
104d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    This program is distributed in the hope that it will be useful,
114d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    but WITHOUT ANY WARRANTY; without even the implied warranty of
124d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
134d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk    GNU General Public License for more details.
144d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
154d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk*/
164d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
174d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk#include <stdarg.h>
184d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk#include <linux/module.h>
194d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk#include <linux/kthread.h>
20ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk#include <xen/events.h>
21ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk#include <xen/grant_table.h>
224d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk#include "common.h"
234d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
24d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilkstruct backend_info {
2501f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk	struct xenbus_device	*dev;
265185432277ddf5bd91ad5af29cd1945f25ed10fcKonrad Rzeszutek Wilk	struct xen_blkif	*blkif;
2701f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk	struct xenbus_watch	backend_watch;
2801f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk	unsigned		major;
2901f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk	unsigned		minor;
3001f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk	char			*mode;
314d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk};
324d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
338b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilkstatic struct kmem_cache *xen_blkif_cachep;
344d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkstatic void connect(struct backend_info *);
354d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkstatic int connect_ring(struct backend_info *);
364d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkstatic void backend_changed(struct xenbus_watch *, const char **,
374d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			    unsigned int);
384d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
398b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilkstruct xenbus_device *xen_blkbk_xenbus(struct backend_info *be)
4098e036a356747cfaa225478b1e4875e190257b09Jeremy Fitzhardinge{
4198e036a356747cfaa225478b1e4875e190257b09Jeremy Fitzhardinge	return be->dev;
4298e036a356747cfaa225478b1e4875e190257b09Jeremy Fitzhardinge}
4398e036a356747cfaa225478b1e4875e190257b09Jeremy Fitzhardinge
4430fd150202fb2d08a62f9c2966a4b1fcf2e861e7Konrad Rzeszutek Wilkstatic int blkback_name(struct xen_blkif *blkif, char *buf)
454d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
464d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	char *devpath, *devname;
474d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	struct xenbus_device *dev = blkif->be->dev;
484d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
494d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL);
504d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (IS_ERR(devpath))
514d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return PTR_ERR(devpath);
524d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
53d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilk	devname = strstr(devpath, "/dev/");
54d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilk	if (devname != NULL)
554d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		devname += strlen("/dev/");
564d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	else
574d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		devname  = devpath;
584d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
594d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	snprintf(buf, TASK_COMM_LEN, "blkback.%d.%s", blkif->domid, devname);
604d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	kfree(devpath);
614d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
624d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	return 0;
634d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
644d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6530fd150202fb2d08a62f9c2966a4b1fcf2e861e7Konrad Rzeszutek Wilkstatic void xen_update_blkif_status(struct xen_blkif *blkif)
664d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
674d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	int err;
684d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	char name[TASK_COMM_LEN];
694d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
704d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	/* Not ready to connect? */
714d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (!blkif->irq || !blkif->vbd.bdev)
724d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return;
734d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
744d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	/* Already connected? */
754d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (blkif->be->dev->state == XenbusStateConnected)
764d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return;
774d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
784d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	/* Attempt to connect: exit if we fail to. */
794d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	connect(blkif->be);
804d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (blkif->be->dev->state != XenbusStateConnected)
814d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return;
824d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
834d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = blkback_name(blkif, name);
844d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err) {
854d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_error(blkif->be->dev, err, "get blkback dev name");
864d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return;
874d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
884d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
89cbf462908c8080f47c2a3300072877589dd1275fChris Lalancette	err = filemap_write_and_wait(blkif->vbd.bdev->bd_inode->i_mapping);
90cbf462908c8080f47c2a3300072877589dd1275fChris Lalancette	if (err) {
91cbf462908c8080f47c2a3300072877589dd1275fChris Lalancette		xenbus_dev_error(blkif->be->dev, err, "block flush");
92cbf462908c8080f47c2a3300072877589dd1275fChris Lalancette		return;
93cbf462908c8080f47c2a3300072877589dd1275fChris Lalancette	}
94cbf462908c8080f47c2a3300072877589dd1275fChris Lalancette	invalidate_inode_pages2(blkif->vbd.bdev->bd_inode->i_mapping);
95cbf462908c8080f47c2a3300072877589dd1275fChris Lalancette
968b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	blkif->xenblkd = kthread_run(xen_blkif_schedule, blkif, name);
974d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (IS_ERR(blkif->xenblkd)) {
984d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		err = PTR_ERR(blkif->xenblkd);
994d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		blkif->xenblkd = NULL;
1004d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_error(blkif->be->dev, err, "start xenblkd");
1014d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
1024d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
1034d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
10430fd150202fb2d08a62f9c2966a4b1fcf2e861e7Konrad Rzeszutek Wilkstatic struct xen_blkif *xen_blkif_alloc(domid_t domid)
105ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk{
10630fd150202fb2d08a62f9c2966a4b1fcf2e861e7Konrad Rzeszutek Wilk	struct xen_blkif *blkif;
107ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
1088b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL);
109ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	if (!blkif)
110ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		return ERR_PTR(-ENOMEM);
111ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
112ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	memset(blkif, 0, sizeof(*blkif));
113ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	blkif->domid = domid;
114ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	spin_lock_init(&blkif->blk_ring_lock);
115ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	atomic_set(&blkif->refcnt, 1);
116ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	init_waitqueue_head(&blkif->wq);
11729bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk	init_completion(&blkif->drain_complete);
11829bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk	atomic_set(&blkif->drain, 0);
119ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	blkif->st_print = jiffies;
120ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	init_waitqueue_head(&blkif->waiting_to_free);
121ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
122ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	return blkif;
123ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk}
124ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
12530fd150202fb2d08a62f9c2966a4b1fcf2e861e7Konrad Rzeszutek Wilkstatic int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page,
1268b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk			 unsigned int evtchn)
127ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk{
128ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	int err;
129ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
130ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	/* Already connected through? */
131ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	if (blkif->irq)
132ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		return 0;
133ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
1342d073846b891c3f49c4ea03c5db3ac92f92742f1David Vrabel	err = xenbus_map_ring_valloc(blkif->be->dev, shared_page, &blkif->blk_ring);
1352d073846b891c3f49c4ea03c5db3ac92f92742f1David Vrabel	if (err < 0)
136ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		return err;
137ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
138ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	switch (blkif->blk_protocol) {
139ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	case BLKIF_PROTOCOL_NATIVE:
140ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	{
141ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		struct blkif_sring *sring;
1422d073846b891c3f49c4ea03c5db3ac92f92742f1David Vrabel		sring = (struct blkif_sring *)blkif->blk_ring;
143ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE);
144ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		break;
145ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	}
146ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	case BLKIF_PROTOCOL_X86_32:
147ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	{
148ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		struct blkif_x86_32_sring *sring_x86_32;
1492d073846b891c3f49c4ea03c5db3ac92f92742f1David Vrabel		sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring;
150ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE);
151ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		break;
152ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	}
153ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	case BLKIF_PROTOCOL_X86_64:
154ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	{
155ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		struct blkif_x86_64_sring *sring_x86_64;
1562d073846b891c3f49c4ea03c5db3ac92f92742f1David Vrabel		sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring;
157ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE);
158ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		break;
159ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	}
160ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	default:
161ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		BUG();
162ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	}
163ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
1648b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn,
1658b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk						    xen_blkif_be_int, 0,
1668b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk						    "blkif-backend", blkif);
167ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	if (err < 0) {
1682d073846b891c3f49c4ea03c5db3ac92f92742f1David Vrabel		xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring);
169ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		blkif->blk_rings.common.sring = NULL;
170ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		return err;
171ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	}
172ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	blkif->irq = err;
173ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
174ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	return 0;
175ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk}
176ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
17730fd150202fb2d08a62f9c2966a4b1fcf2e861e7Konrad Rzeszutek Wilkstatic void xen_blkif_disconnect(struct xen_blkif *blkif)
178ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk{
179ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	if (blkif->xenblkd) {
180ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		kthread_stop(blkif->xenblkd);
181ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		blkif->xenblkd = NULL;
182ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	}
183ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
184ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	atomic_dec(&blkif->refcnt);
185ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
186ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	atomic_inc(&blkif->refcnt);
187ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
188ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	if (blkif->irq) {
189ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		unbind_from_irqhandler(blkif->irq, blkif);
190ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		blkif->irq = 0;
191ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	}
192ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
193ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	if (blkif->blk_rings.common.sring) {
1942d073846b891c3f49c4ea03c5db3ac92f92742f1David Vrabel		xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring);
195ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		blkif->blk_rings.common.sring = NULL;
196ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	}
197ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk}
198ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
19930fd150202fb2d08a62f9c2966a4b1fcf2e861e7Konrad Rzeszutek Wilkvoid xen_blkif_free(struct xen_blkif *blkif)
200ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk{
201ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	if (!atomic_dec_and_test(&blkif->refcnt))
202ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		BUG();
2038b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	kmem_cache_free(xen_blkif_cachep, blkif);
204ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk}
205ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
2068b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilkint __init xen_blkif_interface_init(void)
207ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk{
2088b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	xen_blkif_cachep = kmem_cache_create("blkif_cache",
20930fd150202fb2d08a62f9c2966a4b1fcf2e861e7Konrad Rzeszutek Wilk					     sizeof(struct xen_blkif),
2108b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk					     0, 0, NULL);
2118b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	if (!xen_blkif_cachep)
212ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk		return -ENOMEM;
213ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk
214ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk	return 0;
215ee9ff8537eacb4383bf9146df6c21b9301c9baa2Konrad Rzeszutek Wilk}
2164d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
217a1397fa3090c25c6c51c04b4101f2786d16b615fKonrad Rzeszutek Wilk/*
2184d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk *  sysfs interface for VBD I/O requests
2194d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk */
2204d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2214d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk#define VBD_SHOW(name, format, args...)					\
2224d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	static ssize_t show_##name(struct device *_dev,			\
2234d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				   struct device_attribute *attr,	\
2244d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				   char *buf)				\
2254d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	{								\
2264d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		struct xenbus_device *dev = to_xenbus_device(_dev);	\
2275cf6e4f6f6d5549904db6ecb3ffd5b8f71f41250Jeremy Fitzhardinge		struct backend_info *be = dev_get_drvdata(&dev->dev);	\
2284d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk									\
2294d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return sprintf(buf, format, ##args);			\
2304d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}								\
2314d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
2324d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2334d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek WilkVBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
2344d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek WilkVBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
2354d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek WilkVBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
23624f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek WilkVBD_SHOW(f_req,  "%d\n", be->blkif->st_f_req);
237b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li DongyangVBD_SHOW(ds_req,  "%d\n", be->blkif->st_ds_req);
2384d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek WilkVBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
2394d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek WilkVBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
2404d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2413d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilkstatic struct attribute *xen_vbdstat_attrs[] = {
2424d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	&dev_attr_oo_req.attr,
2434d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	&dev_attr_rd_req.attr,
2444d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	&dev_attr_wr_req.attr,
24524f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk	&dev_attr_f_req.attr,
246b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	&dev_attr_ds_req.attr,
2474d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	&dev_attr_rd_sect.attr,
2484d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	&dev_attr_wr_sect.attr,
2494d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	NULL
2504d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk};
2514d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2523d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilkstatic struct attribute_group xen_vbdstat_group = {
2534d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	.name = "statistics",
2543d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk	.attrs = xen_vbdstat_attrs,
2554d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk};
2564d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2574d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek WilkVBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
2584d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek WilkVBD_SHOW(mode, "%s\n", be->mode);
2594d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2604d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkint xenvbd_sysfs_addif(struct xenbus_device *dev)
2614d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
2624d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	int error;
2634d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2644d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	error = device_create_file(&dev->dev, &dev_attr_physical_device);
265d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilk	if (error)
2664d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto fail1;
2674d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2684d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	error = device_create_file(&dev->dev, &dev_attr_mode);
2694d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (error)
2704d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto fail2;
2714d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2723d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk	error = sysfs_create_group(&dev->dev.kobj, &xen_vbdstat_group);
2734d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (error)
2744d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto fail3;
2754d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2764d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	return 0;
2774d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2783d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilkfail3:	sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
2794d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkfail2:	device_remove_file(&dev->dev, &dev_attr_mode);
2804d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkfail1:	device_remove_file(&dev->dev, &dev_attr_physical_device);
2814d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	return error;
2824d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
2834d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
2844d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkvoid xenvbd_sysfs_delif(struct xenbus_device *dev)
2854d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
2863d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk	sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
2874d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	device_remove_file(&dev->dev, &dev_attr_mode);
2884d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	device_remove_file(&dev->dev, &dev_attr_physical_device);
2894d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
2904d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
29142c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk
2923d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilkstatic void xen_vbd_free(struct xen_vbd *vbd)
29342c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk{
29442c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	if (vbd->bdev)
29542c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk		blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE);
29642c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	vbd->bdev = NULL;
29742c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk}
29842c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk
2993d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilkstatic int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
3003d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk			  unsigned major, unsigned minor, int readonly,
3013d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk			  int cdrom)
30242c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk{
3033d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk	struct xen_vbd *vbd;
30442c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	struct block_device *bdev;
30524f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk	struct request_queue *q;
30642c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk
30742c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	vbd = &blkif->vbd;
30842c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	vbd->handle   = handle;
30942c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	vbd->readonly = readonly;
31042c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	vbd->type     = 0;
31142c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk
31242c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	vbd->pdevice  = MKDEV(major, minor);
31342c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk
31442c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ?
31542c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk				 FMODE_READ : FMODE_WRITE, NULL);
31642c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk
31742c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	if (IS_ERR(bdev)) {
3183d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk		DPRINTK("xen_vbd_create: device %08x could not be opened.\n",
31942c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk			vbd->pdevice);
32042c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk		return -ENOENT;
32142c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	}
32242c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk
32342c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	vbd->bdev = bdev;
32442c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	if (vbd->bdev->bd_disk == NULL) {
3253d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk		DPRINTK("xen_vbd_create: device %08x doesn't exist.\n",
32642c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk			vbd->pdevice);
3273d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk		xen_vbd_free(vbd);
32842c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk		return -ENOENT;
32942c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	}
3306464920a6e30604cb71d0ecbaa20e35009bd76fbLaszlo Ersek	vbd->size = vbd_sz(vbd);
33142c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk
33242c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom)
33342c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk		vbd->type |= VDISK_CDROM;
33442c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
33542c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk		vbd->type |= VDISK_REMOVABLE;
33642c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk
33724f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk	q = bdev_get_queue(bdev);
33824f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk	if (q && q->flush_flags)
33924f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk		vbd->flush_support = true;
34024f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk
3415ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk	if (q && blk_queue_secdiscard(q))
3425ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk		vbd->discard_secure = true;
3435ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk
34442c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
34542c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk		handle, blkif->domid);
34642c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk	return 0;
34742c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk}
3488b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilkstatic int xen_blkbk_remove(struct xenbus_device *dev)
3494d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
3505cf6e4f6f6d5549904db6ecb3ffd5b8f71f41250Jeremy Fitzhardinge	struct backend_info *be = dev_get_drvdata(&dev->dev);
3514d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
3524d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	DPRINTK("");
3534d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
3544d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (be->major || be->minor)
3554d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenvbd_sysfs_delif(dev);
3564d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
3574d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (be->backend_watch.node) {
3584d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		unregister_xenbus_watch(&be->backend_watch);
3594d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		kfree(be->backend_watch.node);
3604d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		be->backend_watch.node = NULL;
3614d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
3624d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
3634d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (be->blkif) {
3648b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk		xen_blkif_disconnect(be->blkif);
3653d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk		xen_vbd_free(&be->blkif->vbd);
3668b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk		xen_blkif_free(be->blkif);
3674d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		be->blkif = NULL;
3684d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
3694d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
3704d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	kfree(be);
3715cf6e4f6f6d5549904db6ecb3ffd5b8f71f41250Jeremy Fitzhardinge	dev_set_drvdata(&dev->dev, NULL);
3724d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	return 0;
3734d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
3744d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
37524f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilkint xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
37624f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk			      struct backend_info *be, int state)
3774d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
3784d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	struct xenbus_device *dev = be->dev;
3794d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	int err;
3804d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
38124f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk	err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache",
3824d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			    "%d", state);
3834d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err)
38424f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "writing feature-flush-cache");
3854d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
3864d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	return err;
3874d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
3884d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
389b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyangint xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
390b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang{
391b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	struct xenbus_device *dev = be->dev;
392b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	struct xen_blkif *blkif = be->blkif;
393b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	char *type;
394b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	int err;
395b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	int state = 0;
396b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang
397b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL);
398b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	if (!IS_ERR(type)) {
399b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang		if (strncmp(type, "file", 4) == 0) {
400b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang			state = 1;
401b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang			blkif->blk_backend_type = BLKIF_BACKEND_FILE;
402b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang		}
403b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang		if (strncmp(type, "phy", 3) == 0) {
404b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang			struct block_device *bdev = be->blkif->vbd.bdev;
405b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang			struct request_queue *q = bdev_get_queue(bdev);
406b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang			if (blk_queue_discard(q)) {
407b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang				err = xenbus_printf(xbt, dev->nodename,
408b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang					"discard-granularity", "%u",
409b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang					q->limits.discard_granularity);
410b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang				if (err) {
411b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang					xenbus_dev_fatal(dev, err,
412b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang						"writing discard-granularity");
413b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang					goto kfree;
414b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang				}
415b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang				err = xenbus_printf(xbt, dev->nodename,
416b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang					"discard-alignment", "%u",
417b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang					q->limits.discard_alignment);
418b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang				if (err) {
419b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang					xenbus_dev_fatal(dev, err,
420b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang						"writing discard-alignment");
421b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang					goto kfree;
422b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang				}
423b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang				state = 1;
424b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang				blkif->blk_backend_type = BLKIF_BACKEND_PHY;
425b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang			}
4265ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk			/* Optional. */
4275ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk			err = xenbus_printf(xbt, dev->nodename,
4285ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk				"discard-secure", "%d",
4295ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk				blkif->vbd.discard_secure);
4305ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk			if (err) {
4315ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk				xenbus_dev_fatal(dev, err,
4325ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk					"writting discard-secure");
4335ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk				goto kfree;
4345ea42986694a96542644f9cae8b122d3a00c508fKonrad Rzeszutek Wilk			}
435b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang		}
436b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	} else {
437b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang		err = PTR_ERR(type);
438b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang		xenbus_dev_fatal(dev, err, "reading type");
439b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang		goto out;
440b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	}
441b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang
442b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	err = xenbus_printf(xbt, dev->nodename, "feature-discard",
443b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang			    "%d", state);
444b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	if (err)
445b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang		xenbus_dev_fatal(dev, err, "writing feature-discard");
446b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyangkfree:
447b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	kfree(type);
448b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyangout:
449b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	return err;
450b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang}
45129bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilkint xen_blkbk_barrier(struct xenbus_transaction xbt,
45229bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk		      struct backend_info *be, int state)
45329bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk{
45429bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk	struct xenbus_device *dev = be->dev;
45529bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk	int err;
45629bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk
45729bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk	err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
45829bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk			    "%d", state);
45929bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk	if (err)
46029bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "writing feature-barrier");
46129bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk
46229bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk	return err;
46329bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk}
464b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang
46501f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk/*
4664d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk * Entry point to this code when a new device is created.  Allocate the basic
4674d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk * structures, and watch the store waiting for the hotplug scripts to tell us
4684d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk * the device's physical major and minor numbers.  Switch to InitWait.
4694d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk */
4708b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilkstatic int xen_blkbk_probe(struct xenbus_device *dev,
4718b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk			   const struct xenbus_device_id *id)
4724d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
4734d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	int err;
4744d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	struct backend_info *be = kzalloc(sizeof(struct backend_info),
4754d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk					  GFP_KERNEL);
4764d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (!be) {
4774d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, -ENOMEM,
4784d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 "allocating backend structure");
4794d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return -ENOMEM;
4804d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
4814d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	be->dev = dev;
4825cf6e4f6f6d5549904db6ecb3ffd5b8f71f41250Jeremy Fitzhardinge	dev_set_drvdata(&dev->dev, be);
4834d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
4848b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	be->blkif = xen_blkif_alloc(dev->otherend_id);
4854d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (IS_ERR(be->blkif)) {
4864d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		err = PTR_ERR(be->blkif);
4874d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		be->blkif = NULL;
4884d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "creating block interface");
4894d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto fail;
4904d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
4914d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
4924d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	/* setup back pointer */
4934d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	be->blkif->be = be;
4944d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
4958812293323a79134e06c3bf82eba1e217d23382eJeremy Fitzhardinge	err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed,
4968812293323a79134e06c3bf82eba1e217d23382eJeremy Fitzhardinge				   "%s/%s", dev->nodename, "physical-device");
4974d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err)
4984d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto fail;
4994d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5004d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = xenbus_switch_state(dev, XenbusStateInitWait);
5014d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err)
5024d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto fail;
5034d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5044d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	return 0;
5054d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5064d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkfail:
5074d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	DPRINTK("failed");
5088b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	xen_blkbk_remove(dev);
5094d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	return err;
5104d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
5114d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5124d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
51301f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk/*
5144d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk * Callback received when the hotplug scripts have placed the physical-device
5154d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk * node.  Read it and the mode node, and create a vbd.  If the frontend is
5164d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk * ready, connect.
5174d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk */
5184d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkstatic void backend_changed(struct xenbus_watch *watch,
5194d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			    const char **vec, unsigned int len)
5204d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
5214d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	int err;
5224d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	unsigned major;
5234d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	unsigned minor;
5244d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	struct backend_info *be
5254d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		= container_of(watch, struct backend_info, backend_watch);
5264d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	struct xenbus_device *dev = be->dev;
5274d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	int cdrom = 0;
5284d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	char *device_type;
5294d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5304d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	DPRINTK("");
5314d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5324d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = xenbus_scanf(XBT_NIL, dev->nodename, "physical-device", "%x:%x",
5334d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			   &major, &minor);
5344d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (XENBUS_EXIST_ERR(err)) {
53501f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		/*
53601f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		 * Since this watch will fire once immediately after it is
53701f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		 * registered, we expect this.  Ignore it, and wait for the
53801f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		 * hotplug scripts.
53901f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		 */
5404d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return;
5414d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
5424d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err != 2) {
5434d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "reading physical-device");
5444d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return;
5454d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
5464d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5474d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if ((be->major || be->minor) &&
5484d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	    ((be->major != major) || (be->minor != minor))) {
54922b20f2dffd09edd66127f2022c26d0039bad88eKonrad Rzeszutek Wilk		pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n",
550ebe8190659244ec21b5f16950cf7b156f5b7eb01Konrad Rzeszutek Wilk			be->major, be->minor, major, minor);
5514d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return;
5524d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
5534d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5544d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	be->mode = xenbus_read(XBT_NIL, dev->nodename, "mode", NULL);
5554d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (IS_ERR(be->mode)) {
5564d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		err = PTR_ERR(be->mode);
5574d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		be->mode = NULL;
5584d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "reading mode");
5594d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return;
5604d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
5614d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5624d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	device_type = xenbus_read(XBT_NIL, dev->otherend, "device-type", NULL);
5634d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (!IS_ERR(device_type)) {
5644d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		cdrom = strcmp(device_type, "cdrom") == 0;
5654d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		kfree(device_type);
5664d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
5674d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5684d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (be->major == 0 && be->minor == 0) {
5694d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		/* Front end dir is a number, which is used as the handle. */
5704d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5714d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		char *p = strrchr(dev->otherend, '/') + 1;
572d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilk		long handle;
573d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilk		err = strict_strtoul(p, 0, &handle);
574d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilk		if (err)
575d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilk			return;
5764d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5774d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		be->major = major;
5784d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		be->minor = minor;
5794d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5803d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk		err = xen_vbd_create(be->blkif, handle, major, minor,
5814d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 (NULL == strchr(be->mode, 'w')), cdrom);
5824d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		if (err) {
58303e0edf946a08f498788bb6e8ab58453d98f25b9Konrad Rzeszutek Wilk			be->major = 0;
58403e0edf946a08f498788bb6e8ab58453d98f25b9Konrad Rzeszutek Wilk			be->minor = 0;
5854d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			xenbus_dev_fatal(dev, err, "creating vbd structure");
5864d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			return;
5874d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		}
5884d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5894d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		err = xenvbd_sysfs_addif(dev);
5904d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		if (err) {
5913d814731ba67f9514bdf380c1b95dd852ac82a2fKonrad Rzeszutek Wilk			xen_vbd_free(&be->blkif->vbd);
59203e0edf946a08f498788bb6e8ab58453d98f25b9Konrad Rzeszutek Wilk			be->major = 0;
59303e0edf946a08f498788bb6e8ab58453d98f25b9Konrad Rzeszutek Wilk			be->minor = 0;
5944d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			xenbus_dev_fatal(dev, err, "creating sysfs entries");
5954d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			return;
5964d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		}
5974d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
5984d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		/* We're potentially connected now */
5998b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk		xen_update_blkif_status(be->blkif);
6004d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
6014d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
6024d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6034d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
60401f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk/*
6054d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk * Callback received when the frontend's state changes.
6064d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk */
6074d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkstatic void frontend_changed(struct xenbus_device *dev,
6084d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			     enum xenbus_state frontend_state)
6094d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
6105cf6e4f6f6d5549904db6ecb3ffd5b8f71f41250Jeremy Fitzhardinge	struct backend_info *be = dev_get_drvdata(&dev->dev);
6114d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	int err;
6124d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6134d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	DPRINTK("%s", xenbus_strstate(frontend_state));
6144d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6154d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	switch (frontend_state) {
6164d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	case XenbusStateInitialising:
6174d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		if (dev->state == XenbusStateClosed) {
61822b20f2dffd09edd66127f2022c26d0039bad88eKonrad Rzeszutek Wilk			pr_info(DRV_PFX "%s: prepare for reconnect\n",
619ebe8190659244ec21b5f16950cf7b156f5b7eb01Konrad Rzeszutek Wilk				dev->nodename);
6204d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			xenbus_switch_state(dev, XenbusStateInitWait);
6214d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		}
6224d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		break;
6234d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6244d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	case XenbusStateInitialised:
6254d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	case XenbusStateConnected:
62601f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		/*
62701f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		 * Ensure we connect even when two watches fire in
62842b2aa86c6670347a2a07e6d7af0e0ecc8fdbff9Justin P. Mattock		 * close succession and we miss the intermediate value
62901f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		 * of frontend_state.
63001f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		 */
6314d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		if (dev->state == XenbusStateConnected)
6324d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			break;
6334d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
63401f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		/*
63501f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk		 * Enforce precondition before potential leak point.
6361bc05b0ae6448b20d46076899e0cc12ad999e50eJoe Jin		 * xen_blkif_disconnect() is idempotent.
637313d7b003ceceb797e8c0d18ab085ed0638b4affKeir Fraser		 */
6388b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk		xen_blkif_disconnect(be->blkif);
639313d7b003ceceb797e8c0d18ab085ed0638b4affKeir Fraser
6404d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		err = connect_ring(be);
6414d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		if (err)
6424d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			break;
6438b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk		xen_update_blkif_status(be->blkif);
6444d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		break;
6454d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6464d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	case XenbusStateClosing:
6474d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_switch_state(dev, XenbusStateClosing);
6484d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		break;
6494d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6504d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	case XenbusStateClosed:
6516f5986bce558e64fe867bff600a2127a3cb0c006Joe Jin		xen_blkif_disconnect(be->blkif);
6524d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_switch_state(dev, XenbusStateClosed);
6534d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		if (xenbus_dev_is_online(dev))
6544d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			break;
6554d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		/* fall through if not online */
6564d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	case XenbusStateUnknown:
6571bc05b0ae6448b20d46076899e0cc12ad999e50eJoe Jin		/* implies xen_blkif_disconnect() via xen_blkbk_remove() */
6584d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		device_unregister(&dev->dev);
6594d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		break;
6604d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6614d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	default:
6624d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
6634d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 frontend_state);
6644d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		break;
6654d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
6664d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
6674d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6684d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6694d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk/* ** Connection ** */
6704d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6714d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
67201f37f2d53e14a05b7fc3601d182f31ac3b35847Konrad Rzeszutek Wilk/*
6734d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk * Write the physical details regarding the block device to the store, and
6744d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk * switch to Connected state.
6754d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk */
6764d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkstatic void connect(struct backend_info *be)
6774d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
6784d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	struct xenbus_transaction xbt;
6794d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	int err;
6804d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	struct xenbus_device *dev = be->dev;
6814d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6824d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	DPRINTK("%s", dev->otherend);
6834d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
6844d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	/* Supply the information about the device the frontend needs */
6854d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkagain:
6864d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = xenbus_transaction_start(&xbt);
6874d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err) {
6884d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "starting transaction");
6894d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return;
6904d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
6914d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
69224f567f952aa308c3352f3340b9d296fc72bd066Konrad Rzeszutek Wilk	err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support);
6934d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err)
6944d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto abort;
6954d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
696b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang	err = xen_blkbk_discard(xbt, be);
697b3cb0d6adc4bbc70b5e37e49a6068e973545ead7Li Dongyang
69829bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk	/* If we can't advertise it is OK. */
69929bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk	err = xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
70029bde093787f3bdf7b9b4270ada6be7c8076e36bKonrad Rzeszutek Wilk
7014d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
70242c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk			    (unsigned long long)vbd_sz(&be->blkif->vbd));
7034d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err) {
7044d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "writing %s/sectors",
7054d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 dev->nodename);
7064d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto abort;
7074d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
7084d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7094d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	/* FIXME: use a typename instead */
7104d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = xenbus_printf(xbt, dev->nodename, "info", "%u",
71142c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk			    be->blkif->vbd.type |
71242c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk			    (be->blkif->vbd.readonly ? VDISK_READONLY : 0));
7134d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err) {
7144d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "writing %s/info",
7154d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 dev->nodename);
7164d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto abort;
7174d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
7184d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu",
71942c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk			    (unsigned long)
72042c7841d171a2fe32005738dfebd724a90921496Konrad Rzeszutek Wilk			    bdev_logical_block_size(be->blkif->vbd.bdev));
7214d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err) {
7224d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "writing %s/sector-size",
7234d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 dev->nodename);
7244d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto abort;
7254d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
7264d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7274d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = xenbus_transaction_end(xbt, 0);
7284d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err == -EAGAIN)
7294d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		goto again;
7304d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err)
7314d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "ending transaction");
7324d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7334d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = xenbus_switch_state(dev, XenbusStateConnected);
7344d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err)
73508b8bfc1c649cf82edf43f686cbb9a4bac809679Joe Perches		xenbus_dev_fatal(dev, err, "%s: switching to Connected state",
7364d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 dev->nodename);
7374d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7384d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	return;
7394d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk abort:
7404d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	xenbus_transaction_end(xbt, 1);
7414d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
7424d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7434d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7444d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilkstatic int connect_ring(struct backend_info *be)
7454d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
7464d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	struct xenbus_device *dev = be->dev;
7474d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	unsigned long ring_ref;
7484d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	unsigned int evtchn;
7494d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	char protocol[64] = "";
7504d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	int err;
7514d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7524d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	DPRINTK("%s", dev->otherend);
7534d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
754d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilk	err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu",
755d6091b217dd4fdabc4a8cd6fa61775f1e3eb6efeKonrad Rzeszutek Wilk			    &ring_ref, "event-channel", "%u", &evtchn, NULL);
7564d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err) {
7574d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err,
7584d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 "reading %s/ring-ref and event-channel",
7594d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 dev->otherend);
7604d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return err;
7614d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
7624d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7634d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
7644d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
7654d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk			    "%63s", protocol, NULL);
7664d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err)
7674d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		strcpy(protocol, "unspecified, assuming native");
7684d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
7694d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
7704d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
7714d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
7724d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
7734d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
7744d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	else {
7754d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
7764d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return -1;
7774d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
77822b20f2dffd09edd66127f2022c26d0039bad88eKonrad Rzeszutek Wilk	pr_info(DRV_PFX "ring-ref %ld, event-channel %d, protocol %d (%s)\n",
779ebe8190659244ec21b5f16950cf7b156f5b7eb01Konrad Rzeszutek Wilk		ring_ref, evtchn, be->blkif->blk_protocol, protocol);
7804d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7814d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	/* Map the shared frame, irq etc. */
7828b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	err = xen_blkif_map(be->blkif, ring_ref, evtchn);
7834d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	if (err) {
7844d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
7854d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk				 ring_ref, evtchn);
7864d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk		return err;
7874d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	}
7884d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7894d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	return 0;
7904d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
7914d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7924d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7934d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk/* ** Driver Registration ** */
7944d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7954d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
7968b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilkstatic const struct xenbus_device_id xen_blkbk_ids[] = {
7974d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	{ "vbd" },
7984d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	{ "" }
7994d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk};
8004d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
8014d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
80273db144b58a32fc39733db6a7e1fe582072ad26aJan Beulichstatic DEFINE_XENBUS_DRIVER(xen_blkbk, ,
8038b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	.probe = xen_blkbk_probe,
8048b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilk	.remove = xen_blkbk_remove,
8054d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk	.otherend_changed = frontend_changed
80673db144b58a32fc39733db6a7e1fe582072ad26aJan Beulich);
8074d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
8084d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk
8098b6bf747d70e5bac1a34c8fd773230e1cfdd7546Konrad Rzeszutek Wilkint xen_blkif_xenbus_init(void)
8104d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk{
81173db144b58a32fc39733db6a7e1fe582072ad26aJan Beulich	return xenbus_register_backend(&xen_blkbk_driver);
8124d05a28db56225bbab5e1321d818f318e92a4657Konrad Rzeszutek Wilk}
813