diff options
Diffstat (limited to 'drivers/firewire/fw-cdev.c')
-rw-r--r-- | drivers/firewire/fw-cdev.c | 46 |
1 files changed, 19 insertions, 27 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) = { |