brintos

brintos / linux-shallow public Read only

0
0
Text · 39.9 KiB · 026b1f6 Raw
1622 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2003-2022, Intel Corporation. All rights reserved.4 * Intel Management Engine Interface (Intel MEI) Linux driver5 */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 #status21	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_STATUS33};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 #status38	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_CCS48}49 50const char *mei_hbm_state_str(enum mei_hbm_state state)51{52#define MEI_HBM_STATE(state) case MEI_HBM_##state: return #state53	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_STATE65}66 67/**68 * mei_cl_conn_status_to_errno - convert client connect response69 * status to error code70 *71 * @status: client connect response status72 *73 * Return: corresponding error code74 */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 device92 * @hdr: mei header93 * @data: payload94 *95 * Return: >=0 on success, <0 on error96 */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 state106 *107 * @dev: the device structure108 */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 structures117 *118 * @dev: the device structure119 */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 header129 *130 * @mei_hdr: hbm header131 * @length: payload length132 */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 header143 *144 * @cl: client145 * @hbm_cmd: host bus message command146 * @buf: buffer for cl header147 * @len: buffer length148 */149static inline150void 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 message163 *164 * @dev: the device structure165 * @cl: client166 * @hbm_cmd: host bus message command167 * @buf: message buffer168 * @len: buffer length169 *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 and185 *	the message address match186 *187 * @cl: client188 * @cmd: hbm client message189 *190 * Return: true if addresses are the same191 */192static inline193bool 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 client201 *202 * @dev: the device structure203 * @buf: a buffer with hbm cl command204 *205 * Return: the recipient client or NULL if not found206 */207static inline208struct 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 structure224 *225 * Return: 0 on success and < 0 on failure226 */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 structure252 *253 * Return: 0 on success and < 0 on failure254 */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 request287 * @dev: the device structure288 *289 * Return: 0 on success and < 0 on failure290 */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 capabilities328 *329 * @dev: the device structure330 *331 * Return: 0 on success and < 0 on failure332 */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 structure369 *370 * Return: 0 on success and < 0 on failure371 */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 list401 *402 * @dev: the device structure403 * @res: hbm property response404 *405 * Return: 0 on success and -ENOMEM on allocation failure406 */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 request433 *434 * @dev: the device structure435 * @addr: me address436 * @status: response status437 *438 * Return: 0 on success and < 0 on failure439 */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 client464 *465 * @dev: the device structure466 * @req: add client request467 *468 * Return: 0 on success and < 0 on failure469 */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 request491 *492 * @dev: the device structure493 * @cl: a client to disconnect from494 * @start: true for start false for stop495 *496 * Return: 0 on success and -EIO on write failure497 */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 proper520 *      notification FOP521 *522 * @cmd: client notification start response command523 *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 according536 *       notify start response537 *538 * @dev: the device structure539 * @cl: mei host client540 * @cmd: client notification start response command541 */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 according562 *       notify stop response563 *564 * @dev: the device structure565 * @cl: mei host client566 * @cmd: client notification stop response command567 */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 event589 *590 * @dev: the device structure591 * @cmd: notification client message592 */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 request605 *606 * @dev: the device structure607 * @cl: mei host client608 *609 * Return: 0 on success and -EIO on write failure610 */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 request636 *637 * @dev: the device structure638 * @cl: mei host client639 *640 * Return: 0 on success and -EIO on write failure641 */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 client724 *725 * @dev: the device structure726 * @start_idx: client index to start search727 *728 * Return: 0 on success and < 0 on failure729 */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 command768 *769 * @dev: the device structure770 * @pg_cmd: the pg command code771 *772 * Return: -EIO on write failure773 *         -EOPNOTSUPP if the operation is not supported by the protocol774 */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 message798 *799 * @dev: mei device800 *801 * Return: -EIO on write failure802 */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 structure821 * @cl: client info822 *823 * Return: -EIO on write failure824 */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 structure838 * @fctrl: flow control response bus message839 *840 * Return: 0 on success, < 0 otherwise841 */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 me871 *872 * @dev: the device structure873 * @fctrl: flow control response bus message874 */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 structure899 * @cl: a client to disconnect from900 *901 * Return: -EIO on write failure902 */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 FW913 *914 * @dev: the device structure915 * @cl: a client to disconnect from916 *917 * Return: -EIO on write failure918 */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 according929 *       disconnect response930 *931 * @dev: the device structure932 * @cl: mei host client933 * @cmd: disconnect client response host bus message934 */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 client950 *951 * @dev: the device structure952 * @cl: a client to connect to953 *954 * Return: -EIO on write failure955 */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 according966 *        connection response967 *968 * @dev: the device structure969 * @cl: mei host client970 * @cmd: connect client response host bus message971 */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 behalf996 *         an client997 *998 * @dev: the device structure999 * @rs:  hbm client message1000 * @fop_type: file operation type1001 */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 firmware1050 *  host sends disconnect response1051 *1052 * @dev: the device structure.1053 * @disconnect_req: disconnect request bus message from the me1054 *1055 * Return: -ENOMEM on allocation failure1056 */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 received1079 *1080 * @dev: the device structure.1081 *1082 * Return: 0 on success, -EPROTO on state mismatch1083 */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 resume1101 *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 received1112 *1113 * @dev: the device structure.1114 *1115 * Return: 0 on success, -EPROTO on state mismatch1116 */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 then1135		* 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 commands1152 *        are supported by the fw1153 *1154 * @dev: the device structure1155 */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 can1232 *     support the hbm version of the device1233 *1234 * @dev: the device structure1235 * Return: true if driver can support hbm version of the device1236 */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 to1246 * handle the read bus message cmd processing.1247 *1248 * @dev: the device structure1249 * @hdr: header of bus message1250 *1251 * Return: 0 on success and < 0 on failure1252 */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 nesting1276	 * hbm is put to idle during system reset1277	 */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_resp1574		 * message clients may be added or removed1575		 */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