linux/drivers/infiniband/hw/hfi1/firmware.c

// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
 * Copyright(c) 2015 - 2017 Intel Corporation.
 */

#include <linux/firmware.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/crc32.h>

#include "hfi.h"
#include "trace.h"

/*
 * Make it easy to toggle firmware file name and if it gets loaded by
 * editing the following. This may be something we do while in development
 * but not necessarily something a user would ever need to use.
 */
#define DEFAULT_FW_8051_NAME_FPGA
#define DEFAULT_FW_8051_NAME_ASIC
#define DEFAULT_FW_FABRIC_NAME
#define DEFAULT_FW_SBUS_NAME
#define DEFAULT_FW_PCIE_NAME
#define ALT_FW_8051_NAME_ASIC
#define ALT_FW_FABRIC_NAME
#define ALT_FW_SBUS_NAME
#define ALT_FW_PCIE_NAME

MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();

static uint fw_8051_load =;
static uint fw_fabric_serdes_load =;
static uint fw_pcie_serdes_load =;
static uint fw_sbus_load =;

/* Firmware file names get set in hfi1_firmware_init() based on the above */
static char *fw_8051_name;
static char *fw_fabric_serdes_name;
static char *fw_sbus_name;
static char *fw_pcie_serdes_name;

#define SBUS_MAX_POLL_COUNT
#define SBUS_COUNTER(reg, name)

/*
 * Firmware security header.
 */
struct css_header {};

/* expected field values */
#define CSS_MODULE_TYPE
#define CSS_HEADER_LEN
#define CSS_HEADER_VERSION
#define CSS_MODULE_VENDOR

#define KEY_SIZE
#define MU_SIZE
#define EXPONENT_SIZE

/* size of platform configuration partition */
#define MAX_PLATFORM_CONFIG_FILE_SIZE

/* size of file of plaform configuration encoded in format version 4 */
#define PLATFORM_CONFIG_FORMAT_4_FILE_SIZE

/* the file itself */
struct firmware_file {};

struct augmented_firmware_file {};

/* augmented file size difference */
#define AUGMENT_SIZE

struct firmware_details {};

/*
 * The mutex protects fw_state, fw_err, and all of the firmware_details
 * variables.
 */
static DEFINE_MUTEX(fw_mutex);
enum fw_state {};

static enum fw_state fw_state =;
static int fw_err;
static struct firmware_details fw_8051;
static struct firmware_details fw_fabric;
static struct firmware_details fw_pcie;
static struct firmware_details fw_sbus;

/* flags for turn_off_spicos() */
#define SPICO_SBUS
#define SPICO_FABRIC
#define ENABLE_SPICO_SMASK

/* security block commands */
#define RSA_CMD_INIT
#define RSA_CMD_START

/* security block status */
#define RSA_STATUS_IDLE
#define RSA_STATUS_ACTIVE
#define RSA_STATUS_DONE
#define RSA_STATUS_FAILED

/* RSA engine timeout, in ms */
#define RSA_ENGINE_TIMEOUT

/* hardware mutex timeout, in ms */
#define HM_TIMEOUT

/* 8051 memory access timeout, in us */
#define DC8051_ACCESS_TIMEOUT

/* the number of fabric SerDes on the SBus */
#define NUM_FABRIC_SERDES

/* ASIC_STS_SBUS_RESULT.RESULT_CODE value */
#define SBUS_READ_COMPLETE

/* SBus fabric SerDes addresses, one set per HFI */
static const u8 fabric_serdes_addrs[2][NUM_FABRIC_SERDES] =;

/* SBus PCIe SerDes addresses, one set per HFI */
static const u8 pcie_serdes_addrs[2][NUM_PCIE_SERDES] =;

/* SBus PCIe PCS addresses, one set per HFI */
const u8 pcie_pcs_addrs[2][NUM_PCIE_SERDES] =;

