brintos

brintos / linux-shallow public Read only

0
0
Text · 24.9 KiB · 67c3570 Raw
920 lines · c
1/**********************************************************************2 * Author: Cavium, Inc.3 *4 * Contact: support@cavium.com5 *          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 modify10 * it under the terms of the GNU General Public License, Version 2, as11 * published by the Free Software Foundation.12 *13 * This file is distributed in the hope that it will be useful, but14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or16 * NONINFRINGEMENT.  See the GNU General Public License for more details.17 ***********************************************************************/18/*19 * @file octeon_console.c20 */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 33static void octeon_remote_lock(void);34static void octeon_remote_unlock(void);35static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct,36					     const char *name,37					     u32 flags);38static 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    0x0006c00842#define BOOTLOADER_PCI_READ_BUFFER_LEN_ADDR     0x0006c00443#define BOOTLOADER_PCI_READ_BUFFER_OWNER_ADDR   0x0006c00044#define BOOTLOADER_PCI_READ_DESC_ADDR           0x0006c10045#define BOOTLOADER_PCI_WRITE_BUFFER_STR_LEN     24846 47#define OCTEON_PCI_IO_BUF_OWNER_OCTEON    0x0000000148#define OCTEON_PCI_IO_BUF_OWNER_HOST      0x0000000249 50/** Can change without breaking ABI */51#define CVMX_BOOTMEM_NUM_NAMED_BLOCKS 6452 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   358/* CVMX bootmem descriptor minor version */59#define CVMX_BOOTMEM_DESC_MIN_VER   060 61/* Current versions */62#define OCTEON_PCI_CONSOLE_MAJOR_VERSION    163#define OCTEON_PCI_CONSOLE_MINOR_VERSION    064#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 original68 * positions for backwards compatibility.69 * Assumes big endian target70 */71struct 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 incremented85	 */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 */106struct 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 information118 * about all PCI consoles.  The address of this structure is passed to various119 * routines that operation on PCI consoles.120 */121struct 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 defined136 * for individual structure members. The argument are generated137 * by the macros inorder to read only the needed memory.138 *139 * @param oct    Pointer to current octeon device140 * @param base   64bit physical address of the complete structure141 * @param offset Offset from the beginning of the structure to the member being142 *               accessed.143 * @param size   Size of the structure member.144 *145 * @return Value of the structure member promoted into a u64.146 */147static 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, base);156	case 8:157		return octeon_read_device_mem64(oct, base);158	default:159		return 0;160	}161}162 163/*164 * This function retrieves the string name of a named block. It is165 * more complicated than a simple memcpy() since the named block166 * descriptor may not be directly accessible.167 *168 * @param addr   Physical address of the named block descriptor169 * @param str    String to receive the named block string name170 * @param len    Length of the string buffer, which must match the length171 *               stored in the bootmem descriptor.172 */173static 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, addr, (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 descriptor187 *188 * @param exact_match189 *               Exact major version to check against. A zero means190 *               check that the version supports named blocks.191 *192 * @return Zero if the version is correct. Negative if the version is193 *         incorrect. Failures also cause a message to be displayed.194 */195static 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, 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, 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 227static const struct cvmx_bootmem_named_block_desc228*__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, 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, 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 257static 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, 3)) {264		u32 i;265 266		u64 named_block_array_addr = __cvmx_bootmem_desc_get(267					oct, 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, 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, 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, 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(name_length + 1, GFP_KERNEL);301				if (!name_tmp)302					break;303 304				CVMX_BOOTMEM_NAMED_GET_NAME(oct, named_addr,305							    name_tmp,306							    name_length);307				if (!strncmp(name, name_tmp, name_length)) {308					result = named_addr;309					kfree(name_tmp);310					break;311				}312				kfree(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 Octeon327 *328 * @param name      Name of block to find329 * @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 */334static 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, 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 350static void octeon_remote_lock(void)351{352	/* fill this in if any sharing is needed */353}354 355static void octeon_remote_unlock(void)356{357	/* fill this in if any sharing is needed */358}359 360int 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_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				  (u8 *)cmd_str, len);382	octeon_write_device_mem32(oct, BOOTLOADER_PCI_READ_BUFFER_LEN_ADDR,383				  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 quickly388	 * if it really was ready389	 */390	if (octeon_wait_for_bootloader(oct, 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 399int 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 419static 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 429static char console_buffer[OCTEON_CONSOLE_MAX_READ_BYTES];430 431static 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 to448			 * output 'leftover' by itself (in the case of nothing449			 * 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 478static 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 will494		 * be logged495		 */496		bytes_read =497			octeon_console_read(oct, console_num, console_buffer,498					    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 any517	 */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->leftover, (s32)(len + 1));525		console->leftover[0] = '\0';526	}527 528	delay = OCTEON_CONSOLE_POLL_INTERVAL_MS;529 530	schedule_delayed_work(&wk->work, msecs_to_jiffies(delay));531}532 533int 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, &addr,545				      &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 static553	 * mapping to a region of Octeon DRAM that contains the PCI console554	 * 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 = addr560		& ~(OCTEON_BAR1_ENTRY_SIZE - 1ULL);561 562	/* num_consoles > 0, is an indication that the consoles563	 * are accessible564	 */565	oct->num_consoles = octeon_read_device_mem32(oct,566		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 576static 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 512586	buf = kmalloc(OCTEON_UBOOT_VER_BUF_SIZE, GFP_KERNEL);587	if (!buf)588		return;589 590	if (octeon_console_send_cmd(oct, "setenv stdout pci\n", 50)) {591		kfree(buf);592		return;593	}594 595	if (octeon_console_send_cmd(oct, "version\n", 1)) {596		kfree(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 will606		 * be logged607		 */608		bytes_read =609			octeon_console_read(oct,610					    console_num, 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 any629	 */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(buf);649	octeon_console_send_cmd(oct, "setenv stdout serial\n", 50);650}651 652int 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, coreaddr);674		coreaddr = console->addr + offsetof(struct octeon_pci_console,675						    buf_size);676		console->buffer_size = octeon_read_device_mem32(oct, 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, 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, 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(work, msecs_to_jiffies(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, dbg_enb, 2000);702 703		console->active = 1;704	}705 706	return ret;707}708 709/*710 * Removes all consoles711 *712 * @param oct         octeon device713 */714void 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(&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 736static 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 746static 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 757static 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, console->addr +776		offsetof(struct octeon_pci_console, output_read_index));777	wr_idx = octeon_read_device_mem32(oct, console->addr +778		offsetof(struct octeon_pci_console, output_write_index));779 780	bytes_to_read = octeon_console_avail_bytes(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 limit788	 * ourselves to the contiguous block789	 */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, console->output_base_addr + rd_idx,794				 (u8 *)buffer, bytes_to_read);795	octeon_write_device_mem32(oct, console->addr +796				  offsetof(struct octeon_pci_console,797					   output_read_index),798				  (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    80806 807int 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, 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(oct->fw_info.liquidio_firmware_version, 32, "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			else879				size = FBUF_SIZE;880 881			/* download the image */882			octeon_pci_write_core_mem(oct, load_addr, data, (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 loading891	 * 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 for894	 * debugging.895	 *896	 * Octeon always uses UTC time. so timezone information is not sent.897	 */898	ktime_get_real_ts64(&ts);899	ret = snprintf(boottime, MAX_BOOTTIME_SIZE,900		       " time_sec=%lld time_nsec=%ld",901		       (s64)ts.tv_sec, ts.tv_nsec);902	if ((sizeof(h->bootcmd) - strnlen(h->bootcmd, sizeof(h->bootcmd))) <903		ret) {904		dev_err(&oct->pci_dev->dev, "Boot command buffer too small\n");905		return -EINVAL;906	}907	strncat(h->bootcmd, boottime,908		sizeof(h->bootcmd) - strnlen(h->bootcmd, 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, h->bootcmd, 50);915	if (ret)916		dev_info(&oct->pci_dev->dev, "Boot command send failed\n");917 918	return ret;919}920