1+ // SPDX-License-Identifier: GPL-2.0
2+ /**
3+ * Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
4+ **/
5+
6+ #include "fw_operation.h"
7+
8+ #include <linux/errno.h>
9+ #include <linux/types.h>
10+ #include <linux/kernel.h>
11+ #include <linux/bug.h>
12+
13+ typedef struct {
14+ u32 host_offset ;
15+ u32 chip_offset ;
16+ } FW_DEBUG_BUFFER_HEADER_t ;
17+
18+ #define DEBUG_BUFFER_DATA_SIZE (DEBUG_BUFFER_TOTAL_SIZE - sizeof(FW_DEBUG_BUFFER_HEADER_t))
19+
20+ int hailo_read_firmware_notification (struct hailo_resource * resource , struct hailo_d2h_notification * notification )
21+ {
22+ hailo_d2h_buffer_details_t d2h_buffer_details = {0 , 0 };
23+ hailo_resource_read_buffer (resource , 0 , sizeof (d2h_buffer_details ),
24+ & d2h_buffer_details );
25+
26+ if ((sizeof (notification -> buffer ) < d2h_buffer_details .buffer_len ) || (0 == d2h_buffer_details .is_buffer_in_use )) {
27+ return - EINVAL ;
28+ }
29+
30+ notification -> buffer_len = d2h_buffer_details .buffer_len ;
31+ hailo_resource_read_buffer (resource , sizeof (d2h_buffer_details ), notification -> buffer_len , notification -> buffer );
32+
33+ // Write is_buffer_in_use = false
34+ hailo_resource_write16 (resource , 0 , 0 );
35+ return 0 ;
36+ }
37+
38+ static inline size_t calculate_log_ready_to_read (FW_DEBUG_BUFFER_HEADER_t * header )
39+ {
40+ size_t ready_to_read = 0 ;
41+ size_t host_offset = header -> host_offset ;
42+ size_t chip_offset = header -> chip_offset ;
43+
44+ if (chip_offset >= host_offset ) {
45+ ready_to_read = chip_offset - host_offset ;
46+ } else {
47+ ready_to_read = DEBUG_BUFFER_DATA_SIZE - (host_offset - chip_offset );
48+ }
49+
50+ return ready_to_read ;
51+ }
52+
53+ long hailo_read_firmware_log (struct hailo_resource * fw_logger_resource , struct hailo_read_log_params * params )
54+ {
55+ FW_DEBUG_BUFFER_HEADER_t debug_buffer_header = {0 };
56+ size_t read_offset = 0 ;
57+ size_t ready_to_read = 0 ;
58+ size_t size_to_read = 0 ;
59+ uintptr_t user_buffer = (uintptr_t )params -> buffer ;
60+
61+ if (params -> buffer_size > ARRAY_SIZE (params -> buffer )) {
62+ return - EINVAL ;
63+ }
64+
65+ hailo_resource_read_buffer (fw_logger_resource , 0 , sizeof (debug_buffer_header ),
66+ & debug_buffer_header );
67+
68+ /* Point to the start of the data buffer. */
69+ ready_to_read = calculate_log_ready_to_read (& debug_buffer_header );
70+ if (0 == ready_to_read ) {
71+ params -> read_bytes = 0 ;
72+ return 0 ;
73+ }
74+ /* If ready to read is bigger than the buffer size, read only buffer size bytes. */
75+ ready_to_read = min (ready_to_read , params -> buffer_size );
76+
77+ /* Point to the data that is read to be read by the host. */
78+ read_offset = sizeof (debug_buffer_header ) + debug_buffer_header .host_offset ;
79+ /* Check if the offset should cycle back to beginning. */
80+ if (DEBUG_BUFFER_DATA_SIZE <= debug_buffer_header .host_offset + ready_to_read ) {
81+ size_to_read = DEBUG_BUFFER_DATA_SIZE - debug_buffer_header .host_offset ;
82+ hailo_resource_read_buffer (fw_logger_resource , read_offset , size_to_read , (void * )user_buffer );
83+
84+ user_buffer += size_to_read ;
85+ size_to_read = ready_to_read - size_to_read ;
86+ /* Point back to the beginning of the data buffer. */
87+ read_offset -= debug_buffer_header .host_offset ;
88+ }
89+ else {
90+ size_to_read = ready_to_read ;
91+ }
92+
93+ /* size_to_read may become 0 if the read reached DEBUG_BUFFER_DATA_SIZE exactly */
94+ hailo_resource_read_buffer (fw_logger_resource , read_offset , size_to_read , (void * )user_buffer );
95+
96+ /* Change current_offset to represent the new host offset. */
97+ read_offset += size_to_read ;
98+ hailo_resource_write32 (fw_logger_resource , offsetof(FW_DEBUG_BUFFER_HEADER_t , host_offset ),
99+ (u32 )(read_offset - sizeof (debug_buffer_header )));
100+
101+ params -> read_bytes = ready_to_read ;
102+ return 0 ;
103+ }
0 commit comments