Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 148085
b: refs/heads/master
c: 21e9a0a
h: refs/heads/master
i:
  148083: 9f6edb3
v: v3
  • Loading branch information
James Smart authored and James Bottomley committed Jun 8, 2009
1 parent df07816 commit fd5b5b9
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 58 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f4b4c68f74dcd5da03df851090cad28ad4e8d7cc
refs/heads/master: 21e9a0a5fbd2b7cb3ae29f6d491a30bc0e688422
31 changes: 31 additions & 0 deletions trunk/drivers/scsi/lpfc/lpfc_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2277,6 +2277,36 @@ lpfc_param_init(topology, 0, 0, 6)
static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
lpfc_topology_show, lpfc_topology_store);

/**
* lpfc_static_vport_show: Read callback function for
* lpfc_static_vport sysfs file.
* @dev: Pointer to class device object.
* @attr: device attribute structure.
* @buf: Data buffer.
*
* This function is the read call back function for
* lpfc_static_vport sysfs file. The lpfc_static_vport
* sysfs file report the mageability of the vport.
**/
static ssize_t
lpfc_static_vport_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
if (vport->vport_flag & STATIC_VPORT)
sprintf(buf, "1\n");
else
sprintf(buf, "0\n");

return strlen(buf);
}

/*
* Sysfs attribute to control the statistical data collection.
*/
static DEVICE_ATTR(lpfc_static_vport, S_IRUGO,
lpfc_static_vport_show, NULL);

/**
* lpfc_stat_data_ctrl_store - write call back for lpfc_stat_data_ctrl sysfs file
Expand Down Expand Up @@ -3051,6 +3081,7 @@ struct device_attribute *lpfc_vport_attrs[] = {
&dev_attr_lpfc_enable_da_id,
&dev_attr_lpfc_max_scsicmpl_time,
&dev_attr_lpfc_stat_data_ctrl,
&dev_attr_lpfc_static_vport,
NULL,
};

Expand Down
180 changes: 141 additions & 39 deletions trunk/drivers/scsi/lpfc/lpfc_hbadisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2079,6 +2079,128 @@ lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return;
}

/**
* lpfc_create_static_vport - Read HBA config region to create static vports.
* @phba: pointer to lpfc hba data structure.
*
* This routine issue a DUMP mailbox command for config region 22 to get
* the list of static vports to be created. The function create vports
* based on the information returned from the HBA.
**/
void
lpfc_create_static_vport(struct lpfc_hba *phba)
{
LPFC_MBOXQ_t *pmb = NULL;
MAILBOX_t *mb;
struct static_vport_info *vport_info;
int rc, i;
struct fc_vport_identifiers vport_id;
struct fc_vport *new_fc_vport;
struct Scsi_Host *shost;
struct lpfc_vport *vport;
uint16_t offset = 0;
uint8_t *vport_buff;

pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0542 lpfc_create_static_vport failed to"
" allocate mailbox memory\n");
return;
}

mb = &pmb->u.mb;

vport_info = kzalloc(sizeof(struct static_vport_info), GFP_KERNEL);
if (!vport_info) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0543 lpfc_create_static_vport failed to"
" allocate vport_info\n");
mempool_free(pmb, phba->mbox_mem_pool);
return;
}

vport_buff = (uint8_t *) vport_info;
do {
lpfc_dump_static_vport(phba, pmb, offset);
pmb->vport = phba->pport;
rc = lpfc_sli_issue_mbox_wait(phba, pmb, LPFC_MBOX_TMO);

if ((rc != MBX_SUCCESS) || mb->mbxStatus) {
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"0544 lpfc_create_static_vport failed to"
" issue dump mailbox command ret 0x%x "
"status 0x%x\n",
rc, mb->mbxStatus);
goto out;
}

if (mb->un.varDmp.word_cnt >
sizeof(struct static_vport_info) - offset)
mb->un.varDmp.word_cnt =
sizeof(struct static_vport_info) - offset;

lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
vport_buff + offset,
mb->un.varDmp.word_cnt);
offset += mb->un.varDmp.word_cnt;

} while (mb->un.varDmp.word_cnt &&
offset < sizeof(struct static_vport_info));


if ((le32_to_cpu(vport_info->signature) != VPORT_INFO_SIG) ||
((le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK)
!= VPORT_INFO_REV)) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0545 lpfc_create_static_vport bad"
" information header 0x%x 0x%x\n",
le32_to_cpu(vport_info->signature),
le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK);

goto out;
}

shost = lpfc_shost_from_vport(phba->pport);

for (i = 0; i < MAX_STATIC_VPORT_COUNT; i++) {
memset(&vport_id, 0, sizeof(vport_id));
vport_id.port_name = wwn_to_u64(vport_info->vport_list[i].wwpn);
vport_id.node_name = wwn_to_u64(vport_info->vport_list[i].wwnn);
if (!vport_id.port_name || !vport_id.node_name)
continue;

vport_id.roles = FC_PORT_ROLE_FCP_INITIATOR;
vport_id.vport_type = FC_PORTTYPE_NPIV;
vport_id.disable = false;
new_fc_vport = fc_vport_create(shost, 0, &vport_id);

if (!new_fc_vport) {
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"0546 lpfc_create_static_vport failed to"
" create vport \n");
continue;
}

vport = *(struct lpfc_vport **)new_fc_vport->dd_data;
vport->vport_flag |= STATIC_VPORT;
}

out:
/*
* If this is timed out command, setting NULL to context2 tell SLI
* layer not to use this buffer.
*/
spin_lock_irq(&phba->hbalock);
pmb->context2 = NULL;
spin_unlock_irq(&phba->hbalock);
kfree(vport_info);
if (rc != MBX_TIMEOUT)
mempool_free(pmb, phba->mbox_mem_pool);

return;
}

/*
* This routine handles processing a Fabric REG_LOGIN mailbox
* command upon completion. It is setup in the LPFC_MBOXQ
Expand All @@ -2089,16 +2211,17 @@ void
lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_vport *vport = pmb->vport;
MAILBOX_t *mb = &pmb->mb;
MAILBOX_t *mb = &pmb->u.mb;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
struct lpfc_nodelist *ndlp;
struct lpfc_vport **vports;
int i;

ndlp = (struct lpfc_nodelist *) pmb->context2;
pmb->context1 = NULL;
pmb->context2 = NULL;
if (mb->mbxStatus) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
"0258 Register Fabric login error: 0x%x\n",
mb->mbxStatus);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free(pmb, phba->mbox_mem_pool);
Expand All @@ -2117,9 +2240,6 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}

lpfc_vport_set_state(vport, FC_VPORT_FAILED);
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
"0258 Register Fabric login error: 0x%x\n",
mb->mbxStatus);
/* Decrement the reference count to ndlp after the reference
* to the ndlp are done.
*/
Expand All @@ -2128,34 +2248,12 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}

ndlp->nlp_rpi = mb->un.varWords[0];
ndlp->nlp_flag |= NLP_RPI_VALID;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);

if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for(i = 0;
i <= phba->max_vpi && vports[i] != NULL;
i++) {
if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
continue;
if (phba->fc_topology == TOPOLOGY_LOOP) {
lpfc_vport_set_state(vports[i],
FC_VPORT_LINKDOWN);
continue;
}
if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
lpfc_initial_fdisc(vports[i]);
else {
lpfc_vport_set_state(vports[i],
FC_VPORT_NO_FABRIC_SUPP);
lpfc_printf_vlog(vport, KERN_ERR,
LOG_ELS,
"0259 No NPIV "
"Fabric support\n");
}
}
lpfc_destroy_vport_work_array(phba, vports);
lpfc_start_fdiscs(phba);
lpfc_do_scr_ns_plogi(phba, vport);
}

Expand All @@ -2179,13 +2277,16 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
void
lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
MAILBOX_t *mb = &pmb->mb;
MAILBOX_t *mb = &pmb->u.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) {
out:
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
"0260 Register NameServer error: 0x%x\n",
mb->mbxStatus);
/* decrement the node reference count held for this
* callback function.
*/
Expand All @@ -2209,15 +2310,13 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return;
}
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
"0260 Register NameServer error: 0x%x\n",
mb->mbxStatus);
return;
}

