qla_os.c

来自「linux2.6.16版本」· C语言 代码 · 共 2,593 行 · 第 1/5 页

C
2,593
字号
	}	pci_set_drvdata(pdev, ha);	ha->flags.init_done = 1;	num_hosts++;	ret = scsi_add_host(host, &pdev->dev);	if (ret)		goto probe_failed;	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));	/* Go with fc_rport registration. */	list_for_each_entry(fcport, &ha->fcports, list)		qla2x00_reg_remote_port(ha, fcport);	return 0;probe_failed:	qla2x00_free_device(ha);	scsi_host_put(host);probe_disable_device:	pci_disable_device(pdev);probe_out:	return ret;}EXPORT_SYMBOL_GPL(qla2x00_probe_one);void qla2x00_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_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);	/* 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);		}	}	/* Stop currently executing firmware. */	qla2x00_stop_firmware(ha);	/* turn-off interrupts on the card */	if (ha->interrupts_on)		ha->isp_ops.disable_intrs(ha);	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);}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)		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;	list_for_each_entry(fcport, &ha->fcports, list) {		if (fcport->port_type != FCT_TARGET)			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)			qla2x00_schedule_rport_del(ha, fcport, defer);		atomic_set(&fcport->state, FCS_DEVICE_LOST);	}	if (defer && ha->dpc_wait && !ha->dpc_active)		up(ha->dpc_wait);}/** qla2x00_mem_alloc*      Allocates adapter memory.** Returns:*      0  = success.*      1  = failure.*/static uint8_tqla2x00_mem_alloc(scsi_qla_host_t *ha){	char	name[16];	uint8_t   status = 1;	int	retry= 10;	do {		/*		 * This will loop only once if everything goes well, else some		 * number of retries will be performed to get around a kernel		 * bug where available mem is not allocated until after a		 * little delay and a retry.		 */		ha->request_ring = dma_alloc_coherent(&ha->pdev->dev,		    (ha->request_q_length + 1) * sizeof(request_t),		    &ha->request_dma, GFP_KERNEL);		if (ha->request_ring == NULL) {			qla_printk(KERN_WARNING, ha,			    "Memory Allocation failed - request_ring\n");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		ha->response_ring = dma_alloc_coherent(&ha->pdev->dev,		    (ha->response_q_length + 1) * sizeof(response_t),		    &ha->response_dma, GFP_KERNEL);		if (ha->response_ring == NULL) {			qla_printk(KERN_WARNING, ha,			    "Memory Allocation failed - response_ring\n");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,		    &ha->gid_list_dma, GFP_KERNEL);		if (ha->gid_list == NULL) {			qla_printk(KERN_WARNING, ha,			    "Memory Allocation failed - gid_list\n");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		ha->rlc_rsp = dma_alloc_coherent(&ha->pdev->dev,		    sizeof(rpt_lun_cmd_rsp_t), &ha->rlc_rsp_dma, GFP_KERNEL);		if (ha->rlc_rsp == NULL) {			qla_printk(KERN_WARNING, ha,				"Memory Allocation failed - rlc");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		snprintf(name, sizeof(name), "qla2xxx_%ld", ha->host_no);		ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev,		    DMA_POOL_SIZE, 8, 0);		if (ha->s_dma_pool == NULL) {			qla_printk(KERN_WARNING, ha,			    "Memory Allocation failed - s_dma_pool\n");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		/* get consistent memory allocated for init control block */		ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,		    &ha->init_cb_dma);		if (ha->init_cb == NULL) {			qla_printk(KERN_WARNING, ha,			    "Memory Allocation failed - init_cb\n");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		memset(ha->init_cb, 0, ha->init_cb_size);		/* Get consistent memory allocated for Get Port Database cmd */		ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,		    &ha->iodesc_pd_dma);		if (ha->iodesc_pd == NULL) {			/* error */			qla_printk(KERN_WARNING, ha,			    "Memory Allocation failed - iodesc_pd\n");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE);		/* Allocate ioctl related memory. */		if (qla2x00_alloc_ioctl_mem(ha)) {			qla_printk(KERN_WARNING, ha,			    "Memory Allocation failed - ioctl_mem\n");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		if (qla2x00_allocate_sp_pool(ha)) {			qla_printk(KERN_WARNING, ha,			    "Memory Allocation failed - "			    "qla2x00_allocate_sp_pool()\n");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		/* Allocate memory for SNS commands */		if (IS_QLA2100(ha) || IS_QLA2200(ha)) {			/* Get consistent memory allocated for SNS commands */			ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev,			    sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma,			    GFP_KERNEL);			if (ha->sns_cmd == NULL) {				/* error */				qla_printk(KERN_WARNING, ha,				    "Memory Allocation failed - sns_cmd\n");				qla2x00_mem_free(ha);				msleep(100);				continue;			}			memset(ha->sns_cmd, 0, sizeof(struct sns_cmd_pkt));		} else {			/* Get consistent memory allocated for MS IOCB */			ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,			    &ha->ms_iocb_dma);			if (ha->ms_iocb == NULL) {				/* error */				qla_printk(KERN_WARNING, ha,				    "Memory Allocation failed - ms_iocb\n");				qla2x00_mem_free(ha);				msleep(100);				continue;			}			memset(ha->ms_iocb, 0, sizeof(ms_iocb_entry_t));			/*			 * Get consistent memory allocated for CT SNS			 * commands			 */			ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev,			    sizeof(struct ct_sns_pkt), &ha->ct_sns_dma,			    GFP_KERNEL);			if (ha->ct_sns == NULL) {				/* error */				qla_printk(KERN_WARNING, ha,				    "Memory Allocation failed - ct_sns\n");				qla2x00_mem_free(ha);				msleep(100);				continue;			}			memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt));		}		/* Done all allocations without any error. */		status = 0;	} while (retry-- && status != 0);	if (status) {		printk(KERN_WARNING			"%s(): **** FAILED ****\n", __func__);	}	return(status);}/** qla2x00_mem_free*      Frees all adapter allocated memory.** Input:*      ha = adapter block pointer.*/static voidqla2x00_mem_free(scsi_qla_host_t *ha){	struct list_head	*fcpl, *fcptemp;	fc_port_t	*fcport;	unsigned int	wtime;/* max wait time if mbx cmd is busy. */	if (ha == NULL) {		/* error */		DEBUG2(printk("%s(): ERROR invalid ha pointer.\n", __func__));		return;	}	/* Make sure all other threads are stopped. */	wtime = 60 * 1000;	while (ha->dpc_wait && wtime)		wtime = msleep_interruptible(wtime);	/* free ioctl memory */	qla2x00_free_ioctl_mem(ha);	/* free sp pool */	qla2x00_free_sp_pool(ha);	if (ha->sns_cmd)		dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),		    ha->sns_cmd, ha->sns_cmd_dma);	if (ha->ct_sns)		dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),		    ha->ct_sns, ha->ct_sns_dma);	if (ha->ms_iocb)		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);	if (ha->iodesc_pd)		dma_pool_free(ha->s_dma_pool, ha->iodesc_pd, ha->iodesc_pd_dma);	if (ha->init_cb)		dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma);	if (ha->s_dma_pool)		dma_pool_destroy(ha->s_dma_pool);	if (ha->rlc_rsp)		dma_free_coherent(&ha->pdev->dev,		    sizeof(rpt_lun_cmd_rsp_t), ha->rlc_rsp,		    ha->rlc_rsp_dma);	if (ha->gid_list)		dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,		    ha->gid_list_dma);	if (ha->response_ring)		dma_free_coherent(&ha->pdev->dev,		    (ha->response_q_length + 1) * sizeof(response_t),		    ha->response_ring, ha->response_dma);	if (ha->request_ring)		dma_free_coherent(&ha->pdev->dev,		    (ha->request_q_length + 1) * sizeof(request_t),		    ha->request_ring, ha->request_dma);	ha->sns_cmd = NULL;	ha->sns_cmd_dma = 0;	ha->ct_sns = NULL;	ha->ct_sns_dma = 0;	ha->ms_iocb = NULL;	ha->ms_iocb_dma = 0;	ha->iodesc_pd = NULL;	ha->iodesc_pd_dma = 0;	ha->init_cb = NULL;	ha->init_cb_dma = 0;	ha->s_dma_pool = NULL;	ha->rlc_rsp = NULL;	ha->rlc_rsp_dma = 0;	ha->gid_list = NULL;	ha->gid_list_dma = 0;	ha->response_ring = NULL;	ha->response_dma = 0;	ha->request_ring = NULL;	ha->request_dma = 0;

⌨️ 快捷键说明

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