Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2372

kernel-2.6.18-238.el5.src.rpm

From: Ivan Vecera <ivecera@redhat.com>
Date: Tue, 5 Jan 2010 17:51:00 -0500
Subject: [net] be2net: multiple bug fixes
Message-id: <1262713860-14499-1-git-send-email-ivecera@redhat.com>
Patchwork-id: 22314
O-Subject: [RHEL5.5 PATCH] be2net: Multiple bug fixes for be2net
Bugzilla: 549460
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: David S. Miller <davem@redhat.com>

BZs:
#549460 - Multiple bug fixes for be2net

Description:
This includes several upstream fixes for bugs found in Emulex QA.

1) be2net: Bug fix to return correct values in ethtool get_settings
16c02145902d8597841a25e8443cfb082898a2d7

2) be2net: Add support for ethtool self test
ff33a6e2ab97f4cde484cdf1a41778af6d6b7cff

3) be2net: Bug fix to config NIC appropriately before loopback test
fced9999ed7f6975fbb2350a73048918ba60a773

4) be2net: Bug fix to avoid soft lockup in loopback test.
d7b901418250f00eaaa18f9135d09ba61b72a5bc

5) be2net: fix error in rx completion processing
e1187b3be72be59625e445b186007e6eae27fef1

Signed-off-by: Ivan Vecera <ivecera@redhat.com>

diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 655d191..ee196ca 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -34,7 +34,7 @@
 
 #include "be_hw.h"
 
-#define DRV_VER			"2.101.331r"
+#define DRV_VER			"2.101.377r"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
 #define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
@@ -46,16 +46,14 @@
 #define BE_DEVICE_ID1		0x211
 #define BE_DEVICE_ID2		0x221
 #define OC_DEVICE_ID1		0x700
