blob: be41843df75bcb029dc34af8c13c0d3e0c905443 [file] [log] [blame]
Tomas Winkler9fff0422019-03-12 00:10:41 +02001// SPDX-License-Identifier: GPL-2.0
Tomas Winklerbb1b0132012-12-25 19:06:07 +02002/*
Tomas Winklerdf4b37b2020-07-23 17:59:22 +03003 * Copyright (c) 2003-2020, Intel Corporation. All rights reserved.
Tomas Winklerbb1b0132012-12-25 19:06:07 +02004 * Intel Management Engine Interface (Intel MEI) Linux driver
Tomas Winklerbb1b0132012-12-25 19:06:07 +02005 */
Tomas Winkler4fcbc992014-03-18 22:51:55 +02006#include <linux/export.h>
Tomas Winklerbb1b0132012-12-25 19:06:07 +02007#include <linux/sched.h>
8#include <linux/wait.h>
Tomas Winkler180ea052014-03-18 22:52:02 +02009#include <linux/pm_runtime.h>
Tomas Winkler1f180352014-09-29 16:31:46 +030010#include <linux/slab.h>
11
12#include <linux/mei.h>
Tomas Winklerbb1b0132012-12-25 19:06:07 +020013
14#include "mei_dev.h"
Tomas Winkler0edb23f2013-01-08 23:07:12 +020015#include "hbm.h"
Alexander Usyskin12d00662014-02-17 15:13:23 +020016#include "client.h"
Tomas Winklerbb1b0132012-12-25 19:06:07 +020017
Tomas Winkler89778d62014-08-21 14:29:16 +030018static 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
Alexander Usyskin285e2992014-02-17 15:13:20 +020035static 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);
Alexander Usyskin71e117f2015-07-29 14:59:33 +030044 MEI_CL_CS(NOT_ALLOWED);
Alexander Usyskin285e2992014-02-17 15:13:20 +020045 default: return "unknown";
46 }
47#undef MEI_CL_CCS
48}
49
Alexander Usyskin1beeb4b2014-09-29 16:31:33 +030050const 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);
Tomas Winklerc55bf542018-11-22 13:11:37 +020057 MEI_HBM_STATE(DR_SETUP);
Alexander Usyskin1beeb4b2014-09-29 16:31:33 +030058 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
Alexander Usyskin285e2992014-02-17 15:13:20 +020067/**
68 * mei_cl_conn_status_to_errno - convert client connect response
69 * status to error code
70 *
71 * @status: client connect response status
72 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +030073 * Return: corresponding error code
Alexander Usyskin285e2992014-02-17 15:13:20 +020074 */
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;
Alexander Usyskin71e117f2015-07-29 14:59:33 +030083 case MEI_CL_CONN_NOT_ALLOWED: return -EBUSY;
Alexander Usyskin285e2992014-02-17 15:13:20 +020084 default: return -EINVAL;
85 }
86}
87
Tomas Winklerbb1b0132012-12-25 19:06:07 +020088/**
Tomas Winkler98e70862018-07-31 09:35:33 +030089 * 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/**
Tomas Winkler84b32942014-05-07 16:51:28 +0300103 * 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{
Tomas Winkler79563db2015-01-11 00:07:16 +0200120 mei_me_cl_rm_all(dev);
Tomas Winkler84b32942014-05-07 16:51:28 +0300121
122 mei_hbm_idle(dev);
123}
124
125/**
Tomas Winkler2190fe22014-09-29 16:31:40 +0300126 * mei_hbm_hdr - construct hbm header
127 *
Tomas Winkler0cd7c012020-08-18 14:51:38 +0300128 * @mei_hdr: hbm header
Tomas Winkler2190fe22014-09-29 16:31:40 +0300129 * @length: payload length
130 */
131
Tomas Winkler0cd7c012020-08-18 14:51:38 +0300132static inline void mei_hbm_hdr(struct mei_msg_hdr *mei_hdr, size_t length)
Tomas Winkler2190fe22014-09-29 16:31:40 +0300133{
Tomas Winkler0cd7c012020-08-18 14:51:38 +0300134 memset(mei_hdr, 0, sizeof(*mei_hdr));
135 mei_hdr->length = length;
136 mei_hdr->msg_complete = 1;
Tomas Winkler2190fe22014-09-29 16:31:40 +0300137}
138
139/**
Tomas Winklercd51ed62012-12-25 19:06:09 +0200140 * mei_hbm_cl_hdr - construct client hbm header
Masanari Iida393b1482013-04-05 01:05:05 +0900141 *
Tomas Winkler68d1aa62014-08-21 14:29:11 +0300142 * @cl: client
Tomas Winklercd51ed62012-12-25 19:06:09 +0200143 * @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;
Alexander Usyskin1df629e2015-05-04 09:43:56 +0300155 cmd->host_addr = mei_cl_host_addr(cl);
Alexander Usyskind49ed642015-05-04 09:43:54 +0300156 cmd->me_addr = mei_cl_me_id(cl);
Tomas Winklercd51ed62012-12-25 19:06:09 +0200157}
158
159/**
Tomas Winkler68d1aa62014-08-21 14:29:11 +0300160 * 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
Tomas Winkler041330d2016-06-16 17:58:53 +0300165 * @buf: message buffer
Tomas Winkler68d1aa62014-08-21 14:29:11 +0300166 * @len: buffer length
Alexander Usyskince231392014-09-29 16:31:50 +0300167 *
168 * Return: 0 on success, <0 on failure.
Tomas Winkler68d1aa62014-08-21 14:29:11 +0300169 */
Tomas Winkler3fcbab62017-03-20 15:04:04 +0200170static inline int mei_hbm_cl_write(struct mei_device *dev, struct mei_cl *cl,
171 u8 hbm_cmd, void *buf, size_t len)
Tomas Winkler68d1aa62014-08-21 14:29:11 +0300172{
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400173 struct mei_msg_hdr mei_hdr;
Tomas Winkler68d1aa62014-08-21 14:29:11 +0300174
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400175 mei_hbm_hdr(&mei_hdr, len);
176 mei_hbm_cl_hdr(cl, hbm_cmd, buf, len);
Tomas Winkler68d1aa62014-08-21 14:29:11 +0300177
Tomas Winkler98e70862018-07-31 09:35:33 +0300178 return mei_hbm_write_message(dev, &mei_hdr, buf);
Tomas Winkler68d1aa62014-08-21 14:29:11 +0300179}
180
181/**
Tomas Winkler2af89db2014-08-21 14:29:20 +0300182 * mei_hbm_cl_addr_equal - check if the client's and
183 * the message address match
Tomas Winklercd51ed62012-12-25 19:06:09 +0200184 *
Tomas Winkler2af89db2014-08-21 14:29:20 +0300185 * @cl: client
186 * @cmd: hbm client message
Tomas Winklercd51ed62012-12-25 19:06:09 +0200187 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300188 * Return: true if addresses are the same
Tomas Winklercd51ed62012-12-25 19:06:09 +0200189 */
190static inline
Tomas Winkler2af89db2014-08-21 14:29:20 +0300191bool mei_hbm_cl_addr_equal(struct mei_cl *cl, struct mei_hbm_cl_cmd *cmd)
Tomas Winklercd51ed62012-12-25 19:06:09 +0200192{
Alexander Usyskin1df629e2015-05-04 09:43:56 +0300193 return mei_cl_host_addr(cl) == cmd->host_addr &&
Alexander Usyskind49ed642015-05-04 09:43:54 +0300194 mei_cl_me_id(cl) == cmd->me_addr;
Tomas Winklercd51ed62012-12-25 19:06:09 +0200195}
196
Alexander Usyskincb02efc2014-08-21 14:29:19 +0300197/**
Tomas Winkler2af89db2014-08-21 14:29:20 +0300198 * mei_hbm_cl_find_by_cmd - find recipient client
199 *
200 * @dev: the device structure
201 * @buf: a buffer with hbm cl command
202 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300203 * Return: the recipient client or NULL if not found
Tomas Winkler2af89db2014-08-21 14:29:20 +0300204 */
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/**
Alexander Usyskincb02efc2014-08-21 14:29:19 +0300219 * mei_hbm_start_wait - wait for start response message.
220 *
221 * @dev: the device structure
222 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300223 * Return: 0 on success and < 0 on failure
Alexander Usyskincb02efc2014-08-21 14:29:19 +0300224 */
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300225int mei_hbm_start_wait(struct mei_device *dev)
226{
227 int ret;
Alexander Usyskincb02efc2014-08-21 14:29:19 +0300228
229 if (dev->hbm_state > MEI_HBM_STARTING)
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300230 return 0;
231
232 mutex_unlock(&dev->device_lock);
Alexander Usyskincb02efc2014-08-21 14:29:19 +0300233 ret = wait_event_timeout(dev->wait_hbm_start,
234 dev->hbm_state != MEI_HBM_STARTING,
Tomas Winkler7d93e582014-01-14 23:10:10 +0200235 mei_secs_to_jiffies(MEI_HBM_TIMEOUT));
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300236 mutex_lock(&dev->device_lock);
237
Alexander Usyskincb02efc2014-08-21 14:29:19 +0300238 if (ret == 0 && (dev->hbm_state <= MEI_HBM_STARTING)) {
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300239 dev->hbm_state = MEI_HBM_IDLE;
Tomas Winkler2bf94cab2014-09-29 16:31:42 +0300240 dev_err(dev->dev, "waiting for mei start failed\n");
Alexander Usyskin7ca96aa2014-02-19 17:35:49 +0200241 return -ETIME;
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300242 }
243 return 0;
244}
245
Tomas Winkler6bbda152012-12-25 19:06:12 +0200246/**
Tomas Winkler8120e722012-12-25 19:06:11 +0200247 * mei_hbm_start_req - sends start request message.
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200248 *
249 * @dev: the device structure
Tomas Winkler544f9462014-01-08 20:19:21 +0200250 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300251 * Return: 0 on success and < 0 on failure
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200252 */
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300253int mei_hbm_start_req(struct mei_device *dev)
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200254{
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400255 struct mei_msg_hdr mei_hdr;
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300256 struct hbm_host_version_request req;
Tomas Winkler544f9462014-01-08 20:19:21 +0200257 int ret;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200258
Tomas Winkler5ca2d382014-08-21 14:29:13 +0300259 mei_hbm_reset(dev);
260
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300261 mei_hbm_hdr(&mei_hdr, sizeof(req));
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200262
263 /* host start message */
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300264 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;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200268
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300269 dev->hbm_state = MEI_HBM_IDLE;
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300270 ret = mei_hbm_write_message(dev, &mei_hdr, &req);
Tomas Winkler544f9462014-01-08 20:19:21 +0200271 if (ret) {
Tomas Winkler2bf94cab2014-09-29 16:31:42 +0300272 dev_err(dev->dev, "version message write failed: ret = %d\n",
Tomas Winkler544f9462014-01-08 20:19:21 +0200273 ret);
274 return ret;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200275 }
Tomas Winkler544f9462014-01-08 20:19:21 +0200276
Alexander Usyskincb02efc2014-08-21 14:29:19 +0300277 dev->hbm_state = MEI_HBM_STARTING;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200278 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
Alexander Usyskin1892fc22016-09-25 13:25:31 +0300279 mei_schedule_stall_timer(dev);
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300280 return 0;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200281}
282
Alexander Usyskin99c26582015-10-13 15:02:39 +0300283/**
Tomas Winklerc55bf542018-11-22 13:11:37 +0200284 * 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;
Tomas Winklerc55bf542018-11-22 13:11:37 +0200293 unsigned int i;
294 int ret;
295
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300296 mei_hbm_hdr(&mei_hdr, sizeof(req));
Tomas Winklerc55bf542018-11-22 13:11:37 +0200297
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300298 memset(&req, 0, sizeof(req));
Tomas Winklerc55bf542018-11-22 13:11:37 +0200299 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
Tomas Winkler2513eb02018-11-22 13:11:38 +0200309 mei_dma_ring_reset(dev);
310
Tomas Winklerc55bf542018-11-22 13:11:37 +0200311 ret = mei_hbm_write_message(dev, &mei_hdr, &req);
312 if (ret) {
313 dev_err(dev->dev, "dma setup request write failed: ret = %d.\n",
314 ret);
315 return ret;
316 }
317
318 dev->hbm_state = MEI_HBM_DR_SETUP;
319 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
320 mei_schedule_stall_timer(dev);
321 return 0;
322}
323
324/**
Alexander Usyskine5cab1f2020-08-18 14:51:35 +0300325 * 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;
Alexander Usyskinbeb4e1e2020-08-18 14:51:36 +0300341 if (dev->hbm_f_vt_supported)
Alexander Usyskinb7a48042021-02-06 16:43:22 +0200342 req.capability_requested[0] |= HBM_CAP_VT;
343 if (dev->hbm_f_cd_supported)
344 req.capability_requested[0] |= HBM_CAP_CD;
Alexander Usyskine5cab1f2020-08-18 14:51:35 +0300345
346 ret = mei_hbm_write_message(dev, &mei_hdr, &req);
347 if (ret) {
348 dev_err(dev->dev,
349 "capabilities request write failed: ret = %d.\n", ret);
350 return ret;
351 }
352
353 dev->hbm_state = MEI_HBM_CAP_SETUP;
354 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
355 mei_schedule_stall_timer(dev);
356 return 0;
357}
358
359/**
Tomas Winkler8120e722012-12-25 19:06:11 +0200360 * mei_hbm_enum_clients_req - sends enumeration client request message.
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200361 *
362 * @dev: the device structure
363 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300364 * Return: 0 on success and < 0 on failure
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200365 */
Tomas Winkler544f9462014-01-08 20:19:21 +0200366static int mei_hbm_enum_clients_req(struct mei_device *dev)
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200367{
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400368 struct mei_msg_hdr mei_hdr;
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300369 struct hbm_host_enum_request req;
Tomas Winkler544f9462014-01-08 20:19:21 +0200370 int ret;
371
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200372 /* enumerate clients */
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300373 mei_hbm_hdr(&mei_hdr, sizeof(req));
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200374
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300375 memset(&req, 0, sizeof(req));
376 req.hbm_cmd = HOST_ENUM_REQ_CMD;
377 req.flags |= dev->hbm_f_dc_supported ? MEI_HBM_ENUM_F_ALLOW_ADD : 0;
378 req.flags |= dev->hbm_f_ie_supported ?
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400379 MEI_HBM_ENUM_F_IMMEDIATE_ENUM : 0;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200380
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300381 ret = mei_hbm_write_message(dev, &mei_hdr, &req);
Tomas Winkler544f9462014-01-08 20:19:21 +0200382 if (ret) {
Tomas Winkler2bf94cab2014-09-29 16:31:42 +0300383 dev_err(dev->dev, "enumeration request write failed: ret = %d.\n",
Tomas Winkler544f9462014-01-08 20:19:21 +0200384 ret);
385 return ret;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200386 }
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300387 dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200388 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
Alexander Usyskin1892fc22016-09-25 13:25:31 +0300389 mei_schedule_stall_timer(dev);
Tomas Winkler544f9462014-01-08 20:19:21 +0200390 return 0;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200391}
392
Alexander Usyskin99c26582015-10-13 15:02:39 +0300393/**
Tomas Winkler5ca2d382014-08-21 14:29:13 +0300394 * mei_hbm_me_cl_add - add new me client to the list
395 *
396 * @dev: the device structure
397 * @res: hbm property response
398 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300399 * Return: 0 on success and -ENOMEM on allocation failure
Tomas Winkler5ca2d382014-08-21 14:29:13 +0300400 */
401
402static int mei_hbm_me_cl_add(struct mei_device *dev,
403 struct hbm_props_response *res)
404{
405 struct mei_me_client *me_cl;
Tomas Winkler79563db2015-01-11 00:07:16 +0200406 const uuid_le *uuid = &res->client_properties.protocol_name;
407
408 mei_me_cl_rm_by_uuid(dev, uuid);
Tomas Winkler5ca2d382014-08-21 14:29:13 +0300409
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300410 me_cl = kzalloc(sizeof(*me_cl), GFP_KERNEL);
Tomas Winkler5ca2d382014-08-21 14:29:13 +0300411 if (!me_cl)
412 return -ENOMEM;
413
Tomas Winkler79563db2015-01-11 00:07:16 +0200414 mei_me_cl_init(me_cl);
415
Tomas Winkler5ca2d382014-08-21 14:29:13 +0300416 me_cl->props = res->client_properties;
417 me_cl->client_id = res->me_addr;
Tomas Winkler4034b812016-07-26 01:06:04 +0300418 me_cl->tx_flow_ctrl_creds = 0;
Tomas Winkler5ca2d382014-08-21 14:29:13 +0300419
Tomas Winklerb7d88512015-02-10 10:39:31 +0200420 mei_me_cl_add(dev, me_cl);
421
Tomas Winkler5ca2d382014-08-21 14:29:13 +0300422 return 0;
423}
424
Tomas Winkler8120e722012-12-25 19:06:11 +0200425/**
Tomas Winkler70ef8352015-07-23 21:37:12 +0300426 * mei_hbm_add_cl_resp - send response to fw on client add request
427 *
428 * @dev: the device structure
429 * @addr: me address
430 * @status: response status
431 *
432 * Return: 0 on success and < 0 on failure
433 */
434static int mei_hbm_add_cl_resp(struct mei_device *dev, u8 addr, u8 status)
435{
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400436 struct mei_msg_hdr mei_hdr;
437 struct hbm_add_client_response resp;
Tomas Winkler70ef8352015-07-23 21:37:12 +0300438 int ret;
439
440 dev_dbg(dev->dev, "adding client response\n");
441
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300442 mei_hbm_hdr(&mei_hdr, sizeof(resp));
Tomas Winkler70ef8352015-07-23 21:37:12 +0300443
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300444 memset(&resp, 0, sizeof(resp));
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400445 resp.hbm_cmd = MEI_HBM_ADD_CLIENT_RES_CMD;
446 resp.me_addr = addr;
447 resp.status = status;
Tomas Winkler70ef8352015-07-23 21:37:12 +0300448
Tomas Winkler98e70862018-07-31 09:35:33 +0300449 ret = mei_hbm_write_message(dev, &mei_hdr, &resp);
Tomas Winkler70ef8352015-07-23 21:37:12 +0300450 if (ret)
451 dev_err(dev->dev, "add client response write failed: ret = %d\n",
452 ret);
453 return ret;
454}
455
456/**
457 * mei_hbm_fw_add_cl_req - request from the fw to add a client
458 *
459 * @dev: the device structure
460 * @req: add client request
461 *
462 * Return: 0 on success and < 0 on failure
463 */
464static int mei_hbm_fw_add_cl_req(struct mei_device *dev,
465 struct hbm_add_client_request *req)
466{
467 int ret;
468 u8 status = MEI_HBMS_SUCCESS;
469
470 BUILD_BUG_ON(sizeof(struct hbm_add_client_request) !=
471 sizeof(struct hbm_props_response));
472
473 ret = mei_hbm_me_cl_add(dev, (struct hbm_props_response *)req);
474 if (ret)
475 status = !MEI_HBMS_SUCCESS;
476
Alexander Usyskina816a002016-02-07 23:35:41 +0200477 if (dev->dev_state == MEI_DEV_ENABLED)
478 schedule_work(&dev->bus_rescan_work);
479
Tomas Winkler70ef8352015-07-23 21:37:12 +0300480 return mei_hbm_add_cl_resp(dev, req->me_addr, status);
481}
482
483/**
Tomas Winkler965ae372015-07-26 09:54:16 +0300484 * mei_hbm_cl_notify_req - send notification request
485 *
486 * @dev: the device structure
487 * @cl: a client to disconnect from
488 * @start: true for start false for stop
489 *
490 * Return: 0 on success and -EIO on write failure
491 */
492int mei_hbm_cl_notify_req(struct mei_device *dev,
493 struct mei_cl *cl, u8 start)
494{
495
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400496 struct mei_msg_hdr mei_hdr;
497 struct hbm_notification_request req;
Tomas Winkler965ae372015-07-26 09:54:16 +0300498 int ret;
499
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300500 mei_hbm_hdr(&mei_hdr, sizeof(req));
501 mei_hbm_cl_hdr(cl, MEI_HBM_NOTIFY_REQ_CMD, &req, sizeof(req));
Tomas Winkler965ae372015-07-26 09:54:16 +0300502
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400503 req.start = start;
Tomas Winkler965ae372015-07-26 09:54:16 +0300504
Tomas Winkler98e70862018-07-31 09:35:33 +0300505 ret = mei_hbm_write_message(dev, &mei_hdr, &req);
Tomas Winkler965ae372015-07-26 09:54:16 +0300506 if (ret)
507 dev_err(dev->dev, "notify request failed: ret = %d\n", ret);
508
509 return ret;
510}
511
512/**
513 * notify_res_to_fop - convert notification response to the proper
514 * notification FOP
515 *
516 * @cmd: client notification start response command
517 *
518 * Return: MEI_FOP_NOTIFY_START or MEI_FOP_NOTIFY_STOP;
519 */
520static inline enum mei_cb_file_ops notify_res_to_fop(struct mei_hbm_cl_cmd *cmd)
521{
522 struct hbm_notification_response *rs =
523 (struct hbm_notification_response *)cmd;
524
Tomas Winkler51678cc2015-07-26 09:54:18 +0300525 return mei_cl_notify_req2fop(rs->start);
Tomas Winkler965ae372015-07-26 09:54:16 +0300526}
527
528/**
529 * mei_hbm_cl_notify_start_res - update the client state according
530 * notify start response
531 *
532 * @dev: the device structure
533 * @cl: mei host client
534 * @cmd: client notification start response command
535 */
536static void mei_hbm_cl_notify_start_res(struct mei_device *dev,
537 struct mei_cl *cl,
538 struct mei_hbm_cl_cmd *cmd)
539{
540 struct hbm_notification_response *rs =
541 (struct hbm_notification_response *)cmd;
542
543 cl_dbg(dev, cl, "hbm: notify start response status=%d\n", rs->status);
544
545 if (rs->status == MEI_HBMS_SUCCESS ||
546 rs->status == MEI_HBMS_ALREADY_STARTED) {
547 cl->notify_en = true;
548 cl->status = 0;
549 } else {
550 cl->status = -EINVAL;
551 }
552}
553
554/**
555 * mei_hbm_cl_notify_stop_res - update the client state according
556 * notify stop response
557 *
558 * @dev: the device structure
559 * @cl: mei host client
560 * @cmd: client notification stop response command
561 */
562static void mei_hbm_cl_notify_stop_res(struct mei_device *dev,
563 struct mei_cl *cl,
564 struct mei_hbm_cl_cmd *cmd)
565{
566 struct hbm_notification_response *rs =
567 (struct hbm_notification_response *)cmd;
568
569 cl_dbg(dev, cl, "hbm: notify stop response status=%d\n", rs->status);
570
571 if (rs->status == MEI_HBMS_SUCCESS ||
572 rs->status == MEI_HBMS_NOT_STARTED) {
573 cl->notify_en = false;
574 cl->status = 0;
575 } else {
576 /* TODO: spec is not clear yet about other possible issues */
577 cl->status = -EINVAL;
578 }
579}
580
581/**
582 * mei_hbm_cl_notify - signal notification event
583 *
584 * @dev: the device structure
585 * @cmd: notification client message
586 */
587static void mei_hbm_cl_notify(struct mei_device *dev,
588 struct mei_hbm_cl_cmd *cmd)
589{
590 struct mei_cl *cl;
591
592 cl = mei_hbm_cl_find_by_cmd(dev, cmd);
Tomas Winkler237092b2015-07-26 09:54:22 +0300593 if (cl)
594 mei_cl_notify(cl);
Tomas Winkler965ae372015-07-26 09:54:16 +0300595}
596
597/**
Alexander Usyskin369aea82021-02-06 16:43:24 +0200598 * mei_hbm_cl_dma_map_req - send client dma map request
599 *
600 * @dev: the device structure
601 * @cl: mei host client
602 *
603 * Return: 0 on success and -EIO on write failure
604 */
605int mei_hbm_cl_dma_map_req(struct mei_device *dev, struct mei_cl *cl)
606{
607 struct mei_msg_hdr mei_hdr;
608 struct hbm_client_dma_map_request req;
609 int ret;
610
611 mei_hbm_hdr(&mei_hdr, sizeof(req));
612
613 memset(&req, 0, sizeof(req));
614
615 req.hbm_cmd = MEI_HBM_CLIENT_DMA_MAP_REQ_CMD;
616 req.client_buffer_id = cl->dma.buffer_id;
617 req.address_lsb = lower_32_bits(cl->dma.daddr);
618 req.address_msb = upper_32_bits(cl->dma.daddr);
619 req.size = cl->dma.size;
620
621 ret = mei_hbm_write_message(dev, &mei_hdr, &req);
622 if (ret)
623 dev_err(dev->dev, "dma map request failed: ret = %d\n", ret);
624
625 return ret;
626}
627
628/**
629 * mei_hbm_cl_dma_unmap_req - send client dma unmap request
630 *
631 * @dev: the device structure
632 * @cl: mei host client
633 *
634 * Return: 0 on success and -EIO on write failure
635 */
636int mei_hbm_cl_dma_unmap_req(struct mei_device *dev, struct mei_cl *cl)
637{
638 struct mei_msg_hdr mei_hdr;
639 struct hbm_client_dma_unmap_request req;
640 int ret;
641
642 mei_hbm_hdr(&mei_hdr, sizeof(req));
643
644 memset(&req, 0, sizeof(req));
645
646 req.hbm_cmd = MEI_HBM_CLIENT_DMA_UNMAP_REQ_CMD;
647 req.client_buffer_id = cl->dma.buffer_id;
648
649 ret = mei_hbm_write_message(dev, &mei_hdr, &req);
650 if (ret)
651 dev_err(dev->dev, "dma unmap request failed: ret = %d\n", ret);
652
653 return ret;
654}
655
656static void mei_hbm_cl_dma_map_res(struct mei_device *dev,
657 struct hbm_client_dma_response *res)
658{
659 struct mei_cl *cl;
660 struct mei_cl_cb *cb, *next;
661
662 cl = NULL;
663 list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list, list) {
664 if (cb->fop_type != MEI_FOP_DMA_MAP)
665 continue;
666 if (!cb->cl->dma.buffer_id || cb->cl->dma_mapped)
667 continue;
668
669 cl = cb->cl;
670 break;
671 }
672 if (!cl)
673 return;
674
675 dev_dbg(dev->dev, "cl dma map result = %d\n", res->status);
676 cl->status = res->status;
677 if (!cl->status)
678 cl->dma_mapped = 1;
679 wake_up(&cl->wait);
680}
681
682static void mei_hbm_cl_dma_unmap_res(struct mei_device *dev,
683 struct hbm_client_dma_response *res)
684{
685 struct mei_cl *cl;
686 struct mei_cl_cb *cb, *next;
687
688 cl = NULL;
689 list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list, list) {
690 if (cb->fop_type != MEI_FOP_DMA_UNMAP)
691 continue;
692 if (!cb->cl->dma.buffer_id || !cb->cl->dma_mapped)
693 continue;
694
695 cl = cb->cl;
696 break;
697 }
698 if (!cl)
699 return;
700
701 dev_dbg(dev->dev, "cl dma unmap result = %d\n", res->status);
702 cl->status = res->status;
703 if (!cl->status)
704 cl->dma_mapped = 0;
705 wake_up(&cl->wait);
706}
707
708/**
Masanari Iida393b1482013-04-05 01:05:05 +0900709 * mei_hbm_prop_req - request property for a single client
Tomas Winkler8120e722012-12-25 19:06:11 +0200710 *
711 * @dev: the device structure
Alexander Usyskincc25aa92016-04-17 12:16:02 -0400712 * @start_idx: client index to start search
Tomas Winkler8120e722012-12-25 19:06:11 +0200713 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300714 * Return: 0 on success and < 0 on failure
Tomas Winkler8120e722012-12-25 19:06:11 +0200715 */
Alexander Usyskincc25aa92016-04-17 12:16:02 -0400716static int mei_hbm_prop_req(struct mei_device *dev, unsigned long start_idx)
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200717{
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400718 struct mei_msg_hdr mei_hdr;
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300719 struct hbm_props_request req;
Alexander Usyskincc25aa92016-04-17 12:16:02 -0400720 unsigned long addr;
Tomas Winkler544f9462014-01-08 20:19:21 +0200721 int ret;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200722
Alexander Usyskincc25aa92016-04-17 12:16:02 -0400723 addr = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, start_idx);
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200724
725 /* We got all client properties */
Alexander Usyskincc25aa92016-04-17 12:16:02 -0400726 if (addr == MEI_CLIENTS_MAX) {
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +0300727 dev->hbm_state = MEI_HBM_STARTED;
Alexander Usyskin025fb792016-02-07 23:35:43 +0200728 mei_host_client_init(dev);
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200729 return 0;
730 }
731
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300732 mei_hbm_hdr(&mei_hdr, sizeof(req));
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200733
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300734 memset(&req, 0, sizeof(req));
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200735
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300736 req.hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
737 req.me_addr = addr;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200738
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300739 ret = mei_hbm_write_message(dev, &mei_hdr, &req);
Tomas Winkler544f9462014-01-08 20:19:21 +0200740 if (ret) {
Tomas Winkler2bf94cab2014-09-29 16:31:42 +0300741 dev_err(dev->dev, "properties request write failed: ret = %d\n",
Tomas Winkler544f9462014-01-08 20:19:21 +0200742 ret);
743 return ret;
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200744 }
745
746 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
Alexander Usyskin1892fc22016-09-25 13:25:31 +0300747 mei_schedule_stall_timer(dev);
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200748
749 return 0;
750}
751
Alexander Usyskin99c26582015-10-13 15:02:39 +0300752/**
Tomas Winkler4fcbc992014-03-18 22:51:55 +0200753 * mei_hbm_pg - sends pg command
754 *
755 * @dev: the device structure
756 * @pg_cmd: the pg command code
757 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300758 * Return: -EIO on write failure
Tomas Winklerbae1cc72014-08-21 14:29:21 +0300759 * -EOPNOTSUPP if the operation is not supported by the protocol
Tomas Winkler4fcbc992014-03-18 22:51:55 +0200760 */
761int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
762{
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400763 struct mei_msg_hdr mei_hdr;
764 struct hbm_power_gate req;
Tomas Winkler4fcbc992014-03-18 22:51:55 +0200765 int ret;
766
Tomas Winklerbae1cc72014-08-21 14:29:21 +0300767 if (!dev->hbm_f_pg_supported)
768 return -EOPNOTSUPP;
769
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300770 mei_hbm_hdr(&mei_hdr, sizeof(req));
Tomas Winkler4fcbc992014-03-18 22:51:55 +0200771
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300772 memset(&req, 0, sizeof(req));
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400773 req.hbm_cmd = pg_cmd;
Tomas Winkler4fcbc992014-03-18 22:51:55 +0200774
Tomas Winkler98e70862018-07-31 09:35:33 +0300775 ret = mei_hbm_write_message(dev, &mei_hdr, &req);
Tomas Winkler4fcbc992014-03-18 22:51:55 +0200776 if (ret)
Tomas Winkler2bf94cab2014-09-29 16:31:42 +0300777 dev_err(dev->dev, "power gate command write failed.\n");
Tomas Winkler4fcbc992014-03-18 22:51:55 +0200778 return ret;
779}
780EXPORT_SYMBOL_GPL(mei_hbm_pg);
781
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200782/**
Tomas Winkler6bb948c2014-02-12 21:41:52 +0200783 * mei_hbm_stop_req - send stop request message
Tomas Winklere46f1872012-12-25 19:06:10 +0200784 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300785 * @dev: mei device
Tomas Winkler6bb948c2014-02-12 21:41:52 +0200786 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300787 * Return: -EIO on write failure
Tomas Winklere46f1872012-12-25 19:06:10 +0200788 */
Tomas Winkler6bb948c2014-02-12 21:41:52 +0200789static int mei_hbm_stop_req(struct mei_device *dev)
Tomas Winklere46f1872012-12-25 19:06:10 +0200790{
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400791 struct mei_msg_hdr mei_hdr;
792 struct hbm_host_stop_request req;
Tomas Winklere46f1872012-12-25 19:06:10 +0200793
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300794 mei_hbm_hdr(&mei_hdr, sizeof(req));
Tomas Winklere46f1872012-12-25 19:06:10 +0200795
Tomas Winklerdf4b37b2020-07-23 17:59:22 +0300796 memset(&req, 0, sizeof(req));
Alexander Usyskinc0ff9012016-05-09 00:07:47 -0400797 req.hbm_cmd = HOST_STOP_REQ_CMD;
798 req.reason = DRIVER_STOP_REQUEST;
Tomas Winkler6bb948c2014-02-12 21:41:52 +0200799
Tomas Winkler98e70862018-07-31 09:35:33 +0300800 return mei_hbm_write_message(dev, &mei_hdr, &req);
Tomas Winklere46f1872012-12-25 19:06:10 +0200801}
802
803/**
Alexander Usyskin83ce0742014-01-08 22:31:46 +0200804 * mei_hbm_cl_flow_control_req - sends flow control request.
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200805 *
806 * @dev: the device structure
Tomas Winkler8120e722012-12-25 19:06:11 +0200807 * @cl: client info
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200808 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300809 * Return: -EIO on write failure
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200810 */
Tomas Winkler8120e722012-12-25 19:06:11 +0200811int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200812{
Tomas Winkler3fcbab62017-03-20 15:04:04 +0200813 struct hbm_flow_control req;
Tomas Winkler92db1552014-09-29 16:31:37 +0300814
Tomas Winkler46922182014-03-16 14:35:55 +0200815 cl_dbg(dev, cl, "sending flow control\n");
Tomas Winkler3fcbab62017-03-20 15:04:04 +0200816 return mei_hbm_cl_write(dev, cl, MEI_FLOW_CONTROL_CMD,
817 &req, sizeof(req));
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200818}
819
820/**
Tomas Winkler4034b812016-07-26 01:06:04 +0300821 * mei_hbm_add_single_tx_flow_ctrl_creds - adds single buffer credentials.
Tomas Winkler6bbda152012-12-25 19:06:12 +0200822 *
Masanari Iida393b1482013-04-05 01:05:05 +0900823 * @dev: the device structure
Tomas Winkler4034b812016-07-26 01:06:04 +0300824 * @fctrl: flow control response bus message
Alexander Usyskin12d00662014-02-17 15:13:23 +0200825 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300826 * Return: 0 on success, < 0 otherwise
Tomas Winkler6bbda152012-12-25 19:06:12 +0200827 */
Tomas Winkler4034b812016-07-26 01:06:04 +0300828static int mei_hbm_add_single_tx_flow_ctrl_creds(struct mei_device *dev,
829 struct hbm_flow_control *fctrl)
Tomas Winkler6bbda152012-12-25 19:06:12 +0200830{
Alexander Usyskin12d00662014-02-17 15:13:23 +0200831 struct mei_me_client *me_cl;
Tomas Winkler79563db2015-01-11 00:07:16 +0200832 int rets;
Tomas Winkler6bbda152012-12-25 19:06:12 +0200833
Tomas Winkler4034b812016-07-26 01:06:04 +0300834 me_cl = mei_me_cl_by_id(dev, fctrl->me_addr);
Tomas Winklerd3208322014-08-24 12:08:55 +0300835 if (!me_cl) {
Tomas Winkler4034b812016-07-26 01:06:04 +0300836 dev_err(dev->dev, "no such me client %d\n", fctrl->me_addr);
Tomas Winklerd3208322014-08-24 12:08:55 +0300837 return -ENOENT;
Tomas Winkler6bbda152012-12-25 19:06:12 +0200838 }
Alexander Usyskin12d00662014-02-17 15:13:23 +0200839
Tomas Winkler79563db2015-01-11 00:07:16 +0200840 if (WARN_ON(me_cl->props.single_recv_buf == 0)) {
841 rets = -EINVAL;
842 goto out;
843 }
Tomas Winklerd3208322014-08-24 12:08:55 +0300844
Tomas Winkler4034b812016-07-26 01:06:04 +0300845 me_cl->tx_flow_ctrl_creds++;
Tomas Winkler2bf94cab2014-09-29 16:31:42 +0300846 dev_dbg(dev->dev, "recv flow ctrl msg ME %d (single) creds = %d.\n",
Tomas Winkler4034b812016-07-26 01:06:04 +0300847 fctrl->me_addr, me_cl->tx_flow_ctrl_creds);
Alexander Usyskin12d00662014-02-17 15:13:23 +0200848
Tomas Winkler79563db2015-01-11 00:07:16 +0200849 rets = 0;
850out:
851 mei_me_cl_put(me_cl);
852 return rets;
Tomas Winkler6bbda152012-12-25 19:06:12 +0200853}
854
855/**
Tamar Mashiah09f8c332021-06-21 22:37:55 +0300856 * mei_hbm_cl_tx_flow_ctrl_creds_res - flow control response from me
Tomas Winkler6bbda152012-12-25 19:06:12 +0200857 *
858 * @dev: the device structure
Tomas Winkler4034b812016-07-26 01:06:04 +0300859 * @fctrl: flow control response bus message
Tomas Winkler6bbda152012-12-25 19:06:12 +0200860 */
Tomas Winkler4034b812016-07-26 01:06:04 +0300861static void mei_hbm_cl_tx_flow_ctrl_creds_res(struct mei_device *dev,
862 struct hbm_flow_control *fctrl)
Tomas Winkler6bbda152012-12-25 19:06:12 +0200863{
Tomas Winkler31f88f52014-02-17 15:13:25 +0200864 struct mei_cl *cl;
Tomas Winkler6bbda152012-12-25 19:06:12 +0200865
Tomas Winkler4034b812016-07-26 01:06:04 +0300866 if (!fctrl->host_addr) {
Tomas Winkler6bbda152012-12-25 19:06:12 +0200867 /* single receive buffer */
Tomas Winkler4034b812016-07-26 01:06:04 +0300868 mei_hbm_add_single_tx_flow_ctrl_creds(dev, fctrl);
Tomas Winkler6bbda152012-12-25 19:06:12 +0200869 return;
870 }
871
Tomas Winkler4034b812016-07-26 01:06:04 +0300872 cl = mei_hbm_cl_find_by_cmd(dev, fctrl);
Tomas Winkler2af89db2014-08-21 14:29:20 +0300873 if (cl) {
Tomas Winkler4034b812016-07-26 01:06:04 +0300874 cl->tx_flow_ctrl_creds++;
Tomas Winkler2af89db2014-08-21 14:29:20 +0300875 cl_dbg(dev, cl, "flow control creds = %d.\n",
Tomas Winkler4034b812016-07-26 01:06:04 +0300876 cl->tx_flow_ctrl_creds);
Tomas Winkler6bbda152012-12-25 19:06:12 +0200877 }
878}
879
880
881/**
Tomas Winkler8120e722012-12-25 19:06:11 +0200882 * mei_hbm_cl_disconnect_req - sends disconnect message to fw.
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200883 *
884 * @dev: the device structure
Tomas Winkler8120e722012-12-25 19:06:11 +0200885 * @cl: a client to disconnect from
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200886 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300887 * Return: -EIO on write failure
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200888 */
Tomas Winkler8120e722012-12-25 19:06:11 +0200889int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200890{
Tomas Winkler3fcbab62017-03-20 15:04:04 +0200891 struct hbm_client_connect_request req;
Tomas Winkler92db1552014-09-29 16:31:37 +0300892
Tomas Winkler3fcbab62017-03-20 15:04:04 +0200893 return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_REQ_CMD,
894 &req, sizeof(req));
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200895}
896
897/**
Tomas Winkler6bb948c2014-02-12 21:41:52 +0200898 * mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW
899 *
900 * @dev: the device structure
901 * @cl: a client to disconnect from
902 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300903 * Return: -EIO on write failure
Tomas Winkler6bb948c2014-02-12 21:41:52 +0200904 */
905int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
906{
Tomas Winkler3fcbab62017-03-20 15:04:04 +0200907 struct hbm_client_connect_response resp;
Tomas Winkler92db1552014-09-29 16:31:37 +0300908
Tomas Winkler3fcbab62017-03-20 15:04:04 +0200909 return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_RES_CMD,
910 &resp, sizeof(resp));
Tomas Winkler6bb948c2014-02-12 21:41:52 +0200911}
912
913/**
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300914 * mei_hbm_cl_disconnect_res - update the client state according
915 * disconnect response
Tomas Winkler6bbda152012-12-25 19:06:12 +0200916 *
Alexander Usyskind512c202014-10-29 23:50:58 +0200917 * @dev: the device structure
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300918 * @cl: mei host client
919 * @cmd: disconnect client response host bus message
Tomas Winkler6bbda152012-12-25 19:06:12 +0200920 */
Alexander Usyskind512c202014-10-29 23:50:58 +0200921static void mei_hbm_cl_disconnect_res(struct mei_device *dev, struct mei_cl *cl,
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300922 struct mei_hbm_cl_cmd *cmd)
Tomas Winkler6bbda152012-12-25 19:06:12 +0200923{
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300924 struct hbm_client_connect_response *rs =
925 (struct hbm_client_connect_response *)cmd;
Tomas Winkler6bbda152012-12-25 19:06:12 +0200926
Alexander Usyskind512c202014-10-29 23:50:58 +0200927 cl_dbg(dev, cl, "hbm: disconnect response status=%d\n", rs->status);
Tomas Winkler6bbda152012-12-25 19:06:12 +0200928
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300929 if (rs->status == MEI_CL_DISCONN_SUCCESS)
Tomas Winkler3c666182015-05-04 09:43:52 +0300930 cl->state = MEI_FILE_DISCONNECT_REPLY;
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300931 cl->status = 0;
Tomas Winkler6bbda152012-12-25 19:06:12 +0200932}
933
934/**
Tomas Winkler8120e722012-12-25 19:06:11 +0200935 * mei_hbm_cl_connect_req - send connection request to specific me client
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200936 *
937 * @dev: the device structure
Tomas Winkler8120e722012-12-25 19:06:11 +0200938 * @cl: a client to connect to
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200939 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +0300940 * Return: -EIO on write failure
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200941 */
Tomas Winkler8120e722012-12-25 19:06:11 +0200942int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200943{
Tomas Winkler3fcbab62017-03-20 15:04:04 +0200944 struct hbm_client_connect_request req;
Tomas Winkler92db1552014-09-29 16:31:37 +0300945
Tomas Winkler3fcbab62017-03-20 15:04:04 +0200946 return mei_hbm_cl_write(dev, cl, CLIENT_CONNECT_REQ_CMD,
947 &req, sizeof(req));
Tomas Winklerbb1b0132012-12-25 19:06:07 +0200948}
949
950/**
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300951 * mei_hbm_cl_connect_res - update the client state according
952 * connection response
Tomas Winkler6bbda152012-12-25 19:06:12 +0200953 *
Alexander Usyskind512c202014-10-29 23:50:58 +0200954 * @dev: the device structure
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300955 * @cl: mei host client
956 * @cmd: connect client response host bus message
Tomas Winkler6bbda152012-12-25 19:06:12 +0200957 */
Alexander Usyskind512c202014-10-29 23:50:58 +0200958static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl,
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300959 struct mei_hbm_cl_cmd *cmd)
Tomas Winkler6bbda152012-12-25 19:06:12 +0200960{
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300961 struct hbm_client_connect_response *rs =
962 (struct hbm_client_connect_response *)cmd;
Tomas Winkler6bbda152012-12-25 19:06:12 +0200963
Alexander Usyskind512c202014-10-29 23:50:58 +0200964 cl_dbg(dev, cl, "hbm: connect response status=%s\n",
Alexander Usyskin285e2992014-02-17 15:13:20 +0200965 mei_cl_conn_status_str(rs->status));
Tomas Winkler6bbda152012-12-25 19:06:12 +0200966
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300967 if (rs->status == MEI_CL_CONN_SUCCESS)
968 cl->state = MEI_FILE_CONNECTED;
Tomas Winkler70ef8352015-07-23 21:37:12 +0300969 else {
Tomas Winkler3c666182015-05-04 09:43:52 +0300970 cl->state = MEI_FILE_DISCONNECT_REPLY;
Alexander Usyskina816a002016-02-07 23:35:41 +0200971 if (rs->status == MEI_CL_CONN_NOT_FOUND) {
Tomas Winkler70ef8352015-07-23 21:37:12 +0300972 mei_me_cl_del(dev, cl->me_cl);
Alexander Usyskina816a002016-02-07 23:35:41 +0200973 if (dev->dev_state == MEI_DEV_ENABLED)
974 schedule_work(&dev->bus_rescan_work);
975 }
Tomas Winkler70ef8352015-07-23 21:37:12 +0300976 }
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300977 cl->status = mei_cl_conn_status_to_errno(rs->status);
978}
Tomas Winkler6bbda152012-12-25 19:06:12 +0200979
Tomas Winkler12f45ed2014-08-21 14:29:18 +0300980/**
981 * mei_hbm_cl_res - process hbm response received on behalf
982 * an client
983 *
984 * @dev: the device structure
985 * @rs: hbm client message
986 * @fop_type: file operation type
987 */
988static void mei_hbm_cl_res(struct mei_device *dev,
989 struct mei_hbm_cl_cmd *rs,
990 enum mei_cb_file_ops fop_type)
991{
992 struct mei_cl *cl;
993 struct mei_cl_cb *cb, *next;
994
995 cl = NULL;
Alexander Usyskin962ff7b2017-01-27 16:32:45 +0200996 list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list, list) {
Tomas Winkler6bbda152012-12-25 19:06:12 +0200997
Tomas Winkler64092852014-02-17 15:13:21 +0200998 cl = cb->cl;
Tomas Winkler64092852014-02-17 15:13:21 +0200999
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001000 if (cb->fop_type != fop_type)
Tomas Winkler64092852014-02-17 15:13:21 +02001001 continue;
1002
1003 if (mei_hbm_cl_addr_equal(cl, rs)) {
Tomas Winkler928fa662015-02-10 10:39:45 +02001004 list_del_init(&cb->list);
Tomas Winkler64092852014-02-17 15:13:21 +02001005 break;
Tomas Winkler6bbda152012-12-25 19:06:12 +02001006 }
1007 }
Tomas Winkler64092852014-02-17 15:13:21 +02001008
1009 if (!cl)
1010 return;
1011
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001012 switch (fop_type) {
1013 case MEI_FOP_CONNECT:
Alexander Usyskind512c202014-10-29 23:50:58 +02001014 mei_hbm_cl_connect_res(dev, cl, rs);
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001015 break;
1016 case MEI_FOP_DISCONNECT:
Alexander Usyskind512c202014-10-29 23:50:58 +02001017 mei_hbm_cl_disconnect_res(dev, cl, rs);
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001018 break;
Tomas Winkler965ae372015-07-26 09:54:16 +03001019 case MEI_FOP_NOTIFY_START:
1020 mei_hbm_cl_notify_start_res(dev, cl, rs);
1021 break;
1022 case MEI_FOP_NOTIFY_STOP:
1023 mei_hbm_cl_notify_stop_res(dev, cl, rs);
1024 break;
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001025 default:
1026 return;
1027 }
1028
Tomas Winkler64092852014-02-17 15:13:21 +02001029 cl->timer_count = 0;
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001030 wake_up(&cl->wait);
Tomas Winkler6bbda152012-12-25 19:06:12 +02001031}
1032
1033
1034/**
Alexander Usyskin83ce0742014-01-08 22:31:46 +02001035 * mei_hbm_fw_disconnect_req - disconnect request initiated by ME firmware
1036 * host sends disconnect response
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001037 *
1038 * @dev: the device structure.
Tomas Winkler8120e722012-12-25 19:06:11 +02001039 * @disconnect_req: disconnect request bus message from the me
Tomas Winkler6bb948c2014-02-12 21:41:52 +02001040 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +03001041 * Return: -ENOMEM on allocation failure
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001042 */
Tomas Winkler6bb948c2014-02-12 21:41:52 +02001043static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001044 struct hbm_client_connect_request *disconnect_req)
1045{
Tomas Winkler31f88f52014-02-17 15:13:25 +02001046 struct mei_cl *cl;
Tomas Winkler6bb948c2014-02-12 21:41:52 +02001047 struct mei_cl_cb *cb;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001048
Tomas Winkler2af89db2014-08-21 14:29:20 +03001049 cl = mei_hbm_cl_find_by_cmd(dev, disconnect_req);
1050 if (cl) {
Alexander Usyskin6938c192016-02-07 23:35:39 +02001051 cl_warn(dev, cl, "fw disconnect request received\n");
Tomas Winkler3c666182015-05-04 09:43:52 +03001052 cl->state = MEI_FILE_DISCONNECTING;
Tomas Winkler2af89db2014-08-21 14:29:20 +03001053 cl->timer_count = 0;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001054
Tomas Winkler3030dc02016-07-26 01:06:05 +03001055 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT_RSP,
1056 NULL);
Tomas Winkler2af89db2014-08-21 14:29:20 +03001057 if (!cb)
1058 return -ENOMEM;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001059 }
Tomas Winkler6bb948c2014-02-12 21:41:52 +02001060 return 0;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001061}
1062
Tomas Winklerbae1cc72014-08-21 14:29:21 +03001063/**
Alexander Usyskin63f75232015-08-02 22:20:53 +03001064 * mei_hbm_pg_enter_res - PG enter response received
1065 *
1066 * @dev: the device structure.
1067 *
1068 * Return: 0 on success, -EPROTO on state mismatch
1069 */
1070static int mei_hbm_pg_enter_res(struct mei_device *dev)
1071{
1072 if (mei_pg_state(dev) != MEI_PG_OFF ||
1073 dev->pg_event != MEI_PG_EVENT_WAIT) {
1074 dev_err(dev->dev, "hbm: pg entry response: state mismatch [%s, %d]\n",
1075 mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
1076 return -EPROTO;
1077 }
1078
1079 dev->pg_event = MEI_PG_EVENT_RECEIVED;
1080 wake_up(&dev->wait_pg);
1081
1082 return 0;
1083}
1084
1085/**
Alexander Usyskin859ef2f2015-08-02 22:20:54 +03001086 * mei_hbm_pg_resume - process with PG resume
1087 *
1088 * @dev: the device structure.
1089 */
1090void mei_hbm_pg_resume(struct mei_device *dev)
1091{
1092 pm_request_resume(dev->dev);
1093}
1094EXPORT_SYMBOL_GPL(mei_hbm_pg_resume);
1095
1096/**
Alexander Usyskin63f75232015-08-02 22:20:53 +03001097 * mei_hbm_pg_exit_res - PG exit response received
1098 *
1099 * @dev: the device structure.
1100 *
1101 * Return: 0 on success, -EPROTO on state mismatch
1102 */
1103static int mei_hbm_pg_exit_res(struct mei_device *dev)
1104{
1105 if (mei_pg_state(dev) != MEI_PG_ON ||
1106 (dev->pg_event != MEI_PG_EVENT_WAIT &&
1107 dev->pg_event != MEI_PG_EVENT_IDLE)) {
1108 dev_err(dev->dev, "hbm: pg exit response: state mismatch [%s, %d]\n",
1109 mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
1110 return -EPROTO;
1111 }
1112
1113 switch (dev->pg_event) {
1114 case MEI_PG_EVENT_WAIT:
1115 dev->pg_event = MEI_PG_EVENT_RECEIVED;
1116 wake_up(&dev->wait_pg);
1117 break;
1118 case MEI_PG_EVENT_IDLE:
1119 /*
1120 * If the driver is not waiting on this then
1121 * this is HW initiated exit from PG.
1122 * Start runtime pm resume sequence to exit from PG.
1123 */
1124 dev->pg_event = MEI_PG_EVENT_RECEIVED;
Alexander Usyskin859ef2f2015-08-02 22:20:54 +03001125 mei_hbm_pg_resume(dev);
Alexander Usyskin63f75232015-08-02 22:20:53 +03001126 break;
1127 default:
1128 WARN(1, "hbm: pg exit response: unexpected pg event = %d\n",
1129 dev->pg_event);
1130 return -EPROTO;
1131 }
1132
1133 return 0;
1134}
1135
1136/**
Alexander Usyskina8605ea2014-09-29 16:31:49 +03001137 * mei_hbm_config_features - check what hbm features and commands
Tomas Winklerbae1cc72014-08-21 14:29:21 +03001138 * are supported by the fw
1139 *
1140 * @dev: the device structure
1141 */
1142static void mei_hbm_config_features(struct mei_device *dev)
1143{
1144 /* Power Gating Isolation Support */
1145 dev->hbm_f_pg_supported = 0;
1146 if (dev->version.major_version > HBM_MAJOR_VERSION_PGI)
1147 dev->hbm_f_pg_supported = 1;
1148
1149 if (dev->version.major_version == HBM_MAJOR_VERSION_PGI &&
1150 dev->version.minor_version >= HBM_MINOR_VERSION_PGI)
1151 dev->hbm_f_pg_supported = 1;
Tomas Winkler70ef8352015-07-23 21:37:12 +03001152
Alexander Usyskin37fd0b622019-02-20 16:55:37 +02001153 dev->hbm_f_dc_supported = 0;
Tomas Winkler70ef8352015-07-23 21:37:12 +03001154 if (dev->version.major_version >= HBM_MAJOR_VERSION_DC)
1155 dev->hbm_f_dc_supported = 1;
Alexander Usyskin18901352015-07-23 21:37:13 +03001156
Alexander Usyskin37fd0b622019-02-20 16:55:37 +02001157 dev->hbm_f_ie_supported = 0;
Alexander Usyskin27f476e2016-02-07 23:35:42 +02001158 if (dev->version.major_version >= HBM_MAJOR_VERSION_IE)
1159 dev->hbm_f_ie_supported = 1;
1160
Alexander Usyskin18901352015-07-23 21:37:13 +03001161 /* disconnect on connect timeout instead of link reset */
Alexander Usyskin37fd0b622019-02-20 16:55:37 +02001162 dev->hbm_f_dot_supported = 0;
Alexander Usyskin18901352015-07-23 21:37:13 +03001163 if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT)
1164 dev->hbm_f_dot_supported = 1;
Tomas Winkler4d998772015-07-26 09:54:17 +03001165
1166 /* Notification Event Support */
Alexander Usyskin37fd0b622019-02-20 16:55:37 +02001167 dev->hbm_f_ev_supported = 0;
Tomas Winkler4d998772015-07-26 09:54:17 +03001168 if (dev->version.major_version >= HBM_MAJOR_VERSION_EV)
1169 dev->hbm_f_ev_supported = 1;
Alexander Usyskinf4e06242016-02-07 23:35:38 +02001170
1171 /* Fixed Address Client Support */
Alexander Usyskin37fd0b622019-02-20 16:55:37 +02001172 dev->hbm_f_fa_supported = 0;
Alexander Usyskinf4e06242016-02-07 23:35:38 +02001173 if (dev->version.major_version >= HBM_MAJOR_VERSION_FA)
1174 dev->hbm_f_fa_supported = 1;
Alexander Usyskin7ee7f452017-01-11 01:27:21 +02001175
1176 /* OS ver message Support */
Alexander Usyskin37fd0b622019-02-20 16:55:37 +02001177 dev->hbm_f_os_supported = 0;
Alexander Usyskin7ee7f452017-01-11 01:27:21 +02001178 if (dev->version.major_version >= HBM_MAJOR_VERSION_OS)
1179 dev->hbm_f_os_supported = 1;
Tomas Winklerc2bd9fc2018-07-31 09:35:36 +03001180
1181 /* DMA Ring Support */
Alexander Usyskin37fd0b622019-02-20 16:55:37 +02001182 dev->hbm_f_dr_supported = 0;
Tomas Winklerc2bd9fc2018-07-31 09:35:36 +03001183 if (dev->version.major_version > HBM_MAJOR_VERSION_DR ||
1184 (dev->version.major_version == HBM_MAJOR_VERSION_DR &&
1185 dev->version.minor_version >= HBM_MINOR_VERSION_DR))
1186 dev->hbm_f_dr_supported = 1;
Alexander Usyskine5cab1f2020-08-18 14:51:35 +03001187
Alexander Usyskinbeb4e1e2020-08-18 14:51:36 +03001188 /* VTag Support */
1189 dev->hbm_f_vt_supported = 0;
1190 if (dev->version.major_version > HBM_MAJOR_VERSION_VT ||
1191 (dev->version.major_version == HBM_MAJOR_VERSION_VT &&
1192 dev->version.minor_version >= HBM_MINOR_VERSION_VT))
1193 dev->hbm_f_vt_supported = 1;
1194
1195 /* Capability message Support */
Alexander Usyskine5cab1f2020-08-18 14:51:35 +03001196 dev->hbm_f_cap_supported = 0;
1197 if (dev->version.major_version > HBM_MAJOR_VERSION_CAP ||
1198 (dev->version.major_version == HBM_MAJOR_VERSION_CAP &&
1199 dev->version.minor_version >= HBM_MINOR_VERSION_CAP))
1200 dev->hbm_f_cap_supported = 1;
Alexander Usyskinb7a48042021-02-06 16:43:22 +02001201
1202 /* Client DMA Support */
1203 dev->hbm_f_cd_supported = 0;
1204 if (dev->version.major_version > HBM_MAJOR_VERSION_CD ||
1205 (dev->version.major_version == HBM_MAJOR_VERSION_CD &&
1206 dev->version.minor_version >= HBM_MINOR_VERSION_CD))
1207 dev->hbm_f_cd_supported = 1;
Tomas Winklerbae1cc72014-08-21 14:29:21 +03001208}
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001209
1210/**
Tomas Winkler2c9b48a2013-06-16 09:16:31 +03001211 * mei_hbm_version_is_supported - checks whether the driver can
1212 * support the hbm version of the device
1213 *
1214 * @dev: the device structure
Alexander Usyskina8605ea2014-09-29 16:31:49 +03001215 * Return: true if driver can support hbm version of the device
Tomas Winkler2c9b48a2013-06-16 09:16:31 +03001216 */
1217bool mei_hbm_version_is_supported(struct mei_device *dev)
1218{
1219 return (dev->version.major_version < HBM_MAJOR_VERSION) ||
1220 (dev->version.major_version == HBM_MAJOR_VERSION &&
1221 dev->version.minor_version <= HBM_MINOR_VERSION);
1222}
1223
1224/**
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001225 * mei_hbm_dispatch - bottom half read routine after ISR to
1226 * handle the read bus message cmd processing.
1227 *
1228 * @dev: the device structure
Alexander Usyskina8605ea2014-09-29 16:31:49 +03001229 * @hdr: header of bus message
Tomas Winkler544f9462014-01-08 20:19:21 +02001230 *
Alexander Usyskina8605ea2014-09-29 16:31:49 +03001231 * Return: 0 on success and < 0 on failure
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001232 */
Tomas Winkler544f9462014-01-08 20:19:21 +02001233int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001234{
1235 struct mei_bus_message *mei_msg;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001236 struct hbm_host_version_response *version_res;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001237 struct hbm_props_response *props_res;
1238 struct hbm_host_enum_response *enum_res;
Tomas Winklerc55bf542018-11-22 13:11:37 +02001239 struct hbm_dma_setup_response *dma_setup_res;
Tomas Winkler70ef8352015-07-23 21:37:12 +03001240 struct hbm_add_client_request *add_cl_req;
Alexander Usyskinbeb4e1e2020-08-18 14:51:36 +03001241 struct hbm_capability_response *capability_res;
Tomas Winkler70ef8352015-07-23 21:37:12 +03001242 int ret;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001243
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001244 struct mei_hbm_cl_cmd *cl_cmd;
1245 struct hbm_client_connect_request *disconnect_req;
Tomas Winkler4034b812016-07-26 01:06:04 +03001246 struct hbm_flow_control *fctrl;
Alexander Usyskin369aea82021-02-06 16:43:24 +02001247 struct hbm_client_dma_response *client_dma_res;
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001248
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001249 /* read the message to our buffer */
1250 BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf));
1251 mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
1252 mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001253 cl_cmd = (struct mei_hbm_cl_cmd *)mei_msg;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001254
Tomas Winkler66ae4602014-01-08 20:19:22 +02001255 /* ignore spurious message and prevent reset nesting
1256 * hbm is put to idle during system reset
1257 */
1258 if (dev->hbm_state == MEI_HBM_IDLE) {
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001259 dev_dbg(dev->dev, "hbm: state is idle ignore spurious messages\n");
Tomas Winkler66ae4602014-01-08 20:19:22 +02001260 return 0;
1261 }
1262
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001263 switch (mei_msg->hbm_cmd) {
1264 case HOST_START_RES_CMD:
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001265 dev_dbg(dev->dev, "hbm: start: response message received.\n");
Tomas Winkler544f9462014-01-08 20:19:21 +02001266
1267 dev->init_clients_timer = 0;
1268
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001269 version_res = (struct hbm_host_version_response *)mei_msg;
Tomas Winkler2c9b48a2013-06-16 09:16:31 +03001270
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001271 dev_dbg(dev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n",
Tomas Winkler2c9b48a2013-06-16 09:16:31 +03001272 HBM_MAJOR_VERSION, HBM_MINOR_VERSION,
1273 version_res->me_max_version.major_version,
1274 version_res->me_max_version.minor_version);
1275
1276 if (version_res->host_version_supported) {
1277 dev->version.major_version = HBM_MAJOR_VERSION;
1278 dev->version.minor_version = HBM_MINOR_VERSION;
1279 } else {
1280 dev->version.major_version =
1281 version_res->me_max_version.major_version;
1282 dev->version.minor_version =
1283 version_res->me_max_version.minor_version;
1284 }
1285
1286 if (!mei_hbm_version_is_supported(dev)) {
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001287 dev_warn(dev->dev, "hbm: start: version mismatch - stopping the driver.\n");
Tomas Winklere46f1872012-12-25 19:06:10 +02001288
Tomas Winkler544f9462014-01-08 20:19:21 +02001289 dev->hbm_state = MEI_HBM_STOPPED;
Tomas Winkler6bb948c2014-02-12 21:41:52 +02001290 if (mei_hbm_stop_req(dev)) {
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001291 dev_err(dev->dev, "hbm: start: failed to send stop request\n");
Tomas Winkler544f9462014-01-08 20:19:21 +02001292 return -EIO;
1293 }
1294 break;
Tomas Winklere46f1872012-12-25 19:06:10 +02001295 }
1296
Tomas Winklerbae1cc72014-08-21 14:29:21 +03001297 mei_hbm_config_features(dev);
1298
Tomas Winkler544f9462014-01-08 20:19:21 +02001299 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
Alexander Usyskincb02efc2014-08-21 14:29:19 +03001300 dev->hbm_state != MEI_HBM_STARTING) {
Alexander Usyskin6d7163f2021-10-13 10:45:52 +03001301 if (dev->dev_state == MEI_DEV_POWER_DOWN ||
1302 dev->dev_state == MEI_DEV_POWERING_DOWN) {
Alexander Usyskinda3eb472021-01-29 14:07:49 +02001303 dev_dbg(dev->dev, "hbm: start: on shutdown, ignoring\n");
1304 return 0;
1305 }
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001306 dev_err(dev->dev, "hbm: start: state mismatch, [%d, %d]\n",
Tomas Winkler544f9462014-01-08 20:19:21 +02001307 dev->dev_state, dev->hbm_state);
1308 return -EPROTO;
1309 }
1310
Alexander Usyskine5cab1f2020-08-18 14:51:35 +03001311 if (dev->hbm_f_cap_supported) {
1312 if (mei_hbm_capabilities_req(dev))
1313 return -EIO;
1314 wake_up(&dev->wait_hbm_start);
1315 break;
1316 }
1317
Tomas Winklerc55bf542018-11-22 13:11:37 +02001318 if (dev->hbm_f_dr_supported) {
1319 if (mei_dmam_ring_alloc(dev))
1320 dev_info(dev->dev, "running w/o dma ring\n");
1321 if (mei_dma_ring_is_allocated(dev)) {
1322 if (mei_hbm_dma_setup_req(dev))
1323 return -EIO;
1324
1325 wake_up(&dev->wait_hbm_start);
1326 break;
1327 }
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001328 }
1329
Tomas Winklerc55bf542018-11-22 13:11:37 +02001330 dev->hbm_f_dr_supported = 0;
1331 mei_dmam_ring_free(dev);
1332
1333 if (mei_hbm_enum_clients_req(dev))
1334 return -EIO;
1335
Alexander Usyskincb02efc2014-08-21 14:29:19 +03001336 wake_up(&dev->wait_hbm_start);
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001337 break;
1338
Alexander Usyskine5cab1f2020-08-18 14:51:35 +03001339 case MEI_HBM_CAPABILITIES_RES_CMD:
1340 dev_dbg(dev->dev, "hbm: capabilities response: message received.\n");
1341
1342 dev->init_clients_timer = 0;
1343
Alexander Usyskinda3eb472021-01-29 14:07:49 +02001344 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1345 dev->hbm_state != MEI_HBM_CAP_SETUP) {
1346 if (dev->dev_state == MEI_DEV_POWER_DOWN) {
1347 dev_dbg(dev->dev, "hbm: capabilities response: on shutdown, ignoring\n");
1348 return 0;
1349 }
Alexander Usyskine5cab1f2020-08-18 14:51:35 +03001350 dev_err(dev->dev, "hbm: capabilities response: state mismatch, [%d, %d]\n",
1351 dev->dev_state, dev->hbm_state);
1352 return -EPROTO;
1353 }
1354
Alexander Usyskinbeb4e1e2020-08-18 14:51:36 +03001355 capability_res = (struct hbm_capability_response *)mei_msg;
1356 if (!(capability_res->capability_granted[0] & HBM_CAP_VT))
1357 dev->hbm_f_vt_supported = 0;
Alexander Usyskinb7a48042021-02-06 16:43:22 +02001358 if (!(capability_res->capability_granted[0] & HBM_CAP_CD))
1359 dev->hbm_f_cd_supported = 0;
Alexander Usyskinbeb4e1e2020-08-18 14:51:36 +03001360
Alexander Usyskine5cab1f2020-08-18 14:51:35 +03001361 if (dev->hbm_f_dr_supported) {
1362 if (mei_dmam_ring_alloc(dev))
1363 dev_info(dev->dev, "running w/o dma ring\n");
1364 if (mei_dma_ring_is_allocated(dev)) {
1365 if (mei_hbm_dma_setup_req(dev))
1366 return -EIO;
1367 break;
1368 }
1369 }
1370
1371 dev->hbm_f_dr_supported = 0;
1372 mei_dmam_ring_free(dev);
1373
1374 if (mei_hbm_enum_clients_req(dev))
1375 return -EIO;
1376 break;
1377
Tomas Winklerc55bf542018-11-22 13:11:37 +02001378 case MEI_HBM_DMA_SETUP_RES_CMD:
1379 dev_dbg(dev->dev, "hbm: dma setup response: message received.\n");
1380
1381 dev->init_clients_timer = 0;
1382
Alexander Usyskinda3eb472021-01-29 14:07:49 +02001383 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1384 dev->hbm_state != MEI_HBM_DR_SETUP) {
Alexander Usyskin6d7163f2021-10-13 10:45:52 +03001385 if (dev->dev_state == MEI_DEV_POWER_DOWN ||
1386 dev->dev_state == MEI_DEV_POWERING_DOWN) {
Alexander Usyskinda3eb472021-01-29 14:07:49 +02001387 dev_dbg(dev->dev, "hbm: dma setup response: on shutdown, ignoring\n");
1388 return 0;
1389 }
Tomas Winklerc55bf542018-11-22 13:11:37 +02001390 dev_err(dev->dev, "hbm: dma setup response: state mismatch, [%d, %d]\n",
1391 dev->dev_state, dev->hbm_state);
1392 return -EPROTO;
1393 }
1394
1395 dma_setup_res = (struct hbm_dma_setup_response *)mei_msg;
1396
1397 if (dma_setup_res->status) {
Tomas Winkler82e59cb2019-01-13 14:24:46 +02001398 u8 status = dma_setup_res->status;
1399
1400 if (status == MEI_HBMS_NOT_ALLOWED) {
1401 dev_dbg(dev->dev, "hbm: dma setup not allowed\n");
1402 } else {
1403 dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
1404 status,
1405 mei_hbm_status_str(status));
1406 }
Tomas Winklerc55bf542018-11-22 13:11:37 +02001407 dev->hbm_f_dr_supported = 0;
1408 mei_dmam_ring_free(dev);
1409 }
1410
1411 if (mei_hbm_enum_clients_req(dev))
1412 return -EIO;
1413 break;
1414
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001415 case CLIENT_CONNECT_RES_CMD:
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001416 dev_dbg(dev->dev, "hbm: client connect response: message received.\n");
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001417 mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_CONNECT);
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001418 break;
1419
1420 case CLIENT_DISCONNECT_RES_CMD:
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001421 dev_dbg(dev->dev, "hbm: client disconnect response: message received.\n");
Tomas Winkler12f45ed2014-08-21 14:29:18 +03001422 mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_DISCONNECT);
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001423 break;
1424
1425 case MEI_FLOW_CONTROL_CMD:
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001426 dev_dbg(dev->dev, "hbm: client flow control response: message received.\n");
Tomas Winkler544f9462014-01-08 20:19:21 +02001427
Tomas Winkler4034b812016-07-26 01:06:04 +03001428 fctrl = (struct hbm_flow_control *)mei_msg;
1429 mei_hbm_cl_tx_flow_ctrl_creds_res(dev, fctrl);
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001430 break;
1431
Tomas Winkler4fcbc992014-03-18 22:51:55 +02001432 case MEI_PG_ISOLATION_ENTRY_RES_CMD:
Alexander Usyskin63f75232015-08-02 22:20:53 +03001433 dev_dbg(dev->dev, "hbm: power gate isolation entry response received\n");
1434 ret = mei_hbm_pg_enter_res(dev);
1435 if (ret)
1436 return ret;
Tomas Winkler4fcbc992014-03-18 22:51:55 +02001437 break;
1438
1439 case MEI_PG_ISOLATION_EXIT_REQ_CMD:
Alexander Usyskin63f75232015-08-02 22:20:53 +03001440 dev_dbg(dev->dev, "hbm: power gate isolation exit request received\n");
1441 ret = mei_hbm_pg_exit_res(dev);
1442 if (ret)
1443 return ret;
Tomas Winkler4fcbc992014-03-18 22:51:55 +02001444 break;
1445
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001446 case HOST_CLIENT_PROPERTIES_RES_CMD:
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001447 dev_dbg(dev->dev, "hbm: properties response: message received.\n");
Tomas Winkler544f9462014-01-08 20:19:21 +02001448
1449 dev->init_clients_timer = 0;
1450
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001451 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +03001452 dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
Alexander Usyskin6d7163f2021-10-13 10:45:52 +03001453 if (dev->dev_state == MEI_DEV_POWER_DOWN ||
1454 dev->dev_state == MEI_DEV_POWERING_DOWN) {
Alexander Usyskinda3eb472021-01-29 14:07:49 +02001455 dev_dbg(dev->dev, "hbm: properties response: on shutdown, ignoring\n");
1456 return 0;
1457 }
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001458 dev_err(dev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
Tomas Winkler544f9462014-01-08 20:19:21 +02001459 dev->dev_state, dev->hbm_state);
1460 return -EPROTO;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001461 }
1462
Tomas Winkler5ca2d382014-08-21 14:29:13 +03001463 props_res = (struct hbm_props_response *)mei_msg;
1464
Alexander Usyskin8d2d8932018-08-06 17:47:33 +03001465 if (props_res->status == MEI_HBMS_CLIENT_NOT_FOUND) {
1466 dev_dbg(dev->dev, "hbm: properties response: %d CLIENT_NOT_FOUND\n",
1467 props_res->me_addr);
1468 } else if (props_res->status) {
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001469 dev_err(dev->dev, "hbm: properties response: wrong status = %d %s\n",
Tomas Winkler89778d62014-08-21 14:29:16 +03001470 props_res->status,
1471 mei_hbm_status_str(props_res->status));
Tomas Winkler5ca2d382014-08-21 14:29:13 +03001472 return -EPROTO;
Alexander Usyskin8d2d8932018-08-06 17:47:33 +03001473 } else {
1474 mei_hbm_me_cl_add(dev, props_res);
Tomas Winkler5ca2d382014-08-21 14:29:13 +03001475 }
1476
Tomas Winkler8120e722012-12-25 19:06:11 +02001477 /* request property for the next client */
Alexander Usyskincc25aa92016-04-17 12:16:02 -04001478 if (mei_hbm_prop_req(dev, props_res->me_addr + 1))
Tomas Winkler544f9462014-01-08 20:19:21 +02001479 return -EIO;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001480
1481 break;
1482
1483 case HOST_ENUM_RES_CMD:
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001484 dev_dbg(dev->dev, "hbm: enumeration response: message received\n");
Tomas Winkler544f9462014-01-08 20:19:21 +02001485
1486 dev->init_clients_timer = 0;
1487
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001488 enum_res = (struct hbm_host_enum_response *) mei_msg;
Tomas Winkler23f5a322013-09-02 03:11:01 +03001489 BUILD_BUG_ON(sizeof(dev->me_clients_map)
1490 < sizeof(enum_res->valid_addresses));
1491 memcpy(dev->me_clients_map, enum_res->valid_addresses,
Tomas Winkler5ca2d382014-08-21 14:29:13 +03001492 sizeof(enum_res->valid_addresses));
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001493
Tomas Winkler544f9462014-01-08 20:19:21 +02001494 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
1495 dev->hbm_state != MEI_HBM_ENUM_CLIENTS) {
Alexander Usyskin6d7163f2021-10-13 10:45:52 +03001496 if (dev->dev_state == MEI_DEV_POWER_DOWN ||
1497 dev->dev_state == MEI_DEV_POWERING_DOWN) {
Alexander Usyskinda3eb472021-01-29 14:07:49 +02001498 dev_dbg(dev->dev, "hbm: enumeration response: on shutdown, ignoring\n");
1499 return 0;
1500 }
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001501 dev_err(dev->dev, "hbm: enumeration response: state mismatch, [%d, %d]\n",
Tomas Winkler544f9462014-01-08 20:19:21 +02001502 dev->dev_state, dev->hbm_state);
1503 return -EPROTO;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001504 }
Tomas Winkler544f9462014-01-08 20:19:21 +02001505
Tomas Winkler544f9462014-01-08 20:19:21 +02001506 dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
1507
1508 /* first property request */
Alexander Usyskincc25aa92016-04-17 12:16:02 -04001509 if (mei_hbm_prop_req(dev, 0))
Tomas Winkler544f9462014-01-08 20:19:21 +02001510 return -EIO;
1511
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001512 break;
1513
1514 case HOST_STOP_RES_CMD:
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001515 dev_dbg(dev->dev, "hbm: stop response: message received\n");
Tomas Winkler9b0d5ef2013-04-18 23:03:48 +03001516
Tomas Winkler544f9462014-01-08 20:19:21 +02001517 dev->init_clients_timer = 0;
1518
1519 if (dev->hbm_state != MEI_HBM_STOPPED) {
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001520 dev_err(dev->dev, "hbm: stop response: state mismatch, [%d, %d]\n",
Tomas Winkler544f9462014-01-08 20:19:21 +02001521 dev->dev_state, dev->hbm_state);
1522 return -EPROTO;
1523 }
1524
Alexander Usyskin3a77df62021-01-29 14:07:48 +02001525 mei_set_devstate(dev, MEI_DEV_POWER_DOWN);
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001526 dev_info(dev->dev, "hbm: stop response: resetting.\n");
Tomas Winkler544f9462014-01-08 20:19:21 +02001527 /* force the reset */
1528 return -EPROTO;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001529
1530 case CLIENT_DISCONNECT_REQ_CMD:
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001531 dev_dbg(dev->dev, "hbm: disconnect request: message received\n");
Tomas Winkler544f9462014-01-08 20:19:21 +02001532
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001533 disconnect_req = (struct hbm_client_connect_request *)mei_msg;
Tomas Winkler8120e722012-12-25 19:06:11 +02001534 mei_hbm_fw_disconnect_req(dev, disconnect_req);
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001535 break;
1536
1537 case ME_STOP_REQ_CMD:
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001538 dev_dbg(dev->dev, "hbm: stop request: message received\n");
Tomas Winkler544f9462014-01-08 20:19:21 +02001539 dev->hbm_state = MEI_HBM_STOPPED;
Tomas Winkler6bb948c2014-02-12 21:41:52 +02001540 if (mei_hbm_stop_req(dev)) {
Tomas Winkler2bf94cab2014-09-29 16:31:42 +03001541 dev_err(dev->dev, "hbm: stop request: failed to send stop request\n");
Tomas Winkler6bb948c2014-02-12 21:41:52 +02001542 return -EIO;
1543 }
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001544 break;
Tomas Winkler70ef8352015-07-23 21:37:12 +03001545
1546 case MEI_HBM_ADD_CLIENT_REQ_CMD:
1547 dev_dbg(dev->dev, "hbm: add client request received\n");
1548 /*
1549 * after the host receives the enum_resp
1550 * message clients may be added or removed
1551 */
Alexander Usyskin84dfe032015-09-21 11:45:32 +03001552 if (dev->hbm_state <= MEI_HBM_ENUM_CLIENTS ||
Tomas Winkler70ef8352015-07-23 21:37:12 +03001553 dev->hbm_state >= MEI_HBM_STOPPED) {
1554 dev_err(dev->dev, "hbm: add client: state mismatch, [%d, %d]\n",
1555 dev->dev_state, dev->hbm_state);
1556 return -EPROTO;
1557 }
1558 add_cl_req = (struct hbm_add_client_request *)mei_msg;
1559 ret = mei_hbm_fw_add_cl_req(dev, add_cl_req);
1560 if (ret) {
1561 dev_err(dev->dev, "hbm: add client: failed to send response %d\n",
1562 ret);
1563 return -EIO;
1564 }
1565 dev_dbg(dev->dev, "hbm: add client request processed\n");
1566 break;
1567
Tomas Winkler965ae372015-07-26 09:54:16 +03001568 case MEI_HBM_NOTIFY_RES_CMD:
1569 dev_dbg(dev->dev, "hbm: notify response received\n");
1570 mei_hbm_cl_res(dev, cl_cmd, notify_res_to_fop(cl_cmd));
1571 break;
1572
1573 case MEI_HBM_NOTIFICATION_CMD:
1574 dev_dbg(dev->dev, "hbm: notification\n");
1575 mei_hbm_cl_notify(dev, cl_cmd);
1576 break;
1577
Alexander Usyskin369aea82021-02-06 16:43:24 +02001578 case MEI_HBM_CLIENT_DMA_MAP_RES_CMD:
1579 dev_dbg(dev->dev, "hbm: client dma map response: message received.\n");
1580 client_dma_res = (struct hbm_client_dma_response *)mei_msg;
1581 mei_hbm_cl_dma_map_res(dev, client_dma_res);
1582 break;
1583
1584 case MEI_HBM_CLIENT_DMA_UNMAP_RES_CMD:
1585 dev_dbg(dev->dev, "hbm: client dma unmap response: message received.\n");
1586 client_dma_res = (struct hbm_client_dma_response *)mei_msg;
1587 mei_hbm_cl_dma_unmap_res(dev, client_dma_res);
1588 break;
1589
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001590 default:
Tomas Winkler40a66972018-11-06 12:04:38 +02001591 WARN(1, "hbm: wrong command %d\n", mei_msg->hbm_cmd);
1592 return -EPROTO;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001593
1594 }
Tomas Winkler544f9462014-01-08 20:19:21 +02001595 return 0;
Tomas Winklerbb1b0132012-12-25 19:06:07 +02001596}
1597