diff options
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/usb.c | 119 |
1 files changed, 39 insertions, 80 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 6e3ff6f61103..c6d5aeb27a02 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -80,20 +80,6 @@ enum usbdev_suspend_state { | |||
80 | USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */ | 80 | USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */ |
81 | }; | 81 | }; |
82 | 82 | ||
83 | struct brcmf_usb_probe_info { | ||
84 | void *usbdev_info; | ||
85 | struct usb_device *usb; /* USB device pointer from OS */ | ||
86 | uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2; | ||
87 | int intr_size; /* Size of interrupt message */ | ||
88 | int interval; /* Interrupt polling interval */ | ||
89 | int vid; | ||
90 | int pid; | ||
91 | enum usb_device_speed device_speed; | ||
92 | enum usbdev_suspend_state suspend_state; | ||
93 | struct usb_interface *intf; | ||
94 | }; | ||
95 | static struct brcmf_usb_probe_info usbdev_probe_info; | ||
96 | |||
97 | struct brcmf_usb_image { | 83 | struct brcmf_usb_image { |
98 | void *data; | 84 | void *data; |
99 | u32 len; | 85 | u32 len; |
@@ -134,7 +120,6 @@ struct brcmf_usbdev_info { | |||
134 | 120 | ||
135 | struct usb_device *usbdev; | 121 | struct usb_device *usbdev; |
136 | struct device *dev; | 122 | struct device *dev; |
137 | enum usb_device_speed device_speed; | ||
138 | 123 | ||
139 | int ctl_in_pipe, ctl_out_pipe; | 124 | int ctl_in_pipe, ctl_out_pipe; |
140 | struct urb *ctl_urb; /* URB for control endpoint */ | 125 | struct urb *ctl_urb; /* URB for control endpoint */ |
@@ -154,9 +139,6 @@ struct brcmf_usbdev_info { | |||
154 | int intr_size; /* Size of interrupt message */ | 139 | int intr_size; /* Size of interrupt message */ |
155 | int interval; /* Interrupt polling interval */ | 140 | int interval; /* Interrupt polling interval */ |
156 | struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */ | 141 | struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */ |
157 | |||
158 | struct brcmf_usb_probe_info probe_info; | ||
159 | |||
160 | }; | 142 | }; |
161 | 143 | ||
162 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, | 144 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, |
@@ -1166,11 +1148,8 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo) | |||
1166 | } | 1148 | } |
1167 | 1149 | ||
1168 | 1150 | ||
1169 | static void brcmf_usb_detach(const struct brcmf_usbdev *bus_pub) | 1151 | static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo) |
1170 | { | 1152 | { |
1171 | struct brcmf_usbdev_info *devinfo = | ||
1172 | (struct brcmf_usbdev_info *)bus_pub; | ||
1173 | |||
1174 | brcmf_dbg(TRACE, "devinfo %p\n", devinfo); | 1153 | brcmf_dbg(TRACE, "devinfo %p\n", devinfo); |
1175 | 1154 | ||
1176 | /* store the image globally */ | 1155 | /* store the image globally */ |
@@ -1187,7 +1166,6 @@ static void brcmf_usb_detach(const struct brcmf_usbdev *bus_pub) | |||
1187 | 1166 | ||
1188 | kfree(devinfo->tx_reqs); | 1167 | kfree(devinfo->tx_reqs); |
1189 | kfree(devinfo->rx_reqs); | 1168 | kfree(devinfo->rx_reqs); |
1190 | kfree(devinfo); | ||
1191 | } | 1169 | } |
1192 | 1170 | ||
1193 | #define TRX_MAGIC 0x30524448 /* "HDR0" */ | 1171 | #define TRX_MAGIC 0x30524448 /* "HDR0" */ |
@@ -1280,14 +1258,9 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) | |||
1280 | 1258 | ||
1281 | 1259 | ||
1282 | static | 1260 | static |
1283 | struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev) | 1261 | struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo, |
1262 | int nrxq, int ntxq) | ||
1284 | { | 1263 | { |
1285 | struct brcmf_usbdev_info *devinfo; | ||
1286 | |||
1287 | devinfo = kzalloc(sizeof(struct brcmf_usbdev_info), GFP_ATOMIC); | ||
1288 | if (devinfo == NULL) | ||
1289 | return NULL; | ||
1290 | |||
1291 | devinfo->bus_pub.nrxq = nrxq; | 1264 | devinfo->bus_pub.nrxq = nrxq; |
1292 | devinfo->rx_low_watermark = nrxq / 2; | 1265 | devinfo->rx_low_watermark = nrxq / 2; |
1293 | devinfo->bus_pub.devinfo = devinfo; | 1266 | devinfo->bus_pub.devinfo = devinfo; |
@@ -1296,18 +1269,6 @@ struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev) | |||
1296 | /* flow control when too many tx urbs posted */ | 1269 | /* flow control when too many tx urbs posted */ |
1297 | devinfo->tx_low_watermark = ntxq / 4; | 1270 | devinfo->tx_low_watermark = ntxq / 4; |
1298 | devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3; | 1271 | devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3; |
1299 | devinfo->dev = dev; | ||
1300 | devinfo->usbdev = usbdev_probe_info.usb; | ||
1301 | devinfo->tx_pipe = usbdev_probe_info.tx_pipe; | ||
1302 | devinfo->rx_pipe = usbdev_probe_info.rx_pipe; | ||
1303 | devinfo->rx_pipe2 = usbdev_probe_info.rx_pipe2; | ||
1304 | devinfo->intr_pipe = usbdev_probe_info.intr_pipe; | ||
1305 | |||
1306 | devinfo->interval = usbdev_probe_info.interval; | ||
1307 | devinfo->intr_size = usbdev_probe_info.intr_size; | ||
1308 | |||
1309 | memcpy(&devinfo->probe_info, &usbdev_probe_info, | ||
1310 | sizeof(struct brcmf_usb_probe_info)); | ||
1311 | devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE; | 1272 | devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE; |
1312 | 1273 | ||
1313 | /* Initialize other structure content */ | 1274 | /* Initialize other structure content */ |
@@ -1366,19 +1327,19 @@ struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev) | |||
1366 | 1327 | ||
1367 | error: | 1328 | error: |
1368 | brcmf_dbg(ERROR, "failed!\n"); | 1329 | brcmf_dbg(ERROR, "failed!\n"); |
1369 | brcmf_usb_detach(&devinfo->bus_pub); | 1330 | brcmf_usb_detach(devinfo); |
1370 | return NULL; | 1331 | return NULL; |
1371 | } | 1332 | } |
1372 | 1333 | ||
1373 | static int brcmf_usb_probe_cb(struct device *dev, const char *desc, | 1334 | static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo, |
1374 | u32 bustype, u32 hdrlen) | 1335 | const char *desc, u32 bustype, u32 hdrlen) |
1375 | { | 1336 | { |
1376 | struct brcmf_bus *bus = NULL; | 1337 | struct brcmf_bus *bus = NULL; |
1377 | struct brcmf_usbdev *bus_pub = NULL; | 1338 | struct brcmf_usbdev *bus_pub = NULL; |
1378 | int ret; | 1339 | int ret; |
1340 | struct device *dev = devinfo->dev; | ||
1379 | 1341 | ||
1380 | 1342 | bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ); | |
1381 | bus_pub = brcmf_usb_attach(BRCMF_USB_NRXQ, BRCMF_USB_NTXQ, dev); | ||
1382 | if (!bus_pub) { | 1343 | if (!bus_pub) { |
1383 | ret = -ENODEV; | 1344 | ret = -ENODEV; |
1384 | goto fail; | 1345 | goto fail; |
@@ -1417,23 +1378,21 @@ static int brcmf_usb_probe_cb(struct device *dev, const char *desc, | |||
1417 | return 0; | 1378 | return 0; |
1418 | fail: | 1379 | fail: |
1419 | /* Release resources in reverse order */ | 1380 | /* Release resources in reverse order */ |
1420 | if (bus_pub) | ||
1421 | brcmf_usb_detach(bus_pub); | ||
1422 | kfree(bus); | 1381 | kfree(bus); |
1382 | brcmf_usb_detach(devinfo); | ||
1423 | return ret; | 1383 | return ret; |
1424 | } | 1384 | } |
1425 | 1385 | ||
1426 | static void | 1386 | static void |
1427 | brcmf_usb_disconnect_cb(struct brcmf_usbdev *bus_pub) | 1387 | brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo) |
1428 | { | 1388 | { |
1429 | if (!bus_pub) | 1389 | if (!devinfo) |
1430 | return; | 1390 | return; |
1431 | brcmf_dbg(TRACE, "enter: bus_pub %p\n", bus_pub); | 1391 | brcmf_dbg(TRACE, "enter: bus_pub %p\n", devinfo); |
1432 | |||
1433 | brcmf_detach(bus_pub->devinfo->dev); | ||
1434 | kfree(bus_pub->bus); | ||
1435 | brcmf_usb_detach(bus_pub); | ||
1436 | 1392 | ||
1393 | brcmf_detach(devinfo->dev); | ||
1394 | kfree(devinfo->bus_pub.bus); | ||
1395 | brcmf_usb_detach(devinfo); | ||
1437 | } | 1396 | } |
1438 | 1397 | ||
1439 | static int | 1398 | static int |
@@ -1445,18 +1404,18 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1445 | struct usb_device *usb = interface_to_usbdev(intf); | 1404 | struct usb_device *usb = interface_to_usbdev(intf); |
1446 | int num_of_eps; | 1405 | int num_of_eps; |
1447 | u8 endpoint_num; | 1406 | u8 endpoint_num; |
1407 | struct brcmf_usbdev_info *devinfo; | ||
1448 | 1408 | ||
1449 | brcmf_dbg(TRACE, "enter\n"); | 1409 | brcmf_dbg(TRACE, "enter\n"); |
1450 | 1410 | ||
1451 | usbdev_probe_info.usb = usb; | 1411 | devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC); |
1452 | usbdev_probe_info.intf = intf; | 1412 | if (devinfo == NULL) |
1413 | return -ENOMEM; | ||
1453 | 1414 | ||
1454 | if (id != NULL) { | 1415 | devinfo->usbdev = usb; |
1455 | usbdev_probe_info.vid = id->idVendor; | 1416 | devinfo->dev = &usb->dev; |
1456 | usbdev_probe_info.pid = id->idProduct; | ||
1457 | } | ||
1458 | 1417 | ||
1459 | usb_set_intfdata(intf, &usbdev_probe_info); | 1418 | usb_set_intfdata(intf, devinfo); |
1460 | 1419 | ||
1461 | /* Check that the device supports only one configuration */ | 1420 | /* Check that the device supports only one configuration */ |
1462 | if (usb->descriptor.bNumConfigurations != 1) { | 1421 | if (usb->descriptor.bNumConfigurations != 1) { |
@@ -1505,11 +1464,11 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1505 | } | 1464 | } |
1506 | 1465 | ||
1507 | endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 1466 | endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
1508 | usbdev_probe_info.intr_pipe = usb_rcvintpipe(usb, endpoint_num); | 1467 | devinfo->intr_pipe = usb_rcvintpipe(usb, endpoint_num); |
1509 | 1468 | ||
1510 | usbdev_probe_info.rx_pipe = 0; | 1469 | devinfo->rx_pipe = 0; |
1511 | usbdev_probe_info.rx_pipe2 = 0; | 1470 | devinfo->rx_pipe2 = 0; |
1512 | usbdev_probe_info.tx_pipe = 0; | 1471 | devinfo->tx_pipe = 0; |
1513 | num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1; | 1472 | num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1; |
1514 | 1473 | ||
1515 | /* Check data endpoints and get pipes */ | 1474 | /* Check data endpoints and get pipes */ |
@@ -1526,35 +1485,33 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1526 | USB_ENDPOINT_NUMBER_MASK; | 1485 | USB_ENDPOINT_NUMBER_MASK; |
1527 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 1486 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) |
1528 | == USB_DIR_IN) { | 1487 | == USB_DIR_IN) { |
1529 | if (!usbdev_probe_info.rx_pipe) { | 1488 | if (!devinfo->rx_pipe) { |
1530 | usbdev_probe_info.rx_pipe = | 1489 | devinfo->rx_pipe = |
1531 | usb_rcvbulkpipe(usb, endpoint_num); | 1490 | usb_rcvbulkpipe(usb, endpoint_num); |
1532 | } else { | 1491 | } else { |
1533 | usbdev_probe_info.rx_pipe2 = | 1492 | devinfo->rx_pipe2 = |
1534 | usb_rcvbulkpipe(usb, endpoint_num); | 1493 | usb_rcvbulkpipe(usb, endpoint_num); |
1535 | } | 1494 | } |
1536 | } else { | 1495 | } else { |
1537 | usbdev_probe_info.tx_pipe = | 1496 | devinfo->tx_pipe = usb_sndbulkpipe(usb, endpoint_num); |
1538 | usb_sndbulkpipe(usb, endpoint_num); | ||
1539 | } | 1497 | } |
1540 | } | 1498 | } |
1541 | 1499 | ||
1542 | /* Allocate interrupt URB and data buffer */ | 1500 | /* Allocate interrupt URB and data buffer */ |
1543 | /* RNDIS says 8-byte intr, our old drivers used 4-byte */ | 1501 | /* RNDIS says 8-byte intr, our old drivers used 4-byte */ |
1544 | if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16)) | 1502 | if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16)) |
1545 | usbdev_probe_info.intr_size = 8; | 1503 | devinfo->intr_size = 8; |
1546 | else | 1504 | else |
1547 | usbdev_probe_info.intr_size = 4; | 1505 | devinfo->intr_size = 4; |
1548 | 1506 | ||
1549 | usbdev_probe_info.interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval; | 1507 | devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval; |
1550 | 1508 | ||
1551 | usbdev_probe_info.device_speed = usb->speed; | ||
1552 | if (usb->speed == USB_SPEED_HIGH) | 1509 | if (usb->speed == USB_SPEED_HIGH) |
1553 | brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n"); | 1510 | brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n"); |
1554 | else | 1511 | else |
1555 | brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n"); | 1512 | brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n"); |
1556 | 1513 | ||
1557 | ret = brcmf_usb_probe_cb(&usb->dev, "", USB_BUS, 0); | 1514 | ret = brcmf_usb_probe_cb(devinfo, "", USB_BUS, 0); |
1558 | if (ret) | 1515 | if (ret) |
1559 | goto fail; | 1516 | goto fail; |
1560 | 1517 | ||
@@ -1563,6 +1520,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1563 | 1520 | ||
1564 | fail: | 1521 | fail: |
1565 | brcmf_dbg(ERROR, "failed with errno %d\n", ret); | 1522 | brcmf_dbg(ERROR, "failed with errno %d\n", ret); |
1523 | kfree(devinfo); | ||
1566 | usb_set_intfdata(intf, NULL); | 1524 | usb_set_intfdata(intf, NULL); |
1567 | return ret; | 1525 | return ret; |
1568 | 1526 | ||
@@ -1571,11 +1529,12 @@ fail: | |||
1571 | static void | 1529 | static void |
1572 | brcmf_usb_disconnect(struct usb_interface *intf) | 1530 | brcmf_usb_disconnect(struct usb_interface *intf) |
1573 | { | 1531 | { |
1574 | struct usb_device *usb = interface_to_usbdev(intf); | 1532 | struct brcmf_usbdev_info *devinfo; |
1575 | 1533 | ||
1576 | brcmf_dbg(TRACE, "enter\n"); | 1534 | brcmf_dbg(TRACE, "enter\n"); |
1577 | brcmf_usb_disconnect_cb(brcmf_usb_get_buspub(&usb->dev)); | 1535 | devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf); |
1578 | usb_set_intfdata(intf, NULL); | 1536 | brcmf_usb_disconnect_cb(devinfo); |
1537 | kfree(devinfo); | ||
1579 | } | 1538 | } |
1580 | 1539 | ||
1581 | /* | 1540 | /* |