linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] libertas: firmware loading rework
@ 2010-08-08  2:11 Dan Williams
  2010-08-08  2:13 ` [PATCH 1/5] libertas: [usb] use new firmware locations Dan Williams
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Dan Williams @ 2010-08-08  2:11 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, David Woodhouse, Holger Schurig

I dumped a ton of Libertas firmware into linux-firmware a long time ago,
but the driver was never updated to use the linux-firmware locations.
Fix that.  USB uses one-stage firmware so it doesn't need to use the
common helper.

John: this is 2.6.37 material.

Dan Williams (5):
  libertas: [usb] use new firmware locations
  libertas: add two-stage firmware request helper
  libertas: [cs] use common firmware request helper and new firmware locations
  libertas: [sdio] use common firmware request helper and new firmware locations
  libertas: [spi] use common firmware request helper and new firmware locations

 drivers/net/wireless/libertas/decl.h    |   13 +++
 drivers/net/wireless/libertas/if_cs.c   |  130 ++++++++++++++++------------
 drivers/net/wireless/libertas/if_sdio.c |  143 +++++++++++++------------------
 drivers/net/wireless/libertas/if_sdio.h |    4 -
 drivers/net/wireless/libertas/if_spi.c  |  144 +++++++++++++++----------------
 drivers/net/wireless/libertas/if_spi.h  |    5 -
 drivers/net/wireless/libertas/if_usb.c  |   60 +++++++++++--
 drivers/net/wireless/libertas/if_usb.h  |    1 +
 drivers/net/wireless/libertas/main.c    |  105 ++++++++++++++++++++++
 9 files changed, 375 insertions(+), 230 deletions(-)

-- 
1.7.2.1



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/5] libertas: [usb] use new firmware locations
  2010-08-08  2:11 [PATCH 0/5] libertas: firmware loading rework Dan Williams
@ 2010-08-08  2:13 ` Dan Williams
  2010-08-08  2:14 ` [PATCH 2/5] libertas: add two-stage firmware request helper Dan Williams
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2010-08-08  2:13 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, David Woodhouse, Holger Schurig

Look for firmware where the linux-firmware tree actually puts it, but
fall back to original firmware name & location when the new location
doesn't exist.

Signed-off-by: Dan Williams <dcbw@redhat.com>
---
 drivers/net/wireless/libertas/if_usb.c |   60 ++++++++++++++++++++++++++++----
 drivers/net/wireless/libertas/if_usb.h |    1 +
 2 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 07ece9d..238de10 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -26,15 +26,25 @@
 
 #define MESSAGE_HEADER_LEN	4
 
-static char *lbs_fw_name = "usb8388.bin";
+static char *lbs_fw_name = NULL;
 module_param_named(fw_name, lbs_fw_name, charp, 0644);
 
+MODULE_FIRMWARE("libertas/usb8388_v9.bin");
+MODULE_FIRMWARE("libertas/usb8388_v5.bin");
+MODULE_FIRMWARE("libertas/usb8388.bin");
+MODULE_FIRMWARE("libertas/usb8682.bin");
 MODULE_FIRMWARE("usb8388.bin");
 
+enum {
+	MODEL_UNKNOWN = 0x0,
+	MODEL_8388 = 0x1,
+	MODEL_8682 = 0x2
+};
+
 static struct usb_device_id if_usb_table[] = {
 	/* Enter the device signature inside */
-	{ USB_DEVICE(0x1286, 0x2001) },
-	{ USB_DEVICE(0x05a3, 0x8388) },
+	{ USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 },
+	{ USB_DEVICE(0x05a3, 0x8388), .driver_info = MODEL_8388 },
 	{}	/* Terminating entry */
 };
 
@@ -66,6 +76,8 @@ static ssize_t if_usb_firmware_set(struct device *dev,
 	struct if_usb_card *cardp = priv->card;
 	int ret;
 
+	BUG_ON(buf == NULL);
+
 	ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW);
 	if (ret == 0)
 		return count;
@@ -91,6 +103,8 @@ static ssize_t if_usb_boot2_set(struct device *dev,
 	struct if_usb_card *cardp = priv->card;
 	int ret;
 
+	BUG_ON(buf == NULL);
+
 	ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2);
 	if (ret == 0)
 		return count;
@@ -244,6 +258,7 @@ static int if_usb_probe(struct usb_interface *intf,
 	init_waitqueue_head(&cardp->fw_wq);
 
 	cardp->udev = udev;
+	cardp->model = (uint32_t) id->driver_info;
 	iface_desc = intf->cur_altsetting;
 
 	lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
@@ -921,6 +936,38 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp,
 	return ret;
 }
 
+/* table of firmware file names */
+static const struct {
+	u32 model;
+	const char *fwname;
+} fw_table[] = {
+	{ MODEL_8388, "libertas/usb8388_v9.bin" },
+	{ MODEL_8388, "libertas/usb8388_v5.bin" },
+	{ MODEL_8388, "libertas/usb8388.bin" },
+	{ MODEL_8388, "usb8388.bin" },
+	{ MODEL_8682, "libertas/usb8682.bin" }
+};
+
+static int get_fw(struct if_usb_card *cardp, const char *fwname)
+{
+	int i;
+
+	/* Try user-specified firmware first */
+	if (fwname)
+		return request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
+
+	/* Otherwise search for firmware to use */
+	for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
+		if (fw_table[i].model != cardp->model)
+			continue;
+		if (request_firmware(&cardp->fw, fw_table[i].fwname,
+					&cardp->udev->dev) == 0)
+			return 0;
+	}
+
+	return -ENOENT;
+}
+
 static int __if_usb_prog_firmware(struct if_usb_card *cardp,
 					const char *fwname, int cmd)
 {
@@ -930,10 +977,9 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp,
 
 	lbs_deb_enter(LBS_DEB_USB);
 
-	ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
-	if (ret < 0) {
-		lbs_pr_err("request_firmware() failed with %#x\n", ret);
-		lbs_pr_err("firmware %s not found\n", fwname);
+	ret = get_fw(cardp, fwname);
+	if (ret) {
+		lbs_pr_err("failed to find firmware (%d)\n", ret);
 		goto done;
 	}
 
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index 5ba0aee..d819e7e 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -43,6 +43,7 @@ struct bootcmdresp
 /** USB card description structure*/
 struct if_usb_card {
 	struct usb_device *udev;
+	uint32_t model;  /* MODEL_* */
 	struct urb *rx_urb, *tx_urb;
 	struct lbs_private *priv;
 
-- 
1.7.2.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/5] libertas: add two-stage firmware request helper
  2010-08-08  2:11 [PATCH 0/5] libertas: firmware loading rework Dan Williams
  2010-08-08  2:13 ` [PATCH 1/5] libertas: [usb] use new firmware locations Dan Williams
