diff options
author | Joe Eykholt <jeykholt@cisco.com> | 2010-03-12 19:08:55 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-04-11 10:23:44 -0400 |
commit | f018b73af6db4f330ad5da9ac53997a699c30c42 (patch) | |
tree | 4f4e9405d923c0021771549dbdec34569c0e27a7 /drivers/scsi/fcoe/fcoe.c | |
parent | b3ef990c1514859bffae221b9e82e46a38f1e7bf (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.c | 51 |
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; |
1301 | err: | 1302 | err: |
1302 | fc_lport_get_stats(lport)->ErrorFrames++; | 1303 | per_cpu_ptr(lport->dev_stats, get_cpu())->ErrorFrames++; |
1303 | 1304 | put_cpu(); | |
1304 | err2: | 1305 | err2: |
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 | |||
1660 | drop: | ||
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 | } |
1842 | out: | 1841 | out: |