-#define OC_DEVICE_ID2		0x701
-#define OC_DEVICE_ID3		0x710
+#define OC_DEVICE_ID2		0x710
 
 static inline char *nic_name(struct pci_dev *pdev)
 {
 	switch (pdev->device) {
 	case OC_DEVICE_ID1:
-	case OC_DEVICE_ID2:
 		return OC_NAME;
-	case OC_DEVICE_ID3:
+	case OC_DEVICE_ID2:
 		return OC_NAME1;
 	case BE_DEVICE_ID2:
 		return BE3_NAME;
@@ -284,6 +282,7 @@ struct be_adapter {
 	u32 tx_fc;		/* Tx flow control */
 	int link_speed;
 	u8 port_type;
+	u8 transceiver;
 };
 
 extern struct ethtool_ops be_ethtool_ops;
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 4da2597..c632e66 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -1492,3 +1492,162 @@ err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
+
+int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
+			u8 loopback_type, u8 enable)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_set_lmode *req;
+	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_hdr_prepare(wrb, sizeof(*req), true, 0,
+				OPCODE_LOWLEVEL_SET_LOOPBACK_MODE);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
+			OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
+			sizeof(*req));
+
+	req->src_port = port_num;
+	req->dest_port = port_num;
+	req->loopback_type = loopback_type;
+	req->loopback_state = enable;
+
+	status = be_mcc_notify_wait(adapter);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
+		u32 loopback_type, u32 pkt_size, u32 num_pkts, u64 pattern)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_loopback_test *req;
+	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_hdr_prepare(wrb, sizeof(*req), true, 0,
+				OPCODE_LOWLEVEL_LOOPBACK_TEST);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
+			OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
+	req->hdr.timeout = 4;
+
+	req->pattern = cpu_to_le64(pattern);
+	req->src_port = cpu_to_le32(port_num);
+	req->dest_port = cpu_to_le32(port_num);
+	req->pkt_size = cpu_to_le32(pkt_size);
+	req->num_pkts = cpu_to_le32(num_pkts);
+	req->loopback_type = cpu_to_le32(loopback_type);
+
+	status = be_mcc_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_loopback_test *resp = embedded_payload(wrb);
+		status = le32_to_cpu(resp->status);
+	}
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
+				u32 byte_cnt, struct be_dma_mem *cmd)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_ddrdma_test *req;
+	struct be_sge *sge;
+	int status;
+	int i, j = 0;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = cmd->va;
+	sge = nonembedded_sgl(wrb);
+	be_wrb_hdr_prepare(wrb, cmd->size, false, 1,
+				OPCODE_LOWLEVEL_HOST_DDR_DMA);
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
+			OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size);
+
+	sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
+	sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
+	sge->len = cpu_to_le32(cmd->size);
+
+	req->pattern = cpu_to_le64(pattern);
+	req->byte_count = cpu_to_le32(byte_cnt);
+	for (i = 0; i < byte_cnt; i++) {
+		req->snd_buff[i] = (u8)(pattern >> (j*8));
+		j++;
+		if (j > 7)
+			j = 0;
+	}
+
+	status = be_mcc_notify_wait(adapter);
+
+	if (!status) {
+		struct be_cmd_resp_ddrdma_test *resp;
+		resp = cmd->va;
+		if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) ||
+				resp->snd_err) {
+			status = -1;
+		}
+	}
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
+				struct be_dma_mem *nonemb_cmd)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_seeprom_read *req;
+	struct be_sge *sge;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	req = nonemb_cmd->va;
+	sge = nonembedded_sgl(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
+			OPCODE_COMMON_SEEPROM_READ);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			OPCODE_COMMON_SEEPROM_READ, sizeof(*req));
+
+	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
+	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
+	sge->len = cpu_to_le32(nonemb_cmd->size);
+
+	status = be_mcc_notify_wait(adapter);
+
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index a091360..9b659aa 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -112,6 +112,7 @@ struct be_mcc_mailbox {
 
 #define CMD_SUBSYSTEM_COMMON	0x1
 #define CMD_SUBSYSTEM_ETH 	0x3
+#define CMD_SUBSYSTEM_LOWLEVEL  0xb
 
 #define OPCODE_COMMON_NTWK_MAC_QUERY			1
 #define OPCODE_COMMON_NTWK_MAC_SET			2
@@ -123,6 +124,8 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_CQ_CREATE				12
 #define OPCODE_COMMON_EQ_CREATE				13
 #define OPCODE_COMMON_MCC_CREATE        		21
+#define OPCODE_COMMON_SEEPROM_READ			30
+#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES               32
 #define OPCODE_COMMON_NTWK_RX_FILTER    		34
 #define OPCODE_COMMON_GET_FW_VERSION			35
 #define OPCODE_COMMON_SET_FLOW_CONTROL			36
@@ -152,6 +155,10 @@ struct be_mcc_mailbox {
 #define OPCODE_ETH_RX_DESTROY           		10
 #define OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG		12
 
+#define OPCODE_LOWLEVEL_HOST_DDR_DMA                    17
+#define OPCODE_LOWLEVEL_LOOPBACK_TEST                   18
+#define OPCODE_LOWLEVEL_SET_LOOPBACK_MODE		19
+
 struct be_cmd_req_hdr {
 	u8 opcode;		/* dword 0 */
 	u8 subsystem;		/* dword 0 */
@@ -797,6 +804,77 @@ struct be_cmd_req_acpi_wol_magic_config{
 	u8 rsvd2[2];
 } __packed;
 
+/********************** LoopBack test *********************/
+
+#define BE_MAC_LOOPBACK 0x0
+#define BE_PHY_LOOPBACK 0x1
+#define BE_ONE_PORT_EXT_LOOPBACK 0x2
+#define BE_NO_LOOPBACK     0xff
+
+struct be_cmd_req_loopback_test {
+	struct be_cmd_req_hdr hdr;
+	u32 loopback_type;
+	u32 num_pkts;
+	u64 pattern;
+	u32 src_port;
+	u32 dest_port;
+	u32 pkt_size;
+};
+
+struct be_cmd_resp_loopback_test {
+	struct be_cmd_resp_hdr resp_hdr;
+	u32    status;
+	u32    num_txfer;
+	u32    num_rx;
+	u32    miscomp_off;
+	u32    ticks_compl;
+};
+
+struct be_cmd_req_set_lmode {
+	struct be_cmd_req_hdr hdr;
+	u8 src_port;
+	u8 dest_port;
+	u8 loopback_type;
+	u8 loopback_state;
+};
+
+struct be_cmd_resp_set_lmode {
+	struct be_cmd_resp_hdr resp_hdr;
+	u8 rsvd0[4];
+};
+
+/********************** DDR DMA test *********************/
+struct be_cmd_req_ddrdma_test {
+	struct be_cmd_req_hdr hdr;
+	u64 pattern;
+	u32 byte_count;
+	u32 rsvd0;
+	u8  snd_buff[4096];
+	u8  rsvd1[4096];
+};
+
+struct be_cmd_resp_ddrdma_test {
+	struct be_cmd_resp_hdr hdr;
+	u64 pattern;
+	u32 byte_cnt;
+	u32 snd_err;
+	u8  rsvd0[4096];
+	u8  rcv_buff[4096];
+};
+
+/*********************** SEEPROM Read ***********************/
+
+#define BE_READ_SEEPROM_LEN 1024
+struct be_cmd_req_seeprom_read {
+	struct be_cmd_req_hdr hdr;
+	u8 rsvd0[BE_READ_SEEPROM_LEN];
+};
+
+struct be_cmd_resp_seeprom_read {
+	struct be_cmd_req_hdr hdr;
+	u8 seeprom_data[BE_READ_SEEPROM_LEN];
+};
+
 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,
@@ -866,3 +944,12 @@ extern int be_cmd_fw_init(struct be_adapter *adapter);
 extern int be_cmd_fw_clean(struct be_adapter *adapter);
 extern void be_async_mcc_enable(struct be_adapter *adapter);
 extern void be_async_mcc_disable(struct be_adapter *adapter);
+extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
+				struct be_dma_mem *nonemb_cmd);
+extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
+				u32 loopback_type, u32 pkt_size,
+				u32 num_pkts, u64 pattern);
+extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
+			u32 byte_cnt, struct be_dma_mem *cmd);
+extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
+				u8 loopback_type, u8 enable);
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index 13e7516..3663af2 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -107,6 +107,15 @@ static const struct be_ethtool_stat et_stats[] = {
 };
 #define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
 
