⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qla_rscn.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
					 * to login to a remote port with just					 * a loop id without knowing about the					 * port id.  Copy the port id and try					 * again.					 */					remote_fcport->d_id.b24 = inuse_did.b24;					iodesc->d_id.b24 = inuse_did.b24;				} else {					remote_fcport->loop_id++;					rval = qla2x00_find_new_loop_id(ha,					    remote_fcport);					if (rval == QLA_FUNCTION_FAILED) {						/* No more loop ids. */						return (QLA_SUCCESS);					}				}			} else if (mb[0] == MBS_PORT_ID_USED) {				/*				 * Device has another loop ID.  The firmware				 * group recommends the driver perform an				 * implicit login with the specified ID.				 */				DEBUG14(printk("scsi(%ld): Login IOCB -- port "				    "id [%02x%02x%02x] already assigned to "				    "loop id [%x].\n", ha->host_no,				    iodesc->d_id.b.domain, iodesc->d_id.b.area,				    iodesc->d_id.b.al_pa, mb[1]));				remote_fcport->loop_id = mb[1];			} else {				/* Unable to perform login, try again. */				DEBUG14(printk("scsi(%ld): Login IOCB -- "				    "failed login [%x/%02x%02x%02x], status=%x "				    "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",				    ha->host_no, remote_fcport->loop_id,				    iodesc->d_id.b.domain, iodesc->d_id.b.area,				    iodesc->d_id.b.al_pa, status, mb[0], mb[1],				    mb[2], mb[6], mb[7]));			}			/* Reissue Login with the same IO descriptor. */			iodesc->signature =			    qla2x00_iodesc_to_handle(iodesc);			iodesc->cb_idx = LOGIN_PORT_IOCB_CB;			iodesc->d_id.b24 = remote_fcport->d_id.b24;			remote_fcport->iodesc_idx_sent = iodesc->idx;			remote_fcport->login_retry--;			DEBUG14(printk("scsi(%ld): Login IOCB -- retrying "			    "login to [%x/%02x%02x%02x] (%d).\n", ha->host_no,			    remote_fcport->loop_id,			    remote_fcport->d_id.b.domain,			    remote_fcport->d_id.b.area,			    remote_fcport->d_id.b.al_pa,			    remote_fcport->login_retry));			qla2x00_send_login_iocb(ha, iodesc,			    &remote_fcport->d_id, 1);			return (QLA_FUNCTION_FAILED);		} else {			/* No more logins, mark device dead. */			DEBUG14(printk("scsi(%ld): Login IOCB -- failed "			    "login [%x/%02x%02x%02x] after retries, status=%x "			    "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",			    ha->host_no, remote_fcport->loop_id,			    iodesc->d_id.b.domain, iodesc->d_id.b.area,			    iodesc->d_id.b.al_pa, status, mb[0], mb[1],			    mb[2], mb[6], mb[7]));			atomic_set(&remote_fcport->state, FCS_DEVICE_DEAD);			if (remote_fcport->port_type == FCT_RSCN) {				DEBUG14(printk("scsi(%ld): Login IOCB -- "				    "Freeing dead RSCN fcport %p "				    "[%x/%02x%02x%02x].\n", ha->host_no,				    remote_fcport, remote_fcport->loop_id,				    remote_fcport->d_id.b.domain,				    remote_fcport->d_id.b.area,				    remote_fcport->d_id.b.al_pa));				list_del(&remote_fcport->list);				kfree(remote_fcport);			}		}	}	return (QLA_SUCCESS);}/** * IO descriptor processing routines. **//** * qla2x00_alloc_rscn_fcport() - Allocate an RSCN type fcport. * @ha: HA context * @flags: allocation flags * * Returns a pointer to the allocated RSCN fcport, or NULL, if none available. */fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags){	fc_port_t *fcport;	fcport = qla2x00_alloc_fcport(ha, flags);	if (fcport == NULL)		return (fcport);	/* Setup RSCN fcport structure. */	fcport->port_type = FCT_RSCN;	return (fcport);}/** * qla2x00_handle_port_rscn() - Handle port RSCN. * @ha: HA context * @rscn_entry: RSCN entry * @fcport: fcport entry to updated * * Returns QLA_SUCCESS if the port RSCN was handled. */intqla2x00_handle_port_rscn(scsi_qla_host_t *ha, uint32_t rscn_entry,    fc_port_t *known_fcport, int ha_locked){	int	rval;	port_id_t rscn_pid;	fc_port_t *fcport, *remote_fcport, *rscn_fcport;	struct io_descriptor *iodesc;	remote_fcport = NULL;	rscn_fcport = NULL;	/* Prepare port id based on incoming entries. */	if (known_fcport) {		rscn_pid.b24 = known_fcport->d_id.b24;		remote_fcport = known_fcport;		DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "		    "fcport [%02x%02x%02x].\n", ha->host_no,		    remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area,		    remote_fcport->d_id.b.al_pa));	} else {		rscn_pid.b.domain = LSB(MSW(rscn_entry));		rscn_pid.b.area = MSB(LSW(rscn_entry));		rscn_pid.b.al_pa = LSB(LSW(rscn_entry));		DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "		    "port id [%02x%02x%02x].\n", ha->host_no,		    rscn_pid.b.domain, rscn_pid.b.area, rscn_pid.b.al_pa));		/*		 * Search fcport lists for a known entry at the specified port		 * ID.		 */		list_for_each_entry(fcport, &ha->fcports, list) {		    if (rscn_pid.b24 == fcport->d_id.b24) {			    remote_fcport = fcport;			    break;		    }		}		list_for_each_entry(fcport, &ha->rscn_fcports, list) {		    if (rscn_pid.b24 == fcport->d_id.b24) {			    rscn_fcport = fcport;			    break;		    }		}		if (remote_fcport == NULL)		    remote_fcport = rscn_fcport;	}	/*	 * If the port is already in our fcport list and online, send an ADISC	 * to see if it's still alive.  Issue login if a new fcport or the known	 * fcport is currently offline.	 */	if (remote_fcport) {		/*		 * No need to send request if the remote fcport is currently		 * waiting for an available io descriptor.		 */		if (known_fcport == NULL &&		    (remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||		    remote_fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED)) {			/*			 * If previous waiting io descriptor is an ADISC, then			 * the new RSCN may come from a new remote fcport being			 * plugged into the same location.			 */			if (remote_fcport->port_type == FCT_RSCN) {			    remote_fcport->iodesc_idx_sent =				IODESC_LOGIN_NEEDED;			} else if (remote_fcport->iodesc_idx_sent ==			    IODESC_ADISC_NEEDED) {				fc_port_t *new_fcport;				remote_fcport->iodesc_idx_sent =				    IODESC_INVALID_INDEX;				/* Create new fcport for later login. */				new_fcport = qla2x00_alloc_rscn_fcport(ha,				    ha_locked ? GFP_ATOMIC: GFP_KERNEL);				if (new_fcport) {					DEBUG14(printk("scsi(%ld): Handle RSCN "					    "-- creating RSCN fcport %p for "					    "future login.\n", ha->host_no,					    new_fcport));					new_fcport->d_id.b24 =					    remote_fcport->d_id.b24;					new_fcport->iodesc_idx_sent =					    IODESC_LOGIN_NEEDED;					list_add_tail(&new_fcport->list,					    &ha->rscn_fcports);					set_bit(IODESC_PROCESS_NEEDED,					    &ha->dpc_flags);				} else {					DEBUG14(printk("scsi(%ld): Handle RSCN "					    "-- unable to allocate RSCN fcport "					    "for future login.\n",					    ha->host_no));				}			}			return (QLA_SUCCESS);		}		/* Send ADISC if the fcport is online */		if (atomic_read(&remote_fcport->state) == FCS_ONLINE ||		    remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED) {			atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);			iodesc = qla2x00_alloc_iodesc(ha);			if (iodesc == NULL) {				/* Mark fcport for later adisc processing */				DEBUG14(printk("scsi(%ld): Handle RSCN -- not "				    "enough IO descriptors for Adisc, flag "				    "for later processing.\n", ha->host_no));				remote_fcport->iodesc_idx_sent =				    IODESC_ADISC_NEEDED;				set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);				return (QLA_SUCCESS);			}			iodesc->cb_idx = ADISC_PORT_IOCB_CB;			iodesc->d_id.b24 = rscn_pid.b24;			iodesc->remote_fcport = remote_fcport;			remote_fcport->iodesc_idx_sent = iodesc->idx;			qla2x00_send_adisc_iocb(ha, iodesc, ha_locked);			return (QLA_SUCCESS);		} else if (remote_fcport->iodesc_idx_sent <		    MAX_IO_DESCRIPTORS &&		    ha->io_descriptors[remote_fcport->iodesc_idx_sent].cb_idx ==		    ADISC_PORT_IOCB_CB) {			/*			 * Receiving another RSCN while an ADISC is pending,			 * abort the IOCB.  Use the same descriptor for the			 * abort.			 */			uint32_t handle_to_abort;			iodesc = &ha->io_descriptors[				remote_fcport->iodesc_idx_sent];			qla2x00_remove_iodesc_timer(iodesc);			handle_to_abort = iodesc->signature;			iodesc->signature = qla2x00_iodesc_to_handle(iodesc);			iodesc->cb_idx = ABORT_IOCB_CB;			iodesc->d_id.b24 = remote_fcport->d_id.b24;			iodesc->remote_fcport = remote_fcport;			remote_fcport->iodesc_idx_sent = iodesc->idx;			DEBUG14(printk("scsi(%ld): Handle RSCN -- issuing "			    "abort to outstanding Adisc [%x/%02x%02x%02x].\n",			    ha->host_no, remote_fcport->loop_id,			    iodesc->d_id.b.domain, iodesc->d_id.b.area,			    iodesc->d_id.b.al_pa));			qla2x00_send_abort_iocb(ha, iodesc, handle_to_abort,			    ha_locked);		}	}	/* We need to login to the remote port, find it. */	if (known_fcport) {		remote_fcport = known_fcport;	} else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&	    rscn_fcport->iodesc_idx_sent < MAX_IO_DESCRIPTORS &&	    ha->io_descriptors[rscn_fcport->iodesc_idx_sent].cb_idx ==	    LOGIN_PORT_IOCB_CB) {		/*		 * Ignore duplicate RSCN on fcport which has already		 * initiated a login IOCB.		 */		DEBUG14(printk("scsi(%ld): Handle RSCN -- ignoring, login "		    "already sent to [%02x%02x%02x].\n", ha->host_no,		    rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,		    rscn_fcport->d_id.b.al_pa));		return (QLA_SUCCESS);	} else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&	    rscn_fcport != remote_fcport) {		/* Reuse same rscn fcport. */		DEBUG14(printk("scsi(%ld): Handle RSCN -- reusing RSCN fcport "		    "[%02x%02x%02x].\n", ha->host_no,		    rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,		    rscn_fcport->d_id.b.al_pa));		remote_fcport = rscn_fcport;	} else {		/* Create new fcport for later login. */		remote_fcport = qla2x00_alloc_rscn_fcport(ha,		    ha_locked ? GFP_ATOMIC: GFP_KERNEL);		list_add_tail(&remote_fcport->list, &ha->rscn_fcports);	}	if (remote_fcport == NULL)		return (QLA_SUCCESS);	/* Prepare fcport for login. */	atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);	remote_fcport->login_retry = 3; /* ha->login_retry_count; */	remote_fcport->d_id.b24 = rscn_pid.b24;	iodesc = qla2x00_alloc_iodesc(ha);	if (iodesc == NULL) {		/* Mark fcport for later adisc processing. */		DEBUG14(printk("scsi(%ld): Handle RSCN -- not enough IO "		    "descriptors for Login, flag for later processing.\n",		    ha->host_no));		remote_fcport->iodesc_idx_sent = IODESC_LOGIN_NEEDED;		set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);		return (QLA_SUCCESS);	}	if (known_fcport == NULL || rscn_pid.b24 != INVALID_PORT_ID) {		remote_fcport->loop_id = ha->min_external_loopid;		rval = qla2x00_find_new_loop_id(ha, remote_fcport);		if (rval == QLA_FUNCTION_FAILED) {			/* No more loop ids, failed. */			DEBUG14(printk("scsi(%ld): Handle RSCN -- no available "			    "loop id to perform Login, failed.\n",			    ha->host_no));			return (rval);		}	}	iodesc->cb_idx = LOGIN_PORT_IOCB_CB;	iodesc->d_id.b24 = rscn_pid.b24;	iodesc->remote_fcport = remote_fcport;	remote_fcport->iodesc_idx_sent = iodesc->idx;	DEBUG14(printk("scsi(%ld): Handle RSCN -- attempting login to "	    "[%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id,	    iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa));	qla2x00_send_login_iocb(ha, iodesc, &rscn_pid, ha_locked);	return (QLA_SUCCESS);}/** * qla2x00_process_iodesc() - Complete IO descriptor processing. * @ha: HA context * @mbxstat: Mailbox IOCB status */voidqla2x00_process_iodesc(scsi_qla_host_t *ha, struct mbx_entry *mbxstat){	int rval;	uint32_t signature;	fc_port_t *fcport;	struct io_descriptor *iodesc;	signature = mbxstat->handle;	DEBUG14(printk("scsi(%ld): Process IODesc -- processing %08x.\n",	    ha->host_no, signature));	/* Retrieve proper IO descriptor. */	iodesc = qla2x00_handle_to_iodesc(ha, signature);	if (iodesc == NULL) {		DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "		    "incorrect signature %08x.\n", ha->host_no, signature));		return;	}	/* Stop IO descriptor timer. */	qla2x00_remove_iodesc_timer(iodesc);	/* Verify signature match. */	if (iodesc->signature != signature) {		DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "		    "signature mismatch, sent %08x, received %08x.\n",		    ha->host_no, iodesc->signature, signature));		return;	}	/* Go with IOCB callback. */	rval = iocb_function_cb_list[iodesc->cb_idx](ha, iodesc, mbxstat);	if (rval != QLA_SUCCESS) {		/* IO descriptor reused by callback. */		return;	}	qla2x00_free_iodesc(iodesc);	if (test_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags)) {		/* Scan our fcports list for any RSCN requests. */		list_for_each_entry(fcport, &ha->fcports, list) {			if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||			    fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {				qla2x00_handle_port_rscn(ha, 0, fcport, 1);				return;			}		}		/* Scan our RSCN fcports list for any RSCN requests. */		list_for_each_entry(fcport, &ha->rscn_fcports, list) {			if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||			    fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {				qla2x00_handle_port_rscn(ha, 0, fcport, 1);				return;			}		}	}	clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);}/** * qla2x00_cancel_io_descriptors() - Cancel all outstanding io descriptors. * @ha: HA context * * This routine will also delete any RSCN entries related to the outstanding * IO descriptors. */voidqla2x00_cancel_io_descriptors(scsi_qla_host_t *ha){	fc_port_t *fcport, *fcptemp;	clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);	/* Abort all IO descriptors. */	qla2x00_init_io_descriptors(ha);	/* Reset all pending IO descriptors in fcports list. */	list_for_each_entry(fcport, &ha->fcports, list) {		fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;	}	/* Reset all pending IO descriptors in rscn fcports list. */	list_for_each_entry_safe(fcport, fcptemp, &ha->rscn_fcports, list) {		DEBUG14(printk("scsi(%ld): Cancel IOs -- Freeing RSCN fcport "		    "%p [%x/%02x%02x%02x].\n", ha->host_no, fcport,		    fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,		    fcport->d_id.b.al_pa));		list_del(&fcport->list);		kfree(fcport);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -