init.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. /*
  2. *
  3. * Intel Management Engine Interface (Intel MEI) Linux driver
  4. * Copyright (c) 2003-2012, Intel Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2, as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. */
  16. #include <linux/pci.h>
  17. #include <linux/sched.h>
  18. #include <linux/wait.h>
  19. #include <linux/delay.h>
  20. #include "mei_dev.h"
  21. #include "hw.h"
  22. #include "interface.h"
  23. #include <linux/mei.h>
  24. const char *mei_dev_state_str(int state)
  25. {
  26. #define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state
  27. switch (state) {
  28. MEI_DEV_STATE(INITIALIZING);
  29. MEI_DEV_STATE(INIT_CLIENTS);
  30. MEI_DEV_STATE(ENABLED);
  31. MEI_DEV_STATE(RESETING);
  32. MEI_DEV_STATE(DISABLED);
  33. MEI_DEV_STATE(RECOVERING_FROM_RESET);
  34. MEI_DEV_STATE(POWER_DOWN);
  35. MEI_DEV_STATE(POWER_UP);
  36. default:
  37. return "unkown";
  38. }
  39. #undef MEI_DEV_STATE
  40. }
  41. /**
  42. * mei_io_list_flush - removes list entry belonging to cl.
  43. *
  44. * @list: An instance of our list structure
  45. * @cl: private data of the file object
  46. */
  47. void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
  48. {
  49. struct mei_cl_cb *pos;
  50. struct mei_cl_cb *next;
  51. list_for_each_entry_safe(pos, next, &list->list, list) {
  52. if (pos->cl) {
  53. if (mei_cl_cmp_id(cl, pos->cl))
  54. list_del(&pos->list);
  55. }
  56. }
  57. }
  58. /**
  59. * mei_cl_flush_queues - flushes queue lists belonging to cl.
  60. *
  61. * @dev: the device structure
  62. * @cl: private data of the file object
  63. */
  64. int mei_cl_flush_queues(struct mei_cl *cl)
  65. {
  66. if (!cl || !cl->dev)
  67. return -EINVAL;
  68. dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
  69. mei_io_list_flush(&cl->dev->read_list, cl);
  70. mei_io_list_flush(&cl->dev->write_list, cl);
  71. mei_io_list_flush(&cl->dev->write_waiting_list, cl);
  72. mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
  73. mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
  74. mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
  75. mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
  76. return 0;
  77. }
  78. /**
  79. * init_mei_device - allocates and initializes the mei device structure
  80. *
  81. * @pdev: The pci device structure
  82. *
  83. * returns The mei_device_device pointer on success, NULL on failure.
  84. */
  85. struct mei_device *mei_device_init(struct pci_dev *pdev)
  86. {
  87. struct mei_device *dev;
  88. dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL);
  89. if (!dev)
  90. return NULL;
  91. /* setup our list array */
  92. INIT_LIST_HEAD(&dev->file_list);
  93. INIT_LIST_HEAD(&dev->wd_cl.link);
  94. INIT_LIST_HEAD(&dev->iamthif_cl.link);
  95. mutex_init(&dev->device_lock);
  96. init_waitqueue_head(&dev->wait_recvd_msg);
  97. init_waitqueue_head(&dev->wait_stop_wd);
  98. dev->dev_state = MEI_DEV_INITIALIZING;
  99. dev->iamthif_state = MEI_IAMTHIF_IDLE;
  100. mei_io_list_init(&dev->read_list);
  101. mei_io_list_init(&dev->write_list);
  102. mei_io_list_init(&dev->write_waiting_list);
  103. mei_io_list_init(&dev->ctrl_wr_list);
  104. mei_io_list_init(&dev->ctrl_rd_list);
  105. mei_io_list_init(&dev->amthif_cmd_list);
  106. mei_io_list_init(&dev->amthif_rd_complete_list);
  107. dev->pdev = pdev;
  108. return dev;
  109. }
  110. /**
  111. * mei_hw_init - initializes host and fw to start work.
  112. *
  113. * @dev: the device structure
  114. *
  115. * returns 0 on success, <0 on failure.
  116. */
  117. int mei_hw_init(struct mei_device *dev)
  118. {
  119. int err = 0;
  120. int ret;
  121. mutex_lock(&dev->device_lock);
  122. dev->host_hw_state = mei_hcsr_read(dev);
  123. dev->me_hw_state = mei_mecsr_read(dev);
  124. dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, mestate = 0x%08x.\n",
  125. dev->host_hw_state, dev->me_hw_state);
  126. /* acknowledge interrupt and stop interupts */
  127. if ((dev->host_hw_state & H_IS) == H_IS)
  128. mei_reg_write(dev, H_CSR, dev->host_hw_state);
  129. /* Doesn't change in runtime */
  130. dev->hbuf_depth = (dev->host_hw_state & H_CBD) >> 24;
  131. dev->recvd_msg = false;
  132. dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
  133. mei_reset(dev, 1);
  134. dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
  135. dev->host_hw_state, dev->me_hw_state);
  136. /* wait for ME to turn on ME_RDY */
  137. if (!dev->recvd_msg) {
  138. mutex_unlock(&dev->device_lock);
  139. err = wait_event_interruptible_timeout(dev->wait_recvd_msg,
  140. dev->recvd_msg,
  141. mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
  142. mutex_lock(&dev->device_lock);
  143. }
  144. if (err <= 0 && !dev->recvd_msg) {
  145. dev->dev_state = MEI_DEV_DISABLED;
  146. dev_dbg(&dev->pdev->dev,
  147. "wait_event_interruptible_timeout failed"
  148. "on wait for ME to turn on ME_RDY.\n");
  149. ret = -ENODEV;
  150. goto out;
  151. }
  152. if (!(((dev->host_hw_state & H_RDY) == H_RDY) &&
  153. ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) {
  154. dev->dev_state = MEI_DEV_DISABLED;
  155. dev_dbg(&dev->pdev->dev,
  156. "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
  157. dev->host_hw_state, dev->me_hw_state);
  158. if (!(dev->host_hw_state & H_RDY))
  159. dev_dbg(&dev->pdev->dev, "host turn off H_RDY.\n");
  160. if (!(dev->me_hw_state & ME_RDY_HRA))
  161. dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n");
  162. dev_err(&dev->pdev->dev, "link layer initialization failed.\n");
  163. ret = -ENODEV;
  164. goto out;
  165. }
  166. if (dev->version.major_version != HBM_MAJOR_VERSION ||
  167. dev->version.minor_version != HBM_MINOR_VERSION) {
  168. dev_dbg(&dev->pdev->dev, "MEI start failed.\n");
  169. ret = -ENODEV;
  170. goto out;
  171. }
  172. dev->recvd_msg = false;
  173. dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
  174. dev->host_hw_state, dev->me_hw_state);
  175. dev_dbg(&dev->pdev->dev, "ME turn on ME_RDY and host turn on H_RDY.\n");
  176. dev_dbg(&dev->pdev->dev, "link layer has been established.\n");
  177. dev_dbg(&dev->pdev->dev, "MEI start success.\n");
  178. ret = 0;
  179. out:
  180. mutex_unlock(&dev->device_lock);
  181. return ret;
  182. }
  183. /**
  184. * mei_hw_reset - resets fw via mei csr register.
  185. *
  186. * @dev: the device structure
  187. * @interrupts_enabled: if interrupt should be enabled after reset.
  188. */
  189. static void mei_hw_reset(struct mei_device *dev, int interrupts_enabled)
  190. {
  191. dev->host_hw_state |= (H_RST | H_IG);
  192. if (interrupts_enabled)
  193. mei_enable_interrupts(dev);
  194. else
  195. mei_disable_interrupts(dev);
  196. }
  197. /**
  198. * mei_reset - resets host and fw.
  199. *
  200. * @dev: the device structure
  201. * @interrupts_enabled: if interrupt should be enabled after reset.
  202. */
  203. void mei_reset(struct mei_device *dev, int interrupts_enabled)
  204. {
  205. struct mei_cl *cl_pos = NULL;
  206. struct mei_cl *cl_next = NULL;
  207. struct mei_cl_cb *cb_pos = NULL;
  208. struct mei_cl_cb *cb_next = NULL;
  209. bool unexpected;
  210. if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
  211. dev->need_reset = true;
  212. return;
  213. }
  214. unexpected = (dev->dev_state != MEI_DEV_INITIALIZING &&
  215. dev->dev_state != MEI_DEV_DISABLED &&
  216. dev->dev_state != MEI_DEV_POWER_DOWN &&
  217. dev->dev_state != MEI_DEV_POWER_UP);
  218. dev->host_hw_state = mei_hcsr_read(dev);
  219. dev_dbg(&dev->pdev->dev, "before reset host_hw_state = 0x%08x.\n",
  220. dev->host_hw_state);
  221. mei_hw_reset(dev, interrupts_enabled);
  222. dev->host_hw_state &= ~H_RST;
  223. dev->host_hw_state |= H_IG;
  224. mei_hcsr_set(dev);
  225. dev_dbg(&dev->pdev->dev, "currently saved host_hw_state = 0x%08x.\n",
  226. dev->host_hw_state);
  227. dev->need_reset = false;
  228. if (dev->dev_state != MEI_DEV_INITIALIZING) {
  229. if (dev->dev_state != MEI_DEV_DISABLED &&
  230. dev->dev_state != MEI_DEV_POWER_DOWN)
  231. dev->dev_state = MEI_DEV_RESETING;
  232. list_for_each_entry_safe(cl_pos,
  233. cl_next, &dev->file_list, link) {
  234. cl_pos->state = MEI_FILE_DISCONNECTED;
  235. cl_pos->mei_flow_ctrl_creds = 0;
  236. cl_pos->read_cb = NULL;
  237. cl_pos->timer_count = 0;
  238. }
  239. /* remove entry if already in list */
  240. dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
  241. mei_me_cl_unlink(dev, &dev->wd_cl);
  242. mei_me_cl_unlink(dev, &dev->iamthif_cl);
  243. mei_amthif_reset_params(dev);
  244. memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
  245. }
  246. dev->me_clients_num = 0;
  247. dev->rd_msg_hdr = 0;
  248. dev->wd_pending = false;
  249. /* update the state of the registers after reset */
  250. dev->host_hw_state = mei_hcsr_read(dev);
  251. dev->me_hw_state = mei_mecsr_read(dev);
  252. dev_dbg(&dev->pdev->dev, "after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
  253. dev->host_hw_state, dev->me_hw_state);
  254. if (unexpected)
  255. dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n",
  256. mei_dev_state_str(dev->dev_state));
  257. /* Wake up all readings so they can be interrupted */
  258. list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
  259. if (waitqueue_active(&cl_pos->rx_wait)) {
  260. dev_dbg(&dev->pdev->dev, "Waking up client!\n");
  261. wake_up_interruptible(&cl_pos->rx_wait);
  262. }
  263. }
  264. /* remove all waiting requests */
  265. list_for_each_entry_safe(cb_pos, cb_next, &dev->write_list.list, list) {
  266. list_del(&cb_pos->list);
  267. mei_io_cb_free(cb_pos);
  268. }
  269. }
  270. /**
  271. * host_start_message - mei host sends start message.
  272. *
  273. * @dev: the device structure
  274. *
  275. * returns none.
  276. */
  277. void mei_host_start_message(struct mei_device *dev)
  278. {
  279. struct mei_msg_hdr *mei_hdr;
  280. struct hbm_host_version_request *start_req;
  281. const size_t len = sizeof(struct hbm_host_version_request);
  282. mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
  283. /* host start message */
  284. start_req = (struct hbm_host_version_request *)&dev->wr_msg_buf[1];
  285. memset(start_req, 0, len);
  286. start_req->hbm_cmd = HOST_START_REQ_CMD;
  287. start_req->host_version.major_version = HBM_MAJOR_VERSION;
  288. start_req->host_version.minor_version = HBM_MINOR_VERSION;
  289. dev->recvd_msg = false;
  290. if (mei_write_message(dev, mei_hdr, (unsigned char *)start_req, len)) {
  291. dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
  292. dev->dev_state = MEI_DEV_RESETING;
  293. mei_reset(dev, 1);
  294. }
  295. dev->init_clients_state = MEI_START_MESSAGE;
  296. dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
  297. return ;
  298. }
  299. /**
  300. * host_enum_clients_message - host sends enumeration client request message.
  301. *
  302. * @dev: the device structure
  303. *
  304. * returns none.
  305. */
  306. void mei_host_enum_clients_message(struct mei_device *dev)
  307. {
  308. struct mei_msg_hdr *mei_hdr;
  309. struct hbm_host_enum_request *enum_req;
  310. const size_t len = sizeof(struct hbm_host_enum_request);
  311. /* enumerate clients */
  312. mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
  313. enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
  314. memset(enum_req, 0, sizeof(struct hbm_host_enum_request));
  315. enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
  316. if (mei_write_message(dev, mei_hdr, (unsigned char *)enum_req, len)) {
  317. dev->dev_state = MEI_DEV_RESETING;
  318. dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
  319. mei_reset(dev, 1);
  320. }
  321. dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE;
  322. dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
  323. return;
  324. }
  325. /**
  326. * allocate_me_clients_storage - allocates storage for me clients
  327. *
  328. * @dev: the device structure
  329. *
  330. * returns none.
  331. */
  332. void mei_allocate_me_clients_storage(struct mei_device *dev)
  333. {
  334. struct mei_me_client *clients;
  335. int b;
  336. /* count how many ME clients we have */
  337. for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
  338. dev->me_clients_num++;
  339. if (dev->me_clients_num <= 0)
  340. return ;
  341. if (dev->me_clients != NULL) {
  342. kfree(dev->me_clients);
  343. dev->me_clients = NULL;
  344. }
  345. dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n",
  346. dev->me_clients_num * sizeof(struct mei_me_client));
  347. /* allocate storage for ME clients representation */
  348. clients = kcalloc(dev->me_clients_num,
  349. sizeof(struct mei_me_client), GFP_KERNEL);
  350. if (!clients) {
  351. dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
  352. dev->dev_state = MEI_DEV_RESETING;
  353. mei_reset(dev, 1);
  354. return ;
  355. }
  356. dev->me_clients = clients;
  357. return ;
  358. }
  359. void mei_host_client_init(struct work_struct *work)
  360. {
  361. struct mei_device *dev = container_of(work,
  362. struct mei_device, init_work);
  363. struct mei_client_properties *client_props;
  364. int i;
  365. mutex_lock(&dev->device_lock);
  366. bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
  367. dev->open_handle_count = 0;
  368. /*
  369. * Reserving the first three client IDs
  370. * 0: Reserved for MEI Bus Message communications
  371. * 1: Reserved for Watchdog
  372. * 2: Reserved for AMTHI
  373. */
  374. bitmap_set(dev->host_clients_map, 0, 3);
  375. for (i = 0; i < dev->me_clients_num; i++) {
  376. client_props = &dev->me_clients[i].props;
  377. if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid))
  378. mei_amthif_host_init(dev);
  379. else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
  380. mei_wd_host_init(dev);
  381. }
  382. dev->dev_state = MEI_DEV_ENABLED;
  383. mutex_unlock(&dev->device_lock);
  384. }
  385. int mei_host_client_enumerate(struct mei_device *dev)
  386. {
  387. struct mei_msg_hdr *mei_hdr;
  388. struct hbm_props_request *prop_req;
  389. const size_t len = sizeof(struct hbm_props_request);
  390. unsigned long next_client_index;
  391. u8 client_num;
  392. client_num = dev->me_client_presentation_num;
  393. next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
  394. dev->me_client_index);
  395. /* We got all client properties */
  396. if (next_client_index == MEI_CLIENTS_MAX) {
  397. schedule_work(&dev->init_work);
  398. return 0;
  399. }
  400. dev->me_clients[client_num].client_id = next_client_index;
  401. dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
  402. mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
  403. prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
  404. memset(prop_req, 0, sizeof(struct hbm_props_request));
  405. prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
  406. prop_req->address = next_client_index;
  407. if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req,
  408. mei_hdr->length)) {
  409. dev->dev_state = MEI_DEV_RESETING;
  410. dev_err(&dev->pdev->dev, "Properties request command failed\n");
  411. mei_reset(dev, 1);
  412. return -EIO;
  413. }
  414. dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
  415. dev->me_client_index = next_client_index;
  416. return 0;
  417. }
  418. /**
  419. * mei_init_file_private - initializes private file structure.
  420. *
  421. * @priv: private file structure to be initialized
  422. * @file: the file structure
  423. */
  424. void mei_cl_init(struct mei_cl *priv, struct mei_device *dev)
  425. {
  426. memset(priv, 0, sizeof(struct mei_cl));
  427. init_waitqueue_head(&priv->wait);
  428. init_waitqueue_head(&priv->rx_wait);
  429. init_waitqueue_head(&priv->tx_wait);
  430. INIT_LIST_HEAD(&priv->link);
  431. priv->reading_state = MEI_IDLE;
  432. priv->writing_state = MEI_IDLE;
  433. priv->dev = dev;
  434. }
  435. int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid)
  436. {
  437. int i, res = -ENOENT;
  438. for (i = 0; i < dev->me_clients_num; ++i)
  439. if (uuid_le_cmp(*cuuid,
  440. dev->me_clients[i].props.protocol_name) == 0) {
  441. res = i;
  442. break;
  443. }
  444. return res;
  445. }
  446. /**
  447. * mei_me_cl_link - create link between host and me clinet and add
  448. * me_cl to the list
  449. *
  450. * @dev: the device structure
  451. * @cl: link between me and host client assocated with opened file descriptor
  452. * @cuuid: uuid of ME client
  453. * @client_id: id of the host client
  454. *
  455. * returns ME client index if ME client
  456. * -EINVAL on incorrect values
  457. * -ENONET if client not found
  458. */
  459. int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl,
  460. const uuid_le *cuuid, u8 host_cl_id)
  461. {
  462. int i;
  463. if (!dev || !cl || !cuuid)
  464. return -EINVAL;
  465. /* check for valid client id */
  466. i = mei_me_cl_by_uuid(dev, cuuid);
  467. if (i >= 0) {
  468. cl->me_client_id = dev->me_clients[i].client_id;
  469. cl->state = MEI_FILE_CONNECTING;
  470. cl->host_client_id = host_cl_id;
  471. list_add_tail(&cl->link, &dev->file_list);
  472. return (u8)i;
  473. }
  474. return -ENOENT;
  475. }
  476. /**
  477. * mei_me_cl_unlink - remove me_cl from the list
  478. *
  479. * @dev: the device structure
  480. * @host_client_id: host client id to be removed
  481. */
  482. void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl)
  483. {
  484. struct mei_cl *pos, *next;
  485. list_for_each_entry_safe(pos, next, &dev->file_list, link) {
  486. if (cl->host_client_id == pos->host_client_id) {
  487. dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
  488. pos->host_client_id, pos->me_client_id);
  489. list_del_init(&pos->link);
  490. break;
  491. }
  492. }
  493. }
  494. /**
  495. * mei_alloc_file_private - allocates a private file structure and sets it up.
  496. * @file: the file structure
  497. *
  498. * returns The allocated file or NULL on failure
  499. */
  500. struct mei_cl *mei_cl_allocate(struct mei_device *dev)
  501. {
  502. struct mei_cl *cl;
  503. cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
  504. if (!cl)
  505. return NULL;
  506. mei_cl_init(cl, dev);
  507. return cl;
  508. }
  509. /**
  510. * mei_disconnect_host_client - sends disconnect message to fw from host client.
  511. *
  512. * @dev: the device structure
  513. * @cl: private data of the file object
  514. *
  515. * Locking: called under "dev->device_lock" lock
  516. *
  517. * returns 0 on success, <0 on failure.
  518. */
  519. int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
  520. {
  521. struct mei_cl_cb *cb;
  522. int rets, err;
  523. if (!dev || !cl)
  524. return -ENODEV;
  525. if (cl->state != MEI_FILE_DISCONNECTING)
  526. return 0;
  527. cb = mei_io_cb_init(cl, NULL);
  528. if (!cb)
  529. return -ENOMEM;
  530. cb->fop_type = MEI_FOP_CLOSE;
  531. if (dev->mei_host_buffer_is_empty) {
  532. dev->mei_host_buffer_is_empty = false;
  533. if (mei_disconnect(dev, cl)) {
  534. rets = -ENODEV;
  535. dev_dbg(&dev->pdev->dev, "failed to call mei_disconnect.\n");
  536. goto free;
  537. }
  538. mdelay(10); /* Wait for hardware disconnection ready */
  539. list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
  540. } else {
  541. dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
  542. list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
  543. }
  544. mutex_unlock(&dev->device_lock);
  545. err = wait_event_timeout(dev->wait_recvd_msg,
  546. MEI_FILE_DISCONNECTED == cl->state,
  547. mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
  548. mutex_lock(&dev->device_lock);
  549. if (MEI_FILE_DISCONNECTED == cl->state) {
  550. rets = 0;
  551. dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
  552. } else {
  553. rets = -ENODEV;
  554. if (MEI_FILE_DISCONNECTED != cl->state)
  555. dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
  556. if (err)
  557. dev_dbg(&dev->pdev->dev,
  558. "wait failed disconnect err=%08x\n",
  559. err);
  560. dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
  561. }
  562. mei_io_list_flush(&dev->ctrl_rd_list, cl);
  563. mei_io_list_flush(&dev->ctrl_wr_list, cl);
  564. free:
  565. mei_io_cb_free(cb);
  566. return rets;
  567. }