aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-04 18:15:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-04 18:15:15 -0400
commit03da30986793385af57eeca3296253c887b742e6 (patch)
tree9c46dbe51c9d0856990649dd917ab45474b7be87 /drivers/scsi/fcoe/fcoe.c
parent6ba74014c1ab0e37af7de6f64b4eccbbae3cb9e7 (diff)
parent339f4f4eab80caa6cf0d39fb057ad6ddb84ba91e (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: (276 commits) [SCSI] zfcp: Trigger logging in the FCP channel on qdio error conditions [SCSI] zfcp: Introduce experimental support for DIF/DIX [SCSI] zfcp: Enable data division support for FCP devices [SCSI] zfcp: Prevent access on uninitialized memory. [SCSI] zfcp: Post events through FC transport class [SCSI] zfcp: Cleanup QDIO attachment and improve processing. [SCSI] zfcp: Cleanup function parameters for sbal value. [SCSI] zfcp: Use correct width for timer_interval field [SCSI] zfcp: Remove SCSI device when removing unit [SCSI] zfcp: Use memdup_user and kstrdup [SCSI] zfcp: Fix retry after failed "open port" erp action [SCSI] zfcp: Fail erp after timeout [SCSI] zfcp: Use forced_reopen in terminate_rport_io callback [SCSI] zfcp: Register SCSI devices after successful fc_remote_port_add [SCSI] zfcp: Do not try "forced close" when port is already closed [SCSI] zfcp: Do not unblock rport from REOPEN_PORT_FORCED [SCSI] sd: add support for runtime PM [SCSI] implement runtime Power Management [SCSI] convert to the new PM framework [SCSI] Unify SAM_ and SAM_STAT_ macros ...
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r--drivers/scsi/fcoe/fcoe.c147
1 files changed, 98 insertions, 49 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 1a429ed6da9d..e79605a61155 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -117,9 +117,14 @@ static void fcoe_recv_frame(struct sk_buff *skb);
117 117
118static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *); 118static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *);
119 119
120module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); 120module_param_call(create, fcoe_create, NULL, (void *)FIP_MODE_AUTO, S_IWUSR);
121__MODULE_PARM_TYPE(create, "string"); 121__MODULE_PARM_TYPE(create, "string");
122MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface"); 122MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
123module_param_call(create_vn2vn, fcoe_create, NULL,
124 (void *)FIP_MODE_VN2VN, S_IWUSR);
125__MODULE_PARM_TYPE(create_vn2vn, "string");
126MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
127 "on an Ethernet interface");
123module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); 128module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
124__MODULE_PARM_TYPE(destroy, "string"); 129__MODULE_PARM_TYPE(destroy, "string");
125MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface"); 130MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
@@ -315,7 +320,11 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
315 dev_uc_add(netdev, flogi_maddr); 320 dev_uc_add(netdev, flogi_maddr);
316 if (fip->spma) 321 if (fip->spma)
317 dev_uc_add(netdev, fip->ctl_src_addr); 322 dev_uc_add(netdev, fip->ctl_src_addr);
318 dev_mc_add(netdev, FIP_ALL_ENODE_MACS); 323 if (fip->mode == FIP_MODE_VN2VN) {
324 dev_mc_add(netdev, FIP_ALL_VN2VN_MACS);
325 dev_mc_add(netdev, FIP_ALL_P2P_MACS);
326 } else
327 dev_mc_add(netdev, FIP_ALL_ENODE_MACS);
319 328
320 /* 329 /*
321 * setup the receive function from ethernet driver 330 * setup the receive function from ethernet driver
@@ -337,10 +346,12 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
337/** 346/**
338 * fcoe_interface_create() - Create a FCoE interface on a net device 347 * fcoe_interface_create() - Create a FCoE interface on a net device
339 * @netdev: The net device to create the FCoE interface on 348 * @netdev: The net device to create the FCoE interface on
349 * @fip_mode: The mode to use for FIP
340 * 350 *
341 * Returns: pointer to a struct fcoe_interface or NULL on error 351 * Returns: pointer to a struct fcoe_interface or NULL on error
342 */ 352 */
343static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) 353static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
354 enum fip_state fip_mode)
344{ 355{
345 struct fcoe_interface *fcoe; 356 struct fcoe_interface *fcoe;
346 int err; 357 int err;
@@ -357,7 +368,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
357 /* 368 /*
358 * Initialize FIP. 369 * Initialize FIP.
359 */ 370 */
360 fcoe_ctlr_init(&fcoe->ctlr); 371 fcoe_ctlr_init(&fcoe->ctlr, fip_mode);
361 fcoe->ctlr.send = fcoe_fip_send; 372 fcoe->ctlr.send = fcoe_fip_send;
362 fcoe->ctlr.update_mac = fcoe_update_src_mac; 373 fcoe->ctlr.update_mac = fcoe_update_src_mac;
363 fcoe->ctlr.get_src_addr = fcoe_get_src_mac; 374 fcoe->ctlr.get_src_addr = fcoe_get_src_mac;
@@ -401,7 +412,11 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
401 dev_uc_del(netdev, flogi_maddr); 412 dev_uc_del(netdev, flogi_maddr);
402 if (fip->spma) 413 if (fip->spma)
403 dev_uc_del(netdev, fip->ctl_src_addr); 414 dev_uc_del(netdev, fip->ctl_src_addr);
404 dev_mc_del(netdev, FIP_ALL_ENODE_MACS); 415 if (fip->mode == FIP_MODE_VN2VN) {
416 dev_mc_del(netdev, FIP_ALL_VN2VN_MACS);
417 dev_mc_del(netdev, FIP_ALL_P2P_MACS);
418 } else
419 dev_mc_del(netdev, FIP_ALL_ENODE_MACS);
405 420
406 /* Tell the LLD we are done w/ FCoE */ 421 /* Tell the LLD we are done w/ FCoE */
407 ops = netdev->netdev_ops; 422 ops = netdev->netdev_ops;
@@ -574,6 +589,50 @@ static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
574} 589}
575 590
576/** 591/**
592 * fcoe_netdev_features_change - Updates the lport's offload flags based
593 * on the LLD netdev's FCoE feature flags
594 */
595static void fcoe_netdev_features_change(struct fc_lport *lport,
596 struct net_device *netdev)
597{
598 mutex_lock(&lport->lp_mutex);
599
600 if (netdev->features & NETIF_F_SG)
601 lport->sg_supp = 1;
602 else
603 lport->sg_supp = 0;
604
605 if (netdev->features & NETIF_F_FCOE_CRC) {
606 lport->crc_offload = 1;
607 FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n");
608 } else {
609 lport->crc_offload = 0;
610 }
611
612 if (netdev->features & NETIF_F_FSO) {
613 lport->seq_offload = 1;
614 lport->lso_max = netdev->gso_max_size;
615 FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
616 lport->lso_max);
617 } else {
618 lport->seq_offload = 0;
619 lport->lso_max = 0;
620 }
621
622 if (netdev->fcoe_ddp_xid) {
623 lport->lro_enabled = 1;
624 lport->lro_xid = netdev->fcoe_ddp_xid;
625 FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n",
626 lport->lro_xid);
627 } else {
628 lport->lro_enabled = 0;
629 lport->lro_xid = 0;
630 }
631
632 mutex_unlock(&lport->lp_mutex);
633}
634
635/**
577 * fcoe_netdev_config() - Set up net devive for SW FCoE 636 * fcoe_netdev_config() - Set up net devive for SW FCoE
578 * @lport: The local port that is associated with the net device 637 * @lport: The local port that is associated with the net device
579 * @netdev: The associated net device 638 * @netdev: The associated net device
@@ -588,7 +647,6 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
588 u64 wwnn, wwpn; 647 u64 wwnn, wwpn;
589 struct fcoe_interface *fcoe; 648 struct fcoe_interface *fcoe;
590 struct fcoe_port *port; 649 struct fcoe_port *port;
591 int vid = 0;
592 650
593 /* Setup lport private data to point to fcoe softc */ 651 /* Setup lport private data to point to fcoe softc */
594 port = lport_priv(lport); 652 port = lport_priv(lport);
@@ -609,25 +667,8 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
609 return -EINVAL; 667 return -EINVAL;
610 668
611 /* offload features support */ 669 /* offload features support */
612 if (netdev->features & NETIF_F_SG) 670 fcoe_netdev_features_change(lport, netdev);
613 lport->sg_supp = 1;
614 671
615 if (netdev->features & NETIF_F_FCOE_CRC) {
616 lport->crc_offload = 1;
617 FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n");
618 }
619 if (netdev->features & NETIF_F_FSO) {
620 lport->seq_offload = 1;
621 lport->lso_max = netdev->gso_max_size;
622 FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
623 lport->lso_max);
624 }
625 if (netdev->fcoe_ddp_xid) {
626 lport->lro_enabled = 1;
627 lport->lro_xid = netdev->fcoe_ddp_xid;
628 FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n",
629 lport->lro_xid);
630 }
631 skb_queue_head_init(&port->fcoe_pending_queue); 672 skb_queue_head_init(&port->fcoe_pending_queue);
632 port->fcoe_pending_queue_active = 0; 673 port->fcoe_pending_queue_active = 0;
633 setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport); 674 setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport);
@@ -635,20 +676,12 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
635 fcoe_link_speed_update(lport); 676 fcoe_link_speed_update(lport);
636 677
637 if (!lport->vport) { 678 if (!lport->vport) {
638 /*
639 * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN:
640 * For WWNN, we use NAA 1 w/ bit 27-16 of word 0 as 0.
641 * For WWPN, we use NAA 2 w/ bit 27-16 of word 0 from VLAN ID
642 */
643 if (netdev->priv_flags & IFF_802_1Q_VLAN)
644 vid = vlan_dev_vlan_id(netdev);
645
646 if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) 679 if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN))
647 wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0); 680 wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
648 fc_set_wwnn(lport, wwnn); 681 fc_set_wwnn(lport, wwnn);
649 if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) 682 if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN))
650 wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 683 wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr,
651 2, vid); 684 2, 0);
652 fc_set_wwpn(lport, wwpn); 685 fc_set_wwpn(lport, wwpn);
653 } 686 }
654 687
@@ -967,7 +1000,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
967 } 1000 }
968 1001
969 /* Initialize the library */ 1002 /* Initialize the library */
970 rc = fcoe_libfc_config(lport, &fcoe_libfc_fcn_templ); 1003 rc = fcoe_libfc_config(lport, &fcoe->ctlr, &fcoe_libfc_fcn_templ, 1);
971 if (rc) { 1004 if (rc) {
972 FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " 1005 FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the "
973 "interface\n"); 1006 "interface\n");
@@ -1210,6 +1243,8 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
1210 struct fcoe_interface *fcoe; 1243 struct fcoe_interface *fcoe;
1211 struct fc_frame_header *fh; 1244 struct fc_frame_header *fh;
1212 struct fcoe_percpu_s *fps; 1245 struct fcoe_percpu_s *fps;
1246 struct fcoe_port *port;
1247 struct ethhdr *eh;
1213 unsigned int cpu; 1248 unsigned int cpu;
1214 1249
1215 fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); 1250 fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type);
@@ -1227,9 +1262,21 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
1227 skb_tail_pointer(skb), skb_end_pointer(skb), 1262 skb_tail_pointer(skb), skb_end_pointer(skb),
1228 skb->csum, skb->dev ? skb->dev->name : "<NULL>"); 1263 skb->csum, skb->dev ? skb->dev->name : "<NULL>");
1229 1264
1230 /* check for FCOE packet type */ 1265 /* check for mac addresses */
1231 if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { 1266 eh = eth_hdr(skb);
1232 FCOE_NETDEV_DBG(netdev, "Wrong FC type frame"); 1267 port = lport_priv(lport);
1268 if (compare_ether_addr(eh->h_dest, port->data_src_addr) &&
1269 compare_ether_addr(eh->h_dest, fcoe->ctlr.ctl_src_addr) &&
1270 compare_ether_addr(eh->h_dest, (u8[6])FC_FCOE_FLOGI_MAC)) {
1271 FCOE_NETDEV_DBG(netdev, "wrong destination mac address:%pM\n",
1272 eh->h_dest);
1273 goto err;
1274 }
1275
1276 if (is_fip_mode(&fcoe->ctlr) &&
1277 compare_ether_addr(eh->h_source, fcoe->ctlr.dest_addr)) {
1278 FCOE_NETDEV_DBG(netdev, "wrong source mac address:%pM\n",
1279 eh->h_source);
1233 goto err; 1280 goto err;
1234 } 1281 }
1235 1282
@@ -1512,11 +1559,9 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
1512 /* fill up mac and fcoe headers */ 1559 /* fill up mac and fcoe headers */
1513 eh = eth_hdr(skb); 1560 eh = eth_hdr(skb);
1514 eh->h_proto = htons(ETH_P_FCOE); 1561 eh->h_proto = htons(ETH_P_FCOE);
1562 memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN);
1515 if (fcoe->ctlr.map_dest) 1563 if (fcoe->ctlr.map_dest)
1516 fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id); 1564 memcpy(eh->h_dest + 3, fh->fh_d_id, 3);
1517 else
1518 /* insert GW address */
1519 memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN);
1520 1565
1521 if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) 1566 if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN))
1522 memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); 1567 memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN);
@@ -1834,6 +1879,9 @@ static int fcoe_device_notification(struct notifier_block *notifier,
1834 schedule_work(&port->destroy_work); 1879 schedule_work(&port->destroy_work);
1835 goto out; 1880 goto out;
1836 break; 1881 break;
1882 case NETDEV_FEAT_CHANGE:
1883 fcoe_netdev_features_change(lport, netdev);
1884 break;
1837 default: 1885 default:
1838 FCOE_NETDEV_DBG(netdev, "Unknown event %ld " 1886 FCOE_NETDEV_DBG(netdev, "Unknown event %ld "
1839 "from netdev netlink\n", event); 1887 "from netdev netlink\n", event);
@@ -1918,8 +1966,8 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp)
1918 rtnl_unlock(); 1966 rtnl_unlock();
1919 1967
1920 if (fcoe) { 1968 if (fcoe) {
1921 fc_fabric_logoff(fcoe->ctlr.lp);
1922 fcoe_ctlr_link_down(&fcoe->ctlr); 1969 fcoe_ctlr_link_down(&fcoe->ctlr);
1970 fcoe_clean_pending_queue(fcoe->ctlr.lp);
1923 } else 1971 } else
1924 rc = -ENODEV; 1972 rc = -ENODEV;
1925 1973
@@ -1972,12 +2020,10 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp)
1972 fcoe = fcoe_hostlist_lookup_port(netdev); 2020 fcoe = fcoe_hostlist_lookup_port(netdev);
1973 rtnl_unlock(); 2021 rtnl_unlock();
1974 2022
1975 if (fcoe) { 2023 if (!fcoe)
1976 if (!fcoe_link_ok(fcoe->ctlr.lp))
1977 fcoe_ctlr_link_up(&fcoe->ctlr);
1978 rc = fc_fabric_login(fcoe->ctlr.lp);
1979 } else
1980 rc = -ENODEV; 2024 rc = -ENODEV;
2025 else if (!fcoe_link_ok(fcoe->ctlr.lp))
2026 fcoe_ctlr_link_up(&fcoe->ctlr);
1981 2027
1982 dev_put(netdev); 2028 dev_put(netdev);
1983out_nodev: 2029out_nodev:
@@ -2031,8 +2077,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
2031 rc = -ENODEV; 2077 rc = -ENODEV;
2032 goto out_putdev; 2078 goto out_putdev;
2033 } 2079 }
2034 list_del(&fcoe->list);
2035 fcoe_interface_cleanup(fcoe); 2080 fcoe_interface_cleanup(fcoe);
2081 list_del(&fcoe->list);
2036 /* RTNL mutex is dropped by fcoe_if_destroy */ 2082 /* RTNL mutex is dropped by fcoe_if_destroy */
2037 fcoe_if_destroy(fcoe->ctlr.lp); 2083 fcoe_if_destroy(fcoe->ctlr.lp);
2038 2084
@@ -2070,6 +2116,7 @@ static void fcoe_destroy_work(struct work_struct *work)
2070 */ 2116 */
2071static int fcoe_create(const char *buffer, struct kernel_param *kp) 2117static int fcoe_create(const char *buffer, struct kernel_param *kp)
2072{ 2118{
2119 enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
2073 int rc; 2120 int rc;
2074 struct fcoe_interface *fcoe; 2121 struct fcoe_interface *fcoe;
2075 struct fc_lport *lport; 2122 struct fc_lport *lport;
@@ -2111,7 +2158,7 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
2111 goto out_putdev; 2158 goto out_putdev;
2112 } 2159 }
2113 2160
2114 fcoe = fcoe_interface_create(netdev); 2161 fcoe = fcoe_interface_create(netdev, fip_mode);
2115 if (!fcoe) { 2162 if (!fcoe) {
2116 rc = -ENOMEM; 2163 rc = -ENOMEM;
2117 goto out_putdev; 2164 goto out_putdev;
@@ -2521,6 +2568,8 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did,
2521 switch (op) { 2568 switch (op) {
2522 case ELS_FLOGI: 2569 case ELS_FLOGI:
2523 case ELS_FDISC: 2570 case ELS_FDISC:
2571 if (lport->point_to_multipoint)
2572 break;
2524 return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp, 2573 return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp,
2525 fip, timeout); 2574 fip, timeout);
2526 case ELS_LOGO: 2575 case ELS_LOGO: