Commit cd50ba8e authored by adam radford's avatar adam radford Committed by James Bottomley

[SCSI] megaraid_sas: Add struct megasas_instance_template changes

The following patch adds struct megasas_instance_template changes to
the megaraid_sas driver, and changes all code to use the new instance
entries:

   irqreturn_t (*service_isr )(int irq, void *devp);
   void (*tasklet)(unsigned long);
   u32 (*init_adapter)(struct megasas_instance *);
   u32 (*build_and_issue_cmd) (struct megasas_instance *, struct scsi_cmnd *);
   void (*issue_dcmd) (struct megasas_instance *instance,
                              struct megasas_cmd *cmd);
Signed-off-by: default avatarAdam Radford <aradford@gmail.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent b6d5d880
......@@ -1364,6 +1364,13 @@ struct megasas_instance_template {
struct megasas_register_set __iomem *);
int (*check_reset)(struct megasas_instance *, \
struct megasas_register_set __iomem *);
irqreturn_t (*service_isr)(int irq, void *devp);
void (*tasklet)(unsigned long);
u32 (*init_adapter)(struct megasas_instance *);
u32 (*build_and_issue_cmd) (struct megasas_instance *,
struct scsi_cmnd *);
void (*issue_dcmd) (struct megasas_instance *instance,
struct megasas_cmd *cmd);
};
#define MEGASAS_IS_LOGICAL(scp) \
......
......@@ -131,6 +131,20 @@ spinlock_t poll_aen_lock;
static void
megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
u8 alt_status);
static irqreturn_t megasas_isr(int irq, void *devp);
static u32
megasas_init_adapter_mfi(struct megasas_instance *instance);
u32
megasas_build_and_issue_cmd(struct megasas_instance *instance,
struct scsi_cmnd *scmd);
static void megasas_complete_cmd_dpc(unsigned long instance_addr);
void
megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
{
instance->instancet->fire_cmd(instance,
cmd->frame_phys_addr, 0, instance->reg_set);
}
/**
* megasas_get_cmd - Get a command from the free pool
......@@ -334,6 +348,11 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
.adp_reset = megasas_adp_reset_xscale,
.check_reset = megasas_check_reset_xscale,
.service_isr = megasas_isr,
.tasklet = megasas_complete_cmd_dpc,
.init_adapter = megasas_init_adapter_mfi,
.build_and_issue_cmd = megasas_build_and_issue_cmd,
.issue_dcmd = megasas_issue_dcmd,
};
/**
......@@ -460,6 +479,11 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
.adp_reset = megasas_adp_reset_ppc,
.check_reset = megasas_check_reset_ppc,
.service_isr = megasas_isr,
.tasklet = megasas_complete_cmd_dpc,
.init_adapter = megasas_init_adapter_mfi,
.build_and_issue_cmd = megasas_build_and_issue_cmd,
.issue_dcmd = megasas_issue_dcmd,
};
/**
......@@ -581,6 +605,11 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
.adp_reset = megasas_adp_reset_skinny,
.check_reset = megasas_check_reset_skinny,
.service_isr = megasas_isr,
.tasklet = megasas_complete_cmd_dpc,
.init_adapter = megasas_init_adapter_mfi,
.build_and_issue_cmd = megasas_build_and_issue_cmd,
.issue_dcmd = megasas_issue_dcmd,
};
......@@ -755,6 +784,11 @@ static struct megasas_instance_template megasas_instance_template_gen2 = {
.read_fw_status_reg = megasas_read_fw_status_reg_gen2,
.adp_reset = megasas_adp_reset_gen2,
.check_reset = megasas_check_reset_gen2,
.service_isr = megasas_isr,
.tasklet = megasas_complete_cmd_dpc,
.init_adapter = megasas_init_adapter_mfi,
.build_and_issue_cmd = megasas_build_and_issue_cmd,
.issue_dcmd = megasas_issue_dcmd,
};
/**
......@@ -1339,6 +1373,51 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
}
u32
megasas_build_and_issue_cmd(struct megasas_instance *instance,
struct scsi_cmnd *scmd)
{
struct megasas_cmd *cmd;
u32 frame_count;
cmd = megasas_get_cmd(instance);
if (!cmd)
return SCSI_MLQUEUE_HOST_BUSY;
/*
* Logical drive command
*/
if (megasas_is_ldio(scmd))
frame_count = megasas_build_ldio(instance, scmd, cmd);
else
frame_count = megasas_build_dcdb(instance, scmd, cmd);
if (!frame_count)
goto out_return_cmd;
cmd->scmd = scmd;
scmd->SCp.ptr = (char *)cmd;
/*
* Issue the command to the FW
*/
atomic_inc(&instance->fw_outstanding);
instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
cmd->frame_count-1, instance->reg_set);
/*
* Check if we have pend cmds to be completed
*/
if (poll_mode_io && atomic_read(&instance->fw_outstanding))
tasklet_schedule(&instance->isr_tasklet);
return 0;
out_return_cmd:
megasas_return_cmd(instance, cmd);
return 1;
}
/**
* megasas_queue_command - Queue entry point
* @scmd: SCSI command to be queued
......@@ -1347,8 +1426,6 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
static int
megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
{
u32 frame_count;
struct megasas_cmd *cmd;
struct megasas_instance *instance;
unsigned long flags;
......@@ -1387,42 +1464,13 @@ megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd
break;
}
cmd = megasas_get_cmd(instance);
if (!cmd)
if (instance->instancet->build_and_issue_cmd(instance, scmd)) {
printk(KERN_ERR "megasas: Err returned from build_and_issue_cmd\n");
return SCSI_MLQUEUE_HOST_BUSY;
/*
* Logical drive command
*/
if (megasas_is_ldio(scmd))
frame_count = megasas_build_ldio(instance, scmd, cmd);
else
frame_count = megasas_build_dcdb(instance, scmd, cmd);
if (!frame_count)
goto out_return_cmd;
cmd->scmd = scmd;
scmd->SCp.ptr = (char *)cmd;
/*
* Issue the command to the FW
*/
atomic_inc(&instance->fw_outstanding);
instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
cmd->frame_count-1, instance->reg_set);
/*
* Check if we have pend cmds to be completed
*/
if (poll_mode_io && atomic_read(&instance->fw_outstanding))
tasklet_schedule(&instance->isr_tasklet);
}
return 0;
out_return_cmd:
megasas_return_cmd(instance, cmd);
out_done:
done(scmd);
return 0;
......@@ -3221,69 +3269,15 @@ megasas_io_completion_timer(unsigned long instance_addr)
jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
}
/**
* megasas_init_mfi - Initializes the FW
* @instance: Adapter soft state
*
* This is the main function for initializing MFI firmware.
*/
static int megasas_init_mfi(struct megasas_instance *instance)
static u32
megasas_init_adapter_mfi(struct megasas_instance *instance)
{
struct megasas_register_set __iomem *reg_set;
u32 context_sz;
u32 reply_q_sz;
u32 max_sectors_1;
u32 max_sectors_2;
u32 tmp_sectors;
struct megasas_register_set __iomem *reg_set;
struct megasas_ctrl_info *ctrl_info;
unsigned long bar_list;
/* Find first memory bar */
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
if (pci_request_selected_regions(instance->pdev, instance->bar,
"megasas: LSI")) {
printk(KERN_DEBUG "megasas: IO memory region busy!\n");
return -EBUSY;
}
instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
if (!instance->reg_set) {
printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
goto fail_ioremap;
}
reg_set = instance->reg_set;
switch(instance->pdev->device)
{
case PCI_DEVICE_ID_LSI_SAS1078R:
case PCI_DEVICE_ID_LSI_SAS1078DE:
instance->instancet = &megasas_instance_template_ppc;
break;
case PCI_DEVICE_ID_LSI_SAS1078GEN2:
case PCI_DEVICE_ID_LSI_SAS0079GEN2:
instance->instancet = &megasas_instance_template_gen2;
break;
case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
instance->instancet = &megasas_instance_template_skinny;
break;
case PCI_DEVICE_ID_LSI_SAS1064R:
case PCI_DEVICE_ID_DELL_PERC5:
default:
instance->instancet = &megasas_instance_template_xscale;
break;
}
/*
* We expect the FW state to be READY
*/
if (megasas_transition_to_ready(instance))
goto fail_ready_state;
/*
* Get various operational parameters from status register
*/
......@@ -3337,6 +3331,87 @@ static int megasas_init_mfi(struct megasas_instance *instance)
if (instance->fw_support_ieee)
instance->flag_ieee = 1;
return 0;
fail_fw_init:
pci_free_consistent(instance->pdev, reply_q_sz,
instance->reply_queue, instance->reply_queue_h);
fail_reply_queue:
megasas_free_cmds(instance);
fail_alloc_cmds:
iounmap(instance->reg_set);
return 1;
}
/**
* megasas_init_fw - Initializes the FW
* @instance: Adapter soft state
*
* This is the main function for initializing firmware
*/
static int megasas_init_fw(struct megasas_instance *instance)
{
u32 max_sectors_1;
u32 max_sectors_2;
u32 tmp_sectors;
struct megasas_register_set __iomem *reg_set;
struct megasas_ctrl_info *ctrl_info;
unsigned long bar_list;
/* Find first memory bar */
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
if (pci_request_selected_regions(instance->pdev, instance->bar,
"megasas: LSI")) {
printk(KERN_DEBUG "megasas: IO memory region busy!\n");
return -EBUSY;
}
instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
if (!instance->reg_set) {
printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
goto fail_ioremap;
}
reg_set = instance->reg_set;
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_SAS1078R:
case PCI_DEVICE_ID_LSI_SAS1078DE:
instance->instancet = &megasas_instance_template_ppc;
break;
case PCI_DEVICE_ID_LSI_SAS1078GEN2:
case PCI_DEVICE_ID_LSI_SAS0079GEN2:
instance->instancet = &megasas_instance_template_gen2;
break;
case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
instance->instancet = &megasas_instance_template_skinny;
break;
case PCI_DEVICE_ID_LSI_SAS1064R:
case PCI_DEVICE_ID_DELL_PERC5:
default:
instance->instancet = &megasas_instance_template_xscale;
break;
}
/*
* We expect the FW state to be READY
*/
if (megasas_transition_to_ready(instance))
goto fail_ready_state;
/* Get operational params, sge flags, send init cmd to controller */
if (instance->instancet->init_adapter(instance))
return -ENODEV;
printk(KERN_ERR "megasas: INIT adapter done\n");
/** for passthrough
* the following function will get the PD LIST.
*/
......@@ -3392,15 +3467,7 @@ static int megasas_init_mfi(struct megasas_instance *instance)
MEGASAS_COMPLETION_TIMER_INTERVAL);
return 0;
fail_fw_init:
pci_free_consistent(instance->pdev, reply_q_sz,
instance->reply_queue, instance->reply_queue_h);
fail_reply_queue:
megasas_free_cmds(instance);
fail_alloc_cmds:
fail_ready_state:
fail_ready_state:
iounmap(instance->reg_set);
fail_ioremap:
......@@ -3855,7 +3922,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/*
* Initialize MFI Firmware
*/
if (megasas_init_mfi(instance))
if (megasas_init_fw(instance))
goto fail_init_mfi;
/* Try to enable MSI-X */
......@@ -3870,7 +3937,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
* Register IRQ
*/
if (request_irq(instance->msi_flag ? instance->msixentry.vector :
pdev->irq, megasas_isr,
pdev->irq, instance->instancet->service_isr,
IRQF_SHARED, "megasas", instance)) {
printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
goto fail_irq;
......@@ -3920,7 +3987,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->pdev->irq, instance);
if (instance->msi_flag)
pci_disable_msix(instance->pdev);
megasas_release_mfi(instance);
fail_irq:
fail_init_mfi:
......@@ -3930,9 +3996,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->evt_detail,
instance->evt_detail_h);
if (instance->producer)
if (instance->producer) {
pci_free_consistent(pdev, sizeof(u32), instance->producer,
instance->producer_h);
megasas_release_mfi(instance);
}
if (instance->consumer)
pci_free_consistent(pdev, sizeof(u32), instance->consumer,
instance->consumer_h);
......@@ -4134,7 +4202,7 @@ megasas_resume(struct pci_dev *pdev)
* Register IRQ
*/
if (request_irq(instance->msi_flag ? instance->msixentry.vector :
pdev->irq, megasas_isr,
pdev->irq, instance->instancet->service_isr,
IRQF_SHARED, "megasas", instance)) {
printk(KERN_ERR "megasas: Failed to register IRQ\n");
goto fail_irq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment