xref: /kernel/linux/linux-5.10/drivers/misc/mei/hbm.c (revision 8c2ecf20)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2003-2020, 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			mei_secs_to_jiffies(MEI_HBM_TIMEOUT));
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 = MEI_CLIENTS_INIT_TIMEOUT;
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 = MEI_CLIENTS_INIT_TIMEOUT;
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	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
345	if (ret) {
346		dev_err(dev->dev,
347			"capabilities request write failed: ret = %d.\n", ret);
348		return ret;
349	}
350
351	dev->hbm_state = MEI_HBM_CAP_SETUP;
352	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
353	mei_schedule_stall_timer(dev);
354	return 0;
355}
356
357/**
358 * mei_hbm_enum_clients_req - sends enumeration client request message.
359 *
360 * @dev: the device structure
361 *
362 * Return: 0 on success and < 0 on failure
363 */
364static int mei_hbm_enum_clients_req(struct mei_device *dev)
365{
366	struct mei_msg_hdr mei_hdr;
367	struct hbm_host_enum_request req;
368	int ret;
369
370	/* enumerate clients */
371	mei_hbm_hdr(&mei_hdr, sizeof(req));
372
373	memset(&req, 0, sizeof(req));
374	req.hbm_cmd = HOST_ENUM_REQ_CMD;
375	req.flags |= dev->hbm_f_dc_supported ? MEI_HBM_ENUM_F_ALLOW_ADD : 0;
376	req.flags |= dev->hbm_f_ie_supported ?
377			  MEI_HBM_ENUM_F_IMMEDIATE_ENUM : 0;
378
379	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
380	if (ret) {
381		dev_err(dev->dev, "enumeration request write failed: ret = %d.\n",
382			ret);
383		return ret;
384	}
385	dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
386	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
387	mei_schedule_stall_timer(dev);
388	return 0;
389}
390
391/**
392 * mei_hbm_me_cl_add - add new me client to the list
393 *
394 * @dev: the device structure
395 * @res: hbm property response
396 *
397 * Return: 0 on success and -ENOMEM on allocation failure
398 */
399
400static int mei_hbm_me_cl_add(struct mei_device *dev,
401			     struct hbm_props_response *res)
402{
403	struct mei_me_client *me_cl;
404	const uuid_le *uuid = &res->client_properties.protocol_name;
405
406	mei_me_cl_rm_by_uuid(dev, uuid);
407
408	me_cl = kzalloc(sizeof(*me_cl), GFP_KERNEL);
409	if (!me_cl)
410		return -ENOMEM;
411
412	mei_me_cl_init(me_cl);
413
414	me_cl->props = res->client_properties;
415	me_cl->client_id = res->me_addr;
416	me_cl->tx_flow_ctrl_creds = 0;
417
418	mei_me_cl_add(dev, me_cl);
419
420	return 0;
421}
422
423/**
424 * mei_hbm_add_cl_resp - send response to fw on client add request
425 *
426 * @dev: the device structure
427 * @addr: me address
428 * @status: response status
429 *
430 * Return: 0 on success and < 0 on failure
431 */
432static int mei_hbm_add_cl_resp(struct mei_device *dev, u8 addr, u8 status)
433{
434	struct mei_msg_hdr mei_hdr;
435	struct hbm_add_client_response resp;
436	int ret;
437
438	dev_dbg(dev->dev, "adding client response\n");
439
440	mei_hbm_hdr(&mei_hdr, sizeof(resp));
441
442	memset(&resp, 0, sizeof(resp));
443	resp.hbm_cmd = MEI_HBM_ADD_CLIENT_RES_CMD;
444	resp.me_addr = addr;
445	resp.status  = status;
446
447	ret = mei_hbm_write_message(dev, &mei_hdr, &resp);
448	if (ret)
449		dev_err(dev->dev, "add client response write failed: ret = %d\n",
450			ret);
451	return ret;
452}
453
454/**
455 * mei_hbm_fw_add_cl_req - request from the fw to add a client
456 *
457 * @dev: the device structure
458 * @req: add client request
459 *
460 * Return: 0 on success and < 0 on failure
461 */
462static int mei_hbm_fw_add_cl_req(struct mei_device *dev,
463			      struct hbm_add_client_request *req)
464{
465	int ret;
466	u8 status = MEI_HBMS_SUCCESS;
467
468	BUILD_BUG_ON(sizeof(struct hbm_add_client_request) !=
469			sizeof(struct hbm_props_response));
470
471	ret = mei_hbm_me_cl_add(dev, (struct hbm_props_response *)req);
472	if (ret)
473		status = !MEI_HBMS_SUCCESS;
474
475	if (dev->dev_state == MEI_DEV_ENABLED)
476		schedule_work(&dev->bus_rescan_work);
477
478	return mei_hbm_add_cl_resp(dev, req->me_addr, status);
479}
480
481/**
482 * mei_hbm_cl_notify_req - send notification request
483 *
484 * @dev: the device structure
485 * @cl: a client to disconnect from
486 * @start: true for start false for stop
487 *
488 * Return: 0 on success and -EIO on write failure
489 */
490int mei_hbm_cl_notify_req(struct mei_device *dev,
491			  struct mei_cl *cl, u8 start)
492{
493
494	struct mei_msg_hdr mei_hdr;
495	struct hbm_notification_request req;
496	int ret;
497
498	mei_hbm_hdr(&mei_hdr, sizeof(req));
499	mei_hbm_cl_hdr(cl, MEI_HBM_NOTIFY_REQ_CMD, &req, sizeof(req));
500
501	req.start = start;
502
503	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
504	if (ret)
505		dev_err(dev->dev, "notify request failed: ret = %d\n", ret);
506
507	return ret;
508}
509
510/**
511 *  notify_res_to_fop - convert notification response to the proper
512 *      notification FOP
513 *
514 * @cmd: client notification start response command
515 *
516 * Return:  MEI_FOP_NOTIFY_START or MEI_FOP_NOTIFY_STOP;
517 */
518static inline enum mei_cb_file_ops notify_res_to_fop(struct mei_hbm_cl_cmd *cmd)
519{
520	struct hbm_notification_response *rs =
521		(struct hbm_notification_response *)cmd;
522
523	return mei_cl_notify_req2fop(rs->start);
524}
525
526/**
527 * mei_hbm_cl_notify_start_res - update the client state according
528 *       notify start response
529 *
530 * @dev: the device structure
531 * @cl: mei host client
532 * @cmd: client notification start response command
533 */
534static void mei_hbm_cl_notify_start_res(struct mei_device *dev,
535					struct mei_cl *cl,
536					struct mei_hbm_cl_cmd *cmd)
537{
538	struct hbm_notification_response *rs =
539		(struct hbm_notification_response *)cmd;
540
541	cl_dbg(dev, cl, "hbm: notify start response status=%d\n", rs->status);
542
543	if (rs->status == MEI_HBMS_SUCCESS ||
544	    rs->status == MEI_HBMS_ALREADY_STARTED) {
545		cl->notify_en = true;
546		cl->status = 0;
547	} else {
548		cl->status = -EINVAL;
549	}
550}
551
552/**
553 * mei_hbm_cl_notify_stop_res - update the client state according
554 *       notify stop response
555 *
556 * @dev: the device structure
557 * @cl: mei host client
558 * @cmd: client notification stop response command
559 */
560static void mei_hbm_cl_notify_stop_res(struct mei_device *dev,
561				       struct mei_cl *cl,
562				       struct mei_hbm_cl_cmd *cmd)
563{
564	struct hbm_notification_response *rs =
565		(struct hbm_notification_response *)cmd;
566
567	cl_dbg(dev, cl, "hbm: notify stop response status=%d\n", rs->status);
568
569	if (rs->status == MEI_HBMS_SUCCESS ||
570	    rs->status == MEI_HBMS_NOT_STARTED) {
571		cl->notify_en = false;
572		cl->status = 0;
573	} else {
574		/* TODO: spec is not clear yet about other possible issues */
575		cl->status = -EINVAL;
576	}
577}
578
579/**
580 * mei_hbm_cl_notify - signal notification event
581 *
582 * @dev: the device structure
583 * @cmd: notification client message
584 */
585static void mei_hbm_cl_notify(struct mei_device *dev,
586			      struct mei_hbm_cl_cmd *cmd)
587{
588	struct mei_cl *cl;
589
590	cl = mei_hbm_cl_find_by_cmd(dev, cmd);
591	if (cl)
592		mei_cl_notify(cl);
593}
594
595/**
596 * mei_hbm_prop_req - request property for a single client
597 *
598 * @dev: the device structure
599 * @start_idx: client index to start search
600 *
601 * Return: 0 on success and < 0 on failure
602 */
603static int mei_hbm_prop_req(struct mei_device *dev, unsigned long start_idx)
604{
605	struct mei_msg_hdr mei_hdr;
606	struct hbm_props_request req;
607	unsigned long addr;
608	int ret;
609
610	addr = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, start_idx);
611
612	/* We got all client properties */
613	if (addr == MEI_CLIENTS_MAX) {
614		dev->hbm_state = MEI_HBM_STARTED;
615		mei_host_client_init(dev);
616		return 0;
617	}
618
619	mei_hbm_hdr(&mei_hdr, sizeof(req));
620
621	memset(&req, 0, sizeof(req));
622
623	req.hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
624	req.me_addr = addr;
625
626	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
627	if (ret) {
628		dev_err(dev->dev, "properties request write failed: ret = %d\n",
629			ret);
630		return ret;
631	}
632
633	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
634	mei_schedule_stall_timer(dev);
635
636	return 0;
637}
638
639/**
640 * mei_hbm_pg - sends pg command
641 *
642 * @dev: the device structure
643 * @pg_cmd: the pg command code
644 *
645 * Return: -EIO on write failure
646 *         -EOPNOTSUPP if the operation is not supported by the protocol
647 */
648int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
649{
650	struct mei_msg_hdr mei_hdr;
651	struct hbm_power_gate req;
652	int ret;
653
654	if (!dev->hbm_f_pg_supported)
655		return -EOPNOTSUPP;
656
657	mei_hbm_hdr(&mei_hdr, sizeof(req));
658
659	memset(&req, 0, sizeof(req));
660	req.hbm_cmd = pg_cmd;
661
662	ret = mei_hbm_write_message(dev, &mei_hdr, &req);
663	if (ret)
664		dev_err(dev->dev, "power gate command write failed.\n");
665	return ret;
666}
667EXPORT_SYMBOL_GPL(mei_hbm_pg);
668
669/**
670 * mei_hbm_stop_req - send stop request message
671 *
672 * @dev: mei device
673 *
674 * Return: -EIO on write failure
675 */
676static int mei_hbm_stop_req(struct mei_device *dev)
677{
678	struct mei_msg_hdr mei_hdr;
679	struct hbm_host_stop_request req;
680
681	mei_hbm_hdr(&mei_hdr, sizeof(req));
682
683	memset(&req, 0, sizeof(req));
684	req.hbm_cmd = HOST_STOP_REQ_CMD;
685	req.reason = DRIVER_STOP_REQUEST;
686
687	return mei_hbm_write_message(dev, &mei_hdr, &req);
688}
689
690/**
691 * mei_hbm_cl_flow_control_req - sends flow control request.
692 *
693 * @dev: the device structure
694 * @cl: client info
695 *
696 * Return: -EIO on write failure
697 */
698int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
699{
700	struct hbm_flow_control req;
701
702	cl_dbg(dev, cl, "sending flow control\n");
703	return mei_hbm_cl_write(dev, cl, MEI_FLOW_CONTROL_CMD,
704				&req, sizeof(req));
705}
706
707/**
708 * mei_hbm_add_single_tx_flow_ctrl_creds - adds single buffer credentials.
709 *
710 * @dev: the device structure
711 * @fctrl: flow control response bus message
712 *
713 * Return: 0 on success, < 0 otherwise
714 */
715static int mei_hbm_add_single_tx_flow_ctrl_creds(struct mei_device *dev,
716						 struct hbm_flow_control *fctrl)
717{
718	struct mei_me_client *me_cl;
719	int rets;
720
721	me_cl = mei_me_cl_by_id(dev, fctrl->me_addr);
722	if (!me_cl) {
723		dev_err(dev->dev, "no such me client %d\n", fctrl->me_addr);
724		return -ENOENT;
725	}
726
727	if (WARN_ON(me_cl->props.single_recv_buf == 0)) {
728		rets = -EINVAL;
729		goto out;
730	}
731
732	me_cl->tx_flow_ctrl_creds++;
733	dev_dbg(dev->dev, "recv flow ctrl msg ME %d (single) creds = %d.\n",
734		fctrl->me_addr, me_cl->tx_flow_ctrl_creds);
735
736	rets = 0;
737out:
738	mei_me_cl_put(me_cl);
739	return rets;
740}
741
742/**
743 * mei_hbm_cl_flow_control_res - flow control response from me
744 *
745 * @dev: the device structure
746 * @fctrl: flow control response bus message
747 */
748static void mei_hbm_cl_tx_flow_ctrl_creds_res(struct mei_device *dev,
749					       struct hbm_flow_control *fctrl)
750{
751	struct mei_cl *cl;
752
753	if (!fctrl->host_addr) {
754		/* single receive buffer */
755		mei_hbm_add_single_tx_flow_ctrl_creds(dev, fctrl);
756		return;
757	}
758
759	cl = mei_hbm_cl_find_by_cmd(dev, fctrl);
760	if (cl) {
761		cl->tx_flow_ctrl_creds++;
762		cl_dbg(dev, cl, "flow control creds = %d.\n",
763				cl->tx_flow_ctrl_creds);
764	}
765}
766
767
768/**
769 * mei_hbm_cl_disconnect_req - sends disconnect message to fw.
770 *
771 * @dev: the device structure
772 * @cl: a client to disconnect from
773 *
774 * Return: -EIO on write failure
775 */
776int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
777{
778	struct hbm_client_connect_request req;
779
780	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_REQ_CMD,
781				&req, sizeof(req));
782}
783
784/**
785 * mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW
786 *
787 * @dev: the device structure
788 * @cl: a client to disconnect from
789 *
790 * Return: -EIO on write failure
791 */
792int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
793{
794	struct hbm_client_connect_response resp;
795
796	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_RES_CMD,
797				&resp, sizeof(resp));
798}
799
800/**
801 * mei_hbm_cl_disconnect_res - update the client state according
802 *       disconnect response
803 *
804 * @dev: the device structure
805 * @cl: mei host client
806 * @cmd: disconnect client response host bus message
807 */
808static void mei_hbm_cl_disconnect_res(struct mei_device *dev, struct mei_cl *cl,
809				      struct mei_hbm_cl_cmd *cmd)
810{
811	struct hbm_client_connect_response *rs =
812		(struct hbm_client_connect_response *)cmd;
813
814	cl_dbg(dev, cl, "hbm: disconnect response status=%d\n", rs->status);
815
816	if (rs->status == MEI_CL_DISCONN_SUCCESS)
817		cl->state = MEI_FILE_DISCONNECT_REPLY;
818	cl->status = 0;
819}
820
821/**
822 * mei_hbm_cl_connect_req - send connection request to specific me client
823 *
824 * @dev: the device structure
825 * @cl: a client to connect to
826 *
827 * Return: -EIO on write failure
828 */
829int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
830{
831	struct hbm_client_connect_request req;
832
833	return mei_hbm_cl_write(dev, cl, CLIENT_CONNECT_REQ_CMD,
834				&req, sizeof(req));
835}
836
837/**
838 * mei_hbm_cl_connect_res - update the client state according
839 *        connection response
840 *
841 * @dev: the device structure
842 * @cl: mei host client
843 * @cmd: connect client response host bus message
844 */
845static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl,
846				   struct mei_hbm_cl_cmd *cmd)
847{
848	struct hbm_client_connect_response *rs =
849		(struct hbm_client_connect_response *)cmd;
850
851	cl_dbg(dev, cl, "hbm: connect response status=%s\n",
852			mei_cl_conn_status_str(rs->status));
853
854	if (rs->status == MEI_CL_CONN_SUCCESS)
855		cl->state = MEI_FILE_CONNECTED;
856	else {
857		cl->state = MEI_FILE_DISCONNECT_REPLY;
858		if (rs->status == MEI_CL_CONN_NOT_FOUND) {
859			mei_me_cl_del(dev, cl->me_cl);
860			if (dev->dev_state == MEI_DEV_ENABLED)
861				schedule_work(&dev->bus_rescan_work);
862		}
863	}
864	cl->status = mei_cl_conn_status_to_errno(rs->status);
865}
866
867/**
868 * mei_hbm_cl_res - process hbm response received on behalf
869 *         an client
870 *
871 * @dev: the device structure
872 * @rs:  hbm client message
873 * @fop_type: file operation type
874 */
875static void mei_hbm_cl_res(struct mei_device *dev,
876			   struct mei_hbm_cl_cmd *rs,
877			   enum mei_cb_file_ops fop_type)
878{
879	struct mei_cl *cl;
880	struct mei_cl_cb *cb, *next;
881
882	cl = NULL;
883	list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list, list) {
884
885		cl = cb->cl;
886
887		if (cb->fop_type != fop_type)
888			continue;
889
890		if (mei_hbm_cl_addr_equal(cl, rs)) {
891			list_del_init(&cb->list);
892			break;
893		}
894	}
895
896	if (!cl)
897		return;
898
899	switch (fop_type) {
900	case MEI_FOP_CONNECT:
901		mei_hbm_cl_connect_res(dev, cl, rs);
902		break;
903	case MEI_FOP_DISCONNECT:
904		mei_hbm_cl_disconnect_res(dev, cl, rs);
905		break;
906	case MEI_FOP_NOTIFY_START:
907		mei_hbm_cl_notify_start_res(dev, cl, rs);
908		break;
909	case MEI_FOP_NOTIFY_STOP:
910		mei_hbm_cl_notify_stop_res(dev, cl, rs);
911		break;
912	default:
913		return;
914	}
915
916	cl->timer_count = 0;
917	wake_up(&cl->wait);
918}
919
920
921/**
922 * mei_hbm_fw_disconnect_req - disconnect request initiated by ME firmware
923 *  host sends disconnect response
924 *
925 * @dev: the device structure.
926 * @disconnect_req: disconnect request bus message from the me
927 *
928 * Return: -ENOMEM on allocation failure
929 */
930static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
931		struct hbm_client_connect_request *disconnect_req)
932{
933	struct mei_cl *cl;
934	struct mei_cl_cb *cb;
935
936	cl = mei_hbm_cl_find_by_cmd(dev, disconnect_req);
937	if (cl) {
938		cl_warn(dev, cl, "fw disconnect request received\n");
939		cl->state = MEI_FILE_DISCONNECTING;
940		cl->timer_count = 0;
941
942		cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT_RSP,
943					       NULL);
944		if (!cb)
945			return -ENOMEM;
946	}
947	return 0;
948}
949
950/**
951 * mei_hbm_pg_enter_res - PG enter response received
952 *
953 * @dev: the device structure.
954 *
955 * Return: 0 on success, -EPROTO on state mismatch
956 */
957static int mei_hbm_pg_enter_res(struct mei_device *dev)
958{
959	if (mei_pg_state(dev) != MEI_PG_OFF ||
960	    dev->pg_event != MEI_PG_EVENT_WAIT) {
961		dev_err(dev->dev, "hbm: pg entry response: state mismatch [%s, %d]\n",
962			mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
963		return -EPROTO;
964	}
965
966	dev->pg_event = MEI_PG_EVENT_RECEIVED;
967	wake_up(&dev->wait_pg);
968
969	return 0;
970}
971
972/**
973 * mei_hbm_pg_resume - process with PG resume
974 *
975 * @dev: the device structure.
976 */
977void mei_hbm_pg_resume(struct mei_device *dev)
978{
979	pm_request_resume(dev->dev);
980}
981EXPORT_SYMBOL_GPL(mei_hbm_pg_resume);
982
983/**
984 * mei_hbm_pg_exit_res - PG exit response received
985 *
986 * @dev: the device structure.
987 *
988 * Return: 0 on success, -EPROTO on state mismatch
989 */
990static int mei_hbm_pg_exit_res(struct mei_device *dev)
991{
992	if (mei_pg_state(dev) != MEI_PG_ON ||
993	    (dev->pg_event != MEI_PG_EVENT_WAIT &&
994	     dev->pg_event != MEI_PG_EVENT_IDLE)) {
995		dev_err(dev->dev, "hbm: pg exit response: state mismatch [%s, %d]\n",
996			mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
997		return -EPROTO;
998	}
999
1000	switch (dev->pg_event) {
1001	case MEI_PG_EVENT_WAIT:
1002		dev->pg_event = MEI_PG_EVENT_RECEIVED;
1003		wake_up(&dev->wait_pg);
1004		break;
1005	case MEI_PG_EVENT_IDLE:
1006		/*
1007		* If the driver is not waiting on this then
1008		* this is HW initiated exit from PG.
1009		* Start runtime pm resume sequence to exit from PG.
1010		*/
1011		dev->pg_event = MEI_PG_EVENT_RECEIVED;
1012		mei_hbm_pg_resume(dev);
1013		break;
1014	default:
1015		WARN(1, "hbm: pg exit response: unexpected pg event = %d\n",
1016		     dev->pg_event);
1017		return -EPROTO;
1018	}
1019
1020	return 0;
1021}
1022
1023/**
1024 * mei_hbm_config_features - check what hbm features and commands
1025 *        are supported by the fw
1026 *
1027 * @dev: the device structure
1028 */
1029static void mei_hbm_config_features(struct mei_device *dev)
1030{
1031	/* Power Gating Isolation Support */
1032	dev->hbm_f_pg_supported = 0;
1033	if (dev->version.major_version > HBM_MAJOR_VERSION_PGI)
1034		dev->hbm_f_pg_supported = 1;
1035
1036	if (dev->version.major_version == HBM_MAJOR_VERSION_PGI &&
1037	    dev->version.minor_version >= HBM_MINOR_VERSION_PGI)
1038		dev->hbm_f_pg_supported = 1;
1039
1040	dev->hbm_f_dc_supported = 0;
1041	if (dev->version.major_version >= HBM_MAJOR_VERSION_DC)
1042		dev->hbm_f_dc_supported = 1;
1043
1044	dev->hbm_f_ie_supported = 0;
1045	if (dev->version.major_version >= HBM_MAJOR_VERSION_IE)
1046		dev->hbm_f_ie_supported = 1;
1047
1048	/* disconnect on connect timeout instead of link reset */
1049	dev->hbm_f_dot_supported = 0;
1050	if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT)
1051		dev->hbm_f_dot_supported = 1;
1052
1053	/* Notification Event Support */
1054	dev->hbm_f_ev_supported = 0;
1055	if (dev->version.major_version >= HBM_MAJOR_VERSION_EV)
1056		dev->hbm_f_ev_supported = 1;
1057
1058	/* Fixed Address Client Support */
1059	dev->hbm_f_fa_supported = 0;
1060	if (dev->version.major_version >= HBM_MAJOR_VERSION_FA)
1061		dev->hbm_f_fa_supported = 1;
1062
1063	/* OS ver message Support */
1064	dev->hbm_f_os_supported = 0;
1065	if (dev->version.major_version >= HBM_MAJOR_VERSION_OS)
1066		dev->hbm_f_os_supported = 1;
1067
1068	/* DMA Ring Support */
1069	dev->hbm_f_dr_supported = 0;
1070	if (dev->version.major_version > HBM_MAJOR_VERSION_DR ||
1071	    (dev->version.major_version == HBM_MAJOR_VERSION_DR &&
1072	     dev->version.minor_version >= HBM_MINOR_VERSION_DR))
1073		dev->hbm_f_dr_supported = 1;
1074
1075	/* VTag Support */
1076	dev->hbm_f_vt_supported = 0;
1077	if (dev->version.major_version > HBM_MAJOR_VERSION_VT ||
1078	    (dev->version.major_version == HBM_MAJOR_VERSION_VT &&
1079	     dev->version.minor_version >= HBM_MINOR_VERSION_VT))
1080		dev->hbm_f_vt_supported = 1;
1081
1082	/* Capability message Support */
1083	dev->hbm_f_cap_supported = 0;
1084	if (dev->version.major_version > HBM_MAJOR_VERSION_CAP ||
1085	    (dev->version.major_version == HBM_MAJOR_VERSION_CAP &&
1086	     dev->version.minor_version >= HBM_MINOR_VERSION_CAP))
1087		dev->hbm_f_cap_supported = 1;
1088}
1089
1090/**
1091 * mei_hbm_version_is_supported - checks whether the driver can
1092 *     support the hbm version of the device
1093 *
1094 * @dev: the device structure
1095 * Return: true if driver can support hbm version of the device
1096 */
1097bool mei_hbm_version_is_supported(struct mei_device *dev)
1098{
1099	return	(dev->version.major_version < HBM_MAJOR_VERSION) ||
1100		(dev->version.major_version == HBM_MAJOR_VERSION &&
1101		 dev->version.minor_version <= HBM_MINOR_VERSION);
1102}
1103
1104/**
1105 * mei_hbm_dispatch - bottom half read routine after ISR to
1106 * handle the read bus message cmd processing.
1107 *
1108 * @dev: the device structure
1109 * @hdr: header of bus message
1110 *
1111 * Return: 0 on success and < 0 on failure
1112 */
1113int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
1114{
1115	struct mei_bus_message *mei_msg;
1116	struct hbm_host_version_response *version_res;
1117	struct hbm_props_response *props_res;
1118	struct hbm_host_enum_response *enum_res;
1119	struct hbm_dma_setup_response *dma_setup_res;
1120	struct hbm_add_client_request *add_cl_req;
1121	struct hbm_capability_response *capability_res;
1122	int ret;
1123
1124	struct mei_hbm_cl_cmd *cl_cmd;
1125	struct hbm_client_connect_request *disconnect_req;
1126	struct hbm_flow_control *fctrl;
1127
1128	/* read the message to our buffer */
1129	BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf));
1130	mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
1131	mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
1132	cl_cmd  = (struct mei_hbm_cl_cmd *)mei_msg;
1133
1134	/* ignore spurious message and prevent reset nesting
1135	 * hbm is put to idle during system reset
1136	 */
1137	if (dev->hbm_state == MEI_HBM_IDLE) {
1138		dev_dbg(dev->dev, "hbm: state is idle ignore spurious messages\n");
1139		return 0;
1140	}
1141
1142	switch (mei_msg->hbm_cmd) {
1143	case HOST_START_RES_CMD:
1144		dev_dbg(dev->dev, "hbm: start: response message received.\n");
1145
1146		dev->init_clients_timer = 0;
1147
1148		version_res = (struct hbm_host_version_response *)mei_msg;
1149
1150		dev_dbg(dev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n",
1151				HBM_MAJOR_VERSION, HBM_MINOR_VERSION,
1152				version_res->me_max_version.major_version,
1153				version_res->me_max_version.minor_version);
1154
1155		if (version_res->host_version_supported) {
1156			dev->version.major_version = HBM_MAJOR_VERSION;
1157			dev->version.minor_version = HBM_MINOR_VERSION;
1158		} else {
1159			dev->version.major_version =
1160				version_res->me_max_version.major_version;
1161			dev->version.minor_version =
1162				version_res->me_max_version.minor_version;
1163		}
1164
1165		if (!mei_hbm_version_is_supported(dev)) {
1166			dev_warn(dev->dev, "hbm: start: version mismatch - stopping the driver.\n");
1167
1168			dev->hbm_state = MEI_HBM_STOPPED;
1169			if (mei_hbm_stop_req(dev)) {
1170				dev_err(dev->dev, "hbm: start: failed to send stop request\n");
1171				return -EIO;
1172			}
1173			break;
1174		}
1175
1176		mei_hbm_config_features(dev);
1177
1178		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1179		    dev->hbm_state != MEI_HBM_STARTING) {
1180			dev_err(dev->dev, "hbm: start: state mismatch, [%d, %d]\n",
1181				dev->dev_state, dev->hbm_state);
1182			return -EPROTO;
1183		}
1184
1185		if (dev->hbm_f_cap_supported) {
1186			if (mei_hbm_capabilities_req(dev))
1187				return -EIO;
1188			wake_up(&dev->wait_hbm_start);
1189			break;
1190		}
1191
1192		if (dev->hbm_f_dr_supported) {
1193			if (mei_dmam_ring_alloc(dev))
1194				dev_info(dev->dev, "running w/o dma ring\n");
1195			if (mei_dma_ring_is_allocated(dev)) {
1196				if (mei_hbm_dma_setup_req(dev))
1197					return -EIO;
1198
1199				wake_up(&dev->wait_hbm_start);
1200				break;
1201			}
1202		}
1203
1204		dev->hbm_f_dr_supported = 0;
1205		mei_dmam_ring_free(dev);
1206
1207		if (mei_hbm_enum_clients_req(dev))
1208			return -EIO;
1209
1210		wake_up(&dev->wait_hbm_start);
1211		break;
1212
1213	case MEI_HBM_CAPABILITIES_RES_CMD:
1214		dev_dbg(dev->dev, "hbm: capabilities response: message received.\n");
1215
1216		dev->init_clients_timer = 0;
1217
1218		if (dev->hbm_state != MEI_HBM_CAP_SETUP) {
1219			dev_err(dev->dev, "hbm: capabilities response: state mismatch, [%d, %d]\n",
1220				dev->dev_state, dev->hbm_state);
1221			return -EPROTO;
1222		}
1223
1224		capability_res = (struct hbm_capability_response *)mei_msg;
1225		if (!(capability_res->capability_granted[0] & HBM_CAP_VT))
1226			dev->hbm_f_vt_supported = 0;
1227
1228		if (dev->hbm_f_dr_supported) {
1229			if (mei_dmam_ring_alloc(dev))
1230				dev_info(dev->dev, "running w/o dma ring\n");
1231			if (mei_dma_ring_is_allocated(dev)) {
1232				if (mei_hbm_dma_setup_req(dev))
1233					return -EIO;
1234				break;
1235			}
1236		}
1237
1238		dev->hbm_f_dr_supported = 0;
1239		mei_dmam_ring_free(dev);
1240
1241		if (mei_hbm_enum_clients_req(dev))
1242			return -EIO;
1243		break;
1244
1245	case MEI_HBM_DMA_SETUP_RES_CMD:
1246		dev_dbg(dev->dev, "hbm: dma setup response: message received.\n");
1247
1248		dev->init_clients_timer = 0;
1249
1250		if (dev->hbm_state != MEI_HBM_DR_SETUP) {
1251			dev_err(dev->dev, "hbm: dma setup response: state mismatch, [%d, %d]\n",
1252				dev->dev_state, dev->hbm_state);
1253			return -EPROTO;
1254		}
1255
1256		dma_setup_res = (struct hbm_dma_setup_response *)mei_msg;
1257
1258		if (dma_setup_res->status) {
1259			u8 status = dma_setup_res->status;
1260
1261			if (status == MEI_HBMS_NOT_ALLOWED) {
1262				dev_dbg(dev->dev, "hbm: dma setup not allowed\n");
1263			} else {
1264				dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
1265					 status,
1266					 mei_hbm_status_str(status));
1267			}
1268			dev->hbm_f_dr_supported = 0;
1269			mei_dmam_ring_free(dev);
1270		}
1271
1272		if (mei_hbm_enum_clients_req(dev))
1273			return -EIO;
1274		break;
1275
1276	case CLIENT_CONNECT_RES_CMD:
1277		dev_dbg(dev->dev, "hbm: client connect response: message received.\n");
1278		mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_CONNECT);
1279		break;
1280
1281	case CLIENT_DISCONNECT_RES_CMD:
1282		dev_dbg(dev->dev, "hbm: client disconnect response: message received.\n");
1283		mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_DISCONNECT);
1284		break;
1285
1286	case MEI_FLOW_CONTROL_CMD:
1287		dev_dbg(dev->dev, "hbm: client flow control response: message received.\n");
1288
1289		fctrl = (struct hbm_flow_control *)mei_msg;
1290		mei_hbm_cl_tx_flow_ctrl_creds_res(dev, fctrl);
1291		break;
1292
1293	case MEI_PG_ISOLATION_ENTRY_RES_CMD:
1294		dev_dbg(dev->dev, "hbm: power gate isolation entry response received\n");
1295		ret = mei_hbm_pg_enter_res(dev);
1296		if (ret)
1297			return ret;
1298		break;
1299
1300	case MEI_PG_ISOLATION_EXIT_REQ_CMD:
1301		dev_dbg(dev->dev, "hbm: power gate isolation exit request received\n");
1302		ret = mei_hbm_pg_exit_res(dev);
1303		if (ret)
1304			return ret;
1305		break;
1306
1307	case HOST_CLIENT_PROPERTIES_RES_CMD:
1308		dev_dbg(dev->dev, "hbm: properties response: message received.\n");
1309
1310		dev->init_clients_timer = 0;
1311
1312		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1313		    dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
1314			dev_err(dev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
1315				dev->dev_state, dev->hbm_state);
1316			return -EPROTO;
1317		}
1318
1319		props_res = (struct hbm_props_response *)mei_msg;
1320
1321		if (props_res->status == MEI_HBMS_CLIENT_NOT_FOUND) {
1322			dev_dbg(dev->dev, "hbm: properties response: %d CLIENT_NOT_FOUND\n",
1323				props_res->me_addr);
1324		} else if (props_res->status) {
1325			dev_err(dev->dev, "hbm: properties response: wrong status = %d %s\n",
1326				props_res->status,
1327				mei_hbm_status_str(props_res->status));
1328			return -EPROTO;
1329		} else {
1330			mei_hbm_me_cl_add(dev, props_res);
1331		}
1332
1333		/* request property for the next client */
1334		if (mei_hbm_prop_req(dev, props_res->me_addr + 1))
1335			return -EIO;
1336
1337		break;
1338
1339	case HOST_ENUM_RES_CMD:
1340		dev_dbg(dev->dev, "hbm: enumeration response: message received\n");
1341
1342		dev->init_clients_timer = 0;
1343
1344		enum_res = (struct hbm_host_enum_response *) mei_msg;
1345		BUILD_BUG_ON(sizeof(dev->me_clients_map)
1346				< sizeof(enum_res->valid_addresses));
1347		memcpy(dev->me_clients_map, enum_res->valid_addresses,
1348				sizeof(enum_res->valid_addresses));
1349
1350		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1351		    dev->hbm_state != MEI_HBM_ENUM_CLIENTS) {
1352			dev_err(dev->dev, "hbm: enumeration response: state mismatch, [%d, %d]\n",
1353				dev->dev_state, dev->hbm_state);
1354			return -EPROTO;
1355		}
1356
1357		dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
1358
1359		/* first property request */
1360		if (mei_hbm_prop_req(dev, 0))
1361			return -EIO;
1362
1363		break;
1364
1365	case HOST_STOP_RES_CMD:
1366		dev_dbg(dev->dev, "hbm: stop response: message received\n");
1367
1368		dev->init_clients_timer = 0;
1369
1370		if (dev->hbm_state != MEI_HBM_STOPPED) {
1371			dev_err(dev->dev, "hbm: stop response: state mismatch, [%d, %d]\n",
1372				dev->dev_state, dev->hbm_state);
1373			return -EPROTO;
1374		}
1375
1376		mei_set_devstate(dev, MEI_DEV_POWER_DOWN);
1377		dev_info(dev->dev, "hbm: stop response: resetting.\n");
1378		/* force the reset */
1379		return -EPROTO;
1380		break;
1381
1382	case CLIENT_DISCONNECT_REQ_CMD:
1383		dev_dbg(dev->dev, "hbm: disconnect request: message received\n");
1384
1385		disconnect_req = (struct hbm_client_connect_request *)mei_msg;
1386		mei_hbm_fw_disconnect_req(dev, disconnect_req);
1387		break;
1388
1389	case ME_STOP_REQ_CMD:
1390		dev_dbg(dev->dev, "hbm: stop request: message received\n");
1391		dev->hbm_state = MEI_HBM_STOPPED;
1392		if (mei_hbm_stop_req(dev)) {
1393			dev_err(dev->dev, "hbm: stop request: failed to send stop request\n");
1394			return -EIO;
1395		}
1396		break;
1397
1398	case MEI_HBM_ADD_CLIENT_REQ_CMD:
1399		dev_dbg(dev->dev, "hbm: add client request received\n");
1400		/*
1401		 * after the host receives the enum_resp
1402		 * message clients may be added or removed
1403		 */
1404		if (dev->hbm_state <= MEI_HBM_ENUM_CLIENTS ||
1405		    dev->hbm_state >= MEI_HBM_STOPPED) {
1406			dev_err(dev->dev, "hbm: add client: state mismatch, [%d, %d]\n",
1407				dev->dev_state, dev->hbm_state);
1408			return -EPROTO;
1409		}
1410		add_cl_req = (struct hbm_add_client_request *)mei_msg;
1411		ret = mei_hbm_fw_add_cl_req(dev, add_cl_req);
1412		if (ret) {
1413			dev_err(dev->dev, "hbm: add client: failed to send response %d\n",
1414				ret);
1415			return -EIO;
1416		}
1417		dev_dbg(dev->dev, "hbm: add client request processed\n");
1418		break;
1419
1420	case MEI_HBM_NOTIFY_RES_CMD:
1421		dev_dbg(dev->dev, "hbm: notify response received\n");
1422		mei_hbm_cl_res(dev, cl_cmd, notify_res_to_fop(cl_cmd));
1423		break;
1424
1425	case MEI_HBM_NOTIFICATION_CMD:
1426		dev_dbg(dev->dev, "hbm: notification\n");
1427		mei_hbm_cl_notify(dev, cl_cmd);
1428		break;
1429
1430	default:
1431		WARN(1, "hbm: wrong command %d\n", mei_msg->hbm_cmd);
1432		return -EPROTO;
1433
1434	}
1435	return 0;
1436}
1437
1438