qla_ip.c

来自「这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自」· C语言 代码 · 共 1,757 行 · 第 1/4 页

C
1,757
字号
		ha->ipdev_db_top = ipdev->next;	else		ipdev->last->next = ipdev->next;	if (ipdev->next == NULL)		ha->ipdev_db_bottom = ipdev->last;	else		ipdev->next->last = ipdev->last;	/* Add IP device block to free list */	ipdev->next = ha->ipdev_db_next_free;	ha->ipdev_db_next_free = ipdev;}/** * qla2x00_reserve_ip_block() - Move an IP device to the IP device list. * @ha: SCSI driver HA context * @ipdevblk: reserved IP device to add  * * This routine will move the unused @ipdevblk from the free list to the top of * the active IP device list. * * Returns QL_STATUS_SUCCESS if the operation succeeded. */static intqla2x00_reserve_ip_block(scsi_qla_host_t *ha, struct ip_device **ipdevblk){	struct ip_device *ipdev;	/* Get free IP device block */	ipdev = ha->ipdev_db_next_free;	if (ipdev) { 		/* Remove IP device block from free list */		ha->ipdev_db_next_free = ipdev->next;		/* Add IP device block to top of IP device list */		ipdev->next = ha->ipdev_db_top;		ipdev->last = NULL;		if (ha->ipdev_db_top == NULL)			ha->ipdev_db_bottom = ipdev;		else			ha->ipdev_db_top->last = ipdev;		ha->ipdev_db_top = ipdev;		*ipdevblk = ipdev;		return (QL_STATUS_SUCCESS);	}	/* Out of IP blocks */	DEBUG12(printk("%s: out of IP blocks\n", __func__);)	return (QL_STATUS_RESOURCE_ERROR);}/** * qla2x00_update_ip_device_data() - Update IP device list with driver data. * @ha: SCSI driver HA context * @fcdev: SCSI driver FC device list * * This routine searchs for the device port name in the current IP database and * updates the IP device list. * * If device found: *	- Handle device movement between public and private loops *	- Mark device present *	- Log in device if necessary * If device not found and private loop device: *	- Insert the new entry in database * If device not found and public IP device: * 	- Ignore device until packet received from device * * Returns QL_STATUS_SUCCESS if the operation succeeded. */static intqla2x00_update_ip_device_data(scsi_qla_host_t *ha, fcdev_t *fcdev){	int	status;	struct ip_device *ipdev;	status = 0;	if (!ha->flags.enable_ip) {		/* IP not enabled, just return */		return (QL_STATUS_SUCCESS);	}	/* Scan list of IP devices for match */	for (ipdev = ha->ipdev_db_top; ipdev; ipdev = ipdev->next) {		if (memcmp(fcdev->wwn, ipdev->port_name, WWN_SIZE))			continue;		/* Found device in IP device list */		DEBUG12(printk("%s: already in IP list, port ID: %x\n",				__func__,				ipdev->port_id[2] << 16 |				 ipdev->port_id[1] << 8 |				 ipdev->port_id[0]);)		if (fcdev->flag != DEV_PUBLIC &&			!(ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) {			/*			 * Device on private loop now, was on private loop			 * before.			 */			DEBUG12(printk("%s: was private loop, now "					"private loop\n",					__func__);)			/* Update private loop ID in database */			ipdev->loop_id = fcdev->loop_id;			ipdev->flags |= IP_DEV_FLAG_PRESENT;		}		else if (fcdev->flag != DEV_PUBLIC &&				(ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) {			/*			 * Device on private loop now, was public device before.			 */			DEBUG12(printk("%s: was public, now private loop\n",					__func__);)			/*			 * If loop ID changed, logout device and free loop ID.			 */			if (fcdev->loop_id != ipdev->loop_id) { 				qla2x00_ip_send_logout_port_iocb(ha, ipdev, 0);				qla2x00_free_loopid(ha, ipdev->loop_id);				/*				 * Clear public device flag and save private				 * loop ID in database.				 */				ipdev->flags &= ~IP_DEV_FLAG_PUBLIC_DEVICE;				ipdev->loop_id = fcdev->loop_id;			}			ipdev->flags |= IP_DEV_FLAG_PRESENT;		}		else if (fcdev->flag == DEV_PUBLIC &&				!(ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) {			/*			 * Device public now, was on private loop before.			 */			DEBUG12(printk("%s: was private loop, now public\n",					__func__);)			/*			 * Reserve public loop ID, save it in database.			 */			status = qla2x00_reserve_loopid(ha, &ipdev->loop_id);			if (status == QL_STATUS_SUCCESS) { 				/*				 * Save port ID and set public device flag.				 */				ipdev->port_id[0] = fcdev->d_id.r.d_id[0];				ipdev->port_id[1] = fcdev->d_id.r.d_id[1];				ipdev->port_id[2] = fcdev->d_id.r.d_id[2];				ipdev->flags |= IP_DEV_FLAG_PUBLIC_DEVICE;				/* Login public device */				status = qla2x00_ip_send_login_port_iocb(ha,							ipdev, 0);			}			if (status == QL_STATUS_RESOURCE_ERROR) {				/* Out of loop IDs */				ipdev->flags &= ~IP_DEV_FLAG_PUBLIC_DEVICE;			}		}		else {			/*			 * Device public now, was public device before.			 */			DEBUG12(printk("%s: was public, now public\n",					__func__);)			/* Check if port ID changed */			if (ipdev->port_id[0] != fcdev->d_id.r.d_id[0] ||				ipdev->port_id[1] != fcdev->d_id.r.d_id[1] ||				ipdev->port_id[2] != fcdev->d_id.r.d_id[2]) {				/* Save new port ID */				ipdev->port_id[0] = fcdev->d_id.r.d_id[0];				ipdev->port_id[1] = fcdev->d_id.r.d_id[1];				ipdev->port_id[2] = fcdev->d_id.r.d_id[2];				DEBUG12(printk("%s: Port ID changed\n",						__func__);)				/* Logout public device */				qla2x00_ip_send_logout_port_iocb(ha, ipdev, 0);			}			/* Login public device */			status = qla2x00_ip_send_login_port_iocb(ha, ipdev, 0);			if (status == QL_STATUS_RESOURCE_ERROR) {				/* Out of loop IDs */				ipdev->flags &= ~IP_DEV_FLAG_PUBLIC_DEVICE;			}		}		return (status);	}	/* Device not found in database */	DEBUG12(printk("%s: device NOT in list\n", __func__);)	/* If private loop device, add device to IP list */	/* Public devices will be added as needed when packet received */	if (fcdev->flag != DEV_PUBLIC) {		/* Add (force) new private loop device to IP list */		status = qla2x00_add_new_ip_device(ha,					fcdev->loop_id,					NULL,					fcdev->wwn,					TRUE,					0);	}	/* The following code is temporary, until FARP supported */	/* Login all IP public devices for now */	if (fcdev->flag == DEV_PUBLIC) {		/* Add (don't force) new public device to IP list */		status = qla2x00_add_new_ip_device(ha,					PUBLIC_LOOP_DEVICE,					(uint8_t *)&fcdev->d_id,					fcdev->wwn,					FALSE,					0);	}	return (status);}/** * qla2x00_ip_send_login_port_iocb() - Login to an IP device. * @ha: SCSI driver HA context * @ipdev: IP device to login to * @ha_locked: Flag indicating if the function is called with the hardware lock * * This routine will build and send a mailbox IOCB to login to a fabric port. * * The qla2x00_ip_mailbox_iocb_done() routine will be called upon IOCB * completion, where further processing is performed. * * Returns QL_STATUS_SUCCESS if the operation succeeded. */static intqla2x00_ip_send_login_port_iocb(scsi_qla_host_t *ha,				struct ip_device *ipdev, uint32_t ha_locked){	unsigned long	flags = 0;	struct mbx_entry *mbxentry;	DEBUG12(printk("%s: port ID: %x\n",			__func__,			ipdev->port_id[2]<<16 |			ipdev->port_id[1]<<8 |			ipdev->port_id[0]);)	/* Send marker if required */	if (ha->marker_needed != 0) {		if (ha_locked) {			if(__qla2x00_marker(ha,					0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS)				return (QL_STATUS_ERROR);		}		else {			if(qla2x00_marker(ha,					0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS)				return (QL_STATUS_ERROR);		}		ha->marker_needed = 0;	}	if (!ha_locked)		spin_lock_irqsave(&ha->hardware_lock, flags);	mbxentry = (struct mbx_entry *)qla2x00_req_pkt(ha);	if (mbxentry == NULL) {		DEBUG12(printk("%s: failed\n", __func__);)		if (!ha_locked)			spin_unlock_irqrestore(&ha->hardware_lock, flags);		return (QL_STATUS_ERROR);	}	/* Build fabric login MBX IOCB */	mbxentry->entry_type = ET_MAILBOX_COMMAND;	mbxentry->entry_count = 1;	mbxentry->sys_define1 = SOURCE_IP;	mbxentry->entry_status = 0;	mbxentry->handle = ipdev->index | (MBC_LOGIN_FABRIC_PORT << 16);	mbxentry->loop_id = ipdev->loop_id;	mbxentry->mb0 = MBC_LOGIN_FABRIC_PORT;	mbxentry->mb1 = (ipdev->loop_id << 8) | 				(MBC_NO_PROCESS_LOGIN |				 MBC_NO_PLOGI_IF_LOGGED_IN);	mbxentry->mb2 = ipdev->port_id[2];	mbxentry->mb3 = (ipdev->port_id[1] << 8) | ipdev->port_id[0];	mbxentry->mb6 = 0;	mbxentry->mb7 = 0;	/* Issue command to ISP */	qla2x00_isp_cmd(ha);	if (!ha_locked)		spin_unlock_irqrestore(&ha->hardware_lock, flags);	return (QL_STATUS_SUCCESS);}/** * qla2x00_ip_send_logout_port_iocb() - Logout an IP device. * @ha: SCSI driver HA context * @ipdev: IP device to logout * @ha_locked: Flag indicating if the function is called with the hardware lock * * This routine will build and send a mailbox IOCB to logout a fabric port. * * The qla2x00_ip_mailbox_iocb_done() routine will be called upon IOCB * completion, where further processing is performed. * * Returns QL_STATUS_SUCCESS if the operation succeeded. */static intqla2x00_ip_send_logout_port_iocb(scsi_qla_host_t *ha,				struct ip_device *ipdev, uint32_t ha_locked){	unsigned long	flags = 0;	struct mbx_entry *mbxentry;	DEBUG12(printk("%s: port ID: %x\n",			__func__,			ipdev->port_id[2]<<16 |			ipdev->port_id[1]<<8 |			ipdev->port_id[0]);)	/* Send marker if required */	if (ha->marker_needed != 0) {		if (ha_locked) {			if(__qla2x00_marker(ha,					0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS)				return (QL_STATUS_ERROR);		}		else {			if(qla2x00_marker(ha,					0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS)				return (QL_STATUS_ERROR);		}		ha->marker_needed = 0;	}	if (!ha_locked)		spin_lock_irqsave(&ha->hardware_lock, flags);	mbxentry = (struct mbx_entry *)qla2x00_req_pkt(ha);	if (mbxentry == NULL) {		DEBUG12(printk("%s: failed\n", __func__);)		if (!ha_locked)			spin_unlock_irqrestore(&ha->hardware_lock, flags);		return (QL_STATUS_ERROR);	}	/* Build fabric logout MBX IOCB */	mbxentry->entry_type = ET_MAILBOX_COMMAND;	mbxentry->entry_count = 1;	mbxentry->sys_define1 = SOURCE_IP;	mbxentry->entry_status = 0;	mbxentry->handle = ipdev->index | (MBC_LOGOUT_FABRIC_PORT << 16);	mbxentry->loop_id = ipdev->loop_id;	mbxentry->mb0 = MBC_LOGOUT_FABRIC_PORT;	mbxentry->mb1 = ipdev->loop_id << 8;	mbxentry->mb2 = 0;	mbxentry->mb3 = 0;	mbxentry->mb6 = 0;	mbxentry->mb7 = 0;	/* Issue command to ISP */	qla2x00_isp_cmd(ha);	if (!ha_locked)		spin_unlock_irqrestore(&ha->hardware_lock, flags);	return (QL_STATUS_SUCCESS);}/** * qla2x00_ip_mailbox_iocb_done() - Process an mailbox IOCB completion. * @ha: SCSI driver HA context * @mbxentry: completed mailbox IOCB entry * * This routine is currently used for fabric login and logouts only. */static voidqla2x00_ip_mailbox_iocb_done(scsi_qla_host_t *ha, struct mbx_entry *mbxentry){	int		status;	uint16_t	cmd;	uint16_t	index;	struct ip_device *ipdev;	/* Parse-out originating mailbox command */	cmd = MSW(mbxentry->handle);	DEBUG12(printk("%s: cmd %x, status %x, mb0 %x, mb1 %x, mb2 %x\n",			__func__,			cmd,			mbxentry->status,			mbxentry->mb0,			mbxentry->mb1,			mbxentry->mb2);)	/* Get device block pointer */	index = LSW(mbxentry->handle);	if (index >= QLLAN_MAX_IP_DEVICES) {		/* Bad handle from ISP */		DEBUG12(printk("%s: bad handle from isp\n", __func__);)		/* TODO: Cleanup??? */		return;	}	ipdev = &ha->ipdev_db[index];	if (cmd == MBC_LOGOUT_FABRIC_PORT) {		/* Check fabric logout completion status */		if (/*mbxentry->status == CS_COMPLETE && */			mbxentry->mb0 == MBS_COMMAND_COMPLETE) {			/* Logout successful -- do nothing */		}		else {			DEBUG12(printk("%s: fabric logout failed\n", __func__);)		}	}	else {		/* Check fabric login completion status */		/* Note: sometimes ISP returns Status=0x30 and MB0=0x4000 */

⌨️ 快捷键说明

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