diff options
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 200 |
1 files changed, 148 insertions, 52 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 76e3d0b5bfa6..fe30b1b65e1d 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | #include <scsi/fc/fc_encaps.h> | 42 | #include <scsi/fc/fc_encaps.h> |
43 | #include <scsi/fc/fc_fip.h> | 43 | #include <scsi/fc/fc_fip.h> |
44 | #include <scsi/fc/fc_fcoe.h> | ||
44 | 45 | ||
45 | #include <scsi/libfc.h> | 46 | #include <scsi/libfc.h> |
46 | #include <scsi/fc_frame.h> | 47 | #include <scsi/fc_frame.h> |
@@ -150,6 +151,21 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled); | |||
150 | static int fcoe_vport_disable(struct fc_vport *, bool disable); | 151 | static int fcoe_vport_disable(struct fc_vport *, bool disable); |
151 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); | 152 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); |
152 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); | 153 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); |
154 | static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *); | ||
155 | static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *); | ||
156 | |||
157 | static struct fcoe_sysfs_function_template fcoe_sysfs_templ = { | ||
158 | .get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode, | ||
159 | .get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb, | ||
160 | .get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb, | ||
161 | .get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb, | ||
162 | .get_fcoe_ctlr_symb_err = fcoe_ctlr_get_lesb, | ||
163 | .get_fcoe_ctlr_err_block = fcoe_ctlr_get_lesb, | ||
164 | .get_fcoe_ctlr_fcs_error = fcoe_ctlr_get_lesb, | ||
165 | |||
166 | .get_fcoe_fcf_selected = fcoe_fcf_get_selected, | ||
167 | .get_fcoe_fcf_vlan_id = fcoe_fcf_get_vlan_id, | ||
168 | }; | ||
153 | 169 | ||
154 | static struct libfc_function_template fcoe_libfc_fcn_templ = { | 170 | static struct libfc_function_template fcoe_libfc_fcn_templ = { |
155 | .frame_send = fcoe_xmit, | 171 | .frame_send = fcoe_xmit, |
@@ -282,7 +298,7 @@ static struct scsi_host_template fcoe_shost_template = { | |||
282 | static int fcoe_interface_setup(struct fcoe_interface *fcoe, | 298 | static int fcoe_interface_setup(struct fcoe_interface *fcoe, |
283 | struct net_device *netdev) | 299 | struct net_device *netdev) |
284 | { | 300 | { |
285 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 301 | struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); |
286 | struct netdev_hw_addr *ha; | 302 | struct netdev_hw_addr *ha; |
287 | struct net_device *real_dev; | 303 | struct net_device *real_dev; |
288 | u8 flogi_maddr[ETH_ALEN]; | 304 | u8 flogi_maddr[ETH_ALEN]; |
@@ -366,7 +382,10 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, | |||
366 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | 382 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, |
367 | enum fip_state fip_mode) | 383 | enum fip_state fip_mode) |
368 | { | 384 | { |
385 | struct fcoe_ctlr_device *ctlr_dev; | ||
386 | struct fcoe_ctlr *ctlr; | ||
369 | struct fcoe_interface *fcoe; | 387 | struct fcoe_interface *fcoe; |
388 | int size; | ||
370 | int err; | 389 | int err; |
371 | 390 | ||
372 | if (!try_module_get(THIS_MODULE)) { | 391 | if (!try_module_get(THIS_MODULE)) { |
@@ -376,27 +395,32 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | |||
376 | goto out; | 395 | goto out; |
377 | } | 396 | } |
378 | 397 | ||
379 | fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); | 398 | size = sizeof(struct fcoe_ctlr) + sizeof(struct fcoe_interface); |
380 | if (!fcoe) { | 399 | ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &fcoe_sysfs_templ, |
381 | FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); | 400 | size); |
401 | if (!ctlr_dev) { | ||
402 | FCOE_DBG("Failed to add fcoe_ctlr_device\n"); | ||
382 | fcoe = ERR_PTR(-ENOMEM); | 403 | fcoe = ERR_PTR(-ENOMEM); |
383 | goto out_putmod; | 404 | goto out_putmod; |
384 | } | 405 | } |
385 | 406 | ||
407 | ctlr = fcoe_ctlr_device_priv(ctlr_dev); | ||
408 | fcoe = fcoe_ctlr_priv(ctlr); | ||
409 | |||
386 | dev_hold(netdev); | 410 | dev_hold(netdev); |
387 | 411 | ||
388 | /* | 412 | /* |
389 | * Initialize FIP. | 413 | * Initialize FIP. |
390 | */ | 414 | */ |
391 | fcoe_ctlr_init(&fcoe->ctlr, fip_mode); | 415 | fcoe_ctlr_init(ctlr, fip_mode); |
392 | fcoe->ctlr.send = fcoe_fip_send; | 416 | ctlr->send = fcoe_fip_send; |
393 | fcoe->ctlr.update_mac = fcoe_update_src_mac; | 417 | ctlr->update_mac = fcoe_update_src_mac; |
394 | fcoe->ctlr.get_src_addr = fcoe_get_src_mac; | 418 | ctlr->get_src_addr = fcoe_get_src_mac; |
395 | 419 | ||
396 | err = fcoe_interface_setup(fcoe, netdev); | 420 | err = fcoe_interface_setup(fcoe, netdev); |
397 | if (err) { | 421 | if (err) { |
398 | fcoe_ctlr_destroy(&fcoe->ctlr); | 422 | fcoe_ctlr_destroy(ctlr); |
399 | kfree(fcoe); | 423 | fcoe_ctlr_device_delete(ctlr_dev); |
400 | dev_put(netdev); | 424 | dev_put(netdev); |
401 | fcoe = ERR_PTR(err); | 425 | fcoe = ERR_PTR(err); |
402 | goto out_putmod; | 426 | goto out_putmod; |
@@ -419,7 +443,7 @@ out: | |||
419 | static void fcoe_interface_remove(struct fcoe_interface *fcoe) | 443 | static void fcoe_interface_remove(struct fcoe_interface *fcoe) |
420 | { | 444 | { |
421 | struct net_device *netdev = fcoe->netdev; | 445 | struct net_device *netdev = fcoe->netdev; |
422 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 446 | struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); |
423 | u8 flogi_maddr[ETH_ALEN]; | 447 | u8 flogi_maddr[ETH_ALEN]; |
424 | const struct net_device_ops *ops; | 448 | const struct net_device_ops *ops; |
425 | 449 | ||
@@ -462,7 +486,8 @@ static void fcoe_interface_remove(struct fcoe_interface *fcoe) | |||
462 | static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | 486 | static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) |
463 | { | 487 | { |
464 | struct net_device *netdev = fcoe->netdev; | 488 | struct net_device *netdev = fcoe->netdev; |
465 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 489 | struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); |
490 | struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); | ||
466 | 491 | ||
467 | rtnl_lock(); | 492 | rtnl_lock(); |
468 | if (!fcoe->removed) | 493 | if (!fcoe->removed) |
@@ -472,8 +497,8 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | |||
472 | /* Release the self-reference taken during fcoe_interface_create() */ | 497 | /* Release the self-reference taken during fcoe_interface_create() */ |
473 | /* tear-down the FCoE controller */ | 498 | /* tear-down the FCoE controller */ |
474 | fcoe_ctlr_destroy(fip); | 499 | fcoe_ctlr_destroy(fip); |
475 | scsi_host_put(fcoe->ctlr.lp->host); | 500 | scsi_host_put(fip->lp->host); |
476 | kfree(fcoe); | 501 | fcoe_ctlr_device_delete(ctlr_dev); |
477 | dev_put(netdev); | 502 | dev_put(netdev); |
478 | module_put(THIS_MODULE); | 503 | module_put(THIS_MODULE); |
479 | } | 504 | } |
@@ -493,9 +518,11 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev, | |||
493 | struct net_device *orig_dev) | 518 | struct net_device *orig_dev) |
494 | { | 519 | { |
495 | struct fcoe_interface *fcoe; | 520 | struct fcoe_interface *fcoe; |
521 | struct fcoe_ctlr *ctlr; | ||
496 | 522 | ||
497 | fcoe = container_of(ptype, struct fcoe_interface, fip_packet_type); | 523 | fcoe = container_of(ptype, struct fcoe_interface, fip_packet_type); |
498 | fcoe_ctlr_recv(&fcoe->ctlr, skb); | 524 | ctlr = fcoe_to_ctlr(fcoe); |
525 | fcoe_ctlr_recv(ctlr, skb); | ||
499 | return 0; | 526 | return 0; |
500 | } | 527 | } |
501 | 528 | ||
@@ -645,11 +672,13 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) | |||
645 | u32 mfs; | 672 | u32 mfs; |
646 | u64 wwnn, wwpn; | 673 | u64 wwnn, wwpn; |
647 | struct fcoe_interface *fcoe; | 674 | struct fcoe_interface *fcoe; |
675 | struct fcoe_ctlr *ctlr; | ||
648 | struct fcoe_port *port; | 676 | struct fcoe_port *port; |
649 | 677 | ||
650 | /* Setup lport private data to point to fcoe softc */ | 678 | /* Setup lport private data to point to fcoe softc */ |
651 | port = lport_priv(lport); | 679 | port = lport_priv(lport); |
652 | fcoe = port->priv; | 680 | fcoe = port->priv; |
681 | ctlr = fcoe_to_ctlr(fcoe); | ||
653 | 682 | ||
654 | /* | 683 | /* |
655 | * Determine max frame size based on underlying device and optional | 684 | * Determine max frame size based on underlying device and optional |
@@ -676,10 +705,10 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) | |||
676 | 705 | ||
677 | if (!lport->vport) { | 706 | if (!lport->vport) { |
678 | if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) | 707 | if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) |
679 | wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0); | 708 | wwnn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, 1, 0); |
680 | fc_set_wwnn(lport, wwnn); | 709 | fc_set_wwnn(lport, wwnn); |
681 | if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) | 710 | if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) |
682 | wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, | 711 | wwpn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, |
683 | 2, 0); | 712 | 2, 0); |
684 | fc_set_wwpn(lport, wwpn); | 713 | fc_set_wwpn(lport, wwpn); |
685 | } | 714 | } |
@@ -1056,6 +1085,7 @@ static int fcoe_ddp_done(struct fc_lport *lport, u16 xid) | |||
1056 | static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | 1085 | static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, |
1057 | struct device *parent, int npiv) | 1086 | struct device *parent, int npiv) |
1058 | { | 1087 | { |
1088 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); | ||
1059 | struct net_device *netdev = fcoe->netdev; | 1089 | struct net_device *netdev = fcoe->netdev; |
1060 | struct fc_lport *lport, *n_port; | 1090 | struct fc_lport *lport, *n_port; |
1061 | struct fcoe_port *port; | 1091 | struct fcoe_port *port; |
@@ -1119,7 +1149,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
1119 | } | 1149 | } |
1120 | 1150 | ||
1121 | /* Initialize the library */ | 1151 | /* Initialize the library */ |
1122 | rc = fcoe_libfc_config(lport, &fcoe->ctlr, &fcoe_libfc_fcn_templ, 1); | 1152 | rc = fcoe_libfc_config(lport, ctlr, &fcoe_libfc_fcn_templ, 1); |
1123 | if (rc) { | 1153 | if (rc) { |
1124 | FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " | 1154 | FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " |
1125 | "interface\n"); | 1155 | "interface\n"); |
@@ -1386,6 +1416,7 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, | |||
1386 | { | 1416 | { |
1387 | struct fc_lport *lport; | 1417 | struct fc_lport *lport; |
1388 | struct fcoe_rcv_info *fr; | 1418 | struct fcoe_rcv_info *fr; |
1419 | struct fcoe_ctlr *ctlr; | ||
1389 | struct fcoe_interface *fcoe; | 1420 | struct fcoe_interface *fcoe; |
1390 | struct fc_frame_header *fh; | 1421 | struct fc_frame_header *fh; |
1391 | struct fcoe_percpu_s *fps; | 1422 | struct fcoe_percpu_s *fps; |
@@ -1393,7 +1424,8 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, | |||
1393 | unsigned int cpu; | 1424 | unsigned int cpu; |
1394 | 1425 | ||
1395 | fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); | 1426 | fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); |
1396 | lport = fcoe->ctlr.lp; | 1427 | ctlr = fcoe_to_ctlr(fcoe); |
1428 | lport = ctlr->lp; | ||
1397 | if (unlikely(!lport)) { | 1429 | if (unlikely(!lport)) { |
1398 | FCOE_NETDEV_DBG(netdev, "Cannot find hba structure"); | 1430 | FCOE_NETDEV_DBG(netdev, "Cannot find hba structure"); |
1399 | goto err2; | 1431 | goto err2; |
@@ -1409,8 +1441,8 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, | |||
1409 | 1441 | ||
1410 | eh = eth_hdr(skb); | 1442 | eh = eth_hdr(skb); |
1411 | 1443 | ||
1412 | if (is_fip_mode(&fcoe->ctlr) && | 1444 | if (is_fip_mode(ctlr) && |
1413 | compare_ether_addr(eh->h_source, fcoe->ctlr.dest_addr)) { | 1445 | compare_ether_addr(eh->h_source, ctlr->dest_addr)) { |
1414 | FCOE_NETDEV_DBG(netdev, "wrong source mac address:%pM\n", | 1446 | FCOE_NETDEV_DBG(netdev, "wrong source mac address:%pM\n", |
1415 | eh->h_source); | 1447 | eh->h_source); |
1416 | goto err; | 1448 | goto err; |
@@ -1544,6 +1576,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1544 | unsigned int elen; /* eth header, may include vlan */ | 1576 | unsigned int elen; /* eth header, may include vlan */ |
1545 | struct fcoe_port *port = lport_priv(lport); | 1577 | struct fcoe_port *port = lport_priv(lport); |
1546 | struct fcoe_interface *fcoe = port->priv; | 1578 | struct fcoe_interface *fcoe = port->priv; |
1579 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); | ||
1547 | u8 sof, eof; | 1580 | u8 sof, eof; |
1548 | struct fcoe_hdr *hp; | 1581 | struct fcoe_hdr *hp; |
1549 | 1582 | ||
@@ -1559,7 +1592,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1559 | } | 1592 | } |
1560 | 1593 | ||
1561 | if (unlikely(fh->fh_type == FC_TYPE_ELS) && | 1594 | if (unlikely(fh->fh_type == FC_TYPE_ELS) && |
1562 | fcoe_ctlr_els_send(&fcoe->ctlr, lport, skb)) | 1595 | fcoe_ctlr_els_send(ctlr, lport, skb)) |
1563 | return 0; | 1596 | return 0; |
1564 | 1597 | ||
1565 | sof = fr_sof(fp); | 1598 | sof = fr_sof(fp); |
@@ -1623,12 +1656,12 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1623 | /* fill up mac and fcoe headers */ | 1656 | /* fill up mac and fcoe headers */ |
1624 | eh = eth_hdr(skb); | 1657 | eh = eth_hdr(skb); |
1625 | eh->h_proto = htons(ETH_P_FCOE); | 1658 | eh->h_proto = htons(ETH_P_FCOE); |
1626 | memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN); | 1659 | memcpy(eh->h_dest, ctlr->dest_addr, ETH_ALEN); |
1627 | if (fcoe->ctlr.map_dest) | 1660 | if (ctlr->map_dest) |
1628 | memcpy(eh->h_dest + 3, fh->fh_d_id, 3); | 1661 | memcpy(eh->h_dest + 3, fh->fh_d_id, 3); |
1629 | 1662 | ||
1630 | if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) | 1663 | if (unlikely(ctlr->flogi_oxid != FC_XID_UNKNOWN)) |
1631 | memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); | 1664 | memcpy(eh->h_source, ctlr->ctl_src_addr, ETH_ALEN); |
1632 | else | 1665 | else |
1633 | memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); | 1666 | memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); |
1634 | 1667 | ||
@@ -1677,6 +1710,7 @@ static void fcoe_percpu_flush_done(struct sk_buff *skb) | |||
1677 | static inline int fcoe_filter_frames(struct fc_lport *lport, | 1710 | static inline int fcoe_filter_frames(struct fc_lport *lport, |
1678 | struct fc_frame *fp) | 1711 | struct fc_frame *fp) |
1679 | { | 1712 | { |
1713 | struct fcoe_ctlr *ctlr; | ||
1680 | struct fcoe_interface *fcoe; | 1714 | struct fcoe_interface *fcoe; |
1681 | struct fc_frame_header *fh; | 1715 | struct fc_frame_header *fh; |
1682 | struct sk_buff *skb = (struct sk_buff *)fp; | 1716 | struct sk_buff *skb = (struct sk_buff *)fp; |
@@ -1698,7 +1732,8 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, | |||
1698 | return 0; | 1732 | return 0; |
1699 | 1733 | ||
1700 | fcoe = ((struct fcoe_port *)lport_priv(lport))->priv; | 1734 | fcoe = ((struct fcoe_port *)lport_priv(lport))->priv; |
1701 | if (is_fip_mode(&fcoe->ctlr) && fc_frame_payload_op(fp) == ELS_LOGO && | 1735 | ctlr = fcoe_to_ctlr(fcoe); |
1736 | if (is_fip_mode(ctlr) && fc_frame_payload_op(fp) == ELS_LOGO && | ||
1702 | ntoh24(fh->fh_s_id) == FC_FID_FLOGI) { | 1737 | ntoh24(fh->fh_s_id) == FC_FID_FLOGI) { |
1703 | FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n"); | 1738 | FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n"); |
1704 | return -EINVAL; | 1739 | return -EINVAL; |
@@ -1877,6 +1912,7 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier, | |||
1877 | ulong event, void *ptr) | 1912 | ulong event, void *ptr) |
1878 | { | 1913 | { |
1879 | struct dcb_app_type *entry = ptr; | 1914 | struct dcb_app_type *entry = ptr; |
1915 | struct fcoe_ctlr *ctlr; | ||
1880 | struct fcoe_interface *fcoe; | 1916 | struct fcoe_interface *fcoe; |
1881 | struct net_device *netdev; | 1917 | struct net_device *netdev; |
1882 | struct fcoe_port *port; | 1918 | struct fcoe_port *port; |
@@ -1894,6 +1930,8 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier, | |||
1894 | if (!fcoe) | 1930 | if (!fcoe) |
1895 | return NOTIFY_OK; | 1931 | return NOTIFY_OK; |
1896 | 1932 | ||
1933 | ctlr = fcoe_to_ctlr(fcoe); | ||
1934 | |||
1897 | if (entry->dcbx & DCB_CAP_DCBX_VER_CEE) | 1935 | if (entry->dcbx & DCB_CAP_DCBX_VER_CEE) |
1898 | prio = ffs(entry->app.priority) - 1; | 1936 | prio = ffs(entry->app.priority) - 1; |
1899 | else | 1937 | else |
@@ -1904,10 +1942,10 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier, | |||
1904 | 1942 | ||
1905 | if (entry->app.protocol == ETH_P_FIP || | 1943 | if (entry->app.protocol == ETH_P_FIP || |
1906 | entry->app.protocol == ETH_P_FCOE) | 1944 | entry->app.protocol == ETH_P_FCOE) |
1907 | fcoe->ctlr.priority = prio; | 1945 | ctlr->priority = prio; |
1908 | 1946 | ||
1909 | if (entry->app.protocol == ETH_P_FCOE) { | 1947 | if (entry->app.protocol == ETH_P_FCOE) { |
1910 | port = lport_priv(fcoe->ctlr.lp); | 1948 | port = lport_priv(ctlr->lp); |
1911 | port->priority = prio; | 1949 | port->priority = prio; |
1912 | } | 1950 | } |
1913 | 1951 | ||
@@ -1929,6 +1967,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1929 | { | 1967 | { |
1930 | struct fc_lport *lport = NULL; | 1968 | struct fc_lport *lport = NULL; |
1931 | struct net_device *netdev = ptr; | 1969 | struct net_device *netdev = ptr; |
1970 | struct fcoe_ctlr *ctlr; | ||
1932 | struct fcoe_interface *fcoe; | 1971 | struct fcoe_interface *fcoe; |
1933 | struct fcoe_port *port; | 1972 | struct fcoe_port *port; |
1934 | struct fcoe_dev_stats *stats; | 1973 | struct fcoe_dev_stats *stats; |
@@ -1938,7 +1977,8 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1938 | 1977 | ||
1939 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { | 1978 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { |
1940 | if (fcoe->netdev == netdev) { | 1979 | if (fcoe->netdev == netdev) { |
1941 | lport = fcoe->ctlr.lp; | 1980 | ctlr = fcoe_to_ctlr(fcoe); |
1981 | lport = ctlr->lp; | ||
1942 | break; | 1982 | break; |
1943 | } | 1983 | } |
1944 | } | 1984 | } |
@@ -1967,7 +2007,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1967 | break; | 2007 | break; |
1968 | case NETDEV_UNREGISTER: | 2008 | case NETDEV_UNREGISTER: |
1969 | list_del(&fcoe->list); | 2009 | list_del(&fcoe->list); |
1970 | port = lport_priv(fcoe->ctlr.lp); | 2010 | port = lport_priv(ctlr->lp); |
1971 | queue_work(fcoe_wq, &port->destroy_work); | 2011 | queue_work(fcoe_wq, &port->destroy_work); |
1972 | goto out; | 2012 | goto out; |
1973 | break; | 2013 | break; |
@@ -1982,8 +2022,8 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1982 | fcoe_link_speed_update(lport); | 2022 | fcoe_link_speed_update(lport); |
1983 | 2023 | ||
1984 | if (link_possible && !fcoe_link_ok(lport)) | 2024 | if (link_possible && !fcoe_link_ok(lport)) |
1985 | fcoe_ctlr_link_up(&fcoe->ctlr); | 2025 | fcoe_ctlr_link_up(ctlr); |
1986 | else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { | 2026 | else if (fcoe_ctlr_link_down(ctlr)) { |
1987 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); | 2027 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); |
1988 | stats->LinkFailureCount++; | 2028 | stats->LinkFailureCount++; |
1989 | put_cpu(); | 2029 | put_cpu(); |
@@ -2003,6 +2043,7 @@ out: | |||
2003 | */ | 2043 | */ |
2004 | static int fcoe_disable(struct net_device *netdev) | 2044 | static int fcoe_disable(struct net_device *netdev) |
2005 | { | 2045 | { |
2046 | struct fcoe_ctlr *ctlr; | ||
2006 | struct fcoe_interface *fcoe; | 2047 | struct fcoe_interface *fcoe; |
2007 | int rc = 0; | 2048 | int rc = 0; |
2008 | 2049 | ||
@@ -2013,8 +2054,9 @@ static int fcoe_disable(struct net_device *netdev) | |||
2013 | rtnl_unlock(); | 2054 | rtnl_unlock(); |
2014 | 2055 | ||
2015 | if (fcoe) { | 2056 | if (fcoe) { |
2016 | fcoe_ctlr_link_down(&fcoe->ctlr); | 2057 | ctlr = fcoe_to_ctlr(fcoe); |
2017 | fcoe_clean_pending_queue(fcoe->ctlr.lp); | 2058 | fcoe_ctlr_link_down(ctlr); |
2059 | fcoe_clean_pending_queue(ctlr->lp); | ||
2018 | } else | 2060 | } else |
2019 | rc = -ENODEV; | 2061 | rc = -ENODEV; |
2020 | 2062 | ||
@@ -2032,6 +2074,7 @@ static int fcoe_disable(struct net_device *netdev) | |||
2032 | */ | 2074 | */ |
2033 | static int fcoe_enable(struct net_device *netdev) | 2075 | static int fcoe_enable(struct net_device *netdev) |
2034 | { | 2076 | { |
2077 | struct fcoe_ctlr *ctlr; | ||
2035 | struct fcoe_interface *fcoe; | 2078 | struct fcoe_interface *fcoe; |
2036 | int rc = 0; | 2079 | int rc = 0; |
2037 | 2080 | ||
@@ -2040,11 +2083,17 @@ static int fcoe_enable(struct net_device *netdev) | |||
2040 | fcoe = fcoe_hostlist_lookup_port(netdev); | 2083 | fcoe = fcoe_hostlist_lookup_port(netdev); |
2041 | rtnl_unlock(); | 2084 | rtnl_unlock(); |
2042 | 2085 | ||
2043 | if (!fcoe) | 2086 | if (!fcoe) { |
2044 | rc = -ENODEV; | 2087 | rc = -ENODEV; |
2045 | else if (!fcoe_link_ok(fcoe->ctlr.lp)) | 2088 | goto out; |
2046 | fcoe_ctlr_link_up(&fcoe->ctlr); | 2089 | } |
2090 | |||
2091 | ctlr = fcoe_to_ctlr(fcoe); | ||
2092 | |||
2093 | if (!fcoe_link_ok(ctlr->lp)) | ||
2094 | fcoe_ctlr_link_up(ctlr); | ||
2047 | 2095 | ||
2096 | out: | ||
2048 | mutex_unlock(&fcoe_config_mutex); | 2097 | mutex_unlock(&fcoe_config_mutex); |
2049 | return rc; | 2098 | return rc; |
2050 | } | 2099 | } |
@@ -2059,6 +2108,7 @@ static int fcoe_enable(struct net_device *netdev) | |||
2059 | */ | 2108 | */ |
2060 | static int fcoe_destroy(struct net_device *netdev) | 2109 | static int fcoe_destroy(struct net_device *netdev) |
2061 | { | 2110 | { |
2111 | struct fcoe_ctlr *ctlr; | ||
2062 | struct fcoe_interface *fcoe; | 2112 | struct fcoe_interface *fcoe; |
2063 | struct fc_lport *lport; | 2113 | struct fc_lport *lport; |
2064 | struct fcoe_port *port; | 2114 | struct fcoe_port *port; |
@@ -2071,7 +2121,8 @@ static int fcoe_destroy(struct net_device *netdev) | |||
2071 | rc = -ENODEV; | 2121 | rc = -ENODEV; |
2072 | goto out_nodev; | 2122 | goto out_nodev; |
2073 | } | 2123 | } |
2074 | lport = fcoe->ctlr.lp; | 2124 | ctlr = fcoe_to_ctlr(fcoe); |
2125 | lport = ctlr->lp; | ||
2075 | port = lport_priv(lport); | 2126 | port = lport_priv(lport); |
2076 | list_del(&fcoe->list); | 2127 | list_del(&fcoe->list); |
2077 | queue_work(fcoe_wq, &port->destroy_work); | 2128 | queue_work(fcoe_wq, &port->destroy_work); |
@@ -2126,7 +2177,8 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) | |||
2126 | int dcbx; | 2177 | int dcbx; |
2127 | u8 fup, up; | 2178 | u8 fup, up; |
2128 | struct net_device *netdev = fcoe->realdev; | 2179 | struct net_device *netdev = fcoe->realdev; |
2129 | struct fcoe_port *port = lport_priv(fcoe->ctlr.lp); | 2180 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); |
2181 | struct fcoe_port *port = lport_priv(ctlr->lp); | ||
2130 | struct dcb_app app = { | 2182 | struct dcb_app app = { |
2131 | .priority = 0, | 2183 | .priority = 0, |
2132 | .protocol = ETH_P_FCOE | 2184 | .protocol = ETH_P_FCOE |
@@ -2149,7 +2201,7 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) | |||
2149 | } | 2201 | } |
2150 | 2202 | ||
2151 | port->priority = ffs(up) ? ffs(up) - 1 : 0; | 2203 | port->priority = ffs(up) ? ffs(up) - 1 : 0; |
2152 | fcoe->ctlr.priority = ffs(fup) ? ffs(fup) - 1 : port->priority; | 2204 | ctlr->priority = ffs(fup) ? ffs(fup) - 1 : port->priority; |
2153 | } | 2205 | } |
2154 | #endif | 2206 | #endif |
2155 | } | 2207 | } |
@@ -2166,6 +2218,8 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) | |||
2166 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | 2218 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) |
2167 | { | 2219 | { |
2168 | int rc = 0; | 2220 | int rc = 0; |
2221 | struct fcoe_ctlr_device *ctlr_dev; | ||
2222 | struct fcoe_ctlr *ctlr; | ||
2169 | struct fcoe_interface *fcoe; | 2223 | struct fcoe_interface *fcoe; |
2170 | struct fc_lport *lport; | 2224 | struct fc_lport *lport; |
2171 | 2225 | ||
@@ -2184,7 +2238,9 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2184 | goto out_nodev; | 2238 | goto out_nodev; |
2185 | } | 2239 | } |
2186 | 2240 | ||
2187 | lport = fcoe_if_create(fcoe, &netdev->dev, 0); | 2241 | ctlr = fcoe_to_ctlr(fcoe); |
2242 | ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr); | ||
2243 | lport = fcoe_if_create(fcoe, &ctlr_dev->dev, 0); | ||
2188 | if (IS_ERR(lport)) { | 2244 | if (IS_ERR(lport)) { |
2189 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", | 2245 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", |
2190 | netdev->name); | 2246 | netdev->name); |
@@ -2195,7 +2251,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2195 | } | 2251 | } |
2196 | 2252 | ||
2197 | /* Make this the "master" N_Port */ | 2253 | /* Make this the "master" N_Port */ |
2198 | fcoe->ctlr.lp = lport; | 2254 | ctlr->lp = lport; |
2199 | 2255 | ||
2200 | /* setup DCB priority attributes. */ | 2256 | /* setup DCB priority attributes. */ |
2201 | fcoe_dcb_create(fcoe); | 2257 | fcoe_dcb_create(fcoe); |
@@ -2208,7 +2264,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2208 | fc_fabric_login(lport); | 2264 | fc_fabric_login(lport); |
2209 | if (!fcoe_link_ok(lport)) { | 2265 | if (!fcoe_link_ok(lport)) { |
2210 | rtnl_unlock(); | 2266 | rtnl_unlock(); |
2211 | fcoe_ctlr_link_up(&fcoe->ctlr); | 2267 | fcoe_ctlr_link_up(ctlr); |
2212 | mutex_unlock(&fcoe_config_mutex); | 2268 | mutex_unlock(&fcoe_config_mutex); |
2213 | return rc; | 2269 | return rc; |
2214 | } | 2270 | } |
@@ -2320,11 +2376,12 @@ static int fcoe_reset(struct Scsi_Host *shost) | |||
2320 | struct fc_lport *lport = shost_priv(shost); | 2376 | struct fc_lport *lport = shost_priv(shost); |
2321 | struct fcoe_port *port = lport_priv(lport); | 2377 | struct fcoe_port *port = lport_priv(lport); |
2322 | struct fcoe_interface *fcoe = port->priv; | 2378 | struct fcoe_interface *fcoe = port->priv; |
2379 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); | ||
2323 | 2380 | ||
2324 | fcoe_ctlr_link_down(&fcoe->ctlr); | 2381 | fcoe_ctlr_link_down(ctlr); |
2325 | fcoe_clean_pending_queue(fcoe->ctlr.lp); | 2382 | fcoe_clean_pending_queue(ctlr->lp); |
2326 | if (!fcoe_link_ok(fcoe->ctlr.lp)) | 2383 | if (!fcoe_link_ok(ctlr->lp)) |
2327 | fcoe_ctlr_link_up(&fcoe->ctlr); | 2384 | fcoe_ctlr_link_up(ctlr); |
2328 | return 0; | 2385 | return 0; |
2329 | } | 2386 | } |
2330 | 2387 | ||
@@ -2359,10 +2416,12 @@ fcoe_hostlist_lookup_port(const struct net_device *netdev) | |||
2359 | */ | 2416 | */ |
2360 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) | 2417 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) |
2361 | { | 2418 | { |
2419 | struct fcoe_ctlr *ctlr; | ||
2362 | struct fcoe_interface *fcoe; | 2420 | struct fcoe_interface *fcoe; |
2363 | 2421 | ||
2364 | fcoe = fcoe_hostlist_lookup_port(netdev); | 2422 | fcoe = fcoe_hostlist_lookup_port(netdev); |
2365 | return (fcoe) ? fcoe->ctlr.lp : NULL; | 2423 | ctlr = fcoe_to_ctlr(fcoe); |
2424 | return (fcoe) ? ctlr->lp : NULL; | ||
2366 | } | 2425 | } |
2367 | 2426 | ||
2368 | /** | 2427 | /** |
@@ -2466,6 +2525,7 @@ module_init(fcoe_init); | |||
2466 | static void __exit fcoe_exit(void) | 2525 | static void __exit fcoe_exit(void) |
2467 | { | 2526 | { |
2468 | struct fcoe_interface *fcoe, *tmp; | 2527 | struct fcoe_interface *fcoe, *tmp; |
2528 | struct fcoe_ctlr *ctlr; | ||
2469 | struct fcoe_port *port; | 2529 | struct fcoe_port *port; |
2470 | unsigned int cpu; | 2530 | unsigned int cpu; |
2471 | 2531 | ||
@@ -2477,7 +2537,8 @@ static void __exit fcoe_exit(void) | |||
2477 | rtnl_lock(); | 2537 | rtnl_lock(); |
2478 | list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) { | 2538 | list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) { |
2479 | list_del(&fcoe->list); | 2539 | list_del(&fcoe->list); |
2480 | port = lport_priv(fcoe->ctlr.lp); | 2540 | ctlr = fcoe_to_ctlr(fcoe); |
2541 | port = lport_priv(ctlr->lp); | ||
2481 | queue_work(fcoe_wq, &port->destroy_work); | 2542 | queue_work(fcoe_wq, &port->destroy_work); |
2482 | } | 2543 | } |
2483 | rtnl_unlock(); | 2544 | rtnl_unlock(); |
@@ -2573,7 +2634,7 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did, | |||
2573 | { | 2634 | { |
2574 | struct fcoe_port *port = lport_priv(lport); | 2635 | struct fcoe_port *port = lport_priv(lport); |
2575 | struct fcoe_interface *fcoe = port->priv; | 2636 | struct fcoe_interface *fcoe = port->priv; |
2576 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 2637 | struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); |
2577 | struct fc_frame_header *fh = fc_frame_header_get(fp); | 2638 | struct fc_frame_header *fh = fc_frame_header_get(fp); |
2578 | 2639 | ||
2579 | switch (op) { | 2640 | switch (op) { |
@@ -2730,6 +2791,40 @@ static void fcoe_get_lesb(struct fc_lport *lport, | |||
2730 | __fcoe_get_lesb(lport, fc_lesb, netdev); | 2791 | __fcoe_get_lesb(lport, fc_lesb, netdev); |
2731 | } | 2792 | } |
2732 | 2793 | ||
2794 | static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev) | ||
2795 | { | ||
2796 | struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); | ||
2797 | struct net_device *netdev = fcoe_netdev(fip->lp); | ||
2798 | struct fcoe_fc_els_lesb *fcoe_lesb; | ||
2799 | struct fc_els_lesb fc_lesb; | ||
2800 | |||
2801 | __fcoe_get_lesb(fip->lp, &fc_lesb, netdev); | ||
2802 | fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb); | ||
2803 | |||
2804 | ctlr_dev->lesb.lesb_link_fail = | ||
2805 | ntohl(fcoe_lesb->lesb_link_fail); | ||
2806 | ctlr_dev->lesb.lesb_vlink_fail = | ||
2807 | ntohl(fcoe_lesb->lesb_vlink_fail); | ||
2808 | ctlr_dev->lesb.lesb_miss_fka = | ||
2809 | ntohl(fcoe_lesb->lesb_miss_fka); | ||
2810 | ctlr_dev->lesb.lesb_symb_err = | ||
2811 | ntohl(fcoe_lesb->lesb_symb_err); | ||
2812 | ctlr_dev->lesb.lesb_err_block = | ||
2813 | ntohl(fcoe_lesb->lesb_err_block); | ||
2814 | ctlr_dev->lesb.lesb_fcs_error = | ||
2815 | ntohl(fcoe_lesb->lesb_fcs_error); | ||
2816 | } | ||
2817 | |||
2818 | static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev) | ||
2819 | { | ||
2820 | struct fcoe_ctlr_device *ctlr_dev = | ||
2821 | fcoe_fcf_dev_to_ctlr_dev(fcf_dev); | ||
2822 | struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); | ||
2823 | struct fcoe_interface *fcoe = fcoe_ctlr_priv(ctlr); | ||
2824 | |||
2825 | fcf_dev->vlan_id = vlan_dev_vlan_id(fcoe->netdev); | ||
2826 | } | ||
2827 | |||
2733 | /** | 2828 | /** |
2734 | * fcoe_set_port_id() - Callback from libfc when Port_ID is set. | 2829 | * fcoe_set_port_id() - Callback from libfc when Port_ID is set. |
2735 | * @lport: the local port | 2830 | * @lport: the local port |
@@ -2747,7 +2842,8 @@ static void fcoe_set_port_id(struct fc_lport *lport, | |||
2747 | { | 2842 | { |
2748 | struct fcoe_port *port = lport_priv(lport); | 2843 | struct fcoe_port *port = lport_priv(lport); |
2749 | struct fcoe_interface *fcoe = port->priv; | 2844 | struct fcoe_interface *fcoe = port->priv; |
2845 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); | ||
2750 | 2846 | ||
2751 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) | 2847 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) |
2752 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); | 2848 | fcoe_ctlr_recv_flogi(ctlr, lport, fp); |
2753 | } | 2849 | } |