From e95147d8fa4e63bf6d8ff249f074d0047338fc61 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Wed, 21 Oct 2009 16:27:39 -0700 Subject: [SCSI] libfc: removes unused disc_work and ex_list Reported-by: Alex Lyakas Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- include/scsi/libfc.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/scsi/libfc.h') diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 65dc9aacbf7..4ff14858056 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -742,7 +742,6 @@ struct fc_lport { /* Miscellaneous */ struct delayed_work retry_work; - struct delayed_work disc_work; }; /* -- cgit v1.2.3-70-g09d2 From b4a9c7ede96e90f7b1ec009ce7256059295e76df Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Wed, 21 Oct 2009 16:28:30 -0700 Subject: [SCSI] libfc: fix free of fc_rport_priv with timer pending Timer crashes were caused by freeing a struct fc_rport_priv with a timer pending, causing the timer facility list to be corrupted. This was during FC uplink flap tests with a lot of targets. After discovery, we were doing an PLOGI on an rdata that was in DELETE state but not yet removed from the lookup list. This moved the rdata from DELETE state to PLOGI state. If the PLOGI exchange allocation failed and needed to be retried, the timer scheduling could race with the free being done by fc_rport_work(). When fc_rport_login() is called on a rport in DELETE state, move it to a new state RESTART. In fc_rport_work, when handling a LOGO, STOPPED or FAILED event, look for restart state. In the RESTART case, don't take the rdata off the list and after the transport remote port is deleted and exchanges are reset, re-login to the remote port. Note that the new RESTART state also corrects a problem we had when re-discovering a port that had moved to DELETE state. In that case, a new rdata was created, but the old rdata would do an exchange manager reset affecting the FC_ID for both the new rdata and old rdata. With the new state, the new port isn't logged into until after any old exchanges are reset. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 69 +++++++++++++++++++++++++++++++------------ include/scsi/libfc.h | 1 + 2 files changed, 51 insertions(+), 19 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 49abb839a22..324e156b5d0 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -86,6 +86,7 @@ static const char *fc_rport_state_names[] = { [RPORT_ST_LOGO] = "LOGO", [RPORT_ST_ADISC] = "ADISC", [RPORT_ST_DELETE] = "Delete", + [RPORT_ST_RESTART] = "Restart", }; /** @@ -99,8 +100,7 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, struct fc_rport_priv *rdata; list_for_each_entry(rdata, &lport->disc.rports, peers) - if (rdata->ids.port_id == port_id && - rdata->rp_state != RPORT_ST_DELETE) + if (rdata->ids.port_id == port_id) return rdata; return NULL; } @@ -235,6 +235,7 @@ static void fc_rport_work(struct work_struct *work) struct fc_rport_operations *rport_ops; struct fc_rport_identifiers ids; struct fc_rport *rport; + int restart = 0; mutex_lock(&rdata->rp_mutex); event = rdata->event; @@ -287,8 +288,19 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); if (port_id != FC_FID_DIR_SERV) { + /* + * We must drop rp_mutex before taking disc_mutex. + * Re-evaluate state to allow for restart. + * A transition to RESTART state must only happen + * while disc_mutex is held and rdata is on the list. + */ mutex_lock(&lport->disc.disc_mutex); - list_del(&rdata->peers); + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state == RPORT_ST_RESTART) + restart = 1; + else + list_del(&rdata->peers); + mutex_unlock(&rdata->rp_mutex); mutex_unlock(&lport->disc.disc_mutex); } @@ -312,7 +324,13 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); fc_remote_port_delete(rport); } - kref_put(&rdata->kref, lport->tt.rport_destroy); + if (restart) { + mutex_lock(&rdata->rp_mutex); + FC_RPORT_DBG(rdata, "work restart\n"); + fc_rport_enter_plogi(rdata); + mutex_unlock(&rdata->rp_mutex); + } else + kref_put(&rdata->kref, lport->tt.rport_destroy); break; default: @@ -342,6 +360,12 @@ int fc_rport_login(struct fc_rport_priv *rdata) FC_RPORT_DBG(rdata, "ADISC port\n"); fc_rport_enter_adisc(rdata); break; + case RPORT_ST_RESTART: + break; + case RPORT_ST_DELETE: + FC_RPORT_DBG(rdata, "Restart deleted port\n"); + fc_rport_state_enter(rdata, RPORT_ST_RESTART); + break; default: FC_RPORT_DBG(rdata, "Login to port\n"); fc_rport_enter_plogi(rdata); @@ -397,20 +421,21 @@ int fc_rport_logoff(struct fc_rport_priv *rdata) if (rdata->rp_state == RPORT_ST_DELETE) { FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); - mutex_unlock(&rdata->rp_mutex); goto out; } - fc_rport_enter_logo(rdata); + if (rdata->rp_state == RPORT_ST_RESTART) + FC_RPORT_DBG(rdata, "Port in Restart state, deleting\n"); + else + fc_rport_enter_logo(rdata); /* * Change the state to Delete so that we discard * the response. */ fc_rport_enter_delete(rdata, RPORT_EV_STOP); - mutex_unlock(&rdata->rp_mutex); - out: + mutex_unlock(&rdata->rp_mutex); return 0; } @@ -466,6 +491,7 @@ static void fc_rport_timeout(struct work_struct *work) case RPORT_ST_READY: case RPORT_ST_INIT: case RPORT_ST_DELETE: + case RPORT_ST_RESTART: break; } @@ -499,6 +525,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) fc_rport_enter_logo(rdata); break; case RPORT_ST_DELETE: + case RPORT_ST_RESTART: case RPORT_ST_READY: case RPORT_ST_INIT: break; @@ -1248,6 +1275,7 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, } break; case RPORT_ST_PRLI: + case RPORT_ST_RTV: case RPORT_ST_READY: case RPORT_ST_ADISC: FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d " @@ -1255,11 +1283,14 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, /* XXX TBD - should reset */ break; case RPORT_ST_DELETE: - default: - FC_RPORT_DBG(rdata, "Received PLOGI in unexpected state %d\n", - rdata->rp_state); - fc_frame_free(rx_fp); - goto out; + case RPORT_ST_LOGO: + case RPORT_ST_RESTART: + FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n", + fc_rport_state(rdata)); + mutex_unlock(&rdata->rp_mutex); + rjt_data.reason = ELS_RJT_BUSY; + rjt_data.explan = ELS_EXPL_NONE; + goto reject; } /* @@ -1510,14 +1541,14 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", fc_rport_state(rdata)); + fc_rport_enter_delete(rdata, RPORT_EV_LOGO); + /* - * If the remote port was created due to discovery, - * log back in. It may have seen a stale RSCN about us. + * If the remote port was created due to discovery, set state + * to log back in. It may have seen a stale RSCN about us. */ - if (rdata->rp_state != RPORT_ST_DELETE && rdata->disc_id) - fc_rport_enter_plogi(rdata); - else - fc_rport_enter_delete(rdata, RPORT_EV_LOGO); + if (rdata->disc_id) + fc_rport_state_enter(rdata, RPORT_ST_RESTART); mutex_unlock(&rdata->rp_mutex); } else FC_RPORT_ID_DBG(lport, sid, diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 4ff14858056..1662d73d85a 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -145,6 +145,7 @@ enum fc_rport_state { RPORT_ST_LOGO, /* port logout sent */ RPORT_ST_ADISC, /* Discover Address sent */ RPORT_ST_DELETE, /* port being deleted */ + RPORT_ST_RESTART, /* remote port being deleted and will restart */ }; /** -- cgit v1.2.3-70-g09d2 From e881a172dac4d9ea3b2a1540041d872963c269bd Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 15 Oct 2009 17:46:39 -0700 Subject: [SCSI] modify change_queue_depth to take in reason why it is being called This patch modifies scsi_host_template->change_queue_depth so that it takes an argument indicating why it is being called. This will be used so that if a LLD needs to do some extra processing when handling queue fulls or later ramp ups, it can do so. This is a simple port of the drivers setting a change_queue_depth callback. In the patch I just have these LLDs adjust the queue depth if the user was requesting it. Signed-off-by: Mike Christie [Vasu.Dev: v2 Also converted pmcraid_change_queue_depth and then verified all modules compile using "make allmodconfig" for any new build warnings on X86_64. Updated original description after combing two original patches from Mike to make this patch git bisectable.] Signed-off-by: Vasu Dev [jejb: fixed up 53c700] Signed-off-by: James Bottomley --- drivers/ata/libata-scsi.c | 7 ++++++- drivers/ata/sata_nv.c | 2 +- drivers/message/fusion/mptscsih.c | 9 +++++++-- drivers/message/fusion/mptscsih.h | 3 ++- drivers/s390/scsi/zfcp_scsi.c | 6 +++++- drivers/scsi/3w-9xxx.c | 6 +++++- drivers/scsi/3w-xxxx.c | 6 +++++- drivers/scsi/53c700.c | 7 +++++-- drivers/scsi/aacraid/linit.c | 6 +++++- drivers/scsi/arcmsr/arcmsr_hba.c | 5 ++++- drivers/scsi/hptiop.c | 5 ++++- drivers/scsi/ibmvscsi/ibmvfc.c | 7 ++++++- drivers/scsi/ibmvscsi/ibmvscsi.c | 7 ++++++- drivers/scsi/ipr.c | 7 ++++++- drivers/scsi/libfc/fc_fcp.c | 5 ++++- drivers/scsi/libiscsi.c | 5 ++++- drivers/scsi/libsas/sas_scsi_host.c | 6 +++++- drivers/scsi/megaraid/megaraid_mbox.c | 7 ++++++- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 10 +++++++--- drivers/scsi/pmcraid.c | 7 ++++++- drivers/scsi/qla2xxx/qla_os.c | 7 +++++-- drivers/scsi/scsi_sysfs.c | 3 ++- include/linux/libata.h | 2 +- include/scsi/libfc.h | 2 +- include/scsi/libiscsi.h | 3 ++- include/scsi/libsas.h | 3 ++- include/scsi/scsi_host.h | 8 +++++++- 27 files changed, 119 insertions(+), 32 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b4ee28dec52..5d52c2fcd07 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1208,6 +1208,7 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) * ata_scsi_change_queue_depth - SCSI callback for queue depth config * @sdev: SCSI device to configure queue depth for * @queue_depth: new queue depth + * @reason: calling context * * This is libata standard hostt->change_queue_depth callback. * SCSI will call into this callback when user tries to set queue @@ -1219,12 +1220,16 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) * RETURNS: * Newly configured queue depth. */ -int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) +int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth, + int reason) { struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev; unsigned long flags; + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (queue_depth < 1 || queue_depth == sdev->queue_depth) return sdev->queue_depth; diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 1eb4e020eb5..0c82d335c55 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -1975,7 +1975,7 @@ static int nv_swncq_slave_config(struct scsi_device *sdev) ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); if (strncmp(model_num, "Maxtor", 6) == 0) { - ata_scsi_change_queue_depth(sdev, 1); + ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT); ata_dev_printk(dev, KERN_NOTICE, "Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth); } diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index f68ec48a881..57752751712 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2351,11 +2351,12 @@ mptscsih_slave_destroy(struct scsi_device *sdev) * mptscsih_change_queue_depth - This function will set a devices queue depth * @sdev: per scsi_device pointer * @qdepth: requested queue depth + * @reason: calling context * * Adding support for new 'change_queue_depth' api. */ int -mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) +mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) { MPT_SCSI_HOST *hd = shost_priv(sdev->host); VirtTarget *vtarget; @@ -2367,6 +2368,9 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) starget = scsi_target(sdev); vtarget = starget->hostdata; + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (ioc->bus_type == SPI) { if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) max_depth = 1; @@ -2433,7 +2437,8 @@ mptscsih_slave_configure(struct scsi_device *sdev) ioc->name, vtarget->negoFlags, vtarget->maxOffset, vtarget->minSyncFactor)); - mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); + mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH, + SCSI_QDEPTH_DEFAULT); dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "tagged %d, simple %d, ordered %d\n", ioc->name,sdev->tagged_supported, sdev->simple_tags, diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index e0b33e04a33..45a5ff3eff6 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -128,7 +128,8 @@ extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_F extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); -extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); +extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, + int reason); extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); extern struct device_attribute *mptscsih_host_attrs[]; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 0e1a34627a2..ad115470172 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -29,8 +29,12 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu) return fcp_sns_info_ptr; } -static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth) +static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, + int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); return sdev->queue_depth; } diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 36c21b19e5d..2d16d49fd3c 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -186,8 +186,12 @@ static ssize_t twa_show_stats(struct device *dev, } /* End twa_show_stats() */ /* This function will set a devices queue depth */ -static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth) +static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth, + int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (queue_depth > TW_Q_LENGTH-2) queue_depth = TW_Q_LENGTH-2; scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index faa0fcfed71..d224294c38f 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -521,8 +521,12 @@ static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr, } /* End tw_show_stats() */ /* This function will set a devices queue depth */ -static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth) +static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth, + int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (queue_depth > TW_Q_LENGTH-2) queue_depth = TW_Q_LENGTH-2; scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index f5a9addb705..6c60a8060c5 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -175,7 +175,7 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host); STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt); STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt); STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt); -static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth); +static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth, int reason); static int NCR_700_change_queue_type(struct scsi_device *SDpnt, int depth); STATIC struct device_attribute *NCR_700_dev_attrs[]; @@ -2082,8 +2082,11 @@ NCR_700_slave_destroy(struct scsi_device *SDp) } static int -NCR_700_change_queue_depth(struct scsi_device *SDp, int depth) +NCR_700_change_queue_depth(struct scsi_device *SDp, int depth, int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (depth > NCR_700_MAX_TAGS) depth = NCR_700_MAX_TAGS; diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 9b97c3e016f..e9373a2d14f 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -472,8 +472,12 @@ static int aac_slave_configure(struct scsi_device *sdev) * total capacity and the queue depth supported by the target device. */ -static int aac_change_queue_depth(struct scsi_device *sdev, int depth) +static int aac_change_queue_depth(struct scsi_device *sdev, int depth, + int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && (sdev_channel(sdev) == CONTAINER_CHANNEL)) { struct scsi_device * dev; diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 80aac01b5a6..47d5d19f8c9 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -98,8 +98,11 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); static const char *arcmsr_info(struct Scsi_Host *); static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, - int queue_depth) + int queue_depth, int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (queue_depth > ARCMSR_MAX_CMD_PERLUN) queue_depth = ARCMSR_MAX_CMD_PERLUN; scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index a0e7e711ff9..901a3daeb36 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -861,10 +861,13 @@ static int hptiop_reset(struct scsi_cmnd *scp) } static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev, - int queue_depth) + int queue_depth, int reason) { struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata; + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (queue_depth > hba->max_requests) queue_depth = hba->max_requests; scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index bc9beb8c587..87b536a97cb 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2764,12 +2764,17 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev) * ibmvfc_change_queue_depth - Change the device's queue depth * @sdev: scsi device struct * @qdepth: depth to set + * @reason: calling context * * Return value: * actual depth set **/ -static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth) +static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth, + int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (qdepth > IBMVFC_MAX_CMDS_PER_LUN) qdepth = IBMVFC_MAX_CMDS_PER_LUN; diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index d9b0e9d3198..e475b7957c2 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1637,12 +1637,17 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev) * ibmvscsi_change_queue_depth - Change the device's queue depth * @sdev: scsi device struct * @qdepth: depth to set + * @reason: calling context * * Return value: * actual depth set **/ -static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth) +static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth, + int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN) qdepth = IBMVSCSI_MAX_CMDS_PER_LUN; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 5f045505a1f..d40d5c79fff 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3367,16 +3367,21 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; }; * ipr_change_queue_depth - Change the device's queue depth * @sdev: scsi device struct * @qdepth: depth to set + * @reason: calling context * * Return value: * actual depth set **/ -static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth) +static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth, + int reason) { struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata; struct ipr_resource_entry *res; unsigned long lock_flags = 0; + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); res = (struct ipr_resource_entry *)sdev->hostdata; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index a67f53a5026..beaab818d8d 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -2064,8 +2064,11 @@ int fc_slave_alloc(struct scsi_device *sdev) } EXPORT_SYMBOL(fc_slave_alloc); -int fc_change_queue_depth(struct scsi_device *sdev, int qdepth) +int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); return sdev->queue_depth; } diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index f1a4246f890..67d0f3fc8ac 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1643,8 +1643,11 @@ fault: } EXPORT_SYMBOL_GPL(iscsi_queuecommand); -int iscsi_change_queue_depth(struct scsi_device *sdev, int depth) +int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); return sdev->queue_depth; } diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 1c558d3bce1..14b13196b22 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -820,10 +820,14 @@ void sas_slave_destroy(struct scsi_device *scsi_dev) ata_port_disable(dev->sata_dev.ap); } -int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth) +int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth, + int reason) { int res = min(new_depth, SAS_MAX_QD); + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (scsi_dev->tagged_supported) scsi_adjust_queue_depth(scsi_dev, scsi_get_tag_type(scsi_dev), res); diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 234f0b7eb21..fd181c2a8ae 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -335,12 +335,17 @@ static struct device_attribute *megaraid_sdev_attrs[] = { * megaraid_change_queue_depth - Change the device's queue depth * @sdev: scsi device struct * @qdepth: depth to set + * @reason: calling context * * Return value: * actual depth set */ -static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth) +static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth, + int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (qdepth > MBOX_MAX_SCSI_CMDS) qdepth = MBOX_MAX_SCSI_CMDS; scsi_adjust_queue_depth(sdev, 0, qdepth); diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 8dc682f00fd..55ee014a7e0 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -1099,11 +1099,12 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, * _scsih_change_queue_depth - setting device queue depth * @sdev: scsi device struct * @qdepth: requested queue depth + * @reason: calling context * * Returns queue depth. */ static int -_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) +_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) { struct Scsi_Host *shost = sdev->host; int max_depth; @@ -1114,6 +1115,9 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) struct _sas_device *sas_device; unsigned long flags; + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + max_depth = shost->can_queue; /* limit max device queue for SATA to 32 */ @@ -1569,7 +1573,7 @@ _scsih_slave_configure(struct scsi_device *sdev) r_level, raid_device->handle, (unsigned long long)raid_device->wwid, raid_device->num_pds, ds); - _scsih_change_queue_depth(sdev, qdepth); + _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); return 0; } @@ -1615,7 +1619,7 @@ _scsih_slave_configure(struct scsi_device *sdev) _scsih_display_sata_capabilities(ioc, sas_device, sdev); } - _scsih_change_queue_depth(sdev, qdepth); + _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); if (ssp_target) sas_read_port_mode_page(sdev); diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index f7c70e2a822..86d158ee357 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -278,12 +278,17 @@ static void pmcraid_slave_destroy(struct scsi_device *scsi_dev) * pmcraid_change_queue_depth - Change the device's queue depth * @scsi_dev: scsi device struct * @depth: depth to set + * @reason: calling context * * Return value * actual depth set */ -static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth) +static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth, + int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (depth > PMCRAID_MAX_CMD_PER_LUN) depth = PMCRAID_MAX_CMD_PER_LUN; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ecf2a40d70b..d69744a62fe 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -138,7 +138,7 @@ static int qla2xxx_eh_target_reset(struct scsi_cmnd *); static int qla2xxx_eh_bus_reset(struct scsi_cmnd *); static int qla2xxx_eh_host_reset(struct scsi_cmnd *); -static int qla2x00_change_queue_depth(struct scsi_device *, int); +static int qla2x00_change_queue_depth(struct scsi_device *, int, int); static int qla2x00_change_queue_type(struct scsi_device *, int); struct scsi_host_template qla2xxx_driver_template = { @@ -1235,8 +1235,11 @@ qla2xxx_slave_destroy(struct scsi_device *sdev) } static int -qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth) +qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); return sdev->queue_depth; } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 5c7eb63a19d..a48782866b2 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -766,7 +766,8 @@ sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr, if (depth < 1) return -EINVAL; - retval = sht->change_queue_depth(sdev, depth); + retval = sht->change_queue_depth(sdev, depth, + SCSI_QDEPTH_DEFAULT); if (retval < 0) return retval; diff --git a/include/linux/libata.h b/include/linux/libata.h index 87698640c09..85df383fd4b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1023,7 +1023,7 @@ extern int ata_std_bios_param(struct scsi_device *sdev, extern int ata_scsi_slave_config(struct scsi_device *sdev); extern void ata_scsi_slave_destroy(struct scsi_device *sdev); extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, - int queue_depth); + int queue_depth, int reason); extern struct ata_device *ata_dev_pair(struct ata_device *adev); extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 1662d73d85a..9617f9365e4 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -919,7 +919,7 @@ int fc_slave_alloc(struct scsi_device *sdev); /* * Adjust the queue depth. */ -int fc_change_queue_depth(struct scsi_device *sdev, int qdepth); +int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason); /* * Change the tag type. diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index a72edd4ecee..2db2bc26b1e 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -333,7 +333,8 @@ struct iscsi_host { /* * scsi host template */ -extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth); +extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, + int reason); extern int iscsi_eh_abort(struct scsi_cmnd *sc); extern int iscsi_eh_target_reset(struct scsi_cmnd *sc); extern int iscsi_eh_device_reset(struct scsi_cmnd *sc); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index e78d3b62d8e..9eaa3f05f95 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -634,7 +634,8 @@ extern int sas_target_alloc(struct scsi_target *); extern int sas_slave_alloc(struct scsi_device *); extern int sas_slave_configure(struct scsi_device *); extern void sas_slave_destroy(struct scsi_device *); -extern int sas_change_queue_depth(struct scsi_device *, int new_depth); +extern int sas_change_queue_depth(struct scsi_device *, int new_depth, + int reason); extern int sas_change_queue_type(struct scsi_device *, int qt); extern int sas_bios_param(struct scsi_device *, struct block_device *, diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 6e728b17690..603054d8f40 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -43,6 +43,12 @@ struct blk_queue_tags; #define DISABLE_CLUSTERING 0 #define ENABLE_CLUSTERING 1 +enum { + SCSI_QDEPTH_DEFAULT, /* default requested change, e.g. from sysfs */ + SCSI_QDEPTH_QFULL, /* scsi-ml requested due to queue full */ + SCSI_QDEPTH_RAMP_UP, /* scsi-ml requested due to threshhold event */ +}; + struct scsi_host_template { struct module *module; const char *name; @@ -294,7 +300,7 @@ struct scsi_host_template { * * Status: OPTIONAL */ - int (* change_queue_depth)(struct scsi_device *, int); + int (* change_queue_depth)(struct scsi_device *, int, int); /* * Fill in this function to allow the changing of tag types -- cgit v1.2.3-70-g09d2 From 1a7b75ae719754c77ccd4d18b0d258ae5db38a25 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Tue, 3 Nov 2009 11:45:47 -0800 Subject: [SCSI] libfc: Move non-common routines and prototypes out of libfc.h This patch moves all non-common routines and function prototypes out of libfc.h and into the appropriate .c files. It makes these routines 'static' when necessary and removes any unnecessary EXPORT_SYMBOL statements. A result of moving the fc_exch_seq_send, fc_seq_els_rsp_send, fc_exch_alloc and fc_seq_start_next prototypes out of libfc.h is that they were no longer being imported into fc_exch.c when libfc.h was included. This caused errors where routines in fc_exch.c were looking for undefined symbols. To fix this this patch reorganizes fc_seq_alloc, fc_seq_start_next and fc_seq_start_next_locked. This move also made it so that fc_seq_start_next_locked did not need to be prototyped at the top of fc_exch.c. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 329 +++++++++++++++++++++++-------------------- include/scsi/libfc.h | 49 ------- 2 files changed, 177 insertions(+), 201 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 170cdf4bac9..659bb05287f 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -107,7 +107,6 @@ static void fc_seq_ls_rjt(struct fc_seq *, enum fc_els_rjt_reason, enum fc_els_rjt_explan); static void fc_exch_els_rec(struct fc_seq *, struct fc_frame *); static void fc_exch_els_rrq(struct fc_seq *, struct fc_frame *); -static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp); /* * Internal implementation notes. @@ -272,7 +271,6 @@ static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp, fh->fh_seq_cnt = htons(ep->seq.cnt); } - /* * Release a reference to an exchange. * If the refcnt goes to zero and the exchange is complete, it is freed. @@ -372,7 +370,104 @@ static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec) spin_unlock_bh(&ep->ex_lock); } -int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec) +/** + * send a frame using existing sequence and exchange. + */ +static int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, + struct fc_frame *fp) +{ + struct fc_exch *ep; + struct fc_frame_header *fh = fc_frame_header_get(fp); + int error; + u32 f_ctl; + + ep = fc_seq_exch(sp); + WARN_ON((ep->esb_stat & ESB_ST_SEQ_INIT) != ESB_ST_SEQ_INIT); + + f_ctl = ntoh24(fh->fh_f_ctl); + fc_exch_setup_hdr(ep, fp, f_ctl); + + /* + * update sequence count if this frame is carrying + * multiple FC frames when sequence offload is enabled + * by LLD. + */ + if (fr_max_payload(fp)) + sp->cnt += DIV_ROUND_UP((fr_len(fp) - sizeof(*fh)), + fr_max_payload(fp)); + else + sp->cnt++; + + /* + * Send the frame. + */ + error = lp->tt.frame_send(lp, fp); + + /* + * Update the exchange and sequence flags, + * assuming all frames for the sequence have been sent. + * We can only be called to send once for each sequence. + */ + spin_lock_bh(&ep->ex_lock); + ep->f_ctl = f_ctl & ~FC_FC_FIRST_SEQ; /* not first seq */ + if (f_ctl & (FC_FC_END_SEQ | FC_FC_SEQ_INIT)) + ep->esb_stat &= ~ESB_ST_SEQ_INIT; + spin_unlock_bh(&ep->ex_lock); + return error; +} + +/** + * fc_seq_alloc() - Allocate a sequence. + * @ep: Exchange pointer + * @seq_id: Sequence ID to allocate a sequence for + * + * We don't support multiple originated sequences on the same exchange. + * By implication, any previously originated sequence on this exchange + * is complete, and we reallocate the same sequence. + */ +static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id) +{ + struct fc_seq *sp; + + sp = &ep->seq; + sp->ssb_stat = 0; + sp->cnt = 0; + sp->id = seq_id; + return sp; +} + +static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp) +{ + struct fc_exch *ep = fc_seq_exch(sp); + + sp = fc_seq_alloc(ep, ep->seq_id++); + FC_EXCH_DBG(ep, "f_ctl %6x seq %2x\n", + ep->f_ctl, sp->id); + return sp; +} + +/** + * Allocate a new sequence on the same exchange as the supplied sequence. + * This will never return NULL. + */ +static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) +{ + struct fc_exch *ep = fc_seq_exch(sp); + + spin_lock_bh(&ep->ex_lock); + sp = fc_seq_start_next_locked(sp); + spin_unlock_bh(&ep->ex_lock); + + return sp; +} + +/** + * This function is for seq_exch_abort function pointer in + * struct libfc_function_template, see comment block on + * seq_exch_abort for description of this function. + */ +static int fc_seq_exch_abort(const struct fc_seq *req_sp, + unsigned int timer_msec) { struct fc_seq *sp; struct fc_exch *ep; @@ -472,24 +567,6 @@ done: fc_exch_release(ep); } -/* - * Allocate a sequence. - * - * We don't support multiple originated sequences on the same exchange. - * By implication, any previously originated sequence on this exchange - * is complete, and we reallocate the same sequence. - */ -static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id) -{ - struct fc_seq *sp; - - sp = &ep->seq; - sp->ssb_stat = 0; - sp->cnt = 0; - sp->id = seq_id; - return sp; -} - /** * fc_exch_em_alloc() - allocate an exchange from a specified EM. * @lport: ptr to the local port @@ -570,7 +647,8 @@ err: * EM is selected having either a NULL match function pointer * or call to match function returning true. */ -struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp) +static struct fc_exch *fc_exch_alloc(struct fc_lport *lport, + struct fc_frame *fp) { struct fc_exch_mgr_anchor *ema; struct fc_exch *ep; @@ -584,7 +662,6 @@ struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp) } return NULL; } -EXPORT_SYMBOL(fc_exch_alloc); /* * Lookup and hold an exchange. @@ -607,7 +684,13 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) return ep; } -void fc_exch_done(struct fc_seq *sp) + +/** + * fc_exch_done() - Indicate that an exchange/sequence tuple is complete and + * the memory allocated for the related objects may be freed. + * @sp: Sequence pointer + */ +static void fc_exch_done(struct fc_seq *sp) { struct fc_exch *ep = fc_seq_exch(sp); int rc; @@ -618,7 +701,6 @@ void fc_exch_done(struct fc_seq *sp) if (!rc) fc_exch_delete(ep); } -EXPORT_SYMBOL(fc_exch_done); /* * Allocate a new exchange as responder. @@ -821,76 +903,15 @@ static void fc_exch_set_addr(struct fc_exch *ep, } } -static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp) -{ - struct fc_exch *ep = fc_seq_exch(sp); - - sp = fc_seq_alloc(ep, ep->seq_id++); - FC_EXCH_DBG(ep, "f_ctl %6x seq %2x\n", - ep->f_ctl, sp->id); - return sp; -} -/* - * Allocate a new sequence on the same exchange as the supplied sequence. - * This will never return NULL. +/** + * fc_seq_els_rsp_send() - Send ELS response using mainly infomation + * in exchange and sequence in EM layer. + * @sp: Sequence pointer + * @els_cmd: ELS command + * @els_data: ELS data */ -struct fc_seq *fc_seq_start_next(struct fc_seq *sp) -{ - struct fc_exch *ep = fc_seq_exch(sp); - - spin_lock_bh(&ep->ex_lock); - sp = fc_seq_start_next_locked(sp); - spin_unlock_bh(&ep->ex_lock); - - return sp; -} -EXPORT_SYMBOL(fc_seq_start_next); - -int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, struct fc_frame *fp) -{ - struct fc_exch *ep; - struct fc_frame_header *fh = fc_frame_header_get(fp); - int error; - u32 f_ctl; - - ep = fc_seq_exch(sp); - WARN_ON((ep->esb_stat & ESB_ST_SEQ_INIT) != ESB_ST_SEQ_INIT); - - f_ctl = ntoh24(fh->fh_f_ctl); - fc_exch_setup_hdr(ep, fp, f_ctl); - - /* - * update sequence count if this frame is carrying - * multiple FC frames when sequence offload is enabled - * by LLD. - */ - if (fr_max_payload(fp)) - sp->cnt += DIV_ROUND_UP((fr_len(fp) - sizeof(*fh)), - fr_max_payload(fp)); - else - sp->cnt++; - - /* - * Send the frame. - */ - error = lp->tt.frame_send(lp, fp); - - /* - * Update the exchange and sequence flags, - * assuming all frames for the sequence have been sent. - * We can only be called to send once for each sequence. - */ - spin_lock_bh(&ep->ex_lock); - ep->f_ctl = f_ctl & ~FC_FC_FIRST_SEQ; /* not first seq */ - if (f_ctl & (FC_FC_END_SEQ | FC_FC_SEQ_INIT)) - ep->esb_stat &= ~ESB_ST_SEQ_INIT; - spin_unlock_bh(&ep->ex_lock); - return error; -} -EXPORT_SYMBOL(fc_seq_send); - -void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, - struct fc_seq_els_data *els_data) +static void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, + struct fc_seq_els_data *els_data) { switch (els_cmd) { case ELS_LS_RJT: @@ -909,7 +930,6 @@ void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, FC_EXCH_DBG(fc_seq_exch(sp), "Invalid ELS CMD:%x\n", els_cmd); } } -EXPORT_SYMBOL(fc_seq_els_rsp_send); /* * Send a sequence, which is also the last sequence in the exchange. @@ -1662,6 +1682,68 @@ cleanup: fc_exch_release(aborted_ep); } + +/** + * This function is for exch_seq_send function pointer in + * struct libfc_function_template, see comment block on + * exch_seq_send for description of this function. + */ +static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, + struct fc_frame *fp, + void (*resp)(struct fc_seq *, + struct fc_frame *fp, + void *arg), + void (*destructor)(struct fc_seq *, + void *), + void *arg, u32 timer_msec) +{ + struct fc_exch *ep; + struct fc_seq *sp = NULL; + struct fc_frame_header *fh; + int rc = 1; + + ep = fc_exch_alloc(lp, fp); + if (!ep) { + fc_frame_free(fp); + return NULL; + } + ep->esb_stat |= ESB_ST_SEQ_INIT; + fh = fc_frame_header_get(fp); + fc_exch_set_addr(ep, ntoh24(fh->fh_s_id), ntoh24(fh->fh_d_id)); + ep->resp = resp; + ep->destructor = destructor; + ep->arg = arg; + ep->r_a_tov = FC_DEF_R_A_TOV; + ep->lp = lp; + sp = &ep->seq; + + ep->fh_type = fh->fh_type; /* save for possbile timeout handling */ + ep->f_ctl = ntoh24(fh->fh_f_ctl); + fc_exch_setup_hdr(ep, fp, ep->f_ctl); + sp->cnt++; + + if (ep->xid <= lp->lro_xid) + fc_fcp_ddp_setup(fr_fsp(fp), ep->xid); + + if (unlikely(lp->tt.frame_send(lp, fp))) + goto err; + + if (timer_msec) + fc_exch_timer_set_locked(ep, timer_msec); + ep->f_ctl &= ~FC_FC_FIRST_SEQ; /* not first seq */ + + if (ep->f_ctl & FC_FC_SEQ_INIT) + ep->esb_stat &= ~ESB_ST_SEQ_INIT; + spin_unlock_bh(&ep->ex_lock); + return sp; +err: + rc = fc_exch_done_locked(ep); + spin_unlock_bh(&ep->ex_lock); + if (!rc) + fc_exch_delete(ep); + return NULL; +} + /* * Send ELS RRQ - Reinstate Recovery Qualifier. * This tells the remote port to stop blocking the use of @@ -1902,63 +1984,6 @@ void fc_exch_mgr_free(struct fc_lport *lport) } EXPORT_SYMBOL(fc_exch_mgr_free); - -struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, - struct fc_frame *fp, - void (*resp)(struct fc_seq *, - struct fc_frame *fp, - void *arg), - void (*destructor)(struct fc_seq *, void *), - void *arg, u32 timer_msec) -{ - struct fc_exch *ep; - struct fc_seq *sp = NULL; - struct fc_frame_header *fh; - int rc = 1; - - ep = fc_exch_alloc(lp, fp); - if (!ep) { - fc_frame_free(fp); - return NULL; - } - ep->esb_stat |= ESB_ST_SEQ_INIT; - fh = fc_frame_header_get(fp); - fc_exch_set_addr(ep, ntoh24(fh->fh_s_id), ntoh24(fh->fh_d_id)); - ep->resp = resp; - ep->destructor = destructor; - ep->arg = arg; - ep->r_a_tov = FC_DEF_R_A_TOV; - ep->lp = lp; - sp = &ep->seq; - - ep->fh_type = fh->fh_type; /* save for possbile timeout handling */ - ep->f_ctl = ntoh24(fh->fh_f_ctl); - fc_exch_setup_hdr(ep, fp, ep->f_ctl); - sp->cnt++; - - if (ep->xid <= lp->lro_xid) - fc_fcp_ddp_setup(fr_fsp(fp), ep->xid); - - if (unlikely(lp->tt.frame_send(lp, fp))) - goto err; - - if (timer_msec) - fc_exch_timer_set_locked(ep, timer_msec); - ep->f_ctl &= ~FC_FC_FIRST_SEQ; /* not first seq */ - - if (ep->f_ctl & FC_FC_SEQ_INIT) - ep->esb_stat &= ~ESB_ST_SEQ_INIT; - spin_unlock_bh(&ep->ex_lock); - return sp; -err: - rc = fc_exch_done_locked(ep); - spin_unlock_bh(&ep->ex_lock); - if (!rc) - fc_exch_delete(ep); - return NULL; -} -EXPORT_SYMBOL(fc_exch_seq_send); - /* * Receive a frame */ diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 9617f9365e4..f207b6cac06 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -1011,55 +1011,6 @@ void fc_exch_mgr_free(struct fc_lport *lport); */ void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp); -/* - * This function is for exch_seq_send function pointer in - * struct libfc_function_template, see comment block on - * exch_seq_send for description of this function. - */ -struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, - struct fc_frame *fp, - void (*resp)(struct fc_seq *sp, - struct fc_frame *fp, - void *arg), - void (*destructor)(struct fc_seq *sp, - void *arg), - void *arg, u32 timer_msec); - -/* - * send a frame using existing sequence and exchange. - */ -int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, struct fc_frame *fp); - -/* - * Send ELS response using mainly infomation - * in exchange and sequence in EM layer. - */ -void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, - struct fc_seq_els_data *els_data); - -/* - * This function is for seq_exch_abort function pointer in - * struct libfc_function_template, see comment block on - * seq_exch_abort for description of this function. - */ -int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec); - -/* - * Indicate that an exchange/sequence tuple is complete and the memory - * allocated for the related objects may be freed. - */ -void fc_exch_done(struct fc_seq *sp); - -/* - * Allocate a new exchange and sequence pair. - */ -struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp); -/* - * Start a new sequence on the same exchange as the supplied sequence. - */ -struct fc_seq *fc_seq_start_next(struct fc_seq *sp); - - /* * Reset all EMs of a lport, releasing its all sequences and * exchanges. If sid is non-zero, then reset only exchanges -- cgit v1.2.3-70-g09d2 From 255f6386b816b2bc0c251af0ee4985ad5a8461b7 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Tue, 3 Nov 2009 11:45:52 -0800 Subject: [SCSI] libfc: Remove fc_fcp_complete This function is never used, let's remove it. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 17 ----------------- include/scsi/libfc.h | 8 -------- 2 files changed, 25 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 479af9352a4..3ab08f8dfb2 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1874,23 +1874,6 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) fc_fcp_pkt_release(fsp); } -/** - * fc_fcp_complete() - complete processing of a fcp packet - * @fsp: fcp packet - * - * This function may sleep if a fsp timer is pending. - * The host lock must not be held by caller. - */ -void fc_fcp_complete(struct fc_fcp_pkt *fsp) -{ - if (fc_fcp_lock_pkt(fsp)) - return; - - fc_fcp_complete_locked(fsp); - fc_fcp_unlock_pkt(fsp); -} -EXPORT_SYMBOL(fc_fcp_complete); - /** * fc_eh_abort() - Abort a command * @sc_cmd: scsi command to abort diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index f207b6cac06..db2175da2da 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -887,14 +887,6 @@ int fc_fcp_init(struct fc_lport *); int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)); -/* - * complete processing of a fcp packet - * - * This function may sleep if a fsp timer is pending. - * The host lock must not be held by caller. - */ -void fc_fcp_complete(struct fc_fcp_pkt *fsp); - /* * Send an ABTS frame to the target device. The sc_cmd argument * is a pointer to the SCSI command to be aborted. -- cgit v1.2.3-70-g09d2 From 8866a5d9075b7129194576f5f810e85a693c40ba Mon Sep 17 00:00:00 2001 From: Robert Love Date: Tue, 3 Nov 2009 11:45:58 -0800 Subject: [SCSI] libfc: Add libfc/fc_libfc.[ch] for libfc internal routines include/scsi/libfc.h is currently loaded with common code shared between libfc's sub-modules as well as shared between libfc and fcoe. Previous patches attempted to move out non-common code. This patch creates two files for common libfc routines that will not be shared with fcoe, fnic or any other LLDs. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/Makefile | 1 + drivers/scsi/libfc/fc_disc.c | 2 + drivers/scsi/libfc/fc_exch.c | 2 + drivers/scsi/libfc/fc_fcp.c | 8 +--- drivers/scsi/libfc/fc_libfc.c | 35 +++++++++++++++ drivers/scsi/libfc/fc_libfc.h | 102 ++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libfc/fc_lport.c | 2 + drivers/scsi/libfc/fc_rport.c | 2 + include/scsi/libfc.h | 79 -------------------------------- 9 files changed, 147 insertions(+), 86 deletions(-) create mode 100644 drivers/scsi/libfc/fc_libfc.c create mode 100644 drivers/scsi/libfc/fc_libfc.h (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/Makefile b/drivers/scsi/libfc/Makefile index 55f982de3a9..2be549c1db7 100644 --- a/drivers/scsi/libfc/Makefile +++ b/drivers/scsi/libfc/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_LIBFC) += libfc.o libfc-objs := \ + fc_libfc.o \ fc_disc.o \ fc_exch.o \ fc_elsct.o \ diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index d4cb3f9b1a0..a4bdec28fef 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -40,6 +40,8 @@ #include +#include "fc_libfc.h" + #define FC_DISC_RETRY_LIMIT 3 /* max retries */ #define FC_DISC_RETRY_DELAY 500UL /* (msecs) delay */ diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 659bb05287f..ee6031e24c1 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -32,6 +32,8 @@ #include #include +#include "fc_libfc.h" + u16 fc_cpu_mask; /* cpu mask for possible cpus */ EXPORT_SYMBOL(fc_cpu_mask); static u16 fc_cpu_order; /* 2's power to represent total possible cpus */ diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 3ab08f8dfb2..8a31ced98bd 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -39,13 +39,7 @@ #include #include -MODULE_AUTHOR("Open-FCoE.org"); -MODULE_DESCRIPTION("libfc"); -MODULE_LICENSE("GPL v2"); - -unsigned int fc_debug_logging; -module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); +#include "fc_libfc.h" static struct kmem_cache *scsi_pkt_cachep; diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c new file mode 100644 index 00000000000..e64ea870a4c --- /dev/null +++ b/drivers/scsi/libfc/fc_libfc.c @@ -0,0 +1,35 @@ +/* + * Copyright(c) 2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#include +#include +#include +#include + +#include + +#include "fc_libfc.h" + +MODULE_AUTHOR("Open-FCoE.org"); +MODULE_DESCRIPTION("libfc"); +MODULE_LICENSE("GPL v2"); + +unsigned int fc_debug_logging; +module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h new file mode 100644 index 00000000000..388fae4364a --- /dev/null +++ b/drivers/scsi/libfc/fc_libfc.h @@ -0,0 +1,102 @@ +/* + * Copyright(c) 2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_LIBFC_H_ +#define _FC_LIBFC_H_ + +#define FC_LIBFC_LOGGING 0x01 /* General logging, not categorized */ +#define FC_LPORT_LOGGING 0x02 /* lport layer logging */ +#define FC_DISC_LOGGING 0x04 /* discovery layer logging */ +#define FC_RPORT_LOGGING 0x08 /* rport layer logging */ +#define FC_FCP_LOGGING 0x10 /* I/O path logging */ +#define FC_EM_LOGGING 0x20 /* Exchange Manager logging */ +#define FC_EXCH_LOGGING 0x40 /* Exchange/Sequence logging */ +#define FC_SCSI_LOGGING 0x80 /* SCSI logging (mostly error handling) */ + +extern unsigned int fc_debug_logging; + +#define FC_CHECK_LOGGING(LEVEL, CMD) \ +do { \ + if (unlikely(fc_debug_logging & LEVEL)) \ + do { \ + CMD; \ + } while (0); \ +} while (0) + +#define FC_LIBFC_DBG(fmt, args...) \ + FC_CHECK_LOGGING(FC_LIBFC_LOGGING, \ + printk(KERN_INFO "libfc: " fmt, ##args)) + +#define FC_LPORT_DBG(lport, fmt, args...) \ + FC_CHECK_LOGGING(FC_LPORT_LOGGING, \ + printk(KERN_INFO "host%u: lport %6x: " fmt, \ + (lport)->host->host_no, \ + fc_host_port_id((lport)->host), ##args)) + +#define FC_DISC_DBG(disc, fmt, args...) \ + FC_CHECK_LOGGING(FC_DISC_LOGGING, \ + printk(KERN_INFO "host%u: disc: " fmt, \ + (disc)->lport->host->host_no, \ + ##args)) + +#define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \ + FC_CHECK_LOGGING(FC_RPORT_LOGGING, \ + printk(KERN_INFO "host%u: rport %6x: " fmt, \ + (lport)->host->host_no, \ + (port_id), ##args)) + +#define FC_RPORT_DBG(rdata, fmt, args...) \ + FC_RPORT_ID_DBG((rdata)->local_port, (rdata)->ids.port_id, fmt, ##args) + +#define FC_FCP_DBG(pkt, fmt, args...) \ + FC_CHECK_LOGGING(FC_FCP_LOGGING, \ + printk(KERN_INFO "host%u: fcp: %6x: " fmt, \ + (pkt)->lp->host->host_no, \ + pkt->rport->port_id, ##args)) + +#define FC_EXCH_DBG(exch, fmt, args...) \ + FC_CHECK_LOGGING(FC_EXCH_LOGGING, \ + printk(KERN_INFO "host%u: xid %4x: " fmt, \ + (exch)->lp->host->host_no, \ + exch->xid, ##args)) + +#define FC_SCSI_DBG(lport, fmt, args...) \ + FC_CHECK_LOGGING(FC_SCSI_LOGGING, \ + printk(KERN_INFO "host%u: scsi: " fmt, \ + (lport)->host->host_no, ##args)) + +/* + * Set up direct-data placement for this I/O request + */ +void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid); + +/* + * Module setup functions + */ +int fc_setup_exch_mgr(void); +void fc_destroy_exch_mgr(void); +int fc_setup_rport(void); +void fc_destroy_rport(void); + +/* + * Internal libfc functions + */ +const char *fc_els_resp_type(struct fc_frame *); + +#endif /* _FC_LIBFC_H_ */ diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 536492ae6a8..f7f20a46e49 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -95,6 +95,8 @@ #include #include +#include "fc_libfc.h" + /* Fabric IDs to use for point-to-point mode, chosen on whims. */ #define FC_LOCAL_PTP_FID_LO 0x010101 #define FC_LOCAL_PTP_FID_HI 0x010102 diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 324e156b5d0..622285c81fe 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -55,6 +55,8 @@ #include #include +#include "fc_libfc.h" + struct workqueue_struct *rport_event_queue; static void fc_rport_enter_plogi(struct fc_rport_priv *); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index db2175da2da..690f8296e63 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -34,67 +34,6 @@ #include -#define FC_LIBFC_LOGGING 0x01 /* General logging, not categorized */ -#define FC_LPORT_LOGGING 0x02 /* lport layer logging */ -#define FC_DISC_LOGGING 0x04 /* discovery layer logging */ -#define FC_RPORT_LOGGING 0x08 /* rport layer logging */ -#define FC_FCP_LOGGING 0x10 /* I/O path logging */ -#define FC_EM_LOGGING 0x20 /* Exchange Manager logging */ -#define FC_EXCH_LOGGING 0x40 /* Exchange/Sequence logging */ -#define FC_SCSI_LOGGING 0x80 /* SCSI logging (mostly error handling) */ - -extern unsigned int fc_debug_logging; - -#define FC_CHECK_LOGGING(LEVEL, CMD) \ -do { \ - if (unlikely(fc_debug_logging & LEVEL)) \ - do { \ - CMD; \ - } while (0); \ -} while (0) - -#define FC_LIBFC_DBG(fmt, args...) \ - FC_CHECK_LOGGING(FC_LIBFC_LOGGING, \ - printk(KERN_INFO "libfc: " fmt, ##args)) - -#define FC_LPORT_DBG(lport, fmt, args...) \ - FC_CHECK_LOGGING(FC_LPORT_LOGGING, \ - printk(KERN_INFO "host%u: lport %6x: " fmt, \ - (lport)->host->host_no, \ - fc_host_port_id((lport)->host), ##args)) - -#define FC_DISC_DBG(disc, fmt, args...) \ - FC_CHECK_LOGGING(FC_DISC_LOGGING, \ - printk(KERN_INFO "host%u: disc: " fmt, \ - (disc)->lport->host->host_no, \ - ##args)) - -#define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \ - FC_CHECK_LOGGING(FC_RPORT_LOGGING, \ - printk(KERN_INFO "host%u: rport %6x: " fmt, \ - (lport)->host->host_no, \ - (port_id), ##args)) - -#define FC_RPORT_DBG(rdata, fmt, args...) \ - FC_RPORT_ID_DBG((rdata)->local_port, (rdata)->ids.port_id, fmt, ##args) - -#define FC_FCP_DBG(pkt, fmt, args...) \ - FC_CHECK_LOGGING(FC_FCP_LOGGING, \ - printk(KERN_INFO "host%u: fcp: %6x: " fmt, \ - (pkt)->lp->host->host_no, \ - pkt->rport->port_id, ##args)) - -#define FC_EXCH_DBG(exch, fmt, args...) \ - FC_CHECK_LOGGING(FC_EXCH_LOGGING, \ - printk(KERN_INFO "host%u: xid %4x: " fmt, \ - (exch)->lp->host->host_no, \ - exch->xid, ##args)) - -#define FC_SCSI_DBG(lport, fmt, args...) \ - FC_CHECK_LOGGING(FC_SCSI_LOGGING, \ - printk(KERN_INFO "host%u: scsi: " fmt, \ - (lport)->host->host_no, ##args)) - /* * libfc error codes */ @@ -923,11 +862,6 @@ 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 *****************************/ @@ -1020,17 +954,4 @@ void fc_get_host_port_state(struct Scsi_Host *shost); void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout); struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *); -/* - * module setup functions. - */ -int fc_setup_exch_mgr(void); -void fc_destroy_exch_mgr(void); -int fc_setup_rport(void); -void fc_destroy_rport(void); - -/* - * Internal libfc functions. - */ -const char *fc_els_resp_type(struct fc_frame *); - #endif /* _LIBFC_H_ */ -- cgit v1.2.3-70-g09d2 From 86221969e20a2f60ce104160dc836a964974673b Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 3 Nov 2009 11:46:08 -0800 Subject: [SCSI] libfc: changes to libfc_host_alloc to consolidate initialization with allocation I'd like to keep basic initialization together with allocation, which means this can't just be a tail-call to scsi_host_alloc. This is needed to create a generic libfc host allocation routine for NPIV VN_Ports, which will share the exchange ID space (through sharing exchange manager structures) with the parent lport. In order to clone the exchange manager list when the lport is allocated, the list head must be initialized earlier. Also, update fnic to use the libfc_host_alloc so that later changes do not break it. (contribution by Joe Eykholt) Signed-off-by: Chris Leech Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 8 +++----- drivers/scsi/fnic/fnic_main.c | 10 ++++------ drivers/scsi/libfc/fc_lport.c | 1 - include/scsi/libfc.h | 15 ++++++++++++--- 4 files changed, 19 insertions(+), 15 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 4efbc17a7d7..8ca488de492 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -515,8 +515,6 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, int rc = 0; /* lport scsi host config */ - lp->host = shost; - lp->host->max_lun = FCOE_MAX_LUN; lp->host->max_id = FCOE_MAX_FCP_TARGET; lp->host->max_channel = 0; @@ -734,14 +732,14 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, FCOE_NETDEV_DBG(netdev, "Create Interface\n"); - shost = libfc_host_alloc(&fcoe_shost_template, + lport = libfc_host_alloc(&fcoe_shost_template, sizeof(struct fcoe_port)); - if (!shost) { + if (!lport) { FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); rc = -ENOMEM; goto out; } - lport = shost_priv(shost); + shost = lport->host; port = lport_priv(lport); port->lport = lport; port->fcoe = fcoe; diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index fc61f17025c..018cc427504 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -424,15 +424,13 @@ static int __devinit fnic_probe(struct pci_dev *pdev, * Allocate SCSI Host and set up association between host, * local port, and fnic */ - host = scsi_host_alloc(&fnic_host_template, - sizeof(struct fc_lport) + sizeof(struct fnic)); - if (!host) { - printk(KERN_ERR PFX "Unable to alloc SCSI host\n"); + lp = libfc_host_alloc(&fnic_host_template, sizeof(struct fnic)); + if (!lp) { + printk(KERN_ERR PFX "Unable to alloc libfc local port\n"); err = -ENOMEM; goto err_out; } - lp = shost_priv(host); - lp->host = host; + host = lp->host; fnic = lport_priv(lp); fnic->lport = lp; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index f7f20a46e49..41650d33628 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1505,7 +1505,6 @@ int fc_lport_init(struct fc_lport *lport) if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT) fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT; - INIT_LIST_HEAD(&lport->ema_list); return 0; } EXPORT_SYMBOL(fc_lport_init); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 690f8296e63..ed3057b4e78 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -739,12 +739,21 @@ static inline void *lport_priv(const struct fc_lport *lp) * @sht: ptr to the scsi host templ * @priv_size: size of private data after fc_lport * - * Returns: ptr to Scsi_Host + * Returns: libfc lport */ -static inline struct Scsi_Host * +static inline struct fc_lport * libfc_host_alloc(struct scsi_host_template *sht, int priv_size) { - return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size); + struct fc_lport *lport; + struct Scsi_Host *shost; + + shost = scsi_host_alloc(sht, sizeof(*lport) + priv_size); + if (!shost) + return NULL; + lport = shost_priv(shost); + lport->host = shost; + INIT_LIST_HEAD(&lport->ema_list); + return lport; } /* -- cgit v1.2.3-70-g09d2 From 174e1ebffd30a7599b889900089f7acef944cc6b Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 3 Nov 2009 11:46:14 -0800 Subject: [SCSI] libfc: add some generic NPIV support routines to libfc Adds a function to create a new VN_Port instances, which share the EM list with the N_Port, VN_Port lookup by fabric ID when responding to a new request (otherwise the exchange lookup from the N_Ports EM list is trusted to return an exchange with a cached lport value for the correct VN_Port), a pointer to a fc_vport structure for VN_Ports, and flags to indicate if an N_Port supports NPIV and if the switch/fabric allows it. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/Makefile | 3 +- drivers/scsi/libfc/fc_exch.c | 29 +++++++++++++++ drivers/scsi/libfc/fc_npiv.c | 86 ++++++++++++++++++++++++++++++++++++++++++++ include/scsi/libfc.h | 20 +++++++++++ 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 drivers/scsi/libfc/fc_npiv.c (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/Makefile b/drivers/scsi/libfc/Makefile index 2be549c1db7..4bb23ac86a5 100644 --- a/drivers/scsi/libfc/Makefile +++ b/drivers/scsi/libfc/Makefile @@ -10,4 +10,5 @@ libfc-objs := \ fc_frame.o \ fc_lport.o \ fc_rport.o \ - fc_fcp.o + fc_fcp.o \ + fc_npiv.o diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index ee6031e24c1..751a485685d 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1134,6 +1134,15 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp, u32 f_ctl; enum fc_pf_rjt_reason reject; + /* We can have the wrong fc_lport at this point with NPIV, which is a + * problem now that we know a new exchange needs to be allocated + */ + lp = fc_vport_id_lookup(lp, ntoh24(fh->fh_d_id)); + if (!lp) { + fc_frame_free(fp); + return; + } + fr_seq(fp) = NULL; reject = fc_seq_lookup_recip(lp, mp, fp); if (reject == FC_RJT_NONE) { @@ -1900,6 +1909,26 @@ void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema) } EXPORT_SYMBOL(fc_exch_mgr_del); +/** + * fc_exch_mgr_list_clone() - share all exchange manager objects + * @src: source lport to clone exchange managers from + * @dst: new lport that takes references to all the exchange managers + */ +int fc_exch_mgr_list_clone(struct fc_lport *src, struct fc_lport *dst) +{ + struct fc_exch_mgr_anchor *ema, *tmp; + + list_for_each_entry(ema, &src->ema_list, ema_list) { + if (!fc_exch_mgr_add(dst, ema->mp, ema->match)) + goto err; + } + return 0; +err: + list_for_each_entry_safe(ema, tmp, &dst->ema_list, ema_list) + fc_exch_mgr_del(ema); + return -ENOMEM; +} + struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, enum fc_class class, u16 min_xid, u16 max_xid, diff --git a/drivers/scsi/libfc/fc_npiv.c b/drivers/scsi/libfc/fc_npiv.c new file mode 100644 index 00000000000..39f02c09a8d --- /dev/null +++ b/drivers/scsi/libfc/fc_npiv.c @@ -0,0 +1,86 @@ +/* + * Copyright(c) 2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +/* + * NPIV VN_Port helper functions for libfc + */ + +#include + +/** + * fc_vport_create() - Create a new NPIV vport instance + * @vport: fc_vport structure from scsi_transport_fc + * @privsize: driver private data size to allocate along with the Scsi_Host + */ + +struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize) +{ + struct Scsi_Host *shost = vport_to_shost(vport); + struct fc_lport *n_port = shost_priv(shost); + struct fc_lport *vn_port; + + vn_port = libfc_host_alloc(shost->hostt, privsize); + if (!vn_port) + goto err_out; + if (fc_exch_mgr_list_clone(n_port, vn_port)) + goto err_put; + + vn_port->vport = vport; + vport->dd_data = vn_port; + + mutex_lock(&n_port->lp_mutex); + list_add_tail(&vn_port->list, &n_port->vports); + mutex_unlock(&n_port->lp_mutex); + + return vn_port; + +err_put: + scsi_host_put(vn_port->host); +err_out: + return NULL; +} +EXPORT_SYMBOL(libfc_vport_create); + +/** + * fc_vport_id_lookup() - find NPIV lport that matches a given fabric ID + * @n_port: Top level N_Port which may have multiple NPIV VN_Ports + * @port_id: Fabric ID to find a match for + * + * Returns: matching lport pointer or NULL if there is no match + */ +struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id) +{ + struct fc_lport *lport = NULL; + struct fc_lport *vn_port; + + if (fc_host_port_id(n_port->host) == port_id) + return n_port; + + mutex_lock(&n_port->lp_mutex); + list_for_each_entry(vn_port, &n_port->vports, list) { + if (fc_host_port_id(vn_port->host) == port_id) { + lport = vn_port; + break; + } + } + mutex_unlock(&n_port->lp_mutex); + + return lport; +} + diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index ed3057b4e78..2c6d55de8cc 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -640,6 +640,8 @@ struct fc_lport { /* Associations */ struct Scsi_Host *host; struct list_head ema_list; + struct list_head vports; /* child vports if N_Port */ + struct fc_vport *vport; /* parent vport if VN_Port */ struct fc_rport_priv *dns_rp; struct fc_rport_priv *ptp_rp; void *scsi_priv; @@ -664,6 +666,8 @@ struct fc_lport { u32 seq_offload:1; /* seq offload supported */ u32 crc_offload:1; /* crc offload supported */ u32 lro_enabled:1; /* large receive offload */ + u32 does_npiv:1; /* supports multiple vports */ + u32 npiv_enabled:1; /* switch/fabric allows NPIV */ u32 mfs; /* max FC payload size */ unsigned int service_params; unsigned int e_d_tov; @@ -753,6 +757,7 @@ libfc_host_alloc(struct scsi_host_template *sht, int priv_size) lport = shost_priv(shost); lport->host = shost; INIT_LIST_HEAD(&lport->ema_list); + INIT_LIST_HEAD(&lport->vports); return lport; } @@ -805,6 +810,15 @@ int fc_lport_reset(struct fc_lport *); */ int fc_set_mfs(struct fc_lport *lp, u32 mfs); +/* + * Allocate a new lport struct for an NPIV VN_Port + */ +struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize); + +/* + * Find an NPIV VN_Port by port ID + */ +struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id); /* * REMOTE PORT LAYER @@ -911,6 +925,12 @@ struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport, */ void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema); +/* + * Clone an exchange manager list, getting reference holds for each EM. + * This is for use with NPIV and sharing the X_ID space between VN_Ports. + */ +int fc_exch_mgr_list_clone(struct fc_lport *src, struct fc_lport *dst); + /* * Allocates an Exchange Manager (EM). * -- cgit v1.2.3-70-g09d2 From 8faecddb212d502b1b77936498b9a82b13c4ff44 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 3 Nov 2009 11:46:19 -0800 Subject: [SCSI] libfc: vport link handling and fc_vport state managment NPIV vports are managed in libfc by changing their virtual link state when the parent N_Ports internal state changes. The vport link is only online when the N_Port is in a ready state (logged into the fabric). vport_state is updated as needed in this patch as well, currently the states LINKDOWN, INITIALIZING, ACTIVE, DSIABLED, and NO_FABRIC_SUPP are used. This also changes the fc_host port_state handling to differentiate between LINKDOWN and OFFLINE. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 72 ++++++++++++++++++++++++++++++++--------- drivers/scsi/libfc/fc_npiv.c | 75 +++++++++++++++++++++++++++++++++++++++++++ include/scsi/libfc.h | 8 +++++ 3 files changed, 140 insertions(+), 15 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 41650d33628..46897cf23ea 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -224,10 +224,18 @@ void fc_get_host_port_state(struct Scsi_Host *shost) { struct fc_lport *lp = shost_priv(shost); - if (lp->link_up) - fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; + mutex_lock(&lp->lp_mutex); + if (!lp->link_up) + fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; else - fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; + switch (lp->state) { + case LPORT_ST_READY: + fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; + break; + default: + fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; + } + mutex_unlock(&lp->lp_mutex); } EXPORT_SYMBOL(fc_get_host_port_state); @@ -493,40 +501,62 @@ int fc_fabric_login(struct fc_lport *lport) EXPORT_SYMBOL(fc_fabric_login); /** - * fc_linkup() - Handler for transport linkup events + * __fc_linkup() - Handler for transport linkup events * @lport: The lport whose link is up + * + * Locking: must be called with the lp_mutex held */ -void fc_linkup(struct fc_lport *lport) +void __fc_linkup(struct fc_lport *lport) { - printk(KERN_INFO "libfc: Link up on port (%6x)\n", - fc_host_port_id(lport->host)); - - mutex_lock(&lport->lp_mutex); if (!lport->link_up) { lport->link_up = 1; if (lport->state == LPORT_ST_RESET) fc_lport_enter_flogi(lport); } +} + +/** + * fc_linkup() - Handler for transport linkup events + * @lport: The lport whose link is up + */ +void fc_linkup(struct fc_lport *lport) +{ + printk(KERN_INFO "libfc: Link up on port (%6x)\n", + fc_host_port_id(lport->host)); + + mutex_lock(&lport->lp_mutex); + __fc_linkup(lport); mutex_unlock(&lport->lp_mutex); } EXPORT_SYMBOL(fc_linkup); /** - * fc_linkdown() - Handler for transport linkdown events + * __fc_linkdown() - Handler for transport linkdown events * @lport: The lport whose link is down + * + * Locking: must be called with the lp_mutex held */ -void fc_linkdown(struct fc_lport *lport) +void __fc_linkdown(struct fc_lport *lport) { - mutex_lock(&lport->lp_mutex); - printk(KERN_INFO "libfc: Link down on port (%6x)\n", - fc_host_port_id(lport->host)); - if (lport->link_up) { lport->link_up = 0; fc_lport_enter_reset(lport); lport->tt.fcp_cleanup(lport); } +} + +/** + * fc_linkdown() - Handler for transport linkdown events + * @lport: The lport whose link is down + */ +void fc_linkdown(struct fc_lport *lport) +{ + printk(KERN_INFO "libfc: Link down on port (%6x)\n", + fc_host_port_id(lport->host)); + + mutex_lock(&lport->lp_mutex); + __fc_linkdown(lport); mutex_unlock(&lport->lp_mutex); } EXPORT_SYMBOL(fc_linkdown); @@ -654,6 +684,9 @@ static void fc_lport_enter_ready(struct fc_lport *lport) fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_READY); + if (lport->vport) + fc_vport_set_state(lport->vport, FC_VPORT_ACTIVE); + fc_vports_linkchange(lport); if (!lport->ptp_rp) lport->tt.disc_start(fc_lport_disc_callback, lport); @@ -868,7 +901,14 @@ static void fc_lport_enter_reset(struct fc_lport *lport) FC_LPORT_DBG(lport, "Entered RESET state from %s state\n", fc_lport_state(lport)); + if (lport->vport) { + if (lport->link_up) + fc_vport_set_state(lport->vport, FC_VPORT_INITIALIZING); + else + fc_vport_set_state(lport->vport, FC_VPORT_LINKDOWN); + } fc_lport_state_enter(lport, LPORT_ST_RESET); + fc_vports_linkchange(lport); fc_lport_reset_locked(lport); if (lport->link_up) fc_lport_enter_flogi(lport); @@ -887,6 +927,7 @@ static void fc_lport_enter_disabled(struct fc_lport *lport) fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_DISABLED); + fc_vports_linkchange(lport); fc_lport_reset_locked(lport); } @@ -1333,6 +1374,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport) fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_LOGO); + fc_vports_linkchange(lport); fp = fc_frame_alloc(lport, sizeof(*logo)); if (!fp) { diff --git a/drivers/scsi/libfc/fc_npiv.c b/drivers/scsi/libfc/fc_npiv.c index 39f02c09a8d..c68f6c7341c 100644 --- a/drivers/scsi/libfc/fc_npiv.c +++ b/drivers/scsi/libfc/fc_npiv.c @@ -84,3 +84,78 @@ struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id) return lport; } +/* + * When setting the link state of vports during an lport state change, it's + * necessary to hold the lp_mutex of both the N_Port and the VN_Port. + * This tells the lockdep engine to treat the nested locking of the VN_Port + * as a different lock class. + */ +enum libfc_lport_mutex_class { + LPORT_MUTEX_NORMAL = 0, + LPORT_MUTEX_VN_PORT = 1, +}; + +/** + * __fc_vport_setlink() - update link and status on a VN_Port + * @n_port: parent N_Port + * @vn_port: VN_Port to update + * + * Locking: must be called with both the N_Port and VN_Port lp_mutex held + */ +static void __fc_vport_setlink(struct fc_lport *n_port, + struct fc_lport *vn_port) +{ + struct fc_vport *vport = vn_port->vport; + + if (vn_port->state == LPORT_ST_DISABLED) + return; + + if (n_port->state == LPORT_ST_READY) { + if (n_port->npiv_enabled) { + fc_vport_set_state(vport, FC_VPORT_INITIALIZING); + __fc_linkup(vn_port); + } else { + fc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP); + __fc_linkdown(vn_port); + } + } else { + fc_vport_set_state(vport, FC_VPORT_LINKDOWN); + __fc_linkdown(vn_port); + } +} + +/** + * fc_vport_setlink() - update link and status on a VN_Port + * @vn_port: virtual port to update + */ +void fc_vport_setlink(struct fc_lport *vn_port) +{ + struct fc_vport *vport = vn_port->vport; + struct Scsi_Host *shost = vport_to_shost(vport); + struct fc_lport *n_port = shost_priv(shost); + + mutex_lock(&n_port->lp_mutex); + mutex_lock_nested(&vn_port->lp_mutex, LPORT_MUTEX_VN_PORT); + __fc_vport_setlink(n_port, vn_port); + mutex_unlock(&vn_port->lp_mutex); + mutex_unlock(&n_port->lp_mutex); +} +EXPORT_SYMBOL(fc_vport_setlink); + +/** + * fc_vports_linkchange() - change the link state of all vports + * @n_port: Parent N_Port that has changed state + * + * Locking: called with the n_port lp_mutex held + */ +void fc_vports_linkchange(struct fc_lport *n_port) +{ + struct fc_lport *vn_port; + + list_for_each_entry(vn_port, &n_port->vports, list) { + mutex_lock_nested(&vn_port->lp_mutex, LPORT_MUTEX_VN_PORT); + __fc_vport_setlink(n_port, vn_port); + mutex_unlock(&vn_port->lp_mutex); + } +} + diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 2c6d55de8cc..dfeb1ee4f03 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -788,11 +788,13 @@ int fc_fabric_login(struct fc_lport *lp); /* * The link is up for the given local port. */ +void __fc_linkup(struct fc_lport *); void fc_linkup(struct fc_lport *); /* * Link is down for the given local port. */ +void __fc_linkdown(struct fc_lport *); void fc_linkdown(struct fc_lport *); /* @@ -820,6 +822,12 @@ struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize); */ struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id); +/* + * NPIV VN_Port link state management + */ +void fc_vport_setlink(struct fc_lport *vn_port); +void fc_vports_linkchange(struct fc_lport *n_port); + /* * REMOTE PORT LAYER *****************************/ -- cgit v1.2.3-70-g09d2 From 11b561886643d4e23d0fd58c205d830a448dd0a2 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 3 Nov 2009 11:46:29 -0800 Subject: [SCSI] libfcoe, fcoe: libfcoe NPIV support The FIP code in libfcoe needed several changes to support NPIV 1) dst_src_addr needs to be managed per-n_port-ID for FPMA fabrics with NPIV enabled. Managing the MAC address is now handled in fcoe, with some slight changes to update_mac() and a new get_src_addr() function pointer. 2) The libfc elsct_send() hook is used to setup FCoE specific response handlers for FIP encapsulated ELS exchanges. This lets the FCoE specific handling know which VN_Port the exchange is for, and doesn't require tracking OX_IDs. It might be possible to roll back to the full FIP frame in these, but for now I've just stashed the contents of the MAC address descriptor in the skb context block for later use. Also, because fcoe_elsct_send() just passes control on to fc_elsct_send(), all transmits still come through the normal frame_send() path. 3) The NPIV changes added a mutex hold in the keep alive sending, the lport mutex is protecting the vport list. We can't take a mutex from a timer, so move the FIP keep alive logic to the link work struct. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 147 ++++++++++++++++++++++++++++++++++++------ drivers/scsi/fcoe/fcoe.h | 1 + drivers/scsi/fcoe/libfcoe.c | 82 +++++++++++++---------- drivers/scsi/libfc/fc_elsct.c | 3 +- drivers/scsi/libfc/fc_lport.c | 6 +- include/scsi/fc_frame.h | 3 + include/scsi/libfc.h | 10 +++ include/scsi/libfcoe.h | 15 +++-- 8 files changed, 207 insertions(+), 60 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 8ca488de492..a64c398c981 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -226,7 +226,8 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, } static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb); -static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new); +static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr); +static u8 *fcoe_get_src_mac(struct fc_lport *lport); static void fcoe_destroy_work(struct work_struct *work); /** @@ -254,6 +255,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) fcoe_ctlr_init(&fcoe->ctlr); fcoe->ctlr.send = fcoe_fip_send; fcoe->ctlr.update_mac = fcoe_update_src_mac; + fcoe->ctlr.get_src_addr = fcoe_get_src_mac; fcoe_interface_setup(fcoe, netdev); @@ -286,8 +288,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) /* Delete secondary MAC addresses */ memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); dev_unicast_delete(netdev, flogi_maddr); - if (!is_zero_ether_addr(fip->data_src_addr)) - dev_unicast_delete(netdev, fip->data_src_addr); if (fip->spma) dev_unicast_delete(netdev, fip->ctl_src_addr); dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); @@ -369,25 +369,37 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) /** * fcoe_update_src_mac() - Update Ethernet MAC filters. - * @fip: FCoE controller. - * @old: Unicast MAC address to delete if the MAC is non-zero. - * @new: Unicast MAC address to add. + * @lport: libfc lport + * @addr: Unicast MAC address to add. * * Remove any previously-set unicast MAC filter. * Add secondary FCoE MAC address filter for our OUI. */ -static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) +static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) { - struct fcoe_interface *fcoe; + struct fcoe_port *port = lport_priv(lport); + struct fcoe_interface *fcoe = port->fcoe; - fcoe = fcoe_from_ctlr(fip); rtnl_lock(); - if (!is_zero_ether_addr(old)) - dev_unicast_delete(fcoe->netdev, old); - dev_unicast_add(fcoe->netdev, new); + if (!is_zero_ether_addr(port->data_src_addr)) + dev_unicast_delete(fcoe->netdev, port->data_src_addr); + if (!is_zero_ether_addr(addr)) + dev_unicast_add(fcoe->netdev, addr); + memcpy(port->data_src_addr, addr, ETH_ALEN); rtnl_unlock(); } +/** + * fcoe_get_src_mac() - return the Ethernet source address for an lport + * @lport: libfc lport + */ +static u8 *fcoe_get_src_mac(struct fc_lport *lport) +{ + struct fcoe_port *port = lport_priv(lport); + + return port->data_src_addr; +} + /** * fcoe_lport_config() - sets up the fc_lport * @lp: ptr to the fc_lport @@ -650,6 +662,11 @@ static void fcoe_if_destroy(struct fc_lport *lport) /* Free existing transmit skbs */ fcoe_clean_pending_queue(lport); + rtnl_lock(); + if (!is_zero_ether_addr(port->data_src_addr)) + dev_unicast_delete(netdev, port->data_src_addr); + rtnl_unlock(); + /* receives may not be stopped until after this */ fcoe_interface_put(fcoe); @@ -706,10 +723,16 @@ static int fcoe_ddp_done(struct fc_lport *lp, u16 xid) return 0; } +static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, + u32 did, struct fc_frame *fp, unsigned int op, + void (*resp)(struct fc_seq *, struct fc_frame *, void *), + void *arg, u32 timeout); + static struct libfc_function_template fcoe_libfc_fcn_templ = { .frame_send = fcoe_xmit, .ddp_setup = fcoe_ddp_setup, .ddp_done = fcoe_ddp_done, + .elsct_send = fcoe_elsct_send, }; /** @@ -1226,7 +1249,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) } if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && - fcoe_ctlr_els_send(&fcoe->ctlr, skb)) + fcoe_ctlr_els_send(&fcoe->ctlr, lp, skb)) return 0; sof = fr_sof(fp); @@ -1291,7 +1314,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); else - memcpy(eh->h_source, fcoe->ctlr.data_src_addr, ETH_ALEN); + memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); hp = (struct fcoe_hdr *)(eh + 1); memset(hp, 0, sizeof(*hp)); @@ -1464,11 +1487,6 @@ int fcoe_percpu_receive_thread(void *arg) } fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; } - if (unlikely(port->fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN) && - fcoe_ctlr_recv_flogi(&port->fcoe->ctlr, fp, mac)) { - fc_frame_free(fp); - continue; - } fc_exch_recv(lp, fp); } return 0; @@ -2061,3 +2079,94 @@ static void __exit fcoe_exit(void) fcoe_if_exit(); } module_exit(fcoe_exit); + +/** + * fcoe_flogi_resp() - FCoE specific FLOGI and FDISC response handler + * @seq: active sequence in the FLOGI or FDISC exchange + * @fp: response frame, or error encoded in a pointer (timeout) + * @arg: pointer the the fcoe_ctlr structure + * + * This handles MAC address managment for FCoE, then passes control on to + * the libfc FLOGI response handler. + */ +static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) +{ + struct fcoe_ctlr *fip = arg; + struct fc_exch *exch = fc_seq_exch(seq); + struct fc_lport *lport = exch->lp; + u8 *mac; + + if (IS_ERR(fp)) + goto done; + + mac = fr_cb(fp)->granted_mac; + if (is_zero_ether_addr(mac)) { + /* pre-FIP */ + mac = eth_hdr(&fp->skb)->h_source; + if (fcoe_ctlr_recv_flogi(fip, lport, fp, mac)) { + fc_frame_free(fp); + return; + } + } else { + /* FIP, libfcoe has already seen it */ + fip->update_mac(lport, fr_cb(fp)->granted_mac); + } +done: + fc_lport_flogi_resp(seq, fp, lport); +} + +/** + * fcoe_logo_resp() - FCoE specific LOGO response handler + * @seq: active sequence in the LOGO exchange + * @fp: response frame, or error encoded in a pointer (timeout) + * @arg: pointer the the fcoe_ctlr structure + * + * This handles MAC address managment for FCoE, then passes control on to + * the libfc LOGO response handler. + */ +static void fcoe_logo_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) +{ + struct fcoe_ctlr *fip = arg; + struct fc_exch *exch = fc_seq_exch(seq); + struct fc_lport *lport = exch->lp; + static u8 zero_mac[ETH_ALEN] = { 0 }; + + if (!IS_ERR(fp)) + fip->update_mac(lport, zero_mac); + fc_lport_logo_resp(seq, fp, lport); +} + +/** + * fcoe_elsct_send - FCoE specific ELS handler + * + * This does special case handling of FIP encapsualted ELS exchanges for FCoE, + * using FCoE specific response handlers and passing the FIP controller as + * the argument (the lport is still available from the exchange). + * + * Most of the work here is just handed off to the libfc routine. + */ +static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, + u32 did, struct fc_frame *fp, unsigned int op, + void (*resp)(struct fc_seq *, struct fc_frame *, void *), + void *arg, u32 timeout) +{ + struct fcoe_port *port = lport_priv(lport); + struct fcoe_interface *fcoe = port->fcoe; + struct fcoe_ctlr *fip = &fcoe->ctlr; + struct fc_frame_header *fh = fc_frame_header_get(fp); + + switch (op) { + case ELS_FLOGI: + case ELS_FDISC: + return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp, + fip, timeout); + case ELS_LOGO: + /* only hook onto fabric logouts, not port logouts */ + if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI) + break; + return fc_elsct_send(lport, did, fp, op, fcoe_logo_resp, + fip, timeout); + } + return fc_elsct_send(lport, did, fp, op, resp, arg, timeout); +} + diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index a123552847e..99dfa7c2aea 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h @@ -104,6 +104,7 @@ struct fcoe_port { u8 fcoe_pending_queue_active; struct timer_list timer; /* queue timer */ struct work_struct destroy_work; /* to prevent rtnl deadlocks */ + u8 data_src_addr[ETH_ALEN]; }; #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index d8ea04a2919..6a93ba96569 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -322,6 +322,7 @@ EXPORT_SYMBOL(fcoe_ctlr_link_down); /** * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF. * @fip: FCoE controller. + * @lport: libfc fc_lport to send from * @ports: 0 for controller keep-alive, 1 for port keep-alive. * @sa: source MAC address. * @@ -332,7 +333,9 @@ EXPORT_SYMBOL(fcoe_ctlr_link_down); * The source MAC is the assigned mapped source address. * The destination is the FCF's F-port. */ -static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) +static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, + struct fc_lport *lport, + int ports, u8 *sa) { struct sk_buff *skb; struct fip_kal { @@ -374,16 +377,14 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); - if (ports) { vn = (struct fip_vn_desc *)(kal + 1); vn->fd_desc.fip_dtype = FIP_DT_VN_ID; vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW; - memcpy(vn->fd_mac, fip->data_src_addr, ETH_ALEN); + memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN); hton24(vn->fd_fc_id, fc_host_port_id(lp->host)); put_unaligned_be64(lp->wwpn, &vn->fd_wwpn); } - skb_put(skb, len); skb->protocol = htons(ETH_P_FIP); skb_reset_mac_header(skb); @@ -394,6 +395,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) /** * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it. * @fip: FCoE controller. + * @lport: libfc fc_lport to use for the source address * @dtype: FIP descriptor type for the frame. * @skb: FCoE ELS frame including FC header but no FCoE headers. * @@ -405,7 +407,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) * Headroom includes the FIP encapsulation description, FIP header, and * Ethernet header. The tailroom is for the FIP MAC descriptor. */ -static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, +static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, u8 dtype, struct sk_buff *skb) { struct fip_encaps_head { @@ -450,7 +452,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, mac->fd_desc.fip_dtype = FIP_DT_MAC; mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) - memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN); + memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); else if (fip->spma) memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); @@ -463,6 +465,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, /** * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate. * @fip: FCoE controller. + * @lport: libfc fc_lport to send from * @skb: FCoE ELS frame including FC header but no FCoE headers. * * Returns a non-zero error code if the frame should not be sent. @@ -471,11 +474,13 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, * The caller must check that the length is a multiple of 4. * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). */ -int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) +int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, + struct sk_buff *skb) { struct fc_frame_header *fh; u16 old_xid; u8 op; + u8 mac[ETH_ALEN]; fh = (struct fc_frame_header *)skb->data; op = *(u8 *)(fh + 1); @@ -530,14 +535,15 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) * FLOGI. */ fip->flogi_oxid = FC_XID_UNKNOWN; - fc_fcoe_set_mac(fip->data_src_addr, fh->fh_s_id); + fc_fcoe_set_mac(mac, fh->fh_d_id); + fip->update_mac(lport, mac); return 0; default: if (fip->state != FIP_ST_ENABLED) goto drop; return 0; } - if (fcoe_ctlr_encaps(fip, op, skb)) + if (fcoe_ctlr_encaps(fip, lport, op, skb)) goto drop; fip->send(fip, skb); return -EINPROGRESS; @@ -796,7 +802,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) { struct fc_lport *lp = fip->lp; struct fip_header *fiph; - struct fc_frame *fp; + struct fc_frame *fp = (struct fc_frame *)skb; struct fc_frame_header *fh = NULL; struct fip_desc *desc; struct fip_encaps *els; @@ -835,6 +841,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) "in FIP ELS\n"); goto drop; } + memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); break; case FIP_DT_FLOGI: case FIP_DT_FDISC: @@ -865,13 +872,10 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) goto drop; els_op = *(u8 *)(fh + 1); - if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) && - sub == FIP_SC_REP && fip->flogi_oxid == ntohs(fh->fh_ox_id) && - els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) { + if (els_dtype == FIP_DT_FLOGI && sub == FIP_SC_REP && + fip->flogi_oxid == ntohs(fh->fh_ox_id) && + els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) fip->flogi_oxid = FC_XID_UNKNOWN; - fip->update_mac(fip, fip->data_src_addr, granted_mac); - memcpy(fip->data_src_addr, granted_mac, ETH_ALEN); - } /* * Convert skb into an fc_frame containing only the ELS. @@ -958,7 +962,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, if (dlen < sizeof(*vp)) return; if (compare_ether_addr(vp->fd_mac, - fip->data_src_addr) == 0 && + fip->get_src_addr(lp)) == 0 && get_unaligned_be64(&vp->fd_wwpn) == lp->wwpn && ntoh24(vp->fd_fc_id) == fc_host_port_id(lp->host)) desc_mask &= ~BIT(FIP_DT_VN_ID); @@ -1113,8 +1117,6 @@ static void fcoe_ctlr_timeout(unsigned long arg) struct fcoe_fcf *sel; struct fcoe_fcf *fcf; unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); - u8 send_ctlr_ka; - u8 send_port_ka; spin_lock_bh(&fip->lock); if (fip->state == FIP_ST_DISABLED) { @@ -1153,12 +1155,10 @@ static void fcoe_ctlr_timeout(unsigned long arg) schedule_work(&fip->link_work); } - send_ctlr_ka = 0; - send_port_ka = 0; if (sel) { if (time_after_eq(jiffies, fip->ctlr_ka_time)) { fip->ctlr_ka_time = jiffies + sel->fka_period; - send_ctlr_ka = 1; + fip->send_ctlr_ka = 1; } if (time_after(next_timer, fip->ctlr_ka_time)) next_timer = fip->ctlr_ka_time; @@ -1166,7 +1166,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) if (time_after_eq(jiffies, fip->port_ka_time)) { fip->port_ka_time += jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); - send_port_ka = 1; + fip->send_port_ka = 1; } if (time_after(next_timer, fip->port_ka_time)) next_timer = fip->port_ka_time; @@ -1176,12 +1176,9 @@ static void fcoe_ctlr_timeout(unsigned long arg) msecs_to_jiffies(FCOE_CTLR_START_DELAY); mod_timer(&fip->timer, next_timer); } + if (fip->send_ctlr_ka || fip->send_port_ka) + schedule_work(&fip->link_work); spin_unlock_bh(&fip->lock); - - if (send_ctlr_ka) - fcoe_ctlr_send_keep_alive(fip, 0, fip->ctl_src_addr); - if (send_port_ka) - fcoe_ctlr_send_keep_alive(fip, 1, fip->data_src_addr); } /** @@ -1196,6 +1193,8 @@ static void fcoe_ctlr_timeout(unsigned long arg) static void fcoe_ctlr_link_work(struct work_struct *work) { struct fcoe_ctlr *fip; + struct fc_lport *vport; + u8 *mac; int link; int last_link; @@ -1212,6 +1211,22 @@ static void fcoe_ctlr_link_work(struct work_struct *work) else fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT); } + + if (fip->send_ctlr_ka) { + fip->send_ctlr_ka = 0; + fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr); + } + if (fip->send_port_ka) { + fip->send_port_ka = 0; + mutex_lock(&fip->lp->lp_mutex); + mac = fip->get_src_addr(fip->lp); + fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac); + list_for_each_entry(vport, &fip->lp->vports, list) { + mac = fip->get_src_addr(vport); + fcoe_ctlr_send_keep_alive(fip, vport, 1, mac); + } + mutex_unlock(&fip->lp->lp_mutex); + } } /** @@ -1236,6 +1251,7 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) /** * fcoe_ctlr_recv_flogi() - snoop Pre-FIP receipt of FLOGI response or request. * @fip: FCoE controller. + * @lport: libfc fc_lport instance received on * @fp: FC frame. * @sa: Ethernet source MAC address from received FCoE frame. * @@ -1248,7 +1264,8 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) * * Return non-zero if the frame should not be delivered to libfc. */ -int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) +int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, + struct fc_frame *fp, u8 *sa) { struct fc_frame_header *fh; u8 op; @@ -1283,11 +1300,9 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) fip->map_dest = 0; } fip->flogi_oxid = FC_XID_UNKNOWN; - memcpy(mac, fip->data_src_addr, ETH_ALEN); - fc_fcoe_set_mac(fip->data_src_addr, fh->fh_d_id); + fc_fcoe_set_mac(mac, fh->fh_d_id); + fip->update_mac(lport, mac); spin_unlock_bh(&fip->lock); - - fip->update_mac(fip, mac, fip->data_src_addr); } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) { /* * Save source MAC for point-to-point responses. @@ -1370,3 +1385,4 @@ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) return 0; } EXPORT_SYMBOL_GPL(fcoe_libfc_config); + diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index 92984587ff4..aae54fe3b29 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -31,7 +31,7 @@ /* * fc_elsct_send - sends ELS/CT frame */ -static struct fc_seq *fc_elsct_send(struct fc_lport *lport, +struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did, struct fc_frame *fp, unsigned int op, @@ -63,6 +63,7 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport, return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); } +EXPORT_SYMBOL(fc_elsct_send); int fc_elsct_init(struct fc_lport *lport) { diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index ccba67ca68a..807f5b3e4ef 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1320,7 +1320,7 @@ static void fc_lport_timeout(struct work_struct *work) * held, but it will lock, call an _enter_* function or fc_lport_error * and then unlock the lport. */ -static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, +void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg) { struct fc_lport *lport = lp_arg; @@ -1357,6 +1357,7 @@ out: err: mutex_unlock(&lport->lp_mutex); } +EXPORT_SYMBOL(fc_lport_logo_resp); /** * fc_rport_enter_logo() - Logout of the fabric @@ -1397,7 +1398,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport) * held, but it will lock, call an _enter_* function or fc_lport_error * and then unlock the lport. */ -static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, +void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg) { struct fc_lport *lport = lp_arg; @@ -1480,6 +1481,7 @@ out: err: mutex_unlock(&lport->lp_mutex); } +EXPORT_SYMBOL(fc_lport_flogi_resp); /** * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h index 148126dcf9e..ab2f8d41761 100644 --- a/include/scsi/fc_frame.h +++ b/include/scsi/fc_frame.h @@ -28,6 +28,8 @@ #include #include +#include + /* * The fc_frame interface is used to pass frame data between functions. * The frame includes the data buffer, length, and SOF / EOF delimiter types. @@ -67,6 +69,7 @@ struct fcoe_rcv_info { enum fc_sof fr_sof; /* start of frame delimiter */ enum fc_eof fr_eof; /* end of frame delimiter */ u8 fr_flags; /* flags - see below */ + u8 granted_mac[ETH_ALEN]; /* FCoE MAC address */ }; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index dfeb1ee4f03..dad66ce8673 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -900,6 +900,16 @@ void fc_fcp_destroy(struct fc_lport *); * Initializes ELS/CT interface */ int fc_elsct_init(struct fc_lport *lp); +struct fc_seq *fc_elsct_send(struct fc_lport *lport, + u32 did, + struct fc_frame *fp, + unsigned int op, + void (*resp)(struct fc_seq *, + struct fc_frame *fp, + void *arg), + void *arg, u32 timer_msec); +void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); +void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); /* diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index b2410605b74..8ef5e209c21 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -74,11 +74,13 @@ enum fip_state { * @last_link: last link state reported to libfc. * @map_dest: use the FC_MAP mode for destination MAC addresses. * @spma: supports SPMA server-provided MACs mode + * @send_ctlr_ka: need to send controller keep alive + * @send_port_ka: need to send port keep alives * @dest_addr: MAC address of the selected FC forwarder. * @ctl_src_addr: the native MAC address of our local port. - * @data_src_addr: the assigned MAC address for the local port after FLOGI. * @send: LLD-supplied function to handle sending of FIP Ethernet frames. * @update_mac: LLD-supplied function to handle changes to MAC addresses. + * @get_src_addr: LLD-supplied function to supply a source MAC address. * @lock: lock protecting this structure. * * This structure is used by all FCoE drivers. It contains information @@ -106,12 +108,14 @@ struct fcoe_ctlr { u8 last_link; u8 map_dest; u8 spma; + u8 send_ctlr_ka; + u8 send_port_ka; u8 dest_addr[ETH_ALEN]; u8 ctl_src_addr[ETH_ALEN]; - u8 data_src_addr[ETH_ALEN]; void (*send)(struct fcoe_ctlr *, struct sk_buff *); - void (*update_mac)(struct fcoe_ctlr *, u8 *old, u8 *new); + void (*update_mac)(struct fc_lport *, u8 *addr); + u8 * (*get_src_addr)(struct fc_lport *); spinlock_t lock; }; @@ -155,9 +159,10 @@ void fcoe_ctlr_init(struct fcoe_ctlr *); void fcoe_ctlr_destroy(struct fcoe_ctlr *); void fcoe_ctlr_link_up(struct fcoe_ctlr *); int fcoe_ctlr_link_down(struct fcoe_ctlr *); -int fcoe_ctlr_els_send(struct fcoe_ctlr *, struct sk_buff *); +int fcoe_ctlr_els_send(struct fcoe_ctlr *, struct fc_lport *, struct sk_buff *); void fcoe_ctlr_recv(struct fcoe_ctlr *, struct sk_buff *); -int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_frame *fp, u8 *sa); +int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_lport *lport, + struct fc_frame *fp, u8 *sa); /* libfcoe funcs */ u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); -- cgit v1.2.3-70-g09d2 From 28cc0e31d874af05244da421e05565f2ba72fd5c Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 3 Nov 2009 11:46:46 -0800 Subject: [SCSI] libfc: RPN_ID is obsolete and unnecessary RPN_ID has been obsolete per FC-GS-5 for several years. The port name is registered implicitly as part of FLOGI, and it is undesirable for ports to change a registered port name using RPN_ID while logged into the fabric. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 95 ++----------------------------------------- include/scsi/libfc.h | 1 - 2 files changed, 3 insertions(+), 93 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 807f5b3e4ef..47577e4a2e8 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -108,7 +108,6 @@ static void fc_lport_error(struct fc_lport *, struct fc_frame *); static void fc_lport_enter_reset(struct fc_lport *); static void fc_lport_enter_flogi(struct fc_lport *); static void fc_lport_enter_dns(struct fc_lport *); -static void fc_lport_enter_rpn_id(struct fc_lport *); static void fc_lport_enter_rft_id(struct fc_lport *); static void fc_lport_enter_scr(struct fc_lport *); static void fc_lport_enter_ready(struct fc_lport *); @@ -118,7 +117,6 @@ static const char *fc_lport_state_names[] = { [LPORT_ST_DISABLED] = "disabled", [LPORT_ST_FLOGI] = "FLOGI", [LPORT_ST_DNS] = "dNS", - [LPORT_ST_RPN_ID] = "RPN_ID", [LPORT_ST_RFT_ID] = "RFT_ID", [LPORT_ST_SCR] = "SCR", [LPORT_ST_READY] = "Ready", @@ -153,7 +151,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, case RPORT_EV_READY: if (lport->state == LPORT_ST_DNS) { lport->dns_rp = rdata; - fc_lport_enter_rpn_id(lport); + fc_lport_enter_rft_id(lport); } else { FC_LPORT_DBG(lport, "Received an READY event " "on port (%6x) for the directory " @@ -965,7 +963,6 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) case LPORT_ST_DISABLED: case LPORT_ST_READY: case LPORT_ST_RESET: - case LPORT_ST_RPN_ID: case LPORT_ST_RFT_ID: case LPORT_ST_SCR: case LPORT_ST_DNS: @@ -980,8 +977,8 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) /** * fc_lport_rft_id_resp() - Handle response to Register Fibre - * Channel Types by ID (RPN_ID) request - * @sp: current sequence in RPN_ID exchange + * Channel Types by ID (RFT_ID) request + * @sp: current sequence in RFT_ID exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance * @@ -1032,60 +1029,6 @@ err: mutex_unlock(&lport->lp_mutex); } -/** - * fc_lport_rpn_id_resp() - Handle response to Register Port - * Name by ID (RPN_ID) request - * @sp: current sequence in RPN_ID exchange - * @fp: response frame - * @lp_arg: Fibre Channel host port instance - * - * Locking Note: This function will be called without the lport lock - * held, but it will lock, call an _enter_* function or fc_lport_error - * and then unlock the lport. - */ -static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, - void *lp_arg) -{ - struct fc_lport *lport = lp_arg; - struct fc_frame_header *fh; - struct fc_ct_hdr *ct; - - FC_LPORT_DBG(lport, "Received a RPN_ID %s\n", fc_els_resp_type(fp)); - - if (fp == ERR_PTR(-FC_EX_CLOSED)) - return; - - mutex_lock(&lport->lp_mutex); - - if (lport->state != LPORT_ST_RPN_ID) { - FC_LPORT_DBG(lport, "Received a RPN_ID response, but in state " - "%s\n", fc_lport_state(lport)); - if (IS_ERR(fp)) - goto err; - goto out; - } - - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - - fh = fc_frame_header_get(fp); - ct = fc_frame_payload_get(fp, sizeof(*ct)); - if (fh && ct && fh->fh_type == FC_TYPE_CT && - ct->ct_fs_type == FC_FST_DIR && - ct->ct_fs_subtype == FC_NS_SUBTYPE && - ntohs(ct->ct_cmd) == FC_FS_ACC) - fc_lport_enter_rft_id(lport); - else - fc_lport_error(lport, fp); - -out: - fc_frame_free(fp); -err: - mutex_unlock(&lport->lp_mutex); -} - /** * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request * @sp: current sequence in SCR exchange @@ -1203,35 +1146,6 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport) fc_lport_error(lport, fp); } -/** - * fc_rport_enter_rft_id() - Register port name with the name server - * @lport: Fibre Channel local port to register - * - * Locking Note: The lport lock is expected to be held before calling - * this routine. - */ -static void fc_lport_enter_rpn_id(struct fc_lport *lport) -{ - struct fc_frame *fp; - - FC_LPORT_DBG(lport, "Entered RPN_ID state from %s state\n", - fc_lport_state(lport)); - - fc_lport_state_enter(lport, LPORT_ST_RPN_ID); - - fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) + - sizeof(struct fc_ns_rn_id)); - if (!fp) { - fc_lport_error(lport, fp); - return; - } - - if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RPN_ID, - fc_lport_rpn_id_resp, - lport, lport->e_d_tov)) - fc_lport_error(lport, NULL); -} - static struct fc_rport_operations fc_lport_rport_ops = { .event_callback = fc_lport_rport_callback, }; @@ -1293,9 +1207,6 @@ static void fc_lport_timeout(struct work_struct *work) case LPORT_ST_DNS: fc_lport_enter_dns(lport); break; - case LPORT_ST_RPN_ID: - fc_lport_enter_rpn_id(lport); - break; case LPORT_ST_RFT_ID: fc_lport_enter_rft_id(lport); break; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index dad66ce8673..75be713ea03 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -61,7 +61,6 @@ enum fc_lport_state { LPORT_ST_DISABLED = 0, LPORT_ST_FLOGI, LPORT_ST_DNS, - LPORT_ST_RPN_ID, LPORT_ST_RFT_ID, LPORT_ST_SCR, LPORT_ST_READY, -- cgit v1.2.3-70-g09d2 From c9c7bd7a5e7321aa96289c9b48fdbcc828c105e6 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 3 Nov 2009 11:46:51 -0800 Subject: [SCSI] libfc: RNN_ID may be required before RSNN_NN with some switches One could interpret FC-GS-5 to say that an explicit RNN_ID is required before RSNN_NN is allowed to succeed, which is why RNN_ID was not obsoleted along with RPN_ID acording to this document: ftp://ftp.t11.org/t11/member/fc/gs-5/05-546v2.pdf Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 91 ++++++++++++++++++++++++++++++++++++++++++- include/scsi/fc_encode.h | 4 +- include/scsi/libfc.h | 1 + 3 files changed, 93 insertions(+), 3 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 47577e4a2e8..897b5a8487e 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -108,6 +108,7 @@ static void fc_lport_error(struct fc_lport *, struct fc_frame *); static void fc_lport_enter_reset(struct fc_lport *); static void fc_lport_enter_flogi(struct fc_lport *); static void fc_lport_enter_dns(struct fc_lport *); +static void fc_lport_enter_rnn_id(struct fc_lport *); static void fc_lport_enter_rft_id(struct fc_lport *); static void fc_lport_enter_scr(struct fc_lport *); static void fc_lport_enter_ready(struct fc_lport *); @@ -117,6 +118,7 @@ static const char *fc_lport_state_names[] = { [LPORT_ST_DISABLED] = "disabled", [LPORT_ST_FLOGI] = "FLOGI", [LPORT_ST_DNS] = "dNS", + [LPORT_ST_RNN_ID] = "RNN_ID", [LPORT_ST_RFT_ID] = "RFT_ID", [LPORT_ST_SCR] = "SCR", [LPORT_ST_READY] = "Ready", @@ -151,7 +153,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, case RPORT_EV_READY: if (lport->state == LPORT_ST_DNS) { lport->dns_rp = rdata; - fc_lport_enter_rft_id(lport); + fc_lport_enter_rnn_id(lport); } else { FC_LPORT_DBG(lport, "Received an READY event " "on port (%6x) for the directory " @@ -963,6 +965,7 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) case LPORT_ST_DISABLED: case LPORT_ST_READY: case LPORT_ST_RESET: + case LPORT_ST_RNN_ID: case LPORT_ST_RFT_ID: case LPORT_ST_SCR: case LPORT_ST_DNS: @@ -1029,6 +1032,60 @@ err: mutex_unlock(&lport->lp_mutex); } +/** + * fc_lport_rnn_id_resp() - Handle response to Register Node + * Name by ID (RNN_ID) request + * @sp: current sequence in RNN_ID exchange + * @fp: response frame + * @lp_arg: Fibre Channel host port instance + * + * Locking Note: This function will be called without the lport lock + * held, but it will lock, call an _enter_* function or fc_lport_error + * and then unlock the lport. + */ +static void fc_lport_rnn_id_resp(struct fc_seq *sp, struct fc_frame *fp, + void *lp_arg) +{ + struct fc_lport *lport = lp_arg; + struct fc_frame_header *fh; + struct fc_ct_hdr *ct; + + FC_LPORT_DBG(lport, "Received a RNN_ID %s\n", fc_els_resp_type(fp)); + + if (fp == ERR_PTR(-FC_EX_CLOSED)) + return; + + mutex_lock(&lport->lp_mutex); + + if (lport->state != LPORT_ST_RNN_ID) { + FC_LPORT_DBG(lport, "Received a RNN_ID response, but in state " + "%s\n", fc_lport_state(lport)); + if (IS_ERR(fp)) + goto err; + goto out; + } + + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + + fh = fc_frame_header_get(fp); + ct = fc_frame_payload_get(fp, sizeof(*ct)); + if (fh && ct && fh->fh_type == FC_TYPE_CT && + ct->ct_fs_type == FC_FST_DIR && + ct->ct_fs_subtype == FC_NS_SUBTYPE && + ntohs(ct->ct_cmd) == FC_FS_ACC) + fc_lport_enter_rft_id(lport); + else + fc_lport_error(lport, fp); + +out: + fc_frame_free(fp); +err: + mutex_unlock(&lport->lp_mutex); +} + /** * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request * @sp: current sequence in SCR exchange @@ -1146,6 +1203,35 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport) fc_lport_error(lport, fp); } +/** + * fc_rport_enter_rnn_id() - Register node name with the name server + * @lport: Fibre Channel local port to register + * + * Locking Note: The lport lock is expected to be held before calling + * this routine. + */ +static void fc_lport_enter_rnn_id(struct fc_lport *lport) +{ + struct fc_frame *fp; + + FC_LPORT_DBG(lport, "Entered RNN_ID state from %s state\n", + fc_lport_state(lport)); + + fc_lport_state_enter(lport, LPORT_ST_RNN_ID); + + fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) + + sizeof(struct fc_ns_rn_id)); + if (!fp) { + fc_lport_error(lport, fp); + return; + } + + if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RNN_ID, + fc_lport_rnn_id_resp, + lport, lport->e_d_tov)) + fc_lport_error(lport, fp); +} + static struct fc_rport_operations fc_lport_rport_ops = { .event_callback = fc_lport_rport_callback, }; @@ -1207,6 +1293,9 @@ static void fc_lport_timeout(struct work_struct *work) case LPORT_ST_DNS: fc_lport_enter_dns(lport); break; + case LPORT_ST_RNN_ID: + fc_lport_enter_rnn_id(lport); + break; case LPORT_ST_RFT_ID: fc_lport_enter_rft_id(lport); break; diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h index c93ca3ece1a..ad13cb1c3ee 100644 --- a/include/scsi/fc_encode.h +++ b/include/scsi/fc_encode.h @@ -128,12 +128,12 @@ static inline int fc_ct_fill(struct fc_lport *lport, ct->payload.rft.fts = lport->fcts; break; - case FC_NS_RPN_ID: + case FC_NS_RNN_ID: ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id)); hton24(ct->payload.rn.fr_fid.fp_fid, fc_host_port_id(lport->host)); ct->payload.rft.fts = lport->fcts; - put_unaligned_be64(lport->wwpn, &ct->payload.rn.fr_wwn); + put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn); break; default: diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 75be713ea03..3d22dfd6720 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -61,6 +61,7 @@ enum fc_lport_state { LPORT_ST_DISABLED = 0, LPORT_ST_FLOGI, LPORT_ST_DNS, + LPORT_ST_RNN_ID, LPORT_ST_RFT_ID, LPORT_ST_SCR, LPORT_ST_READY, -- cgit v1.2.3-70-g09d2 From 5baa17c3e66fc2e414f501b2dd59b962dfc64919 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 3 Nov 2009 11:46:56 -0800 Subject: [SCSI] libfc: Register Symbolic Node Name (RSNN_NN) Register the fc_host symbolic name as the symbolic node name with the fabric name server. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 6 +-- drivers/scsi/libfc/fc_lport.c | 91 +++++++++++++++++++++++++++++++++++++++++++ include/scsi/fc/fc_ns.h | 10 +++++ include/scsi/fc_encode.h | 10 +++++ include/scsi/libfc.h | 1 + 5 files changed, 115 insertions(+), 3 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index f23cdb38d5c..437eacf2732 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -591,9 +591,9 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, if (!lp->vport) fc_host_max_npiv_vports(lp->host) = USHORT_MAX; - sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s", - FCOE_NAME, FCOE_VERSION, - fcoe_netdev(lp)->name); + snprintf(fc_host_symbolic_name(lp->host), FC_SYMBOLIC_NAME_SIZE, + "%s v%s over %s", FCOE_NAME, FCOE_VERSION, + fcoe_netdev(lp)->name); return 0; } diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 897b5a8487e..cc389c03f69 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -109,6 +109,7 @@ static void fc_lport_enter_reset(struct fc_lport *); static void fc_lport_enter_flogi(struct fc_lport *); static void fc_lport_enter_dns(struct fc_lport *); static void fc_lport_enter_rnn_id(struct fc_lport *); +static void fc_lport_enter_rsnn_nn(struct fc_lport *); static void fc_lport_enter_rft_id(struct fc_lport *); static void fc_lport_enter_scr(struct fc_lport *); static void fc_lport_enter_ready(struct fc_lport *); @@ -119,6 +120,7 @@ static const char *fc_lport_state_names[] = { [LPORT_ST_FLOGI] = "FLOGI", [LPORT_ST_DNS] = "dNS", [LPORT_ST_RNN_ID] = "RNN_ID", + [LPORT_ST_RSNN_NN] = "RSNN_NN", [LPORT_ST_RFT_ID] = "RFT_ID", [LPORT_ST_SCR] = "SCR", [LPORT_ST_READY] = "Ready", @@ -966,6 +968,7 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) case LPORT_ST_READY: case LPORT_ST_RESET: case LPORT_ST_RNN_ID: + case LPORT_ST_RSNN_NN: case LPORT_ST_RFT_ID: case LPORT_ST_SCR: case LPORT_ST_DNS: @@ -1032,6 +1035,60 @@ err: mutex_unlock(&lport->lp_mutex); } +/** + * fc_lport_rsnn_nn_resp() - Handle response to Register Symbolic Node Name + * by Node Name (RSNN_NN) request + * @sp: current sequence in RSNN_NN exchange + * @fp: response frame + * @lp_arg: Fibre Channel host port instance + * + * Locking Note: This function will be called without the lport lock + * held, but it will lock, call an _enter_* function or fc_lport_error + * and then unlock the lport. + */ +static void fc_lport_rsnn_nn_resp(struct fc_seq *sp, struct fc_frame *fp, + void *lp_arg) +{ + struct fc_lport *lport = lp_arg; + struct fc_frame_header *fh; + struct fc_ct_hdr *ct; + + FC_LPORT_DBG(lport, "Received a RSNN_NN %s\n", fc_els_resp_type(fp)); + + if (fp == ERR_PTR(-FC_EX_CLOSED)) + return; + + mutex_lock(&lport->lp_mutex); + + if (lport->state != LPORT_ST_RSNN_NN) { + FC_LPORT_DBG(lport, "Received a RSNN_NN response, but in state " + "%s\n", fc_lport_state(lport)); + if (IS_ERR(fp)) + goto err; + goto out; + } + + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + + fh = fc_frame_header_get(fp); + ct = fc_frame_payload_get(fp, sizeof(*ct)); + if (fh && ct && fh->fh_type == FC_TYPE_CT && + ct->ct_fs_type == FC_FST_DIR && + ct->ct_fs_subtype == FC_NS_SUBTYPE && + ntohs(ct->ct_cmd) == FC_FS_ACC) + fc_lport_enter_rsnn_nn(lport); + else + fc_lport_error(lport, fp); + +out: + fc_frame_free(fp); +err: + mutex_unlock(&lport->lp_mutex); +} + /** * fc_lport_rnn_id_resp() - Handle response to Register Node * Name by ID (RNN_ID) request @@ -1203,6 +1260,37 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport) fc_lport_error(lport, fp); } +/** + * fc_rport_enter_rsnn_nn() - Register symbolic node name with the name server + * @lport: Fibre Channel local port to register + * + * Locking Note: The lport lock is expected to be held before calling + * this routine. + */ +static void fc_lport_enter_rsnn_nn(struct fc_lport *lport) +{ + struct fc_frame *fp; + size_t len; + + FC_LPORT_DBG(lport, "Entered RSNN_NN state from %s state\n", + fc_lport_state(lport)); + + fc_lport_state_enter(lport, LPORT_ST_RSNN_NN); + + len = strnlen(fc_host_symbolic_name(lport->host), 255); + fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) + + sizeof(struct fc_ns_rsnn) + len); + if (!fp) { + fc_lport_error(lport, fp); + return; + } + + if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RSNN_NN, + fc_lport_rsnn_nn_resp, + lport, lport->e_d_tov)) + fc_lport_error(lport, fp); +} + /** * fc_rport_enter_rnn_id() - Register node name with the name server * @lport: Fibre Channel local port to register @@ -1296,6 +1384,9 @@ static void fc_lport_timeout(struct work_struct *work) case LPORT_ST_RNN_ID: fc_lport_enter_rnn_id(lport); break; + case LPORT_ST_RSNN_NN: + fc_lport_enter_rsnn_nn(lport); + break; case LPORT_ST_RFT_ID: fc_lport_enter_rft_id(lport); break; diff --git a/include/scsi/fc/fc_ns.h b/include/scsi/fc/fc_ns.h index 790d7b97d4b..fa828305632 100644 --- a/include/scsi/fc/fc_ns.h +++ b/include/scsi/fc/fc_ns.h @@ -47,6 +47,7 @@ enum fc_ns_req { FC_NS_RFT_ID = 0x0217, /* reg FC4 type for ID */ FC_NS_RPN_ID = 0x0212, /* reg port name for ID */ FC_NS_RNN_ID = 0x0213, /* reg node name for ID */ + FC_NS_RSNN_NN = 0x0239, /* reg symbolic node name */ }; /* @@ -156,4 +157,13 @@ struct fc_ns_rn_id { __be64 fr_wwn; /* node name or port name */ } __attribute__((__packed__)); +/* + * RSNN_NN request - register symbolic node name + */ +struct fc_ns_rsnn { + __be64 fr_wwn; /* node name */ + __u8 fr_name_len; + char fr_name[]; +} __attribute__((__packed__)); + #endif /* _FC_NS_H_ */ diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h index ad13cb1c3ee..89981afba72 100644 --- a/include/scsi/fc_encode.h +++ b/include/scsi/fc_encode.h @@ -33,6 +33,7 @@ struct fc_ct_req { struct fc_ns_rn_id rn; struct fc_ns_rft rft; struct fc_ns_fid fid; + struct fc_ns_rsnn snn; } payload; }; @@ -136,6 +137,15 @@ static inline int fc_ct_fill(struct fc_lport *lport, put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn); break; + case FC_NS_RSNN_NN: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn)); + put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn); + strncpy(ct->payload.snn.fr_name, + fc_host_symbolic_name(lport->host), 255); + ct->payload.snn.fr_name_len = + strnlen(ct->payload.snn.fr_name, 255); + break; + default: return -EINVAL; } diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 3d22dfd6720..1a632069c40 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -62,6 +62,7 @@ enum fc_lport_state { LPORT_ST_FLOGI, LPORT_ST_DNS, LPORT_ST_RNN_ID, + LPORT_ST_RSNN_NN, LPORT_ST_RFT_ID, LPORT_ST_SCR, LPORT_ST_READY, -- cgit v1.2.3-70-g09d2 From c9866a548024c33e30f35a14bbcb71ba78266383 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 3 Nov 2009 11:47:01 -0800 Subject: [SCSI] libfc: Register Symbolic Port Name (RSPN_ID) Register the fc_host symbolic name as the symbolic port name with the fabric name server. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 90 +++++++++++++++++++++++++++++++++++++++++++ include/scsi/fc/fc_ns.h | 10 +++++ include/scsi/fc_encode.h | 11 ++++++ include/scsi/libfc.h | 1 + 4 files changed, 112 insertions(+) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index cc389c03f69..28a35da1493 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -110,6 +110,7 @@ static void fc_lport_enter_flogi(struct fc_lport *); static void fc_lport_enter_dns(struct fc_lport *); static void fc_lport_enter_rnn_id(struct fc_lport *); static void fc_lport_enter_rsnn_nn(struct fc_lport *); +static void fc_lport_enter_rspn_id(struct fc_lport *); static void fc_lport_enter_rft_id(struct fc_lport *); static void fc_lport_enter_scr(struct fc_lport *); static void fc_lport_enter_ready(struct fc_lport *); @@ -121,6 +122,7 @@ static const char *fc_lport_state_names[] = { [LPORT_ST_DNS] = "dNS", [LPORT_ST_RNN_ID] = "RNN_ID", [LPORT_ST_RSNN_NN] = "RSNN_NN", + [LPORT_ST_RSPN_ID] = "RSPN_ID", [LPORT_ST_RFT_ID] = "RFT_ID", [LPORT_ST_SCR] = "SCR", [LPORT_ST_READY] = "Ready", @@ -969,6 +971,7 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) case LPORT_ST_RESET: case LPORT_ST_RNN_ID: case LPORT_ST_RSNN_NN: + case LPORT_ST_RSPN_ID: case LPORT_ST_RFT_ID: case LPORT_ST_SCR: case LPORT_ST_DNS: @@ -1035,6 +1038,59 @@ err: mutex_unlock(&lport->lp_mutex); } +/** + * fc_lport_rspn_id_resp() - Handle response to Register Symbolic Port Name + * by ID (RSPN_ID) request + * @sp: current sequence in RSPN_ID exchange + * @fp: response frame + * @lp_arg: Fibre Channel host port instance + * + * Locking Note: This function will be called without the lport lock + * held, but it will lock, call an _enter_* function or fc_lport_error + * and then unlock the lport. + */ +static void fc_lport_rspn_id_resp(struct fc_seq *sp, struct fc_frame *fp, + void *lp_arg) +{ + struct fc_lport *lport = lp_arg; + struct fc_frame_header *fh; + struct fc_ct_hdr *ct; + + FC_LPORT_DBG(lport, "Received a RSPN_ID %s\n", fc_els_resp_type(fp)); + + if (fp == ERR_PTR(-FC_EX_CLOSED)) + return; + + mutex_lock(&lport->lp_mutex); + + if (lport->state != LPORT_ST_RSPN_ID) { + FC_LPORT_DBG(lport, "Received a RSPN_ID response, but in state " + "%s\n", fc_lport_state(lport)); + if (IS_ERR(fp)) + goto err; + goto out; + } + + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + + fh = fc_frame_header_get(fp); + ct = fc_frame_payload_get(fp, sizeof(*ct)); + if (fh && ct && fh->fh_type == FC_TYPE_CT && + ct->ct_fs_type == FC_FST_DIR && + ct->ct_fs_subtype == FC_NS_SUBTYPE && + ntohs(ct->ct_cmd) == FC_FS_ACC) + fc_lport_enter_rspn_id(lport); + else + fc_lport_error(lport, fp); + +out: + fc_frame_free(fp); +err: + mutex_unlock(&lport->lp_mutex); +} /** * fc_lport_rsnn_nn_resp() - Handle response to Register Symbolic Node Name * by Node Name (RSNN_NN) request @@ -1260,6 +1316,37 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport) fc_lport_error(lport, fp); } +/** + * fc_rport_enter_rspn_id() - Register symbolic port name with the name server + * @lport: Fibre Channel local port to register + * + * Locking Note: The lport lock is expected to be held before calling + * this routine. + */ +static void fc_lport_enter_rspn_id(struct fc_lport *lport) +{ + struct fc_frame *fp; + size_t len; + + FC_LPORT_DBG(lport, "Entered RSPN_ID state from %s state\n", + fc_lport_state(lport)); + + fc_lport_state_enter(lport, LPORT_ST_RSPN_ID); + + len = strnlen(fc_host_symbolic_name(lport->host), 255); + fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) + + sizeof(struct fc_ns_rspn) + len); + if (!fp) { + fc_lport_error(lport, fp); + return; + } + + if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RSPN_ID, + fc_lport_rspn_id_resp, + lport, lport->e_d_tov)) + fc_lport_error(lport, fp); +} + /** * fc_rport_enter_rsnn_nn() - Register symbolic node name with the name server * @lport: Fibre Channel local port to register @@ -1387,6 +1474,9 @@ static void fc_lport_timeout(struct work_struct *work) case LPORT_ST_RSNN_NN: fc_lport_enter_rsnn_nn(lport); break; + case LPORT_ST_RSPN_ID: + fc_lport_enter_rspn_id(lport); + break; case LPORT_ST_RFT_ID: fc_lport_enter_rft_id(lport); break; diff --git a/include/scsi/fc/fc_ns.h b/include/scsi/fc/fc_ns.h index fa828305632..3fd59a2cb81 100644 --- a/include/scsi/fc/fc_ns.h +++ b/include/scsi/fc/fc_ns.h @@ -47,6 +47,7 @@ enum fc_ns_req { FC_NS_RFT_ID = 0x0217, /* reg FC4 type for ID */ FC_NS_RPN_ID = 0x0212, /* reg port name for ID */ FC_NS_RNN_ID = 0x0213, /* reg node name for ID */ + FC_NS_RSPN_ID = 0x0218, /* reg symbolic port name */ FC_NS_RSNN_NN = 0x0239, /* reg symbolic node name */ }; @@ -166,4 +167,13 @@ struct fc_ns_rsnn { char fr_name[]; } __attribute__((__packed__)); +/* + * RSPN_ID request - register symbolic port name + */ +struct fc_ns_rspn { + struct fc_ns_fid fr_fid; /* port ID object */ + __u8 fr_name_len; + char fr_name[]; +} __attribute__((__packed__)); + #endif /* _FC_NS_H_ */ diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h index 89981afba72..9afcbb94ec3 100644 --- a/include/scsi/fc_encode.h +++ b/include/scsi/fc_encode.h @@ -34,6 +34,7 @@ struct fc_ct_req { struct fc_ns_rft rft; struct fc_ns_fid fid; struct fc_ns_rsnn snn; + struct fc_ns_rspn spn; } payload; }; @@ -137,6 +138,16 @@ static inline int fc_ct_fill(struct fc_lport *lport, put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn); break; + case FC_NS_RSPN_ID: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn)); + hton24(ct->payload.spn.fr_fid.fp_fid, + fc_host_port_id(lport->host)); + strncpy(ct->payload.spn.fr_name, + fc_host_symbolic_name(lport->host), 255); + ct->payload.spn.fr_name_len = + strnlen(ct->payload.spn.fr_name, 255); + break; + case FC_NS_RSNN_NN: ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn)); put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 1a632069c40..8258edfa328 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -63,6 +63,7 @@ enum fc_lport_state { LPORT_ST_DNS, LPORT_ST_RNN_ID, LPORT_ST_RSNN_NN, + LPORT_ST_RSPN_ID, LPORT_ST_RFT_ID, LPORT_ST_SCR, LPORT_ST_READY, -- cgit v1.2.3-70-g09d2 From a51ab39606042e76a483547620699530caa12c40 Mon Sep 17 00:00:00 2001 From: Steve Ma Date: Tue, 3 Nov 2009 11:47:34 -0800 Subject: [SCSI] libfc, fcoe: Add FC passthrough support This is the Open-FCoE implementation of the FC passthrough support via bsg interface. Passthrough support is added to both N_Ports and VN_Ports. Signed-off-by: Steve Ma Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 4 + drivers/scsi/libfc/fc_lport.c | 267 ++++++++++++++++++++++++++++++++++++++++++ include/scsi/libfc.h | 7 ++ 3 files changed, 278 insertions(+) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index f1c126b798a..8f078d306a0 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -134,6 +134,8 @@ struct fc_function_template fcoe_transport_function = { .vport_delete = fcoe_vport_destroy, .vport_disable = fcoe_vport_disable, .set_vport_symbolic_name = fcoe_set_vport_symbolic_name, + + .bsg_request = fc_lport_bsg_request, }; struct fc_function_template fcoe_vport_transport_function = { @@ -167,6 +169,8 @@ struct fc_function_template fcoe_vport_transport_function = { .issue_fc_host_lip = fcoe_reset, .terminate_rport_io = fc_rport_terminate_io, + + .bsg_request = fc_lport_bsg_request, }; static struct scsi_host_template fcoe_shost_template = { diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index dfea6c572df..2162e6b0f43 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -94,6 +94,7 @@ #include #include +#include #include "fc_libfc.h" @@ -127,6 +128,24 @@ static const char *fc_lport_state_names[] = { [LPORT_ST_RESET] = "reset", }; +/** + * struct fc_bsg_info - FC Passthrough managemet structure + * @job: The passthrough job + * @lport: The local port to pass through a command + * @rsp_code: The expected response code + * @sg: job->reply_payload.sg_list + * @nents: job->reply_payload.sg_cnt + * @offset: The offset into the response data + */ +struct fc_bsg_info { + struct fc_bsg_job *job; + struct fc_lport *lport; + u16 rsp_code; + struct scatterlist *sg; + u32 nents; + size_t offset; +}; + static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp) { fc_frame_free(fp); @@ -1512,3 +1531,251 @@ int fc_lport_init(struct fc_lport *lport) return 0; } EXPORT_SYMBOL(fc_lport_init); + +/** + * fc_lport_bsg_resp() - The common response handler for fc pass-thru requests + * @sp: current sequence in the fc pass-thru request exchange + * @fp: received response frame + * @info_arg: pointer to struct fc_bsg_info + */ +static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, + void *info_arg) +{ + struct fc_bsg_info *info = info_arg; + struct fc_bsg_job *job = info->job; + struct fc_lport *lport = info->lport; + struct fc_frame_header *fh; + size_t len; + void *buf; + + if (IS_ERR(fp)) { + job->reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ? + -ECONNABORTED : -ETIMEDOUT; + job->reply_len = sizeof(uint32_t); + job->state_flags |= FC_RQST_STATE_DONE; + job->job_done(job); + kfree(info); + return; + } + + mutex_lock(&lport->lp_mutex); + fh = fc_frame_header_get(fp); + len = fr_len(fp) - sizeof(*fh); + buf = fc_frame_payload_get(fp, 0); + + if (fr_sof(fp) == FC_SOF_I3 && !ntohs(fh->fh_seq_cnt)) { + /* Get the response code from the first frame payload */ + unsigned short cmd = (info->rsp_code == FC_FS_ACC) ? + ntohs(((struct fc_ct_hdr *)buf)->ct_cmd) : + (unsigned short)fc_frame_payload_op(fp); + + /* Save the reply status of the job */ + job->reply->reply_data.ctels_reply.status = + (cmd == info->rsp_code) ? + FC_CTELS_STATUS_OK : FC_CTELS_STATUS_REJECT; + } + + job->reply->reply_payload_rcv_len += + fc_copy_buffer_to_sglist(buf, len, info->sg, &info->nents, + &info->offset, KM_BIO_SRC_IRQ, NULL); + + if (fr_eof(fp) == FC_EOF_T && + (ntoh24(fh->fh_f_ctl) & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == + (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { + if (job->reply->reply_payload_rcv_len > + job->reply_payload.payload_len) + job->reply->reply_payload_rcv_len = + job->reply_payload.payload_len; + job->reply->result = 0; + job->state_flags |= FC_RQST_STATE_DONE; + job->job_done(job); + kfree(info); + } + fc_frame_free(fp); + mutex_unlock(&lport->lp_mutex); +} + +/** + * fc_lport_els_request() - Send ELS pass-thru request + * @job: The bsg fc pass-thru job structure + * @lport: The local port sending the request + * @did: The destination port id. + * + * Locking Note: The lport lock is expected to be held before calling + * this routine. + */ +static int fc_lport_els_request(struct fc_bsg_job *job, + struct fc_lport *lport, + u32 did, u32 tov) +{ + struct fc_bsg_info *info; + struct fc_frame *fp; + struct fc_frame_header *fh; + char *pp; + int len; + + fp = fc_frame_alloc(lport, sizeof(struct fc_frame_header) + + job->request_payload.payload_len); + if (!fp) + return -ENOMEM; + + len = job->request_payload.payload_len; + pp = fc_frame_payload_get(fp, len); + + sg_copy_to_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, + pp, len); + + fh = fc_frame_header_get(fp); + fh->fh_r_ctl = FC_RCTL_ELS_REQ; + hton24(fh->fh_d_id, did); + hton24(fh->fh_s_id, fc_host_port_id(lport->host)); + fh->fh_type = FC_TYPE_ELS; + hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | + FC_FC_END_SEQ | FC_FC_SEQ_INIT); + fh->fh_cs_ctl = 0; + fh->fh_df_ctl = 0; + fh->fh_parm_offset = 0; + + info = kzalloc(sizeof(struct fc_bsg_info), GFP_KERNEL); + if (!info) { + fc_frame_free(fp); + return -ENOMEM; + } + + info->job = job; + info->lport = lport; + info->rsp_code = ELS_LS_ACC; + info->nents = job->reply_payload.sg_cnt; + info->sg = job->reply_payload.sg_list; + + if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp, + NULL, info, tov)) + return -ECOMM; + return 0; +} + +/** + * fc_lport_ct_request() - Send CT pass-thru request + * @job: The bsg fc pass-thru job structure + * @lport: The local port sending the request + * @did: The destination FC-ID + * @tov: The time to wait for a response + * + * Locking Note: The lport lock is expected to be held before calling + * this routine. + */ +static int fc_lport_ct_request(struct fc_bsg_job *job, + struct fc_lport *lport, u32 did, u32 tov) +{ + struct fc_bsg_info *info; + struct fc_frame *fp; + struct fc_frame_header *fh; + struct fc_ct_req *ct; + size_t len; + + fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) + + job->request_payload.payload_len); + if (!fp) + return -ENOMEM; + + len = job->request_payload.payload_len; + ct = fc_frame_payload_get(fp, len); + + sg_copy_to_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, + ct, len); + + fh = fc_frame_header_get(fp); + fh->fh_r_ctl = FC_RCTL_DD_UNSOL_CTL; + hton24(fh->fh_d_id, did); + hton24(fh->fh_s_id, fc_host_port_id(lport->host)); + fh->fh_type = FC_TYPE_CT; + hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | + FC_FC_END_SEQ | FC_FC_SEQ_INIT); + fh->fh_cs_ctl = 0; + fh->fh_df_ctl = 0; + fh->fh_parm_offset = 0; + + info = kzalloc(sizeof(struct fc_bsg_info), GFP_KERNEL); + if (!info) { + fc_frame_free(fp); + return -ENOMEM; + } + + info->job = job; + info->lport = lport; + info->rsp_code = FC_FS_ACC; + info->nents = job->reply_payload.sg_cnt; + info->sg = job->reply_payload.sg_list; + + if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp, + NULL, info, tov)) + return -ECOMM; + return 0; +} + +/** + * fc_lport_bsg_request() - The common entry point for sending + * fc pass-thru requests + * @job: The fc pass-thru job structure + */ +int fc_lport_bsg_request(struct fc_bsg_job *job) +{ + struct request *rsp = job->req->next_rq; + struct Scsi_Host *shost = job->shost; + struct fc_lport *lport = shost_priv(shost); + struct fc_rport *rport; + struct fc_rport_priv *rdata; + int rc = -EINVAL; + u32 did; + + job->reply->reply_payload_rcv_len = 0; + rsp->resid_len = job->reply_payload.payload_len; + + mutex_lock(&lport->lp_mutex); + + switch (job->request->msgcode) { + case FC_BSG_RPT_ELS: + rport = job->rport; + if (!rport) + break; + + rdata = rport->dd_data; + rc = fc_lport_els_request(job, lport, rport->port_id, + rdata->e_d_tov); + break; + + case FC_BSG_RPT_CT: + rport = job->rport; + if (!rport) + break; + + rdata = rport->dd_data; + rc = fc_lport_ct_request(job, lport, rport->port_id, + rdata->e_d_tov); + break; + + case FC_BSG_HST_CT: + did = ntoh24(job->request->rqst_data.h_ct.port_id); + if (did == FC_FID_DIR_SERV) + rdata = lport->dns_rp; + else + rdata = lport->tt.rport_lookup(lport, did); + + if (!rdata) + break; + + rc = fc_lport_ct_request(job, lport, did, rdata->e_d_tov); + break; + + case FC_BSG_HST_ELS_NOLOGIN: + did = ntoh24(job->request->rqst_data.h_els.port_id); + rc = fc_lport_els_request(job, lport, did, lport->e_d_tov); + break; + } + + mutex_unlock(&lport->lp_mutex); + return rc; +} +EXPORT_SYMBOL(fc_lport_bsg_request); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 8258edfa328..54df9fe00c1 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -830,6 +831,12 @@ struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id); void fc_vport_setlink(struct fc_lport *vn_port); void fc_vports_linkchange(struct fc_lport *n_port); +/* + * Issue fc pass-thru request via bsg interface + */ +int fc_lport_bsg_request(struct fc_bsg_job *job); + + /* * REMOTE PORT LAYER *****************************/ -- cgit v1.2.3-70-g09d2 From 3a3b42bf89a9b90ae9ed2c57fdc378e5473a0ef9 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Tue, 3 Nov 2009 11:47:39 -0800 Subject: [SCSI] libfc: Formatting cleanups across libfc This patch makes a variety of cleanup changes to all libfc files. This patch adds kernel-doc headers to all functions lacking them and attempts to better format existing headers. It also add kernel-doc headers to structures. This patch ensures that the current naming conventions for local ports, remote ports and remote port private data is upheld in the following manner. struct instance (i.e. variable name) -------------------------------------------------- fc_lport lport fc_rport rport fc_rport_libfc_priv rpriv fc_rport_priv rdata I also renamed dns_rp and ptp_rp to dns_rdata and ptp_rdata respectively. I used emacs 'indent-region' and 'tabify' on all libfc files to correct spacing alignments. I feel sorry for anyone attempting to review this patch. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 78 ++-- drivers/scsi/libfc/fc_elsct.c | 33 +- drivers/scsi/libfc/fc_exch.c | 587 +++++++++++++++++-------- drivers/scsi/libfc/fc_fcp.c | 667 ++++++++++++++++------------ drivers/scsi/libfc/fc_libfc.c | 4 +- drivers/scsi/libfc/fc_libfc.h | 34 +- drivers/scsi/libfc/fc_lport.c | 247 ++++++----- drivers/scsi/libfc/fc_rport.c | 235 +++++----- include/scsi/libfc.h | 994 +++++++++++++++++++++--------------------- 9 files changed, 1624 insertions(+), 1255 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index a4bdec28fef..7b790ad15a9 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -53,8 +53,8 @@ static int fc_disc_single(struct fc_lport *, struct fc_disc_port *); static void fc_disc_restart(struct fc_disc *); /** - * fc_disc_stop_rports() - delete all the remote ports associated with the lport - * @disc: The discovery job to stop rports on + * fc_disc_stop_rports() - Delete all the remote ports associated with the lport + * @disc: The discovery job to stop remote ports on * * Locking Note: This function expects that the lport mutex is locked before * calling it. @@ -74,9 +74,9 @@ void fc_disc_stop_rports(struct fc_disc *disc) /** * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN) - * @sp: Current sequence of the RSCN exchange - * @fp: RSCN Frame - * @lport: Fibre Channel host port instance + * @sp: The sequence of the RSCN exchange + * @fp: The RSCN frame + * @lport: The local port that the request will be sent on * * Locking Note: This function expects that the disc_mutex is locked * before it is called. @@ -185,9 +185,9 @@ reject: /** * fc_disc_recv_req() - Handle incoming requests - * @sp: Current sequence of the request exchange - * @fp: The frame - * @lport: The FC local port + * @sp: The sequence of the request exchange + * @fp: The request frame + * @lport: The local port receiving the request * * Locking Note: This function is called from the EM and will lock * the disc_mutex before calling the handler for the @@ -215,7 +215,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, /** * fc_disc_restart() - Restart discovery - * @lport: FC discovery context + * @disc: The discovery object to be restarted * * Locking Note: This function expects that the disc mutex * is already locked. @@ -242,9 +242,9 @@ static void fc_disc_restart(struct fc_disc *disc) } /** - * fc_disc_start() - Fibre Channel Target discovery - * @lport: FC local port - * @disc_callback: function to be called when discovery is complete + * fc_disc_start() - Start discovery on a local port + * @lport: The local port to have discovery started on + * @disc_callback: Callback function to be called when discovery is complete */ static void fc_disc_start(void (*disc_callback)(struct fc_lport *, enum fc_disc_event), @@ -265,8 +265,8 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *, /** * fc_disc_done() - Discovery has been completed - * @disc: FC discovery context - * @event: discovery completion status + * @disc: The discovery context + * @event: The discovery completion status * * Locking Note: This function expects that the disc mutex is locked before * it is called. The discovery callback is then made with the lock released, @@ -286,8 +286,8 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) } /* - * Go through all remote ports. If they were found in the latest - * discovery, reverify or log them in. Otherwise, log them out. + * Go through all remote ports. If they were found in the latest + * discovery, reverify or log them in. Otherwise, log them out. * Skip ports which were never discovered. These are the dNS port * and ports which were created by PLOGI. */ @@ -307,8 +307,8 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) /** * fc_disc_error() - Handle error on dNS request - * @disc: FC discovery context - * @fp: The frame pointer + * @disc: The discovery context + * @fp: The error code encoded as a frame pointer */ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) { @@ -344,7 +344,7 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) /** * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request - * @lport: FC discovery context + * @lport: The discovery context * * Locking Note: This function expects that the disc_mutex is locked * before it is called. @@ -378,9 +378,9 @@ err: /** * fc_disc_gpn_ft_parse() - Parse the body of the dNS GPN_FT response. - * @lport: Fibre Channel host port instance - * @buf: GPN_FT response buffer - * @len: size of response buffer + * @lport: The local port the GPN_FT was received on + * @buf: The GPN_FT response buffer + * @len: The size of response buffer * * Goes through the list of IDs and names resulting from a request. */ @@ -479,10 +479,8 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) } /** - * fc_disc_timeout() - Retry handler for the disc component - * @work: Structure holding disc obj that needs retry discovery - * - * Handle retry of memory allocation for remote ports. + * fc_disc_timeout() - Handler for discovery timeouts + * @work: Structure holding discovery context that needs to retry discovery */ static void fc_disc_timeout(struct work_struct *work) { @@ -496,9 +494,9 @@ static void fc_disc_timeout(struct work_struct *work) /** * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT) - * @sp: Current sequence of GPN_FT exchange - * @fp: response frame - * @lp_arg: Fibre Channel host port instance + * @sp: The sequence that the GPN_FT response was received on + * @fp: The GPN_FT response frame + * @lp_arg: The discovery context * * Locking Note: This function is called without disc mutex held, and * should do all its processing with the mutex held @@ -569,9 +567,9 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, /** * fc_disc_gpn_id_resp() - Handle a response frame from Get Port Names (GPN_ID) - * @sp: exchange sequence - * @fp: response frame - * @rdata_arg: remote port private data + * @sp: The sequence the GPN_ID is on + * @fp: The response frame + * @rdata_arg: The remote port that sent the GPN_ID response * * Locking Note: This function is called without disc mutex held. */ @@ -639,7 +637,7 @@ out: /** * fc_disc_gpn_id_req() - Send Get Port Names by ID (GPN_ID) request - * @lport: local port + * @lport: The local port to initiate discovery on * @rdata: remote port private data * * Locking Note: This function expects that the disc_mutex is locked @@ -656,7 +654,7 @@ static int fc_disc_gpn_id_req(struct fc_lport *lport, if (!fp) return -ENOMEM; if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, FC_NS_GPN_ID, - fc_disc_gpn_id_resp, rdata, lport->e_d_tov)) + fc_disc_gpn_id_resp, rdata, lport->e_d_tov)) return -ENOMEM; kref_get(&rdata->kref); return 0; @@ -664,8 +662,8 @@ static int fc_disc_gpn_id_req(struct fc_lport *lport, /** * fc_disc_single() - Discover the directory information for a single target - * @lport: local port - * @dp: The port to rediscover + * @lport: The local port the remote port is associated with + * @dp: The port to rediscover * * Locking Note: This function expects that the disc_mutex is locked * before it is called. @@ -683,7 +681,7 @@ static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp) /** * fc_disc_stop() - Stop discovery for a given lport - * @lport: The lport that discovery should stop for + * @lport: The local port that discovery should stop on */ void fc_disc_stop(struct fc_lport *lport) { @@ -697,7 +695,7 @@ void fc_disc_stop(struct fc_lport *lport) /** * fc_disc_stop_final() - Stop discovery for a given lport - * @lport: The lport that discovery should stop for + * @lport: The lport that discovery should stop on * * This function will block until discovery has been * completely stopped and all rports have been deleted. @@ -709,8 +707,8 @@ void fc_disc_stop_final(struct fc_lport *lport) } /** - * fc_disc_init() - Initialize the discovery block - * @lport: FC local port + * fc_disc_init() - Initialize the discovery layer for a local port + * @lport: The local port that needs the discovery layer to be initialized */ int fc_disc_init(struct fc_lport *lport) { diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index aae54fe3b29..01be43f80f3 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -28,17 +28,22 @@ #include #include -/* - * fc_elsct_send - sends ELS/CT frame +/** + * fc_elsct_send() - Send an ELS or CT frame + * @lport: The local port to send the frame on + * @did: The destination ID for the frame + * @fp: The frame to be sent + * @op: The operational code + * @resp: The callback routine when the response is received + * @arg: The argument to pass to the response callback routine + * @timer_msec: The timeout period for the frame (in msecs) */ -struct fc_seq *fc_elsct_send(struct fc_lport *lport, - u32 did, - struct fc_frame *fp, - unsigned int op, - void (*resp)(struct fc_seq *, - struct fc_frame *fp, - void *arg), - void *arg, u32 timer_msec) +struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did, + struct fc_frame *fp, unsigned int op, + void (*resp)(struct fc_seq *, + struct fc_frame *, + void *), + void *arg, u32 timer_msec) { enum fc_rctl r_ctl; enum fc_fh_type fh_type; @@ -65,6 +70,10 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, } EXPORT_SYMBOL(fc_elsct_send); +/** + * fc_elsct_init() - Initialize the ELS/CT layer + * @lport: The local port to initialize the ELS/CT layer for + */ int fc_elsct_init(struct fc_lport *lport) { if (!lport->tt.elsct_send) @@ -75,8 +84,8 @@ int fc_elsct_init(struct fc_lport *lport) EXPORT_SYMBOL(fc_elsct_init); /** - * fc_els_resp_type() - return string describing ELS response for debug. - * @fp: frame pointer with possible error code. + * fc_els_resp_type() - Return a string describing the ELS response + * @fp: The frame pointer or possible error code */ const char *fc_els_resp_type(struct fc_frame *fp) { diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 751a485685d..0f45bb8521f 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -37,7 +37,7 @@ u16 fc_cpu_mask; /* cpu mask for possible cpus */ EXPORT_SYMBOL(fc_cpu_mask); static u16 fc_cpu_order; /* 2's power to represent total possible cpus */ -static struct kmem_cache *fc_em_cachep; /* cache for exchanges */ +static struct kmem_cache *fc_em_cachep; /* cache for exchanges */ /* * Structure and function definitions for managing Fibre Channel Exchanges @@ -52,34 +52,46 @@ static struct kmem_cache *fc_em_cachep; /* cache for exchanges */ * fc_seq holds the state for an individual sequence. */ -/* - * Per cpu exchange pool +/** + * struct fc_exch_pool - Per cpu exchange pool + * @next_index: Next possible free exchange index + * @total_exches: Total allocated exchanges + * @lock: Exch pool lock + * @ex_list: List of exchanges * * This structure manages per cpu exchanges in array of exchange pointers. * This array is allocated followed by struct fc_exch_pool memory for * assigned range of exchanges to per cpu pool. */ struct fc_exch_pool { - u16 next_index; /* next possible free exchange index */ - u16 total_exches; /* total allocated exchanges */ - spinlock_t lock; /* exch pool lock */ - struct list_head ex_list; /* allocated exchanges list */ + u16 next_index; + u16 total_exches; + spinlock_t lock; + struct list_head ex_list; }; -/* - * Exchange manager. +/** + * struct fc_exch_mgr - The Exchange Manager (EM). + * @class: Default class for new sequences + * @kref: Reference counter + * @min_xid: Minimum exchange ID + * @max_xid: Maximum exchange ID + * @ep_pool: Reserved exchange pointers + * @pool_max_index: Max exch array index in exch pool + * @pool: Per cpu exch pool + * @stats: Statistics structure * * This structure is the center for creating exchanges and sequences. * It manages the allocation of exchange IDs. */ struct fc_exch_mgr { - enum fc_class class; /* default class for sequences */ - struct kref kref; /* exchange mgr reference count */ - u16 min_xid; /* min exchange ID */ - u16 max_xid; /* max exchange ID */ - mempool_t *ep_pool; /* reserve ep's */ - u16 pool_max_index; /* max exch array index in exch pool */ - struct fc_exch_pool *pool; /* per cpu exch pool */ + enum fc_class class; + struct kref kref; + u16 min_xid; + u16 max_xid; + mempool_t *ep_pool; + u16 pool_max_index; + struct fc_exch_pool *pool; /* * currently exchange mgr stats are updated but not used. @@ -97,6 +109,18 @@ struct fc_exch_mgr { }; #define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq) +/** + * struct fc_exch_mgr_anchor - primary structure for list of EMs + * @ema_list: Exchange Manager Anchor list + * @mp: Exchange Manager associated with this anchor + * @match: Routine to determine if this anchor's EM should be used + * + * When walking the list of anchors the match routine will be called + * for each anchor to determine if that EM should be used. The last + * anchor in the list will always match to handle any exchanges not + * handled by other EMs. The non-default EMs would be added to the + * anchor list by HW that provides FCoE offloads. + */ struct fc_exch_mgr_anchor { struct list_head ema_list; struct fc_exch_mgr *mp; @@ -196,6 +220,15 @@ static char *fc_exch_rctl_names[] = FC_RCTL_NAMES_INIT; #define FC_TABLE_SIZE(x) (sizeof(x) / sizeof(x[0])) +/** + * fc_exch_name_lookup() - Lookup name by opcode + * @op: Opcode to be looked up + * @table: Opcode/name table + * @max_index: Index not to be exceeded + * + * This routine is used to determine a human-readable string identifying + * a R_CTL opcode. + */ static inline const char *fc_exch_name_lookup(unsigned int op, char **table, unsigned int max_index) { @@ -208,25 +241,34 @@ static inline const char *fc_exch_name_lookup(unsigned int op, char **table, return name; } +/** + * fc_exch_rctl_name() - Wrapper routine for fc_exch_name_lookup() + * @op: The opcode to be looked up + */ static const char *fc_exch_rctl_name(unsigned int op) { return fc_exch_name_lookup(op, fc_exch_rctl_names, FC_TABLE_SIZE(fc_exch_rctl_names)); } -/* - * Hold an exchange - keep it from being freed. +/** + * fc_exch_hold() - Increment an exchange's reference count + * @ep: Echange to be held */ -static void fc_exch_hold(struct fc_exch *ep) +static inline void fc_exch_hold(struct fc_exch *ep) { atomic_inc(&ep->ex_refcnt); } -/* - * setup fc hdr by initializing few more FC header fields and sof/eof. - * Initialized fields by this func: - * - fh_ox_id, fh_rx_id, fh_seq_id, fh_seq_cnt - * - sof and eof +/** + * fc_exch_setup_hdr() - Initialize a FC header by initializing some fields + * and determine SOF and EOF. + * @ep: The exchange to that will use the header + * @fp: The frame whose header is to be modified + * @f_ctl: F_CTL bits that will be used for the frame header + * + * The fields initialized by this routine are: fh_ox_id, fh_rx_id, + * fh_seq_id, fh_seq_cnt and the SOF and EOF. */ static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp, u32 f_ctl) @@ -243,7 +285,7 @@ static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp, if (fc_sof_needs_ack(ep->class)) fr_eof(fp) = FC_EOF_N; /* - * Form f_ctl. + * From F_CTL. * The number of fill bytes to make the length a 4-byte * multiple is the low order 2-bits of the f_ctl. * The fill itself will have been cleared by the frame @@ -273,9 +315,12 @@ static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp, fh->fh_seq_cnt = htons(ep->seq.cnt); } -/* - * Release a reference to an exchange. - * If the refcnt goes to zero and the exchange is complete, it is freed. +/** + * fc_exch_release() - Decrement an exchange's reference count + * @ep: Exchange to be released + * + * If the reference count reaches zero and the exchange is complete, + * it is freed. */ static void fc_exch_release(struct fc_exch *ep) { @@ -290,6 +335,10 @@ static void fc_exch_release(struct fc_exch *ep) } } +/** + * fc_exch_done_locked() - Complete an exchange with the exchange lock held + * @ep: The exchange that is complete + */ static int fc_exch_done_locked(struct fc_exch *ep) { int rc = 1; @@ -314,6 +363,15 @@ static int fc_exch_done_locked(struct fc_exch *ep) return rc; } +/** + * fc_exch_ptr_get() - Return an exchange from an exchange pool + * @pool: Exchange Pool to get an exchange from + * @index: Index of the exchange within the pool + * + * Use the index to get an exchange from within an exchange pool. exches + * will point to an array of exchange pointers. The index will select + * the exchange within the array. + */ static inline struct fc_exch *fc_exch_ptr_get(struct fc_exch_pool *pool, u16 index) { @@ -321,12 +379,22 @@ static inline struct fc_exch *fc_exch_ptr_get(struct fc_exch_pool *pool, return exches[index]; } +/** + * fc_exch_ptr_set() - Assign an exchange to a slot in an exchange pool + * @pool: The pool to assign the exchange to + * @index: The index in the pool where the exchange will be assigned + * @ep: The exchange to assign to the pool + */ static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index, struct fc_exch *ep) { ((struct fc_exch **)(pool + 1))[index] = ep; } +/** + * fc_exch_delete() - Delete an exchange + * @ep: The exchange to be deleted + */ static void fc_exch_delete(struct fc_exch *ep) { struct fc_exch_pool *pool; @@ -342,8 +410,14 @@ static void fc_exch_delete(struct fc_exch *ep) fc_exch_release(ep); /* drop hold for exch in mp */ } -/* - * Internal version of fc_exch_timer_set - used with lock held. +/** + * fc_exch_timer_set_locked() - Start a timer for an exchange w/ the + * the exchange lock held + * @ep: The exchange whose timer will start + * @timer_msec: The timeout period + * + * Used for upper level protocols to time out the exchange. + * The timer is cancelled when it fires or when the exchange completes. */ static inline void fc_exch_timer_set_locked(struct fc_exch *ep, unsigned int timer_msec) @@ -358,12 +432,10 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep, fc_exch_hold(ep); /* hold for timer */ } -/* - * Set timer for an exchange. - * The time is a minimum delay in milliseconds until the timer fires. - * Used for upper level protocols to time out the exchange. - * The timer is cancelled when it fires or when the exchange completes. - * Returns non-zero if a timer couldn't be allocated. +/** + * fc_exch_timer_set() - Lock the exchange and set the timer + * @ep: The exchange whose timer will start + * @timer_msec: The timeout period */ static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec) { @@ -373,15 +445,18 @@ static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec) } /** - * send a frame using existing sequence and exchange. + * fc_seq_send() - Send a frame using existing sequence/exchange pair + * @lport: The local port that the exchange will be sent on + * @sp: The sequence to be sent + * @fp: The frame to be sent on the exchange */ -static int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, +static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp) { struct fc_exch *ep; struct fc_frame_header *fh = fc_frame_header_get(fp); int error; - u32 f_ctl; + u32 f_ctl; ep = fc_seq_exch(sp); WARN_ON((ep->esb_stat & ESB_ST_SEQ_INIT) != ESB_ST_SEQ_INIT); @@ -403,7 +478,7 @@ static int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, /* * Send the frame. */ - error = lp->tt.frame_send(lp, fp); + error = lport->tt.frame_send(lport, fp); /* * Update the exchange and sequence flags, @@ -419,9 +494,9 @@ static int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, } /** - * fc_seq_alloc() - Allocate a sequence. - * @ep: Exchange pointer - * @seq_id: Sequence ID to allocate a sequence for + * fc_seq_alloc() - Allocate a sequence for a given exchange + * @ep: The exchange to allocate a new sequence for + * @seq_id: The sequence ID to be used * * We don't support multiple originated sequences on the same exchange. * By implication, any previously originated sequence on this exchange @@ -438,6 +513,11 @@ static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id) return sp; } +/** + * fc_seq_start_next_locked() - Allocate a new sequence on the same + * exchange as the supplied sequence + * @sp: The sequence/exchange to get a new sequence for + */ static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp) { struct fc_exch *ep = fc_seq_exch(sp); @@ -449,8 +529,9 @@ static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp) } /** - * Allocate a new sequence on the same exchange as the supplied sequence. - * This will never return NULL. + * fc_seq_start_next() - Lock the exchange and get a new sequence + * for a given sequence/exchange pair + * @sp: The sequence/exchange to get a new exchange for */ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) { @@ -464,9 +545,11 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) } /** - * This function is for seq_exch_abort function pointer in - * struct libfc_function_template, see comment block on - * seq_exch_abort for description of this function. + * fc_seq_exch_abort() - Abort an exchange and sequence + * @req_sp: The sequence to be aborted + * @timer_msec: The period of time to wait before aborting + * + * Generally called because of a timeout or an abort from the upper layer. */ static int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec) @@ -519,9 +602,9 @@ static int fc_seq_exch_abort(const struct fc_seq *req_sp, return error; } -/* - * Exchange timeout - handle exchange timer expiration. - * The timer will have been cancelled before this is called. +/** + * fc_exch_timeout() - Handle exchange timer expiration + * @work: The work_struct identifying the exchange that timed out */ static void fc_exch_timeout(struct work_struct *work) { @@ -570,9 +653,9 @@ done: } /** - * fc_exch_em_alloc() - allocate an exchange from a specified EM. - * @lport: ptr to the local port - * @mp: ptr to the exchange manager + * fc_exch_em_alloc() - Allocate an exchange from a specified EM. + * @lport: The local port that the exchange is for + * @mp: The exchange manager that will allocate the exchange * * Returns pointer to allocated fc_exch with exch lock held. */ @@ -640,14 +723,15 @@ err: } /** - * fc_exch_alloc() - allocate an exchange. - * @lport: ptr to the local port - * @fp: ptr to the FC frame + * fc_exch_alloc() - Allocate an exchange from an EM on a + * local port's list of EMs. + * @lport: The local port that will own the exchange + * @fp: The FC frame that the exchange will be for * - * This function walks the list of the exchange manager(EM) - * anchors to select a EM for new exchange allocation. The - * EM is selected having either a NULL match function pointer - * or call to match function returning true. + * This function walks the list of exchange manager(EM) + * anchors to select an EM for a new exchange allocation. The + * EM is selected when a NULL match function pointer is encountered + * or when a call to a match function returns true. */ static struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp) @@ -665,8 +749,10 @@ static struct fc_exch *fc_exch_alloc(struct fc_lport *lport, return NULL; } -/* - * Lookup and hold an exchange. +/** + * fc_exch_find() - Lookup and hold an exchange + * @mp: The exchange manager to lookup the exchange from + * @xid: The XID of the exchange to look up */ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) { @@ -689,8 +775,8 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) /** * fc_exch_done() - Indicate that an exchange/sequence tuple is complete and - * the memory allocated for the related objects may be freed. - * @sp: Sequence pointer + * the memory allocated for the related objects may be freed. + * @sp: The sequence that has completed */ static void fc_exch_done(struct fc_seq *sp) { @@ -704,8 +790,12 @@ static void fc_exch_done(struct fc_seq *sp) fc_exch_delete(ep); } -/* - * Allocate a new exchange as responder. +/** + * fc_exch_resp() - Allocate a new exchange for a response frame + * @lport: The local port that the exchange was for + * @mp: The exchange manager to allocate the exchange from + * @fp: The response frame + * * Sets the responder ID in the frame header. */ static struct fc_exch *fc_exch_resp(struct fc_lport *lport, @@ -746,8 +836,13 @@ static struct fc_exch *fc_exch_resp(struct fc_lport *lport, return ep; } -/* - * Find a sequence for receive where the other end is originating the sequence. +/** + * fc_seq_lookup_recip() - Find a sequence where the other end + * originated the sequence + * @lport: The local port that the frame was sent to + * @mp: The Exchange Manager to lookup the exchange from + * @fp: The frame associated with the sequence we're looking for + * * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold * on the ep that should be released by the caller. */ @@ -853,10 +948,12 @@ rel: return reject; } -/* - * Find the sequence for a frame being received. - * We originated the sequence, so it should be found. - * We may or may not have originated the exchange. +/** + * fc_seq_lookup_orig() - Find a sequence where this end + * originated the sequence + * @mp: The Exchange Manager to lookup the exchange from + * @fp: The frame associated with the sequence we're looking for + * * Does not hold the sequence for the caller. */ static struct fc_seq *fc_seq_lookup_orig(struct fc_exch_mgr *mp, @@ -888,8 +985,12 @@ static struct fc_seq *fc_seq_lookup_orig(struct fc_exch_mgr *mp, return sp; } -/* - * Set addresses for an exchange. +/** + * fc_exch_set_addr() - Set the source and destination IDs for an exchange + * @ep: The exchange to set the addresses for + * @orig_id: The originator's ID + * @resp_id: The responder's ID + * * Note this must be done before the first sequence of the exchange is sent. */ static void fc_exch_set_addr(struct fc_exch *ep, @@ -906,11 +1007,11 @@ static void fc_exch_set_addr(struct fc_exch *ep, } /** - * fc_seq_els_rsp_send() - Send ELS response using mainly infomation - * in exchange and sequence in EM layer. - * @sp: Sequence pointer - * @els_cmd: ELS command - * @els_data: ELS data + * fc_seq_els_rsp_send() - Send an ELS response using infomation from + * the existing sequence/exchange. + * @sp: The sequence/exchange to get information from + * @els_cmd: The ELS command to be sent + * @els_data: The ELS data to be sent */ static void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, struct fc_seq_els_data *els_data) @@ -933,8 +1034,12 @@ static void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, } } -/* - * Send a sequence, which is also the last sequence in the exchange. +/** + * fc_seq_send_last() - Send a sequence that is the last in the exchange + * @sp: The sequence that is to be sent + * @fp: The frame that will be sent on the sequence + * @rctl: The R_CTL information to be sent + * @fh_type: The frame header type */ static void fc_seq_send_last(struct fc_seq *sp, struct fc_frame *fp, enum fc_rctl rctl, enum fc_fh_type fh_type) @@ -948,9 +1053,12 @@ static void fc_seq_send_last(struct fc_seq *sp, struct fc_frame *fp, fc_seq_send(ep->lp, sp, fp); } -/* +/** + * fc_seq_send_ack() - Send an acknowledgement that we've received a frame + * @sp: The sequence to send the ACK on + * @rx_fp: The received frame that is being acknoledged + * * Send ACK_1 (or equiv.) indicating we received something. - * The frame we're acking is supplied. */ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) { @@ -958,14 +1066,14 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) struct fc_frame_header *rx_fh; struct fc_frame_header *fh; struct fc_exch *ep = fc_seq_exch(sp); - struct fc_lport *lp = ep->lp; + struct fc_lport *lport = ep->lp; unsigned int f_ctl; /* * Don't send ACKs for class 3. */ if (fc_sof_needs_ack(fr_sof(rx_fp))) { - fp = fc_frame_alloc(lp, 0); + fp = fc_frame_alloc(lport, 0); if (!fp) return; @@ -1000,12 +1108,16 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) else fr_eof(fp) = FC_EOF_N; - (void) lp->tt.frame_send(lp, fp); + lport->tt.frame_send(lport, fp); } } -/* - * Send BLS Reject. +/** + * fc_exch_send_ba_rjt() - Send BLS Reject + * @rx_fp: The frame being rejected + * @reason: The reason the frame is being rejected + * @explan: The explaination for the rejection + * * This is for rejecting BA_ABTS only. */ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp, @@ -1016,11 +1128,11 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp, struct fc_frame_header *rx_fh; struct fc_frame_header *fh; struct fc_ba_rjt *rp; - struct fc_lport *lp; + struct fc_lport *lport; unsigned int f_ctl; - lp = fr_dev(rx_fp); - fp = fc_frame_alloc(lp, sizeof(*rp)); + lport = fr_dev(rx_fp); + fp = fc_frame_alloc(lport, sizeof(*rp)); if (!fp) return; fh = fc_frame_header_get(fp); @@ -1065,13 +1177,17 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp, if (fc_sof_needs_ack(fr_sof(fp))) fr_eof(fp) = FC_EOF_N; - (void) lp->tt.frame_send(lp, fp); + lport->tt.frame_send(lport, fp); } -/* - * Handle an incoming ABTS. This would be for target mode usually, - * but could be due to lost FCP transfer ready, confirm or RRQ. - * We always handle this as an exchange abort, ignoring the parameter. +/** + * fc_exch_recv_abts() - Handle an incoming ABTS + * @ep: The exchange the abort was on + * @rx_fp: The ABTS frame + * + * This would be for target mode usually, but could be due to lost + * FCP transfer ready, confirm or RRQ. We always handle this as an + * exchange abort, ignoring the parameter. */ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) { @@ -1120,10 +1236,14 @@ free: fc_frame_free(rx_fp); } -/* - * Handle receive where the other end is originating the sequence. +/** + * fc_exch_recv_req() - Handler for an incoming request where is other + * end is originating the sequence + * @lport: The local port that received the request + * @mp: The EM that the exchange is on + * @fp: The request frame */ -static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp, +static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); @@ -1137,14 +1257,14 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp, /* We can have the wrong fc_lport at this point with NPIV, which is a * problem now that we know a new exchange needs to be allocated */ - lp = fc_vport_id_lookup(lp, ntoh24(fh->fh_d_id)); - if (!lp) { + lport = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id)); + if (!lport) { fc_frame_free(fp); return; } fr_seq(fp) = NULL; - reject = fc_seq_lookup_recip(lp, mp, fp); + reject = fc_seq_lookup_recip(lport, mp, fp); if (reject == FC_RJT_NONE) { sp = fr_seq(fp); /* sequence will be held */ ep = fc_seq_exch(sp); @@ -1167,17 +1287,21 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp, if (ep->resp) ep->resp(sp, fp, ep->arg); else - lp->tt.lport_recv(lp, sp, fp); + lport->tt.lport_recv(lport, sp, fp); fc_exch_release(ep); /* release from lookup */ } else { - FC_LPORT_DBG(lp, "exch/seq lookup failed: reject %x\n", reject); + FC_LPORT_DBG(lport, "exch/seq lookup failed: reject %x\n", + reject); fc_frame_free(fp); } } -/* - * Handle receive where the other end is originating the sequence in - * response to our exchange. +/** + * fc_exch_recv_seq_resp() - Handler for an incoming response where the other + * end is the originator of the sequence that is a + * response to our initial exchange + * @mp: The EM that the exchange is on + * @fp: The response frame */ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) { @@ -1268,8 +1392,11 @@ out: fc_frame_free(fp); } -/* - * Handle receive for a sequence where other end is responding to our sequence. +/** + * fc_exch_recv_resp() - Handler for a sequence where other end is + * responding to our sequence + * @mp: The EM that the exchange is on + * @fp: The response frame */ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) { @@ -1285,9 +1412,13 @@ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) fc_frame_free(fp); } -/* - * Handle the response to an ABTS for exchange or sequence. - * This can be BA_ACC or BA_RJT. +/** + * fc_exch_abts_resp() - Handler for a response to an ABT + * @ep: The exchange that the frame is on + * @fp: The response frame + * + * This response would be to an ABTS cancelling an exchange or sequence. + * The response can be either BA_ACC or BA_RJT */ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) { @@ -1362,9 +1493,12 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) } -/* - * Receive BLS sequence. - * This is always a sequence initiated by the remote side. +/** + * fc_exch_recv_bls() - Handler for a BLS sequence + * @mp: The EM that the exchange is on + * @fp: The request frame + * + * The BLS frame is always a sequence initiated by the remote side. * We may be either the originator or recipient of the exchange. */ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp) @@ -1421,8 +1555,10 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp) fc_exch_release(ep); /* release hold taken by fc_exch_find */ } -/* - * Accept sequence with LS_ACC. +/** + * fc_seq_ls_acc() - Accept sequence with LS_ACC + * @req_sp: The request sequence + * * If this fails due to allocation or transmit congestion, assume the * originator will repeat the sequence. */ @@ -1442,8 +1578,12 @@ static void fc_seq_ls_acc(struct fc_seq *req_sp) } } -/* - * Reject sequence with ELS LS_RJT. +/** + * fc_seq_ls_rjt() - Reject a sequence with ELS LS_RJT + * @req_sp: The request sequence + * @reason: The reason the sequence is being rejected + * @explan: The explaination for the rejection + * * If this fails due to allocation or transmit congestion, assume the * originator will repeat the sequence. */ @@ -1466,6 +1606,10 @@ static void fc_seq_ls_rjt(struct fc_seq *req_sp, enum fc_els_rjt_reason reason, } } +/** + * fc_exch_reset() - Reset an exchange + * @ep: The exchange to be reset + */ static void fc_exch_reset(struct fc_exch *ep) { struct fc_seq *sp; @@ -1500,16 +1644,16 @@ static void fc_exch_reset(struct fc_exch *ep) } /** - * fc_exch_pool_reset() - Resets an per cpu exches pool. - * @lport: ptr to the local port - * @pool: ptr to the per cpu exches pool - * @sid: source FC ID - * @did: destination FC ID + * fc_exch_pool_reset() - Reset a per cpu exchange pool + * @lport: The local port that the exchange pool is on + * @pool: The exchange pool to be reset + * @sid: The source ID + * @did: The destination ID * - * Resets an per cpu exches pool, releasing its all sequences - * and exchanges. If sid is non-zero, then reset only exchanges - * we sourced from that FID. If did is non-zero, reset only - * exchanges destined to that FID. + * Resets a per cpu exches pool, releasing all of its sequences + * and exchanges. If sid is non-zero then reset only exchanges + * we sourced from the local port's FID. If did is non-zero then + * only reset exchanges destined for the local port's FID. */ static void fc_exch_pool_reset(struct fc_lport *lport, struct fc_exch_pool *pool, @@ -1543,15 +1687,15 @@ restart: } /** - * fc_exch_mgr_reset() - Resets all EMs of a lport - * @lport: ptr to the local port - * @sid: source FC ID - * @did: destination FC ID + * fc_exch_mgr_reset() - Reset all EMs of a local port + * @lport: The local port whose EMs are to be reset + * @sid: The source ID + * @did: The destination ID * - * Reset all EMs of a lport, releasing its all sequences and - * exchanges. If sid is non-zero, then reset only exchanges - * we sourced from that FID. If did is non-zero, reset only - * exchanges destined to that FID. + * Reset all EMs associated with a given local port. Release all + * sequences and exchanges. If sid is non-zero then reset only the + * exchanges sent from the local port's FID. If did is non-zero then + * reset only exchanges destined for the local port's FID. */ void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did) { @@ -1567,8 +1711,11 @@ void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did) } EXPORT_SYMBOL(fc_exch_mgr_reset); -/* - * Handle incoming ELS REC - Read Exchange Concise. +/** + * fc_exch_els_rec() - Handler for ELS REC (Read Exchange Concise) requests + * @sp: The sequence the REC is on + * @rfp: The REC frame + * * Note that the requesting port may be different than the S_ID in the request. */ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) @@ -1650,10 +1797,11 @@ reject: fc_frame_free(rfp); } -/* - * Handle response from RRQ. - * Not much to do here, really. - * Should report errors. +/** + * fc_exch_rrq_resp() - Handler for RRQ responses + * @sp: The sequence that the RRQ is on + * @fp: The RRQ frame + * @arg: The exchange that the RRQ is on * * TODO: fix error handler. */ @@ -1695,11 +1843,25 @@ cleanup: /** - * This function is for exch_seq_send function pointer in - * struct libfc_function_template, see comment block on - * exch_seq_send for description of this function. + * fc_exch_seq_send() - Send a frame using a new exchange and sequence + * @lport: The local port to send the frame on + * @fp: The frame to be sent + * @resp: The response handler for this request + * @destructor: The destructor for the exchange + * @arg: The argument to be passed to the response handler + * @timer_msec: The timeout period for the exchange + * + * The frame pointer with some of the header's fields must be + * filled before calling this routine, those fields are: + * + * - routing control + * - FC port did + * - FC port sid + * - FC header type + * - frame control + * - parameter or relative offset */ -static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, +static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, struct fc_frame *fp, void (*resp)(struct fc_seq *, struct fc_frame *fp, @@ -1713,7 +1875,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, struct fc_frame_header *fh; int rc = 1; - ep = fc_exch_alloc(lp, fp); + ep = fc_exch_alloc(lport, fp); if (!ep) { fc_frame_free(fp); return NULL; @@ -1725,7 +1887,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, ep->destructor = destructor; ep->arg = arg; ep->r_a_tov = FC_DEF_R_A_TOV; - ep->lp = lp; + ep->lp = lport; sp = &ep->seq; ep->fh_type = fh->fh_type; /* save for possbile timeout handling */ @@ -1733,10 +1895,10 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, fc_exch_setup_hdr(ep, fp, ep->f_ctl); sp->cnt++; - if (ep->xid <= lp->lro_xid) + if (ep->xid <= lport->lro_xid) fc_fcp_ddp_setup(fr_fsp(fp), ep->xid); - if (unlikely(lp->tt.frame_send(lp, fp))) + if (unlikely(lport->tt.frame_send(lport, fp))) goto err; if (timer_msec) @@ -1755,21 +1917,23 @@ err: return NULL; } -/* - * Send ELS RRQ - Reinstate Recovery Qualifier. +/** + * fc_exch_rrq() - Send an ELS RRQ (Reinstate Recovery Qualifier) command + * @ep: The exchange to send the RRQ on + * * This tells the remote port to stop blocking the use of * the exchange and the seq_cnt range. */ static void fc_exch_rrq(struct fc_exch *ep) { - struct fc_lport *lp; + struct fc_lport *lport; struct fc_els_rrq *rrq; struct fc_frame *fp; u32 did; - lp = ep->lp; + lport = ep->lp; - fp = fc_frame_alloc(lp, sizeof(*rrq)); + fp = fc_frame_alloc(lport, sizeof(*rrq)); if (!fp) goto retry; @@ -1785,10 +1949,11 @@ static void fc_exch_rrq(struct fc_exch *ep) did = ep->sid; fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, did, - fc_host_port_id(lp->host), FC_TYPE_ELS, + fc_host_port_id(lport->host), FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); - if (fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep, lp->e_d_tov)) + if (fc_exch_seq_send(lport, fp, fc_exch_rrq_resp, NULL, ep, + lport->e_d_tov)) return; retry: @@ -1805,8 +1970,10 @@ retry: } -/* - * Handle incoming ELS RRQ - Reset Recovery Qualifier. +/** + * fc_exch_els_rrq() - Handler for ELS RRQ (Reset Recovery Qualifier) requests + * @sp: The sequence that the RRQ is on + * @fp: The RRQ frame */ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) { @@ -1872,6 +2039,12 @@ out: fc_exch_release(ep); /* drop hold from fc_exch_find */ } +/** + * fc_exch_mgr_add() - Add an exchange manager to a local port's list of EMs + * @lport: The local port to add the exchange manager to + * @mp: The exchange manager to be added to the local port + * @match: The match routine that indicates when this EM should be used + */ struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport, struct fc_exch_mgr *mp, bool (*match)(struct fc_frame *)) @@ -1891,6 +2064,10 @@ struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport, } EXPORT_SYMBOL(fc_exch_mgr_add); +/** + * fc_exch_mgr_destroy() - Destroy an exchange manager + * @kref: The reference to the EM to be destroyed + */ static void fc_exch_mgr_destroy(struct kref *kref) { struct fc_exch_mgr *mp = container_of(kref, struct fc_exch_mgr, kref); @@ -1900,6 +2077,10 @@ static void fc_exch_mgr_destroy(struct kref *kref) kfree(mp); } +/** + * fc_exch_mgr_del() - Delete an EM from a local port's list + * @ema: The exchange manager anchor identifying the EM to be deleted + */ void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema) { /* remove EM anchor from EM anchors list */ @@ -1910,9 +2091,9 @@ void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema) EXPORT_SYMBOL(fc_exch_mgr_del); /** - * fc_exch_mgr_list_clone() - share all exchange manager objects - * @src: source lport to clone exchange managers from - * @dst: new lport that takes references to all the exchange managers + * fc_exch_mgr_list_clone() - Share all exchange manager objects + * @src: Source lport to clone exchange managers from + * @dst: New lport that takes references to all the exchange managers */ int fc_exch_mgr_list_clone(struct fc_lport *src, struct fc_lport *dst) { @@ -1929,7 +2110,15 @@ err: return -ENOMEM; } -struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, +/** + * fc_exch_mgr_alloc() - Allocate an exchange manager + * @lport: The local port that the new EM will be associated with + * @class: The default FC class for new exchanges + * @min_xid: The minimum XID for exchanges from the new EM + * @max_xid: The maximum XID for exchanges from the new EM + * @match: The match routine for the new EM + */ +struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport, enum fc_class class, u16 min_xid, u16 max_xid, bool (*match)(struct fc_frame *)) @@ -1942,7 +2131,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN || (min_xid & fc_cpu_mask) != 0) { - FC_LPORT_DBG(lp, "Invalid min_xid 0x:%x and max_xid 0x:%x\n", + FC_LPORT_DBG(lport, "Invalid min_xid 0x:%x and max_xid 0x:%x\n", min_xid, max_xid); return NULL; } @@ -1985,7 +2174,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, } kref_init(&mp->kref); - if (!fc_exch_mgr_add(lp, mp, match)) { + if (!fc_exch_mgr_add(lport, mp, match)) { free_percpu(mp->pool); goto free_mempool; } @@ -2006,6 +2195,10 @@ free_mp: } EXPORT_SYMBOL(fc_exch_mgr_alloc); +/** + * fc_exch_mgr_free() - Free all exchange managers on a local port + * @lport: The local port whose EMs are to be freed + */ void fc_exch_mgr_free(struct fc_lport *lport) { struct fc_exch_mgr_anchor *ema, *next; @@ -2015,10 +2208,12 @@ void fc_exch_mgr_free(struct fc_lport *lport) } EXPORT_SYMBOL(fc_exch_mgr_free); -/* - * Receive a frame +/** + * fc_exch_recv() - Handler for received frames + * @lport: The local port the frame was received on + * @fp: The received frame */ -void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp) +void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); struct fc_exch_mgr_anchor *ema; @@ -2026,8 +2221,8 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp) u16 oxid; /* lport lock ? */ - if (!lp || lp->state == LPORT_ST_DISABLED) { - FC_LPORT_DBG(lp, "Receiving frames for an lport that " + if (!lport || lport->state == LPORT_ST_DISABLED) { + FC_LPORT_DBG(lport, "Receiving frames for an lport that " "has not been initialized correctly\n"); fc_frame_free(fp); return; @@ -2036,7 +2231,7 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp) f_ctl = ntoh24(fh->fh_f_ctl); oxid = ntohs(fh->fh_ox_id); if (f_ctl & FC_FC_EX_CTX) { - list_for_each_entry(ema, &lp->ema_list, ema_list) { + list_for_each_entry(ema, &lport->ema_list, ema_list) { if ((oxid >= ema->mp->min_xid) && (oxid <= ema->mp->max_xid)) { found = 1; @@ -2045,13 +2240,13 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp) } if (!found) { - FC_LPORT_DBG(lp, "Received response for out " + FC_LPORT_DBG(lport, "Received response for out " "of range oxid:%hx\n", oxid); fc_frame_free(fp); return; } } else - ema = list_entry(lp->ema_list.prev, typeof(*ema), ema_list); + ema = list_entry(lport->ema_list.prev, typeof(*ema), ema_list); /* * If frame is marked invalid, just drop it. @@ -2070,37 +2265,42 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp) else if (f_ctl & FC_FC_SEQ_CTX) fc_exch_recv_resp(ema->mp, fp); else - fc_exch_recv_req(lp, ema->mp, fp); + fc_exch_recv_req(lport, ema->mp, fp); break; default: - FC_LPORT_DBG(lp, "dropping invalid frame (eof %x)", fr_eof(fp)); + FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)", + fr_eof(fp)); fc_frame_free(fp); } } EXPORT_SYMBOL(fc_exch_recv); -int fc_exch_init(struct fc_lport *lp) +/** + * fc_exch_init() - Initialize the exchange layer for a local port + * @lport: The local port to initialize the exchange layer for + */ +int fc_exch_init(struct fc_lport *lport) { - if (!lp->tt.seq_start_next) - lp->tt.seq_start_next = fc_seq_start_next; + if (!lport->tt.seq_start_next) + lport->tt.seq_start_next = fc_seq_start_next; - if (!lp->tt.exch_seq_send) - lp->tt.exch_seq_send = fc_exch_seq_send; + if (!lport->tt.exch_seq_send) + lport->tt.exch_seq_send = fc_exch_seq_send; - if (!lp->tt.seq_send) - lp->tt.seq_send = fc_seq_send; + if (!lport->tt.seq_send) + lport->tt.seq_send = fc_seq_send; - if (!lp->tt.seq_els_rsp_send) - lp->tt.seq_els_rsp_send = fc_seq_els_rsp_send; + if (!lport->tt.seq_els_rsp_send) + lport->tt.seq_els_rsp_send = fc_seq_els_rsp_send; - if (!lp->tt.exch_done) - lp->tt.exch_done = fc_exch_done; + if (!lport->tt.exch_done) + lport->tt.exch_done = fc_exch_done; - if (!lp->tt.exch_mgr_reset) - lp->tt.exch_mgr_reset = fc_exch_mgr_reset; + if (!lport->tt.exch_mgr_reset) + lport->tt.exch_mgr_reset = fc_exch_mgr_reset; - if (!lp->tt.seq_exch_abort) - lp->tt.seq_exch_abort = fc_seq_exch_abort; + if (!lport->tt.seq_exch_abort) + lport->tt.seq_exch_abort = fc_seq_exch_abort; return 0; } @@ -2141,7 +2341,10 @@ int fc_setup_exch_mgr() return 0; } -void fc_destroy_exch_mgr(void) +/** + * fc_destroy_exch_mgr() - Destroy an exchange manager + */ +void fc_destroy_exch_mgr() { kmem_cache_destroy(fc_em_cachep); } diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 98279fe0d0c..970b54f653b 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -67,10 +67,16 @@ struct kmem_cache *scsi_pkt_cachep; #define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status) #define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual) +/** + * struct fc_fcp_internal - FCP layer internal data + * @scsi_pkt_pool: Memory pool to draw FCP packets from + * @scsi_pkt_queue: Current FCP packets + * @throttled: The FCP packet queue is throttled + */ struct fc_fcp_internal { - mempool_t *scsi_pkt_pool; + mempool_t *scsi_pkt_pool; struct list_head scsi_pkt_queue; - u8 throttled; + u8 throttled; }; #define fc_get_scsi_internal(x) ((struct fc_fcp_internal *)(x)->scsi_priv) @@ -84,9 +90,9 @@ static void fc_fcp_recv(struct fc_seq *, struct fc_frame *, void *); static void fc_fcp_resp(struct fc_fcp_pkt *, struct fc_frame *); static void fc_fcp_complete_locked(struct fc_fcp_pkt *); static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *); -static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp); +static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *); static void fc_timeout_error(struct fc_fcp_pkt *); -static void fc_fcp_timeout(unsigned long data); +static void fc_fcp_timeout(unsigned long); static void fc_fcp_rec(struct fc_fcp_pkt *); static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *); static void fc_fcp_rec_resp(struct fc_seq *, struct fc_frame *, void *); @@ -125,23 +131,22 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *); #define FC_FCP_DFLT_QUEUE_DEPTH 32 /** - * fc_fcp_pkt_alloc - allocation routine for scsi_pkt packet - * @lp: fc lport struct - * @gfp: gfp flags for allocation + * fc_fcp_pkt_alloc() - Allocate a fcp_pkt + * @lport: The local port that the FCP packet is for + * @gfp: GFP flags for allocation * - * This is used by upper layer scsi driver. - * Return Value : scsi_pkt structure or null on allocation failure. - * Context : call from process context. no locking required. + * Return value: fcp_pkt structure or null on allocation failure. + * Context: Can be called from process context, no lock is required. */ -static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp) +static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp) { - struct fc_fcp_internal *si = fc_get_scsi_internal(lp); + struct fc_fcp_internal *si = fc_get_scsi_internal(lport); struct fc_fcp_pkt *fsp; fsp = mempool_alloc(si->scsi_pkt_pool, gfp); if (fsp) { memset(fsp, 0, sizeof(*fsp)); - fsp->lp = lp; + fsp->lp = lport; atomic_set(&fsp->ref_cnt, 1); init_timer(&fsp->timer); INIT_LIST_HEAD(&fsp->list); @@ -151,12 +156,11 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp) } /** - * fc_fcp_pkt_release() - release hold on scsi_pkt packet - * @fsp: fcp packet struct + * fc_fcp_pkt_release() - Release hold on a fcp_pkt + * @fsp: The FCP packet to be released * - * This is used by upper layer scsi driver. - * Context : call from process and interrupt context. - * no locking required + * Context: Can be called from process or interrupt context, + * no lock is required. */ static void fc_fcp_pkt_release(struct fc_fcp_pkt *fsp) { @@ -167,20 +171,25 @@ static void fc_fcp_pkt_release(struct fc_fcp_pkt *fsp) } } +/** + * fc_fcp_pkt_hold() - Hold a fcp_pkt + * @fsp: The FCP packet to be held + */ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp) { atomic_inc(&fsp->ref_cnt); } /** - * fc_fcp_pkt_destory() - release hold on scsi_pkt packet - * @seq: exchange sequence - * @fsp: fcp packet struct + * fc_fcp_pkt_destory() - Release hold on a fcp_pkt + * @seq: The sequence that the FCP packet is on (required by destructor API) + * @fsp: The FCP packet to be released + * + * This routine is called by a destructor callback in the exch_seq_send() + * routine of the libfc Transport Template. The 'struct fc_seq' is a required + * argument even though it is not used by this routine. * - * Release hold on scsi_pkt packet set to keep scsi_pkt - * till EM layer exch resource is not freed. - * Context : called from from EM layer. - * no locking required + * Context: No locking required. */ static void fc_fcp_pkt_destroy(struct fc_seq *seq, void *fsp) { @@ -188,10 +197,10 @@ static void fc_fcp_pkt_destroy(struct fc_seq *seq, void *fsp) } /** - * fc_fcp_lock_pkt() - lock a packet and get a ref to it. - * @fsp: fcp packet + * fc_fcp_lock_pkt() - Lock a fcp_pkt and increase its reference count + * @fsp: The FCP packet to be locked and incremented * - * We should only return error if we return a command to scsi-ml before + * We should only return error if we return a command to SCSI-ml before * getting a response. This can happen in cases where we send a abort, but * do not wait for the response and the abort and command can be passing * each other on the wire/network-layer. @@ -216,18 +225,33 @@ static inline int fc_fcp_lock_pkt(struct fc_fcp_pkt *fsp) return 0; } +/** + * fc_fcp_unlock_pkt() - Release a fcp_pkt's lock and decrement its + * reference count + * @fsp: The FCP packet to be unlocked and decremented + */ static inline void fc_fcp_unlock_pkt(struct fc_fcp_pkt *fsp) { spin_unlock_bh(&fsp->scsi_pkt_lock); fc_fcp_pkt_release(fsp); } +/** + * fc_fcp_timer_set() - Start a timer for a fcp_pkt + * @fsp: The FCP packet to start a timer for + * @delay: The timeout period for the timer + */ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay) { if (!(fsp->state & FC_SRB_COMPL)) mod_timer(&fsp->timer, jiffies + delay); } +/** + * fc_fcp_send_abort() - Send an abort for exchanges associated with a + * fcp_pkt + * @fsp: The FCP packet to abort exchanges on + */ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) { if (!fsp->seq_ptr) @@ -237,9 +261,14 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) return fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0); } -/* - * Retry command. - * An abort isn't needed. +/** + * fc_fcp_retry_cmd() - Retry a fcp_pkt + * @fsp: The FCP packet to be retried + * + * Sets the status code to be FC_ERROR and then calls + * fc_fcp_complete_locked() which in turn calls fc_io_compl(). + * fc_io_compl() will notify the SCSI-ml that the I/O is done. + * The SCSI-ml will retry the command. */ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) { @@ -254,43 +283,35 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) fc_fcp_complete_locked(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 +/** + * fc_fcp_ddp_setup() - Calls a LLD's ddp_setup routine to set up DDP context + * @fsp: The FCP packet that will manage the DDP frames + * @xid: The XID that will be used for the DDP exchange */ void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid) { - struct fc_lport *lp; + struct fc_lport *lport; if (!fsp) return; - lp = fsp->lp; + lport = 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))) + (lport->lro_enabled) && (lport->tt.ddp_setup)) { + if (lport->tt.ddp_setup(lport, xid, scsi_sglist(fsp->cmd), + scsi_sg_count(fsp->cmd))) fsp->xfer_ddp = xid; } } -/* - * 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 +/** + * fc_fcp_ddp_done() - Calls a LLD's ddp_done routine to release any + * DDP related resources for a fcp_pkt + * @fsp: The FCP packet that DDP had been used on */ static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) { - struct fc_lport *lp; + struct fc_lport *lport; if (!fsp) return; @@ -298,22 +319,22 @@ static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) if (fsp->xfer_ddp == FC_XID_UNKNOWN) return; - lp = fsp->lp; - if (lp->tt.ddp_done) { - fsp->xfer_len = lp->tt.ddp_done(lp, fsp->xfer_ddp); + lport = fsp->lp; + if (lport->tt.ddp_done) { + fsp->xfer_len = lport->tt.ddp_done(lport, fsp->xfer_ddp); fsp->xfer_ddp = FC_XID_UNKNOWN; } } - -/* - * Receive SCSI data from target. - * Called after receiving solicited data. +/** + * fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target + * @fsp: The FCP packet the data is on + * @fp: The data frame */ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) { struct scsi_cmnd *sc = fsp->cmd; - struct fc_lport *lp = fsp->lp; + struct fc_lport *lport = fsp->lp; struct fcoe_dev_stats *stats; struct fc_frame_header *fh; size_t start_offset; @@ -363,13 +384,13 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if (~crc != le32_to_cpu(fr_crc(fp))) { crc_err: - stats = fc_lport_get_stats(lp); + stats = fc_lport_get_stats(lport); stats->ErrorFrames++; /* FIXME - per cpu count, not total count! */ if (stats->InvalidCRCCount++ < 5) printk(KERN_WARNING "libfc: CRC error on data " "frame for port (%6x)\n", - fc_host_port_id(lp->host)); + fc_host_port_id(lport->host)); /* * Assume the frame is total garbage. * We may have copied it over the good part @@ -397,18 +418,17 @@ crc_err: } /** - * fc_fcp_send_data() - Send SCSI data to target. - * @fsp: ptr to fc_fcp_pkt - * @sp: ptr to this sequence - * @offset: starting offset for this data request - * @seq_blen: the burst length for this data request + * fc_fcp_send_data() - Send SCSI data to a target + * @fsp: The FCP packet the data is on + * @sp: The sequence the data is to be sent on + * @offset: The starting offset for this data request + * @seq_blen: The burst length for this data request * * Called after receiving a Transfer Ready data descriptor. - * if LLD is capable of seq offload then send down seq_blen - * size of data in single frame, otherwise send multiple FC - * frames of max FC frame payload supported by target port. - * - * Returns : 0 for success. + * If the LLD is capable of sequence offload then send down the + * seq_blen ammount of data in single frame, otherwise send + * multiple frames of the maximum frame payload supported by + * the target port. */ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, size_t offset, size_t seq_blen) @@ -417,7 +437,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, struct scsi_cmnd *sc; struct scatterlist *sg; struct fc_frame *fp = NULL; - struct fc_lport *lp = fsp->lp; + struct fc_lport *lport = fsp->lp; size_t remaining; size_t t_blen; size_t tlen; @@ -426,7 +446,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, int error; void *data = NULL; void *page_addr; - int using_sg = lp->sg_supp; + int using_sg = lport->sg_supp; u32 f_ctl; WARN_ON(seq_blen <= 0); @@ -448,10 +468,10 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, * to max FC frame payload previously set in fsp->max_payload. */ t_blen = fsp->max_payload; - if (lp->seq_offload) { - t_blen = min(seq_blen, (size_t)lp->lso_max); + if (lport->seq_offload) { + t_blen = min(seq_blen, (size_t)lport->lso_max); FC_FCP_DBG(fsp, "fsp=%p:lso:blen=%zx lso_max=0x%x t_blen=%zx\n", - fsp, seq_blen, lp->lso_max, t_blen); + fsp, seq_blen, lport->lso_max, t_blen); } WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD); @@ -463,7 +483,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, remaining = seq_blen; fh_parm_offset = frame_offset = offset; tlen = 0; - seq = lp->tt.seq_start_next(seq); + seq = lport->tt.seq_start_next(seq); f_ctl = FC_FC_REL_OFF; WARN_ON(!seq); @@ -486,11 +506,11 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, if (tlen % 4) using_sg = 0; if (using_sg) { - fp = _fc_frame_alloc(lp, 0); + fp = _fc_frame_alloc(lport, 0); if (!fp) return -ENOMEM; } else { - fp = fc_frame_alloc(lp, tlen); + fp = fc_frame_alloc(lport, tlen); if (!fp) return -ENOMEM; @@ -550,7 +570,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, /* * send fragment using for a sequence. */ - error = lp->tt.seq_send(lp, seq, fp); + error = lport->tt.seq_send(lport, seq, fp); if (error) { WARN_ON(1); /* send error should be rare */ fc_fcp_retry_cmd(fsp); @@ -562,6 +582,11 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, return 0; } +/** + * fc_fcp_abts_resp() - Send an ABTS response + * @fsp: The FCP packet that is being aborted + * @fp: The response frame + */ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) { int ba_done = 1; @@ -598,8 +623,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) } /** - * fc_fcp_reduce_can_queue() - drop can_queue - * @lp: lport to drop queueing for + * fc_fcp_reduce_can_queue() - Reduce the can_queue value for a local port + * @lport: The local port to reduce can_queue on * * If we are getting memory allocation failures, then we may * be trying to execute too many commands. We let the running @@ -607,37 +632,36 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) * can_queue. Eventually we will hit the point where we run * on all reserved structs. */ -static void fc_fcp_reduce_can_queue(struct fc_lport *lp) +static void fc_fcp_reduce_can_queue(struct fc_lport *lport) { - struct fc_fcp_internal *si = fc_get_scsi_internal(lp); + struct fc_fcp_internal *si = fc_get_scsi_internal(lport); unsigned long flags; int can_queue; - spin_lock_irqsave(lp->host->host_lock, flags); + spin_lock_irqsave(lport->host->host_lock, flags); if (si->throttled) goto done; si->throttled = 1; - can_queue = lp->host->can_queue; + can_queue = lport->host->can_queue; can_queue >>= 1; if (!can_queue) can_queue = 1; - lp->host->can_queue = can_queue; - shost_printk(KERN_ERR, lp->host, "libfc: Could not allocate frame.\n" + lport->host->can_queue = can_queue; + shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n" "Reducing can_queue to %d.\n", can_queue); done: - spin_unlock_irqrestore(lp->host->host_lock, flags); + spin_unlock_irqrestore(lport->host->host_lock, flags); } /** - * fc_fcp_recv() - Reveive FCP frames + * fc_fcp_recv() - Reveive an FCP frame * @seq: The sequence the frame is on - * @fp: The FC frame + * @fp: The received frame * @arg: The related FCP packet * - * Return : None - * Context : called from Soft IRQ context - * can not called holding list lock + * Context: Called from Soft IRQ context. Can not be called + * holding the FCP packet list lock. */ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) { @@ -710,6 +734,11 @@ errout: fc_fcp_reduce_can_queue(lport); } +/** + * fc_fcp_resp() - Handler for FCP responses + * @fsp: The FCP packet the response is for + * @fp: The response frame + */ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) { struct fc_frame_header *fh; @@ -823,15 +852,16 @@ err: } /** - * fc_fcp_complete_locked() - complete processing of a fcp packet - * @fsp: fcp packet + * fc_fcp_complete_locked() - Complete processing of a fcp_pkt with the + * fcp_pkt lock held + * @fsp: The FCP packet to be completed * * This function may sleep if a timer is pending. The packet lock must be * held, and the host lock must not be held. */ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) { - struct fc_lport *lp = fsp->lp; + struct fc_lport *lport = fsp->lp; struct fc_seq *seq; struct fc_exch *ep; u32 f_ctl; @@ -862,7 +892,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) struct fc_frame *conf_frame; struct fc_seq *csp; - csp = lp->tt.seq_start_next(seq); + csp = lport->tt.seq_start_next(seq); conf_frame = fc_frame_alloc(fsp->lp, 0); if (conf_frame) { f_ctl = FC_FC_SEQ_INIT; @@ -871,43 +901,48 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) fc_fill_fc_hdr(conf_frame, FC_RCTL_DD_SOL_CTL, ep->did, ep->sid, FC_TYPE_FCP, f_ctl, 0); - lp->tt.seq_send(lp, csp, conf_frame); + lport->tt.seq_send(lport, csp, conf_frame); } } - lp->tt.exch_done(seq); + lport->tt.exch_done(seq); } fc_io_compl(fsp); } +/** + * fc_fcp_cleanup_cmd() - Cancel the active exchange on a fcp_pkt + * @fsp: The FCP packet whose exchanges should be canceled + * @error: The reason for the cancellation + */ static void fc_fcp_cleanup_cmd(struct fc_fcp_pkt *fsp, int error) { - struct fc_lport *lp = fsp->lp; + struct fc_lport *lport = fsp->lp; if (fsp->seq_ptr) { - lp->tt.exch_done(fsp->seq_ptr); + lport->tt.exch_done(fsp->seq_ptr); fsp->seq_ptr = NULL; } fsp->status_code = error; } /** - * fc_fcp_cleanup_each_cmd() - Cleanup active commads - * @lp: logical port - * @id: target id - * @lun: lun - * @error: fsp status code + * fc_fcp_cleanup_each_cmd() - Cancel all exchanges on a local port + * @lport: The local port whose exchanges should be canceled + * @id: The target's ID + * @lun: The LUN + * @error: The reason for cancellation * * If lun or id is -1, they are ignored. */ -static void fc_fcp_cleanup_each_cmd(struct fc_lport *lp, unsigned int id, +static void fc_fcp_cleanup_each_cmd(struct fc_lport *lport, unsigned int id, unsigned int lun, int error) { - struct fc_fcp_internal *si = fc_get_scsi_internal(lp); + struct fc_fcp_internal *si = fc_get_scsi_internal(lport); struct fc_fcp_pkt *fsp; struct scsi_cmnd *sc_cmd; unsigned long flags; - spin_lock_irqsave(lp->host->host_lock, flags); + spin_lock_irqsave(lport->host->host_lock, flags); restart: list_for_each_entry(fsp, &si->scsi_pkt_queue, list) { sc_cmd = fsp->cmd; @@ -918,7 +953,7 @@ restart: continue; fc_fcp_pkt_hold(fsp); - spin_unlock_irqrestore(lp->host->host_lock, flags); + spin_unlock_irqrestore(lport->host->host_lock, flags); if (!fc_fcp_lock_pkt(fsp)) { fc_fcp_cleanup_cmd(fsp, error); @@ -927,35 +962,36 @@ restart: } fc_fcp_pkt_release(fsp); - spin_lock_irqsave(lp->host->host_lock, flags); + spin_lock_irqsave(lport->host->host_lock, flags); /* * while we dropped the lock multiple pkts could * have been released, so we have to start over. */ goto restart; } - spin_unlock_irqrestore(lp->host->host_lock, flags); + spin_unlock_irqrestore(lport->host->host_lock, flags); } -static void fc_fcp_abort_io(struct fc_lport *lp) +/** + * fc_fcp_abort_io() - Abort all FCP-SCSI exchanges on a local port + * @lport: The local port whose exchanges are to be aborted + */ +static void fc_fcp_abort_io(struct fc_lport *lport) { - fc_fcp_cleanup_each_cmd(lp, -1, -1, FC_HRD_ERROR); + fc_fcp_cleanup_each_cmd(lport, -1, -1, FC_HRD_ERROR); } /** - * fc_fcp_pkt_send() - send a fcp packet to the lower level. - * @lp: fc lport - * @fsp: fc packet. + * fc_fcp_pkt_send() - Send a fcp_pkt + * @lport: The local port to send the FCP packet on + * @fsp: The FCP packet to send * - * This is called by upper layer protocol. - * Return : zero for success and -1 for failure - * Context : called from queuecommand which can be called from process - * or scsi soft irq. - * Locks : called with the host lock and irqs disabled. + * Return: Zero for success and -1 for failure + * Locks: Called with the host lock and irqs disabled. */ -static int fc_fcp_pkt_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp) +static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) { - struct fc_fcp_internal *si = fc_get_scsi_internal(lp); + struct fc_fcp_internal *si = fc_get_scsi_internal(lport); int rc; fsp->cmd->SCp.ptr = (char *)fsp; @@ -967,16 +1003,22 @@ static int fc_fcp_pkt_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp) memcpy(fsp->cdb_cmd.fc_cdb, fsp->cmd->cmnd, fsp->cmd->cmd_len); list_add_tail(&fsp->list, &si->scsi_pkt_queue); - spin_unlock_irq(lp->host->host_lock); - rc = lp->tt.fcp_cmd_send(lp, fsp, fc_fcp_recv); - spin_lock_irq(lp->host->host_lock); + spin_unlock_irq(lport->host->host_lock); + rc = lport->tt.fcp_cmd_send(lport, fsp, fc_fcp_recv); + spin_lock_irq(lport->host->host_lock); if (rc) list_del(&fsp->list); return rc; } -static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp, +/** + * fc_fcp_cmd_send() - Send a FCP command + * @lport: The local port to send the command on + * @fsp: The FCP packet the command is on + * @resp: The handler for the response + */ +static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg)) @@ -984,14 +1026,14 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp, struct fc_frame *fp; struct fc_seq *seq; struct fc_rport *rport; - struct fc_rport_libfc_priv *rp; + struct fc_rport_libfc_priv *rpriv; const size_t len = sizeof(fsp->cdb_cmd); int rc = 0; if (fc_fcp_lock_pkt(fsp)) return 0; - fp = fc_frame_alloc(lp, sizeof(fsp->cdb_cmd)); + fp = fc_frame_alloc(lport, sizeof(fsp->cdb_cmd)); if (!fp) { rc = -1; goto unlock; @@ -1001,13 +1043,14 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp, fr_fsp(fp) = fsp; rport = fsp->rport; fsp->max_payload = rport->maxframe_size; - rp = rport->dd_data; + rpriv = rport->dd_data; fc_fill_fc_hdr(fp, FC_RCTL_DD_UNSOL_CMD, rport->port_id, - fc_host_port_id(rp->local_port->host), FC_TYPE_FCP, + fc_host_port_id(rpriv->local_port->host), FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); - seq = lp->tt.exch_seq_send(lp, fp, resp, fc_fcp_pkt_destroy, fsp, 0); + seq = lport->tt.exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy, + fsp, 0); if (!seq) { rc = -1; goto unlock; @@ -1025,8 +1068,10 @@ unlock: return rc; } -/* - * transport error handler +/** + * fc_fcp_error() - Handler for FCP layer errors + * @fsp: The FCP packet the error is on + * @fp: The frame that has errored */ static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) { @@ -1051,9 +1096,11 @@ unlock: fc_fcp_unlock_pkt(fsp); } -/* - * Scsi abort handler- calls to send an abort - * and then wait for abort completion +/** + * fc_fcp_pkt_abort() - Abort a fcp_pkt + * @fsp: The FCP packet to abort on + * + * Called to send an abort and then wait for abort completion */ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp) { @@ -1082,14 +1129,15 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp) return rc; } -/* - * Retry LUN reset after resource allocation failed. +/** + * fc_lun_reset_send() - Send LUN reset command + * @data: The FCP packet that identifies the LUN to be reset */ static void fc_lun_reset_send(unsigned long data) { struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data; - struct fc_lport *lp = fsp->lp; - if (lp->tt.fcp_cmd_send(lp, fsp, fc_tm_done)) { + struct fc_lport *lport = fsp->lp; + if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) { if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY) return; if (fc_fcp_lock_pkt(fsp)) @@ -1100,11 +1148,15 @@ static void fc_lun_reset_send(unsigned long data) } } -/* - * Scsi device reset handler- send a LUN RESET to the device - * and wait for reset reply +/** + * fc_lun_reset() - Send a LUN RESET command to a device + * and wait for the reply + * @lport: The local port to sent the comand on + * @fsp: The FCP packet that identifies the LUN to be reset + * @id: The SCSI command ID + * @lun: The LUN ID to be reset */ -static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp, +static int fc_lun_reset(struct fc_lport *lport, struct fc_fcp_pkt *fsp, unsigned int id, unsigned int lun) { int rc; @@ -1132,14 +1184,14 @@ static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp, spin_lock_bh(&fsp->scsi_pkt_lock); if (fsp->seq_ptr) { - lp->tt.exch_done(fsp->seq_ptr); + lport->tt.exch_done(fsp->seq_ptr); fsp->seq_ptr = NULL; } fsp->wait_for_comp = 0; spin_unlock_bh(&fsp->scsi_pkt_lock); if (!rc) { - FC_SCSI_DBG(lp, "lun reset failed\n"); + FC_SCSI_DBG(lport, "lun reset failed\n"); return FAILED; } @@ -1147,13 +1199,16 @@ static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp, if (fsp->cdb_status != FCP_TMF_CMPL) return FAILED; - FC_SCSI_DBG(lp, "lun reset to lun %u completed\n", lun); - fc_fcp_cleanup_each_cmd(lp, id, lun, FC_CMD_ABORTED); + FC_SCSI_DBG(lport, "lun reset to lun %u completed\n", lun); + fc_fcp_cleanup_each_cmd(lport, id, lun, FC_CMD_ABORTED); return SUCCESS; } -/* - * Task Managment response handler +/** + * fc_tm_done() - Task Managment response handler + * @seq: The sequence that the response is on + * @fp: The response frame + * @arg: The FCP packet the response is for */ static void fc_tm_done(struct fc_seq *seq, struct fc_frame *fp, void *arg) { @@ -1190,34 +1245,31 @@ static void fc_tm_done(struct fc_seq *seq, struct fc_frame *fp, void *arg) fc_fcp_unlock_pkt(fsp); } -static void fc_fcp_cleanup(struct fc_lport *lp) +/** + * fc_fcp_cleanup() - Cleanup all FCP exchanges on a local port + * @lport: The local port to be cleaned up + */ +static void fc_fcp_cleanup(struct fc_lport *lport) { - fc_fcp_cleanup_each_cmd(lp, -1, -1, FC_ERROR); + fc_fcp_cleanup_each_cmd(lport, -1, -1, FC_ERROR); } -/* - * fc_fcp_timeout: called by OS timer function. - * - * The timer has been inactivated and must be reactivated if desired - * using fc_fcp_timer_set(). - * - * Algorithm: - * - * If REC is supported, just issue it, and return. The REC exchange will - * complete or time out, and recovery can continue at that point. - * - * Otherwise, if the response has been received without all the data, - * it has been ER_TIMEOUT since the response was received. +/** + * fc_fcp_timeout() - Handler for fcp_pkt timeouts + * @data: The FCP packet that has timed out * - * If the response has not been received, - * we see if data was received recently. If it has been, we continue waiting, - * otherwise, we abort the command. + * If REC is supported then just issue it and return. The REC exchange will + * complete or time out and recovery can continue at that point. Otherwise, + * if the response has been received without all the data it has been + * ER_TIMEOUT since the response was received. If the response has not been + * received we see if data was received recently. If it has been then we + * continue waiting, otherwise, we abort the command. */ static void fc_fcp_timeout(unsigned long data) { struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data; struct fc_rport *rport = fsp->rport; - struct fc_rport_libfc_priv *rp = rport->dd_data; + struct fc_rport_libfc_priv *rpriv = rport->dd_data; if (fc_fcp_lock_pkt(fsp)) return; @@ -1227,7 +1279,7 @@ static void fc_fcp_timeout(unsigned long data) fsp->state |= FC_SRB_FCP_PROCESSING_TMO; - if (rp->flags & FC_RP_FLAGS_REC_SUPPORTED) + if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) fc_fcp_rec(fsp); else if (time_after_eq(fsp->last_pkt_time + (FC_SCSI_ER_TIMEOUT / 2), jiffies)) @@ -1241,35 +1293,37 @@ unlock: fc_fcp_unlock_pkt(fsp); } -/* - * Send a REC ELS request +/** + * fc_fcp_rec() - Send a REC ELS request + * @fsp: The FCP packet to send the REC request on */ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) { - struct fc_lport *lp; + struct fc_lport *lport; struct fc_frame *fp; struct fc_rport *rport; - struct fc_rport_libfc_priv *rp; + struct fc_rport_libfc_priv *rpriv; - lp = fsp->lp; + lport = fsp->lp; rport = fsp->rport; - rp = rport->dd_data; - if (!fsp->seq_ptr || rp->rp_state != RPORT_ST_READY) { + rpriv = rport->dd_data; + if (!fsp->seq_ptr || rpriv->rp_state != RPORT_ST_READY) { fsp->status_code = FC_HRD_ERROR; fsp->io_status = 0; fc_fcp_complete_locked(fsp); return; } - fp = fc_frame_alloc(lp, sizeof(struct fc_els_rec)); + fp = fc_frame_alloc(lport, sizeof(struct fc_els_rec)); if (!fp) goto retry; fr_seq(fp) = fsp->seq_ptr; fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id, - fc_host_port_id(rp->local_port->host), FC_TYPE_ELS, + fc_host_port_id(rpriv->local_port->host), FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); - if (lp->tt.elsct_send(lp, rport->port_id, fp, ELS_REC, fc_fcp_rec_resp, - fsp, jiffies_to_msecs(FC_SCSI_REC_TOV))) { + if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, + fc_fcp_rec_resp, fsp, + jiffies_to_msecs(FC_SCSI_REC_TOV))) { fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */ return; } @@ -1280,12 +1334,16 @@ retry: fc_timeout_error(fsp); } -/* - * Receive handler for REC ELS frame - * if it is a reject then let the scsi layer to handle - * the timeout. if it is a LS_ACC then if the io was not completed - * then set the timeout and return otherwise complete the exchange - * and tell the scsi layer to restart the I/O. +/** + * fc_fcp_rec_resp() - Handler for REC ELS responses + * @seq: The sequence the response is on + * @fp: The response frame + * @arg: The FCP packet the response is on + * + * If the response is a reject then the scsi layer will handle + * the timeout. If the response is a LS_ACC then if the I/O was not completed + * set the timeout and return. If the I/O was completed then complete the + * exchange and tell the SCSI layer. */ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) { @@ -1297,7 +1355,7 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) u32 offset; enum dma_data_direction data_dir; enum fc_rctl r_ctl; - struct fc_rport_libfc_priv *rp; + struct fc_rport_libfc_priv *rpriv; if (IS_ERR(fp)) { fc_fcp_rec_error(fsp, fp); @@ -1320,13 +1378,13 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) /* fall through */ case ELS_RJT_UNSUP: FC_FCP_DBG(fsp, "device does not support REC\n"); - rp = fsp->rport->dd_data; + rpriv = fsp->rport->dd_data; /* * if we do not spport RECs or got some bogus * reason then resetup timer so we check for * making progress. */ - rp->flags &= ~FC_RP_FLAGS_REC_SUPPORTED; + rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED; fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT); break; case ELS_RJT_LOGIC: @@ -1423,8 +1481,10 @@ out: fc_frame_free(fp); } -/* - * Handle error response or timeout for REC exchange. +/** + * fc_fcp_rec_error() - Handler for REC errors + * @fsp: The FCP packet the error is on + * @fp: The REC frame */ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) { @@ -1463,10 +1523,9 @@ out: fc_fcp_pkt_release(fsp); /* drop hold for outstanding REC */ } -/* - * Time out error routine: - * abort's the I/O close the exchange and - * send completion notification to scsi layer +/** + * fc_timeout_error() - Handler for fcp_pkt timeouts + * @fsp: The FCP packt that has timed out */ static void fc_timeout_error(struct fc_fcp_pkt *fsp) { @@ -1480,16 +1539,18 @@ static void fc_timeout_error(struct fc_fcp_pkt *fsp) fc_fcp_send_abort(fsp); } -/* - * Sequence retransmission request. +/** + * fc_fcp_srr() - Send a SRR request (Sequence Retransmission Request) + * @fsp: The FCP packet the SRR is to be sent on + * @r_ctl: The R_CTL field for the SRR request * This is called after receiving status but insufficient data, or * when expecting status but the request has timed out. */ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) { - struct fc_lport *lp = fsp->lp; + struct fc_lport *lport = fsp->lp; struct fc_rport *rport; - struct fc_rport_libfc_priv *rp; + struct fc_rport_libfc_priv *rpriv; struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr); struct fc_seq *seq; struct fcp_srr *srr; @@ -1497,12 +1558,13 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) u8 cdb_op; rport = fsp->rport; - rp = rport->dd_data; + rpriv = rport->dd_data; cdb_op = fsp->cdb_cmd.fc_cdb[0]; - if (!(rp->flags & FC_RP_FLAGS_RETRY) || rp->rp_state != RPORT_ST_READY) + if (!(rpriv->flags & FC_RP_FLAGS_RETRY) || + rpriv->rp_state != RPORT_ST_READY) goto retry; /* shouldn't happen */ - fp = fc_frame_alloc(lp, sizeof(*srr)); + fp = fc_frame_alloc(lport, sizeof(*srr)); if (!fp) goto retry; @@ -1515,11 +1577,11 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) srr->srr_rel_off = htonl(offset); fc_fill_fc_hdr(fp, FC_RCTL_ELS4_REQ, rport->port_id, - fc_host_port_id(rp->local_port->host), FC_TYPE_FCP, + fc_host_port_id(rpriv->local_port->host), FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); - seq = lp->tt.exch_seq_send(lp, fp, fc_fcp_srr_resp, NULL, - fsp, jiffies_to_msecs(FC_SCSI_REC_TOV)); + seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, + fsp, jiffies_to_msecs(FC_SCSI_REC_TOV)); if (!seq) goto retry; @@ -1533,8 +1595,11 @@ retry: fc_fcp_retry_cmd(fsp); } -/* - * Handle response from SRR. +/** + * fc_fcp_srr_resp() - Handler for SRR response + * @seq: The sequence the SRR is on + * @fp: The SRR frame + * @arg: The FCP packet the SRR is on */ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) { @@ -1580,6 +1645,11 @@ out: fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */ } +/** + * fc_fcp_srr_error() - Handler for SRR errors + * @fsp: The FCP packet that the SRR error is on + * @fp: The SRR frame + */ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) { if (fc_fcp_lock_pkt(fsp)) @@ -1604,31 +1674,36 @@ out: fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */ } -static inline int fc_fcp_lport_queue_ready(struct fc_lport *lp) +/** + * fc_fcp_lport_queue_ready() - Determine if the lport and it's queue is ready + * @lport: The local port to be checked + */ +static inline int fc_fcp_lport_queue_ready(struct fc_lport *lport) { /* lock ? */ - return (lp->state == LPORT_ST_READY) && lp->link_up && !lp->qfull; + return (lport->state == LPORT_ST_READY) && + lport->link_up && !lport->qfull; } /** - * fc_queuecommand - The queuecommand function of the scsi template - * @cmd: struct scsi_cmnd to be executed - * @done: Callback function to be called when cmd is completed + * fc_queuecommand() - The queuecommand function of the SCSI template + * @cmd: The scsi_cmnd to be executed + * @done: The callback function to be called when the scsi_cmnd is complete * - * this is the i/o strategy routine, called by the scsi layer - * this routine is called with holding the host_lock. + * This is the i/o strategy routine, called by the SCSI layer. This routine + * is called with the host_lock held. */ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) { - struct fc_lport *lp; + struct fc_lport *lport; struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device)); struct fc_fcp_pkt *fsp; - struct fc_rport_libfc_priv *rp; + struct fc_rport_libfc_priv *rpriv; int rval; int rc = 0; struct fcoe_dev_stats *stats; - lp = shost_priv(sc_cmd->device->host); + lport = shost_priv(sc_cmd->device->host); rval = fc_remote_port_chkready(rport); if (rval) { @@ -1647,14 +1722,14 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) goto out; } - rp = rport->dd_data; + rpriv = rport->dd_data; - if (!fc_fcp_lport_queue_ready(lp)) { + if (!fc_fcp_lport_queue_ready(lport)) { rc = SCSI_MLQUEUE_HOST_BUSY; goto out; } - fsp = fc_fcp_pkt_alloc(lp, GFP_ATOMIC); + fsp = fc_fcp_pkt_alloc(lport, GFP_ATOMIC); if (fsp == NULL) { rc = SCSI_MLQUEUE_HOST_BUSY; goto out; @@ -1664,7 +1739,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) * build the libfc request pkt */ fsp->cmd = sc_cmd; /* save the cmd */ - fsp->lp = lp; /* save the softc ptr */ + fsp->lp = lport; /* save the softc ptr */ fsp->rport = rport; /* set the remote port ptr */ fsp->xfer_ddp = FC_XID_UNKNOWN; sc_cmd->scsi_done = done; @@ -1678,7 +1753,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) /* * setup the data direction */ - stats = fc_lport_get_stats(lp); + stats = fc_lport_get_stats(lport); if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { fsp->req_flags = FC_SRB_READ; stats->InputRequests++; @@ -1692,7 +1767,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) stats->ControlRequests++; } - fsp->tgt_flags = rp->flags; + fsp->tgt_flags = rpriv->flags; init_timer(&fsp->timer); fsp->timer.data = (unsigned long)fsp; @@ -1702,7 +1777,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) * if we get -1 return then put the request in the pending * queue. */ - rval = fc_fcp_pkt_send(lp, fsp); + rval = fc_fcp_pkt_send(lport, fsp); if (rval != 0) { fsp->state = FC_SRB_FREE; fc_fcp_pkt_release(fsp); @@ -1714,18 +1789,17 @@ out: EXPORT_SYMBOL(fc_queuecommand); /** - * fc_io_compl() - Handle responses for completed commands - * @fsp: scsi packet - * - * Translates a error to a Linux SCSI error. + * fc_io_compl() - Handle responses for completed commands + * @fsp: The FCP packet that is complete * + * Translates fcp_pkt errors to a Linux SCSI errors. * The fcp packet lock must be held when calling. */ static void fc_io_compl(struct fc_fcp_pkt *fsp) { struct fc_fcp_internal *si; struct scsi_cmnd *sc_cmd; - struct fc_lport *lp; + struct fc_lport *lport; unsigned long flags; /* release outstanding ddp context */ @@ -1738,11 +1812,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) spin_lock_bh(&fsp->scsi_pkt_lock); } - lp = fsp->lp; - si = fc_get_scsi_internal(lp); - spin_lock_irqsave(lp->host->host_lock, flags); + lport = fsp->lp; + si = fc_get_scsi_internal(lport); + spin_lock_irqsave(lport->host->host_lock, flags); if (!fsp->cmd) { - spin_unlock_irqrestore(lp->host->host_lock, flags); + spin_unlock_irqrestore(lport->host->host_lock, flags); return; } @@ -1759,7 +1833,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) fsp->cmd = NULL; if (!sc_cmd->SCp.ptr) { - spin_unlock_irqrestore(lp->host->host_lock, flags); + spin_unlock_irqrestore(lport->host->host_lock, flags); return; } @@ -1826,7 +1900,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) list_del(&fsp->list); sc_cmd->SCp.ptr = NULL; sc_cmd->scsi_done(sc_cmd); - spin_unlock_irqrestore(lp->host->host_lock, flags); + spin_unlock_irqrestore(lport->host->host_lock, flags); /* release ref from initial allocation in queue command */ fc_fcp_pkt_release(fsp); @@ -1834,35 +1908,34 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) /** * fc_eh_abort() - Abort a command - * @sc_cmd: scsi command to abort + * @sc_cmd: The SCSI command to abort * - * From scsi host template. - * send ABTS to the target device and wait for the response - * sc_cmd is the pointer to the command to be aborted. + * From SCSI host template. + * Send an ABTS to the target device and wait for the response. */ int fc_eh_abort(struct scsi_cmnd *sc_cmd) { struct fc_fcp_pkt *fsp; - struct fc_lport *lp; + struct fc_lport *lport; int rc = FAILED; unsigned long flags; - lp = shost_priv(sc_cmd->device->host); - if (lp->state != LPORT_ST_READY) + lport = shost_priv(sc_cmd->device->host); + if (lport->state != LPORT_ST_READY) return rc; - else if (!lp->link_up) + else if (!lport->link_up) return rc; - spin_lock_irqsave(lp->host->host_lock, flags); + spin_lock_irqsave(lport->host->host_lock, flags); fsp = CMD_SP(sc_cmd); if (!fsp) { /* command completed while scsi eh was setting up */ - spin_unlock_irqrestore(lp->host->host_lock, flags); + spin_unlock_irqrestore(lport->host->host_lock, flags); return SUCCESS; } /* grab a ref so the fsp and sc_cmd cannot be relased from under us */ fc_fcp_pkt_hold(fsp); - spin_unlock_irqrestore(lp->host->host_lock, flags); + spin_unlock_irqrestore(lport->host->host_lock, flags); if (fc_fcp_lock_pkt(fsp)) { /* completed while we were waiting for timer to be deleted */ @@ -1880,34 +1953,32 @@ release_pkt: EXPORT_SYMBOL(fc_eh_abort); /** - * fc_eh_device_reset() Reset a single LUN - * @sc_cmd: scsi command + * fc_eh_device_reset() - Reset a single LUN + * @sc_cmd: The SCSI command which identifies the device whose + * LUN is to be reset * - * Set from scsi host template to send tm cmd to the target and wait for the - * response. + * Set from SCSI host template. */ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd) { - struct fc_lport *lp; + struct fc_lport *lport; struct fc_fcp_pkt *fsp; struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device)); int rc = FAILED; - struct fc_rport_libfc_priv *rp; int rval; rval = fc_remote_port_chkready(rport); if (rval) goto out; - rp = rport->dd_data; - lp = shost_priv(sc_cmd->device->host); + lport = shost_priv(sc_cmd->device->host); - if (lp->state != LPORT_ST_READY) + if (lport->state != LPORT_ST_READY) return rc; - FC_SCSI_DBG(lp, "Resetting rport (%6x)\n", rport->port_id); + FC_SCSI_DBG(lport, "Resetting rport (%6x)\n", rport->port_id); - fsp = fc_fcp_pkt_alloc(lp, GFP_NOIO); + fsp = fc_fcp_pkt_alloc(lport, GFP_NOIO); if (fsp == NULL) { printk(KERN_WARNING "libfc: could not allocate scsi_pkt\n"); sc_cmd->result = DID_NO_CONNECT << 16; @@ -1919,13 +1990,13 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd) * the sc passed in is not setup for execution like when sent * through the queuecommand callout. */ - fsp->lp = lp; /* save the softc ptr */ + fsp->lp = lport; /* save the softc ptr */ fsp->rport = rport; /* set the remote port ptr */ /* * flush outstanding commands */ - rc = fc_lun_reset(lp, fsp, scmd_id(sc_cmd), sc_cmd->device->lun); + rc = fc_lun_reset(lport, fsp, scmd_id(sc_cmd), sc_cmd->device->lun); fsp->state = FC_SRB_FREE; fc_fcp_pkt_release(fsp); @@ -1935,38 +2006,39 @@ out: EXPORT_SYMBOL(fc_eh_device_reset); /** - * fc_eh_host_reset() - The reset function will reset the ports on the host. - * @sc_cmd: scsi command + * fc_eh_host_reset() - Reset a Scsi_Host. + * @sc_cmd: The SCSI command that identifies the SCSI host to be reset */ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) { struct Scsi_Host *shost = sc_cmd->device->host; - struct fc_lport *lp = shost_priv(shost); + struct fc_lport *lport = shost_priv(shost); unsigned long wait_tmo; - FC_SCSI_DBG(lp, "Resetting host\n"); + FC_SCSI_DBG(lport, "Resetting host\n"); - lp->tt.lport_reset(lp); + lport->tt.lport_reset(lport); wait_tmo = jiffies + FC_HOST_RESET_TIMEOUT; - while (!fc_fcp_lport_queue_ready(lp) && time_before(jiffies, wait_tmo)) + while (!fc_fcp_lport_queue_ready(lport) && time_before(jiffies, + wait_tmo)) msleep(1000); - if (fc_fcp_lport_queue_ready(lp)) { + if (fc_fcp_lport_queue_ready(lport)) { shost_printk(KERN_INFO, shost, "libfc: Host reset succeeded " - "on port (%6x)\n", fc_host_port_id(lp->host)); + "on port (%6x)\n", fc_host_port_id(lport->host)); return SUCCESS; } else { shost_printk(KERN_INFO, shost, "libfc: Host reset failed, " "port (%6x) is not ready.\n", - fc_host_port_id(lp->host)); + fc_host_port_id(lport->host)); return FAILED; } } EXPORT_SYMBOL(fc_eh_host_reset); /** - * fc_slave_alloc() - configure queue depth - * @sdev: scsi device + * fc_slave_alloc() - Configure the queue depth of a Scsi_Host + * @sdev: The SCSI device that identifies the SCSI host * * Configures queue depth based on host's cmd_per_len. If not set * then we use the libfc default. @@ -1988,6 +2060,12 @@ int fc_slave_alloc(struct scsi_device *sdev) } EXPORT_SYMBOL(fc_slave_alloc); +/** + * fc_change_queue_depth() - Change a device's queue depth + * @sdev: The SCSI device whose queue depth is to change + * @qdepth: The new queue depth + * @reason: The resason for the change + */ int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) { switch (reason) { @@ -2007,6 +2085,11 @@ int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) } EXPORT_SYMBOL(fc_change_queue_depth); +/** + * fc_change_queue_type() - Change a device's queue type + * @sdev: The SCSI device whose queue depth is to change + * @tag_type: Identifier for queue type + */ int fc_change_queue_type(struct scsi_device *sdev, int tag_type) { if (sdev->tagged_supported) { @@ -2022,17 +2105,21 @@ int fc_change_queue_type(struct scsi_device *sdev, int tag_type) } EXPORT_SYMBOL(fc_change_queue_type); -void fc_fcp_destroy(struct fc_lport *lp) +/** + * fc_fcp_destory() - Tear down the FCP layer for a given local port + * @lport: The local port that no longer needs the FCP layer + */ +void fc_fcp_destroy(struct fc_lport *lport) { - struct fc_fcp_internal *si = fc_get_scsi_internal(lp); + struct fc_fcp_internal *si = fc_get_scsi_internal(lport); if (!list_empty(&si->scsi_pkt_queue)) printk(KERN_ERR "libfc: Leaked SCSI packets when destroying " - "port (%6x)\n", fc_host_port_id(lp->host)); + "port (%6x)\n", fc_host_port_id(lport->host)); mempool_destroy(si->scsi_pkt_pool); kfree(si); - lp->scsi_priv = NULL; + lport->scsi_priv = NULL; } EXPORT_SYMBOL(fc_fcp_destroy); @@ -2058,24 +2145,28 @@ void fc_destroy_fcp() kmem_cache_destroy(scsi_pkt_cachep); } -int fc_fcp_init(struct fc_lport *lp) +/** + * fc_fcp_init() - Initialize the FCP layer for a local port + * @lport: The local port to initialize the exchange layer for + */ +int fc_fcp_init(struct fc_lport *lport) { int rc; struct fc_fcp_internal *si; - if (!lp->tt.fcp_cmd_send) - lp->tt.fcp_cmd_send = fc_fcp_cmd_send; + if (!lport->tt.fcp_cmd_send) + lport->tt.fcp_cmd_send = fc_fcp_cmd_send; - if (!lp->tt.fcp_cleanup) - lp->tt.fcp_cleanup = fc_fcp_cleanup; + if (!lport->tt.fcp_cleanup) + lport->tt.fcp_cleanup = fc_fcp_cleanup; - if (!lp->tt.fcp_abort_io) - lp->tt.fcp_abort_io = fc_fcp_abort_io; + if (!lport->tt.fcp_abort_io) + lport->tt.fcp_abort_io = fc_fcp_abort_io; si = kzalloc(sizeof(struct fc_fcp_internal), GFP_KERNEL); if (!si) return -ENOMEM; - lp->scsi_priv = si; + lport->scsi_priv = si; INIT_LIST_HEAD(&si->scsi_pkt_queue); si->scsi_pkt_pool = mempool_create_slab_pool(2, scsi_pkt_cachep); diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c index 295eafb0316..39f4b6ab04b 100644 --- a/drivers/scsi/libfc/fc_libfc.c +++ b/drivers/scsi/libfc/fc_libfc.c @@ -75,7 +75,7 @@ module_exit(libfc_exit); /** * fc_copy_buffer_to_sglist() - This routine copies the data of a buffer - * into a scatter-gather list (SG list). + * into a scatter-gather list (SG list). * * @buf: pointer to the data buffer. * @len: the byte-length of the data buffer. @@ -84,7 +84,7 @@ module_exit(libfc_exit); * @offset: pointer to the current offset in the SG list. * @km_type: dedicated page table slot type for kmap_atomic. * @crc: pointer to the 32-bit crc value. - * If crc is NULL, CRC is not calculated. + * If crc is NULL, CRC is not calculated. */ u32 fc_copy_buffer_to_sglist(void *buf, size_t len, struct scatterlist *sg, diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h index e4b5e9280cb..741fd5c72e1 100644 --- a/drivers/scsi/libfc/fc_libfc.h +++ b/drivers/scsi/libfc/fc_libfc.h @@ -22,22 +22,22 @@ #define FC_LIBFC_LOGGING 0x01 /* General logging, not categorized */ #define FC_LPORT_LOGGING 0x02 /* lport layer logging */ -#define FC_DISC_LOGGING 0x04 /* discovery layer logging */ +#define FC_DISC_LOGGING 0x04 /* discovery layer logging */ #define FC_RPORT_LOGGING 0x08 /* rport layer logging */ -#define FC_FCP_LOGGING 0x10 /* I/O path logging */ -#define FC_EM_LOGGING 0x20 /* Exchange Manager logging */ -#define FC_EXCH_LOGGING 0x40 /* Exchange/Sequence logging */ -#define FC_SCSI_LOGGING 0x80 /* SCSI logging (mostly error handling) */ +#define FC_FCP_LOGGING 0x10 /* I/O path logging */ +#define FC_EM_LOGGING 0x20 /* Exchange Manager logging */ +#define FC_EXCH_LOGGING 0x40 /* Exchange/Sequence logging */ +#define FC_SCSI_LOGGING 0x80 /* SCSI logging (mostly error handling) */ extern unsigned int fc_debug_logging; -#define FC_CHECK_LOGGING(LEVEL, CMD) \ -do { \ - if (unlikely(fc_debug_logging & LEVEL)) \ - do { \ - CMD; \ - } while (0); \ -} while (0) +#define FC_CHECK_LOGGING(LEVEL, CMD) \ + do { \ + if (unlikely(fc_debug_logging & LEVEL)) \ + do { \ + CMD; \ + } while (0); \ + } while (0) #define FC_LIBFC_DBG(fmt, args...) \ FC_CHECK_LOGGING(FC_LIBFC_LOGGING, \ @@ -49,10 +49,10 @@ do { \ (lport)->host->host_no, \ fc_host_port_id((lport)->host), ##args)) -#define FC_DISC_DBG(disc, fmt, args...) \ - FC_CHECK_LOGGING(FC_DISC_LOGGING, \ - printk(KERN_INFO "host%u: disc: " fmt, \ - (disc)->lport->host->host_no, \ +#define FC_DISC_DBG(disc, fmt, args...) \ + FC_CHECK_LOGGING(FC_DISC_LOGGING, \ + printk(KERN_INFO "host%u: disc: " fmt, \ + (disc)->lport->host->host_no, \ ##args)) #define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \ @@ -77,7 +77,7 @@ do { \ exch->xid, ##args)) #define FC_SCSI_DBG(lport, fmt, args...) \ - FC_CHECK_LOGGING(FC_SCSI_LOGGING, \ + FC_CHECK_LOGGING(FC_SCSI_LOGGING, \ printk(KERN_INFO "host%u: scsi: " fmt, \ (lport)->host->host_no, ##args)) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2162e6b0f43..90930c43545 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -133,7 +133,7 @@ static const char *fc_lport_state_names[] = { * @job: The passthrough job * @lport: The local port to pass through a command * @rsp_code: The expected response code - * @sg: job->reply_payload.sg_list + * @sg: job->reply_payload.sg_list * @nents: job->reply_payload.sg_cnt * @offset: The offset into the response data */ @@ -146,6 +146,11 @@ struct fc_bsg_info { size_t offset; }; +/** + * fc_frame_drop() - Dummy frame handler + * @lport: The local port the frame was received on + * @fp: The received frame + */ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp) { fc_frame_free(fp); @@ -172,7 +177,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, switch (event) { case RPORT_EV_READY: if (lport->state == LPORT_ST_DNS) { - lport->dns_rp = rdata; + lport->dns_rdata = rdata; fc_lport_enter_ns(lport, LPORT_ST_RNN_ID); } else { FC_LPORT_DBG(lport, "Received an READY event " @@ -187,7 +192,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, case RPORT_EV_LOGO: case RPORT_EV_FAILED: case RPORT_EV_STOP: - lport->dns_rp = NULL; + lport->dns_rdata = NULL; break; case RPORT_EV_NONE: break; @@ -211,8 +216,8 @@ static const char *fc_lport_state(struct fc_lport *lport) /** * fc_lport_ptp_setup() - Create an rport for point-to-point mode - * @lport: The lport to attach the ptp rport to - * @fid: The FID of the ptp rport + * @lport: The lport to attach the ptp rport to + * @remote_fid: The FID of the ptp rport * @remote_wwpn: The WWPN of the ptp rport * @remote_wwnn: The WWNN of the ptp rport */ @@ -221,18 +226,22 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, u64 remote_wwnn) { mutex_lock(&lport->disc.disc_mutex); - if (lport->ptp_rp) - lport->tt.rport_logoff(lport->ptp_rp); - lport->ptp_rp = lport->tt.rport_create(lport, remote_fid); - lport->ptp_rp->ids.port_name = remote_wwpn; - lport->ptp_rp->ids.node_name = remote_wwnn; + if (lport->ptp_rdata) + lport->tt.rport_logoff(lport->ptp_rdata); + lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); + lport->ptp_rdata->ids.port_name = remote_wwpn; + lport->ptp_rdata->ids.node_name = remote_wwnn; mutex_unlock(&lport->disc.disc_mutex); - lport->tt.rport_login(lport->ptp_rp); + lport->tt.rport_login(lport->ptp_rdata); fc_lport_enter_ready(lport); } +/** + * fc_get_host_port_type() - Return the port type of the given Scsi_Host + * @shost: The SCSI host whose port type is to be determined + */ void fc_get_host_port_type(struct Scsi_Host *shost) { /* TODO - currently just NPORT */ @@ -240,25 +249,33 @@ void fc_get_host_port_type(struct Scsi_Host *shost) } EXPORT_SYMBOL(fc_get_host_port_type); +/** + * fc_get_host_port_state() - Return the port state of the given Scsi_Host + * @shost: The SCSI host whose port state is to be determined + */ void fc_get_host_port_state(struct Scsi_Host *shost) { - struct fc_lport *lp = shost_priv(shost); + struct fc_lport *lport = shost_priv(shost); - mutex_lock(&lp->lp_mutex); - if (!lp->link_up) + mutex_lock(&lport->lp_mutex); + if (!lport->link_up) fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; else - switch (lp->state) { + switch (lport->state) { case LPORT_ST_READY: fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; break; default: fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; } - mutex_unlock(&lp->lp_mutex); + mutex_unlock(&lport->lp_mutex); } EXPORT_SYMBOL(fc_get_host_port_state); +/** + * fc_get_host_speed() - Return the speed of the given Scsi_Host + * @shost: The SCSI host whose port speed is to be determined + */ void fc_get_host_speed(struct Scsi_Host *shost) { struct fc_lport *lport = shost_priv(shost); @@ -267,24 +284,28 @@ void fc_get_host_speed(struct Scsi_Host *shost) } EXPORT_SYMBOL(fc_get_host_speed); +/** + * fc_get_host_stats() - Return the Scsi_Host's statistics + * @shost: The SCSI host whose statistics are to be returned + */ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost) { struct fc_host_statistics *fcoe_stats; - struct fc_lport *lp = shost_priv(shost); + struct fc_lport *lport = shost_priv(shost); struct timespec v0, v1; unsigned int cpu; - fcoe_stats = &lp->host_stats; + fcoe_stats = &lport->host_stats; memset(fcoe_stats, 0, sizeof(struct fc_host_statistics)); jiffies_to_timespec(jiffies, &v0); - jiffies_to_timespec(lp->boot_time, &v1); + jiffies_to_timespec(lport->boot_time, &v1); fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec); for_each_possible_cpu(cpu) { struct fcoe_dev_stats *stats; - stats = per_cpu_ptr(lp->dev_stats, cpu); + stats = per_cpu_ptr(lport->dev_stats, cpu); fcoe_stats->tx_frames += stats->TxFrames; fcoe_stats->tx_words += stats->TxWords; @@ -309,12 +330,15 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost) } EXPORT_SYMBOL(fc_get_host_stats); -/* - * Fill in FLOGI command for request. +/** + * fc_lport_flogi_fill() - Fill in FLOGI command for request + * @lport: The local port the FLOGI is for + * @flogi: The FLOGI command + * @op: The opcode */ -static void -fc_lport_flogi_fill(struct fc_lport *lport, struct fc_els_flogi *flogi, - unsigned int op) +static void fc_lport_flogi_fill(struct fc_lport *lport, + struct fc_els_flogi *flogi, + unsigned int op) { struct fc_els_csp *sp; struct fc_els_cssp *cp; @@ -342,8 +366,10 @@ fc_lport_flogi_fill(struct fc_lport *lport, struct fc_els_flogi *flogi, } } -/* - * Add a supported FC-4 type. +/** + * fc_lport_add_fc4_type() - Add a supported FC-4 type to a local port + * @lport: The local port to add a new FC-4 type to + * @type: The new FC-4 type */ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) { @@ -355,9 +381,9 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) /** * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. + * @sp: The sequence in the RLIR exchange + * @fp: The RLIR request frame * @lport: Fibre Channel local port recieving the RLIR - * @sp: current sequence in the RLIR exchange - * @fp: RLIR request frame * * Locking Note: The lport lock is expected to be held before calling * this function. @@ -374,9 +400,9 @@ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, /** * fc_lport_recv_echo_req() - Handle received ECHO request - * @lport: Fibre Channel local port recieving the ECHO - * @sp: current sequence in the ECHO exchange - * @fp: ECHO request frame + * @sp: The sequence in the ECHO exchange + * @fp: ECHO request frame + * @lport: The local port recieving the ECHO * * Locking Note: The lport lock is expected to be held before calling * this function. @@ -483,9 +509,9 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, /** * fc_lport_recv_logo_req() - Handle received fabric LOGO request - * @lport: Fibre Channel local port recieving the LOGO - * @sp: current sequence in the LOGO exchange - * @fp: LOGO request frame + * @sp: The sequence in the LOGO exchange + * @fp: The LOGO request frame + * @lport: The local port recieving the LOGO * * Locking Note: The lport lock is exected to be held before calling * this function. @@ -500,7 +526,7 @@ static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp, /** * fc_fabric_login() - Start the lport state machine - * @lport: The lport that should log into the fabric + * @lport: The local port that should log into the fabric * * Locking Note: This function should not be called * with the lport lock held. @@ -538,7 +564,7 @@ void __fc_linkup(struct fc_lport *lport) /** * fc_linkup() - Handler for transport linkup events - * @lport: The lport whose link is up + * @lport: The local port whose link is up */ void fc_linkup(struct fc_lport *lport) { @@ -568,7 +594,7 @@ void __fc_linkdown(struct fc_lport *lport) /** * fc_linkdown() - Handler for transport linkdown events - * @lport: The lport whose link is down + * @lport: The local port whose link is down */ void fc_linkdown(struct fc_lport *lport) { @@ -583,7 +609,7 @@ EXPORT_SYMBOL(fc_linkdown); /** * fc_fabric_logoff() - Logout of the fabric - * @lport: fc_lport pointer to logoff the fabric + * @lport: The local port to logoff the fabric * * Return value: * 0 for success, -1 for failure @@ -592,8 +618,8 @@ int fc_fabric_logoff(struct fc_lport *lport) { lport->tt.disc_stop_final(lport); mutex_lock(&lport->lp_mutex); - if (lport->dns_rp) - lport->tt.rport_logoff(lport->dns_rp); + if (lport->dns_rdata) + lport->tt.rport_logoff(lport->dns_rdata); mutex_unlock(&lport->lp_mutex); lport->tt.rport_flush_queue(); mutex_lock(&lport->lp_mutex); @@ -605,11 +631,9 @@ int fc_fabric_logoff(struct fc_lport *lport) EXPORT_SYMBOL(fc_fabric_logoff); /** - * fc_lport_destroy() - unregister a fc_lport - * @lport: fc_lport pointer to unregister + * fc_lport_destroy() - Unregister a fc_lport + * @lport: The local port to unregister * - * Return value: - * None * Note: * exit routine for fc_lport instance * clean-up all the allocated memory @@ -632,13 +656,9 @@ int fc_lport_destroy(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_destroy); /** - * fc_set_mfs() - sets up the mfs for the corresponding fc_lport - * @lport: fc_lport pointer to unregister - * @mfs: the new mfs for fc_lport - * - * Set mfs for the given fc_lport to the new mfs. - * - * Return: 0 for success + * fc_set_mfs() - Set the maximum frame size for a local port + * @lport: The local port to set the MFS for + * @mfs: The new MFS */ int fc_set_mfs(struct fc_lport *lport, u32 mfs) { @@ -669,7 +689,7 @@ EXPORT_SYMBOL(fc_set_mfs); /** * fc_lport_disc_callback() - Callback for discovery events - * @lport: FC local port + * @lport: The local port receiving the event * @event: The discovery event */ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) @@ -693,7 +713,7 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) /** * fc_rport_enter_ready() - Enter the ready state and start discovery - * @lport: Fibre Channel local port that is ready + * @lport: The local port that is ready * * Locking Note: The lport lock is expected to be held before calling * this routine. @@ -708,15 +728,15 @@ static void fc_lport_enter_ready(struct fc_lport *lport) fc_vport_set_state(lport->vport, FC_VPORT_ACTIVE); fc_vports_linkchange(lport); - if (!lport->ptp_rp) + if (!lport->ptp_rdata) lport->tt.disc_start(fc_lport_disc_callback, lport); } /** * fc_lport_recv_flogi_req() - Receive a FLOGI request * @sp_in: The sequence the FLOGI is on - * @rx_fp: The frame the FLOGI is in - * @lport: The lport that recieved the request + * @rx_fp: The FLOGI frame + * @lport: The local port that recieved the request * * A received FLOGI request indicates a point-to-point connection. * Accept it with the common service parameters indicating our N port. @@ -802,9 +822,9 @@ out: /** * fc_lport_recv_req() - The generic lport request handler - * @lport: The lport that received the request - * @sp: The sequence the request is on - * @fp: The frame the request is in + * @lport: The local port that received the request + * @sp: The sequence the request is on + * @fp: The request frame * * This function will see if the lport handles the request or * if an rport should handle the request. @@ -872,8 +892,8 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, } /** - * fc_lport_reset() - Reset an lport - * @lport: The lport which should be reset + * fc_lport_reset() - Reset a local port + * @lport: The local port which should be reset * * Locking Note: This functions should not be called with the * lport lock held. @@ -889,18 +909,18 @@ int fc_lport_reset(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_reset); /** - * fc_lport_reset_locked() - Reset the local port - * @lport: Fibre Channel local port to be reset + * fc_lport_reset_locked() - Reset the local port w/ the lport lock held + * @lport: The local port to be reset * * Locking Note: The lport lock is expected to be held before calling * this routine. */ static void fc_lport_reset_locked(struct fc_lport *lport) { - if (lport->dns_rp) - lport->tt.rport_logoff(lport->dns_rp); + if (lport->dns_rdata) + lport->tt.rport_logoff(lport->dns_rdata); - lport->ptp_rp = NULL; + lport->ptp_rdata = NULL; lport->tt.disc_stop(lport); @@ -911,7 +931,7 @@ static void fc_lport_reset_locked(struct fc_lport *lport) /** * fc_lport_enter_reset() - Reset the local port - * @lport: Fibre Channel local port to be reset + * @lport: The local port to be reset * * Locking Note: The lport lock is expected to be held before calling * this routine. @@ -935,8 +955,8 @@ static void fc_lport_enter_reset(struct fc_lport *lport) } /** - * fc_lport_enter_disabled() - disable the local port - * @lport: Fibre Channel local port to be reset + * fc_lport_enter_disabled() - Disable the local port + * @lport: The local port to be reset * * Locking Note: The lport lock is expected to be held before calling * this routine. @@ -953,8 +973,8 @@ static void fc_lport_enter_disabled(struct fc_lport *lport) /** * fc_lport_error() - Handler for any errors - * @lport: The fc_lport object - * @fp: The frame pointer + * @lport: The local port that the error was on + * @fp: The error code encoded in a frame pointer * * If the error was caused by a resource allocation failure * then wait for half a second and retry, otherwise retry @@ -1002,13 +1022,13 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) /** * fc_lport_ns_resp() - Handle response to a name server - * registration exchange - * @sp: current sequence in exchange - * @fp: response frame + * registration exchange + * @sp: current sequence in exchange + * @fp: response frame * @lp_arg: Fibre Channel host port instance * * Locking Note: This function will be called without the lport lock - * held, but it will lock, call an _enter_* function or fc_lport_error + * held, but it will lock, call an _enter_* function or fc_lport_error() * and then unlock the lport. */ static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp, @@ -1027,7 +1047,7 @@ static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp, if (lport->state < LPORT_ST_RNN_ID || lport->state > LPORT_ST_RFT_ID) { FC_LPORT_DBG(lport, "Received a name server response, " - "but in state %s\n", fc_lport_state(lport)); + "but in state %s\n", fc_lport_state(lport)); if (IS_ERR(fp)) goto err; goto out; @@ -1072,8 +1092,8 @@ err: /** * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request - * @sp: current sequence in SCR exchange - * @fp: response frame + * @sp: current sequence in SCR exchange + * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the registration request * * Locking Note: This function will be called without the lport lock @@ -1119,8 +1139,8 @@ err: } /** - * fc_lport_enter_scr() - Send a State Change Register (SCR) request - * @lport: Fibre Channel local port to register for state changes + * fc_lport_enter_scr() - Send a SCR (State Change Register) request + * @lport: The local port to register for state changes * * Locking Note: The lport lock is expected to be held before calling * this routine. @@ -1212,8 +1232,8 @@ static struct fc_rport_operations fc_lport_rport_ops = { }; /** - * fc_rport_enter_dns() - Create a rport to the name server - * @lport: Fibre Channel local port requesting a rport for the name server + * fc_rport_enter_dns() - Create a fc_rport for the name server + * @lport: The local port requesting a remote port for the name server * * Locking Note: The lport lock is expected to be held before calling * this routine. @@ -1242,8 +1262,8 @@ err: } /** - * fc_lport_timeout() - Handler for the retry_work timer. - * @work: The work struct of the fc_lport + * fc_lport_timeout() - Handler for the retry_work timer + * @work: The work struct of the local port */ static void fc_lport_timeout(struct work_struct *work) { @@ -1287,16 +1307,16 @@ static void fc_lport_timeout(struct work_struct *work) /** * fc_lport_logo_resp() - Handle response to LOGO request - * @sp: current sequence in LOGO exchange - * @fp: response frame - * @lp_arg: Fibre Channel lport port instance that sent the LOGO request + * @sp: The sequence that the LOGO was on + * @fp: The LOGO frame + * @lp_arg: The lport port that received the LOGO request * * Locking Note: This function will be called without the lport lock - * held, but it will lock, call an _enter_* function or fc_lport_error + * held, but it will lock, call an _enter_* function or fc_lport_error() * and then unlock the lport. */ void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, - void *lp_arg) + void *lp_arg) { struct fc_lport *lport = lp_arg; u8 op; @@ -1336,7 +1356,7 @@ EXPORT_SYMBOL(fc_lport_logo_resp); /** * fc_rport_enter_logo() - Logout of the fabric - * @lport: Fibre Channel local port to be logged out + * @lport: The local port to be logged out * * Locking Note: The lport lock is expected to be held before calling * this routine. @@ -1365,16 +1385,16 @@ static void fc_lport_enter_logo(struct fc_lport *lport) /** * fc_lport_flogi_resp() - Handle response to FLOGI request - * @sp: current sequence in FLOGI exchange - * @fp: response frame - * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request + * @sp: The sequence that the FLOGI was on + * @fp: The FLOGI response frame + * @lp_arg: The lport port that received the FLOGI response * * Locking Note: This function will be called without the lport lock - * held, but it will lock, call an _enter_* function or fc_lport_error + * held, but it will lock, call an _enter_* function or fc_lport_error() * and then unlock the lport. */ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, - void *lp_arg) + void *lp_arg) { struct fc_lport *lport = lp_arg; struct fc_frame_header *fh; @@ -1484,7 +1504,10 @@ void fc_lport_enter_flogi(struct fc_lport *lport) fc_lport_error(lport, NULL); } -/* Configure a fc_lport */ +/** + * fc_lport_config() - Configure a fc_lport + * @lport: The local port to be configured + */ int fc_lport_config(struct fc_lport *lport) { INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout); @@ -1499,6 +1522,10 @@ int fc_lport_config(struct fc_lport *lport) } EXPORT_SYMBOL(fc_lport_config); +/** + * fc_lport_init() - Initialize the lport layer for a local port + * @lport: The local port to initialize the exchange layer for + */ int fc_lport_init(struct fc_lport *lport) { if (!lport->tt.lport_recv) @@ -1533,10 +1560,10 @@ int fc_lport_init(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_init); /** - * fc_lport_bsg_resp() - The common response handler for fc pass-thru requests - * @sp: current sequence in the fc pass-thru request exchange - * @fp: received response frame - * @info_arg: pointer to struct fc_bsg_info + * fc_lport_bsg_resp() - The common response handler for FC Passthrough requests + * @sp: The sequence for the FC Passthrough response + * @fp: The response frame + * @info_arg: The BSG info that the response is for */ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, void *info_arg) @@ -1596,10 +1623,10 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_lport_els_request() - Send ELS pass-thru request - * @job: The bsg fc pass-thru job structure + * fc_lport_els_request() - Send ELS passthrough request + * @job: The BSG Passthrough job * @lport: The local port sending the request - * @did: The destination port id. + * @did: The destination port id * * Locking Note: The lport lock is expected to be held before calling * this routine. @@ -1656,11 +1683,11 @@ static int fc_lport_els_request(struct fc_bsg_job *job, } /** - * fc_lport_ct_request() - Send CT pass-thru request - * @job: The bsg fc pass-thru job structure + * fc_lport_ct_request() - Send CT Passthrough request + * @job: The BSG Passthrough job * @lport: The local port sending the request * @did: The destination FC-ID - * @tov: The time to wait for a response + * @tov: The timeout period to wait for the response * * Locking Note: The lport lock is expected to be held before calling * this routine. @@ -1717,8 +1744,8 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, /** * fc_lport_bsg_request() - The common entry point for sending - * fc pass-thru requests - * @job: The fc pass-thru job structure + * FC Passthrough requests + * @job: The BSG passthrough job */ int fc_lport_bsg_request(struct fc_bsg_job *job) { @@ -1759,7 +1786,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) case FC_BSG_HST_CT: did = ntoh24(job->request->rqst_data.h_ct.port_id); if (did == FC_FID_DIR_SERV) - rdata = lport->dns_rp; + rdata = lport->dns_rdata; else rdata = lport->tt.rport_lookup(lport, did); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 622285c81fe..6578968a753 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -92,9 +92,9 @@ static const char *fc_rport_state_names[] = { }; /** - * fc_rport_lookup() - lookup a remote port by port_id - * @lport: Fibre Channel host port instance - * @port_id: remote port port_id to match + * fc_rport_lookup() - Lookup a remote port by port_id + * @lport: The local port to lookup the remote port on + * @port_id: The remote port ID to look up */ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, u32 port_id) @@ -109,8 +109,10 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, /** * fc_rport_create() - Create a new remote port - * @lport: The local port that the new remote port is for - * @port_id: The port ID for the new remote port + * @lport: The local port this remote port will be associated with + * @ids: The identifiers for the new remote port + * + * The remote port will start in the INIT state. * * Locking note: must be called with the disc_mutex held. */ @@ -149,8 +151,8 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, } /** - * fc_rport_destroy() - free a remote port after last reference is released. - * @kref: pointer to kref inside struct fc_rport_priv + * fc_rport_destroy() - Free a remote port after last reference is released + * @kref: The remote port's kref */ static void fc_rport_destroy(struct kref *kref) { @@ -161,8 +163,8 @@ static void fc_rport_destroy(struct kref *kref) } /** - * fc_rport_state() - return a string for the state the rport is in - * @rdata: remote port private data + * fc_rport_state() - Return a string identifying the remote port's state + * @rdata: The remote port */ static const char *fc_rport_state(struct fc_rport_priv *rdata) { @@ -175,9 +177,9 @@ static const char *fc_rport_state(struct fc_rport_priv *rdata) } /** - * fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds. - * @rport: Pointer to Fibre Channel remote port structure - * @timeout: timeout in seconds + * fc_set_rport_loss_tmo() - Set the remote port loss timeout + * @rport: The remote port that gets a new timeout value + * @timeout: The new timeout value (in seconds) */ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) { @@ -189,9 +191,11 @@ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) EXPORT_SYMBOL(fc_set_rport_loss_tmo); /** - * fc_plogi_get_maxframe() - Get max payload from the common service parameters - * @flp: FLOGI payload structure - * @maxval: upper limit, may be less than what is in the service parameters + * fc_plogi_get_maxframe() - Get the maximum payload from the common service + * parameters in a FLOGI frame + * @flp: The FLOGI payload + * @maxval: The maximum frame size upper limit; this may be less than what + * is in the service parameters */ static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval) @@ -212,9 +216,9 @@ static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, } /** - * fc_rport_state_enter() - Change the rport's state - * @rdata: The rport whose state should change - * @new: The new state of the rport + * fc_rport_state_enter() - Change the state of a remote port + * @rdata: The remote port whose state should change + * @new: The new state * * Locking Note: Called with the rport lock held */ @@ -226,12 +230,16 @@ static void fc_rport_state_enter(struct fc_rport_priv *rdata, rdata->rp_state = new; } +/** + * fc_rport_work() - Handler for remote port events in the rport_event_queue + * @work: Handle to the remote port being dequeued + */ static void fc_rport_work(struct work_struct *work) { u32 port_id; struct fc_rport_priv *rdata = container_of(work, struct fc_rport_priv, event_work); - struct fc_rport_libfc_priv *rp; + struct fc_rport_libfc_priv *rpriv; enum fc_rport_event event; struct fc_lport *lport = rdata->local_port; struct fc_rport_operations *rport_ops; @@ -268,12 +276,12 @@ static void fc_rport_work(struct work_struct *work) rport->maxframe_size = rdata->maxframe_size; rport->supported_classes = rdata->supported_classes; - rp = rport->dd_data; - rp->local_port = lport; - rp->rp_state = rdata->rp_state; - rp->flags = rdata->flags; - rp->e_d_tov = rdata->e_d_tov; - rp->r_a_tov = rdata->r_a_tov; + rpriv = rport->dd_data; + rpriv->local_port = lport; + rpriv->rp_state = rdata->rp_state; + rpriv->flags = rdata->flags; + rpriv->e_d_tov = rdata->e_d_tov; + rpriv->r_a_tov = rdata->r_a_tov; mutex_unlock(&rdata->rp_mutex); if (rport_ops && rport_ops->event_callback) { @@ -319,8 +327,8 @@ static void fc_rport_work(struct work_struct *work) lport->tt.exch_mgr_reset(lport, port_id, 0); if (rport) { - rp = rport->dd_data; - rp->rp_state = RPORT_ST_DELETE; + rpriv = rport->dd_data; + rpriv->rp_state = RPORT_ST_DELETE; mutex_lock(&rdata->rp_mutex); rdata->rport = NULL; mutex_unlock(&rdata->rp_mutex); @@ -343,7 +351,7 @@ static void fc_rport_work(struct work_struct *work) /** * fc_rport_login() - Start the remote port login state machine - * @rdata: private remote port + * @rdata: The remote port to be logged in to * * Locking Note: Called without the rport lock held. This * function will hold the rport lock, call an _enter_* @@ -379,9 +387,9 @@ int fc_rport_login(struct fc_rport_priv *rdata) } /** - * fc_rport_enter_delete() - schedule a remote port to be deleted. - * @rdata: private remote port - * @event: event to report as the reason for deletion + * fc_rport_enter_delete() - Schedule a remote port to be deleted + * @rdata: The remote port to be deleted + * @event: The event to report as the reason for deletion * * Locking Note: Called with the rport lock held. * @@ -408,8 +416,8 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, } /** - * fc_rport_logoff() - Logoff and remove an rport - * @rdata: private remote port + * fc_rport_logoff() - Logoff and remove a remote port + * @rdata: The remote port to be logged off of * * Locking Note: Called without the rport lock held. This * function will hold the rport lock, call an _enter_* @@ -442,8 +450,8 @@ out: } /** - * fc_rport_enter_ready() - The rport is ready - * @rdata: private remote port + * fc_rport_enter_ready() - Transition to the RPORT_ST_READY state + * @rdata: The remote port that is ready * * Locking Note: The rport lock is expected to be held before calling * this routine. @@ -460,8 +468,8 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) } /** - * fc_rport_timeout() - Handler for the retry_work timer. - * @work: The work struct of the fc_rport_priv + * fc_rport_timeout() - Handler for the retry_work timer + * @work: Handle to the remote port that has timed out * * Locking Note: Called without the rport lock held. This * function will hold the rport lock, call an _enter_* @@ -502,8 +510,8 @@ static void fc_rport_timeout(struct work_struct *work) /** * fc_rport_error() - Error handler, called once retries have been exhausted - * @rdata: private remote port - * @fp: The frame pointer + * @rdata: The remote port the error is happened on + * @fp: The error code encapsulated in a frame pointer * * Locking Note: The rport lock is expected to be held before * calling this routine @@ -535,9 +543,9 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) } /** - * fc_rport_error_retry() - Error handler when retries are desired - * @rdata: private remote port data - * @fp: The frame pointer + * fc_rport_error_retry() - Handler for remote port state retries + * @rdata: The remote port whose state is to be retried + * @fp: The error code encapsulated in a frame pointer * * If the error was an exchange timeout retry immediately, * otherwise wait for E_D_TOV. @@ -569,10 +577,10 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, } /** - * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response - * @sp: current sequence in the PLOGI exchange - * @fp: response frame - * @rdata_arg: private remote port data + * fc_rport_plogi_recv_resp() - Handler for ELS PLOGI responses + * @sp: The sequence the PLOGI is on + * @fp: The PLOGI response frame + * @rdata_arg: The remote port that sent the PLOGI response * * Locking Note: This function will be called without the rport lock * held, but it will lock, call an _enter_* function or fc_rport_error @@ -635,8 +643,8 @@ err: } /** - * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer - * @rdata: private remote port data + * fc_rport_enter_plogi() - Send Port Login (PLOGI) request + * @rdata: The remote port to send a PLOGI to * * Locking Note: The rport lock is expected to be held before calling * this routine. @@ -668,9 +676,9 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) /** * fc_rport_prli_resp() - Process Login (PRLI) response handler - * @sp: current sequence in the PRLI exchange - * @fp: response frame - * @rdata_arg: private remote port data + * @sp: The sequence the PRLI response was on + * @fp: The PRLI response frame + * @rdata_arg: The remote port that sent the PRLI response * * Locking Note: This function will be called without the rport lock * held, but it will lock, call an _enter_* function or fc_rport_error @@ -739,10 +747,10 @@ err: } /** - * fc_rport_logo_resp() - Logout (LOGO) response handler - * @sp: current sequence in the LOGO exchange - * @fp: response frame - * @rdata_arg: private remote port data + * fc_rport_logo_resp() - Handler for logout (LOGO) responses + * @sp: The sequence the LOGO was on + * @fp: The LOGO response frame + * @rdata_arg: The remote port that sent the LOGO response * * Locking Note: This function will be called without the rport lock * held, but it will lock, call an _enter_* function or fc_rport_error @@ -785,8 +793,8 @@ err: } /** - * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer - * @rdata: private remote port data + * fc_rport_enter_prli() - Send Process Login (PRLI) request + * @rdata: The remote port to send the PRLI request to * * Locking Note: The rport lock is expected to be held before calling * this routine. @@ -828,10 +836,10 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) } /** - * fc_rport_els_rtv_resp() - Request Timeout Value response handler - * @sp: current sequence in the RTV exchange - * @fp: response frame - * @rdata_arg: private remote port data + * fc_rport_els_rtv_resp() - Handler for Request Timeout Value (RTV) responses + * @sp: The sequence the RTV was on + * @fp: The RTV response frame + * @rdata_arg: The remote port that sent the RTV response * * Many targets don't seem to support this. * @@ -894,8 +902,8 @@ err: } /** - * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer - * @rdata: private remote port data + * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request + * @rdata: The remote port to send the RTV request to * * Locking Note: The rport lock is expected to be held before calling * this routine. @@ -917,15 +925,15 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) } if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, - fc_rport_rtv_resp, rdata, lport->e_d_tov)) + fc_rport_rtv_resp, rdata, lport->e_d_tov)) fc_rport_error_retry(rdata, NULL); else kref_get(&rdata->kref); } /** - * fc_rport_enter_logo() - Send Logout (LOGO) request to peer - * @rdata: private remote port data + * fc_rport_enter_logo() - Send a logout (LOGO) request + * @rdata: The remote port to send the LOGO request to * * Locking Note: The rport lock is expected to be held before calling * this routine. @@ -954,17 +962,17 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) } /** - * fc_rport_els_adisc_resp() - Address Discovery response handler - * @sp: current sequence in the ADISC exchange - * @fp: response frame - * @rdata_arg: remote port private. + * fc_rport_els_adisc_resp() - Handler for Address Discovery (ADISC) responses + * @sp: The sequence the ADISC response was on + * @fp: The ADISC response frame + * @rdata_arg: The remote port that sent the ADISC response * * Locking Note: This function will be called without the rport lock * held, but it will lock, call an _enter_* function or fc_rport_error * and then unlock the rport. */ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, - void *rdata_arg) + void *rdata_arg) { struct fc_rport_priv *rdata = rdata_arg; struct fc_els_adisc *adisc; @@ -1012,8 +1020,8 @@ err: } /** - * fc_rport_enter_adisc() - Send Address Discover (ADISC) request to peer - * @rdata: remote port private data + * fc_rport_enter_adisc() - Send Address Discover (ADISC) request + * @rdata: The remote port to send the ADISC request to * * Locking Note: The rport lock is expected to be held before calling * this routine. @@ -1041,10 +1049,10 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) } /** - * fc_rport_recv_adisc_req() - Handle incoming Address Discovery (ADISC) Request - * @rdata: remote port private - * @sp: current sequence in the ADISC exchange - * @in_fp: ADISC request frame + * fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests + * @rdata: The remote port that sent the ADISC request + * @sp: The sequence the ADISC request was on + * @in_fp: The ADISC request frame * * Locking Note: Called with the lport and rport locks held. */ @@ -1085,10 +1093,10 @@ drop: } /** - * fc_rport_recv_els_req() - handle a validated ELS request. - * @lport: Fibre Channel local port - * @sp: current sequence in the PLOGI exchange - * @fp: response frame + * fc_rport_recv_els_req() - Handler for validated ELS requests + * @lport: The local port that received the ELS request + * @sp: The sequence that the ELS request was on + * @fp: The ELS request frame * * Handle incoming ELS requests that require port login. * The ELS opcode has already been validated by the caller. @@ -1160,10 +1168,10 @@ reject: } /** - * fc_rport_recv_req() - Handle a received ELS request from a rport - * @sp: current sequence in the PLOGI exchange - * @fp: response frame - * @lport: Fibre Channel local port + * fc_rport_recv_req() - Handler for requests + * @sp: The sequence the request was on + * @fp: The request frame + * @lport: The local port that received the request * * Locking Note: Called with the lport lock held. */ @@ -1203,10 +1211,10 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request - * @lport: local port - * @sp: current sequence in the PLOGI exchange - * @fp: PLOGI request frame + * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests + * @lport: The local port that received the PLOGI request + * @sp: The sequence that the PLOGI request was on + * @rx_fp: The PLOGI request frame * * Locking Note: The rport lock is held before calling this function. */ @@ -1328,10 +1336,10 @@ reject: } /** - * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request - * @rdata: private remote port data - * @sp: current sequence in the PRLI exchange - * @fp: PRLI request frame + * fc_rport_recv_prli_req() - Handler for process login (PRLI) requests + * @rdata: The remote port that sent the PRLI request + * @sp: The sequence that the PRLI was on + * @rx_fp: The PRLI request frame * * Locking Note: The rport lock is exected to be held before calling * this function. @@ -1485,10 +1493,10 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, } /** - * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request - * @rdata: private remote port data - * @sp: current sequence in the PRLO exchange - * @fp: PRLO request frame + * fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests + * @rdata: The remote port that sent the PRLO request + * @sp: The sequence that the PRLO was on + * @fp: The PRLO request frame * * Locking Note: The rport lock is exected to be held before calling * this function. @@ -1515,10 +1523,10 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, } /** - * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request - * @lport: local port. - * @sp: current sequence in the LOGO exchange - * @fp: LOGO request frame + * fc_rport_recv_logo_req() - Handler for logout (LOGO) requests + * @lport: The local port that received the LOGO request + * @sp: The sequence that the LOGO request was on + * @fp: The LOGO request frame * * Locking Note: The rport lock is exected to be held before calling * this function. @@ -1559,11 +1567,18 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, fc_frame_free(fp); } +/** + * fc_rport_flush_queue() - Flush the rport_event_queue + */ static void fc_rport_flush_queue(void) { flush_workqueue(rport_event_queue); } +/** + * fc_rport_init() - Initialize the remote port layer for a local port + * @lport: The local port to initialize the remote port layer for + */ int fc_rport_init(struct fc_lport *lport) { if (!lport->tt.rport_lookup) @@ -1591,7 +1606,10 @@ int fc_rport_init(struct fc_lport *lport) } EXPORT_SYMBOL(fc_rport_init); -int fc_setup_rport(void) +/** + * fc_setup_rport() - Initialize the rport_event_queue + */ +int fc_setup_rport() { rport_event_queue = create_singlethread_workqueue("fc_rport_eq"); if (!rport_event_queue) @@ -1599,15 +1617,22 @@ int fc_setup_rport(void) return 0; } -void fc_destroy_rport(void) +/** + * fc_destroy_rport() - Destroy the rport_event_queue + */ +void fc_destroy_rport() { destroy_workqueue(rport_event_queue); } +/** + * fc_rport_terminate_io() - Stop all outstanding I/O on a remote port + * @rport: The remote port whose I/O should be terminated + */ void fc_rport_terminate_io(struct fc_rport *rport) { - struct fc_rport_libfc_priv *rp = rport->dd_data; - struct fc_lport *lport = rp->local_port; + struct fc_rport_libfc_priv *rpriv = rport->dd_data; + struct fc_lport *lport = rpriv->local_port; lport->tt.exch_mgr_reset(lport, 0, rport->port_id); lport->tt.exch_mgr_reset(lport, rport->port_id, 0); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 54df9fe00c1..310d8a22b72 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -55,8 +55,17 @@ p[2] = ((v) & 0xFF); \ } while (0) -/* - * FC HBA status +/** + * enum fc_lport_state - Local port states + * @LPORT_ST_DISABLED: Disabled + * @LPORT_ST_FLOGI: Fabric login (FLOGI) sent + * @LPORT_ST_DNS: Waiting for name server remote port to become ready + * @LPORT_ST_RPN_ID: Register port name by ID (RPN_ID) sent + * @LPORT_ST_RFT_ID: Register Fibre Channel types by ID (RFT_ID) sent + * @LPORT_ST_SCR: State Change Register (SCR) sent + * @LPORT_ST_READY: Ready for use + * @LPORT_ST_LOGO: Local port logout (LOGO) sent + * @LPORT_ST_RESET: Local port reset */ enum fc_lport_state { LPORT_ST_DISABLED = 0, @@ -78,16 +87,28 @@ enum fc_disc_event { DISC_EV_FAILED }; +/** + * enum fc_rport_state - Remote port states + * @RPORT_ST_INIT: Initialized + * @RPORT_ST_PLOGI: Waiting for PLOGI completion + * @RPORT_ST_PRLI: Waiting for PRLI completion + * @RPORT_ST_RTV: Waiting for RTV completion + * @RPORT_ST_READY: Ready for use + * @RPORT_ST_LOGO: Remote port logout (LOGO) sent + * @RPORT_ST_ADISC: Discover Address sent + * @RPORT_ST_DELETE: Remote port being deleted + * @RPORT_ST_RESTART: Remote port being deleted and will restart +*/ enum fc_rport_state { - RPORT_ST_INIT, /* initialized */ - RPORT_ST_PLOGI, /* waiting for PLOGI completion */ - RPORT_ST_PRLI, /* waiting for PRLI completion */ - RPORT_ST_RTV, /* waiting for RTV completion */ - RPORT_ST_READY, /* ready for use */ - RPORT_ST_LOGO, /* port logout sent */ - RPORT_ST_ADISC, /* Discover Address sent */ - RPORT_ST_DELETE, /* port being deleted */ - RPORT_ST_RESTART, /* remote port being deleted and will restart */ + RPORT_ST_INIT, + RPORT_ST_PLOGI, + RPORT_ST_PRLI, + RPORT_ST_RTV, + RPORT_ST_READY, + RPORT_ST_LOGO, + RPORT_ST_ADISC, + RPORT_ST_DELETE, + RPORT_ST_RESTART, }; /** @@ -98,12 +119,20 @@ enum fc_rport_state { * @port_id: Port ID of the discovered port */ struct fc_disc_port { - struct fc_lport *lp; - struct list_head peers; - struct work_struct rport_work; - u32 port_id; + struct fc_lport *lp; + struct list_head peers; + struct work_struct rport_work; + u32 port_id; }; +/** + * enum fc_rport_event - Remote port events + * @RPORT_EV_NONE: No event + * @RPORT_EV_READY: Remote port is ready for use + * @RPORT_EV_FAILED: State machine failed, remote port is not ready + * @RPORT_EV_STOP: Remote port has been stopped + * @RPORT_EV_LOGO: Remote port logout (LOGO) sent + */ enum fc_rport_event { RPORT_EV_NONE = 0, RPORT_EV_READY, @@ -114,6 +143,10 @@ enum fc_rport_event { struct fc_rport_priv; +/** + * struct fc_rport_operations - Operations for a remote port + * @event_callback: Function to be called for remote port events + */ struct fc_rport_operations { void (*event_callback)(struct fc_lport *, struct fc_rport_priv *, enum fc_rport_event); @@ -121,11 +154,11 @@ struct fc_rport_operations { /** * struct fc_rport_libfc_priv - libfc internal information about a remote port - * @local_port: Fibre Channel host port instance - * @rp_state: indicates READY for I/O or DELETE when blocked. - * @flags: REC and RETRY supported flags - * @e_d_tov: error detect timeout value (in msec) - * @r_a_tov: resource allocation timeout value (in msec) + * @local_port: The associated local port + * @rp_state: Indicates READY for I/O or DELETE when blocked + * @flags: REC and RETRY supported flags + * @e_d_tov: Error detect timeout value (in msec) + * @r_a_tov: Resource allocation timeout value (in msec) */ struct fc_rport_libfc_priv { struct fc_lport *local_port; @@ -138,47 +171,64 @@ struct fc_rport_libfc_priv { }; /** - * struct fc_rport_priv - libfc rport and discovery info about a remote port - * @local_port: Fibre Channel host port instance - * @rport: transport remote port - * @kref: reference counter - * @rp_state: state tracks progress of PLOGI, PRLI, and RTV exchanges - * @ids: remote port identifiers and roles - * @flags: REC and RETRY supported flags - * @max_seq: maximum number of concurrent sequences - * @disc_id: discovery identifier - * @maxframe_size: maximum frame size - * @retries: retry count in current state - * @e_d_tov: error detect timeout value (in msec) - * @r_a_tov: resource allocation timeout value (in msec) - * @rp_mutex: mutex protects rport - * @retry_work: - * @event_callback: Callback for rport READY, FAILED or LOGO + * struct fc_rport_priv - libfc remote port and discovery info + * @local_port: The associated local port + * @rport: The FC transport remote port + * @kref: Reference counter + * @rp_state: Enumeration that tracks progress of PLOGI, PRLI, + * and RTV exchanges + * @ids: The remote port identifiers and roles + * @flags: REC and RETRY supported flags + * @max_seq: Maximum number of concurrent sequences + * @disc_id: The discovery identifier + * @maxframe_size: The maximum frame size + * @retries: The retry count for the current state + * @e_d_tov: Error detect timeout value (in msec) + * @r_a_tov: Resource allocation timeout value (in msec) + * @rp_mutex: The mutex that protects the remote port + * @retry_work: Handle for retries + * @event_callback: Callback when READY, FAILED or LOGO states complete */ struct fc_rport_priv { - struct fc_lport *local_port; - struct fc_rport *rport; - struct kref kref; - enum fc_rport_state rp_state; + struct fc_lport *local_port; + struct fc_rport *rport; + struct kref kref; + enum fc_rport_state rp_state; struct fc_rport_identifiers ids; - u16 flags; - u16 max_seq; - u16 disc_id; - u16 maxframe_size; - unsigned int retries; - unsigned int e_d_tov; - unsigned int r_a_tov; - struct mutex rp_mutex; - struct delayed_work retry_work; - enum fc_rport_event event; - struct fc_rport_operations *ops; - struct list_head peers; - struct work_struct event_work; - u32 supported_classes; + u16 flags; + u16 max_seq; + u16 disc_id; + u16 maxframe_size; + unsigned int retries; + unsigned int e_d_tov; + unsigned int r_a_tov; + struct mutex rp_mutex; + struct delayed_work retry_work; + enum fc_rport_event event; + struct fc_rport_operations *ops; + struct list_head peers; + struct work_struct event_work; + u32 supported_classes; }; -/* - * fcoe stats structure +/** + * struct fcoe_dev_stats - fcoe stats structure + * @SecondsSinceLastReset: Seconds since the last reset + * @TxFrames: Number of transmitted frames + * @TxWords: Number of transmitted words + * @RxFrames: Number of received frames + * @RxWords: Number of received words + * @ErrorFrames: Number of received error frames + * @DumpedFrames: Number of dumped frames + * @LinkFailureCount: Number of link failures + * @LossOfSignalCount: Number for signal losses + * @InvalidTxWordCount: Number of invalid transmitted words + * @InvalidCRCCount: Number of invalid CRCs + * @InputRequests: Number of input requests + * @OutputRequests: Number of output requests + * @ControlRequests: Number of control requests + * @InputMegabytes: Number of received megabytes + * @OutputMegabytes: Number of transmitted megabytes */ struct fcoe_dev_stats { u64 SecondsSinceLastReset; @@ -199,10 +249,13 @@ struct fcoe_dev_stats { u64 OutputMegabytes; }; -/* - * els data is used for passing ELS respone specific - * data to send ELS response mainly using infomation - * in exchange and sequence in EM layer. +/** + * struct fc_seq_els_data - ELS data used for passing ELS specific responses + * @fp: The ELS frame + * @reason: The reason for rejection + * @explan: The explaination of the rejection + * + * Mainly used by the exchange manager layer. */ struct fc_seq_els_data { struct fc_frame *fp; @@ -210,77 +263,87 @@ struct fc_seq_els_data { enum fc_els_rjt_explan explan; }; -/* - * FCP request structure, one for each scsi cmd request +/** + * struct fc_fcp_pkt - FCP request structure (one for each scsi_cmnd request) + * @lp: The associated local port + * @state: The state of the I/O + * @tgt_flags: Target's flags + * @ref_cnt: Reference count + * @scsi_pkt_lock: Lock to protect the SCSI packet (must be taken before the + * host_lock if both are to be held at the same time) + * @cmd: The SCSI command (set and clear with the host_lock held) + * @list: Tracks queued commands (accessed with the host_lock held) + * @timer: The command timer + * @tm_done: Completion indicator + * @wait_for_comp: Indicator to wait for completion of the I/O (in jiffies) + * @start_time: Timestamp indicating the start of the I/O (in jiffies) + * @end_time: Timestamp indicating the end of the I/O (in jiffies) + * @last_pkt_time: Timestamp of the last frame received (in jiffies) + * @data_len: The length of the data + * @cdb_cmd: The CDB command + * @xfer_len: The transfer length + * @xfer_ddp: Indicates if this transfer used DDP (XID of the exchange + * will be set here if DDP was setup) + * @xfer_contig_end: The offset into the buffer if the buffer is contiguous + * (Tx and Rx) + * @max_payload: The maximum payload size (in bytes) + * @io_status: SCSI result (upper 24 bits) + * @cdb_status: CDB status + * @status_code: FCP I/O status + * @scsi_comp_flags: Completion flags (bit 3 Underrun bit 2: overrun) + * @req_flags: Request flags (bit 0: read bit:1 write) + * @scsi_resid: SCSI residule length + * @rport: The remote port that the SCSI command is targeted at + * @seq_ptr: The sequence that will carry the SCSI command + * @recov_retry: Number of recovery retries + * @recov_seq: The sequence for REC or SRR */ struct fc_fcp_pkt { - /* - * housekeeping stuff - */ - struct fc_lport *lp; /* handle to hba struct */ - u16 state; /* scsi_pkt state state */ - u16 tgt_flags; /* target flags */ - atomic_t ref_cnt; /* fcp pkt ref count */ - spinlock_t scsi_pkt_lock; /* Must be taken before the host lock - * if both are held at the same time */ - /* - * SCSI I/O related stuff - */ - struct scsi_cmnd *cmd; /* scsi command pointer. set/clear - * under host lock */ - struct list_head list; /* tracks queued commands. access under - * host lock */ - /* - * timeout related stuff - */ - struct timer_list timer; /* command timer */ + /* Housekeeping information */ + struct fc_lport *lp; + u16 state; + u16 tgt_flags; + atomic_t ref_cnt; + spinlock_t scsi_pkt_lock; + + /* SCSI I/O related information */ + struct scsi_cmnd *cmd; + struct list_head list; + + /* Timeout related information */ + struct timer_list timer; struct completion tm_done; - int wait_for_comp; - unsigned long start_time; /* start jiffie */ - unsigned long end_time; /* end jiffie */ - unsigned long last_pkt_time; /* jiffies of last frame received */ - - /* - * scsi cmd and data transfer information - */ - u32 data_len; - /* - * transport related veriables - */ - 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 */ - - /* - * scsi/fcp return status - */ - u32 io_status; /* SCSI result upper 24 bits */ - u8 cdb_status; - u8 status_code; /* FCP I/O status */ - /* bit 3 Underrun bit 2: overrun */ - u8 scsi_comp_flags; - u32 req_flags; /* bit 0: read bit:1 write */ - u32 scsi_resid; /* residule length */ - - struct fc_rport *rport; /* remote port pointer */ - struct fc_seq *seq_ptr; /* current sequence pointer */ - /* - * Error Processing - */ - u8 recov_retry; /* count of recovery retries */ - struct fc_seq *recov_seq; /* sequence for REC or SRR */ + int wait_for_comp; + unsigned long start_time; + unsigned long end_time; + unsigned long last_pkt_time; + + /* SCSI command and data transfer information */ + u32 data_len; + + /* Transport related veriables */ + struct fcp_cmnd cdb_cmd; + size_t xfer_len; + u16 xfer_ddp; + u32 xfer_contig_end; + u16 max_payload; + + /* SCSI/FCP return status */ + u32 io_status; + u8 cdb_status; + u8 status_code; + u8 scsi_comp_flags; + u32 req_flags; + u32 scsi_resid; + + /* Associated structures */ + struct fc_rport *rport; + struct fc_seq *seq_ptr; + + /* Error Processing information */ + u8 recov_retry; + struct fc_seq *recov_seq; }; -/* - * 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 @@ -293,23 +356,51 @@ static inline bool fc_fcp_is_read(const struct fc_fcp_pkt *fsp) struct fc_exch_mgr; struct fc_exch_mgr_anchor; -extern u16 fc_cpu_mask; /* cpu mask for possible cpus */ +extern u16 fc_cpu_mask; /* cpu mask for possible cpus */ -/* - * Sequence. +/** + * struct fc_seq - FC sequence + * @id: The sequence ID + * @ssb_stat: Status flags for the sequence status block (SSB) + * @cnt: Number of frames sent so far + * @rec_data: FC-4 value for REC */ struct fc_seq { - u8 id; /* seq ID */ - u16 ssb_stat; /* status flags for sequence status block */ - u16 cnt; /* frames sent so far on sequence */ - u32 rec_data; /* FC-4 value for REC */ + u8 id; + u16 ssb_stat; + u16 cnt; + u32 rec_data; }; #define FC_EX_DONE (1 << 0) /* ep is completed */ #define FC_EX_RST_CLEANUP (1 << 1) /* reset is forcing completion */ -/* - * Exchange. +/** + * struct fc_exch - Fibre Channel Exchange + * @em: Exchange manager + * @pool: Exchange pool + * @state: The exchange's state + * @xid: The exchange ID + * @ex_list: Handle used by the EM to track free exchanges + * @ex_lock: Lock that protects the exchange + * @ex_refcnt: Reference count + * @timeout_work: Handle for timeout handler + * @lp: The local port that this exchange is on + * @oxid: Originator's exchange ID + * @rxid: Responder's exchange ID + * @oid: Originator's FCID + * @sid: Source FCID + * @did: Destination FCID + * @esb_stat: ESB exchange status + * @r_a_tov: Resouce allocation time out value (in msecs) + * @seq_id: The next sequence ID to use + * @f_ctl: F_CTL flags for the sequence + * @fh_type: The frame type + * @class: The class of service + * @seq: The sequence in use on this exchange + * @resp: Callback for responses on this exchange + * @destructor: Called when destroying the exchange + * @arg: Passed as a void pointer to the resp() callback * * Locking notes: The ex_lock protects following items: * state, esb_stat, f_ctl, seq.ssb_stat @@ -317,76 +408,59 @@ struct fc_seq { * sequence allocation */ struct fc_exch { - struct fc_exch_mgr *em; /* exchange manager */ - struct fc_exch_pool *pool; /* per cpu exches pool */ - u32 state; /* internal driver state */ - u16 xid; /* our exchange ID */ - struct list_head ex_list; /* free or busy list linkage */ - spinlock_t ex_lock; /* lock covering exchange state */ - atomic_t ex_refcnt; /* reference counter */ - struct delayed_work timeout_work; /* timer for upper level protocols */ - struct fc_lport *lp; /* fc device instance */ - u16 oxid; /* originator's exchange ID */ - u16 rxid; /* responder's exchange ID */ - u32 oid; /* originator's FCID */ - u32 sid; /* source FCID */ - u32 did; /* destination FCID */ - u32 esb_stat; /* exchange status for ESB */ - u32 r_a_tov; /* r_a_tov from rport (msec) */ - u8 seq_id; /* next sequence ID to use */ - u32 f_ctl; /* F_CTL flags for sequences */ - u8 fh_type; /* frame type */ - enum fc_class class; /* class of service */ - struct fc_seq seq; /* single sequence */ - /* - * Handler for responses to this current exchange. - */ - void (*resp)(struct fc_seq *, struct fc_frame *, void *); - void (*destructor)(struct fc_seq *, void *); - /* - * arg is passed as void pointer to exchange - * resp and destructor handlers - */ - void *arg; + struct fc_exch_mgr *em; + struct fc_exch_pool *pool; + u32 state; + u16 xid; + struct list_head ex_list; + spinlock_t ex_lock; + atomic_t ex_refcnt; + struct delayed_work timeout_work; + struct fc_lport *lp; + u16 oxid; + u16 rxid; + u32 oid; + u32 sid; + u32 did; + u32 esb_stat; + u32 r_a_tov; + u8 seq_id; + u32 f_ctl; + u8 fh_type; + enum fc_class class; + struct fc_seq seq; + + void (*resp)(struct fc_seq *, struct fc_frame *, void *); + void *arg; + + void (*destructor)(struct fc_seq *, void *); + }; #define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq) -struct libfc_function_template { +struct libfc_function_template { /* * Interface to send a FC frame * * STATUS: REQUIRED */ - int (*frame_send)(struct fc_lport *lp, struct fc_frame *fp); + int (*frame_send)(struct fc_lport *, struct fc_frame *); /* * Interface to send ELS/CT frames * * STATUS: OPTIONAL */ - struct fc_seq *(*elsct_send)(struct fc_lport *lport, - u32 did, - struct fc_frame *fp, - unsigned int op, + struct fc_seq *(*elsct_send)(struct fc_lport *, u32 did, + struct fc_frame *, unsigned int op, void (*resp)(struct fc_seq *, - struct fc_frame *fp, - void *arg), + struct fc_frame *, void *arg), void *arg, u32 timer_msec); /* * Send the FC frame payload using a new exchange and sequence. * - * The frame pointer with some of the header's fields must be - * filled before calling exch_seq_send(), those fields are, - * - * - routing control - * - FC port did - * - FC port sid - * - FC header type - * - frame control - * - parameter or relative offset - * * The exchange response handler is set in this routine to resp() * function pointer. It can be called in two scenarios: if a timeout * occurs or if a response frame is received for the exchange. The @@ -407,14 +481,13 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - struct fc_seq *(*exch_seq_send)(struct fc_lport *lp, - struct fc_frame *fp, - void (*resp)(struct fc_seq *sp, - struct fc_frame *fp, - void *arg), - void (*destructor)(struct fc_seq *sp, - void *arg), - void *arg, unsigned int timer_msec); + struct fc_seq *(*exch_seq_send)(struct fc_lport *, struct fc_frame *, + void (*resp)(struct fc_seq *, + struct fc_frame *, + void *), + void (*destructor)(struct fc_seq *, + void *), + void *, unsigned int timer_msec); /* * Sets up the DDP context for a given exchange id on the given @@ -422,22 +495,22 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - int (*ddp_setup)(struct fc_lport *lp, u16 xid, - struct scatterlist *sgl, unsigned int sgc); + int (*ddp_setup)(struct fc_lport *, u16, struct scatterlist *, + unsigned int); /* * 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); + int (*ddp_done)(struct fc_lport *, u16); /* * Send a frame using an existing sequence and exchange. * * STATUS: OPTIONAL */ - int (*seq_send)(struct fc_lport *lp, struct fc_seq *sp, - struct fc_frame *fp); + int (*seq_send)(struct fc_lport *, struct fc_seq *, + struct fc_frame *); /* * Send an ELS response using infomation from a previous @@ -445,8 +518,8 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - void (*seq_els_rsp_send)(struct fc_seq *sp, enum fc_els_cmd els_cmd, - struct fc_seq_els_data *els_data); + void (*seq_els_rsp_send)(struct fc_seq *, enum fc_els_cmd, + struct fc_seq_els_data *); /* * Abort an exchange and sequence. Generally called because of a @@ -458,7 +531,7 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - int (*seq_exch_abort)(const struct fc_seq *req_sp, + int (*seq_exch_abort)(const struct fc_seq *, unsigned int timer_msec); /* @@ -467,14 +540,14 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - void (*exch_done)(struct fc_seq *sp); + void (*exch_done)(struct fc_seq *); /* * Start a new sequence on the same exchange/sequence tuple. * * STATUS: OPTIONAL */ - struct fc_seq *(*seq_start_next)(struct fc_seq *sp); + struct fc_seq *(*seq_start_next)(struct fc_seq *); /* * Reset an exchange manager, completing all sequences and exchanges. @@ -483,8 +556,7 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - void (*exch_mgr_reset)(struct fc_lport *, - u32 s_id, u32 d_id); + void (*exch_mgr_reset)(struct fc_lport *, u32 s_id, u32 d_id); /* * Flush the rport work queue. Generally used before shutdown. @@ -498,8 +570,8 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - void (*lport_recv)(struct fc_lport *lp, struct fc_seq *sp, - struct fc_frame *fp); + void (*lport_recv)(struct fc_lport *, struct fc_seq *, + struct fc_frame *); /* * Reset the local port. @@ -565,31 +637,31 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - int (*fcp_cmd_send)(struct fc_lport *lp, struct fc_fcp_pkt *fsp, - void (*resp)(struct fc_seq *, struct fc_frame *fp, - void *arg)); + int (*fcp_cmd_send)(struct fc_lport *, struct fc_fcp_pkt *, + void (*resp)(struct fc_seq *, struct fc_frame *, + void *)); /* * Cleanup the FCP layer, used durring link down and reset * * STATUS: OPTIONAL */ - void (*fcp_cleanup)(struct fc_lport *lp); + void (*fcp_cleanup)(struct fc_lport *); /* * Abort all I/O on a local port * * STATUS: OPTIONAL */ - void (*fcp_abort_io)(struct fc_lport *lp); + void (*fcp_abort_io)(struct fc_lport *); /* * Receive a request for the discovery layer. * * STATUS: OPTIONAL */ - void (*disc_recv_req)(struct fc_seq *, - struct fc_frame *, struct fc_lport *); + void (*disc_recv_req)(struct fc_seq *, struct fc_frame *, + struct fc_lport *); /* * Start discovery for a local port. @@ -618,133 +690,224 @@ struct libfc_function_template { void (*disc_stop_final) (struct fc_lport *); }; -/* information used by the discovery layer */ +/** + * struct fc_disc - Discovery context + * @retry_count: Number of retries + * @pending: 1 if discovery is pending, 0 if not + * @requesting: 1 if discovery has been requested, 0 if not + * @seq_count: Number of sequences used for discovery + * @buf_len: Length of the discovery buffer + * @disc_id: Discovery ID + * @rports: List of discovered remote ports + * @lport: The local port that discovery is for + * @disc_mutex: Mutex that protects the discovery context + * @partial_buf: Partial name buffer (if names are returned + * in multiple frames) + * @disc_work: handle for delayed work context + * @disc_callback: Callback routine called when discovery completes + */ struct fc_disc { - unsigned char retry_count; - unsigned char pending; - unsigned char requested; - unsigned short seq_count; - unsigned char buf_len; - u16 disc_id; + unsigned char retry_count; + unsigned char pending; + unsigned char requested; + unsigned short seq_count; + unsigned char buf_len; + u16 disc_id; + + struct list_head rports; + struct fc_lport *lport; + struct mutex disc_mutex; + struct fc_gpn_ft_resp partial_buf; + struct delayed_work disc_work; void (*disc_callback)(struct fc_lport *, enum fc_disc_event); - - struct list_head rports; - struct fc_lport *lport; - struct mutex disc_mutex; - struct fc_gpn_ft_resp partial_buf; /* partial name buffer */ - struct delayed_work disc_work; }; +/** + * struct fc_lport - Local port + * @host: The SCSI host associated with a local port + * @ema_list: Exchange manager anchor list + * @dns_rdata: The directory server remote port + * @ptp_rdata: Point to point remote port + * @scsi_priv: FCP layer internal data + * @disc: Discovery context + * @vports: Child vports if N_Port + * @vport: Parent vport if VN_Port + * @tt: Libfc function template + * @link_up: Link state (1 = link up, 0 = link down) + * @qfull: Queue state (1 queue is full, 0 queue is not full) + * @state: Identifies the state + * @boot_time: Timestamp indicating when the local port came online + * @host_stats: SCSI host statistics + * @dev_stats: FCoE device stats (TODO: libfc should not be + * FCoE aware) + * @retry_count: Number of retries in the current state + * @wwpn: World Wide Port Name + * @wwnn: World Wide Node Name + * @service_params: Common service parameters + * @e_d_tov: Error detection timeout value + * @r_a_tov: Resouce allocation timeout value + * @rnid_gen: RNID information + * @sg_supp: Indicates if scatter gather is supported + * @seq_offload: Indicates if sequence offload is supported + * @crc_offload: Indicates if CRC offload is supported + * @lro_enabled: Indicates if large receive offload is supported + * @does_npiv: Supports multiple vports + * @npiv_enabled: Switch/fabric allows NPIV + * @mfs: The maximum Fibre Channel payload size + * @max_retry_count: The maximum retry attempts + * @max_rport_retry_count: The maximum remote port retry attempts + * @lro_xid: The maximum XID for LRO + * @lso_max: The maximum large offload send size + * @fcts: FC-4 type mask + * @lp_mutex: Mutex to protect the local port + * @list: Handle for list of local ports + * @retry_work: Handle to local port for delayed retry context + */ struct fc_lport { - struct list_head list; - /* Associations */ - struct Scsi_Host *host; - struct list_head ema_list; - struct list_head vports; /* child vports if N_Port */ - struct fc_vport *vport; /* parent vport if VN_Port */ - struct fc_rport_priv *dns_rp; - struct fc_rport_priv *ptp_rp; - void *scsi_priv; - struct fc_disc disc; + struct Scsi_Host *host; + struct list_head ema_list; + struct fc_rport_priv *dns_rdata; + struct fc_rport_priv *ptp_rdata; + void *scsi_priv; + struct fc_disc disc; + + /* Virtual port information */ + struct list_head vports; + struct fc_vport *vport; /* Operational Information */ struct libfc_function_template tt; - u8 link_up; - u8 qfull; - enum fc_lport_state state; - unsigned long boot_time; - - struct fc_host_statistics host_stats; - struct fcoe_dev_stats *dev_stats; - - u64 wwpn; - u64 wwnn; - u8 retry_count; + u8 link_up; + u8 qfull; + enum fc_lport_state state; + unsigned long boot_time; + struct fc_host_statistics host_stats; + struct fcoe_dev_stats *dev_stats; + u8 retry_count; + + /* Fabric information */ + u64 wwpn; + u64 wwnn; + unsigned int service_params; + unsigned int e_d_tov; + unsigned int r_a_tov; + struct fc_els_rnid_gen rnid_gen; /* Capabilities */ - u32 sg_supp:1; /* scatter gather supported */ - u32 seq_offload:1; /* seq offload supported */ - u32 crc_offload:1; /* crc offload supported */ - u32 lro_enabled:1; /* large receive offload */ - u32 does_npiv:1; /* supports multiple vports */ - u32 npiv_enabled:1; /* switch/fabric allows NPIV */ - u32 mfs; /* max FC payload size */ - unsigned int service_params; - unsigned int e_d_tov; - unsigned int r_a_tov; - u8 max_retry_count; - u8 max_rport_retry_count; - 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 */ - - /* Semaphores */ - struct mutex lp_mutex; + u32 sg_supp:1; + u32 seq_offload:1; + u32 crc_offload:1; + u32 lro_enabled:1; + u32 does_npiv:1; + u32 npiv_enabled:1; + u32 mfs; + u8 max_retry_count; + u8 max_rport_retry_count; + u16 link_speed; + u16 link_supported_speeds; + u16 lro_xid; + unsigned int lso_max; + struct fc_ns_fts fcts; /* Miscellaneous */ - struct delayed_work retry_work; + struct mutex lp_mutex; + struct list_head list; + struct delayed_work retry_work; }; /* * FC_LPORT HELPER FUNCTIONS *****************************/ -static inline int fc_lport_test_ready(struct fc_lport *lp) + +/** + * fc_lport_test_ready() - Determine if a local port is in the READY state + * @lport: The local port to test + */ +static inline int fc_lport_test_ready(struct fc_lport *lport) { - return lp->state == LPORT_ST_READY; + return lport->state == LPORT_ST_READY; } -static inline void fc_set_wwnn(struct fc_lport *lp, u64 wwnn) +/** + * fc_set_wwnn() - Set the World Wide Node Name of a local port + * @lport: The local port whose WWNN is to be set + * @wwnn: The new WWNN + */ +static inline void fc_set_wwnn(struct fc_lport *lport, u64 wwnn) { - lp->wwnn = wwnn; + lport->wwnn = wwnn; } -static inline void fc_set_wwpn(struct fc_lport *lp, u64 wwnn) +/** + * fc_set_wwpn() - Set the World Wide Port Name of a local port + * @lport: The local port whose WWPN is to be set + * @wwnn: The new WWPN + */ +static inline void fc_set_wwpn(struct fc_lport *lport, u64 wwnn) { - lp->wwpn = wwnn; + lport->wwpn = wwnn; } -static inline void fc_lport_state_enter(struct fc_lport *lp, +/** + * fc_lport_state_enter() - Change a local port's state + * @lport: The local port whose state is to change + * @state: The new state + */ +static inline void fc_lport_state_enter(struct fc_lport *lport, enum fc_lport_state state) { - if (state != lp->state) - lp->retry_count = 0; - lp->state = state; + if (state != lport->state) + lport->retry_count = 0; + lport->state = state; } -static inline int fc_lport_init_stats(struct fc_lport *lp) +/** + * fc_lport_init_stats() - Allocate per-CPU statistics for a local port + * @lport: The local port whose statistics are to be initialized + */ +static inline int fc_lport_init_stats(struct fc_lport *lport) { - /* allocate per cpu stats block */ - lp->dev_stats = alloc_percpu(struct fcoe_dev_stats); - if (!lp->dev_stats) + lport->dev_stats = alloc_percpu(struct fcoe_dev_stats); + if (!lport->dev_stats) return -ENOMEM; return 0; } -static inline void fc_lport_free_stats(struct fc_lport *lp) +/** + * fc_lport_free_stats() - Free memory for a local port's statistics + * @lport: The local port whose statistics are to be freed + */ +static inline void fc_lport_free_stats(struct fc_lport *lport) { - free_percpu(lp->dev_stats); + free_percpu(lport->dev_stats); } -static inline struct fcoe_dev_stats *fc_lport_get_stats(struct fc_lport *lp) +/** + * fc_lport_get_stats() - Get a local port's statistics + * @lport: The local port whose statistics are to be retreived + */ +static inline struct fcoe_dev_stats *fc_lport_get_stats(struct fc_lport *lport) { - return per_cpu_ptr(lp->dev_stats, smp_processor_id()); + return per_cpu_ptr(lport->dev_stats, smp_processor_id()); } -static inline void *lport_priv(const struct fc_lport *lp) +/** + * lport_priv() - Return the private data from a local port + * @lport: The local port whose private data is to be retreived + */ +static inline void *lport_priv(const struct fc_lport *lport) { - return (void *)(lp + 1); + return (void *)(lport + 1); } /** - * libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport - * @sht: ptr to the scsi host templ - * @priv_size: size of private data after fc_lport + * libfc_host_alloc() - Allocate a Scsi_Host with room for a local port and + * LLD private data + * @sht: The SCSI host template + * @priv_size: Size of private data * * Returns: libfc lport */ @@ -765,156 +928,73 @@ libfc_host_alloc(struct scsi_host_template *sht, int priv_size) } /* - * LOCAL PORT LAYER + * FC_FCP HELPER FUNCTIONS *****************************/ -int fc_lport_init(struct fc_lport *lp); - -/* - * Destroy the specified local port by finding and freeing all - * fc_rports associated with it and then by freeing the fc_lport - * itself. - */ -int fc_lport_destroy(struct fc_lport *lp); - -/* - * Logout the specified local port from the fabric - */ -int fc_fabric_logoff(struct fc_lport *lp); - -/* - * Initiate the LP state machine. This handler will use fc_host_attr - * to store the FLOGI service parameters, so fc_host_attr must be - * initialized before calling this handler. - */ -int fc_fabric_login(struct fc_lport *lp); +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; +} /* - * The link is up for the given local port. - */ + * LOCAL PORT LAYER + *****************************/ +int fc_lport_init(struct fc_lport *); +int fc_lport_destroy(struct fc_lport *); +int fc_fabric_logoff(struct fc_lport *); +int fc_fabric_login(struct fc_lport *); void __fc_linkup(struct fc_lport *); void fc_linkup(struct fc_lport *); - -/* - * Link is down for the given local port. - */ void __fc_linkdown(struct fc_lport *); void fc_linkdown(struct fc_lport *); - -/* - * Configure the local port. - */ +void fc_vport_setlink(struct fc_lport *); +void fc_vports_linkchange(struct fc_lport *); int fc_lport_config(struct fc_lport *); - -/* - * Reset the local port. - */ int fc_lport_reset(struct fc_lport *); - -/* - * Set the mfs or reset - */ -int fc_set_mfs(struct fc_lport *lp, u32 mfs); - -/* - * Allocate a new lport struct for an NPIV VN_Port - */ -struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize); - -/* - * Find an NPIV VN_Port by port ID - */ -struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id); - -/* - * NPIV VN_Port link state management - */ -void fc_vport_setlink(struct fc_lport *vn_port); -void fc_vports_linkchange(struct fc_lport *n_port); - -/* - * Issue fc pass-thru request via bsg interface - */ -int fc_lport_bsg_request(struct fc_bsg_job *job); - +int fc_set_mfs(struct fc_lport *, u32 mfs); +struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize); +struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id); +int fc_lport_bsg_request(struct fc_bsg_job *); /* * REMOTE PORT LAYER *****************************/ -int fc_rport_init(struct fc_lport *lp); -void fc_rport_terminate_io(struct fc_rport *rp); +int fc_rport_init(struct fc_lport *); +void fc_rport_terminate_io(struct fc_rport *); /* * DISCOVERY LAYER *****************************/ -int fc_disc_init(struct fc_lport *lp); - +int fc_disc_init(struct fc_lport *); /* - * SCSI LAYER + * FCP LAYER *****************************/ -/* - * Initialize the SCSI block of libfc - */ int fc_fcp_init(struct fc_lport *); +void fc_fcp_destroy(struct fc_lport *); /* - * This section provides an API which allows direct interaction - * with the SCSI-ml. Each of these functions satisfies a function - * pointer defined in Scsi_Host and therefore is always called - * directly from the SCSI-ml. - */ -int fc_queuecommand(struct scsi_cmnd *sc_cmd, + * SCSI INTERACTION LAYER + *****************************/ +int fc_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); - -/* - * Send an ABTS frame to the target device. The sc_cmd argument - * is a pointer to the SCSI command to be aborted. - */ -int fc_eh_abort(struct scsi_cmnd *sc_cmd); - -/* - * Reset a LUN by sending send the tm cmd to the target. - */ -int fc_eh_device_reset(struct scsi_cmnd *sc_cmd); - -/* - * Reset the host adapter. - */ -int fc_eh_host_reset(struct scsi_cmnd *sc_cmd); - -/* - * Check rport status. - */ -int fc_slave_alloc(struct scsi_device *sdev); - -/* - * Adjust the queue depth. - */ -int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason); - -/* - * Change the tag type. - */ -int fc_change_queue_type(struct scsi_device *sdev, int tag_type); - -/* - * Free memory pools used by the FCP layer. - */ -void fc_fcp_destroy(struct fc_lport *); +int fc_eh_abort(struct scsi_cmnd *); +int fc_eh_device_reset(struct scsi_cmnd *); +int fc_eh_host_reset(struct scsi_cmnd *); +int fc_slave_alloc(struct scsi_device *); +int fc_change_queue_depth(struct scsi_device *, int qdepth, int reason); +int fc_change_queue_type(struct scsi_device *, int tag_type); /* * ELS/CT interface *****************************/ -/* - * Initializes ELS/CT interface - */ -int fc_elsct_init(struct fc_lport *lp); -struct fc_seq *fc_elsct_send(struct fc_lport *lport, - u32 did, - struct fc_frame *fp, +int fc_elsct_init(struct fc_lport *); +struct fc_seq *fc_elsct_send(struct fc_lport *, u32 did, + struct fc_frame *, unsigned int op, void (*resp)(struct fc_seq *, - struct fc_frame *fp, + struct fc_frame *, void *arg), void *arg, u32 timer_msec); void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); @@ -924,90 +1004,26 @@ void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); /* * EXCHANGE MANAGER LAYER *****************************/ -/* - * Initializes Exchange Manager related - * function pointers in struct libfc_function_template. - */ -int fc_exch_init(struct fc_lport *lp); - -/* - * Adds Exchange Manager (EM) mp to lport. - * - * Adds specified mp to lport using struct fc_exch_mgr_anchor, - * the struct fc_exch_mgr_anchor allows same EM sharing by - * more than one lport with their specified match function, - * the match function is used in allocating exchange from - * added mp. - */ -struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport, - struct fc_exch_mgr *mp, +int fc_exch_init(struct fc_lport *); +struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *, + struct fc_exch_mgr *, bool (*match)(struct fc_frame *)); - -/* - * Deletes Exchange Manager (EM) from lport by removing - * its anchor ema from lport. - * - * If removed anchor ema was the last user of its associated EM - * then also destroys associated EM. - */ -void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema); - -/* - * Clone an exchange manager list, getting reference holds for each EM. - * This is for use with NPIV and sharing the X_ID space between VN_Ports. - */ +void fc_exch_mgr_del(struct fc_exch_mgr_anchor *); int fc_exch_mgr_list_clone(struct fc_lport *src, struct fc_lport *dst); - -/* - * Allocates an Exchange Manager (EM). - * - * The EM manages exchanges for their allocation and - * free, also allows exchange lookup for received - * frame. - * - * The class is used for initializing FC class of - * allocated exchange from EM. - * - * The min_xid and max_xid will limit new - * exchange ID (XID) within this range for - * a new exchange. - * The LLD may choose to have multiple EMs, - * e.g. one EM instance per CPU receive thread in LLD. - * - * Specified match function is used in allocating exchanges - * from newly allocated EM. - */ -struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, - enum fc_class class, - u16 min_xid, - u16 max_xid, +struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *, enum fc_class class, + u16 min_xid, u16 max_xid, bool (*match)(struct fc_frame *)); - -/* - * Free all exchange managers of a lport. - */ -void fc_exch_mgr_free(struct fc_lport *lport); - -/* - * Receive a frame on specified local port and exchange manager. - */ -void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp); - -/* - * Reset all EMs of a lport, releasing its all sequences and - * exchanges. If sid is non-zero, then reset only exchanges - * we sourced from that FID. If did is non-zero, reset only - * exchanges destined to that FID. - */ +void fc_exch_mgr_free(struct fc_lport *); +void fc_exch_recv(struct fc_lport *, struct fc_frame *); void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id); /* * Functions for fc_functions_template */ -void fc_get_host_speed(struct Scsi_Host *shost); -void fc_get_host_port_type(struct Scsi_Host *shost); -void fc_get_host_port_state(struct Scsi_Host *shost); -void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout); +void fc_get_host_speed(struct Scsi_Host *); +void fc_get_host_port_type(struct Scsi_Host *); +void fc_get_host_port_state(struct Scsi_Host *); +void fc_set_rport_loss_tmo(struct fc_rport *, u32 timeout); struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *); #endif /* _LIBFC_H_ */ -- cgit v1.2.3-70-g09d2 From 093bb6a2d378ee83fc6ab886c772b6be86abb5a8 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 3 Nov 2009 11:49:05 -0800 Subject: [SCSI] libfc: add set_fid function to libfc template This is to notify the LLD when an FC_ID is assigned to the local port. The fnic driver needs to push the assigned FC_ID to firmware. It currently does this by intercepting the FLOGI responses, and in order to make that code more common with FIP and NPIV, it makes more sense to wait until the local port has completely handled the FLOGI or FDISC response. Also, when we fix point-to-point FC_ID assignment, we'll need this callback as well. Add a call to the libfc template, which is called whenever the local port FC_ID is being assigned. It defaults to fc_lport_set_fid(), supplied by libfc. As additional benefit of this function, the LLD may determine the MAC address that caused the change by looking at the received frame. We also print the assigned port ID as long as it isn't 0. Setting port ID to 0 happens often in reset while retrying FLOGI, and would be uninteresting. This replaces the previous message which didn't identify the host adapter instance. patch v2 note: changed one word in a comment. "intercepted" -> "provided". Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 34 +++++++++++++++++++++++++++------- include/scsi/libfc.h | 20 ++++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 90930c43545..653b52dd2ff 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -732,6 +732,27 @@ static void fc_lport_enter_ready(struct fc_lport *lport) lport->tt.disc_start(fc_lport_disc_callback, lport); } +/** + * fc_lport_set_port_id() - set the local port Port ID + * @lport: The local port which will have its Port ID set. + * @port_id: The new port ID. + * @fp: The frame containing the incoming request, or NULL. + * + * Locking Note: The lport lock is expected to be held before calling + * this function. + */ +static void fc_lport_set_port_id(struct fc_lport *lport, u32 port_id, + struct fc_frame *fp) +{ + if (port_id) + printk(KERN_INFO "host%d: Assigned Port ID %6x\n", + lport->host->host_no, port_id); + + fc_host_port_id(lport->host) = port_id; + if (lport->tt.lport_set_port_id) + lport->tt.lport_set_port_id(lport, port_id, fp); +} + /** * fc_lport_recv_flogi_req() - Receive a FLOGI request * @sp_in: The sequence the FLOGI is on @@ -790,7 +811,7 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, remote_fid = FC_LOCAL_PTP_FID_HI; } - fc_host_port_id(lport->host) = local_fid; + fc_lport_set_port_id(lport, local_fid, rx_fp); fp = fc_frame_alloc(lport, sizeof(*flp)); if (fp) { @@ -926,7 +947,9 @@ static void fc_lport_reset_locked(struct fc_lport *lport) lport->tt.exch_mgr_reset(lport, 0, 0); fc_host_fabric_name(lport->host) = 0; - fc_host_port_id(lport->host) = 0; + + if (fc_host_port_id(lport->host)) + fc_lport_set_port_id(lport, 0, NULL); } /** @@ -1428,11 +1451,6 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, fh = fc_frame_header_get(fp); did = ntoh24(fh->fh_d_id); if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { - - printk(KERN_INFO "libfc: Assigned FID (%6x) in FLOGI response\n", - did); - fc_host_port_id(lport->host) = did; - flp = fc_frame_payload_get(fp, sizeof(*flp)); if (flp) { mfs = ntohs(flp->fl_csp.sp_bb_data) & @@ -1452,6 +1470,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, if (e_d_tov > lport->e_d_tov) lport->e_d_tov = e_d_tov; lport->r_a_tov = 2 * e_d_tov; + fc_lport_set_port_id(lport, did, fp); printk(KERN_INFO "libfc: Port (%6x) entered " "point to point mode\n", did); fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id), @@ -1464,6 +1483,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, lport->r_a_tov = r_a_tov; fc_host_fabric_name(lport->host) = get_unaligned_be64(&flp->fl_wwnn); + fc_lport_set_port_id(lport, did, fp); fc_lport_enter_dns(lport); } } diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 310d8a22b72..67ce9fa1fee 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -580,6 +580,26 @@ struct libfc_function_template { */ int (*lport_reset)(struct fc_lport *); + /* + * Set the local port FC_ID. + * + * This may be provided by the LLD to allow it to be + * notified when the local port is assigned a FC-ID. + * + * The frame, if non-NULL, is the incoming frame with the + * FLOGI LS_ACC or FLOGI, and may contain the granted MAC + * address for the LLD. The frame pointer may be NULL if + * no MAC is associated with this assignment (LOGO or PLOGI). + * + * If FC_ID is non-zero, r_a_tov and e_d_tov must be valid. + * + * Note: this is called with the local port mutex held. + * + * STATUS: OPTIONAL + */ + void (*lport_set_port_id)(struct fc_lport *, u32 port_id, + struct fc_frame *); + /* * Create a remote port with a given port ID * -- cgit v1.2.3-70-g09d2 From ab593b187391bdd03ccad2968972a2e118a88cd4 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 3 Nov 2009 11:49:27 -0800 Subject: [SCSI] libfc: register FC4 features with the FC switch Customers and certification tests have pointed out that we don't show up on the switch management software as an initiator. On some MDS switches 'show fcns database' command shows libfc initiators as 'fcp' not 'fcp:init' like other initiators. On others switches, I think the switch gets the features by doing a PRLI, but it may be only certain models or under certain configurations. Fix this by registering our FC4 features with the RFF_ID CT request after local port login and after the RFT_ID. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 12 +++++++++++- include/scsi/fc/fc_fcp.h | 6 ++++++ include/scsi/fc/fc_ns.h | 13 ++++++++++++- include/scsi/fc_encode.h | 12 ++++++++++++ include/scsi/libfc.h | 2 ++ 5 files changed, 43 insertions(+), 2 deletions(-) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index d3aec195939..1bcc5e11d2c 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -122,6 +122,7 @@ static const char *fc_lport_state_names[] = { [LPORT_ST_RSNN_NN] = "RSNN_NN", [LPORT_ST_RSPN_ID] = "RSPN_ID", [LPORT_ST_RFT_ID] = "RFT_ID", + [LPORT_ST_RFF_ID] = "RFF_ID", [LPORT_ST_SCR] = "SCR", [LPORT_ST_READY] = "Ready", [LPORT_ST_LOGO] = "LOGO", @@ -1034,6 +1035,7 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) case LPORT_ST_RSNN_NN: case LPORT_ST_RSPN_ID: case LPORT_ST_RFT_ID: + case LPORT_ST_RFF_ID: case LPORT_ST_SCR: case LPORT_ST_DNS: case LPORT_ST_FLOGI: @@ -1070,7 +1072,7 @@ static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&lport->lp_mutex); - if (lport->state < LPORT_ST_RNN_ID || lport->state > LPORT_ST_RFT_ID) { + if (lport->state < LPORT_ST_RNN_ID || lport->state > LPORT_ST_RFF_ID) { FC_LPORT_DBG(lport, "Received a name server response, " "but in state %s\n", fc_lport_state(lport)); if (IS_ERR(fp)) @@ -1101,6 +1103,9 @@ static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp, fc_lport_enter_ns(lport, LPORT_ST_RFT_ID); break; case LPORT_ST_RFT_ID: + fc_lport_enter_ns(lport, LPORT_ST_RFF_ID); + break; + case LPORT_ST_RFF_ID: fc_lport_enter_scr(lport); break; default: @@ -1235,6 +1240,10 @@ static void fc_lport_enter_ns(struct fc_lport *lport, enum fc_lport_state state) cmd = FC_NS_RFT_ID; size += sizeof(struct fc_ns_rft); break; + case LPORT_ST_RFF_ID: + cmd = FC_NS_RFF_ID; + size += sizeof(struct fc_ns_rff_id); + break; default: fc_lport_error(lport, NULL); return; @@ -1317,6 +1326,7 @@ static void fc_lport_timeout(struct work_struct *work) case LPORT_ST_RSNN_NN: case LPORT_ST_RSPN_ID: case LPORT_ST_RFT_ID: + case LPORT_ST_RFF_ID: fc_lport_enter_ns(lport, lport->state); break; case LPORT_ST_SCR: diff --git a/include/scsi/fc/fc_fcp.h b/include/scsi/fc/fc_fcp.h index 5d38f1989f3..29ecb0b02b0 100644 --- a/include/scsi/fc/fc_fcp.h +++ b/include/scsi/fc/fc_fcp.h @@ -196,4 +196,10 @@ struct fcp_srr { __u8 srr_resvd2[3]; /* reserved */ }; +/* + * Feature bits in name server FC-4 Features object. + */ +#define FCP_FEAT_TARG (1 << 0) /* target function supported */ +#define FCP_FEAT_INIT (1 << 1) /* initiator function supported */ + #endif /* _FC_FCP_H_ */ diff --git a/include/scsi/fc/fc_ns.h b/include/scsi/fc/fc_ns.h index f4d354eb26b..e7d3ac497d7 100644 --- a/include/scsi/fc/fc_ns.h +++ b/include/scsi/fc/fc_ns.h @@ -46,10 +46,11 @@ enum fc_ns_req { FC_NS_GID_FT = 0x0171, /* get IDs by FC4 type */ FC_NS_GPN_FT = 0x0172, /* get port names by FC4 type */ FC_NS_GID_PT = 0x01a1, /* get IDs by port type */ - FC_NS_RFT_ID = 0x0217, /* reg FC4 type for ID */ FC_NS_RPN_ID = 0x0212, /* reg port name for ID */ FC_NS_RNN_ID = 0x0213, /* reg node name for ID */ + FC_NS_RFT_ID = 0x0217, /* reg FC4 type for ID */ FC_NS_RSPN_ID = 0x0218, /* reg symbolic port name */ + FC_NS_RFF_ID = 0x021f, /* reg FC4 Features for ID */ FC_NS_RSNN_NN = 0x0239, /* reg symbolic node name */ }; @@ -178,4 +179,14 @@ struct fc_ns_rspn { char fr_name[]; } __attribute__((__packed__)); +/* + * RFF_ID request - register FC-4 Features for ID. + */ +struct fc_ns_rff_id { + struct fc_ns_fid fr_fid; /* port ID object */ + __u8 fr_resvd[2]; + __u8 fr_feat; /* FC-4 Feature bits */ + __u8 fr_type; /* FC-4 type */ +} __attribute__((__packed__)); + #endif /* _FC_NS_H_ */ diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h index ab2260cb149..8eb0a0fc0a7 100644 --- a/include/scsi/fc_encode.h +++ b/include/scsi/fc_encode.h @@ -32,6 +32,7 @@ struct fc_ct_req { struct fc_ns_gid_ft gid; struct fc_ns_rn_id rn; struct fc_ns_rft rft; + struct fc_ns_rff_id rff; struct fc_ns_fid fid; struct fc_ns_rsnn snn; struct fc_ns_rspn spn; @@ -131,6 +132,17 @@ static inline int fc_ct_fill(struct fc_lport *lport, ct->payload.rft.fts = lport->fcts; break; + case FC_NS_RFF_ID: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id)); + hton24(ct->payload.rff.fr_fid.fp_fid, + fc_host_port_id(lport->host)); + ct->payload.rff.fr_type = FC_TYPE_FCP; + if (lport->service_params & FCP_SPPF_INIT_FCN) + ct->payload.rff.fr_feat = FCP_FEAT_INIT; + if (lport->service_params & FCP_SPPF_TARG_FCN) + ct->payload.rff.fr_feat |= FCP_FEAT_TARG; + break; + case FC_NS_RNN_ID: ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id)); hton24(ct->payload.rn.fr_fid.fp_fid, diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 67ce9fa1fee..2936fbae41e 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -62,6 +62,7 @@ * @LPORT_ST_DNS: Waiting for name server remote port to become ready * @LPORT_ST_RPN_ID: Register port name by ID (RPN_ID) sent * @LPORT_ST_RFT_ID: Register Fibre Channel types by ID (RFT_ID) sent + * @LPORT_ST_RFF_ID: Register FC-4 Features by ID (RFF_ID) sent * @LPORT_ST_SCR: State Change Register (SCR) sent * @LPORT_ST_READY: Ready for use * @LPORT_ST_LOGO: Local port logout (LOGO) sent @@ -75,6 +76,7 @@ enum fc_lport_state { LPORT_ST_RSNN_NN, LPORT_ST_RSPN_ID, LPORT_ST_RFT_ID, + LPORT_ST_RFF_ID, LPORT_ST_SCR, LPORT_ST_READY, LPORT_ST_LOGO, -- cgit v1.2.3-70-g09d2 From 6580bbd0afe6ba1be5d53b331e92a7690046c923 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 20 Nov 2009 14:54:52 -0800 Subject: [SCSI] libfc: add FC-BB-5 LESB counters to fcoe_dev_stats FC-BB-5 Rev2.0, Clause 7.10 extends the FC-LS-3 LESB for FC-BB_E. We are already tracking Link Failure Count so add the rest in this patch. For VLinkFailureCount and MissDiscAdvCount, they are part of the per-cpu fcoe_dev_stats. For SymbolErrorCount, ErroredBlockCount, and FCSErrorCount, they are defined in IEEE 802.3-2008 and are per LLD. They are expected to come from LLD. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- include/scsi/libfc.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/scsi/libfc.h') diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 2936fbae41e..b97be2903cb 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -231,6 +231,8 @@ struct fc_rport_priv { * @ControlRequests: Number of control requests * @InputMegabytes: Number of received megabytes * @OutputMegabytes: Number of transmitted megabytes + * @VLinkFailureCount: Number of virtual link failures + * @MissDiscAdvCount: Number of missing FIP discovery advertisement */ struct fcoe_dev_stats { u64 SecondsSinceLastReset; @@ -249,6 +251,8 @@ struct fcoe_dev_stats { u64 ControlRequests; u64 InputMegabytes; u64 OutputMegabytes; + u64 VLinkFailureCount; + u64 MissDiscAdvCount; }; /** -- cgit v1.2.3-70-g09d2 From b84056bf68404a5fe06b452ea9790b9927e793a6 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 20 Nov 2009 14:55:19 -0800 Subject: [SCSI] fcoe, libfc: add get_lesb() to allow LLD to fill the link error status block (LESB) Add a member function pointer as get_lesb to libfc_function_template so LLD can fill the LESB based on its own statistics. For fcoe, it fills the LESB as a fcoe_fc_els_lesb struct according to FC-BB-5. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 34 ++++++++++++++++++++++++++++++++++ include/scsi/libfc.h | 6 ++++++ 2 files changed, 40 insertions(+) (limited to 'include/scsi/libfc.h') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 32298ed6061..a30ffaa1222 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -111,6 +111,8 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *, void *, u32 timeout); static void fcoe_recv_frame(struct sk_buff *skb); +static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *); + module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); __MODULE_PARM_TYPE(create, "string"); MODULE_PARM_DESC(create, "Create fcoe fcoe using net device passed in."); @@ -141,6 +143,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { .ddp_setup = fcoe_ddp_setup, .ddp_done = fcoe_ddp_done, .elsct_send = fcoe_elsct_send, + .get_lesb = fcoe_get_lesb, }; struct fc_function_template fcoe_transport_function = { @@ -2455,3 +2458,34 @@ static void fcoe_set_vport_symbolic_name(struct fc_vport *vport) lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RSPN_ID, NULL, NULL, 3 * lport->r_a_tov); } + +/** + * fcoe_get_lesb() - Fill the FCoE Link Error Status Block + * @lport: the local port + * @fc_lesb: the link error status block + */ +static void fcoe_get_lesb(struct fc_lport *lport, + struct fc_els_lesb *fc_lesb) +{ + unsigned int cpu; + u32 lfc, vlfc, mdac; + struct fcoe_dev_stats *devst; + struct fcoe_fc_els_lesb *lesb; + struct net_device *netdev = fcoe_netdev(lport); + + lfc = 0; + vlfc = 0; + mdac = 0; + lesb = (struct fcoe_fc_els_lesb *)fc_lesb; + memset(lesb, 0, sizeof(*lesb)); + for_each_possible_cpu(cpu) { + devst = per_cpu_ptr(lport->dev_stats, cpu); + lfc += devst->LinkFailureCount; + vlfc += devst->VLinkFailureCount; + mdac += devst->MissDiscAdvCount; + } + lesb->lesb_link_fail = htonl(lfc); + lesb->lesb_vlink_fail = htonl(vlfc); + lesb->lesb_miss_fka = htonl(mdac); + lesb->lesb_fcs_error = htonl(dev_get_stats(netdev)->rx_crc_errors); +} diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index b97be2903cb..4b912eee33e 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -510,6 +510,12 @@ struct libfc_function_template { * STATUS: OPTIONAL */ int (*ddp_done)(struct fc_lport *, u16); + /* + * Allow LLD to fill its own Link Error Status Block + * + * STATUS: OPTIONAL + */ + void (*get_lesb)(struct fc_lport *, struct fc_els_lesb *lesb); /* * Send a frame using an existing sequence and exchange. * -- cgit v1.2.3-70-g09d2