xen_drm_front.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. // SPDX-License-Identifier: GPL-2.0 OR MIT
  2. /*
  3. * Xen para-virtual DRM device
  4. *
  5. * Copyright (C) 2016-2018 EPAM Systems Inc.
  6. *
  7. * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
  8. */
  9. #include <linux/delay.h>
  10. #include <linux/dma-mapping.h>
  11. #include <linux/module.h>
  12. #include <drm/drm_atomic_helper.h>
  13. #include <drm/drm_drv.h>
  14. #include <drm/drm_ioctl.h>
  15. #include <drm/drm_probe_helper.h>
  16. #include <drm/drm_file.h>
  17. #include <drm/drm_gem.h>
  18. #include <drm/drm_print.h>
  19. #include <xen/platform_pci.h>
  20. #include <xen/xen.h>
  21. #include <xen/xenbus.h>
  22. #include <xen/xen-front-pgdir-shbuf.h>
  23. #include <xen/interface/io/displif.h>
  24. #include "xen_drm_front.h"
  25. #include "xen_drm_front_cfg.h"
  26. #include "xen_drm_front_evtchnl.h"
  27. #include "xen_drm_front_gem.h"
  28. #include "xen_drm_front_kms.h"
  29. struct xen_drm_front_dbuf {
  30. struct list_head list;
  31. u64 dbuf_cookie;
  32. u64 fb_cookie;
  33. struct xen_front_pgdir_shbuf shbuf;
  34. };
  35. static void dbuf_add_to_list(struct xen_drm_front_info *front_info,
  36. struct xen_drm_front_dbuf *dbuf, u64 dbuf_cookie)
  37. {
  38. dbuf->dbuf_cookie = dbuf_cookie;
  39. list_add(&dbuf->list, &front_info->dbuf_list);
  40. }
  41. static struct xen_drm_front_dbuf *dbuf_get(struct list_head *dbuf_list,
  42. u64 dbuf_cookie)
  43. {
  44. struct xen_drm_front_dbuf *buf, *q;
  45. list_for_each_entry_safe(buf, q, dbuf_list, list)
  46. if (buf->dbuf_cookie == dbuf_cookie)
  47. return buf;
  48. return NULL;
  49. }
  50. static void dbuf_free(struct list_head *dbuf_list, u64 dbuf_cookie)
  51. {
  52. struct xen_drm_front_dbuf *buf, *q;
  53. list_for_each_entry_safe(buf, q, dbuf_list, list)
  54. if (buf->dbuf_cookie == dbuf_cookie) {
  55. list_del(&buf->list);
  56. xen_front_pgdir_shbuf_unmap(&buf->shbuf);
  57. xen_front_pgdir_shbuf_free(&buf->shbuf);
  58. kfree(buf);
  59. break;
  60. }
  61. }
  62. static void dbuf_free_all(struct list_head *dbuf_list)
  63. {
  64. struct xen_drm_front_dbuf *buf, *q;
  65. list_for_each_entry_safe(buf, q, dbuf_list, list) {
  66. list_del(&buf->list);
  67. xen_front_pgdir_shbuf_unmap(&buf->shbuf);
  68. xen_front_pgdir_shbuf_free(&buf->shbuf);
  69. kfree(buf);
  70. }
  71. }
  72. static struct xendispl_req *
  73. be_prepare_req(struct xen_drm_front_evtchnl *evtchnl, u8 operation)
  74. {
  75. struct xendispl_req *req;
  76. req = RING_GET_REQUEST(&evtchnl->u.req.ring,
  77. evtchnl->u.req.ring.req_prod_pvt);
  78. req->operation = operation;
  79. req->id = evtchnl->evt_next_id++;
  80. evtchnl->evt_id = req->id;
  81. return req;
  82. }
  83. static int be_stream_do_io(struct xen_drm_front_evtchnl *evtchnl,
  84. struct xendispl_req *req)
  85. {
  86. reinit_completion(&evtchnl->u.req.completion);
  87. if (unlikely(evtchnl->state != EVTCHNL_STATE_CONNECTED))
  88. return -EIO;
  89. xen_drm_front_evtchnl_flush(evtchnl);
  90. return 0;
  91. }
  92. static int be_stream_wait_io(struct xen_drm_front_evtchnl *evtchnl)
  93. {
  94. if (wait_for_completion_timeout(&evtchnl->u.req.completion,
  95. msecs_to_jiffies(XEN_DRM_FRONT_WAIT_BACK_MS)) <= 0)
  96. return -ETIMEDOUT;
  97. return evtchnl->u.req.resp_status;
  98. }
  99. int xen_drm_front_mode_set(struct xen_drm_front_drm_pipeline *pipeline,
  100. u32 x, u32 y, u32 width, u32 height,
  101. u32 bpp, u64 fb_cookie)
  102. {
  103. struct xen_drm_front_evtchnl *evtchnl;
  104. struct xen_drm_front_info *front_info;
  105. struct xendispl_req *req;
  106. unsigned long flags;
  107. int ret;
  108. front_info = pipeline->drm_info->front_info;
  109. evtchnl = &front_info->evt_pairs[pipeline->index].req;
  110. if (unlikely(!evtchnl))
  111. return -EIO;
  112. mutex_lock(&evtchnl->u.req.req_io_lock);
  113. spin_lock_irqsave(&front_info->io_lock, flags);
  114. req = be_prepare_req(evtchnl, XENDISPL_OP_SET_CONFIG);
  115. req->op.set_config.x = x;
  116. req->op.set_config.y = y;
  117. req->op.set_config.width = width;
  118. req->op.set_config.height = height;
  119. req->op.set_config.bpp = bpp;
  120. req->op.set_config.fb_cookie = fb_cookie;
  121. ret = be_stream_do_io(evtchnl, req);
  122. spin_unlock_irqrestore(&front_info->io_lock, flags);
  123. if (ret == 0)
  124. ret = be_stream_wait_io(evtchnl);
  125. mutex_unlock(&evtchnl->u.req.req_io_lock);
  126. return ret;
  127. }
  128. int xen_drm_front_dbuf_create(struct xen_drm_front_info *front_info,
  129. u64 dbuf_cookie, u32 width, u32 height,
  130. u32 bpp, u64 size, u32 offset,
  131. struct page **pages)
  132. {
  133. struct xen_drm_front_evtchnl *evtchnl;
  134. struct xen_drm_front_dbuf *dbuf;
  135. struct xendispl_req *req;
  136. struct xen_front_pgdir_shbuf_cfg buf_cfg;
  137. unsigned long flags;
  138. int ret;
  139. evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req;
  140. if (unlikely(!evtchnl))
  141. return -EIO;
  142. dbuf = kzalloc_obj(*dbuf);
  143. if (!dbuf)
  144. return -ENOMEM;
  145. dbuf_add_to_list(front_info, dbuf, dbuf_cookie);
  146. memset(&buf_cfg, 0, sizeof(buf_cfg));
  147. buf_cfg.xb_dev = front_info->xb_dev;
  148. buf_cfg.num_pages = DIV_ROUND_UP(size, PAGE_SIZE);
  149. buf_cfg.pages = pages;
  150. buf_cfg.pgdir = &dbuf->shbuf;
  151. buf_cfg.be_alloc = front_info->cfg.be_alloc;
  152. ret = xen_front_pgdir_shbuf_alloc(&buf_cfg);
  153. if (ret < 0)
  154. goto fail_shbuf_alloc;
  155. mutex_lock(&evtchnl->u.req.req_io_lock);
  156. spin_lock_irqsave(&front_info->io_lock, flags);
  157. req = be_prepare_req(evtchnl, XENDISPL_OP_DBUF_CREATE);
  158. req->op.dbuf_create.gref_directory =
  159. xen_front_pgdir_shbuf_get_dir_start(&dbuf->shbuf);
  160. req->op.dbuf_create.buffer_sz = size;
  161. req->op.dbuf_create.data_ofs = offset;
  162. req->op.dbuf_create.dbuf_cookie = dbuf_cookie;
  163. req->op.dbuf_create.width = width;
  164. req->op.dbuf_create.height = height;
  165. req->op.dbuf_create.bpp = bpp;
  166. if (buf_cfg.be_alloc)
  167. req->op.dbuf_create.flags |= XENDISPL_DBUF_FLG_REQ_ALLOC;
  168. ret = be_stream_do_io(evtchnl, req);
  169. spin_unlock_irqrestore(&front_info->io_lock, flags);
  170. if (ret < 0)
  171. goto fail;
  172. ret = be_stream_wait_io(evtchnl);
  173. if (ret < 0)
  174. goto fail;
  175. ret = xen_front_pgdir_shbuf_map(&dbuf->shbuf);
  176. if (ret < 0)
  177. goto fail;
  178. mutex_unlock(&evtchnl->u.req.req_io_lock);
  179. return 0;
  180. fail:
  181. mutex_unlock(&evtchnl->u.req.req_io_lock);
  182. fail_shbuf_alloc:
  183. dbuf_free(&front_info->dbuf_list, dbuf_cookie);
  184. return ret;
  185. }
  186. static int xen_drm_front_dbuf_destroy(struct xen_drm_front_info *front_info,
  187. u64 dbuf_cookie)
  188. {
  189. struct xen_drm_front_evtchnl *evtchnl;
  190. struct xendispl_req *req;
  191. unsigned long flags;
  192. bool be_alloc;
  193. int ret;
  194. evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req;
  195. if (unlikely(!evtchnl))
  196. return -EIO;
  197. be_alloc = front_info->cfg.be_alloc;
  198. /*
  199. * For the backend allocated buffer release references now, so backend
  200. * can free the buffer.
  201. */
  202. if (be_alloc)
  203. dbuf_free(&front_info->dbuf_list, dbuf_cookie);
  204. mutex_lock(&evtchnl->u.req.req_io_lock);
  205. spin_lock_irqsave(&front_info->io_lock, flags);
  206. req = be_prepare_req(evtchnl, XENDISPL_OP_DBUF_DESTROY);
  207. req->op.dbuf_destroy.dbuf_cookie = dbuf_cookie;
  208. ret = be_stream_do_io(evtchnl, req);
  209. spin_unlock_irqrestore(&front_info->io_lock, flags);
  210. if (ret == 0)
  211. ret = be_stream_wait_io(evtchnl);
  212. /*
  213. * Do this regardless of communication status with the backend:
  214. * if we cannot remove remote resources remove what we can locally.
  215. */
  216. if (!be_alloc)
  217. dbuf_free(&front_info->dbuf_list, dbuf_cookie);
  218. mutex_unlock(&evtchnl->u.req.req_io_lock);
  219. return ret;
  220. }
  221. int xen_drm_front_fb_attach(struct xen_drm_front_info *front_info,
  222. u64 dbuf_cookie, u64 fb_cookie, u32 width,
  223. u32 height, u32 pixel_format)
  224. {
  225. struct xen_drm_front_evtchnl *evtchnl;
  226. struct xen_drm_front_dbuf *buf;
  227. struct xendispl_req *req;
  228. unsigned long flags;
  229. int ret;
  230. evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req;
  231. if (unlikely(!evtchnl))
  232. return -EIO;
  233. buf = dbuf_get(&front_info->dbuf_list, dbuf_cookie);
  234. if (!buf)
  235. return -EINVAL;
  236. buf->fb_cookie = fb_cookie;
  237. mutex_lock(&evtchnl->u.req.req_io_lock);
  238. spin_lock_irqsave(&front_info->io_lock, flags);
  239. req = be_prepare_req(evtchnl, XENDISPL_OP_FB_ATTACH);
  240. req->op.fb_attach.dbuf_cookie = dbuf_cookie;
  241. req->op.fb_attach.fb_cookie = fb_cookie;
  242. req->op.fb_attach.width = width;
  243. req->op.fb_attach.height = height;
  244. req->op.fb_attach.pixel_format = pixel_format;
  245. ret = be_stream_do_io(evtchnl, req);
  246. spin_unlock_irqrestore(&front_info->io_lock, flags);
  247. if (ret == 0)
  248. ret = be_stream_wait_io(evtchnl);
  249. mutex_unlock(&evtchnl->u.req.req_io_lock);
  250. return ret;
  251. }
  252. int xen_drm_front_fb_detach(struct xen_drm_front_info *front_info,
  253. u64 fb_cookie)
  254. {
  255. struct xen_drm_front_evtchnl *evtchnl;
  256. struct xendispl_req *req;
  257. unsigned long flags;
  258. int ret;
  259. evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req;
  260. if (unlikely(!evtchnl))
  261. return -EIO;
  262. mutex_lock(&evtchnl->u.req.req_io_lock);
  263. spin_lock_irqsave(&front_info->io_lock, flags);
  264. req = be_prepare_req(evtchnl, XENDISPL_OP_FB_DETACH);
  265. req->op.fb_detach.fb_cookie = fb_cookie;
  266. ret = be_stream_do_io(evtchnl, req);
  267. spin_unlock_irqrestore(&front_info->io_lock, flags);
  268. if (ret == 0)
  269. ret = be_stream_wait_io(evtchnl);
  270. mutex_unlock(&evtchnl->u.req.req_io_lock);
  271. return ret;
  272. }
  273. int xen_drm_front_page_flip(struct xen_drm_front_info *front_info,
  274. int conn_idx, u64 fb_cookie)
  275. {
  276. struct xen_drm_front_evtchnl *evtchnl;
  277. struct xendispl_req *req;
  278. unsigned long flags;
  279. int ret;
  280. if (unlikely(conn_idx >= front_info->num_evt_pairs))
  281. return -EINVAL;
  282. evtchnl = &front_info->evt_pairs[conn_idx].req;
  283. mutex_lock(&evtchnl->u.req.req_io_lock);
  284. spin_lock_irqsave(&front_info->io_lock, flags);
  285. req = be_prepare_req(evtchnl, XENDISPL_OP_PG_FLIP);
  286. req->op.pg_flip.fb_cookie = fb_cookie;
  287. ret = be_stream_do_io(evtchnl, req);
  288. spin_unlock_irqrestore(&front_info->io_lock, flags);
  289. if (ret == 0)
  290. ret = be_stream_wait_io(evtchnl);
  291. mutex_unlock(&evtchnl->u.req.req_io_lock);
  292. return ret;
  293. }
  294. void xen_drm_front_on_frame_done(struct xen_drm_front_info *front_info,
  295. int conn_idx, u64 fb_cookie)
  296. {
  297. struct xen_drm_front_drm_info *drm_info = front_info->drm_info;
  298. if (unlikely(conn_idx >= front_info->cfg.num_connectors))
  299. return;
  300. xen_drm_front_kms_on_frame_done(&drm_info->pipeline[conn_idx],
  301. fb_cookie);
  302. }
  303. void xen_drm_front_gem_object_free(struct drm_gem_object *obj)
  304. {
  305. struct xen_drm_front_drm_info *drm_info = obj->dev->dev_private;
  306. int idx;
  307. if (drm_dev_enter(obj->dev, &idx)) {
  308. xen_drm_front_dbuf_destroy(drm_info->front_info,
  309. xen_drm_front_dbuf_to_cookie(obj));
  310. drm_dev_exit(idx);
  311. } else {
  312. dbuf_free(&drm_info->front_info->dbuf_list,
  313. xen_drm_front_dbuf_to_cookie(obj));
  314. }
  315. xen_drm_front_gem_free_object_unlocked(obj);
  316. }
  317. static int xen_drm_drv_dumb_create(struct drm_file *filp,
  318. struct drm_device *dev,
  319. struct drm_mode_create_dumb *args)
  320. {
  321. struct xen_drm_front_drm_info *drm_info = dev->dev_private;
  322. struct drm_gem_object *obj;
  323. int ret;
  324. /*
  325. * Dumb creation is a two stage process: first we create a fully
  326. * constructed GEM object which is communicated to the backend, and
  327. * only after that we can create GEM's handle. This is done so,
  328. * because of the possible races: once you create a handle it becomes
  329. * immediately visible to user-space, so the latter can try accessing
  330. * object without pages etc.
  331. * For details also see drm_gem_handle_create
  332. */
  333. args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
  334. args->size = args->pitch * args->height;
  335. obj = xen_drm_front_gem_create(dev, args->size);
  336. if (IS_ERR(obj)) {
  337. ret = PTR_ERR(obj);
  338. goto fail;
  339. }
  340. ret = xen_drm_front_dbuf_create(drm_info->front_info,
  341. xen_drm_front_dbuf_to_cookie(obj),
  342. args->width, args->height, args->bpp,
  343. args->size, 0,
  344. xen_drm_front_gem_get_pages(obj));
  345. if (ret)
  346. goto fail_backend;
  347. /* This is the tail of GEM object creation */
  348. ret = drm_gem_handle_create(filp, obj, &args->handle);
  349. if (ret)
  350. goto fail_handle;
  351. /* Drop reference from allocate - handle holds it now */
  352. drm_gem_object_put(obj);
  353. return 0;
  354. fail_handle:
  355. xen_drm_front_dbuf_destroy(drm_info->front_info,
  356. xen_drm_front_dbuf_to_cookie(obj));
  357. fail_backend:
  358. /* drop reference from allocate */
  359. drm_gem_object_put(obj);
  360. fail:
  361. DRM_ERROR("Failed to create dumb buffer: %d\n", ret);
  362. return ret;
  363. }
  364. static void xen_drm_drv_release(struct drm_device *dev)
  365. {
  366. struct xen_drm_front_drm_info *drm_info = dev->dev_private;
  367. struct xen_drm_front_info *front_info = drm_info->front_info;
  368. xen_drm_front_kms_fini(drm_info);
  369. drm_atomic_helper_shutdown(dev);
  370. drm_mode_config_cleanup(dev);
  371. if (front_info->cfg.be_alloc)
  372. xenbus_switch_state(front_info->xb_dev,
  373. XenbusStateInitialising);
  374. kfree(drm_info);
  375. }
  376. DEFINE_DRM_GEM_FOPS(xen_drm_dev_fops);
  377. static const struct drm_driver xen_drm_driver = {
  378. .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
  379. .release = xen_drm_drv_release,
  380. .gem_prime_import_sg_table = xen_drm_front_gem_import_sg_table,
  381. .dumb_create = xen_drm_drv_dumb_create,
  382. .fops = &xen_drm_dev_fops,
  383. .name = "xendrm-du",
  384. .desc = "Xen PV DRM Display Unit",
  385. .major = 1,
  386. .minor = 0,
  387. };
  388. static int xen_drm_drv_init(struct xen_drm_front_info *front_info)
  389. {
  390. struct device *dev = &front_info->xb_dev->dev;
  391. struct xen_drm_front_drm_info *drm_info;
  392. struct drm_device *drm_dev;
  393. int ret;
  394. if (drm_firmware_drivers_only())
  395. return -ENODEV;
  396. DRM_INFO("Creating %s\n", xen_drm_driver.desc);
  397. drm_info = kzalloc_obj(*drm_info);
  398. if (!drm_info) {
  399. ret = -ENOMEM;
  400. goto fail;
  401. }
  402. drm_info->front_info = front_info;
  403. front_info->drm_info = drm_info;
  404. drm_dev = drm_dev_alloc(&xen_drm_driver, dev);
  405. if (IS_ERR(drm_dev)) {
  406. ret = PTR_ERR(drm_dev);
  407. goto fail_dev;
  408. }
  409. drm_info->drm_dev = drm_dev;
  410. drm_dev->dev_private = drm_info;
  411. ret = xen_drm_front_kms_init(drm_info);
  412. if (ret) {
  413. DRM_ERROR("Failed to initialize DRM/KMS, ret %d\n", ret);
  414. goto fail_modeset;
  415. }
  416. ret = drm_dev_register(drm_dev, 0);
  417. if (ret)
  418. goto fail_register;
  419. return 0;
  420. fail_register:
  421. drm_dev_unregister(drm_dev);
  422. fail_modeset:
  423. drm_kms_helper_poll_fini(drm_dev);
  424. drm_mode_config_cleanup(drm_dev);
  425. drm_dev_put(drm_dev);
  426. fail_dev:
  427. kfree(drm_info);
  428. front_info->drm_info = NULL;
  429. fail:
  430. return ret;
  431. }
  432. static void xen_drm_drv_fini(struct xen_drm_front_info *front_info)
  433. {
  434. struct xen_drm_front_drm_info *drm_info = front_info->drm_info;
  435. struct drm_device *dev;
  436. if (!drm_info)
  437. return;
  438. dev = drm_info->drm_dev;
  439. if (!dev)
  440. return;
  441. /* Nothing to do if device is already unplugged */
  442. if (drm_dev_is_unplugged(dev))
  443. return;
  444. drm_kms_helper_poll_fini(dev);
  445. drm_dev_unplug(dev);
  446. drm_dev_put(dev);
  447. front_info->drm_info = NULL;
  448. xen_drm_front_evtchnl_free_all(front_info);
  449. dbuf_free_all(&front_info->dbuf_list);
  450. /*
  451. * If we are not using backend allocated buffers, then tell the
  452. * backend we are ready to (re)initialize. Otherwise, wait for
  453. * drm_driver.release.
  454. */
  455. if (!front_info->cfg.be_alloc)
  456. xenbus_switch_state(front_info->xb_dev,
  457. XenbusStateInitialising);
  458. }
  459. static int displback_initwait(struct xen_drm_front_info *front_info)
  460. {
  461. struct xen_drm_front_cfg *cfg = &front_info->cfg;
  462. int ret;
  463. cfg->front_info = front_info;
  464. ret = xen_drm_front_cfg_card(front_info, cfg);
  465. if (ret < 0)
  466. return ret;
  467. DRM_INFO("Have %d connector(s)\n", cfg->num_connectors);
  468. /* Create event channels for all connectors and publish */
  469. ret = xen_drm_front_evtchnl_create_all(front_info);
  470. if (ret < 0)
  471. return ret;
  472. return xen_drm_front_evtchnl_publish_all(front_info);
  473. }
  474. static int displback_connect(struct xen_drm_front_info *front_info)
  475. {
  476. xen_drm_front_evtchnl_set_state(front_info, EVTCHNL_STATE_CONNECTED);
  477. return xen_drm_drv_init(front_info);
  478. }
  479. static void displback_disconnect(struct xen_drm_front_info *front_info)
  480. {
  481. if (!front_info->drm_info)
  482. return;
  483. /* Tell the backend to wait until we release the DRM driver. */
  484. xenbus_switch_state(front_info->xb_dev, XenbusStateReconfiguring);
  485. xen_drm_drv_fini(front_info);
  486. }
  487. static void displback_changed(struct xenbus_device *xb_dev,
  488. enum xenbus_state backend_state)
  489. {
  490. struct xen_drm_front_info *front_info = dev_get_drvdata(&xb_dev->dev);
  491. int ret;
  492. DRM_DEBUG("Backend state is %s, front is %s\n",
  493. xenbus_strstate(backend_state),
  494. xenbus_strstate(xb_dev->state));
  495. switch (backend_state) {
  496. case XenbusStateReconfiguring:
  497. case XenbusStateReconfigured:
  498. case XenbusStateInitialised:
  499. break;
  500. case XenbusStateInitialising:
  501. if (xb_dev->state == XenbusStateReconfiguring)
  502. break;
  503. /* recovering after backend unexpected closure */
  504. displback_disconnect(front_info);
  505. break;
  506. case XenbusStateInitWait:
  507. if (xb_dev->state == XenbusStateReconfiguring)
  508. break;
  509. /* recovering after backend unexpected closure */
  510. displback_disconnect(front_info);
  511. if (xb_dev->state != XenbusStateInitialising)
  512. break;
  513. ret = displback_initwait(front_info);
  514. if (ret < 0)
  515. xenbus_dev_fatal(xb_dev, ret, "initializing frontend");
  516. else
  517. xenbus_switch_state(xb_dev, XenbusStateInitialised);
  518. break;
  519. case XenbusStateConnected:
  520. if (xb_dev->state != XenbusStateInitialised)
  521. break;
  522. ret = displback_connect(front_info);
  523. if (ret < 0) {
  524. displback_disconnect(front_info);
  525. xenbus_dev_fatal(xb_dev, ret, "connecting backend");
  526. } else {
  527. xenbus_switch_state(xb_dev, XenbusStateConnected);
  528. }
  529. break;
  530. case XenbusStateClosing:
  531. /*
  532. * in this state backend starts freeing resources,
  533. * so let it go into closed state, so we can also
  534. * remove ours
  535. */
  536. break;
  537. case XenbusStateUnknown:
  538. case XenbusStateClosed:
  539. if (xb_dev->state == XenbusStateClosed)
  540. break;
  541. displback_disconnect(front_info);
  542. break;
  543. }
  544. }
  545. static int xen_drv_probe(struct xenbus_device *xb_dev,
  546. const struct xenbus_device_id *id)
  547. {
  548. struct xen_drm_front_info *front_info;
  549. struct device *dev = &xb_dev->dev;
  550. int ret;
  551. ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
  552. if (ret < 0) {
  553. DRM_ERROR("Cannot setup DMA mask, ret %d", ret);
  554. return ret;
  555. }
  556. front_info = devm_kzalloc(&xb_dev->dev,
  557. sizeof(*front_info), GFP_KERNEL);
  558. if (!front_info)
  559. return -ENOMEM;
  560. front_info->xb_dev = xb_dev;
  561. spin_lock_init(&front_info->io_lock);
  562. INIT_LIST_HEAD(&front_info->dbuf_list);
  563. dev_set_drvdata(&xb_dev->dev, front_info);
  564. return xenbus_switch_state(xb_dev, XenbusStateInitialising);
  565. }
  566. static void xen_drv_remove(struct xenbus_device *dev)
  567. {
  568. struct xen_drm_front_info *front_info = dev_get_drvdata(&dev->dev);
  569. int to = 100;
  570. xenbus_switch_state(dev, XenbusStateClosing);
  571. /*
  572. * On driver removal it is disconnected from XenBus,
  573. * so no backend state change events come via .otherend_changed
  574. * callback. This prevents us from exiting gracefully, e.g.
  575. * signaling the backend to free event channels, waiting for its
  576. * state to change to XenbusStateClosed and cleaning at our end.
  577. * Normally when front driver removed backend will finally go into
  578. * XenbusStateInitWait state.
  579. *
  580. * Workaround: read backend's state manually and wait with time-out.
  581. */
  582. while ((xenbus_read_unsigned(front_info->xb_dev->otherend, "state",
  583. XenbusStateUnknown) != XenbusStateInitWait) &&
  584. --to)
  585. msleep(10);
  586. if (!to) {
  587. unsigned int state;
  588. state = xenbus_read_unsigned(front_info->xb_dev->otherend,
  589. "state", XenbusStateUnknown);
  590. DRM_ERROR("Backend state is %s while removing driver\n",
  591. xenbus_strstate(state));
  592. }
  593. xen_drm_drv_fini(front_info);
  594. xenbus_frontend_closed(dev);
  595. }
  596. static const struct xenbus_device_id xen_driver_ids[] = {
  597. { XENDISPL_DRIVER_NAME },
  598. { "" }
  599. };
  600. static struct xenbus_driver xen_driver = {
  601. .ids = xen_driver_ids,
  602. .probe = xen_drv_probe,
  603. .remove = xen_drv_remove,
  604. .otherend_changed = displback_changed,
  605. .not_essential = true,
  606. };
  607. static int __init xen_drv_init(void)
  608. {
  609. /* At the moment we only support case with XEN_PAGE_SIZE == PAGE_SIZE */
  610. if (XEN_PAGE_SIZE != PAGE_SIZE) {
  611. DRM_ERROR(XENDISPL_DRIVER_NAME ": different kernel and Xen page sizes are not supported: XEN_PAGE_SIZE (%lu) != PAGE_SIZE (%lu)\n",
  612. XEN_PAGE_SIZE, PAGE_SIZE);
  613. return -ENODEV;
  614. }
  615. if (!xen_domain())
  616. return -ENODEV;
  617. if (!xen_has_pv_devices())
  618. return -ENODEV;
  619. DRM_INFO("Registering XEN PV " XENDISPL_DRIVER_NAME "\n");
  620. return xenbus_register_frontend(&xen_driver);
  621. }
  622. static void __exit xen_drv_fini(void)
  623. {
  624. DRM_INFO("Unregistering XEN PV " XENDISPL_DRIVER_NAME "\n");
  625. xenbus_unregister_driver(&xen_driver);
  626. }
  627. module_init(xen_drv_init);
  628. module_exit(xen_drv_fini);
  629. MODULE_DESCRIPTION("Xen para-virtualized display device frontend");
  630. MODULE_LICENSE("GPL");
  631. MODULE_ALIAS("xen:" XENDISPL_DRIVER_NAME);