1 | /********************************************************************** |
2 | * Author: Cavium, Inc. |
3 | * |
4 | * Contact: support@cavium.com |
5 | * Please include "LiquidIO" in the subject. |
6 | * |
7 | * Copyright (c) 2003-2016 Cavium, Inc. |
8 | * |
9 | * This file is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License, Version 2, as |
11 | * published by the Free Software Foundation. |
12 | * |
13 | * This file is distributed in the hope that it will be useful, but |
14 | * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty |
15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or |
16 | * NONINFRINGEMENT. See the GNU General Public License for more details. |
17 | ***********************************************************************/ |
18 | /* |
19 | * @file octeon_console.c |
20 | */ |
21 | #include <linux/moduleparam.h> |
22 | #include <linux/pci.h> |
23 | #include <linux/netdevice.h> |
24 | #include <linux/crc32.h> |
25 | #include "liquidio_common.h" |
26 | #include "octeon_droq.h" |
27 | #include "octeon_iq.h" |
28 | #include "response_manager.h" |
29 | #include "octeon_device.h" |
30 | #include "liquidio_image.h" |
31 | #include "octeon_mem_ops.h" |
32 | |
33 | static void octeon_remote_lock(void); |
34 | static void octeon_remote_unlock(void); |
35 | static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct, |
36 | const char *name, |
37 | u32 flags); |
38 | static int octeon_console_read(struct octeon_device *oct, u32 console_num, |
39 | char *buffer, u32 buf_size); |
40 | |
41 | #define BOOTLOADER_PCI_READ_BUFFER_DATA_ADDR 0x0006c008 |
42 | #define BOOTLOADER_PCI_READ_BUFFER_LEN_ADDR 0x0006c004 |
43 | #define BOOTLOADER_PCI_READ_BUFFER_OWNER_ADDR 0x0006c000 |
44 | #define BOOTLOADER_PCI_READ_DESC_ADDR 0x0006c100 |
45 | #define BOOTLOADER_PCI_WRITE_BUFFER_STR_LEN 248 |
46 | |
47 | #define OCTEON_PCI_IO_BUF_OWNER_OCTEON 0x00000001 |
48 | #define OCTEON_PCI_IO_BUF_OWNER_HOST 0x00000002 |
49 | |
50 | /** Can change without breaking ABI */ |
51 | #define CVMX_BOOTMEM_NUM_NAMED_BLOCKS 64 |
52 | |
53 | /** minimum alignment of bootmem alloced blocks */ |
54 | #define CVMX_BOOTMEM_ALIGNMENT_SIZE (16ull) |
55 | |
56 | /** CVMX bootmem descriptor major version */ |
57 | #define CVMX_BOOTMEM_DESC_MAJ_VER 3 |
58 | /* CVMX bootmem descriptor minor version */ |
59 | #define CVMX_BOOTMEM_DESC_MIN_VER 0 |
60 | |
61 | /* Current versions */ |
62 | #define OCTEON_PCI_CONSOLE_MAJOR_VERSION 1 |
63 | #define OCTEON_PCI_CONSOLE_MINOR_VERSION 0 |
64 | #define OCTEON_PCI_CONSOLE_BLOCK_NAME "__pci_console" |
65 | #define OCTEON_CONSOLE_POLL_INTERVAL_MS 100 /* 10 times per second */ |
66 | |
67 | /* First three members of cvmx_bootmem_desc are left in original |
68 | * positions for backwards compatibility. |
69 | * Assumes big endian target |
70 | */ |
71 | struct cvmx_bootmem_desc { |
72 | /** spinlock to control access to list */ |
73 | u32 lock; |
74 | |
75 | /** flags for indicating various conditions */ |
76 | u32 flags; |
77 | |
78 | u64 head_addr; |
79 | |
80 | /** incremented changed when incompatible changes made */ |
81 | u32 major_version; |
82 | |
83 | /** incremented changed when compatible changes made, |
84 | * reset to zero when major incremented |
85 | */ |
86 | u32 minor_version; |
87 | |
88 | u64 app_data_addr; |
89 | u64 app_data_size; |
90 | |
91 | /** number of elements in named blocks array */ |
92 | u32 nb_num_blocks; |
93 | |
94 | /** length of name array in bootmem blocks */ |
95 | u32 named_block_name_len; |
96 | |
97 | /** address of named memory block descriptors */ |
98 | u64 named_block_array_addr; |
99 | }; |
100 | |
101 | /* Structure that defines a single console. |
102 | * |
103 | * Note: when read_index == write_index, the buffer is empty. |
104 | * The actual usable size of each console is console_buf_size -1; |
105 | */ |
106 | struct octeon_pci_console { |
107 | u64 input_base_addr; |
108 | u32 input_read_index; |
109 | u32 input_write_index; |
110 | u64 output_base_addr; |
111 | u32 output_read_index; |
112 | u32 output_write_index; |
113 | u32 lock; |
114 | u32 buf_size; |
115 | }; |
116 | |
117 | /* This is the main container structure that contains all the information |
118 | * about all PCI consoles. The address of this structure is passed to various |
119 | * routines that operation on PCI consoles. |
120 | */ |
121 | struct octeon_pci_console_desc { |
122 | u32 major_version; |
123 | u32 minor_version; |
124 | u32 lock; |
125 | u32 flags; |
126 | u32 num_consoles; |
127 | u32 pad; |
128 | /* must be 64 bit aligned here... */ |
129 | /* Array of addresses of octeon_pci_console structures */ |
130 | u64 console_addr_array[]; |
131 | /* Implicit storage for console_addr_array */ |
132 | }; |
133 | |
134 | /* |
135 | * This function is the implementation of the get macros defined |
136 | * for individual structure members. The argument are generated |
137 | * by the macros inorder to read only the needed memory. |
138 | * |
139 | * @param oct Pointer to current octeon device |
140 | * @param base 64bit physical address of the complete structure |
141 | * @param offset Offset from the beginning of the structure to the member being |
142 | * accessed. |
143 | * @param size Size of the structure member. |
144 | * |
145 | * @return Value of the structure member promoted into a u64. |
146 | */ |
147 | static inline u64 __cvmx_bootmem_desc_get(struct octeon_device *oct, |
148 | u64 base, |
149 | u32 offset, |
150 | u32 size) |
151 | { |
152 | base = (1ull << 63) | (base + offset); |
153 | switch (size) { |
154 | case 4: |
155 | return octeon_read_device_mem32(oct, core_addr: base); |
156 | case 8: |
157 | return octeon_read_device_mem64(oct, core_addr: base); |
158 | default: |
159 | return 0; |
160 | } |
161 | } |
162 | |
163 | /* |
164 | * This function retrieves the string name of a named block. It is |
165 | * more complicated than a simple memcpy() since the named block |
166 | * descriptor may not be directly accessible. |
167 | * |
168 | * @param addr Physical address of the named block descriptor |
169 | * @param str String to receive the named block string name |
170 | * @param len Length of the string buffer, which must match the length |
171 | * stored in the bootmem descriptor. |
172 | */ |
173 | static void CVMX_BOOTMEM_NAMED_GET_NAME(struct octeon_device *oct, |
174 | u64 addr, |
175 | char *str, |
176 | u32 len) |
177 | { |
178 | addr += offsetof(struct cvmx_bootmem_named_block_desc, name); |
179 | octeon_pci_read_core_mem(oct, coreaddr: addr, buf: (u8 *)str, len); |
180 | str[len] = 0; |
181 | } |
182 | |
183 | /* See header file for descriptions of functions */ |
184 | |
185 | /* |
186 | * Check the version information on the bootmem descriptor |
187 | * |
188 | * @param exact_match |
189 | * Exact major version to check against. A zero means |
190 | * check that the version supports named blocks. |
191 | * |
192 | * @return Zero if the version is correct. Negative if the version is |
193 | * incorrect. Failures also cause a message to be displayed. |
194 | */ |
195 | static int __cvmx_bootmem_check_version(struct octeon_device *oct, |
196 | u32 exact_match) |
197 | { |
198 | u32 major_version; |
199 | u32 minor_version; |
200 | |
201 | if (!oct->bootmem_desc_addr) |
202 | oct->bootmem_desc_addr = |
203 | octeon_read_device_mem64(oct, |
204 | BOOTLOADER_PCI_READ_DESC_ADDR); |
205 | major_version = (u32)__cvmx_bootmem_desc_get( |
206 | oct, base: oct->bootmem_desc_addr, |
207 | offsetof(struct cvmx_bootmem_desc, major_version), |
208 | sizeof_field(struct cvmx_bootmem_desc, major_version)); |
209 | minor_version = (u32)__cvmx_bootmem_desc_get( |
210 | oct, base: oct->bootmem_desc_addr, |
211 | offsetof(struct cvmx_bootmem_desc, minor_version), |
212 | sizeof_field(struct cvmx_bootmem_desc, minor_version)); |
213 | |
214 | dev_dbg(&oct->pci_dev->dev, "%s: major_version=%d\n" , __func__, |
215 | major_version); |
216 | if ((major_version > 3) || |
217 | (exact_match && major_version != exact_match)) { |
218 | dev_err(&oct->pci_dev->dev, "bootmem ver mismatch %d.%d addr:0x%llx\n" , |
219 | major_version, minor_version, |
220 | (long long)oct->bootmem_desc_addr); |
221 | return -1; |
222 | } else { |
223 | return 0; |
224 | } |
225 | } |
226 | |
227 | static const struct cvmx_bootmem_named_block_desc |
228 | *__cvmx_bootmem_find_named_block_flags(struct octeon_device *oct, |
229 | const char *name, u32 flags) |
230 | { |
231 | struct cvmx_bootmem_named_block_desc *desc = |
232 | &oct->bootmem_named_block_desc; |
233 | u64 named_addr = cvmx_bootmem_phy_named_block_find(oct, name, flags); |
234 | |
235 | if (named_addr) { |
236 | desc->base_addr = __cvmx_bootmem_desc_get( |
237 | oct, base: named_addr, |
238 | offsetof(struct cvmx_bootmem_named_block_desc, |
239 | base_addr), |
240 | sizeof_field( |
241 | struct cvmx_bootmem_named_block_desc, |
242 | base_addr)); |
243 | desc->size = __cvmx_bootmem_desc_get(oct, base: named_addr, |
244 | offsetof(struct cvmx_bootmem_named_block_desc, |
245 | size), |
246 | sizeof_field( |
247 | struct cvmx_bootmem_named_block_desc, |
248 | size)); |
249 | |
250 | strscpy(desc->name, name, sizeof(desc->name)); |
251 | return &oct->bootmem_named_block_desc; |
252 | } else { |
253 | return NULL; |
254 | } |
255 | } |
256 | |
257 | static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct, |
258 | const char *name, |
259 | u32 flags) |
260 | { |
261 | u64 result = 0; |
262 | |
263 | if (!__cvmx_bootmem_check_version(oct, exact_match: 3)) { |
264 | u32 i; |
265 | |
266 | u64 named_block_array_addr = __cvmx_bootmem_desc_get( |
267 | oct, base: oct->bootmem_desc_addr, |
268 | offsetof(struct cvmx_bootmem_desc, |
269 | named_block_array_addr), |
270 | sizeof_field(struct cvmx_bootmem_desc, |
271 | named_block_array_addr)); |
272 | u32 num_blocks = (u32)__cvmx_bootmem_desc_get( |
273 | oct, base: oct->bootmem_desc_addr, |
274 | offsetof(struct cvmx_bootmem_desc, |
275 | nb_num_blocks), |
276 | sizeof_field(struct cvmx_bootmem_desc, |
277 | nb_num_blocks)); |
278 | |
279 | u32 name_length = (u32)__cvmx_bootmem_desc_get( |
280 | oct, base: oct->bootmem_desc_addr, |
281 | offsetof(struct cvmx_bootmem_desc, |
282 | named_block_name_len), |
283 | sizeof_field(struct cvmx_bootmem_desc, |
284 | named_block_name_len)); |
285 | |
286 | u64 named_addr = named_block_array_addr; |
287 | |
288 | for (i = 0; i < num_blocks; i++) { |
289 | u64 named_size = __cvmx_bootmem_desc_get( |
290 | oct, base: named_addr, |
291 | offsetof( |
292 | struct cvmx_bootmem_named_block_desc, |
293 | size), |
294 | sizeof_field( |
295 | struct cvmx_bootmem_named_block_desc, |
296 | size)); |
297 | |
298 | if (name && named_size) { |
299 | char *name_tmp = |
300 | kmalloc(size: name_length + 1, GFP_KERNEL); |
301 | if (!name_tmp) |
302 | break; |
303 | |
304 | CVMX_BOOTMEM_NAMED_GET_NAME(oct, addr: named_addr, |
305 | str: name_tmp, |
306 | len: name_length); |
307 | if (!strncmp(name, name_tmp, name_length)) { |
308 | result = named_addr; |
309 | kfree(objp: name_tmp); |
310 | break; |
311 | } |
312 | kfree(objp: name_tmp); |
313 | } else if (!name && !named_size) { |
314 | result = named_addr; |
315 | break; |
316 | } |
317 | |
318 | named_addr += |
319 | sizeof(struct cvmx_bootmem_named_block_desc); |
320 | } |
321 | } |
322 | return result; |
323 | } |
324 | |
325 | /* |
326 | * Find a named block on the remote Octeon |
327 | * |
328 | * @param name Name of block to find |
329 | * @param base_addr Address the block is at (OUTPUT) |
330 | * @param size The size of the block (OUTPUT) |
331 | * |
332 | * @return Zero on success, One on failure. |
333 | */ |
334 | static int octeon_named_block_find(struct octeon_device *oct, const char *name, |
335 | u64 *base_addr, u64 *size) |
336 | { |
337 | const struct cvmx_bootmem_named_block_desc *named_block; |
338 | |
339 | octeon_remote_lock(); |
340 | named_block = __cvmx_bootmem_find_named_block_flags(oct, name, flags: 0); |
341 | octeon_remote_unlock(); |
342 | if (named_block) { |
343 | *base_addr = named_block->base_addr; |
344 | *size = named_block->size; |
345 | return 0; |
346 | } |
347 | return 1; |
348 | } |
349 | |
350 | static void octeon_remote_lock(void) |
351 | { |
352 | /* fill this in if any sharing is needed */ |
353 | } |
354 | |
355 | static void octeon_remote_unlock(void) |
356 | { |
357 | /* fill this in if any sharing is needed */ |
358 | } |
359 | |
360 | int octeon_console_send_cmd(struct octeon_device *oct, char *cmd_str, |
361 | u32 wait_hundredths) |
362 | { |
363 | u32 len = (u32)strlen(cmd_str); |
364 | |
365 | dev_dbg(&oct->pci_dev->dev, "sending \"%s\" to bootloader\n" , cmd_str); |
366 | |
367 | if (len > BOOTLOADER_PCI_WRITE_BUFFER_STR_LEN - 1) { |
368 | dev_err(&oct->pci_dev->dev, "Command string too long, max length is: %d\n" , |
369 | BOOTLOADER_PCI_WRITE_BUFFER_STR_LEN - 1); |
370 | return -1; |
371 | } |
372 | |
373 | if (octeon_wait_for_bootloader(oct, wait_time_hundredths: wait_hundredths) != 0) { |
374 | dev_err(&oct->pci_dev->dev, "Bootloader not ready for command.\n" ); |
375 | return -1; |
376 | } |
377 | |
378 | /* Write command to bootloader */ |
379 | octeon_remote_lock(); |
380 | octeon_pci_write_core_mem(oct, BOOTLOADER_PCI_READ_BUFFER_DATA_ADDR, |
381 | buf: (u8 *)cmd_str, len); |
382 | octeon_write_device_mem32(oct, BOOTLOADER_PCI_READ_BUFFER_LEN_ADDR, |
383 | val: len); |
384 | octeon_write_device_mem32(oct, BOOTLOADER_PCI_READ_BUFFER_OWNER_ADDR, |
385 | OCTEON_PCI_IO_BUF_OWNER_OCTEON); |
386 | |
387 | /* Bootloader should accept command very quickly |
388 | * if it really was ready |
389 | */ |
390 | if (octeon_wait_for_bootloader(oct, wait_time_hundredths: 200) != 0) { |
391 | octeon_remote_unlock(); |
392 | dev_err(&oct->pci_dev->dev, "Bootloader did not accept command.\n" ); |
393 | return -1; |
394 | } |
395 | octeon_remote_unlock(); |
396 | return 0; |
397 | } |
398 | |
399 | int octeon_wait_for_bootloader(struct octeon_device *oct, |
400 | u32 wait_time_hundredths) |
401 | { |
402 | dev_dbg(&oct->pci_dev->dev, "waiting %d0 ms for bootloader\n" , |
403 | wait_time_hundredths); |
404 | |
405 | if (octeon_mem_access_ok(oct)) |
406 | return -1; |
407 | |
408 | while (wait_time_hundredths > 0 && |
409 | octeon_read_device_mem32(oct, |
410 | BOOTLOADER_PCI_READ_BUFFER_OWNER_ADDR) |
411 | != OCTEON_PCI_IO_BUF_OWNER_HOST) { |
412 | if (--wait_time_hundredths <= 0) |
413 | return -1; |
414 | schedule_timeout_uninterruptible(HZ / 100); |
415 | } |
416 | return 0; |
417 | } |
418 | |
419 | static void octeon_console_handle_result(struct octeon_device *oct, |
420 | size_t console_num) |
421 | { |
422 | struct octeon_console *console; |
423 | |
424 | console = &oct->console[console_num]; |
425 | |
426 | console->waiting = 0; |
427 | } |
428 | |
429 | static char console_buffer[OCTEON_CONSOLE_MAX_READ_BYTES]; |
430 | |
431 | static void output_console_line(struct octeon_device *oct, |
432 | struct octeon_console *console, |
433 | size_t console_num, |
434 | char *console_buffer, |
435 | s32 bytes_read) |
436 | { |
437 | char *line; |
438 | s32 i; |
439 | size_t len; |
440 | |
441 | line = console_buffer; |
442 | for (i = 0; i < bytes_read; i++) { |
443 | /* Output a line at a time, prefixed */ |
444 | if (console_buffer[i] == '\n') { |
445 | console_buffer[i] = '\0'; |
446 | /* We need to output 'line', prefaced by 'leftover'. |
447 | * However, it is possible we're being called to |
448 | * output 'leftover' by itself (in the case of nothing |
449 | * having been read from the console). |
450 | * |
451 | * To avoid duplication, check for this condition. |
452 | */ |
453 | if (console->leftover[0] && |
454 | (line != console->leftover)) { |
455 | if (console->print) |
456 | (*console->print)(oct, (u32)console_num, |
457 | console->leftover, |
458 | line); |
459 | console->leftover[0] = '\0'; |
460 | } else { |
461 | if (console->print) |
462 | (*console->print)(oct, (u32)console_num, |
463 | line, NULL); |
464 | } |
465 | line = &console_buffer[i + 1]; |
466 | } |
467 | } |
468 | |
469 | /* Save off any leftovers */ |
470 | if (line != &console_buffer[bytes_read]) { |
471 | console_buffer[bytes_read] = '\0'; |
472 | len = strlen(console->leftover); |
473 | strscpy(&console->leftover[len], line, |
474 | sizeof(console->leftover) - len + 1); |
475 | } |
476 | } |
477 | |
478 | static void check_console(struct work_struct *work) |
479 | { |
480 | s32 bytes_read, tries, total_read; |
481 | size_t len; |
482 | struct octeon_console *console; |
483 | struct cavium_wk *wk = (struct cavium_wk *)work; |
484 | struct octeon_device *oct = (struct octeon_device *)wk->ctxptr; |
485 | u32 console_num = (u32)wk->ctxul; |
486 | u32 delay; |
487 | |
488 | console = &oct->console[console_num]; |
489 | tries = 0; |
490 | total_read = 0; |
491 | |
492 | do { |
493 | /* Take console output regardless of whether it will |
494 | * be logged |
495 | */ |
496 | bytes_read = |
497 | octeon_console_read(oct, console_num, buffer: console_buffer, |
498 | buf_size: sizeof(console_buffer) - 1); |
499 | if (bytes_read > 0) { |
500 | total_read += bytes_read; |
501 | if (console->waiting) |
502 | octeon_console_handle_result(oct, console_num); |
503 | if (console->print) { |
504 | output_console_line(oct, console, console_num, |
505 | console_buffer, bytes_read); |
506 | } |
507 | } else if (bytes_read < 0) { |
508 | dev_err(&oct->pci_dev->dev, "Error reading console %u, ret=%d\n" , |
509 | console_num, bytes_read); |
510 | } |
511 | |
512 | tries++; |
513 | } while ((bytes_read > 0) && (tries < 16)); |
514 | |
515 | /* If nothing is read after polling the console, |
516 | * output any leftovers if any |
517 | */ |
518 | if (console->print && (total_read == 0) && |
519 | (console->leftover[0])) { |
520 | /* append '\n' as terminator for 'output_console_line' */ |
521 | len = strlen(console->leftover); |
522 | console->leftover[len] = '\n'; |
523 | output_console_line(oct, console, console_num, |
524 | console_buffer: console->leftover, bytes_read: (s32)(len + 1)); |
525 | console->leftover[0] = '\0'; |
526 | } |
527 | |
528 | delay = OCTEON_CONSOLE_POLL_INTERVAL_MS; |
529 | |
530 | schedule_delayed_work(dwork: &wk->work, delay: msecs_to_jiffies(m: delay)); |
531 | } |
532 | |
533 | int octeon_init_consoles(struct octeon_device *oct) |
534 | { |
535 | int ret = 0; |
536 | u64 addr, size; |
537 | |
538 | ret = octeon_mem_access_ok(oct); |
539 | if (ret) { |
540 | dev_err(&oct->pci_dev->dev, "Memory access not okay'\n" ); |
541 | return ret; |
542 | } |
543 | |
544 | ret = octeon_named_block_find(oct, OCTEON_PCI_CONSOLE_BLOCK_NAME, base_addr: &addr, |
545 | size: &size); |
546 | if (ret) { |
547 | dev_err(&oct->pci_dev->dev, "Could not find console '%s'\n" , |
548 | OCTEON_PCI_CONSOLE_BLOCK_NAME); |
549 | return ret; |
550 | } |
551 | |
552 | /* Dedicate one of Octeon's BAR1 index registers to create a static |
553 | * mapping to a region of Octeon DRAM that contains the PCI console |
554 | * named block. |
555 | */ |
556 | oct->console_nb_info.bar1_index = BAR1_INDEX_STATIC_MAP; |
557 | oct->fn_list.bar1_idx_setup(oct, addr, oct->console_nb_info.bar1_index, |
558 | true); |
559 | oct->console_nb_info.dram_region_base = addr |
560 | & ~(OCTEON_BAR1_ENTRY_SIZE - 1ULL); |
561 | |
562 | /* num_consoles > 0, is an indication that the consoles |
563 | * are accessible |
564 | */ |
565 | oct->num_consoles = octeon_read_device_mem32(oct, |
566 | core_addr: addr + offsetof(struct octeon_pci_console_desc, |
567 | num_consoles)); |
568 | oct->console_desc_addr = addr; |
569 | |
570 | dev_dbg(&oct->pci_dev->dev, "Initialized consoles. %d available\n" , |
571 | oct->num_consoles); |
572 | |
573 | return ret; |
574 | } |
575 | |
576 | static void octeon_get_uboot_version(struct octeon_device *oct) |
577 | { |
578 | s32 bytes_read, tries, total_read; |
579 | struct octeon_console *console; |
580 | u32 console_num = 0; |
581 | char *uboot_ver; |
582 | char *buf; |
583 | char *p; |
584 | |
585 | #define OCTEON_UBOOT_VER_BUF_SIZE 512 |
586 | buf = kmalloc(OCTEON_UBOOT_VER_BUF_SIZE, GFP_KERNEL); |
587 | if (!buf) |
588 | return; |
589 | |
590 | if (octeon_console_send_cmd(oct, cmd_str: "setenv stdout pci\n" , wait_hundredths: 50)) { |
591 | kfree(objp: buf); |
592 | return; |
593 | } |
594 | |
595 | if (octeon_console_send_cmd(oct, cmd_str: "version\n" , wait_hundredths: 1)) { |
596 | kfree(objp: buf); |
597 | return; |
598 | } |
599 | |
600 | console = &oct->console[console_num]; |
601 | tries = 0; |
602 | total_read = 0; |
603 | |
604 | do { |
605 | /* Take console output regardless of whether it will |
606 | * be logged |
607 | */ |
608 | bytes_read = |
609 | octeon_console_read(oct, |
610 | console_num, buffer: buf + total_read, |
611 | OCTEON_UBOOT_VER_BUF_SIZE - 1 - |
612 | total_read); |
613 | if (bytes_read > 0) { |
614 | buf[bytes_read] = '\0'; |
615 | |
616 | total_read += bytes_read; |
617 | if (console->waiting) |
618 | octeon_console_handle_result(oct, console_num); |
619 | } else if (bytes_read < 0) { |
620 | dev_err(&oct->pci_dev->dev, "Error reading console %u, ret=%d\n" , |
621 | console_num, bytes_read); |
622 | } |
623 | |
624 | tries++; |
625 | } while ((bytes_read > 0) && (tries < 16)); |
626 | |
627 | /* If nothing is read after polling the console, |
628 | * output any leftovers if any |
629 | */ |
630 | if ((total_read == 0) && (console->leftover[0])) { |
631 | dev_dbg(&oct->pci_dev->dev, "%u: %s\n" , |
632 | console_num, console->leftover); |
633 | console->leftover[0] = '\0'; |
634 | } |
635 | |
636 | buf[OCTEON_UBOOT_VER_BUF_SIZE - 1] = '\0'; |
637 | |
638 | uboot_ver = strstr(buf, "U-Boot" ); |
639 | if (uboot_ver) { |
640 | p = strstr(uboot_ver, "mips" ); |
641 | if (p) { |
642 | p--; |
643 | *p = '\0'; |
644 | dev_info(&oct->pci_dev->dev, "%s\n" , uboot_ver); |
645 | } |
646 | } |
647 | |
648 | kfree(objp: buf); |
649 | octeon_console_send_cmd(oct, cmd_str: "setenv stdout serial\n" , wait_hundredths: 50); |
650 | } |
651 | |
652 | int octeon_add_console(struct octeon_device *oct, u32 console_num, |
653 | char *dbg_enb) |
654 | { |
655 | int ret = 0; |
656 | u32 delay; |
657 | u64 coreaddr; |
658 | struct delayed_work *work; |
659 | struct octeon_console *console; |
660 | |
661 | if (console_num >= oct->num_consoles) { |
662 | dev_err(&oct->pci_dev->dev, |
663 | "trying to read from console number %d when only 0 to %d exist\n" , |
664 | console_num, oct->num_consoles); |
665 | } else { |
666 | console = &oct->console[console_num]; |
667 | |
668 | console->waiting = 0; |
669 | |
670 | coreaddr = oct->console_desc_addr + console_num * 8 + |
671 | offsetof(struct octeon_pci_console_desc, |
672 | console_addr_array); |
673 | console->addr = octeon_read_device_mem64(oct, core_addr: coreaddr); |
674 | coreaddr = console->addr + offsetof(struct octeon_pci_console, |
675 | buf_size); |
676 | console->buffer_size = octeon_read_device_mem32(oct, core_addr: coreaddr); |
677 | coreaddr = console->addr + offsetof(struct octeon_pci_console, |
678 | input_base_addr); |
679 | console->input_base_addr = |
680 | octeon_read_device_mem64(oct, core_addr: coreaddr); |
681 | coreaddr = console->addr + offsetof(struct octeon_pci_console, |
682 | output_base_addr); |
683 | console->output_base_addr = |
684 | octeon_read_device_mem64(oct, core_addr: coreaddr); |
685 | console->leftover[0] = '\0'; |
686 | |
687 | work = &oct->console_poll_work[console_num].work; |
688 | |
689 | octeon_get_uboot_version(oct); |
690 | |
691 | INIT_DELAYED_WORK(work, check_console); |
692 | oct->console_poll_work[console_num].ctxptr = (void *)oct; |
693 | oct->console_poll_work[console_num].ctxul = console_num; |
694 | delay = OCTEON_CONSOLE_POLL_INTERVAL_MS; |
695 | schedule_delayed_work(dwork: work, delay: msecs_to_jiffies(m: delay)); |
696 | |
697 | /* an empty string means use default debug console enablement */ |
698 | if (dbg_enb && !dbg_enb[0]) |
699 | dbg_enb = "setenv pci_console_active 1" ; |
700 | if (dbg_enb) |
701 | ret = octeon_console_send_cmd(oct, cmd_str: dbg_enb, wait_hundredths: 2000); |
702 | |
703 | console->active = 1; |
704 | } |
705 | |
706 | return ret; |
707 | } |
708 | |
709 | /* |
710 | * Removes all consoles |
711 | * |
712 | * @param oct octeon device |
713 | */ |
714 | void octeon_remove_consoles(struct octeon_device *oct) |
715 | { |
716 | u32 i; |
717 | struct octeon_console *console; |
718 | |
719 | for (i = 0; i < oct->num_consoles; i++) { |
720 | console = &oct->console[i]; |
721 | |
722 | if (!console->active) |
723 | continue; |
724 | |
725 | cancel_delayed_work_sync(dwork: &oct->console_poll_work[i]. |
726 | work); |
727 | console->addr = 0; |
728 | console->buffer_size = 0; |
729 | console->input_base_addr = 0; |
730 | console->output_base_addr = 0; |
731 | } |
732 | |
733 | oct->num_consoles = 0; |
734 | } |
735 | |
736 | static inline int octeon_console_free_bytes(u32 buffer_size, |
737 | u32 wr_idx, |
738 | u32 rd_idx) |
739 | { |
740 | if (rd_idx >= buffer_size || wr_idx >= buffer_size) |
741 | return -1; |
742 | |
743 | return ((buffer_size - 1) - (wr_idx - rd_idx)) % buffer_size; |
744 | } |
745 | |
746 | static inline int octeon_console_avail_bytes(u32 buffer_size, |
747 | u32 wr_idx, |
748 | u32 rd_idx) |
749 | { |
750 | if (rd_idx >= buffer_size || wr_idx >= buffer_size) |
751 | return -1; |
752 | |
753 | return buffer_size - 1 - |
754 | octeon_console_free_bytes(buffer_size, wr_idx, rd_idx); |
755 | } |
756 | |
757 | static int octeon_console_read(struct octeon_device *oct, u32 console_num, |
758 | char *buffer, u32 buf_size) |
759 | { |
760 | int bytes_to_read; |
761 | u32 rd_idx, wr_idx; |
762 | struct octeon_console *console; |
763 | |
764 | if (console_num >= oct->num_consoles) { |
765 | dev_err(&oct->pci_dev->dev, "Attempted to read from disabled console %d\n" , |
766 | console_num); |
767 | return 0; |
768 | } |
769 | |
770 | console = &oct->console[console_num]; |
771 | |
772 | /* Check to see if any data is available. |
773 | * Maybe optimize this with 64-bit read. |
774 | */ |
775 | rd_idx = octeon_read_device_mem32(oct, core_addr: console->addr + |
776 | offsetof(struct octeon_pci_console, output_read_index)); |
777 | wr_idx = octeon_read_device_mem32(oct, core_addr: console->addr + |
778 | offsetof(struct octeon_pci_console, output_write_index)); |
779 | |
780 | bytes_to_read = octeon_console_avail_bytes(buffer_size: console->buffer_size, |
781 | wr_idx, rd_idx); |
782 | if (bytes_to_read <= 0) |
783 | return bytes_to_read; |
784 | |
785 | bytes_to_read = min_t(s32, bytes_to_read, buf_size); |
786 | |
787 | /* Check to see if what we want to read is not contiguous, and limit |
788 | * ourselves to the contiguous block |
789 | */ |
790 | if (rd_idx + bytes_to_read >= console->buffer_size) |
791 | bytes_to_read = console->buffer_size - rd_idx; |
792 | |
793 | octeon_pci_read_core_mem(oct, coreaddr: console->output_base_addr + rd_idx, |
794 | buf: (u8 *)buffer, len: bytes_to_read); |
795 | octeon_write_device_mem32(oct, core_addr: console->addr + |
796 | offsetof(struct octeon_pci_console, |
797 | output_read_index), |
798 | val: (rd_idx + bytes_to_read) % |
799 | console->buffer_size); |
800 | |
801 | return bytes_to_read; |
802 | } |
803 | |
804 | #define FBUF_SIZE (4 * 1024 * 1024) |
805 | #define MAX_BOOTTIME_SIZE 80 |
806 | |
807 | int octeon_download_firmware(struct octeon_device *oct, const u8 *data, |
808 | size_t size) |
809 | { |
810 | struct octeon_firmware_file_header *h; |
811 | char boottime[MAX_BOOTTIME_SIZE]; |
812 | struct timespec64 ts; |
813 | u32 crc32_result; |
814 | u64 load_addr; |
815 | u32 image_len; |
816 | int ret = 0; |
817 | u32 i, rem; |
818 | |
819 | if (size < sizeof(struct octeon_firmware_file_header)) { |
820 | dev_err(&oct->pci_dev->dev, "Firmware file too small (%d < %d).\n" , |
821 | (u32)size, |
822 | (u32)sizeof(struct octeon_firmware_file_header)); |
823 | return -EINVAL; |
824 | } |
825 | |
826 | h = (struct octeon_firmware_file_header *)data; |
827 | |
828 | if (be32_to_cpu(h->magic) != LIO_NIC_MAGIC) { |
829 | dev_err(&oct->pci_dev->dev, "Unrecognized firmware file.\n" ); |
830 | return -EINVAL; |
831 | } |
832 | |
833 | crc32_result = crc32((unsigned int)~0, data, |
834 | sizeof(struct octeon_firmware_file_header) - |
835 | sizeof(u32)) ^ ~0U; |
836 | if (crc32_result != be32_to_cpu(h->crc32)) { |
837 | dev_err(&oct->pci_dev->dev, "Firmware CRC mismatch (0x%08x != 0x%08x).\n" , |
838 | crc32_result, be32_to_cpu(h->crc32)); |
839 | return -EINVAL; |
840 | } |
841 | |
842 | if (memcmp(LIQUIDIO_BASE_VERSION, q: h->version, |
843 | strlen(LIQUIDIO_BASE_VERSION))) { |
844 | dev_err(&oct->pci_dev->dev, "Unmatched firmware version. Expected %s.x, got %s.\n" , |
845 | LIQUIDIO_BASE_VERSION, |
846 | h->version); |
847 | return -EINVAL; |
848 | } |
849 | |
850 | if (be32_to_cpu(h->num_images) > LIO_MAX_IMAGES) { |
851 | dev_err(&oct->pci_dev->dev, "Too many images in firmware file (%d).\n" , |
852 | be32_to_cpu(h->num_images)); |
853 | return -EINVAL; |
854 | } |
855 | |
856 | dev_info(&oct->pci_dev->dev, "Firmware version: %s\n" , h->version); |
857 | snprintf(buf: oct->fw_info.liquidio_firmware_version, size: 32, fmt: "LIQUIDIO: %s" , |
858 | h->version); |
859 | |
860 | data += sizeof(struct octeon_firmware_file_header); |
861 | |
862 | dev_info(&oct->pci_dev->dev, "%s: Loading %d images\n" , __func__, |
863 | be32_to_cpu(h->num_images)); |
864 | /* load all images */ |
865 | for (i = 0; i < be32_to_cpu(h->num_images); i++) { |
866 | load_addr = be64_to_cpu(h->desc[i].addr); |
867 | image_len = be32_to_cpu(h->desc[i].len); |
868 | |
869 | dev_info(&oct->pci_dev->dev, "Loading firmware %d at %llx\n" , |
870 | image_len, load_addr); |
871 | |
872 | /* Write in 4MB chunks*/ |
873 | rem = image_len; |
874 | |
875 | while (rem) { |
876 | if (rem < FBUF_SIZE) |
877 | size = rem; |
878 | else |
879 | size = FBUF_SIZE; |
880 | |
881 | /* download the image */ |
882 | octeon_pci_write_core_mem(oct, coreaddr: load_addr, buf: data, len: (u32)size); |
883 | |
884 | data += size; |
885 | rem -= (u32)size; |
886 | load_addr += size; |
887 | } |
888 | } |
889 | |
890 | /* Pass date and time information to NIC at the time of loading |
891 | * firmware and periodically update the host time to NIC firmware. |
892 | * This is to make NIC firmware use the same time reference as Host, |
893 | * so that it is easy to correlate logs from firmware and host for |
894 | * debugging. |
895 | * |
896 | * Octeon always uses UTC time. so timezone information is not sent. |
897 | */ |
898 | ktime_get_real_ts64(tv: &ts); |
899 | ret = snprintf(buf: boottime, MAX_BOOTTIME_SIZE, |
900 | fmt: " time_sec=%lld time_nsec=%ld" , |
901 | (s64)ts.tv_sec, ts.tv_nsec); |
902 | if ((sizeof(h->bootcmd) - strnlen(p: h->bootcmd, maxlen: sizeof(h->bootcmd))) < |
903 | ret) { |
904 | dev_err(&oct->pci_dev->dev, "Boot command buffer too small\n" ); |
905 | return -EINVAL; |
906 | } |
907 | strncat(p: h->bootcmd, q: boottime, |
908 | count: sizeof(h->bootcmd) - strnlen(p: h->bootcmd, maxlen: sizeof(h->bootcmd))); |
909 | |
910 | dev_info(&oct->pci_dev->dev, "Writing boot command: %s\n" , |
911 | h->bootcmd); |
912 | |
913 | /* Invoke the bootcmd */ |
914 | ret = octeon_console_send_cmd(oct, cmd_str: h->bootcmd, wait_hundredths: 50); |
915 | if (ret) |
916 | dev_info(&oct->pci_dev->dev, "Boot command send failed\n" ); |
917 | |
918 | return ret; |
919 | } |
920 | |