mic_boot.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /*
  2. * Intel MIC Platform Software Stack (MPSS)
  3. *
  4. * Copyright(c) 2013 Intel Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License, version 2, as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * The full GNU General Public License is included in this distribution in
  16. * the file called "COPYING".
  17. *
  18. * Intel MIC Host driver.
  19. *
  20. */
  21. #include <linux/delay.h>
  22. #include <linux/firmware.h>
  23. #include <linux/pci.h>
  24. #include <linux/kmod.h>
  25. #include <linux/mic_common.h>
  26. #include <linux/mic_bus.h>
  27. #include "../common/mic_dev.h"
  28. #include "mic_device.h"
  29. #include "mic_smpt.h"
  30. #include "mic_virtio.h"
  31. static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev)
  32. {
  33. return dev_get_drvdata(scdev->dev.parent);
  34. }
  35. static void *__mic_dma_alloc(struct device *dev, size_t size,
  36. dma_addr_t *dma_handle, gfp_t gfp,
  37. struct dma_attrs *attrs)
  38. {
  39. struct scif_hw_dev *scdev = dev_get_drvdata(dev);
  40. struct mic_device *mdev = scdev_to_mdev(scdev);
  41. dma_addr_t tmp;
  42. void *va = kmalloc(size, gfp);
  43. if (va) {
  44. tmp = mic_map_single(mdev, va, size);
  45. if (dma_mapping_error(dev, tmp)) {
  46. kfree(va);
  47. va = NULL;
  48. } else {
  49. *dma_handle = tmp;
  50. }
  51. }
  52. return va;
  53. }
  54. static void __mic_dma_free(struct device *dev, size_t size, void *vaddr,
  55. dma_addr_t dma_handle, struct dma_attrs *attrs)
  56. {
  57. struct scif_hw_dev *scdev = dev_get_drvdata(dev);
  58. struct mic_device *mdev = scdev_to_mdev(scdev);
  59. mic_unmap_single(mdev, dma_handle, size);
  60. kfree(vaddr);
  61. }
  62. static dma_addr_t
  63. __mic_dma_map_page(struct device *dev, struct page *page, unsigned long offset,
  64. size_t size, enum dma_data_direction dir,
  65. struct dma_attrs *attrs)
  66. {
  67. void *va = phys_to_virt(page_to_phys(page)) + offset;
  68. struct scif_hw_dev *scdev = dev_get_drvdata(dev);
  69. struct mic_device *mdev = scdev_to_mdev(scdev);
  70. return mic_map_single(mdev, va, size);
  71. }
  72. static void
  73. __mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
  74. size_t size, enum dma_data_direction dir,
  75. struct dma_attrs *attrs)
  76. {
  77. struct scif_hw_dev *scdev = dev_get_drvdata(dev);
  78. struct mic_device *mdev = scdev_to_mdev(scdev);
  79. mic_unmap_single(mdev, dma_addr, size);
  80. }
  81. static int __mic_dma_map_sg(struct device *dev, struct scatterlist *sg,
  82. int nents, enum dma_data_direction dir,
  83. struct dma_attrs *attrs)
  84. {
  85. struct scif_hw_dev *scdev = dev_get_drvdata(dev);
  86. struct mic_device *mdev = scdev_to_mdev(scdev);
  87. struct scatterlist *s;
  88. int i, j, ret;
  89. dma_addr_t da;
  90. ret = dma_map_sg(mdev->sdev->parent, sg, nents, dir);
  91. if (ret <= 0)
  92. return 0;
  93. for_each_sg(sg, s, nents, i) {
  94. da = mic_map(mdev, sg_dma_address(s) + s->offset, s->length);
  95. if (!da)
  96. goto err;
  97. sg_dma_address(s) = da;
  98. }
  99. return nents;
  100. err:
  101. for_each_sg(sg, s, i, j) {
  102. mic_unmap(mdev, sg_dma_address(s), s->length);
  103. sg_dma_address(s) = mic_to_dma_addr(mdev, sg_dma_address(s));
  104. }
  105. dma_unmap_sg(mdev->sdev->parent, sg, nents, dir);
  106. return 0;
  107. }
  108. static void __mic_dma_unmap_sg(struct device *dev,
  109. struct scatterlist *sg, int nents,
  110. enum dma_data_direction dir,
  111. struct dma_attrs *attrs)
  112. {
  113. struct scif_hw_dev *scdev = dev_get_drvdata(dev);
  114. struct mic_device *mdev = scdev_to_mdev(scdev);
  115. struct scatterlist *s;
  116. dma_addr_t da;
  117. int i;
  118. for_each_sg(sg, s, nents, i) {
  119. da = mic_to_dma_addr(mdev, sg_dma_address(s));
  120. mic_unmap(mdev, sg_dma_address(s), s->length);
  121. sg_dma_address(s) = da;
  122. }
  123. dma_unmap_sg(mdev->sdev->parent, sg, nents, dir);
  124. }
  125. static struct dma_map_ops __mic_dma_ops = {
  126. .alloc = __mic_dma_alloc,
  127. .free = __mic_dma_free,
  128. .map_page = __mic_dma_map_page,
  129. .unmap_page = __mic_dma_unmap_page,
  130. .map_sg = __mic_dma_map_sg,
  131. .unmap_sg = __mic_dma_unmap_sg,
  132. };
  133. static struct mic_irq *
  134. ___mic_request_irq(struct scif_hw_dev *scdev,
  135. irqreturn_t (*func)(int irq, void *data),
  136. const char *name,
  137. void *data, int db)
  138. {
  139. struct mic_device *mdev = scdev_to_mdev(scdev);
  140. return mic_request_threaded_irq(mdev, func, NULL, name, data,
  141. db, MIC_INTR_DB);
  142. }
  143. static void
  144. ___mic_free_irq(struct scif_hw_dev *scdev,
  145. struct mic_irq *cookie, void *data)
  146. {
  147. struct mic_device *mdev = scdev_to_mdev(scdev);
  148. return mic_free_irq(mdev, cookie, data);
  149. }
  150. static void ___mic_ack_interrupt(struct scif_hw_dev *scdev, int num)
  151. {
  152. struct mic_device *mdev = scdev_to_mdev(scdev);
  153. mdev->ops->intr_workarounds(mdev);
  154. }
  155. static int ___mic_next_db(struct scif_hw_dev *scdev)
  156. {
  157. struct mic_device *mdev = scdev_to_mdev(scdev);
  158. return mic_next_db(mdev);
  159. }
  160. static void ___mic_send_intr(struct scif_hw_dev *scdev, int db)
  161. {
  162. struct mic_device *mdev = scdev_to_mdev(scdev);
  163. mdev->ops->send_intr(mdev, db);
  164. }
  165. static void __iomem *___mic_ioremap(struct scif_hw_dev *scdev,
  166. phys_addr_t pa, size_t len)
  167. {
  168. struct mic_device *mdev = scdev_to_mdev(scdev);
  169. return mdev->aper.va + pa;
  170. }
  171. static void ___mic_iounmap(struct scif_hw_dev *scdev, void __iomem *va)
  172. {
  173. /* nothing to do */
  174. }
  175. static struct scif_hw_ops scif_hw_ops = {
  176. .request_irq = ___mic_request_irq,
  177. .free_irq = ___mic_free_irq,
  178. .ack_interrupt = ___mic_ack_interrupt,
  179. .next_db = ___mic_next_db,
  180. .send_intr = ___mic_send_intr,
  181. .ioremap = ___mic_ioremap,
  182. .iounmap = ___mic_iounmap,
  183. };
  184. static inline struct mic_device *mbdev_to_mdev(struct mbus_device *mbdev)
  185. {
  186. return dev_get_drvdata(mbdev->dev.parent);
  187. }
  188. static dma_addr_t
  189. mic_dma_map_page(struct device *dev, struct page *page,
  190. unsigned long offset, size_t size, enum dma_data_direction dir,
  191. struct dma_attrs *attrs)
  192. {
  193. void *va = phys_to_virt(page_to_phys(page)) + offset;
  194. struct mic_device *mdev = dev_get_drvdata(dev->parent);
  195. return mic_map_single(mdev, va, size);
  196. }
  197. static void
  198. mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
  199. size_t size, enum dma_data_direction dir,
  200. struct dma_attrs *attrs)
  201. {
  202. struct mic_device *mdev = dev_get_drvdata(dev->parent);
  203. mic_unmap_single(mdev, dma_addr, size);
  204. }
  205. static struct dma_map_ops mic_dma_ops = {
  206. .map_page = mic_dma_map_page,
  207. .unmap_page = mic_dma_unmap_page,
  208. };
  209. static struct mic_irq *
  210. _mic_request_threaded_irq(struct mbus_device *mbdev,
  211. irq_handler_t handler, irq_handler_t thread_fn,
  212. const char *name, void *data, int intr_src)
  213. {
  214. return mic_request_threaded_irq(mbdev_to_mdev(mbdev), handler,
  215. thread_fn, name, data,
  216. intr_src, MIC_INTR_DMA);
  217. }
  218. static void _mic_free_irq(struct mbus_device *mbdev,
  219. struct mic_irq *cookie, void *data)
  220. {
  221. return mic_free_irq(mbdev_to_mdev(mbdev), cookie, data);
  222. }
  223. static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
  224. {
  225. struct mic_device *mdev = mbdev_to_mdev(mbdev);
  226. mdev->ops->intr_workarounds(mdev);
  227. }
  228. static struct mbus_hw_ops mbus_hw_ops = {
  229. .request_threaded_irq = _mic_request_threaded_irq,
  230. .free_irq = _mic_free_irq,
  231. .ack_interrupt = _mic_ack_interrupt,
  232. };
  233. /**
  234. * mic_reset - Reset the MIC device.
  235. * @mdev: pointer to mic_device instance
  236. */
  237. static void mic_reset(struct mic_device *mdev)
  238. {
  239. int i;
  240. #define MIC_RESET_TO (45)
  241. reinit_completion(&mdev->reset_wait);
  242. mdev->ops->reset_fw_ready(mdev);
  243. mdev->ops->reset(mdev);
  244. for (i = 0; i < MIC_RESET_TO; i++) {
  245. if (mdev->ops->is_fw_ready(mdev))
  246. goto done;
  247. /*
  248. * Resets typically take 10s of seconds to complete.
  249. * Since an MMIO read is required to check if the
  250. * firmware is ready or not, a 1 second delay works nicely.
  251. */
  252. msleep(1000);
  253. }
  254. mic_set_state(mdev, MIC_RESET_FAILED);
  255. done:
  256. complete_all(&mdev->reset_wait);
  257. }
  258. /* Initialize the MIC bootparams */
  259. void mic_bootparam_init(struct mic_device *mdev)
  260. {
  261. struct mic_bootparam *bootparam = mdev->dp;
  262. bootparam->magic = cpu_to_le32(MIC_MAGIC);
  263. bootparam->c2h_shutdown_db = mdev->shutdown_db;
  264. bootparam->h2c_shutdown_db = -1;
  265. bootparam->h2c_config_db = -1;
  266. bootparam->shutdown_status = 0;
  267. bootparam->shutdown_card = 0;
  268. /* Total nodes = number of MICs + 1 for self node */
  269. bootparam->tot_nodes = atomic_read(&g_num_mics) + 1;
  270. bootparam->node_id = mdev->id + 1;
  271. bootparam->scif_host_dma_addr = 0x0;
  272. bootparam->scif_card_dma_addr = 0x0;
  273. bootparam->c2h_scif_db = -1;
  274. bootparam->h2c_scif_db = -1;
  275. }
  276. /**
  277. * mic_request_dma_chans - Request DMA channels
  278. * @mdev: pointer to mic_device instance
  279. *
  280. * returns number of DMA channels acquired
  281. */
  282. static int mic_request_dma_chans(struct mic_device *mdev)
  283. {
  284. dma_cap_mask_t mask;
  285. struct dma_chan *chan;
  286. request_module("mic_x100_dma");
  287. dma_cap_zero(mask);
  288. dma_cap_set(DMA_MEMCPY, mask);
  289. do {
  290. chan = dma_request_channel(mask, mdev->ops->dma_filter,
  291. mdev->sdev->parent);
  292. if (chan) {
  293. mdev->dma_ch[mdev->num_dma_ch++] = chan;
  294. if (mdev->num_dma_ch >= MIC_MAX_DMA_CHAN)
  295. break;
  296. }
  297. } while (chan);
  298. dev_info(mdev->sdev->parent, "DMA channels # %d\n", mdev->num_dma_ch);
  299. return mdev->num_dma_ch;
  300. }
  301. /**
  302. * mic_free_dma_chans - release DMA channels
  303. * @mdev: pointer to mic_device instance
  304. *
  305. * returns none
  306. */
  307. static void mic_free_dma_chans(struct mic_device *mdev)
  308. {
  309. int i = 0;
  310. for (i = 0; i < mdev->num_dma_ch; i++) {
  311. dma_release_channel(mdev->dma_ch[i]);
  312. mdev->dma_ch[i] = NULL;
  313. }
  314. mdev->num_dma_ch = 0;
  315. }
  316. /**
  317. * mic_start - Start the MIC.
  318. * @mdev: pointer to mic_device instance
  319. * @buf: buffer containing boot string including firmware/ramdisk path.
  320. *
  321. * This function prepares an MIC for boot and initiates boot.
  322. * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
  323. */
  324. int mic_start(struct mic_device *mdev, const char *buf)
  325. {
  326. int rc;
  327. mutex_lock(&mdev->mic_mutex);
  328. mic_bootparam_init(mdev);
  329. retry:
  330. if (MIC_OFFLINE != mdev->state) {
  331. rc = -EINVAL;
  332. goto unlock_ret;
  333. }
  334. if (!mdev->ops->is_fw_ready(mdev)) {
  335. mic_reset(mdev);
  336. /*
  337. * The state will either be MIC_OFFLINE if the reset succeeded
  338. * or MIC_RESET_FAILED if the firmware reset failed.
  339. */
  340. goto retry;
  341. }
  342. mdev->dma_mbdev = mbus_register_device(mdev->sdev->parent,
  343. MBUS_DEV_DMA_HOST, &mic_dma_ops,
  344. &mbus_hw_ops, mdev->mmio.va);
  345. if (IS_ERR(mdev->dma_mbdev)) {
  346. rc = PTR_ERR(mdev->dma_mbdev);
  347. goto unlock_ret;
  348. }
  349. if (!mic_request_dma_chans(mdev)) {
  350. rc = -ENODEV;
  351. goto dma_remove;
  352. }
  353. mdev->scdev = scif_register_device(mdev->sdev->parent, MIC_SCIF_DEV,
  354. &__mic_dma_ops, &scif_hw_ops,
  355. mdev->id + 1, 0, &mdev->mmio,
  356. &mdev->aper, mdev->dp, NULL,
  357. mdev->dma_ch, mdev->num_dma_ch);
  358. if (IS_ERR(mdev->scdev)) {
  359. rc = PTR_ERR(mdev->scdev);
  360. goto dma_free;
  361. }
  362. rc = mdev->ops->load_mic_fw(mdev, buf);
  363. if (rc)
  364. goto scif_remove;
  365. mic_smpt_restore(mdev);
  366. mic_intr_restore(mdev);
  367. mdev->intr_ops->enable_interrupts(mdev);
  368. mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
  369. mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
  370. mdev->ops->send_firmware_intr(mdev);
  371. mic_set_state(mdev, MIC_ONLINE);
  372. goto unlock_ret;
  373. scif_remove:
  374. scif_unregister_device(mdev->scdev);
  375. dma_free:
  376. mic_free_dma_chans(mdev);
  377. dma_remove:
  378. mbus_unregister_device(mdev->dma_mbdev);
  379. unlock_ret:
  380. mutex_unlock(&mdev->mic_mutex);
  381. return rc;
  382. }
  383. /**
  384. * mic_stop - Prepare the MIC for reset and trigger reset.
  385. * @mdev: pointer to mic_device instance
  386. * @force: force a MIC to reset even if it is already offline.
  387. *
  388. * RETURNS: None.
  389. */
  390. void mic_stop(struct mic_device *mdev, bool force)
  391. {
  392. mutex_lock(&mdev->mic_mutex);
  393. if (MIC_OFFLINE != mdev->state || force) {
  394. scif_unregister_device(mdev->scdev);
  395. mic_virtio_reset_devices(mdev);
  396. mic_free_dma_chans(mdev);
  397. mbus_unregister_device(mdev->dma_mbdev);
  398. mic_bootparam_init(mdev);
  399. mic_reset(mdev);
  400. if (MIC_RESET_FAILED == mdev->state)
  401. goto unlock;
  402. mic_set_shutdown_status(mdev, MIC_NOP);
  403. if (MIC_SUSPENDED != mdev->state)
  404. mic_set_state(mdev, MIC_OFFLINE);
  405. }
  406. unlock:
  407. mutex_unlock(&mdev->mic_mutex);
  408. }
  409. /**
  410. * mic_shutdown - Initiate MIC shutdown.
  411. * @mdev: pointer to mic_device instance
  412. *
  413. * RETURNS: None.
  414. */
  415. void mic_shutdown(struct mic_device *mdev)
  416. {
  417. struct mic_bootparam *bootparam = mdev->dp;
  418. s8 db = bootparam->h2c_shutdown_db;
  419. mutex_lock(&mdev->mic_mutex);
  420. if (MIC_ONLINE == mdev->state && db != -1) {
  421. bootparam->shutdown_card = 1;
  422. mdev->ops->send_intr(mdev, db);
  423. mic_set_state(mdev, MIC_SHUTTING_DOWN);
  424. }
  425. mutex_unlock(&mdev->mic_mutex);
  426. }
  427. /**
  428. * mic_shutdown_work - Handle shutdown interrupt from MIC.
  429. * @work: The work structure.
  430. *
  431. * This work is scheduled whenever the host has received a shutdown
  432. * interrupt from the MIC.
  433. */
  434. void mic_shutdown_work(struct work_struct *work)
  435. {
  436. struct mic_device *mdev = container_of(work, struct mic_device,
  437. shutdown_work);
  438. struct mic_bootparam *bootparam = mdev->dp;
  439. mutex_lock(&mdev->mic_mutex);
  440. mic_set_shutdown_status(mdev, bootparam->shutdown_status);
  441. bootparam->shutdown_status = 0;
  442. /*
  443. * if state is MIC_SUSPENDED, OSPM suspend is in progress. We do not
  444. * change the state here so as to prevent users from booting the card
  445. * during and after the suspend operation.
  446. */
  447. if (MIC_SHUTTING_DOWN != mdev->state &&
  448. MIC_SUSPENDED != mdev->state)
  449. mic_set_state(mdev, MIC_SHUTTING_DOWN);
  450. mutex_unlock(&mdev->mic_mutex);
  451. }
  452. /**
  453. * mic_reset_trigger_work - Trigger MIC reset.
  454. * @work: The work structure.
  455. *
  456. * This work is scheduled whenever the host wants to reset the MIC.
  457. */
  458. void mic_reset_trigger_work(struct work_struct *work)
  459. {
  460. struct mic_device *mdev = container_of(work, struct mic_device,
  461. reset_trigger_work);
  462. mic_stop(mdev, false);
  463. }
  464. /**
  465. * mic_complete_resume - Complete MIC Resume after an OSPM suspend/hibernate
  466. * event.
  467. * @mdev: pointer to mic_device instance
  468. *
  469. * RETURNS: None.
  470. */
  471. void mic_complete_resume(struct mic_device *mdev)
  472. {
  473. if (mdev->state != MIC_SUSPENDED) {
  474. dev_warn(mdev->sdev->parent, "state %d should be %d\n",
  475. mdev->state, MIC_SUSPENDED);
  476. return;
  477. }
  478. /* Make sure firmware is ready */
  479. if (!mdev->ops->is_fw_ready(mdev))
  480. mic_stop(mdev, true);
  481. mutex_lock(&mdev->mic_mutex);
  482. mic_set_state(mdev, MIC_OFFLINE);
  483. mutex_unlock(&mdev->mic_mutex);
  484. }
  485. /**
  486. * mic_prepare_suspend - Handle suspend notification for the MIC device.
  487. * @mdev: pointer to mic_device instance
  488. *
  489. * RETURNS: None.
  490. */
  491. void mic_prepare_suspend(struct mic_device *mdev)
  492. {
  493. unsigned long timeout;
  494. #define MIC_SUSPEND_TIMEOUT (60 * HZ)
  495. mutex_lock(&mdev->mic_mutex);
  496. switch (mdev->state) {
  497. case MIC_OFFLINE:
  498. /*
  499. * Card is already offline. Set state to MIC_SUSPENDED
  500. * to prevent users from booting the card.
  501. */
  502. mic_set_state(mdev, MIC_SUSPENDED);
  503. mutex_unlock(&mdev->mic_mutex);
  504. break;
  505. case MIC_ONLINE:
  506. /*
  507. * Card is online. Set state to MIC_SUSPENDING and notify
  508. * MIC user space daemon which will issue card
  509. * shutdown and reset.
  510. */
  511. mic_set_state(mdev, MIC_SUSPENDING);
  512. mutex_unlock(&mdev->mic_mutex);
  513. timeout = wait_for_completion_timeout(&mdev->reset_wait,
  514. MIC_SUSPEND_TIMEOUT);
  515. /* Force reset the card if the shutdown completion timed out */
  516. if (!timeout) {
  517. mutex_lock(&mdev->mic_mutex);
  518. mic_set_state(mdev, MIC_SUSPENDED);
  519. mutex_unlock(&mdev->mic_mutex);
  520. mic_stop(mdev, true);
  521. }
  522. break;
  523. case MIC_SHUTTING_DOWN:
  524. /*
  525. * Card is shutting down. Set state to MIC_SUSPENDED
  526. * to prevent further boot of the card.
  527. */
  528. mic_set_state(mdev, MIC_SUSPENDED);
  529. mutex_unlock(&mdev->mic_mutex);
  530. timeout = wait_for_completion_timeout(&mdev->reset_wait,
  531. MIC_SUSPEND_TIMEOUT);
  532. /* Force reset the card if the shutdown completion timed out */
  533. if (!timeout)
  534. mic_stop(mdev, true);
  535. break;
  536. default:
  537. mutex_unlock(&mdev->mic_mutex);
  538. break;
  539. }
  540. }
  541. /**
  542. * mic_suspend - Initiate MIC suspend. Suspend merely issues card shutdown.
  543. * @mdev: pointer to mic_device instance
  544. *
  545. * RETURNS: None.
  546. */
  547. void mic_suspend(struct mic_device *mdev)
  548. {
  549. struct mic_bootparam *bootparam = mdev->dp;
  550. s8 db = bootparam->h2c_shutdown_db;
  551. mutex_lock(&mdev->mic_mutex);
  552. if (MIC_SUSPENDING == mdev->state && db != -1) {
  553. bootparam->shutdown_card = 1;
  554. mdev->ops->send_intr(mdev, db);
  555. mic_set_state(mdev, MIC_SUSPENDED);
  556. }
  557. mutex_unlock(&mdev->mic_mutex);
  558. }