summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/p54/p54usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/p54/p54usb.c')
-rw-r--r--drivers/net/wireless/p54/p54usb.c94
1 files changed, 77 insertions, 17 deletions
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 5de2ebfb28c7..da6640afc835 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -424,9 +424,46 @@ static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
data, len, &alen, 2000);
}
+static const char p54u_romboot_3887[] = "~~~~";
+static const char p54u_firmware_upload_3887[] = "<\r";
+
+static int p54u_device_reset_3887(struct ieee80211_hw *dev)
+{
+ struct p54u_priv *priv = dev->priv;
+ int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING);
+ u8 buf[4];
+
+ if (lock) {
+ ret = usb_lock_device_for_reset(priv->udev, priv->intf);
+ if (ret < 0) {
+ dev_err(&priv->udev->dev, "(p54usb) unable to lock "
+ " device for reset: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = usb_reset_device(priv->udev);
+ if (lock)
+ usb_unlock_device(priv->udev);
+
+ if (ret) {
+ dev_err(&priv->udev->dev, "(p54usb) unable to reset "
+ "device: %d\n", ret);
+ return ret;
+ }
+
+ memcpy(&buf, p54u_romboot_3887, sizeof(buf));
+ ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
+ buf, sizeof(buf));
+ if (ret)
+ dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
+ "boot ROM: %d\n", ret);
+
+ return ret;
+}
+
static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
{
- static char start_string[] = "~~~~<\r";
struct p54u_priv *priv = dev->priv;
const struct firmware *fw_entry = NULL;
int err, alen;
@@ -445,12 +482,9 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
goto err_bufalloc;
}
- memcpy(buf, start_string, 4);
- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
- if (err) {
- dev_err(&priv->udev->dev, "(p54usb) reset failed! (%d)\n", err);
+ err = p54u_device_reset_3887(dev);
+ if (err)
goto err_reset;
- }
err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev);
if (err) {
@@ -466,15 +500,22 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
if (err)
goto err_upload_failed;
+ if (priv->common.fw_interface != FW_LM87) {
+ dev_err(&priv->udev->dev, "wrong firmware, "
+ "please get a LM87 firmware and try again.\n");
+ err = -EINVAL;
+ goto err_upload_failed;
+ }
+
left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
- strcpy(buf, start_string);
- left -= strlen(start_string);
- tmp += strlen(start_string);
+ strcpy(buf, p54u_firmware_upload_3887);
+ left -= strlen(p54u_firmware_upload_3887);
+ tmp += strlen(p54u_firmware_upload_3887);
data = fw_entry->data;
remains = fw_entry->size;
- hdr = (struct x2_header *)(buf + strlen(start_string));
+ hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));
memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
hdr->fw_length = cpu_to_le32(fw_entry->size);
@@ -616,6 +657,14 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
return err;
}
+ if (priv->common.fw_interface != FW_LM86) {
+ dev_err(&priv->udev->dev, "wrong firmware, "
+ "please get a LM86(USB) firmware and try again.\n");
+ kfree(buf);
+ release_firmware(fw_entry);
+ return -EINVAL;
+ }
+
#define P54U_WRITE(type, addr, data) \
do {\
err = p54u_write(priv, buf, type,\
@@ -876,6 +925,9 @@ static int __devinit p54u_probe(struct usb_interface *intf,
SET_IEEE80211_DEV(dev, &intf->dev);
usb_set_intfdata(intf, dev);
priv->udev = udev;
+ priv->intf = intf;
+ skb_queue_head_init(&priv->rx_queue);
+ init_usb_anchor(&priv->submitted);
usb_get_dev(udev);
@@ -918,20 +970,15 @@ static int __devinit p54u_probe(struct usb_interface *intf,
if (err)
goto err_free_dev;
- skb_queue_head_init(&priv->rx_queue);
- init_usb_anchor(&priv->submitted);
-
p54u_open(dev);
err = p54_read_eeprom(dev);
p54u_stop(dev);
if (err)
goto err_free_dev;
- err = ieee80211_register_hw(dev);
- if (err) {
- dev_err(&udev->dev, "(p54usb) Cannot register netdevice\n");
+ err = p54_register_common(dev, &udev->dev);
+ if (err)
goto err_free_dev;
- }
return 0;
@@ -958,11 +1005,24 @@ static void __devexit p54u_disconnect(struct usb_interface *intf)
ieee80211_free_hw(dev);
}
+static int p54u_pre_reset(struct usb_interface *intf)
+{
+ return 0;
+}
+
+static int p54u_post_reset(struct usb_interface *intf)
+{
+ return 0;
+}
+
static struct usb_driver p54u_driver = {
.name = "p54usb",
.id_table = p54u_table,
.probe = p54u_probe,
.disconnect = p54u_disconnect,
+ .pre_reset = p54u_pre_reset,
+ .post_reset = p54u_post_reset,
+ .soft_unbind = 1,
};
static int __init p54u_init(void)