aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_init.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2014-02-20 09:56:45 -0500
committerJames Bottomley <JBottomley@Parallels.com>2014-03-15 10:18:56 -0700
commit1ba981fd3ad1f91b8bb205ce6aac6aad45f2fa7a (patch)
treec5638d855f177a4be300a2df71d8d621a2cfc0ca /drivers/scsi/lpfc/lpfc_init.c
parent[SCSI] lpfc 8.3.45: Added dport mailbox pass through support. (diff)
downloadlinux-dev-1ba981fd3ad1f91b8bb205ce6aac6aad45f2fa7a.tar.xz
linux-dev-1ba981fd3ad1f91b8bb205ce6aac6aad45f2fa7a.zip
[SCSI] lpfc 8.3.45: Incorporated support of a low-latency io path
Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c241
1 files changed, 235 insertions, 6 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index aa29ea099188..157ad1ceceae 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -80,6 +80,7 @@ static void lpfc_sli4_cq_event_pool_destroy(struct lpfc_hba *);
static void lpfc_sli4_cq_event_release_all(struct lpfc_hba *);
static void lpfc_sli4_disable_intr(struct lpfc_hba *);
static uint32_t lpfc_sli4_enable_intr(struct lpfc_hba *, uint32_t);
+static void lpfc_sli4_oas_verify(struct lpfc_hba *phba);
static struct scsi_transport_template *lpfc_transport_template = NULL;
static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
@@ -4856,6 +4857,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0};
struct lpfc_mqe *mqe;
int longs;
+ int fof_vectors = 0;
/* Get all the module params for configuring this host */
lpfc_get_cfgparam(phba);
@@ -5121,6 +5123,12 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
}
}
mempool_free(mboxq, phba->mbox_mem_pool);
+
+ /* Verify OAS is supported */
+ lpfc_sli4_oas_verify(phba);
+ if (phba->cfg_fof)
+ fof_vectors = 1;
+
/* Verify all the SLI4 queues */
rc = lpfc_sli4_queue_verify(phba);
if (rc)
@@ -5162,7 +5170,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
phba->sli4_hba.fcp_eq_hdl =
kzalloc((sizeof(struct lpfc_fcp_eq_hdl) *
- phba->cfg_fcp_io_channel), GFP_KERNEL);
+ (fof_vectors + phba->cfg_fcp_io_channel)),
+ GFP_KERNEL);
if (!phba->sli4_hba.fcp_eq_hdl) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2572 Failed allocate memory for "
@@ -5172,7 +5181,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
}
phba->sli4_hba.msix_entries = kzalloc((sizeof(struct msix_entry) *
- phba->cfg_fcp_io_channel), GFP_KERNEL);
+ (fof_vectors +
+ phba->cfg_fcp_io_channel)), GFP_KERNEL);
if (!phba->sli4_hba.msix_entries) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2573 Failed allocate memory for msi-x "
@@ -5393,6 +5403,10 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
/* Initialize FCF connection rec list */
INIT_LIST_HEAD(&phba->fcf_conn_rec_list);
+ /* Initialize OAS configuration list */
+ spin_lock_init(&phba->devicelock);
+ INIT_LIST_HEAD(&phba->luns);
+
return 0;
}
@@ -6819,6 +6833,7 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
int cfg_fcp_io_channel;
uint32_t cpu;
uint32_t i = 0;
+ int fof_vectors = phba->cfg_fof ? 1 : 0;
/*
* Sanity check for configured queue parameters against the run-time
@@ -6845,7 +6860,7 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
cfg_fcp_io_channel = i;
}
- if (cfg_fcp_io_channel >
+ if (cfg_fcp_io_channel + fof_vectors >
phba->sli4_hba.max_cfg_param.max_eq) {
if (phba->sli4_hba.max_cfg_param.max_eq <
LPFC_FCP_IO_CHAN_MIN) {
@@ -6862,7 +6877,8 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
"available EQs: from %d to %d\n",
cfg_fcp_io_channel,
phba->sli4_hba.max_cfg_param.max_eq);
- cfg_fcp_io_channel = phba->sli4_hba.max_cfg_param.max_eq;
+ cfg_fcp_io_channel = phba->sli4_hba.max_cfg_param.max_eq -
+ fof_vectors;
}
/* The actual number of FCP event queues adopted */
@@ -7073,6 +7089,9 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
}
phba->sli4_hba.dat_rq = qdesc;
+ /* Create the Queues needed for Flash Optimized Fabric operations */
+ if (phba->cfg_fof)
+ lpfc_fof_queue_create(phba);
return 0;
out_error:
@@ -7097,6 +7116,9 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
{
int idx;
+ if (phba->cfg_fof)
+ lpfc_fof_queue_destroy(phba);
+
if (phba->sli4_hba.hba_eq != NULL) {
/* Release HBA event queue */
for (idx = 0; idx < phba->cfg_fcp_io_channel; idx++) {
@@ -7481,8 +7503,20 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
phba->sli4_hba.hdr_rq->queue_id,
phba->sli4_hba.dat_rq->queue_id,
phba->sli4_hba.els_cq->queue_id);
+
+ if (phba->cfg_fof) {
+ rc = lpfc_fof_queue_setup(phba);
+ if (rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0549 Failed setup of FOF Queues: "
+ "rc = 0x%x\n", rc);
+ goto out_destroy_els_rq;
+ }
+ }
return 0;
+out_destroy_els_rq:
+ lpfc_rq_destroy(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq);
out_destroy_els_wq:
lpfc_wq_destroy(phba, phba->sli4_hba.els_wq);
out_destroy_mbx_wq:
@@ -7521,6 +7555,9 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba)
{
int fcp_qidx;
+ /* Unset the queues created for Flash Optimized Fabric operations */
+ if (phba->cfg_fof)
+ lpfc_fof_queue_destroy(phba);
/* Unset mailbox command work queue */
lpfc_mq_destroy(phba, phba->sli4_hba.mbx_wq);
/* Unset ELS work queue */
@@ -8638,6 +8675,10 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
/* Configure MSI-X capability structure */
vectors = phba->cfg_fcp_io_channel;
+ if (phba->cfg_fof) {
+ phba->sli4_hba.msix_entries[index].entry = index;
+ vectors++;
+ }
enable_msix_vectors:
rc = pci_enable_msix(phba->pcidev, phba->sli4_hba.msix_entries,
vectors);
@@ -8667,7 +8708,15 @@ enable_msix_vectors:
phba->sli4_hba.fcp_eq_hdl[index].idx = index;
phba->sli4_hba.fcp_eq_hdl[index].phba = phba;
atomic_set(&phba->sli4_hba.fcp_eq_hdl[index].fcp_eq_in_use, 1);
- rc = request_irq(phba->sli4_hba.msix_entries[index].vector,
+ if (phba->cfg_fof && (index == (vectors - 1)))
+ rc = request_irq(
+ phba->sli4_hba.msix_entries[index].vector,
+ &lpfc_sli4_fof_intr_handler, IRQF_SHARED,
+ (char *)&phba->sli4_hba.handler_name[index],
+ &phba->sli4_hba.fcp_eq_hdl[index]);
+ else
+ rc = request_irq(
+ phba->sli4_hba.msix_entries[index].vector,
&lpfc_sli4_hba_intr_handler, IRQF_SHARED,
(char *)&phba->sli4_hba.handler_name[index],
&phba->sli4_hba.fcp_eq_hdl[index]);
@@ -8679,6 +8728,9 @@ enable_msix_vectors:
}
}
+ if (phba->cfg_fof)
+ vectors--;
+
if (vectors != phba->cfg_fcp_io_channel) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3238 Reducing IO channels to match number of "
@@ -8724,7 +8776,10 @@ lpfc_sli4_disable_msix(struct lpfc_hba *phba)
free_irq(phba->sli4_hba.msix_entries[index].vector,
&phba->sli4_hba.fcp_eq_hdl[index]);
}
-
+ if (phba->cfg_fof) {
+ free_irq(phba->sli4_hba.msix_entries[index].vector,
+ &phba->sli4_hba.fcp_eq_hdl[index]);
+ }
/* Disable MSI-X */
pci_disable_msix(phba->pcidev);
@@ -8774,6 +8829,10 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba)
phba->sli4_hba.fcp_eq_hdl[index].phba = phba;
}
+ if (phba->cfg_fof) {
+ phba->sli4_hba.fcp_eq_hdl[index].idx = index;
+ phba->sli4_hba.fcp_eq_hdl[index].phba = phba;
+ }
return 0;
}
@@ -8856,6 +8915,12 @@ lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode)
atomic_set(&phba->sli4_hba.fcp_eq_hdl[index].
fcp_eq_in_use, 1);
}
+ if (phba->cfg_fof) {
+ phba->sli4_hba.fcp_eq_hdl[index].idx = index;
+ phba->sli4_hba.fcp_eq_hdl[index].phba = phba;
+ atomic_set(&phba->sli4_hba.fcp_eq_hdl[index].
+ fcp_eq_in_use, 1);
+ }
}
}
return intr_mode;
@@ -9166,6 +9231,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
phba->sli3_options &= ~LPFC_SLI4_PHWQ_ENABLED;
sli4_params->sge_supp_len = mbx_sli4_parameters->sge_supp_len;
sli4_params->loopbk_scope = bf_get(loopbk_scope, mbx_sli4_parameters);
+ sli4_params->oas_supported = bf_get(cfg_oas, mbx_sli4_parameters);
sli4_params->cqv = bf_get(cfg_cqv, mbx_sli4_parameters);
sli4_params->mqv = bf_get(cfg_mqv, mbx_sli4_parameters);
sli4_params->wqv = bf_get(cfg_wqv, mbx_sli4_parameters);
@@ -10799,6 +10865,169 @@ lpfc_io_resume(struct pci_dev *pdev)
return;
}
+/**
+ * lpfc_sli4_oas_verify - Verify OAS is supported by this adapter
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine checks to see if OAS is supported for this adapter. If
+ * supported, the configure Flash Optimized Fabric flag is set. Otherwise,
+ * the enable oas flag is cleared and the pool created for OAS device data
+ * is destroyed.
+ *
+ **/
+void
+lpfc_sli4_oas_verify(struct lpfc_hba *phba)
+{
+
+ if (!phba->cfg_EnableXLane)
+ return;
+
+ if (phba->sli4_hba.pc_sli4_params.oas_supported) {
+ phba->cfg_fof = 1;
+ } else {
+ phba->cfg_EnableXLane = 0;
+ if (phba->device_data_mem_pool)
+ mempool_destroy(phba->device_data_mem_pool);
+ phba->device_data_mem_pool = NULL;
+ }
+
+ return;
+}
+
+/**
+ * lpfc_fof_queue_setup - Set up all the fof queues
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to set up all the fof queues for the FC HBA
+ * operation.
+ *
+ * Return codes
+ * 0 - successful
+ * -ENOMEM - No available memory
+ **/
+int
+lpfc_fof_queue_setup(struct lpfc_hba *phba)
+{
+ struct lpfc_sli *psli = &phba->sli;
+ int rc;
+
+ rc = lpfc_eq_create(phba, phba->sli4_hba.fof_eq, LPFC_MAX_IMAX);
+ if (rc)
+ return -ENOMEM;
+
+ if (phba->cfg_EnableXLane) {
+
+ rc = lpfc_cq_create(phba, phba->sli4_hba.oas_cq,
+ phba->sli4_hba.fof_eq, LPFC_WCQ, LPFC_FCP);
+ if (rc)
+ goto out_oas_cq;
+
+ rc = lpfc_wq_create(phba, phba->sli4_hba.oas_wq,
+ phba->sli4_hba.oas_cq, LPFC_FCP);
+ if (rc)
+ goto out_oas_wq;
+
+ phba->sli4_hba.oas_cq->pring = &psli->ring[LPFC_FCP_OAS_RING];
+ phba->sli4_hba.oas_ring = &psli->ring[LPFC_FCP_OAS_RING];
+ }
+
+ return 0;
+
+out_oas_wq:
+ if (phba->cfg_EnableXLane)
+ lpfc_cq_destroy(phba, phba->sli4_hba.oas_cq);
+out_oas_cq:
+ lpfc_eq_destroy(phba, phba->sli4_hba.fof_eq);
+ return rc;
+
+}
+
+/**
+ * lpfc_fof_queue_create - Create all the fof queues
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to allocate all the fof queues for the FC HBA
+ * operation. For each SLI4 queue type, the parameters such as queue entry
+ * count (queue depth) shall be taken from the module parameter. For now,
+ * we just use some constant number as place holder.
+ *
+ * Return codes
+ * 0 - successful
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
+ **/
+int
+lpfc_fof_queue_create(struct lpfc_hba *phba)
+{
+ struct lpfc_queue *qdesc;
+
+ /* Create FOF EQ */
+ qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.eq_esize,
+ phba->sli4_hba.eq_ecount);
+ if (!qdesc)
+ goto out_error;
+
+ phba->sli4_hba.fof_eq = qdesc;
+
+ if (phba->cfg_EnableXLane) {
+
+ /* Create OAS CQ */
+ qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize,
+ phba->sli4_hba.cq_ecount);
+ if (!qdesc)
+ goto out_error;
+
+ phba->sli4_hba.oas_cq = qdesc;
+
+ /* Create OAS WQ */
+ qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.wq_esize,
+ phba->sli4_hba.wq_ecount);
+ if (!qdesc)
+ goto out_error;
+
+ phba->sli4_hba.oas_wq = qdesc;
+
+ }
+ return 0;
+
+out_error:
+ lpfc_fof_queue_destroy(phba);
+ return -ENOMEM;
+}
+
+/**
+ * lpfc_fof_queue_destroy - Destroy all the fof queues
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to release all the SLI4 queues with the FC HBA
+ * operation.
+ *
+ * Return codes
+ * 0 - successful
+ **/
+int
+lpfc_fof_queue_destroy(struct lpfc_hba *phba)
+{
+ /* Release FOF Event queue */
+ if (phba->sli4_hba.fof_eq != NULL) {
+ lpfc_sli4_queue_free(phba->sli4_hba.fof_eq);
+ phba->sli4_hba.fof_eq = NULL;
+ }
+
+ /* Release OAS Completion queue */
+ if (phba->sli4_hba.oas_cq != NULL) {
+ lpfc_sli4_queue_free(phba->sli4_hba.oas_cq);
+ phba->sli4_hba.oas_cq = NULL;
+ }
+
+ /* Release OAS Work queue */
+ if (phba->sli4_hba.oas_wq != NULL) {
+ lpfc_sli4_queue_free(phba->sli4_hba.oas_wq);
+ phba->sli4_hba.oas_wq = NULL;
+ }
+ return 0;
+}
+
static struct pci_device_id lpfc_id_table[] = {
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
PCI_ANY_ID, PCI_ANY_ID, },