@ 2010-08-08  2:14 ` Dan Williams
  2010-08-08  2:15 ` [PATCH 3/5] libertas: [cs] use common firmware request helper and new firmware locations Dan Williams
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2010-08-08  2:14 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, David Woodhouse, Holger Schurig

SDIO, GSPI, and CS all use 2-stage firmware and the loading
process and logic should be the same.  Allow module parameters
to override the automatic firmware choice, otherwise just walk
the bus driver's firmware table and pick out the first firmware
pair that exists for the given model.

Some special care is taken to allow overriding of just the helper
or the main firmware, but let the other of the pair be chosen
automatically.

Signed-off-by: Dan Williams <dcbw@redhat.com>
---
 drivers/net/wireless/libertas/decl.h |   13 ++++
 drivers/net/wireless/libertas/main.c |  105 ++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 1d141fe..2ae752d 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -8,7 +8,14 @@
 #define _LBS_DECL_H_
 
 #include <linux/netdevice.h>
+#include <linux/firmware.h>
 
+/* Should be terminated by a NULL entry */
+struct lbs_fw_table {
+	int model;
+	const char *helper;
+	const char *fwname;
+};
 
 struct lbs_private;
 struct sk_buff;
@@ -53,4 +60,10 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
 u32 lbs_fw_index_to_data_rate(u8 index);
 u8 lbs_data_rate_to_fw_index(u32 rate);
 
+int lbs_get_firmware(struct device *dev, const char *user_helper,
+			const char *user_mainfw, u32 card_model,
+			const struct lbs_fw_table *fw_table,
+			const struct firmware **helper,
+			const struct firmware **mainfw);
+
 #endif
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 24958a8..47ce5a6 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1047,6 +1047,111 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
 }
 EXPORT_SYMBOL_GPL(lbs_notify_command_response);
 