/* SBus fabric SerDes broadcast addresses, one per HFI */
static const u8 fabric_serdes_broadcast[2] =;
static const u8 all_fabric_serdes_broadcast =;

/* SBus PCIe SerDes broadcast addresses, one per HFI */
const u8 pcie_serdes_broadcast[2] =;
static const u8 all_pcie_serdes_broadcast =;

static const u32 platform_config_table_limits[PLATFORM_CONFIG_TABLE_MAX] =;

/* forwards */
static void dispose_one_firmware(struct firmware_details *fdet);
static int load_fabric_serdes_firmware(struct hfi1_devdata *dd,
				       struct firmware_details *fdet);
static void dump_fw_version(struct hfi1_devdata *dd);

/*
 * Read a single 64-bit value from 8051 data memory.
 *
 * Expects:
 * o caller to have already set up data read, no auto increment
 * o caller to turn off read enable when finished
 *
 * The address argument is a byte offset.  Bits 0:2 in the address are
 * ignored - i.e. the hardware will always do aligned 8-byte reads as if
 * the lower bits are zero.
 *
 * Return 0 on success, -ENXIO on a read error (timeout).
 */
static int __read_8051_data(struct hfi1_devdata *dd, u32 addr, u64 *result)
{}

/*
 * Read 8051 data starting at addr, for len bytes.  Will read in 8-byte chunks.
 * Return 0 on success, -errno on error.
 */
int read_8051_data(struct hfi1_devdata *dd, u32 addr, u32 len, u64 *result)
{}

/*
 * Write data or code to the 8051 code or data RAM.
 */
static int write_8051(struct hfi1_devdata *dd, int code, u32 start,
		      const u8 *data, u32 len)
{}

/* return 0 if values match, non-zero and complain otherwise */
static int invalid_header(struct hfi1_devdata *dd, const char *what,
			  u32 actual, u32 expected)
{}

/*
 * Verify that the static fields in the CSS header match.
 */
static int verify_css_header(struct hfi1_devdata *dd, struct css_header *css)
{}

/*
 * Make sure there are at least some bytes after the prefix.
 */
static int payload_check(struct hfi1_devdata *dd, const char *name,
			 long file_size, long prefix_size)
{}

/*
 * Request the firmware from the system.  Extract the pieces and fill in
 * fdet.  If successful, the caller will need to call dispose_one_firmware().
 * Returns 0 on success, -ERRNO on error.
 */
static int obtain_one_firmware(struct hfi1_devdata *dd, const char *name,
			       struct firmware_details *fdet)
{}

static void dispose_one_firmware(struct firmware_details *fdet)
{}

/*
 * Obtain the 4 firmwares from the OS.  All must be obtained at once or not
 * at all.  If called with the firmware state in FW_TRY, use alternate names.
 * On exit, this routine will have set the firmware state to one of FW_TRY,
 * FW_FINAL, or FW_ERR.
 *
 * Must be holding fw_mutex.
 */
static void __obtain_firmware(struct hfi1_devdata *dd)
{}

/*
 * Called by all HFIs when loading their firmware - i.e. device probe time.
 * The first one will do the actual firmware load.  Use a mutex to resolve
 * any possible race condition.
 *
 * The call to this routine cannot be moved to driver load because the kernel
 * call request_firmware() requires a device which is only available after
 * the first device probe.
 */
static int obtain_firmware(struct hfi1_devdata *dd)
{}

/*
 * Called when the driver unloads.  The timing is asymmetric with its
 * counterpart, obtain_firmware().  If called at device remove time,
 * then it is conceivable that another device could probe while the
 * firmware is being disposed.  The mutexes can be moved to do that
 * safely, but then the firmware would be requested from the OS multiple
 * times.
 *
 * No mutex is needed as the driver is unloading and there cannot be any
 * other callers.
 */
void dispose_firmware(void)
{}

/*
 * Called with the result of a firmware download.
 *
 * Return 1 to retry loading the firmware, 0 to stop.
 */
