Add memory support required by 0x73 controller Signed-off-by Bo Yang<bo.yang@xxxxxxx> --- drivers/scsi/megaraid/megaraid_sas.c | 164 +++++++++++++++++++++++++++++++++++ drivers/scsi/megaraid/megaraid_sas.h | 19 ++++ 2 files changed, 183 insertions(+) diff -rupN linux-2.6.28_orig/drivers/scsi/megaraid/megaraid_sas.c linux-2.6.28_new/drivers/scsi/megaraid/megaraid_sas.c --- linux-2.6.28_orig/drivers/scsi/megaraid/megaraid_sas.c 2009-02-12 16:05:07.000000000 -0500 +++ linux-2.6.28_new/drivers/scsi/megaraid/megaraid_sas.c 2009-02-12 16:12:54.000000000 -0500 @@ -2039,6 +2039,144 @@ static int megasas_alloc_cmds(struct meg } /** + * megasas_skinny_mem_alloc: allocation memory for 0x73 and 0x71 controller + * @instance: Adapter soft state + * + * this function will allocate the memory for 0.73 comtroller. + */ +static int +megasas_skinny_mem_alloc(struct megasas_instance *instance) +{ + u8 i = 0, mem_alloc_done = 0; + u32 *virt, ind, num_bk = 0; + dma_addr_t paddr; + u32 mem_alloc_size = MEGASAS_SKINNY_SZ_MEM_BK * 256; + u32 *mem_tb = instance->skinny_mm_tb; + + instance->skinny_mm_tb = pci_alloc_consistent(instance->pdev, + MEGASAS_SKINNY_MAX_NUM_MEM_BK*sizeof(u32), + &instance->skinny_mm_tb_h); + + memset(instance->skinny_mm_tb, 0, + MEGASAS_SKINNY_MAX_NUM_MEM_BK * sizeof(u32)); + + instance->skinny_mm_alloc_ind = 0; + + while (!mem_alloc_done) { + + virt = pci_alloc_consistent(instance->pdev, + mem_alloc_size, + &paddr); + if (virt) { + num_bk = (mem_alloc_size/ + MEGASAS_SKINNY_SZ_MEM_BK); + + for (ind = 0; ind < num_bk; ind++) { + if (instance->skinny_mm_alloc_ind < + MEGASAS_SKINNY_MAX_NUM_MEM_BK) { + *mem_tb = (u32)(paddr+ + (MEGASAS_SKINNY_SZ_MEM_BK*ind)); + mem_tb++; + instance->skinny_mm_alloc_ind++; + } else { + mem_alloc_done = 1; + } + } + + instance->skinny_mm_bk[i].vir = virt; + instance->skinny_mm_bk[i].paddr = paddr; + instance->skinny_mm_bk[i].sz = mem_alloc_size; + } else { + if (mem_alloc_size > MEGASAS_SKINNY_SZ_MEM_BK) + mem_alloc_size = mem_alloc_size / 2; + } + } + + if (instance->skinny_mm_alloc_ind == 0) + return -1; + + return 0; +} + +/** + * megasas_skinny_mem_alloc: de-allocate memory for 0x73 and 0x71 controller + * @instance: Adapter soft state + * + * this function will de-allocate the memory for 0.73 comtroller. + */ +static void +megasas_skinny_mem_dealloc(struct megasas_instance *instance) +{ + int i = 0; + + for (i = 0; i < MEGASAS_SKINNY_MAX_NUM_MEM_BK; i++) { + if (instance->skinny_mm_bk[i].vir) { + pci_free_consistent(instance->pdev, + instance->skinny_mm_bk[i].sz, + instance->skinny_mm_bk[i].vir, + instance->skinny_mm_bk[i].paddr); + } + } + + if (instance->skinny_mm_tb) + pci_free_consistent(instance->pdev, + MEGASAS_SKINNY_MAX_NUM_MEM_BK * sizeof(u32), + instance->skinny_mm_tb, + instance->skinny_mm_tb_h); + +} + +/** + * megasas_mem_to_fw - Send requested memory to FW + * @instance: Adapter soft state + * + * Issues an internal command (DCMD) to get the FW's controller structure. + * This information is mainly used to send out the memory table to FW + */ +static int +megasas_mem_to_fw(struct megasas_instance *instance) +{ + int ret = 0; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n"); + return -ENOMEM; + } + + dcmd = &cmd->frame->dcmd; + + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->mbox.s[0] = instance->skinny_mm_alloc_ind; + dcmd->mbox.s[2] = MEGASAS_SKINNY_SZ_MEM_BK / 1024; + + 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(u32) * MEGASAS_SKINNY_MAX_NUM_MEM_BK; + dcmd->opcode = MR_DCMD_CTRL_MFI_HOST_MEM_ALLOC; + dcmd->sgl.sge32[0].phys_addr = instance->skinny_mm_tb_h; + dcmd->sgl.sge32[0].length = sizeof(u32) * MEGASAS_SKINNY_MAX_NUM_MEM_BK; + + if (!megasas_issue_polled(instance, cmd)) { + ret = 0; + + } else { + ret = -1; + } + + megasas_return_cmd(instance, cmd); + + return ret; +} + +/** * megasas_get_controller_info - Returns FW's controller structure * @instance: Adapter soft state * @ctrl_info: Controller information structure @@ -2290,6 +2428,9 @@ static int megasas_init_mfi(struct megas * Get various operational parameters from status register */ instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; + instance->memory_need = + instance->instancet->read_fw_status_reg(reg_set) & 0x08000000; + /* * Reduce the max supported cmds by 1. This is to ensure that the * reply_q_sz (1 more than the max cmd that driver may send) @@ -2325,6 +2466,25 @@ static int megasas_init_mfi(struct megas goto fail_reply_queue; } + if (instance->memory_need) { + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + + if (megasas_skinny_mem_alloc(instance)) { + printk(KERN_DEBUG "megasas: failed " + "allocate mem\n"); + megasas_skinny_mem_dealloc(instance); + } + + if (megasas_mem_to_fw(instance)) { + printk(KERN_DEBUG "megasas: fail to " + "dcmd cmd to pass mem to fw\n"); + } + } + } + if (megasas_issue_init_mfi(instance)) goto fail_fw_init; @@ -3110,6 +3270,10 @@ static void __devexit megasas_detach_one free_irq(instance->pdev->irq, instance); + if (instance->memory_need) { + megasas_skinny_mem_dealloc(instance); + } + megasas_release_mfi(instance); pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), diff -rupN linux-2.6.28_orig/drivers/scsi/megaraid/megaraid_sas.h linux-2.6.28_new/drivers/scsi/megaraid/megaraid_sas.h --- linux-2.6.28_orig/drivers/scsi/megaraid/megaraid_sas.h 2009-02-12 16:05:08.000000000 -0500 +++ linux-2.6.28_new/drivers/scsi/megaraid/megaraid_sas.h 2009-02-12 15:24:58.000000000 -0500 @@ -1092,6 +1092,16 @@ struct megasas_aen_event { struct megasas_instance *instance; }; +#define MR_DCMD_CTRL_MFI_HOST_MEM_ALLOC 0x0100e100 +#define MEGASAS_SKINNY_SZ_MEM_BK (64*1024) +#define MEGASAS_SKINNY_MAX_NUM_MEM_BK 512 + +struct megasas_skinny_mm_bk { + u32 vir; + u32 sz; + dma_addr_t paddr; +}; + struct megasas_instance { u32 *producer; @@ -1105,6 +1115,15 @@ struct megasas_instance { unsigned long base_addr; struct megasas_register_set __iomem *reg_set; + u32 *skinny_mm_tb; + dma_addr_t skinny_mm_tb_h; + + struct megasas_skinny_mm_bk skinny_mm_bk[MEGASAS_SKINNY_MAX_NUM_MEM_BK]; + + u32 skinny_mm_alloc_ind; + struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; + + u8 memory_need; s8 init_id; u16 max_num_sge; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html