+/**
+ *  @brief Retrieves two-stage firmware
+ *
+ *  @param dev     	A pointer to device structure
+ *  @param user_helper	User-defined helper firmware file
+ *  @param user_mainfw	User-defined main firmware file
+ *  @param card_model	Bus-specific card model ID used to filter firmware table
+ *                         elements
+ *  @param fw_table	Table of firmware file names and device model numbers
+ *                         terminated by an entry with a NULL helper name
+ *  @param helper	On success, the helper firmware; caller must free
+ *  @param mainfw	On success, the main firmware; caller must free
+ *
+ *  @return		0 on success, non-zero on failure
+ */
+int lbs_get_firmware(struct device *dev, const char *user_helper,
+			const char *user_mainfw, u32 card_model,
+			const struct lbs_fw_table *fw_table,
+			const struct firmware **helper,
+			const struct firmware **mainfw)
+{
+	const struct lbs_fw_table *iter;
+	int ret;
+
+	BUG_ON(helper == NULL);
+	BUG_ON(mainfw == NULL);
+
+	/* Try user-specified firmware first */
+	if (user_helper) {
+		ret = request_firmware(helper, user_helper, dev);
+		if (ret) {
+			lbs_pr_err("couldn't find helper firmware %s",
+					user_helper);
+			goto fail;
+		}
+	}
+	if (user_mainfw) {
+		ret = request_firmware(mainfw, user_mainfw, dev);
+		if (ret) {
+			lbs_pr_err("couldn't find main firmware %s",
+					user_mainfw);
+			goto fail;
+		}
+	}
+
+	if (*helper && *mainfw)
+		return 0;
+
+	/* Otherwise search for firmware to use.  If neither the helper or
+	 * the main firmware were specified by the user, then we need to
+	 * make sure that found helper & main are from the same entry in
+	 * fw_table.
+	 */
+	iter = fw_table;
+	while (iter && iter->helper) {
+		if (iter->model != card_model)
+			goto next;
+
+		if (*helper == NULL) {
+			ret = request_firmware(helper, iter->helper, dev);
+			if (ret)
+				goto next;
+
+			/* If the device has one-stage firmware (ie cf8305) and
+			 * we've got it then we don't need to bother with the
+			 * main firmware.
+			 */
+			if (iter->fwname == NULL)
+				return 0;
+		}
+
+		if (*mainfw == NULL) {
+			ret = request_firmware(mainfw, iter->fwname, dev);
+			if (ret && !user_helper) {
+				/* Clear the helper if it wasn't user-specified
+				 * and the main firmware load failed, to ensure
+				 * we don't have mismatched firmware pairs.
+				 */
+				release_firmware(*helper);
+				*helper = NULL;
+			}
+		}
+
+		if (*helper && *mainfw)
+			return 0;
+
+  next:
+		iter++;
+	}
+
+  fail:
+	/* Failed */
+	if (*helper) {
+		release_firmware(*helper);
+		*helper = NULL;
+	}
+	if (*mainfw) {
+		release_firmware(*mainfw);
+		*mainfw = NULL;
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(lbs_get_firmware);
+
 static int __init lbs_init_module(void)
 {
 	lbs_deb_enter(LBS_DEB_MAIN);
-- 
1.7.2.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/5] libertas: [cs] use common firmware request helper and new firmware locations
  2010-08-08  2:11 [PATCH 0/5] libertas: firmware loading rework Dan Williams
  2010-08-08  2:13 ` [PATCH 1/5] libertas: [usb] use new firmware locations Dan Williams
  2010-08-08  2:14 ` [PATCH 2/5] libertas: add two-stage firmware request helper Dan Williams
@ 2010-08-08  2:15 ` Dan Williams
  2010-08-08  2:15 ` [PATCH 4/5] libertas: [sdio] " Dan Williams
  2010-08-08  2:16 ` [PATCH 5/5] libertas: [spi] " Dan Williams
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2010-08-08  2:15 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, David Woodhouse, Holger Schurig

linux-firmware puts libertas firmware in /libertas.  Fix the driver to
look there first, but fall back to the old firmware names if the new
ones don't exist.

Signed-off-by: Dan Williams <dcbw@redhat.com>
---
 drivers/net/wireless/libertas/if_cs.c |  130 +++++++++++++++++++--------------
 1 files changed, 74 insertions(+), 56 deletions(-)

diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 08e4e39..a6fd704 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -49,7 +49,6 @@
 MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
 MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
 MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("libertas_cs_helper.fw");
 
 
 
@@ -62,9 +61,34 @@ struct if_cs_card {
 	struct lbs_private *priv;
 	void __iomem *iobase;
 	bool align_regs;
+	u32 model;
 };
 
 
+enum {
+	MODEL_UNKNOWN = 0x00,
+	MODEL_8305 = 0x01,
+	MODEL_8381 = 0x02,
+	MODEL_8385 = 0x03
+};
+
+static const struct lbs_fw_table fw_table[] = {
+	{ MODEL_8305, "libertas/cf8305.bin", NULL },
+	{ MODEL_8305, "libertas_cs_helper.fw", NULL },
+	{ MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" },
+	{ MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" },
+	{ MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" },
+	{ MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" },
+	{ 0, NULL, NULL }
+};
+MODULE_FIRMWARE("libertas/cf8305.bin");
+MODULE_FIRMWARE("libertas/cf8381_helper.bin");
+MODULE_FIRMWARE("libertas/cf8381.bin");
+MODULE_FIRMWARE("libertas/cf8385_helper.bin");
+MODULE_FIRMWARE("libertas/cf8385.bin");
+MODULE_FIRMWARE("libertas_cs_helper.fw");
+MODULE_FIRMWARE("libertas_cs.fw");
+
 
 /********************************************************************/
 /* Hardware access                                                  */
@@ -290,22 +314,19 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
 #define CF8385_MANFID		0x02df
 #define CF8385_CARDID		0x8103
 
-static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev)
-{
-	return (p_dev->manf_id == CF8305_MANFID &&
-		p_dev->card_id == CF8305_CARDID);
-}
-
-static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev)
-{
-	return (p_dev->manf_id == CF8381_MANFID &&
-		p_dev->card_id == CF8381_CARDID);
-}
-
-static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev)
+/* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when
+ * that gets fixed.  Currently there's no way to access it from the probe hook.
+ */
+static inline u32 get_model(u16 manf_id, u16 card_id)
 {
-	return (p_dev->manf_id == CF8385_MANFID &&
-		p_dev->card_id == CF8385_CARDID);
+	/* NOTE: keep in sync with if_cs_ids */
+	if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID)
+		return MODEL_8305;
+	else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID)
+		return MODEL_8381;
+	else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID)
+		return MODEL_8385;
+	return MODEL_UNKNOWN;
 }
 
 /********************************************************************/
@@ -559,12 +580,11 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
  *
  * Return 0 on success
  */
-static int if_cs_prog_helper(struct if_cs_card *card)
+static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
 {
 	int ret = 0;
 	int sent = 0;
 	u8  scratch;
-	const struct firmware *fw;
 
 	lbs_deb_enter(LBS_DEB_CS);
 
@@ -590,14 +610,6 @@ static int if_cs_prog_helper(struct if_cs_card *card)
 		goto done;
 	}
 
-	/* TODO: make firmware file configurable */
-	ret = request_firmware(&fw, "libertas_cs_helper.fw",
-		&card->p_dev->dev);
-	if (ret) {
-		lbs_pr_err("can't load helper firmware\n");
-		ret = -ENODEV;
-		goto done;
-	}
 	lbs_deb_cs("helper size %td\n", fw->size);
 
 	/* "Set the 5 bytes of the helper image to 0" */
@@ -636,7 +648,7 @@ static int if_cs_prog_helper(struct if_cs_card *card)
 		if (ret < 0) {
 			lbs_pr_err("can't download helper at 0x%x, ret %d\n",
 				sent, ret);
-			goto err_release;
+			goto done;
 		}
 
 		if (count == 0)
@@ -645,17 +657,14 @@ static int if_cs_prog_helper(struct if_cs_card *card)
 		sent += count;
 	}
 
-err_release:
-	release_firmware(fw);
 done:
 	lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
 	return ret;
 }
 
 
-static int if_cs_prog_real(struct if_cs_card *card)
+static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
 {
-	const struct firmware *fw;
 	int ret = 0;
 	int retry = 0;
 	int len = 0;
@@ -663,21 +672,13 @@ static int if_cs_prog_real(struct if_cs_card *card)
 
 	lbs_deb_enter(LBS_DEB_CS);
 
-	/* TODO: make firmware file configurable */
-	ret = request_firmware(&fw, "libertas_cs.fw",
-		&card->p_dev->dev);
-	if (ret) {
-		lbs_pr_err("can't load firmware\n");
-		ret = -ENODEV;
-		goto done;
-	}
 	lbs_deb_cs("fw size %td\n", fw->size);
 
 	ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW,
 		IF_CS_SQ_HELPER_OK);
 	if (ret < 0) {
 		lbs_pr_err("helper firmware doesn't answer\n");
-		goto err_release;
+		goto done;
 	}
 
 	for (sent = 0; sent < fw->size; sent += len) {
@@ -692,7 +693,7 @@ static int if_cs_prog_real(struct if_cs_card *card)
 		if (retry > 20) {
 			lbs_pr_err("could not download firmware\n");
 			ret = -ENODEV;
-			goto err_release;
+			goto done;
 		}
 		if (retry) {
 			sent -= len;
@@ -711,7 +712,7 @@ static int if_cs_prog_real(struct if_cs_card *card)
 			IF_CS_BIT_COMMAND);
 		if (ret < 0) {
 			lbs_pr_err("can't download firmware at 0x%x\n", sent);
-			goto err_release;
+			goto done;
 		}
 	}
 
@@ -719,9 +720,6 @@ static int if_cs_prog_real(struct if_cs_card *card)
 	if (ret < 0)
 		lbs_pr_err("firmware download failed\n");
 
-err_release:
-	release_firmware(fw);
-
 done:
 	lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
 	return ret;
@@ -825,6 +823,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	unsigned int prod_id;
 	struct lbs_private *priv;
 	struct if_cs_card *card;
+	const struct firmware *helper = NULL;
+	const struct firmware *mainfw = NULL;
 
 	lbs_deb_enter(LBS_DEB_CS);
 
@@ -844,7 +844,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 		goto out1;
 	}
 
-
 	/*
 	 * Allocate an interrupt line.  Note that this does not assign
 	 * a handler to the interrupt, unless the 'Handler' member of
@@ -883,34 +882,47 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	 */
 	card->align_regs = 0;
 
+	card->model = get_model(p_dev->manf_id, p_dev->card_id);
+	if (card->model == MODEL_UNKNOWN) {
+		lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n",
+			   p_dev->manf_id, p_dev->card_id);
+		goto out2;
+	}
+
 	/* Check if we have a current silicon */
 	prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID);
-	if (if_cs_hw_is_cf8305(p_dev)) {
+	if (card->model == MODEL_8305) {
 		card->align_regs = 1;
 		if (prod_id < IF_CS_CF8305_B1_REV) {
-			lbs_pr_err("old chips like 8305 rev B3 "
-				"aren't supported\n");
+			lbs_pr_err("8305 rev B0 and older are not supported\n");
 			ret = -ENODEV;
 			goto out2;
 		}
 	}
 
-	if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) {
-		lbs_pr_err("old chips like 8381 rev B3 aren't supported\n");
+	if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) {
+		lbs_pr_err("8381 rev B2 and older are not supported\n");
 		ret = -ENODEV;
 		goto out2;
 	}
 
-	if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) {
-		lbs_pr_err("old chips like 8385 rev B1 aren't supported\n");
+	if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) {
+		lbs_pr_err("8385 rev B0 and older are not supported\n");
 		ret = -ENODEV;
 		goto out2;
 	}
 
+	ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model,
+				&fw_table[0], &helper, &mainfw);
+	if (ret) {
+		lbs_pr_err("failed to find firmware (%d)\n", ret);
+		goto out2;
+	}
+
 	/* Load the firmware early, before calling into libertas.ko */
-	ret = if_cs_prog_helper(card);
-	if (ret == 0 && !if_cs_hw_is_cf8305(p_dev))
-		ret = if_cs_prog_real(card);
+	ret = if_cs_prog_helper(card, helper);
+	if (ret == 0 && (card->model != MODEL_8305))
+		ret = if_cs_prog_real(card, mainfw);
 	if (ret)
 		goto out2;
 
@@ -959,6 +971,11 @@ out2:
 out1:
 	pcmcia_disable_device(p_dev);
 out:
+	if (helper)
+		release_firmware(helper);
+	if (mainfw)
+		release_firmware(mainfw);
+
 	lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
 	return ret;
 }
@@ -995,6 +1012,7 @@ static struct pcmcia_device_id if_cs_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID),
 	PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID),
 	PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID),
+	/* NOTE: keep in sync with get_model() */
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
-- 
1.7.2.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/5] libertas: [sdio] use common firmware request helper and new firmware locations
  2010-08-08  2:11 [PATCH 0/5] libertas: firmware loading rework Dan Williams
                   ` (2 preceding siblings ...)
  2010-08-08  2:15 ` [PATCH 3/5] libertas: [cs] use common firmware request helper and new firmware locations Dan Williams
@ 2010-08-08  2:15 ` Dan Williams
  2010-08-08  2:16 ` [PATCH 5/5] libertas: [spi] " Dan Williams
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2010-08-08  2:15 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, David Woodhouse, Holger Schurig

linux-firmware puts libertas firmware in /libertas.  Fix the driver to
look there first, but fall back to the old firmware names if the new
ones don't exist.  Add preference for newer firmware versions too.

Signed-off-by: Dan Williams <dcbw@redhat.com>
---
 drivers/net/wireless/libertas/if_sdio.c |  143 +++++++++++++------------------
 drivers/net/wireless/libertas/if_sdio.h |    4 -
 2 files changed, 60 insertions(+), 87 deletions(-)

diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 6e71346..024e5ca 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -76,36 +76,32 @@ static const struct sdio_device_id if_sdio_ids[] = {
 
 MODULE_DEVICE_TABLE(sdio, if_sdio_ids);
 
-struct if_sdio_model {
-	int model;
-	const char *helper;
-	const char *firmware;
-};
-
-static struct if_sdio_model if_sdio_models[] = {
-	{
-		/* 8385 */
-		.model = IF_SDIO_MODEL_8385,
-		.helper = "sd8385_helper.bin",
-		.firmware = "sd8385.bin",
-	},
-	{
-		/* 8686 */
-		.model = IF_SDIO_MODEL_8686,
-		.helper = "sd8686_helper.bin",
-		.firmware = "sd8686.bin",
-	},
-	{
-		/* 8688 */
-		.model = IF_SDIO_MODEL_8688,
-		.helper = "sd8688_helper.bin",
-		.firmware = "sd8688.bin",
-	},
+#define MODEL_8385	0x04
+#define MODEL_8686	0x0b
+#define MODEL_8688	0x10
+
+static const struct lbs_fw_table fw_table[] = {
+	{ MODEL_8385, "libertas/sd8385_helper.bin", "libertas/sd8385.bin" },
+	{ MODEL_8385, "sd8385_helper.bin", "sd8385.bin" },
+	{ MODEL_8686, "libertas/sd8686_v9_helper.bin", "libertas/sd8686_v9.bin" },
+	{ MODEL_8686, "libertas/sd8686_v8_helper.bin", "libertas/sd8686_v8.bin" },
+	{ MODEL_8686, "sd8686_helper.bin", "sd8686.bin" },
+	{ MODEL_8688, "libertas/sd8688_helper.bin", "libertas/sd8688.bin" },
+	{ MODEL_8688, "sd8688_helper.bin", "sd8688.bin" },
+	{ 0, NULL, NULL }
 };
+MODULE_FIRMWARE("libertas/sd8385_helper.bin");
+MODULE_FIRMWARE("libertas/sd8385.bin");
 MODULE_FIRMWARE("sd8385_helper.bin");
 MODULE_FIRMWARE("sd8385.bin");
+MODULE_FIRMWARE("libertas/sd8686_v9_helper.bin");
+MODULE_FIRMWARE("libertas/sd8686_v9.bin");
+MODULE_FIRMWARE("libertas/sd8686_v8_helper.bin");
+MODULE_FIRMWARE("libertas/sd8686_v8.bin");
 MODULE_FIRMWARE("sd8686_helper.bin");
 MODULE_FIRMWARE("sd8686.bin");
+MODULE_FIRMWARE("libertas/sd8688_helper.bin");
+MODULE_FIRMWARE("libertas/sd8688.bin");
 MODULE_FIRMWARE("sd8688_helper.bin");
 MODULE_FIRMWARE("sd8688.bin");
 
@@ -185,11 +181,11 @@ static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err)
 	u16 rx_len;
 
 	switch (card->model) {
-	case IF_SDIO_MODEL_8385:
-	case IF_SDIO_MODEL_8686:
+	case MODEL_8385:
+	case MODEL_8686:
 		rx_len = if_sdio_read_scratch(card, &ret);
 		break;
-	case IF_SDIO_MODEL_8688:
+	case MODEL_8688:
 	default: /* for newer chipsets */
 		rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret);
 		if (!ret)
@@ -286,7 +282,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
-	if (card->model == IF_SDIO_MODEL_8385) {
+	if (card->model == MODEL_8385) {
 		event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
 		if (ret)
 			goto out;
@@ -464,10 +460,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)
 
 #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY)
 
-static int if_sdio_prog_helper(struct if_sdio_card *card)
+static int if_sdio_prog_helper(struct if_sdio_card *card,
+				const struct firmware *fw)
 {
 	int ret;
-	const struct firmware *fw;
 	unsigned long timeout;
 	u8 *chunk_buffer;
 	u32 chunk_size;
@@ -476,16 +472,10 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
-	ret = request_firmware(&fw, card->helper, &card->func->dev);
-	if (ret) {
-		lbs_pr_err("can't load helper firmware\n");
-		goto out;
-	}
-
 	chunk_buffer = kzalloc(64, GFP_KERNEL);
 	if (!chunk_buffer) {
 		ret = -ENOMEM;
-		goto release_fw;
+		goto out;
 	}
 
 	sdio_claim_host(card->func);
@@ -560,22 +550,19 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)
 release:
 	sdio_release_host(card->func);
 	kfree(chunk_buffer);
-release_fw:
-	release_firmware(fw);
 
 out:
 	if (ret)
 		lbs_pr_err("failed to load helper firmware\n");
 
 	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
 	return ret;
 }
 
-static int if_sdio_prog_real(struct if_sdio_card *card)
+static int if_sdio_prog_real(struct if_sdio_card *card,
+				const struct firmware *fw)
 {
 	int ret;
-	const struct firmware *fw;
 	unsigned long timeout;
 	u8 *chunk_buffer;
 	u32 chunk_size;
@@ -584,16 +571,10 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
-	ret = request_firmware(&fw, card->firmware, &card->func->dev);
-	if (ret) {
-		lbs_pr_err("can't load firmware\n");
-		goto out;
-	}
-
 	chunk_buffer = kzalloc(512, GFP_KERNEL);
 	if (!chunk_buffer) {
 		ret = -ENOMEM;
-		goto release_fw;
+		goto out;
 	}
 
 	sdio_claim_host(card->func);
@@ -683,15 +664,12 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
 release:
 	sdio_release_host(card->func);
 	kfree(chunk_buffer);
-release_fw:
-	release_firmware(fw);
 
 out:
 	if (ret)
 		lbs_pr_err("failed to load firmware\n");
 
 	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
 	return ret;
 }
 
@@ -699,6 +677,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
 {
 	int ret;
 	u16 scratch;
+	const struct firmware *helper = NULL;
+	const struct firmware *mainfw = NULL;
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
@@ -716,11 +696,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
 		goto success;
 	}
 
-	ret = if_sdio_prog_helper(card);
+	ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name,
+				card->model, &fw_table[0], &helper, &mainfw);
+	if (ret) {
+		lbs_pr_err("failed to find firmware (%d)\n", ret);
+		goto out;
+	}
+
+	ret = if_sdio_prog_helper(card, helper);
 	if (ret)
 		goto out;
 
-	ret = if_sdio_prog_real(card);
+	ret = if_sdio_prog_real(card, mainfw);
 	if (ret)
 		goto out;
 
@@ -731,8 +718,12 @@ success:
 	ret = 0;
 
 out:
-	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+	if (helper)
+		release_firmware(helper);
+	if (mainfw)
+		release_firmware(mainfw);
 
+	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
 	return ret;
 }
 
@@ -936,7 +927,7 @@ static int if_sdio_probe(struct sdio_func *func,
 				"ID: %x", &model) == 1)
 			break;
 		if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
-			model = IF_SDIO_MODEL_8385;
+			model = MODEL_8385;
 			break;
 		}
 	}
@@ -954,13 +945,13 @@ static int if_sdio_probe(struct sdio_func *func,
 	card->model = model;
 
 	switch (card->model) {
-	case IF_SDIO_MODEL_8385:
+	case MODEL_8385:
 		card->scratch_reg = IF_SDIO_SCRATCH_OLD;
 		break;
-	case IF_SDIO_MODEL_8686:
+	case MODEL_8686:
 		card->scratch_reg = IF_SDIO_SCRATCH;
 		break;
-	case IF_SDIO_MODEL_8688:
+	case MODEL_8688:
 	default: /* for newer chipsets */
 		card->scratch_reg = IF_SDIO_FW_STATUS;
 		break;
@@ -970,31 +961,17 @@ static int if_sdio_probe(struct sdio_func *func,
 	card->workqueue = create_workqueue("libertas_sdio");
 	INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
 
-	for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) {
-		if (card->model == if_sdio_models[i].model)
+	/* Check if we support this card */
+	for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
+		if (card->model == fw_table[i].model)
 			break;
 	}
-
-	if (i == ARRAY_SIZE(if_sdio_models)) {
+	if (i == ARRAY_SIZE(fw_table)) {
 		lbs_pr_err("unknown card model 0x%x\n", card->model);
 		ret = -ENODEV;
 		goto free;
 	}
 
-	card->helper = if_sdio_models[i].helper;
-	card->firmware = if_sdio_models[i].firmware;
-
-	if (lbs_helper_name) {
-		lbs_deb_sdio("overriding helper firmware: %s\n",
-			lbs_helper_name);
-		card->helper = lbs_helper_name;
-	}
-
-	if (lbs_fw_name) {
-		lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name);
-		card->firmware = lbs_fw_name;
-	}
-
 	sdio_claim_host(func);
 
 	ret = sdio_enable_func(func);
@@ -1008,7 +985,7 @@ static int if_sdio_probe(struct sdio_func *func,
 	/* For 1-bit transfers to the 8686 model, we need to enable the
 	 * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
 	 * bit to allow access to non-vendor registers. */
-	if ((card->model == IF_SDIO_MODEL_8686) &&
+	if ((card->model == MODEL_8686) &&
 	    (host->caps & MMC_CAP_SDIO_IRQ) &&
 	    (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
 		u8 reg;
@@ -1071,8 +1048,8 @@ static int if_sdio_probe(struct sdio_func *func,
 	 * Get rx_unit if the chip is SD8688 or newer.
 	 * SD8385 & SD8686 do not have rx_unit.
 	 */
-	if ((card->model != IF_SDIO_MODEL_8385)
-			&& (card->model != IF_SDIO_MODEL_8686))
+	if ((card->model != MODEL_8385)
+			&& (card->model != MODEL_8686))
 		card->rx_unit = if_sdio_read_rx_unit(card);
 	else
 		card->rx_unit = 0;
@@ -1088,7 +1065,7 @@ static int if_sdio_probe(struct sdio_func *func,
 	/*
 	 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
 	 */
-	if (card->model == IF_SDIO_MODEL_8688) {
+	if (card->model == MODEL_8688) {
 		struct cmd_header cmd;
 
 		memset(&cmd, 0, sizeof(cmd));
@@ -1141,7 +1118,7 @@ static void if_sdio_remove(struct sdio_func *func)
 
 	card = sdio_get_drvdata(func);
 
-	if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) {
+	if (user_rmmod && (card->model == MODEL_8688)) {
 		/*
 		 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT
 		 * multiple functions
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
index 12179c1..62fda35 100644
--- a/drivers/net/wireless/libertas/if_sdio.h
+++ b/drivers/net/wireless/libertas/if_sdio.h
@@ -12,10 +12,6 @@
 #ifndef _LBS_IF_SDIO_H
 #define _LBS_IF_SDIO_H
 
-#define IF_SDIO_MODEL_8385	0x04
-#define IF_SDIO_MODEL_8686	0x0b
-#define IF_SDIO_MODEL_8688	0x10
-
 #define IF_SDIO_IOPORT		0x00
 
 #define IF_SDIO_H_INT_MASK	0x04
-- 
1.7.2.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5/5] libertas: [spi] use common firmware request helper and new firmware locations
  2010-08-08  2:11 [PATCH 0/5] libertas: firmware loading rework Dan Williams
                   ` (3 preceding siblings ...)
  2010-08-08  2:15 ` [PATCH 4/5] libertas: [sdio] " Dan Williams
@ 2010-08-08  2:16 ` Dan Williams
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2010-08-08  2:16 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, David Woodhouse, Holger Schurig

linux-firmware puts libertas firmware in /libertas.  Fix the driver to
look there first, but fall back to the old firmware names if the new
ones don't exist.  Add preference for newer firmware versions too.

Signed-off-by: Dan Williams <dcbw@redhat.com>
---
 drivers/net/wireless/libertas/if_spi.c |  144 +++++++++++++++-----------------
 drivers/net/wireless/libertas/if_spi.h |    5 -
 2 files changed, 69 insertions(+), 80 deletions(-)

diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index fe3f080..012e7fd 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -39,9 +39,6 @@ struct if_spi_card {
 	struct lbs_private		*priv;
 	struct libertas_spi_platform_data *pdata;
 
-	char				helper_fw_name[IF_SPI_FW_NAME_MAX];
-	char				main_fw_name[IF_SPI_FW_NAME_MAX];
-
 	/* The card ID and card revision, as reported by the hardware. */
 	u16				card_id;
 	u8				card_rev;
@@ -70,10 +67,28 @@ static void free_if_spi_card(struct if_spi_card *card)
 	kfree(card);
 }
 
-static struct chip_ident chip_id_to_device_name[] = {
-	{ .chip_id = 0x04, .name = 8385 },
-	{ .chip_id = 0x0b, .name = 8686 },
+#define MODEL_8385	0x04
+#define MODEL_8686	0x0b
+#define MODEL_8688	0x10
+
+static const struct lbs_fw_table fw_table[] = {
+	{ MODEL_8385, "libertas/gspi8385_helper.bin", "libertas/gspi8385.bin" },
+	{ MODEL_8385, "libertas/gspi8385_hlp.bin", "libertas/gspi8385.bin" },
+	{ MODEL_8686, "libertas/gspi8686_v9_helper.bin", "libertas/gspi8686_v9.bin" },
+	{ MODEL_8686, "libertas/gspi8686_hlp.bin", "libertas/gspi8686.bin" },
+	{ MODEL_8688, "libertas/gspi8688_helper.bin", "libertas/gspi8688.bin" },
+	{ 0, NULL, NULL }
 };
+MODULE_FIRMWARE("libertas/gspi8385_helper.bin");
+MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8385.bin");
+MODULE_FIRMWARE("libertas/gspi8686_v9_helper.bin");
+MODULE_FIRMWARE("libertas/gspi8686_v9.bin");
+MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8686.bin");
+MODULE_FIRMWARE("libertas/gspi8688_helper.bin");
+MODULE_FIRMWARE("libertas/gspi8688.bin");
+
 
 /*
  * SPI Interface Unit Routines
@@ -399,26 +414,20 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes)
  * Firmware Loading
  */
 
-static int if_spi_prog_helper_firmware(struct if_spi_card *card)
+static int if_spi_prog_helper_firmware(struct if_spi_card *card,
+					const struct firmware *firmware)
 {
 	int err = 0;
-	const struct firmware *firmware = NULL;
 	int bytes_remaining;
 	const u8 *fw;
 	u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
-	struct spi_device *spi = card->spi;
 
 	lbs_deb_enter(LBS_DEB_SPI);
 
 	err = spu_set_interrupt_mode(card, 1, 0);
 	if (err)
 		goto out;
-	/* Get helper firmware image */
-	err = request_firmware(&firmware, card->helper_fw_name, &spi->dev);
-	if (err) {
-		lbs_pr_err("request_firmware failed with err = %d\n", err);
-		goto out;
-	}
+
 	bytes_remaining = firmware->size;
 	fw = firmware->data;
 
@@ -429,13 +438,13 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card)
 		err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
 					HELPER_FW_LOAD_CHUNK_SZ);
 		if (err)
-			goto release_firmware;
+			goto out;
 
 		err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
 					IF_SPI_HIST_CMD_DOWNLOAD_RDY,
 					IF_SPI_HIST_CMD_DOWNLOAD_RDY);
 		if (err)
-			goto release_firmware;
+			goto out;
 
 		/* Feed the data into the command read/write port reg
 		 * in chunks of 64 bytes */
@@ -446,16 +455,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card)
 		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
 					temp, HELPER_FW_LOAD_CHUNK_SZ);
 		if (err)
