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 966589ade0SSathya Perla if (be_error(adapter)) 979aebddd1SJeff Kirsher return; 989aebddd1SJeff Kirsher 999aebddd1SJeff Kirsher val |= mccq->id & DB_MCCQ_RING_ID_MASK; 1009aebddd1SJeff Kirsher val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; 1019aebddd1SJeff Kirsher 1029aebddd1SJeff Kirsher wmb(); 1039aebddd1SJeff Kirsher iowrite32(val, adapter->db + DB_MCCQ_OFFSET); 1049aebddd1SJeff Kirsher } 1059aebddd1SJeff Kirsher 1069aebddd1SJeff Kirsher /* To check if valid bit is set, check the entire word as we don't know 1079aebddd1SJeff Kirsher * the endianness of the data (old entry is host endian while a new entry is 1089aebddd1SJeff Kirsher * little endian) */ 1099aebddd1SJeff Kirsher static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) 1109aebddd1SJeff Kirsher { 1119e9ff4b7SSathya Perla u32 flags; 1129e9ff4b7SSathya Perla 1139aebddd1SJeff Kirsher if (compl->flags != 0) { 1149e9ff4b7SSathya Perla flags = le32_to_cpu(compl->flags); 1159e9ff4b7SSathya Perla if (flags & CQE_FLAGS_VALID_MASK) { 1169e9ff4b7SSathya Perla compl->flags = flags; 1179aebddd1SJeff Kirsher return true; 1189aebddd1SJeff Kirsher } 1199aebddd1SJeff Kirsher } 1209e9ff4b7SSathya Perla return false; 1219e9ff4b7SSathya Perla } 1229aebddd1SJeff Kirsher 1239aebddd1SJeff Kirsher /* Need to reset the entire word that houses the valid bit */ 1249aebddd1SJeff Kirsher static inline void be_mcc_compl_use(struct be_mcc_compl *compl) 1259aebddd1SJeff Kirsher { 1269aebddd1SJeff Kirsher compl->flags = 0; 1279aebddd1SJeff Kirsher } 1289aebddd1SJeff Kirsher 129652bf646SPadmanabh Ratnakar static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1) 130652bf646SPadmanabh Ratnakar { 131652bf646SPadmanabh Ratnakar unsigned long addr; 132652bf646SPadmanabh Ratnakar 133652bf646SPadmanabh Ratnakar addr = tag1; 134652bf646SPadmanabh Ratnakar addr = ((addr << 16) << 16) | tag0; 135652bf646SPadmanabh Ratnakar return (void *)addr; 136652bf646SPadmanabh Ratnakar } 137652bf646SPadmanabh Ratnakar 1384c60005fSKalesh AP static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status) 1394c60005fSKalesh AP { 1404c60005fSKalesh AP if (base_status == MCC_STATUS_NOT_SUPPORTED || 1414c60005fSKalesh AP base_status == MCC_STATUS_ILLEGAL_REQUEST || 1424c60005fSKalesh AP addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES || 14377be8c1cSKalesh AP addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS || 1444c60005fSKalesh AP (opcode == OPCODE_COMMON_WRITE_FLASHROM && 1454c60005fSKalesh AP (base_status == MCC_STATUS_ILLEGAL_FIELD || 1464c60005fSKalesh AP addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH))) 1474c60005fSKalesh AP return true; 1484c60005fSKalesh AP else 1494c60005fSKalesh AP return false; 1504c60005fSKalesh AP } 1514c60005fSKalesh AP 152559b633fSSathya Perla /* Place holder for all the async MCC cmds wherein the caller is not in a busy 153559b633fSSathya Perla * loop (has not issued be_mcc_notify_wait()) 154559b633fSSathya Perla */ 155559b633fSSathya Perla static void be_async_cmd_process(struct be_adapter *adapter, 156559b633fSSathya Perla struct be_mcc_compl *compl, 157559b633fSSathya Perla struct be_cmd_resp_hdr *resp_hdr) 158559b633fSSathya Perla { 159559b633fSSathya Perla enum mcc_base_status base_status = base_status(compl->status); 160559b633fSSathya Perla u8 opcode = 0, subsystem = 0; 161559b633fSSathya Perla 162559b633fSSathya Perla if (resp_hdr) { 163559b633fSSathya Perla opcode = resp_hdr->opcode; 164559b633fSSathya Perla subsystem = resp_hdr->subsystem; 165559b633fSSathya Perla } 166559b633fSSathya Perla 167559b633fSSathya Perla if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST && 168559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_LOWLEVEL) { 169559b633fSSathya Perla complete(&adapter->et_cmd_compl); 170559b633fSSathya Perla return; 171559b633fSSathya Perla } 172559b633fSSathya Perla 173559b633fSSathya Perla if ((opcode == OPCODE_COMMON_WRITE_FLASHROM || 174559b633fSSathya Perla opcode == OPCODE_COMMON_WRITE_OBJECT) && 175559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_COMMON) { 176559b633fSSathya Perla adapter->flash_status = compl->status; 177559b633fSSathya Perla complete(&adapter->et_cmd_compl); 178559b633fSSathya Perla return; 179559b633fSSathya Perla } 180559b633fSSathya Perla 181559b633fSSathya Perla if ((opcode == OPCODE_ETH_GET_STATISTICS || 182559b633fSSathya Perla opcode == OPCODE_ETH_GET_PPORT_STATS) && 183559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_ETH && 184559b633fSSathya Perla base_status == MCC_STATUS_SUCCESS) { 185559b633fSSathya Perla be_parse_stats(adapter); 186559b633fSSathya Perla adapter->stats_cmd_sent = false; 187559b633fSSathya Perla return; 188559b633fSSathya Perla } 189559b633fSSathya Perla 190559b633fSSathya Perla if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES && 191559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_COMMON) { 192559b633fSSathya Perla if (base_status == MCC_STATUS_SUCCESS) { 193559b633fSSathya Perla struct be_cmd_resp_get_cntl_addnl_attribs *resp = 194559b633fSSathya Perla (void *)resp_hdr; 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 3369aebddd1SJeff Kirsher static void be_async_grp5_evt_process(struct be_adapter *adapter, 3373acf19d9SSathya Perla struct be_mcc_compl *compl) 3389aebddd1SJeff Kirsher { 3393acf19d9SSathya Perla u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) & 3403acf19d9SSathya Perla ASYNC_EVENT_TYPE_MASK; 3419aebddd1SJeff Kirsher 3429aebddd1SJeff Kirsher switch (event_type) { 3439aebddd1SJeff Kirsher case ASYNC_EVENT_COS_PRIORITY: 3443acf19d9SSathya Perla be_async_grp5_cos_priority_process(adapter, compl); 3459aebddd1SJeff Kirsher break; 3469aebddd1SJeff Kirsher case ASYNC_EVENT_QOS_SPEED: 3473acf19d9SSathya Perla be_async_grp5_qos_speed_process(adapter, compl); 3489aebddd1SJeff Kirsher break; 3499aebddd1SJeff Kirsher case ASYNC_EVENT_PVID_STATE: 3503acf19d9SSathya Perla be_async_grp5_pvid_state_process(adapter, compl); 3519aebddd1SJeff Kirsher break; 3529aebddd1SJeff Kirsher default: 3539aebddd1SJeff Kirsher break; 3549aebddd1SJeff Kirsher } 3559aebddd1SJeff Kirsher } 3569aebddd1SJeff Kirsher 357bc0c3405SAjit Khaparde static void be_async_dbg_evt_process(struct be_adapter *adapter, 3583acf19d9SSathya Perla struct be_mcc_compl *cmp) 359bc0c3405SAjit Khaparde { 360bc0c3405SAjit Khaparde u8 event_type = 0; 361bc0c3405SAjit Khaparde struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp; 362bc0c3405SAjit Khaparde 3633acf19d9SSathya Perla event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) & 3643acf19d9SSathya Perla ASYNC_EVENT_TYPE_MASK; 365bc0c3405SAjit Khaparde 366bc0c3405SAjit Khaparde switch (event_type) { 367bc0c3405SAjit Khaparde case ASYNC_DEBUG_EVENT_TYPE_QNQ: 368bc0c3405SAjit Khaparde if (evt->valid) 369bc0c3405SAjit Khaparde adapter->qnq_vid = le16_to_cpu(evt->vlan_tag); 370bc0c3405SAjit Khaparde adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD; 371bc0c3405SAjit Khaparde break; 372bc0c3405SAjit Khaparde default: 37305ccaa2bSVasundhara Volam dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n", 37405ccaa2bSVasundhara Volam event_type); 375bc0c3405SAjit Khaparde break; 376bc0c3405SAjit Khaparde } 377bc0c3405SAjit Khaparde } 378bc0c3405SAjit Khaparde 37921252377SVasundhara Volam static void be_async_sliport_evt_process(struct be_adapter *adapter, 38021252377SVasundhara Volam struct be_mcc_compl *cmp) 38121252377SVasundhara Volam { 38221252377SVasundhara Volam u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) & 38321252377SVasundhara Volam ASYNC_EVENT_TYPE_MASK; 38421252377SVasundhara Volam 38521252377SVasundhara Volam if (event_type == ASYNC_EVENT_PORT_MISCONFIG) 38621252377SVasundhara Volam be_async_port_misconfig_event_process(adapter, cmp); 38721252377SVasundhara Volam } 38821252377SVasundhara Volam 3893acf19d9SSathya Perla static inline bool is_link_state_evt(u32 flags) 3909aebddd1SJeff Kirsher { 3913acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 3929aebddd1SJeff Kirsher ASYNC_EVENT_CODE_LINK_STATE; 3939aebddd1SJeff Kirsher } 3949aebddd1SJeff Kirsher 3953acf19d9SSathya Perla static inline bool is_grp5_evt(u32 flags) 3969aebddd1SJeff Kirsher { 3973acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 3983acf19d9SSathya Perla ASYNC_EVENT_CODE_GRP_5; 3999aebddd1SJeff Kirsher } 4009aebddd1SJeff Kirsher 4013acf19d9SSathya Perla static inline bool is_dbg_evt(u32 flags) 402bc0c3405SAjit Khaparde { 4033acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4043acf19d9SSathya Perla ASYNC_EVENT_CODE_QNQ; 4053acf19d9SSathya Perla } 4063acf19d9SSathya Perla 40721252377SVasundhara Volam static inline bool is_sliport_evt(u32 flags) 40821252377SVasundhara Volam { 40921252377SVasundhara Volam return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 41021252377SVasundhara Volam ASYNC_EVENT_CODE_SLIPORT; 41121252377SVasundhara Volam } 41221252377SVasundhara Volam 4133acf19d9SSathya Perla static void be_mcc_event_process(struct be_adapter *adapter, 4143acf19d9SSathya Perla struct be_mcc_compl *compl) 4153acf19d9SSathya Perla { 4163acf19d9SSathya Perla if (is_link_state_evt(compl->flags)) 4173acf19d9SSathya Perla be_async_link_state_process(adapter, compl); 4183acf19d9SSathya Perla else if (is_grp5_evt(compl->flags)) 4193acf19d9SSathya Perla be_async_grp5_evt_process(adapter, compl); 4203acf19d9SSathya Perla else if (is_dbg_evt(compl->flags)) 4213acf19d9SSathya Perla be_async_dbg_evt_process(adapter, compl); 42221252377SVasundhara Volam else if (is_sliport_evt(compl->flags)) 42321252377SVasundhara Volam be_async_sliport_evt_process(adapter, compl); 424bc0c3405SAjit Khaparde } 425bc0c3405SAjit Khaparde 4269aebddd1SJeff Kirsher static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) 4279aebddd1SJeff Kirsher { 4289aebddd1SJeff Kirsher struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq; 4299aebddd1SJeff Kirsher struct be_mcc_compl *compl = queue_tail_node(mcc_cq); 4309aebddd1SJeff Kirsher 4319aebddd1SJeff Kirsher if (be_mcc_compl_is_new(compl)) { 4329aebddd1SJeff Kirsher queue_tail_inc(mcc_cq); 4339aebddd1SJeff Kirsher return compl; 4349aebddd1SJeff Kirsher } 4359aebddd1SJeff Kirsher return NULL; 4369aebddd1SJeff Kirsher } 4379aebddd1SJeff Kirsher 4389aebddd1SJeff Kirsher void be_async_mcc_enable(struct be_adapter *adapter) 4399aebddd1SJeff Kirsher { 4409aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_cq_lock); 4419aebddd1SJeff Kirsher 4429aebddd1SJeff Kirsher be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0); 4439aebddd1SJeff Kirsher adapter->mcc_obj.rearm_cq = true; 4449aebddd1SJeff Kirsher 4459aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_cq_lock); 4469aebddd1SJeff Kirsher } 4479aebddd1SJeff Kirsher 4489aebddd1SJeff Kirsher void be_async_mcc_disable(struct be_adapter *adapter) 4499aebddd1SJeff Kirsher { 450a323d9bfSSathya Perla spin_lock_bh(&adapter->mcc_cq_lock); 451a323d9bfSSathya Perla 4529aebddd1SJeff Kirsher adapter->mcc_obj.rearm_cq = false; 453a323d9bfSSathya Perla be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); 454a323d9bfSSathya Perla 455a323d9bfSSathya Perla spin_unlock_bh(&adapter->mcc_cq_lock); 4569aebddd1SJeff Kirsher } 4579aebddd1SJeff Kirsher 45810ef9ab4SSathya Perla int be_process_mcc(struct be_adapter *adapter) 4599aebddd1SJeff Kirsher { 4609aebddd1SJeff Kirsher struct be_mcc_compl *compl; 46110ef9ab4SSathya Perla int num = 0, status = 0; 4629aebddd1SJeff Kirsher struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 4639aebddd1SJeff Kirsher 464072a9c48SAmerigo Wang spin_lock(&adapter->mcc_cq_lock); 4653acf19d9SSathya Perla 4669aebddd1SJeff Kirsher while ((compl = be_mcc_compl_get(adapter))) { 4679aebddd1SJeff Kirsher if (compl->flags & CQE_FLAGS_ASYNC_MASK) { 4683acf19d9SSathya Perla be_mcc_event_process(adapter, compl); 4699aebddd1SJeff Kirsher } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { 47010ef9ab4SSathya Perla status = be_mcc_compl_process(adapter, compl); 4719aebddd1SJeff Kirsher atomic_dec(&mcc_obj->q.used); 4729aebddd1SJeff Kirsher } 4739aebddd1SJeff Kirsher be_mcc_compl_use(compl); 4749aebddd1SJeff Kirsher num++; 4759aebddd1SJeff Kirsher } 4769aebddd1SJeff Kirsher 47710ef9ab4SSathya Perla if (num) 47810ef9ab4SSathya Perla be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); 47910ef9ab4SSathya Perla 480072a9c48SAmerigo Wang spin_unlock(&adapter->mcc_cq_lock); 48110ef9ab4SSathya Perla return status; 4829aebddd1SJeff Kirsher } 4839aebddd1SJeff Kirsher 4849aebddd1SJeff Kirsher /* Wait till no more pending mcc requests are present */ 4859aebddd1SJeff Kirsher static int be_mcc_wait_compl(struct be_adapter *adapter) 4869aebddd1SJeff Kirsher { 4879aebddd1SJeff Kirsher #define mcc_timeout 120000 /* 12s timeout */ 48810ef9ab4SSathya Perla int i, status = 0; 4899aebddd1SJeff Kirsher struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 4909aebddd1SJeff Kirsher 4916589ade0SSathya Perla for (i = 0; i < mcc_timeout; i++) { 4926589ade0SSathya Perla if (be_error(adapter)) 4939aebddd1SJeff Kirsher return -EIO; 4949aebddd1SJeff Kirsher 495072a9c48SAmerigo Wang local_bh_disable(); 49610ef9ab4SSathya Perla status = be_process_mcc(adapter); 497072a9c48SAmerigo Wang local_bh_enable(); 4989aebddd1SJeff Kirsher 4999aebddd1SJeff Kirsher if (atomic_read(&mcc_obj->q.used) == 0) 5009aebddd1SJeff Kirsher break; 5019aebddd1SJeff Kirsher udelay(100); 5029aebddd1SJeff Kirsher } 5039aebddd1SJeff Kirsher if (i == mcc_timeout) { 5046589ade0SSathya Perla dev_err(&adapter->pdev->dev, "FW not responding\n"); 5056589ade0SSathya Perla adapter->fw_timeout = true; 506652bf646SPadmanabh Ratnakar return -EIO; 5079aebddd1SJeff Kirsher } 5089aebddd1SJeff Kirsher return status; 5099aebddd1SJeff Kirsher } 5109aebddd1SJeff Kirsher 5119aebddd1SJeff Kirsher /* Notify MCC requests and wait for completion */ 5129aebddd1SJeff Kirsher static int be_mcc_notify_wait(struct be_adapter *adapter) 5139aebddd1SJeff Kirsher { 514652bf646SPadmanabh Ratnakar int status; 515652bf646SPadmanabh Ratnakar struct be_mcc_wrb *wrb; 516652bf646SPadmanabh Ratnakar struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 517652bf646SPadmanabh Ratnakar u16 index = mcc_obj->q.head; 518652bf646SPadmanabh Ratnakar struct be_cmd_resp_hdr *resp; 519652bf646SPadmanabh Ratnakar 520652bf646SPadmanabh Ratnakar index_dec(&index, mcc_obj->q.len); 521652bf646SPadmanabh Ratnakar wrb = queue_index_node(&mcc_obj->q, index); 522652bf646SPadmanabh Ratnakar 523652bf646SPadmanabh Ratnakar resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1); 524652bf646SPadmanabh Ratnakar 5259aebddd1SJeff Kirsher be_mcc_notify(adapter); 526652bf646SPadmanabh Ratnakar 527652bf646SPadmanabh Ratnakar status = be_mcc_wait_compl(adapter); 528652bf646SPadmanabh Ratnakar if (status == -EIO) 529652bf646SPadmanabh Ratnakar goto out; 530652bf646SPadmanabh Ratnakar 5314c60005fSKalesh AP status = (resp->base_status | 5324c60005fSKalesh AP ((resp->addl_status & CQE_ADDL_STATUS_MASK) << 5334c60005fSKalesh AP CQE_ADDL_STATUS_SHIFT)); 534652bf646SPadmanabh Ratnakar out: 535652bf646SPadmanabh Ratnakar return status; 5369aebddd1SJeff Kirsher } 5379aebddd1SJeff Kirsher 5389aebddd1SJeff Kirsher static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) 5399aebddd1SJeff Kirsher { 5409aebddd1SJeff Kirsher int msecs = 0; 5419aebddd1SJeff Kirsher u32 ready; 5429aebddd1SJeff Kirsher 5436589ade0SSathya Perla do { 5446589ade0SSathya Perla if (be_error(adapter)) 5459aebddd1SJeff Kirsher return -EIO; 5469aebddd1SJeff Kirsher 5479aebddd1SJeff Kirsher ready = ioread32(db); 548434b3648SSathya Perla if (ready == 0xffffffff) 5499aebddd1SJeff Kirsher return -1; 5509aebddd1SJeff Kirsher 5519aebddd1SJeff Kirsher ready &= MPU_MAILBOX_DB_RDY_MASK; 5529aebddd1SJeff Kirsher if (ready) 5539aebddd1SJeff Kirsher break; 5549aebddd1SJeff Kirsher 5559aebddd1SJeff Kirsher if (msecs > 4000) { 5566589ade0SSathya Perla dev_err(&adapter->pdev->dev, "FW not responding\n"); 5576589ade0SSathya Perla adapter->fw_timeout = true; 558f67ef7baSPadmanabh Ratnakar be_detect_error(adapter); 5599aebddd1SJeff Kirsher return -1; 5609aebddd1SJeff Kirsher } 5619aebddd1SJeff Kirsher 5629aebddd1SJeff Kirsher msleep(1); 5639aebddd1SJeff Kirsher msecs++; 5649aebddd1SJeff Kirsher } while (true); 5659aebddd1SJeff Kirsher 5669aebddd1SJeff Kirsher return 0; 5679aebddd1SJeff Kirsher } 5689aebddd1SJeff Kirsher 5699aebddd1SJeff Kirsher /* 5709aebddd1SJeff Kirsher * Insert the mailbox address into the doorbell in two steps 5719aebddd1SJeff Kirsher * Polls on the mbox doorbell till a command completion (or a timeout) occurs 5729aebddd1SJeff Kirsher */ 5739aebddd1SJeff Kirsher static int be_mbox_notify_wait(struct be_adapter *adapter) 5749aebddd1SJeff Kirsher { 5759aebddd1SJeff Kirsher int status; 5769aebddd1SJeff Kirsher u32 val = 0; 5779aebddd1SJeff Kirsher void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET; 5789aebddd1SJeff Kirsher struct be_dma_mem *mbox_mem = &adapter->mbox_mem; 5799aebddd1SJeff Kirsher struct be_mcc_mailbox *mbox = mbox_mem->va; 5809aebddd1SJeff Kirsher struct be_mcc_compl *compl = &mbox->compl; 5819aebddd1SJeff Kirsher 5829aebddd1SJeff Kirsher /* wait for ready to be set */ 5839aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 5849aebddd1SJeff Kirsher if (status != 0) 5859aebddd1SJeff Kirsher return status; 5869aebddd1SJeff Kirsher 5879aebddd1SJeff Kirsher val |= MPU_MAILBOX_DB_HI_MASK; 5889aebddd1SJeff Kirsher /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ 5899aebddd1SJeff Kirsher val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; 5909aebddd1SJeff Kirsher iowrite32(val, db); 5919aebddd1SJeff Kirsher 5929aebddd1SJeff Kirsher /* wait for ready to be set */ 5939aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 5949aebddd1SJeff Kirsher if (status != 0) 5959aebddd1SJeff Kirsher return status; 5969aebddd1SJeff Kirsher 5979aebddd1SJeff Kirsher val = 0; 5989aebddd1SJeff Kirsher /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ 5999aebddd1SJeff Kirsher val |= (u32)(mbox_mem->dma >> 4) << 2; 6009aebddd1SJeff Kirsher iowrite32(val, db); 6019aebddd1SJeff Kirsher 6029aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 6039aebddd1SJeff Kirsher if (status != 0) 6049aebddd1SJeff Kirsher return status; 6059aebddd1SJeff Kirsher 6069aebddd1SJeff Kirsher /* A cq entry has been made now */ 6079aebddd1SJeff Kirsher if (be_mcc_compl_is_new(compl)) { 6089aebddd1SJeff Kirsher status = be_mcc_compl_process(adapter, &mbox->compl); 6099aebddd1SJeff Kirsher be_mcc_compl_use(compl); 6109aebddd1SJeff Kirsher if (status) 6119aebddd1SJeff Kirsher return status; 6129aebddd1SJeff Kirsher } else { 6139aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "invalid mailbox completion\n"); 6149aebddd1SJeff Kirsher return -1; 6159aebddd1SJeff Kirsher } 6169aebddd1SJeff Kirsher return 0; 6179aebddd1SJeff Kirsher } 6189aebddd1SJeff Kirsher 619c5b3ad4cSSathya Perla static u16 be_POST_stage_get(struct be_adapter *adapter) 6209aebddd1SJeff Kirsher { 6219aebddd1SJeff Kirsher u32 sem; 6229aebddd1SJeff Kirsher 623c5b3ad4cSSathya Perla if (BEx_chip(adapter)) 624c5b3ad4cSSathya Perla sem = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx); 6259aebddd1SJeff Kirsher else 626c5b3ad4cSSathya Perla pci_read_config_dword(adapter->pdev, 627c5b3ad4cSSathya Perla SLIPORT_SEMAPHORE_OFFSET_SH, &sem); 628c5b3ad4cSSathya Perla 629c5b3ad4cSSathya Perla return sem & POST_STAGE_MASK; 6309aebddd1SJeff Kirsher } 6319aebddd1SJeff Kirsher 63287f20c26SGavin Shan static int lancer_wait_ready(struct be_adapter *adapter) 633bf99e50dSPadmanabh Ratnakar { 634bf99e50dSPadmanabh Ratnakar #define SLIPORT_READY_TIMEOUT 30 635bf99e50dSPadmanabh Ratnakar u32 sliport_status; 636e673244aSKalesh AP int i; 637bf99e50dSPadmanabh Ratnakar 638bf99e50dSPadmanabh Ratnakar for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) { 639bf99e50dSPadmanabh Ratnakar sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); 640bf99e50dSPadmanabh Ratnakar if (sliport_status & SLIPORT_STATUS_RDY_MASK) 6419fa465c0SSathya Perla return 0; 6429fa465c0SSathya Perla 6439fa465c0SSathya Perla if (sliport_status & SLIPORT_STATUS_ERR_MASK && 6449fa465c0SSathya Perla !(sliport_status & SLIPORT_STATUS_RN_MASK)) 6459fa465c0SSathya Perla return -EIO; 646bf99e50dSPadmanabh Ratnakar 647bf99e50dSPadmanabh Ratnakar msleep(1000); 648bf99e50dSPadmanabh Ratnakar } 649bf99e50dSPadmanabh Ratnakar 650e673244aSKalesh AP return sliport_status ? : -1; 651bf99e50dSPadmanabh Ratnakar } 652bf99e50dSPadmanabh Ratnakar 653bf99e50dSPadmanabh Ratnakar int be_fw_wait_ready(struct be_adapter *adapter) 6549aebddd1SJeff Kirsher { 6559aebddd1SJeff Kirsher u16 stage; 6569aebddd1SJeff Kirsher int status, timeout = 0; 6579aebddd1SJeff Kirsher struct device *dev = &adapter->pdev->dev; 6589aebddd1SJeff Kirsher 659bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) { 660bf99e50dSPadmanabh Ratnakar status = lancer_wait_ready(adapter); 661e673244aSKalesh AP if (status) { 662e673244aSKalesh AP stage = status; 663e673244aSKalesh AP goto err; 664e673244aSKalesh AP } 665e673244aSKalesh AP return 0; 666bf99e50dSPadmanabh Ratnakar } 667bf99e50dSPadmanabh Ratnakar 6689aebddd1SJeff Kirsher do { 669ca3de6b2SSathya Perla /* There's no means to poll POST state on BE2/3 VFs */ 670ca3de6b2SSathya Perla if (BEx_chip(adapter) && be_virtfn(adapter)) 671ca3de6b2SSathya Perla return 0; 672ca3de6b2SSathya Perla 673c5b3ad4cSSathya Perla stage = be_POST_stage_get(adapter); 67466d29cbcSGavin Shan if (stage == POST_STAGE_ARMFW_RDY) 67566d29cbcSGavin Shan return 0; 67666d29cbcSGavin Shan 677a2cc4e0bSSathya Perla dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout); 6789aebddd1SJeff Kirsher if (msleep_interruptible(2000)) { 6799aebddd1SJeff Kirsher dev_err(dev, "Waiting for POST aborted\n"); 6809aebddd1SJeff Kirsher return -EINTR; 6819aebddd1SJeff Kirsher } 6829aebddd1SJeff Kirsher timeout += 2; 6833ab81b5fSSomnath Kotur } while (timeout < 60); 6849aebddd1SJeff Kirsher 685e673244aSKalesh AP err: 686e673244aSKalesh AP dev_err(dev, "POST timeout; stage=%#x\n", stage); 6879fa465c0SSathya Perla return -ETIMEDOUT; 6889aebddd1SJeff Kirsher } 6899aebddd1SJeff Kirsher 6909aebddd1SJeff Kirsher static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) 6919aebddd1SJeff Kirsher { 6929aebddd1SJeff Kirsher return &wrb->payload.sgl[0]; 6939aebddd1SJeff Kirsher } 6949aebddd1SJeff Kirsher 695a2cc4e0bSSathya Perla static inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr) 696bea50988SSathya Perla { 697bea50988SSathya Perla wrb->tag0 = addr & 0xFFFFFFFF; 698bea50988SSathya Perla wrb->tag1 = upper_32_bits(addr); 699bea50988SSathya Perla } 7009aebddd1SJeff Kirsher 7019aebddd1SJeff Kirsher /* Don't touch the hdr after it's prepared */ 702106df1e3SSomnath Kotur /* mem will be NULL for embedded commands */ 703106df1e3SSomnath Kotur static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, 704106df1e3SSomnath Kotur u8 subsystem, u8 opcode, int cmd_len, 705a2cc4e0bSSathya Perla struct be_mcc_wrb *wrb, 706a2cc4e0bSSathya Perla struct be_dma_mem *mem) 7079aebddd1SJeff Kirsher { 708106df1e3SSomnath Kotur struct be_sge *sge; 709106df1e3SSomnath Kotur 7109aebddd1SJeff Kirsher req_hdr->opcode = opcode; 7119aebddd1SJeff Kirsher req_hdr->subsystem = subsystem; 7129aebddd1SJeff Kirsher req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); 7139aebddd1SJeff Kirsher req_hdr->version = 0; 714bea50988SSathya Perla fill_wrb_tags(wrb, (ulong) req_hdr); 715106df1e3SSomnath Kotur wrb->payload_length = cmd_len; 716106df1e3SSomnath Kotur if (mem) { 717106df1e3SSomnath Kotur wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) << 718106df1e3SSomnath Kotur MCC_WRB_SGE_CNT_SHIFT; 719106df1e3SSomnath Kotur sge = nonembedded_sgl(wrb); 720106df1e3SSomnath Kotur sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma)); 721106df1e3SSomnath Kotur sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF); 722106df1e3SSomnath Kotur sge->len = cpu_to_le32(mem->size); 723106df1e3SSomnath Kotur } else 724106df1e3SSomnath Kotur wrb->embedded |= MCC_WRB_EMBEDDED_MASK; 725106df1e3SSomnath Kotur be_dws_cpu_to_le(wrb, 8); 7269aebddd1SJeff Kirsher } 7279aebddd1SJeff Kirsher 7289aebddd1SJeff Kirsher static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, 7299aebddd1SJeff Kirsher struct be_dma_mem *mem) 7309aebddd1SJeff Kirsher { 7319aebddd1SJeff Kirsher int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); 7329aebddd1SJeff Kirsher u64 dma = (u64)mem->dma; 7339aebddd1SJeff Kirsher 7349aebddd1SJeff Kirsher for (i = 0; i < buf_pages; i++) { 7359aebddd1SJeff Kirsher pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); 7369aebddd1SJeff Kirsher pages[i].hi = cpu_to_le32(upper_32_bits(dma)); 7379aebddd1SJeff Kirsher dma += PAGE_SIZE_4K; 7389aebddd1SJeff Kirsher } 7399aebddd1SJeff Kirsher } 7409aebddd1SJeff Kirsher 7419aebddd1SJeff Kirsher static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter) 7429aebddd1SJeff Kirsher { 7439aebddd1SJeff Kirsher struct be_dma_mem *mbox_mem = &adapter->mbox_mem; 7449aebddd1SJeff Kirsher struct be_mcc_wrb *wrb 7459aebddd1SJeff Kirsher = &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; 7469aebddd1SJeff Kirsher memset(wrb, 0, sizeof(*wrb)); 7479aebddd1SJeff Kirsher return wrb; 7489aebddd1SJeff Kirsher } 7499aebddd1SJeff Kirsher 7509aebddd1SJeff Kirsher static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) 7519aebddd1SJeff Kirsher { 7529aebddd1SJeff Kirsher struct be_queue_info *mccq = &adapter->mcc_obj.q; 7539aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 7549aebddd1SJeff Kirsher 755aa790db9SPadmanabh Ratnakar if (!mccq->created) 756aa790db9SPadmanabh Ratnakar return NULL; 757aa790db9SPadmanabh Ratnakar 7584d277125SVasundhara Volam if (atomic_read(&mccq->used) >= mccq->len) 7599aebddd1SJeff Kirsher return NULL; 7609aebddd1SJeff Kirsher 7619aebddd1SJeff Kirsher wrb = queue_head_node(mccq); 7629aebddd1SJeff Kirsher queue_head_inc(mccq); 7639aebddd1SJeff Kirsher atomic_inc(&mccq->used); 7649aebddd1SJeff Kirsher memset(wrb, 0, sizeof(*wrb)); 7659aebddd1SJeff Kirsher return wrb; 7669aebddd1SJeff Kirsher } 7679aebddd1SJeff Kirsher 768bea50988SSathya Perla static bool use_mcc(struct be_adapter *adapter) 769bea50988SSathya Perla { 770bea50988SSathya Perla return adapter->mcc_obj.q.created; 771bea50988SSathya Perla } 772bea50988SSathya Perla 773bea50988SSathya Perla /* Must be used only in process context */ 774bea50988SSathya Perla static int be_cmd_lock(struct be_adapter *adapter) 775bea50988SSathya Perla { 776bea50988SSathya Perla if (use_mcc(adapter)) { 777bea50988SSathya Perla spin_lock_bh(&adapter->mcc_lock); 778bea50988SSathya Perla return 0; 779bea50988SSathya Perla } else { 780bea50988SSathya Perla return mutex_lock_interruptible(&adapter->mbox_lock); 781bea50988SSathya Perla } 782bea50988SSathya Perla } 783bea50988SSathya Perla 784bea50988SSathya Perla /* Must be used only in process context */ 785bea50988SSathya Perla static void be_cmd_unlock(struct be_adapter *adapter) 786bea50988SSathya Perla { 787bea50988SSathya Perla if (use_mcc(adapter)) 788bea50988SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 789bea50988SSathya Perla else 790bea50988SSathya Perla return mutex_unlock(&adapter->mbox_lock); 791bea50988SSathya Perla } 792bea50988SSathya Perla 793bea50988SSathya Perla static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter, 794bea50988SSathya Perla struct be_mcc_wrb *wrb) 795bea50988SSathya Perla { 796bea50988SSathya Perla struct be_mcc_wrb *dest_wrb; 797bea50988SSathya Perla 798bea50988SSathya Perla if (use_mcc(adapter)) { 799bea50988SSathya Perla dest_wrb = wrb_from_mccq(adapter); 800bea50988SSathya Perla if (!dest_wrb) 801bea50988SSathya Perla return NULL; 802bea50988SSathya Perla } else { 803bea50988SSathya Perla dest_wrb = wrb_from_mbox(adapter); 804bea50988SSathya Perla } 805bea50988SSathya Perla 806bea50988SSathya Perla memcpy(dest_wrb, wrb, sizeof(*wrb)); 807bea50988SSathya Perla if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK)) 808bea50988SSathya Perla fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb)); 809bea50988SSathya Perla 810bea50988SSathya Perla return dest_wrb; 811bea50988SSathya Perla } 812bea50988SSathya Perla 813bea50988SSathya Perla /* Must be used only in process context */ 814bea50988SSathya Perla static int be_cmd_notify_wait(struct be_adapter *adapter, 815bea50988SSathya Perla struct be_mcc_wrb *wrb) 816bea50988SSathya Perla { 817bea50988SSathya Perla struct be_mcc_wrb *dest_wrb; 818bea50988SSathya Perla int status; 819bea50988SSathya Perla 820bea50988SSathya Perla status = be_cmd_lock(adapter); 821bea50988SSathya Perla if (status) 822bea50988SSathya Perla return status; 823bea50988SSathya Perla 824bea50988SSathya Perla dest_wrb = be_cmd_copy(adapter, wrb); 825bea50988SSathya Perla if (!dest_wrb) 826bea50988SSathya Perla return -EBUSY; 827bea50988SSathya Perla 828bea50988SSathya Perla if (use_mcc(adapter)) 829bea50988SSathya Perla status = be_mcc_notify_wait(adapter); 830bea50988SSathya Perla else 831bea50988SSathya Perla status = be_mbox_notify_wait(adapter); 832bea50988SSathya Perla 833bea50988SSathya Perla if (!status) 834bea50988SSathya Perla memcpy(wrb, dest_wrb, sizeof(*wrb)); 835bea50988SSathya Perla 836bea50988SSathya Perla be_cmd_unlock(adapter); 837bea50988SSathya Perla return status; 838bea50988SSathya Perla } 839bea50988SSathya Perla 8409aebddd1SJeff Kirsher /* Tell fw we're about to start firing cmds by writing a 8419aebddd1SJeff Kirsher * special pattern across the wrb hdr; uses mbox 8429aebddd1SJeff Kirsher */ 8439aebddd1SJeff Kirsher int be_cmd_fw_init(struct be_adapter *adapter) 8449aebddd1SJeff Kirsher { 8459aebddd1SJeff Kirsher u8 *wrb; 8469aebddd1SJeff Kirsher int status; 8479aebddd1SJeff Kirsher 848bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) 849bf99e50dSPadmanabh Ratnakar return 0; 850bf99e50dSPadmanabh Ratnakar 8519aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 8529aebddd1SJeff Kirsher return -1; 8539aebddd1SJeff Kirsher 8549aebddd1SJeff Kirsher wrb = (u8 *)wrb_from_mbox(adapter); 8559aebddd1SJeff Kirsher *wrb++ = 0xFF; 8569aebddd1SJeff Kirsher *wrb++ = 0x12; 8579aebddd1SJeff Kirsher *wrb++ = 0x34; 8589aebddd1SJeff Kirsher *wrb++ = 0xFF; 8599aebddd1SJeff Kirsher *wrb++ = 0xFF; 8609aebddd1SJeff Kirsher *wrb++ = 0x56; 8619aebddd1SJeff Kirsher *wrb++ = 0x78; 8629aebddd1SJeff Kirsher *wrb = 0xFF; 8639aebddd1SJeff Kirsher 8649aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 8659aebddd1SJeff Kirsher 8669aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 8679aebddd1SJeff Kirsher return status; 8689aebddd1SJeff Kirsher } 8699aebddd1SJeff Kirsher 8709aebddd1SJeff Kirsher /* Tell fw we're done with firing cmds by writing a 8719aebddd1SJeff Kirsher * special pattern across the wrb hdr; uses mbox 8729aebddd1SJeff Kirsher */ 8739aebddd1SJeff Kirsher int be_cmd_fw_clean(struct be_adapter *adapter) 8749aebddd1SJeff Kirsher { 8759aebddd1SJeff Kirsher u8 *wrb; 8769aebddd1SJeff Kirsher int status; 8779aebddd1SJeff Kirsher 878bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) 879bf99e50dSPadmanabh Ratnakar return 0; 880bf99e50dSPadmanabh Ratnakar 8819aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 8829aebddd1SJeff Kirsher return -1; 8839aebddd1SJeff Kirsher 8849aebddd1SJeff Kirsher wrb = (u8 *)wrb_from_mbox(adapter); 8859aebddd1SJeff Kirsher *wrb++ = 0xFF; 8869aebddd1SJeff Kirsher *wrb++ = 0xAA; 8879aebddd1SJeff Kirsher *wrb++ = 0xBB; 8889aebddd1SJeff Kirsher *wrb++ = 0xFF; 8899aebddd1SJeff Kirsher *wrb++ = 0xFF; 8909aebddd1SJeff Kirsher *wrb++ = 0xCC; 8919aebddd1SJeff Kirsher *wrb++ = 0xDD; 8929aebddd1SJeff Kirsher *wrb = 0xFF; 8939aebddd1SJeff Kirsher 8949aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 8959aebddd1SJeff Kirsher 8969aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 8979aebddd1SJeff Kirsher return status; 8989aebddd1SJeff Kirsher } 899bf99e50dSPadmanabh Ratnakar 900f2f781a7SSathya Perla int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo) 9019aebddd1SJeff Kirsher { 9029aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 9039aebddd1SJeff Kirsher struct be_cmd_req_eq_create *req; 904f2f781a7SSathya Perla struct be_dma_mem *q_mem = &eqo->q.dma_mem; 905f2f781a7SSathya Perla int status, ver = 0; 9069aebddd1SJeff Kirsher 9079aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 9089aebddd1SJeff Kirsher return -1; 9099aebddd1SJeff Kirsher 9109aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 9119aebddd1SJeff Kirsher req = embedded_payload(wrb); 9129aebddd1SJeff Kirsher 913106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 914a2cc4e0bSSathya Perla OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb, 915a2cc4e0bSSathya Perla NULL); 9169aebddd1SJeff Kirsher 917f2f781a7SSathya Perla /* Support for EQ_CREATEv2 available only SH-R onwards */ 918f2f781a7SSathya Perla if (!(BEx_chip(adapter) || lancer_chip(adapter))) 919f2f781a7SSathya Perla ver = 2; 920f2f781a7SSathya Perla 921f2f781a7SSathya Perla req->hdr.version = ver; 9229aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 9239aebddd1SJeff Kirsher 9249aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); 9259aebddd1SJeff Kirsher /* 4byte eqe*/ 9269aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); 9279aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, count, req->context, 928f2f781a7SSathya Perla __ilog2_u32(eqo->q.len / 256)); 9299aebddd1SJeff Kirsher be_dws_cpu_to_le(req->context, sizeof(req->context)); 9309aebddd1SJeff Kirsher 9319aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 9329aebddd1SJeff Kirsher 9339aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 9349aebddd1SJeff Kirsher if (!status) { 9359aebddd1SJeff Kirsher struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); 93603d28ffeSKalesh AP 937f2f781a7SSathya Perla eqo->q.id = le16_to_cpu(resp->eq_id); 938f2f781a7SSathya Perla eqo->msix_idx = 939f2f781a7SSathya Perla (ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx; 940f2f781a7SSathya Perla eqo->q.created = true; 9419aebddd1SJeff Kirsher } 9429aebddd1SJeff Kirsher 9439aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 9449aebddd1SJeff Kirsher return status; 9459aebddd1SJeff Kirsher } 9469aebddd1SJeff Kirsher 947f9449ab7SSathya Perla /* Use MCC */ 9489aebddd1SJeff Kirsher int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, 9495ee4979bSSathya Perla bool permanent, u32 if_handle, u32 pmac_id) 9509aebddd1SJeff Kirsher { 9519aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 9529aebddd1SJeff Kirsher struct be_cmd_req_mac_query *req; 9539aebddd1SJeff Kirsher int status; 9549aebddd1SJeff Kirsher 955f9449ab7SSathya Perla spin_lock_bh(&adapter->mcc_lock); 9569aebddd1SJeff Kirsher 957f9449ab7SSathya Perla wrb = wrb_from_mccq(adapter); 958f9449ab7SSathya Perla if (!wrb) { 959f9449ab7SSathya Perla status = -EBUSY; 960f9449ab7SSathya Perla goto err; 961f9449ab7SSathya Perla } 9629aebddd1SJeff Kirsher req = embedded_payload(wrb); 9639aebddd1SJeff Kirsher 964106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 965a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb, 966a2cc4e0bSSathya Perla NULL); 9675ee4979bSSathya Perla req->type = MAC_ADDRESS_TYPE_NETWORK; 9689aebddd1SJeff Kirsher if (permanent) { 9699aebddd1SJeff Kirsher req->permanent = 1; 9709aebddd1SJeff Kirsher } else { 9719aebddd1SJeff Kirsher req->if_id = cpu_to_le16((u16)if_handle); 972590c391dSPadmanabh Ratnakar req->pmac_id = cpu_to_le32(pmac_id); 9739aebddd1SJeff Kirsher req->permanent = 0; 9749aebddd1SJeff Kirsher } 9759aebddd1SJeff Kirsher 976f9449ab7SSathya Perla status = be_mcc_notify_wait(adapter); 9779aebddd1SJeff Kirsher if (!status) { 9789aebddd1SJeff Kirsher struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); 97903d28ffeSKalesh AP 9809aebddd1SJeff Kirsher memcpy(mac_addr, resp->mac.addr, ETH_ALEN); 9819aebddd1SJeff Kirsher } 9829aebddd1SJeff Kirsher 983f9449ab7SSathya Perla err: 984f9449ab7SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 9859aebddd1SJeff Kirsher return status; 9869aebddd1SJeff Kirsher } 9879aebddd1SJeff Kirsher 9889aebddd1SJeff Kirsher /* Uses synchronous MCCQ */ 9899aebddd1SJeff Kirsher int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, 9909aebddd1SJeff Kirsher u32 if_id, u32 *pmac_id, u32 domain) 9919aebddd1SJeff Kirsher { 9929aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 9939aebddd1SJeff Kirsher struct be_cmd_req_pmac_add *req; 9949aebddd1SJeff Kirsher int status; 9959aebddd1SJeff Kirsher 9969aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 9979aebddd1SJeff Kirsher 9989aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 9999aebddd1SJeff Kirsher if (!wrb) { 10009aebddd1SJeff Kirsher status = -EBUSY; 10019aebddd1SJeff Kirsher goto err; 10029aebddd1SJeff Kirsher } 10039aebddd1SJeff Kirsher req = embedded_payload(wrb); 10049aebddd1SJeff Kirsher 1005106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1006a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb, 1007a2cc4e0bSSathya Perla NULL); 10089aebddd1SJeff Kirsher 10099aebddd1SJeff Kirsher req->hdr.domain = domain; 10109aebddd1SJeff Kirsher req->if_id = cpu_to_le32(if_id); 10119aebddd1SJeff Kirsher memcpy(req->mac_address, mac_addr, ETH_ALEN); 10129aebddd1SJeff Kirsher 10139aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 10149aebddd1SJeff Kirsher if (!status) { 10159aebddd1SJeff Kirsher struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb); 101603d28ffeSKalesh AP 10179aebddd1SJeff Kirsher *pmac_id = le32_to_cpu(resp->pmac_id); 10189aebddd1SJeff Kirsher } 10199aebddd1SJeff Kirsher 10209aebddd1SJeff Kirsher err: 10219aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 1022e3a7ae2cSSomnath Kotur 1023e3a7ae2cSSomnath Kotur if (status == MCC_STATUS_UNAUTHORIZED_REQUEST) 1024e3a7ae2cSSomnath Kotur status = -EPERM; 1025e3a7ae2cSSomnath Kotur 10269aebddd1SJeff Kirsher return status; 10279aebddd1SJeff Kirsher } 10289aebddd1SJeff Kirsher 10299aebddd1SJeff Kirsher /* Uses synchronous MCCQ */ 103030128031SSathya Perla int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) 10319aebddd1SJeff Kirsher { 10329aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10339aebddd1SJeff Kirsher struct be_cmd_req_pmac_del *req; 10349aebddd1SJeff Kirsher int status; 10359aebddd1SJeff Kirsher 103630128031SSathya Perla if (pmac_id == -1) 103730128031SSathya Perla return 0; 103830128031SSathya Perla 10399aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 10409aebddd1SJeff Kirsher 10419aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 10429aebddd1SJeff Kirsher if (!wrb) { 10439aebddd1SJeff Kirsher status = -EBUSY; 10449aebddd1SJeff Kirsher goto err; 10459aebddd1SJeff Kirsher } 10469aebddd1SJeff Kirsher req = embedded_payload(wrb); 10479aebddd1SJeff Kirsher 1048106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1049cd3307aaSKalesh AP OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req), 1050cd3307aaSKalesh AP wrb, NULL); 10519aebddd1SJeff Kirsher 10529aebddd1SJeff Kirsher req->hdr.domain = dom; 10539aebddd1SJeff Kirsher req->if_id = cpu_to_le32(if_id); 10549aebddd1SJeff Kirsher req->pmac_id = cpu_to_le32(pmac_id); 10559aebddd1SJeff Kirsher 10569aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 10579aebddd1SJeff Kirsher 10589aebddd1SJeff Kirsher err: 10599aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 10609aebddd1SJeff Kirsher return status; 10619aebddd1SJeff Kirsher } 10629aebddd1SJeff Kirsher 10639aebddd1SJeff Kirsher /* Uses Mbox */ 106410ef9ab4SSathya Perla int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, 106510ef9ab4SSathya Perla struct be_queue_info *eq, bool no_delay, int coalesce_wm) 10669aebddd1SJeff Kirsher { 10679aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10689aebddd1SJeff Kirsher struct be_cmd_req_cq_create *req; 10699aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &cq->dma_mem; 10709aebddd1SJeff Kirsher void *ctxt; 10719aebddd1SJeff Kirsher int status; 10729aebddd1SJeff Kirsher 10739aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 10749aebddd1SJeff Kirsher return -1; 10759aebddd1SJeff Kirsher 10769aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 10779aebddd1SJeff Kirsher req = embedded_payload(wrb); 10789aebddd1SJeff Kirsher ctxt = &req->context; 10799aebddd1SJeff Kirsher 1080106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1081a2cc4e0bSSathya Perla OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb, 1082a2cc4e0bSSathya Perla NULL); 10839aebddd1SJeff Kirsher 10849aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 1085bbdc42f8SAjit Khaparde 1086bbdc42f8SAjit Khaparde if (BEx_chip(adapter)) { 10879aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt, 10889aebddd1SJeff Kirsher coalesce_wm); 10899aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, nodelay, 10909aebddd1SJeff Kirsher ctxt, no_delay); 10919aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt, 10929aebddd1SJeff Kirsher __ilog2_u32(cq->len / 256)); 10939aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1); 10949aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1); 10959aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id); 1096bbdc42f8SAjit Khaparde } else { 1097bbdc42f8SAjit Khaparde req->hdr.version = 2; 1098bbdc42f8SAjit Khaparde req->page_size = 1; /* 1 for 4K */ 109909e83a9dSAjit Khaparde 110009e83a9dSAjit Khaparde /* coalesce-wm field in this cmd is not relevant to Lancer. 110109e83a9dSAjit Khaparde * Lancer uses COMMON_MODIFY_CQ to set this field 110209e83a9dSAjit Khaparde */ 110309e83a9dSAjit Khaparde if (!lancer_chip(adapter)) 110409e83a9dSAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm, 110509e83a9dSAjit Khaparde ctxt, coalesce_wm); 1106bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt, 1107bbdc42f8SAjit Khaparde no_delay); 1108bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt, 1109bbdc42f8SAjit Khaparde __ilog2_u32(cq->len / 256)); 1110bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1); 1111a2cc4e0bSSathya Perla AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1); 1112a2cc4e0bSSathya Perla AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id); 11139aebddd1SJeff Kirsher } 11149aebddd1SJeff Kirsher 11159aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 11169aebddd1SJeff Kirsher 11179aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 11189aebddd1SJeff Kirsher 11199aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 11209aebddd1SJeff Kirsher if (!status) { 11219aebddd1SJeff Kirsher struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); 112203d28ffeSKalesh AP 11239aebddd1SJeff Kirsher cq->id = le16_to_cpu(resp->cq_id); 11249aebddd1SJeff Kirsher cq->created = true; 11259aebddd1SJeff Kirsher } 11269aebddd1SJeff Kirsher 11279aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 11289aebddd1SJeff Kirsher 11299aebddd1SJeff Kirsher return status; 11309aebddd1SJeff Kirsher } 11319aebddd1SJeff Kirsher 11329aebddd1SJeff Kirsher static u32 be_encoded_q_len(int q_len) 11339aebddd1SJeff Kirsher { 11349aebddd1SJeff Kirsher u32 len_encoded = fls(q_len); /* log2(len) + 1 */ 113503d28ffeSKalesh AP 11369aebddd1SJeff Kirsher if (len_encoded == 16) 11379aebddd1SJeff Kirsher len_encoded = 0; 11389aebddd1SJeff Kirsher return len_encoded; 11399aebddd1SJeff Kirsher } 11409aebddd1SJeff Kirsher 11414188e7dfSJingoo Han static int be_cmd_mccq_ext_create(struct be_adapter *adapter, 11429aebddd1SJeff Kirsher struct be_queue_info *mccq, 11439aebddd1SJeff Kirsher struct be_queue_info *cq) 11449aebddd1SJeff Kirsher { 11459aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 11469aebddd1SJeff Kirsher struct be_cmd_req_mcc_ext_create *req; 11479aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &mccq->dma_mem; 11489aebddd1SJeff Kirsher void *ctxt; 11499aebddd1SJeff Kirsher int status; 11509aebddd1SJeff Kirsher 11519aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 11529aebddd1SJeff Kirsher return -1; 11539aebddd1SJeff Kirsher 11549aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 11559aebddd1SJeff Kirsher req = embedded_payload(wrb); 11569aebddd1SJeff Kirsher ctxt = &req->context; 11579aebddd1SJeff Kirsher 1158106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1159a2cc4e0bSSathya Perla OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb, 1160a2cc4e0bSSathya Perla NULL); 11619aebddd1SJeff Kirsher 11629aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 1163666d39c7SVasundhara Volam if (BEx_chip(adapter)) { 11649aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); 11659aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, 11669aebddd1SJeff Kirsher be_encoded_q_len(mccq->len)); 11679aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); 1168666d39c7SVasundhara Volam } else { 1169666d39c7SVasundhara Volam req->hdr.version = 1; 1170666d39c7SVasundhara Volam req->cq_id = cpu_to_le16(cq->id); 1171666d39c7SVasundhara Volam 1172666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt, 1173666d39c7SVasundhara Volam be_encoded_q_len(mccq->len)); 1174666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1); 1175666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id, 1176666d39c7SVasundhara Volam ctxt, cq->id); 1177666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid, 1178666d39c7SVasundhara Volam ctxt, 1); 11799aebddd1SJeff Kirsher } 11809aebddd1SJeff Kirsher 118121252377SVasundhara Volam /* Subscribe to Link State, Sliport Event and Group 5 Events 118221252377SVasundhara Volam * (bits 1, 5 and 17 set) 118321252377SVasundhara Volam */ 118421252377SVasundhara Volam req->async_event_bitmap[0] = 118521252377SVasundhara Volam cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) | 118621252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_GRP_5) | 118721252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_QNQ) | 118821252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_SLIPORT)); 118921252377SVasundhara Volam 11909aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 11919aebddd1SJeff Kirsher 11929aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 11939aebddd1SJeff Kirsher 11949aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 11959aebddd1SJeff Kirsher if (!status) { 11969aebddd1SJeff Kirsher struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); 119703d28ffeSKalesh AP 11989aebddd1SJeff Kirsher mccq->id = le16_to_cpu(resp->id); 11999aebddd1SJeff Kirsher mccq->created = true; 12009aebddd1SJeff Kirsher } 12019aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 12029aebddd1SJeff Kirsher 12039aebddd1SJeff Kirsher return status; 12049aebddd1SJeff Kirsher } 12059aebddd1SJeff Kirsher 12064188e7dfSJingoo Han static int be_cmd_mccq_org_create(struct be_adapter *adapter, 12079aebddd1SJeff Kirsher struct be_queue_info *mccq, 12089aebddd1SJeff Kirsher struct be_queue_info *cq) 12099aebddd1SJeff Kirsher { 12109aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 12119aebddd1SJeff Kirsher struct be_cmd_req_mcc_create *req; 12129aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &mccq->dma_mem; 12139aebddd1SJeff Kirsher void *ctxt; 12149aebddd1SJeff Kirsher int status; 12159aebddd1SJeff Kirsher 12169aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 12179aebddd1SJeff Kirsher return -1; 12189aebddd1SJeff Kirsher 12199aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 12209aebddd1SJeff Kirsher req = embedded_payload(wrb); 12219aebddd1SJeff Kirsher ctxt = &req->context; 12229aebddd1SJeff Kirsher 1223106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1224a2cc4e0bSSathya Perla OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb, 1225a2cc4e0bSSathya Perla NULL); 12269aebddd1SJeff Kirsher 12279aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 12289aebddd1SJeff Kirsher 12299aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); 12309aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, 12319aebddd1SJeff Kirsher be_encoded_q_len(mccq->len)); 12329aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); 12339aebddd1SJeff Kirsher 12349aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 12359aebddd1SJeff Kirsher 12369aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 12379aebddd1SJeff Kirsher 12389aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 12399aebddd1SJeff Kirsher if (!status) { 12409aebddd1SJeff Kirsher struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); 124103d28ffeSKalesh AP 12429aebddd1SJeff Kirsher mccq->id = le16_to_cpu(resp->id); 12439aebddd1SJeff Kirsher mccq->created = true; 12449aebddd1SJeff Kirsher } 12459aebddd1SJeff Kirsher 12469aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 12479aebddd1SJeff Kirsher return status; 12489aebddd1SJeff Kirsher } 12499aebddd1SJeff Kirsher 12509aebddd1SJeff Kirsher int be_cmd_mccq_create(struct be_adapter *adapter, 1251a2cc4e0bSSathya Perla struct be_queue_info *mccq, struct be_queue_info *cq) 12529aebddd1SJeff Kirsher { 12539aebddd1SJeff Kirsher int status; 12549aebddd1SJeff Kirsher 12559aebddd1SJeff Kirsher status = be_cmd_mccq_ext_create(adapter, mccq, cq); 1256666d39c7SVasundhara Volam if (status && BEx_chip(adapter)) { 12579aebddd1SJeff Kirsher dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 " 12589aebddd1SJeff Kirsher "or newer to avoid conflicting priorities between NIC " 12599aebddd1SJeff Kirsher "and FCoE traffic"); 12609aebddd1SJeff Kirsher status = be_cmd_mccq_org_create(adapter, mccq, cq); 12619aebddd1SJeff Kirsher } 12629aebddd1SJeff Kirsher return status; 12639aebddd1SJeff Kirsher } 12649aebddd1SJeff Kirsher 126594d73aaaSVasundhara Volam int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) 12669aebddd1SJeff Kirsher { 12677707133cSSathya Perla struct be_mcc_wrb wrb = {0}; 12689aebddd1SJeff Kirsher struct be_cmd_req_eth_tx_create *req; 126994d73aaaSVasundhara Volam struct be_queue_info *txq = &txo->q; 127094d73aaaSVasundhara Volam struct be_queue_info *cq = &txo->cq; 12719aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &txq->dma_mem; 127294d73aaaSVasundhara Volam int status, ver = 0; 12739aebddd1SJeff Kirsher 12747707133cSSathya Perla req = embedded_payload(&wrb); 1275106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 12767707133cSSathya Perla OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL); 12779aebddd1SJeff Kirsher 12789aebddd1SJeff Kirsher if (lancer_chip(adapter)) { 12799aebddd1SJeff Kirsher req->hdr.version = 1; 128094d73aaaSVasundhara Volam } else if (BEx_chip(adapter)) { 128194d73aaaSVasundhara Volam if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) 128294d73aaaSVasundhara Volam req->hdr.version = 2; 128394d73aaaSVasundhara Volam } else { /* For SH */ 128494d73aaaSVasundhara Volam req->hdr.version = 2; 12859aebddd1SJeff Kirsher } 12869aebddd1SJeff Kirsher 128781b02655SVasundhara Volam if (req->hdr.version > 0) 128881b02655SVasundhara Volam req->if_id = cpu_to_le16(adapter->if_handle); 12899aebddd1SJeff Kirsher req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); 12909aebddd1SJeff Kirsher req->ulp_num = BE_ULP1_NUM; 12919aebddd1SJeff Kirsher req->type = BE_ETH_TX_RING_TYPE_STANDARD; 129294d73aaaSVasundhara Volam req->cq_id = cpu_to_le16(cq->id); 129394d73aaaSVasundhara Volam req->queue_size = be_encoded_q_len(txq->len); 12949aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 129594d73aaaSVasundhara Volam ver = req->hdr.version; 129694d73aaaSVasundhara Volam 12977707133cSSathya Perla status = be_cmd_notify_wait(adapter, &wrb); 12989aebddd1SJeff Kirsher if (!status) { 12997707133cSSathya Perla struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb); 130003d28ffeSKalesh AP 13019aebddd1SJeff Kirsher txq->id = le16_to_cpu(resp->cid); 130294d73aaaSVasundhara Volam if (ver == 2) 130394d73aaaSVasundhara Volam txo->db_offset = le32_to_cpu(resp->db_offset); 130494d73aaaSVasundhara Volam else 130594d73aaaSVasundhara Volam txo->db_offset = DB_TXULP1_OFFSET; 13069aebddd1SJeff Kirsher txq->created = true; 13079aebddd1SJeff Kirsher } 13089aebddd1SJeff Kirsher 13099aebddd1SJeff Kirsher return status; 13109aebddd1SJeff Kirsher } 13119aebddd1SJeff Kirsher 13129aebddd1SJeff Kirsher /* Uses MCC */ 13139aebddd1SJeff Kirsher int be_cmd_rxq_create(struct be_adapter *adapter, 13149aebddd1SJeff Kirsher struct be_queue_info *rxq, u16 cq_id, u16 frag_size, 131510ef9ab4SSathya Perla u32 if_id, u32 rss, u8 *rss_id) 13169aebddd1SJeff Kirsher { 13179aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 13189aebddd1SJeff Kirsher struct be_cmd_req_eth_rx_create *req; 13199aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &rxq->dma_mem; 13209aebddd1SJeff Kirsher int status; 13219aebddd1SJeff Kirsher 13229aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 13239aebddd1SJeff Kirsher 13249aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 13259aebddd1SJeff Kirsher if (!wrb) { 13269aebddd1SJeff Kirsher status = -EBUSY; 13279aebddd1SJeff Kirsher goto err; 13289aebddd1SJeff Kirsher } 13299aebddd1SJeff Kirsher req = embedded_payload(wrb); 13309aebddd1SJeff Kirsher 1331106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1332106df1e3SSomnath Kotur OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL); 13339aebddd1SJeff Kirsher 13349aebddd1SJeff Kirsher req->cq_id = cpu_to_le16(cq_id); 13359aebddd1SJeff Kirsher req->frag_size = fls(frag_size) - 1; 13369aebddd1SJeff Kirsher req->num_pages = 2; 13379aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 13389aebddd1SJeff Kirsher req->interface_id = cpu_to_le32(if_id); 133910ef9ab4SSathya Perla req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE); 13409aebddd1SJeff Kirsher req->rss_queue = cpu_to_le32(rss); 13419aebddd1SJeff Kirsher 13429aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 13439aebddd1SJeff Kirsher if (!status) { 13449aebddd1SJeff Kirsher struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); 134503d28ffeSKalesh AP 13469aebddd1SJeff Kirsher rxq->id = le16_to_cpu(resp->id); 13479aebddd1SJeff Kirsher rxq->created = true; 13489aebddd1SJeff Kirsher *rss_id = resp->rss_id; 13499aebddd1SJeff Kirsher } 13509aebddd1SJeff Kirsher 13519aebddd1SJeff Kirsher err: 13529aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 13539aebddd1SJeff Kirsher return status; 13549aebddd1SJeff Kirsher } 13559aebddd1SJeff Kirsher 13569aebddd1SJeff Kirsher /* Generic destroyer function for all types of queues 13579aebddd1SJeff Kirsher * Uses Mbox 13589aebddd1SJeff Kirsher */ 13599aebddd1SJeff Kirsher int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, 13609aebddd1SJeff Kirsher int queue_type) 13619aebddd1SJeff Kirsher { 13629aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 13639aebddd1SJeff Kirsher struct be_cmd_req_q_destroy *req; 13649aebddd1SJeff Kirsher u8 subsys = 0, opcode = 0; 13659aebddd1SJeff Kirsher int status; 13669aebddd1SJeff Kirsher 13679aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 13689aebddd1SJeff Kirsher return -1; 13699aebddd1SJeff Kirsher 13709aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 13719aebddd1SJeff Kirsher req = embedded_payload(wrb); 13729aebddd1SJeff Kirsher 13739aebddd1SJeff Kirsher switch (queue_type) { 13749aebddd1SJeff Kirsher case QTYPE_EQ: 13759aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 13769aebddd1SJeff Kirsher opcode = OPCODE_COMMON_EQ_DESTROY; 13779aebddd1SJeff Kirsher break; 13789aebddd1SJeff Kirsher case QTYPE_CQ: 13799aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 13809aebddd1SJeff Kirsher opcode = OPCODE_COMMON_CQ_DESTROY; 13819aebddd1SJeff Kirsher break; 13829aebddd1SJeff Kirsher case QTYPE_TXQ: 13839aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_ETH; 13849aebddd1SJeff Kirsher opcode = OPCODE_ETH_TX_DESTROY; 13859aebddd1SJeff Kirsher break; 13869aebddd1SJeff Kirsher case QTYPE_RXQ: 13879aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_ETH; 13889aebddd1SJeff Kirsher opcode = OPCODE_ETH_RX_DESTROY; 13899aebddd1SJeff Kirsher break; 13909aebddd1SJeff Kirsher case QTYPE_MCCQ: 13919aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 13929aebddd1SJeff Kirsher opcode = OPCODE_COMMON_MCC_DESTROY; 13939aebddd1SJeff Kirsher break; 13949aebddd1SJeff Kirsher default: 13959aebddd1SJeff Kirsher BUG(); 13969aebddd1SJeff Kirsher } 13979aebddd1SJeff Kirsher 1398106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb, 1399106df1e3SSomnath Kotur NULL); 14009aebddd1SJeff Kirsher req->id = cpu_to_le16(q->id); 14019aebddd1SJeff Kirsher 14029aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 14039aebddd1SJeff Kirsher q->created = false; 14049aebddd1SJeff Kirsher 14059aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 14069aebddd1SJeff Kirsher return status; 14079aebddd1SJeff Kirsher } 14089aebddd1SJeff Kirsher 14099aebddd1SJeff Kirsher /* Uses MCC */ 14109aebddd1SJeff Kirsher int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) 14119aebddd1SJeff Kirsher { 14129aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 14139aebddd1SJeff Kirsher struct be_cmd_req_q_destroy *req; 14149aebddd1SJeff Kirsher int status; 14159aebddd1SJeff Kirsher 14169aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 14179aebddd1SJeff Kirsher 14189aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 14199aebddd1SJeff Kirsher if (!wrb) { 14209aebddd1SJeff Kirsher status = -EBUSY; 14219aebddd1SJeff Kirsher goto err; 14229aebddd1SJeff Kirsher } 14239aebddd1SJeff Kirsher req = embedded_payload(wrb); 14249aebddd1SJeff Kirsher 1425106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1426106df1e3SSomnath Kotur OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL); 14279aebddd1SJeff Kirsher req->id = cpu_to_le16(q->id); 14289aebddd1SJeff Kirsher 14299aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 14309aebddd1SJeff Kirsher q->created = false; 14319aebddd1SJeff Kirsher 14329aebddd1SJeff Kirsher err: 14339aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 14349aebddd1SJeff Kirsher return status; 14359aebddd1SJeff Kirsher } 14369aebddd1SJeff Kirsher 14379aebddd1SJeff Kirsher /* Create an rx filtering policy configuration on an i/f 1438bea50988SSathya Perla * Will use MBOX only if MCCQ has not been created. 14399aebddd1SJeff Kirsher */ 14409aebddd1SJeff Kirsher int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, 14411578e777SPadmanabh Ratnakar u32 *if_handle, u32 domain) 14429aebddd1SJeff Kirsher { 1443bea50988SSathya Perla struct be_mcc_wrb wrb = {0}; 14449aebddd1SJeff Kirsher struct be_cmd_req_if_create *req; 14459aebddd1SJeff Kirsher int status; 14469aebddd1SJeff Kirsher 1447bea50988SSathya Perla req = embedded_payload(&wrb); 1448106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1449a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_INTERFACE_CREATE, 1450a2cc4e0bSSathya Perla sizeof(*req), &wrb, NULL); 14519aebddd1SJeff Kirsher req->hdr.domain = domain; 14529aebddd1SJeff Kirsher req->capability_flags = cpu_to_le32(cap_flags); 14539aebddd1SJeff Kirsher req->enable_flags = cpu_to_le32(en_flags); 1454f9449ab7SSathya Perla req->pmac_invalid = true; 14559aebddd1SJeff Kirsher 1456bea50988SSathya Perla status = be_cmd_notify_wait(adapter, &wrb); 14579aebddd1SJeff Kirsher if (!status) { 1458bea50988SSathya Perla struct be_cmd_resp_if_create *resp = embedded_payload(&wrb); 145903d28ffeSKalesh AP 14609aebddd1SJeff Kirsher *if_handle = le32_to_cpu(resp->interface_id); 1461b5bb9776SSathya Perla 1462b5bb9776SSathya Perla /* Hack to retrieve VF's pmac-id on BE3 */ 146318c57c74SKalesh AP if (BE3_chip(adapter) && be_virtfn(adapter)) 1464b5bb9776SSathya Perla adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id); 14659aebddd1SJeff Kirsher } 14669aebddd1SJeff Kirsher return status; 14679aebddd1SJeff Kirsher } 14689aebddd1SJeff Kirsher 1469f9449ab7SSathya Perla /* Uses MCCQ */ 147030128031SSathya Perla int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain) 14719aebddd1SJeff Kirsher { 14729aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 14739aebddd1SJeff Kirsher struct be_cmd_req_if_destroy *req; 14749aebddd1SJeff Kirsher int status; 14759aebddd1SJeff Kirsher 147630128031SSathya Perla if (interface_id == -1) 1477f9449ab7SSathya Perla return 0; 14789aebddd1SJeff Kirsher 1479f9449ab7SSathya Perla spin_lock_bh(&adapter->mcc_lock); 1480f9449ab7SSathya Perla 1481f9449ab7SSathya Perla wrb = wrb_from_mccq(adapter); 1482f9449ab7SSathya Perla if (!wrb) { 1483f9449ab7SSathya Perla status = -EBUSY; 1484f9449ab7SSathya Perla goto err; 1485f9449ab7SSathya Perla } 14869aebddd1SJeff Kirsher req = embedded_payload(wrb); 14879aebddd1SJeff Kirsher 1488106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1489a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_INTERFACE_DESTROY, 1490a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 14919aebddd1SJeff Kirsher req->hdr.domain = domain; 14929aebddd1SJeff Kirsher req->interface_id = cpu_to_le32(interface_id); 14939aebddd1SJeff Kirsher 1494f9449ab7SSathya Perla status = be_mcc_notify_wait(adapter); 1495f9449ab7SSathya Perla err: 1496f9449ab7SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 14979aebddd1SJeff Kirsher return status; 14989aebddd1SJeff Kirsher } 14999aebddd1SJeff Kirsher 15009aebddd1SJeff Kirsher /* Get stats is a non embedded command: the request is not embedded inside 15019aebddd1SJeff Kirsher * WRB but is a separate dma memory block 15029aebddd1SJeff Kirsher * Uses asynchronous MCC 15039aebddd1SJeff Kirsher */ 15049aebddd1SJeff Kirsher int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) 15059aebddd1SJeff Kirsher { 15069aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 15079aebddd1SJeff Kirsher struct be_cmd_req_hdr *hdr; 15089aebddd1SJeff Kirsher int status = 0; 15099aebddd1SJeff Kirsher 15109aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 15119aebddd1SJeff Kirsher 15129aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 15139aebddd1SJeff Kirsher if (!wrb) { 15149aebddd1SJeff Kirsher status = -EBUSY; 15159aebddd1SJeff Kirsher goto err; 15169aebddd1SJeff Kirsher } 15179aebddd1SJeff Kirsher hdr = nonemb_cmd->va; 15189aebddd1SJeff Kirsher 1519106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH, 1520a2cc4e0bSSathya Perla OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, 1521a2cc4e0bSSathya Perla nonemb_cmd); 15229aebddd1SJeff Kirsher 1523ca34fe38SSathya Perla /* version 1 of the cmd is not supported only by BE2 */ 152461000861SAjit Khaparde if (BE2_chip(adapter)) 152561000861SAjit Khaparde hdr->version = 0; 152661000861SAjit Khaparde if (BE3_chip(adapter) || lancer_chip(adapter)) 15279aebddd1SJeff Kirsher hdr->version = 1; 152861000861SAjit Khaparde else 152961000861SAjit Khaparde hdr->version = 2; 15309aebddd1SJeff Kirsher 15319aebddd1SJeff Kirsher be_mcc_notify(adapter); 15329aebddd1SJeff Kirsher adapter->stats_cmd_sent = true; 15339aebddd1SJeff Kirsher 15349aebddd1SJeff Kirsher err: 15359aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 15369aebddd1SJeff Kirsher return status; 15379aebddd1SJeff Kirsher } 15389aebddd1SJeff Kirsher 15399aebddd1SJeff Kirsher /* Lancer Stats */ 15409aebddd1SJeff Kirsher int lancer_cmd_get_pport_stats(struct be_adapter *adapter, 15419aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 15429aebddd1SJeff Kirsher { 15439aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 15449aebddd1SJeff Kirsher struct lancer_cmd_req_pport_stats *req; 15459aebddd1SJeff Kirsher int status = 0; 15469aebddd1SJeff Kirsher 1547f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS, 1548f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH)) 1549f25b119cSPadmanabh Ratnakar return -EPERM; 1550f25b119cSPadmanabh Ratnakar 15519aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 15529aebddd1SJeff Kirsher 15539aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 15549aebddd1SJeff Kirsher if (!wrb) { 15559aebddd1SJeff Kirsher status = -EBUSY; 15569aebddd1SJeff Kirsher goto err; 15579aebddd1SJeff Kirsher } 15589aebddd1SJeff Kirsher req = nonemb_cmd->va; 15599aebddd1SJeff Kirsher 1560106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1561a2cc4e0bSSathya Perla OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, 1562a2cc4e0bSSathya Perla wrb, nonemb_cmd); 15639aebddd1SJeff Kirsher 1564d51ebd33SPadmanabh Ratnakar req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num); 15659aebddd1SJeff Kirsher req->cmd_params.params.reset_stats = 0; 15669aebddd1SJeff Kirsher 15679aebddd1SJeff Kirsher be_mcc_notify(adapter); 15689aebddd1SJeff Kirsher adapter->stats_cmd_sent = true; 15699aebddd1SJeff Kirsher 15709aebddd1SJeff Kirsher err: 15719aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 15729aebddd1SJeff Kirsher return status; 15739aebddd1SJeff Kirsher } 15749aebddd1SJeff Kirsher 1575323ff71eSSathya Perla static int be_mac_to_link_speed(int mac_speed) 1576323ff71eSSathya Perla { 1577323ff71eSSathya Perla switch (mac_speed) { 1578323ff71eSSathya Perla case PHY_LINK_SPEED_ZERO: 1579323ff71eSSathya Perla return 0; 1580323ff71eSSathya Perla case PHY_LINK_SPEED_10MBPS: 1581323ff71eSSathya Perla return 10; 1582323ff71eSSathya Perla case PHY_LINK_SPEED_100MBPS: 1583323ff71eSSathya Perla return 100; 1584323ff71eSSathya Perla case PHY_LINK_SPEED_1GBPS: 1585323ff71eSSathya Perla return 1000; 1586323ff71eSSathya Perla case PHY_LINK_SPEED_10GBPS: 1587323ff71eSSathya Perla return 10000; 1588b971f847SVasundhara Volam case PHY_LINK_SPEED_20GBPS: 1589b971f847SVasundhara Volam return 20000; 1590b971f847SVasundhara Volam case PHY_LINK_SPEED_25GBPS: 1591b971f847SVasundhara Volam return 25000; 1592b971f847SVasundhara Volam case PHY_LINK_SPEED_40GBPS: 1593b971f847SVasundhara Volam return 40000; 1594323ff71eSSathya Perla } 1595323ff71eSSathya Perla return 0; 1596323ff71eSSathya Perla } 1597323ff71eSSathya Perla 1598323ff71eSSathya Perla /* Uses synchronous mcc 1599323ff71eSSathya Perla * Returns link_speed in Mbps 1600323ff71eSSathya Perla */ 1601323ff71eSSathya Perla int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, 1602323ff71eSSathya Perla u8 *link_status, u32 dom) 16039aebddd1SJeff Kirsher { 16049aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 16059aebddd1SJeff Kirsher struct be_cmd_req_link_status *req; 16069aebddd1SJeff Kirsher int status; 16079aebddd1SJeff Kirsher 16089aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 16099aebddd1SJeff Kirsher 1610b236916aSAjit Khaparde if (link_status) 1611b236916aSAjit Khaparde *link_status = LINK_DOWN; 1612b236916aSAjit Khaparde 16139aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 16149aebddd1SJeff Kirsher if (!wrb) { 16159aebddd1SJeff Kirsher status = -EBUSY; 16169aebddd1SJeff Kirsher goto err; 16179aebddd1SJeff Kirsher } 16189aebddd1SJeff Kirsher req = embedded_payload(wrb); 16199aebddd1SJeff Kirsher 162057cd80d4SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1621a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, 1622a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 162357cd80d4SPadmanabh Ratnakar 1624ca34fe38SSathya Perla /* version 1 of the cmd is not supported only by BE2 */ 1625ca34fe38SSathya Perla if (!BE2_chip(adapter)) 1626daad6167SPadmanabh Ratnakar req->hdr.version = 1; 1627daad6167SPadmanabh Ratnakar 162857cd80d4SPadmanabh Ratnakar req->hdr.domain = dom; 16299aebddd1SJeff Kirsher 16309aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 16319aebddd1SJeff Kirsher if (!status) { 16329aebddd1SJeff Kirsher struct be_cmd_resp_link_status *resp = embedded_payload(wrb); 163303d28ffeSKalesh AP 1634323ff71eSSathya Perla if (link_speed) { 1635323ff71eSSathya Perla *link_speed = resp->link_speed ? 1636323ff71eSSathya Perla le16_to_cpu(resp->link_speed) * 10 : 1637323ff71eSSathya Perla be_mac_to_link_speed(resp->mac_speed); 1638323ff71eSSathya Perla 1639323ff71eSSathya Perla if (!resp->logical_link_status) 1640323ff71eSSathya Perla *link_speed = 0; 16419aebddd1SJeff Kirsher } 1642b236916aSAjit Khaparde if (link_status) 1643b236916aSAjit Khaparde *link_status = resp->logical_link_status; 16449aebddd1SJeff Kirsher } 16459aebddd1SJeff Kirsher 16469aebddd1SJeff Kirsher err: 16479aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 16489aebddd1SJeff Kirsher return status; 16499aebddd1SJeff Kirsher } 16509aebddd1SJeff Kirsher 16519aebddd1SJeff Kirsher /* Uses synchronous mcc */ 16529aebddd1SJeff Kirsher int be_cmd_get_die_temperature(struct be_adapter *adapter) 16539aebddd1SJeff Kirsher { 16549aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 16559aebddd1SJeff Kirsher struct be_cmd_req_get_cntl_addnl_attribs *req; 1656117affe3SVasundhara Volam int status = 0; 16579aebddd1SJeff Kirsher 16589aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 16599aebddd1SJeff Kirsher 16609aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 16619aebddd1SJeff Kirsher if (!wrb) { 16629aebddd1SJeff Kirsher status = -EBUSY; 16639aebddd1SJeff Kirsher goto err; 16649aebddd1SJeff Kirsher } 16659aebddd1SJeff Kirsher req = embedded_payload(wrb); 16669aebddd1SJeff Kirsher 1667106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1668a2cc4e0bSSathya Perla OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, 1669a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 16709aebddd1SJeff Kirsher 16713de09455SSomnath Kotur be_mcc_notify(adapter); 16729aebddd1SJeff Kirsher 16739aebddd1SJeff Kirsher err: 16749aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 16759aebddd1SJeff Kirsher return status; 16769aebddd1SJeff Kirsher } 16779aebddd1SJeff Kirsher 16789aebddd1SJeff Kirsher /* Uses synchronous mcc */ 16799aebddd1SJeff Kirsher int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size) 16809aebddd1SJeff Kirsher { 16819aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 16829aebddd1SJeff Kirsher struct be_cmd_req_get_fat *req; 16839aebddd1SJeff Kirsher int status; 16849aebddd1SJeff Kirsher 16859aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 16869aebddd1SJeff Kirsher 16879aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 16889aebddd1SJeff Kirsher if (!wrb) { 16899aebddd1SJeff Kirsher status = -EBUSY; 16909aebddd1SJeff Kirsher goto err; 16919aebddd1SJeff Kirsher } 16929aebddd1SJeff Kirsher req = embedded_payload(wrb); 16939aebddd1SJeff Kirsher 1694106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1695a2cc4e0bSSathya Perla OPCODE_COMMON_MANAGE_FAT, sizeof(*req), wrb, 1696a2cc4e0bSSathya Perla NULL); 16979aebddd1SJeff Kirsher req->fat_operation = cpu_to_le32(QUERY_FAT); 16989aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 16999aebddd1SJeff Kirsher if (!status) { 17009aebddd1SJeff Kirsher struct be_cmd_resp_get_fat *resp = embedded_payload(wrb); 170103d28ffeSKalesh AP 17029aebddd1SJeff Kirsher if (log_size && resp->log_size) 17039aebddd1SJeff Kirsher *log_size = le32_to_cpu(resp->log_size) - 17049aebddd1SJeff Kirsher sizeof(u32); 17059aebddd1SJeff Kirsher } 17069aebddd1SJeff Kirsher err: 17079aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 17089aebddd1SJeff Kirsher return status; 17099aebddd1SJeff Kirsher } 17109aebddd1SJeff Kirsher 1711c5f156deSVasundhara Volam int be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) 17129aebddd1SJeff Kirsher { 17139aebddd1SJeff Kirsher struct be_dma_mem get_fat_cmd; 17149aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 17159aebddd1SJeff Kirsher struct be_cmd_req_get_fat *req; 17169aebddd1SJeff Kirsher u32 offset = 0, total_size, buf_size, 17179aebddd1SJeff Kirsher log_offset = sizeof(u32), payload_len; 1718c5f156deSVasundhara Volam int status = 0; 17199aebddd1SJeff Kirsher 17209aebddd1SJeff Kirsher if (buf_len == 0) 1721c5f156deSVasundhara Volam return -EIO; 17229aebddd1SJeff Kirsher 17239aebddd1SJeff Kirsher total_size = buf_len; 17249aebddd1SJeff Kirsher 17259aebddd1SJeff Kirsher get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024; 17269aebddd1SJeff Kirsher get_fat_cmd.va = pci_alloc_consistent(adapter->pdev, 17279aebddd1SJeff Kirsher get_fat_cmd.size, 17289aebddd1SJeff Kirsher &get_fat_cmd.dma); 17299aebddd1SJeff Kirsher if (!get_fat_cmd.va) { 17309aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, 1731cd3307aaSKalesh AP "Memory allocation failure while reading FAT data\n"); 1732c5f156deSVasundhara Volam return -ENOMEM; 17339aebddd1SJeff Kirsher } 17349aebddd1SJeff Kirsher 17359aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 17369aebddd1SJeff Kirsher 17379aebddd1SJeff Kirsher while (total_size) { 17389aebddd1SJeff Kirsher buf_size = min(total_size, (u32)60*1024); 17399aebddd1SJeff Kirsher total_size -= buf_size; 17409aebddd1SJeff Kirsher 17419aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 17429aebddd1SJeff Kirsher if (!wrb) { 17439aebddd1SJeff Kirsher status = -EBUSY; 17449aebddd1SJeff Kirsher goto err; 17459aebddd1SJeff Kirsher } 17469aebddd1SJeff Kirsher req = get_fat_cmd.va; 17479aebddd1SJeff Kirsher 17489aebddd1SJeff Kirsher payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size; 1749106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1750a2cc4e0bSSathya Perla OPCODE_COMMON_MANAGE_FAT, payload_len, 1751a2cc4e0bSSathya Perla wrb, &get_fat_cmd); 17529aebddd1SJeff Kirsher 17539aebddd1SJeff Kirsher req->fat_operation = cpu_to_le32(RETRIEVE_FAT); 17549aebddd1SJeff Kirsher req->read_log_offset = cpu_to_le32(log_offset); 17559aebddd1SJeff Kirsher req->read_log_length = cpu_to_le32(buf_size); 17569aebddd1SJeff Kirsher req->data_buffer_size = cpu_to_le32(buf_size); 17579aebddd1SJeff Kirsher 17589aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 17599aebddd1SJeff Kirsher if (!status) { 17609aebddd1SJeff Kirsher struct be_cmd_resp_get_fat *resp = get_fat_cmd.va; 176103d28ffeSKalesh AP 17629aebddd1SJeff Kirsher memcpy(buf + offset, 17639aebddd1SJeff Kirsher resp->data_buffer, 176492aa9214SSomnath Kotur le32_to_cpu(resp->read_log_length)); 17659aebddd1SJeff Kirsher } else { 17669aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n"); 17679aebddd1SJeff Kirsher goto err; 17689aebddd1SJeff Kirsher } 17699aebddd1SJeff Kirsher offset += buf_size; 17709aebddd1SJeff Kirsher log_offset += buf_size; 17719aebddd1SJeff Kirsher } 17729aebddd1SJeff Kirsher err: 17739aebddd1SJeff Kirsher pci_free_consistent(adapter->pdev, get_fat_cmd.size, 1774a2cc4e0bSSathya Perla get_fat_cmd.va, get_fat_cmd.dma); 17759aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 1776c5f156deSVasundhara Volam return status; 17779aebddd1SJeff Kirsher } 17789aebddd1SJeff Kirsher 177904b71175SSathya Perla /* Uses synchronous mcc */ 1780e97e3cdaSKalesh AP int be_cmd_get_fw_ver(struct be_adapter *adapter) 17819aebddd1SJeff Kirsher { 17829aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 17839aebddd1SJeff Kirsher struct be_cmd_req_get_fw_version *req; 17849aebddd1SJeff Kirsher int status; 17859aebddd1SJeff Kirsher 178604b71175SSathya Perla spin_lock_bh(&adapter->mcc_lock); 17879aebddd1SJeff Kirsher 178804b71175SSathya Perla wrb = wrb_from_mccq(adapter); 178904b71175SSathya Perla if (!wrb) { 179004b71175SSathya Perla status = -EBUSY; 179104b71175SSathya Perla goto err; 179204b71175SSathya Perla } 179304b71175SSathya Perla 17949aebddd1SJeff Kirsher req = embedded_payload(wrb); 17959aebddd1SJeff Kirsher 1796106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1797a2cc4e0bSSathya Perla OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb, 1798a2cc4e0bSSathya Perla NULL); 179904b71175SSathya Perla status = be_mcc_notify_wait(adapter); 18009aebddd1SJeff Kirsher if (!status) { 18019aebddd1SJeff Kirsher struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb); 1802acbafeb1SSathya Perla 1803242eb470SVasundhara Volam strlcpy(adapter->fw_ver, resp->firmware_version_string, 1804242eb470SVasundhara Volam sizeof(adapter->fw_ver)); 1805242eb470SVasundhara Volam strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string, 1806242eb470SVasundhara Volam sizeof(adapter->fw_on_flash)); 18079aebddd1SJeff Kirsher } 180804b71175SSathya Perla err: 180904b71175SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 18109aebddd1SJeff Kirsher return status; 18119aebddd1SJeff Kirsher } 18129aebddd1SJeff Kirsher 18139aebddd1SJeff Kirsher /* set the EQ delay interval of an EQ to specified value 18149aebddd1SJeff Kirsher * Uses async mcc 18159aebddd1SJeff Kirsher */ 1816b502ae8dSKalesh AP static int __be_cmd_modify_eqd(struct be_adapter *adapter, 1817b502ae8dSKalesh AP struct be_set_eqd *set_eqd, int num) 18189aebddd1SJeff Kirsher { 18199aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 18209aebddd1SJeff Kirsher struct be_cmd_req_modify_eq_delay *req; 18212632bafdSSathya Perla int status = 0, i; 18229aebddd1SJeff Kirsher 18239aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 18249aebddd1SJeff Kirsher 18259aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 18269aebddd1SJeff Kirsher if (!wrb) { 18279aebddd1SJeff Kirsher status = -EBUSY; 18289aebddd1SJeff Kirsher goto err; 18299aebddd1SJeff Kirsher } 18309aebddd1SJeff Kirsher req = embedded_payload(wrb); 18319aebddd1SJeff Kirsher 1832106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1833a2cc4e0bSSathya Perla OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb, 1834a2cc4e0bSSathya Perla NULL); 18359aebddd1SJeff Kirsher 18362632bafdSSathya Perla req->num_eq = cpu_to_le32(num); 18372632bafdSSathya Perla for (i = 0; i < num; i++) { 18382632bafdSSathya Perla req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id); 18392632bafdSSathya Perla req->set_eqd[i].phase = 0; 18402632bafdSSathya Perla req->set_eqd[i].delay_multiplier = 18412632bafdSSathya Perla cpu_to_le32(set_eqd[i].delay_multiplier); 18422632bafdSSathya Perla } 18439aebddd1SJeff Kirsher 18449aebddd1SJeff Kirsher be_mcc_notify(adapter); 18459aebddd1SJeff Kirsher err: 18469aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 18479aebddd1SJeff Kirsher return status; 18489aebddd1SJeff Kirsher } 18499aebddd1SJeff Kirsher 185093676703SKalesh AP int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd, 185193676703SKalesh AP int num) 185293676703SKalesh AP { 185393676703SKalesh AP int num_eqs, i = 0; 185493676703SKalesh AP 185593676703SKalesh AP while (num) { 185693676703SKalesh AP num_eqs = min(num, 8); 185793676703SKalesh AP __be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs); 185893676703SKalesh AP i += num_eqs; 185993676703SKalesh AP num -= num_eqs; 186093676703SKalesh AP } 186193676703SKalesh AP 186293676703SKalesh AP return 0; 186393676703SKalesh AP } 186493676703SKalesh AP 18659aebddd1SJeff Kirsher /* Uses sycnhronous mcc */ 18669aebddd1SJeff Kirsher int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, 1867435452aaSVasundhara Volam u32 num, u32 domain) 18689aebddd1SJeff Kirsher { 18699aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 18709aebddd1SJeff Kirsher struct be_cmd_req_vlan_config *req; 18719aebddd1SJeff Kirsher int status; 18729aebddd1SJeff Kirsher 18739aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 18749aebddd1SJeff Kirsher 18759aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 18769aebddd1SJeff Kirsher if (!wrb) { 18779aebddd1SJeff Kirsher status = -EBUSY; 18789aebddd1SJeff Kirsher goto err; 18799aebddd1SJeff Kirsher } 18809aebddd1SJeff Kirsher req = embedded_payload(wrb); 18819aebddd1SJeff Kirsher 1882106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1883a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req), 1884a2cc4e0bSSathya Perla wrb, NULL); 1885435452aaSVasundhara Volam req->hdr.domain = domain; 18869aebddd1SJeff Kirsher 18879aebddd1SJeff Kirsher req->interface_id = if_id; 1888012bd387SAjit Khaparde req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0; 18899aebddd1SJeff Kirsher req->num_vlan = num; 18909aebddd1SJeff Kirsher memcpy(req->normal_vlan, vtag_array, 18919aebddd1SJeff Kirsher req->num_vlan * sizeof(vtag_array[0])); 18929aebddd1SJeff Kirsher 18939aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 18949aebddd1SJeff Kirsher err: 18959aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 18969aebddd1SJeff Kirsher return status; 18979aebddd1SJeff Kirsher } 18989aebddd1SJeff Kirsher 1899ac34b743SSathya Perla static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) 19009aebddd1SJeff Kirsher { 19019aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19029aebddd1SJeff Kirsher struct be_dma_mem *mem = &adapter->rx_filter; 19039aebddd1SJeff Kirsher struct be_cmd_req_rx_filter *req = mem->va; 19049aebddd1SJeff Kirsher int status; 19059aebddd1SJeff Kirsher 19069aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 19079aebddd1SJeff Kirsher 19089aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 19099aebddd1SJeff Kirsher if (!wrb) { 19109aebddd1SJeff Kirsher status = -EBUSY; 19119aebddd1SJeff Kirsher goto err; 19129aebddd1SJeff Kirsher } 19139aebddd1SJeff Kirsher memset(req, 0, sizeof(*req)); 1914106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1915106df1e3SSomnath Kotur OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req), 1916106df1e3SSomnath Kotur wrb, mem); 19179aebddd1SJeff Kirsher 19189aebddd1SJeff Kirsher req->if_id = cpu_to_le32(adapter->if_handle); 1919ac34b743SSathya Perla req->if_flags_mask = cpu_to_le32(flags); 1920ac34b743SSathya Perla req->if_flags = (value == ON) ? req->if_flags_mask : 0; 1921d9d604f8SAjit Khaparde 1922ac34b743SSathya Perla if (flags & BE_IF_FLAGS_MULTICAST) { 19239aebddd1SJeff Kirsher struct netdev_hw_addr *ha; 19249aebddd1SJeff Kirsher int i = 0; 19259aebddd1SJeff Kirsher 19261610c79fSPadmanabh Ratnakar /* Reset mcast promisc mode if already set by setting mask 19271610c79fSPadmanabh Ratnakar * and not setting flags field 19281610c79fSPadmanabh Ratnakar */ 19291610c79fSPadmanabh Ratnakar req->if_flags_mask |= 1930abb93951SPadmanabh Ratnakar cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS & 193192bf14abSSathya Perla be_if_cap_flags(adapter)); 1932016f97b1SPadmanabh Ratnakar req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev)); 19339aebddd1SJeff Kirsher netdev_for_each_mc_addr(ha, adapter->netdev) 19349aebddd1SJeff Kirsher memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN); 19359aebddd1SJeff Kirsher } 19369aebddd1SJeff Kirsher 19379aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 19389aebddd1SJeff Kirsher err: 19399aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 19409aebddd1SJeff Kirsher return status; 19419aebddd1SJeff Kirsher } 19429aebddd1SJeff Kirsher 1943ac34b743SSathya Perla int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) 1944ac34b743SSathya Perla { 1945ac34b743SSathya Perla struct device *dev = &adapter->pdev->dev; 1946ac34b743SSathya Perla 1947ac34b743SSathya Perla if ((flags & be_if_cap_flags(adapter)) != flags) { 1948ac34b743SSathya Perla dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags); 1949ac34b743SSathya Perla dev_warn(dev, "Interface is capable of 0x%x flags only\n", 1950ac34b743SSathya Perla be_if_cap_flags(adapter)); 1951ac34b743SSathya Perla } 1952ac34b743SSathya Perla flags &= be_if_cap_flags(adapter); 1953ac34b743SSathya Perla 1954ac34b743SSathya Perla return __be_cmd_rx_filter(adapter, flags, value); 1955ac34b743SSathya Perla } 1956ac34b743SSathya Perla 19579aebddd1SJeff Kirsher /* Uses synchrounous mcc */ 19589aebddd1SJeff Kirsher int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) 19599aebddd1SJeff Kirsher { 19609aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19619aebddd1SJeff Kirsher struct be_cmd_req_set_flow_control *req; 19629aebddd1SJeff Kirsher int status; 19639aebddd1SJeff Kirsher 1964f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL, 1965f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 1966f25b119cSPadmanabh Ratnakar return -EPERM; 1967f25b119cSPadmanabh Ratnakar 19689aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 19699aebddd1SJeff Kirsher 19709aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 19719aebddd1SJeff Kirsher if (!wrb) { 19729aebddd1SJeff Kirsher status = -EBUSY; 19739aebddd1SJeff Kirsher goto err; 19749aebddd1SJeff Kirsher } 19759aebddd1SJeff Kirsher req = embedded_payload(wrb); 19769aebddd1SJeff Kirsher 1977106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1978a2cc4e0bSSathya Perla OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req), 1979a2cc4e0bSSathya Perla wrb, NULL); 19809aebddd1SJeff Kirsher 1981b29812c1SSuresh Reddy req->hdr.version = 1; 19829aebddd1SJeff Kirsher req->tx_flow_control = cpu_to_le16((u16)tx_fc); 19839aebddd1SJeff Kirsher req->rx_flow_control = cpu_to_le16((u16)rx_fc); 19849aebddd1SJeff Kirsher 19859aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 19869aebddd1SJeff Kirsher 19879aebddd1SJeff Kirsher err: 19889aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 1989b29812c1SSuresh Reddy 1990b29812c1SSuresh Reddy if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED) 1991b29812c1SSuresh Reddy return -EOPNOTSUPP; 1992b29812c1SSuresh Reddy 19939aebddd1SJeff Kirsher return status; 19949aebddd1SJeff Kirsher } 19959aebddd1SJeff Kirsher 19969aebddd1SJeff Kirsher /* Uses sycn mcc */ 19979aebddd1SJeff Kirsher int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) 19989aebddd1SJeff Kirsher { 19999aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20009aebddd1SJeff Kirsher struct be_cmd_req_get_flow_control *req; 20019aebddd1SJeff Kirsher int status; 20029aebddd1SJeff Kirsher 2003f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL, 2004f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 2005f25b119cSPadmanabh Ratnakar return -EPERM; 2006f25b119cSPadmanabh Ratnakar 20079aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 20089aebddd1SJeff Kirsher 20099aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 20109aebddd1SJeff Kirsher if (!wrb) { 20119aebddd1SJeff Kirsher status = -EBUSY; 20129aebddd1SJeff Kirsher goto err; 20139aebddd1SJeff Kirsher } 20149aebddd1SJeff Kirsher req = embedded_payload(wrb); 20159aebddd1SJeff Kirsher 2016106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2017a2cc4e0bSSathya Perla OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req), 2018a2cc4e0bSSathya Perla wrb, NULL); 20199aebddd1SJeff Kirsher 20209aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 20219aebddd1SJeff Kirsher if (!status) { 20229aebddd1SJeff Kirsher struct be_cmd_resp_get_flow_control *resp = 20239aebddd1SJeff Kirsher embedded_payload(wrb); 202403d28ffeSKalesh AP 20259aebddd1SJeff Kirsher *tx_fc = le16_to_cpu(resp->tx_flow_control); 20269aebddd1SJeff Kirsher *rx_fc = le16_to_cpu(resp->rx_flow_control); 20279aebddd1SJeff Kirsher } 20289aebddd1SJeff Kirsher 20299aebddd1SJeff Kirsher err: 20309aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 20319aebddd1SJeff Kirsher return status; 20329aebddd1SJeff Kirsher } 20339aebddd1SJeff Kirsher 20349aebddd1SJeff Kirsher /* Uses mbox */ 2035e97e3cdaSKalesh AP int be_cmd_query_fw_cfg(struct be_adapter *adapter) 20369aebddd1SJeff Kirsher { 20379aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20389aebddd1SJeff Kirsher struct be_cmd_req_query_fw_cfg *req; 20399aebddd1SJeff Kirsher int status; 20409aebddd1SJeff Kirsher 20419aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 20429aebddd1SJeff Kirsher return -1; 20439aebddd1SJeff Kirsher 20449aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 20459aebddd1SJeff Kirsher req = embedded_payload(wrb); 20469aebddd1SJeff Kirsher 2047106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2048a2cc4e0bSSathya Perla OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, 2049a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 20509aebddd1SJeff Kirsher 20519aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 20529aebddd1SJeff Kirsher if (!status) { 20539aebddd1SJeff Kirsher struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); 205403d28ffeSKalesh AP 2055e97e3cdaSKalesh AP adapter->port_num = le32_to_cpu(resp->phys_port); 2056e97e3cdaSKalesh AP adapter->function_mode = le32_to_cpu(resp->function_mode); 2057e97e3cdaSKalesh AP adapter->function_caps = le32_to_cpu(resp->function_caps); 2058e97e3cdaSKalesh AP adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF; 2059acbafeb1SSathya Perla dev_info(&adapter->pdev->dev, 2060acbafeb1SSathya Perla "FW config: function_mode=0x%x, function_caps=0x%x\n", 2061acbafeb1SSathya Perla adapter->function_mode, adapter->function_caps); 20629aebddd1SJeff Kirsher } 20639aebddd1SJeff Kirsher 20649aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 20659aebddd1SJeff Kirsher return status; 20669aebddd1SJeff Kirsher } 20679aebddd1SJeff Kirsher 20689aebddd1SJeff Kirsher /* Uses mbox */ 20699aebddd1SJeff Kirsher int be_cmd_reset_function(struct be_adapter *adapter) 20709aebddd1SJeff Kirsher { 20719aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20729aebddd1SJeff Kirsher struct be_cmd_req_hdr *req; 20739aebddd1SJeff Kirsher int status; 20749aebddd1SJeff Kirsher 2075bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) { 2076bf99e50dSPadmanabh Ratnakar iowrite32(SLI_PORT_CONTROL_IP_MASK, 2077bf99e50dSPadmanabh Ratnakar adapter->db + SLIPORT_CONTROL_OFFSET); 20789fa465c0SSathya Perla status = lancer_wait_ready(adapter); 20799fa465c0SSathya Perla if (status) 2080bf99e50dSPadmanabh Ratnakar dev_err(&adapter->pdev->dev, 2081bf99e50dSPadmanabh Ratnakar "Adapter in non recoverable error\n"); 2082bf99e50dSPadmanabh Ratnakar return status; 2083bf99e50dSPadmanabh Ratnakar } 2084bf99e50dSPadmanabh Ratnakar 20859aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 20869aebddd1SJeff Kirsher return -1; 20879aebddd1SJeff Kirsher 20889aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 20899aebddd1SJeff Kirsher req = embedded_payload(wrb); 20909aebddd1SJeff Kirsher 2091106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON, 2092a2cc4e0bSSathya Perla OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb, 2093a2cc4e0bSSathya Perla NULL); 20949aebddd1SJeff Kirsher 20959aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 20969aebddd1SJeff Kirsher 20979aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 20989aebddd1SJeff Kirsher return status; 20999aebddd1SJeff Kirsher } 21009aebddd1SJeff Kirsher 2101594ad54aSSuresh Reddy int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, 210233cb0fa7SBen Hutchings u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey) 21039aebddd1SJeff Kirsher { 21049aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21059aebddd1SJeff Kirsher struct be_cmd_req_rss_config *req; 21069aebddd1SJeff Kirsher int status; 21079aebddd1SJeff Kirsher 2108da1388d6SVasundhara Volam if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS)) 2109da1388d6SVasundhara Volam return 0; 2110da1388d6SVasundhara Volam 2111b51aa367SKalesh AP spin_lock_bh(&adapter->mcc_lock); 21129aebddd1SJeff Kirsher 2113b51aa367SKalesh AP wrb = wrb_from_mccq(adapter); 2114b51aa367SKalesh AP if (!wrb) { 2115b51aa367SKalesh AP status = -EBUSY; 2116b51aa367SKalesh AP goto err; 2117b51aa367SKalesh AP } 21189aebddd1SJeff Kirsher req = embedded_payload(wrb); 21199aebddd1SJeff Kirsher 2120106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 2121106df1e3SSomnath Kotur OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL); 21229aebddd1SJeff Kirsher 21239aebddd1SJeff Kirsher req->if_id = cpu_to_le32(adapter->if_handle); 2124594ad54aSSuresh Reddy req->enable_rss = cpu_to_le16(rss_hash_opts); 21259aebddd1SJeff Kirsher req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1); 2126594ad54aSSuresh Reddy 2127b51aa367SKalesh AP if (!BEx_chip(adapter)) 2128594ad54aSSuresh Reddy req->hdr.version = 1; 2129594ad54aSSuresh Reddy 21309aebddd1SJeff Kirsher memcpy(req->cpu_table, rsstable, table_size); 2131e2557877SVenkata Duvvuru memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN); 21329aebddd1SJeff Kirsher be_dws_cpu_to_le(req->hash, sizeof(req->hash)); 21339aebddd1SJeff Kirsher 2134b51aa367SKalesh AP status = be_mcc_notify_wait(adapter); 2135b51aa367SKalesh AP err: 2136b51aa367SKalesh AP spin_unlock_bh(&adapter->mcc_lock); 21379aebddd1SJeff Kirsher return status; 21389aebddd1SJeff Kirsher } 21399aebddd1SJeff Kirsher 21409aebddd1SJeff Kirsher /* Uses sync mcc */ 21419aebddd1SJeff Kirsher int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, 21429aebddd1SJeff Kirsher u8 bcn, u8 sts, u8 state) 21439aebddd1SJeff Kirsher { 21449aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21459aebddd1SJeff Kirsher struct be_cmd_req_enable_disable_beacon *req; 21469aebddd1SJeff Kirsher int status; 21479aebddd1SJeff Kirsher 21489aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 21499aebddd1SJeff Kirsher 21509aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 21519aebddd1SJeff Kirsher if (!wrb) { 21529aebddd1SJeff Kirsher status = -EBUSY; 21539aebddd1SJeff Kirsher goto err; 21549aebddd1SJeff Kirsher } 21559aebddd1SJeff Kirsher req = embedded_payload(wrb); 21569aebddd1SJeff Kirsher 2157106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2158a2cc4e0bSSathya Perla OPCODE_COMMON_ENABLE_DISABLE_BEACON, 2159a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 21609aebddd1SJeff Kirsher 21619aebddd1SJeff Kirsher req->port_num = port_num; 21629aebddd1SJeff Kirsher req->beacon_state = state; 21639aebddd1SJeff Kirsher req->beacon_duration = bcn; 21649aebddd1SJeff Kirsher req->status_duration = sts; 21659aebddd1SJeff Kirsher 21669aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 21679aebddd1SJeff Kirsher 21689aebddd1SJeff Kirsher err: 21699aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 21709aebddd1SJeff Kirsher return status; 21719aebddd1SJeff Kirsher } 21729aebddd1SJeff Kirsher 21739aebddd1SJeff Kirsher /* Uses sync mcc */ 21749aebddd1SJeff Kirsher int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) 21759aebddd1SJeff Kirsher { 21769aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21779aebddd1SJeff Kirsher struct be_cmd_req_get_beacon_state *req; 21789aebddd1SJeff Kirsher int status; 21799aebddd1SJeff Kirsher 21809aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 21819aebddd1SJeff Kirsher 21829aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 21839aebddd1SJeff Kirsher if (!wrb) { 21849aebddd1SJeff Kirsher status = -EBUSY; 21859aebddd1SJeff Kirsher goto err; 21869aebddd1SJeff Kirsher } 21879aebddd1SJeff Kirsher req = embedded_payload(wrb); 21889aebddd1SJeff Kirsher 2189106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2190a2cc4e0bSSathya Perla OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req), 2191a2cc4e0bSSathya Perla wrb, NULL); 21929aebddd1SJeff Kirsher 21939aebddd1SJeff Kirsher req->port_num = port_num; 21949aebddd1SJeff Kirsher 21959aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 21969aebddd1SJeff Kirsher if (!status) { 21979aebddd1SJeff Kirsher struct be_cmd_resp_get_beacon_state *resp = 21989aebddd1SJeff Kirsher embedded_payload(wrb); 219903d28ffeSKalesh AP 22009aebddd1SJeff Kirsher *state = resp->beacon_state; 22019aebddd1SJeff Kirsher } 22029aebddd1SJeff Kirsher 22039aebddd1SJeff Kirsher err: 22049aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 22059aebddd1SJeff Kirsher return status; 22069aebddd1SJeff Kirsher } 22079aebddd1SJeff Kirsher 2208e36edd9dSMark Leonard /* Uses sync mcc */ 2209e36edd9dSMark Leonard int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, 2210e36edd9dSMark Leonard u8 page_num, u8 *data) 2211e36edd9dSMark Leonard { 2212e36edd9dSMark Leonard struct be_dma_mem cmd; 2213e36edd9dSMark Leonard struct be_mcc_wrb *wrb; 2214e36edd9dSMark Leonard struct be_cmd_req_port_type *req; 2215e36edd9dSMark Leonard int status; 2216e36edd9dSMark Leonard 2217e36edd9dSMark Leonard if (page_num > TR_PAGE_A2) 2218e36edd9dSMark Leonard return -EINVAL; 2219e36edd9dSMark Leonard 2220e36edd9dSMark Leonard cmd.size = sizeof(struct be_cmd_resp_port_type); 2221e36edd9dSMark Leonard cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 2222e36edd9dSMark Leonard if (!cmd.va) { 2223e36edd9dSMark Leonard dev_err(&adapter->pdev->dev, "Memory allocation failed\n"); 2224e36edd9dSMark Leonard return -ENOMEM; 2225e36edd9dSMark Leonard } 2226e36edd9dSMark Leonard memset(cmd.va, 0, cmd.size); 2227e36edd9dSMark Leonard 2228e36edd9dSMark Leonard spin_lock_bh(&adapter->mcc_lock); 2229e36edd9dSMark Leonard 2230e36edd9dSMark Leonard wrb = wrb_from_mccq(adapter); 2231e36edd9dSMark Leonard if (!wrb) { 2232e36edd9dSMark Leonard status = -EBUSY; 2233e36edd9dSMark Leonard goto err; 2234e36edd9dSMark Leonard } 2235e36edd9dSMark Leonard req = cmd.va; 2236e36edd9dSMark Leonard 2237e36edd9dSMark Leonard be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2238e36edd9dSMark Leonard OPCODE_COMMON_READ_TRANSRECV_DATA, 2239e36edd9dSMark Leonard cmd.size, wrb, &cmd); 2240e36edd9dSMark Leonard 2241e36edd9dSMark Leonard req->port = cpu_to_le32(adapter->hba_port_num); 2242e36edd9dSMark Leonard req->page_num = cpu_to_le32(page_num); 2243e36edd9dSMark Leonard status = be_mcc_notify_wait(adapter); 2244e36edd9dSMark Leonard if (!status) { 2245e36edd9dSMark Leonard struct be_cmd_resp_port_type *resp = cmd.va; 2246e36edd9dSMark Leonard 2247e36edd9dSMark Leonard memcpy(data, resp->page_data, PAGE_DATA_LEN); 2248e36edd9dSMark Leonard } 2249e36edd9dSMark Leonard err: 2250e36edd9dSMark Leonard spin_unlock_bh(&adapter->mcc_lock); 2251e36edd9dSMark Leonard pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 2252e36edd9dSMark Leonard return status; 2253e36edd9dSMark Leonard } 2254e36edd9dSMark Leonard 22559aebddd1SJeff Kirsher int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, 2256f67ef7baSPadmanabh Ratnakar u32 data_size, u32 data_offset, 2257f67ef7baSPadmanabh Ratnakar const char *obj_name, u32 *data_written, 2258f67ef7baSPadmanabh Ratnakar u8 *change_status, u8 *addn_status) 22599aebddd1SJeff Kirsher { 22609aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 22619aebddd1SJeff Kirsher struct lancer_cmd_req_write_object *req; 22629aebddd1SJeff Kirsher struct lancer_cmd_resp_write_object *resp; 22639aebddd1SJeff Kirsher void *ctxt = NULL; 22649aebddd1SJeff Kirsher int status; 22659aebddd1SJeff Kirsher 22669aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 22679aebddd1SJeff Kirsher adapter->flash_status = 0; 22689aebddd1SJeff Kirsher 22699aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 22709aebddd1SJeff Kirsher if (!wrb) { 22719aebddd1SJeff Kirsher status = -EBUSY; 22729aebddd1SJeff Kirsher goto err_unlock; 22739aebddd1SJeff Kirsher } 22749aebddd1SJeff Kirsher 22759aebddd1SJeff Kirsher req = embedded_payload(wrb); 22769aebddd1SJeff Kirsher 2277106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 22789aebddd1SJeff Kirsher OPCODE_COMMON_WRITE_OBJECT, 2279106df1e3SSomnath Kotur sizeof(struct lancer_cmd_req_write_object), wrb, 2280106df1e3SSomnath Kotur NULL); 22819aebddd1SJeff Kirsher 22829aebddd1SJeff Kirsher ctxt = &req->context; 22839aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 22849aebddd1SJeff Kirsher write_length, ctxt, data_size); 22859aebddd1SJeff Kirsher 22869aebddd1SJeff Kirsher if (data_size == 0) 22879aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 22889aebddd1SJeff Kirsher eof, ctxt, 1); 22899aebddd1SJeff Kirsher else 22909aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 22919aebddd1SJeff Kirsher eof, ctxt, 0); 22929aebddd1SJeff Kirsher 22939aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 22949aebddd1SJeff Kirsher req->write_offset = cpu_to_le32(data_offset); 2295242eb470SVasundhara Volam strlcpy(req->object_name, obj_name, sizeof(req->object_name)); 22969aebddd1SJeff Kirsher req->descriptor_count = cpu_to_le32(1); 22979aebddd1SJeff Kirsher req->buf_len = cpu_to_le32(data_size); 22989aebddd1SJeff Kirsher req->addr_low = cpu_to_le32((cmd->dma + 22999aebddd1SJeff Kirsher sizeof(struct lancer_cmd_req_write_object)) 23009aebddd1SJeff Kirsher & 0xFFFFFFFF); 23019aebddd1SJeff Kirsher req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma + 23029aebddd1SJeff Kirsher sizeof(struct lancer_cmd_req_write_object))); 23039aebddd1SJeff Kirsher 23049aebddd1SJeff Kirsher be_mcc_notify(adapter); 23059aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 23069aebddd1SJeff Kirsher 23075eeff635SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 2308701962d0SSomnath Kotur msecs_to_jiffies(60000))) 2309fd45160cSKalesh AP status = -ETIMEDOUT; 23109aebddd1SJeff Kirsher else 23119aebddd1SJeff Kirsher status = adapter->flash_status; 23129aebddd1SJeff Kirsher 23139aebddd1SJeff Kirsher resp = embedded_payload(wrb); 2314f67ef7baSPadmanabh Ratnakar if (!status) { 23159aebddd1SJeff Kirsher *data_written = le32_to_cpu(resp->actual_write_len); 2316f67ef7baSPadmanabh Ratnakar *change_status = resp->change_status; 2317f67ef7baSPadmanabh Ratnakar } else { 23189aebddd1SJeff Kirsher *addn_status = resp->additional_status; 2319f67ef7baSPadmanabh Ratnakar } 23209aebddd1SJeff Kirsher 23219aebddd1SJeff Kirsher return status; 23229aebddd1SJeff Kirsher 23239aebddd1SJeff Kirsher err_unlock: 23249aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 23259aebddd1SJeff Kirsher return status; 23269aebddd1SJeff Kirsher } 23279aebddd1SJeff Kirsher 23286809cee0SRavikumar Nelavelli int be_cmd_query_cable_type(struct be_adapter *adapter) 23296809cee0SRavikumar Nelavelli { 23306809cee0SRavikumar Nelavelli u8 page_data[PAGE_DATA_LEN]; 23316809cee0SRavikumar Nelavelli int status; 23326809cee0SRavikumar Nelavelli 23336809cee0SRavikumar Nelavelli status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, 23346809cee0SRavikumar Nelavelli page_data); 23356809cee0SRavikumar Nelavelli if (!status) { 23366809cee0SRavikumar Nelavelli switch (adapter->phy.interface_type) { 23376809cee0SRavikumar Nelavelli case PHY_TYPE_QSFP: 23386809cee0SRavikumar Nelavelli adapter->phy.cable_type = 23396809cee0SRavikumar Nelavelli page_data[QSFP_PLUS_CABLE_TYPE_OFFSET]; 23406809cee0SRavikumar Nelavelli break; 23416809cee0SRavikumar Nelavelli case PHY_TYPE_SFP_PLUS_10GB: 23426809cee0SRavikumar Nelavelli adapter->phy.cable_type = 23436809cee0SRavikumar Nelavelli page_data[SFP_PLUS_CABLE_TYPE_OFFSET]; 23446809cee0SRavikumar Nelavelli break; 23456809cee0SRavikumar Nelavelli default: 23466809cee0SRavikumar Nelavelli adapter->phy.cable_type = 0; 23476809cee0SRavikumar Nelavelli break; 23486809cee0SRavikumar Nelavelli } 23496809cee0SRavikumar Nelavelli } 23506809cee0SRavikumar Nelavelli return status; 23516809cee0SRavikumar Nelavelli } 23526809cee0SRavikumar Nelavelli 235321252377SVasundhara Volam int be_cmd_query_sfp_info(struct be_adapter *adapter) 235421252377SVasundhara Volam { 235521252377SVasundhara Volam u8 page_data[PAGE_DATA_LEN]; 235621252377SVasundhara Volam int status; 235721252377SVasundhara Volam 235821252377SVasundhara Volam status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, 235921252377SVasundhara Volam page_data); 236021252377SVasundhara Volam if (!status) { 236121252377SVasundhara Volam strlcpy(adapter->phy.vendor_name, page_data + 236221252377SVasundhara Volam SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1); 236321252377SVasundhara Volam strlcpy(adapter->phy.vendor_pn, 236421252377SVasundhara Volam page_data + SFP_VENDOR_PN_OFFSET, 236521252377SVasundhara Volam SFP_VENDOR_NAME_LEN - 1); 236621252377SVasundhara Volam } 236721252377SVasundhara Volam 236821252377SVasundhara Volam return status; 236921252377SVasundhara Volam } 237021252377SVasundhara Volam 2371f0613380SKalesh AP int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name) 2372f0613380SKalesh AP { 2373f0613380SKalesh AP struct lancer_cmd_req_delete_object *req; 2374f0613380SKalesh AP struct be_mcc_wrb *wrb; 2375f0613380SKalesh AP int status; 2376f0613380SKalesh AP 2377f0613380SKalesh AP spin_lock_bh(&adapter->mcc_lock); 2378f0613380SKalesh AP 2379f0613380SKalesh AP wrb = wrb_from_mccq(adapter); 2380f0613380SKalesh AP if (!wrb) { 2381f0613380SKalesh AP status = -EBUSY; 2382f0613380SKalesh AP goto err; 2383f0613380SKalesh AP } 2384f0613380SKalesh AP 2385f0613380SKalesh AP req = embedded_payload(wrb); 2386f0613380SKalesh AP 2387f0613380SKalesh AP be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2388f0613380SKalesh AP OPCODE_COMMON_DELETE_OBJECT, 2389f0613380SKalesh AP sizeof(*req), wrb, NULL); 2390f0613380SKalesh AP 2391242eb470SVasundhara Volam strlcpy(req->object_name, obj_name, sizeof(req->object_name)); 2392f0613380SKalesh AP 2393f0613380SKalesh AP status = be_mcc_notify_wait(adapter); 2394f0613380SKalesh AP err: 2395f0613380SKalesh AP spin_unlock_bh(&adapter->mcc_lock); 2396f0613380SKalesh AP return status; 2397f0613380SKalesh AP } 2398f0613380SKalesh AP 2399de49bd5aSPadmanabh Ratnakar int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, 2400de49bd5aSPadmanabh Ratnakar u32 data_size, u32 data_offset, const char *obj_name, 2401de49bd5aSPadmanabh Ratnakar u32 *data_read, u32 *eof, u8 *addn_status) 2402de49bd5aSPadmanabh Ratnakar { 2403de49bd5aSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 2404de49bd5aSPadmanabh Ratnakar struct lancer_cmd_req_read_object *req; 2405de49bd5aSPadmanabh Ratnakar struct lancer_cmd_resp_read_object *resp; 2406de49bd5aSPadmanabh Ratnakar int status; 2407de49bd5aSPadmanabh Ratnakar 2408de49bd5aSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 2409de49bd5aSPadmanabh Ratnakar 2410de49bd5aSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 2411de49bd5aSPadmanabh Ratnakar if (!wrb) { 2412de49bd5aSPadmanabh Ratnakar status = -EBUSY; 2413de49bd5aSPadmanabh Ratnakar goto err_unlock; 2414de49bd5aSPadmanabh Ratnakar } 2415de49bd5aSPadmanabh Ratnakar 2416de49bd5aSPadmanabh Ratnakar req = embedded_payload(wrb); 2417de49bd5aSPadmanabh Ratnakar 2418de49bd5aSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2419de49bd5aSPadmanabh Ratnakar OPCODE_COMMON_READ_OBJECT, 2420de49bd5aSPadmanabh Ratnakar sizeof(struct lancer_cmd_req_read_object), wrb, 2421de49bd5aSPadmanabh Ratnakar NULL); 2422de49bd5aSPadmanabh Ratnakar 2423de49bd5aSPadmanabh Ratnakar req->desired_read_len = cpu_to_le32(data_size); 2424de49bd5aSPadmanabh Ratnakar req->read_offset = cpu_to_le32(data_offset); 2425de49bd5aSPadmanabh Ratnakar strcpy(req->object_name, obj_name); 2426de49bd5aSPadmanabh Ratnakar req->descriptor_count = cpu_to_le32(1); 2427de49bd5aSPadmanabh Ratnakar req->buf_len = cpu_to_le32(data_size); 2428de49bd5aSPadmanabh Ratnakar req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF)); 2429de49bd5aSPadmanabh Ratnakar req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma)); 2430de49bd5aSPadmanabh Ratnakar 2431de49bd5aSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 2432de49bd5aSPadmanabh Ratnakar 2433de49bd5aSPadmanabh Ratnakar resp = embedded_payload(wrb); 2434de49bd5aSPadmanabh Ratnakar if (!status) { 2435de49bd5aSPadmanabh Ratnakar *data_read = le32_to_cpu(resp->actual_read_len); 2436de49bd5aSPadmanabh Ratnakar *eof = le32_to_cpu(resp->eof); 2437de49bd5aSPadmanabh Ratnakar } else { 2438de49bd5aSPadmanabh Ratnakar *addn_status = resp->additional_status; 2439de49bd5aSPadmanabh Ratnakar } 2440de49bd5aSPadmanabh Ratnakar 2441de49bd5aSPadmanabh Ratnakar err_unlock: 2442de49bd5aSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 2443de49bd5aSPadmanabh Ratnakar return status; 2444de49bd5aSPadmanabh Ratnakar } 2445de49bd5aSPadmanabh Ratnakar 24469aebddd1SJeff Kirsher int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, 244770a7b525SVasundhara Volam u32 flash_type, u32 flash_opcode, u32 img_offset, 244870a7b525SVasundhara Volam u32 buf_size) 24499aebddd1SJeff Kirsher { 24509aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 24519aebddd1SJeff Kirsher struct be_cmd_write_flashrom *req; 24529aebddd1SJeff Kirsher int status; 24539aebddd1SJeff Kirsher 24549aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 24559aebddd1SJeff Kirsher adapter->flash_status = 0; 24569aebddd1SJeff Kirsher 24579aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 24589aebddd1SJeff Kirsher if (!wrb) { 24599aebddd1SJeff Kirsher status = -EBUSY; 24609aebddd1SJeff Kirsher goto err_unlock; 24619aebddd1SJeff Kirsher } 24629aebddd1SJeff Kirsher req = cmd->va; 24639aebddd1SJeff Kirsher 2464106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2465a2cc4e0bSSathya Perla OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb, 2466a2cc4e0bSSathya Perla cmd); 24679aebddd1SJeff Kirsher 24689aebddd1SJeff Kirsher req->params.op_type = cpu_to_le32(flash_type); 246970a7b525SVasundhara Volam if (flash_type == OPTYPE_OFFSET_SPECIFIED) 247070a7b525SVasundhara Volam req->params.offset = cpu_to_le32(img_offset); 247170a7b525SVasundhara Volam 24729aebddd1SJeff Kirsher req->params.op_code = cpu_to_le32(flash_opcode); 24739aebddd1SJeff Kirsher req->params.data_buf_size = cpu_to_le32(buf_size); 24749aebddd1SJeff Kirsher 24759aebddd1SJeff Kirsher be_mcc_notify(adapter); 24769aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 24779aebddd1SJeff Kirsher 24785eeff635SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 2479e2edb7d5SSathya Perla msecs_to_jiffies(40000))) 2480fd45160cSKalesh AP status = -ETIMEDOUT; 24819aebddd1SJeff Kirsher else 24829aebddd1SJeff Kirsher status = adapter->flash_status; 24839aebddd1SJeff Kirsher 24849aebddd1SJeff Kirsher return status; 24859aebddd1SJeff Kirsher 24869aebddd1SJeff Kirsher err_unlock: 24879aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 24889aebddd1SJeff Kirsher return status; 24899aebddd1SJeff Kirsher } 24909aebddd1SJeff Kirsher 24919aebddd1SJeff Kirsher int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, 249270a7b525SVasundhara Volam u16 img_optype, u32 img_offset, u32 crc_offset) 24939aebddd1SJeff Kirsher { 2494be716446SPadmanabh Ratnakar struct be_cmd_read_flash_crc *req; 249570a7b525SVasundhara Volam struct be_mcc_wrb *wrb; 24969aebddd1SJeff Kirsher int status; 24979aebddd1SJeff Kirsher 24989aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 24999aebddd1SJeff Kirsher 25009aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 25019aebddd1SJeff Kirsher if (!wrb) { 25029aebddd1SJeff Kirsher status = -EBUSY; 25039aebddd1SJeff Kirsher goto err; 25049aebddd1SJeff Kirsher } 25059aebddd1SJeff Kirsher req = embedded_payload(wrb); 25069aebddd1SJeff Kirsher 2507106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2508be716446SPadmanabh Ratnakar OPCODE_COMMON_READ_FLASHROM, sizeof(*req), 2509be716446SPadmanabh Ratnakar wrb, NULL); 25109aebddd1SJeff Kirsher 251170a7b525SVasundhara Volam req->params.op_type = cpu_to_le32(img_optype); 251270a7b525SVasundhara Volam if (img_optype == OPTYPE_OFFSET_SPECIFIED) 251370a7b525SVasundhara Volam req->params.offset = cpu_to_le32(img_offset + crc_offset); 251470a7b525SVasundhara Volam else 251570a7b525SVasundhara Volam req->params.offset = cpu_to_le32(crc_offset); 251670a7b525SVasundhara Volam 25179aebddd1SJeff Kirsher req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); 25189aebddd1SJeff Kirsher req->params.data_buf_size = cpu_to_le32(0x4); 25199aebddd1SJeff Kirsher 25209aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 25219aebddd1SJeff Kirsher if (!status) 2522be716446SPadmanabh Ratnakar memcpy(flashed_crc, req->crc, 4); 25239aebddd1SJeff Kirsher 25249aebddd1SJeff Kirsher err: 25259aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25269aebddd1SJeff Kirsher return status; 25279aebddd1SJeff Kirsher } 25289aebddd1SJeff Kirsher 25299aebddd1SJeff Kirsher int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, 25309aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 25319aebddd1SJeff Kirsher { 25329aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 25339aebddd1SJeff Kirsher struct be_cmd_req_acpi_wol_magic_config *req; 25349aebddd1SJeff Kirsher int status; 25359aebddd1SJeff Kirsher 25369aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 25379aebddd1SJeff Kirsher 25389aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 25399aebddd1SJeff Kirsher if (!wrb) { 25409aebddd1SJeff Kirsher status = -EBUSY; 25419aebddd1SJeff Kirsher goto err; 25429aebddd1SJeff Kirsher } 25439aebddd1SJeff Kirsher req = nonemb_cmd->va; 25449aebddd1SJeff Kirsher 2545106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 2546a2cc4e0bSSathya Perla OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req), 2547a2cc4e0bSSathya Perla wrb, nonemb_cmd); 25489aebddd1SJeff Kirsher memcpy(req->magic_mac, mac, ETH_ALEN); 25499aebddd1SJeff Kirsher 25509aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 25519aebddd1SJeff Kirsher 25529aebddd1SJeff Kirsher err: 25539aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25549aebddd1SJeff Kirsher return status; 25559aebddd1SJeff Kirsher } 25569aebddd1SJeff Kirsher 25579aebddd1SJeff Kirsher int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, 25589aebddd1SJeff Kirsher u8 loopback_type, u8 enable) 25599aebddd1SJeff Kirsher { 25609aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 25619aebddd1SJeff Kirsher struct be_cmd_req_set_lmode *req; 25629aebddd1SJeff Kirsher int status; 25639aebddd1SJeff Kirsher 25649aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 25659aebddd1SJeff Kirsher 25669aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 25679aebddd1SJeff Kirsher if (!wrb) { 25689aebddd1SJeff Kirsher status = -EBUSY; 25699aebddd1SJeff Kirsher goto err; 25709aebddd1SJeff Kirsher } 25719aebddd1SJeff Kirsher 25729aebddd1SJeff Kirsher req = embedded_payload(wrb); 25739aebddd1SJeff Kirsher 2574106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 2575a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req), 2576a2cc4e0bSSathya Perla wrb, NULL); 25779aebddd1SJeff Kirsher 25789aebddd1SJeff Kirsher req->src_port = port_num; 25799aebddd1SJeff Kirsher req->dest_port = port_num; 25809aebddd1SJeff Kirsher req->loopback_type = loopback_type; 25819aebddd1SJeff Kirsher req->loopback_state = enable; 25829aebddd1SJeff Kirsher 25839aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 25849aebddd1SJeff Kirsher err: 25859aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25869aebddd1SJeff Kirsher return status; 25879aebddd1SJeff Kirsher } 25889aebddd1SJeff Kirsher 25899aebddd1SJeff Kirsher int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, 2590a2cc4e0bSSathya Perla u32 loopback_type, u32 pkt_size, u32 num_pkts, 2591a2cc4e0bSSathya Perla u64 pattern) 25929aebddd1SJeff Kirsher { 25939aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 25949aebddd1SJeff Kirsher struct be_cmd_req_loopback_test *req; 25955eeff635SSuresh Reddy struct be_cmd_resp_loopback_test *resp; 25969aebddd1SJeff Kirsher int status; 25979aebddd1SJeff Kirsher 25989aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 25999aebddd1SJeff Kirsher 26009aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 26019aebddd1SJeff Kirsher if (!wrb) { 26029aebddd1SJeff Kirsher status = -EBUSY; 26039aebddd1SJeff Kirsher goto err; 26049aebddd1SJeff Kirsher } 26059aebddd1SJeff Kirsher 26069aebddd1SJeff Kirsher req = embedded_payload(wrb); 26079aebddd1SJeff Kirsher 2608106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 2609a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, 2610a2cc4e0bSSathya Perla NULL); 26119aebddd1SJeff Kirsher 26125eeff635SSuresh Reddy req->hdr.timeout = cpu_to_le32(15); 26139aebddd1SJeff Kirsher req->pattern = cpu_to_le64(pattern); 26149aebddd1SJeff Kirsher req->src_port = cpu_to_le32(port_num); 26159aebddd1SJeff Kirsher req->dest_port = cpu_to_le32(port_num); 26169aebddd1SJeff Kirsher req->pkt_size = cpu_to_le32(pkt_size); 26179aebddd1SJeff Kirsher req->num_pkts = cpu_to_le32(num_pkts); 26189aebddd1SJeff Kirsher req->loopback_type = cpu_to_le32(loopback_type); 26199aebddd1SJeff Kirsher 26205eeff635SSuresh Reddy be_mcc_notify(adapter); 26219aebddd1SJeff Kirsher 26225eeff635SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 26235eeff635SSuresh Reddy 26245eeff635SSuresh Reddy wait_for_completion(&adapter->et_cmd_compl); 26255eeff635SSuresh Reddy resp = embedded_payload(wrb); 26265eeff635SSuresh Reddy status = le32_to_cpu(resp->status); 26275eeff635SSuresh Reddy 26285eeff635SSuresh Reddy return status; 26299aebddd1SJeff Kirsher err: 26309aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 26319aebddd1SJeff Kirsher return status; 26329aebddd1SJeff Kirsher } 26339aebddd1SJeff Kirsher 26349aebddd1SJeff Kirsher int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, 26359aebddd1SJeff Kirsher u32 byte_cnt, struct be_dma_mem *cmd) 26369aebddd1SJeff Kirsher { 26379aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 26389aebddd1SJeff Kirsher struct be_cmd_req_ddrdma_test *req; 26399aebddd1SJeff Kirsher int status; 26409aebddd1SJeff Kirsher int i, j = 0; 26419aebddd1SJeff Kirsher 26429aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 26439aebddd1SJeff Kirsher 26449aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 26459aebddd1SJeff Kirsher if (!wrb) { 26469aebddd1SJeff Kirsher status = -EBUSY; 26479aebddd1SJeff Kirsher goto err; 26489aebddd1SJeff Kirsher } 26499aebddd1SJeff Kirsher req = cmd->va; 2650106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 2651a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb, 2652a2cc4e0bSSathya Perla cmd); 26539aebddd1SJeff Kirsher 26549aebddd1SJeff Kirsher req->pattern = cpu_to_le64(pattern); 26559aebddd1SJeff Kirsher req->byte_count = cpu_to_le32(byte_cnt); 26569aebddd1SJeff Kirsher for (i = 0; i < byte_cnt; i++) { 26579aebddd1SJeff Kirsher req->snd_buff[i] = (u8)(pattern >> (j*8)); 26589aebddd1SJeff Kirsher j++; 26599aebddd1SJeff Kirsher if (j > 7) 26609aebddd1SJeff Kirsher j = 0; 26619aebddd1SJeff Kirsher } 26629aebddd1SJeff Kirsher 26639aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 26649aebddd1SJeff Kirsher 26659aebddd1SJeff Kirsher if (!status) { 26669aebddd1SJeff Kirsher struct be_cmd_resp_ddrdma_test *resp; 266703d28ffeSKalesh AP 26689aebddd1SJeff Kirsher resp = cmd->va; 26699aebddd1SJeff Kirsher if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) || 26709aebddd1SJeff Kirsher resp->snd_err) { 26719aebddd1SJeff Kirsher status = -1; 26729aebddd1SJeff Kirsher } 26739aebddd1SJeff Kirsher } 26749aebddd1SJeff Kirsher 26759aebddd1SJeff Kirsher err: 26769aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 26779aebddd1SJeff Kirsher return status; 26789aebddd1SJeff Kirsher } 26799aebddd1SJeff Kirsher 26809aebddd1SJeff Kirsher int be_cmd_get_seeprom_data(struct be_adapter *adapter, 26819aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 26829aebddd1SJeff Kirsher { 26839aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 26849aebddd1SJeff Kirsher struct be_cmd_req_seeprom_read *req; 26859aebddd1SJeff Kirsher int status; 26869aebddd1SJeff Kirsher 26879aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 26889aebddd1SJeff Kirsher 26899aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 26909aebddd1SJeff Kirsher if (!wrb) { 26919aebddd1SJeff Kirsher status = -EBUSY; 26929aebddd1SJeff Kirsher goto err; 26939aebddd1SJeff Kirsher } 26949aebddd1SJeff Kirsher req = nonemb_cmd->va; 26959aebddd1SJeff Kirsher 2696106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2697106df1e3SSomnath Kotur OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb, 2698106df1e3SSomnath Kotur nonemb_cmd); 26999aebddd1SJeff Kirsher 27009aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 27019aebddd1SJeff Kirsher 27029aebddd1SJeff Kirsher err: 27039aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 27049aebddd1SJeff Kirsher return status; 27059aebddd1SJeff Kirsher } 27069aebddd1SJeff Kirsher 270742f11cf2SAjit Khaparde int be_cmd_get_phy_info(struct be_adapter *adapter) 27089aebddd1SJeff Kirsher { 27099aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 27109aebddd1SJeff Kirsher struct be_cmd_req_get_phy_info *req; 27119aebddd1SJeff Kirsher struct be_dma_mem cmd; 27129aebddd1SJeff Kirsher int status; 27139aebddd1SJeff Kirsher 2714f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS, 2715f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 2716f25b119cSPadmanabh Ratnakar return -EPERM; 2717f25b119cSPadmanabh Ratnakar 27189aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 27199aebddd1SJeff Kirsher 27209aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 27219aebddd1SJeff Kirsher if (!wrb) { 27229aebddd1SJeff Kirsher status = -EBUSY; 27239aebddd1SJeff Kirsher goto err; 27249aebddd1SJeff Kirsher } 27259aebddd1SJeff Kirsher cmd.size = sizeof(struct be_cmd_req_get_phy_info); 2726a2cc4e0bSSathya Perla cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 27279aebddd1SJeff Kirsher if (!cmd.va) { 27289aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); 27299aebddd1SJeff Kirsher status = -ENOMEM; 27309aebddd1SJeff Kirsher goto err; 27319aebddd1SJeff Kirsher } 27329aebddd1SJeff Kirsher 27339aebddd1SJeff Kirsher req = cmd.va; 27349aebddd1SJeff Kirsher 2735106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2736106df1e3SSomnath Kotur OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req), 2737106df1e3SSomnath Kotur wrb, &cmd); 27389aebddd1SJeff Kirsher 27399aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 27409aebddd1SJeff Kirsher if (!status) { 27419aebddd1SJeff Kirsher struct be_phy_info *resp_phy_info = 27429aebddd1SJeff Kirsher cmd.va + sizeof(struct be_cmd_req_hdr); 274303d28ffeSKalesh AP 274442f11cf2SAjit Khaparde adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type); 274542f11cf2SAjit Khaparde adapter->phy.interface_type = 27469aebddd1SJeff Kirsher le16_to_cpu(resp_phy_info->interface_type); 274742f11cf2SAjit Khaparde adapter->phy.auto_speeds_supported = 274842f11cf2SAjit Khaparde le16_to_cpu(resp_phy_info->auto_speeds_supported); 274942f11cf2SAjit Khaparde adapter->phy.fixed_speeds_supported = 275042f11cf2SAjit Khaparde le16_to_cpu(resp_phy_info->fixed_speeds_supported); 275142f11cf2SAjit Khaparde adapter->phy.misc_params = 275242f11cf2SAjit Khaparde le32_to_cpu(resp_phy_info->misc_params); 275368cb7e47SVasundhara Volam 275468cb7e47SVasundhara Volam if (BE2_chip(adapter)) { 275568cb7e47SVasundhara Volam adapter->phy.fixed_speeds_supported = 275668cb7e47SVasundhara Volam BE_SUPPORTED_SPEED_10GBPS | 275768cb7e47SVasundhara Volam BE_SUPPORTED_SPEED_1GBPS; 275868cb7e47SVasundhara Volam } 27599aebddd1SJeff Kirsher } 2760a2cc4e0bSSathya Perla pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 27619aebddd1SJeff Kirsher err: 27629aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 27639aebddd1SJeff Kirsher return status; 27649aebddd1SJeff Kirsher } 27659aebddd1SJeff Kirsher 2766bc0ee163SLad, Prabhakar static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain) 27679aebddd1SJeff Kirsher { 27689aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 27699aebddd1SJeff Kirsher struct be_cmd_req_set_qos *req; 27709aebddd1SJeff Kirsher int status; 27719aebddd1SJeff Kirsher 27729aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 27739aebddd1SJeff Kirsher 27749aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 27759aebddd1SJeff Kirsher if (!wrb) { 27769aebddd1SJeff Kirsher status = -EBUSY; 27779aebddd1SJeff Kirsher goto err; 27789aebddd1SJeff Kirsher } 27799aebddd1SJeff Kirsher 27809aebddd1SJeff Kirsher req = embedded_payload(wrb); 27819aebddd1SJeff Kirsher 2782106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2783106df1e3SSomnath Kotur OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL); 27849aebddd1SJeff Kirsher 27859aebddd1SJeff Kirsher req->hdr.domain = domain; 27869aebddd1SJeff Kirsher req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC); 27879aebddd1SJeff Kirsher req->max_bps_nic = cpu_to_le32(bps); 27889aebddd1SJeff Kirsher 27899aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 27909aebddd1SJeff Kirsher 27919aebddd1SJeff Kirsher err: 27929aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 27939aebddd1SJeff Kirsher return status; 27949aebddd1SJeff Kirsher } 27959aebddd1SJeff Kirsher 27969aebddd1SJeff Kirsher int be_cmd_get_cntl_attributes(struct be_adapter *adapter) 27979aebddd1SJeff Kirsher { 27989aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 27999aebddd1SJeff Kirsher struct be_cmd_req_cntl_attribs *req; 28009aebddd1SJeff Kirsher struct be_cmd_resp_cntl_attribs *resp; 28019aebddd1SJeff Kirsher int status; 28029aebddd1SJeff Kirsher int payload_len = max(sizeof(*req), sizeof(*resp)); 28039aebddd1SJeff Kirsher struct mgmt_controller_attrib *attribs; 28049aebddd1SJeff Kirsher struct be_dma_mem attribs_cmd; 28059aebddd1SJeff Kirsher 2806d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 2807d98ef50fSSuresh Reddy return -1; 2808d98ef50fSSuresh Reddy 28099aebddd1SJeff Kirsher memset(&attribs_cmd, 0, sizeof(struct be_dma_mem)); 28109aebddd1SJeff Kirsher attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs); 28119aebddd1SJeff Kirsher attribs_cmd.va = pci_alloc_consistent(adapter->pdev, attribs_cmd.size, 28129aebddd1SJeff Kirsher &attribs_cmd.dma); 28139aebddd1SJeff Kirsher if (!attribs_cmd.va) { 2814a2cc4e0bSSathya Perla dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); 2815d98ef50fSSuresh Reddy status = -ENOMEM; 2816d98ef50fSSuresh Reddy goto err; 28179aebddd1SJeff Kirsher } 28189aebddd1SJeff Kirsher 28199aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 28209aebddd1SJeff Kirsher if (!wrb) { 28219aebddd1SJeff Kirsher status = -EBUSY; 28229aebddd1SJeff Kirsher goto err; 28239aebddd1SJeff Kirsher } 28249aebddd1SJeff Kirsher req = attribs_cmd.va; 28259aebddd1SJeff Kirsher 2826106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2827a2cc4e0bSSathya Perla OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len, 2828a2cc4e0bSSathya Perla wrb, &attribs_cmd); 28299aebddd1SJeff Kirsher 28309aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 28319aebddd1SJeff Kirsher if (!status) { 28329aebddd1SJeff Kirsher attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr); 28339aebddd1SJeff Kirsher adapter->hba_port_num = attribs->hba_attribs.phy_port; 28349aebddd1SJeff Kirsher } 28359aebddd1SJeff Kirsher 28369aebddd1SJeff Kirsher err: 28379aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 2838d98ef50fSSuresh Reddy if (attribs_cmd.va) 2839d98ef50fSSuresh Reddy pci_free_consistent(adapter->pdev, attribs_cmd.size, 2840d98ef50fSSuresh Reddy attribs_cmd.va, attribs_cmd.dma); 28419aebddd1SJeff Kirsher return status; 28429aebddd1SJeff Kirsher } 28439aebddd1SJeff Kirsher 28449aebddd1SJeff Kirsher /* Uses mbox */ 28459aebddd1SJeff Kirsher int be_cmd_req_native_mode(struct be_adapter *adapter) 28469aebddd1SJeff Kirsher { 28479aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 28489aebddd1SJeff Kirsher struct be_cmd_req_set_func_cap *req; 28499aebddd1SJeff Kirsher int status; 28509aebddd1SJeff Kirsher 28519aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 28529aebddd1SJeff Kirsher return -1; 28539aebddd1SJeff Kirsher 28549aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 28559aebddd1SJeff Kirsher if (!wrb) { 28569aebddd1SJeff Kirsher status = -EBUSY; 28579aebddd1SJeff Kirsher goto err; 28589aebddd1SJeff Kirsher } 28599aebddd1SJeff Kirsher 28609aebddd1SJeff Kirsher req = embedded_payload(wrb); 28619aebddd1SJeff Kirsher 2862106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2863a2cc4e0bSSathya Perla OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP, 2864a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 28659aebddd1SJeff Kirsher 28669aebddd1SJeff Kirsher req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS | 28679aebddd1SJeff Kirsher CAPABILITY_BE3_NATIVE_ERX_API); 28689aebddd1SJeff Kirsher req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API); 28699aebddd1SJeff Kirsher 28709aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 28719aebddd1SJeff Kirsher if (!status) { 28729aebddd1SJeff Kirsher struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb); 287303d28ffeSKalesh AP 28749aebddd1SJeff Kirsher adapter->be3_native = le32_to_cpu(resp->cap_flags) & 28759aebddd1SJeff Kirsher CAPABILITY_BE3_NATIVE_ERX_API; 2876d379142bSSathya Perla if (!adapter->be3_native) 2877d379142bSSathya Perla dev_warn(&adapter->pdev->dev, 2878d379142bSSathya Perla "adapter not in advanced mode\n"); 28799aebddd1SJeff Kirsher } 28809aebddd1SJeff Kirsher err: 28819aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 28829aebddd1SJeff Kirsher return status; 28839aebddd1SJeff Kirsher } 2884590c391dSPadmanabh Ratnakar 2885f25b119cSPadmanabh Ratnakar /* Get privilege(s) for a function */ 2886f25b119cSPadmanabh Ratnakar int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, 2887f25b119cSPadmanabh Ratnakar u32 domain) 2888f25b119cSPadmanabh Ratnakar { 2889f25b119cSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 2890f25b119cSPadmanabh Ratnakar struct be_cmd_req_get_fn_privileges *req; 2891f25b119cSPadmanabh Ratnakar int status; 2892f25b119cSPadmanabh Ratnakar 2893f25b119cSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 2894f25b119cSPadmanabh Ratnakar 2895f25b119cSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 2896f25b119cSPadmanabh Ratnakar if (!wrb) { 2897f25b119cSPadmanabh Ratnakar status = -EBUSY; 2898f25b119cSPadmanabh Ratnakar goto err; 2899f25b119cSPadmanabh Ratnakar } 2900f25b119cSPadmanabh Ratnakar 2901f25b119cSPadmanabh Ratnakar req = embedded_payload(wrb); 2902f25b119cSPadmanabh Ratnakar 2903f25b119cSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2904f25b119cSPadmanabh Ratnakar OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req), 2905f25b119cSPadmanabh Ratnakar wrb, NULL); 2906f25b119cSPadmanabh Ratnakar 2907f25b119cSPadmanabh Ratnakar req->hdr.domain = domain; 2908f25b119cSPadmanabh Ratnakar 2909f25b119cSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 2910f25b119cSPadmanabh Ratnakar if (!status) { 2911f25b119cSPadmanabh Ratnakar struct be_cmd_resp_get_fn_privileges *resp = 2912f25b119cSPadmanabh Ratnakar embedded_payload(wrb); 291303d28ffeSKalesh AP 2914f25b119cSPadmanabh Ratnakar *privilege = le32_to_cpu(resp->privilege_mask); 291502308d74SSuresh Reddy 291602308d74SSuresh Reddy /* In UMC mode FW does not return right privileges. 291702308d74SSuresh Reddy * Override with correct privilege equivalent to PF. 291802308d74SSuresh Reddy */ 291902308d74SSuresh Reddy if (BEx_chip(adapter) && be_is_mc(adapter) && 292002308d74SSuresh Reddy be_physfn(adapter)) 292102308d74SSuresh Reddy *privilege = MAX_PRIVILEGES; 2922f25b119cSPadmanabh Ratnakar } 2923f25b119cSPadmanabh Ratnakar 2924f25b119cSPadmanabh Ratnakar err: 2925f25b119cSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 2926f25b119cSPadmanabh Ratnakar return status; 2927f25b119cSPadmanabh Ratnakar } 2928f25b119cSPadmanabh Ratnakar 292904a06028SSathya Perla /* Set privilege(s) for a function */ 293004a06028SSathya Perla int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, 293104a06028SSathya Perla u32 domain) 293204a06028SSathya Perla { 293304a06028SSathya Perla struct be_mcc_wrb *wrb; 293404a06028SSathya Perla struct be_cmd_req_set_fn_privileges *req; 293504a06028SSathya Perla int status; 293604a06028SSathya Perla 293704a06028SSathya Perla spin_lock_bh(&adapter->mcc_lock); 293804a06028SSathya Perla 293904a06028SSathya Perla wrb = wrb_from_mccq(adapter); 294004a06028SSathya Perla if (!wrb) { 294104a06028SSathya Perla status = -EBUSY; 294204a06028SSathya Perla goto err; 294304a06028SSathya Perla } 294404a06028SSathya Perla 294504a06028SSathya Perla req = embedded_payload(wrb); 294604a06028SSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 294704a06028SSathya Perla OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req), 294804a06028SSathya Perla wrb, NULL); 294904a06028SSathya Perla req->hdr.domain = domain; 295004a06028SSathya Perla if (lancer_chip(adapter)) 295104a06028SSathya Perla req->privileges_lancer = cpu_to_le32(privileges); 295204a06028SSathya Perla else 295304a06028SSathya Perla req->privileges = cpu_to_le32(privileges); 295404a06028SSathya Perla 295504a06028SSathya Perla status = be_mcc_notify_wait(adapter); 295604a06028SSathya Perla err: 295704a06028SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 295804a06028SSathya Perla return status; 295904a06028SSathya Perla } 296004a06028SSathya Perla 29615a712c13SSathya Perla /* pmac_id_valid: true => pmac_id is supplied and MAC address is requested. 29625a712c13SSathya Perla * pmac_id_valid: false => pmac_id or MAC address is requested. 29635a712c13SSathya Perla * If pmac_id is returned, pmac_id_valid is returned as true 29645a712c13SSathya Perla */ 29651578e777SPadmanabh Ratnakar int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, 2966b188f090SSuresh Reddy bool *pmac_id_valid, u32 *pmac_id, u32 if_handle, 2967b188f090SSuresh Reddy u8 domain) 2968590c391dSPadmanabh Ratnakar { 2969590c391dSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 2970590c391dSPadmanabh Ratnakar struct be_cmd_req_get_mac_list *req; 2971590c391dSPadmanabh Ratnakar int status; 2972590c391dSPadmanabh Ratnakar int mac_count; 2973e5e1ee89SPadmanabh Ratnakar struct be_dma_mem get_mac_list_cmd; 2974e5e1ee89SPadmanabh Ratnakar int i; 2975e5e1ee89SPadmanabh Ratnakar 2976e5e1ee89SPadmanabh Ratnakar memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem)); 2977e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list); 2978e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev, 2979e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.size, 2980e5e1ee89SPadmanabh Ratnakar &get_mac_list_cmd.dma); 2981e5e1ee89SPadmanabh Ratnakar 2982e5e1ee89SPadmanabh Ratnakar if (!get_mac_list_cmd.va) { 2983e5e1ee89SPadmanabh Ratnakar dev_err(&adapter->pdev->dev, 2984e5e1ee89SPadmanabh Ratnakar "Memory allocation failure during GET_MAC_LIST\n"); 2985e5e1ee89SPadmanabh Ratnakar return -ENOMEM; 2986e5e1ee89SPadmanabh Ratnakar } 2987590c391dSPadmanabh Ratnakar 2988590c391dSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 2989590c391dSPadmanabh Ratnakar 2990590c391dSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 2991590c391dSPadmanabh Ratnakar if (!wrb) { 2992590c391dSPadmanabh Ratnakar status = -EBUSY; 2993e5e1ee89SPadmanabh Ratnakar goto out; 2994590c391dSPadmanabh Ratnakar } 2995e5e1ee89SPadmanabh Ratnakar 2996e5e1ee89SPadmanabh Ratnakar req = get_mac_list_cmd.va; 2997590c391dSPadmanabh Ratnakar 2998590c391dSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2999bf591f51SSathya Perla OPCODE_COMMON_GET_MAC_LIST, 3000bf591f51SSathya Perla get_mac_list_cmd.size, wrb, &get_mac_list_cmd); 3001590c391dSPadmanabh Ratnakar req->hdr.domain = domain; 3002e5e1ee89SPadmanabh Ratnakar req->mac_type = MAC_ADDRESS_TYPE_NETWORK; 30035a712c13SSathya Perla if (*pmac_id_valid) { 30045a712c13SSathya Perla req->mac_id = cpu_to_le32(*pmac_id); 3005b188f090SSuresh Reddy req->iface_id = cpu_to_le16(if_handle); 30065a712c13SSathya Perla req->perm_override = 0; 30075a712c13SSathya Perla } else { 3008e5e1ee89SPadmanabh Ratnakar req->perm_override = 1; 30095a712c13SSathya Perla } 3010590c391dSPadmanabh Ratnakar 3011590c391dSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 3012590c391dSPadmanabh Ratnakar if (!status) { 3013590c391dSPadmanabh Ratnakar struct be_cmd_resp_get_mac_list *resp = 3014e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va; 30155a712c13SSathya Perla 30165a712c13SSathya Perla if (*pmac_id_valid) { 30175a712c13SSathya Perla memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr, 30185a712c13SSathya Perla ETH_ALEN); 30195a712c13SSathya Perla goto out; 30205a712c13SSathya Perla } 30215a712c13SSathya Perla 3022e5e1ee89SPadmanabh Ratnakar mac_count = resp->true_mac_count + resp->pseudo_mac_count; 3023e5e1ee89SPadmanabh Ratnakar /* Mac list returned could contain one or more active mac_ids 3024dbedd44eSJoe Perches * or one or more true or pseudo permanent mac addresses. 30251578e777SPadmanabh Ratnakar * If an active mac_id is present, return first active mac_id 30261578e777SPadmanabh Ratnakar * found. 3027e5e1ee89SPadmanabh Ratnakar */ 3028590c391dSPadmanabh Ratnakar for (i = 0; i < mac_count; i++) { 3029e5e1ee89SPadmanabh Ratnakar struct get_list_macaddr *mac_entry; 3030e5e1ee89SPadmanabh Ratnakar u16 mac_addr_size; 3031e5e1ee89SPadmanabh Ratnakar u32 mac_id; 3032e5e1ee89SPadmanabh Ratnakar 3033e5e1ee89SPadmanabh Ratnakar mac_entry = &resp->macaddr_list[i]; 3034e5e1ee89SPadmanabh Ratnakar mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size); 3035e5e1ee89SPadmanabh Ratnakar /* mac_id is a 32 bit value and mac_addr size 3036e5e1ee89SPadmanabh Ratnakar * is 6 bytes 3037e5e1ee89SPadmanabh Ratnakar */ 3038e5e1ee89SPadmanabh Ratnakar if (mac_addr_size == sizeof(u32)) { 30395a712c13SSathya Perla *pmac_id_valid = true; 3040e5e1ee89SPadmanabh Ratnakar mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; 3041e5e1ee89SPadmanabh Ratnakar *pmac_id = le32_to_cpu(mac_id); 3042e5e1ee89SPadmanabh Ratnakar goto out; 3043590c391dSPadmanabh Ratnakar } 3044590c391dSPadmanabh Ratnakar } 30451578e777SPadmanabh Ratnakar /* If no active mac_id found, return first mac addr */ 30465a712c13SSathya Perla *pmac_id_valid = false; 3047e5e1ee89SPadmanabh Ratnakar memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, 3048e5e1ee89SPadmanabh Ratnakar ETH_ALEN); 3049590c391dSPadmanabh Ratnakar } 3050590c391dSPadmanabh Ratnakar 3051e5e1ee89SPadmanabh Ratnakar out: 3052590c391dSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 3053e5e1ee89SPadmanabh Ratnakar pci_free_consistent(adapter->pdev, get_mac_list_cmd.size, 3054e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va, get_mac_list_cmd.dma); 3055590c391dSPadmanabh Ratnakar return status; 3056590c391dSPadmanabh Ratnakar } 3057590c391dSPadmanabh Ratnakar 3058a2cc4e0bSSathya Perla int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id, 3059a2cc4e0bSSathya Perla u8 *mac, u32 if_handle, bool active, u32 domain) 30605a712c13SSathya Perla { 3061b188f090SSuresh Reddy if (!active) 3062b188f090SSuresh Reddy be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id, 3063b188f090SSuresh Reddy if_handle, domain); 30643175d8c2SSathya Perla if (BEx_chip(adapter)) 30655a712c13SSathya Perla return be_cmd_mac_addr_query(adapter, mac, false, 3066b188f090SSuresh Reddy if_handle, curr_pmac_id); 30673175d8c2SSathya Perla else 30683175d8c2SSathya Perla /* Fetch the MAC address using pmac_id */ 30693175d8c2SSathya Perla return be_cmd_get_mac_from_list(adapter, mac, &active, 3070b188f090SSuresh Reddy &curr_pmac_id, 3071b188f090SSuresh Reddy if_handle, domain); 30725a712c13SSathya Perla } 30735a712c13SSathya Perla 307495046b92SSathya Perla int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac) 307595046b92SSathya Perla { 307695046b92SSathya Perla int status; 307795046b92SSathya Perla bool pmac_valid = false; 307895046b92SSathya Perla 3079c7bf7169SJoe Perches eth_zero_addr(mac); 308095046b92SSathya Perla 30813175d8c2SSathya Perla if (BEx_chip(adapter)) { 30823175d8c2SSathya Perla if (be_physfn(adapter)) 30833175d8c2SSathya Perla status = be_cmd_mac_addr_query(adapter, mac, true, 0, 30843175d8c2SSathya Perla 0); 308595046b92SSathya Perla else 308695046b92SSathya Perla status = be_cmd_mac_addr_query(adapter, mac, false, 308795046b92SSathya Perla adapter->if_handle, 0); 30883175d8c2SSathya Perla } else { 30893175d8c2SSathya Perla status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid, 3090b188f090SSuresh Reddy NULL, adapter->if_handle, 0); 30913175d8c2SSathya Perla } 30923175d8c2SSathya Perla 309395046b92SSathya Perla return status; 309495046b92SSathya Perla } 309595046b92SSathya Perla 3096590c391dSPadmanabh Ratnakar /* Uses synchronous MCCQ */ 3097590c391dSPadmanabh Ratnakar int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, 3098590c391dSPadmanabh Ratnakar u8 mac_count, u32 domain) 3099590c391dSPadmanabh Ratnakar { 3100590c391dSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3101590c391dSPadmanabh Ratnakar struct be_cmd_req_set_mac_list *req; 3102590c391dSPadmanabh Ratnakar int status; 3103590c391dSPadmanabh Ratnakar struct be_dma_mem cmd; 3104590c391dSPadmanabh Ratnakar 3105590c391dSPadmanabh Ratnakar memset(&cmd, 0, sizeof(struct be_dma_mem)); 3106590c391dSPadmanabh Ratnakar cmd.size = sizeof(struct be_cmd_req_set_mac_list); 3107590c391dSPadmanabh Ratnakar cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, 3108590c391dSPadmanabh Ratnakar &cmd.dma, GFP_KERNEL); 3109d0320f75SJoe Perches if (!cmd.va) 3110590c391dSPadmanabh Ratnakar return -ENOMEM; 3111590c391dSPadmanabh Ratnakar 3112590c391dSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 3113590c391dSPadmanabh Ratnakar 3114590c391dSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 3115590c391dSPadmanabh Ratnakar if (!wrb) { 3116590c391dSPadmanabh Ratnakar status = -EBUSY; 3117590c391dSPadmanabh Ratnakar goto err; 3118590c391dSPadmanabh Ratnakar } 3119590c391dSPadmanabh Ratnakar 3120590c391dSPadmanabh Ratnakar req = cmd.va; 3121590c391dSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3122590c391dSPadmanabh Ratnakar OPCODE_COMMON_SET_MAC_LIST, sizeof(*req), 3123590c391dSPadmanabh Ratnakar wrb, &cmd); 3124590c391dSPadmanabh Ratnakar 3125590c391dSPadmanabh Ratnakar req->hdr.domain = domain; 3126590c391dSPadmanabh Ratnakar req->mac_count = mac_count; 3127590c391dSPadmanabh Ratnakar if (mac_count) 3128590c391dSPadmanabh Ratnakar memcpy(req->mac, mac_array, ETH_ALEN*mac_count); 3129590c391dSPadmanabh Ratnakar 3130590c391dSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 3131590c391dSPadmanabh Ratnakar 3132590c391dSPadmanabh Ratnakar err: 3133a2cc4e0bSSathya Perla dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); 3134590c391dSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 3135590c391dSPadmanabh Ratnakar return status; 3136590c391dSPadmanabh Ratnakar } 31374762f6ceSAjit Khaparde 31383175d8c2SSathya Perla /* Wrapper to delete any active MACs and provision the new mac. 31393175d8c2SSathya Perla * Changes to MAC_LIST are allowed iff none of the MAC addresses in the 31403175d8c2SSathya Perla * current list are active. 31413175d8c2SSathya Perla */ 31423175d8c2SSathya Perla int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom) 31433175d8c2SSathya Perla { 31443175d8c2SSathya Perla bool active_mac = false; 31453175d8c2SSathya Perla u8 old_mac[ETH_ALEN]; 31463175d8c2SSathya Perla u32 pmac_id; 31473175d8c2SSathya Perla int status; 31483175d8c2SSathya Perla 31493175d8c2SSathya Perla status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac, 3150b188f090SSuresh Reddy &pmac_id, if_id, dom); 3151b188f090SSuresh Reddy 31523175d8c2SSathya Perla if (!status && active_mac) 31533175d8c2SSathya Perla be_cmd_pmac_del(adapter, if_id, pmac_id, dom); 31543175d8c2SSathya Perla 31553175d8c2SSathya Perla return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom); 31563175d8c2SSathya Perla } 31573175d8c2SSathya Perla 3158f1f3ee1bSAjit Khaparde int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, 3159e7bcbd7bSKalesh AP u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk) 3160f1f3ee1bSAjit Khaparde { 3161f1f3ee1bSAjit Khaparde struct be_mcc_wrb *wrb; 3162f1f3ee1bSAjit Khaparde struct be_cmd_req_set_hsw_config *req; 3163f1f3ee1bSAjit Khaparde void *ctxt; 3164f1f3ee1bSAjit Khaparde int status; 3165f1f3ee1bSAjit Khaparde 3166f1f3ee1bSAjit Khaparde spin_lock_bh(&adapter->mcc_lock); 3167f1f3ee1bSAjit Khaparde 3168f1f3ee1bSAjit Khaparde wrb = wrb_from_mccq(adapter); 3169f1f3ee1bSAjit Khaparde if (!wrb) { 3170f1f3ee1bSAjit Khaparde status = -EBUSY; 3171f1f3ee1bSAjit Khaparde goto err; 3172f1f3ee1bSAjit Khaparde } 3173f1f3ee1bSAjit Khaparde 3174f1f3ee1bSAjit Khaparde req = embedded_payload(wrb); 3175f1f3ee1bSAjit Khaparde ctxt = &req->context; 3176f1f3ee1bSAjit Khaparde 3177f1f3ee1bSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3178a2cc4e0bSSathya Perla OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb, 3179a2cc4e0bSSathya Perla NULL); 3180f1f3ee1bSAjit Khaparde 3181f1f3ee1bSAjit Khaparde req->hdr.domain = domain; 3182f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id); 3183f1f3ee1bSAjit Khaparde if (pvid) { 3184f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1); 3185f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid); 3186f1f3ee1bSAjit Khaparde } 3187a77dcb8cSAjit Khaparde if (!BEx_chip(adapter) && hsw_mode) { 3188a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, 3189a77dcb8cSAjit Khaparde ctxt, adapter->hba_port_num); 3190a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1); 3191a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type, 3192a77dcb8cSAjit Khaparde ctxt, hsw_mode); 3193a77dcb8cSAjit Khaparde } 3194f1f3ee1bSAjit Khaparde 3195e7bcbd7bSKalesh AP /* Enable/disable both mac and vlan spoof checking */ 3196e7bcbd7bSKalesh AP if (!BEx_chip(adapter) && spoofchk) { 3197e7bcbd7bSKalesh AP AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk, 3198e7bcbd7bSKalesh AP ctxt, spoofchk); 3199e7bcbd7bSKalesh AP AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk, 3200e7bcbd7bSKalesh AP ctxt, spoofchk); 3201e7bcbd7bSKalesh AP } 3202e7bcbd7bSKalesh AP 3203f1f3ee1bSAjit Khaparde be_dws_cpu_to_le(req->context, sizeof(req->context)); 3204f1f3ee1bSAjit Khaparde status = be_mcc_notify_wait(adapter); 3205f1f3ee1bSAjit Khaparde 3206f1f3ee1bSAjit Khaparde err: 3207f1f3ee1bSAjit Khaparde spin_unlock_bh(&adapter->mcc_lock); 3208f1f3ee1bSAjit Khaparde return status; 3209f1f3ee1bSAjit Khaparde } 3210f1f3ee1bSAjit Khaparde 3211f1f3ee1bSAjit Khaparde /* Get Hyper switch config */ 3212f1f3ee1bSAjit Khaparde int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, 3213e7bcbd7bSKalesh AP u32 domain, u16 intf_id, u8 *mode, bool *spoofchk) 3214f1f3ee1bSAjit Khaparde { 3215f1f3ee1bSAjit Khaparde struct be_mcc_wrb *wrb; 3216f1f3ee1bSAjit Khaparde struct be_cmd_req_get_hsw_config *req; 3217f1f3ee1bSAjit Khaparde void *ctxt; 3218f1f3ee1bSAjit Khaparde int status; 3219f1f3ee1bSAjit Khaparde u16 vid; 3220f1f3ee1bSAjit Khaparde 3221f1f3ee1bSAjit Khaparde spin_lock_bh(&adapter->mcc_lock); 3222f1f3ee1bSAjit Khaparde 3223f1f3ee1bSAjit Khaparde wrb = wrb_from_mccq(adapter); 3224f1f3ee1bSAjit Khaparde if (!wrb) { 3225f1f3ee1bSAjit Khaparde status = -EBUSY; 3226f1f3ee1bSAjit Khaparde goto err; 3227f1f3ee1bSAjit Khaparde } 3228f1f3ee1bSAjit Khaparde 3229f1f3ee1bSAjit Khaparde req = embedded_payload(wrb); 3230f1f3ee1bSAjit Khaparde ctxt = &req->context; 3231f1f3ee1bSAjit Khaparde 3232f1f3ee1bSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3233a2cc4e0bSSathya Perla OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb, 3234a2cc4e0bSSathya Perla NULL); 3235f1f3ee1bSAjit Khaparde 3236f1f3ee1bSAjit Khaparde req->hdr.domain = domain; 3237a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, 3238a77dcb8cSAjit Khaparde ctxt, intf_id); 3239f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1); 3240a77dcb8cSAjit Khaparde 32412c07c1d7SVasundhara Volam if (!BEx_chip(adapter) && mode) { 3242a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, 3243a77dcb8cSAjit Khaparde ctxt, adapter->hba_port_num); 3244a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1); 3245a77dcb8cSAjit Khaparde } 3246f1f3ee1bSAjit Khaparde be_dws_cpu_to_le(req->context, sizeof(req->context)); 3247f1f3ee1bSAjit Khaparde 3248f1f3ee1bSAjit Khaparde status = be_mcc_notify_wait(adapter); 3249f1f3ee1bSAjit Khaparde if (!status) { 3250f1f3ee1bSAjit Khaparde struct be_cmd_resp_get_hsw_config *resp = 3251f1f3ee1bSAjit Khaparde embedded_payload(wrb); 325203d28ffeSKalesh AP 3253a2cc4e0bSSathya Perla be_dws_le_to_cpu(&resp->context, sizeof(resp->context)); 3254f1f3ee1bSAjit Khaparde vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3255f1f3ee1bSAjit Khaparde pvid, &resp->context); 3256a77dcb8cSAjit Khaparde if (pvid) 3257f1f3ee1bSAjit Khaparde *pvid = le16_to_cpu(vid); 3258a77dcb8cSAjit Khaparde if (mode) 3259a77dcb8cSAjit Khaparde *mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3260a77dcb8cSAjit Khaparde port_fwd_type, &resp->context); 3261e7bcbd7bSKalesh AP if (spoofchk) 3262e7bcbd7bSKalesh AP *spoofchk = 3263e7bcbd7bSKalesh AP AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3264e7bcbd7bSKalesh AP spoofchk, &resp->context); 3265f1f3ee1bSAjit Khaparde } 3266f1f3ee1bSAjit Khaparde 3267f1f3ee1bSAjit Khaparde err: 3268f1f3ee1bSAjit Khaparde spin_unlock_bh(&adapter->mcc_lock); 3269f1f3ee1bSAjit Khaparde return status; 3270f1f3ee1bSAjit Khaparde } 3271f1f3ee1bSAjit Khaparde 3272f7062ee5SSathya Perla static bool be_is_wol_excluded(struct be_adapter *adapter) 3273f7062ee5SSathya Perla { 3274f7062ee5SSathya Perla struct pci_dev *pdev = adapter->pdev; 3275f7062ee5SSathya Perla 327618c57c74SKalesh AP if (be_virtfn(adapter)) 3277f7062ee5SSathya Perla return true; 3278f7062ee5SSathya Perla 3279f7062ee5SSathya Perla switch (pdev->subsystem_device) { 3280f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID1: 3281f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID2: 3282f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID3: 3283f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID4: 3284f7062ee5SSathya Perla return true; 3285f7062ee5SSathya Perla default: 3286f7062ee5SSathya Perla return false; 3287f7062ee5SSathya Perla } 3288f7062ee5SSathya Perla } 3289f7062ee5SSathya Perla 32904762f6ceSAjit Khaparde int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) 32914762f6ceSAjit Khaparde { 32924762f6ceSAjit Khaparde struct be_mcc_wrb *wrb; 32934762f6ceSAjit Khaparde struct be_cmd_req_acpi_wol_magic_config_v1 *req; 329476a9e08eSSuresh Reddy int status = 0; 32954762f6ceSAjit Khaparde struct be_dma_mem cmd; 32964762f6ceSAjit Khaparde 3297f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, 3298f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH)) 3299f25b119cSPadmanabh Ratnakar return -EPERM; 3300f25b119cSPadmanabh Ratnakar 330176a9e08eSSuresh Reddy if (be_is_wol_excluded(adapter)) 330276a9e08eSSuresh Reddy return status; 330376a9e08eSSuresh Reddy 3304d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 3305d98ef50fSSuresh Reddy return -1; 3306d98ef50fSSuresh Reddy 33074762f6ceSAjit Khaparde memset(&cmd, 0, sizeof(struct be_dma_mem)); 33084762f6ceSAjit Khaparde cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); 3309a2cc4e0bSSathya Perla cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 33104762f6ceSAjit Khaparde if (!cmd.va) { 3311a2cc4e0bSSathya Perla dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); 3312d98ef50fSSuresh Reddy status = -ENOMEM; 3313d98ef50fSSuresh Reddy goto err; 33144762f6ceSAjit Khaparde } 33154762f6ceSAjit Khaparde 33164762f6ceSAjit Khaparde wrb = wrb_from_mbox(adapter); 33174762f6ceSAjit Khaparde if (!wrb) { 33184762f6ceSAjit Khaparde status = -EBUSY; 33194762f6ceSAjit Khaparde goto err; 33204762f6ceSAjit Khaparde } 33214762f6ceSAjit Khaparde 33224762f6ceSAjit Khaparde req = cmd.va; 33234762f6ceSAjit Khaparde 33244762f6ceSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 33254762f6ceSAjit Khaparde OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, 332676a9e08eSSuresh Reddy sizeof(*req), wrb, &cmd); 33274762f6ceSAjit Khaparde 33284762f6ceSAjit Khaparde req->hdr.version = 1; 33294762f6ceSAjit Khaparde req->query_options = BE_GET_WOL_CAP; 33304762f6ceSAjit Khaparde 33314762f6ceSAjit Khaparde status = be_mbox_notify_wait(adapter); 33324762f6ceSAjit Khaparde if (!status) { 33334762f6ceSAjit Khaparde struct be_cmd_resp_acpi_wol_magic_config_v1 *resp; 333403d28ffeSKalesh AP 33354762f6ceSAjit Khaparde resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va; 33364762f6ceSAjit Khaparde 33374762f6ceSAjit Khaparde adapter->wol_cap = resp->wol_settings; 333876a9e08eSSuresh Reddy if (adapter->wol_cap & BE_WOL_CAP) 333976a9e08eSSuresh Reddy adapter->wol_en = true; 33404762f6ceSAjit Khaparde } 33414762f6ceSAjit Khaparde err: 33424762f6ceSAjit Khaparde mutex_unlock(&adapter->mbox_lock); 3343d98ef50fSSuresh Reddy if (cmd.va) 33444762f6ceSAjit Khaparde pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 33454762f6ceSAjit Khaparde return status; 3346941a77d5SSomnath Kotur 3347941a77d5SSomnath Kotur } 3348baaa08d1SVasundhara Volam 3349baaa08d1SVasundhara Volam int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level) 3350baaa08d1SVasundhara Volam { 3351baaa08d1SVasundhara Volam struct be_dma_mem extfat_cmd; 3352baaa08d1SVasundhara Volam struct be_fat_conf_params *cfgs; 3353baaa08d1SVasundhara Volam int status; 3354baaa08d1SVasundhara Volam int i, j; 3355baaa08d1SVasundhara Volam 3356baaa08d1SVasundhara Volam memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); 3357baaa08d1SVasundhara Volam extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); 3358baaa08d1SVasundhara Volam extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size, 3359baaa08d1SVasundhara Volam &extfat_cmd.dma); 3360baaa08d1SVasundhara Volam if (!extfat_cmd.va) 3361baaa08d1SVasundhara Volam return -ENOMEM; 3362baaa08d1SVasundhara Volam 3363baaa08d1SVasundhara Volam status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd); 3364baaa08d1SVasundhara Volam if (status) 3365baaa08d1SVasundhara Volam goto err; 3366baaa08d1SVasundhara Volam 3367baaa08d1SVasundhara Volam cfgs = (struct be_fat_conf_params *) 3368baaa08d1SVasundhara Volam (extfat_cmd.va + sizeof(struct be_cmd_resp_hdr)); 3369baaa08d1SVasundhara Volam for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) { 3370baaa08d1SVasundhara Volam u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes); 337103d28ffeSKalesh AP 3372baaa08d1SVasundhara Volam for (j = 0; j < num_modes; j++) { 3373baaa08d1SVasundhara Volam if (cfgs->module[i].trace_lvl[j].mode == MODE_UART) 3374baaa08d1SVasundhara Volam cfgs->module[i].trace_lvl[j].dbg_lvl = 3375baaa08d1SVasundhara Volam cpu_to_le32(level); 3376baaa08d1SVasundhara Volam } 3377baaa08d1SVasundhara Volam } 3378baaa08d1SVasundhara Volam 3379baaa08d1SVasundhara Volam status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs); 3380baaa08d1SVasundhara Volam err: 3381baaa08d1SVasundhara Volam pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va, 3382baaa08d1SVasundhara Volam extfat_cmd.dma); 3383baaa08d1SVasundhara Volam return status; 3384baaa08d1SVasundhara Volam } 3385baaa08d1SVasundhara Volam 3386baaa08d1SVasundhara Volam int be_cmd_get_fw_log_level(struct be_adapter *adapter) 3387baaa08d1SVasundhara Volam { 3388baaa08d1SVasundhara Volam struct be_dma_mem extfat_cmd; 3389baaa08d1SVasundhara Volam struct be_fat_conf_params *cfgs; 3390baaa08d1SVasundhara Volam int status, j; 3391baaa08d1SVasundhara Volam int level = 0; 3392baaa08d1SVasundhara Volam 3393baaa08d1SVasundhara Volam memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); 3394baaa08d1SVasundhara Volam extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); 3395baaa08d1SVasundhara Volam extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size, 3396baaa08d1SVasundhara Volam &extfat_cmd.dma); 3397baaa08d1SVasundhara Volam 3398baaa08d1SVasundhara Volam if (!extfat_cmd.va) { 3399baaa08d1SVasundhara Volam dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n", 3400baaa08d1SVasundhara Volam __func__); 3401baaa08d1SVasundhara Volam goto err; 3402baaa08d1SVasundhara Volam } 3403baaa08d1SVasundhara Volam 3404baaa08d1SVasundhara Volam status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd); 3405baaa08d1SVasundhara Volam if (!status) { 3406baaa08d1SVasundhara Volam cfgs = (struct be_fat_conf_params *)(extfat_cmd.va + 3407baaa08d1SVasundhara Volam sizeof(struct be_cmd_resp_hdr)); 340803d28ffeSKalesh AP 3409baaa08d1SVasundhara Volam for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) { 3410baaa08d1SVasundhara Volam if (cfgs->module[0].trace_lvl[j].mode == MODE_UART) 3411baaa08d1SVasundhara Volam level = cfgs->module[0].trace_lvl[j].dbg_lvl; 3412baaa08d1SVasundhara Volam } 3413baaa08d1SVasundhara Volam } 3414baaa08d1SVasundhara Volam pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va, 3415baaa08d1SVasundhara Volam extfat_cmd.dma); 3416baaa08d1SVasundhara Volam err: 3417baaa08d1SVasundhara Volam return level; 3418baaa08d1SVasundhara Volam } 3419baaa08d1SVasundhara Volam 3420941a77d5SSomnath Kotur int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter, 3421941a77d5SSomnath Kotur struct be_dma_mem *cmd) 3422941a77d5SSomnath Kotur { 3423941a77d5SSomnath Kotur struct be_mcc_wrb *wrb; 3424941a77d5SSomnath Kotur struct be_cmd_req_get_ext_fat_caps *req; 3425941a77d5SSomnath Kotur int status; 3426941a77d5SSomnath Kotur 3427941a77d5SSomnath Kotur if (mutex_lock_interruptible(&adapter->mbox_lock)) 3428941a77d5SSomnath Kotur return -1; 3429941a77d5SSomnath Kotur 3430941a77d5SSomnath Kotur wrb = wrb_from_mbox(adapter); 3431941a77d5SSomnath Kotur if (!wrb) { 3432941a77d5SSomnath Kotur status = -EBUSY; 3433941a77d5SSomnath Kotur goto err; 3434941a77d5SSomnath Kotur } 3435941a77d5SSomnath Kotur 3436941a77d5SSomnath Kotur req = cmd->va; 3437941a77d5SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3438941a77d5SSomnath Kotur OPCODE_COMMON_GET_EXT_FAT_CAPABILITES, 3439941a77d5SSomnath Kotur cmd->size, wrb, cmd); 3440941a77d5SSomnath Kotur req->parameter_type = cpu_to_le32(1); 3441941a77d5SSomnath Kotur 3442941a77d5SSomnath Kotur status = be_mbox_notify_wait(adapter); 3443941a77d5SSomnath Kotur err: 3444941a77d5SSomnath Kotur mutex_unlock(&adapter->mbox_lock); 3445941a77d5SSomnath Kotur return status; 3446941a77d5SSomnath Kotur } 3447941a77d5SSomnath Kotur 3448941a77d5SSomnath Kotur int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, 3449941a77d5SSomnath Kotur struct be_dma_mem *cmd, 3450941a77d5SSomnath Kotur struct be_fat_conf_params *configs) 3451941a77d5SSomnath Kotur { 3452941a77d5SSomnath Kotur struct be_mcc_wrb *wrb; 3453941a77d5SSomnath Kotur struct be_cmd_req_set_ext_fat_caps *req; 3454941a77d5SSomnath Kotur int status; 3455941a77d5SSomnath Kotur 3456941a77d5SSomnath Kotur spin_lock_bh(&adapter->mcc_lock); 3457941a77d5SSomnath Kotur 3458941a77d5SSomnath Kotur wrb = wrb_from_mccq(adapter); 3459941a77d5SSomnath Kotur if (!wrb) { 3460941a77d5SSomnath Kotur status = -EBUSY; 3461941a77d5SSomnath Kotur goto err; 3462941a77d5SSomnath Kotur } 3463941a77d5SSomnath Kotur 3464941a77d5SSomnath Kotur req = cmd->va; 3465941a77d5SSomnath Kotur memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params)); 3466941a77d5SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3467941a77d5SSomnath Kotur OPCODE_COMMON_SET_EXT_FAT_CAPABILITES, 3468941a77d5SSomnath Kotur cmd->size, wrb, cmd); 3469941a77d5SSomnath Kotur 3470941a77d5SSomnath Kotur status = be_mcc_notify_wait(adapter); 3471941a77d5SSomnath Kotur err: 3472941a77d5SSomnath Kotur spin_unlock_bh(&adapter->mcc_lock); 3473941a77d5SSomnath Kotur return status; 34744762f6ceSAjit Khaparde } 34756a4ab669SParav Pandit 347621252377SVasundhara Volam int be_cmd_query_port_name(struct be_adapter *adapter) 3477b4e32a71SPadmanabh Ratnakar { 3478b4e32a71SPadmanabh Ratnakar struct be_cmd_req_get_port_name *req; 347921252377SVasundhara Volam struct be_mcc_wrb *wrb; 3480b4e32a71SPadmanabh Ratnakar int status; 3481b4e32a71SPadmanabh Ratnakar 348221252377SVasundhara Volam if (mutex_lock_interruptible(&adapter->mbox_lock)) 348321252377SVasundhara Volam return -1; 3484b4e32a71SPadmanabh Ratnakar 348521252377SVasundhara Volam wrb = wrb_from_mbox(adapter); 3486b4e32a71SPadmanabh Ratnakar req = embedded_payload(wrb); 3487b4e32a71SPadmanabh Ratnakar 3488b4e32a71SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3489b4e32a71SPadmanabh Ratnakar OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb, 3490b4e32a71SPadmanabh Ratnakar NULL); 349121252377SVasundhara Volam if (!BEx_chip(adapter)) 3492b4e32a71SPadmanabh Ratnakar req->hdr.version = 1; 3493b4e32a71SPadmanabh Ratnakar 349421252377SVasundhara Volam status = be_mbox_notify_wait(adapter); 3495b4e32a71SPadmanabh Ratnakar if (!status) { 3496b4e32a71SPadmanabh Ratnakar struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb); 349703d28ffeSKalesh AP 349821252377SVasundhara Volam adapter->port_name = resp->port_name[adapter->hba_port_num]; 3499b4e32a71SPadmanabh Ratnakar } else { 350021252377SVasundhara Volam adapter->port_name = adapter->hba_port_num + '0'; 3501b4e32a71SPadmanabh Ratnakar } 350221252377SVasundhara Volam 350321252377SVasundhara Volam mutex_unlock(&adapter->mbox_lock); 3504b4e32a71SPadmanabh Ratnakar return status; 3505b4e32a71SPadmanabh Ratnakar } 3506b4e32a71SPadmanabh Ratnakar 350710cccf60SVasundhara Volam /* Descriptor type */ 350810cccf60SVasundhara Volam enum { 350910cccf60SVasundhara Volam FUNC_DESC = 1, 351010cccf60SVasundhara Volam VFT_DESC = 2 351110cccf60SVasundhara Volam }; 351210cccf60SVasundhara Volam 351310cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count, 351410cccf60SVasundhara Volam int desc_type) 3515abb93951SPadmanabh Ratnakar { 3516150d58c7SVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 351710cccf60SVasundhara Volam struct be_nic_res_desc *nic; 3518abb93951SPadmanabh Ratnakar int i; 3519abb93951SPadmanabh Ratnakar 3520abb93951SPadmanabh Ratnakar for (i = 0; i < desc_count; i++) { 3521150d58c7SVasundhara Volam if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 || 352210cccf60SVasundhara Volam hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) { 352310cccf60SVasundhara Volam nic = (struct be_nic_res_desc *)hdr; 352410cccf60SVasundhara Volam if (desc_type == FUNC_DESC || 352510cccf60SVasundhara Volam (desc_type == VFT_DESC && 352610cccf60SVasundhara Volam nic->flags & (1 << VFT_SHIFT))) 352710cccf60SVasundhara Volam return nic; 352810cccf60SVasundhara Volam } 3529150d58c7SVasundhara Volam 3530150d58c7SVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 3531150d58c7SVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 3532150d58c7SVasundhara Volam } 3533950e2958SWei Yang return NULL; 3534abb93951SPadmanabh Ratnakar } 3535abb93951SPadmanabh Ratnakar 353610cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count) 353710cccf60SVasundhara Volam { 353810cccf60SVasundhara Volam return be_get_nic_desc(buf, desc_count, VFT_DESC); 353910cccf60SVasundhara Volam } 354010cccf60SVasundhara Volam 354110cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count) 354210cccf60SVasundhara Volam { 354310cccf60SVasundhara Volam return be_get_nic_desc(buf, desc_count, FUNC_DESC); 354410cccf60SVasundhara Volam } 354510cccf60SVasundhara Volam 3546150d58c7SVasundhara Volam static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf, 3547150d58c7SVasundhara Volam u32 desc_count) 3548150d58c7SVasundhara Volam { 3549150d58c7SVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 3550150d58c7SVasundhara Volam struct be_pcie_res_desc *pcie; 3551150d58c7SVasundhara Volam int i; 3552150d58c7SVasundhara Volam 3553150d58c7SVasundhara Volam for (i = 0; i < desc_count; i++) { 3554150d58c7SVasundhara Volam if ((hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 || 3555150d58c7SVasundhara Volam hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1)) { 3556150d58c7SVasundhara Volam pcie = (struct be_pcie_res_desc *)hdr; 3557150d58c7SVasundhara Volam if (pcie->pf_num == devfn) 3558150d58c7SVasundhara Volam return pcie; 3559150d58c7SVasundhara Volam } 3560150d58c7SVasundhara Volam 3561150d58c7SVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 3562150d58c7SVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 3563150d58c7SVasundhara Volam } 3564abb93951SPadmanabh Ratnakar return NULL; 3565abb93951SPadmanabh Ratnakar } 3566abb93951SPadmanabh Ratnakar 3567f93f160bSVasundhara Volam static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count) 3568f93f160bSVasundhara Volam { 3569f93f160bSVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 3570f93f160bSVasundhara Volam int i; 3571f93f160bSVasundhara Volam 3572f93f160bSVasundhara Volam for (i = 0; i < desc_count; i++) { 3573f93f160bSVasundhara Volam if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1) 3574f93f160bSVasundhara Volam return (struct be_port_res_desc *)hdr; 3575f93f160bSVasundhara Volam 3576f93f160bSVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 3577f93f160bSVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 3578f93f160bSVasundhara Volam } 3579f93f160bSVasundhara Volam return NULL; 3580f93f160bSVasundhara Volam } 3581f93f160bSVasundhara Volam 358292bf14abSSathya Perla static void be_copy_nic_desc(struct be_resources *res, 358392bf14abSSathya Perla struct be_nic_res_desc *desc) 358492bf14abSSathya Perla { 358592bf14abSSathya Perla res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count); 358692bf14abSSathya Perla res->max_vlans = le16_to_cpu(desc->vlan_count); 358792bf14abSSathya Perla res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count); 358892bf14abSSathya Perla res->max_tx_qs = le16_to_cpu(desc->txq_count); 358992bf14abSSathya Perla res->max_rss_qs = le16_to_cpu(desc->rssq_count); 359092bf14abSSathya Perla res->max_rx_qs = le16_to_cpu(desc->rq_count); 359192bf14abSSathya Perla res->max_evt_qs = le16_to_cpu(desc->eq_count); 3592f2858738SVasundhara Volam res->max_cq_count = le16_to_cpu(desc->cq_count); 3593f2858738SVasundhara Volam res->max_iface_count = le16_to_cpu(desc->iface_count); 3594f2858738SVasundhara Volam res->max_mcc_count = le16_to_cpu(desc->mcc_count); 359592bf14abSSathya Perla /* Clear flags that driver is not interested in */ 359692bf14abSSathya Perla res->if_cap_flags = le32_to_cpu(desc->cap_flags) & 359792bf14abSSathya Perla BE_IF_CAP_FLAGS_WANT; 359892bf14abSSathya Perla } 359992bf14abSSathya Perla 3600abb93951SPadmanabh Ratnakar /* Uses Mbox */ 360192bf14abSSathya Perla int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) 3602abb93951SPadmanabh Ratnakar { 3603abb93951SPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3604abb93951SPadmanabh Ratnakar struct be_cmd_req_get_func_config *req; 3605abb93951SPadmanabh Ratnakar int status; 3606abb93951SPadmanabh Ratnakar struct be_dma_mem cmd; 3607abb93951SPadmanabh Ratnakar 3608d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 3609d98ef50fSSuresh Reddy return -1; 3610d98ef50fSSuresh Reddy 3611abb93951SPadmanabh Ratnakar memset(&cmd, 0, sizeof(struct be_dma_mem)); 3612abb93951SPadmanabh Ratnakar cmd.size = sizeof(struct be_cmd_resp_get_func_config); 3613a2cc4e0bSSathya Perla cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 3614abb93951SPadmanabh Ratnakar if (!cmd.va) { 3615abb93951SPadmanabh Ratnakar dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); 3616d98ef50fSSuresh Reddy status = -ENOMEM; 3617d98ef50fSSuresh Reddy goto err; 3618abb93951SPadmanabh Ratnakar } 3619abb93951SPadmanabh Ratnakar 3620abb93951SPadmanabh Ratnakar wrb = wrb_from_mbox(adapter); 3621abb93951SPadmanabh Ratnakar if (!wrb) { 3622abb93951SPadmanabh Ratnakar status = -EBUSY; 3623abb93951SPadmanabh Ratnakar goto err; 3624abb93951SPadmanabh Ratnakar } 3625abb93951SPadmanabh Ratnakar 3626abb93951SPadmanabh Ratnakar req = cmd.va; 3627abb93951SPadmanabh Ratnakar 3628abb93951SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3629abb93951SPadmanabh Ratnakar OPCODE_COMMON_GET_FUNC_CONFIG, 3630abb93951SPadmanabh Ratnakar cmd.size, wrb, &cmd); 3631abb93951SPadmanabh Ratnakar 363228710c55SKalesh AP if (skyhawk_chip(adapter)) 363328710c55SKalesh AP req->hdr.version = 1; 363428710c55SKalesh AP 3635abb93951SPadmanabh Ratnakar status = be_mbox_notify_wait(adapter); 3636abb93951SPadmanabh Ratnakar if (!status) { 3637abb93951SPadmanabh Ratnakar struct be_cmd_resp_get_func_config *resp = cmd.va; 3638abb93951SPadmanabh Ratnakar u32 desc_count = le32_to_cpu(resp->desc_count); 3639150d58c7SVasundhara Volam struct be_nic_res_desc *desc; 3640abb93951SPadmanabh Ratnakar 364110cccf60SVasundhara Volam desc = be_get_func_nic_desc(resp->func_param, desc_count); 3642abb93951SPadmanabh Ratnakar if (!desc) { 3643abb93951SPadmanabh Ratnakar status = -EINVAL; 3644abb93951SPadmanabh Ratnakar goto err; 3645abb93951SPadmanabh Ratnakar } 3646abb93951SPadmanabh Ratnakar 3647d5c18473SPadmanabh Ratnakar adapter->pf_number = desc->pf_num; 364892bf14abSSathya Perla be_copy_nic_desc(res, desc); 3649abb93951SPadmanabh Ratnakar } 3650abb93951SPadmanabh Ratnakar err: 3651abb93951SPadmanabh Ratnakar mutex_unlock(&adapter->mbox_lock); 3652d98ef50fSSuresh Reddy if (cmd.va) 3653d98ef50fSSuresh Reddy pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 3654abb93951SPadmanabh Ratnakar return status; 3655abb93951SPadmanabh Ratnakar } 3656abb93951SPadmanabh Ratnakar 3657ba48c0c9SVasundhara Volam /* Will use MBOX only if MCCQ has not been created */ 365892bf14abSSathya Perla int be_cmd_get_profile_config(struct be_adapter *adapter, 3659f2858738SVasundhara Volam struct be_resources *res, u8 query, u8 domain) 3660a05f99dbSVasundhara Volam { 3661150d58c7SVasundhara Volam struct be_cmd_resp_get_profile_config *resp; 3662ba48c0c9SVasundhara Volam struct be_cmd_req_get_profile_config *req; 366310cccf60SVasundhara Volam struct be_nic_res_desc *vf_res; 3664150d58c7SVasundhara Volam struct be_pcie_res_desc *pcie; 3665f93f160bSVasundhara Volam struct be_port_res_desc *port; 3666150d58c7SVasundhara Volam struct be_nic_res_desc *nic; 3667ba48c0c9SVasundhara Volam struct be_mcc_wrb wrb = {0}; 3668a05f99dbSVasundhara Volam struct be_dma_mem cmd; 3669f2858738SVasundhara Volam u16 desc_count; 3670a05f99dbSVasundhara Volam int status; 3671a05f99dbSVasundhara Volam 3672a05f99dbSVasundhara Volam memset(&cmd, 0, sizeof(struct be_dma_mem)); 3673a05f99dbSVasundhara Volam cmd.size = sizeof(struct be_cmd_resp_get_profile_config); 3674150d58c7SVasundhara Volam cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 3675150d58c7SVasundhara Volam if (!cmd.va) 3676a05f99dbSVasundhara Volam return -ENOMEM; 3677a05f99dbSVasundhara Volam 3678ba48c0c9SVasundhara Volam req = cmd.va; 3679ba48c0c9SVasundhara Volam be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3680ba48c0c9SVasundhara Volam OPCODE_COMMON_GET_PROFILE_CONFIG, 3681ba48c0c9SVasundhara Volam cmd.size, &wrb, &cmd); 3682ba48c0c9SVasundhara Volam 3683ba48c0c9SVasundhara Volam req->hdr.domain = domain; 3684ba48c0c9SVasundhara Volam if (!lancer_chip(adapter)) 3685ba48c0c9SVasundhara Volam req->hdr.version = 1; 3686ba48c0c9SVasundhara Volam req->type = ACTIVE_PROFILE_TYPE; 3687ba48c0c9SVasundhara Volam 3688f2858738SVasundhara Volam /* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the 3689f2858738SVasundhara Volam * descriptors with all bits set to "1" for the fields which can be 3690f2858738SVasundhara Volam * modified using SET_PROFILE_CONFIG cmd. 3691f2858738SVasundhara Volam */ 3692f2858738SVasundhara Volam if (query == RESOURCE_MODIFIABLE) 3693f2858738SVasundhara Volam req->type |= QUERY_MODIFIABLE_FIELDS_TYPE; 3694f2858738SVasundhara Volam 3695ba48c0c9SVasundhara Volam status = be_cmd_notify_wait(adapter, &wrb); 3696150d58c7SVasundhara Volam if (status) 3697abb93951SPadmanabh Ratnakar goto err; 3698150d58c7SVasundhara Volam 3699150d58c7SVasundhara Volam resp = cmd.va; 3700f2858738SVasundhara Volam desc_count = le16_to_cpu(resp->desc_count); 3701150d58c7SVasundhara Volam 3702150d58c7SVasundhara Volam pcie = be_get_pcie_desc(adapter->pdev->devfn, resp->func_param, 3703150d58c7SVasundhara Volam desc_count); 3704150d58c7SVasundhara Volam if (pcie) 370592bf14abSSathya Perla res->max_vfs = le16_to_cpu(pcie->num_vfs); 3706150d58c7SVasundhara Volam 3707f93f160bSVasundhara Volam port = be_get_port_desc(resp->func_param, desc_count); 3708f93f160bSVasundhara Volam if (port) 3709f93f160bSVasundhara Volam adapter->mc_type = port->mc_type; 3710f93f160bSVasundhara Volam 371110cccf60SVasundhara Volam nic = be_get_func_nic_desc(resp->func_param, desc_count); 371292bf14abSSathya Perla if (nic) 371392bf14abSSathya Perla be_copy_nic_desc(res, nic); 371492bf14abSSathya Perla 371510cccf60SVasundhara Volam vf_res = be_get_vft_desc(resp->func_param, desc_count); 371610cccf60SVasundhara Volam if (vf_res) 371710cccf60SVasundhara Volam res->vf_if_cap_flags = vf_res->cap_flags; 3718abb93951SPadmanabh Ratnakar err: 3719a05f99dbSVasundhara Volam if (cmd.va) 3720150d58c7SVasundhara Volam pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 3721abb93951SPadmanabh Ratnakar return status; 3722abb93951SPadmanabh Ratnakar } 3723abb93951SPadmanabh Ratnakar 3724bec84e6bSVasundhara Volam /* Will use MBOX only if MCCQ has not been created */ 3725bec84e6bSVasundhara Volam static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc, 3726bec84e6bSVasundhara Volam int size, int count, u8 version, u8 domain) 3727d5c18473SPadmanabh Ratnakar { 3728d5c18473SPadmanabh Ratnakar struct be_cmd_req_set_profile_config *req; 3729bec84e6bSVasundhara Volam struct be_mcc_wrb wrb = {0}; 3730bec84e6bSVasundhara Volam struct be_dma_mem cmd; 3731d5c18473SPadmanabh Ratnakar int status; 3732d5c18473SPadmanabh Ratnakar 3733bec84e6bSVasundhara Volam memset(&cmd, 0, sizeof(struct be_dma_mem)); 3734bec84e6bSVasundhara Volam cmd.size = sizeof(struct be_cmd_req_set_profile_config); 3735bec84e6bSVasundhara Volam cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); 3736bec84e6bSVasundhara Volam if (!cmd.va) 3737bec84e6bSVasundhara Volam return -ENOMEM; 3738d5c18473SPadmanabh Ratnakar 3739bec84e6bSVasundhara Volam req = cmd.va; 3740d5c18473SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3741bec84e6bSVasundhara Volam OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size, 3742bec84e6bSVasundhara Volam &wrb, &cmd); 3743a401801cSSathya Perla req->hdr.version = version; 3744d5c18473SPadmanabh Ratnakar req->hdr.domain = domain; 3745bec84e6bSVasundhara Volam req->desc_count = cpu_to_le32(count); 3746a401801cSSathya Perla memcpy(req->desc, desc, size); 3747d5c18473SPadmanabh Ratnakar 3748bec84e6bSVasundhara Volam status = be_cmd_notify_wait(adapter, &wrb); 3749bec84e6bSVasundhara Volam 3750bec84e6bSVasundhara Volam if (cmd.va) 3751bec84e6bSVasundhara Volam pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); 3752d5c18473SPadmanabh Ratnakar return status; 3753d5c18473SPadmanabh Ratnakar } 3754d5c18473SPadmanabh Ratnakar 3755a401801cSSathya Perla /* Mark all fields invalid */ 3756bec84e6bSVasundhara Volam static void be_reset_nic_desc(struct be_nic_res_desc *nic) 3757a401801cSSathya Perla { 3758a401801cSSathya Perla memset(nic, 0, sizeof(*nic)); 3759a401801cSSathya Perla nic->unicast_mac_count = 0xFFFF; 3760a401801cSSathya Perla nic->mcc_count = 0xFFFF; 3761a401801cSSathya Perla nic->vlan_count = 0xFFFF; 3762a401801cSSathya Perla nic->mcast_mac_count = 0xFFFF; 3763a401801cSSathya Perla nic->txq_count = 0xFFFF; 3764a401801cSSathya Perla nic->rq_count = 0xFFFF; 3765a401801cSSathya Perla nic->rssq_count = 0xFFFF; 3766a401801cSSathya Perla nic->lro_count = 0xFFFF; 3767a401801cSSathya Perla nic->cq_count = 0xFFFF; 3768a401801cSSathya Perla nic->toe_conn_count = 0xFFFF; 3769a401801cSSathya Perla nic->eq_count = 0xFFFF; 37700f77ba73SRavikumar Nelavelli nic->iface_count = 0xFFFF; 3771a401801cSSathya Perla nic->link_param = 0xFF; 37720f77ba73SRavikumar Nelavelli nic->channel_id_param = cpu_to_le16(0xF000); 3773a401801cSSathya Perla nic->acpi_params = 0xFF; 3774a401801cSSathya Perla nic->wol_param = 0x0F; 37750f77ba73SRavikumar Nelavelli nic->tunnel_iface_count = 0xFFFF; 37760f77ba73SRavikumar Nelavelli nic->direct_tenant_iface_count = 0xFFFF; 3777bec84e6bSVasundhara Volam nic->bw_min = 0xFFFFFFFF; 3778a401801cSSathya Perla nic->bw_max = 0xFFFFFFFF; 3779a401801cSSathya Perla } 3780a401801cSSathya Perla 3781bec84e6bSVasundhara Volam /* Mark all fields invalid */ 3782bec84e6bSVasundhara Volam static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie) 3783bec84e6bSVasundhara Volam { 3784bec84e6bSVasundhara Volam memset(pcie, 0, sizeof(*pcie)); 3785bec84e6bSVasundhara Volam pcie->sriov_state = 0xFF; 3786bec84e6bSVasundhara Volam pcie->pf_state = 0xFF; 3787bec84e6bSVasundhara Volam pcie->pf_type = 0xFF; 3788bec84e6bSVasundhara Volam pcie->num_vfs = 0xFFFF; 3789bec84e6bSVasundhara Volam } 3790bec84e6bSVasundhara Volam 37910f77ba73SRavikumar Nelavelli int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed, 37920f77ba73SRavikumar Nelavelli u8 domain) 3793a401801cSSathya Perla { 3794a401801cSSathya Perla struct be_nic_res_desc nic_desc; 37950f77ba73SRavikumar Nelavelli u32 bw_percent; 37960f77ba73SRavikumar Nelavelli u16 version = 0; 37970f77ba73SRavikumar Nelavelli 37980f77ba73SRavikumar Nelavelli if (BE3_chip(adapter)) 37990f77ba73SRavikumar Nelavelli return be_cmd_set_qos(adapter, max_rate / 10, domain); 3800a401801cSSathya Perla 3801a401801cSSathya Perla be_reset_nic_desc(&nic_desc); 38020f77ba73SRavikumar Nelavelli nic_desc.pf_num = adapter->pf_number; 38030f77ba73SRavikumar Nelavelli nic_desc.vf_num = domain; 380458bdeaa6SKalesh AP nic_desc.bw_min = 0; 38050f77ba73SRavikumar Nelavelli if (lancer_chip(adapter)) { 3806a401801cSSathya Perla nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0; 3807a401801cSSathya Perla nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0; 3808a401801cSSathya Perla nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) | 3809a401801cSSathya Perla (1 << NOSV_SHIFT); 38100f77ba73SRavikumar Nelavelli nic_desc.bw_max = cpu_to_le32(max_rate / 10); 38110f77ba73SRavikumar Nelavelli } else { 38120f77ba73SRavikumar Nelavelli version = 1; 38130f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1; 38140f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 38150f77ba73SRavikumar Nelavelli nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT); 38160f77ba73SRavikumar Nelavelli bw_percent = max_rate ? (max_rate * 100) / link_speed : 100; 38170f77ba73SRavikumar Nelavelli nic_desc.bw_max = cpu_to_le32(bw_percent); 38180f77ba73SRavikumar Nelavelli } 3819a401801cSSathya Perla 3820a401801cSSathya Perla return be_cmd_set_profile_config(adapter, &nic_desc, 38210f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_len, 3822bec84e6bSVasundhara Volam 1, version, domain); 3823bec84e6bSVasundhara Volam } 3824bec84e6bSVasundhara Volam 3825f2858738SVasundhara Volam static void be_fill_vf_res_template(struct be_adapter *adapter, 3826f2858738SVasundhara Volam struct be_resources pool_res, 3827f2858738SVasundhara Volam u16 num_vfs, u16 num_vf_qs, 3828f2858738SVasundhara Volam struct be_nic_res_desc *nic_vft) 3829f2858738SVasundhara Volam { 3830f2858738SVasundhara Volam u32 vf_if_cap_flags = pool_res.vf_if_cap_flags; 3831f2858738SVasundhara Volam struct be_resources res_mod = {0}; 3832f2858738SVasundhara Volam 3833f2858738SVasundhara Volam /* Resource with fields set to all '1's by GET_PROFILE_CONFIG cmd, 3834f2858738SVasundhara Volam * which are modifiable using SET_PROFILE_CONFIG cmd. 3835f2858738SVasundhara Volam */ 3836f2858738SVasundhara Volam be_cmd_get_profile_config(adapter, &res_mod, RESOURCE_MODIFIABLE, 0); 3837f2858738SVasundhara Volam 3838f2858738SVasundhara Volam /* If RSS IFACE capability flags are modifiable for a VF, set the 3839f2858738SVasundhara Volam * capability flag as valid and set RSS and DEFQ_RSS IFACE flags if 3840f2858738SVasundhara Volam * more than 1 RSSQ is available for a VF. 3841f2858738SVasundhara Volam * Otherwise, provision only 1 queue pair for VF. 3842f2858738SVasundhara Volam */ 3843f2858738SVasundhara Volam if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_RSS) { 3844f2858738SVasundhara Volam nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT); 3845f2858738SVasundhara Volam if (num_vf_qs > 1) { 3846f2858738SVasundhara Volam vf_if_cap_flags |= BE_IF_FLAGS_RSS; 3847f2858738SVasundhara Volam if (pool_res.if_cap_flags & BE_IF_FLAGS_DEFQ_RSS) 3848f2858738SVasundhara Volam vf_if_cap_flags |= BE_IF_FLAGS_DEFQ_RSS; 3849f2858738SVasundhara Volam } else { 3850f2858738SVasundhara Volam vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS | 3851f2858738SVasundhara Volam BE_IF_FLAGS_DEFQ_RSS); 3852f2858738SVasundhara Volam } 3853f2858738SVasundhara Volam 3854f2858738SVasundhara Volam nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags); 3855f2858738SVasundhara Volam } else { 3856f2858738SVasundhara Volam num_vf_qs = 1; 3857f2858738SVasundhara Volam } 3858f2858738SVasundhara Volam 3859f2858738SVasundhara Volam nic_vft->rq_count = cpu_to_le16(num_vf_qs); 3860f2858738SVasundhara Volam nic_vft->txq_count = cpu_to_le16(num_vf_qs); 3861f2858738SVasundhara Volam nic_vft->rssq_count = cpu_to_le16(num_vf_qs); 3862f2858738SVasundhara Volam nic_vft->cq_count = cpu_to_le16(pool_res.max_cq_count / 3863f2858738SVasundhara Volam (num_vfs + 1)); 3864f2858738SVasundhara Volam 3865f2858738SVasundhara Volam /* Distribute unicast MACs, VLANs, IFACE count and MCCQ count equally 3866f2858738SVasundhara Volam * among the PF and it's VFs, if the fields are changeable 3867f2858738SVasundhara Volam */ 3868f2858738SVasundhara Volam if (res_mod.max_uc_mac == FIELD_MODIFIABLE) 3869f2858738SVasundhara Volam nic_vft->unicast_mac_count = cpu_to_le16(pool_res.max_uc_mac / 3870f2858738SVasundhara Volam (num_vfs + 1)); 3871f2858738SVasundhara Volam 3872f2858738SVasundhara Volam if (res_mod.max_vlans == FIELD_MODIFIABLE) 3873f2858738SVasundhara Volam nic_vft->vlan_count = cpu_to_le16(pool_res.max_vlans / 3874f2858738SVasundhara Volam (num_vfs + 1)); 3875f2858738SVasundhara Volam 3876f2858738SVasundhara Volam if (res_mod.max_iface_count == FIELD_MODIFIABLE) 3877f2858738SVasundhara Volam nic_vft->iface_count = cpu_to_le16(pool_res.max_iface_count / 3878f2858738SVasundhara Volam (num_vfs + 1)); 3879f2858738SVasundhara Volam 3880f2858738SVasundhara Volam if (res_mod.max_mcc_count == FIELD_MODIFIABLE) 3881f2858738SVasundhara Volam nic_vft->mcc_count = cpu_to_le16(pool_res.max_mcc_count / 3882f2858738SVasundhara Volam (num_vfs + 1)); 3883f2858738SVasundhara Volam } 3884f2858738SVasundhara Volam 3885bec84e6bSVasundhara Volam int be_cmd_set_sriov_config(struct be_adapter *adapter, 3886f2858738SVasundhara Volam struct be_resources pool_res, u16 num_vfs, 3887f2858738SVasundhara Volam u16 num_vf_qs) 3888bec84e6bSVasundhara Volam { 3889bec84e6bSVasundhara Volam struct { 3890bec84e6bSVasundhara Volam struct be_pcie_res_desc pcie; 3891bec84e6bSVasundhara Volam struct be_nic_res_desc nic_vft; 3892bec84e6bSVasundhara Volam } __packed desc; 3893bec84e6bSVasundhara Volam 3894bec84e6bSVasundhara Volam /* PF PCIE descriptor */ 3895bec84e6bSVasundhara Volam be_reset_pcie_desc(&desc.pcie); 3896bec84e6bSVasundhara Volam desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1; 3897bec84e6bSVasundhara Volam desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 3898f2858738SVasundhara Volam desc.pcie.flags = BIT(IMM_SHIFT) | BIT(NOSV_SHIFT); 3899bec84e6bSVasundhara Volam desc.pcie.pf_num = adapter->pdev->devfn; 3900bec84e6bSVasundhara Volam desc.pcie.sriov_state = num_vfs ? 1 : 0; 3901bec84e6bSVasundhara Volam desc.pcie.num_vfs = cpu_to_le16(num_vfs); 3902bec84e6bSVasundhara Volam 3903bec84e6bSVasundhara Volam /* VF NIC Template descriptor */ 3904bec84e6bSVasundhara Volam be_reset_nic_desc(&desc.nic_vft); 3905bec84e6bSVasundhara Volam desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1; 3906bec84e6bSVasundhara Volam desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 3907f2858738SVasundhara Volam desc.nic_vft.flags = BIT(VFT_SHIFT) | BIT(IMM_SHIFT) | BIT(NOSV_SHIFT); 3908bec84e6bSVasundhara Volam desc.nic_vft.pf_num = adapter->pdev->devfn; 3909bec84e6bSVasundhara Volam desc.nic_vft.vf_num = 0; 3910bec84e6bSVasundhara Volam 3911f2858738SVasundhara Volam be_fill_vf_res_template(adapter, pool_res, num_vfs, num_vf_qs, 3912f2858738SVasundhara Volam &desc.nic_vft); 3913bec84e6bSVasundhara Volam 3914bec84e6bSVasundhara Volam return be_cmd_set_profile_config(adapter, &desc, 3915bec84e6bSVasundhara Volam 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0); 3916a401801cSSathya Perla } 3917a401801cSSathya Perla 3918a401801cSSathya Perla int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) 3919a401801cSSathya Perla { 3920a401801cSSathya Perla struct be_mcc_wrb *wrb; 3921a401801cSSathya Perla struct be_cmd_req_manage_iface_filters *req; 3922a401801cSSathya Perla int status; 3923a401801cSSathya Perla 3924a401801cSSathya Perla if (iface == 0xFFFFFFFF) 3925a401801cSSathya Perla return -1; 3926a401801cSSathya Perla 3927a401801cSSathya Perla spin_lock_bh(&adapter->mcc_lock); 3928a401801cSSathya Perla 3929a401801cSSathya Perla wrb = wrb_from_mccq(adapter); 3930a401801cSSathya Perla if (!wrb) { 3931a401801cSSathya Perla status = -EBUSY; 3932a401801cSSathya Perla goto err; 3933a401801cSSathya Perla } 3934a401801cSSathya Perla req = embedded_payload(wrb); 3935a401801cSSathya Perla 3936a401801cSSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3937a401801cSSathya Perla OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req), 3938a401801cSSathya Perla wrb, NULL); 3939a401801cSSathya Perla req->op = op; 3940a401801cSSathya Perla req->target_iface_id = cpu_to_le32(iface); 3941a401801cSSathya Perla 3942a401801cSSathya Perla status = be_mcc_notify_wait(adapter); 3943a401801cSSathya Perla err: 3944a401801cSSathya Perla spin_unlock_bh(&adapter->mcc_lock); 3945a401801cSSathya Perla return status; 3946a401801cSSathya Perla } 3947a401801cSSathya Perla 3948a401801cSSathya Perla int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port) 3949a401801cSSathya Perla { 3950a401801cSSathya Perla struct be_port_res_desc port_desc; 3951a401801cSSathya Perla 3952a401801cSSathya Perla memset(&port_desc, 0, sizeof(port_desc)); 3953a401801cSSathya Perla port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1; 3954a401801cSSathya Perla port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 3955a401801cSSathya Perla port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT); 3956a401801cSSathya Perla port_desc.link_num = adapter->hba_port_num; 3957a401801cSSathya Perla if (port) { 3958a401801cSSathya Perla port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) | 3959a401801cSSathya Perla (1 << RCVID_SHIFT); 3960a401801cSSathya Perla port_desc.nv_port = swab16(port); 3961a401801cSSathya Perla } else { 3962a401801cSSathya Perla port_desc.nv_flags = NV_TYPE_DISABLED; 3963a401801cSSathya Perla port_desc.nv_port = 0; 3964a401801cSSathya Perla } 3965a401801cSSathya Perla 3966a401801cSSathya Perla return be_cmd_set_profile_config(adapter, &port_desc, 3967bec84e6bSVasundhara Volam RESOURCE_DESC_SIZE_V1, 1, 1, 0); 3968a401801cSSathya Perla } 3969a401801cSSathya Perla 39704c876616SSathya Perla int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, 39714c876616SSathya Perla int vf_num) 39724c876616SSathya Perla { 39734c876616SSathya Perla struct be_mcc_wrb *wrb; 39744c876616SSathya Perla struct be_cmd_req_get_iface_list *req; 39754c876616SSathya Perla struct be_cmd_resp_get_iface_list *resp; 39764c876616SSathya Perla int status; 39774c876616SSathya Perla 39784c876616SSathya Perla spin_lock_bh(&adapter->mcc_lock); 39794c876616SSathya Perla 39804c876616SSathya Perla wrb = wrb_from_mccq(adapter); 39814c876616SSathya Perla if (!wrb) { 39824c876616SSathya Perla status = -EBUSY; 39834c876616SSathya Perla goto err; 39844c876616SSathya Perla } 39854c876616SSathya Perla req = embedded_payload(wrb); 39864c876616SSathya Perla 39874c876616SSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 39884c876616SSathya Perla OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp), 39894c876616SSathya Perla wrb, NULL); 39904c876616SSathya Perla req->hdr.domain = vf_num + 1; 39914c876616SSathya Perla 39924c876616SSathya Perla status = be_mcc_notify_wait(adapter); 39934c876616SSathya Perla if (!status) { 39944c876616SSathya Perla resp = (struct be_cmd_resp_get_iface_list *)req; 39954c876616SSathya Perla vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id); 39964c876616SSathya Perla } 39974c876616SSathya Perla 39984c876616SSathya Perla err: 39994c876616SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 40004c876616SSathya Perla return status; 40014c876616SSathya Perla } 40024c876616SSathya Perla 40035c510811SSomnath Kotur static int lancer_wait_idle(struct be_adapter *adapter) 40045c510811SSomnath Kotur { 40055c510811SSomnath Kotur #define SLIPORT_IDLE_TIMEOUT 30 40065c510811SSomnath Kotur u32 reg_val; 40075c510811SSomnath Kotur int status = 0, i; 40085c510811SSomnath Kotur 40095c510811SSomnath Kotur for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) { 40105c510811SSomnath Kotur reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET); 40115c510811SSomnath Kotur if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0) 40125c510811SSomnath Kotur break; 40135c510811SSomnath Kotur 40145c510811SSomnath Kotur ssleep(1); 40155c510811SSomnath Kotur } 40165c510811SSomnath Kotur 40175c510811SSomnath Kotur if (i == SLIPORT_IDLE_TIMEOUT) 40185c510811SSomnath Kotur status = -1; 40195c510811SSomnath Kotur 40205c510811SSomnath Kotur return status; 40215c510811SSomnath Kotur } 40225c510811SSomnath Kotur 40235c510811SSomnath Kotur int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask) 40245c510811SSomnath Kotur { 40255c510811SSomnath Kotur int status = 0; 40265c510811SSomnath Kotur 40275c510811SSomnath Kotur status = lancer_wait_idle(adapter); 40285c510811SSomnath Kotur if (status) 40295c510811SSomnath Kotur return status; 40305c510811SSomnath Kotur 40315c510811SSomnath Kotur iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET); 40325c510811SSomnath Kotur 40335c510811SSomnath Kotur return status; 40345c510811SSomnath Kotur } 40355c510811SSomnath Kotur 40365c510811SSomnath Kotur /* Routine to check whether dump image is present or not */ 40375c510811SSomnath Kotur bool dump_present(struct be_adapter *adapter) 40385c510811SSomnath Kotur { 40395c510811SSomnath Kotur u32 sliport_status = 0; 40405c510811SSomnath Kotur 40415c510811SSomnath Kotur sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); 40425c510811SSomnath Kotur return !!(sliport_status & SLIPORT_STATUS_DIP_MASK); 40435c510811SSomnath Kotur } 40445c510811SSomnath Kotur 40455c510811SSomnath Kotur int lancer_initiate_dump(struct be_adapter *adapter) 40465c510811SSomnath Kotur { 4047f0613380SKalesh AP struct device *dev = &adapter->pdev->dev; 40485c510811SSomnath Kotur int status; 40495c510811SSomnath Kotur 4050f0613380SKalesh AP if (dump_present(adapter)) { 4051f0613380SKalesh AP dev_info(dev, "Previous dump not cleared, not forcing dump\n"); 4052f0613380SKalesh AP return -EEXIST; 4053f0613380SKalesh AP } 4054f0613380SKalesh AP 40555c510811SSomnath Kotur /* give firmware reset and diagnostic dump */ 40565c510811SSomnath Kotur status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK | 40575c510811SSomnath Kotur PHYSDEV_CONTROL_DD_MASK); 40585c510811SSomnath Kotur if (status < 0) { 4059f0613380SKalesh AP dev_err(dev, "FW reset failed\n"); 40605c510811SSomnath Kotur return status; 40615c510811SSomnath Kotur } 40625c510811SSomnath Kotur 40635c510811SSomnath Kotur status = lancer_wait_idle(adapter); 40645c510811SSomnath Kotur if (status) 40655c510811SSomnath Kotur return status; 40665c510811SSomnath Kotur 40675c510811SSomnath Kotur if (!dump_present(adapter)) { 4068f0613380SKalesh AP dev_err(dev, "FW dump not generated\n"); 4069f0613380SKalesh AP return -EIO; 40705c510811SSomnath Kotur } 40715c510811SSomnath Kotur 40725c510811SSomnath Kotur return 0; 40735c510811SSomnath Kotur } 40745c510811SSomnath Kotur 4075f0613380SKalesh AP int lancer_delete_dump(struct be_adapter *adapter) 4076f0613380SKalesh AP { 4077f0613380SKalesh AP int status; 4078f0613380SKalesh AP 4079f0613380SKalesh AP status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE); 4080f0613380SKalesh AP return be_cmd_status(status); 4081f0613380SKalesh AP } 4082f0613380SKalesh AP 4083dcf7ebbaSPadmanabh Ratnakar /* Uses sync mcc */ 4084dcf7ebbaSPadmanabh Ratnakar int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) 4085dcf7ebbaSPadmanabh Ratnakar { 4086dcf7ebbaSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 4087dcf7ebbaSPadmanabh Ratnakar struct be_cmd_enable_disable_vf *req; 4088dcf7ebbaSPadmanabh Ratnakar int status; 4089dcf7ebbaSPadmanabh Ratnakar 40900599863dSVasundhara Volam if (BEx_chip(adapter)) 4091dcf7ebbaSPadmanabh Ratnakar return 0; 4092dcf7ebbaSPadmanabh Ratnakar 4093dcf7ebbaSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 4094dcf7ebbaSPadmanabh Ratnakar 4095dcf7ebbaSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 4096dcf7ebbaSPadmanabh Ratnakar if (!wrb) { 4097dcf7ebbaSPadmanabh Ratnakar status = -EBUSY; 4098dcf7ebbaSPadmanabh Ratnakar goto err; 4099dcf7ebbaSPadmanabh Ratnakar } 4100dcf7ebbaSPadmanabh Ratnakar 4101dcf7ebbaSPadmanabh Ratnakar req = embedded_payload(wrb); 4102dcf7ebbaSPadmanabh Ratnakar 4103dcf7ebbaSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4104dcf7ebbaSPadmanabh Ratnakar OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req), 4105dcf7ebbaSPadmanabh Ratnakar wrb, NULL); 4106dcf7ebbaSPadmanabh Ratnakar 4107dcf7ebbaSPadmanabh Ratnakar req->hdr.domain = domain; 4108dcf7ebbaSPadmanabh Ratnakar req->enable = 1; 4109dcf7ebbaSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 4110dcf7ebbaSPadmanabh Ratnakar err: 4111dcf7ebbaSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 4112dcf7ebbaSPadmanabh Ratnakar return status; 4113dcf7ebbaSPadmanabh Ratnakar } 4114dcf7ebbaSPadmanabh Ratnakar 411568c45a2dSSomnath Kotur int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable) 411668c45a2dSSomnath Kotur { 411768c45a2dSSomnath Kotur struct be_mcc_wrb *wrb; 411868c45a2dSSomnath Kotur struct be_cmd_req_intr_set *req; 411968c45a2dSSomnath Kotur int status; 412068c45a2dSSomnath Kotur 412168c45a2dSSomnath Kotur if (mutex_lock_interruptible(&adapter->mbox_lock)) 412268c45a2dSSomnath Kotur return -1; 412368c45a2dSSomnath Kotur 412468c45a2dSSomnath Kotur wrb = wrb_from_mbox(adapter); 412568c45a2dSSomnath Kotur 412668c45a2dSSomnath Kotur req = embedded_payload(wrb); 412768c45a2dSSomnath Kotur 412868c45a2dSSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 412968c45a2dSSomnath Kotur OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req), 413068c45a2dSSomnath Kotur wrb, NULL); 413168c45a2dSSomnath Kotur 413268c45a2dSSomnath Kotur req->intr_enabled = intr_enable; 413368c45a2dSSomnath Kotur 413468c45a2dSSomnath Kotur status = be_mbox_notify_wait(adapter); 413568c45a2dSSomnath Kotur 413668c45a2dSSomnath Kotur mutex_unlock(&adapter->mbox_lock); 413768c45a2dSSomnath Kotur return status; 413868c45a2dSSomnath Kotur } 413968c45a2dSSomnath Kotur 4140542963b7SVasundhara Volam /* Uses MBOX */ 4141542963b7SVasundhara Volam int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id) 4142542963b7SVasundhara Volam { 4143542963b7SVasundhara Volam struct be_cmd_req_get_active_profile *req; 4144542963b7SVasundhara Volam struct be_mcc_wrb *wrb; 4145542963b7SVasundhara Volam int status; 4146542963b7SVasundhara Volam 4147542963b7SVasundhara Volam if (mutex_lock_interruptible(&adapter->mbox_lock)) 4148542963b7SVasundhara Volam return -1; 4149542963b7SVasundhara Volam 4150542963b7SVasundhara Volam wrb = wrb_from_mbox(adapter); 4151542963b7SVasundhara Volam if (!wrb) { 4152542963b7SVasundhara Volam status = -EBUSY; 4153542963b7SVasundhara Volam goto err; 4154542963b7SVasundhara Volam } 4155542963b7SVasundhara Volam 4156542963b7SVasundhara Volam req = embedded_payload(wrb); 4157542963b7SVasundhara Volam 4158542963b7SVasundhara Volam be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4159542963b7SVasundhara Volam OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req), 4160542963b7SVasundhara Volam wrb, NULL); 4161542963b7SVasundhara Volam 4162542963b7SVasundhara Volam status = be_mbox_notify_wait(adapter); 4163542963b7SVasundhara Volam if (!status) { 4164542963b7SVasundhara Volam struct be_cmd_resp_get_active_profile *resp = 4165542963b7SVasundhara Volam embedded_payload(wrb); 416603d28ffeSKalesh AP 4167542963b7SVasundhara Volam *profile_id = le16_to_cpu(resp->active_profile_id); 4168542963b7SVasundhara Volam } 4169542963b7SVasundhara Volam 4170542963b7SVasundhara Volam err: 4171542963b7SVasundhara Volam mutex_unlock(&adapter->mbox_lock); 4172542963b7SVasundhara Volam return status; 4173542963b7SVasundhara Volam } 4174542963b7SVasundhara Volam 4175bdce2ad7SSuresh Reddy int be_cmd_set_logical_link_config(struct be_adapter *adapter, 4176bdce2ad7SSuresh Reddy int link_state, u8 domain) 4177bdce2ad7SSuresh Reddy { 4178bdce2ad7SSuresh Reddy struct be_mcc_wrb *wrb; 4179bdce2ad7SSuresh Reddy struct be_cmd_req_set_ll_link *req; 4180bdce2ad7SSuresh Reddy int status; 4181bdce2ad7SSuresh Reddy 4182bdce2ad7SSuresh Reddy if (BEx_chip(adapter) || lancer_chip(adapter)) 418318fd6025SKalesh AP return -EOPNOTSUPP; 4184bdce2ad7SSuresh Reddy 4185bdce2ad7SSuresh Reddy spin_lock_bh(&adapter->mcc_lock); 4186bdce2ad7SSuresh Reddy 4187bdce2ad7SSuresh Reddy wrb = wrb_from_mccq(adapter); 4188bdce2ad7SSuresh Reddy if (!wrb) { 4189bdce2ad7SSuresh Reddy status = -EBUSY; 4190bdce2ad7SSuresh Reddy goto err; 4191bdce2ad7SSuresh Reddy } 4192bdce2ad7SSuresh Reddy 4193bdce2ad7SSuresh Reddy req = embedded_payload(wrb); 4194bdce2ad7SSuresh Reddy 4195bdce2ad7SSuresh Reddy be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4196bdce2ad7SSuresh Reddy OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG, 4197bdce2ad7SSuresh Reddy sizeof(*req), wrb, NULL); 4198bdce2ad7SSuresh Reddy 4199bdce2ad7SSuresh Reddy req->hdr.version = 1; 4200bdce2ad7SSuresh Reddy req->hdr.domain = domain; 4201bdce2ad7SSuresh Reddy 4202bdce2ad7SSuresh Reddy if (link_state == IFLA_VF_LINK_STATE_ENABLE) 4203bdce2ad7SSuresh Reddy req->link_config |= 1; 4204bdce2ad7SSuresh Reddy 4205bdce2ad7SSuresh Reddy if (link_state == IFLA_VF_LINK_STATE_AUTO) 4206bdce2ad7SSuresh Reddy req->link_config |= 1 << PLINK_TRACK_SHIFT; 4207bdce2ad7SSuresh Reddy 4208bdce2ad7SSuresh Reddy status = be_mcc_notify_wait(adapter); 4209bdce2ad7SSuresh Reddy err: 4210bdce2ad7SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 4211bdce2ad7SSuresh Reddy return status; 4212bdce2ad7SSuresh Reddy } 4213bdce2ad7SSuresh Reddy 42146a4ab669SParav Pandit int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, 42156a4ab669SParav Pandit int wrb_payload_size, u16 *cmd_status, u16 *ext_status) 42166a4ab669SParav Pandit { 42176a4ab669SParav Pandit struct be_adapter *adapter = netdev_priv(netdev_handle); 42186a4ab669SParav Pandit struct be_mcc_wrb *wrb; 42196a4ab669SParav Pandit struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload; 42206a4ab669SParav Pandit struct be_cmd_req_hdr *req; 42216a4ab669SParav Pandit struct be_cmd_resp_hdr *resp; 42226a4ab669SParav Pandit int status; 42236a4ab669SParav Pandit 42246a4ab669SParav Pandit spin_lock_bh(&adapter->mcc_lock); 42256a4ab669SParav Pandit 42266a4ab669SParav Pandit wrb = wrb_from_mccq(adapter); 42276a4ab669SParav Pandit if (!wrb) { 42286a4ab669SParav Pandit status = -EBUSY; 42296a4ab669SParav Pandit goto err; 42306a4ab669SParav Pandit } 42316a4ab669SParav Pandit req = embedded_payload(wrb); 42326a4ab669SParav Pandit resp = embedded_payload(wrb); 42336a4ab669SParav Pandit 42346a4ab669SParav Pandit be_wrb_cmd_hdr_prepare(req, hdr->subsystem, 42356a4ab669SParav Pandit hdr->opcode, wrb_payload_size, wrb, NULL); 42366a4ab669SParav Pandit memcpy(req, wrb_payload, wrb_payload_size); 42376a4ab669SParav Pandit be_dws_cpu_to_le(req, wrb_payload_size); 42386a4ab669SParav Pandit 42396a4ab669SParav Pandit status = be_mcc_notify_wait(adapter); 42406a4ab669SParav Pandit if (cmd_status) 42416a4ab669SParav Pandit *cmd_status = (status & 0xffff); 42426a4ab669SParav Pandit if (ext_status) 42436a4ab669SParav Pandit *ext_status = 0; 42446a4ab669SParav Pandit memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length); 42456a4ab669SParav Pandit be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length); 42466a4ab669SParav Pandit err: 42476a4ab669SParav Pandit spin_unlock_bh(&adapter->mcc_lock); 42486a4ab669SParav Pandit return status; 42496a4ab669SParav Pandit } 42506a4ab669SParav Pandit EXPORT_SYMBOL(be_roce_mcc_cmd); 4251