aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/scsi/fcoe/fcoe.c51
-rw-r--r--drivers/scsi/fcoe/libfcoe.c19
-rw-r--r--drivers/scsi/libfc/fc_exch.c3
-rw-r--r--drivers/scsi/libfc/fc_fcp.c8
4 files changed, 45 insertions, 36 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index fd0b2b3b27b8..927b3e63d871 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -1075,7 +1075,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu)
1075 struct sk_buff *skb; 1075 struct sk_buff *skb;
1076#ifdef CONFIG_SMP 1076#ifdef CONFIG_SMP
1077 struct fcoe_percpu_s *p0; 1077 struct fcoe_percpu_s *p0;
1078 unsigned targ_cpu = smp_processor_id(); 1078 unsigned targ_cpu = get_cpu();
1079#endif /* CONFIG_SMP */ 1079#endif /* CONFIG_SMP */
1080 1080
1081 FCOE_DBG("Destroying receive thread for CPU %d\n", cpu); 1081 FCOE_DBG("Destroying receive thread for CPU %d\n", cpu);
@@ -1131,6 +1131,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu)
1131 kfree_skb(skb); 1131 kfree_skb(skb);
1132 spin_unlock_bh(&p->fcoe_rx_list.lock); 1132 spin_unlock_bh(&p->fcoe_rx_list.lock);
1133 } 1133 }
1134 put_cpu();
1134#else 1135#else
1135 /* 1136 /*
1136 * This a non-SMP scenario where the singular Rx thread is 1137 * This a non-SMP scenario where the singular Rx thread is
@@ -1299,8 +1300,8 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
1299 1300
1300 return 0; 1301 return 0;
1301err: 1302err:
1302 fc_lport_get_stats(lport)->ErrorFrames++; 1303 per_cpu_ptr(lport->dev_stats, get_cpu())->ErrorFrames++;
1303 1304 put_cpu();
1304err2: 1305err2:
1305 kfree_skb(skb); 1306 kfree_skb(skb);
1306 return -1; 1307 return -1;
@@ -1529,9 +1530,10 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
1529 skb_shinfo(skb)->gso_size = 0; 1530 skb_shinfo(skb)->gso_size = 0;
1530 } 1531 }
1531 /* update tx stats: regardless if LLD fails */ 1532 /* update tx stats: regardless if LLD fails */
1532 stats = fc_lport_get_stats(lport); 1533 stats = per_cpu_ptr(lport->dev_stats, get_cpu());
1533 stats->TxFrames++; 1534 stats->TxFrames++;
1534 stats->TxWords += wlen; 1535 stats->TxWords += wlen;
1536 put_cpu();
1535 1537
1536 /* send down to lld */ 1538 /* send down to lld */
1537 fr_dev(fp) = lport; 1539 fr_dev(fp) = lport;
@@ -1595,7 +1597,7 @@ static void fcoe_recv_frame(struct sk_buff *skb)
1595 hp = (struct fcoe_hdr *) skb_network_header(skb); 1597 hp = (struct fcoe_hdr *) skb_network_header(skb);
1596 fh = (struct fc_frame_header *) skb_transport_header(skb); 1598 fh = (struct fc_frame_header *) skb_transport_header(skb);
1597 1599
1598 stats = fc_lport_get_stats(lport); 1600 stats = per_cpu_ptr(lport->dev_stats, get_cpu());
1599 if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { 1601 if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
1600 if (stats->ErrorFrames < 5) 1602 if (stats->ErrorFrames < 5)
1601 printk(KERN_WARNING "fcoe: FCoE version " 1603 printk(KERN_WARNING "fcoe: FCoE version "
@@ -1604,9 +1606,7 @@ static void fcoe_recv_frame(struct sk_buff *skb)
1604 "initiator supports version " 1606 "initiator supports version "
1605 "%x\n", FC_FCOE_DECAPS_VER(hp), 1607 "%x\n", FC_FCOE_DECAPS_VER(hp),
1606 FC_FCOE_VER); 1608 FC_FCOE_VER);
1607 stats->ErrorFrames++; 1609 goto drop;
1608 kfree_skb(skb);
1609 return;
1610 } 1610 }
1611 1611
1612 skb_pull(skb, sizeof(struct fcoe_hdr)); 1612 skb_pull(skb, sizeof(struct fcoe_hdr));
@@ -1621,16 +1621,12 @@ static void fcoe_recv_frame(struct sk_buff *skb)
1621 fr_sof(fp) = hp->fcoe_sof; 1621 fr_sof(fp) = hp->fcoe_sof;
1622 1622
1623 /* Copy out the CRC and EOF trailer for access */ 1623 /* Copy out the CRC and EOF trailer for access */
1624 if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) { 1624 if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof)))
1625 kfree_skb(skb); 1625 goto drop;
1626 return;
1627 }
1628 fr_eof(fp) = crc_eof.fcoe_eof; 1626 fr_eof(fp) = crc_eof.fcoe_eof;
1629 fr_crc(fp) = crc_eof.fcoe_crc32; 1627 fr_crc(fp) = crc_eof.fcoe_crc32;
1630 if (pskb_trim(skb, fr_len)) { 1628 if (pskb_trim(skb, fr_len))
1631 kfree_skb(skb); 1629 goto drop;
1632 return;
1633 }
1634 1630
1635 /* 1631 /*
1636 * We only check CRC if no offload is available and if it is 1632 * We only check CRC if no offload is available and if it is
@@ -1644,25 +1640,27 @@ static void fcoe_recv_frame(struct sk_buff *skb)
1644 fr_flags(fp) |= FCPHF_CRC_UNCHECKED; 1640 fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
1645 1641
1646 fh = fc_frame_header_get(fp); 1642 fh = fc_frame_header_get(fp);
1647 if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && 1643 if ((fh->fh_r_ctl != FC_RCTL_DD_SOL_DATA ||
1648 fh->fh_type == FC_TYPE_FCP) { 1644 fh->fh_type != FC_TYPE_FCP) &&
1649 fc_exch_recv(lport, fp); 1645 (fr_flags(fp) & FCPHF_CRC_UNCHECKED)) {
1650 return;
1651 }
1652 if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
1653 if (le32_to_cpu(fr_crc(fp)) != 1646 if (le32_to_cpu(fr_crc(fp)) !=
1654 ~crc32(~0, skb->data, fr_len)) { 1647 ~crc32(~0, skb->data, fr_len)) {
1655 if (stats->InvalidCRCCount < 5) 1648 if (stats->InvalidCRCCount < 5)
1656 printk(KERN_WARNING "fcoe: dropping " 1649 printk(KERN_WARNING "fcoe: dropping "
1657 "frame with CRC error\n"); 1650 "frame with CRC error\n");
1658 stats->InvalidCRCCount++; 1651 stats->InvalidCRCCount++;
1659 stats->ErrorFrames++; 1652 goto drop;
1660 fc_frame_free(fp);
1661 return;
1662 } 1653 }
1663 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; 1654 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
1664 } 1655 }
1656 put_cpu();
1665 fc_exch_recv(lport, fp); 1657 fc_exch_recv(lport, fp);
1658 return;
1659
1660drop:
1661 stats->ErrorFrames++;
1662 put_cpu();
1663 kfree_skb(skb);
1666} 1664}
1667 1665
1668/** 1666/**
@@ -1835,8 +1833,9 @@ static int fcoe_device_notification(struct notifier_block *notifier,
1835 if (link_possible && !fcoe_link_ok(lport)) 1833 if (link_possible && !fcoe_link_ok(lport))
1836 fcoe_ctlr_link_up(&fcoe->ctlr); 1834 fcoe_ctlr_link_up(&fcoe->ctlr);
1837 else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { 1835 else if (fcoe_ctlr_link_down(&fcoe->ctlr)) {
1838 stats = fc_lport_get_stats(lport); 1836 stats = per_cpu_ptr(lport->dev_stats, get_cpu());
1839 stats->LinkFailureCount++; 1837 stats->LinkFailureCount++;
1838 put_cpu();
1840 fcoe_clean_pending_queue(lport); 1839 fcoe_clean_pending_queue(lport);
1841 } 1840 }
1842out: 1841out:
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
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index dc12a2bf0c9b..d0496dafd84a 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -676,9 +676,10 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
676 } 676 }
677 memset(ep, 0, sizeof(*ep)); 677 memset(ep, 0, sizeof(*ep));
678 678
679 cpu = smp_processor_id(); 679 cpu = get_cpu();
680 pool = per_cpu_ptr(mp->pool, cpu); 680 pool = per_cpu_ptr(mp->pool, cpu);
681 spin_lock_bh(&pool->lock); 681 spin_lock_bh(&pool->lock);
682 put_cpu();
682 index = pool->next_index; 683 index = pool->next_index;
683 /* allocate new exch from pool */ 684 /* allocate new exch from pool */
684 while (fc_exch_ptr_get(pool, index)) { 685 while (fc_exch_ptr_get(pool, index)) {
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 044c420a1371..220c4bc536ca 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -484,13 +484,14 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
484 484
485 if (~crc != le32_to_cpu(fr_crc(fp))) { 485 if (~crc != le32_to_cpu(fr_crc(fp))) {
486crc_err: 486crc_err:
487 stats = fc_lport_get_stats(lport); 487 stats = per_cpu_ptr(lport->dev_stats, get_cpu());
488 stats->ErrorFrames++; 488 stats->ErrorFrames++;
489 /* FIXME - per cpu count, not total count! */ 489 /* per cpu count, not total count, but OK for limit */
490 if (stats->InvalidCRCCount++ < 5) 490 if (stats->InvalidCRCCount++ < 5)
491 printk(KERN_WARNING "libfc: CRC error on data " 491 printk(KERN_WARNING "libfc: CRC error on data "
492 "frame for port (%6x)\n", 492 "frame for port (%6x)\n",
493 fc_host_port_id(lport->host)); 493 fc_host_port_id(lport->host));
494 put_cpu();
494 /* 495 /*
495 * Assume the frame is total garbage. 496 * Assume the frame is total garbage.
496 * We may have copied it over the good part 497 * We may have copied it over the good part
@@ -1819,7 +1820,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
1819 /* 1820 /*
1820 * setup the data direction 1821 * setup the data direction
1821 */ 1822 */
1822 stats = fc_lport_get_stats(lport); 1823 stats = per_cpu_ptr(lport->dev_stats, get_cpu());
1823 if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { 1824 if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) {
1824 fsp->req_flags = FC_SRB_READ; 1825 fsp->req_flags = FC_SRB_READ;
1825 stats->InputRequests++; 1826 stats->InputRequests++;
@@ -1832,6 +1833,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
1832 fsp->req_flags = 0; 1833 fsp->req_flags = 0;
1833 stats->ControlRequests++; 1834 stats->ControlRequests++;
1834 } 1835 }
1836 put_cpu();
1835 1837
1836 fsp->tgt_flags = rpriv->flags; 1838 fsp->tgt_flags = rpriv->flags;
1837 1839