📄 qla_os.c
字号:
scsi_qla_host_t *ha; srb_t *sp; int rval = FAILED; ha = (scsi_qla_host_t *) cmd->device->host->hostdata; sp = (srb_t *) CMD_SP(cmd); qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d:%d): LOOP RESET ISSUED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); spin_unlock_irq(ha->host->host_lock); if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) { DEBUG2(printk("%s failed:board disabled\n",__func__)); spin_lock_irq(ha->host->host_lock); return FAILED; } if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) { if (qla2x00_loop_reset(ha) == QLA_SUCCESS) rval = SUCCESS; } spin_lock_irq(ha->host->host_lock); if (rval == FAILED) goto out; /* Waiting for our command in done_queue to be returned to OS.*/ if (cmd->device->host->eh_active) if (!qla2x00_eh_wait_for_pending_commands(ha)) rval = FAILED; out: qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, (rval == FAILED) ? "failed" : "succeded"); return rval;}/*************************************************************************** qla2xxx_eh_host_reset** Description:* The reset function will reset the Adapter.** Input:* cmd = Linux SCSI command packet of the command that cause the* adapter reset.** Returns:* Either SUCCESS or FAILED.** Note:**************************************************************************/intqla2xxx_eh_host_reset(struct scsi_cmnd *cmd){ scsi_qla_host_t *ha = (scsi_qla_host_t *)cmd->device->host->hostdata; int rval = SUCCESS; /* Display which one we're actually resetting for debug. */ DEBUG(printk("qla2xxx_eh_host_reset:Resetting scsi(%ld).\n", ha->host_no)); /* * Now issue reset. */ qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d:%d): ADAPTER RESET issued.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); spin_unlock_irq(ha->host->host_lock); if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) goto board_disabled; /* * Fixme-may be dpc thread is active and processing * loop_resync,so wait a while for it to * be completed and then issue big hammer.Otherwise * it may cause I/O failure as big hammer marks the * devices as lost kicking of the port_down_timer * while dpc is stuck for the mailbox to complete. */ /* Blocking call-Does context switching if loop is Not Ready */ qla2x00_wait_for_loop_ready(ha); set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); if (qla2x00_abort_isp(ha)) { clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); /* failed. schedule dpc to try */ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) goto board_disabled; } clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); spin_lock_irq(ha->host->host_lock); if (rval == FAILED) goto out; /* Waiting for our command in done_queue to be returned to OS.*/ if (!qla2x00_eh_wait_for_pending_commands(ha)) rval = FAILED; out: qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, (rval == FAILED) ? "failed" : "succeded"); return rval; board_disabled: spin_lock_irq(ha->host->host_lock); qla_printk(KERN_INFO, ha, "%s: failed:board disabled\n", __func__); return FAILED;}/** qla2x00_loop_reset* Issue loop reset.** Input:* ha = adapter block pointer.** Returns:* 0 = success*/static intqla2x00_loop_reset(scsi_qla_host_t *ha){ int status = QLA_SUCCESS; uint16_t t; os_tgt_t *tq; if (ha->flags.enable_lip_reset) { status = qla2x00_lip_reset(ha); } if (status == QLA_SUCCESS && ha->flags.enable_target_reset) { for (t = 0; t < MAX_FIBRE_DEVICES; t++) { if ((tq = TGT_Q(ha, t)) == NULL) continue; if (tq->fcport == NULL) continue; status = qla2x00_target_reset(ha, 0, t); if (status != QLA_SUCCESS) { break; } } } if (status == QLA_SUCCESS && ((!ha->flags.enable_target_reset && !ha->flags.enable_lip_reset) || ha->flags.enable_lip_full_login)) { status = qla2x00_full_login_lip(ha); } /* Issue marker command only when we are going to start the I/O */ ha->marker_needed = 1; if (status) { /* Empty */ DEBUG2_3(printk("%s(%ld): **** FAILED ****\n", __func__, ha->host_no);) } else { /* Empty */ DEBUG3(printk("%s(%ld): exiting normally.\n", __func__, ha->host_no);) } return(status);}/* * qla2x00_device_reset * Issue bus device reset message to the target. * * Input: * ha = adapter block pointer. * t = SCSI ID. * TARGET_QUEUE_LOCK must be released. * ADAPTER_STATE_LOCK must be released. * * Context: * Kernel context. */static intqla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport){ /* Abort Target command will clear Reservation */ return qla2x00_abort_target(reset_fcport);}/*************************************************************************** qla2xxx_slave_configure** Description:**************************************************************************/intqla2xxx_slave_configure(struct scsi_device *sdev){ scsi_qla_host_t *ha = to_qla_host(sdev->host); int queue_depth; if (IS_QLA2100(ha) || IS_QLA2200(ha)) queue_depth = 16; else queue_depth = 32; if (sdev->tagged_supported) { if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU) queue_depth = ql2xmaxqdepth; ql2xmaxqdepth = queue_depth; scsi_activate_tcq(sdev, queue_depth); qla_printk(KERN_INFO, ha, "scsi(%d:%d:%d:%d): Enabled tagged queuing, queue " "depth %d.\n", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun, sdev->queue_depth); } else { scsi_adjust_queue_depth(sdev, 0 /* TCQ off */, sdev->host->hostt->cmd_per_lun /* 3 */); } return (0);}/** * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. * @ha: HA context * * At exit, the @ha's flags.enable_64bit_addressing set to indicated * supported addressing method. */static voidqla2x00_config_dma_addressing(scsi_qla_host_t *ha){ /* Assume 32bit DMA address */ ha->flags.enable_64bit_addressing = 0; ha->calc_request_entries = qla2x00_calc_iocbs_32; ha->build_scsi_iocbs = qla2x00_build_scsi_iocbs_32; /* * Given the two variants pci_set_dma_mask(), allow the compiler to * assist in setting the proper dma mask. */ if (sizeof(dma_addr_t) > 4) { if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) { ha->flags.enable_64bit_addressing = 1; ha->calc_request_entries = qla2x00_calc_iocbs_64; ha->build_scsi_iocbs = qla2x00_build_scsi_iocbs_64; if (pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) { qla_printk(KERN_DEBUG, ha, "Failed to set 64 bit PCI consistent mask; " "using 32 bit.\n"); pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK); } } else { qla_printk(KERN_DEBUG, ha, "Failed to set 64 bit PCI DMA mask, falling back " "to 32 bit MASK.\n"); pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK); } } else { pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK); }}static intqla2x00_iospace_config(scsi_qla_host_t *ha){ unsigned long pio, pio_len, pio_flags; unsigned long mmio, mmio_len, mmio_flags; /* We only need PIO for Flash operations on ISP2312 v2 chips. */ pio = pci_resource_start(ha->pdev, 0); pio_len = pci_resource_len(ha->pdev, 0); pio_flags = pci_resource_flags(ha->pdev, 0); if (pio_flags & IORESOURCE_IO) { if (pio_len < MIN_IOBASE_LEN) { qla_printk(KERN_WARNING, ha, "Invalid PCI I/O region size (%s)...\n", ha->pdev->slot_name); pio = 0; } } else { qla_printk(KERN_WARNING, ha, "region #0 not a PIO resource (%s)...\n", ha->pdev->slot_name); pio = 0; } /* Use MMIO operations for all accesses. */ mmio = pci_resource_start(ha->pdev, 1); mmio_len = pci_resource_len(ha->pdev, 1); mmio_flags = pci_resource_flags(ha->pdev, 1); if (!(mmio_flags & IORESOURCE_MEM)) { qla_printk(KERN_ERR, ha, "region #0 not an MMIO resource (%s), aborting\n", ha->pdev->slot_name); goto iospace_error_exit; } if (mmio_len < MIN_IOBASE_LEN) { qla_printk(KERN_ERR, ha, "Invalid PCI mem region size (%s), aborting\n", ha->pdev->slot_name); goto iospace_error_exit; } if (pci_request_regions(ha->pdev, ha->brd_info->drv_name)) { qla_printk(KERN_WARNING, ha, "Failed to reserve PIO/MMIO regions (%s)\n", ha->pdev->slot_name); goto iospace_error_exit; } ha->pio_address = pio; ha->pio_length = pio_len; ha->iobase = ioremap(mmio, MIN_IOBASE_LEN); if (!ha->iobase) { qla_printk(KERN_ERR, ha, "cannot remap MMIO (%s), aborting\n", ha->pdev->slot_name); goto iospace_error_exit; } return (0);iospace_error_exit: return (-ENOMEM);}/* * PCI driver interface */int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info){ int ret; device_reg_t __iomem *reg; struct Scsi_Host *host; scsi_qla_host_t *ha; unsigned long flags = 0; unsigned long wait_switch = 0; char pci_info[20]; char fw_str[30]; if (pci_enable_device(pdev)) return -1; host = scsi_host_alloc(&qla2x00_driver_template, sizeof(scsi_qla_host_t)); if (host == NULL) { printk(KERN_WARNING "qla2xxx: Couldn't allocate host from scsi layer!\n"); goto probe_disable_device; } /* Clear our data area */ ha = (scsi_qla_host_t *)host->hostdata; memset(ha, 0, sizeof(scsi_qla_host_t)); ha->pdev = pdev; ha->host = host; ha->host_no = host->host_no; ha->brd_info = brd_info; sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no); /* Configure PCI I/O space */ ret = qla2x00_iospace_config(ha); if (ret != 0) { goto probe_failed; } /* Sanitize the information from PCI BIOS. */ host->irq = pdev->irq; qla_printk(KERN_INFO, ha, "Found an %s, irq %d, iobase 0x%p\n", ha->brd_info->isp_name, host->irq, ha->iobase); spin_lock_init(&ha->hardware_lock); /* 4.23 Initialize /proc/scsi/qla2x00 counters */ ha->actthreads = 0; ha->qthreads = 0; ha->total_isr_cnt = 0; ha->total_isp_aborts = 0; ha->total_lip_cnt = 0; ha->total_dev_errs = 0; ha->total_ios = 0; ha->total_bytes = 0; ha->prev_topology = 0; ha->ports = MAX_BUSES; if (IS_QLA2100(ha)) { ha->max_targets = MAX_TARGETS_2100; ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; ha->request_q_length = REQUEST_ENTRY_CNT_2100; ha->response_q_length = RESPONSE_ENTRY_CNT_2100; ha->last_loop_id = SNS_LAST_LOOP_ID_2100; host->sg_tablesize = 32; } else if (IS_QLA2200(ha)) { ha->max_targets = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->request_q_length = REQUEST_ENTRY_CNT_2200; ha->response_q_length = RESPONSE_ENTRY_CNT_2100; ha->last_loop_id = SNS_LAST_LOOP_ID_2100; } else /*if (IS_QLA2300(ha))*/ { ha->max_targets = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->request_q_length = REQUEST_ENTRY_CNT_2200; ha->response_q_length = RESPONSE_ENTRY_CNT_2300; ha->last_loop_id = SNS_LAST_LOOP_ID_2300; } host->can_queue = ha->request_q_length + 128; /* load the F/W, read paramaters, and init the H/W */ ha->instance = num_hosts; init_MUTEX(&ha->mbx_cmd_sem); init_MUTEX_LOCKED(&ha->mbx_intr_sem); INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); INIT_LIST_HEAD(&ha->rscn_fcports); INIT_LIST_HEAD(&ha->done_queue); INIT_LIST_HEAD(&ha->retry_queue); INIT_LIST_HEAD(&ha->scsi_retry_queue); INIT_LIST_HEAD(&ha->pending_queue); /* * These locks are used to prevent more than one CPU * from modifying the queue at the same time. The * higher level "host_lock" will reduce most * contention for these locks. */ spin_lock_init(&ha->mbx_reg_lock); spin_lock_init(&ha->list_lock); ha->dpc_pid = -1; init_completion(&ha->dpc_inited); init_completion(&ha->dpc_exited); qla2x00_config_dma_addressing(ha); if (qla2x00_mem_alloc(ha)) { qla_printk(KERN_WARNING, ha, "[ERROR] Failed to allocate memory for adapter\n"); goto probe_failed; } if (qla2x00_initialize_adapter(ha) && !(ha->device_flags & DFLG_NO_CABLE)) { qla_printk(KERN_WARNING, ha, "Failed to initialize adapter\n"); DEBUG2(printk("scsi(%ld): Failed to initialize adapter - " "Adapter flags %x.\n", ha->host_no, ha->device_flags)); goto probe_failed; } /* * Startup the kernel thread for this host adapter */ ha->dpc_should_die = 0; ha->dpc_pid = kernel_thread(qla2x00_do_dpc, ha, 0); if (ha->dpc_pid < 0) { qla_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n"); goto probe_failed; } wait_for_completion(&ha->dpc_inited); host->this_id = 255; host->cmd_per_lun = 3; host->max_cmd_len = MAX_CMDSZ; host->max_channel = ha->ports - 1; host->max_lun = ha->max_luns; BUG_ON(qla2xxx_transport_template == NULL); host->transportt = qla2xxx_transport_template; host->unique_id = ha->instance; host->max_id = ha->max_targets; if (IS_QLA2100(ha) || IS_QLA2200(ha)) ret = request_irq(host->irq, qla2100_intr_handler, SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha); else ret = request_irq(host->irq, qla2300_intr_handler, SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha); if (ret != 0) { qla_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d already in use.\n", host->irq); goto probe_failed;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -