return (void *)addr;
}
-static int be_mcc_compl_process(struct be_adapter *adapter,
- struct be_mcc_compl *compl)
+static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status)
+{
+ if (base_status == MCC_STATUS_NOT_SUPPORTED ||
+ base_status == MCC_STATUS_ILLEGAL_REQUEST ||
+ addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES ||
+ (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
+ (base_status == MCC_STATUS_ILLEGAL_FIELD ||
+ addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH)))
+ return true;
+ else
+ return false;
+}
+
+/* Place holder for all the async MCC cmds wherein the caller is not in a busy
+ * loop (has not issued be_mcc_notify_wait())
+ */
+static void be_async_cmd_process(struct be_adapter *adapter,
+ struct be_mcc_compl *compl,
+ struct be_cmd_resp_hdr *resp_hdr)
{
- u16 compl_status, extd_status;
- struct be_cmd_resp_hdr *resp_hdr;
+ enum mcc_base_status base_status = base_status(compl->status);
u8 opcode = 0, subsystem = 0;
- /* Just swap the status to host endian; mcc tag is opaquely copied
- * from mcc_wrb */
- be_dws_le_to_cpu(compl, 4);
-
- compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
- CQE_STATUS_COMPL_MASK;
-
- resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
-
if (resp_hdr) {
opcode = resp_hdr->opcode;
subsystem = resp_hdr->subsystem;
if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
complete(&adapter->et_cmd_compl);
- return 0;
+ return;
}
- if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
- (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
- (subsystem == CMD_SUBSYSTEM_COMMON)) {
- adapter->flash_status = compl_status;
+ if ((opcode == OPCODE_COMMON_WRITE_FLASHROM ||
+ opcode == OPCODE_COMMON_WRITE_OBJECT) &&
+ subsystem == CMD_SUBSYSTEM_COMMON) {
+ adapter->flash_status = compl->status;
complete(&adapter->et_cmd_compl);
+ return;
}
- if (compl_status == MCC_STATUS_SUCCESS) {
- if (((opcode == OPCODE_ETH_GET_STATISTICS) ||
- (opcode == OPCODE_ETH_GET_PPORT_STATS)) &&
- (subsystem == CMD_SUBSYSTEM_ETH)) {
- be_parse_stats(adapter);
- adapter->stats_cmd_sent = false;
- }
- if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
- subsystem == CMD_SUBSYSTEM_COMMON) {
+ if ((opcode == OPCODE_ETH_GET_STATISTICS ||
+ opcode == OPCODE_ETH_GET_PPORT_STATS) &&
+ subsystem == CMD_SUBSYSTEM_ETH &&
+ base_status == MCC_STATUS_SUCCESS) {
+ be_parse_stats(adapter);
+ adapter->stats_cmd_sent = false;
+ return;
+ }
+
+ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
+ subsystem == CMD_SUBSYSTEM_COMMON) {
+ if (base_status == MCC_STATUS_SUCCESS) {
struct be_cmd_resp_get_cntl_addnl_attribs *resp =
- (void *)resp_hdr;
+ (void *)resp_hdr;
adapter->drv_stats.be_on_die_temperature =
- resp->on_die_temperature;
- }
- } else {
- if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
+ resp->on_die_temperature;
+ } else {
adapter->be_get_temp_freq = 0;
+ }
+ return;
+ }
+}
+
+static int be_mcc_compl_process(struct be_adapter *adapter,
+ struct be_mcc_compl *compl)
+{
+ enum mcc_base_status base_status;
+ enum mcc_addl_status addl_status;
+ struct be_cmd_resp_hdr *resp_hdr;
+ u8 opcode = 0, subsystem = 0;
+
+ /* Just swap the status to host endian; mcc tag is opaquely copied
+ * from mcc_wrb */
+ be_dws_le_to_cpu(compl, 4);
+
+ base_status = base_status(compl->status);
+ addl_status = addl_status(compl->status);
+
+ resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
+ if (resp_hdr) {
+ opcode = resp_hdr->opcode;
+ subsystem = resp_hdr->subsystem;
+ }
- if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
- compl_status == MCC_STATUS_ILLEGAL_REQUEST)
- goto done;
+ be_async_cmd_process(adapter, compl, resp_hdr);
- if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
+ if (base_status != MCC_STATUS_SUCCESS &&
+ !be_skip_err_log(opcode, base_status, addl_status)) {
+
+ if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
dev_warn(&adapter->pdev->dev,
"VF is not privileged to issue opcode %d-%d\n",
opcode, subsystem);
} else {
- extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
- CQE_STATUS_EXTD_MASK;
dev_err(&adapter->pdev->dev,
"opcode %d-%d failed:status %d-%d\n",
- opcode, subsystem, compl_status, extd_status);
-
- if (extd_status == MCC_ADDL_STS_INSUFFICIENT_RESOURCES)
- return extd_status;
+ opcode, subsystem, base_status, addl_status);
}
}
-done:
- return compl_status;
+ return compl->status;
}
/* Link state evt is a string of bytes; no need for endian swapping */
static void be_async_link_state_process(struct be_adapter *adapter,
- struct be_async_event_link_state *evt)
+ struct be_mcc_compl *compl)
{
+ struct be_async_event_link_state *evt =
+ (struct be_async_event_link_state *)compl;
+
/* When link status changes, link speed must be re-queried from FW */
adapter->phy.link_speed = -1;
/* Grp5 CoS Priority evt */
static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
- struct
- be_async_event_grp5_cos_priority
- *evt)
+ struct be_mcc_compl *compl)
{
+ struct be_async_event_grp5_cos_priority *evt =
+ (struct be_async_event_grp5_cos_priority *)compl;
+
if (evt->valid) {
adapter->vlan_prio_bmap = evt->available_priority_bmap;
adapter->recommended_prio &= ~VLAN_PRIO_MASK;
/* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */
static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
- struct
- be_async_event_grp5_qos_link_speed
- *evt)
+ struct be_mcc_compl *compl)
{
+ struct be_async_event_grp5_qos_link_speed *evt =
+ (struct be_async_event_grp5_qos_link_speed *)compl;
+
if (adapter->phy.link_speed >= 0 &&
evt->physical_port == adapter->port_num)
adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10;
/*Grp5 PVID evt*/
static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
- struct
- be_async_event_grp5_pvid_state
- *evt)
+ struct be_mcc_compl *compl)
{
+ struct be_async_event_grp5_pvid_state *evt =
+ (struct be_async_event_grp5_pvid_state *)compl;
+
if (evt->enabled) {
adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid);
}
static void be_async_grp5_evt_process(struct be_adapter *adapter,
- u32 trailer, struct be_mcc_compl *evt)
+ struct be_mcc_compl *compl)
{
- u8 event_type = 0;
-
- event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
- ASYNC_TRAILER_EVENT_TYPE_MASK;
+ u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) &
+ ASYNC_EVENT_TYPE_MASK;
switch (event_type) {
case ASYNC_EVENT_COS_PRIORITY:
- be_async_grp5_cos_priority_process(adapter,
- (struct be_async_event_grp5_cos_priority *)evt);
- break;
+ be_async_grp5_cos_priority_process(adapter, compl);
+ break;
case ASYNC_EVENT_QOS_SPEED:
- be_async_grp5_qos_speed_process(adapter,
- (struct be_async_event_grp5_qos_link_speed *)evt);
- break;
+ be_async_grp5_qos_speed_process(adapter, compl);
+ break;
case ASYNC_EVENT_PVID_STATE:
- be_async_grp5_pvid_state_process(adapter,
- (struct be_async_event_grp5_pvid_state *)evt);
- break;
+ be_async_grp5_pvid_state_process(adapter, compl);
+ break;
default:
dev_warn(&adapter->pdev->dev, "Unknown grp5 event 0x%x!\n",
event_type);
}
static void be_async_dbg_evt_process(struct be_adapter *adapter,
- u32 trailer, struct be_mcc_compl *cmp)
+ struct be_mcc_compl *cmp)
{
u8 event_type = 0;
struct be_async_event_qnq *evt = (struct be_async_event_qnq *) cmp;
- event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
- ASYNC_TRAILER_EVENT_TYPE_MASK;
+ event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
+ ASYNC_EVENT_TYPE_MASK;
switch (event_type) {
case ASYNC_DEBUG_EVENT_TYPE_QNQ:
}
}
-static inline bool is_link_state_evt(u32 trailer)
+static inline bool is_link_state_evt(u32 flags)
+{
+ return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
+ ASYNC_EVENT_CODE_LINK_STATE;
+}
+
+static inline bool is_grp5_evt(u32 flags)
{
- return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
- ASYNC_TRAILER_EVENT_CODE_MASK) ==
- ASYNC_EVENT_CODE_LINK_STATE;
+ return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
+ ASYNC_EVENT_CODE_GRP_5;
}
-static inline bool is_grp5_evt(u32 trailer)
+static inline bool is_dbg_evt(u32 flags)
{
- return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
- ASYNC_TRAILER_EVENT_CODE_MASK) ==
- ASYNC_EVENT_CODE_GRP_5);
+ return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
+ ASYNC_EVENT_CODE_QNQ;
}
-static inline bool is_dbg_evt(u32 trailer)
+static void be_mcc_event_process(struct be_adapter *adapter,
+ struct be_mcc_compl *compl)
{
- return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
- ASYNC_TRAILER_EVENT_CODE_MASK) ==
- ASYNC_EVENT_CODE_QNQ);
+ if (is_link_state_evt(compl->flags))
+ be_async_link_state_process(adapter, compl);
+ else if (is_grp5_evt(compl->flags))
+ be_async_grp5_evt_process(adapter, compl);
+ else if (is_dbg_evt(compl->flags))
+ be_async_dbg_evt_process(adapter, compl);
}
static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
spin_lock(&adapter->mcc_cq_lock);
+
while ((compl = be_mcc_compl_get(adapter))) {
if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
- /* Interpret flags as an async trailer */
- if (is_link_state_evt(compl->flags))
- be_async_link_state_process(adapter,
- (struct be_async_event_link_state *) compl);
- else if (is_grp5_evt(compl->flags))
- be_async_grp5_evt_process(adapter,
- compl->flags, compl);
- else if (is_dbg_evt(compl->flags))
- be_async_dbg_evt_process(adapter,
- compl->flags, compl);
+ be_mcc_event_process(adapter, compl);
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
- status = be_mcc_compl_process(adapter, compl);
- atomic_dec(&mcc_obj->q.used);
+ status = be_mcc_compl_process(adapter, compl);
+ atomic_dec(&mcc_obj->q.used);
}
be_mcc_compl_use(compl);
num++;
if (status == -EIO)
goto out;
- status = resp->status;
+ status = (resp->base_status |
+ ((resp->addl_status & CQE_ADDL_STATUS_MASK) <<
+ CQE_ADDL_STATUS_SHIFT));
out:
return status;
}
}
/* Uses synchronous mcc */
-int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
- char *fw_on_flash)
+int be_cmd_get_fw_ver(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_fw_version *req;
status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
- strcpy(fw_ver, resp->firmware_version_string);
- if (fw_on_flash)
- strcpy(fw_on_flash, resp->fw_on_flash_version_string);
+ strcpy(adapter->fw_ver, resp->firmware_version_string);
+ strcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string);
}
err:
spin_unlock_bh(&adapter->mcc_lock);
}
/* Uses mbox */
-int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
- u32 *mode, u32 *caps, u16 *asic_rev)
+int be_cmd_query_fw_cfg(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_query_fw_cfg *req;
status = be_mbox_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
- *port_num = le32_to_cpu(resp->phys_port);
- *mode = le32_to_cpu(resp->function_mode);
- *caps = le32_to_cpu(resp->function_caps);
- *asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
+ adapter->port_num = le32_to_cpu(resp->phys_port);
+ adapter->function_mode = le32_to_cpu(resp->function_mode);
+ adapter->function_caps = le32_to_cpu(resp->function_caps);
+ adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
}
mutex_unlock(&adapter->mbox_lock);
}
int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
- u32 rss_hash_opts, u16 table_size, u8 *rss_hkey)
+ u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_rss_config *req;
if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
msecs_to_jiffies(60000)))
- status = -1;
+ status = -ETIMEDOUT;
else
status = adapter->flash_status;
if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
msecs_to_jiffies(40000)))
- status = -1;
+ status = -ETIMEDOUT;
else
status = adapter->flash_status;
}
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
- int offset)
+ u16 optype, int offset)
{
struct be_mcc_wrb *wrb;
struct be_cmd_read_flash_crc *req;
OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
wrb, NULL);
- req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
+ req->params.op_type = cpu_to_le32(optype);
req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
req->params.offset = cpu_to_le32(offset);
req->params.data_buf_size = cpu_to_le32(0x4);
return status;
}
-static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count)
+/* Descriptor type */
+enum {
+ FUNC_DESC = 1,
+ VFT_DESC = 2
+};
+
+static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
+ int desc_type)
{
struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
+ struct be_nic_res_desc *nic;
int i;
for (i = 0; i < desc_count; i++) {
if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
- hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1)
- return (struct be_nic_res_desc *)hdr;
+ hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) {
+ nic = (struct be_nic_res_desc *)hdr;
+ if (desc_type == FUNC_DESC ||
+ (desc_type == VFT_DESC &&
+ nic->flags & (1 << VFT_SHIFT)))
+ return nic;
+ }
hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
hdr = (void *)hdr + hdr->desc_len;
return NULL;
}
+static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count)
+{
+ return be_get_nic_desc(buf, desc_count, VFT_DESC);
+}
+
+static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count)
+{
+ return be_get_nic_desc(buf, desc_count, FUNC_DESC);
+}
+
static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf,
u32 desc_count)
{
u32 desc_count = le32_to_cpu(resp->desc_count);
struct be_nic_res_desc *desc;
- desc = be_get_nic_desc(resp->func_param, desc_count);
+ desc = be_get_func_nic_desc(resp->func_param, desc_count);
if (!desc) {
status = -EINVAL;
goto err;
return status;
}
-/* Uses mbox */
-static int be_cmd_get_profile_config_mbox(struct be_adapter *adapter,
- u8 domain, struct be_dma_mem *cmd)
-{
- struct be_mcc_wrb *wrb;
- struct be_cmd_req_get_profile_config *req;
- int status;
-
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
- wrb = wrb_from_mbox(adapter);
-
- req = cmd->va;
- be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_PROFILE_CONFIG,
- cmd->size, wrb, cmd);
-
- req->type = ACTIVE_PROFILE_TYPE;
- req->hdr.domain = domain;
- if (!lancer_chip(adapter))
- req->hdr.version = 1;
-
- status = be_mbox_notify_wait(adapter);
-
- mutex_unlock(&adapter->mbox_lock);
- return status;
-}
-
-/* Uses sync mcc */
-static int be_cmd_get_profile_config_mccq(struct be_adapter *adapter,
- u8 domain, struct be_dma_mem *cmd)
-{
- struct be_mcc_wrb *wrb;
- struct be_cmd_req_get_profile_config *req;
- int status;
-
- spin_lock_bh(&adapter->mcc_lock);
-
- wrb = wrb_from_mccq(adapter);
- if (!wrb) {
- status = -EBUSY;
- goto err;
- }
-
- req = cmd->va;
- be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_PROFILE_CONFIG,
- cmd->size, wrb, cmd);
-
- req->type = ACTIVE_PROFILE_TYPE;
- req->hdr.domain = domain;
- if (!lancer_chip(adapter))
- req->hdr.version = 1;
-
- status = be_mcc_notify_wait(adapter);
-
-err:
- spin_unlock_bh(&adapter->mcc_lock);
- return status;
-}
-
-/* Uses sync mcc, if MCCQ is already created otherwise mbox */
+/* Will use MBOX only if MCCQ has not been created */
int be_cmd_get_profile_config(struct be_adapter *adapter,
struct be_resources *res, u8 domain)
{
struct be_cmd_resp_get_profile_config *resp;
+ struct be_cmd_req_get_profile_config *req;
+ struct be_nic_res_desc *vf_res;
struct be_pcie_res_desc *pcie;
struct be_port_res_desc *port;
struct be_nic_res_desc *nic;
- struct be_queue_info *mccq = &adapter->mcc_obj.q;
+ struct be_mcc_wrb wrb = {0};
struct be_dma_mem cmd;
u32 desc_count;
int status;
if (!cmd.va)
return -ENOMEM;
- if (!mccq->created)
- status = be_cmd_get_profile_config_mbox(adapter, domain, &cmd);
- else
- status = be_cmd_get_profile_config_mccq(adapter, domain, &cmd);
+ req = cmd.va;
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_PROFILE_CONFIG,
+ cmd.size, &wrb, &cmd);
+
+ req->hdr.domain = domain;
+ if (!lancer_chip(adapter))
+ req->hdr.version = 1;
+ req->type = ACTIVE_PROFILE_TYPE;
+
+ status = be_cmd_notify_wait(adapter, &wrb);
if (status)
goto err;
if (port)
adapter->mc_type = port->mc_type;
- nic = be_get_nic_desc(resp->func_param, desc_count);
+ nic = be_get_func_nic_desc(resp->func_param, desc_count);
if (nic)
be_copy_nic_desc(res, nic);
+ vf_res = be_get_vft_desc(resp->func_param, desc_count);
+ if (vf_res)
+ res->vf_if_cap_flags = vf_res->cap_flags;
err:
if (cmd.va)
pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
return status;
}
-int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
- int size, u8 version, u8 domain)
+/* Will use MBOX only if MCCQ has not been created */
+static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
+ int size, int count, u8 version, u8 domain)
{
struct be_cmd_req_set_profile_config *req;
- struct be_mcc_wrb *wrb;
+ struct be_mcc_wrb wrb = {0};
+ struct be_dma_mem cmd;
int status;
- spin_lock_bh(&adapter->mcc_lock);
-
- wrb = wrb_from_mccq(adapter);
- if (!wrb) {
- status = -EBUSY;
- goto err;
- }
+ memset(&cmd, 0, sizeof(struct be_dma_mem));
+ cmd.size = sizeof(struct be_cmd_req_set_profile_config);
+ cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
+ if (!cmd.va)
+ return -ENOMEM;
- req = embedded_payload(wrb);
+ req = cmd.va;
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req),
- wrb, NULL);
+ OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size,
+ &wrb, &cmd);
req->hdr.version = version;
req->hdr.domain = domain;
- req->desc_count = cpu_to_le32(1);
+ req->desc_count = cpu_to_le32(count);
memcpy(req->desc, desc, size);
- status = be_mcc_notify_wait(adapter);
-err:
- spin_unlock_bh(&adapter->mcc_lock);
+ status = be_cmd_notify_wait(adapter, &wrb);
+
+ if (cmd.va)
+ pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
return status;
}
/* Mark all fields invalid */
-void be_reset_nic_desc(struct be_nic_res_desc *nic)
+static void be_reset_nic_desc(struct be_nic_res_desc *nic)
{
memset(nic, 0, sizeof(*nic));
nic->unicast_mac_count = 0xFFFF;
nic->cq_count = 0xFFFF;
nic->toe_conn_count = 0xFFFF;
nic->eq_count = 0xFFFF;
+ nic->iface_count = 0xFFFF;
nic->link_param = 0xFF;
+ nic->channel_id_param = cpu_to_le16(0xF000);
nic->acpi_params = 0xFF;
nic->wol_param = 0x0F;
+ nic->tunnel_iface_count = 0xFFFF;
+ nic->direct_tenant_iface_count = 0xFFFF;
nic->bw_min = 0xFFFFFFFF;
nic->bw_max = 0xFFFFFFFF;
}
-int be_cmd_config_qos(struct be_adapter *adapter, u32 bps, u8 domain)
+/* Mark all fields invalid */
+static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie)
{
- if (lancer_chip(adapter)) {
- struct be_nic_res_desc nic_desc;
+ memset(pcie, 0, sizeof(*pcie));
+ pcie->sriov_state = 0xFF;
+ pcie->pf_state = 0xFF;
+ pcie->pf_type = 0xFF;
+ pcie->num_vfs = 0xFFFF;
+}
- be_reset_nic_desc(&nic_desc);
+int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
+ u8 domain)
+{
+ struct be_nic_res_desc nic_desc;
+ u32 bw_percent;
+ u16 version = 0;
+
+ if (BE3_chip(adapter))
+ return be_cmd_set_qos(adapter, max_rate / 10, domain);
+
+ be_reset_nic_desc(&nic_desc);
+ nic_desc.pf_num = adapter->pf_number;
+ nic_desc.vf_num = domain;
+ if (lancer_chip(adapter)) {
nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
(1 << NOSV_SHIFT);
- nic_desc.pf_num = adapter->pf_number;
- nic_desc.vf_num = domain;
- nic_desc.bw_max = cpu_to_le32(bps);
+ nic_desc.bw_max = cpu_to_le32(max_rate / 10);
+ } else {
+ version = 1;
+ nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
+ nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
+ nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
+ bw_percent = max_rate ? (max_rate * 100) / link_speed : 100;
+ nic_desc.bw_max = cpu_to_le32(bw_percent);
+ }
- return be_cmd_set_profile_config(adapter, &nic_desc,
- RESOURCE_DESC_SIZE_V0,
- 0, domain);
+ return be_cmd_set_profile_config(adapter, &nic_desc,
+ nic_desc.hdr.desc_len,
+ 1, version, domain);
+}
+
+int be_cmd_set_sriov_config(struct be_adapter *adapter,
+ struct be_resources res, u16 num_vfs)
+{
+ struct {
+ struct be_pcie_res_desc pcie;
+ struct be_nic_res_desc nic_vft;
+ } __packed desc;
+ u16 vf_q_count;
+
+ if (BEx_chip(adapter) || lancer_chip(adapter))
+ return 0;
+
+ /* PF PCIE descriptor */
+ be_reset_pcie_desc(&desc.pcie);
+ desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1;
+ desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
+ desc.pcie.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
+ desc.pcie.pf_num = adapter->pdev->devfn;
+ desc.pcie.sriov_state = num_vfs ? 1 : 0;
+ desc.pcie.num_vfs = cpu_to_le16(num_vfs);
+
+ /* VF NIC Template descriptor */
+ be_reset_nic_desc(&desc.nic_vft);
+ desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
+ desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
+ desc.nic_vft.flags = (1 << VFT_SHIFT) | (1 << IMM_SHIFT) |
+ (1 << NOSV_SHIFT);
+ desc.nic_vft.pf_num = adapter->pdev->devfn;
+ desc.nic_vft.vf_num = 0;
+
+ if (num_vfs && res.vf_if_cap_flags & BE_IF_FLAGS_RSS) {
+ /* If number of VFs requested is 8 less than max supported,
+ * assign 8 queue pairs to the PF and divide the remaining
+ * resources evenly among the VFs
+ */
+ if (num_vfs < (be_max_vfs(adapter) - 8))
+ vf_q_count = (res.max_rss_qs - 8) / num_vfs;
+ else
+ vf_q_count = res.max_rss_qs / num_vfs;
+
+ desc.nic_vft.rq_count = cpu_to_le16(vf_q_count);
+ desc.nic_vft.txq_count = cpu_to_le16(vf_q_count);
+ desc.nic_vft.rssq_count = cpu_to_le16(vf_q_count - 1);
+ desc.nic_vft.cq_count = cpu_to_le16(3 * vf_q_count);
} else {
- return be_cmd_set_qos(adapter, bps, domain);
+ desc.nic_vft.txq_count = cpu_to_le16(1);
+ desc.nic_vft.rq_count = cpu_to_le16(1);
+ desc.nic_vft.rssq_count = cpu_to_le16(0);
+ /* One CQ for each TX, RX and MCCQ */
+ desc.nic_vft.cq_count = cpu_to_le16(3);
}
+
+ return be_cmd_set_profile_config(adapter, &desc,
+ 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
}
int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
}
return be_cmd_set_profile_config(adapter, &port_desc,
- RESOURCE_DESC_SIZE_V1, 1, 0);
+ RESOURCE_DESC_SIZE_V1, 1, 1, 0);
}
int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,