bna: fix interrupts storm caused by erroneous packets
[linux/fpc-iii.git] / sound / firewire / fireworks / fireworks_transaction.c
blobf550808d178416cfd8c67cb9b78722687b2001e5
1 /*
2 * fireworks_transaction.c - a part of driver for Fireworks based devices
4 * Copyright (c) 2013-2014 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
9 /*
10 * Fireworks have its own transaction. The transaction can be delivered by AV/C
11 * Vendor Specific command frame or usual asynchronous transaction. At least,
12 * Windows driver and firmware version 5.5 or later don't use AV/C command.
14 * Transaction substance:
15 * At first, 6 data exist. Following to the data, parameters for each command
16 * exist. All of the parameters are 32 bit aligned to big endian.
17 * data[0]: Length of transaction substance
18 * data[1]: Transaction version
19 * data[2]: Sequence number. This is incremented by the device
20 * data[3]: Transaction category
21 * data[4]: Transaction command
22 * data[5]: Return value in response.
23 * data[6-]: Parameters
25 * Transaction address:
26 * command: 0xecc000000000
27 * response: 0xecc080000000 (default)
29 * I note that the address for response can be changed by command. But this
30 * module uses the default address.
32 #include "./fireworks.h"
34 #define MEMORY_SPACE_EFW_COMMAND 0xecc000000000ULL
35 #define MEMORY_SPACE_EFW_RESPONSE 0xecc080000000ULL
37 #define ERROR_RETRIES 3
38 #define ERROR_DELAY_MS 5
39 #define EFC_TIMEOUT_MS 125
41 static DEFINE_SPINLOCK(instances_lock);
42 static struct snd_efw *instances[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
44 static DEFINE_SPINLOCK(transaction_queues_lock);
45 static LIST_HEAD(transaction_queues);
47 enum transaction_queue_state {
48 STATE_PENDING,
49 STATE_BUS_RESET,
50 STATE_COMPLETE
53 struct transaction_queue {
54 struct list_head list;
55 struct fw_unit *unit;
56 void *buf;
57 unsigned int size;
58 u32 seqnum;
59 enum transaction_queue_state state;
60 wait_queue_head_t wait;
63 int snd_efw_transaction_cmd(struct fw_unit *unit,
64 const void *cmd, unsigned int size)
66 return snd_fw_transaction(unit, TCODE_WRITE_BLOCK_REQUEST,
67 MEMORY_SPACE_EFW_COMMAND,
68 (void *)cmd, size, 0);
71 int snd_efw_transaction_run(struct fw_unit *unit,
72 const void *cmd, unsigned int cmd_size,
73 void *resp, unsigned int resp_size)
75 struct transaction_queue t;
76 unsigned int tries;
77 int ret;
79 t.unit = unit;
80 t.buf = resp;
81 t.size = resp_size;
82 t.seqnum = be32_to_cpu(((struct snd_efw_transaction *)cmd)->seqnum) + 1;
83 t.state = STATE_PENDING;
84 init_waitqueue_head(&t.wait);
86 spin_lock_irq(&transaction_queues_lock);
87 list_add_tail(&t.list, &transaction_queues);
88 spin_unlock_irq(&transaction_queues_lock);
90 tries = 0;
91 do {
92 ret = snd_efw_transaction_cmd(t.unit, (void *)cmd, cmd_size);
93 if (ret < 0)
94 break;
96 wait_event_timeout(t.wait, t.state != STATE_PENDING,
97 msecs_to_jiffies(EFC_TIMEOUT_MS));
99 if (t.state == STATE_COMPLETE) {
100 ret = t.size;
101 break;
102 } else if (t.state == STATE_BUS_RESET) {
103 msleep(ERROR_DELAY_MS);
104 } else if (++tries >= ERROR_RETRIES) {
105 dev_err(&t.unit->device, "EFW transaction timed out\n");
106 ret = -EIO;
107 break;
109 } while (1);
111 spin_lock_irq(&transaction_queues_lock);
112 list_del(&t.list);
113 spin_unlock_irq(&transaction_queues_lock);
115 return ret;
118 static void
119 copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode)
121 size_t capacity, till_end;
122 struct snd_efw_transaction *t;
124 spin_lock_irq(&efw->lock);
126 t = (struct snd_efw_transaction *)data;
127 length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length);
129 if (efw->push_ptr < efw->pull_ptr)
130 capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr);
131 else
132 capacity = snd_efw_resp_buf_size -
133 (unsigned int)(efw->push_ptr - efw->pull_ptr);
135 /* confirm enough space for this response */
136 if (capacity < length) {
137 *rcode = RCODE_CONFLICT_ERROR;
138 goto end;
141 /* copy to ring buffer */
142 while (length > 0) {
143 till_end = snd_efw_resp_buf_size -
144 (unsigned int)(efw->push_ptr - efw->resp_buf);
145 till_end = min_t(unsigned int, length, till_end);
147 memcpy(efw->push_ptr, data, till_end);
149 efw->push_ptr += till_end;
150 if (efw->push_ptr >= efw->resp_buf + snd_efw_resp_buf_size)
151 efw->push_ptr -= snd_efw_resp_buf_size;
153 length -= till_end;
154 data += till_end;
157 /* for hwdep */
158 efw->resp_queues++;
159 wake_up(&efw->hwdep_wait);
161 *rcode = RCODE_COMPLETE;
162 end:
163 spin_unlock_irq(&efw->lock);
166 static void
167 handle_resp_for_user(struct fw_card *card, int generation, int source,
168 void *data, size_t length, int *rcode)
170 struct fw_device *device;
171 struct snd_efw *efw;
172 unsigned int i;
174 spin_lock_irq(&instances_lock);
176 for (i = 0; i < SNDRV_CARDS; i++) {
177 efw = instances[i];
178 if (efw == NULL)
179 continue;
180 device = fw_parent_device(efw->unit);
181 if ((device->card != card) ||
182 (device->generation != generation))
183 continue;
184 smp_rmb(); /* node id vs. generation */
185 if (device->node_id != source)
186 continue;
188 break;
190 if (i == SNDRV_CARDS)
191 goto end;
193 copy_resp_to_buf(efw, data, length, rcode);
194 end:
195 spin_unlock_irq(&instances_lock);
198 static void
199 handle_resp_for_kernel(struct fw_card *card, int generation, int source,
200 void *data, size_t length, int *rcode, u32 seqnum)
202 struct fw_device *device;
203 struct transaction_queue *t;
204 unsigned long flags;
206 spin_lock_irqsave(&transaction_queues_lock, flags);
207 list_for_each_entry(t, &transaction_queues, list) {
208 device = fw_parent_device(t->unit);
209 if ((device->card != card) ||
210 (device->generation != generation))
211 continue;
212 smp_rmb(); /* node_id vs. generation */
213 if (device->node_id != source)
214 continue;
216 if ((t->state == STATE_PENDING) && (t->seqnum == seqnum)) {
217 t->state = STATE_COMPLETE;
218 t->size = min_t(unsigned int, length, t->size);
219 memcpy(t->buf, data, t->size);
220 wake_up(&t->wait);
221 *rcode = RCODE_COMPLETE;
224 spin_unlock_irqrestore(&transaction_queues_lock, flags);
227 static void
228 efw_response(struct fw_card *card, struct fw_request *request,
229 int tcode, int destination, int source,
230 int generation, unsigned long long offset,
231 void *data, size_t length, void *callback_data)
233 int rcode, dummy;
234 u32 seqnum;
236 rcode = RCODE_TYPE_ERROR;
237 if (length < sizeof(struct snd_efw_transaction)) {
238 rcode = RCODE_DATA_ERROR;
239 goto end;
240 } else if (offset != MEMORY_SPACE_EFW_RESPONSE) {
241 rcode = RCODE_ADDRESS_ERROR;
242 goto end;
245 seqnum = be32_to_cpu(((struct snd_efw_transaction *)data)->seqnum);
246 if (seqnum > SND_EFW_TRANSACTION_USER_SEQNUM_MAX + 1) {
247 handle_resp_for_kernel(card, generation, source,
248 data, length, &rcode, seqnum);
249 if (snd_efw_resp_buf_debug)
250 handle_resp_for_user(card, generation, source,
251 data, length, &dummy);
252 } else {
253 handle_resp_for_user(card, generation, source,
254 data, length, &rcode);
256 end:
257 fw_send_response(card, request, rcode);
260 void snd_efw_transaction_add_instance(struct snd_efw *efw)
262 unsigned int i;
264 spin_lock_irq(&instances_lock);
266 for (i = 0; i < SNDRV_CARDS; i++) {
267 if (instances[i] != NULL)
268 continue;
269 instances[i] = efw;
270 break;
273 spin_unlock_irq(&instances_lock);
276 void snd_efw_transaction_remove_instance(struct snd_efw *efw)
278 unsigned int i;
280 spin_lock_irq(&instances_lock);
282 for (i = 0; i < SNDRV_CARDS; i++) {
283 if (instances[i] != efw)
284 continue;
285 instances[i] = NULL;
288 spin_unlock_irq(&instances_lock);
291 void snd_efw_transaction_bus_reset(struct fw_unit *unit)
293 struct transaction_queue *t;
295 spin_lock_irq(&transaction_queues_lock);
296 list_for_each_entry(t, &transaction_queues, list) {
297 if ((t->unit == unit) &&
298 (t->state == STATE_PENDING)) {
299 t->state = STATE_BUS_RESET;
300 wake_up(&t->wait);
303 spin_unlock_irq(&transaction_queues_lock);
306 static struct fw_address_handler resp_register_handler = {
307 .length = SND_EFW_RESPONSE_MAXIMUM_BYTES,
308 .address_callback = efw_response
311 int snd_efw_transaction_register(void)
313 static const struct fw_address_region resp_register_region = {
314 .start = MEMORY_SPACE_EFW_RESPONSE,
315 .end = MEMORY_SPACE_EFW_RESPONSE +
316 SND_EFW_RESPONSE_MAXIMUM_BYTES
318 return fw_core_add_address_handler(&resp_register_handler,
319 &resp_register_region);
322 void snd_efw_transaction_unregister(void)
324 WARN_ON(!list_empty(&transaction_queues));
325 fw_core_remove_address_handler(&resp_register_handler);