-			goto release_firmware;
+			goto out;
 
 		/* Interrupt the boot code */
 		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
 		if (err)
-			goto release_firmware;
+			goto out;
 		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
 				       IF_SPI_CIC_CMD_DOWNLOAD_OVER);
 		if (err)
-			goto release_firmware;
+			goto out;
 		bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
 		fw += HELPER_FW_LOAD_CHUNK_SZ;
 	}
@@ -465,18 +474,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card)
 	 * bootloader. This completes the helper download. */
 	err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
 	if (err)
-		goto release_firmware;
+		goto out;
 	err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
 	if (err)
-		goto release_firmware;
+		goto out;
 	err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
 				IF_SPI_CIC_CMD_DOWNLOAD_OVER);
-		goto release_firmware;
+		goto out;
 
 	lbs_deb_spi("waiting for helper to boot...\n");
 
-release_firmware:
-	release_firmware(firmware);
 out:
 	if (err)
 		lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
@@ -523,13 +530,12 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
 	return len;
 }
 
-static int if_spi_prog_main_firmware(struct if_spi_card *card)
+static int if_spi_prog_main_firmware(struct if_spi_card *card,
+					const struct firmware *firmware)
 {
 	int len, prev_len;
 	int bytes, crc_err = 0, err = 0;
-	const struct firmware *firmware = NULL;
 	const u8 *fw;
-	struct spi_device *spi = card->spi;
 	u16 num_crc_errs;
 
 	lbs_deb_enter(LBS_DEB_SPI);
@@ -538,19 +544,11 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
 	if (err)
 		goto out;
 
-	/* Get firmware image */
-	err = request_firmware(&firmware, card->main_fw_name, &spi->dev);
-	if (err) {
-		lbs_pr_err("%s: can't get firmware '%s' from kernel. "
-			"err = %d\n", __func__, card->main_fw_name, err);
-		goto out;
-	}
-
 	err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
 	if (err) {
 		lbs_pr_err("%s: timed out waiting for initial "
 			   "scratch reg = 0\n", __func__);
-		goto release_firmware;
+		goto out;
 	}
 
 	num_crc_errs = 0;
@@ -560,7 +558,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
 	while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
 		if (len < 0) {
 			err = len;
-			goto release_firmware;
+			goto out;
 		}
 		if (bytes < 0) {
 			/* If there are no more bytes left, we would normally
@@ -575,7 +573,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
 				lbs_pr_err("Too many CRC errors encountered "
 					   "in firmware load.\n");
 				err = -EIO;
-				goto release_firmware;
+				goto out;
 			}
 		} else {
 			/* Previous transfer succeeded. Advance counters. */
@@ -590,15 +588,15 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
 
 		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
 		if (err)
-			goto release_firmware;
+			goto out;
 		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
 				card->cmd_buffer, len);
 		if (err)
-			goto release_firmware;
+			goto out;
 		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
 					IF_SPI_CIC_CMD_DOWNLOAD_OVER);
 		if (err)
