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