Commit 2a9bf3d0 authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[SCSI] lpfc 8.3.13: Add TX Queue Support for SLI4 ELS commands.

parent 98fc5dd9
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
 *******************************************************************/

#include <scsi/scsi_host.h>

struct lpfc_sli2_slim;

#define LPFC_PCI_DEV_LP		0x1
@@ -376,6 +375,7 @@ struct lpfc_vport {
#define WORKER_FABRIC_BLOCK_TMO        0x400	/* hba: fabric block timeout */
#define WORKER_RAMP_DOWN_QUEUE         0x800	/* hba: Decrease Q depth */
#define WORKER_RAMP_UP_QUEUE           0x1000	/* hba: Increase Q depth */
#define WORKER_SERVICE_TXQ             0x2000	/* hba: IOCBs on the txq */

	struct timer_list fc_fdmitmo;
	struct timer_list els_tmofunc;
@@ -624,6 +624,7 @@ struct lpfc_hba {
	uint32_t cfg_hostmem_hgp;
	uint32_t cfg_log_verbose;
	uint32_t cfg_aer_support;
	uint32_t cfg_iocb_cnt;
	uint32_t cfg_suppress_link_up;
#define LPFC_INITIALIZE_LINK              0	/* do normal init_link mbox */
#define LPFC_DELAY_INIT_LINK              1	/* layered driver hold off */
@@ -812,6 +813,8 @@ struct lpfc_hba {

	uint8_t menlo_flag;	/* menlo generic flags */
#define HBA_MENLO_SUPPORT	0x1 /* HBA supports menlo commands */
	uint32_t iocb_cnt;
	uint32_t iocb_max;
};

static inline struct Scsi_Host *
+58 −0
Original line number Diff line number Diff line
@@ -1949,6 +1949,59 @@ static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
LPFC_ATTR_R(suppress_link_up, LPFC_INITIALIZE_LINK, LPFC_INITIALIZE_LINK,
		LPFC_DELAY_INIT_LINK_INDEFINITELY,
		"Suppress Link Up at initialization");
/*
# lpfc_cnt: Number of IOCBs allocated for ELS, CT, and ABTS
#       1 - (1024)
#       2 - (2048)
#       3 - (3072)
#       4 - (4096)
#       5 - (5120)
*/
static ssize_t
lpfc_iocb_hw_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(dev);
	struct lpfc_hba   *phba = ((struct lpfc_vport *) shost->hostdata)->phba;

	return snprintf(buf, PAGE_SIZE, "%d\n", phba->iocb_max);
}

static DEVICE_ATTR(iocb_hw, S_IRUGO,
			 lpfc_iocb_hw_show, NULL);
static ssize_t
lpfc_txq_hw_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(dev);
	struct lpfc_hba   *phba = ((struct lpfc_vport *) shost->hostdata)->phba;

	return snprintf(buf, PAGE_SIZE, "%d\n",
		phba->sli.ring[LPFC_ELS_RING].txq_max);
}

static DEVICE_ATTR(txq_hw, S_IRUGO,
			 lpfc_txq_hw_show, NULL);
static ssize_t
lpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr,
 char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(dev);
	struct lpfc_hba   *phba = ((struct lpfc_vport *) shost->hostdata)->phba;

	return snprintf(buf, PAGE_SIZE, "%d\n",
		phba->sli.ring[LPFC_ELS_RING].txcmplq_max);
}

static DEVICE_ATTR(txcmplq_hw, S_IRUGO,
			 lpfc_txcmplq_hw_show, NULL);

int lpfc_iocb_cnt = 2;
module_param(lpfc_iocb_cnt, int, 1);
MODULE_PARM_DESC(lpfc_iocb_cnt,
	"Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs");
lpfc_param_show(iocb_cnt);
lpfc_param_init(iocb_cnt, 2, 1, 5);
static DEVICE_ATTR(lpfc_iocb_cnt, S_IRUGO,
			 lpfc_iocb_cnt_show, NULL);

