aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/fcoe
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2009-07-29 17:05:21 -0700
committerJames Bottomley <James.Bottomley@suse.de>2009-08-22 17:52:09 -0500
commitd7179680d04f1e196b7a5f70e7f93bb1850407c6 (patch)
treee31aaf450afcd7cba0d719178424ece5013964f8 /drivers/scsi/fcoe
parente8af4d4380babc89d193c16163f070a6418f033b (diff)
[SCSI] fcoe, libfc: adds offload EM per eth device with only single xid range per EM
Updates fcoe_em_config to allocate a single instance of sharable offload EM for supported lp->lro_xid per eth device, and then share this EM for subsequently more lports creation on same eth device (e.g when using VLAN). Adds tiny fcoe_oem_match function for offload EM to return true for read types IO to have read IO exchanges allocated from offload shared EM. Removes fc_em_alloc_xid function completely which was needed to manage two xid ranges within a EM, this is not needed any more with allocation of separate sharable offload EM per eth device. Instead this patch adds simple xid allocation logic to manage single xid range. Adds fc_exch_em_alloc with mp->next_xid as cursor to allocate new xid from single xid range of EM, uses mp->next_xid instead removed mp->last_xid which slightly increase probability of finding empty xid on exch allocation. Removes restriction of not allowing use of xid zero along with changing two xid range change to single xid range. Makes fc_fcp_ddp_setup calling conditional to only xid allocated from shared offload EM. Signed-off-by: Vasu Dev <vasu.dev@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r--drivers/scsi/fcoe/fcoe.c67
-rw-r--r--drivers/scsi/fcoe/fcoe.h3
2 files changed, 67 insertions, 3 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 86410b9a30c..0306aa95eb3 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -415,6 +415,17 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
return 0;
}
+/*
+ * fcoe_oem_match() - match for read types IO
+ * @fp: the fc_frame for new IO.
+ *
+ * Returns : true for read types IO, otherwise returns false.
+ */
+bool fcoe_oem_match(struct fc_frame *fp)
+{
+ return fc_fcp_is_read(fr_fsp(fp));
+}
+
/**
* fcoe_em_config() - allocates em for this lport
* @lp: the port that em is to allocated for
@@ -425,9 +436,61 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
*/
static inline int fcoe_em_config(struct fc_lport *lp)
{
- if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCOE_MIN_XID,
- FCOE_MAX_XID, NULL))
+ struct fcoe_softc *fc = lport_priv(lp);
+ struct fcoe_softc *oldfc = NULL;
+ u16 min_xid = FCOE_MIN_XID;
+ u16 max_xid = FCOE_MAX_XID;
+
+ /*
+ * Check if need to allocate an em instance for
+ * offload exchange ids to be shared across all VN_PORTs/lport.
+ */
+ if (!lp->lro_enabled || !lp->lro_xid || (lp->lro_xid >= max_xid)) {
+ lp->lro_xid = 0;
+ goto skip_oem;
+ }
+
+ /*
+ * Reuse existing offload em instance in case
+ * it is already allocated on phys_dev.
+ */
+ list_for_each_entry(oldfc, &fcoe_hostlist, list) {
+ if (oldfc->phys_dev == fc->phys_dev) {
+ fc->oem = oldfc->oem;
+ break;
+ }
+ }
+
+ if (fc->oem) {
+ if (!fc_exch_mgr_add(lp, fc->oem, fcoe_oem_match)) {
+ printk(KERN_ERR "fcoe_em_config: failed to add "
+ "offload em:%p on interface:%s\n",
+ fc->oem, fc->real_dev->name);
+ return -ENOMEM;
+ }
+ } else {
+ fc->oem = fc_exch_mgr_alloc(lp, FC_CLASS_3,
+ FCOE_MIN_XID, lp->lro_xid,
+ fcoe_oem_match);
+ if (!fc->oem) {
+ printk(KERN_ERR "fcoe_em_config: failed to allocate "
+ "em for offload exches on interface:%s\n",
+ fc->real_dev->name);
+ return -ENOMEM;
+ }
+ }
+
+ /*
+ * Exclude offload EM xid range from next EM xid range.
+ */
+ min_xid += lp->lro_xid + 1;
+
+skip_oem:
+ if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, min_xid, max_xid, NULL)) {
+ printk(KERN_ERR "fcoe_em_config: failed to "
+ "allocate em on interface %s\n", fc->real_dev->name);
return -ENOMEM;
+ }
return 0;
}
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 0d724fa0898..6905efc166b 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -37,7 +37,7 @@
#define FCOE_MAX_OUTSTANDING_COMMANDS 1024
-#define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */
+#define FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */
#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
unsigned int fcoe_debug_logging;
@@ -81,6 +81,7 @@ struct fcoe_softc {
struct list_head list;
struct net_device *real_dev;
struct net_device *phys_dev; /* device with ethtool_ops */
+ struct fc_exch_mgr *oem; /* offload exchange manger */
struct packet_type fcoe_packet_type;
struct packet_type fip_packet_type;
struct sk_buff_head fcoe_pending_queue;