Commit 45ed1190 authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.3.5: fix fcp command polling, add FIP mode, performance...

[SCSI] lpfc 8.3.5: fix fcp command polling, add FIP mode, performance optimisations and devloss timout fixes

This patch includes the following changes:
- Fixed Panic/Hang when using polling mode for fcp commands
- Added support for Read_rev mbox bits indicating FIP mode of HBA
- Optimize performance of slow-path handling of els responses
- Add code to cleanup orphaned unsolicited receive sequences
- Fixed Devloss timeout when multiple initiators are in same zone
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 0d878419
......@@ -110,6 +110,7 @@ struct hbq_dmabuf {
uint32_t size;
uint32_t tag;
struct lpfc_cq_event cq_event;
unsigned long time_stamp;
};
/* Priority bit. Set value to exceed low water mark in lpfc_mem. */
......@@ -405,6 +406,7 @@ struct lpfc_vport {
uint8_t stat_data_enabled;
uint8_t stat_data_blocked;
struct list_head rcv_buffer_list;
unsigned long rcv_buffer_time_stamp;
uint32_t vport_flag;
#define STATIC_VPORT 1
};
......@@ -527,14 +529,16 @@ struct lpfc_hba {
#define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */
#define DEFER_ERATT 0x2 /* Deferred error attention in progress */
#define HBA_FCOE_SUPPORT 0x4 /* HBA function supports FCOE */
#define HBA_RECEIVE_BUFFER 0x8 /* Rcv buffer posted to worker thread */
#define HBA_SP_QUEUE_EVT 0x8 /* Slow-path qevt posted to worker thread*/
#define HBA_POST_RECEIVE_BUFFER 0x10 /* Rcv buffers need to be posted */
#define FCP_XRI_ABORT_EVENT 0x20
#define ELS_XRI_ABORT_EVENT 0x40
#define ASYNC_EVENT 0x80
#define LINK_DISABLED 0x100 /* Link disabled by user */
#define FCF_DISC_INPROGRESS 0x200 /* FCF discovery in progress */
#define HBA_AER_ENABLED 0x800 /* AER enabled with HBA */
#define HBA_FIP_SUPPORT 0x400 /* FIP support in HBA */
#define HBA_AER_ENABLED 0x800 /* AER enabled with HBA */
uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
struct lpfc_dmabuf slim2p;
MAILBOX_t *mbox;
......@@ -606,7 +610,6 @@ struct lpfc_hba {
uint32_t cfg_enable_hba_reset;
uint32_t cfg_enable_hba_heartbeat;
uint32_t cfg_enable_bg;
uint32_t cfg_enable_fip;
uint32_t cfg_log_verbose;
uint32_t cfg_aer_support;
......
......@@ -100,6 +100,28 @@ lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
}
/**
* lpfc_enable_fip_show - Return the fip mode of the HBA
* @dev: class unused variable.
* @attr: device attribute, not used.
* @buf: on return contains the module description text.
*
* Returns: size of formatted string.
**/
static ssize_t
lpfc_enable_fip_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
if (phba->hba_flag & HBA_FIP_SUPPORT)
return snprintf(buf, PAGE_SIZE, "1\n");
else
return snprintf(buf, PAGE_SIZE, "0\n");
}
static ssize_t
lpfc_bg_info_show(struct device *dev, struct device_attribute *attr,
char *buf)
......@@ -1134,6 +1156,9 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,
if ((val & 0x3) != val)
return -EINVAL;
if (phba->sli_rev == LPFC_SLI_REV4)
val = 0;
spin_lock_irq(&phba->hbalock);
old_val = phba->cfg_poll;
......@@ -1597,6 +1622,7 @@ static DEVICE_ATTR(num_discovered_ports, S_IRUGO,
static DEVICE_ATTR(menlo_mgmt_mode, S_IRUGO, lpfc_mlomgmt_show, NULL);
static DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);
static DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show, NULL);
static DEVICE_ATTR(lpfc_enable_fip, S_IRUGO, lpfc_enable_fip_show, NULL);
static DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
lpfc_board_mode_show, lpfc_board_mode_store);
static DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
......@@ -3127,15 +3153,6 @@ LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat.");
*/
LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support");
/*
# lpfc_enable_fip: When set, FIP is required to start discovery. If not
# set, the driver will add an FCF record manually if the port has no
# FCF records available and start discovery.
# Value range is [0,1]. Default value is 1 (enabled)
*/
LPFC_ATTR_RW(enable_fip, 0, 0, 1, "Enable FIP Discovery");
/*
# lpfc_prot_mask: i
# - Bit mask of host protection capabilities used to register with the
......@@ -3194,6 +3211,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_num_discovered_ports,
&dev_attr_menlo_mgmt_mode,
&dev_attr_lpfc_drvr_version,
&dev_attr_lpfc_enable_fip,
&dev_attr_lpfc_temp_sensor,
&dev_attr_lpfc_log_verbose,
&dev_attr_lpfc_lun_queue_depth,
......@@ -3201,7 +3219,6 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_peer_port_login,
&dev_attr_lpfc_nodev_tmo,
&dev_attr_lpfc_devloss_tmo,
&dev_attr_lpfc_enable_fip,
&dev_attr_lpfc_fcp_class,
&dev_attr_lpfc_use_adisc,
&dev_attr_lpfc_ack0,
......@@ -3256,7 +3273,6 @@ struct device_attribute *lpfc_vport_attrs[] = {
&dev_attr_lpfc_lun_queue_depth,
&dev_attr_lpfc_nodev_tmo,
&dev_attr_lpfc_devloss_tmo,
&dev_attr_lpfc_enable_fip,
&dev_attr_lpfc_hba_queue_depth,
&dev_attr_lpfc_peer_port_login,
&dev_attr_lpfc_restrict_login,
......@@ -4412,13 +4428,15 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_enable_hba_reset_init(phba, lpfc_enable_hba_reset);
lpfc_enable_hba_heartbeat_init(phba, lpfc_enable_hba_heartbeat);
lpfc_enable_bg_init(phba, lpfc_enable_bg);
if (phba->sli_rev == LPFC_SLI_REV4)
phba->cfg_poll = 0;
else
phba->cfg_poll = lpfc_poll;
phba->cfg_soft_wwnn = 0L;
phba->cfg_soft_wwpn = 0L;
lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt);
lpfc_prot_sg_seg_cnt_init(phba, lpfc_prot_sg_seg_cnt);
lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
lpfc_enable_fip_init(phba, lpfc_enable_fip);
lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
lpfc_aer_support_init(phba, lpfc_aer_support);
......
......@@ -49,6 +49,8 @@ void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *);
struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
void lpfc_cleanup_rcv_buffers(struct lpfc_vport *);
void lpfc_rcv_seq_check_edtov(struct lpfc_vport *);
void lpfc_cleanup_rpis(struct lpfc_vport *, int);
int lpfc_linkdown(struct lpfc_hba *);
void lpfc_linkdown_port(struct lpfc_vport *);
......@@ -214,7 +216,10 @@ void lpfc_stop_vport_timers(struct lpfc_vport *);
void lpfc_poll_timeout(unsigned long ptr);
void lpfc_poll_start_timer(struct lpfc_hba *);
void lpfc_poll_eratt(unsigned long);
void lpfc_sli_poll_fcp_ring(struct lpfc_hba *);
int
lpfc_sli_handle_fast_ring_event(struct lpfc_hba *,
struct lpfc_sli_ring *, uint32_t);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
......
......@@ -173,7 +173,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
* in FIP mode send FLOGI, FDISC and LOGO as FIP frames.
*/
if ((did == Fabric_DID) &&
bf_get(lpfc_fip_flag, &phba->sli4_hba.sli4_flags) &&
(phba->hba_flag & HBA_FIP_SUPPORT) &&
((elscmd == ELS_CMD_FLOGI) ||
(elscmd == ELS_CMD_FDISC) ||
(elscmd == ELS_CMD_LOGO)))
......
......@@ -568,7 +568,7 @@ lpfc_work_done(struct lpfc_hba *phba)
status >>= (4*LPFC_ELS_RING);
if ((status & HA_RXMASK) ||
(pring->flag & LPFC_DEFERRED_RING_EVENT) ||
(phba->hba_flag & HBA_RECEIVE_BUFFER)) {
(phba->hba_flag & HBA_SP_QUEUE_EVT)) {
if (pring->flag & LPFC_STOP_IOCB_EVENT) {
pring->flag |= LPFC_DEFERRED_RING_EVENT;
/* Set the lpfc data pending flag */
......@@ -706,6 +706,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
void
lpfc_port_link_failure(struct lpfc_vport *vport)
{
/* Cleanup any outstanding received buffers */
lpfc_cleanup_rcv_buffers(vport);
/* Cleanup any outstanding RSCN activity */
lpfc_els_flush_rscn(vport);
......@@ -1282,7 +1285,7 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,
!bf_get(lpfc_fcf_record_fcf_valid, new_fcf_record))
return 0;
if (!phba->cfg_enable_fip) {
if (!(phba->hba_flag & HBA_FIP_SUPPORT)) {
*boot_flag = 0;
*addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov,
new_fcf_record);
......@@ -1997,7 +2000,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
* is phase 1 implementation that support FCF index 0 and driver
* defaults.
*/
if (phba->cfg_enable_fip == 0) {
if (!(phba->hba_flag & HBA_FIP_SUPPORT)) {
fcf_record = kzalloc(sizeof(struct fcf_record),
GFP_KERNEL);
if (unlikely(!fcf_record)) {
......@@ -4442,7 +4445,7 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba)
*/
if (!(phba->hba_flag & HBA_FCOE_SUPPORT) ||
!(phba->fcf.fcf_flag & FCF_REGISTERED) ||
(phba->cfg_enable_fip == 0)) {
(!(phba->hba_flag & HBA_FIP_SUPPORT))) {
spin_unlock_irq(&phba->hbalock);
return;
}
......@@ -4615,14 +4618,6 @@ lpfc_read_fcoe_param(struct lpfc_hba *phba,
(fcoe_param_hdr->length != FCOE_PARAM_LENGTH))
return;
if (bf_get(lpfc_fip_param_hdr_fipp_mode, fcoe_param_hdr) ==
FIPP_MODE_ON)
phba->cfg_enable_fip = 1;
if (bf_get(lpfc_fip_param_hdr_fipp_mode, fcoe_param_hdr) ==
FIPP_MODE_OFF)
phba->cfg_enable_fip = 0;
if (fcoe_param_hdr->parm_flags & FIPP_VLAN_VALID) {
phba->valid_vlan = 1;
phba->vlan_id = le16_to_cpu(fcoe_param->vlan_tag) &
......
......@@ -1601,6 +1601,11 @@ struct lpfc_mbx_read_rev {
#define lpfc_mbx_rd_rev_fcoe_SHIFT 20
#define lpfc_mbx_rd_rev_fcoe_MASK 0x00000001
#define lpfc_mbx_rd_rev_fcoe_WORD word1
#define lpfc_mbx_rd_rev_cee_ver_SHIFT 21
#define lpfc_mbx_rd_rev_cee_ver_MASK 0x00000003
#define lpfc_mbx_rd_rev_cee_ver_WORD word1
#define LPFC_PREDCBX_CEE_MODE 0
#define LPFC_DCBX_CEE_MODE 1
#define lpfc_mbx_rd_rev_vpd_SHIFT 29
#define lpfc_mbx_rd_rev_vpd_MASK 0x00000001
#define lpfc_mbx_rd_rev_vpd_WORD word1
......
......@@ -853,12 +853,19 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
void
lpfc_hb_timeout_handler(struct lpfc_hba *phba)
{
struct lpfc_vport **vports;
LPFC_MBOXQ_t *pmboxq;
struct lpfc_dmabuf *buf_ptr;
int retval;
int retval, i;
struct lpfc_sli *psli = &phba->sli;
LIST_HEAD(completions);
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++)
lpfc_rcv_seq_check_edtov(vports[i]);
lpfc_destroy_vport_work_array(phba, vports);
if ((phba->link_state == LPFC_HBA_ERROR) ||
(phba->pport->load_flag & FC_UNLOADING) ||
(phba->pport->fc_flag & FC_OFFLINE_MODE))
......@@ -3519,7 +3526,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
/* Driver internel slow-path CQ Event pool */
INIT_LIST_HEAD(&phba->sli4_hba.sp_cqe_event_pool);
/* Response IOCB work queue list */
INIT_LIST_HEAD(&phba->sli4_hba.sp_rspiocb_work_queue);
INIT_LIST_HEAD(&phba->sli4_hba.sp_queue_event);
/* Asynchronous event CQ Event work queue list */
INIT_LIST_HEAD(&phba->sli4_hba.sp_asynce_work_queue);
/* Fast-path XRI aborted CQ Event work queue list */
......
......@@ -1759,11 +1759,6 @@ lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq)
/* Set up host requested features. */
bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1);
if (phba->cfg_enable_fip)
bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 0);
else
bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 1);
/* Enable DIF (block guard) only if configured to do so. */
if (phba->cfg_enable_bg)
bf_set(lpfc_mbx_rq_ftr_rq_dif, &mboxq->u.mqe.un.req_ftrs, 1);
......
......@@ -2773,7 +2773,9 @@ void lpfc_poll_timeout(unsigned long ptr)
struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_poll_fcp_ring (phba);
lpfc_sli_handle_fast_ring_event(phba,
&phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ);
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_poll_rearm_timer(phba);
}
......@@ -2932,7 +2934,11 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
goto out_host_busy_free_buf;
}
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_poll_fcp_ring(phba);
spin_unlock(shost->host_lock);
lpfc_sli_handle_fast_ring_event(phba,
&phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ);
spin_lock(shost->host_lock);
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_poll_rearm_timer(phba);
}
......@@ -3028,7 +3034,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
}
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_sli_poll_fcp_ring (phba);
lpfc_sli_handle_fast_ring_event(phba,
&phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ);
lpfc_cmd->waitq = &waitq;
/* Wait for abort to complete */
......@@ -3546,7 +3553,8 @@ lpfc_slave_configure(struct scsi_device *sdev)
rport->dev_loss_tmo = vport->cfg_devloss_tmo;
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_poll_fcp_ring(phba);
lpfc_sli_handle_fast_ring_event(phba,
&phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ);
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_poll_rearm_timer(phba);
}
......
This diff is collapsed.
......@@ -49,6 +49,7 @@ struct lpfc_iocbq {
struct list_head clist;
uint16_t iotag; /* pre-assigned IO tag */
uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */
struct lpfc_cq_event cq_event;
IOCB_t iocb; /* IOCB cmd */
uint8_t retry; /* retry counter for IOCB cmd - if needed */
......@@ -79,7 +80,6 @@ struct lpfc_iocbq {
struct lpfc_iocbq *);
void (*iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
struct lpfc_iocbq *);
struct lpfc_cq_event cq_event;
};
#define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */
......
......@@ -352,7 +352,7 @@ struct lpfc_sli4_hba {
unsigned long *rpi_bmask;
uint16_t rpi_count;
struct lpfc_sli4_flags sli4_flags;
struct list_head sp_rspiocb_work_queue;
struct list_head sp_queue_event;
struct list_head sp_cqe_event_pool;
struct list_head sp_asynce_work_queue;
struct list_head sp_fcp_xri_aborted_work_queue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment