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 682e365b1bSSomnath Kotur }, 692e365b1bSSomnath Kotur { 702e365b1bSSomnath Kotur OPCODE_LOWLEVEL_HOST_DDR_DMA, 712e365b1bSSomnath Kotur CMD_SUBSYSTEM_LOWLEVEL, 722e365b1bSSomnath Kotur BE_PRIV_DEVCFG | BE_PRIV_DEVSEC 732e365b1bSSomnath Kotur }, 742e365b1bSSomnath Kotur { 752e365b1bSSomnath Kotur OPCODE_LOWLEVEL_LOOPBACK_TEST, 762e365b1bSSomnath Kotur CMD_SUBSYSTEM_LOWLEVEL, 772e365b1bSSomnath Kotur BE_PRIV_DEVCFG | BE_PRIV_DEVSEC 782e365b1bSSomnath Kotur }, 792e365b1bSSomnath Kotur { 802e365b1bSSomnath Kotur OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, 812e365b1bSSomnath Kotur CMD_SUBSYSTEM_LOWLEVEL, 822e365b1bSSomnath Kotur BE_PRIV_DEVCFG | BE_PRIV_DEVSEC 832e365b1bSSomnath Kotur }, 84f25b119cSPadmanabh Ratnakar }; 85f25b119cSPadmanabh Ratnakar 86a2cc4e0bSSathya Perla static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, u8 subsystem) 87f25b119cSPadmanabh Ratnakar { 88f25b119cSPadmanabh Ratnakar int i; 89f25b119cSPadmanabh Ratnakar int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map); 90f25b119cSPadmanabh Ratnakar u32 cmd_privileges = adapter->cmd_privileges; 91f25b119cSPadmanabh Ratnakar 92f25b119cSPadmanabh Ratnakar for (i = 0; i < num_entries; i++) 93f25b119cSPadmanabh Ratnakar if (opcode == cmd_priv_map[i].opcode && 94f25b119cSPadmanabh Ratnakar subsystem == cmd_priv_map[i].subsystem) 95f25b119cSPadmanabh Ratnakar if (!(cmd_privileges & cmd_priv_map[i].priv_mask)) 96f25b119cSPadmanabh Ratnakar return false; 97f25b119cSPadmanabh Ratnakar 98f25b119cSPadmanabh Ratnakar return true; 99f25b119cSPadmanabh Ratnakar } 100f25b119cSPadmanabh Ratnakar 1013de09455SSomnath Kotur static inline void *embedded_payload(struct be_mcc_wrb *wrb) 1023de09455SSomnath Kotur { 1033de09455SSomnath Kotur return wrb->payload.embedded_payload; 1043de09455SSomnath Kotur } 1059aebddd1SJeff Kirsher 106efaa408eSSuresh Reddy static int be_mcc_notify(struct be_adapter *adapter) 1079aebddd1SJeff Kirsher { 1089aebddd1SJeff Kirsher struct be_queue_info *mccq = &adapter->mcc_obj.q; 1099aebddd1SJeff Kirsher u32 val = 0; 1109aebddd1SJeff Kirsher 111954f6825SVenkata Duvvuru if (be_check_error(adapter, BE_ERROR_ANY)) 112efaa408eSSuresh Reddy return -EIO; 1139aebddd1SJeff Kirsher 1149aebddd1SJeff Kirsher val |= mccq->id & DB_MCCQ_RING_ID_MASK; 1159aebddd1SJeff Kirsher val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; 1169aebddd1SJeff Kirsher 1179aebddd1SJeff Kirsher wmb(); 1189aebddd1SJeff Kirsher iowrite32(val, adapter->db + DB_MCCQ_OFFSET); 119efaa408eSSuresh Reddy 120efaa408eSSuresh Reddy return 0; 1219aebddd1SJeff Kirsher } 1229aebddd1SJeff Kirsher 1239aebddd1SJeff Kirsher /* To check if valid bit is set, check the entire word as we don't know 1249aebddd1SJeff Kirsher * the endianness of the data (old entry is host endian while a new entry is 1259aebddd1SJeff Kirsher * little endian) */ 1269aebddd1SJeff Kirsher static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) 1279aebddd1SJeff Kirsher { 1289e9ff4b7SSathya Perla u32 flags; 1299e9ff4b7SSathya Perla 1309aebddd1SJeff Kirsher if (compl->flags != 0) { 1319e9ff4b7SSathya Perla flags = le32_to_cpu(compl->flags); 1329e9ff4b7SSathya Perla if (flags & CQE_FLAGS_VALID_MASK) { 1339e9ff4b7SSathya Perla compl->flags = flags; 1349aebddd1SJeff Kirsher return true; 1359aebddd1SJeff Kirsher } 1369aebddd1SJeff Kirsher } 1379e9ff4b7SSathya Perla return false; 1389e9ff4b7SSathya Perla } 1399aebddd1SJeff Kirsher 1409aebddd1SJeff Kirsher /* Need to reset the entire word that houses the valid bit */ 1419aebddd1SJeff Kirsher static inline void be_mcc_compl_use(struct be_mcc_compl *compl) 1429aebddd1SJeff Kirsher { 1439aebddd1SJeff Kirsher compl->flags = 0; 1449aebddd1SJeff Kirsher } 1459aebddd1SJeff Kirsher 146652bf646SPadmanabh Ratnakar static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1) 147652bf646SPadmanabh Ratnakar { 148652bf646SPadmanabh Ratnakar unsigned long addr; 149652bf646SPadmanabh Ratnakar 150652bf646SPadmanabh Ratnakar addr = tag1; 151652bf646SPadmanabh Ratnakar addr = ((addr << 16) << 16) | tag0; 152652bf646SPadmanabh Ratnakar return (void *)addr; 153652bf646SPadmanabh Ratnakar } 154652bf646SPadmanabh Ratnakar 1554c60005fSKalesh AP static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status) 1564c60005fSKalesh AP { 1574c60005fSKalesh AP if (base_status == MCC_STATUS_NOT_SUPPORTED || 1584c60005fSKalesh AP base_status == MCC_STATUS_ILLEGAL_REQUEST || 1594c60005fSKalesh AP addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES || 16077be8c1cSKalesh AP addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS || 1614c60005fSKalesh AP (opcode == OPCODE_COMMON_WRITE_FLASHROM && 1624c60005fSKalesh AP (base_status == MCC_STATUS_ILLEGAL_FIELD || 1634c60005fSKalesh AP addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH))) 1644c60005fSKalesh AP return true; 1654c60005fSKalesh AP else 1664c60005fSKalesh AP return false; 1674c60005fSKalesh AP } 1684c60005fSKalesh AP 169559b633fSSathya Perla /* Place holder for all the async MCC cmds wherein the caller is not in a busy 170559b633fSSathya Perla * loop (has not issued be_mcc_notify_wait()) 171559b633fSSathya Perla */ 172559b633fSSathya Perla static void be_async_cmd_process(struct be_adapter *adapter, 173559b633fSSathya Perla struct be_mcc_compl *compl, 174559b633fSSathya Perla struct be_cmd_resp_hdr *resp_hdr) 175559b633fSSathya Perla { 176559b633fSSathya Perla enum mcc_base_status base_status = base_status(compl->status); 177559b633fSSathya Perla u8 opcode = 0, subsystem = 0; 178559b633fSSathya Perla 179559b633fSSathya Perla if (resp_hdr) { 180559b633fSSathya Perla opcode = resp_hdr->opcode; 181559b633fSSathya Perla subsystem = resp_hdr->subsystem; 182559b633fSSathya Perla } 183559b633fSSathya Perla 184559b633fSSathya Perla if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST && 185559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_LOWLEVEL) { 186559b633fSSathya Perla complete(&adapter->et_cmd_compl); 187559b633fSSathya Perla return; 188559b633fSSathya Perla } 189559b633fSSathya Perla 1909c855975SSuresh Reddy if (opcode == OPCODE_LOWLEVEL_SET_LOOPBACK_MODE && 1919c855975SSuresh Reddy subsystem == CMD_SUBSYSTEM_LOWLEVEL) { 1929c855975SSuresh Reddy complete(&adapter->et_cmd_compl); 1939c855975SSuresh Reddy return; 1949c855975SSuresh Reddy } 1959c855975SSuresh Reddy 196559b633fSSathya Perla if ((opcode == OPCODE_COMMON_WRITE_FLASHROM || 197559b633fSSathya Perla opcode == OPCODE_COMMON_WRITE_OBJECT) && 198559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_COMMON) { 199559b633fSSathya Perla adapter->flash_status = compl->status; 200559b633fSSathya Perla complete(&adapter->et_cmd_compl); 201559b633fSSathya Perla return; 202559b633fSSathya Perla } 203559b633fSSathya Perla 204559b633fSSathya Perla if ((opcode == OPCODE_ETH_GET_STATISTICS || 205559b633fSSathya Perla opcode == OPCODE_ETH_GET_PPORT_STATS) && 206559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_ETH && 207559b633fSSathya Perla base_status == MCC_STATUS_SUCCESS) { 208559b633fSSathya Perla be_parse_stats(adapter); 209559b633fSSathya Perla adapter->stats_cmd_sent = false; 210559b633fSSathya Perla return; 211559b633fSSathya Perla } 212559b633fSSathya Perla 213559b633fSSathya Perla if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES && 214559b633fSSathya Perla subsystem == CMD_SUBSYSTEM_COMMON) { 215559b633fSSathya Perla if (base_status == MCC_STATUS_SUCCESS) { 216559b633fSSathya Perla struct be_cmd_resp_get_cntl_addnl_attribs *resp = 217559b633fSSathya Perla (void *)resp_hdr; 21829e9122bSVenkata Duvvuru adapter->hwmon_info.be_on_die_temp = 219559b633fSSathya Perla resp->on_die_temperature; 220559b633fSSathya Perla } else { 221559b633fSSathya Perla adapter->be_get_temp_freq = 0; 22229e9122bSVenkata Duvvuru adapter->hwmon_info.be_on_die_temp = 22329e9122bSVenkata Duvvuru BE_INVALID_DIE_TEMP; 224559b633fSSathya Perla } 225559b633fSSathya Perla return; 226559b633fSSathya Perla } 227559b633fSSathya Perla } 228559b633fSSathya Perla 2299aebddd1SJeff Kirsher static int be_mcc_compl_process(struct be_adapter *adapter, 2309aebddd1SJeff Kirsher struct be_mcc_compl *compl) 2319aebddd1SJeff Kirsher { 2324c60005fSKalesh AP enum mcc_base_status base_status; 2334c60005fSKalesh AP enum mcc_addl_status addl_status; 234652bf646SPadmanabh Ratnakar struct be_cmd_resp_hdr *resp_hdr; 235652bf646SPadmanabh Ratnakar u8 opcode = 0, subsystem = 0; 2369aebddd1SJeff Kirsher 2379aebddd1SJeff Kirsher /* Just swap the status to host endian; mcc tag is opaquely copied 2389aebddd1SJeff Kirsher * from mcc_wrb */ 2399aebddd1SJeff Kirsher be_dws_le_to_cpu(compl, 4); 2409aebddd1SJeff Kirsher 2414c60005fSKalesh AP base_status = base_status(compl->status); 2424c60005fSKalesh AP addl_status = addl_status(compl->status); 24396c9b2e4SVasundhara Volam 244652bf646SPadmanabh Ratnakar resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1); 245652bf646SPadmanabh Ratnakar if (resp_hdr) { 246652bf646SPadmanabh Ratnakar opcode = resp_hdr->opcode; 247652bf646SPadmanabh Ratnakar subsystem = resp_hdr->subsystem; 248652bf646SPadmanabh Ratnakar } 249652bf646SPadmanabh Ratnakar 250559b633fSSathya Perla be_async_cmd_process(adapter, compl, resp_hdr); 2515eeff635SSuresh Reddy 252559b633fSSathya Perla if (base_status != MCC_STATUS_SUCCESS && 253559b633fSSathya Perla !be_skip_err_log(opcode, base_status, addl_status)) { 254fa5c867dSSuresh Reddy if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST || 255fa5c867dSSuresh Reddy addl_status == MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES) { 25697f1d8cdSVasundhara Volam dev_warn(&adapter->pdev->dev, 257522609f2SVasundhara Volam "VF is not privileged to issue opcode %d-%d\n", 25897f1d8cdSVasundhara Volam opcode, subsystem); 2599aebddd1SJeff Kirsher } else { 26097f1d8cdSVasundhara Volam dev_err(&adapter->pdev->dev, 26197f1d8cdSVasundhara Volam "opcode %d-%d failed:status %d-%d\n", 2624c60005fSKalesh AP opcode, subsystem, base_status, addl_status); 2639aebddd1SJeff Kirsher } 2649aebddd1SJeff Kirsher } 2654c60005fSKalesh AP return compl->status; 2669aebddd1SJeff Kirsher } 2679aebddd1SJeff Kirsher 2689aebddd1SJeff Kirsher /* Link state evt is a string of bytes; no need for endian swapping */ 2699aebddd1SJeff Kirsher static void be_async_link_state_process(struct be_adapter *adapter, 2703acf19d9SSathya Perla struct be_mcc_compl *compl) 2719aebddd1SJeff Kirsher { 2723acf19d9SSathya Perla struct be_async_event_link_state *evt = 2733acf19d9SSathya Perla (struct be_async_event_link_state *)compl; 2743acf19d9SSathya Perla 275b236916aSAjit Khaparde /* When link status changes, link speed must be re-queried from FW */ 27642f11cf2SAjit Khaparde adapter->phy.link_speed = -1; 277b236916aSAjit Khaparde 278bdce2ad7SSuresh Reddy /* On BEx the FW does not send a separate link status 279bdce2ad7SSuresh Reddy * notification for physical and logical link. 280bdce2ad7SSuresh Reddy * On other chips just process the logical link 281bdce2ad7SSuresh Reddy * status notification 282bdce2ad7SSuresh Reddy */ 283bdce2ad7SSuresh Reddy if (!BEx_chip(adapter) && 2842e177a5cSPadmanabh Ratnakar !(evt->port_link_status & LOGICAL_LINK_STATUS_MASK)) 2852e177a5cSPadmanabh Ratnakar return; 2862e177a5cSPadmanabh Ratnakar 287b236916aSAjit Khaparde /* For the initial link status do not rely on the ASYNC event as 288b236916aSAjit Khaparde * it may not be received in some cases. 289b236916aSAjit Khaparde */ 290b236916aSAjit Khaparde if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT) 291bdce2ad7SSuresh Reddy be_link_status_update(adapter, 292bdce2ad7SSuresh Reddy evt->port_link_status & LINK_STATUS_MASK); 2939aebddd1SJeff Kirsher } 2949aebddd1SJeff Kirsher 29521252377SVasundhara Volam static void be_async_port_misconfig_event_process(struct be_adapter *adapter, 29621252377SVasundhara Volam struct be_mcc_compl *compl) 29721252377SVasundhara Volam { 29821252377SVasundhara Volam struct be_async_event_misconfig_port *evt = 29921252377SVasundhara Volam (struct be_async_event_misconfig_port *)compl; 30021252377SVasundhara Volam u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1); 30121252377SVasundhara Volam struct device *dev = &adapter->pdev->dev; 30221252377SVasundhara Volam u8 port_misconfig_evt; 30321252377SVasundhara Volam 30421252377SVasundhara Volam port_misconfig_evt = 30521252377SVasundhara Volam ((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff); 30621252377SVasundhara Volam 30721252377SVasundhara Volam /* Log an error message that would allow a user to determine 30821252377SVasundhara Volam * whether the SFPs have an issue 30921252377SVasundhara Volam */ 31021252377SVasundhara Volam dev_info(dev, "Port %c: %s %s", adapter->port_name, 31121252377SVasundhara Volam be_port_misconfig_evt_desc[port_misconfig_evt], 31221252377SVasundhara Volam be_port_misconfig_remedy_desc[port_misconfig_evt]); 31321252377SVasundhara Volam 31421252377SVasundhara Volam if (port_misconfig_evt == INCOMPATIBLE_SFP) 31521252377SVasundhara Volam adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP; 31621252377SVasundhara Volam } 31721252377SVasundhara Volam 3189aebddd1SJeff Kirsher /* Grp5 CoS Priority evt */ 3199aebddd1SJeff Kirsher static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, 3203acf19d9SSathya Perla struct be_mcc_compl *compl) 3219aebddd1SJeff Kirsher { 3223acf19d9SSathya Perla struct be_async_event_grp5_cos_priority *evt = 3233acf19d9SSathya Perla (struct be_async_event_grp5_cos_priority *)compl; 3243acf19d9SSathya Perla 3259aebddd1SJeff Kirsher if (evt->valid) { 3269aebddd1SJeff Kirsher adapter->vlan_prio_bmap = evt->available_priority_bmap; 327fdf81bfbSSathya Perla adapter->recommended_prio_bits = 3289aebddd1SJeff Kirsher evt->reco_default_priority << VLAN_PRIO_SHIFT; 3299aebddd1SJeff Kirsher } 3309aebddd1SJeff Kirsher } 3319aebddd1SJeff Kirsher 332323ff71eSSathya Perla /* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */ 3339aebddd1SJeff Kirsher static void be_async_grp5_qos_speed_process(struct be_adapter *adapter, 3343acf19d9SSathya Perla struct be_mcc_compl *compl) 3359aebddd1SJeff Kirsher { 3363acf19d9SSathya Perla struct be_async_event_grp5_qos_link_speed *evt = 3373acf19d9SSathya Perla (struct be_async_event_grp5_qos_link_speed *)compl; 3383acf19d9SSathya Perla 339323ff71eSSathya Perla if (adapter->phy.link_speed >= 0 && 340323ff71eSSathya Perla evt->physical_port == adapter->port_num) 341323ff71eSSathya Perla adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10; 3429aebddd1SJeff Kirsher } 3439aebddd1SJeff Kirsher 3449aebddd1SJeff Kirsher /*Grp5 PVID evt*/ 3459aebddd1SJeff Kirsher static void be_async_grp5_pvid_state_process(struct be_adapter *adapter, 3463acf19d9SSathya Perla struct be_mcc_compl *compl) 3479aebddd1SJeff Kirsher { 3483acf19d9SSathya Perla struct be_async_event_grp5_pvid_state *evt = 3493acf19d9SSathya Perla (struct be_async_event_grp5_pvid_state *)compl; 3503acf19d9SSathya Perla 351bdac85b5SRavikumar Nelavelli if (evt->enabled) { 352939cf306SSomnath Kotur adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK; 353bdac85b5SRavikumar Nelavelli dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid); 354bdac85b5SRavikumar Nelavelli } else { 3559aebddd1SJeff Kirsher adapter->pvid = 0; 3569aebddd1SJeff Kirsher } 357bdac85b5SRavikumar Nelavelli } 3589aebddd1SJeff Kirsher 359760c295eSVenkata Duvvuru #define MGMT_ENABLE_MASK 0x4 360760c295eSVenkata Duvvuru static void be_async_grp5_fw_control_process(struct be_adapter *adapter, 361760c295eSVenkata Duvvuru struct be_mcc_compl *compl) 362760c295eSVenkata Duvvuru { 363760c295eSVenkata Duvvuru struct be_async_fw_control *evt = (struct be_async_fw_control *)compl; 364760c295eSVenkata Duvvuru u32 evt_dw1 = le32_to_cpu(evt->event_data_word1); 365760c295eSVenkata Duvvuru 366760c295eSVenkata Duvvuru if (evt_dw1 & MGMT_ENABLE_MASK) { 367760c295eSVenkata Duvvuru adapter->flags |= BE_FLAGS_OS2BMC; 368760c295eSVenkata Duvvuru adapter->bmc_filt_mask = le32_to_cpu(evt->event_data_word2); 369760c295eSVenkata Duvvuru } else { 370760c295eSVenkata Duvvuru adapter->flags &= ~BE_FLAGS_OS2BMC; 371760c295eSVenkata Duvvuru } 372760c295eSVenkata Duvvuru } 373760c295eSVenkata Duvvuru 3749aebddd1SJeff Kirsher static void be_async_grp5_evt_process(struct be_adapter *adapter, 3753acf19d9SSathya Perla struct be_mcc_compl *compl) 3769aebddd1SJeff Kirsher { 3773acf19d9SSathya Perla u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) & 3783acf19d9SSathya Perla ASYNC_EVENT_TYPE_MASK; 3799aebddd1SJeff Kirsher 3809aebddd1SJeff Kirsher switch (event_type) { 3819aebddd1SJeff Kirsher case ASYNC_EVENT_COS_PRIORITY: 3823acf19d9SSathya Perla be_async_grp5_cos_priority_process(adapter, compl); 3839aebddd1SJeff Kirsher break; 3849aebddd1SJeff Kirsher case ASYNC_EVENT_QOS_SPEED: 3853acf19d9SSathya Perla be_async_grp5_qos_speed_process(adapter, compl); 3869aebddd1SJeff Kirsher break; 3879aebddd1SJeff Kirsher case ASYNC_EVENT_PVID_STATE: 3883acf19d9SSathya Perla be_async_grp5_pvid_state_process(adapter, compl); 3899aebddd1SJeff Kirsher break; 390760c295eSVenkata Duvvuru /* Async event to disable/enable os2bmc and/or mac-learning */ 391760c295eSVenkata Duvvuru case ASYNC_EVENT_FW_CONTROL: 392760c295eSVenkata Duvvuru be_async_grp5_fw_control_process(adapter, compl); 393760c295eSVenkata Duvvuru break; 3949aebddd1SJeff Kirsher default: 3959aebddd1SJeff Kirsher break; 3969aebddd1SJeff Kirsher } 3979aebddd1SJeff Kirsher } 3989aebddd1SJeff Kirsher 399bc0c3405SAjit Khaparde static void be_async_dbg_evt_process(struct be_adapter *adapter, 4003acf19d9SSathya Perla struct be_mcc_compl *cmp) 401bc0c3405SAjit Khaparde { 402bc0c3405SAjit Khaparde u8 event_type = 0; 403bc0c3405SAjit Khaparde struct be_async_event_qnq *evt = (struct be_async_event_qnq *)cmp; 404bc0c3405SAjit Khaparde 4053acf19d9SSathya Perla event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) & 4063acf19d9SSathya Perla ASYNC_EVENT_TYPE_MASK; 407bc0c3405SAjit Khaparde 408bc0c3405SAjit Khaparde switch (event_type) { 409bc0c3405SAjit Khaparde case ASYNC_DEBUG_EVENT_TYPE_QNQ: 410bc0c3405SAjit Khaparde if (evt->valid) 411bc0c3405SAjit Khaparde adapter->qnq_vid = le16_to_cpu(evt->vlan_tag); 412bc0c3405SAjit Khaparde adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD; 413bc0c3405SAjit Khaparde break; 414bc0c3405SAjit Khaparde default: 41505ccaa2bSVasundhara Volam dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n", 41605ccaa2bSVasundhara Volam event_type); 417bc0c3405SAjit Khaparde break; 418bc0c3405SAjit Khaparde } 419bc0c3405SAjit Khaparde } 420bc0c3405SAjit Khaparde 42121252377SVasundhara Volam static void be_async_sliport_evt_process(struct be_adapter *adapter, 42221252377SVasundhara Volam struct be_mcc_compl *cmp) 42321252377SVasundhara Volam { 42421252377SVasundhara Volam u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) & 42521252377SVasundhara Volam ASYNC_EVENT_TYPE_MASK; 42621252377SVasundhara Volam 42721252377SVasundhara Volam if (event_type == ASYNC_EVENT_PORT_MISCONFIG) 42821252377SVasundhara Volam be_async_port_misconfig_event_process(adapter, cmp); 42921252377SVasundhara Volam } 43021252377SVasundhara Volam 4313acf19d9SSathya Perla static inline bool is_link_state_evt(u32 flags) 4329aebddd1SJeff Kirsher { 4333acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4349aebddd1SJeff Kirsher ASYNC_EVENT_CODE_LINK_STATE; 4359aebddd1SJeff Kirsher } 4369aebddd1SJeff Kirsher 4373acf19d9SSathya Perla static inline bool is_grp5_evt(u32 flags) 4389aebddd1SJeff Kirsher { 4393acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4403acf19d9SSathya Perla ASYNC_EVENT_CODE_GRP_5; 4419aebddd1SJeff Kirsher } 4429aebddd1SJeff Kirsher 4433acf19d9SSathya Perla static inline bool is_dbg_evt(u32 flags) 444bc0c3405SAjit Khaparde { 4453acf19d9SSathya Perla return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 4463acf19d9SSathya Perla ASYNC_EVENT_CODE_QNQ; 4473acf19d9SSathya Perla } 4483acf19d9SSathya Perla 44921252377SVasundhara Volam static inline bool is_sliport_evt(u32 flags) 45021252377SVasundhara Volam { 45121252377SVasundhara Volam return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == 45221252377SVasundhara Volam ASYNC_EVENT_CODE_SLIPORT; 45321252377SVasundhara Volam } 45421252377SVasundhara Volam 4553acf19d9SSathya Perla static void be_mcc_event_process(struct be_adapter *adapter, 4563acf19d9SSathya Perla struct be_mcc_compl *compl) 4573acf19d9SSathya Perla { 4583acf19d9SSathya Perla if (is_link_state_evt(compl->flags)) 4593acf19d9SSathya Perla be_async_link_state_process(adapter, compl); 4603acf19d9SSathya Perla else if (is_grp5_evt(compl->flags)) 4613acf19d9SSathya Perla be_async_grp5_evt_process(adapter, compl); 4623acf19d9SSathya Perla else if (is_dbg_evt(compl->flags)) 4633acf19d9SSathya Perla be_async_dbg_evt_process(adapter, compl); 46421252377SVasundhara Volam else if (is_sliport_evt(compl->flags)) 46521252377SVasundhara Volam be_async_sliport_evt_process(adapter, compl); 466bc0c3405SAjit Khaparde } 467bc0c3405SAjit Khaparde 4689aebddd1SJeff Kirsher static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) 4699aebddd1SJeff Kirsher { 4709aebddd1SJeff Kirsher struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq; 4719aebddd1SJeff Kirsher struct be_mcc_compl *compl = queue_tail_node(mcc_cq); 4729aebddd1SJeff Kirsher 4739aebddd1SJeff Kirsher if (be_mcc_compl_is_new(compl)) { 4749aebddd1SJeff Kirsher queue_tail_inc(mcc_cq); 4759aebddd1SJeff Kirsher return compl; 4769aebddd1SJeff Kirsher } 4779aebddd1SJeff Kirsher return NULL; 4789aebddd1SJeff Kirsher } 4799aebddd1SJeff Kirsher 4809aebddd1SJeff Kirsher void be_async_mcc_enable(struct be_adapter *adapter) 4819aebddd1SJeff Kirsher { 4829aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_cq_lock); 4839aebddd1SJeff Kirsher 4849aebddd1SJeff Kirsher be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0); 4859aebddd1SJeff Kirsher adapter->mcc_obj.rearm_cq = true; 4869aebddd1SJeff Kirsher 4879aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_cq_lock); 4889aebddd1SJeff Kirsher } 4899aebddd1SJeff Kirsher 4909aebddd1SJeff Kirsher void be_async_mcc_disable(struct be_adapter *adapter) 4919aebddd1SJeff Kirsher { 492a323d9bfSSathya Perla spin_lock_bh(&adapter->mcc_cq_lock); 493a323d9bfSSathya Perla 4949aebddd1SJeff Kirsher adapter->mcc_obj.rearm_cq = false; 495a323d9bfSSathya Perla be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); 496a323d9bfSSathya Perla 497a323d9bfSSathya Perla spin_unlock_bh(&adapter->mcc_cq_lock); 4989aebddd1SJeff Kirsher } 4999aebddd1SJeff Kirsher 50010ef9ab4SSathya Perla int be_process_mcc(struct be_adapter *adapter) 5019aebddd1SJeff Kirsher { 5029aebddd1SJeff Kirsher struct be_mcc_compl *compl; 50310ef9ab4SSathya Perla int num = 0, status = 0; 5049aebddd1SJeff Kirsher struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 5059aebddd1SJeff Kirsher 506072a9c48SAmerigo Wang spin_lock(&adapter->mcc_cq_lock); 5073acf19d9SSathya Perla 5089aebddd1SJeff Kirsher while ((compl = be_mcc_compl_get(adapter))) { 5099aebddd1SJeff Kirsher if (compl->flags & CQE_FLAGS_ASYNC_MASK) { 5103acf19d9SSathya Perla be_mcc_event_process(adapter, compl); 5119aebddd1SJeff Kirsher } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { 51210ef9ab4SSathya Perla status = be_mcc_compl_process(adapter, compl); 5139aebddd1SJeff Kirsher atomic_dec(&mcc_obj->q.used); 5149aebddd1SJeff Kirsher } 5159aebddd1SJeff Kirsher be_mcc_compl_use(compl); 5169aebddd1SJeff Kirsher num++; 5179aebddd1SJeff Kirsher } 5189aebddd1SJeff Kirsher 51910ef9ab4SSathya Perla if (num) 52010ef9ab4SSathya Perla be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); 52110ef9ab4SSathya Perla 522072a9c48SAmerigo Wang spin_unlock(&adapter->mcc_cq_lock); 52310ef9ab4SSathya Perla return status; 5249aebddd1SJeff Kirsher } 5259aebddd1SJeff Kirsher 5269aebddd1SJeff Kirsher /* Wait till no more pending mcc requests are present */ 5279aebddd1SJeff Kirsher static int be_mcc_wait_compl(struct be_adapter *adapter) 5289aebddd1SJeff Kirsher { 5299aebddd1SJeff Kirsher #define mcc_timeout 120000 /* 12s timeout */ 53010ef9ab4SSathya Perla int i, status = 0; 5319aebddd1SJeff Kirsher struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 5329aebddd1SJeff Kirsher 5336589ade0SSathya Perla for (i = 0; i < mcc_timeout; i++) { 534954f6825SVenkata Duvvuru if (be_check_error(adapter, BE_ERROR_ANY)) 5359aebddd1SJeff Kirsher return -EIO; 5369aebddd1SJeff Kirsher 537072a9c48SAmerigo Wang local_bh_disable(); 53810ef9ab4SSathya Perla status = be_process_mcc(adapter); 539072a9c48SAmerigo Wang local_bh_enable(); 5409aebddd1SJeff Kirsher 5419aebddd1SJeff Kirsher if (atomic_read(&mcc_obj->q.used) == 0) 5429aebddd1SJeff Kirsher break; 5439aebddd1SJeff Kirsher udelay(100); 5449aebddd1SJeff Kirsher } 5459aebddd1SJeff Kirsher if (i == mcc_timeout) { 5466589ade0SSathya Perla dev_err(&adapter->pdev->dev, "FW not responding\n"); 547954f6825SVenkata Duvvuru be_set_error(adapter, BE_ERROR_FW); 548652bf646SPadmanabh Ratnakar return -EIO; 5499aebddd1SJeff Kirsher } 5509aebddd1SJeff Kirsher return status; 5519aebddd1SJeff Kirsher } 5529aebddd1SJeff Kirsher 5539aebddd1SJeff Kirsher /* Notify MCC requests and wait for completion */ 5549aebddd1SJeff Kirsher static int be_mcc_notify_wait(struct be_adapter *adapter) 5559aebddd1SJeff Kirsher { 556652bf646SPadmanabh Ratnakar int status; 557652bf646SPadmanabh Ratnakar struct be_mcc_wrb *wrb; 558652bf646SPadmanabh Ratnakar struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; 559652bf646SPadmanabh Ratnakar u16 index = mcc_obj->q.head; 560652bf646SPadmanabh Ratnakar struct be_cmd_resp_hdr *resp; 561652bf646SPadmanabh Ratnakar 562652bf646SPadmanabh Ratnakar index_dec(&index, mcc_obj->q.len); 563652bf646SPadmanabh Ratnakar wrb = queue_index_node(&mcc_obj->q, index); 564652bf646SPadmanabh Ratnakar 565652bf646SPadmanabh Ratnakar resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1); 566652bf646SPadmanabh Ratnakar 567efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 568efaa408eSSuresh Reddy if (status) 569efaa408eSSuresh Reddy goto out; 570652bf646SPadmanabh Ratnakar 571652bf646SPadmanabh Ratnakar status = be_mcc_wait_compl(adapter); 572652bf646SPadmanabh Ratnakar if (status == -EIO) 573652bf646SPadmanabh Ratnakar goto out; 574652bf646SPadmanabh Ratnakar 5754c60005fSKalesh AP status = (resp->base_status | 5764c60005fSKalesh AP ((resp->addl_status & CQE_ADDL_STATUS_MASK) << 5774c60005fSKalesh AP CQE_ADDL_STATUS_SHIFT)); 578652bf646SPadmanabh Ratnakar out: 579652bf646SPadmanabh Ratnakar return status; 5809aebddd1SJeff Kirsher } 5819aebddd1SJeff Kirsher 5829aebddd1SJeff Kirsher static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) 5839aebddd1SJeff Kirsher { 5849aebddd1SJeff Kirsher int msecs = 0; 5859aebddd1SJeff Kirsher u32 ready; 5869aebddd1SJeff Kirsher 5876589ade0SSathya Perla do { 588954f6825SVenkata Duvvuru if (be_check_error(adapter, BE_ERROR_ANY)) 5899aebddd1SJeff Kirsher return -EIO; 5909aebddd1SJeff Kirsher 5919aebddd1SJeff Kirsher ready = ioread32(db); 592434b3648SSathya Perla if (ready == 0xffffffff) 5939aebddd1SJeff Kirsher return -1; 5949aebddd1SJeff Kirsher 5959aebddd1SJeff Kirsher ready &= MPU_MAILBOX_DB_RDY_MASK; 5969aebddd1SJeff Kirsher if (ready) 5979aebddd1SJeff Kirsher break; 5989aebddd1SJeff Kirsher 5999aebddd1SJeff Kirsher if (msecs > 4000) { 6006589ade0SSathya Perla dev_err(&adapter->pdev->dev, "FW not responding\n"); 601954f6825SVenkata Duvvuru be_set_error(adapter, BE_ERROR_FW); 602f67ef7baSPadmanabh Ratnakar be_detect_error(adapter); 6039aebddd1SJeff Kirsher return -1; 6049aebddd1SJeff Kirsher } 6059aebddd1SJeff Kirsher 6069aebddd1SJeff Kirsher msleep(1); 6079aebddd1SJeff Kirsher msecs++; 6089aebddd1SJeff Kirsher } while (true); 6099aebddd1SJeff Kirsher 6109aebddd1SJeff Kirsher return 0; 6119aebddd1SJeff Kirsher } 6129aebddd1SJeff Kirsher 6139aebddd1SJeff Kirsher /* 6149aebddd1SJeff Kirsher * Insert the mailbox address into the doorbell in two steps 6159aebddd1SJeff Kirsher * Polls on the mbox doorbell till a command completion (or a timeout) occurs 6169aebddd1SJeff Kirsher */ 6179aebddd1SJeff Kirsher static int be_mbox_notify_wait(struct be_adapter *adapter) 6189aebddd1SJeff Kirsher { 6199aebddd1SJeff Kirsher int status; 6209aebddd1SJeff Kirsher u32 val = 0; 6219aebddd1SJeff Kirsher void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET; 6229aebddd1SJeff Kirsher struct be_dma_mem *mbox_mem = &adapter->mbox_mem; 6239aebddd1SJeff Kirsher struct be_mcc_mailbox *mbox = mbox_mem->va; 6249aebddd1SJeff Kirsher struct be_mcc_compl *compl = &mbox->compl; 6259aebddd1SJeff Kirsher 6269aebddd1SJeff Kirsher /* wait for ready to be set */ 6279aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 6289aebddd1SJeff Kirsher if (status != 0) 6299aebddd1SJeff Kirsher return status; 6309aebddd1SJeff Kirsher 6319aebddd1SJeff Kirsher val |= MPU_MAILBOX_DB_HI_MASK; 6329aebddd1SJeff Kirsher /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ 6339aebddd1SJeff Kirsher val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; 6349aebddd1SJeff Kirsher iowrite32(val, db); 6359aebddd1SJeff Kirsher 6369aebddd1SJeff Kirsher /* wait for ready to be set */ 6379aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 6389aebddd1SJeff Kirsher if (status != 0) 6399aebddd1SJeff Kirsher return status; 6409aebddd1SJeff Kirsher 6419aebddd1SJeff Kirsher val = 0; 6429aebddd1SJeff Kirsher /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ 6439aebddd1SJeff Kirsher val |= (u32)(mbox_mem->dma >> 4) << 2; 6449aebddd1SJeff Kirsher iowrite32(val, db); 6459aebddd1SJeff Kirsher 6469aebddd1SJeff Kirsher status = be_mbox_db_ready_wait(adapter, db); 6479aebddd1SJeff Kirsher if (status != 0) 6489aebddd1SJeff Kirsher return status; 6499aebddd1SJeff Kirsher 6509aebddd1SJeff Kirsher /* A cq entry has been made now */ 6519aebddd1SJeff Kirsher if (be_mcc_compl_is_new(compl)) { 6529aebddd1SJeff Kirsher status = be_mcc_compl_process(adapter, &mbox->compl); 6539aebddd1SJeff Kirsher be_mcc_compl_use(compl); 6549aebddd1SJeff Kirsher if (status) 6559aebddd1SJeff Kirsher return status; 6569aebddd1SJeff Kirsher } else { 6579aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "invalid mailbox completion\n"); 6589aebddd1SJeff Kirsher return -1; 6599aebddd1SJeff Kirsher } 6609aebddd1SJeff Kirsher return 0; 6619aebddd1SJeff Kirsher } 6629aebddd1SJeff Kirsher 663c5b3ad4cSSathya Perla static u16 be_POST_stage_get(struct be_adapter *adapter) 6649aebddd1SJeff Kirsher { 6659aebddd1SJeff Kirsher u32 sem; 6669aebddd1SJeff Kirsher 667c5b3ad4cSSathya Perla if (BEx_chip(adapter)) 668c5b3ad4cSSathya Perla sem = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx); 6699aebddd1SJeff Kirsher else 670c5b3ad4cSSathya Perla pci_read_config_dword(adapter->pdev, 671c5b3ad4cSSathya Perla SLIPORT_SEMAPHORE_OFFSET_SH, &sem); 672c5b3ad4cSSathya Perla 673c5b3ad4cSSathya Perla return sem & POST_STAGE_MASK; 6749aebddd1SJeff Kirsher } 6759aebddd1SJeff Kirsher 67687f20c26SGavin Shan static int lancer_wait_ready(struct be_adapter *adapter) 677bf99e50dSPadmanabh Ratnakar { 678bf99e50dSPadmanabh Ratnakar #define SLIPORT_READY_TIMEOUT 30 679bf99e50dSPadmanabh Ratnakar u32 sliport_status; 680e673244aSKalesh AP int i; 681bf99e50dSPadmanabh Ratnakar 682bf99e50dSPadmanabh Ratnakar for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) { 683bf99e50dSPadmanabh Ratnakar sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); 684bf99e50dSPadmanabh Ratnakar if (sliport_status & SLIPORT_STATUS_RDY_MASK) 6859fa465c0SSathya Perla return 0; 6869fa465c0SSathya Perla 6879fa465c0SSathya Perla if (sliport_status & SLIPORT_STATUS_ERR_MASK && 6889fa465c0SSathya Perla !(sliport_status & SLIPORT_STATUS_RN_MASK)) 6899fa465c0SSathya Perla return -EIO; 690bf99e50dSPadmanabh Ratnakar 691bf99e50dSPadmanabh Ratnakar msleep(1000); 692bf99e50dSPadmanabh Ratnakar } 693bf99e50dSPadmanabh Ratnakar 694e673244aSKalesh AP return sliport_status ? : -1; 695bf99e50dSPadmanabh Ratnakar } 696bf99e50dSPadmanabh Ratnakar 697bf99e50dSPadmanabh Ratnakar int be_fw_wait_ready(struct be_adapter *adapter) 6989aebddd1SJeff Kirsher { 6999aebddd1SJeff Kirsher u16 stage; 7009aebddd1SJeff Kirsher int status, timeout = 0; 7019aebddd1SJeff Kirsher struct device *dev = &adapter->pdev->dev; 7029aebddd1SJeff Kirsher 703bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) { 704bf99e50dSPadmanabh Ratnakar status = lancer_wait_ready(adapter); 705e673244aSKalesh AP if (status) { 706e673244aSKalesh AP stage = status; 707e673244aSKalesh AP goto err; 708e673244aSKalesh AP } 709e673244aSKalesh AP return 0; 710bf99e50dSPadmanabh Ratnakar } 711bf99e50dSPadmanabh Ratnakar 7129aebddd1SJeff Kirsher do { 713ca3de6b2SSathya Perla /* There's no means to poll POST state on BE2/3 VFs */ 714ca3de6b2SSathya Perla if (BEx_chip(adapter) && be_virtfn(adapter)) 715ca3de6b2SSathya Perla return 0; 716ca3de6b2SSathya Perla 717c5b3ad4cSSathya Perla stage = be_POST_stage_get(adapter); 71866d29cbcSGavin Shan if (stage == POST_STAGE_ARMFW_RDY) 71966d29cbcSGavin Shan return 0; 72066d29cbcSGavin Shan 721a2cc4e0bSSathya Perla dev_info(dev, "Waiting for POST, %ds elapsed\n", timeout); 7229aebddd1SJeff Kirsher if (msleep_interruptible(2000)) { 7239aebddd1SJeff Kirsher dev_err(dev, "Waiting for POST aborted\n"); 7249aebddd1SJeff Kirsher return -EINTR; 7259aebddd1SJeff Kirsher } 7269aebddd1SJeff Kirsher timeout += 2; 7273ab81b5fSSomnath Kotur } while (timeout < 60); 7289aebddd1SJeff Kirsher 729e673244aSKalesh AP err: 730e673244aSKalesh AP dev_err(dev, "POST timeout; stage=%#x\n", stage); 7319fa465c0SSathya Perla return -ETIMEDOUT; 7329aebddd1SJeff Kirsher } 7339aebddd1SJeff Kirsher 7349aebddd1SJeff Kirsher static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) 7359aebddd1SJeff Kirsher { 7369aebddd1SJeff Kirsher return &wrb->payload.sgl[0]; 7379aebddd1SJeff Kirsher } 7389aebddd1SJeff Kirsher 739a2cc4e0bSSathya Perla static inline void fill_wrb_tags(struct be_mcc_wrb *wrb, unsigned long addr) 740bea50988SSathya Perla { 741bea50988SSathya Perla wrb->tag0 = addr & 0xFFFFFFFF; 742bea50988SSathya Perla wrb->tag1 = upper_32_bits(addr); 743bea50988SSathya Perla } 7449aebddd1SJeff Kirsher 7459aebddd1SJeff Kirsher /* Don't touch the hdr after it's prepared */ 746106df1e3SSomnath Kotur /* mem will be NULL for embedded commands */ 747106df1e3SSomnath Kotur static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, 748106df1e3SSomnath Kotur u8 subsystem, u8 opcode, int cmd_len, 749a2cc4e0bSSathya Perla struct be_mcc_wrb *wrb, 750a2cc4e0bSSathya Perla struct be_dma_mem *mem) 7519aebddd1SJeff Kirsher { 752106df1e3SSomnath Kotur struct be_sge *sge; 753106df1e3SSomnath Kotur 7549aebddd1SJeff Kirsher req_hdr->opcode = opcode; 7559aebddd1SJeff Kirsher req_hdr->subsystem = subsystem; 7569aebddd1SJeff Kirsher req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); 7579aebddd1SJeff Kirsher req_hdr->version = 0; 758bea50988SSathya Perla fill_wrb_tags(wrb, (ulong) req_hdr); 759106df1e3SSomnath Kotur wrb->payload_length = cmd_len; 760106df1e3SSomnath Kotur if (mem) { 761106df1e3SSomnath Kotur wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) << 762106df1e3SSomnath Kotur MCC_WRB_SGE_CNT_SHIFT; 763106df1e3SSomnath Kotur sge = nonembedded_sgl(wrb); 764106df1e3SSomnath Kotur sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma)); 765106df1e3SSomnath Kotur sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF); 766106df1e3SSomnath Kotur sge->len = cpu_to_le32(mem->size); 767106df1e3SSomnath Kotur } else 768106df1e3SSomnath Kotur wrb->embedded |= MCC_WRB_EMBEDDED_MASK; 769106df1e3SSomnath Kotur be_dws_cpu_to_le(wrb, 8); 7709aebddd1SJeff Kirsher } 7719aebddd1SJeff Kirsher 7729aebddd1SJeff Kirsher static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, 7739aebddd1SJeff Kirsher struct be_dma_mem *mem) 7749aebddd1SJeff Kirsher { 7759aebddd1SJeff Kirsher int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); 7769aebddd1SJeff Kirsher u64 dma = (u64)mem->dma; 7779aebddd1SJeff Kirsher 7789aebddd1SJeff Kirsher for (i = 0; i < buf_pages; i++) { 7799aebddd1SJeff Kirsher pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); 7809aebddd1SJeff Kirsher pages[i].hi = cpu_to_le32(upper_32_bits(dma)); 7819aebddd1SJeff Kirsher dma += PAGE_SIZE_4K; 7829aebddd1SJeff Kirsher } 7839aebddd1SJeff Kirsher } 7849aebddd1SJeff Kirsher 7859aebddd1SJeff Kirsher static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter) 7869aebddd1SJeff Kirsher { 7879aebddd1SJeff Kirsher struct be_dma_mem *mbox_mem = &adapter->mbox_mem; 7889aebddd1SJeff Kirsher struct be_mcc_wrb *wrb 7899aebddd1SJeff Kirsher = &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; 7909aebddd1SJeff Kirsher memset(wrb, 0, sizeof(*wrb)); 7919aebddd1SJeff Kirsher return wrb; 7929aebddd1SJeff Kirsher } 7939aebddd1SJeff Kirsher 7949aebddd1SJeff Kirsher static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) 7959aebddd1SJeff Kirsher { 7969aebddd1SJeff Kirsher struct be_queue_info *mccq = &adapter->mcc_obj.q; 7979aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 7989aebddd1SJeff Kirsher 799aa790db9SPadmanabh Ratnakar if (!mccq->created) 800aa790db9SPadmanabh Ratnakar return NULL; 801aa790db9SPadmanabh Ratnakar 8024d277125SVasundhara Volam if (atomic_read(&mccq->used) >= mccq->len) 8039aebddd1SJeff Kirsher return NULL; 8049aebddd1SJeff Kirsher 8059aebddd1SJeff Kirsher wrb = queue_head_node(mccq); 8069aebddd1SJeff Kirsher queue_head_inc(mccq); 8079aebddd1SJeff Kirsher atomic_inc(&mccq->used); 8089aebddd1SJeff Kirsher memset(wrb, 0, sizeof(*wrb)); 8099aebddd1SJeff Kirsher return wrb; 8109aebddd1SJeff Kirsher } 8119aebddd1SJeff Kirsher 812bea50988SSathya Perla static bool use_mcc(struct be_adapter *adapter) 813bea50988SSathya Perla { 814bea50988SSathya Perla return adapter->mcc_obj.q.created; 815bea50988SSathya Perla } 816bea50988SSathya Perla 817bea50988SSathya Perla /* Must be used only in process context */ 818bea50988SSathya Perla static int be_cmd_lock(struct be_adapter *adapter) 819bea50988SSathya Perla { 820bea50988SSathya Perla if (use_mcc(adapter)) { 821bea50988SSathya Perla spin_lock_bh(&adapter->mcc_lock); 822bea50988SSathya Perla return 0; 823bea50988SSathya Perla } else { 824bea50988SSathya Perla return mutex_lock_interruptible(&adapter->mbox_lock); 825bea50988SSathya Perla } 826bea50988SSathya Perla } 827bea50988SSathya Perla 828bea50988SSathya Perla /* Must be used only in process context */ 829bea50988SSathya Perla static void be_cmd_unlock(struct be_adapter *adapter) 830bea50988SSathya Perla { 831bea50988SSathya Perla if (use_mcc(adapter)) 832bea50988SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 833bea50988SSathya Perla else 834bea50988SSathya Perla return mutex_unlock(&adapter->mbox_lock); 835bea50988SSathya Perla } 836bea50988SSathya Perla 837bea50988SSathya Perla static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter, 838bea50988SSathya Perla struct be_mcc_wrb *wrb) 839bea50988SSathya Perla { 840bea50988SSathya Perla struct be_mcc_wrb *dest_wrb; 841bea50988SSathya Perla 842bea50988SSathya Perla if (use_mcc(adapter)) { 843bea50988SSathya Perla dest_wrb = wrb_from_mccq(adapter); 844bea50988SSathya Perla if (!dest_wrb) 845bea50988SSathya Perla return NULL; 846bea50988SSathya Perla } else { 847bea50988SSathya Perla dest_wrb = wrb_from_mbox(adapter); 848bea50988SSathya Perla } 849bea50988SSathya Perla 850bea50988SSathya Perla memcpy(dest_wrb, wrb, sizeof(*wrb)); 851bea50988SSathya Perla if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK)) 852bea50988SSathya Perla fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb)); 853bea50988SSathya Perla 854bea50988SSathya Perla return dest_wrb; 855bea50988SSathya Perla } 856bea50988SSathya Perla 857bea50988SSathya Perla /* Must be used only in process context */ 858bea50988SSathya Perla static int be_cmd_notify_wait(struct be_adapter *adapter, 859bea50988SSathya Perla struct be_mcc_wrb *wrb) 860bea50988SSathya Perla { 861bea50988SSathya Perla struct be_mcc_wrb *dest_wrb; 862bea50988SSathya Perla int status; 863bea50988SSathya Perla 864bea50988SSathya Perla status = be_cmd_lock(adapter); 865bea50988SSathya Perla if (status) 866bea50988SSathya Perla return status; 867bea50988SSathya Perla 868bea50988SSathya Perla dest_wrb = be_cmd_copy(adapter, wrb); 8690c884567SSuresh Reddy if (!dest_wrb) { 8700c884567SSuresh Reddy status = -EBUSY; 8710c884567SSuresh Reddy goto unlock; 8720c884567SSuresh Reddy } 873bea50988SSathya Perla 874bea50988SSathya Perla if (use_mcc(adapter)) 875bea50988SSathya Perla status = be_mcc_notify_wait(adapter); 876bea50988SSathya Perla else 877bea50988SSathya Perla status = be_mbox_notify_wait(adapter); 878bea50988SSathya Perla 879bea50988SSathya Perla if (!status) 880bea50988SSathya Perla memcpy(wrb, dest_wrb, sizeof(*wrb)); 881bea50988SSathya Perla 8820c884567SSuresh Reddy unlock: 883bea50988SSathya Perla be_cmd_unlock(adapter); 884bea50988SSathya Perla return status; 885bea50988SSathya Perla } 886bea50988SSathya Perla 8879aebddd1SJeff Kirsher /* Tell fw we're about to start firing cmds by writing a 8889aebddd1SJeff Kirsher * special pattern across the wrb hdr; uses mbox 8899aebddd1SJeff Kirsher */ 8909aebddd1SJeff Kirsher int be_cmd_fw_init(struct be_adapter *adapter) 8919aebddd1SJeff Kirsher { 8929aebddd1SJeff Kirsher u8 *wrb; 8939aebddd1SJeff Kirsher int status; 8949aebddd1SJeff Kirsher 895bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) 896bf99e50dSPadmanabh Ratnakar return 0; 897bf99e50dSPadmanabh Ratnakar 8989aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 8999aebddd1SJeff Kirsher return -1; 9009aebddd1SJeff Kirsher 9019aebddd1SJeff Kirsher wrb = (u8 *)wrb_from_mbox(adapter); 9029aebddd1SJeff Kirsher *wrb++ = 0xFF; 9039aebddd1SJeff Kirsher *wrb++ = 0x12; 9049aebddd1SJeff Kirsher *wrb++ = 0x34; 9059aebddd1SJeff Kirsher *wrb++ = 0xFF; 9069aebddd1SJeff Kirsher *wrb++ = 0xFF; 9079aebddd1SJeff Kirsher *wrb++ = 0x56; 9089aebddd1SJeff Kirsher *wrb++ = 0x78; 9099aebddd1SJeff Kirsher *wrb = 0xFF; 9109aebddd1SJeff Kirsher 9119aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 9129aebddd1SJeff Kirsher 9139aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 9149aebddd1SJeff Kirsher return status; 9159aebddd1SJeff Kirsher } 9169aebddd1SJeff Kirsher 9179aebddd1SJeff Kirsher /* Tell fw we're done with firing cmds by writing a 9189aebddd1SJeff Kirsher * special pattern across the wrb hdr; uses mbox 9199aebddd1SJeff Kirsher */ 9209aebddd1SJeff Kirsher int be_cmd_fw_clean(struct be_adapter *adapter) 9219aebddd1SJeff Kirsher { 9229aebddd1SJeff Kirsher u8 *wrb; 9239aebddd1SJeff Kirsher int status; 9249aebddd1SJeff Kirsher 925bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) 926bf99e50dSPadmanabh Ratnakar return 0; 927bf99e50dSPadmanabh Ratnakar 9289aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 9299aebddd1SJeff Kirsher return -1; 9309aebddd1SJeff Kirsher 9319aebddd1SJeff Kirsher wrb = (u8 *)wrb_from_mbox(adapter); 9329aebddd1SJeff Kirsher *wrb++ = 0xFF; 9339aebddd1SJeff Kirsher *wrb++ = 0xAA; 9349aebddd1SJeff Kirsher *wrb++ = 0xBB; 9359aebddd1SJeff Kirsher *wrb++ = 0xFF; 9369aebddd1SJeff Kirsher *wrb++ = 0xFF; 9379aebddd1SJeff Kirsher *wrb++ = 0xCC; 9389aebddd1SJeff Kirsher *wrb++ = 0xDD; 9399aebddd1SJeff Kirsher *wrb = 0xFF; 9409aebddd1SJeff Kirsher 9419aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 9429aebddd1SJeff Kirsher 9439aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 9449aebddd1SJeff Kirsher return status; 9459aebddd1SJeff Kirsher } 946bf99e50dSPadmanabh Ratnakar 947f2f781a7SSathya Perla int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo) 9489aebddd1SJeff Kirsher { 9499aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 9509aebddd1SJeff Kirsher struct be_cmd_req_eq_create *req; 951f2f781a7SSathya Perla struct be_dma_mem *q_mem = &eqo->q.dma_mem; 952f2f781a7SSathya Perla int status, ver = 0; 9539aebddd1SJeff Kirsher 9549aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 9559aebddd1SJeff Kirsher return -1; 9569aebddd1SJeff Kirsher 9579aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 9589aebddd1SJeff Kirsher req = embedded_payload(wrb); 9599aebddd1SJeff Kirsher 960106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 961a2cc4e0bSSathya Perla OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb, 962a2cc4e0bSSathya Perla NULL); 9639aebddd1SJeff Kirsher 964f2f781a7SSathya Perla /* Support for EQ_CREATEv2 available only SH-R onwards */ 965f2f781a7SSathya Perla if (!(BEx_chip(adapter) || lancer_chip(adapter))) 966f2f781a7SSathya Perla ver = 2; 967f2f781a7SSathya Perla 968f2f781a7SSathya Perla req->hdr.version = ver; 9699aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 9709aebddd1SJeff Kirsher 9719aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); 9729aebddd1SJeff Kirsher /* 4byte eqe*/ 9739aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); 9749aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_eq_context, count, req->context, 975f2f781a7SSathya Perla __ilog2_u32(eqo->q.len / 256)); 9769aebddd1SJeff Kirsher be_dws_cpu_to_le(req->context, sizeof(req->context)); 9779aebddd1SJeff Kirsher 9789aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 9799aebddd1SJeff Kirsher 9809aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 9819aebddd1SJeff Kirsher if (!status) { 9829aebddd1SJeff Kirsher struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); 98303d28ffeSKalesh AP 984f2f781a7SSathya Perla eqo->q.id = le16_to_cpu(resp->eq_id); 985f2f781a7SSathya Perla eqo->msix_idx = 986f2f781a7SSathya Perla (ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx; 987f2f781a7SSathya Perla eqo->q.created = true; 9889aebddd1SJeff Kirsher } 9899aebddd1SJeff Kirsher 9909aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 9919aebddd1SJeff Kirsher return status; 9929aebddd1SJeff Kirsher } 9939aebddd1SJeff Kirsher 994f9449ab7SSathya Perla /* Use MCC */ 9959aebddd1SJeff Kirsher int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, 9965ee4979bSSathya Perla bool permanent, u32 if_handle, u32 pmac_id) 9979aebddd1SJeff Kirsher { 9989aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 9999aebddd1SJeff Kirsher struct be_cmd_req_mac_query *req; 10009aebddd1SJeff Kirsher int status; 10019aebddd1SJeff Kirsher 1002f9449ab7SSathya Perla spin_lock_bh(&adapter->mcc_lock); 10039aebddd1SJeff Kirsher 1004f9449ab7SSathya Perla wrb = wrb_from_mccq(adapter); 1005f9449ab7SSathya Perla if (!wrb) { 1006f9449ab7SSathya Perla status = -EBUSY; 1007f9449ab7SSathya Perla goto err; 1008f9449ab7SSathya Perla } 10099aebddd1SJeff Kirsher req = embedded_payload(wrb); 10109aebddd1SJeff Kirsher 1011106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1012a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb, 1013a2cc4e0bSSathya Perla NULL); 10145ee4979bSSathya Perla req->type = MAC_ADDRESS_TYPE_NETWORK; 10159aebddd1SJeff Kirsher if (permanent) { 10169aebddd1SJeff Kirsher req->permanent = 1; 10179aebddd1SJeff Kirsher } else { 10189aebddd1SJeff Kirsher req->if_id = cpu_to_le16((u16)if_handle); 1019590c391dSPadmanabh Ratnakar req->pmac_id = cpu_to_le32(pmac_id); 10209aebddd1SJeff Kirsher req->permanent = 0; 10219aebddd1SJeff Kirsher } 10229aebddd1SJeff Kirsher 1023f9449ab7SSathya Perla status = be_mcc_notify_wait(adapter); 10249aebddd1SJeff Kirsher if (!status) { 10259aebddd1SJeff Kirsher struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); 102603d28ffeSKalesh AP 10279aebddd1SJeff Kirsher memcpy(mac_addr, resp->mac.addr, ETH_ALEN); 10289aebddd1SJeff Kirsher } 10299aebddd1SJeff Kirsher 1030f9449ab7SSathya Perla err: 1031f9449ab7SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 10329aebddd1SJeff Kirsher return status; 10339aebddd1SJeff Kirsher } 10349aebddd1SJeff Kirsher 10359aebddd1SJeff Kirsher /* Uses synchronous MCCQ */ 10369aebddd1SJeff Kirsher int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, 10379aebddd1SJeff Kirsher u32 if_id, u32 *pmac_id, u32 domain) 10389aebddd1SJeff Kirsher { 10399aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10409aebddd1SJeff Kirsher struct be_cmd_req_pmac_add *req; 10419aebddd1SJeff Kirsher int status; 10429aebddd1SJeff Kirsher 10439aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 10449aebddd1SJeff Kirsher 10459aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 10469aebddd1SJeff Kirsher if (!wrb) { 10479aebddd1SJeff Kirsher status = -EBUSY; 10489aebddd1SJeff Kirsher goto err; 10499aebddd1SJeff Kirsher } 10509aebddd1SJeff Kirsher req = embedded_payload(wrb); 10519aebddd1SJeff Kirsher 1052106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1053a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb, 1054a2cc4e0bSSathya Perla NULL); 10559aebddd1SJeff Kirsher 10569aebddd1SJeff Kirsher req->hdr.domain = domain; 10579aebddd1SJeff Kirsher req->if_id = cpu_to_le32(if_id); 10589aebddd1SJeff Kirsher memcpy(req->mac_address, mac_addr, ETH_ALEN); 10599aebddd1SJeff Kirsher 10609aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 10619aebddd1SJeff Kirsher if (!status) { 10629aebddd1SJeff Kirsher struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb); 106303d28ffeSKalesh AP 10649aebddd1SJeff Kirsher *pmac_id = le32_to_cpu(resp->pmac_id); 10659aebddd1SJeff Kirsher } 10669aebddd1SJeff Kirsher 10679aebddd1SJeff Kirsher err: 10689aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 1069e3a7ae2cSSomnath Kotur 1070e3a7ae2cSSomnath Kotur if (status == MCC_STATUS_UNAUTHORIZED_REQUEST) 1071e3a7ae2cSSomnath Kotur status = -EPERM; 1072e3a7ae2cSSomnath Kotur 10739aebddd1SJeff Kirsher return status; 10749aebddd1SJeff Kirsher } 10759aebddd1SJeff Kirsher 10769aebddd1SJeff Kirsher /* Uses synchronous MCCQ */ 107730128031SSathya Perla int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) 10789aebddd1SJeff Kirsher { 10799aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 10809aebddd1SJeff Kirsher struct be_cmd_req_pmac_del *req; 10819aebddd1SJeff Kirsher int status; 10829aebddd1SJeff Kirsher 108330128031SSathya Perla if (pmac_id == -1) 108430128031SSathya Perla return 0; 108530128031SSathya Perla 10869aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 10879aebddd1SJeff Kirsher 10889aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 10899aebddd1SJeff Kirsher if (!wrb) { 10909aebddd1SJeff Kirsher status = -EBUSY; 10919aebddd1SJeff Kirsher goto err; 10929aebddd1SJeff Kirsher } 10939aebddd1SJeff Kirsher req = embedded_payload(wrb); 10949aebddd1SJeff Kirsher 1095106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1096cd3307aaSKalesh AP OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req), 1097cd3307aaSKalesh AP wrb, NULL); 10989aebddd1SJeff Kirsher 10999aebddd1SJeff Kirsher req->hdr.domain = dom; 11009aebddd1SJeff Kirsher req->if_id = cpu_to_le32(if_id); 11019aebddd1SJeff Kirsher req->pmac_id = cpu_to_le32(pmac_id); 11029aebddd1SJeff Kirsher 11039aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 11049aebddd1SJeff Kirsher 11059aebddd1SJeff Kirsher err: 11069aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 11079aebddd1SJeff Kirsher return status; 11089aebddd1SJeff Kirsher } 11099aebddd1SJeff Kirsher 11109aebddd1SJeff Kirsher /* Uses Mbox */ 111110ef9ab4SSathya Perla int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, 111210ef9ab4SSathya Perla struct be_queue_info *eq, bool no_delay, int coalesce_wm) 11139aebddd1SJeff Kirsher { 11149aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 11159aebddd1SJeff Kirsher struct be_cmd_req_cq_create *req; 11169aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &cq->dma_mem; 11179aebddd1SJeff Kirsher void *ctxt; 11189aebddd1SJeff Kirsher int status; 11199aebddd1SJeff Kirsher 11209aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 11219aebddd1SJeff Kirsher return -1; 11229aebddd1SJeff Kirsher 11239aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 11249aebddd1SJeff Kirsher req = embedded_payload(wrb); 11259aebddd1SJeff Kirsher ctxt = &req->context; 11269aebddd1SJeff Kirsher 1127106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1128a2cc4e0bSSathya Perla OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb, 1129a2cc4e0bSSathya Perla NULL); 11309aebddd1SJeff Kirsher 11319aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 1132bbdc42f8SAjit Khaparde 1133bbdc42f8SAjit Khaparde if (BEx_chip(adapter)) { 11349aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt, 11359aebddd1SJeff Kirsher coalesce_wm); 11369aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, nodelay, 11379aebddd1SJeff Kirsher ctxt, no_delay); 11389aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt, 11399aebddd1SJeff Kirsher __ilog2_u32(cq->len / 256)); 11409aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1); 11419aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1); 11429aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id); 1143bbdc42f8SAjit Khaparde } else { 1144bbdc42f8SAjit Khaparde req->hdr.version = 2; 1145bbdc42f8SAjit Khaparde req->page_size = 1; /* 1 for 4K */ 114609e83a9dSAjit Khaparde 114709e83a9dSAjit Khaparde /* coalesce-wm field in this cmd is not relevant to Lancer. 114809e83a9dSAjit Khaparde * Lancer uses COMMON_MODIFY_CQ to set this field 114909e83a9dSAjit Khaparde */ 115009e83a9dSAjit Khaparde if (!lancer_chip(adapter)) 115109e83a9dSAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm, 115209e83a9dSAjit Khaparde ctxt, coalesce_wm); 1153bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt, 1154bbdc42f8SAjit Khaparde no_delay); 1155bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt, 1156bbdc42f8SAjit Khaparde __ilog2_u32(cq->len / 256)); 1157bbdc42f8SAjit Khaparde AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1); 1158a2cc4e0bSSathya Perla AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1); 1159a2cc4e0bSSathya Perla AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id); 11609aebddd1SJeff Kirsher } 11619aebddd1SJeff Kirsher 11629aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 11639aebddd1SJeff Kirsher 11649aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 11659aebddd1SJeff Kirsher 11669aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 11679aebddd1SJeff Kirsher if (!status) { 11689aebddd1SJeff Kirsher struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); 116903d28ffeSKalesh AP 11709aebddd1SJeff Kirsher cq->id = le16_to_cpu(resp->cq_id); 11719aebddd1SJeff Kirsher cq->created = true; 11729aebddd1SJeff Kirsher } 11739aebddd1SJeff Kirsher 11749aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 11759aebddd1SJeff Kirsher 11769aebddd1SJeff Kirsher return status; 11779aebddd1SJeff Kirsher } 11789aebddd1SJeff Kirsher 11799aebddd1SJeff Kirsher static u32 be_encoded_q_len(int q_len) 11809aebddd1SJeff Kirsher { 11819aebddd1SJeff Kirsher u32 len_encoded = fls(q_len); /* log2(len) + 1 */ 118203d28ffeSKalesh AP 11839aebddd1SJeff Kirsher if (len_encoded == 16) 11849aebddd1SJeff Kirsher len_encoded = 0; 11859aebddd1SJeff Kirsher return len_encoded; 11869aebddd1SJeff Kirsher } 11879aebddd1SJeff Kirsher 11884188e7dfSJingoo Han static int be_cmd_mccq_ext_create(struct be_adapter *adapter, 11899aebddd1SJeff Kirsher struct be_queue_info *mccq, 11909aebddd1SJeff Kirsher struct be_queue_info *cq) 11919aebddd1SJeff Kirsher { 11929aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 11939aebddd1SJeff Kirsher struct be_cmd_req_mcc_ext_create *req; 11949aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &mccq->dma_mem; 11959aebddd1SJeff Kirsher void *ctxt; 11969aebddd1SJeff Kirsher int status; 11979aebddd1SJeff Kirsher 11989aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 11999aebddd1SJeff Kirsher return -1; 12009aebddd1SJeff Kirsher 12019aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 12029aebddd1SJeff Kirsher req = embedded_payload(wrb); 12039aebddd1SJeff Kirsher ctxt = &req->context; 12049aebddd1SJeff Kirsher 1205106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1206a2cc4e0bSSathya Perla OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb, 1207a2cc4e0bSSathya Perla NULL); 12089aebddd1SJeff Kirsher 12099aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 1210666d39c7SVasundhara Volam if (BEx_chip(adapter)) { 12119aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); 12129aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, 12139aebddd1SJeff Kirsher be_encoded_q_len(mccq->len)); 12149aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); 1215666d39c7SVasundhara Volam } else { 1216666d39c7SVasundhara Volam req->hdr.version = 1; 1217666d39c7SVasundhara Volam req->cq_id = cpu_to_le16(cq->id); 1218666d39c7SVasundhara Volam 1219666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, ring_size, ctxt, 1220666d39c7SVasundhara Volam be_encoded_q_len(mccq->len)); 1221666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, valid, ctxt, 1); 1222666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_id, 1223666d39c7SVasundhara Volam ctxt, cq->id); 1224666d39c7SVasundhara Volam AMAP_SET_BITS(struct amap_mcc_context_v1, async_cq_valid, 1225666d39c7SVasundhara Volam ctxt, 1); 12269aebddd1SJeff Kirsher } 12279aebddd1SJeff Kirsher 122821252377SVasundhara Volam /* Subscribe to Link State, Sliport Event and Group 5 Events 122921252377SVasundhara Volam * (bits 1, 5 and 17 set) 123021252377SVasundhara Volam */ 123121252377SVasundhara Volam req->async_event_bitmap[0] = 123221252377SVasundhara Volam cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) | 123321252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_GRP_5) | 123421252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_QNQ) | 123521252377SVasundhara Volam BIT(ASYNC_EVENT_CODE_SLIPORT)); 123621252377SVasundhara Volam 12379aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 12389aebddd1SJeff Kirsher 12399aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 12409aebddd1SJeff Kirsher 12419aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 12429aebddd1SJeff Kirsher if (!status) { 12439aebddd1SJeff Kirsher struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); 124403d28ffeSKalesh AP 12459aebddd1SJeff Kirsher mccq->id = le16_to_cpu(resp->id); 12469aebddd1SJeff Kirsher mccq->created = true; 12479aebddd1SJeff Kirsher } 12489aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 12499aebddd1SJeff Kirsher 12509aebddd1SJeff Kirsher return status; 12519aebddd1SJeff Kirsher } 12529aebddd1SJeff Kirsher 12534188e7dfSJingoo Han static int be_cmd_mccq_org_create(struct be_adapter *adapter, 12549aebddd1SJeff Kirsher struct be_queue_info *mccq, 12559aebddd1SJeff Kirsher struct be_queue_info *cq) 12569aebddd1SJeff Kirsher { 12579aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 12589aebddd1SJeff Kirsher struct be_cmd_req_mcc_create *req; 12599aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &mccq->dma_mem; 12609aebddd1SJeff Kirsher void *ctxt; 12619aebddd1SJeff Kirsher int status; 12629aebddd1SJeff Kirsher 12639aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 12649aebddd1SJeff Kirsher return -1; 12659aebddd1SJeff Kirsher 12669aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 12679aebddd1SJeff Kirsher req = embedded_payload(wrb); 12689aebddd1SJeff Kirsher ctxt = &req->context; 12699aebddd1SJeff Kirsher 1270106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1271a2cc4e0bSSathya Perla OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb, 1272a2cc4e0bSSathya Perla NULL); 12739aebddd1SJeff Kirsher 12749aebddd1SJeff Kirsher req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 12759aebddd1SJeff Kirsher 12769aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); 12779aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, 12789aebddd1SJeff Kirsher be_encoded_q_len(mccq->len)); 12799aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); 12809aebddd1SJeff Kirsher 12819aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 12829aebddd1SJeff Kirsher 12839aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 12849aebddd1SJeff Kirsher 12859aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 12869aebddd1SJeff Kirsher if (!status) { 12879aebddd1SJeff Kirsher struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); 128803d28ffeSKalesh AP 12899aebddd1SJeff Kirsher mccq->id = le16_to_cpu(resp->id); 12909aebddd1SJeff Kirsher mccq->created = true; 12919aebddd1SJeff Kirsher } 12929aebddd1SJeff Kirsher 12939aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 12949aebddd1SJeff Kirsher return status; 12959aebddd1SJeff Kirsher } 12969aebddd1SJeff Kirsher 12979aebddd1SJeff Kirsher int be_cmd_mccq_create(struct be_adapter *adapter, 1298a2cc4e0bSSathya Perla struct be_queue_info *mccq, struct be_queue_info *cq) 12999aebddd1SJeff Kirsher { 13009aebddd1SJeff Kirsher int status; 13019aebddd1SJeff Kirsher 13029aebddd1SJeff Kirsher status = be_cmd_mccq_ext_create(adapter, mccq, cq); 1303666d39c7SVasundhara Volam if (status && BEx_chip(adapter)) { 13049aebddd1SJeff Kirsher dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 " 13059aebddd1SJeff Kirsher "or newer to avoid conflicting priorities between NIC " 13069aebddd1SJeff Kirsher "and FCoE traffic"); 13079aebddd1SJeff Kirsher status = be_cmd_mccq_org_create(adapter, mccq, cq); 13089aebddd1SJeff Kirsher } 13099aebddd1SJeff Kirsher return status; 13109aebddd1SJeff Kirsher } 13119aebddd1SJeff Kirsher 131294d73aaaSVasundhara Volam int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) 13139aebddd1SJeff Kirsher { 13147707133cSSathya Perla struct be_mcc_wrb wrb = {0}; 13159aebddd1SJeff Kirsher struct be_cmd_req_eth_tx_create *req; 131694d73aaaSVasundhara Volam struct be_queue_info *txq = &txo->q; 131794d73aaaSVasundhara Volam struct be_queue_info *cq = &txo->cq; 13189aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &txq->dma_mem; 131994d73aaaSVasundhara Volam int status, ver = 0; 13209aebddd1SJeff Kirsher 13217707133cSSathya Perla req = embedded_payload(&wrb); 1322106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 13237707133cSSathya Perla OPCODE_ETH_TX_CREATE, sizeof(*req), &wrb, NULL); 13249aebddd1SJeff Kirsher 13259aebddd1SJeff Kirsher if (lancer_chip(adapter)) { 13269aebddd1SJeff Kirsher req->hdr.version = 1; 132794d73aaaSVasundhara Volam } else if (BEx_chip(adapter)) { 132894d73aaaSVasundhara Volam if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) 132994d73aaaSVasundhara Volam req->hdr.version = 2; 133094d73aaaSVasundhara Volam } else { /* For SH */ 133194d73aaaSVasundhara Volam req->hdr.version = 2; 13329aebddd1SJeff Kirsher } 13339aebddd1SJeff Kirsher 133481b02655SVasundhara Volam if (req->hdr.version > 0) 133581b02655SVasundhara Volam req->if_id = cpu_to_le16(adapter->if_handle); 13369aebddd1SJeff Kirsher req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); 13379aebddd1SJeff Kirsher req->ulp_num = BE_ULP1_NUM; 13389aebddd1SJeff Kirsher req->type = BE_ETH_TX_RING_TYPE_STANDARD; 133994d73aaaSVasundhara Volam req->cq_id = cpu_to_le16(cq->id); 134094d73aaaSVasundhara Volam req->queue_size = be_encoded_q_len(txq->len); 13419aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 134294d73aaaSVasundhara Volam ver = req->hdr.version; 134394d73aaaSVasundhara Volam 13447707133cSSathya Perla status = be_cmd_notify_wait(adapter, &wrb); 13459aebddd1SJeff Kirsher if (!status) { 13467707133cSSathya Perla struct be_cmd_resp_eth_tx_create *resp = embedded_payload(&wrb); 134703d28ffeSKalesh AP 13489aebddd1SJeff Kirsher txq->id = le16_to_cpu(resp->cid); 134994d73aaaSVasundhara Volam if (ver == 2) 135094d73aaaSVasundhara Volam txo->db_offset = le32_to_cpu(resp->db_offset); 135194d73aaaSVasundhara Volam else 135294d73aaaSVasundhara Volam txo->db_offset = DB_TXULP1_OFFSET; 13539aebddd1SJeff Kirsher txq->created = true; 13549aebddd1SJeff Kirsher } 13559aebddd1SJeff Kirsher 13569aebddd1SJeff Kirsher return status; 13579aebddd1SJeff Kirsher } 13589aebddd1SJeff Kirsher 13599aebddd1SJeff Kirsher /* Uses MCC */ 13609aebddd1SJeff Kirsher int be_cmd_rxq_create(struct be_adapter *adapter, 13619aebddd1SJeff Kirsher struct be_queue_info *rxq, u16 cq_id, u16 frag_size, 136210ef9ab4SSathya Perla u32 if_id, u32 rss, u8 *rss_id) 13639aebddd1SJeff Kirsher { 13649aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 13659aebddd1SJeff Kirsher struct be_cmd_req_eth_rx_create *req; 13669aebddd1SJeff Kirsher struct be_dma_mem *q_mem = &rxq->dma_mem; 13679aebddd1SJeff Kirsher int status; 13689aebddd1SJeff Kirsher 13699aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 13709aebddd1SJeff Kirsher 13719aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 13729aebddd1SJeff Kirsher if (!wrb) { 13739aebddd1SJeff Kirsher status = -EBUSY; 13749aebddd1SJeff Kirsher goto err; 13759aebddd1SJeff Kirsher } 13769aebddd1SJeff Kirsher req = embedded_payload(wrb); 13779aebddd1SJeff Kirsher 1378106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1379106df1e3SSomnath Kotur OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL); 13809aebddd1SJeff Kirsher 13819aebddd1SJeff Kirsher req->cq_id = cpu_to_le16(cq_id); 13829aebddd1SJeff Kirsher req->frag_size = fls(frag_size) - 1; 13839aebddd1SJeff Kirsher req->num_pages = 2; 13849aebddd1SJeff Kirsher be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 13859aebddd1SJeff Kirsher req->interface_id = cpu_to_le32(if_id); 138610ef9ab4SSathya Perla req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE); 13879aebddd1SJeff Kirsher req->rss_queue = cpu_to_le32(rss); 13889aebddd1SJeff Kirsher 13899aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 13909aebddd1SJeff Kirsher if (!status) { 13919aebddd1SJeff Kirsher struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); 139203d28ffeSKalesh AP 13939aebddd1SJeff Kirsher rxq->id = le16_to_cpu(resp->id); 13949aebddd1SJeff Kirsher rxq->created = true; 13959aebddd1SJeff Kirsher *rss_id = resp->rss_id; 13969aebddd1SJeff Kirsher } 13979aebddd1SJeff Kirsher 13989aebddd1SJeff Kirsher err: 13999aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 14009aebddd1SJeff Kirsher return status; 14019aebddd1SJeff Kirsher } 14029aebddd1SJeff Kirsher 14039aebddd1SJeff Kirsher /* Generic destroyer function for all types of queues 14049aebddd1SJeff Kirsher * Uses Mbox 14059aebddd1SJeff Kirsher */ 14069aebddd1SJeff Kirsher int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, 14079aebddd1SJeff Kirsher int queue_type) 14089aebddd1SJeff Kirsher { 14099aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 14109aebddd1SJeff Kirsher struct be_cmd_req_q_destroy *req; 14119aebddd1SJeff Kirsher u8 subsys = 0, opcode = 0; 14129aebddd1SJeff Kirsher int status; 14139aebddd1SJeff Kirsher 14149aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 14159aebddd1SJeff Kirsher return -1; 14169aebddd1SJeff Kirsher 14179aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 14189aebddd1SJeff Kirsher req = embedded_payload(wrb); 14199aebddd1SJeff Kirsher 14209aebddd1SJeff Kirsher switch (queue_type) { 14219aebddd1SJeff Kirsher case QTYPE_EQ: 14229aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 14239aebddd1SJeff Kirsher opcode = OPCODE_COMMON_EQ_DESTROY; 14249aebddd1SJeff Kirsher break; 14259aebddd1SJeff Kirsher case QTYPE_CQ: 14269aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 14279aebddd1SJeff Kirsher opcode = OPCODE_COMMON_CQ_DESTROY; 14289aebddd1SJeff Kirsher break; 14299aebddd1SJeff Kirsher case QTYPE_TXQ: 14309aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_ETH; 14319aebddd1SJeff Kirsher opcode = OPCODE_ETH_TX_DESTROY; 14329aebddd1SJeff Kirsher break; 14339aebddd1SJeff Kirsher case QTYPE_RXQ: 14349aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_ETH; 14359aebddd1SJeff Kirsher opcode = OPCODE_ETH_RX_DESTROY; 14369aebddd1SJeff Kirsher break; 14379aebddd1SJeff Kirsher case QTYPE_MCCQ: 14389aebddd1SJeff Kirsher subsys = CMD_SUBSYSTEM_COMMON; 14399aebddd1SJeff Kirsher opcode = OPCODE_COMMON_MCC_DESTROY; 14409aebddd1SJeff Kirsher break; 14419aebddd1SJeff Kirsher default: 14429aebddd1SJeff Kirsher BUG(); 14439aebddd1SJeff Kirsher } 14449aebddd1SJeff Kirsher 1445106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb, 1446106df1e3SSomnath Kotur NULL); 14479aebddd1SJeff Kirsher req->id = cpu_to_le16(q->id); 14489aebddd1SJeff Kirsher 14499aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 14509aebddd1SJeff Kirsher q->created = false; 14519aebddd1SJeff Kirsher 14529aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 14539aebddd1SJeff Kirsher return status; 14549aebddd1SJeff Kirsher } 14559aebddd1SJeff Kirsher 14569aebddd1SJeff Kirsher /* Uses MCC */ 14579aebddd1SJeff Kirsher int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) 14589aebddd1SJeff Kirsher { 14599aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 14609aebddd1SJeff Kirsher struct be_cmd_req_q_destroy *req; 14619aebddd1SJeff Kirsher int status; 14629aebddd1SJeff Kirsher 14639aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 14649aebddd1SJeff Kirsher 14659aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 14669aebddd1SJeff Kirsher if (!wrb) { 14679aebddd1SJeff Kirsher status = -EBUSY; 14689aebddd1SJeff Kirsher goto err; 14699aebddd1SJeff Kirsher } 14709aebddd1SJeff Kirsher req = embedded_payload(wrb); 14719aebddd1SJeff Kirsher 1472106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1473106df1e3SSomnath Kotur OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL); 14749aebddd1SJeff Kirsher req->id = cpu_to_le16(q->id); 14759aebddd1SJeff Kirsher 14769aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 14779aebddd1SJeff Kirsher q->created = false; 14789aebddd1SJeff Kirsher 14799aebddd1SJeff Kirsher err: 14809aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 14819aebddd1SJeff Kirsher return status; 14829aebddd1SJeff Kirsher } 14839aebddd1SJeff Kirsher 14849aebddd1SJeff Kirsher /* Create an rx filtering policy configuration on an i/f 1485bea50988SSathya Perla * Will use MBOX only if MCCQ has not been created. 14869aebddd1SJeff Kirsher */ 14879aebddd1SJeff Kirsher int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, 14881578e777SPadmanabh Ratnakar u32 *if_handle, u32 domain) 14899aebddd1SJeff Kirsher { 1490bea50988SSathya Perla struct be_mcc_wrb wrb = {0}; 14919aebddd1SJeff Kirsher struct be_cmd_req_if_create *req; 14929aebddd1SJeff Kirsher int status; 14939aebddd1SJeff Kirsher 1494bea50988SSathya Perla req = embedded_payload(&wrb); 1495106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1496a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_INTERFACE_CREATE, 1497a2cc4e0bSSathya Perla sizeof(*req), &wrb, NULL); 14989aebddd1SJeff Kirsher req->hdr.domain = domain; 14999aebddd1SJeff Kirsher req->capability_flags = cpu_to_le32(cap_flags); 15009aebddd1SJeff Kirsher req->enable_flags = cpu_to_le32(en_flags); 1501f9449ab7SSathya Perla req->pmac_invalid = true; 15029aebddd1SJeff Kirsher 1503bea50988SSathya Perla status = be_cmd_notify_wait(adapter, &wrb); 15049aebddd1SJeff Kirsher if (!status) { 1505bea50988SSathya Perla struct be_cmd_resp_if_create *resp = embedded_payload(&wrb); 150603d28ffeSKalesh AP 15079aebddd1SJeff Kirsher *if_handle = le32_to_cpu(resp->interface_id); 1508b5bb9776SSathya Perla 1509b5bb9776SSathya Perla /* Hack to retrieve VF's pmac-id on BE3 */ 151018c57c74SKalesh AP if (BE3_chip(adapter) && be_virtfn(adapter)) 1511b5bb9776SSathya Perla adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id); 15129aebddd1SJeff Kirsher } 15139aebddd1SJeff Kirsher return status; 15149aebddd1SJeff Kirsher } 15159aebddd1SJeff Kirsher 151662219066SAjit Khaparde /* Uses MCCQ if available else MBOX */ 151730128031SSathya Perla int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain) 15189aebddd1SJeff Kirsher { 151962219066SAjit Khaparde struct be_mcc_wrb wrb = {0}; 15209aebddd1SJeff Kirsher struct be_cmd_req_if_destroy *req; 15219aebddd1SJeff Kirsher int status; 15229aebddd1SJeff Kirsher 152330128031SSathya Perla if (interface_id == -1) 1524f9449ab7SSathya Perla return 0; 15259aebddd1SJeff Kirsher 152662219066SAjit Khaparde req = embedded_payload(&wrb); 15279aebddd1SJeff Kirsher 1528106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1529a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_INTERFACE_DESTROY, 153062219066SAjit Khaparde sizeof(*req), &wrb, NULL); 15319aebddd1SJeff Kirsher req->hdr.domain = domain; 15329aebddd1SJeff Kirsher req->interface_id = cpu_to_le32(interface_id); 15339aebddd1SJeff Kirsher 153462219066SAjit Khaparde status = be_cmd_notify_wait(adapter, &wrb); 15359aebddd1SJeff Kirsher return status; 15369aebddd1SJeff Kirsher } 15379aebddd1SJeff Kirsher 15389aebddd1SJeff Kirsher /* Get stats is a non embedded command: the request is not embedded inside 15399aebddd1SJeff Kirsher * WRB but is a separate dma memory block 15409aebddd1SJeff Kirsher * Uses asynchronous MCC 15419aebddd1SJeff Kirsher */ 15429aebddd1SJeff Kirsher int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) 15439aebddd1SJeff Kirsher { 15449aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 15459aebddd1SJeff Kirsher struct be_cmd_req_hdr *hdr; 15469aebddd1SJeff Kirsher int status = 0; 15479aebddd1SJeff Kirsher 15489aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 15499aebddd1SJeff Kirsher 15509aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 15519aebddd1SJeff Kirsher if (!wrb) { 15529aebddd1SJeff Kirsher status = -EBUSY; 15539aebddd1SJeff Kirsher goto err; 15549aebddd1SJeff Kirsher } 15559aebddd1SJeff Kirsher hdr = nonemb_cmd->va; 15569aebddd1SJeff Kirsher 1557106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH, 1558a2cc4e0bSSathya Perla OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, 1559a2cc4e0bSSathya Perla nonemb_cmd); 15609aebddd1SJeff Kirsher 1561ca34fe38SSathya Perla /* version 1 of the cmd is not supported only by BE2 */ 156261000861SAjit Khaparde if (BE2_chip(adapter)) 156361000861SAjit Khaparde hdr->version = 0; 156461000861SAjit Khaparde if (BE3_chip(adapter) || lancer_chip(adapter)) 15659aebddd1SJeff Kirsher hdr->version = 1; 156661000861SAjit Khaparde else 156761000861SAjit Khaparde hdr->version = 2; 15689aebddd1SJeff Kirsher 1569efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 1570efaa408eSSuresh Reddy if (status) 1571efaa408eSSuresh Reddy goto err; 1572efaa408eSSuresh Reddy 15739aebddd1SJeff Kirsher adapter->stats_cmd_sent = true; 15749aebddd1SJeff Kirsher 15759aebddd1SJeff Kirsher err: 15769aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 15779aebddd1SJeff Kirsher return status; 15789aebddd1SJeff Kirsher } 15799aebddd1SJeff Kirsher 15809aebddd1SJeff Kirsher /* Lancer Stats */ 15819aebddd1SJeff Kirsher int lancer_cmd_get_pport_stats(struct be_adapter *adapter, 15829aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 15839aebddd1SJeff Kirsher { 15849aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 15859aebddd1SJeff Kirsher struct lancer_cmd_req_pport_stats *req; 15869aebddd1SJeff Kirsher int status = 0; 15879aebddd1SJeff Kirsher 1588f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS, 1589f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH)) 1590f25b119cSPadmanabh Ratnakar return -EPERM; 1591f25b119cSPadmanabh Ratnakar 15929aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 15939aebddd1SJeff Kirsher 15949aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 15959aebddd1SJeff Kirsher if (!wrb) { 15969aebddd1SJeff Kirsher status = -EBUSY; 15979aebddd1SJeff Kirsher goto err; 15989aebddd1SJeff Kirsher } 15999aebddd1SJeff Kirsher req = nonemb_cmd->va; 16009aebddd1SJeff Kirsher 1601106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 1602a2cc4e0bSSathya Perla OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, 1603a2cc4e0bSSathya Perla wrb, nonemb_cmd); 16049aebddd1SJeff Kirsher 1605d51ebd33SPadmanabh Ratnakar req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num); 16069aebddd1SJeff Kirsher req->cmd_params.params.reset_stats = 0; 16079aebddd1SJeff Kirsher 1608efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 1609efaa408eSSuresh Reddy if (status) 1610efaa408eSSuresh Reddy goto err; 1611efaa408eSSuresh Reddy 16129aebddd1SJeff Kirsher adapter->stats_cmd_sent = true; 16139aebddd1SJeff Kirsher 16149aebddd1SJeff Kirsher err: 16159aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 16169aebddd1SJeff Kirsher return status; 16179aebddd1SJeff Kirsher } 16189aebddd1SJeff Kirsher 1619323ff71eSSathya Perla static int be_mac_to_link_speed(int mac_speed) 1620323ff71eSSathya Perla { 1621323ff71eSSathya Perla switch (mac_speed) { 1622323ff71eSSathya Perla case PHY_LINK_SPEED_ZERO: 1623323ff71eSSathya Perla return 0; 1624323ff71eSSathya Perla case PHY_LINK_SPEED_10MBPS: 1625323ff71eSSathya Perla return 10; 1626323ff71eSSathya Perla case PHY_LINK_SPEED_100MBPS: 1627323ff71eSSathya Perla return 100; 1628323ff71eSSathya Perla case PHY_LINK_SPEED_1GBPS: 1629323ff71eSSathya Perla return 1000; 1630323ff71eSSathya Perla case PHY_LINK_SPEED_10GBPS: 1631323ff71eSSathya Perla return 10000; 1632b971f847SVasundhara Volam case PHY_LINK_SPEED_20GBPS: 1633b971f847SVasundhara Volam return 20000; 1634b971f847SVasundhara Volam case PHY_LINK_SPEED_25GBPS: 1635b971f847SVasundhara Volam return 25000; 1636b971f847SVasundhara Volam case PHY_LINK_SPEED_40GBPS: 1637b971f847SVasundhara Volam return 40000; 1638323ff71eSSathya Perla } 1639323ff71eSSathya Perla return 0; 1640323ff71eSSathya Perla } 1641323ff71eSSathya Perla 1642323ff71eSSathya Perla /* Uses synchronous mcc 1643323ff71eSSathya Perla * Returns link_speed in Mbps 1644323ff71eSSathya Perla */ 1645323ff71eSSathya Perla int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, 1646323ff71eSSathya Perla u8 *link_status, u32 dom) 16479aebddd1SJeff Kirsher { 16489aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 16499aebddd1SJeff Kirsher struct be_cmd_req_link_status *req; 16509aebddd1SJeff Kirsher int status; 16519aebddd1SJeff Kirsher 16529aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 16539aebddd1SJeff Kirsher 1654b236916aSAjit Khaparde if (link_status) 1655b236916aSAjit Khaparde *link_status = LINK_DOWN; 1656b236916aSAjit Khaparde 16579aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 16589aebddd1SJeff Kirsher if (!wrb) { 16599aebddd1SJeff Kirsher status = -EBUSY; 16609aebddd1SJeff Kirsher goto err; 16619aebddd1SJeff Kirsher } 16629aebddd1SJeff Kirsher req = embedded_payload(wrb); 16639aebddd1SJeff Kirsher 166457cd80d4SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1665a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, 1666a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 166757cd80d4SPadmanabh Ratnakar 1668ca34fe38SSathya Perla /* version 1 of the cmd is not supported only by BE2 */ 1669ca34fe38SSathya Perla if (!BE2_chip(adapter)) 1670daad6167SPadmanabh Ratnakar req->hdr.version = 1; 1671daad6167SPadmanabh Ratnakar 167257cd80d4SPadmanabh Ratnakar req->hdr.domain = dom; 16739aebddd1SJeff Kirsher 16749aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 16759aebddd1SJeff Kirsher if (!status) { 16769aebddd1SJeff Kirsher struct be_cmd_resp_link_status *resp = embedded_payload(wrb); 167703d28ffeSKalesh AP 1678323ff71eSSathya Perla if (link_speed) { 1679323ff71eSSathya Perla *link_speed = resp->link_speed ? 1680323ff71eSSathya Perla le16_to_cpu(resp->link_speed) * 10 : 1681323ff71eSSathya Perla be_mac_to_link_speed(resp->mac_speed); 1682323ff71eSSathya Perla 1683323ff71eSSathya Perla if (!resp->logical_link_status) 1684323ff71eSSathya Perla *link_speed = 0; 16859aebddd1SJeff Kirsher } 1686b236916aSAjit Khaparde if (link_status) 1687b236916aSAjit Khaparde *link_status = resp->logical_link_status; 16889aebddd1SJeff Kirsher } 16899aebddd1SJeff Kirsher 16909aebddd1SJeff Kirsher err: 16919aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 16929aebddd1SJeff Kirsher return status; 16939aebddd1SJeff Kirsher } 16949aebddd1SJeff Kirsher 16959aebddd1SJeff Kirsher /* Uses synchronous mcc */ 16969aebddd1SJeff Kirsher int be_cmd_get_die_temperature(struct be_adapter *adapter) 16979aebddd1SJeff Kirsher { 16989aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 16999aebddd1SJeff Kirsher struct be_cmd_req_get_cntl_addnl_attribs *req; 1700117affe3SVasundhara Volam int status = 0; 17019aebddd1SJeff Kirsher 17029aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 17039aebddd1SJeff Kirsher 17049aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 17059aebddd1SJeff Kirsher if (!wrb) { 17069aebddd1SJeff Kirsher status = -EBUSY; 17079aebddd1SJeff Kirsher goto err; 17089aebddd1SJeff Kirsher } 17099aebddd1SJeff Kirsher req = embedded_payload(wrb); 17109aebddd1SJeff Kirsher 1711106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1712a2cc4e0bSSathya Perla OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, 1713a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 17149aebddd1SJeff Kirsher 1715efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 17169aebddd1SJeff Kirsher err: 17179aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 17189aebddd1SJeff Kirsher return status; 17199aebddd1SJeff Kirsher } 17209aebddd1SJeff Kirsher 17219aebddd1SJeff Kirsher /* Uses synchronous mcc */ 1722fd7ff6f0SVenkat Duvvuru int be_cmd_get_fat_dump_len(struct be_adapter *adapter, u32 *dump_size) 17239aebddd1SJeff Kirsher { 1724fd7ff6f0SVenkat Duvvuru struct be_mcc_wrb wrb = {0}; 17259aebddd1SJeff Kirsher struct be_cmd_req_get_fat *req; 17269aebddd1SJeff Kirsher int status; 17279aebddd1SJeff Kirsher 1728fd7ff6f0SVenkat Duvvuru req = embedded_payload(&wrb); 17299aebddd1SJeff Kirsher 1730106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1731fd7ff6f0SVenkat Duvvuru OPCODE_COMMON_MANAGE_FAT, sizeof(*req), 1732fd7ff6f0SVenkat Duvvuru &wrb, NULL); 17339aebddd1SJeff Kirsher req->fat_operation = cpu_to_le32(QUERY_FAT); 1734fd7ff6f0SVenkat Duvvuru status = be_cmd_notify_wait(adapter, &wrb); 17359aebddd1SJeff Kirsher if (!status) { 1736fd7ff6f0SVenkat Duvvuru struct be_cmd_resp_get_fat *resp = embedded_payload(&wrb); 173703d28ffeSKalesh AP 1738fd7ff6f0SVenkat Duvvuru if (dump_size && resp->log_size) 1739fd7ff6f0SVenkat Duvvuru *dump_size = le32_to_cpu(resp->log_size) - 17409aebddd1SJeff Kirsher sizeof(u32); 17419aebddd1SJeff Kirsher } 17429aebddd1SJeff Kirsher return status; 17439aebddd1SJeff Kirsher } 17449aebddd1SJeff Kirsher 1745fd7ff6f0SVenkat Duvvuru int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf) 17469aebddd1SJeff Kirsher { 17479aebddd1SJeff Kirsher struct be_dma_mem get_fat_cmd; 17489aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 17499aebddd1SJeff Kirsher struct be_cmd_req_get_fat *req; 17509aebddd1SJeff Kirsher u32 offset = 0, total_size, buf_size, 17519aebddd1SJeff Kirsher log_offset = sizeof(u32), payload_len; 1752fd7ff6f0SVenkat Duvvuru int status; 17539aebddd1SJeff Kirsher 17549aebddd1SJeff Kirsher if (buf_len == 0) 1755fd7ff6f0SVenkat Duvvuru return 0; 17569aebddd1SJeff Kirsher 17579aebddd1SJeff Kirsher total_size = buf_len; 17589aebddd1SJeff Kirsher 17599aebddd1SJeff Kirsher get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024; 1760e51000dbSSriharsha Basavapatna get_fat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 17619aebddd1SJeff Kirsher get_fat_cmd.size, 1762e51000dbSSriharsha Basavapatna &get_fat_cmd.dma, GFP_ATOMIC); 1763fd7ff6f0SVenkat Duvvuru if (!get_fat_cmd.va) 1764c5f156deSVasundhara Volam return -ENOMEM; 17659aebddd1SJeff Kirsher 17669aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 17679aebddd1SJeff Kirsher 17689aebddd1SJeff Kirsher while (total_size) { 17699aebddd1SJeff Kirsher buf_size = min(total_size, (u32)60*1024); 17709aebddd1SJeff Kirsher total_size -= buf_size; 17719aebddd1SJeff Kirsher 17729aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 17739aebddd1SJeff Kirsher if (!wrb) { 17749aebddd1SJeff Kirsher status = -EBUSY; 17759aebddd1SJeff Kirsher goto err; 17769aebddd1SJeff Kirsher } 17779aebddd1SJeff Kirsher req = get_fat_cmd.va; 17789aebddd1SJeff Kirsher 17799aebddd1SJeff Kirsher payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size; 1780106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1781a2cc4e0bSSathya Perla OPCODE_COMMON_MANAGE_FAT, payload_len, 1782a2cc4e0bSSathya Perla wrb, &get_fat_cmd); 17839aebddd1SJeff Kirsher 17849aebddd1SJeff Kirsher req->fat_operation = cpu_to_le32(RETRIEVE_FAT); 17859aebddd1SJeff Kirsher req->read_log_offset = cpu_to_le32(log_offset); 17869aebddd1SJeff Kirsher req->read_log_length = cpu_to_le32(buf_size); 17879aebddd1SJeff Kirsher req->data_buffer_size = cpu_to_le32(buf_size); 17889aebddd1SJeff Kirsher 17899aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 17909aebddd1SJeff Kirsher if (!status) { 17919aebddd1SJeff Kirsher struct be_cmd_resp_get_fat *resp = get_fat_cmd.va; 179203d28ffeSKalesh AP 17939aebddd1SJeff Kirsher memcpy(buf + offset, 17949aebddd1SJeff Kirsher resp->data_buffer, 179592aa9214SSomnath Kotur le32_to_cpu(resp->read_log_length)); 17969aebddd1SJeff Kirsher } else { 17979aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n"); 17989aebddd1SJeff Kirsher goto err; 17999aebddd1SJeff Kirsher } 18009aebddd1SJeff Kirsher offset += buf_size; 18019aebddd1SJeff Kirsher log_offset += buf_size; 18029aebddd1SJeff Kirsher } 18039aebddd1SJeff Kirsher err: 1804e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, get_fat_cmd.size, 1805a2cc4e0bSSathya Perla get_fat_cmd.va, get_fat_cmd.dma); 18069aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 1807c5f156deSVasundhara Volam return status; 18089aebddd1SJeff Kirsher } 18099aebddd1SJeff Kirsher 181004b71175SSathya Perla /* Uses synchronous mcc */ 1811e97e3cdaSKalesh AP int be_cmd_get_fw_ver(struct be_adapter *adapter) 18129aebddd1SJeff Kirsher { 18139aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 18149aebddd1SJeff Kirsher struct be_cmd_req_get_fw_version *req; 18159aebddd1SJeff Kirsher int status; 18169aebddd1SJeff Kirsher 181704b71175SSathya Perla spin_lock_bh(&adapter->mcc_lock); 18189aebddd1SJeff Kirsher 181904b71175SSathya Perla wrb = wrb_from_mccq(adapter); 182004b71175SSathya Perla if (!wrb) { 182104b71175SSathya Perla status = -EBUSY; 182204b71175SSathya Perla goto err; 182304b71175SSathya Perla } 182404b71175SSathya Perla 18259aebddd1SJeff Kirsher req = embedded_payload(wrb); 18269aebddd1SJeff Kirsher 1827106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1828a2cc4e0bSSathya Perla OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb, 1829a2cc4e0bSSathya Perla NULL); 183004b71175SSathya Perla status = be_mcc_notify_wait(adapter); 18319aebddd1SJeff Kirsher if (!status) { 18329aebddd1SJeff Kirsher struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb); 1833acbafeb1SSathya Perla 1834242eb470SVasundhara Volam strlcpy(adapter->fw_ver, resp->firmware_version_string, 1835242eb470SVasundhara Volam sizeof(adapter->fw_ver)); 1836242eb470SVasundhara Volam strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string, 1837242eb470SVasundhara Volam sizeof(adapter->fw_on_flash)); 18389aebddd1SJeff Kirsher } 183904b71175SSathya Perla err: 184004b71175SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 18419aebddd1SJeff Kirsher return status; 18429aebddd1SJeff Kirsher } 18439aebddd1SJeff Kirsher 18449aebddd1SJeff Kirsher /* set the EQ delay interval of an EQ to specified value 18459aebddd1SJeff Kirsher * Uses async mcc 18469aebddd1SJeff Kirsher */ 1847b502ae8dSKalesh AP static int __be_cmd_modify_eqd(struct be_adapter *adapter, 1848b502ae8dSKalesh AP struct be_set_eqd *set_eqd, int num) 18499aebddd1SJeff Kirsher { 18509aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 18519aebddd1SJeff Kirsher struct be_cmd_req_modify_eq_delay *req; 18522632bafdSSathya Perla int status = 0, i; 18539aebddd1SJeff Kirsher 18549aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 18559aebddd1SJeff Kirsher 18569aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 18579aebddd1SJeff Kirsher if (!wrb) { 18589aebddd1SJeff Kirsher status = -EBUSY; 18599aebddd1SJeff Kirsher goto err; 18609aebddd1SJeff Kirsher } 18619aebddd1SJeff Kirsher req = embedded_payload(wrb); 18629aebddd1SJeff Kirsher 1863106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1864a2cc4e0bSSathya Perla OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb, 1865a2cc4e0bSSathya Perla NULL); 18669aebddd1SJeff Kirsher 18672632bafdSSathya Perla req->num_eq = cpu_to_le32(num); 18682632bafdSSathya Perla for (i = 0; i < num; i++) { 18692632bafdSSathya Perla req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id); 18702632bafdSSathya Perla req->set_eqd[i].phase = 0; 18712632bafdSSathya Perla req->set_eqd[i].delay_multiplier = 18722632bafdSSathya Perla cpu_to_le32(set_eqd[i].delay_multiplier); 18732632bafdSSathya Perla } 18749aebddd1SJeff Kirsher 1875efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 18769aebddd1SJeff Kirsher err: 18779aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 18789aebddd1SJeff Kirsher return status; 18799aebddd1SJeff Kirsher } 18809aebddd1SJeff Kirsher 188193676703SKalesh AP int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd, 188293676703SKalesh AP int num) 188393676703SKalesh AP { 188493676703SKalesh AP int num_eqs, i = 0; 188593676703SKalesh AP 188693676703SKalesh AP while (num) { 188793676703SKalesh AP num_eqs = min(num, 8); 188893676703SKalesh AP __be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs); 188993676703SKalesh AP i += num_eqs; 189093676703SKalesh AP num -= num_eqs; 189193676703SKalesh AP } 189293676703SKalesh AP 189393676703SKalesh AP return 0; 189493676703SKalesh AP } 189593676703SKalesh AP 18969aebddd1SJeff Kirsher /* Uses sycnhronous mcc */ 18979aebddd1SJeff Kirsher int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, 1898435452aaSVasundhara Volam u32 num, u32 domain) 18999aebddd1SJeff Kirsher { 19009aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19019aebddd1SJeff Kirsher struct be_cmd_req_vlan_config *req; 19029aebddd1SJeff Kirsher int status; 19039aebddd1SJeff Kirsher 19049aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 19059aebddd1SJeff Kirsher 19069aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 19079aebddd1SJeff Kirsher if (!wrb) { 19089aebddd1SJeff Kirsher status = -EBUSY; 19099aebddd1SJeff Kirsher goto err; 19109aebddd1SJeff Kirsher } 19119aebddd1SJeff Kirsher req = embedded_payload(wrb); 19129aebddd1SJeff Kirsher 1913106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1914a2cc4e0bSSathya Perla OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req), 1915a2cc4e0bSSathya Perla wrb, NULL); 1916435452aaSVasundhara Volam req->hdr.domain = domain; 19179aebddd1SJeff Kirsher 19189aebddd1SJeff Kirsher req->interface_id = if_id; 1919012bd387SAjit Khaparde req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0; 19209aebddd1SJeff Kirsher req->num_vlan = num; 19219aebddd1SJeff Kirsher memcpy(req->normal_vlan, vtag_array, 19229aebddd1SJeff Kirsher req->num_vlan * sizeof(vtag_array[0])); 19239aebddd1SJeff Kirsher 19249aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 19259aebddd1SJeff Kirsher err: 19269aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 19279aebddd1SJeff Kirsher return status; 19289aebddd1SJeff Kirsher } 19299aebddd1SJeff Kirsher 1930ac34b743SSathya Perla static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) 19319aebddd1SJeff Kirsher { 19329aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19339aebddd1SJeff Kirsher struct be_dma_mem *mem = &adapter->rx_filter; 19349aebddd1SJeff Kirsher struct be_cmd_req_rx_filter *req = mem->va; 19359aebddd1SJeff Kirsher int status; 19369aebddd1SJeff Kirsher 19379aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 19389aebddd1SJeff Kirsher 19399aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 19409aebddd1SJeff Kirsher if (!wrb) { 19419aebddd1SJeff Kirsher status = -EBUSY; 19429aebddd1SJeff Kirsher goto err; 19439aebddd1SJeff Kirsher } 19449aebddd1SJeff Kirsher memset(req, 0, sizeof(*req)); 1945106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1946106df1e3SSomnath Kotur OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req), 1947106df1e3SSomnath Kotur wrb, mem); 19489aebddd1SJeff Kirsher 19499aebddd1SJeff Kirsher req->if_id = cpu_to_le32(adapter->if_handle); 1950ac34b743SSathya Perla req->if_flags_mask = cpu_to_le32(flags); 1951ac34b743SSathya Perla req->if_flags = (value == ON) ? req->if_flags_mask : 0; 1952d9d604f8SAjit Khaparde 1953ac34b743SSathya Perla if (flags & BE_IF_FLAGS_MULTICAST) { 19549aebddd1SJeff Kirsher struct netdev_hw_addr *ha; 19559aebddd1SJeff Kirsher int i = 0; 19569aebddd1SJeff Kirsher 19571610c79fSPadmanabh Ratnakar /* Reset mcast promisc mode if already set by setting mask 19581610c79fSPadmanabh Ratnakar * and not setting flags field 19591610c79fSPadmanabh Ratnakar */ 19601610c79fSPadmanabh Ratnakar req->if_flags_mask |= 1961abb93951SPadmanabh Ratnakar cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS & 196292bf14abSSathya Perla be_if_cap_flags(adapter)); 1963016f97b1SPadmanabh Ratnakar req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev)); 19649aebddd1SJeff Kirsher netdev_for_each_mc_addr(ha, adapter->netdev) 19659aebddd1SJeff Kirsher memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN); 19669aebddd1SJeff Kirsher } 19679aebddd1SJeff Kirsher 1968b6588879SSathya Perla status = be_mcc_notify_wait(adapter); 19699aebddd1SJeff Kirsher err: 19709aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 19719aebddd1SJeff Kirsher return status; 19729aebddd1SJeff Kirsher } 19739aebddd1SJeff Kirsher 1974ac34b743SSathya Perla int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) 1975ac34b743SSathya Perla { 1976ac34b743SSathya Perla struct device *dev = &adapter->pdev->dev; 1977ac34b743SSathya Perla 1978ac34b743SSathya Perla if ((flags & be_if_cap_flags(adapter)) != flags) { 1979ac34b743SSathya Perla dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags); 1980ac34b743SSathya Perla dev_warn(dev, "Interface is capable of 0x%x flags only\n", 1981ac34b743SSathya Perla be_if_cap_flags(adapter)); 1982ac34b743SSathya Perla } 1983ac34b743SSathya Perla flags &= be_if_cap_flags(adapter); 1984196e3735SKalesh AP if (!flags) 1985196e3735SKalesh AP return -ENOTSUPP; 1986ac34b743SSathya Perla 1987ac34b743SSathya Perla return __be_cmd_rx_filter(adapter, flags, value); 1988ac34b743SSathya Perla } 1989ac34b743SSathya Perla 19909aebddd1SJeff Kirsher /* Uses synchrounous mcc */ 19919aebddd1SJeff Kirsher int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) 19929aebddd1SJeff Kirsher { 19939aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 19949aebddd1SJeff Kirsher struct be_cmd_req_set_flow_control *req; 19959aebddd1SJeff Kirsher int status; 19969aebddd1SJeff Kirsher 1997f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL, 1998f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 1999f25b119cSPadmanabh Ratnakar return -EPERM; 2000f25b119cSPadmanabh Ratnakar 20019aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 20029aebddd1SJeff Kirsher 20039aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 20049aebddd1SJeff Kirsher if (!wrb) { 20059aebddd1SJeff Kirsher status = -EBUSY; 20069aebddd1SJeff Kirsher goto err; 20079aebddd1SJeff Kirsher } 20089aebddd1SJeff Kirsher req = embedded_payload(wrb); 20099aebddd1SJeff Kirsher 2010106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2011a2cc4e0bSSathya Perla OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req), 2012a2cc4e0bSSathya Perla wrb, NULL); 20139aebddd1SJeff Kirsher 2014b29812c1SSuresh Reddy req->hdr.version = 1; 20159aebddd1SJeff Kirsher req->tx_flow_control = cpu_to_le16((u16)tx_fc); 20169aebddd1SJeff Kirsher req->rx_flow_control = cpu_to_le16((u16)rx_fc); 20179aebddd1SJeff Kirsher 20189aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 20199aebddd1SJeff Kirsher 20209aebddd1SJeff Kirsher err: 20219aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 2022b29812c1SSuresh Reddy 2023b29812c1SSuresh Reddy if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED) 2024b29812c1SSuresh Reddy return -EOPNOTSUPP; 2025b29812c1SSuresh Reddy 20269aebddd1SJeff Kirsher return status; 20279aebddd1SJeff Kirsher } 20289aebddd1SJeff Kirsher 20299aebddd1SJeff Kirsher /* Uses sycn mcc */ 20309aebddd1SJeff Kirsher int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) 20319aebddd1SJeff Kirsher { 20329aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20339aebddd1SJeff Kirsher struct be_cmd_req_get_flow_control *req; 20349aebddd1SJeff Kirsher int status; 20359aebddd1SJeff Kirsher 2036f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL, 2037f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 2038f25b119cSPadmanabh Ratnakar return -EPERM; 2039f25b119cSPadmanabh Ratnakar 20409aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 20419aebddd1SJeff Kirsher 20429aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 20439aebddd1SJeff Kirsher if (!wrb) { 20449aebddd1SJeff Kirsher status = -EBUSY; 20459aebddd1SJeff Kirsher goto err; 20469aebddd1SJeff Kirsher } 20479aebddd1SJeff Kirsher req = embedded_payload(wrb); 20489aebddd1SJeff Kirsher 2049106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2050a2cc4e0bSSathya Perla OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req), 2051a2cc4e0bSSathya Perla wrb, NULL); 20529aebddd1SJeff Kirsher 20539aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 20549aebddd1SJeff Kirsher if (!status) { 20559aebddd1SJeff Kirsher struct be_cmd_resp_get_flow_control *resp = 20569aebddd1SJeff Kirsher embedded_payload(wrb); 205703d28ffeSKalesh AP 20589aebddd1SJeff Kirsher *tx_fc = le16_to_cpu(resp->tx_flow_control); 20599aebddd1SJeff Kirsher *rx_fc = le16_to_cpu(resp->rx_flow_control); 20609aebddd1SJeff Kirsher } 20619aebddd1SJeff Kirsher 20629aebddd1SJeff Kirsher err: 20639aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 20649aebddd1SJeff Kirsher return status; 20659aebddd1SJeff Kirsher } 20669aebddd1SJeff Kirsher 20679aebddd1SJeff Kirsher /* Uses mbox */ 2068e97e3cdaSKalesh AP int be_cmd_query_fw_cfg(struct be_adapter *adapter) 20699aebddd1SJeff Kirsher { 20709aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 20719aebddd1SJeff Kirsher struct be_cmd_req_query_fw_cfg *req; 20729aebddd1SJeff Kirsher int status; 20739aebddd1SJeff Kirsher 20749aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 20759aebddd1SJeff Kirsher return -1; 20769aebddd1SJeff Kirsher 20779aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 20789aebddd1SJeff Kirsher req = embedded_payload(wrb); 20799aebddd1SJeff Kirsher 2080106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2081a2cc4e0bSSathya Perla OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, 2082a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 20839aebddd1SJeff Kirsher 20849aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 20859aebddd1SJeff Kirsher if (!status) { 20869aebddd1SJeff Kirsher struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); 208703d28ffeSKalesh AP 2088e97e3cdaSKalesh AP adapter->port_num = le32_to_cpu(resp->phys_port); 2089e97e3cdaSKalesh AP adapter->function_mode = le32_to_cpu(resp->function_mode); 2090e97e3cdaSKalesh AP adapter->function_caps = le32_to_cpu(resp->function_caps); 2091e97e3cdaSKalesh AP adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF; 2092acbafeb1SSathya Perla dev_info(&adapter->pdev->dev, 2093acbafeb1SSathya Perla "FW config: function_mode=0x%x, function_caps=0x%x\n", 2094acbafeb1SSathya Perla adapter->function_mode, adapter->function_caps); 20959aebddd1SJeff Kirsher } 20969aebddd1SJeff Kirsher 20979aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 20989aebddd1SJeff Kirsher return status; 20999aebddd1SJeff Kirsher } 21009aebddd1SJeff Kirsher 21019aebddd1SJeff Kirsher /* Uses mbox */ 21029aebddd1SJeff Kirsher int be_cmd_reset_function(struct be_adapter *adapter) 21039aebddd1SJeff Kirsher { 21049aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21059aebddd1SJeff Kirsher struct be_cmd_req_hdr *req; 21069aebddd1SJeff Kirsher int status; 21079aebddd1SJeff Kirsher 2108bf99e50dSPadmanabh Ratnakar if (lancer_chip(adapter)) { 2109bf99e50dSPadmanabh Ratnakar iowrite32(SLI_PORT_CONTROL_IP_MASK, 2110bf99e50dSPadmanabh Ratnakar adapter->db + SLIPORT_CONTROL_OFFSET); 21119fa465c0SSathya Perla status = lancer_wait_ready(adapter); 21129fa465c0SSathya Perla if (status) 2113bf99e50dSPadmanabh Ratnakar dev_err(&adapter->pdev->dev, 2114bf99e50dSPadmanabh Ratnakar "Adapter in non recoverable error\n"); 2115bf99e50dSPadmanabh Ratnakar return status; 2116bf99e50dSPadmanabh Ratnakar } 2117bf99e50dSPadmanabh Ratnakar 21189aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 21199aebddd1SJeff Kirsher return -1; 21209aebddd1SJeff Kirsher 21219aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 21229aebddd1SJeff Kirsher req = embedded_payload(wrb); 21239aebddd1SJeff Kirsher 2124106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON, 2125a2cc4e0bSSathya Perla OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb, 2126a2cc4e0bSSathya Perla NULL); 21279aebddd1SJeff Kirsher 21289aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 21299aebddd1SJeff Kirsher 21309aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 21319aebddd1SJeff Kirsher return status; 21329aebddd1SJeff Kirsher } 21339aebddd1SJeff Kirsher 2134594ad54aSSuresh Reddy int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, 213533cb0fa7SBen Hutchings u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey) 21369aebddd1SJeff Kirsher { 21379aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21389aebddd1SJeff Kirsher struct be_cmd_req_rss_config *req; 21399aebddd1SJeff Kirsher int status; 21409aebddd1SJeff Kirsher 2141da1388d6SVasundhara Volam if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS)) 2142da1388d6SVasundhara Volam return 0; 2143da1388d6SVasundhara Volam 2144b51aa367SKalesh AP spin_lock_bh(&adapter->mcc_lock); 21459aebddd1SJeff Kirsher 2146b51aa367SKalesh AP wrb = wrb_from_mccq(adapter); 2147b51aa367SKalesh AP if (!wrb) { 2148b51aa367SKalesh AP status = -EBUSY; 2149b51aa367SKalesh AP goto err; 2150b51aa367SKalesh AP } 21519aebddd1SJeff Kirsher req = embedded_payload(wrb); 21529aebddd1SJeff Kirsher 2153106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 2154106df1e3SSomnath Kotur OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL); 21559aebddd1SJeff Kirsher 21569aebddd1SJeff Kirsher req->if_id = cpu_to_le32(adapter->if_handle); 2157594ad54aSSuresh Reddy req->enable_rss = cpu_to_le16(rss_hash_opts); 21589aebddd1SJeff Kirsher req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1); 2159594ad54aSSuresh Reddy 2160b51aa367SKalesh AP if (!BEx_chip(adapter)) 2161594ad54aSSuresh Reddy req->hdr.version = 1; 2162594ad54aSSuresh Reddy 21639aebddd1SJeff Kirsher memcpy(req->cpu_table, rsstable, table_size); 2164e2557877SVenkata Duvvuru memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN); 21659aebddd1SJeff Kirsher be_dws_cpu_to_le(req->hash, sizeof(req->hash)); 21669aebddd1SJeff Kirsher 2167b51aa367SKalesh AP status = be_mcc_notify_wait(adapter); 2168b51aa367SKalesh AP err: 2169b51aa367SKalesh AP spin_unlock_bh(&adapter->mcc_lock); 21709aebddd1SJeff Kirsher return status; 21719aebddd1SJeff Kirsher } 21729aebddd1SJeff Kirsher 21739aebddd1SJeff Kirsher /* Uses sync mcc */ 21749aebddd1SJeff Kirsher int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, 21759aebddd1SJeff Kirsher u8 bcn, u8 sts, u8 state) 21769aebddd1SJeff Kirsher { 21779aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 21789aebddd1SJeff Kirsher struct be_cmd_req_enable_disable_beacon *req; 21799aebddd1SJeff Kirsher int status; 21809aebddd1SJeff Kirsher 21819aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 21829aebddd1SJeff Kirsher 21839aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 21849aebddd1SJeff Kirsher if (!wrb) { 21859aebddd1SJeff Kirsher status = -EBUSY; 21869aebddd1SJeff Kirsher goto err; 21879aebddd1SJeff Kirsher } 21889aebddd1SJeff Kirsher req = embedded_payload(wrb); 21899aebddd1SJeff Kirsher 2190106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2191a2cc4e0bSSathya Perla OPCODE_COMMON_ENABLE_DISABLE_BEACON, 2192a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 21939aebddd1SJeff Kirsher 21949aebddd1SJeff Kirsher req->port_num = port_num; 21959aebddd1SJeff Kirsher req->beacon_state = state; 21969aebddd1SJeff Kirsher req->beacon_duration = bcn; 21979aebddd1SJeff Kirsher req->status_duration = sts; 21989aebddd1SJeff Kirsher 21999aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 22009aebddd1SJeff Kirsher 22019aebddd1SJeff Kirsher err: 22029aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 22039aebddd1SJeff Kirsher return status; 22049aebddd1SJeff Kirsher } 22059aebddd1SJeff Kirsher 22069aebddd1SJeff Kirsher /* Uses sync mcc */ 22079aebddd1SJeff Kirsher int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) 22089aebddd1SJeff Kirsher { 22099aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 22109aebddd1SJeff Kirsher struct be_cmd_req_get_beacon_state *req; 22119aebddd1SJeff Kirsher int status; 22129aebddd1SJeff Kirsher 22139aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 22149aebddd1SJeff Kirsher 22159aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 22169aebddd1SJeff Kirsher if (!wrb) { 22179aebddd1SJeff Kirsher status = -EBUSY; 22189aebddd1SJeff Kirsher goto err; 22199aebddd1SJeff Kirsher } 22209aebddd1SJeff Kirsher req = embedded_payload(wrb); 22219aebddd1SJeff Kirsher 2222106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2223a2cc4e0bSSathya Perla OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req), 2224a2cc4e0bSSathya Perla wrb, NULL); 22259aebddd1SJeff Kirsher 22269aebddd1SJeff Kirsher req->port_num = port_num; 22279aebddd1SJeff Kirsher 22289aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 22299aebddd1SJeff Kirsher if (!status) { 22309aebddd1SJeff Kirsher struct be_cmd_resp_get_beacon_state *resp = 22319aebddd1SJeff Kirsher embedded_payload(wrb); 223203d28ffeSKalesh AP 22339aebddd1SJeff Kirsher *state = resp->beacon_state; 22349aebddd1SJeff Kirsher } 22359aebddd1SJeff Kirsher 22369aebddd1SJeff Kirsher err: 22379aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 22389aebddd1SJeff Kirsher return status; 22399aebddd1SJeff Kirsher } 22409aebddd1SJeff Kirsher 2241e36edd9dSMark Leonard /* Uses sync mcc */ 2242e36edd9dSMark Leonard int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, 2243e36edd9dSMark Leonard u8 page_num, u8 *data) 2244e36edd9dSMark Leonard { 2245e36edd9dSMark Leonard struct be_dma_mem cmd; 2246e36edd9dSMark Leonard struct be_mcc_wrb *wrb; 2247e36edd9dSMark Leonard struct be_cmd_req_port_type *req; 2248e36edd9dSMark Leonard int status; 2249e36edd9dSMark Leonard 2250e36edd9dSMark Leonard if (page_num > TR_PAGE_A2) 2251e36edd9dSMark Leonard return -EINVAL; 2252e36edd9dSMark Leonard 2253e36edd9dSMark Leonard cmd.size = sizeof(struct be_cmd_resp_port_type); 2254e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 2255e51000dbSSriharsha Basavapatna GFP_ATOMIC); 2256e36edd9dSMark Leonard if (!cmd.va) { 2257e36edd9dSMark Leonard dev_err(&adapter->pdev->dev, "Memory allocation failed\n"); 2258e36edd9dSMark Leonard return -ENOMEM; 2259e36edd9dSMark Leonard } 2260e36edd9dSMark Leonard 2261e36edd9dSMark Leonard spin_lock_bh(&adapter->mcc_lock); 2262e36edd9dSMark Leonard 2263e36edd9dSMark Leonard wrb = wrb_from_mccq(adapter); 2264e36edd9dSMark Leonard if (!wrb) { 2265e36edd9dSMark Leonard status = -EBUSY; 2266e36edd9dSMark Leonard goto err; 2267e36edd9dSMark Leonard } 2268e36edd9dSMark Leonard req = cmd.va; 2269e36edd9dSMark Leonard 2270e36edd9dSMark Leonard be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2271e36edd9dSMark Leonard OPCODE_COMMON_READ_TRANSRECV_DATA, 2272e36edd9dSMark Leonard cmd.size, wrb, &cmd); 2273e36edd9dSMark Leonard 2274e36edd9dSMark Leonard req->port = cpu_to_le32(adapter->hba_port_num); 2275e36edd9dSMark Leonard req->page_num = cpu_to_le32(page_num); 2276e36edd9dSMark Leonard status = be_mcc_notify_wait(adapter); 2277e36edd9dSMark Leonard if (!status) { 2278e36edd9dSMark Leonard struct be_cmd_resp_port_type *resp = cmd.va; 2279e36edd9dSMark Leonard 2280e36edd9dSMark Leonard memcpy(data, resp->page_data, PAGE_DATA_LEN); 2281e36edd9dSMark Leonard } 2282e36edd9dSMark Leonard err: 2283e36edd9dSMark Leonard spin_unlock_bh(&adapter->mcc_lock); 2284e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); 2285e36edd9dSMark Leonard return status; 2286e36edd9dSMark Leonard } 2287e36edd9dSMark Leonard 2288a23113b5SSuresh Reddy static int lancer_cmd_write_object(struct be_adapter *adapter, 2289a23113b5SSuresh Reddy struct be_dma_mem *cmd, u32 data_size, 2290a23113b5SSuresh Reddy u32 data_offset, const char *obj_name, 2291a23113b5SSuresh Reddy u32 *data_written, u8 *change_status, 2292a23113b5SSuresh Reddy u8 *addn_status) 22939aebddd1SJeff Kirsher { 22949aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 22959aebddd1SJeff Kirsher struct lancer_cmd_req_write_object *req; 22969aebddd1SJeff Kirsher struct lancer_cmd_resp_write_object *resp; 22979aebddd1SJeff Kirsher void *ctxt = NULL; 22989aebddd1SJeff Kirsher int status; 22999aebddd1SJeff Kirsher 23009aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 23019aebddd1SJeff Kirsher adapter->flash_status = 0; 23029aebddd1SJeff Kirsher 23039aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 23049aebddd1SJeff Kirsher if (!wrb) { 23059aebddd1SJeff Kirsher status = -EBUSY; 23069aebddd1SJeff Kirsher goto err_unlock; 23079aebddd1SJeff Kirsher } 23089aebddd1SJeff Kirsher 23099aebddd1SJeff Kirsher req = embedded_payload(wrb); 23109aebddd1SJeff Kirsher 2311106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 23129aebddd1SJeff Kirsher OPCODE_COMMON_WRITE_OBJECT, 2313106df1e3SSomnath Kotur sizeof(struct lancer_cmd_req_write_object), wrb, 2314106df1e3SSomnath Kotur NULL); 23159aebddd1SJeff Kirsher 23169aebddd1SJeff Kirsher ctxt = &req->context; 23179aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 23189aebddd1SJeff Kirsher write_length, ctxt, data_size); 23199aebddd1SJeff Kirsher 23209aebddd1SJeff Kirsher if (data_size == 0) 23219aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 23229aebddd1SJeff Kirsher eof, ctxt, 1); 23239aebddd1SJeff Kirsher else 23249aebddd1SJeff Kirsher AMAP_SET_BITS(struct amap_lancer_write_obj_context, 23259aebddd1SJeff Kirsher eof, ctxt, 0); 23269aebddd1SJeff Kirsher 23279aebddd1SJeff Kirsher be_dws_cpu_to_le(ctxt, sizeof(req->context)); 23289aebddd1SJeff Kirsher req->write_offset = cpu_to_le32(data_offset); 2329242eb470SVasundhara Volam strlcpy(req->object_name, obj_name, sizeof(req->object_name)); 23309aebddd1SJeff Kirsher req->descriptor_count = cpu_to_le32(1); 23319aebddd1SJeff Kirsher req->buf_len = cpu_to_le32(data_size); 23329aebddd1SJeff Kirsher req->addr_low = cpu_to_le32((cmd->dma + 23339aebddd1SJeff Kirsher sizeof(struct lancer_cmd_req_write_object)) 23349aebddd1SJeff Kirsher & 0xFFFFFFFF); 23359aebddd1SJeff Kirsher req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma + 23369aebddd1SJeff Kirsher sizeof(struct lancer_cmd_req_write_object))); 23379aebddd1SJeff Kirsher 2338efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 2339efaa408eSSuresh Reddy if (status) 2340efaa408eSSuresh Reddy goto err_unlock; 2341efaa408eSSuresh Reddy 23429aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 23439aebddd1SJeff Kirsher 23445eeff635SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 2345701962d0SSomnath Kotur msecs_to_jiffies(60000))) 2346fd45160cSKalesh AP status = -ETIMEDOUT; 23479aebddd1SJeff Kirsher else 23489aebddd1SJeff Kirsher status = adapter->flash_status; 23499aebddd1SJeff Kirsher 23509aebddd1SJeff Kirsher resp = embedded_payload(wrb); 2351f67ef7baSPadmanabh Ratnakar if (!status) { 23529aebddd1SJeff Kirsher *data_written = le32_to_cpu(resp->actual_write_len); 2353f67ef7baSPadmanabh Ratnakar *change_status = resp->change_status; 2354f67ef7baSPadmanabh Ratnakar } else { 23559aebddd1SJeff Kirsher *addn_status = resp->additional_status; 2356f67ef7baSPadmanabh Ratnakar } 23579aebddd1SJeff Kirsher 23589aebddd1SJeff Kirsher return status; 23599aebddd1SJeff Kirsher 23609aebddd1SJeff Kirsher err_unlock: 23619aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 23629aebddd1SJeff Kirsher return status; 23639aebddd1SJeff Kirsher } 23649aebddd1SJeff Kirsher 23656809cee0SRavikumar Nelavelli int be_cmd_query_cable_type(struct be_adapter *adapter) 23666809cee0SRavikumar Nelavelli { 23676809cee0SRavikumar Nelavelli u8 page_data[PAGE_DATA_LEN]; 23686809cee0SRavikumar Nelavelli int status; 23696809cee0SRavikumar Nelavelli 23706809cee0SRavikumar Nelavelli status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, 23716809cee0SRavikumar Nelavelli page_data); 23726809cee0SRavikumar Nelavelli if (!status) { 23736809cee0SRavikumar Nelavelli switch (adapter->phy.interface_type) { 23746809cee0SRavikumar Nelavelli case PHY_TYPE_QSFP: 23756809cee0SRavikumar Nelavelli adapter->phy.cable_type = 23766809cee0SRavikumar Nelavelli page_data[QSFP_PLUS_CABLE_TYPE_OFFSET]; 23776809cee0SRavikumar Nelavelli break; 23786809cee0SRavikumar Nelavelli case PHY_TYPE_SFP_PLUS_10GB: 23796809cee0SRavikumar Nelavelli adapter->phy.cable_type = 23806809cee0SRavikumar Nelavelli page_data[SFP_PLUS_CABLE_TYPE_OFFSET]; 23816809cee0SRavikumar Nelavelli break; 23826809cee0SRavikumar Nelavelli default: 23836809cee0SRavikumar Nelavelli adapter->phy.cable_type = 0; 23846809cee0SRavikumar Nelavelli break; 23856809cee0SRavikumar Nelavelli } 23866809cee0SRavikumar Nelavelli } 23876809cee0SRavikumar Nelavelli return status; 23886809cee0SRavikumar Nelavelli } 23896809cee0SRavikumar Nelavelli 239021252377SVasundhara Volam int be_cmd_query_sfp_info(struct be_adapter *adapter) 239121252377SVasundhara Volam { 239221252377SVasundhara Volam u8 page_data[PAGE_DATA_LEN]; 239321252377SVasundhara Volam int status; 239421252377SVasundhara Volam 239521252377SVasundhara Volam status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, 239621252377SVasundhara Volam page_data); 239721252377SVasundhara Volam if (!status) { 239821252377SVasundhara Volam strlcpy(adapter->phy.vendor_name, page_data + 239921252377SVasundhara Volam SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1); 240021252377SVasundhara Volam strlcpy(adapter->phy.vendor_pn, 240121252377SVasundhara Volam page_data + SFP_VENDOR_PN_OFFSET, 240221252377SVasundhara Volam SFP_VENDOR_NAME_LEN - 1); 240321252377SVasundhara Volam } 240421252377SVasundhara Volam 240521252377SVasundhara Volam return status; 240621252377SVasundhara Volam } 240721252377SVasundhara Volam 2408a23113b5SSuresh Reddy static int lancer_cmd_delete_object(struct be_adapter *adapter, 2409a23113b5SSuresh Reddy const char *obj_name) 2410f0613380SKalesh AP { 2411f0613380SKalesh AP struct lancer_cmd_req_delete_object *req; 2412f0613380SKalesh AP struct be_mcc_wrb *wrb; 2413f0613380SKalesh AP int status; 2414f0613380SKalesh AP 2415f0613380SKalesh AP spin_lock_bh(&adapter->mcc_lock); 2416f0613380SKalesh AP 2417f0613380SKalesh AP wrb = wrb_from_mccq(adapter); 2418f0613380SKalesh AP if (!wrb) { 2419f0613380SKalesh AP status = -EBUSY; 2420f0613380SKalesh AP goto err; 2421f0613380SKalesh AP } 2422f0613380SKalesh AP 2423f0613380SKalesh AP req = embedded_payload(wrb); 2424f0613380SKalesh AP 2425f0613380SKalesh AP be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2426f0613380SKalesh AP OPCODE_COMMON_DELETE_OBJECT, 2427f0613380SKalesh AP sizeof(*req), wrb, NULL); 2428f0613380SKalesh AP 2429242eb470SVasundhara Volam strlcpy(req->object_name, obj_name, sizeof(req->object_name)); 2430f0613380SKalesh AP 2431f0613380SKalesh AP status = be_mcc_notify_wait(adapter); 2432f0613380SKalesh AP err: 2433f0613380SKalesh AP spin_unlock_bh(&adapter->mcc_lock); 2434f0613380SKalesh AP return status; 2435f0613380SKalesh AP } 2436f0613380SKalesh AP 2437de49bd5aSPadmanabh Ratnakar int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, 2438de49bd5aSPadmanabh Ratnakar u32 data_size, u32 data_offset, const char *obj_name, 2439de49bd5aSPadmanabh Ratnakar u32 *data_read, u32 *eof, u8 *addn_status) 2440de49bd5aSPadmanabh Ratnakar { 2441de49bd5aSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 2442de49bd5aSPadmanabh Ratnakar struct lancer_cmd_req_read_object *req; 2443de49bd5aSPadmanabh Ratnakar struct lancer_cmd_resp_read_object *resp; 2444de49bd5aSPadmanabh Ratnakar int status; 2445de49bd5aSPadmanabh Ratnakar 2446de49bd5aSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 2447de49bd5aSPadmanabh Ratnakar 2448de49bd5aSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 2449de49bd5aSPadmanabh Ratnakar if (!wrb) { 2450de49bd5aSPadmanabh Ratnakar status = -EBUSY; 2451de49bd5aSPadmanabh Ratnakar goto err_unlock; 2452de49bd5aSPadmanabh Ratnakar } 2453de49bd5aSPadmanabh Ratnakar 2454de49bd5aSPadmanabh Ratnakar req = embedded_payload(wrb); 2455de49bd5aSPadmanabh Ratnakar 2456de49bd5aSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2457de49bd5aSPadmanabh Ratnakar OPCODE_COMMON_READ_OBJECT, 2458de49bd5aSPadmanabh Ratnakar sizeof(struct lancer_cmd_req_read_object), wrb, 2459de49bd5aSPadmanabh Ratnakar NULL); 2460de49bd5aSPadmanabh Ratnakar 2461de49bd5aSPadmanabh Ratnakar req->desired_read_len = cpu_to_le32(data_size); 2462de49bd5aSPadmanabh Ratnakar req->read_offset = cpu_to_le32(data_offset); 2463de49bd5aSPadmanabh Ratnakar strcpy(req->object_name, obj_name); 2464de49bd5aSPadmanabh Ratnakar req->descriptor_count = cpu_to_le32(1); 2465de49bd5aSPadmanabh Ratnakar req->buf_len = cpu_to_le32(data_size); 2466de49bd5aSPadmanabh Ratnakar req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF)); 2467de49bd5aSPadmanabh Ratnakar req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma)); 2468de49bd5aSPadmanabh Ratnakar 2469de49bd5aSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 2470de49bd5aSPadmanabh Ratnakar 2471de49bd5aSPadmanabh Ratnakar resp = embedded_payload(wrb); 2472de49bd5aSPadmanabh Ratnakar if (!status) { 2473de49bd5aSPadmanabh Ratnakar *data_read = le32_to_cpu(resp->actual_read_len); 2474de49bd5aSPadmanabh Ratnakar *eof = le32_to_cpu(resp->eof); 2475de49bd5aSPadmanabh Ratnakar } else { 2476de49bd5aSPadmanabh Ratnakar *addn_status = resp->additional_status; 2477de49bd5aSPadmanabh Ratnakar } 2478de49bd5aSPadmanabh Ratnakar 2479de49bd5aSPadmanabh Ratnakar err_unlock: 2480de49bd5aSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 2481de49bd5aSPadmanabh Ratnakar return status; 2482de49bd5aSPadmanabh Ratnakar } 2483de49bd5aSPadmanabh Ratnakar 2484a23113b5SSuresh Reddy static int be_cmd_write_flashrom(struct be_adapter *adapter, 2485a23113b5SSuresh Reddy struct be_dma_mem *cmd, u32 flash_type, 2486a23113b5SSuresh Reddy u32 flash_opcode, u32 img_offset, u32 buf_size) 24879aebddd1SJeff Kirsher { 24889aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 24899aebddd1SJeff Kirsher struct be_cmd_write_flashrom *req; 24909aebddd1SJeff Kirsher int status; 24919aebddd1SJeff Kirsher 24929aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 24939aebddd1SJeff Kirsher adapter->flash_status = 0; 24949aebddd1SJeff Kirsher 24959aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 24969aebddd1SJeff Kirsher if (!wrb) { 24979aebddd1SJeff Kirsher status = -EBUSY; 24989aebddd1SJeff Kirsher goto err_unlock; 24999aebddd1SJeff Kirsher } 25009aebddd1SJeff Kirsher req = cmd->va; 25019aebddd1SJeff Kirsher 2502106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2503a2cc4e0bSSathya Perla OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb, 2504a2cc4e0bSSathya Perla cmd); 25059aebddd1SJeff Kirsher 25069aebddd1SJeff Kirsher req->params.op_type = cpu_to_le32(flash_type); 250770a7b525SVasundhara Volam if (flash_type == OPTYPE_OFFSET_SPECIFIED) 250870a7b525SVasundhara Volam req->params.offset = cpu_to_le32(img_offset); 250970a7b525SVasundhara Volam 25109aebddd1SJeff Kirsher req->params.op_code = cpu_to_le32(flash_opcode); 25119aebddd1SJeff Kirsher req->params.data_buf_size = cpu_to_le32(buf_size); 25129aebddd1SJeff Kirsher 2513efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 2514efaa408eSSuresh Reddy if (status) 2515efaa408eSSuresh Reddy goto err_unlock; 2516efaa408eSSuresh Reddy 25179aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25189aebddd1SJeff Kirsher 25195eeff635SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 2520e2edb7d5SSathya Perla msecs_to_jiffies(40000))) 2521fd45160cSKalesh AP status = -ETIMEDOUT; 25229aebddd1SJeff Kirsher else 25239aebddd1SJeff Kirsher status = adapter->flash_status; 25249aebddd1SJeff Kirsher 25259aebddd1SJeff Kirsher return status; 25269aebddd1SJeff Kirsher 25279aebddd1SJeff Kirsher err_unlock: 25289aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25299aebddd1SJeff Kirsher return status; 25309aebddd1SJeff Kirsher } 25319aebddd1SJeff Kirsher 2532a23113b5SSuresh Reddy static int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, 253370a7b525SVasundhara Volam u16 img_optype, u32 img_offset, u32 crc_offset) 25349aebddd1SJeff Kirsher { 2535be716446SPadmanabh Ratnakar struct be_cmd_read_flash_crc *req; 253670a7b525SVasundhara Volam struct be_mcc_wrb *wrb; 25379aebddd1SJeff Kirsher int status; 25389aebddd1SJeff Kirsher 25399aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 25409aebddd1SJeff Kirsher 25419aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 25429aebddd1SJeff Kirsher if (!wrb) { 25439aebddd1SJeff Kirsher status = -EBUSY; 25449aebddd1SJeff Kirsher goto err; 25459aebddd1SJeff Kirsher } 25469aebddd1SJeff Kirsher req = embedded_payload(wrb); 25479aebddd1SJeff Kirsher 2548106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 2549be716446SPadmanabh Ratnakar OPCODE_COMMON_READ_FLASHROM, sizeof(*req), 2550be716446SPadmanabh Ratnakar wrb, NULL); 25519aebddd1SJeff Kirsher 255270a7b525SVasundhara Volam req->params.op_type = cpu_to_le32(img_optype); 255370a7b525SVasundhara Volam if (img_optype == OPTYPE_OFFSET_SPECIFIED) 255470a7b525SVasundhara Volam req->params.offset = cpu_to_le32(img_offset + crc_offset); 255570a7b525SVasundhara Volam else 255670a7b525SVasundhara Volam req->params.offset = cpu_to_le32(crc_offset); 255770a7b525SVasundhara Volam 25589aebddd1SJeff Kirsher req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); 25599aebddd1SJeff Kirsher req->params.data_buf_size = cpu_to_le32(0x4); 25609aebddd1SJeff Kirsher 25619aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 25629aebddd1SJeff Kirsher if (!status) 2563be716446SPadmanabh Ratnakar memcpy(flashed_crc, req->crc, 4); 25649aebddd1SJeff Kirsher 25659aebddd1SJeff Kirsher err: 25669aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 25679aebddd1SJeff Kirsher return status; 25689aebddd1SJeff Kirsher } 25699aebddd1SJeff Kirsher 2570a23113b5SSuresh Reddy static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; 2571a23113b5SSuresh Reddy 2572a23113b5SSuresh Reddy static bool phy_flashing_required(struct be_adapter *adapter) 2573a23113b5SSuresh Reddy { 2574a23113b5SSuresh Reddy return (adapter->phy.phy_type == PHY_TYPE_TN_8022 && 2575a23113b5SSuresh Reddy adapter->phy.interface_type == PHY_TYPE_BASET_10GB); 2576a23113b5SSuresh Reddy } 2577a23113b5SSuresh Reddy 2578a23113b5SSuresh Reddy static bool is_comp_in_ufi(struct be_adapter *adapter, 2579a23113b5SSuresh Reddy struct flash_section_info *fsec, int type) 2580a23113b5SSuresh Reddy { 2581a23113b5SSuresh Reddy int i = 0, img_type = 0; 2582a23113b5SSuresh Reddy struct flash_section_info_g2 *fsec_g2 = NULL; 2583a23113b5SSuresh Reddy 2584a23113b5SSuresh Reddy if (BE2_chip(adapter)) 2585a23113b5SSuresh Reddy fsec_g2 = (struct flash_section_info_g2 *)fsec; 2586a23113b5SSuresh Reddy 2587a23113b5SSuresh Reddy for (i = 0; i < MAX_FLASH_COMP; i++) { 2588a23113b5SSuresh Reddy if (fsec_g2) 2589a23113b5SSuresh Reddy img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type); 2590a23113b5SSuresh Reddy else 2591a23113b5SSuresh Reddy img_type = le32_to_cpu(fsec->fsec_entry[i].type); 2592a23113b5SSuresh Reddy 2593a23113b5SSuresh Reddy if (img_type == type) 2594a23113b5SSuresh Reddy return true; 2595a23113b5SSuresh Reddy } 2596a23113b5SSuresh Reddy return false; 2597a23113b5SSuresh Reddy } 2598a23113b5SSuresh Reddy 2599a23113b5SSuresh Reddy static struct flash_section_info *get_fsec_info(struct be_adapter *adapter, 2600a23113b5SSuresh Reddy int header_size, 2601a23113b5SSuresh Reddy const struct firmware *fw) 2602a23113b5SSuresh Reddy { 2603a23113b5SSuresh Reddy struct flash_section_info *fsec = NULL; 2604a23113b5SSuresh Reddy const u8 *p = fw->data; 2605a23113b5SSuresh Reddy 2606a23113b5SSuresh Reddy p += header_size; 2607a23113b5SSuresh Reddy while (p < (fw->data + fw->size)) { 2608a23113b5SSuresh Reddy fsec = (struct flash_section_info *)p; 2609a23113b5SSuresh Reddy if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) 2610a23113b5SSuresh Reddy return fsec; 2611a23113b5SSuresh Reddy p += 32; 2612a23113b5SSuresh Reddy } 2613a23113b5SSuresh Reddy return NULL; 2614a23113b5SSuresh Reddy } 2615a23113b5SSuresh Reddy 2616a23113b5SSuresh Reddy static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p, 2617a23113b5SSuresh Reddy u32 img_offset, u32 img_size, int hdr_size, 2618a23113b5SSuresh Reddy u16 img_optype, bool *crc_match) 2619a23113b5SSuresh Reddy { 2620a23113b5SSuresh Reddy u32 crc_offset; 2621a23113b5SSuresh Reddy int status; 2622a23113b5SSuresh Reddy u8 crc[4]; 2623a23113b5SSuresh Reddy 2624a23113b5SSuresh Reddy status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset, 2625a23113b5SSuresh Reddy img_size - 4); 2626a23113b5SSuresh Reddy if (status) 2627a23113b5SSuresh Reddy return status; 2628a23113b5SSuresh Reddy 2629a23113b5SSuresh Reddy crc_offset = hdr_size + img_offset + img_size - 4; 2630a23113b5SSuresh Reddy 2631a23113b5SSuresh Reddy /* Skip flashing, if crc of flashed region matches */ 2632a23113b5SSuresh Reddy if (!memcmp(crc, p + crc_offset, 4)) 2633a23113b5SSuresh Reddy *crc_match = true; 2634a23113b5SSuresh Reddy else 2635a23113b5SSuresh Reddy *crc_match = false; 2636a23113b5SSuresh Reddy 2637a23113b5SSuresh Reddy return status; 2638a23113b5SSuresh Reddy } 2639a23113b5SSuresh Reddy 2640a23113b5SSuresh Reddy static int be_flash(struct be_adapter *adapter, const u8 *img, 2641a23113b5SSuresh Reddy struct be_dma_mem *flash_cmd, int optype, int img_size, 2642a23113b5SSuresh Reddy u32 img_offset) 2643a23113b5SSuresh Reddy { 2644a23113b5SSuresh Reddy u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0; 2645a23113b5SSuresh Reddy struct be_cmd_write_flashrom *req = flash_cmd->va; 2646a23113b5SSuresh Reddy int status; 2647a23113b5SSuresh Reddy 2648a23113b5SSuresh Reddy while (total_bytes) { 2649a23113b5SSuresh Reddy num_bytes = min_t(u32, 32 * 1024, total_bytes); 2650a23113b5SSuresh Reddy 2651a23113b5SSuresh Reddy total_bytes -= num_bytes; 2652a23113b5SSuresh Reddy 2653a23113b5SSuresh Reddy if (!total_bytes) { 2654a23113b5SSuresh Reddy if (optype == OPTYPE_PHY_FW) 2655a23113b5SSuresh Reddy flash_op = FLASHROM_OPER_PHY_FLASH; 2656a23113b5SSuresh Reddy else 2657a23113b5SSuresh Reddy flash_op = FLASHROM_OPER_FLASH; 2658a23113b5SSuresh Reddy } else { 2659a23113b5SSuresh Reddy if (optype == OPTYPE_PHY_FW) 2660a23113b5SSuresh Reddy flash_op = FLASHROM_OPER_PHY_SAVE; 2661a23113b5SSuresh Reddy else 2662a23113b5SSuresh Reddy flash_op = FLASHROM_OPER_SAVE; 2663a23113b5SSuresh Reddy } 2664a23113b5SSuresh Reddy 2665a23113b5SSuresh Reddy memcpy(req->data_buf, img, num_bytes); 2666a23113b5SSuresh Reddy img += num_bytes; 2667a23113b5SSuresh Reddy status = be_cmd_write_flashrom(adapter, flash_cmd, optype, 2668a23113b5SSuresh Reddy flash_op, img_offset + 2669a23113b5SSuresh Reddy bytes_sent, num_bytes); 2670a23113b5SSuresh Reddy if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST && 2671a23113b5SSuresh Reddy optype == OPTYPE_PHY_FW) 2672a23113b5SSuresh Reddy break; 2673a23113b5SSuresh Reddy else if (status) 2674a23113b5SSuresh Reddy return status; 2675a23113b5SSuresh Reddy 2676a23113b5SSuresh Reddy bytes_sent += num_bytes; 2677a23113b5SSuresh Reddy } 2678a23113b5SSuresh Reddy return 0; 2679a23113b5SSuresh Reddy } 2680a23113b5SSuresh Reddy 2681a23113b5SSuresh Reddy /* For BE2, BE3 and BE3-R */ 2682a23113b5SSuresh Reddy static int be_flash_BEx(struct be_adapter *adapter, 2683a23113b5SSuresh Reddy const struct firmware *fw, 2684a23113b5SSuresh Reddy struct be_dma_mem *flash_cmd, int num_of_images) 2685a23113b5SSuresh Reddy { 2686a23113b5SSuresh Reddy int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); 2687a23113b5SSuresh Reddy struct device *dev = &adapter->pdev->dev; 2688a23113b5SSuresh Reddy struct flash_section_info *fsec = NULL; 2689a23113b5SSuresh Reddy int status, i, filehdr_size, num_comp; 2690a23113b5SSuresh Reddy const struct flash_comp *pflashcomp; 2691a23113b5SSuresh Reddy bool crc_match; 2692a23113b5SSuresh Reddy const u8 *p; 2693a23113b5SSuresh Reddy 2694a23113b5SSuresh Reddy struct flash_comp gen3_flash_types[] = { 2695a23113b5SSuresh Reddy { BE3_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE, 2696a23113b5SSuresh Reddy BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI}, 2697a23113b5SSuresh Reddy { BE3_REDBOOT_START, OPTYPE_REDBOOT, 2698a23113b5SSuresh Reddy BE3_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE}, 2699a23113b5SSuresh Reddy { BE3_ISCSI_BIOS_START, OPTYPE_BIOS, 2700a23113b5SSuresh Reddy BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI}, 2701a23113b5SSuresh Reddy { BE3_PXE_BIOS_START, OPTYPE_PXE_BIOS, 2702a23113b5SSuresh Reddy BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE}, 2703a23113b5SSuresh Reddy { BE3_FCOE_BIOS_START, OPTYPE_FCOE_BIOS, 2704a23113b5SSuresh Reddy BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE}, 2705a23113b5SSuresh Reddy { BE3_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP, 2706a23113b5SSuresh Reddy BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI}, 2707a23113b5SSuresh Reddy { BE3_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE, 2708a23113b5SSuresh Reddy BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE}, 2709a23113b5SSuresh Reddy { BE3_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP, 2710a23113b5SSuresh Reddy BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE}, 2711a23113b5SSuresh Reddy { BE3_NCSI_START, OPTYPE_NCSI_FW, 2712a23113b5SSuresh Reddy BE3_NCSI_COMP_MAX_SIZE, IMAGE_NCSI}, 2713a23113b5SSuresh Reddy { BE3_PHY_FW_START, OPTYPE_PHY_FW, 2714a23113b5SSuresh Reddy BE3_PHY_FW_COMP_MAX_SIZE, IMAGE_FIRMWARE_PHY} 2715a23113b5SSuresh Reddy }; 2716a23113b5SSuresh Reddy 2717a23113b5SSuresh Reddy struct flash_comp gen2_flash_types[] = { 2718a23113b5SSuresh Reddy { BE2_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE, 2719a23113b5SSuresh Reddy BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI}, 2720a23113b5SSuresh Reddy { BE2_REDBOOT_START, OPTYPE_REDBOOT, 2721a23113b5SSuresh Reddy BE2_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE}, 2722a23113b5SSuresh Reddy { BE2_ISCSI_BIOS_START, OPTYPE_BIOS, 2723a23113b5SSuresh Reddy BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI}, 2724a23113b5SSuresh Reddy { BE2_PXE_BIOS_START, OPTYPE_PXE_BIOS, 2725a23113b5SSuresh Reddy BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE}, 2726a23113b5SSuresh Reddy { BE2_FCOE_BIOS_START, OPTYPE_FCOE_BIOS, 2727a23113b5SSuresh Reddy BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE}, 2728a23113b5SSuresh Reddy { BE2_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP, 2729a23113b5SSuresh Reddy BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI}, 2730a23113b5SSuresh Reddy { BE2_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE, 2731a23113b5SSuresh Reddy BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE}, 2732a23113b5SSuresh Reddy { BE2_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP, 2733a23113b5SSuresh Reddy BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE} 2734a23113b5SSuresh Reddy }; 2735a23113b5SSuresh Reddy 2736a23113b5SSuresh Reddy if (BE3_chip(adapter)) { 2737a23113b5SSuresh Reddy pflashcomp = gen3_flash_types; 2738a23113b5SSuresh Reddy filehdr_size = sizeof(struct flash_file_hdr_g3); 2739a23113b5SSuresh Reddy num_comp = ARRAY_SIZE(gen3_flash_types); 2740a23113b5SSuresh Reddy } else { 2741a23113b5SSuresh Reddy pflashcomp = gen2_flash_types; 2742a23113b5SSuresh Reddy filehdr_size = sizeof(struct flash_file_hdr_g2); 2743a23113b5SSuresh Reddy num_comp = ARRAY_SIZE(gen2_flash_types); 2744a23113b5SSuresh Reddy img_hdrs_size = 0; 2745a23113b5SSuresh Reddy } 2746a23113b5SSuresh Reddy 2747a23113b5SSuresh Reddy /* Get flash section info*/ 2748a23113b5SSuresh Reddy fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); 2749a23113b5SSuresh Reddy if (!fsec) { 2750a23113b5SSuresh Reddy dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); 2751a23113b5SSuresh Reddy return -1; 2752a23113b5SSuresh Reddy } 2753a23113b5SSuresh Reddy for (i = 0; i < num_comp; i++) { 2754a23113b5SSuresh Reddy if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type)) 2755a23113b5SSuresh Reddy continue; 2756a23113b5SSuresh Reddy 2757a23113b5SSuresh Reddy if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) && 2758a23113b5SSuresh Reddy memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) 2759a23113b5SSuresh Reddy continue; 2760a23113b5SSuresh Reddy 2761a23113b5SSuresh Reddy if (pflashcomp[i].optype == OPTYPE_PHY_FW && 2762a23113b5SSuresh Reddy !phy_flashing_required(adapter)) 2763a23113b5SSuresh Reddy continue; 2764a23113b5SSuresh Reddy 2765a23113b5SSuresh Reddy if (pflashcomp[i].optype == OPTYPE_REDBOOT) { 2766a23113b5SSuresh Reddy status = be_check_flash_crc(adapter, fw->data, 2767a23113b5SSuresh Reddy pflashcomp[i].offset, 2768a23113b5SSuresh Reddy pflashcomp[i].size, 2769a23113b5SSuresh Reddy filehdr_size + 2770a23113b5SSuresh Reddy img_hdrs_size, 2771a23113b5SSuresh Reddy OPTYPE_REDBOOT, &crc_match); 2772a23113b5SSuresh Reddy if (status) { 2773a23113b5SSuresh Reddy dev_err(dev, 2774a23113b5SSuresh Reddy "Could not get CRC for 0x%x region\n", 2775a23113b5SSuresh Reddy pflashcomp[i].optype); 2776a23113b5SSuresh Reddy continue; 2777a23113b5SSuresh Reddy } 2778a23113b5SSuresh Reddy 2779a23113b5SSuresh Reddy if (crc_match) 2780a23113b5SSuresh Reddy continue; 2781a23113b5SSuresh Reddy } 2782a23113b5SSuresh Reddy 2783a23113b5SSuresh Reddy p = fw->data + filehdr_size + pflashcomp[i].offset + 2784a23113b5SSuresh Reddy img_hdrs_size; 2785a23113b5SSuresh Reddy if (p + pflashcomp[i].size > fw->data + fw->size) 2786a23113b5SSuresh Reddy return -1; 2787a23113b5SSuresh Reddy 2788a23113b5SSuresh Reddy status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, 2789a23113b5SSuresh Reddy pflashcomp[i].size, 0); 2790a23113b5SSuresh Reddy if (status) { 2791a23113b5SSuresh Reddy dev_err(dev, "Flashing section type 0x%x failed\n", 2792a23113b5SSuresh Reddy pflashcomp[i].img_type); 2793a23113b5SSuresh Reddy return status; 2794a23113b5SSuresh Reddy } 2795a23113b5SSuresh Reddy } 2796a23113b5SSuresh Reddy return 0; 2797a23113b5SSuresh Reddy } 2798a23113b5SSuresh Reddy 2799a23113b5SSuresh Reddy static u16 be_get_img_optype(struct flash_section_entry fsec_entry) 2800a23113b5SSuresh Reddy { 2801a23113b5SSuresh Reddy u32 img_type = le32_to_cpu(fsec_entry.type); 2802a23113b5SSuresh Reddy u16 img_optype = le16_to_cpu(fsec_entry.optype); 2803a23113b5SSuresh Reddy 2804a23113b5SSuresh Reddy if (img_optype != 0xFFFF) 2805a23113b5SSuresh Reddy return img_optype; 2806a23113b5SSuresh Reddy 2807a23113b5SSuresh Reddy switch (img_type) { 2808a23113b5SSuresh Reddy case IMAGE_FIRMWARE_ISCSI: 2809a23113b5SSuresh Reddy img_optype = OPTYPE_ISCSI_ACTIVE; 2810a23113b5SSuresh Reddy break; 2811a23113b5SSuresh Reddy case IMAGE_BOOT_CODE: 2812a23113b5SSuresh Reddy img_optype = OPTYPE_REDBOOT; 2813a23113b5SSuresh Reddy break; 2814a23113b5SSuresh Reddy case IMAGE_OPTION_ROM_ISCSI: 2815a23113b5SSuresh Reddy img_optype = OPTYPE_BIOS; 2816a23113b5SSuresh Reddy break; 2817a23113b5SSuresh Reddy case IMAGE_OPTION_ROM_PXE: 2818a23113b5SSuresh Reddy img_optype = OPTYPE_PXE_BIOS; 2819a23113b5SSuresh Reddy break; 2820a23113b5SSuresh Reddy case IMAGE_OPTION_ROM_FCOE: 2821a23113b5SSuresh Reddy img_optype = OPTYPE_FCOE_BIOS; 2822a23113b5SSuresh Reddy break; 2823a23113b5SSuresh Reddy case IMAGE_FIRMWARE_BACKUP_ISCSI: 2824a23113b5SSuresh Reddy img_optype = OPTYPE_ISCSI_BACKUP; 2825a23113b5SSuresh Reddy break; 2826a23113b5SSuresh Reddy case IMAGE_NCSI: 2827a23113b5SSuresh Reddy img_optype = OPTYPE_NCSI_FW; 2828a23113b5SSuresh Reddy break; 2829a23113b5SSuresh Reddy case IMAGE_FLASHISM_JUMPVECTOR: 2830a23113b5SSuresh Reddy img_optype = OPTYPE_FLASHISM_JUMPVECTOR; 2831a23113b5SSuresh Reddy break; 2832a23113b5SSuresh Reddy case IMAGE_FIRMWARE_PHY: 2833a23113b5SSuresh Reddy img_optype = OPTYPE_SH_PHY_FW; 2834a23113b5SSuresh Reddy break; 2835a23113b5SSuresh Reddy case IMAGE_REDBOOT_DIR: 2836a23113b5SSuresh Reddy img_optype = OPTYPE_REDBOOT_DIR; 2837a23113b5SSuresh Reddy break; 2838a23113b5SSuresh Reddy case IMAGE_REDBOOT_CONFIG: 2839a23113b5SSuresh Reddy img_optype = OPTYPE_REDBOOT_CONFIG; 2840a23113b5SSuresh Reddy break; 2841a23113b5SSuresh Reddy case IMAGE_UFI_DIR: 2842a23113b5SSuresh Reddy img_optype = OPTYPE_UFI_DIR; 2843a23113b5SSuresh Reddy break; 2844a23113b5SSuresh Reddy default: 2845a23113b5SSuresh Reddy break; 2846a23113b5SSuresh Reddy } 2847a23113b5SSuresh Reddy 2848a23113b5SSuresh Reddy return img_optype; 2849a23113b5SSuresh Reddy } 2850a23113b5SSuresh Reddy 2851a23113b5SSuresh Reddy static int be_flash_skyhawk(struct be_adapter *adapter, 2852a23113b5SSuresh Reddy const struct firmware *fw, 2853a23113b5SSuresh Reddy struct be_dma_mem *flash_cmd, int num_of_images) 2854a23113b5SSuresh Reddy { 2855a23113b5SSuresh Reddy int img_hdrs_size = num_of_images * sizeof(struct image_hdr); 2856a23113b5SSuresh Reddy bool crc_match, old_fw_img, flash_offset_support = true; 2857a23113b5SSuresh Reddy struct device *dev = &adapter->pdev->dev; 2858a23113b5SSuresh Reddy struct flash_section_info *fsec = NULL; 2859a23113b5SSuresh Reddy u32 img_offset, img_size, img_type; 2860a23113b5SSuresh Reddy u16 img_optype, flash_optype; 2861a23113b5SSuresh Reddy int status, i, filehdr_size; 2862a23113b5SSuresh Reddy const u8 *p; 2863a23113b5SSuresh Reddy 2864a23113b5SSuresh Reddy filehdr_size = sizeof(struct flash_file_hdr_g3); 2865a23113b5SSuresh Reddy fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); 2866a23113b5SSuresh Reddy if (!fsec) { 2867a23113b5SSuresh Reddy dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); 2868a23113b5SSuresh Reddy return -EINVAL; 2869a23113b5SSuresh Reddy } 2870a23113b5SSuresh Reddy 2871a23113b5SSuresh Reddy retry_flash: 2872a23113b5SSuresh Reddy for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { 2873a23113b5SSuresh Reddy img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); 2874a23113b5SSuresh Reddy img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); 2875a23113b5SSuresh Reddy img_type = le32_to_cpu(fsec->fsec_entry[i].type); 2876a23113b5SSuresh Reddy img_optype = be_get_img_optype(fsec->fsec_entry[i]); 2877a23113b5SSuresh Reddy old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF; 2878a23113b5SSuresh Reddy 2879a23113b5SSuresh Reddy if (img_optype == 0xFFFF) 2880a23113b5SSuresh Reddy continue; 2881a23113b5SSuresh Reddy 2882a23113b5SSuresh Reddy if (flash_offset_support) 2883a23113b5SSuresh Reddy flash_optype = OPTYPE_OFFSET_SPECIFIED; 2884a23113b5SSuresh Reddy else 2885a23113b5SSuresh Reddy flash_optype = img_optype; 2886a23113b5SSuresh Reddy 2887a23113b5SSuresh Reddy /* Don't bother verifying CRC if an old FW image is being 2888a23113b5SSuresh Reddy * flashed 2889a23113b5SSuresh Reddy */ 2890a23113b5SSuresh Reddy if (old_fw_img) 2891a23113b5SSuresh Reddy goto flash; 2892a23113b5SSuresh Reddy 2893a23113b5SSuresh Reddy status = be_check_flash_crc(adapter, fw->data, img_offset, 2894a23113b5SSuresh Reddy img_size, filehdr_size + 2895a23113b5SSuresh Reddy img_hdrs_size, flash_optype, 2896a23113b5SSuresh Reddy &crc_match); 2897a23113b5SSuresh Reddy if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST || 2898a23113b5SSuresh Reddy base_status(status) == MCC_STATUS_ILLEGAL_FIELD) { 2899a23113b5SSuresh Reddy /* The current FW image on the card does not support 2900a23113b5SSuresh Reddy * OFFSET based flashing. Retry using older mechanism 2901a23113b5SSuresh Reddy * of OPTYPE based flashing 2902a23113b5SSuresh Reddy */ 2903a23113b5SSuresh Reddy if (flash_optype == OPTYPE_OFFSET_SPECIFIED) { 2904a23113b5SSuresh Reddy flash_offset_support = false; 2905a23113b5SSuresh Reddy goto retry_flash; 2906a23113b5SSuresh Reddy } 2907a23113b5SSuresh Reddy 2908a23113b5SSuresh Reddy /* The current FW image on the card does not recognize 2909a23113b5SSuresh Reddy * the new FLASH op_type. The FW download is partially 2910a23113b5SSuresh Reddy * complete. Reboot the server now to enable FW image 2911a23113b5SSuresh Reddy * to recognize the new FLASH op_type. To complete the 2912a23113b5SSuresh Reddy * remaining process, download the same FW again after 2913a23113b5SSuresh Reddy * the reboot. 2914a23113b5SSuresh Reddy */ 2915a23113b5SSuresh Reddy dev_err(dev, "Flash incomplete. Reset the server\n"); 2916a23113b5SSuresh Reddy dev_err(dev, "Download FW image again after reset\n"); 2917a23113b5SSuresh Reddy return -EAGAIN; 2918a23113b5SSuresh Reddy } else if (status) { 2919a23113b5SSuresh Reddy dev_err(dev, "Could not get CRC for 0x%x region\n", 2920a23113b5SSuresh Reddy img_optype); 2921a23113b5SSuresh Reddy return -EFAULT; 2922a23113b5SSuresh Reddy } 2923a23113b5SSuresh Reddy 2924a23113b5SSuresh Reddy if (crc_match) 2925a23113b5SSuresh Reddy continue; 2926a23113b5SSuresh Reddy 2927a23113b5SSuresh Reddy flash: 2928a23113b5SSuresh Reddy p = fw->data + filehdr_size + img_offset + img_hdrs_size; 2929a23113b5SSuresh Reddy if (p + img_size > fw->data + fw->size) 2930a23113b5SSuresh Reddy return -1; 2931a23113b5SSuresh Reddy 2932a23113b5SSuresh Reddy status = be_flash(adapter, p, flash_cmd, flash_optype, img_size, 2933a23113b5SSuresh Reddy img_offset); 2934a23113b5SSuresh Reddy 2935a23113b5SSuresh Reddy /* The current FW image on the card does not support OFFSET 2936a23113b5SSuresh Reddy * based flashing. Retry using older mechanism of OPTYPE based 2937a23113b5SSuresh Reddy * flashing 2938a23113b5SSuresh Reddy */ 2939a23113b5SSuresh Reddy if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD && 2940a23113b5SSuresh Reddy flash_optype == OPTYPE_OFFSET_SPECIFIED) { 2941a23113b5SSuresh Reddy flash_offset_support = false; 2942a23113b5SSuresh Reddy goto retry_flash; 2943a23113b5SSuresh Reddy } 2944a23113b5SSuresh Reddy 2945a23113b5SSuresh Reddy /* For old FW images ignore ILLEGAL_FIELD error or errors on 2946a23113b5SSuresh Reddy * UFI_DIR region 2947a23113b5SSuresh Reddy */ 2948a23113b5SSuresh Reddy if (old_fw_img && 2949a23113b5SSuresh Reddy (base_status(status) == MCC_STATUS_ILLEGAL_FIELD || 2950a23113b5SSuresh Reddy (img_optype == OPTYPE_UFI_DIR && 2951a23113b5SSuresh Reddy base_status(status) == MCC_STATUS_FAILED))) { 2952a23113b5SSuresh Reddy continue; 2953a23113b5SSuresh Reddy } else if (status) { 2954a23113b5SSuresh Reddy dev_err(dev, "Flashing section type 0x%x failed\n", 2955a23113b5SSuresh Reddy img_type); 29566b525782SSuresh Reddy 29576b525782SSuresh Reddy switch (addl_status(status)) { 29586b525782SSuresh Reddy case MCC_ADDL_STATUS_MISSING_SIGNATURE: 29596b525782SSuresh Reddy dev_err(dev, 29606b525782SSuresh Reddy "Digital signature missing in FW\n"); 29616b525782SSuresh Reddy return -EINVAL; 29626b525782SSuresh Reddy case MCC_ADDL_STATUS_INVALID_SIGNATURE: 29636b525782SSuresh Reddy dev_err(dev, 29646b525782SSuresh Reddy "Invalid digital signature in FW\n"); 29656b525782SSuresh Reddy return -EINVAL; 29666b525782SSuresh Reddy default: 2967a23113b5SSuresh Reddy return -EFAULT; 2968a23113b5SSuresh Reddy } 2969a23113b5SSuresh Reddy } 29706b525782SSuresh Reddy } 2971a23113b5SSuresh Reddy return 0; 2972a23113b5SSuresh Reddy } 2973a23113b5SSuresh Reddy 2974a23113b5SSuresh Reddy int lancer_fw_download(struct be_adapter *adapter, 2975a23113b5SSuresh Reddy const struct firmware *fw) 2976a23113b5SSuresh Reddy { 2977a23113b5SSuresh Reddy struct device *dev = &adapter->pdev->dev; 2978a23113b5SSuresh Reddy struct be_dma_mem flash_cmd; 2979a23113b5SSuresh Reddy const u8 *data_ptr = NULL; 2980a23113b5SSuresh Reddy u8 *dest_image_ptr = NULL; 2981a23113b5SSuresh Reddy size_t image_size = 0; 2982a23113b5SSuresh Reddy u32 chunk_size = 0; 2983a23113b5SSuresh Reddy u32 data_written = 0; 2984a23113b5SSuresh Reddy u32 offset = 0; 2985a23113b5SSuresh Reddy int status = 0; 2986a23113b5SSuresh Reddy u8 add_status = 0; 2987a23113b5SSuresh Reddy u8 change_status; 2988a23113b5SSuresh Reddy 2989a23113b5SSuresh Reddy if (!IS_ALIGNED(fw->size, sizeof(u32))) { 2990a23113b5SSuresh Reddy dev_err(dev, "FW image size should be multiple of 4\n"); 2991a23113b5SSuresh Reddy return -EINVAL; 2992a23113b5SSuresh Reddy } 2993a23113b5SSuresh Reddy 2994a23113b5SSuresh Reddy flash_cmd.size = sizeof(struct lancer_cmd_req_write_object) 2995a23113b5SSuresh Reddy + LANCER_FW_DOWNLOAD_CHUNK; 2996a23113b5SSuresh Reddy flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, 2997a23113b5SSuresh Reddy &flash_cmd.dma, GFP_KERNEL); 2998a23113b5SSuresh Reddy if (!flash_cmd.va) 2999a23113b5SSuresh Reddy return -ENOMEM; 3000a23113b5SSuresh Reddy 3001a23113b5SSuresh Reddy dest_image_ptr = flash_cmd.va + 3002a23113b5SSuresh Reddy sizeof(struct lancer_cmd_req_write_object); 3003a23113b5SSuresh Reddy image_size = fw->size; 3004a23113b5SSuresh Reddy data_ptr = fw->data; 3005a23113b5SSuresh Reddy 3006a23113b5SSuresh Reddy while (image_size) { 3007a23113b5SSuresh Reddy chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK); 3008a23113b5SSuresh Reddy 3009a23113b5SSuresh Reddy /* Copy the image chunk content. */ 3010a23113b5SSuresh Reddy memcpy(dest_image_ptr, data_ptr, chunk_size); 3011a23113b5SSuresh Reddy 3012a23113b5SSuresh Reddy status = lancer_cmd_write_object(adapter, &flash_cmd, 3013a23113b5SSuresh Reddy chunk_size, offset, 3014a23113b5SSuresh Reddy LANCER_FW_DOWNLOAD_LOCATION, 3015a23113b5SSuresh Reddy &data_written, &change_status, 3016a23113b5SSuresh Reddy &add_status); 3017a23113b5SSuresh Reddy if (status) 3018a23113b5SSuresh Reddy break; 3019a23113b5SSuresh Reddy 3020a23113b5SSuresh Reddy offset += data_written; 3021a23113b5SSuresh Reddy data_ptr += data_written; 3022a23113b5SSuresh Reddy image_size -= data_written; 3023a23113b5SSuresh Reddy } 3024a23113b5SSuresh Reddy 3025a23113b5SSuresh Reddy if (!status) { 3026a23113b5SSuresh Reddy /* Commit the FW written */ 3027a23113b5SSuresh Reddy status = lancer_cmd_write_object(adapter, &flash_cmd, 3028a23113b5SSuresh Reddy 0, offset, 3029a23113b5SSuresh Reddy LANCER_FW_DOWNLOAD_LOCATION, 3030a23113b5SSuresh Reddy &data_written, &change_status, 3031a23113b5SSuresh Reddy &add_status); 3032a23113b5SSuresh Reddy } 3033a23113b5SSuresh Reddy 3034a23113b5SSuresh Reddy dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma); 3035a23113b5SSuresh Reddy if (status) { 3036a23113b5SSuresh Reddy dev_err(dev, "Firmware load error\n"); 3037a23113b5SSuresh Reddy return be_cmd_status(status); 3038a23113b5SSuresh Reddy } 3039a23113b5SSuresh Reddy 3040a23113b5SSuresh Reddy dev_info(dev, "Firmware flashed successfully\n"); 3041a23113b5SSuresh Reddy 3042a23113b5SSuresh Reddy if (change_status == LANCER_FW_RESET_NEEDED) { 3043a23113b5SSuresh Reddy dev_info(dev, "Resetting adapter to activate new FW\n"); 3044a23113b5SSuresh Reddy status = lancer_physdev_ctrl(adapter, 3045a23113b5SSuresh Reddy PHYSDEV_CONTROL_FW_RESET_MASK); 3046a23113b5SSuresh Reddy if (status) { 3047a23113b5SSuresh Reddy dev_err(dev, "Adapter busy, could not reset FW\n"); 3048a23113b5SSuresh Reddy dev_err(dev, "Reboot server to activate new FW\n"); 3049a23113b5SSuresh Reddy } 3050a23113b5SSuresh Reddy } else if (change_status != LANCER_NO_RESET_NEEDED) { 3051a23113b5SSuresh Reddy dev_info(dev, "Reboot server to activate new FW\n"); 3052a23113b5SSuresh Reddy } 3053a23113b5SSuresh Reddy 3054a23113b5SSuresh Reddy return 0; 3055a23113b5SSuresh Reddy } 3056a23113b5SSuresh Reddy 3057a23113b5SSuresh Reddy /* Check if the flash image file is compatible with the adapter that 3058a23113b5SSuresh Reddy * is being flashed. 3059a23113b5SSuresh Reddy */ 3060a23113b5SSuresh Reddy static bool be_check_ufi_compatibility(struct be_adapter *adapter, 3061a23113b5SSuresh Reddy struct flash_file_hdr_g3 *fhdr) 3062a23113b5SSuresh Reddy { 3063a23113b5SSuresh Reddy if (!fhdr) { 3064a23113b5SSuresh Reddy dev_err(&adapter->pdev->dev, "Invalid FW UFI file"); 3065a23113b5SSuresh Reddy return false; 3066a23113b5SSuresh Reddy } 3067a23113b5SSuresh Reddy 3068a23113b5SSuresh Reddy /* First letter of the build version is used to identify 3069a23113b5SSuresh Reddy * which chip this image file is meant for. 3070a23113b5SSuresh Reddy */ 3071a23113b5SSuresh Reddy switch (fhdr->build[0]) { 3072a23113b5SSuresh Reddy case BLD_STR_UFI_TYPE_SH: 3073a23113b5SSuresh Reddy if (!skyhawk_chip(adapter)) 3074a23113b5SSuresh Reddy return false; 3075a23113b5SSuresh Reddy break; 3076a23113b5SSuresh Reddy case BLD_STR_UFI_TYPE_BE3: 3077a23113b5SSuresh Reddy if (!BE3_chip(adapter)) 3078a23113b5SSuresh Reddy return false; 3079a23113b5SSuresh Reddy break; 3080a23113b5SSuresh Reddy case BLD_STR_UFI_TYPE_BE2: 3081a23113b5SSuresh Reddy if (!BE2_chip(adapter)) 3082a23113b5SSuresh Reddy return false; 3083a23113b5SSuresh Reddy break; 3084a23113b5SSuresh Reddy default: 3085a23113b5SSuresh Reddy return false; 3086a23113b5SSuresh Reddy } 3087a23113b5SSuresh Reddy 3088a23113b5SSuresh Reddy /* In BE3 FW images the "asic_type_rev" field doesn't track the 3089a23113b5SSuresh Reddy * asic_rev of the chips it is compatible with. 3090a23113b5SSuresh Reddy * When asic_type_rev is 0 the image is compatible only with 3091a23113b5SSuresh Reddy * pre-BE3-R chips (asic_rev < 0x10) 3092a23113b5SSuresh Reddy */ 3093a23113b5SSuresh Reddy if (BEx_chip(adapter) && fhdr->asic_type_rev == 0) 3094a23113b5SSuresh Reddy return adapter->asic_rev < 0x10; 3095a23113b5SSuresh Reddy else 3096a23113b5SSuresh Reddy return (fhdr->asic_type_rev >= adapter->asic_rev); 3097a23113b5SSuresh Reddy } 3098a23113b5SSuresh Reddy 3099a23113b5SSuresh Reddy int be_fw_download(struct be_adapter *adapter, const struct firmware *fw) 3100a23113b5SSuresh Reddy { 3101a23113b5SSuresh Reddy struct device *dev = &adapter->pdev->dev; 3102a23113b5SSuresh Reddy struct flash_file_hdr_g3 *fhdr3; 3103a23113b5SSuresh Reddy struct image_hdr *img_hdr_ptr; 3104a23113b5SSuresh Reddy int status = 0, i, num_imgs; 3105a23113b5SSuresh Reddy struct be_dma_mem flash_cmd; 3106a23113b5SSuresh Reddy 3107a23113b5SSuresh Reddy fhdr3 = (struct flash_file_hdr_g3 *)fw->data; 3108a23113b5SSuresh Reddy if (!be_check_ufi_compatibility(adapter, fhdr3)) { 3109a23113b5SSuresh Reddy dev_err(dev, "Flash image is not compatible with adapter\n"); 3110a23113b5SSuresh Reddy return -EINVAL; 3111a23113b5SSuresh Reddy } 3112a23113b5SSuresh Reddy 3113a23113b5SSuresh Reddy flash_cmd.size = sizeof(struct be_cmd_write_flashrom); 3114a23113b5SSuresh Reddy flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma, 3115a23113b5SSuresh Reddy GFP_KERNEL); 3116a23113b5SSuresh Reddy if (!flash_cmd.va) 3117a23113b5SSuresh Reddy return -ENOMEM; 3118a23113b5SSuresh Reddy 3119a23113b5SSuresh Reddy num_imgs = le32_to_cpu(fhdr3->num_imgs); 3120a23113b5SSuresh Reddy for (i = 0; i < num_imgs; i++) { 3121a23113b5SSuresh Reddy img_hdr_ptr = (struct image_hdr *)(fw->data + 3122a23113b5SSuresh Reddy (sizeof(struct flash_file_hdr_g3) + 3123a23113b5SSuresh Reddy i * sizeof(struct image_hdr))); 3124a23113b5SSuresh Reddy if (!BE2_chip(adapter) && 3125a23113b5SSuresh Reddy le32_to_cpu(img_hdr_ptr->imageid) != 1) 3126a23113b5SSuresh Reddy continue; 3127a23113b5SSuresh Reddy 3128a23113b5SSuresh Reddy if (skyhawk_chip(adapter)) 3129a23113b5SSuresh Reddy status = be_flash_skyhawk(adapter, fw, &flash_cmd, 3130a23113b5SSuresh Reddy num_imgs); 3131a23113b5SSuresh Reddy else 3132a23113b5SSuresh Reddy status = be_flash_BEx(adapter, fw, &flash_cmd, 3133a23113b5SSuresh Reddy num_imgs); 3134a23113b5SSuresh Reddy } 3135a23113b5SSuresh Reddy 3136a23113b5SSuresh Reddy dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma); 3137a23113b5SSuresh Reddy if (!status) 3138a23113b5SSuresh Reddy dev_info(dev, "Firmware flashed successfully\n"); 3139a23113b5SSuresh Reddy 3140a23113b5SSuresh Reddy return status; 3141a23113b5SSuresh Reddy } 3142a23113b5SSuresh Reddy 31439aebddd1SJeff Kirsher int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, 31449aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 31459aebddd1SJeff Kirsher { 31469aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 31479aebddd1SJeff Kirsher struct be_cmd_req_acpi_wol_magic_config *req; 31489aebddd1SJeff Kirsher int status; 31499aebddd1SJeff Kirsher 31509aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 31519aebddd1SJeff Kirsher 31529aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 31539aebddd1SJeff Kirsher if (!wrb) { 31549aebddd1SJeff Kirsher status = -EBUSY; 31559aebddd1SJeff Kirsher goto err; 31569aebddd1SJeff Kirsher } 31579aebddd1SJeff Kirsher req = nonemb_cmd->va; 31589aebddd1SJeff Kirsher 3159106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 3160a2cc4e0bSSathya Perla OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req), 3161a2cc4e0bSSathya Perla wrb, nonemb_cmd); 31629aebddd1SJeff Kirsher memcpy(req->magic_mac, mac, ETH_ALEN); 31639aebddd1SJeff Kirsher 31649aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 31659aebddd1SJeff Kirsher 31669aebddd1SJeff Kirsher err: 31679aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 31689aebddd1SJeff Kirsher return status; 31699aebddd1SJeff Kirsher } 31709aebddd1SJeff Kirsher 31719aebddd1SJeff Kirsher int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, 31729aebddd1SJeff Kirsher u8 loopback_type, u8 enable) 31739aebddd1SJeff Kirsher { 31749aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 31759aebddd1SJeff Kirsher struct be_cmd_req_set_lmode *req; 31769aebddd1SJeff Kirsher int status; 31779aebddd1SJeff Kirsher 31782e365b1bSSomnath Kotur if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, 31792e365b1bSSomnath Kotur CMD_SUBSYSTEM_LOWLEVEL)) 31802e365b1bSSomnath Kotur return -EPERM; 31812e365b1bSSomnath Kotur 31829aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 31839aebddd1SJeff Kirsher 31849aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 31859aebddd1SJeff Kirsher if (!wrb) { 31869aebddd1SJeff Kirsher status = -EBUSY; 31879c855975SSuresh Reddy goto err_unlock; 31889aebddd1SJeff Kirsher } 31899aebddd1SJeff Kirsher 31909aebddd1SJeff Kirsher req = embedded_payload(wrb); 31919aebddd1SJeff Kirsher 3192106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 3193a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req), 3194a2cc4e0bSSathya Perla wrb, NULL); 31959aebddd1SJeff Kirsher 31969aebddd1SJeff Kirsher req->src_port = port_num; 31979aebddd1SJeff Kirsher req->dest_port = port_num; 31989aebddd1SJeff Kirsher req->loopback_type = loopback_type; 31999aebddd1SJeff Kirsher req->loopback_state = enable; 32009aebddd1SJeff Kirsher 32019c855975SSuresh Reddy status = be_mcc_notify(adapter); 32029c855975SSuresh Reddy if (status) 32039c855975SSuresh Reddy goto err_unlock; 32049c855975SSuresh Reddy 32059c855975SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 32069c855975SSuresh Reddy 32079c855975SSuresh Reddy if (!wait_for_completion_timeout(&adapter->et_cmd_compl, 32089c855975SSuresh Reddy msecs_to_jiffies(SET_LB_MODE_TIMEOUT))) 32099c855975SSuresh Reddy status = -ETIMEDOUT; 32109c855975SSuresh Reddy 32119c855975SSuresh Reddy return status; 32129c855975SSuresh Reddy 32139c855975SSuresh Reddy err_unlock: 32149aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 32159aebddd1SJeff Kirsher return status; 32169aebddd1SJeff Kirsher } 32179aebddd1SJeff Kirsher 32189aebddd1SJeff Kirsher int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, 3219a2cc4e0bSSathya Perla u32 loopback_type, u32 pkt_size, u32 num_pkts, 3220a2cc4e0bSSathya Perla u64 pattern) 32219aebddd1SJeff Kirsher { 32229aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 32239aebddd1SJeff Kirsher struct be_cmd_req_loopback_test *req; 32245eeff635SSuresh Reddy struct be_cmd_resp_loopback_test *resp; 32259aebddd1SJeff Kirsher int status; 32269aebddd1SJeff Kirsher 32272e365b1bSSomnath Kotur if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_LOOPBACK_TEST, 32282e365b1bSSomnath Kotur CMD_SUBSYSTEM_LOWLEVEL)) 32292e365b1bSSomnath Kotur return -EPERM; 32302e365b1bSSomnath Kotur 32319aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 32329aebddd1SJeff Kirsher 32339aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 32349aebddd1SJeff Kirsher if (!wrb) { 32359aebddd1SJeff Kirsher status = -EBUSY; 32369aebddd1SJeff Kirsher goto err; 32379aebddd1SJeff Kirsher } 32389aebddd1SJeff Kirsher 32399aebddd1SJeff Kirsher req = embedded_payload(wrb); 32409aebddd1SJeff Kirsher 3241106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 3242a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, 3243a2cc4e0bSSathya Perla NULL); 32449aebddd1SJeff Kirsher 32455eeff635SSuresh Reddy req->hdr.timeout = cpu_to_le32(15); 32469aebddd1SJeff Kirsher req->pattern = cpu_to_le64(pattern); 32479aebddd1SJeff Kirsher req->src_port = cpu_to_le32(port_num); 32489aebddd1SJeff Kirsher req->dest_port = cpu_to_le32(port_num); 32499aebddd1SJeff Kirsher req->pkt_size = cpu_to_le32(pkt_size); 32509aebddd1SJeff Kirsher req->num_pkts = cpu_to_le32(num_pkts); 32519aebddd1SJeff Kirsher req->loopback_type = cpu_to_le32(loopback_type); 32529aebddd1SJeff Kirsher 3253efaa408eSSuresh Reddy status = be_mcc_notify(adapter); 3254efaa408eSSuresh Reddy if (status) 3255efaa408eSSuresh Reddy goto err; 32569aebddd1SJeff Kirsher 32575eeff635SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 32585eeff635SSuresh Reddy 32595eeff635SSuresh Reddy wait_for_completion(&adapter->et_cmd_compl); 32605eeff635SSuresh Reddy resp = embedded_payload(wrb); 32615eeff635SSuresh Reddy status = le32_to_cpu(resp->status); 32625eeff635SSuresh Reddy 32635eeff635SSuresh Reddy return status; 32649aebddd1SJeff Kirsher err: 32659aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 32669aebddd1SJeff Kirsher return status; 32679aebddd1SJeff Kirsher } 32689aebddd1SJeff Kirsher 32699aebddd1SJeff Kirsher int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, 32709aebddd1SJeff Kirsher u32 byte_cnt, struct be_dma_mem *cmd) 32719aebddd1SJeff Kirsher { 32729aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 32739aebddd1SJeff Kirsher struct be_cmd_req_ddrdma_test *req; 32749aebddd1SJeff Kirsher int status; 32759aebddd1SJeff Kirsher int i, j = 0; 32769aebddd1SJeff Kirsher 32772e365b1bSSomnath Kotur if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_HOST_DDR_DMA, 32782e365b1bSSomnath Kotur CMD_SUBSYSTEM_LOWLEVEL)) 32792e365b1bSSomnath Kotur return -EPERM; 32802e365b1bSSomnath Kotur 32819aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 32829aebddd1SJeff Kirsher 32839aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 32849aebddd1SJeff Kirsher if (!wrb) { 32859aebddd1SJeff Kirsher status = -EBUSY; 32869aebddd1SJeff Kirsher goto err; 32879aebddd1SJeff Kirsher } 32889aebddd1SJeff Kirsher req = cmd->va; 3289106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 3290a2cc4e0bSSathya Perla OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb, 3291a2cc4e0bSSathya Perla cmd); 32929aebddd1SJeff Kirsher 32939aebddd1SJeff Kirsher req->pattern = cpu_to_le64(pattern); 32949aebddd1SJeff Kirsher req->byte_count = cpu_to_le32(byte_cnt); 32959aebddd1SJeff Kirsher for (i = 0; i < byte_cnt; i++) { 32969aebddd1SJeff Kirsher req->snd_buff[i] = (u8)(pattern >> (j*8)); 32979aebddd1SJeff Kirsher j++; 32989aebddd1SJeff Kirsher if (j > 7) 32999aebddd1SJeff Kirsher j = 0; 33009aebddd1SJeff Kirsher } 33019aebddd1SJeff Kirsher 33029aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 33039aebddd1SJeff Kirsher 33049aebddd1SJeff Kirsher if (!status) { 33059aebddd1SJeff Kirsher struct be_cmd_resp_ddrdma_test *resp; 330603d28ffeSKalesh AP 33079aebddd1SJeff Kirsher resp = cmd->va; 33089aebddd1SJeff Kirsher if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) || 33099aebddd1SJeff Kirsher resp->snd_err) { 33109aebddd1SJeff Kirsher status = -1; 33119aebddd1SJeff Kirsher } 33129aebddd1SJeff Kirsher } 33139aebddd1SJeff Kirsher 33149aebddd1SJeff Kirsher err: 33159aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 33169aebddd1SJeff Kirsher return status; 33179aebddd1SJeff Kirsher } 33189aebddd1SJeff Kirsher 33199aebddd1SJeff Kirsher int be_cmd_get_seeprom_data(struct be_adapter *adapter, 33209aebddd1SJeff Kirsher struct be_dma_mem *nonemb_cmd) 33219aebddd1SJeff Kirsher { 33229aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 33239aebddd1SJeff Kirsher struct be_cmd_req_seeprom_read *req; 33249aebddd1SJeff Kirsher int status; 33259aebddd1SJeff Kirsher 33269aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 33279aebddd1SJeff Kirsher 33289aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 33299aebddd1SJeff Kirsher if (!wrb) { 33309aebddd1SJeff Kirsher status = -EBUSY; 33319aebddd1SJeff Kirsher goto err; 33329aebddd1SJeff Kirsher } 33339aebddd1SJeff Kirsher req = nonemb_cmd->va; 33349aebddd1SJeff Kirsher 3335106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3336106df1e3SSomnath Kotur OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb, 3337106df1e3SSomnath Kotur nonemb_cmd); 33389aebddd1SJeff Kirsher 33399aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 33409aebddd1SJeff Kirsher 33419aebddd1SJeff Kirsher err: 33429aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 33439aebddd1SJeff Kirsher return status; 33449aebddd1SJeff Kirsher } 33459aebddd1SJeff Kirsher 334642f11cf2SAjit Khaparde int be_cmd_get_phy_info(struct be_adapter *adapter) 33479aebddd1SJeff Kirsher { 33489aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 33499aebddd1SJeff Kirsher struct be_cmd_req_get_phy_info *req; 33509aebddd1SJeff Kirsher struct be_dma_mem cmd; 33519aebddd1SJeff Kirsher int status; 33529aebddd1SJeff Kirsher 3353f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS, 3354f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_COMMON)) 3355f25b119cSPadmanabh Ratnakar return -EPERM; 3356f25b119cSPadmanabh Ratnakar 33579aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 33589aebddd1SJeff Kirsher 33599aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 33609aebddd1SJeff Kirsher if (!wrb) { 33619aebddd1SJeff Kirsher status = -EBUSY; 33629aebddd1SJeff Kirsher goto err; 33639aebddd1SJeff Kirsher } 33649aebddd1SJeff Kirsher cmd.size = sizeof(struct be_cmd_req_get_phy_info); 3365e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 3366e51000dbSSriharsha Basavapatna GFP_ATOMIC); 33679aebddd1SJeff Kirsher if (!cmd.va) { 33689aebddd1SJeff Kirsher dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); 33699aebddd1SJeff Kirsher status = -ENOMEM; 33709aebddd1SJeff Kirsher goto err; 33719aebddd1SJeff Kirsher } 33729aebddd1SJeff Kirsher 33739aebddd1SJeff Kirsher req = cmd.va; 33749aebddd1SJeff Kirsher 3375106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3376106df1e3SSomnath Kotur OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req), 3377106df1e3SSomnath Kotur wrb, &cmd); 33789aebddd1SJeff Kirsher 33799aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 33809aebddd1SJeff Kirsher if (!status) { 33819aebddd1SJeff Kirsher struct be_phy_info *resp_phy_info = 33829aebddd1SJeff Kirsher cmd.va + sizeof(struct be_cmd_req_hdr); 338303d28ffeSKalesh AP 338442f11cf2SAjit Khaparde adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type); 338542f11cf2SAjit Khaparde adapter->phy.interface_type = 33869aebddd1SJeff Kirsher le16_to_cpu(resp_phy_info->interface_type); 338742f11cf2SAjit Khaparde adapter->phy.auto_speeds_supported = 338842f11cf2SAjit Khaparde le16_to_cpu(resp_phy_info->auto_speeds_supported); 338942f11cf2SAjit Khaparde adapter->phy.fixed_speeds_supported = 339042f11cf2SAjit Khaparde le16_to_cpu(resp_phy_info->fixed_speeds_supported); 339142f11cf2SAjit Khaparde adapter->phy.misc_params = 339242f11cf2SAjit Khaparde le32_to_cpu(resp_phy_info->misc_params); 339368cb7e47SVasundhara Volam 339468cb7e47SVasundhara Volam if (BE2_chip(adapter)) { 339568cb7e47SVasundhara Volam adapter->phy.fixed_speeds_supported = 339668cb7e47SVasundhara Volam BE_SUPPORTED_SPEED_10GBPS | 339768cb7e47SVasundhara Volam BE_SUPPORTED_SPEED_1GBPS; 339868cb7e47SVasundhara Volam } 33999aebddd1SJeff Kirsher } 3400e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); 34019aebddd1SJeff Kirsher err: 34029aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 34039aebddd1SJeff Kirsher return status; 34049aebddd1SJeff Kirsher } 34059aebddd1SJeff Kirsher 3406bc0ee163SLad, Prabhakar static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain) 34079aebddd1SJeff Kirsher { 34089aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 34099aebddd1SJeff Kirsher struct be_cmd_req_set_qos *req; 34109aebddd1SJeff Kirsher int status; 34119aebddd1SJeff Kirsher 34129aebddd1SJeff Kirsher spin_lock_bh(&adapter->mcc_lock); 34139aebddd1SJeff Kirsher 34149aebddd1SJeff Kirsher wrb = wrb_from_mccq(adapter); 34159aebddd1SJeff Kirsher if (!wrb) { 34169aebddd1SJeff Kirsher status = -EBUSY; 34179aebddd1SJeff Kirsher goto err; 34189aebddd1SJeff Kirsher } 34199aebddd1SJeff Kirsher 34209aebddd1SJeff Kirsher req = embedded_payload(wrb); 34219aebddd1SJeff Kirsher 3422106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3423106df1e3SSomnath Kotur OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL); 34249aebddd1SJeff Kirsher 34259aebddd1SJeff Kirsher req->hdr.domain = domain; 34269aebddd1SJeff Kirsher req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC); 34279aebddd1SJeff Kirsher req->max_bps_nic = cpu_to_le32(bps); 34289aebddd1SJeff Kirsher 34299aebddd1SJeff Kirsher status = be_mcc_notify_wait(adapter); 34309aebddd1SJeff Kirsher 34319aebddd1SJeff Kirsher err: 34329aebddd1SJeff Kirsher spin_unlock_bh(&adapter->mcc_lock); 34339aebddd1SJeff Kirsher return status; 34349aebddd1SJeff Kirsher } 34359aebddd1SJeff Kirsher 34369aebddd1SJeff Kirsher int be_cmd_get_cntl_attributes(struct be_adapter *adapter) 34379aebddd1SJeff Kirsher { 34389aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 34399aebddd1SJeff Kirsher struct be_cmd_req_cntl_attribs *req; 34409aebddd1SJeff Kirsher struct be_cmd_resp_cntl_attribs *resp; 3441a155a5dbSSriharsha Basavapatna int status, i; 34429aebddd1SJeff Kirsher int payload_len = max(sizeof(*req), sizeof(*resp)); 34439aebddd1SJeff Kirsher struct mgmt_controller_attrib *attribs; 34449aebddd1SJeff Kirsher struct be_dma_mem attribs_cmd; 3445a155a5dbSSriharsha Basavapatna u32 *serial_num; 34469aebddd1SJeff Kirsher 3447d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 3448d98ef50fSSuresh Reddy return -1; 3449d98ef50fSSuresh Reddy 34509aebddd1SJeff Kirsher memset(&attribs_cmd, 0, sizeof(struct be_dma_mem)); 34519aebddd1SJeff Kirsher attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs); 3452e51000dbSSriharsha Basavapatna attribs_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 3453e51000dbSSriharsha Basavapatna attribs_cmd.size, 3454e51000dbSSriharsha Basavapatna &attribs_cmd.dma, GFP_ATOMIC); 34559aebddd1SJeff Kirsher if (!attribs_cmd.va) { 3456a2cc4e0bSSathya Perla dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); 3457d98ef50fSSuresh Reddy status = -ENOMEM; 3458d98ef50fSSuresh Reddy goto err; 34599aebddd1SJeff Kirsher } 34609aebddd1SJeff Kirsher 34619aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 34629aebddd1SJeff Kirsher if (!wrb) { 34639aebddd1SJeff Kirsher status = -EBUSY; 34649aebddd1SJeff Kirsher goto err; 34659aebddd1SJeff Kirsher } 34669aebddd1SJeff Kirsher req = attribs_cmd.va; 34679aebddd1SJeff Kirsher 3468106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3469a2cc4e0bSSathya Perla OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len, 3470a2cc4e0bSSathya Perla wrb, &attribs_cmd); 34719aebddd1SJeff Kirsher 34729aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 34739aebddd1SJeff Kirsher if (!status) { 34749aebddd1SJeff Kirsher attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr); 34759aebddd1SJeff Kirsher adapter->hba_port_num = attribs->hba_attribs.phy_port; 3476a155a5dbSSriharsha Basavapatna serial_num = attribs->hba_attribs.controller_serial_number; 3477a155a5dbSSriharsha Basavapatna for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++) 3478a155a5dbSSriharsha Basavapatna adapter->serial_num[i] = le32_to_cpu(serial_num[i]) & 3479a155a5dbSSriharsha Basavapatna (BIT_MASK(16) - 1); 34809aebddd1SJeff Kirsher } 34819aebddd1SJeff Kirsher 34829aebddd1SJeff Kirsher err: 34839aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 3484d98ef50fSSuresh Reddy if (attribs_cmd.va) 3485e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, attribs_cmd.size, 3486d98ef50fSSuresh Reddy attribs_cmd.va, attribs_cmd.dma); 34879aebddd1SJeff Kirsher return status; 34889aebddd1SJeff Kirsher } 34899aebddd1SJeff Kirsher 34909aebddd1SJeff Kirsher /* Uses mbox */ 34919aebddd1SJeff Kirsher int be_cmd_req_native_mode(struct be_adapter *adapter) 34929aebddd1SJeff Kirsher { 34939aebddd1SJeff Kirsher struct be_mcc_wrb *wrb; 34949aebddd1SJeff Kirsher struct be_cmd_req_set_func_cap *req; 34959aebddd1SJeff Kirsher int status; 34969aebddd1SJeff Kirsher 34979aebddd1SJeff Kirsher if (mutex_lock_interruptible(&adapter->mbox_lock)) 34989aebddd1SJeff Kirsher return -1; 34999aebddd1SJeff Kirsher 35009aebddd1SJeff Kirsher wrb = wrb_from_mbox(adapter); 35019aebddd1SJeff Kirsher if (!wrb) { 35029aebddd1SJeff Kirsher status = -EBUSY; 35039aebddd1SJeff Kirsher goto err; 35049aebddd1SJeff Kirsher } 35059aebddd1SJeff Kirsher 35069aebddd1SJeff Kirsher req = embedded_payload(wrb); 35079aebddd1SJeff Kirsher 3508106df1e3SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3509a2cc4e0bSSathya Perla OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP, 3510a2cc4e0bSSathya Perla sizeof(*req), wrb, NULL); 35119aebddd1SJeff Kirsher 35129aebddd1SJeff Kirsher req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS | 35139aebddd1SJeff Kirsher CAPABILITY_BE3_NATIVE_ERX_API); 35149aebddd1SJeff Kirsher req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API); 35159aebddd1SJeff Kirsher 35169aebddd1SJeff Kirsher status = be_mbox_notify_wait(adapter); 35179aebddd1SJeff Kirsher if (!status) { 35189aebddd1SJeff Kirsher struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb); 351903d28ffeSKalesh AP 35209aebddd1SJeff Kirsher adapter->be3_native = le32_to_cpu(resp->cap_flags) & 35219aebddd1SJeff Kirsher CAPABILITY_BE3_NATIVE_ERX_API; 3522d379142bSSathya Perla if (!adapter->be3_native) 3523d379142bSSathya Perla dev_warn(&adapter->pdev->dev, 3524d379142bSSathya Perla "adapter not in advanced mode\n"); 35259aebddd1SJeff Kirsher } 35269aebddd1SJeff Kirsher err: 35279aebddd1SJeff Kirsher mutex_unlock(&adapter->mbox_lock); 35289aebddd1SJeff Kirsher return status; 35299aebddd1SJeff Kirsher } 3530590c391dSPadmanabh Ratnakar 3531f25b119cSPadmanabh Ratnakar /* Get privilege(s) for a function */ 3532f25b119cSPadmanabh Ratnakar int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, 3533f25b119cSPadmanabh Ratnakar u32 domain) 3534f25b119cSPadmanabh Ratnakar { 3535f25b119cSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3536f25b119cSPadmanabh Ratnakar struct be_cmd_req_get_fn_privileges *req; 3537f25b119cSPadmanabh Ratnakar int status; 3538f25b119cSPadmanabh Ratnakar 3539f25b119cSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 3540f25b119cSPadmanabh Ratnakar 3541f25b119cSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 3542f25b119cSPadmanabh Ratnakar if (!wrb) { 3543f25b119cSPadmanabh Ratnakar status = -EBUSY; 3544f25b119cSPadmanabh Ratnakar goto err; 3545f25b119cSPadmanabh Ratnakar } 3546f25b119cSPadmanabh Ratnakar 3547f25b119cSPadmanabh Ratnakar req = embedded_payload(wrb); 3548f25b119cSPadmanabh Ratnakar 3549f25b119cSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3550f25b119cSPadmanabh Ratnakar OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req), 3551f25b119cSPadmanabh Ratnakar wrb, NULL); 3552f25b119cSPadmanabh Ratnakar 3553f25b119cSPadmanabh Ratnakar req->hdr.domain = domain; 3554f25b119cSPadmanabh Ratnakar 3555f25b119cSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 3556f25b119cSPadmanabh Ratnakar if (!status) { 3557f25b119cSPadmanabh Ratnakar struct be_cmd_resp_get_fn_privileges *resp = 3558f25b119cSPadmanabh Ratnakar embedded_payload(wrb); 355903d28ffeSKalesh AP 3560f25b119cSPadmanabh Ratnakar *privilege = le32_to_cpu(resp->privilege_mask); 356102308d74SSuresh Reddy 356202308d74SSuresh Reddy /* In UMC mode FW does not return right privileges. 356302308d74SSuresh Reddy * Override with correct privilege equivalent to PF. 356402308d74SSuresh Reddy */ 356502308d74SSuresh Reddy if (BEx_chip(adapter) && be_is_mc(adapter) && 356602308d74SSuresh Reddy be_physfn(adapter)) 356702308d74SSuresh Reddy *privilege = MAX_PRIVILEGES; 3568f25b119cSPadmanabh Ratnakar } 3569f25b119cSPadmanabh Ratnakar 3570f25b119cSPadmanabh Ratnakar err: 3571f25b119cSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 3572f25b119cSPadmanabh Ratnakar return status; 3573f25b119cSPadmanabh Ratnakar } 3574f25b119cSPadmanabh Ratnakar 357504a06028SSathya Perla /* Set privilege(s) for a function */ 357604a06028SSathya Perla int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, 357704a06028SSathya Perla u32 domain) 357804a06028SSathya Perla { 357904a06028SSathya Perla struct be_mcc_wrb *wrb; 358004a06028SSathya Perla struct be_cmd_req_set_fn_privileges *req; 358104a06028SSathya Perla int status; 358204a06028SSathya Perla 358304a06028SSathya Perla spin_lock_bh(&adapter->mcc_lock); 358404a06028SSathya Perla 358504a06028SSathya Perla wrb = wrb_from_mccq(adapter); 358604a06028SSathya Perla if (!wrb) { 358704a06028SSathya Perla status = -EBUSY; 358804a06028SSathya Perla goto err; 358904a06028SSathya Perla } 359004a06028SSathya Perla 359104a06028SSathya Perla req = embedded_payload(wrb); 359204a06028SSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 359304a06028SSathya Perla OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req), 359404a06028SSathya Perla wrb, NULL); 359504a06028SSathya Perla req->hdr.domain = domain; 359604a06028SSathya Perla if (lancer_chip(adapter)) 359704a06028SSathya Perla req->privileges_lancer = cpu_to_le32(privileges); 359804a06028SSathya Perla else 359904a06028SSathya Perla req->privileges = cpu_to_le32(privileges); 360004a06028SSathya Perla 360104a06028SSathya Perla status = be_mcc_notify_wait(adapter); 360204a06028SSathya Perla err: 360304a06028SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 360404a06028SSathya Perla return status; 360504a06028SSathya Perla } 360604a06028SSathya Perla 36075a712c13SSathya Perla /* pmac_id_valid: true => pmac_id is supplied and MAC address is requested. 36085a712c13SSathya Perla * pmac_id_valid: false => pmac_id or MAC address is requested. 36095a712c13SSathya Perla * If pmac_id is returned, pmac_id_valid is returned as true 36105a712c13SSathya Perla */ 36111578e777SPadmanabh Ratnakar int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, 3612b188f090SSuresh Reddy bool *pmac_id_valid, u32 *pmac_id, u32 if_handle, 3613b188f090SSuresh Reddy u8 domain) 3614590c391dSPadmanabh Ratnakar { 3615590c391dSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3616590c391dSPadmanabh Ratnakar struct be_cmd_req_get_mac_list *req; 3617590c391dSPadmanabh Ratnakar int status; 3618590c391dSPadmanabh Ratnakar int mac_count; 3619e5e1ee89SPadmanabh Ratnakar struct be_dma_mem get_mac_list_cmd; 3620e5e1ee89SPadmanabh Ratnakar int i; 3621e5e1ee89SPadmanabh Ratnakar 3622e5e1ee89SPadmanabh Ratnakar memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem)); 3623e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list); 3624e51000dbSSriharsha Basavapatna get_mac_list_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 3625e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.size, 3626e51000dbSSriharsha Basavapatna &get_mac_list_cmd.dma, 3627e51000dbSSriharsha Basavapatna GFP_ATOMIC); 3628e5e1ee89SPadmanabh Ratnakar 3629e5e1ee89SPadmanabh Ratnakar if (!get_mac_list_cmd.va) { 3630e5e1ee89SPadmanabh Ratnakar dev_err(&adapter->pdev->dev, 3631e5e1ee89SPadmanabh Ratnakar "Memory allocation failure during GET_MAC_LIST\n"); 3632e5e1ee89SPadmanabh Ratnakar return -ENOMEM; 3633e5e1ee89SPadmanabh Ratnakar } 3634590c391dSPadmanabh Ratnakar 3635590c391dSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 3636590c391dSPadmanabh Ratnakar 3637590c391dSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 3638590c391dSPadmanabh Ratnakar if (!wrb) { 3639590c391dSPadmanabh Ratnakar status = -EBUSY; 3640e5e1ee89SPadmanabh Ratnakar goto out; 3641590c391dSPadmanabh Ratnakar } 3642e5e1ee89SPadmanabh Ratnakar 3643e5e1ee89SPadmanabh Ratnakar req = get_mac_list_cmd.va; 3644590c391dSPadmanabh Ratnakar 3645590c391dSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3646bf591f51SSathya Perla OPCODE_COMMON_GET_MAC_LIST, 3647bf591f51SSathya Perla get_mac_list_cmd.size, wrb, &get_mac_list_cmd); 3648590c391dSPadmanabh Ratnakar req->hdr.domain = domain; 3649e5e1ee89SPadmanabh Ratnakar req->mac_type = MAC_ADDRESS_TYPE_NETWORK; 36505a712c13SSathya Perla if (*pmac_id_valid) { 36515a712c13SSathya Perla req->mac_id = cpu_to_le32(*pmac_id); 3652b188f090SSuresh Reddy req->iface_id = cpu_to_le16(if_handle); 36535a712c13SSathya Perla req->perm_override = 0; 36545a712c13SSathya Perla } else { 3655e5e1ee89SPadmanabh Ratnakar req->perm_override = 1; 36565a712c13SSathya Perla } 3657590c391dSPadmanabh Ratnakar 3658590c391dSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 3659590c391dSPadmanabh Ratnakar if (!status) { 3660590c391dSPadmanabh Ratnakar struct be_cmd_resp_get_mac_list *resp = 3661e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va; 36625a712c13SSathya Perla 36635a712c13SSathya Perla if (*pmac_id_valid) { 36645a712c13SSathya Perla memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr, 36655a712c13SSathya Perla ETH_ALEN); 36665a712c13SSathya Perla goto out; 36675a712c13SSathya Perla } 36685a712c13SSathya Perla 3669e5e1ee89SPadmanabh Ratnakar mac_count = resp->true_mac_count + resp->pseudo_mac_count; 3670e5e1ee89SPadmanabh Ratnakar /* Mac list returned could contain one or more active mac_ids 3671dbedd44eSJoe Perches * or one or more true or pseudo permanent mac addresses. 36721578e777SPadmanabh Ratnakar * If an active mac_id is present, return first active mac_id 36731578e777SPadmanabh Ratnakar * found. 3674e5e1ee89SPadmanabh Ratnakar */ 3675590c391dSPadmanabh Ratnakar for (i = 0; i < mac_count; i++) { 3676e5e1ee89SPadmanabh Ratnakar struct get_list_macaddr *mac_entry; 3677e5e1ee89SPadmanabh Ratnakar u16 mac_addr_size; 3678e5e1ee89SPadmanabh Ratnakar u32 mac_id; 3679e5e1ee89SPadmanabh Ratnakar 3680e5e1ee89SPadmanabh Ratnakar mac_entry = &resp->macaddr_list[i]; 3681e5e1ee89SPadmanabh Ratnakar mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size); 3682e5e1ee89SPadmanabh Ratnakar /* mac_id is a 32 bit value and mac_addr size 3683e5e1ee89SPadmanabh Ratnakar * is 6 bytes 3684e5e1ee89SPadmanabh Ratnakar */ 3685e5e1ee89SPadmanabh Ratnakar if (mac_addr_size == sizeof(u32)) { 36865a712c13SSathya Perla *pmac_id_valid = true; 3687e5e1ee89SPadmanabh Ratnakar mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; 3688e5e1ee89SPadmanabh Ratnakar *pmac_id = le32_to_cpu(mac_id); 3689e5e1ee89SPadmanabh Ratnakar goto out; 3690590c391dSPadmanabh Ratnakar } 3691590c391dSPadmanabh Ratnakar } 36921578e777SPadmanabh Ratnakar /* If no active mac_id found, return first mac addr */ 36935a712c13SSathya Perla *pmac_id_valid = false; 3694e5e1ee89SPadmanabh Ratnakar memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, 3695e5e1ee89SPadmanabh Ratnakar ETH_ALEN); 3696590c391dSPadmanabh Ratnakar } 3697590c391dSPadmanabh Ratnakar 3698e5e1ee89SPadmanabh Ratnakar out: 3699590c391dSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 3700e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, get_mac_list_cmd.size, 3701e5e1ee89SPadmanabh Ratnakar get_mac_list_cmd.va, get_mac_list_cmd.dma); 3702590c391dSPadmanabh Ratnakar return status; 3703590c391dSPadmanabh Ratnakar } 3704590c391dSPadmanabh Ratnakar 3705a2cc4e0bSSathya Perla int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id, 3706a2cc4e0bSSathya Perla u8 *mac, u32 if_handle, bool active, u32 domain) 37075a712c13SSathya Perla { 3708b188f090SSuresh Reddy if (!active) 3709b188f090SSuresh Reddy be_cmd_get_mac_from_list(adapter, mac, &active, &curr_pmac_id, 3710b188f090SSuresh Reddy if_handle, domain); 37113175d8c2SSathya Perla if (BEx_chip(adapter)) 37125a712c13SSathya Perla return be_cmd_mac_addr_query(adapter, mac, false, 3713b188f090SSuresh Reddy if_handle, curr_pmac_id); 37143175d8c2SSathya Perla else 37153175d8c2SSathya Perla /* Fetch the MAC address using pmac_id */ 37163175d8c2SSathya Perla return be_cmd_get_mac_from_list(adapter, mac, &active, 3717b188f090SSuresh Reddy &curr_pmac_id, 3718b188f090SSuresh Reddy if_handle, domain); 37195a712c13SSathya Perla } 37205a712c13SSathya Perla 372195046b92SSathya Perla int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac) 372295046b92SSathya Perla { 372395046b92SSathya Perla int status; 372495046b92SSathya Perla bool pmac_valid = false; 372595046b92SSathya Perla 3726c7bf7169SJoe Perches eth_zero_addr(mac); 372795046b92SSathya Perla 37283175d8c2SSathya Perla if (BEx_chip(adapter)) { 37293175d8c2SSathya Perla if (be_physfn(adapter)) 37303175d8c2SSathya Perla status = be_cmd_mac_addr_query(adapter, mac, true, 0, 37313175d8c2SSathya Perla 0); 373295046b92SSathya Perla else 373395046b92SSathya Perla status = be_cmd_mac_addr_query(adapter, mac, false, 373495046b92SSathya Perla adapter->if_handle, 0); 37353175d8c2SSathya Perla } else { 37363175d8c2SSathya Perla status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid, 3737b188f090SSuresh Reddy NULL, adapter->if_handle, 0); 37383175d8c2SSathya Perla } 37393175d8c2SSathya Perla 374095046b92SSathya Perla return status; 374195046b92SSathya Perla } 374295046b92SSathya Perla 3743590c391dSPadmanabh Ratnakar /* Uses synchronous MCCQ */ 3744590c391dSPadmanabh Ratnakar int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, 3745590c391dSPadmanabh Ratnakar u8 mac_count, u32 domain) 3746590c391dSPadmanabh Ratnakar { 3747590c391dSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 3748590c391dSPadmanabh Ratnakar struct be_cmd_req_set_mac_list *req; 3749590c391dSPadmanabh Ratnakar int status; 3750590c391dSPadmanabh Ratnakar struct be_dma_mem cmd; 3751590c391dSPadmanabh Ratnakar 3752590c391dSPadmanabh Ratnakar memset(&cmd, 0, sizeof(struct be_dma_mem)); 3753590c391dSPadmanabh Ratnakar cmd.size = sizeof(struct be_cmd_req_set_mac_list); 3754e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 3755e51000dbSSriharsha Basavapatna GFP_KERNEL); 3756d0320f75SJoe Perches if (!cmd.va) 3757590c391dSPadmanabh Ratnakar return -ENOMEM; 3758590c391dSPadmanabh Ratnakar 3759590c391dSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 3760590c391dSPadmanabh Ratnakar 3761590c391dSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 3762590c391dSPadmanabh Ratnakar if (!wrb) { 3763590c391dSPadmanabh Ratnakar status = -EBUSY; 3764590c391dSPadmanabh Ratnakar goto err; 3765590c391dSPadmanabh Ratnakar } 3766590c391dSPadmanabh Ratnakar 3767590c391dSPadmanabh Ratnakar req = cmd.va; 3768590c391dSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3769590c391dSPadmanabh Ratnakar OPCODE_COMMON_SET_MAC_LIST, sizeof(*req), 3770590c391dSPadmanabh Ratnakar wrb, &cmd); 3771590c391dSPadmanabh Ratnakar 3772590c391dSPadmanabh Ratnakar req->hdr.domain = domain; 3773590c391dSPadmanabh Ratnakar req->mac_count = mac_count; 3774590c391dSPadmanabh Ratnakar if (mac_count) 3775590c391dSPadmanabh Ratnakar memcpy(req->mac, mac_array, ETH_ALEN*mac_count); 3776590c391dSPadmanabh Ratnakar 3777590c391dSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 3778590c391dSPadmanabh Ratnakar 3779590c391dSPadmanabh Ratnakar err: 3780a2cc4e0bSSathya Perla dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); 3781590c391dSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 3782590c391dSPadmanabh Ratnakar return status; 3783590c391dSPadmanabh Ratnakar } 37844762f6ceSAjit Khaparde 37853175d8c2SSathya Perla /* Wrapper to delete any active MACs and provision the new mac. 37863175d8c2SSathya Perla * Changes to MAC_LIST are allowed iff none of the MAC addresses in the 37873175d8c2SSathya Perla * current list are active. 37883175d8c2SSathya Perla */ 37893175d8c2SSathya Perla int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom) 37903175d8c2SSathya Perla { 37913175d8c2SSathya Perla bool active_mac = false; 37923175d8c2SSathya Perla u8 old_mac[ETH_ALEN]; 37933175d8c2SSathya Perla u32 pmac_id; 37943175d8c2SSathya Perla int status; 37953175d8c2SSathya Perla 37963175d8c2SSathya Perla status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac, 3797b188f090SSuresh Reddy &pmac_id, if_id, dom); 3798b188f090SSuresh Reddy 37993175d8c2SSathya Perla if (!status && active_mac) 38003175d8c2SSathya Perla be_cmd_pmac_del(adapter, if_id, pmac_id, dom); 38013175d8c2SSathya Perla 38023175d8c2SSathya Perla return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom); 38033175d8c2SSathya Perla } 38043175d8c2SSathya Perla 3805f1f3ee1bSAjit Khaparde int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, 3806e7bcbd7bSKalesh AP u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk) 3807f1f3ee1bSAjit Khaparde { 3808f1f3ee1bSAjit Khaparde struct be_mcc_wrb *wrb; 3809f1f3ee1bSAjit Khaparde struct be_cmd_req_set_hsw_config *req; 3810f1f3ee1bSAjit Khaparde void *ctxt; 3811f1f3ee1bSAjit Khaparde int status; 3812f1f3ee1bSAjit Khaparde 3813f1f3ee1bSAjit Khaparde spin_lock_bh(&adapter->mcc_lock); 3814f1f3ee1bSAjit Khaparde 3815f1f3ee1bSAjit Khaparde wrb = wrb_from_mccq(adapter); 3816f1f3ee1bSAjit Khaparde if (!wrb) { 3817f1f3ee1bSAjit Khaparde status = -EBUSY; 3818f1f3ee1bSAjit Khaparde goto err; 3819f1f3ee1bSAjit Khaparde } 3820f1f3ee1bSAjit Khaparde 3821f1f3ee1bSAjit Khaparde req = embedded_payload(wrb); 3822f1f3ee1bSAjit Khaparde ctxt = &req->context; 3823f1f3ee1bSAjit Khaparde 3824f1f3ee1bSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3825a2cc4e0bSSathya Perla OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb, 3826a2cc4e0bSSathya Perla NULL); 3827f1f3ee1bSAjit Khaparde 3828f1f3ee1bSAjit Khaparde req->hdr.domain = domain; 3829f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id); 3830f1f3ee1bSAjit Khaparde if (pvid) { 3831f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1); 3832f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid); 3833f1f3ee1bSAjit Khaparde } 3834a77dcb8cSAjit Khaparde if (!BEx_chip(adapter) && hsw_mode) { 3835a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, 3836a77dcb8cSAjit Khaparde ctxt, adapter->hba_port_num); 3837a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1); 3838a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type, 3839a77dcb8cSAjit Khaparde ctxt, hsw_mode); 3840a77dcb8cSAjit Khaparde } 3841f1f3ee1bSAjit Khaparde 3842e7bcbd7bSKalesh AP /* Enable/disable both mac and vlan spoof checking */ 3843e7bcbd7bSKalesh AP if (!BEx_chip(adapter) && spoofchk) { 3844e7bcbd7bSKalesh AP AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk, 3845e7bcbd7bSKalesh AP ctxt, spoofchk); 3846e7bcbd7bSKalesh AP AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk, 3847e7bcbd7bSKalesh AP ctxt, spoofchk); 3848e7bcbd7bSKalesh AP } 3849e7bcbd7bSKalesh AP 3850f1f3ee1bSAjit Khaparde be_dws_cpu_to_le(req->context, sizeof(req->context)); 3851f1f3ee1bSAjit Khaparde status = be_mcc_notify_wait(adapter); 3852f1f3ee1bSAjit Khaparde 3853f1f3ee1bSAjit Khaparde err: 3854f1f3ee1bSAjit Khaparde spin_unlock_bh(&adapter->mcc_lock); 3855f1f3ee1bSAjit Khaparde return status; 3856f1f3ee1bSAjit Khaparde } 3857f1f3ee1bSAjit Khaparde 3858f1f3ee1bSAjit Khaparde /* Get Hyper switch config */ 3859f1f3ee1bSAjit Khaparde int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, 3860e7bcbd7bSKalesh AP u32 domain, u16 intf_id, u8 *mode, bool *spoofchk) 3861f1f3ee1bSAjit Khaparde { 3862f1f3ee1bSAjit Khaparde struct be_mcc_wrb *wrb; 3863f1f3ee1bSAjit Khaparde struct be_cmd_req_get_hsw_config *req; 3864f1f3ee1bSAjit Khaparde void *ctxt; 3865f1f3ee1bSAjit Khaparde int status; 3866f1f3ee1bSAjit Khaparde u16 vid; 3867f1f3ee1bSAjit Khaparde 3868f1f3ee1bSAjit Khaparde spin_lock_bh(&adapter->mcc_lock); 3869f1f3ee1bSAjit Khaparde 3870f1f3ee1bSAjit Khaparde wrb = wrb_from_mccq(adapter); 3871f1f3ee1bSAjit Khaparde if (!wrb) { 3872f1f3ee1bSAjit Khaparde status = -EBUSY; 3873f1f3ee1bSAjit Khaparde goto err; 3874f1f3ee1bSAjit Khaparde } 3875f1f3ee1bSAjit Khaparde 3876f1f3ee1bSAjit Khaparde req = embedded_payload(wrb); 3877f1f3ee1bSAjit Khaparde ctxt = &req->context; 3878f1f3ee1bSAjit Khaparde 3879f1f3ee1bSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 3880a2cc4e0bSSathya Perla OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb, 3881a2cc4e0bSSathya Perla NULL); 3882f1f3ee1bSAjit Khaparde 3883f1f3ee1bSAjit Khaparde req->hdr.domain = domain; 3884a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, 3885a77dcb8cSAjit Khaparde ctxt, intf_id); 3886f1f3ee1bSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1); 3887a77dcb8cSAjit Khaparde 38882c07c1d7SVasundhara Volam if (!BEx_chip(adapter) && mode) { 3889a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, 3890a77dcb8cSAjit Khaparde ctxt, adapter->hba_port_num); 3891a77dcb8cSAjit Khaparde AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1); 3892a77dcb8cSAjit Khaparde } 3893f1f3ee1bSAjit Khaparde be_dws_cpu_to_le(req->context, sizeof(req->context)); 3894f1f3ee1bSAjit Khaparde 3895f1f3ee1bSAjit Khaparde status = be_mcc_notify_wait(adapter); 3896f1f3ee1bSAjit Khaparde if (!status) { 3897f1f3ee1bSAjit Khaparde struct be_cmd_resp_get_hsw_config *resp = 3898f1f3ee1bSAjit Khaparde embedded_payload(wrb); 389903d28ffeSKalesh AP 3900a2cc4e0bSSathya Perla be_dws_le_to_cpu(&resp->context, sizeof(resp->context)); 3901f1f3ee1bSAjit Khaparde vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3902f1f3ee1bSAjit Khaparde pvid, &resp->context); 3903a77dcb8cSAjit Khaparde if (pvid) 3904f1f3ee1bSAjit Khaparde *pvid = le16_to_cpu(vid); 3905a77dcb8cSAjit Khaparde if (mode) 3906a77dcb8cSAjit Khaparde *mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3907a77dcb8cSAjit Khaparde port_fwd_type, &resp->context); 3908e7bcbd7bSKalesh AP if (spoofchk) 3909e7bcbd7bSKalesh AP *spoofchk = 3910e7bcbd7bSKalesh AP AMAP_GET_BITS(struct amap_get_hsw_resp_context, 3911e7bcbd7bSKalesh AP spoofchk, &resp->context); 3912f1f3ee1bSAjit Khaparde } 3913f1f3ee1bSAjit Khaparde 3914f1f3ee1bSAjit Khaparde err: 3915f1f3ee1bSAjit Khaparde spin_unlock_bh(&adapter->mcc_lock); 3916f1f3ee1bSAjit Khaparde return status; 3917f1f3ee1bSAjit Khaparde } 3918f1f3ee1bSAjit Khaparde 3919f7062ee5SSathya Perla static bool be_is_wol_excluded(struct be_adapter *adapter) 3920f7062ee5SSathya Perla { 3921f7062ee5SSathya Perla struct pci_dev *pdev = adapter->pdev; 3922f7062ee5SSathya Perla 392318c57c74SKalesh AP if (be_virtfn(adapter)) 3924f7062ee5SSathya Perla return true; 3925f7062ee5SSathya Perla 3926f7062ee5SSathya Perla switch (pdev->subsystem_device) { 3927f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID1: 3928f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID2: 3929f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID3: 3930f7062ee5SSathya Perla case OC_SUBSYS_DEVICE_ID4: 3931f7062ee5SSathya Perla return true; 3932f7062ee5SSathya Perla default: 3933f7062ee5SSathya Perla return false; 3934f7062ee5SSathya Perla } 3935f7062ee5SSathya Perla } 3936f7062ee5SSathya Perla 39374762f6ceSAjit Khaparde int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) 39384762f6ceSAjit Khaparde { 39394762f6ceSAjit Khaparde struct be_mcc_wrb *wrb; 39404762f6ceSAjit Khaparde struct be_cmd_req_acpi_wol_magic_config_v1 *req; 394176a9e08eSSuresh Reddy int status = 0; 39424762f6ceSAjit Khaparde struct be_dma_mem cmd; 39434762f6ceSAjit Khaparde 3944f25b119cSPadmanabh Ratnakar if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, 3945f25b119cSPadmanabh Ratnakar CMD_SUBSYSTEM_ETH)) 3946f25b119cSPadmanabh Ratnakar return -EPERM; 3947f25b119cSPadmanabh Ratnakar 394876a9e08eSSuresh Reddy if (be_is_wol_excluded(adapter)) 394976a9e08eSSuresh Reddy return status; 395076a9e08eSSuresh Reddy 3951d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 3952d98ef50fSSuresh Reddy return -1; 3953d98ef50fSSuresh Reddy 39544762f6ceSAjit Khaparde memset(&cmd, 0, sizeof(struct be_dma_mem)); 39554762f6ceSAjit Khaparde cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); 3956e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 3957e51000dbSSriharsha Basavapatna GFP_ATOMIC); 39584762f6ceSAjit Khaparde if (!cmd.va) { 3959a2cc4e0bSSathya Perla dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); 3960d98ef50fSSuresh Reddy status = -ENOMEM; 3961d98ef50fSSuresh Reddy goto err; 39624762f6ceSAjit Khaparde } 39634762f6ceSAjit Khaparde 39644762f6ceSAjit Khaparde wrb = wrb_from_mbox(adapter); 39654762f6ceSAjit Khaparde if (!wrb) { 39664762f6ceSAjit Khaparde status = -EBUSY; 39674762f6ceSAjit Khaparde goto err; 39684762f6ceSAjit Khaparde } 39694762f6ceSAjit Khaparde 39704762f6ceSAjit Khaparde req = cmd.va; 39714762f6ceSAjit Khaparde 39724762f6ceSAjit Khaparde be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, 39734762f6ceSAjit Khaparde OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, 397476a9e08eSSuresh Reddy sizeof(*req), wrb, &cmd); 39754762f6ceSAjit Khaparde 39764762f6ceSAjit Khaparde req->hdr.version = 1; 39774762f6ceSAjit Khaparde req->query_options = BE_GET_WOL_CAP; 39784762f6ceSAjit Khaparde 39794762f6ceSAjit Khaparde status = be_mbox_notify_wait(adapter); 39804762f6ceSAjit Khaparde if (!status) { 39814762f6ceSAjit Khaparde struct be_cmd_resp_acpi_wol_magic_config_v1 *resp; 398203d28ffeSKalesh AP 39834762f6ceSAjit Khaparde resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va; 39844762f6ceSAjit Khaparde 39854762f6ceSAjit Khaparde adapter->wol_cap = resp->wol_settings; 398676a9e08eSSuresh Reddy if (adapter->wol_cap & BE_WOL_CAP) 398776a9e08eSSuresh Reddy adapter->wol_en = true; 39884762f6ceSAjit Khaparde } 39894762f6ceSAjit Khaparde err: 39904762f6ceSAjit Khaparde mutex_unlock(&adapter->mbox_lock); 3991d98ef50fSSuresh Reddy if (cmd.va) 3992e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, 3993e51000dbSSriharsha Basavapatna cmd.dma); 39944762f6ceSAjit Khaparde return status; 3995941a77d5SSomnath Kotur 3996941a77d5SSomnath Kotur } 3997baaa08d1SVasundhara Volam 3998baaa08d1SVasundhara Volam int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level) 3999baaa08d1SVasundhara Volam { 4000baaa08d1SVasundhara Volam struct be_dma_mem extfat_cmd; 4001baaa08d1SVasundhara Volam struct be_fat_conf_params *cfgs; 4002baaa08d1SVasundhara Volam int status; 4003baaa08d1SVasundhara Volam int i, j; 4004baaa08d1SVasundhara Volam 4005baaa08d1SVasundhara Volam memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); 4006baaa08d1SVasundhara Volam extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); 4007e51000dbSSriharsha Basavapatna extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 4008e51000dbSSriharsha Basavapatna extfat_cmd.size, &extfat_cmd.dma, 4009e51000dbSSriharsha Basavapatna GFP_ATOMIC); 4010baaa08d1SVasundhara Volam if (!extfat_cmd.va) 4011baaa08d1SVasundhara Volam return -ENOMEM; 4012baaa08d1SVasundhara Volam 4013baaa08d1SVasundhara Volam status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd); 4014baaa08d1SVasundhara Volam if (status) 4015baaa08d1SVasundhara Volam goto err; 4016baaa08d1SVasundhara Volam 4017baaa08d1SVasundhara Volam cfgs = (struct be_fat_conf_params *) 4018baaa08d1SVasundhara Volam (extfat_cmd.va + sizeof(struct be_cmd_resp_hdr)); 4019baaa08d1SVasundhara Volam for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) { 4020baaa08d1SVasundhara Volam u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes); 402103d28ffeSKalesh AP 4022baaa08d1SVasundhara Volam for (j = 0; j < num_modes; j++) { 4023baaa08d1SVasundhara Volam if (cfgs->module[i].trace_lvl[j].mode == MODE_UART) 4024baaa08d1SVasundhara Volam cfgs->module[i].trace_lvl[j].dbg_lvl = 4025baaa08d1SVasundhara Volam cpu_to_le32(level); 4026baaa08d1SVasundhara Volam } 4027baaa08d1SVasundhara Volam } 4028baaa08d1SVasundhara Volam 4029baaa08d1SVasundhara Volam status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd, cfgs); 4030baaa08d1SVasundhara Volam err: 4031e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va, 4032baaa08d1SVasundhara Volam extfat_cmd.dma); 4033baaa08d1SVasundhara Volam return status; 4034baaa08d1SVasundhara Volam } 4035baaa08d1SVasundhara Volam 4036baaa08d1SVasundhara Volam int be_cmd_get_fw_log_level(struct be_adapter *adapter) 4037baaa08d1SVasundhara Volam { 4038baaa08d1SVasundhara Volam struct be_dma_mem extfat_cmd; 4039baaa08d1SVasundhara Volam struct be_fat_conf_params *cfgs; 4040baaa08d1SVasundhara Volam int status, j; 4041baaa08d1SVasundhara Volam int level = 0; 4042baaa08d1SVasundhara Volam 4043baaa08d1SVasundhara Volam memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); 4044baaa08d1SVasundhara Volam extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); 4045e51000dbSSriharsha Basavapatna extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, 4046e51000dbSSriharsha Basavapatna extfat_cmd.size, &extfat_cmd.dma, 4047e51000dbSSriharsha Basavapatna GFP_ATOMIC); 4048baaa08d1SVasundhara Volam 4049baaa08d1SVasundhara Volam if (!extfat_cmd.va) { 4050baaa08d1SVasundhara Volam dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n", 4051baaa08d1SVasundhara Volam __func__); 4052baaa08d1SVasundhara Volam goto err; 4053baaa08d1SVasundhara Volam } 4054baaa08d1SVasundhara Volam 4055baaa08d1SVasundhara Volam status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd); 4056baaa08d1SVasundhara Volam if (!status) { 4057baaa08d1SVasundhara Volam cfgs = (struct be_fat_conf_params *)(extfat_cmd.va + 4058baaa08d1SVasundhara Volam sizeof(struct be_cmd_resp_hdr)); 405903d28ffeSKalesh AP 4060baaa08d1SVasundhara Volam for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) { 4061baaa08d1SVasundhara Volam if (cfgs->module[0].trace_lvl[j].mode == MODE_UART) 4062baaa08d1SVasundhara Volam level = cfgs->module[0].trace_lvl[j].dbg_lvl; 4063baaa08d1SVasundhara Volam } 4064baaa08d1SVasundhara Volam } 4065e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, extfat_cmd.size, extfat_cmd.va, 4066baaa08d1SVasundhara Volam extfat_cmd.dma); 4067baaa08d1SVasundhara Volam err: 4068baaa08d1SVasundhara Volam return level; 4069baaa08d1SVasundhara Volam } 4070baaa08d1SVasundhara Volam 4071941a77d5SSomnath Kotur int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter, 4072941a77d5SSomnath Kotur struct be_dma_mem *cmd) 4073941a77d5SSomnath Kotur { 4074941a77d5SSomnath Kotur struct be_mcc_wrb *wrb; 4075941a77d5SSomnath Kotur struct be_cmd_req_get_ext_fat_caps *req; 4076941a77d5SSomnath Kotur int status; 4077941a77d5SSomnath Kotur 4078941a77d5SSomnath Kotur if (mutex_lock_interruptible(&adapter->mbox_lock)) 4079941a77d5SSomnath Kotur return -1; 4080941a77d5SSomnath Kotur 4081941a77d5SSomnath Kotur wrb = wrb_from_mbox(adapter); 4082941a77d5SSomnath Kotur if (!wrb) { 4083941a77d5SSomnath Kotur status = -EBUSY; 4084941a77d5SSomnath Kotur goto err; 4085941a77d5SSomnath Kotur } 4086941a77d5SSomnath Kotur 4087941a77d5SSomnath Kotur req = cmd->va; 4088941a77d5SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4089941a77d5SSomnath Kotur OPCODE_COMMON_GET_EXT_FAT_CAPABILITES, 4090941a77d5SSomnath Kotur cmd->size, wrb, cmd); 4091941a77d5SSomnath Kotur req->parameter_type = cpu_to_le32(1); 4092941a77d5SSomnath Kotur 4093941a77d5SSomnath Kotur status = be_mbox_notify_wait(adapter); 4094941a77d5SSomnath Kotur err: 4095941a77d5SSomnath Kotur mutex_unlock(&adapter->mbox_lock); 4096941a77d5SSomnath Kotur return status; 4097941a77d5SSomnath Kotur } 4098941a77d5SSomnath Kotur 4099941a77d5SSomnath Kotur int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, 4100941a77d5SSomnath Kotur struct be_dma_mem *cmd, 4101941a77d5SSomnath Kotur struct be_fat_conf_params *configs) 4102941a77d5SSomnath Kotur { 4103941a77d5SSomnath Kotur struct be_mcc_wrb *wrb; 4104941a77d5SSomnath Kotur struct be_cmd_req_set_ext_fat_caps *req; 4105941a77d5SSomnath Kotur int status; 4106941a77d5SSomnath Kotur 4107941a77d5SSomnath Kotur spin_lock_bh(&adapter->mcc_lock); 4108941a77d5SSomnath Kotur 4109941a77d5SSomnath Kotur wrb = wrb_from_mccq(adapter); 4110941a77d5SSomnath Kotur if (!wrb) { 4111941a77d5SSomnath Kotur status = -EBUSY; 4112941a77d5SSomnath Kotur goto err; 4113941a77d5SSomnath Kotur } 4114941a77d5SSomnath Kotur 4115941a77d5SSomnath Kotur req = cmd->va; 4116941a77d5SSomnath Kotur memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params)); 4117941a77d5SSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4118941a77d5SSomnath Kotur OPCODE_COMMON_SET_EXT_FAT_CAPABILITES, 4119941a77d5SSomnath Kotur cmd->size, wrb, cmd); 4120941a77d5SSomnath Kotur 4121941a77d5SSomnath Kotur status = be_mcc_notify_wait(adapter); 4122941a77d5SSomnath Kotur err: 4123941a77d5SSomnath Kotur spin_unlock_bh(&adapter->mcc_lock); 4124941a77d5SSomnath Kotur return status; 41254762f6ceSAjit Khaparde } 41266a4ab669SParav Pandit 412721252377SVasundhara Volam int be_cmd_query_port_name(struct be_adapter *adapter) 4128b4e32a71SPadmanabh Ratnakar { 4129b4e32a71SPadmanabh Ratnakar struct be_cmd_req_get_port_name *req; 413021252377SVasundhara Volam struct be_mcc_wrb *wrb; 4131b4e32a71SPadmanabh Ratnakar int status; 4132b4e32a71SPadmanabh Ratnakar 413321252377SVasundhara Volam if (mutex_lock_interruptible(&adapter->mbox_lock)) 413421252377SVasundhara Volam return -1; 4135b4e32a71SPadmanabh Ratnakar 413621252377SVasundhara Volam wrb = wrb_from_mbox(adapter); 4137b4e32a71SPadmanabh Ratnakar req = embedded_payload(wrb); 4138b4e32a71SPadmanabh Ratnakar 4139b4e32a71SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4140b4e32a71SPadmanabh Ratnakar OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb, 4141b4e32a71SPadmanabh Ratnakar NULL); 414221252377SVasundhara Volam if (!BEx_chip(adapter)) 4143b4e32a71SPadmanabh Ratnakar req->hdr.version = 1; 4144b4e32a71SPadmanabh Ratnakar 414521252377SVasundhara Volam status = be_mbox_notify_wait(adapter); 4146b4e32a71SPadmanabh Ratnakar if (!status) { 4147b4e32a71SPadmanabh Ratnakar struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb); 414803d28ffeSKalesh AP 414921252377SVasundhara Volam adapter->port_name = resp->port_name[adapter->hba_port_num]; 4150b4e32a71SPadmanabh Ratnakar } else { 415121252377SVasundhara Volam adapter->port_name = adapter->hba_port_num + '0'; 4152b4e32a71SPadmanabh Ratnakar } 415321252377SVasundhara Volam 415421252377SVasundhara Volam mutex_unlock(&adapter->mbox_lock); 4155b4e32a71SPadmanabh Ratnakar return status; 4156b4e32a71SPadmanabh Ratnakar } 4157b4e32a71SPadmanabh Ratnakar 4158980df249SSuresh Reddy /* When more than 1 NIC descriptor is present in the descriptor list, 4159980df249SSuresh Reddy * the caller must specify the pf_num to obtain the NIC descriptor 4160980df249SSuresh Reddy * corresponding to its pci function. 4161980df249SSuresh Reddy * get_vft must be true when the caller wants the VF-template desc of the 4162980df249SSuresh Reddy * PF-pool. 4163980df249SSuresh Reddy * The pf_num should be set to PF_NUM_IGNORE when the caller knows 4164980df249SSuresh Reddy * that only it's NIC descriptor is present in the descriptor list. 4165980df249SSuresh Reddy */ 416610cccf60SVasundhara Volam static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count, 4167980df249SSuresh Reddy bool get_vft, u8 pf_num) 4168abb93951SPadmanabh Ratnakar { 4169150d58c7SVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 417010cccf60SVasundhara Volam struct be_nic_res_desc *nic; 4171abb93951SPadmanabh Ratnakar int i; 4172abb93951SPadmanabh Ratnakar 4173abb93951SPadmanabh Ratnakar for (i = 0; i < desc_count; i++) { 4174150d58c7SVasundhara Volam if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 || 417510cccf60SVasundhara Volam hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) { 417610cccf60SVasundhara Volam nic = (struct be_nic_res_desc *)hdr; 4177980df249SSuresh Reddy 4178980df249SSuresh Reddy if ((pf_num == PF_NUM_IGNORE || 4179980df249SSuresh Reddy nic->pf_num == pf_num) && 4180980df249SSuresh Reddy (!get_vft || nic->flags & BIT(VFT_SHIFT))) 418110cccf60SVasundhara Volam return nic; 418210cccf60SVasundhara Volam } 4183150d58c7SVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 4184150d58c7SVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 4185150d58c7SVasundhara Volam } 4186950e2958SWei Yang return NULL; 4187abb93951SPadmanabh Ratnakar } 4188abb93951SPadmanabh Ratnakar 4189980df249SSuresh Reddy static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count, 4190980df249SSuresh Reddy u8 pf_num) 419110cccf60SVasundhara Volam { 4192980df249SSuresh Reddy return be_get_nic_desc(buf, desc_count, true, pf_num); 419310cccf60SVasundhara Volam } 419410cccf60SVasundhara Volam 4195980df249SSuresh Reddy static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count, 4196980df249SSuresh Reddy u8 pf_num) 419710cccf60SVasundhara Volam { 4198980df249SSuresh Reddy return be_get_nic_desc(buf, desc_count, false, pf_num); 419910cccf60SVasundhara Volam } 420010cccf60SVasundhara Volam 4201980df249SSuresh Reddy static struct be_pcie_res_desc *be_get_pcie_desc(u8 *buf, u32 desc_count, 4202980df249SSuresh Reddy u8 pf_num) 4203150d58c7SVasundhara Volam { 4204150d58c7SVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 4205150d58c7SVasundhara Volam struct be_pcie_res_desc *pcie; 4206150d58c7SVasundhara Volam int i; 4207150d58c7SVasundhara Volam 4208150d58c7SVasundhara Volam for (i = 0; i < desc_count; i++) { 4209980df249SSuresh Reddy if (hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 || 4210980df249SSuresh Reddy hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1) { 4211150d58c7SVasundhara Volam pcie = (struct be_pcie_res_desc *)hdr; 4212980df249SSuresh Reddy if (pcie->pf_num == pf_num) 4213150d58c7SVasundhara Volam return pcie; 4214150d58c7SVasundhara Volam } 4215150d58c7SVasundhara Volam 4216150d58c7SVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 4217150d58c7SVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 4218150d58c7SVasundhara Volam } 4219abb93951SPadmanabh Ratnakar return NULL; 4220abb93951SPadmanabh Ratnakar } 4221abb93951SPadmanabh Ratnakar 4222f93f160bSVasundhara Volam static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count) 4223f93f160bSVasundhara Volam { 4224f93f160bSVasundhara Volam struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; 4225f93f160bSVasundhara Volam int i; 4226f93f160bSVasundhara Volam 4227f93f160bSVasundhara Volam for (i = 0; i < desc_count; i++) { 4228f93f160bSVasundhara Volam if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1) 4229f93f160bSVasundhara Volam return (struct be_port_res_desc *)hdr; 4230f93f160bSVasundhara Volam 4231f93f160bSVasundhara Volam hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; 4232f93f160bSVasundhara Volam hdr = (void *)hdr + hdr->desc_len; 4233f93f160bSVasundhara Volam } 4234f93f160bSVasundhara Volam return NULL; 4235f93f160bSVasundhara Volam } 4236f93f160bSVasundhara Volam 423792bf14abSSathya Perla static void be_copy_nic_desc(struct be_resources *res, 423892bf14abSSathya Perla struct be_nic_res_desc *desc) 423992bf14abSSathya Perla { 424092bf14abSSathya Perla res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count); 424192bf14abSSathya Perla res->max_vlans = le16_to_cpu(desc->vlan_count); 424292bf14abSSathya Perla res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count); 424392bf14abSSathya Perla res->max_tx_qs = le16_to_cpu(desc->txq_count); 424492bf14abSSathya Perla res->max_rss_qs = le16_to_cpu(desc->rssq_count); 424592bf14abSSathya Perla res->max_rx_qs = le16_to_cpu(desc->rq_count); 424692bf14abSSathya Perla res->max_evt_qs = le16_to_cpu(desc->eq_count); 4247f2858738SVasundhara Volam res->max_cq_count = le16_to_cpu(desc->cq_count); 4248f2858738SVasundhara Volam res->max_iface_count = le16_to_cpu(desc->iface_count); 4249f2858738SVasundhara Volam res->max_mcc_count = le16_to_cpu(desc->mcc_count); 425092bf14abSSathya Perla /* Clear flags that driver is not interested in */ 425192bf14abSSathya Perla res->if_cap_flags = le32_to_cpu(desc->cap_flags) & 425292bf14abSSathya Perla BE_IF_CAP_FLAGS_WANT; 425392bf14abSSathya Perla } 425492bf14abSSathya Perla 4255abb93951SPadmanabh Ratnakar /* Uses Mbox */ 425692bf14abSSathya Perla int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) 4257abb93951SPadmanabh Ratnakar { 4258abb93951SPadmanabh Ratnakar struct be_mcc_wrb *wrb; 4259abb93951SPadmanabh Ratnakar struct be_cmd_req_get_func_config *req; 4260abb93951SPadmanabh Ratnakar int status; 4261abb93951SPadmanabh Ratnakar struct be_dma_mem cmd; 4262abb93951SPadmanabh Ratnakar 4263d98ef50fSSuresh Reddy if (mutex_lock_interruptible(&adapter->mbox_lock)) 4264d98ef50fSSuresh Reddy return -1; 4265d98ef50fSSuresh Reddy 4266abb93951SPadmanabh Ratnakar memset(&cmd, 0, sizeof(struct be_dma_mem)); 4267abb93951SPadmanabh Ratnakar cmd.size = sizeof(struct be_cmd_resp_get_func_config); 4268e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 4269e51000dbSSriharsha Basavapatna GFP_ATOMIC); 4270abb93951SPadmanabh Ratnakar if (!cmd.va) { 4271abb93951SPadmanabh Ratnakar dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); 4272d98ef50fSSuresh Reddy status = -ENOMEM; 4273d98ef50fSSuresh Reddy goto err; 4274abb93951SPadmanabh Ratnakar } 4275abb93951SPadmanabh Ratnakar 4276abb93951SPadmanabh Ratnakar wrb = wrb_from_mbox(adapter); 4277abb93951SPadmanabh Ratnakar if (!wrb) { 4278abb93951SPadmanabh Ratnakar status = -EBUSY; 4279abb93951SPadmanabh Ratnakar goto err; 4280abb93951SPadmanabh Ratnakar } 4281abb93951SPadmanabh Ratnakar 4282abb93951SPadmanabh Ratnakar req = cmd.va; 4283abb93951SPadmanabh Ratnakar 4284abb93951SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4285abb93951SPadmanabh Ratnakar OPCODE_COMMON_GET_FUNC_CONFIG, 4286abb93951SPadmanabh Ratnakar cmd.size, wrb, &cmd); 4287abb93951SPadmanabh Ratnakar 428828710c55SKalesh AP if (skyhawk_chip(adapter)) 428928710c55SKalesh AP req->hdr.version = 1; 429028710c55SKalesh AP 4291abb93951SPadmanabh Ratnakar status = be_mbox_notify_wait(adapter); 4292abb93951SPadmanabh Ratnakar if (!status) { 4293abb93951SPadmanabh Ratnakar struct be_cmd_resp_get_func_config *resp = cmd.va; 4294abb93951SPadmanabh Ratnakar u32 desc_count = le32_to_cpu(resp->desc_count); 4295150d58c7SVasundhara Volam struct be_nic_res_desc *desc; 4296abb93951SPadmanabh Ratnakar 4297980df249SSuresh Reddy /* GET_FUNC_CONFIG returns resource descriptors of the 4298980df249SSuresh Reddy * current function only. So, pf_num should be set to 4299980df249SSuresh Reddy * PF_NUM_IGNORE. 4300980df249SSuresh Reddy */ 4301980df249SSuresh Reddy desc = be_get_func_nic_desc(resp->func_param, desc_count, 4302980df249SSuresh Reddy PF_NUM_IGNORE); 4303abb93951SPadmanabh Ratnakar if (!desc) { 4304abb93951SPadmanabh Ratnakar status = -EINVAL; 4305abb93951SPadmanabh Ratnakar goto err; 4306abb93951SPadmanabh Ratnakar } 4307980df249SSuresh Reddy 4308980df249SSuresh Reddy /* Store pf_num & vf_num for later use in GET_PROFILE_CONFIG */ 4309980df249SSuresh Reddy adapter->pf_num = desc->pf_num; 4310980df249SSuresh Reddy adapter->vf_num = desc->vf_num; 4311980df249SSuresh Reddy 4312980df249SSuresh Reddy if (res) 431392bf14abSSathya Perla be_copy_nic_desc(res, desc); 4314abb93951SPadmanabh Ratnakar } 4315abb93951SPadmanabh Ratnakar err: 4316abb93951SPadmanabh Ratnakar mutex_unlock(&adapter->mbox_lock); 4317d98ef50fSSuresh Reddy if (cmd.va) 4318e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, 4319e51000dbSSriharsha Basavapatna cmd.dma); 4320abb93951SPadmanabh Ratnakar return status; 4321abb93951SPadmanabh Ratnakar } 4322abb93951SPadmanabh Ratnakar 4323980df249SSuresh Reddy /* Will use MBOX only if MCCQ has not been created */ 432492bf14abSSathya Perla int be_cmd_get_profile_config(struct be_adapter *adapter, 4325f2858738SVasundhara Volam struct be_resources *res, u8 query, u8 domain) 4326a05f99dbSVasundhara Volam { 4327150d58c7SVasundhara Volam struct be_cmd_resp_get_profile_config *resp; 4328ba48c0c9SVasundhara Volam struct be_cmd_req_get_profile_config *req; 432910cccf60SVasundhara Volam struct be_nic_res_desc *vf_res; 4330150d58c7SVasundhara Volam struct be_pcie_res_desc *pcie; 4331f93f160bSVasundhara Volam struct be_port_res_desc *port; 4332150d58c7SVasundhara Volam struct be_nic_res_desc *nic; 4333ba48c0c9SVasundhara Volam struct be_mcc_wrb wrb = {0}; 4334a05f99dbSVasundhara Volam struct be_dma_mem cmd; 4335f2858738SVasundhara Volam u16 desc_count; 4336a05f99dbSVasundhara Volam int status; 4337a05f99dbSVasundhara Volam 4338a05f99dbSVasundhara Volam memset(&cmd, 0, sizeof(struct be_dma_mem)); 4339a05f99dbSVasundhara Volam cmd.size = sizeof(struct be_cmd_resp_get_profile_config); 4340e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 4341e51000dbSSriharsha Basavapatna GFP_ATOMIC); 4342150d58c7SVasundhara Volam if (!cmd.va) 4343a05f99dbSVasundhara Volam return -ENOMEM; 4344a05f99dbSVasundhara Volam 4345ba48c0c9SVasundhara Volam req = cmd.va; 4346ba48c0c9SVasundhara Volam be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4347ba48c0c9SVasundhara Volam OPCODE_COMMON_GET_PROFILE_CONFIG, 4348ba48c0c9SVasundhara Volam cmd.size, &wrb, &cmd); 4349ba48c0c9SVasundhara Volam 4350ba48c0c9SVasundhara Volam if (!lancer_chip(adapter)) 4351ba48c0c9SVasundhara Volam req->hdr.version = 1; 4352ba48c0c9SVasundhara Volam req->type = ACTIVE_PROFILE_TYPE; 435372ef3a88SSomnath Kotur req->hdr.domain = domain; 4354ba48c0c9SVasundhara Volam 4355f2858738SVasundhara Volam /* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the 4356f2858738SVasundhara Volam * descriptors with all bits set to "1" for the fields which can be 4357f2858738SVasundhara Volam * modified using SET_PROFILE_CONFIG cmd. 4358f2858738SVasundhara Volam */ 4359f2858738SVasundhara Volam if (query == RESOURCE_MODIFIABLE) 4360f2858738SVasundhara Volam req->type |= QUERY_MODIFIABLE_FIELDS_TYPE; 4361f2858738SVasundhara Volam 4362ba48c0c9SVasundhara Volam status = be_cmd_notify_wait(adapter, &wrb); 4363150d58c7SVasundhara Volam if (status) 4364abb93951SPadmanabh Ratnakar goto err; 4365150d58c7SVasundhara Volam 4366150d58c7SVasundhara Volam resp = cmd.va; 4367f2858738SVasundhara Volam desc_count = le16_to_cpu(resp->desc_count); 4368150d58c7SVasundhara Volam 4369980df249SSuresh Reddy pcie = be_get_pcie_desc(resp->func_param, desc_count, 4370980df249SSuresh Reddy adapter->pf_num); 4371150d58c7SVasundhara Volam if (pcie) 437292bf14abSSathya Perla res->max_vfs = le16_to_cpu(pcie->num_vfs); 4373150d58c7SVasundhara Volam 4374f93f160bSVasundhara Volam port = be_get_port_desc(resp->func_param, desc_count); 4375f93f160bSVasundhara Volam if (port) 4376f93f160bSVasundhara Volam adapter->mc_type = port->mc_type; 4377f93f160bSVasundhara Volam 4378980df249SSuresh Reddy nic = be_get_func_nic_desc(resp->func_param, desc_count, 4379980df249SSuresh Reddy adapter->pf_num); 438092bf14abSSathya Perla if (nic) 438192bf14abSSathya Perla be_copy_nic_desc(res, nic); 438292bf14abSSathya Perla 4383980df249SSuresh Reddy vf_res = be_get_vft_desc(resp->func_param, desc_count, 4384980df249SSuresh Reddy adapter->pf_num); 438510cccf60SVasundhara Volam if (vf_res) 438610cccf60SVasundhara Volam res->vf_if_cap_flags = vf_res->cap_flags; 4387abb93951SPadmanabh Ratnakar err: 4388a05f99dbSVasundhara Volam if (cmd.va) 4389e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, 4390e51000dbSSriharsha Basavapatna cmd.dma); 4391abb93951SPadmanabh Ratnakar return status; 4392abb93951SPadmanabh Ratnakar } 4393abb93951SPadmanabh Ratnakar 4394bec84e6bSVasundhara Volam /* Will use MBOX only if MCCQ has not been created */ 4395bec84e6bSVasundhara Volam static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc, 4396bec84e6bSVasundhara Volam int size, int count, u8 version, u8 domain) 4397d5c18473SPadmanabh Ratnakar { 4398d5c18473SPadmanabh Ratnakar struct be_cmd_req_set_profile_config *req; 4399bec84e6bSVasundhara Volam struct be_mcc_wrb wrb = {0}; 4400bec84e6bSVasundhara Volam struct be_dma_mem cmd; 4401d5c18473SPadmanabh Ratnakar int status; 4402d5c18473SPadmanabh Ratnakar 4403bec84e6bSVasundhara Volam memset(&cmd, 0, sizeof(struct be_dma_mem)); 4404bec84e6bSVasundhara Volam cmd.size = sizeof(struct be_cmd_req_set_profile_config); 4405e51000dbSSriharsha Basavapatna cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, 4406e51000dbSSriharsha Basavapatna GFP_ATOMIC); 4407bec84e6bSVasundhara Volam if (!cmd.va) 4408bec84e6bSVasundhara Volam return -ENOMEM; 4409d5c18473SPadmanabh Ratnakar 4410bec84e6bSVasundhara Volam req = cmd.va; 4411d5c18473SPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4412bec84e6bSVasundhara Volam OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size, 4413bec84e6bSVasundhara Volam &wrb, &cmd); 4414a401801cSSathya Perla req->hdr.version = version; 4415d5c18473SPadmanabh Ratnakar req->hdr.domain = domain; 4416bec84e6bSVasundhara Volam req->desc_count = cpu_to_le32(count); 4417a401801cSSathya Perla memcpy(req->desc, desc, size); 4418d5c18473SPadmanabh Ratnakar 4419bec84e6bSVasundhara Volam status = be_cmd_notify_wait(adapter, &wrb); 4420bec84e6bSVasundhara Volam 4421bec84e6bSVasundhara Volam if (cmd.va) 4422e51000dbSSriharsha Basavapatna dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, 4423e51000dbSSriharsha Basavapatna cmd.dma); 4424d5c18473SPadmanabh Ratnakar return status; 4425d5c18473SPadmanabh Ratnakar } 4426d5c18473SPadmanabh Ratnakar 4427a401801cSSathya Perla /* Mark all fields invalid */ 4428bec84e6bSVasundhara Volam static void be_reset_nic_desc(struct be_nic_res_desc *nic) 4429a401801cSSathya Perla { 4430a401801cSSathya Perla memset(nic, 0, sizeof(*nic)); 4431a401801cSSathya Perla nic->unicast_mac_count = 0xFFFF; 4432a401801cSSathya Perla nic->mcc_count = 0xFFFF; 4433a401801cSSathya Perla nic->vlan_count = 0xFFFF; 4434a401801cSSathya Perla nic->mcast_mac_count = 0xFFFF; 4435a401801cSSathya Perla nic->txq_count = 0xFFFF; 4436a401801cSSathya Perla nic->rq_count = 0xFFFF; 4437a401801cSSathya Perla nic->rssq_count = 0xFFFF; 4438a401801cSSathya Perla nic->lro_count = 0xFFFF; 4439a401801cSSathya Perla nic->cq_count = 0xFFFF; 4440a401801cSSathya Perla nic->toe_conn_count = 0xFFFF; 4441a401801cSSathya Perla nic->eq_count = 0xFFFF; 44420f77ba73SRavikumar Nelavelli nic->iface_count = 0xFFFF; 4443a401801cSSathya Perla nic->link_param = 0xFF; 44440f77ba73SRavikumar Nelavelli nic->channel_id_param = cpu_to_le16(0xF000); 4445a401801cSSathya Perla nic->acpi_params = 0xFF; 4446a401801cSSathya Perla nic->wol_param = 0x0F; 44470f77ba73SRavikumar Nelavelli nic->tunnel_iface_count = 0xFFFF; 44480f77ba73SRavikumar Nelavelli nic->direct_tenant_iface_count = 0xFFFF; 4449bec84e6bSVasundhara Volam nic->bw_min = 0xFFFFFFFF; 4450a401801cSSathya Perla nic->bw_max = 0xFFFFFFFF; 4451a401801cSSathya Perla } 4452a401801cSSathya Perla 4453bec84e6bSVasundhara Volam /* Mark all fields invalid */ 4454bec84e6bSVasundhara Volam static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie) 4455bec84e6bSVasundhara Volam { 4456bec84e6bSVasundhara Volam memset(pcie, 0, sizeof(*pcie)); 4457bec84e6bSVasundhara Volam pcie->sriov_state = 0xFF; 4458bec84e6bSVasundhara Volam pcie->pf_state = 0xFF; 4459bec84e6bSVasundhara Volam pcie->pf_type = 0xFF; 4460bec84e6bSVasundhara Volam pcie->num_vfs = 0xFFFF; 4461bec84e6bSVasundhara Volam } 4462bec84e6bSVasundhara Volam 44630f77ba73SRavikumar Nelavelli int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed, 44640f77ba73SRavikumar Nelavelli u8 domain) 4465a401801cSSathya Perla { 4466a401801cSSathya Perla struct be_nic_res_desc nic_desc; 44670f77ba73SRavikumar Nelavelli u32 bw_percent; 44680f77ba73SRavikumar Nelavelli u16 version = 0; 44690f77ba73SRavikumar Nelavelli 44700f77ba73SRavikumar Nelavelli if (BE3_chip(adapter)) 44710f77ba73SRavikumar Nelavelli return be_cmd_set_qos(adapter, max_rate / 10, domain); 4472a401801cSSathya Perla 4473a401801cSSathya Perla be_reset_nic_desc(&nic_desc); 4474980df249SSuresh Reddy nic_desc.pf_num = adapter->pf_num; 44750f77ba73SRavikumar Nelavelli nic_desc.vf_num = domain; 447658bdeaa6SKalesh AP nic_desc.bw_min = 0; 44770f77ba73SRavikumar Nelavelli if (lancer_chip(adapter)) { 4478a401801cSSathya Perla nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0; 4479a401801cSSathya Perla nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0; 4480a401801cSSathya Perla nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) | 4481a401801cSSathya Perla (1 << NOSV_SHIFT); 44820f77ba73SRavikumar Nelavelli nic_desc.bw_max = cpu_to_le32(max_rate / 10); 44830f77ba73SRavikumar Nelavelli } else { 44840f77ba73SRavikumar Nelavelli version = 1; 44850f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1; 44860f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 44870f77ba73SRavikumar Nelavelli nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT); 44880f77ba73SRavikumar Nelavelli bw_percent = max_rate ? (max_rate * 100) / link_speed : 100; 44890f77ba73SRavikumar Nelavelli nic_desc.bw_max = cpu_to_le32(bw_percent); 44900f77ba73SRavikumar Nelavelli } 4491a401801cSSathya Perla 4492a401801cSSathya Perla return be_cmd_set_profile_config(adapter, &nic_desc, 44930f77ba73SRavikumar Nelavelli nic_desc.hdr.desc_len, 4494bec84e6bSVasundhara Volam 1, version, domain); 4495bec84e6bSVasundhara Volam } 4496bec84e6bSVasundhara Volam 4497f2858738SVasundhara Volam static void be_fill_vf_res_template(struct be_adapter *adapter, 4498f2858738SVasundhara Volam struct be_resources pool_res, 4499f2858738SVasundhara Volam u16 num_vfs, u16 num_vf_qs, 4500f2858738SVasundhara Volam struct be_nic_res_desc *nic_vft) 4501f2858738SVasundhara Volam { 4502f2858738SVasundhara Volam u32 vf_if_cap_flags = pool_res.vf_if_cap_flags; 4503f2858738SVasundhara Volam struct be_resources res_mod = {0}; 4504f2858738SVasundhara Volam 4505f2858738SVasundhara Volam /* Resource with fields set to all '1's by GET_PROFILE_CONFIG cmd, 4506f2858738SVasundhara Volam * which are modifiable using SET_PROFILE_CONFIG cmd. 4507f2858738SVasundhara Volam */ 4508f2858738SVasundhara Volam be_cmd_get_profile_config(adapter, &res_mod, RESOURCE_MODIFIABLE, 0); 4509f2858738SVasundhara Volam 4510f2858738SVasundhara Volam /* If RSS IFACE capability flags are modifiable for a VF, set the 4511f2858738SVasundhara Volam * capability flag as valid and set RSS and DEFQ_RSS IFACE flags if 4512f2858738SVasundhara Volam * more than 1 RSSQ is available for a VF. 4513f2858738SVasundhara Volam * Otherwise, provision only 1 queue pair for VF. 4514f2858738SVasundhara Volam */ 4515f2858738SVasundhara Volam if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_RSS) { 4516f2858738SVasundhara Volam nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT); 4517f2858738SVasundhara Volam if (num_vf_qs > 1) { 4518f2858738SVasundhara Volam vf_if_cap_flags |= BE_IF_FLAGS_RSS; 4519f2858738SVasundhara Volam if (pool_res.if_cap_flags & BE_IF_FLAGS_DEFQ_RSS) 4520f2858738SVasundhara Volam vf_if_cap_flags |= BE_IF_FLAGS_DEFQ_RSS; 4521f2858738SVasundhara Volam } else { 4522f2858738SVasundhara Volam vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS | 4523f2858738SVasundhara Volam BE_IF_FLAGS_DEFQ_RSS); 4524f2858738SVasundhara Volam } 4525f2858738SVasundhara Volam } else { 4526f2858738SVasundhara Volam num_vf_qs = 1; 4527f2858738SVasundhara Volam } 4528f2858738SVasundhara Volam 4529196e3735SKalesh AP if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) { 4530196e3735SKalesh AP nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT); 4531196e3735SKalesh AP vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS; 4532196e3735SKalesh AP } 4533196e3735SKalesh AP 4534196e3735SKalesh AP nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags); 4535f2858738SVasundhara Volam nic_vft->rq_count = cpu_to_le16(num_vf_qs); 4536f2858738SVasundhara Volam nic_vft->txq_count = cpu_to_le16(num_vf_qs); 4537f2858738SVasundhara Volam nic_vft->rssq_count = cpu_to_le16(num_vf_qs); 4538f2858738SVasundhara Volam nic_vft->cq_count = cpu_to_le16(pool_res.max_cq_count / 4539f2858738SVasundhara Volam (num_vfs + 1)); 4540f2858738SVasundhara Volam 4541f2858738SVasundhara Volam /* Distribute unicast MACs, VLANs, IFACE count and MCCQ count equally 4542f2858738SVasundhara Volam * among the PF and it's VFs, if the fields are changeable 4543f2858738SVasundhara Volam */ 4544f2858738SVasundhara Volam if (res_mod.max_uc_mac == FIELD_MODIFIABLE) 4545f2858738SVasundhara Volam nic_vft->unicast_mac_count = cpu_to_le16(pool_res.max_uc_mac / 4546f2858738SVasundhara Volam (num_vfs + 1)); 4547f2858738SVasundhara Volam 4548f2858738SVasundhara Volam if (res_mod.max_vlans == FIELD_MODIFIABLE) 4549f2858738SVasundhara Volam nic_vft->vlan_count = cpu_to_le16(pool_res.max_vlans / 4550f2858738SVasundhara Volam (num_vfs + 1)); 4551f2858738SVasundhara Volam 4552f2858738SVasundhara Volam if (res_mod.max_iface_count == FIELD_MODIFIABLE) 4553f2858738SVasundhara Volam nic_vft->iface_count = cpu_to_le16(pool_res.max_iface_count / 4554f2858738SVasundhara Volam (num_vfs + 1)); 4555f2858738SVasundhara Volam 4556f2858738SVasundhara Volam if (res_mod.max_mcc_count == FIELD_MODIFIABLE) 4557f2858738SVasundhara Volam nic_vft->mcc_count = cpu_to_le16(pool_res.max_mcc_count / 4558f2858738SVasundhara Volam (num_vfs + 1)); 4559f2858738SVasundhara Volam } 4560f2858738SVasundhara Volam 4561bec84e6bSVasundhara Volam int be_cmd_set_sriov_config(struct be_adapter *adapter, 4562f2858738SVasundhara Volam struct be_resources pool_res, u16 num_vfs, 4563f2858738SVasundhara Volam u16 num_vf_qs) 4564bec84e6bSVasundhara Volam { 4565bec84e6bSVasundhara Volam struct { 4566bec84e6bSVasundhara Volam struct be_pcie_res_desc pcie; 4567bec84e6bSVasundhara Volam struct be_nic_res_desc nic_vft; 4568bec84e6bSVasundhara Volam } __packed desc; 4569bec84e6bSVasundhara Volam 4570bec84e6bSVasundhara Volam /* PF PCIE descriptor */ 4571bec84e6bSVasundhara Volam be_reset_pcie_desc(&desc.pcie); 4572bec84e6bSVasundhara Volam desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1; 4573bec84e6bSVasundhara Volam desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 4574f2858738SVasundhara Volam desc.pcie.flags = BIT(IMM_SHIFT) | BIT(NOSV_SHIFT); 4575bec84e6bSVasundhara Volam desc.pcie.pf_num = adapter->pdev->devfn; 4576bec84e6bSVasundhara Volam desc.pcie.sriov_state = num_vfs ? 1 : 0; 4577bec84e6bSVasundhara Volam desc.pcie.num_vfs = cpu_to_le16(num_vfs); 4578bec84e6bSVasundhara Volam 4579bec84e6bSVasundhara Volam /* VF NIC Template descriptor */ 4580bec84e6bSVasundhara Volam be_reset_nic_desc(&desc.nic_vft); 4581bec84e6bSVasundhara Volam desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1; 4582bec84e6bSVasundhara Volam desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 4583f2858738SVasundhara Volam desc.nic_vft.flags = BIT(VFT_SHIFT) | BIT(IMM_SHIFT) | BIT(NOSV_SHIFT); 4584bec84e6bSVasundhara Volam desc.nic_vft.pf_num = adapter->pdev->devfn; 4585bec84e6bSVasundhara Volam desc.nic_vft.vf_num = 0; 4586bec84e6bSVasundhara Volam 4587f2858738SVasundhara Volam be_fill_vf_res_template(adapter, pool_res, num_vfs, num_vf_qs, 4588f2858738SVasundhara Volam &desc.nic_vft); 4589bec84e6bSVasundhara Volam 4590bec84e6bSVasundhara Volam return be_cmd_set_profile_config(adapter, &desc, 4591bec84e6bSVasundhara Volam 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0); 4592a401801cSSathya Perla } 4593a401801cSSathya Perla 4594a401801cSSathya Perla int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) 4595a401801cSSathya Perla { 4596a401801cSSathya Perla struct be_mcc_wrb *wrb; 4597a401801cSSathya Perla struct be_cmd_req_manage_iface_filters *req; 4598a401801cSSathya Perla int status; 4599a401801cSSathya Perla 4600a401801cSSathya Perla if (iface == 0xFFFFFFFF) 4601a401801cSSathya Perla return -1; 4602a401801cSSathya Perla 4603a401801cSSathya Perla spin_lock_bh(&adapter->mcc_lock); 4604a401801cSSathya Perla 4605a401801cSSathya Perla wrb = wrb_from_mccq(adapter); 4606a401801cSSathya Perla if (!wrb) { 4607a401801cSSathya Perla status = -EBUSY; 4608a401801cSSathya Perla goto err; 4609a401801cSSathya Perla } 4610a401801cSSathya Perla req = embedded_payload(wrb); 4611a401801cSSathya Perla 4612a401801cSSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4613a401801cSSathya Perla OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req), 4614a401801cSSathya Perla wrb, NULL); 4615a401801cSSathya Perla req->op = op; 4616a401801cSSathya Perla req->target_iface_id = cpu_to_le32(iface); 4617a401801cSSathya Perla 4618a401801cSSathya Perla status = be_mcc_notify_wait(adapter); 4619a401801cSSathya Perla err: 4620a401801cSSathya Perla spin_unlock_bh(&adapter->mcc_lock); 4621a401801cSSathya Perla return status; 4622a401801cSSathya Perla } 4623a401801cSSathya Perla 4624a401801cSSathya Perla int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port) 4625a401801cSSathya Perla { 4626a401801cSSathya Perla struct be_port_res_desc port_desc; 4627a401801cSSathya Perla 4628a401801cSSathya Perla memset(&port_desc, 0, sizeof(port_desc)); 4629a401801cSSathya Perla port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1; 4630a401801cSSathya Perla port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1; 4631a401801cSSathya Perla port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT); 4632a401801cSSathya Perla port_desc.link_num = adapter->hba_port_num; 4633a401801cSSathya Perla if (port) { 4634a401801cSSathya Perla port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) | 4635a401801cSSathya Perla (1 << RCVID_SHIFT); 4636a401801cSSathya Perla port_desc.nv_port = swab16(port); 4637a401801cSSathya Perla } else { 4638a401801cSSathya Perla port_desc.nv_flags = NV_TYPE_DISABLED; 4639a401801cSSathya Perla port_desc.nv_port = 0; 4640a401801cSSathya Perla } 4641a401801cSSathya Perla 4642a401801cSSathya Perla return be_cmd_set_profile_config(adapter, &port_desc, 4643bec84e6bSVasundhara Volam RESOURCE_DESC_SIZE_V1, 1, 1, 0); 4644a401801cSSathya Perla } 4645a401801cSSathya Perla 46464c876616SSathya Perla int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, 46474c876616SSathya Perla int vf_num) 46484c876616SSathya Perla { 46494c876616SSathya Perla struct be_mcc_wrb *wrb; 46504c876616SSathya Perla struct be_cmd_req_get_iface_list *req; 46514c876616SSathya Perla struct be_cmd_resp_get_iface_list *resp; 46524c876616SSathya Perla int status; 46534c876616SSathya Perla 46544c876616SSathya Perla spin_lock_bh(&adapter->mcc_lock); 46554c876616SSathya Perla 46564c876616SSathya Perla wrb = wrb_from_mccq(adapter); 46574c876616SSathya Perla if (!wrb) { 46584c876616SSathya Perla status = -EBUSY; 46594c876616SSathya Perla goto err; 46604c876616SSathya Perla } 46614c876616SSathya Perla req = embedded_payload(wrb); 46624c876616SSathya Perla 46634c876616SSathya Perla be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 46644c876616SSathya Perla OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp), 46654c876616SSathya Perla wrb, NULL); 46664c876616SSathya Perla req->hdr.domain = vf_num + 1; 46674c876616SSathya Perla 46684c876616SSathya Perla status = be_mcc_notify_wait(adapter); 46694c876616SSathya Perla if (!status) { 46704c876616SSathya Perla resp = (struct be_cmd_resp_get_iface_list *)req; 46714c876616SSathya Perla vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id); 46724c876616SSathya Perla } 46734c876616SSathya Perla 46744c876616SSathya Perla err: 46754c876616SSathya Perla spin_unlock_bh(&adapter->mcc_lock); 46764c876616SSathya Perla return status; 46774c876616SSathya Perla } 46784c876616SSathya Perla 46795c510811SSomnath Kotur static int lancer_wait_idle(struct be_adapter *adapter) 46805c510811SSomnath Kotur { 46815c510811SSomnath Kotur #define SLIPORT_IDLE_TIMEOUT 30 46825c510811SSomnath Kotur u32 reg_val; 46835c510811SSomnath Kotur int status = 0, i; 46845c510811SSomnath Kotur 46855c510811SSomnath Kotur for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) { 46865c510811SSomnath Kotur reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET); 46875c510811SSomnath Kotur if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0) 46885c510811SSomnath Kotur break; 46895c510811SSomnath Kotur 46905c510811SSomnath Kotur ssleep(1); 46915c510811SSomnath Kotur } 46925c510811SSomnath Kotur 46935c510811SSomnath Kotur if (i == SLIPORT_IDLE_TIMEOUT) 46945c510811SSomnath Kotur status = -1; 46955c510811SSomnath Kotur 46965c510811SSomnath Kotur return status; 46975c510811SSomnath Kotur } 46985c510811SSomnath Kotur 46995c510811SSomnath Kotur int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask) 47005c510811SSomnath Kotur { 47015c510811SSomnath Kotur int status = 0; 47025c510811SSomnath Kotur 47035c510811SSomnath Kotur status = lancer_wait_idle(adapter); 47045c510811SSomnath Kotur if (status) 47055c510811SSomnath Kotur return status; 47065c510811SSomnath Kotur 47075c510811SSomnath Kotur iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET); 47085c510811SSomnath Kotur 47095c510811SSomnath Kotur return status; 47105c510811SSomnath Kotur } 47115c510811SSomnath Kotur 47125c510811SSomnath Kotur /* Routine to check whether dump image is present or not */ 47135c510811SSomnath Kotur bool dump_present(struct be_adapter *adapter) 47145c510811SSomnath Kotur { 47155c510811SSomnath Kotur u32 sliport_status = 0; 47165c510811SSomnath Kotur 47175c510811SSomnath Kotur sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); 47185c510811SSomnath Kotur return !!(sliport_status & SLIPORT_STATUS_DIP_MASK); 47195c510811SSomnath Kotur } 47205c510811SSomnath Kotur 47215c510811SSomnath Kotur int lancer_initiate_dump(struct be_adapter *adapter) 47225c510811SSomnath Kotur { 4723f0613380SKalesh AP struct device *dev = &adapter->pdev->dev; 47245c510811SSomnath Kotur int status; 47255c510811SSomnath Kotur 4726f0613380SKalesh AP if (dump_present(adapter)) { 4727f0613380SKalesh AP dev_info(dev, "Previous dump not cleared, not forcing dump\n"); 4728f0613380SKalesh AP return -EEXIST; 4729f0613380SKalesh AP } 4730f0613380SKalesh AP 47315c510811SSomnath Kotur /* give firmware reset and diagnostic dump */ 47325c510811SSomnath Kotur status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK | 47335c510811SSomnath Kotur PHYSDEV_CONTROL_DD_MASK); 47345c510811SSomnath Kotur if (status < 0) { 4735f0613380SKalesh AP dev_err(dev, "FW reset failed\n"); 47365c510811SSomnath Kotur return status; 47375c510811SSomnath Kotur } 47385c510811SSomnath Kotur 47395c510811SSomnath Kotur status = lancer_wait_idle(adapter); 47405c510811SSomnath Kotur if (status) 47415c510811SSomnath Kotur return status; 47425c510811SSomnath Kotur 47435c510811SSomnath Kotur if (!dump_present(adapter)) { 4744f0613380SKalesh AP dev_err(dev, "FW dump not generated\n"); 4745f0613380SKalesh AP return -EIO; 47465c510811SSomnath Kotur } 47475c510811SSomnath Kotur 47485c510811SSomnath Kotur return 0; 47495c510811SSomnath Kotur } 47505c510811SSomnath Kotur 4751f0613380SKalesh AP int lancer_delete_dump(struct be_adapter *adapter) 4752f0613380SKalesh AP { 4753f0613380SKalesh AP int status; 4754f0613380SKalesh AP 4755f0613380SKalesh AP status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE); 4756f0613380SKalesh AP return be_cmd_status(status); 4757f0613380SKalesh AP } 4758f0613380SKalesh AP 4759dcf7ebbaSPadmanabh Ratnakar /* Uses sync mcc */ 4760dcf7ebbaSPadmanabh Ratnakar int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) 4761dcf7ebbaSPadmanabh Ratnakar { 4762dcf7ebbaSPadmanabh Ratnakar struct be_mcc_wrb *wrb; 4763dcf7ebbaSPadmanabh Ratnakar struct be_cmd_enable_disable_vf *req; 4764dcf7ebbaSPadmanabh Ratnakar int status; 4765dcf7ebbaSPadmanabh Ratnakar 47660599863dSVasundhara Volam if (BEx_chip(adapter)) 4767dcf7ebbaSPadmanabh Ratnakar return 0; 4768dcf7ebbaSPadmanabh Ratnakar 4769dcf7ebbaSPadmanabh Ratnakar spin_lock_bh(&adapter->mcc_lock); 4770dcf7ebbaSPadmanabh Ratnakar 4771dcf7ebbaSPadmanabh Ratnakar wrb = wrb_from_mccq(adapter); 4772dcf7ebbaSPadmanabh Ratnakar if (!wrb) { 4773dcf7ebbaSPadmanabh Ratnakar status = -EBUSY; 4774dcf7ebbaSPadmanabh Ratnakar goto err; 4775dcf7ebbaSPadmanabh Ratnakar } 4776dcf7ebbaSPadmanabh Ratnakar 4777dcf7ebbaSPadmanabh Ratnakar req = embedded_payload(wrb); 4778dcf7ebbaSPadmanabh Ratnakar 4779dcf7ebbaSPadmanabh Ratnakar be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4780dcf7ebbaSPadmanabh Ratnakar OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req), 4781dcf7ebbaSPadmanabh Ratnakar wrb, NULL); 4782dcf7ebbaSPadmanabh Ratnakar 4783dcf7ebbaSPadmanabh Ratnakar req->hdr.domain = domain; 4784dcf7ebbaSPadmanabh Ratnakar req->enable = 1; 4785dcf7ebbaSPadmanabh Ratnakar status = be_mcc_notify_wait(adapter); 4786dcf7ebbaSPadmanabh Ratnakar err: 4787dcf7ebbaSPadmanabh Ratnakar spin_unlock_bh(&adapter->mcc_lock); 4788dcf7ebbaSPadmanabh Ratnakar return status; 4789dcf7ebbaSPadmanabh Ratnakar } 4790dcf7ebbaSPadmanabh Ratnakar 479168c45a2dSSomnath Kotur int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable) 479268c45a2dSSomnath Kotur { 479368c45a2dSSomnath Kotur struct be_mcc_wrb *wrb; 479468c45a2dSSomnath Kotur struct be_cmd_req_intr_set *req; 479568c45a2dSSomnath Kotur int status; 479668c45a2dSSomnath Kotur 479768c45a2dSSomnath Kotur if (mutex_lock_interruptible(&adapter->mbox_lock)) 479868c45a2dSSomnath Kotur return -1; 479968c45a2dSSomnath Kotur 480068c45a2dSSomnath Kotur wrb = wrb_from_mbox(adapter); 480168c45a2dSSomnath Kotur 480268c45a2dSSomnath Kotur req = embedded_payload(wrb); 480368c45a2dSSomnath Kotur 480468c45a2dSSomnath Kotur be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 480568c45a2dSSomnath Kotur OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req), 480668c45a2dSSomnath Kotur wrb, NULL); 480768c45a2dSSomnath Kotur 480868c45a2dSSomnath Kotur req->intr_enabled = intr_enable; 480968c45a2dSSomnath Kotur 481068c45a2dSSomnath Kotur status = be_mbox_notify_wait(adapter); 481168c45a2dSSomnath Kotur 481268c45a2dSSomnath Kotur mutex_unlock(&adapter->mbox_lock); 481368c45a2dSSomnath Kotur return status; 481468c45a2dSSomnath Kotur } 481568c45a2dSSomnath Kotur 4816542963b7SVasundhara Volam /* Uses MBOX */ 4817542963b7SVasundhara Volam int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id) 4818542963b7SVasundhara Volam { 4819542963b7SVasundhara Volam struct be_cmd_req_get_active_profile *req; 4820542963b7SVasundhara Volam struct be_mcc_wrb *wrb; 4821542963b7SVasundhara Volam int status; 4822542963b7SVasundhara Volam 4823542963b7SVasundhara Volam if (mutex_lock_interruptible(&adapter->mbox_lock)) 4824542963b7SVasundhara Volam return -1; 4825542963b7SVasundhara Volam 4826542963b7SVasundhara Volam wrb = wrb_from_mbox(adapter); 4827542963b7SVasundhara Volam if (!wrb) { 4828542963b7SVasundhara Volam status = -EBUSY; 4829542963b7SVasundhara Volam goto err; 4830542963b7SVasundhara Volam } 4831542963b7SVasundhara Volam 4832542963b7SVasundhara Volam req = embedded_payload(wrb); 4833542963b7SVasundhara Volam 4834542963b7SVasundhara Volam be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4835542963b7SVasundhara Volam OPCODE_COMMON_GET_ACTIVE_PROFILE, sizeof(*req), 4836542963b7SVasundhara Volam wrb, NULL); 4837542963b7SVasundhara Volam 4838542963b7SVasundhara Volam status = be_mbox_notify_wait(adapter); 4839542963b7SVasundhara Volam if (!status) { 4840542963b7SVasundhara Volam struct be_cmd_resp_get_active_profile *resp = 4841542963b7SVasundhara Volam embedded_payload(wrb); 484203d28ffeSKalesh AP 4843542963b7SVasundhara Volam *profile_id = le16_to_cpu(resp->active_profile_id); 4844542963b7SVasundhara Volam } 4845542963b7SVasundhara Volam 4846542963b7SVasundhara Volam err: 4847542963b7SVasundhara Volam mutex_unlock(&adapter->mbox_lock); 4848542963b7SVasundhara Volam return status; 4849542963b7SVasundhara Volam } 4850542963b7SVasundhara Volam 4851d9d426afSSuresh Reddy int __be_cmd_set_logical_link_config(struct be_adapter *adapter, 4852d9d426afSSuresh Reddy int link_state, int version, u8 domain) 4853bdce2ad7SSuresh Reddy { 4854bdce2ad7SSuresh Reddy struct be_mcc_wrb *wrb; 4855bdce2ad7SSuresh Reddy struct be_cmd_req_set_ll_link *req; 4856bdce2ad7SSuresh Reddy int status; 4857bdce2ad7SSuresh Reddy 4858bdce2ad7SSuresh Reddy spin_lock_bh(&adapter->mcc_lock); 4859bdce2ad7SSuresh Reddy 4860bdce2ad7SSuresh Reddy wrb = wrb_from_mccq(adapter); 4861bdce2ad7SSuresh Reddy if (!wrb) { 4862bdce2ad7SSuresh Reddy status = -EBUSY; 4863bdce2ad7SSuresh Reddy goto err; 4864bdce2ad7SSuresh Reddy } 4865bdce2ad7SSuresh Reddy 4866bdce2ad7SSuresh Reddy req = embedded_payload(wrb); 4867bdce2ad7SSuresh Reddy 4868bdce2ad7SSuresh Reddy be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 4869bdce2ad7SSuresh Reddy OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG, 4870bdce2ad7SSuresh Reddy sizeof(*req), wrb, NULL); 4871bdce2ad7SSuresh Reddy 4872d9d426afSSuresh Reddy req->hdr.version = version; 4873bdce2ad7SSuresh Reddy req->hdr.domain = domain; 4874bdce2ad7SSuresh Reddy 4875d9d426afSSuresh Reddy if (link_state == IFLA_VF_LINK_STATE_ENABLE || 4876d9d426afSSuresh Reddy link_state == IFLA_VF_LINK_STATE_AUTO) 4877d9d426afSSuresh Reddy req->link_config |= PLINK_ENABLE; 4878bdce2ad7SSuresh Reddy 4879bdce2ad7SSuresh Reddy if (link_state == IFLA_VF_LINK_STATE_AUTO) 4880d9d426afSSuresh Reddy req->link_config |= PLINK_TRACK; 4881bdce2ad7SSuresh Reddy 4882bdce2ad7SSuresh Reddy status = be_mcc_notify_wait(adapter); 4883bdce2ad7SSuresh Reddy err: 4884bdce2ad7SSuresh Reddy spin_unlock_bh(&adapter->mcc_lock); 4885bdce2ad7SSuresh Reddy return status; 4886bdce2ad7SSuresh Reddy } 4887bdce2ad7SSuresh Reddy 4888d9d426afSSuresh Reddy int be_cmd_set_logical_link_config(struct be_adapter *adapter, 4889d9d426afSSuresh Reddy int link_state, u8 domain) 4890d9d426afSSuresh Reddy { 4891d9d426afSSuresh Reddy int status; 4892d9d426afSSuresh Reddy 4893d9d426afSSuresh Reddy if (BEx_chip(adapter)) 4894d9d426afSSuresh Reddy return -EOPNOTSUPP; 4895d9d426afSSuresh Reddy 4896d9d426afSSuresh Reddy status = __be_cmd_set_logical_link_config(adapter, link_state, 4897d9d426afSSuresh Reddy 2, domain); 4898d9d426afSSuresh Reddy 4899d9d426afSSuresh Reddy /* Version 2 of the command will not be recognized by older FW. 4900d9d426afSSuresh Reddy * On such a failure issue version 1 of the command. 4901d9d426afSSuresh Reddy */ 4902d9d426afSSuresh Reddy if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST) 4903d9d426afSSuresh Reddy status = __be_cmd_set_logical_link_config(adapter, link_state, 4904d9d426afSSuresh Reddy 1, domain); 4905d9d426afSSuresh Reddy return status; 4906d9d426afSSuresh Reddy } 49076a4ab669SParav Pandit int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, 49086a4ab669SParav Pandit int wrb_payload_size, u16 *cmd_status, u16 *ext_status) 49096a4ab669SParav Pandit { 49106a4ab669SParav Pandit struct be_adapter *adapter = netdev_priv(netdev_handle); 49116a4ab669SParav Pandit struct be_mcc_wrb *wrb; 49126a4ab669SParav Pandit struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *)wrb_payload; 49136a4ab669SParav Pandit struct be_cmd_req_hdr *req; 49146a4ab669SParav Pandit struct be_cmd_resp_hdr *resp; 49156a4ab669SParav Pandit int status; 49166a4ab669SParav Pandit 49176a4ab669SParav Pandit spin_lock_bh(&adapter->mcc_lock); 49186a4ab669SParav Pandit 49196a4ab669SParav Pandit wrb = wrb_from_mccq(adapter); 49206a4ab669SParav Pandit if (!wrb) { 49216a4ab669SParav Pandit status = -EBUSY; 49226a4ab669SParav Pandit goto err; 49236a4ab669SParav Pandit } 49246a4ab669SParav Pandit req = embedded_payload(wrb); 49256a4ab669SParav Pandit resp = embedded_payload(wrb); 49266a4ab669SParav Pandit 49276a4ab669SParav Pandit be_wrb_cmd_hdr_prepare(req, hdr->subsystem, 49286a4ab669SParav Pandit hdr->opcode, wrb_payload_size, wrb, NULL); 49296a4ab669SParav Pandit memcpy(req, wrb_payload, wrb_payload_size); 49306a4ab669SParav Pandit be_dws_cpu_to_le(req, wrb_payload_size); 49316a4ab669SParav Pandit 49326a4ab669SParav Pandit status = be_mcc_notify_wait(adapter); 49336a4ab669SParav Pandit if (cmd_status) 49346a4ab669SParav Pandit *cmd_status = (status & 0xffff); 49356a4ab669SParav Pandit if (ext_status) 49366a4ab669SParav Pandit *ext_status = 0; 49376a4ab669SParav Pandit memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length); 49386a4ab669SParav Pandit be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length); 49396a4ab669SParav Pandit err: 49406a4ab669SParav Pandit spin_unlock_bh(&adapter->mcc_lock); 49416a4ab669SParav Pandit return status; 49426a4ab669SParav Pandit } 49436a4ab669SParav Pandit EXPORT_SYMBOL(be_roce_mcc_cmd); 4944