19aebddd1SJeff Kirsher /*
2d19261b8SVasundhara Volam  * Copyright (C) 2005 - 2015 Emulex
39aebddd1SJeff Kirsher  * All rights reserved.
49aebddd1SJeff Kirsher  *
59aebddd1SJeff Kirsher  * This program is free software; you can redistribute it and/or
69aebddd1SJeff Kirsher  * modify it under the terms of the GNU General Public License version 2
79aebddd1SJeff Kirsher  * as published by the Free Software Foundation.  The full GNU General
89aebddd1SJeff Kirsher  * Public License is included in this distribution in the file called COPYING.
99aebddd1SJeff Kirsher  *
109aebddd1SJeff Kirsher  * Contact Information:
119aebddd1SJeff Kirsher  * linux-drivers@emulex.com
129aebddd1SJeff Kirsher  *
139aebddd1SJeff Kirsher  * Emulex
149aebddd1SJeff Kirsher  * 3333 Susan Street
159aebddd1SJeff Kirsher  * Costa Mesa, CA 92626
169aebddd1SJeff Kirsher  */
179aebddd1SJeff Kirsher 
186a4ab669SParav Pandit #include <linux/module.h>
199aebddd1SJeff Kirsher #include "be.h"
209aebddd1SJeff Kirsher #include "be_cmds.h"
219aebddd1SJeff Kirsher 
2221252377SVasundhara Volam static char *be_port_misconfig_evt_desc[] = {
2321252377SVasundhara Volam 	"A valid SFP module detected",
2421252377SVasundhara Volam 	"Optics faulted/ incorrectly installed/ not installed.",
2521252377SVasundhara Volam 	"Optics of two types installed.",
2621252377SVasundhara Volam 	"Incompatible optics.",
2721252377SVasundhara Volam 	"Unknown port SFP status"
2821252377SVasundhara Volam };
2921252377SVasundhara Volam 
3021252377SVasundhara Volam static char *be_port_misconfig_remedy_desc[] = {
3121252377SVasundhara Volam 	"",
3221252377SVasundhara Volam 	"Reseat optics. If issue not resolved, replace",
3321252377SVasundhara Volam 	"Remove one optic or install matching pair of optics",
3421252377SVasundhara Volam 	"Replace with compatible optics for card to function",
3521252377SVasundhara Volam 	""
3621252377SVasundhara Volam };
3721252377SVasundhara Volam 
38f25b119cSPadmanabh Ratnakar static struct be_cmd_priv_map cmd_priv_map[] = {
39f25b119cSPadmanabh Ratnakar 	{
40f25b119cSPadmanabh Ratnakar 		OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
41f25b119cSPadmanabh Ratnakar 		CMD_SUBSYSTEM_ETH,
42f25b119cSPadmanabh Ratnakar 		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
43f25b119cSPadmanabh Ratnakar 		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
44f25b119cSPadmanabh Ratnakar 	},
45f25b119cSPadmanabh Ratnakar 	{
46f25b119cSPadmanabh Ratnakar 		OPCODE_COMMON_GET_FLOW_CONTROL,
47f25b119cSPadmanabh Ratnakar 		CMD_SUBSYSTEM_COMMON,
48f25b119cSPadmanabh Ratnakar 		BE_PRIV_LNKQUERY | BE_PRIV_VHADM |
49f25b119cSPadmanabh Ratnakar 		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
50f25b119cSPadmanabh Ratnakar 	},
51f25b119cSPadmanabh Ratnakar 	{
52f25b119cSPadmanabh Ratnakar 		OPCODE_COMMON_SET_FLOW_CONTROL,
53f25b119cSPadmanabh Ratnakar 		CMD_SUBSYSTEM_COMMON,
54f25b119cSPadmanabh Ratnakar 		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
55f25b119cSPadmanabh Ratnakar 		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
56f25b119cSPadmanabh Ratnakar 	},
57f25b119cSPadmanabh Ratnakar 	{
58f25b119cSPadmanabh Ratnakar 		OPCODE_ETH_GET_PPORT_STATS,
59f25b119cSPadmanabh Ratnakar 		CMD_SUBSYSTEM_ETH,
60f25b119cSPadmanabh Ratnakar 		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
61f25b119cSPadmanabh Ratnakar 		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
62f25b119cSPadmanabh Ratnakar 	},
63f25b119cSPadmanabh Ratnakar 	{
64f25b119cSPadmanabh Ratnakar 		OPCODE_COMMON_GET_PHY_DETAILS,
65f25b119cSPadmanabh Ratnakar 		CMD_SUBSYSTEM_COMMON,
66f25b119cSPadmanabh Ratnakar 		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
67f25b119cSPadmanabh Ratnakar 		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
682e365b1bSSomnath Kotur 	},
692e365b1bSSomnath Kotur 	{
702e365b1bSSomnath Kotur 		OPCODE_LOWLEVEL_HOST_DDR_DMA,
712e365b1bSSomnath Kotur 		CMD_SUBSYSTEM_LOWLEVEL,
722e365b1bSSomnath Kotur 		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
732e365b1bSSomnath Kotur 	},
742e365b1bSSomnath Kotur 	{
752e365b1bSSomnath Kotur 		OPCODE_LOWLEVEL_LOOPBACK_TEST,
762e365b1bSSomnath Kotur 		CMD_SUBSYSTEM_LOWLEVEL,
772e365b1bSSomnath Kotur 		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
782e365b1bSSomnath Kotur 	},
792e365b1bSSomnath Kotur 	{
802e365b1bSSomnath Kotur 		OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
812e365b1bSSomnath Kotur 		CMD_SUBSYSTEM_LOWLEVEL,
822e365b1bSSomnath Kotur 		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
832e365b1bSSomnath Kotur 	},
84f25b119cSPadmanabh Ratnakar };
85f25b119cSPadmanabh Ratnakar 
86a2cc4e0bSSathya Perla static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, u8 subsystem)
87f25b119cSPadmanabh Ratnakar {
88f25b119cSPadmanabh Ratnakar 	int i;
89f25b119cSPadmanabh Ratnakar 	int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map);
90f25b119cSPadmanabh Ratnakar 	u32 cmd_privileges = adapter->cmd_privileges;
91f25b119cSPadmanabh Ratnakar 
92f25b119cSPadmanabh Ratnakar 	for (i = 0; i < num_entries; i++)
93f25b119cSPadmanabh Ratnakar 		if (opcode == cmd_priv_map[i].opcode &&
94f25b119cSPadmanabh Ratnakar 		    subsystem == cmd_priv_map[i].subsystem)
95f25b119cSPadmanabh Ratnakar 			if (!(cmd_privileges & cmd_priv_map[i].priv_mask))
96f25b119cSPadmanabh Ratnakar 				return false;
97f25b119cSPadmanabh Ratnakar 
98f25b119cSPadmanabh Ratnakar 	return true;
99f25b119cSPadmanabh Ratnakar }
100f25b119cSPadmanabh Ratnakar 
1013de09455SSomnath Kotur static inline void *embedded_payload(struct be_mcc_wrb *wrb)
1023de09455SSomnath Kotur {
1033de09455SSomnath Kotur 	return wrb->payload.embedded_payload;
1043de09455SSomnath Kotur }
1059aebddd1SJeff Kirsher 
106efaa408eSSuresh Reddy static int be_mcc_notify(struct be_adapter *adapter)
1079aebddd1SJeff Kirsher {
1089aebddd1SJeff Kirsher 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
1099aebddd1SJeff Kirsher 	u32 val = 0;
1109aebddd1SJeff Kirsher 
111954f6825SVenkata Duvvuru 	if (be_check_error(adapter, BE_ERROR_ANY))
112efaa408eSSuresh Reddy 		return -EIO;
1139aebddd1SJeff Kirsher 
1149aebddd1SJeff Kirsher 	val |= mccq->id & DB_MCCQ_RING_ID_MASK;
1159aebddd1SJeff Kirsher 	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
1169aebddd1SJeff Kirsher 
1179aebddd1SJeff Kirsher 	wmb();
1189aebddd1SJeff Kirsher 	iowrite32(val, adapter->db + DB_MCCQ_OFFSET);
119efaa408eSSuresh Reddy 
120efaa408eSSuresh Reddy 	return 0;
1219aebddd1SJeff Kirsher }
1229aebddd1SJeff Kirsher 
1239aebddd1SJeff Kirsher /* To check if valid bit is set, check the entire word as we don't know
1249aebddd1SJeff Kirsher  * the endianness of the data (old entry is host endian while a new entry is
1259aebddd1SJeff Kirsher  * little endian) */
1269aebddd1SJeff Kirsher static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
1279aebddd1SJeff Kirsher {
1289e9ff4b7SSathya Perla 	u32 flags;
1299e9ff4b7SSathya Perla 
1309aebddd1SJeff Kirsher 	if (compl->flags != 0) {
1319e9ff4b7SSathya Perla 		flags = le32_to_cpu(compl->flags);
1329e9ff4b7SSathya Perla 		if (flags & CQE_FLAGS_VALID_MASK) {
1339e9ff4b7SSathya Perla 			compl->flags = flags;
1349aebddd1SJeff Kirsher 			return true;
1359aebddd1SJeff Kirsher 		}
1369aebddd1SJeff Kirsher 	}
1379e9ff4b7SSathya Perla 	return false;
1389e9ff4b7SSathya Perla }
1399aebddd1SJeff Kirsher 
1409aebddd1SJeff Kirsher /* Need to reset the entire word that houses the valid bit */
1419aebddd1SJeff Kirsher static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
1429aebddd1SJeff Kirsher {
1439aebddd1SJeff Kirsher 	compl->flags = 0;
1449aebddd1SJeff Kirsher }
1459aebddd1SJeff Kirsher 
146652bf646SPadmanabh Ratnakar static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
147652bf646SPadmanabh Ratnakar {
148652bf646SPadmanabh Ratnakar 	unsigned long addr;
149652bf646SPadmanabh Ratnakar 
150652bf646SPadmanabh Ratnakar 	addr = tag1;
151652bf646SPadmanabh Ratnakar 	addr = ((addr << 16) << 16) | tag0;
152652bf646SPadmanabh Ratnakar 	return (void *)addr;
153652bf646SPadmanabh Ratnakar }
154652bf646SPadmanabh Ratnakar 
1554c60005fSKalesh AP static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status)
1564c60005fSKalesh AP {
1574c60005fSKalesh AP 	if (base_status == MCC_STATUS_NOT_SUPPORTED ||
1584c60005fSKalesh AP 	    base_status == MCC_STATUS_ILLEGAL_REQUEST ||
1594c60005fSKalesh AP 	    addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES ||
16077be8c1cSKalesh AP 	    addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS ||
1614c60005fSKalesh AP 	    (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
1624c60005fSKalesh AP 	    (base_status == MCC_STATUS_ILLEGAL_FIELD ||
1634c60005fSKalesh AP 	     addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH)))
1644c60005fSKalesh AP 		return true;
1654c60005fSKalesh AP 	else
1664c60005fSKalesh AP 		return false;
1674c60005fSKalesh AP }
1684c60005fSKalesh AP 
169559b633fSSathya Perla /* Place holder for all the async MCC cmds wherein the caller is not in a busy
170559b633fSSathya Perla  * loop (has not issued be_mcc_notify_wait())
171559b633fSSathya Perla  */
172559b633fSSathya Perla static void be_async_cmd_process(struct be_adapter *adapter,
173559b633fSSathya Perla 				 struct be_mcc_compl *compl,
174559b633fSSathya Perla 				 struct be_cmd_resp_hdr *resp_hdr)
175559b633fSSathya Perla {
176559b633fSSathya Perla 	enum mcc_base_status base_status = base_status(compl->status);
177559b633fSSathya Perla 	u8 opcode = 0, subsystem = 0;
178559b633fSSathya Perla 
179559b633fSSathya Perla 	if (resp_hdr) {
180559b633fSSathya Perla 		opcode = resp_hdr->opcode;
181559b633fSSathya Perla 		subsystem = resp_hdr->subsystem;
182559b633fSSathya Perla 	}
183559b633fSSathya Perla 
184559b633fSSathya Perla 	if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
185559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
186559b633fSSathya Perla 		complete(&adapter->et_cmd_compl);
187559b633fSSathya Perla 		return;
188559b633fSSathya Perla 	}
189559b633fSSathya Perla 
1909c855975SSuresh Reddy 	if (opcode == OPCODE_LOWLEVEL_SET_LOOPBACK_MODE &&
1919c855975SSuresh Reddy 	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
1929c855975SSuresh Reddy 		complete(&adapter->et_cmd_compl);
1939c855975SSuresh Reddy 		return;
1949c855975SSuresh Reddy 	}
1959c855975SSuresh Reddy 
196559b633fSSathya Perla 	if ((opcode == OPCODE_COMMON_WRITE_FLASHROM ||
197559b633fSSathya Perla 	     opcode == OPCODE_COMMON_WRITE_OBJECT) &&
198559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_COMMON) {
199559b633fSSathya Perla 		adapter->flash_status = compl->status;
200559b633fSSathya Perla 		complete(&adapter->et_cmd_compl);
201559b633fSSathya Perla 		return;
202559b633fSSathya Perla 	}
203559b633fSSathya Perla 
204559b633fSSathya Perla 	if ((opcode == OPCODE_ETH_GET_STATISTICS ||
205559b633fSSathya Perla 	     opcode == OPCODE_ETH_GET_PPORT_STATS) &&
206559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_ETH &&
207559b633fSSathya Perla 	    base_status == MCC_STATUS_SUCCESS) {
208559b633fSSathya Perla 		be_parse_stats(adapter);
209559b633fSSathya Perla 		adapter->stats_cmd_sent = false;
210559b633fSSathya Perla 		return;
211559b633fSSathya Perla 	}
212559b633fSSathya Perla 
213559b633fSSathya Perla 	if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
214559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_COMMON) {
215559b633fSSathya Perla 		if (base_status == MCC_STATUS_SUCCESS) {
216559b633fSSathya Perla 			struct be_cmd_resp_get_cntl_addnl_attribs *resp =
217559b633fSSathya Perla 							(void *)resp_hdr;
21829e9122bSVenkata Duvvuru 			adapter->hwmon_info.be_on_die_temp =
219559b633fSSathya Perla 						resp->on_die_temperature;
220559b633fSSathya Perla 		} else {
221559b633fSSathya Perla 			adapter->be_get_temp_freq = 0;
22229e9122bSVenkata Duvvuru 			adapter->hwmon_info.be_on_die_temp =
22329e9122bSVenkata Duvvuru 						BE_INVALID_DIE_TEMP;
224559b633fSSathya Perla 		}
225559b633fSSathya Perla 		return;
226559b633fSSathya Perla 	}
227559b633fSSathya Perla }
228559b633fSSathya Perla 
2299aebddd1SJeff Kirsher static int be_mcc_compl_process(struct be_adapter *adapter,
2309aebddd1SJeff Kirsher 				struct be_mcc_compl *compl)
2319aebddd1SJeff Kirsher {
2324c60005fSKalesh AP 	enum mcc_base_status base_status;
2334c60005fSKalesh AP 	enum mcc_addl_status addl_status;
234652bf646SPadmanabh Ratnakar 	struct be_cmd_resp_hdr *resp_hdr;
235652bf646SPadmanabh Ratnakar 	u8 opcode = 0, subsystem = 0;
2369aebddd1SJeff Kirsher 
2379aebddd1SJeff Kirsher 	/* Just swap the status to host endian; mcc tag is opaquely copied
2389aebddd1SJeff Kirsher 	 * from mcc_wrb */
2399aebddd1SJeff Kirsher 	be_dws_le_to_cpu(compl, 4);
2409aebddd1SJeff Kirsher 
2414c60005fSKalesh AP 	base_status = base_status(compl->status);
2424c60005fSKalesh AP 	addl_status = addl_status(compl->status);
24396c9b2e4SVasundhara Volam 
244652bf646SPadmanabh Ratnakar 	resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
245652bf646SPadmanabh Ratnakar 	if (resp_hdr) {
246652bf646SPadmanabh Ratnakar 		opcode = resp_hdr->opcode;
247652bf646SPadmanabh Ratnakar 		subsystem = resp_hdr->subsystem;
248652bf646SPadmanabh Ratnakar 	}
249652bf646SPadmanabh Ratnakar 
250559b633fSSathya Perla 	be_async_cmd_process(adapter, compl, resp_hdr);
2515eeff635SSuresh Reddy 
252559b633fSSathya Perla 	if (base_status != MCC_STATUS_SUCCESS &&
253559b633fSSathya Perla 	    !be_skip_err_log(opcode, base_status, addl_status)) {
254fa5c867dSSuresh Reddy 		if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST ||
255fa5c867dSSuresh Reddy 		    addl_status == MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES) {
25697f1d8cdSVasundhara Volam 			dev_warn(&adapter->pdev->dev,
257522609f2SVasundhara Volam 				 "VF is not privileged to issue opcode %d-%d\n",
25897f1d8cdSVasundhara Volam 				 opcode, subsystem);
2599aebddd1SJeff Kirsher 		} else {
26097f1d8cdSVasundhara Volam 			dev_err(&adapter->pdev->dev,
26197f1d8cdSVasundhara Volam 				"opcode %d-%d failed:status %d-%d\n",
2624c60005fSKalesh AP 				opcode, subsystem, base_status, addl_status);
2639aebddd1SJeff Kirsher 		}
2649aebddd1SJeff Kirsher 	}
2654c60005fSKalesh AP 	return compl->status;
2669aebddd1SJeff Kirsher }
2679aebddd1SJeff Kirsher 
2689aebddd1SJeff Kirsher /* Link state evt is a string of bytes; no need for endian swapping */
2699aebddd1SJeff Kirsher static void be_async_link_state_process(struct be_adapter *adapter,
2703acf19d9SSathya Perla 					struct be_mcc_compl *compl)
2719aebddd1SJeff Kirsher {
2723acf19d9SSathya Perla 	struct be_async_event_link_state *evt =
2733acf19d9SSathya Perla 			(struct be_async_event_link_state *)compl;
2743acf19d9SSathya Perla 
275b236916aSAjit Khaparde 	/* When link status changes, link speed must be re-queried from FW */
27642f11cf2SAjit Khaparde 	adapter->phy.link_speed = -1;
277b236916aSAjit Khaparde 
278bdce2ad7SSuresh Reddy 	/* On BEx the FW does not send a separate link status
279bdce2ad7SSuresh Reddy 	 * notification for physical and logical link.
280bdce2ad7SSuresh Reddy 	 * On other chips just process the logical link
281bdce2ad7SSuresh Reddy 	 * status notification
282bdce2ad7SSuresh Reddy 	 */
283bdce2ad7SSuresh Reddy 	if (!BEx_chip(adapter) &&
2842e177a5cSPadmanabh Ratnakar 	    !(evt->port_link_status & LOGICAL_LINK_STATUS_MASK))
2852e177a5cSPadmanabh Ratnakar 		return;
2862e177a5cSPadmanabh Ratnakar 
287b236916aSAjit Khaparde 	/* For the initial link status do not rely on the ASYNC event as
288b236916aSAjit Khaparde 	 * it may not be received in some cases.
289b236916aSAjit Khaparde 	 */
290b236916aSAjit Khaparde 	if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
291bdce2ad7SSuresh Reddy 		be_link_status_update(adapter,
292bdce2ad7SSuresh Reddy 				      evt->port_link_status & LINK_STATUS_MASK);
2939aebddd1SJeff Kirsher }
2949aebddd1SJeff Kirsher 
29521252377SVasundhara Volam static void be_async_port_misconfig_event_process(struct be_adapter *adapter,
29621252377SVasundhara Volam 						  struct be_mcc_compl *compl)
29721252377SVasundhara Volam {
29821252377SVasundhara Volam 	struct be_async_event_misconfig_port *evt =
29921252377SVasundhara Volam 			(struct be_async_event_misconfig_port *)compl;
30021252377SVasundhara Volam 	u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1);
30121252377SVasundhara Volam 	struct device *dev = &adapter->pdev->dev;
30221252377SVasundhara Volam 	u8 port_misconfig_evt;
30321252377SVasundhara Volam 
30421252377SVasundhara Volam 	port_misconfig_evt =
30521252377SVasundhara Volam 		((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff);
30621252377SVasundhara Volam 
30721252377SVasundhara Volam 	/* Log an error message that would allow a user to determine
30821252377SVasundhara Volam 	 * whether the SFPs have an issue
30921252377SVasundhara Volam 	 */
31021252377SVasundhara Volam 	dev_info(dev, "Port %c: %s %s", adapter->port_name,
31121252377SVasundhara Volam 		 be_port_misconfig_evt_desc[port_misconfig_evt],
31221252377SVasundhara Volam 		 be_port_misconfig_remedy_desc[port_misconfig_evt]);
31321252377SVasundhara Volam 
31421252377SVasundhara Volam 	if (port_misconfig_evt == INCOMPATIBLE_SFP)
31521252377SVasundhara Volam 		adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP;
31621252377SVasundhara Volam }
31721252377SVasundhara Volam 
3189aebddd1SJeff Kirsher /* Grp5 CoS Priority evt */
3199aebddd1SJeff Kirsher static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
3203acf19d9SSathya Perla 					       struct be_mcc_compl *compl)
3219aebddd1SJeff Kirsher {
3223acf19d9SSathya Perla 	struct be_async_event_grp5_cos_priority *evt =
3233acf19d9SSathya Perla 			(struct be_async_event_grp5_cos_priority *)compl;
3243acf19d9SSathya Perla 
3259aebddd1SJeff Kirsher 	if (evt->valid) {
3269aebddd1SJeff Kirsher 		adapter->vlan_prio_bmap = evt->available_priority_bmap;
327fdf81bfbSSathya Perla 		adapter->recommended_prio_bits =
3289aebddd1SJeff Kirsher 			evt->reco_default_priority << VLAN_PRIO_SHIFT;
3299aebddd1SJeff Kirsher 	}
3309aebddd1SJeff Kirsher }
3319aebddd1SJeff Kirsher 
332323ff71eSSathya Perla /* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */
3339aebddd1SJeff Kirsher static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
3343acf19d9SSathya Perla 					    struct be_mcc_compl *compl)
3359aebddd1SJeff Kirsher {
3363acf19d9SSathya Perla 	struct be_async_event_grp5_qos_link_speed *evt =
3373acf19d9SSathya Perla 			(struct be_async_event_grp5_qos_link_speed *)compl;
3383acf19d9SSathya Perla 
339323ff71eSSathya Perla 	if (adapter->phy.link_speed >= 0 &&
340323ff71eSSathya Perla 	    evt->physical_port == adapter->port_num)
341323ff71eSSathya Perla 		adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10;
3429aebddd1SJeff Kirsher }
3439aebddd1SJeff Kirsher 
3449aebddd1SJeff Kirsher /*Grp5 PVID evt*/
3459aebddd1SJeff Kirsher static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
3463acf19d9SSathya Perla 					     struct be_mcc_compl *compl)
3479aebddd1SJeff Kirsher {
3483acf19d9SSathya Perla 	struct be_async_event_grp5_pvid_state *evt =
3493acf19d9SSathya Perla 			(struct be_async_event_grp5_pvid_state *)compl;
3503acf19d9SSathya Perla 
351bdac85b5SRavikumar Nelavelli 	if (evt->enabled) {
352939cf306SSomnath Kotur 		adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
353bdac85b5SRavikumar Nelavelli 		dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid);
354bdac85b5SRavikumar Nelavelli 	} else {
3559aebddd1SJeff Kirsher 		adapter->pvid = 0;
3569aebddd1SJeff Kirsher 	}
357bdac85b5SRavikumar Nelavelli }
3589aebddd1SJeff Kirsher 
359760c295eSVenkata Duvvuru #define MGMT_ENABLE_MASK	0x4
360760c295eSVenkata Duvvuru static void be_async_grp5_fw_control_process(struct be_adapter *adapter,
361760c295eSVenkata Duvvuru 					     struct be_mcc_compl *compl)
362760c295eSVenkata Duvvuru {
363760c295eSVenkata Duvvuru 	struct be_async_fw_control *evt = (struct be_async_fw_control *)compl;
364760c295eSVenkata Duvvuru 	u32 evt_dw1 = le32_to_cpu(evt->event_data_word1);
365760c295eSVenkata Duvvuru 
366760c295eSVenkata Duvvuru 	if (evt_dw1 & MGMT_ENABLE_MASK) {
367760c295eSVenkata Duvvuru 		adapter->flags |= BE_FLAGS_OS2BMC;
368760c295eSVenkata Duvvuru 		adapter->bmc_filt_mask = le32_to_cpu(evt->event_data_word2);
369760c295eSVenkata Duvvuru 	} else {
370760c295eSVenkata Duvvuru 		adapter->flags &= ~BE_FLAGS_OS2BMC;
371760c295eSVenkata Duvvuru 	}
372760c295eSVenkata Duvvuru }
373760c295eSVenkata Duvvuru 
3749aebddd1SJeff Kirsher static void be_async_grp5_evt_process(struct be_adapter *adapter,
3753acf19d9SSathya Perla 				      struct be_mcc_compl *compl)
3769aebddd1SJeff Kirsher {
3773acf19d9SSathya Perla 	u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) &
3783acf19d9SSathya Perla 				ASYNC_EVENT_TYPE_MASK;
3799aebddd1SJeff Kirsher 
3809aebddd1SJeff Kirsher 	switch (event_type) {
3819aebddd1SJeff Kirsher 	case ASYNC_EVENT_COS_PRIORITY:
3823acf19d9SSathya Perla 		be_async_grp5_cos_priority_process(adapter, compl);
3839aebddd1SJeff Kirsher 		break;
3849aebddd1SJeff Kirsher 	case ASYNC_EVENT_QOS_SPEED:
3853acf19d9SSathya Perla 		be_async_grp5_qos_speed_process(adapter, compl);
3869aebddd1SJeff Kirsher 		break;
3879aebddd1SJeff Kirsher 	case ASYNC_EVENT_PVID_STATE:
3883acf19d9SSathya Perla 		be_async_grp5_pvid_state_process(adapter, compl);
3899aebddd1SJeff Kirsher 		break;
390760c295eSVenkata Duvvuru 	/* Async event to disable/enable os2bmc and/or mac-learning */
391760c295eSVenkata Duvvuru 	case ASYNC_EVENT_FW_CONTROL:
392760c295eSVenkata Duvvuru 		be_async_grp5_fw_control_process(adapter, compl);
393760c295eSVenkata Duvvuru 		break;
3949aebddd1SJeff Kirsher 	default:
3959aebddd1SJeff Kirsher 		break;
3969aebddd1SJeff Kirsher 	}
3979aebddd1SJeff Kirsher }
3989aebddd1SJeff Kirsher 
399bc0c3405SAjit Khaparde static void be_async_dbg_evt_process(struct be_adapter *adapter,
4003acf19d9SSathya Perla 				     struct be_mcc_compl *cmp)
401bc0c3405SAjit Khaparde {
402bc0c3405SAjit Khaparde 	u8 event_type = 0;
403bc0c3405SAjit Khaparde 	struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp;
404bc0c3405SAjit Khaparde 
4053acf19d9SSathya Perla 	event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
4063acf19d9SSathya Perla 			ASYNC_EVENT_TYPE_MASK;
407bc0c3405SAjit Khaparde 
408bc0c3405SAjit Khaparde 	switch (event_type) {
409bc0c3405SAjit Khaparde 	case ASYNC_DEBUG_EVENT_TYPE_QNQ:
410bc0c3405SAjit Khaparde 		if (evt->valid)
411bc0c3405SAjit Khaparde 			adapter->qnq_vid = le16_to_cpu(evt->vlan_tag);
412bc0c3405SAjit Khaparde 		adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
413bc0c3405SAjit Khaparde 	break;
414bc0c3405SAjit Khaparde 	default:
41505ccaa2bSVasundhara Volam 		dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n",
41605ccaa2bSVasundhara Volam 			 event_type);
417bc0c3405SAjit Khaparde 	break;
418bc0c3405SAjit Khaparde 	}
419bc0c3405SAjit Khaparde }
420bc0c3405SAjit Khaparde 
42121252377SVasundhara Volam static void be_async_sliport_evt_process(struct be_adapter *adapter,
42221252377SVasundhara Volam 					 struct be_mcc_compl *cmp)
42321252377SVasundhara Volam {
42421252377SVasundhara Volam 	u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
42521252377SVasundhara Volam 			ASYNC_EVENT_TYPE_MASK;
42621252377SVasundhara Volam 
42721252377SVasundhara Volam 	if (event_type == ASYNC_EVENT_PORT_MISCONFIG)
42821252377SVasundhara Volam 		be_async_port_misconfig_event_process(adapter, cmp);
42921252377SVasundhara Volam }
43021252377SVasundhara Volam 
4313acf19d9SSathya Perla static inline bool is_link_state_evt(u32 flags)
4329aebddd1SJeff Kirsher {
4333acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4349aebddd1SJeff Kirsher 			ASYNC_EVENT_CODE_LINK_STATE;
4359aebddd1SJeff Kirsher }
4369aebddd1SJeff Kirsher 
4373acf19d9SSathya Perla static inline bool is_grp5_evt(u32 flags)
4389aebddd1SJeff Kirsher {
4393acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4403acf19d9SSathya Perla 			ASYNC_EVENT_CODE_GRP_5;
4419aebddd1SJeff Kirsher }
4429aebddd1SJeff Kirsher 
4433acf19d9SSathya Perla static inline bool is_dbg_evt(u32 flags)
444bc0c3405SAjit Khaparde {
4453acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4463acf19d9SSathya Perla 			ASYNC_EVENT_CODE_QNQ;
4473acf19d9SSathya Perla }
4483acf19d9SSathya Perla 
44921252377SVasundhara Volam static inline bool is_sliport_evt(u32 flags)
45021252377SVasundhara Volam {
45121252377SVasundhara Volam 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
45221252377SVasundhara Volam 		ASYNC_EVENT_CODE_SLIPORT;
45321252377SVasundhara Volam }
45421252377SVasundhara Volam 
4553acf19d9SSathya Perla static void be_mcc_event_process(struct be_adapter *adapter,
4563acf19d9SSathya Perla 				 struct be_mcc_compl *compl)
4573acf19d9SSathya Perla {
4583acf19d9SSathya Perla 	if (is_link_state_evt(compl->flags))
4593acf19d9SSathya Perla 		be_async_link_state_process(adapter, compl);
4603acf19d9SSathya Perla 	else if (is_grp5_evt(compl->flags))
4613acf19d9SSathya Perla 		be_async_grp5_evt_process(adapter, compl);
4623acf19d9SSathya Perla 	else if (is_dbg_evt(compl->flags))
4633acf19d9SSathya Perla 		be_async_dbg_evt_process(adapter, compl);
46421252377SVasundhara Volam 	else if (is_sliport_evt(compl->flags))
46521252377SVasundhara Volam 		be_async_sliport_evt_process(adapter, compl);
466bc0c3405SAjit Khaparde }
467bc0c3405SAjit Khaparde 
4689aebddd1SJeff Kirsher static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
4699aebddd1SJeff Kirsher {
4709aebddd1SJeff Kirsher 	struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
4719aebddd1SJeff Kirsher 	struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
4729aebddd1SJeff Kirsher 
4739aebddd1SJeff Kirsher 	if (be_mcc_compl_is_new(compl)) {
4749aebddd1SJeff Kirsher 		queue_tail_inc(mcc_cq);
4759aebddd1SJeff Kirsher 		return compl;
4769aebddd1SJeff Kirsher 	}
4779aebddd1SJeff Kirsher 	return NULL;
4789aebddd1SJeff Kirsher }
4799aebddd1SJeff Kirsher 
4809aebddd1SJeff Kirsher void be_async_mcc_enable(struct be_adapter *adapter)
4819aebddd1SJeff Kirsher {
4829aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_cq_lock);
4839aebddd1SJeff Kirsher 
4849aebddd1SJeff Kirsher 	be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0);
4859aebddd1SJeff Kirsher 	adapter->mcc_obj.rearm_cq = true;
4869aebddd1SJeff Kirsher 
4879aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_cq_lock);
4889aebddd1SJeff Kirsher }
4899aebddd1SJeff Kirsher 
4909aebddd1SJeff Kirsher void be_async_mcc_disable(struct be_adapter *adapter)
4919aebddd1SJeff Kirsher {
492a323d9bfSSathya Perla 	spin_lock_bh(&adapter->mcc_cq_lock);
493a323d9bfSSathya Perla 
4949aebddd1SJeff Kirsher 	adapter->mcc_obj.rearm_cq = false;
495a323d9bfSSathya Perla 	be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
496a323d9bfSSathya Perla 
497a323d9bfSSathya Perla 	spin_unlock_bh(&adapter->mcc_cq_lock);
4989aebddd1SJeff Kirsher }
4999aebddd1SJeff Kirsher 
50010ef9ab4SSathya Perla int be_process_mcc(struct be_adapter *adapter)
5019aebddd1SJeff Kirsher {
5029aebddd1SJeff Kirsher 	struct be_mcc_compl *compl;
50310ef9ab4SSathya Perla 	int num = 0, status = 0;
5049aebddd1SJeff Kirsher 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
5059aebddd1SJeff Kirsher 
506072a9c48SAmerigo Wang 	spin_lock(&adapter->mcc_cq_lock);
5073acf19d9SSathya Perla 
5089aebddd1SJeff Kirsher 	while ((compl = be_mcc_compl_get(adapter))) {
5099aebddd1SJeff Kirsher 		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
5103acf19d9SSathya Perla 			be_mcc_event_process(adapter, compl);
5119aebddd1SJeff Kirsher 		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
51210ef9ab4SSathya Perla 			status = be_mcc_compl_process(adapter, compl);
5139aebddd1SJeff Kirsher 			atomic_dec(&mcc_obj->q.used);
5149aebddd1SJeff Kirsher 		}
5159aebddd1SJeff Kirsher 		be_mcc_compl_use(compl);
5169aebddd1SJeff Kirsher 		num++;
5179aebddd1SJeff Kirsher 	}
5189aebddd1SJeff Kirsher 
51910ef9ab4SSathya Perla 	if (num)
52010ef9ab4SSathya Perla 		be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
52110ef9ab4SSathya Perla 
522072a9c48SAmerigo Wang 	spin_unlock(&adapter->mcc_cq_lock);
52310ef9ab4SSathya Perla 	return status;
5249aebddd1SJeff Kirsher }
5259aebddd1SJeff Kirsher 
5269aebddd1SJeff Kirsher /* Wait till no more pending mcc requests are present */
5279aebddd1SJeff Kirsher static int be_mcc_wait_compl(struct be_adapter *adapter)
5289aebddd1SJeff Kirsher {
5299aebddd1SJeff Kirsher #define mcc_timeout		120000 /* 12s timeout */
53010ef9ab4SSathya Perla 	int i, status = 0;
5319aebddd1SJeff Kirsher 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
5329aebddd1SJeff Kirsher 
5336589ade0SSathya Perla 	for (i = 0; i < mcc_timeout; i++) {
534954f6825SVenkata Duvvuru 		if (be_check_error(adapter, BE_ERROR_ANY))
5359aebddd1SJeff Kirsher 			return -EIO;
5369aebddd1SJeff Kirsher 
537072a9c48SAmerigo Wang 		local_bh_disable();
53810ef9ab4SSathya Perla 		status = be_process_mcc(adapter);
539072a9c48SAmerigo Wang 		local_bh_enable();
5409aebddd1SJeff Kirsher 
5419aebddd1SJeff Kirsher 		if (atomic_read(&mcc_obj->q.used) == 0)
5429aebddd1SJeff Kirsher 			break;
5439aebddd1SJeff Kirsher 		udelay(100);
5449aebddd1SJeff Kirsher 	}
5459aebddd1SJeff Kirsher 	if (i == mcc_timeout) {
5466589ade0SSathya Perla 		dev_err(&adapter->pdev->dev, "FW not responding\n");
547954f6825SVenkata Duvvuru 		be_set_error(adapter, BE_ERROR_FW);
548652bf646SPadmanabh Ratnakar 		return -EIO;
5499aebddd1SJeff Kirsher 	}
5509aebddd1SJeff Kirsher 	return status;
5519aebddd1SJeff Kirsher }
5529aebddd1SJeff Kirsher 
5539aebddd1SJeff Kirsher /* Notify MCC requests and wait for completion */
5549aebddd1SJeff Kirsher static int be_mcc_notify_wait(struct be_adapter *adapter)
5559aebddd1SJeff Kirsher {
556652bf646SPadmanabh Ratnakar 	int status;
557652bf646SPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
558652bf646SPadmanabh Ratnakar 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
559652bf646SPadmanabh Ratnakar 	u16 index = mcc_obj->q.head;
560652bf646SPadmanabh Ratnakar 	struct be_cmd_resp_hdr *resp;
561652bf646SPadmanabh Ratnakar 
562652bf646SPadmanabh Ratnakar 	index_dec(&index, mcc_obj->q.len);
563652bf646SPadmanabh Ratnakar 	wrb = queue_index_node(&mcc_obj->q, index);
564652bf646SPadmanabh Ratnakar 
565652bf646SPadmanabh Ratnakar 	resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
566652bf646SPadmanabh Ratnakar 
567efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
568efaa408eSSuresh Reddy 	if (status)
569efaa408eSSuresh Reddy 		goto out;
570652bf646SPadmanabh Ratnakar 
571652bf646SPadmanabh Ratnakar 	status = be_mcc_wait_compl(adapter);
572652bf646SPadmanabh Ratnakar 	if (status == -EIO)
573652bf646SPadmanabh Ratnakar 		goto out;
574652bf646SPadmanabh Ratnakar 
5754c60005fSKalesh AP 	status = (resp->base_status |
5764c60005fSKalesh AP 		  ((resp->addl_status & CQE_ADDL_STATUS_MASK) <<
5774c60005fSKalesh AP 		   CQE_ADDL_STATUS_SHIFT));
578652bf646SPadmanabh Ratnakar out:
579652bf646SPadmanabh Ratnakar 	return status;
5809aebddd1SJeff Kirsher }
5819aebddd1SJeff Kirsher 
5829aebddd1SJeff Kirsher static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
5839aebddd1SJeff Kirsher {
5849aebddd1SJeff Kirsher 	int msecs = 0;
5859aebddd1SJeff Kirsher 	u32 ready;
5869aebddd1SJeff Kirsher 
5876589ade0SSathya Perla 	do {
588954f6825SVenkata Duvvuru 		if (be_check_error(adapter, BE_ERROR_ANY))
5899aebddd1SJeff Kirsher 			return -EIO;
5909aebddd1SJeff Kirsher 
5919aebddd1SJeff Kirsher 		ready = ioread32(db);
592434b3648SSathya Perla 		if (ready == 0xffffffff)
5939aebddd1SJeff Kirsher 			return -1;
5949aebddd1SJeff Kirsher 
5959aebddd1SJeff Kirsher 		ready &= MPU_MAILBOX_DB_RDY_MASK;
5969aebddd1SJeff Kirsher 		if (ready)
5979aebddd1SJeff Kirsher 			break;
5989aebddd1SJeff Kirsher 
5999aebddd1SJeff Kirsher 		if (msecs > 4000) {
6006589ade0SSathya Perla 			dev_err(&adapter->pdev->dev, "FW not responding\n");
601954f6825SVenkata Duvvuru 			be_set_error(adapter, BE_ERROR_FW);
602f67ef7baSPadmanabh Ratnakar 			be_detect_error(adapter);
6039aebddd1SJeff Kirsher 			return -1;
6049aebddd1SJeff Kirsher 		}
6059aebddd1SJeff Kirsher 
6069aebddd1SJeff Kirsher 		msleep(1);
6079aebddd1SJeff Kirsher 		msecs++;
6089aebddd1SJeff Kirsher 	} while (true);
6099aebddd1SJeff Kirsher 
6109aebddd1SJeff Kirsher 	return 0;
6119aebddd1SJeff Kirsher }
6129aebddd1SJeff Kirsher 
6139aebddd1SJeff Kirsher /*
6149aebddd1SJeff Kirsher  * Insert the mailbox address into the doorbell in two steps
6159aebddd1SJeff Kirsher  * Polls on the mbox doorbell till a command completion (or a timeout) occurs
6169aebddd1SJeff Kirsher  */
6179aebddd1SJeff Kirsher static int be_mbox_notify_wait(struct be_adapter *adapter)
6189aebddd1SJeff Kirsher {
6199aebddd1SJeff Kirsher 	int status;
6209aebddd1SJeff Kirsher 	u32 val = 0;
6219aebddd1SJeff Kirsher 	void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET;
6229aebddd1SJeff Kirsher 	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
6239aebddd1SJeff Kirsher 	struct be_mcc_mailbox *mbox = mbox_mem->va;
6249aebddd1SJeff Kirsher 	struct be_mcc_compl *compl = &mbox->compl;
6259aebddd1SJeff Kirsher 
6269aebddd1SJeff Kirsher 	/* wait for ready to be set */
6279aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
6289aebddd1SJeff Kirsher 	if (status != 0)
6299aebddd1SJeff Kirsher 		return status;
6309aebddd1SJeff Kirsher 
6319aebddd1SJeff Kirsher 	val |= MPU_MAILBOX_DB_HI_MASK;
6329aebddd1SJeff Kirsher 	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
6339aebddd1SJeff Kirsher 	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
6349aebddd1SJeff Kirsher 	iowrite32(val, db);
6359aebddd1SJeff Kirsher 
6369aebddd1SJeff Kirsher 	/* wait for ready to be set */
6379aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
6389aebddd1SJeff Kirsher 	if (status != 0)
6399aebddd1SJeff Kirsher 		return status;
6409aebddd1SJeff Kirsher 
6419aebddd1SJeff Kirsher 	val = 0;
6429aebddd1SJeff Kirsher 	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
6439aebddd1SJeff Kirsher 	val |= (u32)(mbox_mem->dma >> 4) << 2;
6449aebddd1SJeff Kirsher 	iowrite32(val, db);
6459aebddd1SJeff Kirsher 
6469aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
6479aebddd1SJeff Kirsher 	if (status != 0)
6489aebddd1SJeff Kirsher 		return status;
6499aebddd1SJeff Kirsher 
6509aebddd1SJeff Kirsher 	/* A cq entry has been made now */
6519aebddd1SJeff Kirsher 	if (be_mcc_compl_is_new(compl)) {
6529aebddd1SJeff Kirsher 		status = be_mcc_compl_process(adapter, &mbox->compl);
6539aebddd1SJeff Kirsher 		be_mcc_compl_use(compl);
6549aebddd1SJeff Kirsher 		if (status)
6559aebddd1SJeff Kirsher 			return status;
6569aebddd1SJeff Kirsher 	} else {
6579aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev, "invalid mailbox completion\n");
6589aebddd1SJeff Kirsher 		return -1;
6599aebddd1SJeff Kirsher 	}
6609aebddd1SJeff Kirsher 	return 0;
6619aebddd1SJeff Kirsher }
6629aebddd1SJeff Kirsher 
663c5b3ad4cSSathya Perla static u16 be_POST_stage_get(struct be_adapter *adapter)
6649aebddd1SJeff Kirsher {
6659aebddd1SJeff Kirsher 	u32 sem;
6669aebddd1SJeff Kirsher 
667c5b3ad4cSSathya Perla 	if (BEx_chip(adapter))
668c5b3ad4cSSathya Perla 		sem  = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx);
6699aebddd1SJeff Kirsher 	else
670c5b3ad4cSSathya Perla 		pci_read_config_dword(adapter->pdev,
671c5b3ad4cSSathya Perla 				      SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
672c5b3ad4cSSathya Perla 
673c5b3ad4cSSathya Perla 	return sem & POST_STAGE_MASK;
6749aebddd1SJeff Kirsher }
6759aebddd1SJeff Kirsher 
67687f20c26SGavin Shan static int lancer_wait_ready(struct be_adapter *adapter)
677bf99e50dSPadmanabh Ratnakar {
678bf99e50dSPadmanabh Ratnakar #define SLIPORT_READY_TIMEOUT 30
679bf99e50dSPadmanabh Ratnakar 	u32 sliport_status;
680e673244aSKalesh AP 	int i;
681bf99e50dSPadmanabh Ratnakar 
682bf99e50dSPadmanabh Ratnakar 	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
683bf99e50dSPadmanabh Ratnakar 		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
684bf99e50dSPadmanabh Ratnakar 		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
6859fa465c0SSathya Perla 			return 0;
6869fa465c0SSathya Perla 
6879fa465c0SSathya Perla 		if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
6889fa465c0SSathya Perla 		    !(sliport_status & SLIPORT_STATUS_RN_MASK))
6899fa465c0SSathya Perla 			return -EIO;
690bf99e50dSPadmanabh Ratnakar 
691bf99e50dSPadmanabh Ratnakar 		msleep(1000);
692bf99e50dSPadmanabh Ratnakar 	}
693bf99e50dSPadmanabh Ratnakar 
694e673244aSKalesh AP 	return sliport_status ? : -1;
695bf99e50dSPadmanabh Ratnakar }
696bf99e50dSPadmanabh Ratnakar 
697bf99e50dSPadmanabh Ratnakar int be_fw_wait_ready(struct be_adapter *adapter)
6989aebddd1SJeff Kirsher {
6999aebddd1SJeff Kirsher 	u16 stage;
7009aebddd1SJeff Kirsher 	int status, timeout = 0;
7019aebddd1SJeff Kirsher 	struct device *dev = &adapter->pdev->dev;
7029aebddd1SJeff Kirsher 
703bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter)) {
704bf99e50dSPadmanabh Ratnakar 		status = lancer_wait_ready(adapter);
705e673244aSKalesh AP 		if (status) {
706e673244aSKalesh AP 			stage = status;
707e673244aSKalesh AP 			goto err;
708e673244aSKalesh AP 		}
709e673244aSKalesh AP 		return 0;
710bf99e50dSPadmanabh Ratnakar 	}
711bf99e50dSPadmanabh Ratnakar 
7129aebddd1SJeff Kirsher 	do {
713ca3de6b2SSathya Perla 		/* There's no means to poll POST state on BE2/3 VFs */
714ca3de6b2SSathya Perla 		if (BEx_chip(adapter) && be_virtfn(adapter))
715ca3de6b2SSathya Perla 			return 0;
716ca3de6b2SSathya Perla 
717c5b3ad4cSSathya Perla 		stage = be_POST_stage_get(adapter);
71866d29cbcSGavin Shan 		if (stage == POST_STAGE_ARMFW_RDY)
71966d29cbcSGavin Shan 			return 0;
72066d29cbcSGavin Shan 
721a2cc4e0bSSathya Perla 		dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout);
7229aebddd1SJeff Kirsher 		if (msleep_interruptible(2000)) {
7239aebddd1SJeff Kirsher 			dev_err(dev, "Waiting for POST aborted\n");
7249aebddd1SJeff Kirsher 			return -EINTR;
7259aebddd1SJeff Kirsher 		}
7269aebddd1SJeff Kirsher 		timeout += 2;
7273ab81b5fSSomnath Kotur 	} while (timeout < 60);
7289aebddd1SJeff Kirsher 
729e673244aSKalesh AP err:
730e673244aSKalesh AP 	dev_err(dev, "POST timeout; stage=%#x\n", stage);
7319fa465c0SSathya Perla 	return -ETIMEDOUT;
7329aebddd1SJeff Kirsher }
7339aebddd1SJeff Kirsher 
7349aebddd1SJeff Kirsher static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
7359aebddd1SJeff Kirsher {
7369aebddd1SJeff Kirsher 	return &wrb->payload.sgl[0];
7379aebddd1SJeff Kirsher }
7389aebddd1SJeff Kirsher 
739a2cc4e0bSSathya Perla static inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr)
740bea50988SSathya Perla {
741bea50988SSathya Perla 	wrb->tag0 = addr & 0xFFFFFFFF;
742bea50988SSathya Perla 	wrb->tag1 = upper_32_bits(addr);
743bea50988SSathya Perla }
7449aebddd1SJeff Kirsher 
7459aebddd1SJeff Kirsher /* Don't touch the hdr after it's prepared */
746106df1e3SSomnath Kotur /* mem will be NULL for embedded commands */
747106df1e3SSomnath Kotur static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
748106df1e3SSomnath Kotur 				   u8 subsystem, u8 opcode, int cmd_len,
749a2cc4e0bSSathya Perla 				   struct be_mcc_wrb *wrb,
750a2cc4e0bSSathya Perla 				   struct be_dma_mem *mem)
7519aebddd1SJeff Kirsher {
752106df1e3SSomnath Kotur 	struct be_sge *sge;
753106df1e3SSomnath Kotur 
7549aebddd1SJeff Kirsher 	req_hdr->opcode = opcode;
7559aebddd1SJeff Kirsher 	req_hdr->subsystem = subsystem;
7569aebddd1SJeff Kirsher 	req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
7579aebddd1SJeff Kirsher 	req_hdr->version = 0;
758bea50988SSathya Perla 	fill_wrb_tags(wrb, (ulong) req_hdr);
759106df1e3SSomnath Kotur 	wrb->payload_length = cmd_len;
760106df1e3SSomnath Kotur 	if (mem) {
761106df1e3SSomnath Kotur 		wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
762106df1e3SSomnath Kotur 			MCC_WRB_SGE_CNT_SHIFT;
763106df1e3SSomnath Kotur 		sge = nonembedded_sgl(wrb);
764106df1e3SSomnath Kotur 		sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
765106df1e3SSomnath Kotur 		sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
766106df1e3SSomnath Kotur 		sge->len = cpu_to_le32(mem->size);
767106df1e3SSomnath Kotur 	} else
768106df1e3SSomnath Kotur 		wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
769106df1e3SSomnath Kotur 	be_dws_cpu_to_le(wrb, 8);
7709aebddd1SJeff Kirsher }
7719aebddd1SJeff Kirsher 
7729aebddd1SJeff Kirsher static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
7739aebddd1SJeff Kirsher 				      struct be_dma_mem *mem)
7749aebddd1SJeff Kirsher {
7759aebddd1SJeff Kirsher 	int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
7769aebddd1SJeff Kirsher 	u64 dma = (u64)mem->dma;
7779aebddd1SJeff Kirsher 
7789aebddd1SJeff Kirsher 	for (i = 0; i < buf_pages; i++) {
7799aebddd1SJeff Kirsher 		pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
7809aebddd1SJeff Kirsher 		pages[i].hi = cpu_to_le32(upper_32_bits(dma));
7819aebddd1SJeff Kirsher 		dma += PAGE_SIZE_4K;
7829aebddd1SJeff Kirsher 	}
7839aebddd1SJeff Kirsher }
7849aebddd1SJeff Kirsher 
7859aebddd1SJeff Kirsher static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter)
7869aebddd1SJeff Kirsher {
7879aebddd1SJeff Kirsher 	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
7889aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb
7899aebddd1SJeff Kirsher 		= &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
7909aebddd1SJeff Kirsher 	memset(wrb, 0, sizeof(*wrb));
7919aebddd1SJeff Kirsher 	return wrb;
7929aebddd1SJeff Kirsher }
7939aebddd1SJeff Kirsher 
7949aebddd1SJeff Kirsher static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
7959aebddd1SJeff Kirsher {
7969aebddd1SJeff Kirsher 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
7979aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
7989aebddd1SJeff Kirsher 
799aa790db9SPadmanabh Ratnakar 	if (!mccq->created)
800aa790db9SPadmanabh Ratnakar 		return NULL;
801aa790db9SPadmanabh Ratnakar 
8024d277125SVasundhara Volam 	if (atomic_read(&mccq->used) >= mccq->len)
8039aebddd1SJeff Kirsher 		return NULL;
8049aebddd1SJeff Kirsher 
8059aebddd1SJeff Kirsher 	wrb = queue_head_node(mccq);
8069aebddd1SJeff Kirsher 	queue_head_inc(mccq);
8079aebddd1SJeff Kirsher 	atomic_inc(&mccq->used);
8089aebddd1SJeff Kirsher 	memset(wrb, 0, sizeof(*wrb));
8099aebddd1SJeff Kirsher 	return wrb;
8109aebddd1SJeff Kirsher }
8119aebddd1SJeff Kirsher 
812bea50988SSathya Perla static bool use_mcc(struct be_adapter *adapter)
813bea50988SSathya Perla {
814bea50988SSathya Perla 	return adapter->mcc_obj.q.created;
815bea50988SSathya Perla }
816bea50988SSathya Perla 
817bea50988SSathya Perla /* Must be used only in process context */
818bea50988SSathya Perla static int be_cmd_lock(struct be_adapter *adapter)
819bea50988SSathya Perla {
820bea50988SSathya Perla 	if (use_mcc(adapter)) {
821bea50988SSathya Perla 		spin_lock_bh(&adapter->mcc_lock);
822bea50988SSathya Perla 		return 0;
823bea50988SSathya Perla 	} else {
824bea50988SSathya Perla 		return mutex_lock_interruptible(&adapter->mbox_lock);
825bea50988SSathya Perla 	}
826bea50988SSathya Perla }
827bea50988SSathya Perla 
828bea50988SSathya Perla /* Must be used only in process context */
829bea50988SSathya Perla static void be_cmd_unlock(struct be_adapter *adapter)
830bea50988SSathya Perla {
831bea50988SSathya Perla 	if (use_mcc(adapter))
832bea50988SSathya Perla 		spin_unlock_bh(&adapter->mcc_lock);
833bea50988SSathya Perla 	else
834bea50988SSathya Perla 		return mutex_unlock(&adapter->mbox_lock);
835bea50988SSathya Perla }
836bea50988SSathya Perla 
837bea50988SSathya Perla static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter,
838bea50988SSathya Perla 				      struct be_mcc_wrb *wrb)
839bea50988SSathya Perla {
840bea50988SSathya Perla 	struct be_mcc_wrb *dest_wrb;
841bea50988SSathya Perla 
842bea50988SSathya Perla 	if (use_mcc(adapter)) {
843bea50988SSathya Perla 		dest_wrb = wrb_from_mccq(adapter);
844bea50988SSathya Perla 		if (!dest_wrb)
845bea50988SSathya Perla 			return NULL;
846bea50988SSathya Perla 	} else {
847bea50988SSathya Perla 		dest_wrb = wrb_from_mbox(adapter);
848bea50988SSathya Perla 	}
849bea50988SSathya Perla 
850bea50988SSathya Perla 	memcpy(dest_wrb, wrb, sizeof(*wrb));
851bea50988SSathya Perla 	if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK))
852bea50988SSathya Perla 		fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb));
853bea50988SSathya Perla 
854bea50988SSathya Perla 	return dest_wrb;
855bea50988SSathya Perla }
856bea50988SSathya Perla 
857bea50988SSathya Perla /* Must be used only in process context */
858bea50988SSathya Perla static int be_cmd_notify_wait(struct be_adapter *adapter,
859bea50988SSathya Perla 			      struct be_mcc_wrb *wrb)
860bea50988SSathya Perla {
861bea50988SSathya Perla 	struct be_mcc_wrb *dest_wrb;
862bea50988SSathya Perla 	int status;
863bea50988SSathya Perla 
864bea50988SSathya Perla 	status = be_cmd_lock(adapter);
865bea50988SSathya Perla 	if (status)
866bea50988SSathya Perla 		return status;
867bea50988SSathya Perla 
868bea50988SSathya Perla 	dest_wrb = be_cmd_copy(adapter, wrb);
8690c884567SSuresh Reddy 	if (!dest_wrb) {
8700c884567SSuresh Reddy 		status = -EBUSY;
8710c884567SSuresh Reddy 		goto unlock;
8720c884567SSuresh Reddy 	}
873bea50988SSathya Perla 
874bea50988SSathya Perla 	if (use_mcc(adapter))
875bea50988SSathya Perla 		status = be_mcc_notify_wait(adapter);
876bea50988SSathya Perla 	else
877bea50988SSathya Perla 		status = be_mbox_notify_wait(adapter);
878bea50988SSathya Perla 
879bea50988SSathya Perla 	if (!status)
880bea50988SSathya Perla 		memcpy(wrb, dest_wrb, sizeof(*wrb));
881bea50988SSathya Perla 
8820c884567SSuresh Reddy unlock:
883bea50988SSathya Perla 	be_cmd_unlock(adapter);
884bea50988SSathya Perla 	return status;
885bea50988SSathya Perla }
886bea50988SSathya Perla 
8879aebddd1SJeff Kirsher /* Tell fw we're about to start firing cmds by writing a
8889aebddd1SJeff Kirsher  * special pattern across the wrb hdr; uses mbox
8899aebddd1SJeff Kirsher  */
8909aebddd1SJeff Kirsher int be_cmd_fw_init(struct be_adapter *adapter)
8919aebddd1SJeff Kirsher {
8929aebddd1SJeff Kirsher 	u8 *wrb;
8939aebddd1SJeff Kirsher 	int status;
8949aebddd1SJeff Kirsher 
895bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter))
896bf99e50dSPadmanabh Ratnakar 		return 0;
897bf99e50dSPadmanabh Ratnakar 
8989aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
8999aebddd1SJeff Kirsher 		return -1;
9009aebddd1SJeff Kirsher 
9019aebddd1SJeff Kirsher 	wrb = (u8 *)wrb_from_mbox(adapter);
9029aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
9039aebddd1SJeff Kirsher 	*wrb++ = 0x12;
9049aebddd1SJeff Kirsher 	*wrb++ = 0x34;
9059aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
9069aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
9079aebddd1SJeff Kirsher 	*wrb++ = 0x56;
9089aebddd1SJeff Kirsher 	*wrb++ = 0x78;
9099aebddd1SJeff Kirsher 	*wrb = 0xFF;
9109aebddd1SJeff Kirsher 
9119aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
9129aebddd1SJeff Kirsher 
9139aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
9149aebddd1SJeff Kirsher 	return status;
9159aebddd1SJeff Kirsher }
9169aebddd1SJeff Kirsher 
9179aebddd1SJeff Kirsher /* Tell fw we're done with firing cmds by writing a
9189aebddd1SJeff Kirsher  * special pattern across the wrb hdr; uses mbox
9199aebddd1SJeff Kirsher  */
9209aebddd1SJeff Kirsher int be_cmd_fw_clean(struct be_adapter *adapter)
9219aebddd1SJeff Kirsher {
9229aebddd1SJeff Kirsher 	u8 *wrb;
9239aebddd1SJeff Kirsher 	int status;
9249aebddd1SJeff Kirsher 
925bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter))
926bf99e50dSPadmanabh Ratnakar 		return 0;
927bf99e50dSPadmanabh Ratnakar 
9289aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
9299aebddd1SJeff Kirsher 		return -1;
9309aebddd1SJeff Kirsher 
9319aebddd1SJeff Kirsher 	wrb = (u8 *)wrb_from_mbox(adapter);
9329aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
9339aebddd1SJeff Kirsher 	*wrb++ = 0xAA;
9349aebddd1SJeff Kirsher 	*wrb++ = 0xBB;
9359aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
9369aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
9379aebddd1SJeff Kirsher 	*wrb++ = 0xCC;
9389aebddd1SJeff Kirsher 	*wrb++ = 0xDD;
9399aebddd1SJeff Kirsher 	*wrb = 0xFF;
9409aebddd1SJeff Kirsher 
9419aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
9429aebddd1SJeff Kirsher 
9439aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
9449aebddd1SJeff Kirsher 	return status;
9459aebddd1SJeff Kirsher }
946bf99e50dSPadmanabh Ratnakar 
947f2f781a7SSathya Perla int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo)
9489aebddd1SJeff Kirsher {
9499aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9509aebddd1SJeff Kirsher 	struct be_cmd_req_eq_create *req;
951f2f781a7SSathya Perla 	struct be_dma_mem *q_mem = &eqo->q.dma_mem;
952f2f781a7SSathya Perla 	int status, ver = 0;
9539aebddd1SJeff Kirsher 
9549aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
9559aebddd1SJeff Kirsher 		return -1;
9569aebddd1SJeff Kirsher 
9579aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
9589aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
9599aebddd1SJeff Kirsher 
960106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
961a2cc4e0bSSathya Perla 			       OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb,
962a2cc4e0bSSathya Perla 			       NULL);
9639aebddd1SJeff Kirsher 
964f2f781a7SSathya Perla 	/* Support for EQ_CREATEv2 available only SH-R onwards */
965f2f781a7SSathya Perla 	if (!(BEx_chip(adapter) || lancer_chip(adapter)))
966f2f781a7SSathya Perla 		ver = 2;
967f2f781a7SSathya Perla 
968f2f781a7SSathya Perla 	req->hdr.version = ver;
9699aebddd1SJeff Kirsher 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
9709aebddd1SJeff Kirsher 
9719aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
9729aebddd1SJeff Kirsher 	/* 4byte eqe*/
9739aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
9749aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, count, req->context,
975f2f781a7SSathya Perla 		      __ilog2_u32(eqo->q.len / 256));
9769aebddd1SJeff Kirsher 	be_dws_cpu_to_le(req->context, sizeof(req->context));
9779aebddd1SJeff Kirsher 
9789aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
9799aebddd1SJeff Kirsher 
9809aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
9819aebddd1SJeff Kirsher 	if (!status) {
9829aebddd1SJeff Kirsher 		struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
98303d28ffeSKalesh AP 
984f2f781a7SSathya Perla 		eqo->q.id = le16_to_cpu(resp->eq_id);
985f2f781a7SSathya Perla 		eqo->msix_idx =
986f2f781a7SSathya Perla 			(ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx;
987f2f781a7SSathya Perla 		eqo->q.created = true;
9889aebddd1SJeff Kirsher 	}
9899aebddd1SJeff Kirsher 
9909aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
9919aebddd1SJeff Kirsher 	return status;
9929aebddd1SJeff Kirsher }
9939aebddd1SJeff Kirsher 
994f9449ab7SSathya Perla /* Use MCC */
9959aebddd1SJeff Kirsher int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
9965ee4979bSSathya Perla 			  bool permanent, u32 if_handle, u32 pmac_id)
9979aebddd1SJeff Kirsher {
9989aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9999aebddd1SJeff Kirsher 	struct be_cmd_req_mac_query *req;
10009aebddd1SJeff Kirsher 	int status;
10019aebddd1SJeff Kirsher 
1002f9449ab7SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
10039aebddd1SJeff Kirsher 
1004f9449ab7SSathya Perla 	wrb = wrb_from_mccq(adapter);
1005f9449ab7SSathya Perla 	if (!wrb) {
1006f9449ab7SSathya Perla 		status = -EBUSY;
1007f9449ab7SSathya Perla 		goto err;
1008f9449ab7SSathya Perla 	}
10099aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10109aebddd1SJeff Kirsher 
1011106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1012a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb,
1013a2cc4e0bSSathya Perla 			       NULL);
10145ee4979bSSathya Perla 	req->type = MAC_ADDRESS_TYPE_NETWORK;
10159aebddd1SJeff Kirsher 	if (permanent) {
10169aebddd1SJeff Kirsher 		req->permanent = 1;
10179aebddd1SJeff Kirsher 	} else {
10189aebddd1SJeff Kirsher 		req->if_id = cpu_to_le16((u16)if_handle);
1019590c391dSPadmanabh Ratnakar 		req->pmac_id = cpu_to_le32(pmac_id);
10209aebddd1SJeff Kirsher 		req->permanent = 0;
10219aebddd1SJeff Kirsher 	}
10229aebddd1SJeff Kirsher 
1023f9449ab7SSathya Perla 	status = be_mcc_notify_wait(adapter);
10249aebddd1SJeff Kirsher 	if (!status) {
10259aebddd1SJeff Kirsher 		struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
102603d28ffeSKalesh AP 
10279aebddd1SJeff Kirsher 		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
10289aebddd1SJeff Kirsher 	}
10299aebddd1SJeff Kirsher 
1030f9449ab7SSathya Perla err:
1031f9449ab7SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
10329aebddd1SJeff Kirsher 	return status;
10339aebddd1SJeff Kirsher }
10349aebddd1SJeff Kirsher 
10359aebddd1SJeff Kirsher /* Uses synchronous MCCQ */
10369aebddd1SJeff Kirsher int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
10379aebddd1SJeff Kirsher 		    u32 if_id, u32 *pmac_id, u32 domain)
10389aebddd1SJeff Kirsher {
10399aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
10409aebddd1SJeff Kirsher 	struct be_cmd_req_pmac_add *req;
10419aebddd1SJeff Kirsher 	int status;
10429aebddd1SJeff Kirsher 
10439aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
10449aebddd1SJeff Kirsher 
10459aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
10469aebddd1SJeff Kirsher 	if (!wrb) {
10479aebddd1SJeff Kirsher 		status = -EBUSY;
10489aebddd1SJeff Kirsher 		goto err;
10499aebddd1SJeff Kirsher 	}
10509aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10519aebddd1SJeff Kirsher 
1052106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1053a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb,
1054a2cc4e0bSSathya Perla 			       NULL);
10559aebddd1SJeff Kirsher 
10569aebddd1SJeff Kirsher 	req->hdr.domain = domain;
10579aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(if_id);
10589aebddd1SJeff Kirsher 	memcpy(req->mac_address, mac_addr, ETH_ALEN);
10599aebddd1SJeff Kirsher 
10609aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
10619aebddd1SJeff Kirsher 	if (!status) {
10629aebddd1SJeff Kirsher 		struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
106303d28ffeSKalesh AP 
10649aebddd1SJeff Kirsher 		*pmac_id = le32_to_cpu(resp->pmac_id);
10659aebddd1SJeff Kirsher 	}
10669aebddd1SJeff Kirsher 
10679aebddd1SJeff Kirsher err:
10689aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1069e3a7ae2cSSomnath Kotur 
1070e3a7ae2cSSomnath Kotur 	 if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
1071e3a7ae2cSSomnath Kotur 		status = -EPERM;
1072e3a7ae2cSSomnath Kotur 
10739aebddd1SJeff Kirsher 	return status;
10749aebddd1SJeff Kirsher }
10759aebddd1SJeff Kirsher 
10769aebddd1SJeff Kirsher /* Uses synchronous MCCQ */
107730128031SSathya Perla int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom)
10789aebddd1SJeff Kirsher {
10799aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
10809aebddd1SJeff Kirsher 	struct be_cmd_req_pmac_del *req;
10819aebddd1SJeff Kirsher 	int status;
10829aebddd1SJeff Kirsher 
108330128031SSathya Perla 	if (pmac_id == -1)
108430128031SSathya Perla 		return 0;
108530128031SSathya Perla 
10869aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
10879aebddd1SJeff Kirsher 
10889aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
10899aebddd1SJeff Kirsher 	if (!wrb) {
10909aebddd1SJeff Kirsher 		status = -EBUSY;
10919aebddd1SJeff Kirsher 		goto err;
10929aebddd1SJeff Kirsher 	}
10939aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10949aebddd1SJeff Kirsher 
1095106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1096cd3307aaSKalesh AP 			       OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req),
1097cd3307aaSKalesh AP 			       wrb, NULL);
10989aebddd1SJeff Kirsher 
10999aebddd1SJeff Kirsher 	req->hdr.domain = dom;
11009aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(if_id);
11019aebddd1SJeff Kirsher 	req->pmac_id = cpu_to_le32(pmac_id);
11029aebddd1SJeff Kirsher 
11039aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
11049aebddd1SJeff Kirsher 
11059aebddd1SJeff Kirsher err:
11069aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
11079aebddd1SJeff Kirsher 	return status;
11089aebddd1SJeff Kirsher }
11099aebddd1SJeff Kirsher 
11109aebddd1SJeff Kirsher /* Uses Mbox */
111110ef9ab4SSathya Perla int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
111210ef9ab4SSathya Perla 		     struct be_queue_info *eq, bool no_delay, int coalesce_wm)
11139aebddd1SJeff Kirsher {
11149aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
11159aebddd1SJeff Kirsher 	struct be_cmd_req_cq_create *req;
11169aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &cq->dma_mem;
11179aebddd1SJeff Kirsher 	void *ctxt;
11189aebddd1SJeff Kirsher 	int status;
11199aebddd1SJeff Kirsher 
11209aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
11219aebddd1SJeff Kirsher 		return -1;
11229aebddd1SJeff Kirsher 
11239aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
11249aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
11259aebddd1SJeff Kirsher 	ctxt = &req->context;
11269aebddd1SJeff Kirsher 
1127106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1128a2cc4e0bSSathya Perla 			       OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb,
1129a2cc4e0bSSathya Perla 			       NULL);
11309aebddd1SJeff Kirsher 
11319aebddd1SJeff Kirsher 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
1132bbdc42f8SAjit Khaparde 
1133bbdc42f8SAjit Khaparde 	if (BEx_chip(adapter)) {
11349aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
11359aebddd1SJeff Kirsher 			      coalesce_wm);
11369aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, nodelay,
11379aebddd1SJeff Kirsher 			      ctxt, no_delay);
11389aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
11399aebddd1SJeff Kirsher 			      __ilog2_u32(cq->len / 256));
11409aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
11419aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
11429aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
1143bbdc42f8SAjit Khaparde 	} else {
1144bbdc42f8SAjit Khaparde 		req->hdr.version = 2;
1145bbdc42f8SAjit Khaparde 		req->page_size = 1; /* 1 for 4K */
114609e83a9dSAjit Khaparde 
114709e83a9dSAjit Khaparde 		/* coalesce-wm field in this cmd is not relevant to Lancer.
114809e83a9dSAjit Khaparde 		 * Lancer uses COMMON_MODIFY_CQ to set this field
114909e83a9dSAjit Khaparde 		 */
115009e83a9dSAjit Khaparde 		if (!lancer_chip(adapter))
115109e83a9dSAjit Khaparde 			AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
115209e83a9dSAjit Khaparde 				      ctxt, coalesce_wm);
1153bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt,
1154bbdc42f8SAjit Khaparde 			      no_delay);
1155bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
1156bbdc42f8SAjit Khaparde 			      __ilog2_u32(cq->len / 256));
1157bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
1158a2cc4e0bSSathya Perla 		AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
1159a2cc4e0bSSathya Perla 		AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
11609aebddd1SJeff Kirsher 	}
11619aebddd1SJeff Kirsher 
11629aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
11639aebddd1SJeff Kirsher 
11649aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
11659aebddd1SJeff Kirsher 
11669aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
11679aebddd1SJeff Kirsher 	if (!status) {
11689aebddd1SJeff Kirsher 		struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
116903d28ffeSKalesh AP 
11709aebddd1SJeff Kirsher 		cq->id = le16_to_cpu(resp->cq_id);
11719aebddd1SJeff Kirsher 		cq->created = true;
11729aebddd1SJeff Kirsher 	}
11739aebddd1SJeff Kirsher 
11749aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
11759aebddd1SJeff Kirsher 
11769aebddd1SJeff Kirsher 	return status;
11779aebddd1SJeff Kirsher }
11789aebddd1SJeff Kirsher 
11799aebddd1SJeff Kirsher static u32 be_encoded_q_len(int q_len)
11809aebddd1SJeff Kirsher {
11819aebddd1SJeff Kirsher 	u32 len_encoded = fls(q_len); /* log2(len) + 1 */
118203d28ffeSKalesh AP 
11839aebddd1SJeff Kirsher 	if (len_encoded == 16)
11849aebddd1SJeff Kirsher 		len_encoded = 0;
11859aebddd1SJeff Kirsher 	return len_encoded;
11869aebddd1SJeff Kirsher }
11879aebddd1SJeff Kirsher 
11884188e7dfSJingoo Han static int be_cmd_mccq_ext_create(struct be_adapter *adapter,
11899aebddd1SJeff Kirsher 				  struct be_queue_info *mccq,
11909aebddd1SJeff Kirsher 				  struct be_queue_info *cq)
11919aebddd1SJeff Kirsher {
11929aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
11939aebddd1SJeff Kirsher 	struct be_cmd_req_mcc_ext_create *req;
11949aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &mccq->dma_mem;
11959aebddd1SJeff Kirsher 	void *ctxt;
11969aebddd1SJeff Kirsher 	int status;
11979aebddd1SJeff Kirsher 
11989aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
11999aebddd1SJeff Kirsher 		return -1;
12009aebddd1SJeff Kirsher 
12019aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
12029aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
12039aebddd1SJeff Kirsher 	ctxt = &req->context;
12049aebddd1SJeff Kirsher 
1205106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1206a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb,
1207a2cc4e0bSSathya Perla 			       NULL);
12089aebddd1SJeff Kirsher 
12099aebddd1SJeff Kirsher 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
1210666d39c7SVasundhara Volam 	if (BEx_chip(adapter)) {
12119aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
12129aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
12139aebddd1SJeff Kirsher 			      be_encoded_q_len(mccq->len));
12149aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
1215666d39c7SVasundhara Volam 	} else {
1216666d39c7SVasundhara Volam 		req->hdr.version = 1;
1217666d39c7SVasundhara Volam 		req->cq_id = cpu_to_le16(cq->id);
1218666d39c7SVasundhara Volam 
1219666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt,
1220666d39c7SVasundhara Volam 			      be_encoded_q_len(mccq->len));
1221666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1);
1222666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id,
1223666d39c7SVasundhara Volam 			      ctxt, cq->id);
1224666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid,
1225666d39c7SVasundhara Volam 			      ctxt, 1);
12269aebddd1SJeff Kirsher 	}
12279aebddd1SJeff Kirsher 
122821252377SVasundhara Volam 	/* Subscribe to Link State, Sliport Event and Group 5 Events
122921252377SVasundhara Volam 	 * (bits 1, 5 and 17 set)
123021252377SVasundhara Volam 	 */
123121252377SVasundhara Volam 	req->async_event_bitmap[0] =
123221252377SVasundhara Volam 			cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) |
123321252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_GRP_5) |
123421252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_QNQ) |
123521252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_SLIPORT));
123621252377SVasundhara Volam 
12379aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
12389aebddd1SJeff Kirsher 
12399aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
12409aebddd1SJeff Kirsher 
12419aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
12429aebddd1SJeff Kirsher 	if (!status) {
12439aebddd1SJeff Kirsher 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
124403d28ffeSKalesh AP 
12459aebddd1SJeff Kirsher 		mccq->id = le16_to_cpu(resp->id);
12469aebddd1SJeff Kirsher 		mccq->created = true;
12479aebddd1SJeff Kirsher 	}
12489aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
12499aebddd1SJeff Kirsher 
12509aebddd1SJeff Kirsher 	return status;
12519aebddd1SJeff Kirsher }
12529aebddd1SJeff Kirsher 
12534188e7dfSJingoo Han static int be_cmd_mccq_org_create(struct be_adapter *adapter,
12549aebddd1SJeff Kirsher 				  struct be_queue_info *mccq,
12559aebddd1SJeff Kirsher 				  struct be_queue_info *cq)
12569aebddd1SJeff Kirsher {
12579aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
12589aebddd1SJeff Kirsher 	struct be_cmd_req_mcc_create *req;
12599aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &mccq->dma_mem;
12609aebddd1SJeff Kirsher 	void *ctxt;
12619aebddd1SJeff Kirsher 	int status;
12629aebddd1SJeff Kirsher 
12639aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
12649aebddd1SJeff Kirsher 		return -1;
12659aebddd1SJeff Kirsher 
12669aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
12679aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
12689aebddd1SJeff Kirsher 	ctxt = &req->context;
12699aebddd1SJeff Kirsher 
1270106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1271a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb,
1272a2cc4e0bSSathya Perla 			       NULL);
12739aebddd1SJeff Kirsher 
12749aebddd1SJeff Kirsher 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
12759aebddd1SJeff Kirsher 
12769aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
12779aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
12789aebddd1SJeff Kirsher 		      be_encoded_q_len(mccq->len));
12799aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
12809aebddd1SJeff Kirsher 
12819aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
12829aebddd1SJeff Kirsher 
12839aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
12849aebddd1SJeff Kirsher 
12859aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
12869aebddd1SJeff Kirsher 	if (!status) {
12879aebddd1SJeff Kirsher 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
128803d28ffeSKalesh AP 
12899aebddd1SJeff Kirsher 		mccq->id = le16_to_cpu(resp->id);
12909aebddd1SJeff Kirsher 		mccq->created = true;
12919aebddd1SJeff Kirsher 	}
12929aebddd1SJeff Kirsher 
12939aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
12949aebddd1SJeff Kirsher 	return status;
12959aebddd1SJeff Kirsher }
12969aebddd1SJeff Kirsher 
12979aebddd1SJeff Kirsher int be_cmd_mccq_create(struct be_adapter *adapter,
1298a2cc4e0bSSathya Perla 		       struct be_queue_info *mccq, struct be_queue_info *cq)
12999aebddd1SJeff Kirsher {
13009aebddd1SJeff Kirsher 	int status;
13019aebddd1SJeff Kirsher 
13029aebddd1SJeff Kirsher 	status = be_cmd_mccq_ext_create(adapter, mccq, cq);
1303666d39c7SVasundhara Volam 	if (status && BEx_chip(adapter)) {
13049aebddd1SJeff Kirsher 		dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
13059aebddd1SJeff Kirsher 			"or newer to avoid conflicting priorities between NIC "
13069aebddd1SJeff Kirsher 			"and FCoE traffic");
13079aebddd1SJeff Kirsher 		status = be_cmd_mccq_org_create(adapter, mccq, cq);
13089aebddd1SJeff Kirsher 	}
13099aebddd1SJeff Kirsher 	return status;
13109aebddd1SJeff Kirsher }
13119aebddd1SJeff Kirsher 
131294d73aaaSVasundhara Volam int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo)
13139aebddd1SJeff Kirsher {
13147707133cSSathya Perla 	struct be_mcc_wrb wrb = {0};
13159aebddd1SJeff Kirsher 	struct be_cmd_req_eth_tx_create *req;
131694d73aaaSVasundhara Volam 	struct be_queue_info *txq = &txo->q;
131794d73aaaSVasundhara Volam 	struct be_queue_info *cq = &txo->cq;
13189aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &txq->dma_mem;
131994d73aaaSVasundhara Volam 	int status, ver = 0;
13209aebddd1SJeff Kirsher 
13217707133cSSathya Perla 	req = embedded_payload(&wrb);
1322106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
13237707133cSSathya Perla 			       OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL);
13249aebddd1SJeff Kirsher 
13259aebddd1SJeff Kirsher 	if (lancer_chip(adapter)) {
13269aebddd1SJeff Kirsher 		req->hdr.version = 1;
132794d73aaaSVasundhara Volam 	} else if (BEx_chip(adapter)) {
132894d73aaaSVasundhara Volam 		if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC)
132994d73aaaSVasundhara Volam 			req->hdr.version = 2;
133094d73aaaSVasundhara Volam 	} else { /* For SH */
133194d73aaaSVasundhara Volam 		req->hdr.version = 2;
13329aebddd1SJeff Kirsher 	}
13339aebddd1SJeff Kirsher 
133481b02655SVasundhara Volam 	if (req->hdr.version > 0)
133581b02655SVasundhara Volam 		req->if_id = cpu_to_le16(adapter->if_handle);
13369aebddd1SJeff Kirsher 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
13379aebddd1SJeff Kirsher 	req->ulp_num = BE_ULP1_NUM;
13389aebddd1SJeff Kirsher 	req->type = BE_ETH_TX_RING_TYPE_STANDARD;
133994d73aaaSVasundhara Volam 	req->cq_id = cpu_to_le16(cq->id);
134094d73aaaSVasundhara Volam 	req->queue_size = be_encoded_q_len(txq->len);
13419aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
134294d73aaaSVasundhara Volam 	ver = req->hdr.version;
134394d73aaaSVasundhara Volam 
13447707133cSSathya Perla 	status = be_cmd_notify_wait(adapter, &wrb);
13459aebddd1SJeff Kirsher 	if (!status) {
13467707133cSSathya Perla 		struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb);
134703d28ffeSKalesh AP 
13489aebddd1SJeff Kirsher 		txq->id = le16_to_cpu(resp->cid);
134994d73aaaSVasundhara Volam 		if (ver == 2)
135094d73aaaSVasundhara Volam 			txo->db_offset = le32_to_cpu(resp->db_offset);
135194d73aaaSVasundhara Volam 		else
135294d73aaaSVasundhara Volam 			txo->db_offset = DB_TXULP1_OFFSET;
13539aebddd1SJeff Kirsher 		txq->created = true;
13549aebddd1SJeff Kirsher 	}
13559aebddd1SJeff Kirsher 
13569aebddd1SJeff Kirsher 	return status;
13579aebddd1SJeff Kirsher }
13589aebddd1SJeff Kirsher 
13599aebddd1SJeff Kirsher /* Uses MCC */
13609aebddd1SJeff Kirsher int be_cmd_rxq_create(struct be_adapter *adapter,
13619aebddd1SJeff Kirsher 		      struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
136210ef9ab4SSathya Perla 		      u32 if_id, u32 rss, u8 *rss_id)
13639aebddd1SJeff Kirsher {
13649aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
13659aebddd1SJeff Kirsher 	struct be_cmd_req_eth_rx_create *req;
13669aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &rxq->dma_mem;
13679aebddd1SJeff Kirsher 	int status;
13689aebddd1SJeff Kirsher 
13699aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
13709aebddd1SJeff Kirsher 
13719aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
13729aebddd1SJeff Kirsher 	if (!wrb) {
13739aebddd1SJeff Kirsher 		status = -EBUSY;
13749aebddd1SJeff Kirsher 		goto err;
13759aebddd1SJeff Kirsher 	}
13769aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
13779aebddd1SJeff Kirsher 
1378106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1379106df1e3SSomnath Kotur 			       OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL);
13809aebddd1SJeff Kirsher 
13819aebddd1SJeff Kirsher 	req->cq_id = cpu_to_le16(cq_id);
13829aebddd1SJeff Kirsher 	req->frag_size = fls(frag_size) - 1;
13839aebddd1SJeff Kirsher 	req->num_pages = 2;
13849aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
13859aebddd1SJeff Kirsher 	req->interface_id = cpu_to_le32(if_id);
138610ef9ab4SSathya Perla 	req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE);
13879aebddd1SJeff Kirsher 	req->rss_queue = cpu_to_le32(rss);
13889aebddd1SJeff Kirsher 
13899aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
13909aebddd1SJeff Kirsher 	if (!status) {
13919aebddd1SJeff Kirsher 		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
139203d28ffeSKalesh AP 
13939aebddd1SJeff Kirsher 		rxq->id = le16_to_cpu(resp->id);
13949aebddd1SJeff Kirsher 		rxq->created = true;
13959aebddd1SJeff Kirsher 		*rss_id = resp->rss_id;
13969aebddd1SJeff Kirsher 	}
13979aebddd1SJeff Kirsher 
13989aebddd1SJeff Kirsher err:
13999aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
14009aebddd1SJeff Kirsher 	return status;
14019aebddd1SJeff Kirsher }
14029aebddd1SJeff Kirsher 
14039aebddd1SJeff Kirsher /* Generic destroyer function for all types of queues
14049aebddd1SJeff Kirsher  * Uses Mbox
14059aebddd1SJeff Kirsher  */
14069aebddd1SJeff Kirsher int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
14079aebddd1SJeff Kirsher 		     int queue_type)
14089aebddd1SJeff Kirsher {
14099aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
14109aebddd1SJeff Kirsher 	struct be_cmd_req_q_destroy *req;
14119aebddd1SJeff Kirsher 	u8 subsys = 0, opcode = 0;
14129aebddd1SJeff Kirsher 	int status;
14139aebddd1SJeff Kirsher 
14149aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
14159aebddd1SJeff Kirsher 		return -1;
14169aebddd1SJeff Kirsher 
14179aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
14189aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
14199aebddd1SJeff Kirsher 
14209aebddd1SJeff Kirsher 	switch (queue_type) {
14219aebddd1SJeff Kirsher 	case QTYPE_EQ:
14229aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
14239aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_EQ_DESTROY;
14249aebddd1SJeff Kirsher 		break;
14259aebddd1SJeff Kirsher 	case QTYPE_CQ:
14269aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
14279aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_CQ_DESTROY;
14289aebddd1SJeff Kirsher 		break;
14299aebddd1SJeff Kirsher 	case QTYPE_TXQ:
14309aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_ETH;
14319aebddd1SJeff Kirsher 		opcode = OPCODE_ETH_TX_DESTROY;
14329aebddd1SJeff Kirsher 		break;
14339aebddd1SJeff Kirsher 	case QTYPE_RXQ:
14349aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_ETH;
14359aebddd1SJeff Kirsher 		opcode = OPCODE_ETH_RX_DESTROY;
14369aebddd1SJeff Kirsher 		break;
14379aebddd1SJeff Kirsher 	case QTYPE_MCCQ:
14389aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
14399aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_MCC_DESTROY;
14409aebddd1SJeff Kirsher 		break;
14419aebddd1SJeff Kirsher 	default:
14429aebddd1SJeff Kirsher 		BUG();
14439aebddd1SJeff Kirsher 	}
14449aebddd1SJeff Kirsher 
1445106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb,
1446106df1e3SSomnath Kotur 			       NULL);
14479aebddd1SJeff Kirsher 	req->id = cpu_to_le16(q->id);
14489aebddd1SJeff Kirsher 
14499aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
14509aebddd1SJeff Kirsher 	q->created = false;
14519aebddd1SJeff Kirsher 
14529aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
14539aebddd1SJeff Kirsher 	return status;
14549aebddd1SJeff Kirsher }
14559aebddd1SJeff Kirsher 
14569aebddd1SJeff Kirsher /* Uses MCC */
14579aebddd1SJeff Kirsher int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
14589aebddd1SJeff Kirsher {
14599aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
14609aebddd1SJeff Kirsher 	struct be_cmd_req_q_destroy *req;
14619aebddd1SJeff Kirsher 	int status;
14629aebddd1SJeff Kirsher 
14639aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
14649aebddd1SJeff Kirsher 
14659aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
14669aebddd1SJeff Kirsher 	if (!wrb) {
14679aebddd1SJeff Kirsher 		status = -EBUSY;
14689aebddd1SJeff Kirsher 		goto err;
14699aebddd1SJeff Kirsher 	}
14709aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
14719aebddd1SJeff Kirsher 
1472106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1473106df1e3SSomnath Kotur 			       OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL);
14749aebddd1SJeff Kirsher 	req->id = cpu_to_le16(q->id);
14759aebddd1SJeff Kirsher 
14769aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
14779aebddd1SJeff Kirsher 	q->created = false;
14789aebddd1SJeff Kirsher 
14799aebddd1SJeff Kirsher err:
14809aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
14819aebddd1SJeff Kirsher 	return status;
14829aebddd1SJeff Kirsher }
14839aebddd1SJeff Kirsher 
14849aebddd1SJeff Kirsher /* Create an rx filtering policy configuration on an i/f
1485bea50988SSathya Perla  * Will use MBOX only if MCCQ has not been created.
14869aebddd1SJeff Kirsher  */
14879aebddd1SJeff Kirsher int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
14881578e777SPadmanabh Ratnakar 		     u32 *if_handle, u32 domain)
14899aebddd1SJeff Kirsher {
1490bea50988SSathya Perla 	struct be_mcc_wrb wrb = {0};
14919aebddd1SJeff Kirsher 	struct be_cmd_req_if_create *req;
14929aebddd1SJeff Kirsher 	int status;
14939aebddd1SJeff Kirsher 
1494bea50988SSathya Perla 	req = embedded_payload(&wrb);
1495106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1496a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_INTERFACE_CREATE,
1497a2cc4e0bSSathya Perla 			       sizeof(*req), &wrb, NULL);
14989aebddd1SJeff Kirsher 	req->hdr.domain = domain;
14999aebddd1SJeff Kirsher 	req->capability_flags = cpu_to_le32(cap_flags);
15009aebddd1SJeff Kirsher 	req->enable_flags = cpu_to_le32(en_flags);
1501f9449ab7SSathya Perla 	req->pmac_invalid = true;
15029aebddd1SJeff Kirsher 
1503bea50988SSathya Perla 	status = be_cmd_notify_wait(adapter, &wrb);
15049aebddd1SJeff Kirsher 	if (!status) {
1505bea50988SSathya Perla 		struct be_cmd_resp_if_create *resp = embedded_payload(&wrb);
150603d28ffeSKalesh AP 
15079aebddd1SJeff Kirsher 		*if_handle = le32_to_cpu(resp->interface_id);
1508b5bb9776SSathya Perla 
1509b5bb9776SSathya Perla 		/* Hack to retrieve VF's pmac-id on BE3 */
151018c57c74SKalesh AP 		if (BE3_chip(adapter) && be_virtfn(adapter))
1511b5bb9776SSathya Perla 			adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id);
15129aebddd1SJeff Kirsher 	}
15139aebddd1SJeff Kirsher 	return status;
15149aebddd1SJeff Kirsher }
15159aebddd1SJeff Kirsher 
1516f9449ab7SSathya Perla /* Uses MCCQ */
151730128031SSathya Perla int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain)
15189aebddd1SJeff Kirsher {
15199aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15209aebddd1SJeff Kirsher 	struct be_cmd_req_if_destroy *req;
15219aebddd1SJeff Kirsher 	int status;
15229aebddd1SJeff Kirsher 
152330128031SSathya Perla 	if (interface_id == -1)
1524f9449ab7SSathya Perla 		return 0;
15259aebddd1SJeff Kirsher 
1526f9449ab7SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
1527f9449ab7SSathya Perla 
1528f9449ab7SSathya Perla 	wrb = wrb_from_mccq(adapter);
1529f9449ab7SSathya Perla 	if (!wrb) {
1530f9449ab7SSathya Perla 		status = -EBUSY;
1531f9449ab7SSathya Perla 		goto err;
1532f9449ab7SSathya Perla 	}
15339aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
15349aebddd1SJeff Kirsher 
1535106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1536a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_INTERFACE_DESTROY,
1537a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
15389aebddd1SJeff Kirsher 	req->hdr.domain = domain;
15399aebddd1SJeff Kirsher 	req->interface_id = cpu_to_le32(interface_id);
15409aebddd1SJeff Kirsher 
1541f9449ab7SSathya Perla 	status = be_mcc_notify_wait(adapter);
1542f9449ab7SSathya Perla err:
1543f9449ab7SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
15449aebddd1SJeff Kirsher 	return status;
15459aebddd1SJeff Kirsher }
15469aebddd1SJeff Kirsher 
15479aebddd1SJeff Kirsher /* Get stats is a non embedded command: the request is not embedded inside
15489aebddd1SJeff Kirsher  * WRB but is a separate dma memory block
15499aebddd1SJeff Kirsher  * Uses asynchronous MCC
15509aebddd1SJeff Kirsher  */
15519aebddd1SJeff Kirsher int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
15529aebddd1SJeff Kirsher {
15539aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15549aebddd1SJeff Kirsher 	struct be_cmd_req_hdr *hdr;
15559aebddd1SJeff Kirsher 	int status = 0;
15569aebddd1SJeff Kirsher 
15579aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
15589aebddd1SJeff Kirsher 
15599aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
15609aebddd1SJeff Kirsher 	if (!wrb) {
15619aebddd1SJeff Kirsher 		status = -EBUSY;
15629aebddd1SJeff Kirsher 		goto err;
15639aebddd1SJeff Kirsher 	}
15649aebddd1SJeff Kirsher 	hdr = nonemb_cmd->va;
15659aebddd1SJeff Kirsher 
1566106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
1567a2cc4e0bSSathya Perla 			       OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb,
1568a2cc4e0bSSathya Perla 			       nonemb_cmd);
15699aebddd1SJeff Kirsher 
1570ca34fe38SSathya Perla 	/* version 1 of the cmd is not supported only by BE2 */
157161000861SAjit Khaparde 	if (BE2_chip(adapter))
157261000861SAjit Khaparde 		hdr->version = 0;
157361000861SAjit Khaparde 	if (BE3_chip(adapter) || lancer_chip(adapter))
15749aebddd1SJeff Kirsher 		hdr->version = 1;
157561000861SAjit Khaparde 	else
157661000861SAjit Khaparde 		hdr->version = 2;
15779aebddd1SJeff Kirsher 
1578efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
1579efaa408eSSuresh Reddy 	if (status)
1580efaa408eSSuresh Reddy 		goto err;
1581efaa408eSSuresh Reddy 
15829aebddd1SJeff Kirsher 	adapter->stats_cmd_sent = true;
15839aebddd1SJeff Kirsher 
15849aebddd1SJeff Kirsher err:
15859aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
15869aebddd1SJeff Kirsher 	return status;
15879aebddd1SJeff Kirsher }
15889aebddd1SJeff Kirsher 
15899aebddd1SJeff Kirsher /* Lancer Stats */
15909aebddd1SJeff Kirsher int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
15919aebddd1SJeff Kirsher 			       struct be_dma_mem *nonemb_cmd)
15929aebddd1SJeff Kirsher {
15939aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15949aebddd1SJeff Kirsher 	struct lancer_cmd_req_pport_stats *req;
15959aebddd1SJeff Kirsher 	int status = 0;
15969aebddd1SJeff Kirsher 
1597f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
1598f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_ETH))
1599f25b119cSPadmanabh Ratnakar 		return -EPERM;
1600f25b119cSPadmanabh Ratnakar 
16019aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16029aebddd1SJeff Kirsher 
16039aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16049aebddd1SJeff Kirsher 	if (!wrb) {
16059aebddd1SJeff Kirsher 		status = -EBUSY;
16069aebddd1SJeff Kirsher 		goto err;
16079aebddd1SJeff Kirsher 	}
16089aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
16099aebddd1SJeff Kirsher 
1610106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1611a2cc4e0bSSathya Perla 			       OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size,
1612a2cc4e0bSSathya Perla 			       wrb, nonemb_cmd);
16139aebddd1SJeff Kirsher 
1614d51ebd33SPadmanabh Ratnakar 	req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num);
16159aebddd1SJeff Kirsher 	req->cmd_params.params.reset_stats = 0;
16169aebddd1SJeff Kirsher 
1617efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
1618efaa408eSSuresh Reddy 	if (status)
1619efaa408eSSuresh Reddy 		goto err;
1620efaa408eSSuresh Reddy 
16219aebddd1SJeff Kirsher 	adapter->stats_cmd_sent = true;
16229aebddd1SJeff Kirsher 
16239aebddd1SJeff Kirsher err:
16249aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
16259aebddd1SJeff Kirsher 	return status;
16269aebddd1SJeff Kirsher }
16279aebddd1SJeff Kirsher 
1628323ff71eSSathya Perla static int be_mac_to_link_speed(int mac_speed)
1629323ff71eSSathya Perla {
1630323ff71eSSathya Perla 	switch (mac_speed) {
1631323ff71eSSathya Perla 	case PHY_LINK_SPEED_ZERO:
1632323ff71eSSathya Perla 		return 0;
1633323ff71eSSathya Perla 	case PHY_LINK_SPEED_10MBPS:
1634323ff71eSSathya Perla 		return 10;
1635323ff71eSSathya Perla 	case PHY_LINK_SPEED_100MBPS:
1636323ff71eSSathya Perla 		return 100;
1637323ff71eSSathya Perla 	case PHY_LINK_SPEED_1GBPS:
1638323ff71eSSathya Perla 		return 1000;
1639323ff71eSSathya Perla 	case PHY_LINK_SPEED_10GBPS:
1640323ff71eSSathya Perla 		return 10000;
1641b971f847SVasundhara Volam 	case PHY_LINK_SPEED_20GBPS:
1642b971f847SVasundhara Volam 		return 20000;
1643b971f847SVasundhara Volam 	case PHY_LINK_SPEED_25GBPS:
1644b971f847SVasundhara Volam 		return 25000;
1645b971f847SVasundhara Volam 	case PHY_LINK_SPEED_40GBPS:
1646b971f847SVasundhara Volam 		return 40000;
1647323ff71eSSathya Perla 	}
1648323ff71eSSathya Perla 	return 0;
1649323ff71eSSathya Perla }
1650323ff71eSSathya Perla 
1651323ff71eSSathya Perla /* Uses synchronous mcc
1652323ff71eSSathya Perla  * Returns link_speed in Mbps
1653323ff71eSSathya Perla  */
1654323ff71eSSathya Perla int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
1655323ff71eSSathya Perla 			     u8 *link_status, u32 dom)
16569aebddd1SJeff Kirsher {
16579aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
16589aebddd1SJeff Kirsher 	struct be_cmd_req_link_status *req;
16599aebddd1SJeff Kirsher 	int status;
16609aebddd1SJeff Kirsher 
16619aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16629aebddd1SJeff Kirsher 
1663b236916aSAjit Khaparde 	if (link_status)
1664b236916aSAjit Khaparde 		*link_status = LINK_DOWN;
1665b236916aSAjit Khaparde 
16669aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16679aebddd1SJeff Kirsher 	if (!wrb) {
16689aebddd1SJeff Kirsher 		status = -EBUSY;
16699aebddd1SJeff Kirsher 		goto err;
16709aebddd1SJeff Kirsher 	}
16719aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
16729aebddd1SJeff Kirsher 
167357cd80d4SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1674a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_LINK_STATUS_QUERY,
1675a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
167657cd80d4SPadmanabh Ratnakar 
1677ca34fe38SSathya Perla 	/* version 1 of the cmd is not supported only by BE2 */
1678ca34fe38SSathya Perla 	if (!BE2_chip(adapter))
1679daad6167SPadmanabh Ratnakar 		req->hdr.version = 1;
1680daad6167SPadmanabh Ratnakar 
168157cd80d4SPadmanabh Ratnakar 	req->hdr.domain = dom;
16829aebddd1SJeff Kirsher 
16839aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
16849aebddd1SJeff Kirsher 	if (!status) {
16859aebddd1SJeff Kirsher 		struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
168603d28ffeSKalesh AP 
1687323ff71eSSathya Perla 		if (link_speed) {
1688323ff71eSSathya Perla 			*link_speed = resp->link_speed ?
1689323ff71eSSathya Perla 				      le16_to_cpu(resp->link_speed) * 10 :
1690323ff71eSSathya Perla 				      be_mac_to_link_speed(resp->mac_speed);
1691323ff71eSSathya Perla 
1692323ff71eSSathya Perla 			if (!resp->logical_link_status)
1693323ff71eSSathya Perla 				*link_speed = 0;
16949aebddd1SJeff Kirsher 		}
1695b236916aSAjit Khaparde 		if (link_status)
1696b236916aSAjit Khaparde 			*link_status = resp->logical_link_status;
16979aebddd1SJeff Kirsher 	}
16989aebddd1SJeff Kirsher 
16999aebddd1SJeff Kirsher err:
17009aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
17019aebddd1SJeff Kirsher 	return status;
17029aebddd1SJeff Kirsher }
17039aebddd1SJeff Kirsher 
17049aebddd1SJeff Kirsher /* Uses synchronous mcc */
17059aebddd1SJeff Kirsher int be_cmd_get_die_temperature(struct be_adapter *adapter)
17069aebddd1SJeff Kirsher {
17079aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
17089aebddd1SJeff Kirsher 	struct be_cmd_req_get_cntl_addnl_attribs *req;
1709117affe3SVasundhara Volam 	int status = 0;
17109aebddd1SJeff Kirsher 
17119aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
17129aebddd1SJeff Kirsher 
17139aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
17149aebddd1SJeff Kirsher 	if (!wrb) {
17159aebddd1SJeff Kirsher 		status = -EBUSY;
17169aebddd1SJeff Kirsher 		goto err;
17179aebddd1SJeff Kirsher 	}
17189aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
17199aebddd1SJeff Kirsher 
1720106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1721a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES,
1722a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
17239aebddd1SJeff Kirsher 
1724efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
17259aebddd1SJeff Kirsher err:
17269aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
17279aebddd1SJeff Kirsher 	return status;
17289aebddd1SJeff Kirsher }
17299aebddd1SJeff Kirsher 
17309aebddd1SJeff Kirsher /* Uses synchronous mcc */
1731fd7ff6f0SVenkat Duvvuru int be_cmd_get_fat_dump_len(struct be_adapter *adapter, u32 *dump_size)
17329aebddd1SJeff Kirsher {
1733fd7ff6f0SVenkat Duvvuru 	struct be_mcc_wrb wrb = {0};
17349aebddd1SJeff Kirsher 	struct be_cmd_req_get_fat *req;
17359aebddd1SJeff Kirsher 	int status;
17369aebddd1SJeff Kirsher 
1737fd7ff6f0SVenkat Duvvuru 	req = embedded_payload(&wrb);
17389aebddd1SJeff Kirsher 
1739106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1740fd7ff6f0SVenkat Duvvuru 			       OPCODE_COMMON_MANAGE_FAT, sizeof(*req),
1741fd7ff6f0SVenkat Duvvuru 			       &wrb, NULL);
17429aebddd1SJeff Kirsher 	req->fat_operation = cpu_to_le32(QUERY_FAT);
1743fd7ff6f0SVenkat Duvvuru 	status = be_cmd_notify_wait(adapter, &wrb);
17449aebddd1SJeff Kirsher 	if (!status) {
1745fd7ff6f0SVenkat Duvvuru 		struct be_cmd_resp_get_fat *resp = embedded_payload(&wrb);
174603d28ffeSKalesh AP 
1747fd7ff6f0SVenkat Duvvuru 		if (dump_size && resp->log_size)
1748fd7ff6f0SVenkat Duvvuru 			*dump_size = le32_to_cpu(resp->log_size) -
17499aebddd1SJeff Kirsher 					sizeof(u32);
17509aebddd1SJeff Kirsher 	}
17519aebddd1SJeff Kirsher 	return status;
17529aebddd1SJeff Kirsher }
17539aebddd1SJeff Kirsher 
1754fd7ff6f0SVenkat Duvvuru int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf)
17559aebddd1SJeff Kirsher {
17569aebddd1SJeff Kirsher 	struct be_dma_mem get_fat_cmd;
17579aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
17589aebddd1SJeff Kirsher 	struct be_cmd_req_get_fat *req;
17599aebddd1SJeff Kirsher 	u32 offset = 0, total_size, buf_size,
17609aebddd1SJeff Kirsher 				log_offset = sizeof(u32), payload_len;
1761fd7ff6f0SVenkat Duvvuru 	int status;
17629aebddd1SJeff Kirsher 
17639aebddd1SJeff Kirsher 	if (buf_len == 0)
1764fd7ff6f0SVenkat Duvvuru 		return 0;
17659aebddd1SJeff Kirsher 
17669aebddd1SJeff Kirsher 	total_size = buf_len;
17679aebddd1SJeff Kirsher 
17689aebddd1SJeff Kirsher 	get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
1769e51000dbSSriharsha Basavapatna 	get_fat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
17709aebddd1SJeff Kirsher 					     get_fat_cmd.size,
1771e51000dbSSriharsha Basavapatna 					     &get_fat_cmd.dma, GFP_ATOMIC);
1772fd7ff6f0SVenkat Duvvuru 	if (!get_fat_cmd.va)
1773c5f156deSVasundhara Volam 		return -ENOMEM;
17749aebddd1SJeff Kirsher 
17759aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
17769aebddd1SJeff Kirsher 
17779aebddd1SJeff Kirsher 	while (total_size) {
17789aebddd1SJeff Kirsher 		buf_size = min(total_size, (u32)60*1024);
17799aebddd1SJeff Kirsher 		total_size -= buf_size;
17809aebddd1SJeff Kirsher 
17819aebddd1SJeff Kirsher 		wrb = wrb_from_mccq(adapter);
17829aebddd1SJeff Kirsher 		if (!wrb) {
17839aebddd1SJeff Kirsher 			status = -EBUSY;
17849aebddd1SJeff Kirsher 			goto err;
17859aebddd1SJeff Kirsher 		}
17869aebddd1SJeff Kirsher 		req = get_fat_cmd.va;
17879aebddd1SJeff Kirsher 
17889aebddd1SJeff Kirsher 		payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size;
1789106df1e3SSomnath Kotur 		be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1790a2cc4e0bSSathya Perla 				       OPCODE_COMMON_MANAGE_FAT, payload_len,
1791a2cc4e0bSSathya Perla 				       wrb, &get_fat_cmd);
17929aebddd1SJeff Kirsher 
17939aebddd1SJeff Kirsher 		req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
17949aebddd1SJeff Kirsher 		req->read_log_offset = cpu_to_le32(log_offset);
17959aebddd1SJeff Kirsher 		req->read_log_length = cpu_to_le32(buf_size);
17969aebddd1SJeff Kirsher 		req->data_buffer_size = cpu_to_le32(buf_size);
17979aebddd1SJeff Kirsher 
17989aebddd1SJeff Kirsher 		status = be_mcc_notify_wait(adapter);
17999aebddd1SJeff Kirsher 		if (!status) {
18009aebddd1SJeff Kirsher 			struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
180103d28ffeSKalesh AP 
18029aebddd1SJeff Kirsher 			memcpy(buf + offset,
18039aebddd1SJeff Kirsher 			       resp->data_buffer,
180492aa9214SSomnath Kotur 			       le32_to_cpu(resp->read_log_length));
18059aebddd1SJeff Kirsher 		} else {
18069aebddd1SJeff Kirsher 			dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
18079aebddd1SJeff Kirsher 			goto err;
18089aebddd1SJeff Kirsher 		}
18099aebddd1SJeff Kirsher 		offset += buf_size;
18109aebddd1SJeff Kirsher 		log_offset += buf_size;
18119aebddd1SJeff Kirsher 	}
18129aebddd1SJeff Kirsher err:
1813e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, get_fat_cmd.size,
1814a2cc4e0bSSathya Perla 			  get_fat_cmd.va, get_fat_cmd.dma);
18159aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1816c5f156deSVasundhara Volam 	return status;
18179aebddd1SJeff Kirsher }
18189aebddd1SJeff Kirsher 
181904b71175SSathya Perla /* Uses synchronous mcc */
1820e97e3cdaSKalesh AP int be_cmd_get_fw_ver(struct be_adapter *adapter)
18219aebddd1SJeff Kirsher {
18229aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
18239aebddd1SJeff Kirsher 	struct be_cmd_req_get_fw_version *req;
18249aebddd1SJeff Kirsher 	int status;
18259aebddd1SJeff Kirsher 
182604b71175SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
18279aebddd1SJeff Kirsher 
182804b71175SSathya Perla 	wrb = wrb_from_mccq(adapter);
182904b71175SSathya Perla 	if (!wrb) {
183004b71175SSathya Perla 		status = -EBUSY;
183104b71175SSathya Perla 		goto err;
183204b71175SSathya Perla 	}
183304b71175SSathya Perla 
18349aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
18359aebddd1SJeff Kirsher 
1836106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1837a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb,
1838a2cc4e0bSSathya Perla 			       NULL);
183904b71175SSathya Perla 	status = be_mcc_notify_wait(adapter);
18409aebddd1SJeff Kirsher 	if (!status) {
18419aebddd1SJeff Kirsher 		struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
1842acbafeb1SSathya Perla 
1843242eb470SVasundhara Volam 		strlcpy(adapter->fw_ver, resp->firmware_version_string,
1844242eb470SVasundhara Volam 			sizeof(adapter->fw_ver));
1845242eb470SVasundhara Volam 		strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string,
1846242eb470SVasundhara Volam 			sizeof(adapter->fw_on_flash));
18479aebddd1SJeff Kirsher 	}
184804b71175SSathya Perla err:
184904b71175SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
18509aebddd1SJeff Kirsher 	return status;
18519aebddd1SJeff Kirsher }
18529aebddd1SJeff Kirsher 
18539aebddd1SJeff Kirsher /* set the EQ delay interval of an EQ to specified value
18549aebddd1SJeff Kirsher  * Uses async mcc
18559aebddd1SJeff Kirsher  */
1856b502ae8dSKalesh AP static int __be_cmd_modify_eqd(struct be_adapter *adapter,
1857b502ae8dSKalesh AP 			       struct be_set_eqd *set_eqd, int num)
18589aebddd1SJeff Kirsher {
18599aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
18609aebddd1SJeff Kirsher 	struct be_cmd_req_modify_eq_delay *req;
18612632bafdSSathya Perla 	int status = 0, i;
18629aebddd1SJeff Kirsher 
18639aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
18649aebddd1SJeff Kirsher 
18659aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
18669aebddd1SJeff Kirsher 	if (!wrb) {
18679aebddd1SJeff Kirsher 		status = -EBUSY;
18689aebddd1SJeff Kirsher 		goto err;
18699aebddd1SJeff Kirsher 	}
18709aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
18719aebddd1SJeff Kirsher 
1872106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1873a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb,
1874a2cc4e0bSSathya Perla 			       NULL);
18759aebddd1SJeff Kirsher 
18762632bafdSSathya Perla 	req->num_eq = cpu_to_le32(num);
18772632bafdSSathya Perla 	for (i = 0; i < num; i++) {
18782632bafdSSathya Perla 		req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
18792632bafdSSathya Perla 		req->set_eqd[i].phase = 0;
18802632bafdSSathya Perla 		req->set_eqd[i].delay_multiplier =
18812632bafdSSathya Perla 				cpu_to_le32(set_eqd[i].delay_multiplier);
18822632bafdSSathya Perla 	}
18839aebddd1SJeff Kirsher 
1884efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
18859aebddd1SJeff Kirsher err:
18869aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
18879aebddd1SJeff Kirsher 	return status;
18889aebddd1SJeff Kirsher }
18899aebddd1SJeff Kirsher 
189093676703SKalesh AP int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd,
189193676703SKalesh AP 		      int num)
189293676703SKalesh AP {
189393676703SKalesh AP 	int num_eqs, i = 0;
189493676703SKalesh AP 
189593676703SKalesh AP 	while (num) {
189693676703SKalesh AP 		num_eqs = min(num, 8);
189793676703SKalesh AP 		__be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs);
189893676703SKalesh AP 		i += num_eqs;
189993676703SKalesh AP 		num -= num_eqs;
190093676703SKalesh AP 	}
190193676703SKalesh AP 
190293676703SKalesh AP 	return 0;
190393676703SKalesh AP }
190493676703SKalesh AP 
19059aebddd1SJeff Kirsher /* Uses sycnhronous mcc */
19069aebddd1SJeff Kirsher int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
1907435452aaSVasundhara Volam 		       u32 num, u32 domain)
19089aebddd1SJeff Kirsher {
19099aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
19109aebddd1SJeff Kirsher 	struct be_cmd_req_vlan_config *req;
19119aebddd1SJeff Kirsher 	int status;
19129aebddd1SJeff Kirsher 
19139aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
19149aebddd1SJeff Kirsher 
19159aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
19169aebddd1SJeff Kirsher 	if (!wrb) {
19179aebddd1SJeff Kirsher 		status = -EBUSY;
19189aebddd1SJeff Kirsher 		goto err;
19199aebddd1SJeff Kirsher 	}
19209aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
19219aebddd1SJeff Kirsher 
1922106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1923a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req),
1924a2cc4e0bSSathya Perla 			       wrb, NULL);
1925435452aaSVasundhara Volam 	req->hdr.domain = domain;
19269aebddd1SJeff Kirsher 
19279aebddd1SJeff Kirsher 	req->interface_id = if_id;
1928012bd387SAjit Khaparde 	req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0;
19299aebddd1SJeff Kirsher 	req->num_vlan = num;
19309aebddd1SJeff Kirsher 	memcpy(req->normal_vlan, vtag_array,
19319aebddd1SJeff Kirsher 	       req->num_vlan * sizeof(vtag_array[0]));
19329aebddd1SJeff Kirsher 
19339aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
19349aebddd1SJeff Kirsher err:
19359aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
19369aebddd1SJeff Kirsher 	return status;
19379aebddd1SJeff Kirsher }
19389aebddd1SJeff Kirsher 
1939ac34b743SSathya Perla static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
19409aebddd1SJeff Kirsher {
19419aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
19429aebddd1SJeff Kirsher 	struct be_dma_mem *mem = &adapter->rx_filter;
19439aebddd1SJeff Kirsher 	struct be_cmd_req_rx_filter *req = mem->va;
19449aebddd1SJeff Kirsher 	int status;
19459aebddd1SJeff Kirsher 
19469aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
19479aebddd1SJeff Kirsher 
19489aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
19499aebddd1SJeff Kirsher 	if (!wrb) {
19509aebddd1SJeff Kirsher 		status = -EBUSY;
19519aebddd1SJeff Kirsher 		goto err;
19529aebddd1SJeff Kirsher 	}
19539aebddd1SJeff Kirsher 	memset(req, 0, sizeof(*req));
1954106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1955106df1e3SSomnath Kotur 			       OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req),
1956106df1e3SSomnath Kotur 			       wrb, mem);
19579aebddd1SJeff Kirsher 
19589aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(adapter->if_handle);
1959ac34b743SSathya Perla 	req->if_flags_mask = cpu_to_le32(flags);
1960ac34b743SSathya Perla 	req->if_flags = (value == ON) ? req->if_flags_mask : 0;
1961d9d604f8SAjit Khaparde 
1962ac34b743SSathya Perla 	if (flags & BE_IF_FLAGS_MULTICAST) {
19639aebddd1SJeff Kirsher 		struct netdev_hw_addr *ha;
19649aebddd1SJeff Kirsher 		int i = 0;
19659aebddd1SJeff Kirsher 
19661610c79fSPadmanabh Ratnakar 		/* Reset mcast promisc mode if already set by setting mask
19671610c79fSPadmanabh Ratnakar 		 * and not setting flags field
19681610c79fSPadmanabh Ratnakar 		 */
19691610c79fSPadmanabh Ratnakar 		req->if_flags_mask |=
1970abb93951SPadmanabh Ratnakar 			cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
197192bf14abSSathya Perla 				    be_if_cap_flags(adapter));
1972016f97b1SPadmanabh Ratnakar 		req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev));
19739aebddd1SJeff Kirsher 		netdev_for_each_mc_addr(ha, adapter->netdev)
19749aebddd1SJeff Kirsher 			memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN);
19759aebddd1SJeff Kirsher 	}
19769aebddd1SJeff Kirsher 
1977b6588879SSathya Perla 	status = be_mcc_notify_wait(adapter);
19789aebddd1SJeff Kirsher err:
19799aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
19809aebddd1SJeff Kirsher 	return status;
19819aebddd1SJeff Kirsher }
19829aebddd1SJeff Kirsher 
1983ac34b743SSathya Perla int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
1984ac34b743SSathya Perla {
1985ac34b743SSathya Perla 	struct device *dev = &adapter->pdev->dev;
1986ac34b743SSathya Perla 
1987ac34b743SSathya Perla 	if ((flags & be_if_cap_flags(adapter)) != flags) {
1988ac34b743SSathya Perla 		dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags);
1989ac34b743SSathya Perla 		dev_warn(dev, "Interface is capable of 0x%x flags only\n",
1990ac34b743SSathya Perla 			 be_if_cap_flags(adapter));
1991ac34b743SSathya Perla 	}
1992ac34b743SSathya Perla 	flags &= be_if_cap_flags(adapter);
1993196e3735SKalesh AP 	if (!flags)
1994196e3735SKalesh AP 		return -ENOTSUPP;
1995ac34b743SSathya Perla 
1996ac34b743SSathya Perla 	return __be_cmd_rx_filter(adapter, flags, value);
1997ac34b743SSathya Perla }
1998ac34b743SSathya Perla 
19999aebddd1SJeff Kirsher /* Uses synchrounous mcc */
20009aebddd1SJeff Kirsher int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
20019aebddd1SJeff Kirsher {
20029aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20039aebddd1SJeff Kirsher 	struct be_cmd_req_set_flow_control *req;
20049aebddd1SJeff Kirsher 	int status;
20059aebddd1SJeff Kirsher 
2006f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
2007f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
2008f25b119cSPadmanabh Ratnakar 		return -EPERM;
2009f25b119cSPadmanabh Ratnakar 
20109aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
20119aebddd1SJeff Kirsher 
20129aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
20139aebddd1SJeff Kirsher 	if (!wrb) {
20149aebddd1SJeff Kirsher 		status = -EBUSY;
20159aebddd1SJeff Kirsher 		goto err;
20169aebddd1SJeff Kirsher 	}
20179aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20189aebddd1SJeff Kirsher 
2019106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2020a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req),
2021a2cc4e0bSSathya Perla 			       wrb, NULL);
20229aebddd1SJeff Kirsher 
2023b29812c1SSuresh Reddy 	req->hdr.version = 1;
20249aebddd1SJeff Kirsher 	req->tx_flow_control = cpu_to_le16((u16)tx_fc);
20259aebddd1SJeff Kirsher 	req->rx_flow_control = cpu_to_le16((u16)rx_fc);
20269aebddd1SJeff Kirsher 
20279aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
20289aebddd1SJeff Kirsher 
20299aebddd1SJeff Kirsher err:
20309aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
2031b29812c1SSuresh Reddy 
2032b29812c1SSuresh Reddy 	if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED)
2033b29812c1SSuresh Reddy 		return  -EOPNOTSUPP;
2034b29812c1SSuresh Reddy 
20359aebddd1SJeff Kirsher 	return status;
20369aebddd1SJeff Kirsher }
20379aebddd1SJeff Kirsher 
20389aebddd1SJeff Kirsher /* Uses sycn mcc */
20399aebddd1SJeff Kirsher int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
20409aebddd1SJeff Kirsher {
20419aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20429aebddd1SJeff Kirsher 	struct be_cmd_req_get_flow_control *req;
20439aebddd1SJeff Kirsher 	int status;
20449aebddd1SJeff Kirsher 
2045f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
2046f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
2047f25b119cSPadmanabh Ratnakar 		return -EPERM;
2048f25b119cSPadmanabh Ratnakar 
20499aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
20509aebddd1SJeff Kirsher 
20519aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
20529aebddd1SJeff Kirsher 	if (!wrb) {
20539aebddd1SJeff Kirsher 		status = -EBUSY;
20549aebddd1SJeff Kirsher 		goto err;
20559aebddd1SJeff Kirsher 	}
20569aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20579aebddd1SJeff Kirsher 
2058106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2059a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req),
2060a2cc4e0bSSathya Perla 			       wrb, NULL);
20619aebddd1SJeff Kirsher 
20629aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
20639aebddd1SJeff Kirsher 	if (!status) {
20649aebddd1SJeff Kirsher 		struct be_cmd_resp_get_flow_control *resp =
20659aebddd1SJeff Kirsher 						embedded_payload(wrb);
206603d28ffeSKalesh AP 
20679aebddd1SJeff Kirsher 		*tx_fc = le16_to_cpu(resp->tx_flow_control);
20689aebddd1SJeff Kirsher 		*rx_fc = le16_to_cpu(resp->rx_flow_control);
20699aebddd1SJeff Kirsher 	}
20709aebddd1SJeff Kirsher 
20719aebddd1SJeff Kirsher err:
20729aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
20739aebddd1SJeff Kirsher 	return status;
20749aebddd1SJeff Kirsher }
20759aebddd1SJeff Kirsher 
20769aebddd1SJeff Kirsher /* Uses mbox */
2077e97e3cdaSKalesh AP int be_cmd_query_fw_cfg(struct be_adapter *adapter)
20789aebddd1SJeff Kirsher {
20799aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20809aebddd1SJeff Kirsher 	struct be_cmd_req_query_fw_cfg *req;
20819aebddd1SJeff Kirsher 	int status;
20829aebddd1SJeff Kirsher 
20839aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
20849aebddd1SJeff Kirsher 		return -1;
20859aebddd1SJeff Kirsher 
20869aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
20879aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20889aebddd1SJeff Kirsher 
2089106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2090a2cc4e0bSSathya Perla 			       OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
2091a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
20929aebddd1SJeff Kirsher 
20939aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
20949aebddd1SJeff Kirsher 	if (!status) {
20959aebddd1SJeff Kirsher 		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
209603d28ffeSKalesh AP 
2097e97e3cdaSKalesh AP 		adapter->port_num = le32_to_cpu(resp->phys_port);
2098e97e3cdaSKalesh AP 		adapter->function_mode = le32_to_cpu(resp->function_mode);
2099e97e3cdaSKalesh AP 		adapter->function_caps = le32_to_cpu(resp->function_caps);
2100e97e3cdaSKalesh AP 		adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
2101acbafeb1SSathya Perla 		dev_info(&adapter->pdev->dev,
2102acbafeb1SSathya Perla 			 "FW config: function_mode=0x%x, function_caps=0x%x\n",
2103acbafeb1SSathya Perla 			 adapter->function_mode, adapter->function_caps);
21049aebddd1SJeff Kirsher 	}
21059aebddd1SJeff Kirsher 
21069aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
21079aebddd1SJeff Kirsher 	return status;
21089aebddd1SJeff Kirsher }
21099aebddd1SJeff Kirsher 
21109aebddd1SJeff Kirsher /* Uses mbox */
21119aebddd1SJeff Kirsher int be_cmd_reset_function(struct be_adapter *adapter)
21129aebddd1SJeff Kirsher {
21139aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21149aebddd1SJeff Kirsher 	struct be_cmd_req_hdr *req;
21159aebddd1SJeff Kirsher 	int status;
21169aebddd1SJeff Kirsher 
2117bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter)) {
2118bf99e50dSPadmanabh Ratnakar 		iowrite32(SLI_PORT_CONTROL_IP_MASK,
2119bf99e50dSPadmanabh Ratnakar 			  adapter->db + SLIPORT_CONTROL_OFFSET);
21209fa465c0SSathya Perla 		status = lancer_wait_ready(adapter);
21219fa465c0SSathya Perla 		if (status)
2122bf99e50dSPadmanabh Ratnakar 			dev_err(&adapter->pdev->dev,
2123bf99e50dSPadmanabh Ratnakar 				"Adapter in non recoverable error\n");
2124bf99e50dSPadmanabh Ratnakar 		return status;
2125bf99e50dSPadmanabh Ratnakar 	}
2126bf99e50dSPadmanabh Ratnakar 
21279aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
21289aebddd1SJeff Kirsher 		return -1;
21299aebddd1SJeff Kirsher 
21309aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
21319aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21329aebddd1SJeff Kirsher 
2133106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
2134a2cc4e0bSSathya Perla 			       OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb,
2135a2cc4e0bSSathya Perla 			       NULL);
21369aebddd1SJeff Kirsher 
21379aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
21389aebddd1SJeff Kirsher 
21399aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
21409aebddd1SJeff Kirsher 	return status;
21419aebddd1SJeff Kirsher }
21429aebddd1SJeff Kirsher 
2143594ad54aSSuresh Reddy int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
214433cb0fa7SBen Hutchings 		      u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey)
21459aebddd1SJeff Kirsher {
21469aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21479aebddd1SJeff Kirsher 	struct be_cmd_req_rss_config *req;
21489aebddd1SJeff Kirsher 	int status;
21499aebddd1SJeff Kirsher 
2150da1388d6SVasundhara Volam 	if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
2151da1388d6SVasundhara Volam 		return 0;
2152da1388d6SVasundhara Volam 
2153b51aa367SKalesh AP 	spin_lock_bh(&adapter->mcc_lock);
21549aebddd1SJeff Kirsher 
2155b51aa367SKalesh AP 	wrb = wrb_from_mccq(adapter);
2156b51aa367SKalesh AP 	if (!wrb) {
2157b51aa367SKalesh AP 		status = -EBUSY;
2158b51aa367SKalesh AP 		goto err;
2159b51aa367SKalesh AP 	}
21609aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21619aebddd1SJeff Kirsher 
2162106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
2163106df1e3SSomnath Kotur 			       OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
21649aebddd1SJeff Kirsher 
21659aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(adapter->if_handle);
2166594ad54aSSuresh Reddy 	req->enable_rss = cpu_to_le16(rss_hash_opts);
21679aebddd1SJeff Kirsher 	req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
2168594ad54aSSuresh Reddy 
2169b51aa367SKalesh AP 	if (!BEx_chip(adapter))
2170594ad54aSSuresh Reddy 		req->hdr.version = 1;
2171594ad54aSSuresh Reddy 
21729aebddd1SJeff Kirsher 	memcpy(req->cpu_table, rsstable, table_size);
2173e2557877SVenkata Duvvuru 	memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN);
21749aebddd1SJeff Kirsher 	be_dws_cpu_to_le(req->hash, sizeof(req->hash));
21759aebddd1SJeff Kirsher 
2176b51aa367SKalesh AP 	status = be_mcc_notify_wait(adapter);
2177b51aa367SKalesh AP err:
2178b51aa367SKalesh AP 	spin_unlock_bh(&adapter->mcc_lock);
21799aebddd1SJeff Kirsher 	return status;
21809aebddd1SJeff Kirsher }
21819aebddd1SJeff Kirsher 
21829aebddd1SJeff Kirsher /* Uses sync mcc */
21839aebddd1SJeff Kirsher int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
21849aebddd1SJeff Kirsher 			    u8 bcn, u8 sts, u8 state)
21859aebddd1SJeff Kirsher {
21869aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21879aebddd1SJeff Kirsher 	struct be_cmd_req_enable_disable_beacon *req;
21889aebddd1SJeff Kirsher 	int status;
21899aebddd1SJeff Kirsher 
21909aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
21919aebddd1SJeff Kirsher 
21929aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
21939aebddd1SJeff Kirsher 	if (!wrb) {
21949aebddd1SJeff Kirsher 		status = -EBUSY;
21959aebddd1SJeff Kirsher 		goto err;
21969aebddd1SJeff Kirsher 	}
21979aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21989aebddd1SJeff Kirsher 
2199106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2200a2cc4e0bSSathya Perla 			       OPCODE_COMMON_ENABLE_DISABLE_BEACON,
2201a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
22029aebddd1SJeff Kirsher 
22039aebddd1SJeff Kirsher 	req->port_num = port_num;
22049aebddd1SJeff Kirsher 	req->beacon_state = state;
22059aebddd1SJeff Kirsher 	req->beacon_duration = bcn;
22069aebddd1SJeff Kirsher 	req->status_duration = sts;
22079aebddd1SJeff Kirsher 
22089aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
22099aebddd1SJeff Kirsher 
22109aebddd1SJeff Kirsher err:
22119aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
22129aebddd1SJeff Kirsher 	return status;
22139aebddd1SJeff Kirsher }
22149aebddd1SJeff Kirsher 
22159aebddd1SJeff Kirsher /* Uses sync mcc */
22169aebddd1SJeff Kirsher int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
22179aebddd1SJeff Kirsher {
22189aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
22199aebddd1SJeff Kirsher 	struct be_cmd_req_get_beacon_state *req;
22209aebddd1SJeff Kirsher 	int status;
22219aebddd1SJeff Kirsher 
22229aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
22239aebddd1SJeff Kirsher 
22249aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
22259aebddd1SJeff Kirsher 	if (!wrb) {
22269aebddd1SJeff Kirsher 		status = -EBUSY;
22279aebddd1SJeff Kirsher 		goto err;
22289aebddd1SJeff Kirsher 	}
22299aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
22309aebddd1SJeff Kirsher 
2231106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2232a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req),
2233a2cc4e0bSSathya Perla 			       wrb, NULL);
22349aebddd1SJeff Kirsher 
22359aebddd1SJeff Kirsher 	req->port_num = port_num;
22369aebddd1SJeff Kirsher 
22379aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
22389aebddd1SJeff Kirsher 	if (!status) {
22399aebddd1SJeff Kirsher 		struct be_cmd_resp_get_beacon_state *resp =
22409aebddd1SJeff Kirsher 						embedded_payload(wrb);
224103d28ffeSKalesh AP 
22429aebddd1SJeff Kirsher 		*state = resp->beacon_state;
22439aebddd1SJeff Kirsher 	}
22449aebddd1SJeff Kirsher 
22459aebddd1SJeff Kirsher err:
22469aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
22479aebddd1SJeff Kirsher 	return status;
22489aebddd1SJeff Kirsher }
22499aebddd1SJeff Kirsher 
2250e36edd9dSMark Leonard /* Uses sync mcc */
2251e36edd9dSMark Leonard int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
2252e36edd9dSMark Leonard 				      u8 page_num, u8 *data)
2253e36edd9dSMark Leonard {
2254e36edd9dSMark Leonard 	struct be_dma_mem cmd;
2255e36edd9dSMark Leonard 	struct be_mcc_wrb *wrb;
2256e36edd9dSMark Leonard 	struct be_cmd_req_port_type *req;
2257e36edd9dSMark Leonard 	int status;
2258e36edd9dSMark Leonard 
2259e36edd9dSMark Leonard 	if (page_num > TR_PAGE_A2)
2260e36edd9dSMark Leonard 		return -EINVAL;
2261e36edd9dSMark Leonard 
2262e36edd9dSMark Leonard 	cmd.size = sizeof(struct be_cmd_resp_port_type);
2263e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
2264e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
2265e36edd9dSMark Leonard 	if (!cmd.va) {
2266e36edd9dSMark Leonard 		dev_err(&adapter->pdev->dev, "Memory allocation failed\n");
2267e36edd9dSMark Leonard 		return -ENOMEM;
2268e36edd9dSMark Leonard 	}
2269e36edd9dSMark Leonard 
2270e36edd9dSMark Leonard 	spin_lock_bh(&adapter->mcc_lock);
2271e36edd9dSMark Leonard 
2272e36edd9dSMark Leonard 	wrb = wrb_from_mccq(adapter);
2273e36edd9dSMark Leonard 	if (!wrb) {
2274e36edd9dSMark Leonard 		status = -EBUSY;
2275e36edd9dSMark Leonard 		goto err;
2276e36edd9dSMark Leonard 	}
2277e36edd9dSMark Leonard 	req = cmd.va;
2278e36edd9dSMark Leonard 
2279e36edd9dSMark Leonard 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2280e36edd9dSMark Leonard 			       OPCODE_COMMON_READ_TRANSRECV_DATA,
2281e36edd9dSMark Leonard 			       cmd.size, wrb, &cmd);
2282e36edd9dSMark Leonard 
2283e36edd9dSMark Leonard 	req->port = cpu_to_le32(adapter->hba_port_num);
2284e36edd9dSMark Leonard 	req->page_num = cpu_to_le32(page_num);
2285e36edd9dSMark Leonard 	status = be_mcc_notify_wait(adapter);
2286e36edd9dSMark Leonard 	if (!status) {
2287e36edd9dSMark Leonard 		struct be_cmd_resp_port_type *resp = cmd.va;
2288e36edd9dSMark Leonard 
2289e36edd9dSMark Leonard 		memcpy(data, resp->page_data, PAGE_DATA_LEN);
2290e36edd9dSMark Leonard 	}
2291e36edd9dSMark Leonard err:
2292e36edd9dSMark Leonard 	spin_unlock_bh(&adapter->mcc_lock);
2293e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
2294e36edd9dSMark Leonard 	return status;
2295e36edd9dSMark Leonard }
2296e36edd9dSMark Leonard 
2297a23113b5SSuresh Reddy static int lancer_cmd_write_object(struct be_adapter *adapter,
2298a23113b5SSuresh Reddy 				   struct be_dma_mem *cmd, u32 data_size,
2299a23113b5SSuresh Reddy 				   u32 data_offset, const char *obj_name,
2300a23113b5SSuresh Reddy 				   u32 *data_written, u8 *change_status,
2301a23113b5SSuresh Reddy 				   u8 *addn_status)
23029aebddd1SJeff Kirsher {
23039aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
23049aebddd1SJeff Kirsher 	struct lancer_cmd_req_write_object *req;
23059aebddd1SJeff Kirsher 	struct lancer_cmd_resp_write_object *resp;
23069aebddd1SJeff Kirsher 	void *ctxt = NULL;
23079aebddd1SJeff Kirsher 	int status;
23089aebddd1SJeff Kirsher 
23099aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
23109aebddd1SJeff Kirsher 	adapter->flash_status = 0;
23119aebddd1SJeff Kirsher 
23129aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
23139aebddd1SJeff Kirsher 	if (!wrb) {
23149aebddd1SJeff Kirsher 		status = -EBUSY;
23159aebddd1SJeff Kirsher 		goto err_unlock;
23169aebddd1SJeff Kirsher 	}
23179aebddd1SJeff Kirsher 
23189aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
23199aebddd1SJeff Kirsher 
2320106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
23219aebddd1SJeff Kirsher 			       OPCODE_COMMON_WRITE_OBJECT,
2322106df1e3SSomnath Kotur 			       sizeof(struct lancer_cmd_req_write_object), wrb,
2323106df1e3SSomnath Kotur 			       NULL);
23249aebddd1SJeff Kirsher 
23259aebddd1SJeff Kirsher 	ctxt = &req->context;
23269aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_lancer_write_obj_context,
23279aebddd1SJeff Kirsher 		      write_length, ctxt, data_size);
23289aebddd1SJeff Kirsher 
23299aebddd1SJeff Kirsher 	if (data_size == 0)
23309aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
23319aebddd1SJeff Kirsher 			      eof, ctxt, 1);
23329aebddd1SJeff Kirsher 	else
23339aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
23349aebddd1SJeff Kirsher 			      eof, ctxt, 0);
23359aebddd1SJeff Kirsher 
23369aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
23379aebddd1SJeff Kirsher 	req->write_offset = cpu_to_le32(data_offset);
2338242eb470SVasundhara Volam 	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
23399aebddd1SJeff Kirsher 	req->descriptor_count = cpu_to_le32(1);
23409aebddd1SJeff Kirsher 	req->buf_len = cpu_to_le32(data_size);
23419aebddd1SJeff Kirsher 	req->addr_low = cpu_to_le32((cmd->dma +
23429aebddd1SJeff Kirsher 				     sizeof(struct lancer_cmd_req_write_object))
23439aebddd1SJeff Kirsher 				    & 0xFFFFFFFF);
23449aebddd1SJeff Kirsher 	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma +
23459aebddd1SJeff Kirsher 				sizeof(struct lancer_cmd_req_write_object)));
23469aebddd1SJeff Kirsher 
2347efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
2348efaa408eSSuresh Reddy 	if (status)
2349efaa408eSSuresh Reddy 		goto err_unlock;
2350efaa408eSSuresh Reddy 
23519aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
23529aebddd1SJeff Kirsher 
23535eeff635SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
2354701962d0SSomnath Kotur 					 msecs_to_jiffies(60000)))
2355fd45160cSKalesh AP 		status = -ETIMEDOUT;
23569aebddd1SJeff Kirsher 	else
23579aebddd1SJeff Kirsher 		status = adapter->flash_status;
23589aebddd1SJeff Kirsher 
23599aebddd1SJeff Kirsher 	resp = embedded_payload(wrb);
2360f67ef7baSPadmanabh Ratnakar 	if (!status) {
23619aebddd1SJeff Kirsher 		*data_written = le32_to_cpu(resp->actual_write_len);
2362f67ef7baSPadmanabh Ratnakar 		*change_status = resp->change_status;
2363f67ef7baSPadmanabh Ratnakar 	} else {
23649aebddd1SJeff Kirsher 		*addn_status = resp->additional_status;
2365f67ef7baSPadmanabh Ratnakar 	}
23669aebddd1SJeff Kirsher 
23679aebddd1SJeff Kirsher 	return status;
23689aebddd1SJeff Kirsher 
23699aebddd1SJeff Kirsher err_unlock:
23709aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
23719aebddd1SJeff Kirsher 	return status;
23729aebddd1SJeff Kirsher }
23739aebddd1SJeff Kirsher 
23746809cee0SRavikumar Nelavelli int be_cmd_query_cable_type(struct be_adapter *adapter)
23756809cee0SRavikumar Nelavelli {
23766809cee0SRavikumar Nelavelli 	u8 page_data[PAGE_DATA_LEN];
23776809cee0SRavikumar Nelavelli 	int status;
23786809cee0SRavikumar Nelavelli 
23796809cee0SRavikumar Nelavelli 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
23806809cee0SRavikumar Nelavelli 						   page_data);
23816809cee0SRavikumar Nelavelli 	if (!status) {
23826809cee0SRavikumar Nelavelli 		switch (adapter->phy.interface_type) {
23836809cee0SRavikumar Nelavelli 		case PHY_TYPE_QSFP:
23846809cee0SRavikumar Nelavelli 			adapter->phy.cable_type =
23856809cee0SRavikumar Nelavelli 				page_data[QSFP_PLUS_CABLE_TYPE_OFFSET];
23866809cee0SRavikumar Nelavelli 			break;
23876809cee0SRavikumar Nelavelli 		case PHY_TYPE_SFP_PLUS_10GB:
23886809cee0SRavikumar Nelavelli 			adapter->phy.cable_type =
23896809cee0SRavikumar Nelavelli 				page_data[SFP_PLUS_CABLE_TYPE_OFFSET];
23906809cee0SRavikumar Nelavelli 			break;
23916809cee0SRavikumar Nelavelli 		default:
23926809cee0SRavikumar Nelavelli 			adapter->phy.cable_type = 0;
23936809cee0SRavikumar Nelavelli 			break;
23946809cee0SRavikumar Nelavelli 		}
23956809cee0SRavikumar Nelavelli 	}
23966809cee0SRavikumar Nelavelli 	return status;
23976809cee0SRavikumar Nelavelli }
23986809cee0SRavikumar Nelavelli 
239921252377SVasundhara Volam int be_cmd_query_sfp_info(struct be_adapter *adapter)
240021252377SVasundhara Volam {
240121252377SVasundhara Volam 	u8 page_data[PAGE_DATA_LEN];
240221252377SVasundhara Volam 	int status;
240321252377SVasundhara Volam 
240421252377SVasundhara Volam 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
240521252377SVasundhara Volam 						   page_data);
240621252377SVasundhara Volam 	if (!status) {
240721252377SVasundhara Volam 		strlcpy(adapter->phy.vendor_name, page_data +
240821252377SVasundhara Volam 			SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
240921252377SVasundhara Volam 		strlcpy(adapter->phy.vendor_pn,
241021252377SVasundhara Volam 			page_data + SFP_VENDOR_PN_OFFSET,
241121252377SVasundhara Volam 			SFP_VENDOR_NAME_LEN - 1);
241221252377SVasundhara Volam 	}
241321252377SVasundhara Volam 
241421252377SVasundhara Volam 	return status;
241521252377SVasundhara Volam }
241621252377SVasundhara Volam 
2417a23113b5SSuresh Reddy static int lancer_cmd_delete_object(struct be_adapter *adapter,
2418a23113b5SSuresh Reddy 				    const char *obj_name)
2419f0613380SKalesh AP {
2420f0613380SKalesh AP 	struct lancer_cmd_req_delete_object *req;
2421f0613380SKalesh AP 	struct be_mcc_wrb *wrb;
2422f0613380SKalesh AP 	int status;
2423f0613380SKalesh AP 
2424f0613380SKalesh AP 	spin_lock_bh(&adapter->mcc_lock);
2425f0613380SKalesh AP 
2426f0613380SKalesh AP 	wrb = wrb_from_mccq(adapter);
2427f0613380SKalesh AP 	if (!wrb) {
2428f0613380SKalesh AP 		status = -EBUSY;
2429f0613380SKalesh AP 		goto err;
2430f0613380SKalesh AP 	}
2431f0613380SKalesh AP 
2432f0613380SKalesh AP 	req = embedded_payload(wrb);
2433f0613380SKalesh AP 
2434f0613380SKalesh AP 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2435f0613380SKalesh AP 			       OPCODE_COMMON_DELETE_OBJECT,
2436f0613380SKalesh AP 			       sizeof(*req), wrb, NULL);
2437f0613380SKalesh AP 
2438242eb470SVasundhara Volam 	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
2439f0613380SKalesh AP 
2440f0613380SKalesh AP 	status = be_mcc_notify_wait(adapter);
2441f0613380SKalesh AP err:
2442f0613380SKalesh AP 	spin_unlock_bh(&adapter->mcc_lock);
2443f0613380SKalesh AP 	return status;
2444f0613380SKalesh AP }
2445f0613380SKalesh AP 
2446de49bd5aSPadmanabh Ratnakar int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
2447de49bd5aSPadmanabh Ratnakar 			   u32 data_size, u32 data_offset, const char *obj_name,
2448de49bd5aSPadmanabh Ratnakar 			   u32 *data_read, u32 *eof, u8 *addn_status)
2449de49bd5aSPadmanabh Ratnakar {
2450de49bd5aSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
2451de49bd5aSPadmanabh Ratnakar 	struct lancer_cmd_req_read_object *req;
2452de49bd5aSPadmanabh Ratnakar 	struct lancer_cmd_resp_read_object *resp;
2453de49bd5aSPadmanabh Ratnakar 	int status;
2454de49bd5aSPadmanabh Ratnakar 
2455de49bd5aSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
2456de49bd5aSPadmanabh Ratnakar 
2457de49bd5aSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
2458de49bd5aSPadmanabh Ratnakar 	if (!wrb) {
2459de49bd5aSPadmanabh Ratnakar 		status = -EBUSY;
2460de49bd5aSPadmanabh Ratnakar 		goto err_unlock;
2461de49bd5aSPadmanabh Ratnakar 	}
2462de49bd5aSPadmanabh Ratnakar 
2463de49bd5aSPadmanabh Ratnakar 	req = embedded_payload(wrb);
2464de49bd5aSPadmanabh Ratnakar 
2465de49bd5aSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2466de49bd5aSPadmanabh Ratnakar 			       OPCODE_COMMON_READ_OBJECT,
2467de49bd5aSPadmanabh Ratnakar 			       sizeof(struct lancer_cmd_req_read_object), wrb,
2468de49bd5aSPadmanabh Ratnakar 			       NULL);
2469de49bd5aSPadmanabh Ratnakar 
2470de49bd5aSPadmanabh Ratnakar 	req->desired_read_len = cpu_to_le32(data_size);
2471de49bd5aSPadmanabh Ratnakar 	req->read_offset = cpu_to_le32(data_offset);
2472de49bd5aSPadmanabh Ratnakar 	strcpy(req->object_name, obj_name);
2473de49bd5aSPadmanabh Ratnakar 	req->descriptor_count = cpu_to_le32(1);
2474de49bd5aSPadmanabh Ratnakar 	req->buf_len = cpu_to_le32(data_size);
2475de49bd5aSPadmanabh Ratnakar 	req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF));
2476de49bd5aSPadmanabh Ratnakar 	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma));
2477de49bd5aSPadmanabh Ratnakar 
2478de49bd5aSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
2479de49bd5aSPadmanabh Ratnakar 
2480de49bd5aSPadmanabh Ratnakar 	resp = embedded_payload(wrb);
2481de49bd5aSPadmanabh Ratnakar 	if (!status) {
2482de49bd5aSPadmanabh Ratnakar 		*data_read = le32_to_cpu(resp->actual_read_len);
2483de49bd5aSPadmanabh Ratnakar 		*eof = le32_to_cpu(resp->eof);
2484de49bd5aSPadmanabh Ratnakar 	} else {
2485de49bd5aSPadmanabh Ratnakar 		*addn_status = resp->additional_status;
2486de49bd5aSPadmanabh Ratnakar 	}
2487de49bd5aSPadmanabh Ratnakar 
2488de49bd5aSPadmanabh Ratnakar err_unlock:
2489de49bd5aSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
2490de49bd5aSPadmanabh Ratnakar 	return status;
2491de49bd5aSPadmanabh Ratnakar }
2492de49bd5aSPadmanabh Ratnakar 
2493a23113b5SSuresh Reddy static int be_cmd_write_flashrom(struct be_adapter *adapter,
2494a23113b5SSuresh Reddy 				 struct be_dma_mem *cmd, u32 flash_type,
2495a23113b5SSuresh Reddy 				 u32 flash_opcode, u32 img_offset, u32 buf_size)
24969aebddd1SJeff Kirsher {
24979aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
24989aebddd1SJeff Kirsher 	struct be_cmd_write_flashrom *req;
24999aebddd1SJeff Kirsher 	int status;
25009aebddd1SJeff Kirsher 
25019aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
25029aebddd1SJeff Kirsher 	adapter->flash_status = 0;
25039aebddd1SJeff Kirsher 
25049aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
25059aebddd1SJeff Kirsher 	if (!wrb) {
25069aebddd1SJeff Kirsher 		status = -EBUSY;
25079aebddd1SJeff Kirsher 		goto err_unlock;
25089aebddd1SJeff Kirsher 	}
25099aebddd1SJeff Kirsher 	req = cmd->va;
25109aebddd1SJeff Kirsher 
2511106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2512a2cc4e0bSSathya Perla 			       OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb,
2513a2cc4e0bSSathya Perla 			       cmd);
25149aebddd1SJeff Kirsher 
25159aebddd1SJeff Kirsher 	req->params.op_type = cpu_to_le32(flash_type);
251670a7b525SVasundhara Volam 	if (flash_type == OPTYPE_OFFSET_SPECIFIED)
251770a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(img_offset);
251870a7b525SVasundhara Volam 
25199aebddd1SJeff Kirsher 	req->params.op_code = cpu_to_le32(flash_opcode);
25209aebddd1SJeff Kirsher 	req->params.data_buf_size = cpu_to_le32(buf_size);
25219aebddd1SJeff Kirsher 
2522efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
2523efaa408eSSuresh Reddy 	if (status)
2524efaa408eSSuresh Reddy 		goto err_unlock;
2525efaa408eSSuresh Reddy 
25269aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25279aebddd1SJeff Kirsher 
25285eeff635SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
2529e2edb7d5SSathya Perla 					 msecs_to_jiffies(40000)))
2530fd45160cSKalesh AP 		status = -ETIMEDOUT;
25319aebddd1SJeff Kirsher 	else
25329aebddd1SJeff Kirsher 		status = adapter->flash_status;
25339aebddd1SJeff Kirsher 
25349aebddd1SJeff Kirsher 	return status;
25359aebddd1SJeff Kirsher 
25369aebddd1SJeff Kirsher err_unlock:
25379aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25389aebddd1SJeff Kirsher 	return status;
25399aebddd1SJeff Kirsher }
25409aebddd1SJeff Kirsher 
2541a23113b5SSuresh Reddy static int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
254270a7b525SVasundhara Volam 				u16 img_optype, u32 img_offset, u32 crc_offset)
25439aebddd1SJeff Kirsher {
2544be716446SPadmanabh Ratnakar 	struct be_cmd_read_flash_crc *req;
254570a7b525SVasundhara Volam 	struct be_mcc_wrb *wrb;
25469aebddd1SJeff Kirsher 	int status;
25479aebddd1SJeff Kirsher 
25489aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
25499aebddd1SJeff Kirsher 
25509aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
25519aebddd1SJeff Kirsher 	if (!wrb) {
25529aebddd1SJeff Kirsher 		status = -EBUSY;
25539aebddd1SJeff Kirsher 		goto err;
25549aebddd1SJeff Kirsher 	}
25559aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
25569aebddd1SJeff Kirsher 
2557106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2558be716446SPadmanabh Ratnakar 			       OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
2559be716446SPadmanabh Ratnakar 			       wrb, NULL);
25609aebddd1SJeff Kirsher 
256170a7b525SVasundhara Volam 	req->params.op_type = cpu_to_le32(img_optype);
256270a7b525SVasundhara Volam 	if (img_optype == OPTYPE_OFFSET_SPECIFIED)
256370a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(img_offset + crc_offset);
256470a7b525SVasundhara Volam 	else
256570a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(crc_offset);
256670a7b525SVasundhara Volam 
25679aebddd1SJeff Kirsher 	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
25689aebddd1SJeff Kirsher 	req->params.data_buf_size = cpu_to_le32(0x4);
25699aebddd1SJeff Kirsher 
25709aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
25719aebddd1SJeff Kirsher 	if (!status)
2572be716446SPadmanabh Ratnakar 		memcpy(flashed_crc, req->crc, 4);
25739aebddd1SJeff Kirsher 
25749aebddd1SJeff Kirsher err:
25759aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25769aebddd1SJeff Kirsher 	return status;
25779aebddd1SJeff Kirsher }
25789aebddd1SJeff Kirsher 
2579a23113b5SSuresh Reddy static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
2580a23113b5SSuresh Reddy 
2581a23113b5SSuresh Reddy static bool phy_flashing_required(struct be_adapter *adapter)
2582a23113b5SSuresh Reddy {
2583a23113b5SSuresh Reddy 	return (adapter->phy.phy_type == PHY_TYPE_TN_8022 &&
2584a23113b5SSuresh Reddy 		adapter->phy.interface_type == PHY_TYPE_BASET_10GB);
2585a23113b5SSuresh Reddy }
2586a23113b5SSuresh Reddy 
2587a23113b5SSuresh Reddy static bool is_comp_in_ufi(struct be_adapter *adapter,
2588a23113b5SSuresh Reddy 			   struct flash_section_info *fsec, int type)
2589a23113b5SSuresh Reddy {
2590a23113b5SSuresh Reddy 	int i = 0, img_type = 0;
2591a23113b5SSuresh Reddy 	struct flash_section_info_g2 *fsec_g2 = NULL;
2592a23113b5SSuresh Reddy 
2593a23113b5SSuresh Reddy 	if (BE2_chip(adapter))
2594a23113b5SSuresh Reddy 		fsec_g2 = (struct flash_section_info_g2 *)fsec;
2595a23113b5SSuresh Reddy 
2596a23113b5SSuresh Reddy 	for (i = 0; i < MAX_FLASH_COMP; i++) {
2597a23113b5SSuresh Reddy 		if (fsec_g2)
2598a23113b5SSuresh Reddy 			img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type);
2599a23113b5SSuresh Reddy 		else
2600a23113b5SSuresh Reddy 			img_type = le32_to_cpu(fsec->fsec_entry[i].type);
2601a23113b5SSuresh Reddy 
2602a23113b5SSuresh Reddy 		if (img_type == type)
2603a23113b5SSuresh Reddy 			return true;
2604a23113b5SSuresh Reddy 	}
2605a23113b5SSuresh Reddy 	return false;
2606a23113b5SSuresh Reddy }
2607a23113b5SSuresh Reddy 
2608a23113b5SSuresh Reddy static struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
2609a23113b5SSuresh Reddy 						int header_size,
2610a23113b5SSuresh Reddy 						const struct firmware *fw)
2611a23113b5SSuresh Reddy {
2612a23113b5SSuresh Reddy 	struct flash_section_info *fsec = NULL;
2613a23113b5SSuresh Reddy 	const u8 *p = fw->data;
2614a23113b5SSuresh Reddy 
2615a23113b5SSuresh Reddy 	p += header_size;
2616a23113b5SSuresh Reddy 	while (p < (fw->data + fw->size)) {
2617a23113b5SSuresh Reddy 		fsec = (struct flash_section_info *)p;
2618a23113b5SSuresh Reddy 		if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie)))
2619a23113b5SSuresh Reddy 			return fsec;
2620a23113b5SSuresh Reddy 		p += 32;
2621a23113b5SSuresh Reddy 	}
2622a23113b5SSuresh Reddy 	return NULL;
2623a23113b5SSuresh Reddy }
2624a23113b5SSuresh Reddy 
2625a23113b5SSuresh Reddy static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
2626a23113b5SSuresh Reddy 			      u32 img_offset, u32 img_size, int hdr_size,
2627a23113b5SSuresh Reddy 			      u16 img_optype, bool *crc_match)
2628a23113b5SSuresh Reddy {
2629a23113b5SSuresh Reddy 	u32 crc_offset;
2630a23113b5SSuresh Reddy 	int status;
2631a23113b5SSuresh Reddy 	u8 crc[4];
2632a23113b5SSuresh Reddy 
2633a23113b5SSuresh Reddy 	status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset,
2634a23113b5SSuresh Reddy 				      img_size - 4);
2635a23113b5SSuresh Reddy 	if (status)
2636a23113b5SSuresh Reddy 		return status;
2637a23113b5SSuresh Reddy 
2638a23113b5SSuresh Reddy 	crc_offset = hdr_size + img_offset + img_size - 4;
2639a23113b5SSuresh Reddy 
2640a23113b5SSuresh Reddy 	/* Skip flashing, if crc of flashed region matches */
2641a23113b5SSuresh Reddy 	if (!memcmp(crc, p + crc_offset, 4))
2642a23113b5SSuresh Reddy 		*crc_match = true;
2643a23113b5SSuresh Reddy 	else
2644a23113b5SSuresh Reddy 		*crc_match = false;
2645a23113b5SSuresh Reddy 
2646a23113b5SSuresh Reddy 	return status;
2647a23113b5SSuresh Reddy }
2648a23113b5SSuresh Reddy 
2649a23113b5SSuresh Reddy static int be_flash(struct be_adapter *adapter, const u8 *img,
2650a23113b5SSuresh Reddy 		    struct be_dma_mem *flash_cmd, int optype, int img_size,
2651a23113b5SSuresh Reddy 		    u32 img_offset)
2652a23113b5SSuresh Reddy {
2653a23113b5SSuresh Reddy 	u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0;
2654a23113b5SSuresh Reddy 	struct be_cmd_write_flashrom *req = flash_cmd->va;
2655a23113b5SSuresh Reddy 	int status;
2656a23113b5SSuresh Reddy 
2657a23113b5SSuresh Reddy 	while (total_bytes) {
2658a23113b5SSuresh Reddy 		num_bytes = min_t(u32, 32 * 1024, total_bytes);
2659a23113b5SSuresh Reddy 
2660a23113b5SSuresh Reddy 		total_bytes -= num_bytes;
2661a23113b5SSuresh Reddy 
2662a23113b5SSuresh Reddy 		if (!total_bytes) {
2663a23113b5SSuresh Reddy 			if (optype == OPTYPE_PHY_FW)
2664a23113b5SSuresh Reddy 				flash_op = FLASHROM_OPER_PHY_FLASH;
2665a23113b5SSuresh Reddy 			else
2666a23113b5SSuresh Reddy 				flash_op = FLASHROM_OPER_FLASH;
2667a23113b5SSuresh Reddy 		} else {
2668a23113b5SSuresh Reddy 			if (optype == OPTYPE_PHY_FW)
2669a23113b5SSuresh Reddy 				flash_op = FLASHROM_OPER_PHY_SAVE;
2670a23113b5SSuresh Reddy 			else
2671a23113b5SSuresh Reddy 				flash_op = FLASHROM_OPER_SAVE;
2672a23113b5SSuresh Reddy 		}
2673a23113b5SSuresh Reddy 
2674a23113b5SSuresh Reddy 		memcpy(req->data_buf, img, num_bytes);
2675a23113b5SSuresh Reddy 		img += num_bytes;
2676a23113b5SSuresh Reddy 		status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
2677a23113b5SSuresh Reddy 					       flash_op, img_offset +
2678a23113b5SSuresh Reddy 					       bytes_sent, num_bytes);
2679a23113b5SSuresh Reddy 		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
2680a23113b5SSuresh Reddy 		    optype == OPTYPE_PHY_FW)
2681a23113b5SSuresh Reddy 			break;
2682a23113b5SSuresh Reddy 		else if (status)
2683a23113b5SSuresh Reddy 			return status;
2684a23113b5SSuresh Reddy 
2685a23113b5SSuresh Reddy 		bytes_sent += num_bytes;
2686a23113b5SSuresh Reddy 	}
2687a23113b5SSuresh Reddy 	return 0;
2688a23113b5SSuresh Reddy }
2689a23113b5SSuresh Reddy 
2690a23113b5SSuresh Reddy /* For BE2, BE3 and BE3-R */
2691a23113b5SSuresh Reddy static int be_flash_BEx(struct be_adapter *adapter,
2692a23113b5SSuresh Reddy 			const struct firmware *fw,
2693a23113b5SSuresh Reddy 			struct be_dma_mem *flash_cmd, int num_of_images)
2694a23113b5SSuresh Reddy {
2695a23113b5SSuresh Reddy 	int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
2696a23113b5SSuresh Reddy 	struct device *dev = &adapter->pdev->dev;
2697a23113b5SSuresh Reddy 	struct flash_section_info *fsec = NULL;
2698a23113b5SSuresh Reddy 	int status, i, filehdr_size, num_comp;
2699a23113b5SSuresh Reddy 	const struct flash_comp *pflashcomp;
2700a23113b5SSuresh Reddy 	bool crc_match;
2701a23113b5SSuresh Reddy 	const u8 *p;
2702a23113b5SSuresh Reddy 
2703a23113b5SSuresh Reddy 	struct flash_comp gen3_flash_types[] = {
2704a23113b5SSuresh Reddy 		{ BE3_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
2705a23113b5SSuresh Reddy 			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
2706a23113b5SSuresh Reddy 		{ BE3_REDBOOT_START, OPTYPE_REDBOOT,
2707a23113b5SSuresh Reddy 			BE3_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
2708a23113b5SSuresh Reddy 		{ BE3_ISCSI_BIOS_START, OPTYPE_BIOS,
2709a23113b5SSuresh Reddy 			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
2710a23113b5SSuresh Reddy 		{ BE3_PXE_BIOS_START, OPTYPE_PXE_BIOS,
2711a23113b5SSuresh Reddy 			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
2712a23113b5SSuresh Reddy 		{ BE3_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
2713a23113b5SSuresh Reddy 			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
2714a23113b5SSuresh Reddy 		{ BE3_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
2715a23113b5SSuresh Reddy 			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
2716a23113b5SSuresh Reddy 		{ BE3_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
2717a23113b5SSuresh Reddy 			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
2718a23113b5SSuresh Reddy 		{ BE3_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
2719a23113b5SSuresh Reddy 			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE},
2720a23113b5SSuresh Reddy 		{ BE3_NCSI_START, OPTYPE_NCSI_FW,
2721a23113b5SSuresh Reddy 			BE3_NCSI_COMP_MAX_SIZE, IMAGE_NCSI},
2722a23113b5SSuresh Reddy 		{ BE3_PHY_FW_START, OPTYPE_PHY_FW,
2723a23113b5SSuresh Reddy 			BE3_PHY_FW_COMP_MAX_SIZE, IMAGE_FIRMWARE_PHY}
2724a23113b5SSuresh Reddy 	};
2725a23113b5SSuresh Reddy 
2726a23113b5SSuresh Reddy 	struct flash_comp gen2_flash_types[] = {
2727a23113b5SSuresh Reddy 		{ BE2_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
2728a23113b5SSuresh Reddy 			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
2729a23113b5SSuresh Reddy 		{ BE2_REDBOOT_START, OPTYPE_REDBOOT,
2730a23113b5SSuresh Reddy 			BE2_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
2731a23113b5SSuresh Reddy 		{ BE2_ISCSI_BIOS_START, OPTYPE_BIOS,
2732a23113b5SSuresh Reddy 			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
2733a23113b5SSuresh Reddy 		{ BE2_PXE_BIOS_START, OPTYPE_PXE_BIOS,
2734a23113b5SSuresh Reddy 			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
2735a23113b5SSuresh Reddy 		{ BE2_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
2736a23113b5SSuresh Reddy 			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
2737a23113b5SSuresh Reddy 		{ BE2_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
2738a23113b5SSuresh Reddy 			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
2739a23113b5SSuresh Reddy 		{ BE2_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
2740a23113b5SSuresh Reddy 			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
2741a23113b5SSuresh Reddy 		{ BE2_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
2742a23113b5SSuresh Reddy 			 BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE}
2743a23113b5SSuresh Reddy 	};
2744a23113b5SSuresh Reddy 
2745a23113b5SSuresh Reddy 	if (BE3_chip(adapter)) {
2746a23113b5SSuresh Reddy 		pflashcomp = gen3_flash_types;
2747a23113b5SSuresh Reddy 		filehdr_size = sizeof(struct flash_file_hdr_g3);
2748a23113b5SSuresh Reddy 		num_comp = ARRAY_SIZE(gen3_flash_types);
2749a23113b5SSuresh Reddy 	} else {
2750a23113b5SSuresh Reddy 		pflashcomp = gen2_flash_types;
2751a23113b5SSuresh Reddy 		filehdr_size = sizeof(struct flash_file_hdr_g2);
2752a23113b5SSuresh Reddy 		num_comp = ARRAY_SIZE(gen2_flash_types);
2753a23113b5SSuresh Reddy 		img_hdrs_size = 0;
2754a23113b5SSuresh Reddy 	}
2755a23113b5SSuresh Reddy 
2756a23113b5SSuresh Reddy 	/* Get flash section info*/
2757a23113b5SSuresh Reddy 	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
2758a23113b5SSuresh Reddy 	if (!fsec) {
2759a23113b5SSuresh Reddy 		dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
2760a23113b5SSuresh Reddy 		return -1;
2761a23113b5SSuresh Reddy 	}
2762a23113b5SSuresh Reddy 	for (i = 0; i < num_comp; i++) {
2763a23113b5SSuresh Reddy 		if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type))
2764a23113b5SSuresh Reddy 			continue;
2765a23113b5SSuresh Reddy 
2766a23113b5SSuresh Reddy 		if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) &&
2767a23113b5SSuresh Reddy 		    memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
2768a23113b5SSuresh Reddy 			continue;
2769a23113b5SSuresh Reddy 
2770a23113b5SSuresh Reddy 		if (pflashcomp[i].optype == OPTYPE_PHY_FW  &&
2771a23113b5SSuresh Reddy 		    !phy_flashing_required(adapter))
2772a23113b5SSuresh Reddy 			continue;
2773a23113b5SSuresh Reddy 
2774a23113b5SSuresh Reddy 		if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
2775a23113b5SSuresh Reddy 			status = be_check_flash_crc(adapter, fw->data,
2776a23113b5SSuresh Reddy 						    pflashcomp[i].offset,
2777a23113b5SSuresh Reddy 						    pflashcomp[i].size,
2778a23113b5SSuresh Reddy 						    filehdr_size +
2779a23113b5SSuresh Reddy 						    img_hdrs_size,
2780a23113b5SSuresh Reddy 						    OPTYPE_REDBOOT, &crc_match);
2781a23113b5SSuresh Reddy 			if (status) {
2782a23113b5SSuresh Reddy 				dev_err(dev,
2783a23113b5SSuresh Reddy 					"Could not get CRC for 0x%x region\n",
2784a23113b5SSuresh Reddy 					pflashcomp[i].optype);
2785a23113b5SSuresh Reddy 				continue;
2786a23113b5SSuresh Reddy 			}
2787a23113b5SSuresh Reddy 
2788a23113b5SSuresh Reddy 			if (crc_match)
2789a23113b5SSuresh Reddy 				continue;
2790a23113b5SSuresh Reddy 		}
2791a23113b5SSuresh Reddy 
2792a23113b5SSuresh Reddy 		p = fw->data + filehdr_size + pflashcomp[i].offset +
2793a23113b5SSuresh Reddy 			img_hdrs_size;
2794a23113b5SSuresh Reddy 		if (p + pflashcomp[i].size > fw->data + fw->size)
2795a23113b5SSuresh Reddy 			return -1;
2796a23113b5SSuresh Reddy 
2797a23113b5SSuresh Reddy 		status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
2798a23113b5SSuresh Reddy 				  pflashcomp[i].size, 0);
2799a23113b5SSuresh Reddy 		if (status) {
2800a23113b5SSuresh Reddy 			dev_err(dev, "Flashing section type 0x%x failed\n",
2801a23113b5SSuresh Reddy 				pflashcomp[i].img_type);
2802a23113b5SSuresh Reddy 			return status;
2803a23113b5SSuresh Reddy 		}
2804a23113b5SSuresh Reddy 	}
2805a23113b5SSuresh Reddy 	return 0;
2806a23113b5SSuresh Reddy }
2807a23113b5SSuresh Reddy 
2808a23113b5SSuresh Reddy static u16 be_get_img_optype(struct flash_section_entry fsec_entry)
2809a23113b5SSuresh Reddy {
2810a23113b5SSuresh Reddy 	u32 img_type = le32_to_cpu(fsec_entry.type);
2811a23113b5SSuresh Reddy 	u16 img_optype = le16_to_cpu(fsec_entry.optype);
2812a23113b5SSuresh Reddy 
2813a23113b5SSuresh Reddy 	if (img_optype != 0xFFFF)
2814a23113b5SSuresh Reddy 		return img_optype;
2815a23113b5SSuresh Reddy 
2816a23113b5SSuresh Reddy 	switch (img_type) {
2817a23113b5SSuresh Reddy 	case IMAGE_FIRMWARE_ISCSI:
2818a23113b5SSuresh Reddy 		img_optype = OPTYPE_ISCSI_ACTIVE;
2819a23113b5SSuresh Reddy 		break;
2820a23113b5SSuresh Reddy 	case IMAGE_BOOT_CODE:
2821a23113b5SSuresh Reddy 		img_optype = OPTYPE_REDBOOT;
2822a23113b5SSuresh Reddy 		break;
2823a23113b5SSuresh Reddy 	case IMAGE_OPTION_ROM_ISCSI:
2824a23113b5SSuresh Reddy 		img_optype = OPTYPE_BIOS;
2825a23113b5SSuresh Reddy 		break;
2826a23113b5SSuresh Reddy 	case IMAGE_OPTION_ROM_PXE:
2827a23113b5SSuresh Reddy 		img_optype = OPTYPE_PXE_BIOS;
2828a23113b5SSuresh Reddy 		break;
2829a23113b5SSuresh Reddy 	case IMAGE_OPTION_ROM_FCOE:
2830a23113b5SSuresh Reddy 		img_optype = OPTYPE_FCOE_BIOS;
2831a23113b5SSuresh Reddy 		break;
2832a23113b5SSuresh Reddy 	case IMAGE_FIRMWARE_BACKUP_ISCSI:
2833a23113b5SSuresh Reddy 		img_optype = OPTYPE_ISCSI_BACKUP;
2834a23113b5SSuresh Reddy 		break;
2835a23113b5SSuresh Reddy 	case IMAGE_NCSI:
2836a23113b5SSuresh Reddy 		img_optype = OPTYPE_NCSI_FW;
2837a23113b5SSuresh Reddy 		break;
2838a23113b5SSuresh Reddy 	case IMAGE_FLASHISM_JUMPVECTOR:
2839a23113b5SSuresh Reddy 		img_optype = OPTYPE_FLASHISM_JUMPVECTOR;
2840a23113b5SSuresh Reddy 		break;
2841a23113b5SSuresh Reddy 	case IMAGE_FIRMWARE_PHY:
2842a23113b5SSuresh Reddy 		img_optype = OPTYPE_SH_PHY_FW;
2843a23113b5SSuresh Reddy 		break;
2844a23113b5SSuresh Reddy 	case IMAGE_REDBOOT_DIR:
2845a23113b5SSuresh Reddy 		img_optype = OPTYPE_REDBOOT_DIR;
2846a23113b5SSuresh Reddy 		break;
2847a23113b5SSuresh Reddy 	case IMAGE_REDBOOT_CONFIG:
2848a23113b5SSuresh Reddy 		img_optype = OPTYPE_REDBOOT_CONFIG;
2849a23113b5SSuresh Reddy 		break;
2850a23113b5SSuresh Reddy 	case IMAGE_UFI_DIR:
2851a23113b5SSuresh Reddy 		img_optype = OPTYPE_UFI_DIR;
2852a23113b5SSuresh Reddy 		break;
2853a23113b5SSuresh Reddy 	default:
2854a23113b5SSuresh Reddy 		break;
2855a23113b5SSuresh Reddy 	}
2856a23113b5SSuresh Reddy 
2857a23113b5SSuresh Reddy 	return img_optype;
2858a23113b5SSuresh Reddy }
2859a23113b5SSuresh Reddy 
2860a23113b5SSuresh Reddy static int be_flash_skyhawk(struct be_adapter *adapter,
2861a23113b5SSuresh Reddy 			    const struct firmware *fw,
2862a23113b5SSuresh Reddy 			    struct be_dma_mem *flash_cmd, int num_of_images)
2863a23113b5SSuresh Reddy {
2864a23113b5SSuresh Reddy 	int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
2865a23113b5SSuresh Reddy 	bool crc_match, old_fw_img, flash_offset_support = true;
2866a23113b5SSuresh Reddy 	struct device *dev = &adapter->pdev->dev;
2867a23113b5SSuresh Reddy 	struct flash_section_info *fsec = NULL;
2868a23113b5SSuresh Reddy 	u32 img_offset, img_size, img_type;
2869a23113b5SSuresh Reddy 	u16 img_optype, flash_optype;
2870a23113b5SSuresh Reddy 	int status, i, filehdr_size;
2871a23113b5SSuresh Reddy 	const u8 *p;
2872a23113b5SSuresh Reddy 
2873a23113b5SSuresh Reddy 	filehdr_size = sizeof(struct flash_file_hdr_g3);
2874a23113b5SSuresh Reddy 	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
2875a23113b5SSuresh Reddy 	if (!fsec) {
2876a23113b5SSuresh Reddy 		dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
2877a23113b5SSuresh Reddy 		return -EINVAL;
2878a23113b5SSuresh Reddy 	}
2879a23113b5SSuresh Reddy 
2880a23113b5SSuresh Reddy retry_flash:
2881a23113b5SSuresh Reddy 	for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
2882a23113b5SSuresh Reddy 		img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
2883a23113b5SSuresh Reddy 		img_size   = le32_to_cpu(fsec->fsec_entry[i].pad_size);
2884a23113b5SSuresh Reddy 		img_type   = le32_to_cpu(fsec->fsec_entry[i].type);
2885a23113b5SSuresh Reddy 		img_optype = be_get_img_optype(fsec->fsec_entry[i]);
2886a23113b5SSuresh Reddy 		old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF;
2887a23113b5SSuresh Reddy 
2888a23113b5SSuresh Reddy 		if (img_optype == 0xFFFF)
2889a23113b5SSuresh Reddy 			continue;
2890a23113b5SSuresh Reddy 
2891a23113b5SSuresh Reddy 		if (flash_offset_support)
2892a23113b5SSuresh Reddy 			flash_optype = OPTYPE_OFFSET_SPECIFIED;
2893a23113b5SSuresh Reddy 		else
2894a23113b5SSuresh Reddy 			flash_optype = img_optype;
2895a23113b5SSuresh Reddy 
2896a23113b5SSuresh Reddy 		/* Don't bother verifying CRC if an old FW image is being
2897a23113b5SSuresh Reddy 		 * flashed
2898a23113b5SSuresh Reddy 		 */
2899a23113b5SSuresh Reddy 		if (old_fw_img)
2900a23113b5SSuresh Reddy 			goto flash;
2901a23113b5SSuresh Reddy 
2902a23113b5SSuresh Reddy 		status = be_check_flash_crc(adapter, fw->data, img_offset,
2903a23113b5SSuresh Reddy 					    img_size, filehdr_size +
2904a23113b5SSuresh Reddy 					    img_hdrs_size, flash_optype,
2905a23113b5SSuresh Reddy 					    &crc_match);
2906a23113b5SSuresh Reddy 		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
2907a23113b5SSuresh Reddy 		    base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
2908a23113b5SSuresh Reddy 			/* The current FW image on the card does not support
2909a23113b5SSuresh Reddy 			 * OFFSET based flashing. Retry using older mechanism
2910a23113b5SSuresh Reddy 			 * of OPTYPE based flashing
2911a23113b5SSuresh Reddy 			 */
2912a23113b5SSuresh Reddy 			if (flash_optype == OPTYPE_OFFSET_SPECIFIED) {
2913a23113b5SSuresh Reddy 				flash_offset_support = false;
2914a23113b5SSuresh Reddy 				goto retry_flash;
2915a23113b5SSuresh Reddy 			}
2916a23113b5SSuresh Reddy 
2917a23113b5SSuresh Reddy 			/* The current FW image on the card does not recognize
2918a23113b5SSuresh Reddy 			 * the new FLASH op_type. The FW download is partially
2919a23113b5SSuresh Reddy 			 * complete. Reboot the server now to enable FW image
2920a23113b5SSuresh Reddy 			 * to recognize the new FLASH op_type. To complete the
2921a23113b5SSuresh Reddy 			 * remaining process, download the same FW again after
2922a23113b5SSuresh Reddy 			 * the reboot.
2923a23113b5SSuresh Reddy 			 */
2924a23113b5SSuresh Reddy 			dev_err(dev, "Flash incomplete. Reset the server\n");
2925a23113b5SSuresh Reddy 			dev_err(dev, "Download FW image again after reset\n");
2926a23113b5SSuresh Reddy 			return -EAGAIN;
2927a23113b5SSuresh Reddy 		} else if (status) {
2928a23113b5SSuresh Reddy 			dev_err(dev, "Could not get CRC for 0x%x region\n",
2929a23113b5SSuresh Reddy 				img_optype);
2930a23113b5SSuresh Reddy 			return -EFAULT;
2931a23113b5SSuresh Reddy 		}
2932a23113b5SSuresh Reddy 
2933a23113b5SSuresh Reddy 		if (crc_match)
2934a23113b5SSuresh Reddy 			continue;
2935a23113b5SSuresh Reddy 
2936a23113b5SSuresh Reddy flash:
2937a23113b5SSuresh Reddy 		p = fw->data + filehdr_size + img_offset + img_hdrs_size;
2938a23113b5SSuresh Reddy 		if (p + img_size > fw->data + fw->size)
2939a23113b5SSuresh Reddy 			return -1;
2940a23113b5SSuresh Reddy 
2941a23113b5SSuresh Reddy 		status = be_flash(adapter, p, flash_cmd, flash_optype, img_size,
2942a23113b5SSuresh Reddy 				  img_offset);
2943a23113b5SSuresh Reddy 
2944a23113b5SSuresh Reddy 		/* The current FW image on the card does not support OFFSET
2945a23113b5SSuresh Reddy 		 * based flashing. Retry using older mechanism of OPTYPE based
2946a23113b5SSuresh Reddy 		 * flashing
2947a23113b5SSuresh Reddy 		 */
2948a23113b5SSuresh Reddy 		if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD &&
2949a23113b5SSuresh Reddy 		    flash_optype == OPTYPE_OFFSET_SPECIFIED) {
2950a23113b5SSuresh Reddy 			flash_offset_support = false;
2951a23113b5SSuresh Reddy 			goto retry_flash;
2952a23113b5SSuresh Reddy 		}
2953a23113b5SSuresh Reddy 
2954a23113b5SSuresh Reddy 		/* For old FW images ignore ILLEGAL_FIELD error or errors on
2955a23113b5SSuresh Reddy 		 * UFI_DIR region
2956a23113b5SSuresh Reddy 		 */
2957a23113b5SSuresh Reddy 		if (old_fw_img &&
2958a23113b5SSuresh Reddy 		    (base_status(status) == MCC_STATUS_ILLEGAL_FIELD ||
2959a23113b5SSuresh Reddy 		     (img_optype == OPTYPE_UFI_DIR &&
2960a23113b5SSuresh Reddy 		      base_status(status) == MCC_STATUS_FAILED))) {
2961a23113b5SSuresh Reddy 			continue;
2962a23113b5SSuresh Reddy 		} else if (status) {
2963a23113b5SSuresh Reddy 			dev_err(dev, "Flashing section type 0x%x failed\n",
2964a23113b5SSuresh Reddy 				img_type);
29656b525782SSuresh Reddy 
29666b525782SSuresh Reddy 			switch (addl_status(status)) {
29676b525782SSuresh Reddy 			case MCC_ADDL_STATUS_MISSING_SIGNATURE:
29686b525782SSuresh Reddy 				dev_err(dev,
29696b525782SSuresh Reddy 					"Digital signature missing in FW\n");
29706b525782SSuresh Reddy 				return -EINVAL;
29716b525782SSuresh Reddy 			case MCC_ADDL_STATUS_INVALID_SIGNATURE:
29726b525782SSuresh Reddy 				dev_err(dev,
29736b525782SSuresh Reddy 					"Invalid digital signature in FW\n");
29746b525782SSuresh Reddy 				return -EINVAL;
29756b525782SSuresh Reddy 			default:
2976a23113b5SSuresh Reddy 				return -EFAULT;
2977a23113b5SSuresh Reddy 			}
2978a23113b5SSuresh Reddy 		}
29796b525782SSuresh Reddy 	}
2980a23113b5SSuresh Reddy 	return 0;
2981a23113b5SSuresh Reddy }
2982a23113b5SSuresh Reddy 
2983a23113b5SSuresh Reddy int lancer_fw_download(struct be_adapter *adapter,
2984a23113b5SSuresh Reddy 		       const struct firmware *fw)
2985a23113b5SSuresh Reddy {
2986a23113b5SSuresh Reddy 	struct device *dev = &adapter->pdev->dev;
2987a23113b5SSuresh Reddy 	struct be_dma_mem flash_cmd;
2988a23113b5SSuresh Reddy 	const u8 *data_ptr = NULL;
2989a23113b5SSuresh Reddy 	u8 *dest_image_ptr = NULL;
2990a23113b5SSuresh Reddy 	size_t image_size = 0;
2991a23113b5SSuresh Reddy 	u32 chunk_size = 0;
2992a23113b5SSuresh Reddy 	u32 data_written = 0;
2993a23113b5SSuresh Reddy 	u32 offset = 0;
2994a23113b5SSuresh Reddy 	int status = 0;
2995a23113b5SSuresh Reddy 	u8 add_status = 0;
2996a23113b5SSuresh Reddy 	u8 change_status;
2997a23113b5SSuresh Reddy 
2998a23113b5SSuresh Reddy 	if (!IS_ALIGNED(fw->size, sizeof(u32))) {
2999a23113b5SSuresh Reddy 		dev_err(dev, "FW image size should be multiple of 4\n");
3000a23113b5SSuresh Reddy 		return -EINVAL;
3001a23113b5SSuresh Reddy 	}
3002a23113b5SSuresh Reddy 
3003a23113b5SSuresh Reddy 	flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
3004a23113b5SSuresh Reddy 				+ LANCER_FW_DOWNLOAD_CHUNK;
3005a23113b5SSuresh Reddy 	flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size,
3006a23113b5SSuresh Reddy 					   &flash_cmd.dma, GFP_KERNEL);
3007a23113b5SSuresh Reddy 	if (!flash_cmd.va)
3008a23113b5SSuresh Reddy 		return -ENOMEM;
3009a23113b5SSuresh Reddy 
3010a23113b5SSuresh Reddy 	dest_image_ptr = flash_cmd.va +
3011a23113b5SSuresh Reddy 				sizeof(struct lancer_cmd_req_write_object);
3012a23113b5SSuresh Reddy 	image_size = fw->size;
3013a23113b5SSuresh Reddy 	data_ptr = fw->data;
3014a23113b5SSuresh Reddy 
3015a23113b5SSuresh Reddy 	while (image_size) {
3016a23113b5SSuresh Reddy 		chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK);
3017a23113b5SSuresh Reddy 
3018a23113b5SSuresh Reddy 		/* Copy the image chunk content. */
3019a23113b5SSuresh Reddy 		memcpy(dest_image_ptr, data_ptr, chunk_size);
3020a23113b5SSuresh Reddy 
3021a23113b5SSuresh Reddy 		status = lancer_cmd_write_object(adapter, &flash_cmd,
3022a23113b5SSuresh Reddy 						 chunk_size, offset,
3023a23113b5SSuresh Reddy 						 LANCER_FW_DOWNLOAD_LOCATION,
3024a23113b5SSuresh Reddy 						 &data_written, &change_status,
3025a23113b5SSuresh Reddy 						 &add_status);
3026a23113b5SSuresh Reddy 		if (status)
3027a23113b5SSuresh Reddy 			break;
3028a23113b5SSuresh Reddy 
3029a23113b5SSuresh Reddy 		offset += data_written;
3030a23113b5SSuresh Reddy 		data_ptr += data_written;
3031a23113b5SSuresh Reddy 		image_size -= data_written;
3032a23113b5SSuresh Reddy 	}
3033a23113b5SSuresh Reddy 
3034a23113b5SSuresh Reddy 	if (!status) {
3035a23113b5SSuresh Reddy 		/* Commit the FW written */
3036a23113b5SSuresh Reddy 		status = lancer_cmd_write_object(adapter, &flash_cmd,
3037a23113b5SSuresh Reddy 						 0, offset,
3038a23113b5SSuresh Reddy 						 LANCER_FW_DOWNLOAD_LOCATION,
3039a23113b5SSuresh Reddy 						 &data_written, &change_status,
3040a23113b5SSuresh Reddy 						 &add_status);
3041a23113b5SSuresh Reddy 	}
3042a23113b5SSuresh Reddy 
3043a23113b5SSuresh Reddy 	dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
3044a23113b5SSuresh Reddy 	if (status) {
3045a23113b5SSuresh Reddy 		dev_err(dev, "Firmware load error\n");
3046a23113b5SSuresh Reddy 		return be_cmd_status(status);
3047a23113b5SSuresh Reddy 	}
3048a23113b5SSuresh Reddy 
3049a23113b5SSuresh Reddy 	dev_info(dev, "Firmware flashed successfully\n");
3050a23113b5SSuresh Reddy 
3051a23113b5SSuresh Reddy 	if (change_status == LANCER_FW_RESET_NEEDED) {
3052a23113b5SSuresh Reddy 		dev_info(dev, "Resetting adapter to activate new FW\n");
3053a23113b5SSuresh Reddy 		status = lancer_physdev_ctrl(adapter,
3054a23113b5SSuresh Reddy 					     PHYSDEV_CONTROL_FW_RESET_MASK);
3055a23113b5SSuresh Reddy 		if (status) {
3056a23113b5SSuresh Reddy 			dev_err(dev, "Adapter busy, could not reset FW\n");
3057a23113b5SSuresh Reddy 			dev_err(dev, "Reboot server to activate new FW\n");
3058a23113b5SSuresh Reddy 		}
3059a23113b5SSuresh Reddy 	} else if (change_status != LANCER_NO_RESET_NEEDED) {
3060a23113b5SSuresh Reddy 		dev_info(dev, "Reboot server to activate new FW\n");
3061a23113b5SSuresh Reddy 	}
3062a23113b5SSuresh Reddy 
3063a23113b5SSuresh Reddy 	return 0;
3064a23113b5SSuresh Reddy }
3065a23113b5SSuresh Reddy 
3066a23113b5SSuresh Reddy /* Check if the flash image file is compatible with the adapter that
3067a23113b5SSuresh Reddy  * is being flashed.
3068a23113b5SSuresh Reddy  */
3069a23113b5SSuresh Reddy static bool be_check_ufi_compatibility(struct be_adapter *adapter,
3070a23113b5SSuresh Reddy 				       struct flash_file_hdr_g3 *fhdr)
3071a23113b5SSuresh Reddy {
3072a23113b5SSuresh Reddy 	if (!fhdr) {
3073a23113b5SSuresh Reddy 		dev_err(&adapter->pdev->dev, "Invalid FW UFI file");
3074a23113b5SSuresh Reddy 		return false;
3075a23113b5SSuresh Reddy 	}
3076a23113b5SSuresh Reddy 
3077a23113b5SSuresh Reddy 	/* First letter of the build version is used to identify
3078a23113b5SSuresh Reddy 	 * which chip this image file is meant for.
3079a23113b5SSuresh Reddy 	 */
3080a23113b5SSuresh Reddy 	switch (fhdr->build[0]) {
3081a23113b5SSuresh Reddy 	case BLD_STR_UFI_TYPE_SH:
3082a23113b5SSuresh Reddy 		if (!skyhawk_chip(adapter))
3083a23113b5SSuresh Reddy 			return false;
3084a23113b5SSuresh Reddy 		break;
3085a23113b5SSuresh Reddy 	case BLD_STR_UFI_TYPE_BE3:
3086a23113b5SSuresh Reddy 		if (!BE3_chip(adapter))
3087a23113b5SSuresh Reddy 			return false;
3088a23113b5SSuresh Reddy 		break;
3089a23113b5SSuresh Reddy 	case BLD_STR_UFI_TYPE_BE2:
3090a23113b5SSuresh Reddy 		if (!BE2_chip(adapter))
3091a23113b5SSuresh Reddy 			return false;
3092a23113b5SSuresh Reddy 		break;
3093a23113b5SSuresh Reddy 	default:
3094a23113b5SSuresh Reddy 		return false;
3095a23113b5SSuresh Reddy 	}
3096a23113b5SSuresh Reddy 
3097a23113b5SSuresh Reddy 	/* In BE3 FW images the "asic_type_rev" field doesn't track the
3098a23113b5SSuresh Reddy 	 * asic_rev of the chips it is compatible with.
3099a23113b5SSuresh Reddy 	 * When asic_type_rev is 0 the image is compatible only with
3100a23113b5SSuresh Reddy 	 * pre-BE3-R chips (asic_rev < 0x10)
3101a23113b5SSuresh Reddy 	 */
3102a23113b5SSuresh Reddy 	if (BEx_chip(adapter) && fhdr->asic_type_rev == 0)
3103a23113b5SSuresh Reddy 		return adapter->asic_rev < 0x10;
3104a23113b5SSuresh Reddy 	else
3105a23113b5SSuresh Reddy 		return (fhdr->asic_type_rev >= adapter->asic_rev);
3106a23113b5SSuresh Reddy }
3107a23113b5SSuresh Reddy 
3108a23113b5SSuresh Reddy int be_fw_download(struct be_adapter *adapter, const struct firmware *fw)
3109a23113b5SSuresh Reddy {
3110a23113b5SSuresh Reddy 	struct device *dev = &adapter->pdev->dev;
3111a23113b5SSuresh Reddy 	struct flash_file_hdr_g3 *fhdr3;
3112a23113b5SSuresh Reddy 	struct image_hdr *img_hdr_ptr;
3113a23113b5SSuresh Reddy 	int status = 0, i, num_imgs;
3114a23113b5SSuresh Reddy 	struct be_dma_mem flash_cmd;
3115a23113b5SSuresh Reddy 
3116a23113b5SSuresh Reddy 	fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
3117a23113b5SSuresh Reddy 	if (!be_check_ufi_compatibility(adapter, fhdr3)) {
3118a23113b5SSuresh Reddy 		dev_err(dev, "Flash image is not compatible with adapter\n");
3119a23113b5SSuresh Reddy 		return -EINVAL;
3120a23113b5SSuresh Reddy 	}
3121a23113b5SSuresh Reddy 
3122a23113b5SSuresh Reddy 	flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
3123a23113b5SSuresh Reddy 	flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
3124a23113b5SSuresh Reddy 					   GFP_KERNEL);
3125a23113b5SSuresh Reddy 	if (!flash_cmd.va)
3126a23113b5SSuresh Reddy 		return -ENOMEM;
3127a23113b5SSuresh Reddy 
3128a23113b5SSuresh Reddy 	num_imgs = le32_to_cpu(fhdr3->num_imgs);
3129a23113b5SSuresh Reddy 	for (i = 0; i < num_imgs; i++) {
3130a23113b5SSuresh Reddy 		img_hdr_ptr = (struct image_hdr *)(fw->data +
3131a23113b5SSuresh Reddy 				(sizeof(struct flash_file_hdr_g3) +
3132a23113b5SSuresh Reddy 				 i * sizeof(struct image_hdr)));
3133a23113b5SSuresh Reddy 		if (!BE2_chip(adapter) &&
3134a23113b5SSuresh Reddy 		    le32_to_cpu(img_hdr_ptr->imageid) != 1)
3135a23113b5SSuresh Reddy 			continue;
3136a23113b5SSuresh Reddy 
3137a23113b5SSuresh Reddy 		if (skyhawk_chip(adapter))
3138a23113b5SSuresh Reddy 			status = be_flash_skyhawk(adapter, fw, &flash_cmd,
3139a23113b5SSuresh Reddy 						  num_imgs);
3140a23113b5SSuresh Reddy 		else
3141a23113b5SSuresh Reddy 			status = be_flash_BEx(adapter, fw, &flash_cmd,
3142a23113b5SSuresh Reddy 					      num_imgs);
3143a23113b5SSuresh Reddy 	}
3144a23113b5SSuresh Reddy 
3145a23113b5SSuresh Reddy 	dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
3146a23113b5SSuresh Reddy 	if (!status)
3147a23113b5SSuresh Reddy 		dev_info(dev, "Firmware flashed successfully\n");
3148a23113b5SSuresh Reddy 
3149a23113b5SSuresh Reddy 	return status;
3150a23113b5SSuresh Reddy }
3151a23113b5SSuresh Reddy 
31529aebddd1SJeff Kirsher int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
31539aebddd1SJeff Kirsher 			    struct be_dma_mem *nonemb_cmd)
31549aebddd1SJeff Kirsher {
31559aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
31569aebddd1SJeff Kirsher 	struct be_cmd_req_acpi_wol_magic_config *req;
31579aebddd1SJeff Kirsher 	int status;
31589aebddd1SJeff Kirsher 
31599aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
31609aebddd1SJeff Kirsher 
31619aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
31629aebddd1SJeff Kirsher 	if (!wrb) {
31639aebddd1SJeff Kirsher 		status = -EBUSY;
31649aebddd1SJeff Kirsher 		goto err;
31659aebddd1SJeff Kirsher 	}
31669aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
31679aebddd1SJeff Kirsher 
3168106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
3169a2cc4e0bSSathya Perla 			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req),
3170a2cc4e0bSSathya Perla 			       wrb, nonemb_cmd);
31719aebddd1SJeff Kirsher 	memcpy(req->magic_mac, mac, ETH_ALEN);
31729aebddd1SJeff Kirsher 
31739aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
31749aebddd1SJeff Kirsher 
31759aebddd1SJeff Kirsher err:
31769aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
31779aebddd1SJeff Kirsher 	return status;
31789aebddd1SJeff Kirsher }
31799aebddd1SJeff Kirsher 
31809aebddd1SJeff Kirsher int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
31819aebddd1SJeff Kirsher 			u8 loopback_type, u8 enable)
31829aebddd1SJeff Kirsher {
31839aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
31849aebddd1SJeff Kirsher 	struct be_cmd_req_set_lmode *req;
31859aebddd1SJeff Kirsher 	int status;
31869aebddd1SJeff Kirsher 
31872e365b1bSSomnath Kotur 	if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
31882e365b1bSSomnath Kotur 			    CMD_SUBSYSTEM_LOWLEVEL))
31892e365b1bSSomnath Kotur 		return -EPERM;
31902e365b1bSSomnath Kotur 
31919aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
31929aebddd1SJeff Kirsher 
31939aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
31949aebddd1SJeff Kirsher 	if (!wrb) {
31959aebddd1SJeff Kirsher 		status = -EBUSY;
31969c855975SSuresh Reddy 		goto err_unlock;
31979aebddd1SJeff Kirsher 	}
31989aebddd1SJeff Kirsher 
31999aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
32009aebddd1SJeff Kirsher 
3201106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
3202a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req),
3203a2cc4e0bSSathya Perla 			       wrb, NULL);
32049aebddd1SJeff Kirsher 
32059aebddd1SJeff Kirsher 	req->src_port = port_num;
32069aebddd1SJeff Kirsher 	req->dest_port = port_num;
32079aebddd1SJeff Kirsher 	req->loopback_type = loopback_type;
32089aebddd1SJeff Kirsher 	req->loopback_state = enable;
32099aebddd1SJeff Kirsher 
32109c855975SSuresh Reddy 	status = be_mcc_notify(adapter);
32119c855975SSuresh Reddy 	if (status)
32129c855975SSuresh Reddy 		goto err_unlock;
32139c855975SSuresh Reddy 
32149c855975SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
32159c855975SSuresh Reddy 
32169c855975SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
32179c855975SSuresh Reddy 					 msecs_to_jiffies(SET_LB_MODE_TIMEOUT)))
32189c855975SSuresh Reddy 		status = -ETIMEDOUT;
32199c855975SSuresh Reddy 
32209c855975SSuresh Reddy 	return status;
32219c855975SSuresh Reddy 
32229c855975SSuresh Reddy err_unlock:
32239aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
32249aebddd1SJeff Kirsher 	return status;
32259aebddd1SJeff Kirsher }
32269aebddd1SJeff Kirsher 
32279aebddd1SJeff Kirsher int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
3228a2cc4e0bSSathya Perla 			 u32 loopback_type, u32 pkt_size, u32 num_pkts,
3229a2cc4e0bSSathya Perla 			 u64 pattern)
32309aebddd1SJeff Kirsher {
32319aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
32329aebddd1SJeff Kirsher 	struct be_cmd_req_loopback_test *req;
32335eeff635SSuresh Reddy 	struct be_cmd_resp_loopback_test *resp;
32349aebddd1SJeff Kirsher 	int status;
32359aebddd1SJeff Kirsher 
32362e365b1bSSomnath Kotur 	if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_LOOPBACK_TEST,
32372e365b1bSSomnath Kotur 			    CMD_SUBSYSTEM_LOWLEVEL))
32382e365b1bSSomnath Kotur 		return -EPERM;
32392e365b1bSSomnath Kotur 
32409aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
32419aebddd1SJeff Kirsher 
32429aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
32439aebddd1SJeff Kirsher 	if (!wrb) {
32449aebddd1SJeff Kirsher 		status = -EBUSY;
32459aebddd1SJeff Kirsher 		goto err;
32469aebddd1SJeff Kirsher 	}
32479aebddd1SJeff Kirsher 
32489aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
32499aebddd1SJeff Kirsher 
3250106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
3251a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb,
3252a2cc4e0bSSathya Perla 			       NULL);
32539aebddd1SJeff Kirsher 
32545eeff635SSuresh Reddy 	req->hdr.timeout = cpu_to_le32(15);
32559aebddd1SJeff Kirsher 	req->pattern = cpu_to_le64(pattern);
32569aebddd1SJeff Kirsher 	req->src_port = cpu_to_le32(port_num);
32579aebddd1SJeff Kirsher 	req->dest_port = cpu_to_le32(port_num);
32589aebddd1SJeff Kirsher 	req->pkt_size = cpu_to_le32(pkt_size);
32599aebddd1SJeff Kirsher 	req->num_pkts = cpu_to_le32(num_pkts);
32609aebddd1SJeff Kirsher 	req->loopback_type = cpu_to_le32(loopback_type);
32619aebddd1SJeff Kirsher 
3262efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
3263efaa408eSSuresh Reddy 	if (status)
3264efaa408eSSuresh Reddy 		goto err;
32659aebddd1SJeff Kirsher 
32665eeff635SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
32675eeff635SSuresh Reddy 
32685eeff635SSuresh Reddy 	wait_for_completion(&adapter->et_cmd_compl);
32695eeff635SSuresh Reddy 	resp = embedded_payload(wrb);
32705eeff635SSuresh Reddy 	status = le32_to_cpu(resp->status);
32715eeff635SSuresh Reddy 
32725eeff635SSuresh Reddy 	return status;
32739aebddd1SJeff Kirsher err:
32749aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
32759aebddd1SJeff Kirsher 	return status;
32769aebddd1SJeff Kirsher }
32779aebddd1SJeff Kirsher 
32789aebddd1SJeff Kirsher int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
32799aebddd1SJeff Kirsher 			u32 byte_cnt, struct be_dma_mem *cmd)
32809aebddd1SJeff Kirsher {
32819aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
32829aebddd1SJeff Kirsher 	struct be_cmd_req_ddrdma_test *req;
32839aebddd1SJeff Kirsher 	int status;
32849aebddd1SJeff Kirsher 	int i, j = 0;
32859aebddd1SJeff Kirsher 
32862e365b1bSSomnath Kotur 	if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_HOST_DDR_DMA,
32872e365b1bSSomnath Kotur 			    CMD_SUBSYSTEM_LOWLEVEL))
32882e365b1bSSomnath Kotur 		return -EPERM;
32892e365b1bSSomnath Kotur 
32909aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
32919aebddd1SJeff Kirsher 
32929aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
32939aebddd1SJeff Kirsher 	if (!wrb) {
32949aebddd1SJeff Kirsher 		status = -EBUSY;
32959aebddd1SJeff Kirsher 		goto err;
32969aebddd1SJeff Kirsher 	}
32979aebddd1SJeff Kirsher 	req = cmd->va;
3298106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
3299a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb,
3300a2cc4e0bSSathya Perla 			       cmd);
33019aebddd1SJeff Kirsher 
33029aebddd1SJeff Kirsher 	req->pattern = cpu_to_le64(pattern);
33039aebddd1SJeff Kirsher 	req->byte_count = cpu_to_le32(byte_cnt);
33049aebddd1SJeff Kirsher 	for (i = 0; i < byte_cnt; i++) {
33059aebddd1SJeff Kirsher 		req->snd_buff[i] = (u8)(pattern >> (j*8));
33069aebddd1SJeff Kirsher 		j++;
33079aebddd1SJeff Kirsher 		if (j > 7)
33089aebddd1SJeff Kirsher 			j = 0;
33099aebddd1SJeff Kirsher 	}
33109aebddd1SJeff Kirsher 
33119aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
33129aebddd1SJeff Kirsher 
33139aebddd1SJeff Kirsher 	if (!status) {
33149aebddd1SJeff Kirsher 		struct be_cmd_resp_ddrdma_test *resp;
331503d28ffeSKalesh AP 
33169aebddd1SJeff Kirsher 		resp = cmd->va;
33179aebddd1SJeff Kirsher 		if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) ||
33189aebddd1SJeff Kirsher 		    resp->snd_err) {
33199aebddd1SJeff Kirsher 			status = -1;
33209aebddd1SJeff Kirsher 		}
33219aebddd1SJeff Kirsher 	}
33229aebddd1SJeff Kirsher 
33239aebddd1SJeff Kirsher err:
33249aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
33259aebddd1SJeff Kirsher 	return status;
33269aebddd1SJeff Kirsher }
33279aebddd1SJeff Kirsher 
33289aebddd1SJeff Kirsher int be_cmd_get_seeprom_data(struct be_adapter *adapter,
33299aebddd1SJeff Kirsher 			    struct be_dma_mem *nonemb_cmd)
33309aebddd1SJeff Kirsher {
33319aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
33329aebddd1SJeff Kirsher 	struct be_cmd_req_seeprom_read *req;
33339aebddd1SJeff Kirsher 	int status;
33349aebddd1SJeff Kirsher 
33359aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
33369aebddd1SJeff Kirsher 
33379aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
33389aebddd1SJeff Kirsher 	if (!wrb) {
33399aebddd1SJeff Kirsher 		status = -EBUSY;
33409aebddd1SJeff Kirsher 		goto err;
33419aebddd1SJeff Kirsher 	}
33429aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
33439aebddd1SJeff Kirsher 
3344106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3345106df1e3SSomnath Kotur 			       OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb,
3346106df1e3SSomnath Kotur 			       nonemb_cmd);
33479aebddd1SJeff Kirsher 
33489aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
33499aebddd1SJeff Kirsher 
33509aebddd1SJeff Kirsher err:
33519aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
33529aebddd1SJeff Kirsher 	return status;
33539aebddd1SJeff Kirsher }
33549aebddd1SJeff Kirsher 
335542f11cf2SAjit Khaparde int be_cmd_get_phy_info(struct be_adapter *adapter)
33569aebddd1SJeff Kirsher {
33579aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
33589aebddd1SJeff Kirsher 	struct be_cmd_req_get_phy_info *req;
33599aebddd1SJeff Kirsher 	struct be_dma_mem cmd;
33609aebddd1SJeff Kirsher 	int status;
33619aebddd1SJeff Kirsher 
3362f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
3363f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
3364f25b119cSPadmanabh Ratnakar 		return -EPERM;
3365f25b119cSPadmanabh Ratnakar 
33669aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
33679aebddd1SJeff Kirsher 
33689aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
33699aebddd1SJeff Kirsher 	if (!wrb) {
33709aebddd1SJeff Kirsher 		status = -EBUSY;
33719aebddd1SJeff Kirsher 		goto err;
33729aebddd1SJeff Kirsher 	}
33739aebddd1SJeff Kirsher 	cmd.size = sizeof(struct be_cmd_req_get_phy_info);
3374e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
3375e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
33769aebddd1SJeff Kirsher 	if (!cmd.va) {
33779aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
33789aebddd1SJeff Kirsher 		status = -ENOMEM;
33799aebddd1SJeff Kirsher 		goto err;
33809aebddd1SJeff Kirsher 	}
33819aebddd1SJeff Kirsher 
33829aebddd1SJeff Kirsher 	req = cmd.va;
33839aebddd1SJeff Kirsher 
3384106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3385106df1e3SSomnath Kotur 			       OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req),
3386106df1e3SSomnath Kotur 			       wrb, &cmd);
33879aebddd1SJeff Kirsher 
33889aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
33899aebddd1SJeff Kirsher 	if (!status) {
33909aebddd1SJeff Kirsher 		struct be_phy_info *resp_phy_info =
33919aebddd1SJeff Kirsher 				cmd.va + sizeof(struct be_cmd_req_hdr);
339203d28ffeSKalesh AP 
339342f11cf2SAjit Khaparde 		adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type);
339442f11cf2SAjit Khaparde 		adapter->phy.interface_type =
33959aebddd1SJeff Kirsher 			le16_to_cpu(resp_phy_info->interface_type);
339642f11cf2SAjit Khaparde 		adapter->phy.auto_speeds_supported =
339742f11cf2SAjit Khaparde 			le16_to_cpu(resp_phy_info->auto_speeds_supported);
339842f11cf2SAjit Khaparde 		adapter->phy.fixed_speeds_supported =
339942f11cf2SAjit Khaparde 			le16_to_cpu(resp_phy_info->fixed_speeds_supported);
340042f11cf2SAjit Khaparde 		adapter->phy.misc_params =
340142f11cf2SAjit Khaparde 			le32_to_cpu(resp_phy_info->misc_params);
340268cb7e47SVasundhara Volam 
340368cb7e47SVasundhara Volam 		if (BE2_chip(adapter)) {
340468cb7e47SVasundhara Volam 			adapter->phy.fixed_speeds_supported =
340568cb7e47SVasundhara Volam 				BE_SUPPORTED_SPEED_10GBPS |
340668cb7e47SVasundhara Volam 				BE_SUPPORTED_SPEED_1GBPS;
340768cb7e47SVasundhara Volam 		}
34089aebddd1SJeff Kirsher 	}
3409e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
34109aebddd1SJeff Kirsher err:
34119aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
34129aebddd1SJeff Kirsher 	return status;
34139aebddd1SJeff Kirsher }
34149aebddd1SJeff Kirsher 
3415bc0ee163SLad, Prabhakar static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain)
34169aebddd1SJeff Kirsher {
34179aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
34189aebddd1SJeff Kirsher 	struct be_cmd_req_set_qos *req;
34199aebddd1SJeff Kirsher 	int status;
34209aebddd1SJeff Kirsher 
34219aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
34229aebddd1SJeff Kirsher 
34239aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
34249aebddd1SJeff Kirsher 	if (!wrb) {
34259aebddd1SJeff Kirsher 		status = -EBUSY;
34269aebddd1SJeff Kirsher 		goto err;
34279aebddd1SJeff Kirsher 	}
34289aebddd1SJeff Kirsher 
34299aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
34309aebddd1SJeff Kirsher 
3431106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3432106df1e3SSomnath Kotur 			       OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL);
34339aebddd1SJeff Kirsher 
34349aebddd1SJeff Kirsher 	req->hdr.domain = domain;
34359aebddd1SJeff Kirsher 	req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
34369aebddd1SJeff Kirsher 	req->max_bps_nic = cpu_to_le32(bps);
34379aebddd1SJeff Kirsher 
34389aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
34399aebddd1SJeff Kirsher 
34409aebddd1SJeff Kirsher err:
34419aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
34429aebddd1SJeff Kirsher 	return status;
34439aebddd1SJeff Kirsher }
34449aebddd1SJeff Kirsher 
34459aebddd1SJeff Kirsher int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
34469aebddd1SJeff Kirsher {
34479aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
34489aebddd1SJeff Kirsher 	struct be_cmd_req_cntl_attribs *req;
34499aebddd1SJeff Kirsher 	struct be_cmd_resp_cntl_attribs *resp;
3450a155a5dbSSriharsha Basavapatna 	int status, i;
34519aebddd1SJeff Kirsher 	int payload_len = max(sizeof(*req), sizeof(*resp));
34529aebddd1SJeff Kirsher 	struct mgmt_controller_attrib *attribs;
34539aebddd1SJeff Kirsher 	struct be_dma_mem attribs_cmd;
3454a155a5dbSSriharsha Basavapatna 	u32 *serial_num;
34559aebddd1SJeff Kirsher 
3456d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3457d98ef50fSSuresh Reddy 		return -1;
3458d98ef50fSSuresh Reddy 
34599aebddd1SJeff Kirsher 	memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
34609aebddd1SJeff Kirsher 	attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
3461e51000dbSSriharsha Basavapatna 	attribs_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
3462e51000dbSSriharsha Basavapatna 					     attribs_cmd.size,
3463e51000dbSSriharsha Basavapatna 					     &attribs_cmd.dma, GFP_ATOMIC);
34649aebddd1SJeff Kirsher 	if (!attribs_cmd.va) {
3465a2cc4e0bSSathya Perla 		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
3466d98ef50fSSuresh Reddy 		status = -ENOMEM;
3467d98ef50fSSuresh Reddy 		goto err;
34689aebddd1SJeff Kirsher 	}
34699aebddd1SJeff Kirsher 
34709aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
34719aebddd1SJeff Kirsher 	if (!wrb) {
34729aebddd1SJeff Kirsher 		status = -EBUSY;
34739aebddd1SJeff Kirsher 		goto err;
34749aebddd1SJeff Kirsher 	}
34759aebddd1SJeff Kirsher 	req = attribs_cmd.va;
34769aebddd1SJeff Kirsher 
3477106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3478a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len,
3479a2cc4e0bSSathya Perla 			       wrb, &attribs_cmd);
34809aebddd1SJeff Kirsher 
34819aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
34829aebddd1SJeff Kirsher 	if (!status) {
34839aebddd1SJeff Kirsher 		attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
34849aebddd1SJeff Kirsher 		adapter->hba_port_num = attribs->hba_attribs.phy_port;
3485a155a5dbSSriharsha Basavapatna 		serial_num = attribs->hba_attribs.controller_serial_number;
3486a155a5dbSSriharsha Basavapatna 		for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++)
3487a155a5dbSSriharsha Basavapatna 			adapter->serial_num[i] = le32_to_cpu(serial_num[i]) &
3488a155a5dbSSriharsha Basavapatna 				(BIT_MASK(16) - 1);
34899aebddd1SJeff Kirsher 	}
34909aebddd1SJeff Kirsher 
34919aebddd1SJeff Kirsher err:
34929aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
3493d98ef50fSSuresh Reddy 	if (attribs_cmd.va)
3494e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, attribs_cmd.size,
3495d98ef50fSSuresh Reddy 				  attribs_cmd.va, attribs_cmd.dma);
34969aebddd1SJeff Kirsher 	return status;
34979aebddd1SJeff Kirsher }
34989aebddd1SJeff Kirsher 
34999aebddd1SJeff Kirsher /* Uses mbox */
35009aebddd1SJeff Kirsher int be_cmd_req_native_mode(struct be_adapter *adapter)
35019aebddd1SJeff Kirsher {
35029aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
35039aebddd1SJeff Kirsher 	struct be_cmd_req_set_func_cap *req;
35049aebddd1SJeff Kirsher 	int status;
35059aebddd1SJeff Kirsher 
35069aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
35079aebddd1SJeff Kirsher 		return -1;
35089aebddd1SJeff Kirsher 
35099aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
35109aebddd1SJeff Kirsher 	if (!wrb) {
35119aebddd1SJeff Kirsher 		status = -EBUSY;
35129aebddd1SJeff Kirsher 		goto err;
35139aebddd1SJeff Kirsher 	}
35149aebddd1SJeff Kirsher 
35159aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
35169aebddd1SJeff Kirsher 
3517106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3518a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP,
3519a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
35209aebddd1SJeff Kirsher 
35219aebddd1SJeff Kirsher 	req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS |
35229aebddd1SJeff Kirsher 				CAPABILITY_BE3_NATIVE_ERX_API);
35239aebddd1SJeff Kirsher 	req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API);
35249aebddd1SJeff Kirsher 
35259aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
35269aebddd1SJeff Kirsher 	if (!status) {
35279aebddd1SJeff Kirsher 		struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb);
352803d28ffeSKalesh AP 
35299aebddd1SJeff Kirsher 		adapter->be3_native = le32_to_cpu(resp->cap_flags) &
35309aebddd1SJeff Kirsher 					CAPABILITY_BE3_NATIVE_ERX_API;
3531d379142bSSathya Perla 		if (!adapter->be3_native)
3532d379142bSSathya Perla 			dev_warn(&adapter->pdev->dev,
3533d379142bSSathya Perla 				 "adapter not in advanced mode\n");
35349aebddd1SJeff Kirsher 	}
35359aebddd1SJeff Kirsher err:
35369aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
35379aebddd1SJeff Kirsher 	return status;
35389aebddd1SJeff Kirsher }
3539590c391dSPadmanabh Ratnakar 
3540f25b119cSPadmanabh Ratnakar /* Get privilege(s) for a function */
3541f25b119cSPadmanabh Ratnakar int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
3542f25b119cSPadmanabh Ratnakar 			     u32 domain)
3543f25b119cSPadmanabh Ratnakar {
3544f25b119cSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3545f25b119cSPadmanabh Ratnakar 	struct be_cmd_req_get_fn_privileges *req;
3546f25b119cSPadmanabh Ratnakar 	int status;
3547f25b119cSPadmanabh Ratnakar 
3548f25b119cSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
3549f25b119cSPadmanabh Ratnakar 
3550f25b119cSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
3551f25b119cSPadmanabh Ratnakar 	if (!wrb) {
3552f25b119cSPadmanabh Ratnakar 		status = -EBUSY;
3553f25b119cSPadmanabh Ratnakar 		goto err;
3554f25b119cSPadmanabh Ratnakar 	}
3555f25b119cSPadmanabh Ratnakar 
3556f25b119cSPadmanabh Ratnakar 	req = embedded_payload(wrb);
3557f25b119cSPadmanabh Ratnakar 
3558f25b119cSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3559f25b119cSPadmanabh Ratnakar 			       OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
3560f25b119cSPadmanabh Ratnakar 			       wrb, NULL);
3561f25b119cSPadmanabh Ratnakar 
3562f25b119cSPadmanabh Ratnakar 	req->hdr.domain = domain;
3563f25b119cSPadmanabh Ratnakar 
3564f25b119cSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3565f25b119cSPadmanabh Ratnakar 	if (!status) {
3566f25b119cSPadmanabh Ratnakar 		struct be_cmd_resp_get_fn_privileges *resp =
3567f25b119cSPadmanabh Ratnakar 						embedded_payload(wrb);
356803d28ffeSKalesh AP 
3569f25b119cSPadmanabh Ratnakar 		*privilege = le32_to_cpu(resp->privilege_mask);
357002308d74SSuresh Reddy 
357102308d74SSuresh Reddy 		/* In UMC mode FW does not return right privileges.
357202308d74SSuresh Reddy 		 * Override with correct privilege equivalent to PF.
357302308d74SSuresh Reddy 		 */
357402308d74SSuresh Reddy 		if (BEx_chip(adapter) && be_is_mc(adapter) &&
357502308d74SSuresh Reddy 		    be_physfn(adapter))
357602308d74SSuresh Reddy 			*privilege = MAX_PRIVILEGES;
3577f25b119cSPadmanabh Ratnakar 	}
3578f25b119cSPadmanabh Ratnakar 
3579f25b119cSPadmanabh Ratnakar err:
3580f25b119cSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3581f25b119cSPadmanabh Ratnakar 	return status;
3582f25b119cSPadmanabh Ratnakar }
3583f25b119cSPadmanabh Ratnakar 
358404a06028SSathya Perla /* Set privilege(s) for a function */
358504a06028SSathya Perla int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges,
358604a06028SSathya Perla 			     u32 domain)
358704a06028SSathya Perla {
358804a06028SSathya Perla 	struct be_mcc_wrb *wrb;
358904a06028SSathya Perla 	struct be_cmd_req_set_fn_privileges *req;
359004a06028SSathya Perla 	int status;
359104a06028SSathya Perla 
359204a06028SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
359304a06028SSathya Perla 
359404a06028SSathya Perla 	wrb = wrb_from_mccq(adapter);
359504a06028SSathya Perla 	if (!wrb) {
359604a06028SSathya Perla 		status = -EBUSY;
359704a06028SSathya Perla 		goto err;
359804a06028SSathya Perla 	}
359904a06028SSathya Perla 
360004a06028SSathya Perla 	req = embedded_payload(wrb);
360104a06028SSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
360204a06028SSathya Perla 			       OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req),
360304a06028SSathya Perla 			       wrb, NULL);
360404a06028SSathya Perla 	req->hdr.domain = domain;
360504a06028SSathya Perla 	if (lancer_chip(adapter))
360604a06028SSathya Perla 		req->privileges_lancer = cpu_to_le32(privileges);
360704a06028SSathya Perla 	else
360804a06028SSathya Perla 		req->privileges = cpu_to_le32(privileges);
360904a06028SSathya Perla 
361004a06028SSathya Perla 	status = be_mcc_notify_wait(adapter);
361104a06028SSathya Perla err:
361204a06028SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
361304a06028SSathya Perla 	return status;
361404a06028SSathya Perla }
361504a06028SSathya Perla 
36165a712c13SSathya Perla /* pmac_id_valid: true => pmac_id is supplied and MAC address is requested.
36175a712c13SSathya Perla  * pmac_id_valid: false => pmac_id or MAC address is requested.
36185a712c13SSathya Perla  *		  If pmac_id is returned, pmac_id_valid is returned as true
36195a712c13SSathya Perla  */
36201578e777SPadmanabh Ratnakar int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
3621b188f090SSuresh Reddy 			     bool *pmac_id_valid, u32 *pmac_id, u32 if_handle,
3622b188f090SSuresh Reddy 			     u8 domain)
3623590c391dSPadmanabh Ratnakar {
3624590c391dSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3625590c391dSPadmanabh Ratnakar 	struct be_cmd_req_get_mac_list *req;
3626590c391dSPadmanabh Ratnakar 	int status;
3627590c391dSPadmanabh Ratnakar 	int mac_count;
3628e5e1ee89SPadmanabh Ratnakar 	struct be_dma_mem get_mac_list_cmd;
3629e5e1ee89SPadmanabh Ratnakar 	int i;
3630e5e1ee89SPadmanabh Ratnakar 
3631e5e1ee89SPadmanabh Ratnakar 	memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
3632e5e1ee89SPadmanabh Ratnakar 	get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
3633e51000dbSSriharsha Basavapatna 	get_mac_list_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
3634e5e1ee89SPadmanabh Ratnakar 						  get_mac_list_cmd.size,
3635e51000dbSSriharsha Basavapatna 						  &get_mac_list_cmd.dma,
3636e51000dbSSriharsha Basavapatna 						  GFP_ATOMIC);
3637e5e1ee89SPadmanabh Ratnakar 
3638e5e1ee89SPadmanabh Ratnakar 	if (!get_mac_list_cmd.va) {
3639e5e1ee89SPadmanabh Ratnakar 		dev_err(&adapter->pdev->dev,
3640e5e1ee89SPadmanabh Ratnakar 			"Memory allocation failure during GET_MAC_LIST\n");
3641e5e1ee89SPadmanabh Ratnakar 		return -ENOMEM;
3642e5e1ee89SPadmanabh Ratnakar 	}
3643590c391dSPadmanabh Ratnakar 
3644590c391dSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
3645590c391dSPadmanabh Ratnakar 
3646590c391dSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
3647590c391dSPadmanabh Ratnakar 	if (!wrb) {
3648590c391dSPadmanabh Ratnakar 		status = -EBUSY;
3649e5e1ee89SPadmanabh Ratnakar 		goto out;
3650590c391dSPadmanabh Ratnakar 	}
3651e5e1ee89SPadmanabh Ratnakar 
3652e5e1ee89SPadmanabh Ratnakar 	req = get_mac_list_cmd.va;
3653590c391dSPadmanabh Ratnakar 
3654590c391dSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3655bf591f51SSathya Perla 			       OPCODE_COMMON_GET_MAC_LIST,
3656bf591f51SSathya Perla 			       get_mac_list_cmd.size, wrb, &get_mac_list_cmd);
3657590c391dSPadmanabh Ratnakar 	req->hdr.domain = domain;
3658e5e1ee89SPadmanabh Ratnakar 	req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
36595a712c13SSathya Perla 	if (*pmac_id_valid) {
36605a712c13SSathya Perla 		req->mac_id = cpu_to_le32(*pmac_id);
3661b188f090SSuresh Reddy 		req->iface_id = cpu_to_le16(if_handle);
36625a712c13SSathya Perla 		req->perm_override = 0;
36635a712c13SSathya Perla 	} else {
3664e5e1ee89SPadmanabh Ratnakar 		req->perm_override = 1;
36655a712c13SSathya Perla 	}
3666590c391dSPadmanabh Ratnakar 
3667590c391dSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3668590c391dSPadmanabh Ratnakar 	if (!status) {
3669590c391dSPadmanabh Ratnakar 		struct be_cmd_resp_get_mac_list *resp =
3670e5e1ee89SPadmanabh Ratnakar 						get_mac_list_cmd.va;
36715a712c13SSathya Perla 
36725a712c13SSathya Perla 		if (*pmac_id_valid) {
36735a712c13SSathya Perla 			memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr,
36745a712c13SSathya Perla 			       ETH_ALEN);
36755a712c13SSathya Perla 			goto out;
36765a712c13SSathya Perla 		}
36775a712c13SSathya Perla 
3678e5e1ee89SPadmanabh Ratnakar 		mac_count = resp->true_mac_count + resp->pseudo_mac_count;
3679e5e1ee89SPadmanabh Ratnakar 		/* Mac list returned could contain one or more active mac_ids
3680dbedd44eSJoe Perches 		 * or one or more true or pseudo permanent mac addresses.
36811578e777SPadmanabh Ratnakar 		 * If an active mac_id is present, return first active mac_id
36821578e777SPadmanabh Ratnakar 		 * found.
3683e5e1ee89SPadmanabh Ratnakar 		 */
3684590c391dSPadmanabh Ratnakar 		for (i = 0; i < mac_count; i++) {
3685e5e1ee89SPadmanabh Ratnakar 			struct get_list_macaddr *mac_entry;
3686e5e1ee89SPadmanabh Ratnakar 			u16 mac_addr_size;
3687e5e1ee89SPadmanabh Ratnakar 			u32 mac_id;
3688e5e1ee89SPadmanabh Ratnakar 
3689e5e1ee89SPadmanabh Ratnakar 			mac_entry = &resp->macaddr_list[i];
3690e5e1ee89SPadmanabh Ratnakar 			mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size);
3691e5e1ee89SPadmanabh Ratnakar 			/* mac_id is a 32 bit value and mac_addr size
3692e5e1ee89SPadmanabh Ratnakar 			 * is 6 bytes
3693e5e1ee89SPadmanabh Ratnakar 			 */
3694e5e1ee89SPadmanabh Ratnakar 			if (mac_addr_size == sizeof(u32)) {
36955a712c13SSathya Perla 				*pmac_id_valid = true;
3696e5e1ee89SPadmanabh Ratnakar 				mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id;
3697e5e1ee89SPadmanabh Ratnakar 				*pmac_id = le32_to_cpu(mac_id);
3698e5e1ee89SPadmanabh Ratnakar 				goto out;
3699590c391dSPadmanabh Ratnakar 			}
3700590c391dSPadmanabh Ratnakar 		}
37011578e777SPadmanabh Ratnakar 		/* If no active mac_id found, return first mac addr */
37025a712c13SSathya Perla 		*pmac_id_valid = false;
3703e5e1ee89SPadmanabh Ratnakar 		memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr,
3704e5e1ee89SPadmanabh Ratnakar 		       ETH_ALEN);
3705590c391dSPadmanabh Ratnakar 	}
3706590c391dSPadmanabh Ratnakar 
3707e5e1ee89SPadmanabh Ratnakar out:
3708590c391dSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3709e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, get_mac_list_cmd.size,
3710e5e1ee89SPadmanabh Ratnakar 			  get_mac_list_cmd.va, get_mac_list_cmd.dma);
3711590c391dSPadmanabh Ratnakar 	return status;
3712590c391dSPadmanabh Ratnakar }
3713590c391dSPadmanabh Ratnakar 
3714a2cc4e0bSSathya Perla int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id,
3715a2cc4e0bSSathya Perla 			  u8 *mac, u32 if_handle, bool active, u32 domain)
37165a712c13SSathya Perla {
3717b188f090SSuresh Reddy 	if (!active)
3718b188f090SSuresh Reddy 		be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id,
3719b188f090SSuresh Reddy 					 if_handle, domain);
37203175d8c2SSathya Perla 	if (BEx_chip(adapter))
37215a712c13SSathya Perla 		return be_cmd_mac_addr_query(adapter, mac, false,
3722b188f090SSuresh Reddy 					     if_handle, curr_pmac_id);
37233175d8c2SSathya Perla 	else
37243175d8c2SSathya Perla 		/* Fetch the MAC address using pmac_id */
37253175d8c2SSathya Perla 		return be_cmd_get_mac_from_list(adapter, mac, &active,
3726b188f090SSuresh Reddy 						&curr_pmac_id,
3727b188f090SSuresh Reddy 						if_handle, domain);
37285a712c13SSathya Perla }
37295a712c13SSathya Perla 
373095046b92SSathya Perla int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac)
373195046b92SSathya Perla {
373295046b92SSathya Perla 	int status;
373395046b92SSathya Perla 	bool pmac_valid = false;
373495046b92SSathya Perla 
3735c7bf7169SJoe Perches 	eth_zero_addr(mac);
373695046b92SSathya Perla 
37373175d8c2SSathya Perla 	if (BEx_chip(adapter)) {
37383175d8c2SSathya Perla 		if (be_physfn(adapter))
37393175d8c2SSathya Perla 			status = be_cmd_mac_addr_query(adapter, mac, true, 0,
37403175d8c2SSathya Perla 						       0);
374195046b92SSathya Perla 		else
374295046b92SSathya Perla 			status = be_cmd_mac_addr_query(adapter, mac, false,
374395046b92SSathya Perla 						       adapter->if_handle, 0);
37443175d8c2SSathya Perla 	} else {
37453175d8c2SSathya Perla 		status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid,
3746b188f090SSuresh Reddy 						  NULL, adapter->if_handle, 0);
37473175d8c2SSathya Perla 	}
37483175d8c2SSathya Perla 
374995046b92SSathya Perla 	return status;
375095046b92SSathya Perla }
375195046b92SSathya Perla 
3752590c391dSPadmanabh Ratnakar /* Uses synchronous MCCQ */
3753590c391dSPadmanabh Ratnakar int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
3754590c391dSPadmanabh Ratnakar 			u8 mac_count, u32 domain)
3755590c391dSPadmanabh Ratnakar {
3756590c391dSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3757590c391dSPadmanabh Ratnakar 	struct be_cmd_req_set_mac_list *req;
3758590c391dSPadmanabh Ratnakar 	int status;
3759590c391dSPadmanabh Ratnakar 	struct be_dma_mem cmd;
3760590c391dSPadmanabh Ratnakar 
3761590c391dSPadmanabh Ratnakar 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3762590c391dSPadmanabh Ratnakar 	cmd.size = sizeof(struct be_cmd_req_set_mac_list);
3763e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
3764e51000dbSSriharsha Basavapatna 				     GFP_KERNEL);
3765d0320f75SJoe Perches 	if (!cmd.va)
3766590c391dSPadmanabh Ratnakar 		return -ENOMEM;
3767590c391dSPadmanabh Ratnakar 
3768590c391dSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
3769590c391dSPadmanabh Ratnakar 
3770590c391dSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
3771590c391dSPadmanabh Ratnakar 	if (!wrb) {
3772590c391dSPadmanabh Ratnakar 		status = -EBUSY;
3773590c391dSPadmanabh Ratnakar 		goto err;
3774590c391dSPadmanabh Ratnakar 	}
3775590c391dSPadmanabh Ratnakar 
3776590c391dSPadmanabh Ratnakar 	req = cmd.va;
3777590c391dSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3778590c391dSPadmanabh Ratnakar 			       OPCODE_COMMON_SET_MAC_LIST, sizeof(*req),
3779590c391dSPadmanabh Ratnakar 			       wrb, &cmd);
3780590c391dSPadmanabh Ratnakar 
3781590c391dSPadmanabh Ratnakar 	req->hdr.domain = domain;
3782590c391dSPadmanabh Ratnakar 	req->mac_count = mac_count;
3783590c391dSPadmanabh Ratnakar 	if (mac_count)
3784590c391dSPadmanabh Ratnakar 		memcpy(req->mac, mac_array, ETH_ALEN*mac_count);
3785590c391dSPadmanabh Ratnakar 
3786590c391dSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3787590c391dSPadmanabh Ratnakar 
3788590c391dSPadmanabh Ratnakar err:
3789a2cc4e0bSSathya Perla 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
3790590c391dSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3791590c391dSPadmanabh Ratnakar 	return status;
3792590c391dSPadmanabh Ratnakar }
37934762f6ceSAjit Khaparde 
37943175d8c2SSathya Perla /* Wrapper to delete any active MACs and provision the new mac.
37953175d8c2SSathya Perla  * Changes to MAC_LIST are allowed iff none of the MAC addresses in the
37963175d8c2SSathya Perla  * current list are active.
37973175d8c2SSathya Perla  */
37983175d8c2SSathya Perla int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
37993175d8c2SSathya Perla {
38003175d8c2SSathya Perla 	bool active_mac = false;
38013175d8c2SSathya Perla 	u8 old_mac[ETH_ALEN];
38023175d8c2SSathya Perla 	u32 pmac_id;
38033175d8c2SSathya Perla 	int status;
38043175d8c2SSathya Perla 
38053175d8c2SSathya Perla 	status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
3806b188f090SSuresh Reddy 					  &pmac_id, if_id, dom);
3807b188f090SSuresh Reddy 
38083175d8c2SSathya Perla 	if (!status && active_mac)
38093175d8c2SSathya Perla 		be_cmd_pmac_del(adapter, if_id, pmac_id, dom);
38103175d8c2SSathya Perla 
38113175d8c2SSathya Perla 	return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom);
38123175d8c2SSathya Perla }
38133175d8c2SSathya Perla 
3814f1f3ee1bSAjit Khaparde int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
3815e7bcbd7bSKalesh AP 			  u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk)
3816f1f3ee1bSAjit Khaparde {
3817f1f3ee1bSAjit Khaparde 	struct be_mcc_wrb *wrb;
3818f1f3ee1bSAjit Khaparde 	struct be_cmd_req_set_hsw_config *req;
3819f1f3ee1bSAjit Khaparde 	void *ctxt;
3820f1f3ee1bSAjit Khaparde 	int status;
3821f1f3ee1bSAjit Khaparde 
3822f1f3ee1bSAjit Khaparde 	spin_lock_bh(&adapter->mcc_lock);
3823f1f3ee1bSAjit Khaparde 
3824f1f3ee1bSAjit Khaparde 	wrb = wrb_from_mccq(adapter);
3825f1f3ee1bSAjit Khaparde 	if (!wrb) {
3826f1f3ee1bSAjit Khaparde 		status = -EBUSY;
3827f1f3ee1bSAjit Khaparde 		goto err;
3828f1f3ee1bSAjit Khaparde 	}
3829f1f3ee1bSAjit Khaparde 
3830f1f3ee1bSAjit Khaparde 	req = embedded_payload(wrb);
3831f1f3ee1bSAjit Khaparde 	ctxt = &req->context;
3832f1f3ee1bSAjit Khaparde 
3833f1f3ee1bSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3834a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb,
3835a2cc4e0bSSathya Perla 			       NULL);
3836f1f3ee1bSAjit Khaparde 
3837f1f3ee1bSAjit Khaparde 	req->hdr.domain = domain;
3838f1f3ee1bSAjit Khaparde 	AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id);
3839f1f3ee1bSAjit Khaparde 	if (pvid) {
3840f1f3ee1bSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1);
3841f1f3ee1bSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid);
3842f1f3ee1bSAjit Khaparde 	}
3843a77dcb8cSAjit Khaparde 	if (!BEx_chip(adapter) && hsw_mode) {
3844a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, interface_id,
3845a77dcb8cSAjit Khaparde 			      ctxt, adapter->hba_port_num);
3846a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1);
3847a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type,
3848a77dcb8cSAjit Khaparde 			      ctxt, hsw_mode);
3849a77dcb8cSAjit Khaparde 	}
3850f1f3ee1bSAjit Khaparde 
3851e7bcbd7bSKalesh AP 	/* Enable/disable both mac and vlan spoof checking */
3852e7bcbd7bSKalesh AP 	if (!BEx_chip(adapter) && spoofchk) {
3853e7bcbd7bSKalesh AP 		AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk,
3854e7bcbd7bSKalesh AP 			      ctxt, spoofchk);
3855e7bcbd7bSKalesh AP 		AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk,
3856e7bcbd7bSKalesh AP 			      ctxt, spoofchk);
3857e7bcbd7bSKalesh AP 	}
3858e7bcbd7bSKalesh AP 
3859f1f3ee1bSAjit Khaparde 	be_dws_cpu_to_le(req->context, sizeof(req->context));
3860f1f3ee1bSAjit Khaparde 	status = be_mcc_notify_wait(adapter);
3861f1f3ee1bSAjit Khaparde 
3862f1f3ee1bSAjit Khaparde err:
3863f1f3ee1bSAjit Khaparde 	spin_unlock_bh(&adapter->mcc_lock);
3864f1f3ee1bSAjit Khaparde 	return status;
3865f1f3ee1bSAjit Khaparde }
3866f1f3ee1bSAjit Khaparde 
3867f1f3ee1bSAjit Khaparde /* Get Hyper switch config */
3868f1f3ee1bSAjit Khaparde int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
3869e7bcbd7bSKalesh AP 			  u32 domain, u16 intf_id, u8 *mode, bool *spoofchk)
3870f1f3ee1bSAjit Khaparde {
3871f1f3ee1bSAjit Khaparde 	struct be_mcc_wrb *wrb;
3872f1f3ee1bSAjit Khaparde 	struct be_cmd_req_get_hsw_config *req;
3873f1f3ee1bSAjit Khaparde 	void *ctxt;
3874f1f3ee1bSAjit Khaparde 	int status;
3875f1f3ee1bSAjit Khaparde 	u16 vid;
3876f1f3ee1bSAjit Khaparde 
3877f1f3ee1bSAjit Khaparde 	spin_lock_bh(&adapter->mcc_lock);
3878f1f3ee1bSAjit Khaparde 
3879f1f3ee1bSAjit Khaparde 	wrb = wrb_from_mccq(adapter);
3880f1f3ee1bSAjit Khaparde 	if (!wrb) {
3881f1f3ee1bSAjit Khaparde 		status = -EBUSY;
3882f1f3ee1bSAjit Khaparde 		goto err;
3883f1f3ee1bSAjit Khaparde 	}
3884f1f3ee1bSAjit Khaparde 
3885f1f3ee1bSAjit Khaparde 	req = embedded_payload(wrb);
3886f1f3ee1bSAjit Khaparde 	ctxt = &req->context;
3887f1f3ee1bSAjit Khaparde 
3888f1f3ee1bSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3889a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb,
3890a2cc4e0bSSathya Perla 			       NULL);
3891f1f3ee1bSAjit Khaparde 
3892f1f3ee1bSAjit Khaparde 	req->hdr.domain = domain;
3893a77dcb8cSAjit Khaparde 	AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
3894a77dcb8cSAjit Khaparde 		      ctxt, intf_id);
3895f1f3ee1bSAjit Khaparde 	AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1);
3896a77dcb8cSAjit Khaparde 
38972c07c1d7SVasundhara Volam 	if (!BEx_chip(adapter) && mode) {
3898a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
3899a77dcb8cSAjit Khaparde 			      ctxt, adapter->hba_port_num);
3900a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1);
3901a77dcb8cSAjit Khaparde 	}
3902f1f3ee1bSAjit Khaparde 	be_dws_cpu_to_le(req->context, sizeof(req->context));
3903f1f3ee1bSAjit Khaparde 
3904f1f3ee1bSAjit Khaparde 	status = be_mcc_notify_wait(adapter);
3905f1f3ee1bSAjit Khaparde 	if (!status) {
3906f1f3ee1bSAjit Khaparde 		struct be_cmd_resp_get_hsw_config *resp =
3907f1f3ee1bSAjit Khaparde 						embedded_payload(wrb);
390803d28ffeSKalesh AP 
3909a2cc4e0bSSathya Perla 		be_dws_le_to_cpu(&resp->context, sizeof(resp->context));
3910f1f3ee1bSAjit Khaparde 		vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3911f1f3ee1bSAjit Khaparde 				    pvid, &resp->context);
3912a77dcb8cSAjit Khaparde 		if (pvid)
3913f1f3ee1bSAjit Khaparde 			*pvid = le16_to_cpu(vid);
3914a77dcb8cSAjit Khaparde 		if (mode)
3915a77dcb8cSAjit Khaparde 			*mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3916a77dcb8cSAjit Khaparde 					      port_fwd_type, &resp->context);
3917e7bcbd7bSKalesh AP 		if (spoofchk)
3918e7bcbd7bSKalesh AP 			*spoofchk =
3919e7bcbd7bSKalesh AP 				AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3920e7bcbd7bSKalesh AP 					      spoofchk, &resp->context);
3921f1f3ee1bSAjit Khaparde 	}
3922f1f3ee1bSAjit Khaparde 
3923f1f3ee1bSAjit Khaparde err:
3924f1f3ee1bSAjit Khaparde 	spin_unlock_bh(&adapter->mcc_lock);
3925f1f3ee1bSAjit Khaparde 	return status;
3926f1f3ee1bSAjit Khaparde }
3927f1f3ee1bSAjit Khaparde 
3928f7062ee5SSathya Perla static bool be_is_wol_excluded(struct be_adapter *adapter)
3929f7062ee5SSathya Perla {
3930f7062ee5SSathya Perla 	struct pci_dev *pdev = adapter->pdev;
3931f7062ee5SSathya Perla 
393218c57c74SKalesh AP 	if (be_virtfn(adapter))
3933f7062ee5SSathya Perla 		return true;
3934f7062ee5SSathya Perla 
3935f7062ee5SSathya Perla 	switch (pdev->subsystem_device) {
3936f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID1:
3937f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID2:
3938f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID3:
3939f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID4:
3940f7062ee5SSathya Perla 		return true;
3941f7062ee5SSathya Perla 	default:
3942f7062ee5SSathya Perla 		return false;
3943f7062ee5SSathya Perla 	}
3944f7062ee5SSathya Perla }
3945f7062ee5SSathya Perla 
39464762f6ceSAjit Khaparde int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
39474762f6ceSAjit Khaparde {
39484762f6ceSAjit Khaparde 	struct be_mcc_wrb *wrb;
39494762f6ceSAjit Khaparde 	struct be_cmd_req_acpi_wol_magic_config_v1 *req;
395076a9e08eSSuresh Reddy 	int status = 0;
39514762f6ceSAjit Khaparde 	struct be_dma_mem cmd;
39524762f6ceSAjit Khaparde 
3953f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
3954f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_ETH))
3955f25b119cSPadmanabh Ratnakar 		return -EPERM;
3956f25b119cSPadmanabh Ratnakar 
395776a9e08eSSuresh Reddy 	if (be_is_wol_excluded(adapter))
395876a9e08eSSuresh Reddy 		return status;
395976a9e08eSSuresh Reddy 
3960d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3961d98ef50fSSuresh Reddy 		return -1;
3962d98ef50fSSuresh Reddy 
39634762f6ceSAjit Khaparde 	memset(&cmd, 0, sizeof(struct be_dma_mem));
39644762f6ceSAjit Khaparde 	cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
3965e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
3966e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
39674762f6ceSAjit Khaparde 	if (!cmd.va) {
3968a2cc4e0bSSathya Perla 		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
3969d98ef50fSSuresh Reddy 		status = -ENOMEM;
3970d98ef50fSSuresh Reddy 		goto err;
39714762f6ceSAjit Khaparde 	}
39724762f6ceSAjit Khaparde 
39734762f6ceSAjit Khaparde 	wrb = wrb_from_mbox(adapter);
39744762f6ceSAjit Khaparde 	if (!wrb) {
39754762f6ceSAjit Khaparde 		status = -EBUSY;
39764762f6ceSAjit Khaparde 		goto err;
39774762f6ceSAjit Khaparde 	}
39784762f6ceSAjit Khaparde 
39794762f6ceSAjit Khaparde 	req = cmd.va;
39804762f6ceSAjit Khaparde 
39814762f6ceSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
39824762f6ceSAjit Khaparde 			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
398376a9e08eSSuresh Reddy 			       sizeof(*req), wrb, &cmd);
39844762f6ceSAjit Khaparde 
39854762f6ceSAjit Khaparde 	req->hdr.version = 1;
39864762f6ceSAjit Khaparde 	req->query_options = BE_GET_WOL_CAP;
39874762f6ceSAjit Khaparde 
39884762f6ceSAjit Khaparde 	status = be_mbox_notify_wait(adapter);
39894762f6ceSAjit Khaparde 	if (!status) {
39904762f6ceSAjit Khaparde 		struct be_cmd_resp_acpi_wol_magic_config_v1 *resp;
399103d28ffeSKalesh AP 
39924762f6ceSAjit Khaparde 		resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va;
39934762f6ceSAjit Khaparde 
39944762f6ceSAjit Khaparde 		adapter->wol_cap = resp->wol_settings;
399576a9e08eSSuresh Reddy 		if (adapter->wol_cap & BE_WOL_CAP)
399676a9e08eSSuresh Reddy 			adapter->wol_en = true;
39974762f6ceSAjit Khaparde 	}
39984762f6ceSAjit Khaparde err:
39994762f6ceSAjit Khaparde 	mutex_unlock(&adapter->mbox_lock);
4000d98ef50fSSuresh Reddy 	if (cmd.va)
4001e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
4002e51000dbSSriharsha Basavapatna 				  cmd.dma);
40034762f6ceSAjit Khaparde 	return status;
4004941a77d5SSomnath Kotur 
4005941a77d5SSomnath Kotur }
4006baaa08d1SVasundhara Volam 
4007baaa08d1SVasundhara Volam int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level)
4008baaa08d1SVasundhara Volam {
4009baaa08d1SVasundhara Volam 	struct be_dma_mem extfat_cmd;
4010baaa08d1SVasundhara Volam 	struct be_fat_conf_params *cfgs;
4011baaa08d1SVasundhara Volam 	int status;
4012baaa08d1SVasundhara Volam 	int i, j;
4013baaa08d1SVasundhara Volam 
4014baaa08d1SVasundhara Volam 	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
4015baaa08d1SVasundhara Volam 	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
4016e51000dbSSriharsha Basavapatna 	extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
4017e51000dbSSriharsha Basavapatna 					    extfat_cmd.size, &extfat_cmd.dma,
4018e51000dbSSriharsha Basavapatna 					    GFP_ATOMIC);
4019baaa08d1SVasundhara Volam 	if (!extfat_cmd.va)
4020baaa08d1SVasundhara Volam 		return -ENOMEM;
4021baaa08d1SVasundhara Volam 
4022baaa08d1SVasundhara Volam 	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
4023baaa08d1SVasundhara Volam 	if (status)
4024baaa08d1SVasundhara Volam 		goto err;
4025baaa08d1SVasundhara Volam 
4026baaa08d1SVasundhara Volam 	cfgs = (struct be_fat_conf_params *)
4027baaa08d1SVasundhara Volam 			(extfat_cmd.va + sizeof(struct be_cmd_resp_hdr));
4028baaa08d1SVasundhara Volam 	for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) {
4029baaa08d1SVasundhara Volam 		u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes);
403003d28ffeSKalesh AP 
4031baaa08d1SVasundhara Volam 		for (j = 0; j < num_modes; j++) {
4032baaa08d1SVasundhara Volam 			if (cfgs->module[i].trace_lvl[j].mode == MODE_UART)
4033baaa08d1SVasundhara Volam 				cfgs->module[i].trace_lvl[j].dbg_lvl =
4034baaa08d1SVasundhara Volam 							cpu_to_le32(level);
4035baaa08d1SVasundhara Volam 		}
4036baaa08d1SVasundhara Volam 	}
4037baaa08d1SVasundhara Volam 
4038baaa08d1SVasundhara Volam 	status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs);
4039baaa08d1SVasundhara Volam err:
4040e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va,
4041baaa08d1SVasundhara Volam 			  extfat_cmd.dma);
4042baaa08d1SVasundhara Volam 	return status;
4043baaa08d1SVasundhara Volam }
4044baaa08d1SVasundhara Volam 
4045baaa08d1SVasundhara Volam int be_cmd_get_fw_log_level(struct be_adapter *adapter)
4046baaa08d1SVasundhara Volam {
4047baaa08d1SVasundhara Volam 	struct be_dma_mem extfat_cmd;
4048baaa08d1SVasundhara Volam 	struct be_fat_conf_params *cfgs;
4049baaa08d1SVasundhara Volam 	int status, j;
4050baaa08d1SVasundhara Volam 	int level = 0;
4051baaa08d1SVasundhara Volam 
4052baaa08d1SVasundhara Volam 	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
4053baaa08d1SVasundhara Volam 	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
4054e51000dbSSriharsha Basavapatna 	extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
4055e51000dbSSriharsha Basavapatna 					    extfat_cmd.size, &extfat_cmd.dma,
4056e51000dbSSriharsha Basavapatna 					    GFP_ATOMIC);
4057baaa08d1SVasundhara Volam 
4058baaa08d1SVasundhara Volam 	if (!extfat_cmd.va) {
4059baaa08d1SVasundhara Volam 		dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
4060baaa08d1SVasundhara Volam 			__func__);
4061baaa08d1SVasundhara Volam 		goto err;
4062baaa08d1SVasundhara Volam 	}
4063baaa08d1SVasundhara Volam 
4064baaa08d1SVasundhara Volam 	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
4065baaa08d1SVasundhara Volam 	if (!status) {
4066baaa08d1SVasundhara Volam 		cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
4067baaa08d1SVasundhara Volam 						sizeof(struct be_cmd_resp_hdr));
406803d28ffeSKalesh AP 
4069baaa08d1SVasundhara Volam 		for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) {
4070baaa08d1SVasundhara Volam 			if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
4071baaa08d1SVasundhara Volam 				level = cfgs->module[0].trace_lvl[j].dbg_lvl;
4072baaa08d1SVasundhara Volam 		}
4073baaa08d1SVasundhara Volam 	}
4074e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va,
4075baaa08d1SVasundhara Volam 			  extfat_cmd.dma);
4076baaa08d1SVasundhara Volam err:
4077baaa08d1SVasundhara Volam 	return level;
4078baaa08d1SVasundhara Volam }
4079baaa08d1SVasundhara Volam 
4080941a77d5SSomnath Kotur int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
4081941a77d5SSomnath Kotur 				   struct be_dma_mem *cmd)
4082941a77d5SSomnath Kotur {
4083941a77d5SSomnath Kotur 	struct be_mcc_wrb *wrb;
4084941a77d5SSomnath Kotur 	struct be_cmd_req_get_ext_fat_caps *req;
4085941a77d5SSomnath Kotur 	int status;
4086941a77d5SSomnath Kotur 
4087941a77d5SSomnath Kotur 	if (mutex_lock_interruptible(&adapter->mbox_lock))
4088941a77d5SSomnath Kotur 		return -1;
4089941a77d5SSomnath Kotur 
4090941a77d5SSomnath Kotur 	wrb = wrb_from_mbox(adapter);
4091941a77d5SSomnath Kotur 	if (!wrb) {
4092941a77d5SSomnath Kotur 		status = -EBUSY;
4093941a77d5SSomnath Kotur 		goto err;
4094941a77d5SSomnath Kotur 	}
4095941a77d5SSomnath Kotur 
4096941a77d5SSomnath Kotur 	req = cmd->va;
4097941a77d5SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4098941a77d5SSomnath Kotur 			       OPCODE_COMMON_GET_EXT_FAT_CAPABILITES,
4099941a77d5SSomnath Kotur 			       cmd->size, wrb, cmd);
4100941a77d5SSomnath Kotur 	req->parameter_type = cpu_to_le32(1);
4101941a77d5SSomnath Kotur 
4102941a77d5SSomnath Kotur 	status = be_mbox_notify_wait(adapter);
4103941a77d5SSomnath Kotur err:
4104941a77d5SSomnath Kotur 	mutex_unlock(&adapter->mbox_lock);
4105941a77d5SSomnath Kotur 	return status;
4106941a77d5SSomnath Kotur }
4107941a77d5SSomnath Kotur 
4108941a77d5SSomnath Kotur int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
4109941a77d5SSomnath Kotur 				   struct be_dma_mem *cmd,
4110941a77d5SSomnath Kotur 				   struct be_fat_conf_params *configs)
4111941a77d5SSomnath Kotur {
4112941a77d5SSomnath Kotur 	struct be_mcc_wrb *wrb;
4113941a77d5SSomnath Kotur 	struct be_cmd_req_set_ext_fat_caps *req;
4114941a77d5SSomnath Kotur 	int status;
4115941a77d5SSomnath Kotur 
4116941a77d5SSomnath Kotur 	spin_lock_bh(&adapter->mcc_lock);
4117941a77d5SSomnath Kotur 
4118941a77d5SSomnath Kotur 	wrb = wrb_from_mccq(adapter);
4119941a77d5SSomnath Kotur 	if (!wrb) {
4120941a77d5SSomnath Kotur 		status = -EBUSY;
4121941a77d5SSomnath Kotur 		goto err;
4122941a77d5SSomnath Kotur 	}
4123941a77d5SSomnath Kotur 
4124941a77d5SSomnath Kotur 	req = cmd->va;
4125941a77d5SSomnath Kotur 	memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params));
4126941a77d5SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4127941a77d5SSomnath Kotur 			       OPCODE_COMMON_SET_EXT_FAT_CAPABILITES,
4128941a77d5SSomnath Kotur 			       cmd->size, wrb, cmd);
4129941a77d5SSomnath Kotur 
4130941a77d5SSomnath Kotur 	status = be_mcc_notify_wait(adapter);
4131941a77d5SSomnath Kotur err:
4132941a77d5SSomnath Kotur 	spin_unlock_bh(&adapter->mcc_lock);
4133941a77d5SSomnath Kotur 	return status;
41344762f6ceSAjit Khaparde }
41356a4ab669SParav Pandit 
413621252377SVasundhara Volam int be_cmd_query_port_name(struct be_adapter *adapter)
4137b4e32a71SPadmanabh Ratnakar {
4138b4e32a71SPadmanabh Ratnakar 	struct be_cmd_req_get_port_name *req;
413921252377SVasundhara Volam 	struct be_mcc_wrb *wrb;
4140b4e32a71SPadmanabh Ratnakar 	int status;
4141b4e32a71SPadmanabh Ratnakar 
414221252377SVasundhara Volam 	if (mutex_lock_interruptible(&adapter->mbox_lock))
414321252377SVasundhara Volam 		return -1;
4144b4e32a71SPadmanabh Ratnakar 
414521252377SVasundhara Volam 	wrb = wrb_from_mbox(adapter);
4146b4e32a71SPadmanabh Ratnakar 	req = embedded_payload(wrb);
4147b4e32a71SPadmanabh Ratnakar 
4148b4e32a71SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4149b4e32a71SPadmanabh Ratnakar 			       OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb,
4150b4e32a71SPadmanabh Ratnakar 			       NULL);
415121252377SVasundhara Volam 	if (!BEx_chip(adapter))
4152b4e32a71SPadmanabh Ratnakar 		req->hdr.version = 1;
4153b4e32a71SPadmanabh Ratnakar 
415421252377SVasundhara Volam 	status = be_mbox_notify_wait(adapter);
4155b4e32a71SPadmanabh Ratnakar 	if (!status) {
4156b4e32a71SPadmanabh Ratnakar 		struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb);
415703d28ffeSKalesh AP 
415821252377SVasundhara Volam 		adapter->port_name = resp->port_name[adapter->hba_port_num];
4159b4e32a71SPadmanabh Ratnakar 	} else {
416021252377SVasundhara Volam 		adapter->port_name = adapter->hba_port_num + '0';
4161b4e32a71SPadmanabh Ratnakar 	}
416221252377SVasundhara Volam 
416321252377SVasundhara Volam 	mutex_unlock(&adapter->mbox_lock);
4164b4e32a71SPadmanabh Ratnakar 	return status;
4165b4e32a71SPadmanabh Ratnakar }
4166b4e32a71SPadmanabh Ratnakar 
4167980df249SSuresh Reddy /* When more than 1 NIC descriptor is present in the descriptor list,
4168980df249SSuresh Reddy  * the caller must specify the pf_num to obtain the NIC descriptor
4169980df249SSuresh Reddy  * corresponding to its pci function.
4170980df249SSuresh Reddy  * get_vft must be true when the caller wants the VF-template desc of the
4171980df249SSuresh Reddy  * PF-pool.
4172980df249SSuresh Reddy  * The pf_num should be set to PF_NUM_IGNORE when the caller knows
4173980df249SSuresh Reddy  * that only it's NIC descriptor is present in the descriptor list.
4174980df249SSuresh Reddy  */
417510cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
4176980df249SSuresh Reddy 					       bool get_vft, u8 pf_num)
4177abb93951SPadmanabh Ratnakar {
4178150d58c7SVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
417910cccf60SVasundhara Volam 	struct be_nic_res_desc *nic;
4180abb93951SPadmanabh Ratnakar 	int i;
4181abb93951SPadmanabh Ratnakar 
4182abb93951SPadmanabh Ratnakar 	for (i = 0; i < desc_count; i++) {
4183150d58c7SVasundhara Volam 		if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
418410cccf60SVasundhara Volam 		    hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) {
418510cccf60SVasundhara Volam 			nic = (struct be_nic_res_desc *)hdr;
4186980df249SSuresh Reddy 
4187980df249SSuresh Reddy 			if ((pf_num == PF_NUM_IGNORE ||
4188980df249SSuresh Reddy 			     nic->pf_num == pf_num) &&
4189980df249SSuresh Reddy 			    (!get_vft || nic->flags & BIT(VFT_SHIFT)))
419010cccf60SVasundhara Volam 				return nic;
419110cccf60SVasundhara Volam 		}
4192150d58c7SVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
4193150d58c7SVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
4194150d58c7SVasundhara Volam 	}
4195950e2958SWei Yang 	return NULL;
4196abb93951SPadmanabh Ratnakar }
4197abb93951SPadmanabh Ratnakar 
4198980df249SSuresh Reddy static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count,
4199980df249SSuresh Reddy 					       u8 pf_num)
420010cccf60SVasundhara Volam {
4201980df249SSuresh Reddy 	return be_get_nic_desc(buf, desc_count, true, pf_num);
420210cccf60SVasundhara Volam }
420310cccf60SVasundhara Volam 
4204980df249SSuresh Reddy static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count,
4205980df249SSuresh Reddy 						    u8 pf_num)
420610cccf60SVasundhara Volam {
4207980df249SSuresh Reddy 	return be_get_nic_desc(buf, desc_count, false, pf_num);
420810cccf60SVasundhara Volam }
420910cccf60SVasundhara Volam 
4210980df249SSuresh Reddy static struct be_pcie_res_desc *be_get_pcie_desc(u8 *buf, u32 desc_count,
4211980df249SSuresh Reddy 						 u8 pf_num)
4212150d58c7SVasundhara Volam {
4213150d58c7SVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
4214150d58c7SVasundhara Volam 	struct be_pcie_res_desc *pcie;
4215150d58c7SVasundhara Volam 	int i;
4216150d58c7SVasundhara Volam 
4217150d58c7SVasundhara Volam 	for (i = 0; i < desc_count; i++) {
4218980df249SSuresh Reddy 		if (hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 ||
4219980df249SSuresh Reddy 		    hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1) {
4220150d58c7SVasundhara Volam 			pcie = (struct be_pcie_res_desc *)hdr;
4221980df249SSuresh Reddy 			if (pcie->pf_num == pf_num)
4222150d58c7SVasundhara Volam 				return pcie;
4223150d58c7SVasundhara Volam 		}
4224150d58c7SVasundhara Volam 
4225150d58c7SVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
4226150d58c7SVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
4227150d58c7SVasundhara Volam 	}
4228abb93951SPadmanabh Ratnakar 	return NULL;
4229abb93951SPadmanabh Ratnakar }
4230abb93951SPadmanabh Ratnakar 
4231f93f160bSVasundhara Volam static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
4232f93f160bSVasundhara Volam {
4233f93f160bSVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
4234f93f160bSVasundhara Volam 	int i;
4235f93f160bSVasundhara Volam 
4236f93f160bSVasundhara Volam 	for (i = 0; i < desc_count; i++) {
4237f93f160bSVasundhara Volam 		if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
4238f93f160bSVasundhara Volam 			return (struct be_port_res_desc *)hdr;
4239f93f160bSVasundhara Volam 
4240f93f160bSVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
4241f93f160bSVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
4242f93f160bSVasundhara Volam 	}
4243f93f160bSVasundhara Volam 	return NULL;
4244f93f160bSVasundhara Volam }
4245f93f160bSVasundhara Volam 
424692bf14abSSathya Perla static void be_copy_nic_desc(struct be_resources *res,
424792bf14abSSathya Perla 			     struct be_nic_res_desc *desc)
424892bf14abSSathya Perla {
424992bf14abSSathya Perla 	res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count);
425092bf14abSSathya Perla 	res->max_vlans = le16_to_cpu(desc->vlan_count);
425192bf14abSSathya Perla 	res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
425292bf14abSSathya Perla 	res->max_tx_qs = le16_to_cpu(desc->txq_count);
425392bf14abSSathya Perla 	res->max_rss_qs = le16_to_cpu(desc->rssq_count);
425492bf14abSSathya Perla 	res->max_rx_qs = le16_to_cpu(desc->rq_count);
425592bf14abSSathya Perla 	res->max_evt_qs = le16_to_cpu(desc->eq_count);
4256f2858738SVasundhara Volam 	res->max_cq_count = le16_to_cpu(desc->cq_count);
4257f2858738SVasundhara Volam 	res->max_iface_count = le16_to_cpu(desc->iface_count);
4258f2858738SVasundhara Volam 	res->max_mcc_count = le16_to_cpu(desc->mcc_count);
425992bf14abSSathya Perla 	/* Clear flags that driver is not interested in */
426092bf14abSSathya Perla 	res->if_cap_flags = le32_to_cpu(desc->cap_flags) &
426192bf14abSSathya Perla 				BE_IF_CAP_FLAGS_WANT;
426292bf14abSSathya Perla }
426392bf14abSSathya Perla 
4264abb93951SPadmanabh Ratnakar /* Uses Mbox */
426592bf14abSSathya Perla int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
4266abb93951SPadmanabh Ratnakar {
4267abb93951SPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
4268abb93951SPadmanabh Ratnakar 	struct be_cmd_req_get_func_config *req;
4269abb93951SPadmanabh Ratnakar 	int status;
4270abb93951SPadmanabh Ratnakar 	struct be_dma_mem cmd;
4271abb93951SPadmanabh Ratnakar 
4272d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
4273d98ef50fSSuresh Reddy 		return -1;
4274d98ef50fSSuresh Reddy 
4275abb93951SPadmanabh Ratnakar 	memset(&cmd, 0, sizeof(struct be_dma_mem));
4276abb93951SPadmanabh Ratnakar 	cmd.size = sizeof(struct be_cmd_resp_get_func_config);
4277e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
4278e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
4279abb93951SPadmanabh Ratnakar 	if (!cmd.va) {
4280abb93951SPadmanabh Ratnakar 		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
4281d98ef50fSSuresh Reddy 		status = -ENOMEM;
4282d98ef50fSSuresh Reddy 		goto err;
4283abb93951SPadmanabh Ratnakar 	}
4284abb93951SPadmanabh Ratnakar 
4285abb93951SPadmanabh Ratnakar 	wrb = wrb_from_mbox(adapter);
4286abb93951SPadmanabh Ratnakar 	if (!wrb) {
4287abb93951SPadmanabh Ratnakar 		status = -EBUSY;
4288abb93951SPadmanabh Ratnakar 		goto err;
4289abb93951SPadmanabh Ratnakar 	}
4290abb93951SPadmanabh Ratnakar 
4291abb93951SPadmanabh Ratnakar 	req = cmd.va;
4292abb93951SPadmanabh Ratnakar 
4293abb93951SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4294abb93951SPadmanabh Ratnakar 			       OPCODE_COMMON_GET_FUNC_CONFIG,
4295abb93951SPadmanabh Ratnakar 			       cmd.size, wrb, &cmd);
4296abb93951SPadmanabh Ratnakar 
429728710c55SKalesh AP 	if (skyhawk_chip(adapter))
429828710c55SKalesh AP 		req->hdr.version = 1;
429928710c55SKalesh AP 
4300abb93951SPadmanabh Ratnakar 	status = be_mbox_notify_wait(adapter);
4301abb93951SPadmanabh Ratnakar 	if (!status) {
4302abb93951SPadmanabh Ratnakar 		struct be_cmd_resp_get_func_config *resp = cmd.va;
4303abb93951SPadmanabh Ratnakar 		u32 desc_count = le32_to_cpu(resp->desc_count);
4304150d58c7SVasundhara Volam 		struct be_nic_res_desc *desc;
4305abb93951SPadmanabh Ratnakar 
4306980df249SSuresh Reddy 		/* GET_FUNC_CONFIG returns resource descriptors of the
4307980df249SSuresh Reddy 		 * current function only. So, pf_num should be set to
4308980df249SSuresh Reddy 		 * PF_NUM_IGNORE.
4309980df249SSuresh Reddy 		 */
4310980df249SSuresh Reddy 		desc = be_get_func_nic_desc(resp->func_param, desc_count,
4311980df249SSuresh Reddy 					    PF_NUM_IGNORE);
4312abb93951SPadmanabh Ratnakar 		if (!desc) {
4313abb93951SPadmanabh Ratnakar 			status = -EINVAL;
4314abb93951SPadmanabh Ratnakar 			goto err;
4315abb93951SPadmanabh Ratnakar 		}
4316980df249SSuresh Reddy 
4317980df249SSuresh Reddy 		/* Store pf_num & vf_num for later use in GET_PROFILE_CONFIG */
4318980df249SSuresh Reddy 		adapter->pf_num = desc->pf_num;
4319980df249SSuresh Reddy 		adapter->vf_num = desc->vf_num;
4320980df249SSuresh Reddy 
4321980df249SSuresh Reddy 		if (res)
432292bf14abSSathya Perla 			be_copy_nic_desc(res, desc);
4323abb93951SPadmanabh Ratnakar 	}
4324abb93951SPadmanabh Ratnakar err:
4325abb93951SPadmanabh Ratnakar 	mutex_unlock(&adapter->mbox_lock);
4326d98ef50fSSuresh Reddy 	if (cmd.va)
4327e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
4328e51000dbSSriharsha Basavapatna 				  cmd.dma);
4329abb93951SPadmanabh Ratnakar 	return status;
4330abb93951SPadmanabh Ratnakar }
4331abb93951SPadmanabh Ratnakar 
4332980df249SSuresh Reddy /* Will use MBOX only if MCCQ has not been created */
433392bf14abSSathya Perla int be_cmd_get_profile_config(struct be_adapter *adapter,
4334f2858738SVasundhara Volam 			      struct be_resources *res, u8 query, u8 domain)
4335a05f99dbSVasundhara Volam {
4336150d58c7SVasundhara Volam 	struct be_cmd_resp_get_profile_config *resp;
4337ba48c0c9SVasundhara Volam 	struct be_cmd_req_get_profile_config *req;
433810cccf60SVasundhara Volam 	struct be_nic_res_desc *vf_res;
4339150d58c7SVasundhara Volam 	struct be_pcie_res_desc *pcie;
4340f93f160bSVasundhara Volam 	struct be_port_res_desc *port;
4341150d58c7SVasundhara Volam 	struct be_nic_res_desc *nic;
4342ba48c0c9SVasundhara Volam 	struct be_mcc_wrb wrb = {0};
4343a05f99dbSVasundhara Volam 	struct be_dma_mem cmd;
4344f2858738SVasundhara Volam 	u16 desc_count;
4345a05f99dbSVasundhara Volam 	int status;
4346a05f99dbSVasundhara Volam 
4347a05f99dbSVasundhara Volam 	memset(&cmd, 0, sizeof(struct be_dma_mem));
4348a05f99dbSVasundhara Volam 	cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
4349e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
4350e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
4351150d58c7SVasundhara Volam 	if (!cmd.va)
4352a05f99dbSVasundhara Volam 		return -ENOMEM;
4353a05f99dbSVasundhara Volam 
4354ba48c0c9SVasundhara Volam 	req = cmd.va;
4355ba48c0c9SVasundhara Volam 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4356ba48c0c9SVasundhara Volam 			       OPCODE_COMMON_GET_PROFILE_CONFIG,
4357ba48c0c9SVasundhara Volam 			       cmd.size, &wrb, &cmd);
4358ba48c0c9SVasundhara Volam 
4359ba48c0c9SVasundhara Volam 	if (!lancer_chip(adapter))
4360ba48c0c9SVasundhara Volam 		req->hdr.version = 1;
4361ba48c0c9SVasundhara Volam 	req->type = ACTIVE_PROFILE_TYPE;
436272ef3a88SSomnath Kotur 	req->hdr.domain = domain;
4363ba48c0c9SVasundhara Volam 
4364f2858738SVasundhara Volam 	/* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the
4365f2858738SVasundhara Volam 	 * descriptors with all bits set to "1" for the fields which can be
4366f2858738SVasundhara Volam 	 * modified using SET_PROFILE_CONFIG cmd.
4367f2858738SVasundhara Volam 	 */
4368f2858738SVasundhara Volam 	if (query == RESOURCE_MODIFIABLE)
4369f2858738SVasundhara Volam 		req->type |= QUERY_MODIFIABLE_FIELDS_TYPE;
4370f2858738SVasundhara Volam 
4371ba48c0c9SVasundhara Volam 	status = be_cmd_notify_wait(adapter, &wrb);
4372150d58c7SVasundhara Volam 	if (status)
4373abb93951SPadmanabh Ratnakar 		goto err;
4374150d58c7SVasundhara Volam 
4375150d58c7SVasundhara Volam 	resp = cmd.va;
4376f2858738SVasundhara Volam 	desc_count = le16_to_cpu(resp->desc_count);
4377150d58c7SVasundhara Volam 
4378980df249SSuresh Reddy 	pcie = be_get_pcie_desc(resp->func_param, desc_count,
4379980df249SSuresh Reddy 				adapter->pf_num);
4380150d58c7SVasundhara Volam 	if (pcie)
438192bf14abSSathya Perla 		res->max_vfs = le16_to_cpu(pcie->num_vfs);
4382150d58c7SVasundhara Volam 
4383f93f160bSVasundhara Volam 	port = be_get_port_desc(resp->func_param, desc_count);
4384f93f160bSVasundhara Volam 	if (port)
4385f93f160bSVasundhara Volam 		adapter->mc_type = port->mc_type;
4386f93f160bSVasundhara Volam 
4387980df249SSuresh Reddy 	nic = be_get_func_nic_desc(resp->func_param, desc_count,
4388980df249SSuresh Reddy 				   adapter->pf_num);
438992bf14abSSathya Perla 	if (nic)
439092bf14abSSathya Perla 		be_copy_nic_desc(res, nic);
439192bf14abSSathya Perla 
4392980df249SSuresh Reddy 	vf_res = be_get_vft_desc(resp->func_param, desc_count,
4393980df249SSuresh Reddy 				 adapter->pf_num);
439410cccf60SVasundhara Volam 	if (vf_res)
439510cccf60SVasundhara Volam 		res->vf_if_cap_flags = vf_res->cap_flags;
4396abb93951SPadmanabh Ratnakar err:
4397a05f99dbSVasundhara Volam 	if (cmd.va)
4398e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
4399e51000dbSSriharsha Basavapatna 				  cmd.dma);
4400abb93951SPadmanabh Ratnakar 	return status;
4401abb93951SPadmanabh Ratnakar }
4402abb93951SPadmanabh Ratnakar 
4403bec84e6bSVasundhara Volam /* Will use MBOX only if MCCQ has not been created */
4404bec84e6bSVasundhara Volam static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
4405bec84e6bSVasundhara Volam 				     int size, int count, u8 version, u8 domain)
4406d5c18473SPadmanabh Ratnakar {
4407d5c18473SPadmanabh Ratnakar 	struct be_cmd_req_set_profile_config *req;
4408bec84e6bSVasundhara Volam 	struct be_mcc_wrb wrb = {0};
4409bec84e6bSVasundhara Volam 	struct be_dma_mem cmd;
4410d5c18473SPadmanabh Ratnakar 	int status;
4411d5c18473SPadmanabh Ratnakar 
4412bec84e6bSVasundhara Volam 	memset(&cmd, 0, sizeof(struct be_dma_mem));
4413bec84e6bSVasundhara Volam 	cmd.size = sizeof(struct be_cmd_req_set_profile_config);
4414e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
4415e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
4416bec84e6bSVasundhara Volam 	if (!cmd.va)
4417bec84e6bSVasundhara Volam 		return -ENOMEM;
4418d5c18473SPadmanabh Ratnakar 
4419bec84e6bSVasundhara Volam 	req = cmd.va;
4420d5c18473SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4421bec84e6bSVasundhara Volam 			       OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size,
4422bec84e6bSVasundhara Volam 			       &wrb, &cmd);
4423a401801cSSathya Perla 	req->hdr.version = version;
4424d5c18473SPadmanabh Ratnakar 	req->hdr.domain = domain;
4425bec84e6bSVasundhara Volam 	req->desc_count = cpu_to_le32(count);
4426a401801cSSathya Perla 	memcpy(req->desc, desc, size);
4427d5c18473SPadmanabh Ratnakar 
4428bec84e6bSVasundhara Volam 	status = be_cmd_notify_wait(adapter, &wrb);
4429bec84e6bSVasundhara Volam 
4430bec84e6bSVasundhara Volam 	if (cmd.va)
4431e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
4432e51000dbSSriharsha Basavapatna 				  cmd.dma);
4433d5c18473SPadmanabh Ratnakar 	return status;
4434d5c18473SPadmanabh Ratnakar }
4435d5c18473SPadmanabh Ratnakar 
4436a401801cSSathya Perla /* Mark all fields invalid */
4437bec84e6bSVasundhara Volam static void be_reset_nic_desc(struct be_nic_res_desc *nic)
4438a401801cSSathya Perla {
4439a401801cSSathya Perla 	memset(nic, 0, sizeof(*nic));
4440a401801cSSathya Perla 	nic->unicast_mac_count = 0xFFFF;
4441a401801cSSathya Perla 	nic->mcc_count = 0xFFFF;
4442a401801cSSathya Perla 	nic->vlan_count = 0xFFFF;
4443a401801cSSathya Perla 	nic->mcast_mac_count = 0xFFFF;
4444a401801cSSathya Perla 	nic->txq_count = 0xFFFF;
4445a401801cSSathya Perla 	nic->rq_count = 0xFFFF;
4446a401801cSSathya Perla 	nic->rssq_count = 0xFFFF;
4447a401801cSSathya Perla 	nic->lro_count = 0xFFFF;
4448a401801cSSathya Perla 	nic->cq_count = 0xFFFF;
4449a401801cSSathya Perla 	nic->toe_conn_count = 0xFFFF;
4450a401801cSSathya Perla 	nic->eq_count = 0xFFFF;
44510f77ba73SRavikumar Nelavelli 	nic->iface_count = 0xFFFF;
4452a401801cSSathya Perla 	nic->link_param = 0xFF;
44530f77ba73SRavikumar Nelavelli 	nic->channel_id_param = cpu_to_le16(0xF000);
4454a401801cSSathya Perla 	nic->acpi_params = 0xFF;
4455a401801cSSathya Perla 	nic->wol_param = 0x0F;
44560f77ba73SRavikumar Nelavelli 	nic->tunnel_iface_count = 0xFFFF;
44570f77ba73SRavikumar Nelavelli 	nic->direct_tenant_iface_count = 0xFFFF;
4458bec84e6bSVasundhara Volam 	nic->bw_min = 0xFFFFFFFF;
4459a401801cSSathya Perla 	nic->bw_max = 0xFFFFFFFF;
4460a401801cSSathya Perla }
4461a401801cSSathya Perla 
4462bec84e6bSVasundhara Volam /* Mark all fields invalid */
4463bec84e6bSVasundhara Volam static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie)
4464bec84e6bSVasundhara Volam {
4465bec84e6bSVasundhara Volam 	memset(pcie, 0, sizeof(*pcie));
4466bec84e6bSVasundhara Volam 	pcie->sriov_state = 0xFF;
4467bec84e6bSVasundhara Volam 	pcie->pf_state = 0xFF;
4468bec84e6bSVasundhara Volam 	pcie->pf_type = 0xFF;
4469bec84e6bSVasundhara Volam 	pcie->num_vfs = 0xFFFF;
4470bec84e6bSVasundhara Volam }
4471bec84e6bSVasundhara Volam 
44720f77ba73SRavikumar Nelavelli int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
44730f77ba73SRavikumar Nelavelli 		      u8 domain)
4474a401801cSSathya Perla {
4475a401801cSSathya Perla 	struct be_nic_res_desc nic_desc;
44760f77ba73SRavikumar Nelavelli 	u32 bw_percent;
44770f77ba73SRavikumar Nelavelli 	u16 version = 0;
44780f77ba73SRavikumar Nelavelli 
44790f77ba73SRavikumar Nelavelli 	if (BE3_chip(adapter))
44800f77ba73SRavikumar Nelavelli 		return be_cmd_set_qos(adapter, max_rate / 10, domain);
4481a401801cSSathya Perla 
4482a401801cSSathya Perla 	be_reset_nic_desc(&nic_desc);
4483980df249SSuresh Reddy 	nic_desc.pf_num = adapter->pf_num;
44840f77ba73SRavikumar Nelavelli 	nic_desc.vf_num = domain;
448558bdeaa6SKalesh AP 	nic_desc.bw_min = 0;
44860f77ba73SRavikumar Nelavelli 	if (lancer_chip(adapter)) {
4487a401801cSSathya Perla 		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
4488a401801cSSathya Perla 		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
4489a401801cSSathya Perla 		nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
4490a401801cSSathya Perla 					(1 << NOSV_SHIFT);
44910f77ba73SRavikumar Nelavelli 		nic_desc.bw_max = cpu_to_le32(max_rate / 10);
44920f77ba73SRavikumar Nelavelli 	} else {
44930f77ba73SRavikumar Nelavelli 		version = 1;
44940f77ba73SRavikumar Nelavelli 		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
44950f77ba73SRavikumar Nelavelli 		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
44960f77ba73SRavikumar Nelavelli 		nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
44970f77ba73SRavikumar Nelavelli 		bw_percent = max_rate ? (max_rate * 100) / link_speed : 100;
44980f77ba73SRavikumar Nelavelli 		nic_desc.bw_max = cpu_to_le32(bw_percent);
44990f77ba73SRavikumar Nelavelli 	}
4500a401801cSSathya Perla 
4501a401801cSSathya Perla 	return be_cmd_set_profile_config(adapter, &nic_desc,
45020f77ba73SRavikumar Nelavelli 					 nic_desc.hdr.desc_len,
4503bec84e6bSVasundhara Volam 					 1, version, domain);
4504bec84e6bSVasundhara Volam }
4505bec84e6bSVasundhara Volam 
4506f2858738SVasundhara Volam static void be_fill_vf_res_template(struct be_adapter *adapter,
4507f2858738SVasundhara Volam 				    struct be_resources pool_res,
4508f2858738SVasundhara Volam 				    u16 num_vfs, u16 num_vf_qs,
4509f2858738SVasundhara Volam 				    struct be_nic_res_desc *nic_vft)
4510f2858738SVasundhara Volam {
4511f2858738SVasundhara Volam 	u32 vf_if_cap_flags = pool_res.vf_if_cap_flags;
4512f2858738SVasundhara Volam 	struct be_resources res_mod = {0};
4513f2858738SVasundhara Volam 
4514f2858738SVasundhara Volam 	/* Resource with fields set to all '1's by GET_PROFILE_CONFIG cmd,
4515f2858738SVasundhara Volam 	 * which are modifiable using SET_PROFILE_CONFIG cmd.
4516f2858738SVasundhara Volam 	 */
4517f2858738SVasundhara Volam 	be_cmd_get_profile_config(adapter, &res_mod, RESOURCE_MODIFIABLE, 0);
4518f2858738SVasundhara Volam 
4519f2858738SVasundhara Volam 	/* If RSS IFACE capability flags are modifiable for a VF, set the
4520f2858738SVasundhara Volam 	 * capability flag as valid and set RSS and DEFQ_RSS IFACE flags if
4521f2858738SVasundhara Volam 	 * more than 1 RSSQ is available for a VF.
4522f2858738SVasundhara Volam 	 * Otherwise, provision only 1 queue pair for VF.
4523f2858738SVasundhara Volam 	 */
4524f2858738SVasundhara Volam 	if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_RSS) {
4525f2858738SVasundhara Volam 		nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
4526f2858738SVasundhara Volam 		if (num_vf_qs > 1) {
4527f2858738SVasundhara Volam 			vf_if_cap_flags |= BE_IF_FLAGS_RSS;
4528f2858738SVasundhara Volam 			if (pool_res.if_cap_flags & BE_IF_FLAGS_DEFQ_RSS)
4529f2858738SVasundhara Volam 				vf_if_cap_flags |= BE_IF_FLAGS_DEFQ_RSS;
4530f2858738SVasundhara Volam 		} else {
4531f2858738SVasundhara Volam 			vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS |
4532f2858738SVasundhara Volam 					     BE_IF_FLAGS_DEFQ_RSS);
4533f2858738SVasundhara Volam 		}
4534f2858738SVasundhara Volam 	} else {
4535f2858738SVasundhara Volam 		num_vf_qs = 1;
4536f2858738SVasundhara Volam 	}
4537f2858738SVasundhara Volam 
4538196e3735SKalesh AP 	if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) {
4539196e3735SKalesh AP 		nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
4540196e3735SKalesh AP 		vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
4541196e3735SKalesh AP 	}
4542196e3735SKalesh AP 
4543196e3735SKalesh AP 	nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
4544f2858738SVasundhara Volam 	nic_vft->rq_count = cpu_to_le16(num_vf_qs);
4545f2858738SVasundhara Volam 	nic_vft->txq_count = cpu_to_le16(num_vf_qs);
4546f2858738SVasundhara Volam 	nic_vft->rssq_count = cpu_to_le16(num_vf_qs);
4547f2858738SVasundhara Volam 	nic_vft->cq_count = cpu_to_le16(pool_res.max_cq_count /
4548f2858738SVasundhara Volam 					(num_vfs + 1));
4549f2858738SVasundhara Volam 
4550f2858738SVasundhara Volam 	/* Distribute unicast MACs, VLANs, IFACE count and MCCQ count equally
4551f2858738SVasundhara Volam 	 * among the PF and it's VFs, if the fields are changeable
4552f2858738SVasundhara Volam 	 */
4553f2858738SVasundhara Volam 	if (res_mod.max_uc_mac == FIELD_MODIFIABLE)
4554f2858738SVasundhara Volam 		nic_vft->unicast_mac_count = cpu_to_le16(pool_res.max_uc_mac /
4555f2858738SVasundhara Volam 							 (num_vfs + 1));
4556f2858738SVasundhara Volam 
4557f2858738SVasundhara Volam 	if (res_mod.max_vlans == FIELD_MODIFIABLE)
4558f2858738SVasundhara Volam 		nic_vft->vlan_count = cpu_to_le16(pool_res.max_vlans /
4559f2858738SVasundhara Volam 						  (num_vfs + 1));
4560f2858738SVasundhara Volam 
4561f2858738SVasundhara Volam 	if (res_mod.max_iface_count == FIELD_MODIFIABLE)
4562f2858738SVasundhara Volam 		nic_vft->iface_count = cpu_to_le16(pool_res.max_iface_count /
4563f2858738SVasundhara Volam 						   (num_vfs + 1));
4564f2858738SVasundhara Volam 
4565f2858738SVasundhara Volam 	if (res_mod.max_mcc_count == FIELD_MODIFIABLE)
4566f2858738SVasundhara Volam 		nic_vft->mcc_count = cpu_to_le16(pool_res.max_mcc_count /
4567f2858738SVasundhara Volam 						 (num_vfs + 1));
4568f2858738SVasundhara Volam }
4569f2858738SVasundhara Volam 
4570bec84e6bSVasundhara Volam int be_cmd_set_sriov_config(struct be_adapter *adapter,
4571f2858738SVasundhara Volam 			    struct be_resources pool_res, u16 num_vfs,
4572f2858738SVasundhara Volam 			    u16 num_vf_qs)
4573bec84e6bSVasundhara Volam {
4574bec84e6bSVasundhara Volam 	struct {
4575bec84e6bSVasundhara Volam 		struct be_pcie_res_desc pcie;
4576bec84e6bSVasundhara Volam 		struct be_nic_res_desc nic_vft;
4577bec84e6bSVasundhara Volam 	} __packed desc;
4578bec84e6bSVasundhara Volam 
4579bec84e6bSVasundhara Volam 	/* PF PCIE descriptor */
4580bec84e6bSVasundhara Volam 	be_reset_pcie_desc(&desc.pcie);
4581bec84e6bSVasundhara Volam 	desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1;
4582bec84e6bSVasundhara Volam 	desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
4583f2858738SVasundhara Volam 	desc.pcie.flags = BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
4584bec84e6bSVasundhara Volam 	desc.pcie.pf_num = adapter->pdev->devfn;
4585bec84e6bSVasundhara Volam 	desc.pcie.sriov_state = num_vfs ? 1 : 0;
4586bec84e6bSVasundhara Volam 	desc.pcie.num_vfs = cpu_to_le16(num_vfs);
4587bec84e6bSVasundhara Volam 
4588bec84e6bSVasundhara Volam 	/* VF NIC Template descriptor */
4589bec84e6bSVasundhara Volam 	be_reset_nic_desc(&desc.nic_vft);
4590bec84e6bSVasundhara Volam 	desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
4591bec84e6bSVasundhara Volam 	desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
4592f2858738SVasundhara Volam 	desc.nic_vft.flags = BIT(VFT_SHIFT) | BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
4593bec84e6bSVasundhara Volam 	desc.nic_vft.pf_num = adapter->pdev->devfn;
4594bec84e6bSVasundhara Volam 	desc.nic_vft.vf_num = 0;
4595bec84e6bSVasundhara Volam 
4596f2858738SVasundhara Volam 	be_fill_vf_res_template(adapter, pool_res, num_vfs, num_vf_qs,
4597f2858738SVasundhara Volam 				&desc.nic_vft);
4598bec84e6bSVasundhara Volam 
4599bec84e6bSVasundhara Volam 	return be_cmd_set_profile_config(adapter, &desc,
4600bec84e6bSVasundhara Volam 					 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
4601a401801cSSathya Perla }
4602a401801cSSathya Perla 
4603a401801cSSathya Perla int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
4604a401801cSSathya Perla {
4605a401801cSSathya Perla 	struct be_mcc_wrb *wrb;
4606a401801cSSathya Perla 	struct be_cmd_req_manage_iface_filters *req;
4607a401801cSSathya Perla 	int status;
4608a401801cSSathya Perla 
4609a401801cSSathya Perla 	if (iface == 0xFFFFFFFF)
4610a401801cSSathya Perla 		return -1;
4611a401801cSSathya Perla 
4612a401801cSSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
4613a401801cSSathya Perla 
4614a401801cSSathya Perla 	wrb = wrb_from_mccq(adapter);
4615a401801cSSathya Perla 	if (!wrb) {
4616a401801cSSathya Perla 		status = -EBUSY;
4617a401801cSSathya Perla 		goto err;
4618a401801cSSathya Perla 	}
4619a401801cSSathya Perla 	req = embedded_payload(wrb);
4620a401801cSSathya Perla 
4621a401801cSSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4622a401801cSSathya Perla 			       OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req),
4623a401801cSSathya Perla 			       wrb, NULL);
4624a401801cSSathya Perla 	req->op = op;
4625a401801cSSathya Perla 	req->target_iface_id = cpu_to_le32(iface);
4626a401801cSSathya Perla 
4627a401801cSSathya Perla 	status = be_mcc_notify_wait(adapter);
4628a401801cSSathya Perla err:
4629a401801cSSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
4630a401801cSSathya Perla 	return status;
4631a401801cSSathya Perla }
4632a401801cSSathya Perla 
4633a401801cSSathya Perla int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port)
4634a401801cSSathya Perla {
4635a401801cSSathya Perla 	struct be_port_res_desc port_desc;
4636a401801cSSathya Perla 
4637a401801cSSathya Perla 	memset(&port_desc, 0, sizeof(port_desc));
4638a401801cSSathya Perla 	port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1;
4639a401801cSSathya Perla 	port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
4640a401801cSSathya Perla 	port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
4641a401801cSSathya Perla 	port_desc.link_num = adapter->hba_port_num;
4642a401801cSSathya Perla 	if (port) {
4643a401801cSSathya Perla 		port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) |
4644a401801cSSathya Perla 					(1 << RCVID_SHIFT);
4645a401801cSSathya Perla 		port_desc.nv_port = swab16(port);
4646a401801cSSathya Perla 	} else {
4647a401801cSSathya Perla 		port_desc.nv_flags = NV_TYPE_DISABLED;
4648a401801cSSathya Perla 		port_desc.nv_port = 0;
4649a401801cSSathya Perla 	}
4650a401801cSSathya Perla 
4651a401801cSSathya Perla 	return be_cmd_set_profile_config(adapter, &port_desc,
4652bec84e6bSVasundhara Volam 					 RESOURCE_DESC_SIZE_V1, 1, 1, 0);
4653a401801cSSathya Perla }
4654a401801cSSathya Perla 
46554c876616SSathya Perla int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
46564c876616SSathya Perla 		     int vf_num)
46574c876616SSathya Perla {
46584c876616SSathya Perla 	struct be_mcc_wrb *wrb;
46594c876616SSathya Perla 	struct be_cmd_req_get_iface_list *req;
46604c876616SSathya Perla 	struct be_cmd_resp_get_iface_list *resp;
46614c876616SSathya Perla 	int status;
46624c876616SSathya Perla 
46634c876616SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
46644c876616SSathya Perla 
46654c876616SSathya Perla 	wrb = wrb_from_mccq(adapter);
46664c876616SSathya Perla 	if (!wrb) {
46674c876616SSathya Perla 		status = -EBUSY;
46684c876616SSathya Perla 		goto err;
46694c876616SSathya Perla 	}
46704c876616SSathya Perla 	req = embedded_payload(wrb);
46714c876616SSathya Perla 
46724c876616SSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
46734c876616SSathya Perla 			       OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp),
46744c876616SSathya Perla 			       wrb, NULL);
46754c876616SSathya Perla 	req->hdr.domain = vf_num + 1;
46764c876616SSathya Perla 
46774c876616SSathya Perla 	status = be_mcc_notify_wait(adapter);
46784c876616SSathya Perla 	if (!status) {
46794c876616SSathya Perla 		resp = (struct be_cmd_resp_get_iface_list *)req;
46804c876616SSathya Perla 		vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id);
46814c876616SSathya Perla 	}
46824c876616SSathya Perla 
46834c876616SSathya Perla err:
46844c876616SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
46854c876616SSathya Perla 	return status;
46864c876616SSathya Perla }
46874c876616SSathya Perla 
46885c510811SSomnath Kotur static int lancer_wait_idle(struct be_adapter *adapter)
46895c510811SSomnath Kotur {
46905c510811SSomnath Kotur #define SLIPORT_IDLE_TIMEOUT 30
46915c510811SSomnath Kotur 	u32 reg_val;
46925c510811SSomnath Kotur 	int status = 0, i;
46935c510811SSomnath Kotur 
46945c510811SSomnath Kotur 	for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
46955c510811SSomnath Kotur 		reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
46965c510811SSomnath Kotur 		if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
46975c510811SSomnath Kotur 			break;
46985c510811SSomnath Kotur 
46995c510811SSomnath Kotur 		ssleep(1);
47005c510811SSomnath Kotur 	}
47015c510811SSomnath Kotur 
47025c510811SSomnath Kotur 	if (i == SLIPORT_IDLE_TIMEOUT)
47035c510811SSomnath Kotur 		status = -1;
47045c510811SSomnath Kotur 
47055c510811SSomnath Kotur 	return status;
47065c510811SSomnath Kotur }
47075c510811SSomnath Kotur 
47085c510811SSomnath Kotur int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
47095c510811SSomnath Kotur {
47105c510811SSomnath Kotur 	int status = 0;
47115c510811SSomnath Kotur 
47125c510811SSomnath Kotur 	status = lancer_wait_idle(adapter);
47135c510811SSomnath Kotur 	if (status)
47145c510811SSomnath Kotur 		return status;
47155c510811SSomnath Kotur 
47165c510811SSomnath Kotur 	iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
47175c510811SSomnath Kotur 
47185c510811SSomnath Kotur 	return status;
47195c510811SSomnath Kotur }
47205c510811SSomnath Kotur 
47215c510811SSomnath Kotur /* Routine to check whether dump image is present or not */
47225c510811SSomnath Kotur bool dump_present(struct be_adapter *adapter)
47235c510811SSomnath Kotur {
47245c510811SSomnath Kotur 	u32 sliport_status = 0;
47255c510811SSomnath Kotur 
47265c510811SSomnath Kotur 	sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
47275c510811SSomnath Kotur 	return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
47285c510811SSomnath Kotur }
47295c510811SSomnath Kotur 
47305c510811SSomnath Kotur int lancer_initiate_dump(struct be_adapter *adapter)
47315c510811SSomnath Kotur {
4732f0613380SKalesh AP 	struct device *dev = &adapter->pdev->dev;
47335c510811SSomnath Kotur 	int status;
47345c510811SSomnath Kotur 
4735f0613380SKalesh AP 	if (dump_present(adapter)) {
4736f0613380SKalesh AP 		dev_info(dev, "Previous dump not cleared, not forcing dump\n");
4737f0613380SKalesh AP 		return -EEXIST;
4738f0613380SKalesh AP 	}
4739f0613380SKalesh AP 
47405c510811SSomnath Kotur 	/* give firmware reset and diagnostic dump */
47415c510811SSomnath Kotur 	status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
47425c510811SSomnath Kotur 				     PHYSDEV_CONTROL_DD_MASK);
47435c510811SSomnath Kotur 	if (status < 0) {
4744f0613380SKalesh AP 		dev_err(dev, "FW reset failed\n");
47455c510811SSomnath Kotur 		return status;
47465c510811SSomnath Kotur 	}
47475c510811SSomnath Kotur 
47485c510811SSomnath Kotur 	status = lancer_wait_idle(adapter);
47495c510811SSomnath Kotur 	if (status)
47505c510811SSomnath Kotur 		return status;
47515c510811SSomnath Kotur 
47525c510811SSomnath Kotur 	if (!dump_present(adapter)) {
4753f0613380SKalesh AP 		dev_err(dev, "FW dump not generated\n");
4754f0613380SKalesh AP 		return -EIO;
47555c510811SSomnath Kotur 	}
47565c510811SSomnath Kotur 
47575c510811SSomnath Kotur 	return 0;
47585c510811SSomnath Kotur }
47595c510811SSomnath Kotur 
4760f0613380SKalesh AP int lancer_delete_dump(struct be_adapter *adapter)
4761f0613380SKalesh AP {
4762f0613380SKalesh AP 	int status;
4763f0613380SKalesh AP 
4764f0613380SKalesh AP 	status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE);
4765f0613380SKalesh AP 	return be_cmd_status(status);
4766f0613380SKalesh AP }
4767f0613380SKalesh AP 
4768dcf7ebbaSPadmanabh Ratnakar /* Uses sync mcc */
4769dcf7ebbaSPadmanabh Ratnakar int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
4770dcf7ebbaSPadmanabh Ratnakar {
4771dcf7ebbaSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
4772dcf7ebbaSPadmanabh Ratnakar 	struct be_cmd_enable_disable_vf *req;
4773dcf7ebbaSPadmanabh Ratnakar 	int status;
4774dcf7ebbaSPadmanabh Ratnakar 
47750599863dSVasundhara Volam 	if (BEx_chip(adapter))
4776dcf7ebbaSPadmanabh Ratnakar 		return 0;
4777dcf7ebbaSPadmanabh Ratnakar 
4778dcf7ebbaSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
4779dcf7ebbaSPadmanabh Ratnakar 
4780dcf7ebbaSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
4781dcf7ebbaSPadmanabh Ratnakar 	if (!wrb) {
4782dcf7ebbaSPadmanabh Ratnakar 		status = -EBUSY;
4783dcf7ebbaSPadmanabh Ratnakar 		goto err;
4784dcf7ebbaSPadmanabh Ratnakar 	}
4785dcf7ebbaSPadmanabh Ratnakar 
4786dcf7ebbaSPadmanabh Ratnakar 	req = embedded_payload(wrb);
4787dcf7ebbaSPadmanabh Ratnakar 
4788dcf7ebbaSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4789dcf7ebbaSPadmanabh Ratnakar 			       OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
4790dcf7ebbaSPadmanabh Ratnakar 			       wrb, NULL);
4791dcf7ebbaSPadmanabh Ratnakar 
4792dcf7ebbaSPadmanabh Ratnakar 	req->hdr.domain = domain;
4793dcf7ebbaSPadmanabh Ratnakar 	req->enable = 1;
4794dcf7ebbaSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
4795dcf7ebbaSPadmanabh Ratnakar err:
4796dcf7ebbaSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
4797dcf7ebbaSPadmanabh Ratnakar 	return status;
4798dcf7ebbaSPadmanabh Ratnakar }
4799dcf7ebbaSPadmanabh Ratnakar 
480068c45a2dSSomnath Kotur int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable)
480168c45a2dSSomnath Kotur {
480268c45a2dSSomnath Kotur 	struct be_mcc_wrb *wrb;
480368c45a2dSSomnath Kotur 	struct be_cmd_req_intr_set *req;
480468c45a2dSSomnath Kotur 	int status;
480568c45a2dSSomnath Kotur 
480668c45a2dSSomnath Kotur 	if (mutex_lock_interruptible(&adapter->mbox_lock))
480768c45a2dSSomnath Kotur 		return -1;
480868c45a2dSSomnath Kotur 
480968c45a2dSSomnath Kotur 	wrb = wrb_from_mbox(adapter);
481068c45a2dSSomnath Kotur 
481168c45a2dSSomnath Kotur 	req = embedded_payload(wrb);
481268c45a2dSSomnath Kotur 
481368c45a2dSSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
481468c45a2dSSomnath Kotur 			       OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req),
481568c45a2dSSomnath Kotur 			       wrb, NULL);
481668c45a2dSSomnath Kotur 
481768c45a2dSSomnath Kotur 	req->intr_enabled = intr_enable;
481868c45a2dSSomnath Kotur 
481968c45a2dSSomnath Kotur 	status = be_mbox_notify_wait(adapter);
482068c45a2dSSomnath Kotur 
482168c45a2dSSomnath Kotur 	mutex_unlock(&adapter->mbox_lock);
482268c45a2dSSomnath Kotur 	return status;
482368c45a2dSSomnath Kotur }
482468c45a2dSSomnath Kotur 
4825542963b7SVasundhara Volam /* Uses MBOX */
4826542963b7SVasundhara Volam int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id)
4827542963b7SVasundhara Volam {
4828542963b7SVasundhara Volam 	struct be_cmd_req_get_active_profile *req;
4829542963b7SVasundhara Volam 	struct be_mcc_wrb *wrb;
4830542963b7SVasundhara Volam 	int status;
4831542963b7SVasundhara Volam 
4832542963b7SVasundhara Volam 	if (mutex_lock_interruptible(&adapter->mbox_lock))
4833542963b7SVasundhara Volam 		return -1;
4834542963b7SVasundhara Volam 
4835542963b7SVasundhara Volam 	wrb = wrb_from_mbox(adapter);
4836542963b7SVasundhara Volam 	if (!wrb) {
4837542963b7SVasundhara Volam 		status = -EBUSY;
4838542963b7SVasundhara Volam 		goto err;
4839542963b7SVasundhara Volam 	}
4840542963b7SVasundhara Volam 
4841542963b7SVasundhara Volam 	req = embedded_payload(wrb);
4842542963b7SVasundhara Volam 
4843542963b7SVasundhara Volam 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4844542963b7SVasundhara Volam 			       OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req),
4845542963b7SVasundhara Volam 			       wrb, NULL);
4846542963b7SVasundhara Volam 
4847542963b7SVasundhara Volam 	status = be_mbox_notify_wait(adapter);
4848542963b7SVasundhara Volam 	if (!status) {
4849542963b7SVasundhara Volam 		struct be_cmd_resp_get_active_profile *resp =
4850542963b7SVasundhara Volam 							embedded_payload(wrb);
485103d28ffeSKalesh AP 
4852542963b7SVasundhara Volam 		*profile_id = le16_to_cpu(resp->active_profile_id);
4853542963b7SVasundhara Volam 	}
4854542963b7SVasundhara Volam 
4855542963b7SVasundhara Volam err:
4856542963b7SVasundhara Volam 	mutex_unlock(&adapter->mbox_lock);
4857542963b7SVasundhara Volam 	return status;
4858542963b7SVasundhara Volam }
4859542963b7SVasundhara Volam 
4860d9d426afSSuresh Reddy int __be_cmd_set_logical_link_config(struct be_adapter *adapter,
4861d9d426afSSuresh Reddy 				     int link_state, int version, u8 domain)
4862bdce2ad7SSuresh Reddy {
4863bdce2ad7SSuresh Reddy 	struct be_mcc_wrb *wrb;
4864bdce2ad7SSuresh Reddy 	struct be_cmd_req_set_ll_link *req;
4865bdce2ad7SSuresh Reddy 	int status;
4866bdce2ad7SSuresh Reddy 
4867bdce2ad7SSuresh Reddy 	spin_lock_bh(&adapter->mcc_lock);
4868bdce2ad7SSuresh Reddy 
4869bdce2ad7SSuresh Reddy 	wrb = wrb_from_mccq(adapter);
4870bdce2ad7SSuresh Reddy 	if (!wrb) {
4871bdce2ad7SSuresh Reddy 		status = -EBUSY;
4872bdce2ad7SSuresh Reddy 		goto err;
4873bdce2ad7SSuresh Reddy 	}
4874bdce2ad7SSuresh Reddy 
4875bdce2ad7SSuresh Reddy 	req = embedded_payload(wrb);
4876bdce2ad7SSuresh Reddy 
4877bdce2ad7SSuresh Reddy 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4878bdce2ad7SSuresh Reddy 			       OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG,
4879bdce2ad7SSuresh Reddy 			       sizeof(*req), wrb, NULL);
4880bdce2ad7SSuresh Reddy 
4881d9d426afSSuresh Reddy 	req->hdr.version = version;
4882bdce2ad7SSuresh Reddy 	req->hdr.domain = domain;
4883bdce2ad7SSuresh Reddy 
4884d9d426afSSuresh Reddy 	if (link_state == IFLA_VF_LINK_STATE_ENABLE ||
4885d9d426afSSuresh Reddy 	    link_state == IFLA_VF_LINK_STATE_AUTO)
4886d9d426afSSuresh Reddy 		req->link_config |= PLINK_ENABLE;
4887bdce2ad7SSuresh Reddy 
4888bdce2ad7SSuresh Reddy 	if (link_state == IFLA_VF_LINK_STATE_AUTO)
4889d9d426afSSuresh Reddy 		req->link_config |= PLINK_TRACK;
4890bdce2ad7SSuresh Reddy 
4891bdce2ad7SSuresh Reddy 	status = be_mcc_notify_wait(adapter);
4892bdce2ad7SSuresh Reddy err:
4893bdce2ad7SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
4894bdce2ad7SSuresh Reddy 	return status;
4895bdce2ad7SSuresh Reddy }
4896bdce2ad7SSuresh Reddy 
4897d9d426afSSuresh Reddy int be_cmd_set_logical_link_config(struct be_adapter *adapter,
4898d9d426afSSuresh Reddy 				   int link_state, u8 domain)
4899d9d426afSSuresh Reddy {
4900d9d426afSSuresh Reddy 	int status;
4901d9d426afSSuresh Reddy 
4902d9d426afSSuresh Reddy 	if (BEx_chip(adapter))
4903d9d426afSSuresh Reddy 		return -EOPNOTSUPP;
4904d9d426afSSuresh Reddy 
4905d9d426afSSuresh Reddy 	status = __be_cmd_set_logical_link_config(adapter, link_state,
4906d9d426afSSuresh Reddy 						  2, domain);
4907d9d426afSSuresh Reddy 
4908d9d426afSSuresh Reddy 	/* Version 2 of the command will not be recognized by older FW.
4909d9d426afSSuresh Reddy 	 * On such a failure issue version 1 of the command.
4910d9d426afSSuresh Reddy 	 */
4911d9d426afSSuresh Reddy 	if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST)
4912d9d426afSSuresh Reddy 		status = __be_cmd_set_logical_link_config(adapter, link_state,
4913d9d426afSSuresh Reddy 							  1, domain);
4914d9d426afSSuresh Reddy 	return status;
4915d9d426afSSuresh Reddy }
49166a4ab669SParav Pandit int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
49176a4ab669SParav Pandit 		    int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
49186a4ab669SParav Pandit {
49196a4ab669SParav Pandit 	struct be_adapter *adapter = netdev_priv(netdev_handle);
49206a4ab669SParav Pandit 	struct be_mcc_wrb *wrb;
49216a4ab669SParav Pandit 	struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload;
49226a4ab669SParav Pandit 	struct be_cmd_req_hdr *req;
49236a4ab669SParav Pandit 	struct be_cmd_resp_hdr *resp;
49246a4ab669SParav Pandit 	int status;
49256a4ab669SParav Pandit 
49266a4ab669SParav Pandit 	spin_lock_bh(&adapter->mcc_lock);
49276a4ab669SParav Pandit 
49286a4ab669SParav Pandit 	wrb = wrb_from_mccq(adapter);
49296a4ab669SParav Pandit 	if (!wrb) {
49306a4ab669SParav Pandit 		status = -EBUSY;
49316a4ab669SParav Pandit 		goto err;
49326a4ab669SParav Pandit 	}
49336a4ab669SParav Pandit 	req = embedded_payload(wrb);
49346a4ab669SParav Pandit 	resp = embedded_payload(wrb);
49356a4ab669SParav Pandit 
49366a4ab669SParav Pandit 	be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
49376a4ab669SParav Pandit 			       hdr->opcode, wrb_payload_size, wrb, NULL);
49386a4ab669SParav Pandit 	memcpy(req, wrb_payload, wrb_payload_size);
49396a4ab669SParav Pandit 	be_dws_cpu_to_le(req, wrb_payload_size);
49406a4ab669SParav Pandit 
49416a4ab669SParav Pandit 	status = be_mcc_notify_wait(adapter);
49426a4ab669SParav Pandit 	if (cmd_status)
49436a4ab669SParav Pandit 		*cmd_status = (status & 0xffff);
49446a4ab669SParav Pandit 	if (ext_status)
49456a4ab669SParav Pandit 		*ext_status = 0;
49466a4ab669SParav Pandit 	memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
49476a4ab669SParav Pandit 	be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
49486a4ab669SParav Pandit err:
49496a4ab669SParav Pandit 	spin_unlock_bh(&adapter->mcc_lock);
49506a4ab669SParav Pandit 	return status;
49516a4ab669SParav Pandit }
49526a4ab669SParav Pandit EXPORT_SYMBOL(be_roce_mcc_cmd);
4953