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 ||
14377be8c1cSKalesh AP 	    addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS ||
1444c60005fSKalesh AP 	    (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
1454c60005fSKalesh AP 	    (base_status == MCC_STATUS_ILLEGAL_FIELD ||
1464c60005fSKalesh AP 	     addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH)))
1474c60005fSKalesh AP 		return true;
1484c60005fSKalesh AP 	else
1494c60005fSKalesh AP 		return false;
1504c60005fSKalesh AP }
1514c60005fSKalesh AP 
152559b633fSSathya Perla /* Place holder for all the async MCC cmds wherein the caller is not in a busy
153559b633fSSathya Perla  * loop (has not issued be_mcc_notify_wait())
154559b633fSSathya Perla  */
155559b633fSSathya Perla static void be_async_cmd_process(struct be_adapter *adapter,
156559b633fSSathya Perla 				 struct be_mcc_compl *compl,
157559b633fSSathya Perla 				 struct be_cmd_resp_hdr *resp_hdr)
158559b633fSSathya Perla {
159559b633fSSathya Perla 	enum mcc_base_status base_status = base_status(compl->status);
160559b633fSSathya Perla 	u8 opcode = 0, subsystem = 0;
161559b633fSSathya Perla 
162559b633fSSathya Perla 	if (resp_hdr) {
163559b633fSSathya Perla 		opcode = resp_hdr->opcode;
164559b633fSSathya Perla 		subsystem = resp_hdr->subsystem;
165559b633fSSathya Perla 	}
166559b633fSSathya Perla 
167559b633fSSathya Perla 	if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
168559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
169559b633fSSathya Perla 		complete(&adapter->et_cmd_compl);
170559b633fSSathya Perla 		return;
171559b633fSSathya Perla 	}
172559b633fSSathya Perla 
173559b633fSSathya Perla 	if ((opcode == OPCODE_COMMON_WRITE_FLASHROM ||
174559b633fSSathya Perla 	     opcode == OPCODE_COMMON_WRITE_OBJECT) &&
175559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_COMMON) {
176559b633fSSathya Perla 		adapter->flash_status = compl->status;
177559b633fSSathya Perla 		complete(&adapter->et_cmd_compl);
178559b633fSSathya Perla 		return;
179559b633fSSathya Perla 	}
180559b633fSSathya Perla 
181559b633fSSathya Perla 	if ((opcode == OPCODE_ETH_GET_STATISTICS ||
182559b633fSSathya Perla 	     opcode == OPCODE_ETH_GET_PPORT_STATS) &&
183559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_ETH &&
184559b633fSSathya Perla 	    base_status == MCC_STATUS_SUCCESS) {
185559b633fSSathya Perla 		be_parse_stats(adapter);
186559b633fSSathya Perla 		adapter->stats_cmd_sent = false;
187559b633fSSathya Perla 		return;
188559b633fSSathya Perla 	}
189559b633fSSathya Perla 
190559b633fSSathya Perla 	if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
191559b633fSSathya Perla 	    subsystem == CMD_SUBSYSTEM_COMMON) {
192559b633fSSathya Perla 		if (base_status == MCC_STATUS_SUCCESS) {
193559b633fSSathya Perla 			struct be_cmd_resp_get_cntl_addnl_attribs *resp =
194559b633fSSathya Perla 							(void *)resp_hdr;
195559b633fSSathya Perla 			adapter->drv_stats.be_on_die_temperature =
196559b633fSSathya Perla 						resp->on_die_temperature;
197559b633fSSathya Perla 		} else {
198559b633fSSathya Perla 			adapter->be_get_temp_freq = 0;
199559b633fSSathya Perla 		}
200559b633fSSathya Perla 		return;
201559b633fSSathya Perla 	}
202559b633fSSathya Perla }
203559b633fSSathya Perla 
2049aebddd1SJeff Kirsher static int be_mcc_compl_process(struct be_adapter *adapter,
2059aebddd1SJeff Kirsher 				struct be_mcc_compl *compl)
2069aebddd1SJeff Kirsher {
2074c60005fSKalesh AP 	enum mcc_base_status base_status;
2084c60005fSKalesh AP 	enum mcc_addl_status addl_status;
209652bf646SPadmanabh Ratnakar 	struct be_cmd_resp_hdr *resp_hdr;
210652bf646SPadmanabh Ratnakar 	u8 opcode = 0, subsystem = 0;
2119aebddd1SJeff Kirsher 
2129aebddd1SJeff Kirsher 	/* Just swap the status to host endian; mcc tag is opaquely copied
2139aebddd1SJeff Kirsher 	 * from mcc_wrb */
2149aebddd1SJeff Kirsher 	be_dws_le_to_cpu(compl, 4);
2159aebddd1SJeff Kirsher 
2164c60005fSKalesh AP 	base_status = base_status(compl->status);
2174c60005fSKalesh AP 	addl_status = addl_status(compl->status);
21896c9b2e4SVasundhara Volam 
219652bf646SPadmanabh Ratnakar 	resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
220652bf646SPadmanabh Ratnakar 	if (resp_hdr) {
221652bf646SPadmanabh Ratnakar 		opcode = resp_hdr->opcode;
222652bf646SPadmanabh Ratnakar 		subsystem = resp_hdr->subsystem;
223652bf646SPadmanabh Ratnakar 	}
224652bf646SPadmanabh Ratnakar 
225559b633fSSathya Perla 	be_async_cmd_process(adapter, compl, resp_hdr);
2265eeff635SSuresh Reddy 
227559b633fSSathya Perla 	if (base_status != MCC_STATUS_SUCCESS &&
228559b633fSSathya Perla 	    !be_skip_err_log(opcode, base_status, addl_status)) {
2294c60005fSKalesh AP 		if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
23097f1d8cdSVasundhara Volam 			dev_warn(&adapter->pdev->dev,
231522609f2SVasundhara Volam 				 "VF is not privileged to issue opcode %d-%d\n",
23297f1d8cdSVasundhara Volam 				 opcode, subsystem);
2339aebddd1SJeff Kirsher 		} else {
23497f1d8cdSVasundhara Volam 			dev_err(&adapter->pdev->dev,
23597f1d8cdSVasundhara Volam 				"opcode %d-%d failed:status %d-%d\n",
2364c60005fSKalesh AP 				opcode, subsystem, base_status, addl_status);
2379aebddd1SJeff Kirsher 		}
2389aebddd1SJeff Kirsher 	}
2394c60005fSKalesh AP 	return compl->status;
2409aebddd1SJeff Kirsher }
2419aebddd1SJeff Kirsher 
2429aebddd1SJeff Kirsher /* Link state evt is a string of bytes; no need for endian swapping */
2439aebddd1SJeff Kirsher static void be_async_link_state_process(struct be_adapter *adapter,
2443acf19d9SSathya Perla 					struct be_mcc_compl *compl)
2459aebddd1SJeff Kirsher {
2463acf19d9SSathya Perla 	struct be_async_event_link_state *evt =
2473acf19d9SSathya Perla 			(struct be_async_event_link_state *)compl;
2483acf19d9SSathya Perla 
249b236916aSAjit Khaparde 	/* When link status changes, link speed must be re-queried from FW */
25042f11cf2SAjit Khaparde 	adapter->phy.link_speed = -1;
251b236916aSAjit Khaparde 
252bdce2ad7SSuresh Reddy 	/* On BEx the FW does not send a separate link status
253bdce2ad7SSuresh Reddy 	 * notification for physical and logical link.
254bdce2ad7SSuresh Reddy 	 * On other chips just process the logical link
255bdce2ad7SSuresh Reddy 	 * status notification
256bdce2ad7SSuresh Reddy 	 */
257bdce2ad7SSuresh Reddy 	if (!BEx_chip(adapter) &&
2582e177a5cSPadmanabh Ratnakar 	    !(evt->port_link_status & LOGICAL_LINK_STATUS_MASK))
2592e177a5cSPadmanabh Ratnakar 		return;
2602e177a5cSPadmanabh Ratnakar 
261b236916aSAjit Khaparde 	/* For the initial link status do not rely on the ASYNC event as
262b236916aSAjit Khaparde 	 * it may not be received in some cases.
263b236916aSAjit Khaparde 	 */
264b236916aSAjit Khaparde 	if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
265bdce2ad7SSuresh Reddy 		be_link_status_update(adapter,
266bdce2ad7SSuresh Reddy 				      evt->port_link_status & LINK_STATUS_MASK);
2679aebddd1SJeff Kirsher }
2689aebddd1SJeff Kirsher 
26921252377SVasundhara Volam static void be_async_port_misconfig_event_process(struct be_adapter *adapter,
27021252377SVasundhara Volam 						  struct be_mcc_compl *compl)
27121252377SVasundhara Volam {
27221252377SVasundhara Volam 	struct be_async_event_misconfig_port *evt =
27321252377SVasundhara Volam 			(struct be_async_event_misconfig_port *)compl;
27421252377SVasundhara Volam 	u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1);
27521252377SVasundhara Volam 	struct device *dev = &adapter->pdev->dev;
27621252377SVasundhara Volam 	u8 port_misconfig_evt;
27721252377SVasundhara Volam 
27821252377SVasundhara Volam 	port_misconfig_evt =
27921252377SVasundhara Volam 		((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff);
28021252377SVasundhara Volam 
28121252377SVasundhara Volam 	/* Log an error message that would allow a user to determine
28221252377SVasundhara Volam 	 * whether the SFPs have an issue
28321252377SVasundhara Volam 	 */
28421252377SVasundhara Volam 	dev_info(dev, "Port %c: %s %s", adapter->port_name,
28521252377SVasundhara Volam 		 be_port_misconfig_evt_desc[port_misconfig_evt],
28621252377SVasundhara Volam 		 be_port_misconfig_remedy_desc[port_misconfig_evt]);
28721252377SVasundhara Volam 
28821252377SVasundhara Volam 	if (port_misconfig_evt == INCOMPATIBLE_SFP)
28921252377SVasundhara Volam 		adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP;
29021252377SVasundhara Volam }
29121252377SVasundhara Volam 
2929aebddd1SJeff Kirsher /* Grp5 CoS Priority evt */
2939aebddd1SJeff Kirsher static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
2943acf19d9SSathya Perla 					       struct be_mcc_compl *compl)
2959aebddd1SJeff Kirsher {
2963acf19d9SSathya Perla 	struct be_async_event_grp5_cos_priority *evt =
2973acf19d9SSathya Perla 			(struct be_async_event_grp5_cos_priority *)compl;
2983acf19d9SSathya Perla 
2999aebddd1SJeff Kirsher 	if (evt->valid) {
3009aebddd1SJeff Kirsher 		adapter->vlan_prio_bmap = evt->available_priority_bmap;
3019aebddd1SJeff Kirsher 		adapter->recommended_prio &= ~VLAN_PRIO_MASK;
3029aebddd1SJeff Kirsher 		adapter->recommended_prio =
3039aebddd1SJeff Kirsher 			evt->reco_default_priority << VLAN_PRIO_SHIFT;
3049aebddd1SJeff Kirsher 	}
3059aebddd1SJeff Kirsher }
3069aebddd1SJeff Kirsher 
307323ff71eSSathya Perla /* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */
3089aebddd1SJeff Kirsher static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
3093acf19d9SSathya Perla 					    struct be_mcc_compl *compl)
3109aebddd1SJeff Kirsher {
3113acf19d9SSathya Perla 	struct be_async_event_grp5_qos_link_speed *evt =
3123acf19d9SSathya Perla 			(struct be_async_event_grp5_qos_link_speed *)compl;
3133acf19d9SSathya Perla 
314323ff71eSSathya Perla 	if (adapter->phy.link_speed >= 0 &&
315323ff71eSSathya Perla 	    evt->physical_port == adapter->port_num)
316323ff71eSSathya Perla 		adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10;
3179aebddd1SJeff Kirsher }
3189aebddd1SJeff Kirsher 
3199aebddd1SJeff Kirsher /*Grp5 PVID evt*/
3209aebddd1SJeff Kirsher static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
3213acf19d9SSathya Perla 					     struct be_mcc_compl *compl)
3229aebddd1SJeff Kirsher {
3233acf19d9SSathya Perla 	struct be_async_event_grp5_pvid_state *evt =
3243acf19d9SSathya Perla 			(struct be_async_event_grp5_pvid_state *)compl;
3253acf19d9SSathya Perla 
326bdac85b5SRavikumar Nelavelli 	if (evt->enabled) {
327939cf306SSomnath Kotur 		adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
328bdac85b5SRavikumar Nelavelli 		dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid);
329bdac85b5SRavikumar Nelavelli 	} else {
3309aebddd1SJeff Kirsher 		adapter->pvid = 0;
3319aebddd1SJeff Kirsher 	}
332bdac85b5SRavikumar Nelavelli }
3339aebddd1SJeff Kirsher 
3349aebddd1SJeff Kirsher static void be_async_grp5_evt_process(struct be_adapter *adapter,
3353acf19d9SSathya Perla 				      struct be_mcc_compl *compl)
3369aebddd1SJeff Kirsher {
3373acf19d9SSathya Perla 	u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) &
3383acf19d9SSathya Perla 				ASYNC_EVENT_TYPE_MASK;
3399aebddd1SJeff Kirsher 
3409aebddd1SJeff Kirsher 	switch (event_type) {
3419aebddd1SJeff Kirsher 	case ASYNC_EVENT_COS_PRIORITY:
3423acf19d9SSathya Perla 		be_async_grp5_cos_priority_process(adapter, compl);
3439aebddd1SJeff Kirsher 		break;
3449aebddd1SJeff Kirsher 	case ASYNC_EVENT_QOS_SPEED:
3453acf19d9SSathya Perla 		be_async_grp5_qos_speed_process(adapter, compl);
3469aebddd1SJeff Kirsher 		break;
3479aebddd1SJeff Kirsher 	case ASYNC_EVENT_PVID_STATE:
3483acf19d9SSathya Perla 		be_async_grp5_pvid_state_process(adapter, compl);
3499aebddd1SJeff Kirsher 		break;
3509aebddd1SJeff Kirsher 	default:
3519aebddd1SJeff Kirsher 		break;
3529aebddd1SJeff Kirsher 	}
3539aebddd1SJeff Kirsher }
3549aebddd1SJeff Kirsher 
355bc0c3405SAjit Khaparde static void be_async_dbg_evt_process(struct be_adapter *adapter,
3563acf19d9SSathya Perla 				     struct be_mcc_compl *cmp)
357bc0c3405SAjit Khaparde {
358bc0c3405SAjit Khaparde 	u8 event_type = 0;
359bc0c3405SAjit Khaparde 	struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp;
360bc0c3405SAjit Khaparde 
3613acf19d9SSathya Perla 	event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
3623acf19d9SSathya Perla 			ASYNC_EVENT_TYPE_MASK;
363bc0c3405SAjit Khaparde 
364bc0c3405SAjit Khaparde 	switch (event_type) {
365bc0c3405SAjit Khaparde 	case ASYNC_DEBUG_EVENT_TYPE_QNQ:
366bc0c3405SAjit Khaparde 		if (evt->valid)
367bc0c3405SAjit Khaparde 			adapter->qnq_vid = le16_to_cpu(evt->vlan_tag);
368bc0c3405SAjit Khaparde 		adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
369bc0c3405SAjit Khaparde 	break;
370bc0c3405SAjit Khaparde 	default:
37105ccaa2bSVasundhara Volam 		dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n",
37205ccaa2bSVasundhara Volam 			 event_type);
373bc0c3405SAjit Khaparde 	break;
374bc0c3405SAjit Khaparde 	}
375bc0c3405SAjit Khaparde }
376bc0c3405SAjit Khaparde 
37721252377SVasundhara Volam static void be_async_sliport_evt_process(struct be_adapter *adapter,
37821252377SVasundhara Volam 					 struct be_mcc_compl *cmp)
37921252377SVasundhara Volam {
38021252377SVasundhara Volam 	u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
38121252377SVasundhara Volam 			ASYNC_EVENT_TYPE_MASK;
38221252377SVasundhara Volam 
38321252377SVasundhara Volam 	if (event_type == ASYNC_EVENT_PORT_MISCONFIG)
38421252377SVasundhara Volam 		be_async_port_misconfig_event_process(adapter, cmp);
38521252377SVasundhara Volam }
38621252377SVasundhara Volam 
3873acf19d9SSathya Perla static inline bool is_link_state_evt(u32 flags)
3889aebddd1SJeff Kirsher {
3893acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
3909aebddd1SJeff Kirsher 			ASYNC_EVENT_CODE_LINK_STATE;
3919aebddd1SJeff Kirsher }
3929aebddd1SJeff Kirsher 
3933acf19d9SSathya Perla static inline bool is_grp5_evt(u32 flags)
3949aebddd1SJeff Kirsher {
3953acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
3963acf19d9SSathya Perla 			ASYNC_EVENT_CODE_GRP_5;
3979aebddd1SJeff Kirsher }
3989aebddd1SJeff Kirsher 
3993acf19d9SSathya Perla static inline bool is_dbg_evt(u32 flags)
400bc0c3405SAjit Khaparde {
4013acf19d9SSathya Perla 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
4023acf19d9SSathya Perla 			ASYNC_EVENT_CODE_QNQ;
4033acf19d9SSathya Perla }
4043acf19d9SSathya Perla 
40521252377SVasundhara Volam static inline bool is_sliport_evt(u32 flags)
40621252377SVasundhara Volam {
40721252377SVasundhara Volam 	return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
40821252377SVasundhara Volam 		ASYNC_EVENT_CODE_SLIPORT;
40921252377SVasundhara Volam }
41021252377SVasundhara Volam 
4113acf19d9SSathya Perla static void be_mcc_event_process(struct be_adapter *adapter,
4123acf19d9SSathya Perla 				 struct be_mcc_compl *compl)
4133acf19d9SSathya Perla {
4143acf19d9SSathya Perla 	if (is_link_state_evt(compl->flags))
4153acf19d9SSathya Perla 		be_async_link_state_process(adapter, compl);
4163acf19d9SSathya Perla 	else if (is_grp5_evt(compl->flags))
4173acf19d9SSathya Perla 		be_async_grp5_evt_process(adapter, compl);
4183acf19d9SSathya Perla 	else if (is_dbg_evt(compl->flags))
4193acf19d9SSathya Perla 		be_async_dbg_evt_process(adapter, compl);
42021252377SVasundhara Volam 	else if (is_sliport_evt(compl->flags))
42121252377SVasundhara Volam 		be_async_sliport_evt_process(adapter, compl);
422bc0c3405SAjit Khaparde }
423bc0c3405SAjit Khaparde 
4249aebddd1SJeff Kirsher static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
4259aebddd1SJeff Kirsher {
4269aebddd1SJeff Kirsher 	struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
4279aebddd1SJeff Kirsher 	struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
4289aebddd1SJeff Kirsher 
4299aebddd1SJeff Kirsher 	if (be_mcc_compl_is_new(compl)) {
4309aebddd1SJeff Kirsher 		queue_tail_inc(mcc_cq);
4319aebddd1SJeff Kirsher 		return compl;
4329aebddd1SJeff Kirsher 	}
4339aebddd1SJeff Kirsher 	return NULL;
4349aebddd1SJeff Kirsher }
4359aebddd1SJeff Kirsher 
4369aebddd1SJeff Kirsher void be_async_mcc_enable(struct be_adapter *adapter)
4379aebddd1SJeff Kirsher {
4389aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_cq_lock);
4399aebddd1SJeff Kirsher 
4409aebddd1SJeff Kirsher 	be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0);
4419aebddd1SJeff Kirsher 	adapter->mcc_obj.rearm_cq = true;
4429aebddd1SJeff Kirsher 
4439aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_cq_lock);
4449aebddd1SJeff Kirsher }
4459aebddd1SJeff Kirsher 
4469aebddd1SJeff Kirsher void be_async_mcc_disable(struct be_adapter *adapter)
4479aebddd1SJeff Kirsher {
448a323d9bfSSathya Perla 	spin_lock_bh(&adapter->mcc_cq_lock);
449a323d9bfSSathya Perla 
4509aebddd1SJeff Kirsher 	adapter->mcc_obj.rearm_cq = false;
451a323d9bfSSathya Perla 	be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
452a323d9bfSSathya Perla 
453a323d9bfSSathya Perla 	spin_unlock_bh(&adapter->mcc_cq_lock);
4549aebddd1SJeff Kirsher }
4559aebddd1SJeff Kirsher 
45610ef9ab4SSathya Perla int be_process_mcc(struct be_adapter *adapter)
4579aebddd1SJeff Kirsher {
4589aebddd1SJeff Kirsher 	struct be_mcc_compl *compl;
45910ef9ab4SSathya Perla 	int num = 0, status = 0;
4609aebddd1SJeff Kirsher 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
4619aebddd1SJeff Kirsher 
462072a9c48SAmerigo Wang 	spin_lock(&adapter->mcc_cq_lock);
4633acf19d9SSathya Perla 
4649aebddd1SJeff Kirsher 	while ((compl = be_mcc_compl_get(adapter))) {
4659aebddd1SJeff Kirsher 		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
4663acf19d9SSathya Perla 			be_mcc_event_process(adapter, compl);
4679aebddd1SJeff Kirsher 		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
46810ef9ab4SSathya Perla 			status = be_mcc_compl_process(adapter, compl);
4699aebddd1SJeff Kirsher 			atomic_dec(&mcc_obj->q.used);
4709aebddd1SJeff Kirsher 		}
4719aebddd1SJeff Kirsher 		be_mcc_compl_use(compl);
4729aebddd1SJeff Kirsher 		num++;
4739aebddd1SJeff Kirsher 	}
4749aebddd1SJeff Kirsher 
47510ef9ab4SSathya Perla 	if (num)
47610ef9ab4SSathya Perla 		be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
47710ef9ab4SSathya Perla 
478072a9c48SAmerigo Wang 	spin_unlock(&adapter->mcc_cq_lock);
47910ef9ab4SSathya Perla 	return status;
4809aebddd1SJeff Kirsher }
4819aebddd1SJeff Kirsher 
4829aebddd1SJeff Kirsher /* Wait till no more pending mcc requests are present */
4839aebddd1SJeff Kirsher static int be_mcc_wait_compl(struct be_adapter *adapter)
4849aebddd1SJeff Kirsher {
4859aebddd1SJeff Kirsher #define mcc_timeout		120000 /* 12s timeout */
48610ef9ab4SSathya Perla 	int i, status = 0;
4879aebddd1SJeff Kirsher 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
4889aebddd1SJeff Kirsher 
4896589ade0SSathya Perla 	for (i = 0; i < mcc_timeout; i++) {
4906589ade0SSathya Perla 		if (be_error(adapter))
4919aebddd1SJeff Kirsher 			return -EIO;
4929aebddd1SJeff Kirsher 
493072a9c48SAmerigo Wang 		local_bh_disable();
49410ef9ab4SSathya Perla 		status = be_process_mcc(adapter);
495072a9c48SAmerigo Wang 		local_bh_enable();
4969aebddd1SJeff Kirsher 
4979aebddd1SJeff Kirsher 		if (atomic_read(&mcc_obj->q.used) == 0)
4989aebddd1SJeff Kirsher 			break;
4999aebddd1SJeff Kirsher 		udelay(100);
5009aebddd1SJeff Kirsher 	}
5019aebddd1SJeff Kirsher 	if (i == mcc_timeout) {
5026589ade0SSathya Perla 		dev_err(&adapter->pdev->dev, "FW not responding\n");
5036589ade0SSathya Perla 		adapter->fw_timeout = true;
504652bf646SPadmanabh Ratnakar 		return -EIO;
5059aebddd1SJeff Kirsher 	}
5069aebddd1SJeff Kirsher 	return status;
5079aebddd1SJeff Kirsher }
5089aebddd1SJeff Kirsher 
5099aebddd1SJeff Kirsher /* Notify MCC requests and wait for completion */
5109aebddd1SJeff Kirsher static int be_mcc_notify_wait(struct be_adapter *adapter)
5119aebddd1SJeff Kirsher {
512652bf646SPadmanabh Ratnakar 	int status;
513652bf646SPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
514652bf646SPadmanabh Ratnakar 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
515652bf646SPadmanabh Ratnakar 	u16 index = mcc_obj->q.head;
516652bf646SPadmanabh Ratnakar 	struct be_cmd_resp_hdr *resp;
517652bf646SPadmanabh Ratnakar 
518652bf646SPadmanabh Ratnakar 	index_dec(&index, mcc_obj->q.len);
519652bf646SPadmanabh Ratnakar 	wrb = queue_index_node(&mcc_obj->q, index);
520652bf646SPadmanabh Ratnakar 
521652bf646SPadmanabh Ratnakar 	resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
522652bf646SPadmanabh Ratnakar 
5239aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
524652bf646SPadmanabh Ratnakar 
525652bf646SPadmanabh Ratnakar 	status = be_mcc_wait_compl(adapter);
526652bf646SPadmanabh Ratnakar 	if (status == -EIO)
527652bf646SPadmanabh Ratnakar 		goto out;
528652bf646SPadmanabh Ratnakar 
5294c60005fSKalesh AP 	status = (resp->base_status |
5304c60005fSKalesh AP 		  ((resp->addl_status & CQE_ADDL_STATUS_MASK) <<
5314c60005fSKalesh AP 		   CQE_ADDL_STATUS_SHIFT));
532652bf646SPadmanabh Ratnakar out:
533652bf646SPadmanabh Ratnakar 	return status;
5349aebddd1SJeff Kirsher }
5359aebddd1SJeff Kirsher 
5369aebddd1SJeff Kirsher static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
5379aebddd1SJeff Kirsher {
5389aebddd1SJeff Kirsher 	int msecs = 0;
5399aebddd1SJeff Kirsher 	u32 ready;
5409aebddd1SJeff Kirsher 
5416589ade0SSathya Perla 	do {
5426589ade0SSathya Perla 		if (be_error(adapter))
5439aebddd1SJeff Kirsher 			return -EIO;
5449aebddd1SJeff Kirsher 
5459aebddd1SJeff Kirsher 		ready = ioread32(db);
546434b3648SSathya Perla 		if (ready == 0xffffffff)
5479aebddd1SJeff Kirsher 			return -1;
5489aebddd1SJeff Kirsher 
5499aebddd1SJeff Kirsher 		ready &= MPU_MAILBOX_DB_RDY_MASK;
5509aebddd1SJeff Kirsher 		if (ready)
5519aebddd1SJeff Kirsher 			break;
5529aebddd1SJeff Kirsher 
5539aebddd1SJeff Kirsher 		if (msecs > 4000) {
5546589ade0SSathya Perla 			dev_err(&adapter->pdev->dev, "FW not responding\n");
5556589ade0SSathya Perla 			adapter->fw_timeout = true;
556f67ef7baSPadmanabh Ratnakar 			be_detect_error(adapter);
5579aebddd1SJeff Kirsher 			return -1;
5589aebddd1SJeff Kirsher 		}
5599aebddd1SJeff Kirsher 
5609aebddd1SJeff Kirsher 		msleep(1);
5619aebddd1SJeff Kirsher 		msecs++;
5629aebddd1SJeff Kirsher 	} while (true);
5639aebddd1SJeff Kirsher 
5649aebddd1SJeff Kirsher 	return 0;
5659aebddd1SJeff Kirsher }
5669aebddd1SJeff Kirsher 
5679aebddd1SJeff Kirsher /*
5689aebddd1SJeff Kirsher  * Insert the mailbox address into the doorbell in two steps
5699aebddd1SJeff Kirsher  * Polls on the mbox doorbell till a command completion (or a timeout) occurs
5709aebddd1SJeff Kirsher  */
5719aebddd1SJeff Kirsher static int be_mbox_notify_wait(struct be_adapter *adapter)
5729aebddd1SJeff Kirsher {
5739aebddd1SJeff Kirsher 	int status;
5749aebddd1SJeff Kirsher 	u32 val = 0;
5759aebddd1SJeff Kirsher 	void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET;
5769aebddd1SJeff Kirsher 	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
5779aebddd1SJeff Kirsher 	struct be_mcc_mailbox *mbox = mbox_mem->va;
5789aebddd1SJeff Kirsher 	struct be_mcc_compl *compl = &mbox->compl;
5799aebddd1SJeff Kirsher 
5809aebddd1SJeff Kirsher 	/* wait for ready to be set */
5819aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
5829aebddd1SJeff Kirsher 	if (status != 0)
5839aebddd1SJeff Kirsher 		return status;
5849aebddd1SJeff Kirsher 
5859aebddd1SJeff Kirsher 	val |= MPU_MAILBOX_DB_HI_MASK;
5869aebddd1SJeff Kirsher 	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
5879aebddd1SJeff Kirsher 	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
5889aebddd1SJeff Kirsher 	iowrite32(val, db);
5899aebddd1SJeff Kirsher 
5909aebddd1SJeff Kirsher 	/* wait for ready to be set */
5919aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
5929aebddd1SJeff Kirsher 	if (status != 0)
5939aebddd1SJeff Kirsher 		return status;
5949aebddd1SJeff Kirsher 
5959aebddd1SJeff Kirsher 	val = 0;
5969aebddd1SJeff Kirsher 	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
5979aebddd1SJeff Kirsher 	val |= (u32)(mbox_mem->dma >> 4) << 2;
5989aebddd1SJeff Kirsher 	iowrite32(val, db);
5999aebddd1SJeff Kirsher 
6009aebddd1SJeff Kirsher 	status = be_mbox_db_ready_wait(adapter, db);
6019aebddd1SJeff Kirsher 	if (status != 0)
6029aebddd1SJeff Kirsher 		return status;
6039aebddd1SJeff Kirsher 
6049aebddd1SJeff Kirsher 	/* A cq entry has been made now */
6059aebddd1SJeff Kirsher 	if (be_mcc_compl_is_new(compl)) {
6069aebddd1SJeff Kirsher 		status = be_mcc_compl_process(adapter, &mbox->compl);
6079aebddd1SJeff Kirsher 		be_mcc_compl_use(compl);
6089aebddd1SJeff Kirsher 		if (status)
6099aebddd1SJeff Kirsher 			return status;
6109aebddd1SJeff Kirsher 	} else {
6119aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev, "invalid mailbox completion\n");
6129aebddd1SJeff Kirsher 		return -1;
6139aebddd1SJeff Kirsher 	}
6149aebddd1SJeff Kirsher 	return 0;
6159aebddd1SJeff Kirsher }
6169aebddd1SJeff Kirsher 
617c5b3ad4cSSathya Perla static u16 be_POST_stage_get(struct be_adapter *adapter)
6189aebddd1SJeff Kirsher {
6199aebddd1SJeff Kirsher 	u32 sem;
6209aebddd1SJeff Kirsher 
621c5b3ad4cSSathya Perla 	if (BEx_chip(adapter))
622c5b3ad4cSSathya Perla 		sem  = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx);
6239aebddd1SJeff Kirsher 	else
624c5b3ad4cSSathya Perla 		pci_read_config_dword(adapter->pdev,
625c5b3ad4cSSathya Perla 				      SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
626c5b3ad4cSSathya Perla 
627c5b3ad4cSSathya Perla 	return sem & POST_STAGE_MASK;
6289aebddd1SJeff Kirsher }
6299aebddd1SJeff Kirsher 
63087f20c26SGavin Shan static int lancer_wait_ready(struct be_adapter *adapter)
631bf99e50dSPadmanabh Ratnakar {
632bf99e50dSPadmanabh Ratnakar #define SLIPORT_READY_TIMEOUT 30
633bf99e50dSPadmanabh Ratnakar 	u32 sliport_status;
634e673244aSKalesh AP 	int i;
635bf99e50dSPadmanabh Ratnakar 
636bf99e50dSPadmanabh Ratnakar 	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
637bf99e50dSPadmanabh Ratnakar 		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
638bf99e50dSPadmanabh Ratnakar 		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
6399fa465c0SSathya Perla 			return 0;
6409fa465c0SSathya Perla 
6419fa465c0SSathya Perla 		if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
6429fa465c0SSathya Perla 		    !(sliport_status & SLIPORT_STATUS_RN_MASK))
6439fa465c0SSathya Perla 			return -EIO;
644bf99e50dSPadmanabh Ratnakar 
645bf99e50dSPadmanabh Ratnakar 		msleep(1000);
646bf99e50dSPadmanabh Ratnakar 	}
647bf99e50dSPadmanabh Ratnakar 
648e673244aSKalesh AP 	return sliport_status ? : -1;
649bf99e50dSPadmanabh Ratnakar }
650bf99e50dSPadmanabh Ratnakar 
651bf99e50dSPadmanabh Ratnakar int be_fw_wait_ready(struct be_adapter *adapter)
6529aebddd1SJeff Kirsher {
6539aebddd1SJeff Kirsher 	u16 stage;
6549aebddd1SJeff Kirsher 	int status, timeout = 0;
6559aebddd1SJeff Kirsher 	struct device *dev = &adapter->pdev->dev;
6569aebddd1SJeff Kirsher 
657bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter)) {
658bf99e50dSPadmanabh Ratnakar 		status = lancer_wait_ready(adapter);
659e673244aSKalesh AP 		if (status) {
660e673244aSKalesh AP 			stage = status;
661e673244aSKalesh AP 			goto err;
662e673244aSKalesh AP 		}
663e673244aSKalesh AP 		return 0;
664bf99e50dSPadmanabh Ratnakar 	}
665bf99e50dSPadmanabh Ratnakar 
6669aebddd1SJeff Kirsher 	do {
667ca3de6b2SSathya Perla 		/* There's no means to poll POST state on BE2/3 VFs */
668ca3de6b2SSathya Perla 		if (BEx_chip(adapter) && be_virtfn(adapter))
669ca3de6b2SSathya Perla 			return 0;
670ca3de6b2SSathya Perla 
671c5b3ad4cSSathya Perla 		stage = be_POST_stage_get(adapter);
67266d29cbcSGavin Shan 		if (stage == POST_STAGE_ARMFW_RDY)
67366d29cbcSGavin Shan 			return 0;
67466d29cbcSGavin Shan 
675a2cc4e0bSSathya Perla 		dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout);
6769aebddd1SJeff Kirsher 		if (msleep_interruptible(2000)) {
6779aebddd1SJeff Kirsher 			dev_err(dev, "Waiting for POST aborted\n");
6789aebddd1SJeff Kirsher 			return -EINTR;
6799aebddd1SJeff Kirsher 		}
6809aebddd1SJeff Kirsher 		timeout += 2;
6813ab81b5fSSomnath Kotur 	} while (timeout < 60);
6829aebddd1SJeff Kirsher 
683e673244aSKalesh AP err:
684e673244aSKalesh AP 	dev_err(dev, "POST timeout; stage=%#x\n", stage);
6859fa465c0SSathya Perla 	return -ETIMEDOUT;
6869aebddd1SJeff Kirsher }
6879aebddd1SJeff Kirsher 
6889aebddd1SJeff Kirsher static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
6899aebddd1SJeff Kirsher {
6909aebddd1SJeff Kirsher 	return &wrb->payload.sgl[0];
6919aebddd1SJeff Kirsher }
6929aebddd1SJeff Kirsher 
693a2cc4e0bSSathya Perla static inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr)
694bea50988SSathya Perla {
695bea50988SSathya Perla 	wrb->tag0 = addr & 0xFFFFFFFF;
696bea50988SSathya Perla 	wrb->tag1 = upper_32_bits(addr);
697bea50988SSathya Perla }
6989aebddd1SJeff Kirsher 
6999aebddd1SJeff Kirsher /* Don't touch the hdr after it's prepared */
700106df1e3SSomnath Kotur /* mem will be NULL for embedded commands */
701106df1e3SSomnath Kotur static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
702106df1e3SSomnath Kotur 				   u8 subsystem, u8 opcode, int cmd_len,
703a2cc4e0bSSathya Perla 				   struct be_mcc_wrb *wrb,
704a2cc4e0bSSathya Perla 				   struct be_dma_mem *mem)
7059aebddd1SJeff Kirsher {
706106df1e3SSomnath Kotur 	struct be_sge *sge;
707106df1e3SSomnath Kotur 
7089aebddd1SJeff Kirsher 	req_hdr->opcode = opcode;
7099aebddd1SJeff Kirsher 	req_hdr->subsystem = subsystem;
7109aebddd1SJeff Kirsher 	req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
7119aebddd1SJeff Kirsher 	req_hdr->version = 0;
712bea50988SSathya Perla 	fill_wrb_tags(wrb, (ulong) req_hdr);
713106df1e3SSomnath Kotur 	wrb->payload_length = cmd_len;
714106df1e3SSomnath Kotur 	if (mem) {
715106df1e3SSomnath Kotur 		wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
716106df1e3SSomnath Kotur 			MCC_WRB_SGE_CNT_SHIFT;
717106df1e3SSomnath Kotur 		sge = nonembedded_sgl(wrb);
718106df1e3SSomnath Kotur 		sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
719106df1e3SSomnath Kotur 		sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
720106df1e3SSomnath Kotur 		sge->len = cpu_to_le32(mem->size);
721106df1e3SSomnath Kotur 	} else
722106df1e3SSomnath Kotur 		wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
723106df1e3SSomnath Kotur 	be_dws_cpu_to_le(wrb, 8);
7249aebddd1SJeff Kirsher }
7259aebddd1SJeff Kirsher 
7269aebddd1SJeff Kirsher static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
7279aebddd1SJeff Kirsher 				      struct be_dma_mem *mem)
7289aebddd1SJeff Kirsher {
7299aebddd1SJeff Kirsher 	int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
7309aebddd1SJeff Kirsher 	u64 dma = (u64)mem->dma;
7319aebddd1SJeff Kirsher 
7329aebddd1SJeff Kirsher 	for (i = 0; i < buf_pages; i++) {
7339aebddd1SJeff Kirsher 		pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
7349aebddd1SJeff Kirsher 		pages[i].hi = cpu_to_le32(upper_32_bits(dma));
7359aebddd1SJeff Kirsher 		dma += PAGE_SIZE_4K;
7369aebddd1SJeff Kirsher 	}
7379aebddd1SJeff Kirsher }
7389aebddd1SJeff Kirsher 
7399aebddd1SJeff Kirsher static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter)
7409aebddd1SJeff Kirsher {
7419aebddd1SJeff Kirsher 	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
7429aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb
7439aebddd1SJeff Kirsher 		= &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
7449aebddd1SJeff Kirsher 	memset(wrb, 0, sizeof(*wrb));
7459aebddd1SJeff Kirsher 	return wrb;
7469aebddd1SJeff Kirsher }
7479aebddd1SJeff Kirsher 
7489aebddd1SJeff Kirsher static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
7499aebddd1SJeff Kirsher {
7509aebddd1SJeff Kirsher 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
7519aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
7529aebddd1SJeff Kirsher 
753aa790db9SPadmanabh Ratnakar 	if (!mccq->created)
754aa790db9SPadmanabh Ratnakar 		return NULL;
755aa790db9SPadmanabh Ratnakar 
7564d277125SVasundhara Volam 	if (atomic_read(&mccq->used) >= mccq->len)
7579aebddd1SJeff Kirsher 		return NULL;
7589aebddd1SJeff Kirsher 
7599aebddd1SJeff Kirsher 	wrb = queue_head_node(mccq);
7609aebddd1SJeff Kirsher 	queue_head_inc(mccq);
7619aebddd1SJeff Kirsher 	atomic_inc(&mccq->used);
7629aebddd1SJeff Kirsher 	memset(wrb, 0, sizeof(*wrb));
7639aebddd1SJeff Kirsher 	return wrb;
7649aebddd1SJeff Kirsher }
7659aebddd1SJeff Kirsher 
766bea50988SSathya Perla static bool use_mcc(struct be_adapter *adapter)
767bea50988SSathya Perla {
768bea50988SSathya Perla 	return adapter->mcc_obj.q.created;
769bea50988SSathya Perla }
770bea50988SSathya Perla 
771bea50988SSathya Perla /* Must be used only in process context */
772bea50988SSathya Perla static int be_cmd_lock(struct be_adapter *adapter)
773bea50988SSathya Perla {
774bea50988SSathya Perla 	if (use_mcc(adapter)) {
775bea50988SSathya Perla 		spin_lock_bh(&adapter->mcc_lock);
776bea50988SSathya Perla 		return 0;
777bea50988SSathya Perla 	} else {
778bea50988SSathya Perla 		return mutex_lock_interruptible(&adapter->mbox_lock);
779bea50988SSathya Perla 	}
780bea50988SSathya Perla }
781bea50988SSathya Perla 
782bea50988SSathya Perla /* Must be used only in process context */
783bea50988SSathya Perla static void be_cmd_unlock(struct be_adapter *adapter)
784bea50988SSathya Perla {
785bea50988SSathya Perla 	if (use_mcc(adapter))
786bea50988SSathya Perla 		spin_unlock_bh(&adapter->mcc_lock);
787bea50988SSathya Perla 	else
788bea50988SSathya Perla 		return mutex_unlock(&adapter->mbox_lock);
789bea50988SSathya Perla }
790bea50988SSathya Perla 
791bea50988SSathya Perla static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter,
792bea50988SSathya Perla 				      struct be_mcc_wrb *wrb)
793bea50988SSathya Perla {
794bea50988SSathya Perla 	struct be_mcc_wrb *dest_wrb;
795bea50988SSathya Perla 
796bea50988SSathya Perla 	if (use_mcc(adapter)) {
797bea50988SSathya Perla 		dest_wrb = wrb_from_mccq(adapter);
798bea50988SSathya Perla 		if (!dest_wrb)
799bea50988SSathya Perla 			return NULL;
800bea50988SSathya Perla 	} else {
801bea50988SSathya Perla 		dest_wrb = wrb_from_mbox(adapter);
802bea50988SSathya Perla 	}
803bea50988SSathya Perla 
804bea50988SSathya Perla 	memcpy(dest_wrb, wrb, sizeof(*wrb));
805bea50988SSathya Perla 	if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK))
806bea50988SSathya Perla 		fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb));
807bea50988SSathya Perla 
808bea50988SSathya Perla 	return dest_wrb;
809bea50988SSathya Perla }
810bea50988SSathya Perla 
811bea50988SSathya Perla /* Must be used only in process context */
812bea50988SSathya Perla static int be_cmd_notify_wait(struct be_adapter *adapter,
813bea50988SSathya Perla 			      struct be_mcc_wrb *wrb)
814bea50988SSathya Perla {
815bea50988SSathya Perla 	struct be_mcc_wrb *dest_wrb;
816bea50988SSathya Perla 	int status;
817bea50988SSathya Perla 
818bea50988SSathya Perla 	status = be_cmd_lock(adapter);
819bea50988SSathya Perla 	if (status)
820bea50988SSathya Perla 		return status;
821bea50988SSathya Perla 
822bea50988SSathya Perla 	dest_wrb = be_cmd_copy(adapter, wrb);
823bea50988SSathya Perla 	if (!dest_wrb)
824bea50988SSathya Perla 		return -EBUSY;
825bea50988SSathya Perla 
826bea50988SSathya Perla 	if (use_mcc(adapter))
827bea50988SSathya Perla 		status = be_mcc_notify_wait(adapter);
828bea50988SSathya Perla 	else
829bea50988SSathya Perla 		status = be_mbox_notify_wait(adapter);
830bea50988SSathya Perla 
831bea50988SSathya Perla 	if (!status)
832bea50988SSathya Perla 		memcpy(wrb, dest_wrb, sizeof(*wrb));
833bea50988SSathya Perla 
834bea50988SSathya Perla 	be_cmd_unlock(adapter);
835bea50988SSathya Perla 	return status;
836bea50988SSathya Perla }
837bea50988SSathya Perla 
8389aebddd1SJeff Kirsher /* Tell fw we're about to start firing cmds by writing a
8399aebddd1SJeff Kirsher  * special pattern across the wrb hdr; uses mbox
8409aebddd1SJeff Kirsher  */
8419aebddd1SJeff Kirsher int be_cmd_fw_init(struct be_adapter *adapter)
8429aebddd1SJeff Kirsher {
8439aebddd1SJeff Kirsher 	u8 *wrb;
8449aebddd1SJeff Kirsher 	int status;
8459aebddd1SJeff Kirsher 
846bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter))
847bf99e50dSPadmanabh Ratnakar 		return 0;
848bf99e50dSPadmanabh Ratnakar 
8499aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
8509aebddd1SJeff Kirsher 		return -1;
8519aebddd1SJeff Kirsher 
8529aebddd1SJeff Kirsher 	wrb = (u8 *)wrb_from_mbox(adapter);
8539aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8549aebddd1SJeff Kirsher 	*wrb++ = 0x12;
8559aebddd1SJeff Kirsher 	*wrb++ = 0x34;
8569aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8579aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8589aebddd1SJeff Kirsher 	*wrb++ = 0x56;
8599aebddd1SJeff Kirsher 	*wrb++ = 0x78;
8609aebddd1SJeff Kirsher 	*wrb = 0xFF;
8619aebddd1SJeff Kirsher 
8629aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
8639aebddd1SJeff Kirsher 
8649aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
8659aebddd1SJeff Kirsher 	return status;
8669aebddd1SJeff Kirsher }
8679aebddd1SJeff Kirsher 
8689aebddd1SJeff Kirsher /* Tell fw we're done with firing cmds by writing a
8699aebddd1SJeff Kirsher  * special pattern across the wrb hdr; uses mbox
8709aebddd1SJeff Kirsher  */
8719aebddd1SJeff Kirsher int be_cmd_fw_clean(struct be_adapter *adapter)
8729aebddd1SJeff Kirsher {
8739aebddd1SJeff Kirsher 	u8 *wrb;
8749aebddd1SJeff Kirsher 	int status;
8759aebddd1SJeff Kirsher 
876bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter))
877bf99e50dSPadmanabh Ratnakar 		return 0;
878bf99e50dSPadmanabh Ratnakar 
8799aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
8809aebddd1SJeff Kirsher 		return -1;
8819aebddd1SJeff Kirsher 
8829aebddd1SJeff Kirsher 	wrb = (u8 *)wrb_from_mbox(adapter);
8839aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8849aebddd1SJeff Kirsher 	*wrb++ = 0xAA;
8859aebddd1SJeff Kirsher 	*wrb++ = 0xBB;
8869aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8879aebddd1SJeff Kirsher 	*wrb++ = 0xFF;
8889aebddd1SJeff Kirsher 	*wrb++ = 0xCC;
8899aebddd1SJeff Kirsher 	*wrb++ = 0xDD;
8909aebddd1SJeff Kirsher 	*wrb = 0xFF;
8919aebddd1SJeff Kirsher 
8929aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
8939aebddd1SJeff Kirsher 
8949aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
8959aebddd1SJeff Kirsher 	return status;
8969aebddd1SJeff Kirsher }
897bf99e50dSPadmanabh Ratnakar 
898f2f781a7SSathya Perla int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo)
8999aebddd1SJeff Kirsher {
9009aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9019aebddd1SJeff Kirsher 	struct be_cmd_req_eq_create *req;
902f2f781a7SSathya Perla 	struct be_dma_mem *q_mem = &eqo->q.dma_mem;
903f2f781a7SSathya Perla 	int status, ver = 0;
9049aebddd1SJeff Kirsher 
9059aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
9069aebddd1SJeff Kirsher 		return -1;
9079aebddd1SJeff Kirsher 
9089aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
9099aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
9109aebddd1SJeff Kirsher 
911106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
912a2cc4e0bSSathya Perla 			       OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb,
913a2cc4e0bSSathya Perla 			       NULL);
9149aebddd1SJeff Kirsher 
915f2f781a7SSathya Perla 	/* Support for EQ_CREATEv2 available only SH-R onwards */
916f2f781a7SSathya Perla 	if (!(BEx_chip(adapter) || lancer_chip(adapter)))
917f2f781a7SSathya Perla 		ver = 2;
918f2f781a7SSathya Perla 
919f2f781a7SSathya Perla 	req->hdr.version = ver;
9209aebddd1SJeff Kirsher 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
9219aebddd1SJeff Kirsher 
9229aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
9239aebddd1SJeff Kirsher 	/* 4byte eqe*/
9249aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
9259aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_eq_context, count, req->context,
926f2f781a7SSathya Perla 		      __ilog2_u32(eqo->q.len / 256));
9279aebddd1SJeff Kirsher 	be_dws_cpu_to_le(req->context, sizeof(req->context));
9289aebddd1SJeff Kirsher 
9299aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
9309aebddd1SJeff Kirsher 
9319aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
9329aebddd1SJeff Kirsher 	if (!status) {
9339aebddd1SJeff Kirsher 		struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
93403d28ffeSKalesh AP 
935f2f781a7SSathya Perla 		eqo->q.id = le16_to_cpu(resp->eq_id);
936f2f781a7SSathya Perla 		eqo->msix_idx =
937f2f781a7SSathya Perla 			(ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx;
938f2f781a7SSathya Perla 		eqo->q.created = true;
9399aebddd1SJeff Kirsher 	}
9409aebddd1SJeff Kirsher 
9419aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
9429aebddd1SJeff Kirsher 	return status;
9439aebddd1SJeff Kirsher }
9449aebddd1SJeff Kirsher 
945f9449ab7SSathya Perla /* Use MCC */
9469aebddd1SJeff Kirsher int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
9475ee4979bSSathya Perla 			  bool permanent, u32 if_handle, u32 pmac_id)
9489aebddd1SJeff Kirsher {
9499aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9509aebddd1SJeff Kirsher 	struct be_cmd_req_mac_query *req;
9519aebddd1SJeff Kirsher 	int status;
9529aebddd1SJeff Kirsher 
953f9449ab7SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
9549aebddd1SJeff Kirsher 
955f9449ab7SSathya Perla 	wrb = wrb_from_mccq(adapter);
956f9449ab7SSathya Perla 	if (!wrb) {
957f9449ab7SSathya Perla 		status = -EBUSY;
958f9449ab7SSathya Perla 		goto err;
959f9449ab7SSathya Perla 	}
9609aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
9619aebddd1SJeff Kirsher 
962106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
963a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb,
964a2cc4e0bSSathya Perla 			       NULL);
9655ee4979bSSathya Perla 	req->type = MAC_ADDRESS_TYPE_NETWORK;
9669aebddd1SJeff Kirsher 	if (permanent) {
9679aebddd1SJeff Kirsher 		req->permanent = 1;
9689aebddd1SJeff Kirsher 	} else {
9699aebddd1SJeff Kirsher 		req->if_id = cpu_to_le16((u16)if_handle);
970590c391dSPadmanabh Ratnakar 		req->pmac_id = cpu_to_le32(pmac_id);
9719aebddd1SJeff Kirsher 		req->permanent = 0;
9729aebddd1SJeff Kirsher 	}
9739aebddd1SJeff Kirsher 
974f9449ab7SSathya Perla 	status = be_mcc_notify_wait(adapter);
9759aebddd1SJeff Kirsher 	if (!status) {
9769aebddd1SJeff Kirsher 		struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
97703d28ffeSKalesh AP 
9789aebddd1SJeff Kirsher 		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
9799aebddd1SJeff Kirsher 	}
9809aebddd1SJeff Kirsher 
981f9449ab7SSathya Perla err:
982f9449ab7SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
9839aebddd1SJeff Kirsher 	return status;
9849aebddd1SJeff Kirsher }
9859aebddd1SJeff Kirsher 
9869aebddd1SJeff Kirsher /* Uses synchronous MCCQ */
9879aebddd1SJeff Kirsher int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
9889aebddd1SJeff Kirsher 		    u32 if_id, u32 *pmac_id, u32 domain)
9899aebddd1SJeff Kirsher {
9909aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
9919aebddd1SJeff Kirsher 	struct be_cmd_req_pmac_add *req;
9929aebddd1SJeff Kirsher 	int status;
9939aebddd1SJeff Kirsher 
9949aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
9959aebddd1SJeff Kirsher 
9969aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
9979aebddd1SJeff Kirsher 	if (!wrb) {
9989aebddd1SJeff Kirsher 		status = -EBUSY;
9999aebddd1SJeff Kirsher 		goto err;
10009aebddd1SJeff Kirsher 	}
10019aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10029aebddd1SJeff Kirsher 
1003106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1004a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb,
1005a2cc4e0bSSathya Perla 			       NULL);
10069aebddd1SJeff Kirsher 
10079aebddd1SJeff Kirsher 	req->hdr.domain = domain;
10089aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(if_id);
10099aebddd1SJeff Kirsher 	memcpy(req->mac_address, mac_addr, ETH_ALEN);
10109aebddd1SJeff Kirsher 
10119aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
10129aebddd1SJeff Kirsher 	if (!status) {
10139aebddd1SJeff Kirsher 		struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
101403d28ffeSKalesh AP 
10159aebddd1SJeff Kirsher 		*pmac_id = le32_to_cpu(resp->pmac_id);
10169aebddd1SJeff Kirsher 	}
10179aebddd1SJeff Kirsher 
10189aebddd1SJeff Kirsher err:
10199aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1020e3a7ae2cSSomnath Kotur 
1021e3a7ae2cSSomnath Kotur 	 if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
1022e3a7ae2cSSomnath Kotur 		status = -EPERM;
1023e3a7ae2cSSomnath Kotur 
10249aebddd1SJeff Kirsher 	return status;
10259aebddd1SJeff Kirsher }
10269aebddd1SJeff Kirsher 
10279aebddd1SJeff Kirsher /* Uses synchronous MCCQ */
102830128031SSathya Perla int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom)
10299aebddd1SJeff Kirsher {
10309aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
10319aebddd1SJeff Kirsher 	struct be_cmd_req_pmac_del *req;
10329aebddd1SJeff Kirsher 	int status;
10339aebddd1SJeff Kirsher 
103430128031SSathya Perla 	if (pmac_id == -1)
103530128031SSathya Perla 		return 0;
103630128031SSathya Perla 
10379aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
10389aebddd1SJeff Kirsher 
10399aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
10409aebddd1SJeff Kirsher 	if (!wrb) {
10419aebddd1SJeff Kirsher 		status = -EBUSY;
10429aebddd1SJeff Kirsher 		goto err;
10439aebddd1SJeff Kirsher 	}
10449aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10459aebddd1SJeff Kirsher 
1046106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1047cd3307aaSKalesh AP 			       OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req),
1048cd3307aaSKalesh AP 			       wrb, NULL);
10499aebddd1SJeff Kirsher 
10509aebddd1SJeff Kirsher 	req->hdr.domain = dom;
10519aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(if_id);
10529aebddd1SJeff Kirsher 	req->pmac_id = cpu_to_le32(pmac_id);
10539aebddd1SJeff Kirsher 
10549aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
10559aebddd1SJeff Kirsher 
10569aebddd1SJeff Kirsher err:
10579aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
10589aebddd1SJeff Kirsher 	return status;
10599aebddd1SJeff Kirsher }
10609aebddd1SJeff Kirsher 
10619aebddd1SJeff Kirsher /* Uses Mbox */
106210ef9ab4SSathya Perla int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
106310ef9ab4SSathya Perla 		     struct be_queue_info *eq, bool no_delay, int coalesce_wm)
10649aebddd1SJeff Kirsher {
10659aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
10669aebddd1SJeff Kirsher 	struct be_cmd_req_cq_create *req;
10679aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &cq->dma_mem;
10689aebddd1SJeff Kirsher 	void *ctxt;
10699aebddd1SJeff Kirsher 	int status;
10709aebddd1SJeff Kirsher 
10719aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
10729aebddd1SJeff Kirsher 		return -1;
10739aebddd1SJeff Kirsher 
10749aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
10759aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
10769aebddd1SJeff Kirsher 	ctxt = &req->context;
10779aebddd1SJeff Kirsher 
1078106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1079a2cc4e0bSSathya Perla 			       OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb,
1080a2cc4e0bSSathya Perla 			       NULL);
10819aebddd1SJeff Kirsher 
10829aebddd1SJeff Kirsher 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
1083bbdc42f8SAjit Khaparde 
1084bbdc42f8SAjit Khaparde 	if (BEx_chip(adapter)) {
10859aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
10869aebddd1SJeff Kirsher 			      coalesce_wm);
10879aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, nodelay,
10889aebddd1SJeff Kirsher 			      ctxt, no_delay);
10899aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
10909aebddd1SJeff Kirsher 			      __ilog2_u32(cq->len / 256));
10919aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
10929aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
10939aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
1094bbdc42f8SAjit Khaparde 	} else {
1095bbdc42f8SAjit Khaparde 		req->hdr.version = 2;
1096bbdc42f8SAjit Khaparde 		req->page_size = 1; /* 1 for 4K */
109709e83a9dSAjit Khaparde 
109809e83a9dSAjit Khaparde 		/* coalesce-wm field in this cmd is not relevant to Lancer.
109909e83a9dSAjit Khaparde 		 * Lancer uses COMMON_MODIFY_CQ to set this field
110009e83a9dSAjit Khaparde 		 */
110109e83a9dSAjit Khaparde 		if (!lancer_chip(adapter))
110209e83a9dSAjit Khaparde 			AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
110309e83a9dSAjit Khaparde 				      ctxt, coalesce_wm);
1104bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt,
1105bbdc42f8SAjit Khaparde 			      no_delay);
1106bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
1107bbdc42f8SAjit Khaparde 			      __ilog2_u32(cq->len / 256));
1108bbdc42f8SAjit Khaparde 		AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
1109a2cc4e0bSSathya Perla 		AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
1110a2cc4e0bSSathya Perla 		AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
11119aebddd1SJeff Kirsher 	}
11129aebddd1SJeff Kirsher 
11139aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
11149aebddd1SJeff Kirsher 
11159aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
11169aebddd1SJeff Kirsher 
11179aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
11189aebddd1SJeff Kirsher 	if (!status) {
11199aebddd1SJeff Kirsher 		struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
112003d28ffeSKalesh AP 
11219aebddd1SJeff Kirsher 		cq->id = le16_to_cpu(resp->cq_id);
11229aebddd1SJeff Kirsher 		cq->created = true;
11239aebddd1SJeff Kirsher 	}
11249aebddd1SJeff Kirsher 
11259aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
11269aebddd1SJeff Kirsher 
11279aebddd1SJeff Kirsher 	return status;
11289aebddd1SJeff Kirsher }
11299aebddd1SJeff Kirsher 
11309aebddd1SJeff Kirsher static u32 be_encoded_q_len(int q_len)
11319aebddd1SJeff Kirsher {
11329aebddd1SJeff Kirsher 	u32 len_encoded = fls(q_len); /* log2(len) + 1 */
113303d28ffeSKalesh AP 
11349aebddd1SJeff Kirsher 	if (len_encoded == 16)
11359aebddd1SJeff Kirsher 		len_encoded = 0;
11369aebddd1SJeff Kirsher 	return len_encoded;
11379aebddd1SJeff Kirsher }
11389aebddd1SJeff Kirsher 
11394188e7dfSJingoo Han static int be_cmd_mccq_ext_create(struct be_adapter *adapter,
11409aebddd1SJeff Kirsher 				  struct be_queue_info *mccq,
11419aebddd1SJeff Kirsher 				  struct be_queue_info *cq)
11429aebddd1SJeff Kirsher {
11439aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
11449aebddd1SJeff Kirsher 	struct be_cmd_req_mcc_ext_create *req;
11459aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &mccq->dma_mem;
11469aebddd1SJeff Kirsher 	void *ctxt;
11479aebddd1SJeff Kirsher 	int status;
11489aebddd1SJeff Kirsher 
11499aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
11509aebddd1SJeff Kirsher 		return -1;
11519aebddd1SJeff Kirsher 
11529aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
11539aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
11549aebddd1SJeff Kirsher 	ctxt = &req->context;
11559aebddd1SJeff Kirsher 
1156106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1157a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb,
1158a2cc4e0bSSathya Perla 			       NULL);
11599aebddd1SJeff Kirsher 
11609aebddd1SJeff Kirsher 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
1161666d39c7SVasundhara Volam 	if (BEx_chip(adapter)) {
11629aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
11639aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
11649aebddd1SJeff Kirsher 			      be_encoded_q_len(mccq->len));
11659aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
1166666d39c7SVasundhara Volam 	} else {
1167666d39c7SVasundhara Volam 		req->hdr.version = 1;
1168666d39c7SVasundhara Volam 		req->cq_id = cpu_to_le16(cq->id);
1169666d39c7SVasundhara Volam 
1170666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt,
1171666d39c7SVasundhara Volam 			      be_encoded_q_len(mccq->len));
1172666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1);
1173666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id,
1174666d39c7SVasundhara Volam 			      ctxt, cq->id);
1175666d39c7SVasundhara Volam 		AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid,
1176666d39c7SVasundhara Volam 			      ctxt, 1);
11779aebddd1SJeff Kirsher 	}
11789aebddd1SJeff Kirsher 
117921252377SVasundhara Volam 	/* Subscribe to Link State, Sliport Event and Group 5 Events
118021252377SVasundhara Volam 	 * (bits 1, 5 and 17 set)
118121252377SVasundhara Volam 	 */
118221252377SVasundhara Volam 	req->async_event_bitmap[0] =
118321252377SVasundhara Volam 			cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) |
118421252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_GRP_5) |
118521252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_QNQ) |
118621252377SVasundhara Volam 				    BIT(ASYNC_EVENT_CODE_SLIPORT));
118721252377SVasundhara Volam 
11889aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
11899aebddd1SJeff Kirsher 
11909aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
11919aebddd1SJeff Kirsher 
11929aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
11939aebddd1SJeff Kirsher 	if (!status) {
11949aebddd1SJeff Kirsher 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
119503d28ffeSKalesh AP 
11969aebddd1SJeff Kirsher 		mccq->id = le16_to_cpu(resp->id);
11979aebddd1SJeff Kirsher 		mccq->created = true;
11989aebddd1SJeff Kirsher 	}
11999aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
12009aebddd1SJeff Kirsher 
12019aebddd1SJeff Kirsher 	return status;
12029aebddd1SJeff Kirsher }
12039aebddd1SJeff Kirsher 
12044188e7dfSJingoo Han static int be_cmd_mccq_org_create(struct be_adapter *adapter,
12059aebddd1SJeff Kirsher 				  struct be_queue_info *mccq,
12069aebddd1SJeff Kirsher 				  struct be_queue_info *cq)
12079aebddd1SJeff Kirsher {
12089aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
12099aebddd1SJeff Kirsher 	struct be_cmd_req_mcc_create *req;
12109aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &mccq->dma_mem;
12119aebddd1SJeff Kirsher 	void *ctxt;
12129aebddd1SJeff Kirsher 	int status;
12139aebddd1SJeff Kirsher 
12149aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
12159aebddd1SJeff Kirsher 		return -1;
12169aebddd1SJeff Kirsher 
12179aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
12189aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
12199aebddd1SJeff Kirsher 	ctxt = &req->context;
12209aebddd1SJeff Kirsher 
1221106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1222a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb,
1223a2cc4e0bSSathya Perla 			       NULL);
12249aebddd1SJeff Kirsher 
12259aebddd1SJeff Kirsher 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
12269aebddd1SJeff Kirsher 
12279aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
12289aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
12299aebddd1SJeff Kirsher 		      be_encoded_q_len(mccq->len));
12309aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
12319aebddd1SJeff Kirsher 
12329aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
12339aebddd1SJeff Kirsher 
12349aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
12359aebddd1SJeff Kirsher 
12369aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
12379aebddd1SJeff Kirsher 	if (!status) {
12389aebddd1SJeff Kirsher 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
123903d28ffeSKalesh AP 
12409aebddd1SJeff Kirsher 		mccq->id = le16_to_cpu(resp->id);
12419aebddd1SJeff Kirsher 		mccq->created = true;
12429aebddd1SJeff Kirsher 	}
12439aebddd1SJeff Kirsher 
12449aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
12459aebddd1SJeff Kirsher 	return status;
12469aebddd1SJeff Kirsher }
12479aebddd1SJeff Kirsher 
12489aebddd1SJeff Kirsher int be_cmd_mccq_create(struct be_adapter *adapter,
1249a2cc4e0bSSathya Perla 		       struct be_queue_info *mccq, struct be_queue_info *cq)
12509aebddd1SJeff Kirsher {
12519aebddd1SJeff Kirsher 	int status;
12529aebddd1SJeff Kirsher 
12539aebddd1SJeff Kirsher 	status = be_cmd_mccq_ext_create(adapter, mccq, cq);
1254666d39c7SVasundhara Volam 	if (status && BEx_chip(adapter)) {
12559aebddd1SJeff Kirsher 		dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
12569aebddd1SJeff Kirsher 			"or newer to avoid conflicting priorities between NIC "
12579aebddd1SJeff Kirsher 			"and FCoE traffic");
12589aebddd1SJeff Kirsher 		status = be_cmd_mccq_org_create(adapter, mccq, cq);
12599aebddd1SJeff Kirsher 	}
12609aebddd1SJeff Kirsher 	return status;
12619aebddd1SJeff Kirsher }
12629aebddd1SJeff Kirsher 
126394d73aaaSVasundhara Volam int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo)
12649aebddd1SJeff Kirsher {
12657707133cSSathya Perla 	struct be_mcc_wrb wrb = {0};
12669aebddd1SJeff Kirsher 	struct be_cmd_req_eth_tx_create *req;
126794d73aaaSVasundhara Volam 	struct be_queue_info *txq = &txo->q;
126894d73aaaSVasundhara Volam 	struct be_queue_info *cq = &txo->cq;
12699aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &txq->dma_mem;
127094d73aaaSVasundhara Volam 	int status, ver = 0;
12719aebddd1SJeff Kirsher 
12727707133cSSathya Perla 	req = embedded_payload(&wrb);
1273106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
12747707133cSSathya Perla 			       OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL);
12759aebddd1SJeff Kirsher 
12769aebddd1SJeff Kirsher 	if (lancer_chip(adapter)) {
12779aebddd1SJeff Kirsher 		req->hdr.version = 1;
127894d73aaaSVasundhara Volam 	} else if (BEx_chip(adapter)) {
127994d73aaaSVasundhara Volam 		if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC)
128094d73aaaSVasundhara Volam 			req->hdr.version = 2;
128194d73aaaSVasundhara Volam 	} else { /* For SH */
128294d73aaaSVasundhara Volam 		req->hdr.version = 2;
12839aebddd1SJeff Kirsher 	}
12849aebddd1SJeff Kirsher 
128581b02655SVasundhara Volam 	if (req->hdr.version > 0)
128681b02655SVasundhara Volam 		req->if_id = cpu_to_le16(adapter->if_handle);
12879aebddd1SJeff Kirsher 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
12889aebddd1SJeff Kirsher 	req->ulp_num = BE_ULP1_NUM;
12899aebddd1SJeff Kirsher 	req->type = BE_ETH_TX_RING_TYPE_STANDARD;
129094d73aaaSVasundhara Volam 	req->cq_id = cpu_to_le16(cq->id);
129194d73aaaSVasundhara Volam 	req->queue_size = be_encoded_q_len(txq->len);
12929aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
129394d73aaaSVasundhara Volam 	ver = req->hdr.version;
129494d73aaaSVasundhara Volam 
12957707133cSSathya Perla 	status = be_cmd_notify_wait(adapter, &wrb);
12969aebddd1SJeff Kirsher 	if (!status) {
12977707133cSSathya Perla 		struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb);
129803d28ffeSKalesh AP 
12999aebddd1SJeff Kirsher 		txq->id = le16_to_cpu(resp->cid);
130094d73aaaSVasundhara Volam 		if (ver == 2)
130194d73aaaSVasundhara Volam 			txo->db_offset = le32_to_cpu(resp->db_offset);
130294d73aaaSVasundhara Volam 		else
130394d73aaaSVasundhara Volam 			txo->db_offset = DB_TXULP1_OFFSET;
13049aebddd1SJeff Kirsher 		txq->created = true;
13059aebddd1SJeff Kirsher 	}
13069aebddd1SJeff Kirsher 
13079aebddd1SJeff Kirsher 	return status;
13089aebddd1SJeff Kirsher }
13099aebddd1SJeff Kirsher 
13109aebddd1SJeff Kirsher /* Uses MCC */
13119aebddd1SJeff Kirsher int be_cmd_rxq_create(struct be_adapter *adapter,
13129aebddd1SJeff Kirsher 		      struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
131310ef9ab4SSathya Perla 		      u32 if_id, u32 rss, u8 *rss_id)
13149aebddd1SJeff Kirsher {
13159aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
13169aebddd1SJeff Kirsher 	struct be_cmd_req_eth_rx_create *req;
13179aebddd1SJeff Kirsher 	struct be_dma_mem *q_mem = &rxq->dma_mem;
13189aebddd1SJeff Kirsher 	int status;
13199aebddd1SJeff Kirsher 
13209aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
13219aebddd1SJeff Kirsher 
13229aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
13239aebddd1SJeff Kirsher 	if (!wrb) {
13249aebddd1SJeff Kirsher 		status = -EBUSY;
13259aebddd1SJeff Kirsher 		goto err;
13269aebddd1SJeff Kirsher 	}
13279aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
13289aebddd1SJeff Kirsher 
1329106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1330106df1e3SSomnath Kotur 			       OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL);
13319aebddd1SJeff Kirsher 
13329aebddd1SJeff Kirsher 	req->cq_id = cpu_to_le16(cq_id);
13339aebddd1SJeff Kirsher 	req->frag_size = fls(frag_size) - 1;
13349aebddd1SJeff Kirsher 	req->num_pages = 2;
13359aebddd1SJeff Kirsher 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
13369aebddd1SJeff Kirsher 	req->interface_id = cpu_to_le32(if_id);
133710ef9ab4SSathya Perla 	req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE);
13389aebddd1SJeff Kirsher 	req->rss_queue = cpu_to_le32(rss);
13399aebddd1SJeff Kirsher 
13409aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
13419aebddd1SJeff Kirsher 	if (!status) {
13429aebddd1SJeff Kirsher 		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
134303d28ffeSKalesh AP 
13449aebddd1SJeff Kirsher 		rxq->id = le16_to_cpu(resp->id);
13459aebddd1SJeff Kirsher 		rxq->created = true;
13469aebddd1SJeff Kirsher 		*rss_id = resp->rss_id;
13479aebddd1SJeff Kirsher 	}
13489aebddd1SJeff Kirsher 
13499aebddd1SJeff Kirsher err:
13509aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
13519aebddd1SJeff Kirsher 	return status;
13529aebddd1SJeff Kirsher }
13539aebddd1SJeff Kirsher 
13549aebddd1SJeff Kirsher /* Generic destroyer function for all types of queues
13559aebddd1SJeff Kirsher  * Uses Mbox
13569aebddd1SJeff Kirsher  */
13579aebddd1SJeff Kirsher int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
13589aebddd1SJeff Kirsher 		     int queue_type)
13599aebddd1SJeff Kirsher {
13609aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
13619aebddd1SJeff Kirsher 	struct be_cmd_req_q_destroy *req;
13629aebddd1SJeff Kirsher 	u8 subsys = 0, opcode = 0;
13639aebddd1SJeff Kirsher 	int status;
13649aebddd1SJeff Kirsher 
13659aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
13669aebddd1SJeff Kirsher 		return -1;
13679aebddd1SJeff Kirsher 
13689aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
13699aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
13709aebddd1SJeff Kirsher 
13719aebddd1SJeff Kirsher 	switch (queue_type) {
13729aebddd1SJeff Kirsher 	case QTYPE_EQ:
13739aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
13749aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_EQ_DESTROY;
13759aebddd1SJeff Kirsher 		break;
13769aebddd1SJeff Kirsher 	case QTYPE_CQ:
13779aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
13789aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_CQ_DESTROY;
13799aebddd1SJeff Kirsher 		break;
13809aebddd1SJeff Kirsher 	case QTYPE_TXQ:
13819aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_ETH;
13829aebddd1SJeff Kirsher 		opcode = OPCODE_ETH_TX_DESTROY;
13839aebddd1SJeff Kirsher 		break;
13849aebddd1SJeff Kirsher 	case QTYPE_RXQ:
13859aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_ETH;
13869aebddd1SJeff Kirsher 		opcode = OPCODE_ETH_RX_DESTROY;
13879aebddd1SJeff Kirsher 		break;
13889aebddd1SJeff Kirsher 	case QTYPE_MCCQ:
13899aebddd1SJeff Kirsher 		subsys = CMD_SUBSYSTEM_COMMON;
13909aebddd1SJeff Kirsher 		opcode = OPCODE_COMMON_MCC_DESTROY;
13919aebddd1SJeff Kirsher 		break;
13929aebddd1SJeff Kirsher 	default:
13939aebddd1SJeff Kirsher 		BUG();
13949aebddd1SJeff Kirsher 	}
13959aebddd1SJeff Kirsher 
1396106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb,
1397106df1e3SSomnath Kotur 			       NULL);
13989aebddd1SJeff Kirsher 	req->id = cpu_to_le16(q->id);
13999aebddd1SJeff Kirsher 
14009aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
14019aebddd1SJeff Kirsher 	q->created = false;
14029aebddd1SJeff Kirsher 
14039aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
14049aebddd1SJeff Kirsher 	return status;
14059aebddd1SJeff Kirsher }
14069aebddd1SJeff Kirsher 
14079aebddd1SJeff Kirsher /* Uses MCC */
14089aebddd1SJeff Kirsher int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
14099aebddd1SJeff Kirsher {
14109aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
14119aebddd1SJeff Kirsher 	struct be_cmd_req_q_destroy *req;
14129aebddd1SJeff Kirsher 	int status;
14139aebddd1SJeff Kirsher 
14149aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
14159aebddd1SJeff Kirsher 
14169aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
14179aebddd1SJeff Kirsher 	if (!wrb) {
14189aebddd1SJeff Kirsher 		status = -EBUSY;
14199aebddd1SJeff Kirsher 		goto err;
14209aebddd1SJeff Kirsher 	}
14219aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
14229aebddd1SJeff Kirsher 
1423106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1424106df1e3SSomnath Kotur 			       OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL);
14259aebddd1SJeff Kirsher 	req->id = cpu_to_le16(q->id);
14269aebddd1SJeff Kirsher 
14279aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
14289aebddd1SJeff Kirsher 	q->created = false;
14299aebddd1SJeff Kirsher 
14309aebddd1SJeff Kirsher err:
14319aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
14329aebddd1SJeff Kirsher 	return status;
14339aebddd1SJeff Kirsher }
14349aebddd1SJeff Kirsher 
14359aebddd1SJeff Kirsher /* Create an rx filtering policy configuration on an i/f
1436bea50988SSathya Perla  * Will use MBOX only if MCCQ has not been created.
14379aebddd1SJeff Kirsher  */
14389aebddd1SJeff Kirsher int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
14391578e777SPadmanabh Ratnakar 		     u32 *if_handle, u32 domain)
14409aebddd1SJeff Kirsher {
1441bea50988SSathya Perla 	struct be_mcc_wrb wrb = {0};
14429aebddd1SJeff Kirsher 	struct be_cmd_req_if_create *req;
14439aebddd1SJeff Kirsher 	int status;
14449aebddd1SJeff Kirsher 
1445bea50988SSathya Perla 	req = embedded_payload(&wrb);
1446106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1447a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_INTERFACE_CREATE,
1448a2cc4e0bSSathya Perla 			       sizeof(*req), &wrb, NULL);
14499aebddd1SJeff Kirsher 	req->hdr.domain = domain;
14509aebddd1SJeff Kirsher 	req->capability_flags = cpu_to_le32(cap_flags);
14519aebddd1SJeff Kirsher 	req->enable_flags = cpu_to_le32(en_flags);
1452f9449ab7SSathya Perla 	req->pmac_invalid = true;
14539aebddd1SJeff Kirsher 
1454bea50988SSathya Perla 	status = be_cmd_notify_wait(adapter, &wrb);
14559aebddd1SJeff Kirsher 	if (!status) {
1456bea50988SSathya Perla 		struct be_cmd_resp_if_create *resp = embedded_payload(&wrb);
145703d28ffeSKalesh AP 
14589aebddd1SJeff Kirsher 		*if_handle = le32_to_cpu(resp->interface_id);
1459b5bb9776SSathya Perla 
1460b5bb9776SSathya Perla 		/* Hack to retrieve VF's pmac-id on BE3 */
1461b5bb9776SSathya Perla 		if (BE3_chip(adapter) && !be_physfn(adapter))
1462b5bb9776SSathya Perla 			adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id);
14639aebddd1SJeff Kirsher 	}
14649aebddd1SJeff Kirsher 	return status;
14659aebddd1SJeff Kirsher }
14669aebddd1SJeff Kirsher 
1467f9449ab7SSathya Perla /* Uses MCCQ */
146830128031SSathya Perla int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain)
14699aebddd1SJeff Kirsher {
14709aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
14719aebddd1SJeff Kirsher 	struct be_cmd_req_if_destroy *req;
14729aebddd1SJeff Kirsher 	int status;
14739aebddd1SJeff Kirsher 
147430128031SSathya Perla 	if (interface_id == -1)
1475f9449ab7SSathya Perla 		return 0;
14769aebddd1SJeff Kirsher 
1477f9449ab7SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
1478f9449ab7SSathya Perla 
1479f9449ab7SSathya Perla 	wrb = wrb_from_mccq(adapter);
1480f9449ab7SSathya Perla 	if (!wrb) {
1481f9449ab7SSathya Perla 		status = -EBUSY;
1482f9449ab7SSathya Perla 		goto err;
1483f9449ab7SSathya Perla 	}
14849aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
14859aebddd1SJeff Kirsher 
1486106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1487a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_INTERFACE_DESTROY,
1488a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
14899aebddd1SJeff Kirsher 	req->hdr.domain = domain;
14909aebddd1SJeff Kirsher 	req->interface_id = cpu_to_le32(interface_id);
14919aebddd1SJeff Kirsher 
1492f9449ab7SSathya Perla 	status = be_mcc_notify_wait(adapter);
1493f9449ab7SSathya Perla err:
1494f9449ab7SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
14959aebddd1SJeff Kirsher 	return status;
14969aebddd1SJeff Kirsher }
14979aebddd1SJeff Kirsher 
14989aebddd1SJeff Kirsher /* Get stats is a non embedded command: the request is not embedded inside
14999aebddd1SJeff Kirsher  * WRB but is a separate dma memory block
15009aebddd1SJeff Kirsher  * Uses asynchronous MCC
15019aebddd1SJeff Kirsher  */
15029aebddd1SJeff Kirsher int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
15039aebddd1SJeff Kirsher {
15049aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15059aebddd1SJeff Kirsher 	struct be_cmd_req_hdr *hdr;
15069aebddd1SJeff Kirsher 	int status = 0;
15079aebddd1SJeff Kirsher 
15089aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
15099aebddd1SJeff Kirsher 
15109aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
15119aebddd1SJeff Kirsher 	if (!wrb) {
15129aebddd1SJeff Kirsher 		status = -EBUSY;
15139aebddd1SJeff Kirsher 		goto err;
15149aebddd1SJeff Kirsher 	}
15159aebddd1SJeff Kirsher 	hdr = nonemb_cmd->va;
15169aebddd1SJeff Kirsher 
1517106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
1518a2cc4e0bSSathya Perla 			       OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb,
1519a2cc4e0bSSathya Perla 			       nonemb_cmd);
15209aebddd1SJeff Kirsher 
1521ca34fe38SSathya Perla 	/* version 1 of the cmd is not supported only by BE2 */
152261000861SAjit Khaparde 	if (BE2_chip(adapter))
152361000861SAjit Khaparde 		hdr->version = 0;
152461000861SAjit Khaparde 	if (BE3_chip(adapter) || lancer_chip(adapter))
15259aebddd1SJeff Kirsher 		hdr->version = 1;
152661000861SAjit Khaparde 	else
152761000861SAjit Khaparde 		hdr->version = 2;
15289aebddd1SJeff Kirsher 
15299aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
15309aebddd1SJeff Kirsher 	adapter->stats_cmd_sent = true;
15319aebddd1SJeff Kirsher 
15329aebddd1SJeff Kirsher err:
15339aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
15349aebddd1SJeff Kirsher 	return status;
15359aebddd1SJeff Kirsher }
15369aebddd1SJeff Kirsher 
15379aebddd1SJeff Kirsher /* Lancer Stats */
15389aebddd1SJeff Kirsher int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
15399aebddd1SJeff Kirsher 			       struct be_dma_mem *nonemb_cmd)
15409aebddd1SJeff Kirsher {
15419aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
15429aebddd1SJeff Kirsher 	struct lancer_cmd_req_pport_stats *req;
15439aebddd1SJeff Kirsher 	int status = 0;
15449aebddd1SJeff Kirsher 
1545f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
1546f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_ETH))
1547f25b119cSPadmanabh Ratnakar 		return -EPERM;
1548f25b119cSPadmanabh Ratnakar 
15499aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
15509aebddd1SJeff Kirsher 
15519aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
15529aebddd1SJeff Kirsher 	if (!wrb) {
15539aebddd1SJeff Kirsher 		status = -EBUSY;
15549aebddd1SJeff Kirsher 		goto err;
15559aebddd1SJeff Kirsher 	}
15569aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
15579aebddd1SJeff Kirsher 
1558106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
1559a2cc4e0bSSathya Perla 			       OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size,
1560a2cc4e0bSSathya Perla 			       wrb, nonemb_cmd);
15619aebddd1SJeff Kirsher 
1562d51ebd33SPadmanabh Ratnakar 	req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num);
15639aebddd1SJeff Kirsher 	req->cmd_params.params.reset_stats = 0;
15649aebddd1SJeff Kirsher 
15659aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
15669aebddd1SJeff Kirsher 	adapter->stats_cmd_sent = true;
15679aebddd1SJeff Kirsher 
15689aebddd1SJeff Kirsher err:
15699aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
15709aebddd1SJeff Kirsher 	return status;
15719aebddd1SJeff Kirsher }
15729aebddd1SJeff Kirsher 
1573323ff71eSSathya Perla static int be_mac_to_link_speed(int mac_speed)
1574323ff71eSSathya Perla {
1575323ff71eSSathya Perla 	switch (mac_speed) {
1576323ff71eSSathya Perla 	case PHY_LINK_SPEED_ZERO:
1577323ff71eSSathya Perla 		return 0;
1578323ff71eSSathya Perla 	case PHY_LINK_SPEED_10MBPS:
1579323ff71eSSathya Perla 		return 10;
1580323ff71eSSathya Perla 	case PHY_LINK_SPEED_100MBPS:
1581323ff71eSSathya Perla 		return 100;
1582323ff71eSSathya Perla 	case PHY_LINK_SPEED_1GBPS:
1583323ff71eSSathya Perla 		return 1000;
1584323ff71eSSathya Perla 	case PHY_LINK_SPEED_10GBPS:
1585323ff71eSSathya Perla 		return 10000;
1586b971f847SVasundhara Volam 	case PHY_LINK_SPEED_20GBPS:
1587b971f847SVasundhara Volam 		return 20000;
1588b971f847SVasundhara Volam 	case PHY_LINK_SPEED_25GBPS:
1589b971f847SVasundhara Volam 		return 25000;
1590b971f847SVasundhara Volam 	case PHY_LINK_SPEED_40GBPS:
1591b971f847SVasundhara Volam 		return 40000;
1592323ff71eSSathya Perla 	}
1593323ff71eSSathya Perla 	return 0;
1594323ff71eSSathya Perla }
1595323ff71eSSathya Perla 
1596323ff71eSSathya Perla /* Uses synchronous mcc
1597323ff71eSSathya Perla  * Returns link_speed in Mbps
1598323ff71eSSathya Perla  */
1599323ff71eSSathya Perla int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
1600323ff71eSSathya Perla 			     u8 *link_status, u32 dom)
16019aebddd1SJeff Kirsher {
16029aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
16039aebddd1SJeff Kirsher 	struct be_cmd_req_link_status *req;
16049aebddd1SJeff Kirsher 	int status;
16059aebddd1SJeff Kirsher 
16069aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16079aebddd1SJeff Kirsher 
1608b236916aSAjit Khaparde 	if (link_status)
1609b236916aSAjit Khaparde 		*link_status = LINK_DOWN;
1610b236916aSAjit Khaparde 
16119aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16129aebddd1SJeff Kirsher 	if (!wrb) {
16139aebddd1SJeff Kirsher 		status = -EBUSY;
16149aebddd1SJeff Kirsher 		goto err;
16159aebddd1SJeff Kirsher 	}
16169aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
16179aebddd1SJeff Kirsher 
161857cd80d4SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1619a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_LINK_STATUS_QUERY,
1620a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
162157cd80d4SPadmanabh Ratnakar 
1622ca34fe38SSathya Perla 	/* version 1 of the cmd is not supported only by BE2 */
1623ca34fe38SSathya Perla 	if (!BE2_chip(adapter))
1624daad6167SPadmanabh Ratnakar 		req->hdr.version = 1;
1625daad6167SPadmanabh Ratnakar 
162657cd80d4SPadmanabh Ratnakar 	req->hdr.domain = dom;
16279aebddd1SJeff Kirsher 
16289aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
16299aebddd1SJeff Kirsher 	if (!status) {
16309aebddd1SJeff Kirsher 		struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
163103d28ffeSKalesh AP 
1632323ff71eSSathya Perla 		if (link_speed) {
1633323ff71eSSathya Perla 			*link_speed = resp->link_speed ?
1634323ff71eSSathya Perla 				      le16_to_cpu(resp->link_speed) * 10 :
1635323ff71eSSathya Perla 				      be_mac_to_link_speed(resp->mac_speed);
1636323ff71eSSathya Perla 
1637323ff71eSSathya Perla 			if (!resp->logical_link_status)
1638323ff71eSSathya Perla 				*link_speed = 0;
16399aebddd1SJeff Kirsher 		}
1640b236916aSAjit Khaparde 		if (link_status)
1641b236916aSAjit Khaparde 			*link_status = resp->logical_link_status;
16429aebddd1SJeff Kirsher 	}
16439aebddd1SJeff Kirsher 
16449aebddd1SJeff Kirsher err:
16459aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
16469aebddd1SJeff Kirsher 	return status;
16479aebddd1SJeff Kirsher }
16489aebddd1SJeff Kirsher 
16499aebddd1SJeff Kirsher /* Uses synchronous mcc */
16509aebddd1SJeff Kirsher int be_cmd_get_die_temperature(struct be_adapter *adapter)
16519aebddd1SJeff Kirsher {
16529aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
16539aebddd1SJeff Kirsher 	struct be_cmd_req_get_cntl_addnl_attribs *req;
1654117affe3SVasundhara Volam 	int status = 0;
16559aebddd1SJeff Kirsher 
16569aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16579aebddd1SJeff Kirsher 
16589aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16599aebddd1SJeff Kirsher 	if (!wrb) {
16609aebddd1SJeff Kirsher 		status = -EBUSY;
16619aebddd1SJeff Kirsher 		goto err;
16629aebddd1SJeff Kirsher 	}
16639aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
16649aebddd1SJeff Kirsher 
1665106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1666a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES,
1667a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
16689aebddd1SJeff Kirsher 
16693de09455SSomnath Kotur 	be_mcc_notify(adapter);
16709aebddd1SJeff Kirsher 
16719aebddd1SJeff Kirsher err:
16729aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
16739aebddd1SJeff Kirsher 	return status;
16749aebddd1SJeff Kirsher }
16759aebddd1SJeff Kirsher 
16769aebddd1SJeff Kirsher /* Uses synchronous mcc */
16779aebddd1SJeff Kirsher int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size)
16789aebddd1SJeff Kirsher {
16799aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
16809aebddd1SJeff Kirsher 	struct be_cmd_req_get_fat *req;
16819aebddd1SJeff Kirsher 	int status;
16829aebddd1SJeff Kirsher 
16839aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
16849aebddd1SJeff Kirsher 
16859aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
16869aebddd1SJeff Kirsher 	if (!wrb) {
16879aebddd1SJeff Kirsher 		status = -EBUSY;
16889aebddd1SJeff Kirsher 		goto err;
16899aebddd1SJeff Kirsher 	}
16909aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
16919aebddd1SJeff Kirsher 
1692106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1693a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MANAGE_FAT, sizeof(*req), wrb,
1694a2cc4e0bSSathya Perla 			       NULL);
16959aebddd1SJeff Kirsher 	req->fat_operation = cpu_to_le32(QUERY_FAT);
16969aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
16979aebddd1SJeff Kirsher 	if (!status) {
16989aebddd1SJeff Kirsher 		struct be_cmd_resp_get_fat *resp = embedded_payload(wrb);
169903d28ffeSKalesh AP 
17009aebddd1SJeff Kirsher 		if (log_size && resp->log_size)
17019aebddd1SJeff Kirsher 			*log_size = le32_to_cpu(resp->log_size) -
17029aebddd1SJeff Kirsher 					sizeof(u32);
17039aebddd1SJeff Kirsher 	}
17049aebddd1SJeff Kirsher err:
17059aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
17069aebddd1SJeff Kirsher 	return status;
17079aebddd1SJeff Kirsher }
17089aebddd1SJeff Kirsher 
1709c5f156deSVasundhara Volam int be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf)
17109aebddd1SJeff Kirsher {
17119aebddd1SJeff Kirsher 	struct be_dma_mem get_fat_cmd;
17129aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
17139aebddd1SJeff Kirsher 	struct be_cmd_req_get_fat *req;
17149aebddd1SJeff Kirsher 	u32 offset = 0, total_size, buf_size,
17159aebddd1SJeff Kirsher 				log_offset = sizeof(u32), payload_len;
1716c5f156deSVasundhara Volam 	int status = 0;
17179aebddd1SJeff Kirsher 
17189aebddd1SJeff Kirsher 	if (buf_len == 0)
1719c5f156deSVasundhara Volam 		return -EIO;
17209aebddd1SJeff Kirsher 
17219aebddd1SJeff Kirsher 	total_size = buf_len;
17229aebddd1SJeff Kirsher 
17239aebddd1SJeff Kirsher 	get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
17249aebddd1SJeff Kirsher 	get_fat_cmd.va = pci_alloc_consistent(adapter->pdev,
17259aebddd1SJeff Kirsher 					      get_fat_cmd.size,
17269aebddd1SJeff Kirsher 					      &get_fat_cmd.dma);
17279aebddd1SJeff Kirsher 	if (!get_fat_cmd.va) {
17289aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev,
1729cd3307aaSKalesh AP 			"Memory allocation failure while reading FAT data\n");
1730c5f156deSVasundhara Volam 		return -ENOMEM;
17319aebddd1SJeff Kirsher 	}
17329aebddd1SJeff Kirsher 
17339aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
17349aebddd1SJeff Kirsher 
17359aebddd1SJeff Kirsher 	while (total_size) {
17369aebddd1SJeff Kirsher 		buf_size = min(total_size, (u32)60*1024);
17379aebddd1SJeff Kirsher 		total_size -= buf_size;
17389aebddd1SJeff Kirsher 
17399aebddd1SJeff Kirsher 		wrb = wrb_from_mccq(adapter);
17409aebddd1SJeff Kirsher 		if (!wrb) {
17419aebddd1SJeff Kirsher 			status = -EBUSY;
17429aebddd1SJeff Kirsher 			goto err;
17439aebddd1SJeff Kirsher 		}
17449aebddd1SJeff Kirsher 		req = get_fat_cmd.va;
17459aebddd1SJeff Kirsher 
17469aebddd1SJeff Kirsher 		payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size;
1747106df1e3SSomnath Kotur 		be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1748a2cc4e0bSSathya Perla 				       OPCODE_COMMON_MANAGE_FAT, payload_len,
1749a2cc4e0bSSathya Perla 				       wrb, &get_fat_cmd);
17509aebddd1SJeff Kirsher 
17519aebddd1SJeff Kirsher 		req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
17529aebddd1SJeff Kirsher 		req->read_log_offset = cpu_to_le32(log_offset);
17539aebddd1SJeff Kirsher 		req->read_log_length = cpu_to_le32(buf_size);
17549aebddd1SJeff Kirsher 		req->data_buffer_size = cpu_to_le32(buf_size);
17559aebddd1SJeff Kirsher 
17569aebddd1SJeff Kirsher 		status = be_mcc_notify_wait(adapter);
17579aebddd1SJeff Kirsher 		if (!status) {
17589aebddd1SJeff Kirsher 			struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
175903d28ffeSKalesh AP 
17609aebddd1SJeff Kirsher 			memcpy(buf + offset,
17619aebddd1SJeff Kirsher 			       resp->data_buffer,
176292aa9214SSomnath Kotur 			       le32_to_cpu(resp->read_log_length));
17639aebddd1SJeff Kirsher 		} else {
17649aebddd1SJeff Kirsher 			dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
17659aebddd1SJeff Kirsher 			goto err;
17669aebddd1SJeff Kirsher 		}
17679aebddd1SJeff Kirsher 		offset += buf_size;
17689aebddd1SJeff Kirsher 		log_offset += buf_size;
17699aebddd1SJeff Kirsher 	}
17709aebddd1SJeff Kirsher err:
17719aebddd1SJeff Kirsher 	pci_free_consistent(adapter->pdev, get_fat_cmd.size,
1772a2cc4e0bSSathya Perla 			    get_fat_cmd.va, get_fat_cmd.dma);
17739aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1774c5f156deSVasundhara Volam 	return status;
17759aebddd1SJeff Kirsher }
17769aebddd1SJeff Kirsher 
177704b71175SSathya Perla /* Uses synchronous mcc */
1778e97e3cdaSKalesh AP int be_cmd_get_fw_ver(struct be_adapter *adapter)
17799aebddd1SJeff Kirsher {
17809aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
17819aebddd1SJeff Kirsher 	struct be_cmd_req_get_fw_version *req;
17829aebddd1SJeff Kirsher 	int status;
17839aebddd1SJeff Kirsher 
178404b71175SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
17859aebddd1SJeff Kirsher 
178604b71175SSathya Perla 	wrb = wrb_from_mccq(adapter);
178704b71175SSathya Perla 	if (!wrb) {
178804b71175SSathya Perla 		status = -EBUSY;
178904b71175SSathya Perla 		goto err;
179004b71175SSathya Perla 	}
179104b71175SSathya Perla 
17929aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
17939aebddd1SJeff Kirsher 
1794106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1795a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb,
1796a2cc4e0bSSathya Perla 			       NULL);
179704b71175SSathya Perla 	status = be_mcc_notify_wait(adapter);
17989aebddd1SJeff Kirsher 	if (!status) {
17999aebddd1SJeff Kirsher 		struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
1800acbafeb1SSathya Perla 
1801242eb470SVasundhara Volam 		strlcpy(adapter->fw_ver, resp->firmware_version_string,
1802242eb470SVasundhara Volam 			sizeof(adapter->fw_ver));
1803242eb470SVasundhara Volam 		strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string,
1804242eb470SVasundhara Volam 			sizeof(adapter->fw_on_flash));
18059aebddd1SJeff Kirsher 	}
180604b71175SSathya Perla err:
180704b71175SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
18089aebddd1SJeff Kirsher 	return status;
18099aebddd1SJeff Kirsher }
18109aebddd1SJeff Kirsher 
18119aebddd1SJeff Kirsher /* set the EQ delay interval of an EQ to specified value
18129aebddd1SJeff Kirsher  * Uses async mcc
18139aebddd1SJeff Kirsher  */
1814b502ae8dSKalesh AP static int __be_cmd_modify_eqd(struct be_adapter *adapter,
1815b502ae8dSKalesh AP 			       struct be_set_eqd *set_eqd, int num)
18169aebddd1SJeff Kirsher {
18179aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
18189aebddd1SJeff Kirsher 	struct be_cmd_req_modify_eq_delay *req;
18192632bafdSSathya Perla 	int status = 0, i;
18209aebddd1SJeff Kirsher 
18219aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
18229aebddd1SJeff Kirsher 
18239aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
18249aebddd1SJeff Kirsher 	if (!wrb) {
18259aebddd1SJeff Kirsher 		status = -EBUSY;
18269aebddd1SJeff Kirsher 		goto err;
18279aebddd1SJeff Kirsher 	}
18289aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
18299aebddd1SJeff Kirsher 
1830106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1831a2cc4e0bSSathya Perla 			       OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb,
1832a2cc4e0bSSathya Perla 			       NULL);
18339aebddd1SJeff Kirsher 
18342632bafdSSathya Perla 	req->num_eq = cpu_to_le32(num);
18352632bafdSSathya Perla 	for (i = 0; i < num; i++) {
18362632bafdSSathya Perla 		req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
18372632bafdSSathya Perla 		req->set_eqd[i].phase = 0;
18382632bafdSSathya Perla 		req->set_eqd[i].delay_multiplier =
18392632bafdSSathya Perla 				cpu_to_le32(set_eqd[i].delay_multiplier);
18402632bafdSSathya Perla 	}
18419aebddd1SJeff Kirsher 
18429aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
18439aebddd1SJeff Kirsher err:
18449aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
18459aebddd1SJeff Kirsher 	return status;
18469aebddd1SJeff Kirsher }
18479aebddd1SJeff Kirsher 
184893676703SKalesh AP int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd,
184993676703SKalesh AP 		      int num)
185093676703SKalesh AP {
185193676703SKalesh AP 	int num_eqs, i = 0;
185293676703SKalesh AP 
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 
186093676703SKalesh AP 	return 0;
186193676703SKalesh AP }
186293676703SKalesh AP 
18639aebddd1SJeff Kirsher /* Uses sycnhronous mcc */
18649aebddd1SJeff Kirsher int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
1865435452aaSVasundhara Volam 		       u32 num, u32 domain)
18669aebddd1SJeff Kirsher {
18679aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
18689aebddd1SJeff Kirsher 	struct be_cmd_req_vlan_config *req;
18699aebddd1SJeff Kirsher 	int status;
18709aebddd1SJeff Kirsher 
18719aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
18729aebddd1SJeff Kirsher 
18739aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
18749aebddd1SJeff Kirsher 	if (!wrb) {
18759aebddd1SJeff Kirsher 		status = -EBUSY;
18769aebddd1SJeff Kirsher 		goto err;
18779aebddd1SJeff Kirsher 	}
18789aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
18799aebddd1SJeff Kirsher 
1880106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1881a2cc4e0bSSathya Perla 			       OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req),
1882a2cc4e0bSSathya Perla 			       wrb, NULL);
1883435452aaSVasundhara Volam 	req->hdr.domain = domain;
18849aebddd1SJeff Kirsher 
18859aebddd1SJeff Kirsher 	req->interface_id = if_id;
1886012bd387SAjit Khaparde 	req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0;
18879aebddd1SJeff Kirsher 	req->num_vlan = num;
18889aebddd1SJeff Kirsher 	memcpy(req->normal_vlan, vtag_array,
18899aebddd1SJeff Kirsher 	       req->num_vlan * sizeof(vtag_array[0]));
18909aebddd1SJeff Kirsher 
18919aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
18929aebddd1SJeff Kirsher err:
18939aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
18949aebddd1SJeff Kirsher 	return status;
18959aebddd1SJeff Kirsher }
18969aebddd1SJeff Kirsher 
1897ac34b743SSathya Perla static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
18989aebddd1SJeff Kirsher {
18999aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
19009aebddd1SJeff Kirsher 	struct be_dma_mem *mem = &adapter->rx_filter;
19019aebddd1SJeff Kirsher 	struct be_cmd_req_rx_filter *req = mem->va;
19029aebddd1SJeff Kirsher 	int status;
19039aebddd1SJeff Kirsher 
19049aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
19059aebddd1SJeff Kirsher 
19069aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
19079aebddd1SJeff Kirsher 	if (!wrb) {
19089aebddd1SJeff Kirsher 		status = -EBUSY;
19099aebddd1SJeff Kirsher 		goto err;
19109aebddd1SJeff Kirsher 	}
19119aebddd1SJeff Kirsher 	memset(req, 0, sizeof(*req));
1912106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1913106df1e3SSomnath Kotur 			       OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req),
1914106df1e3SSomnath Kotur 			       wrb, mem);
19159aebddd1SJeff Kirsher 
19169aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(adapter->if_handle);
1917ac34b743SSathya Perla 	req->if_flags_mask = cpu_to_le32(flags);
1918ac34b743SSathya Perla 	req->if_flags = (value == ON) ? req->if_flags_mask : 0;
1919d9d604f8SAjit Khaparde 
1920ac34b743SSathya Perla 	if (flags & BE_IF_FLAGS_MULTICAST) {
19219aebddd1SJeff Kirsher 		struct netdev_hw_addr *ha;
19229aebddd1SJeff Kirsher 		int i = 0;
19239aebddd1SJeff Kirsher 
19241610c79fSPadmanabh Ratnakar 		/* Reset mcast promisc mode if already set by setting mask
19251610c79fSPadmanabh Ratnakar 		 * and not setting flags field
19261610c79fSPadmanabh Ratnakar 		 */
19271610c79fSPadmanabh Ratnakar 		req->if_flags_mask |=
1928abb93951SPadmanabh Ratnakar 			cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
192992bf14abSSathya Perla 				    be_if_cap_flags(adapter));
1930016f97b1SPadmanabh Ratnakar 		req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev));
19319aebddd1SJeff Kirsher 		netdev_for_each_mc_addr(ha, adapter->netdev)
19329aebddd1SJeff Kirsher 			memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN);
19339aebddd1SJeff Kirsher 	}
19349aebddd1SJeff Kirsher 
19359aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
19369aebddd1SJeff Kirsher err:
19379aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
19389aebddd1SJeff Kirsher 	return status;
19399aebddd1SJeff Kirsher }
19409aebddd1SJeff Kirsher 
1941ac34b743SSathya Perla int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
1942ac34b743SSathya Perla {
1943ac34b743SSathya Perla 	struct device *dev = &adapter->pdev->dev;
1944ac34b743SSathya Perla 
1945ac34b743SSathya Perla 	if ((flags & be_if_cap_flags(adapter)) != flags) {
1946ac34b743SSathya Perla 		dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags);
1947ac34b743SSathya Perla 		dev_warn(dev, "Interface is capable of 0x%x flags only\n",
1948ac34b743SSathya Perla 			 be_if_cap_flags(adapter));
1949ac34b743SSathya Perla 	}
1950ac34b743SSathya Perla 	flags &= be_if_cap_flags(adapter);
1951ac34b743SSathya Perla 
1952ac34b743SSathya Perla 	return __be_cmd_rx_filter(adapter, flags, value);
1953ac34b743SSathya Perla }
1954ac34b743SSathya Perla 
19559aebddd1SJeff Kirsher /* Uses synchrounous mcc */
19569aebddd1SJeff Kirsher int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
19579aebddd1SJeff Kirsher {
19589aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
19599aebddd1SJeff Kirsher 	struct be_cmd_req_set_flow_control *req;
19609aebddd1SJeff Kirsher 	int status;
19619aebddd1SJeff Kirsher 
1962f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
1963f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
1964f25b119cSPadmanabh Ratnakar 		return -EPERM;
1965f25b119cSPadmanabh Ratnakar 
19669aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
19679aebddd1SJeff Kirsher 
19689aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
19699aebddd1SJeff Kirsher 	if (!wrb) {
19709aebddd1SJeff Kirsher 		status = -EBUSY;
19719aebddd1SJeff Kirsher 		goto err;
19729aebddd1SJeff Kirsher 	}
19739aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
19749aebddd1SJeff Kirsher 
1975106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1976a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req),
1977a2cc4e0bSSathya Perla 			       wrb, NULL);
19789aebddd1SJeff Kirsher 
1979b29812c1SSuresh Reddy 	req->hdr.version = 1;
19809aebddd1SJeff Kirsher 	req->tx_flow_control = cpu_to_le16((u16)tx_fc);
19819aebddd1SJeff Kirsher 	req->rx_flow_control = cpu_to_le16((u16)rx_fc);
19829aebddd1SJeff Kirsher 
19839aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
19849aebddd1SJeff Kirsher 
19859aebddd1SJeff Kirsher err:
19869aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
1987b29812c1SSuresh Reddy 
1988b29812c1SSuresh Reddy 	if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED)
1989b29812c1SSuresh Reddy 		return  -EOPNOTSUPP;
1990b29812c1SSuresh Reddy 
19919aebddd1SJeff Kirsher 	return status;
19929aebddd1SJeff Kirsher }
19939aebddd1SJeff Kirsher 
19949aebddd1SJeff Kirsher /* Uses sycn mcc */
19959aebddd1SJeff Kirsher int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
19969aebddd1SJeff Kirsher {
19979aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
19989aebddd1SJeff Kirsher 	struct be_cmd_req_get_flow_control *req;
19999aebddd1SJeff Kirsher 	int status;
20009aebddd1SJeff Kirsher 
2001f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
2002f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
2003f25b119cSPadmanabh Ratnakar 		return -EPERM;
2004f25b119cSPadmanabh Ratnakar 
20059aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
20069aebddd1SJeff Kirsher 
20079aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
20089aebddd1SJeff Kirsher 	if (!wrb) {
20099aebddd1SJeff Kirsher 		status = -EBUSY;
20109aebddd1SJeff Kirsher 		goto err;
20119aebddd1SJeff Kirsher 	}
20129aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20139aebddd1SJeff Kirsher 
2014106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2015a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req),
2016a2cc4e0bSSathya Perla 			       wrb, NULL);
20179aebddd1SJeff Kirsher 
20189aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
20199aebddd1SJeff Kirsher 	if (!status) {
20209aebddd1SJeff Kirsher 		struct be_cmd_resp_get_flow_control *resp =
20219aebddd1SJeff Kirsher 						embedded_payload(wrb);
202203d28ffeSKalesh AP 
20239aebddd1SJeff Kirsher 		*tx_fc = le16_to_cpu(resp->tx_flow_control);
20249aebddd1SJeff Kirsher 		*rx_fc = le16_to_cpu(resp->rx_flow_control);
20259aebddd1SJeff Kirsher 	}
20269aebddd1SJeff Kirsher 
20279aebddd1SJeff Kirsher err:
20289aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
20299aebddd1SJeff Kirsher 	return status;
20309aebddd1SJeff Kirsher }
20319aebddd1SJeff Kirsher 
20329aebddd1SJeff Kirsher /* Uses mbox */
2033e97e3cdaSKalesh AP int be_cmd_query_fw_cfg(struct be_adapter *adapter)
20349aebddd1SJeff Kirsher {
20359aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20369aebddd1SJeff Kirsher 	struct be_cmd_req_query_fw_cfg *req;
20379aebddd1SJeff Kirsher 	int status;
20389aebddd1SJeff Kirsher 
20399aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
20409aebddd1SJeff Kirsher 		return -1;
20419aebddd1SJeff Kirsher 
20429aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
20439aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20449aebddd1SJeff Kirsher 
2045106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2046a2cc4e0bSSathya Perla 			       OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
2047a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
20489aebddd1SJeff Kirsher 
20499aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
20509aebddd1SJeff Kirsher 	if (!status) {
20519aebddd1SJeff Kirsher 		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
205203d28ffeSKalesh AP 
2053e97e3cdaSKalesh AP 		adapter->port_num = le32_to_cpu(resp->phys_port);
2054e97e3cdaSKalesh AP 		adapter->function_mode = le32_to_cpu(resp->function_mode);
2055e97e3cdaSKalesh AP 		adapter->function_caps = le32_to_cpu(resp->function_caps);
2056e97e3cdaSKalesh AP 		adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
2057acbafeb1SSathya Perla 		dev_info(&adapter->pdev->dev,
2058acbafeb1SSathya Perla 			 "FW config: function_mode=0x%x, function_caps=0x%x\n",
2059acbafeb1SSathya Perla 			 adapter->function_mode, adapter->function_caps);
20609aebddd1SJeff Kirsher 	}
20619aebddd1SJeff Kirsher 
20629aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
20639aebddd1SJeff Kirsher 	return status;
20649aebddd1SJeff Kirsher }
20659aebddd1SJeff Kirsher 
20669aebddd1SJeff Kirsher /* Uses mbox */
20679aebddd1SJeff Kirsher int be_cmd_reset_function(struct be_adapter *adapter)
20689aebddd1SJeff Kirsher {
20699aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
20709aebddd1SJeff Kirsher 	struct be_cmd_req_hdr *req;
20719aebddd1SJeff Kirsher 	int status;
20729aebddd1SJeff Kirsher 
2073bf99e50dSPadmanabh Ratnakar 	if (lancer_chip(adapter)) {
2074bf99e50dSPadmanabh Ratnakar 		iowrite32(SLI_PORT_CONTROL_IP_MASK,
2075bf99e50dSPadmanabh Ratnakar 			  adapter->db + SLIPORT_CONTROL_OFFSET);
20769fa465c0SSathya Perla 		status = lancer_wait_ready(adapter);
20779fa465c0SSathya Perla 		if (status)
2078bf99e50dSPadmanabh Ratnakar 			dev_err(&adapter->pdev->dev,
2079bf99e50dSPadmanabh Ratnakar 				"Adapter in non recoverable error\n");
2080bf99e50dSPadmanabh Ratnakar 		return status;
2081bf99e50dSPadmanabh Ratnakar 	}
2082bf99e50dSPadmanabh Ratnakar 
20839aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
20849aebddd1SJeff Kirsher 		return -1;
20859aebddd1SJeff Kirsher 
20869aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
20879aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
20889aebddd1SJeff Kirsher 
2089106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
2090a2cc4e0bSSathya Perla 			       OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb,
2091a2cc4e0bSSathya Perla 			       NULL);
20929aebddd1SJeff Kirsher 
20939aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
20949aebddd1SJeff Kirsher 
20959aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
20969aebddd1SJeff Kirsher 	return status;
20979aebddd1SJeff Kirsher }
20989aebddd1SJeff Kirsher 
2099594ad54aSSuresh Reddy int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
210033cb0fa7SBen Hutchings 		      u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey)
21019aebddd1SJeff Kirsher {
21029aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21039aebddd1SJeff Kirsher 	struct be_cmd_req_rss_config *req;
21049aebddd1SJeff Kirsher 	int status;
21059aebddd1SJeff Kirsher 
2106da1388d6SVasundhara Volam 	if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
2107da1388d6SVasundhara Volam 		return 0;
2108da1388d6SVasundhara Volam 
2109b51aa367SKalesh AP 	spin_lock_bh(&adapter->mcc_lock);
21109aebddd1SJeff Kirsher 
2111b51aa367SKalesh AP 	wrb = wrb_from_mccq(adapter);
2112b51aa367SKalesh AP 	if (!wrb) {
2113b51aa367SKalesh AP 		status = -EBUSY;
2114b51aa367SKalesh AP 		goto err;
2115b51aa367SKalesh AP 	}
21169aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21179aebddd1SJeff Kirsher 
2118106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
2119106df1e3SSomnath Kotur 			       OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
21209aebddd1SJeff Kirsher 
21219aebddd1SJeff Kirsher 	req->if_id = cpu_to_le32(adapter->if_handle);
2122594ad54aSSuresh Reddy 	req->enable_rss = cpu_to_le16(rss_hash_opts);
21239aebddd1SJeff Kirsher 	req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
2124594ad54aSSuresh Reddy 
2125b51aa367SKalesh AP 	if (!BEx_chip(adapter))
2126594ad54aSSuresh Reddy 		req->hdr.version = 1;
2127594ad54aSSuresh Reddy 
21289aebddd1SJeff Kirsher 	memcpy(req->cpu_table, rsstable, table_size);
2129e2557877SVenkata Duvvuru 	memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN);
21309aebddd1SJeff Kirsher 	be_dws_cpu_to_le(req->hash, sizeof(req->hash));
21319aebddd1SJeff Kirsher 
2132b51aa367SKalesh AP 	status = be_mcc_notify_wait(adapter);
2133b51aa367SKalesh AP err:
2134b51aa367SKalesh AP 	spin_unlock_bh(&adapter->mcc_lock);
21359aebddd1SJeff Kirsher 	return status;
21369aebddd1SJeff Kirsher }
21379aebddd1SJeff Kirsher 
21389aebddd1SJeff Kirsher /* Uses sync mcc */
21399aebddd1SJeff Kirsher int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
21409aebddd1SJeff Kirsher 			    u8 bcn, u8 sts, u8 state)
21419aebddd1SJeff Kirsher {
21429aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21439aebddd1SJeff Kirsher 	struct be_cmd_req_enable_disable_beacon *req;
21449aebddd1SJeff Kirsher 	int status;
21459aebddd1SJeff Kirsher 
21469aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
21479aebddd1SJeff Kirsher 
21489aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
21499aebddd1SJeff Kirsher 	if (!wrb) {
21509aebddd1SJeff Kirsher 		status = -EBUSY;
21519aebddd1SJeff Kirsher 		goto err;
21529aebddd1SJeff Kirsher 	}
21539aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21549aebddd1SJeff Kirsher 
2155106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2156a2cc4e0bSSathya Perla 			       OPCODE_COMMON_ENABLE_DISABLE_BEACON,
2157a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
21589aebddd1SJeff Kirsher 
21599aebddd1SJeff Kirsher 	req->port_num = port_num;
21609aebddd1SJeff Kirsher 	req->beacon_state = state;
21619aebddd1SJeff Kirsher 	req->beacon_duration = bcn;
21629aebddd1SJeff Kirsher 	req->status_duration = sts;
21639aebddd1SJeff Kirsher 
21649aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
21659aebddd1SJeff Kirsher 
21669aebddd1SJeff Kirsher err:
21679aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
21689aebddd1SJeff Kirsher 	return status;
21699aebddd1SJeff Kirsher }
21709aebddd1SJeff Kirsher 
21719aebddd1SJeff Kirsher /* Uses sync mcc */
21729aebddd1SJeff Kirsher int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
21739aebddd1SJeff Kirsher {
21749aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
21759aebddd1SJeff Kirsher 	struct be_cmd_req_get_beacon_state *req;
21769aebddd1SJeff Kirsher 	int status;
21779aebddd1SJeff Kirsher 
21789aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
21799aebddd1SJeff Kirsher 
21809aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
21819aebddd1SJeff Kirsher 	if (!wrb) {
21829aebddd1SJeff Kirsher 		status = -EBUSY;
21839aebddd1SJeff Kirsher 		goto err;
21849aebddd1SJeff Kirsher 	}
21859aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
21869aebddd1SJeff Kirsher 
2187106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2188a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req),
2189a2cc4e0bSSathya Perla 			       wrb, NULL);
21909aebddd1SJeff Kirsher 
21919aebddd1SJeff Kirsher 	req->port_num = port_num;
21929aebddd1SJeff Kirsher 
21939aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
21949aebddd1SJeff Kirsher 	if (!status) {
21959aebddd1SJeff Kirsher 		struct be_cmd_resp_get_beacon_state *resp =
21969aebddd1SJeff Kirsher 						embedded_payload(wrb);
219703d28ffeSKalesh AP 
21989aebddd1SJeff Kirsher 		*state = resp->beacon_state;
21999aebddd1SJeff Kirsher 	}
22009aebddd1SJeff Kirsher 
22019aebddd1SJeff Kirsher err:
22029aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
22039aebddd1SJeff Kirsher 	return status;
22049aebddd1SJeff Kirsher }
22059aebddd1SJeff Kirsher 
2206e36edd9dSMark Leonard /* Uses sync mcc */
2207e36edd9dSMark Leonard int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
2208e36edd9dSMark Leonard 				      u8 page_num, u8 *data)
2209e36edd9dSMark Leonard {
2210e36edd9dSMark Leonard 	struct be_dma_mem cmd;
2211e36edd9dSMark Leonard 	struct be_mcc_wrb *wrb;
2212e36edd9dSMark Leonard 	struct be_cmd_req_port_type *req;
2213e36edd9dSMark Leonard 	int status;
2214e36edd9dSMark Leonard 
2215e36edd9dSMark Leonard 	if (page_num > TR_PAGE_A2)
2216e36edd9dSMark Leonard 		return -EINVAL;
2217e36edd9dSMark Leonard 
2218e36edd9dSMark Leonard 	cmd.size = sizeof(struct be_cmd_resp_port_type);
2219e36edd9dSMark Leonard 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
2220e36edd9dSMark Leonard 	if (!cmd.va) {
2221e36edd9dSMark Leonard 		dev_err(&adapter->pdev->dev, "Memory allocation failed\n");
2222e36edd9dSMark Leonard 		return -ENOMEM;
2223e36edd9dSMark Leonard 	}
2224e36edd9dSMark Leonard 	memset(cmd.va, 0, cmd.size);
2225e36edd9dSMark Leonard 
2226e36edd9dSMark Leonard 	spin_lock_bh(&adapter->mcc_lock);
2227e36edd9dSMark Leonard 
2228e36edd9dSMark Leonard 	wrb = wrb_from_mccq(adapter);
2229e36edd9dSMark Leonard 	if (!wrb) {
2230e36edd9dSMark Leonard 		status = -EBUSY;
2231e36edd9dSMark Leonard 		goto err;
2232e36edd9dSMark Leonard 	}
2233e36edd9dSMark Leonard 	req = cmd.va;
2234e36edd9dSMark Leonard 
2235e36edd9dSMark Leonard 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2236e36edd9dSMark Leonard 			       OPCODE_COMMON_READ_TRANSRECV_DATA,
2237e36edd9dSMark Leonard 			       cmd.size, wrb, &cmd);
2238e36edd9dSMark Leonard 
2239e36edd9dSMark Leonard 	req->port = cpu_to_le32(adapter->hba_port_num);
2240e36edd9dSMark Leonard 	req->page_num = cpu_to_le32(page_num);
2241e36edd9dSMark Leonard 	status = be_mcc_notify_wait(adapter);
2242e36edd9dSMark Leonard 	if (!status) {
2243e36edd9dSMark Leonard 		struct be_cmd_resp_port_type *resp = cmd.va;
2244e36edd9dSMark Leonard 
2245e36edd9dSMark Leonard 		memcpy(data, resp->page_data, PAGE_DATA_LEN);
2246e36edd9dSMark Leonard 	}
2247e36edd9dSMark Leonard err:
2248e36edd9dSMark Leonard 	spin_unlock_bh(&adapter->mcc_lock);
2249e36edd9dSMark Leonard 	pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
2250e36edd9dSMark Leonard 	return status;
2251e36edd9dSMark Leonard }
2252e36edd9dSMark Leonard 
22539aebddd1SJeff Kirsher int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
2254f67ef7baSPadmanabh Ratnakar 			    u32 data_size, u32 data_offset,
2255f67ef7baSPadmanabh Ratnakar 			    const char *obj_name, u32 *data_written,
2256f67ef7baSPadmanabh Ratnakar 			    u8 *change_status, u8 *addn_status)
22579aebddd1SJeff Kirsher {
22589aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
22599aebddd1SJeff Kirsher 	struct lancer_cmd_req_write_object *req;
22609aebddd1SJeff Kirsher 	struct lancer_cmd_resp_write_object *resp;
22619aebddd1SJeff Kirsher 	void *ctxt = NULL;
22629aebddd1SJeff Kirsher 	int status;
22639aebddd1SJeff Kirsher 
22649aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
22659aebddd1SJeff Kirsher 	adapter->flash_status = 0;
22669aebddd1SJeff Kirsher 
22679aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
22689aebddd1SJeff Kirsher 	if (!wrb) {
22699aebddd1SJeff Kirsher 		status = -EBUSY;
22709aebddd1SJeff Kirsher 		goto err_unlock;
22719aebddd1SJeff Kirsher 	}
22729aebddd1SJeff Kirsher 
22739aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
22749aebddd1SJeff Kirsher 
2275106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
22769aebddd1SJeff Kirsher 			       OPCODE_COMMON_WRITE_OBJECT,
2277106df1e3SSomnath Kotur 			       sizeof(struct lancer_cmd_req_write_object), wrb,
2278106df1e3SSomnath Kotur 			       NULL);
22799aebddd1SJeff Kirsher 
22809aebddd1SJeff Kirsher 	ctxt = &req->context;
22819aebddd1SJeff Kirsher 	AMAP_SET_BITS(struct amap_lancer_write_obj_context,
22829aebddd1SJeff Kirsher 		      write_length, ctxt, data_size);
22839aebddd1SJeff Kirsher 
22849aebddd1SJeff Kirsher 	if (data_size == 0)
22859aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
22869aebddd1SJeff Kirsher 			      eof, ctxt, 1);
22879aebddd1SJeff Kirsher 	else
22889aebddd1SJeff Kirsher 		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
22899aebddd1SJeff Kirsher 			      eof, ctxt, 0);
22909aebddd1SJeff Kirsher 
22919aebddd1SJeff Kirsher 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
22929aebddd1SJeff Kirsher 	req->write_offset = cpu_to_le32(data_offset);
2293242eb470SVasundhara Volam 	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
22949aebddd1SJeff Kirsher 	req->descriptor_count = cpu_to_le32(1);
22959aebddd1SJeff Kirsher 	req->buf_len = cpu_to_le32(data_size);
22969aebddd1SJeff Kirsher 	req->addr_low = cpu_to_le32((cmd->dma +
22979aebddd1SJeff Kirsher 				     sizeof(struct lancer_cmd_req_write_object))
22989aebddd1SJeff Kirsher 				    & 0xFFFFFFFF);
22999aebddd1SJeff Kirsher 	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma +
23009aebddd1SJeff Kirsher 				sizeof(struct lancer_cmd_req_write_object)));
23019aebddd1SJeff Kirsher 
23029aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
23039aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
23049aebddd1SJeff Kirsher 
23055eeff635SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
2306701962d0SSomnath Kotur 					 msecs_to_jiffies(60000)))
2307fd45160cSKalesh AP 		status = -ETIMEDOUT;
23089aebddd1SJeff Kirsher 	else
23099aebddd1SJeff Kirsher 		status = adapter->flash_status;
23109aebddd1SJeff Kirsher 
23119aebddd1SJeff Kirsher 	resp = embedded_payload(wrb);
2312f67ef7baSPadmanabh Ratnakar 	if (!status) {
23139aebddd1SJeff Kirsher 		*data_written = le32_to_cpu(resp->actual_write_len);
2314f67ef7baSPadmanabh Ratnakar 		*change_status = resp->change_status;
2315f67ef7baSPadmanabh Ratnakar 	} else {
23169aebddd1SJeff Kirsher 		*addn_status = resp->additional_status;
2317f67ef7baSPadmanabh Ratnakar 	}
23189aebddd1SJeff Kirsher 
23199aebddd1SJeff Kirsher 	return status;
23209aebddd1SJeff Kirsher 
23219aebddd1SJeff Kirsher err_unlock:
23229aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
23239aebddd1SJeff Kirsher 	return status;
23249aebddd1SJeff Kirsher }
23259aebddd1SJeff Kirsher 
23266809cee0SRavikumar Nelavelli int be_cmd_query_cable_type(struct be_adapter *adapter)
23276809cee0SRavikumar Nelavelli {
23286809cee0SRavikumar Nelavelli 	u8 page_data[PAGE_DATA_LEN];
23296809cee0SRavikumar Nelavelli 	int status;
23306809cee0SRavikumar Nelavelli 
23316809cee0SRavikumar Nelavelli 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
23326809cee0SRavikumar Nelavelli 						   page_data);
23336809cee0SRavikumar Nelavelli 	if (!status) {
23346809cee0SRavikumar Nelavelli 		switch (adapter->phy.interface_type) {
23356809cee0SRavikumar Nelavelli 		case PHY_TYPE_QSFP:
23366809cee0SRavikumar Nelavelli 			adapter->phy.cable_type =
23376809cee0SRavikumar Nelavelli 				page_data[QSFP_PLUS_CABLE_TYPE_OFFSET];
23386809cee0SRavikumar Nelavelli 			break;
23396809cee0SRavikumar Nelavelli 		case PHY_TYPE_SFP_PLUS_10GB:
23406809cee0SRavikumar Nelavelli 			adapter->phy.cable_type =
23416809cee0SRavikumar Nelavelli 				page_data[SFP_PLUS_CABLE_TYPE_OFFSET];
23426809cee0SRavikumar Nelavelli 			break;
23436809cee0SRavikumar Nelavelli 		default:
23446809cee0SRavikumar Nelavelli 			adapter->phy.cable_type = 0;
23456809cee0SRavikumar Nelavelli 			break;
23466809cee0SRavikumar Nelavelli 		}
23476809cee0SRavikumar Nelavelli 	}
23486809cee0SRavikumar Nelavelli 	return status;
23496809cee0SRavikumar Nelavelli }
23506809cee0SRavikumar Nelavelli 
235121252377SVasundhara Volam int be_cmd_query_sfp_info(struct be_adapter *adapter)
235221252377SVasundhara Volam {
235321252377SVasundhara Volam 	u8 page_data[PAGE_DATA_LEN];
235421252377SVasundhara Volam 	int status;
235521252377SVasundhara Volam 
235621252377SVasundhara Volam 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
235721252377SVasundhara Volam 						   page_data);
235821252377SVasundhara Volam 	if (!status) {
235921252377SVasundhara Volam 		strlcpy(adapter->phy.vendor_name, page_data +
236021252377SVasundhara Volam 			SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
236121252377SVasundhara Volam 		strlcpy(adapter->phy.vendor_pn,
236221252377SVasundhara Volam 			page_data + SFP_VENDOR_PN_OFFSET,
236321252377SVasundhara Volam 			SFP_VENDOR_NAME_LEN - 1);
236421252377SVasundhara Volam 	}
236521252377SVasundhara Volam 
236621252377SVasundhara Volam 	return status;
236721252377SVasundhara Volam }
236821252377SVasundhara Volam 
2369f0613380SKalesh AP int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name)
2370f0613380SKalesh AP {
2371f0613380SKalesh AP 	struct lancer_cmd_req_delete_object *req;
2372f0613380SKalesh AP 	struct be_mcc_wrb *wrb;
2373f0613380SKalesh AP 	int status;
2374f0613380SKalesh AP 
2375f0613380SKalesh AP 	spin_lock_bh(&adapter->mcc_lock);
2376f0613380SKalesh AP 
2377f0613380SKalesh AP 	wrb = wrb_from_mccq(adapter);
2378f0613380SKalesh AP 	if (!wrb) {
2379f0613380SKalesh AP 		status = -EBUSY;
2380f0613380SKalesh AP 		goto err;
2381f0613380SKalesh AP 	}
2382f0613380SKalesh AP 
2383f0613380SKalesh AP 	req = embedded_payload(wrb);
2384f0613380SKalesh AP 
2385f0613380SKalesh AP 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2386f0613380SKalesh AP 			       OPCODE_COMMON_DELETE_OBJECT,
2387f0613380SKalesh AP 			       sizeof(*req), wrb, NULL);
2388f0613380SKalesh AP 
2389242eb470SVasundhara Volam 	strlcpy(req->object_name, obj_name, sizeof(req->object_name));
2390f0613380SKalesh AP 
2391f0613380SKalesh AP 	status = be_mcc_notify_wait(adapter);
2392f0613380SKalesh AP err:
2393f0613380SKalesh AP 	spin_unlock_bh(&adapter->mcc_lock);
2394f0613380SKalesh AP 	return status;
2395f0613380SKalesh AP }
2396f0613380SKalesh AP 
2397de49bd5aSPadmanabh Ratnakar int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
2398de49bd5aSPadmanabh Ratnakar 			   u32 data_size, u32 data_offset, const char *obj_name,
2399de49bd5aSPadmanabh Ratnakar 			   u32 *data_read, u32 *eof, u8 *addn_status)
2400de49bd5aSPadmanabh Ratnakar {
2401de49bd5aSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
2402de49bd5aSPadmanabh Ratnakar 	struct lancer_cmd_req_read_object *req;
2403de49bd5aSPadmanabh Ratnakar 	struct lancer_cmd_resp_read_object *resp;
2404de49bd5aSPadmanabh Ratnakar 	int status;
2405de49bd5aSPadmanabh Ratnakar 
2406de49bd5aSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
2407de49bd5aSPadmanabh Ratnakar 
2408de49bd5aSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
2409de49bd5aSPadmanabh Ratnakar 	if (!wrb) {
2410de49bd5aSPadmanabh Ratnakar 		status = -EBUSY;
2411de49bd5aSPadmanabh Ratnakar 		goto err_unlock;
2412de49bd5aSPadmanabh Ratnakar 	}
2413de49bd5aSPadmanabh Ratnakar 
2414de49bd5aSPadmanabh Ratnakar 	req = embedded_payload(wrb);
2415de49bd5aSPadmanabh Ratnakar 
2416de49bd5aSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2417de49bd5aSPadmanabh Ratnakar 			       OPCODE_COMMON_READ_OBJECT,
2418de49bd5aSPadmanabh Ratnakar 			       sizeof(struct lancer_cmd_req_read_object), wrb,
2419de49bd5aSPadmanabh Ratnakar 			       NULL);
2420de49bd5aSPadmanabh Ratnakar 
2421de49bd5aSPadmanabh Ratnakar 	req->desired_read_len = cpu_to_le32(data_size);
2422de49bd5aSPadmanabh Ratnakar 	req->read_offset = cpu_to_le32(data_offset);
2423de49bd5aSPadmanabh Ratnakar 	strcpy(req->object_name, obj_name);
2424de49bd5aSPadmanabh Ratnakar 	req->descriptor_count = cpu_to_le32(1);
2425de49bd5aSPadmanabh Ratnakar 	req->buf_len = cpu_to_le32(data_size);
2426de49bd5aSPadmanabh Ratnakar 	req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF));
2427de49bd5aSPadmanabh Ratnakar 	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma));
2428de49bd5aSPadmanabh Ratnakar 
2429de49bd5aSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
2430de49bd5aSPadmanabh Ratnakar 
2431de49bd5aSPadmanabh Ratnakar 	resp = embedded_payload(wrb);
2432de49bd5aSPadmanabh Ratnakar 	if (!status) {
2433de49bd5aSPadmanabh Ratnakar 		*data_read = le32_to_cpu(resp->actual_read_len);
2434de49bd5aSPadmanabh Ratnakar 		*eof = le32_to_cpu(resp->eof);
2435de49bd5aSPadmanabh Ratnakar 	} else {
2436de49bd5aSPadmanabh Ratnakar 		*addn_status = resp->additional_status;
2437de49bd5aSPadmanabh Ratnakar 	}
2438de49bd5aSPadmanabh Ratnakar 
2439de49bd5aSPadmanabh Ratnakar err_unlock:
2440de49bd5aSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
2441de49bd5aSPadmanabh Ratnakar 	return status;
2442de49bd5aSPadmanabh Ratnakar }
2443de49bd5aSPadmanabh Ratnakar 
24449aebddd1SJeff Kirsher int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
244570a7b525SVasundhara Volam 			  u32 flash_type, u32 flash_opcode, u32 img_offset,
244670a7b525SVasundhara Volam 			  u32 buf_size)
24479aebddd1SJeff Kirsher {
24489aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
24499aebddd1SJeff Kirsher 	struct be_cmd_write_flashrom *req;
24509aebddd1SJeff Kirsher 	int status;
24519aebddd1SJeff Kirsher 
24529aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
24539aebddd1SJeff Kirsher 	adapter->flash_status = 0;
24549aebddd1SJeff Kirsher 
24559aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
24569aebddd1SJeff Kirsher 	if (!wrb) {
24579aebddd1SJeff Kirsher 		status = -EBUSY;
24589aebddd1SJeff Kirsher 		goto err_unlock;
24599aebddd1SJeff Kirsher 	}
24609aebddd1SJeff Kirsher 	req = cmd->va;
24619aebddd1SJeff Kirsher 
2462106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2463a2cc4e0bSSathya Perla 			       OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb,
2464a2cc4e0bSSathya Perla 			       cmd);
24659aebddd1SJeff Kirsher 
24669aebddd1SJeff Kirsher 	req->params.op_type = cpu_to_le32(flash_type);
246770a7b525SVasundhara Volam 	if (flash_type == OPTYPE_OFFSET_SPECIFIED)
246870a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(img_offset);
246970a7b525SVasundhara Volam 
24709aebddd1SJeff Kirsher 	req->params.op_code = cpu_to_le32(flash_opcode);
24719aebddd1SJeff Kirsher 	req->params.data_buf_size = cpu_to_le32(buf_size);
24729aebddd1SJeff Kirsher 
24739aebddd1SJeff Kirsher 	be_mcc_notify(adapter);
24749aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
24759aebddd1SJeff Kirsher 
24765eeff635SSuresh Reddy 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
2477e2edb7d5SSathya Perla 					 msecs_to_jiffies(40000)))
2478fd45160cSKalesh AP 		status = -ETIMEDOUT;
24799aebddd1SJeff Kirsher 	else
24809aebddd1SJeff Kirsher 		status = adapter->flash_status;
24819aebddd1SJeff Kirsher 
24829aebddd1SJeff Kirsher 	return status;
24839aebddd1SJeff Kirsher 
24849aebddd1SJeff Kirsher err_unlock:
24859aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
24869aebddd1SJeff Kirsher 	return status;
24879aebddd1SJeff Kirsher }
24889aebddd1SJeff Kirsher 
24899aebddd1SJeff Kirsher int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
249070a7b525SVasundhara Volam 			 u16 img_optype, u32 img_offset, u32 crc_offset)
24919aebddd1SJeff Kirsher {
2492be716446SPadmanabh Ratnakar 	struct be_cmd_read_flash_crc *req;
249370a7b525SVasundhara Volam 	struct be_mcc_wrb *wrb;
24949aebddd1SJeff Kirsher 	int status;
24959aebddd1SJeff Kirsher 
24969aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
24979aebddd1SJeff Kirsher 
24989aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
24999aebddd1SJeff Kirsher 	if (!wrb) {
25009aebddd1SJeff Kirsher 		status = -EBUSY;
25019aebddd1SJeff Kirsher 		goto err;
25029aebddd1SJeff Kirsher 	}
25039aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
25049aebddd1SJeff Kirsher 
2505106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2506be716446SPadmanabh Ratnakar 			       OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
2507be716446SPadmanabh Ratnakar 			       wrb, NULL);
25089aebddd1SJeff Kirsher 
250970a7b525SVasundhara Volam 	req->params.op_type = cpu_to_le32(img_optype);
251070a7b525SVasundhara Volam 	if (img_optype == OPTYPE_OFFSET_SPECIFIED)
251170a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(img_offset + crc_offset);
251270a7b525SVasundhara Volam 	else
251370a7b525SVasundhara Volam 		req->params.offset = cpu_to_le32(crc_offset);
251470a7b525SVasundhara Volam 
25159aebddd1SJeff Kirsher 	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
25169aebddd1SJeff Kirsher 	req->params.data_buf_size = cpu_to_le32(0x4);
25179aebddd1SJeff Kirsher 
25189aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
25199aebddd1SJeff Kirsher 	if (!status)
2520be716446SPadmanabh Ratnakar 		memcpy(flashed_crc, req->crc, 4);
25219aebddd1SJeff Kirsher 
25229aebddd1SJeff Kirsher err:
25239aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25249aebddd1SJeff Kirsher 	return status;
25259aebddd1SJeff Kirsher }
25269aebddd1SJeff Kirsher 
25279aebddd1SJeff Kirsher int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
25289aebddd1SJeff Kirsher 			    struct be_dma_mem *nonemb_cmd)
25299aebddd1SJeff Kirsher {
25309aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
25319aebddd1SJeff Kirsher 	struct be_cmd_req_acpi_wol_magic_config *req;
25329aebddd1SJeff Kirsher 	int status;
25339aebddd1SJeff Kirsher 
25349aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
25359aebddd1SJeff Kirsher 
25369aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
25379aebddd1SJeff Kirsher 	if (!wrb) {
25389aebddd1SJeff Kirsher 		status = -EBUSY;
25399aebddd1SJeff Kirsher 		goto err;
25409aebddd1SJeff Kirsher 	}
25419aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
25429aebddd1SJeff Kirsher 
2543106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
2544a2cc4e0bSSathya Perla 			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req),
2545a2cc4e0bSSathya Perla 			       wrb, nonemb_cmd);
25469aebddd1SJeff Kirsher 	memcpy(req->magic_mac, mac, ETH_ALEN);
25479aebddd1SJeff Kirsher 
25489aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
25499aebddd1SJeff Kirsher 
25509aebddd1SJeff Kirsher err:
25519aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25529aebddd1SJeff Kirsher 	return status;
25539aebddd1SJeff Kirsher }
25549aebddd1SJeff Kirsher 
25559aebddd1SJeff Kirsher int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
25569aebddd1SJeff Kirsher 			u8 loopback_type, u8 enable)
25579aebddd1SJeff Kirsher {
25589aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
25599aebddd1SJeff Kirsher 	struct be_cmd_req_set_lmode *req;
25609aebddd1SJeff Kirsher 	int status;
25619aebddd1SJeff Kirsher 
25629aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
25639aebddd1SJeff Kirsher 
25649aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
25659aebddd1SJeff Kirsher 	if (!wrb) {
25669aebddd1SJeff Kirsher 		status = -EBUSY;
25679aebddd1SJeff Kirsher 		goto err;
25689aebddd1SJeff Kirsher 	}
25699aebddd1SJeff Kirsher 
25709aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
25719aebddd1SJeff Kirsher 
2572106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
2573a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req),
2574a2cc4e0bSSathya Perla 			       wrb, NULL);
25759aebddd1SJeff Kirsher 
25769aebddd1SJeff Kirsher 	req->src_port = port_num;
25779aebddd1SJeff Kirsher 	req->dest_port = port_num;
25789aebddd1SJeff Kirsher 	req->loopback_type = loopback_type;
25799aebddd1SJeff Kirsher 	req->loopback_state = enable;
25809aebddd1SJeff Kirsher 
25819aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
25829aebddd1SJeff Kirsher err:
25839aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
25849aebddd1SJeff Kirsher 	return status;
25859aebddd1SJeff Kirsher }
25869aebddd1SJeff Kirsher 
25879aebddd1SJeff Kirsher int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
2588a2cc4e0bSSathya Perla 			 u32 loopback_type, u32 pkt_size, u32 num_pkts,
2589a2cc4e0bSSathya Perla 			 u64 pattern)
25909aebddd1SJeff Kirsher {
25919aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
25929aebddd1SJeff Kirsher 	struct be_cmd_req_loopback_test *req;
25935eeff635SSuresh Reddy 	struct be_cmd_resp_loopback_test *resp;
25949aebddd1SJeff Kirsher 	int status;
25959aebddd1SJeff Kirsher 
25969aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
25979aebddd1SJeff Kirsher 
25989aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
25999aebddd1SJeff Kirsher 	if (!wrb) {
26009aebddd1SJeff Kirsher 		status = -EBUSY;
26019aebddd1SJeff Kirsher 		goto err;
26029aebddd1SJeff Kirsher 	}
26039aebddd1SJeff Kirsher 
26049aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
26059aebddd1SJeff Kirsher 
2606106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
2607a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb,
2608a2cc4e0bSSathya Perla 			       NULL);
26099aebddd1SJeff Kirsher 
26105eeff635SSuresh Reddy 	req->hdr.timeout = cpu_to_le32(15);
26119aebddd1SJeff Kirsher 	req->pattern = cpu_to_le64(pattern);
26129aebddd1SJeff Kirsher 	req->src_port = cpu_to_le32(port_num);
26139aebddd1SJeff Kirsher 	req->dest_port = cpu_to_le32(port_num);
26149aebddd1SJeff Kirsher 	req->pkt_size = cpu_to_le32(pkt_size);
26159aebddd1SJeff Kirsher 	req->num_pkts = cpu_to_le32(num_pkts);
26169aebddd1SJeff Kirsher 	req->loopback_type = cpu_to_le32(loopback_type);
26179aebddd1SJeff Kirsher 
26185eeff635SSuresh Reddy 	be_mcc_notify(adapter);
26199aebddd1SJeff Kirsher 
26205eeff635SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
26215eeff635SSuresh Reddy 
26225eeff635SSuresh Reddy 	wait_for_completion(&adapter->et_cmd_compl);
26235eeff635SSuresh Reddy 	resp = embedded_payload(wrb);
26245eeff635SSuresh Reddy 	status = le32_to_cpu(resp->status);
26255eeff635SSuresh Reddy 
26265eeff635SSuresh Reddy 	return status;
26279aebddd1SJeff Kirsher err:
26289aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
26299aebddd1SJeff Kirsher 	return status;
26309aebddd1SJeff Kirsher }
26319aebddd1SJeff Kirsher 
26329aebddd1SJeff Kirsher int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
26339aebddd1SJeff Kirsher 			u32 byte_cnt, struct be_dma_mem *cmd)
26349aebddd1SJeff Kirsher {
26359aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
26369aebddd1SJeff Kirsher 	struct be_cmd_req_ddrdma_test *req;
26379aebddd1SJeff Kirsher 	int status;
26389aebddd1SJeff Kirsher 	int i, j = 0;
26399aebddd1SJeff Kirsher 
26409aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
26419aebddd1SJeff Kirsher 
26429aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
26439aebddd1SJeff Kirsher 	if (!wrb) {
26449aebddd1SJeff Kirsher 		status = -EBUSY;
26459aebddd1SJeff Kirsher 		goto err;
26469aebddd1SJeff Kirsher 	}
26479aebddd1SJeff Kirsher 	req = cmd->va;
2648106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
2649a2cc4e0bSSathya Perla 			       OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb,
2650a2cc4e0bSSathya Perla 			       cmd);
26519aebddd1SJeff Kirsher 
26529aebddd1SJeff Kirsher 	req->pattern = cpu_to_le64(pattern);
26539aebddd1SJeff Kirsher 	req->byte_count = cpu_to_le32(byte_cnt);
26549aebddd1SJeff Kirsher 	for (i = 0; i < byte_cnt; i++) {
26559aebddd1SJeff Kirsher 		req->snd_buff[i] = (u8)(pattern >> (j*8));
26569aebddd1SJeff Kirsher 		j++;
26579aebddd1SJeff Kirsher 		if (j > 7)
26589aebddd1SJeff Kirsher 			j = 0;
26599aebddd1SJeff Kirsher 	}
26609aebddd1SJeff Kirsher 
26619aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
26629aebddd1SJeff Kirsher 
26639aebddd1SJeff Kirsher 	if (!status) {
26649aebddd1SJeff Kirsher 		struct be_cmd_resp_ddrdma_test *resp;
266503d28ffeSKalesh AP 
26669aebddd1SJeff Kirsher 		resp = cmd->va;
26679aebddd1SJeff Kirsher 		if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) ||
26689aebddd1SJeff Kirsher 		    resp->snd_err) {
26699aebddd1SJeff Kirsher 			status = -1;
26709aebddd1SJeff Kirsher 		}
26719aebddd1SJeff Kirsher 	}
26729aebddd1SJeff Kirsher 
26739aebddd1SJeff Kirsher err:
26749aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
26759aebddd1SJeff Kirsher 	return status;
26769aebddd1SJeff Kirsher }
26779aebddd1SJeff Kirsher 
26789aebddd1SJeff Kirsher int be_cmd_get_seeprom_data(struct be_adapter *adapter,
26799aebddd1SJeff Kirsher 			    struct be_dma_mem *nonemb_cmd)
26809aebddd1SJeff Kirsher {
26819aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
26829aebddd1SJeff Kirsher 	struct be_cmd_req_seeprom_read *req;
26839aebddd1SJeff Kirsher 	int status;
26849aebddd1SJeff Kirsher 
26859aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
26869aebddd1SJeff Kirsher 
26879aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
26889aebddd1SJeff Kirsher 	if (!wrb) {
26899aebddd1SJeff Kirsher 		status = -EBUSY;
26909aebddd1SJeff Kirsher 		goto err;
26919aebddd1SJeff Kirsher 	}
26929aebddd1SJeff Kirsher 	req = nonemb_cmd->va;
26939aebddd1SJeff Kirsher 
2694106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2695106df1e3SSomnath Kotur 			       OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb,
2696106df1e3SSomnath Kotur 			       nonemb_cmd);
26979aebddd1SJeff Kirsher 
26989aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
26999aebddd1SJeff Kirsher 
27009aebddd1SJeff Kirsher err:
27019aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
27029aebddd1SJeff Kirsher 	return status;
27039aebddd1SJeff Kirsher }
27049aebddd1SJeff Kirsher 
270542f11cf2SAjit Khaparde int be_cmd_get_phy_info(struct be_adapter *adapter)
27069aebddd1SJeff Kirsher {
27079aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
27089aebddd1SJeff Kirsher 	struct be_cmd_req_get_phy_info *req;
27099aebddd1SJeff Kirsher 	struct be_dma_mem cmd;
27109aebddd1SJeff Kirsher 	int status;
27119aebddd1SJeff Kirsher 
2712f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
2713f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_COMMON))
2714f25b119cSPadmanabh Ratnakar 		return -EPERM;
2715f25b119cSPadmanabh Ratnakar 
27169aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
27179aebddd1SJeff Kirsher 
27189aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
27199aebddd1SJeff Kirsher 	if (!wrb) {
27209aebddd1SJeff Kirsher 		status = -EBUSY;
27219aebddd1SJeff Kirsher 		goto err;
27229aebddd1SJeff Kirsher 	}
27239aebddd1SJeff Kirsher 	cmd.size = sizeof(struct be_cmd_req_get_phy_info);
2724a2cc4e0bSSathya Perla 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
27259aebddd1SJeff Kirsher 	if (!cmd.va) {
27269aebddd1SJeff Kirsher 		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
27279aebddd1SJeff Kirsher 		status = -ENOMEM;
27289aebddd1SJeff Kirsher 		goto err;
27299aebddd1SJeff Kirsher 	}
27309aebddd1SJeff Kirsher 
27319aebddd1SJeff Kirsher 	req = cmd.va;
27329aebddd1SJeff Kirsher 
2733106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2734106df1e3SSomnath Kotur 			       OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req),
2735106df1e3SSomnath Kotur 			       wrb, &cmd);
27369aebddd1SJeff Kirsher 
27379aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
27389aebddd1SJeff Kirsher 	if (!status) {
27399aebddd1SJeff Kirsher 		struct be_phy_info *resp_phy_info =
27409aebddd1SJeff Kirsher 				cmd.va + sizeof(struct be_cmd_req_hdr);
274103d28ffeSKalesh AP 
274242f11cf2SAjit Khaparde 		adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type);
274342f11cf2SAjit Khaparde 		adapter->phy.interface_type =
27449aebddd1SJeff Kirsher 			le16_to_cpu(resp_phy_info->interface_type);
274542f11cf2SAjit Khaparde 		adapter->phy.auto_speeds_supported =
274642f11cf2SAjit Khaparde 			le16_to_cpu(resp_phy_info->auto_speeds_supported);
274742f11cf2SAjit Khaparde 		adapter->phy.fixed_speeds_supported =
274842f11cf2SAjit Khaparde 			le16_to_cpu(resp_phy_info->fixed_speeds_supported);
274942f11cf2SAjit Khaparde 		adapter->phy.misc_params =
275042f11cf2SAjit Khaparde 			le32_to_cpu(resp_phy_info->misc_params);
275168cb7e47SVasundhara Volam 
275268cb7e47SVasundhara Volam 		if (BE2_chip(adapter)) {
275368cb7e47SVasundhara Volam 			adapter->phy.fixed_speeds_supported =
275468cb7e47SVasundhara Volam 				BE_SUPPORTED_SPEED_10GBPS |
275568cb7e47SVasundhara Volam 				BE_SUPPORTED_SPEED_1GBPS;
275668cb7e47SVasundhara Volam 		}
27579aebddd1SJeff Kirsher 	}
2758a2cc4e0bSSathya Perla 	pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
27599aebddd1SJeff Kirsher err:
27609aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
27619aebddd1SJeff Kirsher 	return status;
27629aebddd1SJeff Kirsher }
27639aebddd1SJeff Kirsher 
2764bc0ee163SLad, Prabhakar static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain)
27659aebddd1SJeff Kirsher {
27669aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
27679aebddd1SJeff Kirsher 	struct be_cmd_req_set_qos *req;
27689aebddd1SJeff Kirsher 	int status;
27699aebddd1SJeff Kirsher 
27709aebddd1SJeff Kirsher 	spin_lock_bh(&adapter->mcc_lock);
27719aebddd1SJeff Kirsher 
27729aebddd1SJeff Kirsher 	wrb = wrb_from_mccq(adapter);
27739aebddd1SJeff Kirsher 	if (!wrb) {
27749aebddd1SJeff Kirsher 		status = -EBUSY;
27759aebddd1SJeff Kirsher 		goto err;
27769aebddd1SJeff Kirsher 	}
27779aebddd1SJeff Kirsher 
27789aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
27799aebddd1SJeff Kirsher 
2780106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2781106df1e3SSomnath Kotur 			       OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL);
27829aebddd1SJeff Kirsher 
27839aebddd1SJeff Kirsher 	req->hdr.domain = domain;
27849aebddd1SJeff Kirsher 	req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
27859aebddd1SJeff Kirsher 	req->max_bps_nic = cpu_to_le32(bps);
27869aebddd1SJeff Kirsher 
27879aebddd1SJeff Kirsher 	status = be_mcc_notify_wait(adapter);
27889aebddd1SJeff Kirsher 
27899aebddd1SJeff Kirsher err:
27909aebddd1SJeff Kirsher 	spin_unlock_bh(&adapter->mcc_lock);
27919aebddd1SJeff Kirsher 	return status;
27929aebddd1SJeff Kirsher }
27939aebddd1SJeff Kirsher 
27949aebddd1SJeff Kirsher int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
27959aebddd1SJeff Kirsher {
27969aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
27979aebddd1SJeff Kirsher 	struct be_cmd_req_cntl_attribs *req;
27989aebddd1SJeff Kirsher 	struct be_cmd_resp_cntl_attribs *resp;
27999aebddd1SJeff Kirsher 	int status;
28009aebddd1SJeff Kirsher 	int payload_len = max(sizeof(*req), sizeof(*resp));
28019aebddd1SJeff Kirsher 	struct mgmt_controller_attrib *attribs;
28029aebddd1SJeff Kirsher 	struct be_dma_mem attribs_cmd;
28039aebddd1SJeff Kirsher 
2804d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
2805d98ef50fSSuresh Reddy 		return -1;
2806d98ef50fSSuresh Reddy 
28079aebddd1SJeff Kirsher 	memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
28089aebddd1SJeff Kirsher 	attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
28099aebddd1SJeff Kirsher 	attribs_cmd.va = pci_alloc_consistent(adapter->pdev, attribs_cmd.size,
28109aebddd1SJeff Kirsher 					      &attribs_cmd.dma);
28119aebddd1SJeff Kirsher 	if (!attribs_cmd.va) {
2812a2cc4e0bSSathya Perla 		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
2813d98ef50fSSuresh Reddy 		status = -ENOMEM;
2814d98ef50fSSuresh Reddy 		goto err;
28159aebddd1SJeff Kirsher 	}
28169aebddd1SJeff Kirsher 
28179aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
28189aebddd1SJeff Kirsher 	if (!wrb) {
28199aebddd1SJeff Kirsher 		status = -EBUSY;
28209aebddd1SJeff Kirsher 		goto err;
28219aebddd1SJeff Kirsher 	}
28229aebddd1SJeff Kirsher 	req = attribs_cmd.va;
28239aebddd1SJeff Kirsher 
2824106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2825a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len,
2826a2cc4e0bSSathya Perla 			       wrb, &attribs_cmd);
28279aebddd1SJeff Kirsher 
28289aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
28299aebddd1SJeff Kirsher 	if (!status) {
28309aebddd1SJeff Kirsher 		attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
28319aebddd1SJeff Kirsher 		adapter->hba_port_num = attribs->hba_attribs.phy_port;
28329aebddd1SJeff Kirsher 	}
28339aebddd1SJeff Kirsher 
28349aebddd1SJeff Kirsher err:
28359aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
2836d98ef50fSSuresh Reddy 	if (attribs_cmd.va)
2837d98ef50fSSuresh Reddy 		pci_free_consistent(adapter->pdev, attribs_cmd.size,
2838d98ef50fSSuresh Reddy 				    attribs_cmd.va, attribs_cmd.dma);
28399aebddd1SJeff Kirsher 	return status;
28409aebddd1SJeff Kirsher }
28419aebddd1SJeff Kirsher 
28429aebddd1SJeff Kirsher /* Uses mbox */
28439aebddd1SJeff Kirsher int be_cmd_req_native_mode(struct be_adapter *adapter)
28449aebddd1SJeff Kirsher {
28459aebddd1SJeff Kirsher 	struct be_mcc_wrb *wrb;
28469aebddd1SJeff Kirsher 	struct be_cmd_req_set_func_cap *req;
28479aebddd1SJeff Kirsher 	int status;
28489aebddd1SJeff Kirsher 
28499aebddd1SJeff Kirsher 	if (mutex_lock_interruptible(&adapter->mbox_lock))
28509aebddd1SJeff Kirsher 		return -1;
28519aebddd1SJeff Kirsher 
28529aebddd1SJeff Kirsher 	wrb = wrb_from_mbox(adapter);
28539aebddd1SJeff Kirsher 	if (!wrb) {
28549aebddd1SJeff Kirsher 		status = -EBUSY;
28559aebddd1SJeff Kirsher 		goto err;
28569aebddd1SJeff Kirsher 	}
28579aebddd1SJeff Kirsher 
28589aebddd1SJeff Kirsher 	req = embedded_payload(wrb);
28599aebddd1SJeff Kirsher 
2860106df1e3SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2861a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP,
2862a2cc4e0bSSathya Perla 			       sizeof(*req), wrb, NULL);
28639aebddd1SJeff Kirsher 
28649aebddd1SJeff Kirsher 	req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS |
28659aebddd1SJeff Kirsher 				CAPABILITY_BE3_NATIVE_ERX_API);
28669aebddd1SJeff Kirsher 	req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API);
28679aebddd1SJeff Kirsher 
28689aebddd1SJeff Kirsher 	status = be_mbox_notify_wait(adapter);
28699aebddd1SJeff Kirsher 	if (!status) {
28709aebddd1SJeff Kirsher 		struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb);
287103d28ffeSKalesh AP 
28729aebddd1SJeff Kirsher 		adapter->be3_native = le32_to_cpu(resp->cap_flags) &
28739aebddd1SJeff Kirsher 					CAPABILITY_BE3_NATIVE_ERX_API;
2874d379142bSSathya Perla 		if (!adapter->be3_native)
2875d379142bSSathya Perla 			dev_warn(&adapter->pdev->dev,
2876d379142bSSathya Perla 				 "adapter not in advanced mode\n");
28779aebddd1SJeff Kirsher 	}
28789aebddd1SJeff Kirsher err:
28799aebddd1SJeff Kirsher 	mutex_unlock(&adapter->mbox_lock);
28809aebddd1SJeff Kirsher 	return status;
28819aebddd1SJeff Kirsher }
2882590c391dSPadmanabh Ratnakar 
2883f25b119cSPadmanabh Ratnakar /* Get privilege(s) for a function */
2884f25b119cSPadmanabh Ratnakar int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
2885f25b119cSPadmanabh Ratnakar 			     u32 domain)
2886f25b119cSPadmanabh Ratnakar {
2887f25b119cSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
2888f25b119cSPadmanabh Ratnakar 	struct be_cmd_req_get_fn_privileges *req;
2889f25b119cSPadmanabh Ratnakar 	int status;
2890f25b119cSPadmanabh Ratnakar 
2891f25b119cSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
2892f25b119cSPadmanabh Ratnakar 
2893f25b119cSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
2894f25b119cSPadmanabh Ratnakar 	if (!wrb) {
2895f25b119cSPadmanabh Ratnakar 		status = -EBUSY;
2896f25b119cSPadmanabh Ratnakar 		goto err;
2897f25b119cSPadmanabh Ratnakar 	}
2898f25b119cSPadmanabh Ratnakar 
2899f25b119cSPadmanabh Ratnakar 	req = embedded_payload(wrb);
2900f25b119cSPadmanabh Ratnakar 
2901f25b119cSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2902f25b119cSPadmanabh Ratnakar 			       OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
2903f25b119cSPadmanabh Ratnakar 			       wrb, NULL);
2904f25b119cSPadmanabh Ratnakar 
2905f25b119cSPadmanabh Ratnakar 	req->hdr.domain = domain;
2906f25b119cSPadmanabh Ratnakar 
2907f25b119cSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
2908f25b119cSPadmanabh Ratnakar 	if (!status) {
2909f25b119cSPadmanabh Ratnakar 		struct be_cmd_resp_get_fn_privileges *resp =
2910f25b119cSPadmanabh Ratnakar 						embedded_payload(wrb);
291103d28ffeSKalesh AP 
2912f25b119cSPadmanabh Ratnakar 		*privilege = le32_to_cpu(resp->privilege_mask);
291302308d74SSuresh Reddy 
291402308d74SSuresh Reddy 		/* In UMC mode FW does not return right privileges.
291502308d74SSuresh Reddy 		 * Override with correct privilege equivalent to PF.
291602308d74SSuresh Reddy 		 */
291702308d74SSuresh Reddy 		if (BEx_chip(adapter) && be_is_mc(adapter) &&
291802308d74SSuresh Reddy 		    be_physfn(adapter))
291902308d74SSuresh Reddy 			*privilege = MAX_PRIVILEGES;
2920f25b119cSPadmanabh Ratnakar 	}
2921f25b119cSPadmanabh Ratnakar 
2922f25b119cSPadmanabh Ratnakar err:
2923f25b119cSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
2924f25b119cSPadmanabh Ratnakar 	return status;
2925f25b119cSPadmanabh Ratnakar }
2926f25b119cSPadmanabh Ratnakar 
292704a06028SSathya Perla /* Set privilege(s) for a function */
292804a06028SSathya Perla int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges,
292904a06028SSathya Perla 			     u32 domain)
293004a06028SSathya Perla {
293104a06028SSathya Perla 	struct be_mcc_wrb *wrb;
293204a06028SSathya Perla 	struct be_cmd_req_set_fn_privileges *req;
293304a06028SSathya Perla 	int status;
293404a06028SSathya Perla 
293504a06028SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
293604a06028SSathya Perla 
293704a06028SSathya Perla 	wrb = wrb_from_mccq(adapter);
293804a06028SSathya Perla 	if (!wrb) {
293904a06028SSathya Perla 		status = -EBUSY;
294004a06028SSathya Perla 		goto err;
294104a06028SSathya Perla 	}
294204a06028SSathya Perla 
294304a06028SSathya Perla 	req = embedded_payload(wrb);
294404a06028SSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
294504a06028SSathya Perla 			       OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req),
294604a06028SSathya Perla 			       wrb, NULL);
294704a06028SSathya Perla 	req->hdr.domain = domain;
294804a06028SSathya Perla 	if (lancer_chip(adapter))
294904a06028SSathya Perla 		req->privileges_lancer = cpu_to_le32(privileges);
295004a06028SSathya Perla 	else
295104a06028SSathya Perla 		req->privileges = cpu_to_le32(privileges);
295204a06028SSathya Perla 
295304a06028SSathya Perla 	status = be_mcc_notify_wait(adapter);
295404a06028SSathya Perla err:
295504a06028SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
295604a06028SSathya Perla 	return status;
295704a06028SSathya Perla }
295804a06028SSathya Perla 
29595a712c13SSathya Perla /* pmac_id_valid: true => pmac_id is supplied and MAC address is requested.
29605a712c13SSathya Perla  * pmac_id_valid: false => pmac_id or MAC address is requested.
29615a712c13SSathya Perla  *		  If pmac_id is returned, pmac_id_valid is returned as true
29625a712c13SSathya Perla  */
29631578e777SPadmanabh Ratnakar int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
2964b188f090SSuresh Reddy 			     bool *pmac_id_valid, u32 *pmac_id, u32 if_handle,
2965b188f090SSuresh Reddy 			     u8 domain)
2966590c391dSPadmanabh Ratnakar {
2967590c391dSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
2968590c391dSPadmanabh Ratnakar 	struct be_cmd_req_get_mac_list *req;
2969590c391dSPadmanabh Ratnakar 	int status;
2970590c391dSPadmanabh Ratnakar 	int mac_count;
2971e5e1ee89SPadmanabh Ratnakar 	struct be_dma_mem get_mac_list_cmd;
2972e5e1ee89SPadmanabh Ratnakar 	int i;
2973e5e1ee89SPadmanabh Ratnakar 
2974e5e1ee89SPadmanabh Ratnakar 	memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
2975e5e1ee89SPadmanabh Ratnakar 	get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
2976e5e1ee89SPadmanabh Ratnakar 	get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev,
2977e5e1ee89SPadmanabh Ratnakar 						   get_mac_list_cmd.size,
2978e5e1ee89SPadmanabh Ratnakar 						   &get_mac_list_cmd.dma);
2979e5e1ee89SPadmanabh Ratnakar 
2980e5e1ee89SPadmanabh Ratnakar 	if (!get_mac_list_cmd.va) {
2981e5e1ee89SPadmanabh Ratnakar 		dev_err(&adapter->pdev->dev,
2982e5e1ee89SPadmanabh Ratnakar 			"Memory allocation failure during GET_MAC_LIST\n");
2983e5e1ee89SPadmanabh Ratnakar 		return -ENOMEM;
2984e5e1ee89SPadmanabh Ratnakar 	}
2985590c391dSPadmanabh Ratnakar 
2986590c391dSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
2987590c391dSPadmanabh Ratnakar 
2988590c391dSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
2989590c391dSPadmanabh Ratnakar 	if (!wrb) {
2990590c391dSPadmanabh Ratnakar 		status = -EBUSY;
2991e5e1ee89SPadmanabh Ratnakar 		goto out;
2992590c391dSPadmanabh Ratnakar 	}
2993e5e1ee89SPadmanabh Ratnakar 
2994e5e1ee89SPadmanabh Ratnakar 	req = get_mac_list_cmd.va;
2995590c391dSPadmanabh Ratnakar 
2996590c391dSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
2997bf591f51SSathya Perla 			       OPCODE_COMMON_GET_MAC_LIST,
2998bf591f51SSathya Perla 			       get_mac_list_cmd.size, wrb, &get_mac_list_cmd);
2999590c391dSPadmanabh Ratnakar 	req->hdr.domain = domain;
3000e5e1ee89SPadmanabh Ratnakar 	req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
30015a712c13SSathya Perla 	if (*pmac_id_valid) {
30025a712c13SSathya Perla 		req->mac_id = cpu_to_le32(*pmac_id);
3003b188f090SSuresh Reddy 		req->iface_id = cpu_to_le16(if_handle);
30045a712c13SSathya Perla 		req->perm_override = 0;
30055a712c13SSathya Perla 	} else {
3006e5e1ee89SPadmanabh Ratnakar 		req->perm_override = 1;
30075a712c13SSathya Perla 	}
3008590c391dSPadmanabh Ratnakar 
3009590c391dSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3010590c391dSPadmanabh Ratnakar 	if (!status) {
3011590c391dSPadmanabh Ratnakar 		struct be_cmd_resp_get_mac_list *resp =
3012e5e1ee89SPadmanabh Ratnakar 						get_mac_list_cmd.va;
30135a712c13SSathya Perla 
30145a712c13SSathya Perla 		if (*pmac_id_valid) {
30155a712c13SSathya Perla 			memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr,
30165a712c13SSathya Perla 			       ETH_ALEN);
30175a712c13SSathya Perla 			goto out;
30185a712c13SSathya Perla 		}
30195a712c13SSathya Perla 
3020e5e1ee89SPadmanabh Ratnakar 		mac_count = resp->true_mac_count + resp->pseudo_mac_count;
3021e5e1ee89SPadmanabh Ratnakar 		/* Mac list returned could contain one or more active mac_ids
3022dbedd44eSJoe Perches 		 * or one or more true or pseudo permanent mac addresses.
30231578e777SPadmanabh Ratnakar 		 * If an active mac_id is present, return first active mac_id
30241578e777SPadmanabh Ratnakar 		 * found.
3025e5e1ee89SPadmanabh Ratnakar 		 */
3026590c391dSPadmanabh Ratnakar 		for (i = 0; i < mac_count; i++) {
3027e5e1ee89SPadmanabh Ratnakar 			struct get_list_macaddr *mac_entry;
3028e5e1ee89SPadmanabh Ratnakar 			u16 mac_addr_size;
3029e5e1ee89SPadmanabh Ratnakar 			u32 mac_id;
3030e5e1ee89SPadmanabh Ratnakar 
3031e5e1ee89SPadmanabh Ratnakar 			mac_entry = &resp->macaddr_list[i];
3032e5e1ee89SPadmanabh Ratnakar 			mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size);
3033e5e1ee89SPadmanabh Ratnakar 			/* mac_id is a 32 bit value and mac_addr size
3034e5e1ee89SPadmanabh Ratnakar 			 * is 6 bytes
3035e5e1ee89SPadmanabh Ratnakar 			 */
3036e5e1ee89SPadmanabh Ratnakar 			if (mac_addr_size == sizeof(u32)) {
30375a712c13SSathya Perla 				*pmac_id_valid = true;
3038e5e1ee89SPadmanabh Ratnakar 				mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id;
3039e5e1ee89SPadmanabh Ratnakar 				*pmac_id = le32_to_cpu(mac_id);
3040e5e1ee89SPadmanabh Ratnakar 				goto out;
3041590c391dSPadmanabh Ratnakar 			}
3042590c391dSPadmanabh Ratnakar 		}
30431578e777SPadmanabh Ratnakar 		/* If no active mac_id found, return first mac addr */
30445a712c13SSathya Perla 		*pmac_id_valid = false;
3045e5e1ee89SPadmanabh Ratnakar 		memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr,
3046e5e1ee89SPadmanabh Ratnakar 		       ETH_ALEN);
3047590c391dSPadmanabh Ratnakar 	}
3048590c391dSPadmanabh Ratnakar 
3049e5e1ee89SPadmanabh Ratnakar out:
3050590c391dSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3051e5e1ee89SPadmanabh Ratnakar 	pci_free_consistent(adapter->pdev, get_mac_list_cmd.size,
3052e5e1ee89SPadmanabh Ratnakar 			    get_mac_list_cmd.va, get_mac_list_cmd.dma);
3053590c391dSPadmanabh Ratnakar 	return status;
3054590c391dSPadmanabh Ratnakar }
3055590c391dSPadmanabh Ratnakar 
3056a2cc4e0bSSathya Perla int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id,
3057a2cc4e0bSSathya Perla 			  u8 *mac, u32 if_handle, bool active, u32 domain)
30585a712c13SSathya Perla {
3059b188f090SSuresh Reddy 	if (!active)
3060b188f090SSuresh Reddy 		be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id,
3061b188f090SSuresh Reddy 					 if_handle, domain);
30623175d8c2SSathya Perla 	if (BEx_chip(adapter))
30635a712c13SSathya Perla 		return be_cmd_mac_addr_query(adapter, mac, false,
3064b188f090SSuresh Reddy 					     if_handle, curr_pmac_id);
30653175d8c2SSathya Perla 	else
30663175d8c2SSathya Perla 		/* Fetch the MAC address using pmac_id */
30673175d8c2SSathya Perla 		return be_cmd_get_mac_from_list(adapter, mac, &active,
3068b188f090SSuresh Reddy 						&curr_pmac_id,
3069b188f090SSuresh Reddy 						if_handle, domain);
30705a712c13SSathya Perla }
30715a712c13SSathya Perla 
307295046b92SSathya Perla int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac)
307395046b92SSathya Perla {
307495046b92SSathya Perla 	int status;
307595046b92SSathya Perla 	bool pmac_valid = false;
307695046b92SSathya Perla 
3077c7bf7169SJoe Perches 	eth_zero_addr(mac);
307895046b92SSathya Perla 
30793175d8c2SSathya Perla 	if (BEx_chip(adapter)) {
30803175d8c2SSathya Perla 		if (be_physfn(adapter))
30813175d8c2SSathya Perla 			status = be_cmd_mac_addr_query(adapter, mac, true, 0,
30823175d8c2SSathya Perla 						       0);
308395046b92SSathya Perla 		else
308495046b92SSathya Perla 			status = be_cmd_mac_addr_query(adapter, mac, false,
308595046b92SSathya Perla 						       adapter->if_handle, 0);
30863175d8c2SSathya Perla 	} else {
30873175d8c2SSathya Perla 		status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid,
3088b188f090SSuresh Reddy 						  NULL, adapter->if_handle, 0);
30893175d8c2SSathya Perla 	}
30903175d8c2SSathya Perla 
309195046b92SSathya Perla 	return status;
309295046b92SSathya Perla }
309395046b92SSathya Perla 
3094590c391dSPadmanabh Ratnakar /* Uses synchronous MCCQ */
3095590c391dSPadmanabh Ratnakar int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
3096590c391dSPadmanabh Ratnakar 			u8 mac_count, u32 domain)
3097590c391dSPadmanabh Ratnakar {
3098590c391dSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3099590c391dSPadmanabh Ratnakar 	struct be_cmd_req_set_mac_list *req;
3100590c391dSPadmanabh Ratnakar 	int status;
3101590c391dSPadmanabh Ratnakar 	struct be_dma_mem cmd;
3102590c391dSPadmanabh Ratnakar 
3103590c391dSPadmanabh Ratnakar 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3104590c391dSPadmanabh Ratnakar 	cmd.size = sizeof(struct be_cmd_req_set_mac_list);
3105590c391dSPadmanabh Ratnakar 	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size,
3106590c391dSPadmanabh Ratnakar 				    &cmd.dma, GFP_KERNEL);
3107d0320f75SJoe Perches 	if (!cmd.va)
3108590c391dSPadmanabh Ratnakar 		return -ENOMEM;
3109590c391dSPadmanabh Ratnakar 
3110590c391dSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
3111590c391dSPadmanabh Ratnakar 
3112590c391dSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
3113590c391dSPadmanabh Ratnakar 	if (!wrb) {
3114590c391dSPadmanabh Ratnakar 		status = -EBUSY;
3115590c391dSPadmanabh Ratnakar 		goto err;
3116590c391dSPadmanabh Ratnakar 	}
3117590c391dSPadmanabh Ratnakar 
3118590c391dSPadmanabh Ratnakar 	req = cmd.va;
3119590c391dSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3120590c391dSPadmanabh Ratnakar 			       OPCODE_COMMON_SET_MAC_LIST, sizeof(*req),
3121590c391dSPadmanabh Ratnakar 			       wrb, &cmd);
3122590c391dSPadmanabh Ratnakar 
3123590c391dSPadmanabh Ratnakar 	req->hdr.domain = domain;
3124590c391dSPadmanabh Ratnakar 	req->mac_count = mac_count;
3125590c391dSPadmanabh Ratnakar 	if (mac_count)
3126590c391dSPadmanabh Ratnakar 		memcpy(req->mac, mac_array, ETH_ALEN*mac_count);
3127590c391dSPadmanabh Ratnakar 
3128590c391dSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
3129590c391dSPadmanabh Ratnakar 
3130590c391dSPadmanabh Ratnakar err:
3131a2cc4e0bSSathya Perla 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
3132590c391dSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
3133590c391dSPadmanabh Ratnakar 	return status;
3134590c391dSPadmanabh Ratnakar }
31354762f6ceSAjit Khaparde 
31363175d8c2SSathya Perla /* Wrapper to delete any active MACs and provision the new mac.
31373175d8c2SSathya Perla  * Changes to MAC_LIST are allowed iff none of the MAC addresses in the
31383175d8c2SSathya Perla  * current list are active.
31393175d8c2SSathya Perla  */
31403175d8c2SSathya Perla int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
31413175d8c2SSathya Perla {
31423175d8c2SSathya Perla 	bool active_mac = false;
31433175d8c2SSathya Perla 	u8 old_mac[ETH_ALEN];
31443175d8c2SSathya Perla 	u32 pmac_id;
31453175d8c2SSathya Perla 	int status;
31463175d8c2SSathya Perla 
31473175d8c2SSathya Perla 	status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
3148b188f090SSuresh Reddy 					  &pmac_id, if_id, dom);
3149b188f090SSuresh Reddy 
31503175d8c2SSathya Perla 	if (!status && active_mac)
31513175d8c2SSathya Perla 		be_cmd_pmac_del(adapter, if_id, pmac_id, dom);
31523175d8c2SSathya Perla 
31533175d8c2SSathya Perla 	return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom);
31543175d8c2SSathya Perla }
31553175d8c2SSathya Perla 
3156f1f3ee1bSAjit Khaparde int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
3157e7bcbd7bSKalesh AP 			  u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk)
3158f1f3ee1bSAjit Khaparde {
3159f1f3ee1bSAjit Khaparde 	struct be_mcc_wrb *wrb;
3160f1f3ee1bSAjit Khaparde 	struct be_cmd_req_set_hsw_config *req;
3161f1f3ee1bSAjit Khaparde 	void *ctxt;
3162f1f3ee1bSAjit Khaparde 	int status;
3163f1f3ee1bSAjit Khaparde 
3164f1f3ee1bSAjit Khaparde 	spin_lock_bh(&adapter->mcc_lock);
3165f1f3ee1bSAjit Khaparde 
3166f1f3ee1bSAjit Khaparde 	wrb = wrb_from_mccq(adapter);
3167f1f3ee1bSAjit Khaparde 	if (!wrb) {
3168f1f3ee1bSAjit Khaparde 		status = -EBUSY;
3169f1f3ee1bSAjit Khaparde 		goto err;
3170f1f3ee1bSAjit Khaparde 	}
3171f1f3ee1bSAjit Khaparde 
3172f1f3ee1bSAjit Khaparde 	req = embedded_payload(wrb);
3173f1f3ee1bSAjit Khaparde 	ctxt = &req->context;
3174f1f3ee1bSAjit Khaparde 
3175f1f3ee1bSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3176a2cc4e0bSSathya Perla 			       OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb,
3177a2cc4e0bSSathya Perla 			       NULL);
3178f1f3ee1bSAjit Khaparde 
3179f1f3ee1bSAjit Khaparde 	req->hdr.domain = domain;
3180f1f3ee1bSAjit Khaparde 	AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id);
3181f1f3ee1bSAjit Khaparde 	if (pvid) {
3182f1f3ee1bSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1);
3183f1f3ee1bSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid);
3184f1f3ee1bSAjit Khaparde 	}
3185a77dcb8cSAjit Khaparde 	if (!BEx_chip(adapter) && hsw_mode) {
3186a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, interface_id,
3187a77dcb8cSAjit Khaparde 			      ctxt, adapter->hba_port_num);
3188a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1);
3189a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type,
3190a77dcb8cSAjit Khaparde 			      ctxt, hsw_mode);
3191a77dcb8cSAjit Khaparde 	}
3192f1f3ee1bSAjit Khaparde 
3193e7bcbd7bSKalesh AP 	/* Enable/disable both mac and vlan spoof checking */
3194e7bcbd7bSKalesh AP 	if (!BEx_chip(adapter) && spoofchk) {
3195e7bcbd7bSKalesh AP 		AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk,
3196e7bcbd7bSKalesh AP 			      ctxt, spoofchk);
3197e7bcbd7bSKalesh AP 		AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk,
3198e7bcbd7bSKalesh AP 			      ctxt, spoofchk);
3199e7bcbd7bSKalesh AP 	}
3200e7bcbd7bSKalesh AP 
3201f1f3ee1bSAjit Khaparde 	be_dws_cpu_to_le(req->context, sizeof(req->context));
3202f1f3ee1bSAjit Khaparde 	status = be_mcc_notify_wait(adapter);
3203f1f3ee1bSAjit Khaparde 
3204f1f3ee1bSAjit Khaparde err:
3205f1f3ee1bSAjit Khaparde 	spin_unlock_bh(&adapter->mcc_lock);
3206f1f3ee1bSAjit Khaparde 	return status;
3207f1f3ee1bSAjit Khaparde }
3208f1f3ee1bSAjit Khaparde 
3209f1f3ee1bSAjit Khaparde /* Get Hyper switch config */
3210f1f3ee1bSAjit Khaparde int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
3211e7bcbd7bSKalesh AP 			  u32 domain, u16 intf_id, u8 *mode, bool *spoofchk)
3212f1f3ee1bSAjit Khaparde {
3213f1f3ee1bSAjit Khaparde 	struct be_mcc_wrb *wrb;
3214f1f3ee1bSAjit Khaparde 	struct be_cmd_req_get_hsw_config *req;
3215f1f3ee1bSAjit Khaparde 	void *ctxt;
3216f1f3ee1bSAjit Khaparde 	int status;
3217f1f3ee1bSAjit Khaparde 	u16 vid;
3218f1f3ee1bSAjit Khaparde 
3219f1f3ee1bSAjit Khaparde 	spin_lock_bh(&adapter->mcc_lock);
3220f1f3ee1bSAjit Khaparde 
3221f1f3ee1bSAjit Khaparde 	wrb = wrb_from_mccq(adapter);
3222f1f3ee1bSAjit Khaparde 	if (!wrb) {
3223f1f3ee1bSAjit Khaparde 		status = -EBUSY;
3224f1f3ee1bSAjit Khaparde 		goto err;
3225f1f3ee1bSAjit Khaparde 	}
3226f1f3ee1bSAjit Khaparde 
3227f1f3ee1bSAjit Khaparde 	req = embedded_payload(wrb);
3228f1f3ee1bSAjit Khaparde 	ctxt = &req->context;
3229f1f3ee1bSAjit Khaparde 
3230f1f3ee1bSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3231a2cc4e0bSSathya Perla 			       OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb,
3232a2cc4e0bSSathya Perla 			       NULL);
3233f1f3ee1bSAjit Khaparde 
3234f1f3ee1bSAjit Khaparde 	req->hdr.domain = domain;
3235a77dcb8cSAjit Khaparde 	AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
3236a77dcb8cSAjit Khaparde 		      ctxt, intf_id);
3237f1f3ee1bSAjit Khaparde 	AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1);
3238a77dcb8cSAjit Khaparde 
32392c07c1d7SVasundhara Volam 	if (!BEx_chip(adapter) && mode) {
3240a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
3241a77dcb8cSAjit Khaparde 			      ctxt, adapter->hba_port_num);
3242a77dcb8cSAjit Khaparde 		AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1);
3243a77dcb8cSAjit Khaparde 	}
3244f1f3ee1bSAjit Khaparde 	be_dws_cpu_to_le(req->context, sizeof(req->context));
3245f1f3ee1bSAjit Khaparde 
3246f1f3ee1bSAjit Khaparde 	status = be_mcc_notify_wait(adapter);
3247f1f3ee1bSAjit Khaparde 	if (!status) {
3248f1f3ee1bSAjit Khaparde 		struct be_cmd_resp_get_hsw_config *resp =
3249f1f3ee1bSAjit Khaparde 						embedded_payload(wrb);
325003d28ffeSKalesh AP 
3251a2cc4e0bSSathya Perla 		be_dws_le_to_cpu(&resp->context, sizeof(resp->context));
3252f1f3ee1bSAjit Khaparde 		vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3253f1f3ee1bSAjit Khaparde 				    pvid, &resp->context);
3254a77dcb8cSAjit Khaparde 		if (pvid)
3255f1f3ee1bSAjit Khaparde 			*pvid = le16_to_cpu(vid);
3256a77dcb8cSAjit Khaparde 		if (mode)
3257a77dcb8cSAjit Khaparde 			*mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3258a77dcb8cSAjit Khaparde 					      port_fwd_type, &resp->context);
3259e7bcbd7bSKalesh AP 		if (spoofchk)
3260e7bcbd7bSKalesh AP 			*spoofchk =
3261e7bcbd7bSKalesh AP 				AMAP_GET_BITS(struct amap_get_hsw_resp_context,
3262e7bcbd7bSKalesh AP 					      spoofchk, &resp->context);
3263f1f3ee1bSAjit Khaparde 	}
3264f1f3ee1bSAjit Khaparde 
3265f1f3ee1bSAjit Khaparde err:
3266f1f3ee1bSAjit Khaparde 	spin_unlock_bh(&adapter->mcc_lock);
3267f1f3ee1bSAjit Khaparde 	return status;
3268f1f3ee1bSAjit Khaparde }
3269f1f3ee1bSAjit Khaparde 
3270f7062ee5SSathya Perla static bool be_is_wol_excluded(struct be_adapter *adapter)
3271f7062ee5SSathya Perla {
3272f7062ee5SSathya Perla 	struct pci_dev *pdev = adapter->pdev;
3273f7062ee5SSathya Perla 
3274f7062ee5SSathya Perla 	if (!be_physfn(adapter))
3275f7062ee5SSathya Perla 		return true;
3276f7062ee5SSathya Perla 
3277f7062ee5SSathya Perla 	switch (pdev->subsystem_device) {
3278f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID1:
3279f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID2:
3280f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID3:
3281f7062ee5SSathya Perla 	case OC_SUBSYS_DEVICE_ID4:
3282f7062ee5SSathya Perla 		return true;
3283f7062ee5SSathya Perla 	default:
3284f7062ee5SSathya Perla 		return false;
3285f7062ee5SSathya Perla 	}
3286f7062ee5SSathya Perla }
3287f7062ee5SSathya Perla 
32884762f6ceSAjit Khaparde int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
32894762f6ceSAjit Khaparde {
32904762f6ceSAjit Khaparde 	struct be_mcc_wrb *wrb;
32914762f6ceSAjit Khaparde 	struct be_cmd_req_acpi_wol_magic_config_v1 *req;
329276a9e08eSSuresh Reddy 	int status = 0;
32934762f6ceSAjit Khaparde 	struct be_dma_mem cmd;
32944762f6ceSAjit Khaparde 
3295f25b119cSPadmanabh Ratnakar 	if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
3296f25b119cSPadmanabh Ratnakar 			    CMD_SUBSYSTEM_ETH))
3297f25b119cSPadmanabh Ratnakar 		return -EPERM;
3298f25b119cSPadmanabh Ratnakar 
329976a9e08eSSuresh Reddy 	if (be_is_wol_excluded(adapter))
330076a9e08eSSuresh Reddy 		return status;
330176a9e08eSSuresh Reddy 
3302d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3303d98ef50fSSuresh Reddy 		return -1;
3304d98ef50fSSuresh Reddy 
33054762f6ceSAjit Khaparde 	memset(&cmd, 0, sizeof(struct be_dma_mem));
33064762f6ceSAjit Khaparde 	cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
3307a2cc4e0bSSathya Perla 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
33084762f6ceSAjit Khaparde 	if (!cmd.va) {
3309a2cc4e0bSSathya Perla 		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
3310d98ef50fSSuresh Reddy 		status = -ENOMEM;
3311d98ef50fSSuresh Reddy 		goto err;
33124762f6ceSAjit Khaparde 	}
33134762f6ceSAjit Khaparde 
33144762f6ceSAjit Khaparde 	wrb = wrb_from_mbox(adapter);
33154762f6ceSAjit Khaparde 	if (!wrb) {
33164762f6ceSAjit Khaparde 		status = -EBUSY;
33174762f6ceSAjit Khaparde 		goto err;
33184762f6ceSAjit Khaparde 	}
33194762f6ceSAjit Khaparde 
33204762f6ceSAjit Khaparde 	req = cmd.va;
33214762f6ceSAjit Khaparde 
33224762f6ceSAjit Khaparde 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
33234762f6ceSAjit Khaparde 			       OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
332476a9e08eSSuresh Reddy 			       sizeof(*req), wrb, &cmd);
33254762f6ceSAjit Khaparde 
33264762f6ceSAjit Khaparde 	req->hdr.version = 1;
33274762f6ceSAjit Khaparde 	req->query_options = BE_GET_WOL_CAP;
33284762f6ceSAjit Khaparde 
33294762f6ceSAjit Khaparde 	status = be_mbox_notify_wait(adapter);
33304762f6ceSAjit Khaparde 	if (!status) {
33314762f6ceSAjit Khaparde 		struct be_cmd_resp_acpi_wol_magic_config_v1 *resp;
333203d28ffeSKalesh AP 
33334762f6ceSAjit Khaparde 		resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va;
33344762f6ceSAjit Khaparde 
33354762f6ceSAjit Khaparde 		adapter->wol_cap = resp->wol_settings;
333676a9e08eSSuresh Reddy 		if (adapter->wol_cap & BE_WOL_CAP)
333776a9e08eSSuresh Reddy 			adapter->wol_en = true;
33384762f6ceSAjit Khaparde 	}
33394762f6ceSAjit Khaparde err:
33404762f6ceSAjit Khaparde 	mutex_unlock(&adapter->mbox_lock);
3341d98ef50fSSuresh Reddy 	if (cmd.va)
33424762f6ceSAjit Khaparde 		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
33434762f6ceSAjit Khaparde 	return status;
3344941a77d5SSomnath Kotur 
3345941a77d5SSomnath Kotur }
3346baaa08d1SVasundhara Volam 
3347baaa08d1SVasundhara Volam int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level)
3348baaa08d1SVasundhara Volam {
3349baaa08d1SVasundhara Volam 	struct be_dma_mem extfat_cmd;
3350baaa08d1SVasundhara Volam 	struct be_fat_conf_params *cfgs;
3351baaa08d1SVasundhara Volam 	int status;
3352baaa08d1SVasundhara Volam 	int i, j;
3353baaa08d1SVasundhara Volam 
3354baaa08d1SVasundhara Volam 	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
3355baaa08d1SVasundhara Volam 	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
3356baaa08d1SVasundhara Volam 	extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
3357baaa08d1SVasundhara Volam 					     &extfat_cmd.dma);
3358baaa08d1SVasundhara Volam 	if (!extfat_cmd.va)
3359baaa08d1SVasundhara Volam 		return -ENOMEM;
3360baaa08d1SVasundhara Volam 
3361baaa08d1SVasundhara Volam 	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
3362baaa08d1SVasundhara Volam 	if (status)
3363baaa08d1SVasundhara Volam 		goto err;
3364baaa08d1SVasundhara Volam 
3365baaa08d1SVasundhara Volam 	cfgs = (struct be_fat_conf_params *)
3366baaa08d1SVasundhara Volam 			(extfat_cmd.va + sizeof(struct be_cmd_resp_hdr));
3367baaa08d1SVasundhara Volam 	for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) {
3368baaa08d1SVasundhara Volam 		u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes);
336903d28ffeSKalesh AP 
3370baaa08d1SVasundhara Volam 		for (j = 0; j < num_modes; j++) {
3371baaa08d1SVasundhara Volam 			if (cfgs->module[i].trace_lvl[j].mode == MODE_UART)
3372baaa08d1SVasundhara Volam 				cfgs->module[i].trace_lvl[j].dbg_lvl =
3373baaa08d1SVasundhara Volam 							cpu_to_le32(level);
3374baaa08d1SVasundhara Volam 		}
3375baaa08d1SVasundhara Volam 	}
3376baaa08d1SVasundhara Volam 
3377baaa08d1SVasundhara Volam 	status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs);
3378baaa08d1SVasundhara Volam err:
3379baaa08d1SVasundhara Volam 	pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
3380baaa08d1SVasundhara Volam 			    extfat_cmd.dma);
3381baaa08d1SVasundhara Volam 	return status;
3382baaa08d1SVasundhara Volam }
3383baaa08d1SVasundhara Volam 
3384baaa08d1SVasundhara Volam int be_cmd_get_fw_log_level(struct be_adapter *adapter)
3385baaa08d1SVasundhara Volam {
3386baaa08d1SVasundhara Volam 	struct be_dma_mem extfat_cmd;
3387baaa08d1SVasundhara Volam 	struct be_fat_conf_params *cfgs;
3388baaa08d1SVasundhara Volam 	int status, j;
3389baaa08d1SVasundhara Volam 	int level = 0;
3390baaa08d1SVasundhara Volam 
3391baaa08d1SVasundhara Volam 	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
3392baaa08d1SVasundhara Volam 	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
3393baaa08d1SVasundhara Volam 	extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
3394baaa08d1SVasundhara Volam 					     &extfat_cmd.dma);
3395baaa08d1SVasundhara Volam 
3396baaa08d1SVasundhara Volam 	if (!extfat_cmd.va) {
3397baaa08d1SVasundhara Volam 		dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
3398baaa08d1SVasundhara Volam 			__func__);
3399baaa08d1SVasundhara Volam 		goto err;
3400baaa08d1SVasundhara Volam 	}
3401baaa08d1SVasundhara Volam 
3402baaa08d1SVasundhara Volam 	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
3403baaa08d1SVasundhara Volam 	if (!status) {
3404baaa08d1SVasundhara Volam 		cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
3405baaa08d1SVasundhara Volam 						sizeof(struct be_cmd_resp_hdr));
340603d28ffeSKalesh AP 
3407baaa08d1SVasundhara Volam 		for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) {
3408baaa08d1SVasundhara Volam 			if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
3409baaa08d1SVasundhara Volam 				level = cfgs->module[0].trace_lvl[j].dbg_lvl;
3410baaa08d1SVasundhara Volam 		}
3411baaa08d1SVasundhara Volam 	}
3412baaa08d1SVasundhara Volam 	pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
3413baaa08d1SVasundhara Volam 			    extfat_cmd.dma);
3414baaa08d1SVasundhara Volam err:
3415baaa08d1SVasundhara Volam 	return level;
3416baaa08d1SVasundhara Volam }
3417baaa08d1SVasundhara Volam 
3418941a77d5SSomnath Kotur int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
3419941a77d5SSomnath Kotur 				   struct be_dma_mem *cmd)
3420941a77d5SSomnath Kotur {
3421941a77d5SSomnath Kotur 	struct be_mcc_wrb *wrb;
3422941a77d5SSomnath Kotur 	struct be_cmd_req_get_ext_fat_caps *req;
3423941a77d5SSomnath Kotur 	int status;
3424941a77d5SSomnath Kotur 
3425941a77d5SSomnath Kotur 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3426941a77d5SSomnath Kotur 		return -1;
3427941a77d5SSomnath Kotur 
3428941a77d5SSomnath Kotur 	wrb = wrb_from_mbox(adapter);
3429941a77d5SSomnath Kotur 	if (!wrb) {
3430941a77d5SSomnath Kotur 		status = -EBUSY;
3431941a77d5SSomnath Kotur 		goto err;
3432941a77d5SSomnath Kotur 	}
3433941a77d5SSomnath Kotur 
3434941a77d5SSomnath Kotur 	req = cmd->va;
3435941a77d5SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3436941a77d5SSomnath Kotur 			       OPCODE_COMMON_GET_EXT_FAT_CAPABILITES,
3437941a77d5SSomnath Kotur 			       cmd->size, wrb, cmd);
3438941a77d5SSomnath Kotur 	req->parameter_type = cpu_to_le32(1);
3439941a77d5SSomnath Kotur 
3440941a77d5SSomnath Kotur 	status = be_mbox_notify_wait(adapter);
3441941a77d5SSomnath Kotur err:
3442941a77d5SSomnath Kotur 	mutex_unlock(&adapter->mbox_lock);
3443941a77d5SSomnath Kotur 	return status;
3444941a77d5SSomnath Kotur }
3445941a77d5SSomnath Kotur 
3446941a77d5SSomnath Kotur int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
3447941a77d5SSomnath Kotur 				   struct be_dma_mem *cmd,
3448941a77d5SSomnath Kotur 				   struct be_fat_conf_params *configs)
3449941a77d5SSomnath Kotur {
3450941a77d5SSomnath Kotur 	struct be_mcc_wrb *wrb;
3451941a77d5SSomnath Kotur 	struct be_cmd_req_set_ext_fat_caps *req;
3452941a77d5SSomnath Kotur 	int status;
3453941a77d5SSomnath Kotur 
3454941a77d5SSomnath Kotur 	spin_lock_bh(&adapter->mcc_lock);
3455941a77d5SSomnath Kotur 
3456941a77d5SSomnath Kotur 	wrb = wrb_from_mccq(adapter);
3457941a77d5SSomnath Kotur 	if (!wrb) {
3458941a77d5SSomnath Kotur 		status = -EBUSY;
3459941a77d5SSomnath Kotur 		goto err;
3460941a77d5SSomnath Kotur 	}
3461941a77d5SSomnath Kotur 
3462941a77d5SSomnath Kotur 	req = cmd->va;
3463941a77d5SSomnath Kotur 	memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params));
3464941a77d5SSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3465941a77d5SSomnath Kotur 			       OPCODE_COMMON_SET_EXT_FAT_CAPABILITES,
3466941a77d5SSomnath Kotur 			       cmd->size, wrb, cmd);
3467941a77d5SSomnath Kotur 
3468941a77d5SSomnath Kotur 	status = be_mcc_notify_wait(adapter);
3469941a77d5SSomnath Kotur err:
3470941a77d5SSomnath Kotur 	spin_unlock_bh(&adapter->mcc_lock);
3471941a77d5SSomnath Kotur 	return status;
34724762f6ceSAjit Khaparde }
34736a4ab669SParav Pandit 
347421252377SVasundhara Volam int be_cmd_query_port_name(struct be_adapter *adapter)
3475b4e32a71SPadmanabh Ratnakar {
3476b4e32a71SPadmanabh Ratnakar 	struct be_cmd_req_get_port_name *req;
347721252377SVasundhara Volam 	struct be_mcc_wrb *wrb;
3478b4e32a71SPadmanabh Ratnakar 	int status;
3479b4e32a71SPadmanabh Ratnakar 
348021252377SVasundhara Volam 	if (mutex_lock_interruptible(&adapter->mbox_lock))
348121252377SVasundhara Volam 		return -1;
3482b4e32a71SPadmanabh Ratnakar 
348321252377SVasundhara Volam 	wrb = wrb_from_mbox(adapter);
3484b4e32a71SPadmanabh Ratnakar 	req = embedded_payload(wrb);
3485b4e32a71SPadmanabh Ratnakar 
3486b4e32a71SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3487b4e32a71SPadmanabh Ratnakar 			       OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb,
3488b4e32a71SPadmanabh Ratnakar 			       NULL);
348921252377SVasundhara Volam 	if (!BEx_chip(adapter))
3490b4e32a71SPadmanabh Ratnakar 		req->hdr.version = 1;
3491b4e32a71SPadmanabh Ratnakar 
349221252377SVasundhara Volam 	status = be_mbox_notify_wait(adapter);
3493b4e32a71SPadmanabh Ratnakar 	if (!status) {
3494b4e32a71SPadmanabh Ratnakar 		struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb);
349503d28ffeSKalesh AP 
349621252377SVasundhara Volam 		adapter->port_name = resp->port_name[adapter->hba_port_num];
3497b4e32a71SPadmanabh Ratnakar 	} else {
349821252377SVasundhara Volam 		adapter->port_name = adapter->hba_port_num + '0';
3499b4e32a71SPadmanabh Ratnakar 	}
350021252377SVasundhara Volam 
350121252377SVasundhara Volam 	mutex_unlock(&adapter->mbox_lock);
3502b4e32a71SPadmanabh Ratnakar 	return status;
3503b4e32a71SPadmanabh Ratnakar }
3504b4e32a71SPadmanabh Ratnakar 
350510cccf60SVasundhara Volam /* Descriptor type */
350610cccf60SVasundhara Volam enum {
350710cccf60SVasundhara Volam 	FUNC_DESC = 1,
350810cccf60SVasundhara Volam 	VFT_DESC = 2
350910cccf60SVasundhara Volam };
351010cccf60SVasundhara Volam 
351110cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
351210cccf60SVasundhara Volam 					       int desc_type)
3513abb93951SPadmanabh Ratnakar {
3514150d58c7SVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
351510cccf60SVasundhara Volam 	struct be_nic_res_desc *nic;
3516abb93951SPadmanabh Ratnakar 	int i;
3517abb93951SPadmanabh Ratnakar 
3518abb93951SPadmanabh Ratnakar 	for (i = 0; i < desc_count; i++) {
3519150d58c7SVasundhara Volam 		if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
352010cccf60SVasundhara Volam 		    hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) {
352110cccf60SVasundhara Volam 			nic = (struct be_nic_res_desc *)hdr;
352210cccf60SVasundhara Volam 			if (desc_type == FUNC_DESC ||
352310cccf60SVasundhara Volam 			    (desc_type == VFT_DESC &&
352410cccf60SVasundhara Volam 			     nic->flags & (1 << VFT_SHIFT)))
352510cccf60SVasundhara Volam 				return nic;
352610cccf60SVasundhara Volam 		}
3527150d58c7SVasundhara Volam 
3528150d58c7SVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
3529150d58c7SVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
3530150d58c7SVasundhara Volam 	}
3531950e2958SWei Yang 	return NULL;
3532abb93951SPadmanabh Ratnakar }
3533abb93951SPadmanabh Ratnakar 
353410cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count)
353510cccf60SVasundhara Volam {
353610cccf60SVasundhara Volam 	return be_get_nic_desc(buf, desc_count, VFT_DESC);
353710cccf60SVasundhara Volam }
353810cccf60SVasundhara Volam 
353910cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count)
354010cccf60SVasundhara Volam {
354110cccf60SVasundhara Volam 	return be_get_nic_desc(buf, desc_count, FUNC_DESC);
354210cccf60SVasundhara Volam }
354310cccf60SVasundhara Volam 
3544150d58c7SVasundhara Volam static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf,
3545150d58c7SVasundhara Volam 						 u32 desc_count)
3546150d58c7SVasundhara Volam {
3547150d58c7SVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
3548150d58c7SVasundhara Volam 	struct be_pcie_res_desc *pcie;
3549150d58c7SVasundhara Volam 	int i;
3550150d58c7SVasundhara Volam 
3551150d58c7SVasundhara Volam 	for (i = 0; i < desc_count; i++) {
3552150d58c7SVasundhara Volam 		if ((hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 ||
3553150d58c7SVasundhara Volam 		     hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1)) {
3554150d58c7SVasundhara Volam 			pcie = (struct be_pcie_res_desc	*)hdr;
3555150d58c7SVasundhara Volam 			if (pcie->pf_num == devfn)
3556150d58c7SVasundhara Volam 				return pcie;
3557150d58c7SVasundhara Volam 		}
3558150d58c7SVasundhara Volam 
3559150d58c7SVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
3560150d58c7SVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
3561150d58c7SVasundhara Volam 	}
3562abb93951SPadmanabh Ratnakar 	return NULL;
3563abb93951SPadmanabh Ratnakar }
3564abb93951SPadmanabh Ratnakar 
3565f93f160bSVasundhara Volam static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
3566f93f160bSVasundhara Volam {
3567f93f160bSVasundhara Volam 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
3568f93f160bSVasundhara Volam 	int i;
3569f93f160bSVasundhara Volam 
3570f93f160bSVasundhara Volam 	for (i = 0; i < desc_count; i++) {
3571f93f160bSVasundhara Volam 		if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
3572f93f160bSVasundhara Volam 			return (struct be_port_res_desc *)hdr;
3573f93f160bSVasundhara Volam 
3574f93f160bSVasundhara Volam 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
3575f93f160bSVasundhara Volam 		hdr = (void *)hdr + hdr->desc_len;
3576f93f160bSVasundhara Volam 	}
3577f93f160bSVasundhara Volam 	return NULL;
3578f93f160bSVasundhara Volam }
3579f93f160bSVasundhara Volam 
358092bf14abSSathya Perla static void be_copy_nic_desc(struct be_resources *res,
358192bf14abSSathya Perla 			     struct be_nic_res_desc *desc)
358292bf14abSSathya Perla {
358392bf14abSSathya Perla 	res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count);
358492bf14abSSathya Perla 	res->max_vlans = le16_to_cpu(desc->vlan_count);
358592bf14abSSathya Perla 	res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
358692bf14abSSathya Perla 	res->max_tx_qs = le16_to_cpu(desc->txq_count);
358792bf14abSSathya Perla 	res->max_rss_qs = le16_to_cpu(desc->rssq_count);
358892bf14abSSathya Perla 	res->max_rx_qs = le16_to_cpu(desc->rq_count);
358992bf14abSSathya Perla 	res->max_evt_qs = le16_to_cpu(desc->eq_count);
3590f2858738SVasundhara Volam 	res->max_cq_count = le16_to_cpu(desc->cq_count);
3591f2858738SVasundhara Volam 	res->max_iface_count = le16_to_cpu(desc->iface_count);
3592f2858738SVasundhara Volam 	res->max_mcc_count = le16_to_cpu(desc->mcc_count);
359392bf14abSSathya Perla 	/* Clear flags that driver is not interested in */
359492bf14abSSathya Perla 	res->if_cap_flags = le32_to_cpu(desc->cap_flags) &
359592bf14abSSathya Perla 				BE_IF_CAP_FLAGS_WANT;
359692bf14abSSathya Perla }
359792bf14abSSathya Perla 
3598abb93951SPadmanabh Ratnakar /* Uses Mbox */
359992bf14abSSathya Perla int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
3600abb93951SPadmanabh Ratnakar {
3601abb93951SPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
3602abb93951SPadmanabh Ratnakar 	struct be_cmd_req_get_func_config *req;
3603abb93951SPadmanabh Ratnakar 	int status;
3604abb93951SPadmanabh Ratnakar 	struct be_dma_mem cmd;
3605abb93951SPadmanabh Ratnakar 
3606d98ef50fSSuresh Reddy 	if (mutex_lock_interruptible(&adapter->mbox_lock))
3607d98ef50fSSuresh Reddy 		return -1;
3608d98ef50fSSuresh Reddy 
3609abb93951SPadmanabh Ratnakar 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3610abb93951SPadmanabh Ratnakar 	cmd.size = sizeof(struct be_cmd_resp_get_func_config);
3611a2cc4e0bSSathya Perla 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
3612abb93951SPadmanabh Ratnakar 	if (!cmd.va) {
3613abb93951SPadmanabh Ratnakar 		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
3614d98ef50fSSuresh Reddy 		status = -ENOMEM;
3615d98ef50fSSuresh Reddy 		goto err;
3616abb93951SPadmanabh Ratnakar 	}
3617abb93951SPadmanabh Ratnakar 
3618abb93951SPadmanabh Ratnakar 	wrb = wrb_from_mbox(adapter);
3619abb93951SPadmanabh Ratnakar 	if (!wrb) {
3620abb93951SPadmanabh Ratnakar 		status = -EBUSY;
3621abb93951SPadmanabh Ratnakar 		goto err;
3622abb93951SPadmanabh Ratnakar 	}
3623abb93951SPadmanabh Ratnakar 
3624abb93951SPadmanabh Ratnakar 	req = cmd.va;
3625abb93951SPadmanabh Ratnakar 
3626abb93951SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3627abb93951SPadmanabh Ratnakar 			       OPCODE_COMMON_GET_FUNC_CONFIG,
3628abb93951SPadmanabh Ratnakar 			       cmd.size, wrb, &cmd);
3629abb93951SPadmanabh Ratnakar 
363028710c55SKalesh AP 	if (skyhawk_chip(adapter))
363128710c55SKalesh AP 		req->hdr.version = 1;
363228710c55SKalesh AP 
3633abb93951SPadmanabh Ratnakar 	status = be_mbox_notify_wait(adapter);
3634abb93951SPadmanabh Ratnakar 	if (!status) {
3635abb93951SPadmanabh Ratnakar 		struct be_cmd_resp_get_func_config *resp = cmd.va;
3636abb93951SPadmanabh Ratnakar 		u32 desc_count = le32_to_cpu(resp->desc_count);
3637150d58c7SVasundhara Volam 		struct be_nic_res_desc *desc;
3638abb93951SPadmanabh Ratnakar 
363910cccf60SVasundhara Volam 		desc = be_get_func_nic_desc(resp->func_param, desc_count);
3640abb93951SPadmanabh Ratnakar 		if (!desc) {
3641abb93951SPadmanabh Ratnakar 			status = -EINVAL;
3642abb93951SPadmanabh Ratnakar 			goto err;
3643abb93951SPadmanabh Ratnakar 		}
3644abb93951SPadmanabh Ratnakar 
3645d5c18473SPadmanabh Ratnakar 		adapter->pf_number = desc->pf_num;
364692bf14abSSathya Perla 		be_copy_nic_desc(res, desc);
3647abb93951SPadmanabh Ratnakar 	}
3648abb93951SPadmanabh Ratnakar err:
3649abb93951SPadmanabh Ratnakar 	mutex_unlock(&adapter->mbox_lock);
3650d98ef50fSSuresh Reddy 	if (cmd.va)
3651d98ef50fSSuresh Reddy 		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
3652abb93951SPadmanabh Ratnakar 	return status;
3653abb93951SPadmanabh Ratnakar }
3654abb93951SPadmanabh Ratnakar 
3655ba48c0c9SVasundhara Volam /* Will use MBOX only if MCCQ has not been created */
365692bf14abSSathya Perla int be_cmd_get_profile_config(struct be_adapter *adapter,
3657f2858738SVasundhara Volam 			      struct be_resources *res, u8 query, u8 domain)
3658a05f99dbSVasundhara Volam {
3659150d58c7SVasundhara Volam 	struct be_cmd_resp_get_profile_config *resp;
3660ba48c0c9SVasundhara Volam 	struct be_cmd_req_get_profile_config *req;
366110cccf60SVasundhara Volam 	struct be_nic_res_desc *vf_res;
3662150d58c7SVasundhara Volam 	struct be_pcie_res_desc *pcie;
3663f93f160bSVasundhara Volam 	struct be_port_res_desc *port;
3664150d58c7SVasundhara Volam 	struct be_nic_res_desc *nic;
3665ba48c0c9SVasundhara Volam 	struct be_mcc_wrb wrb = {0};
3666a05f99dbSVasundhara Volam 	struct be_dma_mem cmd;
3667f2858738SVasundhara Volam 	u16 desc_count;
3668a05f99dbSVasundhara Volam 	int status;
3669a05f99dbSVasundhara Volam 
3670a05f99dbSVasundhara Volam 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3671a05f99dbSVasundhara Volam 	cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
3672150d58c7SVasundhara Volam 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
3673150d58c7SVasundhara Volam 	if (!cmd.va)
3674a05f99dbSVasundhara Volam 		return -ENOMEM;
3675a05f99dbSVasundhara Volam 
3676ba48c0c9SVasundhara Volam 	req = cmd.va;
3677ba48c0c9SVasundhara Volam 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3678ba48c0c9SVasundhara Volam 			       OPCODE_COMMON_GET_PROFILE_CONFIG,
3679ba48c0c9SVasundhara Volam 			       cmd.size, &wrb, &cmd);
3680ba48c0c9SVasundhara Volam 
3681ba48c0c9SVasundhara Volam 	req->hdr.domain = domain;
3682ba48c0c9SVasundhara Volam 	if (!lancer_chip(adapter))
3683ba48c0c9SVasundhara Volam 		req->hdr.version = 1;
3684ba48c0c9SVasundhara Volam 	req->type = ACTIVE_PROFILE_TYPE;
3685ba48c0c9SVasundhara Volam 
3686f2858738SVasundhara Volam 	/* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the
3687f2858738SVasundhara Volam 	 * descriptors with all bits set to "1" for the fields which can be
3688f2858738SVasundhara Volam 	 * modified using SET_PROFILE_CONFIG cmd.
3689f2858738SVasundhara Volam 	 */
3690f2858738SVasundhara Volam 	if (query == RESOURCE_MODIFIABLE)
3691f2858738SVasundhara Volam 		req->type |= QUERY_MODIFIABLE_FIELDS_TYPE;
3692f2858738SVasundhara Volam 
3693ba48c0c9SVasundhara Volam 	status = be_cmd_notify_wait(adapter, &wrb);
3694150d58c7SVasundhara Volam 	if (status)
3695abb93951SPadmanabh Ratnakar 		goto err;
3696150d58c7SVasundhara Volam 
3697150d58c7SVasundhara Volam 	resp = cmd.va;
3698f2858738SVasundhara Volam 	desc_count = le16_to_cpu(resp->desc_count);
3699150d58c7SVasundhara Volam 
3700150d58c7SVasundhara Volam 	pcie = be_get_pcie_desc(adapter->pdev->devfn, resp->func_param,
3701150d58c7SVasundhara Volam 				desc_count);
3702150d58c7SVasundhara Volam 	if (pcie)
370392bf14abSSathya Perla 		res->max_vfs = le16_to_cpu(pcie->num_vfs);
3704150d58c7SVasundhara Volam 
3705f93f160bSVasundhara Volam 	port = be_get_port_desc(resp->func_param, desc_count);
3706f93f160bSVasundhara Volam 	if (port)
3707f93f160bSVasundhara Volam 		adapter->mc_type = port->mc_type;
3708f93f160bSVasundhara Volam 
370910cccf60SVasundhara Volam 	nic = be_get_func_nic_desc(resp->func_param, desc_count);
371092bf14abSSathya Perla 	if (nic)
371192bf14abSSathya Perla 		be_copy_nic_desc(res, nic);
371292bf14abSSathya Perla 
371310cccf60SVasundhara Volam 	vf_res = be_get_vft_desc(resp->func_param, desc_count);
371410cccf60SVasundhara Volam 	if (vf_res)
371510cccf60SVasundhara Volam 		res->vf_if_cap_flags = vf_res->cap_flags;
3716abb93951SPadmanabh Ratnakar err:
3717a05f99dbSVasundhara Volam 	if (cmd.va)
3718150d58c7SVasundhara Volam 		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
3719abb93951SPadmanabh Ratnakar 	return status;
3720abb93951SPadmanabh Ratnakar }
3721abb93951SPadmanabh Ratnakar 
3722bec84e6bSVasundhara Volam /* Will use MBOX only if MCCQ has not been created */
3723bec84e6bSVasundhara Volam static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
3724bec84e6bSVasundhara Volam 				     int size, int count, u8 version, u8 domain)
3725d5c18473SPadmanabh Ratnakar {
3726d5c18473SPadmanabh Ratnakar 	struct be_cmd_req_set_profile_config *req;
3727bec84e6bSVasundhara Volam 	struct be_mcc_wrb wrb = {0};
3728bec84e6bSVasundhara Volam 	struct be_dma_mem cmd;
3729d5c18473SPadmanabh Ratnakar 	int status;
3730d5c18473SPadmanabh Ratnakar 
3731bec84e6bSVasundhara Volam 	memset(&cmd, 0, sizeof(struct be_dma_mem));
3732bec84e6bSVasundhara Volam 	cmd.size = sizeof(struct be_cmd_req_set_profile_config);
3733bec84e6bSVasundhara Volam 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
3734bec84e6bSVasundhara Volam 	if (!cmd.va)
3735bec84e6bSVasundhara Volam 		return -ENOMEM;
3736d5c18473SPadmanabh Ratnakar 
3737bec84e6bSVasundhara Volam 	req = cmd.va;
3738d5c18473SPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3739bec84e6bSVasundhara Volam 			       OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size,
3740bec84e6bSVasundhara Volam 			       &wrb, &cmd);
3741a401801cSSathya Perla 	req->hdr.version = version;
3742d5c18473SPadmanabh Ratnakar 	req->hdr.domain = domain;
3743bec84e6bSVasundhara Volam 	req->desc_count = cpu_to_le32(count);
3744a401801cSSathya Perla 	memcpy(req->desc, desc, size);
3745d5c18473SPadmanabh Ratnakar 
3746bec84e6bSVasundhara Volam 	status = be_cmd_notify_wait(adapter, &wrb);
3747bec84e6bSVasundhara Volam 
3748bec84e6bSVasundhara Volam 	if (cmd.va)
3749bec84e6bSVasundhara Volam 		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
3750d5c18473SPadmanabh Ratnakar 	return status;
3751d5c18473SPadmanabh Ratnakar }
3752d5c18473SPadmanabh Ratnakar 
3753a401801cSSathya Perla /* Mark all fields invalid */
3754bec84e6bSVasundhara Volam static void be_reset_nic_desc(struct be_nic_res_desc *nic)
3755a401801cSSathya Perla {
3756a401801cSSathya Perla 	memset(nic, 0, sizeof(*nic));
3757a401801cSSathya Perla 	nic->unicast_mac_count = 0xFFFF;
3758a401801cSSathya Perla 	nic->mcc_count = 0xFFFF;
3759a401801cSSathya Perla 	nic->vlan_count = 0xFFFF;
3760a401801cSSathya Perla 	nic->mcast_mac_count = 0xFFFF;
3761a401801cSSathya Perla 	nic->txq_count = 0xFFFF;
3762a401801cSSathya Perla 	nic->rq_count = 0xFFFF;
3763a401801cSSathya Perla 	nic->rssq_count = 0xFFFF;
3764a401801cSSathya Perla 	nic->lro_count = 0xFFFF;
3765a401801cSSathya Perla 	nic->cq_count = 0xFFFF;
3766a401801cSSathya Perla 	nic->toe_conn_count = 0xFFFF;
3767a401801cSSathya Perla 	nic->eq_count = 0xFFFF;
37680f77ba73SRavikumar Nelavelli 	nic->iface_count = 0xFFFF;
3769a401801cSSathya Perla 	nic->link_param = 0xFF;
37700f77ba73SRavikumar Nelavelli 	nic->channel_id_param = cpu_to_le16(0xF000);
3771a401801cSSathya Perla 	nic->acpi_params = 0xFF;
3772a401801cSSathya Perla 	nic->wol_param = 0x0F;
37730f77ba73SRavikumar Nelavelli 	nic->tunnel_iface_count = 0xFFFF;
37740f77ba73SRavikumar Nelavelli 	nic->direct_tenant_iface_count = 0xFFFF;
3775bec84e6bSVasundhara Volam 	nic->bw_min = 0xFFFFFFFF;
3776a401801cSSathya Perla 	nic->bw_max = 0xFFFFFFFF;
3777a401801cSSathya Perla }
3778a401801cSSathya Perla 
3779bec84e6bSVasundhara Volam /* Mark all fields invalid */
3780bec84e6bSVasundhara Volam static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie)
3781bec84e6bSVasundhara Volam {
3782bec84e6bSVasundhara Volam 	memset(pcie, 0, sizeof(*pcie));
3783bec84e6bSVasundhara Volam 	pcie->sriov_state = 0xFF;
3784bec84e6bSVasundhara Volam 	pcie->pf_state = 0xFF;
3785bec84e6bSVasundhara Volam 	pcie->pf_type = 0xFF;
3786bec84e6bSVasundhara Volam 	pcie->num_vfs = 0xFFFF;
3787bec84e6bSVasundhara Volam }
3788bec84e6bSVasundhara Volam 
37890f77ba73SRavikumar Nelavelli int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
37900f77ba73SRavikumar Nelavelli 		      u8 domain)
3791a401801cSSathya Perla {
3792a401801cSSathya Perla 	struct be_nic_res_desc nic_desc;
37930f77ba73SRavikumar Nelavelli 	u32 bw_percent;
37940f77ba73SRavikumar Nelavelli 	u16 version = 0;
37950f77ba73SRavikumar Nelavelli 
37960f77ba73SRavikumar Nelavelli 	if (BE3_chip(adapter))
37970f77ba73SRavikumar Nelavelli 		return be_cmd_set_qos(adapter, max_rate / 10, domain);
3798a401801cSSathya Perla 
3799a401801cSSathya Perla 	be_reset_nic_desc(&nic_desc);
38000f77ba73SRavikumar Nelavelli 	nic_desc.pf_num = adapter->pf_number;
38010f77ba73SRavikumar Nelavelli 	nic_desc.vf_num = domain;
380258bdeaa6SKalesh AP 	nic_desc.bw_min = 0;
38030f77ba73SRavikumar Nelavelli 	if (lancer_chip(adapter)) {
3804a401801cSSathya Perla 		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
3805a401801cSSathya Perla 		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
3806a401801cSSathya Perla 		nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
3807a401801cSSathya Perla 					(1 << NOSV_SHIFT);
38080f77ba73SRavikumar Nelavelli 		nic_desc.bw_max = cpu_to_le32(max_rate / 10);
38090f77ba73SRavikumar Nelavelli 	} else {
38100f77ba73SRavikumar Nelavelli 		version = 1;
38110f77ba73SRavikumar Nelavelli 		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
38120f77ba73SRavikumar Nelavelli 		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
38130f77ba73SRavikumar Nelavelli 		nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
38140f77ba73SRavikumar Nelavelli 		bw_percent = max_rate ? (max_rate * 100) / link_speed : 100;
38150f77ba73SRavikumar Nelavelli 		nic_desc.bw_max = cpu_to_le32(bw_percent);
38160f77ba73SRavikumar Nelavelli 	}
3817a401801cSSathya Perla 
3818a401801cSSathya Perla 	return be_cmd_set_profile_config(adapter, &nic_desc,
38190f77ba73SRavikumar Nelavelli 					 nic_desc.hdr.desc_len,
3820bec84e6bSVasundhara Volam 					 1, version, domain);
3821bec84e6bSVasundhara Volam }
3822bec84e6bSVasundhara Volam 
3823f2858738SVasundhara Volam static void be_fill_vf_res_template(struct be_adapter *adapter,
3824f2858738SVasundhara Volam 				    struct be_resources pool_res,
3825f2858738SVasundhara Volam 				    u16 num_vfs, u16 num_vf_qs,
3826f2858738SVasundhara Volam 				    struct be_nic_res_desc *nic_vft)
3827f2858738SVasundhara Volam {
3828f2858738SVasundhara Volam 	u32 vf_if_cap_flags = pool_res.vf_if_cap_flags;
3829f2858738SVasundhara Volam 	struct be_resources res_mod = {0};
3830f2858738SVasundhara Volam 
3831f2858738SVasundhara Volam 	/* Resource with fields set to all '1's by GET_PROFILE_CONFIG cmd,
3832f2858738SVasundhara Volam 	 * which are modifiable using SET_PROFILE_CONFIG cmd.
3833f2858738SVasundhara Volam 	 */
3834f2858738SVasundhara Volam 	be_cmd_get_profile_config(adapter, &res_mod, RESOURCE_MODIFIABLE, 0);
3835f2858738SVasundhara Volam 
3836f2858738SVasundhara Volam 	/* If RSS IFACE capability flags are modifiable for a VF, set the
3837f2858738SVasundhara Volam 	 * capability flag as valid and set RSS and DEFQ_RSS IFACE flags if
3838f2858738SVasundhara Volam 	 * more than 1 RSSQ is available for a VF.
3839f2858738SVasundhara Volam 	 * Otherwise, provision only 1 queue pair for VF.
3840f2858738SVasundhara Volam 	 */
3841f2858738SVasundhara Volam 	if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_RSS) {
3842f2858738SVasundhara Volam 		nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
3843f2858738SVasundhara Volam 		if (num_vf_qs > 1) {
3844f2858738SVasundhara Volam 			vf_if_cap_flags |= BE_IF_FLAGS_RSS;
3845f2858738SVasundhara Volam 			if (pool_res.if_cap_flags & BE_IF_FLAGS_DEFQ_RSS)
3846f2858738SVasundhara Volam 				vf_if_cap_flags |= BE_IF_FLAGS_DEFQ_RSS;
3847f2858738SVasundhara Volam 		} else {
3848f2858738SVasundhara Volam 			vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS |
3849f2858738SVasundhara Volam 					     BE_IF_FLAGS_DEFQ_RSS);
3850f2858738SVasundhara Volam 		}
3851f2858738SVasundhara Volam 
3852f2858738SVasundhara Volam 		nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
3853f2858738SVasundhara Volam 	} else {
3854f2858738SVasundhara Volam 		num_vf_qs = 1;
3855f2858738SVasundhara Volam 	}
3856f2858738SVasundhara Volam 
3857f2858738SVasundhara Volam 	nic_vft->rq_count = cpu_to_le16(num_vf_qs);
3858f2858738SVasundhara Volam 	nic_vft->txq_count = cpu_to_le16(num_vf_qs);
3859f2858738SVasundhara Volam 	nic_vft->rssq_count = cpu_to_le16(num_vf_qs);
3860f2858738SVasundhara Volam 	nic_vft->cq_count = cpu_to_le16(pool_res.max_cq_count /
3861f2858738SVasundhara Volam 					(num_vfs + 1));
3862f2858738SVasundhara Volam 
3863f2858738SVasundhara Volam 	/* Distribute unicast MACs, VLANs, IFACE count and MCCQ count equally
3864f2858738SVasundhara Volam 	 * among the PF and it's VFs, if the fields are changeable
3865f2858738SVasundhara Volam 	 */
3866f2858738SVasundhara Volam 	if (res_mod.max_uc_mac == FIELD_MODIFIABLE)
3867f2858738SVasundhara Volam 		nic_vft->unicast_mac_count = cpu_to_le16(pool_res.max_uc_mac /
3868f2858738SVasundhara Volam 							 (num_vfs + 1));
3869f2858738SVasundhara Volam 
3870f2858738SVasundhara Volam 	if (res_mod.max_vlans == FIELD_MODIFIABLE)
3871f2858738SVasundhara Volam 		nic_vft->vlan_count = cpu_to_le16(pool_res.max_vlans /
3872f2858738SVasundhara Volam 						  (num_vfs + 1));
3873f2858738SVasundhara Volam 
3874f2858738SVasundhara Volam 	if (res_mod.max_iface_count == FIELD_MODIFIABLE)
3875f2858738SVasundhara Volam 		nic_vft->iface_count = cpu_to_le16(pool_res.max_iface_count /
3876f2858738SVasundhara Volam 						   (num_vfs + 1));
3877f2858738SVasundhara Volam 
3878f2858738SVasundhara Volam 	if (res_mod.max_mcc_count == FIELD_MODIFIABLE)
3879f2858738SVasundhara Volam 		nic_vft->mcc_count = cpu_to_le16(pool_res.max_mcc_count /
3880f2858738SVasundhara Volam 						 (num_vfs + 1));
3881f2858738SVasundhara Volam }
3882f2858738SVasundhara Volam 
3883bec84e6bSVasundhara Volam int be_cmd_set_sriov_config(struct be_adapter *adapter,
3884f2858738SVasundhara Volam 			    struct be_resources pool_res, u16 num_vfs,
3885f2858738SVasundhara Volam 			    u16 num_vf_qs)
3886bec84e6bSVasundhara Volam {
3887bec84e6bSVasundhara Volam 	struct {
3888bec84e6bSVasundhara Volam 		struct be_pcie_res_desc pcie;
3889bec84e6bSVasundhara Volam 		struct be_nic_res_desc nic_vft;
3890bec84e6bSVasundhara Volam 	} __packed desc;
3891bec84e6bSVasundhara Volam 
3892bec84e6bSVasundhara Volam 	/* PF PCIE descriptor */
3893bec84e6bSVasundhara Volam 	be_reset_pcie_desc(&desc.pcie);
3894bec84e6bSVasundhara Volam 	desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1;
3895bec84e6bSVasundhara Volam 	desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
3896f2858738SVasundhara Volam 	desc.pcie.flags = BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
3897bec84e6bSVasundhara Volam 	desc.pcie.pf_num = adapter->pdev->devfn;
3898bec84e6bSVasundhara Volam 	desc.pcie.sriov_state = num_vfs ? 1 : 0;
3899bec84e6bSVasundhara Volam 	desc.pcie.num_vfs = cpu_to_le16(num_vfs);
3900bec84e6bSVasundhara Volam 
3901bec84e6bSVasundhara Volam 	/* VF NIC Template descriptor */
3902bec84e6bSVasundhara Volam 	be_reset_nic_desc(&desc.nic_vft);
3903bec84e6bSVasundhara Volam 	desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
3904bec84e6bSVasundhara Volam 	desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
3905f2858738SVasundhara Volam 	desc.nic_vft.flags = BIT(VFT_SHIFT) | BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
3906bec84e6bSVasundhara Volam 	desc.nic_vft.pf_num = adapter->pdev->devfn;
3907bec84e6bSVasundhara Volam 	desc.nic_vft.vf_num = 0;
3908bec84e6bSVasundhara Volam 
3909f2858738SVasundhara Volam 	be_fill_vf_res_template(adapter, pool_res, num_vfs, num_vf_qs,
3910f2858738SVasundhara Volam 				&desc.nic_vft);
3911bec84e6bSVasundhara Volam 
3912bec84e6bSVasundhara Volam 	return be_cmd_set_profile_config(adapter, &desc,
3913bec84e6bSVasundhara Volam 					 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
3914a401801cSSathya Perla }
3915a401801cSSathya Perla 
3916a401801cSSathya Perla int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
3917a401801cSSathya Perla {
3918a401801cSSathya Perla 	struct be_mcc_wrb *wrb;
3919a401801cSSathya Perla 	struct be_cmd_req_manage_iface_filters *req;
3920a401801cSSathya Perla 	int status;
3921a401801cSSathya Perla 
3922a401801cSSathya Perla 	if (iface == 0xFFFFFFFF)
3923a401801cSSathya Perla 		return -1;
3924a401801cSSathya Perla 
3925a401801cSSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
3926a401801cSSathya Perla 
3927a401801cSSathya Perla 	wrb = wrb_from_mccq(adapter);
3928a401801cSSathya Perla 	if (!wrb) {
3929a401801cSSathya Perla 		status = -EBUSY;
3930a401801cSSathya Perla 		goto err;
3931a401801cSSathya Perla 	}
3932a401801cSSathya Perla 	req = embedded_payload(wrb);
3933a401801cSSathya Perla 
3934a401801cSSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
3935a401801cSSathya Perla 			       OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req),
3936a401801cSSathya Perla 			       wrb, NULL);
3937a401801cSSathya Perla 	req->op = op;
3938a401801cSSathya Perla 	req->target_iface_id = cpu_to_le32(iface);
3939a401801cSSathya Perla 
3940a401801cSSathya Perla 	status = be_mcc_notify_wait(adapter);
3941a401801cSSathya Perla err:
3942a401801cSSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
3943a401801cSSathya Perla 	return status;
3944a401801cSSathya Perla }
3945a401801cSSathya Perla 
3946a401801cSSathya Perla int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port)
3947a401801cSSathya Perla {
3948a401801cSSathya Perla 	struct be_port_res_desc port_desc;
3949a401801cSSathya Perla 
3950a401801cSSathya Perla 	memset(&port_desc, 0, sizeof(port_desc));
3951a401801cSSathya Perla 	port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1;
3952a401801cSSathya Perla 	port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
3953a401801cSSathya Perla 	port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
3954a401801cSSathya Perla 	port_desc.link_num = adapter->hba_port_num;
3955a401801cSSathya Perla 	if (port) {
3956a401801cSSathya Perla 		port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) |
3957a401801cSSathya Perla 					(1 << RCVID_SHIFT);
3958a401801cSSathya Perla 		port_desc.nv_port = swab16(port);
3959a401801cSSathya Perla 	} else {
3960a401801cSSathya Perla 		port_desc.nv_flags = NV_TYPE_DISABLED;
3961a401801cSSathya Perla 		port_desc.nv_port = 0;
3962a401801cSSathya Perla 	}
3963a401801cSSathya Perla 
3964a401801cSSathya Perla 	return be_cmd_set_profile_config(adapter, &port_desc,
3965bec84e6bSVasundhara Volam 					 RESOURCE_DESC_SIZE_V1, 1, 1, 0);
3966a401801cSSathya Perla }
3967a401801cSSathya Perla 
39684c876616SSathya Perla int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
39694c876616SSathya Perla 		     int vf_num)
39704c876616SSathya Perla {
39714c876616SSathya Perla 	struct be_mcc_wrb *wrb;
39724c876616SSathya Perla 	struct be_cmd_req_get_iface_list *req;
39734c876616SSathya Perla 	struct be_cmd_resp_get_iface_list *resp;
39744c876616SSathya Perla 	int status;
39754c876616SSathya Perla 
39764c876616SSathya Perla 	spin_lock_bh(&adapter->mcc_lock);
39774c876616SSathya Perla 
39784c876616SSathya Perla 	wrb = wrb_from_mccq(adapter);
39794c876616SSathya Perla 	if (!wrb) {
39804c876616SSathya Perla 		status = -EBUSY;
39814c876616SSathya Perla 		goto err;
39824c876616SSathya Perla 	}
39834c876616SSathya Perla 	req = embedded_payload(wrb);
39844c876616SSathya Perla 
39854c876616SSathya Perla 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
39864c876616SSathya Perla 			       OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp),
39874c876616SSathya Perla 			       wrb, NULL);
39884c876616SSathya Perla 	req->hdr.domain = vf_num + 1;
39894c876616SSathya Perla 
39904c876616SSathya Perla 	status = be_mcc_notify_wait(adapter);
39914c876616SSathya Perla 	if (!status) {
39924c876616SSathya Perla 		resp = (struct be_cmd_resp_get_iface_list *)req;
39934c876616SSathya Perla 		vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id);
39944c876616SSathya Perla 	}
39954c876616SSathya Perla 
39964c876616SSathya Perla err:
39974c876616SSathya Perla 	spin_unlock_bh(&adapter->mcc_lock);
39984c876616SSathya Perla 	return status;
39994c876616SSathya Perla }
40004c876616SSathya Perla 
40015c510811SSomnath Kotur static int lancer_wait_idle(struct be_adapter *adapter)
40025c510811SSomnath Kotur {
40035c510811SSomnath Kotur #define SLIPORT_IDLE_TIMEOUT 30
40045c510811SSomnath Kotur 	u32 reg_val;
40055c510811SSomnath Kotur 	int status = 0, i;
40065c510811SSomnath Kotur 
40075c510811SSomnath Kotur 	for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
40085c510811SSomnath Kotur 		reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
40095c510811SSomnath Kotur 		if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
40105c510811SSomnath Kotur 			break;
40115c510811SSomnath Kotur 
40125c510811SSomnath Kotur 		ssleep(1);
40135c510811SSomnath Kotur 	}
40145c510811SSomnath Kotur 
40155c510811SSomnath Kotur 	if (i == SLIPORT_IDLE_TIMEOUT)
40165c510811SSomnath Kotur 		status = -1;
40175c510811SSomnath Kotur 
40185c510811SSomnath Kotur 	return status;
40195c510811SSomnath Kotur }
40205c510811SSomnath Kotur 
40215c510811SSomnath Kotur int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
40225c510811SSomnath Kotur {
40235c510811SSomnath Kotur 	int status = 0;
40245c510811SSomnath Kotur 
40255c510811SSomnath Kotur 	status = lancer_wait_idle(adapter);
40265c510811SSomnath Kotur 	if (status)
40275c510811SSomnath Kotur 		return status;
40285c510811SSomnath Kotur 
40295c510811SSomnath Kotur 	iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
40305c510811SSomnath Kotur 
40315c510811SSomnath Kotur 	return status;
40325c510811SSomnath Kotur }
40335c510811SSomnath Kotur 
40345c510811SSomnath Kotur /* Routine to check whether dump image is present or not */
40355c510811SSomnath Kotur bool dump_present(struct be_adapter *adapter)
40365c510811SSomnath Kotur {
40375c510811SSomnath Kotur 	u32 sliport_status = 0;
40385c510811SSomnath Kotur 
40395c510811SSomnath Kotur 	sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
40405c510811SSomnath Kotur 	return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
40415c510811SSomnath Kotur }
40425c510811SSomnath Kotur 
40435c510811SSomnath Kotur int lancer_initiate_dump(struct be_adapter *adapter)
40445c510811SSomnath Kotur {
4045f0613380SKalesh AP 	struct device *dev = &adapter->pdev->dev;
40465c510811SSomnath Kotur 	int status;
40475c510811SSomnath Kotur 
4048f0613380SKalesh AP 	if (dump_present(adapter)) {
4049f0613380SKalesh AP 		dev_info(dev, "Previous dump not cleared, not forcing dump\n");
4050f0613380SKalesh AP 		return -EEXIST;
4051f0613380SKalesh AP 	}
4052f0613380SKalesh AP 
40535c510811SSomnath Kotur 	/* give firmware reset and diagnostic dump */
40545c510811SSomnath Kotur 	status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
40555c510811SSomnath Kotur 				     PHYSDEV_CONTROL_DD_MASK);
40565c510811SSomnath Kotur 	if (status < 0) {
4057f0613380SKalesh AP 		dev_err(dev, "FW reset failed\n");
40585c510811SSomnath Kotur 		return status;
40595c510811SSomnath Kotur 	}
40605c510811SSomnath Kotur 
40615c510811SSomnath Kotur 	status = lancer_wait_idle(adapter);
40625c510811SSomnath Kotur 	if (status)
40635c510811SSomnath Kotur 		return status;
40645c510811SSomnath Kotur 
40655c510811SSomnath Kotur 	if (!dump_present(adapter)) {
4066f0613380SKalesh AP 		dev_err(dev, "FW dump not generated\n");
4067f0613380SKalesh AP 		return -EIO;
40685c510811SSomnath Kotur 	}
40695c510811SSomnath Kotur 
40705c510811SSomnath Kotur 	return 0;
40715c510811SSomnath Kotur }
40725c510811SSomnath Kotur 
4073f0613380SKalesh AP int lancer_delete_dump(struct be_adapter *adapter)
4074f0613380SKalesh AP {
4075f0613380SKalesh AP 	int status;
4076f0613380SKalesh AP 
4077f0613380SKalesh AP 	status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE);
4078f0613380SKalesh AP 	return be_cmd_status(status);
4079f0613380SKalesh AP }
4080f0613380SKalesh AP 
4081dcf7ebbaSPadmanabh Ratnakar /* Uses sync mcc */
4082dcf7ebbaSPadmanabh Ratnakar int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
4083dcf7ebbaSPadmanabh Ratnakar {
4084dcf7ebbaSPadmanabh Ratnakar 	struct be_mcc_wrb *wrb;
4085dcf7ebbaSPadmanabh Ratnakar 	struct be_cmd_enable_disable_vf *req;
4086dcf7ebbaSPadmanabh Ratnakar 	int status;
4087dcf7ebbaSPadmanabh Ratnakar 
40880599863dSVasundhara Volam 	if (BEx_chip(adapter))
4089dcf7ebbaSPadmanabh Ratnakar 		return 0;
4090dcf7ebbaSPadmanabh Ratnakar 
4091dcf7ebbaSPadmanabh Ratnakar 	spin_lock_bh(&adapter->mcc_lock);
4092dcf7ebbaSPadmanabh Ratnakar 
4093dcf7ebbaSPadmanabh Ratnakar 	wrb = wrb_from_mccq(adapter);
4094dcf7ebbaSPadmanabh Ratnakar 	if (!wrb) {
4095dcf7ebbaSPadmanabh Ratnakar 		status = -EBUSY;
4096dcf7ebbaSPadmanabh Ratnakar 		goto err;
4097dcf7ebbaSPadmanabh Ratnakar 	}
4098dcf7ebbaSPadmanabh Ratnakar 
4099dcf7ebbaSPadmanabh Ratnakar 	req = embedded_payload(wrb);
4100dcf7ebbaSPadmanabh Ratnakar 
4101dcf7ebbaSPadmanabh Ratnakar 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4102dcf7ebbaSPadmanabh Ratnakar 			       OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
4103dcf7ebbaSPadmanabh Ratnakar 			       wrb, NULL);
4104dcf7ebbaSPadmanabh Ratnakar 
4105dcf7ebbaSPadmanabh Ratnakar 	req->hdr.domain = domain;
4106dcf7ebbaSPadmanabh Ratnakar 	req->enable = 1;
4107dcf7ebbaSPadmanabh Ratnakar 	status = be_mcc_notify_wait(adapter);
4108dcf7ebbaSPadmanabh Ratnakar err:
4109dcf7ebbaSPadmanabh Ratnakar 	spin_unlock_bh(&adapter->mcc_lock);
4110dcf7ebbaSPadmanabh Ratnakar 	return status;
4111dcf7ebbaSPadmanabh Ratnakar }
4112dcf7ebbaSPadmanabh Ratnakar 
411368c45a2dSSomnath Kotur int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable)
411468c45a2dSSomnath Kotur {
411568c45a2dSSomnath Kotur 	struct be_mcc_wrb *wrb;
411668c45a2dSSomnath Kotur 	struct be_cmd_req_intr_set *req;
411768c45a2dSSomnath Kotur 	int status;
411868c45a2dSSomnath Kotur 
411968c45a2dSSomnath Kotur 	if (mutex_lock_interruptible(&adapter->mbox_lock))
412068c45a2dSSomnath Kotur 		return -1;
412168c45a2dSSomnath Kotur 
412268c45a2dSSomnath Kotur 	wrb = wrb_from_mbox(adapter);
412368c45a2dSSomnath Kotur 
412468c45a2dSSomnath Kotur 	req = embedded_payload(wrb);
412568c45a2dSSomnath Kotur 
412668c45a2dSSomnath Kotur 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
412768c45a2dSSomnath Kotur 			       OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req),
412868c45a2dSSomnath Kotur 			       wrb, NULL);
412968c45a2dSSomnath Kotur 
413068c45a2dSSomnath Kotur 	req->intr_enabled = intr_enable;
413168c45a2dSSomnath Kotur 
413268c45a2dSSomnath Kotur 	status = be_mbox_notify_wait(adapter);
413368c45a2dSSomnath Kotur 
413468c45a2dSSomnath Kotur 	mutex_unlock(&adapter->mbox_lock);
413568c45a2dSSomnath Kotur 	return status;
413668c45a2dSSomnath Kotur }
413768c45a2dSSomnath Kotur 
4138542963b7SVasundhara Volam /* Uses MBOX */
4139542963b7SVasundhara Volam int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id)
4140542963b7SVasundhara Volam {
4141542963b7SVasundhara Volam 	struct be_cmd_req_get_active_profile *req;
4142542963b7SVasundhara Volam 	struct be_mcc_wrb *wrb;
4143542963b7SVasundhara Volam 	int status;
4144542963b7SVasundhara Volam 
4145542963b7SVasundhara Volam 	if (mutex_lock_interruptible(&adapter->mbox_lock))
4146542963b7SVasundhara Volam 		return -1;
4147542963b7SVasundhara Volam 
4148542963b7SVasundhara Volam 	wrb = wrb_from_mbox(adapter);
4149542963b7SVasundhara Volam 	if (!wrb) {
4150542963b7SVasundhara Volam 		status = -EBUSY;
4151542963b7SVasundhara Volam 		goto err;
4152542963b7SVasundhara Volam 	}
4153542963b7SVasundhara Volam 
4154542963b7SVasundhara Volam 	req = embedded_payload(wrb);
4155542963b7SVasundhara Volam 
4156542963b7SVasundhara Volam 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4157542963b7SVasundhara Volam 			       OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req),
4158542963b7SVasundhara Volam 			       wrb, NULL);
4159542963b7SVasundhara Volam 
4160542963b7SVasundhara Volam 	status = be_mbox_notify_wait(adapter);
4161542963b7SVasundhara Volam 	if (!status) {
4162542963b7SVasundhara Volam 		struct be_cmd_resp_get_active_profile *resp =
4163542963b7SVasundhara Volam 							embedded_payload(wrb);
416403d28ffeSKalesh AP 
4165542963b7SVasundhara Volam 		*profile_id = le16_to_cpu(resp->active_profile_id);
4166542963b7SVasundhara Volam 	}
4167542963b7SVasundhara Volam 
4168542963b7SVasundhara Volam err:
4169542963b7SVasundhara Volam 	mutex_unlock(&adapter->mbox_lock);
4170542963b7SVasundhara Volam 	return status;
4171542963b7SVasundhara Volam }
4172542963b7SVasundhara Volam 
4173bdce2ad7SSuresh Reddy int be_cmd_set_logical_link_config(struct be_adapter *adapter,
4174bdce2ad7SSuresh Reddy 				   int link_state, u8 domain)
4175bdce2ad7SSuresh Reddy {
4176bdce2ad7SSuresh Reddy 	struct be_mcc_wrb *wrb;
4177bdce2ad7SSuresh Reddy 	struct be_cmd_req_set_ll_link *req;
4178bdce2ad7SSuresh Reddy 	int status;
4179bdce2ad7SSuresh Reddy 
4180bdce2ad7SSuresh Reddy 	if (BEx_chip(adapter) || lancer_chip(adapter))
418118fd6025SKalesh AP 		return -EOPNOTSUPP;
4182bdce2ad7SSuresh Reddy 
4183bdce2ad7SSuresh Reddy 	spin_lock_bh(&adapter->mcc_lock);
4184bdce2ad7SSuresh Reddy 
4185bdce2ad7SSuresh Reddy 	wrb = wrb_from_mccq(adapter);
4186bdce2ad7SSuresh Reddy 	if (!wrb) {
4187bdce2ad7SSuresh Reddy 		status = -EBUSY;
4188bdce2ad7SSuresh Reddy 		goto err;
4189bdce2ad7SSuresh Reddy 	}
4190bdce2ad7SSuresh Reddy 
4191bdce2ad7SSuresh Reddy 	req = embedded_payload(wrb);
4192bdce2ad7SSuresh Reddy 
4193bdce2ad7SSuresh Reddy 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
4194bdce2ad7SSuresh Reddy 			       OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG,
4195bdce2ad7SSuresh Reddy 			       sizeof(*req), wrb, NULL);
4196bdce2ad7SSuresh Reddy 
4197bdce2ad7SSuresh Reddy 	req->hdr.version = 1;
4198bdce2ad7SSuresh Reddy 	req->hdr.domain = domain;
4199bdce2ad7SSuresh Reddy 
4200bdce2ad7SSuresh Reddy 	if (link_state == IFLA_VF_LINK_STATE_ENABLE)
4201bdce2ad7SSuresh Reddy 		req->link_config |= 1;
4202bdce2ad7SSuresh Reddy 
4203bdce2ad7SSuresh Reddy 	if (link_state == IFLA_VF_LINK_STATE_AUTO)
4204bdce2ad7SSuresh Reddy 		req->link_config |= 1 << PLINK_TRACK_SHIFT;
4205bdce2ad7SSuresh Reddy 
4206bdce2ad7SSuresh Reddy 	status = be_mcc_notify_wait(adapter);
4207bdce2ad7SSuresh Reddy err:
4208bdce2ad7SSuresh Reddy 	spin_unlock_bh(&adapter->mcc_lock);
4209bdce2ad7SSuresh Reddy 	return status;
4210bdce2ad7SSuresh Reddy }
4211bdce2ad7SSuresh Reddy 
42126a4ab669SParav Pandit int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
42136a4ab669SParav Pandit 		    int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
42146a4ab669SParav Pandit {
42156a4ab669SParav Pandit 	struct be_adapter *adapter = netdev_priv(netdev_handle);
42166a4ab669SParav Pandit 	struct be_mcc_wrb *wrb;
42176a4ab669SParav Pandit 	struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload;
42186a4ab669SParav Pandit 	struct be_cmd_req_hdr *req;
42196a4ab669SParav Pandit 	struct be_cmd_resp_hdr *resp;
42206a4ab669SParav Pandit 	int status;
42216a4ab669SParav Pandit 
42226a4ab669SParav Pandit 	spin_lock_bh(&adapter->mcc_lock);
42236a4ab669SParav Pandit 
42246a4ab669SParav Pandit 	wrb = wrb_from_mccq(adapter);
42256a4ab669SParav Pandit 	if (!wrb) {
42266a4ab669SParav Pandit 		status = -EBUSY;
42276a4ab669SParav Pandit 		goto err;
42286a4ab669SParav Pandit 	}
42296a4ab669SParav Pandit 	req = embedded_payload(wrb);
42306a4ab669SParav Pandit 	resp = embedded_payload(wrb);
42316a4ab669SParav Pandit 
42326a4ab669SParav Pandit 	be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
42336a4ab669SParav Pandit 			       hdr->opcode, wrb_payload_size, wrb, NULL);
42346a4ab669SParav Pandit 	memcpy(req, wrb_payload, wrb_payload_size);
42356a4ab669SParav Pandit 	be_dws_cpu_to_le(req, wrb_payload_size);
42366a4ab669SParav Pandit 
42376a4ab669SParav Pandit 	status = be_mcc_notify_wait(adapter);
42386a4ab669SParav Pandit 	if (cmd_status)
42396a4ab669SParav Pandit 		*cmd_status = (status & 0xffff);
42406a4ab669SParav Pandit 	if (ext_status)
42416a4ab669SParav Pandit 		*ext_status = 0;
42426a4ab669SParav Pandit 	memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
42436a4ab669SParav Pandit 	be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
42446a4ab669SParav Pandit err:
42456a4ab669SParav Pandit 	spin_unlock_bh(&adapter->mcc_lock);
42466a4ab669SParav Pandit 	return status;
42476a4ab669SParav Pandit }
42486a4ab669SParav Pandit EXPORT_SYMBOL(be_roce_mcc_cmd);
4249