qla_os.c

来自「linux 内核源代码」· C语言 代码 · 共 2,525 行 · 第 1/5 页

C
2,525
字号
skip_pio:	/* 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",		    pci_name(ha->pdev));		goto iospace_error_exit;	}	if (mmio_len < MIN_IOBASE_LEN) {		qla_printk(KERN_ERR, ha,		    "Invalid PCI mem region size (%s), aborting\n",			pci_name(ha->pdev));		goto iospace_error_exit;	}	ha->iobase = ioremap(mmio, MIN_IOBASE_LEN);	if (!ha->iobase) {		qla_printk(KERN_ERR, ha,		    "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));		goto iospace_error_exit;	}	return (0);iospace_error_exit:	return (-ENOMEM);}static voidqla2xxx_scan_start(struct Scsi_Host *shost){	scsi_qla_host_t *ha = shost_priv(shost);	set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);	set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);	set_bit(RSCN_UPDATE, &ha->dpc_flags);}static intqla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time){	scsi_qla_host_t *ha = shost_priv(shost);	if (!ha->host)		return 1;	if (time > ha->loop_reset_delay * HZ)		return 1;	return atomic_read(&ha->loop_state) == LOOP_READY;}/* * PCI driver interface */static int __devinitqla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id){	int	ret = -ENODEV;	device_reg_t __iomem *reg;	struct Scsi_Host *host;	scsi_qla_host_t *ha;	unsigned long	flags = 0;	char pci_info[30];	char fw_str[30];	struct scsi_host_template *sht;	int bars;	bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);	sht = &qla2x00_driver_template;	if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {		bars = pci_select_bars(pdev, IORESOURCE_MEM);		sht = &qla24xx_driver_template;	}	if (pci_enable_device_bars(pdev, bars))		goto probe_out;	if (pci_find_aer_capability(pdev))		if (pci_enable_pcie_error_reporting(pdev))			goto probe_out;	host = scsi_host_alloc(sht, 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 = shost_priv(host);	memset(ha, 0, sizeof(scsi_qla_host_t));	ha->pdev = pdev;	ha->host = host;	ha->host_no = host->host_no;	sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);	ha->parent = NULL;	ha->bars = bars;	/* Set ISP-type information. */	qla2x00_set_isp_flags(ha);	/* Configure PCI I/O space */	ret = qla2x00_iospace_config(ha);	if (ret)		goto probe_failed;	qla_printk(KERN_INFO, ha,	    "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq,	    ha->iobase);	spin_lock_init(&ha->hardware_lock);	ha->prev_topology = 0;	ha->init_cb_size = sizeof(init_cb_t);	ha->mgmt_svr_loop_id = MANAGEMENT_SERVER + ha->vp_idx;	ha->link_data_rate = PORT_SPEED_UNKNOWN;	ha->optrom_size = OPTROM_SIZE_2300;	ha->max_q_depth = MAX_Q_DEPTH;	if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU)		ha->max_q_depth = ql2xmaxqdepth;	/* Assign ISP specific operations. */	if (IS_QLA2100(ha)) {		host->max_id = 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;		ha->gid_list_info_size = 4;		ha->isp_ops = &qla2100_isp_ops;	} else if (IS_QLA2200(ha)) {		host->max_id = 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;		ha->gid_list_info_size = 4;		ha->isp_ops = &qla2100_isp_ops;	} else if (IS_QLA23XX(ha)) {		host->max_id = 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;		ha->gid_list_info_size = 6;		if (IS_QLA2322(ha) || IS_QLA6322(ha))			ha->optrom_size = OPTROM_SIZE_2322;		ha->isp_ops = &qla2300_isp_ops;	} else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {		host->max_id = MAX_TARGETS_2200;		ha->mbx_count = MAILBOX_REGISTER_COUNT;		ha->request_q_length = REQUEST_ENTRY_CNT_24XX;		ha->response_q_length = RESPONSE_ENTRY_CNT_2300;		ha->last_loop_id = SNS_LAST_LOOP_ID_2300;		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);		ha->mgmt_svr_loop_id = 10 + ha->vp_idx;		ha->gid_list_info_size = 8;		ha->optrom_size = OPTROM_SIZE_24XX;		ha->isp_ops = &qla24xx_isp_ops;	} else if (IS_QLA25XX(ha)) {		host->max_id = MAX_TARGETS_2200;		ha->mbx_count = MAILBOX_REGISTER_COUNT;		ha->request_q_length = REQUEST_ENTRY_CNT_24XX;		ha->response_q_length = RESPONSE_ENTRY_CNT_2300;		ha->last_loop_id = SNS_LAST_LOOP_ID_2300;		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);		ha->mgmt_svr_loop_id = 10 + ha->vp_idx;		ha->gid_list_info_size = 8;		ha->optrom_size = OPTROM_SIZE_25XX;		ha->isp_ops = &qla25xx_isp_ops;	}	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(&ha->vport_sem);	init_MUTEX_LOCKED(&ha->mbx_intr_sem);	INIT_LIST_HEAD(&ha->list);	INIT_LIST_HEAD(&ha->fcports);	INIT_LIST_HEAD(&ha->vp_list);	set_bit(0, (unsigned long *) ha->vp_idx_map);	qla2x00_config_dma_addressing(ha);	if (qla2x00_mem_alloc(ha)) {		qla_printk(KERN_WARNING, ha,		    "[ERROR] Failed to allocate memory for adapter\n");		ret = -ENOMEM;		goto probe_failed;	}	if (qla2x00_initialize_adapter(ha)) {		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));		ret = -ENODEV;		goto probe_failed;	}	/*	 * Startup the kernel thread for this host adapter	 */	ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,			"%s_dpc", ha->host_str);	if (IS_ERR(ha->dpc_thread)) {		qla_printk(KERN_WARNING, ha,		    "Unable to start DPC thread!\n");		ret = PTR_ERR(ha->dpc_thread);		goto probe_failed;	}	host->this_id = 255;	host->cmd_per_lun = 3;	host->unique_id = ha->instance;	host->max_cmd_len = MAX_CMDSZ;	host->max_channel = MAX_BUSES - 1;	host->max_lun = MAX_LUNS;	host->transportt = qla2xxx_transport_template;	ret = qla2x00_request_irqs(ha);	if (ret)		goto probe_failed;	/* 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));	ha->isp_ops->disable_intrs(ha);	spin_lock_irqsave(&ha->hardware_lock, flags);	reg = ha->iobase;	if (IS_FWI2_CAPABLE(ha)) {		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);	} else {		WRT_REG_WORD(&reg->isp.semaphore, 0);		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);		/* Enable proper parity */		if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) {			if (IS_QLA2300(ha))				/* SRAM parity */				WRT_REG_WORD(&reg->isp.hccr,				    (HCCR_ENABLE_PARITY + 0x1));			else				/* SRAM, Instruction RAM and GP RAM parity */				WRT_REG_WORD(&reg->isp.hccr,				    (HCCR_ENABLE_PARITY + 0x7));		}	}	spin_unlock_irqrestore(&ha->hardware_lock, flags);	ha->isp_ops->enable_intrs(ha);	pci_set_drvdata(pdev, ha);	ha->flags.init_done = 1;	ha->flags.online = 1;	num_hosts++;	ret = scsi_add_host(host, &pdev->dev);	if (ret)		goto probe_failed;	scsi_scan_host(host);	qla2x00_alloc_sysfs_attr(ha);	qla2x00_init_host_attr(ha);	qla_printk(KERN_INFO, ha, "\n"	    " QLogic Fibre Channel HBA Driver: %s\n"	    "  QLogic %s - %s\n"	    "  ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n",	    qla2x00_version_str, ha->model_number,	    ha->model_desc ? ha->model_desc: "", pdev->device,	    ha->isp_ops->pci_info_str(ha, pci_info), pci_name(pdev),	    ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no,	    ha->isp_ops->fw_version_str(ha, fw_str));	return 0;probe_failed:	qla2x00_free_device(ha);	scsi_host_put(host);probe_disable_device:	pci_disable_device(pdev);probe_out:	return ret;}static voidqla2x00_remove_one(struct pci_dev *pdev){	scsi_qla_host_t *ha;	ha = pci_get_drvdata(pdev);	qla2x00_free_sysfs_attr(ha);	fc_remove_host(ha->host);	scsi_remove_host(ha->host);	qla2x00_free_device(ha);	scsi_host_put(ha->host);	pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);}static voidqla2x00_free_device(scsi_qla_host_t *ha){	/* Disable timer */	if (ha->timer_active)		qla2x00_stop_timer(ha);	/* Kill the kernel thread for this host */	if (ha->dpc_thread) {		struct task_struct *t = ha->dpc_thread;		/*		 * qla2xxx_wake_dpc checks for ->dpc_thread		 * so we need to zero it out.		 */		ha->dpc_thread = NULL;		kthread_stop(t);	}	if (ha->eft)		qla2x00_trace_control(ha, TC_DISABLE, 0, 0);	ha->flags.online = 0;	/* Stop currently executing firmware. */	qla2x00_try_to_stop_firmware(ha);	/* turn-off interrupts on the card */	if (ha->interrupts_on)		ha->isp_ops->disable_intrs(ha);	qla2x00_mem_free(ha);	qla2x00_free_irqs(ha);	/* release io space registers  */	if (ha->iobase)		iounmap(ha->iobase);	pci_release_selected_regions(ha->pdev, ha->bars);}static inline voidqla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,    int defer){	unsigned long flags;	struct fc_rport *rport;	if (!fcport->rport)		return;	rport = fcport->rport;	if (defer) {		spin_lock_irqsave(&fcport->rport_lock, flags);		fcport->drport = rport;		fcport->rport = NULL;		*(fc_port_t **)rport->dd_data = NULL;		spin_unlock_irqrestore(&fcport->rport_lock, flags);		set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);	} else {		spin_lock_irqsave(&fcport->rport_lock, flags);		fcport->rport = NULL;		*(fc_port_t **)rport->dd_data = NULL;		spin_unlock_irqrestore(&fcport->rport_lock, flags);		fc_remote_port_delete(rport);	}}/* * qla2x00_mark_device_lost Updates fcport state when device goes offline. * * Input: ha = adapter block pointer.  fcport = port structure pointer. * * Return: None. * * Context: */void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,    int do_login, int defer){	if (atomic_read(&fcport->state) == FCS_ONLINE &&	    ha->vp_idx == fcport->vp_idx)		qla2x00_schedule_rport_del(ha, fcport, defer);	/*	 * We may need to retry the login, so don't change the state of the	 * port but do the retries.	 */	if (atomic_read(&fcport->state) != FCS_DEVICE_DEAD)		atomic_set(&fcport->state, FCS_DEVICE_LOST);	if (!do_login)		return;	if (fcport->login_retry == 0) {		fcport->login_retry = ha->login_retry_count;		set_bit(RELOGIN_NEEDED, &ha->dpc_flags);		DEBUG(printk("scsi(%ld): Port login retry: "		    "%02x%02x%02x%02x%02x%02x%02x%02x, "		    "id = 0x%04x retry cnt=%d\n",		    ha->host_no,		    fcport->port_name[0],		    fcport->port_name[1],		    fcport->port_name[2],		    fcport->port_name[3],		    fcport->port_name[4],		    fcport->port_name[5],		    fcport->port_name[6],		    fcport->port_name[7],		    fcport->loop_id,		    fcport->login_retry));	}}/* * qla2x00_mark_all_devices_lost *	Updates fcport state when device goes offline. * * Input: *	ha = adapter block pointer. *	fcport = port structure pointer. * * Return: *	None. * * Context: */voidqla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer){	fc_port_t *fcport;	scsi_qla_host_t *pha = to_qla_parent(ha);	list_for_each_entry(fcport, &pha->fcports, list) {		if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx)			continue;		/*		 * No point in marking the device as lost, if the device is		 * already DEAD.		 */		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)			continue;		if (atomic_read(&fcport->state) == FCS_ONLINE) {			if (defer)				qla2x00_schedule_rport_del(ha, fcport, defer);			else if (ha->vp_idx == fcport->vp_idx)				qla2x00_schedule_rport_del(ha, fcport, defer);		}		atomic_set(&fcport->state, FCS_DEVICE_LOST);	}	if (defer)		qla2xxx_wake_dpc(ha);}/** qla2x00_mem_alloc*      Allocates adapter memory.** Returns:*      0  = success.*      1  = failure.*/uint8_tqla2x00_mem_alloc(scsi_qla_host_t *ha)

⌨️ 快捷键说明

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