device_ops.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /*
  2. * Copyright IBM Corp. 2002, 2009
  3. *
  4. * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  5. * Cornelia Huck (cornelia.huck@de.ibm.com)
  6. */
  7. #include <linux/module.h>
  8. #include <linux/init.h>
  9. #include <linux/errno.h>
  10. #include <linux/slab.h>
  11. #include <linux/list.h>
  12. #include <linux/device.h>
  13. #include <linux/delay.h>
  14. #include <asm/ccwdev.h>
  15. #include <asm/idals.h>
  16. #include <asm/chpid.h>
  17. #include <asm/fcx.h>
  18. #include "cio.h"
  19. #include "cio_debug.h"
  20. #include "css.h"
  21. #include "chsc.h"
  22. #include "device.h"
  23. #include "chp.h"
  24. /**
  25. * ccw_device_set_options_mask() - set some options and unset the rest
  26. * @cdev: device for which the options are to be set
  27. * @flags: options to be set
  28. *
  29. * All flags specified in @flags are set, all flags not specified in @flags
  30. * are cleared.
  31. * Returns:
  32. * %0 on success, -%EINVAL on an invalid flag combination.
  33. */
  34. int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
  35. {
  36. /*
  37. * The flag usage is mutal exclusive ...
  38. */
  39. if ((flags & CCWDEV_EARLY_NOTIFICATION) &&
  40. (flags & CCWDEV_REPORT_ALL))
  41. return -EINVAL;
  42. cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
  43. cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0;
  44. cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0;
  45. cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0;
  46. return 0;
  47. }
  48. /**
  49. * ccw_device_set_options() - set some options
  50. * @cdev: device for which the options are to be set
  51. * @flags: options to be set
  52. *
  53. * All flags specified in @flags are set, the remainder is left untouched.
  54. * Returns:
  55. * %0 on success, -%EINVAL if an invalid flag combination would ensue.
  56. */
  57. int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
  58. {
  59. /*
  60. * The flag usage is mutal exclusive ...
  61. */
  62. if (((flags & CCWDEV_EARLY_NOTIFICATION) &&
  63. (flags & CCWDEV_REPORT_ALL)) ||
  64. ((flags & CCWDEV_EARLY_NOTIFICATION) &&
  65. cdev->private->options.repall) ||
  66. ((flags & CCWDEV_REPORT_ALL) &&
  67. cdev->private->options.fast))
  68. return -EINVAL;
  69. cdev->private->options.fast |= (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
  70. cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0;
  71. cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0;
  72. cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0;
  73. return 0;
  74. }
  75. /**
  76. * ccw_device_clear_options() - clear some options
  77. * @cdev: device for which the options are to be cleared
  78. * @flags: options to be cleared
  79. *
  80. * All flags specified in @flags are cleared, the remainder is left untouched.
  81. */
  82. void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
  83. {
  84. cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0;
  85. cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0;
  86. cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0;
  87. cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;
  88. }
  89. /**
  90. * ccw_device_clear() - terminate I/O request processing
  91. * @cdev: target ccw device
  92. * @intparm: interruption parameter; value is only used if no I/O is
  93. * outstanding, otherwise the intparm associated with the I/O request
  94. * is returned
  95. *
  96. * ccw_device_clear() calls csch on @cdev's subchannel.
  97. * Returns:
  98. * %0 on success,
  99. * -%ENODEV on device not operational,
  100. * -%EINVAL on invalid device state.
  101. * Context:
  102. * Interrupts disabled, ccw device lock held
  103. */
  104. int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
  105. {
  106. struct subchannel *sch;
  107. int ret;
  108. if (!cdev || !cdev->dev.parent)
  109. return -ENODEV;
  110. sch = to_subchannel(cdev->dev.parent);
  111. if (!sch->schib.pmcw.ena)
  112. return -EINVAL;
  113. if (cdev->private->state == DEV_STATE_NOT_OPER)
  114. return -ENODEV;
  115. if (cdev->private->state != DEV_STATE_ONLINE &&
  116. cdev->private->state != DEV_STATE_W4SENSE)
  117. return -EINVAL;
  118. ret = cio_clear(sch);
  119. if (ret == 0)
  120. cdev->private->intparm = intparm;
  121. return ret;
  122. }
  123. /**
  124. * ccw_device_start_key() - start a s390 channel program with key
  125. * @cdev: target ccw device
  126. * @cpa: logical start address of channel program
  127. * @intparm: user specific interruption parameter; will be presented back to
  128. * @cdev's interrupt handler. Allows a device driver to associate
  129. * the interrupt with a particular I/O request.
  130. * @lpm: defines the channel path to be used for a specific I/O request. A
  131. * value of 0 will make cio use the opm.
  132. * @key: storage key to be used for the I/O
  133. * @flags: additional flags; defines the action to be performed for I/O
  134. * processing.
  135. *
  136. * Start a S/390 channel program. When the interrupt arrives, the
  137. * IRQ handler is called, either immediately, delayed (dev-end missing,
  138. * or sense required) or never (no IRQ handler registered).
  139. * Returns:
  140. * %0, if the operation was successful;
  141. * -%EBUSY, if the device is busy, or status pending;
  142. * -%EACCES, if no path specified in @lpm is operational;
  143. * -%ENODEV, if the device is not operational.
  144. * Context:
  145. * Interrupts disabled, ccw device lock held
  146. */
  147. int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
  148. unsigned long intparm, __u8 lpm, __u8 key,
  149. unsigned long flags)
  150. {
  151. struct subchannel *sch;
  152. int ret;
  153. if (!cdev || !cdev->dev.parent)
  154. return -ENODEV;
  155. sch = to_subchannel(cdev->dev.parent);
  156. if (!sch->schib.pmcw.ena)
  157. return -EINVAL;
  158. if (cdev->private->state == DEV_STATE_NOT_OPER)
  159. return -ENODEV;
  160. if (cdev->private->state == DEV_STATE_VERIFY ||
  161. cdev->private->state == DEV_STATE_CLEAR_VERIFY) {
  162. /* Remember to fake irb when finished. */
  163. if (!cdev->private->flags.fake_irb) {
  164. cdev->private->flags.fake_irb = 1;
  165. cdev->private->intparm = intparm;
  166. return 0;
  167. } else
  168. /* There's already a fake I/O around. */
  169. return -EBUSY;
  170. }
  171. if (cdev->private->state != DEV_STATE_ONLINE ||
  172. ((sch->schib.scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) &&
  173. !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)) ||
  174. cdev->private->flags.doverify)
  175. return -EBUSY;
  176. ret = cio_set_options (sch, flags);
  177. if (ret)
  178. return ret;
  179. /* Adjust requested path mask to excluded varied off paths. */
  180. if (lpm) {
  181. lpm &= sch->opm;
  182. if (lpm == 0)
  183. return -EACCES;
  184. }
  185. ret = cio_start_key (sch, cpa, lpm, key);
  186. switch (ret) {
  187. case 0:
  188. cdev->private->intparm = intparm;
  189. break;
  190. case -EACCES:
  191. case -ENODEV:
  192. dev_fsm_event(cdev, DEV_EVENT_VERIFY);
  193. break;
  194. }
  195. return ret;
  196. }
  197. /**
  198. * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key
  199. * @cdev: target ccw device
  200. * @cpa: logical start address of channel program
  201. * @intparm: user specific interruption parameter; will be presented back to
  202. * @cdev's interrupt handler. Allows a device driver to associate
  203. * the interrupt with a particular I/O request.
  204. * @lpm: defines the channel path to be used for a specific I/O request. A
  205. * value of 0 will make cio use the opm.
  206. * @key: storage key to be used for the I/O
  207. * @flags: additional flags; defines the action to be performed for I/O
  208. * processing.
  209. * @expires: timeout value in jiffies
  210. *
  211. * Start a S/390 channel program. When the interrupt arrives, the
  212. * IRQ handler is called, either immediately, delayed (dev-end missing,
  213. * or sense required) or never (no IRQ handler registered).
  214. * This function notifies the device driver if the channel program has not
  215. * completed during the time specified by @expires. If a timeout occurs, the
  216. * channel program is terminated via xsch, hsch or csch, and the device's
  217. * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
  218. * Returns:
  219. * %0, if the operation was successful;
  220. * -%EBUSY, if the device is busy, or status pending;
  221. * -%EACCES, if no path specified in @lpm is operational;
  222. * -%ENODEV, if the device is not operational.
  223. * Context:
  224. * Interrupts disabled, ccw device lock held
  225. */
  226. int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
  227. unsigned long intparm, __u8 lpm, __u8 key,
  228. unsigned long flags, int expires)
  229. {
  230. int ret;
  231. if (!cdev)
  232. return -ENODEV;
  233. ccw_device_set_timeout(cdev, expires);
  234. ret = ccw_device_start_key(cdev, cpa, intparm, lpm, key, flags);
  235. if (ret != 0)
  236. ccw_device_set_timeout(cdev, 0);
  237. return ret;
  238. }
  239. /**
  240. * ccw_device_start() - start a s390 channel program
  241. * @cdev: target ccw device
  242. * @cpa: logical start address of channel program
  243. * @intparm: user specific interruption parameter; will be presented back to
  244. * @cdev's interrupt handler. Allows a device driver to associate
  245. * the interrupt with a particular I/O request.
  246. * @lpm: defines the channel path to be used for a specific I/O request. A
  247. * value of 0 will make cio use the opm.
  248. * @flags: additional flags; defines the action to be performed for I/O
  249. * processing.
  250. *
  251. * Start a S/390 channel program. When the interrupt arrives, the
  252. * IRQ handler is called, either immediately, delayed (dev-end missing,
  253. * or sense required) or never (no IRQ handler registered).
  254. * Returns:
  255. * %0, if the operation was successful;
  256. * -%EBUSY, if the device is busy, or status pending;
  257. * -%EACCES, if no path specified in @lpm is operational;
  258. * -%ENODEV, if the device is not operational.
  259. * Context:
  260. * Interrupts disabled, ccw device lock held
  261. */
  262. int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa,
  263. unsigned long intparm, __u8 lpm, unsigned long flags)
  264. {
  265. return ccw_device_start_key(cdev, cpa, intparm, lpm,
  266. PAGE_DEFAULT_KEY, flags);
  267. }
  268. /**
  269. * ccw_device_start_timeout() - start a s390 channel program with timeout
  270. * @cdev: target ccw device
  271. * @cpa: logical start address of channel program
  272. * @intparm: user specific interruption parameter; will be presented back to
  273. * @cdev's interrupt handler. Allows a device driver to associate
  274. * the interrupt with a particular I/O request.
  275. * @lpm: defines the channel path to be used for a specific I/O request. A
  276. * value of 0 will make cio use the opm.
  277. * @flags: additional flags; defines the action to be performed for I/O
  278. * processing.
  279. * @expires: timeout value in jiffies
  280. *
  281. * Start a S/390 channel program. When the interrupt arrives, the
  282. * IRQ handler is called, either immediately, delayed (dev-end missing,
  283. * or sense required) or never (no IRQ handler registered).
  284. * This function notifies the device driver if the channel program has not
  285. * completed during the time specified by @expires. If a timeout occurs, the
  286. * channel program is terminated via xsch, hsch or csch, and the device's
  287. * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
  288. * Returns:
  289. * %0, if the operation was successful;
  290. * -%EBUSY, if the device is busy, or status pending;
  291. * -%EACCES, if no path specified in @lpm is operational;
  292. * -%ENODEV, if the device is not operational.
  293. * Context:
  294. * Interrupts disabled, ccw device lock held
  295. */
  296. int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa,
  297. unsigned long intparm, __u8 lpm,
  298. unsigned long flags, int expires)
  299. {
  300. return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm,
  301. PAGE_DEFAULT_KEY, flags,
  302. expires);
  303. }
  304. /**
  305. * ccw_device_halt() - halt I/O request processing
  306. * @cdev: target ccw device
  307. * @intparm: interruption parameter; value is only used if no I/O is
  308. * outstanding, otherwise the intparm associated with the I/O request
  309. * is returned
  310. *
  311. * ccw_device_halt() calls hsch on @cdev's subchannel.
  312. * Returns:
  313. * %0 on success,
  314. * -%ENODEV on device not operational,
  315. * -%EINVAL on invalid device state,
  316. * -%EBUSY on device busy or interrupt pending.
  317. * Context:
  318. * Interrupts disabled, ccw device lock held
  319. */
  320. int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
  321. {
  322. struct subchannel *sch;
  323. int ret;
  324. if (!cdev || !cdev->dev.parent)
  325. return -ENODEV;
  326. sch = to_subchannel(cdev->dev.parent);
  327. if (!sch->schib.pmcw.ena)
  328. return -EINVAL;
  329. if (cdev->private->state == DEV_STATE_NOT_OPER)
  330. return -ENODEV;
  331. if (cdev->private->state != DEV_STATE_ONLINE &&
  332. cdev->private->state != DEV_STATE_W4SENSE)
  333. return -EINVAL;
  334. ret = cio_halt(sch);
  335. if (ret == 0)
  336. cdev->private->intparm = intparm;
  337. return ret;
  338. }
  339. /**
  340. * ccw_device_resume() - resume channel program execution
  341. * @cdev: target ccw device
  342. *
  343. * ccw_device_resume() calls rsch on @cdev's subchannel.
  344. * Returns:
  345. * %0 on success,
  346. * -%ENODEV on device not operational,
  347. * -%EINVAL on invalid device state,
  348. * -%EBUSY on device busy or interrupt pending.
  349. * Context:
  350. * Interrupts disabled, ccw device lock held
  351. */
  352. int ccw_device_resume(struct ccw_device *cdev)
  353. {
  354. struct subchannel *sch;
  355. if (!cdev || !cdev->dev.parent)
  356. return -ENODEV;
  357. sch = to_subchannel(cdev->dev.parent);
  358. if (!sch->schib.pmcw.ena)
  359. return -EINVAL;
  360. if (cdev->private->state == DEV_STATE_NOT_OPER)
  361. return -ENODEV;
  362. if (cdev->private->state != DEV_STATE_ONLINE ||
  363. !(sch->schib.scsw.cmd.actl & SCSW_ACTL_SUSPENDED))
  364. return -EINVAL;
  365. return cio_resume(sch);
  366. }
  367. /*
  368. * Pass interrupt to device driver.
  369. */
  370. int
  371. ccw_device_call_handler(struct ccw_device *cdev)
  372. {
  373. struct subchannel *sch;
  374. unsigned int stctl;
  375. int ending_status;
  376. sch = to_subchannel(cdev->dev.parent);
  377. /*
  378. * we allow for the device action handler if .
  379. * - we received ending status
  380. * - the action handler requested to see all interrupts
  381. * - we received an intermediate status
  382. * - fast notification was requested (primary status)
  383. * - unsolicited interrupts
  384. */
  385. stctl = scsw_stctl(&cdev->private->irb.scsw);
  386. ending_status = (stctl & SCSW_STCTL_SEC_STATUS) ||
  387. (stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) ||
  388. (stctl == SCSW_STCTL_STATUS_PEND);
  389. if (!ending_status &&
  390. !cdev->private->options.repall &&
  391. !(stctl & SCSW_STCTL_INTER_STATUS) &&
  392. !(cdev->private->options.fast &&
  393. (stctl & SCSW_STCTL_PRIM_STATUS)))
  394. return 0;
  395. /* Clear pending timers for device driver initiated I/O. */
  396. if (ending_status)
  397. ccw_device_set_timeout(cdev, 0);
  398. /*
  399. * Now we are ready to call the device driver interrupt handler.
  400. */
  401. if (cdev->handler)
  402. cdev->handler(cdev, cdev->private->intparm,
  403. &cdev->private->irb);
  404. /*
  405. * Clear the old and now useless interrupt response block.
  406. */
  407. memset(&cdev->private->irb, 0, sizeof(struct irb));
  408. return 1;
  409. }
  410. /**
  411. * ccw_device_get_ciw() - Search for CIW command in extended sense data.
  412. * @cdev: ccw device to inspect
  413. * @ct: command type to look for
  414. *
  415. * During SenseID, command information words (CIWs) describing special
  416. * commands available to the device may have been stored in the extended
  417. * sense data. This function searches for CIWs of a specified command
  418. * type in the extended sense data.
  419. * Returns:
  420. * %NULL if no extended sense data has been stored or if no CIW of the
  421. * specified command type could be found,
  422. * else a pointer to the CIW of the specified command type.
  423. */
  424. struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct)
  425. {
  426. int ciw_cnt;
  427. if (cdev->private->flags.esid == 0)
  428. return NULL;
  429. for (ciw_cnt = 0; ciw_cnt < MAX_CIWS; ciw_cnt++)
  430. if (cdev->private->senseid.ciw[ciw_cnt].ct == ct)
  431. return cdev->private->senseid.ciw + ciw_cnt;
  432. return NULL;
  433. }
  434. /**
  435. * ccw_device_get_path_mask() - get currently available paths
  436. * @cdev: ccw device to be queried
  437. * Returns:
  438. * %0 if no subchannel for the device is available,
  439. * else the mask of currently available paths for the ccw device's subchannel.
  440. */
  441. __u8 ccw_device_get_path_mask(struct ccw_device *cdev)
  442. {
  443. struct subchannel *sch;
  444. if (!cdev->dev.parent)
  445. return 0;
  446. sch = to_subchannel(cdev->dev.parent);
  447. return sch->lpm;
  448. }
  449. /*
  450. * Try to break the lock on a boxed device.
  451. */
  452. int
  453. ccw_device_stlck(struct ccw_device *cdev)
  454. {
  455. void *buf, *buf2;
  456. unsigned long flags;
  457. struct subchannel *sch;
  458. int ret;
  459. if (!cdev)
  460. return -ENODEV;
  461. if (cdev->drv && !cdev->private->options.force)
  462. return -EINVAL;
  463. sch = to_subchannel(cdev->dev.parent);
  464. CIO_TRACE_EVENT(2, "stl lock");
  465. CIO_TRACE_EVENT(2, dev_name(&cdev->dev));
  466. buf = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
  467. if (!buf)
  468. return -ENOMEM;
  469. buf2 = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
  470. if (!buf2) {
  471. kfree(buf);
  472. return -ENOMEM;
  473. }
  474. spin_lock_irqsave(sch->lock, flags);
  475. ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
  476. if (ret)
  477. goto out_unlock;
  478. /*
  479. * Setup ccw. We chain an unconditional reserve and a release so we
  480. * only break the lock.
  481. */
  482. cdev->private->iccws[0].cmd_code = CCW_CMD_STLCK;
  483. cdev->private->iccws[0].cda = (__u32) __pa(buf);
  484. cdev->private->iccws[0].count = 32;
  485. cdev->private->iccws[0].flags = CCW_FLAG_CC;
  486. cdev->private->iccws[1].cmd_code = CCW_CMD_RELEASE;
  487. cdev->private->iccws[1].cda = (__u32) __pa(buf2);
  488. cdev->private->iccws[1].count = 32;
  489. cdev->private->iccws[1].flags = 0;
  490. ret = cio_start(sch, cdev->private->iccws, 0);
  491. if (ret) {
  492. cio_disable_subchannel(sch); //FIXME: return code?
  493. goto out_unlock;
  494. }
  495. cdev->private->irb.scsw.cmd.actl |= SCSW_ACTL_START_PEND;
  496. spin_unlock_irqrestore(sch->lock, flags);
  497. wait_event(cdev->private->wait_q,
  498. cdev->private->irb.scsw.cmd.actl == 0);
  499. spin_lock_irqsave(sch->lock, flags);
  500. cio_disable_subchannel(sch); //FIXME: return code?
  501. if ((cdev->private->irb.scsw.cmd.dstat !=
  502. (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
  503. (cdev->private->irb.scsw.cmd.cstat != 0))
  504. ret = -EIO;
  505. /* Clear irb. */
  506. memset(&cdev->private->irb, 0, sizeof(struct irb));
  507. out_unlock:
  508. kfree(buf);
  509. kfree(buf2);
  510. spin_unlock_irqrestore(sch->lock, flags);
  511. return ret;
  512. }
  513. void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
  514. {
  515. struct subchannel *sch;
  516. struct chp_id chpid;
  517. sch = to_subchannel(cdev->dev.parent);
  518. chp_id_init(&chpid);
  519. chpid.id = sch->schib.pmcw.chpid[chp_no];
  520. return chp_get_chp_desc(chpid);
  521. }
  522. /**
  523. * ccw_device_get_id - obtain a ccw device id
  524. * @cdev: device to obtain the id for
  525. * @dev_id: where to fill in the values
  526. */
  527. void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id)
  528. {
  529. *dev_id = cdev->private->dev_id;
  530. }
  531. EXPORT_SYMBOL(ccw_device_get_id);
  532. /**
  533. * ccw_device_tm_start_key - perform start function
  534. * @cdev: ccw device on which to perform the start function
  535. * @tcw: transport-command word to be started
  536. * @intparm: user defined parameter to be passed to the interrupt handler
  537. * @lpm: mask of paths to use
  538. * @key: storage key to use for storage access
  539. *
  540. * Start the tcw on the given ccw device. Return zero on success, non-zero
  541. * otherwise.
  542. */
  543. int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
  544. unsigned long intparm, u8 lpm, u8 key)
  545. {
  546. struct subchannel *sch;
  547. int rc;
  548. sch = to_subchannel(cdev->dev.parent);
  549. if (!sch->schib.pmcw.ena)
  550. return -EINVAL;
  551. if (cdev->private->state != DEV_STATE_ONLINE)
  552. return -EIO;
  553. /* Adjust requested path mask to excluded varied off paths. */
  554. if (lpm) {
  555. lpm &= sch->opm;
  556. if (lpm == 0)
  557. return -EACCES;
  558. }
  559. rc = cio_tm_start_key(sch, tcw, lpm, key);
  560. if (rc == 0)
  561. cdev->private->intparm = intparm;
  562. return rc;
  563. }
  564. EXPORT_SYMBOL(ccw_device_tm_start_key);
  565. /**
  566. * ccw_device_tm_start_timeout_key - perform start function
  567. * @cdev: ccw device on which to perform the start function
  568. * @tcw: transport-command word to be started
  569. * @intparm: user defined parameter to be passed to the interrupt handler
  570. * @lpm: mask of paths to use
  571. * @key: storage key to use for storage access
  572. * @expires: time span in jiffies after which to abort request
  573. *
  574. * Start the tcw on the given ccw device. Return zero on success, non-zero
  575. * otherwise.
  576. */
  577. int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw,
  578. unsigned long intparm, u8 lpm, u8 key,
  579. int expires)
  580. {
  581. int ret;
  582. ccw_device_set_timeout(cdev, expires);
  583. ret = ccw_device_tm_start_key(cdev, tcw, intparm, lpm, key);
  584. if (ret != 0)
  585. ccw_device_set_timeout(cdev, 0);
  586. return ret;
  587. }
  588. EXPORT_SYMBOL(ccw_device_tm_start_timeout_key);
  589. /**
  590. * ccw_device_tm_start - perform start function
  591. * @cdev: ccw device on which to perform the start function
  592. * @tcw: transport-command word to be started
  593. * @intparm: user defined parameter to be passed to the interrupt handler
  594. * @lpm: mask of paths to use
  595. *
  596. * Start the tcw on the given ccw device. Return zero on success, non-zero
  597. * otherwise.
  598. */
  599. int ccw_device_tm_start(struct ccw_device *cdev, struct tcw *tcw,
  600. unsigned long intparm, u8 lpm)
  601. {
  602. return ccw_device_tm_start_key(cdev, tcw, intparm, lpm,
  603. PAGE_DEFAULT_KEY);
  604. }
  605. EXPORT_SYMBOL(ccw_device_tm_start);
  606. /**
  607. * ccw_device_tm_start_timeout - perform start function
  608. * @cdev: ccw device on which to perform the start function
  609. * @tcw: transport-command word to be started
  610. * @intparm: user defined parameter to be passed to the interrupt handler
  611. * @lpm: mask of paths to use
  612. * @expires: time span in jiffies after which to abort request
  613. *
  614. * Start the tcw on the given ccw device. Return zero on success, non-zero
  615. * otherwise.
  616. */
  617. int ccw_device_tm_start_timeout(struct ccw_device *cdev, struct tcw *tcw,
  618. unsigned long intparm, u8 lpm, int expires)
  619. {
  620. return ccw_device_tm_start_timeout_key(cdev, tcw, intparm, lpm,
  621. PAGE_DEFAULT_KEY, expires);
  622. }
  623. EXPORT_SYMBOL(ccw_device_tm_start_timeout);
  624. /**
  625. * ccw_device_tm_intrg - perform interrogate function
  626. * @cdev: ccw device on which to perform the interrogate function
  627. *
  628. * Perform an interrogate function on the given ccw device. Return zero on
  629. * success, non-zero otherwise.
  630. */
  631. int ccw_device_tm_intrg(struct ccw_device *cdev)
  632. {
  633. struct subchannel *sch = to_subchannel(cdev->dev.parent);
  634. if (!sch->schib.pmcw.ena)
  635. return -EINVAL;
  636. if (cdev->private->state != DEV_STATE_ONLINE)
  637. return -EIO;
  638. if (!scsw_is_tm(&sch->schib.scsw) ||
  639. !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_START_PEND))
  640. return -EINVAL;
  641. return cio_tm_intrg(sch);
  642. }
  643. EXPORT_SYMBOL(ccw_device_tm_intrg);
  644. // FIXME: these have to go:
  645. int
  646. _ccw_device_get_subchannel_number(struct ccw_device *cdev)
  647. {
  648. return cdev->private->schid.sch_no;
  649. }
  650. MODULE_LICENSE("GPL");
  651. EXPORT_SYMBOL(ccw_device_set_options_mask);
  652. EXPORT_SYMBOL(ccw_device_set_options);
  653. EXPORT_SYMBOL(ccw_device_clear_options);
  654. EXPORT_SYMBOL(ccw_device_clear);
  655. EXPORT_SYMBOL(ccw_device_halt);
  656. EXPORT_SYMBOL(ccw_device_resume);
  657. EXPORT_SYMBOL(ccw_device_start_timeout);
  658. EXPORT_SYMBOL(ccw_device_start);
  659. EXPORT_SYMBOL(ccw_device_start_timeout_key);
  660. EXPORT_SYMBOL(ccw_device_start_key);
  661. EXPORT_SYMBOL(ccw_device_get_ciw);
  662. EXPORT_SYMBOL(ccw_device_get_path_mask);
  663. EXPORT_SYMBOL(_ccw_device_get_subchannel_number);
  664. EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);