Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Andy Gospodarek <gospo@redhat.com>
Date: Thu, 4 Dec 2008 16:40:19 -0500
Subject: [net] cxgb3: fixup embedded firmware problems
Message-id: 20081204214018.GF26358@gospo.rdu.redhat.com
O-Subject: [RHEL5.3 PATCH] cxgb3: fixup embedded firmware problems
Bugzilla: 469774
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: John W. Linville <linville@redhat.com>
RH-Acked-by: David Miller <davem@redhat.com>

This should resolve the problems that arose from the patch I mistakenly
posted last week and was included in the last snapshot.

One thing different about this patch, is the local disk is first checked
for firmware, and if it's not available the embedded firmware is used.
The advantage here is that any locally installed firmware with the
correct name will be used before the embedded firmware.  This will be
helpful if Chelsio finds a bug in their existing firmware and needs a
way to get a quick update out without having to load new kernels.

This patch as in my test kernels and has been tested by myself as well
as the reporter.  This will resolve RHBZ 469774.

diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 1134287..cb7efd3 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -834,24 +834,22 @@ static int bind_qsets(struct adapter *adap)
 	return err;
 }
 
+static void t3_release_firmware(const struct firmware *fw)
+{
+	if (!t3_local_firmware_free(fw))
+		return;
+	release_firmware(fw);
+}	
 
 static int t3_request_firmware(const struct firmware **firmware, const char *name,
                  struct device *dev)
 {
-	/* first we will see if this firmware is stored in the driver */
-	printk(KERN_CRIT "%s: checking to see if we have embedded firmware for %s\n",
-			__FUNCTION__, name);
-
-	if (t3_firmware_read(firmware, name))
+	/* first check if there is firmware on the filesystem */
+	if (!request_firmware(firmware, name, dev)) {
 		return 0;
+	}
 
-	printk(KERN_CRIT "%s: embedded firmware not found, looking for %s on filesystem\n",
-			__FUNCTION__, name);
-
-	if (!(*firmware)->data && !(*firmware)->size)	
-		return request_firmware(firmware, name, dev);
-
-	return -ENODEV;
+	return t3_local_firmware_load(firmware, name);
 }
 
 
@@ -874,7 +872,7 @@ static int upgrade_fw(struct adapter *adap)
 		return ret;
 	}
 	ret = t3_load_fw(adap, fw->data, fw->size);
-	release_firmware(fw);
+	t3_release_firmware(fw);
 
 	if (ret == 0)
 		dev_info(dev, "successful upgrade to firmware %d.%d.%d\n",
@@ -941,7 +939,7 @@ static int update_tpsram(struct adapter *adap)
 		dev_err(dev, "loading protocol SRAM failed\n");
 
 release_tpsram:
-	release_firmware(tpsram);
+	t3_release_firmware(tpsram);
 
 	return ret;
 }
diff --git a/drivers/net/cxgb3/t3_firmware.h b/drivers/net/cxgb3/t3_firmware.h
index 66f5041..1ade1cc 100644
--- a/drivers/net/cxgb3/t3_firmware.h
+++ b/drivers/net/cxgb3/t3_firmware.h
@@ -1820,6 +1820,7 @@ static u8 t3b_protocol_sram_data[] = {
 	0x08, 0x34, 0x02, 0x30, 0x00, 0xc0, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x70, 0xea, 0xa5, 0x7f };
 
+
 /* contents of t3c_protocol_sram-1.1.0.bin */
 static u8 t3c_protocol_sram_data[] = {
 	0xff, 0xff, 0xff, 0xf4, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
@@ -1985,47 +1986,60 @@ static u8 t3c_protocol_sram_data[] = {
 	0x70, 0xea, 0xa7, 0x41 };
 
 
-
 struct t3_firmware_map {
-	char	name[128];
-	u8	*data;	
+	char		name[128];
+	u8		*data;	
+	int		size;
+	struct firmware	*fw;
 };
 
 /* this matches up the firmware names with the raw data files */
 static struct t3_firmware_map fw_map[] = {
-	{ "t3fw-6.0.0.bin", t3fw_data },
-	{ "t3b_protocol_sram-1.1.0.bin", t3b_protocol_sram_data },
-	{ "t3c_protocol_sram-1.1.0.bin", t3c_protocol_sram_data },
+	{ "t3fw-6.0.0.bin", t3fw_data , sizeof(t3fw_data), NULL},
+	{ "t3b_protocol_sram-1.1.0.bin", t3b_protocol_sram_data, sizeof(t3b_protocol_sram_data), NULL },
+	{ "t3c_protocol_sram-1.1.0.bin", t3c_protocol_sram_data, sizeof(t3c_protocol_sram_data), NULL },
 };
 
+static inline int t3_local_firmware_free(const struct firmware *firmware)
+{
+	int i;
+
+	for (i=0; i < (sizeof(fw_map) / sizeof(struct t3_firmware_map)); i++)
+		if (fw_map[i].fw == firmware) {
+			kfree(firmware);
+			fw_map[i].fw = NULL;
+			return 0;
+		}
+	return -ENODEV;
+}
+
 /* one function to pass the data out when a filename is requested */
-static inline int t3_firmware_read(const struct firmware **firmware, const char *name)
+static inline int t3_local_firmware_load(const struct firmware **firmware, const char *name)
 {
 	int i; 
 	struct firmware *fw;
-	u8 *data = NULL;
-	int size = 0;
+	struct t3_firmware_map *t3fw_entry = NULL;
 
 	/* check to see if we've got that entry in our table */
-	for (i=0; i < sizeof(fw_map); i++) {
+	for (i=0; i < (sizeof(fw_map) / sizeof(struct t3_firmware_map)); i++) {
 		if (strstr(name, fw_map[i].name)) {
-			data = fw_map[i].data;
-			size = sizeof(fw_map[i].data);
-			printk (KERN_CRIT "%s: We have firmware for %s loaded in the driver! (len = %d)\n",__FUNCTION__,name,size);
+			t3fw_entry = &fw_map[i];
 		}
 	}
 
 	/* if we've got a hit, allocate the memory and populate the pointer */
-	if (data && size) {
+	if (t3fw_entry) {
         	*firmware = fw = kzalloc(sizeof(*firmware), GFP_KERNEL);
 		if (!firmware) {
 			printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
 					__FUNCTION__);
 			return -ENOMEM;
 		}
-		fw->data = data;
-		fw->size = size;
+		fw->data = t3fw_entry->data;
+		fw->size = t3fw_entry->size;
+		t3fw_entry->fw = fw;
+		printk("firmware: trying embedded firmware since %s unavailable.\n", name);
 	}
-	
+
 	return 0;
 }