--- /dev/null
+/*
+ * Firmware loading and handling functions.
+ */
+
+#include <linux/firmware.h>
+#include <linux/module.h>
+
+#include "decl.h"
+
+/**
+ * lbs_get_firmware - Retrieves two-stage firmware
+ *
+ * @dev: A pointer to &device structure
+ * @card_model: Bus-specific card model ID used to filter firmware table
+ * elements
+ * @fw_table: Table of firmware file names and device model numbers
+ * terminated by an entry with a NULL helper name
+ * @helper: On success, the helper firmware; caller must free
+ * @mainfw: On success, the main firmware; caller must free
+ *
+ * returns: 0 on success, non-zero on failure
+ */
+int lbs_get_firmware(struct device *dev, 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);
+
+ /* Search for firmware to use from the 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) {
+ /* Clear the helper to ensure we don't have
+ * mismatched firmware pairs.
+ */
+ release_firmware(*helper);
+ *helper = NULL;
+ }
+ }
+
+ if (*helper && *mainfw)
+ return 0;
+
+ next:
+ iter++;
+ }
+
+ /* Failed */
+ release_firmware(*helper);
+ *helper = NULL;
+ release_firmware(*mainfw);
+ *mainfw = NULL;
+
+ return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(lbs_get_firmware);
#define MESSAGE_HEADER_LEN 4
-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");
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
-static int __if_usb_prog_firmware(struct if_usb_card *cardp,
- const char *fwname, int cmd);
-static int if_usb_prog_firmware(struct if_usb_card *cardp,
- const char *fwname, int cmd);
+static int if_usb_prog_firmware(struct if_usb_card *cardp);
static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
uint8_t *payload, uint16_t nb);
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
static int if_usb_reset_device(struct if_usb_card *cardp);
-/* sysfs hooks */
-
-/*
- * Set function to write firmware to device's persistent memory
- */
-static ssize_t if_usb_firmware_set(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct lbs_private *priv = to_net_dev(dev)->ml_priv;
- 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;
-
- return ret;
-}
-
-/*
- * lbs_flash_fw attribute to be exported per ethX interface through sysfs
- * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to
- * the device's persistent memory:
- * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_fw
- */
-static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set);
-
-/**
- * if_usb_boot2_set - write firmware to device's persistent memory
- *
- * @dev: target device
- * @attr: device attributes
- * @buf: firmware buffer to write
- * @count: number of bytes to write
- *
- * returns: number of bytes written or negative error code
- */
-static ssize_t if_usb_boot2_set(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct lbs_private *priv = to_net_dev(dev)->ml_priv;
- 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;
-
- return ret;
-}
-
-/*
- * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs
- * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware
- * to the device's persistent memory:
- * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_boot2
- */
-static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set);
-
/**
* if_usb_write_bulk_callback - callback function to handle the status
* of the URB
}
/* Upload firmware */
- kparam_block_sysfs_write(fw_name);
- if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) {
- kparam_unblock_sysfs_write(fw_name);
+ if (if_usb_prog_firmware(cardp)) {
lbs_deb_usbd(&udev->dev, "FW upload failed\n");
goto err_prog_firmware;
}
- kparam_unblock_sysfs_write(fw_name);
if (!(priv = lbs_add_card(cardp, &intf->dev)))
goto err_prog_firmware;
usb_get_dev(udev);
usb_set_intfdata(intf, cardp);
- if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw))
- netdev_err(priv->dev,
- "cannot register lbs_flash_fw attribute\n");
-
- if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2))
- netdev_err(priv->dev,
- "cannot register lbs_flash_boot2 attribute\n");
-
/*
* EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
*/
lbs_deb_enter(LBS_DEB_MAIN);
- device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2);
- device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_fw);
-
cardp->surprise_removed = 1;
if (priv) {
return ret;
}
-
-/**
-* if_usb_prog_firmware - programs the firmware subject to cmd
-*
-* @cardp: the if_usb_card descriptor
-* @fwname: firmware or boot2 image file name
-* @cmd: either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW,
-* or BOOT_CMD_UPDATE_BOOT2.
-* returns: 0 or error code
-*/
-static int if_usb_prog_firmware(struct if_usb_card *cardp,
- const char *fwname, int cmd)
-{
- struct lbs_private *priv = cardp->priv;
- unsigned long flags, caps;
- int ret;
-
- caps = priv->fwcapinfo;
- if (((cmd == BOOT_CMD_UPDATE_FW) && !(caps & FW_CAPINFO_FIRMWARE_UPGRADE)) ||
- ((cmd == BOOT_CMD_UPDATE_BOOT2) && !(caps & FW_CAPINFO_BOOT2_UPGRADE)))
- return -EOPNOTSUPP;
-
- /* Ensure main thread is idle. */
- spin_lock_irqsave(&priv->driver_lock, flags);
- while (priv->cur_cmd != NULL || priv->dnld_sent != DNLD_RES_RECEIVED) {
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- if (wait_event_interruptible(priv->waitq,
- (priv->cur_cmd == NULL &&
- priv->dnld_sent == DNLD_RES_RECEIVED))) {
- return -ERESTARTSYS;
- }
- spin_lock_irqsave(&priv->driver_lock, flags);
- }
- priv->dnld_sent = DNLD_BOOTCMD_SENT;
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- ret = __if_usb_prog_firmware(cardp, fwname, cmd);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- priv->dnld_sent = DNLD_RES_RECEIVED;
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- wake_up(&priv->waitq);
-
- return ret;
-}
-
/* table of firmware file names */
static const struct {
u32 model;
const char *fwname;
} fw_table[] = {
+ { MODEL_8388, "libertas/usb8388_olpc.bin" },
{ MODEL_8388, "libertas/usb8388_v9.bin" },
{ MODEL_8388, "libertas/usb8388_v5.bin" },
{ MODEL_8388, "libertas/usb8388.bin" },
{ MODEL_8682, "libertas/usb8682.bin" }
};
-#ifdef CONFIG_OLPC
-
-static int try_olpc_fw(struct if_usb_card *cardp)
-{
- int retval = -ENOENT;
-
- /* try the OLPC firmware first; fall back to fw_table list */
- if (machine_is_olpc() && cardp->model == MODEL_8388)
- retval = request_firmware(&cardp->fw,
- "libertas/usb8388_olpc.bin", &cardp->udev->dev);
- return retval;
-}
-
-#else
-static int try_olpc_fw(struct if_usb_card *cardp) { return -ENOENT; }
-#endif /* !CONFIG_OLPC */
-
-static int get_fw(struct if_usb_card *cardp, const char *fwname)
+static int get_fw(struct if_usb_card *cardp)
{
int i;
- /* Try user-specified firmware first */
- if (fwname)
- return request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
-
- /* Handle OLPC firmware */
- if (try_olpc_fw(cardp) == 0)
- return 0;
-
/* Otherwise search for firmware to use */
for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
if (fw_table[i].model != cardp->model)
return -ENOENT;
}
-static int __if_usb_prog_firmware(struct if_usb_card *cardp,
- const char *fwname, int cmd)
+static int if_usb_prog_firmware(struct if_usb_card *cardp)
{
int i = 0;
static int reset_count = 10;
lbs_deb_enter(LBS_DEB_USB);
- ret = get_fw(cardp, fwname);
+ ret = get_fw(cardp);
if (ret) {
pr_err("failed to find firmware (%d)\n", ret);
goto done;
do {
int j = 0;
i++;
- if_usb_issue_boot_command(cardp, cmd);
+ if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
/* wait for command response */
do {
j++;
}
EXPORT_SYMBOL_GPL(lbs_notify_command_response);
-/**
- * lbs_get_firmware - Retrieves two-stage firmware
- *
- * @dev: A pointer to &device structure
- * @user_helper: User-defined helper firmware file
- * @user_mainfw: User-defined main firmware file
- * @card_model: Bus-specific card model ID used to filter firmware table
- * elements
- * @fw_table: Table of firmware file names and device model numbers
- * terminated by an entry with a NULL helper name
- * @helper: On success, the helper firmware; caller must free
- * @mainfw: On success, the main firmware; caller must free
- *
- * returns: 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) {
- dev_err(dev, "couldn't find helper firmware %s\n",
- user_helper);
- goto fail;
- }
- }
- if (user_mainfw) {
- ret = request_firmware(mainfw, user_mainfw, dev);
- if (ret) {
- dev_err(dev, "couldn't find main firmware %s\n",
- 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 */
- release_firmware(*helper);
- *helper = NULL;
- 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);