aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r--drivers/scsi/fcoe/fcoe.c245
1 files changed, 135 insertions, 110 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 4a43b74c0d27..32298ed60614 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -109,6 +109,7 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
109 struct fc_frame *, 109 struct fc_frame *,
110 void *), 110 void *),
111 void *, u32 timeout); 111 void *, u32 timeout);
112static void fcoe_recv_frame(struct sk_buff *skb);
112 113
113module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); 114module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
114__MODULE_PARM_TYPE(create, "string"); 115__MODULE_PARM_TYPE(create, "string");
@@ -1241,11 +1242,25 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
1241 * this skb. We also have this receive thread locked, 1242 * this skb. We also have this receive thread locked,
1242 * so we're free to queue skbs into it's queue. 1243 * so we're free to queue skbs into it's queue.
1243 */ 1244 */
1244 __skb_queue_tail(&fps->fcoe_rx_list, skb);
1245 if (fps->fcoe_rx_list.qlen == 1)
1246 wake_up_process(fps->thread);
1247 1245
1248 spin_unlock_bh(&fps->fcoe_rx_list.lock); 1246 /* If this is a SCSI-FCP frame, and this is already executing on the
1247 * correct CPU, and the queue for this CPU is empty, then go ahead
1248 * and process the frame directly in the softirq context.
1249 * This lets us process completions without context switching from the
1250 * NET_RX softirq, to our receive processing thread, and then back to
1251 * BLOCK softirq context.
1252 */
1253 if (fh->fh_type == FC_TYPE_FCP &&
1254 cpu == smp_processor_id() &&
1255 skb_queue_empty(&fps->fcoe_rx_list)) {
1256 spin_unlock_bh(&fps->fcoe_rx_list.lock);
1257 fcoe_recv_frame(skb);
1258 } else {
1259 __skb_queue_tail(&fps->fcoe_rx_list, skb);
1260 if (fps->fcoe_rx_list.qlen == 1)
1261 wake_up_process(fps->thread);
1262 spin_unlock_bh(&fps->fcoe_rx_list.lock);
1263 }
1249 1264
1250 return 0; 1265 return 0;
1251err: 1266err:
@@ -1503,26 +1518,134 @@ static void fcoe_percpu_flush_done(struct sk_buff *skb)
1503} 1518}
1504 1519
1505/** 1520/**
1506 * fcoe_percpu_receive_thread() - The per-CPU packet receive thread 1521 * fcoe_recv_frame() - process a single received frame
1507 * @arg: The per-CPU context 1522 * @skb: frame to process
1508 *
1509 * Return: 0 for success
1510 */ 1523 */
1511int fcoe_percpu_receive_thread(void *arg) 1524static void fcoe_recv_frame(struct sk_buff *skb)
1512{ 1525{
1513 struct fcoe_percpu_s *p = arg;
1514 u32 fr_len; 1526 u32 fr_len;
1515 struct fc_lport *lport; 1527 struct fc_lport *lport;
1516 struct fcoe_rcv_info *fr; 1528 struct fcoe_rcv_info *fr;
1517 struct fcoe_dev_stats *stats; 1529 struct fcoe_dev_stats *stats;
1518 struct fc_frame_header *fh; 1530 struct fc_frame_header *fh;
1519 struct sk_buff *skb;
1520 struct fcoe_crc_eof crc_eof; 1531 struct fcoe_crc_eof crc_eof;
1521 struct fc_frame *fp; 1532 struct fc_frame *fp;
1522 u8 *mac = NULL; 1533 u8 *mac = NULL;
1523 struct fcoe_port *port; 1534 struct fcoe_port *port;
1524 struct fcoe_hdr *hp; 1535 struct fcoe_hdr *hp;
1525 1536
1537 fr = fcoe_dev_from_skb(skb);
1538 lport = fr->fr_dev;
1539 if (unlikely(!lport)) {
1540 if (skb->destructor != fcoe_percpu_flush_done)
1541 FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb");
1542 kfree_skb(skb);
1543 return;
1544 }
1545
1546 FCOE_NETDEV_DBG(skb->dev, "skb_info: len:%d data_len:%d "
1547 "head:%p data:%p tail:%p end:%p sum:%d dev:%s",
1548 skb->len, skb->data_len,
1549 skb->head, skb->data, skb_tail_pointer(skb),
1550 skb_end_pointer(skb), skb->csum,
1551 skb->dev ? skb->dev->name : "<NULL>");
1552
1553 /*
1554 * Save source MAC address before discarding header.
1555 */
1556 port = lport_priv(lport);
1557 if (skb_is_nonlinear(skb))
1558 skb_linearize(skb); /* not ideal */
1559 mac = eth_hdr(skb)->h_source;
1560
1561 /*
1562 * Frame length checks and setting up the header pointers
1563 * was done in fcoe_rcv already.
1564 */
1565 hp = (struct fcoe_hdr *) skb_network_header(skb);
1566 fh = (struct fc_frame_header *) skb_transport_header(skb);
1567
1568 stats = fc_lport_get_stats(lport);
1569 if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
1570 if (stats->ErrorFrames < 5)
1571 printk(KERN_WARNING "fcoe: FCoE version "
1572 "mismatch: The frame has "
1573 "version %x, but the "
1574 "initiator supports version "
1575 "%x\n", FC_FCOE_DECAPS_VER(hp),
1576 FC_FCOE_VER);
1577 stats->ErrorFrames++;
1578 kfree_skb(skb);
1579 return;
1580 }
1581
1582 skb_pull(skb, sizeof(struct fcoe_hdr));
1583 fr_len = skb->len - sizeof(struct fcoe_crc_eof);
1584
1585 stats->RxFrames++;
1586 stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
1587
1588 fp = (struct fc_frame *)skb;
1589 fc_frame_init(fp);
1590 fr_dev(fp) = lport;
1591 fr_sof(fp) = hp->fcoe_sof;
1592
1593 /* Copy out the CRC and EOF trailer for access */
1594 if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
1595 kfree_skb(skb);
1596 return;
1597 }
1598 fr_eof(fp) = crc_eof.fcoe_eof;
1599 fr_crc(fp) = crc_eof.fcoe_crc32;
1600 if (pskb_trim(skb, fr_len)) {
1601 kfree_skb(skb);
1602 return;
1603 }
1604
1605 /*
1606 * We only check CRC if no offload is available and if it is
1607 * it's solicited data, in which case, the FCP layer would
1608 * check it during the copy.
1609 */
1610 if (lport->crc_offload &&
1611 skb->ip_summed == CHECKSUM_UNNECESSARY)
1612 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
1613 else
1614 fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
1615
1616 fh = fc_frame_header_get(fp);
1617 if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
1618 fh->fh_type == FC_TYPE_FCP) {
1619 fc_exch_recv(lport, fp);
1620 return;
1621 }
1622 if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
1623 if (le32_to_cpu(fr_crc(fp)) !=
1624 ~crc32(~0, skb->data, fr_len)) {
1625 if (stats->InvalidCRCCount < 5)
1626 printk(KERN_WARNING "fcoe: dropping "
1627 "frame with CRC error\n");
1628 stats->InvalidCRCCount++;
1629 stats->ErrorFrames++;
1630 fc_frame_free(fp);
1631 return;
1632 }
1633 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
1634 }
1635 fc_exch_recv(lport, fp);
1636}
1637
1638/**
1639 * fcoe_percpu_receive_thread() - The per-CPU packet receive thread
1640 * @arg: The per-CPU context
1641 *
1642 * Return: 0 for success
1643 */
1644int fcoe_percpu_receive_thread(void *arg)
1645{
1646 struct fcoe_percpu_s *p = arg;
1647 struct sk_buff *skb;
1648
1526 set_user_nice(current, -20); 1649 set_user_nice(current, -20);
1527 1650
1528 while (!kthread_should_stop()) { 1651 while (!kthread_should_stop()) {
@@ -1538,105 +1661,7 @@ int fcoe_percpu_receive_thread(void *arg)
1538 spin_lock_bh(&p->fcoe_rx_list.lock); 1661 spin_lock_bh(&p->fcoe_rx_list.lock);
1539 } 1662 }
1540 spin_unlock_bh(&p->fcoe_rx_list.lock); 1663 spin_unlock_bh(&p->fcoe_rx_list.lock);
1541 fr = fcoe_dev_from_skb(skb); 1664 fcoe_recv_frame(skb);
1542 lport = fr->fr_dev;
1543 if (unlikely(!lport)) {
1544 if (skb->destructor != fcoe_percpu_flush_done)
1545 FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb");
1546 kfree_skb(skb);
1547 continue;
1548 }
1549
1550 FCOE_NETDEV_DBG(skb->dev, "skb_info: len:%d data_len:%d "
1551 "head:%p data:%p tail:%p end:%p sum:%d dev:%s",
1552 skb->len, skb->data_len,
1553 skb->head, skb->data, skb_tail_pointer(skb),
1554 skb_end_pointer(skb), skb->csum,
1555 skb->dev ? skb->dev->name : "<NULL>");
1556
1557 /*
1558 * Save source MAC address before discarding header.
1559 */
1560 port = lport_priv(lport);
1561 if (skb_is_nonlinear(skb))
1562 skb_linearize(skb); /* not ideal */
1563 mac = eth_hdr(skb)->h_source;
1564
1565 /*
1566 * Frame length checks and setting up the header pointers
1567 * was done in fcoe_rcv already.
1568 */
1569 hp = (struct fcoe_hdr *) skb_network_header(skb);
1570 fh = (struct fc_frame_header *) skb_transport_header(skb);
1571
1572 stats = fc_lport_get_stats(lport);
1573 if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
1574 if (stats->ErrorFrames < 5)
1575 printk(KERN_WARNING "fcoe: FCoE version "
1576 "mismatch: The frame has "
1577 "version %x, but the "
1578 "initiator supports version "
1579 "%x\n", FC_FCOE_DECAPS_VER(hp),
1580 FC_FCOE_VER);
1581 stats->ErrorFrames++;
1582 kfree_skb(skb);
1583 continue;
1584 }
1585
1586 skb_pull(skb, sizeof(struct fcoe_hdr));
1587 fr_len = skb->len - sizeof(struct fcoe_crc_eof);
1588
1589 stats->RxFrames++;
1590 stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
1591
1592 fp = (struct fc_frame *)skb;
1593 fc_frame_init(fp);
1594 fr_dev(fp) = lport;
1595 fr_sof(fp) = hp->fcoe_sof;
1596
1597 /* Copy out the CRC and EOF trailer for access */
1598 if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
1599 kfree_skb(skb);
1600 continue;
1601 }
1602 fr_eof(fp) = crc_eof.fcoe_eof;
1603 fr_crc(fp) = crc_eof.fcoe_crc32;
1604 if (pskb_trim(skb, fr_len)) {
1605 kfree_skb(skb);
1606 continue;
1607 }
1608
1609 /*
1610 * We only check CRC if no offload is available and if it is
1611 * it's solicited data, in which case, the FCP layer would
1612 * check it during the copy.
1613 */
1614 if (lport->crc_offload &&
1615 skb->ip_summed == CHECKSUM_UNNECESSARY)
1616 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
1617 else
1618 fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
1619
1620 fh = fc_frame_header_get(fp);
1621 if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
1622 fh->fh_type == FC_TYPE_FCP) {
1623 fc_exch_recv(lport, fp);
1624 continue;
1625 }
1626 if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
1627 if (le32_to_cpu(fr_crc(fp)) !=
1628 ~crc32(~0, skb->data, fr_len)) {
1629 if (stats->InvalidCRCCount < 5)
1630 printk(KERN_WARNING "fcoe: dropping "
1631 "frame with CRC error\n");
1632 stats->InvalidCRCCount++;
1633 stats->ErrorFrames++;
1634 fc_frame_free(fp);
1635 continue;
1636 }
1637 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
1638 }
1639 fc_exch_recv(lport, fp);
1640 } 1665 }
1641 return 0; 1666 return 0;
1642} 1667}