xref: /kernel/linux/linux-6.6/drivers/misc/mei/hbm.c (revision 62306a36)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2003-2022, Intel Corporation. All rights reserved.
4 * Intel Management Engine Interface (Intel MEI) Linux driver
5 */
6#include <linux/export.h>
7#include <linux/sched.h>
8#include <linux/wait.h>
9#include <linux/pm_runtime.h>
10#include <linux/slab.h>
11
12#include <linux/mei.h>
13
14#include "mei_dev.h"
15#include "hbm.h"
16#include "client.h"
17
18static const char *mei_hbm_status_str(enum mei_hbm_status status)
19{
20#define MEI_HBM_STATUS(status) case MEI_HBMS_##status: return #status
21	switch (status) {
22	MEI_HBM_STATUS(SUCCESS);
23	MEI_HBM_STATUS(CLIENT_NOT_FOUND);
24	MEI_HBM_STATUS(ALREADY_EXISTS);
25	MEI_HBM_STATUS(REJECTED);
26	MEI_HBM_STATUS(INVALID_PARAMETER);
27	MEI_HBM_STATUS(NOT_ALLOWED);
28	MEI_HBM_STATUS(ALREADY_STARTED);
29	MEI_HBM_STATUS(NOT_STARTED);
30	default: return "unknown";
31	}
32#undef MEI_HBM_STATUS
33};
34
35static const char *mei_cl_conn_status_str(enum mei_cl_connect_status status)
36{
37#define MEI_CL_CS(status) case MEI_CL_CONN_##status: return #status
38	switch (status) {
39	MEI_CL_CS(SUCCESS);
40	MEI_CL_CS(NOT_FOUND);
41	MEI_CL_CS(ALREADY_STARTED);
42	MEI_CL_CS(OUT_OF_RESOURCES);
43	MEI_CL_CS(MESSAGE_SMALL);
44	MEI_CL_CS(NOT_ALLOWED);
45	default: return "unknown";
46	}
47#undef MEI_CL_CCS
48}
49
50const char *mei_hbm_state_str(enum mei_hbm_state state)
51{
52#define MEI_HBM_STATE(state) case MEI_HBM_##state: return #state
53	switch (state) {
54	MEI_HBM_STATE(IDLE);
55	MEI_HBM_STATE(STARTING);
56	MEI_HBM_STATE(STARTED);
57	MEI_HBM_STATE(DR_SETUP);
58	MEI_HBM_STATE(ENUM_CLIENTS);
59	MEI_HBM_STATE(CLIENT_PROPERTIES);
60	MEI_HBM_STATE(STOPPED);
61	default:
62		return "unknown";
63	}
64#undef MEI_HBM_STATE
65}
66
67/**
68 * mei_cl_conn_status_to_errno - convert client connect response
69 * status to error code
70 *
71 * @status: client connect response status
72 *
73 * Return: corresponding error code
74 */
75static int mei_cl_conn_status_to_errno(enum mei_cl_connect_status status)
76{
77	switch (status) {
78	case MEI_CL_CONN_SUCCESS:          return 0;
79	case MEI_CL_CONN_NOT_FOUND:        return -ENOTTY;
80	case MEI_CL_CONN_ALREADY_STARTED:  return -EBUSY;
81	case MEI_CL_CONN_OUT_OF_RESOURCES: return -EBUSY;
82	case MEI_CL_CONN_MESSAGE_SMALL:    return -EINVAL;
83	case MEI_CL_CONN_NOT_ALLOWED:      return -EBUSY;
84	default:                           return -EINVAL;
85	}
86}
87
88/**
89 * mei_hbm_write_message - wrapper for sending hbm messages.
90 *
91 * @dev: mei device
92 * @hdr: mei header
93 * @data: payload
94 */
95static inline int mei_hbm_write_message(struct mei_device *dev,
96					struct mei_msg_hdr *hdr,
97					const void *data)
98{
99	return mei_write_message(dev, hdr, sizeof(*hdr), data, hdr->length);
100}
101
102/**
103 * mei_hbm_idle - set hbm to idle state
104 *
105 * @dev: the device structure
106 */
107void mei_hbm_idle(struct mei_device *dev)
108{
109	dev->init_clients_timer = 0;
110	dev->hbm_state = MEI_HBM_IDLE;
111}
112
113/**
114 * mei_hbm_reset - reset hbm counters and book keeping data structurs
115 *
116 * @dev: the device structure
117 */
118void mei_hbm_reset(struct mei_device *dev)
119{
120	mei_me_cl_rm_all(dev);
121
122	mei_hbm_idle(dev);
123}
124
125/**
126 * mei_hbm_hdr - construct hbm header
127 *
128 * @mei_hdr: hbm header
129 * @length: payload length
130 */
131
132static inline void mei_hbm_hdr(struct mei_msg_hdr *mei_hdr, size_t length)
133{
134	memset(mei_hdr, 0, sizeof(*mei_hdr));
135	mei_hdr->length = length;
136	mei_hdr->msg_complete = 1;
137}
138
139/**
140 * mei_hbm_cl_hdr - construct client hbm header
141 *
142 * @cl: client
143 * @hbm_cmd: host bus message command
144 * @buf: buffer for cl header
145 * @len: buffer length
146 */
147static inline
148void mei_hbm_cl_hdr(struct mei_cl *cl, u8 hbm_cmd, void *buf, size_t len)
149{
150	struct mei_hbm_cl_cmd *cmd = buf;
151
152	memset(cmd, 0, len);
153
154	cmd->hbm_cmd = hbm_cmd;
155	cmd->host_addr = mei_cl_host_addr(cl);
156	cmd->me_addr = mei_cl_me_id(cl);
157}
158
159/**
160 * mei_hbm_cl_write - write simple hbm client message
161 *
162 * @dev: the device structure
163 * @cl: client
164 * @hbm_cmd: host bus message command
165 * @buf: message buffer
166 * @len: buffer length
167 *
168 * Return: 0 on success, <0 on failure.
169 */
170static inline int mei_hbm_cl_write(struct mei_device *dev, struct mei_cl *cl,
171				   u8 hbm_cmd, void *buf, size_t len)
172{
173	struct mei_msg_hdr mei_hdr;
174
175	mei_hbm_hdr(&mei_hdr, len);
176	mei_hbm_cl_hdr(cl, hbm_cmd, buf, len);
177
178	return mei_hbm_write_message(dev, &mei_hdr, buf);
179}
180
181/**
182 * mei_hbm_cl_addr_equal - check if the client's and
183 *	the message address match
184 *
185 * @cl: client
186 * @cmd: hbm client message
187 *
188 * Return: true if addresses are the same
189 */
190static inline
191bool mei_hbm_cl_addr_equal(struct mei_cl *cl, struct mei_hbm_cl_cmd *cmd)
192{
193	return  mei_cl_host_addr(cl) == cmd->host_addr &&
194		mei_cl_me_id(cl) == cmd->me_addr;
195}
196
197/**
198 * mei_hbm_cl_find_by_cmd - find recipient client
199 *
200 * @dev: the device structure
201 * @buf: a buffer with hbm cl command
202 *
203 * Return: the recipient client or NULL if not found
204 */
205static inline
206struct mei_cl *mei_hbm_cl_find_by_cmd(struct mei_device *dev, void *buf)
207{
208	struct mei_hbm_cl_cmd *cmd = (struct mei_hbm_cl_cmd *)buf;
209	struct mei_cl *cl;
210
211	list_for_each_entry(cl, &dev->file_list, link)
212		if (mei_hbm_cl_addr_equal(cl, cmd))
213			return cl;
214	return NULL;
215}
216
217
218/**
219 * mei_hbm_start_wait - wait for start response message.
220 *
221 * @dev: the device structure
222 *
223 * Return: 0 on success and < 0 on failure
224 */
225int mei_hbm_start_wait(struct mei_device *dev)
226{
227	int ret;
228
229	if (dev->hbm_state > MEI_HBM_STARTING)
230		return 0;
231
232	mutex_unlock(&dev->device_lock);
233	ret = wait_event_timeout(dev->wait_hbm_start,
234			dev->hbm_state != MEI_HBM_STARTING,
235			dev->timeouts.hbm);
236	mutex_lock(&dev->device_lock);
237
238	if (ret == 0 && (dev->hbm_state <= MEI_HBM_STARTING)) {
239		dev->hbm_state = MEI_HBM_IDLE;
240		dev_err(dev->dev, "waiting for mei start failed\n");
241		return -ETIME;
242	}
243	return 0;
244}
245
246/**
247 * mei_hbm_start_req - sends start request message.
248 *
249 * @dev: the device structure
250 *
251 * Return: 0 on success and < 0 on failure
252 */
253int mei_hbm_start_req(struct mei_device *dev)
254{
255	struct mei_msg_hdr mei_hdr;
256	struct hbm_host_version_request req;
257	int ret;
258
259	mei_hbm_reset(dev);
260
261	mei_hbm_hdr(&mei_hdr, sizeof(req));
262
263	/* host start message */
264	memset(&req, 0, sizeof(req));
265	req.hbm_cmd = HOST_START_REQ_CMD;
266	req.host_version.major_version = HBM_MAJOR_VERSION;
267	req.host_version.minor_version = HBM_MINOR_VERSION;
268
269	dev->hbm_state = MEI_HBM_IDLE;
270	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
271	if (ret) {
272		dev_err(dev->dev, "version message write failed: ret = %d\n",
273			ret);
274		return ret;
275	}
276
277	dev->hbm_state = MEI_HBM_STARTING;
278	dev->init_clients_timer = dev->timeouts.client_init;
279	mei_schedule_stall_timer(dev);
280	return 0;
281}
282
283/**
284 * mei_hbm_dma_setup_req() - setup DMA request
285 * @dev: the device structure
286 *
287 * Return: 0 on success and < 0 on failure
288 */
289static int mei_hbm_dma_setup_req(struct mei_device *dev)
290{
291	struct mei_msg_hdr mei_hdr;
292	struct hbm_dma_setup_request req;
293	unsigned int i;
294	int ret;
295
296	mei_hbm_hdr(&mei_hdr, sizeof(req));
297
298	memset(&req, 0, sizeof(req));
299	req.hbm_cmd = MEI_HBM_DMA_SETUP_REQ_CMD;
300	for (i = 0; i < DMA_DSCR_NUM; i++) {
301		phys_addr_t paddr;
302
303		paddr = dev->dr_dscr[i].daddr;
304		req.dma_dscr[i].addr_hi = upper_32_bits(paddr);
305		req.dma_dscr[i].addr_lo = lower_32_bits(paddr);
306		req.dma_dscr[i].size = dev->dr_dscr[i].size;
307	}
308
309	mei_dma_ring_reset(dev);
310
311	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
312	if (ret) {
313		dev_err(dev->dev, "dma setup request write failed: ret = %d.\n",
314			ret);
315		return ret;
316	}
317
318	dev->hbm_state = MEI_HBM_DR_SETUP;
319	dev->init_clients_timer = dev->timeouts.client_init;
320	mei_schedule_stall_timer(dev);
321	return 0;
322}
323
324/**
325 * mei_hbm_capabilities_req - request capabilities
326 *
327 * @dev: the device structure
328 *
329 * Return: 0 on success and < 0 on failure
330 */
331static int mei_hbm_capabilities_req(struct mei_device *dev)
332{
333	struct mei_msg_hdr mei_hdr;
334	struct hbm_capability_request req;
335	int ret;
336
337	mei_hbm_hdr(&mei_hdr, sizeof(req));
338
339	memset(&req, 0, sizeof(req));
340	req.hbm_cmd = MEI_HBM_CAPABILITIES_REQ_CMD;
341	if (dev->hbm_f_vt_supported)
342		req.capability_requested[0] |= HBM_CAP_VT;
343
344	if (dev->hbm_f_cd_supported)
345		req.capability_requested[0] |= HBM_CAP_CD;
346
347	if (dev->hbm_f_gsc_supported)
348		req.capability_requested[0] |= HBM_CAP_GSC;
349
350	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
351	if (ret) {
352		dev_err(dev->dev,
353			"capabilities request write failed: ret = %d.\n", ret);
354		return ret;
355	}
356
357	dev->hbm_state = MEI_HBM_CAP_SETUP;
358	dev->init_clients_timer = dev->timeouts.client_init;
359	mei_schedule_stall_timer(dev);
360	return 0;
361}
362
363/**
364 * mei_hbm_enum_clients_req - sends enumeration client request message.
365 *
366 * @dev: the device structure
367 *
368 * Return: 0 on success and < 0 on failure
369 */
370static int mei_hbm_enum_clients_req(struct mei_device *dev)
371{
372	struct mei_msg_hdr mei_hdr;
373	struct hbm_host_enum_request req;
374	int ret;
375
376	/* enumerate clients */
377	mei_hbm_hdr(&mei_hdr, sizeof(req));
378
379	memset(&req, 0, sizeof(req));
380	req.hbm_cmd = HOST_ENUM_REQ_CMD;
381	req.flags |= dev->hbm_f_dc_supported ? MEI_HBM_ENUM_F_ALLOW_ADD : 0;
382	req.flags |= dev->hbm_f_ie_supported ?
383			  MEI_HBM_ENUM_F_IMMEDIATE_ENUM : 0;
384
385	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
386	if (ret) {
387		dev_err(dev->dev, "enumeration request write failed: ret = %d.\n",
388			ret);
389		return ret;
390	}
391	dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
392	dev->init_clients_timer = dev->timeouts.client_init;
393	mei_schedule_stall_timer(dev);
394	return 0;
395}
396
397/**
398 * mei_hbm_me_cl_add - add new me client to the list
399 *
400 * @dev: the device structure
401 * @res: hbm property response
402 *
403 * Return: 0 on success and -ENOMEM on allocation failure
404 */
405
406static int mei_hbm_me_cl_add(struct mei_device *dev,
407			     struct hbm_props_response *res)
408{
409	struct mei_me_client *me_cl;
410	const uuid_le *uuid = &res->client_properties.protocol_name;
411
412	mei_me_cl_rm_by_uuid(dev, uuid);
413
414	me_cl = kzalloc(sizeof(*me_cl), GFP_KERNEL);
415	if (!me_cl)
416		return -ENOMEM;
417
418	mei_me_cl_init(me_cl);
419
420	me_cl->props = res->client_properties;
421	me_cl->client_id = res->me_addr;
422	me_cl->tx_flow_ctrl_creds = 0;
423
424	mei_me_cl_add(dev, me_cl);
425
426	return 0;
427}
428
429/**
430 * mei_hbm_add_cl_resp - send response to fw on client add request
431 *
432 * @dev: the device structure
433 * @addr: me address
434 * @status: response status
435 *
436 * Return: 0 on success and < 0 on failure
437 */
438static int mei_hbm_add_cl_resp(struct mei_device *dev, u8 addr, u8 status)
439{
440	struct mei_msg_hdr mei_hdr;
441	struct hbm_add_client_response resp;
442	int ret;
443
444	dev_dbg(dev->dev, "adding client response\n");
445
446	mei_hbm_hdr(&mei_hdr, sizeof(resp));
447
448	memset(&resp, 0, sizeof(resp));
449	resp.hbm_cmd = MEI_HBM_ADD_CLIENT_RES_CMD;
450	resp.me_addr = addr;
451	resp.status  = status;
452
453	ret = mei_hbm_write_message(dev, &mei_hdr, &resp);
454	if (ret)
455		dev_err(dev->dev, "add client response write failed: ret = %d\n",
456			ret);
457	return ret;
458}
459
460/**
461 * mei_hbm_fw_add_cl_req - request from the fw to add a client
462 *
463 * @dev: the device structure
464 * @req: add client request
465 *
466 * Return: 0 on success and < 0 on failure
467 */
468static int mei_hbm_fw_add_cl_req(struct mei_device *dev,
469			      struct hbm_add_client_request *req)
470{
471	int ret;
472	u8 status = MEI_HBMS_SUCCESS;
473
474	BUILD_BUG_ON(sizeof(struct hbm_add_client_request) !=
475			sizeof(struct hbm_props_response));
476
477	ret = mei_hbm_me_cl_add(dev, (struct hbm_props_response *)req);
478	if (ret)
479		status = !MEI_HBMS_SUCCESS;
480
481	if (dev->dev_state == MEI_DEV_ENABLED)
482		schedule_work(&dev->bus_rescan_work);
483
484	return mei_hbm_add_cl_resp(dev, req->me_addr, status);
485}
486
487/**
488 * mei_hbm_cl_notify_req - send notification request
489 *
490 * @dev: the device structure
491 * @cl: a client to disconnect from
492 * @start: true for start false for stop
493 *
494 * Return: 0 on success and -EIO on write failure
495 */
496int mei_hbm_cl_notify_req(struct mei_device *dev,
497			  struct mei_cl *cl, u8 start)
498{
499
500	struct mei_msg_hdr mei_hdr;
501	struct hbm_notification_request req;
502	int ret;
503
504	mei_hbm_hdr(&mei_hdr, sizeof(req));
505	mei_hbm_cl_hdr(cl, MEI_HBM_NOTIFY_REQ_CMD, &req, sizeof(req));
506
507	req.start = start;
508
509	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
510	if (ret)
511		dev_err(dev->dev, "notify request failed: ret = %d\n", ret);
512
513	return ret;
514}
515
516/**
517 *  notify_res_to_fop - convert notification response to the proper
518 *      notification FOP
519 *
520 * @cmd: client notification start response command
521 *
522 * Return:  MEI_FOP_NOTIFY_START or MEI_FOP_NOTIFY_STOP;
523 */
524static inline enum mei_cb_file_ops notify_res_to_fop(struct mei_hbm_cl_cmd *cmd)
525{
526	struct hbm_notification_response *rs =
527		(struct hbm_notification_response *)cmd;
528
529	return mei_cl_notify_req2fop(rs->start);
530}
531
532/**
533 * mei_hbm_cl_notify_start_res - update the client state according
534 *       notify start response
535 *
536 * @dev: the device structure
537 * @cl: mei host client
538 * @cmd: client notification start response command
539 */
540static void mei_hbm_cl_notify_start_res(struct mei_device *dev,
541					struct mei_cl *cl,
542					struct mei_hbm_cl_cmd *cmd)
543{
544	struct hbm_notification_response *rs =
545		(struct hbm_notification_response *)cmd;
546
547	cl_dbg(dev, cl, "hbm: notify start response status=%d\n", rs->status);
548
549	if (rs->status == MEI_HBMS_SUCCESS ||
550	    rs->status == MEI_HBMS_ALREADY_STARTED) {
551		cl->notify_en = true;
552		cl->status = 0;
553	} else {
554		cl->status = -EINVAL;
555	}
556}
557
558/**
559 * mei_hbm_cl_notify_stop_res - update the client state according
560 *       notify stop response
561 *
562 * @dev: the device structure
563 * @cl: mei host client
564 * @cmd: client notification stop response command
565 */
566static void mei_hbm_cl_notify_stop_res(struct mei_device *dev,
567				       struct mei_cl *cl,
568				       struct mei_hbm_cl_cmd *cmd)
569{
570	struct hbm_notification_response *rs =
571		(struct hbm_notification_response *)cmd;
572
573	cl_dbg(dev, cl, "hbm: notify stop response status=%d\n", rs->status);
574
575	if (rs->status == MEI_HBMS_SUCCESS ||
576	    rs->status == MEI_HBMS_NOT_STARTED) {
577		cl->notify_en = false;
578		cl->status = 0;
579	} else {
580		/* TODO: spec is not clear yet about other possible issues */
581		cl->status = -EINVAL;
582	}
583}
584
585/**
586 * mei_hbm_cl_notify - signal notification event
587 *
588 * @dev: the device structure
589 * @cmd: notification client message
590 */
591static void mei_hbm_cl_notify(struct mei_device *dev,
592			      struct mei_hbm_cl_cmd *cmd)
593{
594	struct mei_cl *cl;
595
596	cl = mei_hbm_cl_find_by_cmd(dev, cmd);
597	if (cl)
598		mei_cl_notify(cl);
599}
600
601/**
602 * mei_hbm_cl_dma_map_req - send client dma map request
603 *
604 * @dev: the device structure
605 * @cl: mei host client
606 *
607 * Return: 0 on success and -EIO on write failure
608 */
609int mei_hbm_cl_dma_map_req(struct mei_device *dev, struct mei_cl *cl)
610{
611	struct mei_msg_hdr mei_hdr;
612	struct hbm_client_dma_map_request req;
613	int ret;
614
615	mei_hbm_hdr(&mei_hdr, sizeof(req));
616
617	memset(&req, 0, sizeof(req));
618
619	req.hbm_cmd = MEI_HBM_CLIENT_DMA_MAP_REQ_CMD;
620	req.client_buffer_id = cl->dma.buffer_id;
621	req.address_lsb = lower_32_bits(cl->dma.daddr);
622	req.address_msb = upper_32_bits(cl->dma.daddr);
623	req.size = cl->dma.size;
624
625	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
626	if (ret)
627		dev_err(dev->dev, "dma map request failed: ret = %d\n", ret);
628
629	return ret;
630}
631
632/**
633 * mei_hbm_cl_dma_unmap_req - send client dma unmap request
634 *
635 * @dev: the device structure
636 * @cl: mei host client
637 *
638 * Return: 0 on success and -EIO on write failure
639 */
640int mei_hbm_cl_dma_unmap_req(struct mei_device *dev, struct mei_cl *cl)
641{
642	struct mei_msg_hdr mei_hdr;
643	struct hbm_client_dma_unmap_request req;
644	int ret;
645
646	mei_hbm_hdr(&mei_hdr, sizeof(req));
647
648	memset(&req, 0, sizeof(req));
649
650	req.hbm_cmd = MEI_HBM_CLIENT_DMA_UNMAP_REQ_CMD;
651	req.client_buffer_id = cl->dma.buffer_id;
652
653	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
654	if (ret)
655		dev_err(dev->dev, "dma unmap request failed: ret = %d\n", ret);
656
657	return ret;
658}
659
660static void mei_hbm_cl_dma_map_res(struct mei_device *dev,
661				   struct hbm_client_dma_response *res)
662{
663	struct mei_cl *cl;
664	struct mei_cl_cb *cb, *next;
665
666	cl = NULL;
667	list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list, list) {
668		if (cb->fop_type != MEI_FOP_DMA_MAP)
669			continue;
670		if (!cb->cl->dma.buffer_id || cb->cl->dma_mapped)
671			continue;
672
673		cl = cb->cl;
674		break;
675	}
676	if (!cl)
677		return;
678
679	if (res->status) {
680		dev_err(dev->dev, "cl dma map failed %d\n", res->status);
681		cl->status = -EFAULT;
682	} else {
683		dev_dbg(dev->dev, "cl dma map succeeded\n");
684		cl->dma_mapped = 1;
685		cl->status = 0;
686	}
687	wake_up(&cl->wait);
688}
689
690static void mei_hbm_cl_dma_unmap_res(struct mei_device *dev,
691				     struct hbm_client_dma_response *res)
692{
693	struct mei_cl *cl;
694	struct mei_cl_cb *cb, *next;
695
696	cl = NULL;
697	list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list, list) {
698		if (cb->fop_type != MEI_FOP_DMA_UNMAP)
699			continue;
700		if (!cb->cl->dma.buffer_id || !cb->cl->dma_mapped)
701			continue;
702
703		cl = cb->cl;
704		break;
705	}
706	if (!cl)
707		return;
708
709	if (res->status) {
710		dev_err(dev->dev, "cl dma unmap failed %d\n", res->status);
711		cl->status = -EFAULT;
712	} else {
713		dev_dbg(dev->dev, "cl dma unmap succeeded\n");
714		cl->dma_mapped = 0;
715		cl->status = 0;
716	}
717	wake_up(&cl->wait);
718}
719
720/**
721 * mei_hbm_prop_req - request property for a single client
722 *
723 * @dev: the device structure
724 * @start_idx: client index to start search
725 *
726 * Return: 0 on success and < 0 on failure
727 */
728static int mei_hbm_prop_req(struct mei_device *dev, unsigned long start_idx)
729{
730	struct mei_msg_hdr mei_hdr;
731	struct hbm_props_request req;
732	unsigned long addr;
733	int ret;
734
735	addr = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, start_idx);
736
737	/* We got all client properties */
738	if (addr == MEI_CLIENTS_MAX) {
739		dev->hbm_state = MEI_HBM_STARTED;
740		mei_host_client_init(dev);
741		return 0;
742	}
743
744	mei_hbm_hdr(&mei_hdr, sizeof(req));
745
746	memset(&req, 0, sizeof(req));
747
748	req.hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
749	req.me_addr = addr;
750
751	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
752	if (ret) {
753		dev_err(dev->dev, "properties request write failed: ret = %d\n",
754			ret);
755		return ret;
756	}
757
758	dev->init_clients_timer = dev->timeouts.client_init;
759	mei_schedule_stall_timer(dev);
760
761	return 0;
762}
763
764/**
765 * mei_hbm_pg - sends pg command
766 *
767 * @dev: the device structure
768 * @pg_cmd: the pg command code
769 *
770 * Return: -EIO on write failure
771 *         -EOPNOTSUPP if the operation is not supported by the protocol
772 */
773int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
774{
775	struct mei_msg_hdr mei_hdr;
776	struct hbm_power_gate req;
777	int ret;
778
779	if (!dev->hbm_f_pg_supported)
780		return -EOPNOTSUPP;
781
782	mei_hbm_hdr(&mei_hdr, sizeof(req));
783
784	memset(&req, 0, sizeof(req));
785	req.hbm_cmd = pg_cmd;
786
787	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
788	if (ret)
789		dev_err(dev->dev, "power gate command write failed.\n");
790	return ret;
791}
792EXPORT_SYMBOL_GPL(mei_hbm_pg);
793
794/**
795 * mei_hbm_stop_req - send stop request message
796 *
797 * @dev: mei device
798 *
799 * Return: -EIO on write failure
800 */
801static int mei_hbm_stop_req(struct mei_device *dev)
802{
803	struct mei_msg_hdr mei_hdr;
804	struct hbm_host_stop_request req;
805
806	mei_hbm_hdr(&mei_hdr, sizeof(req));
807
808	memset(&req, 0, sizeof(req));
809	req.hbm_cmd = HOST_STOP_REQ_CMD;
810	req.reason = DRIVER_STOP_REQUEST;
811
812	return mei_hbm_write_message(dev, &mei_hdr, &req);
813}
814
815/**
816 * mei_hbm_cl_flow_control_req - sends flow control request.
817 *
818 * @dev: the device structure
819 * @cl: client info
820 *
821 * Return: -EIO on write failure
822 */
823int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
824{
825	struct hbm_flow_control req;
826
827	cl_dbg(dev, cl, "sending flow control\n");
828	return mei_hbm_cl_write(dev, cl, MEI_FLOW_CONTROL_CMD,
829				&req, sizeof(req));
830}
831
832/**
833 * mei_hbm_add_single_tx_flow_ctrl_creds - adds single buffer credentials.
834 *
835 * @dev: the device structure
836 * @fctrl: flow control response bus message
837 *
838 * Return: 0 on success, < 0 otherwise
839 */
840static int mei_hbm_add_single_tx_flow_ctrl_creds(struct mei_device *dev,
841						 struct hbm_flow_control *fctrl)
842{
843	struct mei_me_client *me_cl;
844	int rets;
845
846	me_cl = mei_me_cl_by_id(dev, fctrl->me_addr);
847	if (!me_cl) {
848		dev_err(dev->dev, "no such me client %d\n", fctrl->me_addr);
849		return -ENOENT;
850	}
851
852	if (WARN_ON(me_cl->props.single_recv_buf == 0)) {
853		rets = -EINVAL;
854		goto out;
855	}
856
857	me_cl->tx_flow_ctrl_creds++;
858	dev_dbg(dev->dev, "recv flow ctrl msg ME %d (single) creds = %d.\n",
859		fctrl->me_addr, me_cl->tx_flow_ctrl_creds);
860
861	rets = 0;
862out:
863	mei_me_cl_put(me_cl);
864	return rets;
865}
866
867/**
868 * mei_hbm_cl_tx_flow_ctrl_creds_res - flow control response from me
869 *
870 * @dev: the device structure
871 * @fctrl: flow control response bus message
872 */
873static void mei_hbm_cl_tx_flow_ctrl_creds_res(struct mei_device *dev,
874					       struct hbm_flow_control *fctrl)
875{
876	struct mei_cl *cl;
877
878	if (!fctrl->host_addr) {
879		/* single receive buffer */
880		mei_hbm_add_single_tx_flow_ctrl_creds(dev, fctrl);
881		return;
882	}
883
884	cl = mei_hbm_cl_find_by_cmd(dev, fctrl);
885	if (cl) {
886		cl->tx_flow_ctrl_creds++;
887		cl_dbg(dev, cl, "flow control creds = %d.\n",
888				cl->tx_flow_ctrl_creds);
889	}
890}
891
892
893/**
894 * mei_hbm_cl_disconnect_req - sends disconnect message to fw.
895 *
896 * @dev: the device structure
897 * @cl: a client to disconnect from
898 *
899 * Return: -EIO on write failure
900 */
901int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
902{
903	struct hbm_client_connect_request req;
904
905	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_REQ_CMD,
906				&req, sizeof(req));
907}
908
909/**
910 * mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW
911 *
912 * @dev: the device structure
913 * @cl: a client to disconnect from
914 *
915 * Return: -EIO on write failure
916 */
917int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
918{
919	struct hbm_client_connect_response resp;
920
921	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_RES_CMD,
922				&resp, sizeof(resp));
923}
924
925/**
926 * mei_hbm_cl_disconnect_res - update the client state according
927 *       disconnect response
928 *
929 * @dev: the device structure
930 * @cl: mei host client
931 * @cmd: disconnect client response host bus message
932 */
933static void mei_hbm_cl_disconnect_res(struct mei_device *dev, struct mei_cl *cl,
934				      struct mei_hbm_cl_cmd *cmd)
935{
936	struct hbm_client_connect_response *rs =
937		(struct hbm_client_connect_response *)cmd;
938
939	cl_dbg(dev, cl, "hbm: disconnect response status=%d\n", rs->status);
940
941	if (rs->status == MEI_CL_DISCONN_SUCCESS)
942		cl->state = MEI_FILE_DISCONNECT_REPLY;
943	cl->status = 0;
944}
945
946/**
947 * mei_hbm_cl_connect_req - send connection request to specific me client
948 *
949 * @dev: the device structure
950 * @cl: a client to connect to
951 *
952 * Return: -EIO on write failure
953 */
954int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
955{
956	struct hbm_client_connect_request req;
957
958	return mei_hbm_cl_write(dev, cl, CLIENT_CONNECT_REQ_CMD,
959				&req, sizeof(req));
960}
961
962/**
963 * mei_hbm_cl_connect_res - update the client state according
964 *        connection response
965 *
966 * @dev: the device structure
967 * @cl: mei host client
968 * @cmd: connect client response host bus message
969 */
970static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl,
971				   struct mei_hbm_cl_cmd *cmd)
972{
973	struct hbm_client_connect_response *rs =
974		(struct hbm_client_connect_response *)cmd;
975
976	cl_dbg(dev, cl, "hbm: connect response status=%s\n",
977			mei_cl_conn_status_str(rs->status));
978
979	if (rs->status == MEI_CL_CONN_SUCCESS)
980		cl->state = MEI_FILE_CONNECTED;
981	else {
982		cl->state = MEI_FILE_DISCONNECT_REPLY;
983		if (rs->status == MEI_CL_CONN_NOT_FOUND) {
984			mei_me_cl_del(dev, cl->me_cl);
985			if (dev->dev_state == MEI_DEV_ENABLED)
986				schedule_work(&dev->bus_rescan_work);
987		}
988	}
989	cl->status = mei_cl_conn_status_to_errno(rs->status);
990}
991
992/**
993 * mei_hbm_cl_res - process hbm response received on behalf
994 *         an client
995 *
996 * @dev: the device structure
997 * @rs:  hbm client message
998 * @fop_type: file operation type
999 */
1000static void mei_hbm_cl_res(struct mei_device *dev,
1001			   struct mei_hbm_cl_cmd *rs,
1002			   enum mei_cb_file_ops fop_type)
1003{
1004	struct mei_cl *cl;
1005	struct mei_cl_cb *cb, *next;
1006
1007	cl = NULL;
1008	list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list, list) {
1009
1010		cl = cb->cl;
1011
1012		if (cb->fop_type != fop_type)
1013			continue;
1014
1015		if (mei_hbm_cl_addr_equal(cl, rs)) {
1016			list_del_init(&cb->list);
1017			break;
1018		}
1019	}
1020
1021	if (!cl)
1022		return;
1023
1024	switch (fop_type) {
1025	case MEI_FOP_CONNECT:
1026		mei_hbm_cl_connect_res(dev, cl, rs);
1027		break;
1028	case MEI_FOP_DISCONNECT:
1029		mei_hbm_cl_disconnect_res(dev, cl, rs);
1030		break;
1031	case MEI_FOP_NOTIFY_START:
1032		mei_hbm_cl_notify_start_res(dev, cl, rs);
1033		break;
1034	case MEI_FOP_NOTIFY_STOP:
1035		mei_hbm_cl_notify_stop_res(dev, cl, rs);
1036		break;
1037	default:
1038		return;
1039	}
1040
1041	cl->timer_count = 0;
1042	wake_up(&cl->wait);
1043}
1044
1045
1046/**
1047 * mei_hbm_fw_disconnect_req - disconnect request initiated by ME firmware
1048 *  host sends disconnect response
1049 *
1050 * @dev: the device structure.
1051 * @disconnect_req: disconnect request bus message from the me
1052 *
1053 * Return: -ENOMEM on allocation failure
1054 */
1055static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
1056		struct hbm_client_connect_request *disconnect_req)
1057{
1058	struct mei_cl *cl;
1059	struct mei_cl_cb *cb;
1060
1061	cl = mei_hbm_cl_find_by_cmd(dev, disconnect_req);
1062	if (cl) {
1063		cl_warn(dev, cl, "fw disconnect request received\n");
1064		cl->state = MEI_FILE_DISCONNECTING;
1065		cl->timer_count = 0;
1066
1067		cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT_RSP,
1068					       NULL);
1069		if (!cb)
1070			return -ENOMEM;
1071	}
1072	return 0;
1073}
1074
1075/**
1076 * mei_hbm_pg_enter_res - PG enter response received
1077 *
1078 * @dev: the device structure.
1079 *
1080 * Return: 0 on success, -EPROTO on state mismatch
1081 */
1082static int mei_hbm_pg_enter_res(struct mei_device *dev)
1083{
1084	if (mei_pg_state(dev) != MEI_PG_OFF ||
1085	    dev->pg_event != MEI_PG_EVENT_WAIT) {
1086		dev_err(dev->dev, "hbm: pg entry response: state mismatch [%s, %d]\n",
1087			mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
1088		return -EPROTO;
1089	}
1090
1091	dev->pg_event = MEI_PG_EVENT_RECEIVED;
1092	wake_up(&dev->wait_pg);
1093
1094	return 0;
1095}
1096
1097/**
1098 * mei_hbm_pg_resume - process with PG resume
1099 *
1100 * @dev: the device structure.
1101 */
1102void mei_hbm_pg_resume(struct mei_device *dev)
1103{
1104	pm_request_resume(dev->dev);
1105}
1106EXPORT_SYMBOL_GPL(mei_hbm_pg_resume);
1107
1108/**
1109 * mei_hbm_pg_exit_res - PG exit response received
1110 *
1111 * @dev: the device structure.
1112 *
1113 * Return: 0 on success, -EPROTO on state mismatch
1114 */
1115static int mei_hbm_pg_exit_res(struct mei_device *dev)
1116{
1117	if (mei_pg_state(dev) != MEI_PG_ON ||
1118	    (dev->pg_event != MEI_PG_EVENT_WAIT &&
1119	     dev->pg_event != MEI_PG_EVENT_IDLE)) {
1120		dev_err(dev->dev, "hbm: pg exit response: state mismatch [%s, %d]\n",
1121			mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
1122		return -EPROTO;
1123	}
1124
1125	switch (dev->pg_event) {
1126	case MEI_PG_EVENT_WAIT:
1127		dev->pg_event = MEI_PG_EVENT_RECEIVED;
1128		wake_up(&dev->wait_pg);
1129		break;
1130	case MEI_PG_EVENT_IDLE:
1131		/*
1132		* If the driver is not waiting on this then
1133		* this is HW initiated exit from PG.
1134		* Start runtime pm resume sequence to exit from PG.
1135		*/
1136		dev->pg_event = MEI_PG_EVENT_RECEIVED;
1137		mei_hbm_pg_resume(dev);
1138		break;
1139	default:
1140		WARN(1, "hbm: pg exit response: unexpected pg event = %d\n",
1141		     dev->pg_event);
1142		return -EPROTO;
1143	}
1144
1145	return 0;
1146}
1147
1148/**
1149 * mei_hbm_config_features - check what hbm features and commands
1150 *        are supported by the fw
1151 *
1152 * @dev: the device structure
1153 */
1154static void mei_hbm_config_features(struct mei_device *dev)
1155{
1156	/* Power Gating Isolation Support */
1157	dev->hbm_f_pg_supported = 0;
1158	if (dev->version.major_version > HBM_MAJOR_VERSION_PGI)
1159		dev->hbm_f_pg_supported = 1;
1160
1161	if (dev->version.major_version == HBM_MAJOR_VERSION_PGI &&
1162	    dev->version.minor_version >= HBM_MINOR_VERSION_PGI)
1163		dev->hbm_f_pg_supported = 1;
1164
1165	dev->hbm_f_dc_supported = 0;
1166	if (dev->version.major_version >= HBM_MAJOR_VERSION_DC)
1167		dev->hbm_f_dc_supported = 1;
1168
1169	dev->hbm_f_ie_supported = 0;
1170	if (dev->version.major_version >= HBM_MAJOR_VERSION_IE)
1171		dev->hbm_f_ie_supported = 1;
1172
1173	/* disconnect on connect timeout instead of link reset */
1174	dev->hbm_f_dot_supported = 0;
1175	if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT)
1176		dev->hbm_f_dot_supported = 1;
1177
1178	/* Notification Event Support */
1179	dev->hbm_f_ev_supported = 0;
1180	if (dev->version.major_version >= HBM_MAJOR_VERSION_EV)
1181		dev->hbm_f_ev_supported = 1;
1182
1183	/* Fixed Address Client Support */
1184	dev->hbm_f_fa_supported = 0;
1185	if (dev->version.major_version >= HBM_MAJOR_VERSION_FA)
1186		dev->hbm_f_fa_supported = 1;
1187
1188	/* OS ver message Support */
1189	dev->hbm_f_os_supported = 0;
1190	if (dev->version.major_version >= HBM_MAJOR_VERSION_OS)
1191		dev->hbm_f_os_supported = 1;
1192
1193	/* DMA Ring Support */
1194	dev->hbm_f_dr_supported = 0;
1195	if (dev->version.major_version > HBM_MAJOR_VERSION_DR ||
1196	    (dev->version.major_version == HBM_MAJOR_VERSION_DR &&
1197	     dev->version.minor_version >= HBM_MINOR_VERSION_DR))
1198		dev->hbm_f_dr_supported = 1;
1199
1200	/* VTag Support */
1201	dev->hbm_f_vt_supported = 0;
1202	if (dev->version.major_version > HBM_MAJOR_VERSION_VT ||
1203	    (dev->version.major_version == HBM_MAJOR_VERSION_VT &&
1204	     dev->version.minor_version >= HBM_MINOR_VERSION_VT))
1205		dev->hbm_f_vt_supported = 1;
1206
1207	/* GSC support */
1208	if (dev->version.major_version > HBM_MAJOR_VERSION_GSC ||
1209	    (dev->version.major_version == HBM_MAJOR_VERSION_GSC &&
1210	     dev->version.minor_version >= HBM_MINOR_VERSION_GSC))
1211		dev->hbm_f_gsc_supported = 1;
1212
1213	/* Capability message Support */
1214	dev->hbm_f_cap_supported = 0;
1215	if (dev->version.major_version > HBM_MAJOR_VERSION_CAP ||
1216	    (dev->version.major_version == HBM_MAJOR_VERSION_CAP &&
1217	     dev->version.minor_version >= HBM_MINOR_VERSION_CAP))
1218		dev->hbm_f_cap_supported = 1;
1219
1220	/* Client DMA Support */
1221	dev->hbm_f_cd_supported = 0;
1222	if (dev->version.major_version > HBM_MAJOR_VERSION_CD ||
1223	    (dev->version.major_version == HBM_MAJOR_VERSION_CD &&
1224	     dev->version.minor_version >= HBM_MINOR_VERSION_CD))
1225		dev->hbm_f_cd_supported = 1;
1226}
1227
1228/**
1229 * mei_hbm_version_is_supported - checks whether the driver can
1230 *     support the hbm version of the device
1231 *
1232 * @dev: the device structure
1233 * Return: true if driver can support hbm version of the device
1234 */
1235bool mei_hbm_version_is_supported(struct mei_device *dev)
1236{
1237	return	(dev->version.major_version < HBM_MAJOR_VERSION) ||
1238		(dev->version.major_version == HBM_MAJOR_VERSION &&
1239		 dev->version.minor_version <= HBM_MINOR_VERSION);
1240}
1241
1242/**
1243 * mei_hbm_dispatch - bottom half read routine after ISR to
1244 * handle the read bus message cmd processing.
1245 *
1246 * @dev: the device structure
1247 * @hdr: header of bus message
1248 *
1249 * Return: 0 on success and < 0 on failure
1250 */
1251int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
1252{
1253	struct mei_bus_message *mei_msg;
1254	struct hbm_host_version_response *version_res;
1255	struct hbm_props_response *props_res;
1256	struct hbm_host_enum_response *enum_res;
1257	struct hbm_dma_setup_response *dma_setup_res;
1258	struct hbm_add_client_request *add_cl_req;
1259	struct hbm_capability_response *capability_res;
1260	int ret;
1261
1262	struct mei_hbm_cl_cmd *cl_cmd;
1263	struct hbm_client_connect_request *disconnect_req;
1264	struct hbm_flow_control *fctrl;
1265	struct hbm_client_dma_response *client_dma_res;
1266
1267	/* read the message to our buffer */
1268	BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf));
1269	mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
1270	mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
1271	cl_cmd  = (struct mei_hbm_cl_cmd *)mei_msg;
1272
1273	/* ignore spurious message and prevent reset nesting
1274	 * hbm is put to idle during system reset
1275	 */
1276	if (dev->hbm_state == MEI_HBM_IDLE) {
1277		dev_dbg(dev->dev, "hbm: state is idle ignore spurious messages\n");
1278		return 0;
1279	}
1280
1281	switch (mei_msg->hbm_cmd) {
1282	case HOST_START_RES_CMD:
1283		dev_dbg(dev->dev, "hbm: start: response message received.\n");
1284
1285		dev->init_clients_timer = 0;
1286
1287		version_res = (struct hbm_host_version_response *)mei_msg;
1288
1289		dev_dbg(dev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n",
1290				HBM_MAJOR_VERSION, HBM_MINOR_VERSION,
1291				version_res->me_max_version.major_version,
1292				version_res->me_max_version.minor_version);
1293
1294		if (version_res->host_version_supported) {
1295			dev->version.major_version = HBM_MAJOR_VERSION;
1296			dev->version.minor_version = HBM_MINOR_VERSION;
1297		} else {
1298			dev->version.major_version =
1299				version_res->me_max_version.major_version;
1300			dev->version.minor_version =
1301				version_res->me_max_version.minor_version;
1302		}
1303
1304		if (!mei_hbm_version_is_supported(dev)) {
1305			dev_warn(dev->dev, "hbm: start: version mismatch - stopping the driver.\n");
1306
1307			dev->hbm_state = MEI_HBM_STOPPED;
1308			if (mei_hbm_stop_req(dev)) {
1309				dev_err(dev->dev, "hbm: start: failed to send stop request\n");
1310				return -EIO;
1311			}
1312			break;
1313		}
1314
1315		mei_hbm_config_features(dev);
1316
1317		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1318		    dev->hbm_state != MEI_HBM_STARTING) {
1319			if (dev->dev_state == MEI_DEV_POWER_DOWN ||
1320			    dev->dev_state == MEI_DEV_POWERING_DOWN) {
1321				dev_dbg(dev->dev, "hbm: start: on shutdown, ignoring\n");
1322				return 0;
1323			}
1324			dev_err(dev->dev, "hbm: start: state mismatch, [%d, %d]\n",
1325				dev->dev_state, dev->hbm_state);
1326			return -EPROTO;
1327		}
1328
1329		if (dev->hbm_f_cap_supported) {
1330			if (mei_hbm_capabilities_req(dev))
1331				return -EIO;
1332			wake_up(&dev->wait_hbm_start);
1333			break;
1334		}
1335
1336		if (dev->hbm_f_dr_supported) {
1337			if (mei_dmam_ring_alloc(dev))
1338				dev_info(dev->dev, "running w/o dma ring\n");
1339			if (mei_dma_ring_is_allocated(dev)) {
1340				if (mei_hbm_dma_setup_req(dev))
1341					return -EIO;
1342
1343				wake_up(&dev->wait_hbm_start);
1344				break;
1345			}
1346		}
1347
1348		dev->hbm_f_dr_supported = 0;
1349		mei_dmam_ring_free(dev);
1350
1351		if (mei_hbm_enum_clients_req(dev))
1352			return -EIO;
1353
1354		wake_up(&dev->wait_hbm_start);
1355		break;
1356
1357	case MEI_HBM_CAPABILITIES_RES_CMD:
1358		dev_dbg(dev->dev, "hbm: capabilities response: message received.\n");
1359
1360		dev->init_clients_timer = 0;
1361
1362		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1363		    dev->hbm_state != MEI_HBM_CAP_SETUP) {
1364			if (dev->dev_state == MEI_DEV_POWER_DOWN ||
1365			    dev->dev_state == MEI_DEV_POWERING_DOWN) {
1366				dev_dbg(dev->dev, "hbm: capabilities response: on shutdown, ignoring\n");
1367				return 0;
1368			}
1369			dev_err(dev->dev, "hbm: capabilities response: state mismatch, [%d, %d]\n",
1370				dev->dev_state, dev->hbm_state);
1371			return -EPROTO;
1372		}
1373
1374		capability_res = (struct hbm_capability_response *)mei_msg;
1375		if (!(capability_res->capability_granted[0] & HBM_CAP_VT))
1376			dev->hbm_f_vt_supported = 0;
1377		if (!(capability_res->capability_granted[0] & HBM_CAP_CD))
1378			dev->hbm_f_cd_supported = 0;
1379
1380		if (!(capability_res->capability_granted[0] & HBM_CAP_GSC))
1381			dev->hbm_f_gsc_supported = 0;
1382
1383		if (dev->hbm_f_dr_supported) {
1384			if (mei_dmam_ring_alloc(dev))
1385				dev_info(dev->dev, "running w/o dma ring\n");
1386			if (mei_dma_ring_is_allocated(dev)) {
1387				if (mei_hbm_dma_setup_req(dev))
1388					return -EIO;
1389				break;
1390			}
1391		}
1392
1393		dev->hbm_f_dr_supported = 0;
1394		mei_dmam_ring_free(dev);
1395
1396		if (mei_hbm_enum_clients_req(dev))
1397			return -EIO;
1398		break;
1399
1400	case MEI_HBM_DMA_SETUP_RES_CMD:
1401		dev_dbg(dev->dev, "hbm: dma setup response: message received.\n");
1402
1403		dev->init_clients_timer = 0;
1404
1405		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1406		    dev->hbm_state != MEI_HBM_DR_SETUP) {
1407			if (dev->dev_state == MEI_DEV_POWER_DOWN ||
1408			    dev->dev_state == MEI_DEV_POWERING_DOWN) {
1409				dev_dbg(dev->dev, "hbm: dma setup response: on shutdown, ignoring\n");
1410				return 0;
1411			}
1412			dev_err(dev->dev, "hbm: dma setup response: state mismatch, [%d, %d]\n",
1413				dev->dev_state, dev->hbm_state);
1414			return -EPROTO;
1415		}
1416
1417		dma_setup_res = (struct hbm_dma_setup_response *)mei_msg;
1418
1419		if (dma_setup_res->status) {
1420			u8 status = dma_setup_res->status;
1421
1422			if (status == MEI_HBMS_NOT_ALLOWED) {
1423				dev_dbg(dev->dev, "hbm: dma setup not allowed\n");
1424			} else {
1425				dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
1426					 status,
1427					 mei_hbm_status_str(status));
1428			}
1429			dev->hbm_f_dr_supported = 0;
1430			mei_dmam_ring_free(dev);
1431		}
1432
1433		if (mei_hbm_enum_clients_req(dev))
1434			return -EIO;
1435		break;
1436
1437	case CLIENT_CONNECT_RES_CMD:
1438		dev_dbg(dev->dev, "hbm: client connect response: message received.\n");
1439		mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_CONNECT);
1440		break;
1441
1442	case CLIENT_DISCONNECT_RES_CMD:
1443		dev_dbg(dev->dev, "hbm: client disconnect response: message received.\n");
1444		mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_DISCONNECT);
1445		break;
1446
1447	case MEI_FLOW_CONTROL_CMD:
1448		dev_dbg(dev->dev, "hbm: client flow control response: message received.\n");
1449
1450		fctrl = (struct hbm_flow_control *)mei_msg;
1451		mei_hbm_cl_tx_flow_ctrl_creds_res(dev, fctrl);
1452		break;
1453
1454	case MEI_PG_ISOLATION_ENTRY_RES_CMD:
1455		dev_dbg(dev->dev, "hbm: power gate isolation entry response received\n");
1456		ret = mei_hbm_pg_enter_res(dev);
1457		if (ret)
1458			return ret;
1459		break;
1460
1461	case MEI_PG_ISOLATION_EXIT_REQ_CMD:
1462		dev_dbg(dev->dev, "hbm: power gate isolation exit request received\n");
1463		ret = mei_hbm_pg_exit_res(dev);
1464		if (ret)
1465			return ret;
1466		break;
1467
1468	case HOST_CLIENT_PROPERTIES_RES_CMD:
1469		dev_dbg(dev->dev, "hbm: properties response: message received.\n");
1470
1471		dev->init_clients_timer = 0;
1472
1473		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1474		    dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
1475			if (dev->dev_state == MEI_DEV_POWER_DOWN ||
1476			    dev->dev_state == MEI_DEV_POWERING_DOWN) {
1477				dev_dbg(dev->dev, "hbm: properties response: on shutdown, ignoring\n");
1478				return 0;
1479			}
1480			dev_err(dev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
1481				dev->dev_state, dev->hbm_state);
1482			return -EPROTO;
1483		}
1484
1485		props_res = (struct hbm_props_response *)mei_msg;
1486
1487		if (props_res->status == MEI_HBMS_CLIENT_NOT_FOUND) {
1488			dev_dbg(dev->dev, "hbm: properties response: %d CLIENT_NOT_FOUND\n",
1489				props_res->me_addr);
1490		} else if (props_res->status) {
1491			dev_err(dev->dev, "hbm: properties response: wrong status = %d %s\n",
1492				props_res->status,
1493				mei_hbm_status_str(props_res->status));
1494			return -EPROTO;
1495		} else {
1496			mei_hbm_me_cl_add(dev, props_res);
1497		}
1498
1499		/* request property for the next client */
1500		if (mei_hbm_prop_req(dev, props_res->me_addr + 1))
1501			return -EIO;
1502
1503		break;
1504
1505	case HOST_ENUM_RES_CMD:
1506		dev_dbg(dev->dev, "hbm: enumeration response: message received\n");
1507
1508		dev->init_clients_timer = 0;
1509
1510		enum_res = (struct hbm_host_enum_response *) mei_msg;
1511		BUILD_BUG_ON(sizeof(dev->me_clients_map)
1512				< sizeof(enum_res->valid_addresses));
1513		memcpy(dev->me_clients_map, enum_res->valid_addresses,
1514				sizeof(enum_res->valid_addresses));
1515
1516		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1517		    dev->hbm_state != MEI_HBM_ENUM_CLIENTS) {
1518			if (dev->dev_state == MEI_DEV_POWER_DOWN ||
1519			    dev->dev_state == MEI_DEV_POWERING_DOWN) {
1520				dev_dbg(dev->dev, "hbm: enumeration response: on shutdown, ignoring\n");
1521				return 0;
1522			}
1523			dev_err(dev->dev, "hbm: enumeration response: state mismatch, [%d, %d]\n",
1524				dev->dev_state, dev->hbm_state);
1525			return -EPROTO;
1526		}
1527
1528		dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
1529
1530		/* first property request */
1531		if (mei_hbm_prop_req(dev, 0))
1532			return -EIO;
1533
1534		break;
1535
1536	case HOST_STOP_RES_CMD:
1537		dev_dbg(dev->dev, "hbm: stop response: message received\n");
1538
1539		dev->init_clients_timer = 0;
1540
1541		if (dev->hbm_state != MEI_HBM_STOPPED) {
1542			dev_err(dev->dev, "hbm: stop response: state mismatch, [%d, %d]\n",
1543				dev->dev_state, dev->hbm_state);
1544			return -EPROTO;
1545		}
1546
1547		mei_set_devstate(dev, MEI_DEV_POWER_DOWN);
1548		dev_info(dev->dev, "hbm: stop response: resetting.\n");
1549		/* force the reset */
1550		return -EPROTO;
1551
1552	case CLIENT_DISCONNECT_REQ_CMD:
1553		dev_dbg(dev->dev, "hbm: disconnect request: message received\n");
1554
1555		disconnect_req = (struct hbm_client_connect_request *)mei_msg;
1556		mei_hbm_fw_disconnect_req(dev, disconnect_req);
1557		break;
1558
1559	case ME_STOP_REQ_CMD:
1560		dev_dbg(dev->dev, "hbm: stop request: message received\n");
1561		dev->hbm_state = MEI_HBM_STOPPED;
1562		if (mei_hbm_stop_req(dev)) {
1563			dev_err(dev->dev, "hbm: stop request: failed to send stop request\n");
1564			return -EIO;
1565		}
1566		break;
1567
1568	case MEI_HBM_ADD_CLIENT_REQ_CMD:
1569		dev_dbg(dev->dev, "hbm: add client request received\n");
1570		/*
1571		 * after the host receives the enum_resp
1572		 * message clients may be added or removed
1573		 */
1574		if (dev->hbm_state <= MEI_HBM_ENUM_CLIENTS ||
1575		    dev->hbm_state >= MEI_HBM_STOPPED) {
1576			dev_err(dev->dev, "hbm: add client: state mismatch, [%d, %d]\n",
1577				dev->dev_state, dev->hbm_state);
1578			return -EPROTO;
1579		}
1580		add_cl_req = (struct hbm_add_client_request *)mei_msg;
1581		ret = mei_hbm_fw_add_cl_req(dev, add_cl_req);
1582		if (ret) {
1583			dev_err(dev->dev, "hbm: add client: failed to send response %d\n",
1584				ret);
1585			return -EIO;
1586		}
1587		dev_dbg(dev->dev, "hbm: add client request processed\n");
1588		break;
1589
1590	case MEI_HBM_NOTIFY_RES_CMD:
1591		dev_dbg(dev->dev, "hbm: notify response received\n");
1592		mei_hbm_cl_res(dev, cl_cmd, notify_res_to_fop(cl_cmd));
1593		break;
1594
1595	case MEI_HBM_NOTIFICATION_CMD:
1596		dev_dbg(dev->dev, "hbm: notification\n");
1597		mei_hbm_cl_notify(dev, cl_cmd);
1598		break;
1599
1600	case MEI_HBM_CLIENT_DMA_MAP_RES_CMD:
1601		dev_dbg(dev->dev, "hbm: client dma map response: message received.\n");
1602		client_dma_res = (struct hbm_client_dma_response *)mei_msg;
1603		mei_hbm_cl_dma_map_res(dev, client_dma_res);
1604		break;
1605
1606	case MEI_HBM_CLIENT_DMA_UNMAP_RES_CMD:
1607		dev_dbg(dev->dev, "hbm: client dma unmap response: message received.\n");
1608		client_dma_res = (struct hbm_client_dma_response *)mei_msg;
1609		mei_hbm_cl_dma_unmap_res(dev, client_dma_res);
1610		break;
1611
1612	default:
1613		WARN(1, "hbm: wrong command %d\n", mei_msg->hbm_cmd);
1614		return -EPROTO;
1615
1616	}
1617	return 0;
1618}
1619
1620