aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r--drivers/scsi/fcoe/fcoe.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index f3f440c955f..8d67467dd9c 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -31,6 +31,8 @@
31#include <linux/sysfs.h> 31#include <linux/sysfs.h>
32#include <linux/ctype.h> 32#include <linux/ctype.h>
33#include <linux/workqueue.h> 33#include <linux/workqueue.h>
34#include <net/dcbnl.h>
35#include <net/dcbevent.h>
34#include <scsi/scsi_tcq.h> 36#include <scsi/scsi_tcq.h>
35#include <scsi/scsicam.h> 37#include <scsi/scsicam.h>
36#include <scsi/scsi_transport.h> 38#include <scsi/scsi_transport.h>
@@ -101,6 +103,8 @@ static int fcoe_ddp_done(struct fc_lport *, u16);
101static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *, 103static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *,
102 unsigned int); 104 unsigned int);
103static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *); 105static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *);
106static int fcoe_dcb_app_notification(struct notifier_block *notifier,
107 ulong event, void *ptr);
104 108
105static bool fcoe_match(struct net_device *netdev); 109static bool fcoe_match(struct net_device *netdev);
106static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode); 110static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode);
@@ -129,6 +133,11 @@ static struct notifier_block fcoe_cpu_notifier = {
129 .notifier_call = fcoe_cpu_callback, 133 .notifier_call = fcoe_cpu_callback,
130}; 134};
131 135
136/* notification function for DCB events */
137static struct notifier_block dcb_notifier = {
138 .notifier_call = fcoe_dcb_app_notification,
139};
140
132static struct scsi_transport_template *fcoe_nport_scsi_transport; 141static struct scsi_transport_template *fcoe_nport_scsi_transport;
133static struct scsi_transport_template *fcoe_vport_scsi_transport; 142static struct scsi_transport_template *fcoe_vport_scsi_transport;
134 143
@@ -1522,6 +1531,8 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
1522 skb_reset_network_header(skb); 1531 skb_reset_network_header(skb);
1523 skb->mac_len = elen; 1532 skb->mac_len = elen;
1524 skb->protocol = htons(ETH_P_FCOE); 1533 skb->protocol = htons(ETH_P_FCOE);
1534 skb->priority = port->priority;
1535
1525 if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN && 1536 if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN &&
1526 fcoe->realdev->features & NETIF_F_HW_VLAN_TX) { 1537 fcoe->realdev->features & NETIF_F_HW_VLAN_TX) {
1527 skb->vlan_tci = VLAN_TAG_PRESENT | 1538 skb->vlan_tci = VLAN_TAG_PRESENT |
@@ -1747,6 +1758,7 @@ int fcoe_percpu_receive_thread(void *arg)
1747 */ 1758 */
1748static void fcoe_dev_setup(void) 1759static void fcoe_dev_setup(void)
1749{ 1760{
1761 register_dcbevent_notifier(&dcb_notifier);
1750 register_netdevice_notifier(&fcoe_notifier); 1762 register_netdevice_notifier(&fcoe_notifier);
1751} 1763}
1752 1764
@@ -1755,9 +1767,69 @@ static void fcoe_dev_setup(void)
1755 */ 1767 */
1756static void fcoe_dev_cleanup(void) 1768static void fcoe_dev_cleanup(void)
1757{ 1769{
1770 unregister_dcbevent_notifier(&dcb_notifier);
1758 unregister_netdevice_notifier(&fcoe_notifier); 1771 unregister_netdevice_notifier(&fcoe_notifier);
1759} 1772}
1760 1773
1774static struct fcoe_interface *
1775fcoe_hostlist_lookup_realdev_port(struct net_device *netdev)
1776{
1777 struct fcoe_interface *fcoe;
1778 struct net_device *real_dev;
1779
1780 list_for_each_entry(fcoe, &fcoe_hostlist, list) {
1781 if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN)
1782 real_dev = vlan_dev_real_dev(fcoe->netdev);
1783 else
1784 real_dev = fcoe->netdev;
1785
1786 if (netdev == real_dev)
1787 return fcoe;
1788 }
1789 return NULL;
1790}
1791
1792static int fcoe_dcb_app_notification(struct notifier_block *notifier,
1793 ulong event, void *ptr)
1794{
1795 struct dcb_app_type *entry = ptr;
1796 struct fcoe_interface *fcoe;
1797 struct net_device *netdev;
1798 struct fcoe_port *port;
1799 int prio;
1800
1801 if (entry->app.selector != DCB_APP_IDTYPE_ETHTYPE)
1802 return NOTIFY_OK;
1803
1804 netdev = dev_get_by_index(&init_net, entry->ifindex);
1805 if (!netdev)
1806 return NOTIFY_OK;
1807
1808 fcoe = fcoe_hostlist_lookup_realdev_port(netdev);
1809 dev_put(netdev);
1810 if (!fcoe)
1811 return NOTIFY_OK;
1812
1813 if (entry->dcbx & DCB_CAP_DCBX_VER_CEE)
1814 prio = ffs(entry->app.priority) - 1;
1815 else
1816 prio = entry->app.priority;
1817
1818 if (prio < 0)
1819 return NOTIFY_OK;
1820
1821 if (entry->app.protocol == ETH_P_FIP ||
1822 entry->app.protocol == ETH_P_FCOE)
1823 fcoe->ctlr.priority = prio;
1824
1825 if (entry->app.protocol == ETH_P_FCOE) {
1826 port = lport_priv(fcoe->ctlr.lp);
1827 port->priority = prio;
1828 }
1829
1830 return NOTIFY_OK;
1831}
1832
1761/** 1833/**
1762 * fcoe_device_notification() - Handler for net device events 1834 * fcoe_device_notification() - Handler for net device events
1763 * @notifier: The context of the notification 1835 * @notifier: The context of the notification
@@ -1966,6 +2038,46 @@ static bool fcoe_match(struct net_device *netdev)
1966} 2038}
1967 2039
1968/** 2040/**
2041 * fcoe_dcb_create() - Initialize DCB attributes and hooks
2042 * @netdev: The net_device object of the L2 link that should be queried
2043 * @port: The fcoe_port to bind FCoE APP priority with
2044 * @
2045 */
2046static void fcoe_dcb_create(struct fcoe_interface *fcoe)
2047{
2048#ifdef CONFIG_DCB
2049 int dcbx;
2050 u8 fup, up;
2051 struct net_device *netdev = fcoe->realdev;
2052 struct fcoe_port *port = lport_priv(fcoe->ctlr.lp);
2053 struct dcb_app app = {
2054 .priority = 0,
2055 .protocol = ETH_P_FCOE
2056 };
2057
2058 /* setup DCB priority attributes. */
2059 if (netdev && netdev->dcbnl_ops && netdev->dcbnl_ops->getdcbx) {
2060 dcbx = netdev->dcbnl_ops->getdcbx(netdev);
2061
2062 if (dcbx & DCB_CAP_DCBX_VER_IEEE) {
2063 app.selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE;
2064 up = dcb_ieee_getapp_mask(netdev, &app);
2065 app.protocol = ETH_P_FIP;
2066 fup = dcb_ieee_getapp_mask(netdev, &app);
2067 } else {
2068 app.selector = DCB_APP_IDTYPE_ETHTYPE;
2069 up = dcb_getapp(netdev, &app);
2070 app.protocol = ETH_P_FIP;
2071 fup = dcb_getapp(netdev, &app);
2072 }
2073
2074 port->priority = ffs(up) ? ffs(up) - 1 : 0;
2075 fcoe->ctlr.priority = ffs(fup) ? ffs(fup) - 1 : port->priority;
2076 }
2077#endif
2078}
2079
2080/**
1969 * fcoe_create() - Create a fcoe interface 2081 * fcoe_create() - Create a fcoe interface
1970 * @netdev : The net_device object the Ethernet interface to create on 2082 * @netdev : The net_device object the Ethernet interface to create on
1971 * @fip_mode: The FIP mode for this creation 2083 * @fip_mode: The FIP mode for this creation
@@ -2008,6 +2120,9 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
2008 /* Make this the "master" N_Port */ 2120 /* Make this the "master" N_Port */
2009 fcoe->ctlr.lp = lport; 2121 fcoe->ctlr.lp = lport;
2010 2122
2123 /* setup DCB priority attributes. */
2124 fcoe_dcb_create(fcoe);
2125
2011 /* add to lports list */ 2126 /* add to lports list */
2012 fcoe_hostlist_add(lport); 2127 fcoe_hostlist_add(lport);
2013 2128