Linux Audio

Check our new training course

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