xen-fbfront.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. /*
  2. * Xen para-virtual frame buffer device
  3. *
  4. * Copyright (C) 2005-2006 Anthony Liguori <aliguori@us.ibm.com>
  5. * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
  6. *
  7. * Based on linux/drivers/video/q40fb.c
  8. *
  9. * This file is subject to the terms and conditions of the GNU General Public
  10. * License. See the file COPYING in the main directory of this archive for
  11. * more details.
  12. */
  13. /*
  14. * TODO:
  15. *
  16. * Switch to grant tables when they become capable of dealing with the
  17. * frame buffer.
  18. */
  19. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  20. #include <linux/console.h>
  21. #include <linux/kernel.h>
  22. #include <linux/errno.h>
  23. #include <linux/fb.h>
  24. #include <linux/module.h>
  25. #include <linux/slab.h>
  26. #include <linux/vmalloc.h>
  27. #include <linux/mm.h>
  28. #include <asm/xen/hypervisor.h>
  29. #include <xen/xen.h>
  30. #include <xen/events.h>
  31. #include <xen/page.h>
  32. #include <xen/interface/io/fbif.h>
  33. #include <xen/interface/io/protocols.h>
  34. #include <xen/xenbus.h>
  35. #include <xen/platform_pci.h>
  36. struct xenfb_info {
  37. unsigned char *fb;
  38. struct fb_info *fb_info;
  39. int x1, y1, x2, y2; /* dirty rectangle,
  40. protected by dirty_lock */
  41. spinlock_t dirty_lock;
  42. int nr_pages;
  43. int irq;
  44. struct xenfb_page *page;
  45. unsigned long *gfns;
  46. int update_wanted; /* XENFB_TYPE_UPDATE wanted */
  47. int feature_resize; /* XENFB_TYPE_RESIZE ok */
  48. struct xenfb_resize resize; /* protected by resize_lock */
  49. int resize_dpy; /* ditto */
  50. spinlock_t resize_lock;
  51. struct xenbus_device *xbdev;
  52. };
  53. #define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8)
  54. enum { KPARAM_MEM, KPARAM_WIDTH, KPARAM_HEIGHT, KPARAM_CNT };
  55. static int video[KPARAM_CNT] = { 2, XENFB_WIDTH, XENFB_HEIGHT };
  56. module_param_array(video, int, NULL, 0);
  57. MODULE_PARM_DESC(video,
  58. "Video memory size in MB, width, height in pixels (default 2,800,600)");
  59. static void xenfb_make_preferred_console(void);
  60. static int xenfb_remove(struct xenbus_device *);
  61. static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *);
  62. static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
  63. static void xenfb_disconnect_backend(struct xenfb_info *);
  64. static void xenfb_send_event(struct xenfb_info *info,
  65. union xenfb_out_event *event)
  66. {
  67. u32 prod;
  68. prod = info->page->out_prod;
  69. /* caller ensures !xenfb_queue_full() */
  70. mb(); /* ensure ring space available */
  71. XENFB_OUT_RING_REF(info->page, prod) = *event;
  72. wmb(); /* ensure ring contents visible */
  73. info->page->out_prod = prod + 1;
  74. notify_remote_via_irq(info->irq);
  75. }
  76. static void xenfb_do_update(struct xenfb_info *info,
  77. int x, int y, int w, int h)
  78. {
  79. union xenfb_out_event event;
  80. memset(&event, 0, sizeof(event));
  81. event.type = XENFB_TYPE_UPDATE;
  82. event.update.x = x;
  83. event.update.y = y;
  84. event.update.width = w;
  85. event.update.height = h;
  86. /* caller ensures !xenfb_queue_full() */
  87. xenfb_send_event(info, &event);
  88. }
  89. static void xenfb_do_resize(struct xenfb_info *info)
  90. {
  91. union xenfb_out_event event;
  92. memset(&event, 0, sizeof(event));
  93. event.resize = info->resize;
  94. /* caller ensures !xenfb_queue_full() */
  95. xenfb_send_event(info, &event);
  96. }
  97. static int xenfb_queue_full(struct xenfb_info *info)
  98. {
  99. u32 cons, prod;
  100. prod = info->page->out_prod;
  101. cons = info->page->out_cons;
  102. return prod - cons == XENFB_OUT_RING_LEN;
  103. }
  104. static void xenfb_handle_resize_dpy(struct xenfb_info *info)
  105. {
  106. unsigned long flags;
  107. spin_lock_irqsave(&info->resize_lock, flags);
  108. if (info->resize_dpy) {
  109. if (!xenfb_queue_full(info)) {
  110. info->resize_dpy = 0;
  111. xenfb_do_resize(info);
  112. }
  113. }
  114. spin_unlock_irqrestore(&info->resize_lock, flags);
  115. }
  116. static void xenfb_refresh(struct xenfb_info *info,
  117. int x1, int y1, int w, int h)
  118. {
  119. unsigned long flags;
  120. int x2 = x1 + w - 1;
  121. int y2 = y1 + h - 1;
  122. xenfb_handle_resize_dpy(info);
  123. if (!info->update_wanted)
  124. return;
  125. spin_lock_irqsave(&info->dirty_lock, flags);
  126. /* Combine with dirty rectangle: */
  127. if (info->y1 < y1)
  128. y1 = info->y1;
  129. if (info->y2 > y2)
  130. y2 = info->y2;
  131. if (info->x1 < x1)
  132. x1 = info->x1;
  133. if (info->x2 > x2)
  134. x2 = info->x2;
  135. if (xenfb_queue_full(info)) {
  136. /* Can't send right now, stash it in the dirty rectangle */
  137. info->x1 = x1;
  138. info->x2 = x2;
  139. info->y1 = y1;
  140. info->y2 = y2;
  141. spin_unlock_irqrestore(&info->dirty_lock, flags);
  142. return;
  143. }
  144. /* Clear dirty rectangle: */
  145. info->x1 = info->y1 = INT_MAX;
  146. info->x2 = info->y2 = 0;
  147. spin_unlock_irqrestore(&info->dirty_lock, flags);
  148. if (x1 <= x2 && y1 <= y2)
  149. xenfb_do_update(info, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
  150. }
  151. static void xenfb_deferred_io(struct fb_info *fb_info,
  152. struct list_head *pagelist)
  153. {
  154. struct xenfb_info *info = fb_info->par;
  155. struct page *page;
  156. unsigned long beg, end;
  157. int y1, y2, miny, maxy;
  158. miny = INT_MAX;
  159. maxy = 0;
  160. list_for_each_entry(page, pagelist, lru) {
  161. beg = page->index << PAGE_SHIFT;
  162. end = beg + PAGE_SIZE - 1;
  163. y1 = beg / fb_info->fix.line_length;
  164. y2 = end / fb_info->fix.line_length;
  165. if (y2 >= fb_info->var.yres)
  166. y2 = fb_info->var.yres - 1;
  167. if (miny > y1)
  168. miny = y1;
  169. if (maxy < y2)
  170. maxy = y2;
  171. }
  172. xenfb_refresh(info, 0, miny, fb_info->var.xres, maxy - miny + 1);
  173. }
  174. static struct fb_deferred_io xenfb_defio = {
  175. .delay = HZ / 20,
  176. .deferred_io = xenfb_deferred_io,
  177. };
  178. static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
  179. unsigned blue, unsigned transp,
  180. struct fb_info *info)
  181. {
  182. u32 v;
  183. if (regno > info->cmap.len)
  184. return 1;
  185. #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
  186. red = CNVT_TOHW(red, info->var.red.length);
  187. green = CNVT_TOHW(green, info->var.green.length);
  188. blue = CNVT_TOHW(blue, info->var.blue.length);
  189. transp = CNVT_TOHW(transp, info->var.transp.length);
  190. #undef CNVT_TOHW
  191. v = (red << info->var.red.offset) |
  192. (green << info->var.green.offset) |
  193. (blue << info->var.blue.offset);
  194. switch (info->var.bits_per_pixel) {
  195. case 16:
  196. case 24:
  197. case 32:
  198. ((u32 *)info->pseudo_palette)[regno] = v;
  199. break;
  200. }
  201. return 0;
  202. }
  203. static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
  204. {
  205. struct xenfb_info *info = p->par;
  206. sys_fillrect(p, rect);
  207. xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
  208. }
  209. static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
  210. {
  211. struct xenfb_info *info = p->par;
  212. sys_imageblit(p, image);
  213. xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
  214. }
  215. static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
  216. {
  217. struct xenfb_info *info = p->par;
  218. sys_copyarea(p, area);
  219. xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
  220. }
  221. static ssize_t xenfb_write(struct fb_info *p, const char __user *buf,
  222. size_t count, loff_t *ppos)
  223. {
  224. struct xenfb_info *info = p->par;
  225. ssize_t res;
  226. res = fb_sys_write(p, buf, count, ppos);
  227. xenfb_refresh(info, 0, 0, info->page->width, info->page->height);
  228. return res;
  229. }
  230. static int
  231. xenfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  232. {
  233. struct xenfb_info *xenfb_info;
  234. int required_mem_len;
  235. xenfb_info = info->par;
  236. if (!xenfb_info->feature_resize) {
  237. if (var->xres == video[KPARAM_WIDTH] &&
  238. var->yres == video[KPARAM_HEIGHT] &&
  239. var->bits_per_pixel == xenfb_info->page->depth) {
  240. return 0;
  241. }
  242. return -EINVAL;
  243. }
  244. /* Can't resize past initial width and height */
  245. if (var->xres > video[KPARAM_WIDTH] || var->yres > video[KPARAM_HEIGHT])
  246. return -EINVAL;
  247. required_mem_len = var->xres * var->yres * xenfb_info->page->depth / 8;
  248. if (var->bits_per_pixel == xenfb_info->page->depth &&
  249. var->xres <= info->fix.line_length / (XENFB_DEPTH / 8) &&
  250. required_mem_len <= info->fix.smem_len) {
  251. var->xres_virtual = var->xres;
  252. var->yres_virtual = var->yres;
  253. return 0;
  254. }
  255. return -EINVAL;
  256. }
  257. static int xenfb_set_par(struct fb_info *info)
  258. {
  259. struct xenfb_info *xenfb_info;
  260. unsigned long flags;
  261. xenfb_info = info->par;
  262. spin_lock_irqsave(&xenfb_info->resize_lock, flags);
  263. xenfb_info->resize.type = XENFB_TYPE_RESIZE;
  264. xenfb_info->resize.width = info->var.xres;
  265. xenfb_info->resize.height = info->var.yres;
  266. xenfb_info->resize.stride = info->fix.line_length;
  267. xenfb_info->resize.depth = info->var.bits_per_pixel;
  268. xenfb_info->resize.offset = 0;
  269. xenfb_info->resize_dpy = 1;
  270. spin_unlock_irqrestore(&xenfb_info->resize_lock, flags);
  271. return 0;
  272. }
  273. static const struct fb_ops xenfb_fb_ops = {
  274. .owner = THIS_MODULE,
  275. .fb_read = fb_sys_read,
  276. .fb_write = xenfb_write,
  277. .fb_setcolreg = xenfb_setcolreg,
  278. .fb_fillrect = xenfb_fillrect,
  279. .fb_copyarea = xenfb_copyarea,
  280. .fb_imageblit = xenfb_imageblit,
  281. .fb_check_var = xenfb_check_var,
  282. .fb_set_par = xenfb_set_par,
  283. };
  284. static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
  285. {
  286. /*
  287. * No in events recognized, simply ignore them all.
  288. * If you need to recognize some, see xen-kbdfront's
  289. * input_handler() for how to do that.
  290. */
  291. struct xenfb_info *info = dev_id;
  292. struct xenfb_page *page = info->page;
  293. if (page->in_cons != page->in_prod) {
  294. info->page->in_cons = info->page->in_prod;
  295. notify_remote_via_irq(info->irq);
  296. }
  297. /* Flush dirty rectangle: */
  298. xenfb_refresh(info, INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
  299. return IRQ_HANDLED;
  300. }
  301. static int xenfb_probe(struct xenbus_device *dev,
  302. const struct xenbus_device_id *id)
  303. {
  304. struct xenfb_info *info;
  305. struct fb_info *fb_info;
  306. int fb_size;
  307. int val;
  308. int ret = 0;
  309. info = kzalloc(sizeof(*info), GFP_KERNEL);
  310. if (info == NULL) {
  311. xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
  312. return -ENOMEM;
  313. }
  314. /* Limit kernel param videoram amount to what is in xenstore */
  315. if (xenbus_scanf(XBT_NIL, dev->otherend, "videoram", "%d", &val) == 1) {
  316. if (val < video[KPARAM_MEM])
  317. video[KPARAM_MEM] = val;
  318. }
  319. video[KPARAM_WIDTH] = xenbus_read_unsigned(dev->otherend, "width",
  320. video[KPARAM_WIDTH]);
  321. video[KPARAM_HEIGHT] = xenbus_read_unsigned(dev->otherend, "height",
  322. video[KPARAM_HEIGHT]);
  323. /* If requested res does not fit in available memory, use default */
  324. fb_size = video[KPARAM_MEM] * 1024 * 1024;
  325. if (video[KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH / 8
  326. > fb_size) {
  327. pr_warn("display parameters %d,%d,%d invalid, use defaults\n",
  328. video[KPARAM_MEM], video[KPARAM_WIDTH],
  329. video[KPARAM_HEIGHT]);
  330. video[KPARAM_WIDTH] = XENFB_WIDTH;
  331. video[KPARAM_HEIGHT] = XENFB_HEIGHT;
  332. fb_size = XENFB_DEFAULT_FB_LEN;
  333. }
  334. dev_set_drvdata(&dev->dev, info);
  335. info->xbdev = dev;
  336. info->irq = -1;
  337. info->x1 = info->y1 = INT_MAX;
  338. spin_lock_init(&info->dirty_lock);
  339. spin_lock_init(&info->resize_lock);
  340. info->fb = vzalloc(fb_size);
  341. if (info->fb == NULL)
  342. goto error_nomem;
  343. info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
  344. info->gfns = vmalloc(array_size(sizeof(unsigned long), info->nr_pages));
  345. if (!info->gfns)
  346. goto error_nomem;
  347. /* set up shared page */
  348. info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
  349. if (!info->page)
  350. goto error_nomem;
  351. /* abusing framebuffer_alloc() to allocate pseudo_palette */
  352. fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
  353. if (fb_info == NULL)
  354. goto error_nomem;
  355. /* complete the abuse: */
  356. fb_info->pseudo_palette = fb_info->par;
  357. fb_info->par = info;
  358. fb_info->screen_base = info->fb;
  359. fb_info->fbops = &xenfb_fb_ops;
  360. fb_info->var.xres_virtual = fb_info->var.xres = video[KPARAM_WIDTH];
  361. fb_info->var.yres_virtual = fb_info->var.yres = video[KPARAM_HEIGHT];
  362. fb_info->var.bits_per_pixel = XENFB_DEPTH;
  363. fb_info->var.red = (struct fb_bitfield){16, 8, 0};
  364. fb_info->var.green = (struct fb_bitfield){8, 8, 0};
  365. fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
  366. fb_info->var.activate = FB_ACTIVATE_NOW;
  367. fb_info->var.height = -1;
  368. fb_info->var.width = -1;
  369. fb_info->var.vmode = FB_VMODE_NONINTERLACED;
  370. fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
  371. fb_info->fix.line_length = fb_info->var.xres * XENFB_DEPTH / 8;
  372. fb_info->fix.smem_start = 0;
  373. fb_info->fix.smem_len = fb_size;
  374. strcpy(fb_info->fix.id, "xen");
  375. fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
  376. fb_info->fix.accel = FB_ACCEL_NONE;
  377. fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
  378. ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
  379. if (ret < 0) {
  380. framebuffer_release(fb_info);
  381. xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
  382. goto error;
  383. }
  384. fb_info->fbdefio = &xenfb_defio;
  385. fb_deferred_io_init(fb_info);
  386. xenfb_init_shared_page(info, fb_info);
  387. ret = xenfb_connect_backend(dev, info);
  388. if (ret < 0) {
  389. xenbus_dev_fatal(dev, ret, "xenfb_connect_backend");
  390. goto error_fb;
  391. }
  392. ret = register_framebuffer(fb_info);
  393. if (ret) {
  394. xenbus_dev_fatal(dev, ret, "register_framebuffer");
  395. goto error_fb;
  396. }
  397. info->fb_info = fb_info;
  398. xenfb_make_preferred_console();
  399. return 0;
  400. error_fb:
  401. fb_deferred_io_cleanup(fb_info);
  402. fb_dealloc_cmap(&fb_info->cmap);
  403. framebuffer_release(fb_info);
  404. error_nomem:
  405. if (!ret) {
  406. ret = -ENOMEM;
  407. xenbus_dev_fatal(dev, ret, "allocating device memory");
  408. }
  409. error:
  410. xenfb_remove(dev);
  411. return ret;
  412. }
  413. static void xenfb_make_preferred_console(void)
  414. {
  415. struct console *c;
  416. if (console_set_on_cmdline)
  417. return;
  418. console_lock();
  419. for_each_console(c) {
  420. if (!strcmp(c->name, "tty") && c->index == 0)
  421. break;
  422. }
  423. console_unlock();
  424. if (c) {
  425. unregister_console(c);
  426. c->flags |= CON_CONSDEV;
  427. c->flags &= ~CON_PRINTBUFFER; /* don't print again */
  428. register_console(c);
  429. }
  430. }
  431. static int xenfb_resume(struct xenbus_device *dev)
  432. {
  433. struct xenfb_info *info = dev_get_drvdata(&dev->dev);
  434. xenfb_disconnect_backend(info);
  435. xenfb_init_shared_page(info, info->fb_info);
  436. return xenfb_connect_backend(dev, info);
  437. }
  438. static int xenfb_remove(struct xenbus_device *dev)
  439. {
  440. struct xenfb_info *info = dev_get_drvdata(&dev->dev);
  441. xenfb_disconnect_backend(info);
  442. if (info->fb_info) {
  443. fb_deferred_io_cleanup(info->fb_info);
  444. unregister_framebuffer(info->fb_info);
  445. fb_dealloc_cmap(&info->fb_info->cmap);
  446. framebuffer_release(info->fb_info);
  447. }
  448. free_page((unsigned long)info->page);
  449. vfree(info->gfns);
  450. vfree(info->fb);
  451. kfree(info);
  452. return 0;
  453. }
  454. static unsigned long vmalloc_to_gfn(void *address)
  455. {
  456. return xen_page_to_gfn(vmalloc_to_page(address));
  457. }
  458. static void xenfb_init_shared_page(struct xenfb_info *info,
  459. struct fb_info *fb_info)
  460. {
  461. int i;
  462. int epd = PAGE_SIZE / sizeof(info->gfns[0]);
  463. for (i = 0; i < info->nr_pages; i++)
  464. info->gfns[i] = vmalloc_to_gfn(info->fb + i * PAGE_SIZE);
  465. for (i = 0; i * epd < info->nr_pages; i++)
  466. info->page->pd[i] = vmalloc_to_gfn(&info->gfns[i * epd]);
  467. info->page->width = fb_info->var.xres;
  468. info->page->height = fb_info->var.yres;
  469. info->page->depth = fb_info->var.bits_per_pixel;
  470. info->page->line_length = fb_info->fix.line_length;
  471. info->page->mem_length = fb_info->fix.smem_len;
  472. info->page->in_cons = info->page->in_prod = 0;
  473. info->page->out_cons = info->page->out_prod = 0;
  474. }
  475. static int xenfb_connect_backend(struct xenbus_device *dev,
  476. struct xenfb_info *info)
  477. {
  478. int ret, evtchn, irq;
  479. struct xenbus_transaction xbt;
  480. ret = xenbus_alloc_evtchn(dev, &evtchn);
  481. if (ret)
  482. return ret;
  483. irq = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
  484. 0, dev->devicetype, info);
  485. if (irq < 0) {
  486. xenbus_free_evtchn(dev, evtchn);
  487. xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
  488. return irq;
  489. }
  490. again:
  491. ret = xenbus_transaction_start(&xbt);
  492. if (ret) {
  493. xenbus_dev_fatal(dev, ret, "starting transaction");
  494. goto unbind_irq;
  495. }
  496. ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
  497. virt_to_gfn(info->page));
  498. if (ret)
  499. goto error_xenbus;
  500. ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
  501. evtchn);
  502. if (ret)
  503. goto error_xenbus;
  504. ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
  505. XEN_IO_PROTO_ABI_NATIVE);
  506. if (ret)
  507. goto error_xenbus;
  508. ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
  509. if (ret)
  510. goto error_xenbus;
  511. ret = xenbus_transaction_end(xbt, 0);
  512. if (ret) {
  513. if (ret == -EAGAIN)
  514. goto again;
  515. xenbus_dev_fatal(dev, ret, "completing transaction");
  516. goto unbind_irq;
  517. }
  518. xenbus_switch_state(dev, XenbusStateInitialised);
  519. info->irq = irq;
  520. return 0;
  521. error_xenbus:
  522. xenbus_transaction_end(xbt, 1);
  523. xenbus_dev_fatal(dev, ret, "writing xenstore");
  524. unbind_irq:
  525. unbind_from_irqhandler(irq, info);
  526. return ret;
  527. }
  528. static void xenfb_disconnect_backend(struct xenfb_info *info)
  529. {
  530. /* Prevent xenfb refresh */
  531. info->update_wanted = 0;
  532. if (info->irq >= 0)
  533. unbind_from_irqhandler(info->irq, info);
  534. info->irq = -1;
  535. }
  536. static void xenfb_backend_changed(struct xenbus_device *dev,
  537. enum xenbus_state backend_state)
  538. {
  539. struct xenfb_info *info = dev_get_drvdata(&dev->dev);
  540. switch (backend_state) {
  541. case XenbusStateInitialising:
  542. case XenbusStateInitialised:
  543. case XenbusStateReconfiguring:
  544. case XenbusStateReconfigured:
  545. case XenbusStateUnknown:
  546. break;
  547. case XenbusStateInitWait:
  548. xenbus_switch_state(dev, XenbusStateConnected);
  549. break;
  550. case XenbusStateConnected:
  551. /*
  552. * Work around xenbus race condition: If backend goes
  553. * through InitWait to Connected fast enough, we can
  554. * get Connected twice here.
  555. */
  556. if (dev->state != XenbusStateConnected)
  557. /* no InitWait seen yet, fudge it */
  558. xenbus_switch_state(dev, XenbusStateConnected);
  559. if (xenbus_read_unsigned(info->xbdev->otherend,
  560. "request-update", 0))
  561. info->update_wanted = 1;
  562. info->feature_resize = xenbus_read_unsigned(dev->otherend,
  563. "feature-resize", 0);
  564. break;
  565. case XenbusStateClosed:
  566. if (dev->state == XenbusStateClosed)
  567. break;
  568. fallthrough; /* Missed the backend's CLOSING state */
  569. case XenbusStateClosing:
  570. xenbus_frontend_closed(dev);
  571. break;
  572. }
  573. }
  574. static const struct xenbus_device_id xenfb_ids[] = {
  575. { "vfb" },
  576. { "" }
  577. };
  578. static struct xenbus_driver xenfb_driver = {
  579. .ids = xenfb_ids,
  580. .probe = xenfb_probe,
  581. .remove = xenfb_remove,
  582. .resume = xenfb_resume,
  583. .otherend_changed = xenfb_backend_changed,
  584. };
  585. static int __init xenfb_init(void)
  586. {
  587. if (!xen_domain())
  588. return -ENODEV;
  589. /* Nothing to do if running in dom0. */
  590. if (xen_initial_domain())
  591. return -ENODEV;
  592. if (!xen_has_pv_devices())
  593. return -ENODEV;
  594. return xenbus_register_frontend(&xenfb_driver);
  595. }
  596. static void __exit xenfb_cleanup(void)
  597. {
  598. xenbus_unregister_driver(&xenfb_driver);
  599. }
  600. module_init(xenfb_init);
  601. module_exit(xenfb_cleanup);
  602. MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");
  603. MODULE_LICENSE("GPL");
  604. MODULE_ALIAS("xen:vfb");