diff options
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r-- | drivers/firewire/ohci.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 23d1468ad253..438e6c831170 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -1006,13 +1006,12 @@ static void ar_context_run(struct ar_context *ctx) | |||
1006 | 1006 | ||
1007 | static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) | 1007 | static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) |
1008 | { | 1008 | { |
1009 | int b, key; | 1009 | __le16 branch; |
1010 | 1010 | ||
1011 | b = (le16_to_cpu(d->control) & DESCRIPTOR_BRANCH_ALWAYS) >> 2; | 1011 | branch = d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS); |
1012 | key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8; | ||
1013 | 1012 | ||
1014 | /* figure out which descriptor the branch address goes in */ | 1013 | /* figure out which descriptor the branch address goes in */ |
1015 | if (z == 2 && (b == 3 || key == 2)) | 1014 | if (z == 2 && branch == cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)) |
1016 | return d; | 1015 | return d; |
1017 | else | 1016 | else |
1018 | return d + z - 1; | 1017 | return d + z - 1; |
@@ -1193,9 +1192,6 @@ static void context_append(struct context *ctx, | |||
1193 | wmb(); /* finish init of new descriptors before branch_address update */ | 1192 | wmb(); /* finish init of new descriptors before branch_address update */ |
1194 | ctx->prev->branch_address = cpu_to_le32(d_bus | z); | 1193 | ctx->prev->branch_address = cpu_to_le32(d_bus | z); |
1195 | ctx->prev = find_branch_descriptor(d, z); | 1194 | ctx->prev = find_branch_descriptor(d, z); |
1196 | |||
1197 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); | ||
1198 | flush_writes(ctx->ohci); | ||
1199 | } | 1195 | } |
1200 | 1196 | ||
1201 | static void context_stop(struct context *ctx) | 1197 | static void context_stop(struct context *ctx) |
@@ -1218,6 +1214,7 @@ static void context_stop(struct context *ctx) | |||
1218 | } | 1214 | } |
1219 | 1215 | ||
1220 | struct driver_data { | 1216 | struct driver_data { |
1217 | u8 inline_data[8]; | ||
1221 | struct fw_packet *packet; | 1218 | struct fw_packet *packet; |
1222 | }; | 1219 | }; |
1223 | 1220 | ||
@@ -1301,20 +1298,28 @@ static int at_context_queue_packet(struct context *ctx, | |||
1301 | return -1; | 1298 | return -1; |
1302 | } | 1299 | } |
1303 | 1300 | ||
1301 | BUILD_BUG_ON(sizeof(struct driver_data) > sizeof(struct descriptor)); | ||
1304 | driver_data = (struct driver_data *) &d[3]; | 1302 | driver_data = (struct driver_data *) &d[3]; |
1305 | driver_data->packet = packet; | 1303 | driver_data->packet = packet; |
1306 | packet->driver_data = driver_data; | 1304 | packet->driver_data = driver_data; |
1307 | 1305 | ||
1308 | if (packet->payload_length > 0) { | 1306 | if (packet->payload_length > 0) { |
1309 | payload_bus = | 1307 | if (packet->payload_length > sizeof(driver_data->inline_data)) { |
1310 | dma_map_single(ohci->card.device, packet->payload, | 1308 | payload_bus = dma_map_single(ohci->card.device, |
1311 | packet->payload_length, DMA_TO_DEVICE); | 1309 | packet->payload, |
1312 | if (dma_mapping_error(ohci->card.device, payload_bus)) { | 1310 | packet->payload_length, |
1313 | packet->ack = RCODE_SEND_ERROR; | 1311 | DMA_TO_DEVICE); |
1314 | return -1; | 1312 | if (dma_mapping_error(ohci->card.device, payload_bus)) { |
1313 | packet->ack = RCODE_SEND_ERROR; | ||
1314 | return -1; | ||
1315 | } | ||
1316 | packet->payload_bus = payload_bus; | ||
1317 | packet->payload_mapped = true; | ||
1318 | } else { | ||
1319 | memcpy(driver_data->inline_data, packet->payload, | ||
1320 | packet->payload_length); | ||
1321 | payload_bus = d_bus + 3 * sizeof(*d); | ||
1315 | } | 1322 | } |
1316 | packet->payload_bus = payload_bus; | ||
1317 | packet->payload_mapped = true; | ||
1318 | 1323 | ||
1319 | d[2].req_count = cpu_to_le16(packet->payload_length); | 1324 | d[2].req_count = cpu_to_le16(packet->payload_length); |
1320 | d[2].data_address = cpu_to_le32(payload_bus); | 1325 | d[2].data_address = cpu_to_le32(payload_bus); |
@@ -1340,8 +1345,12 @@ static int at_context_queue_packet(struct context *ctx, | |||
1340 | 1345 | ||
1341 | context_append(ctx, d, z, 4 - z); | 1346 | context_append(ctx, d, z, 4 - z); |
1342 | 1347 | ||
1343 | if (!ctx->running) | 1348 | if (ctx->running) { |
1349 | reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); | ||
1350 | flush_writes(ohci); | ||
1351 | } else { | ||
1344 | context_run(ctx, 0); | 1352 | context_run(ctx, 0); |
1353 | } | ||
1345 | 1354 | ||
1346 | return 0; | 1355 | return 0; |
1347 | } | 1356 | } |
@@ -2066,8 +2075,6 @@ static int ohci_enable(struct fw_card *card, | |||
2066 | 2075 | ||
2067 | reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus); | 2076 | reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus); |
2068 | reg_write(ohci, OHCI1394_LinkControlSet, | 2077 | reg_write(ohci, OHCI1394_LinkControlSet, |
2069 | OHCI1394_LinkControl_rcvSelfID | | ||
2070 | OHCI1394_LinkControl_rcvPhyPkt | | ||
2071 | OHCI1394_LinkControl_cycleTimerEnable | | 2078 | OHCI1394_LinkControl_cycleTimerEnable | |
2072 | OHCI1394_LinkControl_cycleMaster); | 2079 | OHCI1394_LinkControl_cycleMaster); |
2073 | 2080 | ||
@@ -2094,9 +2101,6 @@ static int ohci_enable(struct fw_card *card, | |||
2094 | reg_write(ohci, OHCI1394_FairnessControl, 0); | 2101 | reg_write(ohci, OHCI1394_FairnessControl, 0); |
2095 | card->priority_budget_implemented = ohci->pri_req_max != 0; | 2102 | card->priority_budget_implemented = ohci->pri_req_max != 0; |
2096 | 2103 | ||
2097 | ar_context_run(&ohci->ar_request_ctx); | ||
2098 | ar_context_run(&ohci->ar_response_ctx); | ||
2099 | |||
2100 | reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000); | 2104 | reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000); |
2101 | reg_write(ohci, OHCI1394_IntEventClear, ~0); | 2105 | reg_write(ohci, OHCI1394_IntEventClear, ~0); |
2102 | reg_write(ohci, OHCI1394_IntMaskClear, ~0); | 2106 | reg_write(ohci, OHCI1394_IntMaskClear, ~0); |
@@ -2186,7 +2190,13 @@ static int ohci_enable(struct fw_card *card, | |||
2186 | reg_write(ohci, OHCI1394_HCControlSet, | 2190 | reg_write(ohci, OHCI1394_HCControlSet, |
2187 | OHCI1394_HCControl_linkEnable | | 2191 | OHCI1394_HCControl_linkEnable | |
2188 | OHCI1394_HCControl_BIBimageValid); | 2192 | OHCI1394_HCControl_BIBimageValid); |
2189 | flush_writes(ohci); | 2193 | |
2194 | reg_write(ohci, OHCI1394_LinkControlSet, | ||
2195 | OHCI1394_LinkControl_rcvSelfID | | ||
2196 | OHCI1394_LinkControl_rcvPhyPkt); | ||
2197 | |||
2198 | ar_context_run(&ohci->ar_request_ctx); | ||
2199 | ar_context_run(&ohci->ar_response_ctx); /* also flushes writes */ | ||
2190 | 2200 | ||
2191 | /* We are ready to go, reset bus to finish initialization. */ | 2201 | /* We are ready to go, reset bus to finish initialization. */ |
2192 | fw_schedule_bus_reset(&ohci->card, false, true); | 2202 | fw_schedule_bus_reset(&ohci->card, false, true); |
@@ -3112,6 +3122,15 @@ static int ohci_queue_iso(struct fw_iso_context *base, | |||
3112 | return ret; | 3122 | return ret; |
3113 | } | 3123 | } |
3114 | 3124 | ||
3125 | static void ohci_flush_queue_iso(struct fw_iso_context *base) | ||
3126 | { | ||
3127 | struct context *ctx = | ||
3128 | &container_of(base, struct iso_context, base)->context; | ||
3129 | |||
3130 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); | ||
3131 | flush_writes(ctx->ohci); | ||
3132 | } | ||
3133 | |||
3115 | static const struct fw_card_driver ohci_driver = { | 3134 | static const struct fw_card_driver ohci_driver = { |
3116 | .enable = ohci_enable, | 3135 | .enable = ohci_enable, |
3117 | .read_phy_reg = ohci_read_phy_reg, | 3136 | .read_phy_reg = ohci_read_phy_reg, |
@@ -3128,6 +3147,7 @@ static const struct fw_card_driver ohci_driver = { | |||
3128 | .free_iso_context = ohci_free_iso_context, | 3147 | .free_iso_context = ohci_free_iso_context, |
3129 | .set_iso_channels = ohci_set_iso_channels, | 3148 | .set_iso_channels = ohci_set_iso_channels, |
3130 | .queue_iso = ohci_queue_iso, | 3149 | .queue_iso = ohci_queue_iso, |
3150 | .flush_queue_iso = ohci_flush_queue_iso, | ||
3131 | .start_iso = ohci_start_iso, | 3151 | .start_iso = ohci_start_iso, |
3132 | .stop_iso = ohci_stop_iso, | 3152 | .stop_iso = ohci_stop_iso, |
3133 | }; | 3153 | }; |