diff options
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/core-card.c | 4 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 76 |
2 files changed, 69 insertions, 11 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 901435cdd5c2..d0f15c2f1e1d 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c | |||
@@ -428,6 +428,10 @@ void fw_card_initialize(struct fw_card *card, | |||
428 | card->device = device; | 428 | card->device = device; |
429 | card->current_tlabel = 0; | 429 | card->current_tlabel = 0; |
430 | card->tlabel_mask = 0; | 430 | card->tlabel_mask = 0; |
431 | card->split_timeout_hi = 0; | ||
432 | card->split_timeout_lo = 800 << 19; | ||
433 | card->split_timeout_cycles = 800; | ||
434 | card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10); | ||
431 | card->color = 0; | 435 | card->color = 0; |
432 | card->broadcast_channel = BROADCAST_CHANNEL_INITIAL; | 436 | card->broadcast_channel = BROADCAST_CHANNEL_INITIAL; |
433 | 437 | ||
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 0034229dfd14..9a7d3ec23f2b 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c | |||
@@ -339,7 +339,8 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, | |||
339 | setup_timer(&t->split_timeout_timer, | 339 | setup_timer(&t->split_timeout_timer, |
340 | split_transaction_timeout_callback, (unsigned long)t); | 340 | split_transaction_timeout_callback, (unsigned long)t); |
341 | /* FIXME: start this timer later, relative to t->timestamp */ | 341 | /* FIXME: start this timer later, relative to t->timestamp */ |
342 | mod_timer(&t->split_timeout_timer, jiffies + DIV_ROUND_UP(HZ, 10)); | 342 | mod_timer(&t->split_timeout_timer, |
343 | jiffies + card->split_timeout_jiffies); | ||
343 | t->callback = callback; | 344 | t->callback = callback; |
344 | t->callback_data = callback_data; | 345 | t->callback_data = callback_data; |
345 | 346 | ||
@@ -673,11 +674,28 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header, | |||
673 | } | 674 | } |
674 | EXPORT_SYMBOL(fw_fill_response); | 675 | EXPORT_SYMBOL(fw_fill_response); |
675 | 676 | ||
676 | static struct fw_request *allocate_request(struct fw_packet *p) | 677 | static u32 compute_split_timeout_timestamp(struct fw_card *card, |
678 | u32 request_timestamp) | ||
679 | { | ||
680 | unsigned int cycles; | ||
681 | u32 timestamp; | ||
682 | |||
683 | cycles = card->split_timeout_cycles; | ||
684 | cycles += request_timestamp & 0x1fff; | ||
685 | |||
686 | timestamp = request_timestamp & ~0x1fff; | ||
687 | timestamp += (cycles / 8000) << 13; | ||
688 | timestamp |= cycles % 8000; | ||
689 | |||
690 | return timestamp; | ||
691 | } | ||
692 | |||
693 | static struct fw_request *allocate_request(struct fw_card *card, | ||
694 | struct fw_packet *p) | ||
677 | { | 695 | { |
678 | struct fw_request *request; | 696 | struct fw_request *request; |
679 | u32 *data, length; | 697 | u32 *data, length; |
680 | int request_tcode, t; | 698 | int request_tcode; |
681 | 699 | ||
682 | request_tcode = HEADER_GET_TCODE(p->header[0]); | 700 | request_tcode = HEADER_GET_TCODE(p->header[0]); |
683 | switch (request_tcode) { | 701 | switch (request_tcode) { |
@@ -712,14 +730,9 @@ static struct fw_request *allocate_request(struct fw_packet *p) | |||
712 | if (request == NULL) | 730 | if (request == NULL) |
713 | return NULL; | 731 | return NULL; |
714 | 732 | ||
715 | t = (p->timestamp & 0x1fff) + 4000; | ||
716 | if (t >= 8000) | ||
717 | t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000; | ||
718 | else | ||
719 | t = (p->timestamp & ~0x1fff) + t; | ||
720 | |||
721 | request->response.speed = p->speed; | 733 | request->response.speed = p->speed; |
722 | request->response.timestamp = t; | 734 | request->response.timestamp = |
735 | compute_split_timeout_timestamp(card, p->timestamp); | ||
723 | request->response.generation = p->generation; | 736 | request->response.generation = p->generation; |
724 | request->response.ack = 0; | 737 | request->response.ack = 0; |
725 | request->response.callback = free_response_callback; | 738 | request->response.callback = free_response_callback; |
@@ -845,7 +858,7 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) | |||
845 | if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) | 858 | if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) |
846 | return; | 859 | return; |
847 | 860 | ||
848 | request = allocate_request(p); | 861 | request = allocate_request(card, p); |
849 | if (request == NULL) { | 862 | if (request == NULL) { |
850 | /* FIXME: send statically allocated busy packet. */ | 863 | /* FIXME: send statically allocated busy packet. */ |
851 | return; | 864 | return; |
@@ -993,6 +1006,19 @@ static u32 read_state_register(struct fw_card *card) | |||
993 | return 0; | 1006 | return 0; |
994 | } | 1007 | } |
995 | 1008 | ||
1009 | static void update_split_timeout(struct fw_card *card) | ||
1010 | { | ||
1011 | unsigned int cycles; | ||
1012 | |||
1013 | cycles = card->split_timeout_hi * 8000 + (card->split_timeout_lo >> 19); | ||
1014 | |||
1015 | cycles = max(cycles, 800u); /* minimum as per the spec */ | ||
1016 | cycles = min(cycles, 3u * 8000u); /* maximum OHCI timeout */ | ||
1017 | |||
1018 | card->split_timeout_cycles = cycles; | ||
1019 | card->split_timeout_jiffies = DIV_ROUND_UP(cycles * HZ, 8000); | ||
1020 | } | ||
1021 | |||
996 | static void handle_registers(struct fw_card *card, struct fw_request *request, | 1022 | static void handle_registers(struct fw_card *card, struct fw_request *request, |
997 | int tcode, int destination, int source, int generation, | 1023 | int tcode, int destination, int source, int generation, |
998 | int speed, unsigned long long offset, | 1024 | int speed, unsigned long long offset, |
@@ -1001,6 +1027,7 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, | |||
1001 | int reg = offset & ~CSR_REGISTER_BASE; | 1027 | int reg = offset & ~CSR_REGISTER_BASE; |
1002 | __be32 *data = payload; | 1028 | __be32 *data = payload; |
1003 | int rcode = RCODE_COMPLETE; | 1029 | int rcode = RCODE_COMPLETE; |
1030 | unsigned long flags; | ||
1004 | 1031 | ||
1005 | switch (reg) { | 1032 | switch (reg) { |
1006 | case CSR_STATE_CLEAR: | 1033 | case CSR_STATE_CLEAR: |
@@ -1039,6 +1066,33 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, | |||
1039 | rcode = RCODE_TYPE_ERROR; | 1066 | rcode = RCODE_TYPE_ERROR; |
1040 | break; | 1067 | break; |
1041 | 1068 | ||
1069 | case CSR_SPLIT_TIMEOUT_HI: | ||
1070 | if (tcode == TCODE_READ_QUADLET_REQUEST) { | ||
1071 | *data = cpu_to_be32(card->split_timeout_hi); | ||
1072 | } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { | ||
1073 | spin_lock_irqsave(&card->lock, flags); | ||
1074 | card->split_timeout_hi = be32_to_cpu(*data) & 7; | ||
1075 | update_split_timeout(card); | ||
1076 | spin_unlock_irqrestore(&card->lock, flags); | ||
1077 | } else { | ||
1078 | rcode = RCODE_TYPE_ERROR; | ||
1079 | } | ||
1080 | break; | ||
1081 | |||
1082 | case CSR_SPLIT_TIMEOUT_LO: | ||
1083 | if (tcode == TCODE_READ_QUADLET_REQUEST) { | ||
1084 | *data = cpu_to_be32(card->split_timeout_lo); | ||
1085 | } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { | ||
1086 | spin_lock_irqsave(&card->lock, flags); | ||
1087 | card->split_timeout_lo = | ||
1088 | be32_to_cpu(*data) & 0xfff80000; | ||
1089 | update_split_timeout(card); | ||
1090 | spin_unlock_irqrestore(&card->lock, flags); | ||
1091 | } else { | ||
1092 | rcode = RCODE_TYPE_ERROR; | ||
1093 | } | ||
1094 | break; | ||
1095 | |||
1042 | case CSR_CYCLE_TIME: | 1096 | case CSR_CYCLE_TIME: |
1043 | if (TCODE_IS_READ_REQUEST(tcode) && length == 4) | 1097 | if (TCODE_IS_READ_REQUEST(tcode) && length == 4) |
1044 | *data = cpu_to_be32(card->driver-> | 1098 | *data = cpu_to_be32(card->driver-> |