summaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe/ixgbe_fcoe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_fcoe.c')
-rw-r--r--drivers/net/ixgbe/ixgbe_fcoe.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index 4123dec0dfb7..45182ab41d6b 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -31,6 +31,8 @@
#include "ixgbe_dcb_82599.h"
#endif /* CONFIG_IXGBE_DCB */
#include <linux/if_ether.h>
+#include <linux/gfp.h>
+#include <linux/if_vlan.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/fc/fc_fs.h>
@@ -202,6 +204,15 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
addr = sg_dma_address(sg);
len = sg_dma_len(sg);
while (len) {
+ /* max number of buffers allowed in one DDP context */
+ if (j >= IXGBE_BUFFCNT_MAX) {
+ netif_err(adapter, drv, adapter->netdev,
+ "xid=%x:%d,%d,%d:addr=%llx "
+ "not enough descriptors\n",
+ xid, i, j, dmacount, (u64)addr);
+ goto out_noddp_free;
+ }
+
/* get the offset of length of current buffer */
thisoff = addr & ((dma_addr_t)bufflen - 1);
thislen = min((bufflen - thisoff), len);
@@ -227,20 +238,13 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
len -= thislen;
addr += thislen;
j++;
- /* max number of buffers allowed in one DDP context */
- if (j > IXGBE_BUFFCNT_MAX) {
- DPRINTK(DRV, ERR, "xid=%x:%d,%d,%d:addr=%llx "
- "not enough descriptors\n",
- xid, i, j, dmacount, (u64)addr);
- goto out_noddp_free;
- }
}
}
/* only the last buffer may have non-full bufflen */
lastsize = thisoff + thislen;
fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
- fcbuff |= (j << IXGBE_FCBUFF_BUFFCNT_SHIFT);
+ fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT);
fcbuff |= (IXGBE_FCBUFF_VALID);
@@ -309,10 +313,12 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
if (fcerr == IXGBE_FCERR_BADCRC)
skb->ip_summed = CHECKSUM_NONE;
- skb_reset_network_header(skb);
- skb_set_transport_header(skb, skb_network_offset(skb) +
- sizeof(struct fcoe_hdr));
- fh = (struct fc_frame_header *)skb_transport_header(skb);
+ if (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q))
+ fh = (struct fc_frame_header *)(skb->data +
+ sizeof(struct vlan_hdr) + sizeof(struct fcoe_hdr));
+ else
+ fh = (struct fc_frame_header *)(skb->data +
+ sizeof(struct fcoe_hdr));
fctl = ntoh24(fh->fh_f_ctl);
if (fctl & FC_FC_EX_CTX)
xid = be16_to_cpu(fh->fh_ox_id);
@@ -520,6 +526,9 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
/* Enable L2 eth type filter for FCoE */
IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FCOE),
(ETH_P_FCOE | IXGBE_ETQF_FCOE | IXGBE_ETQF_FILTER_EN));
+ /* Enable L2 eth type filter for FIP */
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FIP),
+ (ETH_P_FIP | IXGBE_ETQF_FILTER_EN));
if (adapter->ring_feature[RING_F_FCOE].indices) {
/* Use multiple rx queues for FCoE by redirection table */
for (i = 0; i < IXGBE_FCRETA_SIZE; i++) {
@@ -539,6 +548,12 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
IXGBE_ETQS_QUEUE_EN |
(fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT));
}
+ /* send FIP frames to the first FCoE queue */
+ fcoe_i = f->mask;
+ fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx;
+ IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FIP),
+ IXGBE_ETQS_QUEUE_EN |
+ (fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT));
IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL,
IXGBE_FCRXCTRL_FCOELLI |
@@ -614,9 +629,9 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
netdev->vlan_features |= NETIF_F_FSO;
netdev->vlan_features |= NETIF_F_FCOE_MTU;
netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
- netdev_features_change(netdev);
ixgbe_init_interrupt_scheme(adapter);
+ netdev_features_change(netdev);
if (netif_running(netdev))
netdev->netdev_ops->ndo_open(netdev);
@@ -660,11 +675,11 @@ int ixgbe_fcoe_disable(struct net_device *netdev)
netdev->vlan_features &= ~NETIF_F_FSO;
netdev->vlan_features &= ~NETIF_F_FCOE_MTU;
netdev->fcoe_ddp_xid = 0;
- netdev_features_change(netdev);
ixgbe_cleanup_fcoe(adapter);
-
ixgbe_init_interrupt_scheme(adapter);
+ netdev_features_change(netdev);
+
if (netif_running(netdev))
netdev->netdev_ops->ndo_open(netdev);
rc = 0;