aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe.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/fcoe.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/fcoe.c')
-rw-r--r--drivers/scsi/fcoe/fcoe.c51
1 files changed, 25 insertions, 26 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: