/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
- * Enterprise Fibre Channel Host Bus Adapters. *
- * Refer to the README file included with this package for *
- * driver version and adapter support. *
- * Copyright (C) 2004 Emulex Corporation. *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2004-2005 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
+ * Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
- * modify it under the terms of the GNU General Public License *
- * as published by the Free Software Foundation; either version 2 *
- * of the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details, a copy of which *
- * can be found in the file COPYING included with this package. *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
*******************************************************************/
-/*
- * $Id: lpfc_hbadisc.c 1.266 2005/04/13 11:59:06EDT sf_support Exp $
- */
-
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/kthread.h>
#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
static void
lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
- if (!(ndlp->nlp_type & NLP_FABRIC)) {
- /* Nodev timeout on NPort <nlp_DID> */
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
- "%d:0203 Nodev timeout on NPort x%x "
- "Data: x%x x%x x%x\n",
- phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
- ndlp->nlp_state, ndlp->nlp_rpi);
- }
+ int warn_on = 0;
spin_lock_irq(phba->host->host_lock);
if (!(ndlp->nlp_flag & NLP_NODEV_TMO)) {
ndlp->nlp_flag &= ~NLP_NODEV_TMO;
if (ndlp->nlp_sid != NLP_NO_SID) {
+ warn_on = 1;
/* flush the target */
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);
+ if (warn_on) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+ "%d:0203 Nodev timeout on NPort x%x "
+ "Data: x%x x%x x%x\n",
+ phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
+ ndlp->nlp_state, ndlp->nlp_rpi);
+ } else {
+ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+ "%d:0204 Nodev timeout on NPort x%x "
+ "Data: x%x x%x x%x\n",
+ phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
+ ndlp->nlp_state, ndlp->nlp_rpi);
+ }
+
lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM);
return;
}
pmb->context1 = NULL;
- if (ndlp->nlp_rpi != 0)
- lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = mb->un.varWords[0];
- lpfc_addnode_rpi(phba, ndlp, ndlp->nlp_rpi);
ndlp->nlp_type |= NLP_FABRIC;
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
pmb->context1 = NULL;
- if (ndlp->nlp_rpi != 0)
- lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = mb->un.varWords[0];
- lpfc_addnode_rpi(phba, ndlp, ndlp->nlp_rpi);
ndlp->nlp_type |= NLP_FABRIC;
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
struct fc_rport *rport;
struct lpfc_rport_data *rdata;
struct fc_rport_identifiers rport_ids;
- uint64_t wwn;
/* Remote port has reappeared. Re-register w/ FC transport */
- memcpy(&wwn, &ndlp->nlp_nodename, sizeof(uint64_t));
- rport_ids.node_name = be64_to_cpu(wwn);
- memcpy(&wwn, &ndlp->nlp_portname, sizeof(uint64_t));
- rport_ids.port_name = be64_to_cpu(wwn);
+ rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
+ rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rport_ids.port_id = ndlp->nlp_DID;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
- if (ndlp->nlp_type & NLP_FCP_TARGET)
- rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
- if (ndlp->nlp_type & NLP_FCP_INITIATOR)
- rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
if (!rport) {
rdata = rport->dd_data;
rdata->pnode = ndlp;
+ if (ndlp->nlp_type & NLP_FCP_TARGET)
+ rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+ if (ndlp->nlp_type & NLP_FCP_INITIATOR)
+ rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
+
+ if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN)
+ fc_remote_port_rolechg(rport, rport_ids.roles);
+
+
+ return;
+}
+
+static void
+lpfc_unregister_remote_port(struct lpfc_hba * phba,
+ struct lpfc_nodelist * ndlp)
+{
+ struct fc_rport *rport = ndlp->rport;
+ struct lpfc_rport_data *rdata = rport->dd_data;
+
+ ndlp->rport = NULL;
+ rdata->pnode = NULL;
+ fc_remote_port_delete(rport);
+
return;
}
switch(list) {
case NLP_NO_LIST: /* No list, just remove it */
lpfc_nlp_remove(phba, nlp);
+ /* as node removed - stop further transport calls */
+ rport_del = none;
break;
case NLP_UNUSED_LIST:
spin_lock_irq(phba->host->host_lock);
* may have removed the remote port.
*/
if ((rport_del != none) && nlp->rport)
- fc_remote_port_block(nlp->rport);
+ lpfc_unregister_remote_port(phba, nlp);
if (rport_add != none) {
/*
*/
if (!nlp->rport)
lpfc_register_remote_port(phba, nlp);
- else
- fc_remote_port_unblock(nlp->rport);
/*
* if we added to Mapped list, but the remote port
iocb, iocb);
spin_lock_irq(phba->host->
host_lock);
- } else {
- list_add_tail(&iocb->list,
- &phba->lpfc_iocb_list);
- }
+ } else
+ lpfc_sli_release_iocbq(phba,
+ iocb);
}
}
spin_unlock_irq(phba->host->host_lock);
if (rc == MBX_NOT_FINISHED)
mempool_free( mbox, phba->mbox_mem_pool);
}
- lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
lpfc_no_rpi(phba, ndlp);
ndlp->nlp_rpi = 0;
return 1;
LPFC_MBOXQ_t *mb;
LPFC_MBOXQ_t *nextmb;
struct lpfc_dmabuf *mp;
- struct fc_rport *rport;
/* Cleanup node for NPort <nlp_DID> */
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
* and flush cache's w/o generating flush errors.
*/
if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
- rport = ndlp->rport;
- ndlp->rport = NULL;
- fc_remote_port_unblock(rport);
- fc_remote_port_delete(rport);
+ lpfc_unregister_remote_port(phba, ndlp);
ndlp->nlp_sid = NLP_NO_SID;
}
pmb->context1 = NULL;
- if (ndlp->nlp_rpi != 0)
- lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = mb->un.varWords[0];
- lpfc_addnode_rpi(phba, ndlp, ndlp->nlp_rpi);
ndlp->nlp_type |= NLP_FABRIC;
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
}
/*
- * This routine looks up the ndlp hash
- * table for the given RPI. If rpi found
+ * This routine looks up the ndlp lists
+ * for the given RPI. If rpi found
* it return the node list pointer
- * else return 0.
+ * else return NULL.
*/
struct lpfc_nodelist *
lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
{
- struct lpfc_nodelist *ret;
-
- ret = phba->fc_nlplookup[LPFC_RPI_HASH_FUNC(rpi)];
- while ((ret != 0) && (ret->nlp_rpi != rpi)) {
- ret = ret->nlp_rpi_hash_next;
- }
- return ret;
-}
-
-/*
- * This routine looks up the ndlp hash table for the
- * given RPI. If rpi found it return the node list
- * pointer else return 0 after deleting the entry
- * from hash table.
- */
-struct lpfc_nodelist *
-lpfc_findnode_remove_rpi(struct lpfc_hba * phba, uint16_t rpi)
-{
- struct lpfc_nodelist *ret, *temp;;
-
- ret = phba->fc_nlplookup[LPFC_RPI_HASH_FUNC(rpi)];
- if (ret == 0)
- return NULL;
-
- if (ret->nlp_rpi == rpi) {
- phba->fc_nlplookup[LPFC_RPI_HASH_FUNC(rpi)] =
- ret->nlp_rpi_hash_next;
- ret->nlp_rpi_hash_next = NULL;
- return ret;
- }
-
- while ((ret->nlp_rpi_hash_next != 0) &&
- (ret->nlp_rpi_hash_next->nlp_rpi != rpi)) {
- ret = ret->nlp_rpi_hash_next;
- }
-
- if (ret->nlp_rpi_hash_next != 0) {
- temp = ret->nlp_rpi_hash_next;
- ret->nlp_rpi_hash_next = temp->nlp_rpi_hash_next;
- temp->nlp_rpi_hash_next = NULL;
- return temp;
- } else {
- return NULL;
- }
-}
-
-/*
- * This routine adds the node list entry to the
- * ndlp hash table.
- */
-void
-lpfc_addnode_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
- uint16_t rpi)
-{
+ struct lpfc_nodelist *ndlp;
+ struct list_head * lists[]={&phba->fc_nlpunmap_list,
+ &phba->fc_nlpmap_list,
+ &phba->fc_plogi_list,
+ &phba->fc_adisc_list,
+ &phba->fc_reglogin_list};
+ int i;
- uint32_t index;
+ for (i = 0; i < ARRAY_SIZE(lists); i++ )
+ list_for_each_entry(ndlp, lists[i], nlp_listp)
+ if (ndlp->nlp_rpi == rpi)
+ return (ndlp);
- index = LPFC_RPI_HASH_FUNC(rpi);
- ndlp->nlp_rpi_hash_next = phba->fc_nlplookup[index];
- phba->fc_nlplookup[index] = ndlp;
- return;
+ return NULL;
}
void