diff options
-rw-r--r-- | drivers/firewire/core-cdev.c | 45 | ||||
-rw-r--r-- | include/linux/firewire-cdev.h | 76 |
2 files changed, 110 insertions, 11 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 0cf86bcbeea2..9b8df2039155 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
@@ -49,7 +49,8 @@ | |||
49 | /* | 49 | /* |
50 | * ABI version history is documented in linux/firewire-cdev.h. | 50 | * ABI version history is documented in linux/firewire-cdev.h. |
51 | */ | 51 | */ |
52 | #define FW_CDEV_KERNEL_VERSION 3 | 52 | #define FW_CDEV_KERNEL_VERSION 4 |
53 | #define FW_CDEV_VERSION_EVENT_REQUEST2 4 | ||
53 | 54 | ||
54 | struct client { | 55 | struct client { |
55 | u32 version; | 56 | u32 version; |
@@ -176,7 +177,10 @@ struct outbound_transaction_event { | |||
176 | 177 | ||
177 | struct inbound_transaction_event { | 178 | struct inbound_transaction_event { |
178 | struct event event; | 179 | struct event event; |
179 | struct fw_cdev_event_request request; | 180 | union { |
181 | struct fw_cdev_event_request request; | ||
182 | struct fw_cdev_event_request2 request2; | ||
183 | } req; | ||
180 | }; | 184 | }; |
181 | 185 | ||
182 | struct iso_interrupt_event { | 186 | struct iso_interrupt_event { |
@@ -645,6 +649,7 @@ static void handle_request(struct fw_card *card, struct fw_request *request, | |||
645 | struct address_handler_resource *handler = callback_data; | 649 | struct address_handler_resource *handler = callback_data; |
646 | struct inbound_transaction_resource *r; | 650 | struct inbound_transaction_resource *r; |
647 | struct inbound_transaction_event *e; | 651 | struct inbound_transaction_event *e; |
652 | size_t event_size0; | ||
648 | void *fcp_frame = NULL; | 653 | void *fcp_frame = NULL; |
649 | int ret; | 654 | int ret; |
650 | 655 | ||
@@ -678,15 +683,37 @@ static void handle_request(struct fw_card *card, struct fw_request *request, | |||
678 | if (ret < 0) | 683 | if (ret < 0) |
679 | goto failed; | 684 | goto failed; |
680 | 685 | ||
681 | e->request.type = FW_CDEV_EVENT_REQUEST; | 686 | if (handler->client->version < FW_CDEV_VERSION_EVENT_REQUEST2) { |
682 | e->request.tcode = tcode; | 687 | struct fw_cdev_event_request *req = &e->req.request; |
683 | e->request.offset = offset; | 688 | |
684 | e->request.length = length; | 689 | if (tcode & 0x10) |
685 | e->request.handle = r->resource.handle; | 690 | tcode = TCODE_LOCK_REQUEST; |
686 | e->request.closure = handler->closure; | 691 | |
692 | req->type = FW_CDEV_EVENT_REQUEST; | ||
693 | req->tcode = tcode; | ||
694 | req->offset = offset; | ||
695 | req->length = length; | ||
696 | req->handle = r->resource.handle; | ||
697 | req->closure = handler->closure; | ||
698 | event_size0 = sizeof(*req); | ||
699 | } else { | ||
700 | struct fw_cdev_event_request2 *req = &e->req.request2; | ||
701 | |||
702 | req->type = FW_CDEV_EVENT_REQUEST2; | ||
703 | req->tcode = tcode; | ||
704 | req->offset = offset; | ||
705 | req->source_node_id = source; | ||
706 | req->destination_node_id = destination; | ||
707 | req->card = card->index; | ||
708 | req->generation = generation; | ||
709 | req->length = length; | ||
710 | req->handle = r->resource.handle; | ||
711 | req->closure = handler->closure; | ||
712 | event_size0 = sizeof(*req); | ||
713 | } | ||
687 | 714 | ||
688 | queue_event(handler->client, &e->event, | 715 | queue_event(handler->client, &e->event, |
689 | &e->request, sizeof(e->request), r->data, length); | 716 | &e->req, event_size0, r->data, length); |
690 | return; | 717 | return; |
691 | 718 | ||
692 | failed: | 719 | failed: |
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 0d0cc07358af..52c7ffe934ad 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h | |||
@@ -32,6 +32,9 @@ | |||
32 | #define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04 | 32 | #define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04 |
33 | #define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05 | 33 | #define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05 |
34 | 34 | ||
35 | /* available since kernel version 2.6.36 */ | ||
36 | #define FW_CDEV_EVENT_REQUEST2 0x06 | ||
37 | |||
35 | /** | 38 | /** |
36 | * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types | 39 | * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types |
37 | * @closure: For arbitrary use by userspace | 40 | * @closure: For arbitrary use by userspace |
@@ -98,11 +101,46 @@ struct fw_cdev_event_response { | |||
98 | }; | 101 | }; |
99 | 102 | ||
100 | /** | 103 | /** |
101 | * struct fw_cdev_event_request - Sent on incoming request to an address region | 104 | * struct fw_cdev_event_request - Old version of &fw_cdev_event_request2 |
102 | * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl | 105 | * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl |
103 | * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST | 106 | * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST |
107 | * @tcode: See &fw_cdev_event_request2 | ||
108 | * @offset: See &fw_cdev_event_request2 | ||
109 | * @handle: See &fw_cdev_event_request2 | ||
110 | * @length: See &fw_cdev_event_request2 | ||
111 | * @data: See &fw_cdev_event_request2 | ||
112 | * | ||
113 | * This event is sent instead of &fw_cdev_event_request2 if the kernel or | ||
114 | * the client implements ABI version <= 3. | ||
115 | * | ||
116 | * Unlike &fw_cdev_event_request2, the sender identity cannot be established, | ||
117 | * broadcast write requests cannot be distinguished from unicast writes, and | ||
118 | * @tcode of lock requests is %TCODE_LOCK_REQUEST. | ||
119 | * | ||
120 | * Requests to the FCP_REQUEST or FCP_RESPONSE register are responded to as | ||
121 | * with &fw_cdev_event_request2, except in kernel 2.6.32 and older which send | ||
122 | * the response packet of the client's %FW_CDEV_IOC_SEND_RESPONSE ioctl. | ||
123 | */ | ||
124 | struct fw_cdev_event_request { | ||
125 | __u64 closure; | ||
126 | __u32 type; | ||
127 | __u32 tcode; | ||
128 | __u64 offset; | ||
129 | __u32 handle; | ||
130 | __u32 length; | ||
131 | __u32 data[0]; | ||
132 | }; | ||
133 | |||
134 | /** | ||
135 | * struct fw_cdev_event_request2 - Sent on incoming request to an address region | ||
136 | * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl | ||
137 | * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST2 | ||
104 | * @tcode: Transaction code of the incoming request | 138 | * @tcode: Transaction code of the incoming request |
105 | * @offset: The offset into the 48-bit per-node address space | 139 | * @offset: The offset into the 48-bit per-node address space |
140 | * @source_node_id: Sender node ID | ||
141 | * @destination_node_id: Destination node ID | ||
142 | * @card: The index of the card from which the request came | ||
143 | * @generation: Bus generation in which the request is valid | ||
106 | * @handle: Reference to the kernel-side pending request | 144 | * @handle: Reference to the kernel-side pending request |
107 | * @length: Data length, i.e. the request's payload size in bytes | 145 | * @length: Data length, i.e. the request's payload size in bytes |
108 | * @data: Incoming data, if any | 146 | * @data: Incoming data, if any |
@@ -115,12 +153,42 @@ struct fw_cdev_event_response { | |||
115 | * | 153 | * |
116 | * The payload data for requests carrying data (write and lock requests) | 154 | * The payload data for requests carrying data (write and lock requests) |
117 | * follows immediately and can be accessed through the @data field. | 155 | * follows immediately and can be accessed through the @data field. |
156 | * | ||
157 | * Unlike &fw_cdev_event_request, @tcode of lock requests is one of the | ||
158 | * firewire-core specific %TCODE_LOCK_MASK_SWAP...%TCODE_LOCK_VENDOR_DEPENDENT, | ||
159 | * i.e. encodes the extended transaction code. | ||
160 | * | ||
161 | * @card may differ from &fw_cdev_get_info.card because requests are received | ||
162 | * from all cards of the Linux host. @source_node_id, @destination_node_id, and | ||
163 | * @generation pertain to that card. Destination node ID and bus generation may | ||
164 | * therefore differ from the corresponding fields of the last | ||
165 | * &fw_cdev_event_bus_reset. | ||
166 | * | ||
167 | * @destination_node_id may also differ from the current node ID because of a | ||
168 | * non-local bus ID part or in case of a broadcast write request. Note, a | ||
169 | * client must call an %FW_CDEV_IOC_SEND_RESPONSE ioctl even in case of a | ||
170 | * broadcast write request; the kernel will then release the kernel-side pending | ||
171 | * request but will not actually send a response packet. | ||
172 | * | ||
173 | * In case of a write request to FCP_REQUEST or FCP_RESPONSE, the kernel already | ||
174 | * sent a write response immediately after the request was received; in this | ||
175 | * case the client must still call an %FW_CDEV_IOC_SEND_RESPONSE ioctl to | ||
176 | * release the kernel-side pending request, though another response won't be | ||
177 | * sent. | ||
178 | * | ||
179 | * If the client subsequently needs to initiate requests to the sender node of | ||
180 | * an &fw_cdev_event_request2, it needs to use a device file with matching | ||
181 | * card index, node ID, and generation for outbound requests. | ||
118 | */ | 182 | */ |
119 | struct fw_cdev_event_request { | 183 | struct fw_cdev_event_request2 { |
120 | __u64 closure; | 184 | __u64 closure; |
121 | __u32 type; | 185 | __u32 type; |
122 | __u32 tcode; | 186 | __u32 tcode; |
123 | __u64 offset; | 187 | __u64 offset; |
188 | __u32 source_node_id; | ||
189 | __u32 destination_node_id; | ||
190 | __u32 card; | ||
191 | __u32 generation; | ||
124 | __u32 handle; | 192 | __u32 handle; |
125 | __u32 length; | 193 | __u32 length; |
126 | __u32 data[0]; | 194 | __u32 data[0]; |
@@ -200,6 +268,7 @@ struct fw_cdev_event_iso_resource { | |||
200 | * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET | 268 | * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET |
201 | * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE | 269 | * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE |
202 | * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST | 270 | * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST |
271 | * @request2: Valid if @common.type == %FW_CDEV_EVENT_REQUEST2 | ||
203 | * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT | 272 | * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT |
204 | * @iso_resource: Valid if @common.type == | 273 | * @iso_resource: Valid if @common.type == |
205 | * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or | 274 | * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or |
@@ -218,6 +287,7 @@ union fw_cdev_event { | |||
218 | struct fw_cdev_event_bus_reset bus_reset; | 287 | struct fw_cdev_event_bus_reset bus_reset; |
219 | struct fw_cdev_event_response response; | 288 | struct fw_cdev_event_response response; |
220 | struct fw_cdev_event_request request; | 289 | struct fw_cdev_event_request request; |
290 | struct fw_cdev_event_request2 request2; /* added in 2.6.36 */ | ||
221 | struct fw_cdev_event_iso_interrupt iso_interrupt; | 291 | struct fw_cdev_event_iso_interrupt iso_interrupt; |
222 | struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ | 292 | struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ |
223 | }; | 293 | }; |
@@ -263,8 +333,10 @@ union fw_cdev_event { | |||
263 | * (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt | 333 | * (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt |
264 | * (2.6.33) - IR has always packet-per-buffer semantics now, not one of | 334 | * (2.6.33) - IR has always packet-per-buffer semantics now, not one of |
265 | * dual-buffer or packet-per-buffer depending on hardware | 335 | * dual-buffer or packet-per-buffer depending on hardware |
336 | * - shared use and auto-response for FCP registers | ||
266 | * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable | 337 | * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable |
267 | * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 | 338 | * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 |
339 | * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2 | ||
268 | */ | 340 | */ |
269 | #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ | 341 | #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ |
270 | 342 | ||