+static const char et_self_tests[][ETH_GSTRING_LEN] = {
+	"MAC Loopback test",
+	"PHY Loopback test",
+	"External Loopback test",
+	"DDR DMA test",
+	"Link test"
+};
+#define BE_NUM_TESTS ARRAY_SIZE(et_self_tests)
+
 static void
 be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
 {
@@ -295,6 +304,12 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
 			data += ETH_GSTRING_LEN;
 		}
 		break;
+	case ETH_SS_TEST:
+		for (i = 0; i < BE_NUM_TESTS; i++) {
+			memcpy(data, et_self_tests[i], ETH_GSTRING_LEN);
+			data += ETH_GSTRING_LEN;
+		}
+		break;
 	}
 }
 
@@ -306,13 +321,15 @@ static int be_get_stats_count(struct net_device *netdev)
 static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
+
+	int status;
 	u8 mac_speed = 0, connector = 0;
 	u16 link_speed = 0;
 	bool link_up = false;
 
 	if (adapter->link_speed < 0) {
-		be_cmd_link_status_query(adapter, &link_up, &mac_speed,
-					 &link_speed);
+		status = be_cmd_link_status_query(adapter, &link_up, &mac_speed,
+						&link_speed);
 
 		/* link_speed is in units of 10 Mbps */
 		if (link_speed) {
@@ -328,28 +345,51 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 			}
 		}
 
