diff options
-rw-r--r-- | drivers/firewire/core-cdev.c | 12 | ||||
-rw-r--r-- | include/linux/firewire-cdev.h | 29 |
2 files changed, 33 insertions, 8 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 31863cf8b6c4..f40098dec14b 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
@@ -50,8 +50,9 @@ | |||
50 | /* | 50 | /* |
51 | * ABI version history is documented in linux/firewire-cdev.h. | 51 | * ABI version history is documented in linux/firewire-cdev.h. |
52 | */ | 52 | */ |
53 | #define FW_CDEV_KERNEL_VERSION 4 | 53 | #define FW_CDEV_KERNEL_VERSION 4 |
54 | #define FW_CDEV_VERSION_EVENT_REQUEST2 4 | 54 | #define FW_CDEV_VERSION_EVENT_REQUEST2 4 |
55 | #define FW_CDEV_VERSION_ALLOCATE_REGION_END 4 | ||
55 | 56 | ||
56 | struct client { | 57 | struct client { |
57 | u32 version; | 58 | u32 version; |
@@ -773,7 +774,11 @@ static int ioctl_allocate(struct client *client, union ioctl_arg *arg) | |||
773 | return -ENOMEM; | 774 | return -ENOMEM; |
774 | 775 | ||
775 | region.start = a->offset; | 776 | region.start = a->offset; |
776 | region.end = a->offset + a->length; | 777 | if (client->version < FW_CDEV_VERSION_ALLOCATE_REGION_END) |
778 | region.end = a->offset + a->length; | ||
779 | else | ||
780 | region.end = a->region_end; | ||
781 | |||
777 | r->handler.length = a->length; | 782 | r->handler.length = a->length; |
778 | r->handler.address_callback = handle_request; | 783 | r->handler.address_callback = handle_request; |
779 | r->handler.callback_data = r; | 784 | r->handler.callback_data = r; |
@@ -785,6 +790,7 @@ static int ioctl_allocate(struct client *client, union ioctl_arg *arg) | |||
785 | kfree(r); | 790 | kfree(r); |
786 | return ret; | 791 | return ret; |
787 | } | 792 | } |
793 | a->offset = r->handler.offset; | ||
788 | 794 | ||
789 | r->resource.release = release_address_handler; | 795 | r->resource.release = release_address_handler; |
790 | ret = add_client_resource(client, &r->resource, GFP_KERNEL); | 796 | ret = add_client_resource(client, &r->resource, GFP_KERNEL); |
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index da0fec7e8dc0..14831119ff71 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h | |||
@@ -394,6 +394,7 @@ union fw_cdev_event { | |||
394 | * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_* | 394 | * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_* |
395 | * - implemented &fw_cdev_event_bus_reset.bm_node_id | 395 | * - implemented &fw_cdev_event_bus_reset.bm_node_id |
396 | * - added %FW_CDEV_IOC_SEND_PHY_PACKET, _RECEIVE_PHY_PACKETS | 396 | * - added %FW_CDEV_IOC_SEND_PHY_PACKET, _RECEIVE_PHY_PACKETS |
397 | * - added &fw_cdev_allocate.region_end | ||
397 | */ | 398 | */ |
398 | #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ | 399 | #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ |
399 | 400 | ||
@@ -473,17 +474,21 @@ struct fw_cdev_send_response { | |||
473 | }; | 474 | }; |
474 | 475 | ||
475 | /** | 476 | /** |
476 | * struct fw_cdev_allocate - Allocate a CSR address range | 477 | * struct fw_cdev_allocate - Allocate a CSR in an address range |
477 | * @offset: Start offset of the address range | 478 | * @offset: Start offset of the address range |
478 | * @closure: To be passed back to userspace in request events | 479 | * @closure: To be passed back to userspace in request events |
479 | * @length: Length of the address range, in bytes | 480 | * @length: Length of the CSR, in bytes |
480 | * @handle: Handle to the allocation, written by the kernel | 481 | * @handle: Handle to the allocation, written by the kernel |
482 | * @region_end: First address above the address range (added in ABI v4, 2.6.36) | ||
481 | * | 483 | * |
482 | * Allocate an address range in the 48-bit address space on the local node | 484 | * Allocate an address range in the 48-bit address space on the local node |
483 | * (the controller). This allows userspace to listen for requests with an | 485 | * (the controller). This allows userspace to listen for requests with an |
484 | * offset within that address range. When the kernel receives a request | 486 | * offset within that address range. Every time when the kernel receives a |
485 | * within the range, an &fw_cdev_event_request event will be written back. | 487 | * request within the range, an &fw_cdev_event_request2 event will be emitted. |
486 | * The @closure field is passed back to userspace in the response event. | 488 | * (If the kernel or the client implements ABI version <= 3, an |
489 | * &fw_cdev_event_request will be generated instead.) | ||
490 | * | ||
491 | * The @closure field is passed back to userspace in these request events. | ||
487 | * The @handle field is an out parameter, returning a handle to the allocated | 492 | * The @handle field is an out parameter, returning a handle to the allocated |
488 | * range to be used for later deallocation of the range. | 493 | * range to be used for later deallocation of the range. |
489 | * | 494 | * |
@@ -491,12 +496,26 @@ struct fw_cdev_send_response { | |||
491 | * is exclusive except for the FCP command and response registers. If an | 496 | * is exclusive except for the FCP command and response registers. If an |
492 | * exclusive address region is already in use, the ioctl fails with errno set | 497 | * exclusive address region is already in use, the ioctl fails with errno set |
493 | * to %EBUSY. | 498 | * to %EBUSY. |
499 | * | ||
500 | * If kernel and client implement ABI version >= 4, the kernel looks up a free | ||
501 | * spot of size @length inside [@offset..@region_end) and, if found, writes | ||
502 | * the start address of the new CSR back in @offset. I.e. @offset is an | ||
503 | * in and out parameter. If this automatic placement of a CSR in a bigger | ||
504 | * address range is not desired, the client simply needs to set @region_end | ||
505 | * = @offset + @length. | ||
506 | * | ||
507 | * If the kernel or the client implements ABI version <= 3, @region_end is | ||
508 | * ignored and effectively assumed to be @offset + @length. | ||
509 | * | ||
510 | * @region_end is only present in a kernel header >= 2.6.36. If necessary, | ||
511 | * this can for example be tested by #ifdef FW_CDEV_EVENT_REQUEST2. | ||
494 | */ | 512 | */ |
495 | struct fw_cdev_allocate { | 513 | struct fw_cdev_allocate { |
496 | __u64 offset; | 514 | __u64 offset; |
497 | __u64 closure; | 515 | __u64 closure; |
498 | __u32 length; | 516 | __u32 length; |
499 | __u32 handle; | 517 | __u32 handle; |
518 | __u64 region_end; /* available since kernel version 2.6.36 */ | ||
500 | }; | 519 | }; |
501 | 520 | ||
502 | /** | 521 | /** |