ALSA: fireworks: accessing to user space outside spinlock
[cascardo/linux.git] / sound / firewire / fireworks / fireworks_transaction.c
1 /*
2  * fireworks_transaction.c - a part of driver for Fireworks based devices
3  *
4  * Copyright (c) 2013-2014 Takashi Sakamoto
5  *
6  * Licensed under the terms of the GNU General Public License, version 2.
7  */
8
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.
13  *
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
24  *
25  * Transaction address:
26  *  command:    0xecc000000000
27  *  response:   0xecc080000000 (default)
28  *
29  * I note that the address for response can be changed by command. But this
30  * module uses the default address.
31  */
32 #include "./fireworks.h"
33
34 #define MEMORY_SPACE_EFW_COMMAND        0xecc000000000ULL
35 #define MEMORY_SPACE_EFW_RESPONSE       0xecc080000000ULL
36
37 #define ERROR_RETRIES 3
38 #define ERROR_DELAY_MS 5
39 #define EFC_TIMEOUT_MS 125
40
41 static DEFINE_SPINLOCK(instances_lock);
42 static struct snd_efw *instances[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
43
44 static DEFINE_SPINLOCK(transaction_queues_lock);
45 static LIST_HEAD(transaction_queues);
46
47 enum transaction_queue_state {
48         STATE_PENDING,
49         STATE_BUS_RESET,
50         STATE_COMPLETE
51 };
52
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;
61 };
62
63 int snd_efw_transaction_cmd(struct fw_unit *unit,
64                             const void *cmd, unsigned int size)
65 {
66         return snd_fw_transaction(unit, TCODE_WRITE_BLOCK_REQUEST,
67                                   MEMORY_SPACE_EFW_COMMAND,
68                                   (void *)cmd, size, 0);
69 }
70
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)
74 {
75         struct transaction_queue t;
76         unsigned int tries;
77         int ret;
78
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);
85
86         spin_lock_irq(&transaction_queues_lock);
87         list_add_tail(&t.list, &transaction_queues);
88         spin_unlock_irq(&transaction_queues_lock);
89
90         tries = 0;
91         do {
92                 ret = snd_efw_transaction_cmd(t.unit, (void *)cmd, cmd_size);
93                 if (ret < 0)
94                         break;
95
96                 wait_event_timeout(t.wait, t.state != STATE_PENDING,
97                                    msecs_to_jiffies(EFC_TIMEOUT_MS));
98
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;
108                 }
109         } while (1);
110
111         spin_lock_irq(&transaction_queues_lock);
112         list_del(&t.list);
113         spin_unlock_irq(&transaction_queues_lock);
114
115         return ret;
116 }
117
118 static void
119 copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode)
120 {
121         size_t capacity, till_end;
122         struct snd_efw_transaction *t;
123
124         t = (struct snd_efw_transaction *)data;
125         length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length);
126
127         spin_lock_irq(&efw->lock);
128
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);
134
135         /* confirm enough space for this response */
136         if (capacity < length) {
137                 *rcode = RCODE_CONFLICT_ERROR;
138                 goto end;
139         }
140
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);
146
147                 memcpy(efw->push_ptr, data, till_end);
148
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;
152
153                 length -= till_end;
154                 data += till_end;
155         }
156
157         /* for hwdep */
158         wake_up(&efw->hwdep_wait);
159
160         *rcode = RCODE_COMPLETE;
161 end:
162         spin_unlock_irq(&efw->lock);
163 }
164
165 static void
166 handle_resp_for_user(struct fw_card *card, int generation, int source,
167                      void *data, size_t length, int *rcode)
168 {
169         struct fw_device *device;
170         struct snd_efw *efw;
171         unsigned int i;
172
173         spin_lock_irq(&instances_lock);
174
175         for (i = 0; i < SNDRV_CARDS; i++) {
176                 efw = instances[i];
177                 if (efw == NULL)
178                         continue;
179                 device = fw_parent_device(efw->unit);
180                 if ((device->card != card) ||
181                     (device->generation != generation))
182                         continue;
183                 smp_rmb();      /* node id vs. generation */
184                 if (device->node_id != source)
185                         continue;
186
187                 break;
188         }
189         if (i == SNDRV_CARDS)
190                 goto end;
191
192         copy_resp_to_buf(efw, data, length, rcode);
193 end:
194         spin_unlock_irq(&instances_lock);
195 }
196
197 static void
198 handle_resp_for_kernel(struct fw_card *card, int generation, int source,
199                        void *data, size_t length, int *rcode, u32 seqnum)
200 {
201         struct fw_device *device;
202         struct transaction_queue *t;
203         unsigned long flags;
204
205         spin_lock_irqsave(&transaction_queues_lock, flags);
206         list_for_each_entry(t, &transaction_queues, list) {
207                 device = fw_parent_device(t->unit);
208                 if ((device->card != card) ||
209                     (device->generation != generation))
210                         continue;
211                 smp_rmb();      /* node_id vs. generation */
212                 if (device->node_id != source)
213                         continue;
214
215                 if ((t->state == STATE_PENDING) && (t->seqnum == seqnum)) {
216                         t->state = STATE_COMPLETE;
217                         t->size = min_t(unsigned int, length, t->size);
218                         memcpy(t->buf, data, t->size);
219                         wake_up(&t->wait);
220                         *rcode = RCODE_COMPLETE;
221                 }
222         }
223         spin_unlock_irqrestore(&transaction_queues_lock, flags);
224 }
225
226 static void
227 efw_response(struct fw_card *card, struct fw_request *request,
228              int tcode, int destination, int source,
229              int generation, unsigned long long offset,
230              void *data, size_t length, void *callback_data)
231 {
232         int rcode, dummy;
233         u32 seqnum;
234
235         rcode = RCODE_TYPE_ERROR;
236         if (length < sizeof(struct snd_efw_transaction)) {
237                 rcode = RCODE_DATA_ERROR;
238                 goto end;
239         } else if (offset != MEMORY_SPACE_EFW_RESPONSE) {
240                 rcode = RCODE_ADDRESS_ERROR;
241                 goto end;
242         }
243
244         seqnum = be32_to_cpu(((struct snd_efw_transaction *)data)->seqnum);
245         if (seqnum > SND_EFW_TRANSACTION_USER_SEQNUM_MAX + 1) {
246                 handle_resp_for_kernel(card, generation, source,
247                                        data, length, &rcode, seqnum);
248                 if (snd_efw_resp_buf_debug)
249                         handle_resp_for_user(card, generation, source,
250                                              data, length, &dummy);
251         } else {
252                 handle_resp_for_user(card, generation, source,
253                                      data, length, &rcode);
254         }
255 end:
256         fw_send_response(card, request, rcode);
257 }
258
259 void snd_efw_transaction_add_instance(struct snd_efw *efw)
260 {
261         unsigned int i;
262
263         spin_lock_irq(&instances_lock);
264
265         for (i = 0; i < SNDRV_CARDS; i++) {
266                 if (instances[i] != NULL)
267                         continue;
268                 instances[i] = efw;
269                 break;
270         }
271
272         spin_unlock_irq(&instances_lock);
273 }
274
275 void snd_efw_transaction_remove_instance(struct snd_efw *efw)
276 {
277         unsigned int i;
278
279         spin_lock_irq(&instances_lock);
280
281         for (i = 0; i < SNDRV_CARDS; i++) {
282                 if (instances[i] != efw)
283                         continue;
284                 instances[i] = NULL;
285         }
286
287         spin_unlock_irq(&instances_lock);
288 }
289
290 void snd_efw_transaction_bus_reset(struct fw_unit *unit)
291 {
292         struct transaction_queue *t;
293
294         spin_lock_irq(&transaction_queues_lock);
295         list_for_each_entry(t, &transaction_queues, list) {
296                 if ((t->unit == unit) &&
297                     (t->state == STATE_PENDING)) {
298                         t->state = STATE_BUS_RESET;
299                         wake_up(&t->wait);
300                 }
301         }
302         spin_unlock_irq(&transaction_queues_lock);
303 }
304
305 static struct fw_address_handler resp_register_handler = {
306         .length = SND_EFW_RESPONSE_MAXIMUM_BYTES,
307         .address_callback = efw_response
308 };
309
310 int snd_efw_transaction_register(void)
311 {
312         static const struct fw_address_region resp_register_region = {
313                 .start  = MEMORY_SPACE_EFW_RESPONSE,
314                 .end    = MEMORY_SPACE_EFW_RESPONSE +
315                           SND_EFW_RESPONSE_MAXIMUM_BYTES
316         };
317         return fw_core_add_address_handler(&resp_register_handler,
318                                            &resp_register_region);
319 }
320
321 void snd_efw_transaction_unregister(void)
322 {
323         WARN_ON(!list_empty(&transaction_queues));
324         fw_core_remove_address_handler(&resp_register_handler);
325 }