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
68f25b119cSPadmanabh Ratnakar 	}
69f25b119cSPadmanabh Ratnakar };
70f25b119cSPadmanabh Ratnakar 
71a2cc4e0bSSathya Perla static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, u8 subsystem)
72f25b119cSPadmanabh Ratnakar {
73f25b119cSPadmanabh Ratnakar 	int i;
74f25b119cSPadmanabh Ratnakar 	int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map);
75f25b119cSPadmanabh Ratnakar 	u32 cmd_privileges = adapter->cmd_privileges;
76f25b119cSPadmanabh Ratnakar 
77f25b119cSPadmanabh Ratnakar 	for (i = 0; i < num_entries; i++)
78f25b119cSPadmanabh Ratnakar 		if (opcode == cmd_priv_map[i].opcode &&
79f25b119cSPadmanabh Ratnakar 		    subsystem == cmd_priv_map[i].subsystem)
80f25b119cSPadmanabh Ratnakar 			if (!(cmd_privileges & cmd_priv_map[i].priv_mask))
81f25b119cSPadmanabh Ratnakar 				return false;
82f25b119cSPadmanabh Ratnakar 
83f25b119cSPadmanabh Ratnakar 	return true;
84f25b119cSPadmanabh Ratnakar }
85f25b119cSPadmanabh Ratnakar 
863de09455SSomnath Kotur static inline void *embedded_payload(struct be_mcc_wrb *wrb)
873de09455SSomnath Kotur {
883de09455SSomnath Kotur 	return wrb->payload.embedded_payload;
893de09455SSomnath Kotur }
909aebddd1SJeff Kirsher 
91efaa408eSSuresh Reddy static int be_mcc_notify(struct be_adapter *adapter)
929aebddd1SJeff Kirsher {
939aebddd1SJeff Kirsher 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
949aebddd1SJeff Kirsher 	u32 val = 0;
959aebddd1SJeff Kirsher 
96954f6825SVenkata Duvvuru 	if (be_check_error(adapter, BE_ERROR_ANY))
97efaa408eSSuresh Reddy 		return -EIO;
989aebddd1SJeff Kirsher 
999aebddd1SJeff Kirsher 	val |= mccq->id & DB_MCCQ_RING_ID_MASK;
1009aebddd1SJeff Kirsher 	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
1019aebddd1SJeff Kirsher 
1029aebddd1SJeff Kirsher 	wmb();
1039aebddd1SJeff Kirsher 	iowrite32(val, adapter->db + DB_MCCQ_OFFSET);
104efaa408eSSuresh Reddy 
105efaa408eSSuresh Reddy 	return 0;
1069aebddd1SJeff Kirsher }
1079aebddd1SJeff Kirsher 
1089aebddd1SJeff Kirsher /* To check if valid bit is set, check the entire word as we don't know
1099aebddd1SJeff Kirsher  * the endianness of the data (old entry is host endian while a new entry is
1109aebddd1SJeff Kirsher  * little endian) */
1119aebddd1SJeff Kirsher static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
1129aebddd1SJeff Kirsher {
1139e9ff4b7SSathya Perla 	u32 flags;
1149e9ff4b7SSathya Perla 
1159aebddd1SJeff Kirsher 	if (compl->flags != 0) {
1169e9ff4b7SSathya Perla 		flags = le32_to_cpu(compl->flags);
1179e9ff4b7SSathya Perla 		if (flags & CQE_FLAGS_VALID_MASK) {
1189e9ff4b7SSathya Perla 			compl->flags = flags;
1199aebddd1SJeff Kirsher 			return true;
1209aebddd1SJeff Kirsher 		}
1219aebddd1SJeff Kirsher 	}
1229e9ff4b7SSathya Perla 	return false;
1239e9ff4b7SSathya Perla }
1249aebddd1SJeff Kirsher 
1259aebddd1SJeff Kirsher /* Need to reset the entire word that houses the valid bit */
1269aebddd1SJeff Kirsher static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
1279aebddd1SJeff Kirsher {
1289aebddd1SJeff Kirsher 	compl->flags = 0;
1299aebddd1SJeff Kirsher }
1309aebddd1SJeff Kirsher 
131652bf646SPadmanabh Ratnakar static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
132652bf646SPadmanabh Ratnakar {
133652bf646SPadmanabh Ratnakar 	unsigned long addr;
134652bf646SPadmanabh Ratnakar 
135652bf646SPadmanabh Ratnakar 	addr = tag1;
136652bf646SPadmanabh Ratnakar 	addr = ((addr << 16) << 16) | tag0;
137652bf646SPadmanabh Ratnakar 	return (void *)addr;
138652bf646SPadmanabh Ratnakar }
139652bf646SPadmanabh Ratnakar 
1404c60005fSKalesh AP static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status)
1414c60005fSKalesh AP {
1424c60005fSKalesh AP 	if (base_status == MCC_STATUS_NOT_SUPPORTED ||
1434c60005fSKalesh AP 	    base_status == MCC_STATUS_ILLEGAL_REQUEST ||
1444c60005fSKalesh AP 	    addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES ||
14577be8c1cSKalesh AP 	    addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS ||
1464c60005fSKalesh AP 	    (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
1474c60005fSKalesh AP 	    (base_status == MCC_STATUS_ILLEGAL_FIELD ||
1484c60005fSKalesh AP 	     addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH)))
1494c60005fSKalesh AP 		return true;
1504c60005fSKalesh AP 	else
1514c60005fSKalesh AP 		return false;
1524c60005fSKalesh AP }
1534c60005fSKalesh AP 
154559b633fSSathya Perla /* Place holder for all the async MCC cmds wherein the caller is not in a busy
155559b633fSSathya Perla  * loop (has not issued be_mcc_notify_wait())
156559b633fSSathya Perla  */
157559b633fSSathya Perla static void be_async_cmd_process(struct be_adapter *adapter,
158559b633fSSathya Perla 				 struct be_mcc_compl *compl,
159559b633fSSathya Perla 				 struct be_cmd_resp_hdr *resp_hdr)
160559b633fSSathya Perla {
161559b633fSSathya Perla 	enum mcc_base_status base_status = base_status(compl->status);
162559b633fSSathya Perla 	u8 opcode = 0, subsystem = 0;
163559b633fSSathya Perla 
164559b633fSSathya Perla 	if (resp_hdr) {
165559b633fSSathya Perla 		opcode = resp_hdr->opcode;
166559b633fSSathya Perla 		subsystem = resp_hdr->subsystem;
167559b633fSSathya Perla 	}
168559b633fSSathya Perla 
169559b633fSSathya Perla 	if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
170559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
171559b633fSSathya Perla 		complete(&adapter->et_cmd_compl);
172559b633fSSathya Perla 		return;
173559b633fSSathya Perla 	}
174559b633fSSathya Perla 
1759c855975SSuresh Reddy 	if (opcode == OPCODE_LOWLEVEL_SET_LOOPBACK_MODE &&
1769c855975SSuresh Reddy 	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
1779c855975SSuresh Reddy 		complete(&adapter->et_cmd_compl);
1789c855975SSuresh Reddy 		return;
1799c855975SSuresh Reddy 	}
1809c855975SSuresh Reddy 
181559b633fSSathya Perla 	if ((opcode == OPCODE_COMMON_WRITE_FLASHROM ||
182559b633fSSathya Perla 	     opcode == OPCODE_COMMON_WRITE_OBJECT) &&
183559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_COMMON) {
184559b633fSSathya Perla 		adapter->flash_status = compl->status;
185559b633fSSathya Perla 		complete(&adapter->et_cmd_compl);
186559b633fSSathya Perla 		return;
187559b633fSSathya Perla 	}
188559b633fSSathya Perla 
189559b633fSSathya Perla 	if ((opcode == OPCODE_ETH_GET_STATISTICS ||
190559b633fSSathya Perla 	     opcode == OPCODE_ETH_GET_PPORT_STATS) &&
191559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_ETH &&
192559b633fSSathya Perla 	    base_status == MCC_STATUS_SUCCESS) {
193559b633fSSathya Perla 		be_parse_stats(adapter);
194559b633fSSathya Perla 		adapter->stats_cmd_sent = false;
195559b633fSSathya Perla 		return;
196559b633fSSathya Perla 	}
197559b633fSSathya Perla 
198559b633fSSathya Perla 	if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
199559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_COMMON) {
200559b633fSSathya Perla 		if (base_status == MCC_STATUS_SUCCESS) {
201559b633fSSathya Perla 			struct be_cmd_resp_get_cntl_addnl_attribs *resp =
202559b633fSSathya Perla 							(void *)resp_hdr;
20329e9122bSVenkata Duvvuru 			adapter->hwmon_info.be_on_die_temp =
204559b633fSSathya Perla 						resp->on_die_temperature;
205559b633fSSathya Perla 		} else {
206559b633fSSathya Perla 			adapter->be_get_temp_freq = 0;
20729e9122bSVenkata Duvvuru 			adapter->hwmon_info.be_on_die_temp =
20829e9122bSVenkata Duvvuru 						BE_INVALID_DIE_TEMP;
209559b633fSSathya Perla 		}
210559b633fSSathya Perla 		return;
211559b633fSSathya Perla 	}
212559b633fSSathya Perla }
213559b633fSSathya Perla 
2149aebddd1SJeff Kirsher static int be_mcc_compl_process(struct be_adapter *adapter,
2159aebddd1SJeff Kirsher 				struct be_mcc_compl *compl)
2169aebddd1SJeff Kirsher {
2174c60005fSKalesh AP 	enum mcc_base_status base_status;
2184c60005fSKalesh AP 	enum mcc_addl_status addl_status;
219652bf646SPadmanabh Ratnakar 	struct be_cmd_resp_hdr *resp_hdr;
220652bf646SPadmanabh Ratnakar 	u8 opcode = 0, subsystem = 0;
2219aebddd1SJeff Kirsher 
2229aebddd1SJeff Kirsher 	/* Just swap the status to host endian; mcc tag is opaquely copied
2239aebddd1SJeff Kirsher 	 * from mcc_wrb */
2249aebddd1SJeff Kirsher 	be_dws_le_to_cpu(compl, 4);
2259aebddd1SJeff Kirsher 
2264c60005fSKalesh AP 	base_status = base_status(compl->status);
2274c60005fSKalesh AP 	addl_status = addl_status(compl->status);
22896c9b2e4SVasundhara Volam 
229652bf646SPadmanabh Ratnakar 	resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
230652bf646SPadmanabh Ratnakar 	if (resp_hdr) {
231652bf646SPadmanabh Ratnakar 		opcode = resp_hdr->opcode;
232652bf646SPadmanabh Ratnakar 		subsystem = resp_hdr->subsystem;
233652bf646SPadmanabh Ratnakar 	}
234652bf646SPadmanabh Ratnakar 
235559b633fSSathya Perla 	be_async_cmd_process(adapter, compl, resp_hdr);
2365eeff635SSuresh Reddy 
237559b633fSSathya Perla 	if (base_status != MCC_STATUS_SUCCESS &&
238559b633fSSathya Perla 	    !be_skip_err_log(opcode, base_status, addl_status)) {
239fa5c867dSSuresh Reddy 		if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST ||
240fa5c867dSSuresh Reddy 		    addl_status == MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES) {
24197f1d8cdSVasundhara Volam 			dev_warn(&adapter->pdev->dev,
242522609f2SVasundhara Volam 				 "VF is not privileged to issue opcode %d-%d\n",
24397f1d8cdSVasundhara Volam 				 opcode, subsystem);
2449aebddd1SJeff Kirsher 		} else {
24597f1d8cdSVasundhara Volam 			dev_err(&adapter->pdev->dev,
24697f1d8cdSVasundhara Volam 				"opcode %d-%d failed:status %d-%d\n",
2474c60005fSKalesh AP 				opcode, subsystem, base_status, addl_status);
2489aebddd1SJeff Kirsher 		}
2499aebddd1SJeff Kirsher 	}
2504c60005fSKalesh AP 	return compl->status;
2519aebddd1SJeff Kirsher }
2529aebddd1SJeff Kirsher 
2539aebddd1SJeff Kirsher /* Link state evt is a string of bytes; no need for endian swapping */
2549aebddd1SJeff Kirsher static void be_async_link_state_process(struct be_adapter *adapter,
2553acf19d9SSathya Perla 					struct be_mcc_compl *compl)
2569aebddd1SJeff Kirsher {
2573acf19d9SSathya Perla 	struct be_async_event_link_state *evt =
2583acf19d9SSathya Perla 			(struct be_async_event_link_state *)compl;
2593acf19d9SSathya Perla 
260b236916aSAjit Khaparde 	/* When link status changes, link speed must be re-queried from FW */
26142f11cf2SAjit Khaparde 	adapter->phy.link_speed = -1;
262b236916aSAjit Khaparde 
263bdce2ad7SSuresh Reddy 	/* On BEx the FW does not send a separate link status
264bdce2ad7SSuresh Reddy 	 * notification for physical and logical link.
265bdce2ad7SSuresh Reddy 	 * On other chips just process the logical link
266bdce2ad7SSuresh Reddy 	 * status notification
267bdce2ad7SSuresh Reddy 	 */
268bdce2ad7SSuresh Reddy 	if (!BEx_chip(adapter) &&
2692e177a5cSPadmanabh Ratnakar 	    !(evt->port_link_status & LOGICAL_LINK_STATUS_MASK))
2702e177a5cSPadmanabh Ratnakar 		return;
2712e177a5cSPadmanabh Ratnakar 
272b236916aSAjit Khaparde 	/* For the initial link status do not rely on the ASYNC event as
273b236916aSAjit Khaparde 	 * it may not be received in some cases.
274b236916aSAjit Khaparde 	 */
275b236916aSAjit Khaparde 	if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
276bdce2ad7SSuresh Reddy 		be_link_status_update(adapter,
277bdce2ad7SSuresh Reddy 				      evt->port_link_status & LINK_STATUS_MASK);
2789aebddd1SJeff Kirsher }
2799aebddd1SJeff Kirsher 
28021252377SVasundhara Volam static void be_async_port_misconfig_event_process(struct be_adapter *adapter,
28121252377SVasundhara Volam 						  struct be_mcc_compl *compl)
28221252377SVasundhara Volam {
28321252377SVasundhara Volam 	struct be_async_event_misconfig_port *evt =
28421252377SVasundhara Volam 			(struct be_async_event_misconfig_port *)compl;
28521252377SVasundhara Volam 	u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1);
28621252377SVasundhara Volam 	struct device *dev = &adapter->pdev->dev;
28721252377SVasundhara Volam 	u8 port_misconfig_evt;
28821252377SVasundhara Volam 
28921252377SVasundhara Volam 	port_misconfig_evt =
29021252377SVasundhara Volam 		((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff);
29121252377SVasundhara Volam 
29221252377SVasundhara Volam 	/* Log an error message that would allow a user to determine
29321252377SVasundhara Volam 	 * whether the SFPs have an issue
29421252377SVasundhara Volam 	 */
29521252377SVasundhara Volam 	dev_info(dev, "Port %c: %s %s", adapter->port_name,
29621252377SVasundhara Volam 		 be_port_misconfig_evt_desc[port_misconfig_evt],
29721252377SVasundhara Volam 		 be_port_misconfig_remedy_desc[port_misconfig_evt]);
29821252377SVasundhara Volam 
29921252377SVasundhara Volam 	if (port_misconfig_evt == INCOMPATIBLE_SFP)
30021252377SVasundhara Volam 		adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP;
30121252377SVasundhara Volam }
30221252377SVasundhara Volam 
3039aebddd1SJeff Kirsher /* Grp5 CoS Priority evt */
3049aebddd1SJeff Kirsher static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
3053acf19d9SSathya Perla 					       struct be_mcc_compl *compl)
3069aebddd1SJeff Kirsher {
3073acf19d9SSathya Perla 	struct be_async_event_grp5_cos_priority *evt =
3083acf19d9SSathya Perla 			(struct be_async_event_grp5_cos_priority *)compl;
3093acf19d9SSathya Perla 
3109aebddd1SJeff Kirsher 	if (evt->valid) {
3119aebddd1SJeff Kirsher 		adapter->vlan_prio_bmap = evt->available_priority_bmap;
312fdf81bfbSSathya Perla 		adapter->recommended_prio_bits =
3139aebddd1SJeff Kirsher 			evt->reco_default_priority << VLAN_PRIO_SHIFT;
3149aebddd1SJeff Kirsher 	}
3159aebddd1SJeff Kirsher }
3169aebddd1SJeff Kirsher 
317323ff71eSSathya Perla /* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */
3189aebddd1SJeff Kirsher static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
3193acf19d9SSathya Perla 					    struct be_mcc_compl *compl)
3209aebddd1SJeff Kirsher {
3213acf19d9SSathya Perla 	struct be_async_event_grp5_qos_link_speed *evt =
3223acf19d9SSathya Perla 			(struct be_async_event_grp5_qos_link_speed *)compl;
3233acf19d9SSathya Perla 
324323ff71eSSathya Perla 	if (adapter->phy.link_speed >= 0 &&
325323ff71eSSathya Perla 	    evt->physical_port == adapter->port_num)
326323ff71eSSathya Perla 		adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10;
3279aebddd1SJeff Kirsher }
3289aebddd1SJeff Kirsher 
3299aebddd1SJeff Kirsher /*Grp5 PVID evt*/
3309aebddd1SJeff Kirsher static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
3313acf19d9SSathya Perla 					     struct be_mcc_compl *compl)
3329aebddd1SJeff Kirsher {
3333acf19d9SSathya Perla 	struct be_async_event_grp5_pvid_state *evt =
3343acf19d9SSathya Perla 			(struct be_async_event_grp5_pvid_state *)compl;
3353acf19d9SSathya Perla 
336bdac85b5SRavikumar Nelavelli 	if (evt->enabled) {
337939cf306SSomnath Kotur 		adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
338bdac85b5SRavikumar Nelavelli 		dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid);
339bdac85b5SRavikumar Nelavelli 	} else {
3409aebddd1SJeff Kirsher 		adapter->pvid = 0;
3419aebddd1SJeff Kirsher 	}
342bdac85b5SRavikumar Nelavelli }
3439aebddd1SJeff Kirsher 
344760c295eSVenkata Duvvuru #define MGMT_ENABLE_MASK	0x4
345760c295eSVenkata Duvvuru static void be_async_grp5_fw_control_process(struct be_adapter *adapter,
346760c295eSVenkata Duvvuru 					     struct be_mcc_compl *compl)
347760c295eSVenkata Duvvuru {
348760c295eSVenkata Duvvuru 	struct be_async_fw_control *evt = (struct be_async_fw_control *)compl;
349760c295eSVenkata Duvvuru 	u32 evt_dw1 = le32_to_cpu(evt->event_data_word1);
350760c295eSVenkata Duvvuru 
351760c295eSVenkata Duvvuru 	if (evt_dw1 & MGMT_ENABLE_MASK) {
352760c295eSVenkata Duvvuru 		adapter->flags |= BE_FLAGS_OS2BMC;
353760c295eSVenkata Duvvuru 		adapter->bmc_filt_mask = le32_to_cpu(evt->event_data_word2);
354760c295eSVenkata Duvvuru 	} else {
355760c295eSVenkata Duvvuru 		adapter->flags &= ~BE_FLAGS_OS2BMC;
356760c295eSVenkata Duvvuru 	}
357760c295eSVenkata Duvvuru }
358760c295eSVenkata Duvvuru 
3599aebddd1SJeff Kirsher static void be_async_grp5_evt_process(struct be_adapter *adapter,
3603acf19d9SSathya Perla 				      struct be_mcc_compl *compl)
3619aebddd1SJeff Kirsher {
3623acf19d9SSathya Perla 	u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) &
3633acf19d9SSathya Perla 				ASYNC_EVENT_TYPE_MASK;
3649aebddd1SJeff Kirsher 
3659aebddd1SJeff Kirsher 	switch (event_type) {
3669aebddd1SJeff Kirsher 	case ASYNC_EVENT_COS_PRIORITY:
3673acf19d9SSathya Perla 		be_async_grp5_cos_priority_process(adapter, compl);
3689aebddd1SJeff Kirsher 		break;
3699aebddd1SJeff Kirsher 	case ASYNC_EVENT_QOS_SPEED:
3703acf19d9SSathya Perla 		be_async_grp5_qos_speed_process(adapter, compl);
3719aebddd1SJeff Kirsher 		break;
3729aebddd1SJeff Kirsher 	case ASYNC_EVENT_PVID_STATE:
3733acf19d9SSathya Perla 		be_async_grp5_pvid_state_process(adapter, compl);
3749aebddd1SJeff Kirsher 		break;
375760c295eSVenkata Duvvuru 	/* Async event to disable/enable os2bmc and/or mac-learning */
376760c295eSVenkata Duvvuru 	case ASYNC_EVENT_FW_CONTROL:
377760c295eSVenkata Duvvuru 		be_async_grp5_fw_control_process(adapter, compl);
378760c295eSVenkata Duvvuru 		break;
3799aebddd1SJeff Kirsher 	default:
3809aebddd1SJeff Kirsher 		break;
3819aebddd1SJeff Kirsher 	}
3829aebddd1SJeff Kirsher }
3839aebddd1SJeff Kirsher 
384bc0c3405SAjit Khaparde static void be_async_dbg_evt_process(struct be_adapter *adapter,
3853acf19d9SSathya Perla 				     struct be_mcc_compl *cmp)
386bc0c3405SAjit Khaparde {
387bc0c3405SAjit Khaparde 	u8 event_type = 0;
388bc0c3405SAjit Khaparde 	struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp;
389bc0c3405SAjit Khaparde 
3903acf19d9SSathya Perla 	event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
3913acf19d9SSathya Perla 			ASYNC_EVENT_TYPE_MASK;
392bc0c3405SAjit Khaparde 
393bc0c3405SAjit Khaparde 	switch (event_type) {
394bc0c3405SAjit Khaparde 	case ASYNC_DEBUG_EVENT_TYPE_QNQ:
395bc0c3405SAjit Khaparde 		if (evt->valid)
396bc0c3405SAjit Khaparde 			adapter->qnq_vid = le16_to_cpu(evt->vlan_tag);
397bc0c3405SAjit Khaparde 		adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
398bc0c3405SAjit Khaparde 	break;
399bc0c3405SAjit Khaparde 	default:
40005ccaa2bSVasundhara Volam 		dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n",
40105ccaa2bSVasundhara Volam 			 event_type);
402bc0c3405SAjit Khaparde 	break;
403bc0c3405SAjit Khaparde 	}
404bc0c3405SAjit Khaparde }
405bc0c3405SAjit Khaparde 
40621252377SVasundhara Volam static void be_async_sliport_evt_process(struct be_adapter *adapter,
40721252377SVasundhara Volam 					 struct be_mcc_compl *cmp)
40821252377SVasundhara Volam {
40921252377SVasundhara Volam 	u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
41021252377SVasundhara Volam 			ASYNC_EVENT_TYPE_MASK;
41121252377SVasundhara Volam 
41221252377SVasundhara Volam 	if (event_type == ASYNC_EVENT_PORT_MISCONFIG)
41321252377SVasundhara Volam 		be_async_port_misconfig_event_process(adapter, cmp);
41421252377SVasundhara Volam }
41521252377SVasundhara Volam 
4163acf19d9SSathya Perla static inline bool is_link_state_evt(u32 flags)
4179aebddd1SJeff Kirsher {
4183acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4199aebddd1SJeff Kirsher 			ASYNC_EVENT_CODE_LINK_STATE;
4209aebddd1SJeff Kirsher }
4219aebddd1SJeff Kirsher 
4223acf19d9SSathya Perla static inline bool is_grp5_evt(u32 flags)
4239aebddd1SJeff Kirsher {
4243acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4253acf19d9SSathya Perla 			ASYNC_EVENT_CODE_GRP_5;
4269aebddd1SJeff Kirsher }
4279aebddd1SJeff Kirsher 
4283acf19d9SSathya Perla static inline bool is_dbg_evt(u32 flags)
429bc0c3405SAjit Khaparde {
4303acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4313acf19d9SSathya Perla 			ASYNC_EVENT_CODE_QNQ;
4323acf19d9SSathya Perla }
4333acf19d9SSathya Perla 
43421252377SVasundhara Volam static inline bool is_sliport_evt(u32 flags)
43521252377SVasundhara Volam {
43621252377SVasundhara Volam 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
43721252377SVasundhara Volam 		ASYNC_EVENT_CODE_SLIPORT;
43821252377SVasundhara Volam }
43921252377SVasundhara Volam 
4403acf19d9SSathya Perla static void be_mcc_event_process(struct be_adapter *adapter,
4413acf19d9SSathya Perla 				 struct be_mcc_compl *compl)
4423acf19d9SSathya Perla {
4433acf19d9SSathya Perla 	if (is_link_state_evt(compl->flags))
4443acf19d9SSathya Perla 		be_async_link_state_process(adapter, compl);
4453acf19d9SSathya Perla 	else if (is_grp5_evt(compl->flags))
4463acf19d9SSathya Perla 		be_async_grp5_evt_process(adapter, compl);
4473acf19d9SSathya Perla 	else if (is_dbg_evt(compl->flags))
4483acf19d9SSathya Perla 		be_async_dbg_evt_process(adapter, compl);
44921252377SVasundhara Volam 	else if (is_sliport_evt(compl->flags))
45021252377SVasundhara Volam 		be_async_sliport_evt_process(adapter, compl);
451bc0c3405SAjit Khaparde }
452bc0c3405SAjit Khaparde 
4539aebddd1SJeff Kirsher static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
4549aebddd1SJeff Kirsher {
4559aebddd1SJeff Kirsher 	struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
4569aebddd1SJeff Kirsher 	struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
4579aebddd1SJeff Kirsher 
4589aebddd1SJeff Kirsher 	if (be_mcc_compl_is_new(compl)) {
4599aebddd1SJeff Kirsher 		queue_tail_inc(mcc_cq);
4609aebddd1SJeff Kirsher 		return compl;
4619aebddd1SJeff Kirsher 	}
4629aebddd1SJeff Kirsher 	return NULL;
4639aebddd1SJeff Kirsher }
4649aebddd1SJeff Kirsher 
4659aebddd1SJeff Kirsher void be_async_mcc_enable(struct be_adapter *adapter)
4669aebddd1SJeff Kirsher {
4679aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_cq_lock);
4689aebddd1SJeff Kirsher 
4699aebddd1SJeff Kirsher 	be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0);
4709aebddd1SJeff Kirsher 	adapter->mcc_obj.rearm_cq = true;
4719aebddd1SJeff Kirsher 
4729aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_cq_lock);
4739aebddd1SJeff Kirsher }
4749aebddd1SJeff Kirsher 
4759aebddd1SJeff Kirsher void be_async_mcc_disable(struct be_adapter *adapter)
4769aebddd1SJeff Kirsher {
477a323d9bfSSathya Perla 	spin_lock_bh(&adapter->mcc_cq_lock);
478a323d9bfSSathya Perla 
4799aebddd1SJeff Kirsher 	adapter->mcc_obj.rearm_cq = false;
480a323d9bfSSathya Perla 	be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
481a323d9bfSSathya Perla 
482a323d9bfSSathya Perla 	spin_unlock_bh(&adapter->mcc_cq_lock);
4839aebddd1SJeff Kirsher }
4849aebddd1SJeff Kirsher 
48510ef9ab4SSathya Perla int be_process_mcc(struct be_adapter *adapter)
4869aebddd1SJeff Kirsher {
4879aebddd1SJeff Kirsher 	struct be_mcc_compl *compl;
48810ef9ab4SSathya Perla 	int num = 0, status = 0;
4899aebddd1SJeff Kirsher 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
4909aebddd1SJeff Kirsher 
491072a9c48SAmerigo Wang 	spin_lock(&adapter->mcc_cq_lock);
4923acf19d9SSathya Perla 
4939aebddd1SJeff Kirsher 	while ((compl = be_mcc_compl_get(adapter))) {
4949aebddd1SJeff Kirsher 		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
4953acf19d9SSathya Perla 			be_mcc_event_process(adapter, compl);
4969aebddd1SJeff Kirsher 		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
49710ef9ab4SSathya Perla 			status = be_mcc_compl_process(adapter, compl);
4989aebddd1SJeff Kirsher 			atomic_dec(&mcc_obj->q.used);
4999aebddd1SJeff Kirsher 		}
5009aebddd1SJeff Kirsher 		be_mcc_compl_use(compl);
5019aebddd1SJeff Kirsher 		num++;
5029aebddd1SJeff Kirsher 	}
5039aebddd1SJeff Kirsher 
50410ef9ab4SSathya Perla 	if (num)
50510ef9ab4SSathya Perla 		be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
50610ef9ab4SSathya Perla 
507072a9c48SAmerigo Wang 	spin_unlock(&adapter->mcc_cq_lock);
50810ef9ab4SSathya Perla 	return status;
5099aebddd1SJeff Kirsher }
5109aebddd1SJeff Kirsher 
5119aebddd1SJeff Kirsher /* Wait till no more pending mcc requests are present */
5129aebddd1SJeff Kirsher static int be_mcc_wait_compl(struct be_adapter *adapter)
5139aebddd1SJeff Kirsher {
5149aebddd1SJeff Kirsher #define mcc_timeout		120000 /* 12s timeout */
51510ef9ab4SSathya Perla 	int i, status = 0;
5169aebddd1SJeff Kirsher 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
5179aebddd1SJeff Kirsher 
5186589ade0SSathya Perla 	for (i = 0; i < mcc_timeout; i++) {
519954f6825SVenkata Duvvuru 		if (be_check_error(adapter, BE_ERROR_ANY))
5209aebddd1SJeff Kirsher 			return -EIO;
5219aebddd1SJeff Kirsher 
522072a9c48SAmerigo Wang 		local_bh_disable();
52310ef9ab4SSathya Perla 		status = be_process_mcc(adapter);
524072a9c48SAmerigo Wang 		local_bh_enable();
5259aebddd1SJeff Kirsher 
5269aebddd1SJeff Kirsher 		if (atomic_read(&mcc_obj->q.used) == 0)
5279aebddd1SJeff Kirsher 			break;
5289aebddd1SJeff Kirsher 		udelay(100);
5299aebddd1SJeff Kirsher 	}
5309aebddd1SJeff Kirsher 	if (i == mcc_timeout) {
5316589ade0SSathya Perla 		dev_err(&adapter->pdev->dev, "FW not responding\n");
532954f6825SVenkata Duvvuru 		be_set_error(adapter, BE_ERROR_FW);
533652bf646SPadmanabh Ratnakar 		return -EIO;
5349aebddd1SJeff Kirsher 	}
5359aebddd1SJeff Kirsher 	return status;
5369aebddd1SJeff Kirsher }
5379aebddd1SJeff Kirsher 
5389aebddd1SJeff Kirsher /* Notify MCC requests and wait for completion */
5399aebddd1SJeff Kirsher static int be_mcc_notify_wait(struct be_adapter *adapter)
5409aebddd1SJeff Kirsher {
541652bf646SPadmanabh Ratnakar 	int status;
542652bf646SPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
543652bf646SPadmanabh Ratnakar 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
544652bf646SPadmanabh Ratnakar 	u16 index = mcc_obj->q.head;
545652bf646SPadmanabh Ratnakar 	struct be_cmd_resp_hdr *resp;
546652bf646SPadmanabh Ratnakar 
547652bf646SPadmanabh Ratnakar 	index_dec(&index, mcc_obj->q.len);
548652bf646SPadmanabh Ratnakar 	wrb = queue_index_node(&mcc_obj->q, index);
549652bf646SPadmanabh Ratnakar 
550652bf646SPadmanabh Ratnakar 	resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
551652bf646SPadmanabh Ratnakar 
552efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
553efaa408eSSuresh Reddy 	if (status)
554efaa408eSSuresh Reddy 		goto out;
555652bf646SPadmanabh Ratnakar 
556652bf646SPadmanabh Ratnakar 	status = be_mcc_wait_compl(adapter);
557652bf646SPadmanabh Ratnakar 	if (status == -EIO)
558652bf646SPadmanabh Ratnakar 		goto out;
559652bf646SPadmanabh Ratnakar 
5604c60005fSKalesh AP 	status = (resp->base_status |
5614c60005fSKalesh AP 		  ((resp->addl_status & CQE_ADDL_STATUS_MASK) <<
5624c60005fSKalesh AP 		   CQE_ADDL_STATUS_SHIFT));
563652bf646SPadmanabh Ratnakar out:
564652bf646SPadmanabh Ratnakar 	return status;
5659aebddd1SJeff Kirsher }
5669aebddd1SJeff Kirsher 
5679aebddd1SJeff Kirsher static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
5689aebddd1SJeff Kirsher {
5699aebddd1SJeff Kirsher 	int msecs = 0;
5709aebddd1SJeff Kirsher 	u32 ready;
5719aebddd1SJeff Kirsher 
5726589ade0SSathya Perla 	do {
573954f6825SVenkata Duvvuru 		if (be_check_error(adapter, BE_ERROR_ANY))
5749aebddd1SJeff Kirsher 			return -EIO;
5759aebddd1SJeff Kirsher 
5769aebddd1SJeff Kirsher 		ready = ioread32(db);
577434b3648SSathya Perla 		if (ready == 0xffffffff)
5789aebddd1SJeff Kirsher 			return -1;
5799aebddd1SJeff Kirsher 
5809aebddd1SJeff Kirsher 		ready &= MPU_MAILBOX_DB_RDY_MASK;
5819aebddd1SJeff Kirsher 		if (ready)
5829aebddd1SJeff Kirsher 			break;
5839aebddd1SJeff Kirsher 
5849aebddd1SJeff Kirsher 		if (msecs > 4000) {
5856589ade0SSathya Perla 			dev_err(&adapter->pdev->dev, "FW not responding\n");
586954f6825SVenkata Duvvuru 			be_set_error(adapter, BE_ERROR_FW);
587f67ef7baSPadmanabh Ratnakar 			be_detect_error(adapter);
5889aebddd1SJeff Kirsher 			return -1;
5899aebddd1SJeff Kirsher 		}
5909aebddd1SJeff Kirsher 
5919aebddd1SJeff Kirsher 		msleep(1);
5929aebddd1SJeff Kirsher 		msecs++;
5939aebddd1SJeff Kirsher 	} while (true);
5949aebddd1SJeff Kirsher 
5959aebddd1SJeff Kirsher 	return 0;
5969aebddd1SJeff Kirsher }
5979aebddd1SJeff Kirsher 
5989aebddd1SJeff Kirsher /*
5999aebddd1SJeff Kirsher  * Insert the mailbox address into the doorbell in two steps
6009aebddd1SJeff Kirsher  * Polls on the mbox doorbell till a command completion (or a timeout) occurs
6019aebddd1SJeff Kirsher  */
6029aebddd1SJeff Kirsher static int be_mbox_notify_wait(struct be_adapter *adapter)
6039aebddd1SJeff Kirsher {
6049aebddd1SJeff Kirsher 	int status;
6059aebddd1SJeff Kirsher 	u32 val = 0;
6069aebddd1SJeff Kirsher 	void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET;
6079aebddd1SJeff Kirsher 	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
6089aebddd1SJeff Kirsher 	struct be_mcc_mailbox *mbox = mbox_mem->va;
6099aebddd1SJeff Kirsher 	struct be_mcc_compl *compl = &mbox->compl;
6109aebddd1SJeff Kirsher 
6119aebddd1SJeff Kirsher 	/* wait for ready to be set */
6129aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
6139aebddd1SJeff Kirsher 	if (status != 0)
6149aebddd1SJeff Kirsher 		return status;
6159aebddd1SJeff Kirsher 
6169aebddd1SJeff Kirsher 	val |= MPU_MAILBOX_DB_HI_MASK;
6179aebddd1SJeff Kirsher 	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
6189aebddd1SJeff Kirsher 	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
6199aebddd1SJeff Kirsher 	iowrite32(val, db);
6209aebddd1SJeff Kirsher 
6219aebddd1SJeff Kirsher 	/* wait for ready to be set */
6229aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
6239aebddd1SJeff Kirsher 	if (status != 0)
6249aebddd1SJeff Kirsher 		return status;
6259aebddd1SJeff Kirsher 
6269aebddd1SJeff Kirsher 	val = 0;
6279aebddd1SJeff Kirsher 	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
6289aebddd1SJeff Kirsher 	val |= (u32)(mbox_mem->dma >> 4) << 2;
6299aebddd1SJeff Kirsher 	iowrite32(val, db);
6309aebddd1SJeff Kirsher 
6319aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
6329aebddd1SJeff Kirsher 	if (status != 0)
6339aebddd1SJeff Kirsher 		return status;
6349aebddd1SJeff Kirsher 
6359aebddd1SJeff Kirsher 	/* A cq entry has been made now */
6369aebddd1SJeff Kirsher 	if (be_mcc_compl_is_new(compl)) {
6379aebddd1SJeff Kirsher 		status = be_mcc_compl_process(adapter, &mbox->compl);
6389aebddd1SJeff Kirsher 		be_mcc_compl_use(compl);
6399aebddd1SJeff Kirsher 		if (status)
6409aebddd1SJeff Kirsher 			return status;
6419aebddd1SJeff Kirsher 	} else {
6429aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev, "invalid mailbox completion\n");
6439aebddd1SJeff Kirsher 		return -1;
6449aebddd1SJeff Kirsher 	}
6459aebddd1SJeff Kirsher 	return 0;
6469aebddd1SJeff Kirsher }
6479aebddd1SJeff Kirsher 
648c5b3ad4cSSathya Perla static u16 be_POST_stage_get(struct be_adapter *adapter)
6499aebddd1SJeff Kirsher {
6509aebddd1SJeff Kirsher 	u32 sem;
6519aebddd1SJeff Kirsher 
652c5b3ad4cSSathya Perla 	if (BEx_chip(adapter))
653c5b3ad4cSSathya Perla 		sem  = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx);
6549aebddd1SJeff Kirsher 	else
655c5b3ad4cSSathya Perla 		pci_read_config_dword(adapter->pdev,
656c5b3ad4cSSathya Perla 				      SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
657c5b3ad4cSSathya Perla 
658c5b3ad4cSSathya Perla 	return sem & POST_STAGE_MASK;
6599aebddd1SJeff Kirsher }
6609aebddd1SJeff Kirsher 
66187f20c26SGavin Shan static int lancer_wait_ready(struct be_adapter *adapter)
662bf99e50dSPadmanabh Ratnakar {
663bf99e50dSPadmanabh Ratnakar #define SLIPORT_READY_TIMEOUT 30
664bf99e50dSPadmanabh Ratnakar 	u32 sliport_status;
665e673244aSKalesh AP 	int i;
666bf99e50dSPadmanabh Ratnakar 
667bf99e50dSPadmanabh Ratnakar 	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
668bf99e50dSPadmanabh Ratnakar 		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
669bf99e50dSPadmanabh Ratnakar 		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
6709fa465c0SSathya Perla 			return 0;
6719fa465c0SSathya Perla 
6729fa465c0SSathya Perla 		if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
6739fa465c0SSathya Perla 		    !(sliport_status & SLIPORT_STATUS_RN_MASK))
6749fa465c0SSathya Perla 			return -EIO;
675bf99e50dSPadmanabh Ratnakar 
676bf99e50dSPadmanabh Ratnakar 		msleep(1000);
677bf99e50dSPadmanabh Ratnakar 	}
678bf99e50dSPadmanabh Ratnakar 
679e673244aSKalesh AP 	return sliport_status ? : -1;
680bf99e50dSPadmanabh Ratnakar }
681bf99e50dSPadmanabh Ratnakar 
682bf99e50dSPadmanabh Ratnakar int be_fw_wait_ready(struct be_adapter *adapter)
6839aebddd1SJeff Kirsher {
6849aebddd1SJeff Kirsher 	u16 stage;
6859aebddd1SJeff Kirsher 	int status, timeout = 0;
6869aebddd1SJeff Kirsher 	struct device *dev = &adapter->pdev->dev;
6879aebddd1SJeff Kirsher 
688bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter)) {
689bf99e50dSPadmanabh Ratnakar 		status = lancer_wait_ready(adapter);
690e673244aSKalesh AP 		if (status) {
691e673244aSKalesh AP 			stage = status;
692e673244aSKalesh AP 			goto err;
693e673244aSKalesh AP 		}
694e673244aSKalesh AP 		return 0;
695bf99e50dSPadmanabh Ratnakar 	}
696bf99e50dSPadmanabh Ratnakar 
6979aebddd1SJeff Kirsher 	do {
698ca3de6b2SSathya Perla 		/* There's no means to poll POST state on BE2/3 VFs */
699ca3de6b2SSathya Perla 		if (BEx_chip(adapter) && be_virtfn(adapter))
700ca3de6b2SSathya Perla 			return 0;
701ca3de6b2SSathya Perla 
702c5b3ad4cSSathya Perla 		stage = be_POST_stage_get(adapter);
70366d29cbcSGavin Shan 		if (stage == POST_STAGE_ARMFW_RDY)
70466d29cbcSGavin Shan 			return 0;
70566d29cbcSGavin Shan 
706a2cc4e0bSSathya Perla 		dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout);
7079aebddd1SJeff Kirsher 		if (msleep_interruptible(2000)) {
7089aebddd1SJeff Kirsher 			dev_err(dev, "Waiting for POST aborted\n");
7099aebddd1SJeff Kirsher 			return -EINTR;
7109aebddd1SJeff Kirsher 		}
7119aebddd1SJeff Kirsher 		timeout += 2;
7123ab81b5fSSomnath Kotur 	} while (timeout < 60);
7139aebddd1SJeff Kirsher 
714e673244aSKalesh AP err:
715e673244aSKalesh AP 	dev_err(dev, "POST timeout; stage=%#x\n", stage);
7169fa465c0SSathya Perla 	return -ETIMEDOUT;
7179aebddd1SJeff Kirsher }
7189aebddd1SJeff Kirsher 
7199aebddd1SJeff Kirsher static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
7209aebddd1SJeff Kirsher {
7219aebddd1SJeff Kirsher 	return &wrb->payload.sgl[0];
7229aebddd1SJeff Kirsher }
7239aebddd1SJeff Kirsher 
724a2cc4e0bSSathya Perla static inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr)
725bea50988SSathya Perla {
726bea50988SSathya Perla 	wrb->tag0 = addr & 0xFFFFFFFF;
727bea50988SSathya Perla 	wrb->tag1 = upper_32_bits(addr);
728bea50988SSathya Perla }
7299aebddd1SJeff Kirsher 
7309aebddd1SJeff Kirsher /* Don't touch the hdr after it's prepared */
731106df1e3SSomnath Kotur /* mem will be NULL for embedded commands */
732106df1e3SSomnath Kotur static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
733106df1e3SSomnath Kotur 				   u8 subsystem, u8 opcode, int cmd_len,
734a2cc4e0bSSathya Perla 				   struct be_mcc_wrb *wrb,
735a2cc4e0bSSathya Perla 				   struct be_dma_mem *mem)
7369aebddd1SJeff Kirsher {
737106df1e3SSomnath Kotur 	struct be_sge *sge;
738106df1e3SSomnath Kotur 
7399aebddd1SJeff Kirsher 	req_hdr->opcode = opcode;
7409aebddd1SJeff Kirsher 	req_hdr->subsystem = subsystem;
7419aebddd1SJeff Kirsher 	req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
7429aebddd1SJeff Kirsher 	req_hdr->version = 0;
743bea50988SSathya Perla 	fill_wrb_tags(wrb, (ulong) req_hdr);
744106df1e3SSomnath Kotur 	wrb->payload_length = cmd_len;
745106df1e3SSomnath Kotur 	if (mem) {
746106df1e3SSomnath Kotur 		wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
747106df1e3SSomnath Kotur 			MCC_WRB_SGE_CNT_SHIFT;
748106df1e3SSomnath Kotur 		sge = nonembedded_sgl(wrb);
749106df1e3SSomnath Kotur 		sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
750106df1e3SSomnath Kotur 		sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
751106df1e3SSomnath Kotur 		sge->len = cpu_to_le32(mem->size);
752106df1e3SSomnath Kotur 	} else
753106df1e3SSomnath Kotur 		wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
754106df1e3SSomnath Kotur 	be_dws_cpu_to_le(wrb, 8);
7559aebddd1SJeff Kirsher }
7569aebddd1SJeff Kirsher 
7579aebddd1SJeff Kirsher static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
7589aebddd1SJeff Kirsher 				      struct be_dma_mem *mem)
7599aebddd1SJeff Kirsher {
7609aebddd1SJeff Kirsher 	int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
7619aebddd1SJeff Kirsher 	u64 dma = (u64)mem->dma;
7629aebddd1SJeff Kirsher 
7639aebddd1SJeff Kirsher 	for (i = 0; i < buf_pages; i++) {
7649aebddd1SJeff Kirsher 		pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
7659aebddd1SJeff Kirsher 		pages[i].hi = cpu_to_le32(upper_32_bits(dma));
7669aebddd1SJeff Kirsher 		dma += PAGE_SIZE_4K;
7679aebddd1SJeff Kirsher 	}
7689aebddd1SJeff Kirsher }
7699aebddd1SJeff Kirsher 
7709aebddd1SJeff Kirsher static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter)
7719aebddd1SJeff Kirsher {
7729aebddd1SJeff Kirsher 	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
7739aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb
7749aebddd1SJeff Kirsher 		= &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
7759aebddd1SJeff Kirsher 	memset(wrb, 0, sizeof(*wrb));
7769aebddd1SJeff Kirsher 	return wrb;
7779aebddd1SJeff Kirsher }
7789aebddd1SJeff Kirsher 
7799aebddd1SJeff Kirsher static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
7809aebddd1SJeff Kirsher {
7819aebddd1SJeff Kirsher 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
7829aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
7839aebddd1SJeff Kirsher 
784aa790db9SPadmanabh Ratnakar 	if (!mccq->created)
785aa790db9SPadmanabh Ratnakar 		return NULL;
786aa790db9SPadmanabh Ratnakar 
7874d277125SVasundhara Volam 	if (atomic_read(&mccq->used) >= mccq->len)
7889aebddd1SJeff Kirsher 		return NULL;
7899aebddd1SJeff Kirsher 
7909aebddd1SJeff Kirsher 	wrb = queue_head_node(mccq);
7919aebddd1SJeff Kirsher 	queue_head_inc(mccq);
7929aebddd1SJeff Kirsher 	atomic_inc(&mccq->used);
7939aebddd1SJeff Kirsher 	memset(wrb, 0, sizeof(*wrb));
7949aebddd1SJeff Kirsher 	return wrb;
7959aebddd1SJeff Kirsher }
7969aebddd1SJeff Kirsher 
797bea50988SSathya Perla static bool use_mcc(struct be_adapter *adapter)
798bea50988SSathya Perla {
799bea50988SSathya Perla 	return adapter->mcc_obj.q.created;
800bea50988SSathya Perla }
801bea50988SSathya Perla 
802bea50988SSathya Perla /* Must be used only in process context */
803bea50988SSathya Perla static int be_cmd_lock(struct be_adapter *adapter)
804bea50988SSathya Perla {
805bea50988SSathya Perla 	if (use_mcc(adapter)) {
806bea50988SSathya Perla 		spin_lock_bh(&adapter->mcc_lock);
807bea50988SSathya Perla 		return 0;
808bea50988SSathya Perla 	} else {
809bea50988SSathya Perla 		return mutex_lock_interruptible(&adapter->mbox_lock);
810bea50988SSathya Perla 	}
811bea50988SSathya Perla }
812bea50988SSathya Perla 
813bea50988SSathya Perla /* Must be used only in process context */
814bea50988SSathya Perla static void be_cmd_unlock(struct be_adapter *adapter)
815bea50988SSathya Perla {
816bea50988SSathya Perla 	if (use_mcc(adapter))
817bea50988SSathya Perla 		spin_unlock_bh(&adapter->mcc_lock);
818bea50988SSathya Perla 	else
819bea50988SSathya Perla 		return mutex_unlock(&adapter->mbox_lock);
820bea50988SSathya Perla }
821bea50988SSathya Perla 
822bea50988SSathya Perla static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter,
823bea50988SSathya Perla 				      struct be_mcc_wrb *wrb)
824bea50988SSathya Perla {
825bea50988SSathya Perla 	struct be_mcc_wrb *dest_wrb;
826bea50988SSathya Perla 
827bea50988SSathya Perla 	if (use_mcc(adapter)) {
828bea50988SSathya Perla 		dest_wrb = wrb_from_mccq(adapter);
829bea50988SSathya Perla 		if (!dest_wrb)
830bea50988SSathya Perla 			return NULL;
831bea50988SSathya Perla 	} else {
832bea50988SSathya Perla 		dest_wrb = wrb_from_mbox(adapter);
833bea50988SSathya Perla 	}
834bea50988SSathya Perla 
835bea50988SSathya Perla 	memcpy(dest_wrb, wrb, sizeof(*wrb));
836bea50988SSathya Perla 	if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK))
837bea50988SSathya Perla 		fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb));
838bea50988SSathya Perla 
839bea50988SSathya Perla 	return dest_wrb;
840bea50988SSathya Perla }
841bea50988SSathya Perla 
842bea50988SSathya Perla /* Must be used only in process context */
843bea50988SSathya Perla static int be_cmd_notify_wait(struct be_adapter *adapter,
844bea50988SSathya Perla 			      struct be_mcc_wrb *wrb)
845bea50988SSathya Perla {
846bea50988SSathya Perla 	struct be_mcc_wrb *dest_wrb;
847bea50988SSathya Perla 	int status;
848bea50988SSathya Perla 
849bea50988SSathya Perla 	status = be_cmd_lock(adapter);
850bea50988SSathya Perla 	if (status)
851bea50988SSathya Perla 		return status;
852bea50988SSathya Perla 
853bea50988SSathya Perla 	dest_wrb = be_cmd_copy(adapter, wrb);
8540c884567SSuresh Reddy 	if (!dest_wrb) {
8550c884567SSuresh Reddy 		status = -EBUSY;
8560c884567SSuresh Reddy 		goto unlock;
8570c884567SSuresh Reddy 	}
858bea50988SSathya Perla 
859bea50988SSathya Perla 	if (use_mcc(adapter))
860bea50988SSathya Perla 		status = be_mcc_notify_wait(adapter);
861bea50988SSathya Perla 	else
862bea50988SSathya Perla 		status = be_mbox_notify_wait(adapter);
863bea50988SSathya Perla 
864bea50988SSathya Perla 	if (!status)
865bea50988SSathya Perla 		memcpy(wrb, dest_wrb, sizeof(*wrb));
866bea50988SSathya Perla 
8670c884567SSuresh Reddy unlock:
868bea50988SSathya Perla 	be_cmd_unlock(adapter);
869bea50988SSathya Perla 	return status;
870bea50988SSathya Perla }
871bea50988SSathya Perla 
8729aebddd1SJeff Kirsher /* Tell fw we're about to start firing cmds by writing a
8739aebddd1SJeff Kirsher  * special pattern across the wrb hdr; uses mbox
8749aebddd1SJeff Kirsher  */
8759aebddd1SJeff Kirsher int be_cmd_fw_init(struct be_adapter *adapter)
8769aebddd1SJeff Kirsher {
8779aebddd1SJeff Kirsher 	u8 *wrb;
8789aebddd1SJeff Kirsher 	int status;
8799aebddd1SJeff Kirsher 
880bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter))
881bf99e50dSPadmanabh Ratnakar 		return 0;
882bf99e50dSPadmanabh Ratnakar 
8839aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
8849aebddd1SJeff Kirsher 		return -1;
8859aebddd1SJeff Kirsher 
8869aebddd1SJeff Kirsher 	wrb = (u8 *)wrb_from_mbox(adapter);
8879aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8889aebddd1SJeff Kirsher 	*wrb++ = 0x12;
8899aebddd1SJeff Kirsher 	*wrb++ = 0x34;
8909aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8919aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8929aebddd1SJeff Kirsher 	*wrb++ = 0x56;
8939aebddd1SJeff Kirsher 	*wrb++ = 0x78;
8949aebddd1SJeff Kirsher 	*wrb = 0xFF;
8959aebddd1SJeff Kirsher 
8969aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
8979aebddd1SJeff Kirsher 
8989aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
8999aebddd1SJeff Kirsher 	return status;
9009aebddd1SJeff Kirsher }
9019aebddd1SJeff Kirsher 
9029aebddd1SJeff Kirsher /* Tell fw we're done with firing cmds by writing a
9039aebddd1SJeff Kirsher  * special pattern across the wrb hdr; uses mbox
9049aebddd1SJeff Kirsher  */
9059aebddd1SJeff Kirsher int be_cmd_fw_clean(struct be_adapter *adapter)
9069aebddd1SJeff Kirsher {
9079aebddd1SJeff Kirsher 	u8 *wrb;
9089aebddd1SJeff Kirsher 	int status;
9099aebddd1SJeff Kirsher 
910bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter))
911bf99e50dSPadmanabh Ratnakar 		return 0;
912bf99e50dSPadmanabh Ratnakar 
9139aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
9149aebddd1SJeff Kirsher 		return -1;
9159aebddd1SJeff Kirsher 
9169aebddd1SJeff Kirsher 	wrb = (u8 *)wrb_from_mbox(adapter);
9179aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
9189aebddd1SJeff Kirsher 	*wrb++ = 0xAA;
9199aebddd1SJeff Kirsher 	*wrb++ = 0xBB;
9209aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
9219aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
9229aebddd1SJeff Kirsher 	*wrb++ = 0xCC;
9239aebddd1SJeff Kirsher 	*wrb++ = 0xDD;
9249aebddd1SJeff Kirsher 	*wrb = 0xFF;
9259aebddd1SJeff Kirsher 
9269aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
9279aebddd1SJeff Kirsher 
9289aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
9299aebddd1SJeff Kirsher 	return status;
9309aebddd1SJeff Kirsher }
931bf99e50dSPadmanabh Ratnakar 
932f2f781a7SSathya Perla int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo)
9339aebddd1SJeff Kirsher {
9349aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9359aebddd1SJeff Kirsher 	struct be_cmd_req_eq_create *req;
936f2f781a7SSathya Perla 	struct be_dma_mem *q_mem = &eqo->q.dma_mem;
937f2f781a7SSathya Perla 	int status, ver = 0;
9389aebddd1SJeff Kirsher 
9399aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
9409aebddd1SJeff Kirsher 		return -1;
9419aebddd1SJeff Kirsher 
9429aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
9439aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
9449aebddd1SJeff Kirsher 
945106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
946a2cc4e0bSSathya Perla 			       OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb,
947a2cc4e0bSSathya Perla 			       NULL);
9489aebddd1SJeff Kirsher 
949f2f781a7SSathya Perla 	/* Support for EQ_CREATEv2 available only SH-R onwards */
950f2f781a7SSathya Perla 	if (!(BEx_chip(adapter) || lancer_chip(adapter)))
951f2f781a7SSathya Perla 		ver = 2;
952f2f781a7SSathya Perla 
953f2f781a7SSathya Perla 	req->hdr.version = ver;
9549aebddd1SJeff Kirsher 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
9559aebddd1SJeff Kirsher 
9569aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
9579aebddd1SJeff Kirsher 	/* 4byte eqe*/
9589aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
9599aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, count, req->context,
960f2f781a7SSathya Perla 		      __ilog2_u32(eqo->q.len / 256));
9619aebddd1SJeff Kirsher 	be_dws_cpu_to_le(req->context, sizeof(req->context));
9629aebddd1SJeff Kirsher 
9639aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
9649aebddd1SJeff Kirsher 
9659aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
9669aebddd1SJeff Kirsher 	if (!status) {
9679aebddd1SJeff Kirsher 		struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
96803d28ffeSKalesh AP 
969f2f781a7SSathya Perla 		eqo->q.id = le16_to_cpu(resp->eq_id);
970f2f781a7SSathya Perla 		eqo->msix_idx =
971f2f781a7SSathya Perla 			(ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx;
972f2f781a7SSathya Perla 		eqo->q.created = true;
9739aebddd1SJeff Kirsher 	}
9749aebddd1SJeff Kirsher 
9759aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
9769aebddd1SJeff Kirsher 	return status;
9779aebddd1SJeff Kirsher }
9789aebddd1SJeff Kirsher 
979f9449ab7SSathya Perla /* Use MCC */
9809aebddd1SJeff Kirsher int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
9815ee4979bSSathya Perla 			  bool permanent, u32 if_handle, u32 pmac_id)
9829aebddd1SJeff Kirsher {
9839aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9849aebddd1SJeff Kirsher 	struct be_cmd_req_mac_query *req;
9859aebddd1SJeff Kirsher 	int status;
9869aebddd1SJeff Kirsher 
987f9449ab7SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
9889aebddd1SJeff Kirsher 
989f9449ab7SSathya Perla 	wrb = wrb_from_mccq(adapter);
990f9449ab7SSathya Perla 	if (!wrb) {
991f9449ab7SSathya Perla 		status = -EBUSY;
992f9449ab7SSathya Perla 		goto err;
993f9449ab7SSathya Perla 	}
9949aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
9959aebddd1SJeff Kirsher 
996106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
997a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb,
998a2cc4e0bSSathya Perla 			       NULL);
9995ee4979bSSathya Perla 	req->type = MAC_ADDRESS_TYPE_NETWORK;
10009aebddd1SJeff Kirsher 	if (permanent) {
10019aebddd1SJeff Kirsher 		req->permanent = 1;
10029aebddd1SJeff Kirsher 	} else {
10039aebddd1SJeff Kirsher 		req->if_id = cpu_to_le16((u16)if_handle);
1004590c391dSPadmanabh Ratnakar 		req->pmac_id = cpu_to_le32(pmac_id);
10059aebddd1SJeff Kirsher 		req->permanent = 0;
10069aebddd1SJeff Kirsher 	}
10079aebddd1SJeff Kirsher 
1008f9449ab7SSathya Perla 	status = be_mcc_notify_wait(adapter);
10099aebddd1SJeff Kirsher 	if (!status) {
10109aebddd1SJeff Kirsher 		struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
101103d28ffeSKalesh AP 
10129aebddd1SJeff Kirsher 		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
10139aebddd1SJeff Kirsher 	}
10149aebddd1SJeff Kirsher 
1015f9449ab7SSathya Perla err:
1016f9449ab7SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
10179aebddd1SJeff Kirsher 	return status;
10189aebddd1SJeff Kirsher }
10199aebddd1SJeff Kirsher 
10209aebddd1SJeff Kirsher /* Uses synchronous MCCQ */
10219aebddd1SJeff Kirsher int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
10229aebddd1SJeff Kirsher 		    u32 if_id, u32 *pmac_id, u32 domain)
10239aebddd1SJeff Kirsher {
10249aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
10259aebddd1SJeff Kirsher 	struct be_cmd_req_pmac_add *req;
10269aebddd1SJeff Kirsher 	int status;
10279aebddd1SJeff Kirsher 
10289aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
10299aebddd1SJeff Kirsher 
10309aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
10319aebddd1SJeff Kirsher 	if (!wrb) {
10329aebddd1SJeff Kirsher 		status = -EBUSY;
10339aebddd1SJeff Kirsher 		goto err;
10349aebddd1SJeff Kirsher 	}
10359aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10369aebddd1SJeff Kirsher 
1037106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1038a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb,
1039a2cc4e0bSSathya Perla 			       NULL);
10409aebddd1SJeff Kirsher 
10419aebddd1SJeff Kirsher 	req->hdr.domain = domain;
10429aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(if_id);
10439aebddd1SJeff Kirsher 	memcpy(req->mac_address, mac_addr, ETH_ALEN);
10449aebddd1SJeff Kirsher 
10459aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
10469aebddd1SJeff Kirsher 	if (!status) {
10479aebddd1SJeff Kirsher 		struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
104803d28ffeSKalesh AP 
10499aebddd1SJeff Kirsher 		*pmac_id = le32_to_cpu(resp->pmac_id);
10509aebddd1SJeff Kirsher 	}
10519aebddd1SJeff Kirsher 
10529aebddd1SJeff Kirsher err:
10539aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1054e3a7ae2cSSomnath Kotur 
1055e3a7ae2cSSomnath Kotur 	 if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
1056e3a7ae2cSSomnath Kotur 		status = -EPERM;
1057e3a7ae2cSSomnath Kotur 
10589aebddd1SJeff Kirsher 	return status;
10599aebddd1SJeff Kirsher }
10609aebddd1SJeff Kirsher 
10619aebddd1SJeff Kirsher /* Uses synchronous MCCQ */
106230128031SSathya Perla int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom)
10639aebddd1SJeff Kirsher {
10649aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
10659aebddd1SJeff Kirsher 	struct be_cmd_req_pmac_del *req;
10669aebddd1SJeff Kirsher 	int status;
10679aebddd1SJeff Kirsher 
106830128031SSathya Perla 	if (pmac_id == -1)
106930128031SSathya Perla 		return 0;
107030128031SSathya Perla 
10719aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
10729aebddd1SJeff Kirsher 
10739aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
10749aebddd1SJeff Kirsher 	if (!wrb) {
10759aebddd1SJeff Kirsher 		status = -EBUSY;
10769aebddd1SJeff Kirsher 		goto err;
10779aebddd1SJeff Kirsher 	}
10789aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10799aebddd1SJeff Kirsher 
1080106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1081cd3307aaSKalesh AP 			       OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req),
1082cd3307aaSKalesh AP 			       wrb, NULL);
10839aebddd1SJeff Kirsher 
10849aebddd1SJeff Kirsher 	req->hdr.domain = dom;
10859aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(if_id);
10869aebddd1SJeff Kirsher 	req->pmac_id = cpu_to_le32(pmac_id);
10879aebddd1SJeff Kirsher 
10889aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
10899aebddd1SJeff Kirsher 
10909aebddd1SJeff Kirsher err:
10919aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
10929aebddd1SJeff Kirsher 	return status;
10939aebddd1SJeff Kirsher }
10949aebddd1SJeff Kirsher 
10959aebddd1SJeff Kirsher /* Uses Mbox */
109610ef9ab4SSathya Perla int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
109710ef9ab4SSathya Perla 		     struct be_queue_info *eq, bool no_delay, int coalesce_wm)
10989aebddd1SJeff Kirsher {
10999aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
11009aebddd1SJeff Kirsher 	struct be_cmd_req_cq_create *req;
11019aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &cq->dma_mem;
11029aebddd1SJeff Kirsher 	void *ctxt;
11039aebddd1SJeff Kirsher 	int status;
11049aebddd1SJeff Kirsher 
11059aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
11069aebddd1SJeff Kirsher 		return -1;
11079aebddd1SJeff Kirsher 
11089aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
11099aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
11109aebddd1SJeff Kirsher 	ctxt = &req->context;
11119aebddd1SJeff Kirsher 
1112106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1113a2cc4e0bSSathya Perla 			       OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb,
1114a2cc4e0bSSathya Perla 			       NULL);
11159aebddd1SJeff Kirsher 
11169aebddd1SJeff Kirsher 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
1117bbdc42f8SAjit Khaparde 
1118bbdc42f8SAjit Khaparde 	if (BEx_chip(adapter)) {
11199aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
11209aebddd1SJeff Kirsher 			      coalesce_wm);
11219aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, nodelay,
11229aebddd1SJeff Kirsher 			      ctxt, no_delay);
11239aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
11249aebddd1SJeff Kirsher 			      __ilog2_u32(cq->len / 256));
11259aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
11269aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
11279aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
1128bbdc42f8SAjit Khaparde 	} else {
1129bbdc42f8SAjit Khaparde 		req->hdr.version = 2;
1130bbdc42f8SAjit Khaparde 		req->page_size = 1; /* 1 for 4K */
113109e83a9dSAjit Khaparde 
113209e83a9dSAjit Khaparde 		/* coalesce-wm field in this cmd is not relevant to Lancer.
113309e83a9dSAjit Khaparde 		 * Lancer uses COMMON_MODIFY_CQ to set this field
113409e83a9dSAjit Khaparde 		 */
113509e83a9dSAjit Khaparde 		if (!lancer_chip(adapter))
113609e83a9dSAjit Khaparde 			AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
113709e83a9dSAjit Khaparde 				      ctxt, coalesce_wm);
1138bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt,
1139bbdc42f8SAjit Khaparde 			      no_delay);
1140bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
1141bbdc42f8SAjit Khaparde 			      __ilog2_u32(cq->len / 256));
1142bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
1143a2cc4e0bSSathya Perla 		AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
1144a2cc4e0bSSathya Perla 		AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
11459aebddd1SJeff Kirsher 	}
11469aebddd1SJeff Kirsher 
11479aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
11489aebddd1SJeff Kirsher 
11499aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
11509aebddd1SJeff Kirsher 
11519aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
11529aebddd1SJeff Kirsher 	if (!status) {
11539aebddd1SJeff Kirsher 		struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
115403d28ffeSKalesh AP 
11559aebddd1SJeff Kirsher 		cq->id = le16_to_cpu(resp->cq_id);
11569aebddd1SJeff Kirsher 		cq->created = true;
11579aebddd1SJeff Kirsher 	}
11589aebddd1SJeff Kirsher 
11599aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
11609aebddd1SJeff Kirsher 
11619aebddd1SJeff Kirsher 	return status;
11629aebddd1SJeff Kirsher }
11639aebddd1SJeff Kirsher 
11649aebddd1SJeff Kirsher static u32 be_encoded_q_len(int q_len)
11659aebddd1SJeff Kirsher {
11669aebddd1SJeff Kirsher 	u32 len_encoded = fls(q_len); /* log2(len) + 1 */
116703d28ffeSKalesh AP 
11689aebddd1SJeff Kirsher 	if (len_encoded == 16)
11699aebddd1SJeff Kirsher 		len_encoded = 0;
11709aebddd1SJeff Kirsher 	return len_encoded;
11719aebddd1SJeff Kirsher }
11729aebddd1SJeff Kirsher 
11734188e7dfSJingoo Han static int be_cmd_mccq_ext_create(struct be_adapter *adapter,
11749aebddd1SJeff Kirsher 				  struct be_queue_info *mccq,
11759aebddd1SJeff Kirsher 				  struct be_queue_info *cq)
11769aebddd1SJeff Kirsher {
11779aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
11789aebddd1SJeff Kirsher 	struct be_cmd_req_mcc_ext_create *req;
11799aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &mccq->dma_mem;
11809aebddd1SJeff Kirsher 	void *ctxt;
11819aebddd1SJeff Kirsher 	int status;
11829aebddd1SJeff Kirsher 
11839aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
11849aebddd1SJeff Kirsher 		return -1;
11859aebddd1SJeff Kirsher 
11869aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
11879aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
11889aebddd1SJeff Kirsher 	ctxt = &req->context;
11899aebddd1SJeff Kirsher 
1190106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1191a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb,
1192a2cc4e0bSSathya Perla 			       NULL);
11939aebddd1SJeff Kirsher 
11949aebddd1SJeff Kirsher 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
1195666d39c7SVasundhara Volam 	if (BEx_chip(adapter)) {
11969aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
11979aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
11989aebddd1SJeff Kirsher 			      be_encoded_q_len(mccq->len));
11999aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
1200666d39c7SVasundhara Volam 	} else {
1201666d39c7SVasundhara Volam 		req->hdr.version = 1;
1202666d39c7SVasundhara Volam 		req->cq_id = cpu_to_le16(cq->id);
1203666d39c7SVasundhara Volam 
1204666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt,
1205666d39c7SVasundhara Volam 			      be_encoded_q_len(mccq->len));
1206666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1);
1207666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id,
1208666d39c7SVasundhara Volam 			      ctxt, cq->id);
1209666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid,
1210666d39c7SVasundhara Volam 			      ctxt, 1);
12119aebddd1SJeff Kirsher 	}
12129aebddd1SJeff Kirsher 
121321252377SVasundhara Volam 	/* Subscribe to Link State, Sliport Event and Group 5 Events
121421252377SVasundhara Volam 	 * (bits 1, 5 and 17 set)
121521252377SVasundhara Volam 	 */
121621252377SVasundhara Volam 	req->async_event_bitmap[0] =
121721252377SVasundhara Volam 			cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) |
121821252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_GRP_5) |
121921252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_QNQ) |
122021252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_SLIPORT));
122121252377SVasundhara Volam 
12229aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
12239aebddd1SJeff Kirsher 
12249aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
12259aebddd1SJeff Kirsher 
12269aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
12279aebddd1SJeff Kirsher 	if (!status) {
12289aebddd1SJeff Kirsher 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
122903d28ffeSKalesh AP 
12309aebddd1SJeff Kirsher 		mccq->id = le16_to_cpu(resp->id);
12319aebddd1SJeff Kirsher 		mccq->created = true;
12329aebddd1SJeff Kirsher 	}
12339aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
12349aebddd1SJeff Kirsher 
12359aebddd1SJeff Kirsher 	return status;
12369aebddd1SJeff Kirsher }
12379aebddd1SJeff Kirsher 
12384188e7dfSJingoo Han static int be_cmd_mccq_org_create(struct be_adapter *adapter,
12399aebddd1SJeff Kirsher 				  struct be_queue_info *mccq,
12409aebddd1SJeff Kirsher 				  struct be_queue_info *cq)
12419aebddd1SJeff Kirsher {
12429aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
12439aebddd1SJeff Kirsher 	struct be_cmd_req_mcc_create *req;
12449aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &mccq->dma_mem;
12459aebddd1SJeff Kirsher 	void *ctxt;
12469aebddd1SJeff Kirsher 	int status;
12479aebddd1SJeff Kirsher 
12489aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
12499aebddd1SJeff Kirsher 		return -1;
12509aebddd1SJeff Kirsher 
12519aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
12529aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
12539aebddd1SJeff Kirsher 	ctxt = &req->context;
12549aebddd1SJeff Kirsher 
1255106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1256a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb,
1257a2cc4e0bSSathya Perla 			       NULL);
12589aebddd1SJeff Kirsher 
12599aebddd1SJeff Kirsher 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
12609aebddd1SJeff Kirsher 
12619aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
12629aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
12639aebddd1SJeff Kirsher 		      be_encoded_q_len(mccq->len));
12649aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
12659aebddd1SJeff Kirsher 
12669aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
12679aebddd1SJeff Kirsher 
12689aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
12699aebddd1SJeff Kirsher 
12709aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
12719aebddd1SJeff Kirsher 	if (!status) {
12729aebddd1SJeff Kirsher 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
127303d28ffeSKalesh AP 
12749aebddd1SJeff Kirsher 		mccq->id = le16_to_cpu(resp->id);
12759aebddd1SJeff Kirsher 		mccq->created = true;
12769aebddd1SJeff Kirsher 	}
12779aebddd1SJeff Kirsher 
12789aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
12799aebddd1SJeff Kirsher 	return status;
12809aebddd1SJeff Kirsher }
12819aebddd1SJeff Kirsher 
12829aebddd1SJeff Kirsher int be_cmd_mccq_create(struct be_adapter *adapter,
1283a2cc4e0bSSathya Perla 		       struct be_queue_info *mccq, struct be_queue_info *cq)
12849aebddd1SJeff Kirsher {
12859aebddd1SJeff Kirsher 	int status;
12869aebddd1SJeff Kirsher 
12879aebddd1SJeff Kirsher 	status = be_cmd_mccq_ext_create(adapter, mccq, cq);
1288666d39c7SVasundhara Volam 	if (status && BEx_chip(adapter)) {
12899aebddd1SJeff Kirsher 		dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
12909aebddd1SJeff Kirsher 			"or newer to avoid conflicting priorities between NIC "
12919aebddd1SJeff Kirsher 			"and FCoE traffic");
12929aebddd1SJeff Kirsher 		status = be_cmd_mccq_org_create(adapter, mccq, cq);
12939aebddd1SJeff Kirsher 	}
12949aebddd1SJeff Kirsher 	return status;
12959aebddd1SJeff Kirsher }
12969aebddd1SJeff Kirsher 
129794d73aaaSVasundhara Volam int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo)
12989aebddd1SJeff Kirsher {
12997707133cSSathya Perla 	struct be_mcc_wrb wrb = {0};
13009aebddd1SJeff Kirsher 	struct be_cmd_req_eth_tx_create *req;
130194d73aaaSVasundhara Volam 	struct be_queue_info *txq = &txo->q;
130294d73aaaSVasundhara Volam 	struct be_queue_info *cq = &txo->cq;
13039aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &txq->dma_mem;
130494d73aaaSVasundhara Volam 	int status, ver = 0;
13059aebddd1SJeff Kirsher 
13067707133cSSathya Perla 	req = embedded_payload(&wrb);
1307106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
13087707133cSSathya Perla 			       OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL);
13099aebddd1SJeff Kirsher 
13109aebddd1SJeff Kirsher 	if (lancer_chip(adapter)) {
13119aebddd1SJeff Kirsher 		req->hdr.version = 1;
131294d73aaaSVasundhara Volam 	} else if (BEx_chip(adapter)) {
131394d73aaaSVasundhara Volam 		if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC)
131494d73aaaSVasundhara Volam 			req->hdr.version = 2;
131594d73aaaSVasundhara Volam 	} else { /* For SH */
131694d73aaaSVasundhara Volam 		req->hdr.version = 2;
13179aebddd1SJeff Kirsher 	}
13189aebddd1SJeff Kirsher 
131981b02655SVasundhara Volam 	if (req->hdr.version > 0)
132081b02655SVasundhara Volam 		req->if_id = cpu_to_le16(adapter->if_handle);
13219aebddd1SJeff Kirsher 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
13229aebddd1SJeff Kirsher 	req->ulp_num = BE_ULP1_NUM;
13239aebddd1SJeff Kirsher 	req->type = BE_ETH_TX_RING_TYPE_STANDARD;
132494d73aaaSVasundhara Volam 	req->cq_id = cpu_to_le16(cq->id);
132594d73aaaSVasundhara Volam 	req->queue_size = be_encoded_q_len(txq->len);
13269aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
132794d73aaaSVasundhara Volam 	ver = req->hdr.version;
132894d73aaaSVasundhara Volam 
13297707133cSSathya Perla 	status = be_cmd_notify_wait(adapter, &wrb);
13309aebddd1SJeff Kirsher 	if (!status) {
13317707133cSSathya Perla 		struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb);
133203d28ffeSKalesh AP 
13339aebddd1SJeff Kirsher 		txq->id = le16_to_cpu(resp->cid);
133494d73aaaSVasundhara Volam 		if (ver == 2)
133594d73aaaSVasundhara Volam 			txo->db_offset = le32_to_cpu(resp->db_offset);
133694d73aaaSVasundhara Volam 		else
133794d73aaaSVasundhara Volam 			txo->db_offset = DB_TXULP1_OFFSET;
13389aebddd1SJeff Kirsher 		txq->created = true;
13399aebddd1SJeff Kirsher 	}
13409aebddd1SJeff Kirsher 
13419aebddd1SJeff Kirsher 	return status;
13429aebddd1SJeff Kirsher }
13439aebddd1SJeff Kirsher 
13449aebddd1SJeff Kirsher /* Uses MCC */
13459aebddd1SJeff Kirsher int be_cmd_rxq_create(struct be_adapter *adapter,
13469aebddd1SJeff Kirsher 		      struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
134710ef9ab4SSathya Perla 		      u32 if_id, u32 rss, u8 *rss_id)
13489aebddd1SJeff Kirsher {
13499aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
13509aebddd1SJeff Kirsher 	struct be_cmd_req_eth_rx_create *req;
13519aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &rxq->dma_mem;
13529aebddd1SJeff Kirsher 	int status;
13539aebddd1SJeff Kirsher 
13549aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
13559aebddd1SJeff Kirsher 
13569aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
13579aebddd1SJeff Kirsher 	if (!wrb) {
13589aebddd1SJeff Kirsher 		status = -EBUSY;
13599aebddd1SJeff Kirsher 		goto err;
13609aebddd1SJeff Kirsher 	}
13619aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
13629aebddd1SJeff Kirsher 
1363106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1364106df1e3SSomnath Kotur 			       OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL);
13659aebddd1SJeff Kirsher 
13669aebddd1SJeff Kirsher 	req->cq_id = cpu_to_le16(cq_id);
13679aebddd1SJeff Kirsher 	req->frag_size = fls(frag_size) - 1;
13689aebddd1SJeff Kirsher 	req->num_pages = 2;
13699aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
13709aebddd1SJeff Kirsher 	req->interface_id = cpu_to_le32(if_id);
137110ef9ab4SSathya Perla 	req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE);
13729aebddd1SJeff Kirsher 	req->rss_queue = cpu_to_le32(rss);
13739aebddd1SJeff Kirsher 
13749aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
13759aebddd1SJeff Kirsher 	if (!status) {
13769aebddd1SJeff Kirsher 		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
137703d28ffeSKalesh AP 
13789aebddd1SJeff Kirsher 		rxq->id = le16_to_cpu(resp->id);
13799aebddd1SJeff Kirsher 		rxq->created = true;
13809aebddd1SJeff Kirsher 		*rss_id = resp->rss_id;
13819aebddd1SJeff Kirsher 	}
13829aebddd1SJeff Kirsher 
13839aebddd1SJeff Kirsher err:
13849aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
13859aebddd1SJeff Kirsher 	return status;
13869aebddd1SJeff Kirsher }
13879aebddd1SJeff Kirsher 
13889aebddd1SJeff Kirsher /* Generic destroyer function for all types of queues
13899aebddd1SJeff Kirsher  * Uses Mbox
13909aebddd1SJeff Kirsher  */
13919aebddd1SJeff Kirsher int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
13929aebddd1SJeff Kirsher 		     int queue_type)
13939aebddd1SJeff Kirsher {
13949aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
13959aebddd1SJeff Kirsher 	struct be_cmd_req_q_destroy *req;
13969aebddd1SJeff Kirsher 	u8 subsys = 0, opcode = 0;
13979aebddd1SJeff Kirsher 	int status;
13989aebddd1SJeff Kirsher 
13999aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
14009aebddd1SJeff Kirsher 		return -1;
14019aebddd1SJeff Kirsher 
14029aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
14039aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
14049aebddd1SJeff Kirsher 
14059aebddd1SJeff Kirsher 	switch (queue_type) {
14069aebddd1SJeff Kirsher 	case QTYPE_EQ:
14079aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
14089aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_EQ_DESTROY;
14099aebddd1SJeff Kirsher 		break;
14109aebddd1SJeff Kirsher 	case QTYPE_CQ:
14119aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
14129aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_CQ_DESTROY;
14139aebddd1SJeff Kirsher 		break;
14149aebddd1SJeff Kirsher 	case QTYPE_TXQ:
14159aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_ETH;
14169aebddd1SJeff Kirsher 		opcode = OPCODE_ETH_TX_DESTROY;
14179aebddd1SJeff Kirsher 		break;
14189aebddd1SJeff Kirsher 	case QTYPE_RXQ:
14199aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_ETH;
14209aebddd1SJeff Kirsher 		opcode = OPCODE_ETH_RX_DESTROY;
14219aebddd1SJeff Kirsher 		break;
14229aebddd1SJeff Kirsher 	case QTYPE_MCCQ:
14239aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
14249aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_MCC_DESTROY;
14259aebddd1SJeff Kirsher 		break;
14269aebddd1SJeff Kirsher 	default:
14279aebddd1SJeff Kirsher 		BUG();
14289aebddd1SJeff Kirsher 	}
14299aebddd1SJeff Kirsher 
1430106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb,
1431106df1e3SSomnath Kotur 			       NULL);
14329aebddd1SJeff Kirsher 	req->id = cpu_to_le16(q->id);
14339aebddd1SJeff Kirsher 
14349aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
14359aebddd1SJeff Kirsher 	q->created = false;
14369aebddd1SJeff Kirsher 
14379aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
14389aebddd1SJeff Kirsher 	return status;
14399aebddd1SJeff Kirsher }
14409aebddd1SJeff Kirsher 
14419aebddd1SJeff Kirsher /* Uses MCC */
14429aebddd1SJeff Kirsher int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
14439aebddd1SJeff Kirsher {
14449aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
14459aebddd1SJeff Kirsher 	struct be_cmd_req_q_destroy *req;
14469aebddd1SJeff Kirsher 	int status;
14479aebddd1SJeff Kirsher 
14489aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
14499aebddd1SJeff Kirsher 
14509aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
14519aebddd1SJeff Kirsher 	if (!wrb) {
14529aebddd1SJeff Kirsher 		status = -EBUSY;
14539aebddd1SJeff Kirsher 		goto err;
14549aebddd1SJeff Kirsher 	}
14559aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
14569aebddd1SJeff Kirsher 
1457106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1458106df1e3SSomnath Kotur 			       OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL);
14599aebddd1SJeff Kirsher 	req->id = cpu_to_le16(q->id);
14609aebddd1SJeff Kirsher 
14619aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
14629aebddd1SJeff Kirsher 	q->created = false;
14639aebddd1SJeff Kirsher 
14649aebddd1SJeff Kirsher err:
14659aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
14669aebddd1SJeff Kirsher 	return status;
14679aebddd1SJeff Kirsher }
14689aebddd1SJeff Kirsher 
14699aebddd1SJeff Kirsher /* Create an rx filtering policy configuration on an i/f
1470bea50988SSathya Perla  * Will use MBOX only if MCCQ has not been created.
14719aebddd1SJeff Kirsher  */
14729aebddd1SJeff Kirsher int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
14731578e777SPadmanabh Ratnakar 		     u32 *if_handle, u32 domain)
14749aebddd1SJeff Kirsher {
1475bea50988SSathya Perla 	struct be_mcc_wrb wrb = {0};
14769aebddd1SJeff Kirsher 	struct be_cmd_req_if_create *req;
14779aebddd1SJeff Kirsher 	int status;
14789aebddd1SJeff Kirsher 
1479bea50988SSathya Perla 	req = embedded_payload(&wrb);
1480106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1481a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_INTERFACE_CREATE,
1482a2cc4e0bSSathya Perla 			       sizeof(*req), &wrb, NULL);
14839aebddd1SJeff Kirsher 	req->hdr.domain = domain;
14849aebddd1SJeff Kirsher 	req->capability_flags = cpu_to_le32(cap_flags);
14859aebddd1SJeff Kirsher 	req->enable_flags = cpu_to_le32(en_flags);
1486f9449ab7SSathya Perla 	req->pmac_invalid = true;
14879aebddd1SJeff Kirsher 
1488bea50988SSathya Perla 	status = be_cmd_notify_wait(adapter, &wrb);
14899aebddd1SJeff Kirsher 	if (!status) {
1490bea50988SSathya Perla 		struct be_cmd_resp_if_create *resp = embedded_payload(&wrb);
149103d28ffeSKalesh AP 
14929aebddd1SJeff Kirsher 		*if_handle = le32_to_cpu(resp->interface_id);
1493b5bb9776SSathya Perla 
1494b5bb9776SSathya Perla 		/* Hack to retrieve VF's pmac-id on BE3 */
149518c57c74SKalesh AP 		if (BE3_chip(adapter) && be_virtfn(adapter))
1496b5bb9776SSathya Perla 			adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id);
14979aebddd1SJeff Kirsher 	}
14989aebddd1SJeff Kirsher 	return status;
14999aebddd1SJeff Kirsher }
15009aebddd1SJeff Kirsher 
1501f9449ab7SSathya Perla /* Uses MCCQ */
150230128031SSathya Perla int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain)
15039aebddd1SJeff Kirsher {
15049aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15059aebddd1SJeff Kirsher 	struct be_cmd_req_if_destroy *req;
15069aebddd1SJeff Kirsher 	int status;
15079aebddd1SJeff Kirsher 
150830128031SSathya Perla 	if (interface_id == -1)
1509f9449ab7SSathya Perla 		return 0;
15109aebddd1SJeff Kirsher 
1511f9449ab7SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
1512f9449ab7SSathya Perla 
1513f9449ab7SSathya Perla 	wrb = wrb_from_mccq(adapter);
1514f9449ab7SSathya Perla 	if (!wrb) {
1515f9449ab7SSathya Perla 		status = -EBUSY;
1516f9449ab7SSathya Perla 		goto err;
1517f9449ab7SSathya Perla 	}
15189aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
15199aebddd1SJeff Kirsher 
1520106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1521a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_INTERFACE_DESTROY,
1522a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
15239aebddd1SJeff Kirsher 	req->hdr.domain = domain;
15249aebddd1SJeff Kirsher 	req->interface_id = cpu_to_le32(interface_id);
15259aebddd1SJeff Kirsher 
1526f9449ab7SSathya Perla 	status = be_mcc_notify_wait(adapter);
1527f9449ab7SSathya Perla err:
1528f9449ab7SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
15299aebddd1SJeff Kirsher 	return status;
15309aebddd1SJeff Kirsher }
15319aebddd1SJeff Kirsher 
15329aebddd1SJeff Kirsher /* Get stats is a non embedded command: the request is not embedded inside
15339aebddd1SJeff Kirsher  * WRB but is a separate dma memory block
15349aebddd1SJeff Kirsher  * Uses asynchronous MCC
15359aebddd1SJeff Kirsher  */
15369aebddd1SJeff Kirsher int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
15379aebddd1SJeff Kirsher {
15389aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15399aebddd1SJeff Kirsher 	struct be_cmd_req_hdr *hdr;
15409aebddd1SJeff Kirsher 	int status = 0;
15419aebddd1SJeff Kirsher 
15429aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
15439aebddd1SJeff Kirsher 
15449aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
15459aebddd1SJeff Kirsher 	if (!wrb) {
15469aebddd1SJeff Kirsher 		status = -EBUSY;
15479aebddd1SJeff Kirsher 		goto err;
15489aebddd1SJeff Kirsher 	}
15499aebddd1SJeff Kirsher 	hdr = nonemb_cmd->va;
15509aebddd1SJeff Kirsher 
1551106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
1552a2cc4e0bSSathya Perla 			       OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb,
1553a2cc4e0bSSathya Perla 			       nonemb_cmd);
15549aebddd1SJeff Kirsher 
1555ca34fe38SSathya Perla 	/* version 1 of the cmd is not supported only by BE2 */
155661000861SAjit Khaparde 	if (BE2_chip(adapter))
155761000861SAjit Khaparde 		hdr->version = 0;
155861000861SAjit Khaparde 	if (BE3_chip(adapter) || lancer_chip(adapter))
15599aebddd1SJeff Kirsher 		hdr->version = 1;
156061000861SAjit Khaparde 	else
156161000861SAjit Khaparde 		hdr->version = 2;
15629aebddd1SJeff Kirsher 
1563efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
1564efaa408eSSuresh Reddy 	if (status)
1565efaa408eSSuresh Reddy 		goto err;
1566efaa408eSSuresh Reddy 
15679aebddd1SJeff Kirsher 	adapter->stats_cmd_sent = true;
15689aebddd1SJeff Kirsher 
15699aebddd1SJeff Kirsher err:
15709aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
15719aebddd1SJeff Kirsher 	return status;
15729aebddd1SJeff Kirsher }
15739aebddd1SJeff Kirsher 
15749aebddd1SJeff Kirsher /* Lancer Stats */
15759aebddd1SJeff Kirsher int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
15769aebddd1SJeff Kirsher 			       struct be_dma_mem *nonemb_cmd)
15779aebddd1SJeff Kirsher {
15789aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15799aebddd1SJeff Kirsher 	struct lancer_cmd_req_pport_stats *req;
15809aebddd1SJeff Kirsher 	int status = 0;
15819aebddd1SJeff Kirsher 
1582f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
1583f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_ETH))
1584f25b119cSPadmanabh Ratnakar 		return -EPERM;
1585f25b119cSPadmanabh Ratnakar 
15869aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
15879aebddd1SJeff Kirsher 
15889aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
15899aebddd1SJeff Kirsher 	if (!wrb) {
15909aebddd1SJeff Kirsher 		status = -EBUSY;
15919aebddd1SJeff Kirsher 		goto err;
15929aebddd1SJeff Kirsher 	}
15939aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
15949aebddd1SJeff Kirsher 
1595106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1596a2cc4e0bSSathya Perla 			       OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size,
1597a2cc4e0bSSathya Perla 			       wrb, nonemb_cmd);
15989aebddd1SJeff Kirsher 
1599d51ebd33SPadmanabh Ratnakar 	req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num);
16009aebddd1SJeff Kirsher 	req->cmd_params.params.reset_stats = 0;
16019aebddd1SJeff Kirsher 
1602efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
1603efaa408eSSuresh Reddy 	if (status)
1604efaa408eSSuresh Reddy 		goto err;
1605efaa408eSSuresh Reddy 
16069aebddd1SJeff Kirsher 	adapter->stats_cmd_sent = true;
16079aebddd1SJeff Kirsher 
16089aebddd1SJeff Kirsher err:
16099aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
16109aebddd1SJeff Kirsher 	return status;
16119aebddd1SJeff Kirsher }
16129aebddd1SJeff Kirsher 
1613323ff71eSSathya Perla static int be_mac_to_link_speed(int mac_speed)
1614323ff71eSSathya Perla {
1615323ff71eSSathya Perla 	switch (mac_speed) {
1616323ff71eSSathya Perla 	case PHY_LINK_SPEED_ZERO:
1617323ff71eSSathya Perla 		return 0;
1618323ff71eSSathya Perla 	case PHY_LINK_SPEED_10MBPS:
1619323ff71eSSathya Perla 		return 10;
1620323ff71eSSathya Perla 	case PHY_LINK_SPEED_100MBPS:
1621323ff71eSSathya Perla 		return 100;
1622323ff71eSSathya Perla 	case PHY_LINK_SPEED_1GBPS:
1623323ff71eSSathya Perla 		return 1000;
1624323ff71eSSathya Perla 	case PHY_LINK_SPEED_10GBPS:
1625323ff71eSSathya Perla 		return 10000;
1626b971f847SVasundhara Volam 	case PHY_LINK_SPEED_20GBPS:
1627b971f847SVasundhara Volam 		return 20000;
1628b971f847SVasundhara Volam 	case PHY_LINK_SPEED_25GBPS:
1629b971f847SVasundhara Volam 		return 25000;
1630b971f847SVasundhara Volam 	case PHY_LINK_SPEED_40GBPS:
1631b971f847SVasundhara Volam 		return 40000;
1632323ff71eSSathya Perla 	}
1633323ff71eSSathya Perla 	return 0;
1634323ff71eSSathya Perla }
1635323ff71eSSathya Perla 
1636323ff71eSSathya Perla /* Uses synchronous mcc
1637323ff71eSSathya Perla  * Returns link_speed in Mbps
1638323ff71eSSathya Perla  */
1639323ff71eSSathya Perla int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
1640323ff71eSSathya Perla 			     u8 *link_status, u32 dom)
16419aebddd1SJeff Kirsher {
16429aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
16439aebddd1SJeff Kirsher 	struct be_cmd_req_link_status *req;
16449aebddd1SJeff Kirsher 	int status;
16459aebddd1SJeff Kirsher 
16469aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16479aebddd1SJeff Kirsher 
1648b236916aSAjit Khaparde 	if (link_status)
1649b236916aSAjit Khaparde 		*link_status = LINK_DOWN;
1650b236916aSAjit Khaparde 
16519aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16529aebddd1SJeff Kirsher 	if (!wrb) {
16539aebddd1SJeff Kirsher 		status = -EBUSY;
16549aebddd1SJeff Kirsher 		goto err;
16559aebddd1SJeff Kirsher 	}
16569aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
16579aebddd1SJeff Kirsher 
165857cd80d4SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1659a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_LINK_STATUS_QUERY,
1660a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
166157cd80d4SPadmanabh Ratnakar 
1662ca34fe38SSathya Perla 	/* version 1 of the cmd is not supported only by BE2 */
1663ca34fe38SSathya Perla 	if (!BE2_chip(adapter))
1664daad6167SPadmanabh Ratnakar 		req->hdr.version = 1;
1665daad6167SPadmanabh Ratnakar 
166657cd80d4SPadmanabh Ratnakar 	req->hdr.domain = dom;
16679aebddd1SJeff Kirsher 
16689aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
16699aebddd1SJeff Kirsher 	if (!status) {
16709aebddd1SJeff Kirsher 		struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
167103d28ffeSKalesh AP 
1672323ff71eSSathya Perla 		if (link_speed) {
1673323ff71eSSathya Perla 			*link_speed = resp->link_speed ?
1674323ff71eSSathya Perla 				      le16_to_cpu(resp->link_speed) * 10 :
1675323ff71eSSathya Perla 				      be_mac_to_link_speed(resp->mac_speed);
1676323ff71eSSathya Perla 
1677323ff71eSSathya Perla 			if (!resp->logical_link_status)
1678323ff71eSSathya Perla 				*link_speed = 0;
16799aebddd1SJeff Kirsher 		}
1680b236916aSAjit Khaparde 		if (link_status)
1681b236916aSAjit Khaparde 			*link_status = resp->logical_link_status;
16829aebddd1SJeff Kirsher 	}
16839aebddd1SJeff Kirsher 
16849aebddd1SJeff Kirsher err:
16859aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
16869aebddd1SJeff Kirsher 	return status;
16879aebddd1SJeff Kirsher }
16889aebddd1SJeff Kirsher 
16899aebddd1SJeff Kirsher /* Uses synchronous mcc */
16909aebddd1SJeff Kirsher int be_cmd_get_die_temperature(struct be_adapter *adapter)
16919aebddd1SJeff Kirsher {
16929aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
16939aebddd1SJeff Kirsher 	struct be_cmd_req_get_cntl_addnl_attribs *req;
1694117affe3SVasundhara Volam 	int status = 0;
16959aebddd1SJeff Kirsher 
16969aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16979aebddd1SJeff Kirsher 
16989aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16999aebddd1SJeff Kirsher 	if (!wrb) {
17009aebddd1SJeff Kirsher 		status = -EBUSY;
17019aebddd1SJeff Kirsher 		goto err;
17029aebddd1SJeff Kirsher 	}
17039aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
17049aebddd1SJeff Kirsher 
1705106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1706a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES,
1707a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
17089aebddd1SJeff Kirsher 
1709efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
17109aebddd1SJeff Kirsher err:
17119aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
17129aebddd1SJeff Kirsher 	return status;
17139aebddd1SJeff Kirsher }
17149aebddd1SJeff Kirsher 
17159aebddd1SJeff Kirsher /* Uses synchronous mcc */
1716fd7ff6f0SVenkat Duvvuru int be_cmd_get_fat_dump_len(struct be_adapter *adapter, u32 *dump_size)
17179aebddd1SJeff Kirsher {
1718fd7ff6f0SVenkat Duvvuru 	struct be_mcc_wrb wrb = {0};
17199aebddd1SJeff Kirsher 	struct be_cmd_req_get_fat *req;
17209aebddd1SJeff Kirsher 	int status;
17219aebddd1SJeff Kirsher 
1722fd7ff6f0SVenkat Duvvuru 	req = embedded_payload(&wrb);
17239aebddd1SJeff Kirsher 
1724106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1725fd7ff6f0SVenkat Duvvuru 			       OPCODE_COMMON_MANAGE_FAT, sizeof(*req),
1726fd7ff6f0SVenkat Duvvuru 			       &wrb, NULL);
17279aebddd1SJeff Kirsher 	req->fat_operation = cpu_to_le32(QUERY_FAT);
1728fd7ff6f0SVenkat Duvvuru 	status = be_cmd_notify_wait(adapter, &wrb);
17299aebddd1SJeff Kirsher 	if (!status) {
1730fd7ff6f0SVenkat Duvvuru 		struct be_cmd_resp_get_fat *resp = embedded_payload(&wrb);
173103d28ffeSKalesh AP 
1732fd7ff6f0SVenkat Duvvuru 		if (dump_size && resp->log_size)
1733fd7ff6f0SVenkat Duvvuru 			*dump_size = le32_to_cpu(resp->log_size) -
17349aebddd1SJeff Kirsher 					sizeof(u32);
17359aebddd1SJeff Kirsher 	}
17369aebddd1SJeff Kirsher 	return status;
17379aebddd1SJeff Kirsher }
17389aebddd1SJeff Kirsher 
1739fd7ff6f0SVenkat Duvvuru int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf)
17409aebddd1SJeff Kirsher {
17419aebddd1SJeff Kirsher 	struct be_dma_mem get_fat_cmd;
17429aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
17439aebddd1SJeff Kirsher 	struct be_cmd_req_get_fat *req;
17449aebddd1SJeff Kirsher 	u32 offset = 0, total_size, buf_size,
17459aebddd1SJeff Kirsher 				log_offset = sizeof(u32), payload_len;
1746fd7ff6f0SVenkat Duvvuru 	int status;
17479aebddd1SJeff Kirsher 
17489aebddd1SJeff Kirsher 	if (buf_len == 0)
1749fd7ff6f0SVenkat Duvvuru 		return 0;
17509aebddd1SJeff Kirsher 
17519aebddd1SJeff Kirsher 	total_size = buf_len;
17529aebddd1SJeff Kirsher 
17539aebddd1SJeff Kirsher 	get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
1754e51000dbSSriharsha Basavapatna 	get_fat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
17559aebddd1SJeff Kirsher 					     get_fat_cmd.size,
1756e51000dbSSriharsha Basavapatna 					     &get_fat_cmd.dma, GFP_ATOMIC);
1757fd7ff6f0SVenkat Duvvuru 	if (!get_fat_cmd.va)
1758c5f156deSVasundhara Volam 		return -ENOMEM;
17599aebddd1SJeff Kirsher 
17609aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
17619aebddd1SJeff Kirsher 
17629aebddd1SJeff Kirsher 	while (total_size) {
17639aebddd1SJeff Kirsher 		buf_size = min(total_size, (u32)60*1024);
17649aebddd1SJeff Kirsher 		total_size -= buf_size;
17659aebddd1SJeff Kirsher 
17669aebddd1SJeff Kirsher 		wrb = wrb_from_mccq(adapter);
17679aebddd1SJeff Kirsher 		if (!wrb) {
17689aebddd1SJeff Kirsher 			status = -EBUSY;
17699aebddd1SJeff Kirsher 			goto err;
17709aebddd1SJeff Kirsher 		}
17719aebddd1SJeff Kirsher 		req = get_fat_cmd.va;
17729aebddd1SJeff Kirsher 
17739aebddd1SJeff Kirsher 		payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size;
1774106df1e3SSomnath Kotur 		be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1775a2cc4e0bSSathya Perla 				       OPCODE_COMMON_MANAGE_FAT, payload_len,
1776a2cc4e0bSSathya Perla 				       wrb, &get_fat_cmd);
17779aebddd1SJeff Kirsher 
17789aebddd1SJeff Kirsher 		req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
17799aebddd1SJeff Kirsher 		req->read_log_offset = cpu_to_le32(log_offset);
17809aebddd1SJeff Kirsher 		req->read_log_length = cpu_to_le32(buf_size);
17819aebddd1SJeff Kirsher 		req->data_buffer_size = cpu_to_le32(buf_size);
17829aebddd1SJeff Kirsher 
17839aebddd1SJeff Kirsher 		status = be_mcc_notify_wait(adapter);
17849aebddd1SJeff Kirsher 		if (!status) {
17859aebddd1SJeff Kirsher 			struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
178603d28ffeSKalesh AP 
17879aebddd1SJeff Kirsher 			memcpy(buf + offset,
17889aebddd1SJeff Kirsher 			       resp->data_buffer,
178992aa9214SSomnath Kotur 			       le32_to_cpu(resp->read_log_length));
17909aebddd1SJeff Kirsher 		} else {
17919aebddd1SJeff Kirsher 			dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
17929aebddd1SJeff Kirsher 			goto err;
17939aebddd1SJeff Kirsher 		}
17949aebddd1SJeff Kirsher 		offset += buf_size;
17959aebddd1SJeff Kirsher 		log_offset += buf_size;
17969aebddd1SJeff Kirsher 	}
17979aebddd1SJeff Kirsher err:
1798e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, get_fat_cmd.size,
1799a2cc4e0bSSathya Perla 			  get_fat_cmd.va, get_fat_cmd.dma);
18009aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1801c5f156deSVasundhara Volam 	return status;
18029aebddd1SJeff Kirsher }
18039aebddd1SJeff Kirsher 
180404b71175SSathya Perla /* Uses synchronous mcc */
1805e97e3cdaSKalesh AP int be_cmd_get_fw_ver(struct be_adapter *adapter)
18069aebddd1SJeff Kirsher {
18079aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
18089aebddd1SJeff Kirsher 	struct be_cmd_req_get_fw_version *req;
18099aebddd1SJeff Kirsher 	int status;
18109aebddd1SJeff Kirsher 
181104b71175SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
18129aebddd1SJeff Kirsher 
181304b71175SSathya Perla 	wrb = wrb_from_mccq(adapter);
181404b71175SSathya Perla 	if (!wrb) {
181504b71175SSathya Perla 		status = -EBUSY;
181604b71175SSathya Perla 		goto err;
181704b71175SSathya Perla 	}
181804b71175SSathya Perla 
18199aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
18209aebddd1SJeff Kirsher 
1821106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1822a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb,
1823a2cc4e0bSSathya Perla 			       NULL);
182404b71175SSathya Perla 	status = be_mcc_notify_wait(adapter);
18259aebddd1SJeff Kirsher 	if (!status) {
18269aebddd1SJeff Kirsher 		struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
1827acbafeb1SSathya Perla 
1828242eb470SVasundhara Volam 		strlcpy(adapter->fw_ver, resp->firmware_version_string,
1829242eb470SVasundhara Volam 			sizeof(adapter->fw_ver));
1830242eb470SVasundhara Volam 		strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string,
1831242eb470SVasundhara Volam 			sizeof(adapter->fw_on_flash));
18329aebddd1SJeff Kirsher 	}
183304b71175SSathya Perla err:
183404b71175SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
18359aebddd1SJeff Kirsher 	return status;
18369aebddd1SJeff Kirsher }
18379aebddd1SJeff Kirsher 
18389aebddd1SJeff Kirsher /* set the EQ delay interval of an EQ to specified value
18399aebddd1SJeff Kirsher  * Uses async mcc
18409aebddd1SJeff Kirsher  */
1841b502ae8dSKalesh AP static int __be_cmd_modify_eqd(struct be_adapter *adapter,
1842b502ae8dSKalesh AP 			       struct be_set_eqd *set_eqd, int num)
18439aebddd1SJeff Kirsher {
18449aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
18459aebddd1SJeff Kirsher 	struct be_cmd_req_modify_eq_delay *req;
18462632bafdSSathya Perla 	int status = 0, i;
18479aebddd1SJeff Kirsher 
18489aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
18499aebddd1SJeff Kirsher 
18509aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
18519aebddd1SJeff Kirsher 	if (!wrb) {
18529aebddd1SJeff Kirsher 		status = -EBUSY;
18539aebddd1SJeff Kirsher 		goto err;
18549aebddd1SJeff Kirsher 	}
18559aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
18569aebddd1SJeff Kirsher 
1857106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1858a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb,
1859a2cc4e0bSSathya Perla 			       NULL);
18609aebddd1SJeff Kirsher 
18612632bafdSSathya Perla 	req->num_eq = cpu_to_le32(num);
18622632bafdSSathya Perla 	for (i = 0; i < num; i++) {
18632632bafdSSathya Perla 		req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
18642632bafdSSathya Perla 		req->set_eqd[i].phase = 0;
18652632bafdSSathya Perla 		req->set_eqd[i].delay_multiplier =
18662632bafdSSathya Perla 				cpu_to_le32(set_eqd[i].delay_multiplier);
18672632bafdSSathya Perla 	}
18689aebddd1SJeff Kirsher 
1869efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
18709aebddd1SJeff Kirsher err:
18719aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
18729aebddd1SJeff Kirsher 	return status;
18739aebddd1SJeff Kirsher }
18749aebddd1SJeff Kirsher 
187593676703SKalesh AP int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd,
187693676703SKalesh AP 		      int num)
187793676703SKalesh AP {
187893676703SKalesh AP 	int num_eqs, i = 0;
187993676703SKalesh AP 
188093676703SKalesh AP 	while (num) {
188193676703SKalesh AP 		num_eqs = min(num, 8);
188293676703SKalesh AP 		__be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs);
188393676703SKalesh AP 		i += num_eqs;
188493676703SKalesh AP 		num -= num_eqs;
188593676703SKalesh AP 	}
188693676703SKalesh AP 
188793676703SKalesh AP 	return 0;
188893676703SKalesh AP }
188993676703SKalesh AP 
18909aebddd1SJeff Kirsher /* Uses sycnhronous mcc */
18919aebddd1SJeff Kirsher int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
1892435452aaSVasundhara Volam 		       u32 num, u32 domain)
18939aebddd1SJeff Kirsher {
18949aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
18959aebddd1SJeff Kirsher 	struct be_cmd_req_vlan_config *req;
18969aebddd1SJeff Kirsher 	int status;
18979aebddd1SJeff Kirsher 
18989aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
18999aebddd1SJeff Kirsher 
19009aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
19019aebddd1SJeff Kirsher 	if (!wrb) {
19029aebddd1SJeff Kirsher 		status = -EBUSY;
19039aebddd1SJeff Kirsher 		goto err;
19049aebddd1SJeff Kirsher 	}
19059aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
19069aebddd1SJeff Kirsher 
1907106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1908a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req),
1909a2cc4e0bSSathya Perla 			       wrb, NULL);
1910435452aaSVasundhara Volam 	req->hdr.domain = domain;
19119aebddd1SJeff Kirsher 
19129aebddd1SJeff Kirsher 	req->interface_id = if_id;
1913012bd387SAjit Khaparde 	req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0;
19149aebddd1SJeff Kirsher 	req->num_vlan = num;
19159aebddd1SJeff Kirsher 	memcpy(req->normal_vlan, vtag_array,
19169aebddd1SJeff Kirsher 	       req->num_vlan * sizeof(vtag_array[0]));
19179aebddd1SJeff Kirsher 
19189aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
19199aebddd1SJeff Kirsher err:
19209aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
19219aebddd1SJeff Kirsher 	return status;
19229aebddd1SJeff Kirsher }
19239aebddd1SJeff Kirsher 
1924ac34b743SSathya Perla static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
19259aebddd1SJeff Kirsher {
19269aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
19279aebddd1SJeff Kirsher 	struct be_dma_mem *mem = &adapter->rx_filter;
19289aebddd1SJeff Kirsher 	struct be_cmd_req_rx_filter *req = mem->va;
19299aebddd1SJeff Kirsher 	int status;
19309aebddd1SJeff Kirsher 
19319aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
19329aebddd1SJeff Kirsher 
19339aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
19349aebddd1SJeff Kirsher 	if (!wrb) {
19359aebddd1SJeff Kirsher 		status = -EBUSY;
19369aebddd1SJeff Kirsher 		goto err;
19379aebddd1SJeff Kirsher 	}
19389aebddd1SJeff Kirsher 	memset(req, 0, sizeof(*req));
1939106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1940106df1e3SSomnath Kotur 			       OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req),
1941106df1e3SSomnath Kotur 			       wrb, mem);
19429aebddd1SJeff Kirsher 
19439aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(adapter->if_handle);
1944ac34b743SSathya Perla 	req->if_flags_mask = cpu_to_le32(flags);
1945ac34b743SSathya Perla 	req->if_flags = (value == ON) ? req->if_flags_mask : 0;
1946d9d604f8SAjit Khaparde 
1947ac34b743SSathya Perla 	if (flags & BE_IF_FLAGS_MULTICAST) {
19489aebddd1SJeff Kirsher 		struct netdev_hw_addr *ha;
19499aebddd1SJeff Kirsher 		int i = 0;
19509aebddd1SJeff Kirsher 
19511610c79fSPadmanabh Ratnakar 		/* Reset mcast promisc mode if already set by setting mask
19521610c79fSPadmanabh Ratnakar 		 * and not setting flags field
19531610c79fSPadmanabh Ratnakar 		 */
19541610c79fSPadmanabh Ratnakar 		req->if_flags_mask |=
1955abb93951SPadmanabh Ratnakar 			cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
195692bf14abSSathya Perla 				    be_if_cap_flags(adapter));
1957016f97b1SPadmanabh Ratnakar 		req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev));
19589aebddd1SJeff Kirsher 		netdev_for_each_mc_addr(ha, adapter->netdev)
19599aebddd1SJeff Kirsher 			memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN);
19609aebddd1SJeff Kirsher 	}
19619aebddd1SJeff Kirsher 
1962b6588879SSathya Perla 	status = be_mcc_notify_wait(adapter);
19639aebddd1SJeff Kirsher err:
19649aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
19659aebddd1SJeff Kirsher 	return status;
19669aebddd1SJeff Kirsher }
19679aebddd1SJeff Kirsher 
1968ac34b743SSathya Perla int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
1969ac34b743SSathya Perla {
1970ac34b743SSathya Perla 	struct device *dev = &adapter->pdev->dev;
1971ac34b743SSathya Perla 
1972ac34b743SSathya Perla 	if ((flags & be_if_cap_flags(adapter)) != flags) {
1973ac34b743SSathya Perla 		dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags);
1974ac34b743SSathya Perla 		dev_warn(dev, "Interface is capable of 0x%x flags only\n",
1975ac34b743SSathya Perla 			 be_if_cap_flags(adapter));
1976ac34b743SSathya Perla 	}
1977ac34b743SSathya Perla 	flags &= be_if_cap_flags(adapter);
1978196e3735SKalesh AP 	if (!flags)
1979196e3735SKalesh AP 		return -ENOTSUPP;
1980ac34b743SSathya Perla 
1981ac34b743SSathya Perla 	return __be_cmd_rx_filter(adapter, flags, value);
1982ac34b743SSathya Perla }
1983ac34b743SSathya Perla 
19849aebddd1SJeff Kirsher /* Uses synchrounous mcc */
19859aebddd1SJeff Kirsher int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
19869aebddd1SJeff Kirsher {
19879aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
19889aebddd1SJeff Kirsher 	struct be_cmd_req_set_flow_control *req;
19899aebddd1SJeff Kirsher 	int status;
19909aebddd1SJeff Kirsher 
1991f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
1992f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
1993f25b119cSPadmanabh Ratnakar 		return -EPERM;
1994f25b119cSPadmanabh Ratnakar 
19959aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
19969aebddd1SJeff Kirsher 
19979aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
19989aebddd1SJeff Kirsher 	if (!wrb) {
19999aebddd1SJeff Kirsher 		status = -EBUSY;
20009aebddd1SJeff Kirsher 		goto err;
20019aebddd1SJeff Kirsher 	}
20029aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20039aebddd1SJeff Kirsher 
2004106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2005a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req),
2006a2cc4e0bSSathya Perla 			       wrb, NULL);
20079aebddd1SJeff Kirsher 
2008b29812c1SSuresh Reddy 	req->hdr.version = 1;
20099aebddd1SJeff Kirsher 	req->tx_flow_control = cpu_to_le16((u16)tx_fc);
20109aebddd1SJeff Kirsher 	req->rx_flow_control = cpu_to_le16((u16)rx_fc);
20119aebddd1SJeff Kirsher 
20129aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
20139aebddd1SJeff Kirsher 
20149aebddd1SJeff Kirsher err:
20159aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
2016b29812c1SSuresh Reddy 
2017b29812c1SSuresh Reddy 	if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED)
2018b29812c1SSuresh Reddy 		return  -EOPNOTSUPP;
2019b29812c1SSuresh Reddy 
20209aebddd1SJeff Kirsher 	return status;
20219aebddd1SJeff Kirsher }
20229aebddd1SJeff Kirsher 
20239aebddd1SJeff Kirsher /* Uses sycn mcc */
20249aebddd1SJeff Kirsher int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
20259aebddd1SJeff Kirsher {
20269aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20279aebddd1SJeff Kirsher 	struct be_cmd_req_get_flow_control *req;
20289aebddd1SJeff Kirsher 	int status;
20299aebddd1SJeff Kirsher 
2030f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
2031f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
2032f25b119cSPadmanabh Ratnakar 		return -EPERM;
2033f25b119cSPadmanabh Ratnakar 
20349aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
20359aebddd1SJeff Kirsher 
20369aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
20379aebddd1SJeff Kirsher 	if (!wrb) {
20389aebddd1SJeff Kirsher 		status = -EBUSY;
20399aebddd1SJeff Kirsher 		goto err;
20409aebddd1SJeff Kirsher 	}
20419aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20429aebddd1SJeff Kirsher 
2043106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2044a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req),
2045a2cc4e0bSSathya Perla 			       wrb, NULL);
20469aebddd1SJeff Kirsher 
20479aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
20489aebddd1SJeff Kirsher 	if (!status) {
20499aebddd1SJeff Kirsher 		struct be_cmd_resp_get_flow_control *resp =
20509aebddd1SJeff Kirsher 						embedded_payload(wrb);
205103d28ffeSKalesh AP 
20529aebddd1SJeff Kirsher 		*tx_fc = le16_to_cpu(resp->tx_flow_control);
20539aebddd1SJeff Kirsher 		*rx_fc = le16_to_cpu(resp->rx_flow_control);
20549aebddd1SJeff Kirsher 	}
20559aebddd1SJeff Kirsher 
20569aebddd1SJeff Kirsher err:
20579aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
20589aebddd1SJeff Kirsher 	return status;
20599aebddd1SJeff Kirsher }
20609aebddd1SJeff Kirsher 
20619aebddd1SJeff Kirsher /* Uses mbox */
2062e97e3cdaSKalesh AP int be_cmd_query_fw_cfg(struct be_adapter *adapter)
20639aebddd1SJeff Kirsher {
20649aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20659aebddd1SJeff Kirsher 	struct be_cmd_req_query_fw_cfg *req;
20669aebddd1SJeff Kirsher 	int status;
20679aebddd1SJeff Kirsher 
20689aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
20699aebddd1SJeff Kirsher 		return -1;
20709aebddd1SJeff Kirsher 
20719aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
20729aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20739aebddd1SJeff Kirsher 
2074106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2075a2cc4e0bSSathya Perla 			       OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
2076a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
20779aebddd1SJeff Kirsher 
20789aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
20799aebddd1SJeff Kirsher 	if (!status) {
20809aebddd1SJeff Kirsher 		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
208103d28ffeSKalesh AP 
2082e97e3cdaSKalesh AP 		adapter->port_num = le32_to_cpu(resp->phys_port);
2083e97e3cdaSKalesh AP 		adapter->function_mode = le32_to_cpu(resp->function_mode);
2084e97e3cdaSKalesh AP 		adapter->function_caps = le32_to_cpu(resp->function_caps);
2085e97e3cdaSKalesh AP 		adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
2086acbafeb1SSathya Perla 		dev_info(&adapter->pdev->dev,
2087acbafeb1SSathya Perla 			 "FW config: function_mode=0x%x, function_caps=0x%x\n",
2088acbafeb1SSathya Perla 			 adapter->function_mode, adapter->function_caps);
20899aebddd1SJeff Kirsher 	}
20909aebddd1SJeff Kirsher 
20919aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
20929aebddd1SJeff Kirsher 	return status;
20939aebddd1SJeff Kirsher }
20949aebddd1SJeff Kirsher 
20959aebddd1SJeff Kirsher /* Uses mbox */
20969aebddd1SJeff Kirsher int be_cmd_reset_function(struct be_adapter *adapter)
20979aebddd1SJeff Kirsher {
20989aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20999aebddd1SJeff Kirsher 	struct be_cmd_req_hdr *req;
21009aebddd1SJeff Kirsher 	int status;
21019aebddd1SJeff Kirsher 
2102bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter)) {
2103bf99e50dSPadmanabh Ratnakar 		iowrite32(SLI_PORT_CONTROL_IP_MASK,
2104bf99e50dSPadmanabh Ratnakar 			  adapter->db + SLIPORT_CONTROL_OFFSET);
21059fa465c0SSathya Perla 		status = lancer_wait_ready(adapter);
21069fa465c0SSathya Perla 		if (status)
2107bf99e50dSPadmanabh Ratnakar 			dev_err(&adapter->pdev->dev,
2108bf99e50dSPadmanabh Ratnakar 				"Adapter in non recoverable error\n");
2109bf99e50dSPadmanabh Ratnakar 		return status;
2110bf99e50dSPadmanabh Ratnakar 	}
2111bf99e50dSPadmanabh Ratnakar 
21129aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
21139aebddd1SJeff Kirsher 		return -1;
21149aebddd1SJeff Kirsher 
21159aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
21169aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21179aebddd1SJeff Kirsher 
2118106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
2119a2cc4e0bSSathya Perla 			       OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb,
2120a2cc4e0bSSathya Perla 			       NULL);
21219aebddd1SJeff Kirsher 
21229aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
21239aebddd1SJeff Kirsher 
21249aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
21259aebddd1SJeff Kirsher 	return status;
21269aebddd1SJeff Kirsher }
21279aebddd1SJeff Kirsher 
2128594ad54aSSuresh Reddy int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
212933cb0fa7SBen Hutchings 		      u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey)
21309aebddd1SJeff Kirsher {
21319aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21329aebddd1SJeff Kirsher 	struct be_cmd_req_rss_config *req;
21339aebddd1SJeff Kirsher 	int status;
21349aebddd1SJeff Kirsher 
2135da1388d6SVasundhara Volam 	if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
2136da1388d6SVasundhara Volam 		return 0;
2137da1388d6SVasundhara Volam 
2138b51aa367SKalesh AP 	spin_lock_bh(&adapter->mcc_lock);
21399aebddd1SJeff Kirsher 
2140b51aa367SKalesh AP 	wrb = wrb_from_mccq(adapter);
2141b51aa367SKalesh AP 	if (!wrb) {
2142b51aa367SKalesh AP 		status = -EBUSY;
2143b51aa367SKalesh AP 		goto err;
2144b51aa367SKalesh AP 	}
21459aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21469aebddd1SJeff Kirsher 
2147106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
2148106df1e3SSomnath Kotur 			       OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
21499aebddd1SJeff Kirsher 
21509aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(adapter->if_handle);
2151594ad54aSSuresh Reddy 	req->enable_rss = cpu_to_le16(rss_hash_opts);
21529aebddd1SJeff Kirsher 	req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
2153594ad54aSSuresh Reddy 
2154b51aa367SKalesh AP 	if (!BEx_chip(adapter))
2155594ad54aSSuresh Reddy 		req->hdr.version = 1;
2156594ad54aSSuresh Reddy 
21579aebddd1SJeff Kirsher 	memcpy(req->cpu_table, rsstable, table_size);
2158e2557877SVenkata Duvvuru 	memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN);
21599aebddd1SJeff Kirsher 	be_dws_cpu_to_le(req->hash, sizeof(req->hash));
21609aebddd1SJeff Kirsher 
2161b51aa367SKalesh AP 	status = be_mcc_notify_wait(adapter);
2162b51aa367SKalesh AP err:
2163b51aa367SKalesh AP 	spin_unlock_bh(&adapter->mcc_lock);
21649aebddd1SJeff Kirsher 	return status;
21659aebddd1SJeff Kirsher }
21669aebddd1SJeff Kirsher 
21679aebddd1SJeff Kirsher /* Uses sync mcc */
21689aebddd1SJeff Kirsher int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
21699aebddd1SJeff Kirsher 			    u8 bcn, u8 sts, u8 state)
21709aebddd1SJeff Kirsher {
21719aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21729aebddd1SJeff Kirsher 	struct be_cmd_req_enable_disable_beacon *req;
21739aebddd1SJeff Kirsher 	int status;
21749aebddd1SJeff Kirsher 
21759aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
21769aebddd1SJeff Kirsher 
21779aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
21789aebddd1SJeff Kirsher 	if (!wrb) {
21799aebddd1SJeff Kirsher 		status = -EBUSY;
21809aebddd1SJeff Kirsher 		goto err;
21819aebddd1SJeff Kirsher 	}
21829aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21839aebddd1SJeff Kirsher 
2184106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2185a2cc4e0bSSathya Perla 			       OPCODE_COMMON_ENABLE_DISABLE_BEACON,
2186a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
21879aebddd1SJeff Kirsher 
21889aebddd1SJeff Kirsher 	req->port_num = port_num;
21899aebddd1SJeff Kirsher 	req->beacon_state = state;
21909aebddd1SJeff Kirsher 	req->beacon_duration = bcn;
21919aebddd1SJeff Kirsher 	req->status_duration = sts;
21929aebddd1SJeff Kirsher 
21939aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
21949aebddd1SJeff Kirsher 
21959aebddd1SJeff Kirsher err:
21969aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
21979aebddd1SJeff Kirsher 	return status;
21989aebddd1SJeff Kirsher }
21999aebddd1SJeff Kirsher 
22009aebddd1SJeff Kirsher /* Uses sync mcc */
22019aebddd1SJeff Kirsher int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
22029aebddd1SJeff Kirsher {
22039aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
22049aebddd1SJeff Kirsher 	struct be_cmd_req_get_beacon_state *req;
22059aebddd1SJeff Kirsher 	int status;
22069aebddd1SJeff Kirsher 
22079aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
22089aebddd1SJeff Kirsher 
22099aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
22109aebddd1SJeff Kirsher 	if (!wrb) {
22119aebddd1SJeff Kirsher 		status = -EBUSY;
22129aebddd1SJeff Kirsher 		goto err;
22139aebddd1SJeff Kirsher 	}
22149aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
22159aebddd1SJeff Kirsher 
2216106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2217a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req),
2218a2cc4e0bSSathya Perla 			       wrb, NULL);
22199aebddd1SJeff Kirsher 
22209aebddd1SJeff Kirsher 	req->port_num = port_num;
22219aebddd1SJeff Kirsher 
22229aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
22239aebddd1SJeff Kirsher 	if (!status) {
22249aebddd1SJeff Kirsher 		struct be_cmd_resp_get_beacon_state *resp =
22259aebddd1SJeff Kirsher 						embedded_payload(wrb);
222603d28ffeSKalesh AP 
22279aebddd1SJeff Kirsher 		*state = resp->beacon_state;
22289aebddd1SJeff Kirsher 	}
22299aebddd1SJeff Kirsher 
22309aebddd1SJeff Kirsher err:
22319aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
22329aebddd1SJeff Kirsher 	return status;
22339aebddd1SJeff Kirsher }
22349aebddd1SJeff Kirsher 
2235e36edd9dSMark Leonard /* Uses sync mcc */
2236e36edd9dSMark Leonard int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
2237e36edd9dSMark Leonard 				      u8 page_num, u8 *data)
2238e36edd9dSMark Leonard {
2239e36edd9dSMark Leonard 	struct be_dma_mem cmd;
2240e36edd9dSMark Leonard 	struct be_mcc_wrb *wrb;
2241e36edd9dSMark Leonard 	struct be_cmd_req_port_type *req;
2242e36edd9dSMark Leonard 	int status;
2243e36edd9dSMark Leonard 
2244e36edd9dSMark Leonard 	if (page_num > TR_PAGE_A2)
2245e36edd9dSMark Leonard 		return -EINVAL;
2246e36edd9dSMark Leonard 
2247e36edd9dSMark Leonard 	cmd.size = sizeof(struct be_cmd_resp_port_type);
2248e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
2249e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
2250e36edd9dSMark Leonard 	if (!cmd.va) {
2251e36edd9dSMark Leonard 		dev_err(&adapter->pdev->dev, "Memory allocation failed\n");
2252e36edd9dSMark Leonard 		return -ENOMEM;
2253e36edd9dSMark Leonard 	}
2254e36edd9dSMark Leonard 
2255e36edd9dSMark Leonard 	spin_lock_bh(&adapter->mcc_lock);
2256e36edd9dSMark Leonard 
2257e36edd9dSMark Leonard 	wrb = wrb_from_mccq(adapter);
2258e36edd9dSMark Leonard 	if (!wrb) {
2259e36edd9dSMark Leonard 		status = -EBUSY;
2260e36edd9dSMark Leonard 		goto err;
2261e36edd9dSMark Leonard 	}
2262e36edd9dSMark Leonard 	req = cmd.va;
2263e36edd9dSMark Leonard 
2264e36edd9dSMark Leonard 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2265e36edd9dSMark Leonard 			       OPCODE_COMMON_READ_TRANSRECV_DATA,
2266e36edd9dSMark Leonard 			       cmd.size, wrb, &cmd);
2267e36edd9dSMark Leonard 
2268e36edd9dSMark Leonard 	req->port = cpu_to_le32(adapter->hba_port_num);
2269e36edd9dSMark Leonard 	req->page_num = cpu_to_le32(page_num);
2270e36edd9dSMark Leonard 	status = be_mcc_notify_wait(adapter);
2271e36edd9dSMark Leonard 	if (!status) {
2272e36edd9dSMark Leonard 		struct be_cmd_resp_port_type *resp = cmd.va;
2273e36edd9dSMark Leonard 
2274e36edd9dSMark Leonard 		memcpy(data, resp->page_data, PAGE_DATA_LEN);
2275e36edd9dSMark Leonard 	}
2276e36edd9dSMark Leonard err:
2277e36edd9dSMark Leonard 	spin_unlock_bh(&adapter->mcc_lock);
2278e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
2279e36edd9dSMark Leonard 	return status;
2280e36edd9dSMark Leonard }
2281e36edd9dSMark Leonard 
2282a23113b5SSuresh Reddy static int lancer_cmd_write_object(struct be_adapter *adapter,
2283a23113b5SSuresh Reddy 				   struct be_dma_mem *cmd, u32 data_size,
2284a23113b5SSuresh Reddy 				   u32 data_offset, const char *obj_name,
2285a23113b5SSuresh Reddy 				   u32 *data_written, u8 *change_status,
2286a23113b5SSuresh Reddy 				   u8 *addn_status)
22879aebddd1SJeff Kirsher {
22889aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
22899aebddd1SJeff Kirsher 	struct lancer_cmd_req_write_object *req;
22909aebddd1SJeff Kirsher 	struct lancer_cmd_resp_write_object *resp;
22919aebddd1SJeff Kirsher 	void *ctxt = NULL;
22929aebddd1SJeff Kirsher 	int status;
22939aebddd1SJeff Kirsher 
22949aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
22959aebddd1SJeff Kirsher 	adapter->flash_status = 0;
22969aebddd1SJeff Kirsher 
22979aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
22989aebddd1SJeff Kirsher 	if (!wrb) {
22999aebddd1SJeff Kirsher 		status = -EBUSY;
23009aebddd1SJeff Kirsher 		goto err_unlock;
23019aebddd1SJeff Kirsher 	}
23029aebddd1SJeff Kirsher 
23039aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
23049aebddd1SJeff Kirsher 
2305106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
23069aebddd1SJeff Kirsher 			       OPCODE_COMMON_WRITE_OBJECT,
2307106df1e3SSomnath Kotur 			       sizeof(struct lancer_cmd_req_write_object), wrb,
2308106df1e3SSomnath Kotur 			       NULL);
23099aebddd1SJeff Kirsher 
23109aebddd1SJeff Kirsher 	ctxt = &req->context;
23119aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_lancer_write_obj_context,
23129aebddd1SJeff Kirsher 		      write_length, ctxt, data_size);
23139aebddd1SJeff Kirsher 
23149aebddd1SJeff Kirsher 	if (data_size == 0)
23159aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
23169aebddd1SJeff Kirsher 			      eof, ctxt, 1);
23179aebddd1SJeff Kirsher 	else
23189aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
23199aebddd1SJeff Kirsher 			      eof, ctxt, 0);
23209aebddd1SJeff Kirsher 
23219aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
23229aebddd1SJeff Kirsher 	req->write_offset = cpu_to_le32(data_offset);
2323242eb470SVasundhara Volam 	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
23249aebddd1SJeff Kirsher 	req->descriptor_count = cpu_to_le32(1);
23259aebddd1SJeff Kirsher 	req->buf_len = cpu_to_le32(data_size);
23269aebddd1SJeff Kirsher 	req->addr_low = cpu_to_le32((cmd->dma +
23279aebddd1SJeff Kirsher 				     sizeof(struct lancer_cmd_req_write_object))
23289aebddd1SJeff Kirsher 				    & 0xFFFFFFFF);
23299aebddd1SJeff Kirsher 	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma +
23309aebddd1SJeff Kirsher 				sizeof(struct lancer_cmd_req_write_object)));
23319aebddd1SJeff Kirsher 
2332efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
2333efaa408eSSuresh Reddy 	if (status)
2334efaa408eSSuresh Reddy 		goto err_unlock;
2335efaa408eSSuresh Reddy 
23369aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
23379aebddd1SJeff Kirsher 
23385eeff635SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
2339701962d0SSomnath Kotur 					 msecs_to_jiffies(60000)))
2340fd45160cSKalesh AP 		status = -ETIMEDOUT;
23419aebddd1SJeff Kirsher 	else
23429aebddd1SJeff Kirsher 		status = adapter->flash_status;
23439aebddd1SJeff Kirsher 
23449aebddd1SJeff Kirsher 	resp = embedded_payload(wrb);
2345f67ef7baSPadmanabh Ratnakar 	if (!status) {
23469aebddd1SJeff Kirsher 		*data_written = le32_to_cpu(resp->actual_write_len);
2347f67ef7baSPadmanabh Ratnakar 		*change_status = resp->change_status;
2348f67ef7baSPadmanabh Ratnakar 	} else {
23499aebddd1SJeff Kirsher 		*addn_status = resp->additional_status;
2350f67ef7baSPadmanabh Ratnakar 	}
23519aebddd1SJeff Kirsher 
23529aebddd1SJeff Kirsher 	return status;
23539aebddd1SJeff Kirsher 
23549aebddd1SJeff Kirsher err_unlock:
23559aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
23569aebddd1SJeff Kirsher 	return status;
23579aebddd1SJeff Kirsher }
23589aebddd1SJeff Kirsher 
23596809cee0SRavikumar Nelavelli int be_cmd_query_cable_type(struct be_adapter *adapter)
23606809cee0SRavikumar Nelavelli {
23616809cee0SRavikumar Nelavelli 	u8 page_data[PAGE_DATA_LEN];
23626809cee0SRavikumar Nelavelli 	int status;
23636809cee0SRavikumar Nelavelli 
23646809cee0SRavikumar Nelavelli 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
23656809cee0SRavikumar Nelavelli 						   page_data);
23666809cee0SRavikumar Nelavelli 	if (!status) {
23676809cee0SRavikumar Nelavelli 		switch (adapter->phy.interface_type) {
23686809cee0SRavikumar Nelavelli 		case PHY_TYPE_QSFP:
23696809cee0SRavikumar Nelavelli 			adapter->phy.cable_type =
23706809cee0SRavikumar Nelavelli 				page_data[QSFP_PLUS_CABLE_TYPE_OFFSET];
23716809cee0SRavikumar Nelavelli 			break;
23726809cee0SRavikumar Nelavelli 		case PHY_TYPE_SFP_PLUS_10GB:
23736809cee0SRavikumar Nelavelli 			adapter->phy.cable_type =
23746809cee0SRavikumar Nelavelli 				page_data[SFP_PLUS_CABLE_TYPE_OFFSET];
23756809cee0SRavikumar Nelavelli 			break;
23766809cee0SRavikumar Nelavelli 		default:
23776809cee0SRavikumar Nelavelli 			adapter->phy.cable_type = 0;
23786809cee0SRavikumar Nelavelli 			break;
23796809cee0SRavikumar Nelavelli 		}
23806809cee0SRavikumar Nelavelli 	}
23816809cee0SRavikumar Nelavelli 	return status;
23826809cee0SRavikumar Nelavelli }
23836809cee0SRavikumar Nelavelli 
238421252377SVasundhara Volam int be_cmd_query_sfp_info(struct be_adapter *adapter)
238521252377SVasundhara Volam {
238621252377SVasundhara Volam 	u8 page_data[PAGE_DATA_LEN];
238721252377SVasundhara Volam 	int status;
238821252377SVasundhara Volam 
238921252377SVasundhara Volam 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
239021252377SVasundhara Volam 						   page_data);
239121252377SVasundhara Volam 	if (!status) {
239221252377SVasundhara Volam 		strlcpy(adapter->phy.vendor_name, page_data +
239321252377SVasundhara Volam 			SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
239421252377SVasundhara Volam 		strlcpy(adapter->phy.vendor_pn,
239521252377SVasundhara Volam 			page_data + SFP_VENDOR_PN_OFFSET,
239621252377SVasundhara Volam 			SFP_VENDOR_NAME_LEN - 1);
239721252377SVasundhara Volam 	}
239821252377SVasundhara Volam 
239921252377SVasundhara Volam 	return status;
240021252377SVasundhara Volam }
240121252377SVasundhara Volam 
2402a23113b5SSuresh Reddy static int lancer_cmd_delete_object(struct be_adapter *adapter,
2403a23113b5SSuresh Reddy 				    const char *obj_name)
2404f0613380SKalesh AP {
2405f0613380SKalesh AP 	struct lancer_cmd_req_delete_object *req;
2406f0613380SKalesh AP 	struct be_mcc_wrb *wrb;
2407f0613380SKalesh AP 	int status;
2408f0613380SKalesh AP 
2409f0613380SKalesh AP 	spin_lock_bh(&adapter->mcc_lock);
2410f0613380SKalesh AP 
2411f0613380SKalesh AP 	wrb = wrb_from_mccq(adapter);
2412f0613380SKalesh AP 	if (!wrb) {
2413f0613380SKalesh AP 		status = -EBUSY;
2414f0613380SKalesh AP 		goto err;
2415f0613380SKalesh AP 	}
2416f0613380SKalesh AP 
2417f0613380SKalesh AP 	req = embedded_payload(wrb);
2418f0613380SKalesh AP 
2419f0613380SKalesh AP 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2420f0613380SKalesh AP 			       OPCODE_COMMON_DELETE_OBJECT,
2421f0613380SKalesh AP 			       sizeof(*req), wrb, NULL);
2422f0613380SKalesh AP 
2423242eb470SVasundhara Volam 	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
2424f0613380SKalesh AP 
2425f0613380SKalesh AP 	status = be_mcc_notify_wait(adapter);
2426f0613380SKalesh AP err:
2427f0613380SKalesh AP 	spin_unlock_bh(&adapter->mcc_lock);
2428f0613380SKalesh AP 	return status;
2429f0613380SKalesh AP }
2430f0613380SKalesh AP 
2431de49bd5aSPadmanabh Ratnakar int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
2432de49bd5aSPadmanabh Ratnakar 			   u32 data_size, u32 data_offset, const char *obj_name,
2433de49bd5aSPadmanabh Ratnakar 			   u32 *data_read, u32 *eof, u8 *addn_status)
2434de49bd5aSPadmanabh Ratnakar {
2435de49bd5aSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
2436de49bd5aSPadmanabh Ratnakar 	struct lancer_cmd_req_read_object *req;
2437de49bd5aSPadmanabh Ratnakar 	struct lancer_cmd_resp_read_object *resp;
2438de49bd5aSPadmanabh Ratnakar 	int status;
2439de49bd5aSPadmanabh Ratnakar 
2440de49bd5aSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
2441de49bd5aSPadmanabh Ratnakar 
2442de49bd5aSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
2443de49bd5aSPadmanabh Ratnakar 	if (!wrb) {
2444de49bd5aSPadmanabh Ratnakar 		status = -EBUSY;
2445de49bd5aSPadmanabh Ratnakar 		goto err_unlock;
2446de49bd5aSPadmanabh Ratnakar 	}
2447de49bd5aSPadmanabh Ratnakar 
2448de49bd5aSPadmanabh Ratnakar 	req = embedded_payload(wrb);
2449de49bd5aSPadmanabh Ratnakar 
2450de49bd5aSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2451de49bd5aSPadmanabh Ratnakar 			       OPCODE_COMMON_READ_OBJECT,
2452de49bd5aSPadmanabh Ratnakar 			       sizeof(struct lancer_cmd_req_read_object), wrb,
2453de49bd5aSPadmanabh Ratnakar 			       NULL);
2454de49bd5aSPadmanabh Ratnakar 
2455de49bd5aSPadmanabh Ratnakar 	req->desired_read_len = cpu_to_le32(data_size);
2456de49bd5aSPadmanabh Ratnakar 	req->read_offset = cpu_to_le32(data_offset);
2457de49bd5aSPadmanabh Ratnakar 	strcpy(req->object_name, obj_name);
2458de49bd5aSPadmanabh Ratnakar 	req->descriptor_count = cpu_to_le32(1);
2459de49bd5aSPadmanabh Ratnakar 	req->buf_len = cpu_to_le32(data_size);
2460de49bd5aSPadmanabh Ratnakar 	req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF));
2461de49bd5aSPadmanabh Ratnakar 	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma));
2462de49bd5aSPadmanabh Ratnakar 
2463de49bd5aSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
2464de49bd5aSPadmanabh Ratnakar 
2465de49bd5aSPadmanabh Ratnakar 	resp = embedded_payload(wrb);
2466de49bd5aSPadmanabh Ratnakar 	if (!status) {
2467de49bd5aSPadmanabh Ratnakar 		*data_read = le32_to_cpu(resp->actual_read_len);
2468de49bd5aSPadmanabh Ratnakar 		*eof = le32_to_cpu(resp->eof);
2469de49bd5aSPadmanabh Ratnakar 	} else {
2470de49bd5aSPadmanabh Ratnakar 		*addn_status = resp->additional_status;
2471de49bd5aSPadmanabh Ratnakar 	}
2472de49bd5aSPadmanabh Ratnakar 
2473de49bd5aSPadmanabh Ratnakar err_unlock:
2474de49bd5aSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
2475de49bd5aSPadmanabh Ratnakar 	return status;
2476de49bd5aSPadmanabh Ratnakar }
2477de49bd5aSPadmanabh Ratnakar 
2478a23113b5SSuresh Reddy static int be_cmd_write_flashrom(struct be_adapter *adapter,
2479a23113b5SSuresh Reddy 				 struct be_dma_mem *cmd, u32 flash_type,
2480a23113b5SSuresh Reddy 				 u32 flash_opcode, u32 img_offset, u32 buf_size)
24819aebddd1SJeff Kirsher {
24829aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
24839aebddd1SJeff Kirsher 	struct be_cmd_write_flashrom *req;
24849aebddd1SJeff Kirsher 	int status;
24859aebddd1SJeff Kirsher 
24869aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
24879aebddd1SJeff Kirsher 	adapter->flash_status = 0;
24889aebddd1SJeff Kirsher 
24899aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
24909aebddd1SJeff Kirsher 	if (!wrb) {
24919aebddd1SJeff Kirsher 		status = -EBUSY;
24929aebddd1SJeff Kirsher 		goto err_unlock;
24939aebddd1SJeff Kirsher 	}
24949aebddd1SJeff Kirsher 	req = cmd->va;
24959aebddd1SJeff Kirsher 
2496106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2497a2cc4e0bSSathya Perla 			       OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb,
2498a2cc4e0bSSathya Perla 			       cmd);
24999aebddd1SJeff Kirsher 
25009aebddd1SJeff Kirsher 	req->params.op_type = cpu_to_le32(flash_type);
250170a7b525SVasundhara Volam 	if (flash_type == OPTYPE_OFFSET_SPECIFIED)
250270a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(img_offset);
250370a7b525SVasundhara Volam 
25049aebddd1SJeff Kirsher 	req->params.op_code = cpu_to_le32(flash_opcode);
25059aebddd1SJeff Kirsher 	req->params.data_buf_size = cpu_to_le32(buf_size);
25069aebddd1SJeff Kirsher 
2507efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
2508efaa408eSSuresh Reddy 	if (status)
2509efaa408eSSuresh Reddy 		goto err_unlock;
2510efaa408eSSuresh Reddy 
25119aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25129aebddd1SJeff Kirsher 
25135eeff635SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
2514e2edb7d5SSathya Perla 					 msecs_to_jiffies(40000)))
2515fd45160cSKalesh AP 		status = -ETIMEDOUT;
25169aebddd1SJeff Kirsher 	else
25179aebddd1SJeff Kirsher 		status = adapter->flash_status;
25189aebddd1SJeff Kirsher 
25199aebddd1SJeff Kirsher 	return status;
25209aebddd1SJeff Kirsher 
25219aebddd1SJeff Kirsher err_unlock:
25229aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25239aebddd1SJeff Kirsher 	return status;
25249aebddd1SJeff Kirsher }
25259aebddd1SJeff Kirsher 
2526a23113b5SSuresh Reddy static int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
252770a7b525SVasundhara Volam 				u16 img_optype, u32 img_offset, u32 crc_offset)
25289aebddd1SJeff Kirsher {
2529be716446SPadmanabh Ratnakar 	struct be_cmd_read_flash_crc *req;
253070a7b525SVasundhara Volam 	struct be_mcc_wrb *wrb;
25319aebddd1SJeff Kirsher 	int status;
25329aebddd1SJeff Kirsher 
25339aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
25349aebddd1SJeff Kirsher 
25359aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
25369aebddd1SJeff Kirsher 	if (!wrb) {
25379aebddd1SJeff Kirsher 		status = -EBUSY;
25389aebddd1SJeff Kirsher 		goto err;
25399aebddd1SJeff Kirsher 	}
25409aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
25419aebddd1SJeff Kirsher 
2542106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2543be716446SPadmanabh Ratnakar 			       OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
2544be716446SPadmanabh Ratnakar 			       wrb, NULL);
25459aebddd1SJeff Kirsher 
254670a7b525SVasundhara Volam 	req->params.op_type = cpu_to_le32(img_optype);
254770a7b525SVasundhara Volam 	if (img_optype == OPTYPE_OFFSET_SPECIFIED)
254870a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(img_offset + crc_offset);
254970a7b525SVasundhara Volam 	else
255070a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(crc_offset);
255170a7b525SVasundhara Volam 
25529aebddd1SJeff Kirsher 	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
25539aebddd1SJeff Kirsher 	req->params.data_buf_size = cpu_to_le32(0x4);
25549aebddd1SJeff Kirsher 
25559aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
25569aebddd1SJeff Kirsher 	if (!status)
2557be716446SPadmanabh Ratnakar 		memcpy(flashed_crc, req->crc, 4);
25589aebddd1SJeff Kirsher 
25599aebddd1SJeff Kirsher err:
25609aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25619aebddd1SJeff Kirsher 	return status;
25629aebddd1SJeff Kirsher }
25639aebddd1SJeff Kirsher 
2564a23113b5SSuresh Reddy static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
2565a23113b5SSuresh Reddy 
2566a23113b5SSuresh Reddy static bool phy_flashing_required(struct be_adapter *adapter)
2567a23113b5SSuresh Reddy {
2568a23113b5SSuresh Reddy 	return (adapter->phy.phy_type == PHY_TYPE_TN_8022 &&
2569a23113b5SSuresh Reddy 		adapter->phy.interface_type == PHY_TYPE_BASET_10GB);
2570a23113b5SSuresh Reddy }
2571a23113b5SSuresh Reddy 
2572a23113b5SSuresh Reddy static bool is_comp_in_ufi(struct be_adapter *adapter,
2573a23113b5SSuresh Reddy 			   struct flash_section_info *fsec, int type)
2574a23113b5SSuresh Reddy {
2575a23113b5SSuresh Reddy 	int i = 0, img_type = 0;
2576a23113b5SSuresh Reddy 	struct flash_section_info_g2 *fsec_g2 = NULL;
2577a23113b5SSuresh Reddy 
2578a23113b5SSuresh Reddy 	if (BE2_chip(adapter))
2579a23113b5SSuresh Reddy 		fsec_g2 = (struct flash_section_info_g2 *)fsec;
2580a23113b5SSuresh Reddy 
2581a23113b5SSuresh Reddy 	for (i = 0; i < MAX_FLASH_COMP; i++) {
2582a23113b5SSuresh Reddy 		if (fsec_g2)
2583a23113b5SSuresh Reddy 			img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type);
2584a23113b5SSuresh Reddy 		else
2585a23113b5SSuresh Reddy 			img_type = le32_to_cpu(fsec->fsec_entry[i].type);
2586a23113b5SSuresh Reddy 
2587a23113b5SSuresh Reddy 		if (img_type == type)
2588a23113b5SSuresh Reddy 			return true;
2589a23113b5SSuresh Reddy 	}
2590a23113b5SSuresh Reddy 	return false;
2591a23113b5SSuresh Reddy }
2592a23113b5SSuresh Reddy 
2593a23113b5SSuresh Reddy static struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
2594a23113b5SSuresh Reddy 						int header_size,
2595a23113b5SSuresh Reddy 						const struct firmware *fw)
2596a23113b5SSuresh Reddy {
2597a23113b5SSuresh Reddy 	struct flash_section_info *fsec = NULL;
2598a23113b5SSuresh Reddy 	const u8 *p = fw->data;
2599a23113b5SSuresh Reddy 
2600a23113b5SSuresh Reddy 	p += header_size;
2601a23113b5SSuresh Reddy 	while (p < (fw->data + fw->size)) {
2602a23113b5SSuresh Reddy 		fsec = (struct flash_section_info *)p;
2603a23113b5SSuresh Reddy 		if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie)))
2604a23113b5SSuresh Reddy 			return fsec;
2605a23113b5SSuresh Reddy 		p += 32;
2606a23113b5SSuresh Reddy 	}
2607a23113b5SSuresh Reddy 	return NULL;
2608a23113b5SSuresh Reddy }
2609a23113b5SSuresh Reddy 
2610a23113b5SSuresh Reddy static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
2611a23113b5SSuresh Reddy 			      u32 img_offset, u32 img_size, int hdr_size,
2612a23113b5SSuresh Reddy 			      u16 img_optype, bool *crc_match)
2613a23113b5SSuresh Reddy {
2614a23113b5SSuresh Reddy 	u32 crc_offset;
2615a23113b5SSuresh Reddy 	int status;
2616a23113b5SSuresh Reddy 	u8 crc[4];
2617a23113b5SSuresh Reddy 
2618a23113b5SSuresh Reddy 	status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset,
2619a23113b5SSuresh Reddy 				      img_size - 4);
2620a23113b5SSuresh Reddy 	if (status)
2621a23113b5SSuresh Reddy 		return status;
2622a23113b5SSuresh Reddy 
2623a23113b5SSuresh Reddy 	crc_offset = hdr_size + img_offset + img_size - 4;
2624a23113b5SSuresh Reddy 
2625a23113b5SSuresh Reddy 	/* Skip flashing, if crc of flashed region matches */
2626a23113b5SSuresh Reddy 	if (!memcmp(crc, p + crc_offset, 4))
2627a23113b5SSuresh Reddy 		*crc_match = true;
2628a23113b5SSuresh Reddy 	else
2629a23113b5SSuresh Reddy 		*crc_match = false;
2630a23113b5SSuresh Reddy 
2631a23113b5SSuresh Reddy 	return status;
2632a23113b5SSuresh Reddy }
2633a23113b5SSuresh Reddy 
2634a23113b5SSuresh Reddy static int be_flash(struct be_adapter *adapter, const u8 *img,
2635a23113b5SSuresh Reddy 		    struct be_dma_mem *flash_cmd, int optype, int img_size,
2636a23113b5SSuresh Reddy 		    u32 img_offset)
2637a23113b5SSuresh Reddy {
2638a23113b5SSuresh Reddy 	u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0;
2639a23113b5SSuresh Reddy 	struct be_cmd_write_flashrom *req = flash_cmd->va;
2640a23113b5SSuresh Reddy 	int status;
2641a23113b5SSuresh Reddy 
2642a23113b5SSuresh Reddy 	while (total_bytes) {
2643a23113b5SSuresh Reddy 		num_bytes = min_t(u32, 32 * 1024, total_bytes);
2644a23113b5SSuresh Reddy 
2645a23113b5SSuresh Reddy 		total_bytes -= num_bytes;
2646a23113b5SSuresh Reddy 
2647a23113b5SSuresh Reddy 		if (!total_bytes) {
2648a23113b5SSuresh Reddy 			if (optype == OPTYPE_PHY_FW)
2649a23113b5SSuresh Reddy 				flash_op = FLASHROM_OPER_PHY_FLASH;
2650a23113b5SSuresh Reddy 			else
2651a23113b5SSuresh Reddy 				flash_op = FLASHROM_OPER_FLASH;
2652a23113b5SSuresh Reddy 		} else {
2653a23113b5SSuresh Reddy 			if (optype == OPTYPE_PHY_FW)
2654a23113b5SSuresh Reddy 				flash_op = FLASHROM_OPER_PHY_SAVE;
2655a23113b5SSuresh Reddy 			else
2656a23113b5SSuresh Reddy 				flash_op = FLASHROM_OPER_SAVE;
2657a23113b5SSuresh Reddy 		}
2658a23113b5SSuresh Reddy 
2659a23113b5SSuresh Reddy 		memcpy(req->data_buf, img, num_bytes);
2660a23113b5SSuresh Reddy 		img += num_bytes;
2661a23113b5SSuresh Reddy 		status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
2662a23113b5SSuresh Reddy 					       flash_op, img_offset +
2663a23113b5SSuresh Reddy 					       bytes_sent, num_bytes);
2664a23113b5SSuresh Reddy 		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
2665a23113b5SSuresh Reddy 		    optype == OPTYPE_PHY_FW)
2666a23113b5SSuresh Reddy 			break;
2667a23113b5SSuresh Reddy 		else if (status)
2668a23113b5SSuresh Reddy 			return status;
2669a23113b5SSuresh Reddy 
2670a23113b5SSuresh Reddy 		bytes_sent += num_bytes;
2671a23113b5SSuresh Reddy 	}
2672a23113b5SSuresh Reddy 	return 0;
2673a23113b5SSuresh Reddy }
2674a23113b5SSuresh Reddy 
2675a23113b5SSuresh Reddy /* For BE2, BE3 and BE3-R */
2676a23113b5SSuresh Reddy static int be_flash_BEx(struct be_adapter *adapter,
2677a23113b5SSuresh Reddy 			const struct firmware *fw,
2678a23113b5SSuresh Reddy 			struct be_dma_mem *flash_cmd, int num_of_images)
2679a23113b5SSuresh Reddy {
2680a23113b5SSuresh Reddy 	int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
2681a23113b5SSuresh Reddy 	struct device *dev = &adapter->pdev->dev;
2682a23113b5SSuresh Reddy 	struct flash_section_info *fsec = NULL;
2683a23113b5SSuresh Reddy 	int status, i, filehdr_size, num_comp;
2684a23113b5SSuresh Reddy 	const struct flash_comp *pflashcomp;
2685a23113b5SSuresh Reddy 	bool crc_match;
2686a23113b5SSuresh Reddy 	const u8 *p;
2687a23113b5SSuresh Reddy 
2688a23113b5SSuresh Reddy 	struct flash_comp gen3_flash_types[] = {
2689a23113b5SSuresh Reddy 		{ BE3_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
2690a23113b5SSuresh Reddy 			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
2691a23113b5SSuresh Reddy 		{ BE3_REDBOOT_START, OPTYPE_REDBOOT,
2692a23113b5SSuresh Reddy 			BE3_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
2693a23113b5SSuresh Reddy 		{ BE3_ISCSI_BIOS_START, OPTYPE_BIOS,
2694a23113b5SSuresh Reddy 			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
2695a23113b5SSuresh Reddy 		{ BE3_PXE_BIOS_START, OPTYPE_PXE_BIOS,
2696a23113b5SSuresh Reddy 			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
2697a23113b5SSuresh Reddy 		{ BE3_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
2698a23113b5SSuresh Reddy 			BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
2699a23113b5SSuresh Reddy 		{ BE3_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
2700a23113b5SSuresh Reddy 			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
2701a23113b5SSuresh Reddy 		{ BE3_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
2702a23113b5SSuresh Reddy 			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
2703a23113b5SSuresh Reddy 		{ BE3_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
2704a23113b5SSuresh Reddy 			BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE},
2705a23113b5SSuresh Reddy 		{ BE3_NCSI_START, OPTYPE_NCSI_FW,
2706a23113b5SSuresh Reddy 			BE3_NCSI_COMP_MAX_SIZE, IMAGE_NCSI},
2707a23113b5SSuresh Reddy 		{ BE3_PHY_FW_START, OPTYPE_PHY_FW,
2708a23113b5SSuresh Reddy 			BE3_PHY_FW_COMP_MAX_SIZE, IMAGE_FIRMWARE_PHY}
2709a23113b5SSuresh Reddy 	};
2710a23113b5SSuresh Reddy 
2711a23113b5SSuresh Reddy 	struct flash_comp gen2_flash_types[] = {
2712a23113b5SSuresh Reddy 		{ BE2_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
2713a23113b5SSuresh Reddy 			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
2714a23113b5SSuresh Reddy 		{ BE2_REDBOOT_START, OPTYPE_REDBOOT,
2715a23113b5SSuresh Reddy 			BE2_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
2716a23113b5SSuresh Reddy 		{ BE2_ISCSI_BIOS_START, OPTYPE_BIOS,
2717a23113b5SSuresh Reddy 			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
2718a23113b5SSuresh Reddy 		{ BE2_PXE_BIOS_START, OPTYPE_PXE_BIOS,
2719a23113b5SSuresh Reddy 			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
2720a23113b5SSuresh Reddy 		{ BE2_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
2721a23113b5SSuresh Reddy 			BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
2722a23113b5SSuresh Reddy 		{ BE2_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
2723a23113b5SSuresh Reddy 			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
2724a23113b5SSuresh Reddy 		{ BE2_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
2725a23113b5SSuresh Reddy 			BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
2726a23113b5SSuresh Reddy 		{ BE2_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
2727a23113b5SSuresh Reddy 			 BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE}
2728a23113b5SSuresh Reddy 	};
2729a23113b5SSuresh Reddy 
2730a23113b5SSuresh Reddy 	if (BE3_chip(adapter)) {
2731a23113b5SSuresh Reddy 		pflashcomp = gen3_flash_types;
2732a23113b5SSuresh Reddy 		filehdr_size = sizeof(struct flash_file_hdr_g3);
2733a23113b5SSuresh Reddy 		num_comp = ARRAY_SIZE(gen3_flash_types);
2734a23113b5SSuresh Reddy 	} else {
2735a23113b5SSuresh Reddy 		pflashcomp = gen2_flash_types;
2736a23113b5SSuresh Reddy 		filehdr_size = sizeof(struct flash_file_hdr_g2);
2737a23113b5SSuresh Reddy 		num_comp = ARRAY_SIZE(gen2_flash_types);
2738a23113b5SSuresh Reddy 		img_hdrs_size = 0;
2739a23113b5SSuresh Reddy 	}
2740a23113b5SSuresh Reddy 
2741a23113b5SSuresh Reddy 	/* Get flash section info*/
2742a23113b5SSuresh Reddy 	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
2743a23113b5SSuresh Reddy 	if (!fsec) {
2744a23113b5SSuresh Reddy 		dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
2745a23113b5SSuresh Reddy 		return -1;
2746a23113b5SSuresh Reddy 	}
2747a23113b5SSuresh Reddy 	for (i = 0; i < num_comp; i++) {
2748a23113b5SSuresh Reddy 		if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type))
2749a23113b5SSuresh Reddy 			continue;
2750a23113b5SSuresh Reddy 
2751a23113b5SSuresh Reddy 		if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) &&
2752a23113b5SSuresh Reddy 		    memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
2753a23113b5SSuresh Reddy 			continue;
2754a23113b5SSuresh Reddy 
2755a23113b5SSuresh Reddy 		if (pflashcomp[i].optype == OPTYPE_PHY_FW  &&
2756a23113b5SSuresh Reddy 		    !phy_flashing_required(adapter))
2757a23113b5SSuresh Reddy 			continue;
2758a23113b5SSuresh Reddy 
2759a23113b5SSuresh Reddy 		if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
2760a23113b5SSuresh Reddy 			status = be_check_flash_crc(adapter, fw->data,
2761a23113b5SSuresh Reddy 						    pflashcomp[i].offset,
2762a23113b5SSuresh Reddy 						    pflashcomp[i].size,
2763a23113b5SSuresh Reddy 						    filehdr_size +
2764a23113b5SSuresh Reddy 						    img_hdrs_size,
2765a23113b5SSuresh Reddy 						    OPTYPE_REDBOOT, &crc_match);
2766a23113b5SSuresh Reddy 			if (status) {
2767a23113b5SSuresh Reddy 				dev_err(dev,
2768a23113b5SSuresh Reddy 					"Could not get CRC for 0x%x region\n",
2769a23113b5SSuresh Reddy 					pflashcomp[i].optype);
2770a23113b5SSuresh Reddy 				continue;
2771a23113b5SSuresh Reddy 			}
2772a23113b5SSuresh Reddy 
2773a23113b5SSuresh Reddy 			if (crc_match)
2774a23113b5SSuresh Reddy 				continue;
2775a23113b5SSuresh Reddy 		}
2776a23113b5SSuresh Reddy 
2777a23113b5SSuresh Reddy 		p = fw->data + filehdr_size + pflashcomp[i].offset +
2778a23113b5SSuresh Reddy 			img_hdrs_size;
2779a23113b5SSuresh Reddy 		if (p + pflashcomp[i].size > fw->data + fw->size)
2780a23113b5SSuresh Reddy 			return -1;
2781a23113b5SSuresh Reddy 
2782a23113b5SSuresh Reddy 		status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
2783a23113b5SSuresh Reddy 				  pflashcomp[i].size, 0);
2784a23113b5SSuresh Reddy 		if (status) {
2785a23113b5SSuresh Reddy 			dev_err(dev, "Flashing section type 0x%x failed\n",
2786a23113b5SSuresh Reddy 				pflashcomp[i].img_type);
2787a23113b5SSuresh Reddy 			return status;
2788a23113b5SSuresh Reddy 		}
2789a23113b5SSuresh Reddy 	}
2790a23113b5SSuresh Reddy 	return 0;
2791a23113b5SSuresh Reddy }
2792a23113b5SSuresh Reddy 
2793a23113b5SSuresh Reddy static u16 be_get_img_optype(struct flash_section_entry fsec_entry)
2794a23113b5SSuresh Reddy {
2795a23113b5SSuresh Reddy 	u32 img_type = le32_to_cpu(fsec_entry.type);
2796a23113b5SSuresh Reddy 	u16 img_optype = le16_to_cpu(fsec_entry.optype);
2797a23113b5SSuresh Reddy 
2798a23113b5SSuresh Reddy 	if (img_optype != 0xFFFF)
2799a23113b5SSuresh Reddy 		return img_optype;
2800a23113b5SSuresh Reddy 
2801a23113b5SSuresh Reddy 	switch (img_type) {
2802a23113b5SSuresh Reddy 	case IMAGE_FIRMWARE_ISCSI:
2803a23113b5SSuresh Reddy 		img_optype = OPTYPE_ISCSI_ACTIVE;
2804a23113b5SSuresh Reddy 		break;
2805a23113b5SSuresh Reddy 	case IMAGE_BOOT_CODE:
2806a23113b5SSuresh Reddy 		img_optype = OPTYPE_REDBOOT;
2807a23113b5SSuresh Reddy 		break;
2808a23113b5SSuresh Reddy 	case IMAGE_OPTION_ROM_ISCSI:
2809a23113b5SSuresh Reddy 		img_optype = OPTYPE_BIOS;
2810a23113b5SSuresh Reddy 		break;
2811a23113b5SSuresh Reddy 	case IMAGE_OPTION_ROM_PXE:
2812a23113b5SSuresh Reddy 		img_optype = OPTYPE_PXE_BIOS;
2813a23113b5SSuresh Reddy 		break;
2814a23113b5SSuresh Reddy 	case IMAGE_OPTION_ROM_FCOE:
2815a23113b5SSuresh Reddy 		img_optype = OPTYPE_FCOE_BIOS;
2816a23113b5SSuresh Reddy 		break;
2817a23113b5SSuresh Reddy 	case IMAGE_FIRMWARE_BACKUP_ISCSI:
2818a23113b5SSuresh Reddy 		img_optype = OPTYPE_ISCSI_BACKUP;
2819a23113b5SSuresh Reddy 		break;
2820a23113b5SSuresh Reddy 	case IMAGE_NCSI:
2821a23113b5SSuresh Reddy 		img_optype = OPTYPE_NCSI_FW;
2822a23113b5SSuresh Reddy 		break;
2823a23113b5SSuresh Reddy 	case IMAGE_FLASHISM_JUMPVECTOR:
2824a23113b5SSuresh Reddy 		img_optype = OPTYPE_FLASHISM_JUMPVECTOR;
2825a23113b5SSuresh Reddy 		break;
2826a23113b5SSuresh Reddy 	case IMAGE_FIRMWARE_PHY:
2827a23113b5SSuresh Reddy 		img_optype = OPTYPE_SH_PHY_FW;
2828a23113b5SSuresh Reddy 		break;
2829a23113b5SSuresh Reddy 	case IMAGE_REDBOOT_DIR:
2830a23113b5SSuresh Reddy 		img_optype = OPTYPE_REDBOOT_DIR;
2831a23113b5SSuresh Reddy 		break;
2832a23113b5SSuresh Reddy 	case IMAGE_REDBOOT_CONFIG:
2833a23113b5SSuresh Reddy 		img_optype = OPTYPE_REDBOOT_CONFIG;
2834a23113b5SSuresh Reddy 		break;
2835a23113b5SSuresh Reddy 	case IMAGE_UFI_DIR:
2836a23113b5SSuresh Reddy 		img_optype = OPTYPE_UFI_DIR;
2837a23113b5SSuresh Reddy 		break;
2838a23113b5SSuresh Reddy 	default:
2839a23113b5SSuresh Reddy 		break;
2840a23113b5SSuresh Reddy 	}
2841a23113b5SSuresh Reddy 
2842a23113b5SSuresh Reddy 	return img_optype;
2843a23113b5SSuresh Reddy }
2844a23113b5SSuresh Reddy 
2845a23113b5SSuresh Reddy static int be_flash_skyhawk(struct be_adapter *adapter,
2846a23113b5SSuresh Reddy 			    const struct firmware *fw,
2847a23113b5SSuresh Reddy 			    struct be_dma_mem *flash_cmd, int num_of_images)
2848a23113b5SSuresh Reddy {
2849a23113b5SSuresh Reddy 	int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
2850a23113b5SSuresh Reddy 	bool crc_match, old_fw_img, flash_offset_support = true;
2851a23113b5SSuresh Reddy 	struct device *dev = &adapter->pdev->dev;
2852a23113b5SSuresh Reddy 	struct flash_section_info *fsec = NULL;
2853a23113b5SSuresh Reddy 	u32 img_offset, img_size, img_type;
2854a23113b5SSuresh Reddy 	u16 img_optype, flash_optype;
2855a23113b5SSuresh Reddy 	int status, i, filehdr_size;
2856a23113b5SSuresh Reddy 	const u8 *p;
2857a23113b5SSuresh Reddy 
2858a23113b5SSuresh Reddy 	filehdr_size = sizeof(struct flash_file_hdr_g3);
2859a23113b5SSuresh Reddy 	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
2860a23113b5SSuresh Reddy 	if (!fsec) {
2861a23113b5SSuresh Reddy 		dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
2862a23113b5SSuresh Reddy 		return -EINVAL;
2863a23113b5SSuresh Reddy 	}
2864a23113b5SSuresh Reddy 
2865a23113b5SSuresh Reddy retry_flash:
2866a23113b5SSuresh Reddy 	for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
2867a23113b5SSuresh Reddy 		img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
2868a23113b5SSuresh Reddy 		img_size   = le32_to_cpu(fsec->fsec_entry[i].pad_size);
2869a23113b5SSuresh Reddy 		img_type   = le32_to_cpu(fsec->fsec_entry[i].type);
2870a23113b5SSuresh Reddy 		img_optype = be_get_img_optype(fsec->fsec_entry[i]);
2871a23113b5SSuresh Reddy 		old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF;
2872a23113b5SSuresh Reddy 
2873a23113b5SSuresh Reddy 		if (img_optype == 0xFFFF)
2874a23113b5SSuresh Reddy 			continue;
2875a23113b5SSuresh Reddy 
2876a23113b5SSuresh Reddy 		if (flash_offset_support)
2877a23113b5SSuresh Reddy 			flash_optype = OPTYPE_OFFSET_SPECIFIED;
2878a23113b5SSuresh Reddy 		else
2879a23113b5SSuresh Reddy 			flash_optype = img_optype;
2880a23113b5SSuresh Reddy 
2881a23113b5SSuresh Reddy 		/* Don't bother verifying CRC if an old FW image is being
2882a23113b5SSuresh Reddy 		 * flashed
2883a23113b5SSuresh Reddy 		 */
2884a23113b5SSuresh Reddy 		if (old_fw_img)
2885a23113b5SSuresh Reddy 			goto flash;
2886a23113b5SSuresh Reddy 
2887a23113b5SSuresh Reddy 		status = be_check_flash_crc(adapter, fw->data, img_offset,
2888a23113b5SSuresh Reddy 					    img_size, filehdr_size +
2889a23113b5SSuresh Reddy 					    img_hdrs_size, flash_optype,
2890a23113b5SSuresh Reddy 					    &crc_match);
2891a23113b5SSuresh Reddy 		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
2892a23113b5SSuresh Reddy 		    base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
2893a23113b5SSuresh Reddy 			/* The current FW image on the card does not support
2894a23113b5SSuresh Reddy 			 * OFFSET based flashing. Retry using older mechanism
2895a23113b5SSuresh Reddy 			 * of OPTYPE based flashing
2896a23113b5SSuresh Reddy 			 */
2897a23113b5SSuresh Reddy 			if (flash_optype == OPTYPE_OFFSET_SPECIFIED) {
2898a23113b5SSuresh Reddy 				flash_offset_support = false;
2899a23113b5SSuresh Reddy 				goto retry_flash;
2900a23113b5SSuresh Reddy 			}
2901a23113b5SSuresh Reddy 
2902a23113b5SSuresh Reddy 			/* The current FW image on the card does not recognize
2903a23113b5SSuresh Reddy 			 * the new FLASH op_type. The FW download is partially
2904a23113b5SSuresh Reddy 			 * complete. Reboot the server now to enable FW image
2905a23113b5SSuresh Reddy 			 * to recognize the new FLASH op_type. To complete the
2906a23113b5SSuresh Reddy 			 * remaining process, download the same FW again after
2907a23113b5SSuresh Reddy 			 * the reboot.
2908a23113b5SSuresh Reddy 			 */
2909a23113b5SSuresh Reddy 			dev_err(dev, "Flash incomplete. Reset the server\n");
2910a23113b5SSuresh Reddy 			dev_err(dev, "Download FW image again after reset\n");
2911a23113b5SSuresh Reddy 			return -EAGAIN;
2912a23113b5SSuresh Reddy 		} else if (status) {
2913a23113b5SSuresh Reddy 			dev_err(dev, "Could not get CRC for 0x%x region\n",
2914a23113b5SSuresh Reddy 				img_optype);
2915a23113b5SSuresh Reddy 			return -EFAULT;
2916a23113b5SSuresh Reddy 		}
2917a23113b5SSuresh Reddy 
2918a23113b5SSuresh Reddy 		if (crc_match)
2919a23113b5SSuresh Reddy 			continue;
2920a23113b5SSuresh Reddy 
2921a23113b5SSuresh Reddy flash:
2922a23113b5SSuresh Reddy 		p = fw->data + filehdr_size + img_offset + img_hdrs_size;
2923a23113b5SSuresh Reddy 		if (p + img_size > fw->data + fw->size)
2924a23113b5SSuresh Reddy 			return -1;
2925a23113b5SSuresh Reddy 
2926a23113b5SSuresh Reddy 		status = be_flash(adapter, p, flash_cmd, flash_optype, img_size,
2927a23113b5SSuresh Reddy 				  img_offset);
2928a23113b5SSuresh Reddy 
2929a23113b5SSuresh Reddy 		/* The current FW image on the card does not support OFFSET
2930a23113b5SSuresh Reddy 		 * based flashing. Retry using older mechanism of OPTYPE based
2931a23113b5SSuresh Reddy 		 * flashing
2932a23113b5SSuresh Reddy 		 */
2933a23113b5SSuresh Reddy 		if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD &&
2934a23113b5SSuresh Reddy 		    flash_optype == OPTYPE_OFFSET_SPECIFIED) {
2935a23113b5SSuresh Reddy 			flash_offset_support = false;
2936a23113b5SSuresh Reddy 			goto retry_flash;
2937a23113b5SSuresh Reddy 		}
2938a23113b5SSuresh Reddy 
2939a23113b5SSuresh Reddy 		/* For old FW images ignore ILLEGAL_FIELD error or errors on
2940a23113b5SSuresh Reddy 		 * UFI_DIR region
2941a23113b5SSuresh Reddy 		 */
2942a23113b5SSuresh Reddy 		if (old_fw_img &&
2943a23113b5SSuresh Reddy 		    (base_status(status) == MCC_STATUS_ILLEGAL_FIELD ||
2944a23113b5SSuresh Reddy 		     (img_optype == OPTYPE_UFI_DIR &&
2945a23113b5SSuresh Reddy 		      base_status(status) == MCC_STATUS_FAILED))) {
2946a23113b5SSuresh Reddy 			continue;
2947a23113b5SSuresh Reddy 		} else if (status) {
2948a23113b5SSuresh Reddy 			dev_err(dev, "Flashing section type 0x%x failed\n",
2949a23113b5SSuresh Reddy 				img_type);
29506b525782SSuresh Reddy 
29516b525782SSuresh Reddy 			switch (addl_status(status)) {
29526b525782SSuresh Reddy 			case MCC_ADDL_STATUS_MISSING_SIGNATURE:
29536b525782SSuresh Reddy 				dev_err(dev,
29546b525782SSuresh Reddy 					"Digital signature missing in FW\n");
29556b525782SSuresh Reddy 				return -EINVAL;
29566b525782SSuresh Reddy 			case MCC_ADDL_STATUS_INVALID_SIGNATURE:
29576b525782SSuresh Reddy 				dev_err(dev,
29586b525782SSuresh Reddy 					"Invalid digital signature in FW\n");
29596b525782SSuresh Reddy 				return -EINVAL;
29606b525782SSuresh Reddy 			default:
2961a23113b5SSuresh Reddy 				return -EFAULT;
2962a23113b5SSuresh Reddy 			}
2963a23113b5SSuresh Reddy 		}
29646b525782SSuresh Reddy 	}
2965a23113b5SSuresh Reddy 	return 0;
2966a23113b5SSuresh Reddy }
2967a23113b5SSuresh Reddy 
2968a23113b5SSuresh Reddy int lancer_fw_download(struct be_adapter *adapter,
2969a23113b5SSuresh Reddy 		       const struct firmware *fw)
2970a23113b5SSuresh Reddy {
2971a23113b5SSuresh Reddy 	struct device *dev = &adapter->pdev->dev;
2972a23113b5SSuresh Reddy 	struct be_dma_mem flash_cmd;
2973a23113b5SSuresh Reddy 	const u8 *data_ptr = NULL;
2974a23113b5SSuresh Reddy 	u8 *dest_image_ptr = NULL;
2975a23113b5SSuresh Reddy 	size_t image_size = 0;
2976a23113b5SSuresh Reddy 	u32 chunk_size = 0;
2977a23113b5SSuresh Reddy 	u32 data_written = 0;
2978a23113b5SSuresh Reddy 	u32 offset = 0;
2979a23113b5SSuresh Reddy 	int status = 0;
2980a23113b5SSuresh Reddy 	u8 add_status = 0;
2981a23113b5SSuresh Reddy 	u8 change_status;
2982a23113b5SSuresh Reddy 
2983a23113b5SSuresh Reddy 	if (!IS_ALIGNED(fw->size, sizeof(u32))) {
2984a23113b5SSuresh Reddy 		dev_err(dev, "FW image size should be multiple of 4\n");
2985a23113b5SSuresh Reddy 		return -EINVAL;
2986a23113b5SSuresh Reddy 	}
2987a23113b5SSuresh Reddy 
2988a23113b5SSuresh Reddy 	flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
2989a23113b5SSuresh Reddy 				+ LANCER_FW_DOWNLOAD_CHUNK;
2990a23113b5SSuresh Reddy 	flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size,
2991a23113b5SSuresh Reddy 					   &flash_cmd.dma, GFP_KERNEL);
2992a23113b5SSuresh Reddy 	if (!flash_cmd.va)
2993a23113b5SSuresh Reddy 		return -ENOMEM;
2994a23113b5SSuresh Reddy 
2995a23113b5SSuresh Reddy 	dest_image_ptr = flash_cmd.va +
2996a23113b5SSuresh Reddy 				sizeof(struct lancer_cmd_req_write_object);
2997a23113b5SSuresh Reddy 	image_size = fw->size;
2998a23113b5SSuresh Reddy 	data_ptr = fw->data;
2999a23113b5SSuresh Reddy 
3000a23113b5SSuresh Reddy 	while (image_size) {
3001a23113b5SSuresh Reddy 		chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK);
3002a23113b5SSuresh Reddy 
3003a23113b5SSuresh Reddy 		/* Copy the image chunk content. */
3004a23113b5SSuresh Reddy 		memcpy(dest_image_ptr, data_ptr, chunk_size);
3005a23113b5SSuresh Reddy 
3006a23113b5SSuresh Reddy 		status = lancer_cmd_write_object(adapter, &flash_cmd,
3007a23113b5SSuresh Reddy 						 chunk_size, offset,
3008a23113b5SSuresh Reddy 						 LANCER_FW_DOWNLOAD_LOCATION,
3009a23113b5SSuresh Reddy 						 &data_written, &change_status,
3010a23113b5SSuresh Reddy 						 &add_status);
3011a23113b5SSuresh Reddy 		if (status)
3012a23113b5SSuresh Reddy 			break;
3013a23113b5SSuresh Reddy 
3014a23113b5SSuresh Reddy 		offset += data_written;
3015a23113b5SSuresh Reddy 		data_ptr += data_written;
3016a23113b5SSuresh Reddy 		image_size -= data_written;
3017a23113b5SSuresh Reddy 	}
3018a23113b5SSuresh Reddy 
3019a23113b5SSuresh Reddy 	if (!status) {
3020a23113b5SSuresh Reddy 		/* Commit the FW written */
3021a23113b5SSuresh Reddy 		status = lancer_cmd_write_object(adapter, &flash_cmd,
3022a23113b5SSuresh Reddy 						 0, offset,
3023a23113b5SSuresh Reddy 						 LANCER_FW_DOWNLOAD_LOCATION,
3024a23113b5SSuresh Reddy 						 &data_written, &change_status,
3025a23113b5SSuresh Reddy 						 &add_status);
3026a23113b5SSuresh Reddy 	}
3027a23113b5SSuresh Reddy 
3028a23113b5SSuresh Reddy 	dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
3029a23113b5SSuresh Reddy 	if (status) {
3030a23113b5SSuresh Reddy 		dev_err(dev, "Firmware load error\n");
3031a23113b5SSuresh Reddy 		return be_cmd_status(status);
3032a23113b5SSuresh Reddy 	}
3033a23113b5SSuresh Reddy 
3034a23113b5SSuresh Reddy 	dev_info(dev, "Firmware flashed successfully\n");
3035a23113b5SSuresh Reddy 
3036a23113b5SSuresh Reddy 	if (change_status == LANCER_FW_RESET_NEEDED) {
3037a23113b5SSuresh Reddy 		dev_info(dev, "Resetting adapter to activate new FW\n");
3038a23113b5SSuresh Reddy 		status = lancer_physdev_ctrl(adapter,
3039a23113b5SSuresh Reddy 					     PHYSDEV_CONTROL_FW_RESET_MASK);
3040a23113b5SSuresh Reddy 		if (status) {
3041a23113b5SSuresh Reddy 			dev_err(dev, "Adapter busy, could not reset FW\n");
3042a23113b5SSuresh Reddy 			dev_err(dev, "Reboot server to activate new FW\n");
3043a23113b5SSuresh Reddy 		}
3044a23113b5SSuresh Reddy 	} else if (change_status != LANCER_NO_RESET_NEEDED) {
3045a23113b5SSuresh Reddy 		dev_info(dev, "Reboot server to activate new FW\n");
3046a23113b5SSuresh Reddy 	}
3047a23113b5SSuresh Reddy 
3048a23113b5SSuresh Reddy 	return 0;
3049a23113b5SSuresh Reddy }
3050a23113b5SSuresh Reddy 
3051a23113b5SSuresh Reddy /* Check if the flash image file is compatible with the adapter that
3052a23113b5SSuresh Reddy  * is being flashed.
3053a23113b5SSuresh Reddy  */
3054a23113b5SSuresh Reddy static bool be_check_ufi_compatibility(struct be_adapter *adapter,
3055a23113b5SSuresh Reddy 				       struct flash_file_hdr_g3 *fhdr)
3056a23113b5SSuresh Reddy {
3057a23113b5SSuresh Reddy 	if (!fhdr) {
3058a23113b5SSuresh Reddy 		dev_err(&adapter->pdev->dev, "Invalid FW UFI file");
3059a23113b5SSuresh Reddy 		return false;
3060a23113b5SSuresh Reddy 	}
3061a23113b5SSuresh Reddy 
3062a23113b5SSuresh Reddy 	/* First letter of the build version is used to identify
3063a23113b5SSuresh Reddy 	 * which chip this image file is meant for.
3064a23113b5SSuresh Reddy 	 */
3065a23113b5SSuresh Reddy 	switch (fhdr->build[0]) {
3066a23113b5SSuresh Reddy 	case BLD_STR_UFI_TYPE_SH:
3067a23113b5SSuresh Reddy 		if (!skyhawk_chip(adapter))
3068a23113b5SSuresh Reddy 			return false;
3069a23113b5SSuresh Reddy 		break;
3070a23113b5SSuresh Reddy 	case BLD_STR_UFI_TYPE_BE3:
3071a23113b5SSuresh Reddy 		if (!BE3_chip(adapter))
3072a23113b5SSuresh Reddy 			return false;
3073a23113b5SSuresh Reddy 		break;
3074a23113b5SSuresh Reddy 	case BLD_STR_UFI_TYPE_BE2:
3075a23113b5SSuresh Reddy 		if (!BE2_chip(adapter))
3076a23113b5SSuresh Reddy 			return false;
3077a23113b5SSuresh Reddy 		break;
3078a23113b5SSuresh Reddy 	default:
3079a23113b5SSuresh Reddy 		return false;
3080a23113b5SSuresh Reddy 	}
3081a23113b5SSuresh Reddy 
3082a23113b5SSuresh Reddy 	/* In BE3 FW images the "asic_type_rev" field doesn't track the
3083a23113b5SSuresh Reddy 	 * asic_rev of the chips it is compatible with.
3084a23113b5SSuresh Reddy 	 * When asic_type_rev is 0 the image is compatible only with
3085a23113b5SSuresh Reddy 	 * pre-BE3-R chips (asic_rev < 0x10)
3086a23113b5SSuresh Reddy 	 */
3087a23113b5SSuresh Reddy 	if (BEx_chip(adapter) && fhdr->asic_type_rev == 0)
3088a23113b5SSuresh Reddy 		return adapter->asic_rev < 0x10;
3089a23113b5SSuresh Reddy 	else
3090a23113b5SSuresh Reddy 		return (fhdr->asic_type_rev >= adapter->asic_rev);
3091a23113b5SSuresh Reddy }
3092a23113b5SSuresh Reddy 
3093a23113b5SSuresh Reddy int be_fw_download(struct be_adapter *adapter, const struct firmware *fw)
3094a23113b5SSuresh Reddy {
3095a23113b5SSuresh Reddy 	struct device *dev = &adapter->pdev->dev;
3096a23113b5SSuresh Reddy 	struct flash_file_hdr_g3 *fhdr3;
3097a23113b5SSuresh Reddy 	struct image_hdr *img_hdr_ptr;
3098a23113b5SSuresh Reddy 	int status = 0, i, num_imgs;
3099a23113b5SSuresh Reddy 	struct be_dma_mem flash_cmd;
3100a23113b5SSuresh Reddy 
3101a23113b5SSuresh Reddy 	fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
3102a23113b5SSuresh Reddy 	if (!be_check_ufi_compatibility(adapter, fhdr3)) {
3103a23113b5SSuresh Reddy 		dev_err(dev, "Flash image is not compatible with adapter\n");
3104a23113b5SSuresh Reddy 		return -EINVAL;
3105a23113b5SSuresh Reddy 	}
3106a23113b5SSuresh Reddy 
3107a23113b5SSuresh Reddy 	flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
3108a23113b5SSuresh Reddy 	flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
3109a23113b5SSuresh Reddy 					   GFP_KERNEL);
3110a23113b5SSuresh Reddy 	if (!flash_cmd.va)
3111a23113b5SSuresh Reddy 		return -ENOMEM;
3112a23113b5SSuresh Reddy 
3113a23113b5SSuresh Reddy 	num_imgs = le32_to_cpu(fhdr3->num_imgs);
3114a23113b5SSuresh Reddy 	for (i = 0; i < num_imgs; i++) {
3115a23113b5SSuresh Reddy 		img_hdr_ptr = (struct image_hdr *)(fw->data +
3116a23113b5SSuresh Reddy 				(sizeof(struct flash_file_hdr_g3) +
3117a23113b5SSuresh Reddy 				 i * sizeof(struct image_hdr)));
3118a23113b5SSuresh Reddy 		if (!BE2_chip(adapter) &&
3119a23113b5SSuresh Reddy 		    le32_to_cpu(img_hdr_ptr->imageid) != 1)
3120a23113b5SSuresh Reddy 			continue;
3121a23113b5SSuresh Reddy 
3122a23113b5SSuresh Reddy 		if (skyhawk_chip(adapter))
3123a23113b5SSuresh Reddy 			status = be_flash_skyhawk(adapter, fw, &flash_cmd,
3124a23113b5SSuresh Reddy 						  num_imgs);
3125a23113b5SSuresh Reddy 		else
3126a23113b5SSuresh Reddy 			status = be_flash_BEx(adapter, fw, &flash_cmd,
3127a23113b5SSuresh Reddy 					      num_imgs);
3128a23113b5SSuresh Reddy 	}
3129a23113b5SSuresh Reddy 
3130a23113b5SSuresh Reddy 	dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
3131a23113b5SSuresh Reddy 	if (!status)
3132a23113b5SSuresh Reddy 		dev_info(dev, "Firmware flashed successfully\n");
3133a23113b5SSuresh Reddy 
3134a23113b5SSuresh Reddy 	return status;
3135a23113b5SSuresh Reddy }
3136a23113b5SSuresh Reddy 
31379aebddd1SJeff Kirsher int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
31389aebddd1SJeff Kirsher 			    struct be_dma_mem *nonemb_cmd)
31399aebddd1SJeff Kirsher {
31409aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
31419aebddd1SJeff Kirsher 	struct be_cmd_req_acpi_wol_magic_config *req;
31429aebddd1SJeff Kirsher 	int status;
31439aebddd1SJeff Kirsher 
31449aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
31459aebddd1SJeff Kirsher 
31469aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
31479aebddd1SJeff Kirsher 	if (!wrb) {
31489aebddd1SJeff Kirsher 		status = -EBUSY;
31499aebddd1SJeff Kirsher 		goto err;
31509aebddd1SJeff Kirsher 	}
31519aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
31529aebddd1SJeff Kirsher 
3153106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
3154a2cc4e0bSSathya Perla 			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req),
3155a2cc4e0bSSathya Perla 			       wrb, nonemb_cmd);
31569aebddd1SJeff Kirsher 	memcpy(req->magic_mac, mac, ETH_ALEN);
31579aebddd1SJeff Kirsher 
31589aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
31599aebddd1SJeff Kirsher 
31609aebddd1SJeff Kirsher err:
31619aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
31629aebddd1SJeff Kirsher 	return status;
31639aebddd1SJeff Kirsher }
31649aebddd1SJeff Kirsher 
31659aebddd1SJeff Kirsher int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
31669aebddd1SJeff Kirsher 			u8 loopback_type, u8 enable)
31679aebddd1SJeff Kirsher {
31689aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
31699aebddd1SJeff Kirsher 	struct be_cmd_req_set_lmode *req;
31709aebddd1SJeff Kirsher 	int status;
31719aebddd1SJeff Kirsher 
31729aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
31739aebddd1SJeff Kirsher 
31749aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
31759aebddd1SJeff Kirsher 	if (!wrb) {
31769aebddd1SJeff Kirsher 		status = -EBUSY;
31779c855975SSuresh Reddy 		goto err_unlock;
31789aebddd1SJeff Kirsher 	}
31799aebddd1SJeff Kirsher 
31809aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
31819aebddd1SJeff Kirsher 
3182106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
3183a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req),
3184a2cc4e0bSSathya Perla 			       wrb, NULL);
31859aebddd1SJeff Kirsher 
31869aebddd1SJeff Kirsher 	req->src_port = port_num;
31879aebddd1SJeff Kirsher 	req->dest_port = port_num;
31889aebddd1SJeff Kirsher 	req->loopback_type = loopback_type;
31899aebddd1SJeff Kirsher 	req->loopback_state = enable;
31909aebddd1SJeff Kirsher 
31919c855975SSuresh Reddy 	status = be_mcc_notify(adapter);
31929c855975SSuresh Reddy 	if (status)
31939c855975SSuresh Reddy 		goto err_unlock;
31949c855975SSuresh Reddy 
31959c855975SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
31969c855975SSuresh Reddy 
31979c855975SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
31989c855975SSuresh Reddy 					 msecs_to_jiffies(SET_LB_MODE_TIMEOUT)))
31999c855975SSuresh Reddy 		status = -ETIMEDOUT;
32009c855975SSuresh Reddy 
32019c855975SSuresh Reddy 	return status;
32029c855975SSuresh Reddy 
32039c855975SSuresh Reddy err_unlock:
32049aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
32059aebddd1SJeff Kirsher 	return status;
32069aebddd1SJeff Kirsher }
32079aebddd1SJeff Kirsher 
32089aebddd1SJeff Kirsher int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
3209a2cc4e0bSSathya Perla 			 u32 loopback_type, u32 pkt_size, u32 num_pkts,
3210a2cc4e0bSSathya Perla 			 u64 pattern)
32119aebddd1SJeff Kirsher {
32129aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
32139aebddd1SJeff Kirsher 	struct be_cmd_req_loopback_test *req;
32145eeff635SSuresh Reddy 	struct be_cmd_resp_loopback_test *resp;
32159aebddd1SJeff Kirsher 	int status;
32169aebddd1SJeff Kirsher 
32179aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
32189aebddd1SJeff Kirsher 
32199aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
32209aebddd1SJeff Kirsher 	if (!wrb) {
32219aebddd1SJeff Kirsher 		status = -EBUSY;
32229aebddd1SJeff Kirsher 		goto err;
32239aebddd1SJeff Kirsher 	}
32249aebddd1SJeff Kirsher 
32259aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
32269aebddd1SJeff Kirsher 
3227106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
3228a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb,
3229a2cc4e0bSSathya Perla 			       NULL);
32309aebddd1SJeff Kirsher 
32315eeff635SSuresh Reddy 	req->hdr.timeout = cpu_to_le32(15);
32329aebddd1SJeff Kirsher 	req->pattern = cpu_to_le64(pattern);
32339aebddd1SJeff Kirsher 	req->src_port = cpu_to_le32(port_num);
32349aebddd1SJeff Kirsher 	req->dest_port = cpu_to_le32(port_num);
32359aebddd1SJeff Kirsher 	req->pkt_size = cpu_to_le32(pkt_size);
32369aebddd1SJeff Kirsher 	req->num_pkts = cpu_to_le32(num_pkts);
32379aebddd1SJeff Kirsher 	req->loopback_type = cpu_to_le32(loopback_type);
32389aebddd1SJeff Kirsher 
3239efaa408eSSuresh Reddy 	status = be_mcc_notify(adapter);
3240efaa408eSSuresh Reddy 	if (status)
3241efaa408eSSuresh Reddy 		goto err;
32429aebddd1SJeff Kirsher 
32435eeff635SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
32445eeff635SSuresh Reddy 
32455eeff635SSuresh Reddy 	wait_for_completion(&adapter->et_cmd_compl);
32465eeff635SSuresh Reddy 	resp = embedded_payload(wrb);
32475eeff635SSuresh Reddy 	status = le32_to_cpu(resp->status);
32485eeff635SSuresh Reddy 
32495eeff635SSuresh Reddy 	return status;
32509aebddd1SJeff Kirsher err:
32519aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
32529aebddd1SJeff Kirsher 	return status;
32539aebddd1SJeff Kirsher }
32549aebddd1SJeff Kirsher 
32559aebddd1SJeff Kirsher int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
32569aebddd1SJeff Kirsher 			u32 byte_cnt, struct be_dma_mem *cmd)
32579aebddd1SJeff Kirsher {
32589aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
32599aebddd1SJeff Kirsher 	struct be_cmd_req_ddrdma_test *req;
32609aebddd1SJeff Kirsher 	int status;
32619aebddd1SJeff Kirsher 	int i, j = 0;
32629aebddd1SJeff Kirsher 
32639aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
32649aebddd1SJeff Kirsher 
32659aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
32669aebddd1SJeff Kirsher 	if (!wrb) {
32679aebddd1SJeff Kirsher 		status = -EBUSY;
32689aebddd1SJeff Kirsher 		goto err;
32699aebddd1SJeff Kirsher 	}
32709aebddd1SJeff Kirsher 	req = cmd->va;
3271106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
3272a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb,
3273a2cc4e0bSSathya Perla 			       cmd);
32749aebddd1SJeff Kirsher 
32759aebddd1SJeff Kirsher 	req->pattern = cpu_to_le64(pattern);
32769aebddd1SJeff Kirsher 	req->byte_count = cpu_to_le32(byte_cnt);
32779aebddd1SJeff Kirsher 	for (i = 0; i < byte_cnt; i++) {
32789aebddd1SJeff Kirsher 		req->snd_buff[i] = (u8)(pattern >> (j*8));
32799aebddd1SJeff Kirsher 		j++;
32809aebddd1SJeff Kirsher 		if (j > 7)
32819aebddd1SJeff Kirsher 			j = 0;
32829aebddd1SJeff Kirsher 	}
32839aebddd1SJeff Kirsher 
32849aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
32859aebddd1SJeff Kirsher 
32869aebddd1SJeff Kirsher 	if (!status) {
32879aebddd1SJeff Kirsher 		struct be_cmd_resp_ddrdma_test *resp;
328803d28ffeSKalesh AP 
32899aebddd1SJeff Kirsher 		resp = cmd->va;
32909aebddd1SJeff Kirsher 		if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) ||
32919aebddd1SJeff Kirsher 		    resp->snd_err) {
32929aebddd1SJeff Kirsher 			status = -1;
32939aebddd1SJeff Kirsher 		}
32949aebddd1SJeff Kirsher 	}
32959aebddd1SJeff Kirsher 
32969aebddd1SJeff Kirsher err:
32979aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
32989aebddd1SJeff Kirsher 	return status;
32999aebddd1SJeff Kirsher }
33009aebddd1SJeff Kirsher 
33019aebddd1SJeff Kirsher int be_cmd_get_seeprom_data(struct be_adapter *adapter,
33029aebddd1SJeff Kirsher 			    struct be_dma_mem *nonemb_cmd)
33039aebddd1SJeff Kirsher {
33049aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
33059aebddd1SJeff Kirsher 	struct be_cmd_req_seeprom_read *req;
33069aebddd1SJeff Kirsher 	int status;
33079aebddd1SJeff Kirsher 
33089aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
33099aebddd1SJeff Kirsher 
33109aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
33119aebddd1SJeff Kirsher 	if (!wrb) {
33129aebddd1SJeff Kirsher 		status = -EBUSY;
33139aebddd1SJeff Kirsher 		goto err;
33149aebddd1SJeff Kirsher 	}
33159aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
33169aebddd1SJeff Kirsher 
3317106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3318106df1e3SSomnath Kotur 			       OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb,
3319106df1e3SSomnath Kotur 			       nonemb_cmd);
33209aebddd1SJeff Kirsher 
33219aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
33229aebddd1SJeff Kirsher 
33239aebddd1SJeff Kirsher err:
33249aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
33259aebddd1SJeff Kirsher 	return status;
33269aebddd1SJeff Kirsher }
33279aebddd1SJeff Kirsher 
332842f11cf2SAjit Khaparde int be_cmd_get_phy_info(struct be_adapter *adapter)
33299aebddd1SJeff Kirsher {
33309aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
33319aebddd1SJeff Kirsher 	struct be_cmd_req_get_phy_info *req;
33329aebddd1SJeff Kirsher 	struct be_dma_mem cmd;
33339aebddd1SJeff Kirsher 	int status;
33349aebddd1SJeff Kirsher 
3335f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
3336f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
3337f25b119cSPadmanabh Ratnakar 		return -EPERM;
3338f25b119cSPadmanabh Ratnakar 
33399aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
33409aebddd1SJeff Kirsher 
33419aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
33429aebddd1SJeff Kirsher 	if (!wrb) {
33439aebddd1SJeff Kirsher 		status = -EBUSY;
33449aebddd1SJeff Kirsher 		goto err;
33459aebddd1SJeff Kirsher 	}
33469aebddd1SJeff Kirsher 	cmd.size = sizeof(struct be_cmd_req_get_phy_info);
3347e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
3348e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
33499aebddd1SJeff Kirsher 	if (!cmd.va) {
33509aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
33519aebddd1SJeff Kirsher 		status = -ENOMEM;
33529aebddd1SJeff Kirsher 		goto err;
33539aebddd1SJeff Kirsher 	}
33549aebddd1SJeff Kirsher 
33559aebddd1SJeff Kirsher 	req = cmd.va;
33569aebddd1SJeff Kirsher 
3357106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3358106df1e3SSomnath Kotur 			       OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req),
3359106df1e3SSomnath Kotur 			       wrb, &cmd);
33609aebddd1SJeff Kirsher 
33619aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
33629aebddd1SJeff Kirsher 	if (!status) {
33639aebddd1SJeff Kirsher 		struct be_phy_info *resp_phy_info =
33649aebddd1SJeff Kirsher 				cmd.va + sizeof(struct be_cmd_req_hdr);
336503d28ffeSKalesh AP 
336642f11cf2SAjit Khaparde 		adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type);
336742f11cf2SAjit Khaparde 		adapter->phy.interface_type =
33689aebddd1SJeff Kirsher 			le16_to_cpu(resp_phy_info->interface_type);
336942f11cf2SAjit Khaparde 		adapter->phy.auto_speeds_supported =
337042f11cf2SAjit Khaparde 			le16_to_cpu(resp_phy_info->auto_speeds_supported);
337142f11cf2SAjit Khaparde 		adapter->phy.fixed_speeds_supported =
337242f11cf2SAjit Khaparde 			le16_to_cpu(resp_phy_info->fixed_speeds_supported);
337342f11cf2SAjit Khaparde 		adapter->phy.misc_params =
337442f11cf2SAjit Khaparde 			le32_to_cpu(resp_phy_info->misc_params);
337568cb7e47SVasundhara Volam 
337668cb7e47SVasundhara Volam 		if (BE2_chip(adapter)) {
337768cb7e47SVasundhara Volam 			adapter->phy.fixed_speeds_supported =
337868cb7e47SVasundhara Volam 				BE_SUPPORTED_SPEED_10GBPS |
337968cb7e47SVasundhara Volam 				BE_SUPPORTED_SPEED_1GBPS;
338068cb7e47SVasundhara Volam 		}
33819aebddd1SJeff Kirsher 	}
3382e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
33839aebddd1SJeff Kirsher err:
33849aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
33859aebddd1SJeff Kirsher 	return status;
33869aebddd1SJeff Kirsher }
33879aebddd1SJeff Kirsher 
3388bc0ee163SLad, Prabhakar static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain)
33899aebddd1SJeff Kirsher {
33909aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
33919aebddd1SJeff Kirsher 	struct be_cmd_req_set_qos *req;
33929aebddd1SJeff Kirsher 	int status;
33939aebddd1SJeff Kirsher 
33949aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
33959aebddd1SJeff Kirsher 
33969aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
33979aebddd1SJeff Kirsher 	if (!wrb) {
33989aebddd1SJeff Kirsher 		status = -EBUSY;
33999aebddd1SJeff Kirsher 		goto err;
34009aebddd1SJeff Kirsher 	}
34019aebddd1SJeff Kirsher 
34029aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
34039aebddd1SJeff Kirsher 
3404106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3405106df1e3SSomnath Kotur 			       OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL);
34069aebddd1SJeff Kirsher 
34079aebddd1SJeff Kirsher 	req->hdr.domain = domain;
34089aebddd1SJeff Kirsher 	req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
34099aebddd1SJeff Kirsher 	req->max_bps_nic = cpu_to_le32(bps);
34109aebddd1SJeff Kirsher 
34119aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
34129aebddd1SJeff Kirsher 
34139aebddd1SJeff Kirsher err:
34149aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
34159aebddd1SJeff Kirsher 	return status;
34169aebddd1SJeff Kirsher }
34179aebddd1SJeff Kirsher 
34189aebddd1SJeff Kirsher int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
34199aebddd1SJeff Kirsher {
34209aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
34219aebddd1SJeff Kirsher 	struct be_cmd_req_cntl_attribs *req;
34229aebddd1SJeff Kirsher 	struct be_cmd_resp_cntl_attribs *resp;
3423a155a5dbSSriharsha Basavapatna 	int status, i;
34249aebddd1SJeff Kirsher 	int payload_len = max(sizeof(*req), sizeof(*resp));
34259aebddd1SJeff Kirsher 	struct mgmt_controller_attrib *attribs;
34269aebddd1SJeff Kirsher 	struct be_dma_mem attribs_cmd;
3427a155a5dbSSriharsha Basavapatna 	u32 *serial_num;
34289aebddd1SJeff Kirsher 
3429d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3430d98ef50fSSuresh Reddy 		return -1;
3431d98ef50fSSuresh Reddy 
34329aebddd1SJeff Kirsher 	memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
34339aebddd1SJeff Kirsher 	attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
3434e51000dbSSriharsha Basavapatna 	attribs_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
3435e51000dbSSriharsha Basavapatna 					     attribs_cmd.size,
3436e51000dbSSriharsha Basavapatna 					     &attribs_cmd.dma, GFP_ATOMIC);
34379aebddd1SJeff Kirsher 	if (!attribs_cmd.va) {
3438a2cc4e0bSSathya Perla 		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
3439d98ef50fSSuresh Reddy 		status = -ENOMEM;
3440d98ef50fSSuresh Reddy 		goto err;
34419aebddd1SJeff Kirsher 	}
34429aebddd1SJeff Kirsher 
34439aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
34449aebddd1SJeff Kirsher 	if (!wrb) {
34459aebddd1SJeff Kirsher 		status = -EBUSY;
34469aebddd1SJeff Kirsher 		goto err;
34479aebddd1SJeff Kirsher 	}
34489aebddd1SJeff Kirsher 	req = attribs_cmd.va;
34499aebddd1SJeff Kirsher 
3450106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3451a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len,
3452a2cc4e0bSSathya Perla 			       wrb, &attribs_cmd);
34539aebddd1SJeff Kirsher 
34549aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
34559aebddd1SJeff Kirsher 	if (!status) {
34569aebddd1SJeff Kirsher 		attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
34579aebddd1SJeff Kirsher 		adapter->hba_port_num = attribs->hba_attribs.phy_port;
3458a155a5dbSSriharsha Basavapatna 		serial_num = attribs->hba_attribs.controller_serial_number;
3459a155a5dbSSriharsha Basavapatna 		for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++)
3460a155a5dbSSriharsha Basavapatna 			adapter->serial_num[i] = le32_to_cpu(serial_num[i]) &
3461a155a5dbSSriharsha Basavapatna 				(BIT_MASK(16) - 1);
34629aebddd1SJeff Kirsher 	}
34639aebddd1SJeff Kirsher 
34649aebddd1SJeff Kirsher err:
34659aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
3466d98ef50fSSuresh Reddy 	if (attribs_cmd.va)
3467e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, attribs_cmd.size,
3468d98ef50fSSuresh Reddy 				  attribs_cmd.va, attribs_cmd.dma);
34699aebddd1SJeff Kirsher 	return status;
34709aebddd1SJeff Kirsher }
34719aebddd1SJeff Kirsher 
34729aebddd1SJeff Kirsher /* Uses mbox */
34739aebddd1SJeff Kirsher int be_cmd_req_native_mode(struct be_adapter *adapter)
34749aebddd1SJeff Kirsher {
34759aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
34769aebddd1SJeff Kirsher 	struct be_cmd_req_set_func_cap *req;
34779aebddd1SJeff Kirsher 	int status;
34789aebddd1SJeff Kirsher 
34799aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
34809aebddd1SJeff Kirsher 		return -1;
34819aebddd1SJeff Kirsher 
34829aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
34839aebddd1SJeff Kirsher 	if (!wrb) {
34849aebddd1SJeff Kirsher 		status = -EBUSY;
34859aebddd1SJeff Kirsher 		goto err;
34869aebddd1SJeff Kirsher 	}
34879aebddd1SJeff Kirsher 
34889aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
34899aebddd1SJeff Kirsher 
3490106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3491a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP,
3492a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
34939aebddd1SJeff Kirsher 
34949aebddd1SJeff Kirsher 	req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS |
34959aebddd1SJeff Kirsher 				CAPABILITY_BE3_NATIVE_ERX_API);
34969aebddd1SJeff Kirsher 	req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API);
34979aebddd1SJeff Kirsher 
34989aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
34999aebddd1SJeff Kirsher 	if (!status) {
35009aebddd1SJeff Kirsher 		struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb);
350103d28ffeSKalesh AP 
35029aebddd1SJeff Kirsher 		adapter->be3_native = le32_to_cpu(resp->cap_flags) &
35039aebddd1SJeff Kirsher 					CAPABILITY_BE3_NATIVE_ERX_API;
3504d379142bSSathya Perla 		if (!adapter->be3_native)
3505d379142bSSathya Perla 			dev_warn(&adapter->pdev->dev,
3506d379142bSSathya Perla 				 "adapter not in advanced mode\n");
35079aebddd1SJeff Kirsher 	}
35089aebddd1SJeff Kirsher err:
35099aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
35109aebddd1SJeff Kirsher 	return status;
35119aebddd1SJeff Kirsher }
3512590c391dSPadmanabh Ratnakar 
3513f25b119cSPadmanabh Ratnakar /* Get privilege(s) for a function */
3514f25b119cSPadmanabh Ratnakar int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
3515f25b119cSPadmanabh Ratnakar 			     u32 domain)
3516f25b119cSPadmanabh Ratnakar {
3517f25b119cSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3518f25b119cSPadmanabh Ratnakar 	struct be_cmd_req_get_fn_privileges *req;
3519f25b119cSPadmanabh Ratnakar 	int status;
3520f25b119cSPadmanabh Ratnakar 
3521f25b119cSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
3522f25b119cSPadmanabh Ratnakar 
3523f25b119cSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
3524f25b119cSPadmanabh Ratnakar 	if (!wrb) {
3525f25b119cSPadmanabh Ratnakar 		status = -EBUSY;
3526f25b119cSPadmanabh Ratnakar 		goto err;
3527f25b119cSPadmanabh Ratnakar 	}
3528f25b119cSPadmanabh Ratnakar 
3529f25b119cSPadmanabh Ratnakar 	req = embedded_payload(wrb);
3530f25b119cSPadmanabh Ratnakar 
3531f25b119cSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3532f25b119cSPadmanabh Ratnakar 			       OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
3533f25b119cSPadmanabh Ratnakar 			       wrb, NULL);
3534f25b119cSPadmanabh Ratnakar 
3535f25b119cSPadmanabh Ratnakar 	req->hdr.domain = domain;
3536f25b119cSPadmanabh Ratnakar 
3537f25b119cSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3538f25b119cSPadmanabh Ratnakar 	if (!status) {
3539f25b119cSPadmanabh Ratnakar 		struct be_cmd_resp_get_fn_privileges *resp =
3540f25b119cSPadmanabh Ratnakar 						embedded_payload(wrb);
354103d28ffeSKalesh AP 
3542f25b119cSPadmanabh Ratnakar 		*privilege = le32_to_cpu(resp->privilege_mask);
354302308d74SSuresh Reddy 
354402308d74SSuresh Reddy 		/* In UMC mode FW does not return right privileges.
354502308d74SSuresh Reddy 		 * Override with correct privilege equivalent to PF.
354602308d74SSuresh Reddy 		 */
354702308d74SSuresh Reddy 		if (BEx_chip(adapter) && be_is_mc(adapter) &&
354802308d74SSuresh Reddy 		    be_physfn(adapter))
354902308d74SSuresh Reddy 			*privilege = MAX_PRIVILEGES;
3550f25b119cSPadmanabh Ratnakar 	}
3551f25b119cSPadmanabh Ratnakar 
3552f25b119cSPadmanabh Ratnakar err:
3553f25b119cSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3554f25b119cSPadmanabh Ratnakar 	return status;
3555f25b119cSPadmanabh Ratnakar }
3556f25b119cSPadmanabh Ratnakar 
355704a06028SSathya Perla /* Set privilege(s) for a function */
355804a06028SSathya Perla int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges,
355904a06028SSathya Perla 			     u32 domain)
356004a06028SSathya Perla {
356104a06028SSathya Perla 	struct be_mcc_wrb *wrb;
356204a06028SSathya Perla 	struct be_cmd_req_set_fn_privileges *req;
356304a06028SSathya Perla 	int status;
356404a06028SSathya Perla 
356504a06028SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
356604a06028SSathya Perla 
356704a06028SSathya Perla 	wrb = wrb_from_mccq(adapter);
356804a06028SSathya Perla 	if (!wrb) {
356904a06028SSathya Perla 		status = -EBUSY;
357004a06028SSathya Perla 		goto err;
357104a06028SSathya Perla 	}
357204a06028SSathya Perla 
357304a06028SSathya Perla 	req = embedded_payload(wrb);
357404a06028SSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
357504a06028SSathya Perla 			       OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req),
357604a06028SSathya Perla 			       wrb, NULL);
357704a06028SSathya Perla 	req->hdr.domain = domain;
357804a06028SSathya Perla 	if (lancer_chip(adapter))
357904a06028SSathya Perla 		req->privileges_lancer = cpu_to_le32(privileges);
358004a06028SSathya Perla 	else
358104a06028SSathya Perla 		req->privileges = cpu_to_le32(privileges);
358204a06028SSathya Perla 
358304a06028SSathya Perla 	status = be_mcc_notify_wait(adapter);
358404a06028SSathya Perla err:
358504a06028SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
358604a06028SSathya Perla 	return status;
358704a06028SSathya Perla }
358804a06028SSathya Perla 
35895a712c13SSathya Perla /* pmac_id_valid: true => pmac_id is supplied and MAC address is requested.
35905a712c13SSathya Perla  * pmac_id_valid: false => pmac_id or MAC address is requested.
35915a712c13SSathya Perla  *		  If pmac_id is returned, pmac_id_valid is returned as true
35925a712c13SSathya Perla  */
35931578e777SPadmanabh Ratnakar int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
3594b188f090SSuresh Reddy 			     bool *pmac_id_valid, u32 *pmac_id, u32 if_handle,
3595b188f090SSuresh Reddy 			     u8 domain)
3596590c391dSPadmanabh Ratnakar {
3597590c391dSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3598590c391dSPadmanabh Ratnakar 	struct be_cmd_req_get_mac_list *req;
3599590c391dSPadmanabh Ratnakar 	int status;
3600590c391dSPadmanabh Ratnakar 	int mac_count;
3601e5e1ee89SPadmanabh Ratnakar 	struct be_dma_mem get_mac_list_cmd;
3602e5e1ee89SPadmanabh Ratnakar 	int i;
3603e5e1ee89SPadmanabh Ratnakar 
3604e5e1ee89SPadmanabh Ratnakar 	memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
3605e5e1ee89SPadmanabh Ratnakar 	get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
3606e51000dbSSriharsha Basavapatna 	get_mac_list_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
3607e5e1ee89SPadmanabh Ratnakar 						  get_mac_list_cmd.size,
3608e51000dbSSriharsha Basavapatna 						  &get_mac_list_cmd.dma,
3609e51000dbSSriharsha Basavapatna 						  GFP_ATOMIC);
3610e5e1ee89SPadmanabh Ratnakar 
3611e5e1ee89SPadmanabh Ratnakar 	if (!get_mac_list_cmd.va) {
3612e5e1ee89SPadmanabh Ratnakar 		dev_err(&adapter->pdev->dev,
3613e5e1ee89SPadmanabh Ratnakar 			"Memory allocation failure during GET_MAC_LIST\n");
3614e5e1ee89SPadmanabh Ratnakar 		return -ENOMEM;
3615e5e1ee89SPadmanabh Ratnakar 	}
3616590c391dSPadmanabh Ratnakar 
3617590c391dSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
3618590c391dSPadmanabh Ratnakar 
3619590c391dSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
3620590c391dSPadmanabh Ratnakar 	if (!wrb) {
3621590c391dSPadmanabh Ratnakar 		status = -EBUSY;
3622e5e1ee89SPadmanabh Ratnakar 		goto out;
3623590c391dSPadmanabh Ratnakar 	}
3624e5e1ee89SPadmanabh Ratnakar 
3625e5e1ee89SPadmanabh Ratnakar 	req = get_mac_list_cmd.va;
3626590c391dSPadmanabh Ratnakar 
3627590c391dSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3628bf591f51SSathya Perla 			       OPCODE_COMMON_GET_MAC_LIST,
3629bf591f51SSathya Perla 			       get_mac_list_cmd.size, wrb, &get_mac_list_cmd);
3630590c391dSPadmanabh Ratnakar 	req->hdr.domain = domain;
3631e5e1ee89SPadmanabh Ratnakar 	req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
36325a712c13SSathya Perla 	if (*pmac_id_valid) {
36335a712c13SSathya Perla 		req->mac_id = cpu_to_le32(*pmac_id);
3634b188f090SSuresh Reddy 		req->iface_id = cpu_to_le16(if_handle);
36355a712c13SSathya Perla 		req->perm_override = 0;
36365a712c13SSathya Perla 	} else {
3637e5e1ee89SPadmanabh Ratnakar 		req->perm_override = 1;
36385a712c13SSathya Perla 	}
3639590c391dSPadmanabh Ratnakar 
3640590c391dSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3641590c391dSPadmanabh Ratnakar 	if (!status) {
3642590c391dSPadmanabh Ratnakar 		struct be_cmd_resp_get_mac_list *resp =
3643e5e1ee89SPadmanabh Ratnakar 						get_mac_list_cmd.va;
36445a712c13SSathya Perla 
36455a712c13SSathya Perla 		if (*pmac_id_valid) {
36465a712c13SSathya Perla 			memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr,
36475a712c13SSathya Perla 			       ETH_ALEN);
36485a712c13SSathya Perla 			goto out;
36495a712c13SSathya Perla 		}
36505a712c13SSathya Perla 
3651e5e1ee89SPadmanabh Ratnakar 		mac_count = resp->true_mac_count + resp->pseudo_mac_count;
3652e5e1ee89SPadmanabh Ratnakar 		/* Mac list returned could contain one or more active mac_ids
3653dbedd44eSJoe Perches 		 * or one or more true or pseudo permanent mac addresses.
36541578e777SPadmanabh Ratnakar 		 * If an active mac_id is present, return first active mac_id
36551578e777SPadmanabh Ratnakar 		 * found.
3656e5e1ee89SPadmanabh Ratnakar 		 */
3657590c391dSPadmanabh Ratnakar 		for (i = 0; i < mac_count; i++) {
3658e5e1ee89SPadmanabh Ratnakar 			struct get_list_macaddr *mac_entry;
3659e5e1ee89SPadmanabh Ratnakar 			u16 mac_addr_size;
3660e5e1ee89SPadmanabh Ratnakar 			u32 mac_id;
3661e5e1ee89SPadmanabh Ratnakar 
3662e5e1ee89SPadmanabh Ratnakar 			mac_entry = &resp->macaddr_list[i];
3663e5e1ee89SPadmanabh Ratnakar 			mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size);
3664e5e1ee89SPadmanabh Ratnakar 			/* mac_id is a 32 bit value and mac_addr size
3665e5e1ee89SPadmanabh Ratnakar 			 * is 6 bytes
3666e5e1ee89SPadmanabh Ratnakar 			 */
3667e5e1ee89SPadmanabh Ratnakar 			if (mac_addr_size == sizeof(u32)) {
36685a712c13SSathya Perla 				*pmac_id_valid = true;
3669e5e1ee89SPadmanabh Ratnakar 				mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id;
3670e5e1ee89SPadmanabh Ratnakar 				*pmac_id = le32_to_cpu(mac_id);
3671e5e1ee89SPadmanabh Ratnakar 				goto out;
3672590c391dSPadmanabh Ratnakar 			}
3673590c391dSPadmanabh Ratnakar 		}
36741578e777SPadmanabh Ratnakar 		/* If no active mac_id found, return first mac addr */
36755a712c13SSathya Perla 		*pmac_id_valid = false;
3676e5e1ee89SPadmanabh Ratnakar 		memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr,
3677e5e1ee89SPadmanabh Ratnakar 		       ETH_ALEN);
3678590c391dSPadmanabh Ratnakar 	}
3679590c391dSPadmanabh Ratnakar 
3680e5e1ee89SPadmanabh Ratnakar out:
3681590c391dSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3682e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, get_mac_list_cmd.size,
3683e5e1ee89SPadmanabh Ratnakar 			  get_mac_list_cmd.va, get_mac_list_cmd.dma);
3684590c391dSPadmanabh Ratnakar 	return status;
3685590c391dSPadmanabh Ratnakar }
3686590c391dSPadmanabh Ratnakar 
3687a2cc4e0bSSathya Perla int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id,
3688a2cc4e0bSSathya Perla 			  u8 *mac, u32 if_handle, bool active, u32 domain)
36895a712c13SSathya Perla {
3690b188f090SSuresh Reddy 	if (!active)
3691b188f090SSuresh Reddy 		be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id,
3692b188f090SSuresh Reddy 					 if_handle, domain);
36933175d8c2SSathya Perla 	if (BEx_chip(adapter))
36945a712c13SSathya Perla 		return be_cmd_mac_addr_query(adapter, mac, false,
3695b188f090SSuresh Reddy 					     if_handle, curr_pmac_id);
36963175d8c2SSathya Perla 	else
36973175d8c2SSathya Perla 		/* Fetch the MAC address using pmac_id */
36983175d8c2SSathya Perla 		return be_cmd_get_mac_from_list(adapter, mac, &active,
3699b188f090SSuresh Reddy 						&curr_pmac_id,
3700b188f090SSuresh Reddy 						if_handle, domain);
37015a712c13SSathya Perla }
37025a712c13SSathya Perla 
370395046b92SSathya Perla int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac)
370495046b92SSathya Perla {
370595046b92SSathya Perla 	int status;
370695046b92SSathya Perla 	bool pmac_valid = false;
370795046b92SSathya Perla 
3708c7bf7169SJoe Perches 	eth_zero_addr(mac);
370995046b92SSathya Perla 
37103175d8c2SSathya Perla 	if (BEx_chip(adapter)) {
37113175d8c2SSathya Perla 		if (be_physfn(adapter))
37123175d8c2SSathya Perla 			status = be_cmd_mac_addr_query(adapter, mac, true, 0,
37133175d8c2SSathya Perla 						       0);
371495046b92SSathya Perla 		else
371595046b92SSathya Perla 			status = be_cmd_mac_addr_query(adapter, mac, false,
371695046b92SSathya Perla 						       adapter->if_handle, 0);
37173175d8c2SSathya Perla 	} else {
37183175d8c2SSathya Perla 		status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid,
3719b188f090SSuresh Reddy 						  NULL, adapter->if_handle, 0);
37203175d8c2SSathya Perla 	}
37213175d8c2SSathya Perla 
372295046b92SSathya Perla 	return status;
372395046b92SSathya Perla }
372495046b92SSathya Perla 
3725590c391dSPadmanabh Ratnakar /* Uses synchronous MCCQ */
3726590c391dSPadmanabh Ratnakar int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
3727590c391dSPadmanabh Ratnakar 			u8 mac_count, u32 domain)
3728590c391dSPadmanabh Ratnakar {
3729590c391dSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3730590c391dSPadmanabh Ratnakar 	struct be_cmd_req_set_mac_list *req;
3731590c391dSPadmanabh Ratnakar 	int status;
3732590c391dSPadmanabh Ratnakar 	struct be_dma_mem cmd;
3733590c391dSPadmanabh Ratnakar 
3734590c391dSPadmanabh Ratnakar 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3735590c391dSPadmanabh Ratnakar 	cmd.size = sizeof(struct be_cmd_req_set_mac_list);
3736e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
3737e51000dbSSriharsha Basavapatna 				     GFP_KERNEL);
3738d0320f75SJoe Perches 	if (!cmd.va)
3739590c391dSPadmanabh Ratnakar 		return -ENOMEM;
3740590c391dSPadmanabh Ratnakar 
3741590c391dSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
3742590c391dSPadmanabh Ratnakar 
3743590c391dSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
3744590c391dSPadmanabh Ratnakar 	if (!wrb) {
3745590c391dSPadmanabh Ratnakar 		status = -EBUSY;
3746590c391dSPadmanabh Ratnakar 		goto err;
3747590c391dSPadmanabh Ratnakar 	}
3748590c391dSPadmanabh Ratnakar 
3749590c391dSPadmanabh Ratnakar 	req = cmd.va;
3750590c391dSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3751590c391dSPadmanabh Ratnakar 			       OPCODE_COMMON_SET_MAC_LIST, sizeof(*req),
3752590c391dSPadmanabh Ratnakar 			       wrb, &cmd);
3753590c391dSPadmanabh Ratnakar 
3754590c391dSPadmanabh Ratnakar 	req->hdr.domain = domain;
3755590c391dSPadmanabh Ratnakar 	req->mac_count = mac_count;
3756590c391dSPadmanabh Ratnakar 	if (mac_count)
3757590c391dSPadmanabh Ratnakar 		memcpy(req->mac, mac_array, ETH_ALEN*mac_count);
3758590c391dSPadmanabh Ratnakar 
3759590c391dSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3760590c391dSPadmanabh Ratnakar 
3761590c391dSPadmanabh Ratnakar err:
3762a2cc4e0bSSathya Perla 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
3763590c391dSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3764590c391dSPadmanabh Ratnakar 	return status;
3765590c391dSPadmanabh Ratnakar }
37664762f6ceSAjit Khaparde 
37673175d8c2SSathya Perla /* Wrapper to delete any active MACs and provision the new mac.
37683175d8c2SSathya Perla  * Changes to MAC_LIST are allowed iff none of the MAC addresses in the
37693175d8c2SSathya Perla  * current list are active.
37703175d8c2SSathya Perla  */
37713175d8c2SSathya Perla int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
37723175d8c2SSathya Perla {
37733175d8c2SSathya Perla 	bool active_mac = false;
37743175d8c2SSathya Perla 	u8 old_mac[ETH_ALEN];
37753175d8c2SSathya Perla 	u32 pmac_id;
37763175d8c2SSathya Perla 	int status;
37773175d8c2SSathya Perla 
37783175d8c2SSathya Perla 	status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
3779b188f090SSuresh Reddy 					  &pmac_id, if_id, dom);
3780b188f090SSuresh Reddy 
37813175d8c2SSathya Perla 	if (!status && active_mac)
37823175d8c2SSathya Perla 		be_cmd_pmac_del(adapter, if_id, pmac_id, dom);
37833175d8c2SSathya Perla 
37843175d8c2SSathya Perla 	return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom);
37853175d8c2SSathya Perla }
37863175d8c2SSathya Perla 
3787f1f3ee1bSAjit Khaparde int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
3788e7bcbd7bSKalesh AP 			  u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk)
3789f1f3ee1bSAjit Khaparde {
3790f1f3ee1bSAjit Khaparde 	struct be_mcc_wrb *wrb;
3791f1f3ee1bSAjit Khaparde 	struct be_cmd_req_set_hsw_config *req;
3792f1f3ee1bSAjit Khaparde 	void *ctxt;
3793f1f3ee1bSAjit Khaparde 	int status;
3794f1f3ee1bSAjit Khaparde 
3795f1f3ee1bSAjit Khaparde 	spin_lock_bh(&adapter->mcc_lock);
3796f1f3ee1bSAjit Khaparde 
3797f1f3ee1bSAjit Khaparde 	wrb = wrb_from_mccq(adapter);
3798f1f3ee1bSAjit Khaparde 	if (!wrb) {
3799f1f3ee1bSAjit Khaparde 		status = -EBUSY;
3800f1f3ee1bSAjit Khaparde 		goto err;
3801f1f3ee1bSAjit Khaparde 	}
3802f1f3ee1bSAjit Khaparde 
3803f1f3ee1bSAjit Khaparde 	req = embedded_payload(wrb);
3804f1f3ee1bSAjit Khaparde 	ctxt = &req->context;
3805f1f3ee1bSAjit Khaparde 
3806f1f3ee1bSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3807a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb,
3808a2cc4e0bSSathya Perla 			       NULL);
3809f1f3ee1bSAjit Khaparde 
3810f1f3ee1bSAjit Khaparde 	req->hdr.domain = domain;
3811f1f3ee1bSAjit Khaparde 	AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id);
3812f1f3ee1bSAjit Khaparde 	if (pvid) {
3813f1f3ee1bSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1);
3814f1f3ee1bSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid);
3815f1f3ee1bSAjit Khaparde 	}
3816a77dcb8cSAjit Khaparde 	if (!BEx_chip(adapter) && hsw_mode) {
3817a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, interface_id,
3818a77dcb8cSAjit Khaparde 			      ctxt, adapter->hba_port_num);
3819a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1);
3820a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type,
3821a77dcb8cSAjit Khaparde 			      ctxt, hsw_mode);
3822a77dcb8cSAjit Khaparde 	}
3823f1f3ee1bSAjit Khaparde 
3824e7bcbd7bSKalesh AP 	/* Enable/disable both mac and vlan spoof checking */
3825e7bcbd7bSKalesh AP 	if (!BEx_chip(adapter) && spoofchk) {
3826e7bcbd7bSKalesh AP 		AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk,
3827e7bcbd7bSKalesh AP 			      ctxt, spoofchk);
3828e7bcbd7bSKalesh AP 		AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk,
3829e7bcbd7bSKalesh AP 			      ctxt, spoofchk);
3830e7bcbd7bSKalesh AP 	}
3831e7bcbd7bSKalesh AP 
3832f1f3ee1bSAjit Khaparde 	be_dws_cpu_to_le(req->context, sizeof(req->context));
3833f1f3ee1bSAjit Khaparde 	status = be_mcc_notify_wait(adapter);
3834f1f3ee1bSAjit Khaparde 
3835f1f3ee1bSAjit Khaparde err:
3836f1f3ee1bSAjit Khaparde 	spin_unlock_bh(&adapter->mcc_lock);
3837f1f3ee1bSAjit Khaparde 	return status;
3838f1f3ee1bSAjit Khaparde }
3839f1f3ee1bSAjit Khaparde 
3840f1f3ee1bSAjit Khaparde /* Get Hyper switch config */
3841f1f3ee1bSAjit Khaparde int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
3842e7bcbd7bSKalesh AP 			  u32 domain, u16 intf_id, u8 *mode, bool *spoofchk)
3843f1f3ee1bSAjit Khaparde {
3844f1f3ee1bSAjit Khaparde 	struct be_mcc_wrb *wrb;
3845f1f3ee1bSAjit Khaparde 	struct be_cmd_req_get_hsw_config *req;
3846f1f3ee1bSAjit Khaparde 	void *ctxt;
3847f1f3ee1bSAjit Khaparde 	int status;
3848f1f3ee1bSAjit Khaparde 	u16 vid;
3849f1f3ee1bSAjit Khaparde 
3850f1f3ee1bSAjit Khaparde 	spin_lock_bh(&adapter->mcc_lock);
3851f1f3ee1bSAjit Khaparde 
3852f1f3ee1bSAjit Khaparde 	wrb = wrb_from_mccq(adapter);
3853f1f3ee1bSAjit Khaparde 	if (!wrb) {
3854f1f3ee1bSAjit Khaparde 		status = -EBUSY;
3855f1f3ee1bSAjit Khaparde 		goto err;
3856f1f3ee1bSAjit Khaparde 	}
3857f1f3ee1bSAjit Khaparde 
3858f1f3ee1bSAjit Khaparde 	req = embedded_payload(wrb);
3859f1f3ee1bSAjit Khaparde 	ctxt = &req->context;
3860f1f3ee1bSAjit Khaparde 
3861f1f3ee1bSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3862a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb,
3863a2cc4e0bSSathya Perla 			       NULL);
3864f1f3ee1bSAjit Khaparde 
3865f1f3ee1bSAjit Khaparde 	req->hdr.domain = domain;
3866a77dcb8cSAjit Khaparde 	AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
3867a77dcb8cSAjit Khaparde 		      ctxt, intf_id);
3868f1f3ee1bSAjit Khaparde 	AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1);
3869a77dcb8cSAjit Khaparde 
38702c07c1d7SVasundhara Volam 	if (!BEx_chip(adapter) && mode) {
3871a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
3872a77dcb8cSAjit Khaparde 			      ctxt, adapter->hba_port_num);
3873a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1);
3874a77dcb8cSAjit Khaparde 	}
3875f1f3ee1bSAjit Khaparde 	be_dws_cpu_to_le(req->context, sizeof(req->context));
3876f1f3ee1bSAjit Khaparde 
3877f1f3ee1bSAjit Khaparde 	status = be_mcc_notify_wait(adapter);
3878f1f3ee1bSAjit Khaparde 	if (!status) {
3879f1f3ee1bSAjit Khaparde 		struct be_cmd_resp_get_hsw_config *resp =
3880f1f3ee1bSAjit Khaparde 						embedded_payload(wrb);
388103d28ffeSKalesh AP 
3882a2cc4e0bSSathya Perla 		be_dws_le_to_cpu(&resp->context, sizeof(resp->context));
3883f1f3ee1bSAjit Khaparde 		vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3884f1f3ee1bSAjit Khaparde 				    pvid, &resp->context);
3885a77dcb8cSAjit Khaparde 		if (pvid)
3886f1f3ee1bSAjit Khaparde 			*pvid = le16_to_cpu(vid);
3887a77dcb8cSAjit Khaparde 		if (mode)
3888a77dcb8cSAjit Khaparde 			*mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3889a77dcb8cSAjit Khaparde 					      port_fwd_type, &resp->context);
3890e7bcbd7bSKalesh AP 		if (spoofchk)
3891e7bcbd7bSKalesh AP 			*spoofchk =
3892e7bcbd7bSKalesh AP 				AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3893e7bcbd7bSKalesh AP 					      spoofchk, &resp->context);
3894f1f3ee1bSAjit Khaparde 	}
3895f1f3ee1bSAjit Khaparde 
3896f1f3ee1bSAjit Khaparde err:
3897f1f3ee1bSAjit Khaparde 	spin_unlock_bh(&adapter->mcc_lock);
3898f1f3ee1bSAjit Khaparde 	return status;
3899f1f3ee1bSAjit Khaparde }
3900f1f3ee1bSAjit Khaparde 
3901f7062ee5SSathya Perla static bool be_is_wol_excluded(struct be_adapter *adapter)
3902f7062ee5SSathya Perla {
3903f7062ee5SSathya Perla 	struct pci_dev *pdev = adapter->pdev;
3904f7062ee5SSathya Perla 
390518c57c74SKalesh AP 	if (be_virtfn(adapter))
3906f7062ee5SSathya Perla 		return true;
3907f7062ee5SSathya Perla 
3908f7062ee5SSathya Perla 	switch (pdev->subsystem_device) {
3909f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID1:
3910f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID2:
3911f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID3:
3912f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID4:
3913f7062ee5SSathya Perla 		return true;
3914f7062ee5SSathya Perla 	default:
3915f7062ee5SSathya Perla 		return false;
3916f7062ee5SSathya Perla 	}
3917f7062ee5SSathya Perla }
3918f7062ee5SSathya Perla 
39194762f6ceSAjit Khaparde int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
39204762f6ceSAjit Khaparde {
39214762f6ceSAjit Khaparde 	struct be_mcc_wrb *wrb;
39224762f6ceSAjit Khaparde 	struct be_cmd_req_acpi_wol_magic_config_v1 *req;
392376a9e08eSSuresh Reddy 	int status = 0;
39244762f6ceSAjit Khaparde 	struct be_dma_mem cmd;
39254762f6ceSAjit Khaparde 
3926f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
3927f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_ETH))
3928f25b119cSPadmanabh Ratnakar 		return -EPERM;
3929f25b119cSPadmanabh Ratnakar 
393076a9e08eSSuresh Reddy 	if (be_is_wol_excluded(adapter))
393176a9e08eSSuresh Reddy 		return status;
393276a9e08eSSuresh Reddy 
3933d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3934d98ef50fSSuresh Reddy 		return -1;
3935d98ef50fSSuresh Reddy 
39364762f6ceSAjit Khaparde 	memset(&cmd, 0, sizeof(struct be_dma_mem));
39374762f6ceSAjit Khaparde 	cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
3938e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
3939e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
39404762f6ceSAjit Khaparde 	if (!cmd.va) {
3941a2cc4e0bSSathya Perla 		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
3942d98ef50fSSuresh Reddy 		status = -ENOMEM;
3943d98ef50fSSuresh Reddy 		goto err;
39444762f6ceSAjit Khaparde 	}
39454762f6ceSAjit Khaparde 
39464762f6ceSAjit Khaparde 	wrb = wrb_from_mbox(adapter);
39474762f6ceSAjit Khaparde 	if (!wrb) {
39484762f6ceSAjit Khaparde 		status = -EBUSY;
39494762f6ceSAjit Khaparde 		goto err;
39504762f6ceSAjit Khaparde 	}
39514762f6ceSAjit Khaparde 
39524762f6ceSAjit Khaparde 	req = cmd.va;
39534762f6ceSAjit Khaparde 
39544762f6ceSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
39554762f6ceSAjit Khaparde 			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
395676a9e08eSSuresh Reddy 			       sizeof(*req), wrb, &cmd);
39574762f6ceSAjit Khaparde 
39584762f6ceSAjit Khaparde 	req->hdr.version = 1;
39594762f6ceSAjit Khaparde 	req->query_options = BE_GET_WOL_CAP;
39604762f6ceSAjit Khaparde 
39614762f6ceSAjit Khaparde 	status = be_mbox_notify_wait(adapter);
39624762f6ceSAjit Khaparde 	if (!status) {
39634762f6ceSAjit Khaparde 		struct be_cmd_resp_acpi_wol_magic_config_v1 *resp;
396403d28ffeSKalesh AP 
39654762f6ceSAjit Khaparde 		resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va;
39664762f6ceSAjit Khaparde 
39674762f6ceSAjit Khaparde 		adapter->wol_cap = resp->wol_settings;
396876a9e08eSSuresh Reddy 		if (adapter->wol_cap & BE_WOL_CAP)
396976a9e08eSSuresh Reddy 			adapter->wol_en = true;
39704762f6ceSAjit Khaparde 	}
39714762f6ceSAjit Khaparde err:
39724762f6ceSAjit Khaparde 	mutex_unlock(&adapter->mbox_lock);
3973d98ef50fSSuresh Reddy 	if (cmd.va)
3974e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
3975e51000dbSSriharsha Basavapatna 				  cmd.dma);
39764762f6ceSAjit Khaparde 	return status;
3977941a77d5SSomnath Kotur 
3978941a77d5SSomnath Kotur }
3979baaa08d1SVasundhara Volam 
3980baaa08d1SVasundhara Volam int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level)
3981baaa08d1SVasundhara Volam {
3982baaa08d1SVasundhara Volam 	struct be_dma_mem extfat_cmd;
3983baaa08d1SVasundhara Volam 	struct be_fat_conf_params *cfgs;
3984baaa08d1SVasundhara Volam 	int status;
3985baaa08d1SVasundhara Volam 	int i, j;
3986baaa08d1SVasundhara Volam 
3987baaa08d1SVasundhara Volam 	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
3988baaa08d1SVasundhara Volam 	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
3989e51000dbSSriharsha Basavapatna 	extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
3990e51000dbSSriharsha Basavapatna 					    extfat_cmd.size, &extfat_cmd.dma,
3991e51000dbSSriharsha Basavapatna 					    GFP_ATOMIC);
3992baaa08d1SVasundhara Volam 	if (!extfat_cmd.va)
3993baaa08d1SVasundhara Volam 		return -ENOMEM;
3994baaa08d1SVasundhara Volam 
3995baaa08d1SVasundhara Volam 	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
3996baaa08d1SVasundhara Volam 	if (status)
3997baaa08d1SVasundhara Volam 		goto err;
3998baaa08d1SVasundhara Volam 
3999baaa08d1SVasundhara Volam 	cfgs = (struct be_fat_conf_params *)
4000baaa08d1SVasundhara Volam 			(extfat_cmd.va + sizeof(struct be_cmd_resp_hdr));
4001baaa08d1SVasundhara Volam 	for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) {
4002baaa08d1SVasundhara Volam 		u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes);
400303d28ffeSKalesh AP 
4004baaa08d1SVasundhara Volam 		for (j = 0; j < num_modes; j++) {
4005baaa08d1SVasundhara Volam 			if (cfgs->module[i].trace_lvl[j].mode == MODE_UART)
4006baaa08d1SVasundhara Volam 				cfgs->module[i].trace_lvl[j].dbg_lvl =
4007baaa08d1SVasundhara Volam 							cpu_to_le32(level);
4008baaa08d1SVasundhara Volam 		}
4009baaa08d1SVasundhara Volam 	}
4010baaa08d1SVasundhara Volam 
4011baaa08d1SVasundhara Volam 	status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs);
4012baaa08d1SVasundhara Volam err:
4013e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va,
4014baaa08d1SVasundhara Volam 			  extfat_cmd.dma);
4015baaa08d1SVasundhara Volam 	return status;
4016baaa08d1SVasundhara Volam }
4017baaa08d1SVasundhara Volam 
4018baaa08d1SVasundhara Volam int be_cmd_get_fw_log_level(struct be_adapter *adapter)
4019baaa08d1SVasundhara Volam {
4020baaa08d1SVasundhara Volam 	struct be_dma_mem extfat_cmd;
4021baaa08d1SVasundhara Volam 	struct be_fat_conf_params *cfgs;
4022baaa08d1SVasundhara Volam 	int status, j;
4023baaa08d1SVasundhara Volam 	int level = 0;
4024baaa08d1SVasundhara Volam 
4025baaa08d1SVasundhara Volam 	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
4026baaa08d1SVasundhara Volam 	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
4027e51000dbSSriharsha Basavapatna 	extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
4028e51000dbSSriharsha Basavapatna 					    extfat_cmd.size, &extfat_cmd.dma,
4029e51000dbSSriharsha Basavapatna 					    GFP_ATOMIC);
4030baaa08d1SVasundhara Volam 
4031baaa08d1SVasundhara Volam 	if (!extfat_cmd.va) {
4032baaa08d1SVasundhara Volam 		dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
4033baaa08d1SVasundhara Volam 			__func__);
4034baaa08d1SVasundhara Volam 		goto err;
4035baaa08d1SVasundhara Volam 	}
4036baaa08d1SVasundhara Volam 
4037baaa08d1SVasundhara Volam 	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
4038baaa08d1SVasundhara Volam 	if (!status) {
4039baaa08d1SVasundhara Volam 		cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
4040baaa08d1SVasundhara Volam 						sizeof(struct be_cmd_resp_hdr));
404103d28ffeSKalesh AP 
4042baaa08d1SVasundhara Volam 		for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) {
4043baaa08d1SVasundhara Volam 			if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
4044baaa08d1SVasundhara Volam 				level = cfgs->module[0].trace_lvl[j].dbg_lvl;
4045baaa08d1SVasundhara Volam 		}
4046baaa08d1SVasundhara Volam 	}
4047e51000dbSSriharsha Basavapatna 	dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va,
4048baaa08d1SVasundhara Volam 			  extfat_cmd.dma);
4049baaa08d1SVasundhara Volam err:
4050baaa08d1SVasundhara Volam 	return level;
4051baaa08d1SVasundhara Volam }
4052baaa08d1SVasundhara Volam 
4053941a77d5SSomnath Kotur int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
4054941a77d5SSomnath Kotur 				   struct be_dma_mem *cmd)
4055941a77d5SSomnath Kotur {
4056941a77d5SSomnath Kotur 	struct be_mcc_wrb *wrb;
4057941a77d5SSomnath Kotur 	struct be_cmd_req_get_ext_fat_caps *req;
4058941a77d5SSomnath Kotur 	int status;
4059941a77d5SSomnath Kotur 
4060941a77d5SSomnath Kotur 	if (mutex_lock_interruptible(&adapter->mbox_lock))
4061941a77d5SSomnath Kotur 		return -1;
4062941a77d5SSomnath Kotur 
4063941a77d5SSomnath Kotur 	wrb = wrb_from_mbox(adapter);
4064941a77d5SSomnath Kotur 	if (!wrb) {
4065941a77d5SSomnath Kotur 		status = -EBUSY;
4066941a77d5SSomnath Kotur 		goto err;
4067941a77d5SSomnath Kotur 	}
4068941a77d5SSomnath Kotur 
4069941a77d5SSomnath Kotur 	req = cmd->va;
4070941a77d5SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4071941a77d5SSomnath Kotur 			       OPCODE_COMMON_GET_EXT_FAT_CAPABILITES,
4072941a77d5SSomnath Kotur 			       cmd->size, wrb, cmd);
4073941a77d5SSomnath Kotur 	req->parameter_type = cpu_to_le32(1);
4074941a77d5SSomnath Kotur 
4075941a77d5SSomnath Kotur 	status = be_mbox_notify_wait(adapter);
4076941a77d5SSomnath Kotur err:
4077941a77d5SSomnath Kotur 	mutex_unlock(&adapter->mbox_lock);
4078941a77d5SSomnath Kotur 	return status;
4079941a77d5SSomnath Kotur }
4080941a77d5SSomnath Kotur 
4081941a77d5SSomnath Kotur int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
4082941a77d5SSomnath Kotur 				   struct be_dma_mem *cmd,
4083941a77d5SSomnath Kotur 				   struct be_fat_conf_params *configs)
4084941a77d5SSomnath Kotur {
4085941a77d5SSomnath Kotur 	struct be_mcc_wrb *wrb;
4086941a77d5SSomnath Kotur 	struct be_cmd_req_set_ext_fat_caps *req;
4087941a77d5SSomnath Kotur 	int status;
4088941a77d5SSomnath Kotur 
4089941a77d5SSomnath Kotur 	spin_lock_bh(&adapter->mcc_lock);
4090941a77d5SSomnath Kotur 
4091941a77d5SSomnath Kotur 	wrb = wrb_from_mccq(adapter);
4092941a77d5SSomnath Kotur 	if (!wrb) {
4093941a77d5SSomnath Kotur 		status = -EBUSY;
4094941a77d5SSomnath Kotur 		goto err;
4095941a77d5SSomnath Kotur 	}
4096941a77d5SSomnath Kotur 
4097941a77d5SSomnath Kotur 	req = cmd->va;
4098941a77d5SSomnath Kotur 	memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params));
4099941a77d5SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4100941a77d5SSomnath Kotur 			       OPCODE_COMMON_SET_EXT_FAT_CAPABILITES,
4101941a77d5SSomnath Kotur 			       cmd->size, wrb, cmd);
4102941a77d5SSomnath Kotur 
4103941a77d5SSomnath Kotur 	status = be_mcc_notify_wait(adapter);
4104941a77d5SSomnath Kotur err:
4105941a77d5SSomnath Kotur 	spin_unlock_bh(&adapter->mcc_lock);
4106941a77d5SSomnath Kotur 	return status;
41074762f6ceSAjit Khaparde }
41086a4ab669SParav Pandit 
410921252377SVasundhara Volam int be_cmd_query_port_name(struct be_adapter *adapter)
4110b4e32a71SPadmanabh Ratnakar {
4111b4e32a71SPadmanabh Ratnakar 	struct be_cmd_req_get_port_name *req;
411221252377SVasundhara Volam 	struct be_mcc_wrb *wrb;
4113b4e32a71SPadmanabh Ratnakar 	int status;
4114b4e32a71SPadmanabh Ratnakar 
411521252377SVasundhara Volam 	if (mutex_lock_interruptible(&adapter->mbox_lock))
411621252377SVasundhara Volam 		return -1;
4117b4e32a71SPadmanabh Ratnakar 
411821252377SVasundhara Volam 	wrb = wrb_from_mbox(adapter);
4119b4e32a71SPadmanabh Ratnakar 	req = embedded_payload(wrb);
4120b4e32a71SPadmanabh Ratnakar 
4121b4e32a71SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4122b4e32a71SPadmanabh Ratnakar 			       OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb,
4123b4e32a71SPadmanabh Ratnakar 			       NULL);
412421252377SVasundhara Volam 	if (!BEx_chip(adapter))
4125b4e32a71SPadmanabh Ratnakar 		req->hdr.version = 1;
4126b4e32a71SPadmanabh Ratnakar 
412721252377SVasundhara Volam 	status = be_mbox_notify_wait(adapter);
4128b4e32a71SPadmanabh Ratnakar 	if (!status) {
4129b4e32a71SPadmanabh Ratnakar 		struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb);
413003d28ffeSKalesh AP 
413121252377SVasundhara Volam 		adapter->port_name = resp->port_name[adapter->hba_port_num];
4132b4e32a71SPadmanabh Ratnakar 	} else {
413321252377SVasundhara Volam 		adapter->port_name = adapter->hba_port_num + '0';
4134b4e32a71SPadmanabh Ratnakar 	}
413521252377SVasundhara Volam 
413621252377SVasundhara Volam 	mutex_unlock(&adapter->mbox_lock);
4137b4e32a71SPadmanabh Ratnakar 	return status;
4138b4e32a71SPadmanabh Ratnakar }
4139b4e32a71SPadmanabh Ratnakar 
4140980df249SSuresh Reddy /* When more than 1 NIC descriptor is present in the descriptor list,
4141980df249SSuresh Reddy  * the caller must specify the pf_num to obtain the NIC descriptor
4142980df249SSuresh Reddy  * corresponding to its pci function.
4143980df249SSuresh Reddy  * get_vft must be true when the caller wants the VF-template desc of the
4144980df249SSuresh Reddy  * PF-pool.
4145980df249SSuresh Reddy  * The pf_num should be set to PF_NUM_IGNORE when the caller knows
4146980df249SSuresh Reddy  * that only it's NIC descriptor is present in the descriptor list.
4147980df249SSuresh Reddy  */
414810cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
4149980df249SSuresh Reddy 					       bool get_vft, u8 pf_num)
4150abb93951SPadmanabh Ratnakar {
4151150d58c7SVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
415210cccf60SVasundhara Volam 	struct be_nic_res_desc *nic;
4153abb93951SPadmanabh Ratnakar 	int i;
4154abb93951SPadmanabh Ratnakar 
4155abb93951SPadmanabh Ratnakar 	for (i = 0; i < desc_count; i++) {
4156150d58c7SVasundhara Volam 		if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
415710cccf60SVasundhara Volam 		    hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) {
415810cccf60SVasundhara Volam 			nic = (struct be_nic_res_desc *)hdr;
4159980df249SSuresh Reddy 
4160980df249SSuresh Reddy 			if ((pf_num == PF_NUM_IGNORE ||
4161980df249SSuresh Reddy 			     nic->pf_num == pf_num) &&
4162980df249SSuresh Reddy 			    (!get_vft || nic->flags & BIT(VFT_SHIFT)))
416310cccf60SVasundhara Volam 				return nic;
416410cccf60SVasundhara Volam 		}
4165150d58c7SVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
4166150d58c7SVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
4167150d58c7SVasundhara Volam 	}
4168950e2958SWei Yang 	return NULL;
4169abb93951SPadmanabh Ratnakar }
4170abb93951SPadmanabh Ratnakar 
4171980df249SSuresh Reddy static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count,
4172980df249SSuresh Reddy 					       u8 pf_num)
417310cccf60SVasundhara Volam {
4174980df249SSuresh Reddy 	return be_get_nic_desc(buf, desc_count, true, pf_num);
417510cccf60SVasundhara Volam }
417610cccf60SVasundhara Volam 
4177980df249SSuresh Reddy static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count,
4178980df249SSuresh Reddy 						    u8 pf_num)
417910cccf60SVasundhara Volam {
4180980df249SSuresh Reddy 	return be_get_nic_desc(buf, desc_count, false, pf_num);
418110cccf60SVasundhara Volam }
418210cccf60SVasundhara Volam 
4183980df249SSuresh Reddy static struct be_pcie_res_desc *be_get_pcie_desc(u8 *buf, u32 desc_count,
4184980df249SSuresh Reddy 						 u8 pf_num)
4185150d58c7SVasundhara Volam {
4186150d58c7SVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
4187150d58c7SVasundhara Volam 	struct be_pcie_res_desc *pcie;
4188150d58c7SVasundhara Volam 	int i;
4189150d58c7SVasundhara Volam 
4190150d58c7SVasundhara Volam 	for (i = 0; i < desc_count; i++) {
4191980df249SSuresh Reddy 		if (hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 ||
4192980df249SSuresh Reddy 		    hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1) {
4193150d58c7SVasundhara Volam 			pcie = (struct be_pcie_res_desc *)hdr;
4194980df249SSuresh Reddy 			if (pcie->pf_num == pf_num)
4195150d58c7SVasundhara Volam 				return pcie;
4196150d58c7SVasundhara Volam 		}
4197150d58c7SVasundhara Volam 
4198150d58c7SVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
4199150d58c7SVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
4200150d58c7SVasundhara Volam 	}
4201abb93951SPadmanabh Ratnakar 	return NULL;
4202abb93951SPadmanabh Ratnakar }
4203abb93951SPadmanabh Ratnakar 
4204f93f160bSVasundhara Volam static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
4205f93f160bSVasundhara Volam {
4206f93f160bSVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
4207f93f160bSVasundhara Volam 	int i;
4208f93f160bSVasundhara Volam 
4209f93f160bSVasundhara Volam 	for (i = 0; i < desc_count; i++) {
4210f93f160bSVasundhara Volam 		if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
4211f93f160bSVasundhara Volam 			return (struct be_port_res_desc *)hdr;
4212f93f160bSVasundhara Volam 
4213f93f160bSVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
4214f93f160bSVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
4215f93f160bSVasundhara Volam 	}
4216f93f160bSVasundhara Volam 	return NULL;
4217f93f160bSVasundhara Volam }
4218f93f160bSVasundhara Volam 
421992bf14abSSathya Perla static void be_copy_nic_desc(struct be_resources *res,
422092bf14abSSathya Perla 			     struct be_nic_res_desc *desc)
422192bf14abSSathya Perla {
422292bf14abSSathya Perla 	res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count);
422392bf14abSSathya Perla 	res->max_vlans = le16_to_cpu(desc->vlan_count);
422492bf14abSSathya Perla 	res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
422592bf14abSSathya Perla 	res->max_tx_qs = le16_to_cpu(desc->txq_count);
422692bf14abSSathya Perla 	res->max_rss_qs = le16_to_cpu(desc->rssq_count);
422792bf14abSSathya Perla 	res->max_rx_qs = le16_to_cpu(desc->rq_count);
422892bf14abSSathya Perla 	res->max_evt_qs = le16_to_cpu(desc->eq_count);
4229f2858738SVasundhara Volam 	res->max_cq_count = le16_to_cpu(desc->cq_count);
4230f2858738SVasundhara Volam 	res->max_iface_count = le16_to_cpu(desc->iface_count);
4231f2858738SVasundhara Volam 	res->max_mcc_count = le16_to_cpu(desc->mcc_count);
423292bf14abSSathya Perla 	/* Clear flags that driver is not interested in */
423392bf14abSSathya Perla 	res->if_cap_flags = le32_to_cpu(desc->cap_flags) &
423492bf14abSSathya Perla 				BE_IF_CAP_FLAGS_WANT;
423592bf14abSSathya Perla }
423692bf14abSSathya Perla 
4237abb93951SPadmanabh Ratnakar /* Uses Mbox */
423892bf14abSSathya Perla int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
4239abb93951SPadmanabh Ratnakar {
4240abb93951SPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
4241abb93951SPadmanabh Ratnakar 	struct be_cmd_req_get_func_config *req;
4242abb93951SPadmanabh Ratnakar 	int status;
4243abb93951SPadmanabh Ratnakar 	struct be_dma_mem cmd;
4244abb93951SPadmanabh Ratnakar 
4245d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
4246d98ef50fSSuresh Reddy 		return -1;
4247d98ef50fSSuresh Reddy 
4248abb93951SPadmanabh Ratnakar 	memset(&cmd, 0, sizeof(struct be_dma_mem));
4249abb93951SPadmanabh Ratnakar 	cmd.size = sizeof(struct be_cmd_resp_get_func_config);
4250e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
4251e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
4252abb93951SPadmanabh Ratnakar 	if (!cmd.va) {
4253abb93951SPadmanabh Ratnakar 		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
4254d98ef50fSSuresh Reddy 		status = -ENOMEM;
4255d98ef50fSSuresh Reddy 		goto err;
4256abb93951SPadmanabh Ratnakar 	}
4257abb93951SPadmanabh Ratnakar 
4258abb93951SPadmanabh Ratnakar 	wrb = wrb_from_mbox(adapter);
4259abb93951SPadmanabh Ratnakar 	if (!wrb) {
4260abb93951SPadmanabh Ratnakar 		status = -EBUSY;
4261abb93951SPadmanabh Ratnakar 		goto err;
4262abb93951SPadmanabh Ratnakar 	}
4263abb93951SPadmanabh Ratnakar 
4264abb93951SPadmanabh Ratnakar 	req = cmd.va;
4265abb93951SPadmanabh Ratnakar 
4266abb93951SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4267abb93951SPadmanabh Ratnakar 			       OPCODE_COMMON_GET_FUNC_CONFIG,
4268abb93951SPadmanabh Ratnakar 			       cmd.size, wrb, &cmd);
4269abb93951SPadmanabh Ratnakar 
427028710c55SKalesh AP 	if (skyhawk_chip(adapter))
427128710c55SKalesh AP 		req->hdr.version = 1;
427228710c55SKalesh AP 
4273abb93951SPadmanabh Ratnakar 	status = be_mbox_notify_wait(adapter);
4274abb93951SPadmanabh Ratnakar 	if (!status) {
4275abb93951SPadmanabh Ratnakar 		struct be_cmd_resp_get_func_config *resp = cmd.va;
4276abb93951SPadmanabh Ratnakar 		u32 desc_count = le32_to_cpu(resp->desc_count);
4277150d58c7SVasundhara Volam 		struct be_nic_res_desc *desc;
4278abb93951SPadmanabh Ratnakar 
4279980df249SSuresh Reddy 		/* GET_FUNC_CONFIG returns resource descriptors of the
4280980df249SSuresh Reddy 		 * current function only. So, pf_num should be set to
4281980df249SSuresh Reddy 		 * PF_NUM_IGNORE.
4282980df249SSuresh Reddy 		 */
4283980df249SSuresh Reddy 		desc = be_get_func_nic_desc(resp->func_param, desc_count,
4284980df249SSuresh Reddy 					    PF_NUM_IGNORE);
4285abb93951SPadmanabh Ratnakar 		if (!desc) {
4286abb93951SPadmanabh Ratnakar 			status = -EINVAL;
4287abb93951SPadmanabh Ratnakar 			goto err;
4288abb93951SPadmanabh Ratnakar 		}
4289980df249SSuresh Reddy 
4290980df249SSuresh Reddy 		/* Store pf_num & vf_num for later use in GET_PROFILE_CONFIG */
4291980df249SSuresh Reddy 		adapter->pf_num = desc->pf_num;
4292980df249SSuresh Reddy 		adapter->vf_num = desc->vf_num;
4293980df249SSuresh Reddy 
4294980df249SSuresh Reddy 		if (res)
429592bf14abSSathya Perla 			be_copy_nic_desc(res, desc);
4296abb93951SPadmanabh Ratnakar 	}
4297abb93951SPadmanabh Ratnakar err:
4298abb93951SPadmanabh Ratnakar 	mutex_unlock(&adapter->mbox_lock);
4299d98ef50fSSuresh Reddy 	if (cmd.va)
4300e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
4301e51000dbSSriharsha Basavapatna 				  cmd.dma);
4302abb93951SPadmanabh Ratnakar 	return status;
4303abb93951SPadmanabh Ratnakar }
4304abb93951SPadmanabh Ratnakar 
4305980df249SSuresh Reddy /* Will use MBOX only if MCCQ has not been created */
430692bf14abSSathya Perla int be_cmd_get_profile_config(struct be_adapter *adapter,
4307f2858738SVasundhara Volam 			      struct be_resources *res, u8 query, u8 domain)
4308a05f99dbSVasundhara Volam {
4309150d58c7SVasundhara Volam 	struct be_cmd_resp_get_profile_config *resp;
4310ba48c0c9SVasundhara Volam 	struct be_cmd_req_get_profile_config *req;
431110cccf60SVasundhara Volam 	struct be_nic_res_desc *vf_res;
4312150d58c7SVasundhara Volam 	struct be_pcie_res_desc *pcie;
4313f93f160bSVasundhara Volam 	struct be_port_res_desc *port;
4314150d58c7SVasundhara Volam 	struct be_nic_res_desc *nic;
4315ba48c0c9SVasundhara Volam 	struct be_mcc_wrb wrb = {0};
4316a05f99dbSVasundhara Volam 	struct be_dma_mem cmd;
4317f2858738SVasundhara Volam 	u16 desc_count;
4318a05f99dbSVasundhara Volam 	int status;
4319a05f99dbSVasundhara Volam 
4320a05f99dbSVasundhara Volam 	memset(&cmd, 0, sizeof(struct be_dma_mem));
4321a05f99dbSVasundhara Volam 	cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
4322e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
4323e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
4324150d58c7SVasundhara Volam 	if (!cmd.va)
4325a05f99dbSVasundhara Volam 		return -ENOMEM;
4326a05f99dbSVasundhara Volam 
4327ba48c0c9SVasundhara Volam 	req = cmd.va;
4328ba48c0c9SVasundhara Volam 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4329ba48c0c9SVasundhara Volam 			       OPCODE_COMMON_GET_PROFILE_CONFIG,
4330ba48c0c9SVasundhara Volam 			       cmd.size, &wrb, &cmd);
4331ba48c0c9SVasundhara Volam 
4332ba48c0c9SVasundhara Volam 	if (!lancer_chip(adapter))
4333ba48c0c9SVasundhara Volam 		req->hdr.version = 1;
4334ba48c0c9SVasundhara Volam 	req->type = ACTIVE_PROFILE_TYPE;
433572ef3a88SSomnath Kotur 	req->hdr.domain = domain;
4336ba48c0c9SVasundhara Volam 
4337f2858738SVasundhara Volam 	/* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the
4338f2858738SVasundhara Volam 	 * descriptors with all bits set to "1" for the fields which can be
4339f2858738SVasundhara Volam 	 * modified using SET_PROFILE_CONFIG cmd.
4340f2858738SVasundhara Volam 	 */
4341f2858738SVasundhara Volam 	if (query == RESOURCE_MODIFIABLE)
4342f2858738SVasundhara Volam 		req->type |= QUERY_MODIFIABLE_FIELDS_TYPE;
4343f2858738SVasundhara Volam 
4344ba48c0c9SVasundhara Volam 	status = be_cmd_notify_wait(adapter, &wrb);
4345150d58c7SVasundhara Volam 	if (status)
4346abb93951SPadmanabh Ratnakar 		goto err;
4347150d58c7SVasundhara Volam 
4348150d58c7SVasundhara Volam 	resp = cmd.va;
4349f2858738SVasundhara Volam 	desc_count = le16_to_cpu(resp->desc_count);
4350150d58c7SVasundhara Volam 
4351980df249SSuresh Reddy 	pcie = be_get_pcie_desc(resp->func_param, desc_count,
4352980df249SSuresh Reddy 				adapter->pf_num);
4353150d58c7SVasundhara Volam 	if (pcie)
435492bf14abSSathya Perla 		res->max_vfs = le16_to_cpu(pcie->num_vfs);
4355150d58c7SVasundhara Volam 
4356f93f160bSVasundhara Volam 	port = be_get_port_desc(resp->func_param, desc_count);
4357f93f160bSVasundhara Volam 	if (port)
4358f93f160bSVasundhara Volam 		adapter->mc_type = port->mc_type;
4359f93f160bSVasundhara Volam 
4360980df249SSuresh Reddy 	nic = be_get_func_nic_desc(resp->func_param, desc_count,
4361980df249SSuresh Reddy 				   adapter->pf_num);
436292bf14abSSathya Perla 	if (nic)
436392bf14abSSathya Perla 		be_copy_nic_desc(res, nic);
436492bf14abSSathya Perla 
4365980df249SSuresh Reddy 	vf_res = be_get_vft_desc(resp->func_param, desc_count,
4366980df249SSuresh Reddy 				 adapter->pf_num);
436710cccf60SVasundhara Volam 	if (vf_res)
436810cccf60SVasundhara Volam 		res->vf_if_cap_flags = vf_res->cap_flags;
4369abb93951SPadmanabh Ratnakar err:
4370a05f99dbSVasundhara Volam 	if (cmd.va)
4371e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
4372e51000dbSSriharsha Basavapatna 				  cmd.dma);
4373abb93951SPadmanabh Ratnakar 	return status;
4374abb93951SPadmanabh Ratnakar }
4375abb93951SPadmanabh Ratnakar 
4376bec84e6bSVasundhara Volam /* Will use MBOX only if MCCQ has not been created */
4377bec84e6bSVasundhara Volam static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
4378bec84e6bSVasundhara Volam 				     int size, int count, u8 version, u8 domain)
4379d5c18473SPadmanabh Ratnakar {
4380d5c18473SPadmanabh Ratnakar 	struct be_cmd_req_set_profile_config *req;
4381bec84e6bSVasundhara Volam 	struct be_mcc_wrb wrb = {0};
4382bec84e6bSVasundhara Volam 	struct be_dma_mem cmd;
4383d5c18473SPadmanabh Ratnakar 	int status;
4384d5c18473SPadmanabh Ratnakar 
4385bec84e6bSVasundhara Volam 	memset(&cmd, 0, sizeof(struct be_dma_mem));
4386bec84e6bSVasundhara Volam 	cmd.size = sizeof(struct be_cmd_req_set_profile_config);
4387e51000dbSSriharsha Basavapatna 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
4388e51000dbSSriharsha Basavapatna 				     GFP_ATOMIC);
4389bec84e6bSVasundhara Volam 	if (!cmd.va)
4390bec84e6bSVasundhara Volam 		return -ENOMEM;
4391d5c18473SPadmanabh Ratnakar 
4392bec84e6bSVasundhara Volam 	req = cmd.va;
4393d5c18473SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4394bec84e6bSVasundhara Volam 			       OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size,
4395bec84e6bSVasundhara Volam 			       &wrb, &cmd);
4396a401801cSSathya Perla 	req->hdr.version = version;
4397d5c18473SPadmanabh Ratnakar 	req->hdr.domain = domain;
4398bec84e6bSVasundhara Volam 	req->desc_count = cpu_to_le32(count);
4399a401801cSSathya Perla 	memcpy(req->desc, desc, size);
4400d5c18473SPadmanabh Ratnakar 
4401bec84e6bSVasundhara Volam 	status = be_cmd_notify_wait(adapter, &wrb);
4402bec84e6bSVasundhara Volam 
4403bec84e6bSVasundhara Volam 	if (cmd.va)
4404e51000dbSSriharsha Basavapatna 		dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
4405e51000dbSSriharsha Basavapatna 				  cmd.dma);
4406d5c18473SPadmanabh Ratnakar 	return status;
4407d5c18473SPadmanabh Ratnakar }
4408d5c18473SPadmanabh Ratnakar 
4409a401801cSSathya Perla /* Mark all fields invalid */
4410bec84e6bSVasundhara Volam static void be_reset_nic_desc(struct be_nic_res_desc *nic)
4411a401801cSSathya Perla {
4412a401801cSSathya Perla 	memset(nic, 0, sizeof(*nic));
4413a401801cSSathya Perla 	nic->unicast_mac_count = 0xFFFF;
4414a401801cSSathya Perla 	nic->mcc_count = 0xFFFF;
4415a401801cSSathya Perla 	nic->vlan_count = 0xFFFF;
4416a401801cSSathya Perla 	nic->mcast_mac_count = 0xFFFF;
4417a401801cSSathya Perla 	nic->txq_count = 0xFFFF;
4418a401801cSSathya Perla 	nic->rq_count = 0xFFFF;
4419a401801cSSathya Perla 	nic->rssq_count = 0xFFFF;
4420a401801cSSathya Perla 	nic->lro_count = 0xFFFF;
4421a401801cSSathya Perla 	nic->cq_count = 0xFFFF;
4422a401801cSSathya Perla 	nic->toe_conn_count = 0xFFFF;
4423a401801cSSathya Perla 	nic->eq_count = 0xFFFF;
44240f77ba73SRavikumar Nelavelli 	nic->iface_count = 0xFFFF;
4425a401801cSSathya Perla 	nic->link_param = 0xFF;
44260f77ba73SRavikumar Nelavelli 	nic->channel_id_param = cpu_to_le16(0xF000);
4427a401801cSSathya Perla 	nic->acpi_params = 0xFF;
4428a401801cSSathya Perla 	nic->wol_param = 0x0F;
44290f77ba73SRavikumar Nelavelli 	nic->tunnel_iface_count = 0xFFFF;
44300f77ba73SRavikumar Nelavelli 	nic->direct_tenant_iface_count = 0xFFFF;
4431bec84e6bSVasundhara Volam 	nic->bw_min = 0xFFFFFFFF;
4432a401801cSSathya Perla 	nic->bw_max = 0xFFFFFFFF;
4433a401801cSSathya Perla }
4434a401801cSSathya Perla 
4435bec84e6bSVasundhara Volam /* Mark all fields invalid */
4436bec84e6bSVasundhara Volam static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie)
4437bec84e6bSVasundhara Volam {
4438bec84e6bSVasundhara Volam 	memset(pcie, 0, sizeof(*pcie));
4439bec84e6bSVasundhara Volam 	pcie->sriov_state = 0xFF;
4440bec84e6bSVasundhara Volam 	pcie->pf_state = 0xFF;
4441bec84e6bSVasundhara Volam 	pcie->pf_type = 0xFF;
4442bec84e6bSVasundhara Volam 	pcie->num_vfs = 0xFFFF;
4443bec84e6bSVasundhara Volam }
4444bec84e6bSVasundhara Volam 
44450f77ba73SRavikumar Nelavelli int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
44460f77ba73SRavikumar Nelavelli 		      u8 domain)
4447a401801cSSathya Perla {
4448a401801cSSathya Perla 	struct be_nic_res_desc nic_desc;
44490f77ba73SRavikumar Nelavelli 	u32 bw_percent;
44500f77ba73SRavikumar Nelavelli 	u16 version = 0;
44510f77ba73SRavikumar Nelavelli 
44520f77ba73SRavikumar Nelavelli 	if (BE3_chip(adapter))
44530f77ba73SRavikumar Nelavelli 		return be_cmd_set_qos(adapter, max_rate / 10, domain);
4454a401801cSSathya Perla 
4455a401801cSSathya Perla 	be_reset_nic_desc(&nic_desc);
4456980df249SSuresh Reddy 	nic_desc.pf_num = adapter->pf_num;
44570f77ba73SRavikumar Nelavelli 	nic_desc.vf_num = domain;
445858bdeaa6SKalesh AP 	nic_desc.bw_min = 0;
44590f77ba73SRavikumar Nelavelli 	if (lancer_chip(adapter)) {
4460a401801cSSathya Perla 		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
4461a401801cSSathya Perla 		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
4462a401801cSSathya Perla 		nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
4463a401801cSSathya Perla 					(1 << NOSV_SHIFT);
44640f77ba73SRavikumar Nelavelli 		nic_desc.bw_max = cpu_to_le32(max_rate / 10);
44650f77ba73SRavikumar Nelavelli 	} else {
44660f77ba73SRavikumar Nelavelli 		version = 1;
44670f77ba73SRavikumar Nelavelli 		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
44680f77ba73SRavikumar Nelavelli 		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
44690f77ba73SRavikumar Nelavelli 		nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
44700f77ba73SRavikumar Nelavelli 		bw_percent = max_rate ? (max_rate * 100) / link_speed : 100;
44710f77ba73SRavikumar Nelavelli 		nic_desc.bw_max = cpu_to_le32(bw_percent);
44720f77ba73SRavikumar Nelavelli 	}
4473a401801cSSathya Perla 
4474a401801cSSathya Perla 	return be_cmd_set_profile_config(adapter, &nic_desc,
44750f77ba73SRavikumar Nelavelli 					 nic_desc.hdr.desc_len,
4476bec84e6bSVasundhara Volam 					 1, version, domain);
4477bec84e6bSVasundhara Volam }
4478bec84e6bSVasundhara Volam 
4479f2858738SVasundhara Volam static void be_fill_vf_res_template(struct be_adapter *adapter,
4480f2858738SVasundhara Volam 				    struct be_resources pool_res,
4481f2858738SVasundhara Volam 				    u16 num_vfs, u16 num_vf_qs,
4482f2858738SVasundhara Volam 				    struct be_nic_res_desc *nic_vft)
4483f2858738SVasundhara Volam {
4484f2858738SVasundhara Volam 	u32 vf_if_cap_flags = pool_res.vf_if_cap_flags;
4485f2858738SVasundhara Volam 	struct be_resources res_mod = {0};
4486f2858738SVasundhara Volam 
4487f2858738SVasundhara Volam 	/* Resource with fields set to all '1's by GET_PROFILE_CONFIG cmd,
4488f2858738SVasundhara Volam 	 * which are modifiable using SET_PROFILE_CONFIG cmd.
4489f2858738SVasundhara Volam 	 */
4490f2858738SVasundhara Volam 	be_cmd_get_profile_config(adapter, &res_mod, RESOURCE_MODIFIABLE, 0);
4491f2858738SVasundhara Volam 
4492f2858738SVasundhara Volam 	/* If RSS IFACE capability flags are modifiable for a VF, set the
4493f2858738SVasundhara Volam 	 * capability flag as valid and set RSS and DEFQ_RSS IFACE flags if
4494f2858738SVasundhara Volam 	 * more than 1 RSSQ is available for a VF.
4495f2858738SVasundhara Volam 	 * Otherwise, provision only 1 queue pair for VF.
4496f2858738SVasundhara Volam 	 */
4497f2858738SVasundhara Volam 	if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_RSS) {
4498f2858738SVasundhara Volam 		nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
4499f2858738SVasundhara Volam 		if (num_vf_qs > 1) {
4500f2858738SVasundhara Volam 			vf_if_cap_flags |= BE_IF_FLAGS_RSS;
4501f2858738SVasundhara Volam 			if (pool_res.if_cap_flags & BE_IF_FLAGS_DEFQ_RSS)
4502f2858738SVasundhara Volam 				vf_if_cap_flags |= BE_IF_FLAGS_DEFQ_RSS;
4503f2858738SVasundhara Volam 		} else {
4504f2858738SVasundhara Volam 			vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS |
4505f2858738SVasundhara Volam 					     BE_IF_FLAGS_DEFQ_RSS);
4506f2858738SVasundhara Volam 		}
4507f2858738SVasundhara Volam 	} else {
4508f2858738SVasundhara Volam 		num_vf_qs = 1;
4509f2858738SVasundhara Volam 	}
4510f2858738SVasundhara Volam 
4511196e3735SKalesh AP 	if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) {
4512196e3735SKalesh AP 		nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
4513196e3735SKalesh AP 		vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
4514196e3735SKalesh AP 	}
4515196e3735SKalesh AP 
4516196e3735SKalesh AP 	nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
4517f2858738SVasundhara Volam 	nic_vft->rq_count = cpu_to_le16(num_vf_qs);
4518f2858738SVasundhara Volam 	nic_vft->txq_count = cpu_to_le16(num_vf_qs);
4519f2858738SVasundhara Volam 	nic_vft->rssq_count = cpu_to_le16(num_vf_qs);
4520f2858738SVasundhara Volam 	nic_vft->cq_count = cpu_to_le16(pool_res.max_cq_count /
4521f2858738SVasundhara Volam 					(num_vfs + 1));
4522f2858738SVasundhara Volam 
4523f2858738SVasundhara Volam 	/* Distribute unicast MACs, VLANs, IFACE count and MCCQ count equally
4524f2858738SVasundhara Volam 	 * among the PF and it's VFs, if the fields are changeable
4525f2858738SVasundhara Volam 	 */
4526f2858738SVasundhara Volam 	if (res_mod.max_uc_mac == FIELD_MODIFIABLE)
4527f2858738SVasundhara Volam 		nic_vft->unicast_mac_count = cpu_to_le16(pool_res.max_uc_mac /
4528f2858738SVasundhara Volam 							 (num_vfs + 1));
4529f2858738SVasundhara Volam 
4530f2858738SVasundhara Volam 	if (res_mod.max_vlans == FIELD_MODIFIABLE)
4531f2858738SVasundhara Volam 		nic_vft->vlan_count = cpu_to_le16(pool_res.max_vlans /
4532f2858738SVasundhara Volam 						  (num_vfs + 1));
4533f2858738SVasundhara Volam 
4534f2858738SVasundhara Volam 	if (res_mod.max_iface_count == FIELD_MODIFIABLE)
4535f2858738SVasundhara Volam 		nic_vft->iface_count = cpu_to_le16(pool_res.max_iface_count /
4536f2858738SVasundhara Volam 						   (num_vfs + 1));
4537f2858738SVasundhara Volam 
4538f2858738SVasundhara Volam 	if (res_mod.max_mcc_count == FIELD_MODIFIABLE)
4539f2858738SVasundhara Volam 		nic_vft->mcc_count = cpu_to_le16(pool_res.max_mcc_count /
4540f2858738SVasundhara Volam 						 (num_vfs + 1));
4541f2858738SVasundhara Volam }
4542f2858738SVasundhara Volam 
4543bec84e6bSVasundhara Volam int be_cmd_set_sriov_config(struct be_adapter *adapter,
4544f2858738SVasundhara Volam 			    struct be_resources pool_res, u16 num_vfs,
4545f2858738SVasundhara Volam 			    u16 num_vf_qs)
4546bec84e6bSVasundhara Volam {
4547bec84e6bSVasundhara Volam 	struct {
4548bec84e6bSVasundhara Volam 		struct be_pcie_res_desc pcie;
4549bec84e6bSVasundhara Volam 		struct be_nic_res_desc nic_vft;
4550bec84e6bSVasundhara Volam 	} __packed desc;
4551bec84e6bSVasundhara Volam 
4552bec84e6bSVasundhara Volam 	/* PF PCIE descriptor */
4553bec84e6bSVasundhara Volam 	be_reset_pcie_desc(&desc.pcie);
4554bec84e6bSVasundhara Volam 	desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1;
4555bec84e6bSVasundhara Volam 	desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
4556f2858738SVasundhara Volam 	desc.pcie.flags = BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
4557bec84e6bSVasundhara Volam 	desc.pcie.pf_num = adapter->pdev->devfn;
4558bec84e6bSVasundhara Volam 	desc.pcie.sriov_state = num_vfs ? 1 : 0;
4559bec84e6bSVasundhara Volam 	desc.pcie.num_vfs = cpu_to_le16(num_vfs);
4560bec84e6bSVasundhara Volam 
4561bec84e6bSVasundhara Volam 	/* VF NIC Template descriptor */
4562bec84e6bSVasundhara Volam 	be_reset_nic_desc(&desc.nic_vft);
4563bec84e6bSVasundhara Volam 	desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
4564bec84e6bSVasundhara Volam 	desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
4565f2858738SVasundhara Volam 	desc.nic_vft.flags = BIT(VFT_SHIFT) | BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
4566bec84e6bSVasundhara Volam 	desc.nic_vft.pf_num = adapter->pdev->devfn;
4567bec84e6bSVasundhara Volam 	desc.nic_vft.vf_num = 0;
4568bec84e6bSVasundhara Volam 
4569f2858738SVasundhara Volam 	be_fill_vf_res_template(adapter, pool_res, num_vfs, num_vf_qs,
4570f2858738SVasundhara Volam 				&desc.nic_vft);
4571bec84e6bSVasundhara Volam 
4572bec84e6bSVasundhara Volam 	return be_cmd_set_profile_config(adapter, &desc,
4573bec84e6bSVasundhara Volam 					 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
4574a401801cSSathya Perla }
4575a401801cSSathya Perla 
4576a401801cSSathya Perla int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
4577a401801cSSathya Perla {
4578a401801cSSathya Perla 	struct be_mcc_wrb *wrb;
4579a401801cSSathya Perla 	struct be_cmd_req_manage_iface_filters *req;
4580a401801cSSathya Perla 	int status;
4581a401801cSSathya Perla 
4582a401801cSSathya Perla 	if (iface == 0xFFFFFFFF)
4583a401801cSSathya Perla 		return -1;
4584a401801cSSathya Perla 
4585a401801cSSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
4586a401801cSSathya Perla 
4587a401801cSSathya Perla 	wrb = wrb_from_mccq(adapter);
4588a401801cSSathya Perla 	if (!wrb) {
4589a401801cSSathya Perla 		status = -EBUSY;
4590a401801cSSathya Perla 		goto err;
4591a401801cSSathya Perla 	}
4592a401801cSSathya Perla 	req = embedded_payload(wrb);
4593a401801cSSathya Perla 
4594a401801cSSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4595a401801cSSathya Perla 			       OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req),
4596a401801cSSathya Perla 			       wrb, NULL);
4597a401801cSSathya Perla 	req->op = op;
4598a401801cSSathya Perla 	req->target_iface_id = cpu_to_le32(iface);
4599a401801cSSathya Perla 
4600a401801cSSathya Perla 	status = be_mcc_notify_wait(adapter);
4601a401801cSSathya Perla err:
4602a401801cSSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
4603a401801cSSathya Perla 	return status;
4604a401801cSSathya Perla }
4605a401801cSSathya Perla 
4606a401801cSSathya Perla int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port)
4607a401801cSSathya Perla {
4608a401801cSSathya Perla 	struct be_port_res_desc port_desc;
4609a401801cSSathya Perla 
4610a401801cSSathya Perla 	memset(&port_desc, 0, sizeof(port_desc));
4611a401801cSSathya Perla 	port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1;
4612a401801cSSathya Perla 	port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
4613a401801cSSathya Perla 	port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
4614a401801cSSathya Perla 	port_desc.link_num = adapter->hba_port_num;
4615a401801cSSathya Perla 	if (port) {
4616a401801cSSathya Perla 		port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) |
4617a401801cSSathya Perla 					(1 << RCVID_SHIFT);
4618a401801cSSathya Perla 		port_desc.nv_port = swab16(port);
4619a401801cSSathya Perla 	} else {
4620a401801cSSathya Perla 		port_desc.nv_flags = NV_TYPE_DISABLED;
4621a401801cSSathya Perla 		port_desc.nv_port = 0;
4622a401801cSSathya Perla 	}
4623a401801cSSathya Perla 
4624a401801cSSathya Perla 	return be_cmd_set_profile_config(adapter, &port_desc,
4625bec84e6bSVasundhara Volam 					 RESOURCE_DESC_SIZE_V1, 1, 1, 0);
4626a401801cSSathya Perla }
4627a401801cSSathya Perla 
46284c876616SSathya Perla int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
46294c876616SSathya Perla 		     int vf_num)
46304c876616SSathya Perla {
46314c876616SSathya Perla 	struct be_mcc_wrb *wrb;
46324c876616SSathya Perla 	struct be_cmd_req_get_iface_list *req;
46334c876616SSathya Perla 	struct be_cmd_resp_get_iface_list *resp;
46344c876616SSathya Perla 	int status;
46354c876616SSathya Perla 
46364c876616SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
46374c876616SSathya Perla 
46384c876616SSathya Perla 	wrb = wrb_from_mccq(adapter);
46394c876616SSathya Perla 	if (!wrb) {
46404c876616SSathya Perla 		status = -EBUSY;
46414c876616SSathya Perla 		goto err;
46424c876616SSathya Perla 	}
46434c876616SSathya Perla 	req = embedded_payload(wrb);
46444c876616SSathya Perla 
46454c876616SSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
46464c876616SSathya Perla 			       OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp),
46474c876616SSathya Perla 			       wrb, NULL);
46484c876616SSathya Perla 	req->hdr.domain = vf_num + 1;
46494c876616SSathya Perla 
46504c876616SSathya Perla 	status = be_mcc_notify_wait(adapter);
46514c876616SSathya Perla 	if (!status) {
46524c876616SSathya Perla 		resp = (struct be_cmd_resp_get_iface_list *)req;
46534c876616SSathya Perla 		vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id);
46544c876616SSathya Perla 	}
46554c876616SSathya Perla 
46564c876616SSathya Perla err:
46574c876616SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
46584c876616SSathya Perla 	return status;
46594c876616SSathya Perla }
46604c876616SSathya Perla 
46615c510811SSomnath Kotur static int lancer_wait_idle(struct be_adapter *adapter)
46625c510811SSomnath Kotur {
46635c510811SSomnath Kotur #define SLIPORT_IDLE_TIMEOUT 30
46645c510811SSomnath Kotur 	u32 reg_val;
46655c510811SSomnath Kotur 	int status = 0, i;
46665c510811SSomnath Kotur 
46675c510811SSomnath Kotur 	for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
46685c510811SSomnath Kotur 		reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
46695c510811SSomnath Kotur 		if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
46705c510811SSomnath Kotur 			break;
46715c510811SSomnath Kotur 
46725c510811SSomnath Kotur 		ssleep(1);
46735c510811SSomnath Kotur 	}
46745c510811SSomnath Kotur 
46755c510811SSomnath Kotur 	if (i == SLIPORT_IDLE_TIMEOUT)
46765c510811SSomnath Kotur 		status = -1;
46775c510811SSomnath Kotur 
46785c510811SSomnath Kotur 	return status;
46795c510811SSomnath Kotur }
46805c510811SSomnath Kotur 
46815c510811SSomnath Kotur int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
46825c510811SSomnath Kotur {
46835c510811SSomnath Kotur 	int status = 0;
46845c510811SSomnath Kotur 
46855c510811SSomnath Kotur 	status = lancer_wait_idle(adapter);
46865c510811SSomnath Kotur 	if (status)
46875c510811SSomnath Kotur 		return status;
46885c510811SSomnath Kotur 
46895c510811SSomnath Kotur 	iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
46905c510811SSomnath Kotur 
46915c510811SSomnath Kotur 	return status;
46925c510811SSomnath Kotur }
46935c510811SSomnath Kotur 
46945c510811SSomnath Kotur /* Routine to check whether dump image is present or not */
46955c510811SSomnath Kotur bool dump_present(struct be_adapter *adapter)
46965c510811SSomnath Kotur {
46975c510811SSomnath Kotur 	u32 sliport_status = 0;
46985c510811SSomnath Kotur 
46995c510811SSomnath Kotur 	sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
47005c510811SSomnath Kotur 	return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
47015c510811SSomnath Kotur }
47025c510811SSomnath Kotur 
47035c510811SSomnath Kotur int lancer_initiate_dump(struct be_adapter *adapter)
47045c510811SSomnath Kotur {
4705f0613380SKalesh AP 	struct device *dev = &adapter->pdev->dev;
47065c510811SSomnath Kotur 	int status;
47075c510811SSomnath Kotur 
4708f0613380SKalesh AP 	if (dump_present(adapter)) {
4709f0613380SKalesh AP 		dev_info(dev, "Previous dump not cleared, not forcing dump\n");
4710f0613380SKalesh AP 		return -EEXIST;
4711f0613380SKalesh AP 	}
4712f0613380SKalesh AP 
47135c510811SSomnath Kotur 	/* give firmware reset and diagnostic dump */
47145c510811SSomnath Kotur 	status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
47155c510811SSomnath Kotur 				     PHYSDEV_CONTROL_DD_MASK);
47165c510811SSomnath Kotur 	if (status < 0) {
4717f0613380SKalesh AP 		dev_err(dev, "FW reset failed\n");
47185c510811SSomnath Kotur 		return status;
47195c510811SSomnath Kotur 	}
47205c510811SSomnath Kotur 
47215c510811SSomnath Kotur 	status = lancer_wait_idle(adapter);
47225c510811SSomnath Kotur 	if (status)
47235c510811SSomnath Kotur 		return status;
47245c510811SSomnath Kotur 
47255c510811SSomnath Kotur 	if (!dump_present(adapter)) {
4726f0613380SKalesh AP 		dev_err(dev, "FW dump not generated\n");
4727f0613380SKalesh AP 		return -EIO;
47285c510811SSomnath Kotur 	}
47295c510811SSomnath Kotur 
47305c510811SSomnath Kotur 	return 0;
47315c510811SSomnath Kotur }
47325c510811SSomnath Kotur 
4733f0613380SKalesh AP int lancer_delete_dump(struct be_adapter *adapter)
4734f0613380SKalesh AP {
4735f0613380SKalesh AP 	int status;
4736f0613380SKalesh AP 
4737f0613380SKalesh AP 	status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE);
4738f0613380SKalesh AP 	return be_cmd_status(status);
4739f0613380SKalesh AP }
4740f0613380SKalesh AP 
4741dcf7ebbaSPadmanabh Ratnakar /* Uses sync mcc */
4742dcf7ebbaSPadmanabh Ratnakar int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
4743dcf7ebbaSPadmanabh Ratnakar {
4744dcf7ebbaSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
4745dcf7ebbaSPadmanabh Ratnakar 	struct be_cmd_enable_disable_vf *req;
4746dcf7ebbaSPadmanabh Ratnakar 	int status;
4747dcf7ebbaSPadmanabh Ratnakar 
47480599863dSVasundhara Volam 	if (BEx_chip(adapter))
4749dcf7ebbaSPadmanabh Ratnakar 		return 0;
4750dcf7ebbaSPadmanabh Ratnakar 
4751dcf7ebbaSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
4752dcf7ebbaSPadmanabh Ratnakar 
4753dcf7ebbaSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
4754dcf7ebbaSPadmanabh Ratnakar 	if (!wrb) {
4755dcf7ebbaSPadmanabh Ratnakar 		status = -EBUSY;
4756dcf7ebbaSPadmanabh Ratnakar 		goto err;
4757dcf7ebbaSPadmanabh Ratnakar 	}
4758dcf7ebbaSPadmanabh Ratnakar 
4759dcf7ebbaSPadmanabh Ratnakar 	req = embedded_payload(wrb);
4760dcf7ebbaSPadmanabh Ratnakar 
4761dcf7ebbaSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4762dcf7ebbaSPadmanabh Ratnakar 			       OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
4763dcf7ebbaSPadmanabh Ratnakar 			       wrb, NULL);
4764dcf7ebbaSPadmanabh Ratnakar 
4765dcf7ebbaSPadmanabh Ratnakar 	req->hdr.domain = domain;
4766dcf7ebbaSPadmanabh Ratnakar 	req->enable = 1;
4767dcf7ebbaSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
4768dcf7ebbaSPadmanabh Ratnakar err:
4769dcf7ebbaSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
4770dcf7ebbaSPadmanabh Ratnakar 	return status;
4771dcf7ebbaSPadmanabh Ratnakar }
4772dcf7ebbaSPadmanabh Ratnakar 
477368c45a2dSSomnath Kotur int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable)
477468c45a2dSSomnath Kotur {
477568c45a2dSSomnath Kotur 	struct be_mcc_wrb *wrb;
477668c45a2dSSomnath Kotur 	struct be_cmd_req_intr_set *req;
477768c45a2dSSomnath Kotur 	int status;
477868c45a2dSSomnath Kotur 
477968c45a2dSSomnath Kotur 	if (mutex_lock_interruptible(&adapter->mbox_lock))
478068c45a2dSSomnath Kotur 		return -1;
478168c45a2dSSomnath Kotur 
478268c45a2dSSomnath Kotur 	wrb = wrb_from_mbox(adapter);
478368c45a2dSSomnath Kotur 
478468c45a2dSSomnath Kotur 	req = embedded_payload(wrb);
478568c45a2dSSomnath Kotur 
478668c45a2dSSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
478768c45a2dSSomnath Kotur 			       OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req),
478868c45a2dSSomnath Kotur 			       wrb, NULL);
478968c45a2dSSomnath Kotur 
479068c45a2dSSomnath Kotur 	req->intr_enabled = intr_enable;
479168c45a2dSSomnath Kotur 
479268c45a2dSSomnath Kotur 	status = be_mbox_notify_wait(adapter);
479368c45a2dSSomnath Kotur 
479468c45a2dSSomnath Kotur 	mutex_unlock(&adapter->mbox_lock);
479568c45a2dSSomnath Kotur 	return status;
479668c45a2dSSomnath Kotur }
479768c45a2dSSomnath Kotur 
4798542963b7SVasundhara Volam /* Uses MBOX */
4799542963b7SVasundhara Volam int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id)
4800542963b7SVasundhara Volam {
4801542963b7SVasundhara Volam 	struct be_cmd_req_get_active_profile *req;
4802542963b7SVasundhara Volam 	struct be_mcc_wrb *wrb;
4803542963b7SVasundhara Volam 	int status;
4804542963b7SVasundhara Volam 
4805542963b7SVasundhara Volam 	if (mutex_lock_interruptible(&adapter->mbox_lock))
4806542963b7SVasundhara Volam 		return -1;
4807542963b7SVasundhara Volam 
4808542963b7SVasundhara Volam 	wrb = wrb_from_mbox(adapter);
4809542963b7SVasundhara Volam 	if (!wrb) {
4810542963b7SVasundhara Volam 		status = -EBUSY;
4811542963b7SVasundhara Volam 		goto err;
4812542963b7SVasundhara Volam 	}
4813542963b7SVasundhara Volam 
4814542963b7SVasundhara Volam 	req = embedded_payload(wrb);
4815542963b7SVasundhara Volam 
4816542963b7SVasundhara Volam 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4817542963b7SVasundhara Volam 			       OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req),
4818542963b7SVasundhara Volam 			       wrb, NULL);
4819542963b7SVasundhara Volam 
4820542963b7SVasundhara Volam 	status = be_mbox_notify_wait(adapter);
4821542963b7SVasundhara Volam 	if (!status) {
4822542963b7SVasundhara Volam 		struct be_cmd_resp_get_active_profile *resp =
4823542963b7SVasundhara Volam 							embedded_payload(wrb);
482403d28ffeSKalesh AP 
4825542963b7SVasundhara Volam 		*profile_id = le16_to_cpu(resp->active_profile_id);
4826542963b7SVasundhara Volam 	}
4827542963b7SVasundhara Volam 
4828542963b7SVasundhara Volam err:
4829542963b7SVasundhara Volam 	mutex_unlock(&adapter->mbox_lock);
4830542963b7SVasundhara Volam 	return status;
4831542963b7SVasundhara Volam }
4832542963b7SVasundhara Volam 
4833d9d426afSSuresh Reddy int __be_cmd_set_logical_link_config(struct be_adapter *adapter,
4834d9d426afSSuresh Reddy 				     int link_state, int version, u8 domain)
4835bdce2ad7SSuresh Reddy {
4836bdce2ad7SSuresh Reddy 	struct be_mcc_wrb *wrb;
4837bdce2ad7SSuresh Reddy 	struct be_cmd_req_set_ll_link *req;
4838bdce2ad7SSuresh Reddy 	int status;
4839bdce2ad7SSuresh Reddy 
4840bdce2ad7SSuresh Reddy 	spin_lock_bh(&adapter->mcc_lock);
4841bdce2ad7SSuresh Reddy 
4842bdce2ad7SSuresh Reddy 	wrb = wrb_from_mccq(adapter);
4843bdce2ad7SSuresh Reddy 	if (!wrb) {
4844bdce2ad7SSuresh Reddy 		status = -EBUSY;
4845bdce2ad7SSuresh Reddy 		goto err;
4846bdce2ad7SSuresh Reddy 	}
4847bdce2ad7SSuresh Reddy 
4848bdce2ad7SSuresh Reddy 	req = embedded_payload(wrb);
4849bdce2ad7SSuresh Reddy 
4850bdce2ad7SSuresh Reddy 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4851bdce2ad7SSuresh Reddy 			       OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG,
4852bdce2ad7SSuresh Reddy 			       sizeof(*req), wrb, NULL);
4853bdce2ad7SSuresh Reddy 
4854d9d426afSSuresh Reddy 	req->hdr.version = version;
4855bdce2ad7SSuresh Reddy 	req->hdr.domain = domain;
4856bdce2ad7SSuresh Reddy 
4857d9d426afSSuresh Reddy 	if (link_state == IFLA_VF_LINK_STATE_ENABLE ||
4858d9d426afSSuresh Reddy 	    link_state == IFLA_VF_LINK_STATE_AUTO)
4859d9d426afSSuresh Reddy 		req->link_config |= PLINK_ENABLE;
4860bdce2ad7SSuresh Reddy 
4861bdce2ad7SSuresh Reddy 	if (link_state == IFLA_VF_LINK_STATE_AUTO)
4862d9d426afSSuresh Reddy 		req->link_config |= PLINK_TRACK;
4863bdce2ad7SSuresh Reddy 
4864bdce2ad7SSuresh Reddy 	status = be_mcc_notify_wait(adapter);
4865bdce2ad7SSuresh Reddy err:
4866bdce2ad7SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
4867bdce2ad7SSuresh Reddy 	return status;
4868bdce2ad7SSuresh Reddy }
4869bdce2ad7SSuresh Reddy 
4870d9d426afSSuresh Reddy int be_cmd_set_logical_link_config(struct be_adapter *adapter,
4871d9d426afSSuresh Reddy 				   int link_state, u8 domain)
4872d9d426afSSuresh Reddy {
4873d9d426afSSuresh Reddy 	int status;
4874d9d426afSSuresh Reddy 
4875d9d426afSSuresh Reddy 	if (BEx_chip(adapter))
4876d9d426afSSuresh Reddy 		return -EOPNOTSUPP;
4877d9d426afSSuresh Reddy 
4878d9d426afSSuresh Reddy 	status = __be_cmd_set_logical_link_config(adapter, link_state,
4879d9d426afSSuresh Reddy 						  2, domain);
4880d9d426afSSuresh Reddy 
4881d9d426afSSuresh Reddy 	/* Version 2 of the command will not be recognized by older FW.
4882d9d426afSSuresh Reddy 	 * On such a failure issue version 1 of the command.
4883d9d426afSSuresh Reddy 	 */
4884d9d426afSSuresh Reddy 	if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST)
4885d9d426afSSuresh Reddy 		status = __be_cmd_set_logical_link_config(adapter, link_state,
4886d9d426afSSuresh Reddy 							  1, domain);
4887d9d426afSSuresh Reddy 	return status;
4888d9d426afSSuresh Reddy }
48896a4ab669SParav Pandit int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
48906a4ab669SParav Pandit 		    int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
48916a4ab669SParav Pandit {
48926a4ab669SParav Pandit 	struct be_adapter *adapter = netdev_priv(netdev_handle);
48936a4ab669SParav Pandit 	struct be_mcc_wrb *wrb;
48946a4ab669SParav Pandit 	struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload;
48956a4ab669SParav Pandit 	struct be_cmd_req_hdr *req;
48966a4ab669SParav Pandit 	struct be_cmd_resp_hdr *resp;
48976a4ab669SParav Pandit 	int status;
48986a4ab669SParav Pandit 
48996a4ab669SParav Pandit 	spin_lock_bh(&adapter->mcc_lock);
49006a4ab669SParav Pandit 
49016a4ab669SParav Pandit 	wrb = wrb_from_mccq(adapter);
49026a4ab669SParav Pandit 	if (!wrb) {
49036a4ab669SParav Pandit 		status = -EBUSY;
49046a4ab669SParav Pandit 		goto err;
49056a4ab669SParav Pandit 	}
49066a4ab669SParav Pandit 	req = embedded_payload(wrb);
49076a4ab669SParav Pandit 	resp = embedded_payload(wrb);
49086a4ab669SParav Pandit 
49096a4ab669SParav Pandit 	be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
49106a4ab669SParav Pandit 			       hdr->opcode, wrb_payload_size, wrb, NULL);
49116a4ab669SParav Pandit 	memcpy(req, wrb_payload, wrb_payload_size);
49126a4ab669SParav Pandit 	be_dws_cpu_to_le(req, wrb_payload_size);
49136a4ab669SParav Pandit 
49146a4ab669SParav Pandit 	status = be_mcc_notify_wait(adapter);
49156a4ab669SParav Pandit 	if (cmd_status)
49166a4ab669SParav Pandit 		*cmd_status = (status & 0xffff);
49176a4ab669SParav Pandit 	if (ext_status)
49186a4ab669SParav Pandit 		*ext_status = 0;
49196a4ab669SParav Pandit 	memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
49206a4ab669SParav Pandit 	be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
49216a4ab669SParav Pandit err:
49226a4ab669SParav Pandit 	spin_unlock_bh(&adapter->mcc_lock);
49236a4ab669SParav Pandit 	return status;
49246a4ab669SParav Pandit }
49256a4ab669SParav Pandit EXPORT_SYMBOL(be_roce_mcc_cmd);
4926