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 | /** |