-		be_cmd_read_port_type(adapter, adapter->port_num, &connector);
-		switch (connector) {
-		case 7:
-			ecmd->port = PORT_FIBRE;
-			break;
-		default:
-			ecmd->port = PORT_TP;
-			break;
+		status = be_cmd_read_port_type(adapter, adapter->port_num,
+						&connector);
+		if (!status) {
+			switch (connector) {
+			case 7:
+				ecmd->port = PORT_FIBRE;
+				ecmd->transceiver = XCVR_EXTERNAL;
+				break;
+			case 0:
+				ecmd->port = PORT_TP;
+				ecmd->transceiver = XCVR_EXTERNAL;
+				break;
+			default:
+				ecmd->port = PORT_TP;
+				ecmd->transceiver = XCVR_INTERNAL;
+				break;
+			}
+		} else {
+			ecmd->port = PORT_AUI;
+			ecmd->transceiver = XCVR_INTERNAL;
 		}
 
 		adapter->link_speed = ecmd->speed;
 		adapter->port_type = ecmd->port;
+		adapter->transceiver = ecmd->transceiver;
 	} else {
 		ecmd->speed = adapter->link_speed;
 		ecmd->port = adapter->port_type;
+		ecmd->transceiver = adapter->transceiver;
 	}
 
 	ecmd->duplex = DUPLEX_FULL;
 	ecmd->autoneg = AUTONEG_DISABLE;
-	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP);
 	ecmd->phy_address = adapter->port_num;
-	ecmd->transceiver = XCVR_INTERNAL;
+	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;
+	}
 
 	return 0;
 }
@@ -417,6 +457,7 @@ be_phys_id(struct net_device *netdev, u32 data)
 	status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0,
 			BEACON_STATE_DISABLED);
 
+
 	return status;
 }
 
@@ -450,12 +491,143 @@ be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 	return 0;
 }
 
