18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2005 - 2016 Broadcom
48c2ecf20Sopenharmony_ci * All rights reserved.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Contact Information:
78c2ecf20Sopenharmony_ci * linux-drivers@emulex.com
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Emulex
108c2ecf20Sopenharmony_ci * 3333 Susan Street
118c2ecf20Sopenharmony_ci * Costa Mesa, CA 92626
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include "be.h"
168c2ecf20Sopenharmony_ci#include "be_cmds.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ciconst char * const be_misconfig_evt_port_state[] = {
198c2ecf20Sopenharmony_ci	"Physical Link is functional",
208c2ecf20Sopenharmony_ci	"Optics faulted/incorrectly installed/not installed - Reseat optics. If issue not resolved, replace.",
218c2ecf20Sopenharmony_ci	"Optics of two types installed – Remove one optic or install matching pair of optics.",
228c2ecf20Sopenharmony_ci	"Incompatible optics – Replace with compatible optics for card to function.",
238c2ecf20Sopenharmony_ci	"Unqualified optics – Replace with Avago optics for Warranty and Technical Support.",
248c2ecf20Sopenharmony_ci	"Uncertified optics – Replace with Avago-certified optics to enable link operation."
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic char *be_port_misconfig_evt_severity[] = {
288c2ecf20Sopenharmony_ci	"KERN_WARN",
298c2ecf20Sopenharmony_ci	"KERN_INFO",
308c2ecf20Sopenharmony_ci	"KERN_ERR",
318c2ecf20Sopenharmony_ci	"KERN_WARN"
328c2ecf20Sopenharmony_ci};
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic char *phy_state_oper_desc[] = {
358c2ecf20Sopenharmony_ci	"Link is non-operational",
368c2ecf20Sopenharmony_ci	"Link is operational",
378c2ecf20Sopenharmony_ci	""
388c2ecf20Sopenharmony_ci};
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic struct be_cmd_priv_map cmd_priv_map[] = {
418c2ecf20Sopenharmony_ci	{
428c2ecf20Sopenharmony_ci		OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
438c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_ETH,
448c2ecf20Sopenharmony_ci		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
458c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
468c2ecf20Sopenharmony_ci	},
478c2ecf20Sopenharmony_ci	{
488c2ecf20Sopenharmony_ci		OPCODE_COMMON_GET_FLOW_CONTROL,
498c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
508c2ecf20Sopenharmony_ci		BE_PRIV_LNKQUERY | BE_PRIV_VHADM |
518c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
528c2ecf20Sopenharmony_ci	},
538c2ecf20Sopenharmony_ci	{
548c2ecf20Sopenharmony_ci		OPCODE_COMMON_SET_FLOW_CONTROL,
558c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
568c2ecf20Sopenharmony_ci		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
578c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
588c2ecf20Sopenharmony_ci	},
598c2ecf20Sopenharmony_ci	{
608c2ecf20Sopenharmony_ci		OPCODE_ETH_GET_PPORT_STATS,
618c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_ETH,
628c2ecf20Sopenharmony_ci		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
638c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
648c2ecf20Sopenharmony_ci	},
658c2ecf20Sopenharmony_ci	{
668c2ecf20Sopenharmony_ci		OPCODE_COMMON_GET_PHY_DETAILS,
678c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
688c2ecf20Sopenharmony_ci		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
698c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
708c2ecf20Sopenharmony_ci	},
718c2ecf20Sopenharmony_ci	{
728c2ecf20Sopenharmony_ci		OPCODE_LOWLEVEL_HOST_DDR_DMA,
738c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_LOWLEVEL,
748c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
758c2ecf20Sopenharmony_ci	},
768c2ecf20Sopenharmony_ci	{
778c2ecf20Sopenharmony_ci		OPCODE_LOWLEVEL_LOOPBACK_TEST,
788c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_LOWLEVEL,
798c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
808c2ecf20Sopenharmony_ci	},
818c2ecf20Sopenharmony_ci	{
828c2ecf20Sopenharmony_ci		OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
838c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_LOWLEVEL,
848c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
858c2ecf20Sopenharmony_ci	},
868c2ecf20Sopenharmony_ci	{
878c2ecf20Sopenharmony_ci		OPCODE_COMMON_SET_HSW_CONFIG,
888c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
898c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_VHADM |
908c2ecf20Sopenharmony_ci		BE_PRIV_DEVSEC
918c2ecf20Sopenharmony_ci	},
928c2ecf20Sopenharmony_ci	{
938c2ecf20Sopenharmony_ci		OPCODE_COMMON_GET_EXT_FAT_CAPABILITIES,
948c2ecf20Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
958c2ecf20Sopenharmony_ci		BE_PRIV_DEVCFG
968c2ecf20Sopenharmony_ci	}
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, u8 subsystem)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	int i;
1028c2ecf20Sopenharmony_ci	int num_entries = ARRAY_SIZE(cmd_priv_map);
1038c2ecf20Sopenharmony_ci	u32 cmd_privileges = adapter->cmd_privileges;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	for (i = 0; i < num_entries; i++)
1068c2ecf20Sopenharmony_ci		if (opcode == cmd_priv_map[i].opcode &&
1078c2ecf20Sopenharmony_ci		    subsystem == cmd_priv_map[i].subsystem)
1088c2ecf20Sopenharmony_ci			if (!(cmd_privileges & cmd_priv_map[i].priv_mask))
1098c2ecf20Sopenharmony_ci				return false;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	return true;
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistatic inline void *embedded_payload(struct be_mcc_wrb *wrb)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	return wrb->payload.embedded_payload;
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistatic int be_mcc_notify(struct be_adapter *adapter)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	struct be_queue_info *mccq = &adapter->mcc_obj.q;
1228c2ecf20Sopenharmony_ci	u32 val = 0;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	if (be_check_error(adapter, BE_ERROR_ANY))
1258c2ecf20Sopenharmony_ci		return -EIO;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	val |= mccq->id & DB_MCCQ_RING_ID_MASK;
1288c2ecf20Sopenharmony_ci	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	wmb();
1318c2ecf20Sopenharmony_ci	iowrite32(val, adapter->db + DB_MCCQ_OFFSET);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	return 0;
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci/* To check if valid bit is set, check the entire word as we don't know
1378c2ecf20Sopenharmony_ci * the endianness of the data (old entry is host endian while a new entry is
1388c2ecf20Sopenharmony_ci * little endian) */
1398c2ecf20Sopenharmony_cistatic inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	u32 flags;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	if (compl->flags != 0) {
1448c2ecf20Sopenharmony_ci		flags = le32_to_cpu(compl->flags);
1458c2ecf20Sopenharmony_ci		if (flags & CQE_FLAGS_VALID_MASK) {
1468c2ecf20Sopenharmony_ci			compl->flags = flags;
1478c2ecf20Sopenharmony_ci			return true;
1488c2ecf20Sopenharmony_ci		}
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci	return false;
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/* Need to reset the entire word that houses the valid bit */
1548c2ecf20Sopenharmony_cistatic inline void be_mcc_compl_use(struct be_mcc_compl *compl)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	compl->flags = 0;
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cistatic struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	unsigned long addr;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	addr = tag1;
1648c2ecf20Sopenharmony_ci	addr = ((addr << 16) << 16) | tag0;
1658c2ecf20Sopenharmony_ci	return (void *)addr;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	if (base_status == MCC_STATUS_NOT_SUPPORTED ||
1718c2ecf20Sopenharmony_ci	    base_status == MCC_STATUS_ILLEGAL_REQUEST ||
1728c2ecf20Sopenharmony_ci	    addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES ||
1738c2ecf20Sopenharmony_ci	    addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS ||
1748c2ecf20Sopenharmony_ci	    (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
1758c2ecf20Sopenharmony_ci	    (base_status == MCC_STATUS_ILLEGAL_FIELD ||
1768c2ecf20Sopenharmony_ci	     addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH)))
1778c2ecf20Sopenharmony_ci		return true;
1788c2ecf20Sopenharmony_ci	else
1798c2ecf20Sopenharmony_ci		return false;
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci/* Place holder for all the async MCC cmds wherein the caller is not in a busy
1838c2ecf20Sopenharmony_ci * loop (has not issued be_mcc_notify_wait())
1848c2ecf20Sopenharmony_ci */
1858c2ecf20Sopenharmony_cistatic void be_async_cmd_process(struct be_adapter *adapter,
1868c2ecf20Sopenharmony_ci				 struct be_mcc_compl *compl,
1878c2ecf20Sopenharmony_ci				 struct be_cmd_resp_hdr *resp_hdr)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	enum mcc_base_status base_status = base_status(compl->status);
1908c2ecf20Sopenharmony_ci	u8 opcode = 0, subsystem = 0;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	if (resp_hdr) {
1938c2ecf20Sopenharmony_ci		opcode = resp_hdr->opcode;
1948c2ecf20Sopenharmony_ci		subsystem = resp_hdr->subsystem;
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
1988c2ecf20Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
1998c2ecf20Sopenharmony_ci		complete(&adapter->et_cmd_compl);
2008c2ecf20Sopenharmony_ci		return;
2018c2ecf20Sopenharmony_ci	}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	if (opcode == OPCODE_LOWLEVEL_SET_LOOPBACK_MODE &&
2048c2ecf20Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
2058c2ecf20Sopenharmony_ci		complete(&adapter->et_cmd_compl);
2068c2ecf20Sopenharmony_ci		return;
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	if ((opcode == OPCODE_COMMON_WRITE_FLASHROM ||
2108c2ecf20Sopenharmony_ci	     opcode == OPCODE_COMMON_WRITE_OBJECT) &&
2118c2ecf20Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_COMMON) {
2128c2ecf20Sopenharmony_ci		adapter->flash_status = compl->status;
2138c2ecf20Sopenharmony_ci		complete(&adapter->et_cmd_compl);
2148c2ecf20Sopenharmony_ci		return;
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	if ((opcode == OPCODE_ETH_GET_STATISTICS ||
2188c2ecf20Sopenharmony_ci	     opcode == OPCODE_ETH_GET_PPORT_STATS) &&
2198c2ecf20Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_ETH &&
2208c2ecf20Sopenharmony_ci	    base_status == MCC_STATUS_SUCCESS) {
2218c2ecf20Sopenharmony_ci		be_parse_stats(adapter);
2228c2ecf20Sopenharmony_ci		adapter->stats_cmd_sent = false;
2238c2ecf20Sopenharmony_ci		return;
2248c2ecf20Sopenharmony_ci	}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
2278c2ecf20Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_COMMON) {
2288c2ecf20Sopenharmony_ci		if (base_status == MCC_STATUS_SUCCESS) {
2298c2ecf20Sopenharmony_ci			struct be_cmd_resp_get_cntl_addnl_attribs *resp =
2308c2ecf20Sopenharmony_ci							(void *)resp_hdr;
2318c2ecf20Sopenharmony_ci			adapter->hwmon_info.be_on_die_temp =
2328c2ecf20Sopenharmony_ci						resp->on_die_temperature;
2338c2ecf20Sopenharmony_ci		} else {
2348c2ecf20Sopenharmony_ci			adapter->be_get_temp_freq = 0;
2358c2ecf20Sopenharmony_ci			adapter->hwmon_info.be_on_die_temp =
2368c2ecf20Sopenharmony_ci						BE_INVALID_DIE_TEMP;
2378c2ecf20Sopenharmony_ci		}
2388c2ecf20Sopenharmony_ci		return;
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic int be_mcc_compl_process(struct be_adapter *adapter,
2438c2ecf20Sopenharmony_ci				struct be_mcc_compl *compl)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	enum mcc_base_status base_status;
2468c2ecf20Sopenharmony_ci	enum mcc_addl_status addl_status;
2478c2ecf20Sopenharmony_ci	struct be_cmd_resp_hdr *resp_hdr;
2488c2ecf20Sopenharmony_ci	u8 opcode = 0, subsystem = 0;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	/* Just swap the status to host endian; mcc tag is opaquely copied
2518c2ecf20Sopenharmony_ci	 * from mcc_wrb */
2528c2ecf20Sopenharmony_ci	be_dws_le_to_cpu(compl, 4);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	base_status = base_status(compl->status);
2558c2ecf20Sopenharmony_ci	addl_status = addl_status(compl->status);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
2588c2ecf20Sopenharmony_ci	if (resp_hdr) {
2598c2ecf20Sopenharmony_ci		opcode = resp_hdr->opcode;
2608c2ecf20Sopenharmony_ci		subsystem = resp_hdr->subsystem;
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	be_async_cmd_process(adapter, compl, resp_hdr);
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	if (base_status != MCC_STATUS_SUCCESS &&
2668c2ecf20Sopenharmony_ci	    !be_skip_err_log(opcode, base_status, addl_status)) {
2678c2ecf20Sopenharmony_ci		if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST ||
2688c2ecf20Sopenharmony_ci		    addl_status == MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES) {
2698c2ecf20Sopenharmony_ci			dev_warn(&adapter->pdev->dev,
2708c2ecf20Sopenharmony_ci				 "VF is not privileged to issue opcode %d-%d\n",
2718c2ecf20Sopenharmony_ci				 opcode, subsystem);
2728c2ecf20Sopenharmony_ci		} else {
2738c2ecf20Sopenharmony_ci			dev_err(&adapter->pdev->dev,
2748c2ecf20Sopenharmony_ci				"opcode %d-%d failed:status %d-%d\n",
2758c2ecf20Sopenharmony_ci				opcode, subsystem, base_status, addl_status);
2768c2ecf20Sopenharmony_ci		}
2778c2ecf20Sopenharmony_ci	}
2788c2ecf20Sopenharmony_ci	return compl->status;
2798c2ecf20Sopenharmony_ci}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci/* Link state evt is a string of bytes; no need for endian swapping */
2828c2ecf20Sopenharmony_cistatic void be_async_link_state_process(struct be_adapter *adapter,
2838c2ecf20Sopenharmony_ci					struct be_mcc_compl *compl)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	struct be_async_event_link_state *evt =
2868c2ecf20Sopenharmony_ci			(struct be_async_event_link_state *)compl;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	/* When link status changes, link speed must be re-queried from FW */
2898c2ecf20Sopenharmony_ci	adapter->phy.link_speed = -1;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	/* On BEx the FW does not send a separate link status
2928c2ecf20Sopenharmony_ci	 * notification for physical and logical link.
2938c2ecf20Sopenharmony_ci	 * On other chips just process the logical link
2948c2ecf20Sopenharmony_ci	 * status notification
2958c2ecf20Sopenharmony_ci	 */
2968c2ecf20Sopenharmony_ci	if (!BEx_chip(adapter) &&
2978c2ecf20Sopenharmony_ci	    !(evt->port_link_status & LOGICAL_LINK_STATUS_MASK))
2988c2ecf20Sopenharmony_ci		return;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	/* For the initial link status do not rely on the ASYNC event as
3018c2ecf20Sopenharmony_ci	 * it may not be received in some cases.
3028c2ecf20Sopenharmony_ci	 */
3038c2ecf20Sopenharmony_ci	if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
3048c2ecf20Sopenharmony_ci		be_link_status_update(adapter,
3058c2ecf20Sopenharmony_ci				      evt->port_link_status & LINK_STATUS_MASK);
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistatic void be_async_port_misconfig_event_process(struct be_adapter *adapter,
3098c2ecf20Sopenharmony_ci						  struct be_mcc_compl *compl)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	struct be_async_event_misconfig_port *evt =
3128c2ecf20Sopenharmony_ci			(struct be_async_event_misconfig_port *)compl;
3138c2ecf20Sopenharmony_ci	u32 sfp_misconfig_evt_word1 = le32_to_cpu(evt->event_data_word1);
3148c2ecf20Sopenharmony_ci	u32 sfp_misconfig_evt_word2 = le32_to_cpu(evt->event_data_word2);
3158c2ecf20Sopenharmony_ci	u8 phy_oper_state = PHY_STATE_OPER_MSG_NONE;
3168c2ecf20Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
3178c2ecf20Sopenharmony_ci	u8 msg_severity = DEFAULT_MSG_SEVERITY;
3188c2ecf20Sopenharmony_ci	u8 phy_state_info;
3198c2ecf20Sopenharmony_ci	u8 new_phy_state;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	new_phy_state =
3228c2ecf20Sopenharmony_ci		(sfp_misconfig_evt_word1 >> (adapter->hba_port_num * 8)) & 0xff;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	if (new_phy_state == adapter->phy_state)
3258c2ecf20Sopenharmony_ci		return;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	adapter->phy_state = new_phy_state;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	/* for older fw that doesn't populate link effect data */
3308c2ecf20Sopenharmony_ci	if (!sfp_misconfig_evt_word2)
3318c2ecf20Sopenharmony_ci		goto log_message;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	phy_state_info =
3348c2ecf20Sopenharmony_ci		(sfp_misconfig_evt_word2 >> (adapter->hba_port_num * 8)) & 0xff;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	if (phy_state_info & PHY_STATE_INFO_VALID) {
3378c2ecf20Sopenharmony_ci		msg_severity = (phy_state_info & PHY_STATE_MSG_SEVERITY) >> 1;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci		if (be_phy_unqualified(new_phy_state))
3408c2ecf20Sopenharmony_ci			phy_oper_state = (phy_state_info & PHY_STATE_OPER);
3418c2ecf20Sopenharmony_ci	}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cilog_message:
3448c2ecf20Sopenharmony_ci	/* Log an error message that would allow a user to determine
3458c2ecf20Sopenharmony_ci	 * whether the SFPs have an issue
3468c2ecf20Sopenharmony_ci	 */
3478c2ecf20Sopenharmony_ci	if (be_phy_state_unknown(new_phy_state))
3488c2ecf20Sopenharmony_ci		dev_printk(be_port_misconfig_evt_severity[msg_severity], dev,
3498c2ecf20Sopenharmony_ci			   "Port %c: Unrecognized Optics state: 0x%x. %s",
3508c2ecf20Sopenharmony_ci			   adapter->port_name,
3518c2ecf20Sopenharmony_ci			   new_phy_state,
3528c2ecf20Sopenharmony_ci			   phy_state_oper_desc[phy_oper_state]);
3538c2ecf20Sopenharmony_ci	else
3548c2ecf20Sopenharmony_ci		dev_printk(be_port_misconfig_evt_severity[msg_severity], dev,
3558c2ecf20Sopenharmony_ci			   "Port %c: %s %s",
3568c2ecf20Sopenharmony_ci			   adapter->port_name,
3578c2ecf20Sopenharmony_ci			   be_misconfig_evt_port_state[new_phy_state],
3588c2ecf20Sopenharmony_ci			   phy_state_oper_desc[phy_oper_state]);
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	/* Log Vendor name and part no. if a misconfigured SFP is detected */
3618c2ecf20Sopenharmony_ci	if (be_phy_misconfigured(new_phy_state))
3628c2ecf20Sopenharmony_ci		adapter->flags |= BE_FLAGS_PHY_MISCONFIGURED;
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci/* Grp5 CoS Priority evt */
3668c2ecf20Sopenharmony_cistatic void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
3678c2ecf20Sopenharmony_ci					       struct be_mcc_compl *compl)
3688c2ecf20Sopenharmony_ci{
3698c2ecf20Sopenharmony_ci	struct be_async_event_grp5_cos_priority *evt =
3708c2ecf20Sopenharmony_ci			(struct be_async_event_grp5_cos_priority *)compl;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	if (evt->valid) {
3738c2ecf20Sopenharmony_ci		adapter->vlan_prio_bmap = evt->available_priority_bmap;
3748c2ecf20Sopenharmony_ci		adapter->recommended_prio_bits =
3758c2ecf20Sopenharmony_ci			evt->reco_default_priority << VLAN_PRIO_SHIFT;
3768c2ecf20Sopenharmony_ci	}
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci/* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */
3808c2ecf20Sopenharmony_cistatic void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
3818c2ecf20Sopenharmony_ci					    struct be_mcc_compl *compl)
3828c2ecf20Sopenharmony_ci{
3838c2ecf20Sopenharmony_ci	struct be_async_event_grp5_qos_link_speed *evt =
3848c2ecf20Sopenharmony_ci			(struct be_async_event_grp5_qos_link_speed *)compl;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	if (adapter->phy.link_speed >= 0 &&
3878c2ecf20Sopenharmony_ci	    evt->physical_port == adapter->port_num)
3888c2ecf20Sopenharmony_ci		adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10;
3898c2ecf20Sopenharmony_ci}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci/*Grp5 PVID evt*/
3928c2ecf20Sopenharmony_cistatic void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
3938c2ecf20Sopenharmony_ci					     struct be_mcc_compl *compl)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	struct be_async_event_grp5_pvid_state *evt =
3968c2ecf20Sopenharmony_ci			(struct be_async_event_grp5_pvid_state *)compl;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	if (evt->enabled) {
3998c2ecf20Sopenharmony_ci		adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
4008c2ecf20Sopenharmony_ci		dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid);
4018c2ecf20Sopenharmony_ci	} else {
4028c2ecf20Sopenharmony_ci		adapter->pvid = 0;
4038c2ecf20Sopenharmony_ci	}
4048c2ecf20Sopenharmony_ci}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci#define MGMT_ENABLE_MASK	0x4
4078c2ecf20Sopenharmony_cistatic void be_async_grp5_fw_control_process(struct be_adapter *adapter,
4088c2ecf20Sopenharmony_ci					     struct be_mcc_compl *compl)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	struct be_async_fw_control *evt = (struct be_async_fw_control *)compl;
4118c2ecf20Sopenharmony_ci	u32 evt_dw1 = le32_to_cpu(evt->event_data_word1);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	if (evt_dw1 & MGMT_ENABLE_MASK) {
4148c2ecf20Sopenharmony_ci		adapter->flags |= BE_FLAGS_OS2BMC;
4158c2ecf20Sopenharmony_ci		adapter->bmc_filt_mask = le32_to_cpu(evt->event_data_word2);
4168c2ecf20Sopenharmony_ci	} else {
4178c2ecf20Sopenharmony_ci		adapter->flags &= ~BE_FLAGS_OS2BMC;
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic void be_async_grp5_evt_process(struct be_adapter *adapter,
4228c2ecf20Sopenharmony_ci				      struct be_mcc_compl *compl)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) &
4258c2ecf20Sopenharmony_ci				ASYNC_EVENT_TYPE_MASK;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	switch (event_type) {
4288c2ecf20Sopenharmony_ci	case ASYNC_EVENT_COS_PRIORITY:
4298c2ecf20Sopenharmony_ci		be_async_grp5_cos_priority_process(adapter, compl);
4308c2ecf20Sopenharmony_ci		break;
4318c2ecf20Sopenharmony_ci	case ASYNC_EVENT_QOS_SPEED:
4328c2ecf20Sopenharmony_ci		be_async_grp5_qos_speed_process(adapter, compl);
4338c2ecf20Sopenharmony_ci		break;
4348c2ecf20Sopenharmony_ci	case ASYNC_EVENT_PVID_STATE:
4358c2ecf20Sopenharmony_ci		be_async_grp5_pvid_state_process(adapter, compl);
4368c2ecf20Sopenharmony_ci		break;
4378c2ecf20Sopenharmony_ci	/* Async event to disable/enable os2bmc and/or mac-learning */
4388c2ecf20Sopenharmony_ci	case ASYNC_EVENT_FW_CONTROL:
4398c2ecf20Sopenharmony_ci		be_async_grp5_fw_control_process(adapter, compl);
4408c2ecf20Sopenharmony_ci		break;
4418c2ecf20Sopenharmony_ci	default:
4428c2ecf20Sopenharmony_ci		break;
4438c2ecf20Sopenharmony_ci	}
4448c2ecf20Sopenharmony_ci}
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_cistatic void be_async_dbg_evt_process(struct be_adapter *adapter,
4478c2ecf20Sopenharmony_ci				     struct be_mcc_compl *cmp)
4488c2ecf20Sopenharmony_ci{
4498c2ecf20Sopenharmony_ci	u8 event_type = 0;
4508c2ecf20Sopenharmony_ci	struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
4538c2ecf20Sopenharmony_ci			ASYNC_EVENT_TYPE_MASK;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	switch (event_type) {
4568c2ecf20Sopenharmony_ci	case ASYNC_DEBUG_EVENT_TYPE_QNQ:
4578c2ecf20Sopenharmony_ci		if (evt->valid)
4588c2ecf20Sopenharmony_ci			adapter->qnq_vid = le16_to_cpu(evt->vlan_tag);
4598c2ecf20Sopenharmony_ci		adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
4608c2ecf20Sopenharmony_ci	break;
4618c2ecf20Sopenharmony_ci	default:
4628c2ecf20Sopenharmony_ci		dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n",
4638c2ecf20Sopenharmony_ci			 event_type);
4648c2ecf20Sopenharmony_ci	break;
4658c2ecf20Sopenharmony_ci	}
4668c2ecf20Sopenharmony_ci}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_cistatic void be_async_sliport_evt_process(struct be_adapter *adapter,
4698c2ecf20Sopenharmony_ci					 struct be_mcc_compl *cmp)
4708c2ecf20Sopenharmony_ci{
4718c2ecf20Sopenharmony_ci	u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
4728c2ecf20Sopenharmony_ci			ASYNC_EVENT_TYPE_MASK;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	if (event_type == ASYNC_EVENT_PORT_MISCONFIG)
4758c2ecf20Sopenharmony_ci		be_async_port_misconfig_event_process(adapter, cmp);
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_cistatic inline bool is_link_state_evt(u32 flags)
4798c2ecf20Sopenharmony_ci{
4808c2ecf20Sopenharmony_ci	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4818c2ecf20Sopenharmony_ci			ASYNC_EVENT_CODE_LINK_STATE;
4828c2ecf20Sopenharmony_ci}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_cistatic inline bool is_grp5_evt(u32 flags)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4878c2ecf20Sopenharmony_ci			ASYNC_EVENT_CODE_GRP_5;
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_cistatic inline bool is_dbg_evt(u32 flags)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4938c2ecf20Sopenharmony_ci			ASYNC_EVENT_CODE_QNQ;
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic inline bool is_sliport_evt(u32 flags)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4998c2ecf20Sopenharmony_ci		ASYNC_EVENT_CODE_SLIPORT;
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_cistatic void be_mcc_event_process(struct be_adapter *adapter,
5038c2ecf20Sopenharmony_ci				 struct be_mcc_compl *compl)
5048c2ecf20Sopenharmony_ci{
5058c2ecf20Sopenharmony_ci	if (is_link_state_evt(compl->flags))
5068c2ecf20Sopenharmony_ci		be_async_link_state_process(adapter, compl);
5078c2ecf20Sopenharmony_ci	else if (is_grp5_evt(compl->flags))
5088c2ecf20Sopenharmony_ci		be_async_grp5_evt_process(adapter, compl);
5098c2ecf20Sopenharmony_ci	else if (is_dbg_evt(compl->flags))
5108c2ecf20Sopenharmony_ci		be_async_dbg_evt_process(adapter, compl);
5118c2ecf20Sopenharmony_ci	else if (is_sliport_evt(compl->flags))
5128c2ecf20Sopenharmony_ci		be_async_sliport_evt_process(adapter, compl);
5138c2ecf20Sopenharmony_ci}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_cistatic struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
5168c2ecf20Sopenharmony_ci{
5178c2ecf20Sopenharmony_ci	struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
5188c2ecf20Sopenharmony_ci	struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	if (be_mcc_compl_is_new(compl)) {
5218c2ecf20Sopenharmony_ci		queue_tail_inc(mcc_cq);
5228c2ecf20Sopenharmony_ci		return compl;
5238c2ecf20Sopenharmony_ci	}
5248c2ecf20Sopenharmony_ci	return NULL;
5258c2ecf20Sopenharmony_ci}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_civoid be_async_mcc_enable(struct be_adapter *adapter)
5288c2ecf20Sopenharmony_ci{
5298c2ecf20Sopenharmony_ci	spin_lock_bh(&adapter->mcc_cq_lock);
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0);
5328c2ecf20Sopenharmony_ci	adapter->mcc_obj.rearm_cq = true;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	spin_unlock_bh(&adapter->mcc_cq_lock);
5358c2ecf20Sopenharmony_ci}
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_civoid be_async_mcc_disable(struct be_adapter *adapter)
5388c2ecf20Sopenharmony_ci{
5398c2ecf20Sopenharmony_ci	spin_lock_bh(&adapter->mcc_cq_lock);
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	adapter->mcc_obj.rearm_cq = false;
5428c2ecf20Sopenharmony_ci	be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	spin_unlock_bh(&adapter->mcc_cq_lock);
5458c2ecf20Sopenharmony_ci}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ciint be_process_mcc(struct be_adapter *adapter)
5488c2ecf20Sopenharmony_ci{
5498c2ecf20Sopenharmony_ci	struct be_mcc_compl *compl;
5508c2ecf20Sopenharmony_ci	int num = 0, status = 0;
5518c2ecf20Sopenharmony_ci	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	spin_lock(&adapter->mcc_cq_lock);
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	while ((compl = be_mcc_compl_get(adapter))) {
5568c2ecf20Sopenharmony_ci		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
5578c2ecf20Sopenharmony_ci			be_mcc_event_process(adapter, compl);
5588c2ecf20Sopenharmony_ci		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
5598c2ecf20Sopenharmony_ci			status = be_mcc_compl_process(adapter, compl);
5608c2ecf20Sopenharmony_ci			atomic_dec(&mcc_obj->q.used);
5618c2ecf20Sopenharmony_ci		}
5628c2ecf20Sopenharmony_ci		be_mcc_compl_use(compl);
5638c2ecf20Sopenharmony_ci		num++;
5648c2ecf20Sopenharmony_ci	}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	if (num)
5678c2ecf20Sopenharmony_ci		be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	spin_unlock(&adapter->mcc_cq_lock);
5708c2ecf20Sopenharmony_ci	return status;
5718c2ecf20Sopenharmony_ci}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci/* Wait till no more pending mcc requests are present */
5748c2ecf20Sopenharmony_cistatic int be_mcc_wait_compl(struct be_adapter *adapter)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci#define mcc_timeout		12000 /* 12s timeout */
5778c2ecf20Sopenharmony_ci	int i, status = 0;
5788c2ecf20Sopenharmony_ci	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	for (i = 0; i < mcc_timeout; i++) {
5818c2ecf20Sopenharmony_ci		if (be_check_error(adapter, BE_ERROR_ANY))
5828c2ecf20Sopenharmony_ci			return -EIO;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci		local_bh_disable();
5858c2ecf20Sopenharmony_ci		status = be_process_mcc(adapter);
5868c2ecf20Sopenharmony_ci		local_bh_enable();
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci		if (atomic_read(&mcc_obj->q.used) == 0)
5898c2ecf20Sopenharmony_ci			break;
5908c2ecf20Sopenharmony_ci		usleep_range(500, 1000);
5918c2ecf20Sopenharmony_ci	}
5928c2ecf20Sopenharmony_ci	if (i == mcc_timeout) {
5938c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev, "FW not responding\n");
5948c2ecf20Sopenharmony_ci		be_set_error(adapter, BE_ERROR_FW);
5958c2ecf20Sopenharmony_ci		return -EIO;
5968c2ecf20Sopenharmony_ci	}
5978c2ecf20Sopenharmony_ci	return status;
5988c2ecf20Sopenharmony_ci}
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci/* Notify MCC requests and wait for completion */
6018c2ecf20Sopenharmony_cistatic int be_mcc_notify_wait(struct be_adapter *adapter)
6028c2ecf20Sopenharmony_ci{
6038c2ecf20Sopenharmony_ci	int status;
6048c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
6058c2ecf20Sopenharmony_ci	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
6068c2ecf20Sopenharmony_ci	u32 index = mcc_obj->q.head;
6078c2ecf20Sopenharmony_ci	struct be_cmd_resp_hdr *resp;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	index_dec(&index, mcc_obj->q.len);
6108c2ecf20Sopenharmony_ci	wrb = queue_index_node(&mcc_obj->q, index);
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	status = be_mcc_notify(adapter);
6158c2ecf20Sopenharmony_ci	if (status)
6168c2ecf20Sopenharmony_ci		goto out;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	status = be_mcc_wait_compl(adapter);
6198c2ecf20Sopenharmony_ci	if (status == -EIO)
6208c2ecf20Sopenharmony_ci		goto out;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	status = (resp->base_status |
6238c2ecf20Sopenharmony_ci		  ((resp->addl_status & CQE_ADDL_STATUS_MASK) <<
6248c2ecf20Sopenharmony_ci		   CQE_ADDL_STATUS_SHIFT));
6258c2ecf20Sopenharmony_ciout:
6268c2ecf20Sopenharmony_ci	return status;
6278c2ecf20Sopenharmony_ci}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_cistatic int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
6308c2ecf20Sopenharmony_ci{
6318c2ecf20Sopenharmony_ci	int msecs = 0;
6328c2ecf20Sopenharmony_ci	u32 ready;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	do {
6358c2ecf20Sopenharmony_ci		if (be_check_error(adapter, BE_ERROR_ANY))
6368c2ecf20Sopenharmony_ci			return -EIO;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci		ready = ioread32(db);
6398c2ecf20Sopenharmony_ci		if (ready == 0xffffffff)
6408c2ecf20Sopenharmony_ci			return -1;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci		ready &= MPU_MAILBOX_DB_RDY_MASK;
6438c2ecf20Sopenharmony_ci		if (ready)
6448c2ecf20Sopenharmony_ci			break;
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci		if (msecs > 4000) {
6478c2ecf20Sopenharmony_ci			dev_err(&adapter->pdev->dev, "FW not responding\n");
6488c2ecf20Sopenharmony_ci			be_set_error(adapter, BE_ERROR_FW);
6498c2ecf20Sopenharmony_ci			be_detect_error(adapter);
6508c2ecf20Sopenharmony_ci			return -1;
6518c2ecf20Sopenharmony_ci		}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci		msleep(1);
6548c2ecf20Sopenharmony_ci		msecs++;
6558c2ecf20Sopenharmony_ci	} while (true);
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	return 0;
6588c2ecf20Sopenharmony_ci}
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci/*
6618c2ecf20Sopenharmony_ci * Insert the mailbox address into the doorbell in two steps
6628c2ecf20Sopenharmony_ci * Polls on the mbox doorbell till a command completion (or a timeout) occurs
6638c2ecf20Sopenharmony_ci */
6648c2ecf20Sopenharmony_cistatic int be_mbox_notify_wait(struct be_adapter *adapter)
6658c2ecf20Sopenharmony_ci{
6668c2ecf20Sopenharmony_ci	int status;
6678c2ecf20Sopenharmony_ci	u32 val = 0;
6688c2ecf20Sopenharmony_ci	void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET;
6698c2ecf20Sopenharmony_ci	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
6708c2ecf20Sopenharmony_ci	struct be_mcc_mailbox *mbox = mbox_mem->va;
6718c2ecf20Sopenharmony_ci	struct be_mcc_compl *compl = &mbox->compl;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	/* wait for ready to be set */
6748c2ecf20Sopenharmony_ci	status = be_mbox_db_ready_wait(adapter, db);
6758c2ecf20Sopenharmony_ci	if (status != 0)
6768c2ecf20Sopenharmony_ci		return status;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	val |= MPU_MAILBOX_DB_HI_MASK;
6798c2ecf20Sopenharmony_ci	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
6808c2ecf20Sopenharmony_ci	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
6818c2ecf20Sopenharmony_ci	iowrite32(val, db);
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	/* wait for ready to be set */
6848c2ecf20Sopenharmony_ci	status = be_mbox_db_ready_wait(adapter, db);
6858c2ecf20Sopenharmony_ci	if (status != 0)
6868c2ecf20Sopenharmony_ci		return status;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	val = 0;
6898c2ecf20Sopenharmony_ci	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
6908c2ecf20Sopenharmony_ci	val |= (u32)(mbox_mem->dma >> 4) << 2;
6918c2ecf20Sopenharmony_ci	iowrite32(val, db);
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	status = be_mbox_db_ready_wait(adapter, db);
6948c2ecf20Sopenharmony_ci	if (status != 0)
6958c2ecf20Sopenharmony_ci		return status;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	/* A cq entry has been made now */
6988c2ecf20Sopenharmony_ci	if (be_mcc_compl_is_new(compl)) {
6998c2ecf20Sopenharmony_ci		status = be_mcc_compl_process(adapter, &mbox->compl);
7008c2ecf20Sopenharmony_ci		be_mcc_compl_use(compl);
7018c2ecf20Sopenharmony_ci		if (status)
7028c2ecf20Sopenharmony_ci			return status;
7038c2ecf20Sopenharmony_ci	} else {
7048c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev, "invalid mailbox completion\n");
7058c2ecf20Sopenharmony_ci		return -1;
7068c2ecf20Sopenharmony_ci	}
7078c2ecf20Sopenharmony_ci	return 0;
7088c2ecf20Sopenharmony_ci}
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ciu16 be_POST_stage_get(struct be_adapter *adapter)
7118c2ecf20Sopenharmony_ci{
7128c2ecf20Sopenharmony_ci	u32 sem;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	if (BEx_chip(adapter))
7158c2ecf20Sopenharmony_ci		sem  = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx);
7168c2ecf20Sopenharmony_ci	else
7178c2ecf20Sopenharmony_ci		pci_read_config_dword(adapter->pdev,
7188c2ecf20Sopenharmony_ci				      SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	return sem & POST_STAGE_MASK;
7218c2ecf20Sopenharmony_ci}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_cistatic int lancer_wait_ready(struct be_adapter *adapter)
7248c2ecf20Sopenharmony_ci{
7258c2ecf20Sopenharmony_ci#define SLIPORT_READY_TIMEOUT 30
7268c2ecf20Sopenharmony_ci	u32 sliport_status;
7278c2ecf20Sopenharmony_ci	int i;
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
7308c2ecf20Sopenharmony_ci		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
7318c2ecf20Sopenharmony_ci		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
7328c2ecf20Sopenharmony_ci			return 0;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci		if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
7358c2ecf20Sopenharmony_ci		    !(sliport_status & SLIPORT_STATUS_RN_MASK))
7368c2ecf20Sopenharmony_ci			return -EIO;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci		msleep(1000);
7398c2ecf20Sopenharmony_ci	}
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	return sliport_status ? : -1;
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ciint be_fw_wait_ready(struct be_adapter *adapter)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	u16 stage;
7478c2ecf20Sopenharmony_ci	int status, timeout = 0;
7488c2ecf20Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	if (lancer_chip(adapter)) {
7518c2ecf20Sopenharmony_ci		status = lancer_wait_ready(adapter);
7528c2ecf20Sopenharmony_ci		if (status) {
7538c2ecf20Sopenharmony_ci			stage = status;
7548c2ecf20Sopenharmony_ci			goto err;
7558c2ecf20Sopenharmony_ci		}
7568c2ecf20Sopenharmony_ci		return 0;
7578c2ecf20Sopenharmony_ci	}
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	do {
7608c2ecf20Sopenharmony_ci		/* There's no means to poll POST state on BE2/3 VFs */
7618c2ecf20Sopenharmony_ci		if (BEx_chip(adapter) && be_virtfn(adapter))
7628c2ecf20Sopenharmony_ci			return 0;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci		stage = be_POST_stage_get(adapter);
7658c2ecf20Sopenharmony_ci		if (stage == POST_STAGE_ARMFW_RDY)
7668c2ecf20Sopenharmony_ci			return 0;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci		dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout);
7698c2ecf20Sopenharmony_ci		if (msleep_interruptible(2000)) {
7708c2ecf20Sopenharmony_ci			dev_err(dev, "Waiting for POST aborted\n");
7718c2ecf20Sopenharmony_ci			return -EINTR;
7728c2ecf20Sopenharmony_ci		}
7738c2ecf20Sopenharmony_ci		timeout += 2;
7748c2ecf20Sopenharmony_ci	} while (timeout < 60);
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_cierr:
7778c2ecf20Sopenharmony_ci	dev_err(dev, "POST timeout; stage=%#x\n", stage);
7788c2ecf20Sopenharmony_ci	return -ETIMEDOUT;
7798c2ecf20Sopenharmony_ci}
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_cistatic inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
7828c2ecf20Sopenharmony_ci{
7838c2ecf20Sopenharmony_ci	return &wrb->payload.sgl[0];
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_cistatic inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr)
7878c2ecf20Sopenharmony_ci{
7888c2ecf20Sopenharmony_ci	wrb->tag0 = addr & 0xFFFFFFFF;
7898c2ecf20Sopenharmony_ci	wrb->tag1 = upper_32_bits(addr);
7908c2ecf20Sopenharmony_ci}
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci/* Don't touch the hdr after it's prepared */
7938c2ecf20Sopenharmony_ci/* mem will be NULL for embedded commands */
7948c2ecf20Sopenharmony_cistatic void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
7958c2ecf20Sopenharmony_ci				   u8 subsystem, u8 opcode, int cmd_len,
7968c2ecf20Sopenharmony_ci				   struct be_mcc_wrb *wrb,
7978c2ecf20Sopenharmony_ci				   struct be_dma_mem *mem)
7988c2ecf20Sopenharmony_ci{
7998c2ecf20Sopenharmony_ci	struct be_sge *sge;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	req_hdr->opcode = opcode;
8028c2ecf20Sopenharmony_ci	req_hdr->subsystem = subsystem;
8038c2ecf20Sopenharmony_ci	req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
8048c2ecf20Sopenharmony_ci	req_hdr->version = 0;
8058c2ecf20Sopenharmony_ci	fill_wrb_tags(wrb, (ulong) req_hdr);
8068c2ecf20Sopenharmony_ci	wrb->payload_length = cmd_len;
8078c2ecf20Sopenharmony_ci	if (mem) {
8088c2ecf20Sopenharmony_ci		wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
8098c2ecf20Sopenharmony_ci			MCC_WRB_SGE_CNT_SHIFT;
8108c2ecf20Sopenharmony_ci		sge = nonembedded_sgl(wrb);
8118c2ecf20Sopenharmony_ci		sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
8128c2ecf20Sopenharmony_ci		sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
8138c2ecf20Sopenharmony_ci		sge->len = cpu_to_le32(mem->size);
8148c2ecf20Sopenharmony_ci	} else
8158c2ecf20Sopenharmony_ci		wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
8168c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(wrb, 8);
8178c2ecf20Sopenharmony_ci}
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_cistatic void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
8208c2ecf20Sopenharmony_ci				      struct be_dma_mem *mem)
8218c2ecf20Sopenharmony_ci{
8228c2ecf20Sopenharmony_ci	int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
8238c2ecf20Sopenharmony_ci	u64 dma = (u64)mem->dma;
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	for (i = 0; i < buf_pages; i++) {
8268c2ecf20Sopenharmony_ci		pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
8278c2ecf20Sopenharmony_ci		pages[i].hi = cpu_to_le32(upper_32_bits(dma));
8288c2ecf20Sopenharmony_ci		dma += PAGE_SIZE_4K;
8298c2ecf20Sopenharmony_ci	}
8308c2ecf20Sopenharmony_ci}
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_cistatic inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter)
8338c2ecf20Sopenharmony_ci{
8348c2ecf20Sopenharmony_ci	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
8358c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb
8368c2ecf20Sopenharmony_ci		= &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
8378c2ecf20Sopenharmony_ci	memset(wrb, 0, sizeof(*wrb));
8388c2ecf20Sopenharmony_ci	return wrb;
8398c2ecf20Sopenharmony_ci}
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_cistatic struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
8428c2ecf20Sopenharmony_ci{
8438c2ecf20Sopenharmony_ci	struct be_queue_info *mccq = &adapter->mcc_obj.q;
8448c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	if (!mccq->created)
8478c2ecf20Sopenharmony_ci		return NULL;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (atomic_read(&mccq->used) >= mccq->len)
8508c2ecf20Sopenharmony_ci		return NULL;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	wrb = queue_head_node(mccq);
8538c2ecf20Sopenharmony_ci	queue_head_inc(mccq);
8548c2ecf20Sopenharmony_ci	atomic_inc(&mccq->used);
8558c2ecf20Sopenharmony_ci	memset(wrb, 0, sizeof(*wrb));
8568c2ecf20Sopenharmony_ci	return wrb;
8578c2ecf20Sopenharmony_ci}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_cistatic bool use_mcc(struct be_adapter *adapter)
8608c2ecf20Sopenharmony_ci{
8618c2ecf20Sopenharmony_ci	return adapter->mcc_obj.q.created;
8628c2ecf20Sopenharmony_ci}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci/* Must be used only in process context */
8658c2ecf20Sopenharmony_cistatic int be_cmd_lock(struct be_adapter *adapter)
8668c2ecf20Sopenharmony_ci{
8678c2ecf20Sopenharmony_ci	if (use_mcc(adapter)) {
8688c2ecf20Sopenharmony_ci		mutex_lock(&adapter->mcc_lock);
8698c2ecf20Sopenharmony_ci		return 0;
8708c2ecf20Sopenharmony_ci	} else {
8718c2ecf20Sopenharmony_ci		return mutex_lock_interruptible(&adapter->mbox_lock);
8728c2ecf20Sopenharmony_ci	}
8738c2ecf20Sopenharmony_ci}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci/* Must be used only in process context */
8768c2ecf20Sopenharmony_cistatic void be_cmd_unlock(struct be_adapter *adapter)
8778c2ecf20Sopenharmony_ci{
8788c2ecf20Sopenharmony_ci	if (use_mcc(adapter))
8798c2ecf20Sopenharmony_ci		return mutex_unlock(&adapter->mcc_lock);
8808c2ecf20Sopenharmony_ci	else
8818c2ecf20Sopenharmony_ci		return mutex_unlock(&adapter->mbox_lock);
8828c2ecf20Sopenharmony_ci}
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_cistatic struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter,
8858c2ecf20Sopenharmony_ci				      struct be_mcc_wrb *wrb)
8868c2ecf20Sopenharmony_ci{
8878c2ecf20Sopenharmony_ci	struct be_mcc_wrb *dest_wrb;
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	if (use_mcc(adapter)) {
8908c2ecf20Sopenharmony_ci		dest_wrb = wrb_from_mccq(adapter);
8918c2ecf20Sopenharmony_ci		if (!dest_wrb)
8928c2ecf20Sopenharmony_ci			return NULL;
8938c2ecf20Sopenharmony_ci	} else {
8948c2ecf20Sopenharmony_ci		dest_wrb = wrb_from_mbox(adapter);
8958c2ecf20Sopenharmony_ci	}
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	memcpy(dest_wrb, wrb, sizeof(*wrb));
8988c2ecf20Sopenharmony_ci	if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK))
8998c2ecf20Sopenharmony_ci		fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb));
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	return dest_wrb;
9028c2ecf20Sopenharmony_ci}
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci/* Must be used only in process context */
9058c2ecf20Sopenharmony_cistatic int be_cmd_notify_wait(struct be_adapter *adapter,
9068c2ecf20Sopenharmony_ci			      struct be_mcc_wrb *wrb)
9078c2ecf20Sopenharmony_ci{
9088c2ecf20Sopenharmony_ci	struct be_mcc_wrb *dest_wrb;
9098c2ecf20Sopenharmony_ci	int status;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	status = be_cmd_lock(adapter);
9128c2ecf20Sopenharmony_ci	if (status)
9138c2ecf20Sopenharmony_ci		return status;
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	dest_wrb = be_cmd_copy(adapter, wrb);
9168c2ecf20Sopenharmony_ci	if (!dest_wrb) {
9178c2ecf20Sopenharmony_ci		status = -EBUSY;
9188c2ecf20Sopenharmony_ci		goto unlock;
9198c2ecf20Sopenharmony_ci	}
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	if (use_mcc(adapter))
9228c2ecf20Sopenharmony_ci		status = be_mcc_notify_wait(adapter);
9238c2ecf20Sopenharmony_ci	else
9248c2ecf20Sopenharmony_ci		status = be_mbox_notify_wait(adapter);
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	if (!status)
9278c2ecf20Sopenharmony_ci		memcpy(wrb, dest_wrb, sizeof(*wrb));
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ciunlock:
9308c2ecf20Sopenharmony_ci	be_cmd_unlock(adapter);
9318c2ecf20Sopenharmony_ci	return status;
9328c2ecf20Sopenharmony_ci}
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci/* Tell fw we're about to start firing cmds by writing a
9358c2ecf20Sopenharmony_ci * special pattern across the wrb hdr; uses mbox
9368c2ecf20Sopenharmony_ci */
9378c2ecf20Sopenharmony_ciint be_cmd_fw_init(struct be_adapter *adapter)
9388c2ecf20Sopenharmony_ci{
9398c2ecf20Sopenharmony_ci	u8 *wrb;
9408c2ecf20Sopenharmony_ci	int status;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	if (lancer_chip(adapter))
9438c2ecf20Sopenharmony_ci		return 0;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
9468c2ecf20Sopenharmony_ci		return -1;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	wrb = (u8 *)wrb_from_mbox(adapter);
9498c2ecf20Sopenharmony_ci	*wrb++ = 0xFF;
9508c2ecf20Sopenharmony_ci	*wrb++ = 0x12;
9518c2ecf20Sopenharmony_ci	*wrb++ = 0x34;
9528c2ecf20Sopenharmony_ci	*wrb++ = 0xFF;
9538c2ecf20Sopenharmony_ci	*wrb++ = 0xFF;
9548c2ecf20Sopenharmony_ci	*wrb++ = 0x56;
9558c2ecf20Sopenharmony_ci	*wrb++ = 0x78;
9568c2ecf20Sopenharmony_ci	*wrb = 0xFF;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
9618c2ecf20Sopenharmony_ci	return status;
9628c2ecf20Sopenharmony_ci}
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci/* Tell fw we're done with firing cmds by writing a
9658c2ecf20Sopenharmony_ci * special pattern across the wrb hdr; uses mbox
9668c2ecf20Sopenharmony_ci */
9678c2ecf20Sopenharmony_ciint be_cmd_fw_clean(struct be_adapter *adapter)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	u8 *wrb;
9708c2ecf20Sopenharmony_ci	int status;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	if (lancer_chip(adapter))
9738c2ecf20Sopenharmony_ci		return 0;
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
9768c2ecf20Sopenharmony_ci		return -1;
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	wrb = (u8 *)wrb_from_mbox(adapter);
9798c2ecf20Sopenharmony_ci	*wrb++ = 0xFF;
9808c2ecf20Sopenharmony_ci	*wrb++ = 0xAA;
9818c2ecf20Sopenharmony_ci	*wrb++ = 0xBB;
9828c2ecf20Sopenharmony_ci	*wrb++ = 0xFF;
9838c2ecf20Sopenharmony_ci	*wrb++ = 0xFF;
9848c2ecf20Sopenharmony_ci	*wrb++ = 0xCC;
9858c2ecf20Sopenharmony_ci	*wrb++ = 0xDD;
9868c2ecf20Sopenharmony_ci	*wrb = 0xFF;
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
9918c2ecf20Sopenharmony_ci	return status;
9928c2ecf20Sopenharmony_ci}
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ciint be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo)
9958c2ecf20Sopenharmony_ci{
9968c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
9978c2ecf20Sopenharmony_ci	struct be_cmd_req_eq_create *req;
9988c2ecf20Sopenharmony_ci	struct be_dma_mem *q_mem = &eqo->q.dma_mem;
9998c2ecf20Sopenharmony_ci	int status, ver = 0;
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
10028c2ecf20Sopenharmony_ci		return -1;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
10058c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
10088c2ecf20Sopenharmony_ci			       OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb,
10098c2ecf20Sopenharmony_ci			       NULL);
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	/* Support for EQ_CREATEv2 available only SH-R onwards */
10128c2ecf20Sopenharmony_ci	if (!(BEx_chip(adapter) || lancer_chip(adapter)))
10138c2ecf20Sopenharmony_ci		ver = 2;
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci	req->hdr.version = ver;
10168c2ecf20Sopenharmony_ci	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
10198c2ecf20Sopenharmony_ci	/* 4byte eqe*/
10208c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
10218c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_eq_context, count, req->context,
10228c2ecf20Sopenharmony_ci		      __ilog2_u32(eqo->q.len / 256));
10238c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(req->context, sizeof(req->context));
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
10288c2ecf20Sopenharmony_ci	if (!status) {
10298c2ecf20Sopenharmony_ci		struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci		eqo->q.id = le16_to_cpu(resp->eq_id);
10328c2ecf20Sopenharmony_ci		eqo->msix_idx =
10338c2ecf20Sopenharmony_ci			(ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx;
10348c2ecf20Sopenharmony_ci		eqo->q.created = true;
10358c2ecf20Sopenharmony_ci	}
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
10388c2ecf20Sopenharmony_ci	return status;
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci/* Use MCC */
10428c2ecf20Sopenharmony_ciint be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
10438c2ecf20Sopenharmony_ci			  bool permanent, u32 if_handle, u32 pmac_id)
10448c2ecf20Sopenharmony_ci{
10458c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
10468c2ecf20Sopenharmony_ci	struct be_cmd_req_mac_query *req;
10478c2ecf20Sopenharmony_ci	int status;
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
10528c2ecf20Sopenharmony_ci	if (!wrb) {
10538c2ecf20Sopenharmony_ci		status = -EBUSY;
10548c2ecf20Sopenharmony_ci		goto err;
10558c2ecf20Sopenharmony_ci	}
10568c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
10598c2ecf20Sopenharmony_ci			       OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb,
10608c2ecf20Sopenharmony_ci			       NULL);
10618c2ecf20Sopenharmony_ci	req->type = MAC_ADDRESS_TYPE_NETWORK;
10628c2ecf20Sopenharmony_ci	if (permanent) {
10638c2ecf20Sopenharmony_ci		req->permanent = 1;
10648c2ecf20Sopenharmony_ci	} else {
10658c2ecf20Sopenharmony_ci		req->if_id = cpu_to_le16((u16)if_handle);
10668c2ecf20Sopenharmony_ci		req->pmac_id = cpu_to_le32(pmac_id);
10678c2ecf20Sopenharmony_ci		req->permanent = 0;
10688c2ecf20Sopenharmony_ci	}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
10718c2ecf20Sopenharmony_ci	if (!status) {
10728c2ecf20Sopenharmony_ci		struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
10758c2ecf20Sopenharmony_ci	}
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_cierr:
10788c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
10798c2ecf20Sopenharmony_ci	return status;
10808c2ecf20Sopenharmony_ci}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci/* Uses synchronous MCCQ */
10838c2ecf20Sopenharmony_ciint be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
10848c2ecf20Sopenharmony_ci		    u32 if_id, u32 *pmac_id, u32 domain)
10858c2ecf20Sopenharmony_ci{
10868c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
10878c2ecf20Sopenharmony_ci	struct be_cmd_req_pmac_add *req;
10888c2ecf20Sopenharmony_ci	int status;
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
10938c2ecf20Sopenharmony_ci	if (!wrb) {
10948c2ecf20Sopenharmony_ci		status = -EBUSY;
10958c2ecf20Sopenharmony_ci		goto err;
10968c2ecf20Sopenharmony_ci	}
10978c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
11008c2ecf20Sopenharmony_ci			       OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb,
11018c2ecf20Sopenharmony_ci			       NULL);
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
11048c2ecf20Sopenharmony_ci	req->if_id = cpu_to_le32(if_id);
11058c2ecf20Sopenharmony_ci	memcpy(req->mac_address, mac_addr, ETH_ALEN);
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
11088c2ecf20Sopenharmony_ci	if (!status) {
11098c2ecf20Sopenharmony_ci		struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci		*pmac_id = le32_to_cpu(resp->pmac_id);
11128c2ecf20Sopenharmony_ci	}
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_cierr:
11158c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	 if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST)
11188c2ecf20Sopenharmony_ci		status = -EPERM;
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	return status;
11218c2ecf20Sopenharmony_ci}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci/* Uses synchronous MCCQ */
11248c2ecf20Sopenharmony_ciint be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom)
11258c2ecf20Sopenharmony_ci{
11268c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
11278c2ecf20Sopenharmony_ci	struct be_cmd_req_pmac_del *req;
11288c2ecf20Sopenharmony_ci	int status;
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	if (pmac_id == -1)
11318c2ecf20Sopenharmony_ci		return 0;
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
11368c2ecf20Sopenharmony_ci	if (!wrb) {
11378c2ecf20Sopenharmony_ci		status = -EBUSY;
11388c2ecf20Sopenharmony_ci		goto err;
11398c2ecf20Sopenharmony_ci	}
11408c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
11438c2ecf20Sopenharmony_ci			       OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req),
11448c2ecf20Sopenharmony_ci			       wrb, NULL);
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	req->hdr.domain = dom;
11478c2ecf20Sopenharmony_ci	req->if_id = cpu_to_le32(if_id);
11488c2ecf20Sopenharmony_ci	req->pmac_id = cpu_to_le32(pmac_id);
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_cierr:
11538c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
11548c2ecf20Sopenharmony_ci	return status;
11558c2ecf20Sopenharmony_ci}
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci/* Uses Mbox */
11588c2ecf20Sopenharmony_ciint be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
11598c2ecf20Sopenharmony_ci		     struct be_queue_info *eq, bool no_delay, int coalesce_wm)
11608c2ecf20Sopenharmony_ci{
11618c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
11628c2ecf20Sopenharmony_ci	struct be_cmd_req_cq_create *req;
11638c2ecf20Sopenharmony_ci	struct be_dma_mem *q_mem = &cq->dma_mem;
11648c2ecf20Sopenharmony_ci	void *ctxt;
11658c2ecf20Sopenharmony_ci	int status;
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
11688c2ecf20Sopenharmony_ci		return -1;
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
11718c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
11728c2ecf20Sopenharmony_ci	ctxt = &req->context;
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
11758c2ecf20Sopenharmony_ci			       OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb,
11768c2ecf20Sopenharmony_ci			       NULL);
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	if (BEx_chip(adapter)) {
11818c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
11828c2ecf20Sopenharmony_ci			      coalesce_wm);
11838c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, nodelay,
11848c2ecf20Sopenharmony_ci			      ctxt, no_delay);
11858c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
11868c2ecf20Sopenharmony_ci			      __ilog2_u32(cq->len / 256));
11878c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
11888c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
11898c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
11908c2ecf20Sopenharmony_ci	} else {
11918c2ecf20Sopenharmony_ci		req->hdr.version = 2;
11928c2ecf20Sopenharmony_ci		req->page_size = 1; /* 1 for 4K */
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci		/* coalesce-wm field in this cmd is not relevant to Lancer.
11958c2ecf20Sopenharmony_ci		 * Lancer uses COMMON_MODIFY_CQ to set this field
11968c2ecf20Sopenharmony_ci		 */
11978c2ecf20Sopenharmony_ci		if (!lancer_chip(adapter))
11988c2ecf20Sopenharmony_ci			AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
11998c2ecf20Sopenharmony_ci				      ctxt, coalesce_wm);
12008c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt,
12018c2ecf20Sopenharmony_ci			      no_delay);
12028c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
12038c2ecf20Sopenharmony_ci			      __ilog2_u32(cq->len / 256));
12048c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
12058c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
12068c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
12078c2ecf20Sopenharmony_ci	}
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(ctxt, sizeof(req->context));
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
12148c2ecf20Sopenharmony_ci	if (!status) {
12158c2ecf20Sopenharmony_ci		struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci		cq->id = le16_to_cpu(resp->cq_id);
12188c2ecf20Sopenharmony_ci		cq->created = true;
12198c2ecf20Sopenharmony_ci	}
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci	return status;
12248c2ecf20Sopenharmony_ci}
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_cistatic u32 be_encoded_q_len(int q_len)
12278c2ecf20Sopenharmony_ci{
12288c2ecf20Sopenharmony_ci	u32 len_encoded = fls(q_len); /* log2(len) + 1 */
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	if (len_encoded == 16)
12318c2ecf20Sopenharmony_ci		len_encoded = 0;
12328c2ecf20Sopenharmony_ci	return len_encoded;
12338c2ecf20Sopenharmony_ci}
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_cistatic int be_cmd_mccq_ext_create(struct be_adapter *adapter,
12368c2ecf20Sopenharmony_ci				  struct be_queue_info *mccq,
12378c2ecf20Sopenharmony_ci				  struct be_queue_info *cq)
12388c2ecf20Sopenharmony_ci{
12398c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
12408c2ecf20Sopenharmony_ci	struct be_cmd_req_mcc_ext_create *req;
12418c2ecf20Sopenharmony_ci	struct be_dma_mem *q_mem = &mccq->dma_mem;
12428c2ecf20Sopenharmony_ci	void *ctxt;
12438c2ecf20Sopenharmony_ci	int status;
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
12468c2ecf20Sopenharmony_ci		return -1;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
12498c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
12508c2ecf20Sopenharmony_ci	ctxt = &req->context;
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
12538c2ecf20Sopenharmony_ci			       OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb,
12548c2ecf20Sopenharmony_ci			       NULL);
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
12578c2ecf20Sopenharmony_ci	if (BEx_chip(adapter)) {
12588c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
12598c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
12608c2ecf20Sopenharmony_ci			      be_encoded_q_len(mccq->len));
12618c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
12628c2ecf20Sopenharmony_ci	} else {
12638c2ecf20Sopenharmony_ci		req->hdr.version = 1;
12648c2ecf20Sopenharmony_ci		req->cq_id = cpu_to_le16(cq->id);
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt,
12678c2ecf20Sopenharmony_ci			      be_encoded_q_len(mccq->len));
12688c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1);
12698c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id,
12708c2ecf20Sopenharmony_ci			      ctxt, cq->id);
12718c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid,
12728c2ecf20Sopenharmony_ci			      ctxt, 1);
12738c2ecf20Sopenharmony_ci	}
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci	/* Subscribe to Link State, Sliport Event and Group 5 Events
12768c2ecf20Sopenharmony_ci	 * (bits 1, 5 and 17 set)
12778c2ecf20Sopenharmony_ci	 */
12788c2ecf20Sopenharmony_ci	req->async_event_bitmap[0] =
12798c2ecf20Sopenharmony_ci			cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) |
12808c2ecf20Sopenharmony_ci				    BIT(ASYNC_EVENT_CODE_GRP_5) |
12818c2ecf20Sopenharmony_ci				    BIT(ASYNC_EVENT_CODE_QNQ) |
12828c2ecf20Sopenharmony_ci				    BIT(ASYNC_EVENT_CODE_SLIPORT));
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(ctxt, sizeof(req->context));
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
12898c2ecf20Sopenharmony_ci	if (!status) {
12908c2ecf20Sopenharmony_ci		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci		mccq->id = le16_to_cpu(resp->id);
12938c2ecf20Sopenharmony_ci		mccq->created = true;
12948c2ecf20Sopenharmony_ci	}
12958c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	return status;
12988c2ecf20Sopenharmony_ci}
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_cistatic int be_cmd_mccq_org_create(struct be_adapter *adapter,
13018c2ecf20Sopenharmony_ci				  struct be_queue_info *mccq,
13028c2ecf20Sopenharmony_ci				  struct be_queue_info *cq)
13038c2ecf20Sopenharmony_ci{
13048c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
13058c2ecf20Sopenharmony_ci	struct be_cmd_req_mcc_create *req;
13068c2ecf20Sopenharmony_ci	struct be_dma_mem *q_mem = &mccq->dma_mem;
13078c2ecf20Sopenharmony_ci	void *ctxt;
13088c2ecf20Sopenharmony_ci	int status;
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
13118c2ecf20Sopenharmony_ci		return -1;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
13148c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
13158c2ecf20Sopenharmony_ci	ctxt = &req->context;
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
13188c2ecf20Sopenharmony_ci			       OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb,
13198c2ecf20Sopenharmony_ci			       NULL);
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
13248c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
13258c2ecf20Sopenharmony_ci		      be_encoded_q_len(mccq->len));
13268c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(ctxt, sizeof(req->context));
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
13338c2ecf20Sopenharmony_ci	if (!status) {
13348c2ecf20Sopenharmony_ci		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci		mccq->id = le16_to_cpu(resp->id);
13378c2ecf20Sopenharmony_ci		mccq->created = true;
13388c2ecf20Sopenharmony_ci	}
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
13418c2ecf20Sopenharmony_ci	return status;
13428c2ecf20Sopenharmony_ci}
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ciint be_cmd_mccq_create(struct be_adapter *adapter,
13458c2ecf20Sopenharmony_ci		       struct be_queue_info *mccq, struct be_queue_info *cq)
13468c2ecf20Sopenharmony_ci{
13478c2ecf20Sopenharmony_ci	int status;
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ci	status = be_cmd_mccq_ext_create(adapter, mccq, cq);
13508c2ecf20Sopenharmony_ci	if (status && BEx_chip(adapter)) {
13518c2ecf20Sopenharmony_ci		dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
13528c2ecf20Sopenharmony_ci			"or newer to avoid conflicting priorities between NIC "
13538c2ecf20Sopenharmony_ci			"and FCoE traffic");
13548c2ecf20Sopenharmony_ci		status = be_cmd_mccq_org_create(adapter, mccq, cq);
13558c2ecf20Sopenharmony_ci	}
13568c2ecf20Sopenharmony_ci	return status;
13578c2ecf20Sopenharmony_ci}
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ciint be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo)
13608c2ecf20Sopenharmony_ci{
13618c2ecf20Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
13628c2ecf20Sopenharmony_ci	struct be_cmd_req_eth_tx_create *req;
13638c2ecf20Sopenharmony_ci	struct be_queue_info *txq = &txo->q;
13648c2ecf20Sopenharmony_ci	struct be_queue_info *cq = &txo->cq;
13658c2ecf20Sopenharmony_ci	struct be_dma_mem *q_mem = &txq->dma_mem;
13668c2ecf20Sopenharmony_ci	int status, ver = 0;
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	req = embedded_payload(&wrb);
13698c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
13708c2ecf20Sopenharmony_ci			       OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL);
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	if (lancer_chip(adapter)) {
13738c2ecf20Sopenharmony_ci		req->hdr.version = 1;
13748c2ecf20Sopenharmony_ci	} else if (BEx_chip(adapter)) {
13758c2ecf20Sopenharmony_ci		if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC)
13768c2ecf20Sopenharmony_ci			req->hdr.version = 2;
13778c2ecf20Sopenharmony_ci	} else { /* For SH */
13788c2ecf20Sopenharmony_ci		req->hdr.version = 2;
13798c2ecf20Sopenharmony_ci	}
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	if (req->hdr.version > 0)
13828c2ecf20Sopenharmony_ci		req->if_id = cpu_to_le16(adapter->if_handle);
13838c2ecf20Sopenharmony_ci	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
13848c2ecf20Sopenharmony_ci	req->ulp_num = BE_ULP1_NUM;
13858c2ecf20Sopenharmony_ci	req->type = BE_ETH_TX_RING_TYPE_STANDARD;
13868c2ecf20Sopenharmony_ci	req->cq_id = cpu_to_le16(cq->id);
13878c2ecf20Sopenharmony_ci	req->queue_size = be_encoded_q_len(txq->len);
13888c2ecf20Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
13898c2ecf20Sopenharmony_ci	ver = req->hdr.version;
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
13928c2ecf20Sopenharmony_ci	if (!status) {
13938c2ecf20Sopenharmony_ci		struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb);
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci		txq->id = le16_to_cpu(resp->cid);
13968c2ecf20Sopenharmony_ci		if (ver == 2)
13978c2ecf20Sopenharmony_ci			txo->db_offset = le32_to_cpu(resp->db_offset);
13988c2ecf20Sopenharmony_ci		else
13998c2ecf20Sopenharmony_ci			txo->db_offset = DB_TXULP1_OFFSET;
14008c2ecf20Sopenharmony_ci		txq->created = true;
14018c2ecf20Sopenharmony_ci	}
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci	return status;
14048c2ecf20Sopenharmony_ci}
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_ci/* Uses MCC */
14078c2ecf20Sopenharmony_ciint be_cmd_rxq_create(struct be_adapter *adapter,
14088c2ecf20Sopenharmony_ci		      struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
14098c2ecf20Sopenharmony_ci		      u32 if_id, u32 rss, u8 *rss_id)
14108c2ecf20Sopenharmony_ci{
14118c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
14128c2ecf20Sopenharmony_ci	struct be_cmd_req_eth_rx_create *req;
14138c2ecf20Sopenharmony_ci	struct be_dma_mem *q_mem = &rxq->dma_mem;
14148c2ecf20Sopenharmony_ci	int status;
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
14198c2ecf20Sopenharmony_ci	if (!wrb) {
14208c2ecf20Sopenharmony_ci		status = -EBUSY;
14218c2ecf20Sopenharmony_ci		goto err;
14228c2ecf20Sopenharmony_ci	}
14238c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
14268c2ecf20Sopenharmony_ci			       OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL);
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci	req->cq_id = cpu_to_le16(cq_id);
14298c2ecf20Sopenharmony_ci	req->frag_size = fls(frag_size) - 1;
14308c2ecf20Sopenharmony_ci	req->num_pages = 2;
14318c2ecf20Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
14328c2ecf20Sopenharmony_ci	req->interface_id = cpu_to_le32(if_id);
14338c2ecf20Sopenharmony_ci	req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE);
14348c2ecf20Sopenharmony_ci	req->rss_queue = cpu_to_le32(rss);
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
14378c2ecf20Sopenharmony_ci	if (!status) {
14388c2ecf20Sopenharmony_ci		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci		rxq->id = le16_to_cpu(resp->id);
14418c2ecf20Sopenharmony_ci		rxq->created = true;
14428c2ecf20Sopenharmony_ci		*rss_id = resp->rss_id;
14438c2ecf20Sopenharmony_ci	}
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_cierr:
14468c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
14478c2ecf20Sopenharmony_ci	return status;
14488c2ecf20Sopenharmony_ci}
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci/* Generic destroyer function for all types of queues
14518c2ecf20Sopenharmony_ci * Uses Mbox
14528c2ecf20Sopenharmony_ci */
14538c2ecf20Sopenharmony_ciint be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
14548c2ecf20Sopenharmony_ci		     int queue_type)
14558c2ecf20Sopenharmony_ci{
14568c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
14578c2ecf20Sopenharmony_ci	struct be_cmd_req_q_destroy *req;
14588c2ecf20Sopenharmony_ci	u8 subsys = 0, opcode = 0;
14598c2ecf20Sopenharmony_ci	int status;
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
14628c2ecf20Sopenharmony_ci		return -1;
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
14658c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci	switch (queue_type) {
14688c2ecf20Sopenharmony_ci	case QTYPE_EQ:
14698c2ecf20Sopenharmony_ci		subsys = CMD_SUBSYSTEM_COMMON;
14708c2ecf20Sopenharmony_ci		opcode = OPCODE_COMMON_EQ_DESTROY;
14718c2ecf20Sopenharmony_ci		break;
14728c2ecf20Sopenharmony_ci	case QTYPE_CQ:
14738c2ecf20Sopenharmony_ci		subsys = CMD_SUBSYSTEM_COMMON;
14748c2ecf20Sopenharmony_ci		opcode = OPCODE_COMMON_CQ_DESTROY;
14758c2ecf20Sopenharmony_ci		break;
14768c2ecf20Sopenharmony_ci	case QTYPE_TXQ:
14778c2ecf20Sopenharmony_ci		subsys = CMD_SUBSYSTEM_ETH;
14788c2ecf20Sopenharmony_ci		opcode = OPCODE_ETH_TX_DESTROY;
14798c2ecf20Sopenharmony_ci		break;
14808c2ecf20Sopenharmony_ci	case QTYPE_RXQ:
14818c2ecf20Sopenharmony_ci		subsys = CMD_SUBSYSTEM_ETH;
14828c2ecf20Sopenharmony_ci		opcode = OPCODE_ETH_RX_DESTROY;
14838c2ecf20Sopenharmony_ci		break;
14848c2ecf20Sopenharmony_ci	case QTYPE_MCCQ:
14858c2ecf20Sopenharmony_ci		subsys = CMD_SUBSYSTEM_COMMON;
14868c2ecf20Sopenharmony_ci		opcode = OPCODE_COMMON_MCC_DESTROY;
14878c2ecf20Sopenharmony_ci		break;
14888c2ecf20Sopenharmony_ci	default:
14898c2ecf20Sopenharmony_ci		BUG();
14908c2ecf20Sopenharmony_ci	}
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb,
14938c2ecf20Sopenharmony_ci			       NULL);
14948c2ecf20Sopenharmony_ci	req->id = cpu_to_le16(q->id);
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
14978c2ecf20Sopenharmony_ci	q->created = false;
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
15008c2ecf20Sopenharmony_ci	return status;
15018c2ecf20Sopenharmony_ci}
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci/* Uses MCC */
15048c2ecf20Sopenharmony_ciint be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
15058c2ecf20Sopenharmony_ci{
15068c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
15078c2ecf20Sopenharmony_ci	struct be_cmd_req_q_destroy *req;
15088c2ecf20Sopenharmony_ci	int status;
15098c2ecf20Sopenharmony_ci
15108c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
15138c2ecf20Sopenharmony_ci	if (!wrb) {
15148c2ecf20Sopenharmony_ci		status = -EBUSY;
15158c2ecf20Sopenharmony_ci		goto err;
15168c2ecf20Sopenharmony_ci	}
15178c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
15208c2ecf20Sopenharmony_ci			       OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL);
15218c2ecf20Sopenharmony_ci	req->id = cpu_to_le16(q->id);
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
15248c2ecf20Sopenharmony_ci	q->created = false;
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_cierr:
15278c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
15288c2ecf20Sopenharmony_ci	return status;
15298c2ecf20Sopenharmony_ci}
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci/* Create an rx filtering policy configuration on an i/f
15328c2ecf20Sopenharmony_ci * Will use MBOX only if MCCQ has not been created.
15338c2ecf20Sopenharmony_ci */
15348c2ecf20Sopenharmony_ciint be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
15358c2ecf20Sopenharmony_ci		     u32 *if_handle, u32 domain)
15368c2ecf20Sopenharmony_ci{
15378c2ecf20Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
15388c2ecf20Sopenharmony_ci	struct be_cmd_req_if_create *req;
15398c2ecf20Sopenharmony_ci	int status;
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_ci	req = embedded_payload(&wrb);
15428c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
15438c2ecf20Sopenharmony_ci			       OPCODE_COMMON_NTWK_INTERFACE_CREATE,
15448c2ecf20Sopenharmony_ci			       sizeof(*req), &wrb, NULL);
15458c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
15468c2ecf20Sopenharmony_ci	req->capability_flags = cpu_to_le32(cap_flags);
15478c2ecf20Sopenharmony_ci	req->enable_flags = cpu_to_le32(en_flags);
15488c2ecf20Sopenharmony_ci	req->pmac_invalid = true;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
15518c2ecf20Sopenharmony_ci	if (!status) {
15528c2ecf20Sopenharmony_ci		struct be_cmd_resp_if_create *resp = embedded_payload(&wrb);
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci		*if_handle = le32_to_cpu(resp->interface_id);
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci		/* Hack to retrieve VF's pmac-id on BE3 */
15578c2ecf20Sopenharmony_ci		if (BE3_chip(adapter) && be_virtfn(adapter))
15588c2ecf20Sopenharmony_ci			adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id);
15598c2ecf20Sopenharmony_ci	}
15608c2ecf20Sopenharmony_ci	return status;
15618c2ecf20Sopenharmony_ci}
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci/* Uses MCCQ if available else MBOX */
15648c2ecf20Sopenharmony_ciint be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain)
15658c2ecf20Sopenharmony_ci{
15668c2ecf20Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
15678c2ecf20Sopenharmony_ci	struct be_cmd_req_if_destroy *req;
15688c2ecf20Sopenharmony_ci	int status;
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	if (interface_id == -1)
15718c2ecf20Sopenharmony_ci		return 0;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	req = embedded_payload(&wrb);
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
15768c2ecf20Sopenharmony_ci			       OPCODE_COMMON_NTWK_INTERFACE_DESTROY,
15778c2ecf20Sopenharmony_ci			       sizeof(*req), &wrb, NULL);
15788c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
15798c2ecf20Sopenharmony_ci	req->interface_id = cpu_to_le32(interface_id);
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
15828c2ecf20Sopenharmony_ci	return status;
15838c2ecf20Sopenharmony_ci}
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci/* Get stats is a non embedded command: the request is not embedded inside
15868c2ecf20Sopenharmony_ci * WRB but is a separate dma memory block
15878c2ecf20Sopenharmony_ci * Uses asynchronous MCC
15888c2ecf20Sopenharmony_ci */
15898c2ecf20Sopenharmony_ciint be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
15908c2ecf20Sopenharmony_ci{
15918c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
15928c2ecf20Sopenharmony_ci	struct be_cmd_req_hdr *hdr;
15938c2ecf20Sopenharmony_ci	int status = 0;
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
15988c2ecf20Sopenharmony_ci	if (!wrb) {
15998c2ecf20Sopenharmony_ci		status = -EBUSY;
16008c2ecf20Sopenharmony_ci		goto err;
16018c2ecf20Sopenharmony_ci	}
16028c2ecf20Sopenharmony_ci	hdr = nonemb_cmd->va;
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
16058c2ecf20Sopenharmony_ci			       OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb,
16068c2ecf20Sopenharmony_ci			       nonemb_cmd);
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci	/* version 1 of the cmd is not supported only by BE2 */
16098c2ecf20Sopenharmony_ci	if (BE2_chip(adapter))
16108c2ecf20Sopenharmony_ci		hdr->version = 0;
16118c2ecf20Sopenharmony_ci	if (BE3_chip(adapter) || lancer_chip(adapter))
16128c2ecf20Sopenharmony_ci		hdr->version = 1;
16138c2ecf20Sopenharmony_ci	else
16148c2ecf20Sopenharmony_ci		hdr->version = 2;
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_ci	status = be_mcc_notify(adapter);
16178c2ecf20Sopenharmony_ci	if (status)
16188c2ecf20Sopenharmony_ci		goto err;
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_ci	adapter->stats_cmd_sent = true;
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_cierr:
16238c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
16248c2ecf20Sopenharmony_ci	return status;
16258c2ecf20Sopenharmony_ci}
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci/* Lancer Stats */
16288c2ecf20Sopenharmony_ciint lancer_cmd_get_pport_stats(struct be_adapter *adapter,
16298c2ecf20Sopenharmony_ci			       struct be_dma_mem *nonemb_cmd)
16308c2ecf20Sopenharmony_ci{
16318c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
16328c2ecf20Sopenharmony_ci	struct lancer_cmd_req_pport_stats *req;
16338c2ecf20Sopenharmony_ci	int status = 0;
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
16368c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_ETH))
16378c2ecf20Sopenharmony_ci		return -EPERM;
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
16428c2ecf20Sopenharmony_ci	if (!wrb) {
16438c2ecf20Sopenharmony_ci		status = -EBUSY;
16448c2ecf20Sopenharmony_ci		goto err;
16458c2ecf20Sopenharmony_ci	}
16468c2ecf20Sopenharmony_ci	req = nonemb_cmd->va;
16478c2ecf20Sopenharmony_ci
16488c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
16498c2ecf20Sopenharmony_ci			       OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size,
16508c2ecf20Sopenharmony_ci			       wrb, nonemb_cmd);
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci	req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num);
16538c2ecf20Sopenharmony_ci	req->cmd_params.params.reset_stats = 0;
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci	status = be_mcc_notify(adapter);
16568c2ecf20Sopenharmony_ci	if (status)
16578c2ecf20Sopenharmony_ci		goto err;
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	adapter->stats_cmd_sent = true;
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_cierr:
16628c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
16638c2ecf20Sopenharmony_ci	return status;
16648c2ecf20Sopenharmony_ci}
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_cistatic int be_mac_to_link_speed(int mac_speed)
16678c2ecf20Sopenharmony_ci{
16688c2ecf20Sopenharmony_ci	switch (mac_speed) {
16698c2ecf20Sopenharmony_ci	case PHY_LINK_SPEED_ZERO:
16708c2ecf20Sopenharmony_ci		return 0;
16718c2ecf20Sopenharmony_ci	case PHY_LINK_SPEED_10MBPS:
16728c2ecf20Sopenharmony_ci		return 10;
16738c2ecf20Sopenharmony_ci	case PHY_LINK_SPEED_100MBPS:
16748c2ecf20Sopenharmony_ci		return 100;
16758c2ecf20Sopenharmony_ci	case PHY_LINK_SPEED_1GBPS:
16768c2ecf20Sopenharmony_ci		return 1000;
16778c2ecf20Sopenharmony_ci	case PHY_LINK_SPEED_10GBPS:
16788c2ecf20Sopenharmony_ci		return 10000;
16798c2ecf20Sopenharmony_ci	case PHY_LINK_SPEED_20GBPS:
16808c2ecf20Sopenharmony_ci		return 20000;
16818c2ecf20Sopenharmony_ci	case PHY_LINK_SPEED_25GBPS:
16828c2ecf20Sopenharmony_ci		return 25000;
16838c2ecf20Sopenharmony_ci	case PHY_LINK_SPEED_40GBPS:
16848c2ecf20Sopenharmony_ci		return 40000;
16858c2ecf20Sopenharmony_ci	}
16868c2ecf20Sopenharmony_ci	return 0;
16878c2ecf20Sopenharmony_ci}
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci/* Uses synchronous mcc
16908c2ecf20Sopenharmony_ci * Returns link_speed in Mbps
16918c2ecf20Sopenharmony_ci */
16928c2ecf20Sopenharmony_ciint be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
16938c2ecf20Sopenharmony_ci			     u8 *link_status, u32 dom)
16948c2ecf20Sopenharmony_ci{
16958c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
16968c2ecf20Sopenharmony_ci	struct be_cmd_req_link_status *req;
16978c2ecf20Sopenharmony_ci	int status;
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci	if (link_status)
17028c2ecf20Sopenharmony_ci		*link_status = LINK_DOWN;
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
17058c2ecf20Sopenharmony_ci	if (!wrb) {
17068c2ecf20Sopenharmony_ci		status = -EBUSY;
17078c2ecf20Sopenharmony_ci		goto err;
17088c2ecf20Sopenharmony_ci	}
17098c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
17128c2ecf20Sopenharmony_ci			       OPCODE_COMMON_NTWK_LINK_STATUS_QUERY,
17138c2ecf20Sopenharmony_ci			       sizeof(*req), wrb, NULL);
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci	/* version 1 of the cmd is not supported only by BE2 */
17168c2ecf20Sopenharmony_ci	if (!BE2_chip(adapter))
17178c2ecf20Sopenharmony_ci		req->hdr.version = 1;
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci	req->hdr.domain = dom;
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
17228c2ecf20Sopenharmony_ci	if (!status) {
17238c2ecf20Sopenharmony_ci		struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci		if (link_speed) {
17268c2ecf20Sopenharmony_ci			*link_speed = resp->link_speed ?
17278c2ecf20Sopenharmony_ci				      le16_to_cpu(resp->link_speed) * 10 :
17288c2ecf20Sopenharmony_ci				      be_mac_to_link_speed(resp->mac_speed);
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci			if (!resp->logical_link_status)
17318c2ecf20Sopenharmony_ci				*link_speed = 0;
17328c2ecf20Sopenharmony_ci		}
17338c2ecf20Sopenharmony_ci		if (link_status)
17348c2ecf20Sopenharmony_ci			*link_status = resp->logical_link_status;
17358c2ecf20Sopenharmony_ci	}
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_cierr:
17388c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
17398c2ecf20Sopenharmony_ci	return status;
17408c2ecf20Sopenharmony_ci}
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci/* Uses synchronous mcc */
17438c2ecf20Sopenharmony_ciint be_cmd_get_die_temperature(struct be_adapter *adapter)
17448c2ecf20Sopenharmony_ci{
17458c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
17468c2ecf20Sopenharmony_ci	struct be_cmd_req_get_cntl_addnl_attribs *req;
17478c2ecf20Sopenharmony_ci	int status = 0;
17488c2ecf20Sopenharmony_ci
17498c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
17528c2ecf20Sopenharmony_ci	if (!wrb) {
17538c2ecf20Sopenharmony_ci		status = -EBUSY;
17548c2ecf20Sopenharmony_ci		goto err;
17558c2ecf20Sopenharmony_ci	}
17568c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
17598c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES,
17608c2ecf20Sopenharmony_ci			       sizeof(*req), wrb, NULL);
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci	status = be_mcc_notify(adapter);
17638c2ecf20Sopenharmony_cierr:
17648c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
17658c2ecf20Sopenharmony_ci	return status;
17668c2ecf20Sopenharmony_ci}
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci/* Uses synchronous mcc */
17698c2ecf20Sopenharmony_ciint be_cmd_get_fat_dump_len(struct be_adapter *adapter, u32 *dump_size)
17708c2ecf20Sopenharmony_ci{
17718c2ecf20Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
17728c2ecf20Sopenharmony_ci	struct be_cmd_req_get_fat *req;
17738c2ecf20Sopenharmony_ci	int status;
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	req = embedded_payload(&wrb);
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
17788c2ecf20Sopenharmony_ci			       OPCODE_COMMON_MANAGE_FAT, sizeof(*req),
17798c2ecf20Sopenharmony_ci			       &wrb, NULL);
17808c2ecf20Sopenharmony_ci	req->fat_operation = cpu_to_le32(QUERY_FAT);
17818c2ecf20Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
17828c2ecf20Sopenharmony_ci	if (!status) {
17838c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_fat *resp = embedded_payload(&wrb);
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci		if (dump_size && resp->log_size)
17868c2ecf20Sopenharmony_ci			*dump_size = le32_to_cpu(resp->log_size) -
17878c2ecf20Sopenharmony_ci					sizeof(u32);
17888c2ecf20Sopenharmony_ci	}
17898c2ecf20Sopenharmony_ci	return status;
17908c2ecf20Sopenharmony_ci}
17918c2ecf20Sopenharmony_ci
17928c2ecf20Sopenharmony_ciint be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf)
17938c2ecf20Sopenharmony_ci{
17948c2ecf20Sopenharmony_ci	struct be_dma_mem get_fat_cmd;
17958c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
17968c2ecf20Sopenharmony_ci	struct be_cmd_req_get_fat *req;
17978c2ecf20Sopenharmony_ci	u32 offset = 0, total_size, buf_size,
17988c2ecf20Sopenharmony_ci				log_offset = sizeof(u32), payload_len;
17998c2ecf20Sopenharmony_ci	int status;
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	if (buf_len == 0)
18028c2ecf20Sopenharmony_ci		return 0;
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	total_size = buf_len;
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci	get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
18078c2ecf20Sopenharmony_ci	get_fat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
18088c2ecf20Sopenharmony_ci					    get_fat_cmd.size,
18098c2ecf20Sopenharmony_ci					    &get_fat_cmd.dma, GFP_ATOMIC);
18108c2ecf20Sopenharmony_ci	if (!get_fat_cmd.va)
18118c2ecf20Sopenharmony_ci		return -ENOMEM;
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	while (total_size) {
18168c2ecf20Sopenharmony_ci		buf_size = min(total_size, (u32)60*1024);
18178c2ecf20Sopenharmony_ci		total_size -= buf_size;
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci		wrb = wrb_from_mccq(adapter);
18208c2ecf20Sopenharmony_ci		if (!wrb) {
18218c2ecf20Sopenharmony_ci			status = -EBUSY;
18228c2ecf20Sopenharmony_ci			goto err;
18238c2ecf20Sopenharmony_ci		}
18248c2ecf20Sopenharmony_ci		req = get_fat_cmd.va;
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci		payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size;
18278c2ecf20Sopenharmony_ci		be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
18288c2ecf20Sopenharmony_ci				       OPCODE_COMMON_MANAGE_FAT, payload_len,
18298c2ecf20Sopenharmony_ci				       wrb, &get_fat_cmd);
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci		req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
18328c2ecf20Sopenharmony_ci		req->read_log_offset = cpu_to_le32(log_offset);
18338c2ecf20Sopenharmony_ci		req->read_log_length = cpu_to_le32(buf_size);
18348c2ecf20Sopenharmony_ci		req->data_buffer_size = cpu_to_le32(buf_size);
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_ci		status = be_mcc_notify_wait(adapter);
18378c2ecf20Sopenharmony_ci		if (!status) {
18388c2ecf20Sopenharmony_ci			struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci			memcpy(buf + offset,
18418c2ecf20Sopenharmony_ci			       resp->data_buffer,
18428c2ecf20Sopenharmony_ci			       le32_to_cpu(resp->read_log_length));
18438c2ecf20Sopenharmony_ci		} else {
18448c2ecf20Sopenharmony_ci			dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
18458c2ecf20Sopenharmony_ci			goto err;
18468c2ecf20Sopenharmony_ci		}
18478c2ecf20Sopenharmony_ci		offset += buf_size;
18488c2ecf20Sopenharmony_ci		log_offset += buf_size;
18498c2ecf20Sopenharmony_ci	}
18508c2ecf20Sopenharmony_cierr:
18518c2ecf20Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, get_fat_cmd.size,
18528c2ecf20Sopenharmony_ci			  get_fat_cmd.va, get_fat_cmd.dma);
18538c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
18548c2ecf20Sopenharmony_ci	return status;
18558c2ecf20Sopenharmony_ci}
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci/* Uses synchronous mcc */
18588c2ecf20Sopenharmony_ciint be_cmd_get_fw_ver(struct be_adapter *adapter)
18598c2ecf20Sopenharmony_ci{
18608c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
18618c2ecf20Sopenharmony_ci	struct be_cmd_req_get_fw_version *req;
18628c2ecf20Sopenharmony_ci	int status;
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
18678c2ecf20Sopenharmony_ci	if (!wrb) {
18688c2ecf20Sopenharmony_ci		status = -EBUSY;
18698c2ecf20Sopenharmony_ci		goto err;
18708c2ecf20Sopenharmony_ci	}
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
18758c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb,
18768c2ecf20Sopenharmony_ci			       NULL);
18778c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
18788c2ecf20Sopenharmony_ci	if (!status) {
18798c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci		strlcpy(adapter->fw_ver, resp->firmware_version_string,
18828c2ecf20Sopenharmony_ci			sizeof(adapter->fw_ver));
18838c2ecf20Sopenharmony_ci		strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string,
18848c2ecf20Sopenharmony_ci			sizeof(adapter->fw_on_flash));
18858c2ecf20Sopenharmony_ci	}
18868c2ecf20Sopenharmony_cierr:
18878c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
18888c2ecf20Sopenharmony_ci	return status;
18898c2ecf20Sopenharmony_ci}
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci/* set the EQ delay interval of an EQ to specified value
18928c2ecf20Sopenharmony_ci * Uses async mcc
18938c2ecf20Sopenharmony_ci */
18948c2ecf20Sopenharmony_cistatic int __be_cmd_modify_eqd(struct be_adapter *adapter,
18958c2ecf20Sopenharmony_ci			       struct be_set_eqd *set_eqd, int num)
18968c2ecf20Sopenharmony_ci{
18978c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
18988c2ecf20Sopenharmony_ci	struct be_cmd_req_modify_eq_delay *req;
18998c2ecf20Sopenharmony_ci	int status = 0, i;
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
19048c2ecf20Sopenharmony_ci	if (!wrb) {
19058c2ecf20Sopenharmony_ci		status = -EBUSY;
19068c2ecf20Sopenharmony_ci		goto err;
19078c2ecf20Sopenharmony_ci	}
19088c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
19098c2ecf20Sopenharmony_ci
19108c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
19118c2ecf20Sopenharmony_ci			       OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb,
19128c2ecf20Sopenharmony_ci			       NULL);
19138c2ecf20Sopenharmony_ci
19148c2ecf20Sopenharmony_ci	req->num_eq = cpu_to_le32(num);
19158c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
19168c2ecf20Sopenharmony_ci		req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
19178c2ecf20Sopenharmony_ci		req->set_eqd[i].phase = 0;
19188c2ecf20Sopenharmony_ci		req->set_eqd[i].delay_multiplier =
19198c2ecf20Sopenharmony_ci				cpu_to_le32(set_eqd[i].delay_multiplier);
19208c2ecf20Sopenharmony_ci	}
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_ci	status = be_mcc_notify(adapter);
19238c2ecf20Sopenharmony_cierr:
19248c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
19258c2ecf20Sopenharmony_ci	return status;
19268c2ecf20Sopenharmony_ci}
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ciint be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd,
19298c2ecf20Sopenharmony_ci		      int num)
19308c2ecf20Sopenharmony_ci{
19318c2ecf20Sopenharmony_ci	int num_eqs, i = 0;
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci	while (num) {
19348c2ecf20Sopenharmony_ci		num_eqs = min(num, 8);
19358c2ecf20Sopenharmony_ci		__be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs);
19368c2ecf20Sopenharmony_ci		i += num_eqs;
19378c2ecf20Sopenharmony_ci		num -= num_eqs;
19388c2ecf20Sopenharmony_ci	}
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci	return 0;
19418c2ecf20Sopenharmony_ci}
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci/* Uses sycnhronous mcc */
19448c2ecf20Sopenharmony_ciint be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
19458c2ecf20Sopenharmony_ci		       u32 num, u32 domain)
19468c2ecf20Sopenharmony_ci{
19478c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
19488c2ecf20Sopenharmony_ci	struct be_cmd_req_vlan_config *req;
19498c2ecf20Sopenharmony_ci	int status;
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
19548c2ecf20Sopenharmony_ci	if (!wrb) {
19558c2ecf20Sopenharmony_ci		status = -EBUSY;
19568c2ecf20Sopenharmony_ci		goto err;
19578c2ecf20Sopenharmony_ci	}
19588c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
19598c2ecf20Sopenharmony_ci
19608c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
19618c2ecf20Sopenharmony_ci			       OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req),
19628c2ecf20Sopenharmony_ci			       wrb, NULL);
19638c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_ci	req->interface_id = if_id;
19668c2ecf20Sopenharmony_ci	req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0;
19678c2ecf20Sopenharmony_ci	req->num_vlan = num;
19688c2ecf20Sopenharmony_ci	memcpy(req->normal_vlan, vtag_array,
19698c2ecf20Sopenharmony_ci	       req->num_vlan * sizeof(vtag_array[0]));
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
19728c2ecf20Sopenharmony_cierr:
19738c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
19748c2ecf20Sopenharmony_ci	return status;
19758c2ecf20Sopenharmony_ci}
19768c2ecf20Sopenharmony_ci
19778c2ecf20Sopenharmony_cistatic int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
19788c2ecf20Sopenharmony_ci{
19798c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
19808c2ecf20Sopenharmony_ci	struct be_dma_mem *mem = &adapter->rx_filter;
19818c2ecf20Sopenharmony_ci	struct be_cmd_req_rx_filter *req = mem->va;
19828c2ecf20Sopenharmony_ci	int status;
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
19878c2ecf20Sopenharmony_ci	if (!wrb) {
19888c2ecf20Sopenharmony_ci		status = -EBUSY;
19898c2ecf20Sopenharmony_ci		goto err;
19908c2ecf20Sopenharmony_ci	}
19918c2ecf20Sopenharmony_ci	memset(req, 0, sizeof(*req));
19928c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
19938c2ecf20Sopenharmony_ci			       OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req),
19948c2ecf20Sopenharmony_ci			       wrb, mem);
19958c2ecf20Sopenharmony_ci
19968c2ecf20Sopenharmony_ci	req->if_id = cpu_to_le32(adapter->if_handle);
19978c2ecf20Sopenharmony_ci	req->if_flags_mask = cpu_to_le32(flags);
19988c2ecf20Sopenharmony_ci	req->if_flags = (value == ON) ? req->if_flags_mask : 0;
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci	if (flags & BE_IF_FLAGS_MULTICAST) {
20018c2ecf20Sopenharmony_ci		int i;
20028c2ecf20Sopenharmony_ci
20038c2ecf20Sopenharmony_ci		/* Reset mcast promisc mode if already set by setting mask
20048c2ecf20Sopenharmony_ci		 * and not setting flags field
20058c2ecf20Sopenharmony_ci		 */
20068c2ecf20Sopenharmony_ci		req->if_flags_mask |=
20078c2ecf20Sopenharmony_ci			cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
20088c2ecf20Sopenharmony_ci				    be_if_cap_flags(adapter));
20098c2ecf20Sopenharmony_ci		req->mcast_num = cpu_to_le32(adapter->mc_count);
20108c2ecf20Sopenharmony_ci		for (i = 0; i < adapter->mc_count; i++)
20118c2ecf20Sopenharmony_ci			ether_addr_copy(req->mcast_mac[i].byte,
20128c2ecf20Sopenharmony_ci					adapter->mc_list[i].mac);
20138c2ecf20Sopenharmony_ci	}
20148c2ecf20Sopenharmony_ci
20158c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
20168c2ecf20Sopenharmony_cierr:
20178c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
20188c2ecf20Sopenharmony_ci	return status;
20198c2ecf20Sopenharmony_ci}
20208c2ecf20Sopenharmony_ci
20218c2ecf20Sopenharmony_ciint be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
20228c2ecf20Sopenharmony_ci{
20238c2ecf20Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci	if ((flags & be_if_cap_flags(adapter)) != flags) {
20268c2ecf20Sopenharmony_ci		dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags);
20278c2ecf20Sopenharmony_ci		dev_warn(dev, "Interface is capable of 0x%x flags only\n",
20288c2ecf20Sopenharmony_ci			 be_if_cap_flags(adapter));
20298c2ecf20Sopenharmony_ci	}
20308c2ecf20Sopenharmony_ci	flags &= be_if_cap_flags(adapter);
20318c2ecf20Sopenharmony_ci	if (!flags)
20328c2ecf20Sopenharmony_ci		return -ENOTSUPP;
20338c2ecf20Sopenharmony_ci
20348c2ecf20Sopenharmony_ci	return __be_cmd_rx_filter(adapter, flags, value);
20358c2ecf20Sopenharmony_ci}
20368c2ecf20Sopenharmony_ci
20378c2ecf20Sopenharmony_ci/* Uses synchrounous mcc */
20388c2ecf20Sopenharmony_ciint be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
20398c2ecf20Sopenharmony_ci{
20408c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
20418c2ecf20Sopenharmony_ci	struct be_cmd_req_set_flow_control *req;
20428c2ecf20Sopenharmony_ci	int status;
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
20458c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
20468c2ecf20Sopenharmony_ci		return -EPERM;
20478c2ecf20Sopenharmony_ci
20488c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
20498c2ecf20Sopenharmony_ci
20508c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
20518c2ecf20Sopenharmony_ci	if (!wrb) {
20528c2ecf20Sopenharmony_ci		status = -EBUSY;
20538c2ecf20Sopenharmony_ci		goto err;
20548c2ecf20Sopenharmony_ci	}
20558c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
20568c2ecf20Sopenharmony_ci
20578c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
20588c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req),
20598c2ecf20Sopenharmony_ci			       wrb, NULL);
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci	req->hdr.version = 1;
20628c2ecf20Sopenharmony_ci	req->tx_flow_control = cpu_to_le16((u16)tx_fc);
20638c2ecf20Sopenharmony_ci	req->rx_flow_control = cpu_to_le16((u16)rx_fc);
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_cierr:
20688c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_ci	if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED)
20718c2ecf20Sopenharmony_ci		return  -EOPNOTSUPP;
20728c2ecf20Sopenharmony_ci
20738c2ecf20Sopenharmony_ci	return status;
20748c2ecf20Sopenharmony_ci}
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci/* Uses sycn mcc */
20778c2ecf20Sopenharmony_ciint be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
20788c2ecf20Sopenharmony_ci{
20798c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
20808c2ecf20Sopenharmony_ci	struct be_cmd_req_get_flow_control *req;
20818c2ecf20Sopenharmony_ci	int status;
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
20848c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
20858c2ecf20Sopenharmony_ci		return -EPERM;
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
20908c2ecf20Sopenharmony_ci	if (!wrb) {
20918c2ecf20Sopenharmony_ci		status = -EBUSY;
20928c2ecf20Sopenharmony_ci		goto err;
20938c2ecf20Sopenharmony_ci	}
20948c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
20978c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req),
20988c2ecf20Sopenharmony_ci			       wrb, NULL);
20998c2ecf20Sopenharmony_ci
21008c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
21018c2ecf20Sopenharmony_ci	if (!status) {
21028c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_flow_control *resp =
21038c2ecf20Sopenharmony_ci						embedded_payload(wrb);
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci		*tx_fc = le16_to_cpu(resp->tx_flow_control);
21068c2ecf20Sopenharmony_ci		*rx_fc = le16_to_cpu(resp->rx_flow_control);
21078c2ecf20Sopenharmony_ci	}
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_cierr:
21108c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
21118c2ecf20Sopenharmony_ci	return status;
21128c2ecf20Sopenharmony_ci}
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_ci/* Uses mbox */
21158c2ecf20Sopenharmony_ciint be_cmd_query_fw_cfg(struct be_adapter *adapter)
21168c2ecf20Sopenharmony_ci{
21178c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
21188c2ecf20Sopenharmony_ci	struct be_cmd_req_query_fw_cfg *req;
21198c2ecf20Sopenharmony_ci	int status;
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
21228c2ecf20Sopenharmony_ci		return -1;
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
21258c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
21288c2ecf20Sopenharmony_ci			       OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
21298c2ecf20Sopenharmony_ci			       sizeof(*req), wrb, NULL);
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
21328c2ecf20Sopenharmony_ci	if (!status) {
21338c2ecf20Sopenharmony_ci		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
21348c2ecf20Sopenharmony_ci
21358c2ecf20Sopenharmony_ci		adapter->port_num = le32_to_cpu(resp->phys_port);
21368c2ecf20Sopenharmony_ci		adapter->function_mode = le32_to_cpu(resp->function_mode);
21378c2ecf20Sopenharmony_ci		adapter->function_caps = le32_to_cpu(resp->function_caps);
21388c2ecf20Sopenharmony_ci		adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
21398c2ecf20Sopenharmony_ci		dev_info(&adapter->pdev->dev,
21408c2ecf20Sopenharmony_ci			 "FW config: function_mode=0x%x, function_caps=0x%x\n",
21418c2ecf20Sopenharmony_ci			 adapter->function_mode, adapter->function_caps);
21428c2ecf20Sopenharmony_ci	}
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
21458c2ecf20Sopenharmony_ci	return status;
21468c2ecf20Sopenharmony_ci}
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci/* Uses mbox */
21498c2ecf20Sopenharmony_ciint be_cmd_reset_function(struct be_adapter *adapter)
21508c2ecf20Sopenharmony_ci{
21518c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
21528c2ecf20Sopenharmony_ci	struct be_cmd_req_hdr *req;
21538c2ecf20Sopenharmony_ci	int status;
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ci	if (lancer_chip(adapter)) {
21568c2ecf20Sopenharmony_ci		iowrite32(SLI_PORT_CONTROL_IP_MASK,
21578c2ecf20Sopenharmony_ci			  adapter->db + SLIPORT_CONTROL_OFFSET);
21588c2ecf20Sopenharmony_ci		status = lancer_wait_ready(adapter);
21598c2ecf20Sopenharmony_ci		if (status)
21608c2ecf20Sopenharmony_ci			dev_err(&adapter->pdev->dev,
21618c2ecf20Sopenharmony_ci				"Adapter in non recoverable error\n");
21628c2ecf20Sopenharmony_ci		return status;
21638c2ecf20Sopenharmony_ci	}
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
21668c2ecf20Sopenharmony_ci		return -1;
21678c2ecf20Sopenharmony_ci
21688c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
21698c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
21708c2ecf20Sopenharmony_ci
21718c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
21728c2ecf20Sopenharmony_ci			       OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb,
21738c2ecf20Sopenharmony_ci			       NULL);
21748c2ecf20Sopenharmony_ci
21758c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
21768c2ecf20Sopenharmony_ci
21778c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
21788c2ecf20Sopenharmony_ci	return status;
21798c2ecf20Sopenharmony_ci}
21808c2ecf20Sopenharmony_ci
21818c2ecf20Sopenharmony_ciint be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
21828c2ecf20Sopenharmony_ci		      u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey)
21838c2ecf20Sopenharmony_ci{
21848c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
21858c2ecf20Sopenharmony_ci	struct be_cmd_req_rss_config *req;
21868c2ecf20Sopenharmony_ci	int status;
21878c2ecf20Sopenharmony_ci
21888c2ecf20Sopenharmony_ci	if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
21898c2ecf20Sopenharmony_ci		return 0;
21908c2ecf20Sopenharmony_ci
21918c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
21948c2ecf20Sopenharmony_ci	if (!wrb) {
21958c2ecf20Sopenharmony_ci		status = -EBUSY;
21968c2ecf20Sopenharmony_ci		goto err;
21978c2ecf20Sopenharmony_ci	}
21988c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
21998c2ecf20Sopenharmony_ci
22008c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
22018c2ecf20Sopenharmony_ci			       OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
22028c2ecf20Sopenharmony_ci
22038c2ecf20Sopenharmony_ci	req->if_id = cpu_to_le32(adapter->if_handle);
22048c2ecf20Sopenharmony_ci	req->enable_rss = cpu_to_le16(rss_hash_opts);
22058c2ecf20Sopenharmony_ci	req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci	if (!BEx_chip(adapter))
22088c2ecf20Sopenharmony_ci		req->hdr.version = 1;
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci	memcpy(req->cpu_table, rsstable, table_size);
22118c2ecf20Sopenharmony_ci	memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN);
22128c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(req->hash, sizeof(req->hash));
22138c2ecf20Sopenharmony_ci
22148c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
22158c2ecf20Sopenharmony_cierr:
22168c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
22178c2ecf20Sopenharmony_ci	return status;
22188c2ecf20Sopenharmony_ci}
22198c2ecf20Sopenharmony_ci
22208c2ecf20Sopenharmony_ci/* Uses sync mcc */
22218c2ecf20Sopenharmony_ciint be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
22228c2ecf20Sopenharmony_ci			    u8 bcn, u8 sts, u8 state)
22238c2ecf20Sopenharmony_ci{
22248c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
22258c2ecf20Sopenharmony_ci	struct be_cmd_req_enable_disable_beacon *req;
22268c2ecf20Sopenharmony_ci	int status;
22278c2ecf20Sopenharmony_ci
22288c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
22298c2ecf20Sopenharmony_ci
22308c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
22318c2ecf20Sopenharmony_ci	if (!wrb) {
22328c2ecf20Sopenharmony_ci		status = -EBUSY;
22338c2ecf20Sopenharmony_ci		goto err;
22348c2ecf20Sopenharmony_ci	}
22358c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
22368c2ecf20Sopenharmony_ci
22378c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
22388c2ecf20Sopenharmony_ci			       OPCODE_COMMON_ENABLE_DISABLE_BEACON,
22398c2ecf20Sopenharmony_ci			       sizeof(*req), wrb, NULL);
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci	req->port_num = port_num;
22428c2ecf20Sopenharmony_ci	req->beacon_state = state;
22438c2ecf20Sopenharmony_ci	req->beacon_duration = bcn;
22448c2ecf20Sopenharmony_ci	req->status_duration = sts;
22458c2ecf20Sopenharmony_ci
22468c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
22478c2ecf20Sopenharmony_ci
22488c2ecf20Sopenharmony_cierr:
22498c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
22508c2ecf20Sopenharmony_ci	return status;
22518c2ecf20Sopenharmony_ci}
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci/* Uses sync mcc */
22548c2ecf20Sopenharmony_ciint be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
22558c2ecf20Sopenharmony_ci{
22568c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
22578c2ecf20Sopenharmony_ci	struct be_cmd_req_get_beacon_state *req;
22588c2ecf20Sopenharmony_ci	int status;
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
22638c2ecf20Sopenharmony_ci	if (!wrb) {
22648c2ecf20Sopenharmony_ci		status = -EBUSY;
22658c2ecf20Sopenharmony_ci		goto err;
22668c2ecf20Sopenharmony_ci	}
22678c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
22688c2ecf20Sopenharmony_ci
22698c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
22708c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req),
22718c2ecf20Sopenharmony_ci			       wrb, NULL);
22728c2ecf20Sopenharmony_ci
22738c2ecf20Sopenharmony_ci	req->port_num = port_num;
22748c2ecf20Sopenharmony_ci
22758c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
22768c2ecf20Sopenharmony_ci	if (!status) {
22778c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_beacon_state *resp =
22788c2ecf20Sopenharmony_ci						embedded_payload(wrb);
22798c2ecf20Sopenharmony_ci
22808c2ecf20Sopenharmony_ci		*state = resp->beacon_state;
22818c2ecf20Sopenharmony_ci	}
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_cierr:
22848c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
22858c2ecf20Sopenharmony_ci	return status;
22868c2ecf20Sopenharmony_ci}
22878c2ecf20Sopenharmony_ci
22888c2ecf20Sopenharmony_ci/* Uses sync mcc */
22898c2ecf20Sopenharmony_ciint be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
22908c2ecf20Sopenharmony_ci				      u8 page_num, u32 off, u32 len, u8 *data)
22918c2ecf20Sopenharmony_ci{
22928c2ecf20Sopenharmony_ci	struct be_dma_mem cmd;
22938c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
22948c2ecf20Sopenharmony_ci	struct be_cmd_req_port_type *req;
22958c2ecf20Sopenharmony_ci	int status;
22968c2ecf20Sopenharmony_ci
22978c2ecf20Sopenharmony_ci	if (page_num > TR_PAGE_A2)
22988c2ecf20Sopenharmony_ci		return -EINVAL;
22998c2ecf20Sopenharmony_ci
23008c2ecf20Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_resp_port_type);
23018c2ecf20Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
23028c2ecf20Sopenharmony_ci				    GFP_ATOMIC);
23038c2ecf20Sopenharmony_ci	if (!cmd.va) {
23048c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory allocation failed\n");
23058c2ecf20Sopenharmony_ci		return -ENOMEM;
23068c2ecf20Sopenharmony_ci	}
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
23098c2ecf20Sopenharmony_ci
23108c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
23118c2ecf20Sopenharmony_ci	if (!wrb) {
23128c2ecf20Sopenharmony_ci		status = -EBUSY;
23138c2ecf20Sopenharmony_ci		goto err;
23148c2ecf20Sopenharmony_ci	}
23158c2ecf20Sopenharmony_ci	req = cmd.va;
23168c2ecf20Sopenharmony_ci
23178c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
23188c2ecf20Sopenharmony_ci			       OPCODE_COMMON_READ_TRANSRECV_DATA,
23198c2ecf20Sopenharmony_ci			       cmd.size, wrb, &cmd);
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci	req->port = cpu_to_le32(adapter->hba_port_num);
23228c2ecf20Sopenharmony_ci	req->page_num = cpu_to_le32(page_num);
23238c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
23248c2ecf20Sopenharmony_ci	if (!status && len > 0) {
23258c2ecf20Sopenharmony_ci		struct be_cmd_resp_port_type *resp = cmd.va;
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci		memcpy(data, resp->page_data + off, len);
23288c2ecf20Sopenharmony_ci	}
23298c2ecf20Sopenharmony_cierr:
23308c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
23318c2ecf20Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
23328c2ecf20Sopenharmony_ci	return status;
23338c2ecf20Sopenharmony_ci}
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_cistatic int lancer_cmd_write_object(struct be_adapter *adapter,
23368c2ecf20Sopenharmony_ci				   struct be_dma_mem *cmd, u32 data_size,
23378c2ecf20Sopenharmony_ci				   u32 data_offset, const char *obj_name,
23388c2ecf20Sopenharmony_ci				   u32 *data_written, u8 *change_status,
23398c2ecf20Sopenharmony_ci				   u8 *addn_status)
23408c2ecf20Sopenharmony_ci{
23418c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
23428c2ecf20Sopenharmony_ci	struct lancer_cmd_req_write_object *req;
23438c2ecf20Sopenharmony_ci	struct lancer_cmd_resp_write_object *resp;
23448c2ecf20Sopenharmony_ci	void *ctxt = NULL;
23458c2ecf20Sopenharmony_ci	int status;
23468c2ecf20Sopenharmony_ci
23478c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
23488c2ecf20Sopenharmony_ci	adapter->flash_status = 0;
23498c2ecf20Sopenharmony_ci
23508c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
23518c2ecf20Sopenharmony_ci	if (!wrb) {
23528c2ecf20Sopenharmony_ci		status = -EBUSY;
23538c2ecf20Sopenharmony_ci		goto err_unlock;
23548c2ecf20Sopenharmony_ci	}
23558c2ecf20Sopenharmony_ci
23568c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
23578c2ecf20Sopenharmony_ci
23588c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
23598c2ecf20Sopenharmony_ci			       OPCODE_COMMON_WRITE_OBJECT,
23608c2ecf20Sopenharmony_ci			       sizeof(struct lancer_cmd_req_write_object), wrb,
23618c2ecf20Sopenharmony_ci			       NULL);
23628c2ecf20Sopenharmony_ci
23638c2ecf20Sopenharmony_ci	ctxt = &req->context;
23648c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_lancer_write_obj_context,
23658c2ecf20Sopenharmony_ci		      write_length, ctxt, data_size);
23668c2ecf20Sopenharmony_ci
23678c2ecf20Sopenharmony_ci	if (data_size == 0)
23688c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
23698c2ecf20Sopenharmony_ci			      eof, ctxt, 1);
23708c2ecf20Sopenharmony_ci	else
23718c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
23728c2ecf20Sopenharmony_ci			      eof, ctxt, 0);
23738c2ecf20Sopenharmony_ci
23748c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(ctxt, sizeof(req->context));
23758c2ecf20Sopenharmony_ci	req->write_offset = cpu_to_le32(data_offset);
23768c2ecf20Sopenharmony_ci	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
23778c2ecf20Sopenharmony_ci	req->descriptor_count = cpu_to_le32(1);
23788c2ecf20Sopenharmony_ci	req->buf_len = cpu_to_le32(data_size);
23798c2ecf20Sopenharmony_ci	req->addr_low = cpu_to_le32((cmd->dma +
23808c2ecf20Sopenharmony_ci				     sizeof(struct lancer_cmd_req_write_object))
23818c2ecf20Sopenharmony_ci				    & 0xFFFFFFFF);
23828c2ecf20Sopenharmony_ci	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma +
23838c2ecf20Sopenharmony_ci				sizeof(struct lancer_cmd_req_write_object)));
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_ci	status = be_mcc_notify(adapter);
23868c2ecf20Sopenharmony_ci	if (status)
23878c2ecf20Sopenharmony_ci		goto err_unlock;
23888c2ecf20Sopenharmony_ci
23898c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
23908c2ecf20Sopenharmony_ci
23918c2ecf20Sopenharmony_ci	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
23928c2ecf20Sopenharmony_ci					 msecs_to_jiffies(60000)))
23938c2ecf20Sopenharmony_ci		status = -ETIMEDOUT;
23948c2ecf20Sopenharmony_ci	else
23958c2ecf20Sopenharmony_ci		status = adapter->flash_status;
23968c2ecf20Sopenharmony_ci
23978c2ecf20Sopenharmony_ci	resp = embedded_payload(wrb);
23988c2ecf20Sopenharmony_ci	if (!status) {
23998c2ecf20Sopenharmony_ci		*data_written = le32_to_cpu(resp->actual_write_len);
24008c2ecf20Sopenharmony_ci		*change_status = resp->change_status;
24018c2ecf20Sopenharmony_ci	} else {
24028c2ecf20Sopenharmony_ci		*addn_status = resp->additional_status;
24038c2ecf20Sopenharmony_ci	}
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci	return status;
24068c2ecf20Sopenharmony_ci
24078c2ecf20Sopenharmony_cierr_unlock:
24088c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
24098c2ecf20Sopenharmony_ci	return status;
24108c2ecf20Sopenharmony_ci}
24118c2ecf20Sopenharmony_ci
24128c2ecf20Sopenharmony_ciint be_cmd_query_cable_type(struct be_adapter *adapter)
24138c2ecf20Sopenharmony_ci{
24148c2ecf20Sopenharmony_ci	u8 page_data[PAGE_DATA_LEN];
24158c2ecf20Sopenharmony_ci	int status;
24168c2ecf20Sopenharmony_ci
24178c2ecf20Sopenharmony_ci	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
24188c2ecf20Sopenharmony_ci						   0, PAGE_DATA_LEN, page_data);
24198c2ecf20Sopenharmony_ci	if (!status) {
24208c2ecf20Sopenharmony_ci		switch (adapter->phy.interface_type) {
24218c2ecf20Sopenharmony_ci		case PHY_TYPE_QSFP:
24228c2ecf20Sopenharmony_ci			adapter->phy.cable_type =
24238c2ecf20Sopenharmony_ci				page_data[QSFP_PLUS_CABLE_TYPE_OFFSET];
24248c2ecf20Sopenharmony_ci			break;
24258c2ecf20Sopenharmony_ci		case PHY_TYPE_SFP_PLUS_10GB:
24268c2ecf20Sopenharmony_ci			adapter->phy.cable_type =
24278c2ecf20Sopenharmony_ci				page_data[SFP_PLUS_CABLE_TYPE_OFFSET];
24288c2ecf20Sopenharmony_ci			break;
24298c2ecf20Sopenharmony_ci		default:
24308c2ecf20Sopenharmony_ci			adapter->phy.cable_type = 0;
24318c2ecf20Sopenharmony_ci			break;
24328c2ecf20Sopenharmony_ci		}
24338c2ecf20Sopenharmony_ci	}
24348c2ecf20Sopenharmony_ci	return status;
24358c2ecf20Sopenharmony_ci}
24368c2ecf20Sopenharmony_ci
24378c2ecf20Sopenharmony_ciint be_cmd_query_sfp_info(struct be_adapter *adapter)
24388c2ecf20Sopenharmony_ci{
24398c2ecf20Sopenharmony_ci	u8 page_data[PAGE_DATA_LEN];
24408c2ecf20Sopenharmony_ci	int status;
24418c2ecf20Sopenharmony_ci
24428c2ecf20Sopenharmony_ci	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
24438c2ecf20Sopenharmony_ci						   0, PAGE_DATA_LEN, page_data);
24448c2ecf20Sopenharmony_ci	if (!status) {
24458c2ecf20Sopenharmony_ci		strlcpy(adapter->phy.vendor_name, page_data +
24468c2ecf20Sopenharmony_ci			SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
24478c2ecf20Sopenharmony_ci		strlcpy(adapter->phy.vendor_pn,
24488c2ecf20Sopenharmony_ci			page_data + SFP_VENDOR_PN_OFFSET,
24498c2ecf20Sopenharmony_ci			SFP_VENDOR_NAME_LEN - 1);
24508c2ecf20Sopenharmony_ci	}
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_ci	return status;
24538c2ecf20Sopenharmony_ci}
24548c2ecf20Sopenharmony_ci
24558c2ecf20Sopenharmony_cistatic int lancer_cmd_delete_object(struct be_adapter *adapter,
24568c2ecf20Sopenharmony_ci				    const char *obj_name)
24578c2ecf20Sopenharmony_ci{
24588c2ecf20Sopenharmony_ci	struct lancer_cmd_req_delete_object *req;
24598c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
24608c2ecf20Sopenharmony_ci	int status;
24618c2ecf20Sopenharmony_ci
24628c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
24638c2ecf20Sopenharmony_ci
24648c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
24658c2ecf20Sopenharmony_ci	if (!wrb) {
24668c2ecf20Sopenharmony_ci		status = -EBUSY;
24678c2ecf20Sopenharmony_ci		goto err;
24688c2ecf20Sopenharmony_ci	}
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
24718c2ecf20Sopenharmony_ci
24728c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
24738c2ecf20Sopenharmony_ci			       OPCODE_COMMON_DELETE_OBJECT,
24748c2ecf20Sopenharmony_ci			       sizeof(*req), wrb, NULL);
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
24778c2ecf20Sopenharmony_ci
24788c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
24798c2ecf20Sopenharmony_cierr:
24808c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
24818c2ecf20Sopenharmony_ci	return status;
24828c2ecf20Sopenharmony_ci}
24838c2ecf20Sopenharmony_ci
24848c2ecf20Sopenharmony_ciint lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
24858c2ecf20Sopenharmony_ci			   u32 data_size, u32 data_offset, const char *obj_name,
24868c2ecf20Sopenharmony_ci			   u32 *data_read, u32 *eof, u8 *addn_status)
24878c2ecf20Sopenharmony_ci{
24888c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
24898c2ecf20Sopenharmony_ci	struct lancer_cmd_req_read_object *req;
24908c2ecf20Sopenharmony_ci	struct lancer_cmd_resp_read_object *resp;
24918c2ecf20Sopenharmony_ci	int status;
24928c2ecf20Sopenharmony_ci
24938c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
24948c2ecf20Sopenharmony_ci
24958c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
24968c2ecf20Sopenharmony_ci	if (!wrb) {
24978c2ecf20Sopenharmony_ci		status = -EBUSY;
24988c2ecf20Sopenharmony_ci		goto err_unlock;
24998c2ecf20Sopenharmony_ci	}
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
25028c2ecf20Sopenharmony_ci
25038c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
25048c2ecf20Sopenharmony_ci			       OPCODE_COMMON_READ_OBJECT,
25058c2ecf20Sopenharmony_ci			       sizeof(struct lancer_cmd_req_read_object), wrb,
25068c2ecf20Sopenharmony_ci			       NULL);
25078c2ecf20Sopenharmony_ci
25088c2ecf20Sopenharmony_ci	req->desired_read_len = cpu_to_le32(data_size);
25098c2ecf20Sopenharmony_ci	req->read_offset = cpu_to_le32(data_offset);
25108c2ecf20Sopenharmony_ci	strcpy(req->object_name, obj_name);
25118c2ecf20Sopenharmony_ci	req->descriptor_count = cpu_to_le32(1);
25128c2ecf20Sopenharmony_ci	req->buf_len = cpu_to_le32(data_size);
25138c2ecf20Sopenharmony_ci	req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF));
25148c2ecf20Sopenharmony_ci	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma));
25158c2ecf20Sopenharmony_ci
25168c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
25178c2ecf20Sopenharmony_ci
25188c2ecf20Sopenharmony_ci	resp = embedded_payload(wrb);
25198c2ecf20Sopenharmony_ci	if (!status) {
25208c2ecf20Sopenharmony_ci		*data_read = le32_to_cpu(resp->actual_read_len);
25218c2ecf20Sopenharmony_ci		*eof = le32_to_cpu(resp->eof);
25228c2ecf20Sopenharmony_ci	} else {
25238c2ecf20Sopenharmony_ci		*addn_status = resp->additional_status;
25248c2ecf20Sopenharmony_ci	}
25258c2ecf20Sopenharmony_ci
25268c2ecf20Sopenharmony_cierr_unlock:
25278c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
25288c2ecf20Sopenharmony_ci	return status;
25298c2ecf20Sopenharmony_ci}
25308c2ecf20Sopenharmony_ci
25318c2ecf20Sopenharmony_cistatic int be_cmd_write_flashrom(struct be_adapter *adapter,
25328c2ecf20Sopenharmony_ci				 struct be_dma_mem *cmd, u32 flash_type,
25338c2ecf20Sopenharmony_ci				 u32 flash_opcode, u32 img_offset, u32 buf_size)
25348c2ecf20Sopenharmony_ci{
25358c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
25368c2ecf20Sopenharmony_ci	struct be_cmd_write_flashrom *req;
25378c2ecf20Sopenharmony_ci	int status;
25388c2ecf20Sopenharmony_ci
25398c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
25408c2ecf20Sopenharmony_ci	adapter->flash_status = 0;
25418c2ecf20Sopenharmony_ci
25428c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
25438c2ecf20Sopenharmony_ci	if (!wrb) {
25448c2ecf20Sopenharmony_ci		status = -EBUSY;
25458c2ecf20Sopenharmony_ci		goto err_unlock;
25468c2ecf20Sopenharmony_ci	}
25478c2ecf20Sopenharmony_ci	req = cmd->va;
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
25508c2ecf20Sopenharmony_ci			       OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb,
25518c2ecf20Sopenharmony_ci			       cmd);
25528c2ecf20Sopenharmony_ci
25538c2ecf20Sopenharmony_ci	req->params.op_type = cpu_to_le32(flash_type);
25548c2ecf20Sopenharmony_ci	if (flash_type == OPTYPE_OFFSET_SPECIFIED)
25558c2ecf20Sopenharmony_ci		req->params.offset = cpu_to_le32(img_offset);
25568c2ecf20Sopenharmony_ci
25578c2ecf20Sopenharmony_ci	req->params.op_code = cpu_to_le32(flash_opcode);
25588c2ecf20Sopenharmony_ci	req->params.data_buf_size = cpu_to_le32(buf_size);
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_ci	status = be_mcc_notify(adapter);
25618c2ecf20Sopenharmony_ci	if (status)
25628c2ecf20Sopenharmony_ci		goto err_unlock;
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
25658c2ecf20Sopenharmony_ci
25668c2ecf20Sopenharmony_ci	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
25678c2ecf20Sopenharmony_ci					 msecs_to_jiffies(40000)))
25688c2ecf20Sopenharmony_ci		status = -ETIMEDOUT;
25698c2ecf20Sopenharmony_ci	else
25708c2ecf20Sopenharmony_ci		status = adapter->flash_status;
25718c2ecf20Sopenharmony_ci
25728c2ecf20Sopenharmony_ci	return status;
25738c2ecf20Sopenharmony_ci
25748c2ecf20Sopenharmony_cierr_unlock:
25758c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
25768c2ecf20Sopenharmony_ci	return status;
25778c2ecf20Sopenharmony_ci}
25788c2ecf20Sopenharmony_ci
25798c2ecf20Sopenharmony_cistatic int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
25808c2ecf20Sopenharmony_ci				u16 img_optype, u32 img_offset, u32 crc_offset)
25818c2ecf20Sopenharmony_ci{
25828c2ecf20Sopenharmony_ci	struct be_cmd_read_flash_crc *req;
25838c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
25848c2ecf20Sopenharmony_ci	int status;
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
25878c2ecf20Sopenharmony_ci
25888c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
25898c2ecf20Sopenharmony_ci	if (!wrb) {
25908c2ecf20Sopenharmony_ci		status = -EBUSY;
25918c2ecf20Sopenharmony_ci		goto err;
25928c2ecf20Sopenharmony_ci	}
25938c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
25948c2ecf20Sopenharmony_ci
25958c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
25968c2ecf20Sopenharmony_ci			       OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
25978c2ecf20Sopenharmony_ci			       wrb, NULL);
25988c2ecf20Sopenharmony_ci
25998c2ecf20Sopenharmony_ci	req->params.op_type = cpu_to_le32(img_optype);
26008c2ecf20Sopenharmony_ci	if (img_optype == OPTYPE_OFFSET_SPECIFIED)
26018c2ecf20Sopenharmony_ci		req->params.offset = cpu_to_le32(img_offset + crc_offset);
26028c2ecf20Sopenharmony_ci	else
26038c2ecf20Sopenharmony_ci		req->params.offset = cpu_to_le32(crc_offset);
26048c2ecf20Sopenharmony_ci
26058c2ecf20Sopenharmony_ci	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
26068c2ecf20Sopenharmony_ci	req->params.data_buf_size = cpu_to_le32(0x4);
26078c2ecf20Sopenharmony_ci
26088c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
26098c2ecf20Sopenharmony_ci	if (!status)
26108c2ecf20Sopenharmony_ci		memcpy(flashed_crc, req->crc, 4);
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_cierr:
26138c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
26148c2ecf20Sopenharmony_ci	return status;
26158c2ecf20Sopenharmony_ci}
26168c2ecf20Sopenharmony_ci
26178c2ecf20Sopenharmony_cistatic char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_cistatic bool phy_flashing_required(struct be_adapter *adapter)
26208c2ecf20Sopenharmony_ci{
26218c2ecf20Sopenharmony_ci	return (adapter->phy.phy_type == PHY_TYPE_TN_8022 &&
26228c2ecf20Sopenharmony_ci		adapter->phy.interface_type == PHY_TYPE_BASET_10GB);
26238c2ecf20Sopenharmony_ci}
26248c2ecf20Sopenharmony_ci
26258c2ecf20Sopenharmony_cistatic bool is_comp_in_ufi(struct be_adapter *adapter,
26268c2ecf20Sopenharmony_ci			   struct flash_section_info *fsec, int type)
26278c2ecf20Sopenharmony_ci{
26288c2ecf20Sopenharmony_ci	int i = 0, img_type = 0;
26298c2ecf20Sopenharmony_ci	struct flash_section_info_g2 *fsec_g2 = NULL;
26308c2ecf20Sopenharmony_ci
26318c2ecf20Sopenharmony_ci	if (BE2_chip(adapter))
26328c2ecf20Sopenharmony_ci		fsec_g2 = (struct flash_section_info_g2 *)fsec;
26338c2ecf20Sopenharmony_ci
26348c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_FLASH_COMP; i++) {
26358c2ecf20Sopenharmony_ci		if (fsec_g2)
26368c2ecf20Sopenharmony_ci			img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type);
26378c2ecf20Sopenharmony_ci		else
26388c2ecf20Sopenharmony_ci			img_type = le32_to_cpu(fsec->fsec_entry[i].type);
26398c2ecf20Sopenharmony_ci
26408c2ecf20Sopenharmony_ci		if (img_type == type)
26418c2ecf20Sopenharmony_ci			return true;
26428c2ecf20Sopenharmony_ci	}
26438c2ecf20Sopenharmony_ci	return false;
26448c2ecf20Sopenharmony_ci}
26458c2ecf20Sopenharmony_ci
26468c2ecf20Sopenharmony_cistatic struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
26478c2ecf20Sopenharmony_ci						int header_size,
26488c2ecf20Sopenharmony_ci						const struct firmware *fw)
26498c2ecf20Sopenharmony_ci{
26508c2ecf20Sopenharmony_ci	struct flash_section_info *fsec = NULL;
26518c2ecf20Sopenharmony_ci	const u8 *p = fw->data;
26528c2ecf20Sopenharmony_ci
26538c2ecf20Sopenharmony_ci	p += header_size;
26548c2ecf20Sopenharmony_ci	while (p < (fw->data + fw->size)) {
26558c2ecf20Sopenharmony_ci		fsec = (struct flash_section_info *)p;
26568c2ecf20Sopenharmony_ci		if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie)))
26578c2ecf20Sopenharmony_ci			return fsec;
26588c2ecf20Sopenharmony_ci		p += 32;
26598c2ecf20Sopenharmony_ci	}
26608c2ecf20Sopenharmony_ci	return NULL;
26618c2ecf20Sopenharmony_ci}
26628c2ecf20Sopenharmony_ci
26638c2ecf20Sopenharmony_cistatic int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
26648c2ecf20Sopenharmony_ci			      u32 img_offset, u32 img_size, int hdr_size,
26658c2ecf20Sopenharmony_ci			      u16 img_optype, bool *crc_match)
26668c2ecf20Sopenharmony_ci{
26678c2ecf20Sopenharmony_ci	u32 crc_offset;
26688c2ecf20Sopenharmony_ci	int status;
26698c2ecf20Sopenharmony_ci	u8 crc[4];
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_ci	status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset,
26728c2ecf20Sopenharmony_ci				      img_size - 4);
26738c2ecf20Sopenharmony_ci	if (status)
26748c2ecf20Sopenharmony_ci		return status;
26758c2ecf20Sopenharmony_ci
26768c2ecf20Sopenharmony_ci	crc_offset = hdr_size + img_offset + img_size - 4;
26778c2ecf20Sopenharmony_ci
26788c2ecf20Sopenharmony_ci	/* Skip flashing, if crc of flashed region matches */
26798c2ecf20Sopenharmony_ci	if (!memcmp(crc, p + crc_offset, 4))
26808c2ecf20Sopenharmony_ci		*crc_match = true;
26818c2ecf20Sopenharmony_ci	else
26828c2ecf20Sopenharmony_ci		*crc_match = false;
26838c2ecf20Sopenharmony_ci
26848c2ecf20Sopenharmony_ci	return status;
26858c2ecf20Sopenharmony_ci}
26868c2ecf20Sopenharmony_ci
26878c2ecf20Sopenharmony_cistatic int be_flash(struct be_adapter *adapter, const u8 *img,
26888c2ecf20Sopenharmony_ci		    struct be_dma_mem *flash_cmd, int optype, int img_size,
26898c2ecf20Sopenharmony_ci		    u32 img_offset)
26908c2ecf20Sopenharmony_ci{
26918c2ecf20Sopenharmony_ci	u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0;
26928c2ecf20Sopenharmony_ci	struct be_cmd_write_flashrom *req = flash_cmd->va;
26938c2ecf20Sopenharmony_ci	int status;
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_ci	while (total_bytes) {
26968c2ecf20Sopenharmony_ci		num_bytes = min_t(u32, 32 * 1024, total_bytes);
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci		total_bytes -= num_bytes;
26998c2ecf20Sopenharmony_ci
27008c2ecf20Sopenharmony_ci		if (!total_bytes) {
27018c2ecf20Sopenharmony_ci			if (optype == OPTYPE_PHY_FW)
27028c2ecf20Sopenharmony_ci				flash_op = FLASHROM_OPER_PHY_FLASH;
27038c2ecf20Sopenharmony_ci			else
27048c2ecf20Sopenharmony_ci				flash_op = FLASHROM_OPER_FLASH;
27058c2ecf20Sopenharmony_ci		} else {
27068c2ecf20Sopenharmony_ci			if (optype == OPTYPE_PHY_FW)
27078c2ecf20Sopenharmony_ci				flash_op = FLASHROM_OPER_PHY_SAVE;
27088c2ecf20Sopenharmony_ci			else
27098c2ecf20Sopenharmony_ci				flash_op = FLASHROM_OPER_SAVE;
27108c2ecf20Sopenharmony_ci		}
27118c2ecf20Sopenharmony_ci
27128c2ecf20Sopenharmony_ci		memcpy(req->data_buf, img, num_bytes);
27138c2ecf20Sopenharmony_ci		img += num_bytes;
27148c2ecf20Sopenharmony_ci		status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
27158c2ecf20Sopenharmony_ci					       flash_op, img_offset +
27168c2ecf20Sopenharmony_ci					       bytes_sent, num_bytes);
27178c2ecf20Sopenharmony_ci		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
27188c2ecf20Sopenharmony_ci		    optype == OPTYPE_PHY_FW)
27198c2ecf20Sopenharmony_ci			break;
27208c2ecf20Sopenharmony_ci		else if (status)
27218c2ecf20Sopenharmony_ci			return status;
27228c2ecf20Sopenharmony_ci
27238c2ecf20Sopenharmony_ci		bytes_sent += num_bytes;
27248c2ecf20Sopenharmony_ci	}
27258c2ecf20Sopenharmony_ci	return 0;
27268c2ecf20Sopenharmony_ci}
27278c2ecf20Sopenharmony_ci
27288c2ecf20Sopenharmony_ci#define NCSI_UPDATE_LOG	"NCSI section update is not supported in FW ver %s\n"
27298c2ecf20Sopenharmony_cistatic bool be_fw_ncsi_supported(char *ver)
27308c2ecf20Sopenharmony_ci{
27318c2ecf20Sopenharmony_ci	int v1[4] = {3, 102, 148, 0}; /* Min ver that supports NCSI FW */
27328c2ecf20Sopenharmony_ci	int v2[4];
27338c2ecf20Sopenharmony_ci	int i;
27348c2ecf20Sopenharmony_ci
27358c2ecf20Sopenharmony_ci	if (sscanf(ver, "%d.%d.%d.%d", &v2[0], &v2[1], &v2[2], &v2[3]) != 4)
27368c2ecf20Sopenharmony_ci		return false;
27378c2ecf20Sopenharmony_ci
27388c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
27398c2ecf20Sopenharmony_ci		if (v1[i] < v2[i])
27408c2ecf20Sopenharmony_ci			return true;
27418c2ecf20Sopenharmony_ci		else if (v1[i] > v2[i])
27428c2ecf20Sopenharmony_ci			return false;
27438c2ecf20Sopenharmony_ci	}
27448c2ecf20Sopenharmony_ci
27458c2ecf20Sopenharmony_ci	return true;
27468c2ecf20Sopenharmony_ci}
27478c2ecf20Sopenharmony_ci
27488c2ecf20Sopenharmony_ci/* For BE2, BE3 and BE3-R */
27498c2ecf20Sopenharmony_cistatic int be_flash_BEx(struct be_adapter *adapter,
27508c2ecf20Sopenharmony_ci			const struct firmware *fw,
27518c2ecf20Sopenharmony_ci			struct be_dma_mem *flash_cmd, int num_of_images)
27528c2ecf20Sopenharmony_ci{
27538c2ecf20Sopenharmony_ci	int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
27548c2ecf20Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
27558c2ecf20Sopenharmony_ci	struct flash_section_info *fsec = NULL;
27568c2ecf20Sopenharmony_ci	int status, i, filehdr_size, num_comp;
27578c2ecf20Sopenharmony_ci	const struct flash_comp *pflashcomp;
27588c2ecf20Sopenharmony_ci	bool crc_match;
27598c2ecf20Sopenharmony_ci	const u8 *p;
27608c2ecf20Sopenharmony_ci
27618c2ecf20Sopenharmony_ci	static const struct flash_comp gen3_flash_types[] = {
27628c2ecf20Sopenharmony_ci		{ BE3_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
27638c2ecf20Sopenharmony_ci			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
27648c2ecf20Sopenharmony_ci		{ BE3_REDBOOT_START, OPTYPE_REDBOOT,
27658c2ecf20Sopenharmony_ci			BE3_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
27668c2ecf20Sopenharmony_ci		{ BE3_ISCSI_BIOS_START, OPTYPE_BIOS,
27678c2ecf20Sopenharmony_ci			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
27688c2ecf20Sopenharmony_ci		{ BE3_PXE_BIOS_START, OPTYPE_PXE_BIOS,
27698c2ecf20Sopenharmony_ci			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
27708c2ecf20Sopenharmony_ci		{ BE3_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
27718c2ecf20Sopenharmony_ci			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
27728c2ecf20Sopenharmony_ci		{ BE3_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
27738c2ecf20Sopenharmony_ci			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
27748c2ecf20Sopenharmony_ci		{ BE3_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
27758c2ecf20Sopenharmony_ci			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
27768c2ecf20Sopenharmony_ci		{ BE3_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
27778c2ecf20Sopenharmony_ci			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE},
27788c2ecf20Sopenharmony_ci		{ BE3_NCSI_START, OPTYPE_NCSI_FW,
27798c2ecf20Sopenharmony_ci			BE3_NCSI_COMP_MAX_SIZE, IMAGE_NCSI},
27808c2ecf20Sopenharmony_ci		{ BE3_PHY_FW_START, OPTYPE_PHY_FW,
27818c2ecf20Sopenharmony_ci			BE3_PHY_FW_COMP_MAX_SIZE, IMAGE_FIRMWARE_PHY}
27828c2ecf20Sopenharmony_ci	};
27838c2ecf20Sopenharmony_ci
27848c2ecf20Sopenharmony_ci	static const struct flash_comp gen2_flash_types[] = {
27858c2ecf20Sopenharmony_ci		{ BE2_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
27868c2ecf20Sopenharmony_ci			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
27878c2ecf20Sopenharmony_ci		{ BE2_REDBOOT_START, OPTYPE_REDBOOT,
27888c2ecf20Sopenharmony_ci			BE2_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
27898c2ecf20Sopenharmony_ci		{ BE2_ISCSI_BIOS_START, OPTYPE_BIOS,
27908c2ecf20Sopenharmony_ci			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
27918c2ecf20Sopenharmony_ci		{ BE2_PXE_BIOS_START, OPTYPE_PXE_BIOS,
27928c2ecf20Sopenharmony_ci			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
27938c2ecf20Sopenharmony_ci		{ BE2_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
27948c2ecf20Sopenharmony_ci			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
27958c2ecf20Sopenharmony_ci		{ BE2_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
27968c2ecf20Sopenharmony_ci			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
27978c2ecf20Sopenharmony_ci		{ BE2_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
27988c2ecf20Sopenharmony_ci			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
27998c2ecf20Sopenharmony_ci		{ BE2_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
28008c2ecf20Sopenharmony_ci			 BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE}
28018c2ecf20Sopenharmony_ci	};
28028c2ecf20Sopenharmony_ci
28038c2ecf20Sopenharmony_ci	if (BE3_chip(adapter)) {
28048c2ecf20Sopenharmony_ci		pflashcomp = gen3_flash_types;
28058c2ecf20Sopenharmony_ci		filehdr_size = sizeof(struct flash_file_hdr_g3);
28068c2ecf20Sopenharmony_ci		num_comp = ARRAY_SIZE(gen3_flash_types);
28078c2ecf20Sopenharmony_ci	} else {
28088c2ecf20Sopenharmony_ci		pflashcomp = gen2_flash_types;
28098c2ecf20Sopenharmony_ci		filehdr_size = sizeof(struct flash_file_hdr_g2);
28108c2ecf20Sopenharmony_ci		num_comp = ARRAY_SIZE(gen2_flash_types);
28118c2ecf20Sopenharmony_ci		img_hdrs_size = 0;
28128c2ecf20Sopenharmony_ci	}
28138c2ecf20Sopenharmony_ci
28148c2ecf20Sopenharmony_ci	/* Get flash section info*/
28158c2ecf20Sopenharmony_ci	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
28168c2ecf20Sopenharmony_ci	if (!fsec) {
28178c2ecf20Sopenharmony_ci		dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
28188c2ecf20Sopenharmony_ci		return -1;
28198c2ecf20Sopenharmony_ci	}
28208c2ecf20Sopenharmony_ci	for (i = 0; i < num_comp; i++) {
28218c2ecf20Sopenharmony_ci		if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type))
28228c2ecf20Sopenharmony_ci			continue;
28238c2ecf20Sopenharmony_ci
28248c2ecf20Sopenharmony_ci		if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) &&
28258c2ecf20Sopenharmony_ci		    !be_fw_ncsi_supported(adapter->fw_ver)) {
28268c2ecf20Sopenharmony_ci			dev_info(dev, NCSI_UPDATE_LOG, adapter->fw_ver);
28278c2ecf20Sopenharmony_ci			continue;
28288c2ecf20Sopenharmony_ci		}
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_ci		if (pflashcomp[i].optype == OPTYPE_PHY_FW  &&
28318c2ecf20Sopenharmony_ci		    !phy_flashing_required(adapter))
28328c2ecf20Sopenharmony_ci			continue;
28338c2ecf20Sopenharmony_ci
28348c2ecf20Sopenharmony_ci		if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
28358c2ecf20Sopenharmony_ci			status = be_check_flash_crc(adapter, fw->data,
28368c2ecf20Sopenharmony_ci						    pflashcomp[i].offset,
28378c2ecf20Sopenharmony_ci						    pflashcomp[i].size,
28388c2ecf20Sopenharmony_ci						    filehdr_size +
28398c2ecf20Sopenharmony_ci						    img_hdrs_size,
28408c2ecf20Sopenharmony_ci						    OPTYPE_REDBOOT, &crc_match);
28418c2ecf20Sopenharmony_ci			if (status) {
28428c2ecf20Sopenharmony_ci				dev_err(dev,
28438c2ecf20Sopenharmony_ci					"Could not get CRC for 0x%x region\n",
28448c2ecf20Sopenharmony_ci					pflashcomp[i].optype);
28458c2ecf20Sopenharmony_ci				continue;
28468c2ecf20Sopenharmony_ci			}
28478c2ecf20Sopenharmony_ci
28488c2ecf20Sopenharmony_ci			if (crc_match)
28498c2ecf20Sopenharmony_ci				continue;
28508c2ecf20Sopenharmony_ci		}
28518c2ecf20Sopenharmony_ci
28528c2ecf20Sopenharmony_ci		p = fw->data + filehdr_size + pflashcomp[i].offset +
28538c2ecf20Sopenharmony_ci			img_hdrs_size;
28548c2ecf20Sopenharmony_ci		if (p + pflashcomp[i].size > fw->data + fw->size)
28558c2ecf20Sopenharmony_ci			return -1;
28568c2ecf20Sopenharmony_ci
28578c2ecf20Sopenharmony_ci		status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
28588c2ecf20Sopenharmony_ci				  pflashcomp[i].size, 0);
28598c2ecf20Sopenharmony_ci		if (status) {
28608c2ecf20Sopenharmony_ci			dev_err(dev, "Flashing section type 0x%x failed\n",
28618c2ecf20Sopenharmony_ci				pflashcomp[i].img_type);
28628c2ecf20Sopenharmony_ci			return status;
28638c2ecf20Sopenharmony_ci		}
28648c2ecf20Sopenharmony_ci	}
28658c2ecf20Sopenharmony_ci	return 0;
28668c2ecf20Sopenharmony_ci}
28678c2ecf20Sopenharmony_ci
28688c2ecf20Sopenharmony_cistatic u16 be_get_img_optype(struct flash_section_entry fsec_entry)
28698c2ecf20Sopenharmony_ci{
28708c2ecf20Sopenharmony_ci	u32 img_type = le32_to_cpu(fsec_entry.type);
28718c2ecf20Sopenharmony_ci	u16 img_optype = le16_to_cpu(fsec_entry.optype);
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_ci	if (img_optype != 0xFFFF)
28748c2ecf20Sopenharmony_ci		return img_optype;
28758c2ecf20Sopenharmony_ci
28768c2ecf20Sopenharmony_ci	switch (img_type) {
28778c2ecf20Sopenharmony_ci	case IMAGE_FIRMWARE_ISCSI:
28788c2ecf20Sopenharmony_ci		img_optype = OPTYPE_ISCSI_ACTIVE;
28798c2ecf20Sopenharmony_ci		break;
28808c2ecf20Sopenharmony_ci	case IMAGE_BOOT_CODE:
28818c2ecf20Sopenharmony_ci		img_optype = OPTYPE_REDBOOT;
28828c2ecf20Sopenharmony_ci		break;
28838c2ecf20Sopenharmony_ci	case IMAGE_OPTION_ROM_ISCSI:
28848c2ecf20Sopenharmony_ci		img_optype = OPTYPE_BIOS;
28858c2ecf20Sopenharmony_ci		break;
28868c2ecf20Sopenharmony_ci	case IMAGE_OPTION_ROM_PXE:
28878c2ecf20Sopenharmony_ci		img_optype = OPTYPE_PXE_BIOS;
28888c2ecf20Sopenharmony_ci		break;
28898c2ecf20Sopenharmony_ci	case IMAGE_OPTION_ROM_FCOE:
28908c2ecf20Sopenharmony_ci		img_optype = OPTYPE_FCOE_BIOS;
28918c2ecf20Sopenharmony_ci		break;
28928c2ecf20Sopenharmony_ci	case IMAGE_FIRMWARE_BACKUP_ISCSI:
28938c2ecf20Sopenharmony_ci		img_optype = OPTYPE_ISCSI_BACKUP;
28948c2ecf20Sopenharmony_ci		break;
28958c2ecf20Sopenharmony_ci	case IMAGE_NCSI:
28968c2ecf20Sopenharmony_ci		img_optype = OPTYPE_NCSI_FW;
28978c2ecf20Sopenharmony_ci		break;
28988c2ecf20Sopenharmony_ci	case IMAGE_FLASHISM_JUMPVECTOR:
28998c2ecf20Sopenharmony_ci		img_optype = OPTYPE_FLASHISM_JUMPVECTOR;
29008c2ecf20Sopenharmony_ci		break;
29018c2ecf20Sopenharmony_ci	case IMAGE_FIRMWARE_PHY:
29028c2ecf20Sopenharmony_ci		img_optype = OPTYPE_SH_PHY_FW;
29038c2ecf20Sopenharmony_ci		break;
29048c2ecf20Sopenharmony_ci	case IMAGE_REDBOOT_DIR:
29058c2ecf20Sopenharmony_ci		img_optype = OPTYPE_REDBOOT_DIR;
29068c2ecf20Sopenharmony_ci		break;
29078c2ecf20Sopenharmony_ci	case IMAGE_REDBOOT_CONFIG:
29088c2ecf20Sopenharmony_ci		img_optype = OPTYPE_REDBOOT_CONFIG;
29098c2ecf20Sopenharmony_ci		break;
29108c2ecf20Sopenharmony_ci	case IMAGE_UFI_DIR:
29118c2ecf20Sopenharmony_ci		img_optype = OPTYPE_UFI_DIR;
29128c2ecf20Sopenharmony_ci		break;
29138c2ecf20Sopenharmony_ci	default:
29148c2ecf20Sopenharmony_ci		break;
29158c2ecf20Sopenharmony_ci	}
29168c2ecf20Sopenharmony_ci
29178c2ecf20Sopenharmony_ci	return img_optype;
29188c2ecf20Sopenharmony_ci}
29198c2ecf20Sopenharmony_ci
29208c2ecf20Sopenharmony_cistatic int be_flash_skyhawk(struct be_adapter *adapter,
29218c2ecf20Sopenharmony_ci			    const struct firmware *fw,
29228c2ecf20Sopenharmony_ci			    struct be_dma_mem *flash_cmd, int num_of_images)
29238c2ecf20Sopenharmony_ci{
29248c2ecf20Sopenharmony_ci	int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
29258c2ecf20Sopenharmony_ci	bool crc_match, old_fw_img, flash_offset_support = true;
29268c2ecf20Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
29278c2ecf20Sopenharmony_ci	struct flash_section_info *fsec = NULL;
29288c2ecf20Sopenharmony_ci	u32 img_offset, img_size, img_type;
29298c2ecf20Sopenharmony_ci	u16 img_optype, flash_optype;
29308c2ecf20Sopenharmony_ci	int status, i, filehdr_size;
29318c2ecf20Sopenharmony_ci	const u8 *p;
29328c2ecf20Sopenharmony_ci
29338c2ecf20Sopenharmony_ci	filehdr_size = sizeof(struct flash_file_hdr_g3);
29348c2ecf20Sopenharmony_ci	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
29358c2ecf20Sopenharmony_ci	if (!fsec) {
29368c2ecf20Sopenharmony_ci		dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
29378c2ecf20Sopenharmony_ci		return -EINVAL;
29388c2ecf20Sopenharmony_ci	}
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_ciretry_flash:
29418c2ecf20Sopenharmony_ci	for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
29428c2ecf20Sopenharmony_ci		img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
29438c2ecf20Sopenharmony_ci		img_size   = le32_to_cpu(fsec->fsec_entry[i].pad_size);
29448c2ecf20Sopenharmony_ci		img_type   = le32_to_cpu(fsec->fsec_entry[i].type);
29458c2ecf20Sopenharmony_ci		img_optype = be_get_img_optype(fsec->fsec_entry[i]);
29468c2ecf20Sopenharmony_ci		old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF;
29478c2ecf20Sopenharmony_ci
29488c2ecf20Sopenharmony_ci		if (img_optype == 0xFFFF)
29498c2ecf20Sopenharmony_ci			continue;
29508c2ecf20Sopenharmony_ci
29518c2ecf20Sopenharmony_ci		if (flash_offset_support)
29528c2ecf20Sopenharmony_ci			flash_optype = OPTYPE_OFFSET_SPECIFIED;
29538c2ecf20Sopenharmony_ci		else
29548c2ecf20Sopenharmony_ci			flash_optype = img_optype;
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci		/* Don't bother verifying CRC if an old FW image is being
29578c2ecf20Sopenharmony_ci		 * flashed
29588c2ecf20Sopenharmony_ci		 */
29598c2ecf20Sopenharmony_ci		if (old_fw_img)
29608c2ecf20Sopenharmony_ci			goto flash;
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_ci		status = be_check_flash_crc(adapter, fw->data, img_offset,
29638c2ecf20Sopenharmony_ci					    img_size, filehdr_size +
29648c2ecf20Sopenharmony_ci					    img_hdrs_size, flash_optype,
29658c2ecf20Sopenharmony_ci					    &crc_match);
29668c2ecf20Sopenharmony_ci		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
29678c2ecf20Sopenharmony_ci		    base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
29688c2ecf20Sopenharmony_ci			/* The current FW image on the card does not support
29698c2ecf20Sopenharmony_ci			 * OFFSET based flashing. Retry using older mechanism
29708c2ecf20Sopenharmony_ci			 * of OPTYPE based flashing
29718c2ecf20Sopenharmony_ci			 */
29728c2ecf20Sopenharmony_ci			if (flash_optype == OPTYPE_OFFSET_SPECIFIED) {
29738c2ecf20Sopenharmony_ci				flash_offset_support = false;
29748c2ecf20Sopenharmony_ci				goto retry_flash;
29758c2ecf20Sopenharmony_ci			}
29768c2ecf20Sopenharmony_ci
29778c2ecf20Sopenharmony_ci			/* The current FW image on the card does not recognize
29788c2ecf20Sopenharmony_ci			 * the new FLASH op_type. The FW download is partially
29798c2ecf20Sopenharmony_ci			 * complete. Reboot the server now to enable FW image
29808c2ecf20Sopenharmony_ci			 * to recognize the new FLASH op_type. To complete the
29818c2ecf20Sopenharmony_ci			 * remaining process, download the same FW again after
29828c2ecf20Sopenharmony_ci			 * the reboot.
29838c2ecf20Sopenharmony_ci			 */
29848c2ecf20Sopenharmony_ci			dev_err(dev, "Flash incomplete. Reset the server\n");
29858c2ecf20Sopenharmony_ci			dev_err(dev, "Download FW image again after reset\n");
29868c2ecf20Sopenharmony_ci			return -EAGAIN;
29878c2ecf20Sopenharmony_ci		} else if (status) {
29888c2ecf20Sopenharmony_ci			dev_err(dev, "Could not get CRC for 0x%x region\n",
29898c2ecf20Sopenharmony_ci				img_optype);
29908c2ecf20Sopenharmony_ci			return -EFAULT;
29918c2ecf20Sopenharmony_ci		}
29928c2ecf20Sopenharmony_ci
29938c2ecf20Sopenharmony_ci		if (crc_match)
29948c2ecf20Sopenharmony_ci			continue;
29958c2ecf20Sopenharmony_ci
29968c2ecf20Sopenharmony_ciflash:
29978c2ecf20Sopenharmony_ci		p = fw->data + filehdr_size + img_offset + img_hdrs_size;
29988c2ecf20Sopenharmony_ci		if (p + img_size > fw->data + fw->size)
29998c2ecf20Sopenharmony_ci			return -1;
30008c2ecf20Sopenharmony_ci
30018c2ecf20Sopenharmony_ci		status = be_flash(adapter, p, flash_cmd, flash_optype, img_size,
30028c2ecf20Sopenharmony_ci				  img_offset);
30038c2ecf20Sopenharmony_ci
30048c2ecf20Sopenharmony_ci		/* The current FW image on the card does not support OFFSET
30058c2ecf20Sopenharmony_ci		 * based flashing. Retry using older mechanism of OPTYPE based
30068c2ecf20Sopenharmony_ci		 * flashing
30078c2ecf20Sopenharmony_ci		 */
30088c2ecf20Sopenharmony_ci		if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD &&
30098c2ecf20Sopenharmony_ci		    flash_optype == OPTYPE_OFFSET_SPECIFIED) {
30108c2ecf20Sopenharmony_ci			flash_offset_support = false;
30118c2ecf20Sopenharmony_ci			goto retry_flash;
30128c2ecf20Sopenharmony_ci		}
30138c2ecf20Sopenharmony_ci
30148c2ecf20Sopenharmony_ci		/* For old FW images ignore ILLEGAL_FIELD error or errors on
30158c2ecf20Sopenharmony_ci		 * UFI_DIR region
30168c2ecf20Sopenharmony_ci		 */
30178c2ecf20Sopenharmony_ci		if (old_fw_img &&
30188c2ecf20Sopenharmony_ci		    (base_status(status) == MCC_STATUS_ILLEGAL_FIELD ||
30198c2ecf20Sopenharmony_ci		     (img_optype == OPTYPE_UFI_DIR &&
30208c2ecf20Sopenharmony_ci		      base_status(status) == MCC_STATUS_FAILED))) {
30218c2ecf20Sopenharmony_ci			continue;
30228c2ecf20Sopenharmony_ci		} else if (status) {
30238c2ecf20Sopenharmony_ci			dev_err(dev, "Flashing section type 0x%x failed\n",
30248c2ecf20Sopenharmony_ci				img_type);
30258c2ecf20Sopenharmony_ci
30268c2ecf20Sopenharmony_ci			switch (addl_status(status)) {
30278c2ecf20Sopenharmony_ci			case MCC_ADDL_STATUS_MISSING_SIGNATURE:
30288c2ecf20Sopenharmony_ci				dev_err(dev,
30298c2ecf20Sopenharmony_ci					"Digital signature missing in FW\n");
30308c2ecf20Sopenharmony_ci				return -EINVAL;
30318c2ecf20Sopenharmony_ci			case MCC_ADDL_STATUS_INVALID_SIGNATURE:
30328c2ecf20Sopenharmony_ci				dev_err(dev,
30338c2ecf20Sopenharmony_ci					"Invalid digital signature in FW\n");
30348c2ecf20Sopenharmony_ci				return -EINVAL;
30358c2ecf20Sopenharmony_ci			default:
30368c2ecf20Sopenharmony_ci				return -EFAULT;
30378c2ecf20Sopenharmony_ci			}
30388c2ecf20Sopenharmony_ci		}
30398c2ecf20Sopenharmony_ci	}
30408c2ecf20Sopenharmony_ci	return 0;
30418c2ecf20Sopenharmony_ci}
30428c2ecf20Sopenharmony_ci
30438c2ecf20Sopenharmony_ciint lancer_fw_download(struct be_adapter *adapter,
30448c2ecf20Sopenharmony_ci		       const struct firmware *fw)
30458c2ecf20Sopenharmony_ci{
30468c2ecf20Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
30478c2ecf20Sopenharmony_ci	struct be_dma_mem flash_cmd;
30488c2ecf20Sopenharmony_ci	const u8 *data_ptr = NULL;
30498c2ecf20Sopenharmony_ci	u8 *dest_image_ptr = NULL;
30508c2ecf20Sopenharmony_ci	size_t image_size = 0;
30518c2ecf20Sopenharmony_ci	u32 chunk_size = 0;
30528c2ecf20Sopenharmony_ci	u32 data_written = 0;
30538c2ecf20Sopenharmony_ci	u32 offset = 0;
30548c2ecf20Sopenharmony_ci	int status = 0;
30558c2ecf20Sopenharmony_ci	u8 add_status = 0;
30568c2ecf20Sopenharmony_ci	u8 change_status;
30578c2ecf20Sopenharmony_ci
30588c2ecf20Sopenharmony_ci	if (!IS_ALIGNED(fw->size, sizeof(u32))) {
30598c2ecf20Sopenharmony_ci		dev_err(dev, "FW image size should be multiple of 4\n");
30608c2ecf20Sopenharmony_ci		return -EINVAL;
30618c2ecf20Sopenharmony_ci	}
30628c2ecf20Sopenharmony_ci
30638c2ecf20Sopenharmony_ci	flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
30648c2ecf20Sopenharmony_ci				+ LANCER_FW_DOWNLOAD_CHUNK;
30658c2ecf20Sopenharmony_ci	flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
30668c2ecf20Sopenharmony_ci					  GFP_KERNEL);
30678c2ecf20Sopenharmony_ci	if (!flash_cmd.va)
30688c2ecf20Sopenharmony_ci		return -ENOMEM;
30698c2ecf20Sopenharmony_ci
30708c2ecf20Sopenharmony_ci	dest_image_ptr = flash_cmd.va +
30718c2ecf20Sopenharmony_ci				sizeof(struct lancer_cmd_req_write_object);
30728c2ecf20Sopenharmony_ci	image_size = fw->size;
30738c2ecf20Sopenharmony_ci	data_ptr = fw->data;
30748c2ecf20Sopenharmony_ci
30758c2ecf20Sopenharmony_ci	while (image_size) {
30768c2ecf20Sopenharmony_ci		chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK);
30778c2ecf20Sopenharmony_ci
30788c2ecf20Sopenharmony_ci		/* Copy the image chunk content. */
30798c2ecf20Sopenharmony_ci		memcpy(dest_image_ptr, data_ptr, chunk_size);
30808c2ecf20Sopenharmony_ci
30818c2ecf20Sopenharmony_ci		status = lancer_cmd_write_object(adapter, &flash_cmd,
30828c2ecf20Sopenharmony_ci						 chunk_size, offset,
30838c2ecf20Sopenharmony_ci						 LANCER_FW_DOWNLOAD_LOCATION,
30848c2ecf20Sopenharmony_ci						 &data_written, &change_status,
30858c2ecf20Sopenharmony_ci						 &add_status);
30868c2ecf20Sopenharmony_ci		if (status)
30878c2ecf20Sopenharmony_ci			break;
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_ci		offset += data_written;
30908c2ecf20Sopenharmony_ci		data_ptr += data_written;
30918c2ecf20Sopenharmony_ci		image_size -= data_written;
30928c2ecf20Sopenharmony_ci	}
30938c2ecf20Sopenharmony_ci
30948c2ecf20Sopenharmony_ci	if (!status) {
30958c2ecf20Sopenharmony_ci		/* Commit the FW written */
30968c2ecf20Sopenharmony_ci		status = lancer_cmd_write_object(adapter, &flash_cmd,
30978c2ecf20Sopenharmony_ci						 0, offset,
30988c2ecf20Sopenharmony_ci						 LANCER_FW_DOWNLOAD_LOCATION,
30998c2ecf20Sopenharmony_ci						 &data_written, &change_status,
31008c2ecf20Sopenharmony_ci						 &add_status);
31018c2ecf20Sopenharmony_ci	}
31028c2ecf20Sopenharmony_ci
31038c2ecf20Sopenharmony_ci	dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
31048c2ecf20Sopenharmony_ci	if (status) {
31058c2ecf20Sopenharmony_ci		dev_err(dev, "Firmware load error\n");
31068c2ecf20Sopenharmony_ci		return be_cmd_status(status);
31078c2ecf20Sopenharmony_ci	}
31088c2ecf20Sopenharmony_ci
31098c2ecf20Sopenharmony_ci	dev_info(dev, "Firmware flashed successfully\n");
31108c2ecf20Sopenharmony_ci
31118c2ecf20Sopenharmony_ci	if (change_status == LANCER_FW_RESET_NEEDED) {
31128c2ecf20Sopenharmony_ci		dev_info(dev, "Resetting adapter to activate new FW\n");
31138c2ecf20Sopenharmony_ci		status = lancer_physdev_ctrl(adapter,
31148c2ecf20Sopenharmony_ci					     PHYSDEV_CONTROL_FW_RESET_MASK);
31158c2ecf20Sopenharmony_ci		if (status) {
31168c2ecf20Sopenharmony_ci			dev_err(dev, "Adapter busy, could not reset FW\n");
31178c2ecf20Sopenharmony_ci			dev_err(dev, "Reboot server to activate new FW\n");
31188c2ecf20Sopenharmony_ci		}
31198c2ecf20Sopenharmony_ci	} else if (change_status != LANCER_NO_RESET_NEEDED) {
31208c2ecf20Sopenharmony_ci		dev_info(dev, "Reboot server to activate new FW\n");
31218c2ecf20Sopenharmony_ci	}
31228c2ecf20Sopenharmony_ci
31238c2ecf20Sopenharmony_ci	return 0;
31248c2ecf20Sopenharmony_ci}
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_ci/* Check if the flash image file is compatible with the adapter that
31278c2ecf20Sopenharmony_ci * is being flashed.
31288c2ecf20Sopenharmony_ci */
31298c2ecf20Sopenharmony_cistatic bool be_check_ufi_compatibility(struct be_adapter *adapter,
31308c2ecf20Sopenharmony_ci				       struct flash_file_hdr_g3 *fhdr)
31318c2ecf20Sopenharmony_ci{
31328c2ecf20Sopenharmony_ci	if (!fhdr) {
31338c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Invalid FW UFI file");
31348c2ecf20Sopenharmony_ci		return false;
31358c2ecf20Sopenharmony_ci	}
31368c2ecf20Sopenharmony_ci
31378c2ecf20Sopenharmony_ci	/* First letter of the build version is used to identify
31388c2ecf20Sopenharmony_ci	 * which chip this image file is meant for.
31398c2ecf20Sopenharmony_ci	 */
31408c2ecf20Sopenharmony_ci	switch (fhdr->build[0]) {
31418c2ecf20Sopenharmony_ci	case BLD_STR_UFI_TYPE_SH:
31428c2ecf20Sopenharmony_ci		if (!skyhawk_chip(adapter))
31438c2ecf20Sopenharmony_ci			return false;
31448c2ecf20Sopenharmony_ci		break;
31458c2ecf20Sopenharmony_ci	case BLD_STR_UFI_TYPE_BE3:
31468c2ecf20Sopenharmony_ci		if (!BE3_chip(adapter))
31478c2ecf20Sopenharmony_ci			return false;
31488c2ecf20Sopenharmony_ci		break;
31498c2ecf20Sopenharmony_ci	case BLD_STR_UFI_TYPE_BE2:
31508c2ecf20Sopenharmony_ci		if (!BE2_chip(adapter))
31518c2ecf20Sopenharmony_ci			return false;
31528c2ecf20Sopenharmony_ci		break;
31538c2ecf20Sopenharmony_ci	default:
31548c2ecf20Sopenharmony_ci		return false;
31558c2ecf20Sopenharmony_ci	}
31568c2ecf20Sopenharmony_ci
31578c2ecf20Sopenharmony_ci	/* In BE3 FW images the "asic_type_rev" field doesn't track the
31588c2ecf20Sopenharmony_ci	 * asic_rev of the chips it is compatible with.
31598c2ecf20Sopenharmony_ci	 * When asic_type_rev is 0 the image is compatible only with
31608c2ecf20Sopenharmony_ci	 * pre-BE3-R chips (asic_rev < 0x10)
31618c2ecf20Sopenharmony_ci	 */
31628c2ecf20Sopenharmony_ci	if (BEx_chip(adapter) && fhdr->asic_type_rev == 0)
31638c2ecf20Sopenharmony_ci		return adapter->asic_rev < 0x10;
31648c2ecf20Sopenharmony_ci	else
31658c2ecf20Sopenharmony_ci		return (fhdr->asic_type_rev >= adapter->asic_rev);
31668c2ecf20Sopenharmony_ci}
31678c2ecf20Sopenharmony_ci
31688c2ecf20Sopenharmony_ciint be_fw_download(struct be_adapter *adapter, const struct firmware *fw)
31698c2ecf20Sopenharmony_ci{
31708c2ecf20Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
31718c2ecf20Sopenharmony_ci	struct flash_file_hdr_g3 *fhdr3;
31728c2ecf20Sopenharmony_ci	struct image_hdr *img_hdr_ptr;
31738c2ecf20Sopenharmony_ci	int status = 0, i, num_imgs;
31748c2ecf20Sopenharmony_ci	struct be_dma_mem flash_cmd;
31758c2ecf20Sopenharmony_ci
31768c2ecf20Sopenharmony_ci	fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
31778c2ecf20Sopenharmony_ci	if (!be_check_ufi_compatibility(adapter, fhdr3)) {
31788c2ecf20Sopenharmony_ci		dev_err(dev, "Flash image is not compatible with adapter\n");
31798c2ecf20Sopenharmony_ci		return -EINVAL;
31808c2ecf20Sopenharmony_ci	}
31818c2ecf20Sopenharmony_ci
31828c2ecf20Sopenharmony_ci	flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
31838c2ecf20Sopenharmony_ci	flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
31848c2ecf20Sopenharmony_ci					  GFP_KERNEL);
31858c2ecf20Sopenharmony_ci	if (!flash_cmd.va)
31868c2ecf20Sopenharmony_ci		return -ENOMEM;
31878c2ecf20Sopenharmony_ci
31888c2ecf20Sopenharmony_ci	num_imgs = le32_to_cpu(fhdr3->num_imgs);
31898c2ecf20Sopenharmony_ci	for (i = 0; i < num_imgs; i++) {
31908c2ecf20Sopenharmony_ci		img_hdr_ptr = (struct image_hdr *)(fw->data +
31918c2ecf20Sopenharmony_ci				(sizeof(struct flash_file_hdr_g3) +
31928c2ecf20Sopenharmony_ci				 i * sizeof(struct image_hdr)));
31938c2ecf20Sopenharmony_ci		if (!BE2_chip(adapter) &&
31948c2ecf20Sopenharmony_ci		    le32_to_cpu(img_hdr_ptr->imageid) != 1)
31958c2ecf20Sopenharmony_ci			continue;
31968c2ecf20Sopenharmony_ci
31978c2ecf20Sopenharmony_ci		if (skyhawk_chip(adapter))
31988c2ecf20Sopenharmony_ci			status = be_flash_skyhawk(adapter, fw, &flash_cmd,
31998c2ecf20Sopenharmony_ci						  num_imgs);
32008c2ecf20Sopenharmony_ci		else
32018c2ecf20Sopenharmony_ci			status = be_flash_BEx(adapter, fw, &flash_cmd,
32028c2ecf20Sopenharmony_ci					      num_imgs);
32038c2ecf20Sopenharmony_ci	}
32048c2ecf20Sopenharmony_ci
32058c2ecf20Sopenharmony_ci	dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
32068c2ecf20Sopenharmony_ci	if (!status)
32078c2ecf20Sopenharmony_ci		dev_info(dev, "Firmware flashed successfully\n");
32088c2ecf20Sopenharmony_ci
32098c2ecf20Sopenharmony_ci	return status;
32108c2ecf20Sopenharmony_ci}
32118c2ecf20Sopenharmony_ci
32128c2ecf20Sopenharmony_ciint be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
32138c2ecf20Sopenharmony_ci			    struct be_dma_mem *nonemb_cmd)
32148c2ecf20Sopenharmony_ci{
32158c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
32168c2ecf20Sopenharmony_ci	struct be_cmd_req_acpi_wol_magic_config *req;
32178c2ecf20Sopenharmony_ci	int status;
32188c2ecf20Sopenharmony_ci
32198c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
32208c2ecf20Sopenharmony_ci
32218c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
32228c2ecf20Sopenharmony_ci	if (!wrb) {
32238c2ecf20Sopenharmony_ci		status = -EBUSY;
32248c2ecf20Sopenharmony_ci		goto err;
32258c2ecf20Sopenharmony_ci	}
32268c2ecf20Sopenharmony_ci	req = nonemb_cmd->va;
32278c2ecf20Sopenharmony_ci
32288c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
32298c2ecf20Sopenharmony_ci			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req),
32308c2ecf20Sopenharmony_ci			       wrb, nonemb_cmd);
32318c2ecf20Sopenharmony_ci	memcpy(req->magic_mac, mac, ETH_ALEN);
32328c2ecf20Sopenharmony_ci
32338c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
32348c2ecf20Sopenharmony_ci
32358c2ecf20Sopenharmony_cierr:
32368c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
32378c2ecf20Sopenharmony_ci	return status;
32388c2ecf20Sopenharmony_ci}
32398c2ecf20Sopenharmony_ci
32408c2ecf20Sopenharmony_ciint be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
32418c2ecf20Sopenharmony_ci			u8 loopback_type, u8 enable)
32428c2ecf20Sopenharmony_ci{
32438c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
32448c2ecf20Sopenharmony_ci	struct be_cmd_req_set_lmode *req;
32458c2ecf20Sopenharmony_ci	int status;
32468c2ecf20Sopenharmony_ci
32478c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
32488c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_LOWLEVEL))
32498c2ecf20Sopenharmony_ci		return -EPERM;
32508c2ecf20Sopenharmony_ci
32518c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
32528c2ecf20Sopenharmony_ci
32538c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
32548c2ecf20Sopenharmony_ci	if (!wrb) {
32558c2ecf20Sopenharmony_ci		status = -EBUSY;
32568c2ecf20Sopenharmony_ci		goto err_unlock;
32578c2ecf20Sopenharmony_ci	}
32588c2ecf20Sopenharmony_ci
32598c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
32608c2ecf20Sopenharmony_ci
32618c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
32628c2ecf20Sopenharmony_ci			       OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req),
32638c2ecf20Sopenharmony_ci			       wrb, NULL);
32648c2ecf20Sopenharmony_ci
32658c2ecf20Sopenharmony_ci	req->src_port = port_num;
32668c2ecf20Sopenharmony_ci	req->dest_port = port_num;
32678c2ecf20Sopenharmony_ci	req->loopback_type = loopback_type;
32688c2ecf20Sopenharmony_ci	req->loopback_state = enable;
32698c2ecf20Sopenharmony_ci
32708c2ecf20Sopenharmony_ci	status = be_mcc_notify(adapter);
32718c2ecf20Sopenharmony_ci	if (status)
32728c2ecf20Sopenharmony_ci		goto err_unlock;
32738c2ecf20Sopenharmony_ci
32748c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
32758c2ecf20Sopenharmony_ci
32768c2ecf20Sopenharmony_ci	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
32778c2ecf20Sopenharmony_ci					 msecs_to_jiffies(SET_LB_MODE_TIMEOUT)))
32788c2ecf20Sopenharmony_ci		status = -ETIMEDOUT;
32798c2ecf20Sopenharmony_ci
32808c2ecf20Sopenharmony_ci	return status;
32818c2ecf20Sopenharmony_ci
32828c2ecf20Sopenharmony_cierr_unlock:
32838c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
32848c2ecf20Sopenharmony_ci	return status;
32858c2ecf20Sopenharmony_ci}
32868c2ecf20Sopenharmony_ci
32878c2ecf20Sopenharmony_ciint be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
32888c2ecf20Sopenharmony_ci			 u32 loopback_type, u32 pkt_size, u32 num_pkts,
32898c2ecf20Sopenharmony_ci			 u64 pattern)
32908c2ecf20Sopenharmony_ci{
32918c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
32928c2ecf20Sopenharmony_ci	struct be_cmd_req_loopback_test *req;
32938c2ecf20Sopenharmony_ci	struct be_cmd_resp_loopback_test *resp;
32948c2ecf20Sopenharmony_ci	int status;
32958c2ecf20Sopenharmony_ci
32968c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_LOOPBACK_TEST,
32978c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_LOWLEVEL))
32988c2ecf20Sopenharmony_ci		return -EPERM;
32998c2ecf20Sopenharmony_ci
33008c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
33018c2ecf20Sopenharmony_ci
33028c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
33038c2ecf20Sopenharmony_ci	if (!wrb) {
33048c2ecf20Sopenharmony_ci		status = -EBUSY;
33058c2ecf20Sopenharmony_ci		goto err;
33068c2ecf20Sopenharmony_ci	}
33078c2ecf20Sopenharmony_ci
33088c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
33098c2ecf20Sopenharmony_ci
33108c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
33118c2ecf20Sopenharmony_ci			       OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb,
33128c2ecf20Sopenharmony_ci			       NULL);
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_ci	req->hdr.timeout = cpu_to_le32(15);
33158c2ecf20Sopenharmony_ci	req->pattern = cpu_to_le64(pattern);
33168c2ecf20Sopenharmony_ci	req->src_port = cpu_to_le32(port_num);
33178c2ecf20Sopenharmony_ci	req->dest_port = cpu_to_le32(port_num);
33188c2ecf20Sopenharmony_ci	req->pkt_size = cpu_to_le32(pkt_size);
33198c2ecf20Sopenharmony_ci	req->num_pkts = cpu_to_le32(num_pkts);
33208c2ecf20Sopenharmony_ci	req->loopback_type = cpu_to_le32(loopback_type);
33218c2ecf20Sopenharmony_ci
33228c2ecf20Sopenharmony_ci	status = be_mcc_notify(adapter);
33238c2ecf20Sopenharmony_ci	if (status)
33248c2ecf20Sopenharmony_ci		goto err;
33258c2ecf20Sopenharmony_ci
33268c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
33278c2ecf20Sopenharmony_ci
33288c2ecf20Sopenharmony_ci	wait_for_completion(&adapter->et_cmd_compl);
33298c2ecf20Sopenharmony_ci	resp = embedded_payload(wrb);
33308c2ecf20Sopenharmony_ci	status = le32_to_cpu(resp->status);
33318c2ecf20Sopenharmony_ci
33328c2ecf20Sopenharmony_ci	return status;
33338c2ecf20Sopenharmony_cierr:
33348c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
33358c2ecf20Sopenharmony_ci	return status;
33368c2ecf20Sopenharmony_ci}
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ciint be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
33398c2ecf20Sopenharmony_ci			u32 byte_cnt, struct be_dma_mem *cmd)
33408c2ecf20Sopenharmony_ci{
33418c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
33428c2ecf20Sopenharmony_ci	struct be_cmd_req_ddrdma_test *req;
33438c2ecf20Sopenharmony_ci	int status;
33448c2ecf20Sopenharmony_ci	int i, j = 0;
33458c2ecf20Sopenharmony_ci
33468c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_HOST_DDR_DMA,
33478c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_LOWLEVEL))
33488c2ecf20Sopenharmony_ci		return -EPERM;
33498c2ecf20Sopenharmony_ci
33508c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
33518c2ecf20Sopenharmony_ci
33528c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
33538c2ecf20Sopenharmony_ci	if (!wrb) {
33548c2ecf20Sopenharmony_ci		status = -EBUSY;
33558c2ecf20Sopenharmony_ci		goto err;
33568c2ecf20Sopenharmony_ci	}
33578c2ecf20Sopenharmony_ci	req = cmd->va;
33588c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
33598c2ecf20Sopenharmony_ci			       OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb,
33608c2ecf20Sopenharmony_ci			       cmd);
33618c2ecf20Sopenharmony_ci
33628c2ecf20Sopenharmony_ci	req->pattern = cpu_to_le64(pattern);
33638c2ecf20Sopenharmony_ci	req->byte_count = cpu_to_le32(byte_cnt);
33648c2ecf20Sopenharmony_ci	for (i = 0; i < byte_cnt; i++) {
33658c2ecf20Sopenharmony_ci		req->snd_buff[i] = (u8)(pattern >> (j*8));
33668c2ecf20Sopenharmony_ci		j++;
33678c2ecf20Sopenharmony_ci		if (j > 7)
33688c2ecf20Sopenharmony_ci			j = 0;
33698c2ecf20Sopenharmony_ci	}
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
33728c2ecf20Sopenharmony_ci
33738c2ecf20Sopenharmony_ci	if (!status) {
33748c2ecf20Sopenharmony_ci		struct be_cmd_resp_ddrdma_test *resp;
33758c2ecf20Sopenharmony_ci
33768c2ecf20Sopenharmony_ci		resp = cmd->va;
33778c2ecf20Sopenharmony_ci		if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) ||
33788c2ecf20Sopenharmony_ci		    resp->snd_err) {
33798c2ecf20Sopenharmony_ci			status = -1;
33808c2ecf20Sopenharmony_ci		}
33818c2ecf20Sopenharmony_ci	}
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_cierr:
33848c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
33858c2ecf20Sopenharmony_ci	return status;
33868c2ecf20Sopenharmony_ci}
33878c2ecf20Sopenharmony_ci
33888c2ecf20Sopenharmony_ciint be_cmd_get_seeprom_data(struct be_adapter *adapter,
33898c2ecf20Sopenharmony_ci			    struct be_dma_mem *nonemb_cmd)
33908c2ecf20Sopenharmony_ci{
33918c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
33928c2ecf20Sopenharmony_ci	struct be_cmd_req_seeprom_read *req;
33938c2ecf20Sopenharmony_ci	int status;
33948c2ecf20Sopenharmony_ci
33958c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
33968c2ecf20Sopenharmony_ci
33978c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
33988c2ecf20Sopenharmony_ci	if (!wrb) {
33998c2ecf20Sopenharmony_ci		status = -EBUSY;
34008c2ecf20Sopenharmony_ci		goto err;
34018c2ecf20Sopenharmony_ci	}
34028c2ecf20Sopenharmony_ci	req = nonemb_cmd->va;
34038c2ecf20Sopenharmony_ci
34048c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
34058c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb,
34068c2ecf20Sopenharmony_ci			       nonemb_cmd);
34078c2ecf20Sopenharmony_ci
34088c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
34098c2ecf20Sopenharmony_ci
34108c2ecf20Sopenharmony_cierr:
34118c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
34128c2ecf20Sopenharmony_ci	return status;
34138c2ecf20Sopenharmony_ci}
34148c2ecf20Sopenharmony_ci
34158c2ecf20Sopenharmony_ciint be_cmd_get_phy_info(struct be_adapter *adapter)
34168c2ecf20Sopenharmony_ci{
34178c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
34188c2ecf20Sopenharmony_ci	struct be_cmd_req_get_phy_info *req;
34198c2ecf20Sopenharmony_ci	struct be_dma_mem cmd;
34208c2ecf20Sopenharmony_ci	int status;
34218c2ecf20Sopenharmony_ci
34228c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
34238c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
34248c2ecf20Sopenharmony_ci		return -EPERM;
34258c2ecf20Sopenharmony_ci
34268c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
34278c2ecf20Sopenharmony_ci
34288c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
34298c2ecf20Sopenharmony_ci	if (!wrb) {
34308c2ecf20Sopenharmony_ci		status = -EBUSY;
34318c2ecf20Sopenharmony_ci		goto err;
34328c2ecf20Sopenharmony_ci	}
34338c2ecf20Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_req_get_phy_info);
34348c2ecf20Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
34358c2ecf20Sopenharmony_ci				    GFP_ATOMIC);
34368c2ecf20Sopenharmony_ci	if (!cmd.va) {
34378c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
34388c2ecf20Sopenharmony_ci		status = -ENOMEM;
34398c2ecf20Sopenharmony_ci		goto err;
34408c2ecf20Sopenharmony_ci	}
34418c2ecf20Sopenharmony_ci
34428c2ecf20Sopenharmony_ci	req = cmd.va;
34438c2ecf20Sopenharmony_ci
34448c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
34458c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req),
34468c2ecf20Sopenharmony_ci			       wrb, &cmd);
34478c2ecf20Sopenharmony_ci
34488c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
34498c2ecf20Sopenharmony_ci	if (!status) {
34508c2ecf20Sopenharmony_ci		struct be_phy_info *resp_phy_info =
34518c2ecf20Sopenharmony_ci				cmd.va + sizeof(struct be_cmd_req_hdr);
34528c2ecf20Sopenharmony_ci
34538c2ecf20Sopenharmony_ci		adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type);
34548c2ecf20Sopenharmony_ci		adapter->phy.interface_type =
34558c2ecf20Sopenharmony_ci			le16_to_cpu(resp_phy_info->interface_type);
34568c2ecf20Sopenharmony_ci		adapter->phy.auto_speeds_supported =
34578c2ecf20Sopenharmony_ci			le16_to_cpu(resp_phy_info->auto_speeds_supported);
34588c2ecf20Sopenharmony_ci		adapter->phy.fixed_speeds_supported =
34598c2ecf20Sopenharmony_ci			le16_to_cpu(resp_phy_info->fixed_speeds_supported);
34608c2ecf20Sopenharmony_ci		adapter->phy.misc_params =
34618c2ecf20Sopenharmony_ci			le32_to_cpu(resp_phy_info->misc_params);
34628c2ecf20Sopenharmony_ci
34638c2ecf20Sopenharmony_ci		if (BE2_chip(adapter)) {
34648c2ecf20Sopenharmony_ci			adapter->phy.fixed_speeds_supported =
34658c2ecf20Sopenharmony_ci				BE_SUPPORTED_SPEED_10GBPS |
34668c2ecf20Sopenharmony_ci				BE_SUPPORTED_SPEED_1GBPS;
34678c2ecf20Sopenharmony_ci		}
34688c2ecf20Sopenharmony_ci	}
34698c2ecf20Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
34708c2ecf20Sopenharmony_cierr:
34718c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
34728c2ecf20Sopenharmony_ci	return status;
34738c2ecf20Sopenharmony_ci}
34748c2ecf20Sopenharmony_ci
34758c2ecf20Sopenharmony_cistatic int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain)
34768c2ecf20Sopenharmony_ci{
34778c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
34788c2ecf20Sopenharmony_ci	struct be_cmd_req_set_qos *req;
34798c2ecf20Sopenharmony_ci	int status;
34808c2ecf20Sopenharmony_ci
34818c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
34828c2ecf20Sopenharmony_ci
34838c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
34848c2ecf20Sopenharmony_ci	if (!wrb) {
34858c2ecf20Sopenharmony_ci		status = -EBUSY;
34868c2ecf20Sopenharmony_ci		goto err;
34878c2ecf20Sopenharmony_ci	}
34888c2ecf20Sopenharmony_ci
34898c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
34908c2ecf20Sopenharmony_ci
34918c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
34928c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL);
34938c2ecf20Sopenharmony_ci
34948c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
34958c2ecf20Sopenharmony_ci	req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
34968c2ecf20Sopenharmony_ci	req->max_bps_nic = cpu_to_le32(bps);
34978c2ecf20Sopenharmony_ci
34988c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
34998c2ecf20Sopenharmony_ci
35008c2ecf20Sopenharmony_cierr:
35018c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
35028c2ecf20Sopenharmony_ci	return status;
35038c2ecf20Sopenharmony_ci}
35048c2ecf20Sopenharmony_ci
35058c2ecf20Sopenharmony_ciint be_cmd_get_cntl_attributes(struct be_adapter *adapter)
35068c2ecf20Sopenharmony_ci{
35078c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
35088c2ecf20Sopenharmony_ci	struct be_cmd_req_cntl_attribs *req;
35098c2ecf20Sopenharmony_ci	struct be_cmd_resp_cntl_attribs *resp;
35108c2ecf20Sopenharmony_ci	int status, i;
35118c2ecf20Sopenharmony_ci	int payload_len = max(sizeof(*req), sizeof(*resp));
35128c2ecf20Sopenharmony_ci	struct mgmt_controller_attrib *attribs;
35138c2ecf20Sopenharmony_ci	struct be_dma_mem attribs_cmd;
35148c2ecf20Sopenharmony_ci	u32 *serial_num;
35158c2ecf20Sopenharmony_ci
35168c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
35178c2ecf20Sopenharmony_ci		return -1;
35188c2ecf20Sopenharmony_ci
35198c2ecf20Sopenharmony_ci	memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
35208c2ecf20Sopenharmony_ci	attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
35218c2ecf20Sopenharmony_ci	attribs_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
35228c2ecf20Sopenharmony_ci					    attribs_cmd.size,
35238c2ecf20Sopenharmony_ci					    &attribs_cmd.dma, GFP_ATOMIC);
35248c2ecf20Sopenharmony_ci	if (!attribs_cmd.va) {
35258c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
35268c2ecf20Sopenharmony_ci		status = -ENOMEM;
35278c2ecf20Sopenharmony_ci		goto err;
35288c2ecf20Sopenharmony_ci	}
35298c2ecf20Sopenharmony_ci
35308c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
35318c2ecf20Sopenharmony_ci	if (!wrb) {
35328c2ecf20Sopenharmony_ci		status = -EBUSY;
35338c2ecf20Sopenharmony_ci		goto err;
35348c2ecf20Sopenharmony_ci	}
35358c2ecf20Sopenharmony_ci	req = attribs_cmd.va;
35368c2ecf20Sopenharmony_ci
35378c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
35388c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len,
35398c2ecf20Sopenharmony_ci			       wrb, &attribs_cmd);
35408c2ecf20Sopenharmony_ci
35418c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
35428c2ecf20Sopenharmony_ci	if (!status) {
35438c2ecf20Sopenharmony_ci		attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
35448c2ecf20Sopenharmony_ci		adapter->hba_port_num = attribs->hba_attribs.phy_port;
35458c2ecf20Sopenharmony_ci		serial_num = attribs->hba_attribs.controller_serial_number;
35468c2ecf20Sopenharmony_ci		for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++)
35478c2ecf20Sopenharmony_ci			adapter->serial_num[i] = le32_to_cpu(serial_num[i]) &
35488c2ecf20Sopenharmony_ci				(BIT_MASK(16) - 1);
35498c2ecf20Sopenharmony_ci		/* For BEx, since GET_FUNC_CONFIG command is not
35508c2ecf20Sopenharmony_ci		 * supported, we read funcnum here as a workaround.
35518c2ecf20Sopenharmony_ci		 */
35528c2ecf20Sopenharmony_ci		if (BEx_chip(adapter))
35538c2ecf20Sopenharmony_ci			adapter->pf_num = attribs->hba_attribs.pci_funcnum;
35548c2ecf20Sopenharmony_ci	}
35558c2ecf20Sopenharmony_ci
35568c2ecf20Sopenharmony_cierr:
35578c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
35588c2ecf20Sopenharmony_ci	if (attribs_cmd.va)
35598c2ecf20Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, attribs_cmd.size,
35608c2ecf20Sopenharmony_ci				  attribs_cmd.va, attribs_cmd.dma);
35618c2ecf20Sopenharmony_ci	return status;
35628c2ecf20Sopenharmony_ci}
35638c2ecf20Sopenharmony_ci
35648c2ecf20Sopenharmony_ci/* Uses mbox */
35658c2ecf20Sopenharmony_ciint be_cmd_req_native_mode(struct be_adapter *adapter)
35668c2ecf20Sopenharmony_ci{
35678c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
35688c2ecf20Sopenharmony_ci	struct be_cmd_req_set_func_cap *req;
35698c2ecf20Sopenharmony_ci	int status;
35708c2ecf20Sopenharmony_ci
35718c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
35728c2ecf20Sopenharmony_ci		return -1;
35738c2ecf20Sopenharmony_ci
35748c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
35758c2ecf20Sopenharmony_ci	if (!wrb) {
35768c2ecf20Sopenharmony_ci		status = -EBUSY;
35778c2ecf20Sopenharmony_ci		goto err;
35788c2ecf20Sopenharmony_ci	}
35798c2ecf20Sopenharmony_ci
35808c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
35818c2ecf20Sopenharmony_ci
35828c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
35838c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP,
35848c2ecf20Sopenharmony_ci			       sizeof(*req), wrb, NULL);
35858c2ecf20Sopenharmony_ci
35868c2ecf20Sopenharmony_ci	req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS |
35878c2ecf20Sopenharmony_ci				CAPABILITY_BE3_NATIVE_ERX_API);
35888c2ecf20Sopenharmony_ci	req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API);
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
35918c2ecf20Sopenharmony_ci	if (!status) {
35928c2ecf20Sopenharmony_ci		struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb);
35938c2ecf20Sopenharmony_ci
35948c2ecf20Sopenharmony_ci		adapter->be3_native = le32_to_cpu(resp->cap_flags) &
35958c2ecf20Sopenharmony_ci					CAPABILITY_BE3_NATIVE_ERX_API;
35968c2ecf20Sopenharmony_ci		if (!adapter->be3_native)
35978c2ecf20Sopenharmony_ci			dev_warn(&adapter->pdev->dev,
35988c2ecf20Sopenharmony_ci				 "adapter not in advanced mode\n");
35998c2ecf20Sopenharmony_ci	}
36008c2ecf20Sopenharmony_cierr:
36018c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
36028c2ecf20Sopenharmony_ci	return status;
36038c2ecf20Sopenharmony_ci}
36048c2ecf20Sopenharmony_ci
36058c2ecf20Sopenharmony_ci/* Get privilege(s) for a function */
36068c2ecf20Sopenharmony_ciint be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
36078c2ecf20Sopenharmony_ci			     u32 domain)
36088c2ecf20Sopenharmony_ci{
36098c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
36108c2ecf20Sopenharmony_ci	struct be_cmd_req_get_fn_privileges *req;
36118c2ecf20Sopenharmony_ci	int status;
36128c2ecf20Sopenharmony_ci
36138c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
36148c2ecf20Sopenharmony_ci
36158c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
36168c2ecf20Sopenharmony_ci	if (!wrb) {
36178c2ecf20Sopenharmony_ci		status = -EBUSY;
36188c2ecf20Sopenharmony_ci		goto err;
36198c2ecf20Sopenharmony_ci	}
36208c2ecf20Sopenharmony_ci
36218c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
36228c2ecf20Sopenharmony_ci
36238c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
36248c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
36258c2ecf20Sopenharmony_ci			       wrb, NULL);
36268c2ecf20Sopenharmony_ci
36278c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
36288c2ecf20Sopenharmony_ci
36298c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
36308c2ecf20Sopenharmony_ci	if (!status) {
36318c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_fn_privileges *resp =
36328c2ecf20Sopenharmony_ci						embedded_payload(wrb);
36338c2ecf20Sopenharmony_ci
36348c2ecf20Sopenharmony_ci		*privilege = le32_to_cpu(resp->privilege_mask);
36358c2ecf20Sopenharmony_ci
36368c2ecf20Sopenharmony_ci		/* In UMC mode FW does not return right privileges.
36378c2ecf20Sopenharmony_ci		 * Override with correct privilege equivalent to PF.
36388c2ecf20Sopenharmony_ci		 */
36398c2ecf20Sopenharmony_ci		if (BEx_chip(adapter) && be_is_mc(adapter) &&
36408c2ecf20Sopenharmony_ci		    be_physfn(adapter))
36418c2ecf20Sopenharmony_ci			*privilege = MAX_PRIVILEGES;
36428c2ecf20Sopenharmony_ci	}
36438c2ecf20Sopenharmony_ci
36448c2ecf20Sopenharmony_cierr:
36458c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
36468c2ecf20Sopenharmony_ci	return status;
36478c2ecf20Sopenharmony_ci}
36488c2ecf20Sopenharmony_ci
36498c2ecf20Sopenharmony_ci/* Set privilege(s) for a function */
36508c2ecf20Sopenharmony_ciint be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges,
36518c2ecf20Sopenharmony_ci			     u32 domain)
36528c2ecf20Sopenharmony_ci{
36538c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
36548c2ecf20Sopenharmony_ci	struct be_cmd_req_set_fn_privileges *req;
36558c2ecf20Sopenharmony_ci	int status;
36568c2ecf20Sopenharmony_ci
36578c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
36588c2ecf20Sopenharmony_ci
36598c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
36608c2ecf20Sopenharmony_ci	if (!wrb) {
36618c2ecf20Sopenharmony_ci		status = -EBUSY;
36628c2ecf20Sopenharmony_ci		goto err;
36638c2ecf20Sopenharmony_ci	}
36648c2ecf20Sopenharmony_ci
36658c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
36668c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
36678c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req),
36688c2ecf20Sopenharmony_ci			       wrb, NULL);
36698c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
36708c2ecf20Sopenharmony_ci	if (lancer_chip(adapter))
36718c2ecf20Sopenharmony_ci		req->privileges_lancer = cpu_to_le32(privileges);
36728c2ecf20Sopenharmony_ci	else
36738c2ecf20Sopenharmony_ci		req->privileges = cpu_to_le32(privileges);
36748c2ecf20Sopenharmony_ci
36758c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
36768c2ecf20Sopenharmony_cierr:
36778c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
36788c2ecf20Sopenharmony_ci	return status;
36798c2ecf20Sopenharmony_ci}
36808c2ecf20Sopenharmony_ci
36818c2ecf20Sopenharmony_ci/* pmac_id_valid: true => pmac_id is supplied and MAC address is requested.
36828c2ecf20Sopenharmony_ci * pmac_id_valid: false => pmac_id or MAC address is requested.
36838c2ecf20Sopenharmony_ci *		  If pmac_id is returned, pmac_id_valid is returned as true
36848c2ecf20Sopenharmony_ci */
36858c2ecf20Sopenharmony_ciint be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
36868c2ecf20Sopenharmony_ci			     bool *pmac_id_valid, u32 *pmac_id, u32 if_handle,
36878c2ecf20Sopenharmony_ci			     u8 domain)
36888c2ecf20Sopenharmony_ci{
36898c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
36908c2ecf20Sopenharmony_ci	struct be_cmd_req_get_mac_list *req;
36918c2ecf20Sopenharmony_ci	int status;
36928c2ecf20Sopenharmony_ci	int mac_count;
36938c2ecf20Sopenharmony_ci	struct be_dma_mem get_mac_list_cmd;
36948c2ecf20Sopenharmony_ci	int i;
36958c2ecf20Sopenharmony_ci
36968c2ecf20Sopenharmony_ci	memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
36978c2ecf20Sopenharmony_ci	get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
36988c2ecf20Sopenharmony_ci	get_mac_list_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
36998c2ecf20Sopenharmony_ci						 get_mac_list_cmd.size,
37008c2ecf20Sopenharmony_ci						 &get_mac_list_cmd.dma,
37018c2ecf20Sopenharmony_ci						 GFP_ATOMIC);
37028c2ecf20Sopenharmony_ci
37038c2ecf20Sopenharmony_ci	if (!get_mac_list_cmd.va) {
37048c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev,
37058c2ecf20Sopenharmony_ci			"Memory allocation failure during GET_MAC_LIST\n");
37068c2ecf20Sopenharmony_ci		return -ENOMEM;
37078c2ecf20Sopenharmony_ci	}
37088c2ecf20Sopenharmony_ci
37098c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
37108c2ecf20Sopenharmony_ci
37118c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
37128c2ecf20Sopenharmony_ci	if (!wrb) {
37138c2ecf20Sopenharmony_ci		status = -EBUSY;
37148c2ecf20Sopenharmony_ci		goto out;
37158c2ecf20Sopenharmony_ci	}
37168c2ecf20Sopenharmony_ci
37178c2ecf20Sopenharmony_ci	req = get_mac_list_cmd.va;
37188c2ecf20Sopenharmony_ci
37198c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
37208c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_MAC_LIST,
37218c2ecf20Sopenharmony_ci			       get_mac_list_cmd.size, wrb, &get_mac_list_cmd);
37228c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
37238c2ecf20Sopenharmony_ci	req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
37248c2ecf20Sopenharmony_ci	if (*pmac_id_valid) {
37258c2ecf20Sopenharmony_ci		req->mac_id = cpu_to_le32(*pmac_id);
37268c2ecf20Sopenharmony_ci		req->iface_id = cpu_to_le16(if_handle);
37278c2ecf20Sopenharmony_ci		req->perm_override = 0;
37288c2ecf20Sopenharmony_ci	} else {
37298c2ecf20Sopenharmony_ci		req->perm_override = 1;
37308c2ecf20Sopenharmony_ci	}
37318c2ecf20Sopenharmony_ci
37328c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
37338c2ecf20Sopenharmony_ci	if (!status) {
37348c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_mac_list *resp =
37358c2ecf20Sopenharmony_ci						get_mac_list_cmd.va;
37368c2ecf20Sopenharmony_ci
37378c2ecf20Sopenharmony_ci		if (*pmac_id_valid) {
37388c2ecf20Sopenharmony_ci			memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr,
37398c2ecf20Sopenharmony_ci			       ETH_ALEN);
37408c2ecf20Sopenharmony_ci			goto out;
37418c2ecf20Sopenharmony_ci		}
37428c2ecf20Sopenharmony_ci
37438c2ecf20Sopenharmony_ci		mac_count = resp->true_mac_count + resp->pseudo_mac_count;
37448c2ecf20Sopenharmony_ci		/* Mac list returned could contain one or more active mac_ids
37458c2ecf20Sopenharmony_ci		 * or one or more true or pseudo permanent mac addresses.
37468c2ecf20Sopenharmony_ci		 * If an active mac_id is present, return first active mac_id
37478c2ecf20Sopenharmony_ci		 * found.
37488c2ecf20Sopenharmony_ci		 */
37498c2ecf20Sopenharmony_ci		for (i = 0; i < mac_count; i++) {
37508c2ecf20Sopenharmony_ci			struct get_list_macaddr *mac_entry;
37518c2ecf20Sopenharmony_ci			u16 mac_addr_size;
37528c2ecf20Sopenharmony_ci			u32 mac_id;
37538c2ecf20Sopenharmony_ci
37548c2ecf20Sopenharmony_ci			mac_entry = &resp->macaddr_list[i];
37558c2ecf20Sopenharmony_ci			mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size);
37568c2ecf20Sopenharmony_ci			/* mac_id is a 32 bit value and mac_addr size
37578c2ecf20Sopenharmony_ci			 * is 6 bytes
37588c2ecf20Sopenharmony_ci			 */
37598c2ecf20Sopenharmony_ci			if (mac_addr_size == sizeof(u32)) {
37608c2ecf20Sopenharmony_ci				*pmac_id_valid = true;
37618c2ecf20Sopenharmony_ci				mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id;
37628c2ecf20Sopenharmony_ci				*pmac_id = le32_to_cpu(mac_id);
37638c2ecf20Sopenharmony_ci				goto out;
37648c2ecf20Sopenharmony_ci			}
37658c2ecf20Sopenharmony_ci		}
37668c2ecf20Sopenharmony_ci		/* If no active mac_id found, return first mac addr */
37678c2ecf20Sopenharmony_ci		*pmac_id_valid = false;
37688c2ecf20Sopenharmony_ci		memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr,
37698c2ecf20Sopenharmony_ci		       ETH_ALEN);
37708c2ecf20Sopenharmony_ci	}
37718c2ecf20Sopenharmony_ci
37728c2ecf20Sopenharmony_ciout:
37738c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
37748c2ecf20Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, get_mac_list_cmd.size,
37758c2ecf20Sopenharmony_ci			  get_mac_list_cmd.va, get_mac_list_cmd.dma);
37768c2ecf20Sopenharmony_ci	return status;
37778c2ecf20Sopenharmony_ci}
37788c2ecf20Sopenharmony_ci
37798c2ecf20Sopenharmony_ciint be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id,
37808c2ecf20Sopenharmony_ci			  u8 *mac, u32 if_handle, bool active, u32 domain)
37818c2ecf20Sopenharmony_ci{
37828c2ecf20Sopenharmony_ci	if (!active)
37838c2ecf20Sopenharmony_ci		be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id,
37848c2ecf20Sopenharmony_ci					 if_handle, domain);
37858c2ecf20Sopenharmony_ci	if (BEx_chip(adapter))
37868c2ecf20Sopenharmony_ci		return be_cmd_mac_addr_query(adapter, mac, false,
37878c2ecf20Sopenharmony_ci					     if_handle, curr_pmac_id);
37888c2ecf20Sopenharmony_ci	else
37898c2ecf20Sopenharmony_ci		/* Fetch the MAC address using pmac_id */
37908c2ecf20Sopenharmony_ci		return be_cmd_get_mac_from_list(adapter, mac, &active,
37918c2ecf20Sopenharmony_ci						&curr_pmac_id,
37928c2ecf20Sopenharmony_ci						if_handle, domain);
37938c2ecf20Sopenharmony_ci}
37948c2ecf20Sopenharmony_ci
37958c2ecf20Sopenharmony_ciint be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac)
37968c2ecf20Sopenharmony_ci{
37978c2ecf20Sopenharmony_ci	int status;
37988c2ecf20Sopenharmony_ci	bool pmac_valid = false;
37998c2ecf20Sopenharmony_ci
38008c2ecf20Sopenharmony_ci	eth_zero_addr(mac);
38018c2ecf20Sopenharmony_ci
38028c2ecf20Sopenharmony_ci	if (BEx_chip(adapter)) {
38038c2ecf20Sopenharmony_ci		if (be_physfn(adapter))
38048c2ecf20Sopenharmony_ci			status = be_cmd_mac_addr_query(adapter, mac, true, 0,
38058c2ecf20Sopenharmony_ci						       0);
38068c2ecf20Sopenharmony_ci		else
38078c2ecf20Sopenharmony_ci			status = be_cmd_mac_addr_query(adapter, mac, false,
38088c2ecf20Sopenharmony_ci						       adapter->if_handle, 0);
38098c2ecf20Sopenharmony_ci	} else {
38108c2ecf20Sopenharmony_ci		status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid,
38118c2ecf20Sopenharmony_ci						  NULL, adapter->if_handle, 0);
38128c2ecf20Sopenharmony_ci	}
38138c2ecf20Sopenharmony_ci
38148c2ecf20Sopenharmony_ci	return status;
38158c2ecf20Sopenharmony_ci}
38168c2ecf20Sopenharmony_ci
38178c2ecf20Sopenharmony_ci/* Uses synchronous MCCQ */
38188c2ecf20Sopenharmony_ciint be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
38198c2ecf20Sopenharmony_ci			u8 mac_count, u32 domain)
38208c2ecf20Sopenharmony_ci{
38218c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
38228c2ecf20Sopenharmony_ci	struct be_cmd_req_set_mac_list *req;
38238c2ecf20Sopenharmony_ci	int status;
38248c2ecf20Sopenharmony_ci	struct be_dma_mem cmd;
38258c2ecf20Sopenharmony_ci
38268c2ecf20Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
38278c2ecf20Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_req_set_mac_list);
38288c2ecf20Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
38298c2ecf20Sopenharmony_ci				    GFP_KERNEL);
38308c2ecf20Sopenharmony_ci	if (!cmd.va)
38318c2ecf20Sopenharmony_ci		return -ENOMEM;
38328c2ecf20Sopenharmony_ci
38338c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
38348c2ecf20Sopenharmony_ci
38358c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
38368c2ecf20Sopenharmony_ci	if (!wrb) {
38378c2ecf20Sopenharmony_ci		status = -EBUSY;
38388c2ecf20Sopenharmony_ci		goto err;
38398c2ecf20Sopenharmony_ci	}
38408c2ecf20Sopenharmony_ci
38418c2ecf20Sopenharmony_ci	req = cmd.va;
38428c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
38438c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_MAC_LIST, sizeof(*req),
38448c2ecf20Sopenharmony_ci			       wrb, &cmd);
38458c2ecf20Sopenharmony_ci
38468c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
38478c2ecf20Sopenharmony_ci	req->mac_count = mac_count;
38488c2ecf20Sopenharmony_ci	if (mac_count)
38498c2ecf20Sopenharmony_ci		memcpy(req->mac, mac_array, ETH_ALEN*mac_count);
38508c2ecf20Sopenharmony_ci
38518c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
38528c2ecf20Sopenharmony_ci
38538c2ecf20Sopenharmony_cierr:
38548c2ecf20Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
38558c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
38568c2ecf20Sopenharmony_ci	return status;
38578c2ecf20Sopenharmony_ci}
38588c2ecf20Sopenharmony_ci
38598c2ecf20Sopenharmony_ci/* Wrapper to delete any active MACs and provision the new mac.
38608c2ecf20Sopenharmony_ci * Changes to MAC_LIST are allowed iff none of the MAC addresses in the
38618c2ecf20Sopenharmony_ci * current list are active.
38628c2ecf20Sopenharmony_ci */
38638c2ecf20Sopenharmony_ciint be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
38648c2ecf20Sopenharmony_ci{
38658c2ecf20Sopenharmony_ci	bool active_mac = false;
38668c2ecf20Sopenharmony_ci	u8 old_mac[ETH_ALEN];
38678c2ecf20Sopenharmony_ci	u32 pmac_id;
38688c2ecf20Sopenharmony_ci	int status;
38698c2ecf20Sopenharmony_ci
38708c2ecf20Sopenharmony_ci	status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
38718c2ecf20Sopenharmony_ci					  &pmac_id, if_id, dom);
38728c2ecf20Sopenharmony_ci
38738c2ecf20Sopenharmony_ci	if (!status && active_mac)
38748c2ecf20Sopenharmony_ci		be_cmd_pmac_del(adapter, if_id, pmac_id, dom);
38758c2ecf20Sopenharmony_ci
38768c2ecf20Sopenharmony_ci	return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom);
38778c2ecf20Sopenharmony_ci}
38788c2ecf20Sopenharmony_ci
38798c2ecf20Sopenharmony_ciint be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
38808c2ecf20Sopenharmony_ci			  u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk)
38818c2ecf20Sopenharmony_ci{
38828c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
38838c2ecf20Sopenharmony_ci	struct be_cmd_req_set_hsw_config *req;
38848c2ecf20Sopenharmony_ci	void *ctxt;
38858c2ecf20Sopenharmony_ci	int status;
38868c2ecf20Sopenharmony_ci
38878c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_HSW_CONFIG,
38888c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
38898c2ecf20Sopenharmony_ci		return -EPERM;
38908c2ecf20Sopenharmony_ci
38918c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
38928c2ecf20Sopenharmony_ci
38938c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
38948c2ecf20Sopenharmony_ci	if (!wrb) {
38958c2ecf20Sopenharmony_ci		status = -EBUSY;
38968c2ecf20Sopenharmony_ci		goto err;
38978c2ecf20Sopenharmony_ci	}
38988c2ecf20Sopenharmony_ci
38998c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
39008c2ecf20Sopenharmony_ci	ctxt = &req->context;
39018c2ecf20Sopenharmony_ci
39028c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
39038c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb,
39048c2ecf20Sopenharmony_ci			       NULL);
39058c2ecf20Sopenharmony_ci
39068c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
39078c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id);
39088c2ecf20Sopenharmony_ci	if (pvid) {
39098c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1);
39108c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid);
39118c2ecf20Sopenharmony_ci	}
39128c2ecf20Sopenharmony_ci	if (hsw_mode) {
39138c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, interface_id,
39148c2ecf20Sopenharmony_ci			      ctxt, adapter->hba_port_num);
39158c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1);
39168c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type,
39178c2ecf20Sopenharmony_ci			      ctxt, hsw_mode);
39188c2ecf20Sopenharmony_ci	}
39198c2ecf20Sopenharmony_ci
39208c2ecf20Sopenharmony_ci	/* Enable/disable both mac and vlan spoof checking */
39218c2ecf20Sopenharmony_ci	if (!BEx_chip(adapter) && spoofchk) {
39228c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk,
39238c2ecf20Sopenharmony_ci			      ctxt, spoofchk);
39248c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk,
39258c2ecf20Sopenharmony_ci			      ctxt, spoofchk);
39268c2ecf20Sopenharmony_ci	}
39278c2ecf20Sopenharmony_ci
39288c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(req->context, sizeof(req->context));
39298c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
39308c2ecf20Sopenharmony_ci
39318c2ecf20Sopenharmony_cierr:
39328c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
39338c2ecf20Sopenharmony_ci	return status;
39348c2ecf20Sopenharmony_ci}
39358c2ecf20Sopenharmony_ci
39368c2ecf20Sopenharmony_ci/* Get Hyper switch config */
39378c2ecf20Sopenharmony_ciint be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
39388c2ecf20Sopenharmony_ci			  u32 domain, u16 intf_id, u8 *mode, bool *spoofchk)
39398c2ecf20Sopenharmony_ci{
39408c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
39418c2ecf20Sopenharmony_ci	struct be_cmd_req_get_hsw_config *req;
39428c2ecf20Sopenharmony_ci	void *ctxt;
39438c2ecf20Sopenharmony_ci	int status;
39448c2ecf20Sopenharmony_ci	u16 vid;
39458c2ecf20Sopenharmony_ci
39468c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
39478c2ecf20Sopenharmony_ci
39488c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
39498c2ecf20Sopenharmony_ci	if (!wrb) {
39508c2ecf20Sopenharmony_ci		status = -EBUSY;
39518c2ecf20Sopenharmony_ci		goto err;
39528c2ecf20Sopenharmony_ci	}
39538c2ecf20Sopenharmony_ci
39548c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
39558c2ecf20Sopenharmony_ci	ctxt = &req->context;
39568c2ecf20Sopenharmony_ci
39578c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
39588c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb,
39598c2ecf20Sopenharmony_ci			       NULL);
39608c2ecf20Sopenharmony_ci
39618c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
39628c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
39638c2ecf20Sopenharmony_ci		      ctxt, intf_id);
39648c2ecf20Sopenharmony_ci	AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1);
39658c2ecf20Sopenharmony_ci
39668c2ecf20Sopenharmony_ci	if (!BEx_chip(adapter) && mode) {
39678c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
39688c2ecf20Sopenharmony_ci			      ctxt, adapter->hba_port_num);
39698c2ecf20Sopenharmony_ci		AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1);
39708c2ecf20Sopenharmony_ci	}
39718c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(req->context, sizeof(req->context));
39728c2ecf20Sopenharmony_ci
39738c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
39748c2ecf20Sopenharmony_ci	if (!status) {
39758c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_hsw_config *resp =
39768c2ecf20Sopenharmony_ci						embedded_payload(wrb);
39778c2ecf20Sopenharmony_ci
39788c2ecf20Sopenharmony_ci		be_dws_le_to_cpu(&resp->context, sizeof(resp->context));
39798c2ecf20Sopenharmony_ci		vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
39808c2ecf20Sopenharmony_ci				    pvid, &resp->context);
39818c2ecf20Sopenharmony_ci		if (pvid)
39828c2ecf20Sopenharmony_ci			*pvid = le16_to_cpu(vid);
39838c2ecf20Sopenharmony_ci		if (mode)
39848c2ecf20Sopenharmony_ci			*mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
39858c2ecf20Sopenharmony_ci					      port_fwd_type, &resp->context);
39868c2ecf20Sopenharmony_ci		if (spoofchk)
39878c2ecf20Sopenharmony_ci			*spoofchk =
39888c2ecf20Sopenharmony_ci				AMAP_GET_BITS(struct amap_get_hsw_resp_context,
39898c2ecf20Sopenharmony_ci					      spoofchk, &resp->context);
39908c2ecf20Sopenharmony_ci	}
39918c2ecf20Sopenharmony_ci
39928c2ecf20Sopenharmony_cierr:
39938c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
39948c2ecf20Sopenharmony_ci	return status;
39958c2ecf20Sopenharmony_ci}
39968c2ecf20Sopenharmony_ci
39978c2ecf20Sopenharmony_cistatic bool be_is_wol_excluded(struct be_adapter *adapter)
39988c2ecf20Sopenharmony_ci{
39998c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
40008c2ecf20Sopenharmony_ci
40018c2ecf20Sopenharmony_ci	if (be_virtfn(adapter))
40028c2ecf20Sopenharmony_ci		return true;
40038c2ecf20Sopenharmony_ci
40048c2ecf20Sopenharmony_ci	switch (pdev->subsystem_device) {
40058c2ecf20Sopenharmony_ci	case OC_SUBSYS_DEVICE_ID1:
40068c2ecf20Sopenharmony_ci	case OC_SUBSYS_DEVICE_ID2:
40078c2ecf20Sopenharmony_ci	case OC_SUBSYS_DEVICE_ID3:
40088c2ecf20Sopenharmony_ci	case OC_SUBSYS_DEVICE_ID4:
40098c2ecf20Sopenharmony_ci		return true;
40108c2ecf20Sopenharmony_ci	default:
40118c2ecf20Sopenharmony_ci		return false;
40128c2ecf20Sopenharmony_ci	}
40138c2ecf20Sopenharmony_ci}
40148c2ecf20Sopenharmony_ci
40158c2ecf20Sopenharmony_ciint be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
40168c2ecf20Sopenharmony_ci{
40178c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
40188c2ecf20Sopenharmony_ci	struct be_cmd_req_acpi_wol_magic_config_v1 *req;
40198c2ecf20Sopenharmony_ci	int status = 0;
40208c2ecf20Sopenharmony_ci	struct be_dma_mem cmd;
40218c2ecf20Sopenharmony_ci
40228c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
40238c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_ETH))
40248c2ecf20Sopenharmony_ci		return -EPERM;
40258c2ecf20Sopenharmony_ci
40268c2ecf20Sopenharmony_ci	if (be_is_wol_excluded(adapter))
40278c2ecf20Sopenharmony_ci		return status;
40288c2ecf20Sopenharmony_ci
40298c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
40308c2ecf20Sopenharmony_ci		return -1;
40318c2ecf20Sopenharmony_ci
40328c2ecf20Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
40338c2ecf20Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
40348c2ecf20Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
40358c2ecf20Sopenharmony_ci				    GFP_ATOMIC);
40368c2ecf20Sopenharmony_ci	if (!cmd.va) {
40378c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
40388c2ecf20Sopenharmony_ci		status = -ENOMEM;
40398c2ecf20Sopenharmony_ci		goto err;
40408c2ecf20Sopenharmony_ci	}
40418c2ecf20Sopenharmony_ci
40428c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
40438c2ecf20Sopenharmony_ci	if (!wrb) {
40448c2ecf20Sopenharmony_ci		status = -EBUSY;
40458c2ecf20Sopenharmony_ci		goto err;
40468c2ecf20Sopenharmony_ci	}
40478c2ecf20Sopenharmony_ci
40488c2ecf20Sopenharmony_ci	req = cmd.va;
40498c2ecf20Sopenharmony_ci
40508c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
40518c2ecf20Sopenharmony_ci			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
40528c2ecf20Sopenharmony_ci			       sizeof(*req), wrb, &cmd);
40538c2ecf20Sopenharmony_ci
40548c2ecf20Sopenharmony_ci	req->hdr.version = 1;
40558c2ecf20Sopenharmony_ci	req->query_options = BE_GET_WOL_CAP;
40568c2ecf20Sopenharmony_ci
40578c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
40588c2ecf20Sopenharmony_ci	if (!status) {
40598c2ecf20Sopenharmony_ci		struct be_cmd_resp_acpi_wol_magic_config_v1 *resp;
40608c2ecf20Sopenharmony_ci
40618c2ecf20Sopenharmony_ci		resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va;
40628c2ecf20Sopenharmony_ci
40638c2ecf20Sopenharmony_ci		adapter->wol_cap = resp->wol_settings;
40648c2ecf20Sopenharmony_ci
40658c2ecf20Sopenharmony_ci		/* Non-zero macaddr indicates WOL is enabled */
40668c2ecf20Sopenharmony_ci		if (adapter->wol_cap & BE_WOL_CAP &&
40678c2ecf20Sopenharmony_ci		    !is_zero_ether_addr(resp->magic_mac))
40688c2ecf20Sopenharmony_ci			adapter->wol_en = true;
40698c2ecf20Sopenharmony_ci	}
40708c2ecf20Sopenharmony_cierr:
40718c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
40728c2ecf20Sopenharmony_ci	if (cmd.va)
40738c2ecf20Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
40748c2ecf20Sopenharmony_ci				  cmd.dma);
40758c2ecf20Sopenharmony_ci	return status;
40768c2ecf20Sopenharmony_ci
40778c2ecf20Sopenharmony_ci}
40788c2ecf20Sopenharmony_ci
40798c2ecf20Sopenharmony_ciint be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level)
40808c2ecf20Sopenharmony_ci{
40818c2ecf20Sopenharmony_ci	struct be_dma_mem extfat_cmd;
40828c2ecf20Sopenharmony_ci	struct be_fat_conf_params *cfgs;
40838c2ecf20Sopenharmony_ci	int status;
40848c2ecf20Sopenharmony_ci	int i, j;
40858c2ecf20Sopenharmony_ci
40868c2ecf20Sopenharmony_ci	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
40878c2ecf20Sopenharmony_ci	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
40888c2ecf20Sopenharmony_ci	extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
40898c2ecf20Sopenharmony_ci					   extfat_cmd.size, &extfat_cmd.dma,
40908c2ecf20Sopenharmony_ci					   GFP_ATOMIC);
40918c2ecf20Sopenharmony_ci	if (!extfat_cmd.va)
40928c2ecf20Sopenharmony_ci		return -ENOMEM;
40938c2ecf20Sopenharmony_ci
40948c2ecf20Sopenharmony_ci	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
40958c2ecf20Sopenharmony_ci	if (status)
40968c2ecf20Sopenharmony_ci		goto err;
40978c2ecf20Sopenharmony_ci
40988c2ecf20Sopenharmony_ci	cfgs = (struct be_fat_conf_params *)
40998c2ecf20Sopenharmony_ci			(extfat_cmd.va + sizeof(struct be_cmd_resp_hdr));
41008c2ecf20Sopenharmony_ci	for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) {
41018c2ecf20Sopenharmony_ci		u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes);
41028c2ecf20Sopenharmony_ci
41038c2ecf20Sopenharmony_ci		for (j = 0; j < num_modes; j++) {
41048c2ecf20Sopenharmony_ci			if (cfgs->module[i].trace_lvl[j].mode == MODE_UART)
41058c2ecf20Sopenharmony_ci				cfgs->module[i].trace_lvl[j].dbg_lvl =
41068c2ecf20Sopenharmony_ci							cpu_to_le32(level);
41078c2ecf20Sopenharmony_ci		}
41088c2ecf20Sopenharmony_ci	}
41098c2ecf20Sopenharmony_ci
41108c2ecf20Sopenharmony_ci	status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs);
41118c2ecf20Sopenharmony_cierr:
41128c2ecf20Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va,
41138c2ecf20Sopenharmony_ci			  extfat_cmd.dma);
41148c2ecf20Sopenharmony_ci	return status;
41158c2ecf20Sopenharmony_ci}
41168c2ecf20Sopenharmony_ci
41178c2ecf20Sopenharmony_ciint be_cmd_get_fw_log_level(struct be_adapter *adapter)
41188c2ecf20Sopenharmony_ci{
41198c2ecf20Sopenharmony_ci	struct be_dma_mem extfat_cmd;
41208c2ecf20Sopenharmony_ci	struct be_fat_conf_params *cfgs;
41218c2ecf20Sopenharmony_ci	int status, j;
41228c2ecf20Sopenharmony_ci	int level = 0;
41238c2ecf20Sopenharmony_ci
41248c2ecf20Sopenharmony_ci	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
41258c2ecf20Sopenharmony_ci	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
41268c2ecf20Sopenharmony_ci	extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
41278c2ecf20Sopenharmony_ci					   extfat_cmd.size, &extfat_cmd.dma,
41288c2ecf20Sopenharmony_ci					   GFP_ATOMIC);
41298c2ecf20Sopenharmony_ci
41308c2ecf20Sopenharmony_ci	if (!extfat_cmd.va) {
41318c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
41328c2ecf20Sopenharmony_ci			__func__);
41338c2ecf20Sopenharmony_ci		goto err;
41348c2ecf20Sopenharmony_ci	}
41358c2ecf20Sopenharmony_ci
41368c2ecf20Sopenharmony_ci	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
41378c2ecf20Sopenharmony_ci	if (!status) {
41388c2ecf20Sopenharmony_ci		cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
41398c2ecf20Sopenharmony_ci						sizeof(struct be_cmd_resp_hdr));
41408c2ecf20Sopenharmony_ci
41418c2ecf20Sopenharmony_ci		for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) {
41428c2ecf20Sopenharmony_ci			if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
41438c2ecf20Sopenharmony_ci				level = cfgs->module[0].trace_lvl[j].dbg_lvl;
41448c2ecf20Sopenharmony_ci		}
41458c2ecf20Sopenharmony_ci	}
41468c2ecf20Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va,
41478c2ecf20Sopenharmony_ci			  extfat_cmd.dma);
41488c2ecf20Sopenharmony_cierr:
41498c2ecf20Sopenharmony_ci	return level;
41508c2ecf20Sopenharmony_ci}
41518c2ecf20Sopenharmony_ci
41528c2ecf20Sopenharmony_ciint be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
41538c2ecf20Sopenharmony_ci				   struct be_dma_mem *cmd)
41548c2ecf20Sopenharmony_ci{
41558c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
41568c2ecf20Sopenharmony_ci	struct be_cmd_req_get_ext_fat_caps *req;
41578c2ecf20Sopenharmony_ci	int status;
41588c2ecf20Sopenharmony_ci
41598c2ecf20Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_EXT_FAT_CAPABILITIES,
41608c2ecf20Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
41618c2ecf20Sopenharmony_ci		return -EPERM;
41628c2ecf20Sopenharmony_ci
41638c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
41648c2ecf20Sopenharmony_ci		return -1;
41658c2ecf20Sopenharmony_ci
41668c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
41678c2ecf20Sopenharmony_ci	if (!wrb) {
41688c2ecf20Sopenharmony_ci		status = -EBUSY;
41698c2ecf20Sopenharmony_ci		goto err;
41708c2ecf20Sopenharmony_ci	}
41718c2ecf20Sopenharmony_ci
41728c2ecf20Sopenharmony_ci	req = cmd->va;
41738c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
41748c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_EXT_FAT_CAPABILITIES,
41758c2ecf20Sopenharmony_ci			       cmd->size, wrb, cmd);
41768c2ecf20Sopenharmony_ci	req->parameter_type = cpu_to_le32(1);
41778c2ecf20Sopenharmony_ci
41788c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
41798c2ecf20Sopenharmony_cierr:
41808c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
41818c2ecf20Sopenharmony_ci	return status;
41828c2ecf20Sopenharmony_ci}
41838c2ecf20Sopenharmony_ci
41848c2ecf20Sopenharmony_ciint be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
41858c2ecf20Sopenharmony_ci				   struct be_dma_mem *cmd,
41868c2ecf20Sopenharmony_ci				   struct be_fat_conf_params *configs)
41878c2ecf20Sopenharmony_ci{
41888c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
41898c2ecf20Sopenharmony_ci	struct be_cmd_req_set_ext_fat_caps *req;
41908c2ecf20Sopenharmony_ci	int status;
41918c2ecf20Sopenharmony_ci
41928c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
41938c2ecf20Sopenharmony_ci
41948c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
41958c2ecf20Sopenharmony_ci	if (!wrb) {
41968c2ecf20Sopenharmony_ci		status = -EBUSY;
41978c2ecf20Sopenharmony_ci		goto err;
41988c2ecf20Sopenharmony_ci	}
41998c2ecf20Sopenharmony_ci
42008c2ecf20Sopenharmony_ci	req = cmd->va;
42018c2ecf20Sopenharmony_ci	memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params));
42028c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
42038c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_EXT_FAT_CAPABILITIES,
42048c2ecf20Sopenharmony_ci			       cmd->size, wrb, cmd);
42058c2ecf20Sopenharmony_ci
42068c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
42078c2ecf20Sopenharmony_cierr:
42088c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
42098c2ecf20Sopenharmony_ci	return status;
42108c2ecf20Sopenharmony_ci}
42118c2ecf20Sopenharmony_ci
42128c2ecf20Sopenharmony_ciint be_cmd_query_port_name(struct be_adapter *adapter)
42138c2ecf20Sopenharmony_ci{
42148c2ecf20Sopenharmony_ci	struct be_cmd_req_get_port_name *req;
42158c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
42168c2ecf20Sopenharmony_ci	int status;
42178c2ecf20Sopenharmony_ci
42188c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
42198c2ecf20Sopenharmony_ci		return -1;
42208c2ecf20Sopenharmony_ci
42218c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
42228c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
42238c2ecf20Sopenharmony_ci
42248c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
42258c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb,
42268c2ecf20Sopenharmony_ci			       NULL);
42278c2ecf20Sopenharmony_ci	if (!BEx_chip(adapter))
42288c2ecf20Sopenharmony_ci		req->hdr.version = 1;
42298c2ecf20Sopenharmony_ci
42308c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
42318c2ecf20Sopenharmony_ci	if (!status) {
42328c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb);
42338c2ecf20Sopenharmony_ci
42348c2ecf20Sopenharmony_ci		adapter->port_name = resp->port_name[adapter->hba_port_num];
42358c2ecf20Sopenharmony_ci	} else {
42368c2ecf20Sopenharmony_ci		adapter->port_name = adapter->hba_port_num + '0';
42378c2ecf20Sopenharmony_ci	}
42388c2ecf20Sopenharmony_ci
42398c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
42408c2ecf20Sopenharmony_ci	return status;
42418c2ecf20Sopenharmony_ci}
42428c2ecf20Sopenharmony_ci
42438c2ecf20Sopenharmony_ci/* When more than 1 NIC descriptor is present in the descriptor list,
42448c2ecf20Sopenharmony_ci * the caller must specify the pf_num to obtain the NIC descriptor
42458c2ecf20Sopenharmony_ci * corresponding to its pci function.
42468c2ecf20Sopenharmony_ci * get_vft must be true when the caller wants the VF-template desc of the
42478c2ecf20Sopenharmony_ci * PF-pool.
42488c2ecf20Sopenharmony_ci * The pf_num should be set to PF_NUM_IGNORE when the caller knows
42498c2ecf20Sopenharmony_ci * that only it's NIC descriptor is present in the descriptor list.
42508c2ecf20Sopenharmony_ci */
42518c2ecf20Sopenharmony_cistatic struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
42528c2ecf20Sopenharmony_ci					       bool get_vft, u8 pf_num)
42538c2ecf20Sopenharmony_ci{
42548c2ecf20Sopenharmony_ci	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
42558c2ecf20Sopenharmony_ci	struct be_nic_res_desc *nic;
42568c2ecf20Sopenharmony_ci	int i;
42578c2ecf20Sopenharmony_ci
42588c2ecf20Sopenharmony_ci	for (i = 0; i < desc_count; i++) {
42598c2ecf20Sopenharmony_ci		if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
42608c2ecf20Sopenharmony_ci		    hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) {
42618c2ecf20Sopenharmony_ci			nic = (struct be_nic_res_desc *)hdr;
42628c2ecf20Sopenharmony_ci
42638c2ecf20Sopenharmony_ci			if ((pf_num == PF_NUM_IGNORE ||
42648c2ecf20Sopenharmony_ci			     nic->pf_num == pf_num) &&
42658c2ecf20Sopenharmony_ci			    (!get_vft || nic->flags & BIT(VFT_SHIFT)))
42668c2ecf20Sopenharmony_ci				return nic;
42678c2ecf20Sopenharmony_ci		}
42688c2ecf20Sopenharmony_ci		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
42698c2ecf20Sopenharmony_ci		hdr = (void *)hdr + hdr->desc_len;
42708c2ecf20Sopenharmony_ci	}
42718c2ecf20Sopenharmony_ci	return NULL;
42728c2ecf20Sopenharmony_ci}
42738c2ecf20Sopenharmony_ci
42748c2ecf20Sopenharmony_cistatic struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count,
42758c2ecf20Sopenharmony_ci					       u8 pf_num)
42768c2ecf20Sopenharmony_ci{
42778c2ecf20Sopenharmony_ci	return be_get_nic_desc(buf, desc_count, true, pf_num);
42788c2ecf20Sopenharmony_ci}
42798c2ecf20Sopenharmony_ci
42808c2ecf20Sopenharmony_cistatic struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count,
42818c2ecf20Sopenharmony_ci						    u8 pf_num)
42828c2ecf20Sopenharmony_ci{
42838c2ecf20Sopenharmony_ci	return be_get_nic_desc(buf, desc_count, false, pf_num);
42848c2ecf20Sopenharmony_ci}
42858c2ecf20Sopenharmony_ci
42868c2ecf20Sopenharmony_cistatic struct be_pcie_res_desc *be_get_pcie_desc(u8 *buf, u32 desc_count,
42878c2ecf20Sopenharmony_ci						 u8 pf_num)
42888c2ecf20Sopenharmony_ci{
42898c2ecf20Sopenharmony_ci	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
42908c2ecf20Sopenharmony_ci	struct be_pcie_res_desc *pcie;
42918c2ecf20Sopenharmony_ci	int i;
42928c2ecf20Sopenharmony_ci
42938c2ecf20Sopenharmony_ci	for (i = 0; i < desc_count; i++) {
42948c2ecf20Sopenharmony_ci		if (hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 ||
42958c2ecf20Sopenharmony_ci		    hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1) {
42968c2ecf20Sopenharmony_ci			pcie = (struct be_pcie_res_desc *)hdr;
42978c2ecf20Sopenharmony_ci			if (pcie->pf_num == pf_num)
42988c2ecf20Sopenharmony_ci				return pcie;
42998c2ecf20Sopenharmony_ci		}
43008c2ecf20Sopenharmony_ci
43018c2ecf20Sopenharmony_ci		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
43028c2ecf20Sopenharmony_ci		hdr = (void *)hdr + hdr->desc_len;
43038c2ecf20Sopenharmony_ci	}
43048c2ecf20Sopenharmony_ci	return NULL;
43058c2ecf20Sopenharmony_ci}
43068c2ecf20Sopenharmony_ci
43078c2ecf20Sopenharmony_cistatic struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
43088c2ecf20Sopenharmony_ci{
43098c2ecf20Sopenharmony_ci	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
43108c2ecf20Sopenharmony_ci	int i;
43118c2ecf20Sopenharmony_ci
43128c2ecf20Sopenharmony_ci	for (i = 0; i < desc_count; i++) {
43138c2ecf20Sopenharmony_ci		if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
43148c2ecf20Sopenharmony_ci			return (struct be_port_res_desc *)hdr;
43158c2ecf20Sopenharmony_ci
43168c2ecf20Sopenharmony_ci		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
43178c2ecf20Sopenharmony_ci		hdr = (void *)hdr + hdr->desc_len;
43188c2ecf20Sopenharmony_ci	}
43198c2ecf20Sopenharmony_ci	return NULL;
43208c2ecf20Sopenharmony_ci}
43218c2ecf20Sopenharmony_ci
43228c2ecf20Sopenharmony_cistatic void be_copy_nic_desc(struct be_resources *res,
43238c2ecf20Sopenharmony_ci			     struct be_nic_res_desc *desc)
43248c2ecf20Sopenharmony_ci{
43258c2ecf20Sopenharmony_ci	res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count);
43268c2ecf20Sopenharmony_ci	res->max_vlans = le16_to_cpu(desc->vlan_count);
43278c2ecf20Sopenharmony_ci	res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
43288c2ecf20Sopenharmony_ci	res->max_tx_qs = le16_to_cpu(desc->txq_count);
43298c2ecf20Sopenharmony_ci	res->max_rss_qs = le16_to_cpu(desc->rssq_count);
43308c2ecf20Sopenharmony_ci	res->max_rx_qs = le16_to_cpu(desc->rq_count);
43318c2ecf20Sopenharmony_ci	res->max_evt_qs = le16_to_cpu(desc->eq_count);
43328c2ecf20Sopenharmony_ci	res->max_cq_count = le16_to_cpu(desc->cq_count);
43338c2ecf20Sopenharmony_ci	res->max_iface_count = le16_to_cpu(desc->iface_count);
43348c2ecf20Sopenharmony_ci	res->max_mcc_count = le16_to_cpu(desc->mcc_count);
43358c2ecf20Sopenharmony_ci	/* Clear flags that driver is not interested in */
43368c2ecf20Sopenharmony_ci	res->if_cap_flags = le32_to_cpu(desc->cap_flags) &
43378c2ecf20Sopenharmony_ci				BE_IF_CAP_FLAGS_WANT;
43388c2ecf20Sopenharmony_ci}
43398c2ecf20Sopenharmony_ci
43408c2ecf20Sopenharmony_ci/* Uses Mbox */
43418c2ecf20Sopenharmony_ciint be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
43428c2ecf20Sopenharmony_ci{
43438c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
43448c2ecf20Sopenharmony_ci	struct be_cmd_req_get_func_config *req;
43458c2ecf20Sopenharmony_ci	int status;
43468c2ecf20Sopenharmony_ci	struct be_dma_mem cmd;
43478c2ecf20Sopenharmony_ci
43488c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
43498c2ecf20Sopenharmony_ci		return -1;
43508c2ecf20Sopenharmony_ci
43518c2ecf20Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
43528c2ecf20Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_resp_get_func_config);
43538c2ecf20Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
43548c2ecf20Sopenharmony_ci				    GFP_ATOMIC);
43558c2ecf20Sopenharmony_ci	if (!cmd.va) {
43568c2ecf20Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
43578c2ecf20Sopenharmony_ci		status = -ENOMEM;
43588c2ecf20Sopenharmony_ci		goto err;
43598c2ecf20Sopenharmony_ci	}
43608c2ecf20Sopenharmony_ci
43618c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
43628c2ecf20Sopenharmony_ci	if (!wrb) {
43638c2ecf20Sopenharmony_ci		status = -EBUSY;
43648c2ecf20Sopenharmony_ci		goto err;
43658c2ecf20Sopenharmony_ci	}
43668c2ecf20Sopenharmony_ci
43678c2ecf20Sopenharmony_ci	req = cmd.va;
43688c2ecf20Sopenharmony_ci
43698c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
43708c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_FUNC_CONFIG,
43718c2ecf20Sopenharmony_ci			       cmd.size, wrb, &cmd);
43728c2ecf20Sopenharmony_ci
43738c2ecf20Sopenharmony_ci	if (skyhawk_chip(adapter))
43748c2ecf20Sopenharmony_ci		req->hdr.version = 1;
43758c2ecf20Sopenharmony_ci
43768c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
43778c2ecf20Sopenharmony_ci	if (!status) {
43788c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_func_config *resp = cmd.va;
43798c2ecf20Sopenharmony_ci		u32 desc_count = le32_to_cpu(resp->desc_count);
43808c2ecf20Sopenharmony_ci		struct be_nic_res_desc *desc;
43818c2ecf20Sopenharmony_ci
43828c2ecf20Sopenharmony_ci		/* GET_FUNC_CONFIG returns resource descriptors of the
43838c2ecf20Sopenharmony_ci		 * current function only. So, pf_num should be set to
43848c2ecf20Sopenharmony_ci		 * PF_NUM_IGNORE.
43858c2ecf20Sopenharmony_ci		 */
43868c2ecf20Sopenharmony_ci		desc = be_get_func_nic_desc(resp->func_param, desc_count,
43878c2ecf20Sopenharmony_ci					    PF_NUM_IGNORE);
43888c2ecf20Sopenharmony_ci		if (!desc) {
43898c2ecf20Sopenharmony_ci			status = -EINVAL;
43908c2ecf20Sopenharmony_ci			goto err;
43918c2ecf20Sopenharmony_ci		}
43928c2ecf20Sopenharmony_ci
43938c2ecf20Sopenharmony_ci		/* Store pf_num & vf_num for later use in GET_PROFILE_CONFIG */
43948c2ecf20Sopenharmony_ci		adapter->pf_num = desc->pf_num;
43958c2ecf20Sopenharmony_ci		adapter->vf_num = desc->vf_num;
43968c2ecf20Sopenharmony_ci
43978c2ecf20Sopenharmony_ci		if (res)
43988c2ecf20Sopenharmony_ci			be_copy_nic_desc(res, desc);
43998c2ecf20Sopenharmony_ci	}
44008c2ecf20Sopenharmony_cierr:
44018c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
44028c2ecf20Sopenharmony_ci	if (cmd.va)
44038c2ecf20Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
44048c2ecf20Sopenharmony_ci				  cmd.dma);
44058c2ecf20Sopenharmony_ci	return status;
44068c2ecf20Sopenharmony_ci}
44078c2ecf20Sopenharmony_ci
44088c2ecf20Sopenharmony_ci/* This routine returns a list of all the NIC PF_nums in the adapter */
44098c2ecf20Sopenharmony_cistatic u16 be_get_nic_pf_num_list(u8 *buf, u32 desc_count, u16 *nic_pf_nums)
44108c2ecf20Sopenharmony_ci{
44118c2ecf20Sopenharmony_ci	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
44128c2ecf20Sopenharmony_ci	struct be_pcie_res_desc *pcie = NULL;
44138c2ecf20Sopenharmony_ci	int i;
44148c2ecf20Sopenharmony_ci	u16 nic_pf_count = 0;
44158c2ecf20Sopenharmony_ci
44168c2ecf20Sopenharmony_ci	for (i = 0; i < desc_count; i++) {
44178c2ecf20Sopenharmony_ci		if (hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 ||
44188c2ecf20Sopenharmony_ci		    hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1) {
44198c2ecf20Sopenharmony_ci			pcie = (struct be_pcie_res_desc *)hdr;
44208c2ecf20Sopenharmony_ci			if (pcie->pf_state && (pcie->pf_type == MISSION_NIC ||
44218c2ecf20Sopenharmony_ci					       pcie->pf_type == MISSION_RDMA)) {
44228c2ecf20Sopenharmony_ci				nic_pf_nums[nic_pf_count++] = pcie->pf_num;
44238c2ecf20Sopenharmony_ci			}
44248c2ecf20Sopenharmony_ci		}
44258c2ecf20Sopenharmony_ci
44268c2ecf20Sopenharmony_ci		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
44278c2ecf20Sopenharmony_ci		hdr = (void *)hdr + hdr->desc_len;
44288c2ecf20Sopenharmony_ci	}
44298c2ecf20Sopenharmony_ci	return nic_pf_count;
44308c2ecf20Sopenharmony_ci}
44318c2ecf20Sopenharmony_ci
44328c2ecf20Sopenharmony_ci/* Will use MBOX only if MCCQ has not been created */
44338c2ecf20Sopenharmony_ciint be_cmd_get_profile_config(struct be_adapter *adapter,
44348c2ecf20Sopenharmony_ci			      struct be_resources *res,
44358c2ecf20Sopenharmony_ci			      struct be_port_resources *port_res,
44368c2ecf20Sopenharmony_ci			      u8 profile_type, u8 query, u8 domain)
44378c2ecf20Sopenharmony_ci{
44388c2ecf20Sopenharmony_ci	struct be_cmd_resp_get_profile_config *resp;
44398c2ecf20Sopenharmony_ci	struct be_cmd_req_get_profile_config *req;
44408c2ecf20Sopenharmony_ci	struct be_nic_res_desc *vf_res;
44418c2ecf20Sopenharmony_ci	struct be_pcie_res_desc *pcie;
44428c2ecf20Sopenharmony_ci	struct be_port_res_desc *port;
44438c2ecf20Sopenharmony_ci	struct be_nic_res_desc *nic;
44448c2ecf20Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
44458c2ecf20Sopenharmony_ci	struct be_dma_mem cmd;
44468c2ecf20Sopenharmony_ci	u16 desc_count;
44478c2ecf20Sopenharmony_ci	int status;
44488c2ecf20Sopenharmony_ci
44498c2ecf20Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
44508c2ecf20Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
44518c2ecf20Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
44528c2ecf20Sopenharmony_ci				    GFP_ATOMIC);
44538c2ecf20Sopenharmony_ci	if (!cmd.va)
44548c2ecf20Sopenharmony_ci		return -ENOMEM;
44558c2ecf20Sopenharmony_ci
44568c2ecf20Sopenharmony_ci	req = cmd.va;
44578c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
44588c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_PROFILE_CONFIG,
44598c2ecf20Sopenharmony_ci			       cmd.size, &wrb, &cmd);
44608c2ecf20Sopenharmony_ci
44618c2ecf20Sopenharmony_ci	if (!lancer_chip(adapter))
44628c2ecf20Sopenharmony_ci		req->hdr.version = 1;
44638c2ecf20Sopenharmony_ci	req->type = profile_type;
44648c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
44658c2ecf20Sopenharmony_ci
44668c2ecf20Sopenharmony_ci	/* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the
44678c2ecf20Sopenharmony_ci	 * descriptors with all bits set to "1" for the fields which can be
44688c2ecf20Sopenharmony_ci	 * modified using SET_PROFILE_CONFIG cmd.
44698c2ecf20Sopenharmony_ci	 */
44708c2ecf20Sopenharmony_ci	if (query == RESOURCE_MODIFIABLE)
44718c2ecf20Sopenharmony_ci		req->type |= QUERY_MODIFIABLE_FIELDS_TYPE;
44728c2ecf20Sopenharmony_ci
44738c2ecf20Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
44748c2ecf20Sopenharmony_ci	if (status)
44758c2ecf20Sopenharmony_ci		goto err;
44768c2ecf20Sopenharmony_ci
44778c2ecf20Sopenharmony_ci	resp = cmd.va;
44788c2ecf20Sopenharmony_ci	desc_count = le16_to_cpu(resp->desc_count);
44798c2ecf20Sopenharmony_ci
44808c2ecf20Sopenharmony_ci	if (port_res) {
44818c2ecf20Sopenharmony_ci		u16 nic_pf_cnt = 0, i;
44828c2ecf20Sopenharmony_ci		u16 nic_pf_num_list[MAX_NIC_FUNCS];
44838c2ecf20Sopenharmony_ci
44848c2ecf20Sopenharmony_ci		nic_pf_cnt = be_get_nic_pf_num_list(resp->func_param,
44858c2ecf20Sopenharmony_ci						    desc_count,
44868c2ecf20Sopenharmony_ci						    nic_pf_num_list);
44878c2ecf20Sopenharmony_ci
44888c2ecf20Sopenharmony_ci		for (i = 0; i < nic_pf_cnt; i++) {
44898c2ecf20Sopenharmony_ci			nic = be_get_func_nic_desc(resp->func_param, desc_count,
44908c2ecf20Sopenharmony_ci						   nic_pf_num_list[i]);
44918c2ecf20Sopenharmony_ci			if (nic->link_param == adapter->port_num) {
44928c2ecf20Sopenharmony_ci				port_res->nic_pfs++;
44938c2ecf20Sopenharmony_ci				pcie = be_get_pcie_desc(resp->func_param,
44948c2ecf20Sopenharmony_ci							desc_count,
44958c2ecf20Sopenharmony_ci							nic_pf_num_list[i]);
44968c2ecf20Sopenharmony_ci				port_res->max_vfs += le16_to_cpu(pcie->num_vfs);
44978c2ecf20Sopenharmony_ci			}
44988c2ecf20Sopenharmony_ci		}
44998c2ecf20Sopenharmony_ci		goto err;
45008c2ecf20Sopenharmony_ci	}
45018c2ecf20Sopenharmony_ci
45028c2ecf20Sopenharmony_ci	pcie = be_get_pcie_desc(resp->func_param, desc_count,
45038c2ecf20Sopenharmony_ci				adapter->pf_num);
45048c2ecf20Sopenharmony_ci	if (pcie)
45058c2ecf20Sopenharmony_ci		res->max_vfs = le16_to_cpu(pcie->num_vfs);
45068c2ecf20Sopenharmony_ci
45078c2ecf20Sopenharmony_ci	port = be_get_port_desc(resp->func_param, desc_count);
45088c2ecf20Sopenharmony_ci	if (port)
45098c2ecf20Sopenharmony_ci		adapter->mc_type = port->mc_type;
45108c2ecf20Sopenharmony_ci
45118c2ecf20Sopenharmony_ci	nic = be_get_func_nic_desc(resp->func_param, desc_count,
45128c2ecf20Sopenharmony_ci				   adapter->pf_num);
45138c2ecf20Sopenharmony_ci	if (nic)
45148c2ecf20Sopenharmony_ci		be_copy_nic_desc(res, nic);
45158c2ecf20Sopenharmony_ci
45168c2ecf20Sopenharmony_ci	vf_res = be_get_vft_desc(resp->func_param, desc_count,
45178c2ecf20Sopenharmony_ci				 adapter->pf_num);
45188c2ecf20Sopenharmony_ci	if (vf_res)
45198c2ecf20Sopenharmony_ci		res->vf_if_cap_flags = vf_res->cap_flags;
45208c2ecf20Sopenharmony_cierr:
45218c2ecf20Sopenharmony_ci	if (cmd.va)
45228c2ecf20Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
45238c2ecf20Sopenharmony_ci				  cmd.dma);
45248c2ecf20Sopenharmony_ci	return status;
45258c2ecf20Sopenharmony_ci}
45268c2ecf20Sopenharmony_ci
45278c2ecf20Sopenharmony_ci/* Will use MBOX only if MCCQ has not been created */
45288c2ecf20Sopenharmony_cistatic int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
45298c2ecf20Sopenharmony_ci				     int size, int count, u8 version, u8 domain)
45308c2ecf20Sopenharmony_ci{
45318c2ecf20Sopenharmony_ci	struct be_cmd_req_set_profile_config *req;
45328c2ecf20Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
45338c2ecf20Sopenharmony_ci	struct be_dma_mem cmd;
45348c2ecf20Sopenharmony_ci	int status;
45358c2ecf20Sopenharmony_ci
45368c2ecf20Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
45378c2ecf20Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_req_set_profile_config);
45388c2ecf20Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
45398c2ecf20Sopenharmony_ci				    GFP_ATOMIC);
45408c2ecf20Sopenharmony_ci	if (!cmd.va)
45418c2ecf20Sopenharmony_ci		return -ENOMEM;
45428c2ecf20Sopenharmony_ci
45438c2ecf20Sopenharmony_ci	req = cmd.va;
45448c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
45458c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size,
45468c2ecf20Sopenharmony_ci			       &wrb, &cmd);
45478c2ecf20Sopenharmony_ci	req->hdr.version = version;
45488c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
45498c2ecf20Sopenharmony_ci	req->desc_count = cpu_to_le32(count);
45508c2ecf20Sopenharmony_ci	memcpy(req->desc, desc, size);
45518c2ecf20Sopenharmony_ci
45528c2ecf20Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
45538c2ecf20Sopenharmony_ci
45548c2ecf20Sopenharmony_ci	if (cmd.va)
45558c2ecf20Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
45568c2ecf20Sopenharmony_ci				  cmd.dma);
45578c2ecf20Sopenharmony_ci	return status;
45588c2ecf20Sopenharmony_ci}
45598c2ecf20Sopenharmony_ci
45608c2ecf20Sopenharmony_ci/* Mark all fields invalid */
45618c2ecf20Sopenharmony_cistatic void be_reset_nic_desc(struct be_nic_res_desc *nic)
45628c2ecf20Sopenharmony_ci{
45638c2ecf20Sopenharmony_ci	memset(nic, 0, sizeof(*nic));
45648c2ecf20Sopenharmony_ci	nic->unicast_mac_count = 0xFFFF;
45658c2ecf20Sopenharmony_ci	nic->mcc_count = 0xFFFF;
45668c2ecf20Sopenharmony_ci	nic->vlan_count = 0xFFFF;
45678c2ecf20Sopenharmony_ci	nic->mcast_mac_count = 0xFFFF;
45688c2ecf20Sopenharmony_ci	nic->txq_count = 0xFFFF;
45698c2ecf20Sopenharmony_ci	nic->rq_count = 0xFFFF;
45708c2ecf20Sopenharmony_ci	nic->rssq_count = 0xFFFF;
45718c2ecf20Sopenharmony_ci	nic->lro_count = 0xFFFF;
45728c2ecf20Sopenharmony_ci	nic->cq_count = 0xFFFF;
45738c2ecf20Sopenharmony_ci	nic->toe_conn_count = 0xFFFF;
45748c2ecf20Sopenharmony_ci	nic->eq_count = 0xFFFF;
45758c2ecf20Sopenharmony_ci	nic->iface_count = 0xFFFF;
45768c2ecf20Sopenharmony_ci	nic->link_param = 0xFF;
45778c2ecf20Sopenharmony_ci	nic->channel_id_param = cpu_to_le16(0xF000);
45788c2ecf20Sopenharmony_ci	nic->acpi_params = 0xFF;
45798c2ecf20Sopenharmony_ci	nic->wol_param = 0x0F;
45808c2ecf20Sopenharmony_ci	nic->tunnel_iface_count = 0xFFFF;
45818c2ecf20Sopenharmony_ci	nic->direct_tenant_iface_count = 0xFFFF;
45828c2ecf20Sopenharmony_ci	nic->bw_min = 0xFFFFFFFF;
45838c2ecf20Sopenharmony_ci	nic->bw_max = 0xFFFFFFFF;
45848c2ecf20Sopenharmony_ci}
45858c2ecf20Sopenharmony_ci
45868c2ecf20Sopenharmony_ci/* Mark all fields invalid */
45878c2ecf20Sopenharmony_cistatic void be_reset_pcie_desc(struct be_pcie_res_desc *pcie)
45888c2ecf20Sopenharmony_ci{
45898c2ecf20Sopenharmony_ci	memset(pcie, 0, sizeof(*pcie));
45908c2ecf20Sopenharmony_ci	pcie->sriov_state = 0xFF;
45918c2ecf20Sopenharmony_ci	pcie->pf_state = 0xFF;
45928c2ecf20Sopenharmony_ci	pcie->pf_type = 0xFF;
45938c2ecf20Sopenharmony_ci	pcie->num_vfs = 0xFFFF;
45948c2ecf20Sopenharmony_ci}
45958c2ecf20Sopenharmony_ci
45968c2ecf20Sopenharmony_ciint be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
45978c2ecf20Sopenharmony_ci		      u8 domain)
45988c2ecf20Sopenharmony_ci{
45998c2ecf20Sopenharmony_ci	struct be_nic_res_desc nic_desc;
46008c2ecf20Sopenharmony_ci	u32 bw_percent;
46018c2ecf20Sopenharmony_ci	u16 version = 0;
46028c2ecf20Sopenharmony_ci
46038c2ecf20Sopenharmony_ci	if (BE3_chip(adapter))
46048c2ecf20Sopenharmony_ci		return be_cmd_set_qos(adapter, max_rate / 10, domain);
46058c2ecf20Sopenharmony_ci
46068c2ecf20Sopenharmony_ci	be_reset_nic_desc(&nic_desc);
46078c2ecf20Sopenharmony_ci	nic_desc.pf_num = adapter->pf_num;
46088c2ecf20Sopenharmony_ci	nic_desc.vf_num = domain;
46098c2ecf20Sopenharmony_ci	nic_desc.bw_min = 0;
46108c2ecf20Sopenharmony_ci	if (lancer_chip(adapter)) {
46118c2ecf20Sopenharmony_ci		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
46128c2ecf20Sopenharmony_ci		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
46138c2ecf20Sopenharmony_ci		nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
46148c2ecf20Sopenharmony_ci					(1 << NOSV_SHIFT);
46158c2ecf20Sopenharmony_ci		nic_desc.bw_max = cpu_to_le32(max_rate / 10);
46168c2ecf20Sopenharmony_ci	} else {
46178c2ecf20Sopenharmony_ci		version = 1;
46188c2ecf20Sopenharmony_ci		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
46198c2ecf20Sopenharmony_ci		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
46208c2ecf20Sopenharmony_ci		nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
46218c2ecf20Sopenharmony_ci		bw_percent = max_rate ? (max_rate * 100) / link_speed : 100;
46228c2ecf20Sopenharmony_ci		nic_desc.bw_max = cpu_to_le32(bw_percent);
46238c2ecf20Sopenharmony_ci	}
46248c2ecf20Sopenharmony_ci
46258c2ecf20Sopenharmony_ci	return be_cmd_set_profile_config(adapter, &nic_desc,
46268c2ecf20Sopenharmony_ci					 nic_desc.hdr.desc_len,
46278c2ecf20Sopenharmony_ci					 1, version, domain);
46288c2ecf20Sopenharmony_ci}
46298c2ecf20Sopenharmony_ci
46308c2ecf20Sopenharmony_ciint be_cmd_set_sriov_config(struct be_adapter *adapter,
46318c2ecf20Sopenharmony_ci			    struct be_resources pool_res, u16 num_vfs,
46328c2ecf20Sopenharmony_ci			    struct be_resources *vft_res)
46338c2ecf20Sopenharmony_ci{
46348c2ecf20Sopenharmony_ci	struct {
46358c2ecf20Sopenharmony_ci		struct be_pcie_res_desc pcie;
46368c2ecf20Sopenharmony_ci		struct be_nic_res_desc nic_vft;
46378c2ecf20Sopenharmony_ci	} __packed desc;
46388c2ecf20Sopenharmony_ci
46398c2ecf20Sopenharmony_ci	/* PF PCIE descriptor */
46408c2ecf20Sopenharmony_ci	be_reset_pcie_desc(&desc.pcie);
46418c2ecf20Sopenharmony_ci	desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1;
46428c2ecf20Sopenharmony_ci	desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
46438c2ecf20Sopenharmony_ci	desc.pcie.flags = BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
46448c2ecf20Sopenharmony_ci	desc.pcie.pf_num = adapter->pdev->devfn;
46458c2ecf20Sopenharmony_ci	desc.pcie.sriov_state = num_vfs ? 1 : 0;
46468c2ecf20Sopenharmony_ci	desc.pcie.num_vfs = cpu_to_le16(num_vfs);
46478c2ecf20Sopenharmony_ci
46488c2ecf20Sopenharmony_ci	/* VF NIC Template descriptor */
46498c2ecf20Sopenharmony_ci	be_reset_nic_desc(&desc.nic_vft);
46508c2ecf20Sopenharmony_ci	desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
46518c2ecf20Sopenharmony_ci	desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
46528c2ecf20Sopenharmony_ci	desc.nic_vft.flags = vft_res->flags | BIT(VFT_SHIFT) |
46538c2ecf20Sopenharmony_ci			     BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
46548c2ecf20Sopenharmony_ci	desc.nic_vft.pf_num = adapter->pdev->devfn;
46558c2ecf20Sopenharmony_ci	desc.nic_vft.vf_num = 0;
46568c2ecf20Sopenharmony_ci	desc.nic_vft.cap_flags = cpu_to_le32(vft_res->vf_if_cap_flags);
46578c2ecf20Sopenharmony_ci	desc.nic_vft.rq_count = cpu_to_le16(vft_res->max_rx_qs);
46588c2ecf20Sopenharmony_ci	desc.nic_vft.txq_count = cpu_to_le16(vft_res->max_tx_qs);
46598c2ecf20Sopenharmony_ci	desc.nic_vft.rssq_count = cpu_to_le16(vft_res->max_rss_qs);
46608c2ecf20Sopenharmony_ci	desc.nic_vft.cq_count = cpu_to_le16(vft_res->max_cq_count);
46618c2ecf20Sopenharmony_ci
46628c2ecf20Sopenharmony_ci	if (vft_res->max_uc_mac)
46638c2ecf20Sopenharmony_ci		desc.nic_vft.unicast_mac_count =
46648c2ecf20Sopenharmony_ci					cpu_to_le16(vft_res->max_uc_mac);
46658c2ecf20Sopenharmony_ci	if (vft_res->max_vlans)
46668c2ecf20Sopenharmony_ci		desc.nic_vft.vlan_count = cpu_to_le16(vft_res->max_vlans);
46678c2ecf20Sopenharmony_ci	if (vft_res->max_iface_count)
46688c2ecf20Sopenharmony_ci		desc.nic_vft.iface_count =
46698c2ecf20Sopenharmony_ci				cpu_to_le16(vft_res->max_iface_count);
46708c2ecf20Sopenharmony_ci	if (vft_res->max_mcc_count)
46718c2ecf20Sopenharmony_ci		desc.nic_vft.mcc_count = cpu_to_le16(vft_res->max_mcc_count);
46728c2ecf20Sopenharmony_ci
46738c2ecf20Sopenharmony_ci	return be_cmd_set_profile_config(adapter, &desc,
46748c2ecf20Sopenharmony_ci					 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
46758c2ecf20Sopenharmony_ci}
46768c2ecf20Sopenharmony_ci
46778c2ecf20Sopenharmony_ciint be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
46788c2ecf20Sopenharmony_ci{
46798c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
46808c2ecf20Sopenharmony_ci	struct be_cmd_req_manage_iface_filters *req;
46818c2ecf20Sopenharmony_ci	int status;
46828c2ecf20Sopenharmony_ci
46838c2ecf20Sopenharmony_ci	if (iface == 0xFFFFFFFF)
46848c2ecf20Sopenharmony_ci		return -1;
46858c2ecf20Sopenharmony_ci
46868c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
46878c2ecf20Sopenharmony_ci
46888c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
46898c2ecf20Sopenharmony_ci	if (!wrb) {
46908c2ecf20Sopenharmony_ci		status = -EBUSY;
46918c2ecf20Sopenharmony_ci		goto err;
46928c2ecf20Sopenharmony_ci	}
46938c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
46948c2ecf20Sopenharmony_ci
46958c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
46968c2ecf20Sopenharmony_ci			       OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req),
46978c2ecf20Sopenharmony_ci			       wrb, NULL);
46988c2ecf20Sopenharmony_ci	req->op = op;
46998c2ecf20Sopenharmony_ci	req->target_iface_id = cpu_to_le32(iface);
47008c2ecf20Sopenharmony_ci
47018c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
47028c2ecf20Sopenharmony_cierr:
47038c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
47048c2ecf20Sopenharmony_ci	return status;
47058c2ecf20Sopenharmony_ci}
47068c2ecf20Sopenharmony_ci
47078c2ecf20Sopenharmony_ciint be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port)
47088c2ecf20Sopenharmony_ci{
47098c2ecf20Sopenharmony_ci	struct be_port_res_desc port_desc;
47108c2ecf20Sopenharmony_ci
47118c2ecf20Sopenharmony_ci	memset(&port_desc, 0, sizeof(port_desc));
47128c2ecf20Sopenharmony_ci	port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1;
47138c2ecf20Sopenharmony_ci	port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
47148c2ecf20Sopenharmony_ci	port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
47158c2ecf20Sopenharmony_ci	port_desc.link_num = adapter->hba_port_num;
47168c2ecf20Sopenharmony_ci	if (port) {
47178c2ecf20Sopenharmony_ci		port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) |
47188c2ecf20Sopenharmony_ci					(1 << RCVID_SHIFT);
47198c2ecf20Sopenharmony_ci		port_desc.nv_port = swab16(port);
47208c2ecf20Sopenharmony_ci	} else {
47218c2ecf20Sopenharmony_ci		port_desc.nv_flags = NV_TYPE_DISABLED;
47228c2ecf20Sopenharmony_ci		port_desc.nv_port = 0;
47238c2ecf20Sopenharmony_ci	}
47248c2ecf20Sopenharmony_ci
47258c2ecf20Sopenharmony_ci	return be_cmd_set_profile_config(adapter, &port_desc,
47268c2ecf20Sopenharmony_ci					 RESOURCE_DESC_SIZE_V1, 1, 1, 0);
47278c2ecf20Sopenharmony_ci}
47288c2ecf20Sopenharmony_ci
47298c2ecf20Sopenharmony_ciint be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
47308c2ecf20Sopenharmony_ci		     int vf_num)
47318c2ecf20Sopenharmony_ci{
47328c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
47338c2ecf20Sopenharmony_ci	struct be_cmd_req_get_iface_list *req;
47348c2ecf20Sopenharmony_ci	struct be_cmd_resp_get_iface_list *resp;
47358c2ecf20Sopenharmony_ci	int status;
47368c2ecf20Sopenharmony_ci
47378c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
47388c2ecf20Sopenharmony_ci
47398c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
47408c2ecf20Sopenharmony_ci	if (!wrb) {
47418c2ecf20Sopenharmony_ci		status = -EBUSY;
47428c2ecf20Sopenharmony_ci		goto err;
47438c2ecf20Sopenharmony_ci	}
47448c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
47458c2ecf20Sopenharmony_ci
47468c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
47478c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp),
47488c2ecf20Sopenharmony_ci			       wrb, NULL);
47498c2ecf20Sopenharmony_ci	req->hdr.domain = vf_num + 1;
47508c2ecf20Sopenharmony_ci
47518c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
47528c2ecf20Sopenharmony_ci	if (!status) {
47538c2ecf20Sopenharmony_ci		resp = (struct be_cmd_resp_get_iface_list *)req;
47548c2ecf20Sopenharmony_ci		vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id);
47558c2ecf20Sopenharmony_ci	}
47568c2ecf20Sopenharmony_ci
47578c2ecf20Sopenharmony_cierr:
47588c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
47598c2ecf20Sopenharmony_ci	return status;
47608c2ecf20Sopenharmony_ci}
47618c2ecf20Sopenharmony_ci
47628c2ecf20Sopenharmony_cistatic int lancer_wait_idle(struct be_adapter *adapter)
47638c2ecf20Sopenharmony_ci{
47648c2ecf20Sopenharmony_ci#define SLIPORT_IDLE_TIMEOUT 30
47658c2ecf20Sopenharmony_ci	u32 reg_val;
47668c2ecf20Sopenharmony_ci	int status = 0, i;
47678c2ecf20Sopenharmony_ci
47688c2ecf20Sopenharmony_ci	for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
47698c2ecf20Sopenharmony_ci		reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
47708c2ecf20Sopenharmony_ci		if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
47718c2ecf20Sopenharmony_ci			break;
47728c2ecf20Sopenharmony_ci
47738c2ecf20Sopenharmony_ci		ssleep(1);
47748c2ecf20Sopenharmony_ci	}
47758c2ecf20Sopenharmony_ci
47768c2ecf20Sopenharmony_ci	if (i == SLIPORT_IDLE_TIMEOUT)
47778c2ecf20Sopenharmony_ci		status = -1;
47788c2ecf20Sopenharmony_ci
47798c2ecf20Sopenharmony_ci	return status;
47808c2ecf20Sopenharmony_ci}
47818c2ecf20Sopenharmony_ci
47828c2ecf20Sopenharmony_ciint lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
47838c2ecf20Sopenharmony_ci{
47848c2ecf20Sopenharmony_ci	int status = 0;
47858c2ecf20Sopenharmony_ci
47868c2ecf20Sopenharmony_ci	status = lancer_wait_idle(adapter);
47878c2ecf20Sopenharmony_ci	if (status)
47888c2ecf20Sopenharmony_ci		return status;
47898c2ecf20Sopenharmony_ci
47908c2ecf20Sopenharmony_ci	iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
47918c2ecf20Sopenharmony_ci
47928c2ecf20Sopenharmony_ci	return status;
47938c2ecf20Sopenharmony_ci}
47948c2ecf20Sopenharmony_ci
47958c2ecf20Sopenharmony_ci/* Routine to check whether dump image is present or not */
47968c2ecf20Sopenharmony_cibool dump_present(struct be_adapter *adapter)
47978c2ecf20Sopenharmony_ci{
47988c2ecf20Sopenharmony_ci	u32 sliport_status = 0;
47998c2ecf20Sopenharmony_ci
48008c2ecf20Sopenharmony_ci	sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
48018c2ecf20Sopenharmony_ci	return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
48028c2ecf20Sopenharmony_ci}
48038c2ecf20Sopenharmony_ci
48048c2ecf20Sopenharmony_ciint lancer_initiate_dump(struct be_adapter *adapter)
48058c2ecf20Sopenharmony_ci{
48068c2ecf20Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
48078c2ecf20Sopenharmony_ci	int status;
48088c2ecf20Sopenharmony_ci
48098c2ecf20Sopenharmony_ci	if (dump_present(adapter)) {
48108c2ecf20Sopenharmony_ci		dev_info(dev, "Previous dump not cleared, not forcing dump\n");
48118c2ecf20Sopenharmony_ci		return -EEXIST;
48128c2ecf20Sopenharmony_ci	}
48138c2ecf20Sopenharmony_ci
48148c2ecf20Sopenharmony_ci	/* give firmware reset and diagnostic dump */
48158c2ecf20Sopenharmony_ci	status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
48168c2ecf20Sopenharmony_ci				     PHYSDEV_CONTROL_DD_MASK);
48178c2ecf20Sopenharmony_ci	if (status < 0) {
48188c2ecf20Sopenharmony_ci		dev_err(dev, "FW reset failed\n");
48198c2ecf20Sopenharmony_ci		return status;
48208c2ecf20Sopenharmony_ci	}
48218c2ecf20Sopenharmony_ci
48228c2ecf20Sopenharmony_ci	status = lancer_wait_idle(adapter);
48238c2ecf20Sopenharmony_ci	if (status)
48248c2ecf20Sopenharmony_ci		return status;
48258c2ecf20Sopenharmony_ci
48268c2ecf20Sopenharmony_ci	if (!dump_present(adapter)) {
48278c2ecf20Sopenharmony_ci		dev_err(dev, "FW dump not generated\n");
48288c2ecf20Sopenharmony_ci		return -EIO;
48298c2ecf20Sopenharmony_ci	}
48308c2ecf20Sopenharmony_ci
48318c2ecf20Sopenharmony_ci	return 0;
48328c2ecf20Sopenharmony_ci}
48338c2ecf20Sopenharmony_ci
48348c2ecf20Sopenharmony_ciint lancer_delete_dump(struct be_adapter *adapter)
48358c2ecf20Sopenharmony_ci{
48368c2ecf20Sopenharmony_ci	int status;
48378c2ecf20Sopenharmony_ci
48388c2ecf20Sopenharmony_ci	status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE);
48398c2ecf20Sopenharmony_ci	return be_cmd_status(status);
48408c2ecf20Sopenharmony_ci}
48418c2ecf20Sopenharmony_ci
48428c2ecf20Sopenharmony_ci/* Uses sync mcc */
48438c2ecf20Sopenharmony_ciint be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
48448c2ecf20Sopenharmony_ci{
48458c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
48468c2ecf20Sopenharmony_ci	struct be_cmd_enable_disable_vf *req;
48478c2ecf20Sopenharmony_ci	int status;
48488c2ecf20Sopenharmony_ci
48498c2ecf20Sopenharmony_ci	if (BEx_chip(adapter))
48508c2ecf20Sopenharmony_ci		return 0;
48518c2ecf20Sopenharmony_ci
48528c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
48538c2ecf20Sopenharmony_ci
48548c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
48558c2ecf20Sopenharmony_ci	if (!wrb) {
48568c2ecf20Sopenharmony_ci		status = -EBUSY;
48578c2ecf20Sopenharmony_ci		goto err;
48588c2ecf20Sopenharmony_ci	}
48598c2ecf20Sopenharmony_ci
48608c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
48618c2ecf20Sopenharmony_ci
48628c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
48638c2ecf20Sopenharmony_ci			       OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
48648c2ecf20Sopenharmony_ci			       wrb, NULL);
48658c2ecf20Sopenharmony_ci
48668c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
48678c2ecf20Sopenharmony_ci	req->enable = 1;
48688c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
48698c2ecf20Sopenharmony_cierr:
48708c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
48718c2ecf20Sopenharmony_ci	return status;
48728c2ecf20Sopenharmony_ci}
48738c2ecf20Sopenharmony_ci
48748c2ecf20Sopenharmony_ciint be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable)
48758c2ecf20Sopenharmony_ci{
48768c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
48778c2ecf20Sopenharmony_ci	struct be_cmd_req_intr_set *req;
48788c2ecf20Sopenharmony_ci	int status;
48798c2ecf20Sopenharmony_ci
48808c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
48818c2ecf20Sopenharmony_ci		return -1;
48828c2ecf20Sopenharmony_ci
48838c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
48848c2ecf20Sopenharmony_ci
48858c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
48868c2ecf20Sopenharmony_ci
48878c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
48888c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req),
48898c2ecf20Sopenharmony_ci			       wrb, NULL);
48908c2ecf20Sopenharmony_ci
48918c2ecf20Sopenharmony_ci	req->intr_enabled = intr_enable;
48928c2ecf20Sopenharmony_ci
48938c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
48948c2ecf20Sopenharmony_ci
48958c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
48968c2ecf20Sopenharmony_ci	return status;
48978c2ecf20Sopenharmony_ci}
48988c2ecf20Sopenharmony_ci
48998c2ecf20Sopenharmony_ci/* Uses MBOX */
49008c2ecf20Sopenharmony_ciint be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id)
49018c2ecf20Sopenharmony_ci{
49028c2ecf20Sopenharmony_ci	struct be_cmd_req_get_active_profile *req;
49038c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
49048c2ecf20Sopenharmony_ci	int status;
49058c2ecf20Sopenharmony_ci
49068c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
49078c2ecf20Sopenharmony_ci		return -1;
49088c2ecf20Sopenharmony_ci
49098c2ecf20Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
49108c2ecf20Sopenharmony_ci	if (!wrb) {
49118c2ecf20Sopenharmony_ci		status = -EBUSY;
49128c2ecf20Sopenharmony_ci		goto err;
49138c2ecf20Sopenharmony_ci	}
49148c2ecf20Sopenharmony_ci
49158c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
49168c2ecf20Sopenharmony_ci
49178c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
49188c2ecf20Sopenharmony_ci			       OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req),
49198c2ecf20Sopenharmony_ci			       wrb, NULL);
49208c2ecf20Sopenharmony_ci
49218c2ecf20Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
49228c2ecf20Sopenharmony_ci	if (!status) {
49238c2ecf20Sopenharmony_ci		struct be_cmd_resp_get_active_profile *resp =
49248c2ecf20Sopenharmony_ci							embedded_payload(wrb);
49258c2ecf20Sopenharmony_ci
49268c2ecf20Sopenharmony_ci		*profile_id = le16_to_cpu(resp->active_profile_id);
49278c2ecf20Sopenharmony_ci	}
49288c2ecf20Sopenharmony_ci
49298c2ecf20Sopenharmony_cierr:
49308c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
49318c2ecf20Sopenharmony_ci	return status;
49328c2ecf20Sopenharmony_ci}
49338c2ecf20Sopenharmony_ci
49348c2ecf20Sopenharmony_cistatic int
49358c2ecf20Sopenharmony_ci__be_cmd_set_logical_link_config(struct be_adapter *adapter,
49368c2ecf20Sopenharmony_ci				 int link_state, int version, u8 domain)
49378c2ecf20Sopenharmony_ci{
49388c2ecf20Sopenharmony_ci	struct be_cmd_req_set_ll_link *req;
49398c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
49408c2ecf20Sopenharmony_ci	u32 link_config = 0;
49418c2ecf20Sopenharmony_ci	int status;
49428c2ecf20Sopenharmony_ci
49438c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
49448c2ecf20Sopenharmony_ci
49458c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
49468c2ecf20Sopenharmony_ci	if (!wrb) {
49478c2ecf20Sopenharmony_ci		status = -EBUSY;
49488c2ecf20Sopenharmony_ci		goto err;
49498c2ecf20Sopenharmony_ci	}
49508c2ecf20Sopenharmony_ci
49518c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
49528c2ecf20Sopenharmony_ci
49538c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
49548c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG,
49558c2ecf20Sopenharmony_ci			       sizeof(*req), wrb, NULL);
49568c2ecf20Sopenharmony_ci
49578c2ecf20Sopenharmony_ci	req->hdr.version = version;
49588c2ecf20Sopenharmony_ci	req->hdr.domain = domain;
49598c2ecf20Sopenharmony_ci
49608c2ecf20Sopenharmony_ci	if (link_state == IFLA_VF_LINK_STATE_ENABLE ||
49618c2ecf20Sopenharmony_ci	    link_state == IFLA_VF_LINK_STATE_AUTO)
49628c2ecf20Sopenharmony_ci		link_config |= PLINK_ENABLE;
49638c2ecf20Sopenharmony_ci
49648c2ecf20Sopenharmony_ci	if (link_state == IFLA_VF_LINK_STATE_AUTO)
49658c2ecf20Sopenharmony_ci		link_config |= PLINK_TRACK;
49668c2ecf20Sopenharmony_ci
49678c2ecf20Sopenharmony_ci	req->link_config = cpu_to_le32(link_config);
49688c2ecf20Sopenharmony_ci
49698c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
49708c2ecf20Sopenharmony_cierr:
49718c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
49728c2ecf20Sopenharmony_ci	return status;
49738c2ecf20Sopenharmony_ci}
49748c2ecf20Sopenharmony_ci
49758c2ecf20Sopenharmony_ciint be_cmd_set_logical_link_config(struct be_adapter *adapter,
49768c2ecf20Sopenharmony_ci				   int link_state, u8 domain)
49778c2ecf20Sopenharmony_ci{
49788c2ecf20Sopenharmony_ci	int status;
49798c2ecf20Sopenharmony_ci
49808c2ecf20Sopenharmony_ci	if (BE2_chip(adapter))
49818c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
49828c2ecf20Sopenharmony_ci
49838c2ecf20Sopenharmony_ci	status = __be_cmd_set_logical_link_config(adapter, link_state,
49848c2ecf20Sopenharmony_ci						  2, domain);
49858c2ecf20Sopenharmony_ci
49868c2ecf20Sopenharmony_ci	/* Version 2 of the command will not be recognized by older FW.
49878c2ecf20Sopenharmony_ci	 * On such a failure issue version 1 of the command.
49888c2ecf20Sopenharmony_ci	 */
49898c2ecf20Sopenharmony_ci	if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST)
49908c2ecf20Sopenharmony_ci		status = __be_cmd_set_logical_link_config(adapter, link_state,
49918c2ecf20Sopenharmony_ci							  1, domain);
49928c2ecf20Sopenharmony_ci	return status;
49938c2ecf20Sopenharmony_ci}
49948c2ecf20Sopenharmony_ci
49958c2ecf20Sopenharmony_ciint be_cmd_set_features(struct be_adapter *adapter)
49968c2ecf20Sopenharmony_ci{
49978c2ecf20Sopenharmony_ci	struct be_cmd_resp_set_features *resp;
49988c2ecf20Sopenharmony_ci	struct be_cmd_req_set_features *req;
49998c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
50008c2ecf20Sopenharmony_ci	int status;
50018c2ecf20Sopenharmony_ci
50028c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mcc_lock))
50038c2ecf20Sopenharmony_ci		return -1;
50048c2ecf20Sopenharmony_ci
50058c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
50068c2ecf20Sopenharmony_ci	if (!wrb) {
50078c2ecf20Sopenharmony_ci		status = -EBUSY;
50088c2ecf20Sopenharmony_ci		goto err;
50098c2ecf20Sopenharmony_ci	}
50108c2ecf20Sopenharmony_ci
50118c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
50128c2ecf20Sopenharmony_ci
50138c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
50148c2ecf20Sopenharmony_ci			       OPCODE_COMMON_SET_FEATURES,
50158c2ecf20Sopenharmony_ci			       sizeof(*req), wrb, NULL);
50168c2ecf20Sopenharmony_ci
50178c2ecf20Sopenharmony_ci	req->features = cpu_to_le32(BE_FEATURE_UE_RECOVERY);
50188c2ecf20Sopenharmony_ci	req->parameter_len = cpu_to_le32(sizeof(struct be_req_ue_recovery));
50198c2ecf20Sopenharmony_ci	req->parameter.req.uer = cpu_to_le32(BE_UE_RECOVERY_UER_MASK);
50208c2ecf20Sopenharmony_ci
50218c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
50228c2ecf20Sopenharmony_ci	if (status)
50238c2ecf20Sopenharmony_ci		goto err;
50248c2ecf20Sopenharmony_ci
50258c2ecf20Sopenharmony_ci	resp = embedded_payload(wrb);
50268c2ecf20Sopenharmony_ci
50278c2ecf20Sopenharmony_ci	adapter->error_recovery.ue_to_poll_time =
50288c2ecf20Sopenharmony_ci		le16_to_cpu(resp->parameter.resp.ue2rp);
50298c2ecf20Sopenharmony_ci	adapter->error_recovery.ue_to_reset_time =
50308c2ecf20Sopenharmony_ci		le16_to_cpu(resp->parameter.resp.ue2sr);
50318c2ecf20Sopenharmony_ci	adapter->error_recovery.recovery_supported = true;
50328c2ecf20Sopenharmony_cierr:
50338c2ecf20Sopenharmony_ci	/* Checking "MCC_STATUS_INVALID_LENGTH" for SKH as FW
50348c2ecf20Sopenharmony_ci	 * returns this error in older firmware versions
50358c2ecf20Sopenharmony_ci	 */
50368c2ecf20Sopenharmony_ci	if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
50378c2ecf20Sopenharmony_ci	    base_status(status) == MCC_STATUS_INVALID_LENGTH)
50388c2ecf20Sopenharmony_ci		dev_info(&adapter->pdev->dev,
50398c2ecf20Sopenharmony_ci			 "Adapter does not support HW error recovery\n");
50408c2ecf20Sopenharmony_ci
50418c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
50428c2ecf20Sopenharmony_ci	return status;
50438c2ecf20Sopenharmony_ci}
50448c2ecf20Sopenharmony_ci
50458c2ecf20Sopenharmony_ciint be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
50468c2ecf20Sopenharmony_ci		    int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
50478c2ecf20Sopenharmony_ci{
50488c2ecf20Sopenharmony_ci	struct be_adapter *adapter = netdev_priv(netdev_handle);
50498c2ecf20Sopenharmony_ci	struct be_mcc_wrb *wrb;
50508c2ecf20Sopenharmony_ci	struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload;
50518c2ecf20Sopenharmony_ci	struct be_cmd_req_hdr *req;
50528c2ecf20Sopenharmony_ci	struct be_cmd_resp_hdr *resp;
50538c2ecf20Sopenharmony_ci	int status;
50548c2ecf20Sopenharmony_ci
50558c2ecf20Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
50568c2ecf20Sopenharmony_ci
50578c2ecf20Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
50588c2ecf20Sopenharmony_ci	if (!wrb) {
50598c2ecf20Sopenharmony_ci		status = -EBUSY;
50608c2ecf20Sopenharmony_ci		goto err;
50618c2ecf20Sopenharmony_ci	}
50628c2ecf20Sopenharmony_ci	req = embedded_payload(wrb);
50638c2ecf20Sopenharmony_ci	resp = embedded_payload(wrb);
50648c2ecf20Sopenharmony_ci
50658c2ecf20Sopenharmony_ci	be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
50668c2ecf20Sopenharmony_ci			       hdr->opcode, wrb_payload_size, wrb, NULL);
50678c2ecf20Sopenharmony_ci	memcpy(req, wrb_payload, wrb_payload_size);
50688c2ecf20Sopenharmony_ci	be_dws_cpu_to_le(req, wrb_payload_size);
50698c2ecf20Sopenharmony_ci
50708c2ecf20Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
50718c2ecf20Sopenharmony_ci	if (cmd_status)
50728c2ecf20Sopenharmony_ci		*cmd_status = (status & 0xffff);
50738c2ecf20Sopenharmony_ci	if (ext_status)
50748c2ecf20Sopenharmony_ci		*ext_status = 0;
50758c2ecf20Sopenharmony_ci	memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
50768c2ecf20Sopenharmony_ci	be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
50778c2ecf20Sopenharmony_cierr:
50788c2ecf20Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
50798c2ecf20Sopenharmony_ci	return status;
50808c2ecf20Sopenharmony_ci}
50818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(be_roce_mcc_cmd);
5082