Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firewire: core: fix card->reset_jiffies overflow

On a 32-bit machine with, e.g., HZ=1000, jiffies will overflow after
about 50 days, so if there are between 25 and 50 days between bus
resets, the card->reset_jiffies comparisons can get wrong results.

To fix this, ensure that this timestamp always uses 64 bits.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: "Stefan Richter" <stefanr@s5r6.in-berlin.de>

authored by

Clemens Ladisch and committed by
Stefan Richter
e71084af dbc9880f

+9 -6
+3 -2
drivers/firewire/core-card.c
··· 233 233 234 234 /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */ 235 235 if (card->reset_jiffies != 0 && 236 - time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) { 236 + time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) { 237 237 if (!schedule_delayed_work(&card->br_work, 2 * HZ)) 238 238 fw_card_put(card); 239 239 return; ··· 316 316 irm_id = card->irm_node->node_id; 317 317 local_id = card->local_node->node_id; 318 318 319 - grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); 319 + grace = time_after64(get_jiffies_64(), 320 + card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); 320 321 321 322 if ((is_next_generation(generation, card->bm_generation) && 322 323 !card->bm_abdicate) ||
+2 -1
drivers/firewire/core-cdev.c
··· 1205 1205 todo = r->todo; 1206 1206 /* Allow 1000ms grace period for other reallocations. */ 1207 1207 if (todo == ISO_RES_ALLOC && 1208 - time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { 1208 + time_before64(get_jiffies_64(), 1209 + client->device->card->reset_jiffies + HZ)) { 1209 1210 schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3)); 1210 1211 skip = true; 1211 1212 } else {
+2 -1
drivers/firewire/core-device.c
··· 747 747 container_of(work, struct fw_device, work.work); 748 748 int minor = MINOR(device->device.devt); 749 749 750 - if (time_is_after_jiffies(device->card->reset_jiffies + SHUTDOWN_DELAY) 750 + if (time_before64(get_jiffies_64(), 751 + device->card->reset_jiffies + SHUTDOWN_DELAY) 751 752 && !list_empty(&device->card->link)) { 752 753 schedule_delayed_work(&device->work, SHUTDOWN_DELAY); 753 754 return;
+1 -1
drivers/firewire/core-topology.c
··· 545 545 */ 546 546 smp_wmb(); 547 547 card->generation = generation; 548 - card->reset_jiffies = jiffies; 548 + card->reset_jiffies = get_jiffies_64(); 549 549 card->bm_node_id = 0xffff; 550 550 card->bm_abdicate = bm_abdicate; 551 551 fw_schedule_bm_work(card, 0);
+1 -1
include/linux/firewire.h
··· 89 89 int current_tlabel; 90 90 u64 tlabel_mask; 91 91 struct list_head transaction_list; 92 - unsigned long reset_jiffies; 92 + u64 reset_jiffies; 93 93 94 94 u32 split_timeout_hi; 95 95 u32 split_timeout_lo;