+static int
+be_test_ddr_dma(struct be_adapter *adapter)
+{
+	int ret, i;
+	struct be_dma_mem ddrdma_cmd;
+	u64 pattern[2] = {0x5a5a5a5a5a5a5a5a, 0xa5a5a5a5a5a5a5a5};
+
+	ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
+	ddrdma_cmd.va = pci_alloc_consistent(adapter->pdev, ddrdma_cmd.size,
+			&ddrdma_cmd.dma);
+	if (!ddrdma_cmd.va) {
+		dev_err(&adapter->pdev->dev, "Memory allocation failure \n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < 2; i++) {
+		ret = be_cmd_ddr_dma_test(adapter, pattern[i],
+						4096, &ddrdma_cmd);
+		if (ret)
+			goto err;
+	}
+
+err:
+	pci_free_consistent(adapter->pdev, ddrdma_cmd.size,
+			ddrdma_cmd.va, ddrdma_cmd.dma);
+	return ret;
+}
+
+static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,
+				u64 *status)
+{
+	be_cmd_set_loopback(adapter, adapter->port_num,
+				loopback_type, 1);
+	*status = be_cmd_loopback_test(adapter, adapter->port_num,
+				loopback_type, 1500,
+				2, 0xabc);
+	be_cmd_set_loopback(adapter, adapter->port_num,
+				BE_NO_LOOPBACK, 1);
+	return *status;
+}
+
+static int
+be_self_test_count(struct net_device *dev)
+{
+	return BE_NUM_TESTS;
+}
+
+static void
+be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
+{
+	struct be_adapter *adapter = netdev_priv(netdev);
+	bool link_up;
+	u8 mac_speed = 0;
+	u16 qos_link_speed = 0;
+
+	memset(data, 0, sizeof(u64) * BE_NUM_TESTS);
+	if (test->flags & ETH_TEST_FL_OFFLINE) {
+		if (be_loopback_test(adapter, BE_MAC_LOOPBACK,
+						&data[0]) != 0) {
+			test->flags |= ETH_TEST_FL_FAILED;
+		}
+		if (be_loopback_test(adapter, BE_PHY_LOOPBACK,
+						&data[1]) != 0) {
+			test->flags |= ETH_TEST_FL_FAILED;
+		}
+		if (be_loopback_test(adapter, BE_ONE_PORT_EXT_LOOPBACK,
+						&data[2]) != 0) {
+			test->flags |= ETH_TEST_FL_FAILED;
+		}
+	}
+
+	if (be_test_ddr_dma(adapter) != 0) {
+		data[3] = 1;
+		test->flags |= ETH_TEST_FL_FAILED;
+	}
+
+	if (be_cmd_link_status_query(adapter, &link_up,
+				&mac_speed, &qos_link_speed) != 0) {
+		test->flags |= ETH_TEST_FL_FAILED;
+		data[4] = -1;
+	} else if (mac_speed) {
+		data[4] = 1;
+	}
+
+}
+
+static int
+be_get_eeprom_len(struct net_device *netdev)
+{
+	return BE_READ_SEEPROM_LEN;
+}
+
+static int
+be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
+			uint8_t *data)
+{
+	struct be_adapter *adapter = netdev_priv(netdev);
+	struct be_dma_mem eeprom_cmd;
+	struct be_cmd_resp_seeprom_read *resp;
+	int status;
+
+	if (!eeprom->len)
+		return -EINVAL;
+
+	eeprom->magic = BE_VENDOR_ID | (adapter->pdev->device<<16);
+
+	memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
+	eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);
+	eeprom_cmd.va = pci_alloc_consistent(adapter->pdev, eeprom_cmd.size,
+				&eeprom_cmd.dma);
+
+	if (!eeprom_cmd.va) {
+		dev_err(&adapter->pdev->dev,
+			"Memory allocation failure. Could not read eeprom\n");
+		return -ENOMEM;
+	}
+
+	status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd);
+
+	if (!status) {
+		resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va;
+		memcpy(data, resp->seeprom_data, eeprom->len);
+	}
+	pci_free_consistent(adapter->pdev, eeprom_cmd.size, eeprom_cmd.va,
+			eeprom_cmd.dma);
+
+	return status;
+}
+
 struct ethtool_ops be_ethtool_ops = {
 	.get_settings = be_get_settings,
 	.get_drvinfo = be_get_drvinfo,
 	.get_wol = be_get_wol,
 	.set_wol = be_set_wol,
 	.get_link = ethtool_op_get_link,
+	.get_eeprom_len = be_get_eeprom_len,
+	.get_eeprom = be_read_eeprom,
 	.get_coalesce = be_get_coalesce,
 	.set_coalesce = be_set_coalesce,
 	.get_ringparam = be_get_ringparam,
@@ -473,4 +645,6 @@ struct ethtool_ops be_ethtool_ops = {
 	.phys_id = be_phys_id,
 	.get_stats_count = be_get_stats_count,
 	.get_ethtool_stats = be_get_ethtool_stats,
+	.self_test = be_self_test,
+	.self_test_count = be_self_test_count
 };
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 49c91a0..b704e60 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -38,7 +38,6 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
-	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -763,7 +762,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
 
 	/* vlanf could be wrongly set in some cards.
 	 * ignore if vtm is not set */
-	if ((adapter->cap == 0x400) && !vtm)
+	if ((adapter->cap & 0x400) && !vtm)
 		vlanf = 0;
 
 	skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN);
@@ -822,7 +821,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
 
 	/* vlanf could be wrongly set in some cards.
 	 * ignore if vtm is not set */
-	if ((adapter->cap == 0x400) && !vtm)
+	if ((adapter->cap & 0x400) && !vtm)
 		vlanf = 0;
 
 	skb = napi_get_frags(&adapter->napi);
@@ -2146,6 +2145,10 @@ static ssize_t flash_fw_store(struct class_device *cdev, const char *buf,
 	file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0;
 	strncpy(file_name, buf, (ETHTOOL_FLASH_MAX_FILENAME - 1));
 
+	/* Handle situation if filename comes with newline */
+	if (file_name[strlen(file_name) - 1] == '\n')
+		file_name[strlen(file_name) - 1] = '\0';
+
 	status = be_load_fw(adapter, file_name);
 	if (!status)
 		return len;