summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/emulex
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r--drivers/net/ethernet/emulex/benet/Makefile2
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h92
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c213
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h104
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c326
-rw-r--r--drivers/net/ethernet/emulex/benet/be_hw.h80
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c590
-rw-r--r--drivers/net/ethernet/emulex/benet/be_roce.c182
-rw-r--r--drivers/net/ethernet/emulex/benet/be_roce.h75
9 files changed, 1311 insertions, 353 deletions
diff --git a/drivers/net/ethernet/emulex/benet/Makefile b/drivers/net/ethernet/emulex/benet/Makefile
index a60cd8051135..1a91b276940d 100644
--- a/drivers/net/ethernet/emulex/benet/Makefile
+++ b/drivers/net/ethernet/emulex/benet/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_BE2NET) += be2net.o
-be2net-y := be_main.o be_cmds.o be_ethtool.o
+be2net-y := be_main.o be_cmds.o be_ethtool.o be_roce.o
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 9576ac002c23..c5c4c0e83bd1 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -32,8 +32,9 @@
#include <linux/u64_stats_sync.h>
#include "be_hw.h"
+#include "be_roce.h"
-#define DRV_VER "4.2.116u"
+#define DRV_VER "4.2.220u"
#define DRV_NAME "be2net"
#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC"
#define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC"
@@ -102,7 +103,8 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
#define MAX_TX_QS 8
-#define MAX_MSIX_VECTORS MAX_RSS_QS
+#define MAX_ROCE_EQS 5
+#define MAX_MSIX_VECTORS (MAX_RSS_QS + MAX_ROCE_EQS) /* RSS qs + RoCE */
#define BE_TX_BUDGET 256
#define BE_NAPI_WEIGHT 64
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
@@ -162,6 +164,11 @@ static inline void queue_head_inc(struct be_queue_info *q)
index_inc(&q->head, q->len);
}
+static inline void index_dec(u16 *index, u16 limit)
+{
+ *index = MODULO((*index - 1), limit);
+}
+
static inline void queue_tail_inc(struct be_queue_info *q)
{
index_inc(&q->tail, q->len);
@@ -308,11 +315,33 @@ struct be_vf_cfg {
u32 tx_rate;
};
+enum vf_state {
+ ENABLED = 0,
+ ASSIGNED = 1
+};
+
#define BE_FLAGS_LINK_STATUS_INIT 1
#define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
#define BE_UC_PMAC_COUNT 30
#define BE_VF_UC_PMAC_COUNT 2
+struct phy_info {
+ u8 transceiver;
+ u8 autoneg;
+ u8 fc_autoneg;
+ u8 port_type;
+ u16 phy_type;
+ u16 interface_type;
+ u32 misc_params;
+ u16 auto_speeds_supported;
+ u16 fixed_speeds_supported;
+ int link_speed;
+ int forced_port_speed;
+ u32 dac_cable_len;
+ u32 advertising;
+ u32 supported;
+};
+
struct be_adapter {
struct pci_dev *pdev;
struct net_device *netdev;
@@ -377,29 +406,41 @@ struct be_adapter {
u32 rx_fc; /* Rx flow control */
u32 tx_fc; /* Tx flow control */
bool stats_cmd_sent;
- int link_speed;
- u8 port_type;
- u8 transceiver;
- u8 autoneg;
u8 generation; /* BladeEngine ASIC generation */
+ u32 if_type;
+ struct {
+ u8 __iomem *base; /* Door Bell */
+ u32 size;
+ u32 total_size;
+ u64 io_addr;
+ } roce_db;
+ u32 num_msix_roce_vec;
+ struct ocrdma_dev *ocrdma_dev;
+ struct list_head entry;
+
u32 flash_status;
struct completion flash_compl;
- u32 num_vfs;
- u8 is_virtfn;
+ u32 num_vfs; /* Number of VFs provisioned by PF driver */
+ u32 dev_num_vfs; /* Number of VFs supported by HW */
+ u8 virtfn;
struct be_vf_cfg *vf_cfg;
bool be3_native;
u32 sli_family;
u8 hba_port_num;
u16 pvid;
+ struct phy_info phy;
u8 wol_cap;
bool wol;
u32 max_pmac_cnt; /* Max secondary UC MACs programmable */
u32 uc_macs; /* Count of secondary UC MAC programmed */
+ u32 msg_enable;
};
-#define be_physfn(adapter) (!adapter->is_virtfn)
+#define be_physfn(adapter) (!adapter->virtfn)
#define sriov_enabled(adapter) (adapter->num_vfs > 0)
+#define sriov_want(adapter) (adapter->dev_num_vfs && num_vfs && \
+ be_physfn(adapter))
#define for_all_vfs(adapter, vf_cfg, i) \
for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \
i++, vf_cfg++)
@@ -413,6 +454,10 @@ struct be_adapter {
#define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \
(adapter->pdev->device == OC_DEVICE_ID4))
+#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \
+ adapter->sli_family == SKYHAWK_SLI_FAMILY) && \
+ (adapter->function_mode & RDMA_ENABLED))
+
extern const struct ethtool_ops be_ethtool_ops;
#define msix_enabled(adapter) (adapter->num_msix_vec > 0)
@@ -528,14 +573,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb)
return val;
}
-static inline void be_check_sriov_fn_type(struct be_adapter *adapter)
-{
- u32 sli_intf;
-
- pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
- adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
-}
-
static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
{
u32 addr;
@@ -577,10 +614,31 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter)
}
}
+static inline bool be_type_2_3(struct be_adapter *adapter)
+{
+ return (adapter->if_type == SLI_INTF_TYPE_2 ||
+ adapter->if_type == SLI_INTF_TYPE_3) ? true : false;
+}
+
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped);
extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
extern void be_parse_stats(struct be_adapter *adapter);
extern int be_load_fw(struct be_adapter *adapter, u8 *func);
extern bool be_is_wol_supported(struct be_adapter *adapter);
+extern bool be_pause_supported(struct be_adapter *adapter);
+extern u32 be_get_fw_log_level(struct be_adapter *adapter);
+
+/*
+ * internal function to initialize-cleanup roce device.
+ */
+extern void be_roce_dev_add(struct be_adapter *);
+extern void be_roce_dev_remove(struct be_adapter *);
+
+/*
+ * internal function to open-close roce device during ifup-ifdown.
+ */
+extern void be_roce_dev_open(struct be_adapter *);
+extern void be_roce_dev_close(struct be_adapter *);
+
#endif /* BE_H */
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 67b030d72df1..921c2082af4c 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -15,6 +15,7 @@
* Costa Mesa, CA 92626
*/
+#include <linux/module.h>
#include "be.h"
#include "be_cmds.h"
@@ -61,10 +62,21 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
compl->flags = 0;
}
+static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
+{
+ unsigned long addr;
+
+ addr = tag1;
+ addr = ((addr << 16) << 16) | tag0;
+ return (void *)addr;
+}
+
static int be_mcc_compl_process(struct be_adapter *adapter,
- struct be_mcc_compl *compl)
+ struct be_mcc_compl *compl)
{
u16 compl_status, extd_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 */
@@ -73,32 +85,36 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
CQE_STATUS_COMPL_MASK;
- if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) ||
- (compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) &&
- (compl->tag1 == CMD_SUBSYSTEM_COMMON)) {
+ resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
+
+ if (resp_hdr) {
+ opcode = resp_hdr->opcode;
+ subsystem = resp_hdr->subsystem;
+ }
+
+ if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
+ (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
+ (subsystem == CMD_SUBSYSTEM_COMMON)) {
adapter->flash_status = compl_status;
complete(&adapter->flash_compl);
}
if (compl_status == MCC_STATUS_SUCCESS) {
- if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) ||
- (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) &&
- (compl->tag1 == CMD_SUBSYSTEM_ETH)) {
+ 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 (compl->tag0 ==
- OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) {
- struct be_mcc_wrb *mcc_wrb =
- queue_index_node(&adapter->mcc_obj.q,
- compl->tag1);
+ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
+ subsystem == CMD_SUBSYSTEM_COMMON) {
struct be_cmd_resp_get_cntl_addnl_attribs *resp =
- embedded_payload(mcc_wrb);
+ (void *)resp_hdr;
adapter->drv_stats.be_on_die_temperature =
resp->on_die_temperature;
}
} else {
- if (compl->tag0 == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
+ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
be_get_temp_freq = 0;
if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
@@ -106,15 +122,15 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
goto done;
if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
- dev_warn(&adapter->pdev->dev, "This domain(VM) is not "
- "permitted to execute this cmd (opcode %d)\n",
- compl->tag0);
+ dev_warn(&adapter->pdev->dev,
+ "opcode %d-%d is not permitted\n",
+ opcode, subsystem);
} else {
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
CQE_STATUS_EXTD_MASK;
- dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:"
- "status %d, extd-status %d\n",
- compl->tag0, compl_status, extd_status);
+ dev_err(&adapter->pdev->dev,
+ "opcode %d-%d failed:status %d-%d\n",
+ opcode, subsystem, compl_status, extd_status);
}
}
done:
@@ -126,7 +142,7 @@ static void be_async_link_state_process(struct be_adapter *adapter,
struct be_async_event_link_state *evt)
{
/* When link status changes, link speed must be re-queried from FW */
- adapter->link_speed = -1;
+ adapter->phy.link_speed = -1;
/* For the initial link status do not rely on the ASYNC event as
* it may not be received in some cases.
@@ -153,7 +169,7 @@ static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
{
if (evt->physical_port == adapter->port_num) {
/* qos_link_speed is in units of 10 Mbps */
- adapter->link_speed = evt->qos_link_speed * 10;
+ adapter->phy.link_speed = evt->qos_link_speed * 10;
}
}
@@ -286,7 +302,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
if (i == mcc_timeout) {
dev_err(&adapter->pdev->dev, "FW not responding\n");
adapter->fw_timeout = true;
- return -1;
+ return -EIO;
}
return status;
}
@@ -294,8 +310,26 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
/* Notify MCC requests and wait for completion */
static int be_mcc_notify_wait(struct be_adapter *adapter)
{
+ int status;
+ struct be_mcc_wrb *wrb;
+ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
+ u16 index = mcc_obj->q.head;
+ struct be_cmd_resp_hdr *resp;
+
+ index_dec(&index, mcc_obj->q.len);
+ wrb = queue_index_node(&mcc_obj->q, index);
+
+ resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
+
be_mcc_notify(adapter);
- return be_mcc_wait_compl(adapter);
+
+ status = be_mcc_wait_compl(adapter);
+ if (status == -EIO)
+ goto out;
+
+ status = resp->status;
+out:
+ return status;
}
static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
@@ -435,14 +469,17 @@ static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
struct be_mcc_wrb *wrb, struct be_dma_mem *mem)
{
struct be_sge *sge;
+ unsigned long addr = (unsigned long)req_hdr;
+ u64 req_addr = addr;
req_hdr->opcode = opcode;
req_hdr->subsystem = subsystem;
req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
req_hdr->version = 0;
- wrb->tag0 = opcode;
- wrb->tag1 = subsystem;
+ wrb->tag0 = req_addr & 0xFFFFFFFF;
+ wrb->tag1 = upper_32_bits(req_addr);
+
wrb->payload_length = cmd_len;
if (mem) {
wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
@@ -1221,7 +1258,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, wrb,
nonemb_cmd);
- req->cmd_params.params.pport_num = cpu_to_le16(adapter->port_num);
+ req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num);
req->cmd_params.params.reset_stats = 0;
be_mcc_notify(adapter);
@@ -1283,13 +1320,10 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_cntl_addnl_attribs *req;
- u16 mccq_index;
int status;
spin_lock_bh(&adapter->mcc_lock);
- mccq_index = adapter->mcc_obj.q.head;
-
wrb = wrb_from_mccq(adapter);
if (!wrb) {
status = -EBUSY;
@@ -1301,8 +1335,6 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req),
wrb, NULL);
- wrb->tag1 = mccq_index;
-
be_mcc_notify(adapter);
err:
@@ -1824,18 +1856,16 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
spin_unlock_bh(&adapter->mcc_lock);
if (!wait_for_completion_timeout(&adapter->flash_compl,
- msecs_to_jiffies(12000)))
+ msecs_to_jiffies(30000)))
status = -1;
else
status = adapter->flash_status;
resp = embedded_payload(wrb);
- if (!status) {
+ if (!status)
*data_written = le32_to_cpu(resp->actual_write_len);
- } else {
+ else
*addn_status = resp->additional_status;
- status = resp->status;
- }
return status;
@@ -1950,7 +1980,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL);
- req->params.op_type = cpu_to_le32(IMG_TYPE_REDBOOT);
+ req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
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);
@@ -2136,8 +2166,7 @@ err:
return status;
}
-int be_cmd_get_phy_info(struct be_adapter *adapter,
- struct be_phy_info *phy_info)
+int be_cmd_get_phy_info(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_phy_info *req;
@@ -2170,9 +2199,15 @@ int be_cmd_get_phy_info(struct be_adapter *adapter,
if (!status) {
struct be_phy_info *resp_phy_info =
cmd.va + sizeof(struct be_cmd_req_hdr);
- phy_info->phy_type = le16_to_cpu(resp_phy_info->phy_type);
- phy_info->interface_type =
+ adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type);
+ adapter->phy.interface_type =
le16_to_cpu(resp_phy_info->interface_type);
+ adapter->phy.auto_speeds_supported =
+ le16_to_cpu(resp_phy_info->auto_speeds_supported);
+ adapter->phy.fixed_speeds_supported =
+ le16_to_cpu(resp_phy_info->fixed_speeds_supported);
+ adapter->phy.misc_params =
+ le32_to_cpu(resp_phy_info->misc_params);
}
pci_free_consistent(adapter->pdev, cmd.size,
cmd.va, cmd.dma);
@@ -2555,4 +2590,98 @@ err:
mutex_unlock(&adapter->mbox_lock);
pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
return status;
+
+}
+int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_get_ext_fat_caps *req;
+ int status;
+
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
+ wrb = wrb_from_mbox(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = cmd->va;
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_EXT_FAT_CAPABILITES,
+ cmd->size, wrb, cmd);
+ req->parameter_type = cpu_to_le32(1);
+
+ status = be_mbox_notify_wait(adapter);
+err:
+ mutex_unlock(&adapter->mbox_lock);
+ return status;
+}
+
+int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd,
+ struct be_fat_conf_params *configs)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_set_ext_fat_caps *req;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = cmd->va;
+ memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_SET_EXT_FAT_CAPABILITES,
+ cmd->size, wrb, cmd);
+
+ status = be_mcc_notify_wait(adapter);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+
+int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
+ int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
+{
+ struct be_adapter *adapter = netdev_priv(netdev_handle);
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *) wrb_payload;
+ struct be_cmd_req_hdr *req;
+ struct be_cmd_resp_hdr *resp;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+ req = embedded_payload(wrb);
+ resp = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
+ hdr->opcode, wrb_payload_size, wrb, NULL);
+ memcpy(req, wrb_payload, wrb_payload_size);
+ be_dws_cpu_to_le(req, wrb_payload_size);
+
+ status = be_mcc_notify_wait(adapter);
+ if (cmd_status)
+ *cmd_status = (status & 0xffff);
+ if (ext_status)
+ *ext_status = 0;
+ memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
+ be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
}
+EXPORT_SYMBOL(be_roce_mcc_cmd);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index d5b680c56af0..b3f3fc3d1323 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -189,6 +189,8 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_GET_PHY_DETAILS 102
#define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103
#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121
+#define OPCODE_COMMON_GET_EXT_FAT_CAPABILITES 125
+#define OPCODE_COMMON_SET_EXT_FAT_CAPABILITES 126
#define OPCODE_COMMON_GET_MAC_LIST 147
#define OPCODE_COMMON_SET_MAC_LIST 148
#define OPCODE_COMMON_GET_HSW_CONFIG 152
@@ -225,8 +227,12 @@ struct be_cmd_req_hdr {
#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */
#define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */
struct be_cmd_resp_hdr {
- u32 info; /* dword 0 */
- u32 status; /* dword 1 */
+ u8 opcode; /* dword 0 */
+ u8 subsystem; /* dword 0 */
+ u8 rsvd[2]; /* dword 0 */
+ u8 status; /* dword 1 */
+ u8 add_status; /* dword 1 */
+ u8 rsvd1[2]; /* dword 1 */
u32 response_length; /* dword 2 */
u32 actual_resp_len; /* dword 3 */
};
@@ -1056,6 +1062,7 @@ struct be_cmd_resp_modify_eq_delay {
/* The HW can come up in either of the following multi-channel modes
* based on the skew/IPL.
*/
+#define RDMA_ENABLED 0x4
#define FLEX10_MODE 0x400
#define VNIC_MODE 0x20000
#define UMC_ENABLED 0x1000000
@@ -1309,9 +1316,36 @@ enum {
PHY_TYPE_KX4_10GB,
PHY_TYPE_BASET_10GB,
PHY_TYPE_BASET_1GB,
+ PHY_TYPE_BASEX_1GB,
+ PHY_TYPE_SGMII,
PHY_TYPE_DISABLED = 255
};
+#define BE_SUPPORTED_SPEED_NONE 0
+#define BE_SUPPORTED_SPEED_10MBPS 1
+#define BE_SUPPORTED_SPEED_100MBPS 2
+#define BE_SUPPORTED_SPEED_1GBPS 4
+#define BE_SUPPORTED_SPEED_10GBPS 8
+
+#define BE_AN_EN 0x2
+#define BE_PAUSE_SYM_EN 0x80
+
+/* MAC speed valid values */
+#define SPEED_DEFAULT 0x0
+#define SPEED_FORCED_10GB 0x1
+#define SPEED_FORCED_1GB 0x2
+#define SPEED_AUTONEG_10GB 0x3
+#define SPEED_AUTONEG_1GB 0x4
+#define SPEED_AUTONEG_100MB 0x5
+#define SPEED_AUTONEG_10GB_1GB 0x6
+#define SPEED_AUTONEG_10GB_1GB_100MB 0x7
+#define SPEED_AUTONEG_1GB_100MB 0x8
+#define SPEED_AUTONEG_10MB 0x9
+#define SPEED_AUTONEG_1GB_100MB_10MB 0xa
+#define SPEED_AUTONEG_100MB_10MB 0xb
+#define SPEED_FORCED_100MB 0xc
+#define SPEED_FORCED_10MB 0xd
+
struct be_cmd_req_get_phy_info {
struct be_cmd_req_hdr hdr;
u8 rsvd0[24];
@@ -1321,7 +1355,11 @@ struct be_phy_info {
u16 phy_type;
u16 interface_type;
u32 misc_params;
- u32 future_use[4];
+ u16 ext_phy_details;
+ u16 rsvd;
+ u16 auto_speeds_supported;
+ u16 fixed_speeds_supported;
+ u32 future_use[2];
};
struct be_cmd_resp_get_phy_info {
@@ -1528,7 +1566,7 @@ struct be_hw_stats_v1 {
u32 rsvd0[BE_TXP_SW_SZ];
struct be_erx_stats_v1 erx;
struct be_pmem_stats pmem;
- u32 rsvd1[3];
+ u32 rsvd1[18];
};
struct be_cmd_req_get_stats_v1 {
@@ -1567,6 +1605,56 @@ static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
}
}
+
+/************** get fat capabilites *******************/
+#define MAX_MODULES 27
+#define MAX_MODES 4
+#define MODE_UART 0
+#define FW_LOG_LEVEL_DEFAULT 48
+#define FW_LOG_LEVEL_FATAL 64
+
+struct ext_fat_mode {
+ u8 mode;
+ u8 rsvd0;
+ u16 port_mask;
+ u32 dbg_lvl;
+ u64 fun_mask;
+} __packed;
+
+struct ext_fat_modules {
+ u8 modules_str[32];
+ u32 modules_id;
+ u32 num_modes;
+ struct ext_fat_mode trace_lvl[MAX_MODES];
+} __packed;
+
+struct be_fat_conf_params {
+ u32 max_log_entries;
+ u32 log_entry_size;
+ u8 log_type;
+ u8 max_log_funs;
+ u8 max_log_ports;
+ u8 rsvd0;
+ u32 supp_modes;
+ u32 num_modules;
+ struct ext_fat_modules module[MAX_MODULES];
+} __packed;
+
+struct be_cmd_req_get_ext_fat_caps {
+ struct be_cmd_req_hdr hdr;
+ u32 parameter_type;
+};
+
+struct be_cmd_resp_get_ext_fat_caps {
+ struct be_cmd_resp_hdr hdr;
+ struct be_fat_conf_params get_params;
+};
+
+struct be_cmd_req_set_ext_fat_caps {
+ struct be_cmd_req_hdr hdr;
+ struct be_fat_conf_params set_params;
+};
+
extern int be_pci_fnum_get(struct be_adapter *adapter);
extern int be_cmd_POST(struct be_adapter *adapter);
extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -1655,8 +1743,7 @@ extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
struct be_dma_mem *nonemb_cmd);
extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
u8 loopback_type, u8 enable);
-extern int be_cmd_get_phy_info(struct be_adapter *adapter,
- struct be_phy_info *phy_info);
+extern int be_cmd_get_phy_info(struct be_adapter *adapter);
extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
extern void be_detect_dump_ue(struct be_adapter *adapter);
extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
@@ -1673,4 +1760,9 @@ extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
u32 domain, u16 intf_id);
extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
+extern int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd);
+extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd,
+ struct be_fat_conf_params *cfgs);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index c1ff73cb0e62..63e51d476900 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -433,102 +433,193 @@ static int be_get_sset_count(struct net_device *netdev, int stringset)
}
}
+static u32 be_get_port_type(u32 phy_type, u32 dac_cable_len)
+{
+ u32 port;
+
+ switch (phy_type) {
+ case PHY_TYPE_BASET_1GB:
+ case PHY_TYPE_BASEX_1GB:
+ case PHY_TYPE_SGMII:
+ port = PORT_TP;
+ break;
+ case PHY_TYPE_SFP_PLUS_10GB:
+ port = dac_cable_len ? PORT_DA : PORT_FIBRE;
+ break;
+ case PHY_TYPE_XFP_10GB:
+ case PHY_TYPE_SFP_1GB:
+ port = PORT_FIBRE;
+ break;
+ case PHY_TYPE_BASET_10GB:
+ port = PORT_TP;
+ break;
+ default:
+ port = PORT_OTHER;
+ }
+
+ return port;
+}
+
+static u32 convert_to_et_setting(u32 if_type, u32 if_speeds)
+{
+ u32 val = 0;
+
+ switch (if_type) {
+ case PHY_TYPE_BASET_1GB:
+ case PHY_TYPE_BASEX_1GB:
+ case PHY_TYPE_SGMII:
+ val |= SUPPORTED_TP;
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
+ val |= SUPPORTED_1000baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS)
+ val |= SUPPORTED_100baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_10MBPS)
+ val |= SUPPORTED_10baseT_Full;
+ break;
+ case PHY_TYPE_KX4_10GB:
+ val |= SUPPORTED_Backplane;
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
+ val |= SUPPORTED_1000baseKX_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)
+ val |= SUPPORTED_10000baseKX4_Full;
+ break;
+ case PHY_TYPE_KR_10GB:
+ val |= SUPPORTED_Backplane |
+ SUPPORTED_10000baseKR_Full;
+ break;
+ case PHY_TYPE_SFP_PLUS_10GB:
+ case PHY_TYPE_XFP_10GB:
+ case PHY_TYPE_SFP_1GB:
+ val |= SUPPORTED_FIBRE;
+ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)
+ val |= SUPPORTED_10000baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
+ val |= SUPPORTED_1000baseT_Full;
+ break;
+ case PHY_TYPE_BASET_10GB:
+ val |= SUPPORTED_TP;
+ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)
+ val |= SUPPORTED_10000baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
+ val |= SUPPORTED_1000baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS)
+ val |= SUPPORTED_100baseT_Full;
+ break;
+ default:
+ val |= SUPPORTED_TP;
+ }
+
+ return val;
+}
+
+static int convert_to_et_speed(u32 be_speed)
+{
+ int et_speed = SPEED_10000;
+
+ switch (be_speed) {
+ case PHY_LINK_SPEED_10MBPS:
+ et_speed = SPEED_10;
+ break;
+ case PHY_LINK_SPEED_100MBPS:
+ et_speed = SPEED_100;
+ break;
+ case PHY_LINK_SPEED_1GBPS:
+ et_speed = SPEED_1000;
+ break;
+ case PHY_LINK_SPEED_10GBPS:
+ et_speed = SPEED_10000;
+ break;
+ }
+
+ return et_speed;
+}
+
+bool be_pause_supported(struct be_adapter *adapter)
+{
+ return (adapter->phy.interface_type == PHY_TYPE_SFP_PLUS_10GB ||
+ adapter->phy.interface_type == PHY_TYPE_XFP_10GB) ?
+ false : true;
+}
+
static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_phy_info phy_info;
- u8 mac_speed = 0;
+ u8 port_speed = 0;
u16 link_speed = 0;
u8 link_status;
+ u32 et_speed = 0;
int status;
- if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
- status = be_cmd_link_status_query(adapter, &mac_speed,
- &link_speed, &link_status, 0);
- if (!status)
- be_link_status_update(adapter, link_status);
-
- /* link_speed is in units of 10 Mbps */
- if (link_speed) {
- ethtool_cmd_speed_set(ecmd, link_speed*10);
+ if (adapter->phy.link_speed < 0 || !(netdev->flags & IFF_UP)) {
+ if (adapter->phy.forced_port_speed < 0) {
+ status = be_cmd_link_status_query(adapter, &port_speed,
+ &link_speed, &link_status, 0);
+ if (!status)
+ be_link_status_update(adapter, link_status);
+ if (link_speed)
+ et_speed = link_speed * 10;
+ else if (link_status)
+ et_speed = convert_to_et_speed(port_speed);
} else {
- switch (mac_speed) {
- case PHY_LINK_SPEED_10MBPS:
- ethtool_cmd_speed_set(ecmd, SPEED_10);
- break;
- case PHY_LINK_SPEED_100MBPS:
- ethtool_cmd_speed_set(ecmd, SPEED_100);
- break;
- case PHY_LINK_SPEED_1GBPS:
- ethtool_cmd_speed_set(ecmd, SPEED_1000);
- break;
- case PHY_LINK_SPEED_10GBPS:
- ethtool_cmd_speed_set(ecmd, SPEED_10000);
- break;
- case PHY_LINK_SPEED_ZERO:
- ethtool_cmd_speed_set(ecmd, 0);
- break;
- }
+ et_speed = adapter->phy.forced_port_speed;
}
- status = be_cmd_get_phy_info(adapter, &phy_info);
- if (!status) {
- switch (phy_info.interface_type) {
- case PHY_TYPE_XFP_10GB:
- case PHY_TYPE_SFP_1GB:
- case PHY_TYPE_SFP_PLUS_10GB:
- ecmd->port = PORT_FIBRE;
- break;
- default:
- ecmd->port = PORT_TP;
- break;
- }
+ ethtool_cmd_speed_set(ecmd, et_speed);
+
+ status = be_cmd_get_phy_info(adapter);
+ if (status)
+ return status;
+
+ ecmd->supported =
+ convert_to_et_setting(adapter->phy.interface_type,
+ adapter->phy.auto_speeds_supported |
+ adapter->phy.fixed_speeds_supported);
+ ecmd->advertising =
+ convert_to_et_setting(adapter->phy.interface_type,
+ adapter->phy.auto_speeds_supported);
+
+ ecmd->port = be_get_port_type(adapter->phy.interface_type,
+ adapter->phy.dac_cable_len);
+
+ if (adapter->phy.auto_speeds_supported) {
+ ecmd->supported |= SUPPORTED_Autoneg;
+ ecmd->autoneg = AUTONEG_ENABLE;
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ }
- switch (phy_info.interface_type) {
- case PHY_TYPE_KR_10GB:
- case PHY_TYPE_KX4_10GB:
- ecmd->autoneg = AUTONEG_ENABLE;
+ if (be_pause_supported(adapter)) {
+ ecmd->supported |= SUPPORTED_Pause;
+ ecmd->advertising |= ADVERTISED_Pause;
+ }
+
+ switch (adapter->phy.interface_type) {
+ case PHY_TYPE_KR_10GB:
+ case PHY_TYPE_KX4_10GB:
ecmd->transceiver = XCVR_INTERNAL;
- break;
- default:
- ecmd->autoneg = AUTONEG_DISABLE;
- ecmd->transceiver = XCVR_EXTERNAL;
- break;
- }
+ break;
+ default:
+ ecmd->transceiver = XCVR_EXTERNAL;
+ break;
}
/* Save for future use */
- adapter->link_speed = ethtool_cmd_speed(ecmd);
- adapter->port_type = ecmd->port;
- adapter->transceiver = ecmd->transceiver;
- adapter->autoneg = ecmd->autoneg;
+ adapter->phy.link_speed = ethtool_cmd_speed(ecmd);
+ adapter->phy.port_type = ecmd->port;
+ adapter->phy.transceiver = ecmd->transceiver;
+ adapter->phy.autoneg = ecmd->autoneg;
+ adapter->phy.advertising = ecmd->advertising;
+ adapter->phy.supported = ecmd->supported;
} else {
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
- ecmd->port = adapter->port_type;
- ecmd->transceiver = adapter->transceiver;
- ecmd->autoneg = adapter->autoneg;
+ ethtool_cmd_speed_set(ecmd, adapter->phy.link_speed);
+ ecmd->port = adapter->phy.port_type;
+ ecmd->transceiver = adapter->phy.transceiver;
+ ecmd->autoneg = adapter->phy.autoneg;
+ ecmd->advertising = adapter->phy.advertising;
+ ecmd->supported = adapter->phy.supported;
}
- ecmd->duplex = DUPLEX_FULL;
+ ecmd->duplex = netif_carrier_ok(netdev) ? DUPLEX_FULL : DUPLEX_UNKNOWN;
ecmd->phy_address = adapter->port_num;
- switch (ecmd->port) {
- case PORT_FIBRE:
- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
- break;
- case PORT_TP:
- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP);
- break;
- case PORT_AUI:
- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI);
- break;
- }
-
- if (ecmd->autoneg) {
- ecmd->supported |= SUPPORTED_1000baseT_Full;
- ecmd->supported |= SUPPORTED_Autoneg;
- ecmd->advertising |= (ADVERTISED_10000baseT_Full |
- ADVERTISED_1000baseT_Full);
- }
return 0;
}
@@ -548,7 +639,7 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
struct be_adapter *adapter = netdev_priv(netdev);
be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause);
- ecmd->autoneg = 0;
+ ecmd->autoneg = adapter->phy.fc_autoneg;
}
static int
@@ -702,7 +793,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
}
}
- if (be_test_ddr_dma(adapter) != 0) {
+ if (!lancer_chip(adapter) && be_test_ddr_dma(adapter) != 0) {
data[3] = 1;
test->flags |= ETH_TEST_FL_FAILED;
}
@@ -787,6 +878,81 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
return status;
}
+static u32 be_get_msg_level(struct net_device *netdev)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+
+ if (lancer_chip(adapter)) {
+ dev_err(&adapter->pdev->dev, "Operation not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ return adapter->msg_enable;
+}
+
+static void be_set_fw_log_level(struct be_adapter *adapter, u32 level)
+{
+ struct be_dma_mem extfat_cmd;
+ struct be_fat_conf_params *cfgs;
+ int status;
+ int i, j;
+
+ memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
+ extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
+ extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
+ &extfat_cmd.dma);
+ if (!extfat_cmd.va) {
+ dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
+ __func__);
+ goto err;
+ }
+ status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
+ if (!status) {
+ cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
+ sizeof(struct be_cmd_resp_hdr));
+ for (i = 0; i < cfgs->num_modules; i++) {
+ for (j = 0; j < cfgs->module[i].num_modes; j++) {
+ if (cfgs->module[i].trace_lvl[j].mode ==
+ MODE_UART)
+ cfgs->module[i].trace_lvl[j].dbg_lvl =
+ cpu_to_le32(level);
+ }
+ }
+ status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd,
+ cfgs);
+ if (status)
+ dev_err(&adapter->pdev->dev,
+ "Message level set failed\n");
+ } else {
+ dev_err(&adapter->pdev->dev, "Message level get failed\n");
+ }
+
+ pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
+ extfat_cmd.dma);
+err:
+ return;
+}
+
+static void be_set_msg_level(struct net_device *netdev, u32 level)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+
+ if (lancer_chip(adapter)) {
+ dev_err(&adapter->pdev->dev, "Operation not supported\n");
+ return;
+ }
+
+ if (adapter->msg_enable == level)
+ return;
+
+ if ((level & NETIF_MSG_HW) != (adapter->msg_enable & NETIF_MSG_HW))
+ be_set_fw_log_level(adapter, level & NETIF_MSG_HW ?
+ FW_LOG_LEVEL_DEFAULT : FW_LOG_LEVEL_FATAL);
+ adapter->msg_enable = level;
+
+ return;
+}
+
const struct ethtool_ops be_ethtool_ops = {
.get_settings = be_get_settings,
.get_drvinfo = be_get_drvinfo,
@@ -802,6 +968,8 @@ const struct ethtool_ops be_ethtool_ops = {
.set_pauseparam = be_set_pauseparam,
.get_strings = be_get_stat_strings,
.set_phys_id = be_set_phys_id,
+ .get_msglevel = be_get_msg_level,
+ .set_msglevel = be_set_msg_level,
.get_sset_count = be_get_sset_count,
.get_ethtool_stats = be_get_ethtool_stats,
.get_regs_len = be_get_reg_len,
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index f2c89e3ccabd..d9fb0c501fa1 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -58,6 +58,8 @@
#define SLI_PORT_CONTROL_IP_MASK 0x08000000
+#define PCICFG_CUST_SCRATCHPAD_CSR 0x1EC
+
/********* Memory BAR register ************/
#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc
/* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
@@ -98,11 +100,13 @@
#define SLI_INTF_REV_SHIFT 4
#define SLI_INTF_FT_MASK 0x00000001
+#define SLI_INTF_TYPE_2 2
+#define SLI_INTF_TYPE_3 3
/* SLI family */
#define BE_SLI_FAMILY 0x0
#define LANCER_A0_SLI_FAMILY 0xA
-
+#define SKYHAWK_SLI_FAMILY 0x2
/********* ISR0 Register offset **********/
#define CEV_ISR0_OFFSET 0xC18
@@ -162,22 +166,23 @@
#define QUERY_FAT 1
/* Flashrom related descriptors */
+#define MAX_FLASH_COMP 32
#define IMAGE_TYPE_FIRMWARE 160
#define IMAGE_TYPE_BOOTCODE 224
#define IMAGE_TYPE_OPTIONROM 32
#define NUM_FLASHDIR_ENTRIES 32
-#define IMG_TYPE_ISCSI_ACTIVE 0
-#define IMG_TYPE_REDBOOT 1
-#define IMG_TYPE_BIOS 2
-#define IMG_TYPE_PXE_BIOS 3
-#define IMG_TYPE_FCOE_BIOS 8
-#define IMG_TYPE_ISCSI_BACKUP 9
-#define IMG_TYPE_FCOE_FW_ACTIVE 10
-#define IMG_TYPE_FCOE_FW_BACKUP 11
-#define IMG_TYPE_NCSI_FW 13
-#define IMG_TYPE_PHY_FW 99
+#define OPTYPE_ISCSI_ACTIVE 0
+#define OPTYPE_REDBOOT 1
+#define OPTYPE_BIOS 2
+#define OPTYPE_PXE_BIOS 3
+#define OPTYPE_FCOE_BIOS 8
+#define OPTYPE_ISCSI_BACKUP 9
+#define OPTYPE_FCOE_FW_ACTIVE 10
+#define OPTYPE_FCOE_FW_BACKUP 11
+#define OPTYPE_NCSI_FW 13
+#define OPTYPE_PHY_FW 99
#define TN_8022 13
#define ILLEGAL_IOCTL_REQ 2
@@ -223,6 +228,24 @@
#define FLASH_REDBOOT_START_g3 (262144)
#define FLASH_PHY_FW_START_g3 1310720
+#define IMAGE_NCSI 16
+#define IMAGE_OPTION_ROM_PXE 32
+#define IMAGE_OPTION_ROM_FCoE 33
+#define IMAGE_OPTION_ROM_ISCSI 34
+#define IMAGE_FLASHISM_JUMPVECTOR 48
+#define IMAGE_FLASH_ISM 49
+#define IMAGE_JUMP_VECTOR 50
+#define IMAGE_FIRMWARE_iSCSI 160
+#define IMAGE_FIRMWARE_COMP_iSCSI 161
+#define IMAGE_FIRMWARE_FCoE 162
+#define IMAGE_FIRMWARE_COMP_FCoE 163
+#define IMAGE_FIRMWARE_BACKUP_iSCSI 176
+#define IMAGE_FIRMWARE_BACKUP_COMP_iSCSI 177
+#define IMAGE_FIRMWARE_BACKUP_FCoE 178
+#define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179
+#define IMAGE_FIRMWARE_PHY 192
+#define IMAGE_BOOT_CODE 224
+
/************* Rx Packet Type Encoding **************/
#define BE_UNICAST_PACKET 0
#define BE_MULTICAST_PACKET 1
@@ -445,6 +468,7 @@ struct flash_comp {
unsigned long offset;
int optype;
int size;
+ int img_type;
};
struct image_hdr {
@@ -481,17 +505,19 @@ struct flash_section_hdr {
u32 format_rev;
u32 cksum;
u32 antidote;
- u32 build_no;
- u8 id_string[64];
- u32 active_entry_mask;
- u32 valid_entry_mask;
- u32 org_content_mask;
- u32 rsvd0;
- u32 rsvd1;
- u32 rsvd2;
- u32 rsvd3;
- u32 rsvd4;
-};
+ u32 num_images;
+ u8 id_string[128];
+ u32 rsvd[4];
+} __packed;
+
+struct flash_section_hdr_g2 {
+ u32 format_rev;
+ u32 cksum;
+ u32 antidote;
+ u32 build_num;
+ u8 id_string[128];
+ u32 rsvd[8];
+} __packed;
struct flash_section_entry {
u32 type;
@@ -503,10 +529,16 @@ struct flash_section_entry {
u32 rsvd0;
u32 rsvd1;
u8 ver_data[32];
-};
+} __packed;
struct flash_section_info {
u8 cookie[32];
struct flash_section_hdr fsec_hdr;
struct flash_section_entry fsec_entry[32];
-};
+} __packed;
+
+struct flash_section_info_g2 {
+ u8 cookie[32];
+ struct flash_section_hdr_g2 fsec_hdr;
+ struct flash_section_entry fsec_entry[32];
+} __packed;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 528a886bc2cd..501dfa9c88ec 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -421,6 +421,9 @@ void be_parse_stats(struct be_adapter *adapter)
populate_be2_stats(adapter);
}
+ if (lancer_chip(adapter))
+ goto done;
+
/* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */
for_all_rx_queues(adapter, rxo, i) {
/* below erx HW counter can actually wrap around after
@@ -429,6 +432,8 @@ void be_parse_stats(struct be_adapter *adapter)
accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
(u16)erx->rx_drops_no_fragments[rxo->q.id]);
}
+done:
+ return;
}
static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
@@ -731,6 +736,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb);
if (copied) {
+ int gso_segs = skb_shinfo(skb)->gso_segs;
+
/* record the sent skb in the sent_skb table */
BUG_ON(txo->sent_skb_list[start]);
txo->sent_skb_list[start] = skb;
@@ -748,8 +755,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
be_txq_notify(adapter, txq->id, wrb_cnt);
- be_tx_stats_update(txo, wrb_cnt, copied,
- skb_shinfo(skb)->gso_segs, stopped);
+ be_tx_stats_update(txo, wrb_cnt, copied, gso_segs, stopped);
} else {
txq->head = start;
dev_kfree_skb_any(skb);
@@ -797,22 +803,30 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
if (adapter->promiscuous)
return 0;
- if (adapter->vlans_added <= adapter->max_vlans) {
- /* Construct VLAN Table to give to HW */
- for (i = 0; i < VLAN_N_VID; i++) {
- if (adapter->vlan_tag[i]) {
- vtag[ntags] = cpu_to_le16(i);
- ntags++;
- }
- }
- status = be_cmd_vlan_config(adapter, adapter->if_handle,
- vtag, ntags, 1, 0);
- } else {
- status = be_cmd_vlan_config(adapter, adapter->if_handle,
- NULL, 0, 1, 1);
+ if (adapter->vlans_added > adapter->max_vlans)
+ goto set_vlan_promisc;
+
+ /* Construct VLAN Table to give to HW */
+ for (i = 0; i < VLAN_N_VID; i++)
+ if (adapter->vlan_tag[i])
+ vtag[ntags++] = cpu_to_le16(i);
+
+ status = be_cmd_vlan_config(adapter, adapter->if_handle,
+ vtag, ntags, 1, 0);
+
+ /* Set to VLAN promisc mode as setting VLAN filter failed */
+ if (status) {
+ dev_info(&adapter->pdev->dev, "Exhausted VLAN HW filters.\n");
+ dev_info(&adapter->pdev->dev, "Disabling HW VLAN filtering.\n");
+ goto set_vlan_promisc;
}
return status;
+
+set_vlan_promisc:
+ status = be_cmd_vlan_config(adapter, adapter->if_handle,
+ NULL, 0, 1, 1);
+ return status;
}
static int be_vlan_add_vid(struct net_device *netdev, u16 vid)
@@ -862,6 +876,7 @@ ret:
static void be_set_rx_mode(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
+ int status;
if (netdev->flags & IFF_PROMISC) {
be_cmd_rx_filter(adapter, IFF_PROMISC, ON);
@@ -908,7 +923,14 @@ static void be_set_rx_mode(struct net_device *netdev)
}
}
- be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
+ status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
+
+ /* Set to MCAST promisc mode if setting MULTICAST address fails */
+ if (status) {
+ dev_info(&adapter->pdev->dev, "Exhausted multicast HW filters.\n");
+ dev_info(&adapter->pdev->dev, "Disabling HW multicast filtering.\n");
+ be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
+ }
done:
return;
}
@@ -1028,6 +1050,29 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
return status;
}
+static int be_find_vfs(struct be_adapter *adapter, int vf_state)
+{
+ struct pci_dev *dev, *pdev = adapter->pdev;
+ int vfs = 0, assigned_vfs = 0, pos, vf_fn;
+ u16 offset, stride;
+
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_OFFSET, &offset);
+ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_STRIDE, &stride);
+
+ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, NULL);
+ while (dev) {
+ vf_fn = (pdev->devfn + offset + stride * vfs) & 0xFFFF;
+ if (dev->is_virtfn && dev->devfn == vf_fn) {
+ vfs++;
+ if (dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED)
+ assigned_vfs++;
+ }
+ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, dev);
+ }
+ return (vf_state == ASSIGNED) ? assigned_vfs : vfs;
+}
+
static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo)
{
struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]);
@@ -1238,6 +1283,7 @@ static void be_rx_compl_process(struct be_rx_obj *rxo,
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, netdev);
+ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
if (netdev->features & NETIF_F_RXHASH)
skb->rxhash = rxcp->rss_hash;
@@ -1294,6 +1340,7 @@ void be_rx_compl_process_gro(struct be_rx_obj *rxo, struct napi_struct *napi,
skb->len = rxcp->pkt_size;
skb->data_len = rxcp->pkt_size;
skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
if (adapter->netdev->features & NETIF_F_RXHASH)
skb->rxhash = rxcp->rss_hash;
@@ -1555,7 +1602,9 @@ static int event_handle(struct be_eq_obj *eqo)
if (!num)
rearm = true;
- be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
+ if (num || msix_enabled(eqo->adapter))
+ be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
+
if (num)
napi_schedule(&eqo->napi);
@@ -1764,9 +1813,9 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
static int be_num_txqs_want(struct be_adapter *adapter)
{
- if (sriov_enabled(adapter) || be_is_mc(adapter) ||
- lancer_chip(adapter) || !be_physfn(adapter) ||
- adapter->generation == BE_GEN2)
+ if (sriov_want(adapter) || be_is_mc(adapter) ||
+ lancer_chip(adapter) || !be_physfn(adapter) ||
+ adapter->generation == BE_GEN2)
return 1;
else
return MAX_TX_QS;
@@ -2093,7 +2142,7 @@ static void be_msix_disable(struct be_adapter *adapter)
static uint be_num_rss_want(struct be_adapter *adapter)
{
if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
- adapter->num_vfs == 0 && be_physfn(adapter) &&
+ !sriov_want(adapter) && be_physfn(adapter) &&
!be_is_mc(adapter))
return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
else
@@ -2103,10 +2152,17 @@ static uint be_num_rss_want(struct be_adapter *adapter)
static void be_msix_enable(struct be_adapter *adapter)
{
#define BE_MIN_MSIX_VECTORS 1
- int i, status, num_vec;
+ int i, status, num_vec, num_roce_vec = 0;
/* If RSS queues are not used, need a vec for default RX Q */
num_vec = min(be_num_rss_want(adapter), num_online_cpus());
+ if (be_roce_supported(adapter)) {
+ num_roce_vec = min_t(u32, MAX_ROCE_MSIX_VECTORS,
+ (num_online_cpus() + 1));
+ num_roce_vec = min(num_roce_vec, MAX_ROCE_EQS);
+ num_vec += num_roce_vec;
+ num_vec = min(num_vec, MAX_MSIX_VECTORS);
+ }
num_vec = max(num_vec, BE_MIN_MSIX_VECTORS);
for (i = 0; i < num_vec; i++)
@@ -2123,55 +2179,18 @@ static void be_msix_enable(struct be_adapter *adapter)
}
return;
done:
- adapter->num_msix_vec = num_vec;
- return;
-}
-
-static int be_sriov_enable(struct be_adapter *adapter)
-{
- be_check_sriov_fn_type(adapter);
-
-#ifdef CONFIG_PCI_IOV
- if (be_physfn(adapter) && num_vfs) {
- int status, pos;
- u16 dev_vfs;
-
- pos = pci_find_ext_capability(adapter->pdev,
- PCI_EXT_CAP_ID_SRIOV);
- pci_read_config_word(adapter->pdev,
- pos + PCI_SRIOV_TOTAL_VF, &dev_vfs);
-
- adapter->num_vfs = min_t(u16, num_vfs, dev_vfs);
- if (adapter->num_vfs != num_vfs)
- dev_info(&adapter->pdev->dev,
- "Device supports %d VFs and not %d\n",
- adapter->num_vfs, num_vfs);
-
- status = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
- if (status)
- adapter->num_vfs = 0;
-
- if (adapter->num_vfs) {
- adapter->vf_cfg = kcalloc(num_vfs,
- sizeof(struct be_vf_cfg),
- GFP_KERNEL);
- if (!adapter->vf_cfg)
- return -ENOMEM;
+ if (be_roce_supported(adapter)) {
+ if (num_vec > num_roce_vec) {
+ adapter->num_msix_vec = num_vec - num_roce_vec;
+ adapter->num_msix_roce_vec =
+ num_vec - adapter->num_msix_vec;
+ } else {
+ adapter->num_msix_vec = num_vec;
+ adapter->num_msix_roce_vec = 0;
}
- }
-#endif
- return 0;
-}
-
-static void be_sriov_disable(struct be_adapter *adapter)
-{
-#ifdef CONFIG_PCI_IOV
- if (sriov_enabled(adapter)) {
- pci_disable_sriov(adapter->pdev);
- kfree(adapter->vf_cfg);
- adapter->num_vfs = 0;
- }
-#endif
+ } else
+ adapter->num_msix_vec = num_vec;
+ return;
}
static inline int be_msix_vec_get(struct be_adapter *adapter,
@@ -2282,6 +2301,8 @@ static int be_close(struct net_device *netdev)
struct be_eq_obj *eqo;
int i;
+ be_roce_dev_close(adapter);
+
be_async_mcc_disable(adapter);
if (!lancer_chip(adapter))
@@ -2390,6 +2411,7 @@ static int be_open(struct net_device *netdev)
if (!status)
be_link_status_update(adapter, link_status);
+ be_roce_dev_open(adapter);
return 0;
err:
be_close(adapter->netdev);
@@ -2475,6 +2497,11 @@ static void be_vf_clear(struct be_adapter *adapter)
struct be_vf_cfg *vf_cfg;
u32 vf;
+ if (be_find_vfs(adapter, ASSIGNED)) {
+ dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs\n");
+ goto done;
+ }
+
for_all_vfs(adapter, vf_cfg, vf) {
if (lancer_chip(adapter))
be_cmd_set_mac_list(adapter, NULL, 0, vf + 1);
@@ -2484,6 +2511,10 @@ static void be_vf_clear(struct be_adapter *adapter)
be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1);
}
+ pci_disable_sriov(adapter->pdev);
+done:
+ kfree(adapter->vf_cfg);
+ adapter->num_vfs = 0;
}
static int be_clear(struct be_adapter *adapter)
@@ -2513,29 +2544,60 @@ static int be_clear(struct be_adapter *adapter)
be_cmd_fw_clean(adapter);
be_msix_disable(adapter);
- kfree(adapter->pmac_id);
+ pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 0);
return 0;
}
-static void be_vf_setup_init(struct be_adapter *adapter)
+static int be_vf_setup_init(struct be_adapter *adapter)
{
struct be_vf_cfg *vf_cfg;
int vf;
+ adapter->vf_cfg = kcalloc(adapter->num_vfs, sizeof(*vf_cfg),
+ GFP_KERNEL);
+ if (!adapter->vf_cfg)
+ return -ENOMEM;
+
for_all_vfs(adapter, vf_cfg, vf) {
vf_cfg->if_handle = -1;
vf_cfg->pmac_id = -1;
}
+ return 0;
}
static int be_vf_setup(struct be_adapter *adapter)
{
struct be_vf_cfg *vf_cfg;
+ struct device *dev = &adapter->pdev->dev;
u32 cap_flags, en_flags, vf;
u16 def_vlan, lnk_speed;
- int status;
+ int status, enabled_vfs;
+
+ enabled_vfs = be_find_vfs(adapter, ENABLED);
+ if (enabled_vfs) {
+ dev_warn(dev, "%d VFs are already enabled\n", enabled_vfs);
+ dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs);
+ return 0;
+ }
- be_vf_setup_init(adapter);
+ if (num_vfs > adapter->dev_num_vfs) {
+ dev_warn(dev, "Device supports %d VFs and not %d\n",
+ adapter->dev_num_vfs, num_vfs);
+ num_vfs = adapter->dev_num_vfs;
+ }
+
+ status = pci_enable_sriov(adapter->pdev, num_vfs);
+ if (!status) {
+ adapter->num_vfs = num_vfs;
+ } else {
+ /* Platform doesn't support SRIOV though device supports it */
+ dev_warn(dev, "SRIOV enable failed\n");
+ return 0;
+ }
+
+ status = be_vf_setup_init(adapter);
+ if (status)
+ goto err;
cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
BE_IF_FLAGS_MULTICAST;
@@ -2546,9 +2608,11 @@ static int be_vf_setup(struct be_adapter *adapter)
goto err;
}
- status = be_vf_eth_addr_config(adapter);
- if (status)
- goto err;
+ if (!enabled_vfs) {
+ status = be_vf_eth_addr_config(adapter);
+ if (status)
+ goto err;
+ }
for_all_vfs(adapter, vf_cfg, vf) {
status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
@@ -2571,11 +2635,12 @@ err:
static void be_setup_init(struct be_adapter *adapter)
{
adapter->vlan_prio_bmap = 0xff;
- adapter->link_speed = -1;
+ adapter->phy.link_speed = -1;
adapter->if_handle = -1;
adapter->be3_native = false;
adapter->promiscuous = false;
adapter->eq_next_idx = 0;
+ adapter->phy.forced_port_speed = -1;
}
static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac)
@@ -2604,9 +2669,25 @@ do_none:
return status;
}
+/* Routine to query per function resource limits */
+static int be_get_config(struct be_adapter *adapter)
+{
+ int pos;
+ u16 dev_num_vfs;
+
+ pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV);
+ if (pos) {
+ pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF,
+ &dev_num_vfs);
+ adapter->dev_num_vfs = dev_num_vfs;
+ }
+ return 0;
+}
+
static int be_setup(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ struct device *dev = &adapter->pdev->dev;
u32 cap_flags, en_flags;
u32 tx_fc, rx_fc;
int status;
@@ -2614,6 +2695,8 @@ static int be_setup(struct be_adapter *adapter)
be_setup_init(adapter);
+ be_get_config(adapter);
+
be_cmd_req_native_mode(adapter);
be_msix_enable(adapter);
@@ -2680,36 +2763,33 @@ static int be_setup(struct be_adapter *adapter)
be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL);
- status = be_vid_config(adapter, false, 0);
- if (status)
- goto err;
+ be_vid_config(adapter, false, 0);
be_set_rx_mode(adapter->netdev);
- status = be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc);
- /* For Lancer: It is legal for this cmd to fail on VF */
- if (status && (be_physfn(adapter) || !lancer_chip(adapter)))
- goto err;
+ be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc);
- if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) {
- status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
+ if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc)
+ be_cmd_set_flow_control(adapter, adapter->tx_fc,
adapter->rx_fc);
- /* For Lancer: It is legal for this cmd to fail on VF */
- if (status && (be_physfn(adapter) || !lancer_chip(adapter)))
- goto err;
- }
pcie_set_readrq(adapter->pdev, 4096);
- if (sriov_enabled(adapter)) {
- status = be_vf_setup(adapter);
- if (status)
- goto err;
+ if (be_physfn(adapter) && num_vfs) {
+ if (adapter->dev_num_vfs)
+ be_vf_setup(adapter);
+ else
+ dev_warn(dev, "device doesn't support SRIOV\n");
}
+ be_cmd_get_phy_info(adapter);
+ if (be_pause_supported(adapter))
+ adapter->phy.fc_autoneg = 1;
+
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
adapter->flags |= BE_FLAGS_WORKER_SCHEDULED;
+ pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 1);
return 0;
err:
be_clear(adapter);
@@ -2731,6 +2811,8 @@ static void be_netpoll(struct net_device *netdev)
#endif
#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
+char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
+
static bool be_flash_redboot(struct be_adapter *adapter,
const u8 *p, u32 img_start, int image_size,
int hdr_size)
@@ -2760,71 +2842,105 @@ static bool be_flash_redboot(struct be_adapter *adapter,
static bool phy_flashing_required(struct be_adapter *adapter)
{
- int status = 0;
- struct be_phy_info phy_info;
+ return (adapter->phy.phy_type == TN_8022 &&
+ adapter->phy.interface_type == PHY_TYPE_BASET_10GB);
+}
- status = be_cmd_get_phy_info(adapter, &phy_info);
- if (status)
- return false;
- if ((phy_info.phy_type == TN_8022) &&
- (phy_info.interface_type == PHY_TYPE_BASET_10GB)) {
- return true;
+static bool is_comp_in_ufi(struct be_adapter *adapter,
+ struct flash_section_info *fsec, int type)
+{
+ int i = 0, img_type = 0;
+ struct flash_section_info_g2 *fsec_g2 = NULL;
+
+ if (adapter->generation != BE_GEN3)
+ fsec_g2 = (struct flash_section_info_g2 *)fsec;
+
+ for (i = 0; i < MAX_FLASH_COMP; i++) {
+ if (fsec_g2)
+ img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type);
+ else
+ img_type = le32_to_cpu(fsec->fsec_entry[i].type);
+
+ if (img_type == type)
+ return true;
}
return false;
+
+}
+
+struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
+ int header_size,
+ const struct firmware *fw)
+{
+ struct flash_section_info *fsec = NULL;
+ const u8 *p = fw->data;
+
+ p += header_size;
+ while (p < (fw->data + fw->size)) {
+ fsec = (struct flash_section_info *)p;
+ if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie)))
+ return fsec;
+ p += 32;
+ }
+ return NULL;
}
static int be_flash_data(struct be_adapter *adapter,
- const struct firmware *fw,
- struct be_dma_mem *flash_cmd, int num_of_images)
+ const struct firmware *fw,
+ struct be_dma_mem *flash_cmd,
+ int num_of_images)
{
int status = 0, i, filehdr_size = 0;
+ int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
u32 total_bytes = 0, flash_op;
int num_bytes;
const u8 *p = fw->data;
struct be_cmd_write_flashrom *req = flash_cmd->va;
const struct flash_comp *pflashcomp;
- int num_comp;
-
- static const struct flash_comp gen3_flash_types[10] = {
- { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE,
- FLASH_IMAGE_MAX_SIZE_g3},
- { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT,
- FLASH_REDBOOT_IMAGE_MAX_SIZE_g3},
- { FLASH_iSCSI_BIOS_START_g3, IMG_TYPE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g3},
- { FLASH_PXE_BIOS_START_g3, IMG_TYPE_PXE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g3},
- { FLASH_FCoE_BIOS_START_g3, IMG_TYPE_FCOE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g3},
- { FLASH_iSCSI_BACKUP_IMAGE_START_g3, IMG_TYPE_ISCSI_BACKUP,
- FLASH_IMAGE_MAX_SIZE_g3},
- { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE,
- FLASH_IMAGE_MAX_SIZE_g3},
- { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP,
- FLASH_IMAGE_MAX_SIZE_g3},
- { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW,
- FLASH_NCSI_IMAGE_MAX_SIZE_g3},
- { FLASH_PHY_FW_START_g3, IMG_TYPE_PHY_FW,
- FLASH_PHY_FW_IMAGE_MAX_SIZE_g3}
+ int num_comp, hdr_size;
+ struct flash_section_info *fsec = NULL;
+
+ struct flash_comp gen3_flash_types[] = {
+ { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE,
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_iSCSI},
+ { FLASH_REDBOOT_START_g3, OPTYPE_REDBOOT,
+ FLASH_REDBOOT_IMAGE_MAX_SIZE_g3, IMAGE_BOOT_CODE},
+ { FLASH_iSCSI_BIOS_START_g3, OPTYPE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_ISCSI},
+ { FLASH_PXE_BIOS_START_g3, OPTYPE_PXE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_PXE},
+ { FLASH_FCoE_BIOS_START_g3, OPTYPE_FCOE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_FCoE},
+ { FLASH_iSCSI_BACKUP_IMAGE_START_g3, OPTYPE_ISCSI_BACKUP,
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_iSCSI},
+ { FLASH_FCoE_PRIMARY_IMAGE_START_g3, OPTYPE_FCOE_FW_ACTIVE,
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_FCoE},
+ { FLASH_FCoE_BACKUP_IMAGE_START_g3, OPTYPE_FCOE_FW_BACKUP,
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_FCoE},
+ { FLASH_NCSI_START_g3, OPTYPE_NCSI_FW,
+ FLASH_NCSI_IMAGE_MAX_SIZE_g3, IMAGE_NCSI},
+ { FLASH_PHY_FW_START_g3, OPTYPE_PHY_FW,
+ FLASH_PHY_FW_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_PHY}
};
- static const struct flash_comp gen2_flash_types[8] = {
- { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE,
- FLASH_IMAGE_MAX_SIZE_g2},
- { FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT,
- FLASH_REDBOOT_IMAGE_MAX_SIZE_g2},
- { FLASH_iSCSI_BIOS_START_g2, IMG_TYPE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g2},
- { FLASH_PXE_BIOS_START_g2, IMG_TYPE_PXE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g2},
- { FLASH_FCoE_BIOS_START_g2, IMG_TYPE_FCOE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g2},
- { FLASH_iSCSI_BACKUP_IMAGE_START_g2, IMG_TYPE_ISCSI_BACKUP,
- FLASH_IMAGE_MAX_SIZE_g2},
- { FLASH_FCoE_PRIMARY_IMAGE_START_g2, IMG_TYPE_FCOE_FW_ACTIVE,
- FLASH_IMAGE_MAX_SIZE_g2},
- { FLASH_FCoE_BACKUP_IMAGE_START_g2, IMG_TYPE_FCOE_FW_BACKUP,
- FLASH_IMAGE_MAX_SIZE_g2}
+
+ struct flash_comp gen2_flash_types[] = {
+ { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, OPTYPE_ISCSI_ACTIVE,
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_iSCSI},
+ { FLASH_REDBOOT_START_g2, OPTYPE_REDBOOT,
+ FLASH_REDBOOT_IMAGE_MAX_SIZE_g2, IMAGE_BOOT_CODE},
+ { FLASH_iSCSI_BIOS_START_g2, OPTYPE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_ISCSI},
+ { FLASH_PXE_BIOS_START_g2, OPTYPE_PXE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_PXE},
+ { FLASH_FCoE_BIOS_START_g2, OPTYPE_FCOE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_FCoE},
+ { FLASH_iSCSI_BACKUP_IMAGE_START_g2, OPTYPE_ISCSI_BACKUP,
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_iSCSI},
+ { FLASH_FCoE_PRIMARY_IMAGE_START_g2, OPTYPE_FCOE_FW_ACTIVE,
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_FCoE},
+ { FLASH_FCoE_BACKUP_IMAGE_START_g2, OPTYPE_FCOE_FW_BACKUP,
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE}
};
if (adapter->generation == BE_GEN3) {
@@ -2836,22 +2952,37 @@ static int be_flash_data(struct be_adapter *adapter,
filehdr_size = sizeof(struct flash_file_hdr_g2);
num_comp = ARRAY_SIZE(gen2_flash_types);
}
+ /* Get flash section info*/
+ fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
+ if (!fsec) {
+ dev_err(&adapter->pdev->dev,
+ "Invalid Cookie. UFI corrupted ?\n");
+ return -1;
+ }
for (i = 0; i < num_comp; i++) {
- if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) &&
- memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
+ if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type))
+ continue;
+
+ if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) &&
+ memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
continue;
- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) {
+
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW) {
if (!phy_flashing_required(adapter))
continue;
}
- if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) &&
- (!be_flash_redboot(adapter, fw->data,
- pflashcomp[i].offset, pflashcomp[i].size, filehdr_size +
- (num_of_images * sizeof(struct image_hdr)))))
+
+ hdr_size = filehdr_size +
+ (num_of_images * sizeof(struct image_hdr));
+
+ if ((pflashcomp[i].optype == OPTYPE_REDBOOT) &&
+ (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset,
+ pflashcomp[i].size, hdr_size)))
continue;
+
+ /* Flash the component */
p = fw->data;
- p += filehdr_size + pflashcomp[i].offset
- + (num_of_images * sizeof(struct image_hdr));
+ p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
if (p + pflashcomp[i].size > fw->data + fw->size)
return -1;
total_bytes = pflashcomp[i].size;
@@ -2862,12 +2993,12 @@ static int be_flash_data(struct be_adapter *adapter,
num_bytes = total_bytes;
total_bytes -= num_bytes;
if (!total_bytes) {
- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW)
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW)
flash_op = FLASHROM_OPER_PHY_FLASH;
else
flash_op = FLASHROM_OPER_FLASH;
} else {
- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW)
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW)
flash_op = FLASHROM_OPER_PHY_SAVE;
else
flash_op = FLASHROM_OPER_SAVE;
@@ -2879,7 +3010,7 @@ static int be_flash_data(struct be_adapter *adapter,
if (status) {
if ((status == ILLEGAL_IOCTL_REQ) &&
(pflashcomp[i].optype ==
- IMG_TYPE_PHY_FW))
+ OPTYPE_PHY_FW))
break;
dev_err(&adapter->pdev->dev,
"cmd to write to flash rom failed.\n");
@@ -3106,7 +3237,7 @@ static void be_netdev_init(struct net_device *netdev)
netdev->flags |= IFF_MULTICAST;
- netif_set_gso_max_size(netdev, 65535);
+ netif_set_gso_max_size(netdev, 65535 - ETH_HLEN);
netdev->netdev_ops = &be_netdev_ops;
@@ -3122,6 +3253,24 @@ static void be_unmap_pci_bars(struct be_adapter *adapter)
iounmap(adapter->csr);
if (adapter->db)
iounmap(adapter->db);
+ if (adapter->roce_db.base)
+ pci_iounmap(adapter->pdev, adapter->roce_db.base);
+}
+
+static int lancer_roce_map_pci_bars(struct be_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ u8 __iomem *addr;
+
+ addr = pci_iomap(pdev, 2, 0);
+ if (addr == NULL)
+ return -ENOMEM;
+
+ adapter->roce_db.base = addr;
+ adapter->roce_db.io_addr = pci_resource_start(pdev, 2);
+ adapter->roce_db.size = 8192;
+ adapter->roce_db.total_size = pci_resource_len(pdev, 2);
+ return 0;
}
static int be_map_pci_bars(struct be_adapter *adapter)
@@ -3130,11 +3279,18 @@ static int be_map_pci_bars(struct be_adapter *adapter)
int db_reg;
if (lancer_chip(adapter)) {
- addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0),
- pci_resource_len(adapter->pdev, 0));
- if (addr == NULL)
- return -ENOMEM;
- adapter->db = addr;
+ if (be_type_2_3(adapter)) {
+ addr = ioremap_nocache(
+ pci_resource_start(adapter->pdev, 0),
+ pci_resource_len(adapter->pdev, 0));
+ if (addr == NULL)
+ return -ENOMEM;
+ adapter->db = addr;
+ }
+ if (adapter->if_type == SLI_INTF_TYPE_3) {
+ if (lancer_roce_map_pci_bars(adapter))
+ goto pci_map_err;
+ }
return 0;
}
@@ -3159,14 +3315,19 @@ static int be_map_pci_bars(struct be_adapter *adapter)
if (addr == NULL)
goto pci_map_err;
adapter->db = addr;
-
+ if (adapter->sli_family == SKYHAWK_SLI_FAMILY) {
+ adapter->roce_db.size = 4096;
+ adapter->roce_db.io_addr =
+ pci_resource_start(adapter->pdev, db_reg);
+ adapter->roce_db.total_size =
+ pci_resource_len(adapter->pdev, db_reg);
+ }
return 0;
pci_map_err:
be_unmap_pci_bars(adapter);
return -ENOMEM;
}
-
static void be_ctrl_cleanup(struct be_adapter *adapter)
{
struct be_dma_mem *mem = &adapter->mbox_mem_alloced;
@@ -3272,6 +3433,8 @@ static void __devexit be_remove(struct pci_dev *pdev)
if (!adapter)
return;
+ be_roce_dev_remove(adapter);
+
unregister_netdev(adapter->netdev);
be_clear(adapter);
@@ -3280,8 +3443,6 @@ static void __devexit be_remove(struct pci_dev *pdev)
be_ctrl_cleanup(adapter);
- be_sriov_disable(adapter);
-
pci_set_drvdata(pdev, NULL);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -3295,9 +3456,43 @@ bool be_is_wol_supported(struct be_adapter *adapter)
!be_is_wol_excluded(adapter)) ? true : false;
}
-static int be_get_config(struct be_adapter *adapter)
+u32 be_get_fw_log_level(struct be_adapter *adapter)
+{
+ struct be_dma_mem extfat_cmd;
+ struct be_fat_conf_params *cfgs;
+ int status;
+ u32 level = 0;
+ int j;
+
+ memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
+ extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
+ extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
+ &extfat_cmd.dma);
+
+ if (!extfat_cmd.va) {
+ dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
+ __func__);
+ goto err;
+ }
+
+ status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
+ if (!status) {
+ cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
+ sizeof(struct be_cmd_resp_hdr));
+ for (j = 0; j < cfgs->module[0].num_modes; j++) {
+ if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
+ level = cfgs->module[0].trace_lvl[j].dbg_lvl;
+ }
+ }
+ pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
+ extfat_cmd.dma);
+err:
+ return level;
+}
+static int be_get_initial_config(struct be_adapter *adapter)
{
int status;
+ u32 level;
status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
&adapter->function_mode, &adapter->function_caps);
@@ -3335,10 +3530,13 @@ static int be_get_config(struct be_adapter *adapter)
if (be_is_wol_supported(adapter))
adapter->wol = true;
+ level = be_get_fw_log_level(adapter);
+ adapter->msg_enable = level <= FW_LOG_LEVEL_DEFAULT ? NETIF_MSG_HW : 0;
+
return 0;
}
-static int be_dev_family_check(struct be_adapter *adapter)
+static int be_dev_type_check(struct be_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
u32 sli_intf = 0, if_type;
@@ -3350,17 +3548,27 @@ static int be_dev_family_check(struct be_adapter *adapter)
break;
case BE_DEVICE_ID2:
case OC_DEVICE_ID2:
- case OC_DEVICE_ID5:
adapter->generation = BE_GEN3;
break;
case OC_DEVICE_ID3:
case OC_DEVICE_ID4:
pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
+ SLI_INTF_IF_TYPE_SHIFT;
if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
SLI_INTF_IF_TYPE_SHIFT;
-
if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
- if_type != 0x02) {
+ !be_type_2_3(adapter)) {
+ dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
+ return -EINVAL;
+ }
+ adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
+ SLI_INTF_FAMILY_SHIFT);
+ adapter->generation = BE_GEN3;
+ break;
+ case OC_DEVICE_ID5:
+ pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) {
dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
return -EINVAL;
}
@@ -3371,6 +3579,9 @@ static int be_dev_family_check(struct be_adapter *adapter)
default:
adapter->generation = 0;
}
+
+ pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
return 0;
}
@@ -3514,6 +3725,14 @@ reschedule:
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}
+static bool be_reset_required(struct be_adapter *adapter)
+{
+ u32 reg;
+
+ pci_read_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, &reg);
+ return reg;
+}
+
static int __devinit be_probe(struct pci_dev *pdev,
const struct pci_device_id *pdev_id)
{
@@ -3539,7 +3758,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
adapter->pdev = pdev;
pci_set_drvdata(pdev, adapter);
- status = be_dev_family_check(adapter);
+ status = be_dev_type_check(adapter);
if (status)
goto free_netdev;
@@ -3557,13 +3776,9 @@ static int __devinit be_probe(struct pci_dev *pdev,
}
}
- status = be_sriov_enable(adapter);
- if (status)
- goto free_netdev;
-
status = be_ctrl_init(adapter);
if (status)
- goto disable_sriov;
+ goto free_netdev;
if (lancer_chip(adapter)) {
status = lancer_wait_ready(adapter);
@@ -3590,9 +3805,11 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto ctrl_clean;
- status = be_cmd_reset_function(adapter);
- if (status)
- goto ctrl_clean;
+ if (be_reset_required(adapter)) {
+ status = be_cmd_reset_function(adapter);
+ if (status)
+ goto ctrl_clean;
+ }
/* The INTR bit may be set in the card when probed by a kdump kernel
* after a crash.
@@ -3604,7 +3821,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto ctrl_clean;
- status = be_get_config(adapter);
+ status = be_get_initial_config(adapter);
if (status)
goto stats_clean;
@@ -3620,6 +3837,8 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status != 0)
goto unsetup;
+ be_roce_dev_add(adapter);
+
dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev),
adapter->port_num);
@@ -3633,8 +3852,6 @@ stats_clean:
be_stats_cleanup(adapter);
ctrl_clean:
be_ctrl_cleanup(adapter);
-disable_sriov:
- be_sriov_disable(adapter);
free_netdev:
free_netdev(netdev);
pci_set_drvdata(pdev, NULL);
@@ -3749,6 +3966,11 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
pci_disable_device(pdev);
+ /* The error could cause the FW to trigger a flash debug dump.
+ * Resetting the card while flash dump is in progress
+ * can cause it not to recover; wait for it to finish
+ */
+ ssleep(30);
return PCI_ERS_RESULT_NEED_RESET;
}
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
new file mode 100644
index 000000000000..deecc44b3617
--- /dev/null
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2005 - 2011 Emulex
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ */
+
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+
+#include "be.h"
+#include "be_cmds.h"
+
+static struct ocrdma_driver *ocrdma_drv;
+static LIST_HEAD(be_adapter_list);
+static DEFINE_MUTEX(be_adapter_list_lock);
+
+static void _be_roce_dev_add(struct be_adapter *adapter)
+{
+ struct be_dev_info dev_info;
+ int i, num_vec;
+ struct pci_dev *pdev = adapter->pdev;
+
+ if (!ocrdma_drv)
+ return;
+ if (pdev->device == OC_DEVICE_ID5) {
+ /* only msix is supported on these devices */
+ if (!msix_enabled(adapter))
+ return;
+ /* DPP region address and length */
+ dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2);
+ dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2);
+ } else {
+ dev_info.dpp_unmapped_addr = 0;
+ dev_info.dpp_unmapped_len = 0;
+ }
+ dev_info.pdev = adapter->pdev;
+ if (adapter->sli_family == SKYHAWK_SLI_FAMILY)
+ dev_info.db = adapter->db;
+ else
+ dev_info.db = adapter->roce_db.base;
+ dev_info.unmapped_db = adapter->roce_db.io_addr;
+ dev_info.db_page_size = adapter->roce_db.size;
+ dev_info.db_total_size = adapter->roce_db.total_size;
+ dev_info.netdev = adapter->netdev;
+ memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN);
+ dev_info.dev_family = adapter->sli_family;
+ if (msix_enabled(adapter)) {
+ /* provide all the vectors, so that EQ creation response
+ * can decide which one to use.
+ */
+ num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec;
+ dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX;
+ dev_info.msix.num_vectors = min(num_vec, MAX_ROCE_MSIX_VECTORS);
+ /* provide start index of the vector,
+ * so in case of linear usage,
+ * it can use the base as starting point.
+ */
+ dev_info.msix.start_vector = adapter->num_evt_qs;
+ for (i = 0; i < dev_info.msix.num_vectors; i++) {
+ dev_info.msix.vector_list[i] =
+ adapter->msix_entries[i].vector;
+ }
+ } else {
+ dev_info.msix.num_vectors = 0;
+ dev_info.intr_mode = BE_INTERRUPT_MODE_INTX;
+ }
+ adapter->ocrdma_dev = ocrdma_drv->add(&dev_info);
+}
+
+void be_roce_dev_add(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ INIT_LIST_HEAD(&adapter->entry);
+ mutex_lock(&be_adapter_list_lock);
+ list_add_tail(&adapter->entry, &be_adapter_list);
+
+ /* invoke add() routine of roce driver only if
+ * valid driver registered with add method and add() is not yet
+ * invoked on a given adapter.
+ */
+ _be_roce_dev_add(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_remove(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
+ ocrdma_drv->remove(adapter->ocrdma_dev);
+ adapter->ocrdma_dev = NULL;
+}
+
+void be_roce_dev_remove(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_remove(adapter);
+ list_del(&adapter->entry);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_open(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && adapter->ocrdma_dev &&
+ ocrdma_drv->state_change_handler)
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 0);
+}
+
+void be_roce_dev_open(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_open(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_close(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && adapter->ocrdma_dev &&
+ ocrdma_drv->state_change_handler)
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 1);
+}
+
+void be_roce_dev_close(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_close(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+int be_roce_register_driver(struct ocrdma_driver *drv)
+{
+ struct be_adapter *dev;
+
+ mutex_lock(&be_adapter_list_lock);
+ if (ocrdma_drv) {
+ mutex_unlock(&be_adapter_list_lock);
+ return -EINVAL;
+ }
+ ocrdma_drv = drv;
+ list_for_each_entry(dev, &be_adapter_list, entry) {
+ struct net_device *netdev;
+ _be_roce_dev_add(dev);
+ netdev = dev->netdev;
+ if (netif_running(netdev) && netif_oper_up(netdev))
+ _be_roce_dev_open(dev);
+ }
+ mutex_unlock(&be_adapter_list_lock);
+ return 0;
+}
+EXPORT_SYMBOL(be_roce_register_driver);
+
+void be_roce_unregister_driver(struct ocrdma_driver *drv)
+{
+ struct be_adapter *dev;
+
+ mutex_lock(&be_adapter_list_lock);
+ list_for_each_entry(dev, &be_adapter_list, entry) {
+ if (dev->ocrdma_dev)
+ _be_roce_dev_remove(dev);
+ }
+ ocrdma_drv = NULL;
+ mutex_unlock(&be_adapter_list_lock);
+}
+EXPORT_SYMBOL(be_roce_unregister_driver);
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h
new file mode 100644
index 000000000000..db4ea8081c07
--- /dev/null
+++ b/drivers/net/ethernet/emulex/benet/be_roce.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2005 - 2011 Emulex
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ */
+
+#ifndef BE_ROCE_H
+#define BE_ROCE_H
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+
+struct ocrdma_dev;
+
+enum be_interrupt_mode {
+ BE_INTERRUPT_MODE_MSIX = 0,
+ BE_INTERRUPT_MODE_INTX = 1,
+ BE_INTERRUPT_MODE_MSI = 2,
+};
+
+#define MAX_ROCE_MSIX_VECTORS 16
+struct be_dev_info {
+ u8 __iomem *db;
+ u64 unmapped_db;
+ u32 db_page_size;
+ u32 db_total_size;
+ u64 dpp_unmapped_addr;
+ u32 dpp_unmapped_len;
+ struct pci_dev *pdev;
+ struct net_device *netdev;
+ u8 mac_addr[ETH_ALEN];
+ u32 dev_family;
+ enum be_interrupt_mode intr_mode;
+ struct {
+ int num_vectors;
+ int start_vector;
+ u32 vector_list[MAX_ROCE_MSIX_VECTORS];
+ } msix;
+};
+
+/* ocrdma driver register's the callback functions with nic driver. */
+struct ocrdma_driver {
+ unsigned char name[32];
+ struct ocrdma_dev *(*add) (struct be_dev_info *dev_info);
+ void (*remove) (struct ocrdma_dev *);
+ void (*state_change_handler) (struct ocrdma_dev *, u32 new_state);
+};
+
+enum {
+ BE_DEV_UP = 0,
+ BE_DEV_DOWN = 1
+};
+
+/* APIs for RoCE driver to register callback handlers,
+ * which will be invoked when device is added, removed, ifup, ifdown
+ */
+int be_roce_register_driver(struct ocrdma_driver *drv);
+void be_roce_unregister_driver(struct ocrdma_driver *drv);
+
+/* API for RoCE driver to issue mailbox commands */
+int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
+ int wrb_payload_size, u16 *cmd_status, u16 *ext_status);
+
+#endif /* BE_ROCE_H */