diff options
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_cmds.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 226 |
1 files changed, 134 insertions, 92 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index f4ea3490f446..9904bbfd4e93 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -3313,15 +3313,28 @@ err: 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; @@ -3329,6 +3342,16 @@ static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count) 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) { @@ -3424,7 +3447,7 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) 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; @@ -3440,76 +3463,17 @@ 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; @@ -3520,10 +3484,17 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, 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; @@ -3539,48 +3510,52 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, 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; @@ -3601,9 +3576,20 @@ void be_reset_nic_desc(struct be_nic_res_desc *nic) nic->wol_param = 0x0F; nic->tunnel_iface_count = 0xFFFF; nic->direct_tenant_iface_count = 0xFFFF; + nic->bw_min = 0xFFFFFFFF; nic->bw_max = 0xFFFFFFFF; } +/* Mark all fields invalid */ +static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie) +{ + memset(pcie, 0, sizeof(*pcie)); + pcie->sriov_state = 0xFF; + pcie->pf_state = 0xFF; + pcie->pf_type = 0xFF; + pcie->num_vfs = 0xFFFF; +} + int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed, u8 domain) { @@ -3634,7 +3620,63 @@ int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed, return be_cmd_set_profile_config(adapter, &nic_desc, nic_desc.hdr.desc_len, - version, domain); + 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 { + 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) @@ -3686,7 +3728,7 @@ int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port) } 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, |