client.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  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 <linux/mei.h>
  21. #include "mei_dev.h"
  22. #include "hbm.h"
  23. #include "interface.h"
  24. #include "client.h"
  25. /**
  26. * mei_me_cl_by_uuid - locate index of me client
  27. *
  28. * @dev: mei device
  29. * returns me client index or -ENOENT if not found
  30. */
  31. int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *uuid)
  32. {
  33. int i, res = -ENOENT;
  34. for (i = 0; i < dev->me_clients_num; ++i)
  35. if (uuid_le_cmp(*uuid,
  36. dev->me_clients[i].props.protocol_name) == 0) {
  37. res = i;
  38. break;
  39. }
  40. return res;
  41. }
  42. /**
  43. * mei_me_cl_by_id return index to me_clients for client_id
  44. *
  45. * @dev: the device structure
  46. * @client_id: me client id
  47. *
  48. * Locking: called under "dev->device_lock" lock
  49. *
  50. * returns index on success, -ENOENT on failure.
  51. */
  52. int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
  53. {
  54. int i;
  55. for (i = 0; i < dev->me_clients_num; i++)
  56. if (dev->me_clients[i].client_id == client_id)
  57. break;
  58. if (WARN_ON(dev->me_clients[i].client_id != client_id))
  59. return -ENOENT;
  60. if (i == dev->me_clients_num)
  61. return -ENOENT;
  62. return i;
  63. }
  64. /**
  65. * mei_io_list_flush - removes list entry belonging to cl.
  66. *
  67. * @list: An instance of our list structure
  68. * @cl: host client
  69. */
  70. void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
  71. {
  72. struct mei_cl_cb *cb;
  73. struct mei_cl_cb *next;
  74. list_for_each_entry_safe(cb, next, &list->list, list) {
  75. if (cb->cl && mei_cl_cmp_id(cl, cb->cl))
  76. list_del(&cb->list);
  77. }
  78. }
  79. /**
  80. * mei_io_cb_free - free mei_cb_private related memory
  81. *
  82. * @cb: mei callback struct
  83. */
  84. void mei_io_cb_free(struct mei_cl_cb *cb)
  85. {
  86. if (cb == NULL)
  87. return;
  88. kfree(cb->request_buffer.data);
  89. kfree(cb->response_buffer.data);
  90. kfree(cb);
  91. }
  92. /**
  93. * mei_io_cb_init - allocate and initialize io callback
  94. *
  95. * @cl - mei client
  96. * @file: pointer to file structure
  97. *
  98. * returns mei_cl_cb pointer or NULL;
  99. */
  100. struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
  101. {
  102. struct mei_cl_cb *cb;
  103. cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
  104. if (!cb)
  105. return NULL;
  106. mei_io_list_init(cb);
  107. cb->file_object = fp;
  108. cb->cl = cl;
  109. cb->buf_idx = 0;
  110. return cb;
  111. }
  112. /**
  113. * mei_io_cb_alloc_req_buf - allocate request buffer
  114. *
  115. * @cb - io callback structure
  116. * @size: size of the buffer
  117. *
  118. * returns 0 on success
  119. * -EINVAL if cb is NULL
  120. * -ENOMEM if allocation failed
  121. */
  122. int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
  123. {
  124. if (!cb)
  125. return -EINVAL;
  126. if (length == 0)
  127. return 0;
  128. cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
  129. if (!cb->request_buffer.data)
  130. return -ENOMEM;
  131. cb->request_buffer.size = length;
  132. return 0;
  133. }
  134. /**
  135. * mei_io_cb_alloc_req_buf - allocate respose buffer
  136. *
  137. * @cb - io callback structure
  138. * @size: size of the buffer
  139. *
  140. * returns 0 on success
  141. * -EINVAL if cb is NULL
  142. * -ENOMEM if allocation failed
  143. */
  144. int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
  145. {
  146. if (!cb)
  147. return -EINVAL;
  148. if (length == 0)
  149. return 0;
  150. cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
  151. if (!cb->response_buffer.data)
  152. return -ENOMEM;
  153. cb->response_buffer.size = length;
  154. return 0;
  155. }
  156. /**
  157. * mei_cl_flush_queues - flushes queue lists belonging to cl.
  158. *
  159. * @dev: the device structure
  160. * @cl: host client
  161. */
  162. int mei_cl_flush_queues(struct mei_cl *cl)
  163. {
  164. if (WARN_ON(!cl || !cl->dev))
  165. return -EINVAL;
  166. dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
  167. mei_io_list_flush(&cl->dev->read_list, cl);
  168. mei_io_list_flush(&cl->dev->write_list, cl);
  169. mei_io_list_flush(&cl->dev->write_waiting_list, cl);
  170. mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
  171. mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
  172. mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
  173. mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
  174. return 0;
  175. }
  176. /**
  177. * mei_cl_init - initializes intialize cl.
  178. *
  179. * @cl: host client to be initialized
  180. * @dev: mei device
  181. */
  182. void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
  183. {
  184. memset(cl, 0, sizeof(struct mei_cl));
  185. init_waitqueue_head(&cl->wait);
  186. init_waitqueue_head(&cl->rx_wait);
  187. init_waitqueue_head(&cl->tx_wait);
  188. INIT_LIST_HEAD(&cl->link);
  189. cl->reading_state = MEI_IDLE;
  190. cl->writing_state = MEI_IDLE;
  191. cl->dev = dev;
  192. }
  193. /**
  194. * mei_cl_allocate - allocates cl structure and sets it up.
  195. *
  196. * @dev: mei device
  197. * returns The allocated file or NULL on failure
  198. */
  199. struct mei_cl *mei_cl_allocate(struct mei_device *dev)
  200. {
  201. struct mei_cl *cl;
  202. cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
  203. if (!cl)
  204. return NULL;
  205. mei_cl_init(cl, dev);
  206. return cl;
  207. }
  208. /**
  209. * mei_cl_find_read_cb - find this cl's callback in the read list
  210. *
  211. * @dev: device structure
  212. * returns cb on success, NULL on error
  213. */
  214. struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
  215. {
  216. struct mei_device *dev = cl->dev;
  217. struct mei_cl_cb *cb = NULL;
  218. struct mei_cl_cb *next = NULL;
  219. list_for_each_entry_safe(cb, next, &dev->read_list.list, list)
  220. if (mei_cl_cmp_id(cl, cb->cl))
  221. return cb;
  222. return NULL;
  223. }
  224. /**
  225. * mei_me_cl_link - create link between host and me clinet and add
  226. * me_cl to the list
  227. *
  228. * @cl: link between me and host client assocated with opened file descriptor
  229. * @uuid: uuid of ME client
  230. * @client_id: id of the host client
  231. *
  232. * returns ME client index if ME client
  233. * -EINVAL on incorrect values
  234. * -ENONET if client not found
  235. */
  236. int mei_cl_link_me(struct mei_cl *cl, const uuid_le *uuid, u8 host_cl_id)
  237. {
  238. struct mei_device *dev;
  239. int i;
  240. if (WARN_ON(!cl || !cl->dev || !uuid))
  241. return -EINVAL;
  242. dev = cl->dev;
  243. /* check for valid client id */
  244. i = mei_me_cl_by_uuid(dev, uuid);
  245. if (i >= 0) {
  246. cl->me_client_id = dev->me_clients[i].client_id;
  247. cl->state = MEI_FILE_CONNECTING;
  248. cl->host_client_id = host_cl_id;
  249. list_add_tail(&cl->link, &dev->file_list);
  250. return (u8)i;
  251. }
  252. return -ENOENT;
  253. }
  254. /**
  255. * mei_cl_unlink - remove me_cl from the list
  256. *
  257. * @dev: the device structure
  258. * @host_client_id: host client id to be removed
  259. */
  260. int mei_cl_unlink(struct mei_cl *cl)
  261. {
  262. struct mei_device *dev;
  263. struct mei_cl *pos, *next;
  264. if (WARN_ON(!cl || !cl->dev))
  265. return -EINVAL;
  266. dev = cl->dev;
  267. list_for_each_entry_safe(pos, next, &dev->file_list, link) {
  268. if (cl->host_client_id == pos->host_client_id) {
  269. dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
  270. pos->host_client_id, pos->me_client_id);
  271. list_del_init(&pos->link);
  272. break;
  273. }
  274. }
  275. return 0;
  276. }
  277. void mei_host_client_init(struct work_struct *work)
  278. {
  279. struct mei_device *dev = container_of(work,
  280. struct mei_device, init_work);
  281. struct mei_client_properties *client_props;
  282. int i;
  283. mutex_lock(&dev->device_lock);
  284. bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
  285. dev->open_handle_count = 0;
  286. /*
  287. * Reserving the first three client IDs
  288. * 0: Reserved for MEI Bus Message communications
  289. * 1: Reserved for Watchdog
  290. * 2: Reserved for AMTHI
  291. */
  292. bitmap_set(dev->host_clients_map, 0, 3);
  293. for (i = 0; i < dev->me_clients_num; i++) {
  294. client_props = &dev->me_clients[i].props;
  295. if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid))
  296. mei_amthif_host_init(dev);
  297. else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
  298. mei_wd_host_init(dev);
  299. }
  300. dev->dev_state = MEI_DEV_ENABLED;
  301. mutex_unlock(&dev->device_lock);
  302. }
  303. /**
  304. * mei_cl_disconnect - disconnect host clinet form the me one
  305. *
  306. * @cl: host client
  307. *
  308. * Locking: called under "dev->device_lock" lock
  309. *
  310. * returns 0 on success, <0 on failure.
  311. */
  312. int mei_cl_disconnect(struct mei_cl *cl)
  313. {
  314. struct mei_device *dev;
  315. struct mei_cl_cb *cb;
  316. int rets, err;
  317. if (WARN_ON(!cl || !cl->dev))
  318. return -ENODEV;
  319. dev = cl->dev;
  320. if (cl->state != MEI_FILE_DISCONNECTING)
  321. return 0;
  322. cb = mei_io_cb_init(cl, NULL);
  323. if (!cb)
  324. return -ENOMEM;
  325. cb->fop_type = MEI_FOP_CLOSE;
  326. if (dev->mei_host_buffer_is_empty) {
  327. dev->mei_host_buffer_is_empty = false;
  328. if (mei_hbm_cl_disconnect_req(dev, cl)) {
  329. rets = -ENODEV;
  330. dev_err(&dev->pdev->dev, "failed to disconnect.\n");
  331. goto free;
  332. }
  333. mdelay(10); /* Wait for hardware disconnection ready */
  334. list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
  335. } else {
  336. dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
  337. list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
  338. }
  339. mutex_unlock(&dev->device_lock);
  340. err = wait_event_timeout(dev->wait_recvd_msg,
  341. MEI_FILE_DISCONNECTED == cl->state,
  342. mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
  343. mutex_lock(&dev->device_lock);
  344. if (MEI_FILE_DISCONNECTED == cl->state) {
  345. rets = 0;
  346. dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
  347. } else {
  348. rets = -ENODEV;
  349. if (MEI_FILE_DISCONNECTED != cl->state)
  350. dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
  351. if (err)
  352. dev_dbg(&dev->pdev->dev,
  353. "wait failed disconnect err=%08x\n",
  354. err);
  355. dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
  356. }
  357. mei_io_list_flush(&dev->ctrl_rd_list, cl);
  358. mei_io_list_flush(&dev->ctrl_wr_list, cl);
  359. free:
  360. mei_io_cb_free(cb);
  361. return rets;
  362. }
  363. /**
  364. * mei_cl_is_other_connecting - checks if other
  365. * client with the same me client id is connecting
  366. *
  367. * @cl: private data of the file object
  368. *
  369. * returns ture if other client is connected, 0 - otherwise.
  370. */
  371. bool mei_cl_is_other_connecting(struct mei_cl *cl)
  372. {
  373. struct mei_device *dev;
  374. struct mei_cl *pos;
  375. struct mei_cl *next;
  376. if (WARN_ON(!cl || !cl->dev))
  377. return false;
  378. dev = cl->dev;
  379. list_for_each_entry_safe(pos, next, &dev->file_list, link) {
  380. if ((pos->state == MEI_FILE_CONNECTING) &&
  381. (pos != cl) && cl->me_client_id == pos->me_client_id)
  382. return true;
  383. }
  384. return false;
  385. }
  386. /**
  387. * mei_cl_connect - connect host clinet to the me one
  388. *
  389. * @cl: host client
  390. *
  391. * Locking: called under "dev->device_lock" lock
  392. *
  393. * returns 0 on success, <0 on failure.
  394. */
  395. int mei_cl_connect(struct mei_cl *cl, struct file *file)
  396. {
  397. struct mei_device *dev;
  398. struct mei_cl_cb *cb;
  399. long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
  400. int rets;
  401. if (WARN_ON(!cl || !cl->dev))
  402. return -ENODEV;
  403. dev = cl->dev;
  404. cb = mei_io_cb_init(cl, file);
  405. if (!cb) {
  406. rets = -ENOMEM;
  407. goto out;
  408. }
  409. cb->fop_type = MEI_FOP_IOCTL;
  410. if (dev->mei_host_buffer_is_empty &&
  411. !mei_cl_is_other_connecting(cl)) {
  412. dev->mei_host_buffer_is_empty = false;
  413. if (mei_hbm_cl_connect_req(dev, cl)) {
  414. rets = -ENODEV;
  415. goto out;
  416. }
  417. cl->timer_count = MEI_CONNECT_TIMEOUT;
  418. list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
  419. } else {
  420. list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
  421. }
  422. mutex_unlock(&dev->device_lock);
  423. rets = wait_event_timeout(dev->wait_recvd_msg,
  424. (cl->state == MEI_FILE_CONNECTED ||
  425. cl->state == MEI_FILE_DISCONNECTED),
  426. timeout * HZ);
  427. mutex_lock(&dev->device_lock);
  428. if (cl->state != MEI_FILE_CONNECTED) {
  429. rets = -EFAULT;
  430. mei_io_list_flush(&dev->ctrl_rd_list, cl);
  431. mei_io_list_flush(&dev->ctrl_wr_list, cl);
  432. goto out;
  433. }
  434. rets = cl->status;
  435. out:
  436. mei_io_cb_free(cb);
  437. return rets;
  438. }
  439. /**
  440. * mei_cl_flow_ctrl_creds - checks flow_control credits for cl.
  441. *
  442. * @dev: the device structure
  443. * @cl: private data of the file object
  444. *
  445. * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
  446. * -ENOENT if mei_cl is not present
  447. * -EINVAL if single_recv_buf == 0
  448. */
  449. int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
  450. {
  451. struct mei_device *dev;
  452. int i;
  453. if (WARN_ON(!cl || !cl->dev))
  454. return -EINVAL;
  455. dev = cl->dev;
  456. if (!dev->me_clients_num)
  457. return 0;
  458. if (cl->mei_flow_ctrl_creds > 0)
  459. return 1;
  460. for (i = 0; i < dev->me_clients_num; i++) {
  461. struct mei_me_client *me_cl = &dev->me_clients[i];
  462. if (me_cl->client_id == cl->me_client_id) {
  463. if (me_cl->mei_flow_ctrl_creds) {
  464. if (WARN_ON(me_cl->props.single_recv_buf == 0))
  465. return -EINVAL;
  466. return 1;
  467. } else {
  468. return 0;
  469. }
  470. }
  471. }
  472. return -ENOENT;
  473. }
  474. /**
  475. * mei_cl_flow_ctrl_reduce - reduces flow_control.
  476. *
  477. * @dev: the device structure
  478. * @cl: private data of the file object
  479. * @returns
  480. * 0 on success
  481. * -ENOENT when me client is not found
  482. * -EINVAL when ctrl credits are <= 0
  483. */
  484. int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
  485. {
  486. struct mei_device *dev;
  487. int i;
  488. if (WARN_ON(!cl || !cl->dev))
  489. return -EINVAL;
  490. dev = cl->dev;
  491. if (!dev->me_clients_num)
  492. return -ENOENT;
  493. for (i = 0; i < dev->me_clients_num; i++) {
  494. struct mei_me_client *me_cl = &dev->me_clients[i];
  495. if (me_cl->client_id == cl->me_client_id) {
  496. if (me_cl->props.single_recv_buf != 0) {
  497. if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
  498. return -EINVAL;
  499. dev->me_clients[i].mei_flow_ctrl_creds--;
  500. } else {
  501. if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
  502. return -EINVAL;
  503. cl->mei_flow_ctrl_creds--;
  504. }
  505. return 0;
  506. }
  507. }
  508. return -ENOENT;
  509. }
  510. /**
  511. * mei_cl_start_read - the start read client message function.
  512. *
  513. * @cl: host client
  514. *
  515. * returns 0 on success, <0 on failure.
  516. */
  517. int mei_cl_read_start(struct mei_cl *cl)
  518. {
  519. struct mei_device *dev;
  520. struct mei_cl_cb *cb;
  521. int rets;
  522. int i;
  523. if (WARN_ON(!cl || !cl->dev))
  524. return -ENODEV;
  525. dev = cl->dev;
  526. if (cl->state != MEI_FILE_CONNECTED)
  527. return -ENODEV;
  528. if (dev->dev_state != MEI_DEV_ENABLED)
  529. return -ENODEV;
  530. if (cl->read_pending || cl->read_cb) {
  531. dev_dbg(&dev->pdev->dev, "read is pending.\n");
  532. return -EBUSY;
  533. }
  534. i = mei_me_cl_by_id(dev, cl->me_client_id);
  535. if (i < 0) {
  536. dev_err(&dev->pdev->dev, "no such me client %d\n",
  537. cl->me_client_id);
  538. return -ENODEV;
  539. }
  540. cb = mei_io_cb_init(cl, NULL);
  541. if (!cb)
  542. return -ENOMEM;
  543. rets = mei_io_cb_alloc_resp_buf(cb,
  544. dev->me_clients[i].props.max_msg_length);
  545. if (rets)
  546. goto err;
  547. cb->fop_type = MEI_FOP_READ;
  548. cl->read_cb = cb;
  549. if (dev->mei_host_buffer_is_empty) {
  550. dev->mei_host_buffer_is_empty = false;
  551. if (mei_hbm_cl_flow_control_req(dev, cl)) {
  552. rets = -ENODEV;
  553. goto err;
  554. }
  555. list_add_tail(&cb->list, &dev->read_list.list);
  556. } else {
  557. list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
  558. }
  559. return rets;
  560. err:
  561. mei_io_cb_free(cb);
  562. return rets;
  563. }