xenbus.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. /*
  2. * PCI Backend Xenbus Setup - handles setup with frontend and xend
  3. *
  4. * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
  5. */
  6. #include <linux/module.h>
  7. #include <linux/init.h>
  8. #include <linux/list.h>
  9. #include <linux/vmalloc.h>
  10. #include <linux/workqueue.h>
  11. #include <xen/xenbus.h>
  12. #include <xen/events.h>
  13. #include <linux/workqueue.h>
  14. #include "pciback.h"
  15. #define INVALID_EVTCHN_IRQ (-1)
  16. struct workqueue_struct *pciback_wq;
  17. static struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
  18. {
  19. struct pciback_device *pdev;
  20. pdev = kzalloc(sizeof(struct pciback_device), GFP_KERNEL);
  21. if (pdev == NULL)
  22. goto out;
  23. dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
  24. pdev->xdev = xdev;
  25. dev_set_drvdata(&xdev->dev, pdev);
  26. spin_lock_init(&pdev->dev_lock);
  27. pdev->sh_info = NULL;
  28. pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
  29. pdev->be_watching = 0;
  30. INIT_WORK(&pdev->op_work, pciback_do_op);
  31. if (pciback_init_devices(pdev)) {
  32. kfree(pdev);
  33. pdev = NULL;
  34. }
  35. out:
  36. return pdev;
  37. }
  38. static void pciback_disconnect(struct pciback_device *pdev)
  39. {
  40. spin_lock(&pdev->dev_lock);
  41. /* Ensure the guest can't trigger our handler before removing devices */
  42. if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) {
  43. unbind_from_irqhandler(pdev->evtchn_irq, pdev);
  44. pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
  45. }
  46. /* If the driver domain started an op, make sure we complete it
  47. * before releasing the shared memory */
  48. flush_workqueue(pciback_wq);
  49. if (pdev->sh_info != NULL) {
  50. xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_info);
  51. pdev->sh_info = NULL;
  52. }
  53. spin_unlock(&pdev->dev_lock);
  54. }
  55. static void free_pdev(struct pciback_device *pdev)
  56. {
  57. if (pdev->be_watching)
  58. unregister_xenbus_watch(&pdev->be_watch);
  59. pciback_disconnect(pdev);
  60. pciback_release_devices(pdev);
  61. dev_set_drvdata(&pdev->xdev->dev, NULL);
  62. pdev->xdev = NULL;
  63. kfree(pdev);
  64. }
  65. static int pciback_do_attach(struct pciback_device *pdev, int gnt_ref,
  66. int remote_evtchn)
  67. {
  68. int err = 0;
  69. void *vaddr;
  70. dev_dbg(&pdev->xdev->dev,
  71. "Attaching to frontend resources - gnt_ref=%d evtchn=%d\n",
  72. gnt_ref, remote_evtchn);
  73. err = xenbus_map_ring_valloc(pdev->xdev, gnt_ref, &vaddr);
  74. if (err < 0) {
  75. xenbus_dev_fatal(pdev->xdev, err,
  76. "Error mapping other domain page in ours.");
  77. goto out;
  78. }
  79. pdev->sh_info = vaddr;
  80. err = bind_interdomain_evtchn_to_irqhandler(
  81. pdev->xdev->otherend_id, remote_evtchn, pciback_handle_event,
  82. 0, "pciback", pdev);
  83. if (err < 0) {
  84. xenbus_dev_fatal(pdev->xdev, err,
  85. "Error binding event channel to IRQ");
  86. goto out;
  87. }
  88. pdev->evtchn_irq = err;
  89. err = 0;
  90. dev_dbg(&pdev->xdev->dev, "Attached!\n");
  91. out:
  92. return err;
  93. }
  94. static int pciback_attach(struct pciback_device *pdev)
  95. {
  96. int err = 0;
  97. int gnt_ref, remote_evtchn;
  98. char *magic = NULL;
  99. spin_lock(&pdev->dev_lock);
  100. /* Make sure we only do this setup once */
  101. if (xenbus_read_driver_state(pdev->xdev->nodename) !=
  102. XenbusStateInitialised)
  103. goto out;
  104. /* Wait for frontend to state that it has published the configuration */
  105. if (xenbus_read_driver_state(pdev->xdev->otherend) !=
  106. XenbusStateInitialised)
  107. goto out;
  108. dev_dbg(&pdev->xdev->dev, "Reading frontend config\n");
  109. err = xenbus_gather(XBT_NIL, pdev->xdev->otherend,
  110. "pci-op-ref", "%u", &gnt_ref,
  111. "event-channel", "%u", &remote_evtchn,
  112. "magic", NULL, &magic, NULL);
  113. if (err) {
  114. /* If configuration didn't get read correctly, wait longer */
  115. xenbus_dev_fatal(pdev->xdev, err,
  116. "Error reading configuration from frontend");
  117. goto out;
  118. }
  119. if (magic == NULL || strcmp(magic, XEN_PCI_MAGIC) != 0) {
  120. xenbus_dev_fatal(pdev->xdev, -EFAULT,
  121. "version mismatch (%s/%s) with pcifront - "
  122. "halting pciback",
  123. magic, XEN_PCI_MAGIC);
  124. goto out;
  125. }
  126. err = pciback_do_attach(pdev, gnt_ref, remote_evtchn);
  127. if (err)
  128. goto out;
  129. dev_dbg(&pdev->xdev->dev, "Connecting...\n");
  130. err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
  131. if (err)
  132. xenbus_dev_fatal(pdev->xdev, err,
  133. "Error switching to connected state!");
  134. dev_dbg(&pdev->xdev->dev, "Connected? %d\n", err);
  135. out:
  136. spin_unlock(&pdev->dev_lock);
  137. kfree(magic);
  138. return err;
  139. }
  140. static int pciback_publish_pci_dev(struct pciback_device *pdev,
  141. unsigned int domain, unsigned int bus,
  142. unsigned int devfn, unsigned int devid)
  143. {
  144. int err;
  145. int len;
  146. char str[64];
  147. len = snprintf(str, sizeof(str), "vdev-%d", devid);
  148. if (unlikely(len >= (sizeof(str) - 1))) {
  149. err = -ENOMEM;
  150. goto out;
  151. }
  152. err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
  153. "%04x:%02x:%02x.%02x", domain, bus,
  154. PCI_SLOT(devfn), PCI_FUNC(devfn));
  155. out:
  156. return err;
  157. }
  158. static int pciback_export_device(struct pciback_device *pdev,
  159. int domain, int bus, int slot, int func,
  160. int devid)
  161. {
  162. struct pci_dev *dev;
  163. int err = 0;
  164. dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n",
  165. domain, bus, slot, func);
  166. dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func);
  167. if (!dev) {
  168. err = -EINVAL;
  169. xenbus_dev_fatal(pdev->xdev, err,
  170. "Couldn't locate PCI device "
  171. "(%04x:%02x:%02x.%01x)! "
  172. "perhaps already in-use?",
  173. domain, bus, slot, func);
  174. goto out;
  175. }
  176. err = pciback_add_pci_dev(pdev, dev, devid, pciback_publish_pci_dev);
  177. if (err)
  178. goto out;
  179. /* TODO: It'd be nice to export a bridge and have all of its children
  180. * get exported with it. This may be best done in xend (which will
  181. * have to calculate resource usage anyway) but we probably want to
  182. * put something in here to ensure that if a bridge gets given to a
  183. * driver domain, that all devices under that bridge are not given
  184. * to other driver domains (as he who controls the bridge can disable
  185. * it and stop the other devices from working).
  186. */
  187. out:
  188. return err;
  189. }
  190. static int pciback_remove_device(struct pciback_device *pdev,
  191. int domain, int bus, int slot, int func)
  192. {
  193. int err = 0;
  194. struct pci_dev *dev;
  195. dev_dbg(&pdev->xdev->dev, "removing dom %x bus %x slot %x func %x\n",
  196. domain, bus, slot, func);
  197. dev = pciback_get_pci_dev(pdev, domain, bus, PCI_DEVFN(slot, func));
  198. if (!dev) {
  199. err = -EINVAL;
  200. dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device "
  201. "(%04x:%02x:%02x.%01x)! not owned by this domain\n",
  202. domain, bus, slot, func);
  203. goto out;
  204. }
  205. pciback_release_pci_dev(pdev, dev);
  206. out:
  207. return err;
  208. }
  209. static int pciback_publish_pci_root(struct pciback_device *pdev,
  210. unsigned int domain, unsigned int bus)
  211. {
  212. unsigned int d, b;
  213. int i, root_num, len, err;
  214. char str[64];
  215. dev_dbg(&pdev->xdev->dev, "Publishing pci roots\n");
  216. err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
  217. "root_num", "%d", &root_num);
  218. if (err == 0 || err == -ENOENT)
  219. root_num = 0;
  220. else if (err < 0)
  221. goto out;
  222. /* Verify that we haven't already published this pci root */
  223. for (i = 0; i < root_num; i++) {
  224. len = snprintf(str, sizeof(str), "root-%d", i);
  225. if (unlikely(len >= (sizeof(str) - 1))) {
  226. err = -ENOMEM;
  227. goto out;
  228. }
  229. err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
  230. str, "%x:%x", &d, &b);
  231. if (err < 0)
  232. goto out;
  233. if (err != 2) {
  234. err = -EINVAL;
  235. goto out;
  236. }
  237. if (d == domain && b == bus) {
  238. err = 0;
  239. goto out;
  240. }
  241. }
  242. len = snprintf(str, sizeof(str), "root-%d", root_num);
  243. if (unlikely(len >= (sizeof(str) - 1))) {
  244. err = -ENOMEM;
  245. goto out;
  246. }
  247. dev_dbg(&pdev->xdev->dev, "writing root %d at %04x:%02x\n",
  248. root_num, domain, bus);
  249. err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
  250. "%04x:%02x", domain, bus);
  251. if (err)
  252. goto out;
  253. err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
  254. "root_num", "%d", (root_num + 1));
  255. out:
  256. return err;
  257. }
  258. static int pciback_reconfigure(struct pciback_device *pdev)
  259. {
  260. int err = 0;
  261. int num_devs;
  262. int domain, bus, slot, func;
  263. int substate;
  264. int i, len;
  265. char state_str[64];
  266. char dev_str[64];
  267. spin_lock(&pdev->dev_lock);
  268. dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
  269. /* Make sure we only reconfigure once */
  270. if (xenbus_read_driver_state(pdev->xdev->nodename) !=
  271. XenbusStateReconfiguring)
  272. goto out;
  273. err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
  274. &num_devs);
  275. if (err != 1) {
  276. if (err >= 0)
  277. err = -EINVAL;
  278. xenbus_dev_fatal(pdev->xdev, err,
  279. "Error reading number of devices");
  280. goto out;
  281. }
  282. for (i = 0; i < num_devs; i++) {
  283. len = snprintf(state_str, sizeof(state_str), "state-%d", i);
  284. if (unlikely(len >= (sizeof(state_str) - 1))) {
  285. err = -ENOMEM;
  286. xenbus_dev_fatal(pdev->xdev, err,
  287. "String overflow while reading "
  288. "configuration");
  289. goto out;
  290. }
  291. err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, state_str,
  292. "%d", &substate);
  293. if (err != 1)
  294. substate = XenbusStateUnknown;
  295. switch (substate) {
  296. case XenbusStateInitialising:
  297. dev_dbg(&pdev->xdev->dev, "Attaching dev-%d ...\n", i);
  298. len = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
  299. if (unlikely(len >= (sizeof(dev_str) - 1))) {
  300. err = -ENOMEM;
  301. xenbus_dev_fatal(pdev->xdev, err,
  302. "String overflow while "
  303. "reading configuration");
  304. goto out;
  305. }
  306. err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
  307. dev_str, "%x:%x:%x.%x",
  308. &domain, &bus, &slot, &func);
  309. if (err < 0) {
  310. xenbus_dev_fatal(pdev->xdev, err,
  311. "Error reading device "
  312. "configuration");
  313. goto out;
  314. }
  315. if (err != 4) {
  316. err = -EINVAL;
  317. xenbus_dev_fatal(pdev->xdev, err,
  318. "Error parsing pci device "
  319. "configuration");
  320. goto out;
  321. }
  322. err = pciback_export_device(pdev, domain, bus, slot,
  323. func, i);
  324. if (err)
  325. goto out;
  326. /* Publish pci roots. */
  327. err = pciback_publish_pci_roots(pdev,
  328. pciback_publish_pci_root);
  329. if (err) {
  330. xenbus_dev_fatal(pdev->xdev, err,
  331. "Error while publish PCI root"
  332. "buses for frontend");
  333. goto out;
  334. }
  335. err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
  336. state_str, "%d",
  337. XenbusStateInitialised);
  338. if (err) {
  339. xenbus_dev_fatal(pdev->xdev, err,
  340. "Error switching substate of "
  341. "dev-%d\n", i);
  342. goto out;
  343. }
  344. break;
  345. case XenbusStateClosing:
  346. dev_dbg(&pdev->xdev->dev, "Detaching dev-%d ...\n", i);
  347. len = snprintf(dev_str, sizeof(dev_str), "vdev-%d", i);
  348. if (unlikely(len >= (sizeof(dev_str) - 1))) {
  349. err = -ENOMEM;
  350. xenbus_dev_fatal(pdev->xdev, err,
  351. "String overflow while "
  352. "reading configuration");
  353. goto out;
  354. }
  355. err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
  356. dev_str, "%x:%x:%x.%x",
  357. &domain, &bus, &slot, &func);
  358. if (err < 0) {
  359. xenbus_dev_fatal(pdev->xdev, err,
  360. "Error reading device "
  361. "configuration");
  362. goto out;
  363. }
  364. if (err != 4) {
  365. err = -EINVAL;
  366. xenbus_dev_fatal(pdev->xdev, err,
  367. "Error parsing pci device "
  368. "configuration");
  369. goto out;
  370. }
  371. err = pciback_remove_device(pdev, domain, bus, slot,
  372. func);
  373. if (err)
  374. goto out;
  375. /* TODO: If at some point we implement support for pci
  376. * root hot-remove on pcifront side, we'll need to
  377. * remove unnecessary xenstore nodes of pci roots here.
  378. */
  379. break;
  380. default:
  381. break;
  382. }
  383. }
  384. err = xenbus_switch_state(pdev->xdev, XenbusStateReconfigured);
  385. if (err) {
  386. xenbus_dev_fatal(pdev->xdev, err,
  387. "Error switching to reconfigured state!");
  388. goto out;
  389. }
  390. out:
  391. spin_unlock(&pdev->dev_lock);
  392. return 0;
  393. }
  394. static void pciback_frontend_changed(struct xenbus_device *xdev,
  395. enum xenbus_state fe_state)
  396. {
  397. struct pciback_device *pdev = dev_get_drvdata(&xdev->dev);
  398. dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state);
  399. switch (fe_state) {
  400. case XenbusStateInitialised:
  401. pciback_attach(pdev);
  402. break;
  403. case XenbusStateReconfiguring:
  404. pciback_reconfigure(pdev);
  405. break;
  406. case XenbusStateConnected:
  407. /* pcifront switched its state from reconfiguring to connected.
  408. * Then switch to connected state.
  409. */
  410. xenbus_switch_state(xdev, XenbusStateConnected);
  411. break;
  412. case XenbusStateClosing:
  413. pciback_disconnect(pdev);
  414. xenbus_switch_state(xdev, XenbusStateClosing);
  415. break;
  416. case XenbusStateClosed:
  417. pciback_disconnect(pdev);
  418. xenbus_switch_state(xdev, XenbusStateClosed);
  419. if (xenbus_dev_is_online(xdev))
  420. break;
  421. /* fall through if not online */
  422. case XenbusStateUnknown:
  423. dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
  424. device_unregister(&xdev->dev);
  425. break;
  426. default:
  427. break;
  428. }
  429. }
  430. static int pciback_setup_backend(struct pciback_device *pdev)
  431. {
  432. /* Get configuration from xend (if available now) */
  433. int domain, bus, slot, func;
  434. int err = 0;
  435. int i, num_devs;
  436. char dev_str[64];
  437. char state_str[64];
  438. spin_lock(&pdev->dev_lock);
  439. /* It's possible we could get the call to setup twice, so make sure
  440. * we're not already connected.
  441. */
  442. if (xenbus_read_driver_state(pdev->xdev->nodename) !=
  443. XenbusStateInitWait)
  444. goto out;
  445. dev_dbg(&pdev->xdev->dev, "getting be setup\n");
  446. err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
  447. &num_devs);
  448. if (err != 1) {
  449. if (err >= 0)
  450. err = -EINVAL;
  451. xenbus_dev_fatal(pdev->xdev, err,
  452. "Error reading number of devices");
  453. goto out;
  454. }
  455. for (i = 0; i < num_devs; i++) {
  456. int l = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
  457. if (unlikely(l >= (sizeof(dev_str) - 1))) {
  458. err = -ENOMEM;
  459. xenbus_dev_fatal(pdev->xdev, err,
  460. "String overflow while reading "
  461. "configuration");
  462. goto out;
  463. }
  464. err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, dev_str,
  465. "%x:%x:%x.%x", &domain, &bus, &slot, &func);
  466. if (err < 0) {
  467. xenbus_dev_fatal(pdev->xdev, err,
  468. "Error reading device configuration");
  469. goto out;
  470. }
  471. if (err != 4) {
  472. err = -EINVAL;
  473. xenbus_dev_fatal(pdev->xdev, err,
  474. "Error parsing pci device "
  475. "configuration");
  476. goto out;
  477. }
  478. err = pciback_export_device(pdev, domain, bus, slot, func, i);
  479. if (err)
  480. goto out;
  481. /* Switch substate of this device. */
  482. l = snprintf(state_str, sizeof(state_str), "state-%d", i);
  483. if (unlikely(l >= (sizeof(state_str) - 1))) {
  484. err = -ENOMEM;
  485. xenbus_dev_fatal(pdev->xdev, err,
  486. "String overflow while reading "
  487. "configuration");
  488. goto out;
  489. }
  490. err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, state_str,
  491. "%d", XenbusStateInitialised);
  492. if (err) {
  493. xenbus_dev_fatal(pdev->xdev, err, "Error switching "
  494. "substate of dev-%d\n", i);
  495. goto out;
  496. }
  497. }
  498. err = pciback_publish_pci_roots(pdev, pciback_publish_pci_root);
  499. if (err) {
  500. xenbus_dev_fatal(pdev->xdev, err,
  501. "Error while publish PCI root buses "
  502. "for frontend");
  503. goto out;
  504. }
  505. err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
  506. if (err)
  507. xenbus_dev_fatal(pdev->xdev, err,
  508. "Error switching to initialised state!");
  509. out:
  510. spin_unlock(&pdev->dev_lock);
  511. if (!err)
  512. /* see if pcifront is already configured (if not, we'll wait) */
  513. pciback_attach(pdev);
  514. return err;
  515. }
  516. static void pciback_be_watch(struct xenbus_watch *watch,
  517. const char **vec, unsigned int len)
  518. {
  519. struct pciback_device *pdev =
  520. container_of(watch, struct pciback_device, be_watch);
  521. switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
  522. case XenbusStateInitWait:
  523. pciback_setup_backend(pdev);
  524. break;
  525. default:
  526. break;
  527. }
  528. }
  529. static int pciback_xenbus_probe(struct xenbus_device *dev,
  530. const struct xenbus_device_id *id)
  531. {
  532. int err = 0;
  533. struct pciback_device *pdev = alloc_pdev(dev);
  534. if (pdev == NULL) {
  535. err = -ENOMEM;
  536. xenbus_dev_fatal(dev, err,
  537. "Error allocating pciback_device struct");
  538. goto out;
  539. }
  540. /* wait for xend to configure us */
  541. err = xenbus_switch_state(dev, XenbusStateInitWait);
  542. if (err)
  543. goto out;
  544. /* watch the backend node for backend configuration information */
  545. err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
  546. pciback_be_watch);
  547. if (err)
  548. goto out;
  549. pdev->be_watching = 1;
  550. /* We need to force a call to our callback here in case
  551. * xend already configured us!
  552. */
  553. pciback_be_watch(&pdev->be_watch, NULL, 0);
  554. out:
  555. return err;
  556. }
  557. static int pciback_xenbus_remove(struct xenbus_device *dev)
  558. {
  559. struct pciback_device *pdev = dev_get_drvdata(&dev->dev);
  560. if (pdev != NULL)
  561. free_pdev(pdev);
  562. return 0;
  563. }
  564. static const struct xenbus_device_id xenpci_ids[] = {
  565. {"pci"},
  566. {""},
  567. };
  568. static struct xenbus_driver xenbus_pciback_driver = {
  569. .name = "pciback",
  570. .owner = THIS_MODULE,
  571. .ids = xenpci_ids,
  572. .probe = pciback_xenbus_probe,
  573. .remove = pciback_xenbus_remove,
  574. .otherend_changed = pciback_frontend_changed,
  575. };
  576. int __init pciback_xenbus_register(void)
  577. {
  578. pciback_wq = create_workqueue("pciback_workqueue");
  579. if (!pciback_wq) {
  580. printk(KERN_ERR "pciback_xenbus_register: create"
  581. "pciback_workqueue failed\n");
  582. return -EFAULT;
  583. }
  584. return xenbus_register_backend(&xenbus_pciback_driver);
  585. }
  586. void __exit pciback_xenbus_unregister(void)
  587. {
  588. destroy_workqueue(pciback_wq);
  589. xenbus_unregister_driver(&xenbus_pciback_driver);
  590. }