aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/cmp.c50
-rw-r--r--sound/firewire/dice.c207
-rw-r--r--sound/firewire/fcp.c2
-rw-r--r--sound/firewire/isight.c43
-rw-r--r--sound/firewire/lib.c24
-rw-r--r--sound/firewire/lib.h7
-rw-r--r--sound/firewire/scs1x.c8
-rw-r--r--sound/firewire/speakers.c2
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
86io_error:
87 cmp_error(c, "transaction failed: %s\n", fw_rcode_string(rcode));
88 return -EIO;
89
90bus_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
271static int dice_enable_set(struct dice *dice) 227static 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
308static void dice_enable_clear(struct dice *dice) 245static 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)
502err_rx_channel: 423err_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);
506err_resources: 427err_resources:
507 fw_iso_resources_free(&dice->resources); 428 fw_iso_resources_free(&dice->resources);
508error: 429error:
@@ -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
218static int isight_connect(struct isight *isight) 218static 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
223retry_after_bus_reset: 223retry_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
254err_resources: 246err_resources:
255 fw_iso_resources_free(&isight->resources); 247 fw_iso_resources_free(&isight->resources);
256error: 248error:
@@ -315,17 +307,19 @@ static int isight_hw_params(struct snd_pcm_substream *substream,
315static int reg_read(struct isight *isight, int offset, __be32 *value) 307static 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
321static int reg_write(struct isight *isight, int offset, __be32 value) 313static 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
327static void isight_stop_streaming(struct isight *isight) 319static 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
339static int isight_hw_free(struct snd_pcm_substream *substream) 336static 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 */
29int snd_fw_transaction(struct fw_unit *unit, int tcode, 32int 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
7struct fw_unit; 7struct fw_unit;
8 8
9#define FW_GENERATION_MASK 0x00ff
10#define FW_FIXED_GENERATION 0x0100
11#define FW_QUIET 0x0200
12
9int snd_fw_transaction(struct fw_unit *unit, int tcode, 13int 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 */
13static inline bool rcode_is_permanent_error(int rcode) 18static 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:
455static void scs_update(struct fw_unit *unit) 455static 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
466static void scs_remove(struct fw_unit *unit) 470static 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