aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/libfcoe.c
diff options
context:
space:
mode:
authorJoe Eykholt <jeykholt@cisco.com>2010-03-12 19:08:55 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-04-11 10:23:44 -0400
commitf018b73af6db4f330ad5da9ac53997a699c30c42 (patch)
tree4f4e9405d923c0021771549dbdec34569c0e27a7 /drivers/scsi/fcoe/libfcoe.c
parentb3ef990c1514859bffae221b9e82e46a38f1e7bf (diff)
[SCSI] libfc, libfcoe, fcoe: use smp_processor_id() only when preempt disabled
When the kernel is configured for preemption, using smp_processor_id() when preemption is enabled causes a warning backtrace and is wrong since we could move off of that CPU as soon as we get the ID, and we would be referencing the wrong CPU, and possibly an invalid one if it could be hotswapped out. Remove the fc_lport_get_stats() function and explicitly use per_cpu_ptr() to get the statistics. Where preemption has been disabled by holding a _bh lock continue to use smp_processor_id(), but otherwise use get_cpu()/put_cpu(). In fcoe_recv_frame() also changed the cases where we return in the middle to do a goto to the code which bumps ErrorFrames and does a put_cpu(). Two of these cases didn't bump ErrorFrames before, but doing so is harmless because they "can't happen", due to prior length checks. Also rearranged code in fcoe_recv_frame() to have only one call to fc_exch_recv(). It's just as efficient and saves a call to put_cpu(). In fc_fcp.c, adjusted a FIXME comment for code which doesn't need fixing. Signed-off-by: Joe Eykholt <jeykholt@cisco.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/fcoe/libfcoe.c')
-rw-r--r--drivers/scsi/fcoe/libfcoe.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index b7718be3c096..ff5ccba3d741 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -550,7 +550,7 @@ EXPORT_SYMBOL(fcoe_ctlr_els_send);
550 * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller 550 * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller
551 * @fip: The FCoE controller to free FCFs on 551 * @fip: The FCoE controller to free FCFs on
552 * 552 *
553 * Called with lock held. 553 * Called with lock held and preemption disabled.
554 * 554 *
555 * An FCF is considered old if we have missed three advertisements. 555 * An FCF is considered old if we have missed three advertisements.
556 * That is, there have been no valid advertisement from it for three 556 * That is, there have been no valid advertisement from it for three
@@ -567,17 +567,20 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
567 struct fcoe_fcf *next; 567 struct fcoe_fcf *next;
568 unsigned long sel_time = 0; 568 unsigned long sel_time = 0;
569 unsigned long mda_time = 0; 569 unsigned long mda_time = 0;
570 struct fcoe_dev_stats *stats;
570 571
571 list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { 572 list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
572 mda_time = fcf->fka_period + (fcf->fka_period >> 1); 573 mda_time = fcf->fka_period + (fcf->fka_period >> 1);
573 if ((fip->sel_fcf == fcf) && 574 if ((fip->sel_fcf == fcf) &&
574 (time_after(jiffies, fcf->time + mda_time))) { 575 (time_after(jiffies, fcf->time + mda_time))) {
575 mod_timer(&fip->timer, jiffies + mda_time); 576 mod_timer(&fip->timer, jiffies + mda_time);
576 fc_lport_get_stats(fip->lp)->MissDiscAdvCount++; 577 stats = per_cpu_ptr(fip->lp->dev_stats,
578 smp_processor_id());
579 stats->MissDiscAdvCount++;
577 printk(KERN_INFO "libfcoe: host%d: Missing Discovery " 580 printk(KERN_INFO "libfcoe: host%d: Missing Discovery "
578 "Advertisement for fab %llx count %lld\n", 581 "Advertisement for fab %llx count %lld\n",
579 fip->lp->host->host_no, fcf->fabric_name, 582 fip->lp->host->host_no, fcf->fabric_name,
580 fc_lport_get_stats(fip->lp)->MissDiscAdvCount); 583 stats->MissDiscAdvCount);
581 } 584 }
582 if (time_after(jiffies, fcf->time + fcf->fka_period * 3 + 585 if (time_after(jiffies, fcf->time + fcf->fka_period * 3 +
583 msecs_to_jiffies(FIP_FCF_FUZZ * 3))) { 586 msecs_to_jiffies(FIP_FCF_FUZZ * 3))) {
@@ -587,7 +590,9 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
587 WARN_ON(!fip->fcf_count); 590 WARN_ON(!fip->fcf_count);
588 fip->fcf_count--; 591 fip->fcf_count--;
589 kfree(fcf); 592 kfree(fcf);
590 fc_lport_get_stats(fip->lp)->VLinkFailureCount++; 593 stats = per_cpu_ptr(fip->lp->dev_stats,
594 smp_processor_id());
595 stats->VLinkFailureCount++;
591 } else if (fcoe_ctlr_mtu_valid(fcf) && 596 } else if (fcoe_ctlr_mtu_valid(fcf) &&
592 (!sel_time || time_before(sel_time, fcf->time))) { 597 (!sel_time || time_before(sel_time, fcf->time))) {
593 sel_time = fcf->time; 598 sel_time = fcf->time;
@@ -900,9 +905,10 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
900 fr_eof(fp) = FC_EOF_T; 905 fr_eof(fp) = FC_EOF_T;
901 fr_dev(fp) = lport; 906 fr_dev(fp) = lport;
902 907
903 stats = fc_lport_get_stats(lport); 908 stats = per_cpu_ptr(lport->dev_stats, get_cpu());
904 stats->RxFrames++; 909 stats->RxFrames++;
905 stats->RxWords += skb->len / FIP_BPW; 910 stats->RxWords += skb->len / FIP_BPW;
911 put_cpu();
906 912
907 fc_exch_recv(lport, fp); 913 fc_exch_recv(lport, fp);
908 return; 914 return;
@@ -1000,7 +1006,8 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
1000 LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); 1006 LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n");
1001 1007
1002 spin_lock_bh(&fip->lock); 1008 spin_lock_bh(&fip->lock);
1003 fc_lport_get_stats(lport)->VLinkFailureCount++; 1009 per_cpu_ptr(lport->dev_stats,
1010 smp_processor_id())->VLinkFailureCount++;
1004 fcoe_ctlr_reset(fip); 1011 fcoe_ctlr_reset(fip);
1005 spin_unlock_bh(&fip->lock); 1012 spin_unlock_bh(&fip->lock);
1006 1013