19aebddd1SJeff Kirsher /* 2d19261b8SVasundhara Volam * Copyright (C) 2005 - 2015 Emulex 39aebddd1SJeff Kirsher * All rights reserved. 49aebddd1SJeff Kirsher * 59aebddd1SJeff Kirsher * This program is free software; you can redistribute it and/or 69aebddd1SJeff Kirsher * modify it under the terms of the GNU General Public License version 2 79aebddd1SJeff Kirsher * as published by the Free Software Foundation. The full GNU General 89aebddd1SJeff Kirsher * Public License is included in this distribution in the file called COPYING. 99aebddd1SJeff Kirsher * 109aebddd1SJeff Kirsher * Contact Information: 119aebddd1SJeff Kirsher * linux-drivers@emulex.com 129aebddd1SJeff Kirsher * 139aebddd1SJeff Kirsher * Emulex 149aebddd1SJeff Kirsher * 3333 Susan Street 159aebddd1SJeff Kirsher * Costa Mesa, CA 92626 169aebddd1SJeff Kirsher */ 179aebddd1SJeff Kirsher 186a4ab669SParav Pandit #include <linux/module.h> 199aebddd1SJeff Kirsher #include "be.h" 209aebddd1SJeff Kirsher #include "be_cmds.h" 219aebddd1SJeff Kirsher 2221252377SVasundhara Volam static char *be_port_misconfig_evt_desc[] = { 2321252377SVasundhara Volam "A valid SFP module detected", 2421252377SVasundhara Volam "Optics faulted/ incorrectly installed/ not installed.", 2521252377SVasundhara Volam "Optics of two types installed.", 2621252377SVasundhara Volam "Incompatible optics.", 2721252377SVasundhara Volam "Unknown port SFP status" 2821252377SVasundhara Volam }; 2921252377SVasundhara Volam 3021252377SVasundhara Volam static char *be_port_misconfig_remedy_desc[] = { 3121252377SVasundhara Volam "", 3221252377SVasundhara Volam "Reseat optics. If issue not resolved, replace", 3321252377SVasundhara Volam "Remove one optic or install matching pair of optics", 3421252377SVasundhara Volam "Replace with compatible optics for card to function", 3521252377SVasundhara Volam "" 3621252377SVasundhara Volam }; 3721252377SVasundhara Volam 38f25b119cSPadmanabh Ratnakar static struct be_cmd_priv_map cmd_priv_map[] = { 39f25b119cSPadmanabh Ratnakar { 40f25b119cSPadmanabh Ratnakar OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, 41f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH, 42f25b119cSPadmanabh Ratnakar BE_PRIV_LNKMGMT | BE_PRIV_VHADM | 43f25b119cSPadmanabh Ratnakar BE_PRIV_DEVCFG | BE_PRIV_DEVSEC 44f25b119cSPadmanabh Ratnakar }, 45f25b119cSPadmanabh Ratnakar { 46f25b119cSPadmanabh Ratnakar OPCODE_COMMON_GET_FLOW_CONTROL, 47f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON, 48f25b119cSPadmanabh Ratnakar BE_PRIV_LNKQUERY | BE_PRIV_VHADM | 49f25b119cSPadmanabh Ratnakar BE_PRIV_DEVCFG | BE_PRIV_DEVSEC 50f25b119cSPadmanabh Ratnakar }, 51f25b119cSPadmanabh Ratnakar { 52f25b119cSPadmanabh Ratnakar OPCODE_COMMON_SET_FLOW_CONTROL, 53f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON, 54f25b119cSPadmanabh Ratnakar BE_PRIV_LNKMGMT | BE_PRIV_VHADM | 55f25b119cSPadmanabh Ratnakar BE_PRIV_DEVCFG | BE_PRIV_DEVSEC 56f25b119cSPadmanabh Ratnakar }, 57f25b119cSPadmanabh Ratnakar { 58f25b119cSPadmanabh Ratnakar OPCODE_ETH_GET_PPORT_STATS, 59f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH, 60f25b119cSPadmanabh Ratnakar BE_PRIV_LNKMGMT | BE_PRIV_VHADM | 61f25b119cSPadmanabh Ratnakar BE_PRIV_DEVCFG | BE_PRIV_DEVSEC 62f25b119cSPadmanabh Ratnakar }, 63f25b119cSPadmanabh Ratnakar { 64f25b119cSPadmanabh Ratnakar OPCODE_COMMON_GET_PHY_DETAILS, 65f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON, 66f25b119cSPadmanabh Ratnakar BE_PRIV_LNKMGMT | BE_PRIV_VHADM | 67f25b119cSPadmanabh Ratnakar BE_PRIV_DEVCFG | BE_PRIV_DEVSEC 68f25b119cSPadmanabh Ratnakar } 69f25b119cSPadmanabh Ratnakar }; 70f25b119cSPadmanabh Ratnakar 71a2cc4e0bSSathya Perla static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, u8 subsystem) 72f25b119cSPadmanabh Ratnakar { 73f25b119cSPadmanabh Ratnakar int i; 74f25b119cSPadmanabh Ratnakar int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map); 75f25b119cSPadmanabh Ratnakar u32 cmd_privileges = adapter->cmd_privileges; 76f25b119cSPadmanabh Ratnakar 77f25b119cSPadmanabh Ratnakar for (i = 0; i < num_entries; i++) 78f25b119cSPadmanabh Ratnakar if (opcode == cmd_priv_map[i].opcode && 79f25b119cSPadmanabh Ratnakar subsystem == cmd_priv_map[i].subsystem) 80f25b119cSPadmanabh Ratnakar if (!(cmd_privileges & cmd_priv_map[i].priv_mask)) 81f25b119cSPadmanabh Ratnakar return false; 82f25b119cSPadmanabh Ratnakar 83f25b119cSPadmanabh Ratnakar return true; 84f25b119cSPadmanabh Ratnakar } 85f25b119cSPadmanabh Ratnakar 863de09455SSomnath Kotur static inline void *embedded_payload(struct be_mcc_wrb *wrb) 873de09455SSomnath Kotur { 883de09455SSomnath Kotur return wrb->payload.embedded_payload; 893de09455SSomnath Kotur } 909aebddd1SJeff Kirsher 91efaa408eSSuresh Reddy static int be_mcc_notify(struct be_adapter *adapter) 929aebddd1SJeff Kirsher { 939aebddd1SJeff Kirsher struct be_queue_info *mccq = &adapter->mcc_obj.q; 949aebddd1SJeff Kirsher u32 val = 0; 959aebddd1SJeff Kirsher 96954f6825SVenkata Duvvuru if (be_check_error(adapter, BE_ERROR_ANY)) 97efaa408eSSuresh Reddy return -EIO; 989aebddd1SJeff Kirsher 999aebddd1SJeff Kirsher val |= mccq->id & DB_MCCQ_RING_ID_MASK; 1009aebddd1SJeff Kirsher val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; 1019aebddd1SJeff Kirsher 1029aebddd1SJeff Kirsher wmb(); 1039aebddd1SJeff Kirsher iowrite32(val, adapter->db + DB_MCCQ_OFFSET); 104efaa408eSSuresh Reddy 105efaa408eSSuresh Reddy return 0; 1069aebddd1SJeff Kirsher } 1079aebddd1SJeff Kirsher 1089aebddd1SJeff Kirsher /* To check if valid bit is set, check the entire word as we don't know 1099aebddd1SJeff Kirsher * the endianness of the data (old entry is host endian while a new entry is 1109aebddd1SJeff Kirsher * little endian) */ 1119aebddd1SJeff Kirsher static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) 1129aebddd1SJeff Kirsher { 1139e9ff4b7SSathya Perla u32 flags; 1149e9ff4b7SSathya Perla 1159aebddd1SJeff Kirsher if (compl->flags != 0) { 1169e9ff4b7SSathya Perla flags = le32_to_cpu(compl->flags); 1179e9ff4b7SSathya Perla if (flags & CQE_FLAGS_VALID_MASK) { 1189e9ff4b7SSathya Perla compl->flags = flags; 1199aebddd1SJeff Kirsher return true; 1209aebddd1SJeff Kirsher } 1219aebddd1SJeff Kirsher } 1229e9ff4b7SSathya Perla return false; 1239e9ff4b7SSathya Perla } 1249aebddd1SJeff Kirsher 1259aebddd1SJeff Kirsher /* Need to reset the entire word that houses the valid bit */ 1269aebddd1SJeff Kirsher static inline void be_mcc_compl_use(struct be_mcc_compl *compl) 1279aebddd1SJeff Kirsher { 1289aebddd1SJeff Kirsher compl->flags = 0; 1299aebddd1SJeff Kirsher } 1309aebddd1SJeff Kirsher 131652bf646SPadmanabh Ratnakar static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1) 132652bf646SPadmanabh Ratnakar { 133652bf646SPadmanabh Ratnakar unsigned long addr; 134652bf646SPadmanabh Ratnakar 135652bf646SPadmanabh Ratnakar addr = tag1; 136652bf646SPadmanabh Ratnakar addr = ((addr << 16) << 16) | tag0; 137652bf646SPadmanabh Ratnakar return (void *)addr; 138652bf646SPadmanabh Ratnakar } 139652bf646SPadmanabh Ratnakar 1404c60005fSKalesh AP static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status) 1414c60005fSKalesh AP { 1424c60005fSKalesh AP if (base_status == MCC_STATUS_NOT_SUPPORTED || 1434c60005fSKalesh AP base_status == MCC_STATUS_ILLEGAL_REQUEST || 1444c60005fSKalesh AP addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES || 14577be8c1cSKalesh AP addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS || 1464c60005fSKalesh AP (opcode == OPCODE_COMMON_WRITE_FLASHROM && 1474c60005fSKalesh AP (base_status == MCC_STATUS_ILLEGAL_FIELD || 1484c60005fSKalesh AP addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH))) 1494c60005fSKalesh AP return true; 1504c60005fSKalesh AP else 1514c60005fSKalesh AP return false; 1524c60005fSKalesh AP } 1534c60005fSKalesh AP 154559b633fSSathya Perla /* Place holder for all the async MCC cmds wherein the caller is not in a busy 155559b633fSSathya Perla * loop (has not issued be_mcc_notify_wait()) 156559b633fSSathya Perla */ 157559b633fSSathya Perla static void be_async_cmd_process(struct be_adapter *adapter, 158559b633fSSathya Perla struct be_mcc_compl *compl, 159559b633fSSathya Perla struct be_cmd_resp_hdr *resp_hdr) 160559b633fSSathya Perla { 161559b633fSSathya Perla enum mcc_base_status base_status = base_status(compl->status); 162559b633fSSathya Perla u8 opcode = 0, subsystem = 0; 163559b633fSSathya Perla 164559b633fSSathya Perla if (resp_hdr) { 165559b633fSSathya Perla opcode = resp_hdr->opcode; 166559b633fSSathya Perla subsystem = resp_hdr->subsystem; 167559b633fSSathya Perla } 168559b633fSSathya Perla 169559b633fSSathya Perla if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST && 170559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_LOWLEVEL) { 171559b633fSSathya Perla complete(&adapter->et_cmd_compl); 172559b633fSSathya Perla return; 173559b633fSSathya Perla } 174559b633fSSathya Perla 1759c855975SSuresh Reddy if (opcode == OPCODE_LOWLEVEL_SET_LOOPBACK_MODE && 1769c855975SSuresh Reddy subsystem == CMD_SUBSYSTEM_LOWLEVEL) { 1779c855975SSuresh Reddy complete(&adapter->et_cmd_compl); 1789c855975SSuresh Reddy return; 1799c855975SSuresh Reddy } 1809c855975SSuresh Reddy 181559b633fSSathya Perla if ((opcode == OPCODE_COMMON_WRITE_FLASHROM || 182559b633fSSathya Perla opcode == OPCODE_COMMON_WRITE_OBJECT) && 183559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_COMMON) { 184559b633fSSathya Perla adapter->flash_status = compl->status; 185559b633fSSathya Perla complete(&adapter->et_cmd_compl); 186559b633fSSathya Perla return; 187559b633fSSathya Perla } 188559b633fSSathya Perla 189559b633fSSathya Perla if ((opcode == OPCODE_ETH_GET_STATISTICS || 190559b633fSSathya Perla opcode == OPCODE_ETH_GET_PPORT_STATS) && 191559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_ETH && 192559b633fSSathya Perla base_status == MCC_STATUS_SUCCESS) { 193559b633fSSathya Perla be_parse_stats(adapter); 194559b633fSSathya Perla adapter->stats_cmd_sent = false; 195559b633fSSathya Perla return; 196559b633fSSathya Perla } 197559b633fSSathya Perla 198559b633fSSathya Perla if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES && 199559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_COMMON) { 200559b633fSSathya Perla if (base_status == MCC_STATUS_SUCCESS) { 201559b633fSSathya Perla struct be_cmd_resp_get_cntl_addnl_attribs *resp = 202559b633fSSathya Perla (void *)resp_hdr; 20329e9122bSVenkata Duvvuru adapter->hwmon_info.be_on_die_temp = 204559b633fSSathya Perla resp->on_die_temperature; 205559b633fSSathya Perla } else { 206559b633fSSathya Perla adapter->be_get_temp_freq = 0; 20729e9122bSVenkata Duvvuru adapter->hwmon_info.be_on_die_temp = 20829e9122bSVenkata Duvvuru BE_INVALID_DIE_TEMP; 209559b633fSSathya Perla } 210559b633fSSathya Perla return; 211559b633fSSathya Perla } 212559b633fSSathya Perla } 213559b633fSSathya Perla 2149aebddd1SJeff Kirsher static int be_mcc_compl_process(struct be_adapter *adapter, 2159aebddd1SJeff Kirsher struct be_mcc_compl *compl) 2169aebddd1SJeff Kirsher { 2174c60005fSKalesh AP enum mcc_base_status base_status; 2184c60005fSKalesh AP enum mcc_addl_status addl_status; 219652bf646SPadmanabh Ratnakar struct be_cmd_resp_hdr *resp_hdr; 220652bf646SPadmanabh Ratnakar u8 opcode = 0, subsystem = 0; 2219aebddd1SJeff Kirsher 2229aebddd1SJeff Kirsher /* Just swap the status to host endian; mcc tag is opaquely copied 2239aebddd1SJeff Kirsher * from mcc_wrb */ 2249aebddd1SJeff Kirsher be_dws_le_to_cpu(compl, 4); 2259aebddd1SJeff Kirsher 2264c60005fSKalesh AP base_status = base_status(compl->status); 2274c60005fSKalesh AP addl_status = addl_status(compl->status); 22896c9b2e4SVasundhara Volam 229652bf646SPadmanabh Ratnakar resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1); 230652bf646SPadmanabh Ratnakar if (resp_hdr) { 231652bf646SPadmanabh Ratnakar opcode = resp_hdr->opcode; 232652bf646SPadmanabh Ratnakar subsystem = resp_hdr->subsystem; 233652bf646SPadmanabh Ratnakar } 234652bf646SPadmanabh Ratnakar 235559b633fSSathya Perla be_async_cmd_process(adapter, compl, resp_hdr); 2365eeff635SSuresh Reddy 237559b633fSSathya Perla if (base_status != MCC_STATUS_SUCCESS && 238559b633fSSathya Perla !be_skip_err_log(opcode, base_status, addl_status)) { 2394c60005fSKalesh AP if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { 24097f1d8cdSVasundhara Volam dev_warn(&adapter->pdev->dev, 241522609f2SVasundhara Volam "VF is not privileged to issue opcode %d-%d\n", 24297f1d8cdSVasundhara Volam opcode, subsystem); 2439aebddd1SJeff Kirsher } else { 24497f1d8cdSVasundhara Volam dev_err(&adapter->pdev->dev, 24597f1d8cdSVasundhara Volam "opcode %d-%d failed:status %d-%d\n", 2464c60005fSKalesh AP opcode, subsystem, base_status, addl_status); 2479aebddd1SJeff Kirsher } 2489aebddd1SJeff Kirsher } 2494c60005fSKalesh AP return compl->status; 2509aebddd1SJeff Kirsher } 2519aebddd1SJeff Kirsher 2529aebddd1SJeff Kirsher /* Link state evt is a string of bytes; no need for endian swapping */ 2539aebddd1SJeff Kirsher static void be_async_link_state_process(struct be_adapter *adapter, 2543acf19d9SSathya Perla struct be_mcc_compl *compl) 2559aebddd1SJeff Kirsher { 2563acf19d9SSathya Perla struct be_async_event_link_state *evt = 2573acf19d9SSathya Perla (struct be_async_event_link_state *)compl; 2583acf19d9SSathya Perla 259b236916aSAjit Khaparde /* When link status changes, link speed must be re-queried from FW */ 26042f11cf2SAjit Khaparde adapter->phy.link_speed = -1; 261b236916aSAjit Khaparde 262bdce2ad7SSuresh Reddy /* On BEx the FW does not send a separate link status 263bdce2ad7SSuresh Reddy * notification for physical and logical link. 264bdce2ad7SSuresh Reddy * On other chips just process the logical link 265bdce2ad7SSuresh Reddy * status notification 266bdce2ad7SSuresh Reddy */ 267bdce2ad7SSuresh Reddy if (!BEx_chip(adapter) && 2682e177a5cSPadmanabh Ratnakar !(evt->port_link_status & LOGICAL_LINK_STATUS_MASK)) 2692e177a5cSPadmanabh Ratnakar return; 2702e177a5cSPadmanabh Ratnakar 271b236916aSAjit Khaparde /* For the initial link status do not rely on the ASYNC event as 272b236916aSAjit Khaparde * it may not be received in some cases. 273b236916aSAjit Khaparde */ 274b236916aSAjit Khaparde if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT) 275bdce2ad7SSuresh Reddy be_link_status_update(adapter, 276bdce2ad7SSuresh Reddy evt->port_link_status & LINK_STATUS_MASK); 2779aebddd1SJeff Kirsher } 2789aebddd1SJeff Kirsher 27921252377SVasundhara Volam static void be_async_port_misconfig_event_process(struct be_adapter *adapter, 28021252377SVasundhara Volam struct be_mcc_compl *compl) 28121252377SVasundhara Volam { 28221252377SVasundhara Volam struct be_async_event_misconfig_port *evt = 28321252377SVasundhara Volam (struct be_async_event_misconfig_port *)compl; 28421252377SVasundhara Volam u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1); 28521252377SVasundhara Volam struct device *dev = &adapter->pdev->dev; 28621252377SVasundhara Volam u8 port_misconfig_evt; 28721252377SVasundhara Volam 28821252377SVasundhara Volam port_misconfig_evt = 28921252377SVasundhara Volam ((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff); 29021252377SVasundhara Volam 29121252377SVasundhara Volam /* Log an error message that would allow a user to determine 29221252377SVasundhara Volam * whether the SFPs have an issue 29321252377SVasundhara Volam */ 29421252377SVasundhara Volam dev_info(dev, "Port %c: %s %s", adapter->port_name, 29521252377SVasundhara Volam be_port_misconfig_evt_desc[port_misconfig_evt], 29621252377SVasundhara Volam be_port_misconfig_remedy_desc[port_misconfig_evt]); 29721252377SVasundhara Volam 29821252377SVasundhara Volam if (port_misconfig_evt == INCOMPATIBLE_SFP) 29921252377SVasundhara Volam adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP; 30021252377SVasundhara Volam } 30121252377SVasundhara Volam 3029aebddd1SJeff Kirsher /* Grp5 CoS Priority evt */ 3039aebddd1SJeff Kirsher static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, 3043acf19d9SSathya Perla struct be_mcc_compl *compl) 3059aebddd1SJeff Kirsher { 3063acf19d9SSathya Perla struct be_async_event_grp5_cos_priority *evt = 3073acf19d9SSathya Perla (struct be_async_event_grp5_cos_priority *)compl; 3083acf19d9SSathya Perla 3099aebddd1SJeff Kirsher if (evt->valid) { 3109aebddd1SJeff Kirsher adapter->vlan_prio_bmap = evt->available_priority_bmap; 3119aebddd1SJeff Kirsher adapter->recommended_prio &= ~VLAN_PRIO_MASK; 3129aebddd1SJeff Kirsher adapter->recommended_prio = 3139aebddd1SJeff Kirsher evt->reco_default_priority << VLAN_PRIO_SHIFT; 3149aebddd1SJeff Kirsher } 3159aebddd1SJeff Kirsher } 3169aebddd1SJeff Kirsher 317323ff71eSSathya Perla /* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */ 3189aebddd1SJeff Kirsher static void be_async_grp5_qos_speed_process(struct be_adapter *adapter, 3193acf19d9SSathya Perla struct be_mcc_compl *compl) 3209aebddd1SJeff Kirsher { 3213acf19d9SSathya Perla struct be_async_event_grp5_qos_link_speed *evt = 3223acf19d9SSathya Perla (struct be_async_event_grp5_qos_link_speed *)compl; 3233acf19d9SSathya Perla 324323ff71eSSathya Perla if (adapter->phy.link_speed >= 0 && 325323ff71eSSathya Perla evt->physical_port == adapter->port_num) 326323ff71eSSathya Perla adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10; 3279aebddd1SJeff Kirsher } 3289aebddd1SJeff Kirsher 3299aebddd1SJeff Kirsher /*Grp5 PVID evt*/ 3309aebddd1SJeff Kirsher static void be_async_grp5_pvid_state_process(struct be_adapter *adapter, 3313acf19d9SSathya Perla struct be_mcc_compl *compl) 3329aebddd1SJeff Kirsher { 3333acf19d9SSathya Perla struct be_async_event_grp5_pvid_state *evt = 3343acf19d9SSathya Perla (struct be_async_event_grp5_pvid_state *)compl; 3353acf19d9SSathya Perla 336bdac85b5SRavikumar Nelavelli if (evt->enabled) { 337939cf306SSomnath Kotur adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK; 338bdac85b5SRavikumar Nelavelli dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid); 339bdac85b5SRavikumar Nelavelli } else { 3409aebddd1SJeff Kirsher adapter->pvid = 0; 3419aebddd1SJeff Kirsher } 342bdac85b5SRavikumar Nelavelli } 3439aebddd1SJeff Kirsher 344760c295eSVenkata Duvvuru #define MGMT_ENABLE_MASK 0x4 345760c295eSVenkata Duvvuru static void be_async_grp5_fw_control_process(struct be_adapter *adapter, 346760c295eSVenkata Duvvuru struct be_mcc_compl *compl) 347760c295eSVenkata Duvvuru { 348760c295eSVenkata Duvvuru struct be_async_fw_control *evt = (struct be_async_fw_control *)compl; 349760c295eSVenkata Duvvuru u32 evt_dw1 = le32_to_cpu(evt->event_data_word1); 350760c295eSVenkata Duvvuru 351760c295eSVenkata Duvvuru if (evt_dw1 & MGMT_ENABLE_MASK) { 352760c295eSVenkata Duvvuru adapter->flags |= BE_FLAGS_OS2BMC; 353760c295eSVenkata Duvvuru adapter->bmc_filt_mask = le32_to_cpu(evt->event_data_word2); 354760c295eSVenkata Duvvuru } else { 355760c295eSVenkata Duvvuru adapter->flags &= ~BE_FLAGS_OS2BMC; 356760c295eSVenkata Duvvuru } 357760c295eSVenkata Duvvuru } 358760c295eSVenkata Duvvuru 3599aebddd1SJeff Kirsher static void be_async_grp5_evt_process(struct be_adapter *adapter, 3603acf19d9SSathya Perla struct be_mcc_compl *compl) 3619aebddd1SJeff Kirsher { 3623acf19d9SSathya Perla u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) & 3633acf19d9SSathya Perla ASYNC_EVENT_TYPE_MASK; 3649aebddd1SJeff Kirsher 3659aebddd1SJeff Kirsher switch (event_type) { 3669aebddd1SJeff Kirsher case ASYNC_EVENT_COS_PRIORITY: 3673acf19d9SSathya Perla be_async_grp5_cos_priority_process(adapter, compl); 3689aebddd1SJeff Kirsher break; 3699aebddd1SJeff Kirsher case ASYNC_EVENT_QOS_SPEED: 3703acf19d9SSathya Perla be_async_grp5_qos_speed_process(adapter, compl); 3719aebddd1SJeff Kirsher break; 3729aebddd1SJeff Kirsher case ASYNC_EVENT_PVID_STATE: 3733acf19d9SSathya Perla be_async_grp5_pvid_state_process(adapter, compl); 3749aebddd1SJeff Kirsher break; 375760c295eSVenkata Duvvuru /* Async event to disable/enable os2bmc and/or mac-learning */ 376760c295eSVenkata Duvvuru case ASYNC_EVENT_FW_CONTROL: 377760c295eSVenkata Duvvuru be_async_grp5_fw_control_process(adapter, compl); 378760c295eSVenkata Duvvuru break; 3799aebddd1SJeff Kirsher default: 3809aebddd1SJeff Kirsher break; 3819aebddd1SJeff Kirsher } 3829aebddd1SJeff Kirsher } 3839aebddd1SJeff Kirsher 384bc0c3405SAjit Khaparde static void be_async_dbg_evt_process(struct be_adapter *adapter, 3853acf19d9SSathya Perla struct be_mcc_compl *cmp) 386bc0c3405SAjit Khaparde { 387bc0c3405SAjit Khaparde u8 event_type = 0; 388bc0c3405SAjit Khaparde struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp; 389bc0c3405SAjit Khaparde 3903acf19d9SSathya Perla event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) & 3913acf19d9SSathya Perla ASYNC_EVENT_TYPE_MASK; 392bc0c3405SAjit Khaparde 393bc0c3405SAjit Khaparde switch (event_type) { 394bc0c3405SAjit Khaparde case ASYNC_DEBUG_EVENT_TYPE_QNQ: 395bc0c3405SAjit Khaparde if (evt->valid) 396bc0c3405SAjit Khaparde adapter->qnq_vid = le16_to_cpu(evt->vlan_tag); 397bc0c3405SAjit Khaparde adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD; 398bc0c3405SAjit Khaparde break; 399bc0c3405SAjit Khaparde default: 40005ccaa2bSVasundhara Volam dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n", 40105ccaa2bSVasundhara Volam event_type); 402bc0c3405SAjit Khaparde break; 403bc0c3405SAjit Khaparde } 404bc0c3405SAjit Khaparde } 405bc0c3405SAjit Khaparde 40621252377SVasundhara Volam static void be_async_sliport_evt_process(struct be_adapter *adapter, 40721252377SVasundhara Volam struct be_mcc_compl *cmp) 40821252377SVasundhara Volam { 40921252377SVasundhara Volam u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) & 41021252377SVasundhara Volam ASYNC_EVENT_TYPE_MASK; 41121252377SVasundhara Volam 41221252377SVasundhara Volam if (event_type == ASYNC_EVENT_PORT_MISCONFIG) 41321252377SVasundhara Volam be_async_port_misconfig_event_process(adapter, cmp); 41421252377SVasundhara Volam } 41521252377SVasundhara Volam 4163acf19d9SSathya Perla static inline bool is_link_state_evt(u32 flags) 4179aebddd1SJeff Kirsher { 4183acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4199aebddd1SJeff Kirsher ASYNC_EVENT_CODE_LINK_STATE; 4209aebddd1SJeff Kirsher } 4219aebddd1SJeff Kirsher 4223acf19d9SSathya Perla static inline bool is_grp5_evt(u32 flags) 4239aebddd1SJeff Kirsher { 4243acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4253acf19d9SSathya Perla ASYNC_EVENT_CODE_GRP_5; 4269aebddd1SJeff Kirsher } 4279aebddd1SJeff Kirsher 4283acf19d9SSathya Perla static inline bool is_dbg_evt(u32 flags) 429bc0c3405SAjit Khaparde { 4303acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4313acf19d9SSathya Perla ASYNC_EVENT_CODE_QNQ; 4323acf19d9SSathya Perla } 4333acf19d9SSathya Perla 43421252377SVasundhara Volam static inline bool is_sliport_evt(u32 flags) 43521252377SVasundhara Volam { 43621252377SVasundhara Volam return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 43721252377SVasundhara Volam ASYNC_EVENT_CODE_SLIPORT; 43821252377SVasundhara Volam } 43921252377SVasundhara Volam 4403acf19d9SSathya Perla static void be_mcc_event_process(struct be_adapter *adapter, 4413acf19d9SSathya Perla struct be_mcc_compl *compl) 4423acf19d9SSathya Perla { 4433acf19d9SSathya Perla if (is_link_state_evt(compl->flags)) 4443acf19d9SSathya Perla be_async_link_state_process(adapter, compl); 4453acf19d9SSathya Perla else if (is_grp5_evt(compl->flags)) 4463acf19d9SSathya Perla be_async_grp5_evt_process(adapter, compl); 4473acf19d9SSathya Perla else if (is_dbg_evt(compl->flags)) 4483acf19d9SSathya Perla be_async_dbg_evt_process(adapter, compl); 44921252377SVasundhara Volam else if (is_sliport_evt(compl->flags)) 45021252377SVasundhara Volam be_async_sliport_evt_process(adapter, compl); 451bc0c3405SAjit Khaparde } 452bc0c3405SAjit Khaparde 4539aebddd1SJeff Kirsher static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) 4549aebddd1SJeff Kirsher { 4559aebddd1SJeff Kirsher struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq; 4569aebddd1SJeff Kirsher struct be_mcc_compl *compl = queue_tail_node(mcc_cq); 4579aebddd1SJeff Kirsher 4589aebddd1SJeff Kirsher if (be_mcc_compl_is_new(compl)) { 4599aebddd1SJeff Kirsher queue_tail_inc(mcc_cq); 4609aebddd1SJeff Kirsher return compl; 4619aebddd1SJeff Kirsher } 4629aebddd1SJeff Kirsher return NULL; 4639aebddd1SJeff Kirsher } 4649aebddd1SJeff Kirsher 4659aebddd1SJeff Kirsher void be_async_mcc_enable(struct be_adapter *adapter) 4669aebddd1SJeff Kirsher { 4679aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_cq_lock); 4689aebddd1SJeff Kirsher 4699aebddd1SJeff Kirsher be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0); 4709aebddd1SJeff Kirsher adapter->mcc_obj.rearm_cq = true; 4719aebddd1SJeff Kirsher 4729aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_cq_lock); 4739aebddd1SJeff Kirsher } 4749aebddd1SJeff Kirsher 4759aebddd1SJeff Kirsher void be_async_mcc_disable(struct be_adapter *adapter) 4769aebddd1SJeff Kirsher { 477a323d9bfSSathya Perla spin_lock_bh(&adapter->mcc_cq_lock); 478a323d9bfSSathya Perla 4799aebddd1SJeff Kirsher adapter->mcc_obj.rearm_cq = false; 480a323d9bfSSathya Perla be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); 481a323d9bfSSathya Perla 482a323d9bfSSathya Perla spin_unlock_bh(&adapter->mcc_cq_lock); 4839aebddd1SJeff Kirsher } 4849aebddd1SJeff Kirsher 48510ef9ab4SSathya Perla int be_process_mcc(struct be_adapter *adapter) 4869aebddd1SJeff Kirsher { 4879aebddd1SJeff Kirsher struct be_mcc_compl *compl; 48810ef9ab4SSathya Perla int num = 0, status = 0; 4899aebddd1SJeff Kirsher struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 4909aebddd1SJeff Kirsher 491072a9c48SAmerigo Wang spin_lock(&adapter->mcc_cq_lock); 4923acf19d9SSathya Perla 4939aebddd1SJeff Kirsher while ((compl = be_mcc_compl_get(adapter))) { 4949aebddd1SJeff Kirsher if (compl->flags & CQE_FLAGS_ASYNC_MASK) { 4953acf19d9SSathya Perla be_mcc_event_process(adapter, compl); 4969aebddd1SJeff Kirsher } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { 49710ef9ab4SSathya Perla status = be_mcc_compl_process(adapter, compl); 4989aebddd1SJeff Kirsher atomic_dec(&mcc_obj->q.used); 4999aebddd1SJeff Kirsher } 5009aebddd1SJeff Kirsher be_mcc_compl_use(compl); 5019aebddd1SJeff Kirsher num++; 5029aebddd1SJeff Kirsher } 5039aebddd1SJeff Kirsher 50410ef9ab4SSathya Perla if (num) 50510ef9ab4SSathya Perla be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); 50610ef9ab4SSathya Perla 507072a9c48SAmerigo Wang spin_unlock(&adapter->mcc_cq_lock); 50810ef9ab4SSathya Perla return status; 5099aebddd1SJeff Kirsher } 5109aebddd1SJeff Kirsher 5119aebddd1SJeff Kirsher /* Wait till no more pending mcc requests are present */ 5129aebddd1SJeff Kirsher static int be_mcc_wait_compl(struct be_adapter *adapter) 5139aebddd1SJeff Kirsher { 5149aebddd1SJeff Kirsher #define mcc_timeout 120000 /* 12s timeout */ 51510ef9ab4SSathya Perla int i, status = 0; 5169aebddd1SJeff Kirsher struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 5179aebddd1SJeff Kirsher 5186589ade0SSathya Perla for (i = 0; i < mcc_timeout; i++) { 519954f6825SVenkata Duvvuru if (be_check_error(adapter, BE_ERROR_ANY)) 5209aebddd1SJeff Kirsher return -EIO; 5219aebddd1SJeff Kirsher 522072a9c48SAmerigo Wang local_bh_disable(); 52310ef9ab4SSathya Perla status = be_process_mcc(adapter); 524072a9c48SAmerigo Wang local_bh_enable(); 5259aebddd1SJeff Kirsher 5269aebddd1SJeff Kirsher if (atomic_read(&mcc_obj->q.used) == 0) 5279aebddd1SJeff Kirsher break; 5289aebddd1SJeff Kirsher udelay(100); 5299aebddd1SJeff Kirsher } 5309aebddd1SJeff Kirsher if (i == mcc_timeout) { 5316589ade0SSathya Perla dev_err(&adapter->pdev->dev, "FW not responding\n"); 532954f6825SVenkata Duvvuru be_set_error(adapter, BE_ERROR_FW); 533652bf646SPadmanabh Ratnakar return -EIO; 5349aebddd1SJeff Kirsher } 5359aebddd1SJeff Kirsher return status; 5369aebddd1SJeff Kirsher } 5379aebddd1SJeff Kirsher 5389aebddd1SJeff Kirsher /* Notify MCC requests and wait for completion */ 5399aebddd1SJeff Kirsher static int be_mcc_notify_wait(struct be_adapter *adapter) 5409aebddd1SJeff Kirsher { 541652bf646SPadmanabh Ratnakar int status; 542652bf646SPadmanabh Ratnakar struct be_mcc_wrb *wrb; 543652bf646SPadmanabh Ratnakar struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 544652bf646SPadmanabh Ratnakar u16 index = mcc_obj->q.head; 545652bf646SPadmanabh Ratnakar struct be_cmd_resp_hdr *resp; 546652bf646SPadmanabh Ratnakar 547652bf646SPadmanabh Ratnakar index_dec(&index, mcc_obj->q.len); 548652bf646SPadmanabh Ratnakar wrb = queue_index_node(&mcc_obj->q, index); 549652bf646SPadmanabh Ratnakar 550652bf646SPadmanabh Ratnakar resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1); 551652bf646SPadmanabh Ratnakar 552efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 553efaa408eSSuresh Reddy if (status) 554efaa408eSSuresh Reddy goto out; 555652bf646SPadmanabh Ratnakar 556652bf646SPadmanabh Ratnakar status = be_mcc_wait_compl(adapter); 557652bf646SPadmanabh Ratnakar if (status == -EIO) 558652bf646SPadmanabh Ratnakar goto out; 559652bf646SPadmanabh Ratnakar 5604c60005fSKalesh AP status = (resp->base_status | 5614c60005fSKalesh AP ((resp->addl_status & CQE_ADDL_STATUS_MASK) << 5624c60005fSKalesh AP CQE_ADDL_STATUS_SHIFT)); 563652bf646SPadmanabh Ratnakar out: 564652bf646SPadmanabh Ratnakar return status; 5659aebddd1SJeff Kirsher } 5669aebddd1SJeff Kirsher 5679aebddd1SJeff Kirsher static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) 5689aebddd1SJeff Kirsher { 5699aebddd1SJeff Kirsher int msecs = 0; 5709aebddd1SJeff Kirsher u32 ready; 5719aebddd1SJeff Kirsher 5726589ade0SSathya Perla do { 573954f6825SVenkata Duvvuru if (be_check_error(adapter, BE_ERROR_ANY)) 5749aebddd1SJeff Kirsher return -EIO; 5759aebddd1SJeff Kirsher 5769aebddd1SJeff Kirsher ready = ioread32(db); 577434b3648SSathya Perla if (ready == 0xffffffff) 5789aebddd1SJeff Kirsher return -1; 5799aebddd1SJeff Kirsher 5809aebddd1SJeff Kirsher ready &= MPU_MAILBOX_DB_RDY_MASK; 5819aebddd1SJeff Kirsher if (ready) 5829aebddd1SJeff Kirsher break; 5839aebddd1SJeff Kirsher 5849aebddd1SJeff Kirsher if (msecs > 4000) { 5856589ade0SSathya Perla dev_err(&adapter->pdev->dev, "FW not responding\n"); 586954f6825SVenkata Duvvuru be_set_error(adapter, BE_ERROR_FW); 587f67ef7baSPadmanabh Ratnakar be_detect_error(adapter); 5889aebddd1SJeff Kirsher return -1; 5899aebddd1SJeff Kirsher } 5909aebddd1SJeff Kirsher 5919aebddd1SJeff Kirsher msleep(1); 5929aebddd1SJeff Kirsher msecs++; 5939aebddd1SJeff Kirsher } while (true); 5949aebddd1SJeff Kirsher 5959aebddd1SJeff Kirsher return 0; 5969aebddd1SJeff Kirsher } 5979aebddd1SJeff Kirsher 5989aebddd1SJeff Kirsher /* 5999aebddd1SJeff Kirsher * Insert the mailbox address into the doorbell in two steps 6009aebddd1SJeff Kirsher * Polls on the mbox doorbell till a command completion (or a timeout) occurs 6019aebddd1SJeff Kirsher */ 6029aebddd1SJeff Kirsher static int be_mbox_notify_wait(struct be_adapter *adapter) 6039aebddd1SJeff Kirsher { 6049aebddd1SJeff Kirsher int status; 6059aebddd1SJeff Kirsher u32 val = 0; 6069aebddd1SJeff Kirsher void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET; 6079aebddd1SJeff Kirsher struct be_dma_mem *mbox_mem = &adapter->mbox_mem; 6089aebddd1SJeff Kirsher struct be_mcc_mailbox *mbox = mbox_mem->va; 6099aebddd1SJeff Kirsher struct be_mcc_compl *compl = &mbox->compl; 6109aebddd1SJeff Kirsher 6119aebddd1SJeff Kirsher /* wait for ready to be set */ 6129aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 6139aebddd1SJeff Kirsher if (status != 0) 6149aebddd1SJeff Kirsher return status; 6159aebddd1SJeff Kirsher 6169aebddd1SJeff Kirsher val |= MPU_MAILBOX_DB_HI_MASK; 6179aebddd1SJeff Kirsher /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ 6189aebddd1SJeff Kirsher val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; 6199aebddd1SJeff Kirsher iowrite32(val, db); 6209aebddd1SJeff Kirsher 6219aebddd1SJeff Kirsher /* wait for ready to be set */ 6229aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 6239aebddd1SJeff Kirsher if (status != 0) 6249aebddd1SJeff Kirsher return status; 6259aebddd1SJeff Kirsher 6269aebddd1SJeff Kirsher val = 0; 6279aebddd1SJeff Kirsher /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ 6289aebddd1SJeff Kirsher val |= (u32)(mbox_mem->dma >> 4) << 2; 6299aebddd1SJeff Kirsher iowrite32(val, db); 6309aebddd1SJeff Kirsher 6319aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 6329aebddd1SJeff Kirsher if (status != 0) 6339aebddd1SJeff Kirsher return status; 6349aebddd1SJeff Kirsher 6359aebddd1SJeff Kirsher /* A cq entry has been made now */ 6369aebddd1SJeff Kirsher if (be_mcc_compl_is_new(compl)) { 6379aebddd1SJeff Kirsher status = be_mcc_compl_process(adapter, &mbox->compl); 6389aebddd1SJeff Kirsher be_mcc_compl_use(compl); 6399aebddd1SJeff Kirsher if (status) 6409aebddd1SJeff Kirsher return status; 6419aebddd1SJeff Kirsher } else { 6429aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "invalid mailbox completion\n"); 6439aebddd1SJeff Kirsher return -1; 6449aebddd1SJeff Kirsher } 6459aebddd1SJeff Kirsher return 0; 6469aebddd1SJeff Kirsher } 6479aebddd1SJeff Kirsher 648c5b3ad4cSSathya Perla static u16 be_POST_stage_get(struct be_adapter *adapter) 6499aebddd1SJeff Kirsher { 6509aebddd1SJeff Kirsher u32 sem; 6519aebddd1SJeff Kirsher 652c5b3ad4cSSathya Perla if (BEx_chip(adapter)) 653c5b3ad4cSSathya Perla sem = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx); 6549aebddd1SJeff Kirsher else 655c5b3ad4cSSathya Perla pci_read_config_dword(adapter->pdev, 656c5b3ad4cSSathya Perla SLIPORT_SEMAPHORE_OFFSET_SH, &sem); 657c5b3ad4cSSathya Perla 658c5b3ad4cSSathya Perla return sem & POST_STAGE_MASK; 6599aebddd1SJeff Kirsher } 6609aebddd1SJeff Kirsher 66187f20c26SGavin Shan static int lancer_wait_ready(struct be_adapter *adapter) 662bf99e50dSPadmanabh Ratnakar { 663bf99e50dSPadmanabh Ratnakar #define SLIPORT_READY_TIMEOUT 30 664bf99e50dSPadmanabh Ratnakar u32 sliport_status; 665e673244aSKalesh AP int i; 666bf99e50dSPadmanabh Ratnakar 667bf99e50dSPadmanabh Ratnakar for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) { 668bf99e50dSPadmanabh Ratnakar sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); 669bf99e50dSPadmanabh Ratnakar if (sliport_status & SLIPORT_STATUS_RDY_MASK) 6709fa465c0SSathya Perla return 0; 6719fa465c0SSathya Perla 6729fa465c0SSathya Perla if (sliport_status & SLIPORT_STATUS_ERR_MASK && 6739fa465c0SSathya Perla !(sliport_status & SLIPORT_STATUS_RN_MASK)) 6749fa465c0SSathya Perla return -EIO; 675bf99e50dSPadmanabh Ratnakar 676bf99e50dSPadmanabh Ratnakar msleep(1000); 677bf99e50dSPadmanabh Ratnakar } 678bf99e50dSPadmanabh Ratnakar 679e673244aSKalesh AP return sliport_status ? : -1; 680bf99e50dSPadmanabh Ratnakar } 681bf99e50dSPadmanabh Ratnakar 682bf99e50dSPadmanabh Ratnakar int be_fw_wait_ready(struct be_adapter *adapter) 6839aebddd1SJeff Kirsher { 6849aebddd1SJeff Kirsher u16 stage; 6859aebddd1SJeff Kirsher int status, timeout = 0; 6869aebddd1SJeff Kirsher struct device *dev = &adapter->pdev->dev; 6879aebddd1SJeff Kirsher 688bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) { 689bf99e50dSPadmanabh Ratnakar status = lancer_wait_ready(adapter); 690e673244aSKalesh AP if (status) { 691e673244aSKalesh AP stage = status; 692e673244aSKalesh AP goto err; 693e673244aSKalesh AP } 694e673244aSKalesh AP return 0; 695bf99e50dSPadmanabh Ratnakar } 696bf99e50dSPadmanabh Ratnakar 6979aebddd1SJeff Kirsher do { 698ca3de6b2SSathya Perla /* There's no means to poll POST state on BE2/3 VFs */ 699ca3de6b2SSathya Perla if (BEx_chip(adapter) && be_virtfn(adapter)) 700ca3de6b2SSathya Perla return 0; 701ca3de6b2SSathya Perla 702c5b3ad4cSSathya Perla stage = be_POST_stage_get(adapter); 70366d29cbcSGavin Shan if (stage == POST_STAGE_ARMFW_RDY) 70466d29cbcSGavin Shan return 0; 70566d29cbcSGavin Shan 706a2cc4e0bSSathya Perla dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout); 7079aebddd1SJeff Kirsher if (msleep_interruptible(2000)) { 7089aebddd1SJeff Kirsher dev_err(dev, "Waiting for POST aborted\n"); 7099aebddd1SJeff Kirsher return -EINTR; 7109aebddd1SJeff Kirsher } 7119aebddd1SJeff Kirsher timeout += 2; 7123ab81b5fSSomnath Kotur } while (timeout < 60); 7139aebddd1SJeff Kirsher 714e673244aSKalesh AP err: 715e673244aSKalesh AP dev_err(dev, "POST timeout; stage=%#x\n", stage); 7169fa465c0SSathya Perla return -ETIMEDOUT; 7179aebddd1SJeff Kirsher } 7189aebddd1SJeff Kirsher 7199aebddd1SJeff Kirsher static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) 7209aebddd1SJeff Kirsher { 7219aebddd1SJeff Kirsher return &wrb->payload.sgl[0]; 7229aebddd1SJeff Kirsher } 7239aebddd1SJeff Kirsher 724a2cc4e0bSSathya Perla static inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr) 725bea50988SSathya Perla { 726bea50988SSathya Perla wrb->tag0 = addr & 0xFFFFFFFF; 727bea50988SSathya Perla wrb->tag1 = upper_32_bits(addr); 728bea50988SSathya Perla } 7299aebddd1SJeff Kirsher 7309aebddd1SJeff Kirsher /* Don't touch the hdr after it's prepared */ 731106df1e3SSomnath Kotur /* mem will be NULL for embedded commands */ 732106df1e3SSomnath Kotur static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, 733106df1e3SSomnath Kotur u8 subsystem, u8 opcode, int cmd_len, 734a2cc4e0bSSathya Perla struct be_mcc_wrb *wrb, 735a2cc4e0bSSathya Perla struct be_dma_mem *mem) 7369aebddd1SJeff Kirsher { 737106df1e3SSomnath Kotur struct be_sge *sge; 738106df1e3SSomnath Kotur 7399aebddd1SJeff Kirsher req_hdr->opcode = opcode; 7409aebddd1SJeff Kirsher req_hdr->subsystem = subsystem; 7419aebddd1SJeff Kirsher req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); 7429aebddd1SJeff Kirsher req_hdr->version = 0; 743bea50988SSathya Perla fill_wrb_tags(wrb, (ulong) req_hdr); 744106df1e3SSomnath Kotur wrb->payload_length = cmd_len; 745106df1e3SSomnath Kotur if (mem) { 746106df1e3SSomnath Kotur wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) << 747106df1e3SSomnath Kotur MCC_WRB_SGE_CNT_SHIFT; 748106df1e3SSomnath Kotur sge = nonembedded_sgl(wrb); 749106df1e3SSomnath Kotur sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma)); 750106df1e3SSomnath Kotur sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF); 751106df1e3SSomnath Kotur sge->len = cpu_to_le32(mem->size); 752106df1e3SSomnath Kotur } else 753106df1e3SSomnath Kotur wrb->embedded |= MCC_WRB_EMBEDDED_MASK; 754106df1e3SSomnath Kotur be_dws_cpu_to_le(wrb, 8); 7559aebddd1SJeff Kirsher } 7569aebddd1SJeff Kirsher 7579aebddd1SJeff Kirsher static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, 7589aebddd1SJeff Kirsher struct be_dma_mem *mem) 7599aebddd1SJeff Kirsher { 7609aebddd1SJeff Kirsher int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); 7619aebddd1SJeff Kirsher u64 dma = (u64)mem->dma; 7629aebddd1SJeff Kirsher 7639aebddd1SJeff Kirsher for (i = 0; i < buf_pages; i++) { 7649aebddd1SJeff Kirsher pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); 7659aebddd1SJeff Kirsher pages[i].hi = cpu_to_le32(upper_32_bits(dma)); 7669aebddd1SJeff Kirsher dma += PAGE_SIZE_4K; 7679aebddd1SJeff Kirsher } 7689aebddd1SJeff Kirsher } 7699aebddd1SJeff Kirsher 7709aebddd1SJeff Kirsher static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter) 7719aebddd1SJeff Kirsher { 7729aebddd1SJeff Kirsher struct be_dma_mem *mbox_mem = &adapter->mbox_mem; 7739aebddd1SJeff Kirsher struct be_mcc_wrb *wrb 7749aebddd1SJeff Kirsher = &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; 7759aebddd1SJeff Kirsher memset(wrb, 0, sizeof(*wrb)); 7769aebddd1SJeff Kirsher return wrb; 7779aebddd1SJeff Kirsher } 7789aebddd1SJeff Kirsher 7799aebddd1SJeff Kirsher static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) 7809aebddd1SJeff Kirsher { 7819aebddd1SJeff Kirsher struct be_queue_info *mccq = &adapter->mcc_obj.q; 7829aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 7839aebddd1SJeff Kirsher 784aa790db9SPadmanabh Ratnakar if (!mccq->created) 785aa790db9SPadmanabh Ratnakar return NULL; 786aa790db9SPadmanabh Ratnakar 7874d277125SVasundhara Volam if (atomic_read(&mccq->used) >= mccq->len) 7889aebddd1SJeff Kirsher return NULL; 7899aebddd1SJeff Kirsher 7909aebddd1SJeff Kirsher wrb = queue_head_node(mccq); 7919aebddd1SJeff Kirsher queue_head_inc(mccq); 7929aebddd1SJeff Kirsher atomic_inc(&mccq->used); 7939aebddd1SJeff Kirsher memset(wrb, 0, sizeof(*wrb)); 7949aebddd1SJeff Kirsher return wrb; 7959aebddd1SJeff Kirsher } 7969aebddd1SJeff Kirsher 797bea50988SSathya Perla static bool use_mcc(struct be_adapter *adapter) 798bea50988SSathya Perla { 799bea50988SSathya Perla return adapter->mcc_obj.q.created; 800bea50988SSathya Perla } 801bea50988SSathya Perla 802bea50988SSathya Perla /* Must be used only in process context */ 803bea50988SSathya Perla static int be_cmd_lock(struct be_adapter *adapter) 804bea50988SSathya Perla { 805bea50988SSathya Perla if (use_mcc(adapter)) { 806bea50988SSathya Perla spin_lock_bh(&adapter->mcc_lock); 807bea50988SSathya Perla return 0; 808bea50988SSathya Perla } else { 809bea50988SSathya Perla return mutex_lock_interruptible(&adapter->mbox_lock); 810bea50988SSathya Perla } 811bea50988SSathya Perla } 812bea50988SSathya Perla 813bea50988SSathya Perla /* Must be used only in process context */ 814bea50988SSathya Perla static void be_cmd_unlock(struct be_adapter *adapter) 815bea50988SSathya Perla { 816bea50988SSathya Perla if (use_mcc(adapter)) 817bea50988SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 818bea50988SSathya Perla else 819bea50988SSathya Perla return mutex_unlock(&adapter->mbox_lock); 820bea50988SSathya Perla } 821bea50988SSathya Perla 822bea50988SSathya Perla static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter, 823bea50988SSathya Perla struct be_mcc_wrb *wrb) 824bea50988SSathya Perla { 825bea50988SSathya Perla struct be_mcc_wrb *dest_wrb; 826bea50988SSathya Perla 827bea50988SSathya Perla if (use_mcc(adapter)) { 828bea50988SSathya Perla dest_wrb = wrb_from_mccq(adapter); 829bea50988SSathya Perla if (!dest_wrb) 830bea50988SSathya Perla return NULL; 831bea50988SSathya Perla } else { 832bea50988SSathya Perla dest_wrb = wrb_from_mbox(adapter); 833bea50988SSathya Perla } 834bea50988SSathya Perla 835bea50988SSathya Perla memcpy(dest_wrb, wrb, sizeof(*wrb)); 836bea50988SSathya Perla if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK)) 837bea50988SSathya Perla fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb)); 838bea50988SSathya Perla 839bea50988SSathya Perla return dest_wrb; 840bea50988SSathya Perla } 841bea50988SSathya Perla 842bea50988SSathya Perla /* Must be used only in process context */ 843bea50988SSathya Perla static int be_cmd_notify_wait(struct be_adapter *adapter, 844bea50988SSathya Perla struct be_mcc_wrb *wrb) 845bea50988SSathya Perla { 846bea50988SSathya Perla struct be_mcc_wrb *dest_wrb; 847bea50988SSathya Perla int status; 848bea50988SSathya Perla 849bea50988SSathya Perla status = be_cmd_lock(adapter); 850bea50988SSathya Perla if (status) 851bea50988SSathya Perla return status; 852bea50988SSathya Perla 853bea50988SSathya Perla dest_wrb = be_cmd_copy(adapter, wrb); 854bea50988SSathya Perla if (!dest_wrb) 855bea50988SSathya Perla return -EBUSY; 856bea50988SSathya Perla 857bea50988SSathya Perla if (use_mcc(adapter)) 858bea50988SSathya Perla status = be_mcc_notify_wait(adapter); 859bea50988SSathya Perla else 860bea50988SSathya Perla status = be_mbox_notify_wait(adapter); 861bea50988SSathya Perla 862bea50988SSathya Perla if (!status) 863bea50988SSathya Perla memcpy(wrb, dest_wrb, sizeof(*wrb)); 864bea50988SSathya Perla 865bea50988SSathya Perla be_cmd_unlock(adapter); 866bea50988SSathya Perla return status; 867bea50988SSathya Perla } 868bea50988SSathya Perla 8699aebddd1SJeff Kirsher /* Tell fw we're about to start firing cmds by writing a 8709aebddd1SJeff Kirsher * special pattern across the wrb hdr; uses mbox 8719aebddd1SJeff Kirsher */ 8729aebddd1SJeff Kirsher int be_cmd_fw_init(struct be_adapter *adapter) 8739aebddd1SJeff Kirsher { 8749aebddd1SJeff Kirsher u8 *wrb; 8759aebddd1SJeff Kirsher int status; 8769aebddd1SJeff Kirsher 877bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) 878bf99e50dSPadmanabh Ratnakar return 0; 879bf99e50dSPadmanabh Ratnakar 8809aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 8819aebddd1SJeff Kirsher return -1; 8829aebddd1SJeff Kirsher 8839aebddd1SJeff Kirsher wrb = (u8 *)wrb_from_mbox(adapter); 8849aebddd1SJeff Kirsher *wrb++ = 0xFF; 8859aebddd1SJeff Kirsher *wrb++ = 0x12; 8869aebddd1SJeff Kirsher *wrb++ = 0x34; 8879aebddd1SJeff Kirsher *wrb++ = 0xFF; 8889aebddd1SJeff Kirsher *wrb++ = 0xFF; 8899aebddd1SJeff Kirsher *wrb++ = 0x56; 8909aebddd1SJeff Kirsher *wrb++ = 0x78; 8919aebddd1SJeff Kirsher *wrb = 0xFF; 8929aebddd1SJeff Kirsher 8939aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 8949aebddd1SJeff Kirsher 8959aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 8969aebddd1SJeff Kirsher return status; 8979aebddd1SJeff Kirsher } 8989aebddd1SJeff Kirsher 8999aebddd1SJeff Kirsher /* Tell fw we're done with firing cmds by writing a 9009aebddd1SJeff Kirsher * special pattern across the wrb hdr; uses mbox 9019aebddd1SJeff Kirsher */ 9029aebddd1SJeff Kirsher int be_cmd_fw_clean(struct be_adapter *adapter) 9039aebddd1SJeff Kirsher { 9049aebddd1SJeff Kirsher u8 *wrb; 9059aebddd1SJeff Kirsher int status; 9069aebddd1SJeff Kirsher 907bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) 908bf99e50dSPadmanabh Ratnakar return 0; 909bf99e50dSPadmanabh Ratnakar 9109aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 9119aebddd1SJeff Kirsher return -1; 9129aebddd1SJeff Kirsher 9139aebddd1SJeff Kirsher wrb = (u8 *)wrb_from_mbox(adapter); 9149aebddd1SJeff Kirsher *wrb++ = 0xFF; 9159aebddd1SJeff Kirsher *wrb++ = 0xAA; 9169aebddd1SJeff Kirsher *wrb++ = 0xBB; 9179aebddd1SJeff Kirsher *wrb++ = 0xFF; 9189aebddd1SJeff Kirsher *wrb++ = 0xFF; 9199aebddd1SJeff Kirsher *wrb++ = 0xCC; 9209aebddd1SJeff Kirsher *wrb++ = 0xDD; 9219aebddd1SJeff Kirsher *wrb = 0xFF; 9229aebddd1SJeff Kirsher 9239aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 9249aebddd1SJeff Kirsher 9259aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 9269aebddd1SJeff Kirsher return status; 9279aebddd1SJeff Kirsher } 928bf99e50dSPadmanabh Ratnakar 929f2f781a7SSathya Perla int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo) 9309aebddd1SJeff Kirsher { 9319aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 9329aebddd1SJeff Kirsher struct be_cmd_req_eq_create *req; 933f2f781a7SSathya Perla struct be_dma_mem *q_mem = &eqo->q.dma_mem; 934f2f781a7SSathya Perla int status, ver = 0; 9359aebddd1SJeff Kirsher 9369aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 9379aebddd1SJeff Kirsher return -1; 9389aebddd1SJeff Kirsher 9399aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 9409aebddd1SJeff Kirsher req = embedded_payload(wrb); 9419aebddd1SJeff Kirsher 942106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 943a2cc4e0bSSathya Perla OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb, 944a2cc4e0bSSathya Perla NULL); 9459aebddd1SJeff Kirsher 946f2f781a7SSathya Perla /* Support for EQ_CREATEv2 available only SH-R onwards */ 947f2f781a7SSathya Perla if (!(BEx_chip(adapter) || lancer_chip(adapter))) 948f2f781a7SSathya Perla ver = 2; 949f2f781a7SSathya Perla 950f2f781a7SSathya Perla req->hdr.version = ver; 9519aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 9529aebddd1SJeff Kirsher 9539aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); 9549aebddd1SJeff Kirsher /* 4byte eqe*/ 9559aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); 9569aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, count, req->context, 957f2f781a7SSathya Perla __ilog2_u32(eqo->q.len / 256)); 9589aebddd1SJeff Kirsher be_dws_cpu_to_le(req->context, sizeof(req->context)); 9599aebddd1SJeff Kirsher 9609aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 9619aebddd1SJeff Kirsher 9629aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 9639aebddd1SJeff Kirsher if (!status) { 9649aebddd1SJeff Kirsher struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); 96503d28ffeSKalesh AP 966f2f781a7SSathya Perla eqo->q.id = le16_to_cpu(resp->eq_id); 967f2f781a7SSathya Perla eqo->msix_idx = 968f2f781a7SSathya Perla (ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx; 969f2f781a7SSathya Perla eqo->q.created = true; 9709aebddd1SJeff Kirsher } 9719aebddd1SJeff Kirsher 9729aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 9739aebddd1SJeff Kirsher return status; 9749aebddd1SJeff Kirsher } 9759aebddd1SJeff Kirsher 976f9449ab7SSathya Perla /* Use MCC */ 9779aebddd1SJeff Kirsher int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, 9785ee4979bSSathya Perla bool permanent, u32 if_handle, u32 pmac_id) 9799aebddd1SJeff Kirsher { 9809aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 9819aebddd1SJeff Kirsher struct be_cmd_req_mac_query *req; 9829aebddd1SJeff Kirsher int status; 9839aebddd1SJeff Kirsher 984f9449ab7SSathya Perla spin_lock_bh(&adapter->mcc_lock); 9859aebddd1SJeff Kirsher 986f9449ab7SSathya Perla wrb = wrb_from_mccq(adapter); 987f9449ab7SSathya Perla if (!wrb) { 988f9449ab7SSathya Perla status = -EBUSY; 989f9449ab7SSathya Perla goto err; 990f9449ab7SSathya Perla } 9919aebddd1SJeff Kirsher req = embedded_payload(wrb); 9929aebddd1SJeff Kirsher 993106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 994a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb, 995a2cc4e0bSSathya Perla NULL); 9965ee4979bSSathya Perla req->type = MAC_ADDRESS_TYPE_NETWORK; 9979aebddd1SJeff Kirsher if (permanent) { 9989aebddd1SJeff Kirsher req->permanent = 1; 9999aebddd1SJeff Kirsher } else { 10009aebddd1SJeff Kirsher req->if_id = cpu_to_le16((u16)if_handle); 1001590c391dSPadmanabh Ratnakar req->pmac_id = cpu_to_le32(pmac_id); 10029aebddd1SJeff Kirsher req->permanent = 0; 10039aebddd1SJeff Kirsher } 10049aebddd1SJeff Kirsher 1005f9449ab7SSathya Perla status = be_mcc_notify_wait(adapter); 10069aebddd1SJeff Kirsher if (!status) { 10079aebddd1SJeff Kirsher struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); 100803d28ffeSKalesh AP 10099aebddd1SJeff Kirsher memcpy(mac_addr, resp->mac.addr, ETH_ALEN); 10109aebddd1SJeff Kirsher } 10119aebddd1SJeff Kirsher 1012f9449ab7SSathya Perla err: 1013f9449ab7SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 10149aebddd1SJeff Kirsher return status; 10159aebddd1SJeff Kirsher } 10169aebddd1SJeff Kirsher 10179aebddd1SJeff Kirsher /* Uses synchronous MCCQ */ 10189aebddd1SJeff Kirsher int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, 10199aebddd1SJeff Kirsher u32 if_id, u32 *pmac_id, u32 domain) 10209aebddd1SJeff Kirsher { 10219aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10229aebddd1SJeff Kirsher struct be_cmd_req_pmac_add *req; 10239aebddd1SJeff Kirsher int status; 10249aebddd1SJeff Kirsher 10259aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 10269aebddd1SJeff Kirsher 10279aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 10289aebddd1SJeff Kirsher if (!wrb) { 10299aebddd1SJeff Kirsher status = -EBUSY; 10309aebddd1SJeff Kirsher goto err; 10319aebddd1SJeff Kirsher } 10329aebddd1SJeff Kirsher req = embedded_payload(wrb); 10339aebddd1SJeff Kirsher 1034106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1035a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb, 1036a2cc4e0bSSathya Perla NULL); 10379aebddd1SJeff Kirsher 10389aebddd1SJeff Kirsher req->hdr.domain = domain; 10399aebddd1SJeff Kirsher req->if_id = cpu_to_le32(if_id); 10409aebddd1SJeff Kirsher memcpy(req->mac_address, mac_addr, ETH_ALEN); 10419aebddd1SJeff Kirsher 10429aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 10439aebddd1SJeff Kirsher if (!status) { 10449aebddd1SJeff Kirsher struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb); 104503d28ffeSKalesh AP 10469aebddd1SJeff Kirsher *pmac_id = le32_to_cpu(resp->pmac_id); 10479aebddd1SJeff Kirsher } 10489aebddd1SJeff Kirsher 10499aebddd1SJeff Kirsher err: 10509aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 1051e3a7ae2cSSomnath Kotur 1052e3a7ae2cSSomnath Kotur if (status == MCC_STATUS_UNAUTHORIZED_REQUEST) 1053e3a7ae2cSSomnath Kotur status = -EPERM; 1054e3a7ae2cSSomnath Kotur 10559aebddd1SJeff Kirsher return status; 10569aebddd1SJeff Kirsher } 10579aebddd1SJeff Kirsher 10589aebddd1SJeff Kirsher /* Uses synchronous MCCQ */ 105930128031SSathya Perla int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) 10609aebddd1SJeff Kirsher { 10619aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10629aebddd1SJeff Kirsher struct be_cmd_req_pmac_del *req; 10639aebddd1SJeff Kirsher int status; 10649aebddd1SJeff Kirsher 106530128031SSathya Perla if (pmac_id == -1) 106630128031SSathya Perla return 0; 106730128031SSathya Perla 10689aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 10699aebddd1SJeff Kirsher 10709aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 10719aebddd1SJeff Kirsher if (!wrb) { 10729aebddd1SJeff Kirsher status = -EBUSY; 10739aebddd1SJeff Kirsher goto err; 10749aebddd1SJeff Kirsher } 10759aebddd1SJeff Kirsher req = embedded_payload(wrb); 10769aebddd1SJeff Kirsher 1077106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1078cd3307aaSKalesh AP OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req), 1079cd3307aaSKalesh AP wrb, NULL); 10809aebddd1SJeff Kirsher 10819aebddd1SJeff Kirsher req->hdr.domain = dom; 10829aebddd1SJeff Kirsher req->if_id = cpu_to_le32(if_id); 10839aebddd1SJeff Kirsher req->pmac_id = cpu_to_le32(pmac_id); 10849aebddd1SJeff Kirsher 10859aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 10869aebddd1SJeff Kirsher 10879aebddd1SJeff Kirsher err: 10889aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 10899aebddd1SJeff Kirsher return status; 10909aebddd1SJeff Kirsher } 10919aebddd1SJeff Kirsher 10929aebddd1SJeff Kirsher /* Uses Mbox */ 109310ef9ab4SSathya Perla int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, 109410ef9ab4SSathya Perla struct be_queue_info *eq, bool no_delay, int coalesce_wm) 10959aebddd1SJeff Kirsher { 10969aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10979aebddd1SJeff Kirsher struct be_cmd_req_cq_create *req; 10989aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &cq->dma_mem; 10999aebddd1SJeff Kirsher void *ctxt; 11009aebddd1SJeff Kirsher int status; 11019aebddd1SJeff Kirsher 11029aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 11039aebddd1SJeff Kirsher return -1; 11049aebddd1SJeff Kirsher 11059aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 11069aebddd1SJeff Kirsher req = embedded_payload(wrb); 11079aebddd1SJeff Kirsher ctxt = &req->context; 11089aebddd1SJeff Kirsher 1109106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1110a2cc4e0bSSathya Perla OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb, 1111a2cc4e0bSSathya Perla NULL); 11129aebddd1SJeff Kirsher 11139aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 1114bbdc42f8SAjit Khaparde 1115bbdc42f8SAjit Khaparde if (BEx_chip(adapter)) { 11169aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt, 11179aebddd1SJeff Kirsher coalesce_wm); 11189aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, nodelay, 11199aebddd1SJeff Kirsher ctxt, no_delay); 11209aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt, 11219aebddd1SJeff Kirsher __ilog2_u32(cq->len / 256)); 11229aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1); 11239aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1); 11249aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id); 1125bbdc42f8SAjit Khaparde } else { 1126bbdc42f8SAjit Khaparde req->hdr.version = 2; 1127bbdc42f8SAjit Khaparde req->page_size = 1; /* 1 for 4K */ 112809e83a9dSAjit Khaparde 112909e83a9dSAjit Khaparde /* coalesce-wm field in this cmd is not relevant to Lancer. 113009e83a9dSAjit Khaparde * Lancer uses COMMON_MODIFY_CQ to set this field 113109e83a9dSAjit Khaparde */ 113209e83a9dSAjit Khaparde if (!lancer_chip(adapter)) 113309e83a9dSAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm, 113409e83a9dSAjit Khaparde ctxt, coalesce_wm); 1135bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt, 1136bbdc42f8SAjit Khaparde no_delay); 1137bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt, 1138bbdc42f8SAjit Khaparde __ilog2_u32(cq->len / 256)); 1139bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1); 1140a2cc4e0bSSathya Perla AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1); 1141a2cc4e0bSSathya Perla AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id); 11429aebddd1SJeff Kirsher } 11439aebddd1SJeff Kirsher 11449aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 11459aebddd1SJeff Kirsher 11469aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 11479aebddd1SJeff Kirsher 11489aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 11499aebddd1SJeff Kirsher if (!status) { 11509aebddd1SJeff Kirsher struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); 115103d28ffeSKalesh AP 11529aebddd1SJeff Kirsher cq->id = le16_to_cpu(resp->cq_id); 11539aebddd1SJeff Kirsher cq->created = true; 11549aebddd1SJeff Kirsher } 11559aebddd1SJeff Kirsher 11569aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 11579aebddd1SJeff Kirsher 11589aebddd1SJeff Kirsher return status; 11599aebddd1SJeff Kirsher } 11609aebddd1SJeff Kirsher 11619aebddd1SJeff Kirsher static u32 be_encoded_q_len(int q_len) 11629aebddd1SJeff Kirsher { 11639aebddd1SJeff Kirsher u32 len_encoded = fls(q_len); /* log2(len) + 1 */ 116403d28ffeSKalesh AP 11659aebddd1SJeff Kirsher if (len_encoded == 16) 11669aebddd1SJeff Kirsher len_encoded = 0; 11679aebddd1SJeff Kirsher return len_encoded; 11689aebddd1SJeff Kirsher } 11699aebddd1SJeff Kirsher 11704188e7dfSJingoo Han static int be_cmd_mccq_ext_create(struct be_adapter *adapter, 11719aebddd1SJeff Kirsher struct be_queue_info *mccq, 11729aebddd1SJeff Kirsher struct be_queue_info *cq) 11739aebddd1SJeff Kirsher { 11749aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 11759aebddd1SJeff Kirsher struct be_cmd_req_mcc_ext_create *req; 11769aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &mccq->dma_mem; 11779aebddd1SJeff Kirsher void *ctxt; 11789aebddd1SJeff Kirsher int status; 11799aebddd1SJeff Kirsher 11809aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 11819aebddd1SJeff Kirsher return -1; 11829aebddd1SJeff Kirsher 11839aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 11849aebddd1SJeff Kirsher req = embedded_payload(wrb); 11859aebddd1SJeff Kirsher ctxt = &req->context; 11869aebddd1SJeff Kirsher 1187106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1188a2cc4e0bSSathya Perla OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb, 1189a2cc4e0bSSathya Perla NULL); 11909aebddd1SJeff Kirsher 11919aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 1192666d39c7SVasundhara Volam if (BEx_chip(adapter)) { 11939aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); 11949aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, 11959aebddd1SJeff Kirsher be_encoded_q_len(mccq->len)); 11969aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); 1197666d39c7SVasundhara Volam } else { 1198666d39c7SVasundhara Volam req->hdr.version = 1; 1199666d39c7SVasundhara Volam req->cq_id = cpu_to_le16(cq->id); 1200666d39c7SVasundhara Volam 1201666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt, 1202666d39c7SVasundhara Volam be_encoded_q_len(mccq->len)); 1203666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1); 1204666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id, 1205666d39c7SVasundhara Volam ctxt, cq->id); 1206666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid, 1207666d39c7SVasundhara Volam ctxt, 1); 12089aebddd1SJeff Kirsher } 12099aebddd1SJeff Kirsher 121021252377SVasundhara Volam /* Subscribe to Link State, Sliport Event and Group 5 Events 121121252377SVasundhara Volam * (bits 1, 5 and 17 set) 121221252377SVasundhara Volam */ 121321252377SVasundhara Volam req->async_event_bitmap[0] = 121421252377SVasundhara Volam cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) | 121521252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_GRP_5) | 121621252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_QNQ) | 121721252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_SLIPORT)); 121821252377SVasundhara Volam 12199aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 12209aebddd1SJeff Kirsher 12219aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 12229aebddd1SJeff Kirsher 12239aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 12249aebddd1SJeff Kirsher if (!status) { 12259aebddd1SJeff Kirsher struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); 122603d28ffeSKalesh AP 12279aebddd1SJeff Kirsher mccq->id = le16_to_cpu(resp->id); 12289aebddd1SJeff Kirsher mccq->created = true; 12299aebddd1SJeff Kirsher } 12309aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 12319aebddd1SJeff Kirsher 12329aebddd1SJeff Kirsher return status; 12339aebddd1SJeff Kirsher } 12349aebddd1SJeff Kirsher 12354188e7dfSJingoo Han static int be_cmd_mccq_org_create(struct be_adapter *adapter, 12369aebddd1SJeff Kirsher struct be_queue_info *mccq, 12379aebddd1SJeff Kirsher struct be_queue_info *cq) 12389aebddd1SJeff Kirsher { 12399aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 12409aebddd1SJeff Kirsher struct be_cmd_req_mcc_create *req; 12419aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &mccq->dma_mem; 12429aebddd1SJeff Kirsher void *ctxt; 12439aebddd1SJeff Kirsher int status; 12449aebddd1SJeff Kirsher 12459aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 12469aebddd1SJeff Kirsher return -1; 12479aebddd1SJeff Kirsher 12489aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 12499aebddd1SJeff Kirsher req = embedded_payload(wrb); 12509aebddd1SJeff Kirsher ctxt = &req->context; 12519aebddd1SJeff Kirsher 1252106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1253a2cc4e0bSSathya Perla OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb, 1254a2cc4e0bSSathya Perla NULL); 12559aebddd1SJeff Kirsher 12569aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 12579aebddd1SJeff Kirsher 12589aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); 12599aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, 12609aebddd1SJeff Kirsher be_encoded_q_len(mccq->len)); 12619aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); 12629aebddd1SJeff Kirsher 12639aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 12649aebddd1SJeff Kirsher 12659aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 12669aebddd1SJeff Kirsher 12679aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 12689aebddd1SJeff Kirsher if (!status) { 12699aebddd1SJeff Kirsher struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); 127003d28ffeSKalesh AP 12719aebddd1SJeff Kirsher mccq->id = le16_to_cpu(resp->id); 12729aebddd1SJeff Kirsher mccq->created = true; 12739aebddd1SJeff Kirsher } 12749aebddd1SJeff Kirsher 12759aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 12769aebddd1SJeff Kirsher return status; 12779aebddd1SJeff Kirsher } 12789aebddd1SJeff Kirsher 12799aebddd1SJeff Kirsher int be_cmd_mccq_create(struct be_adapter *adapter, 1280a2cc4e0bSSathya Perla struct be_queue_info *mccq, struct be_queue_info *cq) 12819aebddd1SJeff Kirsher { 12829aebddd1SJeff Kirsher int status; 12839aebddd1SJeff Kirsher 12849aebddd1SJeff Kirsher status = be_cmd_mccq_ext_create(adapter, mccq, cq); 1285666d39c7SVasundhara Volam if (status && BEx_chip(adapter)) { 12869aebddd1SJeff Kirsher dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 " 12879aebddd1SJeff Kirsher "or newer to avoid conflicting priorities between NIC " 12889aebddd1SJeff Kirsher "and FCoE traffic"); 12899aebddd1SJeff Kirsher status = be_cmd_mccq_org_create(adapter, mccq, cq); 12909aebddd1SJeff Kirsher } 12919aebddd1SJeff Kirsher return status; 12929aebddd1SJeff Kirsher } 12939aebddd1SJeff Kirsher 129494d73aaaSVasundhara Volam int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) 12959aebddd1SJeff Kirsher { 12967707133cSSathya Perla struct be_mcc_wrb wrb = {0}; 12979aebddd1SJeff Kirsher struct be_cmd_req_eth_tx_create *req; 129894d73aaaSVasundhara Volam struct be_queue_info *txq = &txo->q; 129994d73aaaSVasundhara Volam struct be_queue_info *cq = &txo->cq; 13009aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &txq->dma_mem; 130194d73aaaSVasundhara Volam int status, ver = 0; 13029aebddd1SJeff Kirsher 13037707133cSSathya Perla req = embedded_payload(&wrb); 1304106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 13057707133cSSathya Perla OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL); 13069aebddd1SJeff Kirsher 13079aebddd1SJeff Kirsher if (lancer_chip(adapter)) { 13089aebddd1SJeff Kirsher req->hdr.version = 1; 130994d73aaaSVasundhara Volam } else if (BEx_chip(adapter)) { 131094d73aaaSVasundhara Volam if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) 131194d73aaaSVasundhara Volam req->hdr.version = 2; 131294d73aaaSVasundhara Volam } else { /* For SH */ 131394d73aaaSVasundhara Volam req->hdr.version = 2; 13149aebddd1SJeff Kirsher } 13159aebddd1SJeff Kirsher 131681b02655SVasundhara Volam if (req->hdr.version > 0) 131781b02655SVasundhara Volam req->if_id = cpu_to_le16(adapter->if_handle); 13189aebddd1SJeff Kirsher req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); 13199aebddd1SJeff Kirsher req->ulp_num = BE_ULP1_NUM; 13209aebddd1SJeff Kirsher req->type = BE_ETH_TX_RING_TYPE_STANDARD; 132194d73aaaSVasundhara Volam req->cq_id = cpu_to_le16(cq->id); 132294d73aaaSVasundhara Volam req->queue_size = be_encoded_q_len(txq->len); 13239aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 132494d73aaaSVasundhara Volam ver = req->hdr.version; 132594d73aaaSVasundhara Volam 13267707133cSSathya Perla status = be_cmd_notify_wait(adapter, &wrb); 13279aebddd1SJeff Kirsher if (!status) { 13287707133cSSathya Perla struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb); 132903d28ffeSKalesh AP 13309aebddd1SJeff Kirsher txq->id = le16_to_cpu(resp->cid); 133194d73aaaSVasundhara Volam if (ver == 2) 133294d73aaaSVasundhara Volam txo->db_offset = le32_to_cpu(resp->db_offset); 133394d73aaaSVasundhara Volam else 133494d73aaaSVasundhara Volam txo->db_offset = DB_TXULP1_OFFSET; 13359aebddd1SJeff Kirsher txq->created = true; 13369aebddd1SJeff Kirsher } 13379aebddd1SJeff Kirsher 13389aebddd1SJeff Kirsher return status; 13399aebddd1SJeff Kirsher } 13409aebddd1SJeff Kirsher 13419aebddd1SJeff Kirsher /* Uses MCC */ 13429aebddd1SJeff Kirsher int be_cmd_rxq_create(struct be_adapter *adapter, 13439aebddd1SJeff Kirsher struct be_queue_info *rxq, u16 cq_id, u16 frag_size, 134410ef9ab4SSathya Perla u32 if_id, u32 rss, u8 *rss_id) 13459aebddd1SJeff Kirsher { 13469aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 13479aebddd1SJeff Kirsher struct be_cmd_req_eth_rx_create *req; 13489aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &rxq->dma_mem; 13499aebddd1SJeff Kirsher int status; 13509aebddd1SJeff Kirsher 13519aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 13529aebddd1SJeff Kirsher 13539aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 13549aebddd1SJeff Kirsher if (!wrb) { 13559aebddd1SJeff Kirsher status = -EBUSY; 13569aebddd1SJeff Kirsher goto err; 13579aebddd1SJeff Kirsher } 13589aebddd1SJeff Kirsher req = embedded_payload(wrb); 13599aebddd1SJeff Kirsher 1360106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1361106df1e3SSomnath Kotur OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL); 13629aebddd1SJeff Kirsher 13639aebddd1SJeff Kirsher req->cq_id = cpu_to_le16(cq_id); 13649aebddd1SJeff Kirsher req->frag_size = fls(frag_size) - 1; 13659aebddd1SJeff Kirsher req->num_pages = 2; 13669aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 13679aebddd1SJeff Kirsher req->interface_id = cpu_to_le32(if_id); 136810ef9ab4SSathya Perla req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE); 13699aebddd1SJeff Kirsher req->rss_queue = cpu_to_le32(rss); 13709aebddd1SJeff Kirsher 13719aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 13729aebddd1SJeff Kirsher if (!status) { 13739aebddd1SJeff Kirsher struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); 137403d28ffeSKalesh AP 13759aebddd1SJeff Kirsher rxq->id = le16_to_cpu(resp->id); 13769aebddd1SJeff Kirsher rxq->created = true; 13779aebddd1SJeff Kirsher *rss_id = resp->rss_id; 13789aebddd1SJeff Kirsher } 13799aebddd1SJeff Kirsher 13809aebddd1SJeff Kirsher err: 13819aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 13829aebddd1SJeff Kirsher return status; 13839aebddd1SJeff Kirsher } 13849aebddd1SJeff Kirsher 13859aebddd1SJeff Kirsher /* Generic destroyer function for all types of queues 13869aebddd1SJeff Kirsher * Uses Mbox 13879aebddd1SJeff Kirsher */ 13889aebddd1SJeff Kirsher int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, 13899aebddd1SJeff Kirsher int queue_type) 13909aebddd1SJeff Kirsher { 13919aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 13929aebddd1SJeff Kirsher struct be_cmd_req_q_destroy *req; 13939aebddd1SJeff Kirsher u8 subsys = 0, opcode = 0; 13949aebddd1SJeff Kirsher int status; 13959aebddd1SJeff Kirsher 13969aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 13979aebddd1SJeff Kirsher return -1; 13989aebddd1SJeff Kirsher 13999aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 14009aebddd1SJeff Kirsher req = embedded_payload(wrb); 14019aebddd1SJeff Kirsher 14029aebddd1SJeff Kirsher switch (queue_type) { 14039aebddd1SJeff Kirsher case QTYPE_EQ: 14049aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 14059aebddd1SJeff Kirsher opcode = OPCODE_COMMON_EQ_DESTROY; 14069aebddd1SJeff Kirsher break; 14079aebddd1SJeff Kirsher case QTYPE_CQ: 14089aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 14099aebddd1SJeff Kirsher opcode = OPCODE_COMMON_CQ_DESTROY; 14109aebddd1SJeff Kirsher break; 14119aebddd1SJeff Kirsher case QTYPE_TXQ: 14129aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_ETH; 14139aebddd1SJeff Kirsher opcode = OPCODE_ETH_TX_DESTROY; 14149aebddd1SJeff Kirsher break; 14159aebddd1SJeff Kirsher case QTYPE_RXQ: 14169aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_ETH; 14179aebddd1SJeff Kirsher opcode = OPCODE_ETH_RX_DESTROY; 14189aebddd1SJeff Kirsher break; 14199aebddd1SJeff Kirsher case QTYPE_MCCQ: 14209aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 14219aebddd1SJeff Kirsher opcode = OPCODE_COMMON_MCC_DESTROY; 14229aebddd1SJeff Kirsher break; 14239aebddd1SJeff Kirsher default: 14249aebddd1SJeff Kirsher BUG(); 14259aebddd1SJeff Kirsher } 14269aebddd1SJeff Kirsher 1427106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb, 1428106df1e3SSomnath Kotur NULL); 14299aebddd1SJeff Kirsher req->id = cpu_to_le16(q->id); 14309aebddd1SJeff Kirsher 14319aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 14329aebddd1SJeff Kirsher q->created = false; 14339aebddd1SJeff Kirsher 14349aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 14359aebddd1SJeff Kirsher return status; 14369aebddd1SJeff Kirsher } 14379aebddd1SJeff Kirsher 14389aebddd1SJeff Kirsher /* Uses MCC */ 14399aebddd1SJeff Kirsher int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) 14409aebddd1SJeff Kirsher { 14419aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 14429aebddd1SJeff Kirsher struct be_cmd_req_q_destroy *req; 14439aebddd1SJeff Kirsher int status; 14449aebddd1SJeff Kirsher 14459aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 14469aebddd1SJeff Kirsher 14479aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 14489aebddd1SJeff Kirsher if (!wrb) { 14499aebddd1SJeff Kirsher status = -EBUSY; 14509aebddd1SJeff Kirsher goto err; 14519aebddd1SJeff Kirsher } 14529aebddd1SJeff Kirsher req = embedded_payload(wrb); 14539aebddd1SJeff Kirsher 1454106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1455106df1e3SSomnath Kotur OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL); 14569aebddd1SJeff Kirsher req->id = cpu_to_le16(q->id); 14579aebddd1SJeff Kirsher 14589aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 14599aebddd1SJeff Kirsher q->created = false; 14609aebddd1SJeff Kirsher 14619aebddd1SJeff Kirsher err: 14629aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 14639aebddd1SJeff Kirsher return status; 14649aebddd1SJeff Kirsher } 14659aebddd1SJeff Kirsher 14669aebddd1SJeff Kirsher /* Create an rx filtering policy configuration on an i/f 1467bea50988SSathya Perla * Will use MBOX only if MCCQ has not been created. 14689aebddd1SJeff Kirsher */ 14699aebddd1SJeff Kirsher int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, 14701578e777SPadmanabh Ratnakar u32 *if_handle, u32 domain) 14719aebddd1SJeff Kirsher { 1472bea50988SSathya Perla struct be_mcc_wrb wrb = {0}; 14739aebddd1SJeff Kirsher struct be_cmd_req_if_create *req; 14749aebddd1SJeff Kirsher int status; 14759aebddd1SJeff Kirsher 1476bea50988SSathya Perla req = embedded_payload(&wrb); 1477106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1478a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_INTERFACE_CREATE, 1479a2cc4e0bSSathya Perla sizeof(*req), &wrb, NULL); 14809aebddd1SJeff Kirsher req->hdr.domain = domain; 14819aebddd1SJeff Kirsher req->capability_flags = cpu_to_le32(cap_flags); 14829aebddd1SJeff Kirsher req->enable_flags = cpu_to_le32(en_flags); 1483f9449ab7SSathya Perla req->pmac_invalid = true; 14849aebddd1SJeff Kirsher 1485bea50988SSathya Perla status = be_cmd_notify_wait(adapter, &wrb); 14869aebddd1SJeff Kirsher if (!status) { 1487bea50988SSathya Perla struct be_cmd_resp_if_create *resp = embedded_payload(&wrb); 148803d28ffeSKalesh AP 14899aebddd1SJeff Kirsher *if_handle = le32_to_cpu(resp->interface_id); 1490b5bb9776SSathya Perla 1491b5bb9776SSathya Perla /* Hack to retrieve VF's pmac-id on BE3 */ 149218c57c74SKalesh AP if (BE3_chip(adapter) && be_virtfn(adapter)) 1493b5bb9776SSathya Perla adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id); 14949aebddd1SJeff Kirsher } 14959aebddd1SJeff Kirsher return status; 14969aebddd1SJeff Kirsher } 14979aebddd1SJeff Kirsher 1498f9449ab7SSathya Perla /* Uses MCCQ */ 149930128031SSathya Perla int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain) 15009aebddd1SJeff Kirsher { 15019aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 15029aebddd1SJeff Kirsher struct be_cmd_req_if_destroy *req; 15039aebddd1SJeff Kirsher int status; 15049aebddd1SJeff Kirsher 150530128031SSathya Perla if (interface_id == -1) 1506f9449ab7SSathya Perla return 0; 15079aebddd1SJeff Kirsher 1508f9449ab7SSathya Perla spin_lock_bh(&adapter->mcc_lock); 1509f9449ab7SSathya Perla 1510f9449ab7SSathya Perla wrb = wrb_from_mccq(adapter); 1511f9449ab7SSathya Perla if (!wrb) { 1512f9449ab7SSathya Perla status = -EBUSY; 1513f9449ab7SSathya Perla goto err; 1514f9449ab7SSathya Perla } 15159aebddd1SJeff Kirsher req = embedded_payload(wrb); 15169aebddd1SJeff Kirsher 1517106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1518a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_INTERFACE_DESTROY, 1519a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 15209aebddd1SJeff Kirsher req->hdr.domain = domain; 15219aebddd1SJeff Kirsher req->interface_id = cpu_to_le32(interface_id); 15229aebddd1SJeff Kirsher 1523f9449ab7SSathya Perla status = be_mcc_notify_wait(adapter); 1524f9449ab7SSathya Perla err: 1525f9449ab7SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 15269aebddd1SJeff Kirsher return status; 15279aebddd1SJeff Kirsher } 15289aebddd1SJeff Kirsher 15299aebddd1SJeff Kirsher /* Get stats is a non embedded command: the request is not embedded inside 15309aebddd1SJeff Kirsher * WRB but is a separate dma memory block 15319aebddd1SJeff Kirsher * Uses asynchronous MCC 15329aebddd1SJeff Kirsher */ 15339aebddd1SJeff Kirsher int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) 15349aebddd1SJeff Kirsher { 15359aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 15369aebddd1SJeff Kirsher struct be_cmd_req_hdr *hdr; 15379aebddd1SJeff Kirsher int status = 0; 15389aebddd1SJeff Kirsher 15399aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 15409aebddd1SJeff Kirsher 15419aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 15429aebddd1SJeff Kirsher if (!wrb) { 15439aebddd1SJeff Kirsher status = -EBUSY; 15449aebddd1SJeff Kirsher goto err; 15459aebddd1SJeff Kirsher } 15469aebddd1SJeff Kirsher hdr = nonemb_cmd->va; 15479aebddd1SJeff Kirsher 1548106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH, 1549a2cc4e0bSSathya Perla OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, 1550a2cc4e0bSSathya Perla nonemb_cmd); 15519aebddd1SJeff Kirsher 1552ca34fe38SSathya Perla /* version 1 of the cmd is not supported only by BE2 */ 155361000861SAjit Khaparde if (BE2_chip(adapter)) 155461000861SAjit Khaparde hdr->version = 0; 155561000861SAjit Khaparde if (BE3_chip(adapter) || lancer_chip(adapter)) 15569aebddd1SJeff Kirsher hdr->version = 1; 155761000861SAjit Khaparde else 155861000861SAjit Khaparde hdr->version = 2; 15599aebddd1SJeff Kirsher 1560efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 1561efaa408eSSuresh Reddy if (status) 1562efaa408eSSuresh Reddy goto err; 1563efaa408eSSuresh Reddy 15649aebddd1SJeff Kirsher adapter->stats_cmd_sent = true; 15659aebddd1SJeff Kirsher 15669aebddd1SJeff Kirsher err: 15679aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 15689aebddd1SJeff Kirsher return status; 15699aebddd1SJeff Kirsher } 15709aebddd1SJeff Kirsher 15719aebddd1SJeff Kirsher /* Lancer Stats */ 15729aebddd1SJeff Kirsher int lancer_cmd_get_pport_stats(struct be_adapter *adapter, 15739aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 15749aebddd1SJeff Kirsher { 15759aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 15769aebddd1SJeff Kirsher struct lancer_cmd_req_pport_stats *req; 15779aebddd1SJeff Kirsher int status = 0; 15789aebddd1SJeff Kirsher 1579f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS, 1580f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH)) 1581f25b119cSPadmanabh Ratnakar return -EPERM; 1582f25b119cSPadmanabh Ratnakar 15839aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 15849aebddd1SJeff Kirsher 15859aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 15869aebddd1SJeff Kirsher if (!wrb) { 15879aebddd1SJeff Kirsher status = -EBUSY; 15889aebddd1SJeff Kirsher goto err; 15899aebddd1SJeff Kirsher } 15909aebddd1SJeff Kirsher req = nonemb_cmd->va; 15919aebddd1SJeff Kirsher 1592106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1593a2cc4e0bSSathya Perla OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, 1594a2cc4e0bSSathya Perla wrb, nonemb_cmd); 15959aebddd1SJeff Kirsher 1596d51ebd33SPadmanabh Ratnakar req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num); 15979aebddd1SJeff Kirsher req->cmd_params.params.reset_stats = 0; 15989aebddd1SJeff Kirsher 1599efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 1600efaa408eSSuresh Reddy if (status) 1601efaa408eSSuresh Reddy goto err; 1602efaa408eSSuresh Reddy 16039aebddd1SJeff Kirsher adapter->stats_cmd_sent = true; 16049aebddd1SJeff Kirsher 16059aebddd1SJeff Kirsher err: 16069aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 16079aebddd1SJeff Kirsher return status; 16089aebddd1SJeff Kirsher } 16099aebddd1SJeff Kirsher 1610323ff71eSSathya Perla static int be_mac_to_link_speed(int mac_speed) 1611323ff71eSSathya Perla { 1612323ff71eSSathya Perla switch (mac_speed) { 1613323ff71eSSathya Perla case PHY_LINK_SPEED_ZERO: 1614323ff71eSSathya Perla return 0; 1615323ff71eSSathya Perla case PHY_LINK_SPEED_10MBPS: 1616323ff71eSSathya Perla return 10; 1617323ff71eSSathya Perla case PHY_LINK_SPEED_100MBPS: 1618323ff71eSSathya Perla return 100; 1619323ff71eSSathya Perla case PHY_LINK_SPEED_1GBPS: 1620323ff71eSSathya Perla return 1000; 1621323ff71eSSathya Perla case PHY_LINK_SPEED_10GBPS: 1622323ff71eSSathya Perla return 10000; 1623b971f847SVasundhara Volam case PHY_LINK_SPEED_20GBPS: 1624b971f847SVasundhara Volam return 20000; 1625b971f847SVasundhara Volam case PHY_LINK_SPEED_25GBPS: 1626b971f847SVasundhara Volam return 25000; 1627b971f847SVasundhara Volam case PHY_LINK_SPEED_40GBPS: 1628b971f847SVasundhara Volam return 40000; 1629323ff71eSSathya Perla } 1630323ff71eSSathya Perla return 0; 1631323ff71eSSathya Perla } 1632323ff71eSSathya Perla 1633323ff71eSSathya Perla /* Uses synchronous mcc 1634323ff71eSSathya Perla * Returns link_speed in Mbps 1635323ff71eSSathya Perla */ 1636323ff71eSSathya Perla int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, 1637323ff71eSSathya Perla u8 *link_status, u32 dom) 16389aebddd1SJeff Kirsher { 16399aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 16409aebddd1SJeff Kirsher struct be_cmd_req_link_status *req; 16419aebddd1SJeff Kirsher int status; 16429aebddd1SJeff Kirsher 16439aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 16449aebddd1SJeff Kirsher 1645b236916aSAjit Khaparde if (link_status) 1646b236916aSAjit Khaparde *link_status = LINK_DOWN; 1647b236916aSAjit Khaparde 16489aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 16499aebddd1SJeff Kirsher if (!wrb) { 16509aebddd1SJeff Kirsher status = -EBUSY; 16519aebddd1SJeff Kirsher goto err; 16529aebddd1SJeff Kirsher } 16539aebddd1SJeff Kirsher req = embedded_payload(wrb); 16549aebddd1SJeff Kirsher 165557cd80d4SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1656a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, 1657a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 165857cd80d4SPadmanabh Ratnakar 1659ca34fe38SSathya Perla /* version 1 of the cmd is not supported only by BE2 */ 1660ca34fe38SSathya Perla if (!BE2_chip(adapter)) 1661daad6167SPadmanabh Ratnakar req->hdr.version = 1; 1662daad6167SPadmanabh Ratnakar 166357cd80d4SPadmanabh Ratnakar req->hdr.domain = dom; 16649aebddd1SJeff Kirsher 16659aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 16669aebddd1SJeff Kirsher if (!status) { 16679aebddd1SJeff Kirsher struct be_cmd_resp_link_status *resp = embedded_payload(wrb); 166803d28ffeSKalesh AP 1669323ff71eSSathya Perla if (link_speed) { 1670323ff71eSSathya Perla *link_speed = resp->link_speed ? 1671323ff71eSSathya Perla le16_to_cpu(resp->link_speed) * 10 : 1672323ff71eSSathya Perla be_mac_to_link_speed(resp->mac_speed); 1673323ff71eSSathya Perla 1674323ff71eSSathya Perla if (!resp->logical_link_status) 1675323ff71eSSathya Perla *link_speed = 0; 16769aebddd1SJeff Kirsher } 1677b236916aSAjit Khaparde if (link_status) 1678b236916aSAjit Khaparde *link_status = resp->logical_link_status; 16799aebddd1SJeff Kirsher } 16809aebddd1SJeff Kirsher 16819aebddd1SJeff Kirsher err: 16829aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 16839aebddd1SJeff Kirsher return status; 16849aebddd1SJeff Kirsher } 16859aebddd1SJeff Kirsher 16869aebddd1SJeff Kirsher /* Uses synchronous mcc */ 16879aebddd1SJeff Kirsher int be_cmd_get_die_temperature(struct be_adapter *adapter) 16889aebddd1SJeff Kirsher { 16899aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 16909aebddd1SJeff Kirsher struct be_cmd_req_get_cntl_addnl_attribs *req; 1691117affe3SVasundhara Volam int status = 0; 16929aebddd1SJeff Kirsher 16939aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 16949aebddd1SJeff Kirsher 16959aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 16969aebddd1SJeff Kirsher if (!wrb) { 16979aebddd1SJeff Kirsher status = -EBUSY; 16989aebddd1SJeff Kirsher goto err; 16999aebddd1SJeff Kirsher } 17009aebddd1SJeff Kirsher req = embedded_payload(wrb); 17019aebddd1SJeff Kirsher 1702106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1703a2cc4e0bSSathya Perla OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, 1704a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 17059aebddd1SJeff Kirsher 1706efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 17079aebddd1SJeff Kirsher err: 17089aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 17099aebddd1SJeff Kirsher return status; 17109aebddd1SJeff Kirsher } 17119aebddd1SJeff Kirsher 17129aebddd1SJeff Kirsher /* Uses synchronous mcc */ 17139aebddd1SJeff Kirsher int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size) 17149aebddd1SJeff Kirsher { 17159aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 17169aebddd1SJeff Kirsher struct be_cmd_req_get_fat *req; 17179aebddd1SJeff Kirsher int status; 17189aebddd1SJeff Kirsher 17199aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 17209aebddd1SJeff Kirsher 17219aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 17229aebddd1SJeff Kirsher if (!wrb) { 17239aebddd1SJeff Kirsher status = -EBUSY; 17249aebddd1SJeff Kirsher goto err; 17259aebddd1SJeff Kirsher } 17269aebddd1SJeff Kirsher req = embedded_payload(wrb); 17279aebddd1SJeff Kirsher 1728106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1729a2cc4e0bSSathya Perla OPCODE_COMMON_MANAGE_FAT, sizeof(*req), wrb, 1730a2cc4e0bSSathya Perla NULL); 17319aebddd1SJeff Kirsher req->fat_operation = cpu_to_le32(QUERY_FAT); 17329aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 17339aebddd1SJeff Kirsher if (!status) { 17349aebddd1SJeff Kirsher struct be_cmd_resp_get_fat *resp = embedded_payload(wrb); 173503d28ffeSKalesh AP 17369aebddd1SJeff Kirsher if (log_size && resp->log_size) 17379aebddd1SJeff Kirsher *log_size = le32_to_cpu(resp->log_size) - 17389aebddd1SJeff Kirsher sizeof(u32); 17399aebddd1SJeff Kirsher } 17409aebddd1SJeff Kirsher err: 17419aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 17429aebddd1SJeff Kirsher return status; 17439aebddd1SJeff Kirsher } 17449aebddd1SJeff Kirsher 1745c5f156deSVasundhara Volam int be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) 17469aebddd1SJeff Kirsher { 17479aebddd1SJeff Kirsher struct be_dma_mem get_fat_cmd; 17489aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 17499aebddd1SJeff Kirsher struct be_cmd_req_get_fat *req; 17509aebddd1SJeff Kirsher u32 offset = 0, total_size, buf_size, 17519aebddd1SJeff Kirsher log_offset = sizeof(u32), payload_len; 1752c5f156deSVasundhara Volam int status = 0; 17539aebddd1SJeff Kirsher 17549aebddd1SJeff Kirsher if (buf_len == 0) 1755c5f156deSVasundhara Volam return -EIO; 17569aebddd1SJeff Kirsher 17579aebddd1SJeff Kirsher total_size = buf_len; 17589aebddd1SJeff Kirsher 17599aebddd1SJeff Kirsher get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024; 1760e51000dbSSriharsha Basavapatna get_fat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 17619aebddd1SJeff Kirsher get_fat_cmd.size, 1762e51000dbSSriharsha Basavapatna &get_fat_cmd.dma, GFP_ATOMIC); 17639aebddd1SJeff Kirsher if (!get_fat_cmd.va) { 17649aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, 1765cd3307aaSKalesh AP "Memory allocation failure while reading FAT data\n"); 1766c5f156deSVasundhara Volam return -ENOMEM; 17679aebddd1SJeff Kirsher } 17689aebddd1SJeff Kirsher 17699aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 17709aebddd1SJeff Kirsher 17719aebddd1SJeff Kirsher while (total_size) { 17729aebddd1SJeff Kirsher buf_size = min(total_size, (u32)60*1024); 17739aebddd1SJeff Kirsher total_size -= buf_size; 17749aebddd1SJeff Kirsher 17759aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 17769aebddd1SJeff Kirsher if (!wrb) { 17779aebddd1SJeff Kirsher status = -EBUSY; 17789aebddd1SJeff Kirsher goto err; 17799aebddd1SJeff Kirsher } 17809aebddd1SJeff Kirsher req = get_fat_cmd.va; 17819aebddd1SJeff Kirsher 17829aebddd1SJeff Kirsher payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size; 1783106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1784a2cc4e0bSSathya Perla OPCODE_COMMON_MANAGE_FAT, payload_len, 1785a2cc4e0bSSathya Perla wrb, &get_fat_cmd); 17869aebddd1SJeff Kirsher 17879aebddd1SJeff Kirsher req->fat_operation = cpu_to_le32(RETRIEVE_FAT); 17889aebddd1SJeff Kirsher req->read_log_offset = cpu_to_le32(log_offset); 17899aebddd1SJeff Kirsher req->read_log_length = cpu_to_le32(buf_size); 17909aebddd1SJeff Kirsher req->data_buffer_size = cpu_to_le32(buf_size); 17919aebddd1SJeff Kirsher 17929aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 17939aebddd1SJeff Kirsher if (!status) { 17949aebddd1SJeff Kirsher struct be_cmd_resp_get_fat *resp = get_fat_cmd.va; 179503d28ffeSKalesh AP 17969aebddd1SJeff Kirsher memcpy(buf + offset, 17979aebddd1SJeff Kirsher resp->data_buffer, 179892aa9214SSomnath Kotur le32_to_cpu(resp->read_log_length)); 17999aebddd1SJeff Kirsher } else { 18009aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n"); 18019aebddd1SJeff Kirsher goto err; 18029aebddd1SJeff Kirsher } 18039aebddd1SJeff Kirsher offset += buf_size; 18049aebddd1SJeff Kirsher log_offset += buf_size; 18059aebddd1SJeff Kirsher } 18069aebddd1SJeff Kirsher err: 1807e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, get_fat_cmd.size, 1808a2cc4e0bSSathya Perla get_fat_cmd.va, get_fat_cmd.dma); 18099aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 1810c5f156deSVasundhara Volam return status; 18119aebddd1SJeff Kirsher } 18129aebddd1SJeff Kirsher 181304b71175SSathya Perla /* Uses synchronous mcc */ 1814e97e3cdaSKalesh AP int be_cmd_get_fw_ver(struct be_adapter *adapter) 18159aebddd1SJeff Kirsher { 18169aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 18179aebddd1SJeff Kirsher struct be_cmd_req_get_fw_version *req; 18189aebddd1SJeff Kirsher int status; 18199aebddd1SJeff Kirsher 182004b71175SSathya Perla spin_lock_bh(&adapter->mcc_lock); 18219aebddd1SJeff Kirsher 182204b71175SSathya Perla wrb = wrb_from_mccq(adapter); 182304b71175SSathya Perla if (!wrb) { 182404b71175SSathya Perla status = -EBUSY; 182504b71175SSathya Perla goto err; 182604b71175SSathya Perla } 182704b71175SSathya Perla 18289aebddd1SJeff Kirsher req = embedded_payload(wrb); 18299aebddd1SJeff Kirsher 1830106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1831a2cc4e0bSSathya Perla OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb, 1832a2cc4e0bSSathya Perla NULL); 183304b71175SSathya Perla status = be_mcc_notify_wait(adapter); 18349aebddd1SJeff Kirsher if (!status) { 18359aebddd1SJeff Kirsher struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb); 1836acbafeb1SSathya Perla 1837242eb470SVasundhara Volam strlcpy(adapter->fw_ver, resp->firmware_version_string, 1838242eb470SVasundhara Volam sizeof(adapter->fw_ver)); 1839242eb470SVasundhara Volam strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string, 1840242eb470SVasundhara Volam sizeof(adapter->fw_on_flash)); 18419aebddd1SJeff Kirsher } 184204b71175SSathya Perla err: 184304b71175SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 18449aebddd1SJeff Kirsher return status; 18459aebddd1SJeff Kirsher } 18469aebddd1SJeff Kirsher 18479aebddd1SJeff Kirsher /* set the EQ delay interval of an EQ to specified value 18489aebddd1SJeff Kirsher * Uses async mcc 18499aebddd1SJeff Kirsher */ 1850b502ae8dSKalesh AP static int __be_cmd_modify_eqd(struct be_adapter *adapter, 1851b502ae8dSKalesh AP struct be_set_eqd *set_eqd, int num) 18529aebddd1SJeff Kirsher { 18539aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 18549aebddd1SJeff Kirsher struct be_cmd_req_modify_eq_delay *req; 18552632bafdSSathya Perla int status = 0, i; 18569aebddd1SJeff Kirsher 18579aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 18589aebddd1SJeff Kirsher 18599aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 18609aebddd1SJeff Kirsher if (!wrb) { 18619aebddd1SJeff Kirsher status = -EBUSY; 18629aebddd1SJeff Kirsher goto err; 18639aebddd1SJeff Kirsher } 18649aebddd1SJeff Kirsher req = embedded_payload(wrb); 18659aebddd1SJeff Kirsher 1866106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1867a2cc4e0bSSathya Perla OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb, 1868a2cc4e0bSSathya Perla NULL); 18699aebddd1SJeff Kirsher 18702632bafdSSathya Perla req->num_eq = cpu_to_le32(num); 18712632bafdSSathya Perla for (i = 0; i < num; i++) { 18722632bafdSSathya Perla req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id); 18732632bafdSSathya Perla req->set_eqd[i].phase = 0; 18742632bafdSSathya Perla req->set_eqd[i].delay_multiplier = 18752632bafdSSathya Perla cpu_to_le32(set_eqd[i].delay_multiplier); 18762632bafdSSathya Perla } 18779aebddd1SJeff Kirsher 1878efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 18799aebddd1SJeff Kirsher err: 18809aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 18819aebddd1SJeff Kirsher return status; 18829aebddd1SJeff Kirsher } 18839aebddd1SJeff Kirsher 188493676703SKalesh AP int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd, 188593676703SKalesh AP int num) 188693676703SKalesh AP { 188793676703SKalesh AP int num_eqs, i = 0; 188893676703SKalesh AP 188993676703SKalesh AP while (num) { 189093676703SKalesh AP num_eqs = min(num, 8); 189193676703SKalesh AP __be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs); 189293676703SKalesh AP i += num_eqs; 189393676703SKalesh AP num -= num_eqs; 189493676703SKalesh AP } 189593676703SKalesh AP 189693676703SKalesh AP return 0; 189793676703SKalesh AP } 189893676703SKalesh AP 18999aebddd1SJeff Kirsher /* Uses sycnhronous mcc */ 19009aebddd1SJeff Kirsher int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, 1901435452aaSVasundhara Volam u32 num, u32 domain) 19029aebddd1SJeff Kirsher { 19039aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19049aebddd1SJeff Kirsher struct be_cmd_req_vlan_config *req; 19059aebddd1SJeff Kirsher int status; 19069aebddd1SJeff Kirsher 19079aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 19089aebddd1SJeff Kirsher 19099aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 19109aebddd1SJeff Kirsher if (!wrb) { 19119aebddd1SJeff Kirsher status = -EBUSY; 19129aebddd1SJeff Kirsher goto err; 19139aebddd1SJeff Kirsher } 19149aebddd1SJeff Kirsher req = embedded_payload(wrb); 19159aebddd1SJeff Kirsher 1916106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1917a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req), 1918a2cc4e0bSSathya Perla wrb, NULL); 1919435452aaSVasundhara Volam req->hdr.domain = domain; 19209aebddd1SJeff Kirsher 19219aebddd1SJeff Kirsher req->interface_id = if_id; 1922012bd387SAjit Khaparde req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0; 19239aebddd1SJeff Kirsher req->num_vlan = num; 19249aebddd1SJeff Kirsher memcpy(req->normal_vlan, vtag_array, 19259aebddd1SJeff Kirsher req->num_vlan * sizeof(vtag_array[0])); 19269aebddd1SJeff Kirsher 19279aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 19289aebddd1SJeff Kirsher err: 19299aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 19309aebddd1SJeff Kirsher return status; 19319aebddd1SJeff Kirsher } 19329aebddd1SJeff Kirsher 1933ac34b743SSathya Perla static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) 19349aebddd1SJeff Kirsher { 19359aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19369aebddd1SJeff Kirsher struct be_dma_mem *mem = &adapter->rx_filter; 19379aebddd1SJeff Kirsher struct be_cmd_req_rx_filter *req = mem->va; 19389aebddd1SJeff Kirsher int status; 19399aebddd1SJeff Kirsher 19409aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 19419aebddd1SJeff Kirsher 19429aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 19439aebddd1SJeff Kirsher if (!wrb) { 19449aebddd1SJeff Kirsher status = -EBUSY; 19459aebddd1SJeff Kirsher goto err; 19469aebddd1SJeff Kirsher } 19479aebddd1SJeff Kirsher memset(req, 0, sizeof(*req)); 1948106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1949106df1e3SSomnath Kotur OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req), 1950106df1e3SSomnath Kotur wrb, mem); 19519aebddd1SJeff Kirsher 19529aebddd1SJeff Kirsher req->if_id = cpu_to_le32(adapter->if_handle); 1953ac34b743SSathya Perla req->if_flags_mask = cpu_to_le32(flags); 1954ac34b743SSathya Perla req->if_flags = (value == ON) ? req->if_flags_mask : 0; 1955d9d604f8SAjit Khaparde 1956ac34b743SSathya Perla if (flags & BE_IF_FLAGS_MULTICAST) { 19579aebddd1SJeff Kirsher struct netdev_hw_addr *ha; 19589aebddd1SJeff Kirsher int i = 0; 19599aebddd1SJeff Kirsher 19601610c79fSPadmanabh Ratnakar /* Reset mcast promisc mode if already set by setting mask 19611610c79fSPadmanabh Ratnakar * and not setting flags field 19621610c79fSPadmanabh Ratnakar */ 19631610c79fSPadmanabh Ratnakar req->if_flags_mask |= 1964abb93951SPadmanabh Ratnakar cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS & 196592bf14abSSathya Perla be_if_cap_flags(adapter)); 1966016f97b1SPadmanabh Ratnakar req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev)); 19679aebddd1SJeff Kirsher netdev_for_each_mc_addr(ha, adapter->netdev) 19689aebddd1SJeff Kirsher memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN); 19699aebddd1SJeff Kirsher } 19709aebddd1SJeff Kirsher 19718af65c2fSSuresh Reddy status = be_mcc_notify(adapter); 19729aebddd1SJeff Kirsher err: 19739aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 19749aebddd1SJeff Kirsher return status; 19759aebddd1SJeff Kirsher } 19769aebddd1SJeff Kirsher 1977ac34b743SSathya Perla int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) 1978ac34b743SSathya Perla { 1979ac34b743SSathya Perla struct device *dev = &adapter->pdev->dev; 1980ac34b743SSathya Perla 1981ac34b743SSathya Perla if ((flags & be_if_cap_flags(adapter)) != flags) { 1982ac34b743SSathya Perla dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags); 1983ac34b743SSathya Perla dev_warn(dev, "Interface is capable of 0x%x flags only\n", 1984ac34b743SSathya Perla be_if_cap_flags(adapter)); 1985ac34b743SSathya Perla } 1986ac34b743SSathya Perla flags &= be_if_cap_flags(adapter); 1987ac34b743SSathya Perla 1988ac34b743SSathya Perla return __be_cmd_rx_filter(adapter, flags, value); 1989ac34b743SSathya Perla } 1990ac34b743SSathya Perla 19919aebddd1SJeff Kirsher /* Uses synchrounous mcc */ 19929aebddd1SJeff Kirsher int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) 19939aebddd1SJeff Kirsher { 19949aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19959aebddd1SJeff Kirsher struct be_cmd_req_set_flow_control *req; 19969aebddd1SJeff Kirsher int status; 19979aebddd1SJeff Kirsher 1998f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL, 1999f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 2000f25b119cSPadmanabh Ratnakar return -EPERM; 2001f25b119cSPadmanabh Ratnakar 20029aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 20039aebddd1SJeff Kirsher 20049aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 20059aebddd1SJeff Kirsher if (!wrb) { 20069aebddd1SJeff Kirsher status = -EBUSY; 20079aebddd1SJeff Kirsher goto err; 20089aebddd1SJeff Kirsher } 20099aebddd1SJeff Kirsher req = embedded_payload(wrb); 20109aebddd1SJeff Kirsher 2011106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2012a2cc4e0bSSathya Perla OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req), 2013a2cc4e0bSSathya Perla wrb, NULL); 20149aebddd1SJeff Kirsher 2015b29812c1SSuresh Reddy req->hdr.version = 1; 20169aebddd1SJeff Kirsher req->tx_flow_control = cpu_to_le16((u16)tx_fc); 20179aebddd1SJeff Kirsher req->rx_flow_control = cpu_to_le16((u16)rx_fc); 20189aebddd1SJeff Kirsher 20199aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 20209aebddd1SJeff Kirsher 20219aebddd1SJeff Kirsher err: 20229aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 2023b29812c1SSuresh Reddy 2024b29812c1SSuresh Reddy if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED) 2025b29812c1SSuresh Reddy return -EOPNOTSUPP; 2026b29812c1SSuresh Reddy 20279aebddd1SJeff Kirsher return status; 20289aebddd1SJeff Kirsher } 20299aebddd1SJeff Kirsher 20309aebddd1SJeff Kirsher /* Uses sycn mcc */ 20319aebddd1SJeff Kirsher int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) 20329aebddd1SJeff Kirsher { 20339aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20349aebddd1SJeff Kirsher struct be_cmd_req_get_flow_control *req; 20359aebddd1SJeff Kirsher int status; 20369aebddd1SJeff Kirsher 2037f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL, 2038f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 2039f25b119cSPadmanabh Ratnakar return -EPERM; 2040f25b119cSPadmanabh Ratnakar 20419aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 20429aebddd1SJeff Kirsher 20439aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 20449aebddd1SJeff Kirsher if (!wrb) { 20459aebddd1SJeff Kirsher status = -EBUSY; 20469aebddd1SJeff Kirsher goto err; 20479aebddd1SJeff Kirsher } 20489aebddd1SJeff Kirsher req = embedded_payload(wrb); 20499aebddd1SJeff Kirsher 2050106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2051a2cc4e0bSSathya Perla OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req), 2052a2cc4e0bSSathya Perla wrb, NULL); 20539aebddd1SJeff Kirsher 20549aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 20559aebddd1SJeff Kirsher if (!status) { 20569aebddd1SJeff Kirsher struct be_cmd_resp_get_flow_control *resp = 20579aebddd1SJeff Kirsher embedded_payload(wrb); 205803d28ffeSKalesh AP 20599aebddd1SJeff Kirsher *tx_fc = le16_to_cpu(resp->tx_flow_control); 20609aebddd1SJeff Kirsher *rx_fc = le16_to_cpu(resp->rx_flow_control); 20619aebddd1SJeff Kirsher } 20629aebddd1SJeff Kirsher 20639aebddd1SJeff Kirsher err: 20649aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 20659aebddd1SJeff Kirsher return status; 20669aebddd1SJeff Kirsher } 20679aebddd1SJeff Kirsher 20689aebddd1SJeff Kirsher /* Uses mbox */ 2069e97e3cdaSKalesh AP int be_cmd_query_fw_cfg(struct be_adapter *adapter) 20709aebddd1SJeff Kirsher { 20719aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20729aebddd1SJeff Kirsher struct be_cmd_req_query_fw_cfg *req; 20739aebddd1SJeff Kirsher int status; 20749aebddd1SJeff Kirsher 20759aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 20769aebddd1SJeff Kirsher return -1; 20779aebddd1SJeff Kirsher 20789aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 20799aebddd1SJeff Kirsher req = embedded_payload(wrb); 20809aebddd1SJeff Kirsher 2081106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2082a2cc4e0bSSathya Perla OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, 2083a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 20849aebddd1SJeff Kirsher 20859aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 20869aebddd1SJeff Kirsher if (!status) { 20879aebddd1SJeff Kirsher struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); 208803d28ffeSKalesh AP 2089e97e3cdaSKalesh AP adapter->port_num = le32_to_cpu(resp->phys_port); 2090e97e3cdaSKalesh AP adapter->function_mode = le32_to_cpu(resp->function_mode); 2091e97e3cdaSKalesh AP adapter->function_caps = le32_to_cpu(resp->function_caps); 2092e97e3cdaSKalesh AP adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF; 2093acbafeb1SSathya Perla dev_info(&adapter->pdev->dev, 2094acbafeb1SSathya Perla "FW config: function_mode=0x%x, function_caps=0x%x\n", 2095acbafeb1SSathya Perla adapter->function_mode, adapter->function_caps); 20969aebddd1SJeff Kirsher } 20979aebddd1SJeff Kirsher 20989aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 20999aebddd1SJeff Kirsher return status; 21009aebddd1SJeff Kirsher } 21019aebddd1SJeff Kirsher 21029aebddd1SJeff Kirsher /* Uses mbox */ 21039aebddd1SJeff Kirsher int be_cmd_reset_function(struct be_adapter *adapter) 21049aebddd1SJeff Kirsher { 21059aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21069aebddd1SJeff Kirsher struct be_cmd_req_hdr *req; 21079aebddd1SJeff Kirsher int status; 21089aebddd1SJeff Kirsher 2109bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) { 2110bf99e50dSPadmanabh Ratnakar iowrite32(SLI_PORT_CONTROL_IP_MASK, 2111bf99e50dSPadmanabh Ratnakar adapter->db + SLIPORT_CONTROL_OFFSET); 21129fa465c0SSathya Perla status = lancer_wait_ready(adapter); 21139fa465c0SSathya Perla if (status) 2114bf99e50dSPadmanabh Ratnakar dev_err(&adapter->pdev->dev, 2115bf99e50dSPadmanabh Ratnakar "Adapter in non recoverable error\n"); 2116bf99e50dSPadmanabh Ratnakar return status; 2117bf99e50dSPadmanabh Ratnakar } 2118bf99e50dSPadmanabh Ratnakar 21199aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 21209aebddd1SJeff Kirsher return -1; 21219aebddd1SJeff Kirsher 21229aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 21239aebddd1SJeff Kirsher req = embedded_payload(wrb); 21249aebddd1SJeff Kirsher 2125106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON, 2126a2cc4e0bSSathya Perla OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb, 2127a2cc4e0bSSathya Perla NULL); 21289aebddd1SJeff Kirsher 21299aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 21309aebddd1SJeff Kirsher 21319aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 21329aebddd1SJeff Kirsher return status; 21339aebddd1SJeff Kirsher } 21349aebddd1SJeff Kirsher 2135594ad54aSSuresh Reddy int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, 213633cb0fa7SBen Hutchings u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey) 21379aebddd1SJeff Kirsher { 21389aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21399aebddd1SJeff Kirsher struct be_cmd_req_rss_config *req; 21409aebddd1SJeff Kirsher int status; 21419aebddd1SJeff Kirsher 2142da1388d6SVasundhara Volam if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS)) 2143da1388d6SVasundhara Volam return 0; 2144da1388d6SVasundhara Volam 2145b51aa367SKalesh AP spin_lock_bh(&adapter->mcc_lock); 21469aebddd1SJeff Kirsher 2147b51aa367SKalesh AP wrb = wrb_from_mccq(adapter); 2148b51aa367SKalesh AP if (!wrb) { 2149b51aa367SKalesh AP status = -EBUSY; 2150b51aa367SKalesh AP goto err; 2151b51aa367SKalesh AP } 21529aebddd1SJeff Kirsher req = embedded_payload(wrb); 21539aebddd1SJeff Kirsher 2154106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 2155106df1e3SSomnath Kotur OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL); 21569aebddd1SJeff Kirsher 21579aebddd1SJeff Kirsher req->if_id = cpu_to_le32(adapter->if_handle); 2158594ad54aSSuresh Reddy req->enable_rss = cpu_to_le16(rss_hash_opts); 21599aebddd1SJeff Kirsher req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1); 2160594ad54aSSuresh Reddy 2161b51aa367SKalesh AP if (!BEx_chip(adapter)) 2162594ad54aSSuresh Reddy req->hdr.version = 1; 2163594ad54aSSuresh Reddy 21649aebddd1SJeff Kirsher memcpy(req->cpu_table, rsstable, table_size); 2165e2557877SVenkata Duvvuru memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN); 21669aebddd1SJeff Kirsher be_dws_cpu_to_le(req->hash, sizeof(req->hash)); 21679aebddd1SJeff Kirsher 2168b51aa367SKalesh AP status = be_mcc_notify_wait(adapter); 2169b51aa367SKalesh AP err: 2170b51aa367SKalesh AP spin_unlock_bh(&adapter->mcc_lock); 21719aebddd1SJeff Kirsher return status; 21729aebddd1SJeff Kirsher } 21739aebddd1SJeff Kirsher 21749aebddd1SJeff Kirsher /* Uses sync mcc */ 21759aebddd1SJeff Kirsher int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, 21769aebddd1SJeff Kirsher u8 bcn, u8 sts, u8 state) 21779aebddd1SJeff Kirsher { 21789aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21799aebddd1SJeff Kirsher struct be_cmd_req_enable_disable_beacon *req; 21809aebddd1SJeff Kirsher int status; 21819aebddd1SJeff Kirsher 21829aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 21839aebddd1SJeff Kirsher 21849aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 21859aebddd1SJeff Kirsher if (!wrb) { 21869aebddd1SJeff Kirsher status = -EBUSY; 21879aebddd1SJeff Kirsher goto err; 21889aebddd1SJeff Kirsher } 21899aebddd1SJeff Kirsher req = embedded_payload(wrb); 21909aebddd1SJeff Kirsher 2191106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2192a2cc4e0bSSathya Perla OPCODE_COMMON_ENABLE_DISABLE_BEACON, 2193a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 21949aebddd1SJeff Kirsher 21959aebddd1SJeff Kirsher req->port_num = port_num; 21969aebddd1SJeff Kirsher req->beacon_state = state; 21979aebddd1SJeff Kirsher req->beacon_duration = bcn; 21989aebddd1SJeff Kirsher req->status_duration = sts; 21999aebddd1SJeff Kirsher 22009aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 22019aebddd1SJeff Kirsher 22029aebddd1SJeff Kirsher err: 22039aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 22049aebddd1SJeff Kirsher return status; 22059aebddd1SJeff Kirsher } 22069aebddd1SJeff Kirsher 22079aebddd1SJeff Kirsher /* Uses sync mcc */ 22089aebddd1SJeff Kirsher int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) 22099aebddd1SJeff Kirsher { 22109aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 22119aebddd1SJeff Kirsher struct be_cmd_req_get_beacon_state *req; 22129aebddd1SJeff Kirsher int status; 22139aebddd1SJeff Kirsher 22149aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 22159aebddd1SJeff Kirsher 22169aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 22179aebddd1SJeff Kirsher if (!wrb) { 22189aebddd1SJeff Kirsher status = -EBUSY; 22199aebddd1SJeff Kirsher goto err; 22209aebddd1SJeff Kirsher } 22219aebddd1SJeff Kirsher req = embedded_payload(wrb); 22229aebddd1SJeff Kirsher 2223106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2224a2cc4e0bSSathya Perla OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req), 2225a2cc4e0bSSathya Perla wrb, NULL); 22269aebddd1SJeff Kirsher 22279aebddd1SJeff Kirsher req->port_num = port_num; 22289aebddd1SJeff Kirsher 22299aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 22309aebddd1SJeff Kirsher if (!status) { 22319aebddd1SJeff Kirsher struct be_cmd_resp_get_beacon_state *resp = 22329aebddd1SJeff Kirsher embedded_payload(wrb); 223303d28ffeSKalesh AP 22349aebddd1SJeff Kirsher *state = resp->beacon_state; 22359aebddd1SJeff Kirsher } 22369aebddd1SJeff Kirsher 22379aebddd1SJeff Kirsher err: 22389aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 22399aebddd1SJeff Kirsher return status; 22409aebddd1SJeff Kirsher } 22419aebddd1SJeff Kirsher 2242e36edd9dSMark Leonard /* Uses sync mcc */ 2243e36edd9dSMark Leonard int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, 2244e36edd9dSMark Leonard u8 page_num, u8 *data) 2245e36edd9dSMark Leonard { 2246e36edd9dSMark Leonard struct be_dma_mem cmd; 2247e36edd9dSMark Leonard struct be_mcc_wrb *wrb; 2248e36edd9dSMark Leonard struct be_cmd_req_port_type *req; 2249e36edd9dSMark Leonard int status; 2250e36edd9dSMark Leonard 2251e36edd9dSMark Leonard if (page_num > TR_PAGE_A2) 2252e36edd9dSMark Leonard return -EINVAL; 2253e36edd9dSMark Leonard 2254e36edd9dSMark Leonard cmd.size = sizeof(struct be_cmd_resp_port_type); 2255e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 2256e51000dbSSriharsha Basavapatna GFP_ATOMIC); 2257e36edd9dSMark Leonard if (!cmd.va) { 2258e36edd9dSMark Leonard dev_err(&adapter->pdev->dev, "Memory allocation failed\n"); 2259e36edd9dSMark Leonard return -ENOMEM; 2260e36edd9dSMark Leonard } 2261e36edd9dSMark Leonard 2262e36edd9dSMark Leonard spin_lock_bh(&adapter->mcc_lock); 2263e36edd9dSMark Leonard 2264e36edd9dSMark Leonard wrb = wrb_from_mccq(adapter); 2265e36edd9dSMark Leonard if (!wrb) { 2266e36edd9dSMark Leonard status = -EBUSY; 2267e36edd9dSMark Leonard goto err; 2268e36edd9dSMark Leonard } 2269e36edd9dSMark Leonard req = cmd.va; 2270e36edd9dSMark Leonard 2271e36edd9dSMark Leonard be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2272e36edd9dSMark Leonard OPCODE_COMMON_READ_TRANSRECV_DATA, 2273e36edd9dSMark Leonard cmd.size, wrb, &cmd); 2274e36edd9dSMark Leonard 2275e36edd9dSMark Leonard req->port = cpu_to_le32(adapter->hba_port_num); 2276e36edd9dSMark Leonard req->page_num = cpu_to_le32(page_num); 2277e36edd9dSMark Leonard status = be_mcc_notify_wait(adapter); 2278e36edd9dSMark Leonard if (!status) { 2279e36edd9dSMark Leonard struct be_cmd_resp_port_type *resp = cmd.va; 2280e36edd9dSMark Leonard 2281e36edd9dSMark Leonard memcpy(data, resp->page_data, PAGE_DATA_LEN); 2282e36edd9dSMark Leonard } 2283e36edd9dSMark Leonard err: 2284e36edd9dSMark Leonard spin_unlock_bh(&adapter->mcc_lock); 2285e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); 2286e36edd9dSMark Leonard return status; 2287e36edd9dSMark Leonard } 2288e36edd9dSMark Leonard 22899aebddd1SJeff Kirsher int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, 2290f67ef7baSPadmanabh Ratnakar u32 data_size, u32 data_offset, 2291f67ef7baSPadmanabh Ratnakar const char *obj_name, u32 *data_written, 2292f67ef7baSPadmanabh Ratnakar u8 *change_status, u8 *addn_status) 22939aebddd1SJeff Kirsher { 22949aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 22959aebddd1SJeff Kirsher struct lancer_cmd_req_write_object *req; 22969aebddd1SJeff Kirsher struct lancer_cmd_resp_write_object *resp; 22979aebddd1SJeff Kirsher void *ctxt = NULL; 22989aebddd1SJeff Kirsher int status; 22999aebddd1SJeff Kirsher 23009aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 23019aebddd1SJeff Kirsher adapter->flash_status = 0; 23029aebddd1SJeff Kirsher 23039aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 23049aebddd1SJeff Kirsher if (!wrb) { 23059aebddd1SJeff Kirsher status = -EBUSY; 23069aebddd1SJeff Kirsher goto err_unlock; 23079aebddd1SJeff Kirsher } 23089aebddd1SJeff Kirsher 23099aebddd1SJeff Kirsher req = embedded_payload(wrb); 23109aebddd1SJeff Kirsher 2311106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 23129aebddd1SJeff Kirsher OPCODE_COMMON_WRITE_OBJECT, 2313106df1e3SSomnath Kotur sizeof(struct lancer_cmd_req_write_object), wrb, 2314106df1e3SSomnath Kotur NULL); 23159aebddd1SJeff Kirsher 23169aebddd1SJeff Kirsher ctxt = &req->context; 23179aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 23189aebddd1SJeff Kirsher write_length, ctxt, data_size); 23199aebddd1SJeff Kirsher 23209aebddd1SJeff Kirsher if (data_size == 0) 23219aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 23229aebddd1SJeff Kirsher eof, ctxt, 1); 23239aebddd1SJeff Kirsher else 23249aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 23259aebddd1SJeff Kirsher eof, ctxt, 0); 23269aebddd1SJeff Kirsher 23279aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 23289aebddd1SJeff Kirsher req->write_offset = cpu_to_le32(data_offset); 2329242eb470SVasundhara Volam strlcpy(req->object_name, obj_name, sizeof(req->object_name)); 23309aebddd1SJeff Kirsher req->descriptor_count = cpu_to_le32(1); 23319aebddd1SJeff Kirsher req->buf_len = cpu_to_le32(data_size); 23329aebddd1SJeff Kirsher req->addr_low = cpu_to_le32((cmd->dma + 23339aebddd1SJeff Kirsher sizeof(struct lancer_cmd_req_write_object)) 23349aebddd1SJeff Kirsher & 0xFFFFFFFF); 23359aebddd1SJeff Kirsher req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma + 23369aebddd1SJeff Kirsher sizeof(struct lancer_cmd_req_write_object))); 23379aebddd1SJeff Kirsher 2338efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 2339efaa408eSSuresh Reddy if (status) 2340efaa408eSSuresh Reddy goto err_unlock; 2341efaa408eSSuresh Reddy 23429aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 23439aebddd1SJeff Kirsher 23445eeff635SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 2345701962d0SSomnath Kotur msecs_to_jiffies(60000))) 2346fd45160cSKalesh AP status = -ETIMEDOUT; 23479aebddd1SJeff Kirsher else 23489aebddd1SJeff Kirsher status = adapter->flash_status; 23499aebddd1SJeff Kirsher 23509aebddd1SJeff Kirsher resp = embedded_payload(wrb); 2351f67ef7baSPadmanabh Ratnakar if (!status) { 23529aebddd1SJeff Kirsher *data_written = le32_to_cpu(resp->actual_write_len); 2353f67ef7baSPadmanabh Ratnakar *change_status = resp->change_status; 2354f67ef7baSPadmanabh Ratnakar } else { 23559aebddd1SJeff Kirsher *addn_status = resp->additional_status; 2356f67ef7baSPadmanabh Ratnakar } 23579aebddd1SJeff Kirsher 23589aebddd1SJeff Kirsher return status; 23599aebddd1SJeff Kirsher 23609aebddd1SJeff Kirsher err_unlock: 23619aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 23629aebddd1SJeff Kirsher return status; 23639aebddd1SJeff Kirsher } 23649aebddd1SJeff Kirsher 23656809cee0SRavikumar Nelavelli int be_cmd_query_cable_type(struct be_adapter *adapter) 23666809cee0SRavikumar Nelavelli { 23676809cee0SRavikumar Nelavelli u8 page_data[PAGE_DATA_LEN]; 23686809cee0SRavikumar Nelavelli int status; 23696809cee0SRavikumar Nelavelli 23706809cee0SRavikumar Nelavelli status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, 23716809cee0SRavikumar Nelavelli page_data); 23726809cee0SRavikumar Nelavelli if (!status) { 23736809cee0SRavikumar Nelavelli switch (adapter->phy.interface_type) { 23746809cee0SRavikumar Nelavelli case PHY_TYPE_QSFP: 23756809cee0SRavikumar Nelavelli adapter->phy.cable_type = 23766809cee0SRavikumar Nelavelli page_data[QSFP_PLUS_CABLE_TYPE_OFFSET]; 23776809cee0SRavikumar Nelavelli break; 23786809cee0SRavikumar Nelavelli case PHY_TYPE_SFP_PLUS_10GB: 23796809cee0SRavikumar Nelavelli adapter->phy.cable_type = 23806809cee0SRavikumar Nelavelli page_data[SFP_PLUS_CABLE_TYPE_OFFSET]; 23816809cee0SRavikumar Nelavelli break; 23826809cee0SRavikumar Nelavelli default: 23836809cee0SRavikumar Nelavelli adapter->phy.cable_type = 0; 23846809cee0SRavikumar Nelavelli break; 23856809cee0SRavikumar Nelavelli } 23866809cee0SRavikumar Nelavelli } 23876809cee0SRavikumar Nelavelli return status; 23886809cee0SRavikumar Nelavelli } 23896809cee0SRavikumar Nelavelli 239021252377SVasundhara Volam int be_cmd_query_sfp_info(struct be_adapter *adapter) 239121252377SVasundhara Volam { 239221252377SVasundhara Volam u8 page_data[PAGE_DATA_LEN]; 239321252377SVasundhara Volam int status; 239421252377SVasundhara Volam 239521252377SVasundhara Volam status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, 239621252377SVasundhara Volam page_data); 239721252377SVasundhara Volam if (!status) { 239821252377SVasundhara Volam strlcpy(adapter->phy.vendor_name, page_data + 239921252377SVasundhara Volam SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1); 240021252377SVasundhara Volam strlcpy(adapter->phy.vendor_pn, 240121252377SVasundhara Volam page_data + SFP_VENDOR_PN_OFFSET, 240221252377SVasundhara Volam SFP_VENDOR_NAME_LEN - 1); 240321252377SVasundhara Volam } 240421252377SVasundhara Volam 240521252377SVasundhara Volam return status; 240621252377SVasundhara Volam } 240721252377SVasundhara Volam 2408f0613380SKalesh AP int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name) 2409f0613380SKalesh AP { 2410f0613380SKalesh AP struct lancer_cmd_req_delete_object *req; 2411f0613380SKalesh AP struct be_mcc_wrb *wrb; 2412f0613380SKalesh AP int status; 2413f0613380SKalesh AP 2414f0613380SKalesh AP spin_lock_bh(&adapter->mcc_lock); 2415f0613380SKalesh AP 2416f0613380SKalesh AP wrb = wrb_from_mccq(adapter); 2417f0613380SKalesh AP if (!wrb) { 2418f0613380SKalesh AP status = -EBUSY; 2419f0613380SKalesh AP goto err; 2420f0613380SKalesh AP } 2421f0613380SKalesh AP 2422f0613380SKalesh AP req = embedded_payload(wrb); 2423f0613380SKalesh AP 2424f0613380SKalesh AP be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2425f0613380SKalesh AP OPCODE_COMMON_DELETE_OBJECT, 2426f0613380SKalesh AP sizeof(*req), wrb, NULL); 2427f0613380SKalesh AP 2428242eb470SVasundhara Volam strlcpy(req->object_name, obj_name, sizeof(req->object_name)); 2429f0613380SKalesh AP 2430f0613380SKalesh AP status = be_mcc_notify_wait(adapter); 2431f0613380SKalesh AP err: 2432f0613380SKalesh AP spin_unlock_bh(&adapter->mcc_lock); 2433f0613380SKalesh AP return status; 2434f0613380SKalesh AP } 2435f0613380SKalesh AP 2436de49bd5aSPadmanabh Ratnakar int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, 2437de49bd5aSPadmanabh Ratnakar u32 data_size, u32 data_offset, const char *obj_name, 2438de49bd5aSPadmanabh Ratnakar u32 *data_read, u32 *eof, u8 *addn_status) 2439de49bd5aSPadmanabh Ratnakar { 2440de49bd5aSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 2441de49bd5aSPadmanabh Ratnakar struct lancer_cmd_req_read_object *req; 2442de49bd5aSPadmanabh Ratnakar struct lancer_cmd_resp_read_object *resp; 2443de49bd5aSPadmanabh Ratnakar int status; 2444de49bd5aSPadmanabh Ratnakar 2445de49bd5aSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 2446de49bd5aSPadmanabh Ratnakar 2447de49bd5aSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 2448de49bd5aSPadmanabh Ratnakar if (!wrb) { 2449de49bd5aSPadmanabh Ratnakar status = -EBUSY; 2450de49bd5aSPadmanabh Ratnakar goto err_unlock; 2451de49bd5aSPadmanabh Ratnakar } 2452de49bd5aSPadmanabh Ratnakar 2453de49bd5aSPadmanabh Ratnakar req = embedded_payload(wrb); 2454de49bd5aSPadmanabh Ratnakar 2455de49bd5aSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2456de49bd5aSPadmanabh Ratnakar OPCODE_COMMON_READ_OBJECT, 2457de49bd5aSPadmanabh Ratnakar sizeof(struct lancer_cmd_req_read_object), wrb, 2458de49bd5aSPadmanabh Ratnakar NULL); 2459de49bd5aSPadmanabh Ratnakar 2460de49bd5aSPadmanabh Ratnakar req->desired_read_len = cpu_to_le32(data_size); 2461de49bd5aSPadmanabh Ratnakar req->read_offset = cpu_to_le32(data_offset); 2462de49bd5aSPadmanabh Ratnakar strcpy(req->object_name, obj_name); 2463de49bd5aSPadmanabh Ratnakar req->descriptor_count = cpu_to_le32(1); 2464de49bd5aSPadmanabh Ratnakar req->buf_len = cpu_to_le32(data_size); 2465de49bd5aSPadmanabh Ratnakar req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF)); 2466de49bd5aSPadmanabh Ratnakar req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma)); 2467de49bd5aSPadmanabh Ratnakar 2468de49bd5aSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 2469de49bd5aSPadmanabh Ratnakar 2470de49bd5aSPadmanabh Ratnakar resp = embedded_payload(wrb); 2471de49bd5aSPadmanabh Ratnakar if (!status) { 2472de49bd5aSPadmanabh Ratnakar *data_read = le32_to_cpu(resp->actual_read_len); 2473de49bd5aSPadmanabh Ratnakar *eof = le32_to_cpu(resp->eof); 2474de49bd5aSPadmanabh Ratnakar } else { 2475de49bd5aSPadmanabh Ratnakar *addn_status = resp->additional_status; 2476de49bd5aSPadmanabh Ratnakar } 2477de49bd5aSPadmanabh Ratnakar 2478de49bd5aSPadmanabh Ratnakar err_unlock: 2479de49bd5aSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 2480de49bd5aSPadmanabh Ratnakar return status; 2481de49bd5aSPadmanabh Ratnakar } 2482de49bd5aSPadmanabh Ratnakar 24839aebddd1SJeff Kirsher int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, 248470a7b525SVasundhara Volam u32 flash_type, u32 flash_opcode, u32 img_offset, 248570a7b525SVasundhara Volam u32 buf_size) 24869aebddd1SJeff Kirsher { 24879aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 24889aebddd1SJeff Kirsher struct be_cmd_write_flashrom *req; 24899aebddd1SJeff Kirsher int status; 24909aebddd1SJeff Kirsher 24919aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 24929aebddd1SJeff Kirsher adapter->flash_status = 0; 24939aebddd1SJeff Kirsher 24949aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 24959aebddd1SJeff Kirsher if (!wrb) { 24969aebddd1SJeff Kirsher status = -EBUSY; 24979aebddd1SJeff Kirsher goto err_unlock; 24989aebddd1SJeff Kirsher } 24999aebddd1SJeff Kirsher req = cmd->va; 25009aebddd1SJeff Kirsher 2501106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2502a2cc4e0bSSathya Perla OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb, 2503a2cc4e0bSSathya Perla cmd); 25049aebddd1SJeff Kirsher 25059aebddd1SJeff Kirsher req->params.op_type = cpu_to_le32(flash_type); 250670a7b525SVasundhara Volam if (flash_type == OPTYPE_OFFSET_SPECIFIED) 250770a7b525SVasundhara Volam req->params.offset = cpu_to_le32(img_offset); 250870a7b525SVasundhara Volam 25099aebddd1SJeff Kirsher req->params.op_code = cpu_to_le32(flash_opcode); 25109aebddd1SJeff Kirsher req->params.data_buf_size = cpu_to_le32(buf_size); 25119aebddd1SJeff Kirsher 2512efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 2513efaa408eSSuresh Reddy if (status) 2514efaa408eSSuresh Reddy goto err_unlock; 2515efaa408eSSuresh Reddy 25169aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25179aebddd1SJeff Kirsher 25185eeff635SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 2519e2edb7d5SSathya Perla msecs_to_jiffies(40000))) 2520fd45160cSKalesh AP status = -ETIMEDOUT; 25219aebddd1SJeff Kirsher else 25229aebddd1SJeff Kirsher status = adapter->flash_status; 25239aebddd1SJeff Kirsher 25249aebddd1SJeff Kirsher return status; 25259aebddd1SJeff Kirsher 25269aebddd1SJeff Kirsher err_unlock: 25279aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25289aebddd1SJeff Kirsher return status; 25299aebddd1SJeff Kirsher } 25309aebddd1SJeff Kirsher 25319aebddd1SJeff Kirsher int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, 253270a7b525SVasundhara Volam u16 img_optype, u32 img_offset, u32 crc_offset) 25339aebddd1SJeff Kirsher { 2534be716446SPadmanabh Ratnakar struct be_cmd_read_flash_crc *req; 253570a7b525SVasundhara Volam struct be_mcc_wrb *wrb; 25369aebddd1SJeff Kirsher int status; 25379aebddd1SJeff Kirsher 25389aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 25399aebddd1SJeff Kirsher 25409aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 25419aebddd1SJeff Kirsher if (!wrb) { 25429aebddd1SJeff Kirsher status = -EBUSY; 25439aebddd1SJeff Kirsher goto err; 25449aebddd1SJeff Kirsher } 25459aebddd1SJeff Kirsher req = embedded_payload(wrb); 25469aebddd1SJeff Kirsher 2547106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2548be716446SPadmanabh Ratnakar OPCODE_COMMON_READ_FLASHROM, sizeof(*req), 2549be716446SPadmanabh Ratnakar wrb, NULL); 25509aebddd1SJeff Kirsher 255170a7b525SVasundhara Volam req->params.op_type = cpu_to_le32(img_optype); 255270a7b525SVasundhara Volam if (img_optype == OPTYPE_OFFSET_SPECIFIED) 255370a7b525SVasundhara Volam req->params.offset = cpu_to_le32(img_offset + crc_offset); 255470a7b525SVasundhara Volam else 255570a7b525SVasundhara Volam req->params.offset = cpu_to_le32(crc_offset); 255670a7b525SVasundhara Volam 25579aebddd1SJeff Kirsher req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); 25589aebddd1SJeff Kirsher req->params.data_buf_size = cpu_to_le32(0x4); 25599aebddd1SJeff Kirsher 25609aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 25619aebddd1SJeff Kirsher if (!status) 2562be716446SPadmanabh Ratnakar memcpy(flashed_crc, req->crc, 4); 25639aebddd1SJeff Kirsher 25649aebddd1SJeff Kirsher err: 25659aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25669aebddd1SJeff Kirsher return status; 25679aebddd1SJeff Kirsher } 25689aebddd1SJeff Kirsher 25699aebddd1SJeff Kirsher int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, 25709aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 25719aebddd1SJeff Kirsher { 25729aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 25739aebddd1SJeff Kirsher struct be_cmd_req_acpi_wol_magic_config *req; 25749aebddd1SJeff Kirsher int status; 25759aebddd1SJeff Kirsher 25769aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 25779aebddd1SJeff Kirsher 25789aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 25799aebddd1SJeff Kirsher if (!wrb) { 25809aebddd1SJeff Kirsher status = -EBUSY; 25819aebddd1SJeff Kirsher goto err; 25829aebddd1SJeff Kirsher } 25839aebddd1SJeff Kirsher req = nonemb_cmd->va; 25849aebddd1SJeff Kirsher 2585106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 2586a2cc4e0bSSathya Perla OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req), 2587a2cc4e0bSSathya Perla wrb, nonemb_cmd); 25889aebddd1SJeff Kirsher memcpy(req->magic_mac, mac, ETH_ALEN); 25899aebddd1SJeff Kirsher 25909aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 25919aebddd1SJeff Kirsher 25929aebddd1SJeff Kirsher err: 25939aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25949aebddd1SJeff Kirsher return status; 25959aebddd1SJeff Kirsher } 25969aebddd1SJeff Kirsher 25979aebddd1SJeff Kirsher int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, 25989aebddd1SJeff Kirsher u8 loopback_type, u8 enable) 25999aebddd1SJeff Kirsher { 26009aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 26019aebddd1SJeff Kirsher struct be_cmd_req_set_lmode *req; 26029aebddd1SJeff Kirsher int status; 26039aebddd1SJeff Kirsher 26049aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 26059aebddd1SJeff Kirsher 26069aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 26079aebddd1SJeff Kirsher if (!wrb) { 26089aebddd1SJeff Kirsher status = -EBUSY; 26099c855975SSuresh Reddy goto err_unlock; 26109aebddd1SJeff Kirsher } 26119aebddd1SJeff Kirsher 26129aebddd1SJeff Kirsher req = embedded_payload(wrb); 26139aebddd1SJeff Kirsher 2614106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 2615a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req), 2616a2cc4e0bSSathya Perla wrb, NULL); 26179aebddd1SJeff Kirsher 26189aebddd1SJeff Kirsher req->src_port = port_num; 26199aebddd1SJeff Kirsher req->dest_port = port_num; 26209aebddd1SJeff Kirsher req->loopback_type = loopback_type; 26219aebddd1SJeff Kirsher req->loopback_state = enable; 26229aebddd1SJeff Kirsher 26239c855975SSuresh Reddy status = be_mcc_notify(adapter); 26249c855975SSuresh Reddy if (status) 26259c855975SSuresh Reddy goto err_unlock; 26269c855975SSuresh Reddy 26279c855975SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 26289c855975SSuresh Reddy 26299c855975SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 26309c855975SSuresh Reddy msecs_to_jiffies(SET_LB_MODE_TIMEOUT))) 26319c855975SSuresh Reddy status = -ETIMEDOUT; 26329c855975SSuresh Reddy 26339c855975SSuresh Reddy return status; 26349c855975SSuresh Reddy 26359c855975SSuresh Reddy err_unlock: 26369aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 26379aebddd1SJeff Kirsher return status; 26389aebddd1SJeff Kirsher } 26399aebddd1SJeff Kirsher 26409aebddd1SJeff Kirsher int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, 2641a2cc4e0bSSathya Perla u32 loopback_type, u32 pkt_size, u32 num_pkts, 2642a2cc4e0bSSathya Perla u64 pattern) 26439aebddd1SJeff Kirsher { 26449aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 26459aebddd1SJeff Kirsher struct be_cmd_req_loopback_test *req; 26465eeff635SSuresh Reddy struct be_cmd_resp_loopback_test *resp; 26479aebddd1SJeff Kirsher int status; 26489aebddd1SJeff Kirsher 26499aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 26509aebddd1SJeff Kirsher 26519aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 26529aebddd1SJeff Kirsher if (!wrb) { 26539aebddd1SJeff Kirsher status = -EBUSY; 26549aebddd1SJeff Kirsher goto err; 26559aebddd1SJeff Kirsher } 26569aebddd1SJeff Kirsher 26579aebddd1SJeff Kirsher req = embedded_payload(wrb); 26589aebddd1SJeff Kirsher 2659106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 2660a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, 2661a2cc4e0bSSathya Perla NULL); 26629aebddd1SJeff Kirsher 26635eeff635SSuresh Reddy req->hdr.timeout = cpu_to_le32(15); 26649aebddd1SJeff Kirsher req->pattern = cpu_to_le64(pattern); 26659aebddd1SJeff Kirsher req->src_port = cpu_to_le32(port_num); 26669aebddd1SJeff Kirsher req->dest_port = cpu_to_le32(port_num); 26679aebddd1SJeff Kirsher req->pkt_size = cpu_to_le32(pkt_size); 26689aebddd1SJeff Kirsher req->num_pkts = cpu_to_le32(num_pkts); 26699aebddd1SJeff Kirsher req->loopback_type = cpu_to_le32(loopback_type); 26709aebddd1SJeff Kirsher 2671efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 2672efaa408eSSuresh Reddy if (status) 2673efaa408eSSuresh Reddy goto err; 26749aebddd1SJeff Kirsher 26755eeff635SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 26765eeff635SSuresh Reddy 26775eeff635SSuresh Reddy wait_for_completion(&adapter->et_cmd_compl); 26785eeff635SSuresh Reddy resp = embedded_payload(wrb); 26795eeff635SSuresh Reddy status = le32_to_cpu(resp->status); 26805eeff635SSuresh Reddy 26815eeff635SSuresh Reddy return status; 26829aebddd1SJeff Kirsher err: 26839aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 26849aebddd1SJeff Kirsher return status; 26859aebddd1SJeff Kirsher } 26869aebddd1SJeff Kirsher 26879aebddd1SJeff Kirsher int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, 26889aebddd1SJeff Kirsher u32 byte_cnt, struct be_dma_mem *cmd) 26899aebddd1SJeff Kirsher { 26909aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 26919aebddd1SJeff Kirsher struct be_cmd_req_ddrdma_test *req; 26929aebddd1SJeff Kirsher int status; 26939aebddd1SJeff Kirsher int i, j = 0; 26949aebddd1SJeff Kirsher 26959aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 26969aebddd1SJeff Kirsher 26979aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 26989aebddd1SJeff Kirsher if (!wrb) { 26999aebddd1SJeff Kirsher status = -EBUSY; 27009aebddd1SJeff Kirsher goto err; 27019aebddd1SJeff Kirsher } 27029aebddd1SJeff Kirsher req = cmd->va; 2703106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 2704a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb, 2705a2cc4e0bSSathya Perla cmd); 27069aebddd1SJeff Kirsher 27079aebddd1SJeff Kirsher req->pattern = cpu_to_le64(pattern); 27089aebddd1SJeff Kirsher req->byte_count = cpu_to_le32(byte_cnt); 27099aebddd1SJeff Kirsher for (i = 0; i < byte_cnt; i++) { 27109aebddd1SJeff Kirsher req->snd_buff[i] = (u8)(pattern >> (j*8)); 27119aebddd1SJeff Kirsher j++; 27129aebddd1SJeff Kirsher if (j > 7) 27139aebddd1SJeff Kirsher j = 0; 27149aebddd1SJeff Kirsher } 27159aebddd1SJeff Kirsher 27169aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 27179aebddd1SJeff Kirsher 27189aebddd1SJeff Kirsher if (!status) { 27199aebddd1SJeff Kirsher struct be_cmd_resp_ddrdma_test *resp; 272003d28ffeSKalesh AP 27219aebddd1SJeff Kirsher resp = cmd->va; 27229aebddd1SJeff Kirsher if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) || 27239aebddd1SJeff Kirsher resp->snd_err) { 27249aebddd1SJeff Kirsher status = -1; 27259aebddd1SJeff Kirsher } 27269aebddd1SJeff Kirsher } 27279aebddd1SJeff Kirsher 27289aebddd1SJeff Kirsher err: 27299aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 27309aebddd1SJeff Kirsher return status; 27319aebddd1SJeff Kirsher } 27329aebddd1SJeff Kirsher 27339aebddd1SJeff Kirsher int be_cmd_get_seeprom_data(struct be_adapter *adapter, 27349aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 27359aebddd1SJeff Kirsher { 27369aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 27379aebddd1SJeff Kirsher struct be_cmd_req_seeprom_read *req; 27389aebddd1SJeff Kirsher int status; 27399aebddd1SJeff Kirsher 27409aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 27419aebddd1SJeff Kirsher 27429aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 27439aebddd1SJeff Kirsher if (!wrb) { 27449aebddd1SJeff Kirsher status = -EBUSY; 27459aebddd1SJeff Kirsher goto err; 27469aebddd1SJeff Kirsher } 27479aebddd1SJeff Kirsher req = nonemb_cmd->va; 27489aebddd1SJeff Kirsher 2749106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2750106df1e3SSomnath Kotur OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb, 2751106df1e3SSomnath Kotur nonemb_cmd); 27529aebddd1SJeff Kirsher 27539aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 27549aebddd1SJeff Kirsher 27559aebddd1SJeff Kirsher err: 27569aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 27579aebddd1SJeff Kirsher return status; 27589aebddd1SJeff Kirsher } 27599aebddd1SJeff Kirsher 276042f11cf2SAjit Khaparde int be_cmd_get_phy_info(struct be_adapter *adapter) 27619aebddd1SJeff Kirsher { 27629aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 27639aebddd1SJeff Kirsher struct be_cmd_req_get_phy_info *req; 27649aebddd1SJeff Kirsher struct be_dma_mem cmd; 27659aebddd1SJeff Kirsher int status; 27669aebddd1SJeff Kirsher 2767f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS, 2768f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 2769f25b119cSPadmanabh Ratnakar return -EPERM; 2770f25b119cSPadmanabh Ratnakar 27719aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 27729aebddd1SJeff Kirsher 27739aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 27749aebddd1SJeff Kirsher if (!wrb) { 27759aebddd1SJeff Kirsher status = -EBUSY; 27769aebddd1SJeff Kirsher goto err; 27779aebddd1SJeff Kirsher } 27789aebddd1SJeff Kirsher cmd.size = sizeof(struct be_cmd_req_get_phy_info); 2779e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 2780e51000dbSSriharsha Basavapatna GFP_ATOMIC); 27819aebddd1SJeff Kirsher if (!cmd.va) { 27829aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); 27839aebddd1SJeff Kirsher status = -ENOMEM; 27849aebddd1SJeff Kirsher goto err; 27859aebddd1SJeff Kirsher } 27869aebddd1SJeff Kirsher 27879aebddd1SJeff Kirsher req = cmd.va; 27889aebddd1SJeff Kirsher 2789106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2790106df1e3SSomnath Kotur OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req), 2791106df1e3SSomnath Kotur wrb, &cmd); 27929aebddd1SJeff Kirsher 27939aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 27949aebddd1SJeff Kirsher if (!status) { 27959aebddd1SJeff Kirsher struct be_phy_info *resp_phy_info = 27969aebddd1SJeff Kirsher cmd.va + sizeof(struct be_cmd_req_hdr); 279703d28ffeSKalesh AP 279842f11cf2SAjit Khaparde adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type); 279942f11cf2SAjit Khaparde adapter->phy.interface_type = 28009aebddd1SJeff Kirsher le16_to_cpu(resp_phy_info->interface_type); 280142f11cf2SAjit Khaparde adapter->phy.auto_speeds_supported = 280242f11cf2SAjit Khaparde le16_to_cpu(resp_phy_info->auto_speeds_supported); 280342f11cf2SAjit Khaparde adapter->phy.fixed_speeds_supported = 280442f11cf2SAjit Khaparde le16_to_cpu(resp_phy_info->fixed_speeds_supported); 280542f11cf2SAjit Khaparde adapter->phy.misc_params = 280642f11cf2SAjit Khaparde le32_to_cpu(resp_phy_info->misc_params); 280768cb7e47SVasundhara Volam 280868cb7e47SVasundhara Volam if (BE2_chip(adapter)) { 280968cb7e47SVasundhara Volam adapter->phy.fixed_speeds_supported = 281068cb7e47SVasundhara Volam BE_SUPPORTED_SPEED_10GBPS | 281168cb7e47SVasundhara Volam BE_SUPPORTED_SPEED_1GBPS; 281268cb7e47SVasundhara Volam } 28139aebddd1SJeff Kirsher } 2814e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); 28159aebddd1SJeff Kirsher err: 28169aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 28179aebddd1SJeff Kirsher return status; 28189aebddd1SJeff Kirsher } 28199aebddd1SJeff Kirsher 2820bc0ee163SLad, Prabhakar static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain) 28219aebddd1SJeff Kirsher { 28229aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 28239aebddd1SJeff Kirsher struct be_cmd_req_set_qos *req; 28249aebddd1SJeff Kirsher int status; 28259aebddd1SJeff Kirsher 28269aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 28279aebddd1SJeff Kirsher 28289aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 28299aebddd1SJeff Kirsher if (!wrb) { 28309aebddd1SJeff Kirsher status = -EBUSY; 28319aebddd1SJeff Kirsher goto err; 28329aebddd1SJeff Kirsher } 28339aebddd1SJeff Kirsher 28349aebddd1SJeff Kirsher req = embedded_payload(wrb); 28359aebddd1SJeff Kirsher 2836106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2837106df1e3SSomnath Kotur OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL); 28389aebddd1SJeff Kirsher 28399aebddd1SJeff Kirsher req->hdr.domain = domain; 28409aebddd1SJeff Kirsher req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC); 28419aebddd1SJeff Kirsher req->max_bps_nic = cpu_to_le32(bps); 28429aebddd1SJeff Kirsher 28439aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 28449aebddd1SJeff Kirsher 28459aebddd1SJeff Kirsher err: 28469aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 28479aebddd1SJeff Kirsher return status; 28489aebddd1SJeff Kirsher } 28499aebddd1SJeff Kirsher 28509aebddd1SJeff Kirsher int be_cmd_get_cntl_attributes(struct be_adapter *adapter) 28519aebddd1SJeff Kirsher { 28529aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 28539aebddd1SJeff Kirsher struct be_cmd_req_cntl_attribs *req; 28549aebddd1SJeff Kirsher struct be_cmd_resp_cntl_attribs *resp; 28559aebddd1SJeff Kirsher int status; 28569aebddd1SJeff Kirsher int payload_len = max(sizeof(*req), sizeof(*resp)); 28579aebddd1SJeff Kirsher struct mgmt_controller_attrib *attribs; 28589aebddd1SJeff Kirsher struct be_dma_mem attribs_cmd; 28599aebddd1SJeff Kirsher 2860d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 2861d98ef50fSSuresh Reddy return -1; 2862d98ef50fSSuresh Reddy 28639aebddd1SJeff Kirsher memset(&attribs_cmd, 0, sizeof(struct be_dma_mem)); 28649aebddd1SJeff Kirsher attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs); 2865e51000dbSSriharsha Basavapatna attribs_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 2866e51000dbSSriharsha Basavapatna attribs_cmd.size, 2867e51000dbSSriharsha Basavapatna &attribs_cmd.dma, GFP_ATOMIC); 28689aebddd1SJeff Kirsher if (!attribs_cmd.va) { 2869a2cc4e0bSSathya Perla dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); 2870d98ef50fSSuresh Reddy status = -ENOMEM; 2871d98ef50fSSuresh Reddy goto err; 28729aebddd1SJeff Kirsher } 28739aebddd1SJeff Kirsher 28749aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 28759aebddd1SJeff Kirsher if (!wrb) { 28769aebddd1SJeff Kirsher status = -EBUSY; 28779aebddd1SJeff Kirsher goto err; 28789aebddd1SJeff Kirsher } 28799aebddd1SJeff Kirsher req = attribs_cmd.va; 28809aebddd1SJeff Kirsher 2881106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2882a2cc4e0bSSathya Perla OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len, 2883a2cc4e0bSSathya Perla wrb, &attribs_cmd); 28849aebddd1SJeff Kirsher 28859aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 28869aebddd1SJeff Kirsher if (!status) { 28879aebddd1SJeff Kirsher attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr); 28889aebddd1SJeff Kirsher adapter->hba_port_num = attribs->hba_attribs.phy_port; 28899aebddd1SJeff Kirsher } 28909aebddd1SJeff Kirsher 28919aebddd1SJeff Kirsher err: 28929aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 2893d98ef50fSSuresh Reddy if (attribs_cmd.va) 2894e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, attribs_cmd.size, 2895d98ef50fSSuresh Reddy attribs_cmd.va, attribs_cmd.dma); 28969aebddd1SJeff Kirsher return status; 28979aebddd1SJeff Kirsher } 28989aebddd1SJeff Kirsher 28999aebddd1SJeff Kirsher /* Uses mbox */ 29009aebddd1SJeff Kirsher int be_cmd_req_native_mode(struct be_adapter *adapter) 29019aebddd1SJeff Kirsher { 29029aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 29039aebddd1SJeff Kirsher struct be_cmd_req_set_func_cap *req; 29049aebddd1SJeff Kirsher int status; 29059aebddd1SJeff Kirsher 29069aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 29079aebddd1SJeff Kirsher return -1; 29089aebddd1SJeff Kirsher 29099aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 29109aebddd1SJeff Kirsher if (!wrb) { 29119aebddd1SJeff Kirsher status = -EBUSY; 29129aebddd1SJeff Kirsher goto err; 29139aebddd1SJeff Kirsher } 29149aebddd1SJeff Kirsher 29159aebddd1SJeff Kirsher req = embedded_payload(wrb); 29169aebddd1SJeff Kirsher 2917106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2918a2cc4e0bSSathya Perla OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP, 2919a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 29209aebddd1SJeff Kirsher 29219aebddd1SJeff Kirsher req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS | 29229aebddd1SJeff Kirsher CAPABILITY_BE3_NATIVE_ERX_API); 29239aebddd1SJeff Kirsher req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API); 29249aebddd1SJeff Kirsher 29259aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 29269aebddd1SJeff Kirsher if (!status) { 29279aebddd1SJeff Kirsher struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb); 292803d28ffeSKalesh AP 29299aebddd1SJeff Kirsher adapter->be3_native = le32_to_cpu(resp->cap_flags) & 29309aebddd1SJeff Kirsher CAPABILITY_BE3_NATIVE_ERX_API; 2931d379142bSSathya Perla if (!adapter->be3_native) 2932d379142bSSathya Perla dev_warn(&adapter->pdev->dev, 2933d379142bSSathya Perla "adapter not in advanced mode\n"); 29349aebddd1SJeff Kirsher } 29359aebddd1SJeff Kirsher err: 29369aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 29379aebddd1SJeff Kirsher return status; 29389aebddd1SJeff Kirsher } 2939590c391dSPadmanabh Ratnakar 2940f25b119cSPadmanabh Ratnakar /* Get privilege(s) for a function */ 2941f25b119cSPadmanabh Ratnakar int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, 2942f25b119cSPadmanabh Ratnakar u32 domain) 2943f25b119cSPadmanabh Ratnakar { 2944f25b119cSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 2945f25b119cSPadmanabh Ratnakar struct be_cmd_req_get_fn_privileges *req; 2946f25b119cSPadmanabh Ratnakar int status; 2947f25b119cSPadmanabh Ratnakar 2948f25b119cSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 2949f25b119cSPadmanabh Ratnakar 2950f25b119cSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 2951f25b119cSPadmanabh Ratnakar if (!wrb) { 2952f25b119cSPadmanabh Ratnakar status = -EBUSY; 2953f25b119cSPadmanabh Ratnakar goto err; 2954f25b119cSPadmanabh Ratnakar } 2955f25b119cSPadmanabh Ratnakar 2956f25b119cSPadmanabh Ratnakar req = embedded_payload(wrb); 2957f25b119cSPadmanabh Ratnakar 2958f25b119cSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2959f25b119cSPadmanabh Ratnakar OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req), 2960f25b119cSPadmanabh Ratnakar wrb, NULL); 2961f25b119cSPadmanabh Ratnakar 2962f25b119cSPadmanabh Ratnakar req->hdr.domain = domain; 2963f25b119cSPadmanabh Ratnakar 2964f25b119cSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 2965f25b119cSPadmanabh Ratnakar if (!status) { 2966f25b119cSPadmanabh Ratnakar struct be_cmd_resp_get_fn_privileges *resp = 2967f25b119cSPadmanabh Ratnakar embedded_payload(wrb); 296803d28ffeSKalesh AP 2969f25b119cSPadmanabh Ratnakar *privilege = le32_to_cpu(resp->privilege_mask); 297002308d74SSuresh Reddy 297102308d74SSuresh Reddy /* In UMC mode FW does not return right privileges. 297202308d74SSuresh Reddy * Override with correct privilege equivalent to PF. 297302308d74SSuresh Reddy */ 297402308d74SSuresh Reddy if (BEx_chip(adapter) && be_is_mc(adapter) && 297502308d74SSuresh Reddy be_physfn(adapter)) 297602308d74SSuresh Reddy *privilege = MAX_PRIVILEGES; 2977f25b119cSPadmanabh Ratnakar } 2978f25b119cSPadmanabh Ratnakar 2979f25b119cSPadmanabh Ratnakar err: 2980f25b119cSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 2981f25b119cSPadmanabh Ratnakar return status; 2982f25b119cSPadmanabh Ratnakar } 2983f25b119cSPadmanabh Ratnakar 298404a06028SSathya Perla /* Set privilege(s) for a function */ 298504a06028SSathya Perla int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, 298604a06028SSathya Perla u32 domain) 298704a06028SSathya Perla { 298804a06028SSathya Perla struct be_mcc_wrb *wrb; 298904a06028SSathya Perla struct be_cmd_req_set_fn_privileges *req; 299004a06028SSathya Perla int status; 299104a06028SSathya Perla 299204a06028SSathya Perla spin_lock_bh(&adapter->mcc_lock); 299304a06028SSathya Perla 299404a06028SSathya Perla wrb = wrb_from_mccq(adapter); 299504a06028SSathya Perla if (!wrb) { 299604a06028SSathya Perla status = -EBUSY; 299704a06028SSathya Perla goto err; 299804a06028SSathya Perla } 299904a06028SSathya Perla 300004a06028SSathya Perla req = embedded_payload(wrb); 300104a06028SSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 300204a06028SSathya Perla OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req), 300304a06028SSathya Perla wrb, NULL); 300404a06028SSathya Perla req->hdr.domain = domain; 300504a06028SSathya Perla if (lancer_chip(adapter)) 300604a06028SSathya Perla req->privileges_lancer = cpu_to_le32(privileges); 300704a06028SSathya Perla else 300804a06028SSathya Perla req->privileges = cpu_to_le32(privileges); 300904a06028SSathya Perla 301004a06028SSathya Perla status = be_mcc_notify_wait(adapter); 301104a06028SSathya Perla err: 301204a06028SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 301304a06028SSathya Perla return status; 301404a06028SSathya Perla } 301504a06028SSathya Perla 30165a712c13SSathya Perla /* pmac_id_valid: true => pmac_id is supplied and MAC address is requested. 30175a712c13SSathya Perla * pmac_id_valid: false => pmac_id or MAC address is requested. 30185a712c13SSathya Perla * If pmac_id is returned, pmac_id_valid is returned as true 30195a712c13SSathya Perla */ 30201578e777SPadmanabh Ratnakar int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, 3021b188f090SSuresh Reddy bool *pmac_id_valid, u32 *pmac_id, u32 if_handle, 3022b188f090SSuresh Reddy u8 domain) 3023590c391dSPadmanabh Ratnakar { 3024590c391dSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3025590c391dSPadmanabh Ratnakar struct be_cmd_req_get_mac_list *req; 3026590c391dSPadmanabh Ratnakar int status; 3027590c391dSPadmanabh Ratnakar int mac_count; 3028e5e1ee89SPadmanabh Ratnakar struct be_dma_mem get_mac_list_cmd; 3029e5e1ee89SPadmanabh Ratnakar int i; 3030e5e1ee89SPadmanabh Ratnakar 3031e5e1ee89SPadmanabh Ratnakar memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem)); 3032e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list); 3033e51000dbSSriharsha Basavapatna get_mac_list_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 3034e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.size, 3035e51000dbSSriharsha Basavapatna &get_mac_list_cmd.dma, 3036e51000dbSSriharsha Basavapatna GFP_ATOMIC); 3037e5e1ee89SPadmanabh Ratnakar 3038e5e1ee89SPadmanabh Ratnakar if (!get_mac_list_cmd.va) { 3039e5e1ee89SPadmanabh Ratnakar dev_err(&adapter->pdev->dev, 3040e5e1ee89SPadmanabh Ratnakar "Memory allocation failure during GET_MAC_LIST\n"); 3041e5e1ee89SPadmanabh Ratnakar return -ENOMEM; 3042e5e1ee89SPadmanabh Ratnakar } 3043590c391dSPadmanabh Ratnakar 3044590c391dSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 3045590c391dSPadmanabh Ratnakar 3046590c391dSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 3047590c391dSPadmanabh Ratnakar if (!wrb) { 3048590c391dSPadmanabh Ratnakar status = -EBUSY; 3049e5e1ee89SPadmanabh Ratnakar goto out; 3050590c391dSPadmanabh Ratnakar } 3051e5e1ee89SPadmanabh Ratnakar 3052e5e1ee89SPadmanabh Ratnakar req = get_mac_list_cmd.va; 3053590c391dSPadmanabh Ratnakar 3054590c391dSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3055bf591f51SSathya Perla OPCODE_COMMON_GET_MAC_LIST, 3056bf591f51SSathya Perla get_mac_list_cmd.size, wrb, &get_mac_list_cmd); 3057590c391dSPadmanabh Ratnakar req->hdr.domain = domain; 3058e5e1ee89SPadmanabh Ratnakar req->mac_type = MAC_ADDRESS_TYPE_NETWORK; 30595a712c13SSathya Perla if (*pmac_id_valid) { 30605a712c13SSathya Perla req->mac_id = cpu_to_le32(*pmac_id); 3061b188f090SSuresh Reddy req->iface_id = cpu_to_le16(if_handle); 30625a712c13SSathya Perla req->perm_override = 0; 30635a712c13SSathya Perla } else { 3064e5e1ee89SPadmanabh Ratnakar req->perm_override = 1; 30655a712c13SSathya Perla } 3066590c391dSPadmanabh Ratnakar 3067590c391dSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 3068590c391dSPadmanabh Ratnakar if (!status) { 3069590c391dSPadmanabh Ratnakar struct be_cmd_resp_get_mac_list *resp = 3070e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va; 30715a712c13SSathya Perla 30725a712c13SSathya Perla if (*pmac_id_valid) { 30735a712c13SSathya Perla memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr, 30745a712c13SSathya Perla ETH_ALEN); 30755a712c13SSathya Perla goto out; 30765a712c13SSathya Perla } 30775a712c13SSathya Perla 3078e5e1ee89SPadmanabh Ratnakar mac_count = resp->true_mac_count + resp->pseudo_mac_count; 3079e5e1ee89SPadmanabh Ratnakar /* Mac list returned could contain one or more active mac_ids 3080dbedd44eSJoe Perches * or one or more true or pseudo permanent mac addresses. 30811578e777SPadmanabh Ratnakar * If an active mac_id is present, return first active mac_id 30821578e777SPadmanabh Ratnakar * found. 3083e5e1ee89SPadmanabh Ratnakar */ 3084590c391dSPadmanabh Ratnakar for (i = 0; i < mac_count; i++) { 3085e5e1ee89SPadmanabh Ratnakar struct get_list_macaddr *mac_entry; 3086e5e1ee89SPadmanabh Ratnakar u16 mac_addr_size; 3087e5e1ee89SPadmanabh Ratnakar u32 mac_id; 3088e5e1ee89SPadmanabh Ratnakar 3089e5e1ee89SPadmanabh Ratnakar mac_entry = &resp->macaddr_list[i]; 3090e5e1ee89SPadmanabh Ratnakar mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size); 3091e5e1ee89SPadmanabh Ratnakar /* mac_id is a 32 bit value and mac_addr size 3092e5e1ee89SPadmanabh Ratnakar * is 6 bytes 3093e5e1ee89SPadmanabh Ratnakar */ 3094e5e1ee89SPadmanabh Ratnakar if (mac_addr_size == sizeof(u32)) { 30955a712c13SSathya Perla *pmac_id_valid = true; 3096e5e1ee89SPadmanabh Ratnakar mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; 3097e5e1ee89SPadmanabh Ratnakar *pmac_id = le32_to_cpu(mac_id); 3098e5e1ee89SPadmanabh Ratnakar goto out; 3099590c391dSPadmanabh Ratnakar } 3100590c391dSPadmanabh Ratnakar } 31011578e777SPadmanabh Ratnakar /* If no active mac_id found, return first mac addr */ 31025a712c13SSathya Perla *pmac_id_valid = false; 3103e5e1ee89SPadmanabh Ratnakar memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, 3104e5e1ee89SPadmanabh Ratnakar ETH_ALEN); 3105590c391dSPadmanabh Ratnakar } 3106590c391dSPadmanabh Ratnakar 3107e5e1ee89SPadmanabh Ratnakar out: 3108590c391dSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 3109e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, get_mac_list_cmd.size, 3110e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va, get_mac_list_cmd.dma); 3111590c391dSPadmanabh Ratnakar return status; 3112590c391dSPadmanabh Ratnakar } 3113590c391dSPadmanabh Ratnakar 3114a2cc4e0bSSathya Perla int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id, 3115a2cc4e0bSSathya Perla u8 *mac, u32 if_handle, bool active, u32 domain) 31165a712c13SSathya Perla { 3117b188f090SSuresh Reddy if (!active) 3118b188f090SSuresh Reddy be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id, 3119b188f090SSuresh Reddy if_handle, domain); 31203175d8c2SSathya Perla if (BEx_chip(adapter)) 31215a712c13SSathya Perla return be_cmd_mac_addr_query(adapter, mac, false, 3122b188f090SSuresh Reddy if_handle, curr_pmac_id); 31233175d8c2SSathya Perla else 31243175d8c2SSathya Perla /* Fetch the MAC address using pmac_id */ 31253175d8c2SSathya Perla return be_cmd_get_mac_from_list(adapter, mac, &active, 3126b188f090SSuresh Reddy &curr_pmac_id, 3127b188f090SSuresh Reddy if_handle, domain); 31285a712c13SSathya Perla } 31295a712c13SSathya Perla 313095046b92SSathya Perla int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac) 313195046b92SSathya Perla { 313295046b92SSathya Perla int status; 313395046b92SSathya Perla bool pmac_valid = false; 313495046b92SSathya Perla 3135c7bf7169SJoe Perches eth_zero_addr(mac); 313695046b92SSathya Perla 31373175d8c2SSathya Perla if (BEx_chip(adapter)) { 31383175d8c2SSathya Perla if (be_physfn(adapter)) 31393175d8c2SSathya Perla status = be_cmd_mac_addr_query(adapter, mac, true, 0, 31403175d8c2SSathya Perla 0); 314195046b92SSathya Perla else 314295046b92SSathya Perla status = be_cmd_mac_addr_query(adapter, mac, false, 314395046b92SSathya Perla adapter->if_handle, 0); 31443175d8c2SSathya Perla } else { 31453175d8c2SSathya Perla status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid, 3146b188f090SSuresh Reddy NULL, adapter->if_handle, 0); 31473175d8c2SSathya Perla } 31483175d8c2SSathya Perla 314995046b92SSathya Perla return status; 315095046b92SSathya Perla } 315195046b92SSathya Perla 3152590c391dSPadmanabh Ratnakar /* Uses synchronous MCCQ */ 3153590c391dSPadmanabh Ratnakar int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, 3154590c391dSPadmanabh Ratnakar u8 mac_count, u32 domain) 3155590c391dSPadmanabh Ratnakar { 3156590c391dSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3157590c391dSPadmanabh Ratnakar struct be_cmd_req_set_mac_list *req; 3158590c391dSPadmanabh Ratnakar int status; 3159590c391dSPadmanabh Ratnakar struct be_dma_mem cmd; 3160590c391dSPadmanabh Ratnakar 3161590c391dSPadmanabh Ratnakar memset(&cmd, 0, sizeof(struct be_dma_mem)); 3162590c391dSPadmanabh Ratnakar cmd.size = sizeof(struct be_cmd_req_set_mac_list); 3163e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 3164e51000dbSSriharsha Basavapatna GFP_KERNEL); 3165d0320f75SJoe Perches if (!cmd.va) 3166590c391dSPadmanabh Ratnakar return -ENOMEM; 3167590c391dSPadmanabh Ratnakar 3168590c391dSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 3169590c391dSPadmanabh Ratnakar 3170590c391dSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 3171590c391dSPadmanabh Ratnakar if (!wrb) { 3172590c391dSPadmanabh Ratnakar status = -EBUSY; 3173590c391dSPadmanabh Ratnakar goto err; 3174590c391dSPadmanabh Ratnakar } 3175590c391dSPadmanabh Ratnakar 3176590c391dSPadmanabh Ratnakar req = cmd.va; 3177590c391dSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3178590c391dSPadmanabh Ratnakar OPCODE_COMMON_SET_MAC_LIST, sizeof(*req), 3179590c391dSPadmanabh Ratnakar wrb, &cmd); 3180590c391dSPadmanabh Ratnakar 3181590c391dSPadmanabh Ratnakar req->hdr.domain = domain; 3182590c391dSPadmanabh Ratnakar req->mac_count = mac_count; 3183590c391dSPadmanabh Ratnakar if (mac_count) 3184590c391dSPadmanabh Ratnakar memcpy(req->mac, mac_array, ETH_ALEN*mac_count); 3185590c391dSPadmanabh Ratnakar 3186590c391dSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 3187590c391dSPadmanabh Ratnakar 3188590c391dSPadmanabh Ratnakar err: 3189a2cc4e0bSSathya Perla dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); 3190590c391dSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 3191590c391dSPadmanabh Ratnakar return status; 3192590c391dSPadmanabh Ratnakar } 31934762f6ceSAjit Khaparde 31943175d8c2SSathya Perla /* Wrapper to delete any active MACs and provision the new mac. 31953175d8c2SSathya Perla * Changes to MAC_LIST are allowed iff none of the MAC addresses in the 31963175d8c2SSathya Perla * current list are active. 31973175d8c2SSathya Perla */ 31983175d8c2SSathya Perla int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom) 31993175d8c2SSathya Perla { 32003175d8c2SSathya Perla bool active_mac = false; 32013175d8c2SSathya Perla u8 old_mac[ETH_ALEN]; 32023175d8c2SSathya Perla u32 pmac_id; 32033175d8c2SSathya Perla int status; 32043175d8c2SSathya Perla 32053175d8c2SSathya Perla status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac, 3206b188f090SSuresh Reddy &pmac_id, if_id, dom); 3207b188f090SSuresh Reddy 32083175d8c2SSathya Perla if (!status && active_mac) 32093175d8c2SSathya Perla be_cmd_pmac_del(adapter, if_id, pmac_id, dom); 32103175d8c2SSathya Perla 32113175d8c2SSathya Perla return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom); 32123175d8c2SSathya Perla } 32133175d8c2SSathya Perla 3214f1f3ee1bSAjit Khaparde int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, 3215e7bcbd7bSKalesh AP u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk) 3216f1f3ee1bSAjit Khaparde { 3217f1f3ee1bSAjit Khaparde struct be_mcc_wrb *wrb; 3218f1f3ee1bSAjit Khaparde struct be_cmd_req_set_hsw_config *req; 3219f1f3ee1bSAjit Khaparde void *ctxt; 3220f1f3ee1bSAjit Khaparde int status; 3221f1f3ee1bSAjit Khaparde 3222f1f3ee1bSAjit Khaparde spin_lock_bh(&adapter->mcc_lock); 3223f1f3ee1bSAjit Khaparde 3224f1f3ee1bSAjit Khaparde wrb = wrb_from_mccq(adapter); 3225f1f3ee1bSAjit Khaparde if (!wrb) { 3226f1f3ee1bSAjit Khaparde status = -EBUSY; 3227f1f3ee1bSAjit Khaparde goto err; 3228f1f3ee1bSAjit Khaparde } 3229f1f3ee1bSAjit Khaparde 3230f1f3ee1bSAjit Khaparde req = embedded_payload(wrb); 3231f1f3ee1bSAjit Khaparde ctxt = &req->context; 3232f1f3ee1bSAjit Khaparde 3233f1f3ee1bSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3234a2cc4e0bSSathya Perla OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb, 3235a2cc4e0bSSathya Perla NULL); 3236f1f3ee1bSAjit Khaparde 3237f1f3ee1bSAjit Khaparde req->hdr.domain = domain; 3238f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id); 3239f1f3ee1bSAjit Khaparde if (pvid) { 3240f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1); 3241f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid); 3242f1f3ee1bSAjit Khaparde } 3243a77dcb8cSAjit Khaparde if (!BEx_chip(adapter) && hsw_mode) { 3244a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, 3245a77dcb8cSAjit Khaparde ctxt, adapter->hba_port_num); 3246a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1); 3247a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type, 3248a77dcb8cSAjit Khaparde ctxt, hsw_mode); 3249a77dcb8cSAjit Khaparde } 3250f1f3ee1bSAjit Khaparde 3251e7bcbd7bSKalesh AP /* Enable/disable both mac and vlan spoof checking */ 3252e7bcbd7bSKalesh AP if (!BEx_chip(adapter) && spoofchk) { 3253e7bcbd7bSKalesh AP AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk, 3254e7bcbd7bSKalesh AP ctxt, spoofchk); 3255e7bcbd7bSKalesh AP AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk, 3256e7bcbd7bSKalesh AP ctxt, spoofchk); 3257e7bcbd7bSKalesh AP } 3258e7bcbd7bSKalesh AP 3259f1f3ee1bSAjit Khaparde be_dws_cpu_to_le(req->context, sizeof(req->context)); 3260f1f3ee1bSAjit Khaparde status = be_mcc_notify_wait(adapter); 3261f1f3ee1bSAjit Khaparde 3262f1f3ee1bSAjit Khaparde err: 3263f1f3ee1bSAjit Khaparde spin_unlock_bh(&adapter->mcc_lock); 3264f1f3ee1bSAjit Khaparde return status; 3265f1f3ee1bSAjit Khaparde } 3266f1f3ee1bSAjit Khaparde 3267f1f3ee1bSAjit Khaparde /* Get Hyper switch config */ 3268f1f3ee1bSAjit Khaparde int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, 3269e7bcbd7bSKalesh AP u32 domain, u16 intf_id, u8 *mode, bool *spoofchk) 3270f1f3ee1bSAjit Khaparde { 3271f1f3ee1bSAjit Khaparde struct be_mcc_wrb *wrb; 3272f1f3ee1bSAjit Khaparde struct be_cmd_req_get_hsw_config *req; 3273f1f3ee1bSAjit Khaparde void *ctxt; 3274f1f3ee1bSAjit Khaparde int status; 3275f1f3ee1bSAjit Khaparde u16 vid; 3276f1f3ee1bSAjit Khaparde 3277f1f3ee1bSAjit Khaparde spin_lock_bh(&adapter->mcc_lock); 3278f1f3ee1bSAjit Khaparde 3279f1f3ee1bSAjit Khaparde wrb = wrb_from_mccq(adapter); 3280f1f3ee1bSAjit Khaparde if (!wrb) { 3281f1f3ee1bSAjit Khaparde status = -EBUSY; 3282f1f3ee1bSAjit Khaparde goto err; 3283f1f3ee1bSAjit Khaparde } 3284f1f3ee1bSAjit Khaparde 3285f1f3ee1bSAjit Khaparde req = embedded_payload(wrb); 3286f1f3ee1bSAjit Khaparde ctxt = &req->context; 3287f1f3ee1bSAjit Khaparde 3288f1f3ee1bSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3289a2cc4e0bSSathya Perla OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb, 3290a2cc4e0bSSathya Perla NULL); 3291f1f3ee1bSAjit Khaparde 3292f1f3ee1bSAjit Khaparde req->hdr.domain = domain; 3293a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, 3294a77dcb8cSAjit Khaparde ctxt, intf_id); 3295f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1); 3296a77dcb8cSAjit Khaparde 32972c07c1d7SVasundhara Volam if (!BEx_chip(adapter) && mode) { 3298a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, 3299a77dcb8cSAjit Khaparde ctxt, adapter->hba_port_num); 3300a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1); 3301a77dcb8cSAjit Khaparde } 3302f1f3ee1bSAjit Khaparde be_dws_cpu_to_le(req->context, sizeof(req->context)); 3303f1f3ee1bSAjit Khaparde 3304f1f3ee1bSAjit Khaparde status = be_mcc_notify_wait(adapter); 3305f1f3ee1bSAjit Khaparde if (!status) { 3306f1f3ee1bSAjit Khaparde struct be_cmd_resp_get_hsw_config *resp = 3307f1f3ee1bSAjit Khaparde embedded_payload(wrb); 330803d28ffeSKalesh AP 3309a2cc4e0bSSathya Perla be_dws_le_to_cpu(&resp->context, sizeof(resp->context)); 3310f1f3ee1bSAjit Khaparde vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3311f1f3ee1bSAjit Khaparde pvid, &resp->context); 3312a77dcb8cSAjit Khaparde if (pvid) 3313f1f3ee1bSAjit Khaparde *pvid = le16_to_cpu(vid); 3314a77dcb8cSAjit Khaparde if (mode) 3315a77dcb8cSAjit Khaparde *mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3316a77dcb8cSAjit Khaparde port_fwd_type, &resp->context); 3317e7bcbd7bSKalesh AP if (spoofchk) 3318e7bcbd7bSKalesh AP *spoofchk = 3319e7bcbd7bSKalesh AP AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3320e7bcbd7bSKalesh AP spoofchk, &resp->context); 3321f1f3ee1bSAjit Khaparde } 3322f1f3ee1bSAjit Khaparde 3323f1f3ee1bSAjit Khaparde err: 3324f1f3ee1bSAjit Khaparde spin_unlock_bh(&adapter->mcc_lock); 3325f1f3ee1bSAjit Khaparde return status; 3326f1f3ee1bSAjit Khaparde } 3327f1f3ee1bSAjit Khaparde 3328f7062ee5SSathya Perla static bool be_is_wol_excluded(struct be_adapter *adapter) 3329f7062ee5SSathya Perla { 3330f7062ee5SSathya Perla struct pci_dev *pdev = adapter->pdev; 3331f7062ee5SSathya Perla 333218c57c74SKalesh AP if (be_virtfn(adapter)) 3333f7062ee5SSathya Perla return true; 3334f7062ee5SSathya Perla 3335f7062ee5SSathya Perla switch (pdev->subsystem_device) { 3336f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID1: 3337f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID2: 3338f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID3: 3339f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID4: 3340f7062ee5SSathya Perla return true; 3341f7062ee5SSathya Perla default: 3342f7062ee5SSathya Perla return false; 3343f7062ee5SSathya Perla } 3344f7062ee5SSathya Perla } 3345f7062ee5SSathya Perla 33464762f6ceSAjit Khaparde int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) 33474762f6ceSAjit Khaparde { 33484762f6ceSAjit Khaparde struct be_mcc_wrb *wrb; 33494762f6ceSAjit Khaparde struct be_cmd_req_acpi_wol_magic_config_v1 *req; 335076a9e08eSSuresh Reddy int status = 0; 33514762f6ceSAjit Khaparde struct be_dma_mem cmd; 33524762f6ceSAjit Khaparde 3353f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, 3354f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH)) 3355f25b119cSPadmanabh Ratnakar return -EPERM; 3356f25b119cSPadmanabh Ratnakar 335776a9e08eSSuresh Reddy if (be_is_wol_excluded(adapter)) 335876a9e08eSSuresh Reddy return status; 335976a9e08eSSuresh Reddy 3360d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 3361d98ef50fSSuresh Reddy return -1; 3362d98ef50fSSuresh Reddy 33634762f6ceSAjit Khaparde memset(&cmd, 0, sizeof(struct be_dma_mem)); 33644762f6ceSAjit Khaparde cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); 3365e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 3366e51000dbSSriharsha Basavapatna GFP_ATOMIC); 33674762f6ceSAjit Khaparde if (!cmd.va) { 3368a2cc4e0bSSathya Perla dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); 3369d98ef50fSSuresh Reddy status = -ENOMEM; 3370d98ef50fSSuresh Reddy goto err; 33714762f6ceSAjit Khaparde } 33724762f6ceSAjit Khaparde 33734762f6ceSAjit Khaparde wrb = wrb_from_mbox(adapter); 33744762f6ceSAjit Khaparde if (!wrb) { 33754762f6ceSAjit Khaparde status = -EBUSY; 33764762f6ceSAjit Khaparde goto err; 33774762f6ceSAjit Khaparde } 33784762f6ceSAjit Khaparde 33794762f6ceSAjit Khaparde req = cmd.va; 33804762f6ceSAjit Khaparde 33814762f6ceSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 33824762f6ceSAjit Khaparde OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, 338376a9e08eSSuresh Reddy sizeof(*req), wrb, &cmd); 33844762f6ceSAjit Khaparde 33854762f6ceSAjit Khaparde req->hdr.version = 1; 33864762f6ceSAjit Khaparde req->query_options = BE_GET_WOL_CAP; 33874762f6ceSAjit Khaparde 33884762f6ceSAjit Khaparde status = be_mbox_notify_wait(adapter); 33894762f6ceSAjit Khaparde if (!status) { 33904762f6ceSAjit Khaparde struct be_cmd_resp_acpi_wol_magic_config_v1 *resp; 339103d28ffeSKalesh AP 33924762f6ceSAjit Khaparde resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va; 33934762f6ceSAjit Khaparde 33944762f6ceSAjit Khaparde adapter->wol_cap = resp->wol_settings; 339576a9e08eSSuresh Reddy if (adapter->wol_cap & BE_WOL_CAP) 339676a9e08eSSuresh Reddy adapter->wol_en = true; 33974762f6ceSAjit Khaparde } 33984762f6ceSAjit Khaparde err: 33994762f6ceSAjit Khaparde mutex_unlock(&adapter->mbox_lock); 3400d98ef50fSSuresh Reddy if (cmd.va) 3401e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, 3402e51000dbSSriharsha Basavapatna cmd.dma); 34034762f6ceSAjit Khaparde return status; 3404941a77d5SSomnath Kotur 3405941a77d5SSomnath Kotur } 3406baaa08d1SVasundhara Volam 3407baaa08d1SVasundhara Volam int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level) 3408baaa08d1SVasundhara Volam { 3409baaa08d1SVasundhara Volam struct be_dma_mem extfat_cmd; 3410baaa08d1SVasundhara Volam struct be_fat_conf_params *cfgs; 3411baaa08d1SVasundhara Volam int status; 3412baaa08d1SVasundhara Volam int i, j; 3413baaa08d1SVasundhara Volam 3414baaa08d1SVasundhara Volam memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); 3415baaa08d1SVasundhara Volam extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); 3416e51000dbSSriharsha Basavapatna extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 3417e51000dbSSriharsha Basavapatna extfat_cmd.size, &extfat_cmd.dma, 3418e51000dbSSriharsha Basavapatna GFP_ATOMIC); 3419baaa08d1SVasundhara Volam if (!extfat_cmd.va) 3420baaa08d1SVasundhara Volam return -ENOMEM; 3421baaa08d1SVasundhara Volam 3422baaa08d1SVasundhara Volam status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd); 3423baaa08d1SVasundhara Volam if (status) 3424baaa08d1SVasundhara Volam goto err; 3425baaa08d1SVasundhara Volam 3426baaa08d1SVasundhara Volam cfgs = (struct be_fat_conf_params *) 3427baaa08d1SVasundhara Volam (extfat_cmd.va + sizeof(struct be_cmd_resp_hdr)); 3428baaa08d1SVasundhara Volam for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) { 3429baaa08d1SVasundhara Volam u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes); 343003d28ffeSKalesh AP 3431baaa08d1SVasundhara Volam for (j = 0; j < num_modes; j++) { 3432baaa08d1SVasundhara Volam if (cfgs->module[i].trace_lvl[j].mode == MODE_UART) 3433baaa08d1SVasundhara Volam cfgs->module[i].trace_lvl[j].dbg_lvl = 3434baaa08d1SVasundhara Volam cpu_to_le32(level); 3435baaa08d1SVasundhara Volam } 3436baaa08d1SVasundhara Volam } 3437baaa08d1SVasundhara Volam 3438baaa08d1SVasundhara Volam status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs); 3439baaa08d1SVasundhara Volam err: 3440e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va, 3441baaa08d1SVasundhara Volam extfat_cmd.dma); 3442baaa08d1SVasundhara Volam return status; 3443baaa08d1SVasundhara Volam } 3444baaa08d1SVasundhara Volam 3445baaa08d1SVasundhara Volam int be_cmd_get_fw_log_level(struct be_adapter *adapter) 3446baaa08d1SVasundhara Volam { 3447baaa08d1SVasundhara Volam struct be_dma_mem extfat_cmd; 3448baaa08d1SVasundhara Volam struct be_fat_conf_params *cfgs; 3449baaa08d1SVasundhara Volam int status, j; 3450baaa08d1SVasundhara Volam int level = 0; 3451baaa08d1SVasundhara Volam 3452baaa08d1SVasundhara Volam memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); 3453baaa08d1SVasundhara Volam extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); 3454e51000dbSSriharsha Basavapatna extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 3455e51000dbSSriharsha Basavapatna extfat_cmd.size, &extfat_cmd.dma, 3456e51000dbSSriharsha Basavapatna GFP_ATOMIC); 3457baaa08d1SVasundhara Volam 3458baaa08d1SVasundhara Volam if (!extfat_cmd.va) { 3459baaa08d1SVasundhara Volam dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n", 3460baaa08d1SVasundhara Volam __func__); 3461baaa08d1SVasundhara Volam goto err; 3462baaa08d1SVasundhara Volam } 3463baaa08d1SVasundhara Volam 3464baaa08d1SVasundhara Volam status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd); 3465baaa08d1SVasundhara Volam if (!status) { 3466baaa08d1SVasundhara Volam cfgs = (struct be_fat_conf_params *)(extfat_cmd.va + 3467baaa08d1SVasundhara Volam sizeof(struct be_cmd_resp_hdr)); 346803d28ffeSKalesh AP 3469baaa08d1SVasundhara Volam for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) { 3470baaa08d1SVasundhara Volam if (cfgs->module[0].trace_lvl[j].mode == MODE_UART) 3471baaa08d1SVasundhara Volam level = cfgs->module[0].trace_lvl[j].dbg_lvl; 3472baaa08d1SVasundhara Volam } 3473baaa08d1SVasundhara Volam } 3474e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va, 3475baaa08d1SVasundhara Volam extfat_cmd.dma); 3476baaa08d1SVasundhara Volam err: 3477baaa08d1SVasundhara Volam return level; 3478baaa08d1SVasundhara Volam } 3479baaa08d1SVasundhara Volam 3480941a77d5SSomnath Kotur int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter, 3481941a77d5SSomnath Kotur struct be_dma_mem *cmd) 3482941a77d5SSomnath Kotur { 3483941a77d5SSomnath Kotur struct be_mcc_wrb *wrb; 3484941a77d5SSomnath Kotur struct be_cmd_req_get_ext_fat_caps *req; 3485941a77d5SSomnath Kotur int status; 3486941a77d5SSomnath Kotur 3487941a77d5SSomnath Kotur if (mutex_lock_interruptible(&adapter->mbox_lock)) 3488941a77d5SSomnath Kotur return -1; 3489941a77d5SSomnath Kotur 3490941a77d5SSomnath Kotur wrb = wrb_from_mbox(adapter); 3491941a77d5SSomnath Kotur if (!wrb) { 3492941a77d5SSomnath Kotur status = -EBUSY; 3493941a77d5SSomnath Kotur goto err; 3494941a77d5SSomnath Kotur } 3495941a77d5SSomnath Kotur 3496941a77d5SSomnath Kotur req = cmd->va; 3497941a77d5SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3498941a77d5SSomnath Kotur OPCODE_COMMON_GET_EXT_FAT_CAPABILITES, 3499941a77d5SSomnath Kotur cmd->size, wrb, cmd); 3500941a77d5SSomnath Kotur req->parameter_type = cpu_to_le32(1); 3501941a77d5SSomnath Kotur 3502941a77d5SSomnath Kotur status = be_mbox_notify_wait(adapter); 3503941a77d5SSomnath Kotur err: 3504941a77d5SSomnath Kotur mutex_unlock(&adapter->mbox_lock); 3505941a77d5SSomnath Kotur return status; 3506941a77d5SSomnath Kotur } 3507941a77d5SSomnath Kotur 3508941a77d5SSomnath Kotur int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, 3509941a77d5SSomnath Kotur struct be_dma_mem *cmd, 3510941a77d5SSomnath Kotur struct be_fat_conf_params *configs) 3511941a77d5SSomnath Kotur { 3512941a77d5SSomnath Kotur struct be_mcc_wrb *wrb; 3513941a77d5SSomnath Kotur struct be_cmd_req_set_ext_fat_caps *req; 3514941a77d5SSomnath Kotur int status; 3515941a77d5SSomnath Kotur 3516941a77d5SSomnath Kotur spin_lock_bh(&adapter->mcc_lock); 3517941a77d5SSomnath Kotur 3518941a77d5SSomnath Kotur wrb = wrb_from_mccq(adapter); 3519941a77d5SSomnath Kotur if (!wrb) { 3520941a77d5SSomnath Kotur status = -EBUSY; 3521941a77d5SSomnath Kotur goto err; 3522941a77d5SSomnath Kotur } 3523941a77d5SSomnath Kotur 3524941a77d5SSomnath Kotur req = cmd->va; 3525941a77d5SSomnath Kotur memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params)); 3526941a77d5SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3527941a77d5SSomnath Kotur OPCODE_COMMON_SET_EXT_FAT_CAPABILITES, 3528941a77d5SSomnath Kotur cmd->size, wrb, cmd); 3529941a77d5SSomnath Kotur 3530941a77d5SSomnath Kotur status = be_mcc_notify_wait(adapter); 3531941a77d5SSomnath Kotur err: 3532941a77d5SSomnath Kotur spin_unlock_bh(&adapter->mcc_lock); 3533941a77d5SSomnath Kotur return status; 35344762f6ceSAjit Khaparde } 35356a4ab669SParav Pandit 353621252377SVasundhara Volam int be_cmd_query_port_name(struct be_adapter *adapter) 3537b4e32a71SPadmanabh Ratnakar { 3538b4e32a71SPadmanabh Ratnakar struct be_cmd_req_get_port_name *req; 353921252377SVasundhara Volam struct be_mcc_wrb *wrb; 3540b4e32a71SPadmanabh Ratnakar int status; 3541b4e32a71SPadmanabh Ratnakar 354221252377SVasundhara Volam if (mutex_lock_interruptible(&adapter->mbox_lock)) 354321252377SVasundhara Volam return -1; 3544b4e32a71SPadmanabh Ratnakar 354521252377SVasundhara Volam wrb = wrb_from_mbox(adapter); 3546b4e32a71SPadmanabh Ratnakar req = embedded_payload(wrb); 3547b4e32a71SPadmanabh Ratnakar 3548b4e32a71SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3549b4e32a71SPadmanabh Ratnakar OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb, 3550b4e32a71SPadmanabh Ratnakar NULL); 355121252377SVasundhara Volam if (!BEx_chip(adapter)) 3552b4e32a71SPadmanabh Ratnakar req->hdr.version = 1; 3553b4e32a71SPadmanabh Ratnakar 355421252377SVasundhara Volam status = be_mbox_notify_wait(adapter); 3555b4e32a71SPadmanabh Ratnakar if (!status) { 3556b4e32a71SPadmanabh Ratnakar struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb); 355703d28ffeSKalesh AP 355821252377SVasundhara Volam adapter->port_name = resp->port_name[adapter->hba_port_num]; 3559b4e32a71SPadmanabh Ratnakar } else { 356021252377SVasundhara Volam adapter->port_name = adapter->hba_port_num + '0'; 3561b4e32a71SPadmanabh Ratnakar } 356221252377SVasundhara Volam 356321252377SVasundhara Volam mutex_unlock(&adapter->mbox_lock); 3564b4e32a71SPadmanabh Ratnakar return status; 3565b4e32a71SPadmanabh Ratnakar } 3566b4e32a71SPadmanabh Ratnakar 356710cccf60SVasundhara Volam /* Descriptor type */ 356810cccf60SVasundhara Volam enum { 356910cccf60SVasundhara Volam FUNC_DESC = 1, 357010cccf60SVasundhara Volam VFT_DESC = 2 357110cccf60SVasundhara Volam }; 357210cccf60SVasundhara Volam 357310cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count, 357410cccf60SVasundhara Volam int desc_type) 3575abb93951SPadmanabh Ratnakar { 3576150d58c7SVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 357710cccf60SVasundhara Volam struct be_nic_res_desc *nic; 3578abb93951SPadmanabh Ratnakar int i; 3579abb93951SPadmanabh Ratnakar 3580abb93951SPadmanabh Ratnakar for (i = 0; i < desc_count; i++) { 3581150d58c7SVasundhara Volam if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 || 358210cccf60SVasundhara Volam hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) { 358310cccf60SVasundhara Volam nic = (struct be_nic_res_desc *)hdr; 358410cccf60SVasundhara Volam if (desc_type == FUNC_DESC || 358510cccf60SVasundhara Volam (desc_type == VFT_DESC && 358610cccf60SVasundhara Volam nic->flags & (1 << VFT_SHIFT))) 358710cccf60SVasundhara Volam return nic; 358810cccf60SVasundhara Volam } 3589150d58c7SVasundhara Volam 3590150d58c7SVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 3591150d58c7SVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 3592150d58c7SVasundhara Volam } 3593950e2958SWei Yang return NULL; 3594abb93951SPadmanabh Ratnakar } 3595abb93951SPadmanabh Ratnakar 359610cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count) 359710cccf60SVasundhara Volam { 359810cccf60SVasundhara Volam return be_get_nic_desc(buf, desc_count, VFT_DESC); 359910cccf60SVasundhara Volam } 360010cccf60SVasundhara Volam 360110cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count) 360210cccf60SVasundhara Volam { 360310cccf60SVasundhara Volam return be_get_nic_desc(buf, desc_count, FUNC_DESC); 360410cccf60SVasundhara Volam } 360510cccf60SVasundhara Volam 3606150d58c7SVasundhara Volam static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf, 3607150d58c7SVasundhara Volam u32 desc_count) 3608150d58c7SVasundhara Volam { 3609150d58c7SVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 3610150d58c7SVasundhara Volam struct be_pcie_res_desc *pcie; 3611150d58c7SVasundhara Volam int i; 3612150d58c7SVasundhara Volam 3613150d58c7SVasundhara Volam for (i = 0; i < desc_count; i++) { 3614150d58c7SVasundhara Volam if ((hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 || 3615150d58c7SVasundhara Volam hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1)) { 3616150d58c7SVasundhara Volam pcie = (struct be_pcie_res_desc *)hdr; 3617150d58c7SVasundhara Volam if (pcie->pf_num == devfn) 3618150d58c7SVasundhara Volam return pcie; 3619150d58c7SVasundhara Volam } 3620150d58c7SVasundhara Volam 3621150d58c7SVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 3622150d58c7SVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 3623150d58c7SVasundhara Volam } 3624abb93951SPadmanabh Ratnakar return NULL; 3625abb93951SPadmanabh Ratnakar } 3626abb93951SPadmanabh Ratnakar 3627f93f160bSVasundhara Volam static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count) 3628f93f160bSVasundhara Volam { 3629f93f160bSVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 3630f93f160bSVasundhara Volam int i; 3631f93f160bSVasundhara Volam 3632f93f160bSVasundhara Volam for (i = 0; i < desc_count; i++) { 3633f93f160bSVasundhara Volam if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1) 3634f93f160bSVasundhara Volam return (struct be_port_res_desc *)hdr; 3635f93f160bSVasundhara Volam 3636f93f160bSVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 3637f93f160bSVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 3638f93f160bSVasundhara Volam } 3639f93f160bSVasundhara Volam return NULL; 3640f93f160bSVasundhara Volam } 3641f93f160bSVasundhara Volam 364292bf14abSSathya Perla static void be_copy_nic_desc(struct be_resources *res, 364392bf14abSSathya Perla struct be_nic_res_desc *desc) 364492bf14abSSathya Perla { 364592bf14abSSathya Perla res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count); 364692bf14abSSathya Perla res->max_vlans = le16_to_cpu(desc->vlan_count); 364792bf14abSSathya Perla res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count); 364892bf14abSSathya Perla res->max_tx_qs = le16_to_cpu(desc->txq_count); 364992bf14abSSathya Perla res->max_rss_qs = le16_to_cpu(desc->rssq_count); 365092bf14abSSathya Perla res->max_rx_qs = le16_to_cpu(desc->rq_count); 365192bf14abSSathya Perla res->max_evt_qs = le16_to_cpu(desc->eq_count); 3652f2858738SVasundhara Volam res->max_cq_count = le16_to_cpu(desc->cq_count); 3653f2858738SVasundhara Volam res->max_iface_count = le16_to_cpu(desc->iface_count); 3654f2858738SVasundhara Volam res->max_mcc_count = le16_to_cpu(desc->mcc_count); 365592bf14abSSathya Perla /* Clear flags that driver is not interested in */ 365692bf14abSSathya Perla res->if_cap_flags = le32_to_cpu(desc->cap_flags) & 365792bf14abSSathya Perla BE_IF_CAP_FLAGS_WANT; 365892bf14abSSathya Perla } 365992bf14abSSathya Perla 3660abb93951SPadmanabh Ratnakar /* Uses Mbox */ 366192bf14abSSathya Perla int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) 3662abb93951SPadmanabh Ratnakar { 3663abb93951SPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3664abb93951SPadmanabh Ratnakar struct be_cmd_req_get_func_config *req; 3665abb93951SPadmanabh Ratnakar int status; 3666abb93951SPadmanabh Ratnakar struct be_dma_mem cmd; 3667abb93951SPadmanabh Ratnakar 3668d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 3669d98ef50fSSuresh Reddy return -1; 3670d98ef50fSSuresh Reddy 3671abb93951SPadmanabh Ratnakar memset(&cmd, 0, sizeof(struct be_dma_mem)); 3672abb93951SPadmanabh Ratnakar cmd.size = sizeof(struct be_cmd_resp_get_func_config); 3673e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 3674e51000dbSSriharsha Basavapatna GFP_ATOMIC); 3675abb93951SPadmanabh Ratnakar if (!cmd.va) { 3676abb93951SPadmanabh Ratnakar dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); 3677d98ef50fSSuresh Reddy status = -ENOMEM; 3678d98ef50fSSuresh Reddy goto err; 3679abb93951SPadmanabh Ratnakar } 3680abb93951SPadmanabh Ratnakar 3681abb93951SPadmanabh Ratnakar wrb = wrb_from_mbox(adapter); 3682abb93951SPadmanabh Ratnakar if (!wrb) { 3683abb93951SPadmanabh Ratnakar status = -EBUSY; 3684abb93951SPadmanabh Ratnakar goto err; 3685abb93951SPadmanabh Ratnakar } 3686abb93951SPadmanabh Ratnakar 3687abb93951SPadmanabh Ratnakar req = cmd.va; 3688abb93951SPadmanabh Ratnakar 3689abb93951SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3690abb93951SPadmanabh Ratnakar OPCODE_COMMON_GET_FUNC_CONFIG, 3691abb93951SPadmanabh Ratnakar cmd.size, wrb, &cmd); 3692abb93951SPadmanabh Ratnakar 369328710c55SKalesh AP if (skyhawk_chip(adapter)) 369428710c55SKalesh AP req->hdr.version = 1; 369528710c55SKalesh AP 3696abb93951SPadmanabh Ratnakar status = be_mbox_notify_wait(adapter); 3697abb93951SPadmanabh Ratnakar if (!status) { 3698abb93951SPadmanabh Ratnakar struct be_cmd_resp_get_func_config *resp = cmd.va; 3699abb93951SPadmanabh Ratnakar u32 desc_count = le32_to_cpu(resp->desc_count); 3700150d58c7SVasundhara Volam struct be_nic_res_desc *desc; 3701abb93951SPadmanabh Ratnakar 370210cccf60SVasundhara Volam desc = be_get_func_nic_desc(resp->func_param, desc_count); 3703abb93951SPadmanabh Ratnakar if (!desc) { 3704abb93951SPadmanabh Ratnakar status = -EINVAL; 3705abb93951SPadmanabh Ratnakar goto err; 3706abb93951SPadmanabh Ratnakar } 3707abb93951SPadmanabh Ratnakar 3708d5c18473SPadmanabh Ratnakar adapter->pf_number = desc->pf_num; 370992bf14abSSathya Perla be_copy_nic_desc(res, desc); 3710abb93951SPadmanabh Ratnakar } 3711abb93951SPadmanabh Ratnakar err: 3712abb93951SPadmanabh Ratnakar mutex_unlock(&adapter->mbox_lock); 3713d98ef50fSSuresh Reddy if (cmd.va) 3714e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, 3715e51000dbSSriharsha Basavapatna cmd.dma); 3716abb93951SPadmanabh Ratnakar return status; 3717abb93951SPadmanabh Ratnakar } 3718abb93951SPadmanabh Ratnakar 3719ba48c0c9SVasundhara Volam /* Will use MBOX only if MCCQ has not been created */ 372092bf14abSSathya Perla int be_cmd_get_profile_config(struct be_adapter *adapter, 3721f2858738SVasundhara Volam struct be_resources *res, u8 query, u8 domain) 3722a05f99dbSVasundhara Volam { 3723150d58c7SVasundhara Volam struct be_cmd_resp_get_profile_config *resp; 3724ba48c0c9SVasundhara Volam struct be_cmd_req_get_profile_config *req; 372510cccf60SVasundhara Volam struct be_nic_res_desc *vf_res; 3726150d58c7SVasundhara Volam struct be_pcie_res_desc *pcie; 3727f93f160bSVasundhara Volam struct be_port_res_desc *port; 3728150d58c7SVasundhara Volam struct be_nic_res_desc *nic; 3729ba48c0c9SVasundhara Volam struct be_mcc_wrb wrb = {0}; 3730a05f99dbSVasundhara Volam struct be_dma_mem cmd; 3731f2858738SVasundhara Volam u16 desc_count; 3732a05f99dbSVasundhara Volam int status; 3733a05f99dbSVasundhara Volam 3734a05f99dbSVasundhara Volam memset(&cmd, 0, sizeof(struct be_dma_mem)); 3735a05f99dbSVasundhara Volam cmd.size = sizeof(struct be_cmd_resp_get_profile_config); 3736e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 3737e51000dbSSriharsha Basavapatna GFP_ATOMIC); 3738150d58c7SVasundhara Volam if (!cmd.va) 3739a05f99dbSVasundhara Volam return -ENOMEM; 3740a05f99dbSVasundhara Volam 3741ba48c0c9SVasundhara Volam req = cmd.va; 3742ba48c0c9SVasundhara Volam be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3743ba48c0c9SVasundhara Volam OPCODE_COMMON_GET_PROFILE_CONFIG, 3744ba48c0c9SVasundhara Volam cmd.size, &wrb, &cmd); 3745ba48c0c9SVasundhara Volam 3746ba48c0c9SVasundhara Volam req->hdr.domain = domain; 3747ba48c0c9SVasundhara Volam if (!lancer_chip(adapter)) 3748ba48c0c9SVasundhara Volam req->hdr.version = 1; 3749ba48c0c9SVasundhara Volam req->type = ACTIVE_PROFILE_TYPE; 3750ba48c0c9SVasundhara Volam 3751f2858738SVasundhara Volam /* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the 3752f2858738SVasundhara Volam * descriptors with all bits set to "1" for the fields which can be 3753f2858738SVasundhara Volam * modified using SET_PROFILE_CONFIG cmd. 3754f2858738SVasundhara Volam */ 3755f2858738SVasundhara Volam if (query == RESOURCE_MODIFIABLE) 3756f2858738SVasundhara Volam req->type |= QUERY_MODIFIABLE_FIELDS_TYPE; 3757f2858738SVasundhara Volam 3758ba48c0c9SVasundhara Volam status = be_cmd_notify_wait(adapter, &wrb); 3759150d58c7SVasundhara Volam if (status) 3760abb93951SPadmanabh Ratnakar goto err; 3761150d58c7SVasundhara Volam 3762150d58c7SVasundhara Volam resp = cmd.va; 3763f2858738SVasundhara Volam desc_count = le16_to_cpu(resp->desc_count); 3764150d58c7SVasundhara Volam 3765150d58c7SVasundhara Volam pcie = be_get_pcie_desc(adapter->pdev->devfn, resp->func_param, 3766150d58c7SVasundhara Volam desc_count); 3767150d58c7SVasundhara Volam if (pcie) 376892bf14abSSathya Perla res->max_vfs = le16_to_cpu(pcie->num_vfs); 3769150d58c7SVasundhara Volam 3770f93f160bSVasundhara Volam port = be_get_port_desc(resp->func_param, desc_count); 3771f93f160bSVasundhara Volam if (port) 3772f93f160bSVasundhara Volam adapter->mc_type = port->mc_type; 3773f93f160bSVasundhara Volam 377410cccf60SVasundhara Volam nic = be_get_func_nic_desc(resp->func_param, desc_count); 377592bf14abSSathya Perla if (nic) 377692bf14abSSathya Perla be_copy_nic_desc(res, nic); 377792bf14abSSathya Perla 377810cccf60SVasundhara Volam vf_res = be_get_vft_desc(resp->func_param, desc_count); 377910cccf60SVasundhara Volam if (vf_res) 378010cccf60SVasundhara Volam res->vf_if_cap_flags = vf_res->cap_flags; 3781abb93951SPadmanabh Ratnakar err: 3782a05f99dbSVasundhara Volam if (cmd.va) 3783e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, 3784e51000dbSSriharsha Basavapatna cmd.dma); 3785abb93951SPadmanabh Ratnakar return status; 3786abb93951SPadmanabh Ratnakar } 3787abb93951SPadmanabh Ratnakar 3788bec84e6bSVasundhara Volam /* Will use MBOX only if MCCQ has not been created */ 3789bec84e6bSVasundhara Volam static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc, 3790bec84e6bSVasundhara Volam int size, int count, u8 version, u8 domain) 3791d5c18473SPadmanabh Ratnakar { 3792d5c18473SPadmanabh Ratnakar struct be_cmd_req_set_profile_config *req; 3793bec84e6bSVasundhara Volam struct be_mcc_wrb wrb = {0}; 3794bec84e6bSVasundhara Volam struct be_dma_mem cmd; 3795d5c18473SPadmanabh Ratnakar int status; 3796d5c18473SPadmanabh Ratnakar 3797bec84e6bSVasundhara Volam memset(&cmd, 0, sizeof(struct be_dma_mem)); 3798bec84e6bSVasundhara Volam cmd.size = sizeof(struct be_cmd_req_set_profile_config); 3799e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 3800e51000dbSSriharsha Basavapatna GFP_ATOMIC); 3801bec84e6bSVasundhara Volam if (!cmd.va) 3802bec84e6bSVasundhara Volam return -ENOMEM; 3803d5c18473SPadmanabh Ratnakar 3804bec84e6bSVasundhara Volam req = cmd.va; 3805d5c18473SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3806bec84e6bSVasundhara Volam OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size, 3807bec84e6bSVasundhara Volam &wrb, &cmd); 3808a401801cSSathya Perla req->hdr.version = version; 3809d5c18473SPadmanabh Ratnakar req->hdr.domain = domain; 3810bec84e6bSVasundhara Volam req->desc_count = cpu_to_le32(count); 3811a401801cSSathya Perla memcpy(req->desc, desc, size); 3812d5c18473SPadmanabh Ratnakar 3813bec84e6bSVasundhara Volam status = be_cmd_notify_wait(adapter, &wrb); 3814bec84e6bSVasundhara Volam 3815bec84e6bSVasundhara Volam if (cmd.va) 3816e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, 3817e51000dbSSriharsha Basavapatna cmd.dma); 3818d5c18473SPadmanabh Ratnakar return status; 3819d5c18473SPadmanabh Ratnakar } 3820d5c18473SPadmanabh Ratnakar 3821a401801cSSathya Perla /* Mark all fields invalid */ 3822bec84e6bSVasundhara Volam static void be_reset_nic_desc(struct be_nic_res_desc *nic) 3823a401801cSSathya Perla { 3824a401801cSSathya Perla memset(nic, 0, sizeof(*nic)); 3825a401801cSSathya Perla nic->unicast_mac_count = 0xFFFF; 3826a401801cSSathya Perla nic->mcc_count = 0xFFFF; 3827a401801cSSathya Perla nic->vlan_count = 0xFFFF; 3828a401801cSSathya Perla nic->mcast_mac_count = 0xFFFF; 3829a401801cSSathya Perla nic->txq_count = 0xFFFF; 3830a401801cSSathya Perla nic->rq_count = 0xFFFF; 3831a401801cSSathya Perla nic->rssq_count = 0xFFFF; 3832a401801cSSathya Perla nic->lro_count = 0xFFFF; 3833a401801cSSathya Perla nic->cq_count = 0xFFFF; 3834a401801cSSathya Perla nic->toe_conn_count = 0xFFFF; 3835a401801cSSathya Perla nic->eq_count = 0xFFFF; 38360f77ba73SRavikumar Nelavelli nic->iface_count = 0xFFFF; 3837a401801cSSathya Perla nic->link_param = 0xFF; 38380f77ba73SRavikumar Nelavelli nic->channel_id_param = cpu_to_le16(0xF000); 3839a401801cSSathya Perla nic->acpi_params = 0xFF; 3840a401801cSSathya Perla nic->wol_param = 0x0F; 38410f77ba73SRavikumar Nelavelli nic->tunnel_iface_count = 0xFFFF; 38420f77ba73SRavikumar Nelavelli nic->direct_tenant_iface_count = 0xFFFF; 3843bec84e6bSVasundhara Volam nic->bw_min = 0xFFFFFFFF; 3844a401801cSSathya Perla nic->bw_max = 0xFFFFFFFF; 3845a401801cSSathya Perla } 3846a401801cSSathya Perla 3847bec84e6bSVasundhara Volam /* Mark all fields invalid */ 3848bec84e6bSVasundhara Volam static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie) 3849bec84e6bSVasundhara Volam { 3850bec84e6bSVasundhara Volam memset(pcie, 0, sizeof(*pcie)); 3851bec84e6bSVasundhara Volam pcie->sriov_state = 0xFF; 3852bec84e6bSVasundhara Volam pcie->pf_state = 0xFF; 3853bec84e6bSVasundhara Volam pcie->pf_type = 0xFF; 3854bec84e6bSVasundhara Volam pcie->num_vfs = 0xFFFF; 3855bec84e6bSVasundhara Volam } 3856bec84e6bSVasundhara Volam 38570f77ba73SRavikumar Nelavelli int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed, 38580f77ba73SRavikumar Nelavelli u8 domain) 3859a401801cSSathya Perla { 3860a401801cSSathya Perla struct be_nic_res_desc nic_desc; 38610f77ba73SRavikumar Nelavelli u32 bw_percent; 38620f77ba73SRavikumar Nelavelli u16 version = 0; 38630f77ba73SRavikumar Nelavelli 38640f77ba73SRavikumar Nelavelli if (BE3_chip(adapter)) 38650f77ba73SRavikumar Nelavelli return be_cmd_set_qos(adapter, max_rate / 10, domain); 3866a401801cSSathya Perla 3867a401801cSSathya Perla be_reset_nic_desc(&nic_desc); 38680f77ba73SRavikumar Nelavelli nic_desc.pf_num = adapter->pf_number; 38690f77ba73SRavikumar Nelavelli nic_desc.vf_num = domain; 387058bdeaa6SKalesh AP nic_desc.bw_min = 0; 38710f77ba73SRavikumar Nelavelli if (lancer_chip(adapter)) { 3872a401801cSSathya Perla nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0; 3873a401801cSSathya Perla nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0; 3874a401801cSSathya Perla nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) | 3875a401801cSSathya Perla (1 << NOSV_SHIFT); 38760f77ba73SRavikumar Nelavelli nic_desc.bw_max = cpu_to_le32(max_rate / 10); 38770f77ba73SRavikumar Nelavelli } else { 38780f77ba73SRavikumar Nelavelli version = 1; 38790f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1; 38800f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 38810f77ba73SRavikumar Nelavelli nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT); 38820f77ba73SRavikumar Nelavelli bw_percent = max_rate ? (max_rate * 100) / link_speed : 100; 38830f77ba73SRavikumar Nelavelli nic_desc.bw_max = cpu_to_le32(bw_percent); 38840f77ba73SRavikumar Nelavelli } 3885a401801cSSathya Perla 3886a401801cSSathya Perla return be_cmd_set_profile_config(adapter, &nic_desc, 38870f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_len, 3888bec84e6bSVasundhara Volam 1, version, domain); 3889bec84e6bSVasundhara Volam } 3890bec84e6bSVasundhara Volam 3891f2858738SVasundhara Volam static void be_fill_vf_res_template(struct be_adapter *adapter, 3892f2858738SVasundhara Volam struct be_resources pool_res, 3893f2858738SVasundhara Volam u16 num_vfs, u16 num_vf_qs, 3894f2858738SVasundhara Volam struct be_nic_res_desc *nic_vft) 3895f2858738SVasundhara Volam { 3896f2858738SVasundhara Volam u32 vf_if_cap_flags = pool_res.vf_if_cap_flags; 3897f2858738SVasundhara Volam struct be_resources res_mod = {0}; 3898f2858738SVasundhara Volam 3899f2858738SVasundhara Volam /* Resource with fields set to all '1's by GET_PROFILE_CONFIG cmd, 3900f2858738SVasundhara Volam * which are modifiable using SET_PROFILE_CONFIG cmd. 3901f2858738SVasundhara Volam */ 3902f2858738SVasundhara Volam be_cmd_get_profile_config(adapter, &res_mod, RESOURCE_MODIFIABLE, 0); 3903f2858738SVasundhara Volam 3904f2858738SVasundhara Volam /* If RSS IFACE capability flags are modifiable for a VF, set the 3905f2858738SVasundhara Volam * capability flag as valid and set RSS and DEFQ_RSS IFACE flags if 3906f2858738SVasundhara Volam * more than 1 RSSQ is available for a VF. 3907f2858738SVasundhara Volam * Otherwise, provision only 1 queue pair for VF. 3908f2858738SVasundhara Volam */ 3909f2858738SVasundhara Volam if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_RSS) { 3910f2858738SVasundhara Volam nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT); 3911f2858738SVasundhara Volam if (num_vf_qs > 1) { 3912f2858738SVasundhara Volam vf_if_cap_flags |= BE_IF_FLAGS_RSS; 3913f2858738SVasundhara Volam if (pool_res.if_cap_flags & BE_IF_FLAGS_DEFQ_RSS) 3914f2858738SVasundhara Volam vf_if_cap_flags |= BE_IF_FLAGS_DEFQ_RSS; 3915f2858738SVasundhara Volam } else { 3916f2858738SVasundhara Volam vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS | 3917f2858738SVasundhara Volam BE_IF_FLAGS_DEFQ_RSS); 3918f2858738SVasundhara Volam } 3919f2858738SVasundhara Volam 3920f2858738SVasundhara Volam nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags); 3921f2858738SVasundhara Volam } else { 3922f2858738SVasundhara Volam num_vf_qs = 1; 3923f2858738SVasundhara Volam } 3924f2858738SVasundhara Volam 3925f2858738SVasundhara Volam nic_vft->rq_count = cpu_to_le16(num_vf_qs); 3926f2858738SVasundhara Volam nic_vft->txq_count = cpu_to_le16(num_vf_qs); 3927f2858738SVasundhara Volam nic_vft->rssq_count = cpu_to_le16(num_vf_qs); 3928f2858738SVasundhara Volam nic_vft->cq_count = cpu_to_le16(pool_res.max_cq_count / 3929f2858738SVasundhara Volam (num_vfs + 1)); 3930f2858738SVasundhara Volam 3931f2858738SVasundhara Volam /* Distribute unicast MACs, VLANs, IFACE count and MCCQ count equally 3932f2858738SVasundhara Volam * among the PF and it's VFs, if the fields are changeable 3933f2858738SVasundhara Volam */ 3934f2858738SVasundhara Volam if (res_mod.max_uc_mac == FIELD_MODIFIABLE) 3935f2858738SVasundhara Volam nic_vft->unicast_mac_count = cpu_to_le16(pool_res.max_uc_mac / 3936f2858738SVasundhara Volam (num_vfs + 1)); 3937f2858738SVasundhara Volam 3938f2858738SVasundhara Volam if (res_mod.max_vlans == FIELD_MODIFIABLE) 3939f2858738SVasundhara Volam nic_vft->vlan_count = cpu_to_le16(pool_res.max_vlans / 3940f2858738SVasundhara Volam (num_vfs + 1)); 3941f2858738SVasundhara Volam 3942f2858738SVasundhara Volam if (res_mod.max_iface_count == FIELD_MODIFIABLE) 3943f2858738SVasundhara Volam nic_vft->iface_count = cpu_to_le16(pool_res.max_iface_count / 3944f2858738SVasundhara Volam (num_vfs + 1)); 3945f2858738SVasundhara Volam 3946f2858738SVasundhara Volam if (res_mod.max_mcc_count == FIELD_MODIFIABLE) 3947f2858738SVasundhara Volam nic_vft->mcc_count = cpu_to_le16(pool_res.max_mcc_count / 3948f2858738SVasundhara Volam (num_vfs + 1)); 3949f2858738SVasundhara Volam } 3950f2858738SVasundhara Volam 3951bec84e6bSVasundhara Volam int be_cmd_set_sriov_config(struct be_adapter *adapter, 3952f2858738SVasundhara Volam struct be_resources pool_res, u16 num_vfs, 3953f2858738SVasundhara Volam u16 num_vf_qs) 3954bec84e6bSVasundhara Volam { 3955bec84e6bSVasundhara Volam struct { 3956bec84e6bSVasundhara Volam struct be_pcie_res_desc pcie; 3957bec84e6bSVasundhara Volam struct be_nic_res_desc nic_vft; 3958bec84e6bSVasundhara Volam } __packed desc; 3959bec84e6bSVasundhara Volam 3960bec84e6bSVasundhara Volam /* PF PCIE descriptor */ 3961bec84e6bSVasundhara Volam be_reset_pcie_desc(&desc.pcie); 3962bec84e6bSVasundhara Volam desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1; 3963bec84e6bSVasundhara Volam desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 3964f2858738SVasundhara Volam desc.pcie.flags = BIT(IMM_SHIFT) | BIT(NOSV_SHIFT); 3965bec84e6bSVasundhara Volam desc.pcie.pf_num = adapter->pdev->devfn; 3966bec84e6bSVasundhara Volam desc.pcie.sriov_state = num_vfs ? 1 : 0; 3967bec84e6bSVasundhara Volam desc.pcie.num_vfs = cpu_to_le16(num_vfs); 3968bec84e6bSVasundhara Volam 3969bec84e6bSVasundhara Volam /* VF NIC Template descriptor */ 3970bec84e6bSVasundhara Volam be_reset_nic_desc(&desc.nic_vft); 3971bec84e6bSVasundhara Volam desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1; 3972bec84e6bSVasundhara Volam desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 3973f2858738SVasundhara Volam desc.nic_vft.flags = BIT(VFT_SHIFT) | BIT(IMM_SHIFT) | BIT(NOSV_SHIFT); 3974bec84e6bSVasundhara Volam desc.nic_vft.pf_num = adapter->pdev->devfn; 3975bec84e6bSVasundhara Volam desc.nic_vft.vf_num = 0; 3976bec84e6bSVasundhara Volam 3977f2858738SVasundhara Volam be_fill_vf_res_template(adapter, pool_res, num_vfs, num_vf_qs, 3978f2858738SVasundhara Volam &desc.nic_vft); 3979bec84e6bSVasundhara Volam 3980bec84e6bSVasundhara Volam return be_cmd_set_profile_config(adapter, &desc, 3981bec84e6bSVasundhara Volam 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0); 3982a401801cSSathya Perla } 3983a401801cSSathya Perla 3984a401801cSSathya Perla int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) 3985a401801cSSathya Perla { 3986a401801cSSathya Perla struct be_mcc_wrb *wrb; 3987a401801cSSathya Perla struct be_cmd_req_manage_iface_filters *req; 3988a401801cSSathya Perla int status; 3989a401801cSSathya Perla 3990a401801cSSathya Perla if (iface == 0xFFFFFFFF) 3991a401801cSSathya Perla return -1; 3992a401801cSSathya Perla 3993a401801cSSathya Perla spin_lock_bh(&adapter->mcc_lock); 3994a401801cSSathya Perla 3995a401801cSSathya Perla wrb = wrb_from_mccq(adapter); 3996a401801cSSathya Perla if (!wrb) { 3997a401801cSSathya Perla status = -EBUSY; 3998a401801cSSathya Perla goto err; 3999a401801cSSathya Perla } 4000a401801cSSathya Perla req = embedded_payload(wrb); 4001a401801cSSathya Perla 4002a401801cSSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4003a401801cSSathya Perla OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req), 4004a401801cSSathya Perla wrb, NULL); 4005a401801cSSathya Perla req->op = op; 4006a401801cSSathya Perla req->target_iface_id = cpu_to_le32(iface); 4007a401801cSSathya Perla 4008a401801cSSathya Perla status = be_mcc_notify_wait(adapter); 4009a401801cSSathya Perla err: 4010a401801cSSathya Perla spin_unlock_bh(&adapter->mcc_lock); 4011a401801cSSathya Perla return status; 4012a401801cSSathya Perla } 4013a401801cSSathya Perla 4014a401801cSSathya Perla int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port) 4015a401801cSSathya Perla { 4016a401801cSSathya Perla struct be_port_res_desc port_desc; 4017a401801cSSathya Perla 4018a401801cSSathya Perla memset(&port_desc, 0, sizeof(port_desc)); 4019a401801cSSathya Perla port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1; 4020a401801cSSathya Perla port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 4021a401801cSSathya Perla port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT); 4022a401801cSSathya Perla port_desc.link_num = adapter->hba_port_num; 4023a401801cSSathya Perla if (port) { 4024a401801cSSathya Perla port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) | 4025a401801cSSathya Perla (1 << RCVID_SHIFT); 4026a401801cSSathya Perla port_desc.nv_port = swab16(port); 4027a401801cSSathya Perla } else { 4028a401801cSSathya Perla port_desc.nv_flags = NV_TYPE_DISABLED; 4029a401801cSSathya Perla port_desc.nv_port = 0; 4030a401801cSSathya Perla } 4031a401801cSSathya Perla 4032a401801cSSathya Perla return be_cmd_set_profile_config(adapter, &port_desc, 4033bec84e6bSVasundhara Volam RESOURCE_DESC_SIZE_V1, 1, 1, 0); 4034a401801cSSathya Perla } 4035a401801cSSathya Perla 40364c876616SSathya Perla int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, 40374c876616SSathya Perla int vf_num) 40384c876616SSathya Perla { 40394c876616SSathya Perla struct be_mcc_wrb *wrb; 40404c876616SSathya Perla struct be_cmd_req_get_iface_list *req; 40414c876616SSathya Perla struct be_cmd_resp_get_iface_list *resp; 40424c876616SSathya Perla int status; 40434c876616SSathya Perla 40444c876616SSathya Perla spin_lock_bh(&adapter->mcc_lock); 40454c876616SSathya Perla 40464c876616SSathya Perla wrb = wrb_from_mccq(adapter); 40474c876616SSathya Perla if (!wrb) { 40484c876616SSathya Perla status = -EBUSY; 40494c876616SSathya Perla goto err; 40504c876616SSathya Perla } 40514c876616SSathya Perla req = embedded_payload(wrb); 40524c876616SSathya Perla 40534c876616SSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 40544c876616SSathya Perla OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp), 40554c876616SSathya Perla wrb, NULL); 40564c876616SSathya Perla req->hdr.domain = vf_num + 1; 40574c876616SSathya Perla 40584c876616SSathya Perla status = be_mcc_notify_wait(adapter); 40594c876616SSathya Perla if (!status) { 40604c876616SSathya Perla resp = (struct be_cmd_resp_get_iface_list *)req; 40614c876616SSathya Perla vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id); 40624c876616SSathya Perla } 40634c876616SSathya Perla 40644c876616SSathya Perla err: 40654c876616SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 40664c876616SSathya Perla return status; 40674c876616SSathya Perla } 40684c876616SSathya Perla 40695c510811SSomnath Kotur static int lancer_wait_idle(struct be_adapter *adapter) 40705c510811SSomnath Kotur { 40715c510811SSomnath Kotur #define SLIPORT_IDLE_TIMEOUT 30 40725c510811SSomnath Kotur u32 reg_val; 40735c510811SSomnath Kotur int status = 0, i; 40745c510811SSomnath Kotur 40755c510811SSomnath Kotur for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) { 40765c510811SSomnath Kotur reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET); 40775c510811SSomnath Kotur if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0) 40785c510811SSomnath Kotur break; 40795c510811SSomnath Kotur 40805c510811SSomnath Kotur ssleep(1); 40815c510811SSomnath Kotur } 40825c510811SSomnath Kotur 40835c510811SSomnath Kotur if (i == SLIPORT_IDLE_TIMEOUT) 40845c510811SSomnath Kotur status = -1; 40855c510811SSomnath Kotur 40865c510811SSomnath Kotur return status; 40875c510811SSomnath Kotur } 40885c510811SSomnath Kotur 40895c510811SSomnath Kotur int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask) 40905c510811SSomnath Kotur { 40915c510811SSomnath Kotur int status = 0; 40925c510811SSomnath Kotur 40935c510811SSomnath Kotur status = lancer_wait_idle(adapter); 40945c510811SSomnath Kotur if (status) 40955c510811SSomnath Kotur return status; 40965c510811SSomnath Kotur 40975c510811SSomnath Kotur iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET); 40985c510811SSomnath Kotur 40995c510811SSomnath Kotur return status; 41005c510811SSomnath Kotur } 41015c510811SSomnath Kotur 41025c510811SSomnath Kotur /* Routine to check whether dump image is present or not */ 41035c510811SSomnath Kotur bool dump_present(struct be_adapter *adapter) 41045c510811SSomnath Kotur { 41055c510811SSomnath Kotur u32 sliport_status = 0; 41065c510811SSomnath Kotur 41075c510811SSomnath Kotur sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); 41085c510811SSomnath Kotur return !!(sliport_status & SLIPORT_STATUS_DIP_MASK); 41095c510811SSomnath Kotur } 41105c510811SSomnath Kotur 41115c510811SSomnath Kotur int lancer_initiate_dump(struct be_adapter *adapter) 41125c510811SSomnath Kotur { 4113f0613380SKalesh AP struct device *dev = &adapter->pdev->dev; 41145c510811SSomnath Kotur int status; 41155c510811SSomnath Kotur 4116f0613380SKalesh AP if (dump_present(adapter)) { 4117f0613380SKalesh AP dev_info(dev, "Previous dump not cleared, not forcing dump\n"); 4118f0613380SKalesh AP return -EEXIST; 4119f0613380SKalesh AP } 4120f0613380SKalesh AP 41215c510811SSomnath Kotur /* give firmware reset and diagnostic dump */ 41225c510811SSomnath Kotur status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK | 41235c510811SSomnath Kotur PHYSDEV_CONTROL_DD_MASK); 41245c510811SSomnath Kotur if (status < 0) { 4125f0613380SKalesh AP dev_err(dev, "FW reset failed\n"); 41265c510811SSomnath Kotur return status; 41275c510811SSomnath Kotur } 41285c510811SSomnath Kotur 41295c510811SSomnath Kotur status = lancer_wait_idle(adapter); 41305c510811SSomnath Kotur if (status) 41315c510811SSomnath Kotur return status; 41325c510811SSomnath Kotur 41335c510811SSomnath Kotur if (!dump_present(adapter)) { 4134f0613380SKalesh AP dev_err(dev, "FW dump not generated\n"); 4135f0613380SKalesh AP return -EIO; 41365c510811SSomnath Kotur } 41375c510811SSomnath Kotur 41385c510811SSomnath Kotur return 0; 41395c510811SSomnath Kotur } 41405c510811SSomnath Kotur 4141f0613380SKalesh AP int lancer_delete_dump(struct be_adapter *adapter) 4142f0613380SKalesh AP { 4143f0613380SKalesh AP int status; 4144f0613380SKalesh AP 4145f0613380SKalesh AP status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE); 4146f0613380SKalesh AP return be_cmd_status(status); 4147f0613380SKalesh AP } 4148f0613380SKalesh AP 4149dcf7ebbaSPadmanabh Ratnakar /* Uses sync mcc */ 4150dcf7ebbaSPadmanabh Ratnakar int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) 4151dcf7ebbaSPadmanabh Ratnakar { 4152dcf7ebbaSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 4153dcf7ebbaSPadmanabh Ratnakar struct be_cmd_enable_disable_vf *req; 4154dcf7ebbaSPadmanabh Ratnakar int status; 4155dcf7ebbaSPadmanabh Ratnakar 41560599863dSVasundhara Volam if (BEx_chip(adapter)) 4157dcf7ebbaSPadmanabh Ratnakar return 0; 4158dcf7ebbaSPadmanabh Ratnakar 4159dcf7ebbaSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 4160dcf7ebbaSPadmanabh Ratnakar 4161dcf7ebbaSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 4162dcf7ebbaSPadmanabh Ratnakar if (!wrb) { 4163dcf7ebbaSPadmanabh Ratnakar status = -EBUSY; 4164dcf7ebbaSPadmanabh Ratnakar goto err; 4165dcf7ebbaSPadmanabh Ratnakar } 4166dcf7ebbaSPadmanabh Ratnakar 4167dcf7ebbaSPadmanabh Ratnakar req = embedded_payload(wrb); 4168dcf7ebbaSPadmanabh Ratnakar 4169dcf7ebbaSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4170dcf7ebbaSPadmanabh Ratnakar OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req), 4171dcf7ebbaSPadmanabh Ratnakar wrb, NULL); 4172dcf7ebbaSPadmanabh Ratnakar 4173dcf7ebbaSPadmanabh Ratnakar req->hdr.domain = domain; 4174dcf7ebbaSPadmanabh Ratnakar req->enable = 1; 4175dcf7ebbaSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 4176dcf7ebbaSPadmanabh Ratnakar err: 4177dcf7ebbaSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 4178dcf7ebbaSPadmanabh Ratnakar return status; 4179dcf7ebbaSPadmanabh Ratnakar } 4180dcf7ebbaSPadmanabh Ratnakar 418168c45a2dSSomnath Kotur int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable) 418268c45a2dSSomnath Kotur { 418368c45a2dSSomnath Kotur struct be_mcc_wrb *wrb; 418468c45a2dSSomnath Kotur struct be_cmd_req_intr_set *req; 418568c45a2dSSomnath Kotur int status; 418668c45a2dSSomnath Kotur 418768c45a2dSSomnath Kotur if (mutex_lock_interruptible(&adapter->mbox_lock)) 418868c45a2dSSomnath Kotur return -1; 418968c45a2dSSomnath Kotur 419068c45a2dSSomnath Kotur wrb = wrb_from_mbox(adapter); 419168c45a2dSSomnath Kotur 419268c45a2dSSomnath Kotur req = embedded_payload(wrb); 419368c45a2dSSomnath Kotur 419468c45a2dSSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 419568c45a2dSSomnath Kotur OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req), 419668c45a2dSSomnath Kotur wrb, NULL); 419768c45a2dSSomnath Kotur 419868c45a2dSSomnath Kotur req->intr_enabled = intr_enable; 419968c45a2dSSomnath Kotur 420068c45a2dSSomnath Kotur status = be_mbox_notify_wait(adapter); 420168c45a2dSSomnath Kotur 420268c45a2dSSomnath Kotur mutex_unlock(&adapter->mbox_lock); 420368c45a2dSSomnath Kotur return status; 420468c45a2dSSomnath Kotur } 420568c45a2dSSomnath Kotur 4206542963b7SVasundhara Volam /* Uses MBOX */ 4207542963b7SVasundhara Volam int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id) 4208542963b7SVasundhara Volam { 4209542963b7SVasundhara Volam struct be_cmd_req_get_active_profile *req; 4210542963b7SVasundhara Volam struct be_mcc_wrb *wrb; 4211542963b7SVasundhara Volam int status; 4212542963b7SVasundhara Volam 4213542963b7SVasundhara Volam if (mutex_lock_interruptible(&adapter->mbox_lock)) 4214542963b7SVasundhara Volam return -1; 4215542963b7SVasundhara Volam 4216542963b7SVasundhara Volam wrb = wrb_from_mbox(adapter); 4217542963b7SVasundhara Volam if (!wrb) { 4218542963b7SVasundhara Volam status = -EBUSY; 4219542963b7SVasundhara Volam goto err; 4220542963b7SVasundhara Volam } 4221542963b7SVasundhara Volam 4222542963b7SVasundhara Volam req = embedded_payload(wrb); 4223542963b7SVasundhara Volam 4224542963b7SVasundhara Volam be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4225542963b7SVasundhara Volam OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req), 4226542963b7SVasundhara Volam wrb, NULL); 4227542963b7SVasundhara Volam 4228542963b7SVasundhara Volam status = be_mbox_notify_wait(adapter); 4229542963b7SVasundhara Volam if (!status) { 4230542963b7SVasundhara Volam struct be_cmd_resp_get_active_profile *resp = 4231542963b7SVasundhara Volam embedded_payload(wrb); 423203d28ffeSKalesh AP 4233542963b7SVasundhara Volam *profile_id = le16_to_cpu(resp->active_profile_id); 4234542963b7SVasundhara Volam } 4235542963b7SVasundhara Volam 4236542963b7SVasundhara Volam err: 4237542963b7SVasundhara Volam mutex_unlock(&adapter->mbox_lock); 4238542963b7SVasundhara Volam return status; 4239542963b7SVasundhara Volam } 4240542963b7SVasundhara Volam 4241bdce2ad7SSuresh Reddy int be_cmd_set_logical_link_config(struct be_adapter *adapter, 4242bdce2ad7SSuresh Reddy int link_state, u8 domain) 4243bdce2ad7SSuresh Reddy { 4244bdce2ad7SSuresh Reddy struct be_mcc_wrb *wrb; 4245bdce2ad7SSuresh Reddy struct be_cmd_req_set_ll_link *req; 4246bdce2ad7SSuresh Reddy int status; 4247bdce2ad7SSuresh Reddy 4248bdce2ad7SSuresh Reddy if (BEx_chip(adapter) || lancer_chip(adapter)) 424918fd6025SKalesh AP return -EOPNOTSUPP; 4250bdce2ad7SSuresh Reddy 4251bdce2ad7SSuresh Reddy spin_lock_bh(&adapter->mcc_lock); 4252bdce2ad7SSuresh Reddy 4253bdce2ad7SSuresh Reddy wrb = wrb_from_mccq(adapter); 4254bdce2ad7SSuresh Reddy if (!wrb) { 4255bdce2ad7SSuresh Reddy status = -EBUSY; 4256bdce2ad7SSuresh Reddy goto err; 4257bdce2ad7SSuresh Reddy } 4258bdce2ad7SSuresh Reddy 4259bdce2ad7SSuresh Reddy req = embedded_payload(wrb); 4260bdce2ad7SSuresh Reddy 4261bdce2ad7SSuresh Reddy be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4262bdce2ad7SSuresh Reddy OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG, 4263bdce2ad7SSuresh Reddy sizeof(*req), wrb, NULL); 4264bdce2ad7SSuresh Reddy 4265bdce2ad7SSuresh Reddy req->hdr.version = 1; 4266bdce2ad7SSuresh Reddy req->hdr.domain = domain; 4267bdce2ad7SSuresh Reddy 4268bdce2ad7SSuresh Reddy if (link_state == IFLA_VF_LINK_STATE_ENABLE) 4269bdce2ad7SSuresh Reddy req->link_config |= 1; 4270bdce2ad7SSuresh Reddy 4271bdce2ad7SSuresh Reddy if (link_state == IFLA_VF_LINK_STATE_AUTO) 4272bdce2ad7SSuresh Reddy req->link_config |= 1 << PLINK_TRACK_SHIFT; 4273bdce2ad7SSuresh Reddy 4274bdce2ad7SSuresh Reddy status = be_mcc_notify_wait(adapter); 4275bdce2ad7SSuresh Reddy err: 4276bdce2ad7SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 4277bdce2ad7SSuresh Reddy return status; 4278bdce2ad7SSuresh Reddy } 4279bdce2ad7SSuresh Reddy 42806a4ab669SParav Pandit int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, 42816a4ab669SParav Pandit int wrb_payload_size, u16 *cmd_status, u16 *ext_status) 42826a4ab669SParav Pandit { 42836a4ab669SParav Pandit struct be_adapter *adapter = netdev_priv(netdev_handle); 42846a4ab669SParav Pandit struct be_mcc_wrb *wrb; 42856a4ab669SParav Pandit struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload; 42866a4ab669SParav Pandit struct be_cmd_req_hdr *req; 42876a4ab669SParav Pandit struct be_cmd_resp_hdr *resp; 42886a4ab669SParav Pandit int status; 42896a4ab669SParav Pandit 42906a4ab669SParav Pandit spin_lock_bh(&adapter->mcc_lock); 42916a4ab669SParav Pandit 42926a4ab669SParav Pandit wrb = wrb_from_mccq(adapter); 42936a4ab669SParav Pandit if (!wrb) { 42946a4ab669SParav Pandit status = -EBUSY; 42956a4ab669SParav Pandit goto err; 42966a4ab669SParav Pandit } 42976a4ab669SParav Pandit req = embedded_payload(wrb); 42986a4ab669SParav Pandit resp = embedded_payload(wrb); 42996a4ab669SParav Pandit 43006a4ab669SParav Pandit be_wrb_cmd_hdr_prepare(req, hdr->subsystem, 43016a4ab669SParav Pandit hdr->opcode, wrb_payload_size, wrb, NULL); 43026a4ab669SParav Pandit memcpy(req, wrb_payload, wrb_payload_size); 43036a4ab669SParav Pandit be_dws_cpu_to_le(req, wrb_payload_size); 43046a4ab669SParav Pandit 43056a4ab669SParav Pandit status = be_mcc_notify_wait(adapter); 43066a4ab669SParav Pandit if (cmd_status) 43076a4ab669SParav Pandit *cmd_status = (status & 0xffff); 43086a4ab669SParav Pandit if (ext_status) 43096a4ab669SParav Pandit *ext_status = 0; 43106a4ab669SParav Pandit memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length); 43116a4ab669SParav Pandit be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length); 43126a4ab669SParav Pandit err: 43136a4ab669SParav Pandit spin_unlock_bh(&adapter->mcc_lock); 43146a4ab669SParav Pandit return status; 43156a4ab669SParav Pandit } 43166a4ab669SParav Pandit EXPORT_SYMBOL(be_roce_mcc_cmd); 4317