aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-cdev.c
diff options
context:
space:
mode:
authorDavid Moore <dcm@acm.org>2008-07-30 02:46:25 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2008-08-02 14:03:49 -0400
commit8401d92ba46a1e859464cbd9c9ee304f6e361da3 (patch)
treecdf4ecb706a4f2417b57a8d52d887cd4b2c12130 /drivers/firewire/fw-cdev.c
parentf05e21b39f7dddcebab03ff329fef5783fea58d4 (diff)
firewire: Preserve response data alignment bug when it is harmless
Recently, a bug having to do with the alignment of transaction response data was fixed. However, some apps such as libdc1394 relied on the presence of that bug in order to function correctly. In order to stay compatible with old versions of those apps, this patch preserves the bug in cases where it is harmless to normal operation (such as the single quadlet read) due to a simple duplication of data. This guarantees maximum compatability for those users who are using the old app with the fixed kernel. Signed-off-by: David Moore <dcm@acm.org> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-cdev.c')
-rw-r--r--drivers/firewire/fw-cdev.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index bc81d6fcd2fd..2e6d5848d217 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -369,22 +369,33 @@ complete_transaction(struct fw_card *card, int rcode,
369 struct response *response = data; 369 struct response *response = data;
370 struct client *client = response->client; 370 struct client *client = response->client;
371 unsigned long flags; 371 unsigned long flags;
372 struct fw_cdev_event_response *r = &response->response;
372 373
373 if (length < response->response.length) 374 if (length < r->length)
374 response->response.length = length; 375 r->length = length;
375 if (rcode == RCODE_COMPLETE) 376 if (rcode == RCODE_COMPLETE)
376 memcpy(response->response.data, payload, 377 memcpy(r->data, payload, r->length);
377 response->response.length);
378 378
379 spin_lock_irqsave(&client->lock, flags); 379 spin_lock_irqsave(&client->lock, flags);
380 list_del(&response->resource.link); 380 list_del(&response->resource.link);
381 spin_unlock_irqrestore(&client->lock, flags); 381 spin_unlock_irqrestore(&client->lock, flags);
382 382
383 response->response.type = FW_CDEV_EVENT_RESPONSE; 383 r->type = FW_CDEV_EVENT_RESPONSE;
384 response->response.rcode = rcode; 384 r->rcode = rcode;
385 queue_event(client, &response->event, &response->response, 385
386 sizeof(response->response) + response->response.length, 386 /*
387 NULL, 0); 387 * In the case that sizeof(*r) doesn't align with the position of the
388 * data, and the read is short, preserve an extra copy of the data
389 * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless
390 * for short reads and some apps depended on it, this is both safe
391 * and prudent for compatibility.
392 */
393 if (r->length <= sizeof(*r) - offsetof(typeof(*r), data))
394 queue_event(client, &response->event, r, sizeof(*r),
395 r->data, r->length);
396 else
397 queue_event(client, &response->event, r, sizeof(*r) + r->length,
398 NULL, 0);
388} 399}
389 400
390static int ioctl_send_request(struct client *client, void *buffer) 401static int ioctl_send_request(struct client *client, void *buffer)