Lines Matching +full:autosuspend +full:- +full:delay
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2003-2020, Intel Corporation. All rights reserved.
9 #include <linux/delay.h>
20 * mei_me_cl_init - initialize me client
26 INIT_LIST_HEAD(&me_cl->list); in mei_me_cl_init()
27 kref_init(&me_cl->refcnt); in mei_me_cl_init()
31 * mei_me_cl_get - increases me client refcount
35 * Locking: called under "dev->device_lock" lock
41 if (me_cl && kref_get_unless_zero(&me_cl->refcnt)) in mei_me_cl_get()
48 * mei_me_cl_release - free me client
50 * Locking: called under "dev->device_lock" lock
63 * mei_me_cl_put - decrease me client refcount and free client if necessary
65 * Locking: called under "dev->device_lock" lock
72 kref_put(&me_cl->refcnt, mei_me_cl_release); in mei_me_cl_put()
76 * __mei_me_cl_del - delete me client from the list and decrease
82 * Locking: dev->me_clients_rwsem
89 list_del_init(&me_cl->list); in __mei_me_cl_del()
94 * mei_me_cl_del - delete me client from the list and decrease
102 down_write(&dev->me_clients_rwsem); in mei_me_cl_del()
104 up_write(&dev->me_clients_rwsem); in mei_me_cl_del()
108 * mei_me_cl_add - add me client to the list
115 down_write(&dev->me_clients_rwsem); in mei_me_cl_add()
116 list_add(&me_cl->list, &dev->me_clients); in mei_me_cl_add()
117 up_write(&dev->me_clients_rwsem); in mei_me_cl_add()
121 * __mei_me_cl_by_uuid - locate me client by uuid
129 * Locking: dev->me_clients_rwsem
137 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem)); in __mei_me_cl_by_uuid()
139 list_for_each_entry(me_cl, &dev->me_clients, list) { in __mei_me_cl_by_uuid()
140 pn = &me_cl->props.protocol_name; in __mei_me_cl_by_uuid()
149 * mei_me_cl_by_uuid - locate me client by uuid
157 * Locking: dev->me_clients_rwsem
164 down_read(&dev->me_clients_rwsem); in mei_me_cl_by_uuid()
166 up_read(&dev->me_clients_rwsem); in mei_me_cl_by_uuid()
172 * mei_me_cl_by_id - locate me client by client id
180 * Locking: dev->me_clients_rwsem
187 down_read(&dev->me_clients_rwsem); in mei_me_cl_by_id()
188 list_for_each_entry(__me_cl, &dev->me_clients, list) { in mei_me_cl_by_id()
189 if (__me_cl->client_id == client_id) { in mei_me_cl_by_id()
194 up_read(&dev->me_clients_rwsem); in mei_me_cl_by_id()
200 * __mei_me_cl_by_uuid_id - locate me client by client id and uuid
209 * Locking: dev->me_clients_rwsem
217 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem)); in __mei_me_cl_by_uuid_id()
219 list_for_each_entry(me_cl, &dev->me_clients, list) { in __mei_me_cl_by_uuid_id()
220 pn = &me_cl->props.protocol_name; in __mei_me_cl_by_uuid_id()
222 me_cl->client_id == client_id) in __mei_me_cl_by_uuid_id()
231 * mei_me_cl_by_uuid_id - locate me client by client id and uuid
245 down_read(&dev->me_clients_rwsem); in mei_me_cl_by_uuid_id()
247 up_read(&dev->me_clients_rwsem); in mei_me_cl_by_uuid_id()
253 * mei_me_cl_rm_by_uuid - remove all me clients matching uuid
258 * Locking: called under "dev->device_lock" lock
264 dev_dbg(dev->dev, "remove %pUl\n", uuid); in mei_me_cl_rm_by_uuid()
266 down_write(&dev->me_clients_rwsem); in mei_me_cl_rm_by_uuid()
270 up_write(&dev->me_clients_rwsem); in mei_me_cl_rm_by_uuid()
274 * mei_me_cl_rm_by_uuid_id - remove all me clients matching client id
280 * Locking: called under "dev->device_lock" lock
286 dev_dbg(dev->dev, "remove %pUl %d\n", uuid, id); in mei_me_cl_rm_by_uuid_id()
288 down_write(&dev->me_clients_rwsem); in mei_me_cl_rm_by_uuid_id()
292 up_write(&dev->me_clients_rwsem); in mei_me_cl_rm_by_uuid_id()
296 * mei_me_cl_rm_all - remove all me clients
300 * Locking: called under "dev->device_lock" lock
306 down_write(&dev->me_clients_rwsem); in mei_me_cl_rm_all()
307 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) in mei_me_cl_rm_all()
309 up_write(&dev->me_clients_rwsem); in mei_me_cl_rm_all()
313 * mei_io_cb_free - free mei_cb_private related memory
322 list_del(&cb->list); in mei_io_cb_free()
323 kfree(cb->buf.data); in mei_io_cb_free()
328 * mei_tx_cb_queue - queue tx callback
330 * Locking: called under "dev->device_lock" lock
338 list_add_tail(&cb->list, head); in mei_tx_cb_enqueue()
339 cb->cl->tx_cb_queued++; in mei_tx_cb_enqueue()
343 * mei_tx_cb_dequeue - dequeue tx callback
345 * Locking: called under "dev->device_lock" lock
351 if (!WARN_ON(cb->cl->tx_cb_queued == 0)) in mei_tx_cb_dequeue()
352 cb->cl->tx_cb_queued--; in mei_tx_cb_dequeue()
358 * mei_cl_set_read_by_fp - set pending_read flag to vtag struct for given fp
360 * Locking: called under "dev->device_lock" lock
370 list_for_each_entry(cl_vtag, &cl->vtag_map, list) { in mei_cl_set_read_by_fp()
371 if (cl_vtag->fp == fp) { in mei_cl_set_read_by_fp()
372 cl_vtag->pending_read = true; in mei_cl_set_read_by_fp()
379 * mei_io_cb_init - allocate and initialize io callback
397 INIT_LIST_HEAD(&cb->list); in mei_io_cb_init()
398 cb->fp = fp; in mei_io_cb_init()
399 cb->cl = cl; in mei_io_cb_init()
400 cb->buf_idx = 0; in mei_io_cb_init()
401 cb->fop_type = type; in mei_io_cb_init()
402 cb->vtag = 0; in mei_io_cb_init()
408 * mei_io_list_flush_cl - removes cbs belonging to the cl.
419 if (cl == cb->cl) { in mei_io_list_flush_cl()
420 list_del_init(&cb->list); in mei_io_list_flush_cl()
421 if (cb->fop_type == MEI_FOP_READ) in mei_io_list_flush_cl()
428 * mei_io_tx_list_free_cl - removes cb belonging to the cl and free them
441 if (cl == cb->cl && (!fp || fp == cb->fp)) in mei_io_tx_list_free_cl()
447 * mei_io_list_free_fp - free cb from a list that matches file pointer
457 if (!fp || fp == cb->fp) in mei_io_list_free_fp()
462 * mei_cl_free_pending - free pending cb
470 cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list); in mei_cl_free_pending()
475 * mei_cl_alloc_cb - a convenient wrapper for allocating read cb
497 cb->buf.data = kmalloc(roundup(length, MEI_SLOT_SIZE), GFP_KERNEL); in mei_cl_alloc_cb()
498 if (!cb->buf.data) { in mei_cl_alloc_cb()
502 cb->buf.size = length; in mei_cl_alloc_cb()
508 * mei_cl_enqueue_ctrl_wr_cb - a convenient wrapper for allocating
517 * Locking: called under "dev->device_lock" lock
533 list_add_tail(&cb->list, &cl->dev->ctrl_wr_list); in mei_cl_enqueue_ctrl_wr_cb()
538 * mei_cl_read_cb - find this cl's callback in the read list
551 spin_lock(&cl->rd_completed_lock); in mei_cl_read_cb()
552 list_for_each_entry(cb, &cl->rd_completed, list) in mei_cl_read_cb()
553 if (!fp || fp == cb->fp) { in mei_cl_read_cb()
557 spin_unlock(&cl->rd_completed_lock); in mei_cl_read_cb()
562 * mei_cl_flush_queues - flushes queue lists belonging to cl.
567 * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.
573 if (WARN_ON(!cl || !cl->dev)) in mei_cl_flush_queues()
574 return -EINVAL; in mei_cl_flush_queues()
576 dev = cl->dev; in mei_cl_flush_queues()
579 mei_io_tx_list_free_cl(&cl->dev->write_list, cl, fp); in mei_cl_flush_queues()
580 mei_io_tx_list_free_cl(&cl->dev->write_waiting_list, cl, fp); in mei_cl_flush_queues()
583 mei_io_list_flush_cl(&cl->dev->ctrl_wr_list, cl); in mei_cl_flush_queues()
584 mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl); in mei_cl_flush_queues()
587 spin_lock(&cl->rd_completed_lock); in mei_cl_flush_queues()
588 mei_io_list_free_fp(&cl->rd_completed, fp); in mei_cl_flush_queues()
589 spin_unlock(&cl->rd_completed_lock); in mei_cl_flush_queues()
595 * mei_cl_init - initializes cl.
603 init_waitqueue_head(&cl->wait); in mei_cl_init()
604 init_waitqueue_head(&cl->rx_wait); in mei_cl_init()
605 init_waitqueue_head(&cl->tx_wait); in mei_cl_init()
606 init_waitqueue_head(&cl->ev_wait); in mei_cl_init()
607 INIT_LIST_HEAD(&cl->vtag_map); in mei_cl_init()
608 spin_lock_init(&cl->rd_completed_lock); in mei_cl_init()
609 INIT_LIST_HEAD(&cl->rd_completed); in mei_cl_init()
610 INIT_LIST_HEAD(&cl->rd_pending); in mei_cl_init()
611 INIT_LIST_HEAD(&cl->link); in mei_cl_init()
612 cl->writing_state = MEI_IDLE; in mei_cl_init()
613 cl->state = MEI_FILE_UNINITIALIZED; in mei_cl_init()
614 cl->dev = dev; in mei_cl_init()
618 * mei_cl_allocate - allocates cl structure and sets it up.
637 * mei_cl_link - allocate host id in the host map
642 * -EINVAL on incorrect values
643 * -EMFILE if open count exceeded.
650 if (WARN_ON(!cl || !cl->dev)) in mei_cl_link()
651 return -EINVAL; in mei_cl_link()
653 dev = cl->dev; in mei_cl_link()
655 id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX); in mei_cl_link()
657 dev_err(dev->dev, "id exceeded %d", MEI_CLIENTS_MAX); in mei_cl_link()
658 return -EMFILE; in mei_cl_link()
661 if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) { in mei_cl_link()
662 dev_err(dev->dev, "open_handle_count exceeded %d", in mei_cl_link()
664 return -EMFILE; in mei_cl_link()
667 dev->open_handle_count++; in mei_cl_link()
669 cl->host_client_id = id; in mei_cl_link()
670 list_add_tail(&cl->link, &dev->file_list); in mei_cl_link()
672 set_bit(id, dev->host_clients_map); in mei_cl_link()
674 cl->state = MEI_FILE_INITIALIZING; in mei_cl_link()
681 * mei_cl_unlink - remove host client from the list
695 if (WARN_ON(!cl->dev)) in mei_cl_unlink()
698 dev = cl->dev; in mei_cl_unlink()
702 if (dev->open_handle_count > 0) in mei_cl_unlink()
703 dev->open_handle_count--; in mei_cl_unlink()
706 if (cl->host_client_id) in mei_cl_unlink()
707 clear_bit(cl->host_client_id, dev->host_clients_map); in mei_cl_unlink()
709 list_del_init(&cl->link); in mei_cl_unlink()
711 cl->state = MEI_FILE_UNINITIALIZED; in mei_cl_unlink()
712 cl->writing_state = MEI_IDLE; in mei_cl_unlink()
714 WARN_ON(!list_empty(&cl->rd_completed) || in mei_cl_unlink()
715 !list_empty(&cl->rd_pending) || in mei_cl_unlink()
716 !list_empty(&cl->link)); in mei_cl_unlink()
724 dev->reset_count = 0; in mei_host_client_init()
726 schedule_work(&dev->bus_rescan_work); in mei_host_client_init()
728 pm_runtime_mark_last_busy(dev->dev); in mei_host_client_init()
729 dev_dbg(dev->dev, "rpm: autosuspend\n"); in mei_host_client_init()
730 pm_request_autosuspend(dev->dev); in mei_host_client_init()
734 * mei_hbuf_acquire - try to acquire host buffer
743 dev_dbg(dev->dev, "device is in pg\n"); in mei_hbuf_acquire()
747 if (!dev->hbuf_is_ready) { in mei_hbuf_acquire()
748 dev_dbg(dev->dev, "hbuf is not ready\n"); in mei_hbuf_acquire()
752 dev->hbuf_is_ready = false; in mei_hbuf_acquire()
758 * mei_cl_wake_all - wake up readers, writers and event waiters so
765 struct mei_device *dev = cl->dev; in mei_cl_wake_all()
768 if (waitqueue_active(&cl->rx_wait)) { in mei_cl_wake_all()
770 wake_up_interruptible(&cl->rx_wait); in mei_cl_wake_all()
773 if (waitqueue_active(&cl->tx_wait)) { in mei_cl_wake_all()
775 wake_up_interruptible(&cl->tx_wait); in mei_cl_wake_all()
778 if (waitqueue_active(&cl->ev_wait)) { in mei_cl_wake_all()
780 wake_up_interruptible(&cl->ev_wait); in mei_cl_wake_all()
783 if (waitqueue_active(&cl->wait)) { in mei_cl_wake_all()
785 wake_up(&cl->wait); in mei_cl_wake_all()
790 * mei_cl_set_disconnected - set disconnected state and clear
797 struct mei_device *dev = cl->dev; in mei_cl_set_disconnected()
799 if (cl->state == MEI_FILE_DISCONNECTED || in mei_cl_set_disconnected()
800 cl->state <= MEI_FILE_INITIALIZING) in mei_cl_set_disconnected()
803 cl->state = MEI_FILE_DISCONNECTED; in mei_cl_set_disconnected()
804 mei_io_tx_list_free_cl(&dev->write_list, cl, NULL); in mei_cl_set_disconnected()
805 mei_io_tx_list_free_cl(&dev->write_waiting_list, cl, NULL); in mei_cl_set_disconnected()
806 mei_io_list_flush_cl(&dev->ctrl_rd_list, cl); in mei_cl_set_disconnected()
807 mei_io_list_flush_cl(&dev->ctrl_wr_list, cl); in mei_cl_set_disconnected()
809 cl->rx_flow_ctrl_creds = 0; in mei_cl_set_disconnected()
810 cl->tx_flow_ctrl_creds = 0; in mei_cl_set_disconnected()
811 cl->timer_count = 0; in mei_cl_set_disconnected()
813 if (!cl->me_cl) in mei_cl_set_disconnected()
816 if (!WARN_ON(cl->me_cl->connect_count == 0)) in mei_cl_set_disconnected()
817 cl->me_cl->connect_count--; in mei_cl_set_disconnected()
819 if (cl->me_cl->connect_count == 0) in mei_cl_set_disconnected()
820 cl->me_cl->tx_flow_ctrl_creds = 0; in mei_cl_set_disconnected()
822 mei_me_cl_put(cl->me_cl); in mei_cl_set_disconnected()
823 cl->me_cl = NULL; in mei_cl_set_disconnected()
829 return -ENOENT; in mei_cl_set_connecting()
832 if (me_cl->props.fixed_address) { in mei_cl_set_connecting()
833 if (me_cl->connect_count) { in mei_cl_set_connecting()
835 return -EBUSY; in mei_cl_set_connecting()
839 cl->me_cl = me_cl; in mei_cl_set_connecting()
840 cl->state = MEI_FILE_CONNECTING; in mei_cl_set_connecting()
841 cl->me_cl->connect_count++; in mei_cl_set_connecting()
847 * mei_cl_send_disconnect - send disconnect request
859 dev = cl->dev; in mei_cl_send_disconnect()
862 cl->status = ret; in mei_cl_send_disconnect()
864 cl->state = MEI_FILE_DISCONNECT_REPLY; in mei_cl_send_disconnect()
868 list_move_tail(&cb->list, &dev->ctrl_rd_list); in mei_cl_send_disconnect()
869 cl->timer_count = MEI_CONNECT_TIMEOUT; in mei_cl_send_disconnect()
876 * mei_cl_irq_disconnect - processes close related operation from
877 * interrupt thread context - send disconnect request
888 struct mei_device *dev = cl->dev; in mei_cl_irq_disconnect()
896 return -EOVERFLOW; in mei_cl_irq_disconnect()
899 return -EMSGSIZE; in mei_cl_irq_disconnect()
903 list_move_tail(&cb->list, cmpl_list); in mei_cl_irq_disconnect()
909 * __mei_cl_disconnect - disconnect host client from the me one
922 dev = cl->dev; in __mei_cl_disconnect()
924 cl->state = MEI_FILE_DISCONNECTING; in __mei_cl_disconnect()
928 rets = -ENOMEM; in __mei_cl_disconnect()
940 mutex_unlock(&dev->device_lock); in __mei_cl_disconnect()
941 wait_event_timeout(cl->wait, in __mei_cl_disconnect()
942 cl->state == MEI_FILE_DISCONNECT_REPLY || in __mei_cl_disconnect()
943 cl->state == MEI_FILE_DISCONNECTED, in __mei_cl_disconnect()
945 mutex_lock(&dev->device_lock); in __mei_cl_disconnect()
947 rets = cl->status; in __mei_cl_disconnect()
948 if (cl->state != MEI_FILE_DISCONNECT_REPLY && in __mei_cl_disconnect()
949 cl->state != MEI_FILE_DISCONNECTED) { in __mei_cl_disconnect()
951 rets = -ETIME; in __mei_cl_disconnect()
965 * mei_cl_disconnect - disconnect host client from the me one
969 * Locking: called under "dev->device_lock" lock
978 if (WARN_ON(!cl || !cl->dev)) in mei_cl_disconnect()
979 return -ENODEV; in mei_cl_disconnect()
981 dev = cl->dev; in mei_cl_disconnect()
993 if (dev->dev_state == MEI_DEV_POWER_DOWN) { in mei_cl_disconnect()
999 rets = pm_runtime_get(dev->dev); in mei_cl_disconnect()
1000 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_disconnect()
1001 pm_runtime_put_noidle(dev->dev); in mei_cl_disconnect()
1008 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_disconnect()
1009 pm_runtime_mark_last_busy(dev->dev); in mei_cl_disconnect()
1010 pm_runtime_put_autosuspend(dev->dev); in mei_cl_disconnect()
1017 * mei_cl_is_other_connecting - checks if other
1022 * Return: true if other client is connected, false - otherwise.
1029 dev = cl->dev; in mei_cl_is_other_connecting()
1031 list_for_each_entry(cb, &dev->ctrl_rd_list, list) { in mei_cl_is_other_connecting()
1032 if (cb->fop_type == MEI_FOP_CONNECT && in mei_cl_is_other_connecting()
1033 mei_cl_me_id(cl) == mei_cl_me_id(cb->cl)) in mei_cl_is_other_connecting()
1041 * mei_cl_send_connect - send connect request
1053 dev = cl->dev; in mei_cl_send_connect()
1056 cl->status = ret; in mei_cl_send_connect()
1058 cl->state = MEI_FILE_DISCONNECT_REPLY; in mei_cl_send_connect()
1062 list_move_tail(&cb->list, &dev->ctrl_rd_list); in mei_cl_send_connect()
1063 cl->timer_count = MEI_CONNECT_TIMEOUT; in mei_cl_send_connect()
1069 * mei_cl_irq_connect - send connect request in irq_thread context
1080 struct mei_device *dev = cl->dev; in mei_cl_irq_connect()
1091 return -EOVERFLOW; in mei_cl_irq_connect()
1094 return -EMSGSIZE; in mei_cl_irq_connect()
1098 list_move_tail(&cb->list, cmpl_list); in mei_cl_irq_connect()
1104 * mei_cl_connect - connect host client to the me one
1110 * Locking: called under "dev->device_lock" lock
1121 if (WARN_ON(!cl || !cl->dev || !me_cl)) in mei_cl_connect()
1122 return -ENODEV; in mei_cl_connect()
1124 dev = cl->dev; in mei_cl_connect()
1131 cl->state = MEI_FILE_CONNECTED; in mei_cl_connect()
1136 rets = pm_runtime_get(dev->dev); in mei_cl_connect()
1137 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_connect()
1138 pm_runtime_put_noidle(dev->dev); in mei_cl_connect()
1145 rets = -ENOMEM; in mei_cl_connect()
1156 mutex_unlock(&dev->device_lock); in mei_cl_connect()
1157 wait_event_timeout(cl->wait, in mei_cl_connect()
1158 (cl->state == MEI_FILE_CONNECTED || in mei_cl_connect()
1159 cl->state == MEI_FILE_DISCONNECTED || in mei_cl_connect()
1160 cl->state == MEI_FILE_DISCONNECT_REQUIRED || in mei_cl_connect()
1161 cl->state == MEI_FILE_DISCONNECT_REPLY), in mei_cl_connect()
1163 mutex_lock(&dev->device_lock); in mei_cl_connect()
1166 if (cl->state == MEI_FILE_DISCONNECT_REQUIRED) { in mei_cl_connect()
1167 mei_io_list_flush_cl(&dev->ctrl_rd_list, cl); in mei_cl_connect()
1168 mei_io_list_flush_cl(&dev->ctrl_wr_list, cl); in mei_cl_connect()
1173 rets = -EFAULT; in mei_cl_connect()
1178 if (!cl->status) in mei_cl_connect()
1179 cl->status = -EFAULT; in mei_cl_connect()
1182 rets = cl->status; in mei_cl_connect()
1184 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_connect()
1185 pm_runtime_mark_last_busy(dev->dev); in mei_cl_connect()
1186 pm_runtime_put_autosuspend(dev->dev); in mei_cl_connect()
1198 * mei_cl_alloc_linked - allocate and link host client
1211 ret = -ENOMEM; in mei_cl_alloc_linked()
1226 * mei_cl_tx_flow_ctrl_creds - checks flow_control credits for cl.
1230 * Return: 1 if tx_flow_ctrl_creds >0, 0 - otherwise.
1234 if (WARN_ON(!cl || !cl->me_cl)) in mei_cl_tx_flow_ctrl_creds()
1235 return -EINVAL; in mei_cl_tx_flow_ctrl_creds()
1237 if (cl->tx_flow_ctrl_creds > 0) in mei_cl_tx_flow_ctrl_creds()
1244 if (cl->me_cl->tx_flow_ctrl_creds > 0) in mei_cl_tx_flow_ctrl_creds()
1251 * mei_cl_tx_flow_ctrl_creds_reduce - reduces transmit flow control credits
1258 * -EINVAL when ctrl credits are <= 0
1262 if (WARN_ON(!cl || !cl->me_cl)) in mei_cl_tx_flow_ctrl_creds_reduce()
1263 return -EINVAL; in mei_cl_tx_flow_ctrl_creds_reduce()
1269 if (WARN_ON(cl->me_cl->tx_flow_ctrl_creds <= 0)) in mei_cl_tx_flow_ctrl_creds_reduce()
1270 return -EINVAL; in mei_cl_tx_flow_ctrl_creds_reduce()
1271 cl->me_cl->tx_flow_ctrl_creds--; in mei_cl_tx_flow_ctrl_creds_reduce()
1273 if (WARN_ON(cl->tx_flow_ctrl_creds <= 0)) in mei_cl_tx_flow_ctrl_creds_reduce()
1274 return -EINVAL; in mei_cl_tx_flow_ctrl_creds_reduce()
1275 cl->tx_flow_ctrl_creds--; in mei_cl_tx_flow_ctrl_creds_reduce()
1281 * mei_cl_vtag_alloc - allocate and fill the vtag structure
1287 * * Pointer to allocated struct - on success
1288 * * ERR_PTR(-ENOMEM) on memory allocation failure
1296 return ERR_PTR(-ENOMEM); in mei_cl_vtag_alloc()
1298 INIT_LIST_HEAD(&cl_vtag->list); in mei_cl_vtag_alloc()
1299 cl_vtag->vtag = vtag; in mei_cl_vtag_alloc()
1300 cl_vtag->fp = fp; in mei_cl_vtag_alloc()
1306 * mei_cl_fp_by_vtag - obtain the file pointer by vtag
1312 * * A file pointer - on success
1313 * * ERR_PTR(-ENOENT) if vtag is not found in the client vtag list
1319 list_for_each_entry(vtag_l, &cl->vtag_map, list) in mei_cl_fp_by_vtag()
1320 if (vtag_l->vtag == vtag) in mei_cl_fp_by_vtag()
1321 return vtag_l->fp; in mei_cl_fp_by_vtag()
1323 return ERR_PTR(-ENOENT); in mei_cl_fp_by_vtag()
1327 * mei_cl_reset_read_by_vtag - reset pending_read flag by given vtag
1336 list_for_each_entry(vtag_l, &cl->vtag_map, list) { in mei_cl_reset_read_by_vtag()
1337 if (vtag_l->vtag == vtag) { in mei_cl_reset_read_by_vtag()
1338 vtag_l->pending_read = false; in mei_cl_reset_read_by_vtag()
1345 * mei_cl_read_vtag_add_fc - add flow control for next pending reader
1354 list_for_each_entry(cl_vtag, &cl->vtag_map, list) { in mei_cl_read_vtag_add_fc()
1355 if (cl_vtag->pending_read) { in mei_cl_read_vtag_add_fc()
1359 cl_vtag->fp)) in mei_cl_read_vtag_add_fc()
1360 cl->rx_flow_ctrl_creds++; in mei_cl_read_vtag_add_fc()
1367 * mei_cl_vt_support_check - check if client support vtags
1372 * * 0 - supported, or not connected at all
1373 * * -EOPNOTSUPP - vtags are not supported by client
1377 struct mei_device *dev = cl->dev; in mei_cl_vt_support_check()
1379 if (!dev->hbm_f_vt_supported) in mei_cl_vt_support_check()
1380 return -EOPNOTSUPP; in mei_cl_vt_support_check()
1382 if (!cl->me_cl) in mei_cl_vt_support_check()
1385 return cl->me_cl->props.vt_supported ? 0 : -EOPNOTSUPP; in mei_cl_vt_support_check()
1389 * mei_cl_add_rd_completed - add read completed callback to list with lock
1401 fp = mei_cl_fp_by_vtag(cl, cb->vtag); in mei_cl_add_rd_completed()
1407 cb->fp = fp; in mei_cl_add_rd_completed()
1408 mei_cl_reset_read_by_vtag(cl, cb->vtag); in mei_cl_add_rd_completed()
1412 spin_lock(&cl->rd_completed_lock); in mei_cl_add_rd_completed()
1413 list_add_tail(&cb->list, &cl->rd_completed); in mei_cl_add_rd_completed()
1414 spin_unlock(&cl->rd_completed_lock); in mei_cl_add_rd_completed()
1418 * mei_cl_del_rd_completed - free read completed callback with lock
1426 spin_lock(&cl->rd_completed_lock); in mei_cl_del_rd_completed()
1428 spin_unlock(&cl->rd_completed_lock); in mei_cl_del_rd_completed()
1432 * mei_cl_notify_fop2req - convert fop to proper request
1447 * mei_cl_notify_req2fop - convert notification request top file operation type
1462 * mei_cl_irq_notify - send notification request in irq_thread context
1473 struct mei_device *dev = cl->dev; in mei_cl_irq_notify()
1482 return -EOVERFLOW; in mei_cl_irq_notify()
1485 return -EMSGSIZE; in mei_cl_irq_notify()
1487 request = mei_cl_notify_fop2req(cb->fop_type); in mei_cl_irq_notify()
1490 cl->status = ret; in mei_cl_irq_notify()
1491 list_move_tail(&cb->list, cmpl_list); in mei_cl_irq_notify()
1495 list_move_tail(&cb->list, &dev->ctrl_rd_list); in mei_cl_irq_notify()
1500 * mei_cl_notify_request - send notification stop/start request
1506 * Locking: called under "dev->device_lock" lock
1518 if (WARN_ON(!cl || !cl->dev)) in mei_cl_notify_request()
1519 return -ENODEV; in mei_cl_notify_request()
1521 dev = cl->dev; in mei_cl_notify_request()
1523 if (!dev->hbm_f_ev_supported) { in mei_cl_notify_request()
1525 return -EOPNOTSUPP; in mei_cl_notify_request()
1529 return -ENODEV; in mei_cl_notify_request()
1531 rets = pm_runtime_get(dev->dev); in mei_cl_notify_request()
1532 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_notify_request()
1533 pm_runtime_put_noidle(dev->dev); in mei_cl_notify_request()
1541 rets = -ENOMEM; in mei_cl_notify_request()
1547 rets = -ENODEV; in mei_cl_notify_request()
1550 list_move_tail(&cb->list, &dev->ctrl_rd_list); in mei_cl_notify_request()
1553 mutex_unlock(&dev->device_lock); in mei_cl_notify_request()
1554 wait_event_timeout(cl->wait, in mei_cl_notify_request()
1555 cl->notify_en == request || in mei_cl_notify_request()
1556 cl->status || in mei_cl_notify_request()
1559 mutex_lock(&dev->device_lock); in mei_cl_notify_request()
1561 if (cl->notify_en != request && !cl->status) in mei_cl_notify_request()
1562 cl->status = -EFAULT; in mei_cl_notify_request()
1564 rets = cl->status; in mei_cl_notify_request()
1567 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_notify_request()
1568 pm_runtime_mark_last_busy(dev->dev); in mei_cl_notify_request()
1569 pm_runtime_put_autosuspend(dev->dev); in mei_cl_notify_request()
1576 * mei_cl_notify - raise notification
1580 * Locking: called under "dev->device_lock" lock
1586 if (!cl || !cl->dev) in mei_cl_notify()
1589 dev = cl->dev; in mei_cl_notify()
1591 if (!cl->notify_en) in mei_cl_notify()
1595 cl->notify_ev = true; in mei_cl_notify()
1597 wake_up_interruptible(&cl->ev_wait); in mei_cl_notify()
1599 if (cl->ev_async) in mei_cl_notify()
1600 kill_fasync(&cl->ev_async, SIGIO, POLL_PRI); in mei_cl_notify()
1605 * mei_cl_notify_get - get or wait for notification event
1611 * Locking: called under "dev->device_lock" lock
1622 if (WARN_ON(!cl || !cl->dev)) in mei_cl_notify_get()
1623 return -ENODEV; in mei_cl_notify_get()
1625 dev = cl->dev; in mei_cl_notify_get()
1627 if (!dev->hbm_f_ev_supported) { in mei_cl_notify_get()
1629 return -EOPNOTSUPP; in mei_cl_notify_get()
1633 return -ENODEV; in mei_cl_notify_get()
1635 if (cl->notify_ev) in mei_cl_notify_get()
1639 return -EAGAIN; in mei_cl_notify_get()
1641 mutex_unlock(&dev->device_lock); in mei_cl_notify_get()
1642 rets = wait_event_interruptible(cl->ev_wait, cl->notify_ev); in mei_cl_notify_get()
1643 mutex_lock(&dev->device_lock); in mei_cl_notify_get()
1649 *notify_ev = cl->notify_ev; in mei_cl_notify_get()
1650 cl->notify_ev = false; in mei_cl_notify_get()
1655 * mei_cl_read_start - the start read client message function.
1669 if (WARN_ON(!cl || !cl->dev)) in mei_cl_read_start()
1670 return -ENODEV; in mei_cl_read_start()
1672 dev = cl->dev; in mei_cl_read_start()
1675 return -ENODEV; in mei_cl_read_start()
1677 if (!mei_me_cl_is_active(cl->me_cl)) { in mei_cl_read_start()
1679 return -ENOTTY; in mei_cl_read_start()
1686 if (cl->rx_flow_ctrl_creds) { in mei_cl_read_start()
1688 return -EBUSY; in mei_cl_read_start()
1693 return -ENOMEM; in mei_cl_read_start()
1697 rets = pm_runtime_get(dev->dev); in mei_cl_read_start()
1698 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_read_start()
1699 pm_runtime_put_noidle(dev->dev); in mei_cl_read_start()
1710 list_move_tail(&cb->list, &cl->rd_pending); in mei_cl_read_start()
1712 cl->rx_flow_ctrl_creds++; in mei_cl_read_start()
1715 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_read_start()
1716 pm_runtime_mark_last_busy(dev->dev); in mei_cl_read_start()
1717 pm_runtime_put_autosuspend(dev->dev); in mei_cl_read_start()
1727 ext->type = MEI_EXT_HDR_VTAG; in mei_ext_hdr_set_vtag()
1728 ext->ext_payload[0] = vtag; in mei_ext_hdr_set_vtag()
1729 ext->length = mei_data2slots(sizeof(*ext)); in mei_ext_hdr_set_vtag()
1730 return ext->length; in mei_ext_hdr_set_vtag()
1734 * mei_msg_hdr_init - allocate and initialize mei message header
1749 return ERR_PTR(-EINVAL); in mei_msg_hdr_init()
1752 is_vtag = (cb->vtag && cb->buf_idx == 0); in mei_msg_hdr_init()
1768 return ERR_PTR(-ENOMEM); in mei_msg_hdr_init()
1770 mei_hdr->host_addr = mei_cl_host_addr(cb->cl); in mei_msg_hdr_init()
1771 mei_hdr->me_addr = mei_cl_me_id(cb->cl); in mei_msg_hdr_init()
1772 mei_hdr->internal = cb->internal; in mei_msg_hdr_init()
1773 mei_hdr->extended = is_ext; in mei_msg_hdr_init()
1778 meta = (struct mei_ext_meta_hdr *)mei_hdr->extension; in mei_msg_hdr_init()
1780 meta->count++; in mei_msg_hdr_init()
1781 meta->size += mei_ext_hdr_set_vtag(meta->hdrs, cb->vtag); in mei_msg_hdr_init()
1784 mei_hdr->length = hdr_len - sizeof(*mei_hdr); in mei_msg_hdr_init()
1789 * mei_cl_irq_write - write a message to device
1815 if (WARN_ON(!cl || !cl->dev)) in mei_cl_irq_write()
1816 return -ENODEV; in mei_cl_irq_write()
1818 dev = cl->dev; in mei_cl_irq_write()
1820 buf = &cb->buf; in mei_cl_irq_write()
1822 first_chunk = cb->buf_idx == 0; in mei_cl_irq_write()
1833 buf_len = buf->size - cb->buf_idx; in mei_cl_irq_write()
1834 data = buf->data + cb->buf_idx; in mei_cl_irq_write()
1837 rets = -EOVERFLOW; in mei_cl_irq_write()
1853 mei_hdr->extended, cb->vtag); in mei_cl_irq_write()
1855 hdr_len = sizeof(*mei_hdr) + mei_hdr->length; in mei_cl_irq_write()
1863 mei_hdr->msg_complete = 1; in mei_cl_irq_write()
1865 mei_hdr->dma_ring = 1; in mei_cl_irq_write()
1869 mei_hdr->msg_complete = 1; in mei_cl_irq_write()
1875 buf_len = hbuf_len - hdr_len; in mei_cl_irq_write()
1881 mei_hdr->length += data_len; in mei_cl_irq_write()
1883 if (mei_hdr->dma_ring) in mei_cl_irq_write()
1884 mei_dma_ring_write(dev, buf->data + cb->buf_idx, buf_len); in mei_cl_irq_write()
1890 cl->status = 0; in mei_cl_irq_write()
1891 cl->writing_state = MEI_WRITING; in mei_cl_irq_write()
1892 cb->buf_idx += buf_len; in mei_cl_irq_write()
1896 rets = -EIO; in mei_cl_irq_write()
1901 if (mei_hdr->msg_complete) in mei_cl_irq_write()
1902 list_move_tail(&cb->list, &dev->write_waiting_list); in mei_cl_irq_write()
1909 cl->status = rets; in mei_cl_irq_write()
1910 list_move_tail(&cb->list, cmpl_list); in mei_cl_irq_write()
1915 * mei_cl_write - submit a write cb to mei device
1939 if (WARN_ON(!cl || !cl->dev)) in mei_cl_write()
1940 return -ENODEV; in mei_cl_write()
1943 return -EINVAL; in mei_cl_write()
1945 dev = cl->dev; in mei_cl_write()
1947 buf = &cb->buf; in mei_cl_write()
1948 buf_len = buf->size; in mei_cl_write()
1952 blocking = cb->blocking; in mei_cl_write()
1953 data = buf->data; in mei_cl_write()
1955 rets = pm_runtime_get(dev->dev); in mei_cl_write()
1956 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_write()
1957 pm_runtime_put_noidle(dev->dev); in mei_cl_write()
1962 cb->buf_idx = 0; in mei_cl_write()
1963 cl->writing_state = MEI_IDLE; in mei_cl_write()
1972 rets = -PTR_ERR(mei_hdr); in mei_cl_write()
1978 mei_hdr->extended, cb->vtag); in mei_cl_write()
1980 hdr_len = sizeof(*mei_hdr) + mei_hdr->length; in mei_cl_write()
1996 rets = -EOVERFLOW; in mei_cl_write()
2006 mei_hdr->msg_complete = 1; in mei_cl_write()
2008 mei_hdr->dma_ring = 1; in mei_cl_write()
2012 mei_hdr->msg_complete = 1; in mei_cl_write()
2018 buf_len = hbuf_len - hdr_len; in mei_cl_write()
2022 mei_hdr->length += data_len; in mei_cl_write()
2024 if (mei_hdr->dma_ring) in mei_cl_write()
2025 mei_dma_ring_write(dev, buf->data, buf_len); in mei_cl_write()
2035 cl->writing_state = MEI_WRITING; in mei_cl_write()
2036 cb->buf_idx = buf_len; in mei_cl_write()
2038 buf_len = buf->size; in mei_cl_write()
2041 if (mei_hdr->msg_complete) in mei_cl_write()
2042 mei_tx_cb_enqueue(cb, &dev->write_waiting_list); in mei_cl_write()
2044 mei_tx_cb_enqueue(cb, &dev->write_list); in mei_cl_write()
2047 if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) { in mei_cl_write()
2049 mutex_unlock(&dev->device_lock); in mei_cl_write()
2050 rets = wait_event_interruptible(cl->tx_wait, in mei_cl_write()
2051 cl->writing_state == MEI_WRITE_COMPLETE || in mei_cl_write()
2053 mutex_lock(&dev->device_lock); in mei_cl_write()
2054 /* wait_event_interruptible returns -ERESTARTSYS */ in mei_cl_write()
2057 rets = -EINTR; in mei_cl_write()
2060 if (cl->writing_state != MEI_WRITE_COMPLETE) { in mei_cl_write()
2061 rets = -EFAULT; in mei_cl_write()
2068 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_write()
2069 pm_runtime_mark_last_busy(dev->dev); in mei_cl_write()
2070 pm_runtime_put_autosuspend(dev->dev); in mei_cl_write()
2080 * mei_cl_complete - processes completed operation for a client
2087 struct mei_device *dev = cl->dev; in mei_cl_complete()
2089 switch (cb->fop_type) { in mei_cl_complete()
2092 cl->writing_state = MEI_WRITE_COMPLETE; in mei_cl_complete()
2093 if (waitqueue_active(&cl->tx_wait)) { in mei_cl_complete()
2094 wake_up_interruptible(&cl->tx_wait); in mei_cl_complete()
2096 pm_runtime_mark_last_busy(dev->dev); in mei_cl_complete()
2097 pm_request_autosuspend(dev->dev); in mei_cl_complete()
2104 !WARN_ON(!cl->rx_flow_ctrl_creds)) in mei_cl_complete()
2105 cl->rx_flow_ctrl_creds--; in mei_cl_complete()
2107 wake_up_interruptible(&cl->rx_wait); in mei_cl_complete()
2114 if (waitqueue_active(&cl->wait)) in mei_cl_complete()
2115 wake_up(&cl->wait); in mei_cl_complete()
2129 * mei_cl_all_disconnect - disconnect forcefully all connected clients
2137 list_for_each_entry(cl, &dev->file_list, link) in mei_cl_all_disconnect()