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 919aebddd1SJeff Kirsher static void be_mcc_notify(struct be_adapter *adapter) 929aebddd1SJeff Kirsher { 939aebddd1SJeff Kirsher struct be_queue_info *mccq = &adapter->mcc_obj.q; 949aebddd1SJeff Kirsher u32 val = 0; 959aebddd1SJeff Kirsher 96954f6825SVenkata Duvvuru if (be_check_error(adapter, BE_ERROR_ANY)) 979aebddd1SJeff Kirsher return; 989aebddd1SJeff Kirsher 999aebddd1SJeff Kirsher val |= mccq->id & DB_MCCQ_RING_ID_MASK; 1009aebddd1SJeff Kirsher val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; 1019aebddd1SJeff Kirsher 1029aebddd1SJeff Kirsher wmb(); 1039aebddd1SJeff Kirsher iowrite32(val, adapter->db + DB_MCCQ_OFFSET); 1049aebddd1SJeff Kirsher } 1059aebddd1SJeff Kirsher 1069aebddd1SJeff Kirsher /* To check if valid bit is set, check the entire word as we don't know 1079aebddd1SJeff Kirsher * the endianness of the data (old entry is host endian while a new entry is 1089aebddd1SJeff Kirsher * little endian) */ 1099aebddd1SJeff Kirsher static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) 1109aebddd1SJeff Kirsher { 1119e9ff4b7SSathya Perla u32 flags; 1129e9ff4b7SSathya Perla 1139aebddd1SJeff Kirsher if (compl->flags != 0) { 1149e9ff4b7SSathya Perla flags = le32_to_cpu(compl->flags); 1159e9ff4b7SSathya Perla if (flags & CQE_FLAGS_VALID_MASK) { 1169e9ff4b7SSathya Perla compl->flags = flags; 1179aebddd1SJeff Kirsher return true; 1189aebddd1SJeff Kirsher } 1199aebddd1SJeff Kirsher } 1209e9ff4b7SSathya Perla return false; 1219e9ff4b7SSathya Perla } 1229aebddd1SJeff Kirsher 1239aebddd1SJeff Kirsher /* Need to reset the entire word that houses the valid bit */ 1249aebddd1SJeff Kirsher static inline void be_mcc_compl_use(struct be_mcc_compl *compl) 1259aebddd1SJeff Kirsher { 1269aebddd1SJeff Kirsher compl->flags = 0; 1279aebddd1SJeff Kirsher } 1289aebddd1SJeff Kirsher 129652bf646SPadmanabh Ratnakar static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1) 130652bf646SPadmanabh Ratnakar { 131652bf646SPadmanabh Ratnakar unsigned long addr; 132652bf646SPadmanabh Ratnakar 133652bf646SPadmanabh Ratnakar addr = tag1; 134652bf646SPadmanabh Ratnakar addr = ((addr << 16) << 16) | tag0; 135652bf646SPadmanabh Ratnakar return (void *)addr; 136652bf646SPadmanabh Ratnakar } 137652bf646SPadmanabh Ratnakar 1384c60005fSKalesh AP static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status) 1394c60005fSKalesh AP { 1404c60005fSKalesh AP if (base_status == MCC_STATUS_NOT_SUPPORTED || 1414c60005fSKalesh AP base_status == MCC_STATUS_ILLEGAL_REQUEST || 1424c60005fSKalesh AP addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES || 14377be8c1cSKalesh AP addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS || 1444c60005fSKalesh AP (opcode == OPCODE_COMMON_WRITE_FLASHROM && 1454c60005fSKalesh AP (base_status == MCC_STATUS_ILLEGAL_FIELD || 1464c60005fSKalesh AP addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH))) 1474c60005fSKalesh AP return true; 1484c60005fSKalesh AP else 1494c60005fSKalesh AP return false; 1504c60005fSKalesh AP } 1514c60005fSKalesh AP 152559b633fSSathya Perla /* Place holder for all the async MCC cmds wherein the caller is not in a busy 153559b633fSSathya Perla * loop (has not issued be_mcc_notify_wait()) 154559b633fSSathya Perla */ 155559b633fSSathya Perla static void be_async_cmd_process(struct be_adapter *adapter, 156559b633fSSathya Perla struct be_mcc_compl *compl, 157559b633fSSathya Perla struct be_cmd_resp_hdr *resp_hdr) 158559b633fSSathya Perla { 159559b633fSSathya Perla enum mcc_base_status base_status = base_status(compl->status); 160559b633fSSathya Perla u8 opcode = 0, subsystem = 0; 161559b633fSSathya Perla 162559b633fSSathya Perla if (resp_hdr) { 163559b633fSSathya Perla opcode = resp_hdr->opcode; 164559b633fSSathya Perla subsystem = resp_hdr->subsystem; 165559b633fSSathya Perla } 166559b633fSSathya Perla 167559b633fSSathya Perla if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST && 168559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_LOWLEVEL) { 169559b633fSSathya Perla complete(&adapter->et_cmd_compl); 170559b633fSSathya Perla return; 171559b633fSSathya Perla } 172559b633fSSathya Perla 173559b633fSSathya Perla if ((opcode == OPCODE_COMMON_WRITE_FLASHROM || 174559b633fSSathya Perla opcode == OPCODE_COMMON_WRITE_OBJECT) && 175559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_COMMON) { 176559b633fSSathya Perla adapter->flash_status = compl->status; 177559b633fSSathya Perla complete(&adapter->et_cmd_compl); 178559b633fSSathya Perla return; 179559b633fSSathya Perla } 180559b633fSSathya Perla 181559b633fSSathya Perla if ((opcode == OPCODE_ETH_GET_STATISTICS || 182559b633fSSathya Perla opcode == OPCODE_ETH_GET_PPORT_STATS) && 183559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_ETH && 184559b633fSSathya Perla base_status == MCC_STATUS_SUCCESS) { 185559b633fSSathya Perla be_parse_stats(adapter); 186559b633fSSathya Perla adapter->stats_cmd_sent = false; 187559b633fSSathya Perla return; 188559b633fSSathya Perla } 189559b633fSSathya Perla 190559b633fSSathya Perla if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES && 191559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_COMMON) { 192559b633fSSathya Perla if (base_status == MCC_STATUS_SUCCESS) { 193559b633fSSathya Perla struct be_cmd_resp_get_cntl_addnl_attribs *resp = 194559b633fSSathya Perla (void *)resp_hdr; 19529e9122bSVenkata Duvvuru adapter->hwmon_info.be_on_die_temp = 196559b633fSSathya Perla resp->on_die_temperature; 197559b633fSSathya Perla } else { 198559b633fSSathya Perla adapter->be_get_temp_freq = 0; 19929e9122bSVenkata Duvvuru adapter->hwmon_info.be_on_die_temp = 20029e9122bSVenkata Duvvuru BE_INVALID_DIE_TEMP; 201559b633fSSathya Perla } 202559b633fSSathya Perla return; 203559b633fSSathya Perla } 204559b633fSSathya Perla } 205559b633fSSathya Perla 2069aebddd1SJeff Kirsher static int be_mcc_compl_process(struct be_adapter *adapter, 2079aebddd1SJeff Kirsher struct be_mcc_compl *compl) 2089aebddd1SJeff Kirsher { 2094c60005fSKalesh AP enum mcc_base_status base_status; 2104c60005fSKalesh AP enum mcc_addl_status addl_status; 211652bf646SPadmanabh Ratnakar struct be_cmd_resp_hdr *resp_hdr; 212652bf646SPadmanabh Ratnakar u8 opcode = 0, subsystem = 0; 2139aebddd1SJeff Kirsher 2149aebddd1SJeff Kirsher /* Just swap the status to host endian; mcc tag is opaquely copied 2159aebddd1SJeff Kirsher * from mcc_wrb */ 2169aebddd1SJeff Kirsher be_dws_le_to_cpu(compl, 4); 2179aebddd1SJeff Kirsher 2184c60005fSKalesh AP base_status = base_status(compl->status); 2194c60005fSKalesh AP addl_status = addl_status(compl->status); 22096c9b2e4SVasundhara Volam 221652bf646SPadmanabh Ratnakar resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1); 222652bf646SPadmanabh Ratnakar if (resp_hdr) { 223652bf646SPadmanabh Ratnakar opcode = resp_hdr->opcode; 224652bf646SPadmanabh Ratnakar subsystem = resp_hdr->subsystem; 225652bf646SPadmanabh Ratnakar } 226652bf646SPadmanabh Ratnakar 227559b633fSSathya Perla be_async_cmd_process(adapter, compl, resp_hdr); 2285eeff635SSuresh Reddy 229559b633fSSathya Perla if (base_status != MCC_STATUS_SUCCESS && 230559b633fSSathya Perla !be_skip_err_log(opcode, base_status, addl_status)) { 2314c60005fSKalesh AP if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { 23297f1d8cdSVasundhara Volam dev_warn(&adapter->pdev->dev, 233522609f2SVasundhara Volam "VF is not privileged to issue opcode %d-%d\n", 23497f1d8cdSVasundhara Volam opcode, subsystem); 2359aebddd1SJeff Kirsher } else { 23697f1d8cdSVasundhara Volam dev_err(&adapter->pdev->dev, 23797f1d8cdSVasundhara Volam "opcode %d-%d failed:status %d-%d\n", 2384c60005fSKalesh AP opcode, subsystem, base_status, addl_status); 2399aebddd1SJeff Kirsher } 2409aebddd1SJeff Kirsher } 2414c60005fSKalesh AP return compl->status; 2429aebddd1SJeff Kirsher } 2439aebddd1SJeff Kirsher 2449aebddd1SJeff Kirsher /* Link state evt is a string of bytes; no need for endian swapping */ 2459aebddd1SJeff Kirsher static void be_async_link_state_process(struct be_adapter *adapter, 2463acf19d9SSathya Perla struct be_mcc_compl *compl) 2479aebddd1SJeff Kirsher { 2483acf19d9SSathya Perla struct be_async_event_link_state *evt = 2493acf19d9SSathya Perla (struct be_async_event_link_state *)compl; 2503acf19d9SSathya Perla 251b236916aSAjit Khaparde /* When link status changes, link speed must be re-queried from FW */ 25242f11cf2SAjit Khaparde adapter->phy.link_speed = -1; 253b236916aSAjit Khaparde 254bdce2ad7SSuresh Reddy /* On BEx the FW does not send a separate link status 255bdce2ad7SSuresh Reddy * notification for physical and logical link. 256bdce2ad7SSuresh Reddy * On other chips just process the logical link 257bdce2ad7SSuresh Reddy * status notification 258bdce2ad7SSuresh Reddy */ 259bdce2ad7SSuresh Reddy if (!BEx_chip(adapter) && 2602e177a5cSPadmanabh Ratnakar !(evt->port_link_status & LOGICAL_LINK_STATUS_MASK)) 2612e177a5cSPadmanabh Ratnakar return; 2622e177a5cSPadmanabh Ratnakar 263b236916aSAjit Khaparde /* For the initial link status do not rely on the ASYNC event as 264b236916aSAjit Khaparde * it may not be received in some cases. 265b236916aSAjit Khaparde */ 266b236916aSAjit Khaparde if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT) 267bdce2ad7SSuresh Reddy be_link_status_update(adapter, 268bdce2ad7SSuresh Reddy evt->port_link_status & LINK_STATUS_MASK); 2699aebddd1SJeff Kirsher } 2709aebddd1SJeff Kirsher 27121252377SVasundhara Volam static void be_async_port_misconfig_event_process(struct be_adapter *adapter, 27221252377SVasundhara Volam struct be_mcc_compl *compl) 27321252377SVasundhara Volam { 27421252377SVasundhara Volam struct be_async_event_misconfig_port *evt = 27521252377SVasundhara Volam (struct be_async_event_misconfig_port *)compl; 27621252377SVasundhara Volam u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1); 27721252377SVasundhara Volam struct device *dev = &adapter->pdev->dev; 27821252377SVasundhara Volam u8 port_misconfig_evt; 27921252377SVasundhara Volam 28021252377SVasundhara Volam port_misconfig_evt = 28121252377SVasundhara Volam ((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff); 28221252377SVasundhara Volam 28321252377SVasundhara Volam /* Log an error message that would allow a user to determine 28421252377SVasundhara Volam * whether the SFPs have an issue 28521252377SVasundhara Volam */ 28621252377SVasundhara Volam dev_info(dev, "Port %c: %s %s", adapter->port_name, 28721252377SVasundhara Volam be_port_misconfig_evt_desc[port_misconfig_evt], 28821252377SVasundhara Volam be_port_misconfig_remedy_desc[port_misconfig_evt]); 28921252377SVasundhara Volam 29021252377SVasundhara Volam if (port_misconfig_evt == INCOMPATIBLE_SFP) 29121252377SVasundhara Volam adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP; 29221252377SVasundhara Volam } 29321252377SVasundhara Volam 2949aebddd1SJeff Kirsher /* Grp5 CoS Priority evt */ 2959aebddd1SJeff Kirsher static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, 2963acf19d9SSathya Perla struct be_mcc_compl *compl) 2979aebddd1SJeff Kirsher { 2983acf19d9SSathya Perla struct be_async_event_grp5_cos_priority *evt = 2993acf19d9SSathya Perla (struct be_async_event_grp5_cos_priority *)compl; 3003acf19d9SSathya Perla 3019aebddd1SJeff Kirsher if (evt->valid) { 3029aebddd1SJeff Kirsher adapter->vlan_prio_bmap = evt->available_priority_bmap; 3039aebddd1SJeff Kirsher adapter->recommended_prio &= ~VLAN_PRIO_MASK; 3049aebddd1SJeff Kirsher adapter->recommended_prio = 3059aebddd1SJeff Kirsher evt->reco_default_priority << VLAN_PRIO_SHIFT; 3069aebddd1SJeff Kirsher } 3079aebddd1SJeff Kirsher } 3089aebddd1SJeff Kirsher 309323ff71eSSathya Perla /* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */ 3109aebddd1SJeff Kirsher static void be_async_grp5_qos_speed_process(struct be_adapter *adapter, 3113acf19d9SSathya Perla struct be_mcc_compl *compl) 3129aebddd1SJeff Kirsher { 3133acf19d9SSathya Perla struct be_async_event_grp5_qos_link_speed *evt = 3143acf19d9SSathya Perla (struct be_async_event_grp5_qos_link_speed *)compl; 3153acf19d9SSathya Perla 316323ff71eSSathya Perla if (adapter->phy.link_speed >= 0 && 317323ff71eSSathya Perla evt->physical_port == adapter->port_num) 318323ff71eSSathya Perla adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10; 3199aebddd1SJeff Kirsher } 3209aebddd1SJeff Kirsher 3219aebddd1SJeff Kirsher /*Grp5 PVID evt*/ 3229aebddd1SJeff Kirsher static void be_async_grp5_pvid_state_process(struct be_adapter *adapter, 3233acf19d9SSathya Perla struct be_mcc_compl *compl) 3249aebddd1SJeff Kirsher { 3253acf19d9SSathya Perla struct be_async_event_grp5_pvid_state *evt = 3263acf19d9SSathya Perla (struct be_async_event_grp5_pvid_state *)compl; 3273acf19d9SSathya Perla 328bdac85b5SRavikumar Nelavelli if (evt->enabled) { 329939cf306SSomnath Kotur adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK; 330bdac85b5SRavikumar Nelavelli dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid); 331bdac85b5SRavikumar Nelavelli } else { 3329aebddd1SJeff Kirsher adapter->pvid = 0; 3339aebddd1SJeff Kirsher } 334bdac85b5SRavikumar Nelavelli } 3359aebddd1SJeff Kirsher 336760c295eSVenkata Duvvuru #define MGMT_ENABLE_MASK 0x4 337760c295eSVenkata Duvvuru static void be_async_grp5_fw_control_process(struct be_adapter *adapter, 338760c295eSVenkata Duvvuru struct be_mcc_compl *compl) 339760c295eSVenkata Duvvuru { 340760c295eSVenkata Duvvuru struct be_async_fw_control *evt = (struct be_async_fw_control *)compl; 341760c295eSVenkata Duvvuru u32 evt_dw1 = le32_to_cpu(evt->event_data_word1); 342760c295eSVenkata Duvvuru 343760c295eSVenkata Duvvuru if (evt_dw1 & MGMT_ENABLE_MASK) { 344760c295eSVenkata Duvvuru adapter->flags |= BE_FLAGS_OS2BMC; 345760c295eSVenkata Duvvuru adapter->bmc_filt_mask = le32_to_cpu(evt->event_data_word2); 346760c295eSVenkata Duvvuru } else { 347760c295eSVenkata Duvvuru adapter->flags &= ~BE_FLAGS_OS2BMC; 348760c295eSVenkata Duvvuru } 349760c295eSVenkata Duvvuru } 350760c295eSVenkata Duvvuru 3519aebddd1SJeff Kirsher static void be_async_grp5_evt_process(struct be_adapter *adapter, 3523acf19d9SSathya Perla struct be_mcc_compl *compl) 3539aebddd1SJeff Kirsher { 3543acf19d9SSathya Perla u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) & 3553acf19d9SSathya Perla ASYNC_EVENT_TYPE_MASK; 3569aebddd1SJeff Kirsher 3579aebddd1SJeff Kirsher switch (event_type) { 3589aebddd1SJeff Kirsher case ASYNC_EVENT_COS_PRIORITY: 3593acf19d9SSathya Perla be_async_grp5_cos_priority_process(adapter, compl); 3609aebddd1SJeff Kirsher break; 3619aebddd1SJeff Kirsher case ASYNC_EVENT_QOS_SPEED: 3623acf19d9SSathya Perla be_async_grp5_qos_speed_process(adapter, compl); 3639aebddd1SJeff Kirsher break; 3649aebddd1SJeff Kirsher case ASYNC_EVENT_PVID_STATE: 3653acf19d9SSathya Perla be_async_grp5_pvid_state_process(adapter, compl); 3669aebddd1SJeff Kirsher break; 367760c295eSVenkata Duvvuru /* Async event to disable/enable os2bmc and/or mac-learning */ 368760c295eSVenkata Duvvuru case ASYNC_EVENT_FW_CONTROL: 369760c295eSVenkata Duvvuru be_async_grp5_fw_control_process(adapter, compl); 370760c295eSVenkata Duvvuru break; 3719aebddd1SJeff Kirsher default: 3729aebddd1SJeff Kirsher break; 3739aebddd1SJeff Kirsher } 3749aebddd1SJeff Kirsher } 3759aebddd1SJeff Kirsher 376bc0c3405SAjit Khaparde static void be_async_dbg_evt_process(struct be_adapter *adapter, 3773acf19d9SSathya Perla struct be_mcc_compl *cmp) 378bc0c3405SAjit Khaparde { 379bc0c3405SAjit Khaparde u8 event_type = 0; 380bc0c3405SAjit Khaparde struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp; 381bc0c3405SAjit Khaparde 3823acf19d9SSathya Perla event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) & 3833acf19d9SSathya Perla ASYNC_EVENT_TYPE_MASK; 384bc0c3405SAjit Khaparde 385bc0c3405SAjit Khaparde switch (event_type) { 386bc0c3405SAjit Khaparde case ASYNC_DEBUG_EVENT_TYPE_QNQ: 387bc0c3405SAjit Khaparde if (evt->valid) 388bc0c3405SAjit Khaparde adapter->qnq_vid = le16_to_cpu(evt->vlan_tag); 389bc0c3405SAjit Khaparde adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD; 390bc0c3405SAjit Khaparde break; 391bc0c3405SAjit Khaparde default: 39205ccaa2bSVasundhara Volam dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n", 39305ccaa2bSVasundhara Volam event_type); 394bc0c3405SAjit Khaparde break; 395bc0c3405SAjit Khaparde } 396bc0c3405SAjit Khaparde } 397bc0c3405SAjit Khaparde 39821252377SVasundhara Volam static void be_async_sliport_evt_process(struct be_adapter *adapter, 39921252377SVasundhara Volam struct be_mcc_compl *cmp) 40021252377SVasundhara Volam { 40121252377SVasundhara Volam u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) & 40221252377SVasundhara Volam ASYNC_EVENT_TYPE_MASK; 40321252377SVasundhara Volam 40421252377SVasundhara Volam if (event_type == ASYNC_EVENT_PORT_MISCONFIG) 40521252377SVasundhara Volam be_async_port_misconfig_event_process(adapter, cmp); 40621252377SVasundhara Volam } 40721252377SVasundhara Volam 4083acf19d9SSathya Perla static inline bool is_link_state_evt(u32 flags) 4099aebddd1SJeff Kirsher { 4103acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4119aebddd1SJeff Kirsher ASYNC_EVENT_CODE_LINK_STATE; 4129aebddd1SJeff Kirsher } 4139aebddd1SJeff Kirsher 4143acf19d9SSathya Perla static inline bool is_grp5_evt(u32 flags) 4159aebddd1SJeff Kirsher { 4163acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4173acf19d9SSathya Perla ASYNC_EVENT_CODE_GRP_5; 4189aebddd1SJeff Kirsher } 4199aebddd1SJeff Kirsher 4203acf19d9SSathya Perla static inline bool is_dbg_evt(u32 flags) 421bc0c3405SAjit Khaparde { 4223acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4233acf19d9SSathya Perla ASYNC_EVENT_CODE_QNQ; 4243acf19d9SSathya Perla } 4253acf19d9SSathya Perla 42621252377SVasundhara Volam static inline bool is_sliport_evt(u32 flags) 42721252377SVasundhara Volam { 42821252377SVasundhara Volam return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 42921252377SVasundhara Volam ASYNC_EVENT_CODE_SLIPORT; 43021252377SVasundhara Volam } 43121252377SVasundhara Volam 4323acf19d9SSathya Perla static void be_mcc_event_process(struct be_adapter *adapter, 4333acf19d9SSathya Perla struct be_mcc_compl *compl) 4343acf19d9SSathya Perla { 4353acf19d9SSathya Perla if (is_link_state_evt(compl->flags)) 4363acf19d9SSathya Perla be_async_link_state_process(adapter, compl); 4373acf19d9SSathya Perla else if (is_grp5_evt(compl->flags)) 4383acf19d9SSathya Perla be_async_grp5_evt_process(adapter, compl); 4393acf19d9SSathya Perla else if (is_dbg_evt(compl->flags)) 4403acf19d9SSathya Perla be_async_dbg_evt_process(adapter, compl); 44121252377SVasundhara Volam else if (is_sliport_evt(compl->flags)) 44221252377SVasundhara Volam be_async_sliport_evt_process(adapter, compl); 443bc0c3405SAjit Khaparde } 444bc0c3405SAjit Khaparde 4459aebddd1SJeff Kirsher static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) 4469aebddd1SJeff Kirsher { 4479aebddd1SJeff Kirsher struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq; 4489aebddd1SJeff Kirsher struct be_mcc_compl *compl = queue_tail_node(mcc_cq); 4499aebddd1SJeff Kirsher 4509aebddd1SJeff Kirsher if (be_mcc_compl_is_new(compl)) { 4519aebddd1SJeff Kirsher queue_tail_inc(mcc_cq); 4529aebddd1SJeff Kirsher return compl; 4539aebddd1SJeff Kirsher } 4549aebddd1SJeff Kirsher return NULL; 4559aebddd1SJeff Kirsher } 4569aebddd1SJeff Kirsher 4579aebddd1SJeff Kirsher void be_async_mcc_enable(struct be_adapter *adapter) 4589aebddd1SJeff Kirsher { 4599aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_cq_lock); 4609aebddd1SJeff Kirsher 4619aebddd1SJeff Kirsher be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0); 4629aebddd1SJeff Kirsher adapter->mcc_obj.rearm_cq = true; 4639aebddd1SJeff Kirsher 4649aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_cq_lock); 4659aebddd1SJeff Kirsher } 4669aebddd1SJeff Kirsher 4679aebddd1SJeff Kirsher void be_async_mcc_disable(struct be_adapter *adapter) 4689aebddd1SJeff Kirsher { 469a323d9bfSSathya Perla spin_lock_bh(&adapter->mcc_cq_lock); 470a323d9bfSSathya Perla 4719aebddd1SJeff Kirsher adapter->mcc_obj.rearm_cq = false; 472a323d9bfSSathya Perla be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); 473a323d9bfSSathya Perla 474a323d9bfSSathya Perla spin_unlock_bh(&adapter->mcc_cq_lock); 4759aebddd1SJeff Kirsher } 4769aebddd1SJeff Kirsher 47710ef9ab4SSathya Perla int be_process_mcc(struct be_adapter *adapter) 4789aebddd1SJeff Kirsher { 4799aebddd1SJeff Kirsher struct be_mcc_compl *compl; 48010ef9ab4SSathya Perla int num = 0, status = 0; 4819aebddd1SJeff Kirsher struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 4829aebddd1SJeff Kirsher 483072a9c48SAmerigo Wang spin_lock(&adapter->mcc_cq_lock); 4843acf19d9SSathya Perla 4859aebddd1SJeff Kirsher while ((compl = be_mcc_compl_get(adapter))) { 4869aebddd1SJeff Kirsher if (compl->flags & CQE_FLAGS_ASYNC_MASK) { 4873acf19d9SSathya Perla be_mcc_event_process(adapter, compl); 4889aebddd1SJeff Kirsher } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { 48910ef9ab4SSathya Perla status = be_mcc_compl_process(adapter, compl); 4909aebddd1SJeff Kirsher atomic_dec(&mcc_obj->q.used); 4919aebddd1SJeff Kirsher } 4929aebddd1SJeff Kirsher be_mcc_compl_use(compl); 4939aebddd1SJeff Kirsher num++; 4949aebddd1SJeff Kirsher } 4959aebddd1SJeff Kirsher 49610ef9ab4SSathya Perla if (num) 49710ef9ab4SSathya Perla be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); 49810ef9ab4SSathya Perla 499072a9c48SAmerigo Wang spin_unlock(&adapter->mcc_cq_lock); 50010ef9ab4SSathya Perla return status; 5019aebddd1SJeff Kirsher } 5029aebddd1SJeff Kirsher 5039aebddd1SJeff Kirsher /* Wait till no more pending mcc requests are present */ 5049aebddd1SJeff Kirsher static int be_mcc_wait_compl(struct be_adapter *adapter) 5059aebddd1SJeff Kirsher { 5069aebddd1SJeff Kirsher #define mcc_timeout 120000 /* 12s timeout */ 50710ef9ab4SSathya Perla int i, status = 0; 5089aebddd1SJeff Kirsher struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 5099aebddd1SJeff Kirsher 5106589ade0SSathya Perla for (i = 0; i < mcc_timeout; i++) { 511954f6825SVenkata Duvvuru if (be_check_error(adapter, BE_ERROR_ANY)) 5129aebddd1SJeff Kirsher return -EIO; 5139aebddd1SJeff Kirsher 514072a9c48SAmerigo Wang local_bh_disable(); 51510ef9ab4SSathya Perla status = be_process_mcc(adapter); 516072a9c48SAmerigo Wang local_bh_enable(); 5179aebddd1SJeff Kirsher 5189aebddd1SJeff Kirsher if (atomic_read(&mcc_obj->q.used) == 0) 5199aebddd1SJeff Kirsher break; 5209aebddd1SJeff Kirsher udelay(100); 5219aebddd1SJeff Kirsher } 5229aebddd1SJeff Kirsher if (i == mcc_timeout) { 5236589ade0SSathya Perla dev_err(&adapter->pdev->dev, "FW not responding\n"); 524954f6825SVenkata Duvvuru be_set_error(adapter, BE_ERROR_FW); 525652bf646SPadmanabh Ratnakar return -EIO; 5269aebddd1SJeff Kirsher } 5279aebddd1SJeff Kirsher return status; 5289aebddd1SJeff Kirsher } 5299aebddd1SJeff Kirsher 5309aebddd1SJeff Kirsher /* Notify MCC requests and wait for completion */ 5319aebddd1SJeff Kirsher static int be_mcc_notify_wait(struct be_adapter *adapter) 5329aebddd1SJeff Kirsher { 533652bf646SPadmanabh Ratnakar int status; 534652bf646SPadmanabh Ratnakar struct be_mcc_wrb *wrb; 535652bf646SPadmanabh Ratnakar struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 536652bf646SPadmanabh Ratnakar u16 index = mcc_obj->q.head; 537652bf646SPadmanabh Ratnakar struct be_cmd_resp_hdr *resp; 538652bf646SPadmanabh Ratnakar 539652bf646SPadmanabh Ratnakar index_dec(&index, mcc_obj->q.len); 540652bf646SPadmanabh Ratnakar wrb = queue_index_node(&mcc_obj->q, index); 541652bf646SPadmanabh Ratnakar 542652bf646SPadmanabh Ratnakar resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1); 543652bf646SPadmanabh Ratnakar 5449aebddd1SJeff Kirsher be_mcc_notify(adapter); 545652bf646SPadmanabh Ratnakar 546652bf646SPadmanabh Ratnakar status = be_mcc_wait_compl(adapter); 547652bf646SPadmanabh Ratnakar if (status == -EIO) 548652bf646SPadmanabh Ratnakar goto out; 549652bf646SPadmanabh Ratnakar 5504c60005fSKalesh AP status = (resp->base_status | 5514c60005fSKalesh AP ((resp->addl_status & CQE_ADDL_STATUS_MASK) << 5524c60005fSKalesh AP CQE_ADDL_STATUS_SHIFT)); 553652bf646SPadmanabh Ratnakar out: 554652bf646SPadmanabh Ratnakar return status; 5559aebddd1SJeff Kirsher } 5569aebddd1SJeff Kirsher 5579aebddd1SJeff Kirsher static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) 5589aebddd1SJeff Kirsher { 5599aebddd1SJeff Kirsher int msecs = 0; 5609aebddd1SJeff Kirsher u32 ready; 5619aebddd1SJeff Kirsher 5626589ade0SSathya Perla do { 563954f6825SVenkata Duvvuru if (be_check_error(adapter, BE_ERROR_ANY)) 5649aebddd1SJeff Kirsher return -EIO; 5659aebddd1SJeff Kirsher 5669aebddd1SJeff Kirsher ready = ioread32(db); 567434b3648SSathya Perla if (ready == 0xffffffff) 5689aebddd1SJeff Kirsher return -1; 5699aebddd1SJeff Kirsher 5709aebddd1SJeff Kirsher ready &= MPU_MAILBOX_DB_RDY_MASK; 5719aebddd1SJeff Kirsher if (ready) 5729aebddd1SJeff Kirsher break; 5739aebddd1SJeff Kirsher 5749aebddd1SJeff Kirsher if (msecs > 4000) { 5756589ade0SSathya Perla dev_err(&adapter->pdev->dev, "FW not responding\n"); 576954f6825SVenkata Duvvuru be_set_error(adapter, BE_ERROR_FW); 577f67ef7baSPadmanabh Ratnakar be_detect_error(adapter); 5789aebddd1SJeff Kirsher return -1; 5799aebddd1SJeff Kirsher } 5809aebddd1SJeff Kirsher 5819aebddd1SJeff Kirsher msleep(1); 5829aebddd1SJeff Kirsher msecs++; 5839aebddd1SJeff Kirsher } while (true); 5849aebddd1SJeff Kirsher 5859aebddd1SJeff Kirsher return 0; 5869aebddd1SJeff Kirsher } 5879aebddd1SJeff Kirsher 5889aebddd1SJeff Kirsher /* 5899aebddd1SJeff Kirsher * Insert the mailbox address into the doorbell in two steps 5909aebddd1SJeff Kirsher * Polls on the mbox doorbell till a command completion (or a timeout) occurs 5919aebddd1SJeff Kirsher */ 5929aebddd1SJeff Kirsher static int be_mbox_notify_wait(struct be_adapter *adapter) 5939aebddd1SJeff Kirsher { 5949aebddd1SJeff Kirsher int status; 5959aebddd1SJeff Kirsher u32 val = 0; 5969aebddd1SJeff Kirsher void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET; 5979aebddd1SJeff Kirsher struct be_dma_mem *mbox_mem = &adapter->mbox_mem; 5989aebddd1SJeff Kirsher struct be_mcc_mailbox *mbox = mbox_mem->va; 5999aebddd1SJeff Kirsher struct be_mcc_compl *compl = &mbox->compl; 6009aebddd1SJeff Kirsher 6019aebddd1SJeff Kirsher /* wait for ready to be set */ 6029aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 6039aebddd1SJeff Kirsher if (status != 0) 6049aebddd1SJeff Kirsher return status; 6059aebddd1SJeff Kirsher 6069aebddd1SJeff Kirsher val |= MPU_MAILBOX_DB_HI_MASK; 6079aebddd1SJeff Kirsher /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ 6089aebddd1SJeff Kirsher val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; 6099aebddd1SJeff Kirsher iowrite32(val, db); 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 = 0; 6179aebddd1SJeff Kirsher /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ 6189aebddd1SJeff Kirsher val |= (u32)(mbox_mem->dma >> 4) << 2; 6199aebddd1SJeff Kirsher iowrite32(val, db); 6209aebddd1SJeff Kirsher 6219aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 6229aebddd1SJeff Kirsher if (status != 0) 6239aebddd1SJeff Kirsher return status; 6249aebddd1SJeff Kirsher 6259aebddd1SJeff Kirsher /* A cq entry has been made now */ 6269aebddd1SJeff Kirsher if (be_mcc_compl_is_new(compl)) { 6279aebddd1SJeff Kirsher status = be_mcc_compl_process(adapter, &mbox->compl); 6289aebddd1SJeff Kirsher be_mcc_compl_use(compl); 6299aebddd1SJeff Kirsher if (status) 6309aebddd1SJeff Kirsher return status; 6319aebddd1SJeff Kirsher } else { 6329aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "invalid mailbox completion\n"); 6339aebddd1SJeff Kirsher return -1; 6349aebddd1SJeff Kirsher } 6359aebddd1SJeff Kirsher return 0; 6369aebddd1SJeff Kirsher } 6379aebddd1SJeff Kirsher 638c5b3ad4cSSathya Perla static u16 be_POST_stage_get(struct be_adapter *adapter) 6399aebddd1SJeff Kirsher { 6409aebddd1SJeff Kirsher u32 sem; 6419aebddd1SJeff Kirsher 642c5b3ad4cSSathya Perla if (BEx_chip(adapter)) 643c5b3ad4cSSathya Perla sem = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx); 6449aebddd1SJeff Kirsher else 645c5b3ad4cSSathya Perla pci_read_config_dword(adapter->pdev, 646c5b3ad4cSSathya Perla SLIPORT_SEMAPHORE_OFFSET_SH, &sem); 647c5b3ad4cSSathya Perla 648c5b3ad4cSSathya Perla return sem & POST_STAGE_MASK; 6499aebddd1SJeff Kirsher } 6509aebddd1SJeff Kirsher 65187f20c26SGavin Shan static int lancer_wait_ready(struct be_adapter *adapter) 652bf99e50dSPadmanabh Ratnakar { 653bf99e50dSPadmanabh Ratnakar #define SLIPORT_READY_TIMEOUT 30 654bf99e50dSPadmanabh Ratnakar u32 sliport_status; 655e673244aSKalesh AP int i; 656bf99e50dSPadmanabh Ratnakar 657bf99e50dSPadmanabh Ratnakar for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) { 658bf99e50dSPadmanabh Ratnakar sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); 659bf99e50dSPadmanabh Ratnakar if (sliport_status & SLIPORT_STATUS_RDY_MASK) 6609fa465c0SSathya Perla return 0; 6619fa465c0SSathya Perla 6629fa465c0SSathya Perla if (sliport_status & SLIPORT_STATUS_ERR_MASK && 6639fa465c0SSathya Perla !(sliport_status & SLIPORT_STATUS_RN_MASK)) 6649fa465c0SSathya Perla return -EIO; 665bf99e50dSPadmanabh Ratnakar 666bf99e50dSPadmanabh Ratnakar msleep(1000); 667bf99e50dSPadmanabh Ratnakar } 668bf99e50dSPadmanabh Ratnakar 669e673244aSKalesh AP return sliport_status ? : -1; 670bf99e50dSPadmanabh Ratnakar } 671bf99e50dSPadmanabh Ratnakar 672bf99e50dSPadmanabh Ratnakar int be_fw_wait_ready(struct be_adapter *adapter) 6739aebddd1SJeff Kirsher { 6749aebddd1SJeff Kirsher u16 stage; 6759aebddd1SJeff Kirsher int status, timeout = 0; 6769aebddd1SJeff Kirsher struct device *dev = &adapter->pdev->dev; 6779aebddd1SJeff Kirsher 678bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) { 679bf99e50dSPadmanabh Ratnakar status = lancer_wait_ready(adapter); 680e673244aSKalesh AP if (status) { 681e673244aSKalesh AP stage = status; 682e673244aSKalesh AP goto err; 683e673244aSKalesh AP } 684e673244aSKalesh AP return 0; 685bf99e50dSPadmanabh Ratnakar } 686bf99e50dSPadmanabh Ratnakar 6879aebddd1SJeff Kirsher do { 688ca3de6b2SSathya Perla /* There's no means to poll POST state on BE2/3 VFs */ 689ca3de6b2SSathya Perla if (BEx_chip(adapter) && be_virtfn(adapter)) 690ca3de6b2SSathya Perla return 0; 691ca3de6b2SSathya Perla 692c5b3ad4cSSathya Perla stage = be_POST_stage_get(adapter); 69366d29cbcSGavin Shan if (stage == POST_STAGE_ARMFW_RDY) 69466d29cbcSGavin Shan return 0; 69566d29cbcSGavin Shan 696a2cc4e0bSSathya Perla dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout); 6979aebddd1SJeff Kirsher if (msleep_interruptible(2000)) { 6989aebddd1SJeff Kirsher dev_err(dev, "Waiting for POST aborted\n"); 6999aebddd1SJeff Kirsher return -EINTR; 7009aebddd1SJeff Kirsher } 7019aebddd1SJeff Kirsher timeout += 2; 7023ab81b5fSSomnath Kotur } while (timeout < 60); 7039aebddd1SJeff Kirsher 704e673244aSKalesh AP err: 705e673244aSKalesh AP dev_err(dev, "POST timeout; stage=%#x\n", stage); 7069fa465c0SSathya Perla return -ETIMEDOUT; 7079aebddd1SJeff Kirsher } 7089aebddd1SJeff Kirsher 7099aebddd1SJeff Kirsher static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) 7109aebddd1SJeff Kirsher { 7119aebddd1SJeff Kirsher return &wrb->payload.sgl[0]; 7129aebddd1SJeff Kirsher } 7139aebddd1SJeff Kirsher 714a2cc4e0bSSathya Perla static inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr) 715bea50988SSathya Perla { 716bea50988SSathya Perla wrb->tag0 = addr & 0xFFFFFFFF; 717bea50988SSathya Perla wrb->tag1 = upper_32_bits(addr); 718bea50988SSathya Perla } 7199aebddd1SJeff Kirsher 7209aebddd1SJeff Kirsher /* Don't touch the hdr after it's prepared */ 721106df1e3SSomnath Kotur /* mem will be NULL for embedded commands */ 722106df1e3SSomnath Kotur static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, 723106df1e3SSomnath Kotur u8 subsystem, u8 opcode, int cmd_len, 724a2cc4e0bSSathya Perla struct be_mcc_wrb *wrb, 725a2cc4e0bSSathya Perla struct be_dma_mem *mem) 7269aebddd1SJeff Kirsher { 727106df1e3SSomnath Kotur struct be_sge *sge; 728106df1e3SSomnath Kotur 7299aebddd1SJeff Kirsher req_hdr->opcode = opcode; 7309aebddd1SJeff Kirsher req_hdr->subsystem = subsystem; 7319aebddd1SJeff Kirsher req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); 7329aebddd1SJeff Kirsher req_hdr->version = 0; 733bea50988SSathya Perla fill_wrb_tags(wrb, (ulong) req_hdr); 734106df1e3SSomnath Kotur wrb->payload_length = cmd_len; 735106df1e3SSomnath Kotur if (mem) { 736106df1e3SSomnath Kotur wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) << 737106df1e3SSomnath Kotur MCC_WRB_SGE_CNT_SHIFT; 738106df1e3SSomnath Kotur sge = nonembedded_sgl(wrb); 739106df1e3SSomnath Kotur sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma)); 740106df1e3SSomnath Kotur sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF); 741106df1e3SSomnath Kotur sge->len = cpu_to_le32(mem->size); 742106df1e3SSomnath Kotur } else 743106df1e3SSomnath Kotur wrb->embedded |= MCC_WRB_EMBEDDED_MASK; 744106df1e3SSomnath Kotur be_dws_cpu_to_le(wrb, 8); 7459aebddd1SJeff Kirsher } 7469aebddd1SJeff Kirsher 7479aebddd1SJeff Kirsher static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, 7489aebddd1SJeff Kirsher struct be_dma_mem *mem) 7499aebddd1SJeff Kirsher { 7509aebddd1SJeff Kirsher int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); 7519aebddd1SJeff Kirsher u64 dma = (u64)mem->dma; 7529aebddd1SJeff Kirsher 7539aebddd1SJeff Kirsher for (i = 0; i < buf_pages; i++) { 7549aebddd1SJeff Kirsher pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); 7559aebddd1SJeff Kirsher pages[i].hi = cpu_to_le32(upper_32_bits(dma)); 7569aebddd1SJeff Kirsher dma += PAGE_SIZE_4K; 7579aebddd1SJeff Kirsher } 7589aebddd1SJeff Kirsher } 7599aebddd1SJeff Kirsher 7609aebddd1SJeff Kirsher static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter) 7619aebddd1SJeff Kirsher { 7629aebddd1SJeff Kirsher struct be_dma_mem *mbox_mem = &adapter->mbox_mem; 7639aebddd1SJeff Kirsher struct be_mcc_wrb *wrb 7649aebddd1SJeff Kirsher = &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; 7659aebddd1SJeff Kirsher memset(wrb, 0, sizeof(*wrb)); 7669aebddd1SJeff Kirsher return wrb; 7679aebddd1SJeff Kirsher } 7689aebddd1SJeff Kirsher 7699aebddd1SJeff Kirsher static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) 7709aebddd1SJeff Kirsher { 7719aebddd1SJeff Kirsher struct be_queue_info *mccq = &adapter->mcc_obj.q; 7729aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 7739aebddd1SJeff Kirsher 774aa790db9SPadmanabh Ratnakar if (!mccq->created) 775aa790db9SPadmanabh Ratnakar return NULL; 776aa790db9SPadmanabh Ratnakar 7774d277125SVasundhara Volam if (atomic_read(&mccq->used) >= mccq->len) 7789aebddd1SJeff Kirsher return NULL; 7799aebddd1SJeff Kirsher 7809aebddd1SJeff Kirsher wrb = queue_head_node(mccq); 7819aebddd1SJeff Kirsher queue_head_inc(mccq); 7829aebddd1SJeff Kirsher atomic_inc(&mccq->used); 7839aebddd1SJeff Kirsher memset(wrb, 0, sizeof(*wrb)); 7849aebddd1SJeff Kirsher return wrb; 7859aebddd1SJeff Kirsher } 7869aebddd1SJeff Kirsher 787bea50988SSathya Perla static bool use_mcc(struct be_adapter *adapter) 788bea50988SSathya Perla { 789bea50988SSathya Perla return adapter->mcc_obj.q.created; 790bea50988SSathya Perla } 791bea50988SSathya Perla 792bea50988SSathya Perla /* Must be used only in process context */ 793bea50988SSathya Perla static int be_cmd_lock(struct be_adapter *adapter) 794bea50988SSathya Perla { 795bea50988SSathya Perla if (use_mcc(adapter)) { 796bea50988SSathya Perla spin_lock_bh(&adapter->mcc_lock); 797bea50988SSathya Perla return 0; 798bea50988SSathya Perla } else { 799bea50988SSathya Perla return mutex_lock_interruptible(&adapter->mbox_lock); 800bea50988SSathya Perla } 801bea50988SSathya Perla } 802bea50988SSathya Perla 803bea50988SSathya Perla /* Must be used only in process context */ 804bea50988SSathya Perla static void be_cmd_unlock(struct be_adapter *adapter) 805bea50988SSathya Perla { 806bea50988SSathya Perla if (use_mcc(adapter)) 807bea50988SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 808bea50988SSathya Perla else 809bea50988SSathya Perla return mutex_unlock(&adapter->mbox_lock); 810bea50988SSathya Perla } 811bea50988SSathya Perla 812bea50988SSathya Perla static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter, 813bea50988SSathya Perla struct be_mcc_wrb *wrb) 814bea50988SSathya Perla { 815bea50988SSathya Perla struct be_mcc_wrb *dest_wrb; 816bea50988SSathya Perla 817bea50988SSathya Perla if (use_mcc(adapter)) { 818bea50988SSathya Perla dest_wrb = wrb_from_mccq(adapter); 819bea50988SSathya Perla if (!dest_wrb) 820bea50988SSathya Perla return NULL; 821bea50988SSathya Perla } else { 822bea50988SSathya Perla dest_wrb = wrb_from_mbox(adapter); 823bea50988SSathya Perla } 824bea50988SSathya Perla 825bea50988SSathya Perla memcpy(dest_wrb, wrb, sizeof(*wrb)); 826bea50988SSathya Perla if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK)) 827bea50988SSathya Perla fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb)); 828bea50988SSathya Perla 829bea50988SSathya Perla return dest_wrb; 830bea50988SSathya Perla } 831bea50988SSathya Perla 832bea50988SSathya Perla /* Must be used only in process context */ 833bea50988SSathya Perla static int be_cmd_notify_wait(struct be_adapter *adapter, 834bea50988SSathya Perla struct be_mcc_wrb *wrb) 835bea50988SSathya Perla { 836bea50988SSathya Perla struct be_mcc_wrb *dest_wrb; 837bea50988SSathya Perla int status; 838bea50988SSathya Perla 839bea50988SSathya Perla status = be_cmd_lock(adapter); 840bea50988SSathya Perla if (status) 841bea50988SSathya Perla return status; 842bea50988SSathya Perla 843bea50988SSathya Perla dest_wrb = be_cmd_copy(adapter, wrb); 844bea50988SSathya Perla if (!dest_wrb) 845bea50988SSathya Perla return -EBUSY; 846bea50988SSathya Perla 847bea50988SSathya Perla if (use_mcc(adapter)) 848bea50988SSathya Perla status = be_mcc_notify_wait(adapter); 849bea50988SSathya Perla else 850bea50988SSathya Perla status = be_mbox_notify_wait(adapter); 851bea50988SSathya Perla 852bea50988SSathya Perla if (!status) 853bea50988SSathya Perla memcpy(wrb, dest_wrb, sizeof(*wrb)); 854bea50988SSathya Perla 855bea50988SSathya Perla be_cmd_unlock(adapter); 856bea50988SSathya Perla return status; 857bea50988SSathya Perla } 858bea50988SSathya Perla 8599aebddd1SJeff Kirsher /* Tell fw we're about to start firing cmds by writing a 8609aebddd1SJeff Kirsher * special pattern across the wrb hdr; uses mbox 8619aebddd1SJeff Kirsher */ 8629aebddd1SJeff Kirsher int be_cmd_fw_init(struct be_adapter *adapter) 8639aebddd1SJeff Kirsher { 8649aebddd1SJeff Kirsher u8 *wrb; 8659aebddd1SJeff Kirsher int status; 8669aebddd1SJeff Kirsher 867bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) 868bf99e50dSPadmanabh Ratnakar return 0; 869bf99e50dSPadmanabh Ratnakar 8709aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 8719aebddd1SJeff Kirsher return -1; 8729aebddd1SJeff Kirsher 8739aebddd1SJeff Kirsher wrb = (u8 *)wrb_from_mbox(adapter); 8749aebddd1SJeff Kirsher *wrb++ = 0xFF; 8759aebddd1SJeff Kirsher *wrb++ = 0x12; 8769aebddd1SJeff Kirsher *wrb++ = 0x34; 8779aebddd1SJeff Kirsher *wrb++ = 0xFF; 8789aebddd1SJeff Kirsher *wrb++ = 0xFF; 8799aebddd1SJeff Kirsher *wrb++ = 0x56; 8809aebddd1SJeff Kirsher *wrb++ = 0x78; 8819aebddd1SJeff Kirsher *wrb = 0xFF; 8829aebddd1SJeff Kirsher 8839aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 8849aebddd1SJeff Kirsher 8859aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 8869aebddd1SJeff Kirsher return status; 8879aebddd1SJeff Kirsher } 8889aebddd1SJeff Kirsher 8899aebddd1SJeff Kirsher /* Tell fw we're done with firing cmds by writing a 8909aebddd1SJeff Kirsher * special pattern across the wrb hdr; uses mbox 8919aebddd1SJeff Kirsher */ 8929aebddd1SJeff Kirsher int be_cmd_fw_clean(struct be_adapter *adapter) 8939aebddd1SJeff Kirsher { 8949aebddd1SJeff Kirsher u8 *wrb; 8959aebddd1SJeff Kirsher int status; 8969aebddd1SJeff Kirsher 897bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) 898bf99e50dSPadmanabh Ratnakar return 0; 899bf99e50dSPadmanabh Ratnakar 9009aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 9019aebddd1SJeff Kirsher return -1; 9029aebddd1SJeff Kirsher 9039aebddd1SJeff Kirsher wrb = (u8 *)wrb_from_mbox(adapter); 9049aebddd1SJeff Kirsher *wrb++ = 0xFF; 9059aebddd1SJeff Kirsher *wrb++ = 0xAA; 9069aebddd1SJeff Kirsher *wrb++ = 0xBB; 9079aebddd1SJeff Kirsher *wrb++ = 0xFF; 9089aebddd1SJeff Kirsher *wrb++ = 0xFF; 9099aebddd1SJeff Kirsher *wrb++ = 0xCC; 9109aebddd1SJeff Kirsher *wrb++ = 0xDD; 9119aebddd1SJeff Kirsher *wrb = 0xFF; 9129aebddd1SJeff Kirsher 9139aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 9149aebddd1SJeff Kirsher 9159aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 9169aebddd1SJeff Kirsher return status; 9179aebddd1SJeff Kirsher } 918bf99e50dSPadmanabh Ratnakar 919f2f781a7SSathya Perla int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo) 9209aebddd1SJeff Kirsher { 9219aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 9229aebddd1SJeff Kirsher struct be_cmd_req_eq_create *req; 923f2f781a7SSathya Perla struct be_dma_mem *q_mem = &eqo->q.dma_mem; 924f2f781a7SSathya Perla int status, ver = 0; 9259aebddd1SJeff Kirsher 9269aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 9279aebddd1SJeff Kirsher return -1; 9289aebddd1SJeff Kirsher 9299aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 9309aebddd1SJeff Kirsher req = embedded_payload(wrb); 9319aebddd1SJeff Kirsher 932106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 933a2cc4e0bSSathya Perla OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb, 934a2cc4e0bSSathya Perla NULL); 9359aebddd1SJeff Kirsher 936f2f781a7SSathya Perla /* Support for EQ_CREATEv2 available only SH-R onwards */ 937f2f781a7SSathya Perla if (!(BEx_chip(adapter) || lancer_chip(adapter))) 938f2f781a7SSathya Perla ver = 2; 939f2f781a7SSathya Perla 940f2f781a7SSathya Perla req->hdr.version = ver; 9419aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 9429aebddd1SJeff Kirsher 9439aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); 9449aebddd1SJeff Kirsher /* 4byte eqe*/ 9459aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); 9469aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, count, req->context, 947f2f781a7SSathya Perla __ilog2_u32(eqo->q.len / 256)); 9489aebddd1SJeff Kirsher be_dws_cpu_to_le(req->context, sizeof(req->context)); 9499aebddd1SJeff Kirsher 9509aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 9519aebddd1SJeff Kirsher 9529aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 9539aebddd1SJeff Kirsher if (!status) { 9549aebddd1SJeff Kirsher struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); 95503d28ffeSKalesh AP 956f2f781a7SSathya Perla eqo->q.id = le16_to_cpu(resp->eq_id); 957f2f781a7SSathya Perla eqo->msix_idx = 958f2f781a7SSathya Perla (ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx; 959f2f781a7SSathya Perla eqo->q.created = true; 9609aebddd1SJeff Kirsher } 9619aebddd1SJeff Kirsher 9629aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 9639aebddd1SJeff Kirsher return status; 9649aebddd1SJeff Kirsher } 9659aebddd1SJeff Kirsher 966f9449ab7SSathya Perla /* Use MCC */ 9679aebddd1SJeff Kirsher int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, 9685ee4979bSSathya Perla bool permanent, u32 if_handle, u32 pmac_id) 9699aebddd1SJeff Kirsher { 9709aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 9719aebddd1SJeff Kirsher struct be_cmd_req_mac_query *req; 9729aebddd1SJeff Kirsher int status; 9739aebddd1SJeff Kirsher 974f9449ab7SSathya Perla spin_lock_bh(&adapter->mcc_lock); 9759aebddd1SJeff Kirsher 976f9449ab7SSathya Perla wrb = wrb_from_mccq(adapter); 977f9449ab7SSathya Perla if (!wrb) { 978f9449ab7SSathya Perla status = -EBUSY; 979f9449ab7SSathya Perla goto err; 980f9449ab7SSathya Perla } 9819aebddd1SJeff Kirsher req = embedded_payload(wrb); 9829aebddd1SJeff Kirsher 983106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 984a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb, 985a2cc4e0bSSathya Perla NULL); 9865ee4979bSSathya Perla req->type = MAC_ADDRESS_TYPE_NETWORK; 9879aebddd1SJeff Kirsher if (permanent) { 9889aebddd1SJeff Kirsher req->permanent = 1; 9899aebddd1SJeff Kirsher } else { 9909aebddd1SJeff Kirsher req->if_id = cpu_to_le16((u16)if_handle); 991590c391dSPadmanabh Ratnakar req->pmac_id = cpu_to_le32(pmac_id); 9929aebddd1SJeff Kirsher req->permanent = 0; 9939aebddd1SJeff Kirsher } 9949aebddd1SJeff Kirsher 995f9449ab7SSathya Perla status = be_mcc_notify_wait(adapter); 9969aebddd1SJeff Kirsher if (!status) { 9979aebddd1SJeff Kirsher struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); 99803d28ffeSKalesh AP 9999aebddd1SJeff Kirsher memcpy(mac_addr, resp->mac.addr, ETH_ALEN); 10009aebddd1SJeff Kirsher } 10019aebddd1SJeff Kirsher 1002f9449ab7SSathya Perla err: 1003f9449ab7SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 10049aebddd1SJeff Kirsher return status; 10059aebddd1SJeff Kirsher } 10069aebddd1SJeff Kirsher 10079aebddd1SJeff Kirsher /* Uses synchronous MCCQ */ 10089aebddd1SJeff Kirsher int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, 10099aebddd1SJeff Kirsher u32 if_id, u32 *pmac_id, u32 domain) 10109aebddd1SJeff Kirsher { 10119aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10129aebddd1SJeff Kirsher struct be_cmd_req_pmac_add *req; 10139aebddd1SJeff Kirsher int status; 10149aebddd1SJeff Kirsher 10159aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 10169aebddd1SJeff Kirsher 10179aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 10189aebddd1SJeff Kirsher if (!wrb) { 10199aebddd1SJeff Kirsher status = -EBUSY; 10209aebddd1SJeff Kirsher goto err; 10219aebddd1SJeff Kirsher } 10229aebddd1SJeff Kirsher req = embedded_payload(wrb); 10239aebddd1SJeff Kirsher 1024106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1025a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb, 1026a2cc4e0bSSathya Perla NULL); 10279aebddd1SJeff Kirsher 10289aebddd1SJeff Kirsher req->hdr.domain = domain; 10299aebddd1SJeff Kirsher req->if_id = cpu_to_le32(if_id); 10309aebddd1SJeff Kirsher memcpy(req->mac_address, mac_addr, ETH_ALEN); 10319aebddd1SJeff Kirsher 10329aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 10339aebddd1SJeff Kirsher if (!status) { 10349aebddd1SJeff Kirsher struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb); 103503d28ffeSKalesh AP 10369aebddd1SJeff Kirsher *pmac_id = le32_to_cpu(resp->pmac_id); 10379aebddd1SJeff Kirsher } 10389aebddd1SJeff Kirsher 10399aebddd1SJeff Kirsher err: 10409aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 1041e3a7ae2cSSomnath Kotur 1042e3a7ae2cSSomnath Kotur if (status == MCC_STATUS_UNAUTHORIZED_REQUEST) 1043e3a7ae2cSSomnath Kotur status = -EPERM; 1044e3a7ae2cSSomnath Kotur 10459aebddd1SJeff Kirsher return status; 10469aebddd1SJeff Kirsher } 10479aebddd1SJeff Kirsher 10489aebddd1SJeff Kirsher /* Uses synchronous MCCQ */ 104930128031SSathya Perla int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) 10509aebddd1SJeff Kirsher { 10519aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10529aebddd1SJeff Kirsher struct be_cmd_req_pmac_del *req; 10539aebddd1SJeff Kirsher int status; 10549aebddd1SJeff Kirsher 105530128031SSathya Perla if (pmac_id == -1) 105630128031SSathya Perla return 0; 105730128031SSathya Perla 10589aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 10599aebddd1SJeff Kirsher 10609aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 10619aebddd1SJeff Kirsher if (!wrb) { 10629aebddd1SJeff Kirsher status = -EBUSY; 10639aebddd1SJeff Kirsher goto err; 10649aebddd1SJeff Kirsher } 10659aebddd1SJeff Kirsher req = embedded_payload(wrb); 10669aebddd1SJeff Kirsher 1067106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1068cd3307aaSKalesh AP OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req), 1069cd3307aaSKalesh AP wrb, NULL); 10709aebddd1SJeff Kirsher 10719aebddd1SJeff Kirsher req->hdr.domain = dom; 10729aebddd1SJeff Kirsher req->if_id = cpu_to_le32(if_id); 10739aebddd1SJeff Kirsher req->pmac_id = cpu_to_le32(pmac_id); 10749aebddd1SJeff Kirsher 10759aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 10769aebddd1SJeff Kirsher 10779aebddd1SJeff Kirsher err: 10789aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 10799aebddd1SJeff Kirsher return status; 10809aebddd1SJeff Kirsher } 10819aebddd1SJeff Kirsher 10829aebddd1SJeff Kirsher /* Uses Mbox */ 108310ef9ab4SSathya Perla int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, 108410ef9ab4SSathya Perla struct be_queue_info *eq, bool no_delay, int coalesce_wm) 10859aebddd1SJeff Kirsher { 10869aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10879aebddd1SJeff Kirsher struct be_cmd_req_cq_create *req; 10889aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &cq->dma_mem; 10899aebddd1SJeff Kirsher void *ctxt; 10909aebddd1SJeff Kirsher int status; 10919aebddd1SJeff Kirsher 10929aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 10939aebddd1SJeff Kirsher return -1; 10949aebddd1SJeff Kirsher 10959aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 10969aebddd1SJeff Kirsher req = embedded_payload(wrb); 10979aebddd1SJeff Kirsher ctxt = &req->context; 10989aebddd1SJeff Kirsher 1099106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1100a2cc4e0bSSathya Perla OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb, 1101a2cc4e0bSSathya Perla NULL); 11029aebddd1SJeff Kirsher 11039aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 1104bbdc42f8SAjit Khaparde 1105bbdc42f8SAjit Khaparde if (BEx_chip(adapter)) { 11069aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt, 11079aebddd1SJeff Kirsher coalesce_wm); 11089aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, nodelay, 11099aebddd1SJeff Kirsher ctxt, no_delay); 11109aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt, 11119aebddd1SJeff Kirsher __ilog2_u32(cq->len / 256)); 11129aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1); 11139aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1); 11149aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id); 1115bbdc42f8SAjit Khaparde } else { 1116bbdc42f8SAjit Khaparde req->hdr.version = 2; 1117bbdc42f8SAjit Khaparde req->page_size = 1; /* 1 for 4K */ 111809e83a9dSAjit Khaparde 111909e83a9dSAjit Khaparde /* coalesce-wm field in this cmd is not relevant to Lancer. 112009e83a9dSAjit Khaparde * Lancer uses COMMON_MODIFY_CQ to set this field 112109e83a9dSAjit Khaparde */ 112209e83a9dSAjit Khaparde if (!lancer_chip(adapter)) 112309e83a9dSAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm, 112409e83a9dSAjit Khaparde ctxt, coalesce_wm); 1125bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt, 1126bbdc42f8SAjit Khaparde no_delay); 1127bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt, 1128bbdc42f8SAjit Khaparde __ilog2_u32(cq->len / 256)); 1129bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1); 1130a2cc4e0bSSathya Perla AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1); 1131a2cc4e0bSSathya Perla AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id); 11329aebddd1SJeff Kirsher } 11339aebddd1SJeff Kirsher 11349aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 11359aebddd1SJeff Kirsher 11369aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 11379aebddd1SJeff Kirsher 11389aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 11399aebddd1SJeff Kirsher if (!status) { 11409aebddd1SJeff Kirsher struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); 114103d28ffeSKalesh AP 11429aebddd1SJeff Kirsher cq->id = le16_to_cpu(resp->cq_id); 11439aebddd1SJeff Kirsher cq->created = true; 11449aebddd1SJeff Kirsher } 11459aebddd1SJeff Kirsher 11469aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 11479aebddd1SJeff Kirsher 11489aebddd1SJeff Kirsher return status; 11499aebddd1SJeff Kirsher } 11509aebddd1SJeff Kirsher 11519aebddd1SJeff Kirsher static u32 be_encoded_q_len(int q_len) 11529aebddd1SJeff Kirsher { 11539aebddd1SJeff Kirsher u32 len_encoded = fls(q_len); /* log2(len) + 1 */ 115403d28ffeSKalesh AP 11559aebddd1SJeff Kirsher if (len_encoded == 16) 11569aebddd1SJeff Kirsher len_encoded = 0; 11579aebddd1SJeff Kirsher return len_encoded; 11589aebddd1SJeff Kirsher } 11599aebddd1SJeff Kirsher 11604188e7dfSJingoo Han static int be_cmd_mccq_ext_create(struct be_adapter *adapter, 11619aebddd1SJeff Kirsher struct be_queue_info *mccq, 11629aebddd1SJeff Kirsher struct be_queue_info *cq) 11639aebddd1SJeff Kirsher { 11649aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 11659aebddd1SJeff Kirsher struct be_cmd_req_mcc_ext_create *req; 11669aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &mccq->dma_mem; 11679aebddd1SJeff Kirsher void *ctxt; 11689aebddd1SJeff Kirsher int status; 11699aebddd1SJeff Kirsher 11709aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 11719aebddd1SJeff Kirsher return -1; 11729aebddd1SJeff Kirsher 11739aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 11749aebddd1SJeff Kirsher req = embedded_payload(wrb); 11759aebddd1SJeff Kirsher ctxt = &req->context; 11769aebddd1SJeff Kirsher 1177106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1178a2cc4e0bSSathya Perla OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb, 1179a2cc4e0bSSathya Perla NULL); 11809aebddd1SJeff Kirsher 11819aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 1182666d39c7SVasundhara Volam if (BEx_chip(adapter)) { 11839aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); 11849aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, 11859aebddd1SJeff Kirsher be_encoded_q_len(mccq->len)); 11869aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); 1187666d39c7SVasundhara Volam } else { 1188666d39c7SVasundhara Volam req->hdr.version = 1; 1189666d39c7SVasundhara Volam req->cq_id = cpu_to_le16(cq->id); 1190666d39c7SVasundhara Volam 1191666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt, 1192666d39c7SVasundhara Volam be_encoded_q_len(mccq->len)); 1193666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1); 1194666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id, 1195666d39c7SVasundhara Volam ctxt, cq->id); 1196666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid, 1197666d39c7SVasundhara Volam ctxt, 1); 11989aebddd1SJeff Kirsher } 11999aebddd1SJeff Kirsher 120021252377SVasundhara Volam /* Subscribe to Link State, Sliport Event and Group 5 Events 120121252377SVasundhara Volam * (bits 1, 5 and 17 set) 120221252377SVasundhara Volam */ 120321252377SVasundhara Volam req->async_event_bitmap[0] = 120421252377SVasundhara Volam cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) | 120521252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_GRP_5) | 120621252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_QNQ) | 120721252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_SLIPORT)); 120821252377SVasundhara Volam 12099aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 12109aebddd1SJeff Kirsher 12119aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 12129aebddd1SJeff Kirsher 12139aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 12149aebddd1SJeff Kirsher if (!status) { 12159aebddd1SJeff Kirsher struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); 121603d28ffeSKalesh AP 12179aebddd1SJeff Kirsher mccq->id = le16_to_cpu(resp->id); 12189aebddd1SJeff Kirsher mccq->created = true; 12199aebddd1SJeff Kirsher } 12209aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 12219aebddd1SJeff Kirsher 12229aebddd1SJeff Kirsher return status; 12239aebddd1SJeff Kirsher } 12249aebddd1SJeff Kirsher 12254188e7dfSJingoo Han static int be_cmd_mccq_org_create(struct be_adapter *adapter, 12269aebddd1SJeff Kirsher struct be_queue_info *mccq, 12279aebddd1SJeff Kirsher struct be_queue_info *cq) 12289aebddd1SJeff Kirsher { 12299aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 12309aebddd1SJeff Kirsher struct be_cmd_req_mcc_create *req; 12319aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &mccq->dma_mem; 12329aebddd1SJeff Kirsher void *ctxt; 12339aebddd1SJeff Kirsher int status; 12349aebddd1SJeff Kirsher 12359aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 12369aebddd1SJeff Kirsher return -1; 12379aebddd1SJeff Kirsher 12389aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 12399aebddd1SJeff Kirsher req = embedded_payload(wrb); 12409aebddd1SJeff Kirsher ctxt = &req->context; 12419aebddd1SJeff Kirsher 1242106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1243a2cc4e0bSSathya Perla OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb, 1244a2cc4e0bSSathya Perla NULL); 12459aebddd1SJeff Kirsher 12469aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 12479aebddd1SJeff Kirsher 12489aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); 12499aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, 12509aebddd1SJeff Kirsher be_encoded_q_len(mccq->len)); 12519aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); 12529aebddd1SJeff Kirsher 12539aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 12549aebddd1SJeff Kirsher 12559aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 12569aebddd1SJeff Kirsher 12579aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 12589aebddd1SJeff Kirsher if (!status) { 12599aebddd1SJeff Kirsher struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); 126003d28ffeSKalesh AP 12619aebddd1SJeff Kirsher mccq->id = le16_to_cpu(resp->id); 12629aebddd1SJeff Kirsher mccq->created = true; 12639aebddd1SJeff Kirsher } 12649aebddd1SJeff Kirsher 12659aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 12669aebddd1SJeff Kirsher return status; 12679aebddd1SJeff Kirsher } 12689aebddd1SJeff Kirsher 12699aebddd1SJeff Kirsher int be_cmd_mccq_create(struct be_adapter *adapter, 1270a2cc4e0bSSathya Perla struct be_queue_info *mccq, struct be_queue_info *cq) 12719aebddd1SJeff Kirsher { 12729aebddd1SJeff Kirsher int status; 12739aebddd1SJeff Kirsher 12749aebddd1SJeff Kirsher status = be_cmd_mccq_ext_create(adapter, mccq, cq); 1275666d39c7SVasundhara Volam if (status && BEx_chip(adapter)) { 12769aebddd1SJeff Kirsher dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 " 12779aebddd1SJeff Kirsher "or newer to avoid conflicting priorities between NIC " 12789aebddd1SJeff Kirsher "and FCoE traffic"); 12799aebddd1SJeff Kirsher status = be_cmd_mccq_org_create(adapter, mccq, cq); 12809aebddd1SJeff Kirsher } 12819aebddd1SJeff Kirsher return status; 12829aebddd1SJeff Kirsher } 12839aebddd1SJeff Kirsher 128494d73aaaSVasundhara Volam int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) 12859aebddd1SJeff Kirsher { 12867707133cSSathya Perla struct be_mcc_wrb wrb = {0}; 12879aebddd1SJeff Kirsher struct be_cmd_req_eth_tx_create *req; 128894d73aaaSVasundhara Volam struct be_queue_info *txq = &txo->q; 128994d73aaaSVasundhara Volam struct be_queue_info *cq = &txo->cq; 12909aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &txq->dma_mem; 129194d73aaaSVasundhara Volam int status, ver = 0; 12929aebddd1SJeff Kirsher 12937707133cSSathya Perla req = embedded_payload(&wrb); 1294106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 12957707133cSSathya Perla OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL); 12969aebddd1SJeff Kirsher 12979aebddd1SJeff Kirsher if (lancer_chip(adapter)) { 12989aebddd1SJeff Kirsher req->hdr.version = 1; 129994d73aaaSVasundhara Volam } else if (BEx_chip(adapter)) { 130094d73aaaSVasundhara Volam if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) 130194d73aaaSVasundhara Volam req->hdr.version = 2; 130294d73aaaSVasundhara Volam } else { /* For SH */ 130394d73aaaSVasundhara Volam req->hdr.version = 2; 13049aebddd1SJeff Kirsher } 13059aebddd1SJeff Kirsher 130681b02655SVasundhara Volam if (req->hdr.version > 0) 130781b02655SVasundhara Volam req->if_id = cpu_to_le16(adapter->if_handle); 13089aebddd1SJeff Kirsher req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); 13099aebddd1SJeff Kirsher req->ulp_num = BE_ULP1_NUM; 13109aebddd1SJeff Kirsher req->type = BE_ETH_TX_RING_TYPE_STANDARD; 131194d73aaaSVasundhara Volam req->cq_id = cpu_to_le16(cq->id); 131294d73aaaSVasundhara Volam req->queue_size = be_encoded_q_len(txq->len); 13139aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 131494d73aaaSVasundhara Volam ver = req->hdr.version; 131594d73aaaSVasundhara Volam 13167707133cSSathya Perla status = be_cmd_notify_wait(adapter, &wrb); 13179aebddd1SJeff Kirsher if (!status) { 13187707133cSSathya Perla struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb); 131903d28ffeSKalesh AP 13209aebddd1SJeff Kirsher txq->id = le16_to_cpu(resp->cid); 132194d73aaaSVasundhara Volam if (ver == 2) 132294d73aaaSVasundhara Volam txo->db_offset = le32_to_cpu(resp->db_offset); 132394d73aaaSVasundhara Volam else 132494d73aaaSVasundhara Volam txo->db_offset = DB_TXULP1_OFFSET; 13259aebddd1SJeff Kirsher txq->created = true; 13269aebddd1SJeff Kirsher } 13279aebddd1SJeff Kirsher 13289aebddd1SJeff Kirsher return status; 13299aebddd1SJeff Kirsher } 13309aebddd1SJeff Kirsher 13319aebddd1SJeff Kirsher /* Uses MCC */ 13329aebddd1SJeff Kirsher int be_cmd_rxq_create(struct be_adapter *adapter, 13339aebddd1SJeff Kirsher struct be_queue_info *rxq, u16 cq_id, u16 frag_size, 133410ef9ab4SSathya Perla u32 if_id, u32 rss, u8 *rss_id) 13359aebddd1SJeff Kirsher { 13369aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 13379aebddd1SJeff Kirsher struct be_cmd_req_eth_rx_create *req; 13389aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &rxq->dma_mem; 13399aebddd1SJeff Kirsher int status; 13409aebddd1SJeff Kirsher 13419aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 13429aebddd1SJeff Kirsher 13439aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 13449aebddd1SJeff Kirsher if (!wrb) { 13459aebddd1SJeff Kirsher status = -EBUSY; 13469aebddd1SJeff Kirsher goto err; 13479aebddd1SJeff Kirsher } 13489aebddd1SJeff Kirsher req = embedded_payload(wrb); 13499aebddd1SJeff Kirsher 1350106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1351106df1e3SSomnath Kotur OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL); 13529aebddd1SJeff Kirsher 13539aebddd1SJeff Kirsher req->cq_id = cpu_to_le16(cq_id); 13549aebddd1SJeff Kirsher req->frag_size = fls(frag_size) - 1; 13559aebddd1SJeff Kirsher req->num_pages = 2; 13569aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 13579aebddd1SJeff Kirsher req->interface_id = cpu_to_le32(if_id); 135810ef9ab4SSathya Perla req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE); 13599aebddd1SJeff Kirsher req->rss_queue = cpu_to_le32(rss); 13609aebddd1SJeff Kirsher 13619aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 13629aebddd1SJeff Kirsher if (!status) { 13639aebddd1SJeff Kirsher struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); 136403d28ffeSKalesh AP 13659aebddd1SJeff Kirsher rxq->id = le16_to_cpu(resp->id); 13669aebddd1SJeff Kirsher rxq->created = true; 13679aebddd1SJeff Kirsher *rss_id = resp->rss_id; 13689aebddd1SJeff Kirsher } 13699aebddd1SJeff Kirsher 13709aebddd1SJeff Kirsher err: 13719aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 13729aebddd1SJeff Kirsher return status; 13739aebddd1SJeff Kirsher } 13749aebddd1SJeff Kirsher 13759aebddd1SJeff Kirsher /* Generic destroyer function for all types of queues 13769aebddd1SJeff Kirsher * Uses Mbox 13779aebddd1SJeff Kirsher */ 13789aebddd1SJeff Kirsher int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, 13799aebddd1SJeff Kirsher int queue_type) 13809aebddd1SJeff Kirsher { 13819aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 13829aebddd1SJeff Kirsher struct be_cmd_req_q_destroy *req; 13839aebddd1SJeff Kirsher u8 subsys = 0, opcode = 0; 13849aebddd1SJeff Kirsher int status; 13859aebddd1SJeff Kirsher 13869aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 13879aebddd1SJeff Kirsher return -1; 13889aebddd1SJeff Kirsher 13899aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 13909aebddd1SJeff Kirsher req = embedded_payload(wrb); 13919aebddd1SJeff Kirsher 13929aebddd1SJeff Kirsher switch (queue_type) { 13939aebddd1SJeff Kirsher case QTYPE_EQ: 13949aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 13959aebddd1SJeff Kirsher opcode = OPCODE_COMMON_EQ_DESTROY; 13969aebddd1SJeff Kirsher break; 13979aebddd1SJeff Kirsher case QTYPE_CQ: 13989aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 13999aebddd1SJeff Kirsher opcode = OPCODE_COMMON_CQ_DESTROY; 14009aebddd1SJeff Kirsher break; 14019aebddd1SJeff Kirsher case QTYPE_TXQ: 14029aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_ETH; 14039aebddd1SJeff Kirsher opcode = OPCODE_ETH_TX_DESTROY; 14049aebddd1SJeff Kirsher break; 14059aebddd1SJeff Kirsher case QTYPE_RXQ: 14069aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_ETH; 14079aebddd1SJeff Kirsher opcode = OPCODE_ETH_RX_DESTROY; 14089aebddd1SJeff Kirsher break; 14099aebddd1SJeff Kirsher case QTYPE_MCCQ: 14109aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 14119aebddd1SJeff Kirsher opcode = OPCODE_COMMON_MCC_DESTROY; 14129aebddd1SJeff Kirsher break; 14139aebddd1SJeff Kirsher default: 14149aebddd1SJeff Kirsher BUG(); 14159aebddd1SJeff Kirsher } 14169aebddd1SJeff Kirsher 1417106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb, 1418106df1e3SSomnath Kotur NULL); 14199aebddd1SJeff Kirsher req->id = cpu_to_le16(q->id); 14209aebddd1SJeff Kirsher 14219aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 14229aebddd1SJeff Kirsher q->created = false; 14239aebddd1SJeff Kirsher 14249aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 14259aebddd1SJeff Kirsher return status; 14269aebddd1SJeff Kirsher } 14279aebddd1SJeff Kirsher 14289aebddd1SJeff Kirsher /* Uses MCC */ 14299aebddd1SJeff Kirsher int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) 14309aebddd1SJeff Kirsher { 14319aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 14329aebddd1SJeff Kirsher struct be_cmd_req_q_destroy *req; 14339aebddd1SJeff Kirsher int status; 14349aebddd1SJeff Kirsher 14359aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 14369aebddd1SJeff Kirsher 14379aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 14389aebddd1SJeff Kirsher if (!wrb) { 14399aebddd1SJeff Kirsher status = -EBUSY; 14409aebddd1SJeff Kirsher goto err; 14419aebddd1SJeff Kirsher } 14429aebddd1SJeff Kirsher req = embedded_payload(wrb); 14439aebddd1SJeff Kirsher 1444106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1445106df1e3SSomnath Kotur OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL); 14469aebddd1SJeff Kirsher req->id = cpu_to_le16(q->id); 14479aebddd1SJeff Kirsher 14489aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 14499aebddd1SJeff Kirsher q->created = false; 14509aebddd1SJeff Kirsher 14519aebddd1SJeff Kirsher err: 14529aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 14539aebddd1SJeff Kirsher return status; 14549aebddd1SJeff Kirsher } 14559aebddd1SJeff Kirsher 14569aebddd1SJeff Kirsher /* Create an rx filtering policy configuration on an i/f 1457bea50988SSathya Perla * Will use MBOX only if MCCQ has not been created. 14589aebddd1SJeff Kirsher */ 14599aebddd1SJeff Kirsher int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, 14601578e777SPadmanabh Ratnakar u32 *if_handle, u32 domain) 14619aebddd1SJeff Kirsher { 1462bea50988SSathya Perla struct be_mcc_wrb wrb = {0}; 14639aebddd1SJeff Kirsher struct be_cmd_req_if_create *req; 14649aebddd1SJeff Kirsher int status; 14659aebddd1SJeff Kirsher 1466bea50988SSathya Perla req = embedded_payload(&wrb); 1467106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1468a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_INTERFACE_CREATE, 1469a2cc4e0bSSathya Perla sizeof(*req), &wrb, NULL); 14709aebddd1SJeff Kirsher req->hdr.domain = domain; 14719aebddd1SJeff Kirsher req->capability_flags = cpu_to_le32(cap_flags); 14729aebddd1SJeff Kirsher req->enable_flags = cpu_to_le32(en_flags); 1473f9449ab7SSathya Perla req->pmac_invalid = true; 14749aebddd1SJeff Kirsher 1475bea50988SSathya Perla status = be_cmd_notify_wait(adapter, &wrb); 14769aebddd1SJeff Kirsher if (!status) { 1477bea50988SSathya Perla struct be_cmd_resp_if_create *resp = embedded_payload(&wrb); 147803d28ffeSKalesh AP 14799aebddd1SJeff Kirsher *if_handle = le32_to_cpu(resp->interface_id); 1480b5bb9776SSathya Perla 1481b5bb9776SSathya Perla /* Hack to retrieve VF's pmac-id on BE3 */ 148218c57c74SKalesh AP if (BE3_chip(adapter) && be_virtfn(adapter)) 1483b5bb9776SSathya Perla adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id); 14849aebddd1SJeff Kirsher } 14859aebddd1SJeff Kirsher return status; 14869aebddd1SJeff Kirsher } 14879aebddd1SJeff Kirsher 1488f9449ab7SSathya Perla /* Uses MCCQ */ 148930128031SSathya Perla int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain) 14909aebddd1SJeff Kirsher { 14919aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 14929aebddd1SJeff Kirsher struct be_cmd_req_if_destroy *req; 14939aebddd1SJeff Kirsher int status; 14949aebddd1SJeff Kirsher 149530128031SSathya Perla if (interface_id == -1) 1496f9449ab7SSathya Perla return 0; 14979aebddd1SJeff Kirsher 1498f9449ab7SSathya Perla spin_lock_bh(&adapter->mcc_lock); 1499f9449ab7SSathya Perla 1500f9449ab7SSathya Perla wrb = wrb_from_mccq(adapter); 1501f9449ab7SSathya Perla if (!wrb) { 1502f9449ab7SSathya Perla status = -EBUSY; 1503f9449ab7SSathya Perla goto err; 1504f9449ab7SSathya Perla } 15059aebddd1SJeff Kirsher req = embedded_payload(wrb); 15069aebddd1SJeff Kirsher 1507106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1508a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_INTERFACE_DESTROY, 1509a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 15109aebddd1SJeff Kirsher req->hdr.domain = domain; 15119aebddd1SJeff Kirsher req->interface_id = cpu_to_le32(interface_id); 15129aebddd1SJeff Kirsher 1513f9449ab7SSathya Perla status = be_mcc_notify_wait(adapter); 1514f9449ab7SSathya Perla err: 1515f9449ab7SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 15169aebddd1SJeff Kirsher return status; 15179aebddd1SJeff Kirsher } 15189aebddd1SJeff Kirsher 15199aebddd1SJeff Kirsher /* Get stats is a non embedded command: the request is not embedded inside 15209aebddd1SJeff Kirsher * WRB but is a separate dma memory block 15219aebddd1SJeff Kirsher * Uses asynchronous MCC 15229aebddd1SJeff Kirsher */ 15239aebddd1SJeff Kirsher int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) 15249aebddd1SJeff Kirsher { 15259aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 15269aebddd1SJeff Kirsher struct be_cmd_req_hdr *hdr; 15279aebddd1SJeff Kirsher int status = 0; 15289aebddd1SJeff Kirsher 15299aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 15309aebddd1SJeff Kirsher 15319aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 15329aebddd1SJeff Kirsher if (!wrb) { 15339aebddd1SJeff Kirsher status = -EBUSY; 15349aebddd1SJeff Kirsher goto err; 15359aebddd1SJeff Kirsher } 15369aebddd1SJeff Kirsher hdr = nonemb_cmd->va; 15379aebddd1SJeff Kirsher 1538106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH, 1539a2cc4e0bSSathya Perla OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, 1540a2cc4e0bSSathya Perla nonemb_cmd); 15419aebddd1SJeff Kirsher 1542ca34fe38SSathya Perla /* version 1 of the cmd is not supported only by BE2 */ 154361000861SAjit Khaparde if (BE2_chip(adapter)) 154461000861SAjit Khaparde hdr->version = 0; 154561000861SAjit Khaparde if (BE3_chip(adapter) || lancer_chip(adapter)) 15469aebddd1SJeff Kirsher hdr->version = 1; 154761000861SAjit Khaparde else 154861000861SAjit Khaparde hdr->version = 2; 15499aebddd1SJeff Kirsher 15509aebddd1SJeff Kirsher be_mcc_notify(adapter); 15519aebddd1SJeff Kirsher adapter->stats_cmd_sent = true; 15529aebddd1SJeff Kirsher 15539aebddd1SJeff Kirsher err: 15549aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 15559aebddd1SJeff Kirsher return status; 15569aebddd1SJeff Kirsher } 15579aebddd1SJeff Kirsher 15589aebddd1SJeff Kirsher /* Lancer Stats */ 15599aebddd1SJeff Kirsher int lancer_cmd_get_pport_stats(struct be_adapter *adapter, 15609aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 15619aebddd1SJeff Kirsher { 15629aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 15639aebddd1SJeff Kirsher struct lancer_cmd_req_pport_stats *req; 15649aebddd1SJeff Kirsher int status = 0; 15659aebddd1SJeff Kirsher 1566f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS, 1567f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH)) 1568f25b119cSPadmanabh Ratnakar return -EPERM; 1569f25b119cSPadmanabh Ratnakar 15709aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 15719aebddd1SJeff Kirsher 15729aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 15739aebddd1SJeff Kirsher if (!wrb) { 15749aebddd1SJeff Kirsher status = -EBUSY; 15759aebddd1SJeff Kirsher goto err; 15769aebddd1SJeff Kirsher } 15779aebddd1SJeff Kirsher req = nonemb_cmd->va; 15789aebddd1SJeff Kirsher 1579106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1580a2cc4e0bSSathya Perla OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, 1581a2cc4e0bSSathya Perla wrb, nonemb_cmd); 15829aebddd1SJeff Kirsher 1583d51ebd33SPadmanabh Ratnakar req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num); 15849aebddd1SJeff Kirsher req->cmd_params.params.reset_stats = 0; 15859aebddd1SJeff Kirsher 15869aebddd1SJeff Kirsher be_mcc_notify(adapter); 15879aebddd1SJeff Kirsher adapter->stats_cmd_sent = true; 15889aebddd1SJeff Kirsher 15899aebddd1SJeff Kirsher err: 15909aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 15919aebddd1SJeff Kirsher return status; 15929aebddd1SJeff Kirsher } 15939aebddd1SJeff Kirsher 1594323ff71eSSathya Perla static int be_mac_to_link_speed(int mac_speed) 1595323ff71eSSathya Perla { 1596323ff71eSSathya Perla switch (mac_speed) { 1597323ff71eSSathya Perla case PHY_LINK_SPEED_ZERO: 1598323ff71eSSathya Perla return 0; 1599323ff71eSSathya Perla case PHY_LINK_SPEED_10MBPS: 1600323ff71eSSathya Perla return 10; 1601323ff71eSSathya Perla case PHY_LINK_SPEED_100MBPS: 1602323ff71eSSathya Perla return 100; 1603323ff71eSSathya Perla case PHY_LINK_SPEED_1GBPS: 1604323ff71eSSathya Perla return 1000; 1605323ff71eSSathya Perla case PHY_LINK_SPEED_10GBPS: 1606323ff71eSSathya Perla return 10000; 1607b971f847SVasundhara Volam case PHY_LINK_SPEED_20GBPS: 1608b971f847SVasundhara Volam return 20000; 1609b971f847SVasundhara Volam case PHY_LINK_SPEED_25GBPS: 1610b971f847SVasundhara Volam return 25000; 1611b971f847SVasundhara Volam case PHY_LINK_SPEED_40GBPS: 1612b971f847SVasundhara Volam return 40000; 1613323ff71eSSathya Perla } 1614323ff71eSSathya Perla return 0; 1615323ff71eSSathya Perla } 1616323ff71eSSathya Perla 1617323ff71eSSathya Perla /* Uses synchronous mcc 1618323ff71eSSathya Perla * Returns link_speed in Mbps 1619323ff71eSSathya Perla */ 1620323ff71eSSathya Perla int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, 1621323ff71eSSathya Perla u8 *link_status, u32 dom) 16229aebddd1SJeff Kirsher { 16239aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 16249aebddd1SJeff Kirsher struct be_cmd_req_link_status *req; 16259aebddd1SJeff Kirsher int status; 16269aebddd1SJeff Kirsher 16279aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 16289aebddd1SJeff Kirsher 1629b236916aSAjit Khaparde if (link_status) 1630b236916aSAjit Khaparde *link_status = LINK_DOWN; 1631b236916aSAjit Khaparde 16329aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 16339aebddd1SJeff Kirsher if (!wrb) { 16349aebddd1SJeff Kirsher status = -EBUSY; 16359aebddd1SJeff Kirsher goto err; 16369aebddd1SJeff Kirsher } 16379aebddd1SJeff Kirsher req = embedded_payload(wrb); 16389aebddd1SJeff Kirsher 163957cd80d4SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1640a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, 1641a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 164257cd80d4SPadmanabh Ratnakar 1643ca34fe38SSathya Perla /* version 1 of the cmd is not supported only by BE2 */ 1644ca34fe38SSathya Perla if (!BE2_chip(adapter)) 1645daad6167SPadmanabh Ratnakar req->hdr.version = 1; 1646daad6167SPadmanabh Ratnakar 164757cd80d4SPadmanabh Ratnakar req->hdr.domain = dom; 16489aebddd1SJeff Kirsher 16499aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 16509aebddd1SJeff Kirsher if (!status) { 16519aebddd1SJeff Kirsher struct be_cmd_resp_link_status *resp = embedded_payload(wrb); 165203d28ffeSKalesh AP 1653323ff71eSSathya Perla if (link_speed) { 1654323ff71eSSathya Perla *link_speed = resp->link_speed ? 1655323ff71eSSathya Perla le16_to_cpu(resp->link_speed) * 10 : 1656323ff71eSSathya Perla be_mac_to_link_speed(resp->mac_speed); 1657323ff71eSSathya Perla 1658323ff71eSSathya Perla if (!resp->logical_link_status) 1659323ff71eSSathya Perla *link_speed = 0; 16609aebddd1SJeff Kirsher } 1661b236916aSAjit Khaparde if (link_status) 1662b236916aSAjit Khaparde *link_status = resp->logical_link_status; 16639aebddd1SJeff Kirsher } 16649aebddd1SJeff Kirsher 16659aebddd1SJeff Kirsher err: 16669aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 16679aebddd1SJeff Kirsher return status; 16689aebddd1SJeff Kirsher } 16699aebddd1SJeff Kirsher 16709aebddd1SJeff Kirsher /* Uses synchronous mcc */ 16719aebddd1SJeff Kirsher int be_cmd_get_die_temperature(struct be_adapter *adapter) 16729aebddd1SJeff Kirsher { 16739aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 16749aebddd1SJeff Kirsher struct be_cmd_req_get_cntl_addnl_attribs *req; 1675117affe3SVasundhara Volam int status = 0; 16769aebddd1SJeff Kirsher 16779aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 16789aebddd1SJeff Kirsher 16799aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 16809aebddd1SJeff Kirsher if (!wrb) { 16819aebddd1SJeff Kirsher status = -EBUSY; 16829aebddd1SJeff Kirsher goto err; 16839aebddd1SJeff Kirsher } 16849aebddd1SJeff Kirsher req = embedded_payload(wrb); 16859aebddd1SJeff Kirsher 1686106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1687a2cc4e0bSSathya Perla OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, 1688a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 16899aebddd1SJeff Kirsher 16903de09455SSomnath Kotur be_mcc_notify(adapter); 16919aebddd1SJeff Kirsher 16929aebddd1SJeff Kirsher err: 16939aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 16949aebddd1SJeff Kirsher return status; 16959aebddd1SJeff Kirsher } 16969aebddd1SJeff Kirsher 16979aebddd1SJeff Kirsher /* Uses synchronous mcc */ 16989aebddd1SJeff Kirsher int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size) 16999aebddd1SJeff Kirsher { 17009aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 17019aebddd1SJeff Kirsher struct be_cmd_req_get_fat *req; 17029aebddd1SJeff Kirsher int status; 17039aebddd1SJeff Kirsher 17049aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 17059aebddd1SJeff Kirsher 17069aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 17079aebddd1SJeff Kirsher if (!wrb) { 17089aebddd1SJeff Kirsher status = -EBUSY; 17099aebddd1SJeff Kirsher goto err; 17109aebddd1SJeff Kirsher } 17119aebddd1SJeff Kirsher req = embedded_payload(wrb); 17129aebddd1SJeff Kirsher 1713106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1714a2cc4e0bSSathya Perla OPCODE_COMMON_MANAGE_FAT, sizeof(*req), wrb, 1715a2cc4e0bSSathya Perla NULL); 17169aebddd1SJeff Kirsher req->fat_operation = cpu_to_le32(QUERY_FAT); 17179aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 17189aebddd1SJeff Kirsher if (!status) { 17199aebddd1SJeff Kirsher struct be_cmd_resp_get_fat *resp = embedded_payload(wrb); 172003d28ffeSKalesh AP 17219aebddd1SJeff Kirsher if (log_size && resp->log_size) 17229aebddd1SJeff Kirsher *log_size = le32_to_cpu(resp->log_size) - 17239aebddd1SJeff Kirsher sizeof(u32); 17249aebddd1SJeff Kirsher } 17259aebddd1SJeff Kirsher err: 17269aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 17279aebddd1SJeff Kirsher return status; 17289aebddd1SJeff Kirsher } 17299aebddd1SJeff Kirsher 1730c5f156deSVasundhara Volam int be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) 17319aebddd1SJeff Kirsher { 17329aebddd1SJeff Kirsher struct be_dma_mem get_fat_cmd; 17339aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 17349aebddd1SJeff Kirsher struct be_cmd_req_get_fat *req; 17359aebddd1SJeff Kirsher u32 offset = 0, total_size, buf_size, 17369aebddd1SJeff Kirsher log_offset = sizeof(u32), payload_len; 1737c5f156deSVasundhara Volam int status = 0; 17389aebddd1SJeff Kirsher 17399aebddd1SJeff Kirsher if (buf_len == 0) 1740c5f156deSVasundhara Volam return -EIO; 17419aebddd1SJeff Kirsher 17429aebddd1SJeff Kirsher total_size = buf_len; 17439aebddd1SJeff Kirsher 17449aebddd1SJeff Kirsher get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024; 17459aebddd1SJeff Kirsher get_fat_cmd.va = pci_alloc_consistent(adapter->pdev, 17469aebddd1SJeff Kirsher get_fat_cmd.size, 17479aebddd1SJeff Kirsher &get_fat_cmd.dma); 17489aebddd1SJeff Kirsher if (!get_fat_cmd.va) { 17499aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, 1750cd3307aaSKalesh AP "Memory allocation failure while reading FAT data\n"); 1751c5f156deSVasundhara Volam return -ENOMEM; 17529aebddd1SJeff Kirsher } 17539aebddd1SJeff Kirsher 17549aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 17559aebddd1SJeff Kirsher 17569aebddd1SJeff Kirsher while (total_size) { 17579aebddd1SJeff Kirsher buf_size = min(total_size, (u32)60*1024); 17589aebddd1SJeff Kirsher total_size -= buf_size; 17599aebddd1SJeff Kirsher 17609aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 17619aebddd1SJeff Kirsher if (!wrb) { 17629aebddd1SJeff Kirsher status = -EBUSY; 17639aebddd1SJeff Kirsher goto err; 17649aebddd1SJeff Kirsher } 17659aebddd1SJeff Kirsher req = get_fat_cmd.va; 17669aebddd1SJeff Kirsher 17679aebddd1SJeff Kirsher payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size; 1768106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1769a2cc4e0bSSathya Perla OPCODE_COMMON_MANAGE_FAT, payload_len, 1770a2cc4e0bSSathya Perla wrb, &get_fat_cmd); 17719aebddd1SJeff Kirsher 17729aebddd1SJeff Kirsher req->fat_operation = cpu_to_le32(RETRIEVE_FAT); 17739aebddd1SJeff Kirsher req->read_log_offset = cpu_to_le32(log_offset); 17749aebddd1SJeff Kirsher req->read_log_length = cpu_to_le32(buf_size); 17759aebddd1SJeff Kirsher req->data_buffer_size = cpu_to_le32(buf_size); 17769aebddd1SJeff Kirsher 17779aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 17789aebddd1SJeff Kirsher if (!status) { 17799aebddd1SJeff Kirsher struct be_cmd_resp_get_fat *resp = get_fat_cmd.va; 178003d28ffeSKalesh AP 17819aebddd1SJeff Kirsher memcpy(buf + offset, 17829aebddd1SJeff Kirsher resp->data_buffer, 178392aa9214SSomnath Kotur le32_to_cpu(resp->read_log_length)); 17849aebddd1SJeff Kirsher } else { 17859aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n"); 17869aebddd1SJeff Kirsher goto err; 17879aebddd1SJeff Kirsher } 17889aebddd1SJeff Kirsher offset += buf_size; 17899aebddd1SJeff Kirsher log_offset += buf_size; 17909aebddd1SJeff Kirsher } 17919aebddd1SJeff Kirsher err: 17929aebddd1SJeff Kirsher pci_free_consistent(adapter->pdev, get_fat_cmd.size, 1793a2cc4e0bSSathya Perla get_fat_cmd.va, get_fat_cmd.dma); 17949aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 1795c5f156deSVasundhara Volam return status; 17969aebddd1SJeff Kirsher } 17979aebddd1SJeff Kirsher 179804b71175SSathya Perla /* Uses synchronous mcc */ 1799e97e3cdaSKalesh AP int be_cmd_get_fw_ver(struct be_adapter *adapter) 18009aebddd1SJeff Kirsher { 18019aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 18029aebddd1SJeff Kirsher struct be_cmd_req_get_fw_version *req; 18039aebddd1SJeff Kirsher int status; 18049aebddd1SJeff Kirsher 180504b71175SSathya Perla spin_lock_bh(&adapter->mcc_lock); 18069aebddd1SJeff Kirsher 180704b71175SSathya Perla wrb = wrb_from_mccq(adapter); 180804b71175SSathya Perla if (!wrb) { 180904b71175SSathya Perla status = -EBUSY; 181004b71175SSathya Perla goto err; 181104b71175SSathya Perla } 181204b71175SSathya Perla 18139aebddd1SJeff Kirsher req = embedded_payload(wrb); 18149aebddd1SJeff Kirsher 1815106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1816a2cc4e0bSSathya Perla OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb, 1817a2cc4e0bSSathya Perla NULL); 181804b71175SSathya Perla status = be_mcc_notify_wait(adapter); 18199aebddd1SJeff Kirsher if (!status) { 18209aebddd1SJeff Kirsher struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb); 1821acbafeb1SSathya Perla 1822242eb470SVasundhara Volam strlcpy(adapter->fw_ver, resp->firmware_version_string, 1823242eb470SVasundhara Volam sizeof(adapter->fw_ver)); 1824242eb470SVasundhara Volam strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string, 1825242eb470SVasundhara Volam sizeof(adapter->fw_on_flash)); 18269aebddd1SJeff Kirsher } 182704b71175SSathya Perla err: 182804b71175SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 18299aebddd1SJeff Kirsher return status; 18309aebddd1SJeff Kirsher } 18319aebddd1SJeff Kirsher 18329aebddd1SJeff Kirsher /* set the EQ delay interval of an EQ to specified value 18339aebddd1SJeff Kirsher * Uses async mcc 18349aebddd1SJeff Kirsher */ 1835b502ae8dSKalesh AP static int __be_cmd_modify_eqd(struct be_adapter *adapter, 1836b502ae8dSKalesh AP struct be_set_eqd *set_eqd, int num) 18379aebddd1SJeff Kirsher { 18389aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 18399aebddd1SJeff Kirsher struct be_cmd_req_modify_eq_delay *req; 18402632bafdSSathya Perla int status = 0, i; 18419aebddd1SJeff Kirsher 18429aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 18439aebddd1SJeff Kirsher 18449aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 18459aebddd1SJeff Kirsher if (!wrb) { 18469aebddd1SJeff Kirsher status = -EBUSY; 18479aebddd1SJeff Kirsher goto err; 18489aebddd1SJeff Kirsher } 18499aebddd1SJeff Kirsher req = embedded_payload(wrb); 18509aebddd1SJeff Kirsher 1851106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1852a2cc4e0bSSathya Perla OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb, 1853a2cc4e0bSSathya Perla NULL); 18549aebddd1SJeff Kirsher 18552632bafdSSathya Perla req->num_eq = cpu_to_le32(num); 18562632bafdSSathya Perla for (i = 0; i < num; i++) { 18572632bafdSSathya Perla req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id); 18582632bafdSSathya Perla req->set_eqd[i].phase = 0; 18592632bafdSSathya Perla req->set_eqd[i].delay_multiplier = 18602632bafdSSathya Perla cpu_to_le32(set_eqd[i].delay_multiplier); 18612632bafdSSathya Perla } 18629aebddd1SJeff Kirsher 18639aebddd1SJeff Kirsher be_mcc_notify(adapter); 18649aebddd1SJeff Kirsher err: 18659aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 18669aebddd1SJeff Kirsher return status; 18679aebddd1SJeff Kirsher } 18689aebddd1SJeff Kirsher 186993676703SKalesh AP int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd, 187093676703SKalesh AP int num) 187193676703SKalesh AP { 187293676703SKalesh AP int num_eqs, i = 0; 187393676703SKalesh AP 187493676703SKalesh AP while (num) { 187593676703SKalesh AP num_eqs = min(num, 8); 187693676703SKalesh AP __be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs); 187793676703SKalesh AP i += num_eqs; 187893676703SKalesh AP num -= num_eqs; 187993676703SKalesh AP } 188093676703SKalesh AP 188193676703SKalesh AP return 0; 188293676703SKalesh AP } 188393676703SKalesh AP 18849aebddd1SJeff Kirsher /* Uses sycnhronous mcc */ 18859aebddd1SJeff Kirsher int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, 1886435452aaSVasundhara Volam u32 num, u32 domain) 18879aebddd1SJeff Kirsher { 18889aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 18899aebddd1SJeff Kirsher struct be_cmd_req_vlan_config *req; 18909aebddd1SJeff Kirsher int status; 18919aebddd1SJeff Kirsher 18929aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 18939aebddd1SJeff Kirsher 18949aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 18959aebddd1SJeff Kirsher if (!wrb) { 18969aebddd1SJeff Kirsher status = -EBUSY; 18979aebddd1SJeff Kirsher goto err; 18989aebddd1SJeff Kirsher } 18999aebddd1SJeff Kirsher req = embedded_payload(wrb); 19009aebddd1SJeff Kirsher 1901106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1902a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req), 1903a2cc4e0bSSathya Perla wrb, NULL); 1904435452aaSVasundhara Volam req->hdr.domain = domain; 19059aebddd1SJeff Kirsher 19069aebddd1SJeff Kirsher req->interface_id = if_id; 1907012bd387SAjit Khaparde req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0; 19089aebddd1SJeff Kirsher req->num_vlan = num; 19099aebddd1SJeff Kirsher memcpy(req->normal_vlan, vtag_array, 19109aebddd1SJeff Kirsher req->num_vlan * sizeof(vtag_array[0])); 19119aebddd1SJeff Kirsher 19129aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 19139aebddd1SJeff Kirsher err: 19149aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 19159aebddd1SJeff Kirsher return status; 19169aebddd1SJeff Kirsher } 19179aebddd1SJeff Kirsher 1918ac34b743SSathya Perla static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) 19199aebddd1SJeff Kirsher { 19209aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19219aebddd1SJeff Kirsher struct be_dma_mem *mem = &adapter->rx_filter; 19229aebddd1SJeff Kirsher struct be_cmd_req_rx_filter *req = mem->va; 19239aebddd1SJeff Kirsher int status; 19249aebddd1SJeff Kirsher 19259aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 19269aebddd1SJeff Kirsher 19279aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 19289aebddd1SJeff Kirsher if (!wrb) { 19299aebddd1SJeff Kirsher status = -EBUSY; 19309aebddd1SJeff Kirsher goto err; 19319aebddd1SJeff Kirsher } 19329aebddd1SJeff Kirsher memset(req, 0, sizeof(*req)); 1933106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1934106df1e3SSomnath Kotur OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req), 1935106df1e3SSomnath Kotur wrb, mem); 19369aebddd1SJeff Kirsher 19379aebddd1SJeff Kirsher req->if_id = cpu_to_le32(adapter->if_handle); 1938ac34b743SSathya Perla req->if_flags_mask = cpu_to_le32(flags); 1939ac34b743SSathya Perla req->if_flags = (value == ON) ? req->if_flags_mask : 0; 1940d9d604f8SAjit Khaparde 1941ac34b743SSathya Perla if (flags & BE_IF_FLAGS_MULTICAST) { 19429aebddd1SJeff Kirsher struct netdev_hw_addr *ha; 19439aebddd1SJeff Kirsher int i = 0; 19449aebddd1SJeff Kirsher 19451610c79fSPadmanabh Ratnakar /* Reset mcast promisc mode if already set by setting mask 19461610c79fSPadmanabh Ratnakar * and not setting flags field 19471610c79fSPadmanabh Ratnakar */ 19481610c79fSPadmanabh Ratnakar req->if_flags_mask |= 1949abb93951SPadmanabh Ratnakar cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS & 195092bf14abSSathya Perla be_if_cap_flags(adapter)); 1951016f97b1SPadmanabh Ratnakar req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev)); 19529aebddd1SJeff Kirsher netdev_for_each_mc_addr(ha, adapter->netdev) 19539aebddd1SJeff Kirsher memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN); 19549aebddd1SJeff Kirsher } 19559aebddd1SJeff Kirsher 19569aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 19579aebddd1SJeff Kirsher err: 19589aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 19599aebddd1SJeff Kirsher return status; 19609aebddd1SJeff Kirsher } 19619aebddd1SJeff Kirsher 1962ac34b743SSathya Perla int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) 1963ac34b743SSathya Perla { 1964ac34b743SSathya Perla struct device *dev = &adapter->pdev->dev; 1965ac34b743SSathya Perla 1966ac34b743SSathya Perla if ((flags & be_if_cap_flags(adapter)) != flags) { 1967ac34b743SSathya Perla dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags); 1968ac34b743SSathya Perla dev_warn(dev, "Interface is capable of 0x%x flags only\n", 1969ac34b743SSathya Perla be_if_cap_flags(adapter)); 1970ac34b743SSathya Perla } 1971ac34b743SSathya Perla flags &= be_if_cap_flags(adapter); 1972ac34b743SSathya Perla 1973ac34b743SSathya Perla return __be_cmd_rx_filter(adapter, flags, value); 1974ac34b743SSathya Perla } 1975ac34b743SSathya Perla 19769aebddd1SJeff Kirsher /* Uses synchrounous mcc */ 19779aebddd1SJeff Kirsher int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) 19789aebddd1SJeff Kirsher { 19799aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19809aebddd1SJeff Kirsher struct be_cmd_req_set_flow_control *req; 19819aebddd1SJeff Kirsher int status; 19829aebddd1SJeff Kirsher 1983f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL, 1984f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 1985f25b119cSPadmanabh Ratnakar return -EPERM; 1986f25b119cSPadmanabh Ratnakar 19879aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 19889aebddd1SJeff Kirsher 19899aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 19909aebddd1SJeff Kirsher if (!wrb) { 19919aebddd1SJeff Kirsher status = -EBUSY; 19929aebddd1SJeff Kirsher goto err; 19939aebddd1SJeff Kirsher } 19949aebddd1SJeff Kirsher req = embedded_payload(wrb); 19959aebddd1SJeff Kirsher 1996106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1997a2cc4e0bSSathya Perla OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req), 1998a2cc4e0bSSathya Perla wrb, NULL); 19999aebddd1SJeff Kirsher 2000b29812c1SSuresh Reddy req->hdr.version = 1; 20019aebddd1SJeff Kirsher req->tx_flow_control = cpu_to_le16((u16)tx_fc); 20029aebddd1SJeff Kirsher req->rx_flow_control = cpu_to_le16((u16)rx_fc); 20039aebddd1SJeff Kirsher 20049aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 20059aebddd1SJeff Kirsher 20069aebddd1SJeff Kirsher err: 20079aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 2008b29812c1SSuresh Reddy 2009b29812c1SSuresh Reddy if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED) 2010b29812c1SSuresh Reddy return -EOPNOTSUPP; 2011b29812c1SSuresh Reddy 20129aebddd1SJeff Kirsher return status; 20139aebddd1SJeff Kirsher } 20149aebddd1SJeff Kirsher 20159aebddd1SJeff Kirsher /* Uses sycn mcc */ 20169aebddd1SJeff Kirsher int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) 20179aebddd1SJeff Kirsher { 20189aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20199aebddd1SJeff Kirsher struct be_cmd_req_get_flow_control *req; 20209aebddd1SJeff Kirsher int status; 20219aebddd1SJeff Kirsher 2022f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL, 2023f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 2024f25b119cSPadmanabh Ratnakar return -EPERM; 2025f25b119cSPadmanabh Ratnakar 20269aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 20279aebddd1SJeff Kirsher 20289aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 20299aebddd1SJeff Kirsher if (!wrb) { 20309aebddd1SJeff Kirsher status = -EBUSY; 20319aebddd1SJeff Kirsher goto err; 20329aebddd1SJeff Kirsher } 20339aebddd1SJeff Kirsher req = embedded_payload(wrb); 20349aebddd1SJeff Kirsher 2035106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2036a2cc4e0bSSathya Perla OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req), 2037a2cc4e0bSSathya Perla wrb, NULL); 20389aebddd1SJeff Kirsher 20399aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 20409aebddd1SJeff Kirsher if (!status) { 20419aebddd1SJeff Kirsher struct be_cmd_resp_get_flow_control *resp = 20429aebddd1SJeff Kirsher embedded_payload(wrb); 204303d28ffeSKalesh AP 20449aebddd1SJeff Kirsher *tx_fc = le16_to_cpu(resp->tx_flow_control); 20459aebddd1SJeff Kirsher *rx_fc = le16_to_cpu(resp->rx_flow_control); 20469aebddd1SJeff Kirsher } 20479aebddd1SJeff Kirsher 20489aebddd1SJeff Kirsher err: 20499aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 20509aebddd1SJeff Kirsher return status; 20519aebddd1SJeff Kirsher } 20529aebddd1SJeff Kirsher 20539aebddd1SJeff Kirsher /* Uses mbox */ 2054e97e3cdaSKalesh AP int be_cmd_query_fw_cfg(struct be_adapter *adapter) 20559aebddd1SJeff Kirsher { 20569aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20579aebddd1SJeff Kirsher struct be_cmd_req_query_fw_cfg *req; 20589aebddd1SJeff Kirsher int status; 20599aebddd1SJeff Kirsher 20609aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 20619aebddd1SJeff Kirsher return -1; 20629aebddd1SJeff Kirsher 20639aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 20649aebddd1SJeff Kirsher req = embedded_payload(wrb); 20659aebddd1SJeff Kirsher 2066106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2067a2cc4e0bSSathya Perla OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, 2068a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 20699aebddd1SJeff Kirsher 20709aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 20719aebddd1SJeff Kirsher if (!status) { 20729aebddd1SJeff Kirsher struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); 207303d28ffeSKalesh AP 2074e97e3cdaSKalesh AP adapter->port_num = le32_to_cpu(resp->phys_port); 2075e97e3cdaSKalesh AP adapter->function_mode = le32_to_cpu(resp->function_mode); 2076e97e3cdaSKalesh AP adapter->function_caps = le32_to_cpu(resp->function_caps); 2077e97e3cdaSKalesh AP adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF; 2078acbafeb1SSathya Perla dev_info(&adapter->pdev->dev, 2079acbafeb1SSathya Perla "FW config: function_mode=0x%x, function_caps=0x%x\n", 2080acbafeb1SSathya Perla adapter->function_mode, adapter->function_caps); 20819aebddd1SJeff Kirsher } 20829aebddd1SJeff Kirsher 20839aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 20849aebddd1SJeff Kirsher return status; 20859aebddd1SJeff Kirsher } 20869aebddd1SJeff Kirsher 20879aebddd1SJeff Kirsher /* Uses mbox */ 20889aebddd1SJeff Kirsher int be_cmd_reset_function(struct be_adapter *adapter) 20899aebddd1SJeff Kirsher { 20909aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20919aebddd1SJeff Kirsher struct be_cmd_req_hdr *req; 20929aebddd1SJeff Kirsher int status; 20939aebddd1SJeff Kirsher 2094bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) { 2095bf99e50dSPadmanabh Ratnakar iowrite32(SLI_PORT_CONTROL_IP_MASK, 2096bf99e50dSPadmanabh Ratnakar adapter->db + SLIPORT_CONTROL_OFFSET); 20979fa465c0SSathya Perla status = lancer_wait_ready(adapter); 20989fa465c0SSathya Perla if (status) 2099bf99e50dSPadmanabh Ratnakar dev_err(&adapter->pdev->dev, 2100bf99e50dSPadmanabh Ratnakar "Adapter in non recoverable error\n"); 2101bf99e50dSPadmanabh Ratnakar return status; 2102bf99e50dSPadmanabh Ratnakar } 2103bf99e50dSPadmanabh Ratnakar 21049aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 21059aebddd1SJeff Kirsher return -1; 21069aebddd1SJeff Kirsher 21079aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 21089aebddd1SJeff Kirsher req = embedded_payload(wrb); 21099aebddd1SJeff Kirsher 2110106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON, 2111a2cc4e0bSSathya Perla OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb, 2112a2cc4e0bSSathya Perla NULL); 21139aebddd1SJeff Kirsher 21149aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 21159aebddd1SJeff Kirsher 21169aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 21179aebddd1SJeff Kirsher return status; 21189aebddd1SJeff Kirsher } 21199aebddd1SJeff Kirsher 2120594ad54aSSuresh Reddy int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, 212133cb0fa7SBen Hutchings u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey) 21229aebddd1SJeff Kirsher { 21239aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21249aebddd1SJeff Kirsher struct be_cmd_req_rss_config *req; 21259aebddd1SJeff Kirsher int status; 21269aebddd1SJeff Kirsher 2127da1388d6SVasundhara Volam if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS)) 2128da1388d6SVasundhara Volam return 0; 2129da1388d6SVasundhara Volam 2130b51aa367SKalesh AP spin_lock_bh(&adapter->mcc_lock); 21319aebddd1SJeff Kirsher 2132b51aa367SKalesh AP wrb = wrb_from_mccq(adapter); 2133b51aa367SKalesh AP if (!wrb) { 2134b51aa367SKalesh AP status = -EBUSY; 2135b51aa367SKalesh AP goto err; 2136b51aa367SKalesh AP } 21379aebddd1SJeff Kirsher req = embedded_payload(wrb); 21389aebddd1SJeff Kirsher 2139106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 2140106df1e3SSomnath Kotur OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL); 21419aebddd1SJeff Kirsher 21429aebddd1SJeff Kirsher req->if_id = cpu_to_le32(adapter->if_handle); 2143594ad54aSSuresh Reddy req->enable_rss = cpu_to_le16(rss_hash_opts); 21449aebddd1SJeff Kirsher req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1); 2145594ad54aSSuresh Reddy 2146b51aa367SKalesh AP if (!BEx_chip(adapter)) 2147594ad54aSSuresh Reddy req->hdr.version = 1; 2148594ad54aSSuresh Reddy 21499aebddd1SJeff Kirsher memcpy(req->cpu_table, rsstable, table_size); 2150e2557877SVenkata Duvvuru memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN); 21519aebddd1SJeff Kirsher be_dws_cpu_to_le(req->hash, sizeof(req->hash)); 21529aebddd1SJeff Kirsher 2153b51aa367SKalesh AP status = be_mcc_notify_wait(adapter); 2154b51aa367SKalesh AP err: 2155b51aa367SKalesh AP spin_unlock_bh(&adapter->mcc_lock); 21569aebddd1SJeff Kirsher return status; 21579aebddd1SJeff Kirsher } 21589aebddd1SJeff Kirsher 21599aebddd1SJeff Kirsher /* Uses sync mcc */ 21609aebddd1SJeff Kirsher int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, 21619aebddd1SJeff Kirsher u8 bcn, u8 sts, u8 state) 21629aebddd1SJeff Kirsher { 21639aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21649aebddd1SJeff Kirsher struct be_cmd_req_enable_disable_beacon *req; 21659aebddd1SJeff Kirsher int status; 21669aebddd1SJeff Kirsher 21679aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 21689aebddd1SJeff Kirsher 21699aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 21709aebddd1SJeff Kirsher if (!wrb) { 21719aebddd1SJeff Kirsher status = -EBUSY; 21729aebddd1SJeff Kirsher goto err; 21739aebddd1SJeff Kirsher } 21749aebddd1SJeff Kirsher req = embedded_payload(wrb); 21759aebddd1SJeff Kirsher 2176106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2177a2cc4e0bSSathya Perla OPCODE_COMMON_ENABLE_DISABLE_BEACON, 2178a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 21799aebddd1SJeff Kirsher 21809aebddd1SJeff Kirsher req->port_num = port_num; 21819aebddd1SJeff Kirsher req->beacon_state = state; 21829aebddd1SJeff Kirsher req->beacon_duration = bcn; 21839aebddd1SJeff Kirsher req->status_duration = sts; 21849aebddd1SJeff Kirsher 21859aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 21869aebddd1SJeff Kirsher 21879aebddd1SJeff Kirsher err: 21889aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 21899aebddd1SJeff Kirsher return status; 21909aebddd1SJeff Kirsher } 21919aebddd1SJeff Kirsher 21929aebddd1SJeff Kirsher /* Uses sync mcc */ 21939aebddd1SJeff Kirsher int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) 21949aebddd1SJeff Kirsher { 21959aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21969aebddd1SJeff Kirsher struct be_cmd_req_get_beacon_state *req; 21979aebddd1SJeff Kirsher int status; 21989aebddd1SJeff Kirsher 21999aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 22009aebddd1SJeff Kirsher 22019aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 22029aebddd1SJeff Kirsher if (!wrb) { 22039aebddd1SJeff Kirsher status = -EBUSY; 22049aebddd1SJeff Kirsher goto err; 22059aebddd1SJeff Kirsher } 22069aebddd1SJeff Kirsher req = embedded_payload(wrb); 22079aebddd1SJeff Kirsher 2208106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2209a2cc4e0bSSathya Perla OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req), 2210a2cc4e0bSSathya Perla wrb, NULL); 22119aebddd1SJeff Kirsher 22129aebddd1SJeff Kirsher req->port_num = port_num; 22139aebddd1SJeff Kirsher 22149aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 22159aebddd1SJeff Kirsher if (!status) { 22169aebddd1SJeff Kirsher struct be_cmd_resp_get_beacon_state *resp = 22179aebddd1SJeff Kirsher embedded_payload(wrb); 221803d28ffeSKalesh AP 22199aebddd1SJeff Kirsher *state = resp->beacon_state; 22209aebddd1SJeff Kirsher } 22219aebddd1SJeff Kirsher 22229aebddd1SJeff Kirsher err: 22239aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 22249aebddd1SJeff Kirsher return status; 22259aebddd1SJeff Kirsher } 22269aebddd1SJeff Kirsher 2227e36edd9dSMark Leonard /* Uses sync mcc */ 2228e36edd9dSMark Leonard int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, 2229e36edd9dSMark Leonard u8 page_num, u8 *data) 2230e36edd9dSMark Leonard { 2231e36edd9dSMark Leonard struct be_dma_mem cmd; 2232e36edd9dSMark Leonard struct be_mcc_wrb *wrb; 2233e36edd9dSMark Leonard struct be_cmd_req_port_type *req; 2234e36edd9dSMark Leonard int status; 2235e36edd9dSMark Leonard 2236e36edd9dSMark Leonard if (page_num > TR_PAGE_A2) 2237e36edd9dSMark Leonard return -EINVAL; 2238e36edd9dSMark Leonard 2239e36edd9dSMark Leonard cmd.size = sizeof(struct be_cmd_resp_port_type); 2240e36edd9dSMark Leonard cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 2241e36edd9dSMark Leonard if (!cmd.va) { 2242e36edd9dSMark Leonard dev_err(&adapter->pdev->dev, "Memory allocation failed\n"); 2243e36edd9dSMark Leonard return -ENOMEM; 2244e36edd9dSMark Leonard } 2245e36edd9dSMark Leonard memset(cmd.va, 0, cmd.size); 2246e36edd9dSMark Leonard 2247e36edd9dSMark Leonard spin_lock_bh(&adapter->mcc_lock); 2248e36edd9dSMark Leonard 2249e36edd9dSMark Leonard wrb = wrb_from_mccq(adapter); 2250e36edd9dSMark Leonard if (!wrb) { 2251e36edd9dSMark Leonard status = -EBUSY; 2252e36edd9dSMark Leonard goto err; 2253e36edd9dSMark Leonard } 2254e36edd9dSMark Leonard req = cmd.va; 2255e36edd9dSMark Leonard 2256e36edd9dSMark Leonard be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2257e36edd9dSMark Leonard OPCODE_COMMON_READ_TRANSRECV_DATA, 2258e36edd9dSMark Leonard cmd.size, wrb, &cmd); 2259e36edd9dSMark Leonard 2260e36edd9dSMark Leonard req->port = cpu_to_le32(adapter->hba_port_num); 2261e36edd9dSMark Leonard req->page_num = cpu_to_le32(page_num); 2262e36edd9dSMark Leonard status = be_mcc_notify_wait(adapter); 2263e36edd9dSMark Leonard if (!status) { 2264e36edd9dSMark Leonard struct be_cmd_resp_port_type *resp = cmd.va; 2265e36edd9dSMark Leonard 2266e36edd9dSMark Leonard memcpy(data, resp->page_data, PAGE_DATA_LEN); 2267e36edd9dSMark Leonard } 2268e36edd9dSMark Leonard err: 2269e36edd9dSMark Leonard spin_unlock_bh(&adapter->mcc_lock); 2270e36edd9dSMark Leonard pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 2271e36edd9dSMark Leonard return status; 2272e36edd9dSMark Leonard } 2273e36edd9dSMark Leonard 22749aebddd1SJeff Kirsher int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, 2275f67ef7baSPadmanabh Ratnakar u32 data_size, u32 data_offset, 2276f67ef7baSPadmanabh Ratnakar const char *obj_name, u32 *data_written, 2277f67ef7baSPadmanabh Ratnakar u8 *change_status, u8 *addn_status) 22789aebddd1SJeff Kirsher { 22799aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 22809aebddd1SJeff Kirsher struct lancer_cmd_req_write_object *req; 22819aebddd1SJeff Kirsher struct lancer_cmd_resp_write_object *resp; 22829aebddd1SJeff Kirsher void *ctxt = NULL; 22839aebddd1SJeff Kirsher int status; 22849aebddd1SJeff Kirsher 22859aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 22869aebddd1SJeff Kirsher adapter->flash_status = 0; 22879aebddd1SJeff Kirsher 22889aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 22899aebddd1SJeff Kirsher if (!wrb) { 22909aebddd1SJeff Kirsher status = -EBUSY; 22919aebddd1SJeff Kirsher goto err_unlock; 22929aebddd1SJeff Kirsher } 22939aebddd1SJeff Kirsher 22949aebddd1SJeff Kirsher req = embedded_payload(wrb); 22959aebddd1SJeff Kirsher 2296106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 22979aebddd1SJeff Kirsher OPCODE_COMMON_WRITE_OBJECT, 2298106df1e3SSomnath Kotur sizeof(struct lancer_cmd_req_write_object), wrb, 2299106df1e3SSomnath Kotur NULL); 23009aebddd1SJeff Kirsher 23019aebddd1SJeff Kirsher ctxt = &req->context; 23029aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 23039aebddd1SJeff Kirsher write_length, ctxt, data_size); 23049aebddd1SJeff Kirsher 23059aebddd1SJeff Kirsher if (data_size == 0) 23069aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 23079aebddd1SJeff Kirsher eof, ctxt, 1); 23089aebddd1SJeff Kirsher else 23099aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 23109aebddd1SJeff Kirsher eof, ctxt, 0); 23119aebddd1SJeff Kirsher 23129aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 23139aebddd1SJeff Kirsher req->write_offset = cpu_to_le32(data_offset); 2314242eb470SVasundhara Volam strlcpy(req->object_name, obj_name, sizeof(req->object_name)); 23159aebddd1SJeff Kirsher req->descriptor_count = cpu_to_le32(1); 23169aebddd1SJeff Kirsher req->buf_len = cpu_to_le32(data_size); 23179aebddd1SJeff Kirsher req->addr_low = cpu_to_le32((cmd->dma + 23189aebddd1SJeff Kirsher sizeof(struct lancer_cmd_req_write_object)) 23199aebddd1SJeff Kirsher & 0xFFFFFFFF); 23209aebddd1SJeff Kirsher req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma + 23219aebddd1SJeff Kirsher sizeof(struct lancer_cmd_req_write_object))); 23229aebddd1SJeff Kirsher 23239aebddd1SJeff Kirsher be_mcc_notify(adapter); 23249aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 23259aebddd1SJeff Kirsher 23265eeff635SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 2327701962d0SSomnath Kotur msecs_to_jiffies(60000))) 2328fd45160cSKalesh AP status = -ETIMEDOUT; 23299aebddd1SJeff Kirsher else 23309aebddd1SJeff Kirsher status = adapter->flash_status; 23319aebddd1SJeff Kirsher 23329aebddd1SJeff Kirsher resp = embedded_payload(wrb); 2333f67ef7baSPadmanabh Ratnakar if (!status) { 23349aebddd1SJeff Kirsher *data_written = le32_to_cpu(resp->actual_write_len); 2335f67ef7baSPadmanabh Ratnakar *change_status = resp->change_status; 2336f67ef7baSPadmanabh Ratnakar } else { 23379aebddd1SJeff Kirsher *addn_status = resp->additional_status; 2338f67ef7baSPadmanabh Ratnakar } 23399aebddd1SJeff Kirsher 23409aebddd1SJeff Kirsher return status; 23419aebddd1SJeff Kirsher 23429aebddd1SJeff Kirsher err_unlock: 23439aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 23449aebddd1SJeff Kirsher return status; 23459aebddd1SJeff Kirsher } 23469aebddd1SJeff Kirsher 23476809cee0SRavikumar Nelavelli int be_cmd_query_cable_type(struct be_adapter *adapter) 23486809cee0SRavikumar Nelavelli { 23496809cee0SRavikumar Nelavelli u8 page_data[PAGE_DATA_LEN]; 23506809cee0SRavikumar Nelavelli int status; 23516809cee0SRavikumar Nelavelli 23526809cee0SRavikumar Nelavelli status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, 23536809cee0SRavikumar Nelavelli page_data); 23546809cee0SRavikumar Nelavelli if (!status) { 23556809cee0SRavikumar Nelavelli switch (adapter->phy.interface_type) { 23566809cee0SRavikumar Nelavelli case PHY_TYPE_QSFP: 23576809cee0SRavikumar Nelavelli adapter->phy.cable_type = 23586809cee0SRavikumar Nelavelli page_data[QSFP_PLUS_CABLE_TYPE_OFFSET]; 23596809cee0SRavikumar Nelavelli break; 23606809cee0SRavikumar Nelavelli case PHY_TYPE_SFP_PLUS_10GB: 23616809cee0SRavikumar Nelavelli adapter->phy.cable_type = 23626809cee0SRavikumar Nelavelli page_data[SFP_PLUS_CABLE_TYPE_OFFSET]; 23636809cee0SRavikumar Nelavelli break; 23646809cee0SRavikumar Nelavelli default: 23656809cee0SRavikumar Nelavelli adapter->phy.cable_type = 0; 23666809cee0SRavikumar Nelavelli break; 23676809cee0SRavikumar Nelavelli } 23686809cee0SRavikumar Nelavelli } 23696809cee0SRavikumar Nelavelli return status; 23706809cee0SRavikumar Nelavelli } 23716809cee0SRavikumar Nelavelli 237221252377SVasundhara Volam int be_cmd_query_sfp_info(struct be_adapter *adapter) 237321252377SVasundhara Volam { 237421252377SVasundhara Volam u8 page_data[PAGE_DATA_LEN]; 237521252377SVasundhara Volam int status; 237621252377SVasundhara Volam 237721252377SVasundhara Volam status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, 237821252377SVasundhara Volam page_data); 237921252377SVasundhara Volam if (!status) { 238021252377SVasundhara Volam strlcpy(adapter->phy.vendor_name, page_data + 238121252377SVasundhara Volam SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1); 238221252377SVasundhara Volam strlcpy(adapter->phy.vendor_pn, 238321252377SVasundhara Volam page_data + SFP_VENDOR_PN_OFFSET, 238421252377SVasundhara Volam SFP_VENDOR_NAME_LEN - 1); 238521252377SVasundhara Volam } 238621252377SVasundhara Volam 238721252377SVasundhara Volam return status; 238821252377SVasundhara Volam } 238921252377SVasundhara Volam 2390f0613380SKalesh AP int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name) 2391f0613380SKalesh AP { 2392f0613380SKalesh AP struct lancer_cmd_req_delete_object *req; 2393f0613380SKalesh AP struct be_mcc_wrb *wrb; 2394f0613380SKalesh AP int status; 2395f0613380SKalesh AP 2396f0613380SKalesh AP spin_lock_bh(&adapter->mcc_lock); 2397f0613380SKalesh AP 2398f0613380SKalesh AP wrb = wrb_from_mccq(adapter); 2399f0613380SKalesh AP if (!wrb) { 2400f0613380SKalesh AP status = -EBUSY; 2401f0613380SKalesh AP goto err; 2402f0613380SKalesh AP } 2403f0613380SKalesh AP 2404f0613380SKalesh AP req = embedded_payload(wrb); 2405f0613380SKalesh AP 2406f0613380SKalesh AP be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2407f0613380SKalesh AP OPCODE_COMMON_DELETE_OBJECT, 2408f0613380SKalesh AP sizeof(*req), wrb, NULL); 2409f0613380SKalesh AP 2410242eb470SVasundhara Volam strlcpy(req->object_name, obj_name, sizeof(req->object_name)); 2411f0613380SKalesh AP 2412f0613380SKalesh AP status = be_mcc_notify_wait(adapter); 2413f0613380SKalesh AP err: 2414f0613380SKalesh AP spin_unlock_bh(&adapter->mcc_lock); 2415f0613380SKalesh AP return status; 2416f0613380SKalesh AP } 2417f0613380SKalesh AP 2418de49bd5aSPadmanabh Ratnakar int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, 2419de49bd5aSPadmanabh Ratnakar u32 data_size, u32 data_offset, const char *obj_name, 2420de49bd5aSPadmanabh Ratnakar u32 *data_read, u32 *eof, u8 *addn_status) 2421de49bd5aSPadmanabh Ratnakar { 2422de49bd5aSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 2423de49bd5aSPadmanabh Ratnakar struct lancer_cmd_req_read_object *req; 2424de49bd5aSPadmanabh Ratnakar struct lancer_cmd_resp_read_object *resp; 2425de49bd5aSPadmanabh Ratnakar int status; 2426de49bd5aSPadmanabh Ratnakar 2427de49bd5aSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 2428de49bd5aSPadmanabh Ratnakar 2429de49bd5aSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 2430de49bd5aSPadmanabh Ratnakar if (!wrb) { 2431de49bd5aSPadmanabh Ratnakar status = -EBUSY; 2432de49bd5aSPadmanabh Ratnakar goto err_unlock; 2433de49bd5aSPadmanabh Ratnakar } 2434de49bd5aSPadmanabh Ratnakar 2435de49bd5aSPadmanabh Ratnakar req = embedded_payload(wrb); 2436de49bd5aSPadmanabh Ratnakar 2437de49bd5aSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2438de49bd5aSPadmanabh Ratnakar OPCODE_COMMON_READ_OBJECT, 2439de49bd5aSPadmanabh Ratnakar sizeof(struct lancer_cmd_req_read_object), wrb, 2440de49bd5aSPadmanabh Ratnakar NULL); 2441de49bd5aSPadmanabh Ratnakar 2442de49bd5aSPadmanabh Ratnakar req->desired_read_len = cpu_to_le32(data_size); 2443de49bd5aSPadmanabh Ratnakar req->read_offset = cpu_to_le32(data_offset); 2444de49bd5aSPadmanabh Ratnakar strcpy(req->object_name, obj_name); 2445de49bd5aSPadmanabh Ratnakar req->descriptor_count = cpu_to_le32(1); 2446de49bd5aSPadmanabh Ratnakar req->buf_len = cpu_to_le32(data_size); 2447de49bd5aSPadmanabh Ratnakar req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF)); 2448de49bd5aSPadmanabh Ratnakar req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma)); 2449de49bd5aSPadmanabh Ratnakar 2450de49bd5aSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 2451de49bd5aSPadmanabh Ratnakar 2452de49bd5aSPadmanabh Ratnakar resp = embedded_payload(wrb); 2453de49bd5aSPadmanabh Ratnakar if (!status) { 2454de49bd5aSPadmanabh Ratnakar *data_read = le32_to_cpu(resp->actual_read_len); 2455de49bd5aSPadmanabh Ratnakar *eof = le32_to_cpu(resp->eof); 2456de49bd5aSPadmanabh Ratnakar } else { 2457de49bd5aSPadmanabh Ratnakar *addn_status = resp->additional_status; 2458de49bd5aSPadmanabh Ratnakar } 2459de49bd5aSPadmanabh Ratnakar 2460de49bd5aSPadmanabh Ratnakar err_unlock: 2461de49bd5aSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 2462de49bd5aSPadmanabh Ratnakar return status; 2463de49bd5aSPadmanabh Ratnakar } 2464de49bd5aSPadmanabh Ratnakar 24659aebddd1SJeff Kirsher int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, 246670a7b525SVasundhara Volam u32 flash_type, u32 flash_opcode, u32 img_offset, 246770a7b525SVasundhara Volam u32 buf_size) 24689aebddd1SJeff Kirsher { 24699aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 24709aebddd1SJeff Kirsher struct be_cmd_write_flashrom *req; 24719aebddd1SJeff Kirsher int status; 24729aebddd1SJeff Kirsher 24739aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 24749aebddd1SJeff Kirsher adapter->flash_status = 0; 24759aebddd1SJeff Kirsher 24769aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 24779aebddd1SJeff Kirsher if (!wrb) { 24789aebddd1SJeff Kirsher status = -EBUSY; 24799aebddd1SJeff Kirsher goto err_unlock; 24809aebddd1SJeff Kirsher } 24819aebddd1SJeff Kirsher req = cmd->va; 24829aebddd1SJeff Kirsher 2483106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2484a2cc4e0bSSathya Perla OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb, 2485a2cc4e0bSSathya Perla cmd); 24869aebddd1SJeff Kirsher 24879aebddd1SJeff Kirsher req->params.op_type = cpu_to_le32(flash_type); 248870a7b525SVasundhara Volam if (flash_type == OPTYPE_OFFSET_SPECIFIED) 248970a7b525SVasundhara Volam req->params.offset = cpu_to_le32(img_offset); 249070a7b525SVasundhara Volam 24919aebddd1SJeff Kirsher req->params.op_code = cpu_to_le32(flash_opcode); 24929aebddd1SJeff Kirsher req->params.data_buf_size = cpu_to_le32(buf_size); 24939aebddd1SJeff Kirsher 24949aebddd1SJeff Kirsher be_mcc_notify(adapter); 24959aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 24969aebddd1SJeff Kirsher 24975eeff635SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 2498e2edb7d5SSathya Perla msecs_to_jiffies(40000))) 2499fd45160cSKalesh AP status = -ETIMEDOUT; 25009aebddd1SJeff Kirsher else 25019aebddd1SJeff Kirsher status = adapter->flash_status; 25029aebddd1SJeff Kirsher 25039aebddd1SJeff Kirsher return status; 25049aebddd1SJeff Kirsher 25059aebddd1SJeff Kirsher err_unlock: 25069aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25079aebddd1SJeff Kirsher return status; 25089aebddd1SJeff Kirsher } 25099aebddd1SJeff Kirsher 25109aebddd1SJeff Kirsher int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, 251170a7b525SVasundhara Volam u16 img_optype, u32 img_offset, u32 crc_offset) 25129aebddd1SJeff Kirsher { 2513be716446SPadmanabh Ratnakar struct be_cmd_read_flash_crc *req; 251470a7b525SVasundhara Volam struct be_mcc_wrb *wrb; 25159aebddd1SJeff Kirsher int status; 25169aebddd1SJeff Kirsher 25179aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 25189aebddd1SJeff Kirsher 25199aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 25209aebddd1SJeff Kirsher if (!wrb) { 25219aebddd1SJeff Kirsher status = -EBUSY; 25229aebddd1SJeff Kirsher goto err; 25239aebddd1SJeff Kirsher } 25249aebddd1SJeff Kirsher req = embedded_payload(wrb); 25259aebddd1SJeff Kirsher 2526106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2527be716446SPadmanabh Ratnakar OPCODE_COMMON_READ_FLASHROM, sizeof(*req), 2528be716446SPadmanabh Ratnakar wrb, NULL); 25299aebddd1SJeff Kirsher 253070a7b525SVasundhara Volam req->params.op_type = cpu_to_le32(img_optype); 253170a7b525SVasundhara Volam if (img_optype == OPTYPE_OFFSET_SPECIFIED) 253270a7b525SVasundhara Volam req->params.offset = cpu_to_le32(img_offset + crc_offset); 253370a7b525SVasundhara Volam else 253470a7b525SVasundhara Volam req->params.offset = cpu_to_le32(crc_offset); 253570a7b525SVasundhara Volam 25369aebddd1SJeff Kirsher req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); 25379aebddd1SJeff Kirsher req->params.data_buf_size = cpu_to_le32(0x4); 25389aebddd1SJeff Kirsher 25399aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 25409aebddd1SJeff Kirsher if (!status) 2541be716446SPadmanabh Ratnakar memcpy(flashed_crc, req->crc, 4); 25429aebddd1SJeff Kirsher 25439aebddd1SJeff Kirsher err: 25449aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25459aebddd1SJeff Kirsher return status; 25469aebddd1SJeff Kirsher } 25479aebddd1SJeff Kirsher 25489aebddd1SJeff Kirsher int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, 25499aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 25509aebddd1SJeff Kirsher { 25519aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 25529aebddd1SJeff Kirsher struct be_cmd_req_acpi_wol_magic_config *req; 25539aebddd1SJeff Kirsher int status; 25549aebddd1SJeff Kirsher 25559aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 25569aebddd1SJeff Kirsher 25579aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 25589aebddd1SJeff Kirsher if (!wrb) { 25599aebddd1SJeff Kirsher status = -EBUSY; 25609aebddd1SJeff Kirsher goto err; 25619aebddd1SJeff Kirsher } 25629aebddd1SJeff Kirsher req = nonemb_cmd->va; 25639aebddd1SJeff Kirsher 2564106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 2565a2cc4e0bSSathya Perla OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req), 2566a2cc4e0bSSathya Perla wrb, nonemb_cmd); 25679aebddd1SJeff Kirsher memcpy(req->magic_mac, mac, ETH_ALEN); 25689aebddd1SJeff Kirsher 25699aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 25709aebddd1SJeff Kirsher 25719aebddd1SJeff Kirsher err: 25729aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25739aebddd1SJeff Kirsher return status; 25749aebddd1SJeff Kirsher } 25759aebddd1SJeff Kirsher 25769aebddd1SJeff Kirsher int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, 25779aebddd1SJeff Kirsher u8 loopback_type, u8 enable) 25789aebddd1SJeff Kirsher { 25799aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 25809aebddd1SJeff Kirsher struct be_cmd_req_set_lmode *req; 25819aebddd1SJeff Kirsher int status; 25829aebddd1SJeff Kirsher 25839aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 25849aebddd1SJeff Kirsher 25859aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 25869aebddd1SJeff Kirsher if (!wrb) { 25879aebddd1SJeff Kirsher status = -EBUSY; 25889aebddd1SJeff Kirsher goto err; 25899aebddd1SJeff Kirsher } 25909aebddd1SJeff Kirsher 25919aebddd1SJeff Kirsher req = embedded_payload(wrb); 25929aebddd1SJeff Kirsher 2593106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 2594a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req), 2595a2cc4e0bSSathya Perla wrb, NULL); 25969aebddd1SJeff Kirsher 25979aebddd1SJeff Kirsher req->src_port = port_num; 25989aebddd1SJeff Kirsher req->dest_port = port_num; 25999aebddd1SJeff Kirsher req->loopback_type = loopback_type; 26009aebddd1SJeff Kirsher req->loopback_state = enable; 26019aebddd1SJeff Kirsher 26029aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 26039aebddd1SJeff Kirsher err: 26049aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 26059aebddd1SJeff Kirsher return status; 26069aebddd1SJeff Kirsher } 26079aebddd1SJeff Kirsher 26089aebddd1SJeff Kirsher int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, 2609a2cc4e0bSSathya Perla u32 loopback_type, u32 pkt_size, u32 num_pkts, 2610a2cc4e0bSSathya Perla u64 pattern) 26119aebddd1SJeff Kirsher { 26129aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 26139aebddd1SJeff Kirsher struct be_cmd_req_loopback_test *req; 26145eeff635SSuresh Reddy struct be_cmd_resp_loopback_test *resp; 26159aebddd1SJeff Kirsher int status; 26169aebddd1SJeff Kirsher 26179aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 26189aebddd1SJeff Kirsher 26199aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 26209aebddd1SJeff Kirsher if (!wrb) { 26219aebddd1SJeff Kirsher status = -EBUSY; 26229aebddd1SJeff Kirsher goto err; 26239aebddd1SJeff Kirsher } 26249aebddd1SJeff Kirsher 26259aebddd1SJeff Kirsher req = embedded_payload(wrb); 26269aebddd1SJeff Kirsher 2627106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 2628a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, 2629a2cc4e0bSSathya Perla NULL); 26309aebddd1SJeff Kirsher 26315eeff635SSuresh Reddy req->hdr.timeout = cpu_to_le32(15); 26329aebddd1SJeff Kirsher req->pattern = cpu_to_le64(pattern); 26339aebddd1SJeff Kirsher req->src_port = cpu_to_le32(port_num); 26349aebddd1SJeff Kirsher req->dest_port = cpu_to_le32(port_num); 26359aebddd1SJeff Kirsher req->pkt_size = cpu_to_le32(pkt_size); 26369aebddd1SJeff Kirsher req->num_pkts = cpu_to_le32(num_pkts); 26379aebddd1SJeff Kirsher req->loopback_type = cpu_to_le32(loopback_type); 26389aebddd1SJeff Kirsher 26395eeff635SSuresh Reddy be_mcc_notify(adapter); 26409aebddd1SJeff Kirsher 26415eeff635SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 26425eeff635SSuresh Reddy 26435eeff635SSuresh Reddy wait_for_completion(&adapter->et_cmd_compl); 26445eeff635SSuresh Reddy resp = embedded_payload(wrb); 26455eeff635SSuresh Reddy status = le32_to_cpu(resp->status); 26465eeff635SSuresh Reddy 26475eeff635SSuresh Reddy return status; 26489aebddd1SJeff Kirsher err: 26499aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 26509aebddd1SJeff Kirsher return status; 26519aebddd1SJeff Kirsher } 26529aebddd1SJeff Kirsher 26539aebddd1SJeff Kirsher int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, 26549aebddd1SJeff Kirsher u32 byte_cnt, struct be_dma_mem *cmd) 26559aebddd1SJeff Kirsher { 26569aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 26579aebddd1SJeff Kirsher struct be_cmd_req_ddrdma_test *req; 26589aebddd1SJeff Kirsher int status; 26599aebddd1SJeff Kirsher int i, j = 0; 26609aebddd1SJeff Kirsher 26619aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 26629aebddd1SJeff Kirsher 26639aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 26649aebddd1SJeff Kirsher if (!wrb) { 26659aebddd1SJeff Kirsher status = -EBUSY; 26669aebddd1SJeff Kirsher goto err; 26679aebddd1SJeff Kirsher } 26689aebddd1SJeff Kirsher req = cmd->va; 2669106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 2670a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb, 2671a2cc4e0bSSathya Perla cmd); 26729aebddd1SJeff Kirsher 26739aebddd1SJeff Kirsher req->pattern = cpu_to_le64(pattern); 26749aebddd1SJeff Kirsher req->byte_count = cpu_to_le32(byte_cnt); 26759aebddd1SJeff Kirsher for (i = 0; i < byte_cnt; i++) { 26769aebddd1SJeff Kirsher req->snd_buff[i] = (u8)(pattern >> (j*8)); 26779aebddd1SJeff Kirsher j++; 26789aebddd1SJeff Kirsher if (j > 7) 26799aebddd1SJeff Kirsher j = 0; 26809aebddd1SJeff Kirsher } 26819aebddd1SJeff Kirsher 26829aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 26839aebddd1SJeff Kirsher 26849aebddd1SJeff Kirsher if (!status) { 26859aebddd1SJeff Kirsher struct be_cmd_resp_ddrdma_test *resp; 268603d28ffeSKalesh AP 26879aebddd1SJeff Kirsher resp = cmd->va; 26889aebddd1SJeff Kirsher if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) || 26899aebddd1SJeff Kirsher resp->snd_err) { 26909aebddd1SJeff Kirsher status = -1; 26919aebddd1SJeff Kirsher } 26929aebddd1SJeff Kirsher } 26939aebddd1SJeff Kirsher 26949aebddd1SJeff Kirsher err: 26959aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 26969aebddd1SJeff Kirsher return status; 26979aebddd1SJeff Kirsher } 26989aebddd1SJeff Kirsher 26999aebddd1SJeff Kirsher int be_cmd_get_seeprom_data(struct be_adapter *adapter, 27009aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 27019aebddd1SJeff Kirsher { 27029aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 27039aebddd1SJeff Kirsher struct be_cmd_req_seeprom_read *req; 27049aebddd1SJeff Kirsher int status; 27059aebddd1SJeff Kirsher 27069aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 27079aebddd1SJeff Kirsher 27089aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 27099aebddd1SJeff Kirsher if (!wrb) { 27109aebddd1SJeff Kirsher status = -EBUSY; 27119aebddd1SJeff Kirsher goto err; 27129aebddd1SJeff Kirsher } 27139aebddd1SJeff Kirsher req = nonemb_cmd->va; 27149aebddd1SJeff Kirsher 2715106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2716106df1e3SSomnath Kotur OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb, 2717106df1e3SSomnath Kotur nonemb_cmd); 27189aebddd1SJeff Kirsher 27199aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 27209aebddd1SJeff Kirsher 27219aebddd1SJeff Kirsher err: 27229aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 27239aebddd1SJeff Kirsher return status; 27249aebddd1SJeff Kirsher } 27259aebddd1SJeff Kirsher 272642f11cf2SAjit Khaparde int be_cmd_get_phy_info(struct be_adapter *adapter) 27279aebddd1SJeff Kirsher { 27289aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 27299aebddd1SJeff Kirsher struct be_cmd_req_get_phy_info *req; 27309aebddd1SJeff Kirsher struct be_dma_mem cmd; 27319aebddd1SJeff Kirsher int status; 27329aebddd1SJeff Kirsher 2733f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS, 2734f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 2735f25b119cSPadmanabh Ratnakar return -EPERM; 2736f25b119cSPadmanabh Ratnakar 27379aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 27389aebddd1SJeff Kirsher 27399aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 27409aebddd1SJeff Kirsher if (!wrb) { 27419aebddd1SJeff Kirsher status = -EBUSY; 27429aebddd1SJeff Kirsher goto err; 27439aebddd1SJeff Kirsher } 27449aebddd1SJeff Kirsher cmd.size = sizeof(struct be_cmd_req_get_phy_info); 2745a2cc4e0bSSathya Perla cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 27469aebddd1SJeff Kirsher if (!cmd.va) { 27479aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); 27489aebddd1SJeff Kirsher status = -ENOMEM; 27499aebddd1SJeff Kirsher goto err; 27509aebddd1SJeff Kirsher } 27519aebddd1SJeff Kirsher 27529aebddd1SJeff Kirsher req = cmd.va; 27539aebddd1SJeff Kirsher 2754106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2755106df1e3SSomnath Kotur OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req), 2756106df1e3SSomnath Kotur wrb, &cmd); 27579aebddd1SJeff Kirsher 27589aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 27599aebddd1SJeff Kirsher if (!status) { 27609aebddd1SJeff Kirsher struct be_phy_info *resp_phy_info = 27619aebddd1SJeff Kirsher cmd.va + sizeof(struct be_cmd_req_hdr); 276203d28ffeSKalesh AP 276342f11cf2SAjit Khaparde adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type); 276442f11cf2SAjit Khaparde adapter->phy.interface_type = 27659aebddd1SJeff Kirsher le16_to_cpu(resp_phy_info->interface_type); 276642f11cf2SAjit Khaparde adapter->phy.auto_speeds_supported = 276742f11cf2SAjit Khaparde le16_to_cpu(resp_phy_info->auto_speeds_supported); 276842f11cf2SAjit Khaparde adapter->phy.fixed_speeds_supported = 276942f11cf2SAjit Khaparde le16_to_cpu(resp_phy_info->fixed_speeds_supported); 277042f11cf2SAjit Khaparde adapter->phy.misc_params = 277142f11cf2SAjit Khaparde le32_to_cpu(resp_phy_info->misc_params); 277268cb7e47SVasundhara Volam 277368cb7e47SVasundhara Volam if (BE2_chip(adapter)) { 277468cb7e47SVasundhara Volam adapter->phy.fixed_speeds_supported = 277568cb7e47SVasundhara Volam BE_SUPPORTED_SPEED_10GBPS | 277668cb7e47SVasundhara Volam BE_SUPPORTED_SPEED_1GBPS; 277768cb7e47SVasundhara Volam } 27789aebddd1SJeff Kirsher } 2779a2cc4e0bSSathya Perla pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 27809aebddd1SJeff Kirsher err: 27819aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 27829aebddd1SJeff Kirsher return status; 27839aebddd1SJeff Kirsher } 27849aebddd1SJeff Kirsher 2785bc0ee163SLad, Prabhakar static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain) 27869aebddd1SJeff Kirsher { 27879aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 27889aebddd1SJeff Kirsher struct be_cmd_req_set_qos *req; 27899aebddd1SJeff Kirsher int status; 27909aebddd1SJeff Kirsher 27919aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 27929aebddd1SJeff Kirsher 27939aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 27949aebddd1SJeff Kirsher if (!wrb) { 27959aebddd1SJeff Kirsher status = -EBUSY; 27969aebddd1SJeff Kirsher goto err; 27979aebddd1SJeff Kirsher } 27989aebddd1SJeff Kirsher 27999aebddd1SJeff Kirsher req = embedded_payload(wrb); 28009aebddd1SJeff Kirsher 2801106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2802106df1e3SSomnath Kotur OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL); 28039aebddd1SJeff Kirsher 28049aebddd1SJeff Kirsher req->hdr.domain = domain; 28059aebddd1SJeff Kirsher req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC); 28069aebddd1SJeff Kirsher req->max_bps_nic = cpu_to_le32(bps); 28079aebddd1SJeff Kirsher 28089aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 28099aebddd1SJeff Kirsher 28109aebddd1SJeff Kirsher err: 28119aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 28129aebddd1SJeff Kirsher return status; 28139aebddd1SJeff Kirsher } 28149aebddd1SJeff Kirsher 28159aebddd1SJeff Kirsher int be_cmd_get_cntl_attributes(struct be_adapter *adapter) 28169aebddd1SJeff Kirsher { 28179aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 28189aebddd1SJeff Kirsher struct be_cmd_req_cntl_attribs *req; 28199aebddd1SJeff Kirsher struct be_cmd_resp_cntl_attribs *resp; 28209aebddd1SJeff Kirsher int status; 28219aebddd1SJeff Kirsher int payload_len = max(sizeof(*req), sizeof(*resp)); 28229aebddd1SJeff Kirsher struct mgmt_controller_attrib *attribs; 28239aebddd1SJeff Kirsher struct be_dma_mem attribs_cmd; 28249aebddd1SJeff Kirsher 2825d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 2826d98ef50fSSuresh Reddy return -1; 2827d98ef50fSSuresh Reddy 28289aebddd1SJeff Kirsher memset(&attribs_cmd, 0, sizeof(struct be_dma_mem)); 28299aebddd1SJeff Kirsher attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs); 28309aebddd1SJeff Kirsher attribs_cmd.va = pci_alloc_consistent(adapter->pdev, attribs_cmd.size, 28319aebddd1SJeff Kirsher &attribs_cmd.dma); 28329aebddd1SJeff Kirsher if (!attribs_cmd.va) { 2833a2cc4e0bSSathya Perla dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); 2834d98ef50fSSuresh Reddy status = -ENOMEM; 2835d98ef50fSSuresh Reddy goto err; 28369aebddd1SJeff Kirsher } 28379aebddd1SJeff Kirsher 28389aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 28399aebddd1SJeff Kirsher if (!wrb) { 28409aebddd1SJeff Kirsher status = -EBUSY; 28419aebddd1SJeff Kirsher goto err; 28429aebddd1SJeff Kirsher } 28439aebddd1SJeff Kirsher req = attribs_cmd.va; 28449aebddd1SJeff Kirsher 2845106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2846a2cc4e0bSSathya Perla OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len, 2847a2cc4e0bSSathya Perla wrb, &attribs_cmd); 28489aebddd1SJeff Kirsher 28499aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 28509aebddd1SJeff Kirsher if (!status) { 28519aebddd1SJeff Kirsher attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr); 28529aebddd1SJeff Kirsher adapter->hba_port_num = attribs->hba_attribs.phy_port; 28539aebddd1SJeff Kirsher } 28549aebddd1SJeff Kirsher 28559aebddd1SJeff Kirsher err: 28569aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 2857d98ef50fSSuresh Reddy if (attribs_cmd.va) 2858d98ef50fSSuresh Reddy pci_free_consistent(adapter->pdev, attribs_cmd.size, 2859d98ef50fSSuresh Reddy attribs_cmd.va, attribs_cmd.dma); 28609aebddd1SJeff Kirsher return status; 28619aebddd1SJeff Kirsher } 28629aebddd1SJeff Kirsher 28639aebddd1SJeff Kirsher /* Uses mbox */ 28649aebddd1SJeff Kirsher int be_cmd_req_native_mode(struct be_adapter *adapter) 28659aebddd1SJeff Kirsher { 28669aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 28679aebddd1SJeff Kirsher struct be_cmd_req_set_func_cap *req; 28689aebddd1SJeff Kirsher int status; 28699aebddd1SJeff Kirsher 28709aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 28719aebddd1SJeff Kirsher return -1; 28729aebddd1SJeff Kirsher 28739aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 28749aebddd1SJeff Kirsher if (!wrb) { 28759aebddd1SJeff Kirsher status = -EBUSY; 28769aebddd1SJeff Kirsher goto err; 28779aebddd1SJeff Kirsher } 28789aebddd1SJeff Kirsher 28799aebddd1SJeff Kirsher req = embedded_payload(wrb); 28809aebddd1SJeff Kirsher 2881106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2882a2cc4e0bSSathya Perla OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP, 2883a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 28849aebddd1SJeff Kirsher 28859aebddd1SJeff Kirsher req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS | 28869aebddd1SJeff Kirsher CAPABILITY_BE3_NATIVE_ERX_API); 28879aebddd1SJeff Kirsher req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API); 28889aebddd1SJeff Kirsher 28899aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 28909aebddd1SJeff Kirsher if (!status) { 28919aebddd1SJeff Kirsher struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb); 289203d28ffeSKalesh AP 28939aebddd1SJeff Kirsher adapter->be3_native = le32_to_cpu(resp->cap_flags) & 28949aebddd1SJeff Kirsher CAPABILITY_BE3_NATIVE_ERX_API; 2895d379142bSSathya Perla if (!adapter->be3_native) 2896d379142bSSathya Perla dev_warn(&adapter->pdev->dev, 2897d379142bSSathya Perla "adapter not in advanced mode\n"); 28989aebddd1SJeff Kirsher } 28999aebddd1SJeff Kirsher err: 29009aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 29019aebddd1SJeff Kirsher return status; 29029aebddd1SJeff Kirsher } 2903590c391dSPadmanabh Ratnakar 2904f25b119cSPadmanabh Ratnakar /* Get privilege(s) for a function */ 2905f25b119cSPadmanabh Ratnakar int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, 2906f25b119cSPadmanabh Ratnakar u32 domain) 2907f25b119cSPadmanabh Ratnakar { 2908f25b119cSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 2909f25b119cSPadmanabh Ratnakar struct be_cmd_req_get_fn_privileges *req; 2910f25b119cSPadmanabh Ratnakar int status; 2911f25b119cSPadmanabh Ratnakar 2912f25b119cSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 2913f25b119cSPadmanabh Ratnakar 2914f25b119cSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 2915f25b119cSPadmanabh Ratnakar if (!wrb) { 2916f25b119cSPadmanabh Ratnakar status = -EBUSY; 2917f25b119cSPadmanabh Ratnakar goto err; 2918f25b119cSPadmanabh Ratnakar } 2919f25b119cSPadmanabh Ratnakar 2920f25b119cSPadmanabh Ratnakar req = embedded_payload(wrb); 2921f25b119cSPadmanabh Ratnakar 2922f25b119cSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2923f25b119cSPadmanabh Ratnakar OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req), 2924f25b119cSPadmanabh Ratnakar wrb, NULL); 2925f25b119cSPadmanabh Ratnakar 2926f25b119cSPadmanabh Ratnakar req->hdr.domain = domain; 2927f25b119cSPadmanabh Ratnakar 2928f25b119cSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 2929f25b119cSPadmanabh Ratnakar if (!status) { 2930f25b119cSPadmanabh Ratnakar struct be_cmd_resp_get_fn_privileges *resp = 2931f25b119cSPadmanabh Ratnakar embedded_payload(wrb); 293203d28ffeSKalesh AP 2933f25b119cSPadmanabh Ratnakar *privilege = le32_to_cpu(resp->privilege_mask); 293402308d74SSuresh Reddy 293502308d74SSuresh Reddy /* In UMC mode FW does not return right privileges. 293602308d74SSuresh Reddy * Override with correct privilege equivalent to PF. 293702308d74SSuresh Reddy */ 293802308d74SSuresh Reddy if (BEx_chip(adapter) && be_is_mc(adapter) && 293902308d74SSuresh Reddy be_physfn(adapter)) 294002308d74SSuresh Reddy *privilege = MAX_PRIVILEGES; 2941f25b119cSPadmanabh Ratnakar } 2942f25b119cSPadmanabh Ratnakar 2943f25b119cSPadmanabh Ratnakar err: 2944f25b119cSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 2945f25b119cSPadmanabh Ratnakar return status; 2946f25b119cSPadmanabh Ratnakar } 2947f25b119cSPadmanabh Ratnakar 294804a06028SSathya Perla /* Set privilege(s) for a function */ 294904a06028SSathya Perla int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, 295004a06028SSathya Perla u32 domain) 295104a06028SSathya Perla { 295204a06028SSathya Perla struct be_mcc_wrb *wrb; 295304a06028SSathya Perla struct be_cmd_req_set_fn_privileges *req; 295404a06028SSathya Perla int status; 295504a06028SSathya Perla 295604a06028SSathya Perla spin_lock_bh(&adapter->mcc_lock); 295704a06028SSathya Perla 295804a06028SSathya Perla wrb = wrb_from_mccq(adapter); 295904a06028SSathya Perla if (!wrb) { 296004a06028SSathya Perla status = -EBUSY; 296104a06028SSathya Perla goto err; 296204a06028SSathya Perla } 296304a06028SSathya Perla 296404a06028SSathya Perla req = embedded_payload(wrb); 296504a06028SSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 296604a06028SSathya Perla OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req), 296704a06028SSathya Perla wrb, NULL); 296804a06028SSathya Perla req->hdr.domain = domain; 296904a06028SSathya Perla if (lancer_chip(adapter)) 297004a06028SSathya Perla req->privileges_lancer = cpu_to_le32(privileges); 297104a06028SSathya Perla else 297204a06028SSathya Perla req->privileges = cpu_to_le32(privileges); 297304a06028SSathya Perla 297404a06028SSathya Perla status = be_mcc_notify_wait(adapter); 297504a06028SSathya Perla err: 297604a06028SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 297704a06028SSathya Perla return status; 297804a06028SSathya Perla } 297904a06028SSathya Perla 29805a712c13SSathya Perla /* pmac_id_valid: true => pmac_id is supplied and MAC address is requested. 29815a712c13SSathya Perla * pmac_id_valid: false => pmac_id or MAC address is requested. 29825a712c13SSathya Perla * If pmac_id is returned, pmac_id_valid is returned as true 29835a712c13SSathya Perla */ 29841578e777SPadmanabh Ratnakar int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, 2985b188f090SSuresh Reddy bool *pmac_id_valid, u32 *pmac_id, u32 if_handle, 2986b188f090SSuresh Reddy u8 domain) 2987590c391dSPadmanabh Ratnakar { 2988590c391dSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 2989590c391dSPadmanabh Ratnakar struct be_cmd_req_get_mac_list *req; 2990590c391dSPadmanabh Ratnakar int status; 2991590c391dSPadmanabh Ratnakar int mac_count; 2992e5e1ee89SPadmanabh Ratnakar struct be_dma_mem get_mac_list_cmd; 2993e5e1ee89SPadmanabh Ratnakar int i; 2994e5e1ee89SPadmanabh Ratnakar 2995e5e1ee89SPadmanabh Ratnakar memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem)); 2996e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list); 2997e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev, 2998e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.size, 2999e5e1ee89SPadmanabh Ratnakar &get_mac_list_cmd.dma); 3000e5e1ee89SPadmanabh Ratnakar 3001e5e1ee89SPadmanabh Ratnakar if (!get_mac_list_cmd.va) { 3002e5e1ee89SPadmanabh Ratnakar dev_err(&adapter->pdev->dev, 3003e5e1ee89SPadmanabh Ratnakar "Memory allocation failure during GET_MAC_LIST\n"); 3004e5e1ee89SPadmanabh Ratnakar return -ENOMEM; 3005e5e1ee89SPadmanabh Ratnakar } 3006590c391dSPadmanabh Ratnakar 3007590c391dSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 3008590c391dSPadmanabh Ratnakar 3009590c391dSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 3010590c391dSPadmanabh Ratnakar if (!wrb) { 3011590c391dSPadmanabh Ratnakar status = -EBUSY; 3012e5e1ee89SPadmanabh Ratnakar goto out; 3013590c391dSPadmanabh Ratnakar } 3014e5e1ee89SPadmanabh Ratnakar 3015e5e1ee89SPadmanabh Ratnakar req = get_mac_list_cmd.va; 3016590c391dSPadmanabh Ratnakar 3017590c391dSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3018bf591f51SSathya Perla OPCODE_COMMON_GET_MAC_LIST, 3019bf591f51SSathya Perla get_mac_list_cmd.size, wrb, &get_mac_list_cmd); 3020590c391dSPadmanabh Ratnakar req->hdr.domain = domain; 3021e5e1ee89SPadmanabh Ratnakar req->mac_type = MAC_ADDRESS_TYPE_NETWORK; 30225a712c13SSathya Perla if (*pmac_id_valid) { 30235a712c13SSathya Perla req->mac_id = cpu_to_le32(*pmac_id); 3024b188f090SSuresh Reddy req->iface_id = cpu_to_le16(if_handle); 30255a712c13SSathya Perla req->perm_override = 0; 30265a712c13SSathya Perla } else { 3027e5e1ee89SPadmanabh Ratnakar req->perm_override = 1; 30285a712c13SSathya Perla } 3029590c391dSPadmanabh Ratnakar 3030590c391dSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 3031590c391dSPadmanabh Ratnakar if (!status) { 3032590c391dSPadmanabh Ratnakar struct be_cmd_resp_get_mac_list *resp = 3033e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va; 30345a712c13SSathya Perla 30355a712c13SSathya Perla if (*pmac_id_valid) { 30365a712c13SSathya Perla memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr, 30375a712c13SSathya Perla ETH_ALEN); 30385a712c13SSathya Perla goto out; 30395a712c13SSathya Perla } 30405a712c13SSathya Perla 3041e5e1ee89SPadmanabh Ratnakar mac_count = resp->true_mac_count + resp->pseudo_mac_count; 3042e5e1ee89SPadmanabh Ratnakar /* Mac list returned could contain one or more active mac_ids 3043dbedd44eSJoe Perches * or one or more true or pseudo permanent mac addresses. 30441578e777SPadmanabh Ratnakar * If an active mac_id is present, return first active mac_id 30451578e777SPadmanabh Ratnakar * found. 3046e5e1ee89SPadmanabh Ratnakar */ 3047590c391dSPadmanabh Ratnakar for (i = 0; i < mac_count; i++) { 3048e5e1ee89SPadmanabh Ratnakar struct get_list_macaddr *mac_entry; 3049e5e1ee89SPadmanabh Ratnakar u16 mac_addr_size; 3050e5e1ee89SPadmanabh Ratnakar u32 mac_id; 3051e5e1ee89SPadmanabh Ratnakar 3052e5e1ee89SPadmanabh Ratnakar mac_entry = &resp->macaddr_list[i]; 3053e5e1ee89SPadmanabh Ratnakar mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size); 3054e5e1ee89SPadmanabh Ratnakar /* mac_id is a 32 bit value and mac_addr size 3055e5e1ee89SPadmanabh Ratnakar * is 6 bytes 3056e5e1ee89SPadmanabh Ratnakar */ 3057e5e1ee89SPadmanabh Ratnakar if (mac_addr_size == sizeof(u32)) { 30585a712c13SSathya Perla *pmac_id_valid = true; 3059e5e1ee89SPadmanabh Ratnakar mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; 3060e5e1ee89SPadmanabh Ratnakar *pmac_id = le32_to_cpu(mac_id); 3061e5e1ee89SPadmanabh Ratnakar goto out; 3062590c391dSPadmanabh Ratnakar } 3063590c391dSPadmanabh Ratnakar } 30641578e777SPadmanabh Ratnakar /* If no active mac_id found, return first mac addr */ 30655a712c13SSathya Perla *pmac_id_valid = false; 3066e5e1ee89SPadmanabh Ratnakar memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, 3067e5e1ee89SPadmanabh Ratnakar ETH_ALEN); 3068590c391dSPadmanabh Ratnakar } 3069590c391dSPadmanabh Ratnakar 3070e5e1ee89SPadmanabh Ratnakar out: 3071590c391dSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 3072e5e1ee89SPadmanabh Ratnakar pci_free_consistent(adapter->pdev, get_mac_list_cmd.size, 3073e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va, get_mac_list_cmd.dma); 3074590c391dSPadmanabh Ratnakar return status; 3075590c391dSPadmanabh Ratnakar } 3076590c391dSPadmanabh Ratnakar 3077a2cc4e0bSSathya Perla int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id, 3078a2cc4e0bSSathya Perla u8 *mac, u32 if_handle, bool active, u32 domain) 30795a712c13SSathya Perla { 3080b188f090SSuresh Reddy if (!active) 3081b188f090SSuresh Reddy be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id, 3082b188f090SSuresh Reddy if_handle, domain); 30833175d8c2SSathya Perla if (BEx_chip(adapter)) 30845a712c13SSathya Perla return be_cmd_mac_addr_query(adapter, mac, false, 3085b188f090SSuresh Reddy if_handle, curr_pmac_id); 30863175d8c2SSathya Perla else 30873175d8c2SSathya Perla /* Fetch the MAC address using pmac_id */ 30883175d8c2SSathya Perla return be_cmd_get_mac_from_list(adapter, mac, &active, 3089b188f090SSuresh Reddy &curr_pmac_id, 3090b188f090SSuresh Reddy if_handle, domain); 30915a712c13SSathya Perla } 30925a712c13SSathya Perla 309395046b92SSathya Perla int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac) 309495046b92SSathya Perla { 309595046b92SSathya Perla int status; 309695046b92SSathya Perla bool pmac_valid = false; 309795046b92SSathya Perla 3098c7bf7169SJoe Perches eth_zero_addr(mac); 309995046b92SSathya Perla 31003175d8c2SSathya Perla if (BEx_chip(adapter)) { 31013175d8c2SSathya Perla if (be_physfn(adapter)) 31023175d8c2SSathya Perla status = be_cmd_mac_addr_query(adapter, mac, true, 0, 31033175d8c2SSathya Perla 0); 310495046b92SSathya Perla else 310595046b92SSathya Perla status = be_cmd_mac_addr_query(adapter, mac, false, 310695046b92SSathya Perla adapter->if_handle, 0); 31073175d8c2SSathya Perla } else { 31083175d8c2SSathya Perla status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid, 3109b188f090SSuresh Reddy NULL, adapter->if_handle, 0); 31103175d8c2SSathya Perla } 31113175d8c2SSathya Perla 311295046b92SSathya Perla return status; 311395046b92SSathya Perla } 311495046b92SSathya Perla 3115590c391dSPadmanabh Ratnakar /* Uses synchronous MCCQ */ 3116590c391dSPadmanabh Ratnakar int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, 3117590c391dSPadmanabh Ratnakar u8 mac_count, u32 domain) 3118590c391dSPadmanabh Ratnakar { 3119590c391dSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3120590c391dSPadmanabh Ratnakar struct be_cmd_req_set_mac_list *req; 3121590c391dSPadmanabh Ratnakar int status; 3122590c391dSPadmanabh Ratnakar struct be_dma_mem cmd; 3123590c391dSPadmanabh Ratnakar 3124590c391dSPadmanabh Ratnakar memset(&cmd, 0, sizeof(struct be_dma_mem)); 3125590c391dSPadmanabh Ratnakar cmd.size = sizeof(struct be_cmd_req_set_mac_list); 3126590c391dSPadmanabh Ratnakar cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, 3127590c391dSPadmanabh Ratnakar &cmd.dma, GFP_KERNEL); 3128d0320f75SJoe Perches if (!cmd.va) 3129590c391dSPadmanabh Ratnakar return -ENOMEM; 3130590c391dSPadmanabh Ratnakar 3131590c391dSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 3132590c391dSPadmanabh Ratnakar 3133590c391dSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 3134590c391dSPadmanabh Ratnakar if (!wrb) { 3135590c391dSPadmanabh Ratnakar status = -EBUSY; 3136590c391dSPadmanabh Ratnakar goto err; 3137590c391dSPadmanabh Ratnakar } 3138590c391dSPadmanabh Ratnakar 3139590c391dSPadmanabh Ratnakar req = cmd.va; 3140590c391dSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3141590c391dSPadmanabh Ratnakar OPCODE_COMMON_SET_MAC_LIST, sizeof(*req), 3142590c391dSPadmanabh Ratnakar wrb, &cmd); 3143590c391dSPadmanabh Ratnakar 3144590c391dSPadmanabh Ratnakar req->hdr.domain = domain; 3145590c391dSPadmanabh Ratnakar req->mac_count = mac_count; 3146590c391dSPadmanabh Ratnakar if (mac_count) 3147590c391dSPadmanabh Ratnakar memcpy(req->mac, mac_array, ETH_ALEN*mac_count); 3148590c391dSPadmanabh Ratnakar 3149590c391dSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 3150590c391dSPadmanabh Ratnakar 3151590c391dSPadmanabh Ratnakar err: 3152a2cc4e0bSSathya Perla dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); 3153590c391dSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 3154590c391dSPadmanabh Ratnakar return status; 3155590c391dSPadmanabh Ratnakar } 31564762f6ceSAjit Khaparde 31573175d8c2SSathya Perla /* Wrapper to delete any active MACs and provision the new mac. 31583175d8c2SSathya Perla * Changes to MAC_LIST are allowed iff none of the MAC addresses in the 31593175d8c2SSathya Perla * current list are active. 31603175d8c2SSathya Perla */ 31613175d8c2SSathya Perla int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom) 31623175d8c2SSathya Perla { 31633175d8c2SSathya Perla bool active_mac = false; 31643175d8c2SSathya Perla u8 old_mac[ETH_ALEN]; 31653175d8c2SSathya Perla u32 pmac_id; 31663175d8c2SSathya Perla int status; 31673175d8c2SSathya Perla 31683175d8c2SSathya Perla status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac, 3169b188f090SSuresh Reddy &pmac_id, if_id, dom); 3170b188f090SSuresh Reddy 31713175d8c2SSathya Perla if (!status && active_mac) 31723175d8c2SSathya Perla be_cmd_pmac_del(adapter, if_id, pmac_id, dom); 31733175d8c2SSathya Perla 31743175d8c2SSathya Perla return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom); 31753175d8c2SSathya Perla } 31763175d8c2SSathya Perla 3177f1f3ee1bSAjit Khaparde int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, 3178e7bcbd7bSKalesh AP u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk) 3179f1f3ee1bSAjit Khaparde { 3180f1f3ee1bSAjit Khaparde struct be_mcc_wrb *wrb; 3181f1f3ee1bSAjit Khaparde struct be_cmd_req_set_hsw_config *req; 3182f1f3ee1bSAjit Khaparde void *ctxt; 3183f1f3ee1bSAjit Khaparde int status; 3184f1f3ee1bSAjit Khaparde 3185f1f3ee1bSAjit Khaparde spin_lock_bh(&adapter->mcc_lock); 3186f1f3ee1bSAjit Khaparde 3187f1f3ee1bSAjit Khaparde wrb = wrb_from_mccq(adapter); 3188f1f3ee1bSAjit Khaparde if (!wrb) { 3189f1f3ee1bSAjit Khaparde status = -EBUSY; 3190f1f3ee1bSAjit Khaparde goto err; 3191f1f3ee1bSAjit Khaparde } 3192f1f3ee1bSAjit Khaparde 3193f1f3ee1bSAjit Khaparde req = embedded_payload(wrb); 3194f1f3ee1bSAjit Khaparde ctxt = &req->context; 3195f1f3ee1bSAjit Khaparde 3196f1f3ee1bSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3197a2cc4e0bSSathya Perla OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb, 3198a2cc4e0bSSathya Perla NULL); 3199f1f3ee1bSAjit Khaparde 3200f1f3ee1bSAjit Khaparde req->hdr.domain = domain; 3201f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id); 3202f1f3ee1bSAjit Khaparde if (pvid) { 3203f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1); 3204f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid); 3205f1f3ee1bSAjit Khaparde } 3206a77dcb8cSAjit Khaparde if (!BEx_chip(adapter) && hsw_mode) { 3207a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, 3208a77dcb8cSAjit Khaparde ctxt, adapter->hba_port_num); 3209a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1); 3210a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type, 3211a77dcb8cSAjit Khaparde ctxt, hsw_mode); 3212a77dcb8cSAjit Khaparde } 3213f1f3ee1bSAjit Khaparde 3214e7bcbd7bSKalesh AP /* Enable/disable both mac and vlan spoof checking */ 3215e7bcbd7bSKalesh AP if (!BEx_chip(adapter) && spoofchk) { 3216e7bcbd7bSKalesh AP AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk, 3217e7bcbd7bSKalesh AP ctxt, spoofchk); 3218e7bcbd7bSKalesh AP AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk, 3219e7bcbd7bSKalesh AP ctxt, spoofchk); 3220e7bcbd7bSKalesh AP } 3221e7bcbd7bSKalesh AP 3222f1f3ee1bSAjit Khaparde be_dws_cpu_to_le(req->context, sizeof(req->context)); 3223f1f3ee1bSAjit Khaparde status = be_mcc_notify_wait(adapter); 3224f1f3ee1bSAjit Khaparde 3225f1f3ee1bSAjit Khaparde err: 3226f1f3ee1bSAjit Khaparde spin_unlock_bh(&adapter->mcc_lock); 3227f1f3ee1bSAjit Khaparde return status; 3228f1f3ee1bSAjit Khaparde } 3229f1f3ee1bSAjit Khaparde 3230f1f3ee1bSAjit Khaparde /* Get Hyper switch config */ 3231f1f3ee1bSAjit Khaparde int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, 3232e7bcbd7bSKalesh AP u32 domain, u16 intf_id, u8 *mode, bool *spoofchk) 3233f1f3ee1bSAjit Khaparde { 3234f1f3ee1bSAjit Khaparde struct be_mcc_wrb *wrb; 3235f1f3ee1bSAjit Khaparde struct be_cmd_req_get_hsw_config *req; 3236f1f3ee1bSAjit Khaparde void *ctxt; 3237f1f3ee1bSAjit Khaparde int status; 3238f1f3ee1bSAjit Khaparde u16 vid; 3239f1f3ee1bSAjit Khaparde 3240f1f3ee1bSAjit Khaparde spin_lock_bh(&adapter->mcc_lock); 3241f1f3ee1bSAjit Khaparde 3242f1f3ee1bSAjit Khaparde wrb = wrb_from_mccq(adapter); 3243f1f3ee1bSAjit Khaparde if (!wrb) { 3244f1f3ee1bSAjit Khaparde status = -EBUSY; 3245f1f3ee1bSAjit Khaparde goto err; 3246f1f3ee1bSAjit Khaparde } 3247f1f3ee1bSAjit Khaparde 3248f1f3ee1bSAjit Khaparde req = embedded_payload(wrb); 3249f1f3ee1bSAjit Khaparde ctxt = &req->context; 3250f1f3ee1bSAjit Khaparde 3251f1f3ee1bSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3252a2cc4e0bSSathya Perla OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb, 3253a2cc4e0bSSathya Perla NULL); 3254f1f3ee1bSAjit Khaparde 3255f1f3ee1bSAjit Khaparde req->hdr.domain = domain; 3256a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, 3257a77dcb8cSAjit Khaparde ctxt, intf_id); 3258f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1); 3259a77dcb8cSAjit Khaparde 32602c07c1d7SVasundhara Volam if (!BEx_chip(adapter) && mode) { 3261a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, 3262a77dcb8cSAjit Khaparde ctxt, adapter->hba_port_num); 3263a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1); 3264a77dcb8cSAjit Khaparde } 3265f1f3ee1bSAjit Khaparde be_dws_cpu_to_le(req->context, sizeof(req->context)); 3266f1f3ee1bSAjit Khaparde 3267f1f3ee1bSAjit Khaparde status = be_mcc_notify_wait(adapter); 3268f1f3ee1bSAjit Khaparde if (!status) { 3269f1f3ee1bSAjit Khaparde struct be_cmd_resp_get_hsw_config *resp = 3270f1f3ee1bSAjit Khaparde embedded_payload(wrb); 327103d28ffeSKalesh AP 3272a2cc4e0bSSathya Perla be_dws_le_to_cpu(&resp->context, sizeof(resp->context)); 3273f1f3ee1bSAjit Khaparde vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3274f1f3ee1bSAjit Khaparde pvid, &resp->context); 3275a77dcb8cSAjit Khaparde if (pvid) 3276f1f3ee1bSAjit Khaparde *pvid = le16_to_cpu(vid); 3277a77dcb8cSAjit Khaparde if (mode) 3278a77dcb8cSAjit Khaparde *mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3279a77dcb8cSAjit Khaparde port_fwd_type, &resp->context); 3280e7bcbd7bSKalesh AP if (spoofchk) 3281e7bcbd7bSKalesh AP *spoofchk = 3282e7bcbd7bSKalesh AP AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3283e7bcbd7bSKalesh AP spoofchk, &resp->context); 3284f1f3ee1bSAjit Khaparde } 3285f1f3ee1bSAjit Khaparde 3286f1f3ee1bSAjit Khaparde err: 3287f1f3ee1bSAjit Khaparde spin_unlock_bh(&adapter->mcc_lock); 3288f1f3ee1bSAjit Khaparde return status; 3289f1f3ee1bSAjit Khaparde } 3290f1f3ee1bSAjit Khaparde 3291f7062ee5SSathya Perla static bool be_is_wol_excluded(struct be_adapter *adapter) 3292f7062ee5SSathya Perla { 3293f7062ee5SSathya Perla struct pci_dev *pdev = adapter->pdev; 3294f7062ee5SSathya Perla 329518c57c74SKalesh AP if (be_virtfn(adapter)) 3296f7062ee5SSathya Perla return true; 3297f7062ee5SSathya Perla 3298f7062ee5SSathya Perla switch (pdev->subsystem_device) { 3299f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID1: 3300f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID2: 3301f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID3: 3302f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID4: 3303f7062ee5SSathya Perla return true; 3304f7062ee5SSathya Perla default: 3305f7062ee5SSathya Perla return false; 3306f7062ee5SSathya Perla } 3307f7062ee5SSathya Perla } 3308f7062ee5SSathya Perla 33094762f6ceSAjit Khaparde int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) 33104762f6ceSAjit Khaparde { 33114762f6ceSAjit Khaparde struct be_mcc_wrb *wrb; 33124762f6ceSAjit Khaparde struct be_cmd_req_acpi_wol_magic_config_v1 *req; 331376a9e08eSSuresh Reddy int status = 0; 33144762f6ceSAjit Khaparde struct be_dma_mem cmd; 33154762f6ceSAjit Khaparde 3316f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, 3317f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH)) 3318f25b119cSPadmanabh Ratnakar return -EPERM; 3319f25b119cSPadmanabh Ratnakar 332076a9e08eSSuresh Reddy if (be_is_wol_excluded(adapter)) 332176a9e08eSSuresh Reddy return status; 332276a9e08eSSuresh Reddy 3323d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 3324d98ef50fSSuresh Reddy return -1; 3325d98ef50fSSuresh Reddy 33264762f6ceSAjit Khaparde memset(&cmd, 0, sizeof(struct be_dma_mem)); 33274762f6ceSAjit Khaparde cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); 3328a2cc4e0bSSathya Perla cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 33294762f6ceSAjit Khaparde if (!cmd.va) { 3330a2cc4e0bSSathya Perla dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); 3331d98ef50fSSuresh Reddy status = -ENOMEM; 3332d98ef50fSSuresh Reddy goto err; 33334762f6ceSAjit Khaparde } 33344762f6ceSAjit Khaparde 33354762f6ceSAjit Khaparde wrb = wrb_from_mbox(adapter); 33364762f6ceSAjit Khaparde if (!wrb) { 33374762f6ceSAjit Khaparde status = -EBUSY; 33384762f6ceSAjit Khaparde goto err; 33394762f6ceSAjit Khaparde } 33404762f6ceSAjit Khaparde 33414762f6ceSAjit Khaparde req = cmd.va; 33424762f6ceSAjit Khaparde 33434762f6ceSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 33444762f6ceSAjit Khaparde OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, 334576a9e08eSSuresh Reddy sizeof(*req), wrb, &cmd); 33464762f6ceSAjit Khaparde 33474762f6ceSAjit Khaparde req->hdr.version = 1; 33484762f6ceSAjit Khaparde req->query_options = BE_GET_WOL_CAP; 33494762f6ceSAjit Khaparde 33504762f6ceSAjit Khaparde status = be_mbox_notify_wait(adapter); 33514762f6ceSAjit Khaparde if (!status) { 33524762f6ceSAjit Khaparde struct be_cmd_resp_acpi_wol_magic_config_v1 *resp; 335303d28ffeSKalesh AP 33544762f6ceSAjit Khaparde resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va; 33554762f6ceSAjit Khaparde 33564762f6ceSAjit Khaparde adapter->wol_cap = resp->wol_settings; 335776a9e08eSSuresh Reddy if (adapter->wol_cap & BE_WOL_CAP) 335876a9e08eSSuresh Reddy adapter->wol_en = true; 33594762f6ceSAjit Khaparde } 33604762f6ceSAjit Khaparde err: 33614762f6ceSAjit Khaparde mutex_unlock(&adapter->mbox_lock); 3362d98ef50fSSuresh Reddy if (cmd.va) 33634762f6ceSAjit Khaparde pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 33644762f6ceSAjit Khaparde return status; 3365941a77d5SSomnath Kotur 3366941a77d5SSomnath Kotur } 3367baaa08d1SVasundhara Volam 3368baaa08d1SVasundhara Volam int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level) 3369baaa08d1SVasundhara Volam { 3370baaa08d1SVasundhara Volam struct be_dma_mem extfat_cmd; 3371baaa08d1SVasundhara Volam struct be_fat_conf_params *cfgs; 3372baaa08d1SVasundhara Volam int status; 3373baaa08d1SVasundhara Volam int i, j; 3374baaa08d1SVasundhara Volam 3375baaa08d1SVasundhara Volam memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); 3376baaa08d1SVasundhara Volam extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); 3377baaa08d1SVasundhara Volam extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size, 3378baaa08d1SVasundhara Volam &extfat_cmd.dma); 3379baaa08d1SVasundhara Volam if (!extfat_cmd.va) 3380baaa08d1SVasundhara Volam return -ENOMEM; 3381baaa08d1SVasundhara Volam 3382baaa08d1SVasundhara Volam status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd); 3383baaa08d1SVasundhara Volam if (status) 3384baaa08d1SVasundhara Volam goto err; 3385baaa08d1SVasundhara Volam 3386baaa08d1SVasundhara Volam cfgs = (struct be_fat_conf_params *) 3387baaa08d1SVasundhara Volam (extfat_cmd.va + sizeof(struct be_cmd_resp_hdr)); 3388baaa08d1SVasundhara Volam for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) { 3389baaa08d1SVasundhara Volam u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes); 339003d28ffeSKalesh AP 3391baaa08d1SVasundhara Volam for (j = 0; j < num_modes; j++) { 3392baaa08d1SVasundhara Volam if (cfgs->module[i].trace_lvl[j].mode == MODE_UART) 3393baaa08d1SVasundhara Volam cfgs->module[i].trace_lvl[j].dbg_lvl = 3394baaa08d1SVasundhara Volam cpu_to_le32(level); 3395baaa08d1SVasundhara Volam } 3396baaa08d1SVasundhara Volam } 3397baaa08d1SVasundhara Volam 3398baaa08d1SVasundhara Volam status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs); 3399baaa08d1SVasundhara Volam err: 3400baaa08d1SVasundhara Volam pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va, 3401baaa08d1SVasundhara Volam extfat_cmd.dma); 3402baaa08d1SVasundhara Volam return status; 3403baaa08d1SVasundhara Volam } 3404baaa08d1SVasundhara Volam 3405baaa08d1SVasundhara Volam int be_cmd_get_fw_log_level(struct be_adapter *adapter) 3406baaa08d1SVasundhara Volam { 3407baaa08d1SVasundhara Volam struct be_dma_mem extfat_cmd; 3408baaa08d1SVasundhara Volam struct be_fat_conf_params *cfgs; 3409baaa08d1SVasundhara Volam int status, j; 3410baaa08d1SVasundhara Volam int level = 0; 3411baaa08d1SVasundhara Volam 3412baaa08d1SVasundhara Volam memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); 3413baaa08d1SVasundhara Volam extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); 3414baaa08d1SVasundhara Volam extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size, 3415baaa08d1SVasundhara Volam &extfat_cmd.dma); 3416baaa08d1SVasundhara Volam 3417baaa08d1SVasundhara Volam if (!extfat_cmd.va) { 3418baaa08d1SVasundhara Volam dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n", 3419baaa08d1SVasundhara Volam __func__); 3420baaa08d1SVasundhara Volam goto err; 3421baaa08d1SVasundhara Volam } 3422baaa08d1SVasundhara Volam 3423baaa08d1SVasundhara Volam status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd); 3424baaa08d1SVasundhara Volam if (!status) { 3425baaa08d1SVasundhara Volam cfgs = (struct be_fat_conf_params *)(extfat_cmd.va + 3426baaa08d1SVasundhara Volam sizeof(struct be_cmd_resp_hdr)); 342703d28ffeSKalesh AP 3428baaa08d1SVasundhara Volam for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) { 3429baaa08d1SVasundhara Volam if (cfgs->module[0].trace_lvl[j].mode == MODE_UART) 3430baaa08d1SVasundhara Volam level = cfgs->module[0].trace_lvl[j].dbg_lvl; 3431baaa08d1SVasundhara Volam } 3432baaa08d1SVasundhara Volam } 3433baaa08d1SVasundhara Volam pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va, 3434baaa08d1SVasundhara Volam extfat_cmd.dma); 3435baaa08d1SVasundhara Volam err: 3436baaa08d1SVasundhara Volam return level; 3437baaa08d1SVasundhara Volam } 3438baaa08d1SVasundhara Volam 3439941a77d5SSomnath Kotur int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter, 3440941a77d5SSomnath Kotur struct be_dma_mem *cmd) 3441941a77d5SSomnath Kotur { 3442941a77d5SSomnath Kotur struct be_mcc_wrb *wrb; 3443941a77d5SSomnath Kotur struct be_cmd_req_get_ext_fat_caps *req; 3444941a77d5SSomnath Kotur int status; 3445941a77d5SSomnath Kotur 3446941a77d5SSomnath Kotur if (mutex_lock_interruptible(&adapter->mbox_lock)) 3447941a77d5SSomnath Kotur return -1; 3448941a77d5SSomnath Kotur 3449941a77d5SSomnath Kotur wrb = wrb_from_mbox(adapter); 3450941a77d5SSomnath Kotur if (!wrb) { 3451941a77d5SSomnath Kotur status = -EBUSY; 3452941a77d5SSomnath Kotur goto err; 3453941a77d5SSomnath Kotur } 3454941a77d5SSomnath Kotur 3455941a77d5SSomnath Kotur req = cmd->va; 3456941a77d5SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3457941a77d5SSomnath Kotur OPCODE_COMMON_GET_EXT_FAT_CAPABILITES, 3458941a77d5SSomnath Kotur cmd->size, wrb, cmd); 3459941a77d5SSomnath Kotur req->parameter_type = cpu_to_le32(1); 3460941a77d5SSomnath Kotur 3461941a77d5SSomnath Kotur status = be_mbox_notify_wait(adapter); 3462941a77d5SSomnath Kotur err: 3463941a77d5SSomnath Kotur mutex_unlock(&adapter->mbox_lock); 3464941a77d5SSomnath Kotur return status; 3465941a77d5SSomnath Kotur } 3466941a77d5SSomnath Kotur 3467941a77d5SSomnath Kotur int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, 3468941a77d5SSomnath Kotur struct be_dma_mem *cmd, 3469941a77d5SSomnath Kotur struct be_fat_conf_params *configs) 3470941a77d5SSomnath Kotur { 3471941a77d5SSomnath Kotur struct be_mcc_wrb *wrb; 3472941a77d5SSomnath Kotur struct be_cmd_req_set_ext_fat_caps *req; 3473941a77d5SSomnath Kotur int status; 3474941a77d5SSomnath Kotur 3475941a77d5SSomnath Kotur spin_lock_bh(&adapter->mcc_lock); 3476941a77d5SSomnath Kotur 3477941a77d5SSomnath Kotur wrb = wrb_from_mccq(adapter); 3478941a77d5SSomnath Kotur if (!wrb) { 3479941a77d5SSomnath Kotur status = -EBUSY; 3480941a77d5SSomnath Kotur goto err; 3481941a77d5SSomnath Kotur } 3482941a77d5SSomnath Kotur 3483941a77d5SSomnath Kotur req = cmd->va; 3484941a77d5SSomnath Kotur memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params)); 3485941a77d5SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3486941a77d5SSomnath Kotur OPCODE_COMMON_SET_EXT_FAT_CAPABILITES, 3487941a77d5SSomnath Kotur cmd->size, wrb, cmd); 3488941a77d5SSomnath Kotur 3489941a77d5SSomnath Kotur status = be_mcc_notify_wait(adapter); 3490941a77d5SSomnath Kotur err: 3491941a77d5SSomnath Kotur spin_unlock_bh(&adapter->mcc_lock); 3492941a77d5SSomnath Kotur return status; 34934762f6ceSAjit Khaparde } 34946a4ab669SParav Pandit 349521252377SVasundhara Volam int be_cmd_query_port_name(struct be_adapter *adapter) 3496b4e32a71SPadmanabh Ratnakar { 3497b4e32a71SPadmanabh Ratnakar struct be_cmd_req_get_port_name *req; 349821252377SVasundhara Volam struct be_mcc_wrb *wrb; 3499b4e32a71SPadmanabh Ratnakar int status; 3500b4e32a71SPadmanabh Ratnakar 350121252377SVasundhara Volam if (mutex_lock_interruptible(&adapter->mbox_lock)) 350221252377SVasundhara Volam return -1; 3503b4e32a71SPadmanabh Ratnakar 350421252377SVasundhara Volam wrb = wrb_from_mbox(adapter); 3505b4e32a71SPadmanabh Ratnakar req = embedded_payload(wrb); 3506b4e32a71SPadmanabh Ratnakar 3507b4e32a71SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3508b4e32a71SPadmanabh Ratnakar OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb, 3509b4e32a71SPadmanabh Ratnakar NULL); 351021252377SVasundhara Volam if (!BEx_chip(adapter)) 3511b4e32a71SPadmanabh Ratnakar req->hdr.version = 1; 3512b4e32a71SPadmanabh Ratnakar 351321252377SVasundhara Volam status = be_mbox_notify_wait(adapter); 3514b4e32a71SPadmanabh Ratnakar if (!status) { 3515b4e32a71SPadmanabh Ratnakar struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb); 351603d28ffeSKalesh AP 351721252377SVasundhara Volam adapter->port_name = resp->port_name[adapter->hba_port_num]; 3518b4e32a71SPadmanabh Ratnakar } else { 351921252377SVasundhara Volam adapter->port_name = adapter->hba_port_num + '0'; 3520b4e32a71SPadmanabh Ratnakar } 352121252377SVasundhara Volam 352221252377SVasundhara Volam mutex_unlock(&adapter->mbox_lock); 3523b4e32a71SPadmanabh Ratnakar return status; 3524b4e32a71SPadmanabh Ratnakar } 3525b4e32a71SPadmanabh Ratnakar 352610cccf60SVasundhara Volam /* Descriptor type */ 352710cccf60SVasundhara Volam enum { 352810cccf60SVasundhara Volam FUNC_DESC = 1, 352910cccf60SVasundhara Volam VFT_DESC = 2 353010cccf60SVasundhara Volam }; 353110cccf60SVasundhara Volam 353210cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count, 353310cccf60SVasundhara Volam int desc_type) 3534abb93951SPadmanabh Ratnakar { 3535150d58c7SVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 353610cccf60SVasundhara Volam struct be_nic_res_desc *nic; 3537abb93951SPadmanabh Ratnakar int i; 3538abb93951SPadmanabh Ratnakar 3539abb93951SPadmanabh Ratnakar for (i = 0; i < desc_count; i++) { 3540150d58c7SVasundhara Volam if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 || 354110cccf60SVasundhara Volam hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) { 354210cccf60SVasundhara Volam nic = (struct be_nic_res_desc *)hdr; 354310cccf60SVasundhara Volam if (desc_type == FUNC_DESC || 354410cccf60SVasundhara Volam (desc_type == VFT_DESC && 354510cccf60SVasundhara Volam nic->flags & (1 << VFT_SHIFT))) 354610cccf60SVasundhara Volam return nic; 354710cccf60SVasundhara Volam } 3548150d58c7SVasundhara Volam 3549150d58c7SVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 3550150d58c7SVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 3551150d58c7SVasundhara Volam } 3552950e2958SWei Yang return NULL; 3553abb93951SPadmanabh Ratnakar } 3554abb93951SPadmanabh Ratnakar 355510cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count) 355610cccf60SVasundhara Volam { 355710cccf60SVasundhara Volam return be_get_nic_desc(buf, desc_count, VFT_DESC); 355810cccf60SVasundhara Volam } 355910cccf60SVasundhara Volam 356010cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count) 356110cccf60SVasundhara Volam { 356210cccf60SVasundhara Volam return be_get_nic_desc(buf, desc_count, FUNC_DESC); 356310cccf60SVasundhara Volam } 356410cccf60SVasundhara Volam 3565150d58c7SVasundhara Volam static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf, 3566150d58c7SVasundhara Volam u32 desc_count) 3567150d58c7SVasundhara Volam { 3568150d58c7SVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 3569150d58c7SVasundhara Volam struct be_pcie_res_desc *pcie; 3570150d58c7SVasundhara Volam int i; 3571150d58c7SVasundhara Volam 3572150d58c7SVasundhara Volam for (i = 0; i < desc_count; i++) { 3573150d58c7SVasundhara Volam if ((hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 || 3574150d58c7SVasundhara Volam hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1)) { 3575150d58c7SVasundhara Volam pcie = (struct be_pcie_res_desc *)hdr; 3576150d58c7SVasundhara Volam if (pcie->pf_num == devfn) 3577150d58c7SVasundhara Volam return pcie; 3578150d58c7SVasundhara Volam } 3579150d58c7SVasundhara Volam 3580150d58c7SVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 3581150d58c7SVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 3582150d58c7SVasundhara Volam } 3583abb93951SPadmanabh Ratnakar return NULL; 3584abb93951SPadmanabh Ratnakar } 3585abb93951SPadmanabh Ratnakar 3586f93f160bSVasundhara Volam static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count) 3587f93f160bSVasundhara Volam { 3588f93f160bSVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 3589f93f160bSVasundhara Volam int i; 3590f93f160bSVasundhara Volam 3591f93f160bSVasundhara Volam for (i = 0; i < desc_count; i++) { 3592f93f160bSVasundhara Volam if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1) 3593f93f160bSVasundhara Volam return (struct be_port_res_desc *)hdr; 3594f93f160bSVasundhara Volam 3595f93f160bSVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 3596f93f160bSVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 3597f93f160bSVasundhara Volam } 3598f93f160bSVasundhara Volam return NULL; 3599f93f160bSVasundhara Volam } 3600f93f160bSVasundhara Volam 360192bf14abSSathya Perla static void be_copy_nic_desc(struct be_resources *res, 360292bf14abSSathya Perla struct be_nic_res_desc *desc) 360392bf14abSSathya Perla { 360492bf14abSSathya Perla res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count); 360592bf14abSSathya Perla res->max_vlans = le16_to_cpu(desc->vlan_count); 360692bf14abSSathya Perla res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count); 360792bf14abSSathya Perla res->max_tx_qs = le16_to_cpu(desc->txq_count); 360892bf14abSSathya Perla res->max_rss_qs = le16_to_cpu(desc->rssq_count); 360992bf14abSSathya Perla res->max_rx_qs = le16_to_cpu(desc->rq_count); 361092bf14abSSathya Perla res->max_evt_qs = le16_to_cpu(desc->eq_count); 3611f2858738SVasundhara Volam res->max_cq_count = le16_to_cpu(desc->cq_count); 3612f2858738SVasundhara Volam res->max_iface_count = le16_to_cpu(desc->iface_count); 3613f2858738SVasundhara Volam res->max_mcc_count = le16_to_cpu(desc->mcc_count); 361492bf14abSSathya Perla /* Clear flags that driver is not interested in */ 361592bf14abSSathya Perla res->if_cap_flags = le32_to_cpu(desc->cap_flags) & 361692bf14abSSathya Perla BE_IF_CAP_FLAGS_WANT; 361792bf14abSSathya Perla } 361892bf14abSSathya Perla 3619abb93951SPadmanabh Ratnakar /* Uses Mbox */ 362092bf14abSSathya Perla int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) 3621abb93951SPadmanabh Ratnakar { 3622abb93951SPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3623abb93951SPadmanabh Ratnakar struct be_cmd_req_get_func_config *req; 3624abb93951SPadmanabh Ratnakar int status; 3625abb93951SPadmanabh Ratnakar struct be_dma_mem cmd; 3626abb93951SPadmanabh Ratnakar 3627d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 3628d98ef50fSSuresh Reddy return -1; 3629d98ef50fSSuresh Reddy 3630abb93951SPadmanabh Ratnakar memset(&cmd, 0, sizeof(struct be_dma_mem)); 3631abb93951SPadmanabh Ratnakar cmd.size = sizeof(struct be_cmd_resp_get_func_config); 3632a2cc4e0bSSathya Perla cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 3633abb93951SPadmanabh Ratnakar if (!cmd.va) { 3634abb93951SPadmanabh Ratnakar dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); 3635d98ef50fSSuresh Reddy status = -ENOMEM; 3636d98ef50fSSuresh Reddy goto err; 3637abb93951SPadmanabh Ratnakar } 3638abb93951SPadmanabh Ratnakar 3639abb93951SPadmanabh Ratnakar wrb = wrb_from_mbox(adapter); 3640abb93951SPadmanabh Ratnakar if (!wrb) { 3641abb93951SPadmanabh Ratnakar status = -EBUSY; 3642abb93951SPadmanabh Ratnakar goto err; 3643abb93951SPadmanabh Ratnakar } 3644abb93951SPadmanabh Ratnakar 3645abb93951SPadmanabh Ratnakar req = cmd.va; 3646abb93951SPadmanabh Ratnakar 3647abb93951SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3648abb93951SPadmanabh Ratnakar OPCODE_COMMON_GET_FUNC_CONFIG, 3649abb93951SPadmanabh Ratnakar cmd.size, wrb, &cmd); 3650abb93951SPadmanabh Ratnakar 365128710c55SKalesh AP if (skyhawk_chip(adapter)) 365228710c55SKalesh AP req->hdr.version = 1; 365328710c55SKalesh AP 3654abb93951SPadmanabh Ratnakar status = be_mbox_notify_wait(adapter); 3655abb93951SPadmanabh Ratnakar if (!status) { 3656abb93951SPadmanabh Ratnakar struct be_cmd_resp_get_func_config *resp = cmd.va; 3657abb93951SPadmanabh Ratnakar u32 desc_count = le32_to_cpu(resp->desc_count); 3658150d58c7SVasundhara Volam struct be_nic_res_desc *desc; 3659abb93951SPadmanabh Ratnakar 366010cccf60SVasundhara Volam desc = be_get_func_nic_desc(resp->func_param, desc_count); 3661abb93951SPadmanabh Ratnakar if (!desc) { 3662abb93951SPadmanabh Ratnakar status = -EINVAL; 3663abb93951SPadmanabh Ratnakar goto err; 3664abb93951SPadmanabh Ratnakar } 3665abb93951SPadmanabh Ratnakar 3666d5c18473SPadmanabh Ratnakar adapter->pf_number = desc->pf_num; 366792bf14abSSathya Perla be_copy_nic_desc(res, desc); 3668abb93951SPadmanabh Ratnakar } 3669abb93951SPadmanabh Ratnakar err: 3670abb93951SPadmanabh Ratnakar mutex_unlock(&adapter->mbox_lock); 3671d98ef50fSSuresh Reddy if (cmd.va) 3672d98ef50fSSuresh Reddy pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 3673abb93951SPadmanabh Ratnakar return status; 3674abb93951SPadmanabh Ratnakar } 3675abb93951SPadmanabh Ratnakar 3676ba48c0c9SVasundhara Volam /* Will use MBOX only if MCCQ has not been created */ 367792bf14abSSathya Perla int be_cmd_get_profile_config(struct be_adapter *adapter, 3678f2858738SVasundhara Volam struct be_resources *res, u8 query, u8 domain) 3679a05f99dbSVasundhara Volam { 3680150d58c7SVasundhara Volam struct be_cmd_resp_get_profile_config *resp; 3681ba48c0c9SVasundhara Volam struct be_cmd_req_get_profile_config *req; 368210cccf60SVasundhara Volam struct be_nic_res_desc *vf_res; 3683150d58c7SVasundhara Volam struct be_pcie_res_desc *pcie; 3684f93f160bSVasundhara Volam struct be_port_res_desc *port; 3685150d58c7SVasundhara Volam struct be_nic_res_desc *nic; 3686ba48c0c9SVasundhara Volam struct be_mcc_wrb wrb = {0}; 3687a05f99dbSVasundhara Volam struct be_dma_mem cmd; 3688f2858738SVasundhara Volam u16 desc_count; 3689a05f99dbSVasundhara Volam int status; 3690a05f99dbSVasundhara Volam 3691a05f99dbSVasundhara Volam memset(&cmd, 0, sizeof(struct be_dma_mem)); 3692a05f99dbSVasundhara Volam cmd.size = sizeof(struct be_cmd_resp_get_profile_config); 3693150d58c7SVasundhara Volam cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 3694150d58c7SVasundhara Volam if (!cmd.va) 3695a05f99dbSVasundhara Volam return -ENOMEM; 3696a05f99dbSVasundhara Volam 3697ba48c0c9SVasundhara Volam req = cmd.va; 3698ba48c0c9SVasundhara Volam be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3699ba48c0c9SVasundhara Volam OPCODE_COMMON_GET_PROFILE_CONFIG, 3700ba48c0c9SVasundhara Volam cmd.size, &wrb, &cmd); 3701ba48c0c9SVasundhara Volam 3702ba48c0c9SVasundhara Volam req->hdr.domain = domain; 3703ba48c0c9SVasundhara Volam if (!lancer_chip(adapter)) 3704ba48c0c9SVasundhara Volam req->hdr.version = 1; 3705ba48c0c9SVasundhara Volam req->type = ACTIVE_PROFILE_TYPE; 3706ba48c0c9SVasundhara Volam 3707f2858738SVasundhara Volam /* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the 3708f2858738SVasundhara Volam * descriptors with all bits set to "1" for the fields which can be 3709f2858738SVasundhara Volam * modified using SET_PROFILE_CONFIG cmd. 3710f2858738SVasundhara Volam */ 3711f2858738SVasundhara Volam if (query == RESOURCE_MODIFIABLE) 3712f2858738SVasundhara Volam req->type |= QUERY_MODIFIABLE_FIELDS_TYPE; 3713f2858738SVasundhara Volam 3714ba48c0c9SVasundhara Volam status = be_cmd_notify_wait(adapter, &wrb); 3715150d58c7SVasundhara Volam if (status) 3716abb93951SPadmanabh Ratnakar goto err; 3717150d58c7SVasundhara Volam 3718150d58c7SVasundhara Volam resp = cmd.va; 3719f2858738SVasundhara Volam desc_count = le16_to_cpu(resp->desc_count); 3720150d58c7SVasundhara Volam 3721150d58c7SVasundhara Volam pcie = be_get_pcie_desc(adapter->pdev->devfn, resp->func_param, 3722150d58c7SVasundhara Volam desc_count); 3723150d58c7SVasundhara Volam if (pcie) 372492bf14abSSathya Perla res->max_vfs = le16_to_cpu(pcie->num_vfs); 3725150d58c7SVasundhara Volam 3726f93f160bSVasundhara Volam port = be_get_port_desc(resp->func_param, desc_count); 3727f93f160bSVasundhara Volam if (port) 3728f93f160bSVasundhara Volam adapter->mc_type = port->mc_type; 3729f93f160bSVasundhara Volam 373010cccf60SVasundhara Volam nic = be_get_func_nic_desc(resp->func_param, desc_count); 373192bf14abSSathya Perla if (nic) 373292bf14abSSathya Perla be_copy_nic_desc(res, nic); 373392bf14abSSathya Perla 373410cccf60SVasundhara Volam vf_res = be_get_vft_desc(resp->func_param, desc_count); 373510cccf60SVasundhara Volam if (vf_res) 373610cccf60SVasundhara Volam res->vf_if_cap_flags = vf_res->cap_flags; 3737abb93951SPadmanabh Ratnakar err: 3738a05f99dbSVasundhara Volam if (cmd.va) 3739150d58c7SVasundhara Volam pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 3740abb93951SPadmanabh Ratnakar return status; 3741abb93951SPadmanabh Ratnakar } 3742abb93951SPadmanabh Ratnakar 3743bec84e6bSVasundhara Volam /* Will use MBOX only if MCCQ has not been created */ 3744bec84e6bSVasundhara Volam static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc, 3745bec84e6bSVasundhara Volam int size, int count, u8 version, u8 domain) 3746d5c18473SPadmanabh Ratnakar { 3747d5c18473SPadmanabh Ratnakar struct be_cmd_req_set_profile_config *req; 3748bec84e6bSVasundhara Volam struct be_mcc_wrb wrb = {0}; 3749bec84e6bSVasundhara Volam struct be_dma_mem cmd; 3750d5c18473SPadmanabh Ratnakar int status; 3751d5c18473SPadmanabh Ratnakar 3752bec84e6bSVasundhara Volam memset(&cmd, 0, sizeof(struct be_dma_mem)); 3753bec84e6bSVasundhara Volam cmd.size = sizeof(struct be_cmd_req_set_profile_config); 3754bec84e6bSVasundhara Volam cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 3755bec84e6bSVasundhara Volam if (!cmd.va) 3756bec84e6bSVasundhara Volam return -ENOMEM; 3757d5c18473SPadmanabh Ratnakar 3758bec84e6bSVasundhara Volam req = cmd.va; 3759d5c18473SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3760bec84e6bSVasundhara Volam OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size, 3761bec84e6bSVasundhara Volam &wrb, &cmd); 3762a401801cSSathya Perla req->hdr.version = version; 3763d5c18473SPadmanabh Ratnakar req->hdr.domain = domain; 3764bec84e6bSVasundhara Volam req->desc_count = cpu_to_le32(count); 3765a401801cSSathya Perla memcpy(req->desc, desc, size); 3766d5c18473SPadmanabh Ratnakar 3767bec84e6bSVasundhara Volam status = be_cmd_notify_wait(adapter, &wrb); 3768bec84e6bSVasundhara Volam 3769bec84e6bSVasundhara Volam if (cmd.va) 3770bec84e6bSVasundhara Volam pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 3771d5c18473SPadmanabh Ratnakar return status; 3772d5c18473SPadmanabh Ratnakar } 3773d5c18473SPadmanabh Ratnakar 3774a401801cSSathya Perla /* Mark all fields invalid */ 3775bec84e6bSVasundhara Volam static void be_reset_nic_desc(struct be_nic_res_desc *nic) 3776a401801cSSathya Perla { 3777a401801cSSathya Perla memset(nic, 0, sizeof(*nic)); 3778a401801cSSathya Perla nic->unicast_mac_count = 0xFFFF; 3779a401801cSSathya Perla nic->mcc_count = 0xFFFF; 3780a401801cSSathya Perla nic->vlan_count = 0xFFFF; 3781a401801cSSathya Perla nic->mcast_mac_count = 0xFFFF; 3782a401801cSSathya Perla nic->txq_count = 0xFFFF; 3783a401801cSSathya Perla nic->rq_count = 0xFFFF; 3784a401801cSSathya Perla nic->rssq_count = 0xFFFF; 3785a401801cSSathya Perla nic->lro_count = 0xFFFF; 3786a401801cSSathya Perla nic->cq_count = 0xFFFF; 3787a401801cSSathya Perla nic->toe_conn_count = 0xFFFF; 3788a401801cSSathya Perla nic->eq_count = 0xFFFF; 37890f77ba73SRavikumar Nelavelli nic->iface_count = 0xFFFF; 3790a401801cSSathya Perla nic->link_param = 0xFF; 37910f77ba73SRavikumar Nelavelli nic->channel_id_param = cpu_to_le16(0xF000); 3792a401801cSSathya Perla nic->acpi_params = 0xFF; 3793a401801cSSathya Perla nic->wol_param = 0x0F; 37940f77ba73SRavikumar Nelavelli nic->tunnel_iface_count = 0xFFFF; 37950f77ba73SRavikumar Nelavelli nic->direct_tenant_iface_count = 0xFFFF; 3796bec84e6bSVasundhara Volam nic->bw_min = 0xFFFFFFFF; 3797a401801cSSathya Perla nic->bw_max = 0xFFFFFFFF; 3798a401801cSSathya Perla } 3799a401801cSSathya Perla 3800bec84e6bSVasundhara Volam /* Mark all fields invalid */ 3801bec84e6bSVasundhara Volam static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie) 3802bec84e6bSVasundhara Volam { 3803bec84e6bSVasundhara Volam memset(pcie, 0, sizeof(*pcie)); 3804bec84e6bSVasundhara Volam pcie->sriov_state = 0xFF; 3805bec84e6bSVasundhara Volam pcie->pf_state = 0xFF; 3806bec84e6bSVasundhara Volam pcie->pf_type = 0xFF; 3807bec84e6bSVasundhara Volam pcie->num_vfs = 0xFFFF; 3808bec84e6bSVasundhara Volam } 3809bec84e6bSVasundhara Volam 38100f77ba73SRavikumar Nelavelli int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed, 38110f77ba73SRavikumar Nelavelli u8 domain) 3812a401801cSSathya Perla { 3813a401801cSSathya Perla struct be_nic_res_desc nic_desc; 38140f77ba73SRavikumar Nelavelli u32 bw_percent; 38150f77ba73SRavikumar Nelavelli u16 version = 0; 38160f77ba73SRavikumar Nelavelli 38170f77ba73SRavikumar Nelavelli if (BE3_chip(adapter)) 38180f77ba73SRavikumar Nelavelli return be_cmd_set_qos(adapter, max_rate / 10, domain); 3819a401801cSSathya Perla 3820a401801cSSathya Perla be_reset_nic_desc(&nic_desc); 38210f77ba73SRavikumar Nelavelli nic_desc.pf_num = adapter->pf_number; 38220f77ba73SRavikumar Nelavelli nic_desc.vf_num = domain; 382358bdeaa6SKalesh AP nic_desc.bw_min = 0; 38240f77ba73SRavikumar Nelavelli if (lancer_chip(adapter)) { 3825a401801cSSathya Perla nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0; 3826a401801cSSathya Perla nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0; 3827a401801cSSathya Perla nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) | 3828a401801cSSathya Perla (1 << NOSV_SHIFT); 38290f77ba73SRavikumar Nelavelli nic_desc.bw_max = cpu_to_le32(max_rate / 10); 38300f77ba73SRavikumar Nelavelli } else { 38310f77ba73SRavikumar Nelavelli version = 1; 38320f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1; 38330f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 38340f77ba73SRavikumar Nelavelli nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT); 38350f77ba73SRavikumar Nelavelli bw_percent = max_rate ? (max_rate * 100) / link_speed : 100; 38360f77ba73SRavikumar Nelavelli nic_desc.bw_max = cpu_to_le32(bw_percent); 38370f77ba73SRavikumar Nelavelli } 3838a401801cSSathya Perla 3839a401801cSSathya Perla return be_cmd_set_profile_config(adapter, &nic_desc, 38400f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_len, 3841bec84e6bSVasundhara Volam 1, version, domain); 3842bec84e6bSVasundhara Volam } 3843bec84e6bSVasundhara Volam 3844f2858738SVasundhara Volam static void be_fill_vf_res_template(struct be_adapter *adapter, 3845f2858738SVasundhara Volam struct be_resources pool_res, 3846f2858738SVasundhara Volam u16 num_vfs, u16 num_vf_qs, 3847f2858738SVasundhara Volam struct be_nic_res_desc *nic_vft) 3848f2858738SVasundhara Volam { 3849f2858738SVasundhara Volam u32 vf_if_cap_flags = pool_res.vf_if_cap_flags; 3850f2858738SVasundhara Volam struct be_resources res_mod = {0}; 3851f2858738SVasundhara Volam 3852f2858738SVasundhara Volam /* Resource with fields set to all '1's by GET_PROFILE_CONFIG cmd, 3853f2858738SVasundhara Volam * which are modifiable using SET_PROFILE_CONFIG cmd. 3854f2858738SVasundhara Volam */ 3855f2858738SVasundhara Volam be_cmd_get_profile_config(adapter, &res_mod, RESOURCE_MODIFIABLE, 0); 3856f2858738SVasundhara Volam 3857f2858738SVasundhara Volam /* If RSS IFACE capability flags are modifiable for a VF, set the 3858f2858738SVasundhara Volam * capability flag as valid and set RSS and DEFQ_RSS IFACE flags if 3859f2858738SVasundhara Volam * more than 1 RSSQ is available for a VF. 3860f2858738SVasundhara Volam * Otherwise, provision only 1 queue pair for VF. 3861f2858738SVasundhara Volam */ 3862f2858738SVasundhara Volam if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_RSS) { 3863f2858738SVasundhara Volam nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT); 3864f2858738SVasundhara Volam if (num_vf_qs > 1) { 3865f2858738SVasundhara Volam vf_if_cap_flags |= BE_IF_FLAGS_RSS; 3866f2858738SVasundhara Volam if (pool_res.if_cap_flags & BE_IF_FLAGS_DEFQ_RSS) 3867f2858738SVasundhara Volam vf_if_cap_flags |= BE_IF_FLAGS_DEFQ_RSS; 3868f2858738SVasundhara Volam } else { 3869f2858738SVasundhara Volam vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS | 3870f2858738SVasundhara Volam BE_IF_FLAGS_DEFQ_RSS); 3871f2858738SVasundhara Volam } 3872f2858738SVasundhara Volam 3873f2858738SVasundhara Volam nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags); 3874f2858738SVasundhara Volam } else { 3875f2858738SVasundhara Volam num_vf_qs = 1; 3876f2858738SVasundhara Volam } 3877f2858738SVasundhara Volam 3878f2858738SVasundhara Volam nic_vft->rq_count = cpu_to_le16(num_vf_qs); 3879f2858738SVasundhara Volam nic_vft->txq_count = cpu_to_le16(num_vf_qs); 3880f2858738SVasundhara Volam nic_vft->rssq_count = cpu_to_le16(num_vf_qs); 3881f2858738SVasundhara Volam nic_vft->cq_count = cpu_to_le16(pool_res.max_cq_count / 3882f2858738SVasundhara Volam (num_vfs + 1)); 3883f2858738SVasundhara Volam 3884f2858738SVasundhara Volam /* Distribute unicast MACs, VLANs, IFACE count and MCCQ count equally 3885f2858738SVasundhara Volam * among the PF and it's VFs, if the fields are changeable 3886f2858738SVasundhara Volam */ 3887f2858738SVasundhara Volam if (res_mod.max_uc_mac == FIELD_MODIFIABLE) 3888f2858738SVasundhara Volam nic_vft->unicast_mac_count = cpu_to_le16(pool_res.max_uc_mac / 3889f2858738SVasundhara Volam (num_vfs + 1)); 3890f2858738SVasundhara Volam 3891f2858738SVasundhara Volam if (res_mod.max_vlans == FIELD_MODIFIABLE) 3892f2858738SVasundhara Volam nic_vft->vlan_count = cpu_to_le16(pool_res.max_vlans / 3893f2858738SVasundhara Volam (num_vfs + 1)); 3894f2858738SVasundhara Volam 3895f2858738SVasundhara Volam if (res_mod.max_iface_count == FIELD_MODIFIABLE) 3896f2858738SVasundhara Volam nic_vft->iface_count = cpu_to_le16(pool_res.max_iface_count / 3897f2858738SVasundhara Volam (num_vfs + 1)); 3898f2858738SVasundhara Volam 3899f2858738SVasundhara Volam if (res_mod.max_mcc_count == FIELD_MODIFIABLE) 3900f2858738SVasundhara Volam nic_vft->mcc_count = cpu_to_le16(pool_res.max_mcc_count / 3901f2858738SVasundhara Volam (num_vfs + 1)); 3902f2858738SVasundhara Volam } 3903f2858738SVasundhara Volam 3904bec84e6bSVasundhara Volam int be_cmd_set_sriov_config(struct be_adapter *adapter, 3905f2858738SVasundhara Volam struct be_resources pool_res, u16 num_vfs, 3906f2858738SVasundhara Volam u16 num_vf_qs) 3907bec84e6bSVasundhara Volam { 3908bec84e6bSVasundhara Volam struct { 3909bec84e6bSVasundhara Volam struct be_pcie_res_desc pcie; 3910bec84e6bSVasundhara Volam struct be_nic_res_desc nic_vft; 3911bec84e6bSVasundhara Volam } __packed desc; 3912bec84e6bSVasundhara Volam 3913bec84e6bSVasundhara Volam /* PF PCIE descriptor */ 3914bec84e6bSVasundhara Volam be_reset_pcie_desc(&desc.pcie); 3915bec84e6bSVasundhara Volam desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1; 3916bec84e6bSVasundhara Volam desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 3917f2858738SVasundhara Volam desc.pcie.flags = BIT(IMM_SHIFT) | BIT(NOSV_SHIFT); 3918bec84e6bSVasundhara Volam desc.pcie.pf_num = adapter->pdev->devfn; 3919bec84e6bSVasundhara Volam desc.pcie.sriov_state = num_vfs ? 1 : 0; 3920bec84e6bSVasundhara Volam desc.pcie.num_vfs = cpu_to_le16(num_vfs); 3921bec84e6bSVasundhara Volam 3922bec84e6bSVasundhara Volam /* VF NIC Template descriptor */ 3923bec84e6bSVasundhara Volam be_reset_nic_desc(&desc.nic_vft); 3924bec84e6bSVasundhara Volam desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1; 3925bec84e6bSVasundhara Volam desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 3926f2858738SVasundhara Volam desc.nic_vft.flags = BIT(VFT_SHIFT) | BIT(IMM_SHIFT) | BIT(NOSV_SHIFT); 3927bec84e6bSVasundhara Volam desc.nic_vft.pf_num = adapter->pdev->devfn; 3928bec84e6bSVasundhara Volam desc.nic_vft.vf_num = 0; 3929bec84e6bSVasundhara Volam 3930f2858738SVasundhara Volam be_fill_vf_res_template(adapter, pool_res, num_vfs, num_vf_qs, 3931f2858738SVasundhara Volam &desc.nic_vft); 3932bec84e6bSVasundhara Volam 3933bec84e6bSVasundhara Volam return be_cmd_set_profile_config(adapter, &desc, 3934bec84e6bSVasundhara Volam 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0); 3935a401801cSSathya Perla } 3936a401801cSSathya Perla 3937a401801cSSathya Perla int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) 3938a401801cSSathya Perla { 3939a401801cSSathya Perla struct be_mcc_wrb *wrb; 3940a401801cSSathya Perla struct be_cmd_req_manage_iface_filters *req; 3941a401801cSSathya Perla int status; 3942a401801cSSathya Perla 3943a401801cSSathya Perla if (iface == 0xFFFFFFFF) 3944a401801cSSathya Perla return -1; 3945a401801cSSathya Perla 3946a401801cSSathya Perla spin_lock_bh(&adapter->mcc_lock); 3947a401801cSSathya Perla 3948a401801cSSathya Perla wrb = wrb_from_mccq(adapter); 3949a401801cSSathya Perla if (!wrb) { 3950a401801cSSathya Perla status = -EBUSY; 3951a401801cSSathya Perla goto err; 3952a401801cSSathya Perla } 3953a401801cSSathya Perla req = embedded_payload(wrb); 3954a401801cSSathya Perla 3955a401801cSSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3956a401801cSSathya Perla OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req), 3957a401801cSSathya Perla wrb, NULL); 3958a401801cSSathya Perla req->op = op; 3959a401801cSSathya Perla req->target_iface_id = cpu_to_le32(iface); 3960a401801cSSathya Perla 3961a401801cSSathya Perla status = be_mcc_notify_wait(adapter); 3962a401801cSSathya Perla err: 3963a401801cSSathya Perla spin_unlock_bh(&adapter->mcc_lock); 3964a401801cSSathya Perla return status; 3965a401801cSSathya Perla } 3966a401801cSSathya Perla 3967a401801cSSathya Perla int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port) 3968a401801cSSathya Perla { 3969a401801cSSathya Perla struct be_port_res_desc port_desc; 3970a401801cSSathya Perla 3971a401801cSSathya Perla memset(&port_desc, 0, sizeof(port_desc)); 3972a401801cSSathya Perla port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1; 3973a401801cSSathya Perla port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 3974a401801cSSathya Perla port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT); 3975a401801cSSathya Perla port_desc.link_num = adapter->hba_port_num; 3976a401801cSSathya Perla if (port) { 3977a401801cSSathya Perla port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) | 3978a401801cSSathya Perla (1 << RCVID_SHIFT); 3979a401801cSSathya Perla port_desc.nv_port = swab16(port); 3980a401801cSSathya Perla } else { 3981a401801cSSathya Perla port_desc.nv_flags = NV_TYPE_DISABLED; 3982a401801cSSathya Perla port_desc.nv_port = 0; 3983a401801cSSathya Perla } 3984a401801cSSathya Perla 3985a401801cSSathya Perla return be_cmd_set_profile_config(adapter, &port_desc, 3986bec84e6bSVasundhara Volam RESOURCE_DESC_SIZE_V1, 1, 1, 0); 3987a401801cSSathya Perla } 3988a401801cSSathya Perla 39894c876616SSathya Perla int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, 39904c876616SSathya Perla int vf_num) 39914c876616SSathya Perla { 39924c876616SSathya Perla struct be_mcc_wrb *wrb; 39934c876616SSathya Perla struct be_cmd_req_get_iface_list *req; 39944c876616SSathya Perla struct be_cmd_resp_get_iface_list *resp; 39954c876616SSathya Perla int status; 39964c876616SSathya Perla 39974c876616SSathya Perla spin_lock_bh(&adapter->mcc_lock); 39984c876616SSathya Perla 39994c876616SSathya Perla wrb = wrb_from_mccq(adapter); 40004c876616SSathya Perla if (!wrb) { 40014c876616SSathya Perla status = -EBUSY; 40024c876616SSathya Perla goto err; 40034c876616SSathya Perla } 40044c876616SSathya Perla req = embedded_payload(wrb); 40054c876616SSathya Perla 40064c876616SSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 40074c876616SSathya Perla OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp), 40084c876616SSathya Perla wrb, NULL); 40094c876616SSathya Perla req->hdr.domain = vf_num + 1; 40104c876616SSathya Perla 40114c876616SSathya Perla status = be_mcc_notify_wait(adapter); 40124c876616SSathya Perla if (!status) { 40134c876616SSathya Perla resp = (struct be_cmd_resp_get_iface_list *)req; 40144c876616SSathya Perla vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id); 40154c876616SSathya Perla } 40164c876616SSathya Perla 40174c876616SSathya Perla err: 40184c876616SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 40194c876616SSathya Perla return status; 40204c876616SSathya Perla } 40214c876616SSathya Perla 40225c510811SSomnath Kotur static int lancer_wait_idle(struct be_adapter *adapter) 40235c510811SSomnath Kotur { 40245c510811SSomnath Kotur #define SLIPORT_IDLE_TIMEOUT 30 40255c510811SSomnath Kotur u32 reg_val; 40265c510811SSomnath Kotur int status = 0, i; 40275c510811SSomnath Kotur 40285c510811SSomnath Kotur for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) { 40295c510811SSomnath Kotur reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET); 40305c510811SSomnath Kotur if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0) 40315c510811SSomnath Kotur break; 40325c510811SSomnath Kotur 40335c510811SSomnath Kotur ssleep(1); 40345c510811SSomnath Kotur } 40355c510811SSomnath Kotur 40365c510811SSomnath Kotur if (i == SLIPORT_IDLE_TIMEOUT) 40375c510811SSomnath Kotur status = -1; 40385c510811SSomnath Kotur 40395c510811SSomnath Kotur return status; 40405c510811SSomnath Kotur } 40415c510811SSomnath Kotur 40425c510811SSomnath Kotur int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask) 40435c510811SSomnath Kotur { 40445c510811SSomnath Kotur int status = 0; 40455c510811SSomnath Kotur 40465c510811SSomnath Kotur status = lancer_wait_idle(adapter); 40475c510811SSomnath Kotur if (status) 40485c510811SSomnath Kotur return status; 40495c510811SSomnath Kotur 40505c510811SSomnath Kotur iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET); 40515c510811SSomnath Kotur 40525c510811SSomnath Kotur return status; 40535c510811SSomnath Kotur } 40545c510811SSomnath Kotur 40555c510811SSomnath Kotur /* Routine to check whether dump image is present or not */ 40565c510811SSomnath Kotur bool dump_present(struct be_adapter *adapter) 40575c510811SSomnath Kotur { 40585c510811SSomnath Kotur u32 sliport_status = 0; 40595c510811SSomnath Kotur 40605c510811SSomnath Kotur sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); 40615c510811SSomnath Kotur return !!(sliport_status & SLIPORT_STATUS_DIP_MASK); 40625c510811SSomnath Kotur } 40635c510811SSomnath Kotur 40645c510811SSomnath Kotur int lancer_initiate_dump(struct be_adapter *adapter) 40655c510811SSomnath Kotur { 4066f0613380SKalesh AP struct device *dev = &adapter->pdev->dev; 40675c510811SSomnath Kotur int status; 40685c510811SSomnath Kotur 4069f0613380SKalesh AP if (dump_present(adapter)) { 4070f0613380SKalesh AP dev_info(dev, "Previous dump not cleared, not forcing dump\n"); 4071f0613380SKalesh AP return -EEXIST; 4072f0613380SKalesh AP } 4073f0613380SKalesh AP 40745c510811SSomnath Kotur /* give firmware reset and diagnostic dump */ 40755c510811SSomnath Kotur status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK | 40765c510811SSomnath Kotur PHYSDEV_CONTROL_DD_MASK); 40775c510811SSomnath Kotur if (status < 0) { 4078f0613380SKalesh AP dev_err(dev, "FW reset failed\n"); 40795c510811SSomnath Kotur return status; 40805c510811SSomnath Kotur } 40815c510811SSomnath Kotur 40825c510811SSomnath Kotur status = lancer_wait_idle(adapter); 40835c510811SSomnath Kotur if (status) 40845c510811SSomnath Kotur return status; 40855c510811SSomnath Kotur 40865c510811SSomnath Kotur if (!dump_present(adapter)) { 4087f0613380SKalesh AP dev_err(dev, "FW dump not generated\n"); 4088f0613380SKalesh AP return -EIO; 40895c510811SSomnath Kotur } 40905c510811SSomnath Kotur 40915c510811SSomnath Kotur return 0; 40925c510811SSomnath Kotur } 40935c510811SSomnath Kotur 4094f0613380SKalesh AP int lancer_delete_dump(struct be_adapter *adapter) 4095f0613380SKalesh AP { 4096f0613380SKalesh AP int status; 4097f0613380SKalesh AP 4098f0613380SKalesh AP status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE); 4099f0613380SKalesh AP return be_cmd_status(status); 4100f0613380SKalesh AP } 4101f0613380SKalesh AP 4102dcf7ebbaSPadmanabh Ratnakar /* Uses sync mcc */ 4103dcf7ebbaSPadmanabh Ratnakar int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) 4104dcf7ebbaSPadmanabh Ratnakar { 4105dcf7ebbaSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 4106dcf7ebbaSPadmanabh Ratnakar struct be_cmd_enable_disable_vf *req; 4107dcf7ebbaSPadmanabh Ratnakar int status; 4108dcf7ebbaSPadmanabh Ratnakar 41090599863dSVasundhara Volam if (BEx_chip(adapter)) 4110dcf7ebbaSPadmanabh Ratnakar return 0; 4111dcf7ebbaSPadmanabh Ratnakar 4112dcf7ebbaSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 4113dcf7ebbaSPadmanabh Ratnakar 4114dcf7ebbaSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 4115dcf7ebbaSPadmanabh Ratnakar if (!wrb) { 4116dcf7ebbaSPadmanabh Ratnakar status = -EBUSY; 4117dcf7ebbaSPadmanabh Ratnakar goto err; 4118dcf7ebbaSPadmanabh Ratnakar } 4119dcf7ebbaSPadmanabh Ratnakar 4120dcf7ebbaSPadmanabh Ratnakar req = embedded_payload(wrb); 4121dcf7ebbaSPadmanabh Ratnakar 4122dcf7ebbaSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4123dcf7ebbaSPadmanabh Ratnakar OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req), 4124dcf7ebbaSPadmanabh Ratnakar wrb, NULL); 4125dcf7ebbaSPadmanabh Ratnakar 4126dcf7ebbaSPadmanabh Ratnakar req->hdr.domain = domain; 4127dcf7ebbaSPadmanabh Ratnakar req->enable = 1; 4128dcf7ebbaSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 4129dcf7ebbaSPadmanabh Ratnakar err: 4130dcf7ebbaSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 4131dcf7ebbaSPadmanabh Ratnakar return status; 4132dcf7ebbaSPadmanabh Ratnakar } 4133dcf7ebbaSPadmanabh Ratnakar 413468c45a2dSSomnath Kotur int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable) 413568c45a2dSSomnath Kotur { 413668c45a2dSSomnath Kotur struct be_mcc_wrb *wrb; 413768c45a2dSSomnath Kotur struct be_cmd_req_intr_set *req; 413868c45a2dSSomnath Kotur int status; 413968c45a2dSSomnath Kotur 414068c45a2dSSomnath Kotur if (mutex_lock_interruptible(&adapter->mbox_lock)) 414168c45a2dSSomnath Kotur return -1; 414268c45a2dSSomnath Kotur 414368c45a2dSSomnath Kotur wrb = wrb_from_mbox(adapter); 414468c45a2dSSomnath Kotur 414568c45a2dSSomnath Kotur req = embedded_payload(wrb); 414668c45a2dSSomnath Kotur 414768c45a2dSSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 414868c45a2dSSomnath Kotur OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req), 414968c45a2dSSomnath Kotur wrb, NULL); 415068c45a2dSSomnath Kotur 415168c45a2dSSomnath Kotur req->intr_enabled = intr_enable; 415268c45a2dSSomnath Kotur 415368c45a2dSSomnath Kotur status = be_mbox_notify_wait(adapter); 415468c45a2dSSomnath Kotur 415568c45a2dSSomnath Kotur mutex_unlock(&adapter->mbox_lock); 415668c45a2dSSomnath Kotur return status; 415768c45a2dSSomnath Kotur } 415868c45a2dSSomnath Kotur 4159542963b7SVasundhara Volam /* Uses MBOX */ 4160542963b7SVasundhara Volam int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id) 4161542963b7SVasundhara Volam { 4162542963b7SVasundhara Volam struct be_cmd_req_get_active_profile *req; 4163542963b7SVasundhara Volam struct be_mcc_wrb *wrb; 4164542963b7SVasundhara Volam int status; 4165542963b7SVasundhara Volam 4166542963b7SVasundhara Volam if (mutex_lock_interruptible(&adapter->mbox_lock)) 4167542963b7SVasundhara Volam return -1; 4168542963b7SVasundhara Volam 4169542963b7SVasundhara Volam wrb = wrb_from_mbox(adapter); 4170542963b7SVasundhara Volam if (!wrb) { 4171542963b7SVasundhara Volam status = -EBUSY; 4172542963b7SVasundhara Volam goto err; 4173542963b7SVasundhara Volam } 4174542963b7SVasundhara Volam 4175542963b7SVasundhara Volam req = embedded_payload(wrb); 4176542963b7SVasundhara Volam 4177542963b7SVasundhara Volam be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4178542963b7SVasundhara Volam OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req), 4179542963b7SVasundhara Volam wrb, NULL); 4180542963b7SVasundhara Volam 4181542963b7SVasundhara Volam status = be_mbox_notify_wait(adapter); 4182542963b7SVasundhara Volam if (!status) { 4183542963b7SVasundhara Volam struct be_cmd_resp_get_active_profile *resp = 4184542963b7SVasundhara Volam embedded_payload(wrb); 418503d28ffeSKalesh AP 4186542963b7SVasundhara Volam *profile_id = le16_to_cpu(resp->active_profile_id); 4187542963b7SVasundhara Volam } 4188542963b7SVasundhara Volam 4189542963b7SVasundhara Volam err: 4190542963b7SVasundhara Volam mutex_unlock(&adapter->mbox_lock); 4191542963b7SVasundhara Volam return status; 4192542963b7SVasundhara Volam } 4193542963b7SVasundhara Volam 4194bdce2ad7SSuresh Reddy int be_cmd_set_logical_link_config(struct be_adapter *adapter, 4195bdce2ad7SSuresh Reddy int link_state, u8 domain) 4196bdce2ad7SSuresh Reddy { 4197bdce2ad7SSuresh Reddy struct be_mcc_wrb *wrb; 4198bdce2ad7SSuresh Reddy struct be_cmd_req_set_ll_link *req; 4199bdce2ad7SSuresh Reddy int status; 4200bdce2ad7SSuresh Reddy 4201bdce2ad7SSuresh Reddy if (BEx_chip(adapter) || lancer_chip(adapter)) 420218fd6025SKalesh AP return -EOPNOTSUPP; 4203bdce2ad7SSuresh Reddy 4204bdce2ad7SSuresh Reddy spin_lock_bh(&adapter->mcc_lock); 4205bdce2ad7SSuresh Reddy 4206bdce2ad7SSuresh Reddy wrb = wrb_from_mccq(adapter); 4207bdce2ad7SSuresh Reddy if (!wrb) { 4208bdce2ad7SSuresh Reddy status = -EBUSY; 4209bdce2ad7SSuresh Reddy goto err; 4210bdce2ad7SSuresh Reddy } 4211bdce2ad7SSuresh Reddy 4212bdce2ad7SSuresh Reddy req = embedded_payload(wrb); 4213bdce2ad7SSuresh Reddy 4214bdce2ad7SSuresh Reddy be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4215bdce2ad7SSuresh Reddy OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG, 4216bdce2ad7SSuresh Reddy sizeof(*req), wrb, NULL); 4217bdce2ad7SSuresh Reddy 4218bdce2ad7SSuresh Reddy req->hdr.version = 1; 4219bdce2ad7SSuresh Reddy req->hdr.domain = domain; 4220bdce2ad7SSuresh Reddy 4221bdce2ad7SSuresh Reddy if (link_state == IFLA_VF_LINK_STATE_ENABLE) 4222bdce2ad7SSuresh Reddy req->link_config |= 1; 4223bdce2ad7SSuresh Reddy 4224bdce2ad7SSuresh Reddy if (link_state == IFLA_VF_LINK_STATE_AUTO) 4225bdce2ad7SSuresh Reddy req->link_config |= 1 << PLINK_TRACK_SHIFT; 4226bdce2ad7SSuresh Reddy 4227bdce2ad7SSuresh Reddy status = be_mcc_notify_wait(adapter); 4228bdce2ad7SSuresh Reddy err: 4229bdce2ad7SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 4230bdce2ad7SSuresh Reddy return status; 4231bdce2ad7SSuresh Reddy } 4232bdce2ad7SSuresh Reddy 42336a4ab669SParav Pandit int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, 42346a4ab669SParav Pandit int wrb_payload_size, u16 *cmd_status, u16 *ext_status) 42356a4ab669SParav Pandit { 42366a4ab669SParav Pandit struct be_adapter *adapter = netdev_priv(netdev_handle); 42376a4ab669SParav Pandit struct be_mcc_wrb *wrb; 42386a4ab669SParav Pandit struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload; 42396a4ab669SParav Pandit struct be_cmd_req_hdr *req; 42406a4ab669SParav Pandit struct be_cmd_resp_hdr *resp; 42416a4ab669SParav Pandit int status; 42426a4ab669SParav Pandit 42436a4ab669SParav Pandit spin_lock_bh(&adapter->mcc_lock); 42446a4ab669SParav Pandit 42456a4ab669SParav Pandit wrb = wrb_from_mccq(adapter); 42466a4ab669SParav Pandit if (!wrb) { 42476a4ab669SParav Pandit status = -EBUSY; 42486a4ab669SParav Pandit goto err; 42496a4ab669SParav Pandit } 42506a4ab669SParav Pandit req = embedded_payload(wrb); 42516a4ab669SParav Pandit resp = embedded_payload(wrb); 42526a4ab669SParav Pandit 42536a4ab669SParav Pandit be_wrb_cmd_hdr_prepare(req, hdr->subsystem, 42546a4ab669SParav Pandit hdr->opcode, wrb_payload_size, wrb, NULL); 42556a4ab669SParav Pandit memcpy(req, wrb_payload, wrb_payload_size); 42566a4ab669SParav Pandit be_dws_cpu_to_le(req, wrb_payload_size); 42576a4ab669SParav Pandit 42586a4ab669SParav Pandit status = be_mcc_notify_wait(adapter); 42596a4ab669SParav Pandit if (cmd_status) 42606a4ab669SParav Pandit *cmd_status = (status & 0xffff); 42616a4ab669SParav Pandit if (ext_status) 42626a4ab669SParav Pandit *ext_status = 0; 42636a4ab669SParav Pandit memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length); 42646a4ab669SParav Pandit be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length); 42656a4ab669SParav Pandit err: 42666a4ab669SParav Pandit spin_unlock_bh(&adapter->mcc_lock); 42676a4ab669SParav Pandit return status; 42686a4ab669SParav Pandit } 42696a4ab669SParav Pandit EXPORT_SYMBOL(be_roce_mcc_cmd); 4270