diff options
Diffstat (limited to 'sound/firewire/fcp.c')
-rw-r--r-- | sound/firewire/fcp.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c index 860c08073c59..6876bfa9f27d 100644 --- a/sound/firewire/fcp.c +++ b/sound/firewire/fcp.c | |||
@@ -30,6 +30,7 @@ enum fcp_state { | |||
30 | STATE_PENDING, | 30 | STATE_PENDING, |
31 | STATE_BUS_RESET, | 31 | STATE_BUS_RESET, |
32 | STATE_COMPLETE, | 32 | STATE_COMPLETE, |
33 | STATE_DEFERRED, | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | struct fcp_transaction { | 36 | struct fcp_transaction { |
@@ -40,6 +41,7 @@ struct fcp_transaction { | |||
40 | unsigned int response_match_bytes; | 41 | unsigned int response_match_bytes; |
41 | enum fcp_state state; | 42 | enum fcp_state state; |
42 | wait_queue_head_t wait; | 43 | wait_queue_head_t wait; |
44 | bool deferrable; | ||
43 | }; | 45 | }; |
44 | 46 | ||
45 | /** | 47 | /** |
@@ -81,6 +83,9 @@ int fcp_avc_transaction(struct fw_unit *unit, | |||
81 | t.state = STATE_PENDING; | 83 | t.state = STATE_PENDING; |
82 | init_waitqueue_head(&t.wait); | 84 | init_waitqueue_head(&t.wait); |
83 | 85 | ||
86 | if (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03) | ||
87 | t.deferrable = true; | ||
88 | |||
84 | spin_lock_irq(&transactions_lock); | 89 | spin_lock_irq(&transactions_lock); |
85 | list_add_tail(&t.list, &transactions); | 90 | list_add_tail(&t.list, &transactions); |
86 | spin_unlock_irq(&transactions_lock); | 91 | spin_unlock_irq(&transactions_lock); |
@@ -93,11 +98,21 @@ int fcp_avc_transaction(struct fw_unit *unit, | |||
93 | (void *)command, command_size, 0); | 98 | (void *)command, command_size, 0); |
94 | if (ret < 0) | 99 | if (ret < 0) |
95 | break; | 100 | break; |
96 | 101 | deferred: | |
97 | wait_event_timeout(t.wait, t.state != STATE_PENDING, | 102 | wait_event_timeout(t.wait, t.state != STATE_PENDING, |
98 | msecs_to_jiffies(FCP_TIMEOUT_MS)); | 103 | msecs_to_jiffies(FCP_TIMEOUT_MS)); |
99 | 104 | ||
100 | if (t.state == STATE_COMPLETE) { | 105 | if (t.state == STATE_DEFERRED) { |
106 | /* | ||
107 | * 'AV/C General Specification' define no time limit | ||
108 | * on command completion once an INTERIM response has | ||
109 | * been sent. but we promise to finish this function | ||
110 | * for a caller. Here we use FCP_TIMEOUT_MS for next | ||
111 | * interval. This is not in the specification. | ||
112 | */ | ||
113 | t.state = STATE_PENDING; | ||
114 | goto deferred; | ||
115 | } else if (t.state == STATE_COMPLETE) { | ||
101 | ret = t.response_size; | 116 | ret = t.response_size; |
102 | break; | 117 | break; |
103 | } else if (t.state == STATE_BUS_RESET) { | 118 | } else if (t.state == STATE_BUS_RESET) { |
@@ -132,7 +147,8 @@ void fcp_bus_reset(struct fw_unit *unit) | |||
132 | spin_lock_irq(&transactions_lock); | 147 | spin_lock_irq(&transactions_lock); |
133 | list_for_each_entry(t, &transactions, list) { | 148 | list_for_each_entry(t, &transactions, list) { |
134 | if (t->unit == unit && | 149 | if (t->unit == unit && |
135 | t->state == STATE_PENDING) { | 150 | (t->state == STATE_PENDING || |
151 | t->state == STATE_DEFERRED)) { | ||
136 | t->state = STATE_BUS_RESET; | 152 | t->state = STATE_BUS_RESET; |
137 | wake_up(&t->wait); | 153 | wake_up(&t->wait); |
138 | } | 154 | } |
@@ -186,10 +202,15 @@ static void fcp_response(struct fw_card *card, struct fw_request *request, | |||
186 | 202 | ||
187 | if (t->state == STATE_PENDING && | 203 | if (t->state == STATE_PENDING && |
188 | is_matching_response(t, data, length)) { | 204 | is_matching_response(t, data, length)) { |
189 | t->state = STATE_COMPLETE; | 205 | if (t->deferrable && *(const u8 *)data == 0x0f) { |
190 | t->response_size = min((unsigned int)length, | 206 | t->state = STATE_DEFERRED; |
191 | t->response_size); | 207 | } else { |
192 | memcpy(t->response_buffer, data, t->response_size); | 208 | t->state = STATE_COMPLETE; |
209 | t->response_size = min_t(unsigned int, length, | ||
210 | t->response_size); | ||
211 | memcpy(t->response_buffer, data, | ||
212 | t->response_size); | ||
213 | } | ||
193 | wake_up(&t->wait); | 214 | wake_up(&t->wait); |
194 | } | 215 | } |
195 | } | 216 | } |