19aebddd1SJeff Kirsher /*
240263820SVasundhara Volam  * Copyright (C) 2005 - 2014 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 
919aebddd1SJeff Kirsher static void 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 
966589ade0SSathya Perla 	if (be_error(adapter))
979aebddd1SJeff Kirsher 		return;
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);
1049aebddd1SJeff Kirsher }
1059aebddd1SJeff Kirsher 
1069aebddd1SJeff Kirsher /* To check if valid bit is set, check the entire word as we don't know
1079aebddd1SJeff Kirsher  * the endianness of the data (old entry is host endian while a new entry is
1089aebddd1SJeff Kirsher  * little endian) */
1099aebddd1SJeff Kirsher static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
1109aebddd1SJeff Kirsher {
1119e9ff4b7SSathya Perla 	u32 flags;
1129e9ff4b7SSathya Perla 
1139aebddd1SJeff Kirsher 	if (compl->flags != 0) {
1149e9ff4b7SSathya Perla 		flags = le32_to_cpu(compl->flags);
1159e9ff4b7SSathya Perla 		if (flags & CQE_FLAGS_VALID_MASK) {
1169e9ff4b7SSathya Perla 			compl->flags = flags;
1179aebddd1SJeff Kirsher 			return true;
1189aebddd1SJeff Kirsher 		}
1199aebddd1SJeff Kirsher 	}
1209e9ff4b7SSathya Perla 	return false;
1219e9ff4b7SSathya Perla }
1229aebddd1SJeff Kirsher 
1239aebddd1SJeff Kirsher /* Need to reset the entire word that houses the valid bit */
1249aebddd1SJeff Kirsher static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
1259aebddd1SJeff Kirsher {
1269aebddd1SJeff Kirsher 	compl->flags = 0;
1279aebddd1SJeff Kirsher }
1289aebddd1SJeff Kirsher 
129652bf646SPadmanabh Ratnakar static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
130652bf646SPadmanabh Ratnakar {
131652bf646SPadmanabh Ratnakar 	unsigned long addr;
132652bf646SPadmanabh Ratnakar 
133652bf646SPadmanabh Ratnakar 	addr = tag1;
134652bf646SPadmanabh Ratnakar 	addr = ((addr << 16) << 16) | tag0;
135652bf646SPadmanabh Ratnakar 	return (void *)addr;
136652bf646SPadmanabh Ratnakar }
137652bf646SPadmanabh Ratnakar 
1384c60005fSKalesh AP static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status)
1394c60005fSKalesh AP {
1404c60005fSKalesh AP 	if (base_status == MCC_STATUS_NOT_SUPPORTED ||
1414c60005fSKalesh AP 	    base_status == MCC_STATUS_ILLEGAL_REQUEST ||
1424c60005fSKalesh AP 	    addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES ||
1434c60005fSKalesh AP 	    (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
1444c60005fSKalesh AP 	    (base_status == MCC_STATUS_ILLEGAL_FIELD ||
1454c60005fSKalesh AP 	     addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH)))
1464c60005fSKalesh AP 		return true;
1474c60005fSKalesh AP 	else
1484c60005fSKalesh AP 		return false;
1494c60005fSKalesh AP }
1504c60005fSKalesh AP 
151559b633fSSathya Perla /* Place holder for all the async MCC cmds wherein the caller is not in a busy
152559b633fSSathya Perla  * loop (has not issued be_mcc_notify_wait())
153559b633fSSathya Perla  */
154559b633fSSathya Perla static void be_async_cmd_process(struct be_adapter *adapter,
155559b633fSSathya Perla 				 struct be_mcc_compl *compl,
156559b633fSSathya Perla 				 struct be_cmd_resp_hdr *resp_hdr)
157559b633fSSathya Perla {
158559b633fSSathya Perla 	enum mcc_base_status base_status = base_status(compl->status);
159559b633fSSathya Perla 	u8 opcode = 0, subsystem = 0;
160559b633fSSathya Perla 
161559b633fSSathya Perla 	if (resp_hdr) {
162559b633fSSathya Perla 		opcode = resp_hdr->opcode;
163559b633fSSathya Perla 		subsystem = resp_hdr->subsystem;
164559b633fSSathya Perla 	}
165559b633fSSathya Perla 
166559b633fSSathya Perla 	if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
167559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
168559b633fSSathya Perla 		complete(&adapter->et_cmd_compl);
169559b633fSSathya Perla 		return;
170559b633fSSathya Perla 	}
171559b633fSSathya Perla 
172559b633fSSathya Perla 	if ((opcode == OPCODE_COMMON_WRITE_FLASHROM ||
173559b633fSSathya Perla 	     opcode == OPCODE_COMMON_WRITE_OBJECT) &&
174559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_COMMON) {
175559b633fSSathya Perla 		adapter->flash_status = compl->status;
176559b633fSSathya Perla 		complete(&adapter->et_cmd_compl);
177559b633fSSathya Perla 		return;
178559b633fSSathya Perla 	}
179559b633fSSathya Perla 
180559b633fSSathya Perla 	if ((opcode == OPCODE_ETH_GET_STATISTICS ||
181559b633fSSathya Perla 	     opcode == OPCODE_ETH_GET_PPORT_STATS) &&
182559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_ETH &&
183559b633fSSathya Perla 	    base_status == MCC_STATUS_SUCCESS) {
184559b633fSSathya Perla 		be_parse_stats(adapter);
185559b633fSSathya Perla 		adapter->stats_cmd_sent = false;
186559b633fSSathya Perla 		return;
187559b633fSSathya Perla 	}
188559b633fSSathya Perla 
189559b633fSSathya Perla 	if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
190559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_COMMON) {
191559b633fSSathya Perla 		if (base_status == MCC_STATUS_SUCCESS) {
192559b633fSSathya Perla 			struct be_cmd_resp_get_cntl_addnl_attribs *resp =
193559b633fSSathya Perla 							(void *)resp_hdr;
194559b633fSSathya Perla 			adapter->drv_stats.be_on_die_temperature =
195559b633fSSathya Perla 						resp->on_die_temperature;
196559b633fSSathya Perla 		} else {
197559b633fSSathya Perla 			adapter->be_get_temp_freq = 0;
198559b633fSSathya Perla 		}
199559b633fSSathya Perla 		return;
200559b633fSSathya Perla 	}
201559b633fSSathya Perla }
202559b633fSSathya Perla 
2039aebddd1SJeff Kirsher static int be_mcc_compl_process(struct be_adapter *adapter,
2049aebddd1SJeff Kirsher 				struct be_mcc_compl *compl)
2059aebddd1SJeff Kirsher {
2064c60005fSKalesh AP 	enum mcc_base_status base_status;
2074c60005fSKalesh AP 	enum mcc_addl_status addl_status;
208652bf646SPadmanabh Ratnakar 	struct be_cmd_resp_hdr *resp_hdr;
209652bf646SPadmanabh Ratnakar 	u8 opcode = 0, subsystem = 0;
2109aebddd1SJeff Kirsher 
2119aebddd1SJeff Kirsher 	/* Just swap the status to host endian; mcc tag is opaquely copied
2129aebddd1SJeff Kirsher 	 * from mcc_wrb */
2139aebddd1SJeff Kirsher 	be_dws_le_to_cpu(compl, 4);
2149aebddd1SJeff Kirsher 
2154c60005fSKalesh AP 	base_status = base_status(compl->status);
2164c60005fSKalesh AP 	addl_status = addl_status(compl->status);
21796c9b2e4SVasundhara Volam 
218652bf646SPadmanabh Ratnakar 	resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
219652bf646SPadmanabh Ratnakar 	if (resp_hdr) {
220652bf646SPadmanabh Ratnakar 		opcode = resp_hdr->opcode;
221652bf646SPadmanabh Ratnakar 		subsystem = resp_hdr->subsystem;
222652bf646SPadmanabh Ratnakar 	}
223652bf646SPadmanabh Ratnakar 
224559b633fSSathya Perla 	be_async_cmd_process(adapter, compl, resp_hdr);
2255eeff635SSuresh Reddy 
226559b633fSSathya Perla 	if (base_status != MCC_STATUS_SUCCESS &&
227559b633fSSathya Perla 	    !be_skip_err_log(opcode, base_status, addl_status)) {
2284c60005fSKalesh AP 		if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
22997f1d8cdSVasundhara Volam 			dev_warn(&adapter->pdev->dev,
230522609f2SVasundhara Volam 				 "VF is not privileged to issue opcode %d-%d\n",
23197f1d8cdSVasundhara Volam 				 opcode, subsystem);
2329aebddd1SJeff Kirsher 		} else {
23397f1d8cdSVasundhara Volam 			dev_err(&adapter->pdev->dev,
23497f1d8cdSVasundhara Volam 				"opcode %d-%d failed:status %d-%d\n",
2354c60005fSKalesh AP 				opcode, subsystem, base_status, addl_status);
2369aebddd1SJeff Kirsher 		}
2379aebddd1SJeff Kirsher 	}
2384c60005fSKalesh AP 	return compl->status;
2399aebddd1SJeff Kirsher }
2409aebddd1SJeff Kirsher 
2419aebddd1SJeff Kirsher /* Link state evt is a string of bytes; no need for endian swapping */
2429aebddd1SJeff Kirsher static void be_async_link_state_process(struct be_adapter *adapter,
2433acf19d9SSathya Perla 					struct be_mcc_compl *compl)
2449aebddd1SJeff Kirsher {
2453acf19d9SSathya Perla 	struct be_async_event_link_state *evt =
2463acf19d9SSathya Perla 			(struct be_async_event_link_state *)compl;
2473acf19d9SSathya Perla 
248b236916aSAjit Khaparde 	/* When link status changes, link speed must be re-queried from FW */
24942f11cf2SAjit Khaparde 	adapter->phy.link_speed = -1;
250b236916aSAjit Khaparde 
251bdce2ad7SSuresh Reddy 	/* On BEx the FW does not send a separate link status
252bdce2ad7SSuresh Reddy 	 * notification for physical and logical link.
253bdce2ad7SSuresh Reddy 	 * On other chips just process the logical link
254bdce2ad7SSuresh Reddy 	 * status notification
255bdce2ad7SSuresh Reddy 	 */
256bdce2ad7SSuresh Reddy 	if (!BEx_chip(adapter) &&
2572e177a5cSPadmanabh Ratnakar 	    !(evt->port_link_status & LOGICAL_LINK_STATUS_MASK))
2582e177a5cSPadmanabh Ratnakar 		return;
2592e177a5cSPadmanabh Ratnakar 
260b236916aSAjit Khaparde 	/* For the initial link status do not rely on the ASYNC event as
261b236916aSAjit Khaparde 	 * it may not be received in some cases.
262b236916aSAjit Khaparde 	 */
263b236916aSAjit Khaparde 	if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
264bdce2ad7SSuresh Reddy 		be_link_status_update(adapter,
265bdce2ad7SSuresh Reddy 				      evt->port_link_status & LINK_STATUS_MASK);
2669aebddd1SJeff Kirsher }
2679aebddd1SJeff Kirsher 
26821252377SVasundhara Volam static void be_async_port_misconfig_event_process(struct be_adapter *adapter,
26921252377SVasundhara Volam 						  struct be_mcc_compl *compl)
27021252377SVasundhara Volam {
27121252377SVasundhara Volam 	struct be_async_event_misconfig_port *evt =
27221252377SVasundhara Volam 			(struct be_async_event_misconfig_port *)compl;
27321252377SVasundhara Volam 	u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1);
27421252377SVasundhara Volam 	struct device *dev = &adapter->pdev->dev;
27521252377SVasundhara Volam 	u8 port_misconfig_evt;
27621252377SVasundhara Volam 
27721252377SVasundhara Volam 	port_misconfig_evt =
27821252377SVasundhara Volam 		((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff);
27921252377SVasundhara Volam 
28021252377SVasundhara Volam 	/* Log an error message that would allow a user to determine
28121252377SVasundhara Volam 	 * whether the SFPs have an issue
28221252377SVasundhara Volam 	 */
28321252377SVasundhara Volam 	dev_info(dev, "Port %c: %s %s", adapter->port_name,
28421252377SVasundhara Volam 		 be_port_misconfig_evt_desc[port_misconfig_evt],
28521252377SVasundhara Volam 		 be_port_misconfig_remedy_desc[port_misconfig_evt]);
28621252377SVasundhara Volam 
28721252377SVasundhara Volam 	if (port_misconfig_evt == INCOMPATIBLE_SFP)
28821252377SVasundhara Volam 		adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP;
28921252377SVasundhara Volam }
29021252377SVasundhara Volam 
2919aebddd1SJeff Kirsher /* Grp5 CoS Priority evt */
2929aebddd1SJeff Kirsher static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
2933acf19d9SSathya Perla 					       struct be_mcc_compl *compl)
2949aebddd1SJeff Kirsher {
2953acf19d9SSathya Perla 	struct be_async_event_grp5_cos_priority *evt =
2963acf19d9SSathya Perla 			(struct be_async_event_grp5_cos_priority *)compl;
2973acf19d9SSathya Perla 
2989aebddd1SJeff Kirsher 	if (evt->valid) {
2999aebddd1SJeff Kirsher 		adapter->vlan_prio_bmap = evt->available_priority_bmap;
3009aebddd1SJeff Kirsher 		adapter->recommended_prio &= ~VLAN_PRIO_MASK;
3019aebddd1SJeff Kirsher 		adapter->recommended_prio =
3029aebddd1SJeff Kirsher 			evt->reco_default_priority << VLAN_PRIO_SHIFT;
3039aebddd1SJeff Kirsher 	}
3049aebddd1SJeff Kirsher }
3059aebddd1SJeff Kirsher 
306323ff71eSSathya Perla /* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */
3079aebddd1SJeff Kirsher static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
3083acf19d9SSathya Perla 					    struct be_mcc_compl *compl)
3099aebddd1SJeff Kirsher {
3103acf19d9SSathya Perla 	struct be_async_event_grp5_qos_link_speed *evt =
3113acf19d9SSathya Perla 			(struct be_async_event_grp5_qos_link_speed *)compl;
3123acf19d9SSathya Perla 
313323ff71eSSathya Perla 	if (adapter->phy.link_speed >= 0 &&
314323ff71eSSathya Perla 	    evt->physical_port == adapter->port_num)
315323ff71eSSathya Perla 		adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10;
3169aebddd1SJeff Kirsher }
3179aebddd1SJeff Kirsher 
3189aebddd1SJeff Kirsher /*Grp5 PVID evt*/
3199aebddd1SJeff Kirsher static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
3203acf19d9SSathya Perla 					     struct be_mcc_compl *compl)
3219aebddd1SJeff Kirsher {
3223acf19d9SSathya Perla 	struct be_async_event_grp5_pvid_state *evt =
3233acf19d9SSathya Perla 			(struct be_async_event_grp5_pvid_state *)compl;
3243acf19d9SSathya Perla 
325bdac85b5SRavikumar Nelavelli 	if (evt->enabled) {
326939cf306SSomnath Kotur 		adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
327bdac85b5SRavikumar Nelavelli 		dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid);
328bdac85b5SRavikumar Nelavelli 	} else {
3299aebddd1SJeff Kirsher 		adapter->pvid = 0;
3309aebddd1SJeff Kirsher 	}
331bdac85b5SRavikumar Nelavelli }
3329aebddd1SJeff Kirsher 
3339aebddd1SJeff Kirsher static void be_async_grp5_evt_process(struct be_adapter *adapter,
3343acf19d9SSathya Perla 				      struct be_mcc_compl *compl)
3359aebddd1SJeff Kirsher {
3363acf19d9SSathya Perla 	u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) &
3373acf19d9SSathya Perla 				ASYNC_EVENT_TYPE_MASK;
3389aebddd1SJeff Kirsher 
3399aebddd1SJeff Kirsher 	switch (event_type) {
3409aebddd1SJeff Kirsher 	case ASYNC_EVENT_COS_PRIORITY:
3413acf19d9SSathya Perla 		be_async_grp5_cos_priority_process(adapter, compl);
3429aebddd1SJeff Kirsher 		break;
3439aebddd1SJeff Kirsher 	case ASYNC_EVENT_QOS_SPEED:
3443acf19d9SSathya Perla 		be_async_grp5_qos_speed_process(adapter, compl);
3459aebddd1SJeff Kirsher 		break;
3469aebddd1SJeff Kirsher 	case ASYNC_EVENT_PVID_STATE:
3473acf19d9SSathya Perla 		be_async_grp5_pvid_state_process(adapter, compl);
3489aebddd1SJeff Kirsher 		break;
3499aebddd1SJeff Kirsher 	default:
3509aebddd1SJeff Kirsher 		break;
3519aebddd1SJeff Kirsher 	}
3529aebddd1SJeff Kirsher }
3539aebddd1SJeff Kirsher 
354bc0c3405SAjit Khaparde static void be_async_dbg_evt_process(struct be_adapter *adapter,
3553acf19d9SSathya Perla 				     struct be_mcc_compl *cmp)
356bc0c3405SAjit Khaparde {
357bc0c3405SAjit Khaparde 	u8 event_type = 0;
358bc0c3405SAjit Khaparde 	struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp;
359bc0c3405SAjit Khaparde 
3603acf19d9SSathya Perla 	event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
3613acf19d9SSathya Perla 			ASYNC_EVENT_TYPE_MASK;
362bc0c3405SAjit Khaparde 
363bc0c3405SAjit Khaparde 	switch (event_type) {
364bc0c3405SAjit Khaparde 	case ASYNC_DEBUG_EVENT_TYPE_QNQ:
365bc0c3405SAjit Khaparde 		if (evt->valid)
366bc0c3405SAjit Khaparde 			adapter->qnq_vid = le16_to_cpu(evt->vlan_tag);
367bc0c3405SAjit Khaparde 		adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
368bc0c3405SAjit Khaparde 	break;
369bc0c3405SAjit Khaparde 	default:
37005ccaa2bSVasundhara Volam 		dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n",
37105ccaa2bSVasundhara Volam 			 event_type);
372bc0c3405SAjit Khaparde 	break;
373bc0c3405SAjit Khaparde 	}
374bc0c3405SAjit Khaparde }
375bc0c3405SAjit Khaparde 
37621252377SVasundhara Volam static void be_async_sliport_evt_process(struct be_adapter *adapter,
37721252377SVasundhara Volam 					 struct be_mcc_compl *cmp)
37821252377SVasundhara Volam {
37921252377SVasundhara Volam 	u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
38021252377SVasundhara Volam 			ASYNC_EVENT_TYPE_MASK;
38121252377SVasundhara Volam 
38221252377SVasundhara Volam 	if (event_type == ASYNC_EVENT_PORT_MISCONFIG)
38321252377SVasundhara Volam 		be_async_port_misconfig_event_process(adapter, cmp);
38421252377SVasundhara Volam }
38521252377SVasundhara Volam 
3863acf19d9SSathya Perla static inline bool is_link_state_evt(u32 flags)
3879aebddd1SJeff Kirsher {
3883acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
3899aebddd1SJeff Kirsher 			ASYNC_EVENT_CODE_LINK_STATE;
3909aebddd1SJeff Kirsher }
3919aebddd1SJeff Kirsher 
3923acf19d9SSathya Perla static inline bool is_grp5_evt(u32 flags)
3939aebddd1SJeff Kirsher {
3943acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
3953acf19d9SSathya Perla 			ASYNC_EVENT_CODE_GRP_5;
3969aebddd1SJeff Kirsher }
3979aebddd1SJeff Kirsher 
3983acf19d9SSathya Perla static inline bool is_dbg_evt(u32 flags)
399bc0c3405SAjit Khaparde {
4003acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4013acf19d9SSathya Perla 			ASYNC_EVENT_CODE_QNQ;
4023acf19d9SSathya Perla }
4033acf19d9SSathya Perla 
40421252377SVasundhara Volam static inline bool is_sliport_evt(u32 flags)
40521252377SVasundhara Volam {
40621252377SVasundhara Volam 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
40721252377SVasundhara Volam 		ASYNC_EVENT_CODE_SLIPORT;
40821252377SVasundhara Volam }
40921252377SVasundhara Volam 
4103acf19d9SSathya Perla static void be_mcc_event_process(struct be_adapter *adapter,
4113acf19d9SSathya Perla 				 struct be_mcc_compl *compl)
4123acf19d9SSathya Perla {
4133acf19d9SSathya Perla 	if (is_link_state_evt(compl->flags))
4143acf19d9SSathya Perla 		be_async_link_state_process(adapter, compl);
4153acf19d9SSathya Perla 	else if (is_grp5_evt(compl->flags))
4163acf19d9SSathya Perla 		be_async_grp5_evt_process(adapter, compl);
4173acf19d9SSathya Perla 	else if (is_dbg_evt(compl->flags))
4183acf19d9SSathya Perla 		be_async_dbg_evt_process(adapter, compl);
41921252377SVasundhara Volam 	else if (is_sliport_evt(compl->flags))
42021252377SVasundhara Volam 		be_async_sliport_evt_process(adapter, compl);
421bc0c3405SAjit Khaparde }
422bc0c3405SAjit Khaparde 
4239aebddd1SJeff Kirsher static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
4249aebddd1SJeff Kirsher {
4259aebddd1SJeff Kirsher 	struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
4269aebddd1SJeff Kirsher 	struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
4279aebddd1SJeff Kirsher 
4289aebddd1SJeff Kirsher 	if (be_mcc_compl_is_new(compl)) {
4299aebddd1SJeff Kirsher 		queue_tail_inc(mcc_cq);
4309aebddd1SJeff Kirsher 		return compl;
4319aebddd1SJeff Kirsher 	}
4329aebddd1SJeff Kirsher 	return NULL;
4339aebddd1SJeff Kirsher }
4349aebddd1SJeff Kirsher 
4359aebddd1SJeff Kirsher void be_async_mcc_enable(struct be_adapter *adapter)
4369aebddd1SJeff Kirsher {
4379aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_cq_lock);
4389aebddd1SJeff Kirsher 
4399aebddd1SJeff Kirsher 	be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0);
4409aebddd1SJeff Kirsher 	adapter->mcc_obj.rearm_cq = true;
4419aebddd1SJeff Kirsher 
4429aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_cq_lock);
4439aebddd1SJeff Kirsher }
4449aebddd1SJeff Kirsher 
4459aebddd1SJeff Kirsher void be_async_mcc_disable(struct be_adapter *adapter)
4469aebddd1SJeff Kirsher {
447a323d9bfSSathya Perla 	spin_lock_bh(&adapter->mcc_cq_lock);
448a323d9bfSSathya Perla 
4499aebddd1SJeff Kirsher 	adapter->mcc_obj.rearm_cq = false;
450a323d9bfSSathya Perla 	be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
451a323d9bfSSathya Perla 
452a323d9bfSSathya Perla 	spin_unlock_bh(&adapter->mcc_cq_lock);
4539aebddd1SJeff Kirsher }
4549aebddd1SJeff Kirsher 
45510ef9ab4SSathya Perla int be_process_mcc(struct be_adapter *adapter)
4569aebddd1SJeff Kirsher {
4579aebddd1SJeff Kirsher 	struct be_mcc_compl *compl;
45810ef9ab4SSathya Perla 	int num = 0, status = 0;
4599aebddd1SJeff Kirsher 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
4609aebddd1SJeff Kirsher 
461072a9c48SAmerigo Wang 	spin_lock(&adapter->mcc_cq_lock);
4623acf19d9SSathya Perla 
4639aebddd1SJeff Kirsher 	while ((compl = be_mcc_compl_get(adapter))) {
4649aebddd1SJeff Kirsher 		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
4653acf19d9SSathya Perla 			be_mcc_event_process(adapter, compl);
4669aebddd1SJeff Kirsher 		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
46710ef9ab4SSathya Perla 			status = be_mcc_compl_process(adapter, compl);
4689aebddd1SJeff Kirsher 			atomic_dec(&mcc_obj->q.used);
4699aebddd1SJeff Kirsher 		}
4709aebddd1SJeff Kirsher 		be_mcc_compl_use(compl);
4719aebddd1SJeff Kirsher 		num++;
4729aebddd1SJeff Kirsher 	}
4739aebddd1SJeff Kirsher 
47410ef9ab4SSathya Perla 	if (num)
47510ef9ab4SSathya Perla 		be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
47610ef9ab4SSathya Perla 
477072a9c48SAmerigo Wang 	spin_unlock(&adapter->mcc_cq_lock);
47810ef9ab4SSathya Perla 	return status;
4799aebddd1SJeff Kirsher }
4809aebddd1SJeff Kirsher 
4819aebddd1SJeff Kirsher /* Wait till no more pending mcc requests are present */
4829aebddd1SJeff Kirsher static int be_mcc_wait_compl(struct be_adapter *adapter)
4839aebddd1SJeff Kirsher {
4849aebddd1SJeff Kirsher #define mcc_timeout		120000 /* 12s timeout */
48510ef9ab4SSathya Perla 	int i, status = 0;
4869aebddd1SJeff Kirsher 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
4879aebddd1SJeff Kirsher 
4886589ade0SSathya Perla 	for (i = 0; i < mcc_timeout; i++) {
4896589ade0SSathya Perla 		if (be_error(adapter))
4909aebddd1SJeff Kirsher 			return -EIO;
4919aebddd1SJeff Kirsher 
492072a9c48SAmerigo Wang 		local_bh_disable();
49310ef9ab4SSathya Perla 		status = be_process_mcc(adapter);
494072a9c48SAmerigo Wang 		local_bh_enable();
4959aebddd1SJeff Kirsher 
4969aebddd1SJeff Kirsher 		if (atomic_read(&mcc_obj->q.used) == 0)
4979aebddd1SJeff Kirsher 			break;
4989aebddd1SJeff Kirsher 		udelay(100);
4999aebddd1SJeff Kirsher 	}
5009aebddd1SJeff Kirsher 	if (i == mcc_timeout) {
5016589ade0SSathya Perla 		dev_err(&adapter->pdev->dev, "FW not responding\n");
5026589ade0SSathya Perla 		adapter->fw_timeout = true;
503652bf646SPadmanabh Ratnakar 		return -EIO;
5049aebddd1SJeff Kirsher 	}
5059aebddd1SJeff Kirsher 	return status;
5069aebddd1SJeff Kirsher }
5079aebddd1SJeff Kirsher 
5089aebddd1SJeff Kirsher /* Notify MCC requests and wait for completion */
5099aebddd1SJeff Kirsher static int be_mcc_notify_wait(struct be_adapter *adapter)
5109aebddd1SJeff Kirsher {
511652bf646SPadmanabh Ratnakar 	int status;
512652bf646SPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
513652bf646SPadmanabh Ratnakar 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
514652bf646SPadmanabh Ratnakar 	u16 index = mcc_obj->q.head;
515652bf646SPadmanabh Ratnakar 	struct be_cmd_resp_hdr *resp;
516652bf646SPadmanabh Ratnakar 
517652bf646SPadmanabh Ratnakar 	index_dec(&index, mcc_obj->q.len);
518652bf646SPadmanabh Ratnakar 	wrb = queue_index_node(&mcc_obj->q, index);
519652bf646SPadmanabh Ratnakar 
520652bf646SPadmanabh Ratnakar 	resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
521652bf646SPadmanabh Ratnakar 
5229aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
523652bf646SPadmanabh Ratnakar 
524652bf646SPadmanabh Ratnakar 	status = be_mcc_wait_compl(adapter);
525652bf646SPadmanabh Ratnakar 	if (status == -EIO)
526652bf646SPadmanabh Ratnakar 		goto out;
527652bf646SPadmanabh Ratnakar 
5284c60005fSKalesh AP 	status = (resp->base_status |
5294c60005fSKalesh AP 		  ((resp->addl_status & CQE_ADDL_STATUS_MASK) <<
5304c60005fSKalesh AP 		   CQE_ADDL_STATUS_SHIFT));
531652bf646SPadmanabh Ratnakar out:
532652bf646SPadmanabh Ratnakar 	return status;
5339aebddd1SJeff Kirsher }
5349aebddd1SJeff Kirsher 
5359aebddd1SJeff Kirsher static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
5369aebddd1SJeff Kirsher {
5379aebddd1SJeff Kirsher 	int msecs = 0;
5389aebddd1SJeff Kirsher 	u32 ready;
5399aebddd1SJeff Kirsher 
5406589ade0SSathya Perla 	do {
5416589ade0SSathya Perla 		if (be_error(adapter))
5429aebddd1SJeff Kirsher 			return -EIO;
5439aebddd1SJeff Kirsher 
5449aebddd1SJeff Kirsher 		ready = ioread32(db);
545434b3648SSathya Perla 		if (ready == 0xffffffff)
5469aebddd1SJeff Kirsher 			return -1;
5479aebddd1SJeff Kirsher 
5489aebddd1SJeff Kirsher 		ready &= MPU_MAILBOX_DB_RDY_MASK;
5499aebddd1SJeff Kirsher 		if (ready)
5509aebddd1SJeff Kirsher 			break;
5519aebddd1SJeff Kirsher 
5529aebddd1SJeff Kirsher 		if (msecs > 4000) {
5536589ade0SSathya Perla 			dev_err(&adapter->pdev->dev, "FW not responding\n");
5546589ade0SSathya Perla 			adapter->fw_timeout = true;
555f67ef7baSPadmanabh Ratnakar 			be_detect_error(adapter);
5569aebddd1SJeff Kirsher 			return -1;
5579aebddd1SJeff Kirsher 		}
5589aebddd1SJeff Kirsher 
5599aebddd1SJeff Kirsher 		msleep(1);
5609aebddd1SJeff Kirsher 		msecs++;
5619aebddd1SJeff Kirsher 	} while (true);
5629aebddd1SJeff Kirsher 
5639aebddd1SJeff Kirsher 	return 0;
5649aebddd1SJeff Kirsher }
5659aebddd1SJeff Kirsher 
5669aebddd1SJeff Kirsher /*
5679aebddd1SJeff Kirsher  * Insert the mailbox address into the doorbell in two steps
5689aebddd1SJeff Kirsher  * Polls on the mbox doorbell till a command completion (or a timeout) occurs
5699aebddd1SJeff Kirsher  */
5709aebddd1SJeff Kirsher static int be_mbox_notify_wait(struct be_adapter *adapter)
5719aebddd1SJeff Kirsher {
5729aebddd1SJeff Kirsher 	int status;
5739aebddd1SJeff Kirsher 	u32 val = 0;
5749aebddd1SJeff Kirsher 	void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET;
5759aebddd1SJeff Kirsher 	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
5769aebddd1SJeff Kirsher 	struct be_mcc_mailbox *mbox = mbox_mem->va;
5779aebddd1SJeff Kirsher 	struct be_mcc_compl *compl = &mbox->compl;
5789aebddd1SJeff Kirsher 
5799aebddd1SJeff Kirsher 	/* wait for ready to be set */
5809aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
5819aebddd1SJeff Kirsher 	if (status != 0)
5829aebddd1SJeff Kirsher 		return status;
5839aebddd1SJeff Kirsher 
5849aebddd1SJeff Kirsher 	val |= MPU_MAILBOX_DB_HI_MASK;
5859aebddd1SJeff Kirsher 	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
5869aebddd1SJeff Kirsher 	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
5879aebddd1SJeff Kirsher 	iowrite32(val, db);
5889aebddd1SJeff Kirsher 
5899aebddd1SJeff Kirsher 	/* wait for ready to be set */
5909aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
5919aebddd1SJeff Kirsher 	if (status != 0)
5929aebddd1SJeff Kirsher 		return status;
5939aebddd1SJeff Kirsher 
5949aebddd1SJeff Kirsher 	val = 0;
5959aebddd1SJeff Kirsher 	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
5969aebddd1SJeff Kirsher 	val |= (u32)(mbox_mem->dma >> 4) << 2;
5979aebddd1SJeff Kirsher 	iowrite32(val, db);
5989aebddd1SJeff Kirsher 
5999aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
6009aebddd1SJeff Kirsher 	if (status != 0)
6019aebddd1SJeff Kirsher 		return status;
6029aebddd1SJeff Kirsher 
6039aebddd1SJeff Kirsher 	/* A cq entry has been made now */
6049aebddd1SJeff Kirsher 	if (be_mcc_compl_is_new(compl)) {
6059aebddd1SJeff Kirsher 		status = be_mcc_compl_process(adapter, &mbox->compl);
6069aebddd1SJeff Kirsher 		be_mcc_compl_use(compl);
6079aebddd1SJeff Kirsher 		if (status)
6089aebddd1SJeff Kirsher 			return status;
6099aebddd1SJeff Kirsher 	} else {
6109aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev, "invalid mailbox completion\n");
6119aebddd1SJeff Kirsher 		return -1;
6129aebddd1SJeff Kirsher 	}
6139aebddd1SJeff Kirsher 	return 0;
6149aebddd1SJeff Kirsher }
6159aebddd1SJeff Kirsher 
616c5b3ad4cSSathya Perla static u16 be_POST_stage_get(struct be_adapter *adapter)
6179aebddd1SJeff Kirsher {
6189aebddd1SJeff Kirsher 	u32 sem;
6199aebddd1SJeff Kirsher 
620c5b3ad4cSSathya Perla 	if (BEx_chip(adapter))
621c5b3ad4cSSathya Perla 		sem  = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx);
6229aebddd1SJeff Kirsher 	else
623c5b3ad4cSSathya Perla 		pci_read_config_dword(adapter->pdev,
624c5b3ad4cSSathya Perla 				      SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
625c5b3ad4cSSathya Perla 
626c5b3ad4cSSathya Perla 	return sem & POST_STAGE_MASK;
6279aebddd1SJeff Kirsher }
6289aebddd1SJeff Kirsher 
62987f20c26SGavin Shan static int lancer_wait_ready(struct be_adapter *adapter)
630bf99e50dSPadmanabh Ratnakar {
631bf99e50dSPadmanabh Ratnakar #define SLIPORT_READY_TIMEOUT 30
632bf99e50dSPadmanabh Ratnakar 	u32 sliport_status;
633e673244aSKalesh AP 	int i;
634bf99e50dSPadmanabh Ratnakar 
635bf99e50dSPadmanabh Ratnakar 	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
636bf99e50dSPadmanabh Ratnakar 		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
637bf99e50dSPadmanabh Ratnakar 		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
6389fa465c0SSathya Perla 			return 0;
6399fa465c0SSathya Perla 
6409fa465c0SSathya Perla 		if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
6419fa465c0SSathya Perla 		    !(sliport_status & SLIPORT_STATUS_RN_MASK))
6429fa465c0SSathya Perla 			return -EIO;
643bf99e50dSPadmanabh Ratnakar 
644bf99e50dSPadmanabh Ratnakar 		msleep(1000);
645bf99e50dSPadmanabh Ratnakar 	}
646bf99e50dSPadmanabh Ratnakar 
647e673244aSKalesh AP 	return sliport_status ? : -1;
648bf99e50dSPadmanabh Ratnakar }
649bf99e50dSPadmanabh Ratnakar 
650bf99e50dSPadmanabh Ratnakar int be_fw_wait_ready(struct be_adapter *adapter)
6519aebddd1SJeff Kirsher {
6529aebddd1SJeff Kirsher 	u16 stage;
6539aebddd1SJeff Kirsher 	int status, timeout = 0;
6549aebddd1SJeff Kirsher 	struct device *dev = &adapter->pdev->dev;
6559aebddd1SJeff Kirsher 
656bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter)) {
657bf99e50dSPadmanabh Ratnakar 		status = lancer_wait_ready(adapter);
658e673244aSKalesh AP 		if (status) {
659e673244aSKalesh AP 			stage = status;
660e673244aSKalesh AP 			goto err;
661e673244aSKalesh AP 		}
662e673244aSKalesh AP 		return 0;
663bf99e50dSPadmanabh Ratnakar 	}
664bf99e50dSPadmanabh Ratnakar 
6659aebddd1SJeff Kirsher 	do {
666ca3de6b2SSathya Perla 		/* There's no means to poll POST state on BE2/3 VFs */
667ca3de6b2SSathya Perla 		if (BEx_chip(adapter) && be_virtfn(adapter))
668ca3de6b2SSathya Perla 			return 0;
669ca3de6b2SSathya Perla 
670c5b3ad4cSSathya Perla 		stage = be_POST_stage_get(adapter);
67166d29cbcSGavin Shan 		if (stage == POST_STAGE_ARMFW_RDY)
67266d29cbcSGavin Shan 			return 0;
67366d29cbcSGavin Shan 
674a2cc4e0bSSathya Perla 		dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout);
6759aebddd1SJeff Kirsher 		if (msleep_interruptible(2000)) {
6769aebddd1SJeff Kirsher 			dev_err(dev, "Waiting for POST aborted\n");
6779aebddd1SJeff Kirsher 			return -EINTR;
6789aebddd1SJeff Kirsher 		}
6799aebddd1SJeff Kirsher 		timeout += 2;
6803ab81b5fSSomnath Kotur 	} while (timeout < 60);
6819aebddd1SJeff Kirsher 
682e673244aSKalesh AP err:
683e673244aSKalesh AP 	dev_err(dev, "POST timeout; stage=%#x\n", stage);
6849fa465c0SSathya Perla 	return -ETIMEDOUT;
6859aebddd1SJeff Kirsher }
6869aebddd1SJeff Kirsher 
6879aebddd1SJeff Kirsher static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
6889aebddd1SJeff Kirsher {
6899aebddd1SJeff Kirsher 	return &wrb->payload.sgl[0];
6909aebddd1SJeff Kirsher }
6919aebddd1SJeff Kirsher 
692a2cc4e0bSSathya Perla static inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr)
693bea50988SSathya Perla {
694bea50988SSathya Perla 	wrb->tag0 = addr & 0xFFFFFFFF;
695bea50988SSathya Perla 	wrb->tag1 = upper_32_bits(addr);
696bea50988SSathya Perla }
6979aebddd1SJeff Kirsher 
6989aebddd1SJeff Kirsher /* Don't touch the hdr after it's prepared */
699106df1e3SSomnath Kotur /* mem will be NULL for embedded commands */
700106df1e3SSomnath Kotur static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
701106df1e3SSomnath Kotur 				   u8 subsystem, u8 opcode, int cmd_len,
702a2cc4e0bSSathya Perla 				   struct be_mcc_wrb *wrb,
703a2cc4e0bSSathya Perla 				   struct be_dma_mem *mem)
7049aebddd1SJeff Kirsher {
705106df1e3SSomnath Kotur 	struct be_sge *sge;
706106df1e3SSomnath Kotur 
7079aebddd1SJeff Kirsher 	req_hdr->opcode = opcode;
7089aebddd1SJeff Kirsher 	req_hdr->subsystem = subsystem;
7099aebddd1SJeff Kirsher 	req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
7109aebddd1SJeff Kirsher 	req_hdr->version = 0;
711bea50988SSathya Perla 	fill_wrb_tags(wrb, (ulong) req_hdr);
712106df1e3SSomnath Kotur 	wrb->payload_length = cmd_len;
713106df1e3SSomnath Kotur 	if (mem) {
714106df1e3SSomnath Kotur 		wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
715106df1e3SSomnath Kotur 			MCC_WRB_SGE_CNT_SHIFT;
716106df1e3SSomnath Kotur 		sge = nonembedded_sgl(wrb);
717106df1e3SSomnath Kotur 		sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
718106df1e3SSomnath Kotur 		sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
719106df1e3SSomnath Kotur 		sge->len = cpu_to_le32(mem->size);
720106df1e3SSomnath Kotur 	} else
721106df1e3SSomnath Kotur 		wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
722106df1e3SSomnath Kotur 	be_dws_cpu_to_le(wrb, 8);
7239aebddd1SJeff Kirsher }
7249aebddd1SJeff Kirsher 
7259aebddd1SJeff Kirsher static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
7269aebddd1SJeff Kirsher 				      struct be_dma_mem *mem)
7279aebddd1SJeff Kirsher {
7289aebddd1SJeff Kirsher 	int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
7299aebddd1SJeff Kirsher 	u64 dma = (u64)mem->dma;
7309aebddd1SJeff Kirsher 
7319aebddd1SJeff Kirsher 	for (i = 0; i < buf_pages; i++) {
7329aebddd1SJeff Kirsher 		pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
7339aebddd1SJeff Kirsher 		pages[i].hi = cpu_to_le32(upper_32_bits(dma));
7349aebddd1SJeff Kirsher 		dma += PAGE_SIZE_4K;
7359aebddd1SJeff Kirsher 	}
7369aebddd1SJeff Kirsher }
7379aebddd1SJeff Kirsher 
7389aebddd1SJeff Kirsher static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter)
7399aebddd1SJeff Kirsher {
7409aebddd1SJeff Kirsher 	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
7419aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb
7429aebddd1SJeff Kirsher 		= &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
7439aebddd1SJeff Kirsher 	memset(wrb, 0, sizeof(*wrb));
7449aebddd1SJeff Kirsher 	return wrb;
7459aebddd1SJeff Kirsher }
7469aebddd1SJeff Kirsher 
7479aebddd1SJeff Kirsher static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
7489aebddd1SJeff Kirsher {
7499aebddd1SJeff Kirsher 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
7509aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
7519aebddd1SJeff Kirsher 
752aa790db9SPadmanabh Ratnakar 	if (!mccq->created)
753aa790db9SPadmanabh Ratnakar 		return NULL;
754aa790db9SPadmanabh Ratnakar 
7554d277125SVasundhara Volam 	if (atomic_read(&mccq->used) >= mccq->len)
7569aebddd1SJeff Kirsher 		return NULL;
7579aebddd1SJeff Kirsher 
7589aebddd1SJeff Kirsher 	wrb = queue_head_node(mccq);
7599aebddd1SJeff Kirsher 	queue_head_inc(mccq);
7609aebddd1SJeff Kirsher 	atomic_inc(&mccq->used);
7619aebddd1SJeff Kirsher 	memset(wrb, 0, sizeof(*wrb));
7629aebddd1SJeff Kirsher 	return wrb;
7639aebddd1SJeff Kirsher }
7649aebddd1SJeff Kirsher 
765bea50988SSathya Perla static bool use_mcc(struct be_adapter *adapter)
766bea50988SSathya Perla {
767bea50988SSathya Perla 	return adapter->mcc_obj.q.created;
768bea50988SSathya Perla }
769bea50988SSathya Perla 
770bea50988SSathya Perla /* Must be used only in process context */
771bea50988SSathya Perla static int be_cmd_lock(struct be_adapter *adapter)
772bea50988SSathya Perla {
773bea50988SSathya Perla 	if (use_mcc(adapter)) {
774bea50988SSathya Perla 		spin_lock_bh(&adapter->mcc_lock);
775bea50988SSathya Perla 		return 0;
776bea50988SSathya Perla 	} else {
777bea50988SSathya Perla 		return mutex_lock_interruptible(&adapter->mbox_lock);
778bea50988SSathya Perla 	}
779bea50988SSathya Perla }
780bea50988SSathya Perla 
781bea50988SSathya Perla /* Must be used only in process context */
782bea50988SSathya Perla static void be_cmd_unlock(struct be_adapter *adapter)
783bea50988SSathya Perla {
784bea50988SSathya Perla 	if (use_mcc(adapter))
785bea50988SSathya Perla 		spin_unlock_bh(&adapter->mcc_lock);
786bea50988SSathya Perla 	else
787bea50988SSathya Perla 		return mutex_unlock(&adapter->mbox_lock);
788bea50988SSathya Perla }
789bea50988SSathya Perla 
790bea50988SSathya Perla static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter,
791bea50988SSathya Perla 				      struct be_mcc_wrb *wrb)
792bea50988SSathya Perla {
793bea50988SSathya Perla 	struct be_mcc_wrb *dest_wrb;
794bea50988SSathya Perla 
795bea50988SSathya Perla 	if (use_mcc(adapter)) {
796bea50988SSathya Perla 		dest_wrb = wrb_from_mccq(adapter);
797bea50988SSathya Perla 		if (!dest_wrb)
798bea50988SSathya Perla 			return NULL;
799bea50988SSathya Perla 	} else {
800bea50988SSathya Perla 		dest_wrb = wrb_from_mbox(adapter);
801bea50988SSathya Perla 	}
802bea50988SSathya Perla 
803bea50988SSathya Perla 	memcpy(dest_wrb, wrb, sizeof(*wrb));
804bea50988SSathya Perla 	if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK))
805bea50988SSathya Perla 		fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb));
806bea50988SSathya Perla 
807bea50988SSathya Perla 	return dest_wrb;
808bea50988SSathya Perla }
809bea50988SSathya Perla 
810bea50988SSathya Perla /* Must be used only in process context */
811bea50988SSathya Perla static int be_cmd_notify_wait(struct be_adapter *adapter,
812bea50988SSathya Perla 			      struct be_mcc_wrb *wrb)
813bea50988SSathya Perla {
814bea50988SSathya Perla 	struct be_mcc_wrb *dest_wrb;
815bea50988SSathya Perla 	int status;
816bea50988SSathya Perla 
817bea50988SSathya Perla 	status = be_cmd_lock(adapter);
818bea50988SSathya Perla 	if (status)
819bea50988SSathya Perla 		return status;
820bea50988SSathya Perla 
821bea50988SSathya Perla 	dest_wrb = be_cmd_copy(adapter, wrb);
822bea50988SSathya Perla 	if (!dest_wrb)
823bea50988SSathya Perla 		return -EBUSY;
824bea50988SSathya Perla 
825bea50988SSathya Perla 	if (use_mcc(adapter))
826bea50988SSathya Perla 		status = be_mcc_notify_wait(adapter);
827bea50988SSathya Perla 	else
828bea50988SSathya Perla 		status = be_mbox_notify_wait(adapter);
829bea50988SSathya Perla 
830bea50988SSathya Perla 	if (!status)
831bea50988SSathya Perla 		memcpy(wrb, dest_wrb, sizeof(*wrb));
832bea50988SSathya Perla 
833bea50988SSathya Perla 	be_cmd_unlock(adapter);
834bea50988SSathya Perla 	return status;
835bea50988SSathya Perla }
836bea50988SSathya Perla 
8379aebddd1SJeff Kirsher /* Tell fw we're about to start firing cmds by writing a
8389aebddd1SJeff Kirsher  * special pattern across the wrb hdr; uses mbox
8399aebddd1SJeff Kirsher  */
8409aebddd1SJeff Kirsher int be_cmd_fw_init(struct be_adapter *adapter)
8419aebddd1SJeff Kirsher {
8429aebddd1SJeff Kirsher 	u8 *wrb;
8439aebddd1SJeff Kirsher 	int status;
8449aebddd1SJeff Kirsher 
845bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter))
846bf99e50dSPadmanabh Ratnakar 		return 0;
847bf99e50dSPadmanabh Ratnakar 
8489aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
8499aebddd1SJeff Kirsher 		return -1;
8509aebddd1SJeff Kirsher 
8519aebddd1SJeff Kirsher 	wrb = (u8 *)wrb_from_mbox(adapter);
8529aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8539aebddd1SJeff Kirsher 	*wrb++ = 0x12;
8549aebddd1SJeff Kirsher 	*wrb++ = 0x34;
8559aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8569aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8579aebddd1SJeff Kirsher 	*wrb++ = 0x56;
8589aebddd1SJeff Kirsher 	*wrb++ = 0x78;
8599aebddd1SJeff Kirsher 	*wrb = 0xFF;
8609aebddd1SJeff Kirsher 
8619aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
8629aebddd1SJeff Kirsher 
8639aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
8649aebddd1SJeff Kirsher 	return status;
8659aebddd1SJeff Kirsher }
8669aebddd1SJeff Kirsher 
8679aebddd1SJeff Kirsher /* Tell fw we're done with firing cmds by writing a
8689aebddd1SJeff Kirsher  * special pattern across the wrb hdr; uses mbox
8699aebddd1SJeff Kirsher  */
8709aebddd1SJeff Kirsher int be_cmd_fw_clean(struct be_adapter *adapter)
8719aebddd1SJeff Kirsher {
8729aebddd1SJeff Kirsher 	u8 *wrb;
8739aebddd1SJeff Kirsher 	int status;
8749aebddd1SJeff Kirsher 
875bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter))
876bf99e50dSPadmanabh Ratnakar 		return 0;
877bf99e50dSPadmanabh Ratnakar 
8789aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
8799aebddd1SJeff Kirsher 		return -1;
8809aebddd1SJeff Kirsher 
8819aebddd1SJeff Kirsher 	wrb = (u8 *)wrb_from_mbox(adapter);
8829aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8839aebddd1SJeff Kirsher 	*wrb++ = 0xAA;
8849aebddd1SJeff Kirsher 	*wrb++ = 0xBB;
8859aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8869aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8879aebddd1SJeff Kirsher 	*wrb++ = 0xCC;
8889aebddd1SJeff Kirsher 	*wrb++ = 0xDD;
8899aebddd1SJeff Kirsher 	*wrb = 0xFF;
8909aebddd1SJeff Kirsher 
8919aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
8929aebddd1SJeff Kirsher 
8939aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
8949aebddd1SJeff Kirsher 	return status;
8959aebddd1SJeff Kirsher }
896bf99e50dSPadmanabh Ratnakar 
897f2f781a7SSathya Perla int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo)
8989aebddd1SJeff Kirsher {
8999aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9009aebddd1SJeff Kirsher 	struct be_cmd_req_eq_create *req;
901f2f781a7SSathya Perla 	struct be_dma_mem *q_mem = &eqo->q.dma_mem;
902f2f781a7SSathya Perla 	int status, ver = 0;
9039aebddd1SJeff Kirsher 
9049aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
9059aebddd1SJeff Kirsher 		return -1;
9069aebddd1SJeff Kirsher 
9079aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
9089aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
9099aebddd1SJeff Kirsher 
910106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
911a2cc4e0bSSathya Perla 			       OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb,
912a2cc4e0bSSathya Perla 			       NULL);
9139aebddd1SJeff Kirsher 
914f2f781a7SSathya Perla 	/* Support for EQ_CREATEv2 available only SH-R onwards */
915f2f781a7SSathya Perla 	if (!(BEx_chip(adapter) || lancer_chip(adapter)))
916f2f781a7SSathya Perla 		ver = 2;
917f2f781a7SSathya Perla 
918f2f781a7SSathya Perla 	req->hdr.version = ver;
9199aebddd1SJeff Kirsher 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
9209aebddd1SJeff Kirsher 
9219aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
9229aebddd1SJeff Kirsher 	/* 4byte eqe*/
9239aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
9249aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, count, req->context,
925f2f781a7SSathya Perla 		      __ilog2_u32(eqo->q.len / 256));
9269aebddd1SJeff Kirsher 	be_dws_cpu_to_le(req->context, sizeof(req->context));
9279aebddd1SJeff Kirsher 
9289aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
9299aebddd1SJeff Kirsher 
9309aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
9319aebddd1SJeff Kirsher 	if (!status) {
9329aebddd1SJeff Kirsher 		struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
93303d28ffeSKalesh AP 
934f2f781a7SSathya Perla 		eqo->q.id = le16_to_cpu(resp->eq_id);
935f2f781a7SSathya Perla 		eqo->msix_idx =
936f2f781a7SSathya Perla 			(ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx;
937f2f781a7SSathya Perla 		eqo->q.created = true;
9389aebddd1SJeff Kirsher 	}
9399aebddd1SJeff Kirsher 
9409aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
9419aebddd1SJeff Kirsher 	return status;
9429aebddd1SJeff Kirsher }
9439aebddd1SJeff Kirsher 
944f9449ab7SSathya Perla /* Use MCC */
9459aebddd1SJeff Kirsher int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
9465ee4979bSSathya Perla 			  bool permanent, u32 if_handle, u32 pmac_id)
9479aebddd1SJeff Kirsher {
9489aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9499aebddd1SJeff Kirsher 	struct be_cmd_req_mac_query *req;
9509aebddd1SJeff Kirsher 	int status;
9519aebddd1SJeff Kirsher 
952f9449ab7SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
9539aebddd1SJeff Kirsher 
954f9449ab7SSathya Perla 	wrb = wrb_from_mccq(adapter);
955f9449ab7SSathya Perla 	if (!wrb) {
956f9449ab7SSathya Perla 		status = -EBUSY;
957f9449ab7SSathya Perla 		goto err;
958f9449ab7SSathya Perla 	}
9599aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
9609aebddd1SJeff Kirsher 
961106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
962a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb,
963a2cc4e0bSSathya Perla 			       NULL);
9645ee4979bSSathya Perla 	req->type = MAC_ADDRESS_TYPE_NETWORK;
9659aebddd1SJeff Kirsher 	if (permanent) {
9669aebddd1SJeff Kirsher 		req->permanent = 1;
9679aebddd1SJeff Kirsher 	} else {
9689aebddd1SJeff Kirsher 		req->if_id = cpu_to_le16((u16)if_handle);
969590c391dSPadmanabh Ratnakar 		req->pmac_id = cpu_to_le32(pmac_id);
9709aebddd1SJeff Kirsher 		req->permanent = 0;
9719aebddd1SJeff Kirsher 	}
9729aebddd1SJeff Kirsher 
973f9449ab7SSathya Perla 	status = be_mcc_notify_wait(adapter);
9749aebddd1SJeff Kirsher 	if (!status) {
9759aebddd1SJeff Kirsher 		struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
97603d28ffeSKalesh AP 
9779aebddd1SJeff Kirsher 		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
9789aebddd1SJeff Kirsher 	}
9799aebddd1SJeff Kirsher 
980f9449ab7SSathya Perla err:
981f9449ab7SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
9829aebddd1SJeff Kirsher 	return status;
9839aebddd1SJeff Kirsher }
9849aebddd1SJeff Kirsher 
9859aebddd1SJeff Kirsher /* Uses synchronous MCCQ */
9869aebddd1SJeff Kirsher int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
9879aebddd1SJeff Kirsher 		    u32 if_id, u32 *pmac_id, u32 domain)
9889aebddd1SJeff Kirsher {
9899aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9909aebddd1SJeff Kirsher 	struct be_cmd_req_pmac_add *req;
9919aebddd1SJeff Kirsher 	int status;
9929aebddd1SJeff Kirsher 
9939aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
9949aebddd1SJeff Kirsher 
9959aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
9969aebddd1SJeff Kirsher 	if (!wrb) {
9979aebddd1SJeff Kirsher 		status = -EBUSY;
9989aebddd1SJeff Kirsher 		goto err;
9999aebddd1SJeff Kirsher 	}
10009aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10019aebddd1SJeff Kirsher 
1002106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1003a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb,
1004a2cc4e0bSSathya Perla 			       NULL);
10059aebddd1SJeff Kirsher 
10069aebddd1SJeff Kirsher 	req->hdr.domain = domain;
10079aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(if_id);
10089aebddd1SJeff Kirsher 	memcpy(req->mac_address, mac_addr, ETH_ALEN);
10099aebddd1SJeff Kirsher 
10109aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
10119aebddd1SJeff Kirsher 	if (!status) {
10129aebddd1SJeff Kirsher 		struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
101303d28ffeSKalesh AP 
10149aebddd1SJeff Kirsher 		*pmac_id = le32_to_cpu(resp->pmac_id);
10159aebddd1SJeff Kirsher 	}
10169aebddd1SJeff Kirsher 
10179aebddd1SJeff Kirsher err:
10189aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1019e3a7ae2cSSomnath Kotur 
1020e3a7ae2cSSomnath Kotur 	 if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
1021e3a7ae2cSSomnath Kotur 		status = -EPERM;
1022e3a7ae2cSSomnath Kotur 
10239aebddd1SJeff Kirsher 	return status;
10249aebddd1SJeff Kirsher }
10259aebddd1SJeff Kirsher 
10269aebddd1SJeff Kirsher /* Uses synchronous MCCQ */
102730128031SSathya Perla int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom)
10289aebddd1SJeff Kirsher {
10299aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
10309aebddd1SJeff Kirsher 	struct be_cmd_req_pmac_del *req;
10319aebddd1SJeff Kirsher 	int status;
10329aebddd1SJeff Kirsher 
103330128031SSathya Perla 	if (pmac_id == -1)
103430128031SSathya Perla 		return 0;
103530128031SSathya Perla 
10369aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
10379aebddd1SJeff Kirsher 
10389aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
10399aebddd1SJeff Kirsher 	if (!wrb) {
10409aebddd1SJeff Kirsher 		status = -EBUSY;
10419aebddd1SJeff Kirsher 		goto err;
10429aebddd1SJeff Kirsher 	}
10439aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10449aebddd1SJeff Kirsher 
1045106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1046cd3307aaSKalesh AP 			       OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req),
1047cd3307aaSKalesh AP 			       wrb, NULL);
10489aebddd1SJeff Kirsher 
10499aebddd1SJeff Kirsher 	req->hdr.domain = dom;
10509aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(if_id);
10519aebddd1SJeff Kirsher 	req->pmac_id = cpu_to_le32(pmac_id);
10529aebddd1SJeff Kirsher 
10539aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
10549aebddd1SJeff Kirsher 
10559aebddd1SJeff Kirsher err:
10569aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
10579aebddd1SJeff Kirsher 	return status;
10589aebddd1SJeff Kirsher }
10599aebddd1SJeff Kirsher 
10609aebddd1SJeff Kirsher /* Uses Mbox */
106110ef9ab4SSathya Perla int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
106210ef9ab4SSathya Perla 		     struct be_queue_info *eq, bool no_delay, int coalesce_wm)
10639aebddd1SJeff Kirsher {
10649aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
10659aebddd1SJeff Kirsher 	struct be_cmd_req_cq_create *req;
10669aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &cq->dma_mem;
10679aebddd1SJeff Kirsher 	void *ctxt;
10689aebddd1SJeff Kirsher 	int status;
10699aebddd1SJeff Kirsher 
10709aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
10719aebddd1SJeff Kirsher 		return -1;
10729aebddd1SJeff Kirsher 
10739aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
10749aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10759aebddd1SJeff Kirsher 	ctxt = &req->context;
10769aebddd1SJeff Kirsher 
1077106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1078a2cc4e0bSSathya Perla 			       OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb,
1079a2cc4e0bSSathya Perla 			       NULL);
10809aebddd1SJeff Kirsher 
10819aebddd1SJeff Kirsher 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
1082bbdc42f8SAjit Khaparde 
1083bbdc42f8SAjit Khaparde 	if (BEx_chip(adapter)) {
10849aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
10859aebddd1SJeff Kirsher 			      coalesce_wm);
10869aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, nodelay,
10879aebddd1SJeff Kirsher 			      ctxt, no_delay);
10889aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
10899aebddd1SJeff Kirsher 			      __ilog2_u32(cq->len / 256));
10909aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
10919aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
10929aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
1093bbdc42f8SAjit Khaparde 	} else {
1094bbdc42f8SAjit Khaparde 		req->hdr.version = 2;
1095bbdc42f8SAjit Khaparde 		req->page_size = 1; /* 1 for 4K */
109609e83a9dSAjit Khaparde 
109709e83a9dSAjit Khaparde 		/* coalesce-wm field in this cmd is not relevant to Lancer.
109809e83a9dSAjit Khaparde 		 * Lancer uses COMMON_MODIFY_CQ to set this field
109909e83a9dSAjit Khaparde 		 */
110009e83a9dSAjit Khaparde 		if (!lancer_chip(adapter))
110109e83a9dSAjit Khaparde 			AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
110209e83a9dSAjit Khaparde 				      ctxt, coalesce_wm);
1103bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt,
1104bbdc42f8SAjit Khaparde 			      no_delay);
1105bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
1106bbdc42f8SAjit Khaparde 			      __ilog2_u32(cq->len / 256));
1107bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
1108a2cc4e0bSSathya Perla 		AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
1109a2cc4e0bSSathya Perla 		AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
11109aebddd1SJeff Kirsher 	}
11119aebddd1SJeff Kirsher 
11129aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
11139aebddd1SJeff Kirsher 
11149aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
11159aebddd1SJeff Kirsher 
11169aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
11179aebddd1SJeff Kirsher 	if (!status) {
11189aebddd1SJeff Kirsher 		struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
111903d28ffeSKalesh AP 
11209aebddd1SJeff Kirsher 		cq->id = le16_to_cpu(resp->cq_id);
11219aebddd1SJeff Kirsher 		cq->created = true;
11229aebddd1SJeff Kirsher 	}
11239aebddd1SJeff Kirsher 
11249aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
11259aebddd1SJeff Kirsher 
11269aebddd1SJeff Kirsher 	return status;
11279aebddd1SJeff Kirsher }
11289aebddd1SJeff Kirsher 
11299aebddd1SJeff Kirsher static u32 be_encoded_q_len(int q_len)
11309aebddd1SJeff Kirsher {
11319aebddd1SJeff Kirsher 	u32 len_encoded = fls(q_len); /* log2(len) + 1 */
113203d28ffeSKalesh AP 
11339aebddd1SJeff Kirsher 	if (len_encoded == 16)
11349aebddd1SJeff Kirsher 		len_encoded = 0;
11359aebddd1SJeff Kirsher 	return len_encoded;
11369aebddd1SJeff Kirsher }
11379aebddd1SJeff Kirsher 
11384188e7dfSJingoo Han static int be_cmd_mccq_ext_create(struct be_adapter *adapter,
11399aebddd1SJeff Kirsher 				  struct be_queue_info *mccq,
11409aebddd1SJeff Kirsher 				  struct be_queue_info *cq)
11419aebddd1SJeff Kirsher {
11429aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
11439aebddd1SJeff Kirsher 	struct be_cmd_req_mcc_ext_create *req;
11449aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &mccq->dma_mem;
11459aebddd1SJeff Kirsher 	void *ctxt;
11469aebddd1SJeff Kirsher 	int status;
11479aebddd1SJeff Kirsher 
11489aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
11499aebddd1SJeff Kirsher 		return -1;
11509aebddd1SJeff Kirsher 
11519aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
11529aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
11539aebddd1SJeff Kirsher 	ctxt = &req->context;
11549aebddd1SJeff Kirsher 
1155106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1156a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb,
1157a2cc4e0bSSathya Perla 			       NULL);
11589aebddd1SJeff Kirsher 
11599aebddd1SJeff Kirsher 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
1160666d39c7SVasundhara Volam 	if (BEx_chip(adapter)) {
11619aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
11629aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
11639aebddd1SJeff Kirsher 			      be_encoded_q_len(mccq->len));
11649aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
1165666d39c7SVasundhara Volam 	} else {
1166666d39c7SVasundhara Volam 		req->hdr.version = 1;
1167666d39c7SVasundhara Volam 		req->cq_id = cpu_to_le16(cq->id);
1168666d39c7SVasundhara Volam 
1169666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt,
1170666d39c7SVasundhara Volam 			      be_encoded_q_len(mccq->len));
1171666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1);
1172666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id,
1173666d39c7SVasundhara Volam 			      ctxt, cq->id);
1174666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid,
1175666d39c7SVasundhara Volam 			      ctxt, 1);
11769aebddd1SJeff Kirsher 	}
11779aebddd1SJeff Kirsher 
117821252377SVasundhara Volam 	/* Subscribe to Link State, Sliport Event and Group 5 Events
117921252377SVasundhara Volam 	 * (bits 1, 5 and 17 set)
118021252377SVasundhara Volam 	 */
118121252377SVasundhara Volam 	req->async_event_bitmap[0] =
118221252377SVasundhara Volam 			cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) |
118321252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_GRP_5) |
118421252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_QNQ) |
118521252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_SLIPORT));
118621252377SVasundhara Volam 
11879aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
11889aebddd1SJeff Kirsher 
11899aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
11909aebddd1SJeff Kirsher 
11919aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
11929aebddd1SJeff Kirsher 	if (!status) {
11939aebddd1SJeff Kirsher 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
119403d28ffeSKalesh AP 
11959aebddd1SJeff Kirsher 		mccq->id = le16_to_cpu(resp->id);
11969aebddd1SJeff Kirsher 		mccq->created = true;
11979aebddd1SJeff Kirsher 	}
11989aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
11999aebddd1SJeff Kirsher 
12009aebddd1SJeff Kirsher 	return status;
12019aebddd1SJeff Kirsher }
12029aebddd1SJeff Kirsher 
12034188e7dfSJingoo Han static int be_cmd_mccq_org_create(struct be_adapter *adapter,
12049aebddd1SJeff Kirsher 				  struct be_queue_info *mccq,
12059aebddd1SJeff Kirsher 				  struct be_queue_info *cq)
12069aebddd1SJeff Kirsher {
12079aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
12089aebddd1SJeff Kirsher 	struct be_cmd_req_mcc_create *req;
12099aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &mccq->dma_mem;
12109aebddd1SJeff Kirsher 	void *ctxt;
12119aebddd1SJeff Kirsher 	int status;
12129aebddd1SJeff Kirsher 
12139aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
12149aebddd1SJeff Kirsher 		return -1;
12159aebddd1SJeff Kirsher 
12169aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
12179aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
12189aebddd1SJeff Kirsher 	ctxt = &req->context;
12199aebddd1SJeff Kirsher 
1220106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1221a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb,
1222a2cc4e0bSSathya Perla 			       NULL);
12239aebddd1SJeff Kirsher 
12249aebddd1SJeff Kirsher 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
12259aebddd1SJeff Kirsher 
12269aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
12279aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
12289aebddd1SJeff Kirsher 		      be_encoded_q_len(mccq->len));
12299aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
12309aebddd1SJeff Kirsher 
12319aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
12329aebddd1SJeff Kirsher 
12339aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
12349aebddd1SJeff Kirsher 
12359aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
12369aebddd1SJeff Kirsher 	if (!status) {
12379aebddd1SJeff Kirsher 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
123803d28ffeSKalesh AP 
12399aebddd1SJeff Kirsher 		mccq->id = le16_to_cpu(resp->id);
12409aebddd1SJeff Kirsher 		mccq->created = true;
12419aebddd1SJeff Kirsher 	}
12429aebddd1SJeff Kirsher 
12439aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
12449aebddd1SJeff Kirsher 	return status;
12459aebddd1SJeff Kirsher }
12469aebddd1SJeff Kirsher 
12479aebddd1SJeff Kirsher int be_cmd_mccq_create(struct be_adapter *adapter,
1248a2cc4e0bSSathya Perla 		       struct be_queue_info *mccq, struct be_queue_info *cq)
12499aebddd1SJeff Kirsher {
12509aebddd1SJeff Kirsher 	int status;
12519aebddd1SJeff Kirsher 
12529aebddd1SJeff Kirsher 	status = be_cmd_mccq_ext_create(adapter, mccq, cq);
1253666d39c7SVasundhara Volam 	if (status && BEx_chip(adapter)) {
12549aebddd1SJeff Kirsher 		dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
12559aebddd1SJeff Kirsher 			"or newer to avoid conflicting priorities between NIC "
12569aebddd1SJeff Kirsher 			"and FCoE traffic");
12579aebddd1SJeff Kirsher 		status = be_cmd_mccq_org_create(adapter, mccq, cq);
12589aebddd1SJeff Kirsher 	}
12599aebddd1SJeff Kirsher 	return status;
12609aebddd1SJeff Kirsher }
12619aebddd1SJeff Kirsher 
126294d73aaaSVasundhara Volam int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo)
12639aebddd1SJeff Kirsher {
12647707133cSSathya Perla 	struct be_mcc_wrb wrb = {0};
12659aebddd1SJeff Kirsher 	struct be_cmd_req_eth_tx_create *req;
126694d73aaaSVasundhara Volam 	struct be_queue_info *txq = &txo->q;
126794d73aaaSVasundhara Volam 	struct be_queue_info *cq = &txo->cq;
12689aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &txq->dma_mem;
126994d73aaaSVasundhara Volam 	int status, ver = 0;
12709aebddd1SJeff Kirsher 
12717707133cSSathya Perla 	req = embedded_payload(&wrb);
1272106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
12737707133cSSathya Perla 			       OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL);
12749aebddd1SJeff Kirsher 
12759aebddd1SJeff Kirsher 	if (lancer_chip(adapter)) {
12769aebddd1SJeff Kirsher 		req->hdr.version = 1;
127794d73aaaSVasundhara Volam 	} else if (BEx_chip(adapter)) {
127894d73aaaSVasundhara Volam 		if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC)
127994d73aaaSVasundhara Volam 			req->hdr.version = 2;
128094d73aaaSVasundhara Volam 	} else { /* For SH */
128194d73aaaSVasundhara Volam 		req->hdr.version = 2;
12829aebddd1SJeff Kirsher 	}
12839aebddd1SJeff Kirsher 
128481b02655SVasundhara Volam 	if (req->hdr.version > 0)
128581b02655SVasundhara Volam 		req->if_id = cpu_to_le16(adapter->if_handle);
12869aebddd1SJeff Kirsher 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
12879aebddd1SJeff Kirsher 	req->ulp_num = BE_ULP1_NUM;
12889aebddd1SJeff Kirsher 	req->type = BE_ETH_TX_RING_TYPE_STANDARD;
128994d73aaaSVasundhara Volam 	req->cq_id = cpu_to_le16(cq->id);
129094d73aaaSVasundhara Volam 	req->queue_size = be_encoded_q_len(txq->len);
12919aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
129294d73aaaSVasundhara Volam 	ver = req->hdr.version;
129394d73aaaSVasundhara Volam 
12947707133cSSathya Perla 	status = be_cmd_notify_wait(adapter, &wrb);
12959aebddd1SJeff Kirsher 	if (!status) {
12967707133cSSathya Perla 		struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb);
129703d28ffeSKalesh AP 
12989aebddd1SJeff Kirsher 		txq->id = le16_to_cpu(resp->cid);
129994d73aaaSVasundhara Volam 		if (ver == 2)
130094d73aaaSVasundhara Volam 			txo->db_offset = le32_to_cpu(resp->db_offset);
130194d73aaaSVasundhara Volam 		else
130294d73aaaSVasundhara Volam 			txo->db_offset = DB_TXULP1_OFFSET;
13039aebddd1SJeff Kirsher 		txq->created = true;
13049aebddd1SJeff Kirsher 	}
13059aebddd1SJeff Kirsher 
13069aebddd1SJeff Kirsher 	return status;
13079aebddd1SJeff Kirsher }
13089aebddd1SJeff Kirsher 
13099aebddd1SJeff Kirsher /* Uses MCC */
13109aebddd1SJeff Kirsher int be_cmd_rxq_create(struct be_adapter *adapter,
13119aebddd1SJeff Kirsher 		      struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
131210ef9ab4SSathya Perla 		      u32 if_id, u32 rss, u8 *rss_id)
13139aebddd1SJeff Kirsher {
13149aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
13159aebddd1SJeff Kirsher 	struct be_cmd_req_eth_rx_create *req;
13169aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &rxq->dma_mem;
13179aebddd1SJeff Kirsher 	int status;
13189aebddd1SJeff Kirsher 
13199aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
13209aebddd1SJeff Kirsher 
13219aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
13229aebddd1SJeff Kirsher 	if (!wrb) {
13239aebddd1SJeff Kirsher 		status = -EBUSY;
13249aebddd1SJeff Kirsher 		goto err;
13259aebddd1SJeff Kirsher 	}
13269aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
13279aebddd1SJeff Kirsher 
1328106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1329106df1e3SSomnath Kotur 			       OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL);
13309aebddd1SJeff Kirsher 
13319aebddd1SJeff Kirsher 	req->cq_id = cpu_to_le16(cq_id);
13329aebddd1SJeff Kirsher 	req->frag_size = fls(frag_size) - 1;
13339aebddd1SJeff Kirsher 	req->num_pages = 2;
13349aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
13359aebddd1SJeff Kirsher 	req->interface_id = cpu_to_le32(if_id);
133610ef9ab4SSathya Perla 	req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE);
13379aebddd1SJeff Kirsher 	req->rss_queue = cpu_to_le32(rss);
13389aebddd1SJeff Kirsher 
13399aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
13409aebddd1SJeff Kirsher 	if (!status) {
13419aebddd1SJeff Kirsher 		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
134203d28ffeSKalesh AP 
13439aebddd1SJeff Kirsher 		rxq->id = le16_to_cpu(resp->id);
13449aebddd1SJeff Kirsher 		rxq->created = true;
13459aebddd1SJeff Kirsher 		*rss_id = resp->rss_id;
13469aebddd1SJeff Kirsher 	}
13479aebddd1SJeff Kirsher 
13489aebddd1SJeff Kirsher err:
13499aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
13509aebddd1SJeff Kirsher 	return status;
13519aebddd1SJeff Kirsher }
13529aebddd1SJeff Kirsher 
13539aebddd1SJeff Kirsher /* Generic destroyer function for all types of queues
13549aebddd1SJeff Kirsher  * Uses Mbox
13559aebddd1SJeff Kirsher  */
13569aebddd1SJeff Kirsher int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
13579aebddd1SJeff Kirsher 		     int queue_type)
13589aebddd1SJeff Kirsher {
13599aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
13609aebddd1SJeff Kirsher 	struct be_cmd_req_q_destroy *req;
13619aebddd1SJeff Kirsher 	u8 subsys = 0, opcode = 0;
13629aebddd1SJeff Kirsher 	int status;
13639aebddd1SJeff Kirsher 
13649aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
13659aebddd1SJeff Kirsher 		return -1;
13669aebddd1SJeff Kirsher 
13679aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
13689aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
13699aebddd1SJeff Kirsher 
13709aebddd1SJeff Kirsher 	switch (queue_type) {
13719aebddd1SJeff Kirsher 	case QTYPE_EQ:
13729aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
13739aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_EQ_DESTROY;
13749aebddd1SJeff Kirsher 		break;
13759aebddd1SJeff Kirsher 	case QTYPE_CQ:
13769aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
13779aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_CQ_DESTROY;
13789aebddd1SJeff Kirsher 		break;
13799aebddd1SJeff Kirsher 	case QTYPE_TXQ:
13809aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_ETH;
13819aebddd1SJeff Kirsher 		opcode = OPCODE_ETH_TX_DESTROY;
13829aebddd1SJeff Kirsher 		break;
13839aebddd1SJeff Kirsher 	case QTYPE_RXQ:
13849aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_ETH;
13859aebddd1SJeff Kirsher 		opcode = OPCODE_ETH_RX_DESTROY;
13869aebddd1SJeff Kirsher 		break;
13879aebddd1SJeff Kirsher 	case QTYPE_MCCQ:
13889aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
13899aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_MCC_DESTROY;
13909aebddd1SJeff Kirsher 		break;
13919aebddd1SJeff Kirsher 	default:
13929aebddd1SJeff Kirsher 		BUG();
13939aebddd1SJeff Kirsher 	}
13949aebddd1SJeff Kirsher 
1395106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb,
1396106df1e3SSomnath Kotur 			       NULL);
13979aebddd1SJeff Kirsher 	req->id = cpu_to_le16(q->id);
13989aebddd1SJeff Kirsher 
13999aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
14009aebddd1SJeff Kirsher 	q->created = false;
14019aebddd1SJeff Kirsher 
14029aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
14039aebddd1SJeff Kirsher 	return status;
14049aebddd1SJeff Kirsher }
14059aebddd1SJeff Kirsher 
14069aebddd1SJeff Kirsher /* Uses MCC */
14079aebddd1SJeff Kirsher int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
14089aebddd1SJeff Kirsher {
14099aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
14109aebddd1SJeff Kirsher 	struct be_cmd_req_q_destroy *req;
14119aebddd1SJeff Kirsher 	int status;
14129aebddd1SJeff Kirsher 
14139aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
14149aebddd1SJeff Kirsher 
14159aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
14169aebddd1SJeff Kirsher 	if (!wrb) {
14179aebddd1SJeff Kirsher 		status = -EBUSY;
14189aebddd1SJeff Kirsher 		goto err;
14199aebddd1SJeff Kirsher 	}
14209aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
14219aebddd1SJeff Kirsher 
1422106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1423106df1e3SSomnath Kotur 			       OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL);
14249aebddd1SJeff Kirsher 	req->id = cpu_to_le16(q->id);
14259aebddd1SJeff Kirsher 
14269aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
14279aebddd1SJeff Kirsher 	q->created = false;
14289aebddd1SJeff Kirsher 
14299aebddd1SJeff Kirsher err:
14309aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
14319aebddd1SJeff Kirsher 	return status;
14329aebddd1SJeff Kirsher }
14339aebddd1SJeff Kirsher 
14349aebddd1SJeff Kirsher /* Create an rx filtering policy configuration on an i/f
1435bea50988SSathya Perla  * Will use MBOX only if MCCQ has not been created.
14369aebddd1SJeff Kirsher  */
14379aebddd1SJeff Kirsher int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
14381578e777SPadmanabh Ratnakar 		     u32 *if_handle, u32 domain)
14399aebddd1SJeff Kirsher {
1440bea50988SSathya Perla 	struct be_mcc_wrb wrb = {0};
14419aebddd1SJeff Kirsher 	struct be_cmd_req_if_create *req;
14429aebddd1SJeff Kirsher 	int status;
14439aebddd1SJeff Kirsher 
1444bea50988SSathya Perla 	req = embedded_payload(&wrb);
1445106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1446a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_INTERFACE_CREATE,
1447a2cc4e0bSSathya Perla 			       sizeof(*req), &wrb, NULL);
14489aebddd1SJeff Kirsher 	req->hdr.domain = domain;
14499aebddd1SJeff Kirsher 	req->capability_flags = cpu_to_le32(cap_flags);
14509aebddd1SJeff Kirsher 	req->enable_flags = cpu_to_le32(en_flags);
1451f9449ab7SSathya Perla 	req->pmac_invalid = true;
14529aebddd1SJeff Kirsher 
1453bea50988SSathya Perla 	status = be_cmd_notify_wait(adapter, &wrb);
14549aebddd1SJeff Kirsher 	if (!status) {
1455bea50988SSathya Perla 		struct be_cmd_resp_if_create *resp = embedded_payload(&wrb);
145603d28ffeSKalesh AP 
14579aebddd1SJeff Kirsher 		*if_handle = le32_to_cpu(resp->interface_id);
1458b5bb9776SSathya Perla 
1459b5bb9776SSathya Perla 		/* Hack to retrieve VF's pmac-id on BE3 */
1460b5bb9776SSathya Perla 		if (BE3_chip(adapter) && !be_physfn(adapter))
1461b5bb9776SSathya Perla 			adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id);
14629aebddd1SJeff Kirsher 	}
14639aebddd1SJeff Kirsher 	return status;
14649aebddd1SJeff Kirsher }
14659aebddd1SJeff Kirsher 
1466f9449ab7SSathya Perla /* Uses MCCQ */
146730128031SSathya Perla int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain)
14689aebddd1SJeff Kirsher {
14699aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
14709aebddd1SJeff Kirsher 	struct be_cmd_req_if_destroy *req;
14719aebddd1SJeff Kirsher 	int status;
14729aebddd1SJeff Kirsher 
147330128031SSathya Perla 	if (interface_id == -1)
1474f9449ab7SSathya Perla 		return 0;
14759aebddd1SJeff Kirsher 
1476f9449ab7SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
1477f9449ab7SSathya Perla 
1478f9449ab7SSathya Perla 	wrb = wrb_from_mccq(adapter);
1479f9449ab7SSathya Perla 	if (!wrb) {
1480f9449ab7SSathya Perla 		status = -EBUSY;
1481f9449ab7SSathya Perla 		goto err;
1482f9449ab7SSathya Perla 	}
14839aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
14849aebddd1SJeff Kirsher 
1485106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1486a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_INTERFACE_DESTROY,
1487a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
14889aebddd1SJeff Kirsher 	req->hdr.domain = domain;
14899aebddd1SJeff Kirsher 	req->interface_id = cpu_to_le32(interface_id);
14909aebddd1SJeff Kirsher 
1491f9449ab7SSathya Perla 	status = be_mcc_notify_wait(adapter);
1492f9449ab7SSathya Perla err:
1493f9449ab7SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
14949aebddd1SJeff Kirsher 	return status;
14959aebddd1SJeff Kirsher }
14969aebddd1SJeff Kirsher 
14979aebddd1SJeff Kirsher /* Get stats is a non embedded command: the request is not embedded inside
14989aebddd1SJeff Kirsher  * WRB but is a separate dma memory block
14999aebddd1SJeff Kirsher  * Uses asynchronous MCC
15009aebddd1SJeff Kirsher  */
15019aebddd1SJeff Kirsher int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
15029aebddd1SJeff Kirsher {
15039aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15049aebddd1SJeff Kirsher 	struct be_cmd_req_hdr *hdr;
15059aebddd1SJeff Kirsher 	int status = 0;
15069aebddd1SJeff Kirsher 
15079aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
15089aebddd1SJeff Kirsher 
15099aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
15109aebddd1SJeff Kirsher 	if (!wrb) {
15119aebddd1SJeff Kirsher 		status = -EBUSY;
15129aebddd1SJeff Kirsher 		goto err;
15139aebddd1SJeff Kirsher 	}
15149aebddd1SJeff Kirsher 	hdr = nonemb_cmd->va;
15159aebddd1SJeff Kirsher 
1516106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
1517a2cc4e0bSSathya Perla 			       OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb,
1518a2cc4e0bSSathya Perla 			       nonemb_cmd);
15199aebddd1SJeff Kirsher 
1520ca34fe38SSathya Perla 	/* version 1 of the cmd is not supported only by BE2 */
152161000861SAjit Khaparde 	if (BE2_chip(adapter))
152261000861SAjit Khaparde 		hdr->version = 0;
152361000861SAjit Khaparde 	if (BE3_chip(adapter) || lancer_chip(adapter))
15249aebddd1SJeff Kirsher 		hdr->version = 1;
152561000861SAjit Khaparde 	else
152661000861SAjit Khaparde 		hdr->version = 2;
15279aebddd1SJeff Kirsher 
15289aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
15299aebddd1SJeff Kirsher 	adapter->stats_cmd_sent = true;
15309aebddd1SJeff Kirsher 
15319aebddd1SJeff Kirsher err:
15329aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
15339aebddd1SJeff Kirsher 	return status;
15349aebddd1SJeff Kirsher }
15359aebddd1SJeff Kirsher 
15369aebddd1SJeff Kirsher /* Lancer Stats */
15379aebddd1SJeff Kirsher int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
15389aebddd1SJeff Kirsher 			       struct be_dma_mem *nonemb_cmd)
15399aebddd1SJeff Kirsher {
15409aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15419aebddd1SJeff Kirsher 	struct lancer_cmd_req_pport_stats *req;
15429aebddd1SJeff Kirsher 	int status = 0;
15439aebddd1SJeff Kirsher 
1544f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
1545f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_ETH))
1546f25b119cSPadmanabh Ratnakar 		return -EPERM;
1547f25b119cSPadmanabh Ratnakar 
15489aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
15499aebddd1SJeff Kirsher 
15509aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
15519aebddd1SJeff Kirsher 	if (!wrb) {
15529aebddd1SJeff Kirsher 		status = -EBUSY;
15539aebddd1SJeff Kirsher 		goto err;
15549aebddd1SJeff Kirsher 	}
15559aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
15569aebddd1SJeff Kirsher 
1557106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1558a2cc4e0bSSathya Perla 			       OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size,
1559a2cc4e0bSSathya Perla 			       wrb, nonemb_cmd);
15609aebddd1SJeff Kirsher 
1561d51ebd33SPadmanabh Ratnakar 	req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num);
15629aebddd1SJeff Kirsher 	req->cmd_params.params.reset_stats = 0;
15639aebddd1SJeff Kirsher 
15649aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
15659aebddd1SJeff Kirsher 	adapter->stats_cmd_sent = true;
15669aebddd1SJeff Kirsher 
15679aebddd1SJeff Kirsher err:
15689aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
15699aebddd1SJeff Kirsher 	return status;
15709aebddd1SJeff Kirsher }
15719aebddd1SJeff Kirsher 
1572323ff71eSSathya Perla static int be_mac_to_link_speed(int mac_speed)
1573323ff71eSSathya Perla {
1574323ff71eSSathya Perla 	switch (mac_speed) {
1575323ff71eSSathya Perla 	case PHY_LINK_SPEED_ZERO:
1576323ff71eSSathya Perla 		return 0;
1577323ff71eSSathya Perla 	case PHY_LINK_SPEED_10MBPS:
1578323ff71eSSathya Perla 		return 10;
1579323ff71eSSathya Perla 	case PHY_LINK_SPEED_100MBPS:
1580323ff71eSSathya Perla 		return 100;
1581323ff71eSSathya Perla 	case PHY_LINK_SPEED_1GBPS:
1582323ff71eSSathya Perla 		return 1000;
1583323ff71eSSathya Perla 	case PHY_LINK_SPEED_10GBPS:
1584323ff71eSSathya Perla 		return 10000;
1585b971f847SVasundhara Volam 	case PHY_LINK_SPEED_20GBPS:
1586b971f847SVasundhara Volam 		return 20000;
1587b971f847SVasundhara Volam 	case PHY_LINK_SPEED_25GBPS:
1588b971f847SVasundhara Volam 		return 25000;
1589b971f847SVasundhara Volam 	case PHY_LINK_SPEED_40GBPS:
1590b971f847SVasundhara Volam 		return 40000;
1591323ff71eSSathya Perla 	}
1592323ff71eSSathya Perla 	return 0;
1593323ff71eSSathya Perla }
1594323ff71eSSathya Perla 
1595323ff71eSSathya Perla /* Uses synchronous mcc
1596323ff71eSSathya Perla  * Returns link_speed in Mbps
1597323ff71eSSathya Perla  */
1598323ff71eSSathya Perla int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
1599323ff71eSSathya Perla 			     u8 *link_status, u32 dom)
16009aebddd1SJeff Kirsher {
16019aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
16029aebddd1SJeff Kirsher 	struct be_cmd_req_link_status *req;
16039aebddd1SJeff Kirsher 	int status;
16049aebddd1SJeff Kirsher 
16059aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16069aebddd1SJeff Kirsher 
1607b236916aSAjit Khaparde 	if (link_status)
1608b236916aSAjit Khaparde 		*link_status = LINK_DOWN;
1609b236916aSAjit Khaparde 
16109aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16119aebddd1SJeff Kirsher 	if (!wrb) {
16129aebddd1SJeff Kirsher 		status = -EBUSY;
16139aebddd1SJeff Kirsher 		goto err;
16149aebddd1SJeff Kirsher 	}
16159aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
16169aebddd1SJeff Kirsher 
161757cd80d4SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1618a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_LINK_STATUS_QUERY,
1619a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
162057cd80d4SPadmanabh Ratnakar 
1621ca34fe38SSathya Perla 	/* version 1 of the cmd is not supported only by BE2 */
1622ca34fe38SSathya Perla 	if (!BE2_chip(adapter))
1623daad6167SPadmanabh Ratnakar 		req->hdr.version = 1;
1624daad6167SPadmanabh Ratnakar 
162557cd80d4SPadmanabh Ratnakar 	req->hdr.domain = dom;
16269aebddd1SJeff Kirsher 
16279aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
16289aebddd1SJeff Kirsher 	if (!status) {
16299aebddd1SJeff Kirsher 		struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
163003d28ffeSKalesh AP 
1631323ff71eSSathya Perla 		if (link_speed) {
1632323ff71eSSathya Perla 			*link_speed = resp->link_speed ?
1633323ff71eSSathya Perla 				      le16_to_cpu(resp->link_speed) * 10 :
1634323ff71eSSathya Perla 				      be_mac_to_link_speed(resp->mac_speed);
1635323ff71eSSathya Perla 
1636323ff71eSSathya Perla 			if (!resp->logical_link_status)
1637323ff71eSSathya Perla 				*link_speed = 0;
16389aebddd1SJeff Kirsher 		}
1639b236916aSAjit Khaparde 		if (link_status)
1640b236916aSAjit Khaparde 			*link_status = resp->logical_link_status;
16419aebddd1SJeff Kirsher 	}
16429aebddd1SJeff Kirsher 
16439aebddd1SJeff Kirsher err:
16449aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
16459aebddd1SJeff Kirsher 	return status;
16469aebddd1SJeff Kirsher }
16479aebddd1SJeff Kirsher 
16489aebddd1SJeff Kirsher /* Uses synchronous mcc */
16499aebddd1SJeff Kirsher int be_cmd_get_die_temperature(struct be_adapter *adapter)
16509aebddd1SJeff Kirsher {
16519aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
16529aebddd1SJeff Kirsher 	struct be_cmd_req_get_cntl_addnl_attribs *req;
1653117affe3SVasundhara Volam 	int status = 0;
16549aebddd1SJeff Kirsher 
16559aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16569aebddd1SJeff Kirsher 
16579aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16589aebddd1SJeff Kirsher 	if (!wrb) {
16599aebddd1SJeff Kirsher 		status = -EBUSY;
16609aebddd1SJeff Kirsher 		goto err;
16619aebddd1SJeff Kirsher 	}
16629aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
16639aebddd1SJeff Kirsher 
1664106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1665a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES,
1666a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
16679aebddd1SJeff Kirsher 
16683de09455SSomnath Kotur 	be_mcc_notify(adapter);
16699aebddd1SJeff Kirsher 
16709aebddd1SJeff Kirsher err:
16719aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
16729aebddd1SJeff Kirsher 	return status;
16739aebddd1SJeff Kirsher }
16749aebddd1SJeff Kirsher 
16759aebddd1SJeff Kirsher /* Uses synchronous mcc */
16769aebddd1SJeff Kirsher int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size)
16779aebddd1SJeff Kirsher {
16789aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
16799aebddd1SJeff Kirsher 	struct be_cmd_req_get_fat *req;
16809aebddd1SJeff Kirsher 	int status;
16819aebddd1SJeff Kirsher 
16829aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16839aebddd1SJeff Kirsher 
16849aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16859aebddd1SJeff Kirsher 	if (!wrb) {
16869aebddd1SJeff Kirsher 		status = -EBUSY;
16879aebddd1SJeff Kirsher 		goto err;
16889aebddd1SJeff Kirsher 	}
16899aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
16909aebddd1SJeff Kirsher 
1691106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1692a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MANAGE_FAT, sizeof(*req), wrb,
1693a2cc4e0bSSathya Perla 			       NULL);
16949aebddd1SJeff Kirsher 	req->fat_operation = cpu_to_le32(QUERY_FAT);
16959aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
16969aebddd1SJeff Kirsher 	if (!status) {
16979aebddd1SJeff Kirsher 		struct be_cmd_resp_get_fat *resp = embedded_payload(wrb);
169803d28ffeSKalesh AP 
16999aebddd1SJeff Kirsher 		if (log_size && resp->log_size)
17009aebddd1SJeff Kirsher 			*log_size = le32_to_cpu(resp->log_size) -
17019aebddd1SJeff Kirsher 					sizeof(u32);
17029aebddd1SJeff Kirsher 	}
17039aebddd1SJeff Kirsher err:
17049aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
17059aebddd1SJeff Kirsher 	return status;
17069aebddd1SJeff Kirsher }
17079aebddd1SJeff Kirsher 
1708c5f156deSVasundhara Volam int be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf)
17099aebddd1SJeff Kirsher {
17109aebddd1SJeff Kirsher 	struct be_dma_mem get_fat_cmd;
17119aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
17129aebddd1SJeff Kirsher 	struct be_cmd_req_get_fat *req;
17139aebddd1SJeff Kirsher 	u32 offset = 0, total_size, buf_size,
17149aebddd1SJeff Kirsher 				log_offset = sizeof(u32), payload_len;
1715c5f156deSVasundhara Volam 	int status = 0;
17169aebddd1SJeff Kirsher 
17179aebddd1SJeff Kirsher 	if (buf_len == 0)
1718c5f156deSVasundhara Volam 		return -EIO;
17199aebddd1SJeff Kirsher 
17209aebddd1SJeff Kirsher 	total_size = buf_len;
17219aebddd1SJeff Kirsher 
17229aebddd1SJeff Kirsher 	get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
17239aebddd1SJeff Kirsher 	get_fat_cmd.va = pci_alloc_consistent(adapter->pdev,
17249aebddd1SJeff Kirsher 					      get_fat_cmd.size,
17259aebddd1SJeff Kirsher 					      &get_fat_cmd.dma);
17269aebddd1SJeff Kirsher 	if (!get_fat_cmd.va) {
17279aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev,
1728cd3307aaSKalesh AP 			"Memory allocation failure while reading FAT data\n");
1729c5f156deSVasundhara Volam 		return -ENOMEM;
17309aebddd1SJeff Kirsher 	}
17319aebddd1SJeff Kirsher 
17329aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
17339aebddd1SJeff Kirsher 
17349aebddd1SJeff Kirsher 	while (total_size) {
17359aebddd1SJeff Kirsher 		buf_size = min(total_size, (u32)60*1024);
17369aebddd1SJeff Kirsher 		total_size -= buf_size;
17379aebddd1SJeff Kirsher 
17389aebddd1SJeff Kirsher 		wrb = wrb_from_mccq(adapter);
17399aebddd1SJeff Kirsher 		if (!wrb) {
17409aebddd1SJeff Kirsher 			status = -EBUSY;
17419aebddd1SJeff Kirsher 			goto err;
17429aebddd1SJeff Kirsher 		}
17439aebddd1SJeff Kirsher 		req = get_fat_cmd.va;
17449aebddd1SJeff Kirsher 
17459aebddd1SJeff Kirsher 		payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size;
1746106df1e3SSomnath Kotur 		be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1747a2cc4e0bSSathya Perla 				       OPCODE_COMMON_MANAGE_FAT, payload_len,
1748a2cc4e0bSSathya Perla 				       wrb, &get_fat_cmd);
17499aebddd1SJeff Kirsher 
17509aebddd1SJeff Kirsher 		req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
17519aebddd1SJeff Kirsher 		req->read_log_offset = cpu_to_le32(log_offset);
17529aebddd1SJeff Kirsher 		req->read_log_length = cpu_to_le32(buf_size);
17539aebddd1SJeff Kirsher 		req->data_buffer_size = cpu_to_le32(buf_size);
17549aebddd1SJeff Kirsher 
17559aebddd1SJeff Kirsher 		status = be_mcc_notify_wait(adapter);
17569aebddd1SJeff Kirsher 		if (!status) {
17579aebddd1SJeff Kirsher 			struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
175803d28ffeSKalesh AP 
17599aebddd1SJeff Kirsher 			memcpy(buf + offset,
17609aebddd1SJeff Kirsher 			       resp->data_buffer,
176192aa9214SSomnath Kotur 			       le32_to_cpu(resp->read_log_length));
17629aebddd1SJeff Kirsher 		} else {
17639aebddd1SJeff Kirsher 			dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
17649aebddd1SJeff Kirsher 			goto err;
17659aebddd1SJeff Kirsher 		}
17669aebddd1SJeff Kirsher 		offset += buf_size;
17679aebddd1SJeff Kirsher 		log_offset += buf_size;
17689aebddd1SJeff Kirsher 	}
17699aebddd1SJeff Kirsher err:
17709aebddd1SJeff Kirsher 	pci_free_consistent(adapter->pdev, get_fat_cmd.size,
1771a2cc4e0bSSathya Perla 			    get_fat_cmd.va, get_fat_cmd.dma);
17729aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1773c5f156deSVasundhara Volam 	return status;
17749aebddd1SJeff Kirsher }
17759aebddd1SJeff Kirsher 
177604b71175SSathya Perla /* Uses synchronous mcc */
1777e97e3cdaSKalesh AP int be_cmd_get_fw_ver(struct be_adapter *adapter)
17789aebddd1SJeff Kirsher {
17799aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
17809aebddd1SJeff Kirsher 	struct be_cmd_req_get_fw_version *req;
17819aebddd1SJeff Kirsher 	int status;
17829aebddd1SJeff Kirsher 
178304b71175SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
17849aebddd1SJeff Kirsher 
178504b71175SSathya Perla 	wrb = wrb_from_mccq(adapter);
178604b71175SSathya Perla 	if (!wrb) {
178704b71175SSathya Perla 		status = -EBUSY;
178804b71175SSathya Perla 		goto err;
178904b71175SSathya Perla 	}
179004b71175SSathya Perla 
17919aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
17929aebddd1SJeff Kirsher 
1793106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1794a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb,
1795a2cc4e0bSSathya Perla 			       NULL);
179604b71175SSathya Perla 	status = be_mcc_notify_wait(adapter);
17979aebddd1SJeff Kirsher 	if (!status) {
17989aebddd1SJeff Kirsher 		struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
1799acbafeb1SSathya Perla 
1800242eb470SVasundhara Volam 		strlcpy(adapter->fw_ver, resp->firmware_version_string,
1801242eb470SVasundhara Volam 			sizeof(adapter->fw_ver));
1802242eb470SVasundhara Volam 		strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string,
1803242eb470SVasundhara Volam 			sizeof(adapter->fw_on_flash));
18049aebddd1SJeff Kirsher 	}
180504b71175SSathya Perla err:
180604b71175SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
18079aebddd1SJeff Kirsher 	return status;
18089aebddd1SJeff Kirsher }
18099aebddd1SJeff Kirsher 
18109aebddd1SJeff Kirsher /* set the EQ delay interval of an EQ to specified value
18119aebddd1SJeff Kirsher  * Uses async mcc
18129aebddd1SJeff Kirsher  */
1813b502ae8dSKalesh AP static int __be_cmd_modify_eqd(struct be_adapter *adapter,
1814b502ae8dSKalesh AP 			       struct be_set_eqd *set_eqd, int num)
18159aebddd1SJeff Kirsher {
18169aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
18179aebddd1SJeff Kirsher 	struct be_cmd_req_modify_eq_delay *req;
18182632bafdSSathya Perla 	int status = 0, i;
18199aebddd1SJeff Kirsher 
18209aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
18219aebddd1SJeff Kirsher 
18229aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
18239aebddd1SJeff Kirsher 	if (!wrb) {
18249aebddd1SJeff Kirsher 		status = -EBUSY;
18259aebddd1SJeff Kirsher 		goto err;
18269aebddd1SJeff Kirsher 	}
18279aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
18289aebddd1SJeff Kirsher 
1829106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1830a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb,
1831a2cc4e0bSSathya Perla 			       NULL);
18329aebddd1SJeff Kirsher 
18332632bafdSSathya Perla 	req->num_eq = cpu_to_le32(num);
18342632bafdSSathya Perla 	for (i = 0; i < num; i++) {
18352632bafdSSathya Perla 		req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
18362632bafdSSathya Perla 		req->set_eqd[i].phase = 0;
18372632bafdSSathya Perla 		req->set_eqd[i].delay_multiplier =
18382632bafdSSathya Perla 				cpu_to_le32(set_eqd[i].delay_multiplier);
18392632bafdSSathya Perla 	}
18409aebddd1SJeff Kirsher 
18419aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
18429aebddd1SJeff Kirsher err:
18439aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
18449aebddd1SJeff Kirsher 	return status;
18459aebddd1SJeff Kirsher }
18469aebddd1SJeff Kirsher 
184793676703SKalesh AP int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd,
184893676703SKalesh AP 		      int num)
184993676703SKalesh AP {
185093676703SKalesh AP 	int num_eqs, i = 0;
185193676703SKalesh AP 
185293676703SKalesh AP 	if (lancer_chip(adapter) && num > 8) {
185393676703SKalesh AP 		while (num) {
185493676703SKalesh AP 			num_eqs = min(num, 8);
185593676703SKalesh AP 			__be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs);
185693676703SKalesh AP 			i += num_eqs;
185793676703SKalesh AP 			num -= num_eqs;
185893676703SKalesh AP 		}
185993676703SKalesh AP 	} else {
186093676703SKalesh AP 		__be_cmd_modify_eqd(adapter, set_eqd, num);
186193676703SKalesh AP 	}
186293676703SKalesh AP 
186393676703SKalesh AP 	return 0;
186493676703SKalesh AP }
186593676703SKalesh AP 
18669aebddd1SJeff Kirsher /* Uses sycnhronous mcc */
18679aebddd1SJeff Kirsher int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
18684d567d97SKalesh AP 		       u32 num)
18699aebddd1SJeff Kirsher {
18709aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
18719aebddd1SJeff Kirsher 	struct be_cmd_req_vlan_config *req;
18729aebddd1SJeff Kirsher 	int status;
18739aebddd1SJeff Kirsher 
18749aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
18759aebddd1SJeff Kirsher 
18769aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
18779aebddd1SJeff Kirsher 	if (!wrb) {
18789aebddd1SJeff Kirsher 		status = -EBUSY;
18799aebddd1SJeff Kirsher 		goto err;
18809aebddd1SJeff Kirsher 	}
18819aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
18829aebddd1SJeff Kirsher 
1883106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1884a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req),
1885a2cc4e0bSSathya Perla 			       wrb, NULL);
18869aebddd1SJeff Kirsher 
18879aebddd1SJeff Kirsher 	req->interface_id = if_id;
1888012bd387SAjit Khaparde 	req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0;
18899aebddd1SJeff Kirsher 	req->num_vlan = num;
18909aebddd1SJeff Kirsher 	memcpy(req->normal_vlan, vtag_array,
18919aebddd1SJeff Kirsher 	       req->num_vlan * sizeof(vtag_array[0]));
18929aebddd1SJeff Kirsher 
18939aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
18949aebddd1SJeff Kirsher err:
18959aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
18969aebddd1SJeff Kirsher 	return status;
18979aebddd1SJeff Kirsher }
18989aebddd1SJeff Kirsher 
1899ac34b743SSathya Perla static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
19009aebddd1SJeff Kirsher {
19019aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
19029aebddd1SJeff Kirsher 	struct be_dma_mem *mem = &adapter->rx_filter;
19039aebddd1SJeff Kirsher 	struct be_cmd_req_rx_filter *req = mem->va;
19049aebddd1SJeff Kirsher 	int status;
19059aebddd1SJeff Kirsher 
19069aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
19079aebddd1SJeff Kirsher 
19089aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
19099aebddd1SJeff Kirsher 	if (!wrb) {
19109aebddd1SJeff Kirsher 		status = -EBUSY;
19119aebddd1SJeff Kirsher 		goto err;
19129aebddd1SJeff Kirsher 	}
19139aebddd1SJeff Kirsher 	memset(req, 0, sizeof(*req));
1914106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1915106df1e3SSomnath Kotur 			       OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req),
1916106df1e3SSomnath Kotur 			       wrb, mem);
19179aebddd1SJeff Kirsher 
19189aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(adapter->if_handle);
1919ac34b743SSathya Perla 	req->if_flags_mask = cpu_to_le32(flags);
1920ac34b743SSathya Perla 	req->if_flags = (value == ON) ? req->if_flags_mask : 0;
1921d9d604f8SAjit Khaparde 
1922ac34b743SSathya Perla 	if (flags & BE_IF_FLAGS_MULTICAST) {
19239aebddd1SJeff Kirsher 		struct netdev_hw_addr *ha;
19249aebddd1SJeff Kirsher 		int i = 0;
19259aebddd1SJeff Kirsher 
19261610c79fSPadmanabh Ratnakar 		/* Reset mcast promisc mode if already set by setting mask
19271610c79fSPadmanabh Ratnakar 		 * and not setting flags field
19281610c79fSPadmanabh Ratnakar 		 */
19291610c79fSPadmanabh Ratnakar 		req->if_flags_mask |=
1930abb93951SPadmanabh Ratnakar 			cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
193192bf14abSSathya Perla 				    be_if_cap_flags(adapter));
1932016f97b1SPadmanabh Ratnakar 		req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev));
19339aebddd1SJeff Kirsher 		netdev_for_each_mc_addr(ha, adapter->netdev)
19349aebddd1SJeff Kirsher 			memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN);
19359aebddd1SJeff Kirsher 	}
19369aebddd1SJeff Kirsher 
19379aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
19389aebddd1SJeff Kirsher err:
19399aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
19409aebddd1SJeff Kirsher 	return status;
19419aebddd1SJeff Kirsher }
19429aebddd1SJeff Kirsher 
1943ac34b743SSathya Perla int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
1944ac34b743SSathya Perla {
1945ac34b743SSathya Perla 	struct device *dev = &adapter->pdev->dev;
1946ac34b743SSathya Perla 
1947ac34b743SSathya Perla 	if ((flags & be_if_cap_flags(adapter)) != flags) {
1948ac34b743SSathya Perla 		dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags);
1949ac34b743SSathya Perla 		dev_warn(dev, "Interface is capable of 0x%x flags only\n",
1950ac34b743SSathya Perla 			 be_if_cap_flags(adapter));
1951ac34b743SSathya Perla 	}
1952ac34b743SSathya Perla 	flags &= be_if_cap_flags(adapter);
1953ac34b743SSathya Perla 
1954ac34b743SSathya Perla 	return __be_cmd_rx_filter(adapter, flags, value);
1955ac34b743SSathya Perla }
1956ac34b743SSathya Perla 
19579aebddd1SJeff Kirsher /* Uses synchrounous mcc */
19589aebddd1SJeff Kirsher int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
19599aebddd1SJeff Kirsher {
19609aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
19619aebddd1SJeff Kirsher 	struct be_cmd_req_set_flow_control *req;
19629aebddd1SJeff Kirsher 	int status;
19639aebddd1SJeff Kirsher 
1964f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
1965f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
1966f25b119cSPadmanabh Ratnakar 		return -EPERM;
1967f25b119cSPadmanabh Ratnakar 
19689aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
19699aebddd1SJeff Kirsher 
19709aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
19719aebddd1SJeff Kirsher 	if (!wrb) {
19729aebddd1SJeff Kirsher 		status = -EBUSY;
19739aebddd1SJeff Kirsher 		goto err;
19749aebddd1SJeff Kirsher 	}
19759aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
19769aebddd1SJeff Kirsher 
1977106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1978a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req),
1979a2cc4e0bSSathya Perla 			       wrb, NULL);
19809aebddd1SJeff Kirsher 
1981b29812c1SSuresh Reddy 	req->hdr.version = 1;
19829aebddd1SJeff Kirsher 	req->tx_flow_control = cpu_to_le16((u16)tx_fc);
19839aebddd1SJeff Kirsher 	req->rx_flow_control = cpu_to_le16((u16)rx_fc);
19849aebddd1SJeff Kirsher 
19859aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
19869aebddd1SJeff Kirsher 
19879aebddd1SJeff Kirsher err:
19889aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1989b29812c1SSuresh Reddy 
1990b29812c1SSuresh Reddy 	if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED)
1991b29812c1SSuresh Reddy 		return  -EOPNOTSUPP;
1992b29812c1SSuresh Reddy 
19939aebddd1SJeff Kirsher 	return status;
19949aebddd1SJeff Kirsher }
19959aebddd1SJeff Kirsher 
19969aebddd1SJeff Kirsher /* Uses sycn mcc */
19979aebddd1SJeff Kirsher int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
19989aebddd1SJeff Kirsher {
19999aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20009aebddd1SJeff Kirsher 	struct be_cmd_req_get_flow_control *req;
20019aebddd1SJeff Kirsher 	int status;
20029aebddd1SJeff Kirsher 
2003f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
2004f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
2005f25b119cSPadmanabh Ratnakar 		return -EPERM;
2006f25b119cSPadmanabh Ratnakar 
20079aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
20089aebddd1SJeff Kirsher 
20099aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
20109aebddd1SJeff Kirsher 	if (!wrb) {
20119aebddd1SJeff Kirsher 		status = -EBUSY;
20129aebddd1SJeff Kirsher 		goto err;
20139aebddd1SJeff Kirsher 	}
20149aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20159aebddd1SJeff Kirsher 
2016106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2017a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req),
2018a2cc4e0bSSathya Perla 			       wrb, NULL);
20199aebddd1SJeff Kirsher 
20209aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
20219aebddd1SJeff Kirsher 	if (!status) {
20229aebddd1SJeff Kirsher 		struct be_cmd_resp_get_flow_control *resp =
20239aebddd1SJeff Kirsher 						embedded_payload(wrb);
202403d28ffeSKalesh AP 
20259aebddd1SJeff Kirsher 		*tx_fc = le16_to_cpu(resp->tx_flow_control);
20269aebddd1SJeff Kirsher 		*rx_fc = le16_to_cpu(resp->rx_flow_control);
20279aebddd1SJeff Kirsher 	}
20289aebddd1SJeff Kirsher 
20299aebddd1SJeff Kirsher err:
20309aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
20319aebddd1SJeff Kirsher 	return status;
20329aebddd1SJeff Kirsher }
20339aebddd1SJeff Kirsher 
20349aebddd1SJeff Kirsher /* Uses mbox */
2035e97e3cdaSKalesh AP int be_cmd_query_fw_cfg(struct be_adapter *adapter)
20369aebddd1SJeff Kirsher {
20379aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20389aebddd1SJeff Kirsher 	struct be_cmd_req_query_fw_cfg *req;
20399aebddd1SJeff Kirsher 	int status;
20409aebddd1SJeff Kirsher 
20419aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
20429aebddd1SJeff Kirsher 		return -1;
20439aebddd1SJeff Kirsher 
20449aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
20459aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20469aebddd1SJeff Kirsher 
2047106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2048a2cc4e0bSSathya Perla 			       OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
2049a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
20509aebddd1SJeff Kirsher 
20519aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
20529aebddd1SJeff Kirsher 	if (!status) {
20539aebddd1SJeff Kirsher 		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
205403d28ffeSKalesh AP 
2055e97e3cdaSKalesh AP 		adapter->port_num = le32_to_cpu(resp->phys_port);
2056e97e3cdaSKalesh AP 		adapter->function_mode = le32_to_cpu(resp->function_mode);
2057e97e3cdaSKalesh AP 		adapter->function_caps = le32_to_cpu(resp->function_caps);
2058e97e3cdaSKalesh AP 		adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
2059acbafeb1SSathya Perla 		dev_info(&adapter->pdev->dev,
2060acbafeb1SSathya Perla 			 "FW config: function_mode=0x%x, function_caps=0x%x\n",
2061acbafeb1SSathya Perla 			 adapter->function_mode, adapter->function_caps);
20629aebddd1SJeff Kirsher 	}
20639aebddd1SJeff Kirsher 
20649aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
20659aebddd1SJeff Kirsher 	return status;
20669aebddd1SJeff Kirsher }
20679aebddd1SJeff Kirsher 
20689aebddd1SJeff Kirsher /* Uses mbox */
20699aebddd1SJeff Kirsher int be_cmd_reset_function(struct be_adapter *adapter)
20709aebddd1SJeff Kirsher {
20719aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20729aebddd1SJeff Kirsher 	struct be_cmd_req_hdr *req;
20739aebddd1SJeff Kirsher 	int status;
20749aebddd1SJeff Kirsher 
2075bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter)) {
2076bf99e50dSPadmanabh Ratnakar 		iowrite32(SLI_PORT_CONTROL_IP_MASK,
2077bf99e50dSPadmanabh Ratnakar 			  adapter->db + SLIPORT_CONTROL_OFFSET);
20789fa465c0SSathya Perla 		status = lancer_wait_ready(adapter);
20799fa465c0SSathya Perla 		if (status)
2080bf99e50dSPadmanabh Ratnakar 			dev_err(&adapter->pdev->dev,
2081bf99e50dSPadmanabh Ratnakar 				"Adapter in non recoverable error\n");
2082bf99e50dSPadmanabh Ratnakar 		return status;
2083bf99e50dSPadmanabh Ratnakar 	}
2084bf99e50dSPadmanabh Ratnakar 
20859aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
20869aebddd1SJeff Kirsher 		return -1;
20879aebddd1SJeff Kirsher 
20889aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
20899aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20909aebddd1SJeff Kirsher 
2091106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
2092a2cc4e0bSSathya Perla 			       OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb,
2093a2cc4e0bSSathya Perla 			       NULL);
20949aebddd1SJeff Kirsher 
20959aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
20969aebddd1SJeff Kirsher 
20979aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
20989aebddd1SJeff Kirsher 	return status;
20999aebddd1SJeff Kirsher }
21009aebddd1SJeff Kirsher 
2101594ad54aSSuresh Reddy int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
210233cb0fa7SBen Hutchings 		      u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey)
21039aebddd1SJeff Kirsher {
21049aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21059aebddd1SJeff Kirsher 	struct be_cmd_req_rss_config *req;
21069aebddd1SJeff Kirsher 	int status;
21079aebddd1SJeff Kirsher 
2108da1388d6SVasundhara Volam 	if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
2109da1388d6SVasundhara Volam 		return 0;
2110da1388d6SVasundhara Volam 
2111b51aa367SKalesh AP 	spin_lock_bh(&adapter->mcc_lock);
21129aebddd1SJeff Kirsher 
2113b51aa367SKalesh AP 	wrb = wrb_from_mccq(adapter);
2114b51aa367SKalesh AP 	if (!wrb) {
2115b51aa367SKalesh AP 		status = -EBUSY;
2116b51aa367SKalesh AP 		goto err;
2117b51aa367SKalesh AP 	}
21189aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21199aebddd1SJeff Kirsher 
2120106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
2121106df1e3SSomnath Kotur 			       OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
21229aebddd1SJeff Kirsher 
21239aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(adapter->if_handle);
2124594ad54aSSuresh Reddy 	req->enable_rss = cpu_to_le16(rss_hash_opts);
21259aebddd1SJeff Kirsher 	req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
2126594ad54aSSuresh Reddy 
2127b51aa367SKalesh AP 	if (!BEx_chip(adapter))
2128594ad54aSSuresh Reddy 		req->hdr.version = 1;
2129594ad54aSSuresh Reddy 
21309aebddd1SJeff Kirsher 	memcpy(req->cpu_table, rsstable, table_size);
2131e2557877SVenkata Duvvuru 	memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN);
21329aebddd1SJeff Kirsher 	be_dws_cpu_to_le(req->hash, sizeof(req->hash));
21339aebddd1SJeff Kirsher 
2134b51aa367SKalesh AP 	status = be_mcc_notify_wait(adapter);
2135b51aa367SKalesh AP err:
2136b51aa367SKalesh AP 	spin_unlock_bh(&adapter->mcc_lock);
21379aebddd1SJeff Kirsher 	return status;
21389aebddd1SJeff Kirsher }
21399aebddd1SJeff Kirsher 
21409aebddd1SJeff Kirsher /* Uses sync mcc */
21419aebddd1SJeff Kirsher int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
21429aebddd1SJeff Kirsher 			    u8 bcn, u8 sts, u8 state)
21439aebddd1SJeff Kirsher {
21449aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21459aebddd1SJeff Kirsher 	struct be_cmd_req_enable_disable_beacon *req;
21469aebddd1SJeff Kirsher 	int status;
21479aebddd1SJeff Kirsher 
21489aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
21499aebddd1SJeff Kirsher 
21509aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
21519aebddd1SJeff Kirsher 	if (!wrb) {
21529aebddd1SJeff Kirsher 		status = -EBUSY;
21539aebddd1SJeff Kirsher 		goto err;
21549aebddd1SJeff Kirsher 	}
21559aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21569aebddd1SJeff Kirsher 
2157106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2158a2cc4e0bSSathya Perla 			       OPCODE_COMMON_ENABLE_DISABLE_BEACON,
2159a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
21609aebddd1SJeff Kirsher 
21619aebddd1SJeff Kirsher 	req->port_num = port_num;
21629aebddd1SJeff Kirsher 	req->beacon_state = state;
21639aebddd1SJeff Kirsher 	req->beacon_duration = bcn;
21649aebddd1SJeff Kirsher 	req->status_duration = sts;
21659aebddd1SJeff Kirsher 
21669aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
21679aebddd1SJeff Kirsher 
21689aebddd1SJeff Kirsher err:
21699aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
21709aebddd1SJeff Kirsher 	return status;
21719aebddd1SJeff Kirsher }
21729aebddd1SJeff Kirsher 
21739aebddd1SJeff Kirsher /* Uses sync mcc */
21749aebddd1SJeff Kirsher int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
21759aebddd1SJeff Kirsher {
21769aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21779aebddd1SJeff Kirsher 	struct be_cmd_req_get_beacon_state *req;
21789aebddd1SJeff Kirsher 	int status;
21799aebddd1SJeff Kirsher 
21809aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
21819aebddd1SJeff Kirsher 
21829aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
21839aebddd1SJeff Kirsher 	if (!wrb) {
21849aebddd1SJeff Kirsher 		status = -EBUSY;
21859aebddd1SJeff Kirsher 		goto err;
21869aebddd1SJeff Kirsher 	}
21879aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21889aebddd1SJeff Kirsher 
2189106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2190a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req),
2191a2cc4e0bSSathya Perla 			       wrb, NULL);
21929aebddd1SJeff Kirsher 
21939aebddd1SJeff Kirsher 	req->port_num = port_num;
21949aebddd1SJeff Kirsher 
21959aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
21969aebddd1SJeff Kirsher 	if (!status) {
21979aebddd1SJeff Kirsher 		struct be_cmd_resp_get_beacon_state *resp =
21989aebddd1SJeff Kirsher 						embedded_payload(wrb);
219903d28ffeSKalesh AP 
22009aebddd1SJeff Kirsher 		*state = resp->beacon_state;
22019aebddd1SJeff Kirsher 	}
22029aebddd1SJeff Kirsher 
22039aebddd1SJeff Kirsher err:
22049aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
22059aebddd1SJeff Kirsher 	return status;
22069aebddd1SJeff Kirsher }
22079aebddd1SJeff Kirsher 
2208e36edd9dSMark Leonard /* Uses sync mcc */
2209e36edd9dSMark Leonard int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
2210e36edd9dSMark Leonard 				      u8 page_num, u8 *data)
2211e36edd9dSMark Leonard {
2212e36edd9dSMark Leonard 	struct be_dma_mem cmd;
2213e36edd9dSMark Leonard 	struct be_mcc_wrb *wrb;
2214e36edd9dSMark Leonard 	struct be_cmd_req_port_type *req;
2215e36edd9dSMark Leonard 	int status;
2216e36edd9dSMark Leonard 
2217e36edd9dSMark Leonard 	if (page_num > TR_PAGE_A2)
2218e36edd9dSMark Leonard 		return -EINVAL;
2219e36edd9dSMark Leonard 
2220e36edd9dSMark Leonard 	cmd.size = sizeof(struct be_cmd_resp_port_type);
2221e36edd9dSMark Leonard 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
2222e36edd9dSMark Leonard 	if (!cmd.va) {
2223e36edd9dSMark Leonard 		dev_err(&adapter->pdev->dev, "Memory allocation failed\n");
2224e36edd9dSMark Leonard 		return -ENOMEM;
2225e36edd9dSMark Leonard 	}
2226e36edd9dSMark Leonard 	memset(cmd.va, 0, cmd.size);
2227e36edd9dSMark Leonard 
2228e36edd9dSMark Leonard 	spin_lock_bh(&adapter->mcc_lock);
2229e36edd9dSMark Leonard 
2230e36edd9dSMark Leonard 	wrb = wrb_from_mccq(adapter);
2231e36edd9dSMark Leonard 	if (!wrb) {
2232e36edd9dSMark Leonard 		status = -EBUSY;
2233e36edd9dSMark Leonard 		goto err;
2234e36edd9dSMark Leonard 	}
2235e36edd9dSMark Leonard 	req = cmd.va;
2236e36edd9dSMark Leonard 
2237e36edd9dSMark Leonard 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2238e36edd9dSMark Leonard 			       OPCODE_COMMON_READ_TRANSRECV_DATA,
2239e36edd9dSMark Leonard 			       cmd.size, wrb, &cmd);
2240e36edd9dSMark Leonard 
2241e36edd9dSMark Leonard 	req->port = cpu_to_le32(adapter->hba_port_num);
2242e36edd9dSMark Leonard 	req->page_num = cpu_to_le32(page_num);
2243e36edd9dSMark Leonard 	status = be_mcc_notify_wait(adapter);
2244e36edd9dSMark Leonard 	if (!status) {
2245e36edd9dSMark Leonard 		struct be_cmd_resp_port_type *resp = cmd.va;
2246e36edd9dSMark Leonard 
2247e36edd9dSMark Leonard 		memcpy(data, resp->page_data, PAGE_DATA_LEN);
2248e36edd9dSMark Leonard 	}
2249e36edd9dSMark Leonard err:
2250e36edd9dSMark Leonard 	spin_unlock_bh(&adapter->mcc_lock);
2251e36edd9dSMark Leonard 	pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
2252e36edd9dSMark Leonard 	return status;
2253e36edd9dSMark Leonard }
2254e36edd9dSMark Leonard 
22559aebddd1SJeff Kirsher int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
2256f67ef7baSPadmanabh Ratnakar 			    u32 data_size, u32 data_offset,
2257f67ef7baSPadmanabh Ratnakar 			    const char *obj_name, u32 *data_written,
2258f67ef7baSPadmanabh Ratnakar 			    u8 *change_status, u8 *addn_status)
22599aebddd1SJeff Kirsher {
22609aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
22619aebddd1SJeff Kirsher 	struct lancer_cmd_req_write_object *req;
22629aebddd1SJeff Kirsher 	struct lancer_cmd_resp_write_object *resp;
22639aebddd1SJeff Kirsher 	void *ctxt = NULL;
22649aebddd1SJeff Kirsher 	int status;
22659aebddd1SJeff Kirsher 
22669aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
22679aebddd1SJeff Kirsher 	adapter->flash_status = 0;
22689aebddd1SJeff Kirsher 
22699aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
22709aebddd1SJeff Kirsher 	if (!wrb) {
22719aebddd1SJeff Kirsher 		status = -EBUSY;
22729aebddd1SJeff Kirsher 		goto err_unlock;
22739aebddd1SJeff Kirsher 	}
22749aebddd1SJeff Kirsher 
22759aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
22769aebddd1SJeff Kirsher 
2277106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
22789aebddd1SJeff Kirsher 			       OPCODE_COMMON_WRITE_OBJECT,
2279106df1e3SSomnath Kotur 			       sizeof(struct lancer_cmd_req_write_object), wrb,
2280106df1e3SSomnath Kotur 			       NULL);
22819aebddd1SJeff Kirsher 
22829aebddd1SJeff Kirsher 	ctxt = &req->context;
22839aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_lancer_write_obj_context,
22849aebddd1SJeff Kirsher 		      write_length, ctxt, data_size);
22859aebddd1SJeff Kirsher 
22869aebddd1SJeff Kirsher 	if (data_size == 0)
22879aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
22889aebddd1SJeff Kirsher 			      eof, ctxt, 1);
22899aebddd1SJeff Kirsher 	else
22909aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
22919aebddd1SJeff Kirsher 			      eof, ctxt, 0);
22929aebddd1SJeff Kirsher 
22939aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
22949aebddd1SJeff Kirsher 	req->write_offset = cpu_to_le32(data_offset);
2295242eb470SVasundhara Volam 	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
22969aebddd1SJeff Kirsher 	req->descriptor_count = cpu_to_le32(1);
22979aebddd1SJeff Kirsher 	req->buf_len = cpu_to_le32(data_size);
22989aebddd1SJeff Kirsher 	req->addr_low = cpu_to_le32((cmd->dma +
22999aebddd1SJeff Kirsher 				     sizeof(struct lancer_cmd_req_write_object))
23009aebddd1SJeff Kirsher 				    & 0xFFFFFFFF);
23019aebddd1SJeff Kirsher 	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma +
23029aebddd1SJeff Kirsher 				sizeof(struct lancer_cmd_req_write_object)));
23039aebddd1SJeff Kirsher 
23049aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
23059aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
23069aebddd1SJeff Kirsher 
23075eeff635SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
2308701962d0SSomnath Kotur 					 msecs_to_jiffies(60000)))
2309fd45160cSKalesh AP 		status = -ETIMEDOUT;
23109aebddd1SJeff Kirsher 	else
23119aebddd1SJeff Kirsher 		status = adapter->flash_status;
23129aebddd1SJeff Kirsher 
23139aebddd1SJeff Kirsher 	resp = embedded_payload(wrb);
2314f67ef7baSPadmanabh Ratnakar 	if (!status) {
23159aebddd1SJeff Kirsher 		*data_written = le32_to_cpu(resp->actual_write_len);
2316f67ef7baSPadmanabh Ratnakar 		*change_status = resp->change_status;
2317f67ef7baSPadmanabh Ratnakar 	} else {
23189aebddd1SJeff Kirsher 		*addn_status = resp->additional_status;
2319f67ef7baSPadmanabh Ratnakar 	}
23209aebddd1SJeff Kirsher 
23219aebddd1SJeff Kirsher 	return status;
23229aebddd1SJeff Kirsher 
23239aebddd1SJeff Kirsher err_unlock:
23249aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
23259aebddd1SJeff Kirsher 	return status;
23269aebddd1SJeff Kirsher }
23279aebddd1SJeff Kirsher 
23286809cee0SRavikumar Nelavelli int be_cmd_query_cable_type(struct be_adapter *adapter)
23296809cee0SRavikumar Nelavelli {
23306809cee0SRavikumar Nelavelli 	u8 page_data[PAGE_DATA_LEN];
23316809cee0SRavikumar Nelavelli 	int status;
23326809cee0SRavikumar Nelavelli 
23336809cee0SRavikumar Nelavelli 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
23346809cee0SRavikumar Nelavelli 						   page_data);
23356809cee0SRavikumar Nelavelli 	if (!status) {
23366809cee0SRavikumar Nelavelli 		switch (adapter->phy.interface_type) {
23376809cee0SRavikumar Nelavelli 		case PHY_TYPE_QSFP:
23386809cee0SRavikumar Nelavelli 			adapter->phy.cable_type =
23396809cee0SRavikumar Nelavelli 				page_data[QSFP_PLUS_CABLE_TYPE_OFFSET];
23406809cee0SRavikumar Nelavelli 			break;
23416809cee0SRavikumar Nelavelli 		case PHY_TYPE_SFP_PLUS_10GB:
23426809cee0SRavikumar Nelavelli 			adapter->phy.cable_type =
23436809cee0SRavikumar Nelavelli 				page_data[SFP_PLUS_CABLE_TYPE_OFFSET];
23446809cee0SRavikumar Nelavelli 			break;
23456809cee0SRavikumar Nelavelli 		default:
23466809cee0SRavikumar Nelavelli 			adapter->phy.cable_type = 0;
23476809cee0SRavikumar Nelavelli 			break;
23486809cee0SRavikumar Nelavelli 		}
23496809cee0SRavikumar Nelavelli 	}
23506809cee0SRavikumar Nelavelli 	return status;
23516809cee0SRavikumar Nelavelli }
23526809cee0SRavikumar Nelavelli 
235321252377SVasundhara Volam int be_cmd_query_sfp_info(struct be_adapter *adapter)
235421252377SVasundhara Volam {
235521252377SVasundhara Volam 	u8 page_data[PAGE_DATA_LEN];
235621252377SVasundhara Volam 	int status;
235721252377SVasundhara Volam 
235821252377SVasundhara Volam 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
235921252377SVasundhara Volam 						   page_data);
236021252377SVasundhara Volam 	if (!status) {
236121252377SVasundhara Volam 		strlcpy(adapter->phy.vendor_name, page_data +
236221252377SVasundhara Volam 			SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
236321252377SVasundhara Volam 		strlcpy(adapter->phy.vendor_pn,
236421252377SVasundhara Volam 			page_data + SFP_VENDOR_PN_OFFSET,
236521252377SVasundhara Volam 			SFP_VENDOR_NAME_LEN - 1);
236621252377SVasundhara Volam 	}
236721252377SVasundhara Volam 
236821252377SVasundhara Volam 	return status;
236921252377SVasundhara Volam }
237021252377SVasundhara Volam 
2371f0613380SKalesh AP int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name)
2372f0613380SKalesh AP {
2373f0613380SKalesh AP 	struct lancer_cmd_req_delete_object *req;
2374f0613380SKalesh AP 	struct be_mcc_wrb *wrb;
2375f0613380SKalesh AP 	int status;
2376f0613380SKalesh AP 
2377f0613380SKalesh AP 	spin_lock_bh(&adapter->mcc_lock);
2378f0613380SKalesh AP 
2379f0613380SKalesh AP 	wrb = wrb_from_mccq(adapter);
2380f0613380SKalesh AP 	if (!wrb) {
2381f0613380SKalesh AP 		status = -EBUSY;
2382f0613380SKalesh AP 		goto err;
2383f0613380SKalesh AP 	}
2384f0613380SKalesh AP 
2385f0613380SKalesh AP 	req = embedded_payload(wrb);
2386f0613380SKalesh AP 
2387f0613380SKalesh AP 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2388f0613380SKalesh AP 			       OPCODE_COMMON_DELETE_OBJECT,
2389f0613380SKalesh AP 			       sizeof(*req), wrb, NULL);
2390f0613380SKalesh AP 
2391242eb470SVasundhara Volam 	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
2392f0613380SKalesh AP 
2393f0613380SKalesh AP 	status = be_mcc_notify_wait(adapter);
2394f0613380SKalesh AP err:
2395f0613380SKalesh AP 	spin_unlock_bh(&adapter->mcc_lock);
2396f0613380SKalesh AP 	return status;
2397f0613380SKalesh AP }
2398f0613380SKalesh AP 
2399de49bd5aSPadmanabh Ratnakar int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
2400de49bd5aSPadmanabh Ratnakar 			   u32 data_size, u32 data_offset, const char *obj_name,
2401de49bd5aSPadmanabh Ratnakar 			   u32 *data_read, u32 *eof, u8 *addn_status)
2402de49bd5aSPadmanabh Ratnakar {
2403de49bd5aSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
2404de49bd5aSPadmanabh Ratnakar 	struct lancer_cmd_req_read_object *req;
2405de49bd5aSPadmanabh Ratnakar 	struct lancer_cmd_resp_read_object *resp;
2406de49bd5aSPadmanabh Ratnakar 	int status;
2407de49bd5aSPadmanabh Ratnakar 
2408de49bd5aSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
2409de49bd5aSPadmanabh Ratnakar 
2410de49bd5aSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
2411de49bd5aSPadmanabh Ratnakar 	if (!wrb) {
2412de49bd5aSPadmanabh Ratnakar 		status = -EBUSY;
2413de49bd5aSPadmanabh Ratnakar 		goto err_unlock;
2414de49bd5aSPadmanabh Ratnakar 	}
2415de49bd5aSPadmanabh Ratnakar 
2416de49bd5aSPadmanabh Ratnakar 	req = embedded_payload(wrb);
2417de49bd5aSPadmanabh Ratnakar 
2418de49bd5aSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2419de49bd5aSPadmanabh Ratnakar 			       OPCODE_COMMON_READ_OBJECT,
2420de49bd5aSPadmanabh Ratnakar 			       sizeof(struct lancer_cmd_req_read_object), wrb,
2421de49bd5aSPadmanabh Ratnakar 			       NULL);
2422de49bd5aSPadmanabh Ratnakar 
2423de49bd5aSPadmanabh Ratnakar 	req->desired_read_len = cpu_to_le32(data_size);
2424de49bd5aSPadmanabh Ratnakar 	req->read_offset = cpu_to_le32(data_offset);
2425de49bd5aSPadmanabh Ratnakar 	strcpy(req->object_name, obj_name);
2426de49bd5aSPadmanabh Ratnakar 	req->descriptor_count = cpu_to_le32(1);
2427de49bd5aSPadmanabh Ratnakar 	req->buf_len = cpu_to_le32(data_size);
2428de49bd5aSPadmanabh Ratnakar 	req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF));
2429de49bd5aSPadmanabh Ratnakar 	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma));
2430de49bd5aSPadmanabh Ratnakar 
2431de49bd5aSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
2432de49bd5aSPadmanabh Ratnakar 
2433de49bd5aSPadmanabh Ratnakar 	resp = embedded_payload(wrb);
2434de49bd5aSPadmanabh Ratnakar 	if (!status) {
2435de49bd5aSPadmanabh Ratnakar 		*data_read = le32_to_cpu(resp->actual_read_len);
2436de49bd5aSPadmanabh Ratnakar 		*eof = le32_to_cpu(resp->eof);
2437de49bd5aSPadmanabh Ratnakar 	} else {
2438de49bd5aSPadmanabh Ratnakar 		*addn_status = resp->additional_status;
2439de49bd5aSPadmanabh Ratnakar 	}
2440de49bd5aSPadmanabh Ratnakar 
2441de49bd5aSPadmanabh Ratnakar err_unlock:
2442de49bd5aSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
2443de49bd5aSPadmanabh Ratnakar 	return status;
2444de49bd5aSPadmanabh Ratnakar }
2445de49bd5aSPadmanabh Ratnakar 
24469aebddd1SJeff Kirsher int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
244770a7b525SVasundhara Volam 			  u32 flash_type, u32 flash_opcode, u32 img_offset,
244870a7b525SVasundhara Volam 			  u32 buf_size)
24499aebddd1SJeff Kirsher {
24509aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
24519aebddd1SJeff Kirsher 	struct be_cmd_write_flashrom *req;
24529aebddd1SJeff Kirsher 	int status;
24539aebddd1SJeff Kirsher 
24549aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
24559aebddd1SJeff Kirsher 	adapter->flash_status = 0;
24569aebddd1SJeff Kirsher 
24579aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
24589aebddd1SJeff Kirsher 	if (!wrb) {
24599aebddd1SJeff Kirsher 		status = -EBUSY;
24609aebddd1SJeff Kirsher 		goto err_unlock;
24619aebddd1SJeff Kirsher 	}
24629aebddd1SJeff Kirsher 	req = cmd->va;
24639aebddd1SJeff Kirsher 
2464106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2465a2cc4e0bSSathya Perla 			       OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb,
2466a2cc4e0bSSathya Perla 			       cmd);
24679aebddd1SJeff Kirsher 
24689aebddd1SJeff Kirsher 	req->params.op_type = cpu_to_le32(flash_type);
246970a7b525SVasundhara Volam 	if (flash_type == OPTYPE_OFFSET_SPECIFIED)
247070a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(img_offset);
247170a7b525SVasundhara Volam 
24729aebddd1SJeff Kirsher 	req->params.op_code = cpu_to_le32(flash_opcode);
24739aebddd1SJeff Kirsher 	req->params.data_buf_size = cpu_to_le32(buf_size);
24749aebddd1SJeff Kirsher 
24759aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
24769aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
24779aebddd1SJeff Kirsher 
24785eeff635SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
2479e2edb7d5SSathya Perla 					 msecs_to_jiffies(40000)))
2480fd45160cSKalesh AP 		status = -ETIMEDOUT;
24819aebddd1SJeff Kirsher 	else
24829aebddd1SJeff Kirsher 		status = adapter->flash_status;
24839aebddd1SJeff Kirsher 
24849aebddd1SJeff Kirsher 	return status;
24859aebddd1SJeff Kirsher 
24869aebddd1SJeff Kirsher err_unlock:
24879aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
24889aebddd1SJeff Kirsher 	return status;
24899aebddd1SJeff Kirsher }
24909aebddd1SJeff Kirsher 
24919aebddd1SJeff Kirsher int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
249270a7b525SVasundhara Volam 			 u16 img_optype, u32 img_offset, u32 crc_offset)
24939aebddd1SJeff Kirsher {
2494be716446SPadmanabh Ratnakar 	struct be_cmd_read_flash_crc *req;
249570a7b525SVasundhara Volam 	struct be_mcc_wrb *wrb;
24969aebddd1SJeff Kirsher 	int status;
24979aebddd1SJeff Kirsher 
24989aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
24999aebddd1SJeff Kirsher 
25009aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
25019aebddd1SJeff Kirsher 	if (!wrb) {
25029aebddd1SJeff Kirsher 		status = -EBUSY;
25039aebddd1SJeff Kirsher 		goto err;
25049aebddd1SJeff Kirsher 	}
25059aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
25069aebddd1SJeff Kirsher 
2507106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2508be716446SPadmanabh Ratnakar 			       OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
2509be716446SPadmanabh Ratnakar 			       wrb, NULL);
25109aebddd1SJeff Kirsher 
251170a7b525SVasundhara Volam 	req->params.op_type = cpu_to_le32(img_optype);
251270a7b525SVasundhara Volam 	if (img_optype == OPTYPE_OFFSET_SPECIFIED)
251370a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(img_offset + crc_offset);
251470a7b525SVasundhara Volam 	else
251570a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(crc_offset);
251670a7b525SVasundhara Volam 
25179aebddd1SJeff Kirsher 	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
25189aebddd1SJeff Kirsher 	req->params.data_buf_size = cpu_to_le32(0x4);
25199aebddd1SJeff Kirsher 
25209aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
25219aebddd1SJeff Kirsher 	if (!status)
2522be716446SPadmanabh Ratnakar 		memcpy(flashed_crc, req->crc, 4);
25239aebddd1SJeff Kirsher 
25249aebddd1SJeff Kirsher err:
25259aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25269aebddd1SJeff Kirsher 	return status;
25279aebddd1SJeff Kirsher }
25289aebddd1SJeff Kirsher 
25299aebddd1SJeff Kirsher int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
25309aebddd1SJeff Kirsher 			    struct be_dma_mem *nonemb_cmd)
25319aebddd1SJeff Kirsher {
25329aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
25339aebddd1SJeff Kirsher 	struct be_cmd_req_acpi_wol_magic_config *req;
25349aebddd1SJeff Kirsher 	int status;
25359aebddd1SJeff Kirsher 
25369aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
25379aebddd1SJeff Kirsher 
25389aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
25399aebddd1SJeff Kirsher 	if (!wrb) {
25409aebddd1SJeff Kirsher 		status = -EBUSY;
25419aebddd1SJeff Kirsher 		goto err;
25429aebddd1SJeff Kirsher 	}
25439aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
25449aebddd1SJeff Kirsher 
2545106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
2546a2cc4e0bSSathya Perla 			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req),
2547a2cc4e0bSSathya Perla 			       wrb, nonemb_cmd);
25489aebddd1SJeff Kirsher 	memcpy(req->magic_mac, mac, ETH_ALEN);
25499aebddd1SJeff Kirsher 
25509aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
25519aebddd1SJeff Kirsher 
25529aebddd1SJeff Kirsher err:
25539aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25549aebddd1SJeff Kirsher 	return status;
25559aebddd1SJeff Kirsher }
25569aebddd1SJeff Kirsher 
25579aebddd1SJeff Kirsher int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
25589aebddd1SJeff Kirsher 			u8 loopback_type, u8 enable)
25599aebddd1SJeff Kirsher {
25609aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
25619aebddd1SJeff Kirsher 	struct be_cmd_req_set_lmode *req;
25629aebddd1SJeff Kirsher 	int status;
25639aebddd1SJeff Kirsher 
25649aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
25659aebddd1SJeff Kirsher 
25669aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
25679aebddd1SJeff Kirsher 	if (!wrb) {
25689aebddd1SJeff Kirsher 		status = -EBUSY;
25699aebddd1SJeff Kirsher 		goto err;
25709aebddd1SJeff Kirsher 	}
25719aebddd1SJeff Kirsher 
25729aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
25739aebddd1SJeff Kirsher 
2574106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
2575a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req),
2576a2cc4e0bSSathya Perla 			       wrb, NULL);
25779aebddd1SJeff Kirsher 
25789aebddd1SJeff Kirsher 	req->src_port = port_num;
25799aebddd1SJeff Kirsher 	req->dest_port = port_num;
25809aebddd1SJeff Kirsher 	req->loopback_type = loopback_type;
25819aebddd1SJeff Kirsher 	req->loopback_state = enable;
25829aebddd1SJeff Kirsher 
25839aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
25849aebddd1SJeff Kirsher err:
25859aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25869aebddd1SJeff Kirsher 	return status;
25879aebddd1SJeff Kirsher }
25889aebddd1SJeff Kirsher 
25899aebddd1SJeff Kirsher int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
2590a2cc4e0bSSathya Perla 			 u32 loopback_type, u32 pkt_size, u32 num_pkts,
2591a2cc4e0bSSathya Perla 			 u64 pattern)
25929aebddd1SJeff Kirsher {
25939aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
25949aebddd1SJeff Kirsher 	struct be_cmd_req_loopback_test *req;
25955eeff635SSuresh Reddy 	struct be_cmd_resp_loopback_test *resp;
25969aebddd1SJeff Kirsher 	int status;
25979aebddd1SJeff Kirsher 
25989aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
25999aebddd1SJeff Kirsher 
26009aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
26019aebddd1SJeff Kirsher 	if (!wrb) {
26029aebddd1SJeff Kirsher 		status = -EBUSY;
26039aebddd1SJeff Kirsher 		goto err;
26049aebddd1SJeff Kirsher 	}
26059aebddd1SJeff Kirsher 
26069aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
26079aebddd1SJeff Kirsher 
2608106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
2609a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb,
2610a2cc4e0bSSathya Perla 			       NULL);
26119aebddd1SJeff Kirsher 
26125eeff635SSuresh Reddy 	req->hdr.timeout = cpu_to_le32(15);
26139aebddd1SJeff Kirsher 	req->pattern = cpu_to_le64(pattern);
26149aebddd1SJeff Kirsher 	req->src_port = cpu_to_le32(port_num);
26159aebddd1SJeff Kirsher 	req->dest_port = cpu_to_le32(port_num);
26169aebddd1SJeff Kirsher 	req->pkt_size = cpu_to_le32(pkt_size);
26179aebddd1SJeff Kirsher 	req->num_pkts = cpu_to_le32(num_pkts);
26189aebddd1SJeff Kirsher 	req->loopback_type = cpu_to_le32(loopback_type);
26199aebddd1SJeff Kirsher 
26205eeff635SSuresh Reddy 	be_mcc_notify(adapter);
26219aebddd1SJeff Kirsher 
26225eeff635SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
26235eeff635SSuresh Reddy 
26245eeff635SSuresh Reddy 	wait_for_completion(&adapter->et_cmd_compl);
26255eeff635SSuresh Reddy 	resp = embedded_payload(wrb);
26265eeff635SSuresh Reddy 	status = le32_to_cpu(resp->status);
26275eeff635SSuresh Reddy 
26285eeff635SSuresh Reddy 	return status;
26299aebddd1SJeff Kirsher err:
26309aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
26319aebddd1SJeff Kirsher 	return status;
26329aebddd1SJeff Kirsher }
26339aebddd1SJeff Kirsher 
26349aebddd1SJeff Kirsher int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
26359aebddd1SJeff Kirsher 			u32 byte_cnt, struct be_dma_mem *cmd)
26369aebddd1SJeff Kirsher {
26379aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
26389aebddd1SJeff Kirsher 	struct be_cmd_req_ddrdma_test *req;
26399aebddd1SJeff Kirsher 	int status;
26409aebddd1SJeff Kirsher 	int i, j = 0;
26419aebddd1SJeff Kirsher 
26429aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
26439aebddd1SJeff Kirsher 
26449aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
26459aebddd1SJeff Kirsher 	if (!wrb) {
26469aebddd1SJeff Kirsher 		status = -EBUSY;
26479aebddd1SJeff Kirsher 		goto err;
26489aebddd1SJeff Kirsher 	}
26499aebddd1SJeff Kirsher 	req = cmd->va;
2650106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
2651a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb,
2652a2cc4e0bSSathya Perla 			       cmd);
26539aebddd1SJeff Kirsher 
26549aebddd1SJeff Kirsher 	req->pattern = cpu_to_le64(pattern);
26559aebddd1SJeff Kirsher 	req->byte_count = cpu_to_le32(byte_cnt);
26569aebddd1SJeff Kirsher 	for (i = 0; i < byte_cnt; i++) {
26579aebddd1SJeff Kirsher 		req->snd_buff[i] = (u8)(pattern >> (j*8));
26589aebddd1SJeff Kirsher 		j++;
26599aebddd1SJeff Kirsher 		if (j > 7)
26609aebddd1SJeff Kirsher 			j = 0;
26619aebddd1SJeff Kirsher 	}
26629aebddd1SJeff Kirsher 
26639aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
26649aebddd1SJeff Kirsher 
26659aebddd1SJeff Kirsher 	if (!status) {
26669aebddd1SJeff Kirsher 		struct be_cmd_resp_ddrdma_test *resp;
266703d28ffeSKalesh AP 
26689aebddd1SJeff Kirsher 		resp = cmd->va;
26699aebddd1SJeff Kirsher 		if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) ||
26709aebddd1SJeff Kirsher 		    resp->snd_err) {
26719aebddd1SJeff Kirsher 			status = -1;
26729aebddd1SJeff Kirsher 		}
26739aebddd1SJeff Kirsher 	}
26749aebddd1SJeff Kirsher 
26759aebddd1SJeff Kirsher err:
26769aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
26779aebddd1SJeff Kirsher 	return status;
26789aebddd1SJeff Kirsher }
26799aebddd1SJeff Kirsher 
26809aebddd1SJeff Kirsher int be_cmd_get_seeprom_data(struct be_adapter *adapter,
26819aebddd1SJeff Kirsher 			    struct be_dma_mem *nonemb_cmd)
26829aebddd1SJeff Kirsher {
26839aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
26849aebddd1SJeff Kirsher 	struct be_cmd_req_seeprom_read *req;
26859aebddd1SJeff Kirsher 	int status;
26869aebddd1SJeff Kirsher 
26879aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
26889aebddd1SJeff Kirsher 
26899aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
26909aebddd1SJeff Kirsher 	if (!wrb) {
26919aebddd1SJeff Kirsher 		status = -EBUSY;
26929aebddd1SJeff Kirsher 		goto err;
26939aebddd1SJeff Kirsher 	}
26949aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
26959aebddd1SJeff Kirsher 
2696106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2697106df1e3SSomnath Kotur 			       OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb,
2698106df1e3SSomnath Kotur 			       nonemb_cmd);
26999aebddd1SJeff Kirsher 
27009aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
27019aebddd1SJeff Kirsher 
27029aebddd1SJeff Kirsher err:
27039aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
27049aebddd1SJeff Kirsher 	return status;
27059aebddd1SJeff Kirsher }
27069aebddd1SJeff Kirsher 
270742f11cf2SAjit Khaparde int be_cmd_get_phy_info(struct be_adapter *adapter)
27089aebddd1SJeff Kirsher {
27099aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
27109aebddd1SJeff Kirsher 	struct be_cmd_req_get_phy_info *req;
27119aebddd1SJeff Kirsher 	struct be_dma_mem cmd;
27129aebddd1SJeff Kirsher 	int status;
27139aebddd1SJeff Kirsher 
2714f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
2715f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
2716f25b119cSPadmanabh Ratnakar 		return -EPERM;
2717f25b119cSPadmanabh Ratnakar 
27189aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
27199aebddd1SJeff Kirsher 
27209aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
27219aebddd1SJeff Kirsher 	if (!wrb) {
27229aebddd1SJeff Kirsher 		status = -EBUSY;
27239aebddd1SJeff Kirsher 		goto err;
27249aebddd1SJeff Kirsher 	}
27259aebddd1SJeff Kirsher 	cmd.size = sizeof(struct be_cmd_req_get_phy_info);
2726a2cc4e0bSSathya Perla 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
27279aebddd1SJeff Kirsher 	if (!cmd.va) {
27289aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
27299aebddd1SJeff Kirsher 		status = -ENOMEM;
27309aebddd1SJeff Kirsher 		goto err;
27319aebddd1SJeff Kirsher 	}
27329aebddd1SJeff Kirsher 
27339aebddd1SJeff Kirsher 	req = cmd.va;
27349aebddd1SJeff Kirsher 
2735106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2736106df1e3SSomnath Kotur 			       OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req),
2737106df1e3SSomnath Kotur 			       wrb, &cmd);
27389aebddd1SJeff Kirsher 
27399aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
27409aebddd1SJeff Kirsher 	if (!status) {
27419aebddd1SJeff Kirsher 		struct be_phy_info *resp_phy_info =
27429aebddd1SJeff Kirsher 				cmd.va + sizeof(struct be_cmd_req_hdr);
274303d28ffeSKalesh AP 
274442f11cf2SAjit Khaparde 		adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type);
274542f11cf2SAjit Khaparde 		adapter->phy.interface_type =
27469aebddd1SJeff Kirsher 			le16_to_cpu(resp_phy_info->interface_type);
274742f11cf2SAjit Khaparde 		adapter->phy.auto_speeds_supported =
274842f11cf2SAjit Khaparde 			le16_to_cpu(resp_phy_info->auto_speeds_supported);
274942f11cf2SAjit Khaparde 		adapter->phy.fixed_speeds_supported =
275042f11cf2SAjit Khaparde 			le16_to_cpu(resp_phy_info->fixed_speeds_supported);
275142f11cf2SAjit Khaparde 		adapter->phy.misc_params =
275242f11cf2SAjit Khaparde 			le32_to_cpu(resp_phy_info->misc_params);
275368cb7e47SVasundhara Volam 
275468cb7e47SVasundhara Volam 		if (BE2_chip(adapter)) {
275568cb7e47SVasundhara Volam 			adapter->phy.fixed_speeds_supported =
275668cb7e47SVasundhara Volam 				BE_SUPPORTED_SPEED_10GBPS |
275768cb7e47SVasundhara Volam 				BE_SUPPORTED_SPEED_1GBPS;
275868cb7e47SVasundhara Volam 		}
27599aebddd1SJeff Kirsher 	}
2760a2cc4e0bSSathya Perla 	pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
27619aebddd1SJeff Kirsher err:
27629aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
27639aebddd1SJeff Kirsher 	return status;
27649aebddd1SJeff Kirsher }
27659aebddd1SJeff Kirsher 
2766bc0ee163SLad, Prabhakar static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain)
27679aebddd1SJeff Kirsher {
27689aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
27699aebddd1SJeff Kirsher 	struct be_cmd_req_set_qos *req;
27709aebddd1SJeff Kirsher 	int status;
27719aebddd1SJeff Kirsher 
27729aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
27739aebddd1SJeff Kirsher 
27749aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
27759aebddd1SJeff Kirsher 	if (!wrb) {
27769aebddd1SJeff Kirsher 		status = -EBUSY;
27779aebddd1SJeff Kirsher 		goto err;
27789aebddd1SJeff Kirsher 	}
27799aebddd1SJeff Kirsher 
27809aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
27819aebddd1SJeff Kirsher 
2782106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2783106df1e3SSomnath Kotur 			       OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL);
27849aebddd1SJeff Kirsher 
27859aebddd1SJeff Kirsher 	req->hdr.domain = domain;
27869aebddd1SJeff Kirsher 	req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
27879aebddd1SJeff Kirsher 	req->max_bps_nic = cpu_to_le32(bps);
27889aebddd1SJeff Kirsher 
27899aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
27909aebddd1SJeff Kirsher 
27919aebddd1SJeff Kirsher err:
27929aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
27939aebddd1SJeff Kirsher 	return status;
27949aebddd1SJeff Kirsher }
27959aebddd1SJeff Kirsher 
27969aebddd1SJeff Kirsher int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
27979aebddd1SJeff Kirsher {
27989aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
27999aebddd1SJeff Kirsher 	struct be_cmd_req_cntl_attribs *req;
28009aebddd1SJeff Kirsher 	struct be_cmd_resp_cntl_attribs *resp;
28019aebddd1SJeff Kirsher 	int status;
28029aebddd1SJeff Kirsher 	int payload_len = max(sizeof(*req), sizeof(*resp));
28039aebddd1SJeff Kirsher 	struct mgmt_controller_attrib *attribs;
28049aebddd1SJeff Kirsher 	struct be_dma_mem attribs_cmd;
28059aebddd1SJeff Kirsher 
2806d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
2807d98ef50fSSuresh Reddy 		return -1;
2808d98ef50fSSuresh Reddy 
28099aebddd1SJeff Kirsher 	memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
28109aebddd1SJeff Kirsher 	attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
28119aebddd1SJeff Kirsher 	attribs_cmd.va = pci_alloc_consistent(adapter->pdev, attribs_cmd.size,
28129aebddd1SJeff Kirsher 					      &attribs_cmd.dma);
28139aebddd1SJeff Kirsher 	if (!attribs_cmd.va) {
2814a2cc4e0bSSathya Perla 		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
2815d98ef50fSSuresh Reddy 		status = -ENOMEM;
2816d98ef50fSSuresh Reddy 		goto err;
28179aebddd1SJeff Kirsher 	}
28189aebddd1SJeff Kirsher 
28199aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
28209aebddd1SJeff Kirsher 	if (!wrb) {
28219aebddd1SJeff Kirsher 		status = -EBUSY;
28229aebddd1SJeff Kirsher 		goto err;
28239aebddd1SJeff Kirsher 	}
28249aebddd1SJeff Kirsher 	req = attribs_cmd.va;
28259aebddd1SJeff Kirsher 
2826106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2827a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len,
2828a2cc4e0bSSathya Perla 			       wrb, &attribs_cmd);
28299aebddd1SJeff Kirsher 
28309aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
28319aebddd1SJeff Kirsher 	if (!status) {
28329aebddd1SJeff Kirsher 		attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
28339aebddd1SJeff Kirsher 		adapter->hba_port_num = attribs->hba_attribs.phy_port;
28349aebddd1SJeff Kirsher 	}
28359aebddd1SJeff Kirsher 
28369aebddd1SJeff Kirsher err:
28379aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
2838d98ef50fSSuresh Reddy 	if (attribs_cmd.va)
2839d98ef50fSSuresh Reddy 		pci_free_consistent(adapter->pdev, attribs_cmd.size,
2840d98ef50fSSuresh Reddy 				    attribs_cmd.va, attribs_cmd.dma);
28419aebddd1SJeff Kirsher 	return status;
28429aebddd1SJeff Kirsher }
28439aebddd1SJeff Kirsher 
28449aebddd1SJeff Kirsher /* Uses mbox */
28459aebddd1SJeff Kirsher int be_cmd_req_native_mode(struct be_adapter *adapter)
28469aebddd1SJeff Kirsher {
28479aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
28489aebddd1SJeff Kirsher 	struct be_cmd_req_set_func_cap *req;
28499aebddd1SJeff Kirsher 	int status;
28509aebddd1SJeff Kirsher 
28519aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
28529aebddd1SJeff Kirsher 		return -1;
28539aebddd1SJeff Kirsher 
28549aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
28559aebddd1SJeff Kirsher 	if (!wrb) {
28569aebddd1SJeff Kirsher 		status = -EBUSY;
28579aebddd1SJeff Kirsher 		goto err;
28589aebddd1SJeff Kirsher 	}
28599aebddd1SJeff Kirsher 
28609aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
28619aebddd1SJeff Kirsher 
2862106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2863a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP,
2864a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
28659aebddd1SJeff Kirsher 
28669aebddd1SJeff Kirsher 	req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS |
28679aebddd1SJeff Kirsher 				CAPABILITY_BE3_NATIVE_ERX_API);
28689aebddd1SJeff Kirsher 	req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API);
28699aebddd1SJeff Kirsher 
28709aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
28719aebddd1SJeff Kirsher 	if (!status) {
28729aebddd1SJeff Kirsher 		struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb);
287303d28ffeSKalesh AP 
28749aebddd1SJeff Kirsher 		adapter->be3_native = le32_to_cpu(resp->cap_flags) &
28759aebddd1SJeff Kirsher 					CAPABILITY_BE3_NATIVE_ERX_API;
2876d379142bSSathya Perla 		if (!adapter->be3_native)
2877d379142bSSathya Perla 			dev_warn(&adapter->pdev->dev,
2878d379142bSSathya Perla 				 "adapter not in advanced mode\n");
28799aebddd1SJeff Kirsher 	}
28809aebddd1SJeff Kirsher err:
28819aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
28829aebddd1SJeff Kirsher 	return status;
28839aebddd1SJeff Kirsher }
2884590c391dSPadmanabh Ratnakar 
2885f25b119cSPadmanabh Ratnakar /* Get privilege(s) for a function */
2886f25b119cSPadmanabh Ratnakar int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
2887f25b119cSPadmanabh Ratnakar 			     u32 domain)
2888f25b119cSPadmanabh Ratnakar {
2889f25b119cSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
2890f25b119cSPadmanabh Ratnakar 	struct be_cmd_req_get_fn_privileges *req;
2891f25b119cSPadmanabh Ratnakar 	int status;
2892f25b119cSPadmanabh Ratnakar 
2893f25b119cSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
2894f25b119cSPadmanabh Ratnakar 
2895f25b119cSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
2896f25b119cSPadmanabh Ratnakar 	if (!wrb) {
2897f25b119cSPadmanabh Ratnakar 		status = -EBUSY;
2898f25b119cSPadmanabh Ratnakar 		goto err;
2899f25b119cSPadmanabh Ratnakar 	}
2900f25b119cSPadmanabh Ratnakar 
2901f25b119cSPadmanabh Ratnakar 	req = embedded_payload(wrb);
2902f25b119cSPadmanabh Ratnakar 
2903f25b119cSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2904f25b119cSPadmanabh Ratnakar 			       OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
2905f25b119cSPadmanabh Ratnakar 			       wrb, NULL);
2906f25b119cSPadmanabh Ratnakar 
2907f25b119cSPadmanabh Ratnakar 	req->hdr.domain = domain;
2908f25b119cSPadmanabh Ratnakar 
2909f25b119cSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
2910f25b119cSPadmanabh Ratnakar 	if (!status) {
2911f25b119cSPadmanabh Ratnakar 		struct be_cmd_resp_get_fn_privileges *resp =
2912f25b119cSPadmanabh Ratnakar 						embedded_payload(wrb);
291303d28ffeSKalesh AP 
2914f25b119cSPadmanabh Ratnakar 		*privilege = le32_to_cpu(resp->privilege_mask);
291502308d74SSuresh Reddy 
291602308d74SSuresh Reddy 		/* In UMC mode FW does not return right privileges.
291702308d74SSuresh Reddy 		 * Override with correct privilege equivalent to PF.
291802308d74SSuresh Reddy 		 */
291902308d74SSuresh Reddy 		if (BEx_chip(adapter) && be_is_mc(adapter) &&
292002308d74SSuresh Reddy 		    be_physfn(adapter))
292102308d74SSuresh Reddy 			*privilege = MAX_PRIVILEGES;
2922f25b119cSPadmanabh Ratnakar 	}
2923f25b119cSPadmanabh Ratnakar 
2924f25b119cSPadmanabh Ratnakar err:
2925f25b119cSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
2926f25b119cSPadmanabh Ratnakar 	return status;
2927f25b119cSPadmanabh Ratnakar }
2928f25b119cSPadmanabh Ratnakar 
292904a06028SSathya Perla /* Set privilege(s) for a function */
293004a06028SSathya Perla int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges,
293104a06028SSathya Perla 			     u32 domain)
293204a06028SSathya Perla {
293304a06028SSathya Perla 	struct be_mcc_wrb *wrb;
293404a06028SSathya Perla 	struct be_cmd_req_set_fn_privileges *req;
293504a06028SSathya Perla 	int status;
293604a06028SSathya Perla 
293704a06028SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
293804a06028SSathya Perla 
293904a06028SSathya Perla 	wrb = wrb_from_mccq(adapter);
294004a06028SSathya Perla 	if (!wrb) {
294104a06028SSathya Perla 		status = -EBUSY;
294204a06028SSathya Perla 		goto err;
294304a06028SSathya Perla 	}
294404a06028SSathya Perla 
294504a06028SSathya Perla 	req = embedded_payload(wrb);
294604a06028SSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
294704a06028SSathya Perla 			       OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req),
294804a06028SSathya Perla 			       wrb, NULL);
294904a06028SSathya Perla 	req->hdr.domain = domain;
295004a06028SSathya Perla 	if (lancer_chip(adapter))
295104a06028SSathya Perla 		req->privileges_lancer = cpu_to_le32(privileges);
295204a06028SSathya Perla 	else
295304a06028SSathya Perla 		req->privileges = cpu_to_le32(privileges);
295404a06028SSathya Perla 
295504a06028SSathya Perla 	status = be_mcc_notify_wait(adapter);
295604a06028SSathya Perla err:
295704a06028SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
295804a06028SSathya Perla 	return status;
295904a06028SSathya Perla }
296004a06028SSathya Perla 
29615a712c13SSathya Perla /* pmac_id_valid: true => pmac_id is supplied and MAC address is requested.
29625a712c13SSathya Perla  * pmac_id_valid: false => pmac_id or MAC address is requested.
29635a712c13SSathya Perla  *		  If pmac_id is returned, pmac_id_valid is returned as true
29645a712c13SSathya Perla  */
29651578e777SPadmanabh Ratnakar int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
2966b188f090SSuresh Reddy 			     bool *pmac_id_valid, u32 *pmac_id, u32 if_handle,
2967b188f090SSuresh Reddy 			     u8 domain)
2968590c391dSPadmanabh Ratnakar {
2969590c391dSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
2970590c391dSPadmanabh Ratnakar 	struct be_cmd_req_get_mac_list *req;
2971590c391dSPadmanabh Ratnakar 	int status;
2972590c391dSPadmanabh Ratnakar 	int mac_count;
2973e5e1ee89SPadmanabh Ratnakar 	struct be_dma_mem get_mac_list_cmd;
2974e5e1ee89SPadmanabh Ratnakar 	int i;
2975e5e1ee89SPadmanabh Ratnakar 
2976e5e1ee89SPadmanabh Ratnakar 	memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
2977e5e1ee89SPadmanabh Ratnakar 	get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
2978e5e1ee89SPadmanabh Ratnakar 	get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev,
2979e5e1ee89SPadmanabh Ratnakar 						   get_mac_list_cmd.size,
2980e5e1ee89SPadmanabh Ratnakar 						   &get_mac_list_cmd.dma);
2981e5e1ee89SPadmanabh Ratnakar 
2982e5e1ee89SPadmanabh Ratnakar 	if (!get_mac_list_cmd.va) {
2983e5e1ee89SPadmanabh Ratnakar 		dev_err(&adapter->pdev->dev,
2984e5e1ee89SPadmanabh Ratnakar 			"Memory allocation failure during GET_MAC_LIST\n");
2985e5e1ee89SPadmanabh Ratnakar 		return -ENOMEM;
2986e5e1ee89SPadmanabh Ratnakar 	}
2987590c391dSPadmanabh Ratnakar 
2988590c391dSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
2989590c391dSPadmanabh Ratnakar 
2990590c391dSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
2991590c391dSPadmanabh Ratnakar 	if (!wrb) {
2992590c391dSPadmanabh Ratnakar 		status = -EBUSY;
2993e5e1ee89SPadmanabh Ratnakar 		goto out;
2994590c391dSPadmanabh Ratnakar 	}
2995e5e1ee89SPadmanabh Ratnakar 
2996e5e1ee89SPadmanabh Ratnakar 	req = get_mac_list_cmd.va;
2997590c391dSPadmanabh Ratnakar 
2998590c391dSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2999bf591f51SSathya Perla 			       OPCODE_COMMON_GET_MAC_LIST,
3000bf591f51SSathya Perla 			       get_mac_list_cmd.size, wrb, &get_mac_list_cmd);
3001590c391dSPadmanabh Ratnakar 	req->hdr.domain = domain;
3002e5e1ee89SPadmanabh Ratnakar 	req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
30035a712c13SSathya Perla 	if (*pmac_id_valid) {
30045a712c13SSathya Perla 		req->mac_id = cpu_to_le32(*pmac_id);
3005b188f090SSuresh Reddy 		req->iface_id = cpu_to_le16(if_handle);
30065a712c13SSathya Perla 		req->perm_override = 0;
30075a712c13SSathya Perla 	} else {
3008e5e1ee89SPadmanabh Ratnakar 		req->perm_override = 1;
30095a712c13SSathya Perla 	}
3010590c391dSPadmanabh Ratnakar 
3011590c391dSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3012590c391dSPadmanabh Ratnakar 	if (!status) {
3013590c391dSPadmanabh Ratnakar 		struct be_cmd_resp_get_mac_list *resp =
3014e5e1ee89SPadmanabh Ratnakar 						get_mac_list_cmd.va;
30155a712c13SSathya Perla 
30165a712c13SSathya Perla 		if (*pmac_id_valid) {
30175a712c13SSathya Perla 			memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr,
30185a712c13SSathya Perla 			       ETH_ALEN);
30195a712c13SSathya Perla 			goto out;
30205a712c13SSathya Perla 		}
30215a712c13SSathya Perla 
3022e5e1ee89SPadmanabh Ratnakar 		mac_count = resp->true_mac_count + resp->pseudo_mac_count;
3023e5e1ee89SPadmanabh Ratnakar 		/* Mac list returned could contain one or more active mac_ids
30241578e777SPadmanabh Ratnakar 		 * or one or more true or pseudo permanant mac addresses.
30251578e777SPadmanabh Ratnakar 		 * If an active mac_id is present, return first active mac_id
30261578e777SPadmanabh Ratnakar 		 * found.
3027e5e1ee89SPadmanabh Ratnakar 		 */
3028590c391dSPadmanabh Ratnakar 		for (i = 0; i < mac_count; i++) {
3029e5e1ee89SPadmanabh Ratnakar 			struct get_list_macaddr *mac_entry;
3030e5e1ee89SPadmanabh Ratnakar 			u16 mac_addr_size;
3031e5e1ee89SPadmanabh Ratnakar 			u32 mac_id;
3032e5e1ee89SPadmanabh Ratnakar 
3033e5e1ee89SPadmanabh Ratnakar 			mac_entry = &resp->macaddr_list[i];
3034e5e1ee89SPadmanabh Ratnakar 			mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size);
3035e5e1ee89SPadmanabh Ratnakar 			/* mac_id is a 32 bit value and mac_addr size
3036e5e1ee89SPadmanabh Ratnakar 			 * is 6 bytes
3037e5e1ee89SPadmanabh Ratnakar 			 */
3038e5e1ee89SPadmanabh Ratnakar 			if (mac_addr_size == sizeof(u32)) {
30395a712c13SSathya Perla 				*pmac_id_valid = true;
3040e5e1ee89SPadmanabh Ratnakar 				mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id;
3041e5e1ee89SPadmanabh Ratnakar 				*pmac_id = le32_to_cpu(mac_id);
3042e5e1ee89SPadmanabh Ratnakar 				goto out;
3043590c391dSPadmanabh Ratnakar 			}
3044590c391dSPadmanabh Ratnakar 		}
30451578e777SPadmanabh Ratnakar 		/* If no active mac_id found, return first mac addr */
30465a712c13SSathya Perla 		*pmac_id_valid = false;
3047e5e1ee89SPadmanabh Ratnakar 		memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr,
3048e5e1ee89SPadmanabh Ratnakar 		       ETH_ALEN);
3049590c391dSPadmanabh Ratnakar 	}
3050590c391dSPadmanabh Ratnakar 
3051e5e1ee89SPadmanabh Ratnakar out:
3052590c391dSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3053e5e1ee89SPadmanabh Ratnakar 	pci_free_consistent(adapter->pdev, get_mac_list_cmd.size,
3054e5e1ee89SPadmanabh Ratnakar 			    get_mac_list_cmd.va, get_mac_list_cmd.dma);
3055590c391dSPadmanabh Ratnakar 	return status;
3056590c391dSPadmanabh Ratnakar }
3057590c391dSPadmanabh Ratnakar 
3058a2cc4e0bSSathya Perla int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id,
3059a2cc4e0bSSathya Perla 			  u8 *mac, u32 if_handle, bool active, u32 domain)
30605a712c13SSathya Perla {
3061b188f090SSuresh Reddy 	if (!active)
3062b188f090SSuresh Reddy 		be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id,
3063b188f090SSuresh Reddy 					 if_handle, domain);
30643175d8c2SSathya Perla 	if (BEx_chip(adapter))
30655a712c13SSathya Perla 		return be_cmd_mac_addr_query(adapter, mac, false,
3066b188f090SSuresh Reddy 					     if_handle, curr_pmac_id);
30673175d8c2SSathya Perla 	else
30683175d8c2SSathya Perla 		/* Fetch the MAC address using pmac_id */
30693175d8c2SSathya Perla 		return be_cmd_get_mac_from_list(adapter, mac, &active,
3070b188f090SSuresh Reddy 						&curr_pmac_id,
3071b188f090SSuresh Reddy 						if_handle, domain);
30725a712c13SSathya Perla }
30735a712c13SSathya Perla 
307495046b92SSathya Perla int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac)
307595046b92SSathya Perla {
307695046b92SSathya Perla 	int status;
307795046b92SSathya Perla 	bool pmac_valid = false;
307895046b92SSathya Perla 
3079c7bf7169SJoe Perches 	eth_zero_addr(mac);
308095046b92SSathya Perla 
30813175d8c2SSathya Perla 	if (BEx_chip(adapter)) {
30823175d8c2SSathya Perla 		if (be_physfn(adapter))
30833175d8c2SSathya Perla 			status = be_cmd_mac_addr_query(adapter, mac, true, 0,
30843175d8c2SSathya Perla 						       0);
308595046b92SSathya Perla 		else
308695046b92SSathya Perla 			status = be_cmd_mac_addr_query(adapter, mac, false,
308795046b92SSathya Perla 						       adapter->if_handle, 0);
30883175d8c2SSathya Perla 	} else {
30893175d8c2SSathya Perla 		status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid,
3090b188f090SSuresh Reddy 						  NULL, adapter->if_handle, 0);
30913175d8c2SSathya Perla 	}
30923175d8c2SSathya Perla 
309395046b92SSathya Perla 	return status;
309495046b92SSathya Perla }
309595046b92SSathya Perla 
3096590c391dSPadmanabh Ratnakar /* Uses synchronous MCCQ */
3097590c391dSPadmanabh Ratnakar int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
3098590c391dSPadmanabh Ratnakar 			u8 mac_count, u32 domain)
3099590c391dSPadmanabh Ratnakar {
3100590c391dSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3101590c391dSPadmanabh Ratnakar 	struct be_cmd_req_set_mac_list *req;
3102590c391dSPadmanabh Ratnakar 	int status;
3103590c391dSPadmanabh Ratnakar 	struct be_dma_mem cmd;
3104590c391dSPadmanabh Ratnakar 
3105590c391dSPadmanabh Ratnakar 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3106590c391dSPadmanabh Ratnakar 	cmd.size = sizeof(struct be_cmd_req_set_mac_list);
3107590c391dSPadmanabh Ratnakar 	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size,
3108590c391dSPadmanabh Ratnakar 				    &cmd.dma, GFP_KERNEL);
3109d0320f75SJoe Perches 	if (!cmd.va)
3110590c391dSPadmanabh Ratnakar 		return -ENOMEM;
3111590c391dSPadmanabh Ratnakar 
3112590c391dSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
3113590c391dSPadmanabh Ratnakar 
3114590c391dSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
3115590c391dSPadmanabh Ratnakar 	if (!wrb) {
3116590c391dSPadmanabh Ratnakar 		status = -EBUSY;
3117590c391dSPadmanabh Ratnakar 		goto err;
3118590c391dSPadmanabh Ratnakar 	}
3119590c391dSPadmanabh Ratnakar 
3120590c391dSPadmanabh Ratnakar 	req = cmd.va;
3121590c391dSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3122590c391dSPadmanabh Ratnakar 			       OPCODE_COMMON_SET_MAC_LIST, sizeof(*req),
3123590c391dSPadmanabh Ratnakar 			       wrb, &cmd);
3124590c391dSPadmanabh Ratnakar 
3125590c391dSPadmanabh Ratnakar 	req->hdr.domain = domain;
3126590c391dSPadmanabh Ratnakar 	req->mac_count = mac_count;
3127590c391dSPadmanabh Ratnakar 	if (mac_count)
3128590c391dSPadmanabh Ratnakar 		memcpy(req->mac, mac_array, ETH_ALEN*mac_count);
3129590c391dSPadmanabh Ratnakar 
3130590c391dSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3131590c391dSPadmanabh Ratnakar 
3132590c391dSPadmanabh Ratnakar err:
3133a2cc4e0bSSathya Perla 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
3134590c391dSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3135590c391dSPadmanabh Ratnakar 	return status;
3136590c391dSPadmanabh Ratnakar }
31374762f6ceSAjit Khaparde 
31383175d8c2SSathya Perla /* Wrapper to delete any active MACs and provision the new mac.
31393175d8c2SSathya Perla  * Changes to MAC_LIST are allowed iff none of the MAC addresses in the
31403175d8c2SSathya Perla  * current list are active.
31413175d8c2SSathya Perla  */
31423175d8c2SSathya Perla int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
31433175d8c2SSathya Perla {
31443175d8c2SSathya Perla 	bool active_mac = false;
31453175d8c2SSathya Perla 	u8 old_mac[ETH_ALEN];
31463175d8c2SSathya Perla 	u32 pmac_id;
31473175d8c2SSathya Perla 	int status;
31483175d8c2SSathya Perla 
31493175d8c2SSathya Perla 	status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
3150b188f090SSuresh Reddy 					  &pmac_id, if_id, dom);
3151b188f090SSuresh Reddy 
31523175d8c2SSathya Perla 	if (!status && active_mac)
31533175d8c2SSathya Perla 		be_cmd_pmac_del(adapter, if_id, pmac_id, dom);
31543175d8c2SSathya Perla 
31553175d8c2SSathya Perla 	return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom);
31563175d8c2SSathya Perla }
31573175d8c2SSathya Perla 
3158f1f3ee1bSAjit Khaparde int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
3159a77dcb8cSAjit Khaparde 			  u32 domain, u16 intf_id, u16 hsw_mode)
3160f1f3ee1bSAjit Khaparde {
3161f1f3ee1bSAjit Khaparde 	struct be_mcc_wrb *wrb;
3162f1f3ee1bSAjit Khaparde 	struct be_cmd_req_set_hsw_config *req;
3163f1f3ee1bSAjit Khaparde 	void *ctxt;
3164f1f3ee1bSAjit Khaparde 	int status;
3165f1f3ee1bSAjit Khaparde 
3166f1f3ee1bSAjit Khaparde 	spin_lock_bh(&adapter->mcc_lock);
3167f1f3ee1bSAjit Khaparde 
3168f1f3ee1bSAjit Khaparde 	wrb = wrb_from_mccq(adapter);
3169f1f3ee1bSAjit Khaparde 	if (!wrb) {
3170f1f3ee1bSAjit Khaparde 		status = -EBUSY;
3171f1f3ee1bSAjit Khaparde 		goto err;
3172f1f3ee1bSAjit Khaparde 	}
3173f1f3ee1bSAjit Khaparde 
3174f1f3ee1bSAjit Khaparde 	req = embedded_payload(wrb);
3175f1f3ee1bSAjit Khaparde 	ctxt = &req->context;
3176f1f3ee1bSAjit Khaparde 
3177f1f3ee1bSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3178a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb,
3179a2cc4e0bSSathya Perla 			       NULL);
3180f1f3ee1bSAjit Khaparde 
3181f1f3ee1bSAjit Khaparde 	req->hdr.domain = domain;
3182f1f3ee1bSAjit Khaparde 	AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id);
3183f1f3ee1bSAjit Khaparde 	if (pvid) {
3184f1f3ee1bSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1);
3185f1f3ee1bSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid);
3186f1f3ee1bSAjit Khaparde 	}
3187a77dcb8cSAjit Khaparde 	if (!BEx_chip(adapter) && hsw_mode) {
3188a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, interface_id,
3189a77dcb8cSAjit Khaparde 			      ctxt, adapter->hba_port_num);
3190a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1);
3191a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type,
3192a77dcb8cSAjit Khaparde 			      ctxt, hsw_mode);
3193a77dcb8cSAjit Khaparde 	}
3194f1f3ee1bSAjit Khaparde 
3195f1f3ee1bSAjit Khaparde 	be_dws_cpu_to_le(req->context, sizeof(req->context));
3196f1f3ee1bSAjit Khaparde 	status = be_mcc_notify_wait(adapter);
3197f1f3ee1bSAjit Khaparde 
3198f1f3ee1bSAjit Khaparde err:
3199f1f3ee1bSAjit Khaparde 	spin_unlock_bh(&adapter->mcc_lock);
3200f1f3ee1bSAjit Khaparde 	return status;
3201f1f3ee1bSAjit Khaparde }
3202f1f3ee1bSAjit Khaparde 
3203f1f3ee1bSAjit Khaparde /* Get Hyper switch config */
3204f1f3ee1bSAjit Khaparde int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
3205a77dcb8cSAjit Khaparde 			  u32 domain, u16 intf_id, u8 *mode)
3206f1f3ee1bSAjit Khaparde {
3207f1f3ee1bSAjit Khaparde 	struct be_mcc_wrb *wrb;
3208f1f3ee1bSAjit Khaparde 	struct be_cmd_req_get_hsw_config *req;
3209f1f3ee1bSAjit Khaparde 	void *ctxt;
3210f1f3ee1bSAjit Khaparde 	int status;
3211f1f3ee1bSAjit Khaparde 	u16 vid;
3212f1f3ee1bSAjit Khaparde 
3213f1f3ee1bSAjit Khaparde 	spin_lock_bh(&adapter->mcc_lock);
3214f1f3ee1bSAjit Khaparde 
3215f1f3ee1bSAjit Khaparde 	wrb = wrb_from_mccq(adapter);
3216f1f3ee1bSAjit Khaparde 	if (!wrb) {
3217f1f3ee1bSAjit Khaparde 		status = -EBUSY;
3218f1f3ee1bSAjit Khaparde 		goto err;
3219f1f3ee1bSAjit Khaparde 	}
3220f1f3ee1bSAjit Khaparde 
3221f1f3ee1bSAjit Khaparde 	req = embedded_payload(wrb);
3222f1f3ee1bSAjit Khaparde 	ctxt = &req->context;
3223f1f3ee1bSAjit Khaparde 
3224f1f3ee1bSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3225a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb,
3226a2cc4e0bSSathya Perla 			       NULL);
3227f1f3ee1bSAjit Khaparde 
3228f1f3ee1bSAjit Khaparde 	req->hdr.domain = domain;
3229a77dcb8cSAjit Khaparde 	AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
3230a77dcb8cSAjit Khaparde 		      ctxt, intf_id);
3231f1f3ee1bSAjit Khaparde 	AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1);
3232a77dcb8cSAjit Khaparde 
32332c07c1d7SVasundhara Volam 	if (!BEx_chip(adapter) && mode) {
3234a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
3235a77dcb8cSAjit Khaparde 			      ctxt, adapter->hba_port_num);
3236a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1);
3237a77dcb8cSAjit Khaparde 	}
3238f1f3ee1bSAjit Khaparde 	be_dws_cpu_to_le(req->context, sizeof(req->context));
3239f1f3ee1bSAjit Khaparde 
3240f1f3ee1bSAjit Khaparde 	status = be_mcc_notify_wait(adapter);
3241f1f3ee1bSAjit Khaparde 	if (!status) {
3242f1f3ee1bSAjit Khaparde 		struct be_cmd_resp_get_hsw_config *resp =
3243f1f3ee1bSAjit Khaparde 						embedded_payload(wrb);
324403d28ffeSKalesh AP 
3245a2cc4e0bSSathya Perla 		be_dws_le_to_cpu(&resp->context, sizeof(resp->context));
3246f1f3ee1bSAjit Khaparde 		vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3247f1f3ee1bSAjit Khaparde 				    pvid, &resp->context);
3248a77dcb8cSAjit Khaparde 		if (pvid)
3249f1f3ee1bSAjit Khaparde 			*pvid = le16_to_cpu(vid);
3250a77dcb8cSAjit Khaparde 		if (mode)
3251a77dcb8cSAjit Khaparde 			*mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3252a77dcb8cSAjit Khaparde 					      port_fwd_type, &resp->context);
3253f1f3ee1bSAjit Khaparde 	}
3254f1f3ee1bSAjit Khaparde 
3255f1f3ee1bSAjit Khaparde err:
3256f1f3ee1bSAjit Khaparde 	spin_unlock_bh(&adapter->mcc_lock);
3257f1f3ee1bSAjit Khaparde 	return status;
3258f1f3ee1bSAjit Khaparde }
3259f1f3ee1bSAjit Khaparde 
3260f7062ee5SSathya Perla static bool be_is_wol_excluded(struct be_adapter *adapter)
3261f7062ee5SSathya Perla {
3262f7062ee5SSathya Perla 	struct pci_dev *pdev = adapter->pdev;
3263f7062ee5SSathya Perla 
3264f7062ee5SSathya Perla 	if (!be_physfn(adapter))
3265f7062ee5SSathya Perla 		return true;
3266f7062ee5SSathya Perla 
3267f7062ee5SSathya Perla 	switch (pdev->subsystem_device) {
3268f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID1:
3269f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID2:
3270f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID3:
3271f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID4:
3272f7062ee5SSathya Perla 		return true;
3273f7062ee5SSathya Perla 	default:
3274f7062ee5SSathya Perla 		return false;
3275f7062ee5SSathya Perla 	}
3276f7062ee5SSathya Perla }
3277f7062ee5SSathya Perla 
32784762f6ceSAjit Khaparde int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
32794762f6ceSAjit Khaparde {
32804762f6ceSAjit Khaparde 	struct be_mcc_wrb *wrb;
32814762f6ceSAjit Khaparde 	struct be_cmd_req_acpi_wol_magic_config_v1 *req;
328276a9e08eSSuresh Reddy 	int status = 0;
32834762f6ceSAjit Khaparde 	struct be_dma_mem cmd;
32844762f6ceSAjit Khaparde 
3285f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
3286f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_ETH))
3287f25b119cSPadmanabh Ratnakar 		return -EPERM;
3288f25b119cSPadmanabh Ratnakar 
328976a9e08eSSuresh Reddy 	if (be_is_wol_excluded(adapter))
329076a9e08eSSuresh Reddy 		return status;
329176a9e08eSSuresh Reddy 
3292d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3293d98ef50fSSuresh Reddy 		return -1;
3294d98ef50fSSuresh Reddy 
32954762f6ceSAjit Khaparde 	memset(&cmd, 0, sizeof(struct be_dma_mem));
32964762f6ceSAjit Khaparde 	cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
3297a2cc4e0bSSathya Perla 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
32984762f6ceSAjit Khaparde 	if (!cmd.va) {
3299a2cc4e0bSSathya Perla 		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
3300d98ef50fSSuresh Reddy 		status = -ENOMEM;
3301d98ef50fSSuresh Reddy 		goto err;
33024762f6ceSAjit Khaparde 	}
33034762f6ceSAjit Khaparde 
33044762f6ceSAjit Khaparde 	wrb = wrb_from_mbox(adapter);
33054762f6ceSAjit Khaparde 	if (!wrb) {
33064762f6ceSAjit Khaparde 		status = -EBUSY;
33074762f6ceSAjit Khaparde 		goto err;
33084762f6ceSAjit Khaparde 	}
33094762f6ceSAjit Khaparde 
33104762f6ceSAjit Khaparde 	req = cmd.va;
33114762f6ceSAjit Khaparde 
33124762f6ceSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
33134762f6ceSAjit Khaparde 			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
331476a9e08eSSuresh Reddy 			       sizeof(*req), wrb, &cmd);
33154762f6ceSAjit Khaparde 
33164762f6ceSAjit Khaparde 	req->hdr.version = 1;
33174762f6ceSAjit Khaparde 	req->query_options = BE_GET_WOL_CAP;
33184762f6ceSAjit Khaparde 
33194762f6ceSAjit Khaparde 	status = be_mbox_notify_wait(adapter);
33204762f6ceSAjit Khaparde 	if (!status) {
33214762f6ceSAjit Khaparde 		struct be_cmd_resp_acpi_wol_magic_config_v1 *resp;
332203d28ffeSKalesh AP 
33234762f6ceSAjit Khaparde 		resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va;
33244762f6ceSAjit Khaparde 
33254762f6ceSAjit Khaparde 		adapter->wol_cap = resp->wol_settings;
332676a9e08eSSuresh Reddy 		if (adapter->wol_cap & BE_WOL_CAP)
332776a9e08eSSuresh Reddy 			adapter->wol_en = true;
33284762f6ceSAjit Khaparde 	}
33294762f6ceSAjit Khaparde err:
33304762f6ceSAjit Khaparde 	mutex_unlock(&adapter->mbox_lock);
3331d98ef50fSSuresh Reddy 	if (cmd.va)
33324762f6ceSAjit Khaparde 		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
33334762f6ceSAjit Khaparde 	return status;
3334941a77d5SSomnath Kotur 
3335941a77d5SSomnath Kotur }
3336baaa08d1SVasundhara Volam 
3337baaa08d1SVasundhara Volam int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level)
3338baaa08d1SVasundhara Volam {
3339baaa08d1SVasundhara Volam 	struct be_dma_mem extfat_cmd;
3340baaa08d1SVasundhara Volam 	struct be_fat_conf_params *cfgs;
3341baaa08d1SVasundhara Volam 	int status;
3342baaa08d1SVasundhara Volam 	int i, j;
3343baaa08d1SVasundhara Volam 
3344baaa08d1SVasundhara Volam 	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
3345baaa08d1SVasundhara Volam 	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
3346baaa08d1SVasundhara Volam 	extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
3347baaa08d1SVasundhara Volam 					     &extfat_cmd.dma);
3348baaa08d1SVasundhara Volam 	if (!extfat_cmd.va)
3349baaa08d1SVasundhara Volam 		return -ENOMEM;
3350baaa08d1SVasundhara Volam 
3351baaa08d1SVasundhara Volam 	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
3352baaa08d1SVasundhara Volam 	if (status)
3353baaa08d1SVasundhara Volam 		goto err;
3354baaa08d1SVasundhara Volam 
3355baaa08d1SVasundhara Volam 	cfgs = (struct be_fat_conf_params *)
3356baaa08d1SVasundhara Volam 			(extfat_cmd.va + sizeof(struct be_cmd_resp_hdr));
3357baaa08d1SVasundhara Volam 	for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) {
3358baaa08d1SVasundhara Volam 		u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes);
335903d28ffeSKalesh AP 
3360baaa08d1SVasundhara Volam 		for (j = 0; j < num_modes; j++) {
3361baaa08d1SVasundhara Volam 			if (cfgs->module[i].trace_lvl[j].mode == MODE_UART)
3362baaa08d1SVasundhara Volam 				cfgs->module[i].trace_lvl[j].dbg_lvl =
3363baaa08d1SVasundhara Volam 							cpu_to_le32(level);
3364baaa08d1SVasundhara Volam 		}
3365baaa08d1SVasundhara Volam 	}
3366baaa08d1SVasundhara Volam 
3367baaa08d1SVasundhara Volam 	status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs);
3368baaa08d1SVasundhara Volam err:
3369baaa08d1SVasundhara Volam 	pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
3370baaa08d1SVasundhara Volam 			    extfat_cmd.dma);
3371baaa08d1SVasundhara Volam 	return status;
3372baaa08d1SVasundhara Volam }
3373baaa08d1SVasundhara Volam 
3374baaa08d1SVasundhara Volam int be_cmd_get_fw_log_level(struct be_adapter *adapter)
3375baaa08d1SVasundhara Volam {
3376baaa08d1SVasundhara Volam 	struct be_dma_mem extfat_cmd;
3377baaa08d1SVasundhara Volam 	struct be_fat_conf_params *cfgs;
3378baaa08d1SVasundhara Volam 	int status, j;
3379baaa08d1SVasundhara Volam 	int level = 0;
3380baaa08d1SVasundhara Volam 
3381baaa08d1SVasundhara Volam 	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
3382baaa08d1SVasundhara Volam 	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
3383baaa08d1SVasundhara Volam 	extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
3384baaa08d1SVasundhara Volam 					     &extfat_cmd.dma);
3385baaa08d1SVasundhara Volam 
3386baaa08d1SVasundhara Volam 	if (!extfat_cmd.va) {
3387baaa08d1SVasundhara Volam 		dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
3388baaa08d1SVasundhara Volam 			__func__);
3389baaa08d1SVasundhara Volam 		goto err;
3390baaa08d1SVasundhara Volam 	}
3391baaa08d1SVasundhara Volam 
3392baaa08d1SVasundhara Volam 	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
3393baaa08d1SVasundhara Volam 	if (!status) {
3394baaa08d1SVasundhara Volam 		cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
3395baaa08d1SVasundhara Volam 						sizeof(struct be_cmd_resp_hdr));
339603d28ffeSKalesh AP 
3397baaa08d1SVasundhara Volam 		for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) {
3398baaa08d1SVasundhara Volam 			if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
3399baaa08d1SVasundhara Volam 				level = cfgs->module[0].trace_lvl[j].dbg_lvl;
3400baaa08d1SVasundhara Volam 		}
3401baaa08d1SVasundhara Volam 	}
3402baaa08d1SVasundhara Volam 	pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
3403baaa08d1SVasundhara Volam 			    extfat_cmd.dma);
3404baaa08d1SVasundhara Volam err:
3405baaa08d1SVasundhara Volam 	return level;
3406baaa08d1SVasundhara Volam }
3407baaa08d1SVasundhara Volam 
3408941a77d5SSomnath Kotur int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
3409941a77d5SSomnath Kotur 				   struct be_dma_mem *cmd)
3410941a77d5SSomnath Kotur {
3411941a77d5SSomnath Kotur 	struct be_mcc_wrb *wrb;
3412941a77d5SSomnath Kotur 	struct be_cmd_req_get_ext_fat_caps *req;
3413941a77d5SSomnath Kotur 	int status;
3414941a77d5SSomnath Kotur 
3415941a77d5SSomnath Kotur 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3416941a77d5SSomnath Kotur 		return -1;
3417941a77d5SSomnath Kotur 
3418941a77d5SSomnath Kotur 	wrb = wrb_from_mbox(adapter);
3419941a77d5SSomnath Kotur 	if (!wrb) {
3420941a77d5SSomnath Kotur 		status = -EBUSY;
3421941a77d5SSomnath Kotur 		goto err;
3422941a77d5SSomnath Kotur 	}
3423941a77d5SSomnath Kotur 
3424941a77d5SSomnath Kotur 	req = cmd->va;
3425941a77d5SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3426941a77d5SSomnath Kotur 			       OPCODE_COMMON_GET_EXT_FAT_CAPABILITES,
3427941a77d5SSomnath Kotur 			       cmd->size, wrb, cmd);
3428941a77d5SSomnath Kotur 	req->parameter_type = cpu_to_le32(1);
3429941a77d5SSomnath Kotur 
3430941a77d5SSomnath Kotur 	status = be_mbox_notify_wait(adapter);
3431941a77d5SSomnath Kotur err:
3432941a77d5SSomnath Kotur 	mutex_unlock(&adapter->mbox_lock);
3433941a77d5SSomnath Kotur 	return status;
3434941a77d5SSomnath Kotur }
3435941a77d5SSomnath Kotur 
3436941a77d5SSomnath Kotur int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
3437941a77d5SSomnath Kotur 				   struct be_dma_mem *cmd,
3438941a77d5SSomnath Kotur 				   struct be_fat_conf_params *configs)
3439941a77d5SSomnath Kotur {
3440941a77d5SSomnath Kotur 	struct be_mcc_wrb *wrb;
3441941a77d5SSomnath Kotur 	struct be_cmd_req_set_ext_fat_caps *req;
3442941a77d5SSomnath Kotur 	int status;
3443941a77d5SSomnath Kotur 
3444941a77d5SSomnath Kotur 	spin_lock_bh(&adapter->mcc_lock);
3445941a77d5SSomnath Kotur 
3446941a77d5SSomnath Kotur 	wrb = wrb_from_mccq(adapter);
3447941a77d5SSomnath Kotur 	if (!wrb) {
3448941a77d5SSomnath Kotur 		status = -EBUSY;
3449941a77d5SSomnath Kotur 		goto err;
3450941a77d5SSomnath Kotur 	}
3451941a77d5SSomnath Kotur 
3452941a77d5SSomnath Kotur 	req = cmd->va;
3453941a77d5SSomnath Kotur 	memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params));
3454941a77d5SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3455941a77d5SSomnath Kotur 			       OPCODE_COMMON_SET_EXT_FAT_CAPABILITES,
3456941a77d5SSomnath Kotur 			       cmd->size, wrb, cmd);
3457941a77d5SSomnath Kotur 
3458941a77d5SSomnath Kotur 	status = be_mcc_notify_wait(adapter);
3459941a77d5SSomnath Kotur err:
3460941a77d5SSomnath Kotur 	spin_unlock_bh(&adapter->mcc_lock);
3461941a77d5SSomnath Kotur 	return status;
34624762f6ceSAjit Khaparde }
34636a4ab669SParav Pandit 
346421252377SVasundhara Volam int be_cmd_query_port_name(struct be_adapter *adapter)
3465b4e32a71SPadmanabh Ratnakar {
3466b4e32a71SPadmanabh Ratnakar 	struct be_cmd_req_get_port_name *req;
346721252377SVasundhara Volam 	struct be_mcc_wrb *wrb;
3468b4e32a71SPadmanabh Ratnakar 	int status;
3469b4e32a71SPadmanabh Ratnakar 
347021252377SVasundhara Volam 	if (mutex_lock_interruptible(&adapter->mbox_lock))
347121252377SVasundhara Volam 		return -1;
3472b4e32a71SPadmanabh Ratnakar 
347321252377SVasundhara Volam 	wrb = wrb_from_mbox(adapter);
3474b4e32a71SPadmanabh Ratnakar 	req = embedded_payload(wrb);
3475b4e32a71SPadmanabh Ratnakar 
3476b4e32a71SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3477b4e32a71SPadmanabh Ratnakar 			       OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb,
3478b4e32a71SPadmanabh Ratnakar 			       NULL);
347921252377SVasundhara Volam 	if (!BEx_chip(adapter))
3480b4e32a71SPadmanabh Ratnakar 		req->hdr.version = 1;
3481b4e32a71SPadmanabh Ratnakar 
348221252377SVasundhara Volam 	status = be_mbox_notify_wait(adapter);
3483b4e32a71SPadmanabh Ratnakar 	if (!status) {
3484b4e32a71SPadmanabh Ratnakar 		struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb);
348503d28ffeSKalesh AP 
348621252377SVasundhara Volam 		adapter->port_name = resp->port_name[adapter->hba_port_num];
3487b4e32a71SPadmanabh Ratnakar 	} else {
348821252377SVasundhara Volam 		adapter->port_name = adapter->hba_port_num + '0';
3489b4e32a71SPadmanabh Ratnakar 	}
349021252377SVasundhara Volam 
349121252377SVasundhara Volam 	mutex_unlock(&adapter->mbox_lock);
3492b4e32a71SPadmanabh Ratnakar 	return status;
3493b4e32a71SPadmanabh Ratnakar }
3494b4e32a71SPadmanabh Ratnakar 
349510cccf60SVasundhara Volam /* Descriptor type */
349610cccf60SVasundhara Volam enum {
349710cccf60SVasundhara Volam 	FUNC_DESC = 1,
349810cccf60SVasundhara Volam 	VFT_DESC = 2
349910cccf60SVasundhara Volam };
350010cccf60SVasundhara Volam 
350110cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
350210cccf60SVasundhara Volam 					       int desc_type)
3503abb93951SPadmanabh Ratnakar {
3504150d58c7SVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
350510cccf60SVasundhara Volam 	struct be_nic_res_desc *nic;
3506abb93951SPadmanabh Ratnakar 	int i;
3507abb93951SPadmanabh Ratnakar 
3508abb93951SPadmanabh Ratnakar 	for (i = 0; i < desc_count; i++) {
3509150d58c7SVasundhara Volam 		if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
351010cccf60SVasundhara Volam 		    hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) {
351110cccf60SVasundhara Volam 			nic = (struct be_nic_res_desc *)hdr;
351210cccf60SVasundhara Volam 			if (desc_type == FUNC_DESC ||
351310cccf60SVasundhara Volam 			    (desc_type == VFT_DESC &&
351410cccf60SVasundhara Volam 			     nic->flags & (1 << VFT_SHIFT)))
351510cccf60SVasundhara Volam 				return nic;
351610cccf60SVasundhara Volam 		}
3517150d58c7SVasundhara Volam 
3518150d58c7SVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
3519150d58c7SVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
3520150d58c7SVasundhara Volam 	}
3521950e2958SWei Yang 	return NULL;
3522abb93951SPadmanabh Ratnakar }
3523abb93951SPadmanabh Ratnakar 
352410cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count)
352510cccf60SVasundhara Volam {
352610cccf60SVasundhara Volam 	return be_get_nic_desc(buf, desc_count, VFT_DESC);
352710cccf60SVasundhara Volam }
352810cccf60SVasundhara Volam 
352910cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count)
353010cccf60SVasundhara Volam {
353110cccf60SVasundhara Volam 	return be_get_nic_desc(buf, desc_count, FUNC_DESC);
353210cccf60SVasundhara Volam }
353310cccf60SVasundhara Volam 
3534150d58c7SVasundhara Volam static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf,
3535150d58c7SVasundhara Volam 						 u32 desc_count)
3536150d58c7SVasundhara Volam {
3537150d58c7SVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
3538150d58c7SVasundhara Volam 	struct be_pcie_res_desc *pcie;
3539150d58c7SVasundhara Volam 	int i;
3540150d58c7SVasundhara Volam 
3541150d58c7SVasundhara Volam 	for (i = 0; i < desc_count; i++) {
3542150d58c7SVasundhara Volam 		if ((hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 ||
3543150d58c7SVasundhara Volam 		     hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1)) {
3544150d58c7SVasundhara Volam 			pcie = (struct be_pcie_res_desc	*)hdr;
3545150d58c7SVasundhara Volam 			if (pcie->pf_num == devfn)
3546150d58c7SVasundhara Volam 				return pcie;
3547150d58c7SVasundhara Volam 		}
3548150d58c7SVasundhara Volam 
3549150d58c7SVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
3550150d58c7SVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
3551150d58c7SVasundhara Volam 	}
3552abb93951SPadmanabh Ratnakar 	return NULL;
3553abb93951SPadmanabh Ratnakar }
3554abb93951SPadmanabh Ratnakar 
3555f93f160bSVasundhara Volam static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
3556f93f160bSVasundhara Volam {
3557f93f160bSVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
3558f93f160bSVasundhara Volam 	int i;
3559f93f160bSVasundhara Volam 
3560f93f160bSVasundhara Volam 	for (i = 0; i < desc_count; i++) {
3561f93f160bSVasundhara Volam 		if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
3562f93f160bSVasundhara Volam 			return (struct be_port_res_desc *)hdr;
3563f93f160bSVasundhara Volam 
3564f93f160bSVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
3565f93f160bSVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
3566f93f160bSVasundhara Volam 	}
3567f93f160bSVasundhara Volam 	return NULL;
3568f93f160bSVasundhara Volam }
3569f93f160bSVasundhara Volam 
357092bf14abSSathya Perla static void be_copy_nic_desc(struct be_resources *res,
357192bf14abSSathya Perla 			     struct be_nic_res_desc *desc)
357292bf14abSSathya Perla {
357392bf14abSSathya Perla 	res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count);
357492bf14abSSathya Perla 	res->max_vlans = le16_to_cpu(desc->vlan_count);
357592bf14abSSathya Perla 	res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
357692bf14abSSathya Perla 	res->max_tx_qs = le16_to_cpu(desc->txq_count);
357792bf14abSSathya Perla 	res->max_rss_qs = le16_to_cpu(desc->rssq_count);
357892bf14abSSathya Perla 	res->max_rx_qs = le16_to_cpu(desc->rq_count);
357992bf14abSSathya Perla 	res->max_evt_qs = le16_to_cpu(desc->eq_count);
358092bf14abSSathya Perla 	/* Clear flags that driver is not interested in */
358192bf14abSSathya Perla 	res->if_cap_flags = le32_to_cpu(desc->cap_flags) &
358292bf14abSSathya Perla 				BE_IF_CAP_FLAGS_WANT;
358392bf14abSSathya Perla 	/* Need 1 RXQ as the default RXQ */
358492bf14abSSathya Perla 	if (res->max_rss_qs && res->max_rss_qs == res->max_rx_qs)
358592bf14abSSathya Perla 		res->max_rss_qs -= 1;
358692bf14abSSathya Perla }
358792bf14abSSathya Perla 
3588abb93951SPadmanabh Ratnakar /* Uses Mbox */
358992bf14abSSathya Perla int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
3590abb93951SPadmanabh Ratnakar {
3591abb93951SPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3592abb93951SPadmanabh Ratnakar 	struct be_cmd_req_get_func_config *req;
3593abb93951SPadmanabh Ratnakar 	int status;
3594abb93951SPadmanabh Ratnakar 	struct be_dma_mem cmd;
3595abb93951SPadmanabh Ratnakar 
3596d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3597d98ef50fSSuresh Reddy 		return -1;
3598d98ef50fSSuresh Reddy 
3599abb93951SPadmanabh Ratnakar 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3600abb93951SPadmanabh Ratnakar 	cmd.size = sizeof(struct be_cmd_resp_get_func_config);
3601a2cc4e0bSSathya Perla 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
3602abb93951SPadmanabh Ratnakar 	if (!cmd.va) {
3603abb93951SPadmanabh Ratnakar 		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
3604d98ef50fSSuresh Reddy 		status = -ENOMEM;
3605d98ef50fSSuresh Reddy 		goto err;
3606abb93951SPadmanabh Ratnakar 	}
3607abb93951SPadmanabh Ratnakar 
3608abb93951SPadmanabh Ratnakar 	wrb = wrb_from_mbox(adapter);
3609abb93951SPadmanabh Ratnakar 	if (!wrb) {
3610abb93951SPadmanabh Ratnakar 		status = -EBUSY;
3611abb93951SPadmanabh Ratnakar 		goto err;
3612abb93951SPadmanabh Ratnakar 	}
3613abb93951SPadmanabh Ratnakar 
3614abb93951SPadmanabh Ratnakar 	req = cmd.va;
3615abb93951SPadmanabh Ratnakar 
3616abb93951SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3617abb93951SPadmanabh Ratnakar 			       OPCODE_COMMON_GET_FUNC_CONFIG,
3618abb93951SPadmanabh Ratnakar 			       cmd.size, wrb, &cmd);
3619abb93951SPadmanabh Ratnakar 
362028710c55SKalesh AP 	if (skyhawk_chip(adapter))
362128710c55SKalesh AP 		req->hdr.version = 1;
362228710c55SKalesh AP 
3623abb93951SPadmanabh Ratnakar 	status = be_mbox_notify_wait(adapter);
3624abb93951SPadmanabh Ratnakar 	if (!status) {
3625abb93951SPadmanabh Ratnakar 		struct be_cmd_resp_get_func_config *resp = cmd.va;
3626abb93951SPadmanabh Ratnakar 		u32 desc_count = le32_to_cpu(resp->desc_count);
3627150d58c7SVasundhara Volam 		struct be_nic_res_desc *desc;
3628abb93951SPadmanabh Ratnakar 
362910cccf60SVasundhara Volam 		desc = be_get_func_nic_desc(resp->func_param, desc_count);
3630abb93951SPadmanabh Ratnakar 		if (!desc) {
3631abb93951SPadmanabh Ratnakar 			status = -EINVAL;
3632abb93951SPadmanabh Ratnakar 			goto err;
3633abb93951SPadmanabh Ratnakar 		}
3634abb93951SPadmanabh Ratnakar 
3635d5c18473SPadmanabh Ratnakar 		adapter->pf_number = desc->pf_num;
363692bf14abSSathya Perla 		be_copy_nic_desc(res, desc);
3637abb93951SPadmanabh Ratnakar 	}
3638abb93951SPadmanabh Ratnakar err:
3639abb93951SPadmanabh Ratnakar 	mutex_unlock(&adapter->mbox_lock);
3640d98ef50fSSuresh Reddy 	if (cmd.va)
3641d98ef50fSSuresh Reddy 		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
3642abb93951SPadmanabh Ratnakar 	return status;
3643abb93951SPadmanabh Ratnakar }
3644abb93951SPadmanabh Ratnakar 
3645ba48c0c9SVasundhara Volam /* Will use MBOX only if MCCQ has not been created */
364692bf14abSSathya Perla int be_cmd_get_profile_config(struct be_adapter *adapter,
364792bf14abSSathya Perla 			      struct be_resources *res, u8 domain)
3648a05f99dbSVasundhara Volam {
3649150d58c7SVasundhara Volam 	struct be_cmd_resp_get_profile_config *resp;
3650ba48c0c9SVasundhara Volam 	struct be_cmd_req_get_profile_config *req;
365110cccf60SVasundhara Volam 	struct be_nic_res_desc *vf_res;
3652150d58c7SVasundhara Volam 	struct be_pcie_res_desc *pcie;
3653f93f160bSVasundhara Volam 	struct be_port_res_desc *port;
3654150d58c7SVasundhara Volam 	struct be_nic_res_desc *nic;
3655ba48c0c9SVasundhara Volam 	struct be_mcc_wrb wrb = {0};
3656a05f99dbSVasundhara Volam 	struct be_dma_mem cmd;
3657150d58c7SVasundhara Volam 	u32 desc_count;
3658a05f99dbSVasundhara Volam 	int status;
3659a05f99dbSVasundhara Volam 
3660a05f99dbSVasundhara Volam 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3661a05f99dbSVasundhara Volam 	cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
3662150d58c7SVasundhara Volam 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
3663150d58c7SVasundhara Volam 	if (!cmd.va)
3664a05f99dbSVasundhara Volam 		return -ENOMEM;
3665a05f99dbSVasundhara Volam 
3666ba48c0c9SVasundhara Volam 	req = cmd.va;
3667ba48c0c9SVasundhara Volam 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3668ba48c0c9SVasundhara Volam 			       OPCODE_COMMON_GET_PROFILE_CONFIG,
3669ba48c0c9SVasundhara Volam 			       cmd.size, &wrb, &cmd);
3670ba48c0c9SVasundhara Volam 
3671ba48c0c9SVasundhara Volam 	req->hdr.domain = domain;
3672ba48c0c9SVasundhara Volam 	if (!lancer_chip(adapter))
3673ba48c0c9SVasundhara Volam 		req->hdr.version = 1;
3674ba48c0c9SVasundhara Volam 	req->type = ACTIVE_PROFILE_TYPE;
3675ba48c0c9SVasundhara Volam 
3676ba48c0c9SVasundhara Volam 	status = be_cmd_notify_wait(adapter, &wrb);
3677150d58c7SVasundhara Volam 	if (status)
3678abb93951SPadmanabh Ratnakar 		goto err;
3679150d58c7SVasundhara Volam 
3680150d58c7SVasundhara Volam 	resp = cmd.va;
3681150d58c7SVasundhara Volam 	desc_count = le32_to_cpu(resp->desc_count);
3682150d58c7SVasundhara Volam 
3683150d58c7SVasundhara Volam 	pcie = be_get_pcie_desc(adapter->pdev->devfn, resp->func_param,
3684150d58c7SVasundhara Volam 				desc_count);
3685150d58c7SVasundhara Volam 	if (pcie)
368692bf14abSSathya Perla 		res->max_vfs = le16_to_cpu(pcie->num_vfs);
3687150d58c7SVasundhara Volam 
3688f93f160bSVasundhara Volam 	port = be_get_port_desc(resp->func_param, desc_count);
3689f93f160bSVasundhara Volam 	if (port)
3690f93f160bSVasundhara Volam 		adapter->mc_type = port->mc_type;
3691f93f160bSVasundhara Volam 
369210cccf60SVasundhara Volam 	nic = be_get_func_nic_desc(resp->func_param, desc_count);
369392bf14abSSathya Perla 	if (nic)
369492bf14abSSathya Perla 		be_copy_nic_desc(res, nic);
369592bf14abSSathya Perla 
369610cccf60SVasundhara Volam 	vf_res = be_get_vft_desc(resp->func_param, desc_count);
369710cccf60SVasundhara Volam 	if (vf_res)
369810cccf60SVasundhara Volam 		res->vf_if_cap_flags = vf_res->cap_flags;
3699abb93951SPadmanabh Ratnakar err:
3700a05f99dbSVasundhara Volam 	if (cmd.va)
3701150d58c7SVasundhara Volam 		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
3702abb93951SPadmanabh Ratnakar 	return status;
3703abb93951SPadmanabh Ratnakar }
3704abb93951SPadmanabh Ratnakar 
3705bec84e6bSVasundhara Volam /* Will use MBOX only if MCCQ has not been created */
3706bec84e6bSVasundhara Volam static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
3707bec84e6bSVasundhara Volam 				     int size, int count, u8 version, u8 domain)
3708d5c18473SPadmanabh Ratnakar {
3709d5c18473SPadmanabh Ratnakar 	struct be_cmd_req_set_profile_config *req;
3710bec84e6bSVasundhara Volam 	struct be_mcc_wrb wrb = {0};
3711bec84e6bSVasundhara Volam 	struct be_dma_mem cmd;
3712d5c18473SPadmanabh Ratnakar 	int status;
3713d5c18473SPadmanabh Ratnakar 
3714bec84e6bSVasundhara Volam 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3715bec84e6bSVasundhara Volam 	cmd.size = sizeof(struct be_cmd_req_set_profile_config);
3716bec84e6bSVasundhara Volam 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
3717bec84e6bSVasundhara Volam 	if (!cmd.va)
3718bec84e6bSVasundhara Volam 		return -ENOMEM;
3719d5c18473SPadmanabh Ratnakar 
3720bec84e6bSVasundhara Volam 	req = cmd.va;
3721d5c18473SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3722bec84e6bSVasundhara Volam 			       OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size,
3723bec84e6bSVasundhara Volam 			       &wrb, &cmd);
3724a401801cSSathya Perla 	req->hdr.version = version;
3725d5c18473SPadmanabh Ratnakar 	req->hdr.domain = domain;
3726bec84e6bSVasundhara Volam 	req->desc_count = cpu_to_le32(count);
3727a401801cSSathya Perla 	memcpy(req->desc, desc, size);
3728d5c18473SPadmanabh Ratnakar 
3729bec84e6bSVasundhara Volam 	status = be_cmd_notify_wait(adapter, &wrb);
3730bec84e6bSVasundhara Volam 
3731bec84e6bSVasundhara Volam 	if (cmd.va)
3732bec84e6bSVasundhara Volam 		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
3733d5c18473SPadmanabh Ratnakar 	return status;
3734d5c18473SPadmanabh Ratnakar }
3735d5c18473SPadmanabh Ratnakar 
3736a401801cSSathya Perla /* Mark all fields invalid */
3737bec84e6bSVasundhara Volam static void be_reset_nic_desc(struct be_nic_res_desc *nic)
3738a401801cSSathya Perla {
3739a401801cSSathya Perla 	memset(nic, 0, sizeof(*nic));
3740a401801cSSathya Perla 	nic->unicast_mac_count = 0xFFFF;
3741a401801cSSathya Perla 	nic->mcc_count = 0xFFFF;
3742a401801cSSathya Perla 	nic->vlan_count = 0xFFFF;
3743a401801cSSathya Perla 	nic->mcast_mac_count = 0xFFFF;
3744a401801cSSathya Perla 	nic->txq_count = 0xFFFF;
3745a401801cSSathya Perla 	nic->rq_count = 0xFFFF;
3746a401801cSSathya Perla 	nic->rssq_count = 0xFFFF;
3747a401801cSSathya Perla 	nic->lro_count = 0xFFFF;
3748a401801cSSathya Perla 	nic->cq_count = 0xFFFF;
3749a401801cSSathya Perla 	nic->toe_conn_count = 0xFFFF;
3750a401801cSSathya Perla 	nic->eq_count = 0xFFFF;
37510f77ba73SRavikumar Nelavelli 	nic->iface_count = 0xFFFF;
3752a401801cSSathya Perla 	nic->link_param = 0xFF;
37530f77ba73SRavikumar Nelavelli 	nic->channel_id_param = cpu_to_le16(0xF000);
3754a401801cSSathya Perla 	nic->acpi_params = 0xFF;
3755a401801cSSathya Perla 	nic->wol_param = 0x0F;
37560f77ba73SRavikumar Nelavelli 	nic->tunnel_iface_count = 0xFFFF;
37570f77ba73SRavikumar Nelavelli 	nic->direct_tenant_iface_count = 0xFFFF;
3758bec84e6bSVasundhara Volam 	nic->bw_min = 0xFFFFFFFF;
3759a401801cSSathya Perla 	nic->bw_max = 0xFFFFFFFF;
3760a401801cSSathya Perla }
3761a401801cSSathya Perla 
3762bec84e6bSVasundhara Volam /* Mark all fields invalid */
3763bec84e6bSVasundhara Volam static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie)
3764bec84e6bSVasundhara Volam {
3765bec84e6bSVasundhara Volam 	memset(pcie, 0, sizeof(*pcie));
3766bec84e6bSVasundhara Volam 	pcie->sriov_state = 0xFF;
3767bec84e6bSVasundhara Volam 	pcie->pf_state = 0xFF;
3768bec84e6bSVasundhara Volam 	pcie->pf_type = 0xFF;
3769bec84e6bSVasundhara Volam 	pcie->num_vfs = 0xFFFF;
3770bec84e6bSVasundhara Volam }
3771bec84e6bSVasundhara Volam 
37720f77ba73SRavikumar Nelavelli int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
37730f77ba73SRavikumar Nelavelli 		      u8 domain)
3774a401801cSSathya Perla {
3775a401801cSSathya Perla 	struct be_nic_res_desc nic_desc;
37760f77ba73SRavikumar Nelavelli 	u32 bw_percent;
37770f77ba73SRavikumar Nelavelli 	u16 version = 0;
37780f77ba73SRavikumar Nelavelli 
37790f77ba73SRavikumar Nelavelli 	if (BE3_chip(adapter))
37800f77ba73SRavikumar Nelavelli 		return be_cmd_set_qos(adapter, max_rate / 10, domain);
3781a401801cSSathya Perla 
3782a401801cSSathya Perla 	be_reset_nic_desc(&nic_desc);
37830f77ba73SRavikumar Nelavelli 	nic_desc.pf_num = adapter->pf_number;
37840f77ba73SRavikumar Nelavelli 	nic_desc.vf_num = domain;
378558bdeaa6SKalesh AP 	nic_desc.bw_min = 0;
37860f77ba73SRavikumar Nelavelli 	if (lancer_chip(adapter)) {
3787a401801cSSathya Perla 		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
3788a401801cSSathya Perla 		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
3789a401801cSSathya Perla 		nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
3790a401801cSSathya Perla 					(1 << NOSV_SHIFT);
37910f77ba73SRavikumar Nelavelli 		nic_desc.bw_max = cpu_to_le32(max_rate / 10);
37920f77ba73SRavikumar Nelavelli 	} else {
37930f77ba73SRavikumar Nelavelli 		version = 1;
37940f77ba73SRavikumar Nelavelli 		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
37950f77ba73SRavikumar Nelavelli 		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
37960f77ba73SRavikumar Nelavelli 		nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
37970f77ba73SRavikumar Nelavelli 		bw_percent = max_rate ? (max_rate * 100) / link_speed : 100;
37980f77ba73SRavikumar Nelavelli 		nic_desc.bw_max = cpu_to_le32(bw_percent);
37990f77ba73SRavikumar Nelavelli 	}
3800a401801cSSathya Perla 
3801a401801cSSathya Perla 	return be_cmd_set_profile_config(adapter, &nic_desc,
38020f77ba73SRavikumar Nelavelli 					 nic_desc.hdr.desc_len,
3803bec84e6bSVasundhara Volam 					 1, version, domain);
3804bec84e6bSVasundhara Volam }
3805bec84e6bSVasundhara Volam 
3806bec84e6bSVasundhara Volam int be_cmd_set_sriov_config(struct be_adapter *adapter,
3807bec84e6bSVasundhara Volam 			    struct be_resources res, u16 num_vfs)
3808bec84e6bSVasundhara Volam {
3809bec84e6bSVasundhara Volam 	struct {
3810bec84e6bSVasundhara Volam 		struct be_pcie_res_desc pcie;
3811bec84e6bSVasundhara Volam 		struct be_nic_res_desc nic_vft;
3812bec84e6bSVasundhara Volam 	} __packed desc;
3813bec84e6bSVasundhara Volam 	u16 vf_q_count;
3814bec84e6bSVasundhara Volam 
3815bec84e6bSVasundhara Volam 	if (BEx_chip(adapter) || lancer_chip(adapter))
3816bec84e6bSVasundhara Volam 		return 0;
3817bec84e6bSVasundhara Volam 
3818bec84e6bSVasundhara Volam 	/* PF PCIE descriptor */
3819bec84e6bSVasundhara Volam 	be_reset_pcie_desc(&desc.pcie);
3820bec84e6bSVasundhara Volam 	desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1;
3821bec84e6bSVasundhara Volam 	desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
3822bec84e6bSVasundhara Volam 	desc.pcie.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
3823bec84e6bSVasundhara Volam 	desc.pcie.pf_num = adapter->pdev->devfn;
3824bec84e6bSVasundhara Volam 	desc.pcie.sriov_state = num_vfs ? 1 : 0;
3825bec84e6bSVasundhara Volam 	desc.pcie.num_vfs = cpu_to_le16(num_vfs);
3826bec84e6bSVasundhara Volam 
3827bec84e6bSVasundhara Volam 	/* VF NIC Template descriptor */
3828bec84e6bSVasundhara Volam 	be_reset_nic_desc(&desc.nic_vft);
3829bec84e6bSVasundhara Volam 	desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
3830bec84e6bSVasundhara Volam 	desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
3831bec84e6bSVasundhara Volam 	desc.nic_vft.flags = (1 << VFT_SHIFT) | (1 << IMM_SHIFT) |
3832bec84e6bSVasundhara Volam 				(1 << NOSV_SHIFT);
3833bec84e6bSVasundhara Volam 	desc.nic_vft.pf_num = adapter->pdev->devfn;
3834bec84e6bSVasundhara Volam 	desc.nic_vft.vf_num = 0;
3835bec84e6bSVasundhara Volam 
3836bec84e6bSVasundhara Volam 	if (num_vfs && res.vf_if_cap_flags & BE_IF_FLAGS_RSS) {
3837bec84e6bSVasundhara Volam 		/* If number of VFs requested is 8 less than max supported,
3838bec84e6bSVasundhara Volam 		 * assign 8 queue pairs to the PF and divide the remaining
3839bec84e6bSVasundhara Volam 		 * resources evenly among the VFs
3840bec84e6bSVasundhara Volam 		 */
3841bec84e6bSVasundhara Volam 		if (num_vfs < (be_max_vfs(adapter) - 8))
3842bec84e6bSVasundhara Volam 			vf_q_count = (res.max_rss_qs - 8) / num_vfs;
3843bec84e6bSVasundhara Volam 		else
3844bec84e6bSVasundhara Volam 			vf_q_count = res.max_rss_qs / num_vfs;
3845bec84e6bSVasundhara Volam 
3846bec84e6bSVasundhara Volam 		desc.nic_vft.rq_count = cpu_to_le16(vf_q_count);
3847bec84e6bSVasundhara Volam 		desc.nic_vft.txq_count = cpu_to_le16(vf_q_count);
3848bec84e6bSVasundhara Volam 		desc.nic_vft.rssq_count = cpu_to_le16(vf_q_count - 1);
3849bec84e6bSVasundhara Volam 		desc.nic_vft.cq_count = cpu_to_le16(3 * vf_q_count);
3850bec84e6bSVasundhara Volam 	} else {
3851bec84e6bSVasundhara Volam 		desc.nic_vft.txq_count = cpu_to_le16(1);
3852bec84e6bSVasundhara Volam 		desc.nic_vft.rq_count = cpu_to_le16(1);
3853bec84e6bSVasundhara Volam 		desc.nic_vft.rssq_count = cpu_to_le16(0);
3854bec84e6bSVasundhara Volam 		/* One CQ for each TX, RX and MCCQ */
3855bec84e6bSVasundhara Volam 		desc.nic_vft.cq_count = cpu_to_le16(3);
3856bec84e6bSVasundhara Volam 	}
3857bec84e6bSVasundhara Volam 
3858bec84e6bSVasundhara Volam 	return be_cmd_set_profile_config(adapter, &desc,
3859bec84e6bSVasundhara Volam 					 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
3860a401801cSSathya Perla }
3861a401801cSSathya Perla 
3862a401801cSSathya Perla int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
3863a401801cSSathya Perla {
3864a401801cSSathya Perla 	struct be_mcc_wrb *wrb;
3865a401801cSSathya Perla 	struct be_cmd_req_manage_iface_filters *req;
3866a401801cSSathya Perla 	int status;
3867a401801cSSathya Perla 
3868a401801cSSathya Perla 	if (iface == 0xFFFFFFFF)
3869a401801cSSathya Perla 		return -1;
3870a401801cSSathya Perla 
3871a401801cSSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
3872a401801cSSathya Perla 
3873a401801cSSathya Perla 	wrb = wrb_from_mccq(adapter);
3874a401801cSSathya Perla 	if (!wrb) {
3875a401801cSSathya Perla 		status = -EBUSY;
3876a401801cSSathya Perla 		goto err;
3877a401801cSSathya Perla 	}
3878a401801cSSathya Perla 	req = embedded_payload(wrb);
3879a401801cSSathya Perla 
3880a401801cSSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3881a401801cSSathya Perla 			       OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req),
3882a401801cSSathya Perla 			       wrb, NULL);
3883a401801cSSathya Perla 	req->op = op;
3884a401801cSSathya Perla 	req->target_iface_id = cpu_to_le32(iface);
3885a401801cSSathya Perla 
3886a401801cSSathya Perla 	status = be_mcc_notify_wait(adapter);
3887a401801cSSathya Perla err:
3888a401801cSSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
3889a401801cSSathya Perla 	return status;
3890a401801cSSathya Perla }
3891a401801cSSathya Perla 
3892a401801cSSathya Perla int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port)
3893a401801cSSathya Perla {
3894a401801cSSathya Perla 	struct be_port_res_desc port_desc;
3895a401801cSSathya Perla 
3896a401801cSSathya Perla 	memset(&port_desc, 0, sizeof(port_desc));
3897a401801cSSathya Perla 	port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1;
3898a401801cSSathya Perla 	port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
3899a401801cSSathya Perla 	port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
3900a401801cSSathya Perla 	port_desc.link_num = adapter->hba_port_num;
3901a401801cSSathya Perla 	if (port) {
3902a401801cSSathya Perla 		port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) |
3903a401801cSSathya Perla 					(1 << RCVID_SHIFT);
3904a401801cSSathya Perla 		port_desc.nv_port = swab16(port);
3905a401801cSSathya Perla 	} else {
3906a401801cSSathya Perla 		port_desc.nv_flags = NV_TYPE_DISABLED;
3907a401801cSSathya Perla 		port_desc.nv_port = 0;
3908a401801cSSathya Perla 	}
3909a401801cSSathya Perla 
3910a401801cSSathya Perla 	return be_cmd_set_profile_config(adapter, &port_desc,
3911bec84e6bSVasundhara Volam 					 RESOURCE_DESC_SIZE_V1, 1, 1, 0);
3912a401801cSSathya Perla }
3913a401801cSSathya Perla 
39144c876616SSathya Perla int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
39154c876616SSathya Perla 		     int vf_num)
39164c876616SSathya Perla {
39174c876616SSathya Perla 	struct be_mcc_wrb *wrb;
39184c876616SSathya Perla 	struct be_cmd_req_get_iface_list *req;
39194c876616SSathya Perla 	struct be_cmd_resp_get_iface_list *resp;
39204c876616SSathya Perla 	int status;
39214c876616SSathya Perla 
39224c876616SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
39234c876616SSathya Perla 
39244c876616SSathya Perla 	wrb = wrb_from_mccq(adapter);
39254c876616SSathya Perla 	if (!wrb) {
39264c876616SSathya Perla 		status = -EBUSY;
39274c876616SSathya Perla 		goto err;
39284c876616SSathya Perla 	}
39294c876616SSathya Perla 	req = embedded_payload(wrb);
39304c876616SSathya Perla 
39314c876616SSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
39324c876616SSathya Perla 			       OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp),
39334c876616SSathya Perla 			       wrb, NULL);
39344c876616SSathya Perla 	req->hdr.domain = vf_num + 1;
39354c876616SSathya Perla 
39364c876616SSathya Perla 	status = be_mcc_notify_wait(adapter);
39374c876616SSathya Perla 	if (!status) {
39384c876616SSathya Perla 		resp = (struct be_cmd_resp_get_iface_list *)req;
39394c876616SSathya Perla 		vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id);
39404c876616SSathya Perla 	}
39414c876616SSathya Perla 
39424c876616SSathya Perla err:
39434c876616SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
39444c876616SSathya Perla 	return status;
39454c876616SSathya Perla }
39464c876616SSathya Perla 
39475c510811SSomnath Kotur static int lancer_wait_idle(struct be_adapter *adapter)
39485c510811SSomnath Kotur {
39495c510811SSomnath Kotur #define SLIPORT_IDLE_TIMEOUT 30
39505c510811SSomnath Kotur 	u32 reg_val;
39515c510811SSomnath Kotur 	int status = 0, i;
39525c510811SSomnath Kotur 
39535c510811SSomnath Kotur 	for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
39545c510811SSomnath Kotur 		reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
39555c510811SSomnath Kotur 		if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
39565c510811SSomnath Kotur 			break;
39575c510811SSomnath Kotur 
39585c510811SSomnath Kotur 		ssleep(1);
39595c510811SSomnath Kotur 	}
39605c510811SSomnath Kotur 
39615c510811SSomnath Kotur 	if (i == SLIPORT_IDLE_TIMEOUT)
39625c510811SSomnath Kotur 		status = -1;
39635c510811SSomnath Kotur 
39645c510811SSomnath Kotur 	return status;
39655c510811SSomnath Kotur }
39665c510811SSomnath Kotur 
39675c510811SSomnath Kotur int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
39685c510811SSomnath Kotur {
39695c510811SSomnath Kotur 	int status = 0;
39705c510811SSomnath Kotur 
39715c510811SSomnath Kotur 	status = lancer_wait_idle(adapter);
39725c510811SSomnath Kotur 	if (status)
39735c510811SSomnath Kotur 		return status;
39745c510811SSomnath Kotur 
39755c510811SSomnath Kotur 	iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
39765c510811SSomnath Kotur 
39775c510811SSomnath Kotur 	return status;
39785c510811SSomnath Kotur }
39795c510811SSomnath Kotur 
39805c510811SSomnath Kotur /* Routine to check whether dump image is present or not */
39815c510811SSomnath Kotur bool dump_present(struct be_adapter *adapter)
39825c510811SSomnath Kotur {
39835c510811SSomnath Kotur 	u32 sliport_status = 0;
39845c510811SSomnath Kotur 
39855c510811SSomnath Kotur 	sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
39865c510811SSomnath Kotur 	return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
39875c510811SSomnath Kotur }
39885c510811SSomnath Kotur 
39895c510811SSomnath Kotur int lancer_initiate_dump(struct be_adapter *adapter)
39905c510811SSomnath Kotur {
3991f0613380SKalesh AP 	struct device *dev = &adapter->pdev->dev;
39925c510811SSomnath Kotur 	int status;
39935c510811SSomnath Kotur 
3994f0613380SKalesh AP 	if (dump_present(adapter)) {
3995f0613380SKalesh AP 		dev_info(dev, "Previous dump not cleared, not forcing dump\n");
3996f0613380SKalesh AP 		return -EEXIST;
3997f0613380SKalesh AP 	}
3998f0613380SKalesh AP 
39995c510811SSomnath Kotur 	/* give firmware reset and diagnostic dump */
40005c510811SSomnath Kotur 	status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
40015c510811SSomnath Kotur 				     PHYSDEV_CONTROL_DD_MASK);
40025c510811SSomnath Kotur 	if (status < 0) {
4003f0613380SKalesh AP 		dev_err(dev, "FW reset failed\n");
40045c510811SSomnath Kotur 		return status;
40055c510811SSomnath Kotur 	}
40065c510811SSomnath Kotur 
40075c510811SSomnath Kotur 	status = lancer_wait_idle(adapter);
40085c510811SSomnath Kotur 	if (status)
40095c510811SSomnath Kotur 		return status;
40105c510811SSomnath Kotur 
40115c510811SSomnath Kotur 	if (!dump_present(adapter)) {
4012f0613380SKalesh AP 		dev_err(dev, "FW dump not generated\n");
4013f0613380SKalesh AP 		return -EIO;
40145c510811SSomnath Kotur 	}
40155c510811SSomnath Kotur 
40165c510811SSomnath Kotur 	return 0;
40175c510811SSomnath Kotur }
40185c510811SSomnath Kotur 
4019f0613380SKalesh AP int lancer_delete_dump(struct be_adapter *adapter)
4020f0613380SKalesh AP {
4021f0613380SKalesh AP 	int status;
4022f0613380SKalesh AP 
4023f0613380SKalesh AP 	status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE);
4024f0613380SKalesh AP 	return be_cmd_status(status);
4025f0613380SKalesh AP }
4026f0613380SKalesh AP 
4027dcf7ebbaSPadmanabh Ratnakar /* Uses sync mcc */
4028dcf7ebbaSPadmanabh Ratnakar int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
4029dcf7ebbaSPadmanabh Ratnakar {
4030dcf7ebbaSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
4031dcf7ebbaSPadmanabh Ratnakar 	struct be_cmd_enable_disable_vf *req;
4032dcf7ebbaSPadmanabh Ratnakar 	int status;
4033dcf7ebbaSPadmanabh Ratnakar 
40340599863dSVasundhara Volam 	if (BEx_chip(adapter))
4035dcf7ebbaSPadmanabh Ratnakar 		return 0;
4036dcf7ebbaSPadmanabh Ratnakar 
4037dcf7ebbaSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
4038dcf7ebbaSPadmanabh Ratnakar 
4039dcf7ebbaSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
4040dcf7ebbaSPadmanabh Ratnakar 	if (!wrb) {
4041dcf7ebbaSPadmanabh Ratnakar 		status = -EBUSY;
4042dcf7ebbaSPadmanabh Ratnakar 		goto err;
4043dcf7ebbaSPadmanabh Ratnakar 	}
4044dcf7ebbaSPadmanabh Ratnakar 
4045dcf7ebbaSPadmanabh Ratnakar 	req = embedded_payload(wrb);
4046dcf7ebbaSPadmanabh Ratnakar 
4047dcf7ebbaSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4048dcf7ebbaSPadmanabh Ratnakar 			       OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
4049dcf7ebbaSPadmanabh Ratnakar 			       wrb, NULL);
4050dcf7ebbaSPadmanabh Ratnakar 
4051dcf7ebbaSPadmanabh Ratnakar 	req->hdr.domain = domain;
4052dcf7ebbaSPadmanabh Ratnakar 	req->enable = 1;
4053dcf7ebbaSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
4054dcf7ebbaSPadmanabh Ratnakar err:
4055dcf7ebbaSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
4056dcf7ebbaSPadmanabh Ratnakar 	return status;
4057dcf7ebbaSPadmanabh Ratnakar }
4058dcf7ebbaSPadmanabh Ratnakar 
405968c45a2dSSomnath Kotur int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable)
406068c45a2dSSomnath Kotur {
406168c45a2dSSomnath Kotur 	struct be_mcc_wrb *wrb;
406268c45a2dSSomnath Kotur 	struct be_cmd_req_intr_set *req;
406368c45a2dSSomnath Kotur 	int status;
406468c45a2dSSomnath Kotur 
406568c45a2dSSomnath Kotur 	if (mutex_lock_interruptible(&adapter->mbox_lock))
406668c45a2dSSomnath Kotur 		return -1;
406768c45a2dSSomnath Kotur 
406868c45a2dSSomnath Kotur 	wrb = wrb_from_mbox(adapter);
406968c45a2dSSomnath Kotur 
407068c45a2dSSomnath Kotur 	req = embedded_payload(wrb);
407168c45a2dSSomnath Kotur 
407268c45a2dSSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
407368c45a2dSSomnath Kotur 			       OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req),
407468c45a2dSSomnath Kotur 			       wrb, NULL);
407568c45a2dSSomnath Kotur 
407668c45a2dSSomnath Kotur 	req->intr_enabled = intr_enable;
407768c45a2dSSomnath Kotur 
407868c45a2dSSomnath Kotur 	status = be_mbox_notify_wait(adapter);
407968c45a2dSSomnath Kotur 
408068c45a2dSSomnath Kotur 	mutex_unlock(&adapter->mbox_lock);
408168c45a2dSSomnath Kotur 	return status;
408268c45a2dSSomnath Kotur }
408368c45a2dSSomnath Kotur 
4084542963b7SVasundhara Volam /* Uses MBOX */
4085542963b7SVasundhara Volam int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id)
4086542963b7SVasundhara Volam {
4087542963b7SVasundhara Volam 	struct be_cmd_req_get_active_profile *req;
4088542963b7SVasundhara Volam 	struct be_mcc_wrb *wrb;
4089542963b7SVasundhara Volam 	int status;
4090542963b7SVasundhara Volam 
4091542963b7SVasundhara Volam 	if (mutex_lock_interruptible(&adapter->mbox_lock))
4092542963b7SVasundhara Volam 		return -1;
4093542963b7SVasundhara Volam 
4094542963b7SVasundhara Volam 	wrb = wrb_from_mbox(adapter);
4095542963b7SVasundhara Volam 	if (!wrb) {
4096542963b7SVasundhara Volam 		status = -EBUSY;
4097542963b7SVasundhara Volam 		goto err;
4098542963b7SVasundhara Volam 	}
4099542963b7SVasundhara Volam 
4100542963b7SVasundhara Volam 	req = embedded_payload(wrb);
4101542963b7SVasundhara Volam 
4102542963b7SVasundhara Volam 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4103542963b7SVasundhara Volam 			       OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req),
4104542963b7SVasundhara Volam 			       wrb, NULL);
4105542963b7SVasundhara Volam 
4106542963b7SVasundhara Volam 	status = be_mbox_notify_wait(adapter);
4107542963b7SVasundhara Volam 	if (!status) {
4108542963b7SVasundhara Volam 		struct be_cmd_resp_get_active_profile *resp =
4109542963b7SVasundhara Volam 							embedded_payload(wrb);
411003d28ffeSKalesh AP 
4111542963b7SVasundhara Volam 		*profile_id = le16_to_cpu(resp->active_profile_id);
4112542963b7SVasundhara Volam 	}
4113542963b7SVasundhara Volam 
4114542963b7SVasundhara Volam err:
4115542963b7SVasundhara Volam 	mutex_unlock(&adapter->mbox_lock);
4116542963b7SVasundhara Volam 	return status;
4117542963b7SVasundhara Volam }
4118542963b7SVasundhara Volam 
4119bdce2ad7SSuresh Reddy int be_cmd_set_logical_link_config(struct be_adapter *adapter,
4120bdce2ad7SSuresh Reddy 				   int link_state, u8 domain)
4121bdce2ad7SSuresh Reddy {
4122bdce2ad7SSuresh Reddy 	struct be_mcc_wrb *wrb;
4123bdce2ad7SSuresh Reddy 	struct be_cmd_req_set_ll_link *req;
4124bdce2ad7SSuresh Reddy 	int status;
4125bdce2ad7SSuresh Reddy 
4126bdce2ad7SSuresh Reddy 	if (BEx_chip(adapter) || lancer_chip(adapter))
412718fd6025SKalesh AP 		return -EOPNOTSUPP;
4128bdce2ad7SSuresh Reddy 
4129bdce2ad7SSuresh Reddy 	spin_lock_bh(&adapter->mcc_lock);
4130bdce2ad7SSuresh Reddy 
4131bdce2ad7SSuresh Reddy 	wrb = wrb_from_mccq(adapter);
4132bdce2ad7SSuresh Reddy 	if (!wrb) {
4133bdce2ad7SSuresh Reddy 		status = -EBUSY;
4134bdce2ad7SSuresh Reddy 		goto err;
4135bdce2ad7SSuresh Reddy 	}
4136bdce2ad7SSuresh Reddy 
4137bdce2ad7SSuresh Reddy 	req = embedded_payload(wrb);
4138bdce2ad7SSuresh Reddy 
4139bdce2ad7SSuresh Reddy 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4140bdce2ad7SSuresh Reddy 			       OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG,
4141bdce2ad7SSuresh Reddy 			       sizeof(*req), wrb, NULL);
4142bdce2ad7SSuresh Reddy 
4143bdce2ad7SSuresh Reddy 	req->hdr.version = 1;
4144bdce2ad7SSuresh Reddy 	req->hdr.domain = domain;
4145bdce2ad7SSuresh Reddy 
4146bdce2ad7SSuresh Reddy 	if (link_state == IFLA_VF_LINK_STATE_ENABLE)
4147bdce2ad7SSuresh Reddy 		req->link_config |= 1;
4148bdce2ad7SSuresh Reddy 
4149bdce2ad7SSuresh Reddy 	if (link_state == IFLA_VF_LINK_STATE_AUTO)
4150bdce2ad7SSuresh Reddy 		req->link_config |= 1 << PLINK_TRACK_SHIFT;
4151bdce2ad7SSuresh Reddy 
4152bdce2ad7SSuresh Reddy 	status = be_mcc_notify_wait(adapter);
4153bdce2ad7SSuresh Reddy err:
4154bdce2ad7SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
4155bdce2ad7SSuresh Reddy 	return status;
4156bdce2ad7SSuresh Reddy }
4157bdce2ad7SSuresh Reddy 
41586a4ab669SParav Pandit int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
41596a4ab669SParav Pandit 		    int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
41606a4ab669SParav Pandit {
41616a4ab669SParav Pandit 	struct be_adapter *adapter = netdev_priv(netdev_handle);
41626a4ab669SParav Pandit 	struct be_mcc_wrb *wrb;
41636a4ab669SParav Pandit 	struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload;
41646a4ab669SParav Pandit 	struct be_cmd_req_hdr *req;
41656a4ab669SParav Pandit 	struct be_cmd_resp_hdr *resp;
41666a4ab669SParav Pandit 	int status;
41676a4ab669SParav Pandit 
41686a4ab669SParav Pandit 	spin_lock_bh(&adapter->mcc_lock);
41696a4ab669SParav Pandit 
41706a4ab669SParav Pandit 	wrb = wrb_from_mccq(adapter);
41716a4ab669SParav Pandit 	if (!wrb) {
41726a4ab669SParav Pandit 		status = -EBUSY;
41736a4ab669SParav Pandit 		goto err;
41746a4ab669SParav Pandit 	}
41756a4ab669SParav Pandit 	req = embedded_payload(wrb);
41766a4ab669SParav Pandit 	resp = embedded_payload(wrb);
41776a4ab669SParav Pandit 
41786a4ab669SParav Pandit 	be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
41796a4ab669SParav Pandit 			       hdr->opcode, wrb_payload_size, wrb, NULL);
41806a4ab669SParav Pandit 	memcpy(req, wrb_payload, wrb_payload_size);
41816a4ab669SParav Pandit 	be_dws_cpu_to_le(req, wrb_payload_size);
41826a4ab669SParav Pandit 
41836a4ab669SParav Pandit 	status = be_mcc_notify_wait(adapter);
41846a4ab669SParav Pandit 	if (cmd_status)
41856a4ab669SParav Pandit 		*cmd_status = (status & 0xffff);
41866a4ab669SParav Pandit 	if (ext_status)
41876a4ab669SParav Pandit 		*ext_status = 0;
41886a4ab669SParav Pandit 	memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
41896a4ab669SParav Pandit 	be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
41906a4ab669SParav Pandit err:
41916a4ab669SParav Pandit 	spin_unlock_bh(&adapter->mcc_lock);
41926a4ab669SParav Pandit 	return status;
41936a4ab669SParav Pandit }
41946a4ab669SParav Pandit EXPORT_SYMBOL(be_roce_mcc_cmd);
4195