Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Ivan Vecera <ivecera@redhat.com>
Date: Tue, 21 Sep 2010 09:28:33 -0400
Subject: [net] be2net: use generated MAC addr for VFs, fix BUG_ON
Message-id: <1285061313-15466-1-git-send-email-ivecera@redhat.com>
Patchwork-id: 28324
O-Subject: [RHEL5.6 PATCH] be2net: Assign generated MAC address for VFs and
	remove a bad BUG_ON
Bugzilla: 630680
RH-Acked-by: Michal Schmidt <mschmidt@redhat.com>

BZs:
#630680 - Update be2net to version 2.102.453r

Description:
This patch removes a bad assert and automatically assign MAC addresses to
virtual functions when created. Without this functionality the SR-IOV
support cannot be used since RHEL5 does not have ndops for assigning
VF MAC address and the NIC does not have MAC addresses for VFs in the
EEPROM.

Test status:
Built without any problem. Tested by ServerEngines.

Upstream commits:
9cd9000 be2net: change to call pmac_del only if necessary (PART)
64600ea be2net: add support to get vf config (PART)
6d87f5c be2net: fix to dynamically generate MAC Address for VFs
323f30b be2net: remove a BUG_ON in be_cmds.c
+ RHEL5 specific stuff

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

diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 654dd62..cc12c54 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -30,10 +30,11 @@
 #include <linux/interrupt.h>
 #include <linux/firmware.h>
 #include <linux/ethtool.h>
+#include <linux/jhash.h>
 
 #include "be_hw.h"
 
-#define DRV_VER			"2.102.404r"
+#define DRV_VER			"2.102.453r"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
 #define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
@@ -225,7 +226,14 @@ struct be_rx_obj {
 	struct be_rx_page_info page_info_tbl[RX_Q_LEN];
 };
 
+struct be_vf_cfg {
+	unsigned char vf_mac_addr[ETH_ALEN];
+	u32 vf_if_handle;
+	u32 vf_pmac_id;
+};
+
 #define BE_NUM_MSIX_VECTORS		2	/* 1 each for Tx and Rx */
+#define BE_INVALID_PMAC_ID		0xffffffff
 struct be_adapter {
 	struct pci_dev *pdev;
 	struct net_device *netdev;
@@ -293,8 +301,7 @@ struct be_adapter {
 	struct completion flash_compl;
 
 	bool sriov_enabled;
-	u32 vf_if_handle[BE_MAX_VF];
-	u32 vf_pmac_id[BE_MAX_VF];
+	struct be_vf_cfg vf_cfg[BE_MAX_VF];
 	u8 base_eq_id;
 	u8 is_virtfn;
 };
@@ -407,6 +414,20 @@ static inline u8 is_udp_pkt(struct sk_buff *skb)
 	return val;
 }
 
+static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
+{
+	u32 addr;
+
+	addr = jhash(adapter->netdev->dev_addr, ETH_ALEN, 0);
+
+	mac[5] = (u8)(addr & 0xFF);
+	mac[4] = (u8)((addr >> 8) & 0xFF);
+	mac[3] = (u8)((addr >> 16) & 0xFF);
+	mac[2] = 0xC9;
+	mac[1] = 0x00;
+	mac[0] = 0x00;
+}
+
 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, bool link_up);
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index f78d67c..ce5a6dc 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -138,10 +138,8 @@ int be_process_mcc(struct be_adapter *adapter)
 	while ((compl = be_mcc_compl_get(adapter))) {
 		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
 			/* Interpret flags as an async trailer */
-			BUG_ON(!is_link_state_evt(compl->flags));
-
-			/* Interpret compl as a async link evt */
-			be_async_link_state_process(adapter,
+			if (is_link_state_evt(compl->flags))
+				be_async_link_state_process(adapter,
 				(struct be_async_event_link_state *) compl);
 		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
 				status = be_mcc_compl_process(adapter, compl);
@@ -889,7 +887,7 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
 }
 
 /* Uses mbox */
-int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
+int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, int domain)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_if_destroy *req;
@@ -909,6 +907,7 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req));
 
+	req->hdr.domain = domain;
 	req->interface_id = cpu_to_le32(interface_id);
 
 	status = be_mbox_notify_wait(adapter);
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index cb05274..064d53a 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -910,7 +910,8 @@ extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id);
 extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags,
 			u32 en_flags, u8 *mac, bool pmac_invalid,
 			u32 *if_handle, u32 *pmac_id, u32 domain);
-extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle);
+extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle,
+			int domain);
 extern int be_cmd_eq_create(struct be_adapter *adapter,
 			struct be_queue_info *eq, int eq_delay);
 extern int be_cmd_cq_create(struct be_adapter *adapter,
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 0697b91..02f039b 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -1844,6 +1844,47 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
 	return status;
 }
 
+/*
+ * Generate a seed MAC address from the PF MAC Address using jhash.
+ * MAC Address for VFs are assigned incrementally starting from the seed.
+ * These addresses are programmed in the ASIC by the PF and the VF driver
+ * queries for the MAC address during its probe.
+ */
+static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
+{
+	u32 vf = 0;
+	int status = 0;
+	u8 mac[ETH_ALEN];
+
+	be_vf_eth_addr_generate(adapter, mac);
+
+	for (vf = 0; vf < num_vfs; vf++) {
+		status = be_cmd_pmac_add(adapter, mac,
+					adapter->vf_cfg[vf].vf_if_handle,
+					&adapter->vf_cfg[vf].vf_pmac_id);
+		if (status)
+			dev_err(&adapter->pdev->dev,
+				"Mac address add failed for VF %d\n", vf);
+		else
+			memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN);
+
+		mac[5] += 1;
+	}
+	return status;
+}
+
+static inline void be_vf_eth_addr_rem(struct be_adapter *adapter)
+{
+	u32 vf;
+
+	for (vf = 0; vf < num_vfs; vf++) {
+		if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID)
+			be_cmd_pmac_del(adapter,
+					adapter->vf_cfg[vf].vf_if_handle,
+					adapter->vf_cfg[vf].vf_pmac_id);
+	}
+}
+
 static int be_setup(struct be_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -1871,13 +1912,15 @@ static int be_setup(struct be_adapter *adapter)
 			cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED
 					| BE_IF_FLAGS_BROADCAST;
 			status = be_cmd_if_create(adapter, cap_flags, en_flags,
-					mac, true, &adapter->vf_if_handle[vf],
+					mac, true,
+					&adapter->vf_cfg[vf].vf_if_handle,
 					NULL, vf+1);
 			if (status) {
 				dev_err(&adapter->pdev->dev,
 				"Interface Create failed for VF %d\n", vf);
 				goto if_destroy;
 			}
+			adapter->vf_cfg[vf].vf_pmac_id = BE_INVALID_PMAC_ID;
 			vf++;
 		}
 	} else if (!be_physfn(adapter)) {
@@ -1901,30 +1944,50 @@ static int be_setup(struct be_adapter *adapter)
 	if (status != 0)
 		goto rx_qs_destroy;
 
+	if (be_physfn(adapter)) {
+		status = be_vf_eth_addr_config(adapter);
+		if (status)
+			goto mcc_q_destroy;
+	}
+
 	adapter->link_speed = -1;
 
 	return 0;
 
+mcc_q_destroy:
+	if (be_physfn(adapter))
+		be_vf_eth_addr_rem(adapter);
+	be_mcc_queues_destroy(adapter);
 rx_qs_destroy:
 	be_rx_queues_destroy(adapter);
 tx_qs_destroy:
 	be_tx_queues_destroy(adapter);
 if_destroy:
 	for (vf = 0; vf < num_vfs; vf++)
-		if (adapter->vf_if_handle[vf])
-			be_cmd_if_destroy(adapter, adapter->vf_if_handle[vf]);
-	be_cmd_if_destroy(adapter, adapter->if_handle);
+		if (adapter->vf_cfg[vf].vf_if_handle)
+			be_cmd_if_destroy(adapter,
+					adapter->vf_cfg[vf].vf_if_handle, vf+1);
+	be_cmd_if_destroy(adapter, adapter->if_handle, 0);
 do_none:
 	return status;
 }
 
 static int be_clear(struct be_adapter *adapter)
 {
+	int vf;
+	if (be_physfn(adapter))
+		be_vf_eth_addr_rem(adapter);
+
 	be_mcc_queues_destroy(adapter);
 	be_rx_queues_destroy(adapter);
 	be_tx_queues_destroy(adapter);
 
-	be_cmd_if_destroy(adapter, adapter->if_handle);
+	for (vf = 0; vf < num_vfs; vf++)
+		if (adapter->vf_cfg[vf].vf_if_handle)
+			be_cmd_if_destroy(adapter,
+				adapter->vf_cfg[vf].vf_if_handle, vf+1);
+
+	be_cmd_if_destroy(adapter, adapter->if_handle, 0);
 
 	/* tell fw we're done with firing cmds */
 	be_cmd_fw_clean(adapter);