device_pgid.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * CCW device PGID and path verification I/O handling.
  4. *
  5. * Copyright IBM Corp. 2002, 2009
  6. * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
  7. * Martin Schwidefsky <schwidefsky@de.ibm.com>
  8. * Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/string.h>
  12. #include <linux/bitops.h>
  13. #include <linux/types.h>
  14. #include <linux/errno.h>
  15. #include <linux/slab.h>
  16. #include <linux/io.h>
  17. #include <asm/ccwdev.h>
  18. #include <asm/cio.h>
  19. #include "cio.h"
  20. #include "cio_debug.h"
  21. #include "device.h"
  22. #include "io_sch.h"
  23. #define PGID_RETRIES 256
  24. #define PGID_TIMEOUT (10 * HZ)
  25. static void verify_start(struct ccw_device *cdev);
  26. /*
  27. * Process path verification data and report result.
  28. */
  29. static void verify_done(struct ccw_device *cdev, int rc)
  30. {
  31. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  32. struct ccw_dev_id *id = &cdev->private->dev_id;
  33. int mpath = cdev->private->flags.mpath;
  34. int pgroup = cdev->private->flags.pgroup;
  35. if (rc)
  36. goto out;
  37. /* Ensure consistent multipathing state at device and channel. */
  38. if (sch->config.mp != mpath) {
  39. sch->config.mp = mpath;
  40. rc = cio_commit_config(sch);
  41. }
  42. out:
  43. CIO_MSG_EVENT(2, "vrfy: device 0.%x.%04x: rc=%d pgroup=%d mpath=%d "
  44. "vpm=%02x\n", id->ssid, id->devno, rc, pgroup, mpath,
  45. sch->vpm);
  46. ccw_device_verify_done(cdev, rc);
  47. }
  48. /*
  49. * Create channel program to perform a NOOP.
  50. */
  51. static void nop_build_cp(struct ccw_device *cdev)
  52. {
  53. struct ccw_request *req = &cdev->private->req;
  54. struct ccw1 *cp = cdev->private->dma_area->iccws;
  55. cp->cmd_code = CCW_CMD_NOOP;
  56. cp->cda = 0;
  57. cp->count = 0;
  58. cp->flags = CCW_FLAG_SLI;
  59. req->cp = cp;
  60. }
  61. /*
  62. * Perform NOOP on a single path.
  63. */
  64. static void nop_do(struct ccw_device *cdev)
  65. {
  66. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  67. struct ccw_request *req = &cdev->private->req;
  68. req->lpm = lpm_adjust(req->lpm, sch->schib.pmcw.pam & sch->opm &
  69. ~cdev->private->path_noirq_mask);
  70. if (!req->lpm)
  71. goto out_nopath;
  72. nop_build_cp(cdev);
  73. ccw_request_start(cdev);
  74. return;
  75. out_nopath:
  76. verify_done(cdev, sch->vpm ? 0 : -EACCES);
  77. }
  78. /*
  79. * Adjust NOOP I/O status.
  80. */
  81. static enum io_status nop_filter(struct ccw_device *cdev, void *data,
  82. struct irb *irb, enum io_status status)
  83. {
  84. /* Only subchannel status might indicate a path error. */
  85. if (status == IO_STATUS_ERROR && irb->scsw.cmd.cstat == 0)
  86. return IO_DONE;
  87. return status;
  88. }
  89. /*
  90. * Process NOOP request result for a single path.
  91. */
  92. static void nop_callback(struct ccw_device *cdev, void *data, int rc)
  93. {
  94. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  95. struct ccw_request *req = &cdev->private->req;
  96. switch (rc) {
  97. case 0:
  98. sch->vpm |= req->lpm;
  99. break;
  100. case -ETIME:
  101. cdev->private->path_noirq_mask |= req->lpm;
  102. break;
  103. case -EACCES:
  104. cdev->private->path_notoper_mask |= req->lpm;
  105. break;
  106. default:
  107. goto err;
  108. }
  109. /* Continue on the next path. */
  110. req->lpm >>= 1;
  111. nop_do(cdev);
  112. return;
  113. err:
  114. verify_done(cdev, rc);
  115. }
  116. /*
  117. * Create channel program to perform SET PGID on a single path.
  118. */
  119. static void spid_build_cp(struct ccw_device *cdev, u8 fn)
  120. {
  121. struct ccw_request *req = &cdev->private->req;
  122. struct ccw1 *cp = cdev->private->dma_area->iccws;
  123. int i = pathmask_to_pos(req->lpm);
  124. struct pgid *pgid = &cdev->private->dma_area->pgid[i];
  125. pgid->inf.fc = fn;
  126. cp->cmd_code = CCW_CMD_SET_PGID;
  127. cp->cda = virt_to_dma32(pgid);
  128. cp->count = sizeof(*pgid);
  129. cp->flags = CCW_FLAG_SLI;
  130. req->cp = cp;
  131. }
  132. static void pgid_wipeout_callback(struct ccw_device *cdev, void *data, int rc)
  133. {
  134. if (rc) {
  135. /* We don't know the path groups' state. Abort. */
  136. verify_done(cdev, rc);
  137. return;
  138. }
  139. /*
  140. * Path groups have been reset. Restart path verification but
  141. * leave paths in path_noirq_mask out.
  142. */
  143. cdev->private->flags.pgid_unknown = 0;
  144. verify_start(cdev);
  145. }
  146. /*
  147. * Reset pathgroups and restart path verification, leave unusable paths out.
  148. */
  149. static void pgid_wipeout_start(struct ccw_device *cdev)
  150. {
  151. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  152. struct ccw_dev_id *id = &cdev->private->dev_id;
  153. struct ccw_request *req = &cdev->private->req;
  154. u8 fn;
  155. CIO_MSG_EVENT(2, "wipe: device 0.%x.%04x: pvm=%02x nim=%02x\n",
  156. id->ssid, id->devno, cdev->private->pgid_valid_mask,
  157. cdev->private->path_noirq_mask);
  158. /* Initialize request data. */
  159. memset(req, 0, sizeof(*req));
  160. req->timeout = PGID_TIMEOUT;
  161. req->maxretries = PGID_RETRIES;
  162. req->lpm = sch->schib.pmcw.pam;
  163. req->callback = pgid_wipeout_callback;
  164. fn = SPID_FUNC_DISBAND;
  165. if (cdev->private->flags.mpath)
  166. fn |= SPID_FUNC_MULTI_PATH;
  167. spid_build_cp(cdev, fn);
  168. ccw_request_start(cdev);
  169. }
  170. /*
  171. * Perform establish/resign SET PGID on a single path.
  172. */
  173. static void spid_do(struct ccw_device *cdev)
  174. {
  175. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  176. struct ccw_request *req = &cdev->private->req;
  177. u8 fn;
  178. /* Use next available path that is not already in correct state. */
  179. req->lpm = lpm_adjust(req->lpm, cdev->private->pgid_todo_mask);
  180. if (!req->lpm)
  181. goto out_nopath;
  182. /* Channel program setup. */
  183. if (req->lpm & sch->opm)
  184. fn = SPID_FUNC_ESTABLISH;
  185. else
  186. fn = SPID_FUNC_RESIGN;
  187. if (cdev->private->flags.mpath)
  188. fn |= SPID_FUNC_MULTI_PATH;
  189. spid_build_cp(cdev, fn);
  190. ccw_request_start(cdev);
  191. return;
  192. out_nopath:
  193. if (cdev->private->flags.pgid_unknown) {
  194. /* At least one SPID could be partially done. */
  195. pgid_wipeout_start(cdev);
  196. return;
  197. }
  198. verify_done(cdev, sch->vpm ? 0 : -EACCES);
  199. }
  200. /*
  201. * Process SET PGID request result for a single path.
  202. */
  203. static void spid_callback(struct ccw_device *cdev, void *data, int rc)
  204. {
  205. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  206. struct ccw_request *req = &cdev->private->req;
  207. switch (rc) {
  208. case 0:
  209. sch->vpm |= req->lpm & sch->opm;
  210. break;
  211. case -ETIME:
  212. cdev->private->flags.pgid_unknown = 1;
  213. cdev->private->path_noirq_mask |= req->lpm;
  214. break;
  215. case -EACCES:
  216. cdev->private->path_notoper_mask |= req->lpm;
  217. break;
  218. case -EOPNOTSUPP:
  219. if (cdev->private->flags.mpath) {
  220. /* Try without multipathing. */
  221. cdev->private->flags.mpath = 0;
  222. goto out_restart;
  223. }
  224. /* Try without pathgrouping. */
  225. cdev->private->flags.pgroup = 0;
  226. goto out_restart;
  227. default:
  228. goto err;
  229. }
  230. req->lpm >>= 1;
  231. spid_do(cdev);
  232. return;
  233. out_restart:
  234. verify_start(cdev);
  235. return;
  236. err:
  237. verify_done(cdev, rc);
  238. }
  239. static void spid_start(struct ccw_device *cdev)
  240. {
  241. struct ccw_request *req = &cdev->private->req;
  242. /* Initialize request data. */
  243. memset(req, 0, sizeof(*req));
  244. req->timeout = PGID_TIMEOUT;
  245. req->maxretries = PGID_RETRIES;
  246. req->lpm = 0x80;
  247. req->singlepath = 1;
  248. req->callback = spid_callback;
  249. spid_do(cdev);
  250. }
  251. static int pgid_is_reset(struct pgid *p)
  252. {
  253. char *c;
  254. for (c = (char *)p + 1; c < (char *)(p + 1); c++) {
  255. if (*c != 0)
  256. return 0;
  257. }
  258. return 1;
  259. }
  260. static int pgid_cmp(struct pgid *p1, struct pgid *p2)
  261. {
  262. return memcmp((char *) p1 + 1, (char *) p2 + 1,
  263. sizeof(struct pgid) - 1);
  264. }
  265. /*
  266. * Determine pathgroup state from PGID data.
  267. */
  268. static void pgid_analyze(struct ccw_device *cdev, struct pgid **p,
  269. int *mismatch, u8 *reserved, u8 *reset)
  270. {
  271. struct pgid *pgid = &cdev->private->dma_area->pgid[0];
  272. struct pgid *first = NULL;
  273. int lpm;
  274. int i;
  275. *mismatch = 0;
  276. *reserved = 0;
  277. *reset = 0;
  278. for (i = 0, lpm = 0x80; i < 8; i++, pgid++, lpm >>= 1) {
  279. if ((cdev->private->pgid_valid_mask & lpm) == 0)
  280. continue;
  281. if (pgid->inf.ps.state2 == SNID_STATE2_RESVD_ELSE)
  282. *reserved |= lpm;
  283. if (pgid_is_reset(pgid)) {
  284. *reset |= lpm;
  285. continue;
  286. }
  287. if (!first) {
  288. first = pgid;
  289. continue;
  290. }
  291. if (pgid_cmp(pgid, first) != 0)
  292. *mismatch = 1;
  293. }
  294. if (!first)
  295. first = &channel_subsystems[0]->global_pgid;
  296. *p = first;
  297. }
  298. static u8 pgid_to_donepm(struct ccw_device *cdev)
  299. {
  300. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  301. struct pgid *pgid;
  302. int i;
  303. int lpm;
  304. u8 donepm = 0;
  305. /* Set bits for paths which are already in the target state. */
  306. for (i = 0; i < 8; i++) {
  307. lpm = 0x80 >> i;
  308. if ((cdev->private->pgid_valid_mask & lpm) == 0)
  309. continue;
  310. pgid = &cdev->private->dma_area->pgid[i];
  311. if (sch->opm & lpm) {
  312. if (pgid->inf.ps.state1 != SNID_STATE1_GROUPED)
  313. continue;
  314. } else {
  315. if (pgid->inf.ps.state1 != SNID_STATE1_UNGROUPED)
  316. continue;
  317. }
  318. if (cdev->private->flags.mpath) {
  319. if (pgid->inf.ps.state3 != SNID_STATE3_MULTI_PATH)
  320. continue;
  321. } else {
  322. if (pgid->inf.ps.state3 != SNID_STATE3_SINGLE_PATH)
  323. continue;
  324. }
  325. donepm |= lpm;
  326. }
  327. return donepm;
  328. }
  329. static void pgid_fill(struct ccw_device *cdev, struct pgid *pgid)
  330. {
  331. int i;
  332. for (i = 0; i < 8; i++)
  333. memcpy(&cdev->private->dma_area->pgid[i], pgid,
  334. sizeof(struct pgid));
  335. }
  336. /*
  337. * Process SENSE PGID data and report result.
  338. */
  339. static void snid_done(struct ccw_device *cdev, int rc)
  340. {
  341. struct ccw_dev_id *id = &cdev->private->dev_id;
  342. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  343. struct pgid *pgid;
  344. int mismatch = 0;
  345. u8 reserved = 0;
  346. u8 reset = 0;
  347. u8 donepm;
  348. if (rc)
  349. goto out;
  350. pgid_analyze(cdev, &pgid, &mismatch, &reserved, &reset);
  351. if (reserved == cdev->private->pgid_valid_mask)
  352. rc = -EUSERS;
  353. else if (mismatch)
  354. rc = -EOPNOTSUPP;
  355. else {
  356. donepm = pgid_to_donepm(cdev);
  357. sch->vpm = donepm & sch->opm;
  358. cdev->private->pgid_reset_mask |= reset;
  359. cdev->private->pgid_todo_mask &=
  360. ~(donepm | cdev->private->path_noirq_mask);
  361. pgid_fill(cdev, pgid);
  362. }
  363. out:
  364. CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x "
  365. "todo=%02x mism=%d rsvd=%02x reset=%02x\n", id->ssid,
  366. id->devno, rc, cdev->private->pgid_valid_mask, sch->vpm,
  367. cdev->private->pgid_todo_mask, mismatch, reserved, reset);
  368. switch (rc) {
  369. case 0:
  370. if (cdev->private->flags.pgid_unknown) {
  371. pgid_wipeout_start(cdev);
  372. return;
  373. }
  374. /* Anything left to do? */
  375. if (cdev->private->pgid_todo_mask == 0) {
  376. verify_done(cdev, sch->vpm == 0 ? -EACCES : 0);
  377. return;
  378. }
  379. /* Perform path-grouping. */
  380. spid_start(cdev);
  381. break;
  382. case -EOPNOTSUPP:
  383. /* Path-grouping not supported. */
  384. cdev->private->flags.pgroup = 0;
  385. cdev->private->flags.mpath = 0;
  386. verify_start(cdev);
  387. break;
  388. default:
  389. verify_done(cdev, rc);
  390. }
  391. }
  392. /*
  393. * Create channel program to perform a SENSE PGID on a single path.
  394. */
  395. static void snid_build_cp(struct ccw_device *cdev)
  396. {
  397. struct ccw_request *req = &cdev->private->req;
  398. struct ccw1 *cp = cdev->private->dma_area->iccws;
  399. int i = pathmask_to_pos(req->lpm);
  400. /* Channel program setup. */
  401. cp->cmd_code = CCW_CMD_SENSE_PGID;
  402. cp->cda = virt_to_dma32(&cdev->private->dma_area->pgid[i]);
  403. cp->count = sizeof(struct pgid);
  404. cp->flags = CCW_FLAG_SLI;
  405. req->cp = cp;
  406. }
  407. /*
  408. * Perform SENSE PGID on a single path.
  409. */
  410. static void snid_do(struct ccw_device *cdev)
  411. {
  412. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  413. struct ccw_request *req = &cdev->private->req;
  414. int ret;
  415. req->lpm = lpm_adjust(req->lpm, sch->schib.pmcw.pam &
  416. ~cdev->private->path_noirq_mask);
  417. if (!req->lpm)
  418. goto out_nopath;
  419. snid_build_cp(cdev);
  420. ccw_request_start(cdev);
  421. return;
  422. out_nopath:
  423. if (cdev->private->pgid_valid_mask)
  424. ret = 0;
  425. else if (cdev->private->path_noirq_mask)
  426. ret = -ETIME;
  427. else
  428. ret = -EACCES;
  429. snid_done(cdev, ret);
  430. }
  431. /*
  432. * Process SENSE PGID request result for single path.
  433. */
  434. static void snid_callback(struct ccw_device *cdev, void *data, int rc)
  435. {
  436. struct ccw_request *req = &cdev->private->req;
  437. switch (rc) {
  438. case 0:
  439. cdev->private->pgid_valid_mask |= req->lpm;
  440. break;
  441. case -ETIME:
  442. cdev->private->flags.pgid_unknown = 1;
  443. cdev->private->path_noirq_mask |= req->lpm;
  444. break;
  445. case -EACCES:
  446. cdev->private->path_notoper_mask |= req->lpm;
  447. break;
  448. default:
  449. goto err;
  450. }
  451. /* Continue on the next path. */
  452. req->lpm >>= 1;
  453. snid_do(cdev);
  454. return;
  455. err:
  456. snid_done(cdev, rc);
  457. }
  458. /*
  459. * Perform path verification.
  460. */
  461. static void verify_start(struct ccw_device *cdev)
  462. {
  463. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  464. struct ccw_request *req = &cdev->private->req;
  465. struct ccw_dev_id *devid = &cdev->private->dev_id;
  466. sch->vpm = 0;
  467. sch->lpm = sch->schib.pmcw.pam;
  468. /* Initialize PGID data. */
  469. memset(cdev->private->dma_area->pgid, 0,
  470. sizeof(cdev->private->dma_area->pgid));
  471. cdev->private->pgid_valid_mask = 0;
  472. cdev->private->pgid_todo_mask = sch->schib.pmcw.pam;
  473. cdev->private->path_notoper_mask = 0;
  474. /* Initialize request data. */
  475. memset(req, 0, sizeof(*req));
  476. req->timeout = PGID_TIMEOUT;
  477. req->maxretries = PGID_RETRIES;
  478. req->lpm = 0x80;
  479. req->singlepath = 1;
  480. if (cdev->private->flags.pgroup) {
  481. CIO_TRACE_EVENT(4, "snid");
  482. CIO_HEX_EVENT(4, devid, sizeof(*devid));
  483. req->callback = snid_callback;
  484. snid_do(cdev);
  485. } else {
  486. CIO_TRACE_EVENT(4, "nop");
  487. CIO_HEX_EVENT(4, devid, sizeof(*devid));
  488. req->filter = nop_filter;
  489. req->callback = nop_callback;
  490. nop_do(cdev);
  491. }
  492. }
  493. /**
  494. * ccw_device_verify_start - perform path verification
  495. * @cdev: ccw device
  496. *
  497. * Perform an I/O on each available channel path to @cdev to determine which
  498. * paths are operational. The resulting path mask is stored in sch->vpm.
  499. * If device options specify pathgrouping, establish a pathgroup for the
  500. * operational paths. When finished, call ccw_device_verify_done with a
  501. * return code specifying the result.
  502. */
  503. void ccw_device_verify_start(struct ccw_device *cdev)
  504. {
  505. CIO_TRACE_EVENT(4, "vrfy");
  506. CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id));
  507. /*
  508. * Initialize pathgroup and multipath state with target values.
  509. * They may change in the course of path verification.
  510. */
  511. cdev->private->flags.pgroup = cdev->private->options.pgroup;
  512. cdev->private->flags.mpath = cdev->private->options.mpath;
  513. cdev->private->flags.doverify = 0;
  514. cdev->private->path_noirq_mask = 0;
  515. verify_start(cdev);
  516. }
  517. /*
  518. * Process disband SET PGID request result.
  519. */
  520. static void disband_callback(struct ccw_device *cdev, void *data, int rc)
  521. {
  522. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  523. struct ccw_dev_id *id = &cdev->private->dev_id;
  524. if (rc)
  525. goto out;
  526. /* Ensure consistent multipathing state at device and channel. */
  527. cdev->private->flags.mpath = 0;
  528. if (sch->config.mp) {
  529. sch->config.mp = 0;
  530. rc = cio_commit_config(sch);
  531. }
  532. out:
  533. CIO_MSG_EVENT(0, "disb: device 0.%x.%04x: rc=%d\n", id->ssid, id->devno,
  534. rc);
  535. ccw_device_disband_done(cdev, rc);
  536. }
  537. /**
  538. * ccw_device_disband_start - disband pathgroup
  539. * @cdev: ccw device
  540. *
  541. * Execute a SET PGID channel program on @cdev to disband a previously
  542. * established pathgroup. When finished, call ccw_device_disband_done with
  543. * a return code specifying the result.
  544. */
  545. void ccw_device_disband_start(struct ccw_device *cdev)
  546. {
  547. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  548. struct ccw_request *req = &cdev->private->req;
  549. u8 fn;
  550. CIO_TRACE_EVENT(4, "disb");
  551. CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id));
  552. /* Request setup. */
  553. memset(req, 0, sizeof(*req));
  554. req->timeout = PGID_TIMEOUT;
  555. req->maxretries = PGID_RETRIES;
  556. req->lpm = sch->schib.pmcw.pam & sch->opm;
  557. req->singlepath = 1;
  558. req->callback = disband_callback;
  559. fn = SPID_FUNC_DISBAND;
  560. if (cdev->private->flags.mpath)
  561. fn |= SPID_FUNC_MULTI_PATH;
  562. spid_build_cp(cdev, fn);
  563. ccw_request_start(cdev);
  564. }
  565. struct stlck_data {
  566. struct completion done;
  567. int rc;
  568. };
  569. static void stlck_build_cp(struct ccw_device *cdev, void *buf1, void *buf2)
  570. {
  571. struct ccw_request *req = &cdev->private->req;
  572. struct ccw1 *cp = cdev->private->dma_area->iccws;
  573. cp[0].cmd_code = CCW_CMD_STLCK;
  574. cp[0].cda = virt_to_dma32(buf1);
  575. cp[0].count = 32;
  576. cp[0].flags = CCW_FLAG_CC;
  577. cp[1].cmd_code = CCW_CMD_RELEASE;
  578. cp[1].cda = virt_to_dma32(buf2);
  579. cp[1].count = 32;
  580. cp[1].flags = 0;
  581. req->cp = cp;
  582. }
  583. static void stlck_callback(struct ccw_device *cdev, void *data, int rc)
  584. {
  585. struct stlck_data *sdata = data;
  586. sdata->rc = rc;
  587. complete(&sdata->done);
  588. }
  589. /**
  590. * ccw_device_stlck_start - perform unconditional release
  591. * @cdev: ccw device
  592. * @data: data pointer to be passed to ccw_device_stlck_done
  593. * @buf1: data pointer used in channel program
  594. * @buf2: data pointer used in channel program
  595. *
  596. * Execute a channel program on @cdev to release an existing PGID reservation.
  597. */
  598. static void ccw_device_stlck_start(struct ccw_device *cdev, void *data,
  599. void *buf1, void *buf2)
  600. {
  601. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  602. struct ccw_request *req = &cdev->private->req;
  603. CIO_TRACE_EVENT(4, "stlck");
  604. CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id));
  605. /* Request setup. */
  606. memset(req, 0, sizeof(*req));
  607. req->timeout = PGID_TIMEOUT;
  608. req->maxretries = PGID_RETRIES;
  609. req->lpm = sch->schib.pmcw.pam & sch->opm;
  610. req->data = data;
  611. req->callback = stlck_callback;
  612. stlck_build_cp(cdev, buf1, buf2);
  613. ccw_request_start(cdev);
  614. }
  615. /*
  616. * Perform unconditional reserve + release.
  617. */
  618. int ccw_device_stlck(struct ccw_device *cdev)
  619. {
  620. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  621. struct stlck_data data;
  622. u8 *buffer;
  623. int rc;
  624. /* Check if steal lock operation is valid for this device. */
  625. if (cdev->drv) {
  626. if (!cdev->private->options.force)
  627. return -EINVAL;
  628. }
  629. buffer = kzalloc(64, GFP_DMA | GFP_KERNEL);
  630. if (!buffer)
  631. return -ENOMEM;
  632. init_completion(&data.done);
  633. data.rc = -EIO;
  634. spin_lock_irq(&sch->lock);
  635. rc = cio_enable_subchannel(sch, (u32)virt_to_phys(sch));
  636. if (rc)
  637. goto out_unlock;
  638. /* Perform operation. */
  639. cdev->private->state = DEV_STATE_STEAL_LOCK;
  640. ccw_device_stlck_start(cdev, &data, &buffer[0], &buffer[32]);
  641. spin_unlock_irq(&sch->lock);
  642. /* Wait for operation to finish. */
  643. if (wait_for_completion_interruptible(&data.done)) {
  644. /* Got a signal. */
  645. spin_lock_irq(&sch->lock);
  646. ccw_request_cancel(cdev);
  647. spin_unlock_irq(&sch->lock);
  648. wait_for_completion(&data.done);
  649. }
  650. rc = data.rc;
  651. /* Check results. */
  652. spin_lock_irq(&sch->lock);
  653. cio_disable_subchannel(sch);
  654. cdev->private->state = DEV_STATE_BOXED;
  655. out_unlock:
  656. spin_unlock_irq(&sch->lock);
  657. kfree(buffer);
  658. return rc;
  659. }