Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] fcoe: Fix write errors on NPIV ports

SCSI errors were generated while writing to LUNs
connected via NPIV ports.

Debugging this it was found that the FCoE packets
transmitted via the NPIV ports were not tagged with
correct user priority as negotiated with peer by DCB
agent. This resulted in FCoE traffic going with priority
zero(0) that did not have priority flow control (PFC)
enabled for it. The initiator after transferring data
to the target never saw any reply indicating the transfer
was complete. This resulted in error recovery (ABTS) and
SCSI command retries by the scsi-mid layer; eventually
resulting in I/O errors.

This patch fixes this issue by keeping the FCoE user
priority information in the fcoe_interface instance
that is common for both the physical port as well as
NPIV ports connected to that physical port; instead
of storing it in fcoe_port structure that has a per
port instance.

Signed-off-by: Neerav Parikh <Neerav.Parikh@intel.com>
Acked-by: Yi Zou <yi.zou@intel.com>
Acked-by: John Fastabend <john.r.fastabend@intel.com>
Tested-by: Marcus Dennis <marcusx.e.dennis@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

authored by

Neerav Parikh and committed by
James Bottomley
31c37a6f bd756dde

+7 -11
+5 -9
drivers/scsi/fcoe/fcoe.c
··· 1643 1643 skb_reset_network_header(skb); 1644 1644 skb->mac_len = elen; 1645 1645 skb->protocol = htons(ETH_P_FCOE); 1646 - skb->priority = port->priority; 1646 + skb->priority = fcoe->priority; 1647 1647 1648 1648 if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN && 1649 1649 fcoe->realdev->features & NETIF_F_HW_VLAN_TX) { ··· 1917 1917 struct fcoe_ctlr *ctlr; 1918 1918 struct fcoe_interface *fcoe; 1919 1919 struct net_device *netdev; 1920 - struct fcoe_port *port; 1921 1920 int prio; 1922 1921 1923 1922 if (entry->app.selector != DCB_APP_IDTYPE_ETHTYPE) ··· 1945 1946 entry->app.protocol == ETH_P_FCOE) 1946 1947 ctlr->priority = prio; 1947 1948 1948 - if (entry->app.protocol == ETH_P_FCOE) { 1949 - port = lport_priv(ctlr->lp); 1950 - port->priority = prio; 1951 - } 1949 + if (entry->app.protocol == ETH_P_FCOE) 1950 + fcoe->priority = prio; 1952 1951 1953 1952 return NOTIFY_OK; 1954 1953 } ··· 2177 2180 u8 fup, up; 2178 2181 struct net_device *netdev = fcoe->realdev; 2179 2182 struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); 2180 - struct fcoe_port *port = lport_priv(ctlr->lp); 2181 2183 struct dcb_app app = { 2182 2184 .priority = 0, 2183 2185 .protocol = ETH_P_FCOE ··· 2198 2202 fup = dcb_getapp(netdev, &app); 2199 2203 } 2200 2204 2201 - port->priority = ffs(up) ? ffs(up) - 1 : 0; 2202 - ctlr->priority = ffs(fup) ? ffs(fup) - 1 : port->priority; 2205 + fcoe->priority = ffs(up) ? ffs(up) - 1 : 0; 2206 + ctlr->priority = ffs(fup) ? ffs(fup) - 1 : fcoe->priority; 2203 2207 } 2204 2208 #endif 2205 2209 }
+2
drivers/scsi/fcoe/fcoe.h
··· 71 71 * @oem: The offload exchange manager for all local port 72 72 * instances associated with this port 73 73 * @removed: Indicates fcoe interface removed from net device 74 + * @priority: Priority for the FCoE packet (DCB) 74 75 * This structure is 1:1 with a net device. 75 76 */ 76 77 struct fcoe_interface { ··· 82 81 struct packet_type fip_packet_type; 83 82 struct fc_exch_mgr *oem; 84 83 u8 removed; 84 + u8 priority; 85 85 }; 86 86 87 87 #define fcoe_to_ctlr(x) \
-2
include/scsi/libfcoe.h
··· 327 327 * @lport: The associated local port 328 328 * @fcoe_pending_queue: The pending Rx queue of skbs 329 329 * @fcoe_pending_queue_active: Indicates if the pending queue is active 330 - * @priority: Packet priority (DCB) 331 330 * @max_queue_depth: Max queue depth of pending queue 332 331 * @min_queue_depth: Min queue depth of pending queue 333 332 * @timer: The queue timer ··· 342 343 struct fc_lport *lport; 343 344 struct sk_buff_head fcoe_pending_queue; 344 345 u8 fcoe_pending_queue_active; 345 - u8 priority; 346 346 u32 max_queue_depth; 347 347 u32 min_queue_depth; 348 348 struct timer_list timer;