diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 10:19:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 10:19:18 -0400 |
commit | 33cf23b0a535475aead57707cb9f4fe135a93544 (patch) | |
tree | 67e14f77f0eeab847a26a6cbfcb44eecb5fa2fda /drivers/scsi/fcoe | |
parent | 7a9b149212f3716c598afe973b6261fd58453b7a (diff) | |
parent | 95bb335c0ebe96afe926387a1ef3a096bd884a82 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (182 commits)
[SCSI] aacraid: add an ifdef'd device delete case instead of taking the device offline
[SCSI] aacraid: prohibit access to array container space
[SCSI] aacraid: add support for handling ATA pass-through commands.
[SCSI] aacraid: expose physical devices for models with newer firmware
[SCSI] aacraid: respond automatically to volumes added by config tool
[SCSI] fcoe: fix fcoe module ref counting
[SCSI] libfcoe: FIP Keep-Alive messages for VPorts are sent with incorrect port_id and wwn
[SCSI] libfcoe: Fix incorrect MAC address clearing
[SCSI] fcoe: fix a circular locking issue with rtnl and sysfs mutex
[SCSI] libfc: Move the port_id into lport
[SCSI] fcoe: move link speed checking into its own routine
[SCSI] libfc: Remove extra pointer check
[SCSI] libfc: Remove unused fc_get_host_port_type
[SCSI] fcoe: fixes wrong error exit in fcoe_create
[SCSI] libfc: set seq_id for incoming sequence
[SCSI] qla2xxx: Updates to ISP82xx support.
[SCSI] qla2xxx: Optionally disable target reset.
[SCSI] qla2xxx: ensure flash operation and host reset via sg_reset are mutually exclusive
[SCSI] qla2xxx: Silence bogus warning by gcc for wrap and did.
[SCSI] qla2xxx: T10 DIF support added.
...
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 194 | ||||
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 111 |
2 files changed, 181 insertions, 124 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 54c870b8c328..9276121db1ef 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -74,6 +74,7 @@ static int fcoe_rcv(struct sk_buff *, struct net_device *, | |||
74 | static int fcoe_percpu_receive_thread(void *); | 74 | static int fcoe_percpu_receive_thread(void *); |
75 | static void fcoe_clean_pending_queue(struct fc_lport *); | 75 | static void fcoe_clean_pending_queue(struct fc_lport *); |
76 | static void fcoe_percpu_clean(struct fc_lport *); | 76 | static void fcoe_percpu_clean(struct fc_lport *); |
77 | static int fcoe_link_speed_update(struct fc_lport *); | ||
77 | static int fcoe_link_ok(struct fc_lport *); | 78 | static int fcoe_link_ok(struct fc_lport *); |
78 | 79 | ||
79 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); | 80 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); |
@@ -146,6 +147,7 @@ static int fcoe_vport_destroy(struct fc_vport *); | |||
146 | static int fcoe_vport_create(struct fc_vport *, bool disabled); | 147 | static int fcoe_vport_create(struct fc_vport *, bool disabled); |
147 | static int fcoe_vport_disable(struct fc_vport *, bool disable); | 148 | static int fcoe_vport_disable(struct fc_vport *, bool disable); |
148 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); | 149 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); |
150 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); | ||
149 | 151 | ||
150 | static struct libfc_function_template fcoe_libfc_fcn_templ = { | 152 | static struct libfc_function_template fcoe_libfc_fcn_templ = { |
151 | .frame_send = fcoe_xmit, | 153 | .frame_send = fcoe_xmit, |
@@ -153,6 +155,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { | |||
153 | .ddp_done = fcoe_ddp_done, | 155 | .ddp_done = fcoe_ddp_done, |
154 | .elsct_send = fcoe_elsct_send, | 156 | .elsct_send = fcoe_elsct_send, |
155 | .get_lesb = fcoe_get_lesb, | 157 | .get_lesb = fcoe_get_lesb, |
158 | .lport_set_port_id = fcoe_set_port_id, | ||
156 | }; | 159 | }; |
157 | 160 | ||
158 | struct fc_function_template fcoe_transport_function = { | 161 | struct fc_function_template fcoe_transport_function = { |
@@ -629,6 +632,8 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) | |||
629 | port->fcoe_pending_queue_active = 0; | 632 | port->fcoe_pending_queue_active = 0; |
630 | setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport); | 633 | setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport); |
631 | 634 | ||
635 | fcoe_link_speed_update(lport); | ||
636 | |||
632 | if (!lport->vport) { | 637 | if (!lport->vport) { |
633 | /* | 638 | /* |
634 | * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN: | 639 | * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN: |
@@ -653,15 +658,13 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) | |||
653 | /** | 658 | /** |
654 | * fcoe_shost_config() - Set up the SCSI host associated with a local port | 659 | * fcoe_shost_config() - Set up the SCSI host associated with a local port |
655 | * @lport: The local port | 660 | * @lport: The local port |
656 | * @shost: The SCSI host to associate with the local port | ||
657 | * @dev: The device associated with the SCSI host | 661 | * @dev: The device associated with the SCSI host |
658 | * | 662 | * |
659 | * Must be called after fcoe_lport_config() and fcoe_netdev_config() | 663 | * Must be called after fcoe_lport_config() and fcoe_netdev_config() |
660 | * | 664 | * |
661 | * Returns: 0 for success | 665 | * Returns: 0 for success |
662 | */ | 666 | */ |
663 | static int fcoe_shost_config(struct fc_lport *lport, struct Scsi_Host *shost, | 667 | static int fcoe_shost_config(struct fc_lport *lport, struct device *dev) |
664 | struct device *dev) | ||
665 | { | 668 | { |
666 | int rc = 0; | 669 | int rc = 0; |
667 | 670 | ||
@@ -669,6 +672,8 @@ static int fcoe_shost_config(struct fc_lport *lport, struct Scsi_Host *shost, | |||
669 | lport->host->max_lun = FCOE_MAX_LUN; | 672 | lport->host->max_lun = FCOE_MAX_LUN; |
670 | lport->host->max_id = FCOE_MAX_FCP_TARGET; | 673 | lport->host->max_id = FCOE_MAX_FCP_TARGET; |
671 | lport->host->max_channel = 0; | 674 | lport->host->max_channel = 0; |
675 | lport->host->max_cmd_len = FCOE_MAX_CMD_LEN; | ||
676 | |||
672 | if (lport->vport) | 677 | if (lport->vport) |
673 | lport->host->transportt = fcoe_vport_transport_template; | 678 | lport->host->transportt = fcoe_vport_transport_template; |
674 | else | 679 | else |
@@ -796,6 +801,12 @@ skip_oem: | |||
796 | /** | 801 | /** |
797 | * fcoe_if_destroy() - Tear down a SW FCoE instance | 802 | * fcoe_if_destroy() - Tear down a SW FCoE instance |
798 | * @lport: The local port to be destroyed | 803 | * @lport: The local port to be destroyed |
804 | * | ||
805 | * Locking: must be called with the RTNL mutex held and RTNL mutex | ||
806 | * needed to be dropped by this function since not dropping RTNL | ||
807 | * would cause circular locking warning on synchronous fip worker | ||
808 | * cancelling thru fcoe_interface_put invoked by this function. | ||
809 | * | ||
799 | */ | 810 | */ |
800 | static void fcoe_if_destroy(struct fc_lport *lport) | 811 | static void fcoe_if_destroy(struct fc_lport *lport) |
801 | { | 812 | { |
@@ -818,7 +829,6 @@ static void fcoe_if_destroy(struct fc_lport *lport) | |||
818 | /* Free existing transmit skbs */ | 829 | /* Free existing transmit skbs */ |
819 | fcoe_clean_pending_queue(lport); | 830 | fcoe_clean_pending_queue(lport); |
820 | 831 | ||
821 | rtnl_lock(); | ||
822 | if (!is_zero_ether_addr(port->data_src_addr)) | 832 | if (!is_zero_ether_addr(port->data_src_addr)) |
823 | dev_uc_del(netdev, port->data_src_addr); | 833 | dev_uc_del(netdev, port->data_src_addr); |
824 | rtnl_unlock(); | 834 | rtnl_unlock(); |
@@ -841,6 +851,7 @@ static void fcoe_if_destroy(struct fc_lport *lport) | |||
841 | 851 | ||
842 | /* Release the Scsi_Host */ | 852 | /* Release the Scsi_Host */ |
843 | scsi_host_put(lport->host); | 853 | scsi_host_put(lport->host); |
854 | module_put(THIS_MODULE); | ||
844 | } | 855 | } |
845 | 856 | ||
846 | /** | 857 | /** |
@@ -897,7 +908,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
897 | struct net_device *netdev = fcoe->netdev; | 908 | struct net_device *netdev = fcoe->netdev; |
898 | struct fc_lport *lport = NULL; | 909 | struct fc_lport *lport = NULL; |
899 | struct fcoe_port *port; | 910 | struct fcoe_port *port; |
900 | struct Scsi_Host *shost; | ||
901 | int rc; | 911 | int rc; |
902 | /* | 912 | /* |
903 | * parent is only a vport if npiv is 1, | 913 | * parent is only a vport if npiv is 1, |
@@ -919,7 +929,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
919 | rc = -ENOMEM; | 929 | rc = -ENOMEM; |
920 | goto out; | 930 | goto out; |
921 | } | 931 | } |
922 | shost = lport->host; | ||
923 | port = lport_priv(lport); | 932 | port = lport_priv(lport); |
924 | port->lport = lport; | 933 | port->lport = lport; |
925 | port->fcoe = fcoe; | 934 | port->fcoe = fcoe; |
@@ -934,7 +943,8 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
934 | } | 943 | } |
935 | 944 | ||
936 | if (npiv) { | 945 | if (npiv) { |
937 | FCOE_NETDEV_DBG(netdev, "Setting vport names, 0x%llX 0x%llX\n", | 946 | FCOE_NETDEV_DBG(netdev, "Setting vport names, " |
947 | "%16.16llx %16.16llx\n", | ||
938 | vport->node_name, vport->port_name); | 948 | vport->node_name, vport->port_name); |
939 | fc_set_wwnn(lport, vport->node_name); | 949 | fc_set_wwnn(lport, vport->node_name); |
940 | fc_set_wwpn(lport, vport->port_name); | 950 | fc_set_wwpn(lport, vport->port_name); |
@@ -949,7 +959,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
949 | } | 959 | } |
950 | 960 | ||
951 | /* configure lport scsi host properties */ | 961 | /* configure lport scsi host properties */ |
952 | rc = fcoe_shost_config(lport, shost, parent); | 962 | rc = fcoe_shost_config(lport, parent); |
953 | if (rc) { | 963 | if (rc) { |
954 | FCOE_NETDEV_DBG(netdev, "Could not configure shost for the " | 964 | FCOE_NETDEV_DBG(netdev, "Could not configure shost for the " |
955 | "interface\n"); | 965 | "interface\n"); |
@@ -1073,7 +1083,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu) | |||
1073 | struct sk_buff *skb; | 1083 | struct sk_buff *skb; |
1074 | #ifdef CONFIG_SMP | 1084 | #ifdef CONFIG_SMP |
1075 | struct fcoe_percpu_s *p0; | 1085 | struct fcoe_percpu_s *p0; |
1076 | unsigned targ_cpu = smp_processor_id(); | 1086 | unsigned targ_cpu = get_cpu(); |
1077 | #endif /* CONFIG_SMP */ | 1087 | #endif /* CONFIG_SMP */ |
1078 | 1088 | ||
1079 | FCOE_DBG("Destroying receive thread for CPU %d\n", cpu); | 1089 | FCOE_DBG("Destroying receive thread for CPU %d\n", cpu); |
@@ -1129,6 +1139,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu) | |||
1129 | kfree_skb(skb); | 1139 | kfree_skb(skb); |
1130 | spin_unlock_bh(&p->fcoe_rx_list.lock); | 1140 | spin_unlock_bh(&p->fcoe_rx_list.lock); |
1131 | } | 1141 | } |
1142 | put_cpu(); | ||
1132 | #else | 1143 | #else |
1133 | /* | 1144 | /* |
1134 | * This a non-SMP scenario where the singular Rx thread is | 1145 | * This a non-SMP scenario where the singular Rx thread is |
@@ -1297,8 +1308,8 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, | |||
1297 | 1308 | ||
1298 | return 0; | 1309 | return 0; |
1299 | err: | 1310 | err: |
1300 | fc_lport_get_stats(lport)->ErrorFrames++; | 1311 | per_cpu_ptr(lport->dev_stats, get_cpu())->ErrorFrames++; |
1301 | 1312 | put_cpu(); | |
1302 | err2: | 1313 | err2: |
1303 | kfree_skb(skb); | 1314 | kfree_skb(skb); |
1304 | return -1; | 1315 | return -1; |
@@ -1444,7 +1455,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1444 | return 0; | 1455 | return 0; |
1445 | } | 1456 | } |
1446 | 1457 | ||
1447 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && | 1458 | if (unlikely(fh->fh_type == FC_TYPE_ELS) && |
1448 | fcoe_ctlr_els_send(&fcoe->ctlr, lport, skb)) | 1459 | fcoe_ctlr_els_send(&fcoe->ctlr, lport, skb)) |
1449 | return 0; | 1460 | return 0; |
1450 | 1461 | ||
@@ -1527,9 +1538,10 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1527 | skb_shinfo(skb)->gso_size = 0; | 1538 | skb_shinfo(skb)->gso_size = 0; |
1528 | } | 1539 | } |
1529 | /* update tx stats: regardless if LLD fails */ | 1540 | /* update tx stats: regardless if LLD fails */ |
1530 | stats = fc_lport_get_stats(lport); | 1541 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); |
1531 | stats->TxFrames++; | 1542 | stats->TxFrames++; |
1532 | stats->TxWords += wlen; | 1543 | stats->TxWords += wlen; |
1544 | put_cpu(); | ||
1533 | 1545 | ||
1534 | /* send down to lld */ | 1546 | /* send down to lld */ |
1535 | fr_dev(fp) = lport; | 1547 | fr_dev(fp) = lport; |
@@ -1563,7 +1575,6 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1563 | struct fc_frame_header *fh; | 1575 | struct fc_frame_header *fh; |
1564 | struct fcoe_crc_eof crc_eof; | 1576 | struct fcoe_crc_eof crc_eof; |
1565 | struct fc_frame *fp; | 1577 | struct fc_frame *fp; |
1566 | u8 *mac = NULL; | ||
1567 | struct fcoe_port *port; | 1578 | struct fcoe_port *port; |
1568 | struct fcoe_hdr *hp; | 1579 | struct fcoe_hdr *hp; |
1569 | 1580 | ||
@@ -1583,13 +1594,9 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1583 | skb_end_pointer(skb), skb->csum, | 1594 | skb_end_pointer(skb), skb->csum, |
1584 | skb->dev ? skb->dev->name : "<NULL>"); | 1595 | skb->dev ? skb->dev->name : "<NULL>"); |
1585 | 1596 | ||
1586 | /* | ||
1587 | * Save source MAC address before discarding header. | ||
1588 | */ | ||
1589 | port = lport_priv(lport); | 1597 | port = lport_priv(lport); |
1590 | if (skb_is_nonlinear(skb)) | 1598 | if (skb_is_nonlinear(skb)) |
1591 | skb_linearize(skb); /* not ideal */ | 1599 | skb_linearize(skb); /* not ideal */ |
1592 | mac = eth_hdr(skb)->h_source; | ||
1593 | 1600 | ||
1594 | /* | 1601 | /* |
1595 | * Frame length checks and setting up the header pointers | 1602 | * Frame length checks and setting up the header pointers |
@@ -1598,7 +1605,7 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1598 | hp = (struct fcoe_hdr *) skb_network_header(skb); | 1605 | hp = (struct fcoe_hdr *) skb_network_header(skb); |
1599 | fh = (struct fc_frame_header *) skb_transport_header(skb); | 1606 | fh = (struct fc_frame_header *) skb_transport_header(skb); |
1600 | 1607 | ||
1601 | stats = fc_lport_get_stats(lport); | 1608 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); |
1602 | if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { | 1609 | if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { |
1603 | if (stats->ErrorFrames < 5) | 1610 | if (stats->ErrorFrames < 5) |
1604 | printk(KERN_WARNING "fcoe: FCoE version " | 1611 | printk(KERN_WARNING "fcoe: FCoE version " |
@@ -1607,9 +1614,7 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1607 | "initiator supports version " | 1614 | "initiator supports version " |
1608 | "%x\n", FC_FCOE_DECAPS_VER(hp), | 1615 | "%x\n", FC_FCOE_DECAPS_VER(hp), |
1609 | FC_FCOE_VER); | 1616 | FC_FCOE_VER); |
1610 | stats->ErrorFrames++; | 1617 | goto drop; |
1611 | kfree_skb(skb); | ||
1612 | return; | ||
1613 | } | 1618 | } |
1614 | 1619 | ||
1615 | skb_pull(skb, sizeof(struct fcoe_hdr)); | 1620 | skb_pull(skb, sizeof(struct fcoe_hdr)); |
@@ -1624,16 +1629,12 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1624 | fr_sof(fp) = hp->fcoe_sof; | 1629 | fr_sof(fp) = hp->fcoe_sof; |
1625 | 1630 | ||
1626 | /* Copy out the CRC and EOF trailer for access */ | 1631 | /* Copy out the CRC and EOF trailer for access */ |
1627 | if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) { | 1632 | if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) |
1628 | kfree_skb(skb); | 1633 | goto drop; |
1629 | return; | ||
1630 | } | ||
1631 | fr_eof(fp) = crc_eof.fcoe_eof; | 1634 | fr_eof(fp) = crc_eof.fcoe_eof; |
1632 | fr_crc(fp) = crc_eof.fcoe_crc32; | 1635 | fr_crc(fp) = crc_eof.fcoe_crc32; |
1633 | if (pskb_trim(skb, fr_len)) { | 1636 | if (pskb_trim(skb, fr_len)) |
1634 | kfree_skb(skb); | 1637 | goto drop; |
1635 | return; | ||
1636 | } | ||
1637 | 1638 | ||
1638 | /* | 1639 | /* |
1639 | * We only check CRC if no offload is available and if it is | 1640 | * We only check CRC if no offload is available and if it is |
@@ -1647,25 +1648,27 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1647 | fr_flags(fp) |= FCPHF_CRC_UNCHECKED; | 1648 | fr_flags(fp) |= FCPHF_CRC_UNCHECKED; |
1648 | 1649 | ||
1649 | fh = fc_frame_header_get(fp); | 1650 | fh = fc_frame_header_get(fp); |
1650 | if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && | 1651 | if ((fh->fh_r_ctl != FC_RCTL_DD_SOL_DATA || |
1651 | fh->fh_type == FC_TYPE_FCP) { | 1652 | fh->fh_type != FC_TYPE_FCP) && |
1652 | fc_exch_recv(lport, fp); | 1653 | (fr_flags(fp) & FCPHF_CRC_UNCHECKED)) { |
1653 | return; | ||
1654 | } | ||
1655 | if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) { | ||
1656 | if (le32_to_cpu(fr_crc(fp)) != | 1654 | if (le32_to_cpu(fr_crc(fp)) != |
1657 | ~crc32(~0, skb->data, fr_len)) { | 1655 | ~crc32(~0, skb->data, fr_len)) { |
1658 | if (stats->InvalidCRCCount < 5) | 1656 | if (stats->InvalidCRCCount < 5) |
1659 | printk(KERN_WARNING "fcoe: dropping " | 1657 | printk(KERN_WARNING "fcoe: dropping " |
1660 | "frame with CRC error\n"); | 1658 | "frame with CRC error\n"); |
1661 | stats->InvalidCRCCount++; | 1659 | stats->InvalidCRCCount++; |
1662 | stats->ErrorFrames++; | 1660 | goto drop; |
1663 | fc_frame_free(fp); | ||
1664 | return; | ||
1665 | } | 1661 | } |
1666 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | 1662 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; |
1667 | } | 1663 | } |
1664 | put_cpu(); | ||
1668 | fc_exch_recv(lport, fp); | 1665 | fc_exch_recv(lport, fp); |
1666 | return; | ||
1667 | |||
1668 | drop: | ||
1669 | stats->ErrorFrames++; | ||
1670 | put_cpu(); | ||
1671 | kfree_skb(skb); | ||
1669 | } | 1672 | } |
1670 | 1673 | ||
1671 | /** | 1674 | /** |
@@ -1835,11 +1838,15 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1835 | FCOE_NETDEV_DBG(netdev, "Unknown event %ld " | 1838 | FCOE_NETDEV_DBG(netdev, "Unknown event %ld " |
1836 | "from netdev netlink\n", event); | 1839 | "from netdev netlink\n", event); |
1837 | } | 1840 | } |
1841 | |||
1842 | fcoe_link_speed_update(lport); | ||
1843 | |||
1838 | if (link_possible && !fcoe_link_ok(lport)) | 1844 | if (link_possible && !fcoe_link_ok(lport)) |
1839 | fcoe_ctlr_link_up(&fcoe->ctlr); | 1845 | fcoe_ctlr_link_up(&fcoe->ctlr); |
1840 | else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { | 1846 | else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { |
1841 | stats = fc_lport_get_stats(lport); | 1847 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); |
1842 | stats->LinkFailureCount++; | 1848 | stats->LinkFailureCount++; |
1849 | put_cpu(); | ||
1843 | fcoe_clean_pending_queue(lport); | 1850 | fcoe_clean_pending_queue(lport); |
1844 | } | 1851 | } |
1845 | out: | 1852 | out: |
@@ -1901,13 +1908,19 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp) | |||
1901 | goto out_nodev; | 1908 | goto out_nodev; |
1902 | } | 1909 | } |
1903 | 1910 | ||
1904 | rtnl_lock(); | 1911 | if (!rtnl_trylock()) { |
1912 | dev_put(netdev); | ||
1913 | mutex_unlock(&fcoe_config_mutex); | ||
1914 | return restart_syscall(); | ||
1915 | } | ||
1916 | |||
1905 | fcoe = fcoe_hostlist_lookup_port(netdev); | 1917 | fcoe = fcoe_hostlist_lookup_port(netdev); |
1906 | rtnl_unlock(); | 1918 | rtnl_unlock(); |
1907 | 1919 | ||
1908 | if (fcoe) | 1920 | if (fcoe) { |
1909 | fc_fabric_logoff(fcoe->ctlr.lp); | 1921 | fc_fabric_logoff(fcoe->ctlr.lp); |
1910 | else | 1922 | fcoe_ctlr_link_down(&fcoe->ctlr); |
1923 | } else | ||
1911 | rc = -ENODEV; | 1924 | rc = -ENODEV; |
1912 | 1925 | ||
1913 | dev_put(netdev); | 1926 | dev_put(netdev); |
@@ -1950,13 +1963,20 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp) | |||
1950 | goto out_nodev; | 1963 | goto out_nodev; |
1951 | } | 1964 | } |
1952 | 1965 | ||
1953 | rtnl_lock(); | 1966 | if (!rtnl_trylock()) { |
1967 | dev_put(netdev); | ||
1968 | mutex_unlock(&fcoe_config_mutex); | ||
1969 | return restart_syscall(); | ||
1970 | } | ||
1971 | |||
1954 | fcoe = fcoe_hostlist_lookup_port(netdev); | 1972 | fcoe = fcoe_hostlist_lookup_port(netdev); |
1955 | rtnl_unlock(); | 1973 | rtnl_unlock(); |
1956 | 1974 | ||
1957 | if (fcoe) | 1975 | if (fcoe) { |
1976 | if (!fcoe_link_ok(fcoe->ctlr.lp)) | ||
1977 | fcoe_ctlr_link_up(&fcoe->ctlr); | ||
1958 | rc = fc_fabric_login(fcoe->ctlr.lp); | 1978 | rc = fc_fabric_login(fcoe->ctlr.lp); |
1959 | else | 1979 | } else |
1960 | rc = -ENODEV; | 1980 | rc = -ENODEV; |
1961 | 1981 | ||
1962 | dev_put(netdev); | 1982 | dev_put(netdev); |
@@ -1999,7 +2019,12 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | |||
1999 | goto out_nodev; | 2019 | goto out_nodev; |
2000 | } | 2020 | } |
2001 | 2021 | ||
2002 | rtnl_lock(); | 2022 | if (!rtnl_trylock()) { |
2023 | dev_put(netdev); | ||
2024 | mutex_unlock(&fcoe_config_mutex); | ||
2025 | return restart_syscall(); | ||
2026 | } | ||
2027 | |||
2003 | fcoe = fcoe_hostlist_lookup_port(netdev); | 2028 | fcoe = fcoe_hostlist_lookup_port(netdev); |
2004 | if (!fcoe) { | 2029 | if (!fcoe) { |
2005 | rtnl_unlock(); | 2030 | rtnl_unlock(); |
@@ -2008,9 +2033,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | |||
2008 | } | 2033 | } |
2009 | list_del(&fcoe->list); | 2034 | list_del(&fcoe->list); |
2010 | fcoe_interface_cleanup(fcoe); | 2035 | fcoe_interface_cleanup(fcoe); |
2011 | rtnl_unlock(); | 2036 | /* RTNL mutex is dropped by fcoe_if_destroy */ |
2012 | fcoe_if_destroy(fcoe->ctlr.lp); | 2037 | fcoe_if_destroy(fcoe->ctlr.lp); |
2013 | module_put(THIS_MODULE); | ||
2014 | 2038 | ||
2015 | out_putdev: | 2039 | out_putdev: |
2016 | dev_put(netdev); | 2040 | dev_put(netdev); |
@@ -2029,6 +2053,8 @@ static void fcoe_destroy_work(struct work_struct *work) | |||
2029 | 2053 | ||
2030 | port = container_of(work, struct fcoe_port, destroy_work); | 2054 | port = container_of(work, struct fcoe_port, destroy_work); |
2031 | mutex_lock(&fcoe_config_mutex); | 2055 | mutex_lock(&fcoe_config_mutex); |
2056 | rtnl_lock(); | ||
2057 | /* RTNL mutex is dropped by fcoe_if_destroy */ | ||
2032 | fcoe_if_destroy(port->lport); | 2058 | fcoe_if_destroy(port->lport); |
2033 | mutex_unlock(&fcoe_config_mutex); | 2059 | mutex_unlock(&fcoe_config_mutex); |
2034 | } | 2060 | } |
@@ -2050,6 +2076,12 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
2050 | struct net_device *netdev; | 2076 | struct net_device *netdev; |
2051 | 2077 | ||
2052 | mutex_lock(&fcoe_config_mutex); | 2078 | mutex_lock(&fcoe_config_mutex); |
2079 | |||
2080 | if (!rtnl_trylock()) { | ||
2081 | mutex_unlock(&fcoe_config_mutex); | ||
2082 | return restart_syscall(); | ||
2083 | } | ||
2084 | |||
2053 | #ifdef CONFIG_FCOE_MODULE | 2085 | #ifdef CONFIG_FCOE_MODULE |
2054 | /* | 2086 | /* |
2055 | * Make sure the module has been initialized, and is not about to be | 2087 | * Make sure the module has been initialized, and is not about to be |
@@ -2058,7 +2090,7 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
2058 | */ | 2090 | */ |
2059 | if (THIS_MODULE->state != MODULE_STATE_LIVE) { | 2091 | if (THIS_MODULE->state != MODULE_STATE_LIVE) { |
2060 | rc = -ENODEV; | 2092 | rc = -ENODEV; |
2061 | goto out_nodev; | 2093 | goto out_nomod; |
2062 | } | 2094 | } |
2063 | #endif | 2095 | #endif |
2064 | 2096 | ||
@@ -2067,7 +2099,6 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
2067 | goto out_nomod; | 2099 | goto out_nomod; |
2068 | } | 2100 | } |
2069 | 2101 | ||
2070 | rtnl_lock(); | ||
2071 | netdev = fcoe_if_to_netdev(buffer); | 2102 | netdev = fcoe_if_to_netdev(buffer); |
2072 | if (!netdev) { | 2103 | if (!netdev) { |
2073 | rc = -ENODEV; | 2104 | rc = -ENODEV; |
@@ -2122,35 +2153,27 @@ out_free: | |||
2122 | out_putdev: | 2153 | out_putdev: |
2123 | dev_put(netdev); | 2154 | dev_put(netdev); |
2124 | out_nodev: | 2155 | out_nodev: |
2125 | rtnl_unlock(); | ||
2126 | module_put(THIS_MODULE); | 2156 | module_put(THIS_MODULE); |
2127 | out_nomod: | 2157 | out_nomod: |
2158 | rtnl_unlock(); | ||
2128 | mutex_unlock(&fcoe_config_mutex); | 2159 | mutex_unlock(&fcoe_config_mutex); |
2129 | return rc; | 2160 | return rc; |
2130 | } | 2161 | } |
2131 | 2162 | ||
2132 | /** | 2163 | /** |
2133 | * fcoe_link_ok() - Check if the link is OK for a local port | 2164 | * fcoe_link_speed_update() - Update the supported and actual link speeds |
2134 | * @lport: The local port to check link on | 2165 | * @lport: The local port to update speeds for |
2135 | * | ||
2136 | * Any permanently-disqualifying conditions have been previously checked. | ||
2137 | * This also updates the speed setting, which may change with link for 100/1000. | ||
2138 | * | ||
2139 | * This function should probably be checking for PAUSE support at some point | ||
2140 | * in the future. Currently Per-priority-pause is not determinable using | ||
2141 | * ethtool, so we shouldn't be restrictive until that problem is resolved. | ||
2142 | * | ||
2143 | * Returns: 0 if link is OK for use by FCoE. | ||
2144 | * | 2166 | * |
2167 | * Returns: 0 if the ethtool query was successful | ||
2168 | * -1 if the ethtool query failed | ||
2145 | */ | 2169 | */ |
2146 | int fcoe_link_ok(struct fc_lport *lport) | 2170 | int fcoe_link_speed_update(struct fc_lport *lport) |
2147 | { | 2171 | { |
2148 | struct fcoe_port *port = lport_priv(lport); | 2172 | struct fcoe_port *port = lport_priv(lport); |
2149 | struct net_device *netdev = port->fcoe->netdev; | 2173 | struct net_device *netdev = port->fcoe->netdev; |
2150 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; | 2174 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; |
2151 | 2175 | ||
2152 | if ((netdev->flags & IFF_UP) && netif_carrier_ok(netdev) && | 2176 | if (!dev_ethtool_get_settings(netdev, &ecmd)) { |
2153 | (!dev_ethtool_get_settings(netdev, &ecmd))) { | ||
2154 | lport->link_supported_speeds &= | 2177 | lport->link_supported_speeds &= |
2155 | ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); | 2178 | ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); |
2156 | if (ecmd.supported & (SUPPORTED_1000baseT_Half | | 2179 | if (ecmd.supported & (SUPPORTED_1000baseT_Half | |
@@ -2170,6 +2193,23 @@ int fcoe_link_ok(struct fc_lport *lport) | |||
2170 | } | 2193 | } |
2171 | 2194 | ||
2172 | /** | 2195 | /** |
2196 | * fcoe_link_ok() - Check if the link is OK for a local port | ||
2197 | * @lport: The local port to check link on | ||
2198 | * | ||
2199 | * Returns: 0 if link is UP and OK, -1 if not | ||
2200 | * | ||
2201 | */ | ||
2202 | int fcoe_link_ok(struct fc_lport *lport) | ||
2203 | { | ||
2204 | struct fcoe_port *port = lport_priv(lport); | ||
2205 | struct net_device *netdev = port->fcoe->netdev; | ||
2206 | |||
2207 | if (netif_oper_up(netdev)) | ||
2208 | return 0; | ||
2209 | return -1; | ||
2210 | } | ||
2211 | |||
2212 | /** | ||
2173 | * fcoe_percpu_clean() - Clear all pending skbs for an local port | 2213 | * fcoe_percpu_clean() - Clear all pending skbs for an local port |
2174 | * @lport: The local port whose skbs are to be cleared | 2214 | * @lport: The local port whose skbs are to be cleared |
2175 | * | 2215 | * |
@@ -2631,3 +2671,25 @@ static void fcoe_get_lesb(struct fc_lport *lport, | |||
2631 | lesb->lesb_miss_fka = htonl(mdac); | 2671 | lesb->lesb_miss_fka = htonl(mdac); |
2632 | lesb->lesb_fcs_error = htonl(dev_get_stats(netdev)->rx_crc_errors); | 2672 | lesb->lesb_fcs_error = htonl(dev_get_stats(netdev)->rx_crc_errors); |
2633 | } | 2673 | } |
2674 | |||
2675 | /** | ||
2676 | * fcoe_set_port_id() - Callback from libfc when Port_ID is set. | ||
2677 | * @lport: the local port | ||
2678 | * @port_id: the port ID | ||
2679 | * @fp: the received frame, if any, that caused the port_id to be set. | ||
2680 | * | ||
2681 | * This routine handles the case where we received a FLOGI and are | ||
2682 | * entering point-to-point mode. We need to call fcoe_ctlr_recv_flogi() | ||
2683 | * so it can set the non-mapped mode and gateway address. | ||
2684 | * | ||
2685 | * The FLOGI LS_ACC is handled by fcoe_flogi_resp(). | ||
2686 | */ | ||
2687 | static void fcoe_set_port_id(struct fc_lport *lport, | ||
2688 | u32 port_id, struct fc_frame *fp) | ||
2689 | { | ||
2690 | struct fcoe_port *port = lport_priv(lport); | ||
2691 | struct fcoe_interface *fcoe = port->fcoe; | ||
2692 | |||
2693 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) | ||
2694 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); | ||
2695 | } | ||
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 3440da48d169..50aaa4bcfc50 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c | |||
@@ -51,7 +51,7 @@ MODULE_LICENSE("GPL v2"); | |||
51 | #define FCOE_CTLR_DEF_FKA FIP_DEF_FKA /* default keep alive (mS) */ | 51 | #define FCOE_CTLR_DEF_FKA FIP_DEF_FKA /* default keep alive (mS) */ |
52 | 52 | ||
53 | static void fcoe_ctlr_timeout(unsigned long); | 53 | static void fcoe_ctlr_timeout(unsigned long); |
54 | static void fcoe_ctlr_link_work(struct work_struct *); | 54 | static void fcoe_ctlr_timer_work(struct work_struct *); |
55 | static void fcoe_ctlr_recv_work(struct work_struct *); | 55 | static void fcoe_ctlr_recv_work(struct work_struct *); |
56 | 56 | ||
57 | static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS; | 57 | static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS; |
@@ -116,7 +116,7 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip) | |||
116 | spin_lock_init(&fip->lock); | 116 | spin_lock_init(&fip->lock); |
117 | fip->flogi_oxid = FC_XID_UNKNOWN; | 117 | fip->flogi_oxid = FC_XID_UNKNOWN; |
118 | setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip); | 118 | setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip); |
119 | INIT_WORK(&fip->link_work, fcoe_ctlr_link_work); | 119 | INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work); |
120 | INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work); | 120 | INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work); |
121 | skb_queue_head_init(&fip->fip_recv_list); | 121 | skb_queue_head_init(&fip->fip_recv_list); |
122 | } | 122 | } |
@@ -164,7 +164,7 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) | |||
164 | fcoe_ctlr_reset_fcfs(fip); | 164 | fcoe_ctlr_reset_fcfs(fip); |
165 | spin_unlock_bh(&fip->lock); | 165 | spin_unlock_bh(&fip->lock); |
166 | del_timer_sync(&fip->timer); | 166 | del_timer_sync(&fip->timer); |
167 | cancel_work_sync(&fip->link_work); | 167 | cancel_work_sync(&fip->timer_work); |
168 | } | 168 | } |
169 | EXPORT_SYMBOL(fcoe_ctlr_destroy); | 169 | EXPORT_SYMBOL(fcoe_ctlr_destroy); |
170 | 170 | ||
@@ -257,14 +257,10 @@ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip) | |||
257 | { | 257 | { |
258 | spin_lock_bh(&fip->lock); | 258 | spin_lock_bh(&fip->lock); |
259 | if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) { | 259 | if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) { |
260 | fip->last_link = 1; | ||
261 | fip->link = 1; | ||
262 | spin_unlock_bh(&fip->lock); | 260 | spin_unlock_bh(&fip->lock); |
263 | fc_linkup(fip->lp); | 261 | fc_linkup(fip->lp); |
264 | } else if (fip->state == FIP_ST_LINK_WAIT) { | 262 | } else if (fip->state == FIP_ST_LINK_WAIT) { |
265 | fip->state = fip->mode; | 263 | fip->state = fip->mode; |
266 | fip->last_link = 1; | ||
267 | fip->link = 1; | ||
268 | spin_unlock_bh(&fip->lock); | 264 | spin_unlock_bh(&fip->lock); |
269 | if (fip->state == FIP_ST_AUTO) | 265 | if (fip->state == FIP_ST_AUTO) |
270 | LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n"); | 266 | LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n"); |
@@ -306,9 +302,7 @@ int fcoe_ctlr_link_down(struct fcoe_ctlr *fip) | |||
306 | LIBFCOE_FIP_DBG(fip, "link down.\n"); | 302 | LIBFCOE_FIP_DBG(fip, "link down.\n"); |
307 | spin_lock_bh(&fip->lock); | 303 | spin_lock_bh(&fip->lock); |
308 | fcoe_ctlr_reset(fip); | 304 | fcoe_ctlr_reset(fip); |
309 | link_dropped = fip->link; | 305 | link_dropped = fip->state != FIP_ST_LINK_WAIT; |
310 | fip->link = 0; | ||
311 | fip->last_link = 0; | ||
312 | fip->state = FIP_ST_LINK_WAIT; | 306 | fip->state = FIP_ST_LINK_WAIT; |
313 | spin_unlock_bh(&fip->lock); | 307 | spin_unlock_bh(&fip->lock); |
314 | 308 | ||
@@ -349,7 +343,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, | |||
349 | 343 | ||
350 | fcf = fip->sel_fcf; | 344 | fcf = fip->sel_fcf; |
351 | lp = fip->lp; | 345 | lp = fip->lp; |
352 | if (!fcf || !fc_host_port_id(lp->host)) | 346 | if (!fcf || !lp->port_id) |
353 | return; | 347 | return; |
354 | 348 | ||
355 | len = sizeof(*kal) + ports * sizeof(*vn); | 349 | len = sizeof(*kal) + ports * sizeof(*vn); |
@@ -380,8 +374,8 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, | |||
380 | vn->fd_desc.fip_dtype = FIP_DT_VN_ID; | 374 | vn->fd_desc.fip_dtype = FIP_DT_VN_ID; |
381 | vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW; | 375 | vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW; |
382 | memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN); | 376 | memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN); |
383 | hton24(vn->fd_fc_id, fc_host_port_id(lp->host)); | 377 | hton24(vn->fd_fc_id, lport->port_id); |
384 | put_unaligned_be64(lp->wwpn, &vn->fd_wwpn); | 378 | put_unaligned_be64(lport->wwpn, &vn->fd_wwpn); |
385 | } | 379 | } |
386 | skb_put(skb, len); | 380 | skb_put(skb, len); |
387 | skb->protocol = htons(ETH_P_FIP); | 381 | skb->protocol = htons(ETH_P_FIP); |
@@ -445,13 +439,18 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, | |||
445 | cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; | 439 | cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; |
446 | 440 | ||
447 | mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac)); | 441 | mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac)); |
448 | memset(mac, 0, sizeof(mac)); | 442 | memset(mac, 0, sizeof(*mac)); |
449 | mac->fd_desc.fip_dtype = FIP_DT_MAC; | 443 | mac->fd_desc.fip_dtype = FIP_DT_MAC; |
450 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; | 444 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; |
451 | if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) | 445 | if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) { |
452 | memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); | 446 | memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); |
453 | else if (fip->spma) | 447 | } else if (fip_flags & FIP_FL_SPMA) { |
448 | LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n"); | ||
454 | memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); | 449 | memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); |
450 | } else { | ||
451 | LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n"); | ||
452 | /* FPMA only FLOGI must leave the MAC desc set to all 0s */ | ||
453 | } | ||
455 | 454 | ||
456 | skb->protocol = htons(ETH_P_FIP); | 455 | skb->protocol = htons(ETH_P_FIP); |
457 | skb_reset_mac_header(skb); | 456 | skb_reset_mac_header(skb); |
@@ -556,7 +555,7 @@ EXPORT_SYMBOL(fcoe_ctlr_els_send); | |||
556 | * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller | 555 | * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller |
557 | * @fip: The FCoE controller to free FCFs on | 556 | * @fip: The FCoE controller to free FCFs on |
558 | * | 557 | * |
559 | * Called with lock held. | 558 | * Called with lock held and preemption disabled. |
560 | * | 559 | * |
561 | * An FCF is considered old if we have missed three advertisements. | 560 | * An FCF is considered old if we have missed three advertisements. |
562 | * That is, there have been no valid advertisement from it for three | 561 | * That is, there have been no valid advertisement from it for three |
@@ -573,17 +572,20 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
573 | struct fcoe_fcf *next; | 572 | struct fcoe_fcf *next; |
574 | unsigned long sel_time = 0; | 573 | unsigned long sel_time = 0; |
575 | unsigned long mda_time = 0; | 574 | unsigned long mda_time = 0; |
575 | struct fcoe_dev_stats *stats; | ||
576 | 576 | ||
577 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { | 577 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { |
578 | mda_time = fcf->fka_period + (fcf->fka_period >> 1); | 578 | mda_time = fcf->fka_period + (fcf->fka_period >> 1); |
579 | if ((fip->sel_fcf == fcf) && | 579 | if ((fip->sel_fcf == fcf) && |
580 | (time_after(jiffies, fcf->time + mda_time))) { | 580 | (time_after(jiffies, fcf->time + mda_time))) { |
581 | mod_timer(&fip->timer, jiffies + mda_time); | 581 | mod_timer(&fip->timer, jiffies + mda_time); |
582 | fc_lport_get_stats(fip->lp)->MissDiscAdvCount++; | 582 | stats = per_cpu_ptr(fip->lp->dev_stats, |
583 | smp_processor_id()); | ||
584 | stats->MissDiscAdvCount++; | ||
583 | printk(KERN_INFO "libfcoe: host%d: Missing Discovery " | 585 | printk(KERN_INFO "libfcoe: host%d: Missing Discovery " |
584 | "Advertisement for fab %llx count %lld\n", | 586 | "Advertisement for fab %16.16llx count %lld\n", |
585 | fip->lp->host->host_no, fcf->fabric_name, | 587 | fip->lp->host->host_no, fcf->fabric_name, |
586 | fc_lport_get_stats(fip->lp)->MissDiscAdvCount); | 588 | stats->MissDiscAdvCount); |
587 | } | 589 | } |
588 | if (time_after(jiffies, fcf->time + fcf->fka_period * 3 + | 590 | if (time_after(jiffies, fcf->time + fcf->fka_period * 3 + |
589 | msecs_to_jiffies(FIP_FCF_FUZZ * 3))) { | 591 | msecs_to_jiffies(FIP_FCF_FUZZ * 3))) { |
@@ -593,7 +595,9 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
593 | WARN_ON(!fip->fcf_count); | 595 | WARN_ON(!fip->fcf_count); |
594 | fip->fcf_count--; | 596 | fip->fcf_count--; |
595 | kfree(fcf); | 597 | kfree(fcf); |
596 | fc_lport_get_stats(fip->lp)->VLinkFailureCount++; | 598 | stats = per_cpu_ptr(fip->lp->dev_stats, |
599 | smp_processor_id()); | ||
600 | stats->VLinkFailureCount++; | ||
597 | } else if (fcoe_ctlr_mtu_valid(fcf) && | 601 | } else if (fcoe_ctlr_mtu_valid(fcf) && |
598 | (!sel_time || time_before(sel_time, fcf->time))) { | 602 | (!sel_time || time_before(sel_time, fcf->time))) { |
599 | sel_time = fcf->time; | 603 | sel_time = fcf->time; |
@@ -776,7 +780,8 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
776 | mtu_valid = fcoe_ctlr_mtu_valid(fcf); | 780 | mtu_valid = fcoe_ctlr_mtu_valid(fcf); |
777 | fcf->time = jiffies; | 781 | fcf->time = jiffies; |
778 | if (!found) { | 782 | if (!found) { |
779 | LIBFCOE_FIP_DBG(fip, "New FCF for fab %llx map %x val %d\n", | 783 | LIBFCOE_FIP_DBG(fip, "New FCF for fab %16.16llx " |
784 | "map %x val %d\n", | ||
780 | fcf->fabric_name, fcf->fc_map, mtu_valid); | 785 | fcf->fabric_name, fcf->fc_map, mtu_valid); |
781 | } | 786 | } |
782 | 787 | ||
@@ -906,9 +911,10 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
906 | fr_eof(fp) = FC_EOF_T; | 911 | fr_eof(fp) = FC_EOF_T; |
907 | fr_dev(fp) = lport; | 912 | fr_dev(fp) = lport; |
908 | 913 | ||
909 | stats = fc_lport_get_stats(lport); | 914 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); |
910 | stats->RxFrames++; | 915 | stats->RxFrames++; |
911 | stats->RxWords += skb->len / FIP_BPW; | 916 | stats->RxWords += skb->len / FIP_BPW; |
917 | put_cpu(); | ||
912 | 918 | ||
913 | fc_exch_recv(lport, fp); | 919 | fc_exch_recv(lport, fp); |
914 | return; | 920 | return; |
@@ -942,9 +948,8 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
942 | u32 desc_mask; | 948 | u32 desc_mask; |
943 | 949 | ||
944 | LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); | 950 | LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); |
945 | if (!fcf) | 951 | |
946 | return; | 952 | if (!fcf || !lport->port_id) |
947 | if (!fcf || !fc_host_port_id(lport->host)) | ||
948 | return; | 953 | return; |
949 | 954 | ||
950 | /* | 955 | /* |
@@ -982,8 +987,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
982 | if (compare_ether_addr(vp->fd_mac, | 987 | if (compare_ether_addr(vp->fd_mac, |
983 | fip->get_src_addr(lport)) == 0 && | 988 | fip->get_src_addr(lport)) == 0 && |
984 | get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn && | 989 | get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn && |
985 | ntoh24(vp->fd_fc_id) == | 990 | ntoh24(vp->fd_fc_id) == lport->port_id) |
986 | fc_host_port_id(lport->host)) | ||
987 | desc_mask &= ~BIT(FIP_DT_VN_ID); | 991 | desc_mask &= ~BIT(FIP_DT_VN_ID); |
988 | break; | 992 | break; |
989 | default: | 993 | default: |
@@ -1006,7 +1010,8 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
1006 | LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); | 1010 | LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); |
1007 | 1011 | ||
1008 | spin_lock_bh(&fip->lock); | 1012 | spin_lock_bh(&fip->lock); |
1009 | fc_lport_get_stats(lport)->VLinkFailureCount++; | 1013 | per_cpu_ptr(lport->dev_stats, |
1014 | smp_processor_id())->VLinkFailureCount++; | ||
1010 | fcoe_ctlr_reset(fip); | 1015 | fcoe_ctlr_reset(fip); |
1011 | spin_unlock_bh(&fip->lock); | 1016 | spin_unlock_bh(&fip->lock); |
1012 | 1017 | ||
@@ -1102,15 +1107,17 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) | |||
1102 | struct fcoe_fcf *best = NULL; | 1107 | struct fcoe_fcf *best = NULL; |
1103 | 1108 | ||
1104 | list_for_each_entry(fcf, &fip->fcfs, list) { | 1109 | list_for_each_entry(fcf, &fip->fcfs, list) { |
1105 | LIBFCOE_FIP_DBG(fip, "consider FCF for fab %llx VFID %d map %x " | 1110 | LIBFCOE_FIP_DBG(fip, "consider FCF for fab %16.16llx " |
1106 | "val %d\n", fcf->fabric_name, fcf->vfid, | 1111 | "VFID %d map %x val %d\n", |
1112 | fcf->fabric_name, fcf->vfid, | ||
1107 | fcf->fc_map, fcoe_ctlr_mtu_valid(fcf)); | 1113 | fcf->fc_map, fcoe_ctlr_mtu_valid(fcf)); |
1108 | if (!fcoe_ctlr_fcf_usable(fcf)) { | 1114 | if (!fcoe_ctlr_fcf_usable(fcf)) { |
1109 | LIBFCOE_FIP_DBG(fip, "FCF for fab %llx map %x %svalid " | 1115 | LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx " |
1110 | "%savailable\n", fcf->fabric_name, | 1116 | "map %x %svalid %savailable\n", |
1111 | fcf->fc_map, (fcf->flags & FIP_FL_SOL) | 1117 | fcf->fabric_name, fcf->fc_map, |
1112 | ? "" : "in", (fcf->flags & FIP_FL_AVAIL) | 1118 | (fcf->flags & FIP_FL_SOL) ? "" : "in", |
1113 | ? "" : "un"); | 1119 | (fcf->flags & FIP_FL_AVAIL) ? |
1120 | "" : "un"); | ||
1114 | continue; | 1121 | continue; |
1115 | } | 1122 | } |
1116 | if (!best) { | 1123 | if (!best) { |
@@ -1175,7 +1182,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1175 | "Starting FCF discovery.\n", | 1182 | "Starting FCF discovery.\n", |
1176 | fip->lp->host->host_no); | 1183 | fip->lp->host->host_no); |
1177 | fip->reset_req = 1; | 1184 | fip->reset_req = 1; |
1178 | schedule_work(&fip->link_work); | 1185 | schedule_work(&fip->timer_work); |
1179 | } | 1186 | } |
1180 | } | 1187 | } |
1181 | 1188 | ||
@@ -1201,43 +1208,31 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1201 | mod_timer(&fip->timer, next_timer); | 1208 | mod_timer(&fip->timer, next_timer); |
1202 | } | 1209 | } |
1203 | if (fip->send_ctlr_ka || fip->send_port_ka) | 1210 | if (fip->send_ctlr_ka || fip->send_port_ka) |
1204 | schedule_work(&fip->link_work); | 1211 | schedule_work(&fip->timer_work); |
1205 | spin_unlock_bh(&fip->lock); | 1212 | spin_unlock_bh(&fip->lock); |
1206 | } | 1213 | } |
1207 | 1214 | ||
1208 | /** | 1215 | /** |
1209 | * fcoe_ctlr_link_work() - Worker thread function for link changes | 1216 | * fcoe_ctlr_timer_work() - Worker thread function for timer work |
1210 | * @work: Handle to a FCoE controller | 1217 | * @work: Handle to a FCoE controller |
1211 | * | 1218 | * |
1212 | * See if the link status has changed and if so, report it. | 1219 | * Sends keep-alives and resets which must not |
1213 | * | ||
1214 | * This is here because fc_linkup() and fc_linkdown() must not | ||
1215 | * be called from the timer directly, since they use a mutex. | 1220 | * be called from the timer directly, since they use a mutex. |
1216 | */ | 1221 | */ |
1217 | static void fcoe_ctlr_link_work(struct work_struct *work) | 1222 | static void fcoe_ctlr_timer_work(struct work_struct *work) |
1218 | { | 1223 | { |
1219 | struct fcoe_ctlr *fip; | 1224 | struct fcoe_ctlr *fip; |
1220 | struct fc_lport *vport; | 1225 | struct fc_lport *vport; |
1221 | u8 *mac; | 1226 | u8 *mac; |
1222 | int link; | ||
1223 | int last_link; | ||
1224 | int reset; | 1227 | int reset; |
1225 | 1228 | ||
1226 | fip = container_of(work, struct fcoe_ctlr, link_work); | 1229 | fip = container_of(work, struct fcoe_ctlr, timer_work); |
1227 | spin_lock_bh(&fip->lock); | 1230 | spin_lock_bh(&fip->lock); |
1228 | last_link = fip->last_link; | ||
1229 | link = fip->link; | ||
1230 | fip->last_link = link; | ||
1231 | reset = fip->reset_req; | 1231 | reset = fip->reset_req; |
1232 | fip->reset_req = 0; | 1232 | fip->reset_req = 0; |
1233 | spin_unlock_bh(&fip->lock); | 1233 | spin_unlock_bh(&fip->lock); |
1234 | 1234 | ||
1235 | if (last_link != link) { | 1235 | if (reset) |
1236 | if (link) | ||
1237 | fc_linkup(fip->lp); | ||
1238 | else | ||
1239 | fc_linkdown(fip->lp); | ||
1240 | } else if (reset && link) | ||
1241 | fc_lport_reset(fip->lp); | 1236 | fc_lport_reset(fip->lp); |
1242 | 1237 | ||
1243 | if (fip->send_ctlr_ka) { | 1238 | if (fip->send_ctlr_ka) { |
@@ -1334,9 +1329,9 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, | |||
1334 | if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) { | 1329 | if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) { |
1335 | memcpy(fip->dest_addr, sa, ETH_ALEN); | 1330 | memcpy(fip->dest_addr, sa, ETH_ALEN); |
1336 | fip->map_dest = 0; | 1331 | fip->map_dest = 0; |
1337 | if (fip->state == FIP_ST_NON_FIP) | 1332 | if (fip->state == FIP_ST_AUTO) |
1338 | LIBFCOE_FIP_DBG(fip, "received FLOGI REQ, " | 1333 | LIBFCOE_FIP_DBG(fip, "received non-FIP FLOGI. " |
1339 | "using non-FIP mode\n"); | 1334 | "Setting non-FIP mode\n"); |
1340 | fip->state = FIP_ST_NON_FIP; | 1335 | fip->state = FIP_ST_NON_FIP; |
1341 | } | 1336 | } |
1342 | spin_unlock_bh(&fip->lock); | 1337 | spin_unlock_bh(&fip->lock); |