162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2005 - 2016 Broadcom
462306a36Sopenharmony_ci * All rights reserved.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Contact Information:
762306a36Sopenharmony_ci * linux-drivers@emulex.com
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Emulex
1062306a36Sopenharmony_ci * 3333 Susan Street
1162306a36Sopenharmony_ci * Costa Mesa, CA 92626
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include "be.h"
1662306a36Sopenharmony_ci#include "be_cmds.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciconst char * const be_misconfig_evt_port_state[] = {
1962306a36Sopenharmony_ci	"Physical Link is functional",
2062306a36Sopenharmony_ci	"Optics faulted/incorrectly installed/not installed - Reseat optics. If issue not resolved, replace.",
2162306a36Sopenharmony_ci	"Optics of two types installed – Remove one optic or install matching pair of optics.",
2262306a36Sopenharmony_ci	"Incompatible optics – Replace with compatible optics for card to function.",
2362306a36Sopenharmony_ci	"Unqualified optics – Replace with Avago optics for Warranty and Technical Support.",
2462306a36Sopenharmony_ci	"Uncertified optics – Replace with Avago-certified optics to enable link operation."
2562306a36Sopenharmony_ci};
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic char *be_port_misconfig_evt_severity[] = {
2862306a36Sopenharmony_ci	"KERN_WARN",
2962306a36Sopenharmony_ci	"KERN_INFO",
3062306a36Sopenharmony_ci	"KERN_ERR",
3162306a36Sopenharmony_ci	"KERN_WARN"
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic char *phy_state_oper_desc[] = {
3562306a36Sopenharmony_ci	"Link is non-operational",
3662306a36Sopenharmony_ci	"Link is operational",
3762306a36Sopenharmony_ci	""
3862306a36Sopenharmony_ci};
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic struct be_cmd_priv_map cmd_priv_map[] = {
4162306a36Sopenharmony_ci	{
4262306a36Sopenharmony_ci		OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
4362306a36Sopenharmony_ci		CMD_SUBSYSTEM_ETH,
4462306a36Sopenharmony_ci		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
4562306a36Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
4662306a36Sopenharmony_ci	},
4762306a36Sopenharmony_ci	{
4862306a36Sopenharmony_ci		OPCODE_COMMON_GET_FLOW_CONTROL,
4962306a36Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
5062306a36Sopenharmony_ci		BE_PRIV_LNKQUERY | BE_PRIV_VHADM |
5162306a36Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
5262306a36Sopenharmony_ci	},
5362306a36Sopenharmony_ci	{
5462306a36Sopenharmony_ci		OPCODE_COMMON_SET_FLOW_CONTROL,
5562306a36Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
5662306a36Sopenharmony_ci		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
5762306a36Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
5862306a36Sopenharmony_ci	},
5962306a36Sopenharmony_ci	{
6062306a36Sopenharmony_ci		OPCODE_ETH_GET_PPORT_STATS,
6162306a36Sopenharmony_ci		CMD_SUBSYSTEM_ETH,
6262306a36Sopenharmony_ci		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
6362306a36Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
6462306a36Sopenharmony_ci	},
6562306a36Sopenharmony_ci	{
6662306a36Sopenharmony_ci		OPCODE_COMMON_GET_PHY_DETAILS,
6762306a36Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
6862306a36Sopenharmony_ci		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
6962306a36Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
7062306a36Sopenharmony_ci	},
7162306a36Sopenharmony_ci	{
7262306a36Sopenharmony_ci		OPCODE_LOWLEVEL_HOST_DDR_DMA,
7362306a36Sopenharmony_ci		CMD_SUBSYSTEM_LOWLEVEL,
7462306a36Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
7562306a36Sopenharmony_ci	},
7662306a36Sopenharmony_ci	{
7762306a36Sopenharmony_ci		OPCODE_LOWLEVEL_LOOPBACK_TEST,
7862306a36Sopenharmony_ci		CMD_SUBSYSTEM_LOWLEVEL,
7962306a36Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
8062306a36Sopenharmony_ci	},
8162306a36Sopenharmony_ci	{
8262306a36Sopenharmony_ci		OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
8362306a36Sopenharmony_ci		CMD_SUBSYSTEM_LOWLEVEL,
8462306a36Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
8562306a36Sopenharmony_ci	},
8662306a36Sopenharmony_ci	{
8762306a36Sopenharmony_ci		OPCODE_COMMON_SET_HSW_CONFIG,
8862306a36Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
8962306a36Sopenharmony_ci		BE_PRIV_DEVCFG | BE_PRIV_VHADM |
9062306a36Sopenharmony_ci		BE_PRIV_DEVSEC
9162306a36Sopenharmony_ci	},
9262306a36Sopenharmony_ci	{
9362306a36Sopenharmony_ci		OPCODE_COMMON_GET_EXT_FAT_CAPABILITIES,
9462306a36Sopenharmony_ci		CMD_SUBSYSTEM_COMMON,
9562306a36Sopenharmony_ci		BE_PRIV_DEVCFG
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, u8 subsystem)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	int i;
10262306a36Sopenharmony_ci	int num_entries = ARRAY_SIZE(cmd_priv_map);
10362306a36Sopenharmony_ci	u32 cmd_privileges = adapter->cmd_privileges;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	for (i = 0; i < num_entries; i++)
10662306a36Sopenharmony_ci		if (opcode == cmd_priv_map[i].opcode &&
10762306a36Sopenharmony_ci		    subsystem == cmd_priv_map[i].subsystem)
10862306a36Sopenharmony_ci			if (!(cmd_privileges & cmd_priv_map[i].priv_mask))
10962306a36Sopenharmony_ci				return false;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	return true;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistatic inline void *embedded_payload(struct be_mcc_wrb *wrb)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	return wrb->payload.embedded_payload;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic int be_mcc_notify(struct be_adapter *adapter)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	struct be_queue_info *mccq = &adapter->mcc_obj.q;
12262306a36Sopenharmony_ci	u32 val = 0;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (be_check_error(adapter, BE_ERROR_ANY))
12562306a36Sopenharmony_ci		return -EIO;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	val |= mccq->id & DB_MCCQ_RING_ID_MASK;
12862306a36Sopenharmony_ci	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	wmb();
13162306a36Sopenharmony_ci	iowrite32(val, adapter->db + DB_MCCQ_OFFSET);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	return 0;
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci/* To check if valid bit is set, check the entire word as we don't know
13762306a36Sopenharmony_ci * the endianness of the data (old entry is host endian while a new entry is
13862306a36Sopenharmony_ci * little endian)
13962306a36Sopenharmony_ci */
14062306a36Sopenharmony_cistatic inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	u32 flags;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	if (compl->flags != 0) {
14562306a36Sopenharmony_ci		flags = le32_to_cpu(compl->flags);
14662306a36Sopenharmony_ci		if (flags & CQE_FLAGS_VALID_MASK) {
14762306a36Sopenharmony_ci			compl->flags = flags;
14862306a36Sopenharmony_ci			return true;
14962306a36Sopenharmony_ci		}
15062306a36Sopenharmony_ci	}
15162306a36Sopenharmony_ci	return false;
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci/* Need to reset the entire word that houses the valid bit */
15562306a36Sopenharmony_cistatic inline void be_mcc_compl_use(struct be_mcc_compl *compl)
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci	compl->flags = 0;
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	unsigned long addr;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	addr = tag1;
16562306a36Sopenharmony_ci	addr = ((addr << 16) << 16) | tag0;
16662306a36Sopenharmony_ci	return (void *)addr;
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	if (base_status == MCC_STATUS_NOT_SUPPORTED ||
17262306a36Sopenharmony_ci	    base_status == MCC_STATUS_ILLEGAL_REQUEST ||
17362306a36Sopenharmony_ci	    addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES ||
17462306a36Sopenharmony_ci	    addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS ||
17562306a36Sopenharmony_ci	    (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
17662306a36Sopenharmony_ci	    (base_status == MCC_STATUS_ILLEGAL_FIELD ||
17762306a36Sopenharmony_ci	     addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH)))
17862306a36Sopenharmony_ci		return true;
17962306a36Sopenharmony_ci	else
18062306a36Sopenharmony_ci		return false;
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci/* Place holder for all the async MCC cmds wherein the caller is not in a busy
18462306a36Sopenharmony_ci * loop (has not issued be_mcc_notify_wait())
18562306a36Sopenharmony_ci */
18662306a36Sopenharmony_cistatic void be_async_cmd_process(struct be_adapter *adapter,
18762306a36Sopenharmony_ci				 struct be_mcc_compl *compl,
18862306a36Sopenharmony_ci				 struct be_cmd_resp_hdr *resp_hdr)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	enum mcc_base_status base_status = base_status(compl->status);
19162306a36Sopenharmony_ci	u8 opcode = 0, subsystem = 0;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	if (resp_hdr) {
19462306a36Sopenharmony_ci		opcode = resp_hdr->opcode;
19562306a36Sopenharmony_ci		subsystem = resp_hdr->subsystem;
19662306a36Sopenharmony_ci	}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
19962306a36Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
20062306a36Sopenharmony_ci		complete(&adapter->et_cmd_compl);
20162306a36Sopenharmony_ci		return;
20262306a36Sopenharmony_ci	}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	if (opcode == OPCODE_LOWLEVEL_SET_LOOPBACK_MODE &&
20562306a36Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
20662306a36Sopenharmony_ci		complete(&adapter->et_cmd_compl);
20762306a36Sopenharmony_ci		return;
20862306a36Sopenharmony_ci	}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	if ((opcode == OPCODE_COMMON_WRITE_FLASHROM ||
21162306a36Sopenharmony_ci	     opcode == OPCODE_COMMON_WRITE_OBJECT) &&
21262306a36Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_COMMON) {
21362306a36Sopenharmony_ci		adapter->flash_status = compl->status;
21462306a36Sopenharmony_ci		complete(&adapter->et_cmd_compl);
21562306a36Sopenharmony_ci		return;
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	if ((opcode == OPCODE_ETH_GET_STATISTICS ||
21962306a36Sopenharmony_ci	     opcode == OPCODE_ETH_GET_PPORT_STATS) &&
22062306a36Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_ETH &&
22162306a36Sopenharmony_ci	    base_status == MCC_STATUS_SUCCESS) {
22262306a36Sopenharmony_ci		be_parse_stats(adapter);
22362306a36Sopenharmony_ci		adapter->stats_cmd_sent = false;
22462306a36Sopenharmony_ci		return;
22562306a36Sopenharmony_ci	}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
22862306a36Sopenharmony_ci	    subsystem == CMD_SUBSYSTEM_COMMON) {
22962306a36Sopenharmony_ci		if (base_status == MCC_STATUS_SUCCESS) {
23062306a36Sopenharmony_ci			struct be_cmd_resp_get_cntl_addnl_attribs *resp =
23162306a36Sopenharmony_ci							(void *)resp_hdr;
23262306a36Sopenharmony_ci			adapter->hwmon_info.be_on_die_temp =
23362306a36Sopenharmony_ci						resp->on_die_temperature;
23462306a36Sopenharmony_ci		} else {
23562306a36Sopenharmony_ci			adapter->be_get_temp_freq = 0;
23662306a36Sopenharmony_ci			adapter->hwmon_info.be_on_die_temp =
23762306a36Sopenharmony_ci						BE_INVALID_DIE_TEMP;
23862306a36Sopenharmony_ci		}
23962306a36Sopenharmony_ci		return;
24062306a36Sopenharmony_ci	}
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistatic int be_mcc_compl_process(struct be_adapter *adapter,
24462306a36Sopenharmony_ci				struct be_mcc_compl *compl)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	enum mcc_base_status base_status;
24762306a36Sopenharmony_ci	enum mcc_addl_status addl_status;
24862306a36Sopenharmony_ci	struct be_cmd_resp_hdr *resp_hdr;
24962306a36Sopenharmony_ci	u8 opcode = 0, subsystem = 0;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	/* Just swap the status to host endian; mcc tag is opaquely copied
25262306a36Sopenharmony_ci	 * from mcc_wrb
25362306a36Sopenharmony_ci	 */
25462306a36Sopenharmony_ci	be_dws_le_to_cpu(compl, 4);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	base_status = base_status(compl->status);
25762306a36Sopenharmony_ci	addl_status = addl_status(compl->status);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
26062306a36Sopenharmony_ci	if (resp_hdr) {
26162306a36Sopenharmony_ci		opcode = resp_hdr->opcode;
26262306a36Sopenharmony_ci		subsystem = resp_hdr->subsystem;
26362306a36Sopenharmony_ci	}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	be_async_cmd_process(adapter, compl, resp_hdr);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	if (base_status != MCC_STATUS_SUCCESS &&
26862306a36Sopenharmony_ci	    !be_skip_err_log(opcode, base_status, addl_status)) {
26962306a36Sopenharmony_ci		if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST ||
27062306a36Sopenharmony_ci		    addl_status == MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES) {
27162306a36Sopenharmony_ci			dev_warn(&adapter->pdev->dev,
27262306a36Sopenharmony_ci				 "VF is not privileged to issue opcode %d-%d\n",
27362306a36Sopenharmony_ci				 opcode, subsystem);
27462306a36Sopenharmony_ci		} else {
27562306a36Sopenharmony_ci			dev_err(&adapter->pdev->dev,
27662306a36Sopenharmony_ci				"opcode %d-%d failed:status %d-%d\n",
27762306a36Sopenharmony_ci				opcode, subsystem, base_status, addl_status);
27862306a36Sopenharmony_ci		}
27962306a36Sopenharmony_ci	}
28062306a36Sopenharmony_ci	return compl->status;
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci/* Link state evt is a string of bytes; no need for endian swapping */
28462306a36Sopenharmony_cistatic void be_async_link_state_process(struct be_adapter *adapter,
28562306a36Sopenharmony_ci					struct be_mcc_compl *compl)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	struct be_async_event_link_state *evt =
28862306a36Sopenharmony_ci			(struct be_async_event_link_state *)compl;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	/* When link status changes, link speed must be re-queried from FW */
29162306a36Sopenharmony_ci	adapter->phy.link_speed = -1;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	/* On BEx the FW does not send a separate link status
29462306a36Sopenharmony_ci	 * notification for physical and logical link.
29562306a36Sopenharmony_ci	 * On other chips just process the logical link
29662306a36Sopenharmony_ci	 * status notification
29762306a36Sopenharmony_ci	 */
29862306a36Sopenharmony_ci	if (!BEx_chip(adapter) &&
29962306a36Sopenharmony_ci	    !(evt->port_link_status & LOGICAL_LINK_STATUS_MASK))
30062306a36Sopenharmony_ci		return;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	/* For the initial link status do not rely on the ASYNC event as
30362306a36Sopenharmony_ci	 * it may not be received in some cases.
30462306a36Sopenharmony_ci	 */
30562306a36Sopenharmony_ci	if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
30662306a36Sopenharmony_ci		be_link_status_update(adapter,
30762306a36Sopenharmony_ci				      evt->port_link_status & LINK_STATUS_MASK);
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cistatic void be_async_port_misconfig_event_process(struct be_adapter *adapter,
31162306a36Sopenharmony_ci						  struct be_mcc_compl *compl)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	struct be_async_event_misconfig_port *evt =
31462306a36Sopenharmony_ci			(struct be_async_event_misconfig_port *)compl;
31562306a36Sopenharmony_ci	u32 sfp_misconfig_evt_word1 = le32_to_cpu(evt->event_data_word1);
31662306a36Sopenharmony_ci	u32 sfp_misconfig_evt_word2 = le32_to_cpu(evt->event_data_word2);
31762306a36Sopenharmony_ci	u8 phy_oper_state = PHY_STATE_OPER_MSG_NONE;
31862306a36Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
31962306a36Sopenharmony_ci	u8 msg_severity = DEFAULT_MSG_SEVERITY;
32062306a36Sopenharmony_ci	u8 phy_state_info;
32162306a36Sopenharmony_ci	u8 new_phy_state;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	new_phy_state =
32462306a36Sopenharmony_ci		(sfp_misconfig_evt_word1 >> (adapter->hba_port_num * 8)) & 0xff;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	if (new_phy_state == adapter->phy_state)
32762306a36Sopenharmony_ci		return;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	adapter->phy_state = new_phy_state;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	/* for older fw that doesn't populate link effect data */
33262306a36Sopenharmony_ci	if (!sfp_misconfig_evt_word2)
33362306a36Sopenharmony_ci		goto log_message;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	phy_state_info =
33662306a36Sopenharmony_ci		(sfp_misconfig_evt_word2 >> (adapter->hba_port_num * 8)) & 0xff;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	if (phy_state_info & PHY_STATE_INFO_VALID) {
33962306a36Sopenharmony_ci		msg_severity = (phy_state_info & PHY_STATE_MSG_SEVERITY) >> 1;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci		if (be_phy_unqualified(new_phy_state))
34262306a36Sopenharmony_ci			phy_oper_state = (phy_state_info & PHY_STATE_OPER);
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cilog_message:
34662306a36Sopenharmony_ci	/* Log an error message that would allow a user to determine
34762306a36Sopenharmony_ci	 * whether the SFPs have an issue
34862306a36Sopenharmony_ci	 */
34962306a36Sopenharmony_ci	if (be_phy_state_unknown(new_phy_state))
35062306a36Sopenharmony_ci		dev_printk(be_port_misconfig_evt_severity[msg_severity], dev,
35162306a36Sopenharmony_ci			   "Port %c: Unrecognized Optics state: 0x%x. %s",
35262306a36Sopenharmony_ci			   adapter->port_name,
35362306a36Sopenharmony_ci			   new_phy_state,
35462306a36Sopenharmony_ci			   phy_state_oper_desc[phy_oper_state]);
35562306a36Sopenharmony_ci	else
35662306a36Sopenharmony_ci		dev_printk(be_port_misconfig_evt_severity[msg_severity], dev,
35762306a36Sopenharmony_ci			   "Port %c: %s %s",
35862306a36Sopenharmony_ci			   adapter->port_name,
35962306a36Sopenharmony_ci			   be_misconfig_evt_port_state[new_phy_state],
36062306a36Sopenharmony_ci			   phy_state_oper_desc[phy_oper_state]);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	/* Log Vendor name and part no. if a misconfigured SFP is detected */
36362306a36Sopenharmony_ci	if (be_phy_misconfigured(new_phy_state))
36462306a36Sopenharmony_ci		adapter->flags |= BE_FLAGS_PHY_MISCONFIGURED;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci/* Grp5 CoS Priority evt */
36862306a36Sopenharmony_cistatic void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
36962306a36Sopenharmony_ci					       struct be_mcc_compl *compl)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	struct be_async_event_grp5_cos_priority *evt =
37262306a36Sopenharmony_ci			(struct be_async_event_grp5_cos_priority *)compl;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	if (evt->valid) {
37562306a36Sopenharmony_ci		adapter->vlan_prio_bmap = evt->available_priority_bmap;
37662306a36Sopenharmony_ci		adapter->recommended_prio_bits =
37762306a36Sopenharmony_ci			evt->reco_default_priority << VLAN_PRIO_SHIFT;
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci/* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */
38262306a36Sopenharmony_cistatic void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
38362306a36Sopenharmony_ci					    struct be_mcc_compl *compl)
38462306a36Sopenharmony_ci{
38562306a36Sopenharmony_ci	struct be_async_event_grp5_qos_link_speed *evt =
38662306a36Sopenharmony_ci			(struct be_async_event_grp5_qos_link_speed *)compl;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	if (adapter->phy.link_speed >= 0 &&
38962306a36Sopenharmony_ci	    evt->physical_port == adapter->port_num)
39062306a36Sopenharmony_ci		adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10;
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci/*Grp5 PVID evt*/
39462306a36Sopenharmony_cistatic void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
39562306a36Sopenharmony_ci					     struct be_mcc_compl *compl)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	struct be_async_event_grp5_pvid_state *evt =
39862306a36Sopenharmony_ci			(struct be_async_event_grp5_pvid_state *)compl;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	if (evt->enabled) {
40162306a36Sopenharmony_ci		adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
40262306a36Sopenharmony_ci		dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid);
40362306a36Sopenharmony_ci	} else {
40462306a36Sopenharmony_ci		adapter->pvid = 0;
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci#define MGMT_ENABLE_MASK	0x4
40962306a36Sopenharmony_cistatic void be_async_grp5_fw_control_process(struct be_adapter *adapter,
41062306a36Sopenharmony_ci					     struct be_mcc_compl *compl)
41162306a36Sopenharmony_ci{
41262306a36Sopenharmony_ci	struct be_async_fw_control *evt = (struct be_async_fw_control *)compl;
41362306a36Sopenharmony_ci	u32 evt_dw1 = le32_to_cpu(evt->event_data_word1);
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	if (evt_dw1 & MGMT_ENABLE_MASK) {
41662306a36Sopenharmony_ci		adapter->flags |= BE_FLAGS_OS2BMC;
41762306a36Sopenharmony_ci		adapter->bmc_filt_mask = le32_to_cpu(evt->event_data_word2);
41862306a36Sopenharmony_ci	} else {
41962306a36Sopenharmony_ci		adapter->flags &= ~BE_FLAGS_OS2BMC;
42062306a36Sopenharmony_ci	}
42162306a36Sopenharmony_ci}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cistatic void be_async_grp5_evt_process(struct be_adapter *adapter,
42462306a36Sopenharmony_ci				      struct be_mcc_compl *compl)
42562306a36Sopenharmony_ci{
42662306a36Sopenharmony_ci	u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) &
42762306a36Sopenharmony_ci				ASYNC_EVENT_TYPE_MASK;
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	switch (event_type) {
43062306a36Sopenharmony_ci	case ASYNC_EVENT_COS_PRIORITY:
43162306a36Sopenharmony_ci		be_async_grp5_cos_priority_process(adapter, compl);
43262306a36Sopenharmony_ci		break;
43362306a36Sopenharmony_ci	case ASYNC_EVENT_QOS_SPEED:
43462306a36Sopenharmony_ci		be_async_grp5_qos_speed_process(adapter, compl);
43562306a36Sopenharmony_ci		break;
43662306a36Sopenharmony_ci	case ASYNC_EVENT_PVID_STATE:
43762306a36Sopenharmony_ci		be_async_grp5_pvid_state_process(adapter, compl);
43862306a36Sopenharmony_ci		break;
43962306a36Sopenharmony_ci	/* Async event to disable/enable os2bmc and/or mac-learning */
44062306a36Sopenharmony_ci	case ASYNC_EVENT_FW_CONTROL:
44162306a36Sopenharmony_ci		be_async_grp5_fw_control_process(adapter, compl);
44262306a36Sopenharmony_ci		break;
44362306a36Sopenharmony_ci	default:
44462306a36Sopenharmony_ci		break;
44562306a36Sopenharmony_ci	}
44662306a36Sopenharmony_ci}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_cistatic void be_async_dbg_evt_process(struct be_adapter *adapter,
44962306a36Sopenharmony_ci				     struct be_mcc_compl *cmp)
45062306a36Sopenharmony_ci{
45162306a36Sopenharmony_ci	u8 event_type = 0;
45262306a36Sopenharmony_ci	struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
45562306a36Sopenharmony_ci			ASYNC_EVENT_TYPE_MASK;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	switch (event_type) {
45862306a36Sopenharmony_ci	case ASYNC_DEBUG_EVENT_TYPE_QNQ:
45962306a36Sopenharmony_ci		if (evt->valid)
46062306a36Sopenharmony_ci			adapter->qnq_vid = le16_to_cpu(evt->vlan_tag);
46162306a36Sopenharmony_ci		adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
46262306a36Sopenharmony_ci	break;
46362306a36Sopenharmony_ci	default:
46462306a36Sopenharmony_ci		dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n",
46562306a36Sopenharmony_ci			 event_type);
46662306a36Sopenharmony_ci	break;
46762306a36Sopenharmony_ci	}
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_cistatic void be_async_sliport_evt_process(struct be_adapter *adapter,
47162306a36Sopenharmony_ci					 struct be_mcc_compl *cmp)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
47462306a36Sopenharmony_ci			ASYNC_EVENT_TYPE_MASK;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	if (event_type == ASYNC_EVENT_PORT_MISCONFIG)
47762306a36Sopenharmony_ci		be_async_port_misconfig_event_process(adapter, cmp);
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_cistatic inline bool is_link_state_evt(u32 flags)
48162306a36Sopenharmony_ci{
48262306a36Sopenharmony_ci	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
48362306a36Sopenharmony_ci			ASYNC_EVENT_CODE_LINK_STATE;
48462306a36Sopenharmony_ci}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_cistatic inline bool is_grp5_evt(u32 flags)
48762306a36Sopenharmony_ci{
48862306a36Sopenharmony_ci	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
48962306a36Sopenharmony_ci			ASYNC_EVENT_CODE_GRP_5;
49062306a36Sopenharmony_ci}
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_cistatic inline bool is_dbg_evt(u32 flags)
49362306a36Sopenharmony_ci{
49462306a36Sopenharmony_ci	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
49562306a36Sopenharmony_ci			ASYNC_EVENT_CODE_QNQ;
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_cistatic inline bool is_sliport_evt(u32 flags)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
50162306a36Sopenharmony_ci		ASYNC_EVENT_CODE_SLIPORT;
50262306a36Sopenharmony_ci}
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_cistatic void be_mcc_event_process(struct be_adapter *adapter,
50562306a36Sopenharmony_ci				 struct be_mcc_compl *compl)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	if (is_link_state_evt(compl->flags))
50862306a36Sopenharmony_ci		be_async_link_state_process(adapter, compl);
50962306a36Sopenharmony_ci	else if (is_grp5_evt(compl->flags))
51062306a36Sopenharmony_ci		be_async_grp5_evt_process(adapter, compl);
51162306a36Sopenharmony_ci	else if (is_dbg_evt(compl->flags))
51262306a36Sopenharmony_ci		be_async_dbg_evt_process(adapter, compl);
51362306a36Sopenharmony_ci	else if (is_sliport_evt(compl->flags))
51462306a36Sopenharmony_ci		be_async_sliport_evt_process(adapter, compl);
51562306a36Sopenharmony_ci}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_cistatic struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
51862306a36Sopenharmony_ci{
51962306a36Sopenharmony_ci	struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
52062306a36Sopenharmony_ci	struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	if (be_mcc_compl_is_new(compl)) {
52362306a36Sopenharmony_ci		queue_tail_inc(mcc_cq);
52462306a36Sopenharmony_ci		return compl;
52562306a36Sopenharmony_ci	}
52662306a36Sopenharmony_ci	return NULL;
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_civoid be_async_mcc_enable(struct be_adapter *adapter)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	spin_lock_bh(&adapter->mcc_cq_lock);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0);
53462306a36Sopenharmony_ci	adapter->mcc_obj.rearm_cq = true;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	spin_unlock_bh(&adapter->mcc_cq_lock);
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_civoid be_async_mcc_disable(struct be_adapter *adapter)
54062306a36Sopenharmony_ci{
54162306a36Sopenharmony_ci	spin_lock_bh(&adapter->mcc_cq_lock);
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	adapter->mcc_obj.rearm_cq = false;
54462306a36Sopenharmony_ci	be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	spin_unlock_bh(&adapter->mcc_cq_lock);
54762306a36Sopenharmony_ci}
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ciint be_process_mcc(struct be_adapter *adapter)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	struct be_mcc_compl *compl;
55262306a36Sopenharmony_ci	int num = 0, status = 0;
55362306a36Sopenharmony_ci	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	spin_lock(&adapter->mcc_cq_lock);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	while ((compl = be_mcc_compl_get(adapter))) {
55862306a36Sopenharmony_ci		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
55962306a36Sopenharmony_ci			be_mcc_event_process(adapter, compl);
56062306a36Sopenharmony_ci		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
56162306a36Sopenharmony_ci			status = be_mcc_compl_process(adapter, compl);
56262306a36Sopenharmony_ci			atomic_dec(&mcc_obj->q.used);
56362306a36Sopenharmony_ci		}
56462306a36Sopenharmony_ci		be_mcc_compl_use(compl);
56562306a36Sopenharmony_ci		num++;
56662306a36Sopenharmony_ci	}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	if (num)
56962306a36Sopenharmony_ci		be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	spin_unlock(&adapter->mcc_cq_lock);
57262306a36Sopenharmony_ci	return status;
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci/* Wait till no more pending mcc requests are present */
57662306a36Sopenharmony_cistatic int be_mcc_wait_compl(struct be_adapter *adapter)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci#define mcc_timeout		12000 /* 12s timeout */
57962306a36Sopenharmony_ci	int i, status = 0;
58062306a36Sopenharmony_ci	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	for (i = 0; i < mcc_timeout; i++) {
58362306a36Sopenharmony_ci		if (be_check_error(adapter, BE_ERROR_ANY))
58462306a36Sopenharmony_ci			return -EIO;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci		local_bh_disable();
58762306a36Sopenharmony_ci		status = be_process_mcc(adapter);
58862306a36Sopenharmony_ci		local_bh_enable();
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci		if (atomic_read(&mcc_obj->q.used) == 0)
59162306a36Sopenharmony_ci			break;
59262306a36Sopenharmony_ci		usleep_range(500, 1000);
59362306a36Sopenharmony_ci	}
59462306a36Sopenharmony_ci	if (i == mcc_timeout) {
59562306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "FW not responding\n");
59662306a36Sopenharmony_ci		be_set_error(adapter, BE_ERROR_FW);
59762306a36Sopenharmony_ci		return -EIO;
59862306a36Sopenharmony_ci	}
59962306a36Sopenharmony_ci	return status;
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci/* Notify MCC requests and wait for completion */
60362306a36Sopenharmony_cistatic int be_mcc_notify_wait(struct be_adapter *adapter)
60462306a36Sopenharmony_ci{
60562306a36Sopenharmony_ci	int status;
60662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
60762306a36Sopenharmony_ci	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
60862306a36Sopenharmony_ci	u32 index = mcc_obj->q.head;
60962306a36Sopenharmony_ci	struct be_cmd_resp_hdr *resp;
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	index_dec(&index, mcc_obj->q.len);
61262306a36Sopenharmony_ci	wrb = queue_index_node(&mcc_obj->q, index);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	status = be_mcc_notify(adapter);
61762306a36Sopenharmony_ci	if (status)
61862306a36Sopenharmony_ci		goto out;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	status = be_mcc_wait_compl(adapter);
62162306a36Sopenharmony_ci	if (status == -EIO)
62262306a36Sopenharmony_ci		goto out;
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	status = (resp->base_status |
62562306a36Sopenharmony_ci		  ((resp->addl_status & CQE_ADDL_STATUS_MASK) <<
62662306a36Sopenharmony_ci		   CQE_ADDL_STATUS_SHIFT));
62762306a36Sopenharmony_ciout:
62862306a36Sopenharmony_ci	return status;
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_cistatic int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
63262306a36Sopenharmony_ci{
63362306a36Sopenharmony_ci	int msecs = 0;
63462306a36Sopenharmony_ci	u32 ready;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	do {
63762306a36Sopenharmony_ci		if (be_check_error(adapter, BE_ERROR_ANY))
63862306a36Sopenharmony_ci			return -EIO;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		ready = ioread32(db);
64162306a36Sopenharmony_ci		if (ready == 0xffffffff)
64262306a36Sopenharmony_ci			return -1;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci		ready &= MPU_MAILBOX_DB_RDY_MASK;
64562306a36Sopenharmony_ci		if (ready)
64662306a36Sopenharmony_ci			break;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci		if (msecs > 4000) {
64962306a36Sopenharmony_ci			dev_err(&adapter->pdev->dev, "FW not responding\n");
65062306a36Sopenharmony_ci			be_set_error(adapter, BE_ERROR_FW);
65162306a36Sopenharmony_ci			be_detect_error(adapter);
65262306a36Sopenharmony_ci			return -1;
65362306a36Sopenharmony_ci		}
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci		msleep(1);
65662306a36Sopenharmony_ci		msecs++;
65762306a36Sopenharmony_ci	} while (true);
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	return 0;
66062306a36Sopenharmony_ci}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci/* Insert the mailbox address into the doorbell in two steps
66362306a36Sopenharmony_ci * Polls on the mbox doorbell till a command completion (or a timeout) occurs
66462306a36Sopenharmony_ci */
66562306a36Sopenharmony_cistatic int be_mbox_notify_wait(struct be_adapter *adapter)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	int status;
66862306a36Sopenharmony_ci	u32 val = 0;
66962306a36Sopenharmony_ci	void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET;
67062306a36Sopenharmony_ci	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
67162306a36Sopenharmony_ci	struct be_mcc_mailbox *mbox = mbox_mem->va;
67262306a36Sopenharmony_ci	struct be_mcc_compl *compl = &mbox->compl;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	/* wait for ready to be set */
67562306a36Sopenharmony_ci	status = be_mbox_db_ready_wait(adapter, db);
67662306a36Sopenharmony_ci	if (status != 0)
67762306a36Sopenharmony_ci		return status;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	val |= MPU_MAILBOX_DB_HI_MASK;
68062306a36Sopenharmony_ci	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
68162306a36Sopenharmony_ci	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
68262306a36Sopenharmony_ci	iowrite32(val, db);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	/* wait for ready to be set */
68562306a36Sopenharmony_ci	status = be_mbox_db_ready_wait(adapter, db);
68662306a36Sopenharmony_ci	if (status != 0)
68762306a36Sopenharmony_ci		return status;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	val = 0;
69062306a36Sopenharmony_ci	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
69162306a36Sopenharmony_ci	val |= (u32)(mbox_mem->dma >> 4) << 2;
69262306a36Sopenharmony_ci	iowrite32(val, db);
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	status = be_mbox_db_ready_wait(adapter, db);
69562306a36Sopenharmony_ci	if (status != 0)
69662306a36Sopenharmony_ci		return status;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	/* A cq entry has been made now */
69962306a36Sopenharmony_ci	if (be_mcc_compl_is_new(compl)) {
70062306a36Sopenharmony_ci		status = be_mcc_compl_process(adapter, &mbox->compl);
70162306a36Sopenharmony_ci		be_mcc_compl_use(compl);
70262306a36Sopenharmony_ci		if (status)
70362306a36Sopenharmony_ci			return status;
70462306a36Sopenharmony_ci	} else {
70562306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "invalid mailbox completion\n");
70662306a36Sopenharmony_ci		return -1;
70762306a36Sopenharmony_ci	}
70862306a36Sopenharmony_ci	return 0;
70962306a36Sopenharmony_ci}
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ciu16 be_POST_stage_get(struct be_adapter *adapter)
71262306a36Sopenharmony_ci{
71362306a36Sopenharmony_ci	u32 sem;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	if (BEx_chip(adapter))
71662306a36Sopenharmony_ci		sem  = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx);
71762306a36Sopenharmony_ci	else
71862306a36Sopenharmony_ci		pci_read_config_dword(adapter->pdev,
71962306a36Sopenharmony_ci				      SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	return sem & POST_STAGE_MASK;
72262306a36Sopenharmony_ci}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_cistatic int lancer_wait_ready(struct be_adapter *adapter)
72562306a36Sopenharmony_ci{
72662306a36Sopenharmony_ci#define SLIPORT_READY_TIMEOUT 30
72762306a36Sopenharmony_ci	u32 sliport_status;
72862306a36Sopenharmony_ci	int i;
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
73162306a36Sopenharmony_ci		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
73262306a36Sopenharmony_ci		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
73362306a36Sopenharmony_ci			return 0;
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci		if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
73662306a36Sopenharmony_ci		    !(sliport_status & SLIPORT_STATUS_RN_MASK))
73762306a36Sopenharmony_ci			return -EIO;
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci		msleep(1000);
74062306a36Sopenharmony_ci	}
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	return sliport_status ? : -1;
74362306a36Sopenharmony_ci}
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ciint be_fw_wait_ready(struct be_adapter *adapter)
74662306a36Sopenharmony_ci{
74762306a36Sopenharmony_ci	u16 stage;
74862306a36Sopenharmony_ci	int status, timeout = 0;
74962306a36Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	if (lancer_chip(adapter)) {
75262306a36Sopenharmony_ci		status = lancer_wait_ready(adapter);
75362306a36Sopenharmony_ci		if (status) {
75462306a36Sopenharmony_ci			stage = status;
75562306a36Sopenharmony_ci			goto err;
75662306a36Sopenharmony_ci		}
75762306a36Sopenharmony_ci		return 0;
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	do {
76162306a36Sopenharmony_ci		/* There's no means to poll POST state on BE2/3 VFs */
76262306a36Sopenharmony_ci		if (BEx_chip(adapter) && be_virtfn(adapter))
76362306a36Sopenharmony_ci			return 0;
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci		stage = be_POST_stage_get(adapter);
76662306a36Sopenharmony_ci		if (stage == POST_STAGE_ARMFW_RDY)
76762306a36Sopenharmony_ci			return 0;
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci		dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout);
77062306a36Sopenharmony_ci		if (msleep_interruptible(2000)) {
77162306a36Sopenharmony_ci			dev_err(dev, "Waiting for POST aborted\n");
77262306a36Sopenharmony_ci			return -EINTR;
77362306a36Sopenharmony_ci		}
77462306a36Sopenharmony_ci		timeout += 2;
77562306a36Sopenharmony_ci	} while (timeout < 60);
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_cierr:
77862306a36Sopenharmony_ci	dev_err(dev, "POST timeout; stage=%#x\n", stage);
77962306a36Sopenharmony_ci	return -ETIMEDOUT;
78062306a36Sopenharmony_ci}
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_cistatic inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
78362306a36Sopenharmony_ci{
78462306a36Sopenharmony_ci	return &wrb->payload.sgl[0];
78562306a36Sopenharmony_ci}
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_cistatic inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr)
78862306a36Sopenharmony_ci{
78962306a36Sopenharmony_ci	wrb->tag0 = addr & 0xFFFFFFFF;
79062306a36Sopenharmony_ci	wrb->tag1 = upper_32_bits(addr);
79162306a36Sopenharmony_ci}
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci/* Don't touch the hdr after it's prepared */
79462306a36Sopenharmony_ci/* mem will be NULL for embedded commands */
79562306a36Sopenharmony_cistatic void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
79662306a36Sopenharmony_ci				   u8 subsystem, u8 opcode, int cmd_len,
79762306a36Sopenharmony_ci				   struct be_mcc_wrb *wrb,
79862306a36Sopenharmony_ci				   struct be_dma_mem *mem)
79962306a36Sopenharmony_ci{
80062306a36Sopenharmony_ci	struct be_sge *sge;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	req_hdr->opcode = opcode;
80362306a36Sopenharmony_ci	req_hdr->subsystem = subsystem;
80462306a36Sopenharmony_ci	req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
80562306a36Sopenharmony_ci	req_hdr->version = 0;
80662306a36Sopenharmony_ci	fill_wrb_tags(wrb, (ulong)req_hdr);
80762306a36Sopenharmony_ci	wrb->payload_length = cmd_len;
80862306a36Sopenharmony_ci	if (mem) {
80962306a36Sopenharmony_ci		wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
81062306a36Sopenharmony_ci			MCC_WRB_SGE_CNT_SHIFT;
81162306a36Sopenharmony_ci		sge = nonembedded_sgl(wrb);
81262306a36Sopenharmony_ci		sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
81362306a36Sopenharmony_ci		sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
81462306a36Sopenharmony_ci		sge->len = cpu_to_le32(mem->size);
81562306a36Sopenharmony_ci	} else
81662306a36Sopenharmony_ci		wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
81762306a36Sopenharmony_ci	be_dws_cpu_to_le(wrb, 8);
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_cistatic void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
82162306a36Sopenharmony_ci				      struct be_dma_mem *mem)
82262306a36Sopenharmony_ci{
82362306a36Sopenharmony_ci	int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
82462306a36Sopenharmony_ci	u64 dma = (u64)mem->dma;
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	for (i = 0; i < buf_pages; i++) {
82762306a36Sopenharmony_ci		pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
82862306a36Sopenharmony_ci		pages[i].hi = cpu_to_le32(upper_32_bits(dma));
82962306a36Sopenharmony_ci		dma += PAGE_SIZE_4K;
83062306a36Sopenharmony_ci	}
83162306a36Sopenharmony_ci}
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_cistatic inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter)
83462306a36Sopenharmony_ci{
83562306a36Sopenharmony_ci	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
83662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb = &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	memset(wrb, 0, sizeof(*wrb));
83962306a36Sopenharmony_ci	return wrb;
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistatic struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
84362306a36Sopenharmony_ci{
84462306a36Sopenharmony_ci	struct be_queue_info *mccq = &adapter->mcc_obj.q;
84562306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	if (!mccq->created)
84862306a36Sopenharmony_ci		return NULL;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	if (atomic_read(&mccq->used) >= mccq->len)
85162306a36Sopenharmony_ci		return NULL;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	wrb = queue_head_node(mccq);
85462306a36Sopenharmony_ci	queue_head_inc(mccq);
85562306a36Sopenharmony_ci	atomic_inc(&mccq->used);
85662306a36Sopenharmony_ci	memset(wrb, 0, sizeof(*wrb));
85762306a36Sopenharmony_ci	return wrb;
85862306a36Sopenharmony_ci}
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_cistatic bool use_mcc(struct be_adapter *adapter)
86162306a36Sopenharmony_ci{
86262306a36Sopenharmony_ci	return adapter->mcc_obj.q.created;
86362306a36Sopenharmony_ci}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci/* Must be used only in process context */
86662306a36Sopenharmony_cistatic int be_cmd_lock(struct be_adapter *adapter)
86762306a36Sopenharmony_ci{
86862306a36Sopenharmony_ci	if (use_mcc(adapter)) {
86962306a36Sopenharmony_ci		mutex_lock(&adapter->mcc_lock);
87062306a36Sopenharmony_ci		return 0;
87162306a36Sopenharmony_ci	} else {
87262306a36Sopenharmony_ci		return mutex_lock_interruptible(&adapter->mbox_lock);
87362306a36Sopenharmony_ci	}
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci/* Must be used only in process context */
87762306a36Sopenharmony_cistatic void be_cmd_unlock(struct be_adapter *adapter)
87862306a36Sopenharmony_ci{
87962306a36Sopenharmony_ci	if (use_mcc(adapter))
88062306a36Sopenharmony_ci		return mutex_unlock(&adapter->mcc_lock);
88162306a36Sopenharmony_ci	else
88262306a36Sopenharmony_ci		return mutex_unlock(&adapter->mbox_lock);
88362306a36Sopenharmony_ci}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_cistatic struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter,
88662306a36Sopenharmony_ci				      struct be_mcc_wrb *wrb)
88762306a36Sopenharmony_ci{
88862306a36Sopenharmony_ci	struct be_mcc_wrb *dest_wrb;
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	if (use_mcc(adapter)) {
89162306a36Sopenharmony_ci		dest_wrb = wrb_from_mccq(adapter);
89262306a36Sopenharmony_ci		if (!dest_wrb)
89362306a36Sopenharmony_ci			return NULL;
89462306a36Sopenharmony_ci	} else {
89562306a36Sopenharmony_ci		dest_wrb = wrb_from_mbox(adapter);
89662306a36Sopenharmony_ci	}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	memcpy(dest_wrb, wrb, sizeof(*wrb));
89962306a36Sopenharmony_ci	if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK))
90062306a36Sopenharmony_ci		fill_wrb_tags(dest_wrb, (ulong)embedded_payload(wrb));
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	return dest_wrb;
90362306a36Sopenharmony_ci}
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci/* Must be used only in process context */
90662306a36Sopenharmony_cistatic int be_cmd_notify_wait(struct be_adapter *adapter,
90762306a36Sopenharmony_ci			      struct be_mcc_wrb *wrb)
90862306a36Sopenharmony_ci{
90962306a36Sopenharmony_ci	struct be_mcc_wrb *dest_wrb;
91062306a36Sopenharmony_ci	int status;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	status = be_cmd_lock(adapter);
91362306a36Sopenharmony_ci	if (status)
91462306a36Sopenharmony_ci		return status;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	dest_wrb = be_cmd_copy(adapter, wrb);
91762306a36Sopenharmony_ci	if (!dest_wrb) {
91862306a36Sopenharmony_ci		status = -EBUSY;
91962306a36Sopenharmony_ci		goto unlock;
92062306a36Sopenharmony_ci	}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	if (use_mcc(adapter))
92362306a36Sopenharmony_ci		status = be_mcc_notify_wait(adapter);
92462306a36Sopenharmony_ci	else
92562306a36Sopenharmony_ci		status = be_mbox_notify_wait(adapter);
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	if (!status)
92862306a36Sopenharmony_ci		memcpy(wrb, dest_wrb, sizeof(*wrb));
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ciunlock:
93162306a36Sopenharmony_ci	be_cmd_unlock(adapter);
93262306a36Sopenharmony_ci	return status;
93362306a36Sopenharmony_ci}
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci/* Tell fw we're about to start firing cmds by writing a
93662306a36Sopenharmony_ci * special pattern across the wrb hdr; uses mbox
93762306a36Sopenharmony_ci */
93862306a36Sopenharmony_ciint be_cmd_fw_init(struct be_adapter *adapter)
93962306a36Sopenharmony_ci{
94062306a36Sopenharmony_ci	u8 *wrb;
94162306a36Sopenharmony_ci	int status;
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	if (lancer_chip(adapter))
94462306a36Sopenharmony_ci		return 0;
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
94762306a36Sopenharmony_ci		return -1;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	wrb = (u8 *)wrb_from_mbox(adapter);
95062306a36Sopenharmony_ci	*wrb++ = 0xFF;
95162306a36Sopenharmony_ci	*wrb++ = 0x12;
95262306a36Sopenharmony_ci	*wrb++ = 0x34;
95362306a36Sopenharmony_ci	*wrb++ = 0xFF;
95462306a36Sopenharmony_ci	*wrb++ = 0xFF;
95562306a36Sopenharmony_ci	*wrb++ = 0x56;
95662306a36Sopenharmony_ci	*wrb++ = 0x78;
95762306a36Sopenharmony_ci	*wrb = 0xFF;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
96262306a36Sopenharmony_ci	return status;
96362306a36Sopenharmony_ci}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci/* Tell fw we're done with firing cmds by writing a
96662306a36Sopenharmony_ci * special pattern across the wrb hdr; uses mbox
96762306a36Sopenharmony_ci */
96862306a36Sopenharmony_ciint be_cmd_fw_clean(struct be_adapter *adapter)
96962306a36Sopenharmony_ci{
97062306a36Sopenharmony_ci	u8 *wrb;
97162306a36Sopenharmony_ci	int status;
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	if (lancer_chip(adapter))
97462306a36Sopenharmony_ci		return 0;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
97762306a36Sopenharmony_ci		return -1;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	wrb = (u8 *)wrb_from_mbox(adapter);
98062306a36Sopenharmony_ci	*wrb++ = 0xFF;
98162306a36Sopenharmony_ci	*wrb++ = 0xAA;
98262306a36Sopenharmony_ci	*wrb++ = 0xBB;
98362306a36Sopenharmony_ci	*wrb++ = 0xFF;
98462306a36Sopenharmony_ci	*wrb++ = 0xFF;
98562306a36Sopenharmony_ci	*wrb++ = 0xCC;
98662306a36Sopenharmony_ci	*wrb++ = 0xDD;
98762306a36Sopenharmony_ci	*wrb = 0xFF;
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
99262306a36Sopenharmony_ci	return status;
99362306a36Sopenharmony_ci}
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ciint be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo)
99662306a36Sopenharmony_ci{
99762306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
99862306a36Sopenharmony_ci	struct be_cmd_req_eq_create *req;
99962306a36Sopenharmony_ci	struct be_dma_mem *q_mem = &eqo->q.dma_mem;
100062306a36Sopenharmony_ci	int status, ver = 0;
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
100362306a36Sopenharmony_ci		return -1;
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
100662306a36Sopenharmony_ci	req = embedded_payload(wrb);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
100962306a36Sopenharmony_ci			       OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb,
101062306a36Sopenharmony_ci			       NULL);
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	/* Support for EQ_CREATEv2 available only SH-R onwards */
101362306a36Sopenharmony_ci	if (!(BEx_chip(adapter) || lancer_chip(adapter)))
101462306a36Sopenharmony_ci		ver = 2;
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	req->hdr.version = ver;
101762306a36Sopenharmony_ci	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
102062306a36Sopenharmony_ci	/* 4byte eqe*/
102162306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
102262306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_eq_context, count, req->context,
102362306a36Sopenharmony_ci		      __ilog2_u32(eqo->q.len / 256));
102462306a36Sopenharmony_ci	be_dws_cpu_to_le(req->context, sizeof(req->context));
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
102962306a36Sopenharmony_ci	if (!status) {
103062306a36Sopenharmony_ci		struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci		eqo->q.id = le16_to_cpu(resp->eq_id);
103362306a36Sopenharmony_ci		eqo->msix_idx =
103462306a36Sopenharmony_ci			(ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx;
103562306a36Sopenharmony_ci		eqo->q.created = true;
103662306a36Sopenharmony_ci	}
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
103962306a36Sopenharmony_ci	return status;
104062306a36Sopenharmony_ci}
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci/* Use MCC */
104362306a36Sopenharmony_ciint be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
104462306a36Sopenharmony_ci			  bool permanent, u32 if_handle, u32 pmac_id)
104562306a36Sopenharmony_ci{
104662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
104762306a36Sopenharmony_ci	struct be_cmd_req_mac_query *req;
104862306a36Sopenharmony_ci	int status;
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
105362306a36Sopenharmony_ci	if (!wrb) {
105462306a36Sopenharmony_ci		status = -EBUSY;
105562306a36Sopenharmony_ci		goto err;
105662306a36Sopenharmony_ci	}
105762306a36Sopenharmony_ci	req = embedded_payload(wrb);
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
106062306a36Sopenharmony_ci			       OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb,
106162306a36Sopenharmony_ci			       NULL);
106262306a36Sopenharmony_ci	req->type = MAC_ADDRESS_TYPE_NETWORK;
106362306a36Sopenharmony_ci	if (permanent) {
106462306a36Sopenharmony_ci		req->permanent = 1;
106562306a36Sopenharmony_ci	} else {
106662306a36Sopenharmony_ci		req->if_id = cpu_to_le16((u16)if_handle);
106762306a36Sopenharmony_ci		req->pmac_id = cpu_to_le32(pmac_id);
106862306a36Sopenharmony_ci		req->permanent = 0;
106962306a36Sopenharmony_ci	}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
107262306a36Sopenharmony_ci	if (!status) {
107362306a36Sopenharmony_ci		struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
107662306a36Sopenharmony_ci	}
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_cierr:
107962306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
108062306a36Sopenharmony_ci	return status;
108162306a36Sopenharmony_ci}
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci/* Uses synchronous MCCQ */
108462306a36Sopenharmony_ciint be_cmd_pmac_add(struct be_adapter *adapter, const u8 *mac_addr,
108562306a36Sopenharmony_ci		    u32 if_id, u32 *pmac_id, u32 domain)
108662306a36Sopenharmony_ci{
108762306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
108862306a36Sopenharmony_ci	struct be_cmd_req_pmac_add *req;
108962306a36Sopenharmony_ci	int status;
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
109462306a36Sopenharmony_ci	if (!wrb) {
109562306a36Sopenharmony_ci		status = -EBUSY;
109662306a36Sopenharmony_ci		goto err;
109762306a36Sopenharmony_ci	}
109862306a36Sopenharmony_ci	req = embedded_payload(wrb);
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
110162306a36Sopenharmony_ci			       OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb,
110262306a36Sopenharmony_ci			       NULL);
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	req->hdr.domain = domain;
110562306a36Sopenharmony_ci	req->if_id = cpu_to_le32(if_id);
110662306a36Sopenharmony_ci	memcpy(req->mac_address, mac_addr, ETH_ALEN);
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
110962306a36Sopenharmony_ci	if (!status) {
111062306a36Sopenharmony_ci		struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci		*pmac_id = le32_to_cpu(resp->pmac_id);
111362306a36Sopenharmony_ci	}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_cierr:
111662306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST)
111962306a36Sopenharmony_ci		status = -EPERM;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	return status;
112262306a36Sopenharmony_ci}
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci/* Uses synchronous MCCQ */
112562306a36Sopenharmony_ciint be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom)
112662306a36Sopenharmony_ci{
112762306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
112862306a36Sopenharmony_ci	struct be_cmd_req_pmac_del *req;
112962306a36Sopenharmony_ci	int status;
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci	if (pmac_id == -1)
113262306a36Sopenharmony_ci		return 0;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
113762306a36Sopenharmony_ci	if (!wrb) {
113862306a36Sopenharmony_ci		status = -EBUSY;
113962306a36Sopenharmony_ci		goto err;
114062306a36Sopenharmony_ci	}
114162306a36Sopenharmony_ci	req = embedded_payload(wrb);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
114462306a36Sopenharmony_ci			       OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req),
114562306a36Sopenharmony_ci			       wrb, NULL);
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	req->hdr.domain = dom;
114862306a36Sopenharmony_ci	req->if_id = cpu_to_le32(if_id);
114962306a36Sopenharmony_ci	req->pmac_id = cpu_to_le32(pmac_id);
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_cierr:
115462306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
115562306a36Sopenharmony_ci	return status;
115662306a36Sopenharmony_ci}
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci/* Uses Mbox */
115962306a36Sopenharmony_ciint be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
116062306a36Sopenharmony_ci		     struct be_queue_info *eq, bool no_delay, int coalesce_wm)
116162306a36Sopenharmony_ci{
116262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
116362306a36Sopenharmony_ci	struct be_cmd_req_cq_create *req;
116462306a36Sopenharmony_ci	struct be_dma_mem *q_mem = &cq->dma_mem;
116562306a36Sopenharmony_ci	void *ctxt;
116662306a36Sopenharmony_ci	int status;
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
116962306a36Sopenharmony_ci		return -1;
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
117262306a36Sopenharmony_ci	req = embedded_payload(wrb);
117362306a36Sopenharmony_ci	ctxt = &req->context;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
117662306a36Sopenharmony_ci			       OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb,
117762306a36Sopenharmony_ci			       NULL);
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	if (BEx_chip(adapter)) {
118262306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
118362306a36Sopenharmony_ci			      coalesce_wm);
118462306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, nodelay,
118562306a36Sopenharmony_ci			      ctxt, no_delay);
118662306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
118762306a36Sopenharmony_ci			      __ilog2_u32(cq->len / 256));
118862306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
118962306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
119062306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
119162306a36Sopenharmony_ci	} else {
119262306a36Sopenharmony_ci		req->hdr.version = 2;
119362306a36Sopenharmony_ci		req->page_size = 1; /* 1 for 4K */
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci		/* coalesce-wm field in this cmd is not relevant to Lancer.
119662306a36Sopenharmony_ci		 * Lancer uses COMMON_MODIFY_CQ to set this field
119762306a36Sopenharmony_ci		 */
119862306a36Sopenharmony_ci		if (!lancer_chip(adapter))
119962306a36Sopenharmony_ci			AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
120062306a36Sopenharmony_ci				      ctxt, coalesce_wm);
120162306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt,
120262306a36Sopenharmony_ci			      no_delay);
120362306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
120462306a36Sopenharmony_ci			      __ilog2_u32(cq->len / 256));
120562306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
120662306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
120762306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
120862306a36Sopenharmony_ci	}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	be_dws_cpu_to_le(ctxt, sizeof(req->context));
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
121562306a36Sopenharmony_ci	if (!status) {
121662306a36Sopenharmony_ci		struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci		cq->id = le16_to_cpu(resp->cq_id);
121962306a36Sopenharmony_ci		cq->created = true;
122062306a36Sopenharmony_ci	}
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	return status;
122562306a36Sopenharmony_ci}
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_cistatic u32 be_encoded_q_len(int q_len)
122862306a36Sopenharmony_ci{
122962306a36Sopenharmony_ci	u32 len_encoded = fls(q_len); /* log2(len) + 1 */
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	if (len_encoded == 16)
123262306a36Sopenharmony_ci		len_encoded = 0;
123362306a36Sopenharmony_ci	return len_encoded;
123462306a36Sopenharmony_ci}
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_cistatic int be_cmd_mccq_ext_create(struct be_adapter *adapter,
123762306a36Sopenharmony_ci				  struct be_queue_info *mccq,
123862306a36Sopenharmony_ci				  struct be_queue_info *cq)
123962306a36Sopenharmony_ci{
124062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
124162306a36Sopenharmony_ci	struct be_cmd_req_mcc_ext_create *req;
124262306a36Sopenharmony_ci	struct be_dma_mem *q_mem = &mccq->dma_mem;
124362306a36Sopenharmony_ci	void *ctxt;
124462306a36Sopenharmony_ci	int status;
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
124762306a36Sopenharmony_ci		return -1;
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
125062306a36Sopenharmony_ci	req = embedded_payload(wrb);
125162306a36Sopenharmony_ci	ctxt = &req->context;
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
125462306a36Sopenharmony_ci			       OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb,
125562306a36Sopenharmony_ci			       NULL);
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
125862306a36Sopenharmony_ci	if (BEx_chip(adapter)) {
125962306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
126062306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
126162306a36Sopenharmony_ci			      be_encoded_q_len(mccq->len));
126262306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
126362306a36Sopenharmony_ci	} else {
126462306a36Sopenharmony_ci		req->hdr.version = 1;
126562306a36Sopenharmony_ci		req->cq_id = cpu_to_le16(cq->id);
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt,
126862306a36Sopenharmony_ci			      be_encoded_q_len(mccq->len));
126962306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1);
127062306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id,
127162306a36Sopenharmony_ci			      ctxt, cq->id);
127262306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid,
127362306a36Sopenharmony_ci			      ctxt, 1);
127462306a36Sopenharmony_ci	}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	/* Subscribe to Link State, Sliport Event and Group 5 Events
127762306a36Sopenharmony_ci	 * (bits 1, 5 and 17 set)
127862306a36Sopenharmony_ci	 */
127962306a36Sopenharmony_ci	req->async_event_bitmap[0] =
128062306a36Sopenharmony_ci			cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) |
128162306a36Sopenharmony_ci				    BIT(ASYNC_EVENT_CODE_GRP_5) |
128262306a36Sopenharmony_ci				    BIT(ASYNC_EVENT_CODE_QNQ) |
128362306a36Sopenharmony_ci				    BIT(ASYNC_EVENT_CODE_SLIPORT));
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	be_dws_cpu_to_le(ctxt, sizeof(req->context));
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
129062306a36Sopenharmony_ci	if (!status) {
129162306a36Sopenharmony_ci		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci		mccq->id = le16_to_cpu(resp->id);
129462306a36Sopenharmony_ci		mccq->created = true;
129562306a36Sopenharmony_ci	}
129662306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	return status;
129962306a36Sopenharmony_ci}
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_cistatic int be_cmd_mccq_org_create(struct be_adapter *adapter,
130262306a36Sopenharmony_ci				  struct be_queue_info *mccq,
130362306a36Sopenharmony_ci				  struct be_queue_info *cq)
130462306a36Sopenharmony_ci{
130562306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
130662306a36Sopenharmony_ci	struct be_cmd_req_mcc_create *req;
130762306a36Sopenharmony_ci	struct be_dma_mem *q_mem = &mccq->dma_mem;
130862306a36Sopenharmony_ci	void *ctxt;
130962306a36Sopenharmony_ci	int status;
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
131262306a36Sopenharmony_ci		return -1;
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
131562306a36Sopenharmony_ci	req = embedded_payload(wrb);
131662306a36Sopenharmony_ci	ctxt = &req->context;
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
131962306a36Sopenharmony_ci			       OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb,
132062306a36Sopenharmony_ci			       NULL);
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
132562306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
132662306a36Sopenharmony_ci		      be_encoded_q_len(mccq->len));
132762306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci	be_dws_cpu_to_le(ctxt, sizeof(req->context));
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
133462306a36Sopenharmony_ci	if (!status) {
133562306a36Sopenharmony_ci		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci		mccq->id = le16_to_cpu(resp->id);
133862306a36Sopenharmony_ci		mccq->created = true;
133962306a36Sopenharmony_ci	}
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
134262306a36Sopenharmony_ci	return status;
134362306a36Sopenharmony_ci}
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ciint be_cmd_mccq_create(struct be_adapter *adapter,
134662306a36Sopenharmony_ci		       struct be_queue_info *mccq, struct be_queue_info *cq)
134762306a36Sopenharmony_ci{
134862306a36Sopenharmony_ci	int status;
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	status = be_cmd_mccq_ext_create(adapter, mccq, cq);
135162306a36Sopenharmony_ci	if (status && BEx_chip(adapter)) {
135262306a36Sopenharmony_ci		dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
135362306a36Sopenharmony_ci			"or newer to avoid conflicting priorities between NIC "
135462306a36Sopenharmony_ci			"and FCoE traffic");
135562306a36Sopenharmony_ci		status = be_cmd_mccq_org_create(adapter, mccq, cq);
135662306a36Sopenharmony_ci	}
135762306a36Sopenharmony_ci	return status;
135862306a36Sopenharmony_ci}
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ciint be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo)
136162306a36Sopenharmony_ci{
136262306a36Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
136362306a36Sopenharmony_ci	struct be_cmd_req_eth_tx_create *req;
136462306a36Sopenharmony_ci	struct be_queue_info *txq = &txo->q;
136562306a36Sopenharmony_ci	struct be_queue_info *cq = &txo->cq;
136662306a36Sopenharmony_ci	struct be_dma_mem *q_mem = &txq->dma_mem;
136762306a36Sopenharmony_ci	int status, ver = 0;
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci	req = embedded_payload(&wrb);
137062306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
137162306a36Sopenharmony_ci			       OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL);
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	if (lancer_chip(adapter)) {
137462306a36Sopenharmony_ci		req->hdr.version = 1;
137562306a36Sopenharmony_ci	} else if (BEx_chip(adapter)) {
137662306a36Sopenharmony_ci		if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC)
137762306a36Sopenharmony_ci			req->hdr.version = 2;
137862306a36Sopenharmony_ci	} else { /* For SH */
137962306a36Sopenharmony_ci		req->hdr.version = 2;
138062306a36Sopenharmony_ci	}
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	if (req->hdr.version > 0)
138362306a36Sopenharmony_ci		req->if_id = cpu_to_le16(adapter->if_handle);
138462306a36Sopenharmony_ci	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
138562306a36Sopenharmony_ci	req->ulp_num = BE_ULP1_NUM;
138662306a36Sopenharmony_ci	req->type = BE_ETH_TX_RING_TYPE_STANDARD;
138762306a36Sopenharmony_ci	req->cq_id = cpu_to_le16(cq->id);
138862306a36Sopenharmony_ci	req->queue_size = be_encoded_q_len(txq->len);
138962306a36Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
139062306a36Sopenharmony_ci	ver = req->hdr.version;
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
139362306a36Sopenharmony_ci	if (!status) {
139462306a36Sopenharmony_ci		struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb);
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci		txq->id = le16_to_cpu(resp->cid);
139762306a36Sopenharmony_ci		if (ver == 2)
139862306a36Sopenharmony_ci			txo->db_offset = le32_to_cpu(resp->db_offset);
139962306a36Sopenharmony_ci		else
140062306a36Sopenharmony_ci			txo->db_offset = DB_TXULP1_OFFSET;
140162306a36Sopenharmony_ci		txq->created = true;
140262306a36Sopenharmony_ci	}
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	return status;
140562306a36Sopenharmony_ci}
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci/* Uses MCC */
140862306a36Sopenharmony_ciint be_cmd_rxq_create(struct be_adapter *adapter,
140962306a36Sopenharmony_ci		      struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
141062306a36Sopenharmony_ci		      u32 if_id, u32 rss, u8 *rss_id)
141162306a36Sopenharmony_ci{
141262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
141362306a36Sopenharmony_ci	struct be_cmd_req_eth_rx_create *req;
141462306a36Sopenharmony_ci	struct be_dma_mem *q_mem = &rxq->dma_mem;
141562306a36Sopenharmony_ci	int status;
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
142062306a36Sopenharmony_ci	if (!wrb) {
142162306a36Sopenharmony_ci		status = -EBUSY;
142262306a36Sopenharmony_ci		goto err;
142362306a36Sopenharmony_ci	}
142462306a36Sopenharmony_ci	req = embedded_payload(wrb);
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
142762306a36Sopenharmony_ci			       OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL);
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	req->cq_id = cpu_to_le16(cq_id);
143062306a36Sopenharmony_ci	req->frag_size = fls(frag_size) - 1;
143162306a36Sopenharmony_ci	req->num_pages = 2;
143262306a36Sopenharmony_ci	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
143362306a36Sopenharmony_ci	req->interface_id = cpu_to_le32(if_id);
143462306a36Sopenharmony_ci	req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE);
143562306a36Sopenharmony_ci	req->rss_queue = cpu_to_le32(rss);
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
143862306a36Sopenharmony_ci	if (!status) {
143962306a36Sopenharmony_ci		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci		rxq->id = le16_to_cpu(resp->id);
144262306a36Sopenharmony_ci		rxq->created = true;
144362306a36Sopenharmony_ci		*rss_id = resp->rss_id;
144462306a36Sopenharmony_ci	}
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_cierr:
144762306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
144862306a36Sopenharmony_ci	return status;
144962306a36Sopenharmony_ci}
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci/* Generic destroyer function for all types of queues
145262306a36Sopenharmony_ci * Uses Mbox
145362306a36Sopenharmony_ci */
145462306a36Sopenharmony_ciint be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
145562306a36Sopenharmony_ci		     int queue_type)
145662306a36Sopenharmony_ci{
145762306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
145862306a36Sopenharmony_ci	struct be_cmd_req_q_destroy *req;
145962306a36Sopenharmony_ci	u8 subsys = 0, opcode = 0;
146062306a36Sopenharmony_ci	int status;
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
146362306a36Sopenharmony_ci		return -1;
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
146662306a36Sopenharmony_ci	req = embedded_payload(wrb);
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	switch (queue_type) {
146962306a36Sopenharmony_ci	case QTYPE_EQ:
147062306a36Sopenharmony_ci		subsys = CMD_SUBSYSTEM_COMMON;
147162306a36Sopenharmony_ci		opcode = OPCODE_COMMON_EQ_DESTROY;
147262306a36Sopenharmony_ci		break;
147362306a36Sopenharmony_ci	case QTYPE_CQ:
147462306a36Sopenharmony_ci		subsys = CMD_SUBSYSTEM_COMMON;
147562306a36Sopenharmony_ci		opcode = OPCODE_COMMON_CQ_DESTROY;
147662306a36Sopenharmony_ci		break;
147762306a36Sopenharmony_ci	case QTYPE_TXQ:
147862306a36Sopenharmony_ci		subsys = CMD_SUBSYSTEM_ETH;
147962306a36Sopenharmony_ci		opcode = OPCODE_ETH_TX_DESTROY;
148062306a36Sopenharmony_ci		break;
148162306a36Sopenharmony_ci	case QTYPE_RXQ:
148262306a36Sopenharmony_ci		subsys = CMD_SUBSYSTEM_ETH;
148362306a36Sopenharmony_ci		opcode = OPCODE_ETH_RX_DESTROY;
148462306a36Sopenharmony_ci		break;
148562306a36Sopenharmony_ci	case QTYPE_MCCQ:
148662306a36Sopenharmony_ci		subsys = CMD_SUBSYSTEM_COMMON;
148762306a36Sopenharmony_ci		opcode = OPCODE_COMMON_MCC_DESTROY;
148862306a36Sopenharmony_ci		break;
148962306a36Sopenharmony_ci	default:
149062306a36Sopenharmony_ci		BUG();
149162306a36Sopenharmony_ci	}
149262306a36Sopenharmony_ci
149362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb,
149462306a36Sopenharmony_ci			       NULL);
149562306a36Sopenharmony_ci	req->id = cpu_to_le16(q->id);
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
149862306a36Sopenharmony_ci	q->created = false;
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
150162306a36Sopenharmony_ci	return status;
150262306a36Sopenharmony_ci}
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci/* Uses MCC */
150562306a36Sopenharmony_ciint be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
150662306a36Sopenharmony_ci{
150762306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
150862306a36Sopenharmony_ci	struct be_cmd_req_q_destroy *req;
150962306a36Sopenharmony_ci	int status;
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
151462306a36Sopenharmony_ci	if (!wrb) {
151562306a36Sopenharmony_ci		status = -EBUSY;
151662306a36Sopenharmony_ci		goto err;
151762306a36Sopenharmony_ci	}
151862306a36Sopenharmony_ci	req = embedded_payload(wrb);
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
152162306a36Sopenharmony_ci			       OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL);
152262306a36Sopenharmony_ci	req->id = cpu_to_le16(q->id);
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
152562306a36Sopenharmony_ci	q->created = false;
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_cierr:
152862306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
152962306a36Sopenharmony_ci	return status;
153062306a36Sopenharmony_ci}
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci/* Create an rx filtering policy configuration on an i/f
153362306a36Sopenharmony_ci * Will use MBOX only if MCCQ has not been created.
153462306a36Sopenharmony_ci */
153562306a36Sopenharmony_ciint be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
153662306a36Sopenharmony_ci		     u32 *if_handle, u32 domain)
153762306a36Sopenharmony_ci{
153862306a36Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
153962306a36Sopenharmony_ci	struct be_cmd_req_if_create *req;
154062306a36Sopenharmony_ci	int status;
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci	req = embedded_payload(&wrb);
154362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
154462306a36Sopenharmony_ci			       OPCODE_COMMON_NTWK_INTERFACE_CREATE,
154562306a36Sopenharmony_ci			       sizeof(*req), &wrb, NULL);
154662306a36Sopenharmony_ci	req->hdr.domain = domain;
154762306a36Sopenharmony_ci	req->capability_flags = cpu_to_le32(cap_flags);
154862306a36Sopenharmony_ci	req->enable_flags = cpu_to_le32(en_flags);
154962306a36Sopenharmony_ci	req->pmac_invalid = true;
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
155262306a36Sopenharmony_ci	if (!status) {
155362306a36Sopenharmony_ci		struct be_cmd_resp_if_create *resp = embedded_payload(&wrb);
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci		*if_handle = le32_to_cpu(resp->interface_id);
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci		/* Hack to retrieve VF's pmac-id on BE3 */
155862306a36Sopenharmony_ci		if (BE3_chip(adapter) && be_virtfn(adapter))
155962306a36Sopenharmony_ci			adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id);
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci	return status;
156262306a36Sopenharmony_ci}
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci/* Uses MCCQ if available else MBOX */
156562306a36Sopenharmony_ciint be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain)
156662306a36Sopenharmony_ci{
156762306a36Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
156862306a36Sopenharmony_ci	struct be_cmd_req_if_destroy *req;
156962306a36Sopenharmony_ci	int status;
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	if (interface_id == -1)
157262306a36Sopenharmony_ci		return 0;
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci	req = embedded_payload(&wrb);
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
157762306a36Sopenharmony_ci			       OPCODE_COMMON_NTWK_INTERFACE_DESTROY,
157862306a36Sopenharmony_ci			       sizeof(*req), &wrb, NULL);
157962306a36Sopenharmony_ci	req->hdr.domain = domain;
158062306a36Sopenharmony_ci	req->interface_id = cpu_to_le32(interface_id);
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
158362306a36Sopenharmony_ci	return status;
158462306a36Sopenharmony_ci}
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci/* Get stats is a non embedded command: the request is not embedded inside
158762306a36Sopenharmony_ci * WRB but is a separate dma memory block
158862306a36Sopenharmony_ci * Uses asynchronous MCC
158962306a36Sopenharmony_ci */
159062306a36Sopenharmony_ciint be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
159162306a36Sopenharmony_ci{
159262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
159362306a36Sopenharmony_ci	struct be_cmd_req_hdr *hdr;
159462306a36Sopenharmony_ci	int status = 0;
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
159962306a36Sopenharmony_ci	if (!wrb) {
160062306a36Sopenharmony_ci		status = -EBUSY;
160162306a36Sopenharmony_ci		goto err;
160262306a36Sopenharmony_ci	}
160362306a36Sopenharmony_ci	hdr = nonemb_cmd->va;
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
160662306a36Sopenharmony_ci			       OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb,
160762306a36Sopenharmony_ci			       nonemb_cmd);
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	/* version 1 of the cmd is not supported only by BE2 */
161062306a36Sopenharmony_ci	if (BE2_chip(adapter))
161162306a36Sopenharmony_ci		hdr->version = 0;
161262306a36Sopenharmony_ci	if (BE3_chip(adapter) || lancer_chip(adapter))
161362306a36Sopenharmony_ci		hdr->version = 1;
161462306a36Sopenharmony_ci	else
161562306a36Sopenharmony_ci		hdr->version = 2;
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci	status = be_mcc_notify(adapter);
161862306a36Sopenharmony_ci	if (status)
161962306a36Sopenharmony_ci		goto err;
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	adapter->stats_cmd_sent = true;
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_cierr:
162462306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
162562306a36Sopenharmony_ci	return status;
162662306a36Sopenharmony_ci}
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_ci/* Lancer Stats */
162962306a36Sopenharmony_ciint lancer_cmd_get_pport_stats(struct be_adapter *adapter,
163062306a36Sopenharmony_ci			       struct be_dma_mem *nonemb_cmd)
163162306a36Sopenharmony_ci{
163262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
163362306a36Sopenharmony_ci	struct lancer_cmd_req_pport_stats *req;
163462306a36Sopenharmony_ci	int status = 0;
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
163762306a36Sopenharmony_ci			    CMD_SUBSYSTEM_ETH))
163862306a36Sopenharmony_ci		return -EPERM;
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
164362306a36Sopenharmony_ci	if (!wrb) {
164462306a36Sopenharmony_ci		status = -EBUSY;
164562306a36Sopenharmony_ci		goto err;
164662306a36Sopenharmony_ci	}
164762306a36Sopenharmony_ci	req = nonemb_cmd->va;
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
165062306a36Sopenharmony_ci			       OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size,
165162306a36Sopenharmony_ci			       wrb, nonemb_cmd);
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci	req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num);
165462306a36Sopenharmony_ci	req->cmd_params.params.reset_stats = 0;
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	status = be_mcc_notify(adapter);
165762306a36Sopenharmony_ci	if (status)
165862306a36Sopenharmony_ci		goto err;
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	adapter->stats_cmd_sent = true;
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_cierr:
166362306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
166462306a36Sopenharmony_ci	return status;
166562306a36Sopenharmony_ci}
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_cistatic int be_mac_to_link_speed(int mac_speed)
166862306a36Sopenharmony_ci{
166962306a36Sopenharmony_ci	switch (mac_speed) {
167062306a36Sopenharmony_ci	case PHY_LINK_SPEED_ZERO:
167162306a36Sopenharmony_ci		return 0;
167262306a36Sopenharmony_ci	case PHY_LINK_SPEED_10MBPS:
167362306a36Sopenharmony_ci		return 10;
167462306a36Sopenharmony_ci	case PHY_LINK_SPEED_100MBPS:
167562306a36Sopenharmony_ci		return 100;
167662306a36Sopenharmony_ci	case PHY_LINK_SPEED_1GBPS:
167762306a36Sopenharmony_ci		return 1000;
167862306a36Sopenharmony_ci	case PHY_LINK_SPEED_10GBPS:
167962306a36Sopenharmony_ci		return 10000;
168062306a36Sopenharmony_ci	case PHY_LINK_SPEED_20GBPS:
168162306a36Sopenharmony_ci		return 20000;
168262306a36Sopenharmony_ci	case PHY_LINK_SPEED_25GBPS:
168362306a36Sopenharmony_ci		return 25000;
168462306a36Sopenharmony_ci	case PHY_LINK_SPEED_40GBPS:
168562306a36Sopenharmony_ci		return 40000;
168662306a36Sopenharmony_ci	}
168762306a36Sopenharmony_ci	return 0;
168862306a36Sopenharmony_ci}
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci/* Uses synchronous mcc
169162306a36Sopenharmony_ci * Returns link_speed in Mbps
169262306a36Sopenharmony_ci */
169362306a36Sopenharmony_ciint be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
169462306a36Sopenharmony_ci			     u8 *link_status, u32 dom)
169562306a36Sopenharmony_ci{
169662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
169762306a36Sopenharmony_ci	struct be_cmd_req_link_status *req;
169862306a36Sopenharmony_ci	int status;
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci	if (link_status)
170362306a36Sopenharmony_ci		*link_status = LINK_DOWN;
170462306a36Sopenharmony_ci
170562306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
170662306a36Sopenharmony_ci	if (!wrb) {
170762306a36Sopenharmony_ci		status = -EBUSY;
170862306a36Sopenharmony_ci		goto err;
170962306a36Sopenharmony_ci	}
171062306a36Sopenharmony_ci	req = embedded_payload(wrb);
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
171362306a36Sopenharmony_ci			       OPCODE_COMMON_NTWK_LINK_STATUS_QUERY,
171462306a36Sopenharmony_ci			       sizeof(*req), wrb, NULL);
171562306a36Sopenharmony_ci
171662306a36Sopenharmony_ci	/* version 1 of the cmd is not supported only by BE2 */
171762306a36Sopenharmony_ci	if (!BE2_chip(adapter))
171862306a36Sopenharmony_ci		req->hdr.version = 1;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	req->hdr.domain = dom;
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
172362306a36Sopenharmony_ci	if (!status) {
172462306a36Sopenharmony_ci		struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci		if (link_speed) {
172762306a36Sopenharmony_ci			*link_speed = resp->link_speed ?
172862306a36Sopenharmony_ci				      le16_to_cpu(resp->link_speed) * 10 :
172962306a36Sopenharmony_ci				      be_mac_to_link_speed(resp->mac_speed);
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci			if (!resp->logical_link_status)
173262306a36Sopenharmony_ci				*link_speed = 0;
173362306a36Sopenharmony_ci		}
173462306a36Sopenharmony_ci		if (link_status)
173562306a36Sopenharmony_ci			*link_status = resp->logical_link_status;
173662306a36Sopenharmony_ci	}
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_cierr:
173962306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
174062306a36Sopenharmony_ci	return status;
174162306a36Sopenharmony_ci}
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci/* Uses synchronous mcc */
174462306a36Sopenharmony_ciint be_cmd_get_die_temperature(struct be_adapter *adapter)
174562306a36Sopenharmony_ci{
174662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
174762306a36Sopenharmony_ci	struct be_cmd_req_get_cntl_addnl_attribs *req;
174862306a36Sopenharmony_ci	int status = 0;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
175162306a36Sopenharmony_ci
175262306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
175362306a36Sopenharmony_ci	if (!wrb) {
175462306a36Sopenharmony_ci		status = -EBUSY;
175562306a36Sopenharmony_ci		goto err;
175662306a36Sopenharmony_ci	}
175762306a36Sopenharmony_ci	req = embedded_payload(wrb);
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
176062306a36Sopenharmony_ci			       OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES,
176162306a36Sopenharmony_ci			       sizeof(*req), wrb, NULL);
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	status = be_mcc_notify(adapter);
176462306a36Sopenharmony_cierr:
176562306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
176662306a36Sopenharmony_ci	return status;
176762306a36Sopenharmony_ci}
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci/* Uses synchronous mcc */
177062306a36Sopenharmony_ciint be_cmd_get_fat_dump_len(struct be_adapter *adapter, u32 *dump_size)
177162306a36Sopenharmony_ci{
177262306a36Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
177362306a36Sopenharmony_ci	struct be_cmd_req_get_fat *req;
177462306a36Sopenharmony_ci	int status;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	req = embedded_payload(&wrb);
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
177962306a36Sopenharmony_ci			       OPCODE_COMMON_MANAGE_FAT, sizeof(*req),
178062306a36Sopenharmony_ci			       &wrb, NULL);
178162306a36Sopenharmony_ci	req->fat_operation = cpu_to_le32(QUERY_FAT);
178262306a36Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
178362306a36Sopenharmony_ci	if (!status) {
178462306a36Sopenharmony_ci		struct be_cmd_resp_get_fat *resp = embedded_payload(&wrb);
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci		if (dump_size && resp->log_size)
178762306a36Sopenharmony_ci			*dump_size = le32_to_cpu(resp->log_size) -
178862306a36Sopenharmony_ci					sizeof(u32);
178962306a36Sopenharmony_ci	}
179062306a36Sopenharmony_ci	return status;
179162306a36Sopenharmony_ci}
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ciint be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf)
179462306a36Sopenharmony_ci{
179562306a36Sopenharmony_ci	struct be_dma_mem get_fat_cmd;
179662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
179762306a36Sopenharmony_ci	struct be_cmd_req_get_fat *req;
179862306a36Sopenharmony_ci	u32 offset = 0, total_size, buf_size,
179962306a36Sopenharmony_ci				log_offset = sizeof(u32), payload_len;
180062306a36Sopenharmony_ci	int status;
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci	if (buf_len == 0)
180362306a36Sopenharmony_ci		return 0;
180462306a36Sopenharmony_ci
180562306a36Sopenharmony_ci	total_size = buf_len;
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60 * 1024;
180862306a36Sopenharmony_ci	get_fat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
180962306a36Sopenharmony_ci					    get_fat_cmd.size,
181062306a36Sopenharmony_ci					    &get_fat_cmd.dma, GFP_ATOMIC);
181162306a36Sopenharmony_ci	if (!get_fat_cmd.va)
181262306a36Sopenharmony_ci		return -ENOMEM;
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	while (total_size) {
181762306a36Sopenharmony_ci		buf_size = min(total_size, (u32)60 * 1024);
181862306a36Sopenharmony_ci		total_size -= buf_size;
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci		wrb = wrb_from_mccq(adapter);
182162306a36Sopenharmony_ci		if (!wrb) {
182262306a36Sopenharmony_ci			status = -EBUSY;
182362306a36Sopenharmony_ci			goto err;
182462306a36Sopenharmony_ci		}
182562306a36Sopenharmony_ci		req = get_fat_cmd.va;
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci		payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size;
182862306a36Sopenharmony_ci		be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
182962306a36Sopenharmony_ci				       OPCODE_COMMON_MANAGE_FAT, payload_len,
183062306a36Sopenharmony_ci				       wrb, &get_fat_cmd);
183162306a36Sopenharmony_ci
183262306a36Sopenharmony_ci		req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
183362306a36Sopenharmony_ci		req->read_log_offset = cpu_to_le32(log_offset);
183462306a36Sopenharmony_ci		req->read_log_length = cpu_to_le32(buf_size);
183562306a36Sopenharmony_ci		req->data_buffer_size = cpu_to_le32(buf_size);
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_ci		status = be_mcc_notify_wait(adapter);
183862306a36Sopenharmony_ci		if (!status) {
183962306a36Sopenharmony_ci			struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci			memcpy(buf + offset,
184262306a36Sopenharmony_ci			       resp->data_buffer,
184362306a36Sopenharmony_ci			       le32_to_cpu(resp->read_log_length));
184462306a36Sopenharmony_ci		} else {
184562306a36Sopenharmony_ci			dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
184662306a36Sopenharmony_ci			goto err;
184762306a36Sopenharmony_ci		}
184862306a36Sopenharmony_ci		offset += buf_size;
184962306a36Sopenharmony_ci		log_offset += buf_size;
185062306a36Sopenharmony_ci	}
185162306a36Sopenharmony_cierr:
185262306a36Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, get_fat_cmd.size,
185362306a36Sopenharmony_ci			  get_fat_cmd.va, get_fat_cmd.dma);
185462306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
185562306a36Sopenharmony_ci	return status;
185662306a36Sopenharmony_ci}
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci/* Uses synchronous mcc */
185962306a36Sopenharmony_ciint be_cmd_get_fw_ver(struct be_adapter *adapter)
186062306a36Sopenharmony_ci{
186162306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
186262306a36Sopenharmony_ci	struct be_cmd_req_get_fw_version *req;
186362306a36Sopenharmony_ci	int status;
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
186862306a36Sopenharmony_ci	if (!wrb) {
186962306a36Sopenharmony_ci		status = -EBUSY;
187062306a36Sopenharmony_ci		goto err;
187162306a36Sopenharmony_ci	}
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_ci	req = embedded_payload(wrb);
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
187662306a36Sopenharmony_ci			       OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb,
187762306a36Sopenharmony_ci			       NULL);
187862306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
187962306a36Sopenharmony_ci	if (!status) {
188062306a36Sopenharmony_ci		struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci		strscpy(adapter->fw_ver, resp->firmware_version_string,
188362306a36Sopenharmony_ci			sizeof(adapter->fw_ver));
188462306a36Sopenharmony_ci		strscpy(adapter->fw_on_flash, resp->fw_on_flash_version_string,
188562306a36Sopenharmony_ci			sizeof(adapter->fw_on_flash));
188662306a36Sopenharmony_ci	}
188762306a36Sopenharmony_cierr:
188862306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
188962306a36Sopenharmony_ci	return status;
189062306a36Sopenharmony_ci}
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci/* set the EQ delay interval of an EQ to specified value
189362306a36Sopenharmony_ci * Uses async mcc
189462306a36Sopenharmony_ci */
189562306a36Sopenharmony_cistatic int __be_cmd_modify_eqd(struct be_adapter *adapter,
189662306a36Sopenharmony_ci			       struct be_set_eqd *set_eqd, int num)
189762306a36Sopenharmony_ci{
189862306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
189962306a36Sopenharmony_ci	struct be_cmd_req_modify_eq_delay *req;
190062306a36Sopenharmony_ci	int status = 0, i;
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
190562306a36Sopenharmony_ci	if (!wrb) {
190662306a36Sopenharmony_ci		status = -EBUSY;
190762306a36Sopenharmony_ci		goto err;
190862306a36Sopenharmony_ci	}
190962306a36Sopenharmony_ci	req = embedded_payload(wrb);
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
191262306a36Sopenharmony_ci			       OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb,
191362306a36Sopenharmony_ci			       NULL);
191462306a36Sopenharmony_ci
191562306a36Sopenharmony_ci	req->num_eq = cpu_to_le32(num);
191662306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
191762306a36Sopenharmony_ci		req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
191862306a36Sopenharmony_ci		req->set_eqd[i].phase = 0;
191962306a36Sopenharmony_ci		req->set_eqd[i].delay_multiplier =
192062306a36Sopenharmony_ci				cpu_to_le32(set_eqd[i].delay_multiplier);
192162306a36Sopenharmony_ci	}
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_ci	status = be_mcc_notify(adapter);
192462306a36Sopenharmony_cierr:
192562306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
192662306a36Sopenharmony_ci	return status;
192762306a36Sopenharmony_ci}
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ciint be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd,
193062306a36Sopenharmony_ci		      int num)
193162306a36Sopenharmony_ci{
193262306a36Sopenharmony_ci	int num_eqs, i = 0;
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci	while (num) {
193562306a36Sopenharmony_ci		num_eqs = min(num, 8);
193662306a36Sopenharmony_ci		__be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs);
193762306a36Sopenharmony_ci		i += num_eqs;
193862306a36Sopenharmony_ci		num -= num_eqs;
193962306a36Sopenharmony_ci	}
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci	return 0;
194262306a36Sopenharmony_ci}
194362306a36Sopenharmony_ci
194462306a36Sopenharmony_ci/* Uses sycnhronous mcc */
194562306a36Sopenharmony_ciint be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
194662306a36Sopenharmony_ci		       u32 num, u32 domain)
194762306a36Sopenharmony_ci{
194862306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
194962306a36Sopenharmony_ci	struct be_cmd_req_vlan_config *req;
195062306a36Sopenharmony_ci	int status;
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
195562306a36Sopenharmony_ci	if (!wrb) {
195662306a36Sopenharmony_ci		status = -EBUSY;
195762306a36Sopenharmony_ci		goto err;
195862306a36Sopenharmony_ci	}
195962306a36Sopenharmony_ci	req = embedded_payload(wrb);
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
196262306a36Sopenharmony_ci			       OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req),
196362306a36Sopenharmony_ci			       wrb, NULL);
196462306a36Sopenharmony_ci	req->hdr.domain = domain;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	req->interface_id = if_id;
196762306a36Sopenharmony_ci	req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0;
196862306a36Sopenharmony_ci	req->num_vlan = num;
196962306a36Sopenharmony_ci	memcpy(req->normal_vlan, vtag_array,
197062306a36Sopenharmony_ci	       req->num_vlan * sizeof(vtag_array[0]));
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
197362306a36Sopenharmony_cierr:
197462306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
197562306a36Sopenharmony_ci	return status;
197662306a36Sopenharmony_ci}
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_cistatic int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
197962306a36Sopenharmony_ci{
198062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
198162306a36Sopenharmony_ci	struct be_dma_mem *mem = &adapter->rx_filter;
198262306a36Sopenharmony_ci	struct be_cmd_req_rx_filter *req = mem->va;
198362306a36Sopenharmony_ci	int status;
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
198862306a36Sopenharmony_ci	if (!wrb) {
198962306a36Sopenharmony_ci		status = -EBUSY;
199062306a36Sopenharmony_ci		goto err;
199162306a36Sopenharmony_ci	}
199262306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
199362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
199462306a36Sopenharmony_ci			       OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req),
199562306a36Sopenharmony_ci			       wrb, mem);
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci	req->if_id = cpu_to_le32(adapter->if_handle);
199862306a36Sopenharmony_ci	req->if_flags_mask = cpu_to_le32(flags);
199962306a36Sopenharmony_ci	req->if_flags = (value == ON) ? req->if_flags_mask : 0;
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_ci	if (flags & BE_IF_FLAGS_MULTICAST) {
200262306a36Sopenharmony_ci		int i;
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_ci		/* Reset mcast promisc mode if already set by setting mask
200562306a36Sopenharmony_ci		 * and not setting flags field
200662306a36Sopenharmony_ci		 */
200762306a36Sopenharmony_ci		req->if_flags_mask |=
200862306a36Sopenharmony_ci			cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
200962306a36Sopenharmony_ci				    be_if_cap_flags(adapter));
201062306a36Sopenharmony_ci		req->mcast_num = cpu_to_le32(adapter->mc_count);
201162306a36Sopenharmony_ci		for (i = 0; i < adapter->mc_count; i++)
201262306a36Sopenharmony_ci			ether_addr_copy(req->mcast_mac[i].byte,
201362306a36Sopenharmony_ci					adapter->mc_list[i].mac);
201462306a36Sopenharmony_ci	}
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
201762306a36Sopenharmony_cierr:
201862306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
201962306a36Sopenharmony_ci	return status;
202062306a36Sopenharmony_ci}
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ciint be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
202362306a36Sopenharmony_ci{
202462306a36Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_ci	if ((flags & be_if_cap_flags(adapter)) != flags) {
202762306a36Sopenharmony_ci		dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags);
202862306a36Sopenharmony_ci		dev_warn(dev, "Interface is capable of 0x%x flags only\n",
202962306a36Sopenharmony_ci			 be_if_cap_flags(adapter));
203062306a36Sopenharmony_ci	}
203162306a36Sopenharmony_ci	flags &= be_if_cap_flags(adapter);
203262306a36Sopenharmony_ci	if (!flags)
203362306a36Sopenharmony_ci		return -ENOTSUPP;
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	return __be_cmd_rx_filter(adapter, flags, value);
203662306a36Sopenharmony_ci}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci/* Uses synchrounous mcc */
203962306a36Sopenharmony_ciint be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
204062306a36Sopenharmony_ci{
204162306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
204262306a36Sopenharmony_ci	struct be_cmd_req_set_flow_control *req;
204362306a36Sopenharmony_ci	int status;
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
204662306a36Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
204762306a36Sopenharmony_ci		return -EPERM;
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
205262306a36Sopenharmony_ci	if (!wrb) {
205362306a36Sopenharmony_ci		status = -EBUSY;
205462306a36Sopenharmony_ci		goto err;
205562306a36Sopenharmony_ci	}
205662306a36Sopenharmony_ci	req = embedded_payload(wrb);
205762306a36Sopenharmony_ci
205862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
205962306a36Sopenharmony_ci			       OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req),
206062306a36Sopenharmony_ci			       wrb, NULL);
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ci	req->hdr.version = 1;
206362306a36Sopenharmony_ci	req->tx_flow_control = cpu_to_le16((u16)tx_fc);
206462306a36Sopenharmony_ci	req->rx_flow_control = cpu_to_le16((u16)rx_fc);
206562306a36Sopenharmony_ci
206662306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_cierr:
206962306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
207062306a36Sopenharmony_ci
207162306a36Sopenharmony_ci	if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED)
207262306a36Sopenharmony_ci		return  -EOPNOTSUPP;
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ci	return status;
207562306a36Sopenharmony_ci}
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci/* Uses sycn mcc */
207862306a36Sopenharmony_ciint be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
207962306a36Sopenharmony_ci{
208062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
208162306a36Sopenharmony_ci	struct be_cmd_req_get_flow_control *req;
208262306a36Sopenharmony_ci	int status;
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
208562306a36Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
208662306a36Sopenharmony_ci		return -EPERM;
208762306a36Sopenharmony_ci
208862306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
209162306a36Sopenharmony_ci	if (!wrb) {
209262306a36Sopenharmony_ci		status = -EBUSY;
209362306a36Sopenharmony_ci		goto err;
209462306a36Sopenharmony_ci	}
209562306a36Sopenharmony_ci	req = embedded_payload(wrb);
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
209862306a36Sopenharmony_ci			       OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req),
209962306a36Sopenharmony_ci			       wrb, NULL);
210062306a36Sopenharmony_ci
210162306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
210262306a36Sopenharmony_ci	if (!status) {
210362306a36Sopenharmony_ci		struct be_cmd_resp_get_flow_control *resp =
210462306a36Sopenharmony_ci						embedded_payload(wrb);
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci		*tx_fc = le16_to_cpu(resp->tx_flow_control);
210762306a36Sopenharmony_ci		*rx_fc = le16_to_cpu(resp->rx_flow_control);
210862306a36Sopenharmony_ci	}
210962306a36Sopenharmony_ci
211062306a36Sopenharmony_cierr:
211162306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
211262306a36Sopenharmony_ci	return status;
211362306a36Sopenharmony_ci}
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_ci/* Uses mbox */
211662306a36Sopenharmony_ciint be_cmd_query_fw_cfg(struct be_adapter *adapter)
211762306a36Sopenharmony_ci{
211862306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
211962306a36Sopenharmony_ci	struct be_cmd_req_query_fw_cfg *req;
212062306a36Sopenharmony_ci	int status;
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
212362306a36Sopenharmony_ci		return -1;
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
212662306a36Sopenharmony_ci	req = embedded_payload(wrb);
212762306a36Sopenharmony_ci
212862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
212962306a36Sopenharmony_ci			       OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
213062306a36Sopenharmony_ci			       sizeof(*req), wrb, NULL);
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
213362306a36Sopenharmony_ci	if (!status) {
213462306a36Sopenharmony_ci		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
213562306a36Sopenharmony_ci
213662306a36Sopenharmony_ci		adapter->port_num = le32_to_cpu(resp->phys_port);
213762306a36Sopenharmony_ci		adapter->function_mode = le32_to_cpu(resp->function_mode);
213862306a36Sopenharmony_ci		adapter->function_caps = le32_to_cpu(resp->function_caps);
213962306a36Sopenharmony_ci		adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
214062306a36Sopenharmony_ci		dev_info(&adapter->pdev->dev,
214162306a36Sopenharmony_ci			 "FW config: function_mode=0x%x, function_caps=0x%x\n",
214262306a36Sopenharmony_ci			 adapter->function_mode, adapter->function_caps);
214362306a36Sopenharmony_ci	}
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
214662306a36Sopenharmony_ci	return status;
214762306a36Sopenharmony_ci}
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci/* Uses mbox */
215062306a36Sopenharmony_ciint be_cmd_reset_function(struct be_adapter *adapter)
215162306a36Sopenharmony_ci{
215262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
215362306a36Sopenharmony_ci	struct be_cmd_req_hdr *req;
215462306a36Sopenharmony_ci	int status;
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_ci	if (lancer_chip(adapter)) {
215762306a36Sopenharmony_ci		iowrite32(SLI_PORT_CONTROL_IP_MASK,
215862306a36Sopenharmony_ci			  adapter->db + SLIPORT_CONTROL_OFFSET);
215962306a36Sopenharmony_ci		status = lancer_wait_ready(adapter);
216062306a36Sopenharmony_ci		if (status)
216162306a36Sopenharmony_ci			dev_err(&adapter->pdev->dev,
216262306a36Sopenharmony_ci				"Adapter in non recoverable error\n");
216362306a36Sopenharmony_ci		return status;
216462306a36Sopenharmony_ci	}
216562306a36Sopenharmony_ci
216662306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
216762306a36Sopenharmony_ci		return -1;
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
217062306a36Sopenharmony_ci	req = embedded_payload(wrb);
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
217362306a36Sopenharmony_ci			       OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb,
217462306a36Sopenharmony_ci			       NULL);
217562306a36Sopenharmony_ci
217662306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
217962306a36Sopenharmony_ci	return status;
218062306a36Sopenharmony_ci}
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ciint be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
218362306a36Sopenharmony_ci		      u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey)
218462306a36Sopenharmony_ci{
218562306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
218662306a36Sopenharmony_ci	struct be_cmd_req_rss_config *req;
218762306a36Sopenharmony_ci	int status;
218862306a36Sopenharmony_ci
218962306a36Sopenharmony_ci	if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
219062306a36Sopenharmony_ci		return 0;
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
219562306a36Sopenharmony_ci	if (!wrb) {
219662306a36Sopenharmony_ci		status = -EBUSY;
219762306a36Sopenharmony_ci		goto err;
219862306a36Sopenharmony_ci	}
219962306a36Sopenharmony_ci	req = embedded_payload(wrb);
220062306a36Sopenharmony_ci
220162306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
220262306a36Sopenharmony_ci			       OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci	req->if_id = cpu_to_le32(adapter->if_handle);
220562306a36Sopenharmony_ci	req->enable_rss = cpu_to_le16(rss_hash_opts);
220662306a36Sopenharmony_ci	req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ci	if (!BEx_chip(adapter))
220962306a36Sopenharmony_ci		req->hdr.version = 1;
221062306a36Sopenharmony_ci
221162306a36Sopenharmony_ci	memcpy(req->cpu_table, rsstable, table_size);
221262306a36Sopenharmony_ci	memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN);
221362306a36Sopenharmony_ci	be_dws_cpu_to_le(req->hash, sizeof(req->hash));
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
221662306a36Sopenharmony_cierr:
221762306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
221862306a36Sopenharmony_ci	return status;
221962306a36Sopenharmony_ci}
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci/* Uses sync mcc */
222262306a36Sopenharmony_ciint be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
222362306a36Sopenharmony_ci			    u8 bcn, u8 sts, u8 state)
222462306a36Sopenharmony_ci{
222562306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
222662306a36Sopenharmony_ci	struct be_cmd_req_enable_disable_beacon *req;
222762306a36Sopenharmony_ci	int status;
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
223262306a36Sopenharmony_ci	if (!wrb) {
223362306a36Sopenharmony_ci		status = -EBUSY;
223462306a36Sopenharmony_ci		goto err;
223562306a36Sopenharmony_ci	}
223662306a36Sopenharmony_ci	req = embedded_payload(wrb);
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
223962306a36Sopenharmony_ci			       OPCODE_COMMON_ENABLE_DISABLE_BEACON,
224062306a36Sopenharmony_ci			       sizeof(*req), wrb, NULL);
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_ci	req->port_num = port_num;
224362306a36Sopenharmony_ci	req->beacon_state = state;
224462306a36Sopenharmony_ci	req->beacon_duration = bcn;
224562306a36Sopenharmony_ci	req->status_duration = sts;
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_cierr:
225062306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
225162306a36Sopenharmony_ci	return status;
225262306a36Sopenharmony_ci}
225362306a36Sopenharmony_ci
225462306a36Sopenharmony_ci/* Uses sync mcc */
225562306a36Sopenharmony_ciint be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
225662306a36Sopenharmony_ci{
225762306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
225862306a36Sopenharmony_ci	struct be_cmd_req_get_beacon_state *req;
225962306a36Sopenharmony_ci	int status;
226062306a36Sopenharmony_ci
226162306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
226262306a36Sopenharmony_ci
226362306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
226462306a36Sopenharmony_ci	if (!wrb) {
226562306a36Sopenharmony_ci		status = -EBUSY;
226662306a36Sopenharmony_ci		goto err;
226762306a36Sopenharmony_ci	}
226862306a36Sopenharmony_ci	req = embedded_payload(wrb);
226962306a36Sopenharmony_ci
227062306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
227162306a36Sopenharmony_ci			       OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req),
227262306a36Sopenharmony_ci			       wrb, NULL);
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci	req->port_num = port_num;
227562306a36Sopenharmony_ci
227662306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
227762306a36Sopenharmony_ci	if (!status) {
227862306a36Sopenharmony_ci		struct be_cmd_resp_get_beacon_state *resp =
227962306a36Sopenharmony_ci						embedded_payload(wrb);
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci		*state = resp->beacon_state;
228262306a36Sopenharmony_ci	}
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_cierr:
228562306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
228662306a36Sopenharmony_ci	return status;
228762306a36Sopenharmony_ci}
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci/* Uses sync mcc */
229062306a36Sopenharmony_ciint be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
229162306a36Sopenharmony_ci				      u8 page_num, u32 off, u32 len, u8 *data)
229262306a36Sopenharmony_ci{
229362306a36Sopenharmony_ci	struct be_dma_mem cmd;
229462306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
229562306a36Sopenharmony_ci	struct be_cmd_req_port_type *req;
229662306a36Sopenharmony_ci	int status;
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_ci	if (page_num > TR_PAGE_A2)
229962306a36Sopenharmony_ci		return -EINVAL;
230062306a36Sopenharmony_ci
230162306a36Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_resp_port_type);
230262306a36Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
230362306a36Sopenharmony_ci				    GFP_ATOMIC);
230462306a36Sopenharmony_ci	if (!cmd.va) {
230562306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory allocation failed\n");
230662306a36Sopenharmony_ci		return -ENOMEM;
230762306a36Sopenharmony_ci	}
230862306a36Sopenharmony_ci
230962306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
231262306a36Sopenharmony_ci	if (!wrb) {
231362306a36Sopenharmony_ci		status = -EBUSY;
231462306a36Sopenharmony_ci		goto err;
231562306a36Sopenharmony_ci	}
231662306a36Sopenharmony_ci	req = cmd.va;
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
231962306a36Sopenharmony_ci			       OPCODE_COMMON_READ_TRANSRECV_DATA,
232062306a36Sopenharmony_ci			       cmd.size, wrb, &cmd);
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci	req->port = cpu_to_le32(adapter->hba_port_num);
232362306a36Sopenharmony_ci	req->page_num = cpu_to_le32(page_num);
232462306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
232562306a36Sopenharmony_ci	if (!status && len > 0) {
232662306a36Sopenharmony_ci		struct be_cmd_resp_port_type *resp = cmd.va;
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci		memcpy(data, resp->page_data + off, len);
232962306a36Sopenharmony_ci	}
233062306a36Sopenharmony_cierr:
233162306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
233262306a36Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
233362306a36Sopenharmony_ci	return status;
233462306a36Sopenharmony_ci}
233562306a36Sopenharmony_ci
233662306a36Sopenharmony_cistatic int lancer_cmd_write_object(struct be_adapter *adapter,
233762306a36Sopenharmony_ci				   struct be_dma_mem *cmd, u32 data_size,
233862306a36Sopenharmony_ci				   u32 data_offset, const char *obj_name,
233962306a36Sopenharmony_ci				   u32 *data_written, u8 *change_status,
234062306a36Sopenharmony_ci				   u8 *addn_status)
234162306a36Sopenharmony_ci{
234262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
234362306a36Sopenharmony_ci	struct lancer_cmd_req_write_object *req;
234462306a36Sopenharmony_ci	struct lancer_cmd_resp_write_object *resp;
234562306a36Sopenharmony_ci	void *ctxt = NULL;
234662306a36Sopenharmony_ci	int status;
234762306a36Sopenharmony_ci
234862306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
234962306a36Sopenharmony_ci	adapter->flash_status = 0;
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
235262306a36Sopenharmony_ci	if (!wrb) {
235362306a36Sopenharmony_ci		status = -EBUSY;
235462306a36Sopenharmony_ci		goto err_unlock;
235562306a36Sopenharmony_ci	}
235662306a36Sopenharmony_ci
235762306a36Sopenharmony_ci	req = embedded_payload(wrb);
235862306a36Sopenharmony_ci
235962306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
236062306a36Sopenharmony_ci			       OPCODE_COMMON_WRITE_OBJECT,
236162306a36Sopenharmony_ci			       sizeof(struct lancer_cmd_req_write_object), wrb,
236262306a36Sopenharmony_ci			       NULL);
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_ci	ctxt = &req->context;
236562306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_lancer_write_obj_context,
236662306a36Sopenharmony_ci		      write_length, ctxt, data_size);
236762306a36Sopenharmony_ci
236862306a36Sopenharmony_ci	if (data_size == 0)
236962306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
237062306a36Sopenharmony_ci			      eof, ctxt, 1);
237162306a36Sopenharmony_ci	else
237262306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
237362306a36Sopenharmony_ci			      eof, ctxt, 0);
237462306a36Sopenharmony_ci
237562306a36Sopenharmony_ci	be_dws_cpu_to_le(ctxt, sizeof(req->context));
237662306a36Sopenharmony_ci	req->write_offset = cpu_to_le32(data_offset);
237762306a36Sopenharmony_ci	strscpy(req->object_name, obj_name, sizeof(req->object_name));
237862306a36Sopenharmony_ci	req->descriptor_count = cpu_to_le32(1);
237962306a36Sopenharmony_ci	req->buf_len = cpu_to_le32(data_size);
238062306a36Sopenharmony_ci	req->addr_low = cpu_to_le32((cmd->dma +
238162306a36Sopenharmony_ci				     sizeof(struct lancer_cmd_req_write_object))
238262306a36Sopenharmony_ci				    & 0xFFFFFFFF);
238362306a36Sopenharmony_ci	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma +
238462306a36Sopenharmony_ci				sizeof(struct lancer_cmd_req_write_object)));
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	status = be_mcc_notify(adapter);
238762306a36Sopenharmony_ci	if (status)
238862306a36Sopenharmony_ci		goto err_unlock;
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_ci	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
239362306a36Sopenharmony_ci					 msecs_to_jiffies(60000)))
239462306a36Sopenharmony_ci		status = -ETIMEDOUT;
239562306a36Sopenharmony_ci	else
239662306a36Sopenharmony_ci		status = adapter->flash_status;
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci	resp = embedded_payload(wrb);
239962306a36Sopenharmony_ci	if (!status) {
240062306a36Sopenharmony_ci		*data_written = le32_to_cpu(resp->actual_write_len);
240162306a36Sopenharmony_ci		*change_status = resp->change_status;
240262306a36Sopenharmony_ci	} else {
240362306a36Sopenharmony_ci		*addn_status = resp->additional_status;
240462306a36Sopenharmony_ci	}
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	return status;
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_cierr_unlock:
240962306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
241062306a36Sopenharmony_ci	return status;
241162306a36Sopenharmony_ci}
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ciint be_cmd_query_cable_type(struct be_adapter *adapter)
241462306a36Sopenharmony_ci{
241562306a36Sopenharmony_ci	u8 page_data[PAGE_DATA_LEN];
241662306a36Sopenharmony_ci	int status;
241762306a36Sopenharmony_ci
241862306a36Sopenharmony_ci	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
241962306a36Sopenharmony_ci						   0, PAGE_DATA_LEN, page_data);
242062306a36Sopenharmony_ci	if (!status) {
242162306a36Sopenharmony_ci		switch (adapter->phy.interface_type) {
242262306a36Sopenharmony_ci		case PHY_TYPE_QSFP:
242362306a36Sopenharmony_ci			adapter->phy.cable_type =
242462306a36Sopenharmony_ci				page_data[QSFP_PLUS_CABLE_TYPE_OFFSET];
242562306a36Sopenharmony_ci			break;
242662306a36Sopenharmony_ci		case PHY_TYPE_SFP_PLUS_10GB:
242762306a36Sopenharmony_ci			adapter->phy.cable_type =
242862306a36Sopenharmony_ci				page_data[SFP_PLUS_CABLE_TYPE_OFFSET];
242962306a36Sopenharmony_ci			break;
243062306a36Sopenharmony_ci		default:
243162306a36Sopenharmony_ci			adapter->phy.cable_type = 0;
243262306a36Sopenharmony_ci			break;
243362306a36Sopenharmony_ci		}
243462306a36Sopenharmony_ci	}
243562306a36Sopenharmony_ci	return status;
243662306a36Sopenharmony_ci}
243762306a36Sopenharmony_ci
243862306a36Sopenharmony_ciint be_cmd_query_sfp_info(struct be_adapter *adapter)
243962306a36Sopenharmony_ci{
244062306a36Sopenharmony_ci	u8 page_data[PAGE_DATA_LEN];
244162306a36Sopenharmony_ci	int status;
244262306a36Sopenharmony_ci
244362306a36Sopenharmony_ci	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
244462306a36Sopenharmony_ci						   0, PAGE_DATA_LEN, page_data);
244562306a36Sopenharmony_ci	if (!status) {
244662306a36Sopenharmony_ci		strscpy(adapter->phy.vendor_name, page_data +
244762306a36Sopenharmony_ci			SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
244862306a36Sopenharmony_ci		strscpy(adapter->phy.vendor_pn,
244962306a36Sopenharmony_ci			page_data + SFP_VENDOR_PN_OFFSET,
245062306a36Sopenharmony_ci			SFP_VENDOR_NAME_LEN - 1);
245162306a36Sopenharmony_ci	}
245262306a36Sopenharmony_ci
245362306a36Sopenharmony_ci	return status;
245462306a36Sopenharmony_ci}
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_cistatic int lancer_cmd_delete_object(struct be_adapter *adapter,
245762306a36Sopenharmony_ci				    const char *obj_name)
245862306a36Sopenharmony_ci{
245962306a36Sopenharmony_ci	struct lancer_cmd_req_delete_object *req;
246062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
246162306a36Sopenharmony_ci	int status;
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
246462306a36Sopenharmony_ci
246562306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
246662306a36Sopenharmony_ci	if (!wrb) {
246762306a36Sopenharmony_ci		status = -EBUSY;
246862306a36Sopenharmony_ci		goto err;
246962306a36Sopenharmony_ci	}
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ci	req = embedded_payload(wrb);
247262306a36Sopenharmony_ci
247362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
247462306a36Sopenharmony_ci			       OPCODE_COMMON_DELETE_OBJECT,
247562306a36Sopenharmony_ci			       sizeof(*req), wrb, NULL);
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_ci	strscpy(req->object_name, obj_name, sizeof(req->object_name));
247862306a36Sopenharmony_ci
247962306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
248062306a36Sopenharmony_cierr:
248162306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
248262306a36Sopenharmony_ci	return status;
248362306a36Sopenharmony_ci}
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_ciint lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
248662306a36Sopenharmony_ci			   u32 data_size, u32 data_offset, const char *obj_name,
248762306a36Sopenharmony_ci			   u32 *data_read, u32 *eof, u8 *addn_status)
248862306a36Sopenharmony_ci{
248962306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
249062306a36Sopenharmony_ci	struct lancer_cmd_req_read_object *req;
249162306a36Sopenharmony_ci	struct lancer_cmd_resp_read_object *resp;
249262306a36Sopenharmony_ci	int status;
249362306a36Sopenharmony_ci
249462306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
249562306a36Sopenharmony_ci
249662306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
249762306a36Sopenharmony_ci	if (!wrb) {
249862306a36Sopenharmony_ci		status = -EBUSY;
249962306a36Sopenharmony_ci		goto err_unlock;
250062306a36Sopenharmony_ci	}
250162306a36Sopenharmony_ci
250262306a36Sopenharmony_ci	req = embedded_payload(wrb);
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
250562306a36Sopenharmony_ci			       OPCODE_COMMON_READ_OBJECT,
250662306a36Sopenharmony_ci			       sizeof(struct lancer_cmd_req_read_object), wrb,
250762306a36Sopenharmony_ci			       NULL);
250862306a36Sopenharmony_ci
250962306a36Sopenharmony_ci	req->desired_read_len = cpu_to_le32(data_size);
251062306a36Sopenharmony_ci	req->read_offset = cpu_to_le32(data_offset);
251162306a36Sopenharmony_ci	strcpy(req->object_name, obj_name);
251262306a36Sopenharmony_ci	req->descriptor_count = cpu_to_le32(1);
251362306a36Sopenharmony_ci	req->buf_len = cpu_to_le32(data_size);
251462306a36Sopenharmony_ci	req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF));
251562306a36Sopenharmony_ci	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma));
251662306a36Sopenharmony_ci
251762306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
251862306a36Sopenharmony_ci
251962306a36Sopenharmony_ci	resp = embedded_payload(wrb);
252062306a36Sopenharmony_ci	if (!status) {
252162306a36Sopenharmony_ci		*data_read = le32_to_cpu(resp->actual_read_len);
252262306a36Sopenharmony_ci		*eof = le32_to_cpu(resp->eof);
252362306a36Sopenharmony_ci	} else {
252462306a36Sopenharmony_ci		*addn_status = resp->additional_status;
252562306a36Sopenharmony_ci	}
252662306a36Sopenharmony_ci
252762306a36Sopenharmony_cierr_unlock:
252862306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
252962306a36Sopenharmony_ci	return status;
253062306a36Sopenharmony_ci}
253162306a36Sopenharmony_ci
253262306a36Sopenharmony_cistatic int be_cmd_write_flashrom(struct be_adapter *adapter,
253362306a36Sopenharmony_ci				 struct be_dma_mem *cmd, u32 flash_type,
253462306a36Sopenharmony_ci				 u32 flash_opcode, u32 img_offset, u32 buf_size)
253562306a36Sopenharmony_ci{
253662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
253762306a36Sopenharmony_ci	struct be_cmd_write_flashrom *req;
253862306a36Sopenharmony_ci	int status;
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
254162306a36Sopenharmony_ci	adapter->flash_status = 0;
254262306a36Sopenharmony_ci
254362306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
254462306a36Sopenharmony_ci	if (!wrb) {
254562306a36Sopenharmony_ci		status = -EBUSY;
254662306a36Sopenharmony_ci		goto err_unlock;
254762306a36Sopenharmony_ci	}
254862306a36Sopenharmony_ci	req = cmd->va;
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
255162306a36Sopenharmony_ci			       OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb,
255262306a36Sopenharmony_ci			       cmd);
255362306a36Sopenharmony_ci
255462306a36Sopenharmony_ci	req->params.op_type = cpu_to_le32(flash_type);
255562306a36Sopenharmony_ci	if (flash_type == OPTYPE_OFFSET_SPECIFIED)
255662306a36Sopenharmony_ci		req->params.offset = cpu_to_le32(img_offset);
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	req->params.op_code = cpu_to_le32(flash_opcode);
255962306a36Sopenharmony_ci	req->params.data_buf_size = cpu_to_le32(buf_size);
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	status = be_mcc_notify(adapter);
256262306a36Sopenharmony_ci	if (status)
256362306a36Sopenharmony_ci		goto err_unlock;
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
256862306a36Sopenharmony_ci					 msecs_to_jiffies(40000)))
256962306a36Sopenharmony_ci		status = -ETIMEDOUT;
257062306a36Sopenharmony_ci	else
257162306a36Sopenharmony_ci		status = adapter->flash_status;
257262306a36Sopenharmony_ci
257362306a36Sopenharmony_ci	return status;
257462306a36Sopenharmony_ci
257562306a36Sopenharmony_cierr_unlock:
257662306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
257762306a36Sopenharmony_ci	return status;
257862306a36Sopenharmony_ci}
257962306a36Sopenharmony_ci
258062306a36Sopenharmony_cistatic int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
258162306a36Sopenharmony_ci				u16 img_optype, u32 img_offset, u32 crc_offset)
258262306a36Sopenharmony_ci{
258362306a36Sopenharmony_ci	struct be_cmd_read_flash_crc *req;
258462306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
258562306a36Sopenharmony_ci	int status;
258662306a36Sopenharmony_ci
258762306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
259062306a36Sopenharmony_ci	if (!wrb) {
259162306a36Sopenharmony_ci		status = -EBUSY;
259262306a36Sopenharmony_ci		goto err;
259362306a36Sopenharmony_ci	}
259462306a36Sopenharmony_ci	req = embedded_payload(wrb);
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
259762306a36Sopenharmony_ci			       OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
259862306a36Sopenharmony_ci			       wrb, NULL);
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_ci	req->params.op_type = cpu_to_le32(img_optype);
260162306a36Sopenharmony_ci	if (img_optype == OPTYPE_OFFSET_SPECIFIED)
260262306a36Sopenharmony_ci		req->params.offset = cpu_to_le32(img_offset + crc_offset);
260362306a36Sopenharmony_ci	else
260462306a36Sopenharmony_ci		req->params.offset = cpu_to_le32(crc_offset);
260562306a36Sopenharmony_ci
260662306a36Sopenharmony_ci	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
260762306a36Sopenharmony_ci	req->params.data_buf_size = cpu_to_le32(0x4);
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
261062306a36Sopenharmony_ci	if (!status)
261162306a36Sopenharmony_ci		memcpy(flashed_crc, req->crc, 4);
261262306a36Sopenharmony_ci
261362306a36Sopenharmony_cierr:
261462306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
261562306a36Sopenharmony_ci	return status;
261662306a36Sopenharmony_ci}
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_cistatic char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
261962306a36Sopenharmony_ci
262062306a36Sopenharmony_cistatic bool phy_flashing_required(struct be_adapter *adapter)
262162306a36Sopenharmony_ci{
262262306a36Sopenharmony_ci	return (adapter->phy.phy_type == PHY_TYPE_TN_8022 &&
262362306a36Sopenharmony_ci		adapter->phy.interface_type == PHY_TYPE_BASET_10GB);
262462306a36Sopenharmony_ci}
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_cistatic bool is_comp_in_ufi(struct be_adapter *adapter,
262762306a36Sopenharmony_ci			   struct flash_section_info *fsec, int type)
262862306a36Sopenharmony_ci{
262962306a36Sopenharmony_ci	int i = 0, img_type = 0;
263062306a36Sopenharmony_ci	struct flash_section_info_g2 *fsec_g2 = NULL;
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	if (BE2_chip(adapter))
263362306a36Sopenharmony_ci		fsec_g2 = (struct flash_section_info_g2 *)fsec;
263462306a36Sopenharmony_ci
263562306a36Sopenharmony_ci	for (i = 0; i < MAX_FLASH_COMP; i++) {
263662306a36Sopenharmony_ci		if (fsec_g2)
263762306a36Sopenharmony_ci			img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type);
263862306a36Sopenharmony_ci		else
263962306a36Sopenharmony_ci			img_type = le32_to_cpu(fsec->fsec_entry[i].type);
264062306a36Sopenharmony_ci
264162306a36Sopenharmony_ci		if (img_type == type)
264262306a36Sopenharmony_ci			return true;
264362306a36Sopenharmony_ci	}
264462306a36Sopenharmony_ci	return false;
264562306a36Sopenharmony_ci}
264662306a36Sopenharmony_ci
264762306a36Sopenharmony_cistatic struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
264862306a36Sopenharmony_ci						int header_size,
264962306a36Sopenharmony_ci						const struct firmware *fw)
265062306a36Sopenharmony_ci{
265162306a36Sopenharmony_ci	struct flash_section_info *fsec = NULL;
265262306a36Sopenharmony_ci	const u8 *p = fw->data;
265362306a36Sopenharmony_ci
265462306a36Sopenharmony_ci	p += header_size;
265562306a36Sopenharmony_ci	while (p < (fw->data + fw->size)) {
265662306a36Sopenharmony_ci		fsec = (struct flash_section_info *)p;
265762306a36Sopenharmony_ci		if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie)))
265862306a36Sopenharmony_ci			return fsec;
265962306a36Sopenharmony_ci		p += 32;
266062306a36Sopenharmony_ci	}
266162306a36Sopenharmony_ci	return NULL;
266262306a36Sopenharmony_ci}
266362306a36Sopenharmony_ci
266462306a36Sopenharmony_cistatic int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
266562306a36Sopenharmony_ci			      u32 img_offset, u32 img_size, int hdr_size,
266662306a36Sopenharmony_ci			      u16 img_optype, bool *crc_match)
266762306a36Sopenharmony_ci{
266862306a36Sopenharmony_ci	u32 crc_offset;
266962306a36Sopenharmony_ci	int status;
267062306a36Sopenharmony_ci	u8 crc[4];
267162306a36Sopenharmony_ci
267262306a36Sopenharmony_ci	status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset,
267362306a36Sopenharmony_ci				      img_size - 4);
267462306a36Sopenharmony_ci	if (status)
267562306a36Sopenharmony_ci		return status;
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_ci	crc_offset = hdr_size + img_offset + img_size - 4;
267862306a36Sopenharmony_ci
267962306a36Sopenharmony_ci	/* Skip flashing, if crc of flashed region matches */
268062306a36Sopenharmony_ci	if (!memcmp(crc, p + crc_offset, 4))
268162306a36Sopenharmony_ci		*crc_match = true;
268262306a36Sopenharmony_ci	else
268362306a36Sopenharmony_ci		*crc_match = false;
268462306a36Sopenharmony_ci
268562306a36Sopenharmony_ci	return status;
268662306a36Sopenharmony_ci}
268762306a36Sopenharmony_ci
268862306a36Sopenharmony_cistatic int be_flash(struct be_adapter *adapter, const u8 *img,
268962306a36Sopenharmony_ci		    struct be_dma_mem *flash_cmd, int optype, int img_size,
269062306a36Sopenharmony_ci		    u32 img_offset)
269162306a36Sopenharmony_ci{
269262306a36Sopenharmony_ci	u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0;
269362306a36Sopenharmony_ci	struct be_cmd_write_flashrom *req = flash_cmd->va;
269462306a36Sopenharmony_ci	int status;
269562306a36Sopenharmony_ci
269662306a36Sopenharmony_ci	while (total_bytes) {
269762306a36Sopenharmony_ci		num_bytes = min_t(u32, 32 * 1024, total_bytes);
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci		total_bytes -= num_bytes;
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci		if (!total_bytes) {
270262306a36Sopenharmony_ci			if (optype == OPTYPE_PHY_FW)
270362306a36Sopenharmony_ci				flash_op = FLASHROM_OPER_PHY_FLASH;
270462306a36Sopenharmony_ci			else
270562306a36Sopenharmony_ci				flash_op = FLASHROM_OPER_FLASH;
270662306a36Sopenharmony_ci		} else {
270762306a36Sopenharmony_ci			if (optype == OPTYPE_PHY_FW)
270862306a36Sopenharmony_ci				flash_op = FLASHROM_OPER_PHY_SAVE;
270962306a36Sopenharmony_ci			else
271062306a36Sopenharmony_ci				flash_op = FLASHROM_OPER_SAVE;
271162306a36Sopenharmony_ci		}
271262306a36Sopenharmony_ci
271362306a36Sopenharmony_ci		memcpy(req->data_buf, img, num_bytes);
271462306a36Sopenharmony_ci		img += num_bytes;
271562306a36Sopenharmony_ci		status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
271662306a36Sopenharmony_ci					       flash_op, img_offset +
271762306a36Sopenharmony_ci					       bytes_sent, num_bytes);
271862306a36Sopenharmony_ci		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
271962306a36Sopenharmony_ci		    optype == OPTYPE_PHY_FW)
272062306a36Sopenharmony_ci			break;
272162306a36Sopenharmony_ci		else if (status)
272262306a36Sopenharmony_ci			return status;
272362306a36Sopenharmony_ci
272462306a36Sopenharmony_ci		bytes_sent += num_bytes;
272562306a36Sopenharmony_ci	}
272662306a36Sopenharmony_ci	return 0;
272762306a36Sopenharmony_ci}
272862306a36Sopenharmony_ci
272962306a36Sopenharmony_ci#define NCSI_UPDATE_LOG	"NCSI section update is not supported in FW ver %s\n"
273062306a36Sopenharmony_cistatic bool be_fw_ncsi_supported(char *ver)
273162306a36Sopenharmony_ci{
273262306a36Sopenharmony_ci	int v1[4] = {3, 102, 148, 0}; /* Min ver that supports NCSI FW */
273362306a36Sopenharmony_ci	int v2[4];
273462306a36Sopenharmony_ci	int i;
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci	if (sscanf(ver, "%d.%d.%d.%d", &v2[0], &v2[1], &v2[2], &v2[3]) != 4)
273762306a36Sopenharmony_ci		return false;
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
274062306a36Sopenharmony_ci		if (v1[i] < v2[i])
274162306a36Sopenharmony_ci			return true;
274262306a36Sopenharmony_ci		else if (v1[i] > v2[i])
274362306a36Sopenharmony_ci			return false;
274462306a36Sopenharmony_ci	}
274562306a36Sopenharmony_ci
274662306a36Sopenharmony_ci	return true;
274762306a36Sopenharmony_ci}
274862306a36Sopenharmony_ci
274962306a36Sopenharmony_ci/* For BE2, BE3 and BE3-R */
275062306a36Sopenharmony_cistatic int be_flash_BEx(struct be_adapter *adapter,
275162306a36Sopenharmony_ci			const struct firmware *fw,
275262306a36Sopenharmony_ci			struct be_dma_mem *flash_cmd, int num_of_images)
275362306a36Sopenharmony_ci{
275462306a36Sopenharmony_ci	int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
275562306a36Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
275662306a36Sopenharmony_ci	struct flash_section_info *fsec = NULL;
275762306a36Sopenharmony_ci	int status, i, filehdr_size, num_comp;
275862306a36Sopenharmony_ci	const struct flash_comp *pflashcomp;
275962306a36Sopenharmony_ci	bool crc_match;
276062306a36Sopenharmony_ci	const u8 *p;
276162306a36Sopenharmony_ci
276262306a36Sopenharmony_ci	static const struct flash_comp gen3_flash_types[] = {
276362306a36Sopenharmony_ci		{ BE3_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
276462306a36Sopenharmony_ci			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
276562306a36Sopenharmony_ci		{ BE3_REDBOOT_START, OPTYPE_REDBOOT,
276662306a36Sopenharmony_ci			BE3_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
276762306a36Sopenharmony_ci		{ BE3_ISCSI_BIOS_START, OPTYPE_BIOS,
276862306a36Sopenharmony_ci			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
276962306a36Sopenharmony_ci		{ BE3_PXE_BIOS_START, OPTYPE_PXE_BIOS,
277062306a36Sopenharmony_ci			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
277162306a36Sopenharmony_ci		{ BE3_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
277262306a36Sopenharmony_ci			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
277362306a36Sopenharmony_ci		{ BE3_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
277462306a36Sopenharmony_ci			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
277562306a36Sopenharmony_ci		{ BE3_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
277662306a36Sopenharmony_ci			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
277762306a36Sopenharmony_ci		{ BE3_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
277862306a36Sopenharmony_ci			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE},
277962306a36Sopenharmony_ci		{ BE3_NCSI_START, OPTYPE_NCSI_FW,
278062306a36Sopenharmony_ci			BE3_NCSI_COMP_MAX_SIZE, IMAGE_NCSI},
278162306a36Sopenharmony_ci		{ BE3_PHY_FW_START, OPTYPE_PHY_FW,
278262306a36Sopenharmony_ci			BE3_PHY_FW_COMP_MAX_SIZE, IMAGE_FIRMWARE_PHY}
278362306a36Sopenharmony_ci	};
278462306a36Sopenharmony_ci
278562306a36Sopenharmony_ci	static const struct flash_comp gen2_flash_types[] = {
278662306a36Sopenharmony_ci		{ BE2_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
278762306a36Sopenharmony_ci			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
278862306a36Sopenharmony_ci		{ BE2_REDBOOT_START, OPTYPE_REDBOOT,
278962306a36Sopenharmony_ci			BE2_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
279062306a36Sopenharmony_ci		{ BE2_ISCSI_BIOS_START, OPTYPE_BIOS,
279162306a36Sopenharmony_ci			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
279262306a36Sopenharmony_ci		{ BE2_PXE_BIOS_START, OPTYPE_PXE_BIOS,
279362306a36Sopenharmony_ci			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
279462306a36Sopenharmony_ci		{ BE2_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
279562306a36Sopenharmony_ci			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
279662306a36Sopenharmony_ci		{ BE2_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
279762306a36Sopenharmony_ci			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
279862306a36Sopenharmony_ci		{ BE2_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
279962306a36Sopenharmony_ci			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
280062306a36Sopenharmony_ci		{ BE2_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
280162306a36Sopenharmony_ci			 BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE}
280262306a36Sopenharmony_ci	};
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_ci	if (BE3_chip(adapter)) {
280562306a36Sopenharmony_ci		pflashcomp = gen3_flash_types;
280662306a36Sopenharmony_ci		filehdr_size = sizeof(struct flash_file_hdr_g3);
280762306a36Sopenharmony_ci		num_comp = ARRAY_SIZE(gen3_flash_types);
280862306a36Sopenharmony_ci	} else {
280962306a36Sopenharmony_ci		pflashcomp = gen2_flash_types;
281062306a36Sopenharmony_ci		filehdr_size = sizeof(struct flash_file_hdr_g2);
281162306a36Sopenharmony_ci		num_comp = ARRAY_SIZE(gen2_flash_types);
281262306a36Sopenharmony_ci		img_hdrs_size = 0;
281362306a36Sopenharmony_ci	}
281462306a36Sopenharmony_ci
281562306a36Sopenharmony_ci	/* Get flash section info*/
281662306a36Sopenharmony_ci	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
281762306a36Sopenharmony_ci	if (!fsec) {
281862306a36Sopenharmony_ci		dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
281962306a36Sopenharmony_ci		return -1;
282062306a36Sopenharmony_ci	}
282162306a36Sopenharmony_ci	for (i = 0; i < num_comp; i++) {
282262306a36Sopenharmony_ci		if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type))
282362306a36Sopenharmony_ci			continue;
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ci		if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) &&
282662306a36Sopenharmony_ci		    !be_fw_ncsi_supported(adapter->fw_ver)) {
282762306a36Sopenharmony_ci			dev_info(dev, NCSI_UPDATE_LOG, adapter->fw_ver);
282862306a36Sopenharmony_ci			continue;
282962306a36Sopenharmony_ci		}
283062306a36Sopenharmony_ci
283162306a36Sopenharmony_ci		if (pflashcomp[i].optype == OPTYPE_PHY_FW  &&
283262306a36Sopenharmony_ci		    !phy_flashing_required(adapter))
283362306a36Sopenharmony_ci			continue;
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_ci		if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
283662306a36Sopenharmony_ci			status = be_check_flash_crc(adapter, fw->data,
283762306a36Sopenharmony_ci						    pflashcomp[i].offset,
283862306a36Sopenharmony_ci						    pflashcomp[i].size,
283962306a36Sopenharmony_ci						    filehdr_size +
284062306a36Sopenharmony_ci						    img_hdrs_size,
284162306a36Sopenharmony_ci						    OPTYPE_REDBOOT, &crc_match);
284262306a36Sopenharmony_ci			if (status) {
284362306a36Sopenharmony_ci				dev_err(dev,
284462306a36Sopenharmony_ci					"Could not get CRC for 0x%x region\n",
284562306a36Sopenharmony_ci					pflashcomp[i].optype);
284662306a36Sopenharmony_ci				continue;
284762306a36Sopenharmony_ci			}
284862306a36Sopenharmony_ci
284962306a36Sopenharmony_ci			if (crc_match)
285062306a36Sopenharmony_ci				continue;
285162306a36Sopenharmony_ci		}
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci		p = fw->data + filehdr_size + pflashcomp[i].offset +
285462306a36Sopenharmony_ci			img_hdrs_size;
285562306a36Sopenharmony_ci		if (p + pflashcomp[i].size > fw->data + fw->size)
285662306a36Sopenharmony_ci			return -1;
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_ci		status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
285962306a36Sopenharmony_ci				  pflashcomp[i].size, 0);
286062306a36Sopenharmony_ci		if (status) {
286162306a36Sopenharmony_ci			dev_err(dev, "Flashing section type 0x%x failed\n",
286262306a36Sopenharmony_ci				pflashcomp[i].img_type);
286362306a36Sopenharmony_ci			return status;
286462306a36Sopenharmony_ci		}
286562306a36Sopenharmony_ci	}
286662306a36Sopenharmony_ci	return 0;
286762306a36Sopenharmony_ci}
286862306a36Sopenharmony_ci
286962306a36Sopenharmony_cistatic u16 be_get_img_optype(struct flash_section_entry fsec_entry)
287062306a36Sopenharmony_ci{
287162306a36Sopenharmony_ci	u32 img_type = le32_to_cpu(fsec_entry.type);
287262306a36Sopenharmony_ci	u16 img_optype = le16_to_cpu(fsec_entry.optype);
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_ci	if (img_optype != 0xFFFF)
287562306a36Sopenharmony_ci		return img_optype;
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_ci	switch (img_type) {
287862306a36Sopenharmony_ci	case IMAGE_FIRMWARE_ISCSI:
287962306a36Sopenharmony_ci		img_optype = OPTYPE_ISCSI_ACTIVE;
288062306a36Sopenharmony_ci		break;
288162306a36Sopenharmony_ci	case IMAGE_BOOT_CODE:
288262306a36Sopenharmony_ci		img_optype = OPTYPE_REDBOOT;
288362306a36Sopenharmony_ci		break;
288462306a36Sopenharmony_ci	case IMAGE_OPTION_ROM_ISCSI:
288562306a36Sopenharmony_ci		img_optype = OPTYPE_BIOS;
288662306a36Sopenharmony_ci		break;
288762306a36Sopenharmony_ci	case IMAGE_OPTION_ROM_PXE:
288862306a36Sopenharmony_ci		img_optype = OPTYPE_PXE_BIOS;
288962306a36Sopenharmony_ci		break;
289062306a36Sopenharmony_ci	case IMAGE_OPTION_ROM_FCOE:
289162306a36Sopenharmony_ci		img_optype = OPTYPE_FCOE_BIOS;
289262306a36Sopenharmony_ci		break;
289362306a36Sopenharmony_ci	case IMAGE_FIRMWARE_BACKUP_ISCSI:
289462306a36Sopenharmony_ci		img_optype = OPTYPE_ISCSI_BACKUP;
289562306a36Sopenharmony_ci		break;
289662306a36Sopenharmony_ci	case IMAGE_NCSI:
289762306a36Sopenharmony_ci		img_optype = OPTYPE_NCSI_FW;
289862306a36Sopenharmony_ci		break;
289962306a36Sopenharmony_ci	case IMAGE_FLASHISM_JUMPVECTOR:
290062306a36Sopenharmony_ci		img_optype = OPTYPE_FLASHISM_JUMPVECTOR;
290162306a36Sopenharmony_ci		break;
290262306a36Sopenharmony_ci	case IMAGE_FIRMWARE_PHY:
290362306a36Sopenharmony_ci		img_optype = OPTYPE_SH_PHY_FW;
290462306a36Sopenharmony_ci		break;
290562306a36Sopenharmony_ci	case IMAGE_REDBOOT_DIR:
290662306a36Sopenharmony_ci		img_optype = OPTYPE_REDBOOT_DIR;
290762306a36Sopenharmony_ci		break;
290862306a36Sopenharmony_ci	case IMAGE_REDBOOT_CONFIG:
290962306a36Sopenharmony_ci		img_optype = OPTYPE_REDBOOT_CONFIG;
291062306a36Sopenharmony_ci		break;
291162306a36Sopenharmony_ci	case IMAGE_UFI_DIR:
291262306a36Sopenharmony_ci		img_optype = OPTYPE_UFI_DIR;
291362306a36Sopenharmony_ci		break;
291462306a36Sopenharmony_ci	default:
291562306a36Sopenharmony_ci		break;
291662306a36Sopenharmony_ci	}
291762306a36Sopenharmony_ci
291862306a36Sopenharmony_ci	return img_optype;
291962306a36Sopenharmony_ci}
292062306a36Sopenharmony_ci
292162306a36Sopenharmony_cistatic int be_flash_skyhawk(struct be_adapter *adapter,
292262306a36Sopenharmony_ci			    const struct firmware *fw,
292362306a36Sopenharmony_ci			    struct be_dma_mem *flash_cmd, int num_of_images)
292462306a36Sopenharmony_ci{
292562306a36Sopenharmony_ci	int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
292662306a36Sopenharmony_ci	bool crc_match, old_fw_img, flash_offset_support = true;
292762306a36Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
292862306a36Sopenharmony_ci	struct flash_section_info *fsec = NULL;
292962306a36Sopenharmony_ci	u32 img_offset, img_size, img_type;
293062306a36Sopenharmony_ci	u16 img_optype, flash_optype;
293162306a36Sopenharmony_ci	int status, i, filehdr_size;
293262306a36Sopenharmony_ci	const u8 *p;
293362306a36Sopenharmony_ci
293462306a36Sopenharmony_ci	filehdr_size = sizeof(struct flash_file_hdr_g3);
293562306a36Sopenharmony_ci	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
293662306a36Sopenharmony_ci	if (!fsec) {
293762306a36Sopenharmony_ci		dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
293862306a36Sopenharmony_ci		return -EINVAL;
293962306a36Sopenharmony_ci	}
294062306a36Sopenharmony_ci
294162306a36Sopenharmony_ciretry_flash:
294262306a36Sopenharmony_ci	for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
294362306a36Sopenharmony_ci		img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
294462306a36Sopenharmony_ci		img_size   = le32_to_cpu(fsec->fsec_entry[i].pad_size);
294562306a36Sopenharmony_ci		img_type   = le32_to_cpu(fsec->fsec_entry[i].type);
294662306a36Sopenharmony_ci		img_optype = be_get_img_optype(fsec->fsec_entry[i]);
294762306a36Sopenharmony_ci		old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF;
294862306a36Sopenharmony_ci
294962306a36Sopenharmony_ci		if (img_optype == 0xFFFF)
295062306a36Sopenharmony_ci			continue;
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci		if (flash_offset_support)
295362306a36Sopenharmony_ci			flash_optype = OPTYPE_OFFSET_SPECIFIED;
295462306a36Sopenharmony_ci		else
295562306a36Sopenharmony_ci			flash_optype = img_optype;
295662306a36Sopenharmony_ci
295762306a36Sopenharmony_ci		/* Don't bother verifying CRC if an old FW image is being
295862306a36Sopenharmony_ci		 * flashed
295962306a36Sopenharmony_ci		 */
296062306a36Sopenharmony_ci		if (old_fw_img)
296162306a36Sopenharmony_ci			goto flash;
296262306a36Sopenharmony_ci
296362306a36Sopenharmony_ci		status = be_check_flash_crc(adapter, fw->data, img_offset,
296462306a36Sopenharmony_ci					    img_size, filehdr_size +
296562306a36Sopenharmony_ci					    img_hdrs_size, flash_optype,
296662306a36Sopenharmony_ci					    &crc_match);
296762306a36Sopenharmony_ci		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
296862306a36Sopenharmony_ci		    base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
296962306a36Sopenharmony_ci			/* The current FW image on the card does not support
297062306a36Sopenharmony_ci			 * OFFSET based flashing. Retry using older mechanism
297162306a36Sopenharmony_ci			 * of OPTYPE based flashing
297262306a36Sopenharmony_ci			 */
297362306a36Sopenharmony_ci			if (flash_optype == OPTYPE_OFFSET_SPECIFIED) {
297462306a36Sopenharmony_ci				flash_offset_support = false;
297562306a36Sopenharmony_ci				goto retry_flash;
297662306a36Sopenharmony_ci			}
297762306a36Sopenharmony_ci
297862306a36Sopenharmony_ci			/* The current FW image on the card does not recognize
297962306a36Sopenharmony_ci			 * the new FLASH op_type. The FW download is partially
298062306a36Sopenharmony_ci			 * complete. Reboot the server now to enable FW image
298162306a36Sopenharmony_ci			 * to recognize the new FLASH op_type. To complete the
298262306a36Sopenharmony_ci			 * remaining process, download the same FW again after
298362306a36Sopenharmony_ci			 * the reboot.
298462306a36Sopenharmony_ci			 */
298562306a36Sopenharmony_ci			dev_err(dev, "Flash incomplete. Reset the server\n");
298662306a36Sopenharmony_ci			dev_err(dev, "Download FW image again after reset\n");
298762306a36Sopenharmony_ci			return -EAGAIN;
298862306a36Sopenharmony_ci		} else if (status) {
298962306a36Sopenharmony_ci			dev_err(dev, "Could not get CRC for 0x%x region\n",
299062306a36Sopenharmony_ci				img_optype);
299162306a36Sopenharmony_ci			return -EFAULT;
299262306a36Sopenharmony_ci		}
299362306a36Sopenharmony_ci
299462306a36Sopenharmony_ci		if (crc_match)
299562306a36Sopenharmony_ci			continue;
299662306a36Sopenharmony_ci
299762306a36Sopenharmony_ciflash:
299862306a36Sopenharmony_ci		p = fw->data + filehdr_size + img_offset + img_hdrs_size;
299962306a36Sopenharmony_ci		if (p + img_size > fw->data + fw->size)
300062306a36Sopenharmony_ci			return -1;
300162306a36Sopenharmony_ci
300262306a36Sopenharmony_ci		status = be_flash(adapter, p, flash_cmd, flash_optype, img_size,
300362306a36Sopenharmony_ci				  img_offset);
300462306a36Sopenharmony_ci
300562306a36Sopenharmony_ci		/* The current FW image on the card does not support OFFSET
300662306a36Sopenharmony_ci		 * based flashing. Retry using older mechanism of OPTYPE based
300762306a36Sopenharmony_ci		 * flashing
300862306a36Sopenharmony_ci		 */
300962306a36Sopenharmony_ci		if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD &&
301062306a36Sopenharmony_ci		    flash_optype == OPTYPE_OFFSET_SPECIFIED) {
301162306a36Sopenharmony_ci			flash_offset_support = false;
301262306a36Sopenharmony_ci			goto retry_flash;
301362306a36Sopenharmony_ci		}
301462306a36Sopenharmony_ci
301562306a36Sopenharmony_ci		/* For old FW images ignore ILLEGAL_FIELD error or errors on
301662306a36Sopenharmony_ci		 * UFI_DIR region
301762306a36Sopenharmony_ci		 */
301862306a36Sopenharmony_ci		if (old_fw_img &&
301962306a36Sopenharmony_ci		    (base_status(status) == MCC_STATUS_ILLEGAL_FIELD ||
302062306a36Sopenharmony_ci		     (img_optype == OPTYPE_UFI_DIR &&
302162306a36Sopenharmony_ci		      base_status(status) == MCC_STATUS_FAILED))) {
302262306a36Sopenharmony_ci			continue;
302362306a36Sopenharmony_ci		} else if (status) {
302462306a36Sopenharmony_ci			dev_err(dev, "Flashing section type 0x%x failed\n",
302562306a36Sopenharmony_ci				img_type);
302662306a36Sopenharmony_ci
302762306a36Sopenharmony_ci			switch (addl_status(status)) {
302862306a36Sopenharmony_ci			case MCC_ADDL_STATUS_MISSING_SIGNATURE:
302962306a36Sopenharmony_ci				dev_err(dev,
303062306a36Sopenharmony_ci					"Digital signature missing in FW\n");
303162306a36Sopenharmony_ci				return -EINVAL;
303262306a36Sopenharmony_ci			case MCC_ADDL_STATUS_INVALID_SIGNATURE:
303362306a36Sopenharmony_ci				dev_err(dev,
303462306a36Sopenharmony_ci					"Invalid digital signature in FW\n");
303562306a36Sopenharmony_ci				return -EINVAL;
303662306a36Sopenharmony_ci			default:
303762306a36Sopenharmony_ci				return -EFAULT;
303862306a36Sopenharmony_ci			}
303962306a36Sopenharmony_ci		}
304062306a36Sopenharmony_ci	}
304162306a36Sopenharmony_ci	return 0;
304262306a36Sopenharmony_ci}
304362306a36Sopenharmony_ci
304462306a36Sopenharmony_ciint lancer_fw_download(struct be_adapter *adapter,
304562306a36Sopenharmony_ci		       const struct firmware *fw)
304662306a36Sopenharmony_ci{
304762306a36Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
304862306a36Sopenharmony_ci	struct be_dma_mem flash_cmd;
304962306a36Sopenharmony_ci	const u8 *data_ptr = NULL;
305062306a36Sopenharmony_ci	u8 *dest_image_ptr = NULL;
305162306a36Sopenharmony_ci	size_t image_size = 0;
305262306a36Sopenharmony_ci	u32 chunk_size = 0;
305362306a36Sopenharmony_ci	u32 data_written = 0;
305462306a36Sopenharmony_ci	u32 offset = 0;
305562306a36Sopenharmony_ci	int status = 0;
305662306a36Sopenharmony_ci	u8 add_status = 0;
305762306a36Sopenharmony_ci	u8 change_status;
305862306a36Sopenharmony_ci
305962306a36Sopenharmony_ci	if (!IS_ALIGNED(fw->size, sizeof(u32))) {
306062306a36Sopenharmony_ci		dev_err(dev, "FW image size should be multiple of 4\n");
306162306a36Sopenharmony_ci		return -EINVAL;
306262306a36Sopenharmony_ci	}
306362306a36Sopenharmony_ci
306462306a36Sopenharmony_ci	flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
306562306a36Sopenharmony_ci				+ LANCER_FW_DOWNLOAD_CHUNK;
306662306a36Sopenharmony_ci	flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
306762306a36Sopenharmony_ci					  GFP_KERNEL);
306862306a36Sopenharmony_ci	if (!flash_cmd.va)
306962306a36Sopenharmony_ci		return -ENOMEM;
307062306a36Sopenharmony_ci
307162306a36Sopenharmony_ci	dest_image_ptr = flash_cmd.va +
307262306a36Sopenharmony_ci				sizeof(struct lancer_cmd_req_write_object);
307362306a36Sopenharmony_ci	image_size = fw->size;
307462306a36Sopenharmony_ci	data_ptr = fw->data;
307562306a36Sopenharmony_ci
307662306a36Sopenharmony_ci	while (image_size) {
307762306a36Sopenharmony_ci		chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK);
307862306a36Sopenharmony_ci
307962306a36Sopenharmony_ci		/* Copy the image chunk content. */
308062306a36Sopenharmony_ci		memcpy(dest_image_ptr, data_ptr, chunk_size);
308162306a36Sopenharmony_ci
308262306a36Sopenharmony_ci		status = lancer_cmd_write_object(adapter, &flash_cmd,
308362306a36Sopenharmony_ci						 chunk_size, offset,
308462306a36Sopenharmony_ci						 LANCER_FW_DOWNLOAD_LOCATION,
308562306a36Sopenharmony_ci						 &data_written, &change_status,
308662306a36Sopenharmony_ci						 &add_status);
308762306a36Sopenharmony_ci		if (status)
308862306a36Sopenharmony_ci			break;
308962306a36Sopenharmony_ci
309062306a36Sopenharmony_ci		offset += data_written;
309162306a36Sopenharmony_ci		data_ptr += data_written;
309262306a36Sopenharmony_ci		image_size -= data_written;
309362306a36Sopenharmony_ci	}
309462306a36Sopenharmony_ci
309562306a36Sopenharmony_ci	if (!status) {
309662306a36Sopenharmony_ci		/* Commit the FW written */
309762306a36Sopenharmony_ci		status = lancer_cmd_write_object(adapter, &flash_cmd,
309862306a36Sopenharmony_ci						 0, offset,
309962306a36Sopenharmony_ci						 LANCER_FW_DOWNLOAD_LOCATION,
310062306a36Sopenharmony_ci						 &data_written, &change_status,
310162306a36Sopenharmony_ci						 &add_status);
310262306a36Sopenharmony_ci	}
310362306a36Sopenharmony_ci
310462306a36Sopenharmony_ci	dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
310562306a36Sopenharmony_ci	if (status) {
310662306a36Sopenharmony_ci		dev_err(dev, "Firmware load error\n");
310762306a36Sopenharmony_ci		return be_cmd_status(status);
310862306a36Sopenharmony_ci	}
310962306a36Sopenharmony_ci
311062306a36Sopenharmony_ci	dev_info(dev, "Firmware flashed successfully\n");
311162306a36Sopenharmony_ci
311262306a36Sopenharmony_ci	if (change_status == LANCER_FW_RESET_NEEDED) {
311362306a36Sopenharmony_ci		dev_info(dev, "Resetting adapter to activate new FW\n");
311462306a36Sopenharmony_ci		status = lancer_physdev_ctrl(adapter,
311562306a36Sopenharmony_ci					     PHYSDEV_CONTROL_FW_RESET_MASK);
311662306a36Sopenharmony_ci		if (status) {
311762306a36Sopenharmony_ci			dev_err(dev, "Adapter busy, could not reset FW\n");
311862306a36Sopenharmony_ci			dev_err(dev, "Reboot server to activate new FW\n");
311962306a36Sopenharmony_ci		}
312062306a36Sopenharmony_ci	} else if (change_status != LANCER_NO_RESET_NEEDED) {
312162306a36Sopenharmony_ci		dev_info(dev, "Reboot server to activate new FW\n");
312262306a36Sopenharmony_ci	}
312362306a36Sopenharmony_ci
312462306a36Sopenharmony_ci	return 0;
312562306a36Sopenharmony_ci}
312662306a36Sopenharmony_ci
312762306a36Sopenharmony_ci/* Check if the flash image file is compatible with the adapter that
312862306a36Sopenharmony_ci * is being flashed.
312962306a36Sopenharmony_ci */
313062306a36Sopenharmony_cistatic bool be_check_ufi_compatibility(struct be_adapter *adapter,
313162306a36Sopenharmony_ci				       struct flash_file_hdr_g3 *fhdr)
313262306a36Sopenharmony_ci{
313362306a36Sopenharmony_ci	if (!fhdr) {
313462306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Invalid FW UFI file");
313562306a36Sopenharmony_ci		return false;
313662306a36Sopenharmony_ci	}
313762306a36Sopenharmony_ci
313862306a36Sopenharmony_ci	/* First letter of the build version is used to identify
313962306a36Sopenharmony_ci	 * which chip this image file is meant for.
314062306a36Sopenharmony_ci	 */
314162306a36Sopenharmony_ci	switch (fhdr->build[0]) {
314262306a36Sopenharmony_ci	case BLD_STR_UFI_TYPE_SH:
314362306a36Sopenharmony_ci		if (!skyhawk_chip(adapter))
314462306a36Sopenharmony_ci			return false;
314562306a36Sopenharmony_ci		break;
314662306a36Sopenharmony_ci	case BLD_STR_UFI_TYPE_BE3:
314762306a36Sopenharmony_ci		if (!BE3_chip(adapter))
314862306a36Sopenharmony_ci			return false;
314962306a36Sopenharmony_ci		break;
315062306a36Sopenharmony_ci	case BLD_STR_UFI_TYPE_BE2:
315162306a36Sopenharmony_ci		if (!BE2_chip(adapter))
315262306a36Sopenharmony_ci			return false;
315362306a36Sopenharmony_ci		break;
315462306a36Sopenharmony_ci	default:
315562306a36Sopenharmony_ci		return false;
315662306a36Sopenharmony_ci	}
315762306a36Sopenharmony_ci
315862306a36Sopenharmony_ci	/* In BE3 FW images the "asic_type_rev" field doesn't track the
315962306a36Sopenharmony_ci	 * asic_rev of the chips it is compatible with.
316062306a36Sopenharmony_ci	 * When asic_type_rev is 0 the image is compatible only with
316162306a36Sopenharmony_ci	 * pre-BE3-R chips (asic_rev < 0x10)
316262306a36Sopenharmony_ci	 */
316362306a36Sopenharmony_ci	if (BEx_chip(adapter) && fhdr->asic_type_rev == 0)
316462306a36Sopenharmony_ci		return adapter->asic_rev < 0x10;
316562306a36Sopenharmony_ci	else
316662306a36Sopenharmony_ci		return (fhdr->asic_type_rev >= adapter->asic_rev);
316762306a36Sopenharmony_ci}
316862306a36Sopenharmony_ci
316962306a36Sopenharmony_ciint be_fw_download(struct be_adapter *adapter, const struct firmware *fw)
317062306a36Sopenharmony_ci{
317162306a36Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
317262306a36Sopenharmony_ci	struct flash_file_hdr_g3 *fhdr3;
317362306a36Sopenharmony_ci	struct image_hdr *img_hdr_ptr;
317462306a36Sopenharmony_ci	int status = 0, i, num_imgs;
317562306a36Sopenharmony_ci	struct be_dma_mem flash_cmd;
317662306a36Sopenharmony_ci
317762306a36Sopenharmony_ci	fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
317862306a36Sopenharmony_ci	if (!be_check_ufi_compatibility(adapter, fhdr3)) {
317962306a36Sopenharmony_ci		dev_err(dev, "Flash image is not compatible with adapter\n");
318062306a36Sopenharmony_ci		return -EINVAL;
318162306a36Sopenharmony_ci	}
318262306a36Sopenharmony_ci
318362306a36Sopenharmony_ci	flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
318462306a36Sopenharmony_ci	flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
318562306a36Sopenharmony_ci					  GFP_KERNEL);
318662306a36Sopenharmony_ci	if (!flash_cmd.va)
318762306a36Sopenharmony_ci		return -ENOMEM;
318862306a36Sopenharmony_ci
318962306a36Sopenharmony_ci	num_imgs = le32_to_cpu(fhdr3->num_imgs);
319062306a36Sopenharmony_ci	for (i = 0; i < num_imgs; i++) {
319162306a36Sopenharmony_ci		img_hdr_ptr = (struct image_hdr *)(fw->data +
319262306a36Sopenharmony_ci				(sizeof(struct flash_file_hdr_g3) +
319362306a36Sopenharmony_ci				 i * sizeof(struct image_hdr)));
319462306a36Sopenharmony_ci		if (!BE2_chip(adapter) &&
319562306a36Sopenharmony_ci		    le32_to_cpu(img_hdr_ptr->imageid) != 1)
319662306a36Sopenharmony_ci			continue;
319762306a36Sopenharmony_ci
319862306a36Sopenharmony_ci		if (skyhawk_chip(adapter))
319962306a36Sopenharmony_ci			status = be_flash_skyhawk(adapter, fw, &flash_cmd,
320062306a36Sopenharmony_ci						  num_imgs);
320162306a36Sopenharmony_ci		else
320262306a36Sopenharmony_ci			status = be_flash_BEx(adapter, fw, &flash_cmd,
320362306a36Sopenharmony_ci					      num_imgs);
320462306a36Sopenharmony_ci	}
320562306a36Sopenharmony_ci
320662306a36Sopenharmony_ci	dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
320762306a36Sopenharmony_ci	if (!status)
320862306a36Sopenharmony_ci		dev_info(dev, "Firmware flashed successfully\n");
320962306a36Sopenharmony_ci
321062306a36Sopenharmony_ci	return status;
321162306a36Sopenharmony_ci}
321262306a36Sopenharmony_ci
321362306a36Sopenharmony_ciint be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
321462306a36Sopenharmony_ci			    struct be_dma_mem *nonemb_cmd)
321562306a36Sopenharmony_ci{
321662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
321762306a36Sopenharmony_ci	struct be_cmd_req_acpi_wol_magic_config *req;
321862306a36Sopenharmony_ci	int status;
321962306a36Sopenharmony_ci
322062306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
322162306a36Sopenharmony_ci
322262306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
322362306a36Sopenharmony_ci	if (!wrb) {
322462306a36Sopenharmony_ci		status = -EBUSY;
322562306a36Sopenharmony_ci		goto err;
322662306a36Sopenharmony_ci	}
322762306a36Sopenharmony_ci	req = nonemb_cmd->va;
322862306a36Sopenharmony_ci
322962306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
323062306a36Sopenharmony_ci			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req),
323162306a36Sopenharmony_ci			       wrb, nonemb_cmd);
323262306a36Sopenharmony_ci	memcpy(req->magic_mac, mac, ETH_ALEN);
323362306a36Sopenharmony_ci
323462306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
323562306a36Sopenharmony_ci
323662306a36Sopenharmony_cierr:
323762306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
323862306a36Sopenharmony_ci	return status;
323962306a36Sopenharmony_ci}
324062306a36Sopenharmony_ci
324162306a36Sopenharmony_ciint be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
324262306a36Sopenharmony_ci			u8 loopback_type, u8 enable)
324362306a36Sopenharmony_ci{
324462306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
324562306a36Sopenharmony_ci	struct be_cmd_req_set_lmode *req;
324662306a36Sopenharmony_ci	int status;
324762306a36Sopenharmony_ci
324862306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
324962306a36Sopenharmony_ci			    CMD_SUBSYSTEM_LOWLEVEL))
325062306a36Sopenharmony_ci		return -EPERM;
325162306a36Sopenharmony_ci
325262306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
325562306a36Sopenharmony_ci	if (!wrb) {
325662306a36Sopenharmony_ci		status = -EBUSY;
325762306a36Sopenharmony_ci		goto err_unlock;
325862306a36Sopenharmony_ci	}
325962306a36Sopenharmony_ci
326062306a36Sopenharmony_ci	req = embedded_payload(wrb);
326162306a36Sopenharmony_ci
326262306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
326362306a36Sopenharmony_ci			       OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req),
326462306a36Sopenharmony_ci			       wrb, NULL);
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci	req->src_port = port_num;
326762306a36Sopenharmony_ci	req->dest_port = port_num;
326862306a36Sopenharmony_ci	req->loopback_type = loopback_type;
326962306a36Sopenharmony_ci	req->loopback_state = enable;
327062306a36Sopenharmony_ci
327162306a36Sopenharmony_ci	status = be_mcc_notify(adapter);
327262306a36Sopenharmony_ci	if (status)
327362306a36Sopenharmony_ci		goto err_unlock;
327462306a36Sopenharmony_ci
327562306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
327662306a36Sopenharmony_ci
327762306a36Sopenharmony_ci	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
327862306a36Sopenharmony_ci					 msecs_to_jiffies(SET_LB_MODE_TIMEOUT)))
327962306a36Sopenharmony_ci		status = -ETIMEDOUT;
328062306a36Sopenharmony_ci
328162306a36Sopenharmony_ci	return status;
328262306a36Sopenharmony_ci
328362306a36Sopenharmony_cierr_unlock:
328462306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
328562306a36Sopenharmony_ci	return status;
328662306a36Sopenharmony_ci}
328762306a36Sopenharmony_ci
328862306a36Sopenharmony_ciint be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
328962306a36Sopenharmony_ci			 u32 loopback_type, u32 pkt_size, u32 num_pkts,
329062306a36Sopenharmony_ci			 u64 pattern)
329162306a36Sopenharmony_ci{
329262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
329362306a36Sopenharmony_ci	struct be_cmd_req_loopback_test *req;
329462306a36Sopenharmony_ci	struct be_cmd_resp_loopback_test *resp;
329562306a36Sopenharmony_ci	int status;
329662306a36Sopenharmony_ci
329762306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_LOOPBACK_TEST,
329862306a36Sopenharmony_ci			    CMD_SUBSYSTEM_LOWLEVEL))
329962306a36Sopenharmony_ci		return -EPERM;
330062306a36Sopenharmony_ci
330162306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
330262306a36Sopenharmony_ci
330362306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
330462306a36Sopenharmony_ci	if (!wrb) {
330562306a36Sopenharmony_ci		status = -EBUSY;
330662306a36Sopenharmony_ci		goto err;
330762306a36Sopenharmony_ci	}
330862306a36Sopenharmony_ci
330962306a36Sopenharmony_ci	req = embedded_payload(wrb);
331062306a36Sopenharmony_ci
331162306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
331262306a36Sopenharmony_ci			       OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb,
331362306a36Sopenharmony_ci			       NULL);
331462306a36Sopenharmony_ci
331562306a36Sopenharmony_ci	req->hdr.timeout = cpu_to_le32(15);
331662306a36Sopenharmony_ci	req->pattern = cpu_to_le64(pattern);
331762306a36Sopenharmony_ci	req->src_port = cpu_to_le32(port_num);
331862306a36Sopenharmony_ci	req->dest_port = cpu_to_le32(port_num);
331962306a36Sopenharmony_ci	req->pkt_size = cpu_to_le32(pkt_size);
332062306a36Sopenharmony_ci	req->num_pkts = cpu_to_le32(num_pkts);
332162306a36Sopenharmony_ci	req->loopback_type = cpu_to_le32(loopback_type);
332262306a36Sopenharmony_ci
332362306a36Sopenharmony_ci	status = be_mcc_notify(adapter);
332462306a36Sopenharmony_ci	if (status)
332562306a36Sopenharmony_ci		goto err;
332662306a36Sopenharmony_ci
332762306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
332862306a36Sopenharmony_ci
332962306a36Sopenharmony_ci	wait_for_completion(&adapter->et_cmd_compl);
333062306a36Sopenharmony_ci	resp = embedded_payload(wrb);
333162306a36Sopenharmony_ci	status = le32_to_cpu(resp->status);
333262306a36Sopenharmony_ci
333362306a36Sopenharmony_ci	return status;
333462306a36Sopenharmony_cierr:
333562306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
333662306a36Sopenharmony_ci	return status;
333762306a36Sopenharmony_ci}
333862306a36Sopenharmony_ci
333962306a36Sopenharmony_ciint be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
334062306a36Sopenharmony_ci			u32 byte_cnt, struct be_dma_mem *cmd)
334162306a36Sopenharmony_ci{
334262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
334362306a36Sopenharmony_ci	struct be_cmd_req_ddrdma_test *req;
334462306a36Sopenharmony_ci	int status;
334562306a36Sopenharmony_ci	int i, j = 0;
334662306a36Sopenharmony_ci
334762306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_HOST_DDR_DMA,
334862306a36Sopenharmony_ci			    CMD_SUBSYSTEM_LOWLEVEL))
334962306a36Sopenharmony_ci		return -EPERM;
335062306a36Sopenharmony_ci
335162306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
335262306a36Sopenharmony_ci
335362306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
335462306a36Sopenharmony_ci	if (!wrb) {
335562306a36Sopenharmony_ci		status = -EBUSY;
335662306a36Sopenharmony_ci		goto err;
335762306a36Sopenharmony_ci	}
335862306a36Sopenharmony_ci	req = cmd->va;
335962306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
336062306a36Sopenharmony_ci			       OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb,
336162306a36Sopenharmony_ci			       cmd);
336262306a36Sopenharmony_ci
336362306a36Sopenharmony_ci	req->pattern = cpu_to_le64(pattern);
336462306a36Sopenharmony_ci	req->byte_count = cpu_to_le32(byte_cnt);
336562306a36Sopenharmony_ci	for (i = 0; i < byte_cnt; i++) {
336662306a36Sopenharmony_ci		req->snd_buff[i] = (u8)(pattern >> (j * 8));
336762306a36Sopenharmony_ci		j++;
336862306a36Sopenharmony_ci		if (j > 7)
336962306a36Sopenharmony_ci			j = 0;
337062306a36Sopenharmony_ci	}
337162306a36Sopenharmony_ci
337262306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
337362306a36Sopenharmony_ci
337462306a36Sopenharmony_ci	if (!status) {
337562306a36Sopenharmony_ci		struct be_cmd_resp_ddrdma_test *resp;
337662306a36Sopenharmony_ci
337762306a36Sopenharmony_ci		resp = cmd->va;
337862306a36Sopenharmony_ci		if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) ||
337962306a36Sopenharmony_ci		    resp->snd_err) {
338062306a36Sopenharmony_ci			status = -1;
338162306a36Sopenharmony_ci		}
338262306a36Sopenharmony_ci	}
338362306a36Sopenharmony_ci
338462306a36Sopenharmony_cierr:
338562306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
338662306a36Sopenharmony_ci	return status;
338762306a36Sopenharmony_ci}
338862306a36Sopenharmony_ci
338962306a36Sopenharmony_ciint be_cmd_get_seeprom_data(struct be_adapter *adapter,
339062306a36Sopenharmony_ci			    struct be_dma_mem *nonemb_cmd)
339162306a36Sopenharmony_ci{
339262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
339362306a36Sopenharmony_ci	struct be_cmd_req_seeprom_read *req;
339462306a36Sopenharmony_ci	int status;
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
339762306a36Sopenharmony_ci
339862306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
339962306a36Sopenharmony_ci	if (!wrb) {
340062306a36Sopenharmony_ci		status = -EBUSY;
340162306a36Sopenharmony_ci		goto err;
340262306a36Sopenharmony_ci	}
340362306a36Sopenharmony_ci	req = nonemb_cmd->va;
340462306a36Sopenharmony_ci
340562306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
340662306a36Sopenharmony_ci			       OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb,
340762306a36Sopenharmony_ci			       nonemb_cmd);
340862306a36Sopenharmony_ci
340962306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
341062306a36Sopenharmony_ci
341162306a36Sopenharmony_cierr:
341262306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
341362306a36Sopenharmony_ci	return status;
341462306a36Sopenharmony_ci}
341562306a36Sopenharmony_ci
341662306a36Sopenharmony_ciint be_cmd_get_phy_info(struct be_adapter *adapter)
341762306a36Sopenharmony_ci{
341862306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
341962306a36Sopenharmony_ci	struct be_cmd_req_get_phy_info *req;
342062306a36Sopenharmony_ci	struct be_dma_mem cmd;
342162306a36Sopenharmony_ci	int status;
342262306a36Sopenharmony_ci
342362306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
342462306a36Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
342562306a36Sopenharmony_ci		return -EPERM;
342662306a36Sopenharmony_ci
342762306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
342862306a36Sopenharmony_ci
342962306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
343062306a36Sopenharmony_ci	if (!wrb) {
343162306a36Sopenharmony_ci		status = -EBUSY;
343262306a36Sopenharmony_ci		goto err;
343362306a36Sopenharmony_ci	}
343462306a36Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_req_get_phy_info);
343562306a36Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
343662306a36Sopenharmony_ci				    GFP_ATOMIC);
343762306a36Sopenharmony_ci	if (!cmd.va) {
343862306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
343962306a36Sopenharmony_ci		status = -ENOMEM;
344062306a36Sopenharmony_ci		goto err;
344162306a36Sopenharmony_ci	}
344262306a36Sopenharmony_ci
344362306a36Sopenharmony_ci	req = cmd.va;
344462306a36Sopenharmony_ci
344562306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
344662306a36Sopenharmony_ci			       OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req),
344762306a36Sopenharmony_ci			       wrb, &cmd);
344862306a36Sopenharmony_ci
344962306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
345062306a36Sopenharmony_ci	if (!status) {
345162306a36Sopenharmony_ci		struct be_phy_info *resp_phy_info =
345262306a36Sopenharmony_ci				cmd.va + sizeof(struct be_cmd_req_hdr);
345362306a36Sopenharmony_ci
345462306a36Sopenharmony_ci		adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type);
345562306a36Sopenharmony_ci		adapter->phy.interface_type =
345662306a36Sopenharmony_ci			le16_to_cpu(resp_phy_info->interface_type);
345762306a36Sopenharmony_ci		adapter->phy.auto_speeds_supported =
345862306a36Sopenharmony_ci			le16_to_cpu(resp_phy_info->auto_speeds_supported);
345962306a36Sopenharmony_ci		adapter->phy.fixed_speeds_supported =
346062306a36Sopenharmony_ci			le16_to_cpu(resp_phy_info->fixed_speeds_supported);
346162306a36Sopenharmony_ci		adapter->phy.misc_params =
346262306a36Sopenharmony_ci			le32_to_cpu(resp_phy_info->misc_params);
346362306a36Sopenharmony_ci
346462306a36Sopenharmony_ci		if (BE2_chip(adapter)) {
346562306a36Sopenharmony_ci			adapter->phy.fixed_speeds_supported =
346662306a36Sopenharmony_ci				BE_SUPPORTED_SPEED_10GBPS |
346762306a36Sopenharmony_ci				BE_SUPPORTED_SPEED_1GBPS;
346862306a36Sopenharmony_ci		}
346962306a36Sopenharmony_ci	}
347062306a36Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
347162306a36Sopenharmony_cierr:
347262306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
347362306a36Sopenharmony_ci	return status;
347462306a36Sopenharmony_ci}
347562306a36Sopenharmony_ci
347662306a36Sopenharmony_cistatic int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain)
347762306a36Sopenharmony_ci{
347862306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
347962306a36Sopenharmony_ci	struct be_cmd_req_set_qos *req;
348062306a36Sopenharmony_ci	int status;
348162306a36Sopenharmony_ci
348262306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
348362306a36Sopenharmony_ci
348462306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
348562306a36Sopenharmony_ci	if (!wrb) {
348662306a36Sopenharmony_ci		status = -EBUSY;
348762306a36Sopenharmony_ci		goto err;
348862306a36Sopenharmony_ci	}
348962306a36Sopenharmony_ci
349062306a36Sopenharmony_ci	req = embedded_payload(wrb);
349162306a36Sopenharmony_ci
349262306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
349362306a36Sopenharmony_ci			       OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL);
349462306a36Sopenharmony_ci
349562306a36Sopenharmony_ci	req->hdr.domain = domain;
349662306a36Sopenharmony_ci	req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
349762306a36Sopenharmony_ci	req->max_bps_nic = cpu_to_le32(bps);
349862306a36Sopenharmony_ci
349962306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
350062306a36Sopenharmony_ci
350162306a36Sopenharmony_cierr:
350262306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
350362306a36Sopenharmony_ci	return status;
350462306a36Sopenharmony_ci}
350562306a36Sopenharmony_ci
350662306a36Sopenharmony_ciint be_cmd_get_cntl_attributes(struct be_adapter *adapter)
350762306a36Sopenharmony_ci{
350862306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
350962306a36Sopenharmony_ci	struct be_cmd_req_cntl_attribs *req;
351062306a36Sopenharmony_ci	struct be_cmd_resp_cntl_attribs *resp;
351162306a36Sopenharmony_ci	int status, i;
351262306a36Sopenharmony_ci	int payload_len = max(sizeof(*req), sizeof(*resp));
351362306a36Sopenharmony_ci	struct mgmt_controller_attrib *attribs;
351462306a36Sopenharmony_ci	struct be_dma_mem attribs_cmd;
351562306a36Sopenharmony_ci	u32 *serial_num;
351662306a36Sopenharmony_ci
351762306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
351862306a36Sopenharmony_ci		return -1;
351962306a36Sopenharmony_ci
352062306a36Sopenharmony_ci	memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
352162306a36Sopenharmony_ci	attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
352262306a36Sopenharmony_ci	attribs_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
352362306a36Sopenharmony_ci					    attribs_cmd.size,
352462306a36Sopenharmony_ci					    &attribs_cmd.dma, GFP_ATOMIC);
352562306a36Sopenharmony_ci	if (!attribs_cmd.va) {
352662306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
352762306a36Sopenharmony_ci		status = -ENOMEM;
352862306a36Sopenharmony_ci		goto err;
352962306a36Sopenharmony_ci	}
353062306a36Sopenharmony_ci
353162306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
353262306a36Sopenharmony_ci	if (!wrb) {
353362306a36Sopenharmony_ci		status = -EBUSY;
353462306a36Sopenharmony_ci		goto err;
353562306a36Sopenharmony_ci	}
353662306a36Sopenharmony_ci	req = attribs_cmd.va;
353762306a36Sopenharmony_ci
353862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
353962306a36Sopenharmony_ci			       OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len,
354062306a36Sopenharmony_ci			       wrb, &attribs_cmd);
354162306a36Sopenharmony_ci
354262306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
354362306a36Sopenharmony_ci	if (!status) {
354462306a36Sopenharmony_ci		attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
354562306a36Sopenharmony_ci		adapter->hba_port_num = attribs->hba_attribs.phy_port;
354662306a36Sopenharmony_ci		serial_num = attribs->hba_attribs.controller_serial_number;
354762306a36Sopenharmony_ci		for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++)
354862306a36Sopenharmony_ci			adapter->serial_num[i] = le32_to_cpu(serial_num[i]) &
354962306a36Sopenharmony_ci				(BIT_MASK(16) - 1);
355062306a36Sopenharmony_ci		/* For BEx, since GET_FUNC_CONFIG command is not
355162306a36Sopenharmony_ci		 * supported, we read funcnum here as a workaround.
355262306a36Sopenharmony_ci		 */
355362306a36Sopenharmony_ci		if (BEx_chip(adapter))
355462306a36Sopenharmony_ci			adapter->pf_num = attribs->hba_attribs.pci_funcnum;
355562306a36Sopenharmony_ci	}
355662306a36Sopenharmony_ci
355762306a36Sopenharmony_cierr:
355862306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
355962306a36Sopenharmony_ci	if (attribs_cmd.va)
356062306a36Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, attribs_cmd.size,
356162306a36Sopenharmony_ci				  attribs_cmd.va, attribs_cmd.dma);
356262306a36Sopenharmony_ci	return status;
356362306a36Sopenharmony_ci}
356462306a36Sopenharmony_ci
356562306a36Sopenharmony_ci/* Uses mbox */
356662306a36Sopenharmony_ciint be_cmd_req_native_mode(struct be_adapter *adapter)
356762306a36Sopenharmony_ci{
356862306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
356962306a36Sopenharmony_ci	struct be_cmd_req_set_func_cap *req;
357062306a36Sopenharmony_ci	int status;
357162306a36Sopenharmony_ci
357262306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
357362306a36Sopenharmony_ci		return -1;
357462306a36Sopenharmony_ci
357562306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
357662306a36Sopenharmony_ci	if (!wrb) {
357762306a36Sopenharmony_ci		status = -EBUSY;
357862306a36Sopenharmony_ci		goto err;
357962306a36Sopenharmony_ci	}
358062306a36Sopenharmony_ci
358162306a36Sopenharmony_ci	req = embedded_payload(wrb);
358262306a36Sopenharmony_ci
358362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
358462306a36Sopenharmony_ci			       OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP,
358562306a36Sopenharmony_ci			       sizeof(*req), wrb, NULL);
358662306a36Sopenharmony_ci
358762306a36Sopenharmony_ci	req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS |
358862306a36Sopenharmony_ci				CAPABILITY_BE3_NATIVE_ERX_API);
358962306a36Sopenharmony_ci	req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API);
359062306a36Sopenharmony_ci
359162306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
359262306a36Sopenharmony_ci	if (!status) {
359362306a36Sopenharmony_ci		struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb);
359462306a36Sopenharmony_ci
359562306a36Sopenharmony_ci		adapter->be3_native = le32_to_cpu(resp->cap_flags) &
359662306a36Sopenharmony_ci					CAPABILITY_BE3_NATIVE_ERX_API;
359762306a36Sopenharmony_ci		if (!adapter->be3_native)
359862306a36Sopenharmony_ci			dev_warn(&adapter->pdev->dev,
359962306a36Sopenharmony_ci				 "adapter not in advanced mode\n");
360062306a36Sopenharmony_ci	}
360162306a36Sopenharmony_cierr:
360262306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
360362306a36Sopenharmony_ci	return status;
360462306a36Sopenharmony_ci}
360562306a36Sopenharmony_ci
360662306a36Sopenharmony_ci/* Get privilege(s) for a function */
360762306a36Sopenharmony_ciint be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
360862306a36Sopenharmony_ci			     u32 domain)
360962306a36Sopenharmony_ci{
361062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
361162306a36Sopenharmony_ci	struct be_cmd_req_get_fn_privileges *req;
361262306a36Sopenharmony_ci	int status;
361362306a36Sopenharmony_ci
361462306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
361562306a36Sopenharmony_ci
361662306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
361762306a36Sopenharmony_ci	if (!wrb) {
361862306a36Sopenharmony_ci		status = -EBUSY;
361962306a36Sopenharmony_ci		goto err;
362062306a36Sopenharmony_ci	}
362162306a36Sopenharmony_ci
362262306a36Sopenharmony_ci	req = embedded_payload(wrb);
362362306a36Sopenharmony_ci
362462306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
362562306a36Sopenharmony_ci			       OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
362662306a36Sopenharmony_ci			       wrb, NULL);
362762306a36Sopenharmony_ci
362862306a36Sopenharmony_ci	req->hdr.domain = domain;
362962306a36Sopenharmony_ci
363062306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
363162306a36Sopenharmony_ci	if (!status) {
363262306a36Sopenharmony_ci		struct be_cmd_resp_get_fn_privileges *resp =
363362306a36Sopenharmony_ci						embedded_payload(wrb);
363462306a36Sopenharmony_ci
363562306a36Sopenharmony_ci		*privilege = le32_to_cpu(resp->privilege_mask);
363662306a36Sopenharmony_ci
363762306a36Sopenharmony_ci		/* In UMC mode FW does not return right privileges.
363862306a36Sopenharmony_ci		 * Override with correct privilege equivalent to PF.
363962306a36Sopenharmony_ci		 */
364062306a36Sopenharmony_ci		if (BEx_chip(adapter) && be_is_mc(adapter) &&
364162306a36Sopenharmony_ci		    be_physfn(adapter))
364262306a36Sopenharmony_ci			*privilege = MAX_PRIVILEGES;
364362306a36Sopenharmony_ci	}
364462306a36Sopenharmony_ci
364562306a36Sopenharmony_cierr:
364662306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
364762306a36Sopenharmony_ci	return status;
364862306a36Sopenharmony_ci}
364962306a36Sopenharmony_ci
365062306a36Sopenharmony_ci/* Set privilege(s) for a function */
365162306a36Sopenharmony_ciint be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges,
365262306a36Sopenharmony_ci			     u32 domain)
365362306a36Sopenharmony_ci{
365462306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
365562306a36Sopenharmony_ci	struct be_cmd_req_set_fn_privileges *req;
365662306a36Sopenharmony_ci	int status;
365762306a36Sopenharmony_ci
365862306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
365962306a36Sopenharmony_ci
366062306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
366162306a36Sopenharmony_ci	if (!wrb) {
366262306a36Sopenharmony_ci		status = -EBUSY;
366362306a36Sopenharmony_ci		goto err;
366462306a36Sopenharmony_ci	}
366562306a36Sopenharmony_ci
366662306a36Sopenharmony_ci	req = embedded_payload(wrb);
366762306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
366862306a36Sopenharmony_ci			       OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req),
366962306a36Sopenharmony_ci			       wrb, NULL);
367062306a36Sopenharmony_ci	req->hdr.domain = domain;
367162306a36Sopenharmony_ci	if (lancer_chip(adapter))
367262306a36Sopenharmony_ci		req->privileges_lancer = cpu_to_le32(privileges);
367362306a36Sopenharmony_ci	else
367462306a36Sopenharmony_ci		req->privileges = cpu_to_le32(privileges);
367562306a36Sopenharmony_ci
367662306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
367762306a36Sopenharmony_cierr:
367862306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
367962306a36Sopenharmony_ci	return status;
368062306a36Sopenharmony_ci}
368162306a36Sopenharmony_ci
368262306a36Sopenharmony_ci/* pmac_id_valid: true => pmac_id is supplied and MAC address is requested.
368362306a36Sopenharmony_ci * pmac_id_valid: false => pmac_id or MAC address is requested.
368462306a36Sopenharmony_ci *		  If pmac_id is returned, pmac_id_valid is returned as true
368562306a36Sopenharmony_ci */
368662306a36Sopenharmony_ciint be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
368762306a36Sopenharmony_ci			     bool *pmac_id_valid, u32 *pmac_id, u32 if_handle,
368862306a36Sopenharmony_ci			     u8 domain)
368962306a36Sopenharmony_ci{
369062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
369162306a36Sopenharmony_ci	struct be_cmd_req_get_mac_list *req;
369262306a36Sopenharmony_ci	int status;
369362306a36Sopenharmony_ci	int mac_count;
369462306a36Sopenharmony_ci	struct be_dma_mem get_mac_list_cmd;
369562306a36Sopenharmony_ci	int i;
369662306a36Sopenharmony_ci
369762306a36Sopenharmony_ci	memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
369862306a36Sopenharmony_ci	get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
369962306a36Sopenharmony_ci	get_mac_list_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
370062306a36Sopenharmony_ci						 get_mac_list_cmd.size,
370162306a36Sopenharmony_ci						 &get_mac_list_cmd.dma,
370262306a36Sopenharmony_ci						 GFP_ATOMIC);
370362306a36Sopenharmony_ci
370462306a36Sopenharmony_ci	if (!get_mac_list_cmd.va) {
370562306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev,
370662306a36Sopenharmony_ci			"Memory allocation failure during GET_MAC_LIST\n");
370762306a36Sopenharmony_ci		return -ENOMEM;
370862306a36Sopenharmony_ci	}
370962306a36Sopenharmony_ci
371062306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
371162306a36Sopenharmony_ci
371262306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
371362306a36Sopenharmony_ci	if (!wrb) {
371462306a36Sopenharmony_ci		status = -EBUSY;
371562306a36Sopenharmony_ci		goto out;
371662306a36Sopenharmony_ci	}
371762306a36Sopenharmony_ci
371862306a36Sopenharmony_ci	req = get_mac_list_cmd.va;
371962306a36Sopenharmony_ci
372062306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
372162306a36Sopenharmony_ci			       OPCODE_COMMON_GET_MAC_LIST,
372262306a36Sopenharmony_ci			       get_mac_list_cmd.size, wrb, &get_mac_list_cmd);
372362306a36Sopenharmony_ci	req->hdr.domain = domain;
372462306a36Sopenharmony_ci	req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
372562306a36Sopenharmony_ci	if (*pmac_id_valid) {
372662306a36Sopenharmony_ci		req->mac_id = cpu_to_le32(*pmac_id);
372762306a36Sopenharmony_ci		req->iface_id = cpu_to_le16(if_handle);
372862306a36Sopenharmony_ci		req->perm_override = 0;
372962306a36Sopenharmony_ci	} else {
373062306a36Sopenharmony_ci		req->perm_override = 1;
373162306a36Sopenharmony_ci	}
373262306a36Sopenharmony_ci
373362306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
373462306a36Sopenharmony_ci	if (!status) {
373562306a36Sopenharmony_ci		struct be_cmd_resp_get_mac_list *resp =
373662306a36Sopenharmony_ci						get_mac_list_cmd.va;
373762306a36Sopenharmony_ci
373862306a36Sopenharmony_ci		if (*pmac_id_valid) {
373962306a36Sopenharmony_ci			memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr,
374062306a36Sopenharmony_ci			       ETH_ALEN);
374162306a36Sopenharmony_ci			goto out;
374262306a36Sopenharmony_ci		}
374362306a36Sopenharmony_ci
374462306a36Sopenharmony_ci		mac_count = resp->true_mac_count + resp->pseudo_mac_count;
374562306a36Sopenharmony_ci		/* Mac list returned could contain one or more active mac_ids
374662306a36Sopenharmony_ci		 * or one or more true or pseudo permanent mac addresses.
374762306a36Sopenharmony_ci		 * If an active mac_id is present, return first active mac_id
374862306a36Sopenharmony_ci		 * found.
374962306a36Sopenharmony_ci		 */
375062306a36Sopenharmony_ci		for (i = 0; i < mac_count; i++) {
375162306a36Sopenharmony_ci			struct get_list_macaddr *mac_entry;
375262306a36Sopenharmony_ci			u16 mac_addr_size;
375362306a36Sopenharmony_ci			u32 mac_id;
375462306a36Sopenharmony_ci
375562306a36Sopenharmony_ci			mac_entry = &resp->macaddr_list[i];
375662306a36Sopenharmony_ci			mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size);
375762306a36Sopenharmony_ci			/* mac_id is a 32 bit value and mac_addr size
375862306a36Sopenharmony_ci			 * is 6 bytes
375962306a36Sopenharmony_ci			 */
376062306a36Sopenharmony_ci			if (mac_addr_size == sizeof(u32)) {
376162306a36Sopenharmony_ci				*pmac_id_valid = true;
376262306a36Sopenharmony_ci				mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id;
376362306a36Sopenharmony_ci				*pmac_id = le32_to_cpu(mac_id);
376462306a36Sopenharmony_ci				goto out;
376562306a36Sopenharmony_ci			}
376662306a36Sopenharmony_ci		}
376762306a36Sopenharmony_ci		/* If no active mac_id found, return first mac addr */
376862306a36Sopenharmony_ci		*pmac_id_valid = false;
376962306a36Sopenharmony_ci		memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr,
377062306a36Sopenharmony_ci		       ETH_ALEN);
377162306a36Sopenharmony_ci	}
377262306a36Sopenharmony_ci
377362306a36Sopenharmony_ciout:
377462306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
377562306a36Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, get_mac_list_cmd.size,
377662306a36Sopenharmony_ci			  get_mac_list_cmd.va, get_mac_list_cmd.dma);
377762306a36Sopenharmony_ci	return status;
377862306a36Sopenharmony_ci}
377962306a36Sopenharmony_ci
378062306a36Sopenharmony_ciint be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id,
378162306a36Sopenharmony_ci			  u8 *mac, u32 if_handle, bool active, u32 domain)
378262306a36Sopenharmony_ci{
378362306a36Sopenharmony_ci	if (!active)
378462306a36Sopenharmony_ci		be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id,
378562306a36Sopenharmony_ci					 if_handle, domain);
378662306a36Sopenharmony_ci	if (BEx_chip(adapter))
378762306a36Sopenharmony_ci		return be_cmd_mac_addr_query(adapter, mac, false,
378862306a36Sopenharmony_ci					     if_handle, curr_pmac_id);
378962306a36Sopenharmony_ci	else
379062306a36Sopenharmony_ci		/* Fetch the MAC address using pmac_id */
379162306a36Sopenharmony_ci		return be_cmd_get_mac_from_list(adapter, mac, &active,
379262306a36Sopenharmony_ci						&curr_pmac_id,
379362306a36Sopenharmony_ci						if_handle, domain);
379462306a36Sopenharmony_ci}
379562306a36Sopenharmony_ci
379662306a36Sopenharmony_ciint be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac)
379762306a36Sopenharmony_ci{
379862306a36Sopenharmony_ci	int status;
379962306a36Sopenharmony_ci	bool pmac_valid = false;
380062306a36Sopenharmony_ci
380162306a36Sopenharmony_ci	eth_zero_addr(mac);
380262306a36Sopenharmony_ci
380362306a36Sopenharmony_ci	if (BEx_chip(adapter)) {
380462306a36Sopenharmony_ci		if (be_physfn(adapter))
380562306a36Sopenharmony_ci			status = be_cmd_mac_addr_query(adapter, mac, true, 0,
380662306a36Sopenharmony_ci						       0);
380762306a36Sopenharmony_ci		else
380862306a36Sopenharmony_ci			status = be_cmd_mac_addr_query(adapter, mac, false,
380962306a36Sopenharmony_ci						       adapter->if_handle, 0);
381062306a36Sopenharmony_ci	} else {
381162306a36Sopenharmony_ci		status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid,
381262306a36Sopenharmony_ci						  NULL, adapter->if_handle, 0);
381362306a36Sopenharmony_ci	}
381462306a36Sopenharmony_ci
381562306a36Sopenharmony_ci	return status;
381662306a36Sopenharmony_ci}
381762306a36Sopenharmony_ci
381862306a36Sopenharmony_ci/* Uses synchronous MCCQ */
381962306a36Sopenharmony_ciint be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
382062306a36Sopenharmony_ci			u8 mac_count, u32 domain)
382162306a36Sopenharmony_ci{
382262306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
382362306a36Sopenharmony_ci	struct be_cmd_req_set_mac_list *req;
382462306a36Sopenharmony_ci	int status;
382562306a36Sopenharmony_ci	struct be_dma_mem cmd;
382662306a36Sopenharmony_ci
382762306a36Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
382862306a36Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_req_set_mac_list);
382962306a36Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
383062306a36Sopenharmony_ci				    GFP_KERNEL);
383162306a36Sopenharmony_ci	if (!cmd.va)
383262306a36Sopenharmony_ci		return -ENOMEM;
383362306a36Sopenharmony_ci
383462306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
383562306a36Sopenharmony_ci
383662306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
383762306a36Sopenharmony_ci	if (!wrb) {
383862306a36Sopenharmony_ci		status = -EBUSY;
383962306a36Sopenharmony_ci		goto err;
384062306a36Sopenharmony_ci	}
384162306a36Sopenharmony_ci
384262306a36Sopenharmony_ci	req = cmd.va;
384362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
384462306a36Sopenharmony_ci			       OPCODE_COMMON_SET_MAC_LIST, sizeof(*req),
384562306a36Sopenharmony_ci			       wrb, &cmd);
384662306a36Sopenharmony_ci
384762306a36Sopenharmony_ci	req->hdr.domain = domain;
384862306a36Sopenharmony_ci	req->mac_count = mac_count;
384962306a36Sopenharmony_ci	if (mac_count)
385062306a36Sopenharmony_ci		memcpy(req->mac, mac_array, ETH_ALEN * mac_count);
385162306a36Sopenharmony_ci
385262306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
385362306a36Sopenharmony_ci
385462306a36Sopenharmony_cierr:
385562306a36Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
385662306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
385762306a36Sopenharmony_ci	return status;
385862306a36Sopenharmony_ci}
385962306a36Sopenharmony_ci
386062306a36Sopenharmony_ci/* Wrapper to delete any active MACs and provision the new mac.
386162306a36Sopenharmony_ci * Changes to MAC_LIST are allowed iff none of the MAC addresses in the
386262306a36Sopenharmony_ci * current list are active.
386362306a36Sopenharmony_ci */
386462306a36Sopenharmony_ciint be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
386562306a36Sopenharmony_ci{
386662306a36Sopenharmony_ci	bool active_mac = false;
386762306a36Sopenharmony_ci	u8 old_mac[ETH_ALEN];
386862306a36Sopenharmony_ci	u32 pmac_id;
386962306a36Sopenharmony_ci	int status;
387062306a36Sopenharmony_ci
387162306a36Sopenharmony_ci	status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
387262306a36Sopenharmony_ci					  &pmac_id, if_id, dom);
387362306a36Sopenharmony_ci
387462306a36Sopenharmony_ci	if (!status && active_mac)
387562306a36Sopenharmony_ci		be_cmd_pmac_del(adapter, if_id, pmac_id, dom);
387662306a36Sopenharmony_ci
387762306a36Sopenharmony_ci	return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom);
387862306a36Sopenharmony_ci}
387962306a36Sopenharmony_ci
388062306a36Sopenharmony_ciint be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
388162306a36Sopenharmony_ci			  u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk)
388262306a36Sopenharmony_ci{
388362306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
388462306a36Sopenharmony_ci	struct be_cmd_req_set_hsw_config *req;
388562306a36Sopenharmony_ci	void *ctxt;
388662306a36Sopenharmony_ci	int status;
388762306a36Sopenharmony_ci
388862306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_HSW_CONFIG,
388962306a36Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
389062306a36Sopenharmony_ci		return -EPERM;
389162306a36Sopenharmony_ci
389262306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
389362306a36Sopenharmony_ci
389462306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
389562306a36Sopenharmony_ci	if (!wrb) {
389662306a36Sopenharmony_ci		status = -EBUSY;
389762306a36Sopenharmony_ci		goto err;
389862306a36Sopenharmony_ci	}
389962306a36Sopenharmony_ci
390062306a36Sopenharmony_ci	req = embedded_payload(wrb);
390162306a36Sopenharmony_ci	ctxt = &req->context;
390262306a36Sopenharmony_ci
390362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
390462306a36Sopenharmony_ci			       OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb,
390562306a36Sopenharmony_ci			       NULL);
390662306a36Sopenharmony_ci
390762306a36Sopenharmony_ci	req->hdr.domain = domain;
390862306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id);
390962306a36Sopenharmony_ci	if (pvid) {
391062306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1);
391162306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid);
391262306a36Sopenharmony_ci	}
391362306a36Sopenharmony_ci	if (hsw_mode) {
391462306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, interface_id,
391562306a36Sopenharmony_ci			      ctxt, adapter->hba_port_num);
391662306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1);
391762306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type,
391862306a36Sopenharmony_ci			      ctxt, hsw_mode);
391962306a36Sopenharmony_ci	}
392062306a36Sopenharmony_ci
392162306a36Sopenharmony_ci	/* Enable/disable both mac and vlan spoof checking */
392262306a36Sopenharmony_ci	if (!BEx_chip(adapter) && spoofchk) {
392362306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk,
392462306a36Sopenharmony_ci			      ctxt, spoofchk);
392562306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk,
392662306a36Sopenharmony_ci			      ctxt, spoofchk);
392762306a36Sopenharmony_ci	}
392862306a36Sopenharmony_ci
392962306a36Sopenharmony_ci	be_dws_cpu_to_le(req->context, sizeof(req->context));
393062306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
393162306a36Sopenharmony_ci
393262306a36Sopenharmony_cierr:
393362306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
393462306a36Sopenharmony_ci	return status;
393562306a36Sopenharmony_ci}
393662306a36Sopenharmony_ci
393762306a36Sopenharmony_ci/* Get Hyper switch config */
393862306a36Sopenharmony_ciint be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
393962306a36Sopenharmony_ci			  u32 domain, u16 intf_id, u8 *mode, bool *spoofchk)
394062306a36Sopenharmony_ci{
394162306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
394262306a36Sopenharmony_ci	struct be_cmd_req_get_hsw_config *req;
394362306a36Sopenharmony_ci	void *ctxt;
394462306a36Sopenharmony_ci	int status;
394562306a36Sopenharmony_ci	u16 vid;
394662306a36Sopenharmony_ci
394762306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
394862306a36Sopenharmony_ci
394962306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
395062306a36Sopenharmony_ci	if (!wrb) {
395162306a36Sopenharmony_ci		status = -EBUSY;
395262306a36Sopenharmony_ci		goto err;
395362306a36Sopenharmony_ci	}
395462306a36Sopenharmony_ci
395562306a36Sopenharmony_ci	req = embedded_payload(wrb);
395662306a36Sopenharmony_ci	ctxt = &req->context;
395762306a36Sopenharmony_ci
395862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
395962306a36Sopenharmony_ci			       OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb,
396062306a36Sopenharmony_ci			       NULL);
396162306a36Sopenharmony_ci
396262306a36Sopenharmony_ci	req->hdr.domain = domain;
396362306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
396462306a36Sopenharmony_ci		      ctxt, intf_id);
396562306a36Sopenharmony_ci	AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1);
396662306a36Sopenharmony_ci
396762306a36Sopenharmony_ci	if (!BEx_chip(adapter) && mode) {
396862306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
396962306a36Sopenharmony_ci			      ctxt, adapter->hba_port_num);
397062306a36Sopenharmony_ci		AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1);
397162306a36Sopenharmony_ci	}
397262306a36Sopenharmony_ci	be_dws_cpu_to_le(req->context, sizeof(req->context));
397362306a36Sopenharmony_ci
397462306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
397562306a36Sopenharmony_ci	if (!status) {
397662306a36Sopenharmony_ci		struct be_cmd_resp_get_hsw_config *resp =
397762306a36Sopenharmony_ci						embedded_payload(wrb);
397862306a36Sopenharmony_ci
397962306a36Sopenharmony_ci		be_dws_le_to_cpu(&resp->context, sizeof(resp->context));
398062306a36Sopenharmony_ci		vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
398162306a36Sopenharmony_ci				    pvid, &resp->context);
398262306a36Sopenharmony_ci		if (pvid)
398362306a36Sopenharmony_ci			*pvid = le16_to_cpu(vid);
398462306a36Sopenharmony_ci		if (mode)
398562306a36Sopenharmony_ci			*mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
398662306a36Sopenharmony_ci					      port_fwd_type, &resp->context);
398762306a36Sopenharmony_ci		if (spoofchk)
398862306a36Sopenharmony_ci			*spoofchk =
398962306a36Sopenharmony_ci				AMAP_GET_BITS(struct amap_get_hsw_resp_context,
399062306a36Sopenharmony_ci					      spoofchk, &resp->context);
399162306a36Sopenharmony_ci	}
399262306a36Sopenharmony_ci
399362306a36Sopenharmony_cierr:
399462306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
399562306a36Sopenharmony_ci	return status;
399662306a36Sopenharmony_ci}
399762306a36Sopenharmony_ci
399862306a36Sopenharmony_cistatic bool be_is_wol_excluded(struct be_adapter *adapter)
399962306a36Sopenharmony_ci{
400062306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
400162306a36Sopenharmony_ci
400262306a36Sopenharmony_ci	if (be_virtfn(adapter))
400362306a36Sopenharmony_ci		return true;
400462306a36Sopenharmony_ci
400562306a36Sopenharmony_ci	switch (pdev->subsystem_device) {
400662306a36Sopenharmony_ci	case OC_SUBSYS_DEVICE_ID1:
400762306a36Sopenharmony_ci	case OC_SUBSYS_DEVICE_ID2:
400862306a36Sopenharmony_ci	case OC_SUBSYS_DEVICE_ID3:
400962306a36Sopenharmony_ci	case OC_SUBSYS_DEVICE_ID4:
401062306a36Sopenharmony_ci		return true;
401162306a36Sopenharmony_ci	default:
401262306a36Sopenharmony_ci		return false;
401362306a36Sopenharmony_ci	}
401462306a36Sopenharmony_ci}
401562306a36Sopenharmony_ci
401662306a36Sopenharmony_ciint be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
401762306a36Sopenharmony_ci{
401862306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
401962306a36Sopenharmony_ci	struct be_cmd_req_acpi_wol_magic_config_v1 *req;
402062306a36Sopenharmony_ci	int status = 0;
402162306a36Sopenharmony_ci	struct be_dma_mem cmd;
402262306a36Sopenharmony_ci
402362306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
402462306a36Sopenharmony_ci			    CMD_SUBSYSTEM_ETH))
402562306a36Sopenharmony_ci		return -EPERM;
402662306a36Sopenharmony_ci
402762306a36Sopenharmony_ci	if (be_is_wol_excluded(adapter))
402862306a36Sopenharmony_ci		return status;
402962306a36Sopenharmony_ci
403062306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
403162306a36Sopenharmony_ci		return -1;
403262306a36Sopenharmony_ci
403362306a36Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
403462306a36Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
403562306a36Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
403662306a36Sopenharmony_ci				    GFP_ATOMIC);
403762306a36Sopenharmony_ci	if (!cmd.va) {
403862306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
403962306a36Sopenharmony_ci		status = -ENOMEM;
404062306a36Sopenharmony_ci		goto err;
404162306a36Sopenharmony_ci	}
404262306a36Sopenharmony_ci
404362306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
404462306a36Sopenharmony_ci	if (!wrb) {
404562306a36Sopenharmony_ci		status = -EBUSY;
404662306a36Sopenharmony_ci		goto err;
404762306a36Sopenharmony_ci	}
404862306a36Sopenharmony_ci
404962306a36Sopenharmony_ci	req = cmd.va;
405062306a36Sopenharmony_ci
405162306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
405262306a36Sopenharmony_ci			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
405362306a36Sopenharmony_ci			       sizeof(*req), wrb, &cmd);
405462306a36Sopenharmony_ci
405562306a36Sopenharmony_ci	req->hdr.version = 1;
405662306a36Sopenharmony_ci	req->query_options = BE_GET_WOL_CAP;
405762306a36Sopenharmony_ci
405862306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
405962306a36Sopenharmony_ci	if (!status) {
406062306a36Sopenharmony_ci		struct be_cmd_resp_acpi_wol_magic_config_v1 *resp;
406162306a36Sopenharmony_ci
406262306a36Sopenharmony_ci		resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va;
406362306a36Sopenharmony_ci
406462306a36Sopenharmony_ci		adapter->wol_cap = resp->wol_settings;
406562306a36Sopenharmony_ci
406662306a36Sopenharmony_ci		/* Non-zero macaddr indicates WOL is enabled */
406762306a36Sopenharmony_ci		if (adapter->wol_cap & BE_WOL_CAP &&
406862306a36Sopenharmony_ci		    !is_zero_ether_addr(resp->magic_mac))
406962306a36Sopenharmony_ci			adapter->wol_en = true;
407062306a36Sopenharmony_ci	}
407162306a36Sopenharmony_cierr:
407262306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
407362306a36Sopenharmony_ci	if (cmd.va)
407462306a36Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
407562306a36Sopenharmony_ci				  cmd.dma);
407662306a36Sopenharmony_ci	return status;
407762306a36Sopenharmony_ci
407862306a36Sopenharmony_ci}
407962306a36Sopenharmony_ci
408062306a36Sopenharmony_ciint be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level)
408162306a36Sopenharmony_ci{
408262306a36Sopenharmony_ci	struct be_dma_mem extfat_cmd;
408362306a36Sopenharmony_ci	struct be_fat_conf_params *cfgs;
408462306a36Sopenharmony_ci	int status;
408562306a36Sopenharmony_ci	int i, j;
408662306a36Sopenharmony_ci
408762306a36Sopenharmony_ci	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
408862306a36Sopenharmony_ci	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
408962306a36Sopenharmony_ci	extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
409062306a36Sopenharmony_ci					   extfat_cmd.size, &extfat_cmd.dma,
409162306a36Sopenharmony_ci					   GFP_ATOMIC);
409262306a36Sopenharmony_ci	if (!extfat_cmd.va)
409362306a36Sopenharmony_ci		return -ENOMEM;
409462306a36Sopenharmony_ci
409562306a36Sopenharmony_ci	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
409662306a36Sopenharmony_ci	if (status)
409762306a36Sopenharmony_ci		goto err;
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_ci	cfgs = (struct be_fat_conf_params *)
410062306a36Sopenharmony_ci			(extfat_cmd.va + sizeof(struct be_cmd_resp_hdr));
410162306a36Sopenharmony_ci	for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) {
410262306a36Sopenharmony_ci		u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes);
410362306a36Sopenharmony_ci
410462306a36Sopenharmony_ci		for (j = 0; j < num_modes; j++) {
410562306a36Sopenharmony_ci			if (cfgs->module[i].trace_lvl[j].mode == MODE_UART)
410662306a36Sopenharmony_ci				cfgs->module[i].trace_lvl[j].dbg_lvl =
410762306a36Sopenharmony_ci							cpu_to_le32(level);
410862306a36Sopenharmony_ci		}
410962306a36Sopenharmony_ci	}
411062306a36Sopenharmony_ci
411162306a36Sopenharmony_ci	status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs);
411262306a36Sopenharmony_cierr:
411362306a36Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va,
411462306a36Sopenharmony_ci			  extfat_cmd.dma);
411562306a36Sopenharmony_ci	return status;
411662306a36Sopenharmony_ci}
411762306a36Sopenharmony_ci
411862306a36Sopenharmony_ciint be_cmd_get_fw_log_level(struct be_adapter *adapter)
411962306a36Sopenharmony_ci{
412062306a36Sopenharmony_ci	struct be_dma_mem extfat_cmd;
412162306a36Sopenharmony_ci	struct be_fat_conf_params *cfgs;
412262306a36Sopenharmony_ci	int status, j;
412362306a36Sopenharmony_ci	int level = 0;
412462306a36Sopenharmony_ci
412562306a36Sopenharmony_ci	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
412662306a36Sopenharmony_ci	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
412762306a36Sopenharmony_ci	extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
412862306a36Sopenharmony_ci					   extfat_cmd.size, &extfat_cmd.dma,
412962306a36Sopenharmony_ci					   GFP_ATOMIC);
413062306a36Sopenharmony_ci
413162306a36Sopenharmony_ci	if (!extfat_cmd.va) {
413262306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
413362306a36Sopenharmony_ci			__func__);
413462306a36Sopenharmony_ci		goto err;
413562306a36Sopenharmony_ci	}
413662306a36Sopenharmony_ci
413762306a36Sopenharmony_ci	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
413862306a36Sopenharmony_ci	if (!status) {
413962306a36Sopenharmony_ci		cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
414062306a36Sopenharmony_ci						sizeof(struct be_cmd_resp_hdr));
414162306a36Sopenharmony_ci
414262306a36Sopenharmony_ci		for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) {
414362306a36Sopenharmony_ci			if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
414462306a36Sopenharmony_ci				level = cfgs->module[0].trace_lvl[j].dbg_lvl;
414562306a36Sopenharmony_ci		}
414662306a36Sopenharmony_ci	}
414762306a36Sopenharmony_ci	dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va,
414862306a36Sopenharmony_ci			  extfat_cmd.dma);
414962306a36Sopenharmony_cierr:
415062306a36Sopenharmony_ci	return level;
415162306a36Sopenharmony_ci}
415262306a36Sopenharmony_ci
415362306a36Sopenharmony_ciint be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
415462306a36Sopenharmony_ci				   struct be_dma_mem *cmd)
415562306a36Sopenharmony_ci{
415662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
415762306a36Sopenharmony_ci	struct be_cmd_req_get_ext_fat_caps *req;
415862306a36Sopenharmony_ci	int status;
415962306a36Sopenharmony_ci
416062306a36Sopenharmony_ci	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_EXT_FAT_CAPABILITIES,
416162306a36Sopenharmony_ci			    CMD_SUBSYSTEM_COMMON))
416262306a36Sopenharmony_ci		return -EPERM;
416362306a36Sopenharmony_ci
416462306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
416562306a36Sopenharmony_ci		return -1;
416662306a36Sopenharmony_ci
416762306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
416862306a36Sopenharmony_ci	if (!wrb) {
416962306a36Sopenharmony_ci		status = -EBUSY;
417062306a36Sopenharmony_ci		goto err;
417162306a36Sopenharmony_ci	}
417262306a36Sopenharmony_ci
417362306a36Sopenharmony_ci	req = cmd->va;
417462306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
417562306a36Sopenharmony_ci			       OPCODE_COMMON_GET_EXT_FAT_CAPABILITIES,
417662306a36Sopenharmony_ci			       cmd->size, wrb, cmd);
417762306a36Sopenharmony_ci	req->parameter_type = cpu_to_le32(1);
417862306a36Sopenharmony_ci
417962306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
418062306a36Sopenharmony_cierr:
418162306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
418262306a36Sopenharmony_ci	return status;
418362306a36Sopenharmony_ci}
418462306a36Sopenharmony_ci
418562306a36Sopenharmony_ciint be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
418662306a36Sopenharmony_ci				   struct be_dma_mem *cmd,
418762306a36Sopenharmony_ci				   struct be_fat_conf_params *configs)
418862306a36Sopenharmony_ci{
418962306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
419062306a36Sopenharmony_ci	struct be_cmd_req_set_ext_fat_caps *req;
419162306a36Sopenharmony_ci	int status;
419262306a36Sopenharmony_ci
419362306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
419462306a36Sopenharmony_ci
419562306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
419662306a36Sopenharmony_ci	if (!wrb) {
419762306a36Sopenharmony_ci		status = -EBUSY;
419862306a36Sopenharmony_ci		goto err;
419962306a36Sopenharmony_ci	}
420062306a36Sopenharmony_ci
420162306a36Sopenharmony_ci	req = cmd->va;
420262306a36Sopenharmony_ci	memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params));
420362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
420462306a36Sopenharmony_ci			       OPCODE_COMMON_SET_EXT_FAT_CAPABILITIES,
420562306a36Sopenharmony_ci			       cmd->size, wrb, cmd);
420662306a36Sopenharmony_ci
420762306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
420862306a36Sopenharmony_cierr:
420962306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
421062306a36Sopenharmony_ci	return status;
421162306a36Sopenharmony_ci}
421262306a36Sopenharmony_ci
421362306a36Sopenharmony_ciint be_cmd_query_port_name(struct be_adapter *adapter)
421462306a36Sopenharmony_ci{
421562306a36Sopenharmony_ci	struct be_cmd_req_get_port_name *req;
421662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
421762306a36Sopenharmony_ci	int status;
421862306a36Sopenharmony_ci
421962306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
422062306a36Sopenharmony_ci		return -1;
422162306a36Sopenharmony_ci
422262306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
422362306a36Sopenharmony_ci	req = embedded_payload(wrb);
422462306a36Sopenharmony_ci
422562306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
422662306a36Sopenharmony_ci			       OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb,
422762306a36Sopenharmony_ci			       NULL);
422862306a36Sopenharmony_ci	if (!BEx_chip(adapter))
422962306a36Sopenharmony_ci		req->hdr.version = 1;
423062306a36Sopenharmony_ci
423162306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
423262306a36Sopenharmony_ci	if (!status) {
423362306a36Sopenharmony_ci		struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb);
423462306a36Sopenharmony_ci
423562306a36Sopenharmony_ci		adapter->port_name = resp->port_name[adapter->hba_port_num];
423662306a36Sopenharmony_ci	} else {
423762306a36Sopenharmony_ci		adapter->port_name = adapter->hba_port_num + '0';
423862306a36Sopenharmony_ci	}
423962306a36Sopenharmony_ci
424062306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
424162306a36Sopenharmony_ci	return status;
424262306a36Sopenharmony_ci}
424362306a36Sopenharmony_ci
424462306a36Sopenharmony_ci/* When more than 1 NIC descriptor is present in the descriptor list,
424562306a36Sopenharmony_ci * the caller must specify the pf_num to obtain the NIC descriptor
424662306a36Sopenharmony_ci * corresponding to its pci function.
424762306a36Sopenharmony_ci * get_vft must be true when the caller wants the VF-template desc of the
424862306a36Sopenharmony_ci * PF-pool.
424962306a36Sopenharmony_ci * The pf_num should be set to PF_NUM_IGNORE when the caller knows
425062306a36Sopenharmony_ci * that only it's NIC descriptor is present in the descriptor list.
425162306a36Sopenharmony_ci */
425262306a36Sopenharmony_cistatic struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
425362306a36Sopenharmony_ci					       bool get_vft, u8 pf_num)
425462306a36Sopenharmony_ci{
425562306a36Sopenharmony_ci	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
425662306a36Sopenharmony_ci	struct be_nic_res_desc *nic;
425762306a36Sopenharmony_ci	int i;
425862306a36Sopenharmony_ci
425962306a36Sopenharmony_ci	for (i = 0; i < desc_count; i++) {
426062306a36Sopenharmony_ci		if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
426162306a36Sopenharmony_ci		    hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) {
426262306a36Sopenharmony_ci			nic = (struct be_nic_res_desc *)hdr;
426362306a36Sopenharmony_ci
426462306a36Sopenharmony_ci			if ((pf_num == PF_NUM_IGNORE ||
426562306a36Sopenharmony_ci			     nic->pf_num == pf_num) &&
426662306a36Sopenharmony_ci			    (!get_vft || nic->flags & BIT(VFT_SHIFT)))
426762306a36Sopenharmony_ci				return nic;
426862306a36Sopenharmony_ci		}
426962306a36Sopenharmony_ci		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
427062306a36Sopenharmony_ci		hdr = (void *)hdr + hdr->desc_len;
427162306a36Sopenharmony_ci	}
427262306a36Sopenharmony_ci	return NULL;
427362306a36Sopenharmony_ci}
427462306a36Sopenharmony_ci
427562306a36Sopenharmony_cistatic struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count,
427662306a36Sopenharmony_ci					       u8 pf_num)
427762306a36Sopenharmony_ci{
427862306a36Sopenharmony_ci	return be_get_nic_desc(buf, desc_count, true, pf_num);
427962306a36Sopenharmony_ci}
428062306a36Sopenharmony_ci
428162306a36Sopenharmony_cistatic struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count,
428262306a36Sopenharmony_ci						    u8 pf_num)
428362306a36Sopenharmony_ci{
428462306a36Sopenharmony_ci	return be_get_nic_desc(buf, desc_count, false, pf_num);
428562306a36Sopenharmony_ci}
428662306a36Sopenharmony_ci
428762306a36Sopenharmony_cistatic struct be_pcie_res_desc *be_get_pcie_desc(u8 *buf, u32 desc_count,
428862306a36Sopenharmony_ci						 u8 pf_num)
428962306a36Sopenharmony_ci{
429062306a36Sopenharmony_ci	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
429162306a36Sopenharmony_ci	struct be_pcie_res_desc *pcie;
429262306a36Sopenharmony_ci	int i;
429362306a36Sopenharmony_ci
429462306a36Sopenharmony_ci	for (i = 0; i < desc_count; i++) {
429562306a36Sopenharmony_ci		if (hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 ||
429662306a36Sopenharmony_ci		    hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1) {
429762306a36Sopenharmony_ci			pcie = (struct be_pcie_res_desc *)hdr;
429862306a36Sopenharmony_ci			if (pcie->pf_num == pf_num)
429962306a36Sopenharmony_ci				return pcie;
430062306a36Sopenharmony_ci		}
430162306a36Sopenharmony_ci
430262306a36Sopenharmony_ci		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
430362306a36Sopenharmony_ci		hdr = (void *)hdr + hdr->desc_len;
430462306a36Sopenharmony_ci	}
430562306a36Sopenharmony_ci	return NULL;
430662306a36Sopenharmony_ci}
430762306a36Sopenharmony_ci
430862306a36Sopenharmony_cistatic struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
430962306a36Sopenharmony_ci{
431062306a36Sopenharmony_ci	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
431162306a36Sopenharmony_ci	int i;
431262306a36Sopenharmony_ci
431362306a36Sopenharmony_ci	for (i = 0; i < desc_count; i++) {
431462306a36Sopenharmony_ci		if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
431562306a36Sopenharmony_ci			return (struct be_port_res_desc *)hdr;
431662306a36Sopenharmony_ci
431762306a36Sopenharmony_ci		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
431862306a36Sopenharmony_ci		hdr = (void *)hdr + hdr->desc_len;
431962306a36Sopenharmony_ci	}
432062306a36Sopenharmony_ci	return NULL;
432162306a36Sopenharmony_ci}
432262306a36Sopenharmony_ci
432362306a36Sopenharmony_cistatic void be_copy_nic_desc(struct be_resources *res,
432462306a36Sopenharmony_ci			     struct be_nic_res_desc *desc)
432562306a36Sopenharmony_ci{
432662306a36Sopenharmony_ci	res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count);
432762306a36Sopenharmony_ci	res->max_vlans = le16_to_cpu(desc->vlan_count);
432862306a36Sopenharmony_ci	res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
432962306a36Sopenharmony_ci	res->max_tx_qs = le16_to_cpu(desc->txq_count);
433062306a36Sopenharmony_ci	res->max_rss_qs = le16_to_cpu(desc->rssq_count);
433162306a36Sopenharmony_ci	res->max_rx_qs = le16_to_cpu(desc->rq_count);
433262306a36Sopenharmony_ci	res->max_evt_qs = le16_to_cpu(desc->eq_count);
433362306a36Sopenharmony_ci	res->max_cq_count = le16_to_cpu(desc->cq_count);
433462306a36Sopenharmony_ci	res->max_iface_count = le16_to_cpu(desc->iface_count);
433562306a36Sopenharmony_ci	res->max_mcc_count = le16_to_cpu(desc->mcc_count);
433662306a36Sopenharmony_ci	/* Clear flags that driver is not interested in */
433762306a36Sopenharmony_ci	res->if_cap_flags = le32_to_cpu(desc->cap_flags) &
433862306a36Sopenharmony_ci				BE_IF_CAP_FLAGS_WANT;
433962306a36Sopenharmony_ci}
434062306a36Sopenharmony_ci
434162306a36Sopenharmony_ci/* Uses Mbox */
434262306a36Sopenharmony_ciint be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
434362306a36Sopenharmony_ci{
434462306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
434562306a36Sopenharmony_ci	struct be_cmd_req_get_func_config *req;
434662306a36Sopenharmony_ci	int status;
434762306a36Sopenharmony_ci	struct be_dma_mem cmd;
434862306a36Sopenharmony_ci
434962306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
435062306a36Sopenharmony_ci		return -1;
435162306a36Sopenharmony_ci
435262306a36Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
435362306a36Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_resp_get_func_config);
435462306a36Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
435562306a36Sopenharmony_ci				    GFP_ATOMIC);
435662306a36Sopenharmony_ci	if (!cmd.va) {
435762306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
435862306a36Sopenharmony_ci		status = -ENOMEM;
435962306a36Sopenharmony_ci		goto err;
436062306a36Sopenharmony_ci	}
436162306a36Sopenharmony_ci
436262306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
436362306a36Sopenharmony_ci	if (!wrb) {
436462306a36Sopenharmony_ci		status = -EBUSY;
436562306a36Sopenharmony_ci		goto err;
436662306a36Sopenharmony_ci	}
436762306a36Sopenharmony_ci
436862306a36Sopenharmony_ci	req = cmd.va;
436962306a36Sopenharmony_ci
437062306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
437162306a36Sopenharmony_ci			       OPCODE_COMMON_GET_FUNC_CONFIG,
437262306a36Sopenharmony_ci			       cmd.size, wrb, &cmd);
437362306a36Sopenharmony_ci
437462306a36Sopenharmony_ci	if (skyhawk_chip(adapter))
437562306a36Sopenharmony_ci		req->hdr.version = 1;
437662306a36Sopenharmony_ci
437762306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
437862306a36Sopenharmony_ci	if (!status) {
437962306a36Sopenharmony_ci		struct be_cmd_resp_get_func_config *resp = cmd.va;
438062306a36Sopenharmony_ci		u32 desc_count = le32_to_cpu(resp->desc_count);
438162306a36Sopenharmony_ci		struct be_nic_res_desc *desc;
438262306a36Sopenharmony_ci
438362306a36Sopenharmony_ci		/* GET_FUNC_CONFIG returns resource descriptors of the
438462306a36Sopenharmony_ci		 * current function only. So, pf_num should be set to
438562306a36Sopenharmony_ci		 * PF_NUM_IGNORE.
438662306a36Sopenharmony_ci		 */
438762306a36Sopenharmony_ci		desc = be_get_func_nic_desc(resp->func_param, desc_count,
438862306a36Sopenharmony_ci					    PF_NUM_IGNORE);
438962306a36Sopenharmony_ci		if (!desc) {
439062306a36Sopenharmony_ci			status = -EINVAL;
439162306a36Sopenharmony_ci			goto err;
439262306a36Sopenharmony_ci		}
439362306a36Sopenharmony_ci
439462306a36Sopenharmony_ci		/* Store pf_num & vf_num for later use in GET_PROFILE_CONFIG */
439562306a36Sopenharmony_ci		adapter->pf_num = desc->pf_num;
439662306a36Sopenharmony_ci		adapter->vf_num = desc->vf_num;
439762306a36Sopenharmony_ci
439862306a36Sopenharmony_ci		if (res)
439962306a36Sopenharmony_ci			be_copy_nic_desc(res, desc);
440062306a36Sopenharmony_ci	}
440162306a36Sopenharmony_cierr:
440262306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
440362306a36Sopenharmony_ci	if (cmd.va)
440462306a36Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
440562306a36Sopenharmony_ci				  cmd.dma);
440662306a36Sopenharmony_ci	return status;
440762306a36Sopenharmony_ci}
440862306a36Sopenharmony_ci
440962306a36Sopenharmony_ci/* This routine returns a list of all the NIC PF_nums in the adapter */
441062306a36Sopenharmony_cistatic u16 be_get_nic_pf_num_list(u8 *buf, u32 desc_count, u16 *nic_pf_nums)
441162306a36Sopenharmony_ci{
441262306a36Sopenharmony_ci	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
441362306a36Sopenharmony_ci	struct be_pcie_res_desc *pcie = NULL;
441462306a36Sopenharmony_ci	int i;
441562306a36Sopenharmony_ci	u16 nic_pf_count = 0;
441662306a36Sopenharmony_ci
441762306a36Sopenharmony_ci	for (i = 0; i < desc_count; i++) {
441862306a36Sopenharmony_ci		if (hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 ||
441962306a36Sopenharmony_ci		    hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1) {
442062306a36Sopenharmony_ci			pcie = (struct be_pcie_res_desc *)hdr;
442162306a36Sopenharmony_ci			if (pcie->pf_state && (pcie->pf_type == MISSION_NIC ||
442262306a36Sopenharmony_ci					       pcie->pf_type == MISSION_RDMA)) {
442362306a36Sopenharmony_ci				nic_pf_nums[nic_pf_count++] = pcie->pf_num;
442462306a36Sopenharmony_ci			}
442562306a36Sopenharmony_ci		}
442662306a36Sopenharmony_ci
442762306a36Sopenharmony_ci		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
442862306a36Sopenharmony_ci		hdr = (void *)hdr + hdr->desc_len;
442962306a36Sopenharmony_ci	}
443062306a36Sopenharmony_ci	return nic_pf_count;
443162306a36Sopenharmony_ci}
443262306a36Sopenharmony_ci
443362306a36Sopenharmony_ci/* Will use MBOX only if MCCQ has not been created */
443462306a36Sopenharmony_ciint be_cmd_get_profile_config(struct be_adapter *adapter,
443562306a36Sopenharmony_ci			      struct be_resources *res,
443662306a36Sopenharmony_ci			      struct be_port_resources *port_res,
443762306a36Sopenharmony_ci			      u8 profile_type, u8 query, u8 domain)
443862306a36Sopenharmony_ci{
443962306a36Sopenharmony_ci	struct be_cmd_resp_get_profile_config *resp;
444062306a36Sopenharmony_ci	struct be_cmd_req_get_profile_config *req;
444162306a36Sopenharmony_ci	struct be_nic_res_desc *vf_res;
444262306a36Sopenharmony_ci	struct be_pcie_res_desc *pcie;
444362306a36Sopenharmony_ci	struct be_port_res_desc *port;
444462306a36Sopenharmony_ci	struct be_nic_res_desc *nic;
444562306a36Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
444662306a36Sopenharmony_ci	struct be_dma_mem cmd;
444762306a36Sopenharmony_ci	u16 desc_count;
444862306a36Sopenharmony_ci	int status;
444962306a36Sopenharmony_ci
445062306a36Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
445162306a36Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
445262306a36Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
445362306a36Sopenharmony_ci				    GFP_ATOMIC);
445462306a36Sopenharmony_ci	if (!cmd.va)
445562306a36Sopenharmony_ci		return -ENOMEM;
445662306a36Sopenharmony_ci
445762306a36Sopenharmony_ci	req = cmd.va;
445862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
445962306a36Sopenharmony_ci			       OPCODE_COMMON_GET_PROFILE_CONFIG,
446062306a36Sopenharmony_ci			       cmd.size, &wrb, &cmd);
446162306a36Sopenharmony_ci
446262306a36Sopenharmony_ci	if (!lancer_chip(adapter))
446362306a36Sopenharmony_ci		req->hdr.version = 1;
446462306a36Sopenharmony_ci	req->type = profile_type;
446562306a36Sopenharmony_ci	req->hdr.domain = domain;
446662306a36Sopenharmony_ci
446762306a36Sopenharmony_ci	/* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the
446862306a36Sopenharmony_ci	 * descriptors with all bits set to "1" for the fields which can be
446962306a36Sopenharmony_ci	 * modified using SET_PROFILE_CONFIG cmd.
447062306a36Sopenharmony_ci	 */
447162306a36Sopenharmony_ci	if (query == RESOURCE_MODIFIABLE)
447262306a36Sopenharmony_ci		req->type |= QUERY_MODIFIABLE_FIELDS_TYPE;
447362306a36Sopenharmony_ci
447462306a36Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
447562306a36Sopenharmony_ci	if (status)
447662306a36Sopenharmony_ci		goto err;
447762306a36Sopenharmony_ci
447862306a36Sopenharmony_ci	resp = cmd.va;
447962306a36Sopenharmony_ci	desc_count = le16_to_cpu(resp->desc_count);
448062306a36Sopenharmony_ci
448162306a36Sopenharmony_ci	if (port_res) {
448262306a36Sopenharmony_ci		u16 nic_pf_cnt = 0, i;
448362306a36Sopenharmony_ci		u16 nic_pf_num_list[MAX_NIC_FUNCS];
448462306a36Sopenharmony_ci
448562306a36Sopenharmony_ci		nic_pf_cnt = be_get_nic_pf_num_list(resp->func_param,
448662306a36Sopenharmony_ci						    desc_count,
448762306a36Sopenharmony_ci						    nic_pf_num_list);
448862306a36Sopenharmony_ci
448962306a36Sopenharmony_ci		for (i = 0; i < nic_pf_cnt; i++) {
449062306a36Sopenharmony_ci			nic = be_get_func_nic_desc(resp->func_param, desc_count,
449162306a36Sopenharmony_ci						   nic_pf_num_list[i]);
449262306a36Sopenharmony_ci			if (nic->link_param == adapter->port_num) {
449362306a36Sopenharmony_ci				port_res->nic_pfs++;
449462306a36Sopenharmony_ci				pcie = be_get_pcie_desc(resp->func_param,
449562306a36Sopenharmony_ci							desc_count,
449662306a36Sopenharmony_ci							nic_pf_num_list[i]);
449762306a36Sopenharmony_ci				port_res->max_vfs += le16_to_cpu(pcie->num_vfs);
449862306a36Sopenharmony_ci			}
449962306a36Sopenharmony_ci		}
450062306a36Sopenharmony_ci		goto err;
450162306a36Sopenharmony_ci	}
450262306a36Sopenharmony_ci
450362306a36Sopenharmony_ci	pcie = be_get_pcie_desc(resp->func_param, desc_count,
450462306a36Sopenharmony_ci				adapter->pf_num);
450562306a36Sopenharmony_ci	if (pcie)
450662306a36Sopenharmony_ci		res->max_vfs = le16_to_cpu(pcie->num_vfs);
450762306a36Sopenharmony_ci
450862306a36Sopenharmony_ci	port = be_get_port_desc(resp->func_param, desc_count);
450962306a36Sopenharmony_ci	if (port)
451062306a36Sopenharmony_ci		adapter->mc_type = port->mc_type;
451162306a36Sopenharmony_ci
451262306a36Sopenharmony_ci	nic = be_get_func_nic_desc(resp->func_param, desc_count,
451362306a36Sopenharmony_ci				   adapter->pf_num);
451462306a36Sopenharmony_ci	if (nic)
451562306a36Sopenharmony_ci		be_copy_nic_desc(res, nic);
451662306a36Sopenharmony_ci
451762306a36Sopenharmony_ci	vf_res = be_get_vft_desc(resp->func_param, desc_count,
451862306a36Sopenharmony_ci				 adapter->pf_num);
451962306a36Sopenharmony_ci	if (vf_res)
452062306a36Sopenharmony_ci		res->vf_if_cap_flags = vf_res->cap_flags;
452162306a36Sopenharmony_cierr:
452262306a36Sopenharmony_ci	if (cmd.va)
452362306a36Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
452462306a36Sopenharmony_ci				  cmd.dma);
452562306a36Sopenharmony_ci	return status;
452662306a36Sopenharmony_ci}
452762306a36Sopenharmony_ci
452862306a36Sopenharmony_ci/* Will use MBOX only if MCCQ has not been created */
452962306a36Sopenharmony_cistatic int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
453062306a36Sopenharmony_ci				     int size, int count, u8 version, u8 domain)
453162306a36Sopenharmony_ci{
453262306a36Sopenharmony_ci	struct be_cmd_req_set_profile_config *req;
453362306a36Sopenharmony_ci	struct be_mcc_wrb wrb = {0};
453462306a36Sopenharmony_ci	struct be_dma_mem cmd;
453562306a36Sopenharmony_ci	int status;
453662306a36Sopenharmony_ci
453762306a36Sopenharmony_ci	memset(&cmd, 0, sizeof(struct be_dma_mem));
453862306a36Sopenharmony_ci	cmd.size = sizeof(struct be_cmd_req_set_profile_config);
453962306a36Sopenharmony_ci	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
454062306a36Sopenharmony_ci				    GFP_ATOMIC);
454162306a36Sopenharmony_ci	if (!cmd.va)
454262306a36Sopenharmony_ci		return -ENOMEM;
454362306a36Sopenharmony_ci
454462306a36Sopenharmony_ci	req = cmd.va;
454562306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
454662306a36Sopenharmony_ci			       OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size,
454762306a36Sopenharmony_ci			       &wrb, &cmd);
454862306a36Sopenharmony_ci	req->hdr.version = version;
454962306a36Sopenharmony_ci	req->hdr.domain = domain;
455062306a36Sopenharmony_ci	req->desc_count = cpu_to_le32(count);
455162306a36Sopenharmony_ci	memcpy(req->desc, desc, size);
455262306a36Sopenharmony_ci
455362306a36Sopenharmony_ci	status = be_cmd_notify_wait(adapter, &wrb);
455462306a36Sopenharmony_ci
455562306a36Sopenharmony_ci	if (cmd.va)
455662306a36Sopenharmony_ci		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
455762306a36Sopenharmony_ci				  cmd.dma);
455862306a36Sopenharmony_ci	return status;
455962306a36Sopenharmony_ci}
456062306a36Sopenharmony_ci
456162306a36Sopenharmony_ci/* Mark all fields invalid */
456262306a36Sopenharmony_cistatic void be_reset_nic_desc(struct be_nic_res_desc *nic)
456362306a36Sopenharmony_ci{
456462306a36Sopenharmony_ci	memset(nic, 0, sizeof(*nic));
456562306a36Sopenharmony_ci	nic->unicast_mac_count = 0xFFFF;
456662306a36Sopenharmony_ci	nic->mcc_count = 0xFFFF;
456762306a36Sopenharmony_ci	nic->vlan_count = 0xFFFF;
456862306a36Sopenharmony_ci	nic->mcast_mac_count = 0xFFFF;
456962306a36Sopenharmony_ci	nic->txq_count = 0xFFFF;
457062306a36Sopenharmony_ci	nic->rq_count = 0xFFFF;
457162306a36Sopenharmony_ci	nic->rssq_count = 0xFFFF;
457262306a36Sopenharmony_ci	nic->lro_count = 0xFFFF;
457362306a36Sopenharmony_ci	nic->cq_count = 0xFFFF;
457462306a36Sopenharmony_ci	nic->toe_conn_count = 0xFFFF;
457562306a36Sopenharmony_ci	nic->eq_count = 0xFFFF;
457662306a36Sopenharmony_ci	nic->iface_count = 0xFFFF;
457762306a36Sopenharmony_ci	nic->link_param = 0xFF;
457862306a36Sopenharmony_ci	nic->channel_id_param = cpu_to_le16(0xF000);
457962306a36Sopenharmony_ci	nic->acpi_params = 0xFF;
458062306a36Sopenharmony_ci	nic->wol_param = 0x0F;
458162306a36Sopenharmony_ci	nic->tunnel_iface_count = 0xFFFF;
458262306a36Sopenharmony_ci	nic->direct_tenant_iface_count = 0xFFFF;
458362306a36Sopenharmony_ci	nic->bw_min = 0xFFFFFFFF;
458462306a36Sopenharmony_ci	nic->bw_max = 0xFFFFFFFF;
458562306a36Sopenharmony_ci}
458662306a36Sopenharmony_ci
458762306a36Sopenharmony_ci/* Mark all fields invalid */
458862306a36Sopenharmony_cistatic void be_reset_pcie_desc(struct be_pcie_res_desc *pcie)
458962306a36Sopenharmony_ci{
459062306a36Sopenharmony_ci	memset(pcie, 0, sizeof(*pcie));
459162306a36Sopenharmony_ci	pcie->sriov_state = 0xFF;
459262306a36Sopenharmony_ci	pcie->pf_state = 0xFF;
459362306a36Sopenharmony_ci	pcie->pf_type = 0xFF;
459462306a36Sopenharmony_ci	pcie->num_vfs = 0xFFFF;
459562306a36Sopenharmony_ci}
459662306a36Sopenharmony_ci
459762306a36Sopenharmony_ciint be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
459862306a36Sopenharmony_ci		      u8 domain)
459962306a36Sopenharmony_ci{
460062306a36Sopenharmony_ci	struct be_nic_res_desc nic_desc;
460162306a36Sopenharmony_ci	u32 bw_percent;
460262306a36Sopenharmony_ci	u16 version = 0;
460362306a36Sopenharmony_ci
460462306a36Sopenharmony_ci	if (BE3_chip(adapter))
460562306a36Sopenharmony_ci		return be_cmd_set_qos(adapter, max_rate / 10, domain);
460662306a36Sopenharmony_ci
460762306a36Sopenharmony_ci	be_reset_nic_desc(&nic_desc);
460862306a36Sopenharmony_ci	nic_desc.pf_num = adapter->pf_num;
460962306a36Sopenharmony_ci	nic_desc.vf_num = domain;
461062306a36Sopenharmony_ci	nic_desc.bw_min = 0;
461162306a36Sopenharmony_ci	if (lancer_chip(adapter)) {
461262306a36Sopenharmony_ci		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
461362306a36Sopenharmony_ci		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
461462306a36Sopenharmony_ci		nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
461562306a36Sopenharmony_ci					(1 << NOSV_SHIFT);
461662306a36Sopenharmony_ci		nic_desc.bw_max = cpu_to_le32(max_rate / 10);
461762306a36Sopenharmony_ci	} else {
461862306a36Sopenharmony_ci		version = 1;
461962306a36Sopenharmony_ci		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
462062306a36Sopenharmony_ci		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
462162306a36Sopenharmony_ci		nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
462262306a36Sopenharmony_ci		bw_percent = max_rate ? (max_rate * 100) / link_speed : 100;
462362306a36Sopenharmony_ci		nic_desc.bw_max = cpu_to_le32(bw_percent);
462462306a36Sopenharmony_ci	}
462562306a36Sopenharmony_ci
462662306a36Sopenharmony_ci	return be_cmd_set_profile_config(adapter, &nic_desc,
462762306a36Sopenharmony_ci					 nic_desc.hdr.desc_len,
462862306a36Sopenharmony_ci					 1, version, domain);
462962306a36Sopenharmony_ci}
463062306a36Sopenharmony_ci
463162306a36Sopenharmony_ciint be_cmd_set_sriov_config(struct be_adapter *adapter,
463262306a36Sopenharmony_ci			    struct be_resources pool_res, u16 num_vfs,
463362306a36Sopenharmony_ci			    struct be_resources *vft_res)
463462306a36Sopenharmony_ci{
463562306a36Sopenharmony_ci	struct {
463662306a36Sopenharmony_ci		struct be_pcie_res_desc pcie;
463762306a36Sopenharmony_ci		struct be_nic_res_desc nic_vft;
463862306a36Sopenharmony_ci	} __packed desc;
463962306a36Sopenharmony_ci
464062306a36Sopenharmony_ci	/* PF PCIE descriptor */
464162306a36Sopenharmony_ci	be_reset_pcie_desc(&desc.pcie);
464262306a36Sopenharmony_ci	desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1;
464362306a36Sopenharmony_ci	desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
464462306a36Sopenharmony_ci	desc.pcie.flags = BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
464562306a36Sopenharmony_ci	desc.pcie.pf_num = adapter->pdev->devfn;
464662306a36Sopenharmony_ci	desc.pcie.sriov_state = num_vfs ? 1 : 0;
464762306a36Sopenharmony_ci	desc.pcie.num_vfs = cpu_to_le16(num_vfs);
464862306a36Sopenharmony_ci
464962306a36Sopenharmony_ci	/* VF NIC Template descriptor */
465062306a36Sopenharmony_ci	be_reset_nic_desc(&desc.nic_vft);
465162306a36Sopenharmony_ci	desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
465262306a36Sopenharmony_ci	desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
465362306a36Sopenharmony_ci	desc.nic_vft.flags = vft_res->flags | BIT(VFT_SHIFT) |
465462306a36Sopenharmony_ci			     BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
465562306a36Sopenharmony_ci	desc.nic_vft.pf_num = adapter->pdev->devfn;
465662306a36Sopenharmony_ci	desc.nic_vft.vf_num = 0;
465762306a36Sopenharmony_ci	desc.nic_vft.cap_flags = cpu_to_le32(vft_res->vf_if_cap_flags);
465862306a36Sopenharmony_ci	desc.nic_vft.rq_count = cpu_to_le16(vft_res->max_rx_qs);
465962306a36Sopenharmony_ci	desc.nic_vft.txq_count = cpu_to_le16(vft_res->max_tx_qs);
466062306a36Sopenharmony_ci	desc.nic_vft.rssq_count = cpu_to_le16(vft_res->max_rss_qs);
466162306a36Sopenharmony_ci	desc.nic_vft.cq_count = cpu_to_le16(vft_res->max_cq_count);
466262306a36Sopenharmony_ci
466362306a36Sopenharmony_ci	if (vft_res->max_uc_mac)
466462306a36Sopenharmony_ci		desc.nic_vft.unicast_mac_count =
466562306a36Sopenharmony_ci					cpu_to_le16(vft_res->max_uc_mac);
466662306a36Sopenharmony_ci	if (vft_res->max_vlans)
466762306a36Sopenharmony_ci		desc.nic_vft.vlan_count = cpu_to_le16(vft_res->max_vlans);
466862306a36Sopenharmony_ci	if (vft_res->max_iface_count)
466962306a36Sopenharmony_ci		desc.nic_vft.iface_count =
467062306a36Sopenharmony_ci				cpu_to_le16(vft_res->max_iface_count);
467162306a36Sopenharmony_ci	if (vft_res->max_mcc_count)
467262306a36Sopenharmony_ci		desc.nic_vft.mcc_count = cpu_to_le16(vft_res->max_mcc_count);
467362306a36Sopenharmony_ci
467462306a36Sopenharmony_ci	return be_cmd_set_profile_config(adapter, &desc,
467562306a36Sopenharmony_ci					 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
467662306a36Sopenharmony_ci}
467762306a36Sopenharmony_ci
467862306a36Sopenharmony_ciint be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
467962306a36Sopenharmony_ci{
468062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
468162306a36Sopenharmony_ci	struct be_cmd_req_manage_iface_filters *req;
468262306a36Sopenharmony_ci	int status;
468362306a36Sopenharmony_ci
468462306a36Sopenharmony_ci	if (iface == 0xFFFFFFFF)
468562306a36Sopenharmony_ci		return -1;
468662306a36Sopenharmony_ci
468762306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
468862306a36Sopenharmony_ci
468962306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
469062306a36Sopenharmony_ci	if (!wrb) {
469162306a36Sopenharmony_ci		status = -EBUSY;
469262306a36Sopenharmony_ci		goto err;
469362306a36Sopenharmony_ci	}
469462306a36Sopenharmony_ci	req = embedded_payload(wrb);
469562306a36Sopenharmony_ci
469662306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
469762306a36Sopenharmony_ci			       OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req),
469862306a36Sopenharmony_ci			       wrb, NULL);
469962306a36Sopenharmony_ci	req->op = op;
470062306a36Sopenharmony_ci	req->target_iface_id = cpu_to_le32(iface);
470162306a36Sopenharmony_ci
470262306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
470362306a36Sopenharmony_cierr:
470462306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
470562306a36Sopenharmony_ci	return status;
470662306a36Sopenharmony_ci}
470762306a36Sopenharmony_ci
470862306a36Sopenharmony_ciint be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port)
470962306a36Sopenharmony_ci{
471062306a36Sopenharmony_ci	struct be_port_res_desc port_desc;
471162306a36Sopenharmony_ci
471262306a36Sopenharmony_ci	memset(&port_desc, 0, sizeof(port_desc));
471362306a36Sopenharmony_ci	port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1;
471462306a36Sopenharmony_ci	port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
471562306a36Sopenharmony_ci	port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
471662306a36Sopenharmony_ci	port_desc.link_num = adapter->hba_port_num;
471762306a36Sopenharmony_ci	if (port) {
471862306a36Sopenharmony_ci		port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) |
471962306a36Sopenharmony_ci					(1 << RCVID_SHIFT);
472062306a36Sopenharmony_ci		port_desc.nv_port = swab16(port);
472162306a36Sopenharmony_ci	} else {
472262306a36Sopenharmony_ci		port_desc.nv_flags = NV_TYPE_DISABLED;
472362306a36Sopenharmony_ci		port_desc.nv_port = 0;
472462306a36Sopenharmony_ci	}
472562306a36Sopenharmony_ci
472662306a36Sopenharmony_ci	return be_cmd_set_profile_config(adapter, &port_desc,
472762306a36Sopenharmony_ci					 RESOURCE_DESC_SIZE_V1, 1, 1, 0);
472862306a36Sopenharmony_ci}
472962306a36Sopenharmony_ci
473062306a36Sopenharmony_ciint be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
473162306a36Sopenharmony_ci		     int vf_num)
473262306a36Sopenharmony_ci{
473362306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
473462306a36Sopenharmony_ci	struct be_cmd_req_get_iface_list *req;
473562306a36Sopenharmony_ci	struct be_cmd_resp_get_iface_list *resp;
473662306a36Sopenharmony_ci	int status;
473762306a36Sopenharmony_ci
473862306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
473962306a36Sopenharmony_ci
474062306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
474162306a36Sopenharmony_ci	if (!wrb) {
474262306a36Sopenharmony_ci		status = -EBUSY;
474362306a36Sopenharmony_ci		goto err;
474462306a36Sopenharmony_ci	}
474562306a36Sopenharmony_ci	req = embedded_payload(wrb);
474662306a36Sopenharmony_ci
474762306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
474862306a36Sopenharmony_ci			       OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp),
474962306a36Sopenharmony_ci			       wrb, NULL);
475062306a36Sopenharmony_ci	req->hdr.domain = vf_num + 1;
475162306a36Sopenharmony_ci
475262306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
475362306a36Sopenharmony_ci	if (!status) {
475462306a36Sopenharmony_ci		resp = (struct be_cmd_resp_get_iface_list *)req;
475562306a36Sopenharmony_ci		vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id);
475662306a36Sopenharmony_ci	}
475762306a36Sopenharmony_ci
475862306a36Sopenharmony_cierr:
475962306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
476062306a36Sopenharmony_ci	return status;
476162306a36Sopenharmony_ci}
476262306a36Sopenharmony_ci
476362306a36Sopenharmony_cistatic int lancer_wait_idle(struct be_adapter *adapter)
476462306a36Sopenharmony_ci{
476562306a36Sopenharmony_ci#define SLIPORT_IDLE_TIMEOUT 30
476662306a36Sopenharmony_ci	u32 reg_val;
476762306a36Sopenharmony_ci	int status = 0, i;
476862306a36Sopenharmony_ci
476962306a36Sopenharmony_ci	for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
477062306a36Sopenharmony_ci		reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
477162306a36Sopenharmony_ci		if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
477262306a36Sopenharmony_ci			break;
477362306a36Sopenharmony_ci
477462306a36Sopenharmony_ci		ssleep(1);
477562306a36Sopenharmony_ci	}
477662306a36Sopenharmony_ci
477762306a36Sopenharmony_ci	if (i == SLIPORT_IDLE_TIMEOUT)
477862306a36Sopenharmony_ci		status = -1;
477962306a36Sopenharmony_ci
478062306a36Sopenharmony_ci	return status;
478162306a36Sopenharmony_ci}
478262306a36Sopenharmony_ci
478362306a36Sopenharmony_ciint lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
478462306a36Sopenharmony_ci{
478562306a36Sopenharmony_ci	int status = 0;
478662306a36Sopenharmony_ci
478762306a36Sopenharmony_ci	status = lancer_wait_idle(adapter);
478862306a36Sopenharmony_ci	if (status)
478962306a36Sopenharmony_ci		return status;
479062306a36Sopenharmony_ci
479162306a36Sopenharmony_ci	iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
479262306a36Sopenharmony_ci
479362306a36Sopenharmony_ci	return status;
479462306a36Sopenharmony_ci}
479562306a36Sopenharmony_ci
479662306a36Sopenharmony_ci/* Routine to check whether dump image is present or not */
479762306a36Sopenharmony_cibool dump_present(struct be_adapter *adapter)
479862306a36Sopenharmony_ci{
479962306a36Sopenharmony_ci	u32 sliport_status = 0;
480062306a36Sopenharmony_ci
480162306a36Sopenharmony_ci	sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
480262306a36Sopenharmony_ci	return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
480362306a36Sopenharmony_ci}
480462306a36Sopenharmony_ci
480562306a36Sopenharmony_ciint lancer_initiate_dump(struct be_adapter *adapter)
480662306a36Sopenharmony_ci{
480762306a36Sopenharmony_ci	struct device *dev = &adapter->pdev->dev;
480862306a36Sopenharmony_ci	int status;
480962306a36Sopenharmony_ci
481062306a36Sopenharmony_ci	if (dump_present(adapter)) {
481162306a36Sopenharmony_ci		dev_info(dev, "Previous dump not cleared, not forcing dump\n");
481262306a36Sopenharmony_ci		return -EEXIST;
481362306a36Sopenharmony_ci	}
481462306a36Sopenharmony_ci
481562306a36Sopenharmony_ci	/* give firmware reset and diagnostic dump */
481662306a36Sopenharmony_ci	status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
481762306a36Sopenharmony_ci				     PHYSDEV_CONTROL_DD_MASK);
481862306a36Sopenharmony_ci	if (status < 0) {
481962306a36Sopenharmony_ci		dev_err(dev, "FW reset failed\n");
482062306a36Sopenharmony_ci		return status;
482162306a36Sopenharmony_ci	}
482262306a36Sopenharmony_ci
482362306a36Sopenharmony_ci	status = lancer_wait_idle(adapter);
482462306a36Sopenharmony_ci	if (status)
482562306a36Sopenharmony_ci		return status;
482662306a36Sopenharmony_ci
482762306a36Sopenharmony_ci	if (!dump_present(adapter)) {
482862306a36Sopenharmony_ci		dev_err(dev, "FW dump not generated\n");
482962306a36Sopenharmony_ci		return -EIO;
483062306a36Sopenharmony_ci	}
483162306a36Sopenharmony_ci
483262306a36Sopenharmony_ci	return 0;
483362306a36Sopenharmony_ci}
483462306a36Sopenharmony_ci
483562306a36Sopenharmony_ciint lancer_delete_dump(struct be_adapter *adapter)
483662306a36Sopenharmony_ci{
483762306a36Sopenharmony_ci	int status;
483862306a36Sopenharmony_ci
483962306a36Sopenharmony_ci	status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE);
484062306a36Sopenharmony_ci	return be_cmd_status(status);
484162306a36Sopenharmony_ci}
484262306a36Sopenharmony_ci
484362306a36Sopenharmony_ci/* Uses sync mcc */
484462306a36Sopenharmony_ciint be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
484562306a36Sopenharmony_ci{
484662306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
484762306a36Sopenharmony_ci	struct be_cmd_enable_disable_vf *req;
484862306a36Sopenharmony_ci	int status;
484962306a36Sopenharmony_ci
485062306a36Sopenharmony_ci	if (BEx_chip(adapter))
485162306a36Sopenharmony_ci		return 0;
485262306a36Sopenharmony_ci
485362306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
485462306a36Sopenharmony_ci
485562306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
485662306a36Sopenharmony_ci	if (!wrb) {
485762306a36Sopenharmony_ci		status = -EBUSY;
485862306a36Sopenharmony_ci		goto err;
485962306a36Sopenharmony_ci	}
486062306a36Sopenharmony_ci
486162306a36Sopenharmony_ci	req = embedded_payload(wrb);
486262306a36Sopenharmony_ci
486362306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
486462306a36Sopenharmony_ci			       OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
486562306a36Sopenharmony_ci			       wrb, NULL);
486662306a36Sopenharmony_ci
486762306a36Sopenharmony_ci	req->hdr.domain = domain;
486862306a36Sopenharmony_ci	req->enable = 1;
486962306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
487062306a36Sopenharmony_cierr:
487162306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
487262306a36Sopenharmony_ci	return status;
487362306a36Sopenharmony_ci}
487462306a36Sopenharmony_ci
487562306a36Sopenharmony_ciint be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable)
487662306a36Sopenharmony_ci{
487762306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
487862306a36Sopenharmony_ci	struct be_cmd_req_intr_set *req;
487962306a36Sopenharmony_ci	int status;
488062306a36Sopenharmony_ci
488162306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
488262306a36Sopenharmony_ci		return -1;
488362306a36Sopenharmony_ci
488462306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
488562306a36Sopenharmony_ci
488662306a36Sopenharmony_ci	req = embedded_payload(wrb);
488762306a36Sopenharmony_ci
488862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
488962306a36Sopenharmony_ci			       OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req),
489062306a36Sopenharmony_ci			       wrb, NULL);
489162306a36Sopenharmony_ci
489262306a36Sopenharmony_ci	req->intr_enabled = intr_enable;
489362306a36Sopenharmony_ci
489462306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
489562306a36Sopenharmony_ci
489662306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
489762306a36Sopenharmony_ci	return status;
489862306a36Sopenharmony_ci}
489962306a36Sopenharmony_ci
490062306a36Sopenharmony_ci/* Uses MBOX */
490162306a36Sopenharmony_ciint be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id)
490262306a36Sopenharmony_ci{
490362306a36Sopenharmony_ci	struct be_cmd_req_get_active_profile *req;
490462306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
490562306a36Sopenharmony_ci	int status;
490662306a36Sopenharmony_ci
490762306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mbox_lock))
490862306a36Sopenharmony_ci		return -1;
490962306a36Sopenharmony_ci
491062306a36Sopenharmony_ci	wrb = wrb_from_mbox(adapter);
491162306a36Sopenharmony_ci	if (!wrb) {
491262306a36Sopenharmony_ci		status = -EBUSY;
491362306a36Sopenharmony_ci		goto err;
491462306a36Sopenharmony_ci	}
491562306a36Sopenharmony_ci
491662306a36Sopenharmony_ci	req = embedded_payload(wrb);
491762306a36Sopenharmony_ci
491862306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
491962306a36Sopenharmony_ci			       OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req),
492062306a36Sopenharmony_ci			       wrb, NULL);
492162306a36Sopenharmony_ci
492262306a36Sopenharmony_ci	status = be_mbox_notify_wait(adapter);
492362306a36Sopenharmony_ci	if (!status) {
492462306a36Sopenharmony_ci		struct be_cmd_resp_get_active_profile *resp =
492562306a36Sopenharmony_ci							embedded_payload(wrb);
492662306a36Sopenharmony_ci
492762306a36Sopenharmony_ci		*profile_id = le16_to_cpu(resp->active_profile_id);
492862306a36Sopenharmony_ci	}
492962306a36Sopenharmony_ci
493062306a36Sopenharmony_cierr:
493162306a36Sopenharmony_ci	mutex_unlock(&adapter->mbox_lock);
493262306a36Sopenharmony_ci	return status;
493362306a36Sopenharmony_ci}
493462306a36Sopenharmony_ci
493562306a36Sopenharmony_cistatic int
493662306a36Sopenharmony_ci__be_cmd_set_logical_link_config(struct be_adapter *adapter,
493762306a36Sopenharmony_ci				 int link_state, int version, u8 domain)
493862306a36Sopenharmony_ci{
493962306a36Sopenharmony_ci	struct be_cmd_req_set_ll_link *req;
494062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
494162306a36Sopenharmony_ci	u32 link_config = 0;
494262306a36Sopenharmony_ci	int status;
494362306a36Sopenharmony_ci
494462306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
494562306a36Sopenharmony_ci
494662306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
494762306a36Sopenharmony_ci	if (!wrb) {
494862306a36Sopenharmony_ci		status = -EBUSY;
494962306a36Sopenharmony_ci		goto err;
495062306a36Sopenharmony_ci	}
495162306a36Sopenharmony_ci
495262306a36Sopenharmony_ci	req = embedded_payload(wrb);
495362306a36Sopenharmony_ci
495462306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
495562306a36Sopenharmony_ci			       OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG,
495662306a36Sopenharmony_ci			       sizeof(*req), wrb, NULL);
495762306a36Sopenharmony_ci
495862306a36Sopenharmony_ci	req->hdr.version = version;
495962306a36Sopenharmony_ci	req->hdr.domain = domain;
496062306a36Sopenharmony_ci
496162306a36Sopenharmony_ci	if (link_state == IFLA_VF_LINK_STATE_ENABLE ||
496262306a36Sopenharmony_ci	    link_state == IFLA_VF_LINK_STATE_AUTO)
496362306a36Sopenharmony_ci		link_config |= PLINK_ENABLE;
496462306a36Sopenharmony_ci
496562306a36Sopenharmony_ci	if (link_state == IFLA_VF_LINK_STATE_AUTO)
496662306a36Sopenharmony_ci		link_config |= PLINK_TRACK;
496762306a36Sopenharmony_ci
496862306a36Sopenharmony_ci	req->link_config = cpu_to_le32(link_config);
496962306a36Sopenharmony_ci
497062306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
497162306a36Sopenharmony_cierr:
497262306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
497362306a36Sopenharmony_ci	return status;
497462306a36Sopenharmony_ci}
497562306a36Sopenharmony_ci
497662306a36Sopenharmony_ciint be_cmd_set_logical_link_config(struct be_adapter *adapter,
497762306a36Sopenharmony_ci				   int link_state, u8 domain)
497862306a36Sopenharmony_ci{
497962306a36Sopenharmony_ci	int status;
498062306a36Sopenharmony_ci
498162306a36Sopenharmony_ci	if (BE2_chip(adapter))
498262306a36Sopenharmony_ci		return -EOPNOTSUPP;
498362306a36Sopenharmony_ci
498462306a36Sopenharmony_ci	status = __be_cmd_set_logical_link_config(adapter, link_state,
498562306a36Sopenharmony_ci						  2, domain);
498662306a36Sopenharmony_ci
498762306a36Sopenharmony_ci	/* Version 2 of the command will not be recognized by older FW.
498862306a36Sopenharmony_ci	 * On such a failure issue version 1 of the command.
498962306a36Sopenharmony_ci	 */
499062306a36Sopenharmony_ci	if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST)
499162306a36Sopenharmony_ci		status = __be_cmd_set_logical_link_config(adapter, link_state,
499262306a36Sopenharmony_ci							  1, domain);
499362306a36Sopenharmony_ci	return status;
499462306a36Sopenharmony_ci}
499562306a36Sopenharmony_ci
499662306a36Sopenharmony_ciint be_cmd_set_features(struct be_adapter *adapter)
499762306a36Sopenharmony_ci{
499862306a36Sopenharmony_ci	struct be_cmd_resp_set_features *resp;
499962306a36Sopenharmony_ci	struct be_cmd_req_set_features *req;
500062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
500162306a36Sopenharmony_ci	int status;
500262306a36Sopenharmony_ci
500362306a36Sopenharmony_ci	if (mutex_lock_interruptible(&adapter->mcc_lock))
500462306a36Sopenharmony_ci		return -1;
500562306a36Sopenharmony_ci
500662306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
500762306a36Sopenharmony_ci	if (!wrb) {
500862306a36Sopenharmony_ci		status = -EBUSY;
500962306a36Sopenharmony_ci		goto err;
501062306a36Sopenharmony_ci	}
501162306a36Sopenharmony_ci
501262306a36Sopenharmony_ci	req = embedded_payload(wrb);
501362306a36Sopenharmony_ci
501462306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
501562306a36Sopenharmony_ci			       OPCODE_COMMON_SET_FEATURES,
501662306a36Sopenharmony_ci			       sizeof(*req), wrb, NULL);
501762306a36Sopenharmony_ci
501862306a36Sopenharmony_ci	req->features = cpu_to_le32(BE_FEATURE_UE_RECOVERY);
501962306a36Sopenharmony_ci	req->parameter_len = cpu_to_le32(sizeof(struct be_req_ue_recovery));
502062306a36Sopenharmony_ci	req->parameter.req.uer = cpu_to_le32(BE_UE_RECOVERY_UER_MASK);
502162306a36Sopenharmony_ci
502262306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
502362306a36Sopenharmony_ci	if (status)
502462306a36Sopenharmony_ci		goto err;
502562306a36Sopenharmony_ci
502662306a36Sopenharmony_ci	resp = embedded_payload(wrb);
502762306a36Sopenharmony_ci
502862306a36Sopenharmony_ci	adapter->error_recovery.ue_to_poll_time =
502962306a36Sopenharmony_ci		le16_to_cpu(resp->parameter.resp.ue2rp);
503062306a36Sopenharmony_ci	adapter->error_recovery.ue_to_reset_time =
503162306a36Sopenharmony_ci		le16_to_cpu(resp->parameter.resp.ue2sr);
503262306a36Sopenharmony_ci	adapter->error_recovery.recovery_supported = true;
503362306a36Sopenharmony_cierr:
503462306a36Sopenharmony_ci	/* Checking "MCC_STATUS_INVALID_LENGTH" for SKH as FW
503562306a36Sopenharmony_ci	 * returns this error in older firmware versions
503662306a36Sopenharmony_ci	 */
503762306a36Sopenharmony_ci	if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
503862306a36Sopenharmony_ci	    base_status(status) == MCC_STATUS_INVALID_LENGTH)
503962306a36Sopenharmony_ci		dev_info(&adapter->pdev->dev,
504062306a36Sopenharmony_ci			 "Adapter does not support HW error recovery\n");
504162306a36Sopenharmony_ci
504262306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
504362306a36Sopenharmony_ci	return status;
504462306a36Sopenharmony_ci}
504562306a36Sopenharmony_ci
504662306a36Sopenharmony_ciint be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
504762306a36Sopenharmony_ci		    int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
504862306a36Sopenharmony_ci{
504962306a36Sopenharmony_ci	struct be_adapter *adapter = netdev_priv(netdev_handle);
505062306a36Sopenharmony_ci	struct be_mcc_wrb *wrb;
505162306a36Sopenharmony_ci	struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload;
505262306a36Sopenharmony_ci	struct be_cmd_req_hdr *req;
505362306a36Sopenharmony_ci	struct be_cmd_resp_hdr *resp;
505462306a36Sopenharmony_ci	int status;
505562306a36Sopenharmony_ci
505662306a36Sopenharmony_ci	mutex_lock(&adapter->mcc_lock);
505762306a36Sopenharmony_ci
505862306a36Sopenharmony_ci	wrb = wrb_from_mccq(adapter);
505962306a36Sopenharmony_ci	if (!wrb) {
506062306a36Sopenharmony_ci		status = -EBUSY;
506162306a36Sopenharmony_ci		goto err;
506262306a36Sopenharmony_ci	}
506362306a36Sopenharmony_ci	req = embedded_payload(wrb);
506462306a36Sopenharmony_ci	resp = embedded_payload(wrb);
506562306a36Sopenharmony_ci
506662306a36Sopenharmony_ci	be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
506762306a36Sopenharmony_ci			       hdr->opcode, wrb_payload_size, wrb, NULL);
506862306a36Sopenharmony_ci	memcpy(req, wrb_payload, wrb_payload_size);
506962306a36Sopenharmony_ci	be_dws_cpu_to_le(req, wrb_payload_size);
507062306a36Sopenharmony_ci
507162306a36Sopenharmony_ci	status = be_mcc_notify_wait(adapter);
507262306a36Sopenharmony_ci	if (cmd_status)
507362306a36Sopenharmony_ci		*cmd_status = (status & 0xffff);
507462306a36Sopenharmony_ci	if (ext_status)
507562306a36Sopenharmony_ci		*ext_status = 0;
507662306a36Sopenharmony_ci	memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
507762306a36Sopenharmony_ci	be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
507862306a36Sopenharmony_cierr:
507962306a36Sopenharmony_ci	mutex_unlock(&adapter->mcc_lock);
508062306a36Sopenharmony_ci	return status;
508162306a36Sopenharmony_ci}
508262306a36Sopenharmony_ciEXPORT_SYMBOL(be_roce_mcc_cmd);
5083