-			goto release_firmware;
+			goto out;
 		prev_len = len;
 	}
 	if (bytes > prev_len) {
@@ -611,12 +609,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
 					SUCCESSFUL_FW_DOWNLOAD_MAGIC);
 	if (err) {
 		lbs_pr_err("failed to confirm the firmware download\n");
-		goto release_firmware;
+		goto out;
 	}
 
-release_firmware:
-	release_firmware(firmware);
-
 out:
 	if (err)
 		lbs_pr_err("failed to load firmware (err=%d)\n", err);
@@ -886,37 +881,16 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
  * SPI callbacks
  */
 
-static int if_spi_calculate_fw_names(u16 card_id,
-			      char *helper_fw, char *main_fw)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
-		if (card_id == chip_id_to_device_name[i].chip_id)
-			break;
-	}
-	if (i == ARRAY_SIZE(chip_id_to_device_name)) {
-		lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
-		return -EAFNOSUPPORT;
-	}
-	snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin",
-		 chip_id_to_device_name[i].name);
-	snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin",
-		 chip_id_to_device_name[i].name);
-	return 0;
-}
-MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
-MODULE_FIRMWARE("libertas/gspi8385.bin");
-MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
-MODULE_FIRMWARE("libertas/gspi8686.bin");
-
 static int __devinit if_spi_probe(struct spi_device *spi)
 {
 	struct if_spi_card *card;
 	struct lbs_private *priv = NULL;
 	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
-	int err = 0;
+	int err = 0, i;
 	u32 scratch;
 	struct sched_param param = { .sched_priority = 1 };
+	const struct firmware *helper = NULL;
+	const struct firmware *mainfw = NULL;
 
 	lbs_deb_enter(LBS_DEB_SPI);
 
@@ -961,10 +935,25 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 		lbs_deb_spi("Firmware is already loaded for "
 			    "Marvell WLAN 802.11 adapter\n");
 	else {
-		err = if_spi_calculate_fw_names(card->card_id,
-				card->helper_fw_name, card->main_fw_name);
-		if (err)
+		/* Check if we support this card */
+		for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
+			if (card->card_id == fw_table[i].model)
+				break;
+		}
+		if (i == ARRAY_SIZE(fw_table)) {
+			lbs_pr_err("Unsupported chip_id: 0x%02x\n",
+					card->card_id);
+			err = -ENODEV;
 			goto free_card;
+		}
+
+		err = lbs_get_firmware(&card->spi->dev, NULL, NULL,
+					card->card_id, &fw_table[0], &helper,
+					&mainfw);
+		if (err) {
+			lbs_pr_err("failed to find firmware (%d)\n", err);
+			goto free_card;
+		}
 
 		lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
 				"(chip_id = 0x%04x, chip_rev = 0x%02x) "
@@ -973,10 +962,10 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 				card->card_id, card->card_rev,
 				spi->master->bus_num, spi->chip_select,
 				spi->max_speed_hz);