/*
# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
@@ -3334,6 +3387,10 @@ struct device_attribute *lpfc_hba_attrs[] = {
	&dev_attr_lpfc_aer_support,
	&dev_attr_lpfc_aer_state_cleanup,
	&dev_attr_lpfc_suppress_link_up,
	&dev_attr_lpfc_iocb_cnt,
	&dev_attr_iocb_hw,
	&dev_attr_txq_hw,
	&dev_attr_txcmplq_hw,
	NULL,
};

@@ -4521,6 +4578,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
	lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
	lpfc_aer_support_init(phba, lpfc_aer_support);
	lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
	lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
	return;
}

+9 −0
Original line number Diff line number Diff line
@@ -377,6 +377,11 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)

	if (rc == IOCB_SUCCESS)
		return 0; /* done for now */
	else if (rc == IOCB_BUSY)
		rc = EAGAIN;
	else
		rc = EIO;


	/* iocb failed so cleanup */
	pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
@@ -625,6 +630,10 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
	lpfc_nlp_put(ndlp);
	if (rc == IOCB_SUCCESS)
		return 0; /* done for now */
	else if (rc == IOCB_BUSY)
		rc = EAGAIN;
	else
		rc = EIO;

	pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
		     job->request_payload.sg_cnt, DMA_TO_DEVICE);
+9 −0
Original line number Diff line number Diff line
@@ -403,3 +403,12 @@ int lpfc_bsg_request(struct fc_bsg_job *);
int lpfc_bsg_timeout(struct fc_bsg_job *);
int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
			     struct lpfc_iocbq *);
void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *,
	struct lpfc_iocbq *);
struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *,
	struct lpfc_sli_ring *);
int __lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t,
	struct lpfc_iocbq *, uint32_t);
uint32_t lpfc_drain_txq(struct lpfc_hba *);

+28 −8
Original line number Diff line number Diff line
@@ -1472,7 +1472,11 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
			}
			goto out;
		}
		/* PLOGI failed */
		/* PLOGI failed Don't print the vport to vport rjts */
		if (irsp->ulpStatus != IOSTAT_LS_RJT ||
			(((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) &&
			((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) ||
			(phba)->pport->cfg_log_verbose & LOG_ELS)
			lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
				 "2753 PLOGI failure DID:%06X Status:x%x/x%x\n",
				 ndlp->nlp_DID, irsp->ulpStatus,
@@ -5144,6 +5148,7 @@ lpfc_els_timeout(unsigned long ptr)
	return;
}


/**
 * lpfc_els_timeout_handler - Process an els timeout event
 * @vport: pointer to a virtual N_Port data structure.
@@ -5164,13 +5169,19 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
	uint32_t els_command = 0;
	uint32_t timeout;
	uint32_t remote_ID = 0xffffffff;
	LIST_HEAD(txcmplq_completions);
	LIST_HEAD(abort_list);


	spin_lock_irq(&phba->hbalock);
	timeout = (uint32_t)(phba->fc_ratov << 1);

	pring = &phba->sli.ring[LPFC_ELS_RING];

	list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
	spin_lock_irq(&phba->hbalock);
	list_splice_init(&pring->txcmplq, &txcmplq_completions);
	spin_unlock_irq(&phba->hbalock);

	list_for_each_entry_safe(piocb, tmp_iocb, &txcmplq_completions, list) {
		cmd = &piocb->iocb;

		if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 ||
@@ -5207,13 +5218,22 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
			if (ndlp && NLP_CHK_NODE_ACT(ndlp))
				remote_ID = ndlp->nlp_DID;
		}
		list_add_tail(&piocb->dlist, &abort_list);
	}
	spin_lock_irq(&phba->hbalock);
	list_splice(&txcmplq_completions, &pring->txcmplq);
	spin_unlock_irq(&phba->hbalock);

	list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) {
		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
			 "0127 ELS timeout Data: x%x x%x x%x "
			 "x%x\n", els_command,
			 remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
		spin_lock_irq(&phba->hbalock);
		list_del_init(&piocb->dlist);
		lpfc_sli_issue_abort_iotag(phba, pring, piocb);
	}
		spin_unlock_irq(&phba->hbalock);
	}

	if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
		mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
Loading