diff options
author | Hante Meuleman <meuleman@broadcom.com> | 2012-09-19 16:21:10 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-09-24 15:02:05 -0400 |
commit | 803599d4041812a2e90d7e9dd423b6977c56e1fb (patch) | |
tree | a8e937074317971342b6800b3e8e240d11658626 /drivers/net/wireless/brcm80211 | |
parent | 30c52bcf5c294d736b2fccdf7afd93b3af7a95bc (diff) |
brcmfmac: store usb fw images in local linked list.
For suspend/resume it is necessary to store firmware in memory.
In order to support multiple usb dongles at the same time a linked
list of firmwares was created.
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/usb.c | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 03f59cd0572..edb431182d1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -81,10 +81,12 @@ enum usbdev_suspend_state { | |||
81 | }; | 81 | }; |
82 | 82 | ||
83 | struct brcmf_usb_image { | 83 | struct brcmf_usb_image { |
84 | void *data; | 84 | struct list_head list; |
85 | u32 len; | 85 | s8 *fwname; |
86 | u8 *image; | ||
87 | int image_len; | ||
86 | }; | 88 | }; |
87 | static struct brcmf_usb_image g_image = { NULL, 0 }; | 89 | static struct list_head fw_image_list; |
88 | 90 | ||
89 | struct intr_transfer_buf { | 91 | struct intr_transfer_buf { |
90 | u32 notification; | 92 | u32 notification; |
@@ -1152,10 +1154,6 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo) | |||
1152 | { | 1154 | { |
1153 | brcmf_dbg(TRACE, "devinfo %p\n", devinfo); | 1155 | brcmf_dbg(TRACE, "devinfo %p\n", devinfo); |
1154 | 1156 | ||
1155 | /* store the image globally */ | ||
1156 | g_image.data = devinfo->image; | ||
1157 | g_image.len = devinfo->image_len; | ||
1158 | |||
1159 | /* free the URBS */ | 1157 | /* free the URBS */ |
1160 | brcmf_usb_free_q(&devinfo->rx_freeq, false); | 1158 | brcmf_usb_free_q(&devinfo->rx_freeq, false); |
1161 | brcmf_usb_free_q(&devinfo->tx_freeq, false); | 1159 | brcmf_usb_free_q(&devinfo->tx_freeq, false); |
@@ -1207,17 +1205,9 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) | |||
1207 | { | 1205 | { |
1208 | s8 *fwname; | 1206 | s8 *fwname; |
1209 | const struct firmware *fw; | 1207 | const struct firmware *fw; |
1208 | struct brcmf_usb_image *fw_image; | ||
1210 | int err; | 1209 | int err; |
1211 | 1210 | ||
1212 | devinfo->image = g_image.data; | ||
1213 | devinfo->image_len = g_image.len; | ||
1214 | |||
1215 | /* | ||
1216 | * if we have an image we can leave here. | ||
1217 | */ | ||
1218 | if (devinfo->image) | ||
1219 | return 0; | ||
1220 | |||
1221 | switch (devinfo->bus_pub.devid) { | 1211 | switch (devinfo->bus_pub.devid) { |
1222 | case 43143: | 1212 | case 43143: |
1223 | fwname = BRCMF_USB_43143_FW_NAME; | 1213 | fwname = BRCMF_USB_43143_FW_NAME; |
@@ -1235,6 +1225,14 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) | |||
1235 | break; | 1225 | break; |
1236 | } | 1226 | } |
1237 | 1227 | ||
1228 | list_for_each_entry(fw_image, &fw_image_list, list) { | ||
1229 | if (fw_image->fwname == fwname) { | ||
1230 | devinfo->image = fw_image->image; | ||
1231 | devinfo->image_len = fw_image->image_len; | ||
1232 | return 0; | ||
1233 | } | ||
1234 | } | ||
1235 | /* fw image not yet loaded. Load it now and add to list */ | ||
1238 | err = request_firmware(&fw, fwname, devinfo->dev); | 1236 | err = request_firmware(&fw, fwname, devinfo->dev); |
1239 | if (!fw) { | 1237 | if (!fw) { |
1240 | brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname); | 1238 | brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname); |
@@ -1245,14 +1243,24 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) | |||
1245 | return -EINVAL; | 1243 | return -EINVAL; |
1246 | } | 1244 | } |
1247 | 1245 | ||
1248 | devinfo->image = vmalloc(fw->size); /* plus nvram */ | 1246 | fw_image = kzalloc(sizeof(*fw_image), GFP_ATOMIC); |
1249 | if (!devinfo->image) | 1247 | if (!fw_image) |
1248 | return -ENOMEM; | ||
1249 | INIT_LIST_HEAD(&fw_image->list); | ||
1250 | list_add_tail(&fw_image->list, &fw_image_list); | ||
1251 | fw_image->fwname = fwname; | ||
1252 | fw_image->image = vmalloc(fw->size); | ||
1253 | if (!fw_image->image) | ||
1250 | return -ENOMEM; | 1254 | return -ENOMEM; |
1251 | 1255 | ||
1252 | memcpy(devinfo->image, fw->data, fw->size); | 1256 | memcpy(fw_image->image, fw->data, fw->size); |
1253 | devinfo->image_len = fw->size; | 1257 | fw_image->image_len = fw->size; |
1254 | 1258 | ||
1255 | release_firmware(fw); | 1259 | release_firmware(fw); |
1260 | |||
1261 | devinfo->image = fw_image->image; | ||
1262 | devinfo->image_len = fw_image->image_len; | ||
1263 | |||
1256 | return 0; | 1264 | return 0; |
1257 | } | 1265 | } |
1258 | 1266 | ||
@@ -1594,15 +1602,25 @@ static struct usb_driver brcmf_usbdrvr = { | |||
1594 | .disable_hub_initiated_lpm = 1, | 1602 | .disable_hub_initiated_lpm = 1, |
1595 | }; | 1603 | }; |
1596 | 1604 | ||
1605 | static void brcmf_release_fw(struct list_head *q) | ||
1606 | { | ||
1607 | struct brcmf_usb_image *fw_image, *next; | ||
1608 | |||
1609 | list_for_each_entry_safe(fw_image, next, q, list) { | ||
1610 | vfree(fw_image->image); | ||
1611 | list_del_init(&fw_image->list); | ||
1612 | } | ||
1613 | } | ||
1614 | |||
1615 | |||
1597 | void brcmf_usb_exit(void) | 1616 | void brcmf_usb_exit(void) |
1598 | { | 1617 | { |
1599 | usb_deregister(&brcmf_usbdrvr); | 1618 | usb_deregister(&brcmf_usbdrvr); |
1600 | vfree(g_image.data); | 1619 | brcmf_release_fw(&fw_image_list); |
1601 | g_image.data = NULL; | ||
1602 | g_image.len = 0; | ||
1603 | } | 1620 | } |
1604 | 1621 | ||
1605 | void brcmf_usb_init(void) | 1622 | void brcmf_usb_init(void) |
1606 | { | 1623 | { |
1624 | INIT_LIST_HEAD(&fw_image_list); | ||
1607 | usb_register(&brcmf_usbdrvr); | 1625 | usb_register(&brcmf_usbdrvr); |
1608 | } | 1626 | } |