Lines Matching refs:mcdi

35 static void cdx_mcdi_start_or_queue(struct cdx_mcdi_iface *mcdi,
37 static void cdx_mcdi_cmd_start_or_queue(struct cdx_mcdi_iface *mcdi,
39 static bool cdx_mcdi_complete_cmd(struct cdx_mcdi_iface *mcdi,
44 static void cdx_mcdi_timeout_cmd(struct cdx_mcdi_iface *mcdi,
67 static void _cdx_mcdi_remove_cmd(struct cdx_mcdi_iface *mcdi, in _cdx_mcdi_remove_cmd() argument
77 ++mcdi->outstanding_cleanups; in _cdx_mcdi_remove_cmd()
82 static void cdx_mcdi_remove_cmd(struct cdx_mcdi_iface *mcdi, in cdx_mcdi_remove_cmd() argument
87 _cdx_mcdi_remove_cmd(mcdi, cmd, cleanup_list); in cdx_mcdi_remove_cmd()
90 if (list_empty(&mcdi->cmd_list)) in cdx_mcdi_remove_cmd()
91 wake_up(&mcdi->cmd_complete_wq); in cdx_mcdi_remove_cmd()
104 struct cdx_mcdi_iface *mcdi; in cdx_mcdi_init() local
107 cdx->mcdi = kzalloc(sizeof(*cdx->mcdi), GFP_KERNEL); in cdx_mcdi_init()
108 if (!cdx->mcdi) in cdx_mcdi_init()
111 mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_init()
112 mcdi->cdx = cdx; in cdx_mcdi_init()
114 mcdi->workqueue = alloc_ordered_workqueue("mcdi_wq", 0); in cdx_mcdi_init()
115 if (!mcdi->workqueue) in cdx_mcdi_init()
117 mutex_init(&mcdi->iface_lock); in cdx_mcdi_init()
118 mcdi->mode = MCDI_MODE_EVENTS; in cdx_mcdi_init()
119 INIT_LIST_HEAD(&mcdi->cmd_list); in cdx_mcdi_init()
120 init_waitqueue_head(&mcdi->cmd_complete_wq); in cdx_mcdi_init()
122 mcdi->new_epoch = true; in cdx_mcdi_init()
126 kfree(cdx->mcdi); in cdx_mcdi_init()
127 cdx->mcdi = NULL; in cdx_mcdi_init()
134 struct cdx_mcdi_iface *mcdi; in cdx_mcdi_finish() local
136 mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_finish()
137 if (!mcdi) in cdx_mcdi_finish()
142 destroy_workqueue(mcdi->workqueue); in cdx_mcdi_finish()
143 kfree(cdx->mcdi); in cdx_mcdi_finish()
144 cdx->mcdi = NULL; in cdx_mcdi_finish()
147 static bool cdx_mcdi_flushed(struct cdx_mcdi_iface *mcdi, bool ignore_cleanups) in cdx_mcdi_flushed() argument
151 mutex_lock(&mcdi->iface_lock); in cdx_mcdi_flushed()
152 flushed = list_empty(&mcdi->cmd_list) && in cdx_mcdi_flushed()
153 (ignore_cleanups || !mcdi->outstanding_cleanups); in cdx_mcdi_flushed()
154 mutex_unlock(&mcdi->iface_lock); in cdx_mcdi_flushed()
161 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_wait_for_cleanup() local
163 if (!mcdi) in cdx_mcdi_wait_for_cleanup()
166 wait_event(mcdi->cmd_complete_wq, in cdx_mcdi_wait_for_cleanup()
167 cdx_mcdi_flushed(mcdi, false)); in cdx_mcdi_wait_for_cleanup()
173 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_wait_for_quiescence() local
177 if (!mcdi) in cdx_mcdi_wait_for_quiescence()
180 flush_workqueue(mcdi->workqueue); in cdx_mcdi_wait_for_quiescence()
182 add_wait_queue(&mcdi->cmd_complete_wq, &wait); in cdx_mcdi_wait_for_quiescence()
184 while (!cdx_mcdi_flushed(mcdi, true)) { in cdx_mcdi_wait_for_quiescence()
191 remove_wait_queue(&mcdi->cmd_complete_wq, &wait); in cdx_mcdi_wait_for_quiescence()
221 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_send_request() local
229 if (!mcdi) in cdx_mcdi_send_request()
232 mcdi->prev_seq = cmd->seq; in cdx_mcdi_send_request()
233 mcdi->seq_held_by[cmd->seq] = cmd; in cdx_mcdi_send_request()
234 mcdi->db_held_by = cmd; in cdx_mcdi_send_request()
237 not_epoch = !mcdi->new_epoch; in cdx_mcdi_send_request()
265 mcdi->new_epoch = false; in cdx_mcdi_send_request()
318 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_process_cleanup_list() local
321 if (!mcdi) in cdx_mcdi_process_cleanup_list()
338 mutex_lock(&mcdi->iface_lock); in cdx_mcdi_process_cleanup_list()
339 CDX_WARN_ON_PARANOID(cleanups > mcdi->outstanding_cleanups); in cdx_mcdi_process_cleanup_list()
340 all_done = (mcdi->outstanding_cleanups -= cleanups) == 0; in cdx_mcdi_process_cleanup_list()
341 mutex_unlock(&mcdi->iface_lock); in cdx_mcdi_process_cleanup_list()
343 wake_up(&mcdi->cmd_complete_wq); in cdx_mcdi_process_cleanup_list()
347 static void _cdx_mcdi_cancel_cmd(struct cdx_mcdi_iface *mcdi, in _cdx_mcdi_cancel_cmd() argument
353 list_for_each_entry(cmd, &mcdi->cmd_list, list) in _cdx_mcdi_cancel_cmd()
362 cdx_mcdi_remove_cmd(mcdi, cmd, cleanup_list); in _cdx_mcdi_cancel_cmd()
377 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_cancel_cmd() local
380 if (!mcdi) in cdx_mcdi_cancel_cmd()
383 mutex_lock(&mcdi->iface_lock); in cdx_mcdi_cancel_cmd()
384 cdx_mcdi_timeout_cmd(mcdi, cmd, &cleanup_list); in cdx_mcdi_cancel_cmd()
385 mutex_unlock(&mcdi->iface_lock); in cdx_mcdi_cancel_cmd()
489 static bool cdx_mcdi_get_seq(struct cdx_mcdi_iface *mcdi, unsigned char *seq) in cdx_mcdi_get_seq() argument
491 *seq = mcdi->prev_seq; in cdx_mcdi_get_seq()
493 *seq = (*seq + 1) % ARRAY_SIZE(mcdi->seq_held_by); in cdx_mcdi_get_seq()
494 } while (mcdi->seq_held_by[*seq] && *seq != mcdi->prev_seq); in cdx_mcdi_get_seq()
495 return !mcdi->seq_held_by[*seq]; in cdx_mcdi_get_seq()
502 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_rpc_async_internal() local
505 if (!mcdi) { in cdx_mcdi_rpc_async_internal()
510 if (mcdi->mode == MCDI_MODE_FAIL) { in cdx_mcdi_rpc_async_internal()
515 cmd->mcdi = mcdi; in cdx_mcdi_rpc_async_internal()
523 queue_work(mcdi->workqueue, &cmd->work); in cdx_mcdi_rpc_async_internal()
527 static void cdx_mcdi_cmd_start_or_queue(struct cdx_mcdi_iface *mcdi, in cdx_mcdi_cmd_start_or_queue() argument
530 struct cdx_mcdi *cdx = mcdi->cdx; in cdx_mcdi_cmd_start_or_queue()
533 if (!mcdi->db_held_by && in cdx_mcdi_cmd_start_or_queue()
534 cdx_mcdi_get_seq(mcdi, &seq)) { in cdx_mcdi_cmd_start_or_queue()
545 static void cdx_mcdi_start_or_queue(struct cdx_mcdi_iface *mcdi, in cdx_mcdi_start_or_queue() argument
550 list_for_each_entry_safe(cmd, tmp, &mcdi->cmd_list, list) in cdx_mcdi_start_or_queue()
553 cdx_mcdi_cmd_start_or_queue(mcdi, cmd); in cdx_mcdi_start_or_queue()
558 struct cdx_mcdi_iface *mcdi; in cdx_mcdi_process_cmd() local
568 mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_process_cmd()
569 if (!mcdi) in cdx_mcdi_process_cmd()
574 mutex_lock(&mcdi->iface_lock); in cdx_mcdi_process_cmd()
575 cmd = mcdi->seq_held_by[respseq]; in cdx_mcdi_process_cmd()
579 mutex_unlock(&mcdi->iface_lock); in cdx_mcdi_process_cmd()
584 cdx_mcdi_complete_cmd(mcdi, cmd, outbuf, len, &cleanup_list); in cdx_mcdi_process_cmd()
589 mutex_unlock(&mcdi->iface_lock); in cdx_mcdi_process_cmd()
591 cdx_mcdi_process_cleanup_list(mcdi->cdx, &cleanup_list); in cdx_mcdi_process_cmd()
598 struct cdx_mcdi_iface *mcdi = cmd->mcdi; in cdx_mcdi_cmd_work() local
600 mutex_lock(&mcdi->iface_lock); in cdx_mcdi_cmd_work()
602 cmd->handle = mcdi->prev_handle++; in cdx_mcdi_cmd_work()
603 list_add_tail(&cmd->list, &mcdi->cmd_list); in cdx_mcdi_cmd_work()
604 cdx_mcdi_cmd_start_or_queue(mcdi, cmd); in cdx_mcdi_cmd_work()
606 mutex_unlock(&mcdi->iface_lock); in cdx_mcdi_cmd_work()
614 static bool cdx_mcdi_complete_cmd(struct cdx_mcdi_iface *mcdi, in cdx_mcdi_complete_cmd() argument
621 struct cdx_mcdi *cdx = mcdi->cdx; in cdx_mcdi_complete_cmd()
682 if (mcdi->db_held_by == cmd) in cdx_mcdi_complete_cmd()
683 mcdi->db_held_by = NULL; in cdx_mcdi_complete_cmd()
695 cdx_mcdi_remove_cmd(mcdi, cmd, cleanup_list); in cdx_mcdi_complete_cmd()
700 mcdi->seq_held_by[cmd->seq] = NULL; in cdx_mcdi_complete_cmd()
702 cdx_mcdi_start_or_queue(mcdi, rc != MC_CMD_ERR_QUEUE_FULL); in cdx_mcdi_complete_cmd()
705 wake_up(&mcdi->cmd_complete_wq); in cdx_mcdi_complete_cmd()
712 static void cdx_mcdi_timeout_cmd(struct cdx_mcdi_iface *mcdi, in cdx_mcdi_timeout_cmd() argument
716 struct cdx_mcdi *cdx = mcdi->cdx; in cdx_mcdi_timeout_cmd()
723 cdx_mcdi_remove_cmd(mcdi, cmd, cleanup_list); in cdx_mcdi_timeout_cmd()
817 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); in cdx_mcdi_mode_fail() local
819 if (!mcdi) in cdx_mcdi_mode_fail()
822 mcdi->mode = MCDI_MODE_FAIL; in cdx_mcdi_mode_fail()
824 while (!list_empty(&mcdi->cmd_list)) { in cdx_mcdi_mode_fail()
827 cmd = list_first_entry(&mcdi->cmd_list, struct cdx_mcdi_cmd, in cdx_mcdi_mode_fail()
829 _cdx_mcdi_cancel_cmd(mcdi, cdx_mcdi_cmd_handle(cmd), cleanup_list); in cdx_mcdi_mode_fail()