* [PATCH 01/11] net, fcoe: add ETH_P_FCOE for Fibre Channel over Ethernet (FCoE)
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
@ 2009-02-27 22:06 ` Yi Zou
2009-02-27 22:06 ` [PATCH 02/11] net: reclaim 8 upper bits of the netdev->features from GSO Yi Zou
` (9 subsequent siblings)
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:06 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
This adds eth type ETH_P_FCOE for Fibre Channel over Ethernet (FCoE),
consequently, the ETH_P_FCOE from fc_fcoe.h and fcoe skb->protocol
is not set as ETH_P_FCOE.
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
drivers/scsi/fcoe/libfcoe.c | 2 +-
include/linux/if_ether.h | 1 +
include/scsi/fc/fc_fcoe.h | 7 -------
3 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 5548bf3..a99a428 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -460,7 +460,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb->mac_len = elen;
- skb->protocol = htons(ETH_P_802_3);
+ skb->protocol = htons(ETH_P_FCOE);
skb->dev = fc->real_dev;
/* fill up mac and fcoe headers */
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 7f3c735..59d197c 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -78,6 +78,7 @@
#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
#define ETH_P_TIPC 0x88CA /* TIPC */
+#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */
#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
/*
diff --git a/include/scsi/fc/fc_fcoe.h b/include/scsi/fc/fc_fcoe.h
index f271d9c..ccb3dbe 100644
--- a/include/scsi/fc/fc_fcoe.h
+++ b/include/scsi/fc/fc_fcoe.h
@@ -25,13 +25,6 @@
*/
/*
- * The FCoE ethertype eventually goes in net/if_ether.h.
- */
-#ifndef ETH_P_FCOE
-#define ETH_P_FCOE 0x8906 /* FCOE ether type */
-#endif
-
-/*
* FC_FCOE_OUI hasn't been standardized yet. XXX TBD.
*/
#ifndef FC_FCOE_OUI
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 02/11] net: reclaim 8 upper bits of the netdev->features from GSO
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
2009-02-27 22:06 ` [PATCH 01/11] net, fcoe: add ETH_P_FCOE for Fibre Channel over Ethernet (FCoE) Yi Zou
@ 2009-02-27 22:06 ` Yi Zou
2009-02-27 22:06 ` [PATCH 03/11] net: define feature flags for FCoE offloads Yi Zou
` (8 subsequent siblings)
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:06 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
From: Chris Leech <christopher.leech@intel.com>
Reclaim 8 upper bits of netdev->features from GSO.
Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
drivers/net/xen-netfront.c | 2 +-
include/linux/netdevice.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index cd6184e..2ce536f 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1511,7 +1511,7 @@ static int xennet_set_tso(struct net_device *dev, u32 data)
static void xennet_set_features(struct net_device *dev)
{
/* Turn off all GSO bits except ROBUST. */
- dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1;
+ dev->features &= ~NETIF_F_GSO_MASK;
dev->features |= NETIF_F_GSO_ROBUST;
xennet_set_sg(dev, 0);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ec54785..c8238d9 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -652,7 +652,7 @@ struct net_device
/* Segmentation offload features */
#define NETIF_F_GSO_SHIFT 16
-#define NETIF_F_GSO_MASK 0xffff0000
+#define NETIF_F_GSO_MASK 0x00ff0000
#define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
#define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 03/11] net: define feature flags for FCoE offloads
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
2009-02-27 22:06 ` [PATCH 01/11] net, fcoe: add ETH_P_FCOE for Fibre Channel over Ethernet (FCoE) Yi Zou
2009-02-27 22:06 ` [PATCH 02/11] net: reclaim 8 upper bits of the netdev->features from GSO Yi Zou
@ 2009-02-27 22:06 ` Yi Zou
2009-02-27 22:06 ` [PATCH 04/11] net: add NETIF_F_FCOE_CRC to can_checksum_protocol Yi Zou
` (7 subsequent siblings)
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:06 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
From: Chris Leech <christopher.leech@intel.com>
Define feature flags for FCoE offloads.
Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
include/linux/netdevice.h | 3 +++
include/linux/skbuff.h | 2 ++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c8238d9..5c40557 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -650,6 +650,8 @@ struct net_device
#define NETIF_F_GRO 16384 /* Generic receive offload */
#define NETIF_F_LRO 32768 /* large receive offload */
+#define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */
+
/* Segmentation offload features */
#define NETIF_F_GSO_SHIFT 16
#define NETIF_F_GSO_MASK 0x00ff0000
@@ -658,6 +660,7 @@ struct net_device
#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
+#define NETIF_F_FSO (SKB_GSO_FCOE << NETIF_F_GSO_SHIFT)
/* List of features with software fallbacks. */
#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9dcf956..02adea2 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -188,6 +188,8 @@ enum {
SKB_GSO_TCP_ECN = 1 << 3,
SKB_GSO_TCPV6 = 1 << 4,
+
+ SKB_GSO_FCOE = 1 << 5,
};
#if BITS_PER_LONG > 32
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 04/11] net: add NETIF_F_FCOE_CRC to can_checksum_protocol
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
` (2 preceding siblings ...)
2009-02-27 22:06 ` [PATCH 03/11] net: define feature flags for FCoE offloads Yi Zou
@ 2009-02-27 22:06 ` Yi Zou
2009-02-27 22:06 ` [PATCH 05/11] net: add FCoE offload support through net_device Yi Zou
` (6 subsequent siblings)
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:06 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
Add FC CRC offload check for ETH_P_FCOE.
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
net/core/dev.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index a17e006..aad4763 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1457,7 +1457,9 @@ static bool can_checksum_protocol(unsigned long features, __be16 protocol)
((features & NETIF_F_IP_CSUM) &&
protocol == htons(ETH_P_IP)) ||
((features & NETIF_F_IPV6_CSUM) &&
- protocol == htons(ETH_P_IPV6)));
+ protocol == htons(ETH_P_IPV6)) ||
+ ((features & NETIF_F_FCOE_CRC) &&
+ protocol == htons(ETH_P_FCOE)));
}
static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 05/11] net: add FCoE offload support through net_device
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
` (3 preceding siblings ...)
2009-02-27 22:06 ` [PATCH 04/11] net: add NETIF_F_FCOE_CRC to can_checksum_protocol Yi Zou
@ 2009-02-27 22:06 ` Yi Zou
2009-02-27 22:07 ` [PATCH 06/11] fcoe, libfc: check offload features from LLD through netdev Yi Zou
` (5 subsequent siblings)
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:06 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
This adds support to provide Fiber Channel over Ethernet (FCoE) offload
through net_device's net_device_ops struct. The offload through net_device
for FCoE is enabled in kernel as built-in or module driver.
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
include/linux/netdevice.h | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 5c40557..7ed49f5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -582,6 +582,14 @@ struct net_device_ops {
#define HAVE_NETDEV_POLL
void (*ndo_poll_controller)(struct net_device *dev);
#endif
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+ int (*ndo_fcoe_ddp_setup)(struct net_device *dev,
+ u16 xid,
+ struct scatterlist *sgl,
+ unsigned int sgc);
+ int (*ndo_fcoe_ddp_done)(struct net_device *dev,
+ u16 xid);
+#endif
};
/*
@@ -843,6 +851,11 @@ struct net_device
struct dcbnl_rtnl_ops *dcbnl_ops;
#endif
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+ /* max exchange id for FCoE LRO by ddp */
+ unsigned int fcoe_ddp_xid;
+#endif
+
#ifdef CONFIG_COMPAT_NET_DEV_OPS
struct {
int (*init)(struct net_device *dev);
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 06/11] fcoe, libfc: check offload features from LLD through netdev
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
` (4 preceding siblings ...)
2009-02-27 22:06 ` [PATCH 05/11] net: add FCoE offload support through net_device Yi Zou
@ 2009-02-27 22:07 ` Yi Zou
2009-02-27 22:07 ` [PATCH 07/11] libfc: use lso_max for sequence offload Yi Zou
` (4 subsequent siblings)
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:07 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
This checks if net_devices supports FCoE offload ops in netdev_ops and it
if it does, then sets up the corresponding flags in the associated fc_lport.
For large send offload, the maximum length supported in one large send is now
described by the added lso_max in fc_lport, which is setup initially from
netdev->gso_max_size.
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
drivers/scsi/fcoe/fcoe_sw.c | 29 ++++++++++++++++++++++++++++-
include/scsi/libfc.h | 1 +
2 files changed, 29 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c
index da210eb..d99217d 100644
--- a/drivers/scsi/fcoe/fcoe_sw.c
+++ b/drivers/scsi/fcoe/fcoe_sw.c
@@ -133,6 +133,13 @@ static int fcoe_sw_lport_config(struct fc_lport *lp)
/* lport fc_lport related configuration */
fc_lport_config(lp);
+ /* offload related configuration */
+ lp->crc_offload = 0;
+ lp->seq_offload = 0;
+ lp->lro_enabled = 0;
+ lp->lro_xid = 0;
+ lp->lso_max = 0;
+
return 0;
}
@@ -186,7 +193,27 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev)
if (fc->real_dev->features & NETIF_F_SG)
lp->sg_supp = 1;
-
+#ifdef NETIF_F_FCOE_CRC
+ if (netdev->features & NETIF_F_FCOE_CRC) {
+ lp->crc_offload = 1;
+ printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n",
+ netdev->name);
+ }
+#endif
+#ifdef NETIF_F_FSO
+ if (netdev->features & NETIF_F_FSO) {
+ lp->seq_offload = 1;
+ lp->lso_max = netdev->gso_max_size;
+ printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n",
+ netdev->name, lp->lso_max);
+ }
+#endif
+ if (netdev->fcoe_ddp_xid) {
+ lp->lro_enabled = 1;
+ lp->lro_xid = netdev->fcoe_ddp_xid;
+ printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n",
+ netdev->name, lp->lro_xid);
+ }
skb_queue_head_init(&fc->fcoe_pending_queue);
fc->fcoe_pending_queue_active = 0;
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index a2e126b..61c746c 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -654,6 +654,7 @@ struct fc_lport {
u16 link_speed;
u16 link_supported_speeds;
u16 lro_xid; /* max xid for fcoe lro */
+ unsigned int lso_max; /* max large send size */
struct fc_ns_fts fcts; /* FC-4 type masks */
struct fc_els_rnid_gen rnid_gen; /* RNID information */
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 07/11] libfc: use lso_max for sequence offload
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
` (5 preceding siblings ...)
2009-02-27 22:07 ` [PATCH 06/11] fcoe, libfc: check offload features from LLD through netdev Yi Zou
@ 2009-02-27 22:07 ` Yi Zou
2009-02-27 22:07 ` [PATCH 08/11] fcoe: add support to large send by gso through net_device for fcoe_sw Yi Zou
` (3 subsequent siblings)
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:07 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
Make sure for large send is supported by LLD in outgoing FCP data, we are only
sending the lso_max a time in one single large send, since that is what
supported by LLD.
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
drivers/scsi/libfc/fc_fcp.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 2a631d7..80e8491 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -435,7 +435,13 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
* burst length (t_blen) to seq_blen, otherwise set t_blen
* to max FC frame payload previously set in fsp->max_payload.
*/
- t_blen = lp->seq_offload ? seq_blen : fsp->max_payload;
+ t_blen = fsp->max_payload;
+ if (lp->seq_offload) {
+ t_blen = min(seq_blen, (size_t)lp->lso_max);
+ FC_DEBUG_FCP("fsp=%p:lso:blen=%zx lso_max=0x%x t_blen=%zx\n",
+ fsp, seq_blen, lp->lso_max, t_blen);
+ }
+
WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD);
if (t_blen > 512)
t_blen &= ~(512 - 1); /* round down to block size */
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 08/11] fcoe: add support to large send by gso through net_device for fcoe_sw
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
` (6 preceding siblings ...)
2009-02-27 22:07 ` [PATCH 07/11] libfc: use lso_max for sequence offload Yi Zou
@ 2009-02-27 22:07 ` Yi Zou
2009-02-27 22:07 ` [PATCH 09/11] libfc: add support of large receive offload by ddp in fc_fcp Yi Zou
` (2 subsequent siblings)
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:07 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
Change fcoe_xmit to setup gso for LLD LSO offload as well as CRC offload
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
drivers/scsi/fcoe/libfcoe.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index a99a428..5dae823 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -423,7 +423,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
/* crc offload */
if (likely(lp->crc_offload)) {
- skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->ip_summed = CHECKSUM_PARTIAL;
skb->csum_start = skb_headroom(skb);
skb->csum_offset = skb->len;
crc = 0;
@@ -483,6 +483,16 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER);
hp->fcoe_sof = sof;
+#ifdef NETIF_F_FSO
+ /* fcoe lso, mss is in max_payload which is non-zero for FCP data */
+ if (lp->seq_offload && fr_max_payload(fp)) {
+ skb_shinfo(skb)->gso_type = SKB_GSO_FCOE;
+ skb_shinfo(skb)->gso_size = fr_max_payload(fp);
+ } else {
+ skb_shinfo(skb)->gso_type = 0;
+ skb_shinfo(skb)->gso_size = 0;
+ }
+#endif
/* update tx stats: regardless if LLD fails */
stats = lp->dev_stats[smp_processor_id()];
if (stats) {
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 09/11] libfc: add support of large receive offload by ddp in fc_fcp
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
` (7 preceding siblings ...)
2009-02-27 22:07 ` [PATCH 08/11] fcoe: add support to large send by gso through net_device for fcoe_sw Yi Zou
@ 2009-02-27 22:07 ` Yi Zou
2009-02-27 22:07 ` [PATCH 10/11] fcoe: add support to FCoE offload support in fcoe_sw through net_device Yi Zou
2009-02-27 22:07 ` [PATCH 11/11] fcoe: fcoe fc crc offload indication by skb->ip_summed Yi Zou
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:07 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
When LLD supports direct data placement (ddp) for large receive of an scsi
i/o coming into fc_fcp, we call into libfc_function_template's ddp_setup()
to prepare for a ddp of large receive for this read I/O. When I/O is complete,
we call the corresponding ddp_done() to get the length of data ddped as well
as to let LLD do clean up.
fc_fcp_ddp_setup()/fc_fcp_ddp_done() are added to setup and complete a ddped
read I/O described by the given fc_fcp_pkt. They would call into corresponding
ddp_setup/ddp_done implemented by the fcoe layer. Eventually, fcoe layer calls
into LLD's ddp_setup/ddp_done provided through net_device
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
drivers/scsi/libfc/fc_exch.c | 4 ++-
drivers/scsi/libfc/fc_fcp.c | 61 +++++++++++++++++++++++++++++++++++++++++-
include/scsi/fc_frame.h | 19 +------------
include/scsi/libfc.h | 30 +++++++++++++++++++++
include/scsi/libfcoe.h | 18 ------------
5 files changed, 95 insertions(+), 37 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 505825b..d9d01e7 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -489,7 +489,7 @@ static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp)
struct fc_exch *ep = NULL;
if (mp->max_read) {
- if (fc_frame_is_read(fp)) {
+ if (fc_fcp_is_read(fr_fsp(fp))) {
min = mp->min_xid;
max = mp->max_read;
plast = &mp->last_read;
@@ -1841,6 +1841,8 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
fc_exch_setup_hdr(ep, fp, ep->f_ctl);
sp->cnt++;
+ fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
+
if (unlikely(lp->tt.frame_send(lp, fp)))
goto err;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 80e8491..379d299 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -265,6 +265,56 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
}
/*
+ * fc_fcp_ddp_setup - calls to LLD's ddp_setup to set up DDP
+ * transfer for a read I/O indicated by the fc_fcp_pkt.
+ * @fsp: ptr to the fc_fcp_pkt
+ *
+ * This is called in exch_seq_send() when we have a newly allocated
+ * exchange with a valid exchange id to setup ddp.
+ *
+ * returns: none
+ */
+void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid)
+{
+ struct fc_lport *lp;
+
+ if (!fsp)
+ return;
+
+ lp = fsp->lp;
+ if ((fsp->req_flags & FC_SRB_READ) &&
+ (lp->lro_enabled) && (lp->tt.ddp_setup)) {
+ if (lp->tt.ddp_setup(lp, xid, scsi_sglist(fsp->cmd),
+ scsi_sg_count(fsp->cmd)))
+ fsp->xfer_ddp = xid;
+ }
+}
+EXPORT_SYMBOL(fc_fcp_ddp_setup);
+
+/*
+ * fc_fcp_ddp_done - calls to LLD's ddp_done to release any
+ * DDP related resources for this I/O if it is initialized
+ * as a ddp transfer
+ * @fsp: ptr to the fc_fcp_pkt
+ *
+ * returns: none
+ */
+static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp)
+{
+ struct fc_lport *lp;
+
+ if (!fsp)
+ return;
+
+ lp = fsp->lp;
+ if (fsp->xfer_ddp && lp->tt.ddp_done) {
+ fsp->xfer_len = lp->tt.ddp_done(lp, fsp->xfer_ddp);
+ fsp->xfer_ddp = 0;
+ }
+}
+
+
+/*
* Receive SCSI data from target.
* Called after receiving solicited data.
*/
@@ -289,6 +339,9 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
len = fr_len(fp) - sizeof(*fh);
buf = fc_frame_payload_get(fp, 0);
+ /* if this I/O is ddped, update xfer len */
+ fc_fcp_ddp_done(fsp);
+
if (offset + len > fsp->data_len) {
/* this should never happen */
if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) &&
@@ -750,6 +803,9 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
fsp->scsi_comp_flags = flags;
expected_len = fsp->data_len;
+ /* if ddp, update xfer len */
+ fc_fcp_ddp_done(fsp);
+
if (unlikely((flags & ~FCP_CONF_REQ) || fc_rp->fr_status)) {
rp_ex = (void *)(fc_rp + 1);
if (flags & (FCP_RSP_LEN_VAL | FCP_SNS_LEN_VAL)) {
@@ -1012,7 +1068,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
}
memcpy(fc_frame_payload_get(fp, len), &fsp->cdb_cmd, len);
- fr_cmd(fp) = fsp->cmd;
+ fr_fsp(fp) = fsp;
rport = fsp->rport;
fsp->max_payload = rport->maxframe_size;
rp = rport->dd_data;
@@ -1746,6 +1802,9 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
struct fc_lport *lp;
unsigned long flags;
+ /* release outstanding ddp context */
+ fc_fcp_ddp_done(fsp);
+
fsp->state |= FC_SRB_COMPL;
if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) {
spin_unlock_bh(&fsp->scsi_pkt_lock);
diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h
index 04d34a7..5951105 100644
--- a/include/scsi/fc_frame.h
+++ b/include/scsi/fc_frame.h
@@ -54,8 +54,7 @@
#define fr_eof(fp) (fr_cb(fp)->fr_eof)
#define fr_flags(fp) (fr_cb(fp)->fr_flags)
#define fr_max_payload(fp) (fr_cb(fp)->fr_max_payload)
-#define fr_cmd(fp) (fr_cb(fp)->fr_cmd)
-#define fr_dir(fp) (fr_cmd(fp)->sc_data_direction)
+#define fr_fsp(fp) (fr_cb(fp)->fr_fsp)
#define fr_crc(fp) (fr_cb(fp)->fr_crc)
struct fc_frame {
@@ -66,7 +65,7 @@ struct fcoe_rcv_info {
struct packet_type *ptype;
struct fc_lport *fr_dev; /* transport layer private pointer */
struct fc_seq *fr_seq; /* for use with exchange manager */
- struct scsi_cmnd *fr_cmd; /* for use of scsi command */
+ struct fc_fcp_pkt *fr_fsp; /* for the corresponding fcp I/O */
u32 fr_crc;
u16 fr_max_payload; /* max FC payload */
enum fc_sof fr_sof; /* start of frame delimiter */
@@ -218,20 +217,6 @@ static inline bool fc_frame_is_cmd(const struct fc_frame *fp)
return fc_frame_rctl(fp) == FC_RCTL_DD_UNSOL_CMD;
}
-static inline bool fc_frame_is_read(const struct fc_frame *fp)
-{
- if (fc_frame_is_cmd(fp) && fr_cmd(fp))
- return fr_dir(fp) == DMA_FROM_DEVICE;
- return false;
-}
-
-static inline bool fc_frame_is_write(const struct fc_frame *fp)
-{
- if (fc_frame_is_cmd(fp) && fr_cmd(fp))
- return fr_dir(fp) == DMA_TO_DEVICE;
- return false;
-}
-
/*
* Check for leaks.
* Print the frame header of any currently allocated frame, assuming there
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 61c746c..a70eafa 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -245,6 +245,7 @@ struct fc_fcp_pkt {
*/
struct fcp_cmnd cdb_cmd;
size_t xfer_len;
+ u16 xfer_ddp; /* this xfer is ddped */
u32 xfer_contig_end; /* offset of end of contiguous xfer */
u16 max_payload; /* max payload size in bytes */
@@ -267,6 +268,15 @@ struct fc_fcp_pkt {
u8 recov_retry; /* count of recovery retries */
struct fc_seq *recov_seq; /* sequence for REC or SRR */
};
+/*
+ * FC_FCP HELPER FUNCTIONS
+ *****************************/
+static inline bool fc_fcp_is_read(const struct fc_fcp_pkt *fsp)
+{
+ if (fsp && fsp->cmd)
+ return fsp->cmd->sc_data_direction == DMA_FROM_DEVICE;
+ return false;
+}
/*
* Structure and function definitions for managing Fibre Channel Exchanges
@@ -400,6 +410,21 @@ struct libfc_function_template {
void *arg, unsigned int timer_msec);
/*
+ * Sets up the DDP context for a given exchange id on the given
+ * scatterlist if LLD supports DDP for large receive.
+ *
+ * STATUS: OPTIONAL
+ */
+ int (*ddp_setup)(struct fc_lport *lp, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc);
+ /*
+ * Completes the DDP transfer and returns the length of data DDPed
+ * for the given exchange id.
+ *
+ * STATUS: OPTIONAL
+ */
+ int (*ddp_done)(struct fc_lport *lp, u16 xid);
+ /*
* Send a frame using an existing sequence and exchange.
*
* STATUS: OPTIONAL
@@ -822,6 +847,11 @@ int fc_change_queue_type(struct scsi_device *sdev, int tag_type);
void fc_fcp_destroy(struct fc_lport *);
/*
+ * Set up direct-data placement for this I/O request
+ */
+void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid);
+
+/*
* ELS/CT interface
*****************************/
/*
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index 941818f..c41f7d0 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -124,24 +124,6 @@ static inline u16 skb_fc_rxid(const struct sk_buff *skb)
return be16_to_cpu(skb_fc_header(skb)->fh_rx_id);
}
-/* FIXME - DMA_BIDIRECTIONAL ? */
-#define skb_cb(skb) ((struct fcoe_rcv_info *)&((skb)->cb[0]))
-#define skb_cmd(skb) (skb_cb(skb)->fr_cmd)
-#define skb_dir(skb) (skb_cmd(skb)->sc_data_direction)
-static inline bool skb_fc_is_read(const struct sk_buff *skb)
-{
- if (skb_fc_is_cmd(skb) && skb_cmd(skb))
- return skb_dir(skb) == DMA_FROM_DEVICE;
- return false;
-}
-
-static inline bool skb_fc_is_write(const struct sk_buff *skb)
-{
- if (skb_fc_is_cmd(skb) && skb_cmd(skb))
- return skb_dir(skb) == DMA_TO_DEVICE;
- return false;
-}
-
/* libfcoe funcs */
int fcoe_reset(struct Scsi_Host *shost);
u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 10/11] fcoe: add support to FCoE offload support in fcoe_sw through net_device
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
` (8 preceding siblings ...)
2009-02-27 22:07 ` [PATCH 09/11] libfc: add support of large receive offload by ddp in fc_fcp Yi Zou
@ 2009-02-27 22:07 ` Yi Zou
2009-02-27 22:07 ` [PATCH 11/11] fcoe: fcoe fc crc offload indication by skb->ip_summed Yi Zou
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:07 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
This adds implementation of ddp_setup()/ddp_done() in fcoe_sw for its
fcoe_sw_libfc_fcn_templ.
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
drivers/scsi/fcoe/fcoe_sw.c | 38 ++++++++++++++++++++++++++++++++++++++
1 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c
index d99217d..2bbbe3c 100644
--- a/drivers/scsi/fcoe/fcoe_sw.c
+++ b/drivers/scsi/fcoe/fcoe_sw.c
@@ -373,8 +373,46 @@ static int fcoe_sw_destroy(struct net_device *netdev)
return 0;
}
+/*
+ * fcoe_sw_ddp_setup - calls LLD's ddp_setup through net_device
+ * @lp: the corresponding fc_lport
+ * @xid: the exchange id for this ddp transfer
+ * @sgl: the scatterlist describing this transfer
+ * @sgc: number of sg items
+ *
+ * Returns : 0 no ddp
+ */
+static int fcoe_sw_ddp_setup(struct fc_lport *lp, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc)
+{
+ struct net_device *n = fcoe_netdev(lp);
+
+ if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup)
+ return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc);
+
+ return 0;
+}
+
+/*
+ * fcoe_sw_ddp_done - calls LLD's ddp_done through net_device
+ * @lp: the corresponding fc_lport
+ * @xid: the exchange id for this ddp transfer
+ *
+ * Returns : the length of data that have been completed by ddp
+ */
+static int fcoe_sw_ddp_done(struct fc_lport *lp, u16 xid)
+{
+ struct net_device *n = fcoe_netdev(lp);
+
+ if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done)
+ return n->netdev_ops->ndo_fcoe_ddp_done(n, xid);
+ return 0;
+}
+
static struct libfc_function_template fcoe_sw_libfc_fcn_templ = {
.frame_send = fcoe_xmit,
+ .ddp_setup = fcoe_sw_ddp_setup,
+ .ddp_done = fcoe_sw_ddp_done,
};
/**
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 11/11] fcoe: fcoe fc crc offload indication by skb->ip_summed
[not found] <20090227220034.4987.50755.stgit@localhost.localdomain>
` (9 preceding siblings ...)
2009-02-27 22:07 ` [PATCH 10/11] fcoe: add support to FCoE offload support in fcoe_sw through net_device Yi Zou
@ 2009-02-27 22:07 ` Yi Zou
10 siblings, 0 replies; 11+ messages in thread
From: Yi Zou @ 2009-02-27 22:07 UTC (permalink / raw)
To: netdev, linux-scsi; +Cc: yi.zou
If LLD supports FCCRC offload, it should set ip_summed to be
CHECKSUM_UNNECESSARY so we don't have to do CRC check again.
Signed-off-by: Yi Zou <yi.zou@intel.com>
---
drivers/scsi/fcoe/libfcoe.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 5dae823..0d6f5be 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -633,7 +633,7 @@ int fcoe_percpu_receive_thread(void *arg)
* it's solicited data, in which case, the FCP layer would
* check it during the copy.
*/
- if (lp->crc_offload)
+ if (lp->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY)
fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
else
fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
^ permalink raw reply related [flat|nested] 11+ messages in thread