Example #1
0
/*
 * Uninitialize the resources used during PQI initialization.
 */
void pqisrc_pqi_uninit(pqisrc_softstate_t *softs)
{
	int i;
	DBG_FUNC("IN\n");
    
    if(softs->devlist_lockcreated==true){    
        os_uninit_spinlock(&softs->devlist_lock);
        softs->devlist_lockcreated = false;
    }
    
	for (i = 0; i <  softs->num_op_raid_ibq; i++) {
        /* OP RAID IB Q */
        if(softs->op_raid_ib_q[i].lockcreated==true){
		OS_UNINIT_PQILOCK(&softs->op_raid_ib_q[i].lock);
		softs->op_raid_ib_q[i].lockcreated = false;
        }
        
        /* OP AIO IB Q */
        if(softs->op_aio_ib_q[i].lockcreated==true){
		OS_UNINIT_PQILOCK(&softs->op_aio_ib_q[i].lock);
		softs->op_aio_ib_q[i].lockcreated = false;
        }
	}

	/* Free Op queues */
	os_dma_mem_free(softs, &softs->op_ibq_dma_mem);
	os_dma_mem_free(softs, &softs->op_obq_dma_mem);
	os_dma_mem_free(softs, &softs->event_q_dma_mem);

	/* Complete all pending commands. */
	os_complete_outstanding_cmds_nodevice(softs);
	
	/* Free  rcb */
	pqisrc_free_rcb(softs, softs->max_outstanding_io + 1);

	/* Free request id lists */
	pqisrc_destroy_taglist(softs,&softs->taglist);

    if(softs->admin_ib_queue.lockcreated==true){
	OS_UNINIT_PQILOCK(&softs->admin_ib_queue.lock);	
        softs->admin_ib_queue.lockcreated = false;
    }

	/* Free Admin Queue */
	os_dma_mem_free(softs, &softs->admin_queue_dma_mem);

	/* Switch back to SIS mode */
	if (pqisrc_force_sis(softs)) {
		DBG_ERR("Failed to switch back the adapter to SIS mode!\n");
	}

	DBG_FUNC("OUT\n");
}
/*
 * Initialize the adapter with supported PQI configuration.
 */
int pqisrc_pqi_init(pqisrc_softstate_t *softs)
{
	int ret = PQI_STATUS_SUCCESS;

	DBG_FUNC("IN\n");

	/* Check the PQI signature */
	ret = pqisrc_check_pqimode(softs);
	if(ret) {
		DBG_ERR("failed to switch to pqi\n");
                goto err_out;
	}

	PQI_SAVE_CTRL_MODE(softs, CTRL_PQI_MODE);
	softs->ctrl_in_pqi_mode = true;
	
	/* Get the No. of Online CPUs,NUMA/Processor config from OS */
	ret = os_get_processor_config(softs);
	if (ret) {
		DBG_ERR("Failed to get processor config from OS %d\n",
			ret);
		goto err_out;
	}
	
	softs->intr_type = INTR_TYPE_NONE;	

	/* Get the interrupt count, type, priority available from OS */
	ret = os_get_intr_config(softs);
	if (ret) {
		DBG_ERR("Failed to get interrupt config from OS %d\n",
			ret);
		goto err_out;
	}

	/*Enable/Set Legacy INTx Interrupt mask clear pqi register,
	 *if allocated interrupt is legacy type.
	 */
	if (INTR_TYPE_FIXED == softs->intr_type) {
		pqisrc_configure_legacy_intx(softs, true);
		sis_enable_intx(softs);
	}

	/* Create Admin Queue pair*/		
	ret = pqisrc_create_admin_queue(softs);
	if(ret) {
                DBG_ERR("Failed to configure admin queue\n");
                goto err_admin_queue;
    	}

	/* For creating event and IO operational queues we have to submit 
	   admin IU requests.So Allocate resources for submitting IUs */  
	     
	/* Allocate the request container block (rcb) */
	ret = pqisrc_allocate_rcb(softs);
	if (ret == PQI_STATUS_FAILURE) {
                DBG_ERR("Failed to allocate rcb \n");
                goto err_rcb;
    	}

	/* Allocate & initialize request id queue */
	ret = pqisrc_init_taglist(softs,&softs->taglist,
				softs->max_outstanding_io);
	if (ret) {
		DBG_ERR("Failed to allocate memory for request id q : %d\n",
			ret);
		goto err_taglist;
	}

	ret = pqisrc_configure_op_queues(softs);
	if (ret) {
			DBG_ERR("Failed to configure op queue\n");
			goto err_config_opq;
	}

	/* Create Operational queues */
	ret = pqisrc_create_op_queues(softs);
	if(ret) {
                DBG_ERR("Failed to create op queue\n");
                ret = PQI_STATUS_FAILURE;
                goto err_create_opq;
        }

	softs->ctrl_online = true;

	DBG_FUNC("OUT\n");
	return ret;

err_create_opq:
err_config_opq:
	pqisrc_destroy_taglist(softs,&softs->taglist);
err_taglist:
	pqisrc_free_rcb(softs, softs->max_outstanding_io + 1);		
err_rcb:
	pqisrc_destroy_admin_queue(softs);
err_admin_queue:
	os_free_intr_config(softs);
err_out:
	DBG_FUNC("OUT failed\n");
	return PQI_STATUS_FAILURE;
}
/*
 * Allocate memory for rcb and SG descriptors.
 */