-		err = if_spi_prog_helper_firmware(card);
+		err = if_spi_prog_helper_firmware(card, helper);
 		if (err)
 			goto free_card;
-		err = if_spi_prog_main_firmware(card);
+		err = if_spi_prog_main_firmware(card, mainfw);
 		if (err)
 			goto free_card;
 		lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
@@ -1044,6 +1033,11 @@ remove_card:
 free_card:
 	free_if_spi_card(card);
 out:
+	if (helper)
+		release_firmware(helper);
+	if (mainfw)
+		release_firmware(mainfw);
+
 	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
 	return err;
 }
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h
index f87eec4..8b1417d 100644
--- a/drivers/net/wireless/libertas/if_spi.h
+++ b/drivers/net/wireless/libertas/if_spi.h
@@ -25,11 +25,6 @@
 
 #define IF_SPI_FW_NAME_MAX 30
 
-struct chip_ident {
-	u16 chip_id;
-	u16 name;
-};
-
 #define MAX_MAIN_FW_LOAD_CRC_ERR 10
 
 /* Chunk size when loading the helper firmware */
-- 
1.7.2.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-08-08  2:15 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-08  2:11 [PATCH 0/5] libertas: firmware loading rework Dan Williams
2010-08-08  2:13 ` [PATCH 1/5] libertas: [usb] use new firmware locations Dan Williams
2010-08-08  2:14 ` [PATCH 2/5] libertas: add two-stage firmware request helper Dan Williams
2010-08-08  2:15 ` [PATCH 3/5] libertas: [cs] use common firmware request helper and new firmware locations Dan Williams
2010-08-08  2:15 ` [PATCH 4/5] libertas: [sdio] " Dan Williams
2010-08-08  2:16 ` [PATCH 5/5] libertas: [spi] " Dan Williams

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).