static int retry_firmware(struct hfi1_devdata *dd, int load_result)
{}

/*
 * Write a block of data to a given array CSR.  All calls will be in
 * multiples of 8 bytes.
 */
static void write_rsa_data(struct hfi1_devdata *dd, int what,
			   const u8 *data, int nbytes)
{}

/*
 * Write a block of data to a given CSR as a stream of writes.  All calls will
 * be in multiples of 8 bytes.
 */
static void write_streamed_rsa_data(struct hfi1_devdata *dd, int what,
				    const u8 *data, int nbytes)
{}

/*
 * Download the signature and start the RSA mechanism.  Wait for
 * RSA_ENGINE_TIMEOUT before giving up.
 */
static int run_rsa(struct hfi1_devdata *dd, const char *who,
		   const u8 *signature)
{}

static void load_security_variables(struct hfi1_devdata *dd,
				    struct firmware_details *fdet)
{}

/* return the 8051 firmware state */
static inline u32 get_firmware_state(struct hfi1_devdata *dd)
{}

/*
 * Wait until the firmware is up and ready to take host requests.
 * Return 0 on success, -ETIMEDOUT on timeout.
 */
int wait_fm_ready(struct hfi1_devdata *dd, u32 mstimeout)
{}

/*
 * Load the 8051 firmware.
 */
static int load_8051_firmware(struct hfi1_devdata *dd,
			      struct firmware_details *fdet)
{}

/*
 * Write the SBus request register
 *
 * No need for masking - the arguments are sized exactly.
 */
void sbus_request(struct hfi1_devdata *dd,
		  u8 receiver_addr, u8 data_addr, u8 command, u32 data_in)
{}

/*
 * Read a value from the SBus.
 *
 * Requires the caller to be in fast mode
 */
static u32 sbus_read(struct hfi1_devdata *dd, u8 receiver_addr, u8 data_addr,
		     u32 data_in)
{}

/*
 * Turn off the SBus and fabric serdes spicos.
 *
 * + Must be called with Sbus fast mode turned on.
 * + Must be called after fabric serdes broadcast is set up.
 * + Must be called before the 8051 is loaded - assumes 8051 is not loaded
 *   when using MISC_CFG_FW_CTRL.
 */
static void turn_off_spicos(struct hfi1_devdata *dd, int flags)
{}

/*
 * Reset all of the fabric serdes for this HFI in preparation to take the
 * link to Polling.
 *
 * To do a reset, we need to write to the serdes registers.  Unfortunately,
 * the fabric serdes download to the other HFI on the ASIC will have turned
 * off the firmware validation on this HFI.  This means we can't write to the
 * registers to reset the serdes.  Work around this by performing a complete
 * re-download and validation of the fabric serdes firmware.  This, as a
 * by-product, will reset the serdes.  NOTE: the re-download requires that
 * the 8051 be in the Offline state.  I.e. not actively trying to use the
 * serdes.  This routine is called at the point where the link is Offline and
 * is getting ready to go to Polling.
 */
void fabric_serdes_reset(struct hfi1_devdata *dd)
{}

/* Access to the SBus in this routine should probably be serialized */
int sbus_request_slow(struct hfi1_devdata *dd,
		      u8 receiver_addr, u8 data_addr, u8 command, u32 data_in)
{}

static int load_fabric_serdes_firmware(struct hfi1_devdata *dd,
				       struct firmware_details *fdet)
{}

static int load_sbus_firmware(struct hfi1_devdata *dd,
			      struct firmware_details *fdet)
{}

static int load_pcie_serdes_firmware(struct hfi1_devdata *dd,
				     struct firmware_details *fdet)
{}

/*
 * Set the given broadcast values on the given list of devices.
 */
static void set_serdes_broadcast(struct hfi1_devdata *dd, u8 bg1, u8 bg2,
				 const u8 *addrs, int count)
{}

