⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 megaraid_sas.c

📁 最新的Megaraid SAS卡驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static irqreturn_t megasas_isr(int irq, void *devp){	return megasas_deplete_reply_queue((struct megasas_instance *)devp,					   DID_OK);}/** * megasas_transition_to_ready -	Move the FW to READY state * @instance:				Adapter soft state * * During the initialization, FW passes can potentially be in any one of * several possible states. If the FW in operational, waiting-for-handshake * states, driver must take steps to bring it to ready state. Otherwise, it * has to wait for the ready state. */static intmegasas_transition_to_ready(struct megasas_instance* instance){	int i;	u8 max_wait;	u32 fw_state;	u32 cur_state;	fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;	if (fw_state != MFI_STATE_READY) 		printk(KERN_INFO "megasas: Waiting for FW to come to ready" 		       " state\n");	while (fw_state != MFI_STATE_READY) {		switch (fw_state) {		case MFI_STATE_FAULT:			printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");			return -ENODEV;		case MFI_STATE_WAIT_HANDSHAKE:			/*			 * Set the CLR bit in inbound doorbell			 */			writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,				&instance->reg_set->inbound_doorbell);			max_wait = 2;			cur_state = MFI_STATE_WAIT_HANDSHAKE;			break;		case MFI_STATE_BOOT_MESSAGE_PENDING:			writel(MFI_INIT_HOTPLUG,				&instance->reg_set->inbound_doorbell);			max_wait = 10;			cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;			break;		case MFI_STATE_OPERATIONAL:			/*			 * Bring it to READY state; assuming max wait 10 secs			 */			instance->instancet->disable_intr(instance->reg_set);			writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);			max_wait = 10;			cur_state = MFI_STATE_OPERATIONAL;			break;		case MFI_STATE_UNDEFINED:			/*			 * This state should not last for more than 2 seconds			 */			max_wait = 2;			cur_state = MFI_STATE_UNDEFINED;			break;		case MFI_STATE_BB_INIT:			max_wait = 2;			cur_state = MFI_STATE_BB_INIT;			break;		case MFI_STATE_FW_INIT:			max_wait = 20;			cur_state = MFI_STATE_FW_INIT;			break;		case MFI_STATE_FW_INIT_2:			max_wait = 20;			cur_state = MFI_STATE_FW_INIT_2;			break;		case MFI_STATE_DEVICE_SCAN:			max_wait = 20;			cur_state = MFI_STATE_DEVICE_SCAN;			break;		case MFI_STATE_FLUSH_CACHE:			max_wait = 20;			cur_state = MFI_STATE_FLUSH_CACHE;			break;		default:			printk(KERN_DEBUG "megasas: Unknown state 0x%x\n",			       fw_state);			return -ENODEV;		}		/*		 * The cur_state should not last for more than max_wait secs		 */		for (i = 0; i < (max_wait * 1000); i++) {			fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &  					MFI_STATE_MASK ;			if (fw_state == cur_state) {				msleep(1);			} else				break;		}		/*		 * Return error if fw_state hasn't changed after max_wait		 */		if (fw_state == cur_state) {			printk(KERN_DEBUG "FW state [%d] hasn't changed "			       "in %d secs\n", fw_state, max_wait);			return -ENODEV;		}	}; 	printk(KERN_INFO "megasas: FW now in Ready state\n");	return 0;}/** * megasas_teardown_frame_pool -	Destroy the cmd frame DMA pool * @instance:				Adapter soft state */static void megasas_teardown_frame_pool(struct megasas_instance *instance){	int i;	u32 max_cmd = instance->max_fw_cmds;	struct megasas_cmd *cmd;	if (!instance->frame_dma_pool)		return;	/*	 * Return all frames to pool	 */	for (i = 0; i < max_cmd; i++) {		cmd = instance->cmd_list[i];		if (cmd->frame)			pci_pool_free(instance->frame_dma_pool, cmd->frame,				      cmd->frame_phys_addr);		if (cmd->sense)			pci_pool_free(instance->sense_dma_pool, cmd->sense,				      cmd->sense_phys_addr);	}	/*	 * Now destroy the pool itself	 */	pci_pool_destroy(instance->frame_dma_pool);	pci_pool_destroy(instance->sense_dma_pool);	instance->frame_dma_pool = NULL;	instance->sense_dma_pool = NULL;}/** * megasas_create_frame_pool -	Creates DMA pool for cmd frames * @instance:			Adapter soft state * * Each command packet has an embedded DMA memory buffer that is used for * filling MFI frame and the SG list that immediately follows the frame. This * function creates those DMA memory buffers for each command packet by using * PCI pool facility. */static int megasas_create_frame_pool(struct megasas_instance *instance){	int i;	u32 max_cmd;	u32 sge_sz;	u32 sgl_sz;	u32 total_sz;	u32 frame_count;	struct megasas_cmd *cmd;	max_cmd = instance->max_fw_cmds;	/*	 * Size of our frame is 64 bytes for MFI frame, followed by max SG	 * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer	 */	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :	    sizeof(struct megasas_sge32);	/*	 * Calculated the number of 64byte frames required for SGL	 */	sgl_sz = sge_sz * instance->max_num_sge;	frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;	/*	 * We need one extra frame for the MFI command	 */	frame_count++;	total_sz = MEGAMFI_FRAME_SIZE * frame_count;	/*	 * Use DMA pool facility provided by PCI layer	 */	instance->frame_dma_pool = pci_pool_create("megasas frame pool",						   instance->pdev, total_sz, 64,						   0);	if (!instance->frame_dma_pool) {		printk(KERN_DEBUG "megasas: failed to setup frame pool\n");		return -ENOMEM;	}	instance->sense_dma_pool = pci_pool_create("megasas sense pool",						   instance->pdev, 128, 4, 0);	if (!instance->sense_dma_pool) {		printk(KERN_DEBUG "megasas: failed to setup sense pool\n");		pci_pool_destroy(instance->frame_dma_pool);		instance->frame_dma_pool = NULL;		return -ENOMEM;	}	/*	 * Allocate and attach a frame to each of the commands in cmd_list.	 * By making cmd->index as the context instead of the &cmd, we can	 * always use 32bit context regardless of the architecture	 */	for (i = 0; i < max_cmd; i++) {		cmd = instance->cmd_list[i];		cmd->frame = pci_pool_alloc(instance->frame_dma_pool,					    GFP_KERNEL, &cmd->frame_phys_addr);		cmd->sense = pci_pool_alloc(instance->sense_dma_pool,					    GFP_KERNEL, &cmd->sense_phys_addr);		/*		 * megasas_teardown_frame_pool() takes care of freeing		 * whatever has been allocated		 */		if (!cmd->frame || !cmd->sense) {			printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n");			megasas_teardown_frame_pool(instance);			return -ENOMEM;		}		cmd->frame->io.context = cmd->index;	}	return 0;}/** * megasas_free_cmds -	Free all the cmds in the free cmd pool * @instance:		Adapter soft state */static void megasas_free_cmds(struct megasas_instance *instance){	int i;	/* First free the MFI frame pool */	megasas_teardown_frame_pool(instance);	/* Free all the commands in the cmd_list */	for (i = 0; i < instance->max_fw_cmds; i++)		kfree(instance->cmd_list[i]);	/* Free the cmd_list buffer itself */	kfree(instance->cmd_list);	instance->cmd_list = NULL;	INIT_LIST_HEAD(&instance->cmd_pool);}/** * megasas_alloc_cmds -	Allocates the command packets * @instance:		Adapter soft state * * Each command that is issued to the FW, whether IO commands from the OS or * internal commands like IOCTLs, are wrapped in local data structure called * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to * the FW. * * Each frame has a 32-bit field called context (tag). This context is used * to get back the megasas_cmd from the frame when a frame gets completed in * the ISR. Typically the address of the megasas_cmd itself would be used as * the context. But we wanted to keep the differences between 32 and 64 bit * systems to the mininum. We always use 32 bit integers for the context. In * this driver, the 32 bit values are the indices into an array cmd_list. * This array is used only to look up the megasas_cmd given the context. The * free commands themselves are maintained in a linked list called cmd_pool. */static int megasas_alloc_cmds(struct megasas_instance *instance){	int i;	int j;	u32 max_cmd;	struct megasas_cmd *cmd;	max_cmd = instance->max_fw_cmds;	/*	 * instance->cmd_list is an array of struct megasas_cmd pointers.	 * Allocate the dynamic array first and then allocate individual	 * commands.	 */	instance->cmd_list = kmalloc(sizeof(struct megasas_cmd *) * max_cmd,				     GFP_KERNEL);	if (!instance->cmd_list) {		printk(KERN_DEBUG "megasas: out of memory\n");		return -ENOMEM;	}	memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) * max_cmd);	for (i = 0; i < max_cmd; i++) {		instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd),						GFP_KERNEL);		if (!instance->cmd_list[i]) {			for (j = 0; j < i; j++)				kfree(instance->cmd_list[j]);			kfree(instance->cmd_list);			instance->cmd_list = NULL;			return -ENOMEM;		}	}	/*	 * Add all the commands to command pool (instance->cmd_pool)	 */	for (i = 0; i < max_cmd; i++) {		cmd = instance->cmd_list[i];		memset(cmd, 0, sizeof(struct megasas_cmd));		cmd->index = i;		cmd->instance = instance;		list_add_tail(&cmd->list, &instance->cmd_pool);	}	/*	 * Create a frame pool and assign one frame to each cmd	 */	if (megasas_create_frame_pool(instance)) {		printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");		megasas_free_cmds(instance);	}	return 0;}/** * megasas_get_controller_info -	Returns FW's controller structure * @instance:				Adapter soft state * @ctrl_info:				Controller information structure * * Issues an internal command (DCMD) to get the FW's controller structure. * This information is mainly used to find out the maximum IO transfer per * command supported by the FW. */static intmegasas_get_ctrl_info(struct megasas_instance *instance,		      struct megasas_ctrl_info *ctrl_info){	int ret = 0;	struct megasas_cmd *cmd;	struct megasas_dcmd_frame *dcmd;	struct megasas_ctrl_info *ci;	dma_addr_t ci_h = 0;	cmd = megasas_get_cmd(instance);	if (!cmd) {		printk(KERN_DEBUG "megasas: Failed to get a free cmd\n");		return -ENOMEM;	}	dcmd = &cmd->frame->dcmd;	ci = pci_alloc_consistent(instance->pdev,				  sizeof(struct megasas_ctrl_info), &ci_h);	if (!ci) {		printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n");		megasas_return_cmd(instance, cmd);		return -ENOMEM;	}	memset(ci, 0, sizeof(*ci));	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);	dcmd->cmd = MFI_CMD_DCMD;	dcmd->cmd_status = 0xFF;	dcmd->sge_count = 1;	dcmd->flags = MFI_FRAME_DIR_READ;	dcmd->timeout = 0;	dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info);	dcmd->opcode = MR_DCMD_CTRL_GET_INFO;	dcmd->sgl.sge32[0].phys_addr = ci_h;	dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info);	if (!megasas_issue_polled(instance, cmd)) {		ret = 0;		memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));	} else {		ret = -1;	}	pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),			    ci, ci_h);	megasas_return_cmd(instance, cmd);	return ret;}/** * megasas_issue_init_mfi -	Initializes the FW * @instance:		Adapter soft state * * Issues the INIT MFI cmd */static intmegasas_issue_init_mfi(struct megasas_instance *instance){	u32 context;	struct megasas_cmd *cmd;	struct megasas_init_frame *init_frame;	struct megasas_init_queue_info *initq_info;	dma_addr_t init_frame_h;	dma_addr_t initq_info_h;	/*	 * Prepare a init frame. Note the init frame points to queue info	 * structure. Each frame has SGL allocated after first 64 bytes. For	 * this frame - since we don't need any SGL - we use SGL's space as	 * queue info structure	 *	 * We will not get a NULL command below. We just created the pool.	 */	cmd = megasas_get_cmd(instance);	init_frame = (struct megasas_init_frame *)cmd->frame;	initq_info = (struct megasas_init_queue_info *)	    ((unsigned long)init_frame + 64);	init_frame_h = cmd->frame_phys_addr;	initq_info_h = init_frame_h + 64;	context = init_frame->context;	memset(init_frame, 0, MEGAMFI_FRAME_SIZE);	memset(initq_info, 0, sizeof(struct megasas_init_queue_info));	init_frame->context = context;		initq_info->reply_queue_entries = instance->max_fw_cmds + 1;	initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;	initq_info->producer_index_phys_addr_lo = instance->producer_h;	initq_info->consumer_index_phys_addr_lo = instance->consumer_h;	init_frame->cmd = MFI_CMD_INIT;	init_frame->cmd_status = 0xFF;	init_frame->queue_info_new_phys_addr_lo = initq_info_h;	init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);	/*	 * disable the intr before firing the init frame to FW 	 */		instance->instancet->disable_intr(instance->reg_set);		/*	 * Issue the init frame in polled mode	 */	if (megasas_issue_polled(instance, cmd)) {		printk(KERN_DEBUG "megasas: Failed to init firmware\n");		megasas_return_cmd(instance, cmd);		goto fail_fw_init;	}	megasas_return_cmd(instance, cmd);	return 0;	fail_fw_init:		return -EINVAL;}

⌨️ 快捷键说明

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