aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2012-09-19 16:21:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-09-24 15:02:05 -0400
commit803599d4041812a2e90d7e9dd423b6977c56e1fb (patch)
treea8e937074317971342b6800b3e8e240d11658626 /drivers/net/wireless/brcm80211
parent30c52bcf5c294d736b2fccdf7afd93b3af7a95bc (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.c64
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
83struct brcmf_usb_image { 83struct 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};
87static struct brcmf_usb_image g_image = { NULL, 0 }; 89static struct list_head fw_image_list;
88 90
89struct intr_transfer_buf { 91struct 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
1605static 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
1597void brcmf_usb_exit(void) 1616void 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
1605void brcmf_usb_init(void) 1622void 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}