diff options
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r-- | drivers/usb/core/hcd.c | 169 |
1 files changed, 105 insertions, 64 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 38d4700926f7..6a05e6934455 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1259,6 +1259,51 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle, | |||
1259 | *dma_handle = 0; | 1259 | *dma_handle = 0; |
1260 | } | 1260 | } |
1261 | 1261 | ||
1262 | static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | ||
1263 | { | ||
1264 | enum dma_data_direction dir; | ||
1265 | |||
1266 | if (urb->transfer_flags & URB_SETUP_MAP_SINGLE) | ||
1267 | dma_unmap_single(hcd->self.controller, | ||
1268 | urb->setup_dma, | ||
1269 | sizeof(struct usb_ctrlrequest), | ||
1270 | DMA_TO_DEVICE); | ||
1271 | else if (urb->transfer_flags & URB_SETUP_MAP_LOCAL) | ||
1272 | hcd_free_coherent(urb->dev->bus, | ||
1273 | &urb->setup_dma, | ||
1274 | (void **) &urb->setup_packet, | ||
1275 | sizeof(struct usb_ctrlrequest), | ||
1276 | DMA_TO_DEVICE); | ||
1277 | |||
1278 | dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
1279 | if (urb->transfer_flags & URB_DMA_MAP_SG) | ||
1280 | dma_unmap_sg(hcd->self.controller, | ||
1281 | urb->sg->sg, | ||
1282 | urb->num_sgs, | ||
1283 | dir); | ||
1284 | else if (urb->transfer_flags & URB_DMA_MAP_PAGE) | ||
1285 | dma_unmap_page(hcd->self.controller, | ||
1286 | urb->transfer_dma, | ||
1287 | urb->transfer_buffer_length, | ||
1288 | dir); | ||
1289 | else if (urb->transfer_flags & URB_DMA_MAP_SINGLE) | ||
1290 | dma_unmap_single(hcd->self.controller, | ||
1291 | urb->transfer_dma, | ||
1292 | urb->transfer_buffer_length, | ||
1293 | dir); | ||
1294 | else if (urb->transfer_flags & URB_MAP_LOCAL) | ||
1295 | hcd_free_coherent(urb->dev->bus, | ||
1296 | &urb->transfer_dma, | ||
1297 | &urb->transfer_buffer, | ||
1298 | urb->transfer_buffer_length, | ||
1299 | dir); | ||
1300 | |||
1301 | /* Make it safe to call this routine more than once */ | ||
1302 | urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL | | ||
1303 | URB_DMA_MAP_SG | URB_DMA_MAP_PAGE | | ||
1304 | URB_DMA_MAP_SINGLE | URB_MAP_LOCAL); | ||
1305 | } | ||
1306 | |||
1262 | static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | 1307 | static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, |
1263 | gfp_t mem_flags) | 1308 | gfp_t mem_flags) |
1264 | { | 1309 | { |
@@ -1270,8 +1315,6 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | |||
1270 | * unless it uses pio or talks to another transport, | 1315 | * unless it uses pio or talks to another transport, |
1271 | * or uses the provided scatter gather list for bulk. | 1316 | * or uses the provided scatter gather list for bulk. |
1272 | */ | 1317 | */ |
1273 | if (is_root_hub(urb->dev)) | ||
1274 | return 0; | ||
1275 | 1318 | ||
1276 | if (usb_endpoint_xfer_control(&urb->ep->desc) | 1319 | if (usb_endpoint_xfer_control(&urb->ep->desc) |
1277 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { | 1320 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { |
@@ -1284,6 +1327,7 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | |||
1284 | if (dma_mapping_error(hcd->self.controller, | 1327 | if (dma_mapping_error(hcd->self.controller, |
1285 | urb->setup_dma)) | 1328 | urb->setup_dma)) |
1286 | return -EAGAIN; | 1329 | return -EAGAIN; |
1330 | urb->transfer_flags |= URB_SETUP_MAP_SINGLE; | ||
1287 | } else if (hcd->driver->flags & HCD_LOCAL_MEM) | 1331 | } else if (hcd->driver->flags & HCD_LOCAL_MEM) |
1288 | ret = hcd_alloc_coherent( | 1332 | ret = hcd_alloc_coherent( |
1289 | urb->dev->bus, mem_flags, | 1333 | urb->dev->bus, mem_flags, |
@@ -1291,20 +1335,57 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | |||
1291 | (void **)&urb->setup_packet, | 1335 | (void **)&urb->setup_packet, |
1292 | sizeof(struct usb_ctrlrequest), | 1336 | sizeof(struct usb_ctrlrequest), |
1293 | DMA_TO_DEVICE); | 1337 | DMA_TO_DEVICE); |
1338 | if (ret) | ||
1339 | return ret; | ||
1340 | urb->transfer_flags |= URB_SETUP_MAP_LOCAL; | ||
1294 | } | 1341 | } |
1295 | 1342 | ||
1296 | dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | 1343 | dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; |
1297 | if (ret == 0 && urb->transfer_buffer_length != 0 | 1344 | if (urb->transfer_buffer_length != 0 |
1298 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { | 1345 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { |
1299 | if (hcd->self.uses_dma) { | 1346 | if (hcd->self.uses_dma) { |
1300 | urb->transfer_dma = dma_map_single ( | 1347 | if (urb->num_sgs) { |
1301 | hcd->self.controller, | 1348 | int n = dma_map_sg( |
1302 | urb->transfer_buffer, | 1349 | hcd->self.controller, |
1303 | urb->transfer_buffer_length, | 1350 | urb->sg->sg, |
1304 | dir); | 1351 | urb->num_sgs, |
1305 | if (dma_mapping_error(hcd->self.controller, | 1352 | dir); |
1353 | if (n <= 0) | ||
1354 | ret = -EAGAIN; | ||
1355 | else | ||
1356 | urb->transfer_flags |= URB_DMA_MAP_SG; | ||
1357 | if (n != urb->num_sgs) { | ||
1358 | urb->num_sgs = n; | ||
1359 | urb->transfer_flags |= | ||
1360 | URB_DMA_SG_COMBINED; | ||
1361 | } | ||
1362 | } else if (urb->sg) { | ||
1363 | struct scatterlist *sg; | ||
1364 | |||
1365 | sg = (struct scatterlist *) urb->sg; | ||
1366 | urb->transfer_dma = dma_map_page( | ||
1367 | hcd->self.controller, | ||
1368 | sg_page(sg), | ||
1369 | sg->offset, | ||
1370 | urb->transfer_buffer_length, | ||
1371 | dir); | ||
1372 | if (dma_mapping_error(hcd->self.controller, | ||
1306 | urb->transfer_dma)) | 1373 | urb->transfer_dma)) |
1307 | return -EAGAIN; | 1374 | ret = -EAGAIN; |
1375 | else | ||
1376 | urb->transfer_flags |= URB_DMA_MAP_PAGE; | ||
1377 | } else { | ||
1378 | urb->transfer_dma = dma_map_single( | ||
1379 | hcd->self.controller, | ||
1380 | urb->transfer_buffer, | ||
1381 | urb->transfer_buffer_length, | ||
1382 | dir); | ||
1383 | if (dma_mapping_error(hcd->self.controller, | ||
1384 | urb->transfer_dma)) | ||
1385 | ret = -EAGAIN; | ||
1386 | else | ||
1387 | urb->transfer_flags |= URB_DMA_MAP_SINGLE; | ||
1388 | } | ||
1308 | } else if (hcd->driver->flags & HCD_LOCAL_MEM) { | 1389 | } else if (hcd->driver->flags & HCD_LOCAL_MEM) { |
1309 | ret = hcd_alloc_coherent( | 1390 | ret = hcd_alloc_coherent( |
1310 | urb->dev->bus, mem_flags, | 1391 | urb->dev->bus, mem_flags, |
@@ -1312,55 +1393,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | |||
1312 | &urb->transfer_buffer, | 1393 | &urb->transfer_buffer, |
1313 | urb->transfer_buffer_length, | 1394 | urb->transfer_buffer_length, |
1314 | dir); | 1395 | dir); |
1315 | 1396 | if (ret == 0) | |
1316 | if (ret && usb_endpoint_xfer_control(&urb->ep->desc) | 1397 | urb->transfer_flags |= URB_MAP_LOCAL; |
1317 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | ||
1318 | hcd_free_coherent(urb->dev->bus, | ||
1319 | &urb->setup_dma, | ||
1320 | (void **)&urb->setup_packet, | ||
1321 | sizeof(struct usb_ctrlrequest), | ||
1322 | DMA_TO_DEVICE); | ||
1323 | } | 1398 | } |
1399 | if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE | | ||
1400 | URB_SETUP_MAP_LOCAL))) | ||
1401 | unmap_urb_for_dma(hcd, urb); | ||
1324 | } | 1402 | } |
1325 | return ret; | 1403 | return ret; |
1326 | } | 1404 | } |
1327 | 1405 | ||
1328 | static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | ||
1329 | { | ||
1330 | enum dma_data_direction dir; | ||
1331 | |||
1332 | if (is_root_hub(urb->dev)) | ||
1333 | return; | ||
1334 | |||
1335 | if (usb_endpoint_xfer_control(&urb->ep->desc) | ||
1336 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { | ||
1337 | if (hcd->self.uses_dma) | ||
1338 | dma_unmap_single(hcd->self.controller, urb->setup_dma, | ||
1339 | sizeof(struct usb_ctrlrequest), | ||
1340 | DMA_TO_DEVICE); | ||
1341 | else if (hcd->driver->flags & HCD_LOCAL_MEM) | ||
1342 | hcd_free_coherent(urb->dev->bus, &urb->setup_dma, | ||
1343 | (void **)&urb->setup_packet, | ||
1344 | sizeof(struct usb_ctrlrequest), | ||
1345 | DMA_TO_DEVICE); | ||
1346 | } | ||
1347 | |||
1348 | dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
1349 | if (urb->transfer_buffer_length != 0 | ||
1350 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { | ||
1351 | if (hcd->self.uses_dma) | ||
1352 | dma_unmap_single(hcd->self.controller, | ||
1353 | urb->transfer_dma, | ||
1354 | urb->transfer_buffer_length, | ||
1355 | dir); | ||
1356 | else if (hcd->driver->flags & HCD_LOCAL_MEM) | ||
1357 | hcd_free_coherent(urb->dev->bus, &urb->transfer_dma, | ||
1358 | &urb->transfer_buffer, | ||
1359 | urb->transfer_buffer_length, | ||
1360 | dir); | ||
1361 | } | ||
1362 | } | ||
1363 | |||
1364 | /*-------------------------------------------------------------------------*/ | 1406 | /*-------------------------------------------------------------------------*/ |
1365 | 1407 | ||
1366 | /* may be called in any context with a valid urb->dev usecount | 1408 | /* may be called in any context with a valid urb->dev usecount |
@@ -1389,21 +1431,20 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | |||
1389 | * URBs must be submitted in process context with interrupts | 1431 | * URBs must be submitted in process context with interrupts |
1390 | * enabled. | 1432 | * enabled. |
1391 | */ | 1433 | */ |
1392 | status = map_urb_for_dma(hcd, urb, mem_flags); | ||
1393 | if (unlikely(status)) { | ||
1394 | usbmon_urb_submit_error(&hcd->self, urb, status); | ||
1395 | goto error; | ||
1396 | } | ||
1397 | 1434 | ||
1398 | if (is_root_hub(urb->dev)) | 1435 | if (is_root_hub(urb->dev)) { |
1399 | status = rh_urb_enqueue(hcd, urb); | 1436 | status = rh_urb_enqueue(hcd, urb); |
1400 | else | 1437 | } else { |
1401 | status = hcd->driver->urb_enqueue(hcd, urb, mem_flags); | 1438 | status = map_urb_for_dma(hcd, urb, mem_flags); |
1439 | if (likely(status == 0)) { | ||
1440 | status = hcd->driver->urb_enqueue(hcd, urb, mem_flags); | ||
1441 | if (unlikely(status)) | ||
1442 | unmap_urb_for_dma(hcd, urb); | ||
1443 | } | ||
1444 | } | ||
1402 | 1445 | ||
1403 | if (unlikely(status)) { | 1446 | if (unlikely(status)) { |
1404 | usbmon_urb_submit_error(&hcd->self, urb, status); | 1447 | usbmon_urb_submit_error(&hcd->self, urb, status); |
1405 | unmap_urb_for_dma(hcd, urb); | ||
1406 | error: | ||
1407 | urb->hcpriv = NULL; | 1448 | urb->hcpriv = NULL; |
1408 | INIT_LIST_HEAD(&urb->urb_list); | 1449 | INIT_LIST_HEAD(&urb->urb_list); |
1409 | atomic_dec(&urb->use_count); | 1450 | atomic_dec(&urb->use_count); |