pmb->context1 = NULL;

ndlp->nlp_rpi = mb->un.varWords[0];
ndlp->nlp_flag |= NLP_RPI_VALID;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);

Expand Down Expand Up @@ -2718,7 +2817,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba,
if (pring->ringno == LPFC_ELS_RING) {
switch (icmd->ulpCommand) {
case CMD_GEN_REQUEST64_CR:
if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi)
if (iocb->context_un.ndlp == ndlp)
return 1;
case CMD_ELS_REQUEST64_CR:
if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID)
Expand Down Expand Up @@ -2765,7 +2864,7 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
*/
psli = &phba->sli;
rpi = ndlp->nlp_rpi;
if (rpi) {
if (ndlp->nlp_flag & NLP_RPI_VALID) {
/* Now process each ring */
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
Expand Down Expand Up @@ -2813,7 +2912,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
LPFC_MBOXQ_t *mbox;
int rc;

if (ndlp->nlp_rpi) {
if (ndlp->nlp_flag & NLP_RPI_VALID) {
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox) {
lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox);
Expand All @@ -2825,6 +2924,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
}
lpfc_no_rpi(phba, ndlp);
ndlp->nlp_rpi = 0;
ndlp->nlp_flag &= ~NLP_RPI_VALID;
return 1;
}
return 0;
Expand Down Expand Up @@ -2972,13 +3072,14 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
int rc;

lpfc_cancel_retry_delay_tmo(vport, ndlp);
if (ndlp->nlp_flag & NLP_DEFER_RM && !ndlp->nlp_rpi) {
if ((ndlp->nlp_flag & NLP_DEFER_RM) &&
!(ndlp->nlp_flag & NLP_RPI_VALID)) {
/* For this case we need to cleanup the default rpi
* allocated by the firmware.
*/
if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))
!= NULL) {
rc = lpfc_reg_login(phba, vport->vpi, ndlp->nlp_DID,
rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID,
(uint8_t *) &vport->fc_sparam, mbox, 0);
if (rc) {
mempool_free(mbox, phba->mbox_mem_pool);
Expand Down Expand Up @@ -3713,6 +3814,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
pmb->context1 = NULL;

ndlp->nlp_rpi = mb->un.varWords[0];
ndlp->nlp_flag |= NLP_RPI_VALID;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/scsi/lpfc/lpfc_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
/* Update the fc_host data structures with new 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_max_npiv_vports(shost) = phba->max_vpi;

/* If no serial number in VPD data, use low 6 bytes of WWNN */
/* This should be consolidated into parse_vpd ? - mr */
Expand Down
38 changes: 38 additions & 0 deletions trunk/drivers/scsi/lpfc/lpfc_mbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,44 @@
#include "lpfc_crtn.h"
#include "lpfc_compat.h"

/**
* lpfc_dump_static_vport - Dump HBA's static vport information.
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @offset: offset for dumping vport info.
*
* The dump mailbox command provides a method for the device driver to obtain
* various types of information from the HBA device.
*
* This routine prepares the mailbox command for dumping list of static
* vports to be created.
**/
void
lpfc_dump_static_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb,
uint16_t offset)
{
MAILBOX_t *mb;
void *ctx;

mb = &pmb->u.mb;
ctx = pmb->context2;

/* Setup to dump vport info region */
memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
mb->mbxCommand = MBX_DUMP_MEMORY;
mb->un.varDmp.cv = 1;
mb->un.varDmp.type = DMP_NV_PARAMS;
mb->un.varDmp.entry_index = offset;
mb->un.varDmp.region_id = DMP_REGION_VPORT;
mb->un.varDmp.word_cnt = DMP_RSP_SIZE/sizeof(uint32_t);
mb->un.varDmp.co = 0;
mb->un.varDmp.resp_offset = 0;
pmb->context2 = ctx;
mb->mbxOwner = OWN_HOST;

return;
}

/**
* lpfc_dump_mem - Prepare a mailbox command for retrieving HBA's VPD memory
* @phba: pointer to lpfc hba data structure.
Expand Down
Loading

0 comments on commit fd5b5b9

Please sign in to comment.