mirror of
https://github.com/torvalds/linux
synced 2024-10-24 04:06:04 +00:00
p54usb: rework driver for resume
This patch redo the driver code so that p54usb no longer hangs the kernel on resume. Signed-off-by: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
a406ac0dc1
commit
1ca5f2e94c
|
@ -81,6 +81,29 @@ static struct usb_device_id p54u_table[] __devinitdata = {
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(usb, p54u_table);
|
MODULE_DEVICE_TABLE(usb, p54u_table);
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
u32 intf;
|
||||||
|
enum p54u_hw_type type;
|
||||||
|
char fw[FIRMWARE_NAME_MAX];
|
||||||
|
char fw_legacy[FIRMWARE_NAME_MAX];
|
||||||
|
char hw[20];
|
||||||
|
} p54u_fwlist[__NUM_P54U_HWTYPES] = {
|
||||||
|
{
|
||||||
|
.type = P54U_NET2280,
|
||||||
|
.intf = FW_LM86,
|
||||||
|
.fw = "isl3886usb",
|
||||||
|
.fw_legacy = "isl3890usb",
|
||||||
|
.hw = "ISL3886 + net2280",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = P54U_3887,
|
||||||
|
.intf = FW_LM87,
|
||||||
|
.fw = "isl3887usb",
|
||||||
|
.fw_legacy = "isl3887usb_bare",
|
||||||
|
.hw = "ISL3887",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static void p54u_rx_cb(struct urb *urb)
|
static void p54u_rx_cb(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = (struct sk_buff *) urb->context;
|
struct sk_buff *skb = (struct sk_buff *) urb->context;
|
||||||
|
@ -125,11 +148,7 @@ static void p54u_rx_cb(struct urb *urb)
|
||||||
}
|
}
|
||||||
skb_reset_tail_pointer(skb);
|
skb_reset_tail_pointer(skb);
|
||||||
skb_trim(skb, 0);
|
skb_trim(skb, 0);
|
||||||
if (urb->transfer_buffer != skb_tail_pointer(skb)) {
|
urb->transfer_buffer = skb_tail_pointer(skb);
|
||||||
/* this should not happen */
|
|
||||||
WARN_ON(1);
|
|
||||||
urb->transfer_buffer = skb_tail_pointer(skb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
skb_queue_tail(&priv->rx_queue, skb);
|
skb_queue_tail(&priv->rx_queue, skb);
|
||||||
usb_anchor_urb(urb, &priv->submitted);
|
usb_anchor_urb(urb, &priv->submitted);
|
||||||
|
@ -378,20 +397,16 @@ static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
|
||||||
data, len, &alen, 2000);
|
data, len, &alen, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char p54u_romboot_3887[] = "~~~~";
|
static int p54u_device_reset(struct ieee80211_hw *dev)
|
||||||
static const char p54u_firmware_upload_3887[] = "<\r";
|
|
||||||
|
|
||||||
static int p54u_device_reset_3887(struct ieee80211_hw *dev)
|
|
||||||
{
|
{
|
||||||
struct p54u_priv *priv = dev->priv;
|
struct p54u_priv *priv = dev->priv;
|
||||||
int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING);
|
int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING);
|
||||||
u8 buf[4];
|
|
||||||
|
|
||||||
if (lock) {
|
if (lock) {
|
||||||
ret = usb_lock_device_for_reset(priv->udev, priv->intf);
|
ret = usb_lock_device_for_reset(priv->udev, priv->intf);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&priv->udev->dev, "(p54usb) unable to lock "
|
dev_err(&priv->udev->dev, "(p54usb) unable to lock "
|
||||||
" device for reset: %d\n", ret);
|
"device for reset (%d)!\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,26 +415,34 @@ static int p54u_device_reset_3887(struct ieee80211_hw *dev)
|
||||||
if (lock)
|
if (lock)
|
||||||
usb_unlock_device(priv->udev);
|
usb_unlock_device(priv->udev);
|
||||||
|
|
||||||
if (ret) {
|
if (ret)
|
||||||
dev_err(&priv->udev->dev, "(p54usb) unable to reset "
|
dev_err(&priv->udev->dev, "(p54usb) unable to reset "
|
||||||
"device: %d\n", ret);
|
"device (%d)!\n", ret);
|
||||||
return ret;
|
|
||||||
}
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char p54u_romboot_3887[] = "~~~~";
|
||||||
|
static int p54u_firmware_reset_3887(struct ieee80211_hw *dev)
|
||||||
|
{
|
||||||
|
struct p54u_priv *priv = dev->priv;
|
||||||
|
u8 buf[4];
|
||||||
|
int ret;
|
||||||
|
|
||||||
memcpy(&buf, p54u_romboot_3887, sizeof(buf));
|
memcpy(&buf, p54u_romboot_3887, sizeof(buf));
|
||||||
ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
|
ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
|
||||||
buf, sizeof(buf));
|
buf, sizeof(buf));
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
|
dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
|
||||||
"boot ROM: %d\n", ret);
|
"boot ROM (%d)!\n", ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char p54u_firmware_upload_3887[] = "<\r";
|
||||||
static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
|
static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
|
||||||
{
|
{
|
||||||
struct p54u_priv *priv = dev->priv;
|
struct p54u_priv *priv = dev->priv;
|
||||||
const struct firmware *fw_entry = NULL;
|
|
||||||
int err, alen;
|
int err, alen;
|
||||||
u8 carry = 0;
|
u8 carry = 0;
|
||||||
u8 *buf, *tmp;
|
u8 *buf, *tmp;
|
||||||
|
@ -428,51 +451,29 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
|
||||||
struct x2_header *hdr;
|
struct x2_header *hdr;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
|
err = p54u_firmware_reset_3887(dev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
|
tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware"
|
dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware"
|
||||||
"upload buffer!\n");
|
"upload buffer!\n");
|
||||||
err = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto err_bufalloc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = p54u_device_reset_3887(dev);
|
left = block_size = min((size_t)P54U_FW_BLOCK, priv->fw->size);
|
||||||
if (err)
|
|
||||||
goto err_reset;
|
|
||||||
|
|
||||||
err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev);
|
|
||||||
if (err) {
|
|
||||||
dev_err(&priv->udev->dev, "p54usb: cannot find firmware "
|
|
||||||
"(isl3887usb)\n");
|
|
||||||
err = request_firmware(&fw_entry, "isl3887usb_bare",
|
|
||||||
&priv->udev->dev);
|
|
||||||
if (err)
|
|
||||||
goto err_req_fw_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p54_parse_firmware(dev, fw_entry);
|
|
||||||
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, p54u_firmware_upload_3887);
|
strcpy(buf, p54u_firmware_upload_3887);
|
||||||
left -= strlen(p54u_firmware_upload_3887);
|
left -= strlen(p54u_firmware_upload_3887);
|
||||||
tmp += strlen(p54u_firmware_upload_3887);
|
tmp += strlen(p54u_firmware_upload_3887);
|
||||||
|
|
||||||
data = fw_entry->data;
|
data = priv->fw->data;
|
||||||
remains = fw_entry->size;
|
remains = priv->fw->size;
|
||||||
|
|
||||||
hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));
|
hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));
|
||||||
memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
|
memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
|
||||||
hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
|
hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
|
||||||
hdr->fw_length = cpu_to_le32(fw_entry->size);
|
hdr->fw_length = cpu_to_le32(priv->fw->size);
|
||||||
hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
|
hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
|
||||||
sizeof(u32)*2));
|
sizeof(u32)*2));
|
||||||
left -= sizeof(*hdr);
|
left -= sizeof(*hdr);
|
||||||
|
@ -514,7 +515,8 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
|
||||||
left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
|
left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
|
||||||
}
|
}
|
||||||
|
|
||||||
*((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
|
*((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, priv->fw->data,
|
||||||
|
priv->fw->size));
|
||||||
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
|
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
|
dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
|
||||||
|
@ -565,19 +567,14 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
|
||||||
if (err)
|
if (err)
|
||||||
goto err_upload_failed;
|
goto err_upload_failed;
|
||||||
|
|
||||||
err_upload_failed:
|
err_upload_failed:
|
||||||
release_firmware(fw_entry);
|
|
||||||
err_req_fw_failed:
|
|
||||||
err_reset:
|
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
err_bufalloc:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
|
static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
|
||||||
{
|
{
|
||||||
struct p54u_priv *priv = dev->priv;
|
struct p54u_priv *priv = dev->priv;
|
||||||
const struct firmware *fw_entry = NULL;
|
|
||||||
const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
|
const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
|
||||||
int err, alen;
|
int err, alen;
|
||||||
void *buf;
|
void *buf;
|
||||||
|
@ -592,33 +589,6 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = request_firmware(&fw_entry, "isl3886usb", &priv->udev->dev);
|
|
||||||
if (err) {
|
|
||||||
dev_err(&priv->udev->dev, "(p54usb) cannot find firmware "
|
|
||||||
"(isl3886usb)\n");
|
|
||||||
err = request_firmware(&fw_entry, "isl3890usb",
|
|
||||||
&priv->udev->dev);
|
|
||||||
if (err) {
|
|
||||||
kfree(buf);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p54_parse_firmware(dev, fw_entry);
|
|
||||||
if (err) {
|
|
||||||
kfree(buf);
|
|
||||||
release_firmware(fw_entry);
|
|
||||||
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) \
|
#define P54U_WRITE(type, addr, data) \
|
||||||
do {\
|
do {\
|
||||||
err = p54u_write(priv, buf, type,\
|
err = p54u_write(priv, buf, type,\
|
||||||
|
@ -718,8 +688,8 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
|
||||||
P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
|
P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
|
||||||
|
|
||||||
/* finally, we can upload firmware now! */
|
/* finally, we can upload firmware now! */
|
||||||
remains = fw_entry->size;
|
remains = priv->fw->size;
|
||||||
data = fw_entry->data;
|
data = priv->fw->data;
|
||||||
offset = ISL38XX_DEV_FIRMWARE_ADDR;
|
offset = ISL38XX_DEV_FIRMWARE_ADDR;
|
||||||
|
|
||||||
while (remains) {
|
while (remains) {
|
||||||
|
@ -828,12 +798,54 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
|
||||||
#undef P54U_WRITE
|
#undef P54U_WRITE
|
||||||
#undef P54U_READ
|
#undef P54U_READ
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
release_firmware(fw_entry);
|
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int p54u_load_firmware(struct ieee80211_hw *dev)
|
||||||
|
{
|
||||||
|
struct p54u_priv *priv = dev->priv;
|
||||||
|
int err, i;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES);
|
||||||
|
|
||||||
|
for (i = 0; i < __NUM_P54U_HWTYPES; i++)
|
||||||
|
if (p54u_fwlist[i].type == priv->hw_type)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i == __NUM_P54U_HWTYPES)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
|
||||||
|
"(%d)!\n", p54u_fwlist[i].fw, err);
|
||||||
|
|
||||||
|
err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy,
|
||||||
|
&priv->udev->dev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = p54_parse_firmware(dev, priv->fw);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (priv->common.fw_interface != p54u_fwlist[i].intf) {
|
||||||
|
dev_err(&priv->udev->dev, "wrong firmware, please get "
|
||||||
|
"a firmware for \"%s\" and try again.\n",
|
||||||
|
p54u_fwlist[i].hw);
|
||||||
|
err = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (err)
|
||||||
|
release_firmware(priv->fw);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int p54u_open(struct ieee80211_hw *dev)
|
static int p54u_open(struct ieee80211_hw *dev)
|
||||||
{
|
{
|
||||||
struct p54u_priv *priv = dev->priv;
|
struct p54u_priv *priv = dev->priv;
|
||||||
|
@ -875,6 +887,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
|
||||||
}
|
}
|
||||||
|
|
||||||
priv = dev->priv;
|
priv = dev->priv;
|
||||||
|
priv->hw_type = P54U_INVALID_HW;
|
||||||
|
|
||||||
SET_IEEE80211_DEV(dev, &intf->dev);
|
SET_IEEE80211_DEV(dev, &intf->dev);
|
||||||
usb_set_intfdata(intf, dev);
|
usb_set_intfdata(intf, dev);
|
||||||
|
@ -906,34 +919,46 @@ static int __devinit p54u_probe(struct usb_interface *intf,
|
||||||
priv->common.open = p54u_open;
|
priv->common.open = p54u_open;
|
||||||
priv->common.stop = p54u_stop;
|
priv->common.stop = p54u_stop;
|
||||||
if (recognized_pipes < P54U_PIPE_NUMBER) {
|
if (recognized_pipes < P54U_PIPE_NUMBER) {
|
||||||
|
/* ISL3887 needs a full reset on resume */
|
||||||
|
udev->reset_resume = 1;
|
||||||
|
err = p54u_device_reset(dev);
|
||||||
|
|
||||||
priv->hw_type = P54U_3887;
|
priv->hw_type = P54U_3887;
|
||||||
dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
|
dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
|
||||||
priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
|
priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
|
||||||
priv->common.tx = p54u_tx_lm87;
|
priv->common.tx = p54u_tx_lm87;
|
||||||
err = p54u_upload_firmware_3887(dev);
|
priv->upload_fw = p54u_upload_firmware_3887;
|
||||||
} else {
|
} else {
|
||||||
priv->hw_type = P54U_NET2280;
|
priv->hw_type = P54U_NET2280;
|
||||||
dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
|
dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
|
||||||
priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
|
priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
|
||||||
priv->common.tx = p54u_tx_net2280;
|
priv->common.tx = p54u_tx_net2280;
|
||||||
err = p54u_upload_firmware_net2280(dev);
|
priv->upload_fw = p54u_upload_firmware_net2280;
|
||||||
}
|
}
|
||||||
|
err = p54u_load_firmware(dev);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_free_dev;
|
goto err_free_dev;
|
||||||
|
|
||||||
|
err = priv->upload_fw(dev);
|
||||||
|
if (err)
|
||||||
|
goto err_free_fw;
|
||||||
|
|
||||||
p54u_open(dev);
|
p54u_open(dev);
|
||||||
err = p54_read_eeprom(dev);
|
err = p54_read_eeprom(dev);
|
||||||
p54u_stop(dev);
|
p54u_stop(dev);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_free_dev;
|
goto err_free_fw;
|
||||||
|
|
||||||
err = p54_register_common(dev, &udev->dev);
|
err = p54_register_common(dev, &udev->dev);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_free_dev;
|
goto err_free_fw;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_free_dev:
|
err_free_fw:
|
||||||
|
release_firmware(priv->fw);
|
||||||
|
|
||||||
|
err_free_dev:
|
||||||
ieee80211_free_hw(dev);
|
ieee80211_free_hw(dev);
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
usb_put_dev(udev);
|
usb_put_dev(udev);
|
||||||
|
@ -952,20 +977,64 @@ static void __devexit p54u_disconnect(struct usb_interface *intf)
|
||||||
|
|
||||||
priv = dev->priv;
|
priv = dev->priv;
|
||||||
usb_put_dev(interface_to_usbdev(intf));
|
usb_put_dev(interface_to_usbdev(intf));
|
||||||
|
release_firmware(priv->fw);
|
||||||
p54_free_common(dev);
|
p54_free_common(dev);
|
||||||
ieee80211_free_hw(dev);
|
ieee80211_free_hw(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int p54u_pre_reset(struct usb_interface *intf)
|
static int p54u_pre_reset(struct usb_interface *intf)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_hw *dev = usb_get_intfdata(intf);
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
p54u_stop(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int p54u_resume(struct usb_interface *intf)
|
||||||
|
{
|
||||||
|
struct ieee80211_hw *dev = usb_get_intfdata(intf);
|
||||||
|
struct p54u_priv *priv;
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
priv = dev->priv;
|
||||||
|
if (unlikely(!(priv->upload_fw && priv->fw)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return priv->upload_fw(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static int p54u_post_reset(struct usb_interface *intf)
|
static int p54u_post_reset(struct usb_interface *intf)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_hw *dev = usb_get_intfdata(intf);
|
||||||
|
struct p54u_priv *priv;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = p54u_resume(intf);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* reinitialize old device state */
|
||||||
|
priv = dev->priv;
|
||||||
|
if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED)
|
||||||
|
ieee80211_restart_hw(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
|
||||||
|
static int p54u_suspend(struct usb_interface *intf, pm_message_t message)
|
||||||
|
{
|
||||||
|
return p54u_pre_reset(intf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
static struct usb_driver p54u_driver = {
|
static struct usb_driver p54u_driver = {
|
||||||
.name = "p54usb",
|
.name = "p54usb",
|
||||||
.id_table = p54u_table,
|
.id_table = p54u_table,
|
||||||
|
@ -973,6 +1042,11 @@ static struct usb_driver p54u_driver = {
|
||||||
.disconnect = p54u_disconnect,
|
.disconnect = p54u_disconnect,
|
||||||
.pre_reset = p54u_pre_reset,
|
.pre_reset = p54u_pre_reset,
|
||||||
.post_reset = p54u_post_reset,
|
.post_reset = p54u_post_reset,
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.suspend = p54u_suspend,
|
||||||
|
.resume = p54u_resume,
|
||||||
|
.reset_resume = p54u_resume,
|
||||||
|
#endif /* CONFIG_PM */
|
||||||
.soft_unbind = 1,
|
.soft_unbind = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -123,18 +123,26 @@ struct p54u_rx_info {
|
||||||
struct ieee80211_hw *dev;
|
struct ieee80211_hw *dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum p54u_hw_type {
|
||||||
|
P54U_INVALID_HW,
|
||||||
|
P54U_NET2280,
|
||||||
|
P54U_3887,
|
||||||
|
|
||||||
|
/* keep last */
|
||||||
|
__NUM_P54U_HWTYPES,
|
||||||
|
};
|
||||||
|
|
||||||
struct p54u_priv {
|
struct p54u_priv {
|
||||||
struct p54_common common;
|
struct p54_common common;
|
||||||
struct usb_device *udev;
|
struct usb_device *udev;
|
||||||
struct usb_interface *intf;
|
struct usb_interface *intf;
|
||||||
enum {
|
int (*upload_fw)(struct ieee80211_hw *dev);
|
||||||
P54U_NET2280 = 0,
|
|
||||||
P54U_3887
|
|
||||||
} hw_type;
|
|
||||||
|
|
||||||
|
enum p54u_hw_type hw_type;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
struct sk_buff_head rx_queue;
|
struct sk_buff_head rx_queue;
|
||||||
struct usb_anchor submitted;
|
struct usb_anchor submitted;
|
||||||
|
const struct firmware *fw;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* P54USB_H */
|
#endif /* P54USB_H */
|
||||||
|
|
Loading…
Reference in a new issue