diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-27 21:33:56 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-27 21:33:56 -0400 |
| commit | febb02bdfe5e2c6ceaa0a38d8b7afca3d98f415a (patch) | |
| tree | f2ea606a30cb11f0d914271b54551627dad26eff | |
| parent | 0b4d569de222452bcb55a4a536ade6cf4d8d1e30 (diff) | |
| parent | 32a0f488ce5e8a9a148491f15edc508ab5e8265b (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: (53 commits)
DVB: firedtv: FireDTV S2 problems with tuning solved
DVB: firedtv: fix printk format mismatch
ieee1394: constify device ID tables
ieee1394: raw1394: add sparse annotations to raw1394_compat_write
ieee1394: Storage class should be before const qualifier
ieee1394: sbp2: follow up on "ieee1394: inherit ud vendor_id from node vendor_id"
firewire: core: optimize propagation of BROADCAST_CHANNEL
firewire: core: simplify broadcast channel allocation
firewire: core: increase bus manager grace period
firewire: core: drop unused call parameters of close_transaction
firewire: cdev: add closure to async stream ioctl
firewire: cdev: simplify FW_CDEV_IOC_SEND_REQUEST return value
firewire: cdev: fix race of ioctl_send_request with bus reset
firewire: cdev: secure add_descriptor ioctl
firewire: cdev: amendment to "add ioctl to query maximum transmission speed"
firewire: broadcast channel support
firewire: implement asynchronous stream transmission
firewire: core: normalize a function argument name
firewire: normalize a variable name
firewire: core: remove condition which is always false
...
| -rw-r--r-- | drivers/firewire/fw-card.c | 149 | ||||
| -rw-r--r-- | drivers/firewire/fw-cdev.c | 1044 | ||||
| -rw-r--r-- | drivers/firewire/fw-device.c | 203 | ||||
| -rw-r--r-- | drivers/firewire/fw-device.h | 23 | ||||
| -rw-r--r-- | drivers/firewire/fw-iso.c | 227 | ||||
| -rw-r--r-- | drivers/firewire/fw-ohci.c | 260 | ||||
| -rw-r--r-- | drivers/firewire/fw-sbp2.c | 57 | ||||
| -rw-r--r-- | drivers/firewire/fw-topology.c | 29 | ||||
| -rw-r--r-- | drivers/firewire/fw-topology.h | 19 | ||||
| -rw-r--r-- | drivers/firewire/fw-transaction.c | 185 | ||||
| -rw-r--r-- | drivers/firewire/fw-transaction.h | 138 | ||||
| -rw-r--r-- | drivers/ieee1394/csr.c | 8 | ||||
| -rw-r--r-- | drivers/ieee1394/dv1394.c | 2 | ||||
| -rw-r--r-- | drivers/ieee1394/eth1394.c | 4 | ||||
| -rw-r--r-- | drivers/ieee1394/highlevel.c | 2 | ||||
| -rw-r--r-- | drivers/ieee1394/nodemgr.c | 4 | ||||
| -rw-r--r-- | drivers/ieee1394/nodemgr.h | 2 | ||||
| -rw-r--r-- | drivers/ieee1394/raw1394.c | 14 | ||||
| -rw-r--r-- | drivers/ieee1394/sbp2.c | 9 | ||||
| -rw-r--r-- | drivers/ieee1394/video1394.c | 2 | ||||
| -rw-r--r-- | drivers/media/dvb/firewire/firedtv-avc.c | 10 | ||||
| -rw-r--r-- | include/linux/firewire-cdev.h | 218 |
22 files changed, 1684 insertions, 925 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index a5dd7a665aa8..8b8c8c22f0fc 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c | |||
| @@ -63,8 +63,7 @@ static int descriptor_count; | |||
| 63 | #define BIB_CMC ((1) << 30) | 63 | #define BIB_CMC ((1) << 30) |
| 64 | #define BIB_IMC ((1) << 31) | 64 | #define BIB_IMC ((1) << 31) |
| 65 | 65 | ||
| 66 | static u32 * | 66 | static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) |
| 67 | generate_config_rom(struct fw_card *card, size_t *config_rom_length) | ||
| 68 | { | 67 | { |
| 69 | struct fw_descriptor *desc; | 68 | struct fw_descriptor *desc; |
| 70 | static u32 config_rom[256]; | 69 | static u32 config_rom[256]; |
| @@ -128,8 +127,7 @@ generate_config_rom(struct fw_card *card, size_t *config_rom_length) | |||
| 128 | return config_rom; | 127 | return config_rom; |
| 129 | } | 128 | } |
| 130 | 129 | ||
| 131 | static void | 130 | static void update_config_roms(void) |
| 132 | update_config_roms(void) | ||
| 133 | { | 131 | { |
| 134 | struct fw_card *card; | 132 | struct fw_card *card; |
| 135 | u32 *config_rom; | 133 | u32 *config_rom; |
| @@ -141,8 +139,7 @@ update_config_roms(void) | |||
| 141 | } | 139 | } |
| 142 | } | 140 | } |
| 143 | 141 | ||
| 144 | int | 142 | int fw_core_add_descriptor(struct fw_descriptor *desc) |
| 145 | fw_core_add_descriptor(struct fw_descriptor *desc) | ||
| 146 | { | 143 | { |
| 147 | size_t i; | 144 | size_t i; |
| 148 | 145 | ||
| @@ -171,8 +168,7 @@ fw_core_add_descriptor(struct fw_descriptor *desc) | |||
| 171 | return 0; | 168 | return 0; |
| 172 | } | 169 | } |
| 173 | 170 | ||
| 174 | void | 171 | void fw_core_remove_descriptor(struct fw_descriptor *desc) |
| 175 | fw_core_remove_descriptor(struct fw_descriptor *desc) | ||
| 176 | { | 172 | { |
| 177 | mutex_lock(&card_mutex); | 173 | mutex_lock(&card_mutex); |
| 178 | 174 | ||
| @@ -185,12 +181,30 @@ fw_core_remove_descriptor(struct fw_descriptor *desc) | |||
| 185 | mutex_unlock(&card_mutex); | 181 | mutex_unlock(&card_mutex); |
| 186 | } | 182 | } |
| 187 | 183 | ||
| 184 | static int set_broadcast_channel(struct device *dev, void *data) | ||
| 185 | { | ||
| 186 | fw_device_set_broadcast_channel(fw_device(dev), (long)data); | ||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 190 | static void allocate_broadcast_channel(struct fw_card *card, int generation) | ||
| 191 | { | ||
| 192 | int channel, bandwidth = 0; | ||
| 193 | |||
| 194 | fw_iso_resource_manage(card, generation, 1ULL << 31, | ||
| 195 | &channel, &bandwidth, true); | ||
| 196 | if (channel == 31) { | ||
| 197 | card->broadcast_channel_allocated = true; | ||
| 198 | device_for_each_child(card->device, (void *)(long)generation, | ||
| 199 | set_broadcast_channel); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 188 | static const char gap_count_table[] = { | 203 | static const char gap_count_table[] = { |
| 189 | 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 | 204 | 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 |
| 190 | }; | 205 | }; |
| 191 | 206 | ||
| 192 | void | 207 | void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) |
| 193 | fw_schedule_bm_work(struct fw_card *card, unsigned long delay) | ||
| 194 | { | 208 | { |
| 195 | int scheduled; | 209 | int scheduled; |
| 196 | 210 | ||
| @@ -200,37 +214,38 @@ fw_schedule_bm_work(struct fw_card *card, unsigned long delay) | |||
| 200 | fw_card_put(card); | 214 | fw_card_put(card); |
| 201 | } | 215 | } |
| 202 | 216 | ||
| 203 | static void | 217 | static void fw_card_bm_work(struct work_struct *work) |
| 204 | fw_card_bm_work(struct work_struct *work) | ||
| 205 | { | 218 | { |
| 206 | struct fw_card *card = container_of(work, struct fw_card, work.work); | 219 | struct fw_card *card = container_of(work, struct fw_card, work.work); |
| 207 | struct fw_device *root_device; | 220 | struct fw_device *root_device; |
| 208 | struct fw_node *root_node, *local_node; | 221 | struct fw_node *root_node; |
| 209 | unsigned long flags; | 222 | unsigned long flags; |
| 210 | int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode; | 223 | int root_id, new_root_id, irm_id, local_id; |
| 224 | int gap_count, generation, grace, rcode; | ||
| 211 | bool do_reset = false; | 225 | bool do_reset = false; |
| 212 | bool root_device_is_running; | 226 | bool root_device_is_running; |
| 213 | bool root_device_is_cmc; | 227 | bool root_device_is_cmc; |
| 214 | __be32 lock_data[2]; | 228 | __be32 lock_data[2]; |
| 215 | 229 | ||
| 216 | spin_lock_irqsave(&card->lock, flags); | 230 | spin_lock_irqsave(&card->lock, flags); |
| 217 | local_node = card->local_node; | ||
| 218 | root_node = card->root_node; | ||
| 219 | 231 | ||
| 220 | if (local_node == NULL) { | 232 | if (card->local_node == NULL) { |
| 221 | spin_unlock_irqrestore(&card->lock, flags); | 233 | spin_unlock_irqrestore(&card->lock, flags); |
| 222 | goto out_put_card; | 234 | goto out_put_card; |
| 223 | } | 235 | } |
| 224 | fw_node_get(local_node); | ||
| 225 | fw_node_get(root_node); | ||
| 226 | 236 | ||
| 227 | generation = card->generation; | 237 | generation = card->generation; |
| 238 | root_node = card->root_node; | ||
| 239 | fw_node_get(root_node); | ||
| 228 | root_device = root_node->data; | 240 | root_device = root_node->data; |
| 229 | root_device_is_running = root_device && | 241 | root_device_is_running = root_device && |
| 230 | atomic_read(&root_device->state) == FW_DEVICE_RUNNING; | 242 | atomic_read(&root_device->state) == FW_DEVICE_RUNNING; |
| 231 | root_device_is_cmc = root_device && root_device->cmc; | 243 | root_device_is_cmc = root_device && root_device->cmc; |
| 232 | root_id = root_node->node_id; | 244 | root_id = root_node->node_id; |
| 233 | grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); | 245 | irm_id = card->irm_node->node_id; |
| 246 | local_id = card->local_node->node_id; | ||
| 247 | |||
| 248 | grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); | ||
| 234 | 249 | ||
| 235 | if (is_next_generation(generation, card->bm_generation) || | 250 | if (is_next_generation(generation, card->bm_generation) || |
| 236 | (card->bm_generation != generation && grace)) { | 251 | (card->bm_generation != generation && grace)) { |
| @@ -246,16 +261,15 @@ fw_card_bm_work(struct work_struct *work) | |||
| 246 | * next generation. | 261 | * next generation. |
| 247 | */ | 262 | */ |
| 248 | 263 | ||
| 249 | irm_id = card->irm_node->node_id; | ||
| 250 | if (!card->irm_node->link_on) { | 264 | if (!card->irm_node->link_on) { |
| 251 | new_root_id = local_node->node_id; | 265 | new_root_id = local_id; |
| 252 | fw_notify("IRM has link off, making local node (%02x) root.\n", | 266 | fw_notify("IRM has link off, making local node (%02x) root.\n", |
| 253 | new_root_id); | 267 | new_root_id); |
| 254 | goto pick_me; | 268 | goto pick_me; |
| 255 | } | 269 | } |
| 256 | 270 | ||
| 257 | lock_data[0] = cpu_to_be32(0x3f); | 271 | lock_data[0] = cpu_to_be32(0x3f); |
| 258 | lock_data[1] = cpu_to_be32(local_node->node_id); | 272 | lock_data[1] = cpu_to_be32(local_id); |
| 259 | 273 | ||
| 260 | spin_unlock_irqrestore(&card->lock, flags); | 274 | spin_unlock_irqrestore(&card->lock, flags); |
| 261 | 275 | ||
| @@ -269,9 +283,14 @@ fw_card_bm_work(struct work_struct *work) | |||
| 269 | goto out; | 283 | goto out; |
| 270 | 284 | ||
| 271 | if (rcode == RCODE_COMPLETE && | 285 | if (rcode == RCODE_COMPLETE && |
| 272 | lock_data[0] != cpu_to_be32(0x3f)) | 286 | lock_data[0] != cpu_to_be32(0x3f)) { |
| 273 | /* Somebody else is BM, let them do the work. */ | 287 | |
| 288 | /* Somebody else is BM. Only act as IRM. */ | ||
| 289 | if (local_id == irm_id) | ||
| 290 | allocate_broadcast_channel(card, generation); | ||
| 291 | |||
| 274 | goto out; | 292 | goto out; |
| 293 | } | ||
| 275 | 294 | ||
| 276 | spin_lock_irqsave(&card->lock, flags); | 295 | spin_lock_irqsave(&card->lock, flags); |
| 277 | 296 | ||
| @@ -282,19 +301,18 @@ fw_card_bm_work(struct work_struct *work) | |||
| 282 | * do a bus reset and pick the local node as | 301 | * do a bus reset and pick the local node as |
| 283 | * root, and thus, IRM. | 302 | * root, and thus, IRM. |
| 284 | */ | 303 | */ |
| 285 | new_root_id = local_node->node_id; | 304 | new_root_id = local_id; |
| 286 | fw_notify("BM lock failed, making local node (%02x) root.\n", | 305 | fw_notify("BM lock failed, making local node (%02x) root.\n", |
| 287 | new_root_id); | 306 | new_root_id); |
| 288 | goto pick_me; | 307 | goto pick_me; |
| 289 | } | 308 | } |
| 290 | } else if (card->bm_generation != generation) { | 309 | } else if (card->bm_generation != generation) { |
| 291 | /* | 310 | /* |
| 292 | * OK, we weren't BM in the last generation, and it's | 311 | * We weren't BM in the last generation, and the last |
| 293 | * less than 100ms since last bus reset. Reschedule | 312 | * bus reset is less than 125ms ago. Reschedule this job. |
| 294 | * this task 100ms from now. | ||
| 295 | */ | 313 | */ |
| 296 | spin_unlock_irqrestore(&card->lock, flags); | 314 | spin_unlock_irqrestore(&card->lock, flags); |
| 297 | fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 10)); | 315 | fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8)); |
| 298 | goto out; | 316 | goto out; |
| 299 | } | 317 | } |
| 300 | 318 | ||
| @@ -310,7 +328,7 @@ fw_card_bm_work(struct work_struct *work) | |||
| 310 | * Either link_on is false, or we failed to read the | 328 | * Either link_on is false, or we failed to read the |
| 311 | * config rom. In either case, pick another root. | 329 | * config rom. In either case, pick another root. |
| 312 | */ | 330 | */ |
| 313 | new_root_id = local_node->node_id; | 331 | new_root_id = local_id; |
| 314 | } else if (!root_device_is_running) { | 332 | } else if (!root_device_is_running) { |
| 315 | /* | 333 | /* |
| 316 | * If we haven't probed this device yet, bail out now | 334 | * If we haven't probed this device yet, bail out now |
| @@ -332,7 +350,7 @@ fw_card_bm_work(struct work_struct *work) | |||
| 332 | * successfully read the config rom, but it's not | 350 | * successfully read the config rom, but it's not |
| 333 | * cycle master capable. | 351 | * cycle master capable. |
| 334 | */ | 352 | */ |
| 335 | new_root_id = local_node->node_id; | 353 | new_root_id = local_id; |
| 336 | } | 354 | } |
| 337 | 355 | ||
| 338 | pick_me: | 356 | pick_me: |
| @@ -363,25 +381,28 @@ fw_card_bm_work(struct work_struct *work) | |||
| 363 | card->index, new_root_id, gap_count); | 381 | card->index, new_root_id, gap_count); |
| 364 | fw_send_phy_config(card, new_root_id, generation, gap_count); | 382 | fw_send_phy_config(card, new_root_id, generation, gap_count); |
| 365 | fw_core_initiate_bus_reset(card, 1); | 383 | fw_core_initiate_bus_reset(card, 1); |
| 384 | /* Will allocate broadcast channel after the reset. */ | ||
| 385 | } else { | ||
| 386 | if (local_id == irm_id) | ||
| 387 | allocate_broadcast_channel(card, generation); | ||
| 366 | } | 388 | } |
| 389 | |||
| 367 | out: | 390 | out: |
| 368 | fw_node_put(root_node); | 391 | fw_node_put(root_node); |
| 369 | fw_node_put(local_node); | ||
| 370 | out_put_card: | 392 | out_put_card: |
| 371 | fw_card_put(card); | 393 | fw_card_put(card); |
| 372 | } | 394 | } |
| 373 | 395 | ||
| 374 | static void | 396 | static void flush_timer_callback(unsigned long data) |
| 375 | flush_timer_callback(unsigned long data) | ||
| 376 | { | 397 | { |
| 377 | struct fw_card *card = (struct fw_card *)data; | 398 | struct fw_card *card = (struct fw_card *)data; |
| 378 | 399 | ||
| 379 | fw_flush_transactions(card); | 400 | fw_flush_transactions(card); |
| 380 | } | 401 | } |
| 381 | 402 | ||
| 382 | void | 403 | void fw_card_initialize(struct fw_card *card, |
| 383 | fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, | 404 | const struct fw_card_driver *driver, |
| 384 | struct device *device) | 405 | struct device *device) |
| 385 | { | 406 | { |
| 386 | static atomic_t index = ATOMIC_INIT(-1); | 407 | static atomic_t index = ATOMIC_INIT(-1); |
| 387 | 408 | ||
| @@ -406,13 +427,12 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, | |||
| 406 | } | 427 | } |
| 407 | EXPORT_SYMBOL(fw_card_initialize); | 428 | EXPORT_SYMBOL(fw_card_initialize); |
| 408 | 429 | ||
| 409 | int | 430 | int fw_card_add(struct fw_card *card, |
| 410 | fw_card_add(struct fw_card *card, | 431 | u32 max_receive, u32 link_speed, u64 guid) |
| 411 | u32 max_receive, u32 link_speed, u64 guid) | ||
| 412 | { | 432 | { |
| 413 | u32 *config_rom; | 433 | u32 *config_rom; |
| 414 | size_t length; | 434 | size_t length; |
| 415 | int err; | 435 | int ret; |
| 416 | 436 | ||
| 417 | card->max_receive = max_receive; | 437 | card->max_receive = max_receive; |
| 418 | card->link_speed = link_speed; | 438 | card->link_speed = link_speed; |
| @@ -423,13 +443,14 @@ fw_card_add(struct fw_card *card, | |||
| 423 | list_add_tail(&card->link, &card_list); | 443 | list_add_tail(&card->link, &card_list); |
| 424 | mutex_unlock(&card_mutex); | 444 | mutex_unlock(&card_mutex); |
| 425 | 445 | ||
| 426 | err = card->driver->enable(card, config_rom, length); | 446 | ret = card->driver->enable(card, config_rom, length); |
| 427 | if (err < 0) { | 447 | if (ret < 0) { |
| 428 | mutex_lock(&card_mutex); | 448 | mutex_lock(&card_mutex); |
| 429 | list_del(&card->link); | 449 | list_del(&card->link); |
| 430 | mutex_unlock(&card_mutex); | 450 | mutex_unlock(&card_mutex); |
| 431 | } | 451 | } |
| 432 | return err; | 452 | |
| 453 | return ret; | ||
| 433 | } | 454 | } |
| 434 | EXPORT_SYMBOL(fw_card_add); | 455 | EXPORT_SYMBOL(fw_card_add); |
| 435 | 456 | ||
| @@ -442,23 +463,20 @@ EXPORT_SYMBOL(fw_card_add); | |||
| 442 | * dummy driver just fails all IO. | 463 | * dummy driver just fails all IO. |
| 443 | */ | 464 | */ |
| 444 | 465 | ||
| 445 | static int | 466 | static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) |
| 446 | dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) | ||
| 447 | { | 467 | { |
| 448 | BUG(); | 468 | BUG(); |
| 449 | return -1; | 469 | return -1; |
| 450 | } | 470 | } |
| 451 | 471 | ||
| 452 | static int | 472 | static int dummy_update_phy_reg(struct fw_card *card, int address, |
| 453 | dummy_update_phy_reg(struct fw_card *card, int address, | 473 | int clear_bits, int set_bits) |
| 454 | int clear_bits, int set_bits) | ||
| 455 | { | 474 | { |
| 456 | return -ENODEV; | 475 | return -ENODEV; |
| 457 | } | 476 | } |
| 458 | 477 | ||
| 459 | static int | 478 | static int dummy_set_config_rom(struct fw_card *card, |
| 460 | dummy_set_config_rom(struct fw_card *card, | 479 | u32 *config_rom, size_t length) |
| 461 | u32 *config_rom, size_t length) | ||
| 462 | { | 480 | { |
| 463 | /* | 481 | /* |
| 464 | * We take the card out of card_list before setting the dummy | 482 | * We take the card out of card_list before setting the dummy |
| @@ -468,27 +486,23 @@ dummy_set_config_rom(struct fw_card *card, | |||
| 468 | return -1; | 486 | return -1; |
| 469 | } | 487 | } |
| 470 | 488 | ||
| 471 | static void | 489 | static void dummy_send_request(struct fw_card *card, struct fw_packet *packet) |
| 472 | dummy_send_request(struct fw_card *card, struct fw_packet *packet) | ||
| 473 | { | 490 | { |
| 474 | packet->callback(packet, card, -ENODEV); | 491 | packet->callback(packet, card, -ENODEV); |
| 475 | } | 492 | } |
| 476 | 493 | ||
| 477 | static void | 494 | static void dummy_send_response(struct fw_card *card, struct fw_packet *packet) |
| 478 | dummy_send_response(struct fw_card *card, struct fw_packet *packet) | ||
| 479 | { | 495 | { |
| 480 | packet->callback(packet, card, -ENODEV); | 496 | packet->callback(packet, card, -ENODEV); |
| 481 | } | 497 | } |
| 482 | 498 | ||
| 483 | static int | 499 | static int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) |
| 484 | dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) | ||
| 485 | { | 500 | { |
| 486 | return -ENOENT; | 501 | return -ENOENT; |
| 487 | } | 502 | } |
| 488 | 503 | ||
| 489 | static int | 504 | static int dummy_enable_phys_dma(struct fw_card *card, |
| 490 | dummy_enable_phys_dma(struct fw_card *card, | 505 | int node_id, int generation) |
| 491 | int node_id, int generation) | ||
| 492 | { | 506 | { |
| 493 | return -ENODEV; | 507 | return -ENODEV; |
| 494 | } | 508 | } |
| @@ -503,16 +517,14 @@ static struct fw_card_driver dummy_driver = { | |||
| 503 | .enable_phys_dma = dummy_enable_phys_dma, | 517 | .enable_phys_dma = dummy_enable_phys_dma, |
| 504 | }; | 518 | }; |
| 505 | 519 | ||
| 506 | void | 520 | void fw_card_release(struct kref *kref) |
| 507 | fw_card_release(struct kref *kref) | ||
| 508 | { | 521 | { |
| 509 | struct fw_card *card = container_of(kref, struct fw_card, kref); | 522 | struct fw_card *card = container_of(kref, struct fw_card, kref); |
| 510 | 523 | ||
| 511 | complete(&card->done); | 524 | complete(&card->done); |
| 512 | } | 525 | } |
| 513 | 526 | ||
| 514 | void | 527 | void fw_core_remove_card(struct fw_card *card) |
| 515 | fw_core_remove_card(struct fw_card *card) | ||
| 516 | { | 528 | { |
| 517 | card->driver->update_phy_reg(card, 4, | 529 | card->driver->update_phy_reg(card, 4, |
| 518 | PHY_LINK_ACTIVE | PHY_CONTENDER, 0); | 530 | PHY_LINK_ACTIVE | PHY_CONTENDER, 0); |
| @@ -536,8 +548,7 @@ fw_core_remove_card(struct fw_card *card) | |||
| 536 | } | 548 | } |
| 537 | EXPORT_SYMBOL(fw_core_remove_card); | 549 | EXPORT_SYMBOL(fw_core_remove_card); |
| 538 | 550 | ||
| 539 | int | 551 | int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) |
| 540 | fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) | ||
| 541 | { | 552 | { |
| 542 | int reg = short_reset ? 5 : 1; | 553 | int reg = short_reset ? 5 : 1; |
| 543 | int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; | 554 | int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; |
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index ed03234cbea8..7eb6594cc3e5 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c | |||
| @@ -18,87 +18,162 @@ | |||
| 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/module.h> | 21 | #include <linux/compat.h> |
| 22 | #include <linux/kernel.h> | 22 | #include <linux/delay.h> |
| 23 | #include <linux/wait.h> | ||
| 24 | #include <linux/errno.h> | ||
| 25 | #include <linux/device.h> | 23 | #include <linux/device.h> |
| 26 | #include <linux/vmalloc.h> | 24 | #include <linux/errno.h> |
| 25 | #include <linux/firewire-cdev.h> | ||
| 26 | #include <linux/idr.h> | ||
| 27 | #include <linux/jiffies.h> | ||
| 28 | #include <linux/kernel.h> | ||
| 29 | #include <linux/kref.h> | ||
| 30 | #include <linux/mm.h> | ||
| 31 | #include <linux/module.h> | ||
| 32 | #include <linux/mutex.h> | ||
| 27 | #include <linux/poll.h> | 33 | #include <linux/poll.h> |
| 28 | #include <linux/preempt.h> | 34 | #include <linux/preempt.h> |
| 35 | #include <linux/spinlock.h> | ||
| 29 | #include <linux/time.h> | 36 | #include <linux/time.h> |
| 30 | #include <linux/delay.h> | 37 | #include <linux/vmalloc.h> |
| 31 | #include <linux/mm.h> | 38 | #include <linux/wait.h> |
| 32 | #include <linux/idr.h> | 39 | #include <linux/workqueue.h> |
| 33 | #include <linux/compat.h> | 40 | |
| 34 | #include <linux/firewire-cdev.h> | ||
| 35 | #include <asm/system.h> | 41 | #include <asm/system.h> |
| 36 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
| 37 | #include "fw-transaction.h" | 43 | |
| 38 | #include "fw-topology.h" | ||
| 39 | #include "fw-device.h" | 44 | #include "fw-device.h" |
| 45 | #include "fw-topology.h" | ||
| 46 | #include "fw-transaction.h" | ||
| 47 | |||
| 48 | struct client { | ||
| 49 | u32 version; | ||
| 50 | struct fw_device *device; | ||
| 51 | |||
| 52 | spinlock_t lock; | ||
| 53 | bool in_shutdown; | ||
| 54 | struct idr resource_idr; | ||
| 55 | struct list_head event_list; | ||
| 56 | wait_queue_head_t wait; | ||
| 57 | u64 bus_reset_closure; | ||
| 58 | |||
| 59 | struct fw_iso_context *iso_context; | ||
| 60 | u64 iso_closure; | ||
| 61 | struct fw_iso_buffer buffer; | ||
| 62 | unsigned long vm_start; | ||
| 40 | 63 | ||
| 41 | struct client; | ||
| 42 | struct client_resource { | ||
| 43 | struct list_head link; | 64 | struct list_head link; |
| 44 | void (*release)(struct client *client, struct client_resource *r); | 65 | struct kref kref; |
| 45 | u32 handle; | ||
| 46 | }; | 66 | }; |
| 47 | 67 | ||
| 68 | static inline void client_get(struct client *client) | ||
| 69 | { | ||
| 70 | kref_get(&client->kref); | ||
| 71 | } | ||
| 72 | |||
| 73 | static void client_release(struct kref *kref) | ||
| 74 | { | ||
| 75 | struct client *client = container_of(kref, struct client, kref); | ||
| 76 | |||
| 77 | fw_device_put(client->device); | ||
| 78 | kfree(client); | ||
| 79 | } | ||
| 80 | |||
| 81 | static void client_put(struct client *client) | ||
| 82 | { | ||
| 83 | kref_put(&client->kref, client_release); | ||
| 84 | } | ||
| 85 | |||
| 86 | struct client_resource; | ||
| 87 | typedef void (*client_resource_release_fn_t)(struct client *, | ||
| 88 | struct client_resource *); | ||
| 89 | struct client_resource { | ||
| 90 | client_resource_release_fn_t release; | ||
| 91 | int handle; | ||
| 92 | }; | ||
| 93 | |||
| 94 | struct address_handler_resource { | ||
| 95 | struct client_resource resource; | ||
| 96 | struct fw_address_handler handler; | ||
| 97 | __u64 closure; | ||
| 98 | struct client *client; | ||
| 99 | }; | ||
| 100 | |||
| 101 | struct outbound_transaction_resource { | ||
| 102 | struct client_resource resource; | ||
| 103 | struct fw_transaction transaction; | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct inbound_transaction_resource { | ||
| 107 | struct client_resource resource; | ||
| 108 | struct fw_request *request; | ||
| 109 | void *data; | ||
| 110 | size_t length; | ||
| 111 | }; | ||
| 112 | |||
| 113 | struct descriptor_resource { | ||
| 114 | struct client_resource resource; | ||
| 115 | struct fw_descriptor descriptor; | ||
| 116 | u32 data[0]; | ||
| 117 | }; | ||
| 118 | |||
| 119 | struct iso_resource { | ||
| 120 | struct client_resource resource; | ||
| 121 | struct client *client; | ||
| 122 | /* Schedule work and access todo only with client->lock held. */ | ||
| 123 | struct delayed_work work; | ||
| 124 | enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC, | ||
| 125 | ISO_RES_ALLOC_ONCE, ISO_RES_DEALLOC_ONCE,} todo; | ||
| 126 | int generation; | ||
| 127 | u64 channels; | ||
| 128 | s32 bandwidth; | ||
| 129 | struct iso_resource_event *e_alloc, *e_dealloc; | ||
| 130 | }; | ||
| 131 | |||
| 132 | static void schedule_iso_resource(struct iso_resource *); | ||
| 133 | static void release_iso_resource(struct client *, struct client_resource *); | ||
| 134 | |||
| 48 | /* | 135 | /* |
| 49 | * dequeue_event() just kfree()'s the event, so the event has to be | 136 | * dequeue_event() just kfree()'s the event, so the event has to be |
| 50 | * the first field in the struct. | 137 | * the first field in a struct XYZ_event. |
| 51 | */ | 138 | */ |
| 52 | |||
| 53 | struct event { | 139 | struct event { |
| 54 | struct { void *data; size_t size; } v[2]; | 140 | struct { void *data; size_t size; } v[2]; |
| 55 | struct list_head link; | 141 | struct list_head link; |
| 56 | }; | 142 | }; |
| 57 | 143 | ||
| 58 | struct bus_reset { | 144 | struct bus_reset_event { |
| 59 | struct event event; | 145 | struct event event; |
| 60 | struct fw_cdev_event_bus_reset reset; | 146 | struct fw_cdev_event_bus_reset reset; |
| 61 | }; | 147 | }; |
| 62 | 148 | ||
| 63 | struct response { | 149 | struct outbound_transaction_event { |
| 64 | struct event event; | 150 | struct event event; |
| 65 | struct fw_transaction transaction; | ||
| 66 | struct client *client; | 151 | struct client *client; |
| 67 | struct client_resource resource; | 152 | struct outbound_transaction_resource r; |
| 68 | struct fw_cdev_event_response response; | 153 | struct fw_cdev_event_response response; |
| 69 | }; | 154 | }; |
| 70 | 155 | ||
| 71 | struct iso_interrupt { | 156 | struct inbound_transaction_event { |
| 72 | struct event event; | 157 | struct event event; |
| 73 | struct fw_cdev_event_iso_interrupt interrupt; | 158 | struct fw_cdev_event_request request; |
| 74 | }; | 159 | }; |
| 75 | 160 | ||
| 76 | struct client { | 161 | struct iso_interrupt_event { |
| 77 | u32 version; | 162 | struct event event; |
| 78 | struct fw_device *device; | 163 | struct fw_cdev_event_iso_interrupt interrupt; |
| 79 | spinlock_t lock; | 164 | }; |
| 80 | u32 resource_handle; | ||
| 81 | struct list_head resource_list; | ||
| 82 | struct list_head event_list; | ||
| 83 | wait_queue_head_t wait; | ||
| 84 | u64 bus_reset_closure; | ||
| 85 | |||
| 86 | struct fw_iso_context *iso_context; | ||
| 87 | u64 iso_closure; | ||
| 88 | struct fw_iso_buffer buffer; | ||
| 89 | unsigned long vm_start; | ||
| 90 | 165 | ||
| 91 | struct list_head link; | 166 | struct iso_resource_event { |
| 167 | struct event event; | ||
| 168 | struct fw_cdev_event_iso_resource resource; | ||
| 92 | }; | 169 | }; |
| 93 | 170 | ||
| 94 | static inline void __user * | 171 | static inline void __user *u64_to_uptr(__u64 value) |
| 95 | u64_to_uptr(__u64 value) | ||
| 96 | { | 172 | { |
| 97 | return (void __user *)(unsigned long)value; | 173 | return (void __user *)(unsigned long)value; |
| 98 | } | 174 | } |
| 99 | 175 | ||
| 100 | static inline __u64 | 176 | static inline __u64 uptr_to_u64(void __user *ptr) |
| 101 | uptr_to_u64(void __user *ptr) | ||
| 102 | { | 177 | { |
| 103 | return (__u64)(unsigned long)ptr; | 178 | return (__u64)(unsigned long)ptr; |
| 104 | } | 179 | } |
| @@ -107,7 +182,6 @@ static int fw_device_op_open(struct inode *inode, struct file *file) | |||
| 107 | { | 182 | { |
| 108 | struct fw_device *device; | 183 | struct fw_device *device; |
| 109 | struct client *client; | 184 | struct client *client; |
| 110 | unsigned long flags; | ||
| 111 | 185 | ||
| 112 | device = fw_device_get_by_devt(inode->i_rdev); | 186 | device = fw_device_get_by_devt(inode->i_rdev); |
| 113 | if (device == NULL) | 187 | if (device == NULL) |
| @@ -125,16 +199,17 @@ static int fw_device_op_open(struct inode *inode, struct file *file) | |||
| 125 | } | 199 | } |
| 126 | 200 | ||
| 127 | client->device = device; | 201 | client->device = device; |
| 128 | INIT_LIST_HEAD(&client->event_list); | ||
| 129 | INIT_LIST_HEAD(&client->resource_list); | ||
| 130 | spin_lock_init(&client->lock); | 202 | spin_lock_init(&client->lock); |
| 203 | idr_init(&client->resource_idr); | ||
| 204 | INIT_LIST_HEAD(&client->event_list); | ||
| 131 | init_waitqueue_head(&client->wait); | 205 | init_waitqueue_head(&client->wait); |
| 206 | kref_init(&client->kref); | ||
| 132 | 207 | ||
| 133 | file->private_data = client; | 208 | file->private_data = client; |
| 134 | 209 | ||
| 135 | spin_lock_irqsave(&device->card->lock, flags); | 210 | mutex_lock(&device->client_list_mutex); |
| 136 | list_add_tail(&client->link, &device->client_list); | 211 | list_add_tail(&client->link, &device->client_list); |
| 137 | spin_unlock_irqrestore(&device->card->lock, flags); | 212 | mutex_unlock(&device->client_list_mutex); |
| 138 | 213 | ||
| 139 | return 0; | 214 | return 0; |
| 140 | } | 215 | } |
| @@ -150,68 +225,69 @@ static void queue_event(struct client *client, struct event *event, | |||
| 150 | event->v[1].size = size1; | 225 | event->v[1].size = size1; |
| 151 | 226 | ||
| 152 | spin_lock_irqsave(&client->lock, flags); | 227 | spin_lock_irqsave(&client->lock, flags); |
| 153 | list_add_tail(&event->link, &client->event_list); | 228 | if (client->in_shutdown) |
| 229 | kfree(event); | ||
| 230 | else | ||
| 231 | list_add_tail(&event->link, &client->event_list); | ||
| 154 | spin_unlock_irqrestore(&client->lock, flags); | 232 | spin_unlock_irqrestore(&client->lock, flags); |
| 155 | 233 | ||
| 156 | wake_up_interruptible(&client->wait); | 234 | wake_up_interruptible(&client->wait); |
| 157 | } | 235 | } |
| 158 | 236 | ||
| 159 | static int | 237 | static int dequeue_event(struct client *client, |
| 160 | dequeue_event(struct client *client, char __user *buffer, size_t count) | 238 | char __user *buffer, size_t count) |
| 161 | { | 239 | { |
| 162 | unsigned long flags; | ||
| 163 | struct event *event; | 240 | struct event *event; |
| 164 | size_t size, total; | 241 | size_t size, total; |
| 165 | int i, retval; | 242 | int i, ret; |
| 166 | 243 | ||
| 167 | retval = wait_event_interruptible(client->wait, | 244 | ret = wait_event_interruptible(client->wait, |
| 168 | !list_empty(&client->event_list) || | 245 | !list_empty(&client->event_list) || |
| 169 | fw_device_is_shutdown(client->device)); | 246 | fw_device_is_shutdown(client->device)); |
| 170 | if (retval < 0) | 247 | if (ret < 0) |
| 171 | return retval; | 248 | return ret; |
| 172 | 249 | ||
| 173 | if (list_empty(&client->event_list) && | 250 | if (list_empty(&client->event_list) && |
| 174 | fw_device_is_shutdown(client->device)) | 251 | fw_device_is_shutdown(client->device)) |
| 175 | return -ENODEV; | 252 | return -ENODEV; |
| 176 | 253 | ||
| 177 | spin_lock_irqsave(&client->lock, flags); | 254 | spin_lock_irq(&client->lock); |
| 178 | event = container_of(client->event_list.next, struct event, link); | 255 | event = list_first_entry(&client->event_list, struct event, link); |
| 179 | list_del(&event->link); | 256 | list_del(&event->link); |
| 180 | spin_unlock_irqrestore(&client->lock, flags); | 257 | spin_unlock_irq(&client->lock); |
| 181 | 258 | ||
| 182 | total = 0; | 259 | total = 0; |
| 183 | for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) { | 260 | for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) { |
| 184 | size = min(event->v[i].size, count - total); | 261 | size = min(event->v[i].size, count - total); |
| 185 | if (copy_to_user(buffer + total, event->v[i].data, size)) { | 262 | if (copy_to_user(buffer + total, event->v[i].data, size)) { |
| 186 | retval = -EFAULT; | 263 | ret = -EFAULT; |
| 187 | goto out; | 264 | goto out; |
| 188 | } | 265 | } |
| 189 | total += size; | 266 | total += size; |
| 190 | } | 267 | } |
| 191 | retval = total; | 268 | ret = total; |
| 192 | 269 | ||
| 193 | out: | 270 | out: |
| 194 | kfree(event); | 271 | kfree(event); |
| 195 | 272 | ||
| 196 | return retval; | 273 | return ret; |
| 197 | } | 274 | } |
| 198 | 275 | ||
| 199 | static ssize_t | 276 | static ssize_t fw_device_op_read(struct file *file, char __user *buffer, |
| 200 | fw_device_op_read(struct file *file, | 277 | size_t count, loff_t *offset) |
| 201 | char __user *buffer, size_t count, loff_t *offset) | ||
| 202 | { | 278 | { |
| 203 | struct client *client = file->private_data; | 279 | struct client *client = file->private_data; |
| 204 | 280 | ||
| 205 | return dequeue_event(client, buffer, count); | 281 | return dequeue_event(client, buffer, count); |
| 206 | } | 282 | } |
| 207 | 283 | ||
| 208 | /* caller must hold card->lock so that node pointers can be dereferenced here */ | 284 | static void fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, |
| 209 | static void | 285 | struct client *client) |
| 210 | fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, | ||
| 211 | struct client *client) | ||
| 212 | { | 286 | { |
| 213 | struct fw_card *card = client->device->card; | 287 | struct fw_card *card = client->device->card; |
| 214 | 288 | ||
| 289 | spin_lock_irq(&card->lock); | ||
| 290 | |||
| 215 | event->closure = client->bus_reset_closure; | 291 | event->closure = client->bus_reset_closure; |
| 216 | event->type = FW_CDEV_EVENT_BUS_RESET; | 292 | event->type = FW_CDEV_EVENT_BUS_RESET; |
| 217 | event->generation = client->device->generation; | 293 | event->generation = client->device->generation; |
| @@ -220,39 +296,49 @@ fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, | |||
| 220 | event->bm_node_id = 0; /* FIXME: We don't track the BM. */ | 296 | event->bm_node_id = 0; /* FIXME: We don't track the BM. */ |
| 221 | event->irm_node_id = card->irm_node->node_id; | 297 | event->irm_node_id = card->irm_node->node_id; |
| 222 | event->root_node_id = card->root_node->node_id; | 298 | event->root_node_id = card->root_node->node_id; |
| 299 | |||
| 300 | spin_unlock_irq(&card->lock); | ||
| 223 | } | 301 | } |
| 224 | 302 | ||
| 225 | static void | 303 | static void for_each_client(struct fw_device *device, |
| 226 | for_each_client(struct fw_device *device, | 304 | void (*callback)(struct client *client)) |
| 227 | void (*callback)(struct client *client)) | ||
| 228 | { | 305 | { |
| 229 | struct fw_card *card = device->card; | ||
| 230 | struct client *c; | 306 | struct client *c; |
| 231 | unsigned long flags; | ||
| 232 | |||
| 233 | spin_lock_irqsave(&card->lock, flags); | ||
| 234 | 307 | ||
| 308 | mutex_lock(&device->client_list_mutex); | ||
| 235 | list_for_each_entry(c, &device->client_list, link) | 309 | list_for_each_entry(c, &device->client_list, link) |
| 236 | callback(c); | 310 | callback(c); |
| 311 | mutex_unlock(&device->client_list_mutex); | ||
| 312 | } | ||
| 313 | |||
| 314 | static int schedule_reallocations(int id, void *p, void *data) | ||
| 315 | { | ||
| 316 | struct client_resource *r = p; | ||
| 237 | 317 | ||
| 238 | spin_unlock_irqrestore(&card->lock, flags); | 318 | if (r->release == release_iso_resource) |
| 319 | schedule_iso_resource(container_of(r, | ||
| 320 | struct iso_resource, resource)); | ||
| 321 | return 0; | ||
| 239 | } | 322 | } |
| 240 | 323 | ||
| 241 | static void | 324 | static void queue_bus_reset_event(struct client *client) |
| 242 | queue_bus_reset_event(struct client *client) | ||
| 243 | { | 325 | { |
| 244 | struct bus_reset *bus_reset; | 326 | struct bus_reset_event *e; |
| 245 | 327 | ||
| 246 | bus_reset = kzalloc(sizeof(*bus_reset), GFP_ATOMIC); | 328 | e = kzalloc(sizeof(*e), GFP_KERNEL); |
| 247 | if (bus_reset == NULL) { | 329 | if (e == NULL) { |
| 248 | fw_notify("Out of memory when allocating bus reset event\n"); | 330 | fw_notify("Out of memory when allocating bus reset event\n"); |
| 249 | return; | 331 | return; |
| 250 | } | 332 | } |
| 251 | 333 | ||
| 252 | fill_bus_reset_event(&bus_reset->reset, client); | 334 | fill_bus_reset_event(&e->reset, client); |
| 335 | |||
| 336 | queue_event(client, &e->event, | ||
| 337 | &e->reset, sizeof(e->reset), NULL, 0); | ||
| 253 | 338 | ||
| 254 | queue_event(client, &bus_reset->event, | 339 | spin_lock_irq(&client->lock); |
| 255 | &bus_reset->reset, sizeof(bus_reset->reset), NULL, 0); | 340 | idr_for_each(&client->resource_idr, schedule_reallocations, client); |
| 341 | spin_unlock_irq(&client->lock); | ||
| 256 | } | 342 | } |
| 257 | 343 | ||
| 258 | void fw_device_cdev_update(struct fw_device *device) | 344 | void fw_device_cdev_update(struct fw_device *device) |
| @@ -274,11 +360,11 @@ static int ioctl_get_info(struct client *client, void *buffer) | |||
| 274 | { | 360 | { |
| 275 | struct fw_cdev_get_info *get_info = buffer; | 361 | struct fw_cdev_get_info *get_info = buffer; |
| 276 | struct fw_cdev_event_bus_reset bus_reset; | 362 | struct fw_cdev_event_bus_reset bus_reset; |
| 277 | struct fw_card *card = client->device->card; | ||
| 278 | unsigned long ret = 0; | 363 | unsigned long ret = 0; |
| 279 | 364 | ||
| 280 | client->version = get_info->version; | 365 | client->version = get_info->version; |
| 281 | get_info->version = FW_CDEV_VERSION; | 366 | get_info->version = FW_CDEV_VERSION; |
| 367 | get_info->card = client->device->card->index; | ||
| 282 | 368 | ||
| 283 | down_read(&fw_device_rwsem); | 369 | down_read(&fw_device_rwsem); |
| 284 | 370 | ||
| @@ -300,49 +386,61 @@ static int ioctl_get_info(struct client *client, void *buffer) | |||
| 300 | client->bus_reset_closure = get_info->bus_reset_closure; | 386 | client->bus_reset_closure = get_info->bus_reset_closure; |
| 301 | if (get_info->bus_reset != 0) { | 387 | if (get_info->bus_reset != 0) { |
| 302 | void __user *uptr = u64_to_uptr(get_info->bus_reset); | 388 | void __user *uptr = u64_to_uptr(get_info->bus_reset); |
| 303 | unsigned long flags; | ||
| 304 | 389 | ||
| 305 | spin_lock_irqsave(&card->lock, flags); | ||
| 306 | fill_bus_reset_event(&bus_reset, client); | 390 | fill_bus_reset_event(&bus_reset, client); |
| 307 | spin_unlock_irqrestore(&card->lock, flags); | ||
| 308 | |||
| 309 | if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset))) | 391 | if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset))) |
| 310 | return -EFAULT; | 392 | return -EFAULT; |
| 311 | } | 393 | } |
| 312 | 394 | ||
| 313 | get_info->card = card->index; | ||
| 314 | |||
| 315 | return 0; | 395 | return 0; |
| 316 | } | 396 | } |
| 317 | 397 | ||
| 318 | static void | 398 | static int add_client_resource(struct client *client, |
| 319 | add_client_resource(struct client *client, struct client_resource *resource) | 399 | struct client_resource *resource, gfp_t gfp_mask) |
| 320 | { | 400 | { |
| 321 | unsigned long flags; | 401 | unsigned long flags; |
| 402 | int ret; | ||
| 403 | |||
| 404 | retry: | ||
| 405 | if (idr_pre_get(&client->resource_idr, gfp_mask) == 0) | ||
| 406 | return -ENOMEM; | ||
| 322 | 407 | ||
| 323 | spin_lock_irqsave(&client->lock, flags); | 408 | spin_lock_irqsave(&client->lock, flags); |
| 324 | list_add_tail(&resource->link, &client->resource_list); | 409 | if (client->in_shutdown) |
| 325 | resource->handle = client->resource_handle++; | 410 | ret = -ECANCELED; |
| 411 | else | ||
| 412 | ret = idr_get_new(&client->resource_idr, resource, | ||
| 413 | &resource->handle); | ||
| 414 | if (ret >= 0) { | ||
| 415 | client_get(client); | ||
| 416 | if (resource->release == release_iso_resource) | ||
| 417 | schedule_iso_resource(container_of(resource, | ||
| 418 | struct iso_resource, resource)); | ||
| 419 | } | ||
| 326 | spin_unlock_irqrestore(&client->lock, flags); | 420 | spin_unlock_irqrestore(&client->lock, flags); |
| 421 | |||
| 422 | if (ret == -EAGAIN) | ||
| 423 | goto retry; | ||
| 424 | |||
| 425 | return ret < 0 ? ret : 0; | ||
| 327 | } | 426 | } |
| 328 | 427 | ||
| 329 | static int | 428 | static int release_client_resource(struct client *client, u32 handle, |
| 330 | release_client_resource(struct client *client, u32 handle, | 429 | client_resource_release_fn_t release, |
| 331 | struct client_resource **resource) | 430 | struct client_resource **resource) |
| 332 | { | 431 | { |
| 333 | struct client_resource *r; | 432 | struct client_resource *r; |
| 334 | unsigned long flags; | ||
| 335 | 433 | ||
| 336 | spin_lock_irqsave(&client->lock, flags); | 434 | spin_lock_irq(&client->lock); |
| 337 | list_for_each_entry(r, &client->resource_list, link) { | 435 | if (client->in_shutdown) |
| 338 | if (r->handle == handle) { | 436 | r = NULL; |
| 339 | list_del(&r->link); | 437 | else |
| 340 | break; | 438 | r = idr_find(&client->resource_idr, handle); |
| 341 | } | 439 | if (r && r->release == release) |
| 342 | } | 440 | idr_remove(&client->resource_idr, handle); |
| 343 | spin_unlock_irqrestore(&client->lock, flags); | 441 | spin_unlock_irq(&client->lock); |
| 344 | 442 | ||
| 345 | if (&r->link == &client->resource_list) | 443 | if (!(r && r->release == release)) |
| 346 | return -EINVAL; | 444 | return -EINVAL; |
| 347 | 445 | ||
| 348 | if (resource) | 446 | if (resource) |
| @@ -350,203 +448,239 @@ release_client_resource(struct client *client, u32 handle, | |||
| 350 | else | 448 | else |
| 351 | r->release(client, r); | 449 | r->release(client, r); |
| 352 | 450 | ||
| 451 | client_put(client); | ||
| 452 | |||
| 353 | return 0; | 453 | return 0; |
| 354 | } | 454 | } |
| 355 | 455 | ||
| 356 | static void | 456 | static void release_transaction(struct client *client, |
| 357 | release_transaction(struct client *client, struct client_resource *resource) | 457 | struct client_resource *resource) |
| 358 | { | 458 | { |
| 359 | struct response *response = | 459 | struct outbound_transaction_resource *r = container_of(resource, |
| 360 | container_of(resource, struct response, resource); | 460 | struct outbound_transaction_resource, resource); |
| 361 | 461 | ||
| 362 | fw_cancel_transaction(client->device->card, &response->transaction); | 462 | fw_cancel_transaction(client->device->card, &r->transaction); |
| 363 | } | 463 | } |
| 364 | 464 | ||
| 365 | static void | 465 | static void complete_transaction(struct fw_card *card, int rcode, |
| 366 | complete_transaction(struct fw_card *card, int rcode, | 466 | void *payload, size_t length, void *data) |
| 367 | void *payload, size_t length, void *data) | ||
| 368 | { | 467 | { |
| 369 | struct response *response = data; | 468 | struct outbound_transaction_event *e = data; |
| 370 | struct client *client = response->client; | 469 | struct fw_cdev_event_response *rsp = &e->response; |
| 470 | struct client *client = e->client; | ||
| 371 | unsigned long flags; | 471 | unsigned long flags; |
| 372 | struct fw_cdev_event_response *r = &response->response; | ||
| 373 | 472 | ||
| 374 | if (length < r->length) | 473 | if (length < rsp->length) |
| 375 | r->length = length; | 474 | rsp->length = length; |
| 376 | if (rcode == RCODE_COMPLETE) | 475 | if (rcode == RCODE_COMPLETE) |
| 377 | memcpy(r->data, payload, r->length); | 476 | memcpy(rsp->data, payload, rsp->length); |
| 378 | 477 | ||
| 379 | spin_lock_irqsave(&client->lock, flags); | 478 | spin_lock_irqsave(&client->lock, flags); |
| 380 | list_del(&response->resource.link); | 479 | /* |
| 480 | * 1. If called while in shutdown, the idr tree must be left untouched. | ||
| 481 | * The idr handle will be removed and the client reference will be | ||
| 482 | * dropped later. | ||
| 483 | * 2. If the call chain was release_client_resource -> | ||
| 484 | * release_transaction -> complete_transaction (instead of a normal | ||
| 485 | * conclusion of the transaction), i.e. if this resource was already | ||
| 486 | * unregistered from the idr, the client reference will be dropped | ||
| 487 | * by release_client_resource and we must not drop it here. | ||
| 488 | */ | ||
| 489 | if (!client->in_shutdown && | ||
| 490 | idr_find(&client->resource_idr, e->r.resource.handle)) { | ||
| 491 | idr_remove(&client->resource_idr, e->r.resource.handle); | ||
| 492 | /* Drop the idr's reference */ | ||
| 493 | client_put(client); | ||
| 494 | } | ||
| 381 | spin_unlock_irqrestore(&client->lock, flags); | 495 | spin_unlock_irqrestore(&client->lock, flags); |
| 382 | 496 | ||
| 383 | r->type = FW_CDEV_EVENT_RESPONSE; | 497 | rsp->type = FW_CDEV_EVENT_RESPONSE; |
| 384 | r->rcode = rcode; | 498 | rsp->rcode = rcode; |
| 385 | 499 | ||
| 386 | /* | 500 | /* |
| 387 | * In the case that sizeof(*r) doesn't align with the position of the | 501 | * In the case that sizeof(*rsp) doesn't align with the position of the |
| 388 | * data, and the read is short, preserve an extra copy of the data | 502 | * data, and the read is short, preserve an extra copy of the data |
| 389 | * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless | 503 | * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless |
| 390 | * for short reads and some apps depended on it, this is both safe | 504 | * for short reads and some apps depended on it, this is both safe |
| 391 | * and prudent for compatibility. | 505 | * and prudent for compatibility. |
| 392 | */ | 506 | */ |
| 393 | if (r->length <= sizeof(*r) - offsetof(typeof(*r), data)) | 507 | if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data)) |
| 394 | queue_event(client, &response->event, r, sizeof(*r), | 508 | queue_event(client, &e->event, rsp, sizeof(*rsp), |
| 395 | r->data, r->length); | 509 | rsp->data, rsp->length); |
| 396 | else | 510 | else |
| 397 | queue_event(client, &response->event, r, sizeof(*r) + r->length, | 511 | queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, |
| 398 | NULL, 0); | 512 | NULL, 0); |
| 513 | |||
| 514 | /* Drop the transaction callback's reference */ | ||
| 515 | client_put(client); | ||
| 399 | } | 516 | } |
| 400 | 517 | ||
| 401 | static int ioctl_send_request(struct client *client, void *buffer) | 518 | static int init_request(struct client *client, |
| 519 | struct fw_cdev_send_request *request, | ||
| 520 | int destination_id, int speed) | ||
| 402 | { | 521 | { |
| 403 | struct fw_device *device = client->device; | 522 | struct outbound_transaction_event *e; |
| 404 | struct fw_cdev_send_request *request = buffer; | 523 | int ret; |
| 405 | struct response *response; | ||
| 406 | 524 | ||
| 407 | /* What is the biggest size we'll accept, really? */ | 525 | if (request->tcode != TCODE_STREAM_DATA && |
| 408 | if (request->length > 4096) | 526 | (request->length > 4096 || request->length > 512 << speed)) |
| 409 | return -EINVAL; | 527 | return -EIO; |
| 410 | 528 | ||
| 411 | response = kmalloc(sizeof(*response) + request->length, GFP_KERNEL); | 529 | e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); |
| 412 | if (response == NULL) | 530 | if (e == NULL) |
| 413 | return -ENOMEM; | 531 | return -ENOMEM; |
| 414 | 532 | ||
| 415 | response->client = client; | 533 | e->client = client; |
| 416 | response->response.length = request->length; | 534 | e->response.length = request->length; |
| 417 | response->response.closure = request->closure; | 535 | e->response.closure = request->closure; |
| 418 | 536 | ||
| 419 | if (request->data && | 537 | if (request->data && |
| 420 | copy_from_user(response->response.data, | 538 | copy_from_user(e->response.data, |
| 421 | u64_to_uptr(request->data), request->length)) { | 539 | u64_to_uptr(request->data), request->length)) { |
| 422 | kfree(response); | 540 | ret = -EFAULT; |
| 423 | return -EFAULT; | 541 | goto failed; |
| 424 | } | 542 | } |
| 425 | 543 | ||
| 426 | response->resource.release = release_transaction; | 544 | e->r.resource.release = release_transaction; |
| 427 | add_client_resource(client, &response->resource); | 545 | ret = add_client_resource(client, &e->r.resource, GFP_KERNEL); |
| 546 | if (ret < 0) | ||
| 547 | goto failed; | ||
| 428 | 548 | ||
| 429 | fw_send_request(device->card, &response->transaction, | 549 | /* Get a reference for the transaction callback */ |
| 430 | request->tcode & 0x1f, | 550 | client_get(client); |
| 431 | device->node->node_id, | ||
| 432 | request->generation, | ||
| 433 | device->max_speed, | ||
| 434 | request->offset, | ||
| 435 | response->response.data, request->length, | ||
| 436 | complete_transaction, response); | ||
| 437 | 551 | ||
| 438 | if (request->data) | 552 | fw_send_request(client->device->card, &e->r.transaction, |
| 439 | return sizeof(request) + request->length; | 553 | request->tcode, destination_id, request->generation, |
| 440 | else | 554 | speed, request->offset, e->response.data, |
| 441 | return sizeof(request); | 555 | request->length, complete_transaction, e); |
| 556 | return 0; | ||
| 557 | |||
| 558 | failed: | ||
| 559 | kfree(e); | ||
| 560 | |||
| 561 | return ret; | ||
| 442 | } | 562 | } |
| 443 | 563 | ||
| 444 | struct address_handler { | 564 | static int ioctl_send_request(struct client *client, void *buffer) |
| 445 | struct fw_address_handler handler; | 565 | { |
| 446 | __u64 closure; | 566 | struct fw_cdev_send_request *request = buffer; |
| 447 | struct client *client; | ||
| 448 | struct client_resource resource; | ||
| 449 | }; | ||
| 450 | 567 | ||
| 451 | struct request { | 568 | switch (request->tcode) { |
| 452 | struct fw_request *request; | 569 | case TCODE_WRITE_QUADLET_REQUEST: |
| 453 | void *data; | 570 | case TCODE_WRITE_BLOCK_REQUEST: |
| 454 | size_t length; | 571 | case TCODE_READ_QUADLET_REQUEST: |
| 455 | struct client_resource resource; | 572 | case TCODE_READ_BLOCK_REQUEST: |
| 456 | }; | 573 | case TCODE_LOCK_MASK_SWAP: |
| 574 | case TCODE_LOCK_COMPARE_SWAP: | ||
| 575 | case TCODE_LOCK_FETCH_ADD: | ||
| 576 | case TCODE_LOCK_LITTLE_ADD: | ||
| 577 | case TCODE_LOCK_BOUNDED_ADD: | ||
| 578 | case TCODE_LOCK_WRAP_ADD: | ||
| 579 | case TCODE_LOCK_VENDOR_DEPENDENT: | ||
| 580 | break; | ||
| 581 | default: | ||
| 582 | return -EINVAL; | ||
| 583 | } | ||
| 457 | 584 | ||
| 458 | struct request_event { | 585 | return init_request(client, request, client->device->node_id, |
| 459 | struct event event; | 586 | client->device->max_speed); |
| 460 | struct fw_cdev_event_request request; | 587 | } |
| 461 | }; | ||
| 462 | 588 | ||
| 463 | static void | 589 | static void release_request(struct client *client, |
| 464 | release_request(struct client *client, struct client_resource *resource) | 590 | struct client_resource *resource) |
| 465 | { | 591 | { |
| 466 | struct request *request = | 592 | struct inbound_transaction_resource *r = container_of(resource, |
| 467 | container_of(resource, struct request, resource); | 593 | struct inbound_transaction_resource, resource); |
| 468 | 594 | ||
| 469 | fw_send_response(client->device->card, request->request, | 595 | fw_send_response(client->device->card, r->request, |
| 470 | RCODE_CONFLICT_ERROR); | 596 | RCODE_CONFLICT_ERROR); |
| 471 | kfree(request); | 597 | kfree(r); |
| 472 | } | 598 | } |
| 473 | 599 | ||
| 474 | static void | 600 | static void handle_request(struct fw_card *card, struct fw_request *request, |
| 475 | handle_request(struct fw_card *card, struct fw_request *r, | 601 | int tcode, int destination, int source, |
| 476 | int tcode, int destination, int source, | 602 | int generation, int speed, |
| 477 | int generation, int speed, | 603 | unsigned long long offset, |
| 478 | unsigned long long offset, | 604 | void *payload, size_t length, void *callback_data) |
| 479 | void *payload, size_t length, void *callback_data) | ||
| 480 | { | 605 | { |
| 481 | struct address_handler *handler = callback_data; | 606 | struct address_handler_resource *handler = callback_data; |
| 482 | struct request *request; | 607 | struct inbound_transaction_resource *r; |
| 483 | struct request_event *e; | 608 | struct inbound_transaction_event *e; |
| 484 | struct client *client = handler->client; | 609 | int ret; |
| 485 | 610 | ||
| 486 | request = kmalloc(sizeof(*request), GFP_ATOMIC); | 611 | r = kmalloc(sizeof(*r), GFP_ATOMIC); |
| 487 | e = kmalloc(sizeof(*e), GFP_ATOMIC); | 612 | e = kmalloc(sizeof(*e), GFP_ATOMIC); |
| 488 | if (request == NULL || e == NULL) { | 613 | if (r == NULL || e == NULL) |
| 489 | kfree(request); | 614 | goto failed; |
| 490 | kfree(e); | ||
| 491 | fw_send_response(card, r, RCODE_CONFLICT_ERROR); | ||
| 492 | return; | ||
| 493 | } | ||
| 494 | 615 | ||
| 495 | request->request = r; | 616 | r->request = request; |
| 496 | request->data = payload; | 617 | r->data = payload; |
| 497 | request->length = length; | 618 | r->length = length; |
| 498 | 619 | ||
| 499 | request->resource.release = release_request; | 620 | r->resource.release = release_request; |
| 500 | add_client_resource(client, &request->resource); | 621 | ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC); |
| 622 | if (ret < 0) | ||
| 623 | goto failed; | ||
| 501 | 624 | ||
| 502 | e->request.type = FW_CDEV_EVENT_REQUEST; | 625 | e->request.type = FW_CDEV_EVENT_REQUEST; |
| 503 | e->request.tcode = tcode; | 626 | e->request.tcode = tcode; |
| 504 | e->request.offset = offset; | 627 | e->request.offset = offset; |
| 505 | e->request.length = length; | 628 | e->request.length = length; |
| 506 | e->request.handle = request->resource.handle; | 629 | e->request.handle = r->resource.handle; |
| 507 | e->request.closure = handler->closure; | 630 | e->request.closure = handler->closure; |
| 508 | 631 | ||
| 509 | queue_event(client, &e->event, | 632 | queue_event(handler->client, &e->event, |
| 510 | &e->request, sizeof(e->request), payload, length); | 633 | &e->request, sizeof(e->request), payload, length); |
| 634 | return; | ||
| 635 | |||
| 636 | failed: | ||
| 637 | kfree(r); | ||
| 638 | kfree(e); | ||
| 639 | fw_send_response(card, request, RCODE_CONFLICT_ERROR); | ||
| 511 | } | 640 | } |
| 512 | 641 | ||
| 513 | static void | 642 | static void release_address_handler(struct client *client, |
| 514 | release_address_handler(struct client *client, | 643 | struct client_resource *resource) |
| 515 | struct client_resource *resource) | ||
| 516 | { | 644 | { |
| 517 | struct address_handler *handler = | 645 | struct address_handler_resource *r = |
| 518 | container_of(resource, struct address_handler, resource); | 646 | container_of(resource, struct address_handler_resource, resource); |
| 519 | 647 | ||
| 520 | fw_core_remove_address_handler(&handler->handler); | 648 | fw_core_remove_address_handler(&r->handler); |
| 521 | kfree(handler); | 649 | kfree(r); |
| 522 | } | 650 | } |
| 523 | 651 | ||
| 524 | static int ioctl_allocate(struct client *client, void *buffer) | 652 | static int ioctl_allocate(struct client *client, void *buffer) |
| 525 | { | 653 | { |
| 526 | struct fw_cdev_allocate *request = buffer; | 654 | struct fw_cdev_allocate *request = buffer; |
| 527 | struct address_handler *handler; | 655 | struct address_handler_resource *r; |
| 528 | struct fw_address_region region; | 656 | struct fw_address_region region; |
| 657 | int ret; | ||
| 529 | 658 | ||
| 530 | handler = kmalloc(sizeof(*handler), GFP_KERNEL); | 659 | r = kmalloc(sizeof(*r), GFP_KERNEL); |
| 531 | if (handler == NULL) | 660 | if (r == NULL) |
| 532 | return -ENOMEM; | 661 | return -ENOMEM; |
| 533 | 662 | ||
| 534 | region.start = request->offset; | 663 | region.start = request->offset; |
| 535 | region.end = request->offset + request->length; | 664 | region.end = request->offset + request->length; |
| 536 | handler->handler.length = request->length; | 665 | r->handler.length = request->length; |
| 537 | handler->handler.address_callback = handle_request; | 666 | r->handler.address_callback = handle_request; |
| 538 | handler->handler.callback_data = handler; | 667 | r->handler.callback_data = r; |
| 539 | handler->closure = request->closure; | 668 | r->closure = request->closure; |
| 540 | handler->client = client; | 669 | r->client = client; |
| 541 | 670 | ||
| 542 | if (fw_core_add_address_handler(&handler->handler, ®ion) < 0) { | 671 | ret = fw_core_add_address_handler(&r->handler, ®ion); |
| 543 | kfree(handler); | 672 | if (ret < 0) { |
| 544 | return -EBUSY; | 673 | kfree(r); |
| 674 | return ret; | ||
| 545 | } | 675 | } |
| 546 | 676 | ||
| 547 | handler->resource.release = release_address_handler; | 677 | r->resource.release = release_address_handler; |
| 548 | add_client_resource(client, &handler->resource); | 678 | ret = add_client_resource(client, &r->resource, GFP_KERNEL); |
| 549 | request->handle = handler->resource.handle; | 679 | if (ret < 0) { |
| 680 | release_address_handler(client, &r->resource); | ||
| 681 | return ret; | ||
| 682 | } | ||
| 683 | request->handle = r->resource.handle; | ||
| 550 | 684 | ||
| 551 | return 0; | 685 | return 0; |
| 552 | } | 686 | } |
| @@ -555,18 +689,22 @@ static int ioctl_deallocate(struct client *client, void *buffer) | |||
| 555 | { | 689 | { |
| 556 | struct fw_cdev_deallocate *request = buffer; | 690 | struct fw_cdev_deallocate *request = buffer; |
| 557 | 691 | ||
| 558 | return release_client_resource(client, request->handle, NULL); | 692 | return release_client_resource(client, request->handle, |
| 693 | release_address_handler, NULL); | ||
| 559 | } | 694 | } |
| 560 | 695 | ||
| 561 | static int ioctl_send_response(struct client *client, void *buffer) | 696 | static int ioctl_send_response(struct client *client, void *buffer) |
| 562 | { | 697 | { |
| 563 | struct fw_cdev_send_response *request = buffer; | 698 | struct fw_cdev_send_response *request = buffer; |
| 564 | struct client_resource *resource; | 699 | struct client_resource *resource; |
| 565 | struct request *r; | 700 | struct inbound_transaction_resource *r; |
| 566 | 701 | ||
| 567 | if (release_client_resource(client, request->handle, &resource) < 0) | 702 | if (release_client_resource(client, request->handle, |
| 703 | release_request, &resource) < 0) | ||
| 568 | return -EINVAL; | 704 | return -EINVAL; |
| 569 | r = container_of(resource, struct request, resource); | 705 | |
| 706 | r = container_of(resource, struct inbound_transaction_resource, | ||
| 707 | resource); | ||
| 570 | if (request->length < r->length) | 708 | if (request->length < r->length) |
| 571 | r->length = request->length; | 709 | r->length = request->length; |
| 572 | if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) | 710 | if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) |
| @@ -588,85 +726,92 @@ static int ioctl_initiate_bus_reset(struct client *client, void *buffer) | |||
| 588 | return fw_core_initiate_bus_reset(client->device->card, short_reset); | 726 | return fw_core_initiate_bus_reset(client->device->card, short_reset); |
| 589 | } | 727 | } |
| 590 | 728 | ||
| 591 | struct descriptor { | ||
| 592 | struct fw_descriptor d; | ||
| 593 | struct client_resource resource; | ||
| 594 | u32 data[0]; | ||
| 595 | }; | ||
| 596 | |||
| 597 | static void release_descriptor(struct client *client, | 729 | static void release_descriptor(struct client *client, |
| 598 | struct client_resource *resource) | 730 | struct client_resource *resource) |
| 599 | { | 731 | { |
| 600 | struct descriptor *descriptor = | 732 | struct descriptor_resource *r = |
| 601 | container_of(resource, struct descriptor, resource); | 733 | container_of(resource, struct descriptor_resource, resource); |
| 602 | 734 | ||
| 603 | fw_core_remove_descriptor(&descriptor->d); | 735 | fw_core_remove_descriptor(&r->descriptor); |
| 604 | kfree(descriptor); | 736 | kfree(r); |
| 605 | } | 737 | } |
| 606 | 738 | ||
| 607 | static int ioctl_add_descriptor(struct client *client, void *buffer) | 739 | static int ioctl_add_descriptor(struct client *client, void *buffer) |
| 608 | { | 740 | { |
| 609 | struct fw_cdev_add_descriptor *request = buffer; | 741 | struct fw_cdev_add_descriptor *request = buffer; |
| 610 | struct descriptor *descriptor; | 742 | struct fw_card *card = client->device->card; |
| 611 | int retval; | 743 | struct descriptor_resource *r; |
| 744 | int ret; | ||
| 745 | |||
| 746 | /* Access policy: Allow this ioctl only on local nodes' device files. */ | ||
| 747 | spin_lock_irq(&card->lock); | ||
| 748 | ret = client->device->node_id != card->local_node->node_id; | ||
| 749 | spin_unlock_irq(&card->lock); | ||
| 750 | if (ret) | ||
| 751 | return -ENOSYS; | ||
| 612 | 752 | ||
| 613 | if (request->length > 256) | 753 | if (request->length > 256) |
| 614 | return -EINVAL; | 754 | return -EINVAL; |
| 615 | 755 | ||
| 616 | descriptor = | 756 | r = kmalloc(sizeof(*r) + request->length * 4, GFP_KERNEL); |
| 617 | kmalloc(sizeof(*descriptor) + request->length * 4, GFP_KERNEL); | 757 | if (r == NULL) |
| 618 | if (descriptor == NULL) | ||
| 619 | return -ENOMEM; | 758 | return -ENOMEM; |
| 620 | 759 | ||
| 621 | if (copy_from_user(descriptor->data, | 760 | if (copy_from_user(r->data, |
| 622 | u64_to_uptr(request->data), request->length * 4)) { | 761 | u64_to_uptr(request->data), request->length * 4)) { |
| 623 | kfree(descriptor); | 762 | ret = -EFAULT; |
| 624 | return -EFAULT; | 763 | goto failed; |
| 625 | } | 764 | } |
| 626 | 765 | ||
| 627 | descriptor->d.length = request->length; | 766 | r->descriptor.length = request->length; |
| 628 | descriptor->d.immediate = request->immediate; | 767 | r->descriptor.immediate = request->immediate; |
| 629 | descriptor->d.key = request->key; | 768 | r->descriptor.key = request->key; |
| 630 | descriptor->d.data = descriptor->data; | 769 | r->descriptor.data = r->data; |
| 631 | 770 | ||
| 632 | retval = fw_core_add_descriptor(&descriptor->d); | 771 | ret = fw_core_add_descriptor(&r->descriptor); |
| 633 | if (retval < 0) { | 772 | if (ret < 0) |
| 634 | kfree(descriptor); | 773 | goto failed; |
| 635 | return retval; | ||
| 636 | } | ||
| 637 | 774 | ||
| 638 | descriptor->resource.release = release_descriptor; | 775 | r->resource.release = release_descriptor; |
| 639 | add_client_resource(client, &descriptor->resource); | 776 | ret = add_client_resource(client, &r->resource, GFP_KERNEL); |
| 640 | request->handle = descriptor->resource.handle; | 777 | if (ret < 0) { |
| 778 | fw_core_remove_descriptor(&r->descriptor); | ||
| 779 | goto failed; | ||
| 780 | } | ||
| 781 | request->handle = r->resource.handle; | ||
| 641 | 782 | ||
| 642 | return 0; | 783 | return 0; |
| 784 | failed: | ||
| 785 | kfree(r); | ||
| 786 | |||
| 787 | return ret; | ||
| 643 | } | 788 | } |
| 644 | 789 | ||
| 645 | static int ioctl_remove_descriptor(struct client *client, void *buffer) | 790 | static int ioctl_remove_descriptor(struct client *client, void *buffer) |
| 646 | { | 791 | { |
| 647 | struct fw_cdev_remove_descriptor *request = buffer; | 792 | struct fw_cdev_remove_descriptor *request = buffer; |
| 648 | 793 | ||
| 649 | return release_client_resource(client, request->handle, NULL); | 794 | return release_client_resource(client, request->handle, |
| 795 | release_descriptor, NULL); | ||
| 650 | } | 796 | } |
| 651 | 797 | ||
| 652 | static void | 798 | static void iso_callback(struct fw_iso_context *context, u32 cycle, |
| 653 | iso_callback(struct fw_iso_context *context, u32 cycle, | 799 | size_t header_length, void *header, void *data) |
| 654 | size_t header_length, void *header, void *data) | ||
| 655 | { | 800 | { |
| 656 | struct client *client = data; | 801 | struct client *client = data; |
| 657 | struct iso_interrupt *irq; | 802 | struct iso_interrupt_event *e; |
| 658 | 803 | ||
| 659 | irq = kzalloc(sizeof(*irq) + header_length, GFP_ATOMIC); | 804 | e = kzalloc(sizeof(*e) + header_length, GFP_ATOMIC); |
| 660 | if (irq == NULL) | 805 | if (e == NULL) |
| 661 | return; | 806 | return; |
| 662 | 807 | ||
| 663 | irq->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; | 808 | e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; |
| 664 | irq->interrupt.closure = client->iso_closure; | 809 | e->interrupt.closure = client->iso_closure; |
| 665 | irq->interrupt.cycle = cycle; | 810 | e->interrupt.cycle = cycle; |
| 666 | irq->interrupt.header_length = header_length; | 811 | e->interrupt.header_length = header_length; |
| 667 | memcpy(irq->interrupt.header, header, header_length); | 812 | memcpy(e->interrupt.header, header, header_length); |
| 668 | queue_event(client, &irq->event, &irq->interrupt, | 813 | queue_event(client, &e->event, &e->interrupt, |
| 669 | sizeof(irq->interrupt) + header_length, NULL, 0); | 814 | sizeof(e->interrupt) + header_length, NULL, 0); |
| 670 | } | 815 | } |
| 671 | 816 | ||
| 672 | static int ioctl_create_iso_context(struct client *client, void *buffer) | 817 | static int ioctl_create_iso_context(struct client *client, void *buffer) |
| @@ -871,6 +1016,261 @@ static int ioctl_get_cycle_timer(struct client *client, void *buffer) | |||
| 871 | return 0; | 1016 | return 0; |
| 872 | } | 1017 | } |
| 873 | 1018 | ||
| 1019 | static void iso_resource_work(struct work_struct *work) | ||
| 1020 | { | ||
| 1021 | struct iso_resource_event *e; | ||
| 1022 | struct iso_resource *r = | ||
| 1023 | container_of(work, struct iso_resource, work.work); | ||
| 1024 | struct client *client = r->client; | ||
| 1025 | int generation, channel, bandwidth, todo; | ||
| 1026 | bool skip, free, success; | ||
| 1027 | |||
| 1028 | spin_lock_irq(&client->lock); | ||
| 1029 | generation = client->device->generation; | ||
| 1030 | todo = r->todo; | ||
| 1031 | /* Allow 1000ms grace period for other reallocations. */ | ||
| 1032 | if (todo == ISO_RES_ALLOC && | ||
| 1033 | time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { | ||
| 1034 | if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3))) | ||
| 1035 | client_get(client); | ||
| 1036 | skip = true; | ||
| 1037 | } else { | ||
| 1038 | /* We could be called twice within the same generation. */ | ||
| 1039 | skip = todo == ISO_RES_REALLOC && | ||
| 1040 | r->generation == generation; | ||
| 1041 | } | ||
| 1042 | free = todo == ISO_RES_DEALLOC || | ||
| 1043 | todo == ISO_RES_ALLOC_ONCE || | ||
| 1044 | todo == ISO_RES_DEALLOC_ONCE; | ||
| 1045 | r->generation = generation; | ||
| 1046 | spin_unlock_irq(&client->lock); | ||
| 1047 | |||
| 1048 | if (skip) | ||
| 1049 | goto out; | ||
| 1050 | |||
| 1051 | bandwidth = r->bandwidth; | ||
| 1052 | |||
| 1053 | fw_iso_resource_manage(client->device->card, generation, | ||
| 1054 | r->channels, &channel, &bandwidth, | ||
| 1055 | todo == ISO_RES_ALLOC || | ||
| 1056 | todo == ISO_RES_REALLOC || | ||
| 1057 | todo == ISO_RES_ALLOC_ONCE); | ||
| 1058 | /* | ||
| 1059 | * Is this generation outdated already? As long as this resource sticks | ||
| 1060 | * in the idr, it will be scheduled again for a newer generation or at | ||
| 1061 | * shutdown. | ||
| 1062 | */ | ||
| 1063 | if (channel == -EAGAIN && | ||
| 1064 | (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC)) | ||
| 1065 | goto out; | ||
| 1066 | |||
| 1067 | success = channel >= 0 || bandwidth > 0; | ||
| 1068 | |||
| 1069 | spin_lock_irq(&client->lock); | ||
| 1070 | /* | ||
| 1071 | * Transit from allocation to reallocation, except if the client | ||
| 1072 | * requested deallocation in the meantime. | ||
| 1073 | */ | ||
| 1074 | if (r->todo == ISO_RES_ALLOC) | ||
| 1075 | r->todo = ISO_RES_REALLOC; | ||
| 1076 | /* | ||
| 1077 | * Allocation or reallocation failure? Pull this resource out of the | ||
| 1078 | * idr and prepare for deletion, unless the client is shutting down. | ||
| 1079 | */ | ||
| 1080 | if (r->todo == ISO_RES_REALLOC && !success && | ||
| 1081 | !client->in_shutdown && | ||
| 1082 | idr_find(&client->resource_idr, r->resource.handle)) { | ||
| 1083 | idr_remove(&client->resource_idr, r->resource.handle); | ||
| 1084 | client_put(client); | ||
| 1085 | free = true; | ||
| 1086 | } | ||
| 1087 | spin_unlock_irq(&client->lock); | ||
| 1088 | |||
| 1089 | if (todo == ISO_RES_ALLOC && channel >= 0) | ||
| 1090 | r->channels = 1ULL << channel; | ||
| 1091 | |||
| 1092 | if (todo == ISO_RES_REALLOC && success) | ||
| 1093 | goto out; | ||
| 1094 | |||
| 1095 | if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) { | ||
| 1096 | e = r->e_alloc; | ||
| 1097 | r->e_alloc = NULL; | ||
| 1098 | } else { | ||
| 1099 | e = r->e_dealloc; | ||
| 1100 | r->e_dealloc = NULL; | ||
| 1101 | } | ||
| 1102 | e->resource.handle = r->resource.handle; | ||
| 1103 | e->resource.channel = channel; | ||
| 1104 | e->resource.bandwidth = bandwidth; | ||
| 1105 | |||
| 1106 | queue_event(client, &e->event, | ||
| 1107 | &e->resource, sizeof(e->resource), NULL, 0); | ||
| 1108 | |||
| 1109 | if (free) { | ||
| 1110 | cancel_delayed_work(&r->work); | ||
| 1111 | kfree(r->e_alloc); | ||
| 1112 | kfree(r->e_dealloc); | ||
| 1113 | kfree(r); | ||
| 1114 | } | ||
| 1115 | out: | ||
| 1116 | client_put(client); | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | static void schedule_iso_resource(struct iso_resource *r) | ||
| 1120 | { | ||
| 1121 | client_get(r->client); | ||
| 1122 | if (!schedule_delayed_work(&r->work, 0)) | ||
| 1123 | client_put(r->client); | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | static void release_iso_resource(struct client *client, | ||
| 1127 | struct client_resource *resource) | ||
| 1128 | { | ||
| 1129 | struct iso_resource *r = | ||
| 1130 | container_of(resource, struct iso_resource, resource); | ||
| 1131 | |||
| 1132 | spin_lock_irq(&client->lock); | ||
| 1133 | r->todo = ISO_RES_DEALLOC; | ||
| 1134 | schedule_iso_resource(r); | ||
| 1135 | spin_unlock_irq(&client->lock); | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | static int init_iso_resource(struct client *client, | ||
| 1139 | struct fw_cdev_allocate_iso_resource *request, int todo) | ||
| 1140 | { | ||
| 1141 | struct iso_resource_event *e1, *e2; | ||
| 1142 | struct iso_resource *r; | ||
| 1143 | int ret; | ||
| 1144 | |||
| 1145 | if ((request->channels == 0 && request->bandwidth == 0) || | ||
| 1146 | request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL || | ||
| 1147 | request->bandwidth < 0) | ||
| 1148 | return -EINVAL; | ||
| 1149 | |||
| 1150 | r = kmalloc(sizeof(*r), GFP_KERNEL); | ||
| 1151 | e1 = kmalloc(sizeof(*e1), GFP_KERNEL); | ||
| 1152 | e2 = kmalloc(sizeof(*e2), GFP_KERNEL); | ||
| 1153 | if (r == NULL || e1 == NULL || e2 == NULL) { | ||
| 1154 | ret = -ENOMEM; | ||
| 1155 | goto fail; | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | INIT_DELAYED_WORK(&r->work, iso_resource_work); | ||
| 1159 | r->client = client; | ||
| 1160 | r->todo = todo; | ||
| 1161 | r->generation = -1; | ||
| 1162 | r->channels = request->channels; | ||
| 1163 | r->bandwidth = request->bandwidth; | ||
| 1164 | r->e_alloc = e1; | ||
| 1165 | r->e_dealloc = e2; | ||
| 1166 | |||
| 1167 | e1->resource.closure = request->closure; | ||
| 1168 | e1->resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED; | ||
| 1169 | e2->resource.closure = request->closure; | ||
| 1170 | e2->resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED; | ||
| 1171 | |||
| 1172 | if (todo == ISO_RES_ALLOC) { | ||
| 1173 | r->resource.release = release_iso_resource; | ||
| 1174 | ret = add_client_resource(client, &r->resource, GFP_KERNEL); | ||
| 1175 | if (ret < 0) | ||
| 1176 | goto fail; | ||
| 1177 | } else { | ||
| 1178 | r->resource.release = NULL; | ||
| 1179 | r->resource.handle = -1; | ||
| 1180 | schedule_iso_resource(r); | ||
| 1181 | } | ||
| 1182 | request->handle = r->resource.handle; | ||
| 1183 | |||
| 1184 | return 0; | ||
| 1185 | fail: | ||
| 1186 | kfree(r); | ||
| 1187 | kfree(e1); | ||
| 1188 | kfree(e2); | ||
| 1189 | |||
| 1190 | return ret; | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | static int ioctl_allocate_iso_resource(struct client *client, void *buffer) | ||
| 1194 | { | ||
| 1195 | struct fw_cdev_allocate_iso_resource *request = buffer; | ||
| 1196 | |||
| 1197 | return init_iso_resource(client, request, ISO_RES_ALLOC); | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | static int ioctl_deallocate_iso_resource(struct client *client, void *buffer) | ||
| 1201 | { | ||
| 1202 | struct fw_cdev_deallocate *request = buffer; | ||
| 1203 | |||
| 1204 | return release_client_resource(client, request->handle, | ||
| 1205 | release_iso_resource, NULL); | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer) | ||
| 1209 | { | ||
| 1210 | struct fw_cdev_allocate_iso_resource *request = buffer; | ||
| 1211 | |||
| 1212 | return init_iso_resource(client, request, ISO_RES_ALLOC_ONCE); | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer) | ||
| 1216 | { | ||
| 1217 | struct fw_cdev_allocate_iso_resource *request = buffer; | ||
| 1218 | |||
| 1219 | return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE); | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | /* | ||
| 1223 | * Returns a speed code: Maximum speed to or from this device, | ||
| 1224 | * limited by the device's link speed, the local node's link speed, | ||
| 1225 | * and all PHY port speeds between the two links. | ||
| 1226 | */ | ||
| 1227 | static int ioctl_get_speed(struct client *client, void *buffer) | ||
| 1228 | { | ||
| 1229 | return client->device->max_speed; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | static int ioctl_send_broadcast_request(struct client *client, void *buffer) | ||
| 1233 | { | ||
| 1234 | struct fw_cdev_send_request *request = buffer; | ||
| 1235 | |||
| 1236 | switch (request->tcode) { | ||
| 1237 | case TCODE_WRITE_QUADLET_REQUEST: | ||
| 1238 | case TCODE_WRITE_BLOCK_REQUEST: | ||
| 1239 | break; | ||
| 1240 | default: | ||
| 1241 | return -EINVAL; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | /* Security policy: Only allow accesses to Units Space. */ | ||
| 1245 | if (request->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END) | ||
| 1246 | return -EACCES; | ||
| 1247 | |||
| 1248 | return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | static int ioctl_send_stream_packet(struct client *client, void *buffer) | ||
| 1252 | { | ||
| 1253 | struct fw_cdev_send_stream_packet *p = buffer; | ||
| 1254 | struct fw_cdev_send_request request; | ||
| 1255 | int dest; | ||
| 1256 | |||
| 1257 | if (p->speed > client->device->card->link_speed || | ||
| 1258 | p->length > 1024 << p->speed) | ||
| 1259 | return -EIO; | ||
| 1260 | |||
| 1261 | if (p->tag > 3 || p->channel > 63 || p->sy > 15) | ||
| 1262 | return -EINVAL; | ||
| 1263 | |||
| 1264 | dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy); | ||
| 1265 | request.tcode = TCODE_STREAM_DATA; | ||
| 1266 | request.length = p->length; | ||
| 1267 | request.closure = p->closure; | ||
| 1268 | request.data = p->data; | ||
| 1269 | request.generation = p->generation; | ||
| 1270 | |||
| 1271 | return init_request(client, &request, dest, p->speed); | ||
| 1272 | } | ||
| 1273 | |||
| 874 | static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { | 1274 | static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { |
| 875 | ioctl_get_info, | 1275 | ioctl_get_info, |
| 876 | ioctl_send_request, | 1276 | ioctl_send_request, |
| @@ -885,13 +1285,20 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { | |||
| 885 | ioctl_start_iso, | 1285 | ioctl_start_iso, |
| 886 | ioctl_stop_iso, | 1286 | ioctl_stop_iso, |
| 887 | ioctl_get_cycle_timer, | 1287 | ioctl_get_cycle_timer, |
| 1288 | ioctl_allocate_iso_resource, | ||
| 1289 | ioctl_deallocate_iso_resource, | ||
| 1290 | ioctl_allocate_iso_resource_once, | ||
| 1291 | ioctl_deallocate_iso_resource_once, | ||
| 1292 | ioctl_get_speed, | ||
| 1293 | ioctl_send_broadcast_request, | ||
| 1294 | ioctl_send_stream_packet, | ||
| 888 | }; | 1295 | }; |
| 889 | 1296 | ||
| 890 | static int | 1297 | static int dispatch_ioctl(struct client *client, |
| 891 | dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) | 1298 | unsigned int cmd, void __user *arg) |
| 892 | { | 1299 | { |
| 893 | char buffer[256]; | 1300 | char buffer[256]; |
| 894 | int retval; | 1301 | int ret; |
| 895 | 1302 | ||
| 896 | if (_IOC_TYPE(cmd) != '#' || | 1303 | if (_IOC_TYPE(cmd) != '#' || |
| 897 | _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers)) | 1304 | _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers)) |
| @@ -903,9 +1310,9 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) | |||
| 903 | return -EFAULT; | 1310 | return -EFAULT; |
| 904 | } | 1311 | } |
| 905 | 1312 | ||
| 906 | retval = ioctl_handlers[_IOC_NR(cmd)](client, buffer); | 1313 | ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer); |
| 907 | if (retval < 0) | 1314 | if (ret < 0) |
| 908 | return retval; | 1315 | return ret; |
| 909 | 1316 | ||
| 910 | if (_IOC_DIR(cmd) & _IOC_READ) { | 1317 | if (_IOC_DIR(cmd) & _IOC_READ) { |
| 911 | if (_IOC_SIZE(cmd) > sizeof(buffer) || | 1318 | if (_IOC_SIZE(cmd) > sizeof(buffer) || |
| @@ -913,12 +1320,11 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) | |||
| 913 | return -EFAULT; | 1320 | return -EFAULT; |
| 914 | } | 1321 | } |
| 915 | 1322 | ||
| 916 | return retval; | 1323 | return ret; |
| 917 | } | 1324 | } |
| 918 | 1325 | ||
| 919 | static long | 1326 | static long fw_device_op_ioctl(struct file *file, |
| 920 | fw_device_op_ioctl(struct file *file, | 1327 | unsigned int cmd, unsigned long arg) |
| 921 | unsigned int cmd, unsigned long arg) | ||
| 922 | { | 1328 | { |
| 923 | struct client *client = file->private_data; | 1329 | struct client *client = file->private_data; |
| 924 | 1330 | ||
| @@ -929,9 +1335,8 @@ fw_device_op_ioctl(struct file *file, | |||
| 929 | } | 1335 | } |
| 930 | 1336 | ||
| 931 | #ifdef CONFIG_COMPAT | 1337 | #ifdef CONFIG_COMPAT |
| 932 | static long | 1338 | static long fw_device_op_compat_ioctl(struct file *file, |
| 933 | fw_device_op_compat_ioctl(struct file *file, | 1339 | unsigned int cmd, unsigned long arg) |
| 934 | unsigned int cmd, unsigned long arg) | ||
| 935 | { | 1340 | { |
| 936 | struct client *client = file->private_data; | 1341 | struct client *client = file->private_data; |
| 937 | 1342 | ||
| @@ -947,7 +1352,7 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 947 | struct client *client = file->private_data; | 1352 | struct client *client = file->private_data; |
| 948 | enum dma_data_direction direction; | 1353 | enum dma_data_direction direction; |
| 949 | unsigned long size; | 1354 | unsigned long size; |
| 950 | int page_count, retval; | 1355 | int page_count, ret; |
| 951 | 1356 | ||
| 952 | if (fw_device_is_shutdown(client->device)) | 1357 | if (fw_device_is_shutdown(client->device)) |
| 953 | return -ENODEV; | 1358 | return -ENODEV; |
| @@ -973,48 +1378,57 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 973 | else | 1378 | else |
| 974 | direction = DMA_FROM_DEVICE; | 1379 | direction = DMA_FROM_DEVICE; |
| 975 | 1380 | ||
| 976 | retval = fw_iso_buffer_init(&client->buffer, client->device->card, | 1381 | ret = fw_iso_buffer_init(&client->buffer, client->device->card, |
| 977 | page_count, direction); | 1382 | page_count, direction); |
| 978 | if (retval < 0) | 1383 | if (ret < 0) |
| 979 | return retval; | 1384 | return ret; |
| 980 | 1385 | ||
| 981 | retval = fw_iso_buffer_map(&client->buffer, vma); | 1386 | ret = fw_iso_buffer_map(&client->buffer, vma); |
| 982 | if (retval < 0) | 1387 | if (ret < 0) |
| 983 | fw_iso_buffer_destroy(&client->buffer, client->device->card); | 1388 | fw_iso_buffer_destroy(&client->buffer, client->device->card); |
| 984 | 1389 | ||
| 985 | return retval; | 1390 | return ret; |
| 1391 | } | ||
| 1392 | |||
| 1393 | static int shutdown_resource(int id, void *p, void *data) | ||
| 1394 | { | ||
| 1395 | struct client_resource *r = p; | ||
| 1396 | struct client *client = data; | ||
| 1397 | |||
| 1398 | r->release(client, r); | ||
| 1399 | client_put(client); | ||
| 1400 | |||
| 1401 | return 0; | ||
| 986 | } | 1402 | } |
| 987 | 1403 | ||
| 988 | static int fw_device_op_release(struct inode *inode, struct file *file) | 1404 | static int fw_device_op_release(struct inode *inode, struct file *file) |
| 989 | { | 1405 | { |
| 990 | struct client *client = file->private_data; | 1406 | struct client *client = file->private_data; |
| 991 | struct event *e, *next_e; | 1407 | struct event *e, *next_e; |
| 992 | struct client_resource *r, *next_r; | ||
| 993 | unsigned long flags; | ||
| 994 | 1408 | ||
| 995 | if (client->buffer.pages) | 1409 | mutex_lock(&client->device->client_list_mutex); |
| 996 | fw_iso_buffer_destroy(&client->buffer, client->device->card); | 1410 | list_del(&client->link); |
| 1411 | mutex_unlock(&client->device->client_list_mutex); | ||
| 997 | 1412 | ||
| 998 | if (client->iso_context) | 1413 | if (client->iso_context) |
| 999 | fw_iso_context_destroy(client->iso_context); | 1414 | fw_iso_context_destroy(client->iso_context); |
| 1000 | 1415 | ||
| 1001 | list_for_each_entry_safe(r, next_r, &client->resource_list, link) | 1416 | if (client->buffer.pages) |
| 1002 | r->release(client, r); | 1417 | fw_iso_buffer_destroy(&client->buffer, client->device->card); |
| 1003 | 1418 | ||
| 1004 | /* | 1419 | /* Freeze client->resource_idr and client->event_list */ |
| 1005 | * FIXME: We should wait for the async tasklets to stop | 1420 | spin_lock_irq(&client->lock); |
| 1006 | * running before freeing the memory. | 1421 | client->in_shutdown = true; |
| 1007 | */ | 1422 | spin_unlock_irq(&client->lock); |
| 1423 | |||
| 1424 | idr_for_each(&client->resource_idr, shutdown_resource, client); | ||
| 1425 | idr_remove_all(&client->resource_idr); | ||
| 1426 | idr_destroy(&client->resource_idr); | ||
| 1008 | 1427 | ||
| 1009 | list_for_each_entry_safe(e, next_e, &client->event_list, link) | 1428 | list_for_each_entry_safe(e, next_e, &client->event_list, link) |
| 1010 | kfree(e); | 1429 | kfree(e); |
| 1011 | 1430 | ||
| 1012 | spin_lock_irqsave(&client->device->card->lock, flags); | 1431 | client_put(client); |
| 1013 | list_del(&client->link); | ||
| 1014 | spin_unlock_irqrestore(&client->device->card->lock, flags); | ||
| 1015 | |||
| 1016 | fw_device_put(client->device); | ||
| 1017 | kfree(client); | ||
| 1018 | 1432 | ||
| 1019 | return 0; | 1433 | return 0; |
| 1020 | } | 1434 | } |
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index bf53acb45652..a47e2129d83d 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c | |||
| @@ -18,22 +18,26 @@ | |||
| 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/module.h> | 21 | #include <linux/ctype.h> |
| 22 | #include <linux/wait.h> | ||
| 23 | #include <linux/errno.h> | ||
| 24 | #include <linux/kthread.h> | ||
| 25 | #include <linux/device.h> | ||
| 26 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 23 | #include <linux/device.h> | ||
| 24 | #include <linux/errno.h> | ||
| 27 | #include <linux/idr.h> | 25 | #include <linux/idr.h> |
| 28 | #include <linux/jiffies.h> | 26 | #include <linux/jiffies.h> |
| 29 | #include <linux/string.h> | 27 | #include <linux/kobject.h> |
| 28 | #include <linux/list.h> | ||
| 29 | #include <linux/mutex.h> | ||
| 30 | #include <linux/rwsem.h> | 30 | #include <linux/rwsem.h> |
| 31 | #include <linux/semaphore.h> | 31 | #include <linux/semaphore.h> |
| 32 | #include <linux/spinlock.h> | ||
| 33 | #include <linux/string.h> | ||
| 34 | #include <linux/workqueue.h> | ||
| 35 | |||
| 32 | #include <asm/system.h> | 36 | #include <asm/system.h> |
| 33 | #include <linux/ctype.h> | 37 | |
| 34 | #include "fw-transaction.h" | ||
| 35 | #include "fw-topology.h" | ||
| 36 | #include "fw-device.h" | 38 | #include "fw-device.h" |
| 39 | #include "fw-topology.h" | ||
| 40 | #include "fw-transaction.h" | ||
| 37 | 41 | ||
| 38 | void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p) | 42 | void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p) |
| 39 | { | 43 | { |
| @@ -132,8 +136,7 @@ static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) | |||
| 132 | vendor, model, specifier_id, version); | 136 | vendor, model, specifier_id, version); |
| 133 | } | 137 | } |
| 134 | 138 | ||
| 135 | static int | 139 | static int fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 136 | fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
| 137 | { | 140 | { |
| 138 | struct fw_unit *unit = fw_unit(dev); | 141 | struct fw_unit *unit = fw_unit(dev); |
| 139 | char modalias[64]; | 142 | char modalias[64]; |
| @@ -152,27 +155,6 @@ struct bus_type fw_bus_type = { | |||
| 152 | }; | 155 | }; |
| 153 | EXPORT_SYMBOL(fw_bus_type); | 156 | EXPORT_SYMBOL(fw_bus_type); |
| 154 | 157 | ||
| 155 | static void fw_device_release(struct device *dev) | ||
| 156 | { | ||
| 157 | struct fw_device *device = fw_device(dev); | ||
| 158 | struct fw_card *card = device->card; | ||
| 159 | unsigned long flags; | ||
| 160 | |||
| 161 | /* | ||
| 162 | * Take the card lock so we don't set this to NULL while a | ||
| 163 | * FW_NODE_UPDATED callback is being handled or while the | ||
| 164 | * bus manager work looks at this node. | ||
| 165 | */ | ||
| 166 | spin_lock_irqsave(&card->lock, flags); | ||
| 167 | device->node->data = NULL; | ||
| 168 | spin_unlock_irqrestore(&card->lock, flags); | ||
| 169 | |||
| 170 | fw_node_put(device->node); | ||
| 171 | kfree(device->config_rom); | ||
| 172 | kfree(device); | ||
| 173 | fw_card_put(card); | ||
| 174 | } | ||
| 175 | |||
| 176 | int fw_device_enable_phys_dma(struct fw_device *device) | 158 | int fw_device_enable_phys_dma(struct fw_device *device) |
| 177 | { | 159 | { |
| 178 | int generation = device->generation; | 160 | int generation = device->generation; |
| @@ -191,8 +173,8 @@ struct config_rom_attribute { | |||
| 191 | u32 key; | 173 | u32 key; |
| 192 | }; | 174 | }; |
| 193 | 175 | ||
| 194 | static ssize_t | 176 | static ssize_t show_immediate(struct device *dev, |
| 195 | show_immediate(struct device *dev, struct device_attribute *dattr, char *buf) | 177 | struct device_attribute *dattr, char *buf) |
| 196 | { | 178 | { |
| 197 | struct config_rom_attribute *attr = | 179 | struct config_rom_attribute *attr = |
| 198 | container_of(dattr, struct config_rom_attribute, attr); | 180 | container_of(dattr, struct config_rom_attribute, attr); |
| @@ -223,8 +205,8 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf) | |||
| 223 | #define IMMEDIATE_ATTR(name, key) \ | 205 | #define IMMEDIATE_ATTR(name, key) \ |
| 224 | { __ATTR(name, S_IRUGO, show_immediate, NULL), key } | 206 | { __ATTR(name, S_IRUGO, show_immediate, NULL), key } |
| 225 | 207 | ||
| 226 | static ssize_t | 208 | static ssize_t show_text_leaf(struct device *dev, |
| 227 | show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf) | 209 | struct device_attribute *dattr, char *buf) |
| 228 | { | 210 | { |
| 229 | struct config_rom_attribute *attr = | 211 | struct config_rom_attribute *attr = |
| 230 | container_of(dattr, struct config_rom_attribute, attr); | 212 | container_of(dattr, struct config_rom_attribute, attr); |
| @@ -293,10 +275,9 @@ static struct config_rom_attribute config_rom_attributes[] = { | |||
| 293 | TEXT_LEAF_ATTR(hardware_version_name, CSR_HARDWARE_VERSION), | 275 | TEXT_LEAF_ATTR(hardware_version_name, CSR_HARDWARE_VERSION), |
| 294 | }; | 276 | }; |
| 295 | 277 | ||
| 296 | static void | 278 | static void init_fw_attribute_group(struct device *dev, |
| 297 | init_fw_attribute_group(struct device *dev, | 279 | struct device_attribute *attrs, |
| 298 | struct device_attribute *attrs, | 280 | struct fw_attribute_group *group) |
| 299 | struct fw_attribute_group *group) | ||
| 300 | { | 281 | { |
| 301 | struct device_attribute *attr; | 282 | struct device_attribute *attr; |
| 302 | int i, j; | 283 | int i, j; |
| @@ -319,9 +300,8 @@ init_fw_attribute_group(struct device *dev, | |||
| 319 | dev->groups = group->groups; | 300 | dev->groups = group->groups; |
| 320 | } | 301 | } |
| 321 | 302 | ||
| 322 | static ssize_t | 303 | static ssize_t modalias_show(struct device *dev, |
| 323 | modalias_show(struct device *dev, | 304 | struct device_attribute *attr, char *buf) |
| 324 | struct device_attribute *attr, char *buf) | ||
| 325 | { | 305 | { |
| 326 | struct fw_unit *unit = fw_unit(dev); | 306 | struct fw_unit *unit = fw_unit(dev); |
| 327 | int length; | 307 | int length; |
| @@ -332,9 +312,8 @@ modalias_show(struct device *dev, | |||
| 332 | return length + 1; | 312 | return length + 1; |
| 333 | } | 313 | } |
| 334 | 314 | ||
| 335 | static ssize_t | 315 | static ssize_t rom_index_show(struct device *dev, |
| 336 | rom_index_show(struct device *dev, | 316 | struct device_attribute *attr, char *buf) |
| 337 | struct device_attribute *attr, char *buf) | ||
| 338 | { | 317 | { |
| 339 | struct fw_device *device = fw_device(dev->parent); | 318 | struct fw_device *device = fw_device(dev->parent); |
| 340 | struct fw_unit *unit = fw_unit(dev); | 319 | struct fw_unit *unit = fw_unit(dev); |
| @@ -349,8 +328,8 @@ static struct device_attribute fw_unit_attributes[] = { | |||
| 349 | __ATTR_NULL, | 328 | __ATTR_NULL, |
| 350 | }; | 329 | }; |
| 351 | 330 | ||
| 352 | static ssize_t | 331 | static ssize_t config_rom_show(struct device *dev, |
| 353 | config_rom_show(struct device *dev, struct device_attribute *attr, char *buf) | 332 | struct device_attribute *attr, char *buf) |
| 354 | { | 333 | { |
| 355 | struct fw_device *device = fw_device(dev); | 334 | struct fw_device *device = fw_device(dev); |
| 356 | size_t length; | 335 | size_t length; |
| @@ -363,8 +342,8 @@ config_rom_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
| 363 | return length; | 342 | return length; |
| 364 | } | 343 | } |
| 365 | 344 | ||
| 366 | static ssize_t | 345 | static ssize_t guid_show(struct device *dev, |
| 367 | guid_show(struct device *dev, struct device_attribute *attr, char *buf) | 346 | struct device_attribute *attr, char *buf) |
| 368 | { | 347 | { |
| 369 | struct fw_device *device = fw_device(dev); | 348 | struct fw_device *device = fw_device(dev); |
| 370 | int ret; | 349 | int ret; |
| @@ -383,8 +362,8 @@ static struct device_attribute fw_device_attributes[] = { | |||
| 383 | __ATTR_NULL, | 362 | __ATTR_NULL, |
| 384 | }; | 363 | }; |
| 385 | 364 | ||
| 386 | static int | 365 | static int read_rom(struct fw_device *device, |
| 387 | read_rom(struct fw_device *device, int generation, int index, u32 *data) | 366 | int generation, int index, u32 *data) |
| 388 | { | 367 | { |
| 389 | int rcode; | 368 | int rcode; |
| 390 | 369 | ||
| @@ -539,7 +518,7 @@ static int read_bus_info_block(struct fw_device *device, int generation) | |||
| 539 | 518 | ||
| 540 | kfree(old_rom); | 519 | kfree(old_rom); |
| 541 | ret = 0; | 520 | ret = 0; |
| 542 | device->cmc = rom[2] & 1 << 30; | 521 | device->cmc = rom[2] >> 30 & 1; |
| 543 | out: | 522 | out: |
| 544 | kfree(rom); | 523 | kfree(rom); |
| 545 | 524 | ||
| @@ -679,11 +658,53 @@ static void fw_device_shutdown(struct work_struct *work) | |||
| 679 | fw_device_put(device); | 658 | fw_device_put(device); |
| 680 | } | 659 | } |
| 681 | 660 | ||
| 661 | static void fw_device_release(struct device *dev) | ||
| 662 | { | ||
| 663 | struct fw_device *device = fw_device(dev); | ||
| 664 | struct fw_card *card = device->card; | ||
| 665 | unsigned long flags; | ||
| 666 | |||
| 667 | /* | ||
| 668 | * Take the card lock so we don't set this to NULL while a | ||
| 669 | * FW_NODE_UPDATED callback is being handled or while the | ||
| 670 | * bus manager work looks at this node. | ||
| 671 | */ | ||
| 672 | spin_lock_irqsave(&card->lock, flags); | ||
| 673 | device->node->data = NULL; | ||
| 674 | spin_unlock_irqrestore(&card->lock, flags); | ||
| 675 | |||
| 676 | fw_node_put(device->node); | ||
| 677 | kfree(device->config_rom); | ||
| 678 | kfree(device); | ||
| 679 | fw_card_put(card); | ||
| 680 | } | ||
| 681 | |||
| 682 | static struct device_type fw_device_type = { | 682 | static struct device_type fw_device_type = { |
| 683 | .release = fw_device_release, | 683 | .release = fw_device_release, |
| 684 | }; | 684 | }; |
| 685 | 685 | ||
| 686 | static void fw_device_update(struct work_struct *work); | 686 | static int update_unit(struct device *dev, void *data) |
| 687 | { | ||
| 688 | struct fw_unit *unit = fw_unit(dev); | ||
| 689 | struct fw_driver *driver = (struct fw_driver *)dev->driver; | ||
| 690 | |||
| 691 | if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { | ||
| 692 | down(&dev->sem); | ||
| 693 | driver->update(unit); | ||
| 694 | up(&dev->sem); | ||
| 695 | } | ||
| 696 | |||
| 697 | return 0; | ||
| 698 | } | ||
| 699 | |||
| 700 | static void fw_device_update(struct work_struct *work) | ||
| 701 | { | ||
| 702 | struct fw_device *device = | ||
| 703 | container_of(work, struct fw_device, work.work); | ||
| 704 | |||
| 705 | fw_device_cdev_update(device); | ||
| 706 | device_for_each_child(&device->device, NULL, update_unit); | ||
| 707 | } | ||
| 687 | 708 | ||
| 688 | /* | 709 | /* |
| 689 | * If a device was pending for deletion because its node went away but its | 710 | * If a device was pending for deletion because its node went away but its |
| @@ -735,12 +756,50 @@ static int lookup_existing_device(struct device *dev, void *data) | |||
| 735 | return match; | 756 | return match; |
| 736 | } | 757 | } |
| 737 | 758 | ||
| 759 | enum { BC_UNKNOWN = 0, BC_UNIMPLEMENTED, BC_IMPLEMENTED, }; | ||
| 760 | |||
| 761 | void fw_device_set_broadcast_channel(struct fw_device *device, int generation) | ||
| 762 | { | ||
| 763 | struct fw_card *card = device->card; | ||
| 764 | __be32 data; | ||
| 765 | int rcode; | ||
| 766 | |||
| 767 | if (!card->broadcast_channel_allocated) | ||
| 768 | return; | ||
| 769 | |||
| 770 | if (device->bc_implemented == BC_UNKNOWN) { | ||
| 771 | rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST, | ||
| 772 | device->node_id, generation, device->max_speed, | ||
| 773 | CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, | ||
| 774 | &data, 4); | ||
| 775 | switch (rcode) { | ||
| 776 | case RCODE_COMPLETE: | ||
| 777 | if (data & cpu_to_be32(1 << 31)) { | ||
| 778 | device->bc_implemented = BC_IMPLEMENTED; | ||
| 779 | break; | ||
| 780 | } | ||
| 781 | /* else fall through to case address error */ | ||
| 782 | case RCODE_ADDRESS_ERROR: | ||
| 783 | device->bc_implemented = BC_UNIMPLEMENTED; | ||
| 784 | } | ||
| 785 | } | ||
| 786 | |||
| 787 | if (device->bc_implemented == BC_IMPLEMENTED) { | ||
| 788 | data = cpu_to_be32(BROADCAST_CHANNEL_INITIAL | | ||
| 789 | BROADCAST_CHANNEL_VALID); | ||
| 790 | fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, | ||
| 791 | device->node_id, generation, device->max_speed, | ||
| 792 | CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, | ||
| 793 | &data, 4); | ||
| 794 | } | ||
| 795 | } | ||
| 796 | |||
| 738 | static void fw_device_init(struct work_struct *work) | 797 | static void fw_device_init(struct work_struct *work) |
| 739 | { | 798 | { |
| 740 | struct fw_device *device = | 799 | struct fw_device *device = |
| 741 | container_of(work, struct fw_device, work.work); | 800 | container_of(work, struct fw_device, work.work); |
| 742 | struct device *revived_dev; | 801 | struct device *revived_dev; |
| 743 | int minor, err; | 802 | int minor, ret; |
| 744 | 803 | ||
| 745 | /* | 804 | /* |
| 746 | * All failure paths here set node->data to NULL, so that we | 805 | * All failure paths here set node->data to NULL, so that we |
| @@ -776,12 +835,12 @@ static void fw_device_init(struct work_struct *work) | |||
| 776 | 835 | ||
| 777 | fw_device_get(device); | 836 | fw_device_get(device); |
| 778 | down_write(&fw_device_rwsem); | 837 | down_write(&fw_device_rwsem); |
| 779 | err = idr_pre_get(&fw_device_idr, GFP_KERNEL) ? | 838 | ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ? |
| 780 | idr_get_new(&fw_device_idr, device, &minor) : | 839 | idr_get_new(&fw_device_idr, device, &minor) : |
| 781 | -ENOMEM; | 840 | -ENOMEM; |
| 782 | up_write(&fw_device_rwsem); | 841 | up_write(&fw_device_rwsem); |
| 783 | 842 | ||
| 784 | if (err < 0) | 843 | if (ret < 0) |
| 785 | goto error; | 844 | goto error; |
| 786 | 845 | ||
| 787 | device->device.bus = &fw_bus_type; | 846 | device->device.bus = &fw_bus_type; |
| @@ -828,6 +887,8 @@ static void fw_device_init(struct work_struct *work) | |||
| 828 | device->config_rom[3], device->config_rom[4], | 887 | device->config_rom[3], device->config_rom[4], |
| 829 | 1 << device->max_speed); | 888 | 1 << device->max_speed); |
| 830 | device->config_rom_retries = 0; | 889 | device->config_rom_retries = 0; |
| 890 | |||
| 891 | fw_device_set_broadcast_channel(device, device->generation); | ||
| 831 | } | 892 | } |
| 832 | 893 | ||
| 833 | /* | 894 | /* |
| @@ -851,29 +912,6 @@ static void fw_device_init(struct work_struct *work) | |||
| 851 | put_device(&device->device); /* our reference */ | 912 | put_device(&device->device); /* our reference */ |
| 852 | } | 913 | } |
| 853 | 914 | ||
| 854 | static int update_unit(struct device *dev, void *data) | ||
| 855 | { | ||
| 856 | struct fw_unit *unit = fw_unit(dev); | ||
| 857 | struct fw_driver *driver = (struct fw_driver *)dev->driver; | ||
| 858 | |||
| 859 | if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { | ||
| 860 | down(&dev->sem); | ||
| 861 | driver->update(unit); | ||
| 862 | up(&dev->sem); | ||
| 863 | } | ||
| 864 | |||
| 865 | return 0; | ||
| 866 | } | ||
| 867 | |||
| 868 | static void fw_device_update(struct work_struct *work) | ||
| 869 | { | ||
| 870 | struct fw_device *device = | ||
| 871 | container_of(work, struct fw_device, work.work); | ||
| 872 | |||
| 873 | fw_device_cdev_update(device); | ||
| 874 | device_for_each_child(&device->device, NULL, update_unit); | ||
| 875 | } | ||
| 876 | |||
| 877 | enum { | 915 | enum { |
| 878 | REREAD_BIB_ERROR, | 916 | REREAD_BIB_ERROR, |
| 879 | REREAD_BIB_GONE, | 917 | REREAD_BIB_GONE, |
| @@ -894,7 +932,7 @@ static int reread_bus_info_block(struct fw_device *device, int generation) | |||
| 894 | if (i == 0 && q == 0) | 932 | if (i == 0 && q == 0) |
| 895 | return REREAD_BIB_GONE; | 933 | return REREAD_BIB_GONE; |
| 896 | 934 | ||
| 897 | if (i > device->config_rom_length || q != device->config_rom[i]) | 935 | if (q != device->config_rom[i]) |
| 898 | return REREAD_BIB_CHANGED; | 936 | return REREAD_BIB_CHANGED; |
| 899 | } | 937 | } |
| 900 | 938 | ||
| @@ -1004,6 +1042,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) | |||
| 1004 | device->node = fw_node_get(node); | 1042 | device->node = fw_node_get(node); |
| 1005 | device->node_id = node->node_id; | 1043 | device->node_id = node->node_id; |
| 1006 | device->generation = card->generation; | 1044 | device->generation = card->generation; |
| 1045 | mutex_init(&device->client_list_mutex); | ||
| 1007 | INIT_LIST_HEAD(&device->client_list); | 1046 | INIT_LIST_HEAD(&device->client_list); |
| 1008 | 1047 | ||
| 1009 | /* | 1048 | /* |
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 8ef6ec2ca21c..97588937c018 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h | |||
| @@ -19,10 +19,17 @@ | |||
| 19 | #ifndef __fw_device_h | 19 | #ifndef __fw_device_h |
| 20 | #define __fw_device_h | 20 | #define __fw_device_h |
| 21 | 21 | ||
| 22 | #include <linux/device.h> | ||
| 22 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
| 23 | #include <linux/cdev.h> | ||
| 24 | #include <linux/idr.h> | 24 | #include <linux/idr.h> |
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/list.h> | ||
| 27 | #include <linux/mutex.h> | ||
| 25 | #include <linux/rwsem.h> | 28 | #include <linux/rwsem.h> |
| 29 | #include <linux/sysfs.h> | ||
| 30 | #include <linux/types.h> | ||
| 31 | #include <linux/workqueue.h> | ||
| 32 | |||
| 26 | #include <asm/atomic.h> | 33 | #include <asm/atomic.h> |
| 27 | 34 | ||
| 28 | enum fw_device_state { | 35 | enum fw_device_state { |
| @@ -38,6 +45,9 @@ struct fw_attribute_group { | |||
| 38 | struct attribute *attrs[11]; | 45 | struct attribute *attrs[11]; |
| 39 | }; | 46 | }; |
| 40 | 47 | ||
| 48 | struct fw_node; | ||
| 49 | struct fw_card; | ||
| 50 | |||
| 41 | /* | 51 | /* |
| 42 | * Note, fw_device.generation always has to be read before fw_device.node_id. | 52 | * Note, fw_device.generation always has to be read before fw_device.node_id. |
| 43 | * Use SMP memory barriers to ensure this. Otherwise requests will be sent | 53 | * Use SMP memory barriers to ensure this. Otherwise requests will be sent |
| @@ -61,13 +71,18 @@ struct fw_device { | |||
| 61 | int node_id; | 71 | int node_id; |
| 62 | int generation; | 72 | int generation; |
| 63 | unsigned max_speed; | 73 | unsigned max_speed; |
| 64 | bool cmc; | ||
| 65 | struct fw_card *card; | 74 | struct fw_card *card; |
| 66 | struct device device; | 75 | struct device device; |
| 76 | |||
| 77 | struct mutex client_list_mutex; | ||
| 67 | struct list_head client_list; | 78 | struct list_head client_list; |
| 79 | |||
| 68 | u32 *config_rom; | 80 | u32 *config_rom; |
| 69 | size_t config_rom_length; | 81 | size_t config_rom_length; |
| 70 | int config_rom_retries; | 82 | int config_rom_retries; |
| 83 | unsigned cmc:1; | ||
| 84 | unsigned bc_implemented:2; | ||
| 85 | |||
| 71 | struct delayed_work work; | 86 | struct delayed_work work; |
| 72 | struct fw_attribute_group attribute_group; | 87 | struct fw_attribute_group attribute_group; |
| 73 | }; | 88 | }; |
| @@ -96,6 +111,7 @@ static inline void fw_device_put(struct fw_device *device) | |||
| 96 | 111 | ||
| 97 | struct fw_device *fw_device_get_by_devt(dev_t devt); | 112 | struct fw_device *fw_device_get_by_devt(dev_t devt); |
| 98 | int fw_device_enable_phys_dma(struct fw_device *device); | 113 | int fw_device_enable_phys_dma(struct fw_device *device); |
| 114 | void fw_device_set_broadcast_channel(struct fw_device *device, int generation); | ||
| 99 | 115 | ||
| 100 | void fw_device_cdev_update(struct fw_device *device); | 116 | void fw_device_cdev_update(struct fw_device *device); |
| 101 | void fw_device_cdev_remove(struct fw_device *device); | 117 | void fw_device_cdev_remove(struct fw_device *device); |
| @@ -176,8 +192,7 @@ struct fw_driver { | |||
| 176 | const struct fw_device_id *id_table; | 192 | const struct fw_device_id *id_table; |
| 177 | }; | 193 | }; |
| 178 | 194 | ||
| 179 | static inline struct fw_driver * | 195 | static inline struct fw_driver *fw_driver(struct device_driver *drv) |
| 180 | fw_driver(struct device_driver *drv) | ||
| 181 | { | 196 | { |
| 182 | return container_of(drv, struct fw_driver, driver); | 197 | return container_of(drv, struct fw_driver, driver); |
| 183 | } | 198 | } |
diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index e14c03dc0065..2baf1007253e 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Isochronous IO functionality | 2 | * Isochronous I/O functionality: |
| 3 | * - Isochronous DMA context management | ||
| 4 | * - Isochronous bus resource management (channels, bandwidth), client side | ||
| 3 | * | 5 | * |
| 4 | * Copyright (C) 2006 Kristian Hoegsberg <krh@bitplanet.net> | 6 | * Copyright (C) 2006 Kristian Hoegsberg <krh@bitplanet.net> |
| 5 | * | 7 | * |
| @@ -18,21 +20,25 @@ | |||
| 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 20 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | */ | 21 | */ |
| 20 | 22 | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/dma-mapping.h> | 23 | #include <linux/dma-mapping.h> |
| 24 | #include <linux/vmalloc.h> | 24 | #include <linux/errno.h> |
| 25 | #include <linux/firewire-constants.h> | ||
| 26 | #include <linux/kernel.h> | ||
| 25 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
| 28 | #include <linux/spinlock.h> | ||
| 29 | #include <linux/vmalloc.h> | ||
| 26 | 30 | ||
| 27 | #include "fw-transaction.h" | ||
| 28 | #include "fw-topology.h" | 31 | #include "fw-topology.h" |
| 29 | #include "fw-device.h" | 32 | #include "fw-transaction.h" |
| 30 | 33 | ||
| 31 | int | 34 | /* |
| 32 | fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, | 35 | * Isochronous DMA context management |
| 33 | int page_count, enum dma_data_direction direction) | 36 | */ |
| 37 | |||
| 38 | int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, | ||
| 39 | int page_count, enum dma_data_direction direction) | ||
| 34 | { | 40 | { |
| 35 | int i, j, retval = -ENOMEM; | 41 | int i, j; |
| 36 | dma_addr_t address; | 42 | dma_addr_t address; |
| 37 | 43 | ||
| 38 | buffer->page_count = page_count; | 44 | buffer->page_count = page_count; |
| @@ -69,19 +75,21 @@ fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, | |||
| 69 | kfree(buffer->pages); | 75 | kfree(buffer->pages); |
| 70 | out: | 76 | out: |
| 71 | buffer->pages = NULL; | 77 | buffer->pages = NULL; |
| 72 | return retval; | 78 | |
| 79 | return -ENOMEM; | ||
| 73 | } | 80 | } |
| 74 | 81 | ||
| 75 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma) | 82 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma) |
| 76 | { | 83 | { |
| 77 | unsigned long uaddr; | 84 | unsigned long uaddr; |
| 78 | int i, retval; | 85 | int i, err; |
| 79 | 86 | ||
| 80 | uaddr = vma->vm_start; | 87 | uaddr = vma->vm_start; |
| 81 | for (i = 0; i < buffer->page_count; i++) { | 88 | for (i = 0; i < buffer->page_count; i++) { |
| 82 | retval = vm_insert_page(vma, uaddr, buffer->pages[i]); | 89 | err = vm_insert_page(vma, uaddr, buffer->pages[i]); |
| 83 | if (retval) | 90 | if (err) |
| 84 | return retval; | 91 | return err; |
| 92 | |||
| 85 | uaddr += PAGE_SIZE; | 93 | uaddr += PAGE_SIZE; |
| 86 | } | 94 | } |
| 87 | 95 | ||
| @@ -105,14 +113,14 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, | |||
| 105 | buffer->pages = NULL; | 113 | buffer->pages = NULL; |
| 106 | } | 114 | } |
| 107 | 115 | ||
| 108 | struct fw_iso_context * | 116 | struct fw_iso_context *fw_iso_context_create(struct fw_card *card, |
| 109 | fw_iso_context_create(struct fw_card *card, int type, | 117 | int type, int channel, int speed, size_t header_size, |
| 110 | int channel, int speed, size_t header_size, | 118 | fw_iso_callback_t callback, void *callback_data) |
| 111 | fw_iso_callback_t callback, void *callback_data) | ||
| 112 | { | 119 | { |
| 113 | struct fw_iso_context *ctx; | 120 | struct fw_iso_context *ctx; |
| 114 | 121 | ||
| 115 | ctx = card->driver->allocate_iso_context(card, type, header_size); | 122 | ctx = card->driver->allocate_iso_context(card, |
| 123 | type, channel, header_size); | ||
| 116 | if (IS_ERR(ctx)) | 124 | if (IS_ERR(ctx)) |
| 117 | return ctx; | 125 | return ctx; |
| 118 | 126 | ||
| @@ -134,25 +142,186 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx) | |||
| 134 | card->driver->free_iso_context(ctx); | 142 | card->driver->free_iso_context(ctx); |
| 135 | } | 143 | } |
| 136 | 144 | ||
| 137 | int | 145 | int fw_iso_context_start(struct fw_iso_context *ctx, |
| 138 | fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags) | 146 | int cycle, int sync, int tags) |
| 139 | { | 147 | { |
| 140 | return ctx->card->driver->start_iso(ctx, cycle, sync, tags); | 148 | return ctx->card->driver->start_iso(ctx, cycle, sync, tags); |
| 141 | } | 149 | } |
| 142 | 150 | ||
| 143 | int | 151 | int fw_iso_context_queue(struct fw_iso_context *ctx, |
| 144 | fw_iso_context_queue(struct fw_iso_context *ctx, | 152 | struct fw_iso_packet *packet, |
| 145 | struct fw_iso_packet *packet, | 153 | struct fw_iso_buffer *buffer, |
| 146 | struct fw_iso_buffer *buffer, | 154 | unsigned long payload) |
| 147 | unsigned long payload) | ||
| 148 | { | 155 | { |
| 149 | struct fw_card *card = ctx->card; | 156 | struct fw_card *card = ctx->card; |
| 150 | 157 | ||
| 151 | return card->driver->queue_iso(ctx, packet, buffer, payload); | 158 | return card->driver->queue_iso(ctx, packet, buffer, payload); |
| 152 | } | 159 | } |
| 153 | 160 | ||
| 154 | int | 161 | int fw_iso_context_stop(struct fw_iso_context *ctx) |
| 155 | fw_iso_context_stop(struct fw_iso_context *ctx) | ||
| 156 | { | 162 | { |
| 157 | return ctx->card->driver->stop_iso(ctx); | 163 | return ctx->card->driver->stop_iso(ctx); |
| 158 | } | 164 | } |
| 165 | |||
| 166 | /* | ||
| 167 | * Isochronous bus resource management (channels, bandwidth), client side | ||
| 168 | */ | ||
| 169 | |||
| 170 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | ||
| 171 | int bandwidth, bool allocate) | ||
| 172 | { | ||
| 173 | __be32 data[2]; | ||
| 174 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; | ||
| 175 | |||
| 176 | /* | ||
| 177 | * On a 1394a IRM with low contention, try < 1 is enough. | ||
| 178 | * On a 1394-1995 IRM, we need at least try < 2. | ||
| 179 | * Let's just do try < 5. | ||
| 180 | */ | ||
| 181 | for (try = 0; try < 5; try++) { | ||
| 182 | new = allocate ? old - bandwidth : old + bandwidth; | ||
| 183 | if (new < 0 || new > BANDWIDTH_AVAILABLE_INITIAL) | ||
| 184 | break; | ||
| 185 | |||
| 186 | data[0] = cpu_to_be32(old); | ||
| 187 | data[1] = cpu_to_be32(new); | ||
| 188 | switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, | ||
| 189 | irm_id, generation, SCODE_100, | ||
| 190 | CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE, | ||
| 191 | data, sizeof(data))) { | ||
| 192 | case RCODE_GENERATION: | ||
| 193 | /* A generation change frees all bandwidth. */ | ||
| 194 | return allocate ? -EAGAIN : bandwidth; | ||
| 195 | |||
| 196 | case RCODE_COMPLETE: | ||
| 197 | if (be32_to_cpup(data) == old) | ||
| 198 | return bandwidth; | ||
| 199 | |||
| 200 | old = be32_to_cpup(data); | ||
| 201 | /* Fall through. */ | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | return -EIO; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int manage_channel(struct fw_card *card, int irm_id, int generation, | ||
| 209 | u32 channels_mask, u64 offset, bool allocate) | ||
| 210 | { | ||
| 211 | __be32 data[2], c, all, old; | ||
| 212 | int i, retry = 5; | ||
| 213 | |||
| 214 | old = all = allocate ? cpu_to_be32(~0) : 0; | ||
| 215 | |||
| 216 | for (i = 0; i < 32; i++) { | ||
| 217 | if (!(channels_mask & 1 << i)) | ||
| 218 | continue; | ||
| 219 | |||
| 220 | c = cpu_to_be32(1 << (31 - i)); | ||
| 221 | if ((old & c) != (all & c)) | ||
| 222 | continue; | ||
| 223 | |||
| 224 | data[0] = old; | ||
| 225 | data[1] = old ^ c; | ||
| 226 | switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, | ||
| 227 | irm_id, generation, SCODE_100, | ||
| 228 | offset, data, sizeof(data))) { | ||
| 229 | case RCODE_GENERATION: | ||
| 230 | /* A generation change frees all channels. */ | ||
| 231 | return allocate ? -EAGAIN : i; | ||
| 232 | |||
| 233 | case RCODE_COMPLETE: | ||
| 234 | if (data[0] == old) | ||
| 235 | return i; | ||
| 236 | |||
| 237 | old = data[0]; | ||
| 238 | |||
| 239 | /* Is the IRM 1394a-2000 compliant? */ | ||
| 240 | if ((data[0] & c) == (data[1] & c)) | ||
| 241 | continue; | ||
| 242 | |||
| 243 | /* 1394-1995 IRM, fall through to retry. */ | ||
| 244 | default: | ||
| 245 | if (retry--) | ||
| 246 | i--; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | return -EIO; | ||
| 251 | } | ||
| 252 | |||
| 253 | static void deallocate_channel(struct fw_card *card, int irm_id, | ||
| 254 | int generation, int channel) | ||
| 255 | { | ||
| 256 | u32 mask; | ||
| 257 | u64 offset; | ||
| 258 | |||
| 259 | mask = channel < 32 ? 1 << channel : 1 << (channel - 32); | ||
| 260 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : | ||
| 261 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; | ||
| 262 | |||
| 263 | manage_channel(card, irm_id, generation, mask, offset, false); | ||
| 264 | } | ||
| 265 | |||
| 266 | /** | ||
| 267 | * fw_iso_resource_manage - Allocate or deallocate a channel and/or bandwidth | ||
| 268 | * | ||
| 269 | * In parameters: card, generation, channels_mask, bandwidth, allocate | ||
| 270 | * Out parameters: channel, bandwidth | ||
| 271 | * This function blocks (sleeps) during communication with the IRM. | ||
| 272 | * | ||
| 273 | * Allocates or deallocates at most one channel out of channels_mask. | ||
| 274 | * channels_mask is a bitfield with MSB for channel 63 and LSB for channel 0. | ||
| 275 | * (Note, the IRM's CHANNELS_AVAILABLE is a big-endian bitfield with MSB for | ||
| 276 | * channel 0 and LSB for channel 63.) | ||
| 277 | * Allocates or deallocates as many bandwidth allocation units as specified. | ||
| 278 | * | ||
| 279 | * Returns channel < 0 if no channel was allocated or deallocated. | ||
| 280 | * Returns bandwidth = 0 if no bandwidth was allocated or deallocated. | ||
| 281 | * | ||
| 282 | * If generation is stale, deallocations succeed but allocations fail with | ||
| 283 | * channel = -EAGAIN. | ||
| 284 | * | ||
| 285 | * If channel allocation fails, no bandwidth will be allocated either. | ||
| 286 | * If bandwidth allocation fails, no channel will be allocated either. | ||
| 287 | * But deallocations of channel and bandwidth are tried independently | ||
| 288 | * of each other's success. | ||
| 289 | */ | ||
| 290 | void fw_iso_resource_manage(struct fw_card *card, int generation, | ||
| 291 | u64 channels_mask, int *channel, int *bandwidth, | ||
| 292 | bool allocate) | ||
| 293 | { | ||
| 294 | u32 channels_hi = channels_mask; /* channels 31...0 */ | ||
| 295 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ | ||
| 296 | int irm_id, ret, c = -EINVAL; | ||
| 297 | |||
| 298 | spin_lock_irq(&card->lock); | ||
| 299 | irm_id = card->irm_node->node_id; | ||
| 300 | spin_unlock_irq(&card->lock); | ||
| 301 | |||
| 302 | if (channels_hi) | ||
| 303 | c = manage_channel(card, irm_id, generation, channels_hi, | ||
| 304 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); | ||
| 305 | if (channels_lo && c < 0) { | ||
| 306 | c = manage_channel(card, irm_id, generation, channels_lo, | ||
| 307 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); | ||
| 308 | if (c >= 0) | ||
| 309 | c += 32; | ||
| 310 | } | ||
| 311 | *channel = c; | ||
| 312 | |||
| 313 | if (allocate && channels_mask != 0 && c < 0) | ||
| 314 | *bandwidth = 0; | ||
| 315 | |||
| 316 | if (*bandwidth == 0) | ||
| 317 | return; | ||
| 318 | |||
| 319 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); | ||
| 320 | if (ret < 0) | ||
| 321 | *bandwidth = 0; | ||
| 322 | |||
| 323 | if (allocate && ret < 0 && c >= 0) { | ||
| 324 | deallocate_channel(card, irm_id, generation, c); | ||
| 325 | *channel = ret; | ||
| 326 | } | ||
| 327 | } | ||
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 6d19828a93a5..1180d0be0bb4 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
| @@ -205,6 +205,7 @@ struct fw_ohci { | |||
| 205 | 205 | ||
| 206 | u32 it_context_mask; | 206 | u32 it_context_mask; |
| 207 | struct iso_context *it_context_list; | 207 | struct iso_context *it_context_list; |
| 208 | u64 ir_context_channels; | ||
| 208 | u32 ir_context_mask; | 209 | u32 ir_context_mask; |
| 209 | struct iso_context *ir_context_list; | 210 | struct iso_context *ir_context_list; |
| 210 | }; | 211 | }; |
| @@ -441,9 +442,8 @@ static inline void flush_writes(const struct fw_ohci *ohci) | |||
| 441 | reg_read(ohci, OHCI1394_Version); | 442 | reg_read(ohci, OHCI1394_Version); |
| 442 | } | 443 | } |
| 443 | 444 | ||
| 444 | static int | 445 | static int ohci_update_phy_reg(struct fw_card *card, int addr, |
| 445 | ohci_update_phy_reg(struct fw_card *card, int addr, | 446 | int clear_bits, int set_bits) |
| 446 | int clear_bits, int set_bits) | ||
| 447 | { | 447 | { |
| 448 | struct fw_ohci *ohci = fw_ohci(card); | 448 | struct fw_ohci *ohci = fw_ohci(card); |
| 449 | u32 val, old; | 449 | u32 val, old; |
| @@ -658,8 +658,8 @@ static void ar_context_tasklet(unsigned long data) | |||
| 658 | } | 658 | } |
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | static int | 661 | static int ar_context_init(struct ar_context *ctx, |
| 662 | ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs) | 662 | struct fw_ohci *ohci, u32 regs) |
| 663 | { | 663 | { |
| 664 | struct ar_buffer ab; | 664 | struct ar_buffer ab; |
| 665 | 665 | ||
| @@ -690,8 +690,7 @@ static void ar_context_run(struct ar_context *ctx) | |||
| 690 | flush_writes(ctx->ohci); | 690 | flush_writes(ctx->ohci); |
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | static struct descriptor * | 693 | static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) |
| 694 | find_branch_descriptor(struct descriptor *d, int z) | ||
| 695 | { | 694 | { |
| 696 | int b, key; | 695 | int b, key; |
| 697 | 696 | ||
| @@ -751,8 +750,7 @@ static void context_tasklet(unsigned long data) | |||
| 751 | * Allocate a new buffer and add it to the list of free buffers for this | 750 | * Allocate a new buffer and add it to the list of free buffers for this |
| 752 | * context. Must be called with ohci->lock held. | 751 | * context. Must be called with ohci->lock held. |
| 753 | */ | 752 | */ |
| 754 | static int | 753 | static int context_add_buffer(struct context *ctx) |
| 755 | context_add_buffer(struct context *ctx) | ||
| 756 | { | 754 | { |
| 757 | struct descriptor_buffer *desc; | 755 | struct descriptor_buffer *desc; |
| 758 | dma_addr_t uninitialized_var(bus_addr); | 756 | dma_addr_t uninitialized_var(bus_addr); |
| @@ -781,9 +779,8 @@ context_add_buffer(struct context *ctx) | |||
| 781 | return 0; | 779 | return 0; |
| 782 | } | 780 | } |
| 783 | 781 | ||
| 784 | static int | 782 | static int context_init(struct context *ctx, struct fw_ohci *ohci, |
| 785 | context_init(struct context *ctx, struct fw_ohci *ohci, | 783 | u32 regs, descriptor_callback_t callback) |
| 786 | u32 regs, descriptor_callback_t callback) | ||
| 787 | { | 784 | { |
| 788 | ctx->ohci = ohci; | 785 | ctx->ohci = ohci; |
| 789 | ctx->regs = regs; | 786 | ctx->regs = regs; |
| @@ -814,8 +811,7 @@ context_init(struct context *ctx, struct fw_ohci *ohci, | |||
| 814 | return 0; | 811 | return 0; |
| 815 | } | 812 | } |
| 816 | 813 | ||
| 817 | static void | 814 | static void context_release(struct context *ctx) |
| 818 | context_release(struct context *ctx) | ||
| 819 | { | 815 | { |
| 820 | struct fw_card *card = &ctx->ohci->card; | 816 | struct fw_card *card = &ctx->ohci->card; |
| 821 | struct descriptor_buffer *desc, *tmp; | 817 | struct descriptor_buffer *desc, *tmp; |
| @@ -827,8 +823,8 @@ context_release(struct context *ctx) | |||
| 827 | } | 823 | } |
| 828 | 824 | ||
| 829 | /* Must be called with ohci->lock held */ | 825 | /* Must be called with ohci->lock held */ |
| 830 | static struct descriptor * | 826 | static struct descriptor *context_get_descriptors(struct context *ctx, |
| 831 | context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus) | 827 | int z, dma_addr_t *d_bus) |
| 832 | { | 828 | { |
| 833 | struct descriptor *d = NULL; | 829 | struct descriptor *d = NULL; |
| 834 | struct descriptor_buffer *desc = ctx->buffer_tail; | 830 | struct descriptor_buffer *desc = ctx->buffer_tail; |
| @@ -912,8 +908,8 @@ struct driver_data { | |||
| 912 | * Must always be called with the ochi->lock held to ensure proper | 908 | * Must always be called with the ochi->lock held to ensure proper |
| 913 | * generation handling and locking around packet queue manipulation. | 909 | * generation handling and locking around packet queue manipulation. |
| 914 | */ | 910 | */ |
| 915 | static int | 911 | static int at_context_queue_packet(struct context *ctx, |
| 916 | at_context_queue_packet(struct context *ctx, struct fw_packet *packet) | 912 | struct fw_packet *packet) |
| 917 | { | 913 | { |
| 918 | struct fw_ohci *ohci = ctx->ohci; | 914 | struct fw_ohci *ohci = ctx->ohci; |
| 919 | dma_addr_t d_bus, uninitialized_var(payload_bus); | 915 | dma_addr_t d_bus, uninitialized_var(payload_bus); |
| @@ -940,7 +936,9 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet) | |||
| 940 | */ | 936 | */ |
| 941 | 937 | ||
| 942 | header = (__le32 *) &d[1]; | 938 | header = (__le32 *) &d[1]; |
| 943 | if (packet->header_length > 8) { | 939 | switch (packet->header_length) { |
| 940 | case 16: | ||
| 941 | case 12: | ||
| 944 | header[0] = cpu_to_le32((packet->header[0] & 0xffff) | | 942 | header[0] = cpu_to_le32((packet->header[0] & 0xffff) | |
| 945 | (packet->speed << 16)); | 943 | (packet->speed << 16)); |
| 946 | header[1] = cpu_to_le32((packet->header[1] & 0xffff) | | 944 | header[1] = cpu_to_le32((packet->header[1] & 0xffff) | |
| @@ -954,12 +952,27 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet) | |||
| 954 | header[3] = (__force __le32) packet->header[3]; | 952 | header[3] = (__force __le32) packet->header[3]; |
| 955 | 953 | ||
| 956 | d[0].req_count = cpu_to_le16(packet->header_length); | 954 | d[0].req_count = cpu_to_le16(packet->header_length); |
| 957 | } else { | 955 | break; |
| 956 | |||
| 957 | case 8: | ||
| 958 | header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) | | 958 | header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) | |
| 959 | (packet->speed << 16)); | 959 | (packet->speed << 16)); |
| 960 | header[1] = cpu_to_le32(packet->header[0]); | 960 | header[1] = cpu_to_le32(packet->header[0]); |
| 961 | header[2] = cpu_to_le32(packet->header[1]); | 961 | header[2] = cpu_to_le32(packet->header[1]); |
| 962 | d[0].req_count = cpu_to_le16(12); | 962 | d[0].req_count = cpu_to_le16(12); |
| 963 | break; | ||
| 964 | |||
| 965 | case 4: | ||
| 966 | header[0] = cpu_to_le32((packet->header[0] & 0xffff) | | ||
| 967 | (packet->speed << 16)); | ||
| 968 | header[1] = cpu_to_le32(packet->header[0] & 0xffff0000); | ||
| 969 | d[0].req_count = cpu_to_le16(8); | ||
| 970 | break; | ||
| 971 | |||
| 972 | default: | ||
| 973 | /* BUG(); */ | ||
| 974 | packet->ack = RCODE_SEND_ERROR; | ||
| 975 | return -1; | ||
| 963 | } | 976 | } |
| 964 | 977 | ||
| 965 | driver_data = (struct driver_data *) &d[3]; | 978 | driver_data = (struct driver_data *) &d[3]; |
| @@ -1095,8 +1108,8 @@ static int handle_at_packet(struct context *context, | |||
| 1095 | #define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) | 1108 | #define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) |
| 1096 | #define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) | 1109 | #define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) |
| 1097 | 1110 | ||
| 1098 | static void | 1111 | static void handle_local_rom(struct fw_ohci *ohci, |
| 1099 | handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) | 1112 | struct fw_packet *packet, u32 csr) |
| 1100 | { | 1113 | { |
| 1101 | struct fw_packet response; | 1114 | struct fw_packet response; |
| 1102 | int tcode, length, i; | 1115 | int tcode, length, i; |
| @@ -1122,8 +1135,8 @@ handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) | |||
| 1122 | fw_core_handle_response(&ohci->card, &response); | 1135 | fw_core_handle_response(&ohci->card, &response); |
| 1123 | } | 1136 | } |
| 1124 | 1137 | ||
| 1125 | static void | 1138 | static void handle_local_lock(struct fw_ohci *ohci, |
| 1126 | handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) | 1139 | struct fw_packet *packet, u32 csr) |
| 1127 | { | 1140 | { |
| 1128 | struct fw_packet response; | 1141 | struct fw_packet response; |
| 1129 | int tcode, length, ext_tcode, sel; | 1142 | int tcode, length, ext_tcode, sel; |
| @@ -1164,8 +1177,7 @@ handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) | |||
| 1164 | fw_core_handle_response(&ohci->card, &response); | 1177 | fw_core_handle_response(&ohci->card, &response); |
| 1165 | } | 1178 | } |
| 1166 | 1179 | ||
| 1167 | static void | 1180 | static void handle_local_request(struct context *ctx, struct fw_packet *packet) |
| 1168 | handle_local_request(struct context *ctx, struct fw_packet *packet) | ||
| 1169 | { | 1181 | { |
| 1170 | u64 offset; | 1182 | u64 offset; |
| 1171 | u32 csr; | 1183 | u32 csr; |
| @@ -1205,11 +1217,10 @@ handle_local_request(struct context *ctx, struct fw_packet *packet) | |||
| 1205 | } | 1217 | } |
| 1206 | } | 1218 | } |
| 1207 | 1219 | ||
| 1208 | static void | 1220 | static void at_context_transmit(struct context *ctx, struct fw_packet *packet) |
| 1209 | at_context_transmit(struct context *ctx, struct fw_packet *packet) | ||
| 1210 | { | 1221 | { |
| 1211 | unsigned long flags; | 1222 | unsigned long flags; |
| 1212 | int retval; | 1223 | int ret; |
| 1213 | 1224 | ||
| 1214 | spin_lock_irqsave(&ctx->ohci->lock, flags); | 1225 | spin_lock_irqsave(&ctx->ohci->lock, flags); |
| 1215 | 1226 | ||
| @@ -1220,10 +1231,10 @@ at_context_transmit(struct context *ctx, struct fw_packet *packet) | |||
| 1220 | return; | 1231 | return; |
| 1221 | } | 1232 | } |
| 1222 | 1233 | ||
| 1223 | retval = at_context_queue_packet(ctx, packet); | 1234 | ret = at_context_queue_packet(ctx, packet); |
| 1224 | spin_unlock_irqrestore(&ctx->ohci->lock, flags); | 1235 | spin_unlock_irqrestore(&ctx->ohci->lock, flags); |
| 1225 | 1236 | ||
| 1226 | if (retval < 0) | 1237 | if (ret < 0) |
| 1227 | packet->callback(packet, &ctx->ohci->card, packet->ack); | 1238 | packet->callback(packet, &ctx->ohci->card, packet->ack); |
| 1228 | 1239 | ||
| 1229 | } | 1240 | } |
| @@ -1590,12 +1601,12 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) | |||
| 1590 | return 0; | 1601 | return 0; |
| 1591 | } | 1602 | } |
| 1592 | 1603 | ||
| 1593 | static int | 1604 | static int ohci_set_config_rom(struct fw_card *card, |
| 1594 | ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) | 1605 | u32 *config_rom, size_t length) |
| 1595 | { | 1606 | { |
| 1596 | struct fw_ohci *ohci; | 1607 | struct fw_ohci *ohci; |
| 1597 | unsigned long flags; | 1608 | unsigned long flags; |
| 1598 | int retval = -EBUSY; | 1609 | int ret = -EBUSY; |
| 1599 | __be32 *next_config_rom; | 1610 | __be32 *next_config_rom; |
| 1600 | dma_addr_t uninitialized_var(next_config_rom_bus); | 1611 | dma_addr_t uninitialized_var(next_config_rom_bus); |
| 1601 | 1612 | ||
| @@ -1649,7 +1660,7 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) | |||
| 1649 | 1660 | ||
| 1650 | reg_write(ohci, OHCI1394_ConfigROMmap, | 1661 | reg_write(ohci, OHCI1394_ConfigROMmap, |
| 1651 | ohci->next_config_rom_bus); | 1662 | ohci->next_config_rom_bus); |
| 1652 | retval = 0; | 1663 | ret = 0; |
| 1653 | } | 1664 | } |
| 1654 | 1665 | ||
| 1655 | spin_unlock_irqrestore(&ohci->lock, flags); | 1666 | spin_unlock_irqrestore(&ohci->lock, flags); |
| @@ -1661,13 +1672,13 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) | |||
| 1661 | * controller could need to access it before the bus reset | 1672 | * controller could need to access it before the bus reset |
| 1662 | * takes effect. | 1673 | * takes effect. |
| 1663 | */ | 1674 | */ |
| 1664 | if (retval == 0) | 1675 | if (ret == 0) |
| 1665 | fw_core_initiate_bus_reset(&ohci->card, 1); | 1676 | fw_core_initiate_bus_reset(&ohci->card, 1); |
| 1666 | else | 1677 | else |
| 1667 | dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, | 1678 | dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, |
| 1668 | next_config_rom, next_config_rom_bus); | 1679 | next_config_rom, next_config_rom_bus); |
| 1669 | 1680 | ||
| 1670 | return retval; | 1681 | return ret; |
| 1671 | } | 1682 | } |
| 1672 | 1683 | ||
| 1673 | static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) | 1684 | static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) |
| @@ -1689,7 +1700,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) | |||
| 1689 | struct fw_ohci *ohci = fw_ohci(card); | 1700 | struct fw_ohci *ohci = fw_ohci(card); |
| 1690 | struct context *ctx = &ohci->at_request_ctx; | 1701 | struct context *ctx = &ohci->at_request_ctx; |
| 1691 | struct driver_data *driver_data = packet->driver_data; | 1702 | struct driver_data *driver_data = packet->driver_data; |
| 1692 | int retval = -ENOENT; | 1703 | int ret = -ENOENT; |
| 1693 | 1704 | ||
| 1694 | tasklet_disable(&ctx->tasklet); | 1705 | tasklet_disable(&ctx->tasklet); |
| 1695 | 1706 | ||
| @@ -1704,23 +1715,22 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) | |||
| 1704 | driver_data->packet = NULL; | 1715 | driver_data->packet = NULL; |
| 1705 | packet->ack = RCODE_CANCELLED; | 1716 | packet->ack = RCODE_CANCELLED; |
| 1706 | packet->callback(packet, &ohci->card, packet->ack); | 1717 | packet->callback(packet, &ohci->card, packet->ack); |
| 1707 | retval = 0; | 1718 | ret = 0; |
| 1708 | |||
| 1709 | out: | 1719 | out: |
| 1710 | tasklet_enable(&ctx->tasklet); | 1720 | tasklet_enable(&ctx->tasklet); |
| 1711 | 1721 | ||
| 1712 | return retval; | 1722 | return ret; |
| 1713 | } | 1723 | } |
| 1714 | 1724 | ||
| 1715 | static int | 1725 | static int ohci_enable_phys_dma(struct fw_card *card, |
| 1716 | ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) | 1726 | int node_id, int generation) |
| 1717 | { | 1727 | { |
| 1718 | #ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA | 1728 | #ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA |
| 1719 | return 0; | 1729 | return 0; |
| 1720 | #else | 1730 | #else |
| 1721 | struct fw_ohci *ohci = fw_ohci(card); | 1731 | struct fw_ohci *ohci = fw_ohci(card); |
| 1722 | unsigned long flags; | 1732 | unsigned long flags; |
| 1723 | int n, retval = 0; | 1733 | int n, ret = 0; |
| 1724 | 1734 | ||
| 1725 | /* | 1735 | /* |
| 1726 | * FIXME: Make sure this bitmask is cleared when we clear the busReset | 1736 | * FIXME: Make sure this bitmask is cleared when we clear the busReset |
| @@ -1730,7 +1740,7 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) | |||
| 1730 | spin_lock_irqsave(&ohci->lock, flags); | 1740 | spin_lock_irqsave(&ohci->lock, flags); |
| 1731 | 1741 | ||
| 1732 | if (ohci->generation != generation) { | 1742 | if (ohci->generation != generation) { |
| 1733 | retval = -ESTALE; | 1743 | ret = -ESTALE; |
| 1734 | goto out; | 1744 | goto out; |
| 1735 | } | 1745 | } |
| 1736 | 1746 | ||
| @@ -1748,12 +1758,12 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) | |||
| 1748 | flush_writes(ohci); | 1758 | flush_writes(ohci); |
| 1749 | out: | 1759 | out: |
| 1750 | spin_unlock_irqrestore(&ohci->lock, flags); | 1760 | spin_unlock_irqrestore(&ohci->lock, flags); |
| 1751 | return retval; | 1761 | |
| 1762 | return ret; | ||
| 1752 | #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ | 1763 | #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ |
| 1753 | } | 1764 | } |
| 1754 | 1765 | ||
| 1755 | static u64 | 1766 | static u64 ohci_get_bus_time(struct fw_card *card) |
| 1756 | ohci_get_bus_time(struct fw_card *card) | ||
| 1757 | { | 1767 | { |
| 1758 | struct fw_ohci *ohci = fw_ohci(card); | 1768 | struct fw_ohci *ohci = fw_ohci(card); |
| 1759 | u32 cycle_time; | 1769 | u32 cycle_time; |
| @@ -1765,6 +1775,28 @@ ohci_get_bus_time(struct fw_card *card) | |||
| 1765 | return bus_time; | 1775 | return bus_time; |
| 1766 | } | 1776 | } |
| 1767 | 1777 | ||
| 1778 | static void copy_iso_headers(struct iso_context *ctx, void *p) | ||
| 1779 | { | ||
| 1780 | int i = ctx->header_length; | ||
| 1781 | |||
| 1782 | if (i + ctx->base.header_size > PAGE_SIZE) | ||
| 1783 | return; | ||
| 1784 | |||
| 1785 | /* | ||
| 1786 | * The iso header is byteswapped to little endian by | ||
| 1787 | * the controller, but the remaining header quadlets | ||
| 1788 | * are big endian. We want to present all the headers | ||
| 1789 | * as big endian, so we have to swap the first quadlet. | ||
| 1790 | */ | ||
| 1791 | if (ctx->base.header_size > 0) | ||
| 1792 | *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); | ||
| 1793 | if (ctx->base.header_size > 4) | ||
| 1794 | *(u32 *) (ctx->header + i + 4) = __swab32(*(u32 *) p); | ||
| 1795 | if (ctx->base.header_size > 8) | ||
| 1796 | memcpy(ctx->header + i + 8, p + 8, ctx->base.header_size - 8); | ||
| 1797 | ctx->header_length += ctx->base.header_size; | ||
| 1798 | } | ||
| 1799 | |||
| 1768 | static int handle_ir_dualbuffer_packet(struct context *context, | 1800 | static int handle_ir_dualbuffer_packet(struct context *context, |
| 1769 | struct descriptor *d, | 1801 | struct descriptor *d, |
| 1770 | struct descriptor *last) | 1802 | struct descriptor *last) |
| @@ -1775,7 +1807,6 @@ static int handle_ir_dualbuffer_packet(struct context *context, | |||
| 1775 | __le32 *ir_header; | 1807 | __le32 *ir_header; |
| 1776 | size_t header_length; | 1808 | size_t header_length; |
| 1777 | void *p, *end; | 1809 | void *p, *end; |
| 1778 | int i; | ||
| 1779 | 1810 | ||
| 1780 | if (db->first_res_count != 0 && db->second_res_count != 0) { | 1811 | if (db->first_res_count != 0 && db->second_res_count != 0) { |
| 1781 | if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) { | 1812 | if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) { |
| @@ -1788,25 +1819,14 @@ static int handle_ir_dualbuffer_packet(struct context *context, | |||
| 1788 | header_length = le16_to_cpu(db->first_req_count) - | 1819 | header_length = le16_to_cpu(db->first_req_count) - |
| 1789 | le16_to_cpu(db->first_res_count); | 1820 | le16_to_cpu(db->first_res_count); |
| 1790 | 1821 | ||
| 1791 | i = ctx->header_length; | ||
| 1792 | p = db + 1; | 1822 | p = db + 1; |
| 1793 | end = p + header_length; | 1823 | end = p + header_length; |
| 1794 | while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { | 1824 | while (p < end) { |
| 1795 | /* | 1825 | copy_iso_headers(ctx, p); |
| 1796 | * The iso header is byteswapped to little endian by | ||
| 1797 | * the controller, but the remaining header quadlets | ||
| 1798 | * are big endian. We want to present all the headers | ||
| 1799 | * as big endian, so we have to swap the first | ||
| 1800 | * quadlet. | ||
| 1801 | */ | ||
| 1802 | *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); | ||
| 1803 | memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); | ||
| 1804 | i += ctx->base.header_size; | ||
| 1805 | ctx->excess_bytes += | 1826 | ctx->excess_bytes += |
| 1806 | (le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff; | 1827 | (le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff; |
| 1807 | p += ctx->base.header_size + 4; | 1828 | p += max(ctx->base.header_size, (size_t)8); |
| 1808 | } | 1829 | } |
| 1809 | ctx->header_length = i; | ||
| 1810 | 1830 | ||
| 1811 | ctx->excess_bytes -= le16_to_cpu(db->second_req_count) - | 1831 | ctx->excess_bytes -= le16_to_cpu(db->second_req_count) - |
| 1812 | le16_to_cpu(db->second_res_count); | 1832 | le16_to_cpu(db->second_res_count); |
| @@ -1832,7 +1852,6 @@ static int handle_ir_packet_per_buffer(struct context *context, | |||
| 1832 | struct descriptor *pd; | 1852 | struct descriptor *pd; |
| 1833 | __le32 *ir_header; | 1853 | __le32 *ir_header; |
| 1834 | void *p; | 1854 | void *p; |
| 1835 | int i; | ||
| 1836 | 1855 | ||
| 1837 | for (pd = d; pd <= last; pd++) { | 1856 | for (pd = d; pd <= last; pd++) { |
| 1838 | if (pd->transfer_status) | 1857 | if (pd->transfer_status) |
| @@ -1842,21 +1861,8 @@ static int handle_ir_packet_per_buffer(struct context *context, | |||
| 1842 | /* Descriptor(s) not done yet, stop iteration */ | 1861 | /* Descriptor(s) not done yet, stop iteration */ |
| 1843 | return 0; | 1862 | return 0; |
| 1844 | 1863 | ||
| 1845 | i = ctx->header_length; | 1864 | p = last + 1; |
| 1846 | p = last + 1; | 1865 | copy_iso_headers(ctx, p); |
| 1847 | |||
| 1848 | if (ctx->base.header_size > 0 && | ||
| 1849 | i + ctx->base.header_size <= PAGE_SIZE) { | ||
| 1850 | /* | ||
| 1851 | * The iso header is byteswapped to little endian by | ||
| 1852 | * the controller, but the remaining header quadlets | ||
| 1853 | * are big endian. We want to present all the headers | ||
| 1854 | * as big endian, so we have to swap the first quadlet. | ||
| 1855 | */ | ||
| 1856 | *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); | ||
| 1857 | memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); | ||
| 1858 | ctx->header_length += ctx->base.header_size; | ||
| 1859 | } | ||
| 1860 | 1866 | ||
| 1861 | if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) { | 1867 | if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) { |
| 1862 | ir_header = (__le32 *) p; | 1868 | ir_header = (__le32 *) p; |
| @@ -1888,21 +1894,24 @@ static int handle_it_packet(struct context *context, | |||
| 1888 | return 1; | 1894 | return 1; |
| 1889 | } | 1895 | } |
| 1890 | 1896 | ||
| 1891 | static struct fw_iso_context * | 1897 | static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, |
| 1892 | ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) | 1898 | int type, int channel, size_t header_size) |
| 1893 | { | 1899 | { |
| 1894 | struct fw_ohci *ohci = fw_ohci(card); | 1900 | struct fw_ohci *ohci = fw_ohci(card); |
| 1895 | struct iso_context *ctx, *list; | 1901 | struct iso_context *ctx, *list; |
| 1896 | descriptor_callback_t callback; | 1902 | descriptor_callback_t callback; |
| 1903 | u64 *channels, dont_care = ~0ULL; | ||
| 1897 | u32 *mask, regs; | 1904 | u32 *mask, regs; |
| 1898 | unsigned long flags; | 1905 | unsigned long flags; |
| 1899 | int index, retval = -ENOMEM; | 1906 | int index, ret = -ENOMEM; |
| 1900 | 1907 | ||
| 1901 | if (type == FW_ISO_CONTEXT_TRANSMIT) { | 1908 | if (type == FW_ISO_CONTEXT_TRANSMIT) { |
| 1909 | channels = &dont_care; | ||
| 1902 | mask = &ohci->it_context_mask; | 1910 | mask = &ohci->it_context_mask; |
| 1903 | list = ohci->it_context_list; | 1911 | list = ohci->it_context_list; |
| 1904 | callback = handle_it_packet; | 1912 | callback = handle_it_packet; |
| 1905 | } else { | 1913 | } else { |
| 1914 | channels = &ohci->ir_context_channels; | ||
| 1906 | mask = &ohci->ir_context_mask; | 1915 | mask = &ohci->ir_context_mask; |
| 1907 | list = ohci->ir_context_list; | 1916 | list = ohci->ir_context_list; |
| 1908 | if (ohci->use_dualbuffer) | 1917 | if (ohci->use_dualbuffer) |
| @@ -1912,9 +1921,11 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) | |||
| 1912 | } | 1921 | } |
| 1913 | 1922 | ||
| 1914 | spin_lock_irqsave(&ohci->lock, flags); | 1923 | spin_lock_irqsave(&ohci->lock, flags); |
| 1915 | index = ffs(*mask) - 1; | 1924 | index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1; |
| 1916 | if (index >= 0) | 1925 | if (index >= 0) { |
| 1926 | *channels &= ~(1ULL << channel); | ||
| 1917 | *mask &= ~(1 << index); | 1927 | *mask &= ~(1 << index); |
| 1928 | } | ||
| 1918 | spin_unlock_irqrestore(&ohci->lock, flags); | 1929 | spin_unlock_irqrestore(&ohci->lock, flags); |
| 1919 | 1930 | ||
| 1920 | if (index < 0) | 1931 | if (index < 0) |
| @@ -1932,8 +1943,8 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) | |||
| 1932 | if (ctx->header == NULL) | 1943 | if (ctx->header == NULL) |
| 1933 | goto out; | 1944 | goto out; |
| 1934 | 1945 | ||
| 1935 | retval = context_init(&ctx->context, ohci, regs, callback); | 1946 | ret = context_init(&ctx->context, ohci, regs, callback); |
| 1936 | if (retval < 0) | 1947 | if (ret < 0) |
| 1937 | goto out_with_header; | 1948 | goto out_with_header; |
| 1938 | 1949 | ||
| 1939 | return &ctx->base; | 1950 | return &ctx->base; |
| @@ -1945,7 +1956,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) | |||
| 1945 | *mask |= 1 << index; | 1956 | *mask |= 1 << index; |
| 1946 | spin_unlock_irqrestore(&ohci->lock, flags); | 1957 | spin_unlock_irqrestore(&ohci->lock, flags); |
| 1947 | 1958 | ||
| 1948 | return ERR_PTR(retval); | 1959 | return ERR_PTR(ret); |
| 1949 | } | 1960 | } |
| 1950 | 1961 | ||
| 1951 | static int ohci_start_iso(struct fw_iso_context *base, | 1962 | static int ohci_start_iso(struct fw_iso_context *base, |
| @@ -2024,16 +2035,16 @@ static void ohci_free_iso_context(struct fw_iso_context *base) | |||
| 2024 | } else { | 2035 | } else { |
| 2025 | index = ctx - ohci->ir_context_list; | 2036 | index = ctx - ohci->ir_context_list; |
| 2026 | ohci->ir_context_mask |= 1 << index; | 2037 | ohci->ir_context_mask |= 1 << index; |
| 2038 | ohci->ir_context_channels |= 1ULL << base->channel; | ||
| 2027 | } | 2039 | } |
| 2028 | 2040 | ||
| 2029 | spin_unlock_irqrestore(&ohci->lock, flags); | 2041 | spin_unlock_irqrestore(&ohci->lock, flags); |
| 2030 | } | 2042 | } |
| 2031 | 2043 | ||
| 2032 | static int | 2044 | static int ohci_queue_iso_transmit(struct fw_iso_context *base, |
| 2033 | ohci_queue_iso_transmit(struct fw_iso_context *base, | 2045 | struct fw_iso_packet *packet, |
| 2034 | struct fw_iso_packet *packet, | 2046 | struct fw_iso_buffer *buffer, |
| 2035 | struct fw_iso_buffer *buffer, | 2047 | unsigned long payload) |
| 2036 | unsigned long payload) | ||
| 2037 | { | 2048 | { |
| 2038 | struct iso_context *ctx = container_of(base, struct iso_context, base); | 2049 | struct iso_context *ctx = container_of(base, struct iso_context, base); |
| 2039 | struct descriptor *d, *last, *pd; | 2050 | struct descriptor *d, *last, *pd; |
| @@ -2128,11 +2139,10 @@ ohci_queue_iso_transmit(struct fw_iso_context *base, | |||
| 2128 | return 0; | 2139 | return 0; |
| 2129 | } | 2140 | } |
| 2130 | 2141 | ||
| 2131 | static int | 2142 | static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, |
| 2132 | ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, | 2143 | struct fw_iso_packet *packet, |
| 2133 | struct fw_iso_packet *packet, | 2144 | struct fw_iso_buffer *buffer, |
| 2134 | struct fw_iso_buffer *buffer, | 2145 | unsigned long payload) |
| 2135 | unsigned long payload) | ||
| 2136 | { | 2146 | { |
| 2137 | struct iso_context *ctx = container_of(base, struct iso_context, base); | 2147 | struct iso_context *ctx = container_of(base, struct iso_context, base); |
| 2138 | struct db_descriptor *db = NULL; | 2148 | struct db_descriptor *db = NULL; |
| @@ -2151,11 +2161,11 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, | |||
| 2151 | z = 2; | 2161 | z = 2; |
| 2152 | 2162 | ||
| 2153 | /* | 2163 | /* |
| 2154 | * The OHCI controller puts the status word in the header | 2164 | * The OHCI controller puts the isochronous header and trailer in the |
| 2155 | * buffer too, so we need 4 extra bytes per packet. | 2165 | * buffer, so we need at least 8 bytes. |
| 2156 | */ | 2166 | */ |
| 2157 | packet_count = p->header_length / ctx->base.header_size; | 2167 | packet_count = p->header_length / ctx->base.header_size; |
| 2158 | header_size = packet_count * (ctx->base.header_size + 4); | 2168 | header_size = packet_count * max(ctx->base.header_size, (size_t)8); |
| 2159 | 2169 | ||
| 2160 | /* Get header size in number of descriptors. */ | 2170 | /* Get header size in number of descriptors. */ |
| 2161 | header_z = DIV_ROUND_UP(header_size, sizeof(*d)); | 2171 | header_z = DIV_ROUND_UP(header_size, sizeof(*d)); |
| @@ -2173,7 +2183,8 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, | |||
| 2173 | db = (struct db_descriptor *) d; | 2183 | db = (struct db_descriptor *) d; |
| 2174 | db->control = cpu_to_le16(DESCRIPTOR_STATUS | | 2184 | db->control = cpu_to_le16(DESCRIPTOR_STATUS | |
| 2175 | DESCRIPTOR_BRANCH_ALWAYS); | 2185 | DESCRIPTOR_BRANCH_ALWAYS); |
| 2176 | db->first_size = cpu_to_le16(ctx->base.header_size + 4); | 2186 | db->first_size = |
| 2187 | cpu_to_le16(max(ctx->base.header_size, (size_t)8)); | ||
| 2177 | if (p->skip && rest == p->payload_length) { | 2188 | if (p->skip && rest == p->payload_length) { |
| 2178 | db->control |= cpu_to_le16(DESCRIPTOR_WAIT); | 2189 | db->control |= cpu_to_le16(DESCRIPTOR_WAIT); |
| 2179 | db->first_req_count = db->first_size; | 2190 | db->first_req_count = db->first_size; |
| @@ -2208,11 +2219,10 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, | |||
| 2208 | return 0; | 2219 | return 0; |
| 2209 | } | 2220 | } |
| 2210 | 2221 | ||
| 2211 | static int | 2222 | static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, |
| 2212 | ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, | 2223 | struct fw_iso_packet *packet, |
| 2213 | struct fw_iso_packet *packet, | 2224 | struct fw_iso_buffer *buffer, |
| 2214 | struct fw_iso_buffer *buffer, | 2225 | unsigned long payload) |
| 2215 | unsigned long payload) | ||
| 2216 | { | 2226 | { |
| 2217 | struct iso_context *ctx = container_of(base, struct iso_context, base); | 2227 | struct iso_context *ctx = container_of(base, struct iso_context, base); |
| 2218 | struct descriptor *d = NULL, *pd = NULL; | 2228 | struct descriptor *d = NULL, *pd = NULL; |
| @@ -2223,11 +2233,11 @@ ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, | |||
| 2223 | int page, offset, packet_count, header_size, payload_per_buffer; | 2233 | int page, offset, packet_count, header_size, payload_per_buffer; |
| 2224 | 2234 | ||
| 2225 | /* | 2235 | /* |
| 2226 | * The OHCI controller puts the status word in the | 2236 | * The OHCI controller puts the isochronous header and trailer in the |
| 2227 | * buffer too, so we need 4 extra bytes per packet. | 2237 | * buffer, so we need at least 8 bytes. |
| 2228 | */ | 2238 | */ |
| 2229 | packet_count = p->header_length / ctx->base.header_size; | 2239 | packet_count = p->header_length / ctx->base.header_size; |
| 2230 | header_size = ctx->base.header_size + 4; | 2240 | header_size = max(ctx->base.header_size, (size_t)8); |
| 2231 | 2241 | ||
| 2232 | /* Get header size in number of descriptors. */ | 2242 | /* Get header size in number of descriptors. */ |
| 2233 | header_z = DIV_ROUND_UP(header_size, sizeof(*d)); | 2243 | header_z = DIV_ROUND_UP(header_size, sizeof(*d)); |
| @@ -2286,29 +2296,27 @@ ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, | |||
| 2286 | return 0; | 2296 | return 0; |
| 2287 | } | 2297 | } |
| 2288 | 2298 | ||
| 2289 | static int | 2299 | static int ohci_queue_iso(struct fw_iso_context *base, |
| 2290 | ohci_queue_iso(struct fw_iso_context *base, | 2300 | struct fw_iso_packet *packet, |
| 2291 | struct fw_iso_packet *packet, | 2301 | struct fw_iso_buffer *buffer, |
| 2292 | struct fw_iso_buffer *buffer, | 2302 | unsigned long payload) |
| 2293 | unsigned long payload) | ||
| 2294 | { | 2303 | { |
| 2295 | struct iso_context *ctx = container_of(base, struct iso_context, base); | 2304 | struct iso_context *ctx = container_of(base, struct iso_context, base); |
| 2296 | unsigned long flags; | 2305 | unsigned long flags; |
| 2297 | int retval; | 2306 | int ret; |
| 2298 | 2307 | ||
| 2299 | spin_lock_irqsave(&ctx->context.ohci->lock, flags); | 2308 | spin_lock_irqsave(&ctx->context.ohci->lock, flags); |
| 2300 | if (base->type == FW_ISO_CONTEXT_TRANSMIT) | 2309 | if (base->type == FW_ISO_CONTEXT_TRANSMIT) |
| 2301 | retval = ohci_queue_iso_transmit(base, packet, buffer, payload); | 2310 | ret = ohci_queue_iso_transmit(base, packet, buffer, payload); |
| 2302 | else if (ctx->context.ohci->use_dualbuffer) | 2311 | else if (ctx->context.ohci->use_dualbuffer) |
| 2303 | retval = ohci_queue_iso_receive_dualbuffer(base, packet, | 2312 | ret = ohci_queue_iso_receive_dualbuffer(base, packet, |
| 2304 | buffer, payload); | 2313 | buffer, payload); |
| 2305 | else | 2314 | else |
| 2306 | retval = ohci_queue_iso_receive_packet_per_buffer(base, packet, | 2315 | ret = ohci_queue_iso_receive_packet_per_buffer(base, packet, |
| 2307 | buffer, | 2316 | buffer, payload); |
| 2308 | payload); | ||
| 2309 | spin_unlock_irqrestore(&ctx->context.ohci->lock, flags); | 2317 | spin_unlock_irqrestore(&ctx->context.ohci->lock, flags); |
| 2310 | 2318 | ||
| 2311 | return retval; | 2319 | return ret; |
| 2312 | } | 2320 | } |
| 2313 | 2321 | ||
| 2314 | static const struct fw_card_driver ohci_driver = { | 2322 | static const struct fw_card_driver ohci_driver = { |
| @@ -2357,8 +2365,8 @@ static void ohci_pmac_off(struct pci_dev *dev) | |||
| 2357 | #define ohci_pmac_off(dev) | 2365 | #define ohci_pmac_off(dev) |
| 2358 | #endif /* CONFIG_PPC_PMAC */ | 2366 | #endif /* CONFIG_PPC_PMAC */ |
| 2359 | 2367 | ||
| 2360 | static int __devinit | 2368 | static int __devinit pci_probe(struct pci_dev *dev, |
| 2361 | pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) | 2369 | const struct pci_device_id *ent) |
| 2362 | { | 2370 | { |
| 2363 | struct fw_ohci *ohci; | 2371 | struct fw_ohci *ohci; |
| 2364 | u32 bus_options, max_receive, link_speed, version; | 2372 | u32 bus_options, max_receive, link_speed, version; |
| @@ -2440,6 +2448,7 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
| 2440 | ohci->it_context_list = kzalloc(size, GFP_KERNEL); | 2448 | ohci->it_context_list = kzalloc(size, GFP_KERNEL); |
| 2441 | 2449 | ||
| 2442 | reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); | 2450 | reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); |
| 2451 | ohci->ir_context_channels = ~0ULL; | ||
| 2443 | ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); | 2452 | ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); |
| 2444 | reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); | 2453 | reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); |
| 2445 | size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask); | 2454 | size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask); |
| @@ -2467,11 +2476,12 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
| 2467 | reg_read(ohci, OHCI1394_GUIDLo); | 2476 | reg_read(ohci, OHCI1394_GUIDLo); |
| 2468 | 2477 | ||
| 2469 | err = fw_card_add(&ohci->card, max_receive, link_speed, guid); | 2478 | err = fw_card_add(&ohci->card, max_receive, link_speed, guid); |
| 2470 | if (err < 0) | 2479 | if (err) |
| 2471 | goto fail_self_id; | 2480 | goto fail_self_id; |
| 2472 | 2481 | ||
| 2473 | fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", | 2482 | fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", |
| 2474 | dev_name(&dev->dev), version >> 16, version & 0xff); | 2483 | dev_name(&dev->dev), version >> 16, version & 0xff); |
| 2484 | |||
| 2475 | return 0; | 2485 | return 0; |
| 2476 | 2486 | ||
| 2477 | fail_self_id: | 2487 | fail_self_id: |
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index c71c4419d9e8..2bcf51557c72 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c | |||
| @@ -392,20 +392,18 @@ static const struct { | |||
| 392 | } | 392 | } |
| 393 | }; | 393 | }; |
| 394 | 394 | ||
| 395 | static void | 395 | static void free_orb(struct kref *kref) |
| 396 | free_orb(struct kref *kref) | ||
| 397 | { | 396 | { |
| 398 | struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref); | 397 | struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref); |
| 399 | 398 | ||
| 400 | kfree(orb); | 399 | kfree(orb); |
| 401 | } | 400 | } |
| 402 | 401 | ||
| 403 | static void | 402 | static void sbp2_status_write(struct fw_card *card, struct fw_request *request, |
| 404 | sbp2_status_write(struct fw_card *card, struct fw_request *request, | 403 | int tcode, int destination, int source, |
| 405 | int tcode, int destination, int source, | 404 | int generation, int speed, |
| 406 | int generation, int speed, | 405 | unsigned long long offset, |
| 407 | unsigned long long offset, | 406 | void *payload, size_t length, void *callback_data) |
| 408 | void *payload, size_t length, void *callback_data) | ||
| 409 | { | 407 | { |
| 410 | struct sbp2_logical_unit *lu = callback_data; | 408 | struct sbp2_logical_unit *lu = callback_data; |
| 411 | struct sbp2_orb *orb; | 409 | struct sbp2_orb *orb; |
| @@ -451,9 +449,8 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request, | |||
| 451 | fw_send_response(card, request, RCODE_COMPLETE); | 449 | fw_send_response(card, request, RCODE_COMPLETE); |
| 452 | } | 450 | } |
| 453 | 451 | ||
| 454 | static void | 452 | static void complete_transaction(struct fw_card *card, int rcode, |
| 455 | complete_transaction(struct fw_card *card, int rcode, | 453 | void *payload, size_t length, void *data) |
| 456 | void *payload, size_t length, void *data) | ||
| 457 | { | 454 | { |
| 458 | struct sbp2_orb *orb = data; | 455 | struct sbp2_orb *orb = data; |
| 459 | unsigned long flags; | 456 | unsigned long flags; |
| @@ -482,9 +479,8 @@ complete_transaction(struct fw_card *card, int rcode, | |||
| 482 | kref_put(&orb->kref, free_orb); | 479 | kref_put(&orb->kref, free_orb); |
| 483 | } | 480 | } |
| 484 | 481 | ||
| 485 | static void | 482 | static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, |
| 486 | sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, | 483 | int node_id, int generation, u64 offset) |
| 487 | int node_id, int generation, u64 offset) | ||
| 488 | { | 484 | { |
| 489 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); | 485 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); |
| 490 | unsigned long flags; | 486 | unsigned long flags; |
| @@ -531,8 +527,8 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) | |||
| 531 | return retval; | 527 | return retval; |
| 532 | } | 528 | } |
| 533 | 529 | ||
| 534 | static void | 530 | static void complete_management_orb(struct sbp2_orb *base_orb, |
| 535 | complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | 531 | struct sbp2_status *status) |
| 536 | { | 532 | { |
| 537 | struct sbp2_management_orb *orb = | 533 | struct sbp2_management_orb *orb = |
| 538 | container_of(base_orb, struct sbp2_management_orb, base); | 534 | container_of(base_orb, struct sbp2_management_orb, base); |
| @@ -542,10 +538,9 @@ complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | |||
| 542 | complete(&orb->done); | 538 | complete(&orb->done); |
| 543 | } | 539 | } |
| 544 | 540 | ||
| 545 | static int | 541 | static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, |
| 546 | sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, | 542 | int generation, int function, |
| 547 | int generation, int function, int lun_or_login_id, | 543 | int lun_or_login_id, void *response) |
| 548 | void *response) | ||
| 549 | { | 544 | { |
| 550 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); | 545 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); |
| 551 | struct sbp2_management_orb *orb; | 546 | struct sbp2_management_orb *orb; |
| @@ -652,9 +647,8 @@ static void sbp2_agent_reset(struct sbp2_logical_unit *lu) | |||
| 652 | &d, sizeof(d)); | 647 | &d, sizeof(d)); |
| 653 | } | 648 | } |
| 654 | 649 | ||
| 655 | static void | 650 | static void complete_agent_reset_write_no_wait(struct fw_card *card, |
| 656 | complete_agent_reset_write_no_wait(struct fw_card *card, int rcode, | 651 | int rcode, void *payload, size_t length, void *data) |
| 657 | void *payload, size_t length, void *data) | ||
| 658 | { | 652 | { |
| 659 | kfree(data); | 653 | kfree(data); |
| 660 | } | 654 | } |
| @@ -1299,8 +1293,7 @@ static void sbp2_unmap_scatterlist(struct device *card_device, | |||
| 1299 | sizeof(orb->page_table), DMA_TO_DEVICE); | 1293 | sizeof(orb->page_table), DMA_TO_DEVICE); |
| 1300 | } | 1294 | } |
| 1301 | 1295 | ||
| 1302 | static unsigned int | 1296 | static unsigned int sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) |
| 1303 | sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) | ||
| 1304 | { | 1297 | { |
| 1305 | int sam_status; | 1298 | int sam_status; |
| 1306 | 1299 | ||
| @@ -1337,8 +1330,8 @@ sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) | |||
| 1337 | } | 1330 | } |
| 1338 | } | 1331 | } |
| 1339 | 1332 | ||
| 1340 | static void | 1333 | static void complete_command_orb(struct sbp2_orb *base_orb, |
| 1341 | complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | 1334 | struct sbp2_status *status) |
| 1342 | { | 1335 | { |
| 1343 | struct sbp2_command_orb *orb = | 1336 | struct sbp2_command_orb *orb = |
| 1344 | container_of(base_orb, struct sbp2_command_orb, base); | 1337 | container_of(base_orb, struct sbp2_command_orb, base); |
| @@ -1384,9 +1377,8 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | |||
| 1384 | orb->done(orb->cmd); | 1377 | orb->done(orb->cmd); |
| 1385 | } | 1378 | } |
| 1386 | 1379 | ||
| 1387 | static int | 1380 | static int sbp2_map_scatterlist(struct sbp2_command_orb *orb, |
| 1388 | sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, | 1381 | struct fw_device *device, struct sbp2_logical_unit *lu) |
| 1389 | struct sbp2_logical_unit *lu) | ||
| 1390 | { | 1382 | { |
| 1391 | struct scatterlist *sg = scsi_sglist(orb->cmd); | 1383 | struct scatterlist *sg = scsi_sglist(orb->cmd); |
| 1392 | int i, n; | 1384 | int i, n; |
| @@ -1584,9 +1576,8 @@ static int sbp2_scsi_abort(struct scsi_cmnd *cmd) | |||
| 1584 | * This is the concatenation of target port identifier and logical unit | 1576 | * This is the concatenation of target port identifier and logical unit |
| 1585 | * identifier as per SAM-2...SAM-4 annex A. | 1577 | * identifier as per SAM-2...SAM-4 annex A. |
| 1586 | */ | 1578 | */ |
| 1587 | static ssize_t | 1579 | static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, |
| 1588 | sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, | 1580 | struct device_attribute *attr, char *buf) |
| 1589 | char *buf) | ||
| 1590 | { | 1581 | { |
| 1591 | struct scsi_device *sdev = to_scsi_device(dev); | 1582 | struct scsi_device *sdev = to_scsi_device(dev); |
| 1592 | struct sbp2_logical_unit *lu; | 1583 | struct sbp2_logical_unit *lu; |
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 8dd6703b55cd..d0deecc4de93 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c | |||
| @@ -314,9 +314,8 @@ typedef void (*fw_node_callback_t)(struct fw_card * card, | |||
| 314 | struct fw_node * node, | 314 | struct fw_node * node, |
| 315 | struct fw_node * parent); | 315 | struct fw_node * parent); |
| 316 | 316 | ||
| 317 | static void | 317 | static void for_each_fw_node(struct fw_card *card, struct fw_node *root, |
| 318 | for_each_fw_node(struct fw_card *card, struct fw_node *root, | 318 | fw_node_callback_t callback) |
| 319 | fw_node_callback_t callback) | ||
| 320 | { | 319 | { |
| 321 | struct list_head list; | 320 | struct list_head list; |
| 322 | struct fw_node *node, *next, *child, *parent; | 321 | struct fw_node *node, *next, *child, *parent; |
| @@ -349,9 +348,8 @@ for_each_fw_node(struct fw_card *card, struct fw_node *root, | |||
| 349 | fw_node_put(node); | 348 | fw_node_put(node); |
| 350 | } | 349 | } |
| 351 | 350 | ||
| 352 | static void | 351 | static void report_lost_node(struct fw_card *card, |
| 353 | report_lost_node(struct fw_card *card, | 352 | struct fw_node *node, struct fw_node *parent) |
| 354 | struct fw_node *node, struct fw_node *parent) | ||
| 355 | { | 353 | { |
| 356 | fw_node_event(card, node, FW_NODE_DESTROYED); | 354 | fw_node_event(card, node, FW_NODE_DESTROYED); |
| 357 | fw_node_put(node); | 355 | fw_node_put(node); |
| @@ -360,9 +358,8 @@ report_lost_node(struct fw_card *card, | |||
| 360 | card->bm_retries = 0; | 358 | card->bm_retries = 0; |
| 361 | } | 359 | } |
| 362 | 360 | ||
| 363 | static void | 361 | static void report_found_node(struct fw_card *card, |
| 364 | report_found_node(struct fw_card *card, | 362 | struct fw_node *node, struct fw_node *parent) |
| 365 | struct fw_node *node, struct fw_node *parent) | ||
| 366 | { | 363 | { |
| 367 | int b_path = (node->phy_speed == SCODE_BETA); | 364 | int b_path = (node->phy_speed == SCODE_BETA); |
| 368 | 365 | ||
| @@ -415,8 +412,7 @@ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) | |||
| 415 | * found, lost or updated. Update the nodes in the card topology tree | 412 | * found, lost or updated. Update the nodes in the card topology tree |
| 416 | * as we go. | 413 | * as we go. |
| 417 | */ | 414 | */ |
| 418 | static void | 415 | static void update_tree(struct fw_card *card, struct fw_node *root) |
| 419 | update_tree(struct fw_card *card, struct fw_node *root) | ||
| 420 | { | 416 | { |
| 421 | struct list_head list0, list1; | 417 | struct list_head list0, list1; |
| 422 | struct fw_node *node0, *node1, *next1; | 418 | struct fw_node *node0, *node1, *next1; |
| @@ -497,8 +493,8 @@ update_tree(struct fw_card *card, struct fw_node *root) | |||
| 497 | } | 493 | } |
| 498 | } | 494 | } |
| 499 | 495 | ||
| 500 | static void | 496 | static void update_topology_map(struct fw_card *card, |
| 501 | update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) | 497 | u32 *self_ids, int self_id_count) |
| 502 | { | 498 | { |
| 503 | int node_count; | 499 | int node_count; |
| 504 | 500 | ||
| @@ -510,10 +506,8 @@ update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) | |||
| 510 | fw_compute_block_crc(card->topology_map); | 506 | fw_compute_block_crc(card->topology_map); |
| 511 | } | 507 | } |
| 512 | 508 | ||
| 513 | void | 509 | void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, |
| 514 | fw_core_handle_bus_reset(struct fw_card *card, | 510 | int self_id_count, u32 *self_ids) |
| 515 | int node_id, int generation, | ||
| 516 | int self_id_count, u32 * self_ids) | ||
| 517 | { | 511 | { |
| 518 | struct fw_node *local_node; | 512 | struct fw_node *local_node; |
| 519 | unsigned long flags; | 513 | unsigned long flags; |
| @@ -532,6 +526,7 @@ fw_core_handle_bus_reset(struct fw_card *card, | |||
| 532 | 526 | ||
| 533 | spin_lock_irqsave(&card->lock, flags); | 527 | spin_lock_irqsave(&card->lock, flags); |
| 534 | 528 | ||
| 529 | card->broadcast_channel_allocated = false; | ||
| 535 | card->node_id = node_id; | 530 | card->node_id = node_id; |
| 536 | /* | 531 | /* |
| 537 | * Update node_id before generation to prevent anybody from using | 532 | * Update node_id before generation to prevent anybody from using |
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index addb9f8ea776..3c497bb4fae4 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h | |||
| @@ -19,6 +19,11 @@ | |||
| 19 | #ifndef __fw_topology_h | 19 | #ifndef __fw_topology_h |
| 20 | #define __fw_topology_h | 20 | #define __fw_topology_h |
| 21 | 21 | ||
| 22 | #include <linux/list.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | |||
| 25 | #include <asm/atomic.h> | ||
| 26 | |||
| 22 | enum { | 27 | enum { |
| 23 | FW_NODE_CREATED, | 28 | FW_NODE_CREATED, |
| 24 | FW_NODE_UPDATED, | 29 | FW_NODE_UPDATED, |
| @@ -51,26 +56,22 @@ struct fw_node { | |||
| 51 | struct fw_node *ports[0]; | 56 | struct fw_node *ports[0]; |
| 52 | }; | 57 | }; |
| 53 | 58 | ||
| 54 | static inline struct fw_node * | 59 | static inline struct fw_node *fw_node_get(struct fw_node *node) |
| 55 | fw_node_get(struct fw_node *node) | ||
| 56 | { | 60 | { |
| 57 | atomic_inc(&node->ref_count); | 61 | atomic_inc(&node->ref_count); |
| 58 | 62 | ||
| 59 | return node; | 63 | return node; |
| 60 | } | 64 | } |
| 61 | 65 | ||
| 62 | static inline void | 66 | static inline void fw_node_put(struct fw_node *node) |
| 63 | fw_node_put(struct fw_node *node) | ||
| 64 | { | 67 | { |
| 65 | if (atomic_dec_and_test(&node->ref_count)) | 68 | if (atomic_dec_and_test(&node->ref_count)) |
| 66 | kfree(node); | 69 | kfree(node); |
| 67 | } | 70 | } |
| 68 | 71 | ||
| 69 | void | 72 | struct fw_card; |
| 70 | fw_destroy_nodes(struct fw_card *card); | 73 | void fw_destroy_nodes(struct fw_card *card); |
| 71 | |||
| 72 | int | ||
| 73 | fw_compute_block_crc(u32 *block); | ||
| 74 | 74 | ||
| 75 | int fw_compute_block_crc(u32 *block); | ||
| 75 | 76 | ||
| 76 | #endif /* __fw_topology_h */ | 77 | #endif /* __fw_topology_h */ |
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 699ac041f39a..283dac6d327d 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c | |||
| @@ -64,10 +64,8 @@ | |||
| 64 | #define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23)) | 64 | #define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23)) |
| 65 | #define PHY_IDENTIFIER(id) ((id) << 30) | 65 | #define PHY_IDENTIFIER(id) ((id) << 30) |
| 66 | 66 | ||
| 67 | static int | 67 | static int close_transaction(struct fw_transaction *transaction, |
| 68 | close_transaction(struct fw_transaction *transaction, | 68 | struct fw_card *card, int rcode) |
| 69 | struct fw_card *card, int rcode, | ||
| 70 | u32 *payload, size_t length) | ||
| 71 | { | 69 | { |
| 72 | struct fw_transaction *t; | 70 | struct fw_transaction *t; |
| 73 | unsigned long flags; | 71 | unsigned long flags; |
| @@ -83,7 +81,7 @@ close_transaction(struct fw_transaction *transaction, | |||
| 83 | spin_unlock_irqrestore(&card->lock, flags); | 81 | spin_unlock_irqrestore(&card->lock, flags); |
| 84 | 82 | ||
| 85 | if (&t->link != &card->transaction_list) { | 83 | if (&t->link != &card->transaction_list) { |
| 86 | t->callback(card, rcode, payload, length, t->callback_data); | 84 | t->callback(card, rcode, NULL, 0, t->callback_data); |
| 87 | return 0; | 85 | return 0; |
| 88 | } | 86 | } |
| 89 | 87 | ||
| @@ -94,9 +92,8 @@ close_transaction(struct fw_transaction *transaction, | |||
| 94 | * Only valid for transactions that are potentially pending (ie have | 92 | * Only valid for transactions that are potentially pending (ie have |
| 95 | * been sent). | 93 | * been sent). |
| 96 | */ | 94 | */ |
| 97 | int | 95 | int fw_cancel_transaction(struct fw_card *card, |
| 98 | fw_cancel_transaction(struct fw_card *card, | 96 | struct fw_transaction *transaction) |
| 99 | struct fw_transaction *transaction) | ||
| 100 | { | 97 | { |
| 101 | /* | 98 | /* |
| 102 | * Cancel the packet transmission if it's still queued. That | 99 | * Cancel the packet transmission if it's still queued. That |
| @@ -112,20 +109,19 @@ fw_cancel_transaction(struct fw_card *card, | |||
| 112 | * if the transaction is still pending and remove it in that case. | 109 | * if the transaction is still pending and remove it in that case. |
| 113 | */ | 110 | */ |
| 114 | 111 | ||
| 115 | return close_transaction(transaction, card, RCODE_CANCELLED, NULL, 0); | 112 | return close_transaction(transaction, card, RCODE_CANCELLED); |
| 116 | } | 113 | } |
| 117 | EXPORT_SYMBOL(fw_cancel_transaction); | 114 | EXPORT_SYMBOL(fw_cancel_transaction); |
| 118 | 115 | ||
| 119 | static void | 116 | static void transmit_complete_callback(struct fw_packet *packet, |
| 120 | transmit_complete_callback(struct fw_packet *packet, | 117 | struct fw_card *card, int status) |
| 121 | struct fw_card *card, int status) | ||
| 122 | { | 118 | { |
| 123 | struct fw_transaction *t = | 119 | struct fw_transaction *t = |
| 124 | container_of(packet, struct fw_transaction, packet); | 120 | container_of(packet, struct fw_transaction, packet); |
| 125 | 121 | ||
| 126 | switch (status) { | 122 | switch (status) { |
| 127 | case ACK_COMPLETE: | 123 | case ACK_COMPLETE: |
| 128 | close_transaction(t, card, RCODE_COMPLETE, NULL, 0); | 124 | close_transaction(t, card, RCODE_COMPLETE); |
| 129 | break; | 125 | break; |
| 130 | case ACK_PENDING: | 126 | case ACK_PENDING: |
| 131 | t->timestamp = packet->timestamp; | 127 | t->timestamp = packet->timestamp; |
| @@ -133,31 +129,42 @@ transmit_complete_callback(struct fw_packet *packet, | |||
| 133 | case ACK_BUSY_X: | 129 | case ACK_BUSY_X: |
| 134 | case ACK_BUSY_A: | 130 | case ACK_BUSY_A: |
| 135 | case ACK_BUSY_B: | 131 | case ACK_BUSY_B: |
| 136 | close_transaction(t, card, RCODE_BUSY, NULL, 0); | 132 | close_transaction(t, card, RCODE_BUSY); |
| 137 | break; | 133 | break; |
| 138 | case ACK_DATA_ERROR: | 134 | case ACK_DATA_ERROR: |
| 139 | close_transaction(t, card, RCODE_DATA_ERROR, NULL, 0); | 135 | close_transaction(t, card, RCODE_DATA_ERROR); |
| 140 | break; | 136 | break; |
| 141 | case ACK_TYPE_ERROR: | 137 | case ACK_TYPE_ERROR: |
| 142 | close_transaction(t, card, RCODE_TYPE_ERROR, NULL, 0); | 138 | close_transaction(t, card, RCODE_TYPE_ERROR); |
| 143 | break; | 139 | break; |
| 144 | default: | 140 | default: |
| 145 | /* | 141 | /* |
| 146 | * In this case the ack is really a juju specific | 142 | * In this case the ack is really a juju specific |
| 147 | * rcode, so just forward that to the callback. | 143 | * rcode, so just forward that to the callback. |
| 148 | */ | 144 | */ |
| 149 | close_transaction(t, card, status, NULL, 0); | 145 | close_transaction(t, card, status); |
| 150 | break; | 146 | break; |
| 151 | } | 147 | } |
| 152 | } | 148 | } |
| 153 | 149 | ||
| 154 | static void | 150 | static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, |
| 155 | fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, | ||
| 156 | int destination_id, int source_id, int generation, int speed, | 151 | int destination_id, int source_id, int generation, int speed, |
| 157 | unsigned long long offset, void *payload, size_t length) | 152 | unsigned long long offset, void *payload, size_t length) |
| 158 | { | 153 | { |
| 159 | int ext_tcode; | 154 | int ext_tcode; |
| 160 | 155 | ||
| 156 | if (tcode == TCODE_STREAM_DATA) { | ||
| 157 | packet->header[0] = | ||
| 158 | HEADER_DATA_LENGTH(length) | | ||
| 159 | destination_id | | ||
| 160 | HEADER_TCODE(TCODE_STREAM_DATA); | ||
| 161 | packet->header_length = 4; | ||
| 162 | packet->payload = payload; | ||
| 163 | packet->payload_length = length; | ||
| 164 | |||
| 165 | goto common; | ||
| 166 | } | ||
| 167 | |||
| 161 | if (tcode > 0x10) { | 168 | if (tcode > 0x10) { |
| 162 | ext_tcode = tcode & ~0x10; | 169 | ext_tcode = tcode & ~0x10; |
| 163 | tcode = TCODE_LOCK_REQUEST; | 170 | tcode = TCODE_LOCK_REQUEST; |
| @@ -204,7 +211,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, | |||
| 204 | packet->payload_length = 0; | 211 | packet->payload_length = 0; |
| 205 | break; | 212 | break; |
| 206 | } | 213 | } |
| 207 | 214 | common: | |
| 208 | packet->speed = speed; | 215 | packet->speed = speed; |
| 209 | packet->generation = generation; | 216 | packet->generation = generation; |
| 210 | packet->ack = 0; | 217 | packet->ack = 0; |
| @@ -246,13 +253,14 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, | |||
| 246 | * @param callback function to be called when the transaction is completed | 253 | * @param callback function to be called when the transaction is completed |
| 247 | * @param callback_data pointer to arbitrary data, which will be | 254 | * @param callback_data pointer to arbitrary data, which will be |
| 248 | * passed to the callback | 255 | * passed to the callback |
| 256 | * | ||
| 257 | * In case of asynchronous stream packets i.e. TCODE_STREAM_DATA, the caller | ||
| 258 | * needs to synthesize @destination_id with fw_stream_packet_destination_id(). | ||
| 249 | */ | 259 | */ |
| 250 | void | 260 | void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, |
| 251 | fw_send_request(struct fw_card *card, struct fw_transaction *t, | 261 | int destination_id, int generation, int speed, |
| 252 | int tcode, int destination_id, int generation, int speed, | 262 | unsigned long long offset, void *payload, size_t length, |
| 253 | unsigned long long offset, | 263 | fw_transaction_callback_t callback, void *callback_data) |
| 254 | void *payload, size_t length, | ||
| 255 | fw_transaction_callback_t callback, void *callback_data) | ||
| 256 | { | 264 | { |
| 257 | unsigned long flags; | 265 | unsigned long flags; |
| 258 | int tlabel; | 266 | int tlabel; |
| @@ -322,16 +330,16 @@ static void transaction_callback(struct fw_card *card, int rcode, | |||
| 322 | * Returns the RCODE. | 330 | * Returns the RCODE. |
| 323 | */ | 331 | */ |
| 324 | int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, | 332 | int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, |
| 325 | int generation, int speed, unsigned long long offset, | 333 | int generation, int speed, unsigned long long offset, |
| 326 | void *data, size_t length) | 334 | void *payload, size_t length) |
| 327 | { | 335 | { |
| 328 | struct transaction_callback_data d; | 336 | struct transaction_callback_data d; |
| 329 | struct fw_transaction t; | 337 | struct fw_transaction t; |
| 330 | 338 | ||
| 331 | init_completion(&d.done); | 339 | init_completion(&d.done); |
| 332 | d.payload = data; | 340 | d.payload = payload; |
| 333 | fw_send_request(card, &t, tcode, destination_id, generation, speed, | 341 | fw_send_request(card, &t, tcode, destination_id, generation, speed, |
| 334 | offset, data, length, transaction_callback, &d); | 342 | offset, payload, length, transaction_callback, &d); |
| 335 | wait_for_completion(&d.done); | 343 | wait_for_completion(&d.done); |
| 336 | 344 | ||
| 337 | return d.rcode; | 345 | return d.rcode; |
| @@ -399,9 +407,8 @@ void fw_flush_transactions(struct fw_card *card) | |||
| 399 | } | 407 | } |
| 400 | } | 408 | } |
| 401 | 409 | ||
| 402 | static struct fw_address_handler * | 410 | static struct fw_address_handler *lookup_overlapping_address_handler( |
| 403 | lookup_overlapping_address_handler(struct list_head *list, | 411 | struct list_head *list, unsigned long long offset, size_t length) |
| 404 | unsigned long long offset, size_t length) | ||
| 405 | { | 412 | { |
| 406 | struct fw_address_handler *handler; | 413 | struct fw_address_handler *handler; |
| 407 | 414 | ||
| @@ -414,9 +421,8 @@ lookup_overlapping_address_handler(struct list_head *list, | |||
| 414 | return NULL; | 421 | return NULL; |
| 415 | } | 422 | } |
| 416 | 423 | ||
| 417 | static struct fw_address_handler * | 424 | static struct fw_address_handler *lookup_enclosing_address_handler( |
| 418 | lookup_enclosing_address_handler(struct list_head *list, | 425 | struct list_head *list, unsigned long long offset, size_t length) |
| 419 | unsigned long long offset, size_t length) | ||
| 420 | { | 426 | { |
| 421 | struct fw_address_handler *handler; | 427 | struct fw_address_handler *handler; |
| 422 | 428 | ||
| @@ -449,36 +455,44 @@ const struct fw_address_region fw_unit_space_region = | |||
| 449 | #endif /* 0 */ | 455 | #endif /* 0 */ |
| 450 | 456 | ||
| 451 | /** | 457 | /** |
| 452 | * Allocate a range of addresses in the node space of the OHCI | 458 | * fw_core_add_address_handler - register for incoming requests |
| 453 | * controller. When a request is received that falls within the | 459 | * @handler: callback |
| 454 | * specified address range, the specified callback is invoked. The | 460 | * @region: region in the IEEE 1212 node space address range |
| 455 | * parameters passed to the callback give the details of the | 461 | * |
| 456 | * particular request. | 462 | * region->start, ->end, and handler->length have to be quadlet-aligned. |
| 463 | * | ||
| 464 | * When a request is received that falls within the specified address range, | ||
| 465 | * the specified callback is invoked. The parameters passed to the callback | ||
| 466 | * give the details of the particular request. | ||
| 457 | * | 467 | * |
| 458 | * Return value: 0 on success, non-zero otherwise. | 468 | * Return value: 0 on success, non-zero otherwise. |
| 459 | * The start offset of the handler's address region is determined by | 469 | * The start offset of the handler's address region is determined by |
| 460 | * fw_core_add_address_handler() and is returned in handler->offset. | 470 | * fw_core_add_address_handler() and is returned in handler->offset. |
| 461 | * The offset is quadlet-aligned. | ||
| 462 | */ | 471 | */ |
| 463 | int | 472 | int fw_core_add_address_handler(struct fw_address_handler *handler, |
| 464 | fw_core_add_address_handler(struct fw_address_handler *handler, | 473 | const struct fw_address_region *region) |
| 465 | const struct fw_address_region *region) | ||
| 466 | { | 474 | { |
| 467 | struct fw_address_handler *other; | 475 | struct fw_address_handler *other; |
| 468 | unsigned long flags; | 476 | unsigned long flags; |
| 469 | int ret = -EBUSY; | 477 | int ret = -EBUSY; |
| 470 | 478 | ||
| 479 | if (region->start & 0xffff000000000003ULL || | ||
| 480 | region->end & 0xffff000000000003ULL || | ||
| 481 | region->start >= region->end || | ||
| 482 | handler->length & 3 || | ||
| 483 | handler->length == 0) | ||
| 484 | return -EINVAL; | ||
| 485 | |||
| 471 | spin_lock_irqsave(&address_handler_lock, flags); | 486 | spin_lock_irqsave(&address_handler_lock, flags); |
| 472 | 487 | ||
| 473 | handler->offset = roundup(region->start, 4); | 488 | handler->offset = region->start; |
| 474 | while (handler->offset + handler->length <= region->end) { | 489 | while (handler->offset + handler->length <= region->end) { |
| 475 | other = | 490 | other = |
| 476 | lookup_overlapping_address_handler(&address_handler_list, | 491 | lookup_overlapping_address_handler(&address_handler_list, |
| 477 | handler->offset, | 492 | handler->offset, |
| 478 | handler->length); | 493 | handler->length); |
| 479 | if (other != NULL) { | 494 | if (other != NULL) { |
| 480 | handler->offset = | 495 | handler->offset += other->length; |
| 481 | roundup(other->offset + other->length, 4); | ||
| 482 | } else { | 496 | } else { |
| 483 | list_add_tail(&handler->link, &address_handler_list); | 497 | list_add_tail(&handler->link, &address_handler_list); |
| 484 | ret = 0; | 498 | ret = 0; |
| @@ -493,12 +507,7 @@ fw_core_add_address_handler(struct fw_address_handler *handler, | |||
| 493 | EXPORT_SYMBOL(fw_core_add_address_handler); | 507 | EXPORT_SYMBOL(fw_core_add_address_handler); |
| 494 | 508 | ||
| 495 | /** | 509 | /** |
| 496 | * Deallocate a range of addresses allocated with fw_allocate. This | 510 | * fw_core_remove_address_handler - unregister an address handler |
| 497 | * will call the associated callback one last time with a the special | ||
| 498 | * tcode TCODE_DEALLOCATE, to let the client destroy the registered | ||
| 499 | * callback data. For convenience, the callback parameters offset and | ||
| 500 | * length are set to the start and the length respectively for the | ||
| 501 | * deallocated region, payload is set to NULL. | ||
| 502 | */ | 511 | */ |
| 503 | void fw_core_remove_address_handler(struct fw_address_handler *handler) | 512 | void fw_core_remove_address_handler(struct fw_address_handler *handler) |
| 504 | { | 513 | { |
| @@ -518,9 +527,8 @@ struct fw_request { | |||
| 518 | u32 data[0]; | 527 | u32 data[0]; |
| 519 | }; | 528 | }; |
| 520 | 529 | ||
| 521 | static void | 530 | static void free_response_callback(struct fw_packet *packet, |
| 522 | free_response_callback(struct fw_packet *packet, | 531 | struct fw_card *card, int status) |
| 523 | struct fw_card *card, int status) | ||
| 524 | { | 532 | { |
| 525 | struct fw_request *request; | 533 | struct fw_request *request; |
| 526 | 534 | ||
| @@ -528,9 +536,8 @@ free_response_callback(struct fw_packet *packet, | |||
| 528 | kfree(request); | 536 | kfree(request); |
| 529 | } | 537 | } |
| 530 | 538 | ||
| 531 | void | 539 | void fw_fill_response(struct fw_packet *response, u32 *request_header, |
| 532 | fw_fill_response(struct fw_packet *response, u32 *request_header, | 540 | int rcode, void *payload, size_t length) |
| 533 | int rcode, void *payload, size_t length) | ||
| 534 | { | 541 | { |
| 535 | int tcode, tlabel, extended_tcode, source, destination; | 542 | int tcode, tlabel, extended_tcode, source, destination; |
| 536 | 543 | ||
| @@ -588,8 +595,7 @@ fw_fill_response(struct fw_packet *response, u32 *request_header, | |||
| 588 | } | 595 | } |
| 589 | EXPORT_SYMBOL(fw_fill_response); | 596 | EXPORT_SYMBOL(fw_fill_response); |
| 590 | 597 | ||
| 591 | static struct fw_request * | 598 | static struct fw_request *allocate_request(struct fw_packet *p) |
| 592 | allocate_request(struct fw_packet *p) | ||
| 593 | { | 599 | { |
| 594 | struct fw_request *request; | 600 | struct fw_request *request; |
| 595 | u32 *data, length; | 601 | u32 *data, length; |
| @@ -649,8 +655,8 @@ allocate_request(struct fw_packet *p) | |||
| 649 | return request; | 655 | return request; |
| 650 | } | 656 | } |
| 651 | 657 | ||
| 652 | void | 658 | void fw_send_response(struct fw_card *card, |
| 653 | fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) | 659 | struct fw_request *request, int rcode) |
| 654 | { | 660 | { |
| 655 | /* unified transaction or broadcast transaction: don't respond */ | 661 | /* unified transaction or broadcast transaction: don't respond */ |
| 656 | if (request->ack != ACK_PENDING || | 662 | if (request->ack != ACK_PENDING || |
| @@ -670,8 +676,7 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) | |||
| 670 | } | 676 | } |
| 671 | EXPORT_SYMBOL(fw_send_response); | 677 | EXPORT_SYMBOL(fw_send_response); |
| 672 | 678 | ||
| 673 | void | 679 | void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) |
| 674 | fw_core_handle_request(struct fw_card *card, struct fw_packet *p) | ||
| 675 | { | 680 | { |
| 676 | struct fw_address_handler *handler; | 681 | struct fw_address_handler *handler; |
| 677 | struct fw_request *request; | 682 | struct fw_request *request; |
| @@ -719,8 +724,7 @@ fw_core_handle_request(struct fw_card *card, struct fw_packet *p) | |||
| 719 | } | 724 | } |
| 720 | EXPORT_SYMBOL(fw_core_handle_request); | 725 | EXPORT_SYMBOL(fw_core_handle_request); |
| 721 | 726 | ||
| 722 | void | 727 | void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) |
| 723 | fw_core_handle_response(struct fw_card *card, struct fw_packet *p) | ||
| 724 | { | 728 | { |
| 725 | struct fw_transaction *t; | 729 | struct fw_transaction *t; |
| 726 | unsigned long flags; | 730 | unsigned long flags; |
| @@ -793,12 +797,10 @@ static const struct fw_address_region topology_map_region = | |||
| 793 | { .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP, | 797 | { .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP, |
| 794 | .end = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, }; | 798 | .end = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, }; |
| 795 | 799 | ||
| 796 | static void | 800 | static void handle_topology_map(struct fw_card *card, struct fw_request *request, |
| 797 | handle_topology_map(struct fw_card *card, struct fw_request *request, | 801 | int tcode, int destination, int source, int generation, |
| 798 | int tcode, int destination, int source, | 802 | int speed, unsigned long long offset, |
| 799 | int generation, int speed, | 803 | void *payload, size_t length, void *callback_data) |
| 800 | unsigned long long offset, | ||
| 801 | void *payload, size_t length, void *callback_data) | ||
| 802 | { | 804 | { |
| 803 | int i, start, end; | 805 | int i, start, end; |
| 804 | __be32 *map; | 806 | __be32 *map; |
| @@ -832,12 +834,10 @@ static const struct fw_address_region registers_region = | |||
| 832 | { .start = CSR_REGISTER_BASE, | 834 | { .start = CSR_REGISTER_BASE, |
| 833 | .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, }; | 835 | .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, }; |
| 834 | 836 | ||
| 835 | static void | 837 | static void handle_registers(struct fw_card *card, struct fw_request *request, |
| 836 | handle_registers(struct fw_card *card, struct fw_request *request, | 838 | int tcode, int destination, int source, int generation, |
| 837 | int tcode, int destination, int source, | 839 | int speed, unsigned long long offset, |
| 838 | int generation, int speed, | 840 | void *payload, size_t length, void *callback_data) |
| 839 | unsigned long long offset, | ||
| 840 | void *payload, size_t length, void *callback_data) | ||
| 841 | { | 841 | { |
| 842 | int reg = offset & ~CSR_REGISTER_BASE; | 842 | int reg = offset & ~CSR_REGISTER_BASE; |
| 843 | unsigned long long bus_time; | 843 | unsigned long long bus_time; |
| @@ -939,11 +939,11 @@ static struct fw_descriptor model_id_descriptor = { | |||
| 939 | 939 | ||
| 940 | static int __init fw_core_init(void) | 940 | static int __init fw_core_init(void) |
| 941 | { | 941 | { |
| 942 | int retval; | 942 | int ret; |
| 943 | 943 | ||
| 944 | retval = bus_register(&fw_bus_type); | 944 | ret = bus_register(&fw_bus_type); |
| 945 | if (retval < 0) | 945 | if (ret < 0) |
| 946 | return retval; | 946 | return ret; |
| 947 | 947 | ||
| 948 | fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops); | 948 | fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops); |
| 949 | if (fw_cdev_major < 0) { | 949 | if (fw_cdev_major < 0) { |
| @@ -951,19 +951,10 @@ static int __init fw_core_init(void) | |||
| 951 | return fw_cdev_major; | 951 | return fw_cdev_major; |
| 952 | } | 952 | } |
| 953 | 953 | ||
| 954 | retval = fw_core_add_address_handler(&topology_map, | 954 | fw_core_add_address_handler(&topology_map, &topology_map_region); |
| 955 | &topology_map_region); | 955 | fw_core_add_address_handler(®isters, ®isters_region); |
| 956 | BUG_ON(retval < 0); | 956 | fw_core_add_descriptor(&vendor_id_descriptor); |
| 957 | 957 | fw_core_add_descriptor(&model_id_descriptor); | |
| 958 | retval = fw_core_add_address_handler(®isters, | ||
| 959 | ®isters_region); | ||
| 960 | BUG_ON(retval < 0); | ||
| 961 | |||
| 962 | /* Add the vendor textual descriptor. */ | ||
| 963 | retval = fw_core_add_descriptor(&vendor_id_descriptor); | ||
| 964 | BUG_ON(retval < 0); | ||
| 965 | retval = fw_core_add_descriptor(&model_id_descriptor); | ||
| 966 | BUG_ON(retval < 0); | ||
| 967 | 958 | ||
| 968 | return 0; | 959 | return 0; |
| 969 | } | 960 | } |
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 1d78e9cc5940..dfa799068f89 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
| @@ -82,14 +82,14 @@ | |||
| 82 | #define CSR_SPEED_MAP 0x2000 | 82 | #define CSR_SPEED_MAP 0x2000 |
| 83 | #define CSR_SPEED_MAP_END 0x3000 | 83 | #define CSR_SPEED_MAP_END 0x3000 |
| 84 | 84 | ||
| 85 | #define BANDWIDTH_AVAILABLE_INITIAL 4915 | ||
| 85 | #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) | 86 | #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) |
| 86 | #define BROADCAST_CHANNEL_VALID (1 << 30) | 87 | #define BROADCAST_CHANNEL_VALID (1 << 30) |
| 87 | 88 | ||
| 88 | #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) | 89 | #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) |
| 89 | #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) | 90 | #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) |
| 90 | 91 | ||
| 91 | static inline void | 92 | static inline void fw_memcpy_from_be32(void *_dst, void *_src, size_t size) |
| 92 | fw_memcpy_from_be32(void *_dst, void *_src, size_t size) | ||
| 93 | { | 93 | { |
| 94 | u32 *dst = _dst; | 94 | u32 *dst = _dst; |
| 95 | __be32 *src = _src; | 95 | __be32 *src = _src; |
| @@ -99,8 +99,7 @@ fw_memcpy_from_be32(void *_dst, void *_src, size_t size) | |||
| 99 | dst[i] = be32_to_cpu(src[i]); | 99 | dst[i] = be32_to_cpu(src[i]); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static inline void | 102 | static inline void fw_memcpy_to_be32(void *_dst, void *_src, size_t size) |
| 103 | fw_memcpy_to_be32(void *_dst, void *_src, size_t size) | ||
| 104 | { | 103 | { |
| 105 | fw_memcpy_from_be32(_dst, _src, size); | 104 | fw_memcpy_from_be32(_dst, _src, size); |
| 106 | } | 105 | } |
| @@ -125,8 +124,7 @@ typedef void (*fw_packet_callback_t)(struct fw_packet *packet, | |||
| 125 | struct fw_card *card, int status); | 124 | struct fw_card *card, int status); |
| 126 | 125 | ||
| 127 | typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, | 126 | typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, |
| 128 | void *data, | 127 | void *data, size_t length, |
| 129 | size_t length, | ||
| 130 | void *callback_data); | 128 | void *callback_data); |
| 131 | 129 | ||
| 132 | /* | 130 | /* |
| @@ -141,12 +139,6 @@ typedef void (*fw_address_callback_t)(struct fw_card *card, | |||
| 141 | void *data, size_t length, | 139 | void *data, size_t length, |
| 142 | void *callback_data); | 140 | void *callback_data); |
| 143 | 141 | ||
| 144 | typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle, | ||
| 145 | int node_id, int generation, | ||
| 146 | u32 *self_ids, | ||
| 147 | int self_id_count, | ||
| 148 | void *callback_data); | ||
| 149 | |||
| 150 | struct fw_packet { | 142 | struct fw_packet { |
| 151 | int speed; | 143 | int speed; |
| 152 | int generation; | 144 | int generation; |
| @@ -187,12 +179,6 @@ struct fw_transaction { | |||
| 187 | void *callback_data; | 179 | void *callback_data; |
| 188 | }; | 180 | }; |
| 189 | 181 | ||
| 190 | static inline struct fw_packet * | ||
| 191 | fw_packet(struct list_head *l) | ||
| 192 | { | ||
| 193 | return list_entry(l, struct fw_packet, link); | ||
| 194 | } | ||
| 195 | |||
| 196 | struct fw_address_handler { | 182 | struct fw_address_handler { |
| 197 | u64 offset; | 183 | u64 offset; |
| 198 | size_t length; | 184 | size_t length; |
| @@ -201,7 +187,6 @@ struct fw_address_handler { | |||
| 201 | struct list_head link; | 187 | struct list_head link; |
| 202 | }; | 188 | }; |
| 203 | 189 | ||
| 204 | |||
| 205 | struct fw_address_region { | 190 | struct fw_address_region { |
| 206 | u64 start; | 191 | u64 start; |
| 207 | u64 end; | 192 | u64 end; |
| @@ -255,6 +240,7 @@ struct fw_card { | |||
| 255 | int bm_retries; | 240 | int bm_retries; |
| 256 | int bm_generation; | 241 | int bm_generation; |
| 257 | 242 | ||
| 243 | bool broadcast_channel_allocated; | ||
| 258 | u32 broadcast_channel; | 244 | u32 broadcast_channel; |
| 259 | u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; | 245 | u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; |
| 260 | }; | 246 | }; |
| @@ -315,10 +301,8 @@ struct fw_iso_packet { | |||
| 315 | struct fw_iso_context; | 301 | struct fw_iso_context; |
| 316 | 302 | ||
| 317 | typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, | 303 | typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, |
| 318 | u32 cycle, | 304 | u32 cycle, size_t header_length, |
| 319 | size_t header_length, | 305 | void *header, void *data); |
| 320 | void *header, | ||
| 321 | void *data); | ||
| 322 | 306 | ||
| 323 | /* | 307 | /* |
| 324 | * An iso buffer is just a set of pages mapped for DMA in the | 308 | * An iso buffer is just a set of pages mapped for DMA in the |
| @@ -344,36 +328,25 @@ struct fw_iso_context { | |||
| 344 | void *callback_data; | 328 | void *callback_data; |
| 345 | }; | 329 | }; |
| 346 | 330 | ||
| 347 | int | 331 | int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, |
| 348 | fw_iso_buffer_init(struct fw_iso_buffer *buffer, | 332 | int page_count, enum dma_data_direction direction); |
| 349 | struct fw_card *card, | 333 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); |
| 350 | int page_count, | 334 | void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); |
| 351 | enum dma_data_direction direction); | 335 | |
| 352 | int | 336 | struct fw_iso_context *fw_iso_context_create(struct fw_card *card, |
| 353 | fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); | 337 | int type, int channel, int speed, size_t header_size, |
| 354 | void | 338 | fw_iso_callback_t callback, void *callback_data); |
| 355 | fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); | 339 | int fw_iso_context_queue(struct fw_iso_context *ctx, |
| 356 | 340 | struct fw_iso_packet *packet, | |
| 357 | struct fw_iso_context * | 341 | struct fw_iso_buffer *buffer, |
| 358 | fw_iso_context_create(struct fw_card *card, int type, | 342 | unsigned long payload); |
| 359 | int channel, int speed, size_t header_size, | 343 | int fw_iso_context_start(struct fw_iso_context *ctx, |
| 360 | fw_iso_callback_t callback, void *callback_data); | 344 | int cycle, int sync, int tags); |
| 361 | 345 | int fw_iso_context_stop(struct fw_iso_context *ctx); | |
| 362 | void | 346 | void fw_iso_context_destroy(struct fw_iso_context *ctx); |
| 363 | fw_iso_context_destroy(struct fw_iso_context *ctx); | 347 | |
| 364 | 348 | void fw_iso_resource_manage(struct fw_card *card, int generation, | |
| 365 | int | 349 | u64 channels_mask, int *channel, int *bandwidth, bool allocate); |
| 366 | fw_iso_context_queue(struct fw_iso_context *ctx, | ||
| 367 | struct fw_iso_packet *packet, | ||
| 368 | struct fw_iso_buffer *buffer, | ||
| 369 | unsigned long payload); | ||
| 370 | |||
| 371 | int | ||
| 372 | fw_iso_context_start(struct fw_iso_context *ctx, | ||
| 373 | int cycle, int sync, int tags); | ||
| 374 | |||
| 375 | int | ||
| 376 | fw_iso_context_stop(struct fw_iso_context *ctx); | ||
| 377 | 350 | ||
| 378 | struct fw_card_driver { | 351 | struct fw_card_driver { |
| 379 | /* | 352 | /* |
| @@ -415,7 +388,7 @@ struct fw_card_driver { | |||
| 415 | 388 | ||
| 416 | struct fw_iso_context * | 389 | struct fw_iso_context * |
| 417 | (*allocate_iso_context)(struct fw_card *card, | 390 | (*allocate_iso_context)(struct fw_card *card, |
| 418 | int type, size_t header_size); | 391 | int type, int channel, size_t header_size); |
| 419 | void (*free_iso_context)(struct fw_iso_context *ctx); | 392 | void (*free_iso_context)(struct fw_iso_context *ctx); |
| 420 | 393 | ||
| 421 | int (*start_iso)(struct fw_iso_context *ctx, | 394 | int (*start_iso)(struct fw_iso_context *ctx, |
| @@ -429,54 +402,45 @@ struct fw_card_driver { | |||
| 429 | int (*stop_iso)(struct fw_iso_context *ctx); | 402 | int (*stop_iso)(struct fw_iso_context *ctx); |
| 430 | }; | 403 | }; |
| 431 | 404 | ||
| 432 | int | 405 | int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); |
| 433 | fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); | ||
| 434 | 406 | ||
| 435 | void | 407 | void fw_send_request(struct fw_card *card, struct fw_transaction *t, |
| 436 | fw_send_request(struct fw_card *card, struct fw_transaction *t, | ||
| 437 | int tcode, int destination_id, int generation, int speed, | 408 | int tcode, int destination_id, int generation, int speed, |
| 438 | unsigned long long offset, void *data, size_t length, | 409 | unsigned long long offset, void *payload, size_t length, |
| 439 | fw_transaction_callback_t callback, void *callback_data); | 410 | fw_transaction_callback_t callback, void *callback_data); |
| 440 | |||
| 441 | int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, | ||
| 442 | int generation, int speed, unsigned long long offset, | ||
| 443 | void *data, size_t length); | ||
| 444 | |||
| 445 | int fw_cancel_transaction(struct fw_card *card, | 411 | int fw_cancel_transaction(struct fw_card *card, |
| 446 | struct fw_transaction *transaction); | 412 | struct fw_transaction *transaction); |
| 447 | |||
| 448 | void fw_flush_transactions(struct fw_card *card); | 413 | void fw_flush_transactions(struct fw_card *card); |
| 449 | 414 | int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, | |
| 415 | int generation, int speed, unsigned long long offset, | ||
| 416 | void *payload, size_t length); | ||
| 450 | void fw_send_phy_config(struct fw_card *card, | 417 | void fw_send_phy_config(struct fw_card *card, |
| 451 | int node_id, int generation, int gap_count); | 418 | int node_id, int generation, int gap_count); |
| 452 | 419 | ||
| 420 | static inline int fw_stream_packet_destination_id(int tag, int channel, int sy) | ||
| 421 | { | ||
| 422 | return tag << 14 | channel << 8 | sy; | ||
| 423 | } | ||
| 424 | |||
| 453 | /* | 425 | /* |
| 454 | * Called by the topology code to inform the device code of node | 426 | * Called by the topology code to inform the device code of node |
| 455 | * activity; found, lost, or updated nodes. | 427 | * activity; found, lost, or updated nodes. |
| 456 | */ | 428 | */ |
| 457 | void | 429 | void fw_node_event(struct fw_card *card, struct fw_node *node, int event); |
| 458 | fw_node_event(struct fw_card *card, struct fw_node *node, int event); | ||
| 459 | 430 | ||
| 460 | /* API used by card level drivers */ | 431 | /* API used by card level drivers */ |
| 461 | 432 | ||
| 462 | void | 433 | void fw_card_initialize(struct fw_card *card, |
| 463 | fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, | 434 | const struct fw_card_driver *driver, struct device *device); |
| 464 | struct device *device); | 435 | int fw_card_add(struct fw_card *card, |
| 465 | int | 436 | u32 max_receive, u32 link_speed, u64 guid); |
| 466 | fw_card_add(struct fw_card *card, | 437 | void fw_core_remove_card(struct fw_card *card); |
| 467 | u32 max_receive, u32 link_speed, u64 guid); | 438 | void fw_core_handle_bus_reset(struct fw_card *card, int node_id, |
| 468 | 439 | int generation, int self_id_count, u32 *self_ids); | |
| 469 | void | 440 | void fw_core_handle_request(struct fw_card *card, struct fw_packet *request); |
| 470 | fw_core_remove_card(struct fw_card *card); | 441 | void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); |
| 471 | 442 | ||
| 472 | void | 443 | extern int fw_irm_set_broadcast_channel_register(struct device *dev, |
| 473 | fw_core_handle_bus_reset(struct fw_card *card, | 444 | void *data); |
| 474 | int node_id, int generation, | ||
| 475 | int self_id_count, u32 *self_ids); | ||
| 476 | void | ||
| 477 | fw_core_handle_request(struct fw_card *card, struct fw_packet *request); | ||
| 478 | |||
| 479 | void | ||
| 480 | fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); | ||
| 481 | 445 | ||
| 482 | #endif /* __fw_transaction_h */ | 446 | #endif /* __fw_transaction_h */ |
diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c index 31400c8ae051..d696f69ebce5 100644 --- a/drivers/ieee1394/csr.c +++ b/drivers/ieee1394/csr.c | |||
| @@ -68,22 +68,22 @@ static struct hpsb_highlevel csr_highlevel = { | |||
| 68 | .host_reset = host_reset, | 68 | .host_reset = host_reset, |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | const static struct hpsb_address_ops map_ops = { | 71 | static const struct hpsb_address_ops map_ops = { |
| 72 | .read = read_maps, | 72 | .read = read_maps, |
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | const static struct hpsb_address_ops fcp_ops = { | 75 | static const struct hpsb_address_ops fcp_ops = { |
| 76 | .write = write_fcp, | 76 | .write = write_fcp, |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | const static struct hpsb_address_ops reg_ops = { | 79 | static const struct hpsb_address_ops reg_ops = { |
| 80 | .read = read_regs, | 80 | .read = read_regs, |
| 81 | .write = write_regs, | 81 | .write = write_regs, |
| 82 | .lock = lock_regs, | 82 | .lock = lock_regs, |
| 83 | .lock64 = lock64_regs, | 83 | .lock64 = lock64_regs, |
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | const static struct hpsb_address_ops config_rom_ops = { | 86 | static const struct hpsb_address_ops config_rom_ops = { |
| 87 | .read = read_config_rom, | 87 | .read = read_config_rom, |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index cb15bfa38d70..823a6297a1af 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c | |||
| @@ -2171,7 +2171,7 @@ static const struct file_operations dv1394_fops= | |||
| 2171 | * Export information about protocols/devices supported by this driver. | 2171 | * Export information about protocols/devices supported by this driver. |
| 2172 | */ | 2172 | */ |
| 2173 | #ifdef MODULE | 2173 | #ifdef MODULE |
| 2174 | static struct ieee1394_device_id dv1394_id_table[] = { | 2174 | static const struct ieee1394_device_id dv1394_id_table[] = { |
| 2175 | { | 2175 | { |
| 2176 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, | 2176 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, |
| 2177 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, | 2177 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, |
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 1a919df809f8..4ca103577c0a 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c | |||
| @@ -181,7 +181,7 @@ static void ether1394_remove_host(struct hpsb_host *host); | |||
| 181 | static void ether1394_host_reset(struct hpsb_host *host); | 181 | static void ether1394_host_reset(struct hpsb_host *host); |
| 182 | 182 | ||
| 183 | /* Function for incoming 1394 packets */ | 183 | /* Function for incoming 1394 packets */ |
| 184 | const static struct hpsb_address_ops addr_ops = { | 184 | static const struct hpsb_address_ops addr_ops = { |
| 185 | .write = ether1394_write, | 185 | .write = ether1394_write, |
| 186 | }; | 186 | }; |
| 187 | 187 | ||
| @@ -438,7 +438,7 @@ static int eth1394_update(struct unit_directory *ud) | |||
| 438 | return eth1394_new_node(hi, ud); | 438 | return eth1394_new_node(hi, ud); |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | static struct ieee1394_device_id eth1394_id_table[] = { | 441 | static const struct ieee1394_device_id eth1394_id_table[] = { |
| 442 | { | 442 | { |
| 443 | .match_flags = (IEEE1394_MATCH_SPECIFIER_ID | | 443 | .match_flags = (IEEE1394_MATCH_SPECIFIER_ID | |
| 444 | IEEE1394_MATCH_VERSION), | 444 | IEEE1394_MATCH_VERSION), |
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 600e391c8fe7..4bc443546e04 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c | |||
| @@ -478,7 +478,7 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, | |||
| 478 | return retval; | 478 | return retval; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | const static struct hpsb_address_ops dummy_ops; | 481 | static const struct hpsb_address_ops dummy_ops; |
| 482 | 482 | ||
| 483 | /* dummy address spaces as lower and upper bounds of the host's a.s. list */ | 483 | /* dummy address spaces as lower and upper bounds of the host's a.s. list */ |
| 484 | static void init_hpsb_highlevel(struct hpsb_host *host) | 484 | static void init_hpsb_highlevel(struct hpsb_host *host) |
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 53aada5bbe1e..a6d55bebe61a 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
| @@ -484,7 +484,7 @@ static struct device_attribute *const fw_host_attrs[] = { | |||
| 484 | static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf) | 484 | static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf) |
| 485 | { | 485 | { |
| 486 | struct hpsb_protocol_driver *driver; | 486 | struct hpsb_protocol_driver *driver; |
| 487 | struct ieee1394_device_id *id; | 487 | const struct ieee1394_device_id *id; |
| 488 | int length = 0; | 488 | int length = 0; |
| 489 | char *scratch = buf; | 489 | char *scratch = buf; |
| 490 | 490 | ||
| @@ -658,7 +658,7 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) | |||
| 658 | { | 658 | { |
| 659 | struct hpsb_protocol_driver *driver; | 659 | struct hpsb_protocol_driver *driver; |
| 660 | struct unit_directory *ud; | 660 | struct unit_directory *ud; |
| 661 | struct ieee1394_device_id *id; | 661 | const struct ieee1394_device_id *id; |
| 662 | 662 | ||
| 663 | /* We only match unit directories */ | 663 | /* We only match unit directories */ |
| 664 | if (dev->platform_data != &nodemgr_ud_platform_data) | 664 | if (dev->platform_data != &nodemgr_ud_platform_data) |
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index ee5acdbd114a..749b271d3107 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h | |||
| @@ -125,7 +125,7 @@ struct hpsb_protocol_driver { | |||
| 125 | * probe function below can implement further protocol | 125 | * probe function below can implement further protocol |
| 126 | * dependent or vendor dependent checking. | 126 | * dependent or vendor dependent checking. |
| 127 | */ | 127 | */ |
| 128 | struct ieee1394_device_id *id_table; | 128 | const struct ieee1394_device_id *id_table; |
| 129 | 129 | ||
| 130 | /* | 130 | /* |
| 131 | * The update function is called when the node has just | 131 | * The update function is called when the node has just |
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index bad66c65b0d6..da5f8829b503 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
| @@ -90,7 +90,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, | |||
| 90 | static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, | 90 | static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, |
| 91 | u64 addr, octlet_t data, octlet_t arg, int ext_tcode, | 91 | u64 addr, octlet_t data, octlet_t arg, int ext_tcode, |
| 92 | u16 flags); | 92 | u16 flags); |
| 93 | const static struct hpsb_address_ops arm_ops = { | 93 | static const struct hpsb_address_ops arm_ops = { |
| 94 | .read = arm_read, | 94 | .read = arm_read, |
| 95 | .write = arm_write, | 95 | .write = arm_write, |
| 96 | .lock = arm_lock, | 96 | .lock = arm_lock, |
| @@ -369,6 +369,7 @@ static const char __user *raw1394_compat_write(const char __user *buf) | |||
| 369 | { | 369 | { |
| 370 | struct compat_raw1394_req __user *cr = (typeof(cr)) buf; | 370 | struct compat_raw1394_req __user *cr = (typeof(cr)) buf; |
| 371 | struct raw1394_request __user *r; | 371 | struct raw1394_request __user *r; |
| 372 | |||
| 372 | r = compat_alloc_user_space(sizeof(struct raw1394_request)); | 373 | r = compat_alloc_user_space(sizeof(struct raw1394_request)); |
| 373 | 374 | ||
| 374 | #define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x)) | 375 | #define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x)) |
| @@ -378,7 +379,8 @@ static const char __user *raw1394_compat_write(const char __user *buf) | |||
| 378 | C(tag) || | 379 | C(tag) || |
| 379 | C(sendb) || | 380 | C(sendb) || |
| 380 | C(recvb)) | 381 | C(recvb)) |
| 381 | return ERR_PTR(-EFAULT); | 382 | return (__force const char __user *)ERR_PTR(-EFAULT); |
| 383 | |||
| 382 | return (const char __user *)r; | 384 | return (const char __user *)r; |
| 383 | } | 385 | } |
| 384 | #undef C | 386 | #undef C |
| @@ -389,6 +391,7 @@ static int | |||
| 389 | raw1394_compat_read(const char __user *buf, struct raw1394_request *r) | 391 | raw1394_compat_read(const char __user *buf, struct raw1394_request *r) |
| 390 | { | 392 | { |
| 391 | struct compat_raw1394_req __user *cr = (typeof(cr)) buf; | 393 | struct compat_raw1394_req __user *cr = (typeof(cr)) buf; |
| 394 | |||
| 392 | if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) || | 395 | if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) || |
| 393 | P(type) || | 396 | P(type) || |
| 394 | P(error) || | 397 | P(error) || |
| @@ -400,6 +403,7 @@ raw1394_compat_read(const char __user *buf, struct raw1394_request *r) | |||
| 400 | P(sendb) || | 403 | P(sendb) || |
| 401 | P(recvb)) | 404 | P(recvb)) |
| 402 | return -EFAULT; | 405 | return -EFAULT; |
| 406 | |||
| 403 | return sizeof(struct compat_raw1394_req); | 407 | return sizeof(struct compat_raw1394_req); |
| 404 | } | 408 | } |
| 405 | #undef P | 409 | #undef P |
| @@ -2249,8 +2253,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, | |||
| 2249 | sizeof(struct compat_raw1394_req) != | 2253 | sizeof(struct compat_raw1394_req) != |
| 2250 | sizeof(struct raw1394_request)) { | 2254 | sizeof(struct raw1394_request)) { |
| 2251 | buffer = raw1394_compat_write(buffer); | 2255 | buffer = raw1394_compat_write(buffer); |
| 2252 | if (IS_ERR(buffer)) | 2256 | if (IS_ERR((__force void *)buffer)) |
| 2253 | return PTR_ERR(buffer); | 2257 | return PTR_ERR((__force void *)buffer); |
| 2254 | } else | 2258 | } else |
| 2255 | #endif | 2259 | #endif |
| 2256 | if (count != sizeof(struct raw1394_request)) { | 2260 | if (count != sizeof(struct raw1394_request)) { |
| @@ -2978,7 +2982,7 @@ static int raw1394_release(struct inode *inode, struct file *file) | |||
| 2978 | * Export information about protocols/devices supported by this driver. | 2982 | * Export information about protocols/devices supported by this driver. |
| 2979 | */ | 2983 | */ |
| 2980 | #ifdef MODULE | 2984 | #ifdef MODULE |
| 2981 | static struct ieee1394_device_id raw1394_id_table[] = { | 2985 | static const struct ieee1394_device_id raw1394_id_table[] = { |
| 2982 | { | 2986 | { |
| 2983 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, | 2987 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, |
| 2984 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, | 2988 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, |
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index f3fd8657ce4b..a51ab233342d 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
| @@ -265,7 +265,7 @@ static struct hpsb_highlevel sbp2_highlevel = { | |||
| 265 | .host_reset = sbp2_host_reset, | 265 | .host_reset = sbp2_host_reset, |
| 266 | }; | 266 | }; |
| 267 | 267 | ||
| 268 | const static struct hpsb_address_ops sbp2_ops = { | 268 | static const struct hpsb_address_ops sbp2_ops = { |
| 269 | .write = sbp2_handle_status_write | 269 | .write = sbp2_handle_status_write |
| 270 | }; | 270 | }; |
| 271 | 271 | ||
| @@ -275,7 +275,7 @@ static int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *, | |||
| 275 | static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64, | 275 | static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64, |
| 276 | size_t, u16); | 276 | size_t, u16); |
| 277 | 277 | ||
| 278 | const static struct hpsb_address_ops sbp2_physdma_ops = { | 278 | static const struct hpsb_address_ops sbp2_physdma_ops = { |
| 279 | .read = sbp2_handle_physdma_read, | 279 | .read = sbp2_handle_physdma_read, |
| 280 | .write = sbp2_handle_physdma_write, | 280 | .write = sbp2_handle_physdma_write, |
| 281 | }; | 281 | }; |
| @@ -285,7 +285,7 @@ const static struct hpsb_address_ops sbp2_physdma_ops = { | |||
| 285 | /* | 285 | /* |
| 286 | * Interface to driver core and IEEE 1394 core | 286 | * Interface to driver core and IEEE 1394 core |
| 287 | */ | 287 | */ |
| 288 | static struct ieee1394_device_id sbp2_id_table[] = { | 288 | static const struct ieee1394_device_id sbp2_id_table[] = { |
| 289 | { | 289 | { |
| 290 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, | 290 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, |
| 291 | .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, | 291 | .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, |
| @@ -1413,8 +1413,7 @@ static void sbp2_parse_unit_directory(struct sbp2_lu *lu, | |||
| 1413 | "(firmware_revision 0x%06x, vendor_id 0x%06x," | 1413 | "(firmware_revision 0x%06x, vendor_id 0x%06x," |
| 1414 | " model_id 0x%06x)", | 1414 | " model_id 0x%06x)", |
| 1415 | NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), | 1415 | NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), |
| 1416 | workarounds, firmware_revision, | 1416 | workarounds, firmware_revision, ud->vendor_id, |
| 1417 | ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id, | ||
| 1418 | model); | 1417 | model); |
| 1419 | 1418 | ||
| 1420 | /* We would need one SCSI host template for each target to adjust | 1419 | /* We would need one SCSI host template for each target to adjust |
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 679a918a5cc7..d287ba79821d 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c | |||
| @@ -1294,7 +1294,7 @@ static const struct file_operations video1394_fops= | |||
| 1294 | * Export information about protocols/devices supported by this driver. | 1294 | * Export information about protocols/devices supported by this driver. |
| 1295 | */ | 1295 | */ |
| 1296 | #ifdef MODULE | 1296 | #ifdef MODULE |
| 1297 | static struct ieee1394_device_id video1394_id_table[] = { | 1297 | static const struct ieee1394_device_id video1394_id_table[] = { |
| 1298 | { | 1298 | { |
| 1299 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, | 1299 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, |
| 1300 | .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, | 1300 | .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, |
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index b55d9ccaf33e..32526f103b59 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c | |||
| @@ -115,7 +115,7 @@ static const char *debug_fcp_ctype(unsigned int ctype) | |||
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | static const char *debug_fcp_opcode(unsigned int opcode, | 117 | static const char *debug_fcp_opcode(unsigned int opcode, |
| 118 | const u8 *data, size_t length) | 118 | const u8 *data, int length) |
| 119 | { | 119 | { |
| 120 | switch (opcode) { | 120 | switch (opcode) { |
| 121 | case AVC_OPCODE_VENDOR: break; | 121 | case AVC_OPCODE_VENDOR: break; |
| @@ -135,13 +135,14 @@ static const char *debug_fcp_opcode(unsigned int opcode, | |||
| 135 | case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC"; | 135 | case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC"; |
| 136 | case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl"; | 136 | case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl"; |
| 137 | case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK"; | 137 | case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK"; |
| 138 | case SFE_VENDOR_OPCODE_TUNE_QPSK2: return "TuneQPSK2"; | ||
| 138 | case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA"; | 139 | case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA"; |
| 139 | case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host"; | 140 | case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host"; |
| 140 | } | 141 | } |
| 141 | return "Vendor"; | 142 | return "Vendor"; |
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | static void debug_fcp(const u8 *data, size_t length) | 145 | static void debug_fcp(const u8 *data, int length) |
| 145 | { | 146 | { |
| 146 | unsigned int subunit_type, subunit_id, op; | 147 | unsigned int subunit_type, subunit_id, op; |
| 147 | const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; | 148 | const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; |
| @@ -266,7 +267,10 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv, | |||
| 266 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | 267 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; |
| 267 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | 268 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; |
| 268 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | 269 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; |
| 269 | c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; | 270 | if (fdtv->type == FIREDTV_DVB_S2) |
| 271 | c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK2; | ||
| 272 | else | ||
| 273 | c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; | ||
| 270 | 274 | ||
| 271 | c->operand[4] = (params->frequency >> 24) & 0xff; | 275 | c->operand[4] = (params->frequency >> 24) & 0xff; |
| 272 | c->operand[5] = (params->frequency >> 16) & 0xff; | 276 | c->operand[5] = (params->frequency >> 16) & 0xff; |
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 4d078e99c017..c6b3ca3af6df 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h | |||
| @@ -25,10 +25,12 @@ | |||
| 25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
| 26 | #include <linux/firewire-constants.h> | 26 | #include <linux/firewire-constants.h> |
| 27 | 27 | ||
| 28 | #define FW_CDEV_EVENT_BUS_RESET 0x00 | 28 | #define FW_CDEV_EVENT_BUS_RESET 0x00 |
| 29 | #define FW_CDEV_EVENT_RESPONSE 0x01 | 29 | #define FW_CDEV_EVENT_RESPONSE 0x01 |
| 30 | #define FW_CDEV_EVENT_REQUEST 0x02 | 30 | #define FW_CDEV_EVENT_REQUEST 0x02 |
| 31 | #define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 | 31 | #define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 |
| 32 | #define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04 | ||
| 33 | #define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05 | ||
| 32 | 34 | ||
| 33 | /** | 35 | /** |
| 34 | * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types | 36 | * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types |
| @@ -136,7 +138,24 @@ struct fw_cdev_event_request { | |||
| 136 | * This event is sent when the controller has completed an &fw_cdev_iso_packet | 138 | * This event is sent when the controller has completed an &fw_cdev_iso_packet |
| 137 | * with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers | 139 | * with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers |
| 138 | * stripped of all packets up until and including the interrupt packet are | 140 | * stripped of all packets up until and including the interrupt packet are |
| 139 | * returned in the @header field. | 141 | * returned in the @header field. The amount of header data per packet is as |
| 142 | * specified at iso context creation by &fw_cdev_create_iso_context.header_size. | ||
| 143 | * | ||
| 144 | * In version 1 of this ABI, header data consisted of the 1394 isochronous | ||
| 145 | * packet header, followed by quadlets from the packet payload if | ||
| 146 | * &fw_cdev_create_iso_context.header_size > 4. | ||
| 147 | * | ||
| 148 | * In version 2 of this ABI, header data consist of the 1394 isochronous | ||
| 149 | * packet header, followed by a timestamp quadlet if | ||
| 150 | * &fw_cdev_create_iso_context.header_size > 4, followed by quadlets from the | ||
| 151 | * packet payload if &fw_cdev_create_iso_context.header_size > 8. | ||
| 152 | * | ||
| 153 | * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2. | ||
| 154 | * | ||
| 155 | * Format of 1394 iso packet header: 16 bits len, 2 bits tag, 6 bits channel, | ||
| 156 | * 4 bits tcode, 4 bits sy, in big endian byte order. Format of timestamp: | ||
| 157 | * 16 bits invalid, 3 bits cycleSeconds, 13 bits cycleCount, in big endian byte | ||
| 158 | * order. | ||
| 140 | */ | 159 | */ |
| 141 | struct fw_cdev_event_iso_interrupt { | 160 | struct fw_cdev_event_iso_interrupt { |
| 142 | __u64 closure; | 161 | __u64 closure; |
| @@ -147,12 +166,44 @@ struct fw_cdev_event_iso_interrupt { | |||
| 147 | }; | 166 | }; |
| 148 | 167 | ||
| 149 | /** | 168 | /** |
| 169 | * struct fw_cdev_event_iso_resource - Iso resources were allocated or freed | ||
| 170 | * @closure: See &fw_cdev_event_common; | ||
| 171 | * set by %FW_CDEV_IOC_(DE)ALLOCATE_ISO_RESOURCE(_ONCE) ioctl | ||
| 172 | * @type: %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or | ||
| 173 | * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED | ||
| 174 | * @handle: Reference by which an allocated resource can be deallocated | ||
| 175 | * @channel: Isochronous channel which was (de)allocated, if any | ||
| 176 | * @bandwidth: Bandwidth allocation units which were (de)allocated, if any | ||
| 177 | * | ||
| 178 | * An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED event is sent after an isochronous | ||
| 179 | * resource was allocated at the IRM. The client has to check @channel and | ||
| 180 | * @bandwidth for whether the allocation actually succeeded. | ||
| 181 | * | ||
| 182 | * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event is sent after an isochronous | ||
| 183 | * resource was deallocated at the IRM. It is also sent when automatic | ||
| 184 | * reallocation after a bus reset failed. | ||
| 185 | * | ||
| 186 | * @channel is <0 if no channel was (de)allocated or if reallocation failed. | ||
| 187 | * @bandwidth is 0 if no bandwidth was (de)allocated or if reallocation failed. | ||
| 188 | */ | ||
| 189 | struct fw_cdev_event_iso_resource { | ||
| 190 | __u64 closure; | ||
| 191 | __u32 type; | ||
| 192 | __u32 handle; | ||
| 193 | __s32 channel; | ||
| 194 | __s32 bandwidth; | ||
| 195 | }; | ||
| 196 | |||
| 197 | /** | ||
| 150 | * union fw_cdev_event - Convenience union of fw_cdev_event_ types | 198 | * union fw_cdev_event - Convenience union of fw_cdev_event_ types |
| 151 | * @common: Valid for all types | 199 | * @common: Valid for all types |
| 152 | * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET | 200 | * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET |
| 153 | * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE | 201 | * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE |
| 154 | * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST | 202 | * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST |
| 155 | * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT | 203 | * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT |
| 204 | * @iso_resource: Valid if @common.type == | ||
| 205 | * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or | ||
| 206 | * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED | ||
| 156 | * | 207 | * |
| 157 | * Convenience union for userspace use. Events could be read(2) into an | 208 | * Convenience union for userspace use. Events could be read(2) into an |
| 158 | * appropriately aligned char buffer and then cast to this union for further | 209 | * appropriately aligned char buffer and then cast to this union for further |
| @@ -163,33 +214,47 @@ struct fw_cdev_event_iso_interrupt { | |||
| 163 | * not fit will be discarded so that the next read(2) will return a new event. | 214 | * not fit will be discarded so that the next read(2) will return a new event. |
| 164 | */ | 215 | */ |
| 165 | union fw_cdev_event { | 216 | union fw_cdev_event { |
| 166 | struct fw_cdev_event_common common; | 217 | struct fw_cdev_event_common common; |
| 167 | struct fw_cdev_event_bus_reset bus_reset; | 218 | struct fw_cdev_event_bus_reset bus_reset; |
| 168 | struct fw_cdev_event_response response; | 219 | struct fw_cdev_event_response response; |
| 169 | struct fw_cdev_event_request request; | 220 | struct fw_cdev_event_request request; |
| 170 | struct fw_cdev_event_iso_interrupt iso_interrupt; | 221 | struct fw_cdev_event_iso_interrupt iso_interrupt; |
| 222 | struct fw_cdev_event_iso_resource iso_resource; | ||
| 171 | }; | 223 | }; |
| 172 | 224 | ||
| 173 | #define FW_CDEV_IOC_GET_INFO _IOWR('#', 0x00, struct fw_cdev_get_info) | 225 | /* available since kernel version 2.6.22 */ |
| 174 | #define FW_CDEV_IOC_SEND_REQUEST _IOW('#', 0x01, struct fw_cdev_send_request) | 226 | #define FW_CDEV_IOC_GET_INFO _IOWR('#', 0x00, struct fw_cdev_get_info) |
| 175 | #define FW_CDEV_IOC_ALLOCATE _IOWR('#', 0x02, struct fw_cdev_allocate) | 227 | #define FW_CDEV_IOC_SEND_REQUEST _IOW('#', 0x01, struct fw_cdev_send_request) |
| 176 | #define FW_CDEV_IOC_DEALLOCATE _IOW('#', 0x03, struct fw_cdev_deallocate) | 228 | #define FW_CDEV_IOC_ALLOCATE _IOWR('#', 0x02, struct fw_cdev_allocate) |
| 177 | #define FW_CDEV_IOC_SEND_RESPONSE _IOW('#', 0x04, struct fw_cdev_send_response) | 229 | #define FW_CDEV_IOC_DEALLOCATE _IOW('#', 0x03, struct fw_cdev_deallocate) |
| 178 | #define FW_CDEV_IOC_INITIATE_BUS_RESET _IOW('#', 0x05, struct fw_cdev_initiate_bus_reset) | 230 | #define FW_CDEV_IOC_SEND_RESPONSE _IOW('#', 0x04, struct fw_cdev_send_response) |
| 179 | #define FW_CDEV_IOC_ADD_DESCRIPTOR _IOWR('#', 0x06, struct fw_cdev_add_descriptor) | 231 | #define FW_CDEV_IOC_INITIATE_BUS_RESET _IOW('#', 0x05, struct fw_cdev_initiate_bus_reset) |
| 180 | #define FW_CDEV_IOC_REMOVE_DESCRIPTOR _IOW('#', 0x07, struct fw_cdev_remove_descriptor) | 232 | #define FW_CDEV_IOC_ADD_DESCRIPTOR _IOWR('#', 0x06, struct fw_cdev_add_descriptor) |
| 233 | #define FW_CDEV_IOC_REMOVE_DESCRIPTOR _IOW('#', 0x07, struct fw_cdev_remove_descriptor) | ||
| 234 | #define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IOWR('#', 0x08, struct fw_cdev_create_iso_context) | ||
| 235 | #define FW_CDEV_IOC_QUEUE_ISO _IOWR('#', 0x09, struct fw_cdev_queue_iso) | ||
| 236 | #define FW_CDEV_IOC_START_ISO _IOW('#', 0x0a, struct fw_cdev_start_iso) | ||
| 237 | #define FW_CDEV_IOC_STOP_ISO _IOW('#', 0x0b, struct fw_cdev_stop_iso) | ||
| 181 | 238 | ||
| 182 | #define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IOWR('#', 0x08, struct fw_cdev_create_iso_context) | 239 | /* available since kernel version 2.6.24 */ |
| 183 | #define FW_CDEV_IOC_QUEUE_ISO _IOWR('#', 0x09, struct fw_cdev_queue_iso) | 240 | #define FW_CDEV_IOC_GET_CYCLE_TIMER _IOR('#', 0x0c, struct fw_cdev_get_cycle_timer) |
| 184 | #define FW_CDEV_IOC_START_ISO _IOW('#', 0x0a, struct fw_cdev_start_iso) | ||
| 185 | #define FW_CDEV_IOC_STOP_ISO _IOW('#', 0x0b, struct fw_cdev_stop_iso) | ||
| 186 | #define FW_CDEV_IOC_GET_CYCLE_TIMER _IOR('#', 0x0c, struct fw_cdev_get_cycle_timer) | ||
| 187 | 241 | ||
| 188 | /* FW_CDEV_VERSION History | 242 | /* available since kernel version 2.6.30 */ |
| 189 | * | 243 | #define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE _IOWR('#', 0x0d, struct fw_cdev_allocate_iso_resource) |
| 190 | * 1 Feb 18, 2007: Initial version. | 244 | #define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE _IOW('#', 0x0e, struct fw_cdev_deallocate) |
| 245 | #define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x0f, struct fw_cdev_allocate_iso_resource) | ||
| 246 | #define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x10, struct fw_cdev_allocate_iso_resource) | ||
| 247 | #define FW_CDEV_IOC_GET_SPEED _IO('#', 0x11) /* returns speed code */ | ||
| 248 | #define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request) | ||
| 249 | #define FW_CDEV_IOC_SEND_STREAM_PACKET _IOW('#', 0x13, struct fw_cdev_send_stream_packet) | ||
| 250 | |||
| 251 | /* | ||
| 252 | * FW_CDEV_VERSION History | ||
| 253 | * 1 (2.6.22) - initial version | ||
| 254 | * 2 (2.6.30) - changed &fw_cdev_event_iso_interrupt.header if | ||
| 255 | * &fw_cdev_create_iso_context.header_size is 8 or more | ||
| 191 | */ | 256 | */ |
| 192 | #define FW_CDEV_VERSION 1 | 257 | #define FW_CDEV_VERSION 2 |
| 193 | 258 | ||
| 194 | /** | 259 | /** |
| 195 | * struct fw_cdev_get_info - General purpose information ioctl | 260 | * struct fw_cdev_get_info - General purpose information ioctl |
| @@ -201,7 +266,7 @@ union fw_cdev_event { | |||
| 201 | * case, @rom_length is updated with the actual length of the | 266 | * case, @rom_length is updated with the actual length of the |
| 202 | * configuration ROM. | 267 | * configuration ROM. |
| 203 | * @rom: If non-zero, address of a buffer to be filled by a copy of the | 268 | * @rom: If non-zero, address of a buffer to be filled by a copy of the |
| 204 | * local node's configuration ROM | 269 | * device's configuration ROM |
| 205 | * @bus_reset: If non-zero, address of a buffer to be filled by a | 270 | * @bus_reset: If non-zero, address of a buffer to be filled by a |
| 206 | * &struct fw_cdev_event_bus_reset with the current state | 271 | * &struct fw_cdev_event_bus_reset with the current state |
| 207 | * of the bus. This does not cause a bus reset to happen. | 272 | * of the bus. This does not cause a bus reset to happen. |
| @@ -229,7 +294,7 @@ struct fw_cdev_get_info { | |||
| 229 | * Send a request to the device. This ioctl implements all outgoing requests. | 294 | * Send a request to the device. This ioctl implements all outgoing requests. |
| 230 | * Both quadlet and block request specify the payload as a pointer to the data | 295 | * Both quadlet and block request specify the payload as a pointer to the data |
| 231 | * in the @data field. Once the transaction completes, the kernel writes an | 296 | * in the @data field. Once the transaction completes, the kernel writes an |
| 232 | * &fw_cdev_event_request event back. The @closure field is passed back to | 297 | * &fw_cdev_event_response event back. The @closure field is passed back to |
| 233 | * user space in the response event. | 298 | * user space in the response event. |
| 234 | */ | 299 | */ |
| 235 | struct fw_cdev_send_request { | 300 | struct fw_cdev_send_request { |
| @@ -284,9 +349,9 @@ struct fw_cdev_allocate { | |||
| 284 | }; | 349 | }; |
| 285 | 350 | ||
| 286 | /** | 351 | /** |
| 287 | * struct fw_cdev_deallocate - Free an address range allocation | 352 | * struct fw_cdev_deallocate - Free a CSR address range or isochronous resource |
| 288 | * @handle: Handle to the address range, as returned by the kernel when the | 353 | * @handle: Handle to the address range or iso resource, as returned by the |
| 289 | * range was allocated | 354 | * kernel when the range or resource was allocated |
| 290 | */ | 355 | */ |
| 291 | struct fw_cdev_deallocate { | 356 | struct fw_cdev_deallocate { |
| 292 | __u32 handle; | 357 | __u32 handle; |
| @@ -329,6 +394,9 @@ struct fw_cdev_initiate_bus_reset { | |||
| 329 | * If successful, the kernel adds the descriptor and writes back a handle to the | 394 | * If successful, the kernel adds the descriptor and writes back a handle to the |
| 330 | * kernel-side object to be used for later removal of the descriptor block and | 395 | * kernel-side object to be used for later removal of the descriptor block and |
| 331 | * immediate key. | 396 | * immediate key. |
| 397 | * | ||
| 398 | * This ioctl affects the configuration ROMs of all local nodes. | ||
| 399 | * The ioctl only succeeds on device files which represent a local node. | ||
| 332 | */ | 400 | */ |
| 333 | struct fw_cdev_add_descriptor { | 401 | struct fw_cdev_add_descriptor { |
| 334 | __u32 immediate; | 402 | __u32 immediate; |
| @@ -344,7 +412,7 @@ struct fw_cdev_add_descriptor { | |||
| 344 | * descriptor was added | 412 | * descriptor was added |
| 345 | * | 413 | * |
| 346 | * Remove a descriptor block and accompanying immediate key from the local | 414 | * Remove a descriptor block and accompanying immediate key from the local |
| 347 | * node's configuration ROM. | 415 | * nodes' configuration ROMs. |
| 348 | */ | 416 | */ |
| 349 | struct fw_cdev_remove_descriptor { | 417 | struct fw_cdev_remove_descriptor { |
| 350 | __u32 handle; | 418 | __u32 handle; |
| @@ -370,6 +438,9 @@ struct fw_cdev_remove_descriptor { | |||
| 370 | * | 438 | * |
| 371 | * If a context was successfully created, the kernel writes back a handle to the | 439 | * If a context was successfully created, the kernel writes back a handle to the |
| 372 | * context, which must be passed in for subsequent operations on that context. | 440 | * context, which must be passed in for subsequent operations on that context. |
| 441 | * | ||
| 442 | * Note that the effect of a @header_size > 4 depends on | ||
| 443 | * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt. | ||
| 373 | */ | 444 | */ |
| 374 | struct fw_cdev_create_iso_context { | 445 | struct fw_cdev_create_iso_context { |
| 375 | __u32 type; | 446 | __u32 type; |
| @@ -473,10 +544,91 @@ struct fw_cdev_stop_iso { | |||
| 473 | * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer | 544 | * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer |
| 474 | * and also the system clock. This allows to express the receive time of an | 545 | * and also the system clock. This allows to express the receive time of an |
| 475 | * isochronous packet as a system time with microsecond accuracy. | 546 | * isochronous packet as a system time with microsecond accuracy. |
| 547 | * | ||
| 548 | * @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and | ||
| 549 | * 12 bits cycleOffset, in host byte order. | ||
| 476 | */ | 550 | */ |
| 477 | struct fw_cdev_get_cycle_timer { | 551 | struct fw_cdev_get_cycle_timer { |
| 478 | __u64 local_time; | 552 | __u64 local_time; |
| 479 | __u32 cycle_timer; | 553 | __u32 cycle_timer; |
| 480 | }; | 554 | }; |
| 481 | 555 | ||
| 556 | /** | ||
| 557 | * struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth | ||
| 558 | * @closure: Passed back to userspace in correponding iso resource events | ||
| 559 | * @channels: Isochronous channels of which one is to be (de)allocated | ||
| 560 | * @bandwidth: Isochronous bandwidth units to be (de)allocated | ||
| 561 | * @handle: Handle to the allocation, written by the kernel (only valid in | ||
| 562 | * case of %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctls) | ||
| 563 | * | ||
| 564 | * The %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctl initiates allocation of an | ||
| 565 | * isochronous channel and/or of isochronous bandwidth at the isochronous | ||
| 566 | * resource manager (IRM). Only one of the channels specified in @channels is | ||
| 567 | * allocated. An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED is sent after | ||
| 568 | * communication with the IRM, indicating success or failure in the event data. | ||
| 569 | * The kernel will automatically reallocate the resources after bus resets. | ||
| 570 | * Should a reallocation fail, an %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event | ||
| 571 | * will be sent. The kernel will also automatically deallocate the resources | ||
| 572 | * when the file descriptor is closed. | ||
| 573 | * | ||
| 574 | * The %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE ioctl can be used to initiate | ||
| 575 | * deallocation of resources which were allocated as described above. | ||
| 576 | * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation. | ||
| 577 | * | ||
| 578 | * The %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE ioctl is a variant of allocation | ||
| 579 | * without automatic re- or deallocation. | ||
| 580 | * An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED event concludes this operation, | ||
| 581 | * indicating success or failure in its data. | ||
| 582 | * | ||
| 583 | * The %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE ioctl works like | ||
| 584 | * %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE except that resources are freed | ||
| 585 | * instead of allocated. | ||
| 586 | * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation. | ||
| 587 | * | ||
| 588 | * To summarize, %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE allocates iso resources | ||
| 589 | * for the lifetime of the fd or handle. | ||
| 590 | * In contrast, %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE allocates iso resources | ||
| 591 | * for the duration of a bus generation. | ||
| 592 | * | ||
| 593 | * @channels is a host-endian bitfield with the least significant bit | ||
| 594 | * representing channel 0 and the most significant bit representing channel 63: | ||
| 595 | * 1ULL << c for each channel c that is a candidate for (de)allocation. | ||
| 596 | * | ||
| 597 | * @bandwidth is expressed in bandwidth allocation units, i.e. the time to send | ||
| 598 | * one quadlet of data (payload or header data) at speed S1600. | ||
| 599 | */ | ||
| 600 | struct fw_cdev_allocate_iso_resource { | ||
| 601 | __u64 closure; | ||
| 602 | __u64 channels; | ||
| 603 | __u32 bandwidth; | ||
| 604 | __u32 handle; | ||
| 605 | }; | ||
| 606 | |||
| 607 | /** | ||
| 608 | * struct fw_cdev_send_stream_packet - send an asynchronous stream packet | ||
| 609 | * @length: Length of outgoing payload, in bytes | ||
| 610 | * @tag: Data format tag | ||
| 611 | * @channel: Isochronous channel to transmit to | ||
| 612 | * @sy: Synchronization code | ||
| 613 | * @closure: Passed back to userspace in the response event | ||
| 614 | * @data: Userspace pointer to payload | ||
| 615 | * @generation: The bus generation where packet is valid | ||
| 616 | * @speed: Speed to transmit at | ||
| 617 | * | ||
| 618 | * The %FW_CDEV_IOC_SEND_STREAM_PACKET ioctl sends an asynchronous stream packet | ||
| 619 | * to every device which is listening to the specified channel. The kernel | ||
| 620 | * writes an &fw_cdev_event_response event which indicates success or failure of | ||
| 621 | * the transmission. | ||
| 622 | */ | ||
| 623 | struct fw_cdev_send_stream_packet { | ||
| 624 | __u32 length; | ||
| 625 | __u32 tag; | ||
| 626 | __u32 channel; | ||
| 627 | __u32 sy; | ||
| 628 | __u64 closure; | ||
| 629 | __u64 data; | ||
| 630 | __u32 generation; | ||
| 631 | __u32 speed; | ||
| 632 | }; | ||
| 633 | |||
| 482 | #endif /* _LINUX_FIREWIRE_CDEV_H */ | 634 | #endif /* _LINUX_FIREWIRE_CDEV_H */ |