static int pqisrc_allocate_rcb(pqisrc_softstate_t *softs)
{
	int ret = PQI_STATUS_SUCCESS;
	int i = 0;
	uint32_t num_req = 0;
	uint32_t sg_buf_size = 0;
	uint64_t alloc_size = 0;
	rcb_t *rcb = NULL;
	rcb_t *prcb = NULL;
	DBG_FUNC("IN\n");

	/* Set maximum outstanding requests */
	/* The valid tag values are from 1, 2, ..., softs->max_outstanding_io
	 * The rcb will be accessed by using the tag as index
	 * * As 0 tag index is not used, we need to allocate one extra.
	 */
	softs->max_outstanding_io = softs->pqi_cap.max_outstanding_io;
	num_req = softs->max_outstanding_io + 1;
	DBG_INIT("Max Outstanding IO reset to %d\n", num_req);

	alloc_size = num_req * sizeof(rcb_t);

	/* Allocate Non DMA memory */
	rcb = os_mem_alloc(softs, alloc_size);
	if (!rcb) {
		DBG_ERR("Failed to allocate memory for rcb\n");
		ret = PQI_STATUS_FAILURE;
		goto err_out;
	}
	softs->rcb = rcb;
	
	/* Allocate sg dma memory for sg chain  */
	sg_buf_size = softs->pqi_cap.max_sg_elem *
			sizeof(sgt_t);

	prcb = &softs->rcb[1];
	/* Initialize rcb */
	for(i=1; i < num_req; i++) {
		char tag[15];
		sprintf(tag, "sg_dma_buf%d", i);
		softs->sg_dma_desc[i].tag = tag;
		softs->sg_dma_desc[i].size = sg_buf_size;
		softs->sg_dma_desc[i].align = PQISRC_DEFAULT_DMA_ALIGN;

		ret = os_dma_mem_alloc(softs, &softs->sg_dma_desc[i]);
		if (ret) {
			DBG_ERR("Failed to Allocate sg desc %d\n", ret);
			ret = PQI_STATUS_FAILURE;
			goto error;
		}
		prcb->sg_chain_virt = (sgt_t *)(softs->sg_dma_desc[i].virt_addr);
		prcb->sg_chain_dma = (dma_addr_t)(softs->sg_dma_desc[i].dma_addr);
		prcb ++;
	}

	DBG_FUNC("OUT\n");
	return ret;
error:
	pqisrc_free_rcb(softs, i);
err_out:
	DBG_FUNC("failed OUT\n");
	return ret;
}