raid 3108の初期化


3108 raid      drivers/scsi/megaraid。      megaraid_sas_base.c megasas_init。
 megasas_init                ,   user space  raid 
	/*
	 * Register character device node
	 */
	rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops);

	if (rval < 0) {
		printk(KERN_DEBUG "megasas: failed to open device node
"); return rval; } pci driver /* * Register ourselves as PCI hotplug module */ rval = pci_register_driver(&megasas_pci_driver); if (rval) { printk(KERN_DEBUG "megasas: PCI hotplug registration failed
"); goto err_pcidrv; } pci probe megasas_probe_one megasas_probe_one pcie , megasas_io_attach SCSI mid-layer host /* * Register with SCSI mid-layer */ if (megasas_io_attach(instance)) goto fail_io_attach; megasas_io_attach : static int megasas_io_attach(struct megasas_instance *instance) { struct Scsi_Host *host = instance->host; /* * Notify the mid-layer about the new controller */ if (scsi_add_host(host, &instance->pdev->dev)) { dev_err(&instance->pdev->dev, "Failed to add host from %s %d
", __func__, __LINE__); return -ENODEV; } return 0; } scsi_add_host host * Trigger SCSI to scan our drives */ scsi_scan_host(host); scan。 kernel 3108 raid 3108 fw 3108 : /* * MFI command opcodes */ #define MFI_CMD_INIT 0x00 #define MFI_CMD_LD_READ 0x01 #define MFI_CMD_LD_WRITE 0x02 #define MFI_CMD_LD_SCSI_IO 0x03 #define MFI_CMD_PD_SCSI_IO 0x04 #define MFI_CMD_DCMD 0x05 #define MFI_CMD_ABORT 0x06 #define MFI_CMD_SMP 0x07 #define MFI_CMD_STP 0x08 #define MFI_CMD_INVALID 0xff MFI_CMD_DCMD MR_DCMD_LD_LIST_QUERY static int megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) { int ret = 0, ld_index = 0, ids = 0; struct megasas_cmd *cmd; struct megasas_dcmd_frame *dcmd; struct MR_LD_TARGETID_LIST *ci; dma_addr_t ci_h = 0; u32 tgtid_count; // struct megasas_cmd *cmd cmd = megasas_get_cmd(instance); if (!cmd) { dev_warn(&instance->pdev->dev, "megasas_ld_list_query: Failed to get cmd
"); return -ENOMEM; } dcmd = &cmd->frame->dcmd; ci = pci_alloc_consistent(instance->pdev, sizeof(struct MR_LD_TARGETID_LIST), &ci_h); if (!ci) { dev_warn(&instance->pdev->dev, "Failed to alloc mem for ld_list_query
"); megasas_return_cmd(instance, cmd); return -ENOMEM; } memset(ci, 0, sizeof(*ci)); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); dcmd->mbox.b[0] = query_type; if (instance->supportmax256vd) dcmd->mbox.b[2] = 1; // dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = MFI_STAT_INVALID_STATUS; dcmd->sge_count = 1; dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); dcmd->timeout = 0; dcmd->data_xfer_len = cpu_to_le32(sizeof(struct MR_LD_TARGETID_LIST)); dcmd->opcode = cpu_to_le32(MR_DCMD_LD_LIST_QUERY); dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h); dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct MR_LD_TARGETID_LIST)); dcmd->pad_0 = 0; // , megasas_issue_blocked_cmd fw , sleep, megasas_issue_polled poll, if (instance->ctrl_context && !instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else ret = megasas_issue_polled(instance, cmd); switch , ,DCMD_FAILED/DCMD_TIMEOUT/DCMD_SUCCESS , case DCMD_SUCCESS switch (ret) { case DCMD_FAILED: dev_info(&instance->pdev->dev, "DCMD not supported by firmware - %s %d
", __func__, __LINE__); ret = megasas_get_ld_list(instance); break; case DCMD_TIMEOUT: switch (dcmd_timeout_ocr_possible(instance)) { case INITIATE_OCR: cmd->flags |= DRV_DCMD_SKIP_REFIRE; /* * DCMD failed from AEN path. * AEN path already hold reset_mutex to avoid PCI access * while OCR is in progress. */ mutex_unlock(&instance->reset_mutex); megasas_reset_fusion(instance->host, MFI_IO_TIMEOUT_OCR); mutex_lock(&instance->reset_mutex); break; case KILL_ADAPTER: megaraid_sas_kill_hba(instance); break; case IGNORE_TIMEOUT: dev_info(&instance->pdev->dev, "Ignore DCMD timeout: %s %d
", __func__, __LINE__); break; } break; case DCMD_SUCCESS: tgtid_count = le32_to_cpu(ci->count); if ((tgtid_count > (instance->fw_supported_vd_count))) break; memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); for (ld_index = 0; ld_index < tgtid_count; ld_index++) { ids = ci->targetId[ld_index]; instance->ld_ids[ids] = ci->targetId[ld_index]; } break; } pci_free_consistent(instance->pdev, sizeof(struct MR_LD_TARGETID_LIST), ci, ci_h); // ok , cmd 。 if (ret != DCMD_TIMEOUT) megasas_return_cmd(instance, cmd); return ret; } 3108 megasas_get_cmd struct megasas_cmd *megasas_get_cmd(struct megasas_instance *instance) { unsigned long flags; struct megasas_cmd *cmd = NULL; spin_lock_irqsave(&instance->mfi_pool_lock, flags); if (!list_empty(&instance->cmd_pool)) { cmd = list_entry((&instance->cmd_pool)->next, struct megasas_cmd, list); list_del_init(&cmd->list); } else { dev_err(&instance->pdev->dev, "Command pool empty!
"); } spin_unlock_irqrestore(&instance->mfi_pool_lock, flags); return cmd; } instance->cmd_pool pool cmd , , instance->cmd_pool , instance->cmd_pool cmd instance->cmd_pool list void megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) { unsigned long flags; u32 blk_tags; struct megasas_cmd_fusion *cmd_fusion; struct fusion_context *fusion = instance->ctrl_context; /* This flag is used only for fusion adapter. * Wait for Interrupt for Polled mode DCMD */ if (cmd->flags & DRV_DCMD_POLLED_MODE) return; spin_lock_irqsave(&instance->mfi_pool_lock, flags); // fusion null , megasas_get_cmd if (fusion) { blk_tags = instance->max_scsi_cmds + cmd->index; cmd_fusion = fusion->cmd_list[blk_tags]; megasas_return_cmd_fusion(instance, cmd_fusion); } cmd->scmd = NULL; cmd->frame_count = 0; cmd->flags = 0; memset(cmd->frame, 0, instance->mfi_frame_size); cmd->frame->io.context = cpu_to_le32(cmd->index); if (!fusion && reset_devices) cmd->frame->hdr.cmd = MFI_CMD_INVALID; list_add(&cmd->list, (&instance->cmd_pool)->next); spin_unlock_irqrestore(&instance->mfi_pool_lock, flags); }