diff options
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 76 |
1 files changed, 42 insertions, 34 deletions
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 1d5b949d4fd0..3ab3db39fc52 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c | |||
@@ -557,38 +557,44 @@ EXPORT_SYMBOL(fcoe_ctlr_els_send); | |||
557 | * | 557 | * |
558 | * Called with lock held and preemption disabled. | 558 | * Called with lock held and preemption disabled. |
559 | * | 559 | * |
560 | * An FCF is considered old if we have missed three advertisements. | 560 | * An FCF is considered old if we have missed two advertisements. |
561 | * That is, there have been no valid advertisement from it for three | 561 | * That is, there have been no valid advertisement from it for 2.5 |
562 | * times its keep-alive period including fuzz. | 562 | * times its keep-alive period. |
563 | * | 563 | * |
564 | * In addition, determine the time when an FCF selection can occur. | 564 | * In addition, determine the time when an FCF selection can occur. |
565 | * | 565 | * |
566 | * Also, increment the MissDiscAdvCount when no advertisement is received | 566 | * Also, increment the MissDiscAdvCount when no advertisement is received |
567 | * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB). | 567 | * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB). |
568 | * | ||
569 | * Returns the time in jiffies for the next call. | ||
568 | */ | 570 | */ |
569 | static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | 571 | static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) |
570 | { | 572 | { |
571 | struct fcoe_fcf *fcf; | 573 | struct fcoe_fcf *fcf; |
572 | struct fcoe_fcf *next; | 574 | struct fcoe_fcf *next; |
575 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); | ||
576 | unsigned long deadline; | ||
573 | unsigned long sel_time = 0; | 577 | unsigned long sel_time = 0; |
574 | unsigned long mda_time = 0; | ||
575 | struct fcoe_dev_stats *stats; | 578 | struct fcoe_dev_stats *stats; |
576 | 579 | ||
577 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { | 580 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { |
578 | mda_time = fcf->fka_period + (fcf->fka_period >> 1); | 581 | deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2; |
579 | if ((fip->sel_fcf == fcf) && | 582 | if (fip->sel_fcf == fcf) { |
580 | (time_after(jiffies, fcf->time + mda_time))) { | 583 | if (time_after(jiffies, deadline)) { |
581 | mod_timer(&fip->timer, jiffies + mda_time); | 584 | stats = per_cpu_ptr(fip->lp->dev_stats, |
582 | stats = per_cpu_ptr(fip->lp->dev_stats, | 585 | smp_processor_id()); |
583 | smp_processor_id()); | 586 | stats->MissDiscAdvCount++; |
584 | stats->MissDiscAdvCount++; | 587 | printk(KERN_INFO "libfcoe: host%d: " |
585 | printk(KERN_INFO "libfcoe: host%d: Missing Discovery " | 588 | "Missing Discovery Advertisement " |
586 | "Advertisement for fab %16.16llx count %lld\n", | 589 | "for fab %16.16llx count %lld\n", |
587 | fip->lp->host->host_no, fcf->fabric_name, | 590 | fip->lp->host->host_no, fcf->fabric_name, |
588 | stats->MissDiscAdvCount); | 591 | stats->MissDiscAdvCount); |
592 | } else if (time_after(next_timer, deadline)) | ||
593 | next_timer = deadline; | ||
589 | } | 594 | } |
590 | if (time_after(jiffies, fcf->time + fcf->fka_period * 3 + | 595 | |
591 | msecs_to_jiffies(FIP_FCF_FUZZ * 3))) { | 596 | deadline += fcf->fka_period; |
597 | if (time_after(jiffies, deadline)) { | ||
592 | if (fip->sel_fcf == fcf) | 598 | if (fip->sel_fcf == fcf) |
593 | fip->sel_fcf = NULL; | 599 | fip->sel_fcf = NULL; |
594 | list_del(&fcf->list); | 600 | list_del(&fcf->list); |
@@ -598,19 +604,21 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
598 | stats = per_cpu_ptr(fip->lp->dev_stats, | 604 | stats = per_cpu_ptr(fip->lp->dev_stats, |
599 | smp_processor_id()); | 605 | smp_processor_id()); |
600 | stats->VLinkFailureCount++; | 606 | stats->VLinkFailureCount++; |
601 | } else if (fcoe_ctlr_mtu_valid(fcf) && | 607 | } else { |
602 | (!sel_time || time_before(sel_time, fcf->time))) { | 608 | if (time_after(next_timer, deadline)) |
603 | sel_time = fcf->time; | 609 | next_timer = deadline; |
610 | if (fcoe_ctlr_mtu_valid(fcf) && | ||
611 | (!sel_time || time_before(sel_time, fcf->time))) | ||
612 | sel_time = fcf->time; | ||
604 | } | 613 | } |
605 | } | 614 | } |
606 | if (sel_time) { | 615 | if (sel_time) { |
607 | sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); | 616 | sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); |
608 | fip->sel_time = sel_time; | 617 | fip->sel_time = sel_time; |
609 | if (time_before(sel_time, fip->timer.expires)) | ||
610 | mod_timer(&fip->timer, sel_time); | ||
611 | } else { | 618 | } else { |
612 | fip->sel_time = 0; | 619 | fip->sel_time = 0; |
613 | } | 620 | } |
621 | return next_timer; | ||
614 | } | 622 | } |
615 | 623 | ||
616 | /** | 624 | /** |
@@ -1148,7 +1156,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1148 | struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg; | 1156 | struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg; |
1149 | struct fcoe_fcf *sel; | 1157 | struct fcoe_fcf *sel; |
1150 | struct fcoe_fcf *fcf; | 1158 | struct fcoe_fcf *fcf; |
1151 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); | 1159 | unsigned long next_timer; |
1152 | 1160 | ||
1153 | spin_lock_bh(&fip->lock); | 1161 | spin_lock_bh(&fip->lock); |
1154 | if (fip->state == FIP_ST_DISABLED) { | 1162 | if (fip->state == FIP_ST_DISABLED) { |
@@ -1157,13 +1165,16 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1157 | } | 1165 | } |
1158 | 1166 | ||
1159 | fcf = fip->sel_fcf; | 1167 | fcf = fip->sel_fcf; |
1160 | fcoe_ctlr_age_fcfs(fip); | 1168 | next_timer = fcoe_ctlr_age_fcfs(fip); |
1161 | 1169 | ||
1162 | sel = fip->sel_fcf; | 1170 | sel = fip->sel_fcf; |
1163 | if (!sel && fip->sel_time && time_after_eq(jiffies, fip->sel_time)) { | 1171 | if (!sel && fip->sel_time) { |
1164 | fcoe_ctlr_select(fip); | 1172 | if (time_after_eq(jiffies, fip->sel_time)) { |
1165 | sel = fip->sel_fcf; | 1173 | fcoe_ctlr_select(fip); |
1166 | fip->sel_time = 0; | 1174 | sel = fip->sel_fcf; |
1175 | fip->sel_time = 0; | ||
1176 | } else if (time_after(next_timer, fip->sel_time)) | ||
1177 | next_timer = fip->sel_time; | ||
1167 | } | 1178 | } |
1168 | 1179 | ||
1169 | if (sel != fcf) { | 1180 | if (sel != fcf) { |
@@ -1201,12 +1212,9 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1201 | } | 1212 | } |
1202 | if (time_after(next_timer, fip->port_ka_time)) | 1213 | if (time_after(next_timer, fip->port_ka_time)) |
1203 | next_timer = fip->port_ka_time; | 1214 | next_timer = fip->port_ka_time; |
1204 | mod_timer(&fip->timer, next_timer); | ||
1205 | } else if (fip->sel_time) { | ||
1206 | next_timer = fip->sel_time + | ||
1207 | msecs_to_jiffies(FCOE_CTLR_START_DELAY); | ||
1208 | mod_timer(&fip->timer, next_timer); | ||
1209 | } | 1215 | } |
1216 | if (!list_empty(&fip->fcfs)) | ||
1217 | mod_timer(&fip->timer, next_timer); | ||
1210 | if (fip->send_ctlr_ka || fip->send_port_ka) | 1218 | if (fip->send_ctlr_ka || fip->send_port_ka) |
1211 | schedule_work(&fip->timer_work); | 1219 | schedule_work(&fip->timer_work); |
1212 | spin_unlock_bh(&fip->lock); | 1220 | spin_unlock_bh(&fip->lock); |