diff options
Diffstat (limited to 'drivers/firewire/core-iso.c')
-rw-r--r-- | drivers/firewire/core-iso.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index c003fa4e2db1..57c3973093ad 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c | |||
@@ -185,6 +185,12 @@ int fw_iso_context_queue(struct fw_iso_context *ctx, | |||
185 | } | 185 | } |
186 | EXPORT_SYMBOL(fw_iso_context_queue); | 186 | EXPORT_SYMBOL(fw_iso_context_queue); |
187 | 187 | ||
188 | void fw_iso_context_queue_flush(struct fw_iso_context *ctx) | ||
189 | { | ||
190 | ctx->card->driver->flush_queue_iso(ctx); | ||
191 | } | ||
192 | EXPORT_SYMBOL(fw_iso_context_queue_flush); | ||
193 | |||
188 | int fw_iso_context_stop(struct fw_iso_context *ctx) | 194 | int fw_iso_context_stop(struct fw_iso_context *ctx) |
189 | { | 195 | { |
190 | return ctx->card->driver->stop_iso(ctx); | 196 | return ctx->card->driver->stop_iso(ctx); |
@@ -196,9 +202,10 @@ EXPORT_SYMBOL(fw_iso_context_stop); | |||
196 | */ | 202 | */ |
197 | 203 | ||
198 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | 204 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, |
199 | int bandwidth, bool allocate, __be32 data[2]) | 205 | int bandwidth, bool allocate) |
200 | { | 206 | { |
201 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; | 207 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; |
208 | __be32 data[2]; | ||
202 | 209 | ||
203 | /* | 210 | /* |
204 | * On a 1394a IRM with low contention, try < 1 is enough. | 211 | * On a 1394a IRM with low contention, try < 1 is enough. |
@@ -233,47 +240,48 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | |||
233 | } | 240 | } |
234 | 241 | ||
235 | static int manage_channel(struct fw_card *card, int irm_id, int generation, | 242 | static int manage_channel(struct fw_card *card, int irm_id, int generation, |
236 | u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) | 243 | u32 channels_mask, u64 offset, bool allocate) |
237 | { | 244 | { |
238 | __be32 c, all, old; | 245 | __be32 bit, all, old; |
239 | int i, ret = -EIO, retry = 5; | 246 | __be32 data[2]; |
247 | int channel, ret = -EIO, retry = 5; | ||
240 | 248 | ||
241 | old = all = allocate ? cpu_to_be32(~0) : 0; | 249 | old = all = allocate ? cpu_to_be32(~0) : 0; |
242 | 250 | ||
243 | for (i = 0; i < 32; i++) { | 251 | for (channel = 0; channel < 32; channel++) { |
244 | if (!(channels_mask & 1 << i)) | 252 | if (!(channels_mask & 1 << channel)) |
245 | continue; | 253 | continue; |
246 | 254 | ||
247 | ret = -EBUSY; | 255 | ret = -EBUSY; |
248 | 256 | ||
249 | c = cpu_to_be32(1 << (31 - i)); | 257 | bit = cpu_to_be32(1 << (31 - channel)); |
250 | if ((old & c) != (all & c)) | 258 | if ((old & bit) != (all & bit)) |
251 | continue; | 259 | continue; |
252 | 260 | ||
253 | data[0] = old; | 261 | data[0] = old; |
254 | data[1] = old ^ c; | 262 | data[1] = old ^ bit; |
255 | switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, | 263 | switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, |
256 | irm_id, generation, SCODE_100, | 264 | irm_id, generation, SCODE_100, |
257 | offset, data, 8)) { | 265 | offset, data, 8)) { |
258 | case RCODE_GENERATION: | 266 | case RCODE_GENERATION: |
259 | /* A generation change frees all channels. */ | 267 | /* A generation change frees all channels. */ |
260 | return allocate ? -EAGAIN : i; | 268 | return allocate ? -EAGAIN : channel; |
261 | 269 | ||
262 | case RCODE_COMPLETE: | 270 | case RCODE_COMPLETE: |
263 | if (data[0] == old) | 271 | if (data[0] == old) |
264 | return i; | 272 | return channel; |
265 | 273 | ||
266 | old = data[0]; | 274 | old = data[0]; |
267 | 275 | ||
268 | /* Is the IRM 1394a-2000 compliant? */ | 276 | /* Is the IRM 1394a-2000 compliant? */ |
269 | if ((data[0] & c) == (data[1] & c)) | 277 | if ((data[0] & bit) == (data[1] & bit)) |
270 | continue; | 278 | continue; |
271 | 279 | ||
272 | /* 1394-1995 IRM, fall through to retry. */ | 280 | /* 1394-1995 IRM, fall through to retry. */ |
273 | default: | 281 | default: |
274 | if (retry) { | 282 | if (retry) { |
275 | retry--; | 283 | retry--; |
276 | i--; | 284 | channel--; |
277 | } else { | 285 | } else { |
278 | ret = -EIO; | 286 | ret = -EIO; |
279 | } | 287 | } |
@@ -284,7 +292,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, | |||
284 | } | 292 | } |
285 | 293 | ||
286 | static void deallocate_channel(struct fw_card *card, int irm_id, | 294 | static void deallocate_channel(struct fw_card *card, int irm_id, |
287 | int generation, int channel, __be32 buffer[2]) | 295 | int generation, int channel) |
288 | { | 296 | { |
289 | u32 mask; | 297 | u32 mask; |
290 | u64 offset; | 298 | u64 offset; |
@@ -293,7 +301,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
293 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : | 301 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : |
294 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; | 302 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; |
295 | 303 | ||
296 | manage_channel(card, irm_id, generation, mask, offset, false, buffer); | 304 | manage_channel(card, irm_id, generation, mask, offset, false); |
297 | } | 305 | } |
298 | 306 | ||
299 | /** | 307 | /** |
@@ -322,7 +330,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
322 | */ | 330 | */ |
323 | void fw_iso_resource_manage(struct fw_card *card, int generation, | 331 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
324 | u64 channels_mask, int *channel, int *bandwidth, | 332 | u64 channels_mask, int *channel, int *bandwidth, |
325 | bool allocate, __be32 buffer[2]) | 333 | bool allocate) |
326 | { | 334 | { |
327 | u32 channels_hi = channels_mask; /* channels 31...0 */ | 335 | u32 channels_hi = channels_mask; /* channels 31...0 */ |
328 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ | 336 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ |
@@ -335,11 +343,11 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
335 | if (channels_hi) | 343 | if (channels_hi) |
336 | c = manage_channel(card, irm_id, generation, channels_hi, | 344 | c = manage_channel(card, irm_id, generation, channels_hi, |
337 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, | 345 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, |
338 | allocate, buffer); | 346 | allocate); |
339 | if (channels_lo && c < 0) { | 347 | if (channels_lo && c < 0) { |
340 | c = manage_channel(card, irm_id, generation, channels_lo, | 348 | c = manage_channel(card, irm_id, generation, channels_lo, |
341 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, | 349 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, |
342 | allocate, buffer); | 350 | allocate); |
343 | if (c >= 0) | 351 | if (c >= 0) |
344 | c += 32; | 352 | c += 32; |
345 | } | 353 | } |
@@ -351,14 +359,14 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
351 | if (*bandwidth == 0) | 359 | if (*bandwidth == 0) |
352 | return; | 360 | return; |
353 | 361 | ||
354 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, | 362 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); |
355 | allocate, buffer); | ||
356 | if (ret < 0) | 363 | if (ret < 0) |
357 | *bandwidth = 0; | 364 | *bandwidth = 0; |
358 | 365 | ||
359 | if (allocate && ret < 0) { | 366 | if (allocate && ret < 0) { |
360 | if (c >= 0) | 367 | if (c >= 0) |
361 | deallocate_channel(card, irm_id, generation, c, buffer); | 368 | deallocate_channel(card, irm_id, generation, c); |
362 | *channel = ret; | 369 | *channel = ret; |
363 | } | 370 | } |
364 | } | 371 | } |
372 | EXPORT_SYMBOL(fw_iso_resource_manage); | ||