1 // SPDX-License-Identifier: GPL-2.0-only
3 * fireworks_transaction.c - a part of driver for Fireworks based devices
5 * Copyright (c) 2013-2014 Takashi Sakamoto
9 * Fireworks have its own transaction. The transaction can be delivered by AV/C
10 * Vendor Specific command frame or usual asynchronous transaction. At least,
11 * Windows driver and firmware version 5.5 or later don't use AV/C command.
13 * Transaction substance:
14 * At first, 6 data exist. Following to the data, parameters for each command
15 * exist. All of the parameters are 32 bit aligned to big endian.
16 * data[0]: Length of transaction substance
17 * data[1]: Transaction version
18 * data[2]: Sequence number. This is incremented by the device
19 * data[3]: Transaction category
20 * data[4]: Transaction command
21 * data[5]: Return value in response.
22 * data[6-]: Parameters
24 * Transaction address:
25 * command: 0xecc000000000
26 * response: 0xecc080000000 (default)
28 * I note that the address for response can be changed by command. But this
29 * module uses the default address.
31 #include "./fireworks.h"
33 #define MEMORY_SPACE_EFW_COMMAND 0xecc000000000ULL
34 #define MEMORY_SPACE_EFW_RESPONSE 0xecc080000000ULL
36 #define ERROR_RETRIES 3
37 #define ERROR_DELAY_MS 5
38 #define EFC_TIMEOUT_MS 125
40 static DEFINE_SPINLOCK(instances_lock
);
41 static struct snd_efw
*instances
[SNDRV_CARDS
] = SNDRV_DEFAULT_PTR
;
43 static DEFINE_SPINLOCK(transaction_queues_lock
);
44 static LIST_HEAD(transaction_queues
);
46 enum transaction_queue_state
{
52 struct transaction_queue
{
53 struct list_head list
;
58 enum transaction_queue_state state
;
59 wait_queue_head_t wait
;
62 int snd_efw_transaction_cmd(struct fw_unit
*unit
,
63 const void *cmd
, unsigned int size
)
65 return snd_fw_transaction(unit
, TCODE_WRITE_BLOCK_REQUEST
,
66 MEMORY_SPACE_EFW_COMMAND
,
67 (void *)cmd
, size
, 0);
70 int snd_efw_transaction_run(struct fw_unit
*unit
,
71 const void *cmd
, unsigned int cmd_size
,
72 void *resp
, unsigned int resp_size
)
74 struct transaction_queue t
;
81 t
.seqnum
= be32_to_cpu(((struct snd_efw_transaction
*)cmd
)->seqnum
) + 1;
82 t
.state
= STATE_PENDING
;
83 init_waitqueue_head(&t
.wait
);
85 spin_lock_irq(&transaction_queues_lock
);
86 list_add_tail(&t
.list
, &transaction_queues
);
87 spin_unlock_irq(&transaction_queues_lock
);
91 ret
= snd_efw_transaction_cmd(t
.unit
, (void *)cmd
, cmd_size
);
95 wait_event_timeout(t
.wait
, t
.state
!= STATE_PENDING
,
96 msecs_to_jiffies(EFC_TIMEOUT_MS
));
98 if (t
.state
== STATE_COMPLETE
) {
101 } else if (t
.state
== STATE_BUS_RESET
) {
102 msleep(ERROR_DELAY_MS
);
103 } else if (++tries
>= ERROR_RETRIES
) {
104 dev_err(&t
.unit
->device
, "EFW transaction timed out\n");
110 spin_lock_irq(&transaction_queues_lock
);
112 spin_unlock_irq(&transaction_queues_lock
);
118 copy_resp_to_buf(struct snd_efw
*efw
, void *data
, size_t length
, int *rcode
)
120 size_t capacity
, till_end
;
121 struct snd_efw_transaction
*t
;
123 t
= (struct snd_efw_transaction
*)data
;
124 length
= min_t(size_t, be32_to_cpu(t
->length
) * sizeof(u32
), length
);
126 spin_lock(&efw
->lock
);
128 if (efw
->push_ptr
< efw
->pull_ptr
)
129 capacity
= (unsigned int)(efw
->pull_ptr
- efw
->push_ptr
);
131 capacity
= snd_efw_resp_buf_size
-
132 (unsigned int)(efw
->push_ptr
- efw
->pull_ptr
);
134 /* confirm enough space for this response */
135 if (capacity
< length
) {
136 *rcode
= RCODE_CONFLICT_ERROR
;
140 /* copy to ring buffer */
142 till_end
= snd_efw_resp_buf_size
-
143 (unsigned int)(efw
->push_ptr
- efw
->resp_buf
);
144 till_end
= min_t(unsigned int, length
, till_end
);
146 memcpy(efw
->push_ptr
, data
, till_end
);
148 efw
->push_ptr
+= till_end
;
149 if (efw
->push_ptr
>= efw
->resp_buf
+ snd_efw_resp_buf_size
)
150 efw
->push_ptr
-= snd_efw_resp_buf_size
;
157 wake_up(&efw
->hwdep_wait
);
159 *rcode
= RCODE_COMPLETE
;
161 spin_unlock_irq(&efw
->lock
);
165 handle_resp_for_user(struct fw_card
*card
, int generation
, int source
,
166 void *data
, size_t length
, int *rcode
)
168 struct fw_device
*device
;
172 spin_lock_irq(&instances_lock
);
174 for (i
= 0; i
< SNDRV_CARDS
; i
++) {
178 device
= fw_parent_device(efw
->unit
);
179 if ((device
->card
!= card
) ||
180 (device
->generation
!= generation
))
182 smp_rmb(); /* node id vs. generation */
183 if (device
->node_id
!= source
)
188 if (i
== SNDRV_CARDS
)
191 copy_resp_to_buf(efw
, data
, length
, rcode
);
193 spin_unlock(&instances_lock
);
197 handle_resp_for_kernel(struct fw_card
*card
, int generation
, int source
,
198 void *data
, size_t length
, int *rcode
, u32 seqnum
)
200 struct fw_device
*device
;
201 struct transaction_queue
*t
;
204 spin_lock_irqsave(&transaction_queues_lock
, flags
);
205 list_for_each_entry(t
, &transaction_queues
, list
) {
206 device
= fw_parent_device(t
->unit
);
207 if ((device
->card
!= card
) ||
208 (device
->generation
!= generation
))
210 smp_rmb(); /* node_id vs. generation */
211 if (device
->node_id
!= source
)
214 if ((t
->state
== STATE_PENDING
) && (t
->seqnum
== seqnum
)) {
215 t
->state
= STATE_COMPLETE
;
216 t
->size
= min_t(unsigned int, length
, t
->size
);
217 memcpy(t
->buf
, data
, t
->size
);
219 *rcode
= RCODE_COMPLETE
;
222 spin_unlock_irqrestore(&transaction_queues_lock
, flags
);
226 efw_response(struct fw_card
*card
, struct fw_request
*request
,
227 int tcode
, int destination
, int source
,
228 int generation
, unsigned long long offset
,
229 void *data
, size_t length
, void *callback_data
)
234 rcode
= RCODE_TYPE_ERROR
;
235 if (length
< sizeof(struct snd_efw_transaction
)) {
236 rcode
= RCODE_DATA_ERROR
;
238 } else if (offset
!= MEMORY_SPACE_EFW_RESPONSE
) {
239 rcode
= RCODE_ADDRESS_ERROR
;
243 seqnum
= be32_to_cpu(((struct snd_efw_transaction
*)data
)->seqnum
);
244 if (seqnum
> SND_EFW_TRANSACTION_USER_SEQNUM_MAX
+ 1) {
245 handle_resp_for_kernel(card
, generation
, source
,
246 data
, length
, &rcode
, seqnum
);
247 if (snd_efw_resp_buf_debug
)
248 handle_resp_for_user(card
, generation
, source
,
249 data
, length
, &dummy
);
251 handle_resp_for_user(card
, generation
, source
,
252 data
, length
, &rcode
);
255 fw_send_response(card
, request
, rcode
);
258 void snd_efw_transaction_add_instance(struct snd_efw
*efw
)
262 spin_lock_irq(&instances_lock
);
264 for (i
= 0; i
< SNDRV_CARDS
; i
++) {
265 if (instances
[i
] != NULL
)
271 spin_unlock_irq(&instances_lock
);
274 void snd_efw_transaction_remove_instance(struct snd_efw
*efw
)
278 spin_lock_irq(&instances_lock
);
280 for (i
= 0; i
< SNDRV_CARDS
; i
++) {
281 if (instances
[i
] != efw
)
286 spin_unlock_irq(&instances_lock
);
289 void snd_efw_transaction_bus_reset(struct fw_unit
*unit
)
291 struct transaction_queue
*t
;
293 spin_lock_irq(&transaction_queues_lock
);
294 list_for_each_entry(t
, &transaction_queues
, list
) {
295 if ((t
->unit
== unit
) &&
296 (t
->state
== STATE_PENDING
)) {
297 t
->state
= STATE_BUS_RESET
;
301 spin_unlock_irq(&transaction_queues_lock
);
304 static struct fw_address_handler resp_register_handler
= {
305 .length
= SND_EFW_RESPONSE_MAXIMUM_BYTES
,
306 .address_callback
= efw_response
309 int snd_efw_transaction_register(void)
311 static const struct fw_address_region resp_register_region
= {
312 .start
= MEMORY_SPACE_EFW_RESPONSE
,
313 .end
= MEMORY_SPACE_EFW_RESPONSE
+
314 SND_EFW_RESPONSE_MAXIMUM_BYTES
316 return fw_core_add_address_handler(&resp_register_handler
,
317 &resp_register_region
);
320 void snd_efw_transaction_unregister(void)
322 WARN_ON(!list_empty(&transaction_queues
));
323 fw_core_remove_address_handler(&resp_register_handler
);