aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjohn fastabend <john.r.fastabend@intel.com>2011-11-18 16:35:56 -0500
committerJames Bottomley <JBottomley@Parallels.com>2011-12-15 02:02:07 -0500
commit6f6c2aa33b915c574543f176dee89d7aefc115c1 (patch)
tree3c6907fe997727e92ed09c018abd8215ce26b6ba
parenta878185c3b93e692ace0d1628a47f3d75504ab4f (diff)
[SCSI] fcoe: fix fcoe in a DCB environment by adding DCB notifiers to set skb priority
Use DCB notifiers to set the skb priority to allow packets to be steered and tagged correctly over DCB enabled drivers that setup traffic classes. This allows queue_mapping() routines to be removed in these drivers that were previously inspecting the ethertype of every skb to mark FCoE/FIP frames. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/fcoe/fcoe.c115
-rw-r--r--drivers/scsi/fcoe/fcoe_ctlr.c4
-rw-r--r--include/scsi/libfcoe.h3
3 files changed, 122 insertions, 0 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index f3f440c955f3..8d67467dd9ce 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
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index c74c4b8e71ef..e7522dcc296e 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -320,6 +320,7 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf)
320 320
321 skb_put(skb, sizeof(*sol)); 321 skb_put(skb, sizeof(*sol));
322 skb->protocol = htons(ETH_P_FIP); 322 skb->protocol = htons(ETH_P_FIP);
323 skb->priority = fip->priority;
323 skb_reset_mac_header(skb); 324 skb_reset_mac_header(skb);
324 skb_reset_network_header(skb); 325 skb_reset_network_header(skb);
325 fip->send(fip, skb); 326 fip->send(fip, skb);
@@ -474,6 +475,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
474 } 475 }
475 skb_put(skb, len); 476 skb_put(skb, len);
476 skb->protocol = htons(ETH_P_FIP); 477 skb->protocol = htons(ETH_P_FIP);
478 skb->priority = fip->priority;
477 skb_reset_mac_header(skb); 479 skb_reset_mac_header(skb);
478 skb_reset_network_header(skb); 480 skb_reset_network_header(skb);
479 fip->send(fip, skb); 481 fip->send(fip, skb);
@@ -566,6 +568,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
566 cap->fip.fip_dl_len = htons(dlen / FIP_BPW); 568 cap->fip.fip_dl_len = htons(dlen / FIP_BPW);
567 569
568 skb->protocol = htons(ETH_P_FIP); 570 skb->protocol = htons(ETH_P_FIP);
571 skb->priority = fip->priority;
569 skb_reset_mac_header(skb); 572 skb_reset_mac_header(skb);
570 skb_reset_network_header(skb); 573 skb_reset_network_header(skb);
571 return 0; 574 return 0;
@@ -1911,6 +1914,7 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
1911 1914
1912 skb_put(skb, len); 1915 skb_put(skb, len);
1913 skb->protocol = htons(ETH_P_FIP); 1916 skb->protocol = htons(ETH_P_FIP);
1917 skb->priority = fip->priority;
1914 skb_reset_mac_header(skb); 1918 skb_reset_mac_header(skb);
1915 skb_reset_network_header(skb); 1919 skb_reset_network_header(skb);
1916 1920
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index d1e95c6ac776..5a35a2a2d3c5 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -147,6 +147,7 @@ struct fcoe_ctlr {
147 u8 map_dest; 147 u8 map_dest;
148 u8 spma; 148 u8 spma;
149 u8 probe_tries; 149 u8 probe_tries;
150 u8 priority;
150 u8 dest_addr[ETH_ALEN]; 151 u8 dest_addr[ETH_ALEN];
151 u8 ctl_src_addr[ETH_ALEN]; 152 u8 ctl_src_addr[ETH_ALEN];
152 153
@@ -301,6 +302,7 @@ struct fcoe_percpu_s {
301 * @lport: The associated local port 302 * @lport: The associated local port
302 * @fcoe_pending_queue: The pending Rx queue of skbs 303 * @fcoe_pending_queue: The pending Rx queue of skbs
303 * @fcoe_pending_queue_active: Indicates if the pending queue is active 304 * @fcoe_pending_queue_active: Indicates if the pending queue is active
305 * @priority: Packet priority (DCB)
304 * @max_queue_depth: Max queue depth of pending queue 306 * @max_queue_depth: Max queue depth of pending queue
305 * @min_queue_depth: Min queue depth of pending queue 307 * @min_queue_depth: Min queue depth of pending queue
306 * @timer: The queue timer 308 * @timer: The queue timer
@@ -316,6 +318,7 @@ struct fcoe_port {
316 struct fc_lport *lport; 318 struct fc_lport *lport;
317 struct sk_buff_head fcoe_pending_queue; 319 struct sk_buff_head fcoe_pending_queue;
318 u8 fcoe_pending_queue_active; 320 u8 fcoe_pending_queue_active;
321 u8 priority;
319 u32 max_queue_depth; 322 u32 max_queue_depth;
320 u32 min_queue_depth; 323 u32 min_queue_depth;
321 struct timer_list timer; 324 struct timer_list timer;