diff options
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r-- | drivers/scsi/fcoe/fcoe_sw.c | 67 | ||||
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 16 |
2 files changed, 79 insertions, 4 deletions
diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index da210eba1941..2bbbe3c0cc7b 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; @@ -346,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, }; /** diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 5548bf3bb58b..0d6f5beb7f9e 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; @@ -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 */ @@ -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) { @@ -623,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; |