diff options
| -rw-r--r-- | drivers/usb/core/buffer.c | 9 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 176 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.h | 1 |
3 files changed, 163 insertions, 23 deletions
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 28d4972f7ad5..acd9f00a0b76 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c | |||
| @@ -53,7 +53,8 @@ int hcd_buffer_create(struct usb_hcd *hcd) | |||
| 53 | char name[16]; | 53 | char name[16]; |
| 54 | int i, size; | 54 | int i, size; |
| 55 | 55 | ||
| 56 | if (!hcd->self.controller->dma_mask) | 56 | if (!hcd->self.controller->dma_mask && |
| 57 | !(hcd->driver->flags & HCD_LOCAL_MEM)) | ||
| 57 | return 0; | 58 | return 0; |
| 58 | 59 | ||
| 59 | for (i = 0; i < HCD_BUFFER_POOLS; i++) { | 60 | for (i = 0; i < HCD_BUFFER_POOLS; i++) { |
| @@ -107,7 +108,8 @@ void *hcd_buffer_alloc( | |||
| 107 | int i; | 108 | int i; |
| 108 | 109 | ||
| 109 | /* some USB hosts just use PIO */ | 110 | /* some USB hosts just use PIO */ |
| 110 | if (!bus->controller->dma_mask) { | 111 | if (!bus->controller->dma_mask && |
| 112 | !(hcd->driver->flags & HCD_LOCAL_MEM)) { | ||
| 111 | *dma = ~(dma_addr_t) 0; | 113 | *dma = ~(dma_addr_t) 0; |
| 112 | return kmalloc(size, mem_flags); | 114 | return kmalloc(size, mem_flags); |
| 113 | } | 115 | } |
| @@ -132,7 +134,8 @@ void hcd_buffer_free( | |||
| 132 | if (!addr) | 134 | if (!addr) |
| 133 | return; | 135 | return; |
| 134 | 136 | ||
| 135 | if (!bus->controller->dma_mask) { | 137 | if (!bus->controller->dma_mask && |
| 138 | !(hcd->driver->flags & HCD_LOCAL_MEM)) { | ||
| 136 | kfree(addr); | 139 | kfree(addr); |
| 137 | return; | 140 | return; |
| 138 | } | 141 | } |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 372372116bb0..febd6b40da3b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
| 36 | #include <asm/irq.h> | 36 | #include <asm/irq.h> |
| 37 | #include <asm/byteorder.h> | 37 | #include <asm/byteorder.h> |
| 38 | #include <asm/unaligned.h> | ||
| 38 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
| 39 | #include <linux/workqueue.h> | 40 | #include <linux/workqueue.h> |
| 40 | 41 | ||
| @@ -1112,48 +1113,177 @@ void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb) | |||
| 1112 | } | 1113 | } |
| 1113 | EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep); | 1114 | EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep); |
| 1114 | 1115 | ||
| 1115 | static void map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | 1116 | /* |
| 1117 | * Some usb host controllers can only perform dma using a small SRAM area. | ||
| 1118 | * The usb core itself is however optimized for host controllers that can dma | ||
| 1119 | * using regular system memory - like pci devices doing bus mastering. | ||
| 1120 | * | ||
| 1121 | * To support host controllers with limited dma capabilites we provide dma | ||
| 1122 | * bounce buffers. This feature can be enabled using the HCD_LOCAL_MEM flag. | ||
| 1123 | * For this to work properly the host controller code must first use the | ||
| 1124 | * function dma_declare_coherent_memory() to point out which memory area | ||
| 1125 | * that should be used for dma allocations. | ||
| 1126 | * | ||
| 1127 | * The HCD_LOCAL_MEM flag then tells the usb code to allocate all data for | ||
| 1128 | * dma using dma_alloc_coherent() which in turn allocates from the memory | ||
| 1129 | * area pointed out with dma_declare_coherent_memory(). | ||
| 1130 | * | ||
| 1131 | * So, to summarize... | ||
| 1132 | * | ||
| 1133 | * - We need "local" memory, canonical example being | ||
| 1134 | * a small SRAM on a discrete controller being the | ||
| 1135 | * only memory that the controller can read ... | ||
| 1136 | * (a) "normal" kernel memory is no good, and | ||
| 1137 | * (b) there's not enough to share | ||
| 1138 | * | ||
| 1139 | * - The only *portable* hook for such stuff in the | ||
| 1140 | * DMA framework is dma_declare_coherent_memory() | ||
| 1141 | * | ||
| 1142 | * - So we use that, even though the primary requirement | ||
| 1143 | * is that the memory be "local" (hence addressible | ||
| 1144 | * by that device), not "coherent". | ||
| 1145 | * | ||
| 1146 | */ | ||
| 1147 | |||
| 1148 | static int hcd_alloc_coherent(struct usb_bus *bus, | ||
| 1149 | gfp_t mem_flags, dma_addr_t *dma_handle, | ||
| 1150 | void **vaddr_handle, size_t size, | ||
| 1151 | enum dma_data_direction dir) | ||
| 1152 | { | ||
| 1153 | unsigned char *vaddr; | ||
| 1154 | |||
| 1155 | vaddr = hcd_buffer_alloc(bus, size + sizeof(vaddr), | ||
| 1156 | mem_flags, dma_handle); | ||
| 1157 | if (!vaddr) | ||
| 1158 | return -ENOMEM; | ||
| 1159 | |||
| 1160 | /* | ||
| 1161 | * Store the virtual address of the buffer at the end | ||
| 1162 | * of the allocated dma buffer. The size of the buffer | ||
| 1163 | * may be uneven so use unaligned functions instead | ||
| 1164 | * of just rounding up. It makes sense to optimize for | ||
| 1165 | * memory footprint over access speed since the amount | ||
| 1166 | * of memory available for dma may be limited. | ||
| 1167 | */ | ||
| 1168 | put_unaligned((unsigned long)*vaddr_handle, | ||
| 1169 | (unsigned long *)(vaddr + size)); | ||
| 1170 | |||
| 1171 | if (dir == DMA_TO_DEVICE) | ||
| 1172 | memcpy(vaddr, *vaddr_handle, size); | ||
| 1173 | |||
| 1174 | *vaddr_handle = vaddr; | ||
| 1175 | return 0; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle, | ||
| 1179 | void **vaddr_handle, size_t size, | ||
| 1180 | enum dma_data_direction dir) | ||
| 1181 | { | ||
| 1182 | unsigned char *vaddr = *vaddr_handle; | ||
| 1183 | |||
| 1184 | vaddr = (void *)get_unaligned((unsigned long *)(vaddr + size)); | ||
| 1185 | |||
| 1186 | if (dir == DMA_FROM_DEVICE) | ||
| 1187 | memcpy(vaddr, *vaddr_handle, size); | ||
| 1188 | |||
| 1189 | hcd_buffer_free(bus, size + sizeof(vaddr), *vaddr_handle, *dma_handle); | ||
| 1190 | |||
| 1191 | *vaddr_handle = vaddr; | ||
| 1192 | *dma_handle = 0; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | ||
| 1196 | gfp_t mem_flags) | ||
| 1116 | { | 1197 | { |
| 1198 | enum dma_data_direction dir; | ||
| 1199 | int ret = 0; | ||
| 1200 | |||
| 1117 | /* Map the URB's buffers for DMA access. | 1201 | /* Map the URB's buffers for DMA access. |
| 1118 | * Lower level HCD code should use *_dma exclusively, | 1202 | * Lower level HCD code should use *_dma exclusively, |
| 1119 | * unless it uses pio or talks to another transport. | 1203 | * unless it uses pio or talks to another transport. |
| 1120 | */ | 1204 | */ |
| 1121 | if (hcd->self.uses_dma && !is_root_hub(urb->dev)) { | 1205 | if (is_root_hub(urb->dev)) |
| 1122 | if (usb_endpoint_xfer_control(&urb->ep->desc) | 1206 | return 0; |
| 1123 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | 1207 | |
| 1124 | urb->setup_dma = dma_map_single ( | 1208 | if (usb_endpoint_xfer_control(&urb->ep->desc) |
| 1209 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { | ||
| 1210 | if (hcd->self.uses_dma) | ||
| 1211 | urb->setup_dma = dma_map_single( | ||
| 1125 | hcd->self.controller, | 1212 | hcd->self.controller, |
| 1126 | urb->setup_packet, | 1213 | urb->setup_packet, |
| 1127 | sizeof (struct usb_ctrlrequest), | 1214 | sizeof(struct usb_ctrlrequest), |
| 1128 | DMA_TO_DEVICE); | 1215 | DMA_TO_DEVICE); |
| 1129 | if (urb->transfer_buffer_length != 0 | 1216 | else if (hcd->driver->flags & HCD_LOCAL_MEM) |
| 1130 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) | 1217 | ret = hcd_alloc_coherent( |
| 1218 | urb->dev->bus, mem_flags, | ||
| 1219 | &urb->setup_dma, | ||
| 1220 | (void **)&urb->setup_packet, | ||
| 1221 | sizeof(struct usb_ctrlrequest), | ||
| 1222 | DMA_TO_DEVICE); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
| 1226 | if (ret == 0 && urb->transfer_buffer_length != 0 | ||
| 1227 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { | ||
| 1228 | if (hcd->self.uses_dma) | ||
| 1131 | urb->transfer_dma = dma_map_single ( | 1229 | urb->transfer_dma = dma_map_single ( |
| 1132 | hcd->self.controller, | 1230 | hcd->self.controller, |
| 1133 | urb->transfer_buffer, | 1231 | urb->transfer_buffer, |
| 1134 | urb->transfer_buffer_length, | 1232 | urb->transfer_buffer_length, |
| 1135 | usb_urb_dir_in(urb) | 1233 | dir); |
| 1136 | ? DMA_FROM_DEVICE | 1234 | else if (hcd->driver->flags & HCD_LOCAL_MEM) { |
| 1137 | : DMA_TO_DEVICE); | 1235 | ret = hcd_alloc_coherent( |
| 1236 | urb->dev->bus, mem_flags, | ||
| 1237 | &urb->transfer_dma, | ||
| 1238 | &urb->transfer_buffer, | ||
| 1239 | urb->transfer_buffer_length, | ||
| 1240 | dir); | ||
| 1241 | |||
| 1242 | if (ret && usb_endpoint_xfer_control(&urb->ep->desc) | ||
| 1243 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | ||
| 1244 | hcd_free_coherent(urb->dev->bus, | ||
| 1245 | &urb->setup_dma, | ||
| 1246 | (void **)&urb->setup_packet, | ||
| 1247 | sizeof(struct usb_ctrlrequest), | ||
| 1248 | DMA_TO_DEVICE); | ||
| 1249 | } | ||
| 1138 | } | 1250 | } |
| 1251 | return ret; | ||
| 1139 | } | 1252 | } |
| 1140 | 1253 | ||
| 1141 | static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | 1254 | static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) |
| 1142 | { | 1255 | { |
| 1143 | if (hcd->self.uses_dma && !is_root_hub(urb->dev)) { | 1256 | enum dma_data_direction dir; |
| 1144 | if (usb_endpoint_xfer_control(&urb->ep->desc) | 1257 | |
| 1145 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | 1258 | if (is_root_hub(urb->dev)) |
| 1259 | return; | ||
| 1260 | |||
| 1261 | if (usb_endpoint_xfer_control(&urb->ep->desc) | ||
| 1262 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { | ||
| 1263 | if (hcd->self.uses_dma) | ||
| 1146 | dma_unmap_single(hcd->self.controller, urb->setup_dma, | 1264 | dma_unmap_single(hcd->self.controller, urb->setup_dma, |
| 1147 | sizeof(struct usb_ctrlrequest), | 1265 | sizeof(struct usb_ctrlrequest), |
| 1148 | DMA_TO_DEVICE); | 1266 | DMA_TO_DEVICE); |
| 1149 | if (urb->transfer_buffer_length != 0 | 1267 | else if (hcd->driver->flags & HCD_LOCAL_MEM) |
| 1150 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) | 1268 | hcd_free_coherent(urb->dev->bus, &urb->setup_dma, |
| 1269 | (void **)&urb->setup_packet, | ||
| 1270 | sizeof(struct usb_ctrlrequest), | ||
| 1271 | DMA_TO_DEVICE); | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
| 1275 | if (urb->transfer_buffer_length != 0 | ||
| 1276 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { | ||
| 1277 | if (hcd->self.uses_dma) | ||
| 1151 | dma_unmap_single(hcd->self.controller, | 1278 | dma_unmap_single(hcd->self.controller, |
| 1152 | urb->transfer_dma, | 1279 | urb->transfer_dma, |
| 1153 | urb->transfer_buffer_length, | 1280 | urb->transfer_buffer_length, |
| 1154 | usb_urb_dir_in(urb) | 1281 | dir); |
| 1155 | ? DMA_FROM_DEVICE | 1282 | else if (hcd->driver->flags & HCD_LOCAL_MEM) |
| 1156 | : DMA_TO_DEVICE); | 1283 | hcd_free_coherent(urb->dev->bus, &urb->transfer_dma, |
| 1284 | &urb->transfer_buffer, | ||
| 1285 | urb->transfer_buffer_length, | ||
| 1286 | dir); | ||
| 1157 | } | 1287 | } |
| 1158 | } | 1288 | } |
| 1159 | 1289 | ||
| @@ -1185,7 +1315,12 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | |||
| 1185 | * URBs must be submitted in process context with interrupts | 1315 | * URBs must be submitted in process context with interrupts |
| 1186 | * enabled. | 1316 | * enabled. |
| 1187 | */ | 1317 | */ |
| 1188 | map_urb_for_dma(hcd, urb); | 1318 | status = map_urb_for_dma(hcd, urb, mem_flags); |
| 1319 | if (unlikely(status)) { | ||
| 1320 | usbmon_urb_submit_error(&hcd->self, urb, status); | ||
| 1321 | goto error; | ||
| 1322 | } | ||
| 1323 | |||
| 1189 | if (is_root_hub(urb->dev)) | 1324 | if (is_root_hub(urb->dev)) |
| 1190 | status = rh_urb_enqueue(hcd, urb); | 1325 | status = rh_urb_enqueue(hcd, urb); |
| 1191 | else | 1326 | else |
| @@ -1194,6 +1329,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | |||
| 1194 | if (unlikely(status)) { | 1329 | if (unlikely(status)) { |
| 1195 | usbmon_urb_submit_error(&hcd->self, urb, status); | 1330 | usbmon_urb_submit_error(&hcd->self, urb, status); |
| 1196 | unmap_urb_for_dma(hcd, urb); | 1331 | unmap_urb_for_dma(hcd, urb); |
| 1332 | error: | ||
| 1197 | urb->hcpriv = NULL; | 1333 | urb->hcpriv = NULL; |
| 1198 | INIT_LIST_HEAD(&urb->urb_list); | 1334 | INIT_LIST_HEAD(&urb->urb_list); |
| 1199 | atomic_dec(&urb->use_count); | 1335 | atomic_dec(&urb->use_count); |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 080298ad5990..0095641c51fa 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
| @@ -165,6 +165,7 @@ struct hc_driver { | |||
| 165 | 165 | ||
| 166 | int flags; | 166 | int flags; |
| 167 | #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ | 167 | #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ |
| 168 | #define HCD_LOCAL_MEM 0x0002 /* HC needs local memory */ | ||
| 168 | #define HCD_USB11 0x0010 /* USB 1.1 */ | 169 | #define HCD_USB11 0x0010 /* USB 1.1 */ |
| 169 | #define HCD_USB2 0x0020 /* USB 2.0 */ | 170 | #define HCD_USB2 0x0020 /* USB 2.0 */ |
| 170 | 171 | ||
