diff options
-rw-r--r-- | sound/firewire/cmp.c | 50 | ||||
-rw-r--r-- | sound/firewire/dice.c | 207 | ||||
-rw-r--r-- | sound/firewire/fcp.c | 2 | ||||
-rw-r--r-- | sound/firewire/isight.c | 43 | ||||
-rw-r--r-- | sound/firewire/lib.c | 24 | ||||
-rw-r--r-- | sound/firewire/lib.h | 7 | ||||
-rw-r--r-- | sound/firewire/scs1x.c | 8 | ||||
-rw-r--r-- | sound/firewire/speakers.c | 2 |
8 files changed, 137 insertions, 206 deletions
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index 645cb0ba4293..efdbf585e404 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c | |||
@@ -48,9 +48,6 @@ static int pcr_modify(struct cmp_connection *c, | |||
48 | int (*check)(struct cmp_connection *c, __be32 pcr), | 48 | int (*check)(struct cmp_connection *c, __be32 pcr), |
49 | enum bus_reset_handling bus_reset_handling) | 49 | enum bus_reset_handling bus_reset_handling) |
50 | { | 50 | { |
51 | struct fw_device *device = fw_parent_device(c->resources.unit); | ||
52 | int generation = c->resources.generation; | ||
53 | int rcode, errors = 0; | ||
54 | __be32 old_arg, buffer[2]; | 51 | __be32 old_arg, buffer[2]; |
55 | int err; | 52 | int err; |
56 | 53 | ||
@@ -59,36 +56,31 @@ static int pcr_modify(struct cmp_connection *c, | |||
59 | old_arg = buffer[0]; | 56 | old_arg = buffer[0]; |
60 | buffer[1] = modify(c, buffer[0]); | 57 | buffer[1] = modify(c, buffer[0]); |
61 | 58 | ||
62 | rcode = fw_run_transaction( | 59 | err = snd_fw_transaction( |
63 | device->card, TCODE_LOCK_COMPARE_SWAP, | 60 | c->resources.unit, TCODE_LOCK_COMPARE_SWAP, |
64 | device->node_id, generation, device->max_speed, | ||
65 | CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index), | 61 | CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index), |
66 | buffer, 8); | 62 | buffer, 8, |
67 | 63 | FW_FIXED_GENERATION | c->resources.generation); | |
68 | if (rcode == RCODE_COMPLETE) { | 64 | |
69 | if (buffer[0] == old_arg) /* success? */ | 65 | if (err < 0) { |
70 | break; | 66 | if (err == -EAGAIN && |
71 | 67 | bus_reset_handling == SUCCEED_ON_BUS_RESET) | |
72 | if (check) { | 68 | err = 0; |
73 | err = check(c, buffer[0]); | 69 | return err; |
74 | if (err < 0) | 70 | } |
75 | return err; | 71 | |
76 | } | 72 | if (buffer[0] == old_arg) /* success? */ |
77 | } else if (rcode == RCODE_GENERATION) | 73 | break; |
78 | goto bus_reset; | 74 | |
79 | else if (rcode_is_permanent_error(rcode) || ++errors >= 3) | 75 | if (check) { |
80 | goto io_error; | 76 | err = check(c, buffer[0]); |
77 | if (err < 0) | ||
78 | return err; | ||
79 | } | ||
81 | } | 80 | } |
82 | c->last_pcr_value = buffer[1]; | 81 | c->last_pcr_value = buffer[1]; |
83 | 82 | ||
84 | return 0; | 83 | return 0; |
85 | |||
86 | io_error: | ||
87 | cmp_error(c, "transaction failed: %s\n", fw_rcode_string(rcode)); | ||
88 | return -EIO; | ||
89 | |||
90 | bus_reset: | ||
91 | return bus_reset_handling == ABORT_ON_BUS_RESET ? -EAGAIN : 0; | ||
92 | } | 84 | } |
93 | 85 | ||
94 | 86 | ||
@@ -108,7 +100,7 @@ int cmp_connection_init(struct cmp_connection *c, | |||
108 | 100 | ||
109 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, | 101 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, |
110 | CSR_REGISTER_BASE + CSR_IMPR, | 102 | CSR_REGISTER_BASE + CSR_IMPR, |
111 | &impr_be, 4); | 103 | &impr_be, 4, 0); |
112 | if (err < 0) | 104 | if (err < 0) |
113 | return err; | 105 | return err; |
114 | impr = be32_to_cpu(impr_be); | 106 | impr = be32_to_cpu(impr_be); |
diff --git a/sound/firewire/dice.c b/sound/firewire/dice.c index e1d8dff23397..59d5ca4438b2 100644 --- a/sound/firewire/dice.c +++ b/sound/firewire/dice.c | |||
@@ -118,7 +118,7 @@ static int dice_owner_set(struct dice *dice) | |||
118 | { | 118 | { |
119 | struct fw_device *device = fw_parent_device(dice->unit); | 119 | struct fw_device *device = fw_parent_device(dice->unit); |
120 | __be64 *buffer; | 120 | __be64 *buffer; |
121 | int rcode, err, errors = 0; | 121 | int err, errors = 0; |
122 | 122 | ||
123 | buffer = kmalloc(2 * 8, GFP_KERNEL); | 123 | buffer = kmalloc(2 * 8, GFP_KERNEL); |
124 | if (!buffer) | 124 | if (!buffer) |
@@ -132,31 +132,24 @@ static int dice_owner_set(struct dice *dice) | |||
132 | 132 | ||
133 | dice->owner_generation = device->generation; | 133 | dice->owner_generation = device->generation; |
134 | smp_rmb(); /* node_id vs. generation */ | 134 | smp_rmb(); /* node_id vs. generation */ |
135 | rcode = fw_run_transaction(device->card, | 135 | err = snd_fw_transaction(dice->unit, |
136 | TCODE_LOCK_COMPARE_SWAP, | 136 | TCODE_LOCK_COMPARE_SWAP, |
137 | device->node_id, | 137 | global_address(dice, GLOBAL_OWNER), |
138 | dice->owner_generation, | 138 | buffer, 2 * 8, |
139 | device->max_speed, | 139 | FW_FIXED_GENERATION | |
140 | global_address(dice, GLOBAL_OWNER), | 140 | dice->owner_generation); |
141 | buffer, 2 * 8); | 141 | |
142 | 142 | if (err == 0) { | |
143 | if (rcode == RCODE_COMPLETE) { | 143 | if (buffer[0] != cpu_to_be64(OWNER_NO_OWNER)) { |
144 | if (buffer[0] == cpu_to_be64(OWNER_NO_OWNER)) { | ||
145 | err = 0; | ||
146 | } else { | ||
147 | dev_err(&dice->unit->device, | 144 | dev_err(&dice->unit->device, |
148 | "device is already in use\n"); | 145 | "device is already in use\n"); |
149 | err = -EBUSY; | 146 | err = -EBUSY; |
150 | } | 147 | } |
151 | break; | 148 | break; |
152 | } | 149 | } |
153 | if (rcode_is_permanent_error(rcode) || ++errors >= 3) { | 150 | if (err != -EAGAIN || ++errors >= 3) |
154 | dev_err(&dice->unit->device, | ||
155 | "setting device owner failed: %s\n", | ||
156 | fw_rcode_string(rcode)); | ||
157 | err = -EIO; | ||
158 | break; | 151 | break; |
159 | } | 152 | |
160 | msleep(20); | 153 | msleep(20); |
161 | } | 154 | } |
162 | 155 | ||
@@ -169,7 +162,7 @@ static int dice_owner_update(struct dice *dice) | |||
169 | { | 162 | { |
170 | struct fw_device *device = fw_parent_device(dice->unit); | 163 | struct fw_device *device = fw_parent_device(dice->unit); |
171 | __be64 *buffer; | 164 | __be64 *buffer; |
172 | int rcode, err, errors = 0; | 165 | int err; |
173 | 166 | ||
174 | if (dice->owner_generation == -1) | 167 | if (dice->owner_generation == -1) |
175 | return 0; | 168 | return 0; |
@@ -178,44 +171,26 @@ static int dice_owner_update(struct dice *dice) | |||
178 | if (!buffer) | 171 | if (!buffer) |
179 | return -ENOMEM; | 172 | return -ENOMEM; |
180 | 173 | ||
181 | for (;;) { | 174 | buffer[0] = cpu_to_be64(OWNER_NO_OWNER); |
182 | buffer[0] = cpu_to_be64(OWNER_NO_OWNER); | 175 | buffer[1] = cpu_to_be64( |
183 | buffer[1] = cpu_to_be64( | 176 | ((u64)device->card->node_id << OWNER_NODE_SHIFT) | |
184 | ((u64)device->card->node_id << OWNER_NODE_SHIFT) | | 177 | dice->notification_handler.offset); |
185 | dice->notification_handler.offset); | ||
186 | 178 | ||
187 | dice->owner_generation = device->generation; | 179 | dice->owner_generation = device->generation; |
188 | smp_rmb(); /* node_id vs. generation */ | 180 | smp_rmb(); /* node_id vs. generation */ |
189 | rcode = fw_run_transaction(device->card, | 181 | err = snd_fw_transaction(dice->unit, TCODE_LOCK_COMPARE_SWAP, |
190 | TCODE_LOCK_COMPARE_SWAP, | 182 | global_address(dice, GLOBAL_OWNER), |
191 | device->node_id, | 183 | buffer, 2 * 8, |
192 | dice->owner_generation, | 184 | FW_FIXED_GENERATION | dice->owner_generation); |
193 | device->max_speed, | 185 | |
194 | global_address(dice, GLOBAL_OWNER), | 186 | if (err == 0) { |
195 | buffer, 2 * 8); | 187 | if (buffer[0] != cpu_to_be64(OWNER_NO_OWNER)) { |
196 | |||
197 | if (rcode == RCODE_COMPLETE) { | ||
198 | if (buffer[0] == cpu_to_be64(OWNER_NO_OWNER)) { | ||
199 | err = 0; | ||
200 | } else { | ||
201 | dev_err(&dice->unit->device, | ||
202 | "device is already in use\n"); | ||
203 | err = -EBUSY; | ||
204 | } | ||
205 | break; | ||
206 | } | ||
207 | if (rcode == RCODE_GENERATION) { | ||
208 | err = 0; /* try again later */ | ||
209 | break; | ||
210 | } | ||
211 | if (rcode_is_permanent_error(rcode) || ++errors >= 3) { | ||
212 | dev_err(&dice->unit->device, | 188 | dev_err(&dice->unit->device, |
213 | "setting device owner failed: %s\n", | 189 | "device is already in use\n"); |
214 | fw_rcode_string(rcode)); | 190 | err = -EBUSY; |
215 | err = -EIO; | ||
216 | break; | ||
217 | } | 191 | } |
218 | msleep(20); | 192 | } else if (err == -EAGAIN) { |
193 | err = 0; /* try again later */ | ||
219 | } | 194 | } |
220 | 195 | ||
221 | kfree(buffer); | 196 | kfree(buffer); |
@@ -230,38 +205,19 @@ static void dice_owner_clear(struct dice *dice) | |||
230 | { | 205 | { |
231 | struct fw_device *device = fw_parent_device(dice->unit); | 206 | struct fw_device *device = fw_parent_device(dice->unit); |
232 | __be64 *buffer; | 207 | __be64 *buffer; |
233 | int rcode, errors = 0; | ||
234 | 208 | ||
235 | buffer = kmalloc(2 * 8, GFP_KERNEL); | 209 | buffer = kmalloc(2 * 8, GFP_KERNEL); |
236 | if (!buffer) | 210 | if (!buffer) |
237 | return; | 211 | return; |
238 | 212 | ||
239 | for (;;) { | 213 | buffer[0] = cpu_to_be64( |
240 | buffer[0] = cpu_to_be64( | 214 | ((u64)device->card->node_id << OWNER_NODE_SHIFT) | |
241 | ((u64)device->card->node_id << OWNER_NODE_SHIFT) | | 215 | dice->notification_handler.offset); |
242 | dice->notification_handler.offset); | 216 | buffer[1] = cpu_to_be64(OWNER_NO_OWNER); |
243 | buffer[1] = cpu_to_be64(OWNER_NO_OWNER); | 217 | snd_fw_transaction(dice->unit, TCODE_LOCK_COMPARE_SWAP, |
244 | 218 | global_address(dice, GLOBAL_OWNER), | |
245 | rcode = fw_run_transaction(device->card, | 219 | buffer, 2 * 8, FW_QUIET | |
246 | TCODE_LOCK_COMPARE_SWAP, | 220 | FW_FIXED_GENERATION | dice->owner_generation); |
247 | device->node_id, | ||
248 | dice->owner_generation, | ||
249 | device->max_speed, | ||
250 | global_address(dice, GLOBAL_OWNER), | ||
251 | buffer, 2 * 8); | ||
252 | |||
253 | if (rcode == RCODE_COMPLETE) | ||
254 | break; | ||
255 | if (rcode == RCODE_GENERATION) | ||
256 | break; | ||
257 | if (rcode_is_permanent_error(rcode) || ++errors >= 3) { | ||
258 | dev_err(&dice->unit->device, | ||
259 | "clearing device owner failed: %s\n", | ||
260 | fw_rcode_string(rcode)); | ||
261 | break; | ||
262 | } | ||
263 | msleep(20); | ||
264 | } | ||
265 | 221 | ||
266 | kfree(buffer); | 222 | kfree(buffer); |
267 | 223 | ||
@@ -270,67 +226,32 @@ static void dice_owner_clear(struct dice *dice) | |||
270 | 226 | ||
271 | static int dice_enable_set(struct dice *dice) | 227 | static int dice_enable_set(struct dice *dice) |
272 | { | 228 | { |
273 | struct fw_device *device = fw_parent_device(dice->unit); | ||
274 | __be32 value; | 229 | __be32 value; |
275 | int rcode, err, errors = 0; | 230 | int err; |
276 | 231 | ||
277 | value = cpu_to_be32(1); | 232 | value = cpu_to_be32(1); |
278 | for (;;) { | 233 | err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, |
279 | rcode = fw_run_transaction(device->card, | 234 | global_address(dice, GLOBAL_ENABLE), |
280 | TCODE_WRITE_QUADLET_REQUEST, | 235 | &value, 4, |
281 | device->node_id, | 236 | FW_FIXED_GENERATION | dice->owner_generation); |
282 | dice->owner_generation, | 237 | if (err < 0) |
283 | device->max_speed, | 238 | return err; |
284 | global_address(dice, GLOBAL_ENABLE), | ||
285 | &value, 4); | ||
286 | if (rcode == RCODE_COMPLETE) { | ||
287 | dice->global_enabled = true; | ||
288 | err = 0; | ||
289 | break; | ||
290 | } | ||
291 | if (rcode == RCODE_GENERATION) { | ||
292 | err = -EAGAIN; | ||
293 | break; | ||
294 | } | ||
295 | if (rcode_is_permanent_error(rcode) || ++errors >= 3) { | ||
296 | dev_err(&dice->unit->device, | ||
297 | "device enabling failed: %s\n", | ||
298 | fw_rcode_string(rcode)); | ||
299 | err = -EIO; | ||
300 | break; | ||
301 | } | ||
302 | msleep(20); | ||
303 | } | ||
304 | 239 | ||
305 | return err; | 240 | dice->global_enabled = true; |
241 | |||
242 | return 0; | ||
306 | } | 243 | } |
307 | 244 | ||
308 | static void dice_enable_clear(struct dice *dice) | 245 | static void dice_enable_clear(struct dice *dice) |
309 | { | 246 | { |
310 | struct fw_device *device = fw_parent_device(dice->unit); | ||
311 | __be32 value; | 247 | __be32 value; |
312 | int rcode, errors = 0; | ||
313 | 248 | ||
314 | value = 0; | 249 | value = 0; |
315 | for (;;) { | 250 | snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, |
316 | rcode = fw_run_transaction(device->card, | 251 | global_address(dice, GLOBAL_ENABLE), |
317 | TCODE_WRITE_QUADLET_REQUEST, | 252 | &value, 4, FW_QUIET | |
318 | device->node_id, | 253 | FW_FIXED_GENERATION | dice->owner_generation); |
319 | dice->owner_generation, | 254 | |
320 | device->max_speed, | ||
321 | global_address(dice, GLOBAL_ENABLE), | ||
322 | &value, 4); | ||
323 | if (rcode == RCODE_COMPLETE || | ||
324 | rcode == RCODE_GENERATION) | ||
325 | break; | ||
326 | if (rcode_is_permanent_error(rcode) || ++errors >= 3) { | ||
327 | dev_err(&dice->unit->device, | ||
328 | "device disabling failed: %s\n", | ||
329 | fw_rcode_string(rcode)); | ||
330 | break; | ||
331 | } | ||
332 | msleep(20); | ||
333 | } | ||
334 | dice->global_enabled = false; | 255 | dice->global_enabled = false; |
335 | } | 256 | } |
336 | 257 | ||
@@ -384,7 +305,7 @@ static int dice_open(struct snd_pcm_substream *substream) | |||
384 | 305 | ||
385 | err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, | 306 | err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, |
386 | global_address(dice, GLOBAL_CLOCK_SELECT), | 307 | global_address(dice, GLOBAL_CLOCK_SELECT), |
387 | &clock_sel, 4); | 308 | &clock_sel, 4, 0); |
388 | if (err < 0) | 309 | if (err < 0) |
389 | goto err_lock; | 310 | goto err_lock; |
390 | rate_index = (be32_to_cpu(clock_sel) & CLOCK_RATE_MASK) | 311 | rate_index = (be32_to_cpu(clock_sel) & CLOCK_RATE_MASK) |
@@ -396,7 +317,7 @@ static int dice_open(struct snd_pcm_substream *substream) | |||
396 | 317 | ||
397 | err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, | 318 | err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, |
398 | rx_address(dice, RX_NUMBER_AUDIO), | 319 | rx_address(dice, RX_NUMBER_AUDIO), |
399 | data, 2 * 4); | 320 | data, 2 * 4, 0); |
400 | if (err < 0) | 321 | if (err < 0) |
401 | goto err_lock; | 322 | goto err_lock; |
402 | number_audio = be32_to_cpu(data[0]); | 323 | number_audio = be32_to_cpu(data[0]); |
@@ -488,7 +409,7 @@ static int dice_stream_start(struct dice *dice) | |||
488 | err = snd_fw_transaction(dice->unit, | 409 | err = snd_fw_transaction(dice->unit, |
489 | TCODE_WRITE_QUADLET_REQUEST, | 410 | TCODE_WRITE_QUADLET_REQUEST, |
490 | rx_address(dice, RX_ISOCHRONOUS), | 411 | rx_address(dice, RX_ISOCHRONOUS), |
491 | &channel, 4); | 412 | &channel, 4, 0); |
492 | if (err < 0) | 413 | if (err < 0) |
493 | goto err_resources; | 414 | goto err_resources; |
494 | } | 415 | } |
@@ -502,7 +423,7 @@ static int dice_stream_start(struct dice *dice) | |||
502 | err_rx_channel: | 423 | err_rx_channel: |
503 | channel = cpu_to_be32((u32)-1); | 424 | channel = cpu_to_be32((u32)-1); |
504 | snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, | 425 | snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, |
505 | rx_address(dice, RX_ISOCHRONOUS), &channel, 4); | 426 | rx_address(dice, RX_ISOCHRONOUS), &channel, 4, 0); |
506 | err_resources: | 427 | err_resources: |
507 | fw_iso_resources_free(&dice->resources); | 428 | fw_iso_resources_free(&dice->resources); |
508 | error: | 429 | error: |
@@ -528,7 +449,7 @@ static void dice_stream_stop(struct dice *dice) | |||
528 | 449 | ||
529 | channel = cpu_to_be32((u32)-1); | 450 | channel = cpu_to_be32((u32)-1); |
530 | snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, | 451 | snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, |
531 | rx_address(dice, RX_ISOCHRONOUS), &channel, 4); | 452 | rx_address(dice, RX_ISOCHRONOUS), &channel, 4, 0); |
532 | 453 | ||
533 | fw_iso_resources_free(&dice->resources); | 454 | fw_iso_resources_free(&dice->resources); |
534 | } | 455 | } |
@@ -880,7 +801,7 @@ static int dice_interface_check(struct fw_unit *unit) | |||
880 | */ | 801 | */ |
881 | err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST, | 802 | err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST, |
882 | DICE_PRIVATE_SPACE, | 803 | DICE_PRIVATE_SPACE, |
883 | pointers, sizeof(pointers)); | 804 | pointers, sizeof(pointers), 0); |
884 | if (err < 0) | 805 | if (err < 0) |
885 | return -ENODEV; | 806 | return -ENODEV; |
886 | for (i = 0; i < ARRAY_SIZE(pointers); ++i) { | 807 | for (i = 0; i < ARRAY_SIZE(pointers); ++i) { |
@@ -896,7 +817,7 @@ static int dice_interface_check(struct fw_unit *unit) | |||
896 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, | 817 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, |
897 | DICE_PRIVATE_SPACE + | 818 | DICE_PRIVATE_SPACE + |
898 | be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION, | 819 | be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION, |
899 | &version, 4); | 820 | &version, 4, 0); |
900 | if (err < 0) | 821 | if (err < 0) |
901 | return -ENODEV; | 822 | return -ENODEV; |
902 | if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) { | 823 | if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) { |
@@ -915,7 +836,7 @@ static int dice_init_offsets(struct dice *dice) | |||
915 | 836 | ||
916 | err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, | 837 | err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, |
917 | DICE_PRIVATE_SPACE, | 838 | DICE_PRIVATE_SPACE, |
918 | pointers, sizeof(pointers)); | 839 | pointers, sizeof(pointers), 0); |
919 | if (err < 0) | 840 | if (err < 0) |
920 | return err; | 841 | return err; |
921 | 842 | ||
@@ -939,7 +860,7 @@ static void dice_card_strings(struct dice *dice) | |||
939 | BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname)); | 860 | BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname)); |
940 | err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, | 861 | err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, |
941 | global_address(dice, GLOBAL_NICK_NAME), | 862 | global_address(dice, GLOBAL_NICK_NAME), |
942 | card->shortname, sizeof(card->shortname)); | 863 | card->shortname, sizeof(card->shortname), 0); |
943 | if (err >= 0) { | 864 | if (err >= 0) { |
944 | /* DICE strings are returned in "always-wrong" endianness */ | 865 | /* DICE strings are returned in "always-wrong" endianness */ |
945 | BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0); | 866 | BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0); |
@@ -1015,14 +936,14 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | |||
1015 | 936 | ||
1016 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, | 937 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, |
1017 | global_address(dice, GLOBAL_CLOCK_SELECT), | 938 | global_address(dice, GLOBAL_CLOCK_SELECT), |
1018 | &clock_sel, 4); | 939 | &clock_sel, 4, 0); |
1019 | if (err < 0) | 940 | if (err < 0) |
1020 | goto error; | 941 | goto error; |
1021 | clock_sel &= cpu_to_be32(~CLOCK_SOURCE_MASK); | 942 | clock_sel &= cpu_to_be32(~CLOCK_SOURCE_MASK); |
1022 | clock_sel |= cpu_to_be32(CLOCK_SOURCE_ARX1); | 943 | clock_sel |= cpu_to_be32(CLOCK_SOURCE_ARX1); |
1023 | err = snd_fw_transaction(unit, TCODE_WRITE_QUADLET_REQUEST, | 944 | err = snd_fw_transaction(unit, TCODE_WRITE_QUADLET_REQUEST, |
1024 | global_address(dice, GLOBAL_CLOCK_SELECT), | 945 | global_address(dice, GLOBAL_CLOCK_SELECT), |
1025 | &clock_sel, 4); | 946 | &clock_sel, 4, 0); |
1026 | if (err < 0) | 947 | if (err < 0) |
1027 | goto error; | 948 | goto error; |
1028 | 949 | ||
diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c index ec578b5ad8da..860c08073c59 100644 --- a/sound/firewire/fcp.c +++ b/sound/firewire/fcp.c | |||
@@ -90,7 +90,7 @@ int fcp_avc_transaction(struct fw_unit *unit, | |||
90 | : TCODE_WRITE_BLOCK_REQUEST; | 90 | : TCODE_WRITE_BLOCK_REQUEST; |
91 | ret = snd_fw_transaction(t.unit, tcode, | 91 | ret = snd_fw_transaction(t.unit, tcode, |
92 | CSR_REGISTER_BASE + CSR_FCP_COMMAND, | 92 | CSR_REGISTER_BASE + CSR_FCP_COMMAND, |
93 | (void *)command, command_size); | 93 | (void *)command, command_size, 0); |
94 | if (ret < 0) | 94 | if (ret < 0) |
95 | break; | 95 | break; |
96 | 96 | ||
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 58a5afefdc69..fd42e6b315e6 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c | |||
@@ -217,7 +217,7 @@ static void isight_packet(struct fw_iso_context *context, u32 cycle, | |||
217 | 217 | ||
218 | static int isight_connect(struct isight *isight) | 218 | static int isight_connect(struct isight *isight) |
219 | { | 219 | { |
220 | int ch, err, rcode, errors = 0; | 220 | int ch, err; |
221 | __be32 value; | 221 | __be32 value; |
222 | 222 | ||
223 | retry_after_bus_reset: | 223 | retry_after_bus_reset: |
@@ -230,27 +230,19 @@ retry_after_bus_reset: | |||
230 | } | 230 | } |
231 | 231 | ||
232 | value = cpu_to_be32(ch | (isight->device->max_speed << SPEED_SHIFT)); | 232 | value = cpu_to_be32(ch | (isight->device->max_speed << SPEED_SHIFT)); |
233 | for (;;) { | 233 | err = snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, |
234 | rcode = fw_run_transaction( | 234 | isight->audio_base + REG_ISO_TX_CONFIG, |
235 | isight->device->card, | 235 | &value, 4, FW_FIXED_GENERATION | |
236 | TCODE_WRITE_QUADLET_REQUEST, | 236 | isight->resources.generation); |
237 | isight->device->node_id, | 237 | if (err == -EAGAIN) { |
238 | isight->resources.generation, | 238 | fw_iso_resources_free(&isight->resources); |
239 | isight->device->max_speed, | 239 | goto retry_after_bus_reset; |
240 | isight->audio_base + REG_ISO_TX_CONFIG, | 240 | } else if (err < 0) { |
241 | &value, 4); | 241 | goto err_resources; |
242 | if (rcode == RCODE_COMPLETE) { | ||
243 | return 0; | ||
244 | } else if (rcode == RCODE_GENERATION) { | ||
245 | fw_iso_resources_free(&isight->resources); | ||
246 | goto retry_after_bus_reset; | ||
247 | } else if (rcode_is_permanent_error(rcode) || ++errors >= 3) { | ||
248 | err = -EIO; | ||
249 | goto err_resources; | ||
250 | } | ||
251 | msleep(5); | ||
252 | } | 242 | } |
253 | 243 | ||
244 | return 0; | ||
245 | |||
254 | err_resources: | 246 | err_resources: |
255 | fw_iso_resources_free(&isight->resources); | 247 | fw_iso_resources_free(&isight->resources); |
256 | error: | 248 | error: |
@@ -315,17 +307,19 @@ static int isight_hw_params(struct snd_pcm_substream *substream, | |||
315 | static int reg_read(struct isight *isight, int offset, __be32 *value) | 307 | static int reg_read(struct isight *isight, int offset, __be32 *value) |
316 | { | 308 | { |
317 | return snd_fw_transaction(isight->unit, TCODE_READ_QUADLET_REQUEST, | 309 | return snd_fw_transaction(isight->unit, TCODE_READ_QUADLET_REQUEST, |
318 | isight->audio_base + offset, value, 4); | 310 | isight->audio_base + offset, value, 4, 0); |
319 | } | 311 | } |
320 | 312 | ||
321 | static int reg_write(struct isight *isight, int offset, __be32 value) | 313 | static int reg_write(struct isight *isight, int offset, __be32 value) |
322 | { | 314 | { |
323 | return snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, | 315 | return snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, |
324 | isight->audio_base + offset, &value, 4); | 316 | isight->audio_base + offset, &value, 4, 0); |
325 | } | 317 | } |
326 | 318 | ||
327 | static void isight_stop_streaming(struct isight *isight) | 319 | static void isight_stop_streaming(struct isight *isight) |
328 | { | 320 | { |
321 | __be32 value; | ||
322 | |||
329 | if (!isight->context) | 323 | if (!isight->context) |
330 | return; | 324 | return; |
331 | 325 | ||
@@ -333,7 +327,10 @@ static void isight_stop_streaming(struct isight *isight) | |||
333 | fw_iso_context_destroy(isight->context); | 327 | fw_iso_context_destroy(isight->context); |
334 | isight->context = NULL; | 328 | isight->context = NULL; |
335 | fw_iso_resources_free(&isight->resources); | 329 | fw_iso_resources_free(&isight->resources); |
336 | reg_write(isight, REG_AUDIO_ENABLE, 0); | 330 | value = 0; |
331 | snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, | ||
332 | isight->audio_base + REG_AUDIO_ENABLE, | ||
333 | &value, 4, FW_QUIET); | ||
337 | } | 334 | } |
338 | 335 | ||
339 | static int isight_hw_free(struct snd_pcm_substream *substream) | 336 | static int isight_hw_free(struct snd_pcm_substream *substream) |
diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c index 14eb41498372..7409edba9f06 100644 --- a/sound/firewire/lib.c +++ b/sound/firewire/lib.c | |||
@@ -11,7 +11,7 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include "lib.h" | 12 | #include "lib.h" |
13 | 13 | ||
14 | #define ERROR_RETRY_DELAY_MS 5 | 14 | #define ERROR_RETRY_DELAY_MS 20 |
15 | 15 | ||
16 | /** | 16 | /** |
17 | * snd_fw_transaction - send a request and wait for its completion | 17 | * snd_fw_transaction - send a request and wait for its completion |
@@ -20,6 +20,9 @@ | |||
20 | * @offset: the address in the target's address space | 20 | * @offset: the address in the target's address space |
21 | * @buffer: input/output data | 21 | * @buffer: input/output data |
22 | * @length: length of @buffer | 22 | * @length: length of @buffer |
23 | * @flags: use %FW_FIXED_GENERATION and add the generation value to attempt the | ||
24 | * request only in that generation; use %FW_QUIET to suppress error | ||
25 | * messages | ||
23 | * | 26 | * |
24 | * Submits an asynchronous request to the target device, and waits for the | 27 | * Submits an asynchronous request to the target device, and waits for the |
25 | * response. The node ID and the current generation are derived from @unit. | 28 | * response. The node ID and the current generation are derived from @unit. |
@@ -27,14 +30,18 @@ | |||
27 | * Returns zero on success, or a negative error code. | 30 | * Returns zero on success, or a negative error code. |
28 | */ | 31 | */ |
29 | int snd_fw_transaction(struct fw_unit *unit, int tcode, | 32 | int snd_fw_transaction(struct fw_unit *unit, int tcode, |
30 | u64 offset, void *buffer, size_t length) | 33 | u64 offset, void *buffer, size_t length, |
34 | unsigned int flags) | ||
31 | { | 35 | { |
32 | struct fw_device *device = fw_parent_device(unit); | 36 | struct fw_device *device = fw_parent_device(unit); |
33 | int generation, rcode, tries = 0; | 37 | int generation, rcode, tries = 0; |
34 | 38 | ||
39 | generation = flags & FW_GENERATION_MASK; | ||
35 | for (;;) { | 40 | for (;;) { |
36 | generation = device->generation; | 41 | if (!(flags & FW_FIXED_GENERATION)) { |
37 | smp_rmb(); /* node_id vs. generation */ | 42 | generation = device->generation; |
43 | smp_rmb(); /* node_id vs. generation */ | ||
44 | } | ||
38 | rcode = fw_run_transaction(device->card, tcode, | 45 | rcode = fw_run_transaction(device->card, tcode, |
39 | device->node_id, generation, | 46 | device->node_id, generation, |
40 | device->max_speed, offset, | 47 | device->max_speed, offset, |
@@ -43,9 +50,14 @@ int snd_fw_transaction(struct fw_unit *unit, int tcode, | |||
43 | if (rcode == RCODE_COMPLETE) | 50 | if (rcode == RCODE_COMPLETE) |
44 | return 0; | 51 | return 0; |
45 | 52 | ||
53 | if (rcode == RCODE_GENERATION && (flags & FW_FIXED_GENERATION)) | ||
54 | return -EAGAIN; | ||
55 | |||
46 | if (rcode_is_permanent_error(rcode) || ++tries >= 3) { | 56 | if (rcode_is_permanent_error(rcode) || ++tries >= 3) { |
47 | dev_err(&unit->device, "transaction failed: %s\n", | 57 | if (!(flags & FW_QUIET)) |
48 | fw_rcode_string(rcode)); | 58 | dev_err(&unit->device, |
59 | "transaction failed: %s\n", | ||
60 | fw_rcode_string(rcode)); | ||
49 | return -EIO; | 61 | return -EIO; |
50 | } | 62 | } |
51 | 63 | ||
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h index aef301476ea9..02cfabc9c3c4 100644 --- a/sound/firewire/lib.h +++ b/sound/firewire/lib.h | |||
@@ -6,8 +6,13 @@ | |||
6 | 6 | ||
7 | struct fw_unit; | 7 | struct fw_unit; |
8 | 8 | ||
9 | #define FW_GENERATION_MASK 0x00ff | ||
10 | #define FW_FIXED_GENERATION 0x0100 | ||
11 | #define FW_QUIET 0x0200 | ||
12 | |||
9 | int snd_fw_transaction(struct fw_unit *unit, int tcode, | 13 | int snd_fw_transaction(struct fw_unit *unit, int tcode, |
10 | u64 offset, void *buffer, size_t length); | 14 | u64 offset, void *buffer, size_t length, |
15 | unsigned int flags); | ||
11 | 16 | ||
12 | /* returns true if retrying the transaction would not make sense */ | 17 | /* returns true if retrying the transaction would not make sense */ |
13 | static inline bool rcode_is_permanent_error(int rcode) | 18 | static inline bool rcode_is_permanent_error(int rcode) |
diff --git a/sound/firewire/scs1x.c b/sound/firewire/scs1x.c index 505fc8123199..858023cf4298 100644 --- a/sound/firewire/scs1x.c +++ b/sound/firewire/scs1x.c | |||
@@ -369,7 +369,7 @@ static int scs_init_hss_address(struct scs *scs) | |||
369 | data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) | | 369 | data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) | |
370 | scs->hss_handler.offset); | 370 | scs->hss_handler.offset); |
371 | err = snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST, | 371 | err = snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST, |
372 | HSS1394_ADDRESS, &data, 8); | 372 | HSS1394_ADDRESS, &data, 8, 0); |
373 | if (err < 0) | 373 | if (err < 0) |
374 | dev_err(&scs->unit->device, "HSS1394 communication failed\n"); | 374 | dev_err(&scs->unit->device, "HSS1394 communication failed\n"); |
375 | 375 | ||
@@ -455,12 +455,16 @@ err_card: | |||
455 | static void scs_update(struct fw_unit *unit) | 455 | static void scs_update(struct fw_unit *unit) |
456 | { | 456 | { |
457 | struct scs *scs = dev_get_drvdata(&unit->device); | 457 | struct scs *scs = dev_get_drvdata(&unit->device); |
458 | int generation; | ||
458 | __be64 data; | 459 | __be64 data; |
459 | 460 | ||
460 | data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) | | 461 | data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) | |
461 | scs->hss_handler.offset); | 462 | scs->hss_handler.offset); |
463 | generation = fw_parent_device(unit)->generation; | ||
464 | smp_rmb(); /* node_id vs. generation */ | ||
462 | snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST, | 465 | snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST, |
463 | HSS1394_ADDRESS, &data, 8); | 466 | HSS1394_ADDRESS, &data, 8, |
467 | FW_FIXED_GENERATION | generation); | ||
464 | } | 468 | } |
465 | 469 | ||
466 | static void scs_remove(struct fw_unit *unit) | 470 | static void scs_remove(struct fw_unit *unit) |
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c index 6a68caf1d04f..eb3f7dce1d6c 100644 --- a/sound/firewire/speakers.c +++ b/sound/firewire/speakers.c | |||
@@ -647,7 +647,7 @@ static u32 fwspk_read_firmware_version(struct fw_unit *unit) | |||
647 | int err; | 647 | int err; |
648 | 648 | ||
649 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, | 649 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, |
650 | OXFORD_FIRMWARE_ID_ADDRESS, &data, 4); | 650 | OXFORD_FIRMWARE_ID_ADDRESS, &data, 4, 0); |
651 | return err >= 0 ? be32_to_cpu(data) : 0; | 651 | return err >= 0 ? be32_to_cpu(data) : 0; |
652 | } | 652 | } |
653 | 653 | ||