aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/emulex/benet/be_cmds.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 09:38:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 09:38:14 -0700
commitae045e2455429c418a418a3376301a9e5753a0a8 (patch)
treeb445bdeecd3f38aa0d0a29c9585cee49e4ccb0f1 /drivers/net/ethernet/emulex/benet/be_cmds.c
parentMerge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random (diff)
parentMerge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (diff)
downloadlinux-dev-ae045e2455429c418a418a3376301a9e5753a0a8.tar.xz
linux-dev-ae045e2455429c418a418a3376301a9e5753a0a8.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: "Highlights: 1) Steady transitioning of the BPF instructure to a generic spot so all kernel subsystems can make use of it, from Alexei Starovoitov. 2) SFC driver supports busy polling, from Alexandre Rames. 3) Take advantage of hash table in UDP multicast delivery, from David Held. 4) Lighten locking, in particular by getting rid of the LRU lists, in inet frag handling. From Florian Westphal. 5) Add support for various RFC6458 control messages in SCTP, from Geir Ola Vaagland. 6) Allow to filter bridge forwarding database dumps by device, from Jamal Hadi Salim. 7) virtio-net also now supports busy polling, from Jason Wang. 8) Some low level optimization tweaks in pktgen from Jesper Dangaard Brouer. 9) Add support for ipv6 address generation modes, so that userland can have some input into the process. From Jiri Pirko. 10) Consolidate common TCP connection request code in ipv4 and ipv6, from Octavian Purdila. 11) New ARP packet logger in netfilter, from Pablo Neira Ayuso. 12) Generic resizable RCU hash table, with intial users in netlink and nftables. From Thomas Graf. 13) Maintain a name assignment type so that userspace can see where a network device name came from (enumerated by kernel, assigned explicitly by userspace, etc.) From Tom Gundersen. 14) Automatic flow label generation on transmit in ipv6, from Tom Herbert. 15) New packet timestamping facilities from Willem de Bruijn, meant to assist in measuring latencies going into/out-of the packet scheduler, latency from TCP data transmission to ACK, etc" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1536 commits) cxgb4 : Disable recursive mailbox commands when enabling vi net: reduce USB network driver config options. tg3: Modify tg3_tso_bug() to handle multiple TX rings amd-xgbe: Perform phy connect/disconnect at dev open/stop amd-xgbe: Use dma_set_mask_and_coherent to set DMA mask net: sun4i-emac: fix memory leak on bad packet sctp: fix possible seqlock seadlock in sctp_packet_transmit() Revert "net: phy: Set the driver when registering an MDIO bus device" cxgb4vf: Turn off SGE RX/TX Callback Timers and interrupts in PCI shutdown routine team: Simplify return path of team_newlink bridge: Update outdated comment on promiscuous mode net-timestamp: ACK timestamp for bytestreams net-timestamp: TCP timestamping net-timestamp: SCHED timestamp on entering packet scheduler net-timestamp: add key to disambiguate concurrent datagrams net-timestamp: move timestamp flags out of sk_flags net-timestamp: extend SCM_TIMESTAMPING ancillary data struct cxgb4i : Move stray CPL definitions to cxgb4 driver tcp: reduce spurious retransmits due to transient SACK reneging qlcnic: Initialize dcbnl_ops before register_netdev ...
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_cmds.c')
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c297
1 files changed, 189 insertions, 108 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index f4ea3490f446..4370ec1952ac 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1749,8 +1749,7 @@ err:
}
/* 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;
@@ -1772,9 +1771,8 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
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);
@@ -1997,8 +1995,7 @@ err:
}
/* 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;
@@ -2017,10 +2014,10 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
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);
@@ -2224,7 +2221,7 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
msecs_to_jiffies(60000)))
- status = -1;
+ status = -ETIMEDOUT;
else
status = adapter->flash_status;
@@ -2243,6 +2240,34 @@ err_unlock:
return status;
}
+int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name)
+{
+ struct lancer_cmd_req_delete_object *req;
+ struct be_mcc_wrb *wrb;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_DELETE_OBJECT,
+ sizeof(*req), wrb, NULL);
+
+ strcpy(req->object_name, obj_name);
+
+ status = be_mcc_notify_wait(adapter);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+
int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 data_size, u32 data_offset, const char *obj_name,
u32 *data_read, u32 *eof, u8 *addn_status)
@@ -2320,7 +2345,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
msecs_to_jiffies(40000)))
- status = -1;
+ status = -ETIMEDOUT;
else
status = adapter->flash_status;
@@ -3313,15 +3338,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 +3367,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 +3472,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 +3488,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 +3509,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 +3535,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 +3601,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 +3645,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 +3753,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,
@@ -3766,13 +3833,19 @@ bool dump_present(struct be_adapter *adapter)
int lancer_initiate_dump(struct be_adapter *adapter)
{
+ struct device *dev = &adapter->pdev->dev;
int status;
+ if (dump_present(adapter)) {
+ dev_info(dev, "Previous dump not cleared, not forcing dump\n");
+ return -EEXIST;
+ }
+
/* give firmware reset and diagnostic dump */
status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
PHYSDEV_CONTROL_DD_MASK);
if (status < 0) {
- dev_err(&adapter->pdev->dev, "Firmware reset failed\n");
+ dev_err(dev, "FW reset failed\n");
return status;
}
@@ -3781,13 +3854,21 @@ int lancer_initiate_dump(struct be_adapter *adapter)
return status;
if (!dump_present(adapter)) {
- dev_err(&adapter->pdev->dev, "Dump image not present\n");
- return -1;
+ dev_err(dev, "FW dump not generated\n");
+ return -EIO;
}
return 0;
}
+int lancer_delete_dump(struct be_adapter *adapter)
+{
+ int status;
+
+ status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE);
+ return be_cmd_status(status);
+}
+
/* Uses sync mcc */
int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
{