diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firewire/fw-cdev.c | 46 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.c | 42 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.h | 9 |
3 files changed, 40 insertions, 57 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 95a207545eb3..7eb6594cc3e5 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c | |||
@@ -522,7 +522,8 @@ static int init_request(struct client *client, | |||
522 | struct outbound_transaction_event *e; | 522 | struct outbound_transaction_event *e; |
523 | int ret; | 523 | int ret; |
524 | 524 | ||
525 | if (request->length > 4096 || request->length > 512 << speed) | 525 | if (request->tcode != TCODE_STREAM_DATA && |
526 | (request->length > 4096 || request->length > 512 << speed)) | ||
526 | return -EIO; | 527 | return -EIO; |
527 | 528 | ||
528 | e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); | 529 | e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); |
@@ -1247,36 +1248,27 @@ static int ioctl_send_broadcast_request(struct client *client, void *buffer) | |||
1247 | return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); | 1248 | return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); |
1248 | } | 1249 | } |
1249 | 1250 | ||
1250 | struct stream_packet { | ||
1251 | struct fw_packet packet; | ||
1252 | u8 data[0]; | ||
1253 | }; | ||
1254 | |||
1255 | static void send_stream_packet_done(struct fw_packet *packet, | ||
1256 | struct fw_card *card, int status) | ||
1257 | { | ||
1258 | kfree(container_of(packet, struct stream_packet, packet)); | ||
1259 | } | ||
1260 | |||
1261 | static int ioctl_send_stream_packet(struct client *client, void *buffer) | 1251 | static int ioctl_send_stream_packet(struct client *client, void *buffer) |
1262 | { | 1252 | { |
1263 | struct fw_cdev_send_stream_packet *request = buffer; | 1253 | struct fw_cdev_send_stream_packet *p = buffer; |
1264 | struct stream_packet *p; | 1254 | struct fw_cdev_send_request request; |
1255 | int dest; | ||
1265 | 1256 | ||
1266 | p = kmalloc(sizeof(*p) + request->size, GFP_KERNEL); | 1257 | if (p->speed > client->device->card->link_speed || |
1267 | if (p == NULL) | 1258 | p->length > 1024 << p->speed) |
1268 | return -ENOMEM; | 1259 | return -EIO; |
1269 | 1260 | ||
1270 | if (request->data && | 1261 | if (p->tag > 3 || p->channel > 63 || p->sy > 15) |
1271 | copy_from_user(p->data, u64_to_uptr(request->data), request->size)) { | 1262 | return -EINVAL; |
1272 | kfree(p); | 1263 | |
1273 | return -EFAULT; | 1264 | dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy); |
1274 | } | 1265 | request.tcode = TCODE_STREAM_DATA; |
1275 | fw_send_stream_packet(client->device->card, &p->packet, | 1266 | request.length = p->length; |
1276 | request->generation, request->speed, | 1267 | request.closure = p->closure; |
1277 | request->channel, request->sy, request->tag, | 1268 | request.data = p->data; |
1278 | p->data, request->size, send_stream_packet_done); | 1269 | request.generation = p->generation; |
1279 | return 0; | 1270 | |
1271 | return init_request(client, &request, dest, p->speed); | ||
1280 | } | 1272 | } |
1281 | 1273 | ||
1282 | static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { | 1274 | static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { |
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index e3da58991960..4a9b37461c26 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c | |||
@@ -37,10 +37,6 @@ | |||
37 | #include "fw-topology.h" | 37 | #include "fw-topology.h" |
38 | #include "fw-device.h" | 38 | #include "fw-device.h" |
39 | 39 | ||
40 | #define HEADER_TAG(tag) ((tag) << 14) | ||
41 | #define HEADER_CHANNEL(ch) ((ch) << 8) | ||
42 | #define HEADER_SY(sy) ((sy) << 0) | ||
43 | |||
44 | #define HEADER_PRI(pri) ((pri) << 0) | 40 | #define HEADER_PRI(pri) ((pri) << 0) |
45 | #define HEADER_TCODE(tcode) ((tcode) << 4) | 41 | #define HEADER_TCODE(tcode) ((tcode) << 4) |
46 | #define HEADER_RETRY(retry) ((retry) << 8) | 42 | #define HEADER_RETRY(retry) ((retry) << 8) |
@@ -158,6 +154,18 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, | |||
158 | { | 154 | { |
159 | int ext_tcode; | 155 | int ext_tcode; |
160 | 156 | ||
157 | if (tcode == TCODE_STREAM_DATA) { | ||
158 | packet->header[0] = | ||
159 | HEADER_DATA_LENGTH(length) | | ||
160 | destination_id | | ||
161 | HEADER_TCODE(TCODE_STREAM_DATA); | ||
162 | packet->header_length = 4; | ||
163 | packet->payload = payload; | ||
164 | packet->payload_length = length; | ||
165 | |||
166 | goto common; | ||
167 | } | ||
168 | |||
161 | if (tcode > 0x10) { | 169 | if (tcode > 0x10) { |
162 | ext_tcode = tcode & ~0x10; | 170 | ext_tcode = tcode & ~0x10; |
163 | tcode = TCODE_LOCK_REQUEST; | 171 | tcode = TCODE_LOCK_REQUEST; |
@@ -204,7 +212,7 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, | |||
204 | packet->payload_length = 0; | 212 | packet->payload_length = 0; |
205 | break; | 213 | break; |
206 | } | 214 | } |
207 | 215 | common: | |
208 | packet->speed = speed; | 216 | packet->speed = speed; |
209 | packet->generation = generation; | 217 | packet->generation = generation; |
210 | packet->ack = 0; | 218 | packet->ack = 0; |
@@ -246,6 +254,9 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, | |||
246 | * @param callback function to be called when the transaction is completed | 254 | * @param callback function to be called when the transaction is completed |
247 | * @param callback_data pointer to arbitrary data, which will be | 255 | * @param callback_data pointer to arbitrary data, which will be |
248 | * passed to the callback | 256 | * passed to the callback |
257 | * | ||
258 | * In case of asynchronous stream packets i.e. TCODE_STREAM_DATA, the caller | ||
259 | * needs to synthesize @destination_id with fw_stream_packet_destination_id(). | ||
249 | */ | 260 | */ |
250 | void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, | 261 | void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, |
251 | int destination_id, int generation, int speed, | 262 | int destination_id, int generation, int speed, |
@@ -297,27 +308,6 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, | |||
297 | } | 308 | } |
298 | EXPORT_SYMBOL(fw_send_request); | 309 | EXPORT_SYMBOL(fw_send_request); |
299 | 310 | ||
300 | void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p, | ||
301 | int generation, int speed, int channel, int sy, int tag, | ||
302 | void *payload, size_t length, fw_packet_callback_t callback) | ||
303 | { | ||
304 | p->callback = callback; | ||
305 | p->header[0] = | ||
306 | HEADER_DATA_LENGTH(length) | ||
307 | | HEADER_TAG(tag) | ||
308 | | HEADER_CHANNEL(channel) | ||
309 | | HEADER_TCODE(TCODE_STREAM_DATA) | ||
310 | | HEADER_SY(sy); | ||
311 | p->header_length = 4; | ||
312 | p->payload = payload; | ||
313 | p->payload_length = length; | ||
314 | p->speed = speed; | ||
315 | p->generation = generation; | ||
316 | p->ack = 0; | ||
317 | |||
318 | card->driver->send_request(card, p); | ||
319 | } | ||
320 | |||
321 | struct transaction_callback_data { | 311 | struct transaction_callback_data { |
322 | struct completion done; | 312 | struct completion done; |
323 | void *payload; | 313 | void *payload; |
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index f90f09c05833..d4f42cecbdfa 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
@@ -412,10 +412,6 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, | |||
412 | int tcode, int destination_id, int generation, int speed, | 412 | int tcode, int destination_id, int generation, int speed, |
413 | unsigned long long offset, void *payload, size_t length, | 413 | unsigned long long offset, void *payload, size_t length, |
414 | fw_transaction_callback_t callback, void *callback_data); | 414 | fw_transaction_callback_t callback, void *callback_data); |
415 | void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p, | ||
416 | int generation, int speed, int channel, int sy, int tag, | ||
417 | void *payload, size_t length, fw_packet_callback_t callback); | ||
418 | |||
419 | int fw_cancel_transaction(struct fw_card *card, | 415 | int fw_cancel_transaction(struct fw_card *card, |
420 | struct fw_transaction *transaction); | 416 | struct fw_transaction *transaction); |
421 | void fw_flush_transactions(struct fw_card *card); | 417 | void fw_flush_transactions(struct fw_card *card); |
@@ -425,6 +421,11 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, | |||
425 | void fw_send_phy_config(struct fw_card *card, | 421 | void fw_send_phy_config(struct fw_card *card, |
426 | int node_id, int generation, int gap_count); | 422 | int node_id, int generation, int gap_count); |
427 | 423 | ||
424 | static inline int fw_stream_packet_destination_id(int tag, int channel, int sy) | ||
425 | { | ||
426 | return tag << 14 | channel << 8 | sy; | ||
427 | } | ||
428 | |||
428 | /* | 429 | /* |
429 | * Called by the topology code to inform the device code of node | 430 | * Called by the topology code to inform the device code of node |
430 | * activity; found, lost, or updated nodes. | 431 | * activity; found, lost, or updated nodes. |