qla_os.c

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

C
2,525
字号
{	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;		}		/* get consistent memory allocated for init control block */		ha->init_cb = dma_alloc_coherent(&ha->pdev->dev,		    ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL);		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);		snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME,		    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;		}		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));			if (IS_FWI2_CAPABLE(ha)) {				/*				 * Get consistent memory allocated for SFP				 * block.				 */				ha->sfp_data = dma_pool_alloc(ha->s_dma_pool,				    GFP_KERNEL, &ha->sfp_data_dma);				if (ha->sfp_data == NULL) {					qla_printk(KERN_WARNING, ha,					    "Memory Allocation failed - "					    "sfp_data\n");					qla2x00_mem_free(ha);					msleep(100);					continue;				}				memset(ha->sfp_data, 0, SFP_BLOCK_SIZE);			}		}		/* Get memory for cached NVRAM */		ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL);		if (ha->nvram == NULL) {			/* error */			qla_printk(KERN_WARNING, ha,			    "Memory Allocation failed - nvram cache\n");			qla2x00_mem_free(ha);			msleep(100);			continue;		}		/* 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.*/voidqla2x00_mem_free(scsi_qla_host_t *ha){	struct list_head	*fcpl, *fcptemp;	fc_port_t	*fcport;	if (ha == NULL) {		/* error */		DEBUG2(printk("%s(): ERROR invalid ha pointer.\n", __func__));		return;	}	/* free sp pool */	qla2x00_free_sp_pool(ha);	if (ha->fw_dump) {		if (ha->eft)			dma_free_coherent(&ha->pdev->dev,			    ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);		vfree(ha->fw_dump);	}	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->sfp_data)		dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);	if (ha->ms_iocb)		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);	if (ha->s_dma_pool)		dma_pool_destroy(ha->s_dma_pool);	if (ha->init_cb)		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,		    ha->init_cb, ha->init_cb_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->eft = NULL;	ha->eft_dma = 0;	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->init_cb = NULL;	ha->init_cb_dma = 0;	ha->s_dma_pool = NULL;	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;	list_for_each_safe(fcpl, fcptemp, &ha->fcports) {		fcport = list_entry(fcpl, fc_port_t, list);		/* fc ports */		list_del_init(&fcport->list);		kfree(fcport);	}	INIT_LIST_HEAD(&ha->fcports);	ha->fw_dump = NULL;	ha->fw_dumped = 0;	ha->fw_dump_reading = 0;	vfree(ha->optrom_buffer);	kfree(ha->nvram);}/* * qla2x00_allocate_sp_pool * 	 This routine is called during initialization to allocate *  	 memory for local srb_t. * * Input: *	 ha   = adapter block pointer. * * Context: *      Kernel context. */static intqla2x00_allocate_sp_pool(scsi_qla_host_t *ha){	int      rval;	rval = QLA_SUCCESS;	ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);	if (ha->srb_mempool == NULL) {		qla_printk(KERN_INFO, ha, "Unable to allocate SRB mempool.\n");		rval = QLA_FUNCTION_FAILED;	}	return (rval);}/* *  This routine frees all adapter allocated memory. * */static voidqla2x00_free_sp_pool( scsi_qla_host_t *ha){	if (ha->srb_mempool) {		mempool_destroy(ha->srb_mempool);		ha->srb_mempool = NULL;	}}/*************************************************************************** qla2x00_do_dpc*   This kernel thread is a task that is schedule by the interrupt handler*   to perform the background processing for interrupts.** Notes:* This task always run in the context of a kernel thread.  It* is kick-off by the driver's detect code and starts up* up one per adapter. It immediately goes to sleep and waits for* some fibre event.  When either the interrupt handler or* the timer routine detects a event it will one of the task* bits then wake us up.**************************************************************************/static intqla2x00_do_dpc(void *data){	int		rval;	scsi_qla_host_t *ha;	fc_port_t	*fcport;	uint8_t		status;	uint16_t	next_loopid;	ha = (scsi_qla_host_t *)data;	set_user_nice(current, -20);	while (!kthread_should_stop()) {		DEBUG3(printk("qla2x00: DPC handler sleeping\n"));		set_current_state(TASK_INTERRUPTIBLE);		schedule();		__set_current_state(TASK_RUNNING);		DEBUG3(printk("qla2x00: DPC handler waking up\n"));		/* Initialization not yet finished. Don't do anything yet. */		if (!ha->flags.init_done)			continue;		DEBUG3(printk("scsi(%ld): DPC handler\n", ha->host_no));		ha->dpc_active = 1;		if (ha->flags.mbox_busy) {			ha->dpc_active = 0;			continue;		}		if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) {			DEBUG(printk("scsi(%ld): dpc: sched "			    "qla2x00_abort_isp ha = %p\n",			    ha->host_no, ha));			if (!(test_and_set_bit(ABORT_ISP_ACTIVE,			    &ha->dpc_flags))) {				if (qla2x00_abort_isp(ha)) {					/* failed. retry later */					set_bit(ISP_ABORT_NEEDED,					    &ha->dpc_flags);				}				clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);			}			DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n",			    ha->host_no));		}		if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))			qla2x00_update_fcports(ha);		if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) {			DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n",			    ha->host_no));			qla2x00_loop_reset(ha);		}		if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) &&		    (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) {			DEBUG(printk("scsi(%ld): qla2x00_reset_marker()\n",			    ha->host_no));			qla2x00_rst_aen(ha);			clear_bit(RESET_ACTIVE, &ha->dpc_flags);		}		/* Retry each device up to login retry count */		if ((test_and_clear_bit(RELOGIN_NEEDED, &ha->dpc_flags)) &&		    !test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) &&		    atomic_read(&ha->loop_state) != LOOP_DOWN) {			DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",			    ha->host_no));			next_loopid = 0;			list_for_each_entry(fcport, &ha->fcports, list) {				/*				 * If the port is not ONLINE then try to login				 * to it if we haven't run out of retries.				 */				if (atomic_read(&fcport->state) != FCS_ONLINE &&				    fcport->login_retry) {					if (fcport->flags & FCF_FABRIC_DEVICE) {						if (fcport->flags &						    FCF_TAPE_PRESENT)							ha->isp_ops->fabric_logout(							    ha, fcport->loop_id,							    fcport->d_id.b.domain,							    fcport->d_id.b.area,							    fcport->d_id.b.al_pa);						status = qla2x00_fabric_login(						    ha, fcport, &next_loopid);					} else						status =						    qla2x00_local_device_login(							ha, fcport);					fcport->login_retry--;					if (status == QLA_SUCCESS) {						fcport->old_loop_id = fcport->loop_id;						DEBUG(printk("scsi(%ld): port login OK: logged in ID 0x%x\n",						    ha->host_no, fcport->loop_id));						qla2x00_update_fcport(ha,						    fcport);					} else if (status == 1) {						set_bit(RELOGIN_NEEDED, &ha->dpc_flags);						/* retry the login again */						DEBUG(printk("scsi(%ld): Retrying %d login again loop_id 0x%x\n",						    ha->host_no,						    fcport->login_retry, fcport->loop_id));					} else {						fcport->login_retry = 0;					}					if (fcport->login_retry == 0)						fcport->loop_id = FC_NO_LOOP_ID;				}				if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))					break;			}			DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",			    ha->host_no));		}		if ((test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags)) &&		    atomic_read(&ha->loop_state) != LOOP_DOWN) {			clear_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags);			DEBUG(printk("scsi(%ld): qla2x00_login_retry()\n",			    ha->host_no));			set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);			DEBUG(printk("scsi(%ld): qla2x00_login_retry - end\n",			    ha->host_no));		}		if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {			DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n",			    ha->host_no));			if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE,			    &ha->dpc_flags))) {				rval = qla2x00_loop_resync(ha);				clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);			}			DEBUG(printk("scsi(%ld): qla2x00_loop_resync - end\n",			    ha->host_no));		}		if (test_and_clear_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_fl

⌨️ 快捷键说明

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