Commit 2e0fef85 authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc: NPIV: split ports

The driver is reorganized to separate the handling of the adapter from
the handling of the FC port. Adapter handling includes submissions of
command requests, receiving responses, and managing adapter resources.
The FC port includes the discovery engine, login handling, and the
mapping of a Scsi_Host on the "port".  Although not a large functional
change, as it touches core structures and functions, resulting in a
large text delta.
Signed-off-by: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 4c2baaaf
......@@ -19,6 +19,8 @@
* included with this package. *
*******************************************************************/
#include <scsi/scsi_host.h>
struct lpfc_sli2_slim;
......@@ -165,48 +167,143 @@ struct lpfc_sysfs_mbox {
struct lpfcMboxq * mbox;
};
struct lpfc_hba;
enum discovery_state {
LPFC_STATE_UNKNOWN = 0, /* HBA state is unknown */
LPFC_LOCAL_CFG_LINK = 6, /* local NPORT Id configured */
LPFC_FLOGI = 7, /* FLOGI sent to Fabric */
LPFC_FABRIC_CFG_LINK = 8, /* Fabric assigned NPORT Id
* configured */
LPFC_NS_REG = 9, /* Register with NameServer */
LPFC_NS_QRY = 10, /* Query NameServer for NPort ID list */
LPFC_BUILD_DISC_LIST = 11, /* Build ADISC and PLOGI lists for
* device authentication / discovery */
LPFC_DISC_AUTH = 12, /* Processing ADISC list */
LPFC_VPORT_READY = 32,
};
enum hba_state {
LPFC_LINK_UNKNOWN = 0, /* HBA state is unknown */
LPFC_WARM_START = 1, /* HBA state after selective reset */
LPFC_INIT_START = 2, /* Initial state after board reset */
LPFC_INIT_MBX_CMDS = 3, /* Initialize HBA with mbox commands */
LPFC_LINK_DOWN = 4, /* HBA initialized, link is down */
LPFC_LINK_UP = 5, /* Link is up - issue READ_LA */
LPFC_CLEAR_LA = 13, /* authentication cmplt - issue
* CLEAR_LA */
LPFC_HBA_ERROR = -1
};
struct lpfc_vport {
struct list_head listentry;
struct lpfc_hba *phba;
uint8_t port_type;
#define LPFC_PHYSICAL_PORT 1
#define LPFC_NPIV_PORT 2
#define LPFC_FABRIC_PORT 3
enum discovery_state port_state;
uint32_t fc_flag; /* FC flags */
/* Several of these flags are HBA centric and should be moved to
* phba->link_flag (e.g. FC_PTP, FC_PUBLIC_LOOP)
*/
#define FC_PT2PT 0x1 /* pt2pt with no fabric */
#define FC_PT2PT_PLOGI 0x2 /* pt2pt initiate PLOGI */
#define FC_DISC_TMO 0x4 /* Discovery timer running */
#define FC_PUBLIC_LOOP 0x8 /* Public loop */
#define FC_LBIT 0x10 /* LOGIN bit in loopinit set */
#define FC_RSCN_MODE 0x20 /* RSCN cmd rcv'ed */
#define FC_NLP_MORE 0x40 /* More node to process in node tbl */
#define FC_OFFLINE_MODE 0x80 /* Interface is offline for diag */
#define FC_FABRIC 0x100 /* We are fabric attached */
#define FC_ESTABLISH_LINK 0x200 /* Reestablish Link */
#define FC_RSCN_DISCOVERY 0x400 /* Authenticate all devices after RSCN*/
#define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */
#define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
#define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */
#define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */
struct list_head fc_nodes;
/* Keep counters for the number of entries in each list. */
uint16_t fc_plogi_cnt;
uint16_t fc_adisc_cnt;
uint16_t fc_reglogin_cnt;
uint16_t fc_prli_cnt;
uint16_t fc_unmap_cnt;
uint16_t fc_map_cnt;
uint16_t fc_npr_cnt;
uint16_t fc_unused_cnt;
struct serv_parm fc_sparam; /* buffer for our service parameters */
uint32_t fc_myDID; /* fibre channel S_ID */
uint32_t fc_prevDID; /* previous fibre channel S_ID */
int32_t stopped; /* HBA has not been restarted since last ERATT */
uint8_t fc_linkspeed; /* Link speed after last READ_LA */
uint32_t num_disc_nodes; /*in addition to hba_state */
uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */
uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */
struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
struct lpfc_name fc_nodename; /* fc nodename */
struct lpfc_name fc_portname; /* fc portname */
struct lpfc_work_evt disc_timeout_evt;
struct timer_list fc_disctmo; /* Discovery rescue timer */
uint8_t fc_ns_retry; /* retries for fabric nameserver */
uint32_t fc_prli_sent; /* cntr for outstanding PRLIs */
spinlock_t work_port_lock;
uint32_t work_port_events; /* Timeout to be handled */
#define WORKER_DISC_TMO 0x1 /* Discovery timeout */
#define WORKER_ELS_TMO 0x2 /* ELS timeout */
#define WORKER_MBOX_TMO 0x4 /* MBOX timeout */
#define WORKER_FDMI_TMO 0x8 /* FDMI timeout */
struct timer_list fc_fdmitmo;
struct timer_list els_tmofunc;
int unreg_vpi_cmpl;
uint8_t load_flag;
#define FC_LOADING 0x1 /* HBA in process of loading drvr */
#define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */
};
struct lpfc_hba {
struct lpfc_sli sli;
enum hba_state link_state;
uint32_t link_flag; /* link state flags */
#define LS_LOOPBACK_MODE 0x40000 /* NPort is in Loopback mode */
/* This flag is set while issuing */
/* INIT_LINK mailbox command */
#define LS_IGNORE_ERATT 0x80000 /* intr handler should ignore ERATT */
uint32_t pgpOffset; /* PGP offset within host memory */
struct lpfc_sli2_slim *slim2p;
struct lpfc_dmabuf hbqslimp;
dma_addr_t slim2p_mapping;
uint16_t pci_cfg_value;
int32_t hba_state;
#define LPFC_STATE_UNKNOWN 0 /* HBA state is unknown */
#define LPFC_WARM_START 1 /* HBA state after selective reset */
#define LPFC_INIT_START 2 /* Initial state after board reset */
#define LPFC_INIT_MBX_CMDS 3 /* Initialize HBA with mbox commands */
#define LPFC_LINK_DOWN 4 /* HBA initialized, link is down */
#define LPFC_LINK_UP 5 /* Link is up - issue READ_LA */
#define LPFC_LOCAL_CFG_LINK 6 /* local NPORT Id configured */
#define LPFC_FLOGI 7 /* FLOGI sent to Fabric */
#define LPFC_FABRIC_CFG_LINK 8 /* Fabric assigned NPORT Id
configured */
#define LPFC_NS_REG 9 /* Register with NameServer */
#define LPFC_NS_QRY 10 /* Query NameServer for NPort ID list */
#define LPFC_BUILD_DISC_LIST 11 /* Build ADISC and PLOGI lists for
* device authentication / discovery */
#define LPFC_DISC_AUTH 12 /* Processing ADISC list */
#define LPFC_CLEAR_LA 13 /* authentication cmplt - issue
CLEAR_LA */
#define LPFC_HBA_READY 32
#define LPFC_HBA_ERROR -1
int32_t stopped; /* HBA has not been restarted since last ERATT */
uint8_t fc_linkspeed; /* Link speed after last READ_LA */
uint32_t fc_eventTag; /* event tag for link attention */
uint32_t fc_prli_sent; /* cntr for outstanding PRLIs */
uint32_t num_disc_nodes; /*in addition to hba_state */
struct timer_list fc_estabtmo; /* link establishment timer */
struct timer_list fc_disctmo; /* Discovery rescue timer */
struct timer_list fc_fdmitmo; /* fdmi timer */
/* These fields used to be binfo */
struct lpfc_name fc_nodename; /* fc nodename */
struct lpfc_name fc_portname; /* fc portname */
uint32_t fc_pref_DID; /* preferred D_ID */
uint8_t fc_pref_ALPA; /* preferred AL_PA */
uint32_t fc_edtov; /* E_D_TOV timer value */
......@@ -216,61 +313,21 @@ struct lpfc_hba {
uint32_t fc_altov; /* AL_TOV timer value */
uint32_t fc_crtov; /* C_R_TOV timer value */
uint32_t fc_citov; /* C_I_TOV timer value */
uint32_t fc_myDID; /* fibre channel S_ID */
uint32_t fc_prevDID; /* previous fibre channel S_ID */
struct serv_parm fc_sparam; /* buffer for our service parameters */
struct serv_parm fc_fabparam; /* fabric service parameters buffer */
uint8_t alpa_map[128]; /* AL_PA map from READ_LA */
uint8_t fc_ns_retry; /* retries for fabric nameserver */
uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */
uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */
struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
uint32_t lmt;
uint32_t fc_flag; /* FC flags */
#define FC_PT2PT 0x1 /* pt2pt with no fabric */
#define FC_PT2PT_PLOGI 0x2 /* pt2pt initiate PLOGI */
#define FC_DISC_TMO 0x4 /* Discovery timer running */
#define FC_PUBLIC_LOOP 0x8 /* Public loop */
#define FC_LBIT 0x10 /* LOGIN bit in loopinit set */
#define FC_RSCN_MODE 0x20 /* RSCN cmd rcv'ed */
#define FC_NLP_MORE 0x40 /* More node to process in node tbl */
#define FC_OFFLINE_MODE 0x80 /* Interface is offline for diag */
#define FC_FABRIC 0x100 /* We are fabric attached */
#define FC_ESTABLISH_LINK 0x200 /* Reestablish Link */
#define FC_RSCN_DISCOVERY 0x400 /* Authenticate all devices after RSCN*/
#define FC_BLOCK_MGMT_IO 0x800 /* Don't allow mgmt mbx or iocb cmds */
#define FC_LOADING 0x1000 /* HBA in process of loading drvr */
#define FC_UNLOADING 0x2000 /* HBA in process of unloading drvr */
#define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */
#define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
#define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */
#define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */
#define FC_LOOPBACK_MODE 0x40000 /* NPort is in Loopback mode */
/* This flag is set while issuing */
/* INIT_LINK mailbox command */
#define FC_IGNORE_ERATT 0x80000 /* intr handler should ignore ERATT */
uint32_t fc_topology; /* link topology, from LINK INIT */
struct lpfc_stats fc_stat;
struct list_head fc_nodes;
/* Keep counters for the number of entries in each list. */
uint16_t fc_plogi_cnt;
uint16_t fc_adisc_cnt;
uint16_t fc_reglogin_cnt;
uint16_t fc_prli_cnt;
uint16_t fc_unmap_cnt;
uint16_t fc_map_cnt;
uint16_t fc_npr_cnt;
uint16_t fc_unused_cnt;
struct lpfc_nodelist fc_fcpnodev; /* nodelist entry for no device */
uint32_t nport_event_cnt; /* timestamp for nlplist entry */
uint32_t wwnn[2];
uint8_t wwnn[8];
uint8_t wwpn[8];
uint32_t RandomData[7];
uint32_t cfg_log_verbose;
......@@ -304,18 +361,12 @@ struct lpfc_hba {
lpfc_vpd_t vpd; /* vital product data */
struct Scsi_Host *host;
struct pci_dev *pcidev;
struct list_head work_list;
uint32_t work_ha; /* Host Attention Bits for WT */
uint32_t work_ha_mask; /* HA Bits owned by WT */
uint32_t work_hs; /* HS stored in case of ERRAT */
uint32_t work_status[2]; /* Extra status from SLIM */
uint32_t work_hba_events; /* Timeout to be handled */
#define WORKER_DISC_TMO 0x1 /* Discovery timeout */
#define WORKER_ELS_TMO 0x2 /* ELS timeout */
#define WORKER_MBOX_TMO 0x4 /* MBOX timeout */
#define WORKER_FDMI_TMO 0x8 /* FDMI timeout */
wait_queue_head_t *work_wait;
struct task_struct *worker_thread;
......@@ -353,7 +404,6 @@ struct lpfc_hba {
uint8_t soft_wwn_enable;
struct timer_list fcp_poll_timer;
struct timer_list els_tmofunc;
/*
* stat counters
......@@ -370,6 +420,7 @@ struct lpfc_hba {
uint32_t total_scsi_bufs;
struct list_head lpfc_iocb_list;
uint32_t total_iocbq_bufs;
spinlock_t hbalock;
/* pci_mem_pools */
struct pci_pool *lpfc_scsi_dma_buf_pool;
......@@ -380,21 +431,33 @@ struct lpfc_hba {
mempool_t *nlp_mem_pool;
struct fc_host_statistics link_stats;
struct list_head port_list;
struct lpfc_vport *pport; /* physical lpfc_vport pointer */
};
static inline struct Scsi_Host *
lpfc_shost_from_vport(struct lpfc_vport *vport)
{
return container_of((void *) vport, struct Scsi_Host, hostdata[0]);
}
static inline void
lpfc_set_loopback_flag(struct lpfc_hba *phba) {
lpfc_set_loopback_flag(struct lpfc_hba *phba)
{
if (phba->cfg_topology == FLAGS_LOCAL_LB)
phba->fc_flag |= FC_LOOPBACK_MODE;
phba->link_flag |= LS_LOOPBACK_MODE;
else
phba->fc_flag &= ~FC_LOOPBACK_MODE;
phba->link_flag &= ~LS_LOOPBACK_MODE;
}
static inline int
lpfc_is_link_up(struct lpfc_hba *phba)
{
return phba->link_state == LPFC_LINK_UP ||
phba->link_state == LPFC_CLEAR_LA;
}
struct rnidrsp {
void *buf;
uint32_t uniqueid;
struct list_head list;
uint32_t data;
};
#define FC_REG_DUMP_EVENT 0x10 /* Register for Dump events */
......@@ -76,55 +76,68 @@ static ssize_t
lpfc_info_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
}
static ssize_t
lpfc_serialnum_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
}
static ssize_t
lpfc_modeldesc_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
}
static ssize_t
lpfc_modelname_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
}
static ssize_t
lpfc_programtype_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
}
static ssize_t
lpfc_portnum_show(struct class_device *cdev, char *buf)
lpfc_vportnum_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
}
static ssize_t
lpfc_fwrev_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
char fwrev[32];
lpfc_decode_firmware_rev(phba, fwrev, 1);
return snprintf(buf, PAGE_SIZE, "%s\n",fwrev);
}
......@@ -133,59 +146,80 @@ static ssize_t
lpfc_hdw_show(struct class_device *cdev, char *buf)
{
char hdw[9];
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
lpfc_vpd_t *vp = &phba->vpd;
lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
}
static ssize_t
lpfc_option_rom_version_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
}
static ssize_t
lpfc_state_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
int len = 0;
switch (phba->hba_state) {
case LPFC_STATE_UNKNOWN:
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
int len = 0;
switch (phba->link_state) {
case LPFC_LINK_UNKNOWN:
case LPFC_WARM_START:
case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS:
case LPFC_LINK_DOWN:
len += snprintf(buf + len, PAGE_SIZE-len, "Link Down\n");
case LPFC_HBA_ERROR:
len += snprintf(buf + len, PAGE_SIZE-len, "Link Down");
break;
case LPFC_LINK_UP:
case LPFC_LOCAL_CFG_LINK:
len += snprintf(buf + len, PAGE_SIZE-len, "Link Up\n");
break;
case LPFC_FLOGI:
case LPFC_FABRIC_CFG_LINK:
case LPFC_NS_REG:
case LPFC_NS_QRY:
case LPFC_BUILD_DISC_LIST:
case LPFC_DISC_AUTH:
case LPFC_CLEAR_LA:
len += snprintf(buf + len, PAGE_SIZE-len,
"Link Up - Discovery\n");
break;
case LPFC_HBA_READY:
len += snprintf(buf + len, PAGE_SIZE-len,
"Link Up - Ready:\n");
len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - \n");
switch (vport->port_state) {
len += snprintf(buf + len, PAGE_SIZE-len,
"initializing\n");
break;
case LPFC_LOCAL_CFG_LINK:
len += snprintf(buf + len, PAGE_SIZE-len,
"configuring\n");
break;
case LPFC_FLOGI:
case LPFC_FABRIC_CFG_LINK:
case LPFC_NS_REG:
case LPFC_NS_QRY:
case LPFC_BUILD_DISC_LIST:
case LPFC_DISC_AUTH:
len += snprintf(buf + len, PAGE_SIZE - len,
"Discovery\n");
break;
case LPFC_VPORT_READY:
len += snprintf(buf + len, PAGE_SIZE - len, "Ready\n");
break;
case LPFC_STATE_UNKNOWN:
len += snprintf(buf + len, PAGE_SIZE - len,
"Unknown\n");
break;
}
if (phba->fc_topology == TOPOLOGY_LOOP) {
if (phba->fc_flag & FC_PUBLIC_LOOP)
if (vport->fc_flag & FC_PUBLIC_LOOP)
len += snprintf(buf + len, PAGE_SIZE-len,
" Public Loop\n");
else
len += snprintf(buf + len, PAGE_SIZE-len,
" Private Loop\n");
} else {
if (phba->fc_flag & FC_FABRIC)
if (vport->fc_flag & FC_FABRIC)
len += snprintf(buf + len, PAGE_SIZE-len,
" Fabric\n");
else
......@@ -193,29 +227,32 @@ lpfc_state_show(struct class_device *cdev, char *buf)
" Point-2-Point\n");
}
}
return len;
}
static ssize_t
lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%d\n", phba->fc_map_cnt +
phba->fc_unmap_cnt);
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
return snprintf(buf, PAGE_SIZE, "%d\n",
vport->fc_map_cnt + vport->fc_unmap_cnt);
}
static int
lpfc_issue_lip(struct Scsi_Host *host)
lpfc_issue_lip(struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *pmboxq;
int mbxstatus = MBXERR_ERROR;
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
(phba->fc_flag & FC_BLOCK_MGMT_IO) ||
(phba->hba_state != LPFC_HBA_READY))
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
(phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) ||
(vport->port_state != LPFC_VPORT_READY))
return -EPERM;
pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
......@@ -320,8 +357,10 @@ lpfc_selective_reset(struct lpfc_hba *phba)
static ssize_t
lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
int status = -EINVAL;
if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
......@@ -336,23 +375,26 @@ lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
static ssize_t
lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
}
static ssize_t
lpfc_board_mode_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
char * state;
if (phba->hba_state == LPFC_HBA_ERROR)
if (phba->link_state == LPFC_HBA_ERROR)
state = "error";
else if (phba->hba_state == LPFC_WARM_START)
else if (phba->link_state == LPFC_WARM_START)
state = "warm start";
else if (phba->hba_state == LPFC_INIT_START)
else if (phba->link_state == LPFC_INIT_START)
state = "offline";
else
state = "online";
......@@ -363,8 +405,9 @@ lpfc_board_mode_show(struct class_device *cdev, char *buf)
static ssize_t
lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct completion online_compl;
int status=0;
......@@ -392,8 +435,9 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
static ssize_t
lpfc_poll_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
}
......@@ -402,8 +446,9 @@ static ssize_t
lpfc_poll_store(struct class_device *cdev, const char *buf,
size_t count)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
uint32_t creg_val;
uint32_t old_val;
int val=0;
......@@ -417,7 +462,7 @@ lpfc_poll_store(struct class_device *cdev, const char *buf,
if ((val & 0x3) != val)
return -EINVAL;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
old_val = phba->cfg_poll;
......@@ -432,16 +477,16 @@ lpfc_poll_store(struct class_device *cdev, const char *buf,
lpfc_poll_start_timer(phba);
}
} else if (val != 0x0) {
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return -EINVAL;
}
if (!(val & DISABLE_FCP_RING_INT) &&
(old_val & DISABLE_FCP_RING_INT))
{
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
del_timer(&phba->fcp_poll_timer);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
creg_val = readl(phba->HCregaddr);
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
writel(creg_val, phba->HCregaddr);
......@@ -450,7 +495,7 @@ lpfc_poll_store(struct class_device *cdev, const char *buf,
phba->cfg_poll = val;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return strlen(buf);
}
......@@ -459,8 +504,9 @@ lpfc_poll_store(struct class_device *cdev, const char *buf,
static ssize_t \
lpfc_##attr##_show(struct class_device *cdev, char *buf) \
{ \
struct Scsi_Host *host = class_to_shost(cdev);\
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
struct Scsi_Host *shost = class_to_shost(cdev);\
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
struct lpfc_hba *phba = vport->phba;\
int val = 0;\
val = phba->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%d\n",\
......@@ -471,8 +517,9 @@ lpfc_##attr##_show(struct class_device *cdev, char *buf) \
static ssize_t \
lpfc_##attr##_show(struct class_device *cdev, char *buf) \
{ \
struct Scsi_Host *host = class_to_shost(cdev);\
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
struct Scsi_Host *shost = class_to_shost(cdev);\
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
struct lpfc_hba *phba = vport->phba;\
int val = 0;\
val = phba->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%#x\n",\
......@@ -514,8 +561,9 @@ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \
static ssize_t \
lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
{ \
struct Scsi_Host *host = class_to_shost(cdev);\
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
struct Scsi_Host *shost = class_to_shost(cdev);\
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
struct lpfc_hba *phba = vport->phba;\
int val=0;\
if (!isdigit(buf[0]))\
return -EINVAL;\
......@@ -576,7 +624,7 @@ static CLASS_DEVICE_ATTR(serialnum, S_IRUGO, lpfc_serialnum_show, NULL);
static CLASS_DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
static CLASS_DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
static CLASS_DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_portnum_show, NULL);
static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
static CLASS_DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
static CLASS_DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
static CLASS_DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
......@@ -600,8 +648,9 @@ static ssize_t
lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
size_t count)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
unsigned int cnt = count;
/*
......@@ -634,8 +683,10 @@ static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
static ssize_t
lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
return snprintf(buf, PAGE_SIZE, "0x%llx\n",
(unsigned long long)phba->cfg_soft_wwpn);
}
......@@ -644,8 +695,9 @@ lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
static ssize_t
lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct completion online_compl;
int stat1=0, stat2=0;
unsigned int i, j, cnt=count;
......@@ -680,9 +732,9 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
}
}
phba->cfg_soft_wwpn = wwn_to_u64(wwpn);
fc_host_port_name(host) = phba->cfg_soft_wwpn;
fc_host_port_name(shost) = phba->cfg_soft_wwpn;
if (phba->cfg_soft_wwnn)
fc_host_node_name(host) = phba->cfg_soft_wwnn;
fc_host_node_name(shost) = phba->cfg_soft_wwnn;
dev_printk(KERN_NOTICE, &phba->pcidev->dev,
"lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
......@@ -790,8 +842,9 @@ MODULE_PARM_DESC(lpfc_nodev_tmo,
static ssize_t
lpfc_nodev_tmo_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
int val = 0;
val = phba->cfg_devloss_tmo;
return snprintf(buf, PAGE_SIZE, "%d\n",
......@@ -829,18 +882,6 @@ lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val)
return -EINVAL;
}
static void
lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba)
{
struct lpfc_nodelist *ndlp;
spin_lock_irq(phba->host->host_lock);
list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp)
if (ndlp->rport)
ndlp->rport->dev_loss_tmo = phba->cfg_devloss_tmo;
spin_unlock_irq(phba->host->host_lock);
}
static int
lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val)
{
......@@ -856,7 +897,6 @@ lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val)
if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
phba->cfg_nodev_tmo = val;
phba->cfg_devloss_tmo = val;
lpfc_update_rport_devloss_tmo(phba);
return 0;
}
......@@ -892,7 +932,6 @@ lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val)
phba->cfg_nodev_tmo = val;
phba->cfg_devloss_tmo = val;
phba->dev_loss_tmo_changed = 1;
lpfc_update_rport_devloss_tmo(phba);
return 0;
}
......@@ -1088,7 +1127,7 @@ LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible");
struct class_device_attribute *lpfc_host_attrs[] = {
struct class_device_attribute *lpfc_hba_attrs[] = {
&class_device_attr_info,
&class_device_attr_serialnum,
&class_device_attr_modeldesc,
......@@ -1136,9 +1175,11 @@ static ssize_t
sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
size_t buf_off;
struct Scsi_Host *host = class_to_shost(container_of(kobj,
struct class_device, kobj));
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct class_device *cdev = container_of(kobj, struct class_device,
kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
if ((off + count) > FF_REG_AREA_SIZE)
return -ERANGE;
......@@ -1148,18 +1189,16 @@ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (off % 4 || count % 4 || (unsigned long)buf % 4)
return -EINVAL;
spin_lock_irq(phba->host->host_lock);
if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
spin_unlock_irq(phba->host->host_lock);
if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
return -EPERM;
}
spin_lock_irq(&phba->hbalock);
for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t))
writel(*((uint32_t *)(buf + buf_off)),
phba->ctrl_regs_memmap_p + off + buf_off);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return count;
}
......@@ -1169,9 +1208,11 @@ sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
size_t buf_off;
uint32_t * tmp_ptr;
struct Scsi_Host *host = class_to_shost(container_of(kobj,
struct class_device, kobj));
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct class_device *cdev = container_of(kobj, struct class_device,
kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
if (off > FF_REG_AREA_SIZE)
return -ERANGE;
......@@ -1184,14 +1225,14 @@ sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (off % 4 || count % 4 || (unsigned long)buf % 4)
return -EINVAL;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) {
tmp_ptr = (uint32_t *)(buf + buf_off);
*tmp_ptr = readl(phba->ctrl_regs_memmap_p + off + buf_off);
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return count;
}
......@@ -1209,7 +1250,7 @@ static struct bin_attribute sysfs_ctlreg_attr = {
static void
sysfs_mbox_idle (struct lpfc_hba * phba)
sysfs_mbox_idle(struct lpfc_hba *phba)
{
phba->sysfs_mbox.state = SMBOX_IDLE;
phba->sysfs_mbox.offset = 0;
......@@ -1224,10 +1265,12 @@ sysfs_mbox_idle (struct lpfc_hba * phba)
static ssize_t
sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct Scsi_Host * host =
class_to_shost(container_of(kobj, struct class_device, kobj));
struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata;
struct lpfcMboxq * mbox = NULL;
struct class_device *cdev = container_of(kobj, struct class_device,
kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfcMboxq *mbox = NULL;
if ((count + off) > MAILBOX_CMD_SIZE)
return -ERANGE;
......@@ -1245,7 +1288,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
memset(mbox, 0, sizeof (LPFC_MBOXQ_t));
}
spin_lock_irq(host->host_lock);
spin_lock_irq(&phba->hbalock);
if (off == 0) {
if (phba->sysfs_mbox.mbox)
......@@ -1258,7 +1301,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
phba->sysfs_mbox.offset != off ||
phba->sysfs_mbox.mbox == NULL ) {
sysfs_mbox_idle(phba);
spin_unlock_irq(host->host_lock);
spin_unlock_irq(&phba->hbalock);
return -EAGAIN;
}
}
......@@ -1268,7 +1311,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
phba->sysfs_mbox.offset = off + count;
spin_unlock_irq(host->host_lock);
spin_unlock_irq(&phba->hbalock);
return count;
}
......@@ -1276,10 +1319,11 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t
sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct Scsi_Host *host =
class_to_shost(container_of(kobj, struct class_device,
kobj));
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct class_device *cdev = container_of(kobj, struct class_device,
kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
int rc;
if (off > MAILBOX_CMD_SIZE)
......@@ -1294,7 +1338,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (off && count == 0)
return 0;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
if (off == 0 &&
phba->sysfs_mbox.state == SMBOX_WRITING &&
......@@ -1317,12 +1361,12 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
case MBX_SET_MASK:
case MBX_SET_SLIM:
case MBX_SET_DEBUG:
if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
printk(KERN_WARNING "mbox_read:Command 0x%x "
"is illegal in on-line state\n",
phba->sysfs_mbox.mbox->mb.mbxCommand);
sysfs_mbox_idle(phba);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return -EPERM;
}
case MBX_LOAD_SM:
......@@ -1352,38 +1396,38 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n",
phba->sysfs_mbox.mbox->mb.mbxCommand);
sysfs_mbox_idle(phba);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return -EPERM;
default:
printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n",
phba->sysfs_mbox.mbox->mb.mbxCommand);
sysfs_mbox_idle(phba);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return -EPERM;
}
if (phba->fc_flag & FC_BLOCK_MGMT_IO) {
if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
sysfs_mbox_idle(phba);
spin_unlock_irq(host->host_lock);
spin_unlock_irq(&phba->hbalock);
return -EAGAIN;
}
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
(!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
rc = lpfc_sli_issue_mbox (phba,
phba->sysfs_mbox.mbox,
MBX_POLL);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
} else {
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
rc = lpfc_sli_issue_mbox_wait (phba,
phba->sysfs_mbox.mbox,
lpfc_mbox_tmo_val(phba,
phba->sysfs_mbox.mbox->mb.mbxCommand) * HZ);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
}
if (rc != MBX_SUCCESS) {
......@@ -1393,7 +1437,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
phba->sysfs_mbox.mbox = NULL;
}
sysfs_mbox_idle(phba);
spin_unlock_irq(host->host_lock);
spin_unlock_irq(&phba->hbalock);
return (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
}
phba->sysfs_mbox.state = SMBOX_READING;
......@@ -1402,7 +1446,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
phba->sysfs_mbox.state != SMBOX_READING) {
printk(KERN_WARNING "mbox_read: Bad State\n");
sysfs_mbox_idle(phba);
spin_unlock_irq(host->host_lock);
spin_unlock_irq(&phba->hbalock);
return -EAGAIN;
}
......@@ -1413,7 +1457,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
sysfs_mbox_idle(phba);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return count;
}
......@@ -1430,35 +1474,35 @@ static struct bin_attribute sysfs_mbox_attr = {
};
int
lpfc_alloc_sysfs_attr(struct lpfc_hba *phba)
lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
{
struct Scsi_Host *host = phba->host;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
int error;
error = sysfs_create_bin_file(&host->shost_classdev.kobj,
error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
&sysfs_ctlreg_attr);
if (error)
goto out;
error = sysfs_create_bin_file(&host->shost_classdev.kobj,
error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
&sysfs_mbox_attr);
if (error)
goto out_remove_ctlreg_attr;
return 0;
out_remove_ctlreg_attr:
sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
out:
return error;
}
void
lpfc_free_sysfs_attr(struct lpfc_hba *phba)
lpfc_free_sysfs_attr(struct lpfc_vport *vport)
{
struct Scsi_Host *host = phba->host;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_mbox_attr);
sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_mbox_attr);
sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
}
......@@ -1469,26 +1513,28 @@ lpfc_free_sysfs_attr(struct lpfc_hba *phba)
static void
lpfc_get_host_port_id(struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
/* note: fc_myDID already in cpu endianness */
fc_host_port_id(shost) = phba->fc_myDID;
fc_host_port_id(shost) = vport->fc_myDID;
}
static void
lpfc_get_host_port_type(struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
spin_lock_irq(shost->host_lock);
if (phba->hba_state == LPFC_HBA_READY) {
if (lpfc_is_link_up(phba)) {
if (phba->fc_topology == TOPOLOGY_LOOP) {
if (phba->fc_flag & FC_PUBLIC_LOOP)
if (vport->fc_flag & FC_PUBLIC_LOOP)
fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
else
fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
} else {
if (phba->fc_flag & FC_FABRIC)
if (vport->fc_flag & FC_FABRIC)
fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
else
fc_host_port_type(shost) = FC_PORTTYPE_PTP;
......@@ -1502,31 +1548,21 @@ lpfc_get_host_port_type(struct Scsi_Host *shost)
static void
lpfc_get_host_port_state(struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
spin_lock_irq(shost->host_lock);
if (phba->fc_flag & FC_OFFLINE_MODE)
if (vport->fc_flag & FC_OFFLINE_MODE)
fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
else {
switch (phba->hba_state) {
case LPFC_STATE_UNKNOWN:
case LPFC_WARM_START:
case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS:
switch (phba->link_state) {
case LPFC_LINK_UNKNOWN:
case LPFC_LINK_DOWN:
fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
break;
case LPFC_LINK_UP:
case LPFC_LOCAL_CFG_LINK:
case LPFC_FLOGI:
case LPFC_FABRIC_CFG_LINK:
case LPFC_NS_REG:
case LPFC_NS_QRY:
case LPFC_BUILD_DISC_LIST:
case LPFC_DISC_AUTH:
case LPFC_CLEAR_LA:
case LPFC_HBA_READY:
/* Links up, beyond this port_type reports state */
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
break;
......@@ -1545,11 +1581,12 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
static void
lpfc_get_host_speed(struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
spin_lock_irq(shost->host_lock);
if (phba->hba_state == LPFC_HBA_READY) {
if (lpfc_is_link_up(phba)) {
switch(phba->fc_linkspeed) {
case LA_1GHZ_LINK:
fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
......@@ -1575,39 +1612,31 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
static void
lpfc_get_host_fabric_name (struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
u64 node_name;
spin_lock_irq(shost->host_lock);
if ((phba->fc_flag & FC_FABRIC) ||
if ((vport->fc_flag & FC_FABRIC) ||
((phba->fc_topology == TOPOLOGY_LOOP) &&
(phba->fc_flag & FC_PUBLIC_LOOP)))
(vport->fc_flag & FC_PUBLIC_LOOP)))
node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
else
/* fabric is local port if there is no F/FL_Port */
node_name = wwn_to_u64(phba->fc_nodename.u.wwn);
node_name = wwn_to_u64(vport->fc_nodename.u.wwn);
spin_unlock_irq(shost->host_lock);
fc_host_fabric_name(shost) = node_name;
}
static void
lpfc_get_host_symbolic_name (struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
spin_lock_irq(shost->host_lock);
lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
spin_unlock_irq(shost->host_lock);
}
static struct fc_host_statistics *
lpfc_get_stats(struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_sli *psli = &phba->sli;
struct fc_host_statistics *hs = &phba->link_stats;
struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
LPFC_MBOXQ_t *pmboxq;
......@@ -1615,7 +1644,15 @@ lpfc_get_stats(struct Scsi_Host *shost)
unsigned long seconds;
int rc = 0;
if (phba->fc_flag & FC_BLOCK_MGMT_IO)
/* prevent udev from issuing mailbox commands
* until the port is configured.
*/
if (phba->link_state < LPFC_LINK_DOWN ||
!phba->mbox_mem_pool ||
(phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
return NULL;
if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
return NULL;
pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
......@@ -1628,7 +1665,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
pmb->mbxOwner = OWN_HOST;
pmboxq->context1 = NULL;
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
else
......@@ -1654,7 +1691,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
pmb->mbxOwner = OWN_HOST;
pmboxq->context1 = NULL;
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
else
......@@ -1711,14 +1748,15 @@ lpfc_get_stats(struct Scsi_Host *shost)
static void
lpfc_reset_stats(struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_lnk_stat *lso = &psli->lnk_stat_offsets;
LPFC_MBOXQ_t *pmboxq;
MAILBOX_t *pmb;
int rc = 0;
if (phba->fc_flag & FC_BLOCK_MGMT_IO)
if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
return;
pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
......@@ -1732,7 +1770,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)
pmb->un.varWords[0] = 0x1; /* reset request */
pmboxq->context1 = NULL;
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
else
......@@ -1751,7 +1789,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)
pmb->mbxOwner = OWN_HOST;
pmboxq->context1 = NULL;
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
else
......@@ -1789,13 +1827,13 @@ lpfc_reset_stats(struct Scsi_Host *shost)
static struct lpfc_nodelist *
lpfc_get_node_by_target(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_nodelist *ndlp;
spin_lock_irq(shost->host_lock);
/* Search for this, mapped, target ID */
list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
starget->id == ndlp->nlp_sid) {
spin_unlock_irq(shost->host_lock);
......@@ -1885,9 +1923,6 @@ struct fc_function_template lpfc_transport_functions = {
.get_host_fabric_name = lpfc_get_host_fabric_name,
.show_host_fabric_name = 1,
.get_host_symbolic_name = lpfc_get_host_symbolic_name,
.show_host_symbolic_name = 1,
/*
* The LPFC driver treats linkdown handling as target loss events
* so there are no sysfs handlers for link_down_tmo.
......
......@@ -26,6 +26,7 @@ void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
struct lpfc_dmabuf *mp);
void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport);
void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
......@@ -36,7 +37,6 @@ void lpfc_unreg_login(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
void lpfc_unreg_did(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
int lpfc_linkdown(struct lpfc_hba *);
void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
......@@ -45,70 +45,70 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_dequeue_node(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_nlp_set_state(struct lpfc_hba *, struct lpfc_nodelist *, int);
void lpfc_drop_node(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_set_disctmo(struct lpfc_hba *);
int lpfc_can_disctmo(struct lpfc_hba *);
int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_dequeue_node(struct lpfc_vport *, struct lpfc_nodelist *);
void lpfc_nlp_set_state(struct lpfc_vport *, struct lpfc_nodelist *, int);
void lpfc_drop_node(struct lpfc_vport *, struct lpfc_nodelist *);
void lpfc_set_disctmo(struct lpfc_vport *);
int lpfc_can_disctmo(struct lpfc_vport *);
int lpfc_unreg_rpi(struct lpfc_vport *, struct lpfc_nodelist *);
int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *, struct lpfc_nodelist *);
void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t);
struct lpfc_iocbq *, struct lpfc_nodelist *);
void lpfc_nlp_init(struct lpfc_vport *, struct lpfc_nodelist *, uint32_t);
struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *);
int lpfc_nlp_put(struct lpfc_nodelist *);
struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t);
void lpfc_disc_list_loopmap(struct lpfc_hba *);
void lpfc_disc_start(struct lpfc_hba *);
void lpfc_disc_flush_list(struct lpfc_hba *);
struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t);
void lpfc_disc_list_loopmap(struct lpfc_vport *);
void lpfc_disc_start(struct lpfc_vport *);
void lpfc_disc_flush_list(struct lpfc_vport *);
void lpfc_disc_timeout(unsigned long);
struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
int lpfc_do_work(void *);
int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,
uint32_t);
int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
struct serv_parm *, uint32_t);
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp);
int lpfc_els_abort_flogi(struct lpfc_hba *);
int lpfc_initial_flogi(struct lpfc_hba *);
int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
int lpfc_issue_els_prli(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_adisc(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_logo(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_scr(struct lpfc_hba *, uint32_t, uint8_t);
int lpfc_initial_flogi(struct lpfc_vport *);
int lpfc_issue_els_plogi(struct lpfc_vport *, uint32_t, uint8_t);
int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t);
int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_els_rsp_acc(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t);
int lpfc_els_rsp_reject(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
struct lpfc_nodelist *);
int lpfc_els_rsp_adisc_acc(struct lpfc_hba *, struct lpfc_iocbq *,
int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *,
struct lpfc_nodelist *);
int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *,
int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *,
struct lpfc_nodelist *);
void lpfc_cancel_retry_delay_tmo(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *);
void lpfc_els_retry_delay(unsigned long);
void lpfc_els_retry_delay_handler(struct lpfc_nodelist *);
void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
int lpfc_els_handle_rscn(struct lpfc_hba *);
int lpfc_els_flush_rscn(struct lpfc_hba *);
int lpfc_rscn_payload_check(struct lpfc_hba *, uint32_t);
void lpfc_els_flush_cmd(struct lpfc_hba *);
int lpfc_els_disc_adisc(struct lpfc_hba *);
int lpfc_els_disc_plogi(struct lpfc_hba *);
int lpfc_els_handle_rscn(struct lpfc_vport *);
int lpfc_els_flush_rscn(struct lpfc_vport *);
int lpfc_rscn_payload_check(struct lpfc_vport *, uint32_t);
void lpfc_els_flush_cmd(struct lpfc_vport *);
int lpfc_els_disc_adisc(struct lpfc_vport *);
int lpfc_els_disc_plogi(struct lpfc_vport *);
void lpfc_els_timeout(unsigned long);
void lpfc_els_timeout_handler(struct lpfc_hba *);
void lpfc_els_timeout_handler(struct lpfc_vport *);
void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
int lpfc_ns_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
int lpfc_fdmi_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
int lpfc_ns_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
void lpfc_fdmi_tmo(unsigned long);
void lpfc_fdmi_tmo_handler(struct lpfc_hba *);
void lpfc_fdmi_timeout_handler(struct lpfc_vport *vport);
int lpfc_config_port_prep(struct lpfc_hba *);
int lpfc_config_port_post(struct lpfc_hba *);
......@@ -146,6 +146,7 @@ void lpfc_poll_start_timer(struct lpfc_hba * phba);
void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
void __lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
void lpfc_reset_barrier(struct lpfc_hba * phba);
......@@ -154,6 +155,7 @@ int lpfc_sli_brdkill(struct lpfc_hba *);
int lpfc_sli_brdreset(struct lpfc_hba *);
int lpfc_sli_brdrestart(struct lpfc_hba *);
int lpfc_sli_hba_setup(struct lpfc_hba *);
int lpfc_sli_host_down(struct lpfc_vport *);
int lpfc_sli_hba_down(struct lpfc_hba *);
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
int lpfc_sli_handle_mb_event(struct lpfc_hba *);
......@@ -164,7 +166,7 @@ void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_sli_issue_iocb(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *, uint32_t);
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
int lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_dmabuf *);
struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
......@@ -173,15 +175,16 @@ struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
uint64_t, lpfc_ctx_cmd);
uint64_t, lpfc_ctx_cmd);
int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
uint64_t, uint32_t, lpfc_ctx_cmd);
uint64_t, uint32_t, lpfc_ctx_cmd);
void lpfc_mbox_timeout(unsigned long);
void lpfc_mbox_timeout_handler(struct lpfc_hba *);
struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t);
struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, struct lpfc_name *);
struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_vport *, uint32_t);
struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *,
struct lpfc_name *);
int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
uint32_t timeout);
......@@ -196,6 +199,7 @@ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba,
struct lpfc_iocbq * rspiocb);
void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
void __lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
/* Function prototypes. */
......@@ -204,17 +208,18 @@ void lpfc_scan_start(struct Scsi_Host *);
int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
void lpfc_get_cfgparam(struct lpfc_hba *);
int lpfc_alloc_sysfs_attr(struct lpfc_hba *);
void lpfc_free_sysfs_attr(struct lpfc_hba *);
extern struct class_device_attribute *lpfc_host_attrs[];
int lpfc_alloc_sysfs_attr(struct lpfc_vport *);
void lpfc_free_sysfs_attr(struct lpfc_vport *);
extern struct class_device_attribute *lpfc_hba_attrs[];
extern struct scsi_host_template lpfc_template;
extern struct fc_function_template lpfc_transport_functions;
void lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp);
void lpfc_get_hba_sym_node_name(struct lpfc_hba *phba, uint8_t *symbp);
void lpfc_terminate_rport_io(struct fc_rport *);
void lpfc_dev_loss_tmo_callbk(struct fc_rport *rport);
struct lpfc_vport *lpfc_create_port(struct lpfc_hba *, int);
void lpfc_post_hba_setup_vport_init(struct lpfc_vport *);
void destroy_port(struct lpfc_vport *);
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
#define HBA_EVENT_RSCN 5
#define HBA_EVENT_LINK_UP 2
#define HBA_EVENT_LINK_DOWN 3
......@@ -59,13 +59,13 @@ static char *lpfc_release_version = LPFC_DRIVER_VERSION;
* lpfc_ct_unsol_event
*/
void
lpfc_ct_unsol_event(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocbq)
lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocbq)
{
struct lpfc_iocbq *next_piocbq;
struct lpfc_dmabuf *pmbuf = NULL;
struct lpfc_dmabuf *matp, *next_matp;
struct lpfc_dmabuf *matp = NULL, *next_matp;
uint32_t ctx = 0, size = 0, cnt = 0;
IOCB_t *icmd = &piocbq->iocb;
IOCB_t *save_icmd = icmd;
......@@ -145,7 +145,7 @@ lpfc_ct_unsol_event(struct lpfc_hba * phba,
}
static void
lpfc_free_ct_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mlist)
lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
{
struct lpfc_dmabuf *mlast, *next_mlast;
......@@ -160,7 +160,7 @@ lpfc_free_ct_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mlist)
}
static struct lpfc_dmabuf *
lpfc_alloc_ct_rsp(struct lpfc_hba * phba, int cmdcode, struct ulp_bde64 * bpl,
lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
uint32_t size, int *entries)
{
struct lpfc_dmabuf *mlist = NULL;
......@@ -216,23 +216,21 @@ lpfc_alloc_ct_rsp(struct lpfc_hba * phba, int cmdcode, struct ulp_bde64 * bpl,
}
static int
lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
struct lpfc_iocbq *),
struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry,
uint32_t tmo)
{
struct lpfc_sli *psli = &phba->sli;
struct lpfc_hba *phba = vport->phba;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
IOCB_t *icmd;
struct lpfc_iocbq *geniocb;
/* Allocate buffer for command iocb */
spin_lock_irq(phba->host->host_lock);
geniocb = lpfc_sli_get_iocbq(phba);
spin_unlock_irq(phba->host->host_lock);
if (geniocb == NULL)
return 1;
......@@ -276,27 +274,26 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
"%d:0119 Issue GEN REQ IOCB for NPORT x%x "
"Data: x%x x%x\n", phba->brd_no, icmd->un.ulpWord[5],
icmd->ulpIoTag, phba->hba_state);
icmd->ulpIoTag, vport->port_state);
geniocb->iocb_cmpl = cmpl;
geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
spin_lock_irq(phba->host->host_lock);
geniocb->vport = vport;
if (lpfc_sli_issue_iocb(phba, pring, geniocb, 0) == IOCB_ERROR) {
lpfc_sli_release_iocbq(phba, geniocb);
spin_unlock_irq(phba->host->host_lock);
return 1;
}
spin_unlock_irq(phba->host->host_lock);
return 0;
}
static int
lpfc_ct_cmd(struct lpfc_hba *phba, struct lpfc_dmabuf *inmp,
lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp,
struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp,
void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
struct lpfc_iocbq *),
uint32_t rsp_size)
{
struct lpfc_hba *phba = vport->phba;
struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt;
struct lpfc_dmabuf *outmp;
int cnt = 0, status;
......@@ -310,7 +307,7 @@ lpfc_ct_cmd(struct lpfc_hba *phba, struct lpfc_dmabuf *inmp,
if (!outmp)
return -ENOMEM;
status = lpfc_gen_req(phba, bmp, inmp, outmp, cmpl, ndlp, 0,
status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0,
cnt+1, 0);
if (status) {
lpfc_free_ct_rsp(phba, outmp);
......@@ -320,19 +317,20 @@ lpfc_ct_cmd(struct lpfc_hba *phba, struct lpfc_dmabuf *inmp,
}
static int
lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_sli_ct_request *Response =
(struct lpfc_sli_ct_request *) mp->virt;
struct lpfc_nodelist *ndlp = NULL;
struct lpfc_dmabuf *mlast, *next_mp;
uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
uint32_t Did;
uint32_t CTentry;
uint32_t Did, CTentry;
int Cnt;
struct list_head head;
lpfc_set_disctmo(phba);
lpfc_set_disctmo(vport);
list_add_tail(&head, &mp->list);
......@@ -350,39 +348,31 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
/* Loop through entire NameServer list of DIDs */
while (Cnt >= sizeof (uint32_t)) {
/* Get next DID from NameServer List */
CTentry = *ctptr++;
Did = ((be32_to_cpu(CTentry)) & Mask_DID);
ndlp = NULL;
if (Did != phba->fc_myDID) {
/* Check for rscn processing or not */
ndlp = lpfc_setup_disc_node(phba, Did);
}
/* Mark all node table entries that are in the
Nameserver */
/* Check for rscn processing or not */
if (Did != vport->fc_myDID)
ndlp = lpfc_setup_disc_node(vport, Did);
if (ndlp) {
/* NameServer Rsp */
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
"%d:0238 Process x%x NameServer"
" Rsp Data: x%x x%x x%x\n",
phba->brd_no,
Did, ndlp->nlp_flag,
phba->fc_flag,
phba->fc_rscn_id_cnt);
vport->fc_flag,
vport->fc_rscn_id_cnt);
} else {
/* NameServer Rsp */
lpfc_printf_log(phba,
KERN_INFO,
LOG_DISCOVERY,
"%d:0239 Skip x%x NameServer "
"Rsp Data: x%x x%x x%x\n",
phba->brd_no,
Did, Size, phba->fc_flag,
phba->fc_rscn_id_cnt);
Did, Size, vport->fc_flag,
vport->fc_rscn_id_cnt);
}
if (CTentry & (be32_to_cpu(SLI_CT_LAST_ENTRY)))
goto nsout1;
Cnt -= sizeof (uint32_t);
......@@ -395,15 +385,15 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
list_del(&head);
/*
* The driver has cycled through all Nports in the RSCN payload.
* Complete the handling by cleaning up and marking the
* current driver state.
*/
if (phba->hba_state == LPFC_HBA_READY) {
lpfc_els_flush_rscn(phba);
spin_lock_irq(phba->host->host_lock);
phba->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */
spin_unlock_irq(phba->host->host_lock);
* The driver has cycled through all Nports in the RSCN payload.
* Complete the handling by cleaning up and marking the
* current driver state.
*/
if (vport->port_state == LPFC_VPORT_READY) {
lpfc_els_flush_rscn(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */
spin_unlock_irq(shost->host_lock);
}
return 0;
}
......@@ -412,18 +402,18 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
static void
lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb)
lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
struct lpfc_vport *vport = cmdiocb->vport;
IOCB_t *irsp;
struct lpfc_sli *psli;
struct lpfc_dmabuf *bmp;
struct lpfc_dmabuf *inp;
struct lpfc_dmabuf *outp;
struct lpfc_nodelist *ndlp;
struct lpfc_sli_ct_request *CTrsp;
int rc;
psli = &phba->sli;
/* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->context_un.rsp_iocb = rspiocb;
......@@ -435,22 +425,20 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
if (irsp->ulpStatus) {
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
(irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) {
(irsp->un.ulpWord[4] == IOERR_SLI_ABORTED)))
goto out;
}
/* Check for retry */
if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
phba->fc_ns_retry++;
if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
vport->fc_ns_retry++;
/* CT command is being retried */
ndlp = lpfc_findnode_did(phba, NameServer_DID);
ndlp = lpfc_findnode_did(vport, NameServer_DID);
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) ==
0) {
rc = lpfc_ns_cmd(vport, ndlp, SLI_CTNS_GID_FT);
if (rc == 0)
goto out;
}
}
}
} else {
/* Good status, continue checking */
CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
......@@ -460,8 +448,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
"%d:0208 NameServer Rsp "
"Data: x%x\n",
phba->brd_no,
phba->fc_flag);
lpfc_ns_rsp(phba, outp,
vport->fc_flag);
lpfc_ns_rsp(vport, outp,
(uint32_t) (irsp->un.genreq64.bdl.bdeSize));
} else if (CTrsp->CommandResponse.bits.CmdRsp ==
be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
......@@ -473,7 +461,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
CTrsp->CommandResponse.bits.CmdRsp,
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation,
phba->fc_flag);
vport->fc_flag);
} else {
/* NameServer Rsp Error */
lpfc_printf_log(phba,
......@@ -485,35 +473,31 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
CTrsp->CommandResponse.bits.CmdRsp,
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation,
phba->fc_flag);
vport->fc_flag);
}
}
/* Link up / RSCN discovery */
lpfc_disc_start(phba);
lpfc_disc_start(vport);
out:
lpfc_free_ct_rsp(phba, outp);
lpfc_mbuf_free(phba, inp->virt, inp->phys);
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
kfree(inp);
kfree(bmp);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irq(phba->host->host_lock);
return;
}
static void
lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb)
lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
struct lpfc_sli *psli;
struct lpfc_dmabuf *bmp;
struct lpfc_dmabuf *inp;
struct lpfc_dmabuf *outp;
IOCB_t *irsp;
struct lpfc_sli_ct_request *CTrsp;
psli = &phba->sli;
/* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->context_un.rsp_iocb = rspiocb;
......@@ -527,31 +511,31 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
/* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
"%d:0209 RFT request completes ulpStatus x%x "
"CmdRsp x%x\n", phba->brd_no, irsp->ulpStatus,
CTrsp->CommandResponse.bits.CmdRsp);
"CmdRsp x%x, Context x%x, Tag x%x\n",
phba->brd_no, irsp->ulpStatus,
CTrsp->CommandResponse.bits.CmdRsp,
cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag);
lpfc_free_ct_rsp(phba, outp);
lpfc_mbuf_free(phba, inp->virt, inp->phys);
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
kfree(inp);
kfree(bmp);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irq(phba->host->host_lock);
return;
}
static void
lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb)
lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
return;
}
static void
lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb)
lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
return;
......@@ -566,7 +550,7 @@ lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
}
void
lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp)
lpfc_get_hba_sym_node_name(struct lpfc_hba *phba, uint8_t *symbp)
{
char fwrev[16];
......@@ -585,8 +569,9 @@ lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp)
* LI_CTNS_RFT_ID
*/
int
lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
lpfc_ns_cmd(struct lpfc_vport *vport, struct lpfc_nodelist * ndlp, int cmdcode)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_dmabuf *mp, *bmp;
struct lpfc_sli_ct_request *CtReq;
struct ulp_bde64 *bpl;
......@@ -620,8 +605,8 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
KERN_INFO,
LOG_DISCOVERY,
"%d:0236 NameServer Req Data: x%x x%x x%x\n",
phba->brd_no, cmdcode, phba->fc_flag,
phba->fc_rscn_id_cnt);
phba->brd_no, cmdcode, vport->fc_flag,
vport->fc_rscn_id_cnt);
bpl = (struct ulp_bde64 *) bmp->virt;
memset(bpl, 0, sizeof(struct ulp_bde64));
......@@ -654,9 +639,9 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_GID_FT);
CtReq->un.gid.Fc4Type = SLI_CTPT_FCP;
if (phba->hba_state < LPFC_HBA_READY)
phba->hba_state = LPFC_NS_QRY;
lpfc_set_disctmo(phba);
if (vport->port_state < LPFC_VPORT_READY)
vport->port_state = LPFC_NS_QRY;
lpfc_set_disctmo(vport);
cmpl = lpfc_cmpl_ct_cmd_gid_ft;
rsp_size = FC_MAX_NS_RSP;
break;
......@@ -664,7 +649,7 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
case SLI_CTNS_RFT_ID:
CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_RFT_ID);
CtReq->un.rft.PortId = be32_to_cpu(phba->fc_myDID);
CtReq->un.rft.PortId = be32_to_cpu(vport->fc_myDID);
CtReq->un.rft.fcpReg = 1;
cmpl = lpfc_cmpl_ct_cmd_rft_id;
break;
......@@ -672,7 +657,7 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
case SLI_CTNS_RFF_ID:
CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_RFF_ID);
CtReq->un.rff.PortId = be32_to_cpu(phba->fc_myDID);
CtReq->un.rff.PortId = be32_to_cpu(vport->fc_myDID);
CtReq->un.rff.feature_res = 0;
CtReq->un.rff.feature_tgt = 0;
CtReq->un.rff.type_code = FC_FCP_DATA;
......@@ -683,8 +668,8 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
case SLI_CTNS_RNN_ID:
CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_RNN_ID);
CtReq->un.rnn.PortId = be32_to_cpu(phba->fc_myDID);
memcpy(CtReq->un.rnn.wwnn, &phba->fc_nodename,
CtReq->un.rnn.PortId = be32_to_cpu(vport->fc_myDID);
memcpy(CtReq->un.rnn.wwnn, &vport->fc_nodename,
sizeof (struct lpfc_name));
cmpl = lpfc_cmpl_ct_cmd_rnn_id;
break;
......@@ -692,7 +677,7 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
case SLI_CTNS_RSNN_NN:
CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_RSNN_NN);
memcpy(CtReq->un.rsnn.wwnn, &phba->fc_nodename,
memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename,
sizeof (struct lpfc_name));
lpfc_get_hba_sym_node_name(phba, CtReq->un.rsnn.symbname);
CtReq->un.rsnn.len = strlen(CtReq->un.rsnn.symbname);
......@@ -700,7 +685,7 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
break;
}
if (!lpfc_ct_cmd(phba, mp, bmp, ndlp, cmpl, rsp_size))
if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size))
/* On success, The cmpl function will free the buffers */
return 0;
......@@ -716,8 +701,8 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
}
static void
lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb)
lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq * rspiocb)
{
struct lpfc_dmabuf *bmp = cmdiocb->context3;
struct lpfc_dmabuf *inp = cmdiocb->context1;
......@@ -727,8 +712,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
struct lpfc_nodelist *ndlp;
uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
struct lpfc_vport *vport = cmdiocb->vport;
ndlp = lpfc_findnode_did(phba, FDMI_DID);
ndlp = lpfc_findnode_did(vport, FDMI_DID);
if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
/* FDMI rsp failed */
lpfc_printf_log(phba,
......@@ -741,18 +727,18 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
switch (be16_to_cpu(fdmi_cmd)) {
case SLI_MGMT_RHBA:
lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_RPA);
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA);
break;
case SLI_MGMT_RPA:
break;
case SLI_MGMT_DHBA:
lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DPRT);
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT);
break;
case SLI_MGMT_DPRT:
lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_RHBA);
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA);
break;
}
......@@ -761,14 +747,14 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
kfree(inp);
kfree(bmp);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irq(phba->host->host_lock);
return;
}
int
lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_dmabuf *mp, *bmp;
struct lpfc_sli_ct_request *CtReq;
struct ulp_bde64 *bpl;
......@@ -810,7 +796,7 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
LOG_DISCOVERY,
"%d:0218 FDMI Request Data: x%x x%x x%x\n",
phba->brd_no,
phba->fc_flag, phba->hba_state, cmdcode);
vport->fc_flag, vport->port_state, cmdcode);
CtReq = (struct lpfc_sli_ct_request *) mp->virt;
......@@ -833,11 +819,11 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
be16_to_cpu(SLI_MGMT_RHBA);
CtReq->CommandResponse.bits.Size = 0;
rh = (REG_HBA *) & CtReq->un.PortID;
memcpy(&rh->hi.PortName, &phba->fc_sparam.portName,
memcpy(&rh->hi.PortName, &vport->fc_sparam.portName,
sizeof (struct lpfc_name));
/* One entry (port) per adapter */
rh->rpl.EntryCnt = be32_to_cpu(1);
memcpy(&rh->rpl.pe, &phba->fc_sparam.portName,
memcpy(&rh->rpl.pe, &vport->fc_sparam.portName,
sizeof (struct lpfc_name));
/* point to the HBA attribute block */
......@@ -853,7 +839,7 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
ae->ad.bits.AttrType = be16_to_cpu(NODE_NAME);
ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES
+ sizeof (struct lpfc_name));
memcpy(&ae->un.NodeName, &phba->fc_sparam.nodeName,
memcpy(&ae->un.NodeName, &vport->fc_sparam.nodeName,
sizeof (struct lpfc_name));
ab->EntryCnt++;
size += FOURBYTES + sizeof (struct lpfc_name);
......@@ -991,7 +977,7 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
pab = (REG_PORT_ATTRIBUTE *) & CtReq->un.PortID;
size = sizeof (struct lpfc_name) + FOURBYTES;
memcpy((uint8_t *) & pab->PortName,
(uint8_t *) & phba->fc_sparam.portName,
(uint8_t *) & vport->fc_sparam.portName,
sizeof (struct lpfc_name));
pab->ab.EntryCnt = 0;
......@@ -1053,7 +1039,7 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size);
ae->ad.bits.AttrType = be16_to_cpu(MAX_FRAME_SIZE);
ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4);
hsp = (struct serv_parm *) & phba->fc_sparam;
hsp = (struct serv_parm *) & vport->fc_sparam;
ae->un.MaxFrameSize =
(((uint32_t) hsp->cmn.
bbRcvSizeMsb) << 8) | (uint32_t) hsp->cmn.
......@@ -1097,7 +1083,7 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
CtReq->CommandResponse.bits.Size = 0;
pe = (PORT_ENTRY *) & CtReq->un.PortID;
memcpy((uint8_t *) & pe->PortName,
(uint8_t *) & phba->fc_sparam.portName,
(uint8_t *) & vport->fc_sparam.portName,
sizeof (struct lpfc_name));
size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name);
break;
......@@ -1107,7 +1093,7 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
CtReq->CommandResponse.bits.Size = 0;
pe = (PORT_ENTRY *) & CtReq->un.PortID;
memcpy((uint8_t *) & pe->PortName,
(uint8_t *) & phba->fc_sparam.portName,
(uint8_t *) & vport->fc_sparam.portName,
sizeof (struct lpfc_name));
size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name);
break;
......@@ -1122,7 +1108,7 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
cmpl = lpfc_cmpl_ct_cmd_fdmi;
if (!lpfc_ct_cmd(phba, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP))
if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP))
return 0;
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
......@@ -1146,37 +1132,36 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
void
lpfc_fdmi_tmo(unsigned long ptr)
{
struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
struct lpfc_hba *phba = vport->phba;
unsigned long iflag;
spin_lock_irqsave(phba->host->host_lock, iflag);
if (!(phba->work_hba_events & WORKER_FDMI_TMO)) {
phba->work_hba_events |= WORKER_FDMI_TMO;
spin_lock_irqsave(&vport->work_port_lock, iflag);
if (!(vport->work_port_events & WORKER_FDMI_TMO)) {
vport->work_port_events |= WORKER_FDMI_TMO;
if (phba->work_wait)
wake_up(phba->work_wait);
}
spin_unlock_irqrestore(phba->host->host_lock,iflag);
spin_unlock_irqrestore(&vport->work_port_lock, iflag);
}
void
lpfc_fdmi_tmo_handler(struct lpfc_hba *phba)
lpfc_fdmi_timeout_handler(struct lpfc_vport *vport)
{
struct lpfc_nodelist *ndlp;
ndlp = lpfc_findnode_did(phba, FDMI_DID);
ndlp = lpfc_findnode_did(vport, FDMI_DID);
if (ndlp) {
if (init_utsname()->nodename[0] != '\0') {
lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
} else {
mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
}
if (init_utsname()->nodename[0] != '\0')
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
else
mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
}
return;
}
void
lpfc_decode_firmware_rev(struct lpfc_hba * phba, char *fwrevision, int flag)
lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
{
struct lpfc_sli *psli = &phba->sli;
lpfc_vpd_t *vp = &phba->vpd;
......
......@@ -49,8 +49,8 @@ struct lpfc_work_evt {
struct lpfc_nodelist {
struct list_head nlp_listp;
struct lpfc_name nlp_portname; /* port name */
struct lpfc_name nlp_nodename; /* node name */
struct lpfc_name nlp_portname;
struct lpfc_name nlp_nodename;
uint32_t nlp_flag; /* entry flags */
uint32_t nlp_DID; /* FC D_ID of entry */
uint32_t nlp_last_elscmd; /* Last ELS cmd sent */
......@@ -75,7 +75,7 @@ struct lpfc_nodelist {
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
struct fc_rport *rport; /* Corresponding FC transport
port structure */
struct lpfc_hba *nlp_phba;
struct lpfc_vport *vport;
struct lpfc_work_evt els_retry_evt;
unsigned long last_ramp_up_time; /* jiffy of last ramp up */
unsigned long last_q_full_time; /* jiffy of last queue full */
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -54,7 +54,7 @@ static uint8_t lpfcAlpaArray[] = {
0x10, 0x0F, 0x08, 0x04, 0x02, 0x01
};
static void lpfc_disc_timeout_handler(struct lpfc_hba *);
static void lpfc_disc_timeout_handler(struct lpfc_vport *);
void
lpfc_terminate_rport_io(struct fc_rport *rport)
......@@ -74,14 +74,12 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
return;
}
phba = ndlp->nlp_phba;
phba = ndlp->vport->phba;
spin_lock_irq(phba->host->host_lock);
if (ndlp->nlp_sid != NLP_NO_SID) {
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
}
spin_unlock_irq(phba->host->host_lock);
return;
}
......@@ -97,6 +95,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
uint8_t *name;
int warn_on = 0;
struct lpfc_hba *phba;
struct lpfc_vport *vport;
rdata = rport->dd_data;
ndlp = rdata->pnode;
......@@ -113,9 +112,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
return;
name = (uint8_t *)&ndlp->nlp_portname;
phba = ndlp->nlp_phba;
spin_lock_irq(phba->host->host_lock);
vport = ndlp->vport;
phba = vport->phba;
if (ndlp->nlp_sid != NLP_NO_SID) {
warn_on = 1;
......@@ -123,11 +121,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
}
if (phba->fc_flag & FC_UNLOADING)
if (vport->load_flag & FC_UNLOADING)
warn_on = 0;
spin_unlock_irq(phba->host->host_lock);
if (warn_on) {
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
"%d:0203 Devloss timeout on "
......@@ -150,11 +146,11 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
ndlp->nlp_state, ndlp->nlp_rpi);
}
if (!(phba->fc_flag & FC_UNLOADING) &&
if (!(vport->load_flag & FC_UNLOADING) &&
!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
!(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
(ndlp->nlp_state != NLP_STE_UNMAPPED_NODE))
lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM);
lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
else {
rdata->pnode = NULL;
ndlp->rport = NULL;
......@@ -166,33 +162,33 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
}
static void
lpfc_work_list_done(struct lpfc_hba * phba)
lpfc_work_list_done(struct lpfc_hba *phba)
{
struct lpfc_work_evt *evtp = NULL;
struct lpfc_nodelist *ndlp;
int free_evt;
spin_lock_irq(phba->host->host_lock);
while(!list_empty(&phba->work_list)) {
spin_lock_irq(&phba->hbalock);
while (!list_empty(&phba->work_list)) {
list_remove_head((&phba->work_list), evtp, typeof(*evtp),
evt_listp);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
free_evt = 1;
switch (evtp->evt) {
case LPFC_EVT_ELS_RETRY:
ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1);
ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
lpfc_els_retry_delay_handler(ndlp);
free_evt = 0;
break;
case LPFC_EVT_ONLINE:
if (phba->hba_state < LPFC_LINK_DOWN)
*(int *)(evtp->evt_arg1) = lpfc_online(phba);
if (phba->link_state < LPFC_LINK_DOWN)
*(int *) (evtp->evt_arg1) = lpfc_online(phba);
else
*(int *)(evtp->evt_arg1) = 0;
*(int *) (evtp->evt_arg1) = 0;
complete((struct completion *)(evtp->evt_arg2));
break;
case LPFC_EVT_OFFLINE_PREP:
if (phba->hba_state >= LPFC_LINK_DOWN)
if (phba->link_state >= LPFC_LINK_DOWN)
lpfc_offline_prep(phba);
*(int *)(evtp->evt_arg1) = 0;
complete((struct completion *)(evtp->evt_arg2));
......@@ -218,33 +214,32 @@ lpfc_work_list_done(struct lpfc_hba * phba)
case LPFC_EVT_KILL:
lpfc_offline(phba);
*(int *)(evtp->evt_arg1)
= (phba->stopped) ? 0 : lpfc_sli_brdkill(phba);
= (phba->pport->stopped)
? 0 : lpfc_sli_brdkill(phba);
lpfc_unblock_mgmt_io(phba);
complete((struct completion *)(evtp->evt_arg2));
break;
}
if (free_evt)
kfree(evtp);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
}
static void
lpfc_work_done(struct lpfc_hba * phba)
lpfc_work_done(struct lpfc_hba *phba)
{
struct lpfc_sli_ring *pring;
int i;
uint32_t ha_copy;
uint32_t control;
uint32_t work_hba_events;
uint32_t ha_copy, control, work_port_events;
struct lpfc_vport *vport;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
ha_copy = phba->work_ha;
phba->work_ha = 0;
work_hba_events=phba->work_hba_events;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
if (ha_copy & HA_ERATT)
lpfc_handle_eratt(phba);
......@@ -255,21 +250,25 @@ lpfc_work_done(struct lpfc_hba * phba)
if (ha_copy & HA_LATT)
lpfc_handle_latt(phba);
if (work_hba_events & WORKER_DISC_TMO)
lpfc_disc_timeout_handler(phba);
vport = phba->pport;
if (work_hba_events & WORKER_ELS_TMO)
lpfc_els_timeout_handler(phba);
work_port_events = vport->work_port_events;
if (work_hba_events & WORKER_MBOX_TMO)
if (work_port_events & WORKER_DISC_TMO)
lpfc_disc_timeout_handler(vport);
if (work_port_events & WORKER_ELS_TMO)
lpfc_els_timeout_handler(vport);
if (work_port_events & WORKER_MBOX_TMO)
lpfc_mbox_timeout_handler(phba);
if (work_hba_events & WORKER_FDMI_TMO)
lpfc_fdmi_tmo_handler(phba);
if (work_port_events & WORKER_FDMI_TMO)
lpfc_fdmi_timeout_handler(vport);
spin_lock_irq(phba->host->host_lock);
phba->work_hba_events &= ~work_hba_events;
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
vport->work_port_events &= ~work_port_events;
spin_unlock_irq(&phba->hbalock);
for (i = 0; i < phba->sli.num_rings; i++, ha_copy >>= 4) {
pring = &phba->sli.ring[i];
......@@ -286,33 +285,37 @@ lpfc_work_done(struct lpfc_hba * phba)
/*
* Turn on Ring interrupts
*/
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
control = readl(phba->HCregaddr);
control |= (HC_R0INT_ENA << i);
writel(control, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
}
}
lpfc_work_list_done (phba);
lpfc_work_list_done(phba);
}
static int
check_work_wait_done(struct lpfc_hba *phba) {
check_work_wait_done(struct lpfc_hba *phba)
{
struct lpfc_vport *vport = phba->pport;
int rc = 0;
if (!vport)
return 0;
spin_lock_irq(&phba->hbalock);
spin_lock_irq(phba->host->host_lock);
if (phba->work_ha ||
phba->work_hba_events ||
vport->work_port_events ||
(!list_empty(&phba->work_list)) ||
kthread_should_stop()) {
spin_unlock_irq(phba->host->host_lock);
return 1;
} else {
spin_unlock_irq(phba->host->host_lock);
return 0;
}
kthread_should_stop())
rc = 1;
spin_unlock_irq(&phba->hbalock);
return rc;
}
int
......@@ -347,7 +350,7 @@ lpfc_do_work(void *p)
* embedding it in the IOCB.
*/
int
lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2,
uint32_t evt)
{
struct lpfc_work_evt *evtp;
......@@ -364,11 +367,11 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
evtp->evt_arg2 = arg2;
evtp->evt = evt;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
list_add_tail(&evtp->evt_listp, &phba->work_list);
if (phba->work_wait)
wake_up(phba->work_wait);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return 1;
}
......@@ -376,75 +379,77 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
int
lpfc_linkdown(struct lpfc_hba *phba)
{
struct lpfc_sli *psli;
struct lpfc_vport *vport = phba->pport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_sli *psli;
struct lpfc_nodelist *ndlp, *next_ndlp;
LPFC_MBOXQ_t *mb;
int rc;
psli = &phba->sli;
/* sysfs or selective reset may call this routine to clean up */
if (phba->hba_state >= LPFC_LINK_DOWN) {
if (phba->hba_state == LPFC_LINK_DOWN)
return 0;
spin_lock_irq(phba->host->host_lock);
phba->hba_state = LPFC_LINK_DOWN;
spin_unlock_irq(phba->host->host_lock);
if (phba->link_state == LPFC_LINK_DOWN) {
return 0;
}
spin_lock_irq(&phba->hbalock);
if (phba->link_state > LPFC_LINK_DOWN)
phba->link_state = LPFC_LINK_DOWN;
spin_unlock_irq(&phba->hbalock);
fc_host_post_event(phba->host, fc_get_event_number(),
FCH_EVT_LINKDOWN, 0);
fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0);
/* Clean up any firmware default rpi's */
if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mb) {
lpfc_unreg_did(phba, 0xffffffff, mb);
mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
== MBX_NOT_FINISHED) {
mempool_free( mb, phba->mbox_mem_pool);
mempool_free(mb, phba->mbox_mem_pool);
}
}
/* Cleanup any outstanding RSCN activity */
lpfc_els_flush_rscn(phba);
lpfc_els_flush_rscn(vport);
/* Cleanup any outstanding ELS commands */
lpfc_els_flush_cmd(phba);
lpfc_els_flush_cmd(vport);
/*
* Issue a LINK DOWN event to all nodes.
*/
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
/* free any ndlp's on unused list */
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
/* free any ndlp's on unused state */
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
else /* otherwise, force node recovery. */
rc = lpfc_disc_state_machine(phba, ndlp, NULL,
rc = lpfc_disc_state_machine(vport, ndlp, NULL,
NLP_EVT_DEVICE_RECOVERY);
}
/* Setup myDID for link up if we are in pt2pt mode */
if (phba->fc_flag & FC_PT2PT) {
phba->fc_myDID = 0;
if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
if (vport->fc_flag & FC_PT2PT) {
vport->fc_myDID = 0;
mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mb) {
lpfc_config_link(phba, mb);
mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
if (lpfc_sli_issue_mbox
(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
if (lpfc_sli_issue_mbox(phba, mb,
(MBX_NOWAIT | MBX_STOP_IOCB))
== MBX_NOT_FINISHED) {
mempool_free( mb, phba->mbox_mem_pool);
mempool_free(mb, phba->mbox_mem_pool);
}
}
spin_lock_irq(phba->host->host_lock);
phba->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI);
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI);
spin_unlock_irq(shost->host_lock);
}
spin_lock_irq(phba->host->host_lock);
phba->fc_flag &= ~FC_LBIT;
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_LBIT;
spin_unlock_irq(shost->host_lock);
/* Turn off discovery timer if its running */
lpfc_can_disctmo(phba);
lpfc_can_disctmo(vport);
/* Must process IOCBs on all rings to handle ABORTed I/Os */
return 0;
......@@ -453,46 +458,47 @@ lpfc_linkdown(struct lpfc_hba *phba)
static int
lpfc_linkup(struct lpfc_hba *phba)
{
struct lpfc_vport *vport = phba->pport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_nodelist *ndlp, *next_ndlp;
fc_host_post_event(phba->host, fc_get_event_number(),
FCH_EVT_LINKUP, 0);
fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKUP, 0);
spin_lock_irq(phba->host->host_lock);
phba->hba_state = LPFC_LINK_UP;
phba->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
phba->fc_flag |= FC_NDISC_ACTIVE;
phba->fc_ns_retry = 0;
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
phba->link_state = LPFC_LINK_UP;
vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
vport->fc_flag |= FC_NDISC_ACTIVE;
vport->fc_ns_retry = 0;
spin_unlock_irq(shost->host_lock);
if (phba->fc_flag & FC_LBIT) {
list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
if (vport->fc_flag & FC_LBIT) {
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) {
if (ndlp->nlp_type & NLP_FABRIC) {
/*
* On Linkup its safe to clean up the
* ndlp from Fabric connections.
*/
lpfc_nlp_set_state(phba, ndlp,
lpfc_nlp_set_state(vport, ndlp,
NLP_STE_UNUSED_NODE);
} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
/*
* Fail outstanding IO now since
* device is marked for PLOGI.
*/
lpfc_unreg_rpi(phba, ndlp);
lpfc_unreg_rpi(vport, ndlp);
}
}
}
}
/* free any ndlp's on unused list */
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
/* free any ndlp's in unused state */
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
nlp_listp) {
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
}
return 0;
......@@ -505,14 +511,14 @@ lpfc_linkup(struct lpfc_hba *phba)
* handed off to the SLI layer.
*/
void
lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_sli *psli;
MAILBOX_t *mb;
struct lpfc_vport *vport = pmb->vport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_sli *psli = &phba->sli;
MAILBOX_t *mb = &pmb->mb;
uint32_t control;
psli = &phba->sli;
mb = &pmb->mb;
/* Since we don't do discovery right now, turn these off here */
psli->ring[psli->extra_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
psli->ring[psli->fcp_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
......@@ -520,32 +526,33 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
/* Check for error */
if ((mb->mbxStatus) && (mb->mbxStatus != 0x1601)) {
/* CLEAR_LA mbox error <mbxStatus> state <hba_state> */
/* CLEAR_LA mbox error <mbxStatus> state <port_state> */
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
"%d:0320 CLEAR_LA mbxStatus error x%x hba "
"state x%x\n",
phba->brd_no, mb->mbxStatus, phba->hba_state);
phba->brd_no, mb->mbxStatus, vport->port_state);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
goto out;
}
if (phba->fc_flag & FC_ABORT_DISCOVERY)
if (vport->fc_flag & FC_ABORT_DISCOVERY)
goto out;
phba->num_disc_nodes = 0;
/* go thru NPR list and issue ELS PLOGIs */
if (phba->fc_npr_cnt) {
lpfc_els_disc_plogi(phba);
}
vport->num_disc_nodes = 0;
/* go thru NPR nodes and issue ELS PLOGIs */
if (vport->fc_npr_cnt)
lpfc_els_disc_plogi(vport);
if (!phba->num_disc_nodes) {
spin_lock_irq(phba->host->host_lock);
phba->fc_flag &= ~FC_NDISC_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
if (!vport->num_disc_nodes) {
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_NDISC_ACTIVE;
spin_unlock_irq(shost->host_lock);
}
phba->hba_state = LPFC_HBA_READY;
printk(KERN_ERR "%s (%d): vport ready\n",
__FUNCTION__, __LINE__);
vport->port_state = LPFC_VPORT_READY;
out:
/* Device Discovery completes */
......@@ -555,34 +562,34 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
"%d:0225 Device Discovery completes\n",
phba->brd_no);
mempool_free( pmb, phba->mbox_mem_pool);
mempool_free(pmb, phba->mbox_mem_pool);
spin_lock_irq(phba->host->host_lock);
phba->fc_flag &= ~FC_ABORT_DISCOVERY;
if (phba->fc_flag & FC_ESTABLISH_LINK) {
phba->fc_flag &= ~FC_ESTABLISH_LINK;
}
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_ESTABLISH_LINK);
spin_unlock_irq(shost->host_lock);
del_timer_sync(&phba->fc_estabtmo);
lpfc_can_disctmo(phba);
lpfc_can_disctmo(vport);
/* turn on Link Attention interrupts */
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
psli->sli_flag |= LPFC_PROCESS_LA;
control = readl(phba->HCregaddr);
control |= HC_LAINT_ENA;
writel(control, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return;
}
static void
lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_vport *vport = pmb->vport;
struct lpfc_sli *psli = &phba->sli;
int rc;
......@@ -592,58 +599,64 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
mempool_free(pmb, phba->mbox_mem_pool);
if (phba->fc_topology == TOPOLOGY_LOOP &&
phba->fc_flag & FC_PUBLIC_LOOP &&
!(phba->fc_flag & FC_LBIT)) {
vport->fc_flag & FC_PUBLIC_LOOP &&
!(vport->fc_flag & FC_LBIT)) {
/* Need to wait for FAN - use discovery timer
* for timeout. hba_state is identically
* for timeout. port_state is identically
* LPFC_LOCAL_CFG_LINK while waiting for FAN
*/
lpfc_set_disctmo(phba);
lpfc_set_disctmo(vport);
return;
}
/* Start discovery by sending a FLOGI. hba_state is identically
/* Start discovery by sending a FLOGI. port_state is identically
* LPFC_FLOGI while waiting for FLOGI cmpl
*/
phba->hba_state = LPFC_FLOGI;
lpfc_set_disctmo(phba);
lpfc_initial_flogi(phba);
vport->port_state = LPFC_FLOGI;
lpfc_set_disctmo(vport);
lpfc_initial_flogi(vport);
return;
out:
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
"%d:0306 CONFIG_LINK mbxStatus error x%x "
"HBA state x%x\n",
phba->brd_no, pmb->mb.mbxStatus, phba->hba_state);
phba->brd_no, pmb->mb.mbxStatus, vport->port_state);
lpfc_linkdown(phba);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
"%d:0200 CONFIG_LINK bad hba state x%x\n",
phba->brd_no, phba->hba_state);
phba->brd_no, vport->port_state);
lpfc_clear_la(phba, pmb);
printk(KERN_ERR "%s (%d): do clear_la\n",
__FUNCTION__, __LINE__);
pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
pmb->vport = vport;
rc = lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
if (rc == MBX_NOT_FINISHED) {
mempool_free(pmb, phba->mbox_mem_pool);
lpfc_disc_flush_list(phba);
lpfc_disc_flush_list(vport);
psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
phba->hba_state = LPFC_HBA_READY;
printk(KERN_ERR "%s (%d): vport ready\n",
__FUNCTION__, __LINE__);
vport->port_state = LPFC_VPORT_READY;
}
return;
}
static void
lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_sli *psli = &phba->sli;
MAILBOX_t *mb = &pmb->mb;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1;
struct lpfc_vport *vport = pmb->vport;
/* Check for error */
......@@ -652,67 +665,78 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
"%d:0319 READ_SPARAM mbxStatus error x%x "
"hba state x%x>\n",
phba->brd_no, mb->mbxStatus, phba->hba_state);
phba->brd_no, mb->mbxStatus, vport->port_state);
lpfc_linkdown(phba);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
goto out;
}
memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt,
memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt,
sizeof (struct serv_parm));
if (phba->cfg_soft_wwnn)
u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
u64_to_wwn(phba->cfg_soft_wwnn,
vport->fc_sparam.nodeName.u.wwn);
if (phba->cfg_soft_wwpn)
u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
memcpy((uint8_t *) & phba->fc_nodename,
(uint8_t *) & phba->fc_sparam.nodeName,
u64_to_wwn(phba->cfg_soft_wwpn,
vport->fc_sparam.portName.u.wwn);
memcpy((uint8_t *) &vport->fc_nodename,
(uint8_t *) &vport->fc_sparam.nodeName,
sizeof (struct lpfc_name));
memcpy((uint8_t *) & phba->fc_portname,
(uint8_t *) & phba->fc_sparam.portName,
memcpy((uint8_t *) &vport->fc_portname,
(uint8_t *) &vport->fc_sparam.portName,
sizeof (struct lpfc_name));
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free( pmb, phba->mbox_mem_pool);
mempool_free(pmb, phba->mbox_mem_pool);
return;
out:
pmb->context1 = NULL;
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
if (phba->hba_state != LPFC_CLEAR_LA) {
if (phba->link_state != LPFC_CLEAR_LA) {
struct lpfc_sli_ring *extra_ring =
&psli->ring[psli->extra_ring];
struct lpfc_sli_ring *fcp_ring = &psli->ring[psli->fcp_ring];
struct lpfc_sli_ring *next_ring = &psli->ring[psli->next_ring];
lpfc_clear_la(phba, pmb);
printk(KERN_ERR "%s (%d): do clear_la\n",
__FUNCTION__, __LINE__);
pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
pmb->vport = vport;
if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB))
== MBX_NOT_FINISHED) {
mempool_free( pmb, phba->mbox_mem_pool);
lpfc_disc_flush_list(phba);
psli->ring[(psli->extra_ring)].flag &=
~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->fcp_ring)].flag &=
~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->next_ring)].flag &=
~LPFC_STOP_IOCB_EVENT;
phba->hba_state = LPFC_HBA_READY;
mempool_free(pmb, phba->mbox_mem_pool);
lpfc_disc_flush_list(vport);
extra_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
fcp_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
next_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
printk(KERN_ERR "%s (%d): vport ready\n",
__FUNCTION__, __LINE__);
vport->port_state = LPFC_VPORT_READY;
}
} else {
mempool_free( pmb, phba->mbox_mem_pool);
mempool_free(pmb, phba->mbox_mem_pool);
}
return;
}
static void
lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
lpfc_mbx_process_link_up(struct lpfc_vport *vport, READ_LA_VAR *la)
{
int i;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox;
int i;
struct lpfc_dmabuf *mp;
int rc;
sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
switch (la->UlnkSpeed) {
case LA_1GHZ_LINK:
phba->fc_linkspeed = LA_1GHZ_LINK;
......@@ -737,9 +761,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
/* Get Loop Map information */
if (la->il)
phba->fc_flag |= FC_LBIT;
vport->fc_flag |= FC_LBIT;
phba->fc_myDID = la->granted_AL_PA;
vport->fc_myDID = la->granted_AL_PA;
i = la->un.lilpBde64.tus.f.bdeSize;
if (i == 0) {
......@@ -781,14 +805,15 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
}
}
} else {
phba->fc_myDID = phba->fc_pref_DID;
phba->fc_flag |= FC_LBIT;
vport->fc_myDID = phba->fc_pref_DID;
vport->fc_flag |= FC_LBIT;
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
lpfc_linkup(phba);
if (sparam_mbox) {
lpfc_read_sparam(phba, sparam_mbox);
sparam_mbox->vport = vport;
sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
rc = lpfc_sli_issue_mbox(phba, sparam_mbox,
(MBX_NOWAIT | MBX_STOP_IOCB));
......@@ -804,8 +829,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
}
if (cfglink_mbox) {
phba->hba_state = LPFC_LOCAL_CFG_LINK;
vport->port_state = LPFC_LOCAL_CFG_LINK;
lpfc_config_link(phba, cfglink_mbox);
cfglink_mbox->vport = vport;
cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
rc = lpfc_sli_issue_mbox(phba, cfglink_mbox,
(MBX_NOWAIT | MBX_STOP_IOCB));
......@@ -815,20 +841,21 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
}
static void
lpfc_mbx_issue_link_down(struct lpfc_hba *phba) {
lpfc_mbx_issue_link_down(struct lpfc_hba *phba)
{
uint32_t control;
struct lpfc_sli *psli = &phba->sli;
lpfc_linkdown(phba);
/* turn on Link Attention interrupts - no CLEAR_LA needed */
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
psli->sli_flag |= LPFC_PROCESS_LA;
control = readl(phba->HCregaddr);
control |= HC_LAINT_ENA;
writel(control, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
}
/*
......@@ -838,8 +865,10 @@ lpfc_mbx_issue_link_down(struct lpfc_hba *phba) {
* handed off to the SLI layer.
*/
void
lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_vport *vport = pmb->vport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
READ_LA_VAR *la;
MAILBOX_t *mb = &pmb->mb;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
......@@ -851,9 +880,9 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
LOG_LINK_EVENT,
"%d:1307 READ_LA mbox error x%x state x%x\n",
phba->brd_no,
mb->mbxStatus, phba->hba_state);
mb->mbxStatus, vport->port_state);
lpfc_mbx_issue_link_down(phba);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
goto lpfc_mbx_cmpl_read_la_free_mbuf;
}
......@@ -861,27 +890,26 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
memcpy(&phba->alpa_map[0], mp->virt, 128);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
if (la->pb)
phba->fc_flag |= FC_BYPASSED_MODE;
vport->fc_flag |= FC_BYPASSED_MODE;
else
phba->fc_flag &= ~FC_BYPASSED_MODE;
spin_unlock_irq(phba->host->host_lock);
vport->fc_flag &= ~FC_BYPASSED_MODE;
spin_unlock_irq(shost->host_lock);
if (((phba->fc_eventTag + 1) < la->eventTag) ||
(phba->fc_eventTag == la->eventTag)) {
phba->fc_stat.LinkMultiEvent++;
if (la->attType == AT_LINK_UP) {
if (la->attType == AT_LINK_UP)
if (phba->fc_eventTag != 0)
lpfc_linkdown(phba);
}
}
phba->fc_eventTag = la->eventTag;
if (la->attType == AT_LINK_UP) {
phba->fc_stat.LinkUp++;
if (phba->fc_flag & FC_LOOPBACK_MODE) {
if (phba->link_flag & LS_LOOPBACK_MODE) {
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
"%d:1306 Link Up Event in loop back mode "
"x%x received Data: x%x x%x x%x x%x\n",
......@@ -896,14 +924,14 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
la->granted_AL_PA, la->UlnkSpeed,
phba->alpa_map[0]);
}
lpfc_mbx_process_link_up(phba, la);
lpfc_mbx_process_link_up(vport, la);
} else {
phba->fc_stat.LinkDown++;
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
"%d:1305 Link Down Event x%x received "
"Data: x%x x%x x%x\n",
phba->brd_no, la->eventTag, phba->fc_eventTag,
phba->hba_state, phba->fc_flag);
phba->pport->port_state, vport->fc_flag);
lpfc_mbx_issue_link_down(phba);
}
......@@ -921,26 +949,20 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
* handed off to the SLI layer.
*/
void
lpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_sli *psli;
MAILBOX_t *mb;
struct lpfc_dmabuf *mp;
struct lpfc_nodelist *ndlp;
psli = &phba->sli;
mb = &pmb->mb;
struct lpfc_vport *vport = pmb->vport;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1;
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
ndlp = (struct lpfc_nodelist *) pmb->context2;
mp = (struct lpfc_dmabuf *) (pmb->context1);
pmb->context1 = NULL;
/* Good status, call state machine */
lpfc_disc_state_machine(phba, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free( pmb, phba->mbox_mem_pool);
mempool_free(pmb, phba->mbox_mem_pool);
lpfc_nlp_put(ndlp);
return;
......@@ -953,20 +975,13 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
* handed off to the SLI layer.
*/
void
lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_sli *psli;
MAILBOX_t *mb;
struct lpfc_dmabuf *mp;
struct lpfc_nodelist *ndlp;
struct lpfc_nodelist *ndlp_fdmi;
psli = &phba->sli;
mb = &pmb->mb;
struct lpfc_vport *vport = pmb->vport;
MAILBOX_t *mb = &pmb->mb;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
struct lpfc_nodelist *ndlp, *ndlp_fdmi;
ndlp = (struct lpfc_nodelist *) pmb->context2;
mp = (struct lpfc_dmabuf *) (pmb->context1);
pmb->context1 = NULL;
pmb->context2 = NULL;
......@@ -978,57 +993,59 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_nlp_put(ndlp);
/* FLOGI failed, so just use loop map to make discovery list */
lpfc_disc_list_loopmap(phba);
lpfc_disc_list_loopmap(vport);
/* Start discovery */
lpfc_disc_start(phba);
lpfc_disc_start(vport);
return;
}
ndlp->nlp_rpi = mb->un.varWords[0];
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_nlp_put(ndlp); /* Drop the reference from the mbox */
if (phba->hba_state == LPFC_FABRIC_CFG_LINK) {
if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
/* This NPort has been assigned an NPort_ID by the fabric as a
* result of the completed fabric login. Issue a State Change
* Registration (SCR) ELS request to the fabric controller
* (SCR_DID) so that this NPort gets RSCN events from the
* fabric.
*/
lpfc_issue_els_scr(phba, SCR_DID, 0);
lpfc_issue_els_scr(vport, SCR_DID, 0);
ndlp = lpfc_findnode_did(phba, NameServer_DID);
ndlp = lpfc_findnode_did(vport, NameServer_DID);
if (!ndlp) {
/* Allocate a new node instance. If the pool is empty,
/* Allocate a new node instance. If the pool is empty,
* start the discovery process and skip the Nameserver
* login process. This is attempted again later on.
* Otherwise, issue a Port Login (PLOGI) to NameServer.
* Otherwise, issue a Port Login (PLOGI) to
* the NameServer
*/
ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
if (!ndlp) {
lpfc_disc_start(phba);
lpfc_disc_start(vport);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free(pmb, phba->mbox_mem_pool);
return;
} else {
lpfc_nlp_init(phba, ndlp, NameServer_DID);
lpfc_nlp_init(vport, ndlp, NameServer_DID);
ndlp->nlp_type |= NLP_FABRIC;
}
}
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(phba, NameServer_DID, 0);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(vport, NameServer_DID, 0);
if (phba->cfg_fdmi_on) {
ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
GFP_KERNEL);
GFP_KERNEL);
if (ndlp_fdmi) {
lpfc_nlp_init(phba, ndlp_fdmi, FDMI_DID);
lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
ndlp_fdmi->nlp_type |= NLP_FABRIC;
ndlp_fdmi->nlp_state = NLP_STE_PLOGI_ISSUE;
lpfc_issue_els_plogi(phba, FDMI_DID, 0);
lpfc_issue_els_plogi(vport, FDMI_DID, 0);
}
}
}
......@@ -1046,32 +1063,28 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
* handed off to the SLI layer.
*/
void
lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_sli *psli;
MAILBOX_t *mb;
struct lpfc_dmabuf *mp;
struct lpfc_nodelist *ndlp;
psli = &phba->sli;
mb = &pmb->mb;
ndlp = (struct lpfc_nodelist *) pmb->context2;
mp = (struct lpfc_dmabuf *) (pmb->context1);
MAILBOX_t *mb = &pmb->mb;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
struct lpfc_vport *vport = pmb->vport;
if (mb->mbxStatus) {
lpfc_nlp_put(ndlp);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free(pmb, phba->mbox_mem_pool);
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
/* RegLogin failed, so just use loop map to make discovery
list */
lpfc_disc_list_loopmap(phba);
/*
* RegLogin failed, so just use loop map to make discovery
* list
*/
lpfc_disc_list_loopmap(vport);
/* Start discovery */
lpfc_disc_start(phba);
lpfc_disc_start(vport);
return;
}
......@@ -1079,37 +1092,39 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
ndlp->nlp_rpi = mb->un.varWords[0];
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
if (phba->hba_state < LPFC_HBA_READY) {
/* Link up discovery requires Fabrib registration. */
lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RNN_ID);
lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RSNN_NN);
lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFT_ID);
lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFF_ID);
if (vport->port_state < LPFC_VPORT_READY) {
/* Link up discovery requires Fabric registration. */
lpfc_ns_cmd(vport, ndlp, SLI_CTNS_RNN_ID);
lpfc_ns_cmd(vport, ndlp, SLI_CTNS_RSNN_NN);
lpfc_ns_cmd(vport, ndlp, SLI_CTNS_RFT_ID);
lpfc_ns_cmd(vport, ndlp, SLI_CTNS_RFF_ID);
}
phba->fc_ns_retry = 0;
vport->fc_ns_retry = 0;
/* Good status, issue CT Request to NameServer */
if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT)) {
if (lpfc_ns_cmd(vport, ndlp, SLI_CTNS_GID_FT)) {
/* Cannot issue NameServer Query, so finish up discovery */
lpfc_disc_start(phba);
lpfc_disc_start(vport);
}
lpfc_nlp_put(ndlp);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free( pmb, phba->mbox_mem_pool);
mempool_free(pmb, phba->mbox_mem_pool);
return;
}
static void
lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
struct fc_rport *rport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct fc_rport *rport;
struct lpfc_rport_data *rdata;
struct fc_rport_identifiers rport_ids;
struct lpfc_hba *phba = vport->phba;
/* Remote port has reappeared. Re-register w/ FC transport */
rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
......@@ -1128,7 +1143,7 @@ lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
*(struct lpfc_rport_data **) ndlp->rport->dd_data) {
lpfc_nlp_put(ndlp);
}
ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids);
if (!rport || !get_device(&rport->dev)) {
dev_printk(KERN_WARNING, &phba->pcidev->dev,
"Warning: fc_remote_port_add failed\n");
......@@ -1159,7 +1174,7 @@ lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
}
static void
lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp)
{
struct fc_rport *rport = ndlp->rport;
struct lpfc_rport_data *rdata = rport->dd_data;
......@@ -1177,42 +1192,46 @@ lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
}
static void
lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
lpfc_nlp_counters(struct lpfc_vport *vport, int state, int count)
{
spin_lock_irq(phba->host->host_lock);
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
spin_lock_irq(shost->host_lock);
switch (state) {
case NLP_STE_UNUSED_NODE:
phba->fc_unused_cnt += count;
vport->fc_unused_cnt += count;
break;
case NLP_STE_PLOGI_ISSUE:
phba->fc_plogi_cnt += count;
vport->fc_plogi_cnt += count;
break;
case NLP_STE_ADISC_ISSUE:
phba->fc_adisc_cnt += count;
vport->fc_adisc_cnt += count;
break;
case NLP_STE_REG_LOGIN_ISSUE:
phba->fc_reglogin_cnt += count;
vport->fc_reglogin_cnt += count;
break;
case NLP_STE_PRLI_ISSUE:
phba->fc_prli_cnt += count;
vport->fc_prli_cnt += count;
break;
case NLP_STE_UNMAPPED_NODE:
phba->fc_unmap_cnt += count;
vport->fc_unmap_cnt += count;
break;
case NLP_STE_MAPPED_NODE:
phba->fc_map_cnt += count;
vport->fc_map_cnt += count;
break;
case NLP_STE_NPR_NODE:
phba->fc_npr_cnt += count;
vport->fc_npr_cnt += count;
break;
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
}
static void
lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
int old_state, int new_state)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (new_state == NLP_STE_UNMAPPED_NODE) {
ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
......@@ -1226,19 +1245,19 @@ lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
/* Transport interface */
if (ndlp->rport && (old_state == NLP_STE_MAPPED_NODE ||
old_state == NLP_STE_UNMAPPED_NODE)) {
phba->nport_event_cnt++;
lpfc_unregister_remote_port(phba, ndlp);
vport->phba->nport_event_cnt++;
lpfc_unregister_remote_port(ndlp);
}
if (new_state == NLP_STE_MAPPED_NODE ||
new_state == NLP_STE_UNMAPPED_NODE) {
phba->nport_event_cnt++;
vport->phba->nport_event_cnt++;
/*
* Tell the fc transport about the port, if we haven't
* already. If we have, and it's a scsi entity, be
* sure to unblock any attached scsi devices
*/
lpfc_register_remote_port(phba, ndlp);
lpfc_register_remote_port(vport, ndlp);
}
/*
......@@ -1251,10 +1270,10 @@ lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
(!ndlp->rport ||
ndlp->rport->scsi_target_id == -1 ||
ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) {
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_TGT_NO_SCSIID;
spin_unlock_irq(phba->host->host_lock);
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
spin_unlock_irq(shost->host_lock);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
}
}
......@@ -1280,61 +1299,67 @@ lpfc_nlp_state_name(char *buffer, size_t size, int state)
}
void
lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
int state)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
int old_state = ndlp->nlp_state;
char name1[16], name2[16];
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE,
"%d:0904 NPort state transition x%06x, %s -> %s\n",
phba->brd_no,
vport->phba->brd_no,
ndlp->nlp_DID,
lpfc_nlp_state_name(name1, sizeof(name1), old_state),
lpfc_nlp_state_name(name2, sizeof(name2), state));
if (old_state == NLP_STE_NPR_NODE &&
(ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
state != NLP_STE_NPR_NODE)
lpfc_cancel_retry_delay_tmo(phba, ndlp);
lpfc_cancel_retry_delay_tmo(vport, ndlp);
if (old_state == NLP_STE_UNMAPPED_NODE) {
ndlp->nlp_flag &= ~NLP_TGT_NO_SCSIID;
ndlp->nlp_type &= ~NLP_FC_NODE;
}
if (list_empty(&ndlp->nlp_listp)) {
spin_lock_irq(phba->host->host_lock);
list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes);
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes);
spin_unlock_irq(shost->host_lock);
} else if (old_state)
lpfc_nlp_counters(phba, old_state, -1);
lpfc_nlp_counters(vport, old_state, -1);
ndlp->nlp_state = state;
lpfc_nlp_counters(phba, state, 1);
lpfc_nlp_state_cleanup(phba, ndlp, old_state, state);
lpfc_nlp_counters(vport, state, 1);
lpfc_nlp_state_cleanup(vport, ndlp, old_state, state);
}
void
lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
lpfc_cancel_retry_delay_tmo(phba, ndlp);
lpfc_cancel_retry_delay_tmo(vport, ndlp);
if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
spin_lock_irq(phba->host->host_lock);
lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
spin_lock_irq(shost->host_lock);
list_del_init(&ndlp->nlp_listp);
spin_unlock_irq(phba->host->host_lock);
lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0);
spin_unlock_irq(shost->host_lock);
lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, 0);
}
void
lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
lpfc_cancel_retry_delay_tmo(phba, ndlp);
lpfc_cancel_retry_delay_tmo(vport, ndlp);
if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
spin_lock_irq(phba->host->host_lock);
lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
spin_lock_irq(shost->host_lock);
list_del_init(&ndlp->nlp_listp);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
lpfc_nlp_put(ndlp);
}
......@@ -1342,11 +1367,13 @@ lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
* Start / ReStart rescue timer for Discovery / RSCN handling
*/
void
lpfc_set_disctmo(struct lpfc_hba * phba)
lpfc_set_disctmo(struct lpfc_vport *vport)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
uint32_t tmo;
if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
if (vport->port_state == LPFC_LOCAL_CFG_LINK) {
/* For FAN, timeout should be greater then edtov */
tmo = (((phba->fc_edtov + 999) / 1000) + 1);
} else {
......@@ -1356,18 +1383,18 @@ lpfc_set_disctmo(struct lpfc_hba * phba)
tmo = ((phba->fc_ratov * 3) + 3);
}
mod_timer(&phba->fc_disctmo, jiffies + HZ * tmo);
spin_lock_irq(phba->host->host_lock);
phba->fc_flag |= FC_DISC_TMO;
spin_unlock_irq(phba->host->host_lock);
mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_DISC_TMO;
spin_unlock_irq(shost->host_lock);
/* Start Discovery Timer state <hba_state> */
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
"%d:0247 Start Discovery Timer state x%x "
"Data: x%x x%lx x%x x%x\n",
phba->brd_no,
phba->hba_state, tmo, (unsigned long)&phba->fc_disctmo,
phba->fc_plogi_cnt, phba->fc_adisc_cnt);
phba->brd_no, vport->port_state, tmo,
(unsigned long)&vport->fc_disctmo, vport->fc_plogi_cnt,
vport->fc_adisc_cnt);
return;
}
......@@ -1376,23 +1403,29 @@ lpfc_set_disctmo(struct lpfc_hba * phba)
* Cancel rescue timer for Discovery / RSCN handling
*/
int
lpfc_can_disctmo(struct lpfc_hba * phba)
lpfc_can_disctmo(struct lpfc_vport *vport)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
unsigned long iflags;
/* Turn off discovery timer if its running */
if (phba->fc_flag & FC_DISC_TMO) {
spin_lock_irq(phba->host->host_lock);
phba->fc_flag &= ~FC_DISC_TMO;
spin_unlock_irq(phba->host->host_lock);
del_timer_sync(&phba->fc_disctmo);
phba->work_hba_events &= ~WORKER_DISC_TMO;
if (vport->fc_flag & FC_DISC_TMO) {
spin_lock_irqsave(shost->host_lock, iflags);
vport->fc_flag &= ~FC_DISC_TMO;
spin_unlock_irqrestore(shost->host_lock, iflags);
del_timer_sync(&vport->fc_disctmo);
spin_lock_irqsave(&vport->work_port_lock, iflags);
vport->work_port_events &= ~WORKER_DISC_TMO;
spin_unlock_irqrestore(&vport->work_port_lock, iflags);
}
/* Cancel Discovery Timer state <hba_state> */
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
"%d:0248 Cancel Discovery Timer state x%x "
"Data: x%x x%x x%x\n",
phba->brd_no, phba->hba_state, phba->fc_flag,
phba->fc_plogi_cnt, phba->fc_adisc_cnt);
phba->brd_no, vport->port_state, vport->fc_flag,
vport->fc_plogi_cnt, vport->fc_adisc_cnt);
return 0;
}
......@@ -1402,15 +1435,13 @@ lpfc_can_disctmo(struct lpfc_hba * phba)
* Return true if iocb matches the specified nport
*/
int
lpfc_check_sli_ndlp(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * iocb, struct lpfc_nodelist * ndlp)
lpfc_check_sli_ndlp(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring,
struct lpfc_iocbq *iocb,
struct lpfc_nodelist *ndlp)
{
struct lpfc_sli *psli;
IOCB_t *icmd;
psli = &phba->sli;
icmd = &iocb->iocb;
struct lpfc_sli *psli = &phba->sli;
IOCB_t *icmd = &iocb->iocb;
if (pring->ringno == LPFC_ELS_RING) {
switch (icmd->ulpCommand) {
case CMD_GEN_REQUEST64_CR:
......@@ -1445,7 +1476,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba,
* associated with nlp_rpi in the LPFC_NODELIST entry.
*/
static int
lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
LIST_HEAD(completions);
struct lpfc_sli *psli;
......@@ -1465,9 +1496,9 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(iocb, next_iocb, &pring->txq,
list) {
list) {
/*
* Check to see if iocb matches the nport we are
* looking for
......@@ -1481,8 +1512,7 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
pring->txq_cnt--;
}
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
}
}
......@@ -1490,13 +1520,14 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
iocb = list_get_first(&completions, struct lpfc_iocbq, list);
list_del(&iocb->list);
if (iocb->iocb_cmpl) {
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
icmd = &iocb->iocb;
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(iocb->iocb_cmpl) (phba, iocb, iocb);
} else
lpfc_sli_release_iocbq(phba, iocb);
(iocb->iocb_cmpl)(phba, iocb, iocb);
}
}
return 0;
......@@ -1512,19 +1543,21 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
* we are waiting to PLOGI back to the remote NPort.
*/
int
lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
LPFC_MBOXQ_t *mbox;
struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *mbox;
int rc;
if (ndlp->nlp_rpi) {
if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox) {
lpfc_unreg_login(phba, ndlp->nlp_rpi, mbox);
mbox->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
rc = lpfc_sli_issue_mbox
(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
if (rc == MBX_NOT_FINISHED)
mempool_free( mbox, phba->mbox_mem_pool);
mempool_free(mbox, phba->mbox_mem_pool);
}
lpfc_no_rpi(phba, ndlp);
ndlp->nlp_rpi = 0;
......@@ -1538,10 +1571,11 @@ lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
* so it can be freed.
*/
static int
lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
LPFC_MBOXQ_t *mb;
LPFC_MBOXQ_t *nextmb;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *mb, *nextmb;
struct lpfc_dmabuf *mp;
/* Cleanup node for NPort <nlp_DID> */
......@@ -1551,7 +1585,7 @@ lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, ndlp->nlp_rpi);
lpfc_dequeue_node(phba, ndlp);
lpfc_dequeue_node(vport, ndlp);
/* cleanup any ndlp on mbox q waiting for reglogin cmpl */
if ((mb = phba->sli.mbox_active)) {
......@@ -1562,13 +1596,13 @@ lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
}
}
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
(ndlp == (struct lpfc_nodelist *) mb->context2)) {
mp = (struct lpfc_dmabuf *) (mb->context1);
if (mp) {
lpfc_mbuf_free(phba, mp->virt, mp->phys);
__lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
}
list_del(&mb->list);
......@@ -1576,12 +1610,12 @@ lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
lpfc_nlp_put(ndlp);
}
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
lpfc_els_abort(phba,ndlp);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_DELAY_TMO;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
ndlp->nlp_last_elscmd = 0;
del_timer_sync(&ndlp->nlp_delayfunc);
......@@ -1589,7 +1623,7 @@ lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
if (!list_empty(&ndlp->els_retry_evt.evt_listp))
list_del_init(&ndlp->els_retry_evt.evt_listp);
lpfc_unreg_rpi(phba, ndlp);
lpfc_unreg_rpi(vport, ndlp);
return 0;
}
......@@ -1600,17 +1634,22 @@ lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
* machine, defer the free till we reach the end of the state machine.
*/
static void
lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
struct lpfc_rport_data *rdata;
if (ndlp->nlp_flag & NLP_DELAY_TMO) {
lpfc_cancel_retry_delay_tmo(phba, ndlp);
lpfc_cancel_retry_delay_tmo(vport, ndlp);
}
lpfc_cleanup_node(phba, ndlp);
lpfc_cleanup_node(vport, ndlp);
if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
/*
* We should never get here with a non-NULL ndlp->rport. But
* if we do, drop the reference to the rport. That seems the
* intelligent thing to do.
*/
if (ndlp->rport && !(vport->load_flag & FC_UNLOADING)) {
put_device(&ndlp->rport->dev);
rdata = ndlp->rport->dd_data;
rdata->pnode = NULL;
......@@ -1619,11 +1658,10 @@ lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
}
static int
lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint32_t did)
{
D_ID mydid;
D_ID ndlpdid;
D_ID matchdid;
D_ID mydid, ndlpdid, matchdid;
if (did == Bcast_DID)
return 0;
......@@ -1637,7 +1675,7 @@ lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
return 1;
/* Next check for area/domain identically equals 0 match */
mydid.un.word = phba->fc_myDID;
mydid.un.word = vport->fc_myDID;
if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) {
return 0;
}
......@@ -1669,15 +1707,15 @@ lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
}
/* Search for a nodelist entry */
struct lpfc_nodelist *
lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did)
static struct lpfc_nodelist *
__lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp;
uint32_t data1;
spin_lock_irq(phba->host->host_lock);
list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
if (lpfc_matchdid(phba, ndlp, did)) {
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
if (lpfc_matchdid(vport, ndlp, did)) {
data1 = (((uint32_t) ndlp->nlp_state << 24) |
((uint32_t) ndlp->nlp_xri << 16) |
((uint32_t) ndlp->nlp_type << 8) |
......@@ -1688,11 +1726,9 @@ lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did)
phba->brd_no,
ndlp, ndlp->nlp_DID,
ndlp->nlp_flag, data1);
spin_unlock_irq(phba->host->host_lock);
return ndlp;
}
}
spin_unlock_irq(phba->host->host_lock);
/* FIND node did <did> NOT FOUND */
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
......@@ -1702,68 +1738,85 @@ lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did)
}
struct lpfc_nodelist *
lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_nodelist *ndlp;
spin_lock_irq(shost->host_lock);
ndlp = __lpfc_findnode_did(vport, did);
spin_unlock_irq(shost->host_lock);
return ndlp;
}
struct lpfc_nodelist *
lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_nodelist *ndlp;
ndlp = lpfc_findnode_did(phba, did);
ndlp = lpfc_findnode_did(vport, did);
if (!ndlp) {
if ((phba->fc_flag & FC_RSCN_MODE) &&
((lpfc_rscn_payload_check(phba, did) == 0)))
if ((vport->fc_flag & FC_RSCN_MODE) != 0 &&
lpfc_rscn_payload_check(vport, did) == 0)
return NULL;
ndlp = (struct lpfc_nodelist *)
mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
mempool_alloc(vport->phba->nlp_mem_pool, GFP_KERNEL);
if (!ndlp)
return NULL;
lpfc_nlp_init(phba, ndlp, did);
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
lpfc_nlp_init(vport, ndlp, did);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
return ndlp;
}
if (phba->fc_flag & FC_RSCN_MODE) {
if (lpfc_rscn_payload_check(phba, did)) {
if (vport->fc_flag & FC_RSCN_MODE) {
if (lpfc_rscn_payload_check(vport, did)) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
/* Since this node is marked for discovery,
* delay timeout is not needed.
*/
if (ndlp->nlp_flag & NLP_DELAY_TMO)
lpfc_cancel_retry_delay_tmo(phba, ndlp);
lpfc_cancel_retry_delay_tmo(vport, ndlp);
} else
ndlp = NULL;
} else {
if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE ||
ndlp->nlp_state == NLP_STE_PLOGI_ISSUE)
return NULL;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
}
return ndlp;
}
/* Build a list of nodes to discover based on the loopmap */
void
lpfc_disc_list_loopmap(struct lpfc_hba * phba)
lpfc_disc_list_loopmap(struct lpfc_vport *vport)
{
struct lpfc_hba *phba = vport->phba;
int j;
uint32_t alpa, index;
if (phba->hba_state <= LPFC_LINK_DOWN) {
if (!lpfc_is_link_up(phba))
return;
}
if (phba->fc_topology != TOPOLOGY_LOOP) {
if (phba->fc_topology != TOPOLOGY_LOOP)
return;
}
/* Check for loop map present or not */
if (phba->alpa_map[0]) {
for (j = 1; j <= phba->alpa_map[0]; j++) {
alpa = phba->alpa_map[j];
if (((phba->fc_myDID & 0xff) == alpa) || (alpa == 0)) {
if (((vport->fc_myDID & 0xff) == alpa) || (alpa == 0))
continue;
}
lpfc_setup_disc_node(phba, alpa);
lpfc_setup_disc_node(vport, alpa);
}
} else {
/* No alpamap, so try all alpa's */
......@@ -1776,113 +1829,139 @@ lpfc_disc_list_loopmap(struct lpfc_hba * phba)
else
index = FC_MAXLOOP - j - 1;
alpa = lpfcAlpaArray[index];
if ((phba->fc_myDID & 0xff) == alpa) {
if ((vport->fc_myDID & 0xff) == alpa)
continue;
}
lpfc_setup_disc_node(phba, alpa);
lpfc_setup_disc_node(vport, alpa);
}
}
return;
}
/* Start Link up / RSCN discovery on NPR list */
void
lpfc_disc_start(struct lpfc_hba * phba)
lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport)
{
struct lpfc_sli *psli;
LPFC_MBOXQ_t *mbox;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *extra_ring = &psli->ring[psli->extra_ring];
struct lpfc_sli_ring *fcp_ring = &psli->ring[psli->fcp_ring];
struct lpfc_sli_ring *next_ring = &psli->ring[psli->next_ring];
int rc;
/* Link up discovery */
if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) != NULL) {
phba->link_state = LPFC_CLEAR_LA;
lpfc_clear_la(phba, mbox);
mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
mbox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT |
MBX_STOP_IOCB));
if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
lpfc_disc_flush_list(vport);
extra_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
fcp_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
next_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
vport->port_state = LPFC_VPORT_READY;
}
}
}
/* Start Link up / RSCN discovery on NPR nodes */
void
lpfc_disc_start(struct lpfc_vport *vport)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp, *next_ndlp;
uint32_t num_sent;
uint32_t clear_la_pending;
int did_changed;
int rc;
psli = &phba->sli;
if (phba->hba_state <= LPFC_LINK_DOWN) {
if (!lpfc_is_link_up(phba))
return;
}
if (phba->hba_state == LPFC_CLEAR_LA)
if (phba->link_state == LPFC_CLEAR_LA)
clear_la_pending = 1;
else
clear_la_pending = 0;
if (phba->hba_state < LPFC_HBA_READY) {
phba->hba_state = LPFC_DISC_AUTH;
}
lpfc_set_disctmo(phba);
if (vport->port_state < LPFC_VPORT_READY)
vport->port_state = LPFC_DISC_AUTH;
if (phba->fc_prevDID == phba->fc_myDID) {
lpfc_set_disctmo(vport);
if (vport->fc_prevDID == vport->fc_myDID)
did_changed = 0;
} else {
else
did_changed = 1;
}
phba->fc_prevDID = phba->fc_myDID;
phba->num_disc_nodes = 0;
vport->fc_prevDID = vport->fc_myDID;
vport->num_disc_nodes = 0;
/* Start Discovery state <hba_state> */
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
"%d:0202 Start Discovery hba state x%x "
"Data: x%x x%x x%x\n",
phba->brd_no, phba->hba_state, phba->fc_flag,
phba->fc_plogi_cnt, phba->fc_adisc_cnt);
phba->brd_no, vport->port_state, vport->fc_flag,
vport->fc_plogi_cnt, vport->fc_adisc_cnt);
/* If our did changed, we MUST do PLOGI */
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
(ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
did_changed) {
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
}
}
/* First do ADISCs - if any */
num_sent = lpfc_els_disc_adisc(phba);
num_sent = lpfc_els_disc_adisc(vport);
if (num_sent)
return;
if ((phba->hba_state < LPFC_HBA_READY) && (!clear_la_pending)) {
if (vport->port_state < LPFC_VPORT_READY && !clear_la_pending) {
if (vport->port_type == LPFC_PHYSICAL_PORT) {
/* If we get here, there is nothing to ADISC */
if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
phba->hba_state = LPFC_CLEAR_LA;
lpfc_clear_la(phba, mbox);
mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
rc = lpfc_sli_issue_mbox(phba, mbox,
(MBX_NOWAIT | MBX_STOP_IOCB));
if (rc == MBX_NOT_FINISHED) {
mempool_free( mbox, phba->mbox_mem_pool);
lpfc_disc_flush_list(phba);
psli->ring[(psli->extra_ring)].flag &=
~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->fcp_ring)].flag &=
~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->next_ring)].flag &=
~LPFC_STOP_IOCB_EVENT;
phba->hba_state = LPFC_HBA_READY;
printk(KERN_ERR "%s (%d): do clear_la\n",
__FUNCTION__, __LINE__);
lpfc_issue_clear_la(phba, vport);
} else if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
vport->num_disc_nodes = 0;
/* go thru NPR nodes and issue ELS PLOGIs */
if (vport->fc_npr_cnt)
lpfc_els_disc_plogi(vport);
if (!vport->num_disc_nodes) {
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_NDISC_ACTIVE;
spin_unlock_irq(shost->host_lock);
}
printk(KERN_ERR "%s (%d): vport ready\n",
__FUNCTION__, __LINE__);
vport->port_state = LPFC_VPORT_READY;
}
} else {
/* Next do PLOGIs - if any */
num_sent = lpfc_els_disc_plogi(phba);
num_sent = lpfc_els_disc_plogi(vport);
if (num_sent)
return;
if (phba->fc_flag & FC_RSCN_MODE) {
if (vport->fc_flag & FC_RSCN_MODE) {
/* Check to see if more RSCNs came in while we
* were processing this one.
*/
if ((phba->fc_rscn_id_cnt == 0) &&
(!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
spin_lock_irq(phba->host->host_lock);
phba->fc_flag &= ~FC_RSCN_MODE;
spin_unlock_irq(phba->host->host_lock);
if ((vport->fc_rscn_id_cnt == 0) &&
(!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_RSCN_MODE;
spin_unlock_irq(shost->host_lock);
} else
lpfc_els_handle_rscn(phba);
lpfc_els_handle_rscn(vport);
}
}
return;
......@@ -1893,7 +1972,7 @@ lpfc_disc_start(struct lpfc_hba * phba)
* ring the match the sppecified nodelist.
*/
static void
lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
LIST_HEAD(completions);
struct lpfc_sli *psli;
......@@ -1907,7 +1986,7 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
/* Error matching iocb on txq or txcmplq
* First check the txq.
*/
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
if (iocb->context1 != ndlp) {
continue;
......@@ -1927,36 +2006,36 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
continue;
}
icmd = &iocb->iocb;
if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) ||
(icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) {
if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR ||
icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX) {
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
}
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) {
iocb = list_get_first(&completions, struct lpfc_iocbq, list);
list_del(&iocb->list);
if (iocb->iocb_cmpl) {
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
icmd = &iocb->iocb;
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(iocb->iocb_cmpl) (phba, iocb, iocb);
} else
lpfc_sli_release_iocbq(phba, iocb);
}
}
return;
}
void
lpfc_disc_flush_list(struct lpfc_hba * phba)
lpfc_disc_flush_list(struct lpfc_vport *vport)
{
struct lpfc_nodelist *ndlp, *next_ndlp;
struct lpfc_hba *phba = vport->phba;
if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) {
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
if (vport->fc_plogi_cnt || vport->fc_adisc_cnt) {
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
nlp_listp) {
if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE ||
ndlp->nlp_state == NLP_STE_ADISC_ISSUE) {
......@@ -1985,47 +2064,51 @@ lpfc_disc_flush_list(struct lpfc_hba * phba)
void
lpfc_disc_timeout(unsigned long ptr)
{
struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
struct lpfc_vport *vport = (struct lpfc_vport *) ptr;
struct lpfc_hba *phba = vport->phba;
unsigned long flags = 0;
if (unlikely(!phba))
return;
spin_lock_irqsave(phba->host->host_lock, flags);
if (!(phba->work_hba_events & WORKER_DISC_TMO)) {
phba->work_hba_events |= WORKER_DISC_TMO;
if ((vport->work_port_events & WORKER_DISC_TMO) == 0) {
spin_lock_irqsave(&vport->work_port_lock, flags);
vport->work_port_events |= WORKER_DISC_TMO;
spin_unlock_irqrestore(&vport->work_port_lock, flags);
if (phba->work_wait)
wake_up(phba->work_wait);
}
spin_unlock_irqrestore(phba->host->host_lock, flags);
return;
}
static void
lpfc_disc_timeout_handler(struct lpfc_hba *phba)
lpfc_disc_timeout_handler(struct lpfc_vport *vport)
{
struct lpfc_sli *psli;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_nodelist *ndlp, *next_ndlp;
LPFC_MBOXQ_t *clearlambox, *initlinkmbox;
LPFC_MBOXQ_t *clearlambox, *initlinkmbox;
int rc, clrlaerr = 0;
if (unlikely(!phba))
if (!(vport->fc_flag & FC_DISC_TMO))
return;
if (!(phba->fc_flag & FC_DISC_TMO))
return;
psli = &phba->sli;
spin_lock_irq(phba->host->host_lock);
phba->fc_flag &= ~FC_DISC_TMO;
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_DISC_TMO;
spin_unlock_irq(shost->host_lock);
switch (phba->hba_state) {
printk(KERN_ERR "%s (%d): link_state = %d, port_state = %d\n",
__FUNCTION__, __LINE__, phba->link_state, vport->port_state);
switch (vport->port_state) {
case LPFC_LOCAL_CFG_LINK:
/* hba_state is identically LPFC_LOCAL_CFG_LINK while waiting for FAN */
/* FAN timeout */
/* port_state is identically LPFC_LOCAL_CFG_LINK while waiting for
* FAN
*/
/* FAN timeout */
lpfc_printf_log(phba,
KERN_WARNING,
LOG_DISCOVERY,
......@@ -2033,27 +2116,27 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
phba->brd_no);
/* Start discovery by sending FLOGI, clean up old rpis */
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
nlp_listp) {
if (ndlp->nlp_state != NLP_STE_NPR_NODE)
continue;
if (ndlp->nlp_type & NLP_FABRIC) {
/* Clean up the ndlp on Fabric connections */
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
/* Fail outstanding IO now since device
* is marked for PLOGI.
*/
lpfc_unreg_rpi(phba, ndlp);
lpfc_unreg_rpi(vport, ndlp);
}
}
phba->hba_state = LPFC_FLOGI;
lpfc_set_disctmo(phba);
lpfc_initial_flogi(phba);
vport->port_state = LPFC_FLOGI;
lpfc_set_disctmo(vport);
lpfc_initial_flogi(vport);
break;
case LPFC_FLOGI:
/* hba_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
/* port_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
/* Initial FLOGI timeout */
lpfc_printf_log(phba,
KERN_ERR,
......@@ -2066,10 +2149,10 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
*/
/* FLOGI failed, so just use loop map to make discovery list */
lpfc_disc_list_loopmap(phba);
lpfc_disc_list_loopmap(vport);
/* Start discovery */
lpfc_disc_start(phba);
lpfc_disc_start(vport);
break;
case LPFC_FABRIC_CFG_LINK:
......@@ -2080,11 +2163,11 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
"login\n", phba->brd_no);
/* Next look for NameServer ndlp */
ndlp = lpfc_findnode_did(phba, NameServer_DID);
ndlp = lpfc_findnode_did(vport, NameServer_DID);
if (ndlp)
lpfc_nlp_put(ndlp);
/* Start discovery */
lpfc_disc_start(phba);
lpfc_disc_start(vport);
break;
case LPFC_NS_QRY:
......@@ -2093,17 +2176,17 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
"%d:0224 NameServer Query timeout "
"Data: x%x x%x\n",
phba->brd_no,
phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
ndlp = lpfc_findnode_did(phba, NameServer_DID);
ndlp = lpfc_findnode_did(vport, NameServer_DID);
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
/* Try it one more time */
rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT);
rc = lpfc_ns_cmd(vport, ndlp, SLI_CTNS_GID_FT);
if (rc == 0)
break;
}
phba->fc_ns_retry = 0;
vport->fc_ns_retry = 0;
}
/* Nothing to authenticate, so CLEAR_LA right now */
......@@ -2114,13 +2197,16 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
"%d:0226 Device Discovery "
"completion error\n",
phba->brd_no);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
break;
}
phba->hba_state = LPFC_CLEAR_LA;
phba->link_state = LPFC_CLEAR_LA;
lpfc_clear_la(phba, clearlambox);
printk(KERN_ERR "%s (%d): do clear_la\n",
__FUNCTION__, __LINE__);
clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
clearlambox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, clearlambox,
(MBX_NOWAIT | MBX_STOP_IOCB));
if (rc == MBX_NOT_FINISHED) {
......@@ -2136,7 +2222,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
"%d:0206 Device Discovery "
"completion error\n",
phba->brd_no);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
break;
}
......@@ -2159,7 +2245,8 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
LOG_DISCOVERY,
"%d:0227 Node Authentication timeout\n",
phba->brd_no);
lpfc_disc_flush_list(phba);
lpfc_disc_flush_list(vport);
clearlambox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!clearlambox) {
clrlaerr = 1;
......@@ -2167,12 +2254,15 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
"%d:0207 Device Discovery "
"completion error\n",
phba->brd_no);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
break;
}
phba->hba_state = LPFC_CLEAR_LA;
phba->link_state = LPFC_CLEAR_LA;
lpfc_clear_la(phba, clearlambox);
printk(KERN_ERR "%s (%d): do clear_la\n",
__FUNCTION__, __LINE__);
clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
clearlambox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, clearlambox,
(MBX_NOWAIT | MBX_STOP_IOCB));
if (rc == MBX_NOT_FINISHED) {
......@@ -2181,40 +2271,73 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
}
break;
case LPFC_CLEAR_LA:
/* CLEAR LA timeout */
lpfc_printf_log(phba,
KERN_ERR,
LOG_DISCOVERY,
"%d:0228 CLEAR LA timeout\n",
phba->brd_no);
clrlaerr = 1;
break;
case LPFC_HBA_READY:
if (phba->fc_flag & FC_RSCN_MODE) {
case LPFC_VPORT_READY:
if (vport->fc_flag & FC_RSCN_MODE) {
lpfc_printf_log(phba,
KERN_ERR,
LOG_DISCOVERY,
"%d:0231 RSCN timeout Data: x%x x%x\n",
phba->brd_no,
phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
/* Cleanup any outstanding ELS commands */
lpfc_els_flush_cmd(phba);
lpfc_els_flush_cmd(vport);
lpfc_els_flush_rscn(phba);
lpfc_disc_flush_list(phba);
lpfc_els_flush_rscn(vport);
lpfc_disc_flush_list(vport);
}
break;
case LPFC_STATE_UNKNOWN:
case LPFC_NS_REG:
case LPFC_BUILD_DISC_LIST:
lpfc_printf_log(phba,
KERN_ERR,
LOG_DISCOVERY,
"%d:0229 Unexpected discovery timeout, vport "
"State x%x\n",
vport->port_state,
phba->brd_no);
break;
}
switch (phba->link_state) {
case LPFC_CLEAR_LA:
/* CLEAR LA timeout */
lpfc_printf_log(phba,
KERN_ERR,
LOG_DISCOVERY,
"%d:0228 CLEAR LA timeout\n",
phba->brd_no);
clrlaerr = 1;
break;
case LPFC_LINK_UNKNOWN:
case LPFC_WARM_START:
case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS:
case LPFC_LINK_DOWN:
case LPFC_LINK_UP:
case LPFC_HBA_ERROR:
lpfc_printf_log(phba,
KERN_ERR,
LOG_DISCOVERY,
"%d:0230 Unexpected timeout, hba link "
"state x%x\n",
phba->brd_no, phba->link_state);
clrlaerr = 1;
break;
}
if (clrlaerr) {
lpfc_disc_flush_list(phba);
lpfc_disc_flush_list(vport);
psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
phba->hba_state = LPFC_HBA_READY;
printk(KERN_ERR "%s (%d): vport ready\n",
__FUNCTION__, __LINE__);
vport->port_state = LPFC_VPORT_READY;
}
return;
......@@ -2227,37 +2350,29 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
* handed off to the SLI layer.
*/
void
lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_sli *psli;
MAILBOX_t *mb;
struct lpfc_dmabuf *mp;
struct lpfc_nodelist *ndlp;
psli = &phba->sli;
mb = &pmb->mb;
ndlp = (struct lpfc_nodelist *) pmb->context2;
mp = (struct lpfc_dmabuf *) (pmb->context1);
MAILBOX_t *mb = &pmb->mb;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
struct lpfc_vport *vport = pmb->vport;
pmb->context1 = NULL;
ndlp->nlp_rpi = mb->un.varWords[0];
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
/* Start issuing Fabric-Device Management Interface (FDMI)
* command to 0xfffffa (FDMI well known port)
/*
* Start issuing Fabric-Device Management Interface (FDMI) command to
* 0xfffffa (FDMI well known port) or Delay issuing FDMI command if
* fdmi-on=2 (supporting RPA/hostnmae)
*/
if (phba->cfg_fdmi_on == 1) {
lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
} else {
/*
* Delay issuing FDMI command if fdmi-on=2
* (supporting RPA/hostnmae)
*/
mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
}
if (phba->cfg_fdmi_on == 1)
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
else
mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
/* Mailbox took a reference to the node */
lpfc_nlp_put(ndlp);
......@@ -2283,16 +2398,12 @@ lpfc_filter_by_wwpn(struct lpfc_nodelist *ndlp, void *param)
sizeof(ndlp->nlp_portname)) == 0;
}
/*
* Search node lists for a remote port matching filter criteria
* Caller needs to hold host_lock before calling this routine.
*/
struct lpfc_nodelist *
__lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
__lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
{
struct lpfc_nodelist *ndlp;
list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
if (ndlp->nlp_state != NLP_STE_UNUSED_NODE &&
filter(ndlp, param))
return ndlp;
......@@ -2305,54 +2416,58 @@ __lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
* This routine is used when the caller does NOT have host_lock.
*/
struct lpfc_nodelist *
lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_nodelist *ndlp;
spin_lock_irq(phba->host->host_lock);
ndlp = __lpfc_find_node(phba, filter, param);
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp = __lpfc_find_node(vport, filter, param);
spin_unlock_irq(shost->host_lock);
return ndlp;
}
/*
* This routine looks up the ndlp lists for the given RPI. If rpi found it
* returns the node list pointer else return NULL.
* returns the node list element pointer else return NULL.
*/
struct lpfc_nodelist *
__lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi)
__lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
{
return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi);
return __lpfc_find_node(vport, lpfc_filter_by_rpi, &rpi);
}
struct lpfc_nodelist *
lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_nodelist *ndlp;
spin_lock_irq(phba->host->host_lock);
ndlp = __lpfc_findnode_rpi(phba, rpi);
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp = __lpfc_findnode_rpi(vport, rpi);
spin_unlock_irq(shost->host_lock);
return ndlp;
}
/*
* This routine looks up the ndlp lists for the given WWPN. If WWPN found it
* returns the node list pointer else return NULL.
* returns the node element list pointer else return NULL.
*/
struct lpfc_nodelist *
lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn)
lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_nodelist *ndlp;
spin_lock_irq(phba->host->host_lock);
ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn);
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn);
spin_unlock_irq(shost->host_lock);
return NULL;
}
void
lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint32_t did)
{
memset(ndlp, 0, sizeof (struct lpfc_nodelist));
INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
......@@ -2360,7 +2475,7 @@ lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
ndlp->nlp_DID = did;
ndlp->nlp_phba = phba;
ndlp->vport = vport;
ndlp->nlp_sid = NLP_NO_SID;
INIT_LIST_HEAD(&ndlp->nlp_listp);
kref_init(&ndlp->kref);
......@@ -2372,8 +2487,8 @@ lpfc_nlp_release(struct kref *kref)
{
struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist,
kref);
lpfc_nlp_remove(ndlp->nlp_phba, ndlp);
mempool_free(ndlp, ndlp->nlp_phba->nlp_mem_pool);
lpfc_nlp_remove(ndlp->vport, ndlp);
mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
}
struct lpfc_nodelist *
......
......@@ -312,8 +312,7 @@ struct csp {
#ifdef __BIG_ENDIAN_BITFIELD
uint16_t increasingOffset:1; /* FC Word 1, bit 31 */
uint16_t randomOffset:1; /* FC Word 1, bit 30 */
uint16_t word1Reserved2:1; /* FC Word 1, bit 29 */
uint16_t response_multiple_Nport:1; /* FC Word 1, bit 29 */
uint16_t fPort:1; /* FC Word 1, bit 28 */
uint16_t altBbCredit:1; /* FC Word 1, bit 27 */
uint16_t edtovResolution:1; /* FC Word 1, bit 26 */
......@@ -2178,8 +2177,8 @@ typedef struct {
#define DMP_RSP_OFFSET 0x14 /* word 5 contains first word of rsp */
#define DMP_RSP_SIZE 0x6C /* maximum of 27 words of rsp data */
/* Structure for MB Command CONFIG_PORT (0x88) */
/* Structure for MB Command CONFIG_PORT (0x88) */
typedef struct {
uint32_t pcbLen;
uint32_t pcbLow; /* bit 31:0 of memory based port config block */
......@@ -2742,15 +2741,15 @@ struct lpfc_sli2_slim {
IOCB_t IOCBs[MAX_SLI2_IOCB];
};
/*******************************************************************
This macro check PCI device to allow special handling for LC HBAs.
Parameters:
device : struct pci_dev 's device field
return 1 => TRUE
0 => FALSE
*******************************************************************/
/*
* This function checks PCI device to allow special handling for LC HBAs.
*
* Parameters:
* device : struct pci_dev 's device field
*
* return 1 => TRUE
* 0 => FALSE
*/
static inline int
lpfc_is_LC_HBA(unsigned short device)
{
......
......@@ -49,6 +49,8 @@ static int lpfc_post_rcv_buf(struct lpfc_hba *);
static struct scsi_transport_template *lpfc_transport_template = NULL;
static DEFINE_IDR(lpfc_hba_index);
/************************************************************************/
/* */
/* lpfc_config_port_prep */
......@@ -61,7 +63,7 @@ static DEFINE_IDR(lpfc_hba_index);
/* */
/************************************************************************/
int
lpfc_config_port_prep(struct lpfc_hba * phba)
lpfc_config_port_prep(struct lpfc_hba *phba)
{
lpfc_vpd_t *vp = &phba->vpd;
int i = 0, rc;
......@@ -75,12 +77,12 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
return -ENOMEM;
}
mb = &pmb->mb;
phba->hba_state = LPFC_INIT_MBX_CMDS;
phba->link_state = LPFC_INIT_MBX_CMDS;
if (lpfc_is_LC_HBA(phba->pcidev->device)) {
if (init_key) {
......@@ -112,7 +114,9 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
return -ERESTART;
}
memcpy(phba->wwnn, (char *)mb->un.varRDnvp.nodename,
sizeof (mb->un.varRDnvp.nodename));
sizeof(phba->wwnn));
memcpy(phba->wwpn, (char *)mb->un.varRDnvp.portname,
sizeof(phba->wwpn));
}
/* Setup and issue mailbox READ REV command */
......@@ -212,37 +216,24 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
/* */
/************************************************************************/
int
lpfc_config_port_post(struct lpfc_hba * phba)
lpfc_config_port_post(struct lpfc_hba *phba)
{
struct lpfc_vport *vport = phba->pport;
LPFC_MBOXQ_t *pmb;
MAILBOX_t *mb;
struct lpfc_dmabuf *mp;
struct lpfc_sli *psli = &phba->sli;
uint32_t status, timeout;
int i, j, rc;
int i, j;
int rc;
pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
return -ENOMEM;
}
mb = &pmb->mb;
lpfc_config_link(phba, pmb);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba,
KERN_ERR,
LOG_INIT,
"%d:0447 Adapter failed init, mbxCmd x%x "
"CONFIG_LINK mbxStatus x%x\n",
phba->brd_no,
mb->mbxCommand, mb->mbxStatus);
phba->hba_state = LPFC_HBA_ERROR;
mempool_free( pmb, phba->mbox_mem_pool);
return -EIO;
}
/* Get login parameters for NID. */
lpfc_read_sparam(phba, pmb);
if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
......@@ -253,7 +244,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
"READ_SPARM mbxStatus x%x\n",
phba->brd_no,
mb->mbxCommand, mb->mbxStatus);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
mp = (struct lpfc_dmabuf *) pmb->context1;
mempool_free( pmb, phba->mbox_mem_pool);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
......@@ -263,25 +254,27 @@ lpfc_config_port_post(struct lpfc_hba * phba)
mp = (struct lpfc_dmabuf *) pmb->context1;
memcpy(&phba->fc_sparam, mp->virt, sizeof (struct serv_parm));
memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
pmb->context1 = NULL;
if (phba->cfg_soft_wwnn)
u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
u64_to_wwn(phba->cfg_soft_wwnn,
vport->fc_sparam.nodeName.u.wwn);
if (phba->cfg_soft_wwpn)
u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName,
u64_to_wwn(phba->cfg_soft_wwpn,
vport->fc_sparam.portName.u.wwn);
memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
sizeof (struct lpfc_name));
memcpy(&phba->fc_portname, &phba->fc_sparam.portName,
memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
sizeof (struct lpfc_name));
/* If no serial number in VPD data, use low 6 bytes of WWNN */
/* This should be consolidated into parse_vpd ? - mr */
if (phba->SerialNumber[0] == 0) {
uint8_t *outptr;
outptr = &phba->fc_nodename.u.s.IEEE[0];
outptr = &vport->fc_nodename.u.s.IEEE[0];
for (i = 0; i < 12; i++) {
status = *outptr++;
j = ((status & 0xf0) >> 4);
......@@ -311,7 +304,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
"READ_CONFIG, mbxStatus x%x\n",
phba->brd_no,
mb->mbxCommand, mb->mbxStatus);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
mempool_free( pmb, phba->mbox_mem_pool);
return -EIO;
}
......@@ -348,7 +341,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
phba->cfg_link_speed = LINK_SPEED_AUTO;
}
phba->hba_state = LPFC_LINK_DOWN;
phba->link_state = LPFC_LINK_DOWN;
/* Only process IOCBs on ring 0 till hba_state is READY */
if (psli->ring[psli->extra_ring].cmdringaddr)
......@@ -362,7 +355,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
lpfc_post_rcv_buf(phba);
/* Enable appropriate host interrupts */
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
status = readl(phba->HCregaddr);
status |= HC_MBINT_ENA | HC_ERINT_ENA | HC_LAINT_ENA;
if (psli->num_rings > 0)
......@@ -380,13 +373,13 @@ lpfc_config_port_post(struct lpfc_hba * phba)
writel(status, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
/*
* Setup the ring 0 (els) timeout handler
*/
timeout = phba->fc_ratov << 1;
mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
......@@ -408,7 +401,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
writel(0xffffffff, phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
if (rc != MBX_BUSY)
mempool_free(pmb, phba->mbox_mem_pool);
return -EIO;
......@@ -429,18 +422,20 @@ lpfc_config_port_post(struct lpfc_hba * phba)
/* */
/************************************************************************/
int
lpfc_hba_down_prep(struct lpfc_hba * phba)
lpfc_hba_down_prep(struct lpfc_hba *phba)
{
struct lpfc_vport *vport = phba->pport;
/* Disable interrupts */
writel(0, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
/* Cleanup potential discovery resources */
lpfc_els_flush_rscn(phba);
lpfc_els_flush_cmd(phba);
lpfc_disc_flush_list(phba);
/* Cleanup potential discovery resources */
lpfc_els_flush_rscn(vport);
lpfc_els_flush_cmd(vport);
lpfc_disc_flush_list(vport);
return (0);
return 0;
}
/************************************************************************/
......@@ -453,7 +448,7 @@ lpfc_hba_down_prep(struct lpfc_hba * phba)
/* */
/************************************************************************/
int
lpfc_hba_down_post(struct lpfc_hba * phba)
lpfc_hba_down_post(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
......@@ -486,11 +481,14 @@ lpfc_hba_down_post(struct lpfc_hba * phba)
/* */
/************************************************************************/
void
lpfc_handle_eratt(struct lpfc_hba * phba)
lpfc_handle_eratt(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
struct lpfc_vport *vport = phba->pport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
uint32_t event_data;
/* If the pci channel is offline, ignore possible errors,
* since we cannot communicate with the pci card anyway. */
if (pci_channel_offline(phba->pcidev))
......@@ -504,10 +502,10 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
"Data: x%x x%x x%x\n",
phba->brd_no, phba->work_hs,
phba->work_status[0], phba->work_status[1]);
spin_lock_irq(phba->host->host_lock);
phba->fc_flag |= FC_ESTABLISH_LINK;
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_ESTABLISH_LINK;
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
/*
* Firmware stops when it triggled erratt with HS_FFER6.
......@@ -544,7 +542,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
phba->work_status[0], phba->work_status[1]);
event_data = FC_REG_DUMP_EVENT;
fc_host_post_vendor_event(phba->host, fc_get_event_number(),
fc_host_post_vendor_event(shost, fc_get_event_number(),
sizeof(event_data), (char *) &event_data,
SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
......@@ -552,7 +550,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
lpfc_offline_prep(phba);
lpfc_offline(phba);
lpfc_unblock_mgmt_io(phba);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
lpfc_hba_down_post(phba);
}
}
......@@ -566,9 +564,10 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
/* */
/************************************************************************/
void
lpfc_handle_latt(struct lpfc_hba * phba)
lpfc_handle_latt(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
struct lpfc_vport *vport = phba->pport;
struct lpfc_sli *psli = &phba->sli;
LPFC_MBOXQ_t *pmb;
volatile uint32_t control;
struct lpfc_dmabuf *mp;
......@@ -589,20 +588,21 @@ lpfc_handle_latt(struct lpfc_hba * phba)
rc = -EIO;
/* Cleanup any outstanding ELS commands */
lpfc_els_flush_cmd(phba);
lpfc_els_flush_cmd(vport);
psli->slistat.link_event++;
lpfc_read_la(phba, pmb, mp);
pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
pmb->vport = vport;
rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
if (rc == MBX_NOT_FINISHED)
goto lpfc_handle_latt_free_mbuf;
/* Clear Link Attention in HA REG */
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
writel(HA_LATT, phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return;
......@@ -614,7 +614,7 @@ lpfc_handle_latt(struct lpfc_hba * phba)
mempool_free(pmb, phba->mbox_mem_pool);
lpfc_handle_latt_err_exit:
/* Enable Link attention interrupts */
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
psli->sli_flag |= LPFC_PROCESS_LA;
control = readl(phba->HCregaddr);
control |= HC_LAINT_ENA;
......@@ -624,9 +624,9 @@ lpfc_handle_latt(struct lpfc_hba * phba)
/* Clear Link Attention in HA REG */
writel(HA_LATT, phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
lpfc_linkdown(phba);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
/* The other case is an error from issue_mbox */
if (rc == -ENOMEM)
......@@ -646,7 +646,7 @@ lpfc_handle_latt(struct lpfc_hba * phba)
/* */
/************************************************************************/
static int
lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
{
uint8_t lenlo, lenhi;
int Length;
......@@ -785,7 +785,7 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
}
static void
lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
{
lpfc_vpd_t *vp;
uint16_t dev_id = phba->pcidev->device;
......@@ -943,7 +943,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
/* Returns the number of buffers NOT posted. */
/**************************************************/
int
lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt,
int type)
{
IOCB_t *icmd;
......@@ -955,9 +955,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
/* While there are buffers to post */
while (cnt > 0) {
/* Allocate buffer for command iocb */
spin_lock_irq(phba->host->host_lock);
iocb = lpfc_sli_get_iocbq(phba);
spin_unlock_irq(phba->host->host_lock);
if (iocb == NULL) {
pring->missbufcnt = cnt;
return cnt;
......@@ -972,9 +970,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
&mp1->phys);
if (mp1 == 0 || mp1->virt == 0) {
kfree(mp1);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, iocb);
spin_unlock_irq(phba->host->host_lock);
pring->missbufcnt = cnt;
return cnt;
}
......@@ -990,9 +986,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
kfree(mp2);
lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
kfree(mp1);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, iocb);
spin_unlock_irq(phba->host->host_lock);
pring->missbufcnt = cnt;
return cnt;
}
......@@ -1018,7 +1012,6 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
icmd->ulpCommand = CMD_QUE_RING_BUF64_CN;
icmd->ulpLe = 1;
spin_lock_irq(phba->host->host_lock);
if (lpfc_sli_issue_iocb(phba, pring, iocb, 0) == IOCB_ERROR) {
lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
kfree(mp1);
......@@ -1030,10 +1023,8 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
}
lpfc_sli_release_iocbq(phba, iocb);
pring->missbufcnt = cnt;
spin_unlock_irq(phba->host->host_lock);
return cnt;
}
spin_unlock_irq(phba->host->host_lock);
lpfc_sli_ringpostbuf_put(phba, pring, mp1);
if (mp2) {
lpfc_sli_ringpostbuf_put(phba, pring, mp2);
......@@ -1050,7 +1041,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
/* */
/************************************************************************/
static int
lpfc_post_rcv_buf(struct lpfc_hba * phba)
lpfc_post_rcv_buf(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
......@@ -1151,7 +1142,7 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
{
int t;
uint32_t *HashWorking;
uint32_t *pwwnn = phba->wwnn;
uint32_t *pwwnn = (uint32_t *) phba->wwnn;
HashWorking = kmalloc(80 * sizeof(uint32_t), GFP_KERNEL);
if (!HashWorking)
......@@ -1170,16 +1161,16 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
}
static void
lpfc_cleanup(struct lpfc_hba * phba)
lpfc_cleanup(struct lpfc_vport *vport)
{
struct lpfc_nodelist *ndlp, *next_ndlp;
/* clean up phba - lpfc specific */
lpfc_can_disctmo(phba);
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
lpfc_can_disctmo(vport);
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
lpfc_nlp_put(ndlp);
INIT_LIST_HEAD(&phba->fc_nodes);
INIT_LIST_HEAD(&vport->fc_nodes);
return;
}
......@@ -1187,7 +1178,9 @@ lpfc_cleanup(struct lpfc_hba * phba)
static void
lpfc_establish_link_tmo(unsigned long ptr)
{
struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
struct lpfc_vport *vport = phba->pport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
unsigned long iflag;
......@@ -1195,34 +1188,37 @@ lpfc_establish_link_tmo(unsigned long ptr)
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
"%d:1300 Re-establishing Link, timer expired "
"Data: x%x x%x\n",
phba->brd_no, phba->fc_flag, phba->hba_state);
spin_lock_irqsave(phba->host->host_lock, iflag);
phba->fc_flag &= ~FC_ESTABLISH_LINK;
spin_unlock_irqrestore(phba->host->host_lock, iflag);
phba->brd_no, vport->fc_flag,
vport->port_state);
spin_lock_irqsave(shost->host_lock, iflag);
vport->fc_flag &= ~FC_ESTABLISH_LINK;
spin_unlock_irqrestore(shost->host_lock, iflag);
}
static int
lpfc_stop_timer(struct lpfc_hba * phba)
static void
lpfc_stop_timer(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
struct lpfc_vport *vport = phba->pport;
del_timer_sync(&phba->fcp_poll_timer);
del_timer_sync(&phba->fc_estabtmo);
del_timer_sync(&phba->fc_disctmo);
del_timer_sync(&phba->fc_fdmitmo);
del_timer_sync(&phba->els_tmofunc);
psli = &phba->sli;
del_timer_sync(&psli->mbox_tmo);
return(1);
del_timer_sync(&vport->els_tmofunc);
del_timer_sync(&vport->fc_fdmitmo);
del_timer_sync(&vport->fc_disctmo);
del_timer_sync(&phba->sli.mbox_tmo);
return;
}
int
lpfc_online(struct lpfc_hba * phba)
lpfc_online(struct lpfc_hba *phba)
{
struct lpfc_vport *vport = phba->pport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (!phba)
return 0;
if (!(phba->fc_flag & FC_OFFLINE_MODE))
if (!(vport->fc_flag & FC_OFFLINE_MODE))
return 0;
lpfc_printf_log(phba,
......@@ -1243,9 +1239,9 @@ lpfc_online(struct lpfc_hba * phba)
return 1;
}
spin_lock_irq(phba->host->host_lock);
phba->fc_flag &= ~FC_OFFLINE_MODE;
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_OFFLINE_MODE;
spin_unlock_irq(shost->host_lock);
lpfc_unblock_mgmt_io(phba);
return 0;
......@@ -1256,9 +1252,9 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
{
unsigned long iflag;
spin_lock_irqsave(phba->host->host_lock, iflag);
phba->fc_flag |= FC_BLOCK_MGMT_IO;
spin_unlock_irqrestore(phba->host->host_lock, iflag);
spin_lock_irqsave(&phba->hbalock, iflag);
phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO;
spin_unlock_irqrestore(&phba->hbalock, iflag);
}
void
......@@ -1266,17 +1262,18 @@ lpfc_unblock_mgmt_io(struct lpfc_hba * phba)
{
unsigned long iflag;
spin_lock_irqsave(phba->host->host_lock, iflag);
phba->fc_flag &= ~FC_BLOCK_MGMT_IO;
spin_unlock_irqrestore(phba->host->host_lock, iflag);
spin_lock_irqsave(&phba->hbalock, iflag);
phba->sli.sli_flag &= ~LPFC_BLOCK_MGMT_IO;
spin_unlock_irqrestore(&phba->hbalock, iflag);
}
void
lpfc_offline_prep(struct lpfc_hba * phba)
{
struct lpfc_vport *vport = phba->pport;
struct lpfc_nodelist *ndlp, *next_ndlp;
if (phba->fc_flag & FC_OFFLINE_MODE)
if (vport->fc_flag & FC_OFFLINE_MODE)
return;
lpfc_block_mgmt_io(phba);
......@@ -1284,19 +1281,21 @@ lpfc_offline_prep(struct lpfc_hba * phba)
lpfc_linkdown(phba);
/* Issue an unreg_login to all nodes */
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
lpfc_unreg_rpi(phba, ndlp);
lpfc_unreg_rpi(vport, ndlp);
lpfc_sli_flush_mbox_queue(phba);
}
void
lpfc_offline(struct lpfc_hba * phba)
lpfc_offline(struct lpfc_hba *phba)
{
struct lpfc_vport *vport = phba->pport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
unsigned long iflag;
if (phba->fc_flag & FC_OFFLINE_MODE)
if (vport->fc_flag & FC_OFFLINE_MODE)
return;
/* stop all timers associated with this hba */
......@@ -1311,12 +1310,14 @@ lpfc_offline(struct lpfc_hba * phba)
/* Bring down the SLI Layer and cleanup. The HBA is offline
now. */
lpfc_sli_hba_down(phba);
lpfc_cleanup(phba);
spin_lock_irqsave(phba->host->host_lock, iflag);
phba->work_hba_events = 0;
lpfc_cleanup(vport);
spin_lock_irqsave(shost->host_lock, iflag);
spin_lock(&phba->hbalock);
phba->work_ha = 0;
phba->fc_flag |= FC_OFFLINE_MODE;
spin_unlock_irqrestore(phba->host->host_lock, iflag);
vport->work_port_events = 0;
vport->fc_flag |= FC_OFFLINE_MODE;
spin_unlock(&phba->hbalock);
spin_unlock_irqrestore(shost->host_lock, iflag);
}
/******************************************************************************
......@@ -1326,12 +1327,12 @@ lpfc_offline(struct lpfc_hba * phba)
*
******************************************************************************/
static int
lpfc_scsi_free(struct lpfc_hba * phba)
lpfc_scsi_free(struct lpfc_hba *phba)
{
struct lpfc_scsi_buf *sb, *sb_next;
struct lpfc_iocbq *io, *io_next;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
/* Release all the lpfc_scsi_bufs maintained by this host. */
list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
list_del(&sb->list);
......@@ -1348,130 +1349,158 @@ lpfc_scsi_free(struct lpfc_hba * phba)
phba->total_iocbq_bufs--;
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return 0;
}
void lpfc_remove_device(struct lpfc_hba *phba)
struct lpfc_vport *
lpfc_create_port(struct lpfc_hba *phba, int instance)
{
unsigned long iflag;
lpfc_free_sysfs_attr(phba);
struct lpfc_vport *vport;
struct Scsi_Host *shost;
int error = 0;
spin_lock_irqsave(phba->host->host_lock, iflag);
phba->fc_flag |= FC_UNLOADING;
shost = scsi_host_alloc(&lpfc_template, sizeof(struct lpfc_vport));
if (!shost)
goto out;
spin_unlock_irqrestore(phba->host->host_lock, iflag);
vport = (struct lpfc_vport *) shost->hostdata;
vport->phba = phba;
fc_remove_host(phba->host);
scsi_remove_host(phba->host);
kthread_stop(phba->worker_thread);
vport->load_flag |= FC_LOADING;
shost->unique_id = instance;
shost->max_id = LPFC_MAX_TARGET;
shost->max_lun = phba->cfg_max_luns;
shost->this_id = -1;
shost->max_cmd_len = 16;
/*
* Bring down the SLI Layer. This step disable all interrupts,
* clears the rings, discards all mailbox commands, and resets
* the HBA.
* Set initial can_queue value since 0 is no longer supported and
* scsi_add_host will fail. This will be adjusted later based on the
* max xri value determined in hba setup.
*/
lpfc_sli_hba_down(phba);
lpfc_sli_brdrestart(phba);
shost->can_queue = phba->cfg_hba_queue_depth - 10;
shost->transportt = lpfc_transport_template;
/* Release the irq reservation */
free_irq(phba->pcidev->irq, phba);
pci_disable_msi(phba->pcidev);
/* Initialize all internally managed lists. */
INIT_LIST_HEAD(&vport->fc_nodes);
spin_lock_init(&vport->work_port_lock);
lpfc_cleanup(phba);
lpfc_stop_timer(phba);
phba->work_hba_events = 0;
init_timer(&vport->fc_disctmo);
vport->fc_disctmo.function = lpfc_disc_timeout;
vport->fc_disctmo.data = (unsigned long) vport;
/*
* Call scsi_free before mem_free since scsi bufs are released to their
* corresponding pools here.
*/
lpfc_scsi_free(phba);
lpfc_mem_free(phba);
init_timer(&vport->fc_fdmitmo);
vport->fc_fdmitmo.function = lpfc_fdmi_tmo;
vport->fc_fdmitmo.data = (unsigned long) vport;
/* Free resources associated with SLI2 interface */
dma_free_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,
phba->slim2p, phba->slim2p_mapping);
init_timer(&vport->els_tmofunc);
vport->els_tmofunc.function = lpfc_els_timeout;
vport->els_tmofunc.data = (unsigned long) vport;
/* unmap adapter SLIM and Control Registers */
iounmap(phba->ctrl_regs_memmap_p);
iounmap(phba->slim_memmap_p);
error = scsi_add_host(shost, &phba->pcidev->dev);
if (error)
goto out_put_shost;
pci_release_regions(phba->pcidev);
pci_disable_device(phba->pcidev);
list_add_tail(&vport->listentry, &phba->port_list);
scsi_scan_host(shost);
return vport;
idr_remove(&lpfc_hba_index, phba->brd_no);
scsi_host_put(phba->host);
out_put_shost:
scsi_host_put(shost);
out:
return NULL;
}
void
destroy_port(struct lpfc_vport *vport)
{
lpfc_cleanup(vport);
list_del(&vport->listentry);
lpfc_free_sysfs_attr(vport);
fc_remove_host(lpfc_shost_from_vport(vport));
scsi_remove_host(lpfc_shost_from_vport(vport));
return;
}
void lpfc_scan_start(struct Scsi_Host *host)
static void
lpfc_remove_device(struct lpfc_vport *vport)
{
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
if (lpfc_alloc_sysfs_attr(phba))
goto error;
lpfc_free_sysfs_attr(vport);
phba->MBslimaddr = phba->slim_memmap_p;
phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_UNLOADING;
spin_unlock_irq(shost->host_lock);
fc_remove_host(shost);
scsi_remove_host(shost);
kthread_stop(phba->worker_thread);
}
void lpfc_scan_start(struct Scsi_Host *shost)
{
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
if (lpfc_sli_hba_setup(phba))
if (lpfc_alloc_sysfs_attr(vport))
goto error;
/*
* hba setup may have changed the hba_queue_depth so we need to adjust
* the value of can_queue.
*/
host->can_queue = phba->cfg_hba_queue_depth - 10;
shost->can_queue = phba->cfg_hba_queue_depth - 10;
return;
error:
lpfc_remove_device(phba);
lpfc_remove_device(vport);
}
int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
if (!phba->host)
return 1;
if (time >= 30 * HZ)
if (time >= 30 * HZ) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"%d:0461 Scanning longer than 30 "
"seconds. Continuing initialization\n",
phba->brd_no);
goto finished;
}
if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"%d:0465 Link down longer than 15 "
"seconds. Continuing initialization\n",
phba->brd_no);
goto finished;
}
if (phba->hba_state != LPFC_HBA_READY)
return 0;
if (phba->num_disc_nodes || phba->fc_prli_sent)
if (vport->port_state != LPFC_VPORT_READY)
return 0;
if ((phba->fc_map_cnt == 0) && (time < 2 * HZ))
if (vport->num_disc_nodes || vport->fc_prli_sent)
return 0;
if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)
if (vport->fc_map_cnt == 0 && time < 2 * HZ)
return 0;
if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ))
if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0)
return 0;
finished:
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
spin_lock_irq(shost->host_lock);
lpfc_poll_start_timer(phba);
spin_unlock_irq(shost->host_lock);
}
/*
* set fixed host attributes
* Must done after lpfc_sli_hba_setup()
* Set fixed host attributes. Must done after lpfc_sli_hba_setup().
*/
fc_host_node_name(shost) = wwn_to_u64(phba->fc_nodename.u.wwn);
fc_host_port_name(shost) = wwn_to_u64(phba->fc_portname.u.wwn);
fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
fc_host_supported_classes(shost) = FC_COS_CLASS3;
memset(fc_host_supported_fc4s(shost), 0,
sizeof(fc_host_supported_fc4s(shost)));
sizeof(fc_host_supported_fc4s(shost)));
fc_host_supported_fc4s(shost)[2] = 1;
fc_host_supported_fc4s(shost)[7] = 1;
......@@ -1488,17 +1517,17 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT;
fc_host_maxframe_size(shost) =
((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
(uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);
(((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
(uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
/* This value is also unchanging */
memset(fc_host_active_fc4s(shost), 0,
sizeof(fc_host_active_fc4s(shost)));
sizeof(fc_host_active_fc4s(shost)));
fc_host_active_fc4s(shost)[2] = 1;
fc_host_active_fc4s(shost)[7] = 1;
spin_lock_irq(shost->host_lock);
phba->fc_flag &= ~FC_LOADING;
vport->fc_flag &= ~FC_LOADING;
spin_unlock_irq(shost->host_lock);
return 1;
......@@ -1507,10 +1536,11 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
static int __devinit
lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
{
struct Scsi_Host *host;
struct lpfc_hba *phba;
struct lpfc_sli *psli;
struct lpfc_vport *vport = NULL;
struct lpfc_hba *phba;
struct lpfc_sli *psli;
struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL;
struct Scsi_Host *shost = NULL;
unsigned long bar0map_len, bar2map_len;
int error = -ENODEV, retval;
int i;
......@@ -1521,61 +1551,41 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
goto out_disable_device;
host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));
if (!host)
phba = kzalloc(sizeof (struct lpfc_hba), GFP_KERNEL);
if (!phba)
goto out_release_regions;
phba = (struct lpfc_hba*)host->hostdata;
memset(phba, 0, sizeof (struct lpfc_hba));
phba->host = host;
spin_lock_init(&phba->hbalock);
phba->fc_flag |= FC_LOADING;
phba->pcidev = pdev;
/* Assign an unused board number */
if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
goto out_put_host;
goto out_free_phba;
error = idr_get_new(&lpfc_hba_index, NULL, &phba->brd_no);
if (error)
goto out_put_host;
goto out_free_phba;
INIT_LIST_HEAD(&phba->port_list);
host->unique_id = phba->brd_no;
/*
* Get all the module params for configuring this host and then
* establish the host.
*/
lpfc_get_cfgparam(phba);
/* Initialize timers used by driver */
init_timer(&phba->fc_estabtmo);
phba->fc_estabtmo.function = lpfc_establish_link_tmo;
phba->fc_estabtmo.data = (unsigned long)phba;
init_timer(&phba->fc_disctmo);
phba->fc_disctmo.function = lpfc_disc_timeout;
phba->fc_disctmo.data = (unsigned long)phba;
init_timer(&phba->fc_fdmitmo);
phba->fc_fdmitmo.function = lpfc_fdmi_tmo;
phba->fc_fdmitmo.data = (unsigned long)phba;
init_timer(&phba->els_tmofunc);
phba->els_tmofunc.function = lpfc_els_timeout;
phba->els_tmofunc.data = (unsigned long)phba;
phba->fc_estabtmo.data = (unsigned long) phba;
psli = &phba->sli;
init_timer(&psli->mbox_tmo);
psli->mbox_tmo.function = lpfc_mbox_timeout;
psli->mbox_tmo.data = (unsigned long)phba;
psli->mbox_tmo.data = (unsigned long) phba;
init_timer(&phba->fcp_poll_timer);
phba->fcp_poll_timer.function = lpfc_poll_timeout;
phba->fcp_poll_timer.data = (unsigned long)phba;
/*
* Get all the module params for configuring this host and then
* establish the host parameters.
*/
lpfc_get_cfgparam(phba);
host->max_id = LPFC_MAX_TARGET;
host->max_lun = phba->cfg_max_luns;
host->this_id = -1;
INIT_LIST_HEAD(&phba->fc_nodes);
phba->fcp_poll_timer.data = (unsigned long) phba;
pci_set_master(pdev);
retval = pci_set_mwi(pdev);
......@@ -1653,10 +1663,11 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
error = -ENOMEM;
goto out_free_iocbq;
}
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
list_add(&iocbq_entry->list, &phba->lpfc_iocb_list);
phba->total_iocbq_bufs++;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
}
/* Initialize HBA structure */
......@@ -1677,22 +1688,19 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_free_iocbq;
}
/*
* Set initial can_queue value since 0 is no longer supported and
* scsi_add_host will fail. This will be adjusted later based on the
* max xri value determined in hba setup.
*/
host->can_queue = phba->cfg_hba_queue_depth - 10;
/* Tell the midlayer we support 16 byte commands */
host->max_cmd_len = 16;
/* Initialize the list of scsi buffers used by driver for scsi IO. */
spin_lock_init(&phba->scsi_buf_list_lock);
INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
host->transportt = lpfc_transport_template;
pci_set_drvdata(pdev, host);
vport = lpfc_create_port(phba, phba->brd_no);
if (!vport)
goto out_kthread_stop;
shost = lpfc_shost_from_vport(vport);
vport->port_type = LPFC_PHYSICAL_PORT;
phba->pport = vport;
pci_set_drvdata(pdev, lpfc_shost_from_vport(vport));
if (phba->cfg_use_msi) {
error = pci_enable_msi(phba->pcidev);
......@@ -1703,36 +1711,46 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
}
error = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED,
LPFC_DRIVER_NAME, phba);
LPFC_DRIVER_NAME, phba);
if (error) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"%d:0451 Enable interrupt handler failed\n",
phba->brd_no);
goto out_kthread_stop;
goto out_destroy_port;
}
error = scsi_add_host(host, &pdev->dev);
phba->MBslimaddr = phba->slim_memmap_p;
phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
error = lpfc_sli_hba_setup(phba);
if (error)
goto out_free_irq;
scsi_scan_host(host);
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
spin_lock_irq(shost->host_lock);
lpfc_poll_start_timer(phba);
spin_unlock_irq(shost->host_lock);
}
return 0;
out_free_irq:
lpfc_stop_timer(phba);
phba->work_hba_events = 0;
phba->pport->work_port_events = 0;
free_irq(phba->pcidev->irq, phba);
pci_disable_msi(phba->pcidev);
out_destroy_port:
destroy_port(vport);
out_kthread_stop:
kthread_stop(phba->worker_thread);
out_free_iocbq:
list_for_each_entry_safe(iocbq_entry, iocbq_next,
&phba->lpfc_iocb_list, list) {
spin_lock_irq(phba->host->host_lock);
kfree(iocbq_entry);
phba->total_iocbq_bufs--;
spin_unlock_irq(phba->host->host_lock);
}
lpfc_mem_free(phba);
out_free_slim:
......@@ -1744,9 +1762,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
iounmap(phba->slim_memmap_p);
out_idr_remove:
idr_remove(&lpfc_hba_index, phba->brd_no);
out_put_host:
phba->host = NULL;
scsi_host_put(host);
out_free_phba:
kfree(phba);
out_release_regions:
pci_release_regions(pdev);
out_disable_device:
......@@ -1759,12 +1776,55 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
static void __devexit
lpfc_pci_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *host = pci_get_drvdata(pdev);
struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata;
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
vport->load_flag |= FC_UNLOADING;
lpfc_remove_device(vport);
/*
* Bring down the SLI Layer. This step disable all interrupts,
* clears the rings, discards all mailbox commands, and resets
* the HBA.
*/
lpfc_sli_hba_down(phba);
lpfc_sli_brdrestart(phba);
lpfc_stop_timer(phba);
kthread_stop(phba->worker_thread);
/* Release the irq reservation */
free_irq(phba->pcidev->irq, phba);
pci_disable_msi(phba->pcidev);
lpfc_remove_device(phba);
vport->work_port_events = 0;
destroy_port(vport);
pci_set_drvdata(pdev, NULL);
/*
* Call scsi_free before mem_free since scsi bufs are released to their
* corresponding pools here.
*/
lpfc_scsi_free(phba);
lpfc_mem_free(phba);
/* Free resources associated with SLI2 interface */
dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
phba->slim2p, phba->slim2p_mapping);
/* unmap adapter SLIM and Control Registers */
iounmap(phba->ctrl_regs_memmap_p);
iounmap(phba->slim_memmap_p);
idr_remove(&lpfc_hba_index, phba->brd_no);
kfree(phba);
pci_release_regions(pdev);
pci_disable_device(pdev);
}
/**
......@@ -1822,10 +1882,12 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
pci_set_master(pdev);
/* Re-establishing Link */
spin_lock_irq(phba->host->host_lock);
phba->fc_flag |= FC_ESTABLISH_LINK;
spin_lock_irq(&phba->hbalock);
phba->pport->fc_flag |= FC_ESTABLISH_LINK;
spin_unlock_irq(&phba->hbalock);
spin_lock_irq(host->host_lock);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(host->host_lock);
/* Take device offline; this will perform cleanup */
......@@ -1935,7 +1997,7 @@ static struct pci_driver lpfc_driver = {
.id_table = lpfc_id_table,
.probe = lpfc_pci_probe_one,
.remove = __devexit_p(lpfc_pci_remove_one),
.err_handler = &lpfc_err_handler,
.err_handler = &lpfc_err_handler,
};
static int __init
......
......@@ -106,7 +106,7 @@ lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
*/
pmb->context1 = (uint8_t *) mp;
mb->mbxOwner = OWN_HOST;
return (0);
return 0;
}
/**********************************************/
......@@ -134,6 +134,7 @@ lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
void
lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
struct lpfc_vport *vport = phba->pport;
MAILBOX_t *mb = &pmb->mb;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
......@@ -147,7 +148,7 @@ lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
mb->un.varCfgLnk.cr_count = phba->cfg_cr_count;
}
mb->un.varCfgLnk.myId = phba->fc_myDID;
mb->un.varCfgLnk.myId = vport->fc_myDID;
mb->un.varCfgLnk.edtov = phba->fc_edtov;
mb->un.varCfgLnk.arbtov = phba->fc_arbtov;
mb->un.varCfgLnk.ratov = phba->fc_ratov;
......@@ -208,7 +209,7 @@ lpfc_init_link(struct lpfc_hba * phba,
*/
vpd = &phba->vpd;
if (vpd->rev.feaLevelHigh >= 0x02){
switch(linkspeed){
switch (linkspeed){
case LINK_SPEED_1G:
case LINK_SPEED_2G:
case LINK_SPEED_4G:
......@@ -263,7 +264,7 @@ lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
LOG_MBOX,
"%d:0301 READ_SPARAM: no buffers\n",
phba->brd_no);
return (1);
return 1;
}
INIT_LIST_HEAD(&mp->list);
mb->mbxCommand = MBX_READ_SPARM64;
......@@ -274,7 +275,7 @@ lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
/* save address for completion */
pmb->context1 = mp;
return (0);
return 0;
}
/********************************************/
......@@ -282,7 +283,7 @@ lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
/* mailbox command */
/********************************************/
void
lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
lpfc_unreg_did(struct lpfc_hba *phba, uint32_t did, LPFC_MBOXQ_t *pmb)
{
MAILBOX_t *mb;
......@@ -335,16 +336,13 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
/* mailbox command */
/********************************************/
int
lpfc_reg_login(struct lpfc_hba * phba,
uint32_t did, uint8_t * param, LPFC_MBOXQ_t * pmb, uint32_t flag)
lpfc_reg_login(struct lpfc_hba *phba, uint32_t did, uint8_t *param,
LPFC_MBOXQ_t *pmb, uint32_t flag)
{
MAILBOX_t *mb = &pmb->mb;
uint8_t *sparam;
struct lpfc_dmabuf *mp;
MAILBOX_t *mb;
struct lpfc_sli *psli;
psli = &phba->sli;
mb = &pmb->mb;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
mb->un.varRegLogin.rpi = 0;
......@@ -365,7 +363,7 @@ lpfc_reg_login(struct lpfc_hba * phba,
"%d:0302 REG_LOGIN: no buffers Data x%x x%x\n",
phba->brd_no,
(uint32_t) did, (uint32_t) flag);
return (1);
return 1;
}
INIT_LIST_HEAD(&mp->list);
sparam = mp->virt;
......@@ -381,7 +379,7 @@ lpfc_reg_login(struct lpfc_hba * phba,
mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys);
mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys);
return (0);
return 0;
}
/**********************************************/
......@@ -389,7 +387,7 @@ lpfc_reg_login(struct lpfc_hba * phba,
/* mailbox command */
/**********************************************/
void
lpfc_unreg_login(struct lpfc_hba * phba, uint32_t rpi, LPFC_MBOXQ_t * pmb)
lpfc_unreg_login(struct lpfc_hba *phba, uint32_t rpi, LPFC_MBOXQ_t * pmb)
{
MAILBOX_t *mb;
......@@ -412,14 +410,14 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
PCB_t *pcbp = &phba->slim2p->pcb;
dma_addr_t pdma_addr;
uint32_t offset;
uint32_t iocbCnt;
uint32_t iocbCnt = 0;
int i;
pcbp->maxRing = (psli->num_rings - 1);
iocbCnt = 0;
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
/* A ring MUST have both cmd and rsp entries defined to be
valid */
if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) {
......@@ -462,9 +460,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
void
lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
MAILBOX_t *mb;
mb = &pmb->mb;
MAILBOX_t *mb = &pmb->mb;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
mb->un.varRdRev.cv = 1;
mb->mbxCommand = MBX_READ_REV;
......@@ -644,8 +640,7 @@ lpfc_mbox_get(struct lpfc_hba * phba)
LPFC_MBOXQ_t *mbq = NULL;
struct lpfc_sli *psli = &phba->sli;
list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t,
list);
list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t, list);
if (mbq) {
psli->mboxq_cnt--;
}
......
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
......@@ -38,6 +38,8 @@
#define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */
#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
int
lpfc_mem_alloc(struct lpfc_hba * phba)
{
......@@ -84,6 +86,7 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
fail_free_mbox_pool:
mempool_destroy(phba->mbox_mem_pool);
phba->mbox_mem_pool = NULL;
fail_free_mbuf_pool:
while (i--)
pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
......@@ -91,8 +94,10 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
kfree(pool->elements);
fail_free_lpfc_mbuf_pool:
pci_pool_destroy(phba->lpfc_mbuf_pool);
phba->lpfc_mbuf_pool = NULL;
fail_free_dma_buf_pool:
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
phba->lpfc_scsi_dma_buf_pool = NULL;
fail:
return -ENOMEM;
}
......@@ -106,6 +111,7 @@ lpfc_mem_free(struct lpfc_hba * phba)
struct lpfc_dmabuf *mp;
int i;
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
mp = (struct lpfc_dmabuf *) (mbox->context1);
if (mp) {
......@@ -117,6 +123,7 @@ lpfc_mem_free(struct lpfc_hba * phba)
}
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irq(&phba->hbalock);
if (psli->mbox_active) {
mbox = psli->mbox_active;
mp = (struct lpfc_dmabuf *) (mbox->context1);
......@@ -132,12 +139,18 @@ lpfc_mem_free(struct lpfc_hba * phba)
pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
pool->elements[i].phys);
kfree(pool->elements);
mempool_destroy(phba->nlp_mem_pool);
mempool_destroy(phba->mbox_mem_pool);
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
pci_pool_destroy(phba->lpfc_mbuf_pool);
phba->nlp_mem_pool = NULL;
phba->mbox_mem_pool = NULL;
phba->lpfc_scsi_dma_buf_pool = NULL;
phba->lpfc_mbuf_pool = NULL;
/* Free the iocb lookup array */
kfree(psli->iocbq_lookup);
psli->iocbq_lookup = NULL;
......@@ -148,20 +161,23 @@ void *
lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
{
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
unsigned long iflags;
void *ret;
ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle);
spin_lock_irqsave(&phba->hbalock, iflags);
if (!ret && ( mem_flags & MEM_PRI) && pool->current_count) {
pool->current_count--;
ret = pool->elements[pool->current_count].virt;
*handle = pool->elements[pool->current_count].phys;
}
spin_unlock_irqrestore(&phba->hbalock, iflags);
return ret;
}
void
lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
......@@ -174,3 +190,14 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
}
return;
}
void
lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{
unsigned long iflags;
spin_lock_irqsave(&phba->hbalock, iflags);
__lpfc_mbuf_free(phba, virt, dma);
spin_unlock_irqrestore(&phba->hbalock, iflags);
return;
}
......@@ -39,16 +39,16 @@
/* Called to verify a rcv'ed ADISC was intended for us. */
static int
lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
struct lpfc_name * nn, struct lpfc_name * pn)
lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_name *nn, struct lpfc_name *pn)
{
/* Compare the ADISC rsp WWNN / WWPN matches our internal node
* table entry for that node.
*/
if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)) != 0)
if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)))
return 0;
if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)) != 0)
if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)))
return 0;
/* we match, return success */
......@@ -56,11 +56,10 @@ lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
}
int
lpfc_check_sparm(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, struct serv_parm * sp,
uint32_t class)
lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct serv_parm * sp, uint32_t class)
{
volatile struct serv_parm *hsp = &phba->fc_sparam;
volatile struct serv_parm *hsp = &vport->fc_sparam;
uint16_t hsp_value, ssp_value = 0;
/*
......@@ -128,8 +127,7 @@ lpfc_check_sparm(struct lpfc_hba * phba,
}
static void *
lpfc_check_elscmpl_iocb(struct lpfc_hba * phba,
struct lpfc_iocbq *cmdiocb,
lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
struct lpfc_dmabuf *pcmd, *prsp;
......@@ -168,11 +166,11 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba,
* routine effectively results in a "software abort".
*/
int
lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
LIST_HEAD(completions);
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
struct lpfc_iocbq *iocb, *next_iocb;
IOCB_t *cmd;
......@@ -183,11 +181,8 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, ndlp->nlp_rpi);
psli = &phba->sli;
pring = &psli->ring[LPFC_ELS_RING];
/* First check the txq */
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
/* Check to see if iocb matches the nport we are looking
for */
......@@ -206,32 +201,34 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) {
iocb = list_get_first(&completions, struct lpfc_iocbq, list);
cmd = &iocb->iocb;
list_del(&iocb->list);
if (iocb->iocb_cmpl) {
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(iocb->iocb_cmpl) (phba, iocb, iocb);
} else
lpfc_sli_release_iocbq(phba, iocb);
}
}
/* If we are delaying issuing an ELS command, cancel it */
if (ndlp->nlp_flag & NLP_DELAY_TMO)
lpfc_cancel_retry_delay_tmo(phba, ndlp);
lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
return 0;
}
static int
lpfc_rcv_plogi(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp,
lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_iocbq *cmdiocb)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_dmabuf *pcmd;
uint32_t *lp;
IOCB_t *icmd;
......@@ -241,14 +238,14 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
int rc;
memset(&stat, 0, sizeof (struct ls_rjt));
if (phba->hba_state <= LPFC_FLOGI) {
if (vport->port_state <= LPFC_FLOGI) {
/* Before responding to PLOGI, check for pt2pt mode.
* If we are pt2pt, with an outstanding FLOGI, abort
* the FLOGI and resend it first.
*/
if (phba->fc_flag & FC_PT2PT) {
if (vport->fc_flag & FC_PT2PT) {
lpfc_els_abort_flogi(phba);
if (!(phba->fc_flag & FC_PT2PT_PLOGI)) {
if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
/* If the other side is supposed to initiate
* the PLOGI anyway, just ACC it now and
* move on with discovery.
......@@ -257,14 +254,14 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
phba->fc_ratov = FF_DEF_RATOV;
/* Start discovery - this should just do
CLEAR_LA */
lpfc_disc_start(phba);
lpfc_disc_start(vport);
} else {
lpfc_initial_flogi(phba);
lpfc_initial_flogi(vport);
}
} else {
stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb,
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
ndlp);
return 0;
}
......@@ -272,11 +269,11 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
lp = (uint32_t *) pcmd->virt;
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3) == 0)) {
if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) {
/* Reject this request because invalid parameters */
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
return 0;
}
icmd = &cmdiocb->iocb;
......@@ -290,12 +287,12 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
ndlp->nlp_rpi);
if ((phba->cfg_fcp_class == 2) &&
(sp->cls2.classValid)) {
if (phba->cfg_fcp_class == 2 && sp->cls2.classValid) {
ndlp->nlp_fcp_info |= CLASS2;
} else {
ndlp->nlp_fcp_info |= CLASS3;
}
ndlp->nlp_class_sup = 0;
if (sp->cls1.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS1;
......@@ -317,14 +314,14 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
case NLP_STE_PRLI_ISSUE:
case NLP_STE_UNMAPPED_NODE:
case NLP_STE_MAPPED_NODE:
lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0);
return 1;
}
if ((phba->fc_flag & FC_PT2PT)
&& !(phba->fc_flag & FC_PT2PT_PLOGI)) {
if ((vport->fc_flag & FC_PT2PT)
&& !(vport->fc_flag & FC_PT2PT_PLOGI)) {
/* rcv'ed PLOGI decides what our NPortId will be */
phba->fc_myDID = icmd->un.rcvels.parmRo;
vport->fc_myDID = icmd->un.rcvels.parmRo;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox == NULL)
goto out;
......@@ -337,15 +334,16 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
goto out;
}
lpfc_can_disctmo(phba);
lpfc_can_disctmo(vport);
}
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox == NULL)
if (!mbox)
goto out;
if (lpfc_reg_login(phba, icmd->un.rcvels.remoteID,
(uint8_t *) sp, mbox, 0)) {
mempool_free( mbox, phba->mbox_mem_pool);
rc = lpfc_reg_login(phba, icmd->un.rcvels.remoteID, (uint8_t *) sp,
mbox, 0);
if (rc) {
mempool_free(mbox, phba->mbox_mem_pool);
goto out;
}
......@@ -357,7 +355,10 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
* mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox
* command issued in lpfc_cmpl_els_acc().
*/
mbox->vport = vport;
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
spin_unlock_irq(shost->host_lock);
/*
* If there is an outstanding PLOGI issued, abort it before
......@@ -373,24 +374,24 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
lpfc_els_abort(phba, ndlp);
}
lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
return 1;
out:
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
return 0;
}
static int
lpfc_rcv_padisc(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp,
lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_iocbq *cmdiocb)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_dmabuf *pcmd;
struct serv_parm *sp;
struct lpfc_name *pnn, *ppn;
struct serv_parm *sp;
struct lpfc_name *pnn, *ppn;
struct ls_rjt stat;
ADISC *ap;
IOCB_t *icmd;
......@@ -412,12 +413,11 @@ lpfc_rcv_padisc(struct lpfc_hba * phba,
}
icmd = &cmdiocb->iocb;
if ((icmd->ulpStatus == 0) &&
(lpfc_check_adisc(phba, ndlp, pnn, ppn))) {
if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
if (cmd == ELS_CMD_ADISC) {
lpfc_els_rsp_adisc_acc(phba, cmdiocb, ndlp);
lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
} else {
lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp,
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp,
NULL, 0);
}
return 1;
......@@ -427,55 +427,57 @@ lpfc_rcv_padisc(struct lpfc_hba * phba,
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
stat.un.b.vendorUnique = 0;
lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
/* 1 sec timeout */
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
ndlp->nlp_prev_state = ndlp->nlp_state;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
return 0;
}
static int
lpfc_rcv_logo(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp,
struct lpfc_iocbq *cmdiocb,
uint32_t els_cmd)
lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)
{
/* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
/* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */
/* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
* PLOGIs during LOGO storms from a device.
*/
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_LOGO_ACC;
spin_unlock_irq(shost->host_lock);
if (els_cmd == ELS_CMD_PRLO)
lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
else
lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
if (!(ndlp->nlp_type & NLP_FABRIC) ||
(ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
/* Only try to re-login if this is NOT a Fabric Node */
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
ndlp->nlp_prev_state = ndlp->nlp_state;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
} else {
ndlp->nlp_prev_state = ndlp->nlp_state;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
}
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
/* The driver has to wait until the ACC completes before it continues
* processing the LOGO. The action will resume in
* lpfc_cmpl_els_logo_acc routine. Since part of processing includes an
......@@ -485,9 +487,8 @@ lpfc_rcv_logo(struct lpfc_hba * phba,
}
static void
lpfc_rcv_prli(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp,
struct lpfc_iocbq *cmdiocb)
lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_iocbq *cmdiocb)
{
struct lpfc_dmabuf *pcmd;
uint32_t *lp;
......@@ -522,31 +523,33 @@ lpfc_rcv_prli(struct lpfc_hba * phba,
}
static uint32_t
lpfc_disc_set_adisc(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp)
lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
/* Check config parameter use-adisc or FCP-2 */
if ((phba->cfg_use_adisc == 0) &&
!(phba->fc_flag & FC_RSCN_MODE)) {
if (!(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE))
if (phba->cfg_use_adisc == 0 &&
(vport->fc_flag & FC_RSCN_MODE) == 0 &&
(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) == 0)
return 0;
}
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_ADISC;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
return 1;
}
static uint32_t
lpfc_disc_illegal(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
lpfc_printf_log(phba,
lpfc_printf_log(vport->phba,
KERN_ERR,
LOG_DISCOVERY,
"%d:0253 Illegal State Transition: node x%x event x%x, "
"state x%x Data: x%x x%x\n",
phba->brd_no,
vport->phba->brd_no,
ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
ndlp->nlp_flag);
return ndlp->nlp_state;
......@@ -555,86 +558,82 @@ lpfc_disc_illegal(struct lpfc_hba * phba,
/* Start of Discovery State Machine routines */
static uint32_t
lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
return ndlp->nlp_state;
}
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
static uint32_t
lpfc_rcv_els_unused_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
lpfc_issue_els_logo(phba, ndlp, 0);
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
lpfc_issue_els_logo(vport, ndlp, 0);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_logo_unused_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_LOGO_ACC;
spin_unlock_irq(phba->host->host_lock);
lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
spin_unlock_irq(shost->host_lock);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_logo_unused_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
static uint32_t
lpfc_device_rm_unused_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
static uint32_t
lpfc_rcv_plogi_plogi_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb = arg;
struct lpfc_dmabuf *pcmd;
struct serv_parm *sp;
uint32_t *lp;
struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
uint32_t *lp = (uint32_t *) pcmd->virt;
struct serv_parm *sp = (struct serv_parm *) (lp + 1);
struct ls_rjt stat;
int port_cmp;
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
lp = (uint32_t *) pcmd->virt;
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
memset(&stat, 0, sizeof (struct ls_rjt));
/* For a PLOGI, we only accept if our portname is less
* than the remote portname.
*/
phba->fc_stat.elsLogiCol++;
port_cmp = memcmp(&phba->fc_portname, &sp->portName,
port_cmp = memcmp(&vport->fc_portname, &sp->portName,
sizeof (struct lpfc_name));
if (port_cmp >= 0) {
......@@ -642,64 +641,64 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
ours */
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
} else {
lpfc_rcv_plogi(phba, ndlp, cmdiocb);
} /* if our portname was less */
lpfc_rcv_plogi(vport, ndlp, cmdiocb);
} /* If our portname was less */
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp);
lpfc_els_abort(vport->phba, ndlp);
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp);
if (evt == NLP_EVT_RCV_LOGO) {
lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
} else {
lpfc_issue_els_logo(phba, ndlp, 0);
lpfc_issue_els_logo(vport, ndlp, 0);
}
/* Put ndlp in npr list set plogi timer for 1 sec */
/* Put ndlp in npr state set plogi timer for 1 sec */
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct lpfc_iocbq *cmdiocb, *rspiocb;
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb, *rspiocb;
struct lpfc_dmabuf *pcmd, *prsp, *mp;
uint32_t *lp;
IOCB_t *irsp;
......@@ -721,13 +720,11 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
prsp = list_get_first(&pcmd->list,
struct lpfc_dmabuf,
list);
lp = (uint32_t *) prsp->virt;
prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
lp = (uint32_t *) prsp->virt;
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
if (!lpfc_check_sparm(phba, ndlp, sp, CLASS3))
if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3))
goto out;
/* PLOGI chkparm OK */
......@@ -740,12 +737,11 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
ndlp->nlp_DID, ndlp->nlp_state,
ndlp->nlp_flag, ndlp->nlp_rpi);
if ((phba->cfg_fcp_class == 2) &&
(sp->cls2.classValid)) {
if (phba->cfg_fcp_class == 2 && (sp->cls2.classValid))
ndlp->nlp_fcp_info |= CLASS2;
} else {
else
ndlp->nlp_fcp_info |= CLASS3;
}
ndlp->nlp_class_sup = 0;
if (sp->cls1.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS1;
......@@ -756,14 +752,14 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
if (sp->cls4.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS4;
ndlp->nlp_maxframe =
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
sp->cmn.bbRcvSizeLsb;
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
if (!(mbox = mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL)))
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox)
goto out;
lpfc_unreg_rpi(phba, ndlp);
lpfc_unreg_rpi(vport, ndlp);
if (lpfc_reg_login(phba, irsp->un.elsreq64.remoteID, (uint8_t *) sp,
mbox, 0) == 0) {
switch (ndlp->nlp_DID) {
......@@ -777,10 +773,12 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
}
mbox->context2 = lpfc_nlp_get(ndlp);
mbox->vport = vport;
if (lpfc_sli_issue_mbox(phba, mbox,
(MBX_NOWAIT | MBX_STOP_IOCB))
!= MBX_NOT_FINISHED) {
lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
lpfc_nlp_set_state(vport, ndlp,
NLP_STE_REG_LOGIN_ISSUE);
return ndlp->nlp_state;
}
lpfc_nlp_put(ndlp);
......@@ -796,49 +794,56 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
out:
/* Free this node since the driver cannot login or has the wrong
sparm */
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
static uint32_t
lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NODEV_REMOVE;
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
else {
} else {
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp);
lpfc_els_abort(vport->phba, ndlp);
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
}
static uint32_t
lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_device_recov_plogi_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp);
ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb;
/* software abort outstanding ADISC */
......@@ -846,34 +851,31 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;
if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
if (lpfc_rcv_plogi(vport, ndlp, cmdiocb))
return ndlp->nlp_state;
}
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prli_adisc_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_prli_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_logo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
......@@ -881,42 +883,43 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
/* software abort outstanding ADISC */
lpfc_els_abort(phba, ndlp);
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_padisc_adisc_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_padisc_adisc_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_padisc(phba, ndlp, cmdiocb);
lpfc_rcv_padisc(vport, ndlp, cmdiocb);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_prlo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
/* Treat like rcv logo */
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb, *rspiocb;
IOCB_t *irsp;
ADISC *ap;
......@@ -928,101 +931,107 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba,
irsp = &rspiocb->iocb;
if ((irsp->ulpStatus) ||
(!lpfc_check_adisc(phba, ndlp, &ap->nodeName, &ap->portName))) {
(!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
/* 1 sec timeout */
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
memset(&ndlp->nlp_nodename, 0, sizeof (struct lpfc_name));
memset(&ndlp->nlp_portname, 0, sizeof (struct lpfc_name));
memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name));
memset(&ndlp->nlp_portname, 0, sizeof(struct lpfc_name));
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
lpfc_unreg_rpi(phba, ndlp);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
lpfc_unreg_rpi(vport, ndlp);
return ndlp->nlp_state;
}
if (ndlp->nlp_type & NLP_FCP_TARGET) {
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
} else {
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
}
return ndlp->nlp_state;
}
static uint32_t
lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NODEV_REMOVE;
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
else {
} else {
/* software abort outstanding ADISC */
lpfc_els_abort(phba, ndlp);
lpfc_els_abort(vport->phba, ndlp);
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
}
static uint32_t
lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_device_recov_adisc_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
/* software abort outstanding ADISC */
lpfc_els_abort(phba, ndlp);
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(phba->host->host_lock);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
ndlp->nlp_flag |= NLP_NPR_ADISC;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_plogi_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
lpfc_rcv_plogi_reglogin_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_plogi(phba, ndlp, cmdiocb);
lpfc_rcv_plogi(vport, ndlp, cmdiocb);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prli_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
LPFC_MBOXQ_t *mb;
LPFC_MBOXQ_t *nextmb;
struct lpfc_dmabuf *mp;
......@@ -1038,7 +1047,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
}
}
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
(ndlp == (struct lpfc_nodelist *) mb->context2)) {
......@@ -1051,49 +1060,49 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
mempool_free(mb, phba->mbox_mem_pool);
}
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_padisc_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
lpfc_rcv_padisc_reglogin_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_padisc(phba, ndlp, cmdiocb);
lpfc_rcv_padisc(vport, ndlp, cmdiocb);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp,
void *arg, uint32_t evt)
lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
LPFC_MBOXQ_t *pmb;
MAILBOX_t *mb;
uint32_t did;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
MAILBOX_t *mb = &pmb->mb;
uint32_t did = mb->un.varWords[1];
pmb = (LPFC_MBOXQ_t *) arg;
mb = &pmb->mb;
did = mb->un.varWords[1];
if (mb->mbxStatus) {
/* RegLogin failed */
lpfc_printf_log(phba,
......@@ -1101,7 +1110,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
LOG_DISCOVERY,
"%d:0246 RegLogin failed Data: x%x x%x x%x\n",
phba->brd_no,
did, mb->mbxStatus, phba->hba_state);
did, mb->mbxStatus, vport->port_state);
/*
* If RegLogin failed due to lack of HBA resources do not
......@@ -1109,20 +1118,20 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
*/
if (mb->mbxStatus == MBXERR_RPI_FULL) {
ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
return ndlp->nlp_state;
}
/* Put ndlp in npr list set plogi timer for 1 sec */
/* Put ndlp in npr state set plogi timer for 1 sec */
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
lpfc_issue_els_logo(phba, ndlp, 0);
lpfc_issue_els_logo(vport, ndlp, 0);
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
return ndlp->nlp_state;
}
......@@ -1131,91 +1140,92 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
/* Only if we are not a fabric nport do we issue PRLI */
if (!(ndlp->nlp_type & NLP_FABRIC)) {
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
lpfc_issue_els_prli(phba, ndlp, 0);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
lpfc_issue_els_prli(vport, ndlp, 0);
} else {
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
}
return ndlp->nlp_state;
}
static uint32_t
lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NODEV_REMOVE;
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
else {
lpfc_drop_node(phba, ndlp);
} else {
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
}
static uint32_t
lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(phba->host->host_lock);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_plogi_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_plogi_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_plogi(phba, ndlp, cmdiocb);
lpfc_rcv_plogi(vport, ndlp, cmdiocb);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prli_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_logo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
/* Software abort outstanding PRLI before sending acc */
lpfc_els_abort(phba, ndlp);
lpfc_els_abort(vport->phba, ndlp);
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_padisc_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_padisc_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_padisc(phba, ndlp, cmdiocb);
lpfc_rcv_padisc(vport, ndlp, cmdiocb);
return ndlp->nlp_state;
}
......@@ -1225,21 +1235,21 @@ lpfc_rcv_padisc_prli_issue(struct lpfc_hba * phba,
* NEXT STATE = PRLI_ISSUE
*/
static uint32_t
lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb, *rspiocb;
struct lpfc_hba *phba = vport->phba;
IOCB_t *irsp;
PRLI *npr;
......@@ -1250,7 +1260,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
irsp = &rspiocb->iocb;
if (irsp->ulpStatus) {
ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
return ndlp->nlp_state;
}
......@@ -1268,7 +1278,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
}
ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
return ndlp->nlp_state;
}
......@@ -1286,22 +1296,25 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
* This routine is envoked when we a request to remove a nport we are in the
* process of PRLIing. We should software abort outstanding prli, unreg
* login, send a logout. We will change node state to UNUSED_NODE, put it
* on plogi list so it can be freed when LOGO completes.
* in plogi state so it can be freed when LOGO completes.
*
*/
static uint32_t
lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NODEV_REMOVE;
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
else {
} else {
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp);
lpfc_els_abort(vport->phba, ndlp);
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
}
......@@ -1324,261 +1337,247 @@ lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
* outstanding PRLI command, then free the node entry.
*/
static uint32_t
lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_device_recov_prli_issue(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
/* software abort outstanding PRLI */
lpfc_els_abort(phba, ndlp);
ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(phba->host->host_lock);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_plogi_unmap_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_plogi(phba, ndlp, cmdiocb);
lpfc_rcv_plogi(vport, ndlp, cmdiocb);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prli_unmap_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_prli_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_prli(phba, ndlp, cmdiocb);
lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
lpfc_rcv_prli(vport, ndlp, cmdiocb);
lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_logo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_padisc_unmap_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_padisc_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_padisc(phba, ndlp, cmdiocb);
lpfc_rcv_padisc(vport, ndlp, cmdiocb);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
return ndlp->nlp_state;
}
static uint32_t
lpfc_device_recov_unmap_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_device_recov_unmap_node(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
lpfc_disc_set_adisc(phba, ndlp);
spin_unlock_irq(shost->host_lock);
lpfc_disc_set_adisc(vport, ndlp);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_plogi_mapped_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_plogi_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_plogi(phba, ndlp, cmdiocb);
lpfc_rcv_plogi(vport, ndlp, cmdiocb);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prli_mapped_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_prli_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_logo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_padisc_mapped_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_padisc_mapped_node(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_padisc(phba, ndlp, cmdiocb);
lpfc_rcv_padisc(vport, ndlp, cmdiocb);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
/* flush the target */
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
/* Treat like rcv logo */
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
return ndlp->nlp_state;
}
static uint32_t
lpfc_device_recov_mapped_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_device_recov_mapped_node(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
uint32_t evt)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(phba->host->host_lock);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
lpfc_disc_set_adisc(phba, ndlp);
spin_unlock_irq(shost->host_lock);
lpfc_disc_set_adisc(vport, ndlp);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
/* Ignore PLOGI if we have an outstanding LOGO */
if (ndlp->nlp_flag & NLP_LOGO_SND) {
return ndlp->nlp_state;
}
if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
spin_lock_irq(phba->host->host_lock);
if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
/* send PLOGI immediately, move to PLOGI issue state */
if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
}
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prli_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct ls_rjt stat;
cmdiocb = (struct lpfc_iocbq *) arg;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
struct ls_rjt stat;
memset(&stat, 0, sizeof (struct ls_rjt));
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
if (ndlp->nlp_flag & NLP_NPR_ADISC) {
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
spin_unlock_irq(phba->host->host_lock);
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
lpfc_issue_els_adisc(phba, ndlp, 0);
spin_unlock_irq(shost->host_lock);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
lpfc_issue_els_adisc(vport, ndlp, 0);
} else {
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
}
}
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_logo_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_rcv_padisc(phba, ndlp, cmdiocb);
lpfc_rcv_padisc(vport, ndlp, cmdiocb);
/*
* Do not start discovery if discovery is about to start
......@@ -1586,53 +1585,51 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
* here will affect the counting of discovery threads.
*/
if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
!(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
!(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
if (ndlp->nlp_flag & NLP_NPR_ADISC) {
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
lpfc_issue_els_adisc(phba, ndlp, 0);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
lpfc_issue_els_adisc(vport, ndlp, 0);
} else {
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
}
}
return ndlp->nlp_state;
}
static uint32_t
lpfc_rcv_prlo_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
cmdiocb = (struct lpfc_iocbq *) arg;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_LOGO_ACC;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
} else {
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
}
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb, *rspiocb;
IOCB_t *irsp;
......@@ -1642,15 +1639,15 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
irsp = &rspiocb->iocb;
if (irsp->ulpStatus) {
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb, *rspiocb;
IOCB_t *irsp;
......@@ -1660,25 +1657,24 @@ lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
irsp = &rspiocb->iocb;
if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_logo_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
lpfc_unreg_rpi(phba, ndlp);
lpfc_unreg_rpi(vport, ndlp);
/* This routine does nothing, just return the current state */
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb, *rspiocb;
IOCB_t *irsp;
......@@ -1688,28 +1684,25 @@ lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
irsp = &rspiocb->iocb;
if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
return ndlp->nlp_state;
}
static uint32_t
lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
LPFC_MBOXQ_t *pmb;
MAILBOX_t *mb;
pmb = (LPFC_MBOXQ_t *) arg;
mb = &pmb->mb;
LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
MAILBOX_t *mb = &pmb->mb;
if (!mb->mbxStatus)
ndlp->nlp_rpi = mb->un.varWords[0];
else {
if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
}
......@@ -1717,28 +1710,32 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
}
static uint32_t
lpfc_device_rm_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NODEV_REMOVE;
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
}
lpfc_drop_node(phba, ndlp);
lpfc_drop_node(vport, ndlp);
return NLP_STE_FREED_NODE;
}
static uint32_t
lpfc_device_recov_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
spin_lock_irq(phba->host->host_lock);
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(shost->host_lock);
if (ndlp->nlp_flag & NLP_DELAY_TMO) {
lpfc_cancel_retry_delay_tmo(phba, ndlp);
lpfc_cancel_retry_delay_tmo(vport, ndlp);
}
return ndlp->nlp_state;
}
......@@ -1801,7 +1798,7 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba,
*/
static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
(struct lpfc_hba *, struct lpfc_nodelist *, void *, uint32_t) = {
(struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t) = {
/* Action routine Event Current State */
lpfc_rcv_plogi_unused_node, /* RCV_PLOGI UNUSED_NODE */
lpfc_rcv_els_unused_node, /* RCV_PRLI */
......@@ -1917,11 +1914,12 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
};
int
lpfc_disc_state_machine(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
struct lpfc_hba *phba = vport->phba;
uint32_t cur_state, rc;
uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *,
uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *,
uint32_t);
lpfc_nlp_get(ndlp);
......@@ -1937,7 +1935,7 @@ lpfc_disc_state_machine(struct lpfc_hba * phba,
evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
rc = (func) (phba, ndlp, arg, evt);
rc = (func) (vport, ndlp, arg, evt);
/* DSM out state <rc> on NPort <nlp_DID> */
lpfc_printf_log(phba,
......
......@@ -41,7 +41,6 @@
#define LPFC_RESET_WAIT 2
#define LPFC_ABORT_WAIT 2
/*
* This routine allocates a scsi buffer, which contains all the necessary
* information needed to initiate a SCSI I/O. The non-DMAable buffer region
......@@ -51,8 +50,9 @@
* and the BPL BDE is setup in the IOCB.
*/
static struct lpfc_scsi_buf *
lpfc_new_scsi_buf(struct lpfc_hba * phba)
lpfc_new_scsi_buf(struct lpfc_vport *vport)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_scsi_buf *psb;
struct ulp_bde64 *bpl;
IOCB_t *iocb;
......@@ -63,7 +63,6 @@ lpfc_new_scsi_buf(struct lpfc_hba * phba)
if (!psb)
return NULL;
memset(psb, 0, sizeof (struct lpfc_scsi_buf));
psb->scsi_hba = phba;
/*
* Get memory from the pci pool to map the virt space to pci bus space
......@@ -292,12 +291,13 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
}
static void
lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb)
lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
struct lpfc_iocbq *rsp_iocb)
{
struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
struct lpfc_hba *phba = lpfc_cmd->scsi_hba;
struct lpfc_hba *phba = vport->phba;
uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
uint32_t resp_info = fcprsp->rspStatus2;
uint32_t scsi_status = fcprsp->rspStatus3;
......@@ -429,6 +429,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
{
struct lpfc_scsi_buf *lpfc_cmd =
(struct lpfc_scsi_buf *) pIocbIn->context1;
struct lpfc_vport *vport = pIocbIn->vport;
struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
struct lpfc_nodelist *pnode = rdata->pnode;
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
......@@ -457,7 +458,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
switch (lpfc_cmd->status) {
case IOSTAT_FCP_RSP_ERROR:
/* Call FCP RSP handler to determine result */
lpfc_handle_fcp_err(lpfc_cmd,pIocbOut);
lpfc_handle_fcp_err(vport, lpfc_cmd, pIocbOut);
break;
case IOSTAT_NPORT_BSY:
case IOSTAT_FABRIC_BSY:
......@@ -534,7 +535,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
tmp_sdev->queue_depth - 1);
}
/*
* The queue depth cannot be lowered any more.
* The queue depth cannot be lowered any more.
* Modify the returned error code to store
* the final depth value set by
* scsi_track_queue_full.
......@@ -553,9 +554,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
}
static void
lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
struct lpfc_nodelist *pnode)
lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
struct lpfc_nodelist *pnode)
{
struct lpfc_hba *phba = vport->phba;
struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
......@@ -642,15 +644,15 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
piocbq->context1 = lpfc_cmd;
piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl;
piocbq->iocb.ulpTimeout = lpfc_cmd->timeout;
piocbq->vport = vport;
}
static int
lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
struct lpfc_scsi_buf *lpfc_cmd,
unsigned int lun,
uint8_t task_mgmt_cmd)
{
struct lpfc_sli *psli;
struct lpfc_iocbq *piocbq;
IOCB_t *piocb;
struct fcp_cmnd *fcp_cmnd;
......@@ -661,8 +663,9 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
return 0;
}
psli = &phba->sli;
piocbq = &(lpfc_cmd->cur_iocbq);
piocbq->vport = vport;
piocb = &piocbq->iocb;
fcp_cmnd = lpfc_cmd->fcp_cmnd;
......@@ -688,7 +691,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
piocb->ulpTimeout = lpfc_cmd->timeout;
}
return (1);
return 1;
}
static void
......@@ -704,10 +707,11 @@ lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba,
}
static int
lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
unsigned tgt_id, unsigned int lun,
struct lpfc_rport_data *rdata)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *iocbq;
struct lpfc_iocbq *iocbqrsp;
int ret;
......@@ -716,12 +720,11 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
return FAILED;
lpfc_cmd->rdata = rdata;
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun,
ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun,
FCP_TARGET_RESET);
if (!ret)
return FAILED;
lpfc_cmd->scsi_hba = phba;
iocbq = &lpfc_cmd->cur_iocbq;
iocbqrsp = lpfc_sli_get_iocbq(phba);
......@@ -758,7 +761,8 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
const char *
lpfc_info(struct Scsi_Host *host)
{
struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata;
struct lpfc_vport *vport = (struct lpfc_vport *) host->hostdata;
struct lpfc_hba *phba = vport->phba;
int len;
static char lpfcinfobuf[384];
......@@ -800,26 +804,22 @@ void lpfc_poll_start_timer(struct lpfc_hba * phba)
void lpfc_poll_timeout(unsigned long ptr)
{
struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
unsigned long iflag;
spin_lock_irqsave(phba->host->host_lock, iflag);
struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_poll_fcp_ring (phba);
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_poll_rearm_timer(phba);
}
spin_unlock_irqrestore(phba->host->host_lock, iflag);
}
static int
lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
{
struct lpfc_hba *phba =
(struct lpfc_hba *) cmnd->device->host->hostdata;
struct lpfc_sli *psli = &phba->sli;
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_rport_data *rdata = cmnd->device->hostdata;
struct lpfc_nodelist *ndlp = rdata->pnode;
struct lpfc_scsi_buf *lpfc_cmd;
......@@ -862,7 +862,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
if (err)
goto out_host_busy_free_buf;
lpfc_scsi_prep_cmnd(phba, lpfc_cmd, ndlp);
lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
err = lpfc_sli_issue_iocb(phba, &phba->sli.ring[psli->fcp_ring],
&lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
......@@ -907,8 +907,9 @@ lpfc_block_error_handler(struct scsi_cmnd *cmnd)
static int
lpfc_abort_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
struct lpfc_iocbq *iocb;
struct lpfc_iocbq *abtsiocb;
......@@ -918,8 +919,6 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
int ret = SUCCESS;
lpfc_block_error_handler(cmnd);
spin_lock_irq(shost->host_lock);
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
BUG_ON(!lpfc_cmd);
......@@ -956,12 +955,13 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
icmd->ulpLe = 1;
icmd->ulpClass = cmd->ulpClass;
if (phba->hba_state >= LPFC_LINK_UP)
if (lpfc_is_link_up(phba))
icmd->ulpCommand = CMD_ABORT_XRI_CN;
else
icmd->ulpCommand = CMD_CLOSE_XRI_CN;
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
abtsiocb->vport = vport;
if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == IOCB_ERROR) {
lpfc_sli_release_iocbq(phba, abtsiocb);
ret = FAILED;
......@@ -977,9 +977,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_sli_poll_fcp_ring (phba);
spin_unlock_irq(phba->host->host_lock);
schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
schedule_timeout_uninterruptible(LPFC_ABORT_WAIT * HZ);
if (++loop_count
> (2 * phba->cfg_devloss_tmo)/LPFC_ABORT_WAIT)
break;
......@@ -1002,16 +1000,15 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
phba->brd_no, ret, cmnd->device->id,
cmnd->device->lun, cmnd->serial_number);
spin_unlock_irq(shost->host_lock);
return ret;
}
static int
lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_scsi_buf *lpfc_cmd;
struct lpfc_iocbq *iocbq, *iocbqrsp;
struct lpfc_rport_data *rdata = cmnd->device->hostdata;
......@@ -1022,7 +1019,6 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
int cnt, loopcnt;
lpfc_block_error_handler(cmnd);
spin_lock_irq(shost->host_lock);
loopcnt = 0;
/*
* If target is not in a MAPPED state, delay the reset until
......@@ -1033,9 +1029,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
goto out;
if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
spin_unlock_irq(phba->host->host_lock);
schedule_timeout_uninterruptible(msecs_to_jiffies(500));
spin_lock_irq(phba->host->host_lock);
loopcnt++;
rdata = cmnd->device->hostdata;
if (!rdata ||
......@@ -1054,15 +1048,14 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
break;
}
lpfc_cmd = lpfc_get_scsi_buf (phba);
lpfc_cmd = lpfc_get_scsi_buf(phba);
if (lpfc_cmd == NULL)
goto out;
lpfc_cmd->timeout = 60;
lpfc_cmd->scsi_hba = phba;
lpfc_cmd->rdata = rdata;
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, cmnd->device->lun,
FCP_TARGET_RESET);
if (!ret)
goto out_free_scsi_buf;
......@@ -1110,10 +1103,8 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
cmnd->device->id, cmnd->device->lun,
0, LPFC_CTX_LUN);
loopcnt = 0;
while(cnt) {
spin_unlock_irq(phba->host->host_lock);
while (cnt) {
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
if (++loopcnt
> (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
......@@ -1143,15 +1134,15 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
ret, cmd_status, cmd_result);
out:
spin_unlock_irq(shost->host_lock);
return ret;
}
static int
lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp = NULL;
int match;
int ret = FAILED, i, err_count = 0;
......@@ -1159,7 +1150,6 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
struct lpfc_scsi_buf * lpfc_cmd;
lpfc_block_error_handler(cmnd);
spin_lock_irq(shost->host_lock);
lpfc_cmd = lpfc_get_scsi_buf(phba);
if (lpfc_cmd == NULL)
......@@ -1167,7 +1157,6 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
/* The lpfc_cmd storage is reused. Set all loop invariants. */
lpfc_cmd->timeout = 60;
lpfc_cmd->scsi_hba = phba;
/*
* Since the driver manages a single bus device, reset all
......@@ -1177,7 +1166,8 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
for (i = 0; i < LPFC_MAX_TARGET; i++) {
/* Search for mapped node by target ID */
match = 0;
list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
spin_lock_irq(shost->host_lock);
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
i == ndlp->nlp_sid &&
ndlp->rport) {
......@@ -1185,10 +1175,12 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
break;
}
}
spin_unlock_irq(shost->host_lock);
if (!match)
continue;
ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba, i, cmnd->device->lun,
ret = lpfc_scsi_tgt_reset(lpfc_cmd, vport, i,
cmnd->device->lun,
ndlp->rport->dd_data);
if (ret != SUCCESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
......@@ -1218,10 +1210,8 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
0, 0, 0, LPFC_CTX_HOST);
loopcnt = 0;
while(cnt) {
spin_unlock_irq(phba->host->host_lock);
while (cnt) {
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
if (++loopcnt
> (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
......@@ -1245,14 +1235,14 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
"%d:0714 SCSI layer issued Bus Reset Data: x%x\n",
phba->brd_no, ret);
out:
spin_unlock_irq(shost->host_lock);
return ret;
}
static int
lpfc_slave_alloc(struct scsi_device *sdev)
{
struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata;
struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_scsi_buf *scsi_buf = NULL;
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
uint32_t total = 0, i;
......@@ -1289,7 +1279,7 @@ lpfc_slave_alloc(struct scsi_device *sdev)
}
for (i = 0; i < num_to_alloc; i++) {
scsi_buf = lpfc_new_scsi_buf(phba);
scsi_buf = lpfc_new_scsi_buf(vport);
if (!scsi_buf) {
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0706 Failed to allocate command "
......@@ -1308,8 +1298,9 @@ lpfc_slave_alloc(struct scsi_device *sdev)
static int
lpfc_slave_configure(struct scsi_device *sdev)
{
struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata;
struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
struct lpfc_hba *phba = vport->phba;
struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
if (sdev->tagged_supported)
scsi_activate_tcq(sdev, phba->cfg_lun_queue_depth);
......@@ -1357,6 +1348,6 @@ struct scsi_host_template lpfc_template = {
.sg_tablesize = LPFC_SG_SEG_CNT,
.cmd_per_lun = LPFC_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = lpfc_host_attrs,
.shost_attrs = lpfc_hba_attrs,
.max_sectors = 0xFFFF,
};
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
......@@ -110,7 +110,6 @@ struct fcp_cmnd {
struct lpfc_scsi_buf {
struct list_head list;
struct scsi_cmnd *pCmd;
struct lpfc_hba *scsi_hba;
struct lpfc_rport_data *rdata;
uint32_t timeout;
......
......@@ -52,9 +52,9 @@
"Data: x%x x%x x%x\n", \
phba->brd_no, \
mb->mbxCommand, \
phba->hba_state, \
phba->pport->port_state, \
psli->sli_flag, \
flag);
flag)
/* There are only four IOCB completion types. */
......@@ -65,8 +65,8 @@ typedef enum _lpfc_iocb_type {
LPFC_ABORT_IOCB
} lpfc_iocb_type;
struct lpfc_iocbq *
lpfc_sli_get_iocbq(struct lpfc_hba * phba)
static struct lpfc_iocbq *
__lpfc_sli_get_iocbq(struct lpfc_hba *phba)
{
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_iocbq * iocbq = NULL;
......@@ -75,10 +75,22 @@ lpfc_sli_get_iocbq(struct lpfc_hba * phba)
return iocbq;
}
struct lpfc_iocbq *
lpfc_sli_get_iocbq(struct lpfc_hba *phba)
{
struct lpfc_iocbq * iocbq = NULL;
unsigned long iflags;
spin_lock_irqsave(&phba->hbalock, iflags);
iocbq = __lpfc_sli_get_iocbq(phba);
spin_unlock_irqrestore(&phba->hbalock, iflags);
return iocbq;
}
void
lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
__lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
size_t start_clean = (size_t)(&((struct lpfc_iocbq *)NULL)->iocb);
size_t start_clean = offsetof(struct lpfc_iocbq, iocb);
/*
* Clean all volatile data fields, preserve iotag and node struct.
......@@ -87,6 +99,19 @@ lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
}
void
lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
unsigned long iflags;
/*
* Clean all volatile data fields, preserve iotag and node struct.
*/
spin_lock_irqsave(&phba->hbalock, iflags);
__lpfc_sli_release_iocbq(phba, iocbq);
spin_unlock_irqrestore(&phba->hbalock, iflags);
}
/*
* Translate the iocb command to an iocb command type used to decide the final
* disposition of each completed IOCB.
......@@ -166,14 +191,14 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
}
static int
lpfc_sli_ring_map(struct lpfc_hba * phba, LPFC_MBOXQ_t *pmb)
lpfc_sli_ring_map(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_sli *psli = &phba->sli;
MAILBOX_t *pmbox = &pmb->mb;
int i, rc;
for (i = 0; i < psli->num_rings; i++) {
phba->hba_state = LPFC_INIT_MBX_CMDS;
phba->link_state = LPFC_INIT_MBX_CMDS;
lpfc_config_ring(phba, i, pmb);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) {
......@@ -187,7 +212,7 @@ lpfc_sli_ring_map(struct lpfc_hba * phba, LPFC_MBOXQ_t *pmb)
pmbox->mbxCommand,
pmbox->mbxStatus,
i);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
return -ENXIO;
}
}
......@@ -195,20 +220,20 @@ lpfc_sli_ring_map(struct lpfc_hba * phba, LPFC_MBOXQ_t *pmb)
}
static int
lpfc_sli_ringtxcmpl_put(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocb)
lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb)
{
list_add_tail(&piocb->list, &pring->txcmplq);
pring->txcmplq_cnt++;
if (unlikely(pring->ringno == LPFC_ELS_RING))
mod_timer(&phba->els_tmofunc,
jiffies + HZ * (phba->fc_ratov << 1));
mod_timer(&piocb->vport->els_tmofunc,
jiffies + HZ * (phba->fc_ratov << 1));
return (0);
return 0;
}
static struct lpfc_iocbq *
lpfc_sli_ringtx_get(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
struct list_head *dlp;
struct lpfc_iocbq *cmd_iocb;
......@@ -224,7 +249,7 @@ lpfc_sli_ringtx_get(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
*/
pring->txq_cnt--;
}
return (cmd_iocb);
return cmd_iocb;
}
static IOCB_t *
......@@ -249,7 +274,7 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
phba->brd_no, pring->ringno,
pring->local_getidx, max_cmd_idx);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
/*
* All error attention handlers are posted to
* worker thread
......@@ -272,33 +297,30 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
uint16_t
lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
struct lpfc_iocbq ** new_arr;
struct lpfc_iocbq ** old_arr;
struct lpfc_iocbq **new_arr;
struct lpfc_iocbq **old_arr;
size_t new_len;
struct lpfc_sli *psli = &phba->sli;
uint16_t iotag;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
iotag = psli->last_iotag;
if(++iotag < psli->iocbq_lookup_len) {
psli->last_iotag = iotag;
psli->iocbq_lookup[iotag] = iocbq;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
iocbq->iotag = iotag;
return iotag;
}
else if (psli->iocbq_lookup_len < (0xffff
} else if (psli->iocbq_lookup_len < (0xffff
- LPFC_IOCBQ_LOOKUP_INCREMENT)) {
new_len = psli->iocbq_lookup_len + LPFC_IOCBQ_LOOKUP_INCREMENT;
spin_unlock_irq(phba->host->host_lock);
new_arr = kmalloc(new_len * sizeof (struct lpfc_iocbq *),
spin_unlock_irq(&phba->hbalock);
new_arr = kzalloc(new_len * sizeof (struct lpfc_iocbq *),
GFP_KERNEL);
if (new_arr) {
memset((char *)new_arr, 0,
new_len * sizeof (struct lpfc_iocbq *));
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
old_arr = psli->iocbq_lookup;
if (new_len <= psli->iocbq_lookup_len) {
/* highly unprobable case */
......@@ -307,11 +329,11 @@ lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
if(++iotag < psli->iocbq_lookup_len) {
psli->last_iotag = iotag;
psli->iocbq_lookup[iotag] = iocbq;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
iocbq->iotag = iotag;
return iotag;
}
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
return 0;
}
if (psli->iocbq_lookup)
......@@ -322,13 +344,13 @@ lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
psli->iocbq_lookup_len = new_len;
psli->last_iotag = iotag;
psli->iocbq_lookup[iotag] = iocbq;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
iocbq->iotag = iotag;
kfree(old_arr);
return iotag;
}
} else
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
"%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n",
......@@ -361,7 +383,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (nextiocb->iocb_cmpl)
lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb);
else
lpfc_sli_release_iocbq(phba, nextiocb);
__lpfc_sli_release_iocbq(phba, nextiocb);
/*
* Let the HBA know what IOCB slot will be the next one the
......@@ -373,8 +395,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
static void
lpfc_sli_update_full_ring(struct lpfc_hba * phba,
struct lpfc_sli_ring *pring)
lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
int ringno = pring->ringno;
......@@ -393,8 +414,7 @@ lpfc_sli_update_full_ring(struct lpfc_hba * phba,
}
static void
lpfc_sli_update_ring(struct lpfc_hba * phba,
struct lpfc_sli_ring *pring)
lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
int ringno = pring->ringno;
......@@ -407,7 +427,7 @@ lpfc_sli_update_ring(struct lpfc_hba * phba,
}
static void
lpfc_sli_resume_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
IOCB_t *iocb;
struct lpfc_iocbq *nextiocb;
......@@ -420,7 +440,7 @@ lpfc_sli_resume_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
* (d) IOCB processing is not blocked by the outstanding mbox command.
*/
if (pring->txq_cnt &&
(phba->hba_state > LPFC_LINK_DOWN) &&
lpfc_is_link_up(phba) &&
(pring->ringno != phba->sli.fcp_ring ||
phba->sli.sli_flag & LPFC_PROCESS_LA) &&
!(pring->flag & LPFC_STOP_IOCB_MBX)) {
......@@ -440,11 +460,13 @@ lpfc_sli_resume_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
/* lpfc_sli_turn_on_ring is only called by lpfc_sli_handle_mb_event below */
static void
lpfc_sli_turn_on_ring(struct lpfc_hba * phba, int ringno)
lpfc_sli_turn_on_ring(struct lpfc_hba *phba, int ringno)
{
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[ringno];
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[ringno];
unsigned long iflags;
/* If the ring is active, flag it */
spin_lock_irqsave(&phba->hbalock, iflags);
if (phba->sli.ring[ringno].cmdringaddr) {
if (phba->sli.ring[ringno].flag & LPFC_STOP_IOCB_MBX) {
phba->sli.ring[ringno].flag &= ~LPFC_STOP_IOCB_MBX;
......@@ -453,11 +475,10 @@ lpfc_sli_turn_on_ring(struct lpfc_hba * phba, int ringno)
*/
phba->sli.ring[ringno].local_getidx
= le32_to_cpu(pgp->cmdGetInx);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_resume_iocb(phba, &phba->sli.ring[ringno]);
spin_unlock_irq(phba->host->host_lock);
}
}
spin_unlock_irqrestore(&phba->hbalock, iflags);
}
static int
......@@ -517,10 +538,10 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
ret = MBX_SHUTDOWN;
break;
}
return (ret);
return ret;
}
static void
lpfc_sli_wake_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
{
wait_queue_head_t *pdone_q;
......@@ -536,7 +557,7 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
}
void
lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_dmabuf *mp;
uint16_t rpi;
......@@ -553,9 +574,9 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
* If a REG_LOGIN succeeded after node is destroyed or node
* is in re-discovery driver need to cleanup the RPI.
*/
if (!(phba->fc_flag & FC_UNLOADING) &&
(pmb->mb.mbxCommand == MBX_REG_LOGIN64) &&
(!pmb->mb.mbxStatus)) {
if (!(phba->pport->load_flag & FC_UNLOADING) &&
pmb->mb.mbxCommand == MBX_REG_LOGIN64 &&
!pmb->mb.mbxStatus) {
rpi = pmb->mb.un.varWords[0];
lpfc_unreg_login(phba, rpi, pmb);
......@@ -565,24 +586,22 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
mempool_free( pmb, phba->mbox_mem_pool);
mempool_free(pmb, phba->mbox_mem_pool);
return;
}
int
lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
{
MAILBOX_t *mbox;
MAILBOX_t *pmbox;
MAILBOX_t *mbox, *pmbox;
LPFC_MBOXQ_t *pmb;
struct lpfc_sli *psli;
int i, rc;
uint32_t process_next;
unsigned long iflags;
psli = &phba->sli;
/* We should only get here if we are in SLI2 mode */
if (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE)) {
return (1);
return 1;
}
phba->sli.slistat.mbox_event++;
......@@ -616,15 +635,18 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
pmbox->mbxCommand,
pmbox->mbxStatus);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
return (1);
spin_unlock_irq(&phba->hbalock);
return 1;
}
mbout:
del_timer_sync(&phba->sli.mbox_tmo);
phba->work_hba_events &= ~WORKER_MBOX_TMO;
spin_lock_irqsave(&phba->pport->work_port_lock, iflags);
phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags);
/*
* It is a fatal error if unknown mbox command completion.
......@@ -639,10 +661,10 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
"%d:0323 Unknown Mailbox command %x Cmpl\n",
phba->brd_no,
pmbox->mbxCommand);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
phba->work_hs = HS_FFER3;
lpfc_handle_eratt(phba);
return (0);
return 0;
}
phba->sli.mbox_active = NULL;
......@@ -659,15 +681,15 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
pmbox->mbxCommand,
pmbox->mbxStatus,
pmbox->un.varWords[0],
phba->hba_state);
phba->pport->port_state);
pmbox->mbxStatus = 0;
pmbox->mbxOwner = OWN_HOST;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
if (rc == MBX_SUCCESS)
return (0);
return 0;
}
}
......@@ -699,12 +721,12 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
do {
process_next = 0; /* by default don't loop */
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
/* Process next mailbox command if there is one */
if ((pmb = lpfc_mbox_get(phba))) {
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
pmb->mb.mbxStatus = MBX_NOT_FINISHED;
......@@ -713,7 +735,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
continue; /* loop back */
}
} else {
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
/* Turn on IOCB processing */
for (i = 0; i < phba->sli.num_rings; i++)
lpfc_sli_turn_on_ring(phba, i);
......@@ -721,7 +743,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
} while (process_next);
return (0);
return 0;
}
static int
lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
......@@ -795,9 +817,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
static struct lpfc_iocbq *
lpfc_sli_iocbq_lookup(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * prspiocb)
lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring,
struct lpfc_iocbq *prspiocb)
{
struct lpfc_iocbq *cmd_iocb = NULL;
uint16_t iotag;
......@@ -821,16 +843,18 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba * phba,
}
static int
lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *saveq)
{
struct lpfc_iocbq * cmdiocbp;
struct lpfc_iocbq *cmdiocbp;
int rc = 1;
unsigned long iflag;
/* Based on the iotag field, get the cmd IOCB from the txcmplq */
spin_lock_irqsave(phba->host->host_lock, iflag);
spin_lock_irqsave(&phba->hbalock, iflag);
cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
spin_unlock_irqrestore(&phba->hbalock, iflag);
if (cmdiocbp) {
if (cmdiocbp->iocb_cmpl) {
/*
......@@ -846,17 +870,8 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
saveq->iocb.un.ulpWord[4] =
IOERR_SLI_ABORTED;
}
spin_unlock_irqrestore(phba->host->host_lock,
iflag);
(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
spin_lock_irqsave(phba->host->host_lock, iflag);
}
else {
spin_unlock_irqrestore(phba->host->host_lock,
iflag);
(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
spin_lock_irqsave(phba->host->host_lock, iflag);
}
(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
} else
lpfc_sli_release_iocbq(phba, cmdiocbp);
} else {
......@@ -885,12 +900,11 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
}
}
spin_unlock_irqrestore(phba->host->host_lock, iflag);
return rc;
}
static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring)
static void
lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
/*
......@@ -904,7 +918,7 @@ static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba,
le32_to_cpu(pgp->rspPutInx),
pring->numRiocb);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
/*
* All error attention handlers are posted to
......@@ -918,10 +932,10 @@ static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba,
return;
}
void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
{
struct lpfc_sli * psli = &phba->sli;
struct lpfc_sli_ring * pring = &psli->ring[LPFC_FCP_RING];
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring = &psli->ring[LPFC_FCP_RING];
IOCB_t *irsp = NULL;
IOCB_t *entry = NULL;
struct lpfc_iocbq *cmdiocbq = NULL;
......@@ -933,6 +947,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
uint32_t rsp_cmpl = 0;
void __iomem *to_slim;
uint32_t ha_copy;
unsigned long iflags;
pring->stats.iocb_event++;
......@@ -960,7 +975,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
lpfc_sli_pcimem_bcopy((uint32_t *) entry,
(uint32_t *) &rspiocbq.iocb,
sizeof (IOCB_t));
sizeof(IOCB_t));
irsp = &rspiocbq.iocb;
type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK);
pring->stats.iocb_rsp++;
......@@ -998,8 +1013,10 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
break;
}
spin_lock_irqsave(&phba->hbalock, iflags);
cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
&rspiocbq);
spin_unlock_irqrestore(&phba->hbalock, iflags);
if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
&rspiocbq);
......@@ -1045,13 +1062,16 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
ha_copy >>= (LPFC_FCP_RING * 4);
if ((rsp_cmpl > 0) && (ha_copy & HA_R0RE_REQ)) {
spin_lock_irqsave(&phba->hbalock, iflags);
pring->stats.iocb_rsp_full++;
status = ((CA_R0ATT | CA_R0RE_RSP) << (LPFC_FCP_RING * 4));
writel(status, phba->CAregaddr);
readl(phba->CAregaddr);
spin_unlock_irqrestore(&phba->hbalock, iflags);
}
if ((ha_copy & HA_R0CE_RSP) &&
(pring->flag & LPFC_CALL_RING_AVAILABLE)) {
spin_lock_irqsave(&phba->hbalock, iflags);
pring->flag &= ~LPFC_CALL_RING_AVAILABLE;
pring->stats.iocb_cmd_empty++;
......@@ -1062,6 +1082,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
if ((pring->lpfc_sli_cmd_available))
(pring->lpfc_sli_cmd_available) (phba, pring);
spin_unlock_irqrestore(&phba->hbalock, iflags);
}
return;
......@@ -1072,10 +1093,10 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
* to check it explicitly.
*/
static int
lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring, uint32_t mask)
lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, uint32_t mask)
{
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
IOCB_t *irsp = NULL;
IOCB_t *entry = NULL;
struct lpfc_iocbq *cmdiocbq = NULL;
......@@ -1086,9 +1107,9 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
lpfc_iocb_type type;
unsigned long iflag;
uint32_t rsp_cmpl = 0;
void __iomem *to_slim;
void __iomem *to_slim;
spin_lock_irqsave(phba->host->host_lock, iflag);
spin_lock_irqsave(&phba->hbalock, iflag);
pring->stats.iocb_event++;
/*
......@@ -1099,7 +1120,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
portRspPut = le32_to_cpu(pgp->rspPutInx);
if (unlikely(portRspPut >= portRspMax)) {
lpfc_sli_rsp_pointers_error(phba, pring);
spin_unlock_irqrestore(phba->host->host_lock, iflag);
spin_unlock_irqrestore(&phba->hbalock, iflag);
return 1;
}
......@@ -1117,7 +1138,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
lpfc_sli_pcimem_bcopy((uint32_t *) entry,
(uint32_t *) &rspiocbq.iocb,
sizeof (IOCB_t));
sizeof(IOCB_t));
INIT_LIST_HEAD(&(rspiocbq.list));
irsp = &rspiocbq.iocb;
......@@ -1161,19 +1182,19 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
&rspiocbq);
} else {
spin_unlock_irqrestore(
phba->host->host_lock, iflag);
spin_unlock_irqrestore(&phba->hbalock,
iflag);
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
&rspiocbq);
spin_lock_irqsave(phba->host->host_lock,
spin_lock_irqsave(&phba->hbalock,
iflag);
}
}
break;
case LPFC_UNSOL_IOCB:
spin_unlock_irqrestore(phba->host->host_lock, iflag);
spin_unlock_irqrestore(&phba->hbalock, iflag);
lpfc_sli_process_unsol_iocb(phba, pring, &rspiocbq);
spin_lock_irqsave(phba->host->host_lock, iflag);
spin_lock_irqsave(&phba->hbalock, iflag);
break;
default:
if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
......@@ -1228,31 +1249,31 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
}
spin_unlock_irqrestore(phba->host->host_lock, iflag);
spin_unlock_irqrestore(&phba->hbalock, iflag);
return rc;
}
int
lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring, uint32_t mask)
lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, uint32_t mask)
{
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
IOCB_t *entry;
IOCB_t *irsp = NULL;
struct lpfc_iocbq *rspiocbp = NULL;
struct lpfc_iocbq *next_iocb;
struct lpfc_iocbq *cmdiocbp;
struct lpfc_iocbq *saveq;
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
uint8_t iocb_cmd_type;
lpfc_iocb_type type;
uint32_t status, free_saveq;
uint32_t portRspPut, portRspMax;
int rc = 1;
unsigned long iflag;
void __iomem *to_slim;
void __iomem *to_slim;
spin_lock_irqsave(phba->host->host_lock, iflag);
spin_lock_irqsave(&phba->hbalock, iflag);
pring->stats.iocb_event++;
/*
......@@ -1274,8 +1295,8 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
phba->brd_no,
pring->ringno, portRspPut, portRspMax);
phba->hba_state = LPFC_HBA_ERROR;
spin_unlock_irqrestore(phba->host->host_lock, iflag);
phba->link_state = LPFC_HBA_ERROR;
spin_unlock_irqrestore(&phba->hbalock, iflag);
phba->work_hs = HS_FFER3;
lpfc_handle_eratt(phba);
......@@ -1299,14 +1320,14 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
* received.
*/
entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
rspiocbp = lpfc_sli_get_iocbq(phba);
rspiocbp = __lpfc_sli_get_iocbq(phba);
if (rspiocbp == NULL) {
printk(KERN_ERR "%s: out of buffers! Failing "
"completion.\n", __FUNCTION__);
break;
}
lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb, sizeof (IOCB_t));
lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb, sizeof(IOCB_t));
irsp = &rspiocbp->iocb;
if (++pring->rspidx >= portRspMax)
......@@ -1366,17 +1387,17 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK;
type = lpfc_sli_iocb_cmd_type(iocb_cmd_type);
if (type == LPFC_SOL_IOCB) {
spin_unlock_irqrestore(phba->host->host_lock,
spin_unlock_irqrestore(&phba->hbalock,
iflag);
rc = lpfc_sli_process_sol_iocb(phba, pring,
saveq);
spin_lock_irqsave(phba->host->host_lock, iflag);
saveq);
spin_lock_irqsave(&phba->hbalock, iflag);
} else if (type == LPFC_UNSOL_IOCB) {
spin_unlock_irqrestore(phba->host->host_lock,
spin_unlock_irqrestore(&phba->hbalock,
iflag);
rc = lpfc_sli_process_unsol_iocb(phba, pring,
saveq);
spin_lock_irqsave(phba->host->host_lock, iflag);
saveq);
spin_lock_irqsave(&phba->hbalock, iflag);
} else if (type == LPFC_ABORT_IOCB) {
if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) &&
((cmdiocbp =
......@@ -1386,15 +1407,15 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
routine */
if (cmdiocbp->iocb_cmpl) {
spin_unlock_irqrestore(
phba->host->host_lock,
&phba->hbalock,
iflag);
(cmdiocbp->iocb_cmpl) (phba,
cmdiocbp, saveq);
spin_lock_irqsave(
phba->host->host_lock,
&phba->hbalock,
iflag);
} else
lpfc_sli_release_iocbq(phba,
__lpfc_sli_release_iocbq(phba,
cmdiocbp);
}
} else if (type == LPFC_UNKNOWN_IOCB) {
......@@ -1425,17 +1446,13 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
}
if (free_saveq) {
if (!list_empty(&saveq->list)) {
list_for_each_entry_safe(rspiocbp,
next_iocb,
&saveq->list,
list) {
list_del(&rspiocbp->list);
lpfc_sli_release_iocbq(phba,
rspiocbp);
}
list_for_each_entry_safe(rspiocbp, next_iocb,
&saveq->list, list) {
list_del(&rspiocbp->list);
__lpfc_sli_release_iocbq(phba,
rspiocbp);
}
lpfc_sli_release_iocbq(phba, saveq);
__lpfc_sli_release_iocbq(phba, saveq);
}
}
......@@ -1470,24 +1487,21 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
}
spin_unlock_irqrestore(phba->host->host_lock, iflag);
spin_unlock_irqrestore(&phba->hbalock, iflag);
return rc;
}
int
void
lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
LIST_HEAD(completions);
struct lpfc_iocbq *iocb, *next_iocb;
IOCB_t *cmd = NULL;
int errcnt;
errcnt = 0;
/* Error everything on txq and txcmplq
* First do the txq.
*/
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
list_splice_init(&pring->txq, &completions);
pring->txq_cnt = 0;
......@@ -1495,26 +1509,25 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) {
iocb = list_get_first(&completions, struct lpfc_iocbq, list);
cmd = &iocb->iocb;
list_del(&iocb->list);
if (iocb->iocb_cmpl) {
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(iocb->iocb_cmpl) (phba, iocb, iocb);
} else
lpfc_sli_release_iocbq(phba, iocb);
}
}
return errcnt;
}
int
lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
{
uint32_t status;
int i = 0;
......@@ -1541,7 +1554,8 @@ lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
msleep(2500);
if (i == 15) {
phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
/* Do post */
phba->pport->port_state = LPFC_STATE_UNKNOWN;
lpfc_sli_brdrestart(phba);
}
/* Read the HBA Host Status Register */
......@@ -1550,7 +1564,7 @@ lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
/* Check to see if any errors occurred during init */
if ((status & HS_FFERM) || (i >= 20)) {
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
retval = 1;
}
......@@ -1559,7 +1573,7 @@ lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
#define BARRIER_TEST_PATTERN (0xdeadbeef)
void lpfc_reset_barrier(struct lpfc_hba * phba)
void lpfc_reset_barrier(struct lpfc_hba *phba)
{
uint32_t __iomem *resp_buf;
uint32_t __iomem *mbox_buf;
......@@ -1584,12 +1598,12 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
hc_copy = readl(phba->HCregaddr);
writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
phba->fc_flag |= FC_IGNORE_ERATT;
phba->link_flag |= LS_IGNORE_ERATT;
if (readl(phba->HAregaddr) & HA_ERATT) {
/* Clear Chip error bit */
writel(HA_ERATT, phba->HAregaddr);
phba->stopped = 1;
phba->pport->stopped = 1;
}
mbox = 0;
......@@ -1606,7 +1620,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
if (phba->sli.sli_flag & LPFC_SLI2_ACTIVE ||
phba->stopped)
phba->pport->stopped)
goto restore_hc;
else
goto clear_errat;
......@@ -1623,17 +1637,17 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
if (readl(phba->HAregaddr) & HA_ERATT) {
writel(HA_ERATT, phba->HAregaddr);
phba->stopped = 1;
phba->pport->stopped = 1;
}
restore_hc:
phba->fc_flag &= ~FC_IGNORE_ERATT;
phba->link_flag &= ~LS_IGNORE_ERATT;
writel(hc_copy, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
}
int
lpfc_sli_brdkill(struct lpfc_hba * phba)
lpfc_sli_brdkill(struct lpfc_hba *phba)
{
struct lpfc_sli *psli;
LPFC_MBOXQ_t *pmb;
......@@ -1650,7 +1664,7 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
LOG_SLI,
"%d:0329 Kill HBA Data: x%x x%x\n",
phba->brd_no,
phba->hba_state,
phba->pport->port_state,
psli->sli_flag);
if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
......@@ -1658,13 +1672,13 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
return 1;
/* Disable the error attention */
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
status = readl(phba->HCregaddr);
status &= ~HC_ERINT_ENA;
writel(status, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
phba->fc_flag |= FC_IGNORE_ERATT;
spin_unlock_irq(phba->host->host_lock);
phba->link_flag |= LS_IGNORE_ERATT;
spin_unlock_irq(&phba->hbalock);
lpfc_kill_board(phba, pmb);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
......@@ -1673,9 +1687,9 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
if (retval != MBX_SUCCESS) {
if (retval != MBX_BUSY)
mempool_free(pmb, phba->mbox_mem_pool);
spin_lock_irq(phba->host->host_lock);
phba->fc_flag &= ~FC_IGNORE_ERATT;
spin_unlock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
phba->link_flag &= ~LS_IGNORE_ERATT;
spin_unlock_irq(&phba->hbalock);
return 1;
}
......@@ -1698,22 +1712,22 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
del_timer_sync(&psli->mbox_tmo);
if (ha_copy & HA_ERATT) {
writel(HA_ERATT, phba->HAregaddr);
phba->stopped = 1;
phba->pport->stopped = 1;
}
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
phba->fc_flag &= ~FC_IGNORE_ERATT;
spin_unlock_irq(phba->host->host_lock);
phba->link_flag &= ~LS_IGNORE_ERATT;
spin_unlock_irq(&phba->hbalock);
psli->mbox_active = NULL;
lpfc_hba_down_post(phba);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
return (ha_copy & HA_ERATT ? 0 : 1);
return ha_copy & HA_ERATT ? 0 : 1;
}
int
lpfc_sli_brdreset(struct lpfc_hba * phba)
lpfc_sli_brdreset(struct lpfc_hba *phba)
{
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
......@@ -1725,12 +1739,12 @@ lpfc_sli_brdreset(struct lpfc_hba * phba)
/* Reset HBA */
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no,
phba->hba_state, psli->sli_flag);
phba->pport->port_state, psli->sli_flag);
/* perform board reset */
phba->fc_eventTag = 0;
phba->fc_myDID = 0;
phba->fc_prevDID = 0;
phba->pport->fc_myDID = 0;
phba->pport->fc_prevDID = 0;
/* Turn off parity checking and serr during the physical reset */
pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
......@@ -1760,12 +1774,12 @@ lpfc_sli_brdreset(struct lpfc_hba * phba)
pring->missbufcnt = 0;
}
phba->hba_state = LPFC_WARM_START;
phba->link_state = LPFC_WARM_START;
return 0;
}
int
lpfc_sli_brdrestart(struct lpfc_hba * phba)
lpfc_sli_brdrestart(struct lpfc_hba *phba)
{
MAILBOX_t *mb;
struct lpfc_sli *psli;
......@@ -1773,14 +1787,14 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
volatile uint32_t word0;
void __iomem *to_slim;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
psli = &phba->sli;
/* Restart HBA */
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"%d:0337 Restart HBA Data: x%x x%x\n", phba->brd_no,
phba->hba_state, psli->sli_flag);
phba->pport->port_state, psli->sli_flag);
word0 = 0;
mb = (MAILBOX_t *) &word0;
......@@ -1794,7 +1808,7 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
readl(to_slim); /* flush */
/* Only skip post after fc_ffinit is completed */
if (phba->hba_state) {
if (phba->pport->port_state) {
skip_post = 1;
word0 = 1; /* This is really setting up word1 */
} else {
......@@ -1806,10 +1820,10 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
readl(to_slim); /* flush */
lpfc_sli_brdreset(phba);
phba->stopped = 0;
phba->hba_state = LPFC_INIT_START;
phba->pport->stopped = 0;
phba->link_state = LPFC_INIT_START;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
psli->stats_start = get_seconds();
......@@ -1850,7 +1864,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
"timeout, status reg x%x\n",
phba->brd_no,
status);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
return -ETIMEDOUT;
}
......@@ -1866,7 +1880,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
"chipset, status reg x%x\n",
phba->brd_no,
status);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
return -EIO;
}
......@@ -1879,7 +1893,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
}
if (i == 15) {
phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
/* Do post */
phba->pport->port_state = LPFC_STATE_UNKNOWN;
lpfc_sli_brdrestart(phba);
}
/* Read the HBA Host Status Register */
......@@ -1897,7 +1912,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
"status reg x%x\n",
phba->brd_no,
status);
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
return -EIO;
}
......@@ -1912,31 +1927,31 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
}
int
lpfc_sli_hba_setup(struct lpfc_hba * phba)
lpfc_sli_hba_setup(struct lpfc_hba *phba)
{
LPFC_MBOXQ_t *pmb;
uint32_t resetcount = 0, rc = 0, done = 0;
pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
return -ENOMEM;
}
while (resetcount < 2 && !done) {
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
phba->hba_state = LPFC_STATE_UNKNOWN;
spin_unlock_irq(&phba->hbalock);
phba->pport->port_state = LPFC_STATE_UNKNOWN;
lpfc_sli_brdrestart(phba);
msleep(2500);
rc = lpfc_sli_chipset_init(phba);
if (rc)
break;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
resetcount++;
/* Call pre CONFIG_PORT mailbox command initialization. A value of 0
......@@ -1946,13 +1961,13 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
*/
rc = lpfc_config_port_prep(phba);
if (rc == -ERESTART) {
phba->hba_state = 0;
phba->pport->port_state = 0;
continue;
} else if (rc) {
break;
}
phba->hba_state = LPFC_INIT_MBX_CMDS;
phba->link_state = LPFC_INIT_MBX_CMDS;
lpfc_config_port(phba, pmb);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc == MBX_SUCCESS)
......@@ -1963,7 +1978,10 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
"CONFIG_PORT, mbxStatus x%x Data: x%x\n",
phba->brd_no, pmb->mb.mbxCommand,
pmb->mb.mbxStatus, 0);
spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(&phba->hbalock);
rc = -ENXIO;
}
}
if (!done)
......@@ -1982,7 +2000,7 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
goto lpfc_sli_hba_setup_exit;
lpfc_sli_hba_setup_error:
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
lpfc_sli_hba_setup_exit:
mempool_free(pmb, phba->mbox_mem_pool);
return rc;
......@@ -2004,36 +2022,34 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
void
lpfc_mbox_timeout(unsigned long ptr)
{
struct lpfc_hba *phba;
struct lpfc_hba *phba = (struct lpfc_hba *) phba;
unsigned long iflag;
uint32_t tmo_posted;
phba = (struct lpfc_hba *)ptr;
spin_lock_irqsave(phba->host->host_lock, iflag);
if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
phba->work_hba_events |= WORKER_MBOX_TMO;
spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
tmo_posted = (phba->pport->work_port_events & WORKER_MBOX_TMO) == 0;
if (!tmo_posted)
phba->pport->work_port_events |= WORKER_MBOX_TMO;
spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
if (!tmo_posted) {
if (phba->work_wait)
wake_up(phba->work_wait);
}
spin_unlock_irqrestore(phba->host->host_lock, iflag);
}
void
lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
{
LPFC_MBOXQ_t *pmbox;
MAILBOX_t *mb;
LPFC_MBOXQ_t *pmbox = phba->sli.mbox_active;
MAILBOX_t *mb = &pmbox->mb;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
spin_lock_irq(phba->host->host_lock);
if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
spin_unlock_irq(phba->host->host_lock);
if (!(phba->pport->work_port_events & WORKER_MBOX_TMO)) {
return;
}
pmbox = phba->sli.mbox_active;
mb = &pmbox->mb;
/* Mbox cmd <mbxCommand> timeout */
lpfc_printf_log(phba,
KERN_ERR,
......@@ -2041,7 +2057,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
"%d:0310 Mailbox command x%x timeout Data: x%x x%x x%p\n",
phba->brd_no,
mb->mbxCommand,
phba->hba_state,
phba->pport->port_state,
phba->sli.sli_flag,
phba->sli.mbox_active);
......@@ -2049,11 +2065,14 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
* would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
* it to fail all oustanding SCSI IO.
*/
phba->hba_state = LPFC_STATE_UNKNOWN;
phba->work_hba_events &= ~WORKER_MBOX_TMO;
phba->fc_flag |= FC_ESTABLISH_LINK;
spin_lock_irq(&phba->pport->work_port_lock);
phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
spin_unlock_irq(&phba->pport->work_port_lock);
spin_lock_irq(&phba->hbalock);
phba->link_state = LPFC_LINK_UNKNOWN;
phba->pport->fc_flag |= FC_ESTABLISH_LINK;
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
pring = &psli->ring[psli->fcp_ring];
lpfc_sli_abort_iocb_ring(phba, pring);
......@@ -2075,10 +2094,10 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
}
int
lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
{
MAILBOX_t *mb;
struct lpfc_sli *psli;
struct lpfc_sli *psli = &phba->sli;
uint32_t status, evtctr;
uint32_t ha_copy;
int i;
......@@ -2090,27 +2109,25 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
if (unlikely(pci_channel_offline(phba->pcidev)))
return MBX_NOT_FINISHED;
spin_lock_irqsave(&phba->hbalock, drvr_flag);
psli = &phba->sli;
spin_lock_irqsave(phba->host->host_lock, drvr_flag);
mb = &pmbox->mb;
status = MBX_SUCCESS;
if (phba->hba_state == LPFC_HBA_ERROR) {
spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
if (phba->link_state == LPFC_HBA_ERROR) {
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
return (MBX_NOT_FINISHED);
return MBX_NOT_FINISHED;
}
if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
!(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
return (MBX_NOT_FINISHED);
return MBX_NOT_FINISHED;
}
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
......@@ -2120,20 +2137,18 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
*/
if (flag & MBX_POLL) {
spin_unlock_irqrestore(phba->host->host_lock,
drvr_flag);
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
return (MBX_NOT_FINISHED);
LOG_MBOX_CANNOT_ISSUE_DATA(phba, mb, psli, flag);
return MBX_NOT_FINISHED;
}
if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
spin_unlock_irqrestore(phba->host->host_lock,
drvr_flag);
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
return (MBX_NOT_FINISHED);
LOG_MBOX_CANNOT_ISSUE_DATA(phba, mb, psli, flag);
return MBX_NOT_FINISHED;
}
/* Handle STOP IOCB processing flag. This is only meaningful
......@@ -2163,15 +2178,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
"%d:0308 Mbox cmd issue - BUSY Data: x%x x%x x%x x%x\n",
phba->brd_no,
mb->mbxCommand,
phba->hba_state,
phba->pport->port_state,
psli->sli_flag,
flag);
psli->slistat.mbox_busy++;
spin_unlock_irqrestore(phba->host->host_lock,
drvr_flag);
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
return (MBX_BUSY);
return MBX_BUSY;
}
/* Handle STOP IOCB processing flag. This is only meaningful
......@@ -2198,11 +2212,10 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
if (!(psli->sli_flag & LPFC_SLI2_ACTIVE) &&
(mb->mbxCommand != MBX_KILL_BOARD)) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(phba->host->host_lock,
drvr_flag);
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag);
return (MBX_NOT_FINISHED);
return MBX_NOT_FINISHED;
}
/* timeout active mbox command */
mod_timer(&psli->mbox_tmo, (jiffies +
......@@ -2216,9 +2229,9 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
"%d:0309 Mailbox cmd x%x issue Data: x%x x%x x%x\n",
phba->brd_no,
mb->mbxCommand,
phba->hba_state,
phba->pport->port_state,
psli->sli_flag,
flag);
flag);
psli->slistat.mbox_cmd++;
evtctr = psli->slistat.mbox_event;
......@@ -2285,12 +2298,12 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
/* Wait for command to complete */
while (((word0 & OWN_CHIP) == OWN_CHIP) ||
(!(ha_copy & HA_MBATT) &&
(phba->hba_state > LPFC_WARM_START))) {
(phba->link_state > LPFC_WARM_START))) {
if (i-- <= 0) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(phba->host->host_lock,
spin_unlock_irqrestore(&phba->hbalock,
drvr_flag);
return (MBX_NOT_FINISHED);
return MBX_NOT_FINISHED;
}
/* Check if we took a mbox interrupt while we were
......@@ -2299,12 +2312,12 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
&& (evtctr != psli->slistat.mbox_event))
break;
spin_unlock_irqrestore(phba->host->host_lock,
spin_unlock_irqrestore(&phba->hbalock,
drvr_flag);
msleep(1);
spin_lock_irqsave(phba->host->host_lock, drvr_flag);
spin_lock_irqsave(&phba->hbalock, drvr_flag);
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First copy command data */
......@@ -2342,7 +2355,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
MAILBOX_CMD_SIZE);
if ((mb->mbxCommand == MBX_DUMP_MEMORY) &&
pmbox->context2) {
lpfc_memcpy_from_slim((void *)pmbox->context2,
lpfc_memcpy_from_slim((void *) pmbox->context2,
phba->MBslimaddr + DMP_RSP_OFFSET,
mb->un.varDmp.word_cnt);
}
......@@ -2355,23 +2368,27 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
status = mb->mbxStatus;
}
spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
return (status);
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
return status;
}
static int
lpfc_sli_ringtx_put(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
struct lpfc_iocbq * piocb)
lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb)
{
unsigned long iflags;
/* Insert the caller's iocb in the txq tail for later processing. */
spin_lock_irqsave(&phba->hbalock, iflags);
list_add_tail(&piocb->list, &pring->txq);
pring->txq_cnt++;
return (0);
spin_unlock_irqrestore(&phba->hbalock, iflags);
return 0;
}
static struct lpfc_iocbq *
lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq ** piocb)
struct lpfc_iocbq **piocb)
{
struct lpfc_iocbq * nextiocb;
......@@ -2389,6 +2406,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb, uint32_t flag)
{
struct lpfc_iocbq *nextiocb;
unsigned long iflags;
IOCB_t *iocb;
/* If the PCI channel is in offline state, do not post iocbs. */
......@@ -2398,7 +2416,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
/*
* We should never get an IOCB if we are in a < LINK_DOWN state
*/
if (unlikely(phba->hba_state < LPFC_LINK_DOWN))
if (unlikely(phba->link_state < LPFC_LINK_DOWN))
return IOCB_ERROR;
/*
......@@ -2408,7 +2426,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (unlikely(pring->flag & LPFC_STOP_IOCB_MBX))
goto iocb_busy;
if (unlikely(phba->hba_state == LPFC_LINK_DOWN)) {
if (unlikely(phba->link_state == LPFC_LINK_DOWN)) {
/*
* Only CREATE_XRI, CLOSE_XRI, and QUE_RING_BUF
* can be issued if the link is not up.
......@@ -2439,6 +2457,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
!(phba->sli.sli_flag & LPFC_PROCESS_LA)))
goto iocb_busy;
spin_lock_irqsave(&phba->hbalock, iflags);
while ((iocb = lpfc_sli_next_iocb_slot(phba, pring)) &&
(nextiocb = lpfc_sli_next_iocb(phba, pring, &piocb)))
lpfc_sli_submit_iocb(phba, pring, iocb, nextiocb);
......@@ -2447,6 +2466,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
lpfc_sli_update_ring(phba, pring);
else
lpfc_sli_update_full_ring(phba, pring);
spin_unlock_irqrestore(&phba->hbalock, iflags);
if (!piocb)
return IOCB_SUCCESS;
......@@ -2454,7 +2474,9 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
goto out_busy;
iocb_busy:
spin_lock_irqsave(&phba->hbalock, iflags);
pring->stats.iocb_cmd_delay++;
spin_unlock_irqrestore(&phba->hbalock, iflags);
out_busy:
......@@ -2539,6 +2561,7 @@ lpfc_sli_setup(struct lpfc_hba *phba)
/* numCiocb and numRiocb are used in config_port */
pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES;
pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES;
pring->iotag_max = phba->cfg_hba_queue_depth;
pring->num_mask = 0;
break;
case LPFC_ELS_RING: /* ring 2 - ELS / CT */
......@@ -2591,14 +2614,14 @@ lpfc_sli_setup(struct lpfc_hba *phba)
}
int
lpfc_sli_queue_setup(struct lpfc_hba * phba)
lpfc_sli_queue_setup(struct lpfc_hba *phba)
{
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
int i;
psli = &phba->sli;
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
INIT_LIST_HEAD(&psli->mboxq);
/* Initialize list headers for txq and txcmplq as double linked lists */
for (i = 0; i < psli->num_rings; i++) {
......@@ -2612,15 +2635,15 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba)
INIT_LIST_HEAD(&pring->iocb_continueq);
INIT_LIST_HEAD(&pring->postbufq);
}
spin_unlock_irq(phba->host->host_lock);
return (1);
spin_unlock_irq(&phba->hbalock);
return 1;
}
int
lpfc_sli_hba_down(struct lpfc_hba * phba)
lpfc_sli_hba_down(struct lpfc_hba *phba)
{
LIST_HEAD(completions);
struct lpfc_sli *psli;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
LPFC_MBOXQ_t *pmb;
struct lpfc_iocbq *iocb;
......@@ -2628,10 +2651,9 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
int i;
unsigned long flags = 0;
psli = &phba->sli;
lpfc_hba_down_prep(phba);
spin_lock_irqsave(phba->host->host_lock, flags);
spin_lock_irqsave(&phba->hbalock, flags);
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
pring->flag |= LPFC_DEFERRED_RING_EVENT;
......@@ -2644,51 +2666,48 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
pring->txq_cnt = 0;
}
spin_unlock_irqrestore(phba->host->host_lock, flags);
spin_unlock_irqrestore(&phba->hbalock, flags);
while (!list_empty(&completions)) {
iocb = list_get_first(&completions, struct lpfc_iocbq, list);
cmd = &iocb->iocb;
list_del(&iocb->list);
if (iocb->iocb_cmpl) {
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
(iocb->iocb_cmpl) (phba, iocb, iocb);
} else
lpfc_sli_release_iocbq(phba, iocb);
}
}
/* Return any active mbox cmds */
del_timer_sync(&psli->mbox_tmo);
spin_lock_irqsave(phba->host->host_lock, flags);
phba->work_hba_events &= ~WORKER_MBOX_TMO;
if (psli->mbox_active) {
pmb = psli->mbox_active;
spin_lock_irqsave(&phba->pport->work_port_lock, flags);
phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
pmb = psli->mbox_active;
if (pmb) {
psli->mbox_active = NULL;
pmb->mb.mbxStatus = MBX_NOT_FINISHED;
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
if (pmb->mbox_cmpl) {
spin_unlock_irqrestore(phba->host->host_lock, flags);
pmb->mbox_cmpl(phba,pmb);
spin_lock_irqsave(phba->host->host_lock, flags);
}
}
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
psli->mbox_active = NULL;
/* Return any pending mbox cmds */
while ((pmb = lpfc_mbox_get(phba)) != NULL) {
pmb->mb.mbxStatus = MBX_NOT_FINISHED;
if (pmb->mbox_cmpl) {
spin_unlock_irqrestore(phba->host->host_lock, flags);
pmb->mbox_cmpl(phba,pmb);
spin_lock_irqsave(phba->host->host_lock, flags);
}
}
INIT_LIST_HEAD(&psli->mboxq);
spin_unlock_irqrestore(phba->host->host_lock, flags);
return 1;
}
......@@ -2710,14 +2729,15 @@ lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt)
}
int
lpfc_sli_ringpostbuf_put(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
struct lpfc_dmabuf * mp)
lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_dmabuf *mp)
{
/* Stick struct lpfc_dmabuf at end of postbufq so driver can look it up
later */
spin_lock_irq(&phba->hbalock);
list_add_tail(&mp->list, &pring->postbufq);
pring->postbufq_cnt++;
spin_unlock_irq(&phba->hbalock);
return 0;
}
......@@ -2730,40 +2750,41 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct list_head *slp = &pring->postbufq;
/* Search postbufq, from the begining, looking for a match on phys */
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
if (mp->phys == phys) {
list_del_init(&mp->list);
pring->postbufq_cnt--;
spin_unlock_irq(&phba->hbalock);
return mp;
}
}
spin_unlock_irq(&phba->hbalock);
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"%d:0410 Cannot find virtual addr for mapped buf on "
"ring %d Data x%llx x%p x%p x%x\n",
phba->brd_no, pring->ringno, (unsigned long long)phys,
phba->brd_no, pring->ringno, (unsigned long long) phys,
slp->next, slp->prev, pring->postbufq_cnt);
return NULL;
}
static void
lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb)
lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
IOCB_t *irsp;
IOCB_t *irsp = &rspiocb->iocb;
uint16_t abort_iotag, abort_context;
struct lpfc_iocbq *abort_iocb, *rsp_ab_iocb;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
abort_iocb = NULL;
irsp = &rspiocb->iocb;
spin_lock_irq(phba->host->host_lock);
if (irsp->ulpStatus) {
abort_context = cmdiocb->iocb.un.acxri.abortContextTag;
abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag;
spin_lock_irq(&phba->hbalock);
if (abort_iotag != 0 && abort_iotag <= phba->sli.last_iotag)
abort_iocb = phba->sli.iocbq_lookup[abort_iotag];
......@@ -2777,41 +2798,40 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
* make sure we have the right iocbq before taking it
* off the txcmplq and try to call completion routine.
*/
if (abort_iocb &&
abort_iocb->iocb.ulpContext == abort_context &&
abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
if (!abort_iocb ||
abort_iocb->iocb.ulpContext != abort_context ||
(abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0)
spin_unlock_irq(&phba->hbalock);
else {
list_del(&abort_iocb->list);
pring->txcmplq_cnt--;
spin_unlock_irq(&phba->hbalock);
rsp_ab_iocb = lpfc_sli_get_iocbq(phba);
if (rsp_ab_iocb == NULL)
lpfc_sli_release_iocbq(phba, abort_iocb);
else {
abort_iocb->iocb_flag &=
~LPFC_DRIVER_ABORTED;
abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
rsp_ab_iocb->iocb.ulpStatus =
IOSTAT_LOCAL_REJECT;
rsp_ab_iocb->iocb.un.ulpWord[4] =
IOERR_SLI_ABORTED;
spin_unlock_irq(phba->host->host_lock);
(abort_iocb->iocb_cmpl)
(phba, abort_iocb, rsp_ab_iocb);
spin_lock_irq(phba->host->host_lock);
(abort_iocb->iocb_cmpl)(phba, abort_iocb,
rsp_ab_iocb);
lpfc_sli_release_iocbq(phba, rsp_ab_iocb);
}
}
}
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irq(phba->host->host_lock);
return;
}
int
lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * cmdiocb)
lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *cmdiocb)
{
struct lpfc_vport *vport = cmdiocb->vport;
struct lpfc_iocbq *abtsiocbp;
IOCB_t *icmd = NULL;
IOCB_t *iabt = NULL;
......@@ -2821,14 +2841,14 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
* to abort.
*/
icmd = &cmdiocb->iocb;
if ((icmd->ulpCommand == CMD_ABORT_XRI_CN) ||
(icmd->ulpCommand == CMD_CLOSE_XRI_CN))
if (icmd->ulpCommand == CMD_ABORT_XRI_CN ||
icmd->ulpCommand == CMD_CLOSE_XRI_CN)
return 0;
/* If we're unloading, interrupts are disabled so we
* need to cleanup the iocb here.
*/
if (phba->fc_flag & FC_UNLOADING)
if (vport->load_flag & FC_UNLOADING)
goto abort_iotag_exit;
/* issue ABTS for this IOCB based on iotag */
......@@ -2848,7 +2868,7 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
iabt->ulpLe = 1;
iabt->ulpClass = icmd->ulpClass;
if (phba->hba_state >= LPFC_LINK_UP)
if (phba->link_state >= LPFC_LINK_UP)
iabt->ulpCommand = CMD_ABORT_XRI_CN;
else
iabt->ulpCommand = CMD_CLOSE_XRI_CN;
......@@ -2863,25 +2883,12 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
retval = lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
abort_iotag_exit:
/* If we could not issue an abort dequeue the iocb and handle
* the completion here.
/*
* Caller to this routine should check for IOCB_ERROR
* and handle it properly. This routine no longer removes
* iocb off txcmplq and call compl in case of IOCB_ERROR.
*/
if (retval == IOCB_ERROR) {
list_del(&cmdiocb->list);
pring->txcmplq_cnt--;
if (cmdiocb->iocb_cmpl) {
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
spin_unlock_irq(phba->host->host_lock);
(cmdiocb->iocb_cmpl) (phba, cmdiocb, cmdiocb);
spin_lock_irq(phba->host->host_lock);
} else
lpfc_sli_release_iocbq(phba, cmdiocb);
}
return 1;
return retval;
}
static int
......@@ -2930,7 +2937,7 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id,
int
lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd)
uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd)
{
struct lpfc_iocbq *iocbq;
int sum, i;
......@@ -2947,14 +2954,10 @@ lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
void
lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb)
lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
unsigned long iflags;
spin_lock_irqsave(phba->host->host_lock, iflags);
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irqrestore(phba->host->host_lock, iflags);
return;
}
......@@ -2972,8 +2975,8 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
for (i = 1; i <= phba->sli.last_iotag; i++) {
iocbq = phba->sli.iocbq_lookup[i];
if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id,
0, abort_cmd) != 0)
if (lpfc_sli_validate_fcp_iocb(iocbq, tgt_id, lun_id, 0,
abort_cmd) != 0)
continue;
/* issue ABTS for this IOCB based on iotag */
......@@ -2989,8 +2992,9 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag;
abtsiocb->iocb.ulpLe = 1;
abtsiocb->iocb.ulpClass = cmd->ulpClass;
abtsiocb->vport = phba->pport;
if (phba->hba_state >= LPFC_LINK_UP)
if (lpfc_is_link_up(phba))
abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN;
else
abtsiocb->iocb.ulpCommand = CMD_CLOSE_XRI_CN;
......@@ -3016,14 +3020,14 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
wait_queue_head_t *pdone_q;
unsigned long iflags;
spin_lock_irqsave(phba->host->host_lock, iflags);
spin_lock_irqsave(&phba->hbalock, iflags);
cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
if (cmdiocbq->context2 && rspiocbq)
memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
&rspiocbq->iocb, sizeof(IOCB_t));
pdone_q = cmdiocbq->context_un.wait_queue;
spin_unlock_irqrestore(phba->host->host_lock, iflags);
spin_unlock_irqrestore(&phba->hbalock, iflags);
if (pdone_q)
wake_up(pdone_q);
return;
......@@ -3036,10 +3040,10 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
* definition this is a wait function.
*/
int
lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * piocb,
struct lpfc_iocbq * prspiocbq,
lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb,
struct lpfc_iocbq *prspiocbq,
uint32_t timeout)
{
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
......@@ -3071,11 +3075,11 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0);
if (retval == IOCB_SUCCESS) {
timeout_req = timeout * HZ;
spin_unlock_irq(phba->host->host_lock);
spin_unlock_irq(&phba->hbalock);
timeleft = wait_event_timeout(done_q,
piocb->iocb_flag & LPFC_IO_WAKE,
timeout_req);
spin_lock_irq(phba->host->host_lock);
spin_lock_irq(&phba->hbalock);
if (piocb->iocb_flag & LPFC_IO_WAKE) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
......@@ -3117,7 +3121,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
}
int
lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
uint32_t timeout)
{
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
......@@ -3125,7 +3129,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
/* The caller must leave context1 empty. */
if (pmboxq->context1 != 0) {
return (MBX_NOT_FINISHED);
return MBX_NOT_FINISHED;
}
/* setup wake call as IOCB callback */
......@@ -3158,9 +3162,10 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
int
lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
{
struct lpfc_vport *vport = phba->pport;
int i = 0;
while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !phba->stopped) {
while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !vport->stopped) {
if (i++ > LPFC_MBOX_TMO * 1000)
return 1;
......@@ -3176,7 +3181,7 @@ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
irqreturn_t
lpfc_intr_handler(int irq, void *dev_id)
{
struct lpfc_hba *phba;
struct lpfc_hba *phba;
uint32_t ha_copy;
uint32_t work_ha_copy;
unsigned long status;
......@@ -3204,7 +3209,7 @@ lpfc_intr_handler(int irq, void *dev_id)
*/
/* Ignore all interrupts during initialization. */
if (unlikely(phba->hba_state < LPFC_LINK_DOWN))
if (unlikely(phba->link_state < LPFC_LINK_DOWN))
return IRQ_NONE;
/*
......@@ -3212,16 +3217,16 @@ lpfc_intr_handler(int irq, void *dev_id)
* Clear Attention Sources, except Error Attention (to
* preserve status) and Link Attention
*/
spin_lock(phba->host->host_lock);
spin_lock(&phba->hbalock);
ha_copy = readl(phba->HAregaddr);
/* If somebody is waiting to handle an eratt don't process it
* here. The brdkill function will do this.
*/
if (phba->fc_flag & FC_IGNORE_ERATT)
if (phba->link_flag & LS_IGNORE_ERATT)
ha_copy &= ~HA_ERATT;
writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
spin_unlock(phba->host->host_lock);
spin_unlock(&phba->hbalock);
if (unlikely(!ha_copy))
return IRQ_NONE;
......@@ -3235,13 +3240,13 @@ lpfc_intr_handler(int irq, void *dev_id)
* Turn off Link Attention interrupts
* until CLEAR_LA done
*/
spin_lock(phba->host->host_lock);
spin_lock(&phba->hbalock);
phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
control = readl(phba->HCregaddr);
control &= ~HC_LAINT_ENA;
writel(control, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock(phba->host->host_lock);
spin_unlock(&phba->hbalock);
}
else
work_ha_copy &= ~HA_LATT;
......@@ -3253,18 +3258,18 @@ lpfc_intr_handler(int irq, void *dev_id)
/*
* Turn off Slow Rings interrupts
*/
spin_lock(phba->host->host_lock);
spin_lock(&phba->hbalock);
control = readl(phba->HCregaddr);
control &= ~(HC_R0INT_ENA << i);
writel(control, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock(phba->host->host_lock);
spin_unlock(&phba->hbalock);
}
}
}
if (work_ha_copy & HA_ERATT) {
phba->hba_state = LPFC_HBA_ERROR;
phba->link_state = LPFC_HBA_ERROR;
/*
* There was a link/board error. Read the
* status register to retrieve the error event
......@@ -3279,14 +3284,14 @@ lpfc_intr_handler(int irq, void *dev_id)
/* Clear Chip error bit */
writel(HA_ERATT, phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
phba->stopped = 1;
phba->pport->stopped = 1;
}
spin_lock(phba->host->host_lock);
spin_lock(&phba->hbalock);
phba->work_ha |= work_ha_copy;
if (phba->work_wait)
wake_up(phba->work_wait);
spin_unlock(phba->host->host_lock);
spin_unlock(&phba->hbalock);
}
ha_copy &= ~(phba->work_ha_mask);
......
......@@ -20,6 +20,7 @@
/* forward declaration for LPFC_IOCB_t's use */
struct lpfc_hba;
struct lpfc_vport;
/* Define the context types that SLI handles for abort and sums. */
typedef enum _lpfc_ctx_cmd {
......@@ -47,6 +48,7 @@ struct lpfc_iocbq {
uint8_t abort_count;
uint8_t rsvd2;
uint32_t drvrTimeout; /* driver timeout in seconds */
struct lpfc_vport *vport;/* virtual port pointer */
void *context1; /* caller context information */
void *context2; /* caller context information */
void *context3; /* caller context information */
......@@ -74,6 +76,7 @@ typedef struct lpfcMboxq {
/* MBOXQs are used in single linked lists */
struct list_head list; /* ptr to next mailbox command */
MAILBOX_t mb; /* Mailbox cmd */
struct lpfc_vport *vport;/* virutal port pointer */
void *context1; /* caller context information */
void *context2; /* caller context information */
......@@ -197,6 +200,7 @@ struct lpfc_sli {
#define LPFC_SLI_MBOX_ACTIVE 0x100 /* HBA mailbox is currently active */
#define LPFC_SLI2_ACTIVE 0x200 /* SLI2 overlay in firmware is active */
#define LPFC_PROCESS_LA 0x400 /* Able to process link attention */
#define LPFC_BLOCK_MGMT_IO 0x800 /* Don't allow mgmt mbx or iocb cmds */
struct lpfc_sli_ring ring[LPFC_MAX_RING];
int fcp_ring; /* ring used for FCP initiator commands */
......
......@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
#define LPFC_DRIVER_VERSION "8.1.12"
#define LPFC_DRIVER_VERSION "8.1.12_psplit"
#define LPFC_DRIVER_NAME "lpfc"
......
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