2475 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2003-2022, Intel Corporation. All rights reserved.4 * Intel Management Engine Interface (Intel MEI) Linux driver5 */6 7#include <linux/sched/signal.h>8#include <linux/wait.h>9#include <linux/delay.h>10#include <linux/slab.h>11#include <linux/pm_runtime.h>12#include <linux/dma-mapping.h>13 14#include <linux/mei.h>15 16#include "mei_dev.h"17#include "hbm.h"18#include "client.h"19 20/**21 * mei_me_cl_init - initialize me client22 *23 * @me_cl: me client24 */25void mei_me_cl_init(struct mei_me_client *me_cl)26{27 INIT_LIST_HEAD(&me_cl->list);28 kref_init(&me_cl->refcnt);29}30 31/**32 * mei_me_cl_get - increases me client refcount33 *34 * @me_cl: me client35 *36 * Locking: called under "dev->device_lock" lock37 *38 * Return: me client or NULL39 */40struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl)41{42 if (me_cl && kref_get_unless_zero(&me_cl->refcnt))43 return me_cl;44 45 return NULL;46}47 48/**49 * mei_me_cl_release - free me client50 *51 * @ref: me_client refcount52 *53 * Locking: called under "dev->device_lock" lock54 */55static void mei_me_cl_release(struct kref *ref)56{57 struct mei_me_client *me_cl =58 container_of(ref, struct mei_me_client, refcnt);59 60 kfree(me_cl);61}62 63/**64 * mei_me_cl_put - decrease me client refcount and free client if necessary65 *66 * @me_cl: me client67 *68 * Locking: called under "dev->device_lock" lock69 */70void mei_me_cl_put(struct mei_me_client *me_cl)71{72 if (me_cl)73 kref_put(&me_cl->refcnt, mei_me_cl_release);74}75 76/**77 * __mei_me_cl_del - delete me client from the list and decrease78 * reference counter79 *80 * @dev: mei device81 * @me_cl: me client82 *83 * Locking: dev->me_clients_rwsem84 */85static void __mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)86{87 if (!me_cl)88 return;89 90 list_del_init(&me_cl->list);91 mei_me_cl_put(me_cl);92}93 94/**95 * mei_me_cl_del - delete me client from the list and decrease96 * reference counter97 *98 * @dev: mei device99 * @me_cl: me client100 */101void mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)102{103 down_write(&dev->me_clients_rwsem);104 __mei_me_cl_del(dev, me_cl);105 up_write(&dev->me_clients_rwsem);106}107 108/**109 * mei_me_cl_add - add me client to the list110 *111 * @dev: mei device112 * @me_cl: me client113 */114void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl)115{116 down_write(&dev->me_clients_rwsem);117 list_add(&me_cl->list, &dev->me_clients);118 up_write(&dev->me_clients_rwsem);119}120 121/**122 * __mei_me_cl_by_uuid - locate me client by uuid123 * increases ref count124 *125 * @dev: mei device126 * @uuid: me client uuid127 *128 * Return: me client or NULL if not found129 *130 * Locking: dev->me_clients_rwsem131 */132static struct mei_me_client *__mei_me_cl_by_uuid(struct mei_device *dev,133 const uuid_le *uuid)134{135 struct mei_me_client *me_cl;136 const uuid_le *pn;137 138 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));139 140 list_for_each_entry(me_cl, &dev->me_clients, list) {141 pn = &me_cl->props.protocol_name;142 if (uuid_le_cmp(*uuid, *pn) == 0)143 return mei_me_cl_get(me_cl);144 }145 146 return NULL;147}148 149/**150 * mei_me_cl_by_uuid - locate me client by uuid151 * increases ref count152 *153 * @dev: mei device154 * @uuid: me client uuid155 *156 * Return: me client or NULL if not found157 *158 * Locking: dev->me_clients_rwsem159 */160struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,161 const uuid_le *uuid)162{163 struct mei_me_client *me_cl;164 165 down_read(&dev->me_clients_rwsem);166 me_cl = __mei_me_cl_by_uuid(dev, uuid);167 up_read(&dev->me_clients_rwsem);168 169 return me_cl;170}171 172/**173 * mei_me_cl_by_id - locate me client by client id174 * increases ref count175 *176 * @dev: the device structure177 * @client_id: me client id178 *179 * Return: me client or NULL if not found180 *181 * Locking: dev->me_clients_rwsem182 */183struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)184{185 186 struct mei_me_client *__me_cl, *me_cl = NULL;187 188 down_read(&dev->me_clients_rwsem);189 list_for_each_entry(__me_cl, &dev->me_clients, list) {190 if (__me_cl->client_id == client_id) {191 me_cl = mei_me_cl_get(__me_cl);192 break;193 }194 }195 up_read(&dev->me_clients_rwsem);196 197 return me_cl;198}199 200/**201 * __mei_me_cl_by_uuid_id - locate me client by client id and uuid202 * increases ref count203 *204 * @dev: the device structure205 * @uuid: me client uuid206 * @client_id: me client id207 *208 * Return: me client or null if not found209 *210 * Locking: dev->me_clients_rwsem211 */212static struct mei_me_client *__mei_me_cl_by_uuid_id(struct mei_device *dev,213 const uuid_le *uuid, u8 client_id)214{215 struct mei_me_client *me_cl;216 const uuid_le *pn;217 218 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));219 220 list_for_each_entry(me_cl, &dev->me_clients, list) {221 pn = &me_cl->props.protocol_name;222 if (uuid_le_cmp(*uuid, *pn) == 0 &&223 me_cl->client_id == client_id)224 return mei_me_cl_get(me_cl);225 }226 227 return NULL;228}229 230 231/**232 * mei_me_cl_by_uuid_id - locate me client by client id and uuid233 * increases ref count234 *235 * @dev: the device structure236 * @uuid: me client uuid237 * @client_id: me client id238 *239 * Return: me client or null if not found240 */241struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,242 const uuid_le *uuid, u8 client_id)243{244 struct mei_me_client *me_cl;245 246 down_read(&dev->me_clients_rwsem);247 me_cl = __mei_me_cl_by_uuid_id(dev, uuid, client_id);248 up_read(&dev->me_clients_rwsem);249 250 return me_cl;251}252 253/**254 * mei_me_cl_rm_by_uuid - remove all me clients matching uuid255 *256 * @dev: the device structure257 * @uuid: me client uuid258 *259 * Locking: called under "dev->device_lock" lock260 */261void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)262{263 struct mei_me_client *me_cl;264 265 dev_dbg(dev->dev, "remove %pUl\n", uuid);266 267 down_write(&dev->me_clients_rwsem);268 me_cl = __mei_me_cl_by_uuid(dev, uuid);269 __mei_me_cl_del(dev, me_cl);270 mei_me_cl_put(me_cl);271 up_write(&dev->me_clients_rwsem);272}273 274/**275 * mei_me_cl_rm_by_uuid_id - remove all me clients matching client id276 *277 * @dev: the device structure278 * @uuid: me client uuid279 * @id: me client id280 *281 * Locking: called under "dev->device_lock" lock282 */283void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, const uuid_le *uuid, u8 id)284{285 struct mei_me_client *me_cl;286 287 dev_dbg(dev->dev, "remove %pUl %d\n", uuid, id);288 289 down_write(&dev->me_clients_rwsem);290 me_cl = __mei_me_cl_by_uuid_id(dev, uuid, id);291 __mei_me_cl_del(dev, me_cl);292 mei_me_cl_put(me_cl);293 up_write(&dev->me_clients_rwsem);294}295 296/**297 * mei_me_cl_rm_all - remove all me clients298 *299 * @dev: the device structure300 *301 * Locking: called under "dev->device_lock" lock302 */303void mei_me_cl_rm_all(struct mei_device *dev)304{305 struct mei_me_client *me_cl, *next;306 307 down_write(&dev->me_clients_rwsem);308 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list)309 __mei_me_cl_del(dev, me_cl);310 up_write(&dev->me_clients_rwsem);311}312 313/**314 * mei_io_cb_free - free mei_cb_private related memory315 *316 * @cb: mei callback struct317 */318void mei_io_cb_free(struct mei_cl_cb *cb)319{320 if (cb == NULL)321 return;322 323 list_del(&cb->list);324 kvfree(cb->buf.data);325 kfree(cb->ext_hdr);326 kfree(cb);327}328 329/**330 * mei_tx_cb_enqueue - queue tx callback331 *332 * @cb: mei callback struct333 * @head: an instance of list to queue on334 *335 * Locking: called under "dev->device_lock" lock336 */337static inline void mei_tx_cb_enqueue(struct mei_cl_cb *cb,338 struct list_head *head)339{340 list_add_tail(&cb->list, head);341 cb->cl->tx_cb_queued++;342}343 344/**345 * mei_tx_cb_dequeue - dequeue tx callback346 *347 * @cb: mei callback struct to dequeue and free348 *349 * Locking: called under "dev->device_lock" lock350 */351static inline void mei_tx_cb_dequeue(struct mei_cl_cb *cb)352{353 if (!WARN_ON(cb->cl->tx_cb_queued == 0))354 cb->cl->tx_cb_queued--;355 356 mei_io_cb_free(cb);357}358 359/**360 * mei_cl_set_read_by_fp - set pending_read flag to vtag struct for given fp361 *362 * @cl: mei client363 * @fp: pointer to file structure364 *365 * Locking: called under "dev->device_lock" lock366 */367static void mei_cl_set_read_by_fp(const struct mei_cl *cl,368 const struct file *fp)369{370 struct mei_cl_vtag *cl_vtag;371 372 list_for_each_entry(cl_vtag, &cl->vtag_map, list) {373 if (cl_vtag->fp == fp) {374 cl_vtag->pending_read = true;375 return;376 }377 }378}379 380/**381 * mei_io_cb_init - allocate and initialize io callback382 *383 * @cl: mei client384 * @type: operation type385 * @fp: pointer to file structure386 *387 * Return: mei_cl_cb pointer or NULL;388 */389static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl,390 enum mei_cb_file_ops type,391 const struct file *fp)392{393 struct mei_cl_cb *cb;394 395 cb = kzalloc(sizeof(*cb), GFP_KERNEL);396 if (!cb)397 return NULL;398 399 INIT_LIST_HEAD(&cb->list);400 cb->fp = fp;401 cb->cl = cl;402 cb->buf_idx = 0;403 cb->fop_type = type;404 cb->vtag = 0;405 cb->ext_hdr = NULL;406 407 return cb;408}409 410/**411 * mei_io_list_flush_cl - removes cbs belonging to the cl.412 *413 * @head: an instance of our list structure414 * @cl: host client415 */416static void mei_io_list_flush_cl(struct list_head *head,417 const struct mei_cl *cl)418{419 struct mei_cl_cb *cb, *next;420 421 list_for_each_entry_safe(cb, next, head, list) {422 if (cl == cb->cl) {423 list_del_init(&cb->list);424 if (cb->fop_type == MEI_FOP_READ)425 mei_io_cb_free(cb);426 }427 }428}429 430/**431 * mei_io_tx_list_free_cl - removes cb belonging to the cl and free them432 *433 * @head: An instance of our list structure434 * @cl: host client435 * @fp: file pointer (matching cb file object), may be NULL436 */437static void mei_io_tx_list_free_cl(struct list_head *head,438 const struct mei_cl *cl,439 const struct file *fp)440{441 struct mei_cl_cb *cb, *next;442 443 list_for_each_entry_safe(cb, next, head, list) {444 if (cl == cb->cl && (!fp || fp == cb->fp))445 mei_tx_cb_dequeue(cb);446 }447}448 449/**450 * mei_io_list_free_fp - free cb from a list that matches file pointer451 *452 * @head: io list453 * @fp: file pointer (matching cb file object), may be NULL454 */455static void mei_io_list_free_fp(struct list_head *head, const struct file *fp)456{457 struct mei_cl_cb *cb, *next;458 459 list_for_each_entry_safe(cb, next, head, list)460 if (!fp || fp == cb->fp)461 mei_io_cb_free(cb);462}463 464/**465 * mei_cl_free_pending - free pending cb466 *467 * @cl: host client468 */469static void mei_cl_free_pending(struct mei_cl *cl)470{471 struct mei_cl_cb *cb;472 473 cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list);474 mei_io_cb_free(cb);475}476 477/**478 * mei_cl_alloc_cb - a convenient wrapper for allocating read cb479 *480 * @cl: host client481 * @length: size of the buffer482 * @fop_type: operation type483 * @fp: associated file pointer (might be NULL)484 *485 * Return: cb on success and NULL on failure486 */487struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,488 enum mei_cb_file_ops fop_type,489 const struct file *fp)490{491 struct mei_cl_cb *cb;492 493 cb = mei_io_cb_init(cl, fop_type, fp);494 if (!cb)495 return NULL;496 497 if (length == 0)498 return cb;499 500 cb->buf.data = kvmalloc(roundup(length, MEI_SLOT_SIZE), GFP_KERNEL);501 if (!cb->buf.data) {502 mei_io_cb_free(cb);503 return NULL;504 }505 cb->buf.size = length;506 507 return cb;508}509 510/**511 * mei_cl_enqueue_ctrl_wr_cb - a convenient wrapper for allocating512 * and enqueuing of the control commands cb513 *514 * @cl: host client515 * @length: size of the buffer516 * @fop_type: operation type517 * @fp: associated file pointer (might be NULL)518 *519 * Return: cb on success and NULL on failure520 * Locking: called under "dev->device_lock" lock521 */522struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl *cl, size_t length,523 enum mei_cb_file_ops fop_type,524 const struct file *fp)525{526 struct mei_cl_cb *cb;527 528 /* for RX always allocate at least client's mtu */529 if (length)530 length = max_t(size_t, length, mei_cl_mtu(cl));531 532 cb = mei_cl_alloc_cb(cl, length, fop_type, fp);533 if (!cb)534 return NULL;535 536 list_add_tail(&cb->list, &cl->dev->ctrl_wr_list);537 return cb;538}539 540/**541 * mei_cl_read_cb - find this cl's callback in the read list542 * for a specific file543 *544 * @cl: host client545 * @fp: file pointer (matching cb file object), may be NULL546 *547 * Return: cb on success, NULL if cb is not found548 */549struct mei_cl_cb *mei_cl_read_cb(struct mei_cl *cl, const struct file *fp)550{551 struct mei_cl_cb *cb;552 struct mei_cl_cb *ret_cb = NULL;553 554 spin_lock(&cl->rd_completed_lock);555 list_for_each_entry(cb, &cl->rd_completed, list)556 if (!fp || fp == cb->fp) {557 ret_cb = cb;558 break;559 }560 spin_unlock(&cl->rd_completed_lock);561 return ret_cb;562}563 564/**565 * mei_cl_flush_queues - flushes queue lists belonging to cl.566 *567 * @cl: host client568 * @fp: file pointer (matching cb file object), may be NULL569 *570 * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.571 */572int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)573{574 struct mei_device *dev;575 576 if (WARN_ON(!cl || !cl->dev))577 return -EINVAL;578 579 dev = cl->dev;580 581 cl_dbg(dev, cl, "remove list entry belonging to cl\n");582 mei_io_tx_list_free_cl(&cl->dev->write_list, cl, fp);583 mei_io_tx_list_free_cl(&cl->dev->write_waiting_list, cl, fp);584 /* free pending and control cb only in final flush */585 if (!fp) {586 mei_io_list_flush_cl(&cl->dev->ctrl_wr_list, cl);587 mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl);588 mei_cl_free_pending(cl);589 }590 spin_lock(&cl->rd_completed_lock);591 mei_io_list_free_fp(&cl->rd_completed, fp);592 spin_unlock(&cl->rd_completed_lock);593 594 return 0;595}596 597/**598 * mei_cl_init - initializes cl.599 *600 * @cl: host client to be initialized601 * @dev: mei device602 */603static void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)604{605 memset(cl, 0, sizeof(*cl));606 init_waitqueue_head(&cl->wait);607 init_waitqueue_head(&cl->rx_wait);608 init_waitqueue_head(&cl->tx_wait);609 init_waitqueue_head(&cl->ev_wait);610 INIT_LIST_HEAD(&cl->vtag_map);611 spin_lock_init(&cl->rd_completed_lock);612 INIT_LIST_HEAD(&cl->rd_completed);613 INIT_LIST_HEAD(&cl->rd_pending);614 INIT_LIST_HEAD(&cl->link);615 cl->writing_state = MEI_IDLE;616 cl->state = MEI_FILE_UNINITIALIZED;617 cl->dev = dev;618}619 620/**621 * mei_cl_allocate - allocates cl structure and sets it up.622 *623 * @dev: mei device624 * Return: The allocated file or NULL on failure625 */626struct mei_cl *mei_cl_allocate(struct mei_device *dev)627{628 struct mei_cl *cl;629 630 cl = kmalloc(sizeof(*cl), GFP_KERNEL);631 if (!cl)632 return NULL;633 634 mei_cl_init(cl, dev);635 636 return cl;637}638 639/**640 * mei_cl_link - allocate host id in the host map641 *642 * @cl: host client643 *644 * Return: 0 on success645 * -EINVAL on incorrect values646 * -EMFILE if open count exceeded.647 */648int mei_cl_link(struct mei_cl *cl)649{650 struct mei_device *dev;651 int id;652 653 if (WARN_ON(!cl || !cl->dev))654 return -EINVAL;655 656 dev = cl->dev;657 658 id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX);659 if (id >= MEI_CLIENTS_MAX) {660 dev_err(dev->dev, "id exceeded %d", MEI_CLIENTS_MAX);661 return -EMFILE;662 }663 664 if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {665 dev_err(dev->dev, "open_handle_count exceeded %d",666 MEI_MAX_OPEN_HANDLE_COUNT);667 return -EMFILE;668 }669 670 dev->open_handle_count++;671 672 cl->host_client_id = id;673 list_add_tail(&cl->link, &dev->file_list);674 675 set_bit(id, dev->host_clients_map);676 677 cl->state = MEI_FILE_INITIALIZING;678 679 cl_dbg(dev, cl, "link cl\n");680 return 0;681}682 683/**684 * mei_cl_unlink - remove host client from the list685 *686 * @cl: host client687 *688 * Return: always 0689 */690int mei_cl_unlink(struct mei_cl *cl)691{692 struct mei_device *dev;693 694 /* don't shout on error exit path */695 if (!cl)696 return 0;697 698 if (WARN_ON(!cl->dev))699 return 0;700 701 dev = cl->dev;702 703 cl_dbg(dev, cl, "unlink client");704 705 if (cl->state == MEI_FILE_UNINITIALIZED)706 return 0;707 708 if (dev->open_handle_count > 0)709 dev->open_handle_count--;710 711 /* never clear the 0 bit */712 if (cl->host_client_id)713 clear_bit(cl->host_client_id, dev->host_clients_map);714 715 list_del_init(&cl->link);716 717 cl->state = MEI_FILE_UNINITIALIZED;718 cl->writing_state = MEI_IDLE;719 720 WARN_ON(!list_empty(&cl->rd_completed) ||721 !list_empty(&cl->rd_pending) ||722 !list_empty(&cl->link));723 724 return 0;725}726 727void mei_host_client_init(struct mei_device *dev)728{729 mei_set_devstate(dev, MEI_DEV_ENABLED);730 dev->reset_count = 0;731 732 schedule_work(&dev->bus_rescan_work);733 734 pm_runtime_mark_last_busy(dev->dev);735 dev_dbg(dev->dev, "rpm: autosuspend\n");736 pm_request_autosuspend(dev->dev);737}738 739/**740 * mei_hbuf_acquire - try to acquire host buffer741 *742 * @dev: the device structure743 * Return: true if host buffer was acquired744 */745bool mei_hbuf_acquire(struct mei_device *dev)746{747 if (mei_pg_state(dev) == MEI_PG_ON ||748 mei_pg_in_transition(dev)) {749 dev_dbg(dev->dev, "device is in pg\n");750 return false;751 }752 753 if (!dev->hbuf_is_ready) {754 dev_dbg(dev->dev, "hbuf is not ready\n");755 return false;756 }757 758 dev->hbuf_is_ready = false;759 760 return true;761}762 763/**764 * mei_cl_wake_all - wake up readers, writers and event waiters so765 * they can be interrupted766 *767 * @cl: host client768 */769static void mei_cl_wake_all(struct mei_cl *cl)770{771 struct mei_device *dev = cl->dev;772 773 /* synchronized under device mutex */774 if (waitqueue_active(&cl->rx_wait)) {775 cl_dbg(dev, cl, "Waking up reading client!\n");776 wake_up_interruptible(&cl->rx_wait);777 }778 /* synchronized under device mutex */779 if (waitqueue_active(&cl->tx_wait)) {780 cl_dbg(dev, cl, "Waking up writing client!\n");781 wake_up_interruptible(&cl->tx_wait);782 }783 /* synchronized under device mutex */784 if (waitqueue_active(&cl->ev_wait)) {785 cl_dbg(dev, cl, "Waking up waiting for event clients!\n");786 wake_up_interruptible(&cl->ev_wait);787 }788 /* synchronized under device mutex */789 if (waitqueue_active(&cl->wait)) {790 cl_dbg(dev, cl, "Waking up ctrl write clients!\n");791 wake_up(&cl->wait);792 }793}794 795/**796 * mei_cl_set_disconnected - set disconnected state and clear797 * associated states and resources798 *799 * @cl: host client800 */801static void mei_cl_set_disconnected(struct mei_cl *cl)802{803 struct mei_device *dev = cl->dev;804 805 if (cl->state == MEI_FILE_DISCONNECTED ||806 cl->state <= MEI_FILE_INITIALIZING)807 return;808 809 cl->state = MEI_FILE_DISCONNECTED;810 mei_io_tx_list_free_cl(&dev->write_list, cl, NULL);811 mei_io_tx_list_free_cl(&dev->write_waiting_list, cl, NULL);812 mei_io_list_flush_cl(&dev->ctrl_rd_list, cl);813 mei_io_list_flush_cl(&dev->ctrl_wr_list, cl);814 mei_cl_wake_all(cl);815 cl->rx_flow_ctrl_creds = 0;816 cl->tx_flow_ctrl_creds = 0;817 cl->timer_count = 0;818 819 if (!cl->me_cl)820 return;821 822 if (!WARN_ON(cl->me_cl->connect_count == 0))823 cl->me_cl->connect_count--;824 825 if (cl->me_cl->connect_count == 0)826 cl->me_cl->tx_flow_ctrl_creds = 0;827 828 mei_me_cl_put(cl->me_cl);829 cl->me_cl = NULL;830}831 832static int mei_cl_set_connecting(struct mei_cl *cl, struct mei_me_client *me_cl)833{834 if (!mei_me_cl_get(me_cl))835 return -ENOENT;836 837 /* only one connection is allowed for fixed address clients */838 if (me_cl->props.fixed_address) {839 if (me_cl->connect_count) {840 mei_me_cl_put(me_cl);841 return -EBUSY;842 }843 }844 845 cl->me_cl = me_cl;846 cl->state = MEI_FILE_CONNECTING;847 cl->me_cl->connect_count++;848 849 return 0;850}851 852/*853 * mei_cl_send_disconnect - send disconnect request854 *855 * @cl: host client856 * @cb: callback block857 *858 * Return: 0, OK; otherwise, error.859 */860static int mei_cl_send_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb)861{862 struct mei_device *dev;863 int ret;864 865 dev = cl->dev;866 867 ret = mei_hbm_cl_disconnect_req(dev, cl);868 cl->status = ret;869 if (ret) {870 cl->state = MEI_FILE_DISCONNECT_REPLY;871 return ret;872 }873 874 list_move_tail(&cb->list, &dev->ctrl_rd_list);875 cl->timer_count = dev->timeouts.connect;876 mei_schedule_stall_timer(dev);877 878 return 0;879}880 881/**882 * mei_cl_irq_disconnect - processes close related operation from883 * interrupt thread context - send disconnect request884 *885 * @cl: client886 * @cb: callback block.887 * @cmpl_list: complete list.888 *889 * Return: 0, OK; otherwise, error.890 */891int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,892 struct list_head *cmpl_list)893{894 struct mei_device *dev = cl->dev;895 u32 msg_slots;896 int slots;897 int ret;898 899 msg_slots = mei_hbm2slots(sizeof(struct hbm_client_connect_request));900 slots = mei_hbuf_empty_slots(dev);901 if (slots < 0)902 return -EOVERFLOW;903 904 if ((u32)slots < msg_slots)905 return -EMSGSIZE;906 907 ret = mei_cl_send_disconnect(cl, cb);908 if (ret)909 list_move_tail(&cb->list, cmpl_list);910 911 return ret;912}913 914/**915 * __mei_cl_disconnect - disconnect host client from the me one916 * internal function runtime pm has to be already acquired917 *918 * @cl: host client919 *920 * Return: 0 on success, <0 on failure.921 */922static int __mei_cl_disconnect(struct mei_cl *cl)923{924 struct mei_device *dev;925 struct mei_cl_cb *cb;926 int rets;927 928 dev = cl->dev;929 930 cl->state = MEI_FILE_DISCONNECTING;931 932 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT, NULL);933 if (!cb) {934 rets = -ENOMEM;935 goto out;936 }937 938 if (mei_hbuf_acquire(dev)) {939 rets = mei_cl_send_disconnect(cl, cb);940 if (rets) {941 cl_err(dev, cl, "failed to disconnect.\n");942 goto out;943 }944 }945 946 mutex_unlock(&dev->device_lock);947 wait_event_timeout(cl->wait,948 cl->state == MEI_FILE_DISCONNECT_REPLY ||949 cl->state == MEI_FILE_DISCONNECTED,950 dev->timeouts.cl_connect);951 mutex_lock(&dev->device_lock);952 953 rets = cl->status;954 if (cl->state != MEI_FILE_DISCONNECT_REPLY &&955 cl->state != MEI_FILE_DISCONNECTED) {956 cl_dbg(dev, cl, "timeout on disconnect from FW client.\n");957 rets = -ETIME;958 }959 960out:961 /* we disconnect also on error */962 mei_cl_set_disconnected(cl);963 if (!rets)964 cl_dbg(dev, cl, "successfully disconnected from FW client.\n");965 966 mei_io_cb_free(cb);967 return rets;968}969 970/**971 * mei_cl_disconnect - disconnect host client from the me one972 *973 * @cl: host client974 *975 * Locking: called under "dev->device_lock" lock976 *977 * Return: 0 on success, <0 on failure.978 */979int mei_cl_disconnect(struct mei_cl *cl)980{981 struct mei_device *dev;982 int rets;983 984 if (WARN_ON(!cl || !cl->dev))985 return -ENODEV;986 987 dev = cl->dev;988 989 cl_dbg(dev, cl, "disconnecting");990 991 if (!mei_cl_is_connected(cl))992 return 0;993 994 if (mei_cl_is_fixed_address(cl)) {995 mei_cl_set_disconnected(cl);996 return 0;997 }998 999 if (dev->dev_state == MEI_DEV_POWERING_DOWN ||1000 dev->dev_state == MEI_DEV_POWER_DOWN) {1001 cl_dbg(dev, cl, "Device is powering down, don't bother with disconnection\n");1002 mei_cl_set_disconnected(cl);1003 return 0;1004 }1005 1006 rets = pm_runtime_get(dev->dev);1007 if (rets < 0 && rets != -EINPROGRESS) {1008 pm_runtime_put_noidle(dev->dev);1009 cl_err(dev, cl, "rpm: get failed %d\n", rets);1010 return rets;1011 }1012 1013 rets = __mei_cl_disconnect(cl);1014 1015 cl_dbg(dev, cl, "rpm: autosuspend\n");1016 pm_runtime_mark_last_busy(dev->dev);1017 pm_runtime_put_autosuspend(dev->dev);1018 1019 return rets;1020}1021 1022 1023/**1024 * mei_cl_is_other_connecting - checks if other1025 * client with the same me client id is connecting1026 *1027 * @cl: private data of the file object1028 *1029 * Return: true if other client is connected, false - otherwise.1030 */1031static bool mei_cl_is_other_connecting(struct mei_cl *cl)1032{1033 struct mei_device *dev;1034 struct mei_cl_cb *cb;1035 1036 dev = cl->dev;1037 1038 list_for_each_entry(cb, &dev->ctrl_rd_list, list) {1039 if (cb->fop_type == MEI_FOP_CONNECT &&1040 mei_cl_me_id(cl) == mei_cl_me_id(cb->cl))1041 return true;1042 }1043 1044 return false;1045}1046 1047/**1048 * mei_cl_send_connect - send connect request1049 *1050 * @cl: host client1051 * @cb: callback block1052 *1053 * Return: 0, OK; otherwise, error.1054 */1055static int mei_cl_send_connect(struct mei_cl *cl, struct mei_cl_cb *cb)1056{1057 struct mei_device *dev;1058 int ret;1059 1060 dev = cl->dev;1061 1062 ret = mei_hbm_cl_connect_req(dev, cl);1063 cl->status = ret;1064 if (ret) {1065 cl->state = MEI_FILE_DISCONNECT_REPLY;1066 return ret;1067 }1068 1069 list_move_tail(&cb->list, &dev->ctrl_rd_list);1070 cl->timer_count = dev->timeouts.connect;1071 mei_schedule_stall_timer(dev);1072 return 0;1073}1074 1075/**1076 * mei_cl_irq_connect - send connect request in irq_thread context1077 *1078 * @cl: host client1079 * @cb: callback block1080 * @cmpl_list: complete list1081 *1082 * Return: 0, OK; otherwise, error.1083 */1084int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,1085 struct list_head *cmpl_list)1086{1087 struct mei_device *dev = cl->dev;1088 u32 msg_slots;1089 int slots;1090 int rets;1091 1092 if (mei_cl_is_other_connecting(cl))1093 return 0;1094 1095 msg_slots = mei_hbm2slots(sizeof(struct hbm_client_connect_request));1096 slots = mei_hbuf_empty_slots(dev);1097 if (slots < 0)1098 return -EOVERFLOW;1099 1100 if ((u32)slots < msg_slots)1101 return -EMSGSIZE;1102 1103 rets = mei_cl_send_connect(cl, cb);1104 if (rets)1105 list_move_tail(&cb->list, cmpl_list);1106 1107 return rets;1108}1109 1110/**1111 * mei_cl_connect - connect host client to the me one1112 *1113 * @cl: host client1114 * @me_cl: me client1115 * @fp: pointer to file structure1116 *1117 * Locking: called under "dev->device_lock" lock1118 *1119 * Return: 0 on success, <0 on failure.1120 */1121int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,1122 const struct file *fp)1123{1124 struct mei_device *dev;1125 struct mei_cl_cb *cb;1126 int rets;1127 1128 if (WARN_ON(!cl || !cl->dev || !me_cl))1129 return -ENODEV;1130 1131 dev = cl->dev;1132 1133 rets = mei_cl_set_connecting(cl, me_cl);1134 if (rets)1135 goto nortpm;1136 1137 if (mei_cl_is_fixed_address(cl)) {1138 cl->state = MEI_FILE_CONNECTED;1139 rets = 0;1140 goto nortpm;1141 }1142 1143 rets = pm_runtime_get(dev->dev);1144 if (rets < 0 && rets != -EINPROGRESS) {1145 pm_runtime_put_noidle(dev->dev);1146 cl_err(dev, cl, "rpm: get failed %d\n", rets);1147 goto nortpm;1148 }1149 1150 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_CONNECT, fp);1151 if (!cb) {1152 rets = -ENOMEM;1153 goto out;1154 }1155 1156 /* run hbuf acquire last so we don't have to undo */1157 if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {1158 rets = mei_cl_send_connect(cl, cb);1159 if (rets)1160 goto out;1161 }1162 1163 mutex_unlock(&dev->device_lock);1164 wait_event_timeout(cl->wait,1165 (cl->state == MEI_FILE_CONNECTED ||1166 cl->state == MEI_FILE_DISCONNECTED ||1167 cl->state == MEI_FILE_DISCONNECT_REQUIRED ||1168 cl->state == MEI_FILE_DISCONNECT_REPLY),1169 dev->timeouts.cl_connect);1170 mutex_lock(&dev->device_lock);1171 1172 if (!mei_cl_is_connected(cl)) {1173 if (cl->state == MEI_FILE_DISCONNECT_REQUIRED) {1174 mei_io_list_flush_cl(&dev->ctrl_rd_list, cl);1175 mei_io_list_flush_cl(&dev->ctrl_wr_list, cl);1176 /* ignore disconnect return valuue;1177 * in case of failure reset will be invoked1178 */1179 __mei_cl_disconnect(cl);1180 rets = -EFAULT;1181 goto out;1182 }1183 1184 /* timeout or something went really wrong */1185 if (!cl->status)1186 cl->status = -EFAULT;1187 }1188 1189 rets = cl->status;1190out:1191 cl_dbg(dev, cl, "rpm: autosuspend\n");1192 pm_runtime_mark_last_busy(dev->dev);1193 pm_runtime_put_autosuspend(dev->dev);1194 1195 mei_io_cb_free(cb);1196 1197nortpm:1198 if (!mei_cl_is_connected(cl))1199 mei_cl_set_disconnected(cl);1200 1201 return rets;1202}1203 1204/**1205 * mei_cl_alloc_linked - allocate and link host client1206 *1207 * @dev: the device structure1208 *1209 * Return: cl on success ERR_PTR on failure1210 */1211struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev)1212{1213 struct mei_cl *cl;1214 int ret;1215 1216 cl = mei_cl_allocate(dev);1217 if (!cl) {1218 ret = -ENOMEM;1219 goto err;1220 }1221 1222 ret = mei_cl_link(cl);1223 if (ret)1224 goto err;1225 1226 return cl;1227err:1228 kfree(cl);1229 return ERR_PTR(ret);1230}1231 1232/**1233 * mei_cl_tx_flow_ctrl_creds - checks flow_control credits for cl.1234 *1235 * @cl: host client1236 *1237 * Return: 1 if tx_flow_ctrl_creds >0, 0 - otherwise.1238 */1239static int mei_cl_tx_flow_ctrl_creds(struct mei_cl *cl)1240{1241 if (WARN_ON(!cl || !cl->me_cl))1242 return -EINVAL;1243 1244 if (cl->tx_flow_ctrl_creds > 0)1245 return 1;1246 1247 if (mei_cl_is_fixed_address(cl))1248 return 1;1249 1250 if (mei_cl_is_single_recv_buf(cl)) {1251 if (cl->me_cl->tx_flow_ctrl_creds > 0)1252 return 1;1253 }1254 return 0;1255}1256 1257/**1258 * mei_cl_tx_flow_ctrl_creds_reduce - reduces transmit flow control credits1259 * for a client1260 *1261 * @cl: host client1262 *1263 * Return:1264 * 0 on success1265 * -EINVAL when ctrl credits are <= 01266 */1267static int mei_cl_tx_flow_ctrl_creds_reduce(struct mei_cl *cl)1268{1269 if (WARN_ON(!cl || !cl->me_cl))1270 return -EINVAL;1271 1272 if (mei_cl_is_fixed_address(cl))1273 return 0;1274 1275 if (mei_cl_is_single_recv_buf(cl)) {1276 if (WARN_ON(cl->me_cl->tx_flow_ctrl_creds <= 0))1277 return -EINVAL;1278 cl->me_cl->tx_flow_ctrl_creds--;1279 } else {1280 if (WARN_ON(cl->tx_flow_ctrl_creds <= 0))1281 return -EINVAL;1282 cl->tx_flow_ctrl_creds--;1283 }1284 return 0;1285}1286 1287/**1288 * mei_cl_vtag_alloc - allocate and fill the vtag structure1289 *1290 * @fp: pointer to file structure1291 * @vtag: vm tag1292 *1293 * Return:1294 * * Pointer to allocated struct - on success1295 * * ERR_PTR(-ENOMEM) on memory allocation failure1296 */1297struct mei_cl_vtag *mei_cl_vtag_alloc(struct file *fp, u8 vtag)1298{1299 struct mei_cl_vtag *cl_vtag;1300 1301 cl_vtag = kzalloc(sizeof(*cl_vtag), GFP_KERNEL);1302 if (!cl_vtag)1303 return ERR_PTR(-ENOMEM);1304 1305 INIT_LIST_HEAD(&cl_vtag->list);1306 cl_vtag->vtag = vtag;1307 cl_vtag->fp = fp;1308 1309 return cl_vtag;1310}1311 1312/**1313 * mei_cl_fp_by_vtag - obtain the file pointer by vtag1314 *1315 * @cl: host client1316 * @vtag: virtual tag1317 *1318 * Return:1319 * * A file pointer - on success1320 * * ERR_PTR(-ENOENT) if vtag is not found in the client vtag list1321 */1322const struct file *mei_cl_fp_by_vtag(const struct mei_cl *cl, u8 vtag)1323{1324 struct mei_cl_vtag *vtag_l;1325 1326 list_for_each_entry(vtag_l, &cl->vtag_map, list)1327 /* The client on bus has one fixed fp */1328 if ((cl->cldev && mei_cldev_enabled(cl->cldev)) ||1329 vtag_l->vtag == vtag)1330 return vtag_l->fp;1331 1332 return ERR_PTR(-ENOENT);1333}1334 1335/**1336 * mei_cl_reset_read_by_vtag - reset pending_read flag by given vtag1337 *1338 * @cl: host client1339 * @vtag: vm tag1340 */1341static void mei_cl_reset_read_by_vtag(const struct mei_cl *cl, u8 vtag)1342{1343 struct mei_cl_vtag *vtag_l;1344 1345 list_for_each_entry(vtag_l, &cl->vtag_map, list) {1346 /* The client on bus has one fixed vtag map */1347 if ((cl->cldev && mei_cldev_enabled(cl->cldev)) ||1348 vtag_l->vtag == vtag) {1349 vtag_l->pending_read = false;1350 break;1351 }1352 }1353}1354 1355/**1356 * mei_cl_read_vtag_add_fc - add flow control for next pending reader1357 * in the vtag list1358 *1359 * @cl: host client1360 */1361static void mei_cl_read_vtag_add_fc(struct mei_cl *cl)1362{1363 struct mei_cl_vtag *cl_vtag;1364 1365 list_for_each_entry(cl_vtag, &cl->vtag_map, list) {1366 if (cl_vtag->pending_read) {1367 if (mei_cl_enqueue_ctrl_wr_cb(cl,1368 mei_cl_mtu(cl),1369 MEI_FOP_READ,1370 cl_vtag->fp))1371 cl->rx_flow_ctrl_creds++;1372 break;1373 }1374 }1375}1376 1377/**1378 * mei_cl_vt_support_check - check if client support vtags1379 *1380 * @cl: host client1381 *1382 * Return:1383 * * 0 - supported, or not connected at all1384 * * -EOPNOTSUPP - vtags are not supported by client1385 */1386int mei_cl_vt_support_check(const struct mei_cl *cl)1387{1388 struct mei_device *dev = cl->dev;1389 1390 if (!dev->hbm_f_vt_supported)1391 return -EOPNOTSUPP;1392 1393 if (!cl->me_cl)1394 return 0;1395 1396 return cl->me_cl->props.vt_supported ? 0 : -EOPNOTSUPP;1397}1398 1399/**1400 * mei_cl_add_rd_completed - add read completed callback to list with lock1401 * and vtag check1402 *1403 * @cl: host client1404 * @cb: callback block1405 *1406 */1407void mei_cl_add_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)1408{1409 const struct file *fp;1410 1411 if (!mei_cl_vt_support_check(cl)) {1412 fp = mei_cl_fp_by_vtag(cl, cb->vtag);1413 if (IS_ERR(fp)) {1414 /* client already disconnected, discarding */1415 mei_io_cb_free(cb);1416 return;1417 }1418 cb->fp = fp;1419 mei_cl_reset_read_by_vtag(cl, cb->vtag);1420 mei_cl_read_vtag_add_fc(cl);1421 }1422 1423 spin_lock(&cl->rd_completed_lock);1424 list_add_tail(&cb->list, &cl->rd_completed);1425 spin_unlock(&cl->rd_completed_lock);1426}1427 1428/**1429 * mei_cl_del_rd_completed - free read completed callback with lock1430 *1431 * @cl: host client1432 * @cb: callback block1433 *1434 */1435void mei_cl_del_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)1436{1437 spin_lock(&cl->rd_completed_lock);1438 mei_io_cb_free(cb);1439 spin_unlock(&cl->rd_completed_lock);1440}1441 1442/**1443 * mei_cl_notify_fop2req - convert fop to proper request1444 *1445 * @fop: client notification start response command1446 *1447 * Return: MEI_HBM_NOTIFICATION_START/STOP1448 */1449u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop)1450{1451 if (fop == MEI_FOP_NOTIFY_START)1452 return MEI_HBM_NOTIFICATION_START;1453 else1454 return MEI_HBM_NOTIFICATION_STOP;1455}1456 1457/**1458 * mei_cl_notify_req2fop - convert notification request top file operation type1459 *1460 * @req: hbm notification request type1461 *1462 * Return: MEI_FOP_NOTIFY_START/STOP1463 */1464enum mei_cb_file_ops mei_cl_notify_req2fop(u8 req)1465{1466 if (req == MEI_HBM_NOTIFICATION_START)1467 return MEI_FOP_NOTIFY_START;1468 else1469 return MEI_FOP_NOTIFY_STOP;1470}1471 1472/**1473 * mei_cl_irq_notify - send notification request in irq_thread context1474 *1475 * @cl: client1476 * @cb: callback block.1477 * @cmpl_list: complete list.1478 *1479 * Return: 0 on such and error otherwise.1480 */1481int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,1482 struct list_head *cmpl_list)1483{1484 struct mei_device *dev = cl->dev;1485 u32 msg_slots;1486 int slots;1487 int ret;1488 bool request;1489 1490 msg_slots = mei_hbm2slots(sizeof(struct hbm_client_connect_request));1491 slots = mei_hbuf_empty_slots(dev);1492 if (slots < 0)1493 return -EOVERFLOW;1494 1495 if ((u32)slots < msg_slots)1496 return -EMSGSIZE;1497 1498 request = mei_cl_notify_fop2req(cb->fop_type);1499 ret = mei_hbm_cl_notify_req(dev, cl, request);1500 if (ret) {1501 cl->status = ret;1502 list_move_tail(&cb->list, cmpl_list);1503 return ret;1504 }1505 1506 list_move_tail(&cb->list, &dev->ctrl_rd_list);1507 return 0;1508}1509 1510/**1511 * mei_cl_notify_request - send notification stop/start request1512 *1513 * @cl: host client1514 * @fp: associate request with file1515 * @request: 1 for start or 0 for stop1516 *1517 * Locking: called under "dev->device_lock" lock1518 *1519 * Return: 0 on such and error otherwise.1520 */1521int mei_cl_notify_request(struct mei_cl *cl,1522 const struct file *fp, u8 request)1523{1524 struct mei_device *dev;1525 struct mei_cl_cb *cb;1526 enum mei_cb_file_ops fop_type;1527 int rets;1528 1529 if (WARN_ON(!cl || !cl->dev))1530 return -ENODEV;1531 1532 dev = cl->dev;1533 1534 if (!dev->hbm_f_ev_supported) {1535 cl_dbg(dev, cl, "notifications not supported\n");1536 return -EOPNOTSUPP;1537 }1538 1539 if (!mei_cl_is_connected(cl))1540 return -ENODEV;1541 1542 rets = pm_runtime_get(dev->dev);1543 if (rets < 0 && rets != -EINPROGRESS) {1544 pm_runtime_put_noidle(dev->dev);1545 cl_err(dev, cl, "rpm: get failed %d\n", rets);1546 return rets;1547 }1548 1549 fop_type = mei_cl_notify_req2fop(request);1550 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, fop_type, fp);1551 if (!cb) {1552 rets = -ENOMEM;1553 goto out;1554 }1555 1556 if (mei_hbuf_acquire(dev)) {1557 if (mei_hbm_cl_notify_req(dev, cl, request)) {1558 rets = -ENODEV;1559 goto out;1560 }1561 list_move_tail(&cb->list, &dev->ctrl_rd_list);1562 }1563 1564 mutex_unlock(&dev->device_lock);1565 wait_event_timeout(cl->wait,1566 cl->notify_en == request ||1567 cl->status ||1568 !mei_cl_is_connected(cl),1569 dev->timeouts.cl_connect);1570 mutex_lock(&dev->device_lock);1571 1572 if (cl->notify_en != request && !cl->status)1573 cl->status = -EFAULT;1574 1575 rets = cl->status;1576 1577out:1578 cl_dbg(dev, cl, "rpm: autosuspend\n");1579 pm_runtime_mark_last_busy(dev->dev);1580 pm_runtime_put_autosuspend(dev->dev);1581 1582 mei_io_cb_free(cb);1583 return rets;1584}1585 1586/**1587 * mei_cl_notify - raise notification1588 *1589 * @cl: host client1590 *1591 * Locking: called under "dev->device_lock" lock1592 */1593void mei_cl_notify(struct mei_cl *cl)1594{1595 struct mei_device *dev;1596 1597 if (!cl || !cl->dev)1598 return;1599 1600 dev = cl->dev;1601 1602 if (!cl->notify_en)1603 return;1604 1605 cl_dbg(dev, cl, "notify event");1606 cl->notify_ev = true;1607 if (!mei_cl_bus_notify_event(cl))1608 wake_up_interruptible(&cl->ev_wait);1609 1610 if (cl->ev_async)1611 kill_fasync(&cl->ev_async, SIGIO, POLL_PRI);1612 1613}1614 1615/**1616 * mei_cl_notify_get - get or wait for notification event1617 *1618 * @cl: host client1619 * @block: this request is blocking1620 * @notify_ev: true if notification event was received1621 *1622 * Locking: called under "dev->device_lock" lock1623 *1624 * Return: 0 on such and error otherwise.1625 */1626int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev)1627{1628 struct mei_device *dev;1629 int rets;1630 1631 *notify_ev = false;1632 1633 if (WARN_ON(!cl || !cl->dev))1634 return -ENODEV;1635 1636 dev = cl->dev;1637 1638 if (!dev->hbm_f_ev_supported) {1639 cl_dbg(dev, cl, "notifications not supported\n");1640 return -EOPNOTSUPP;1641 }1642 1643 if (!mei_cl_is_connected(cl))1644 return -ENODEV;1645 1646 if (cl->notify_ev)1647 goto out;1648 1649 if (!block)1650 return -EAGAIN;1651 1652 mutex_unlock(&dev->device_lock);1653 rets = wait_event_interruptible(cl->ev_wait, cl->notify_ev);1654 mutex_lock(&dev->device_lock);1655 1656 if (rets < 0)1657 return rets;1658 1659out:1660 *notify_ev = cl->notify_ev;1661 cl->notify_ev = false;1662 return 0;1663}1664 1665/**1666 * mei_cl_read_start - the start read client message function.1667 *1668 * @cl: host client1669 * @length: number of bytes to read1670 * @fp: pointer to file structure1671 *1672 * Return: 0 on success, <0 on failure.1673 */1674int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)1675{1676 struct mei_device *dev;1677 struct mei_cl_cb *cb;1678 int rets;1679 1680 if (WARN_ON(!cl || !cl->dev))1681 return -ENODEV;1682 1683 dev = cl->dev;1684 1685 if (!mei_cl_is_connected(cl))1686 return -ENODEV;1687 1688 if (!mei_me_cl_is_active(cl->me_cl)) {1689 cl_err(dev, cl, "no such me client\n");1690 return -ENOTTY;1691 }1692 1693 if (mei_cl_is_fixed_address(cl))1694 return 0;1695 1696 /* HW currently supports only one pending read */1697 if (cl->rx_flow_ctrl_creds) {1698 mei_cl_set_read_by_fp(cl, fp);1699 return -EBUSY;1700 }1701 1702 cb = mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, fp);1703 if (!cb)1704 return -ENOMEM;1705 1706 mei_cl_set_read_by_fp(cl, fp);1707 1708 rets = pm_runtime_get(dev->dev);1709 if (rets < 0 && rets != -EINPROGRESS) {1710 pm_runtime_put_noidle(dev->dev);1711 cl_err(dev, cl, "rpm: get failed %d\n", rets);1712 goto nortpm;1713 }1714 1715 rets = 0;1716 if (mei_hbuf_acquire(dev)) {1717 rets = mei_hbm_cl_flow_control_req(dev, cl);1718 if (rets < 0)1719 goto out;1720 1721 list_move_tail(&cb->list, &cl->rd_pending);1722 }1723 cl->rx_flow_ctrl_creds++;1724 1725out:1726 cl_dbg(dev, cl, "rpm: autosuspend\n");1727 pm_runtime_mark_last_busy(dev->dev);1728 pm_runtime_put_autosuspend(dev->dev);1729nortpm:1730 if (rets)1731 mei_io_cb_free(cb);1732 1733 return rets;1734}1735 1736static inline u8 mei_ext_hdr_set_vtag(void *ext, u8 vtag)1737{1738 struct mei_ext_hdr_vtag *vtag_hdr = ext;1739 1740 vtag_hdr->hdr.type = MEI_EXT_HDR_VTAG;1741 vtag_hdr->hdr.length = mei_data2slots(sizeof(*vtag_hdr));1742 vtag_hdr->vtag = vtag;1743 vtag_hdr->reserved = 0;1744 return vtag_hdr->hdr.length;1745}1746 1747static inline bool mei_ext_hdr_is_gsc(struct mei_ext_hdr *ext)1748{1749 return ext && ext->type == MEI_EXT_HDR_GSC;1750}1751 1752static inline u8 mei_ext_hdr_set_gsc(struct mei_ext_hdr *ext, struct mei_ext_hdr *gsc_hdr)1753{1754 memcpy(ext, gsc_hdr, mei_ext_hdr_len(gsc_hdr));1755 return ext->length;1756}1757 1758/**1759 * mei_msg_hdr_init - allocate and initialize mei message header1760 *1761 * @cb: message callback structure1762 *1763 * Return: a pointer to initialized header or ERR_PTR on failure1764 */1765static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb)1766{1767 size_t hdr_len;1768 struct mei_ext_meta_hdr *meta;1769 struct mei_msg_hdr *mei_hdr;1770 bool is_ext, is_hbm, is_gsc, is_vtag;1771 struct mei_ext_hdr *next_ext;1772 1773 if (!cb)1774 return ERR_PTR(-EINVAL);1775 1776 /* Extended header for vtag is attached only on the first fragment */1777 is_vtag = (cb->vtag && cb->buf_idx == 0);1778 is_hbm = cb->cl->me_cl->client_id == 0;1779 is_gsc = ((!is_hbm) && cb->cl->dev->hbm_f_gsc_supported && mei_ext_hdr_is_gsc(cb->ext_hdr));1780 is_ext = is_vtag || is_gsc;1781 1782 /* Compute extended header size */1783 hdr_len = sizeof(*mei_hdr);1784 1785 if (!is_ext)1786 goto setup_hdr;1787 1788 hdr_len += sizeof(*meta);1789 if (is_vtag)1790 hdr_len += sizeof(struct mei_ext_hdr_vtag);1791 1792 if (is_gsc)1793 hdr_len += mei_ext_hdr_len(cb->ext_hdr);1794 1795setup_hdr:1796 mei_hdr = kzalloc(hdr_len, GFP_KERNEL);1797 if (!mei_hdr)1798 return ERR_PTR(-ENOMEM);1799 1800 mei_hdr->host_addr = mei_cl_host_addr(cb->cl);1801 mei_hdr->me_addr = mei_cl_me_id(cb->cl);1802 mei_hdr->internal = cb->internal;1803 mei_hdr->extended = is_ext;1804 1805 if (!is_ext)1806 goto out;1807 1808 meta = (struct mei_ext_meta_hdr *)mei_hdr->extension;1809 meta->size = 0;1810 next_ext = (struct mei_ext_hdr *)meta->hdrs;1811 if (is_vtag) {1812 meta->count++;1813 meta->size += mei_ext_hdr_set_vtag(next_ext, cb->vtag);1814 next_ext = mei_ext_next(next_ext);1815 }1816 1817 if (is_gsc) {1818 meta->count++;1819 meta->size += mei_ext_hdr_set_gsc(next_ext, cb->ext_hdr);1820 next_ext = mei_ext_next(next_ext);1821 }1822 1823out:1824 mei_hdr->length = hdr_len - sizeof(*mei_hdr);1825 return mei_hdr;1826}1827 1828/**1829 * mei_cl_irq_write - write a message to device1830 * from the interrupt thread context1831 *1832 * @cl: client1833 * @cb: callback block.1834 * @cmpl_list: complete list.1835 *1836 * Return: 0, OK; otherwise error.1837 */1838int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,1839 struct list_head *cmpl_list)1840{1841 struct mei_device *dev;1842 struct mei_msg_data *buf;1843 struct mei_msg_hdr *mei_hdr = NULL;1844 size_t hdr_len;1845 size_t hbuf_len, dr_len;1846 size_t buf_len = 0;1847 size_t data_len;1848 int hbuf_slots;1849 u32 dr_slots;1850 u32 dma_len;1851 int rets;1852 bool first_chunk;1853 const void *data = NULL;1854 1855 if (WARN_ON(!cl || !cl->dev))1856 return -ENODEV;1857 1858 dev = cl->dev;1859 1860 buf = &cb->buf;1861 1862 first_chunk = cb->buf_idx == 0;1863 1864 rets = first_chunk ? mei_cl_tx_flow_ctrl_creds(cl) : 1;1865 if (rets < 0)1866 goto err;1867 1868 if (rets == 0) {1869 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");1870 return 0;1871 }1872 1873 if (buf->data) {1874 buf_len = buf->size - cb->buf_idx;1875 data = buf->data + cb->buf_idx;1876 }1877 hbuf_slots = mei_hbuf_empty_slots(dev);1878 if (hbuf_slots < 0) {1879 rets = -EOVERFLOW;1880 goto err;1881 }1882 1883 hbuf_len = mei_slots2data(hbuf_slots) & MEI_MSG_MAX_LEN_MASK;1884 dr_slots = mei_dma_ring_empty_slots(dev);1885 dr_len = mei_slots2data(dr_slots);1886 1887 mei_hdr = mei_msg_hdr_init(cb);1888 if (IS_ERR(mei_hdr)) {1889 rets = PTR_ERR(mei_hdr);1890 mei_hdr = NULL;1891 goto err;1892 }1893 1894 hdr_len = sizeof(*mei_hdr) + mei_hdr->length;1895 1896 /**1897 * Split the message only if we can write the whole host buffer1898 * otherwise wait for next time the host buffer is empty.1899 */1900 if (hdr_len + buf_len <= hbuf_len) {1901 data_len = buf_len;1902 mei_hdr->msg_complete = 1;1903 } else if (dr_slots && hbuf_len >= hdr_len + sizeof(dma_len)) {1904 mei_hdr->dma_ring = 1;1905 if (buf_len > dr_len)1906 buf_len = dr_len;1907 else1908 mei_hdr->msg_complete = 1;1909 1910 data_len = sizeof(dma_len);1911 dma_len = buf_len;1912 data = &dma_len;1913 } else if ((u32)hbuf_slots == mei_hbuf_depth(dev)) {1914 buf_len = hbuf_len - hdr_len;1915 data_len = buf_len;1916 } else {1917 kfree(mei_hdr);1918 return 0;1919 }1920 mei_hdr->length += data_len;1921 1922 if (mei_hdr->dma_ring && buf->data)1923 mei_dma_ring_write(dev, buf->data + cb->buf_idx, buf_len);1924 rets = mei_write_message(dev, mei_hdr, hdr_len, data, data_len);1925 1926 if (rets)1927 goto err;1928 1929 cl->status = 0;1930 cl->writing_state = MEI_WRITING;1931 cb->buf_idx += buf_len;1932 1933 if (first_chunk) {1934 if (mei_cl_tx_flow_ctrl_creds_reduce(cl)) {1935 rets = -EIO;1936 goto err;1937 }1938 }1939 1940 if (mei_hdr->msg_complete)1941 list_move_tail(&cb->list, &dev->write_waiting_list);1942 1943 kfree(mei_hdr);1944 return 0;1945 1946err:1947 kfree(mei_hdr);1948 cl->status = rets;1949 list_move_tail(&cb->list, cmpl_list);1950 return rets;1951}1952 1953/**1954 * mei_cl_write - submit a write cb to mei device1955 * assumes device_lock is locked1956 *1957 * @cl: host client1958 * @cb: write callback with filled data1959 * @timeout: send timeout in milliseconds.1960 * effective only for blocking writes: the cb->blocking is set.1961 * set timeout to the MAX_SCHEDULE_TIMEOUT to maixum allowed wait.1962 *1963 * Return: number of bytes sent on success, <0 on failure.1964 */1965ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, unsigned long timeout)1966{1967 struct mei_device *dev;1968 struct mei_msg_data *buf;1969 struct mei_msg_hdr *mei_hdr = NULL;1970 size_t hdr_len;1971 size_t hbuf_len, dr_len;1972 size_t buf_len;1973 size_t data_len;1974 int hbuf_slots;1975 u32 dr_slots;1976 u32 dma_len;1977 ssize_t rets;1978 bool blocking;1979 const void *data;1980 1981 if (WARN_ON(!cl || !cl->dev))1982 return -ENODEV;1983 1984 if (WARN_ON(!cb))1985 return -EINVAL;1986 1987 dev = cl->dev;1988 1989 buf = &cb->buf;1990 buf_len = buf->size;1991 1992 cl_dbg(dev, cl, "buf_len=%zd\n", buf_len);1993 1994 blocking = cb->blocking;1995 data = buf->data;1996 1997 rets = pm_runtime_get(dev->dev);1998 if (rets < 0 && rets != -EINPROGRESS) {1999 pm_runtime_put_noidle(dev->dev);2000 cl_err(dev, cl, "rpm: get failed %zd\n", rets);2001 goto free;2002 }2003 2004 cb->buf_idx = 0;2005 cl->writing_state = MEI_IDLE;2006 2007 2008 rets = mei_cl_tx_flow_ctrl_creds(cl);2009 if (rets < 0)2010 goto err;2011 2012 mei_hdr = mei_msg_hdr_init(cb);2013 if (IS_ERR(mei_hdr)) {2014 rets = PTR_ERR(mei_hdr);2015 mei_hdr = NULL;2016 goto err;2017 }2018 2019 hdr_len = sizeof(*mei_hdr) + mei_hdr->length;2020 2021 if (rets == 0) {2022 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");2023 rets = buf_len;2024 goto out;2025 }2026 2027 if (!mei_hbuf_acquire(dev)) {2028 cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n");2029 rets = buf_len;2030 goto out;2031 }2032 2033 hbuf_slots = mei_hbuf_empty_slots(dev);2034 if (hbuf_slots < 0) {2035 buf_len = -EOVERFLOW;2036 goto out;2037 }2038 2039 hbuf_len = mei_slots2data(hbuf_slots) & MEI_MSG_MAX_LEN_MASK;2040 dr_slots = mei_dma_ring_empty_slots(dev);2041 dr_len = mei_slots2data(dr_slots);2042 2043 if (hdr_len + buf_len <= hbuf_len) {2044 data_len = buf_len;2045 mei_hdr->msg_complete = 1;2046 } else if (dr_slots && hbuf_len >= hdr_len + sizeof(dma_len)) {2047 mei_hdr->dma_ring = 1;2048 if (buf_len > dr_len)2049 buf_len = dr_len;2050 else2051 mei_hdr->msg_complete = 1;2052 2053 data_len = sizeof(dma_len);2054 dma_len = buf_len;2055 data = &dma_len;2056 } else {2057 buf_len = hbuf_len - hdr_len;2058 data_len = buf_len;2059 }2060 2061 mei_hdr->length += data_len;2062 2063 if (mei_hdr->dma_ring && buf->data)2064 mei_dma_ring_write(dev, buf->data, buf_len);2065 rets = mei_write_message(dev, mei_hdr, hdr_len, data, data_len);2066 2067 if (rets)2068 goto err;2069 2070 rets = mei_cl_tx_flow_ctrl_creds_reduce(cl);2071 if (rets)2072 goto err;2073 2074 cl->writing_state = MEI_WRITING;2075 cb->buf_idx = buf_len;2076 /* restore return value */2077 buf_len = buf->size;2078 2079out:2080 if (mei_hdr->msg_complete)2081 mei_tx_cb_enqueue(cb, &dev->write_waiting_list);2082 else2083 mei_tx_cb_enqueue(cb, &dev->write_list);2084 2085 cb = NULL;2086 if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {2087 2088 mutex_unlock(&dev->device_lock);2089 rets = wait_event_interruptible_timeout(cl->tx_wait,2090 cl->writing_state == MEI_WRITE_COMPLETE ||2091 (!mei_cl_is_connected(cl)),2092 msecs_to_jiffies(timeout));2093 mutex_lock(&dev->device_lock);2094 /* clean all queue on timeout as something fatal happened */2095 if (rets == 0) {2096 rets = -ETIME;2097 mei_io_tx_list_free_cl(&dev->write_list, cl, NULL);2098 mei_io_tx_list_free_cl(&dev->write_waiting_list, cl, NULL);2099 }2100 /* wait_event_interruptible returns -ERESTARTSYS */2101 if (rets > 0)2102 rets = 0;2103 if (rets) {2104 if (signal_pending(current))2105 rets = -EINTR;2106 goto err;2107 }2108 if (cl->writing_state != MEI_WRITE_COMPLETE) {2109 rets = -EFAULT;2110 goto err;2111 }2112 }2113 2114 rets = buf_len;2115err:2116 cl_dbg(dev, cl, "rpm: autosuspend\n");2117 pm_runtime_mark_last_busy(dev->dev);2118 pm_runtime_put_autosuspend(dev->dev);2119free:2120 mei_io_cb_free(cb);2121 2122 kfree(mei_hdr);2123 2124 return rets;2125}2126 2127/**2128 * mei_cl_complete - processes completed operation for a client2129 *2130 * @cl: private data of the file object.2131 * @cb: callback block.2132 */2133void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)2134{2135 struct mei_device *dev = cl->dev;2136 2137 switch (cb->fop_type) {2138 case MEI_FOP_WRITE:2139 mei_tx_cb_dequeue(cb);2140 cl->writing_state = MEI_WRITE_COMPLETE;2141 if (waitqueue_active(&cl->tx_wait)) {2142 wake_up_interruptible(&cl->tx_wait);2143 } else {2144 pm_runtime_mark_last_busy(dev->dev);2145 pm_request_autosuspend(dev->dev);2146 }2147 break;2148 2149 case MEI_FOP_READ:2150 mei_cl_add_rd_completed(cl, cb);2151 if (!mei_cl_is_fixed_address(cl) &&2152 !WARN_ON(!cl->rx_flow_ctrl_creds))2153 cl->rx_flow_ctrl_creds--;2154 if (!mei_cl_bus_rx_event(cl))2155 wake_up_interruptible(&cl->rx_wait);2156 break;2157 2158 case MEI_FOP_CONNECT:2159 case MEI_FOP_DISCONNECT:2160 case MEI_FOP_NOTIFY_STOP:2161 case MEI_FOP_NOTIFY_START:2162 case MEI_FOP_DMA_MAP:2163 case MEI_FOP_DMA_UNMAP:2164 if (waitqueue_active(&cl->wait))2165 wake_up(&cl->wait);2166 2167 break;2168 case MEI_FOP_DISCONNECT_RSP:2169 mei_io_cb_free(cb);2170 mei_cl_set_disconnected(cl);2171 break;2172 default:2173 BUG_ON(0);2174 }2175}2176 2177 2178/**2179 * mei_cl_all_disconnect - disconnect forcefully all connected clients2180 *2181 * @dev: mei device2182 */2183void mei_cl_all_disconnect(struct mei_device *dev)2184{2185 struct mei_cl *cl;2186 2187 list_for_each_entry(cl, &dev->file_list, link)2188 mei_cl_set_disconnected(cl);2189}2190EXPORT_SYMBOL_GPL(mei_cl_all_disconnect);2191 2192static struct mei_cl *mei_cl_dma_map_find(struct mei_device *dev, u8 buffer_id)2193{2194 struct mei_cl *cl;2195 2196 list_for_each_entry(cl, &dev->file_list, link)2197 if (cl->dma.buffer_id == buffer_id)2198 return cl;2199 return NULL;2200}2201 2202/**2203 * mei_cl_irq_dma_map - send client dma map request in irq_thread context2204 *2205 * @cl: client2206 * @cb: callback block.2207 * @cmpl_list: complete list.2208 *2209 * Return: 0 on such and error otherwise.2210 */2211int mei_cl_irq_dma_map(struct mei_cl *cl, struct mei_cl_cb *cb,2212 struct list_head *cmpl_list)2213{2214 struct mei_device *dev = cl->dev;2215 u32 msg_slots;2216 int slots;2217 int ret;2218 2219 msg_slots = mei_hbm2slots(sizeof(struct hbm_client_dma_map_request));2220 slots = mei_hbuf_empty_slots(dev);2221 if (slots < 0)2222 return -EOVERFLOW;2223 2224 if ((u32)slots < msg_slots)2225 return -EMSGSIZE;2226 2227 ret = mei_hbm_cl_dma_map_req(dev, cl);2228 if (ret) {2229 cl->status = ret;2230 list_move_tail(&cb->list, cmpl_list);2231 return ret;2232 }2233 2234 list_move_tail(&cb->list, &dev->ctrl_rd_list);2235 return 0;2236}2237 2238/**2239 * mei_cl_irq_dma_unmap - send client dma unmap request in irq_thread context2240 *2241 * @cl: client2242 * @cb: callback block.2243 * @cmpl_list: complete list.2244 *2245 * Return: 0 on such and error otherwise.2246 */2247int mei_cl_irq_dma_unmap(struct mei_cl *cl, struct mei_cl_cb *cb,2248 struct list_head *cmpl_list)2249{2250 struct mei_device *dev = cl->dev;2251 u32 msg_slots;2252 int slots;2253 int ret;2254 2255 msg_slots = mei_hbm2slots(sizeof(struct hbm_client_dma_unmap_request));2256 slots = mei_hbuf_empty_slots(dev);2257 if (slots < 0)2258 return -EOVERFLOW;2259 2260 if ((u32)slots < msg_slots)2261 return -EMSGSIZE;2262 2263 ret = mei_hbm_cl_dma_unmap_req(dev, cl);2264 if (ret) {2265 cl->status = ret;2266 list_move_tail(&cb->list, cmpl_list);2267 return ret;2268 }2269 2270 list_move_tail(&cb->list, &dev->ctrl_rd_list);2271 return 0;2272}2273 2274static int mei_cl_dma_alloc(struct mei_cl *cl, u8 buf_id, size_t size)2275{2276 cl->dma.vaddr = dmam_alloc_coherent(cl->dev->dev, size,2277 &cl->dma.daddr, GFP_KERNEL);2278 if (!cl->dma.vaddr)2279 return -ENOMEM;2280 2281 cl->dma.buffer_id = buf_id;2282 cl->dma.size = size;2283 2284 return 0;2285}2286 2287static void mei_cl_dma_free(struct mei_cl *cl)2288{2289 cl->dma.buffer_id = 0;2290 dmam_free_coherent(cl->dev->dev,2291 cl->dma.size, cl->dma.vaddr, cl->dma.daddr);2292 cl->dma.size = 0;2293 cl->dma.vaddr = NULL;2294 cl->dma.daddr = 0;2295}2296 2297/**2298 * mei_cl_dma_alloc_and_map - send client dma map request2299 *2300 * @cl: host client2301 * @fp: pointer to file structure2302 * @buffer_id: id of the mapped buffer2303 * @size: size of the buffer2304 *2305 * Locking: called under "dev->device_lock" lock2306 *2307 * Return:2308 * * -ENODEV2309 * * -EINVAL2310 * * -EOPNOTSUPP2311 * * -EPROTO2312 * * -ENOMEM;2313 */2314int mei_cl_dma_alloc_and_map(struct mei_cl *cl, const struct file *fp,2315 u8 buffer_id, size_t size)2316{2317 struct mei_device *dev;2318 struct mei_cl_cb *cb;2319 int rets;2320 2321 if (WARN_ON(!cl || !cl->dev))2322 return -ENODEV;2323 2324 dev = cl->dev;2325 2326 if (!dev->hbm_f_cd_supported) {2327 cl_dbg(dev, cl, "client dma is not supported\n");2328 return -EOPNOTSUPP;2329 }2330 2331 if (buffer_id == 0)2332 return -EINVAL;2333 2334 if (mei_cl_is_connected(cl))2335 return -EPROTO;2336 2337 if (cl->dma_mapped)2338 return -EPROTO;2339 2340 if (mei_cl_dma_map_find(dev, buffer_id)) {2341 cl_dbg(dev, cl, "client dma with id %d is already allocated\n",2342 cl->dma.buffer_id);2343 return -EPROTO;2344 }2345 2346 rets = pm_runtime_get(dev->dev);2347 if (rets < 0 && rets != -EINPROGRESS) {2348 pm_runtime_put_noidle(dev->dev);2349 cl_err(dev, cl, "rpm: get failed %d\n", rets);2350 return rets;2351 }2352 2353 rets = mei_cl_dma_alloc(cl, buffer_id, size);2354 if (rets) {2355 pm_runtime_put_noidle(dev->dev);2356 return rets;2357 }2358 2359 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DMA_MAP, fp);2360 if (!cb) {2361 rets = -ENOMEM;2362 goto out;2363 }2364 2365 if (mei_hbuf_acquire(dev)) {2366 if (mei_hbm_cl_dma_map_req(dev, cl)) {2367 rets = -ENODEV;2368 goto out;2369 }2370 list_move_tail(&cb->list, &dev->ctrl_rd_list);2371 }2372 2373 cl->status = 0;2374 2375 mutex_unlock(&dev->device_lock);2376 wait_event_timeout(cl->wait,2377 cl->dma_mapped || cl->status,2378 dev->timeouts.cl_connect);2379 mutex_lock(&dev->device_lock);2380 2381 if (!cl->dma_mapped && !cl->status)2382 cl->status = -EFAULT;2383 2384 rets = cl->status;2385 2386out:2387 if (rets)2388 mei_cl_dma_free(cl);2389 2390 cl_dbg(dev, cl, "rpm: autosuspend\n");2391 pm_runtime_mark_last_busy(dev->dev);2392 pm_runtime_put_autosuspend(dev->dev);2393 2394 mei_io_cb_free(cb);2395 return rets;2396}2397 2398/**2399 * mei_cl_dma_unmap - send client dma unmap request2400 *2401 * @cl: host client2402 * @fp: pointer to file structure2403 *2404 * Locking: called under "dev->device_lock" lock2405 *2406 * Return: 0 on such and error otherwise.2407 */2408int mei_cl_dma_unmap(struct mei_cl *cl, const struct file *fp)2409{2410 struct mei_device *dev;2411 struct mei_cl_cb *cb;2412 int rets;2413 2414 if (WARN_ON(!cl || !cl->dev))2415 return -ENODEV;2416 2417 dev = cl->dev;2418 2419 if (!dev->hbm_f_cd_supported) {2420 cl_dbg(dev, cl, "client dma is not supported\n");2421 return -EOPNOTSUPP;2422 }2423 2424 /* do not allow unmap for connected client */2425 if (mei_cl_is_connected(cl))2426 return -EPROTO;2427 2428 if (!cl->dma_mapped)2429 return -EPROTO;2430 2431 rets = pm_runtime_get(dev->dev);2432 if (rets < 0 && rets != -EINPROGRESS) {2433 pm_runtime_put_noidle(dev->dev);2434 cl_err(dev, cl, "rpm: get failed %d\n", rets);2435 return rets;2436 }2437 2438 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DMA_UNMAP, fp);2439 if (!cb) {2440 rets = -ENOMEM;2441 goto out;2442 }2443 2444 if (mei_hbuf_acquire(dev)) {2445 if (mei_hbm_cl_dma_unmap_req(dev, cl)) {2446 rets = -ENODEV;2447 goto out;2448 }2449 list_move_tail(&cb->list, &dev->ctrl_rd_list);2450 }2451 2452 cl->status = 0;2453 2454 mutex_unlock(&dev->device_lock);2455 wait_event_timeout(cl->wait,2456 !cl->dma_mapped || cl->status,2457 dev->timeouts.cl_connect);2458 mutex_lock(&dev->device_lock);2459 2460 if (cl->dma_mapped && !cl->status)2461 cl->status = -EFAULT;2462 2463 rets = cl->status;2464 2465 if (!rets)2466 mei_cl_dma_free(cl);2467out:2468 cl_dbg(dev, cl, "rpm: autosuspend\n");2469 pm_runtime_mark_last_busy(dev->dev);2470 pm_runtime_put_autosuspend(dev->dev);2471 2472 mei_io_cb_free(cb);2473 return rets;2474}2475