1 /*-
2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $FreeBSD$
32 */
33
34 /**
35 * @file
36 *
37 */
38
39 #ifndef __OCS_UTILS_H
40 #define __OCS_UTILS_H
41
42 #include "ocs_list.h"
43 typedef struct ocs_array_s ocs_array_t;
44
45 extern void ocs_array_set_slablen(uint32_t len);
46 extern ocs_array_t *ocs_array_alloc(ocs_os_handle_t os, uint32_t size, uint32_t count);
47 extern void ocs_array_free(ocs_array_t *array);
48 extern void *ocs_array_get(ocs_array_t *array, uint32_t idx);
49 extern uint32_t ocs_array_get_count(ocs_array_t *array);
50 extern uint32_t ocs_array_get_size(ocs_array_t *array);
51
52 /* Void pointer array and iterator */
53 typedef struct ocs_varray_s ocs_varray_t;
54
55 extern ocs_varray_t *ocs_varray_alloc(ocs_os_handle_t os, uint32_t entry_count);
56 extern void ocs_varray_free(ocs_varray_t *ai);
57 extern int32_t ocs_varray_add(ocs_varray_t *ai, void *entry);
58 extern void ocs_varray_iter_reset(ocs_varray_t *ai);
59 extern void *ocs_varray_iter_next(ocs_varray_t *ai);
60 extern void *_ocs_varray_iter_next(ocs_varray_t *ai);
61 extern void ocs_varray_lock(ocs_varray_t *ai);
62 extern void ocs_varray_unlock(ocs_varray_t *ai);
63 extern uint32_t ocs_varray_get_count(ocs_varray_t *ai);
64
65
66 /***************************************************************************
67 * Circular buffer
68 *
69 */
70
71 typedef struct ocs_cbuf_s ocs_cbuf_t;
72
73 extern ocs_cbuf_t *ocs_cbuf_alloc(ocs_os_handle_t os, uint32_t entry_count);
74 extern void ocs_cbuf_free(ocs_cbuf_t *cbuf);
75 extern void *ocs_cbuf_get(ocs_cbuf_t *cbuf, int32_t timeout_usec);
76 extern int32_t ocs_cbuf_put(ocs_cbuf_t *cbuf, void *elem);
77 extern int32_t ocs_cbuf_prime(ocs_cbuf_t *cbuf, ocs_array_t *array);
78
79 typedef struct {
80 void *vaddr;
81 uint32_t length;
82 } ocs_scsi_vaddr_len_t;
83
84
85 #define OCS_TEXTBUF_MAX_ALLOC_LEN (256*1024)
86
87 typedef struct {
88 ocs_list_link_t link;
89 uint8_t user_allocated:1;
90 uint8_t *buffer;
91 uint32_t buffer_length;
92 uint32_t buffer_written;
93 } ocs_textbuf_segment_t;
94
95 typedef struct {
96 ocs_t *ocs;
97 ocs_list_t segment_list;
98 uint8_t extendable:1;
99 uint32_t allocation_length;
100 uint32_t total_allocation_length;
101 uint32_t max_allocation_length;
102 } ocs_textbuf_t;
103
104 extern int32_t ocs_textbuf_alloc(ocs_t *ocs, ocs_textbuf_t *textbuf, uint32_t length);
105 extern uint32_t ocs_textbuf_initialized(ocs_textbuf_t *textbuf);
106 extern int32_t ocs_textbuf_init(ocs_t *ocs, ocs_textbuf_t *textbuf, void *buffer, uint32_t length);
107 extern void ocs_textbuf_free(ocs_t *ocs, ocs_textbuf_t *textbuf);
108 extern void ocs_textbuf_putc(ocs_textbuf_t *textbuf, uint8_t c);
109 extern void ocs_textbuf_puts(ocs_textbuf_t *textbuf, char *s);
110 __attribute__((format(printf,2,3)))
111 extern void ocs_textbuf_printf(ocs_textbuf_t *textbuf, const char *fmt, ...);
112 __attribute__((format(printf,2,0)))
113 extern void ocs_textbuf_vprintf(ocs_textbuf_t *textbuf, const char *fmt, va_list ap);
114 extern void ocs_textbuf_buffer(ocs_textbuf_t *textbuf, uint8_t *buffer, uint32_t buffer_length);
115 extern void ocs_textbuf_copy(ocs_textbuf_t *textbuf, uint8_t *buffer, uint32_t buffer_length);
116 extern int32_t ocs_textbuf_remaining(ocs_textbuf_t *textbuf);
117 extern void ocs_textbuf_reset(ocs_textbuf_t *textbuf);
118 extern uint8_t *ocs_textbuf_get_buffer(ocs_textbuf_t *textbuf);
119 extern int32_t ocs_textbuf_get_length(ocs_textbuf_t *textbuf);
120 extern int32_t ocs_textbuf_get_written(ocs_textbuf_t *textbuf);
121 extern uint8_t *ocs_textbuf_ext_get_buffer(ocs_textbuf_t *textbuf, uint32_t idx);
122 extern int32_t ocs_textbuf_ext_get_length(ocs_textbuf_t *textbuf, uint32_t idx);
123 extern int32_t ocs_textbuf_ext_get_written(ocs_textbuf_t *textbuf, uint32_t idx);
124
125
126 typedef struct ocs_pool_s ocs_pool_t;
127
128 extern ocs_pool_t *ocs_pool_alloc(ocs_os_handle_t os, uint32_t size, uint32_t count, uint32_t use_lock);
129 extern void ocs_pool_reset(ocs_pool_t *pool);
130 extern void ocs_pool_free(ocs_pool_t *pool);
131 extern void *ocs_pool_get(ocs_pool_t *pool);
132 extern void ocs_pool_put(ocs_pool_t *pool, void *item);
133 extern uint32_t ocs_pool_get_count(ocs_pool_t *pool);
134 extern void *ocs_pool_get_instance(ocs_pool_t *pool, uint32_t idx);
135 extern uint32_t ocs_pool_get_freelist_count(ocs_pool_t *pool);
136
137
138 /* Uncomment this line to enable logging extended queue history
139 */
140 //#define OCS_DEBUG_QUEUE_HISTORY
141
142
143 /* Allocate maximum allowed (4M) */
144 #if defined(OCS_DEBUG_QUEUE_HISTORY)
145 #define OCS_Q_HIST_SIZE (1000000UL) /* Size in words */
146 #endif
147
148 #define OCS_LOG_ENABLE_SM_TRACE(ocs) (((ocs) != NULL) ? (((ocs)->logmask & (1U << 0)) != 0) : 0)
149 #define OCS_LOG_ENABLE_ELS_TRACE(ocs) (((ocs) != NULL) ? (((ocs)->logmask & (1U << 1)) != 0) : 0)
150 #define OCS_LOG_ENABLE_SCSI_TRACE(ocs) (((ocs) != NULL) ? (((ocs)->logmask & (1U << 2)) != 0) : 0)
151 #define OCS_LOG_ENABLE_SCSI_TGT_TRACE(ocs) (((ocs) != NULL) ? (((ocs)->logmask & (1U << 3)) != 0) : 0)
152 #define OCS_LOG_ENABLE_DOMAIN_SM_TRACE(ocs) (((ocs) != NULL) ? (((ocs)->logmask & (1U << 4)) != 0) : 0)
153 #define OCS_LOG_ENABLE_Q_FULL_BUSY_MSG(ocs) (((ocs) != NULL) ? (((ocs)->logmask & (1U << 5)) != 0) : 0)
154 #define OCS_LOG_ENABLE_IO_ERRORS(ocs) (((ocs) != NULL) ? (((ocs)->logmask & (1U << 6)) != 0) : 0)
155
156
157 extern void ocs_dump32(uint32_t, ocs_os_handle_t, const char *, void *, uint32_t);
158 extern void ocs_debug_enable(uint32_t mask);
159 extern void ocs_debug_disable(uint32_t mask);
160 extern int ocs_debug_is_enabled(uint32_t mask);
161 extern void ocs_debug_attach(void *);
162 extern void ocs_debug_detach(void *);
163
164 #if defined(OCS_DEBUG_QUEUE_HISTORY)
165
166 /**
167 * @brief Queue history footer
168 */
169 typedef union ocs_q_hist_ftr_u {
170 uint32_t word;
171 struct {
172 #define Q_HIST_TYPE_LEN 3
173 #define Q_HIST_MASK_LEN 29
174 uint32_t mask:Q_HIST_MASK_LEN,
175 type:Q_HIST_TYPE_LEN;
176 } s;
177 } ocs_q_hist_ftr_t;
178
179
180 /**
181 * @brief WQE command mask lookup
182 */
183 typedef struct ocs_q_hist_wqe_mask_s {
184 uint8_t command;
185 uint32_t mask;
186 } ocs_q_hist_wqe_mask_t;
187
188 /**
189 * @brief CQE mask lookup
190 */
191 typedef struct ocs_q_hist_cqe_mask_s {
192 uint8_t ctype;
193 uint32_t :Q_HIST_MASK_LEN,
194 type:Q_HIST_TYPE_LEN;
195 uint32_t mask;
196 uint32_t mask_err;
197 } ocs_q_hist_cqe_mask_t;
198
199 /**
200 * @brief Queue history type
201 */
202 typedef enum {
203 /* changes need to be made to ocs_queue_history_type_name() as well */
204 OCS_Q_HIST_TYPE_WQE = 0,
205 OCS_Q_HIST_TYPE_CWQE,
206 OCS_Q_HIST_TYPE_CXABT,
207 OCS_Q_HIST_TYPE_MISC,
208 } ocs_q_hist_type_t;
209
210 static __inline const char *
ocs_queue_history_type_name(ocs_q_hist_type_t type)211 ocs_queue_history_type_name(ocs_q_hist_type_t type)
212 {
213 switch (type) {
214 case OCS_Q_HIST_TYPE_WQE: return "wqe"; break;
215 case OCS_Q_HIST_TYPE_CWQE: return "wcqe"; break;
216 case OCS_Q_HIST_TYPE_CXABT: return "xacqe"; break;
217 case OCS_Q_HIST_TYPE_MISC: return "misc"; break;
218 default: return "unknown"; break;
219 }
220 }
221
222 typedef struct {
223 ocs_t *ocs;
224 uint32_t *q_hist;
225 uint32_t q_hist_index;
226 ocs_lock_t q_hist_lock;
227 } ocs_hw_q_hist_t;
228
229 extern void ocs_queue_history_cqe(ocs_hw_q_hist_t*, uint8_t, uint32_t *, uint8_t, uint32_t, uint32_t);
230 extern void ocs_queue_history_wq(ocs_hw_q_hist_t*, uint32_t *, uint32_t, uint32_t);
231 extern void ocs_queue_history_misc(ocs_hw_q_hist_t*, uint32_t *, uint32_t);
232 extern void ocs_queue_history_init(ocs_t *, ocs_hw_q_hist_t*);
233 extern void ocs_queue_history_free(ocs_hw_q_hist_t*);
234 extern uint32_t ocs_queue_history_prev_index(uint32_t);
235 extern uint8_t ocs_queue_history_q_info_enabled(void);
236 extern uint8_t ocs_queue_history_timestamp_enabled(void);
237 #else
238 #define ocs_queue_history_wq(...)
239 #define ocs_queue_history_cqe(...)
240 #define ocs_queue_history_misc(...)
241 #define ocs_queue_history_init(...)
242 #define ocs_queue_history_free(...)
243 #endif
244
245 #define OCS_DEBUG_ALWAYS (1U << 0)
246 #define OCS_DEBUG_ENABLE_MQ_DUMP (1U << 1)
247 #define OCS_DEBUG_ENABLE_CQ_DUMP (1U << 2)
248 #define OCS_DEBUG_ENABLE_WQ_DUMP (1U << 3)
249 #define OCS_DEBUG_ENABLE_EQ_DUMP (1U << 4)
250 #define OCS_DEBUG_ENABLE_SPARAM_DUMP (1U << 5)
251
252 extern void _ocs_assert(const char *cond, const char *filename, int linenum);
253
254 #define ocs_assert(cond, ...) \
255 do { \
256 if (!(cond)) { \
257 _ocs_assert(#cond, __FILE__, __LINE__); \
258 return __VA_ARGS__; \
259 } \
260 } while (0)
261
262 extern void ocs_dump_service_params(const char *label, void *sparms);
263 extern void ocs_display_sparams(const char *prelabel, const char *reqlabel, int dest, void *textbuf, void *sparams);
264
265
266 typedef struct {
267 uint16_t crc;
268 uint16_t app_tag;
269 uint32_t ref_tag;
270 } ocs_dif_t;
271
272 /* DIF guard calculations */
273 extern uint16_t ocs_scsi_dif_calc_crc(const uint8_t *, uint32_t size, uint16_t crc);
274 extern uint16_t ocs_scsi_dif_calc_checksum(ocs_scsi_vaddr_len_t addrlen[], uint32_t addrlen_count);
275
276 /**
277 * @brief Power State change message types
278 *
279 */
280 typedef enum {
281 OCS_PM_PREPARE = 1,
282 OCS_PM_SLEEP,
283 OCS_PM_HIBERNATE,
284 OCS_PM_RESUME,
285 } ocs_pm_msg_e;
286
287 /**
288 * @brief Power State values
289 *
290 */
291 typedef enum {
292 OCS_PM_STATE_S0 = 0,
293 OCS_PM_STATE_S1,
294 OCS_PM_STATE_S2,
295 OCS_PM_STATE_S3,
296 OCS_PM_STATE_S4,
297 } ocs_pm_state_e;
298
299 typedef struct {
300 ocs_pm_state_e pm_state; /*<< Current PM state */
301 } ocs_pm_context_t;
302
303 extern int32_t ocs_pm_request(ocs_t *ocs, ocs_pm_msg_e msg, int32_t (*callback)(ocs_t *ocs, int32_t status, void *arg),
304 void *arg);
305 extern ocs_pm_state_e ocs_pm_get_state(ocs_t *ocs);
306 extern const char *ocs_pm_get_state_string(ocs_t *ocs);
307
308 #define SPV_ROWLEN 256
309 #define SPV_DIM 3
310
311
312 /*!
313 * @defgroup spv Sparse Vector
314 */
315
316 /**
317 * @brief Sparse vector structure.
318 */
319 typedef struct sparse_vector_s {
320 ocs_os_handle_t os;
321 uint32_t max_idx; /**< maximum index value */
322 void **array; /**< pointer to 3D array */
323 } *sparse_vector_t;
324
325 extern void spv_del(sparse_vector_t spv);
326 extern sparse_vector_t spv_new(ocs_os_handle_t os);
327 extern void spv_set(sparse_vector_t sv, uint32_t idx, void *value);
328 extern void *spv_get(sparse_vector_t sv, uint32_t idx);
329
330 extern unsigned short t10crc16(const unsigned char *blk_adr, unsigned long blk_len, unsigned short crc);
331
332 typedef struct ocs_ramlog_s ocs_ramlog_t;
333
334 #define OCS_RAMLOG_DEFAULT_BUFFERS 5
335
336 extern ocs_ramlog_t *ocs_ramlog_init(ocs_t *ocs, uint32_t buffer_len, uint32_t buffer_count);
337 extern void ocs_ramlog_free(ocs_t *ocs, ocs_ramlog_t *ramlog);
338 extern void ocs_ramlog_clear(ocs_t *ocs, ocs_ramlog_t *ramlog, int clear_start_of_day, int clear_recent);
339 __attribute__((format(printf,2,3)))
340 extern int32_t ocs_ramlog_printf(void *os, const char *fmt, ...);
341 __attribute__((format(printf,2,0)))
342 extern int32_t ocs_ramlog_vprintf(ocs_ramlog_t *ramlog, const char *fmt, va_list ap);
343 extern int32_t ocs_ddump_ramlog(ocs_textbuf_t *textbuf, ocs_ramlog_t *ramlog);
344
345 #endif
346