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>
This commit is contained in:
Clemens Ladisch 2011-01-22 15:05:03 +01:00 committed by Stefan Richter
parent dbc9880fa7
commit e71084af58
5 changed files with 9 additions and 6 deletions

View File

@ -233,7 +233,7 @@ static void br_work(struct work_struct *work)
/* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */ /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
if (card->reset_jiffies != 0 && if (card->reset_jiffies != 0 &&
time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) { time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) {
if (!schedule_delayed_work(&card->br_work, 2 * HZ)) if (!schedule_delayed_work(&card->br_work, 2 * HZ))
fw_card_put(card); fw_card_put(card);
return; return;
@ -316,7 +316,8 @@ static void bm_work(struct work_struct *work)
irm_id = card->irm_node->node_id; irm_id = card->irm_node->node_id;
local_id = card->local_node->node_id; local_id = card->local_node->node_id;
grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); grace = time_after64(get_jiffies_64(),
card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
if ((is_next_generation(generation, card->bm_generation) && if ((is_next_generation(generation, card->bm_generation) &&
!card->bm_abdicate) || !card->bm_abdicate) ||

View File

@ -1205,7 +1205,8 @@ static void iso_resource_work(struct work_struct *work)
todo = r->todo; todo = r->todo;
/* Allow 1000ms grace period for other reallocations. */ /* Allow 1000ms grace period for other reallocations. */
if (todo == ISO_RES_ALLOC && if (todo == ISO_RES_ALLOC &&
time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { time_before64(get_jiffies_64(),
client->device->card->reset_jiffies + HZ)) {
schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3)); schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3));
skip = true; skip = true;
} else { } else {

View File

@ -747,7 +747,8 @@ static void fw_device_shutdown(struct work_struct *work)
container_of(work, struct fw_device, work.work); container_of(work, struct fw_device, work.work);
int minor = MINOR(device->device.devt); int minor = MINOR(device->device.devt);
if (time_is_after_jiffies(device->card->reset_jiffies + SHUTDOWN_DELAY) if (time_before64(get_jiffies_64(),
device->card->reset_jiffies + SHUTDOWN_DELAY)
&& !list_empty(&device->card->link)) { && !list_empty(&device->card->link)) {
schedule_delayed_work(&device->work, SHUTDOWN_DELAY); schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
return; return;

View File

@ -545,7 +545,7 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
*/ */
smp_wmb(); smp_wmb();
card->generation = generation; card->generation = generation;
card->reset_jiffies = jiffies; card->reset_jiffies = get_jiffies_64();
card->bm_node_id = 0xffff; card->bm_node_id = 0xffff;
card->bm_abdicate = bm_abdicate; card->bm_abdicate = bm_abdicate;
fw_schedule_bm_work(card, 0); fw_schedule_bm_work(card, 0);

View File

@ -89,7 +89,7 @@ struct fw_card {
int current_tlabel; int current_tlabel;
u64 tlabel_mask; u64 tlabel_mask;
struct list_head transaction_list; struct list_head transaction_list;
unsigned long reset_jiffies; u64 reset_jiffies;
u32 split_timeout_hi; u32 split_timeout_hi;
u32 split_timeout_lo; u32 split_timeout_lo;