1 /*
2  * ISHTP bus layer messages handling
3  *
4  * Copyright (c) 2003-2016, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  */
16 
17 #include <linux/export.h>
18 #include <linux/slab.h>
19 #include <linux/sched.h>
20 #include <linux/wait.h>
21 #include <linux/spinlock.h>
22 #include "ishtp-dev.h"
23 #include "hbm.h"
24 #include "client.h"
25 
26 /**
27  * ishtp_hbm_fw_cl_allocate() - Allocate FW clients
28  * @dev: ISHTP device instance
29  *
30  * Allocates storage for fw clients
31  */
32 static void ishtp_hbm_fw_cl_allocate(struct ishtp_device *dev)
33 {
34 	struct ishtp_fw_client *clients;
35 	int b;
36 
37 	/* count how many ISH clients we have */
38 	for_each_set_bit(b, dev->fw_clients_map, ISHTP_CLIENTS_MAX)
39 		dev->fw_clients_num++;
40 
41 	if (dev->fw_clients_num <= 0)
42 		return;
43 
44 	/* allocate storage for fw clients representation */
45 	clients = kcalloc(dev->fw_clients_num, sizeof(struct ishtp_fw_client),
46 			  GFP_KERNEL);
47 	if (!clients) {
48 		dev->dev_state = ISHTP_DEV_RESETTING;
49 		ish_hw_reset(dev);
50 		return;
51 	}
52 	dev->fw_clients = clients;
53 }
54 
55 /**
56  * ishtp_hbm_cl_hdr() - construct client hbm header
57  * @cl: client
58  * @hbm_cmd: host bus message command
59  * @buf: buffer for cl header
60  * @len: buffer length
61  *
62  * Initialize HBM buffer
63  */
64 static inline void ishtp_hbm_cl_hdr(struct ishtp_cl *cl, uint8_t hbm_cmd,
65 	void *buf, size_t len)
66 {
67 	struct ishtp_hbm_cl_cmd *cmd = buf;
68 
69 	memset(cmd, 0, len);
70 
71 	cmd->hbm_cmd = hbm_cmd;
72 	cmd->host_addr = cl->host_client_id;
73 	cmd->fw_addr = cl->fw_client_id;
74 }
75 
76 /**
77  * ishtp_hbm_cl_addr_equal() - Compare client address
78  * @cl: client
79  * @buf: Client command buffer
80  *
81  * Compare client address with the address in command buffer
82  *
83  * Return: True if they have the same address
84  */
85 static inline bool ishtp_hbm_cl_addr_equal(struct ishtp_cl *cl, void *buf)
86 {
87 	struct ishtp_hbm_cl_cmd *cmd = buf;
88 
89 	return cl->host_client_id == cmd->host_addr &&
90 		cl->fw_client_id == cmd->fw_addr;
91 }
92 
93 /**
94  * ishtp_hbm_start_wait() - Wait for HBM start message
95  * @dev: ISHTP device instance
96  *
97  * Wait for HBM start message from firmware
98  *
99  * Return: 0 if HBM start is/was received else timeout error
100  */
101 int ishtp_hbm_start_wait(struct ishtp_device *dev)
102 {
103 	int ret;
104 
105 	if (dev->hbm_state > ISHTP_HBM_START)
106 		return 0;
107 
108 	dev_dbg(dev->devc, "Going to wait for ishtp start. hbm_state=%08X\n",
109 		dev->hbm_state);
110 	ret = wait_event_interruptible_timeout(dev->wait_hbm_recvd_msg,
111 					dev->hbm_state >= ISHTP_HBM_STARTED,
112 					(ISHTP_INTEROP_TIMEOUT * HZ));
113 
114 	dev_dbg(dev->devc,
115 		"Woke up from waiting for ishtp start. hbm_state=%08X\n",
116 		dev->hbm_state);
117 
118 	if (ret <= 0 && (dev->hbm_state <= ISHTP_HBM_START)) {
119 		dev->hbm_state = ISHTP_HBM_IDLE;
120 		dev_err(dev->devc,
121 		"waiting for ishtp start failed. ret=%d hbm_state=%08X\n",
122 			ret, dev->hbm_state);
123 		return -ETIMEDOUT;
124 	}
125 	return 0;
126 }
127 
128 /**
129  * ishtp_hbm_start_req() - Send HBM start message
130  * @dev: ISHTP device instance
131  *
132  * Send HBM start message to firmware
133  *
134  * Return: 0 if success else error code
135  */
136 int ishtp_hbm_start_req(struct ishtp_device *dev)
137 {
138 	struct ishtp_msg_hdr hdr;
139 	struct hbm_host_version_request start_req = { 0 };
140 
141 	ishtp_hbm_hdr(&hdr, sizeof(start_req));
142 
143 	/* host start message */
144 	start_req.hbm_cmd = HOST_START_REQ_CMD;
145 	start_req.host_version.major_version = HBM_MAJOR_VERSION;
146 	start_req.host_version.minor_version = HBM_MINOR_VERSION;
147 
148 	/*
149 	 * (!) Response to HBM start may be so quick that this thread would get
150 	 * preempted BEFORE managing to set hbm_state = ISHTP_HBM_START.
151 	 * So set it at first, change back to ISHTP_HBM_IDLE upon failure
152 	 */
153 	dev->hbm_state = ISHTP_HBM_START;
154 	if (ishtp_write_message(dev, &hdr, &start_req)) {
155 		dev_err(dev->devc, "version message send failed\n");
156 		dev->dev_state = ISHTP_DEV_RESETTING;
157 		dev->hbm_state = ISHTP_HBM_IDLE;
158 		ish_hw_reset(dev);
159 		return -ENODEV;
160 	}
161 
162 	return 0;
163 }
164 
165 /**
166  * ishtp_hbm_enum_clients_req() - Send client enum req
167  * @dev: ISHTP device instance
168  *
169  * Send enumeration client request message
170  *
171  * Return: 0 if success else error code
172  */
173 void ishtp_hbm_enum_clients_req(struct ishtp_device *dev)
174 {
175 	struct ishtp_msg_hdr hdr;
176 	struct hbm_host_enum_request enum_req = { 0 };
177 
178 	/* enumerate clients */
179 	ishtp_hbm_hdr(&hdr, sizeof(enum_req));
180 	enum_req.hbm_cmd = HOST_ENUM_REQ_CMD;
181 
182 	if (ishtp_write_message(dev, &hdr, &enum_req)) {
183 		dev->dev_state = ISHTP_DEV_RESETTING;
184 		dev_err(dev->devc, "enumeration request send failed\n");
185 		ish_hw_reset(dev);
186 	}
187 	dev->hbm_state = ISHTP_HBM_ENUM_CLIENTS;
188 }
189 
190 /**
191  * ishtp_hbm_prop_req() - Request property
192  * @dev: ISHTP device instance
193  *
194  * Request property for a single client
195  *
196  * Return: 0 if success else error code
197  */
198 static int ishtp_hbm_prop_req(struct ishtp_device *dev)
199 {
200 	struct ishtp_msg_hdr hdr;
201 	struct hbm_props_request prop_req = { 0 };
202 	unsigned long next_client_index;
203 	uint8_t client_num;
204 
205 	client_num = dev->fw_client_presentation_num;
206 
207 	next_client_index = find_next_bit(dev->fw_clients_map,
208 		ISHTP_CLIENTS_MAX, dev->fw_client_index);
209 
210 	/* We got all client properties */
211 	if (next_client_index == ISHTP_CLIENTS_MAX) {
212 		dev->hbm_state = ISHTP_HBM_WORKING;
213 		dev->dev_state = ISHTP_DEV_ENABLED;
214 
215 		for (dev->fw_client_presentation_num = 1;
216 			dev->fw_client_presentation_num < client_num + 1;
217 				++dev->fw_client_presentation_num)
218 			/* Add new client device */
219 			ishtp_bus_new_client(dev);
220 		return 0;
221 	}
222 
223 	dev->fw_clients[client_num].client_id = next_client_index;
224 
225 	ishtp_hbm_hdr(&hdr, sizeof(prop_req));
226 
227 	prop_req.hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
228 	prop_req.address = next_client_index;
229 
230 	if (ishtp_write_message(dev, &hdr, &prop_req)) {
231 		dev->dev_state = ISHTP_DEV_RESETTING;
232 		dev_err(dev->devc, "properties request send failed\n");
233 		ish_hw_reset(dev);
234 		return -EIO;
235 	}
236 
237 	dev->fw_client_index = next_client_index;
238 
239 	return 0;
240 }
241 
242 /**
243  * ishtp_hbm_stop_req() - Send HBM stop
244  * @dev: ISHTP device instance
245  *
246  * Send stop request message
247  */
248 static void ishtp_hbm_stop_req(struct ishtp_device *dev)
249 {
250 	struct ishtp_msg_hdr hdr;
251 	struct hbm_host_stop_request stop_req = { 0 } ;
252 
253 	ishtp_hbm_hdr(&hdr, sizeof(stop_req));
254 
255 	stop_req.hbm_cmd = HOST_STOP_REQ_CMD;
256 	stop_req.reason = DRIVER_STOP_REQUEST;
257 
258 	ishtp_write_message(dev, &hdr, &stop_req);
259 }
260 
261 /**
262  * ishtp_hbm_cl_flow_control_req() - Send flow control request
263  * @dev: ISHTP device instance
264  * @cl: ISHTP client instance
265  *
266  * Send flow control request
267  *
268  * Return: 0 if success else error code
269  */
270 int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
271 				  struct ishtp_cl *cl)
272 {
273 	struct ishtp_msg_hdr hdr;
274 	struct hbm_flow_control flow_ctrl;
275 	const size_t len = sizeof(flow_ctrl);
276 	int	rv;
277 	unsigned long	flags;
278 
279 	spin_lock_irqsave(&cl->fc_spinlock, flags);
280 
281 	ishtp_hbm_hdr(&hdr, len);
282 	ishtp_hbm_cl_hdr(cl, ISHTP_FLOW_CONTROL_CMD, &flow_ctrl, len);
283 
284 	/*
285 	 * Sync possible race when RB recycle and packet receive paths
286 	 * both try to send an out FC
287 	 */
288 	if (cl->out_flow_ctrl_creds) {
289 		spin_unlock_irqrestore(&cl->fc_spinlock, flags);
290 		return	0;
291 	}
292 
293 	cl->recv_msg_num_frags = 0;
294 
295 	rv = ishtp_write_message(dev, &hdr, &flow_ctrl);
296 	if (!rv) {
297 		++cl->out_flow_ctrl_creds;
298 		++cl->out_flow_ctrl_cnt;
299 		cl->ts_out_fc = ktime_get();
300 		if (cl->ts_rx) {
301 			ktime_t ts_diff = ktime_sub(cl->ts_out_fc, cl->ts_rx);
302 			if (ktime_after(ts_diff, cl->ts_max_fc_delay))
303 				cl->ts_max_fc_delay = ts_diff;
304 		}
305 	} else {
306 		++cl->err_send_fc;
307 	}
308 
309 	spin_unlock_irqrestore(&cl->fc_spinlock, flags);
310 	return	rv;
311 }
312 
313 /**
314  * ishtp_hbm_cl_disconnect_req() - Send disconnect request
315  * @dev: ISHTP device instance
316  * @cl: ISHTP client instance
317  *
318  * Send disconnect message to fw
319  *
320  * Return: 0 if success else error code
321  */
322 int ishtp_hbm_cl_disconnect_req(struct ishtp_device *dev, struct ishtp_cl *cl)
323 {
324 	struct ishtp_msg_hdr hdr;
325 	struct hbm_client_connect_request disconn_req;
326 	const size_t len = sizeof(disconn_req);
327 
328 	ishtp_hbm_hdr(&hdr, len);
329 	ishtp_hbm_cl_hdr(cl, CLIENT_DISCONNECT_REQ_CMD, &disconn_req, len);
330 
331 	return ishtp_write_message(dev, &hdr, &disconn_req);
332 }
333 
334 /**
335  * ishtp_hbm_cl_disconnect_res() - Get disconnect response
336  * @dev: ISHTP device instance
337  * @rs: Response message
338  *
339  * Received disconnect response from fw
340  */
341 static void ishtp_hbm_cl_disconnect_res(struct ishtp_device *dev,
342 	struct hbm_client_connect_response *rs)
343 {
344 	struct ishtp_cl *cl = NULL;
345 	unsigned long	flags;
346 
347 	spin_lock_irqsave(&dev->cl_list_lock, flags);
348 	list_for_each_entry(cl, &dev->cl_list, link) {
349 		if (!rs->status && ishtp_hbm_cl_addr_equal(cl, rs)) {
350 			cl->state = ISHTP_CL_DISCONNECTED;
351 			wake_up_interruptible(&cl->wait_ctrl_res);
352 			break;
353 		}
354 	}
355 	spin_unlock_irqrestore(&dev->cl_list_lock, flags);
356 }
357 
358 /**
359  * ishtp_hbm_cl_connect_req() - Send connect request
360  * @dev: ISHTP device instance
361  * @cl: client device instance
362  *
363  * Send connection request to specific fw client
364  *
365  * Return: 0 if success else error code
366  */
367 int ishtp_hbm_cl_connect_req(struct ishtp_device *dev, struct ishtp_cl *cl)
368 {
369 	struct ishtp_msg_hdr hdr;
370 	struct hbm_client_connect_request conn_req;
371 	const size_t len = sizeof(conn_req);
372 
373 	ishtp_hbm_hdr(&hdr, len);
374 	ishtp_hbm_cl_hdr(cl, CLIENT_CONNECT_REQ_CMD, &conn_req, len);
375 
376 	return ishtp_write_message(dev, &hdr, &conn_req);
377 }
378 
379 /**
380  * ishtp_hbm_cl_connect_res() - Get connect response
381  * @dev: ISHTP device instance
382  * @rs: Response message
383  *
384  * Received connect response from fw
385  */
386 static void ishtp_hbm_cl_connect_res(struct ishtp_device *dev,
387 	struct hbm_client_connect_response *rs)
388 {
389 	struct ishtp_cl *cl = NULL;
390 	unsigned long	flags;
391 
392 	spin_lock_irqsave(&dev->cl_list_lock, flags);
393 	list_for_each_entry(cl, &dev->cl_list, link) {
394 		if (ishtp_hbm_cl_addr_equal(cl, rs)) {
395 			if (!rs->status) {
396 				cl->state = ISHTP_CL_CONNECTED;
397 				cl->status = 0;
398 			} else {
399 				cl->state = ISHTP_CL_DISCONNECTED;
400 				cl->status = -ENODEV;
401 			}
402 			wake_up_interruptible(&cl->wait_ctrl_res);
403 			break;
404 		}
405 	}
406 	spin_unlock_irqrestore(&dev->cl_list_lock, flags);
407 }
408 
409 /**
410  * ishtp_client_disconnect_request() - Receive disconnect request
411  * @dev: ISHTP device instance
412  * @disconnect_req: disconnect request structure
413  *
414  * Disconnect request bus message from the fw. Send diconnect response.
415  */
416 static void ishtp_hbm_fw_disconnect_req(struct ishtp_device *dev,
417 	struct hbm_client_connect_request *disconnect_req)
418 {
419 	struct ishtp_cl *cl;
420 	const size_t len = sizeof(struct hbm_client_connect_response);
421 	unsigned long	flags;
422 	struct ishtp_msg_hdr hdr;
423 	unsigned char data[4];	/* All HBM messages are 4 bytes */
424 
425 	spin_lock_irqsave(&dev->cl_list_lock, flags);
426 	list_for_each_entry(cl, &dev->cl_list, link) {
427 		if (ishtp_hbm_cl_addr_equal(cl, disconnect_req)) {
428 			cl->state = ISHTP_CL_DISCONNECTED;
429 
430 			/* send disconnect response */
431 			ishtp_hbm_hdr(&hdr, len);
432 			ishtp_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD, data,
433 				len);
434 			ishtp_write_message(dev, &hdr, data);
435 			break;
436 		}
437 	}
438 	spin_unlock_irqrestore(&dev->cl_list_lock, flags);
439 }
440 
441 /**
442  * ishtp_hbm_dma_xfer_ack(() - Receive transfer ACK
443  * @dev: ISHTP device instance
444  * @dma_xfer: HBM transfer message
445  *
446  * Receive ack for ISHTP-over-DMA client message
447  */
448 static void ishtp_hbm_dma_xfer_ack(struct ishtp_device *dev,
449 				   struct dma_xfer_hbm *dma_xfer)
450 {
451 	void	*msg;
452 	uint64_t	offs;
453 	struct ishtp_msg_hdr	*ishtp_hdr =
454 		(struct ishtp_msg_hdr *)&dev->ishtp_msg_hdr;
455 	unsigned int	msg_offs;
456 	struct ishtp_cl *cl;
457 
458 	for (msg_offs = 0; msg_offs < ishtp_hdr->length;
459 		msg_offs += sizeof(struct dma_xfer_hbm)) {
460 		offs = dma_xfer->msg_addr - dev->ishtp_host_dma_tx_buf_phys;
461 		if (offs > dev->ishtp_host_dma_tx_buf_size) {
462 			dev_err(dev->devc, "Bad DMA Tx ack message address\n");
463 			return;
464 		}
465 		if (dma_xfer->msg_length >
466 				dev->ishtp_host_dma_tx_buf_size - offs) {
467 			dev_err(dev->devc, "Bad DMA Tx ack message size\n");
468 			return;
469 		}
470 
471 		/* logical address of the acked mem */
472 		msg = (unsigned char *)dev->ishtp_host_dma_tx_buf + offs;
473 		ishtp_cl_release_dma_acked_mem(dev, msg, dma_xfer->msg_length);
474 
475 		list_for_each_entry(cl, &dev->cl_list, link) {
476 			if (cl->fw_client_id == dma_xfer->fw_client_id &&
477 			    cl->host_client_id == dma_xfer->host_client_id)
478 				/*
479 				 * in case that a single ack may be sent
480 				 * over several dma transfers, and the last msg
481 				 * addr was inside the acked memory, but not in
482 				 * its start
483 				 */
484 				if (cl->last_dma_addr >=
485 							(unsigned char *)msg &&
486 						cl->last_dma_addr <
487 						(unsigned char *)msg +
488 						dma_xfer->msg_length) {
489 					cl->last_dma_acked = 1;
490 
491 					if (!list_empty(&cl->tx_list.list) &&
492 						cl->ishtp_flow_ctrl_creds) {
493 						/*
494 						 * start sending the first msg
495 						 */
496 						ishtp_cl_send_msg(dev, cl);
497 					}
498 				}
499 		}
500 		++dma_xfer;
501 	}
502 }
503 
504 /**
505  * ishtp_hbm_dma_xfer() - Receive DMA transfer message
506  * @dev: ISHTP device instance
507  * @dma_xfer: HBM transfer message
508  *
509  * Receive ISHTP-over-DMA client message
510  */
511 static void ishtp_hbm_dma_xfer(struct ishtp_device *dev,
512 			       struct dma_xfer_hbm *dma_xfer)
513 {
514 	void	*msg;
515 	uint64_t	offs;
516 	struct ishtp_msg_hdr	hdr;
517 	struct ishtp_msg_hdr	*ishtp_hdr =
518 		(struct ishtp_msg_hdr *) &dev->ishtp_msg_hdr;
519 	struct dma_xfer_hbm	*prm = dma_xfer;
520 	unsigned int	msg_offs;
521 
522 	for (msg_offs = 0; msg_offs < ishtp_hdr->length;
523 		msg_offs += sizeof(struct dma_xfer_hbm)) {
524 
525 		offs = dma_xfer->msg_addr - dev->ishtp_host_dma_rx_buf_phys;
526 		if (offs > dev->ishtp_host_dma_rx_buf_size) {
527 			dev_err(dev->devc, "Bad DMA Rx message address\n");
528 			return;
529 		}
530 		if (dma_xfer->msg_length >
531 				dev->ishtp_host_dma_rx_buf_size - offs) {
532 			dev_err(dev->devc, "Bad DMA Rx message size\n");
533 			return;
534 		}
535 		msg = dev->ishtp_host_dma_rx_buf + offs;
536 		recv_ishtp_cl_msg_dma(dev, msg, dma_xfer);
537 		dma_xfer->hbm = DMA_XFER_ACK;	/* Prepare for response */
538 		++dma_xfer;
539 	}
540 
541 	/* Send DMA_XFER_ACK [...] */
542 	ishtp_hbm_hdr(&hdr, ishtp_hdr->length);
543 	ishtp_write_message(dev, &hdr, (unsigned char *)prm);
544 }
545 
546 /**
547  * ishtp_hbm_dispatch() - HBM dispatch function
548  * @dev: ISHTP device instance
549  * @hdr: bus message
550  *
551  * Bottom half read routine after ISR to handle the read bus message cmd
552  * processing
553  */
554 void ishtp_hbm_dispatch(struct ishtp_device *dev,
555 			struct ishtp_bus_message *hdr)
556 {
557 	struct ishtp_bus_message *ishtp_msg;
558 	struct ishtp_fw_client *fw_client;
559 	struct hbm_host_version_response *version_res;
560 	struct hbm_client_connect_response *connect_res;
561 	struct hbm_client_connect_response *disconnect_res;
562 	struct hbm_client_connect_request *disconnect_req;
563 	struct hbm_props_response *props_res;
564 	struct hbm_host_enum_response *enum_res;
565 	struct ishtp_msg_hdr ishtp_hdr;
566 	struct dma_alloc_notify	dma_alloc_notify;
567 	struct dma_xfer_hbm	*dma_xfer;
568 
569 	ishtp_msg = hdr;
570 
571 	switch (ishtp_msg->hbm_cmd) {
572 	case HOST_START_RES_CMD:
573 		version_res = (struct hbm_host_version_response *)ishtp_msg;
574 		if (!version_res->host_version_supported) {
575 			dev->version = version_res->fw_max_version;
576 
577 			dev->hbm_state = ISHTP_HBM_STOPPED;
578 			ishtp_hbm_stop_req(dev);
579 			return;
580 		}
581 
582 		dev->version.major_version = HBM_MAJOR_VERSION;
583 		dev->version.minor_version = HBM_MINOR_VERSION;
584 		if (dev->dev_state == ISHTP_DEV_INIT_CLIENTS &&
585 				dev->hbm_state == ISHTP_HBM_START) {
586 			dev->hbm_state = ISHTP_HBM_STARTED;
587 			ishtp_hbm_enum_clients_req(dev);
588 		} else {
589 			dev_err(dev->devc,
590 				"reset: wrong host start response\n");
591 			/* BUG: why do we arrive here? */
592 			ish_hw_reset(dev);
593 			return;
594 		}
595 
596 		wake_up_interruptible(&dev->wait_hbm_recvd_msg);
597 		break;
598 
599 	case CLIENT_CONNECT_RES_CMD:
600 		connect_res = (struct hbm_client_connect_response *)ishtp_msg;
601 		ishtp_hbm_cl_connect_res(dev, connect_res);
602 		break;
603 
604 	case CLIENT_DISCONNECT_RES_CMD:
605 		disconnect_res =
606 			(struct hbm_client_connect_response *)ishtp_msg;
607 		ishtp_hbm_cl_disconnect_res(dev, disconnect_res);
608 		break;
609 
610 	case HOST_CLIENT_PROPERTIES_RES_CMD:
611 		props_res = (struct hbm_props_response *)ishtp_msg;
612 		fw_client = &dev->fw_clients[dev->fw_client_presentation_num];
613 
614 		if (props_res->status || !dev->fw_clients) {
615 			dev_err(dev->devc,
616 			"reset: properties response hbm wrong status\n");
617 			ish_hw_reset(dev);
618 			return;
619 		}
620 
621 		if (fw_client->client_id != props_res->address) {
622 			dev_err(dev->devc,
623 				"reset: host properties response address mismatch [%02X %02X]\n",
624 				fw_client->client_id, props_res->address);
625 			ish_hw_reset(dev);
626 			return;
627 		}
628 
629 		if (dev->dev_state != ISHTP_DEV_INIT_CLIENTS ||
630 			dev->hbm_state != ISHTP_HBM_CLIENT_PROPERTIES) {
631 			dev_err(dev->devc,
632 				"reset: unexpected properties response\n");
633 			ish_hw_reset(dev);
634 			return;
635 		}
636 
637 		fw_client->props = props_res->client_properties;
638 		dev->fw_client_index++;
639 		dev->fw_client_presentation_num++;
640 
641 		/* request property for the next client */
642 		ishtp_hbm_prop_req(dev);
643 
644 		if (dev->dev_state != ISHTP_DEV_ENABLED)
645 			break;
646 
647 		if (!ishtp_use_dma_transfer())
648 			break;
649 
650 		dev_dbg(dev->devc, "Requesting to use DMA\n");
651 		ishtp_cl_alloc_dma_buf(dev);
652 		if (dev->ishtp_host_dma_rx_buf) {
653 			const size_t len = sizeof(dma_alloc_notify);
654 
655 			memset(&dma_alloc_notify, 0, sizeof(dma_alloc_notify));
656 			dma_alloc_notify.hbm = DMA_BUFFER_ALLOC_NOTIFY;
657 			dma_alloc_notify.buf_size =
658 					dev->ishtp_host_dma_rx_buf_size;
659 			dma_alloc_notify.buf_address =
660 					dev->ishtp_host_dma_rx_buf_phys;
661 			ishtp_hbm_hdr(&ishtp_hdr, len);
662 			ishtp_write_message(dev, &ishtp_hdr,
663 				(unsigned char *)&dma_alloc_notify);
664 		}
665 
666 		break;
667 
668 	case HOST_ENUM_RES_CMD:
669 		enum_res = (struct hbm_host_enum_response *) ishtp_msg;
670 		memcpy(dev->fw_clients_map, enum_res->valid_addresses, 32);
671 		if (dev->dev_state == ISHTP_DEV_INIT_CLIENTS &&
672 			dev->hbm_state == ISHTP_HBM_ENUM_CLIENTS) {
673 			dev->fw_client_presentation_num = 0;
674 			dev->fw_client_index = 0;
675 
676 			ishtp_hbm_fw_cl_allocate(dev);
677 			dev->hbm_state = ISHTP_HBM_CLIENT_PROPERTIES;
678 
679 			/* first property request */
680 			ishtp_hbm_prop_req(dev);
681 		} else {
682 			dev_err(dev->devc,
683 			      "reset: unexpected enumeration response hbm\n");
684 			ish_hw_reset(dev);
685 			return;
686 		}
687 		break;
688 
689 	case HOST_STOP_RES_CMD:
690 		if (dev->hbm_state != ISHTP_HBM_STOPPED)
691 			dev_err(dev->devc, "unexpected stop response\n");
692 
693 		dev->dev_state = ISHTP_DEV_DISABLED;
694 		dev_info(dev->devc, "reset: FW stop response\n");
695 		ish_hw_reset(dev);
696 		break;
697 
698 	case CLIENT_DISCONNECT_REQ_CMD:
699 		/* search for client */
700 		disconnect_req =
701 			(struct hbm_client_connect_request *)ishtp_msg;
702 		ishtp_hbm_fw_disconnect_req(dev, disconnect_req);
703 		break;
704 
705 	case FW_STOP_REQ_CMD:
706 		dev->hbm_state = ISHTP_HBM_STOPPED;
707 		break;
708 
709 	case DMA_BUFFER_ALLOC_RESPONSE:
710 		dev->ishtp_host_dma_enabled = 1;
711 		break;
712 
713 	case DMA_XFER:
714 		dma_xfer = (struct dma_xfer_hbm *)ishtp_msg;
715 		if (!dev->ishtp_host_dma_enabled) {
716 			dev_err(dev->devc,
717 				"DMA XFER requested but DMA is not enabled\n");
718 			break;
719 		}
720 		ishtp_hbm_dma_xfer(dev, dma_xfer);
721 		break;
722 
723 	case DMA_XFER_ACK:
724 		dma_xfer = (struct dma_xfer_hbm *)ishtp_msg;
725 		if (!dev->ishtp_host_dma_enabled ||
726 		    !dev->ishtp_host_dma_tx_buf) {
727 			dev_err(dev->devc,
728 				"DMA XFER acked but DMA Tx is not enabled\n");
729 			break;
730 		}
731 		ishtp_hbm_dma_xfer_ack(dev, dma_xfer);
732 		break;
733 
734 	default:
735 		dev_err(dev->devc, "unknown HBM: %u\n",
736 			(unsigned int)ishtp_msg->hbm_cmd);
737 
738 		break;
739 	}
740 }
741 
742 /**
743  * bh_hbm_work_fn() - HBM work function
744  * @work: work struct
745  *
746  * Bottom half processing work function (instead of thread handler)
747  * for processing hbm messages
748  */
749 void	bh_hbm_work_fn(struct work_struct *work)
750 {
751 	unsigned long	flags;
752 	struct ishtp_device	*dev;
753 	unsigned char	hbm[IPC_PAYLOAD_SIZE];
754 
755 	dev = container_of(work, struct ishtp_device, bh_hbm_work);
756 	spin_lock_irqsave(&dev->rd_msg_spinlock, flags);
757 	if (dev->rd_msg_fifo_head != dev->rd_msg_fifo_tail) {
758 		memcpy(hbm, dev->rd_msg_fifo + dev->rd_msg_fifo_head,
759 			IPC_PAYLOAD_SIZE);
760 		dev->rd_msg_fifo_head =
761 			(dev->rd_msg_fifo_head + IPC_PAYLOAD_SIZE) %
762 			(RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE);
763 		spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
764 		ishtp_hbm_dispatch(dev, (struct ishtp_bus_message *)hbm);
765 	} else {
766 		spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
767 	}
768 }
769 
770 /**
771  * recv_hbm() - Receive HBM message
772  * @dev: ISHTP device instance
773  * @ishtp_hdr: received bus message
774  *
775  * Receive and process ISHTP bus messages in ISR context. This will schedule
776  * work function to process message
777  */
778 void	recv_hbm(struct ishtp_device *dev, struct ishtp_msg_hdr *ishtp_hdr)
779 {
780 	uint8_t	rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
781 	struct ishtp_bus_message	*ishtp_msg =
782 		(struct ishtp_bus_message *)rd_msg_buf;
783 	unsigned long	flags;
784 
785 	dev->ops->ishtp_read(dev, rd_msg_buf, ishtp_hdr->length);
786 
787 	/* Flow control - handle in place */
788 	if (ishtp_msg->hbm_cmd == ISHTP_FLOW_CONTROL_CMD) {
789 		struct hbm_flow_control *flow_control =
790 			(struct hbm_flow_control *)ishtp_msg;
791 		struct ishtp_cl *cl = NULL;
792 		unsigned long	flags, tx_flags;
793 
794 		spin_lock_irqsave(&dev->cl_list_lock, flags);
795 		list_for_each_entry(cl, &dev->cl_list, link) {
796 			if (cl->host_client_id == flow_control->host_addr &&
797 					cl->fw_client_id ==
798 					flow_control->fw_addr) {
799 				/*
800 				 * NOTE: It's valid only for counting
801 				 * flow-control implementation to receive a
802 				 * FC in the middle of sending. Meanwhile not
803 				 * supported
804 				 */
805 				if (cl->ishtp_flow_ctrl_creds)
806 					dev_err(dev->devc,
807 					 "recv extra FC from FW client %u (host client %u) (FC count was %d)\n",
808 					 (unsigned int)cl->fw_client_id,
809 					 (unsigned int)cl->host_client_id,
810 					 cl->ishtp_flow_ctrl_creds);
811 				else {
812 					++cl->ishtp_flow_ctrl_creds;
813 					++cl->ishtp_flow_ctrl_cnt;
814 					cl->last_ipc_acked = 1;
815 					spin_lock_irqsave(
816 							&cl->tx_list_spinlock,
817 							tx_flags);
818 					if (!list_empty(&cl->tx_list.list)) {
819 						/*
820 						 * start sending the first msg
821 						 *	= the callback function
822 						 */
823 						spin_unlock_irqrestore(
824 							&cl->tx_list_spinlock,
825 							tx_flags);
826 						ishtp_cl_send_msg(dev, cl);
827 					} else {
828 						spin_unlock_irqrestore(
829 							&cl->tx_list_spinlock,
830 							tx_flags);
831 					}
832 				}
833 				break;
834 			}
835 		}
836 		spin_unlock_irqrestore(&dev->cl_list_lock, flags);
837 		goto	eoi;
838 	}
839 
840 	/*
841 	 * Some messages that are safe for ISR processing and important
842 	 * to be done "quickly" and in-order, go here
843 	 */
844 	if (ishtp_msg->hbm_cmd == CLIENT_CONNECT_RES_CMD ||
845 			ishtp_msg->hbm_cmd == CLIENT_DISCONNECT_RES_CMD ||
846 			ishtp_msg->hbm_cmd == CLIENT_DISCONNECT_REQ_CMD ||
847 			ishtp_msg->hbm_cmd == DMA_XFER) {
848 		ishtp_hbm_dispatch(dev, ishtp_msg);
849 		goto	eoi;
850 	}
851 
852 	/*
853 	 * All other HBMs go here.
854 	 * We schedule HBMs for processing serially by using system wq,
855 	 * possibly there will be multiple HBMs scheduled at the same time.
856 	 */
857 	spin_lock_irqsave(&dev->rd_msg_spinlock, flags);
858 	if ((dev->rd_msg_fifo_tail + IPC_PAYLOAD_SIZE) %
859 			(RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE) ==
860 			dev->rd_msg_fifo_head) {
861 		spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
862 		dev_err(dev->devc, "BH buffer overflow, dropping HBM %u\n",
863 			(unsigned int)ishtp_msg->hbm_cmd);
864 		goto	eoi;
865 	}
866 	memcpy(dev->rd_msg_fifo + dev->rd_msg_fifo_tail, ishtp_msg,
867 		ishtp_hdr->length);
868 	dev->rd_msg_fifo_tail = (dev->rd_msg_fifo_tail + IPC_PAYLOAD_SIZE) %
869 		(RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE);
870 	spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
871 	schedule_work(&dev->bh_hbm_work);
872 eoi:
873 	return;
874 }
875 
876 /**
877  * recv_fixed_cl_msg() - Receive fixed client message
878  * @dev: ISHTP device instance
879  * @ishtp_hdr: received bus message
880  *
881  * Receive and process ISHTP fixed client messages (address == 0)
882  * in ISR context
883  */
884 void recv_fixed_cl_msg(struct ishtp_device *dev,
885 	struct ishtp_msg_hdr *ishtp_hdr)
886 {
887 	uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
888 
889 	dev->print_log(dev,
890 		"%s() got fixed client msg from client #%d\n",
891 		__func__, ishtp_hdr->fw_addr);
892 	dev->ops->ishtp_read(dev, rd_msg_buf, ishtp_hdr->length);
893 	if (ishtp_hdr->fw_addr == ISHTP_SYSTEM_STATE_CLIENT_ADDR) {
894 		struct ish_system_states_header *msg_hdr =
895 			(struct ish_system_states_header *)rd_msg_buf;
896 		if (msg_hdr->cmd == SYSTEM_STATE_SUBSCRIBE)
897 			ishtp_send_resume(dev);
898 		/* if FW request arrived here, the system is not suspended */
899 		else
900 			dev_err(dev->devc, "unknown fixed client msg [%02X]\n",
901 				msg_hdr->cmd);
902 	}
903 }
904 
905 /**
906  * fix_cl_hdr() - Initialize fixed client header
907  * @hdr: message header
908  * @length: length of message
909  * @cl_addr: Client address
910  *
911  * Initialize message header for fixed client
912  */
913 static inline void fix_cl_hdr(struct ishtp_msg_hdr *hdr, size_t length,
914 	uint8_t cl_addr)
915 {
916 	hdr->host_addr = 0;
917 	hdr->fw_addr = cl_addr;
918 	hdr->length = length;
919 	hdr->msg_complete = 1;
920 	hdr->reserved = 0;
921 }
922 
923 /*** Suspend and resume notification ***/
924 
925 static uint32_t current_state;
926 static uint32_t supported_states = 0 | SUSPEND_STATE_BIT;
927 
928 /**
929  * ishtp_send_suspend() - Send suspend message to FW
930  * @dev: ISHTP device instance
931  *
932  * Send suspend message to FW. This is useful for system freeze (non S3) case
933  */
934 void ishtp_send_suspend(struct ishtp_device *dev)
935 {
936 	struct ishtp_msg_hdr	ishtp_hdr;
937 	struct ish_system_states_status state_status_msg;
938 	const size_t len = sizeof(struct ish_system_states_status);
939 
940 	fix_cl_hdr(&ishtp_hdr, len, ISHTP_SYSTEM_STATE_CLIENT_ADDR);
941 
942 	memset(&state_status_msg, 0, len);
943 	state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS;
944 	state_status_msg.supported_states = supported_states;
945 	current_state |= SUSPEND_STATE_BIT;
946 	dev->print_log(dev, "%s() sends SUSPEND notification\n", __func__);
947 	state_status_msg.states_status = current_state;
948 
949 	ishtp_write_message(dev, &ishtp_hdr,
950 		(unsigned char *)&state_status_msg);
951 }
952 EXPORT_SYMBOL(ishtp_send_suspend);
953 
954 /**
955  * ishtp_send_resume() - Send resume message to FW
956  * @dev: ISHTP device instance
957  *
958  * Send resume message to FW. This is useful for system freeze (non S3) case
959  */
960 void ishtp_send_resume(struct ishtp_device *dev)
961 {
962 	struct ishtp_msg_hdr	ishtp_hdr;
963 	struct ish_system_states_status state_status_msg;
964 	const size_t len = sizeof(struct ish_system_states_status);
965 
966 	fix_cl_hdr(&ishtp_hdr, len, ISHTP_SYSTEM_STATE_CLIENT_ADDR);
967 
968 	memset(&state_status_msg, 0, len);
969 	state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS;
970 	state_status_msg.supported_states = supported_states;
971 	current_state &= ~SUSPEND_STATE_BIT;
972 	dev->print_log(dev, "%s() sends RESUME notification\n", __func__);
973 	state_status_msg.states_status = current_state;
974 
975 	ishtp_write_message(dev, &ishtp_hdr,
976 		(unsigned char *)&state_status_msg);
977 }
978 EXPORT_SYMBOL(ishtp_send_resume);
979 
980 /**
981  * ishtp_query_subscribers() - Send query subscribers message
982  * @dev: ISHTP device instance
983  *
984  * Send message to query subscribers
985  */
986 void ishtp_query_subscribers(struct ishtp_device *dev)
987 {
988 	struct ishtp_msg_hdr	ishtp_hdr;
989 	struct ish_system_states_query_subscribers query_subscribers_msg;
990 	const size_t len = sizeof(struct ish_system_states_query_subscribers);
991 
992 	fix_cl_hdr(&ishtp_hdr, len, ISHTP_SYSTEM_STATE_CLIENT_ADDR);
993 
994 	memset(&query_subscribers_msg, 0, len);
995 	query_subscribers_msg.hdr.cmd = SYSTEM_STATE_QUERY_SUBSCRIBERS;
996 
997 	ishtp_write_message(dev, &ishtp_hdr,
998 		(unsigned char *)&query_subscribers_msg);
999 }
1000