int acquire_hw_mutex(struct hfi1_devdata *dd)
{}

void release_hw_mutex(struct hfi1_devdata *dd)
{}

/* return the given resource bit(s) as a mask for the given HFI */
static inline u64 resource_mask(u32 hfi1_id, u32 resource)
{}

static void fail_mutex_acquire_message(struct hfi1_devdata *dd,
				       const char *func)
{}

/*
 * Acquire access to a chip resource.
 *
 * Return 0 on success, -EBUSY if resource busy, -EIO if mutex acquire failed.
 */
static int __acquire_chip_resource(struct hfi1_devdata *dd, u32 resource)
{}

/*
 * Acquire access to a chip resource, wait up to mswait milliseconds for
 * the resource to become available.
 *
 * Return 0 on success, -EBUSY if busy (even after wait), -EIO if mutex
 * acquire failed.
 */
int acquire_chip_resource(struct hfi1_devdata *dd, u32 resource, u32 mswait)
{}

/*
 * Release access to a chip resource
 */
void release_chip_resource(struct hfi1_devdata *dd, u32 resource)
{}

/*
 * Return true if resource is set, false otherwise.  Print a warning
 * if not set and a function is supplied.
 */
bool check_chip_resource(struct hfi1_devdata *dd, u32 resource,
			 const char *func)
{}

static void clear_chip_resources(struct hfi1_devdata *dd, const char *func)
{}

void init_chip_resources(struct hfi1_devdata *dd)
{}

void finish_chip_resources(struct hfi1_devdata *dd)
{}

void set_sbus_fast_mode(struct hfi1_devdata *dd)
{}

void clear_sbus_fast_mode(struct hfi1_devdata *dd)
{}

int load_firmware(struct hfi1_devdata *dd)
{}

int hfi1_firmware_init(struct hfi1_devdata *dd)
{}

/*
 * This function is a helper function for parse_platform_config(...) and
 * does not check for validity of the platform configuration cache
 * (because we know it is invalid as we are building up the cache).
 * As such, this should not be called from anywhere other than
 * parse_platform_config
 */
static int check_meta_version(struct hfi1_devdata *dd, u32 *system_table)
{}

int parse_platform_config(struct hfi1_devdata *dd)
{}

static void get_integrated_platform_config_field(
		struct hfi1_devdata *dd,
		enum platform_config_table_type_encoding table_type,
		int field_index, u32 *data)
{}

static int get_platform_fw_field_metadata(struct hfi1_devdata *dd, int table,
					  int field, u32 *field_len_bits,
					  u32 *field_start_bits)
{}

/* This is the central interface to getting data out of the platform config
 * file. It depends on parse_platform_config() having populated the
 * platform_config_cache in hfi1_devdata, and checks the cache_valid member to
 * validate the sanity of the cache.
 *
 * The non-obvious parameters:
 * @table_index: Acts as a look up key into which instance of the tables the
 * relevant field is fetched from.
 *
 * This applies to the data tables that have multiple instances. The port table
 * is an exception to this rule as each HFI only has one port and thus the
 * relevant table can be distinguished by hfi_id.
 *
 * @data: pointer to memory that will be populated with the field requested.
 * @len: length of memory pointed by @data in bytes.
 */
int get_platform_config_field(struct hfi1_devdata *dd,
			      enum platform_config_table_type_encoding
			      table_type, int table_index, int field_index,
			      u32 *data, u32 len)
{}

/*
 * Download the firmware needed for the Gen3 PCIe SerDes.  An update
 * to the SBus firmware is needed before updating the PCIe firmware.
 *
 * Note: caller must be holding the SBus resource.
 */
int load_pcie_firmware(struct hfi1_devdata *dd)
{}

/*
 * Read the GUID from the hardware, store it in dd.
 */
void read_guid(struct hfi1_devdata *dd)
{}

/* read and display firmware version info */
static void dump_fw_version(struct hfi1_devdata *dd)
{}