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 + -
显示快捷键?