diff options
-rw-r--r-- | drivers/firewire/fw-ohci.c | 61 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.c | 99 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.h | 13 |
3 files changed, 92 insertions, 81 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index d6f0644b05d4..8dc872aedce7 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
@@ -221,24 +221,48 @@ static void ar_context_tasklet(unsigned long data) | |||
221 | { | 221 | { |
222 | struct ar_context *ctx = (struct ar_context *)data; | 222 | struct ar_context *ctx = (struct ar_context *)data; |
223 | struct fw_ohci *ohci = ctx->ohci; | 223 | struct fw_ohci *ohci = ctx->ohci; |
224 | u32 status; | 224 | struct fw_packet p; |
225 | int length, speed, ack, timestamp, tcode; | 225 | u32 status, length, tcode; |
226 | 226 | ||
227 | /* FIXME: What to do about evt_* errors? */ | 227 | /* FIXME: What to do about evt_* errors? */ |
228 | length = le16_to_cpu(ctx->descriptor.req_count) - | 228 | length = le16_to_cpu(ctx->descriptor.req_count) - |
229 | le16_to_cpu(ctx->descriptor.res_count) - 4; | 229 | le16_to_cpu(ctx->descriptor.res_count) - 4; |
230 | status = le32_to_cpu(ctx->buffer[length / 4]); | 230 | status = le32_to_cpu(ctx->buffer[length / 4]); |
231 | ack = ((status >> 16) & 0x1f) - 16; | ||
232 | speed = (status >> 21) & 0x7; | ||
233 | timestamp = status & 0xffff; | ||
234 | 231 | ||
235 | ctx->buffer[0] = le32_to_cpu(ctx->buffer[0]); | 232 | p.ack = ((status >> 16) & 0x1f) - 16; |
236 | ctx->buffer[1] = le32_to_cpu(ctx->buffer[1]); | 233 | p.speed = (status >> 21) & 0x7; |
237 | ctx->buffer[2] = le32_to_cpu(ctx->buffer[2]); | 234 | p.timestamp = status & 0xffff; |
235 | p.generation = ohci->request_generation; | ||
236 | |||
237 | p.header[0] = le32_to_cpu(ctx->buffer[0]); | ||
238 | p.header[1] = le32_to_cpu(ctx->buffer[1]); | ||
239 | p.header[2] = le32_to_cpu(ctx->buffer[2]); | ||
240 | |||
241 | tcode = (p.header[0] >> 4) & 0x0f; | ||
242 | switch (tcode) { | ||
243 | case TCODE_WRITE_QUADLET_REQUEST: | ||
244 | case TCODE_READ_QUADLET_RESPONSE: | ||
245 | p.header[3] = ctx->buffer[3]; | ||
246 | p.header_length = 16; | ||
247 | break; | ||
248 | |||
249 | case TCODE_WRITE_BLOCK_REQUEST: | ||
250 | case TCODE_READ_BLOCK_REQUEST : | ||
251 | case TCODE_READ_BLOCK_RESPONSE: | ||
252 | case TCODE_LOCK_REQUEST: | ||
253 | case TCODE_LOCK_RESPONSE: | ||
254 | p.header[3] = le32_to_cpu(ctx->buffer[3]); | ||
255 | p.header_length = 16; | ||
256 | break; | ||
257 | |||
258 | case TCODE_WRITE_RESPONSE: | ||
259 | case TCODE_READ_QUADLET_REQUEST: | ||
260 | p.header_length = 12; | ||
261 | break; | ||
262 | } | ||
238 | 263 | ||
239 | tcode = (ctx->buffer[0] >> 4) & 0x0f; | 264 | p.payload = (void *) ctx->buffer + p.header_length; |
240 | if (TCODE_IS_BLOCK_PACKET(tcode)) | 265 | p.payload_length = length - p.header_length; |
241 | ctx->buffer[3] = le32_to_cpu(ctx->buffer[3]); | ||
242 | 266 | ||
243 | /* The OHCI bus reset handler synthesizes a phy packet with | 267 | /* The OHCI bus reset handler synthesizes a phy packet with |
244 | * the new generation number when a bus reset happens (see | 268 | * the new generation number when a bus reset happens (see |
@@ -248,15 +272,12 @@ static void ar_context_tasklet(unsigned long data) | |||
248 | * we use the unique tlabel for finding the matching | 272 | * we use the unique tlabel for finding the matching |
249 | * request. */ | 273 | * request. */ |
250 | 274 | ||
251 | if (ack + 16 == 0x09) | 275 | if (p.ack + 16 == 0x09) |
252 | ohci->request_generation = (ctx->buffer[2] >> 16) & 0xff; | 276 | ohci->request_generation = (ctx->buffer[2] >> 16) & 0xff; |
253 | else if (ctx == &ohci->ar_request_ctx) | 277 | else if (ctx == &ohci->ar_request_ctx) |
254 | fw_core_handle_request(&ohci->card, speed, ack, timestamp, | 278 | fw_core_handle_request(&ohci->card, &p); |
255 | ohci->request_generation, | ||
256 | length, ctx->buffer); | ||
257 | else | 279 | else |
258 | fw_core_handle_response(&ohci->card, speed, ack, timestamp, | 280 | fw_core_handle_response(&ohci->card, &p); |
259 | length, ctx->buffer); | ||
260 | 281 | ||
261 | ctx->descriptor.data_address = cpu_to_le32(ctx->buffer_bus); | 282 | ctx->descriptor.data_address = cpu_to_le32(ctx->buffer_bus); |
262 | ctx->descriptor.req_count = cpu_to_le16(sizeof ctx->buffer); | 283 | ctx->descriptor.req_count = cpu_to_le16(sizeof ctx->buffer); |
@@ -323,15 +344,15 @@ do_packet_callbacks(struct fw_ohci *ohci, struct list_head *list) | |||
323 | struct fw_packet *p, *next; | 344 | struct fw_packet *p, *next; |
324 | 345 | ||
325 | list_for_each_entry_safe(p, next, list, link) | 346 | list_for_each_entry_safe(p, next, list, link) |
326 | p->callback(p, &ohci->card, p->status); | 347 | p->callback(p, &ohci->card, p->ack); |
327 | } | 348 | } |
328 | 349 | ||
329 | static void | 350 | static void |
330 | complete_transmission(struct fw_packet *packet, | 351 | complete_transmission(struct fw_packet *packet, |
331 | int status, struct list_head *list) | 352 | int ack, struct list_head *list) |
332 | { | 353 | { |
333 | list_move_tail(&packet->link, list); | 354 | list_move_tail(&packet->link, list); |
334 | packet->status = status; | 355 | packet->ack = ack; |
335 | } | 356 | } |
336 | 357 | ||
337 | /* This function prepares the first packet in the context queue for | 358 | /* This function prepares the first packet in the context queue for |
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 57ecf95e5271..4ca39f09f58a 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c | |||
@@ -426,15 +426,15 @@ free_response_callback(struct fw_packet *packet, | |||
426 | 426 | ||
427 | static void | 427 | static void |
428 | fw_fill_response(struct fw_packet *response, | 428 | fw_fill_response(struct fw_packet *response, |
429 | u32 *request, u32 *data, size_t length) | 429 | struct fw_packet *request, void *data) |
430 | { | 430 | { |
431 | int tcode, tlabel, extended_tcode, source, destination; | 431 | int tcode, tlabel, extended_tcode, source, destination; |
432 | 432 | ||
433 | tcode = header_get_tcode(request[0]); | 433 | tcode = header_get_tcode(request->header[0]); |
434 | tlabel = header_get_tlabel(request[0]); | 434 | tlabel = header_get_tlabel(request->header[0]); |
435 | source = header_get_destination(request[0]); | 435 | source = header_get_destination(request->header[0]); |
436 | destination = header_get_source(request[1]); | 436 | destination = header_get_source(request->header[1]); |
437 | extended_tcode = header_get_extended_tcode(request[3]); | 437 | extended_tcode = header_get_extended_tcode(request->header[3]); |
438 | 438 | ||
439 | response->header[0] = | 439 | response->header[0] = |
440 | header_retry(RETRY_1) | | 440 | header_retry(RETRY_1) | |
@@ -463,11 +463,11 @@ fw_fill_response(struct fw_packet *response, | |||
463 | case TCODE_LOCK_REQUEST: | 463 | case TCODE_LOCK_REQUEST: |
464 | response->header[0] |= header_tcode(tcode + 2); | 464 | response->header[0] |= header_tcode(tcode + 2); |
465 | response->header[3] = | 465 | response->header[3] = |
466 | header_data_length(length) | | 466 | header_data_length(request->payload_length) | |
467 | header_extended_tcode(extended_tcode); | 467 | header_extended_tcode(extended_tcode); |
468 | response->header_length = 16; | 468 | response->header_length = 16; |
469 | response->payload = data; | 469 | response->payload = data; |
470 | response->payload_length = length; | 470 | response->payload_length = request->payload_length; |
471 | break; | 471 | break; |
472 | 472 | ||
473 | default: | 473 | default: |
@@ -477,24 +477,23 @@ fw_fill_response(struct fw_packet *response, | |||
477 | } | 477 | } |
478 | 478 | ||
479 | static struct fw_request * | 479 | static struct fw_request * |
480 | allocate_request(u32 *header, int ack, | 480 | allocate_request(struct fw_packet *p) |
481 | int speed, int timestamp, int generation) | ||
482 | { | 481 | { |
483 | struct fw_request *request; | 482 | struct fw_request *request; |
484 | u32 *data, length; | 483 | u32 *data, length; |
485 | int request_tcode; | 484 | int request_tcode, t; |
486 | 485 | ||
487 | request_tcode = header_get_tcode(header[0]); | 486 | request_tcode = header_get_tcode(p->header[0]); |
488 | switch (request_tcode) { | 487 | switch (request_tcode) { |
489 | case TCODE_WRITE_QUADLET_REQUEST: | 488 | case TCODE_WRITE_QUADLET_REQUEST: |
490 | data = &header[3]; | 489 | data = &p->header[3]; |
491 | length = 4; | 490 | length = 4; |
492 | break; | 491 | break; |
493 | 492 | ||
494 | case TCODE_WRITE_BLOCK_REQUEST: | 493 | case TCODE_WRITE_BLOCK_REQUEST: |
495 | case TCODE_LOCK_REQUEST: | 494 | case TCODE_LOCK_REQUEST: |
496 | data = &header[4]; | 495 | data = p->payload; |
497 | length = header_get_data_length(header[3]); | 496 | length = header_get_data_length(p->header[3]); |
498 | break; | 497 | break; |
499 | 498 | ||
500 | case TCODE_READ_QUADLET_REQUEST: | 499 | case TCODE_READ_QUADLET_REQUEST: |
@@ -504,7 +503,7 @@ allocate_request(u32 *header, int ack, | |||
504 | 503 | ||
505 | case TCODE_READ_BLOCK_REQUEST: | 504 | case TCODE_READ_BLOCK_REQUEST: |
506 | data = NULL; | 505 | data = NULL; |
507 | length = header_get_data_length(header[3]); | 506 | length = header_get_data_length(p->header[3]); |
508 | break; | 507 | break; |
509 | 508 | ||
510 | default: | 509 | default: |
@@ -516,16 +515,22 @@ allocate_request(u32 *header, int ack, | |||
516 | if (request == NULL) | 515 | if (request == NULL) |
517 | return NULL; | 516 | return NULL; |
518 | 517 | ||
519 | request->response.speed = speed; | 518 | t = (p->timestamp & 0x1fff) + 4000; |
520 | request->response.timestamp = timestamp; | 519 | if (t >= 8000) |
521 | request->response.generation = generation; | 520 | t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000; |
521 | else | ||
522 | t = (p->timestamp & ~0x1fff) + t; | ||
523 | |||
524 | request->response.speed = p->speed; | ||
525 | request->response.timestamp = t; | ||
526 | request->response.generation = p->generation; | ||
522 | request->response.callback = free_response_callback; | 527 | request->response.callback = free_response_callback; |
523 | request->ack = ack; | 528 | request->ack = p->ack; |
524 | request->length = length; | 529 | request->length = p->payload_length; |
525 | if (data) | 530 | if (data) |
526 | memcpy(request->data, data, length); | 531 | memcpy(request->data, p->payload, p->payload_length); |
527 | 532 | ||
528 | fw_fill_response(&request->response, header, request->data, length); | 533 | fw_fill_response(&request->response, p, request->data); |
529 | 534 | ||
530 | return request; | 535 | return request; |
531 | } | 536 | } |
@@ -554,31 +559,23 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) | |||
554 | EXPORT_SYMBOL(fw_send_response); | 559 | EXPORT_SYMBOL(fw_send_response); |
555 | 560 | ||
556 | void | 561 | void |
557 | fw_core_handle_request(struct fw_card *card, | 562 | fw_core_handle_request(struct fw_card *card, struct fw_packet *p) |
558 | int speed, int ack, int timestamp, | ||
559 | int generation, u32 length, u32 *header) | ||
560 | { | 563 | { |
561 | struct fw_address_handler *handler; | 564 | struct fw_address_handler *handler; |
562 | struct fw_request *request; | 565 | struct fw_request *request; |
563 | unsigned long long offset; | 566 | unsigned long long offset; |
564 | unsigned long flags; | 567 | unsigned long flags; |
565 | int tcode, destination, source, t; | 568 | int tcode, destination, source; |
566 | 569 | ||
567 | if (length > 2048) { | 570 | if (p->payload_length > 2048) { |
568 | /* FIXME: send error response. */ | 571 | /* FIXME: send error response. */ |
569 | return; | 572 | return; |
570 | } | 573 | } |
571 | 574 | ||
572 | if (ack != ACK_PENDING && ack != ACK_COMPLETE) | 575 | if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) |
573 | return; | 576 | return; |
574 | 577 | ||
575 | t = (timestamp & 0x1fff) + 4000; | 578 | request = allocate_request(p); |
576 | if (t >= 8000) | ||
577 | t = (timestamp & ~0x1fff) + 0x2000 + t - 8000; | ||
578 | else | ||
579 | t = (timestamp & ~0x1fff) + t; | ||
580 | |||
581 | request = allocate_request(header, ack, speed, t, generation); | ||
582 | if (request == NULL) { | 579 | if (request == NULL) { |
583 | /* FIXME: send statically allocated busy packet. */ | 580 | /* FIXME: send statically allocated busy packet. */ |
584 | return; | 581 | return; |
@@ -586,10 +583,10 @@ fw_core_handle_request(struct fw_card *card, | |||
586 | 583 | ||
587 | offset = | 584 | offset = |
588 | ((unsigned long long) | 585 | ((unsigned long long) |
589 | header_get_offset_high(header[1]) << 32) | header[2]; | 586 | header_get_offset_high(p->header[1]) << 32) | p->header[2]; |
590 | tcode = header_get_tcode(header[0]); | 587 | tcode = header_get_tcode(p->header[0]); |
591 | destination = header_get_destination(header[0]); | 588 | destination = header_get_destination(p->header[0]); |
592 | source = header_get_source(header[0]); | 589 | source = header_get_source(p->header[0]); |
593 | 590 | ||
594 | spin_lock_irqsave(&address_handler_lock, flags); | 591 | spin_lock_irqsave(&address_handler_lock, flags); |
595 | handler = lookup_enclosing_address_handler(&address_handler_list, | 592 | handler = lookup_enclosing_address_handler(&address_handler_list, |
@@ -607,16 +604,14 @@ fw_core_handle_request(struct fw_card *card, | |||
607 | else | 604 | else |
608 | handler->address_callback(card, request, | 605 | handler->address_callback(card, request, |
609 | tcode, destination, source, | 606 | tcode, destination, source, |
610 | generation, speed, offset, | 607 | p->generation, p->speed, offset, |
611 | request->data, request->length, | 608 | request->data, request->length, |
612 | handler->callback_data); | 609 | handler->callback_data); |
613 | } | 610 | } |
614 | EXPORT_SYMBOL(fw_core_handle_request); | 611 | EXPORT_SYMBOL(fw_core_handle_request); |
615 | 612 | ||
616 | void | 613 | void |
617 | fw_core_handle_response(struct fw_card *card, | 614 | fw_core_handle_response(struct fw_card *card, struct fw_packet *p) |
618 | int speed, int ack, int timestamp, | ||
619 | u32 length, u32 *header) | ||
620 | { | 615 | { |
621 | struct fw_transaction *t; | 616 | struct fw_transaction *t; |
622 | unsigned long flags; | 617 | unsigned long flags; |
@@ -624,11 +619,11 @@ fw_core_handle_response(struct fw_card *card, | |||
624 | size_t data_length; | 619 | size_t data_length; |
625 | int tcode, tlabel, destination, source, rcode; | 620 | int tcode, tlabel, destination, source, rcode; |
626 | 621 | ||
627 | tcode = header_get_tcode(header[0]); | 622 | tcode = header_get_tcode(p->header[0]); |
628 | tlabel = header_get_tlabel(header[0]); | 623 | tlabel = header_get_tlabel(p->header[0]); |
629 | destination = header_get_destination(header[0]); | 624 | destination = header_get_destination(p->header[0]); |
630 | source = header_get_source(header[1]); | 625 | source = header_get_source(p->header[1]); |
631 | rcode = header_get_rcode(header[1]); | 626 | rcode = header_get_rcode(p->header[1]); |
632 | 627 | ||
633 | spin_lock_irqsave(&card->lock, flags); | 628 | spin_lock_irqsave(&card->lock, flags); |
634 | list_for_each_entry(t, &card->transaction_list, link) { | 629 | list_for_each_entry(t, &card->transaction_list, link) { |
@@ -650,7 +645,7 @@ fw_core_handle_response(struct fw_card *card, | |||
650 | 645 | ||
651 | switch (tcode) { | 646 | switch (tcode) { |
652 | case TCODE_READ_QUADLET_RESPONSE: | 647 | case TCODE_READ_QUADLET_RESPONSE: |
653 | data = (u32 *) &header[3]; | 648 | data = (u32 *) &p->header[3]; |
654 | data_length = 4; | 649 | data_length = 4; |
655 | break; | 650 | break; |
656 | 651 | ||
@@ -661,8 +656,8 @@ fw_core_handle_response(struct fw_card *card, | |||
661 | 656 | ||
662 | case TCODE_READ_BLOCK_RESPONSE: | 657 | case TCODE_READ_BLOCK_RESPONSE: |
663 | case TCODE_LOCK_RESPONSE: | 658 | case TCODE_LOCK_RESPONSE: |
664 | data = &header[4]; | 659 | data = &p->header[4]; |
665 | data_length = header_get_data_length(header[3]); | 660 | data_length = header_get_data_length(p->header[3]); |
666 | break; | 661 | break; |
667 | 662 | ||
668 | default: | 663 | default: |
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index df652452bdb5..903235b142f2 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
@@ -180,7 +180,7 @@ struct fw_packet { | |||
180 | * must never block. | 180 | * must never block. |
181 | */ | 181 | */ |
182 | fw_packet_callback_t callback; | 182 | fw_packet_callback_t callback; |
183 | int status; | 183 | int ack; |
184 | struct list_head link; | 184 | struct list_head link; |
185 | }; | 185 | }; |
186 | 186 | ||
@@ -415,14 +415,9 @@ fw_core_handle_bus_reset(struct fw_card *card, | |||
415 | int node_id, int generation, | 415 | int node_id, int generation, |
416 | int self_id_count, u32 *self_ids); | 416 | int self_id_count, u32 *self_ids); |
417 | void | 417 | void |
418 | fw_core_handle_request(struct fw_card *card, | 418 | fw_core_handle_request(struct fw_card *card, struct fw_packet *request); |
419 | int speed, int ack, int timestamp, | ||
420 | int generation, | ||
421 | u32 length, u32 *payload); | ||
422 | void | ||
423 | fw_core_handle_response(struct fw_card *card, | ||
424 | int speed, int ack, int timestamp, | ||
425 | u32 length, u32 *payload); | ||
426 | 419 | ||
420 | void | ||
421 | fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); | ||
427 | 422 | ||
428 | #endif /* __fw_transaction_h */ | 423 | #endif /* __fw_transaction_h */ |