summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/emulex/benet/be_cmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_cmds.c')
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c257
1 files changed, 185 insertions, 72 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 3c9b4f12e3e5..25d3290b8cac 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -263,6 +263,27 @@ static void be_async_grp5_evt_process(struct be_adapter *adapter,
}
}
+static void be_async_dbg_evt_process(struct be_adapter *adapter,
+ u32 trailer, 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;
+
+ switch (event_type) {
+ case ASYNC_DEBUG_EVENT_TYPE_QNQ:
+ if (evt->valid)
+ adapter->qnq_vid = le16_to_cpu(evt->vlan_tag);
+ adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
+ break;
+ default:
+ dev_warn(&adapter->pdev->dev, "Unknown debug event\n");
+ break;
+ }
+}
+
static inline bool is_link_state_evt(u32 trailer)
{
return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
@@ -277,6 +298,13 @@ static inline bool is_grp5_evt(u32 trailer)
ASYNC_EVENT_CODE_GRP_5);
}
+static inline bool is_dbg_evt(u32 trailer)
+{
+ return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
+ ASYNC_TRAILER_EVENT_CODE_MASK) ==
+ ASYNC_EVENT_CODE_QNQ);
+}
+
static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
{
struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
@@ -325,6 +353,9 @@ int be_process_mcc(struct be_adapter *adapter)
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);
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
status = be_mcc_compl_process(adapter, compl);
atomic_dec(&mcc_obj->q.used);
@@ -687,10 +718,8 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
if (!mccq->created)
return NULL;
- if (atomic_read(&mccq->used) >= mccq->len) {
- dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n");
+ if (atomic_read(&mccq->used) >= mccq->len)
return NULL;
- }
wrb = queue_head_node(mccq);
queue_head_inc(mccq);
@@ -1022,6 +1051,7 @@ int be_cmd_mccq_ext_create(struct be_adapter *adapter,
/* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */
req->async_event_bitmap[0] = cpu_to_le32(0x00000022);
+ req->async_event_bitmap[0] |= cpu_to_le32(1 << ASYNC_EVENT_CODE_QNQ);
be_dws_cpu_to_le(ctxt, sizeof(req->context));
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
@@ -1095,15 +1125,14 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
return status;
}
-int be_cmd_txq_create(struct be_adapter *adapter,
- struct be_queue_info *txq,
- struct be_queue_info *cq)
+int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_eth_tx_create *req;
+ struct be_queue_info *txq = &txo->q;
+ struct be_queue_info *cq = &txo->cq;
struct be_dma_mem *q_mem = &txq->dma_mem;
- void *ctxt;
- int status;
+ int status, ver = 0;
spin_lock_bh(&adapter->mcc_lock);
@@ -1114,34 +1143,37 @@ int be_cmd_txq_create(struct be_adapter *adapter,
}
req = embedded_payload(wrb);
- ctxt = &req->context;
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
OPCODE_ETH_TX_CREATE, sizeof(*req), wrb, NULL);
if (lancer_chip(adapter)) {
req->hdr.version = 1;
- AMAP_SET_BITS(struct amap_tx_context, if_id, ctxt,
- adapter->if_handle);
+ req->if_id = cpu_to_le16(adapter->if_handle);
+ } else if (BEx_chip(adapter)) {
+ if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC)
+ req->hdr.version = 2;
+ } else { /* For SH */
+ req->hdr.version = 2;
}
req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
req->ulp_num = BE_ULP1_NUM;
req->type = BE_ETH_TX_RING_TYPE_STANDARD;
-
- AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt,
- be_encoded_q_len(txq->len));
- AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1);
- AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id);
-
- be_dws_cpu_to_le(ctxt, sizeof(req->context));
-
+ req->cq_id = cpu_to_le16(cq->id);
+ req->queue_size = be_encoded_q_len(txq->len);
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+ ver = req->hdr.version;
+
status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb);
txq->id = le16_to_cpu(resp->cid);
+ if (ver == 2)
+ txo->db_offset = le32_to_cpu(resp->db_offset);
+ else
+ txo->db_offset = DB_TXULP1_OFFSET;
txq->created = true;
}
@@ -1834,7 +1866,7 @@ err:
/* Uses mbox */
int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
- u32 *mode, u32 *caps)
+ u32 *mode, u32 *caps, u16 *asic_rev)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_query_fw_cfg *req;
@@ -1855,6 +1887,7 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
*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;
}
mutex_unlock(&adapter->mbox_lock);
@@ -1897,7 +1930,8 @@ int be_cmd_reset_function(struct be_adapter *adapter)
return status;
}
-int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
+int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
+ u32 rss_hash_opts, u16 table_size)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_rss_config *req;
@@ -1916,16 +1950,12 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
req->if_id = cpu_to_le32(adapter->if_handle);
- req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4 |
- RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6);
+ req->enable_rss = cpu_to_le16(rss_hash_opts);
+ req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
- if (lancer_chip(adapter) || skyhawk_chip(adapter)) {
+ if (lancer_chip(adapter) || skyhawk_chip(adapter))
req->hdr.version = 1;
- req->enable_rss |= cpu_to_le16(RSS_ENABLE_UDP_IPV4 |
- RSS_ENABLE_UDP_IPV6);
- }
- req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
memcpy(req->cpu_table, rsstable, table_size);
memcpy(req->hash, myhash, sizeof(myhash));
be_dws_cpu_to_le(req->hash, sizeof(req->hash));
@@ -2343,7 +2373,6 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter,
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_seeprom_read *req;
- struct be_sge *sge;
int status;
spin_lock_bh(&adapter->mcc_lock);
@@ -2354,7 +2383,6 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter,
goto err;
}
req = nonemb_cmd->va;
- sge = nonembedded_sgl(wrb);
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb,
@@ -2461,6 +2489,9 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
struct mgmt_controller_attrib *attribs;
struct be_dma_mem attribs_cmd;
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
attribs_cmd.va = pci_alloc_consistent(adapter->pdev, attribs_cmd.size,
@@ -2468,12 +2499,10 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
if (!attribs_cmd.va) {
dev_err(&adapter->pdev->dev,
"Memory allocation failure\n");
- return -ENOMEM;
+ status = -ENOMEM;
+ goto err;
}
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
-
wrb = wrb_from_mbox(adapter);
if (!wrb) {
status = -EBUSY;
@@ -2493,8 +2522,9 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
err:
mutex_unlock(&adapter->mbox_lock);
- pci_free_consistent(adapter->pdev, attribs_cmd.size, attribs_cmd.va,
- attribs_cmd.dma);
+ if (attribs_cmd.va)
+ pci_free_consistent(adapter->pdev, attribs_cmd.size,
+ attribs_cmd.va, attribs_cmd.dma);
return status;
}
@@ -2667,10 +2697,8 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
cmd.size = sizeof(struct be_cmd_req_set_mac_list);
cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size,
&cmd.dma, GFP_KERNEL);
- if (!cmd.va) {
- dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+ if (!cmd.va)
return -ENOMEM;
- }
spin_lock_bh(&adapter->mcc_lock);
@@ -2794,6 +2822,9 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
CMD_SUBSYSTEM_ETH))
return -EPERM;
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
memset(&cmd, 0, sizeof(struct be_dma_mem));
cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
@@ -2801,12 +2832,10 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
if (!cmd.va) {
dev_err(&adapter->pdev->dev,
"Memory allocation failure\n");
- return -ENOMEM;
+ status = -ENOMEM;
+ goto err;
}
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
-
wrb = wrb_from_mbox(adapter);
if (!wrb) {
status = -EBUSY;
@@ -2837,7 +2866,8 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
}
err:
mutex_unlock(&adapter->mbox_lock);
- pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
+ if (cmd.va)
+ pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
return status;
}
@@ -2942,14 +2972,15 @@ static struct be_nic_resource_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
int i;
for (i = 0; i < desc_count; i++) {
- desc->desc_len = RESOURCE_DESC_SIZE;
+ desc->desc_len = desc->desc_len ? : RESOURCE_DESC_SIZE;
if (((void *)desc + desc->desc_len) >
(void *)(buf + max_buf_size)) {
desc = NULL;
break;
}
- if (desc->desc_type == NIC_RESOURCE_DESC_TYPE_ID)
+ if (desc->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
+ desc->desc_type == NIC_RESOURCE_DESC_TYPE_V1)
break;
desc = (void *)desc + desc->desc_len;
@@ -2969,16 +3000,18 @@ int be_cmd_get_func_config(struct be_adapter *adapter)
int status;
struct be_dma_mem cmd;
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
memset(&cmd, 0, sizeof(struct be_dma_mem));
cmd.size = sizeof(struct be_cmd_resp_get_func_config);
cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
&cmd.dma);
if (!cmd.va) {
dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
- return -ENOMEM;
+ status = -ENOMEM;
+ goto err;
}
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
wrb = wrb_from_mbox(adapter);
if (!wrb) {
@@ -2992,6 +3025,9 @@ int be_cmd_get_func_config(struct be_adapter *adapter)
OPCODE_COMMON_GET_FUNC_CONFIG,
cmd.size, wrb, &cmd);
+ if (skyhawk_chip(adapter))
+ req->hdr.version = 1;
+
status = be_mbox_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_get_func_config *resp = cmd.va;
@@ -3018,28 +3054,46 @@ int be_cmd_get_func_config(struct be_adapter *adapter)
}
err:
mutex_unlock(&adapter->mbox_lock);
- pci_free_consistent(adapter->pdev, cmd.size,
- cmd.va, cmd.dma);
+ if (cmd.va)
+ pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
return status;
}
- /* Uses sync mcc */
-int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
- u8 domain)
+/* Uses mbox */
+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;
- struct be_dma_mem cmd;
- memset(&cmd, 0, sizeof(struct be_dma_mem));
- cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
- cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
- &cmd.dma);
- if (!cmd.va) {
- dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
- return -ENOMEM;
- }
+ 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 */
+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);
@@ -3049,16 +3103,47 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
goto err;
}
- req = cmd.va;
-
+ req = cmd->va;
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_GET_PROFILE_CONFIG,
- cmd.size, wrb, &cmd);
+ 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 */
+int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
+ u16 *txq_count, u8 domain)
+{
+ struct be_queue_info *mccq = &adapter->mcc_obj.q;
+ struct be_dma_mem cmd;
+ int status;
+
+ memset(&cmd, 0, sizeof(struct be_dma_mem));
+ if (!lancer_chip(adapter))
+ cmd.size = sizeof(struct be_cmd_resp_get_profile_config_v1);
+ else
+ cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
+ cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+ &cmd.dma);
+ if (!cmd.va) {
+ dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+ 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);
if (!status) {
struct be_cmd_resp_get_profile_config *resp = cmd.va;
u32 desc_count = le32_to_cpu(resp->desc_count);
@@ -3071,12 +3156,15 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
status = -EINVAL;
goto err;
}
- *cap_flags = le32_to_cpu(desc->cap_flags);
+ if (cap_flags)
+ *cap_flags = le32_to_cpu(desc->cap_flags);
+ if (txq_count)
+ *txq_count = le32_to_cpu(desc->txq_count);
}
err:
- spin_unlock_bh(&adapter->mcc_lock);
- pci_free_consistent(adapter->pdev, cmd.size,
- cmd.va, cmd.dma);
+ if (cmd.va)
+ pci_free_consistent(adapter->pdev, cmd.size,
+ cmd.va, cmd.dma);
return status;
}
@@ -3105,7 +3193,7 @@ int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
req->hdr.domain = domain;
req->desc_count = cpu_to_le32(1);
- req->nic_desc.desc_type = NIC_RESOURCE_DESC_TYPE_ID;
+ req->nic_desc.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
req->nic_desc.desc_len = RESOURCE_DESC_SIZE;
req->nic_desc.flags = (1 << QUN) | (1 << IMM) | (1 << NOSV);
req->nic_desc.pf_num = adapter->pf_number;
@@ -3202,6 +3290,31 @@ err:
return status;
}
+int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_intr_set *req;
+ int status;
+
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
+ wrb = wrb_from_mbox(adapter);
+
+ req = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req),
+ wrb, NULL);
+
+ req->intr_enabled = intr_enable;
+
+ status = be_mbox_notify_wait(adapter);
+
+ mutex_unlock(&adapter->mbox_lock);
+ return status;
+}
+
int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
{