* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_sas.c
- * Version : v00.00.03.01
+ * Version : v00.00.02.04
*
* Authors:
* Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_LSI_SAS1064R, /* xscale IOP */
+ PCI_DEVICE_ID_LSI_SAS1064R, // xscale IOP
PCI_ANY_ID,
PCI_ANY_ID,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_LSI_SAS1078R, /* ppc IOP */
+ PCI_DEVICE_ID_LSI_SAS1078R, // ppc IOP
PCI_ANY_ID,
PCI_ANY_ID,
},
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_LSI_VERDE_ZCR, /* xscale IOP, vega */
- PCI_ANY_ID,
- PCI_ANY_ID,
- },
{
PCI_VENDOR_ID_DELL,
- PCI_DEVICE_ID_DELL_PERC5, /* xscale IOP */
+ PCI_DEVICE_ID_DELL_PERC5, // xscale IOP
PCI_ANY_ID,
PCI_ANY_ID,
},
* @regs: MFI register set
*/
static inline void
-megasas_disable_intr(struct megasas_instance *instance)
+megasas_disable_intr(struct megasas_register_set __iomem * regs)
{
u32 mask = 0x1f;
- struct megasas_register_set __iomem *regs = instance->reg_set;
-
- if(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078R)
- mask = 0xffffffff;
-
writel(mask, ®s->outbound_intr_mask);
/* Dummy readl to force pci flush */
megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
{
u32 frame_count;
+ unsigned long flags;
struct megasas_cmd *cmd;
struct megasas_instance *instance;
goto out_return_cmd;
cmd->scmd = scmd;
+ scmd->SCp.ptr = (char *)cmd;
+ scmd->SCp.sent_command = jiffies;
/*
* Issue the command to the FW
*/
- atomic_inc(&instance->fw_outstanding);
+ spin_lock_irqsave(&instance->instance_lock, flags);
+ instance->fw_outstanding++;
+ spin_unlock_irqrestore(&instance->instance_lock, flags);
instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
*/
if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
return -ENXIO;
-
- /*
- * The RAID firmware may require extended timeouts.
- */
- if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
- sdev->timeout = 90 * HZ;
return 0;
}
for (i = 0; i < wait_time; i++) {
- int outstanding = atomic_read(&instance->fw_outstanding);
-
- if (!outstanding)
+ if (!instance->fw_outstanding)
break;
if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
- "commands to complete\n",i,outstanding);
+ "commands to complete\n", i,
+ instance->fw_outstanding);
}
msleep(1000);
}
- if (atomic_read(&instance->fw_outstanding)) {
+ if (instance->fw_outstanding) {
instance->hw_crit_error = 1;
return FAILED;
}
return ret_val;
}
+static enum scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+{
+ unsigned long seconds;
+
+ if (scmd->SCp.ptr) {
+ seconds = (jiffies - scmd->SCp.sent_command) / HZ;
+
+ if (seconds < 90) {
+ return EH_RESET_TIMER;
+ } else {
+ return EH_NOT_HANDLED;
+ }
+ }
+
+ return EH_HANDLED;
+}
+
/**
* megasas_reset_device - Device reset handler entry point
*/
int ret;
/*
- * First wait for all commands to complete
+ * Frist wait for all commands to complete
*/
ret = megasas_generic_reset(scmd);
.eh_device_reset_handler = megasas_reset_device,
.eh_bus_reset_handler = megasas_reset_bus_host,
.eh_host_reset_handler = megasas_reset_bus_host,
+ .eh_timed_out = megasas_reset_timer,
.use_clustering = ENABLE_CLUSTERING,
};
{
int exception = 0;
struct megasas_header *hdr = &cmd->frame->hdr;
+ unsigned long flags;
if (cmd->scmd) {
cmd->scmd->SCp.ptr = (char *)0;
if (exception) {
- atomic_dec(&instance->fw_outstanding);
+ spin_lock_irqsave(&instance->instance_lock, flags);
+ instance->fw_outstanding--;
+ spin_unlock_irqrestore(&instance->instance_lock, flags);
megasas_unmap_sgbuf(instance, cmd);
cmd->scmd->scsi_done(cmd->scmd);
break;
}
- atomic_dec(&instance->fw_outstanding);
+ spin_lock_irqsave(&instance->instance_lock, flags);
+ instance->fw_outstanding--;
+ spin_unlock_irqrestore(&instance->instance_lock, flags);
megasas_unmap_sgbuf(instance, cmd);
cmd->scmd->scsi_done(cmd->scmd);
/*
* Bring it to READY state; assuming max wait 2 secs
*/
- megasas_disable_intr(instance);
+ megasas_disable_intr(instance->reg_set);
writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell);
max_wait = 10;
init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
- /*
- * disable the intr before firing the init frame to FW
- */
- megasas_disable_intr(instance);
-
/*
* Issue the init frame in polled mode
*/
*/
INIT_LIST_HEAD(&instance->cmd_pool);
- atomic_set(&instance->fw_outstanding,0);
-
init_waitqueue_head(&instance->int_cmd_wait_q);
init_waitqueue_head(&instance->abort_cmd_wait_q);
spin_lock_init(&instance->cmd_pool_lock);
+ spin_lock_init(&instance->instance_lock);
sema_init(&instance->aen_mutex, 1);
sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
/*
* Register IRQ
*/
- if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, "megasas", instance)) {
+ if (request_irq(pdev->irq, megasas_isr, SA_SHIRQ, "megasas", instance)) {
printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
goto fail_irq;
}
megasas_mgmt_info.max_index--;
pci_set_drvdata(pdev, NULL);
- megasas_disable_intr(instance);
+ megasas_disable_intr(instance->reg_set);
free_irq(instance->pdev->irq, instance);
megasas_release_mfi(instance);
pci_set_drvdata(instance->pdev, NULL);
- megasas_disable_intr(instance);
+ megasas_disable_intr(instance->reg_set);
free_irq(instance->pdev->irq, instance);