📄 qla_os.c
字号:
} /* Initialized the timer */ qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL); DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", ha->host_no, ha)); reg = ha->iobase; /* Disable ISP interrupts. */ qla2x00_disable_intrs(ha); /* Ensure mailbox registers are free. */ spin_lock_irqsave(&ha->hardware_lock, flags); WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); WRT_REG_WORD(®->hccr, HCCR_CLR_HOST_INT); /* Enable proper parity */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) { if (IS_QLA2300(ha)) /* SRAM parity */ WRT_REG_WORD(®->hccr, (HCCR_ENABLE_PARITY + 0x1)); else /* SRAM, Instruction RAM and GP RAM parity */ WRT_REG_WORD(®->hccr, (HCCR_ENABLE_PARITY + 0x7)); } spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Enable chip interrupts. */ qla2x00_enable_intrs(ha); /* v2.19.5b6 */ /* * Wait around max loop_reset_delay secs for the devices to come * on-line. We don't want Linux scanning before we are ready. * */ for (wait_switch = jiffies + (ha->loop_reset_delay * HZ); time_before(jiffies,wait_switch) && !(ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES)) && (ha->device_flags & SWITCH_FOUND) ;) { qla2x00_check_fabric_devices(ha); msleep(10); } pci_set_drvdata(pdev, ha); ha->flags.init_done = 1; num_hosts++; /* List the target we have found */ if (displayConfig) { qla2x00_display_fc_names(ha); } if (scsi_add_host(host, &pdev->dev)) goto probe_failed; sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); qla_printk(KERN_INFO, ha, "\n" " QLogic Fibre Channel HBA Driver: %s\n" " QLogic %s - %s\n" " %s: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str, ha->model_number, ha->model_desc ? ha->model_desc: "", ha->brd_info->isp_name, qla2x00_get_pci_info_str(ha, pci_info), pci_name(ha->pdev), ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, qla2x00_get_fw_version_str(ha, fw_str)); if (ql2xdoinitscan) scsi_scan_host(host); return 0;probe_failed: qla2x00_free_device(ha); scsi_host_put(host);probe_disable_device: pci_disable_device(pdev); return -1;}EXPORT_SYMBOL_GPL(qla2x00_probe_one);void qla2x00_remove_one(struct pci_dev *pdev){ scsi_qla_host_t *ha; ha = pci_get_drvdata(pdev); sysfs_remove_bin_file(&ha->host->shost_gendev.kobj, &sysfs_fw_dump_attr); sysfs_remove_bin_file(&ha->host->shost_gendev.kobj, &sysfs_nvram_attr); scsi_remove_host(ha->host); qla2x00_free_device(ha); scsi_host_put(ha->host); pci_set_drvdata(pdev, NULL);}EXPORT_SYMBOL_GPL(qla2x00_remove_one);static voidqla2x00_free_device(scsi_qla_host_t *ha){ int ret; /* Abort any outstanding IO descriptors. */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) qla2x00_cancel_io_descriptors(ha); /* turn-off interrupts on the card */ if (ha->interrupts_on) qla2x00_disable_intrs(ha); /* Disable timer */ if (ha->timer_active) qla2x00_stop_timer(ha); /* Kill the kernel thread for this host */ if (ha->dpc_pid >= 0) { ha->dpc_should_die = 1; wmb(); ret = kill_proc(ha->dpc_pid, SIGHUP, 1); if (ret) { qla_printk(KERN_ERR, ha, "Unable to signal DPC thread -- (%d)\n", ret); /* TODO: SOMETHING MORE??? */ } else { wait_for_completion(&ha->dpc_exited); } } qla2x00_mem_free(ha); ha->flags.online = 0; /* Detach interrupts */ if (ha->pdev->irq) free_irq(ha->pdev->irq, ha); /* release io space registers */ if (ha->iobase) iounmap(ha->iobase); pci_release_regions(ha->pdev); pci_disable_device(ha->pdev);}/* * The following support functions are adopted to handle * the re-entrant qla2x00_proc_info correctly. */static voidcopy_mem_info(struct info_str *info, char *data, int len){ if (info->pos + len > info->offset + info->length) len = info->offset + info->length - info->pos; if (info->pos + len < info->offset) { info->pos += len; return; } if (info->pos < info->offset) { off_t partial; partial = info->offset - info->pos; data += partial; info->pos += partial; len -= partial; } if (len > 0) { memcpy(info->buffer, data, len); info->pos += len; info->buffer += len; }}static intcopy_info(struct info_str *info, char *fmt, ...){ va_list args; char buf[256]; int len; va_start(args, fmt); len = vsprintf(buf, fmt, args); va_end(args); copy_mem_info(info, buf, len); return (len);}/************************************************************************** qla2x00_proc_info** Description:* Return information to handle /proc support for the driver.** inout : decides the direction of the dataflow and the meaning of the* variables* buffer: If inout==0 data is being written to it else read from it* (ptr to a page buffer)* *start: If inout==0 start of the valid data in the buffer* offset: If inout==0 starting offset from the beginning of all* possible data to return.* length: If inout==0 max number of bytes to be written into the buffer* else number of bytes in "buffer"* Returns:* < 0: error. errno value.* >= 0: sizeof data returned.*************************************************************************/intqla2x00_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length, int inout){ struct info_str info; int retval = -EINVAL; os_lun_t *up; os_tgt_t *tq; unsigned int t, l; uint32_t tmp_sn; uint32_t *flags; uint8_t *loop_state; scsi_qla_host_t *ha; char fw_info[30]; DEBUG3(printk(KERN_INFO "Entering proc_info buff_in=%p, offset=0x%lx, length=0x%x\n", buffer, offset, length);) ha = (scsi_qla_host_t *) shost->hostdata; if (inout) { /* Has data been written to the file? */ DEBUG3(printk( "%s: has data been written to the file. \n", __func__);) return -ENOSYS; } if (start) { *start = buffer; } info.buffer = buffer; info.length = length; info.offset = offset; info.pos = 0; /* start building the print buffer */ copy_info(&info, "QLogic PCI to Fibre Channel Host Adapter for %s:\n" " Firmware version %s, ", ha->model_number, qla2x00_get_fw_version_str(ha, fw_info)); copy_info(&info, "Driver version %s\n", qla2x00_version_str); tmp_sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; copy_info(&info, "ISP: %s, Serial# %c%05d\n", ha->brd_info->isp_name, ('A' + tmp_sn/100000), (tmp_sn%100000)); copy_info(&info, "Request Queue = 0x%llx, Response Queue = 0x%llx\n", (unsigned long long)ha->request_dma, (unsigned long long)ha->response_dma); copy_info(&info, "Request Queue count = %d, Response Queue count = %d\n", ha->request_q_length, ha->response_q_length); copy_info(&info, "Total number of active commands = %ld\n", ha->actthreads); copy_info(&info, "Total number of interrupts = %ld\n", (long)ha->total_isr_cnt); copy_info(&info, " Device queue depth = 0x%x\n", (ql2xmaxqdepth == 0) ? 16 : ql2xmaxqdepth); copy_info(&info, "Number of free request entries = %d\n", ha->req_q_cnt); copy_info(&info, "Number of mailbox timeouts = %ld\n", ha->total_mbx_timeout); copy_info(&info, "Number of ISP aborts = %ld\n", ha->total_isp_aborts); copy_info(&info, "Number of loop resyncs = %ld\n", ha->total_loop_resync); copy_info(&info, "Number of retries for empty slots = %ld\n", qla2x00_stats.outarray_full); copy_info(&info, "Number of reqs in pending_q= %ld, retry_q= %d, " "done_q= %ld, scsi_retry_q= %d\n", ha->qthreads, ha->retry_q_cnt, ha->done_q_cnt, ha->scsi_retry_q_cnt); flags = (uint32_t *) &ha->flags; if (atomic_read(&ha->loop_state) == LOOP_DOWN) { loop_state = "DOWN"; } else if (atomic_read(&ha->loop_state) == LOOP_UP) { loop_state = "UP"; } else if (atomic_read(&ha->loop_state) == LOOP_READY) { loop_state = "READY"; } else if (atomic_read(&ha->loop_state) == LOOP_TIMEOUT) { loop_state = "TIMEOUT"; } else if (atomic_read(&ha->loop_state) == LOOP_UPDATE) { loop_state = "UPDATE"; } else { loop_state = "UNKNOWN"; } copy_info(&info, "Host adapter:loop state = <%s>, flags = 0x%lx\n", loop_state , *flags); copy_info(&info, "Dpc flags = 0x%lx\n", ha->dpc_flags); copy_info(&info, "MBX flags = 0x%x\n", ha->mbx_flags); copy_info(&info, "Link down Timeout = %3.3d\n", ha->link_down_timeout); copy_info(&info, "Port down retry = %3.3d\n", ha->port_down_retry_count); copy_info(&info, "Login retry count = %3.3d\n", ha->login_retry_count); copy_info(&info, "Commands retried with dropped frame(s) = %d\n", ha->dropped_frame_error_cnt); copy_info(&info, "Product ID = %04x %04x %04x %04x\n", ha->product_id[0], ha->product_id[1], ha->product_id[2], ha->product_id[3]); copy_info(&info, "\n"); /* 2.25 node/port display to proc */ /* Display the node name for adapter */ copy_info(&info, "\nSCSI Device Information:\n"); copy_info(&info, "scsi-qla%d-adapter-node=" "%02x%02x%02x%02x%02x%02x%02x%02x;\n", (int)ha->instance, ha->init_cb->node_name[0], ha->init_cb->node_name[1], ha->init_cb->node_name[2], ha->init_cb->node_name[3], ha->init_cb->node_name[4], ha->init_cb->node_name[5], ha->init_cb->node_name[6], ha->init_cb->node_name[7]); /* display the port name for adapter */ copy_info(&info, "scsi-qla%d-adapter-port=" "%02x%02x%02x%02x%02x%02x%02x%02x;\n", (int)ha->instance, ha->init_cb->port_name[0], ha->init_cb->port_name[1], ha->init_cb->port_name[2], ha->init_cb->port_name[3], ha->init_cb->port_name[4], ha->init_cb->port_name[5], ha->init_cb->port_name[6], ha->init_cb->port_name[7]); /* Print out device port names */ for (t = 0; t < MAX_FIBRE_DEVICES; t++) { if ((tq = TGT_Q(ha, t)) == NULL) continue; copy_info(&info, "scsi-qla%d-target-%d=" "%02x%02x%02x%02x%02x%02x%02x%02x;\n", (int)ha->instance, t, tq->port_name[0], tq->port_name[1], tq->port_name[2], tq->port_name[3], tq->port_name[4], tq->port_name[5], tq->port_name[6], tq->port_name[7]); } copy_info(&info, "\nSCSI LUN Information:\n"); copy_info(&info, "(Id:Lun) * - indicates lun is not registered with the OS.\n"); /* scan for all equipment stats */ for (t = 0; t < MAX_FIBRE_DEVICES; t++) { /* scan all luns */ for (l = 0; l < ha->max_luns; l++) { up = (os_lun_t *) GET_LU_Q(ha, t, l); if (up == NULL) { continue; } if (up->fclun == NULL) { continue; } copy_info(&info, "(%2d:%2d): Total reqs %ld,", t,l,up->io_cnt); copy_info(&info, " Pending reqs %ld,", up->out_cnt); if (up->io_cnt < 4) { copy_info(&info, " flags 0x%x*,", (int)up->q_flag); } else { copy_info(&info, " flags 0x%x,", (int)up->q_flag); } copy_info(&info, " %ld:%d:%02x %02x", up->fclun->fcport->ha->instance, up->fclun->fcport->cur_path, up->fclun->fcport->loop_id, up->fclun->device_type); copy_info(&info, "\n"); if (info.pos >= info.offset + info.length) { /* No need to continue */ goto profile_stop; } } if (info.pos >= info.offset + info.length) { /* No need to continue */ break; } }profile_stop: retval = info.pos > info.offset ? info.pos - info.offset : 0; DEBUG3(printk(KERN_INFO "Exiting proc_info: info.pos=%d, offset=0x%lx, " "length=0x%x\n", info.pos, offset, length);) return (retval);}/** qla2x00_display_fc_names* This routine will the node names of the different devices found* after port inquiry.** Input:* cmd = SCSI command structure** Returns:* None.*/static voidqla2x00_display_fc_names(scsi_qla_host_t *ha) { uint16_t tgt; os_tgt_t *tq; /* Display the node name for adapter */ qla_printk(KERN_INFO, ha, "scsi-qla%d-adapter-node=%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", (int)ha->instance, ha->init_cb->node_name[0], ha->init_cb->node_name[1], ha->init_cb->node_name[2], ha->init_cb->node_name[3], ha->init_cb->node_name[4], ha->init_cb->node_name[5], ha->init_cb->node_name[6], ha->init_cb->node_name[7]); /* display the port name for adapter */ qla_printk(KERN_INFO, ha, "scsi-qla%d-adapter-port=%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", (int)ha->instance, ha->init_cb->port_name[0], ha->init_cb->port_name[1], ha->init_cb->port_name[2], ha->init_cb->port_name[3], ha->init_cb->port_name[4], ha->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -