[SCSI] libsas, libata: fix start of life for a sas ata_port
[linux-flexiantxendom0-3.2.10.git] / drivers / scsi / ipr.c
index dcad238..467dc38 100644 (file)
@@ -104,7 +104,9 @@ static DEFINE_SPINLOCK(ipr_driver_lock);
 static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
        { /* Gemstone, Citrine, Obsidian, and Obsidian-E */
                .mailbox = 0x0042C,
+               .max_cmds = 100,
                .cache_line_size = 0x20,
+               .clear_isr = 1,
                {
                        .set_interrupt_mask_reg = 0x0022C,
                        .clr_interrupt_mask_reg = 0x00230,
@@ -126,7 +128,9 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
        },
        { /* Snipe and Scamp */
                .mailbox = 0x0052C,
+               .max_cmds = 100,
                .cache_line_size = 0x20,
+               .clear_isr = 1,
                {
                        .set_interrupt_mask_reg = 0x00288,
                        .clr_interrupt_mask_reg = 0x0028C,
@@ -148,7 +152,9 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
        },
        { /* CRoC */
                .mailbox = 0x00044,
+               .max_cmds = 1000,
                .cache_line_size = 0x20,
+               .clear_isr = 0,
                {
                        .set_interrupt_mask_reg = 0x00010,
                        .clr_interrupt_mask_reg = 0x00018,
@@ -847,8 +853,6 @@ static void ipr_do_req(struct ipr_cmnd *ipr_cmd,
 
        ipr_trc_hook(ipr_cmd, IPR_TRACE_START, 0);
 
-       mb();
-
        ipr_send_command(ipr_cmd);
 }
 
@@ -982,8 +986,6 @@ static void ipr_send_hcam(struct ipr_ioa_cfg *ioa_cfg, u8 type,
 
                ipr_trc_hook(ipr_cmd, IPR_TRACE_START, IPR_IOA_RES_ADDR);
 
-               mb();
-
                ipr_send_command(ipr_cmd);
        } else {
                list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q);
@@ -4547,8 +4549,12 @@ static int ipr_ata_slave_alloc(struct scsi_device *sdev)
        ENTER;
        if (sdev->sdev_target)
                sata_port = sdev->sdev_target->hostdata;
-       if (sata_port)
+       if (sata_port) {
                rc = ata_sas_port_init(sata_port->ap);
+               if (rc == 0)
+                       rc = ata_sas_sync_probe(sata_port->ap);
+       }
+
        if (rc)
                ipr_slave_destroy(sdev);
 
@@ -5049,12 +5055,14 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
                del_timer(&ioa_cfg->reset_cmd->timer);
                ipr_reset_ioa_job(ioa_cfg->reset_cmd);
        } else if ((int_reg & IPR_PCII_HRRQ_UPDATED) == int_reg) {
-               if (ipr_debug && printk_ratelimit())
-                       dev_err(&ioa_cfg->pdev->dev,
-                               "Spurious interrupt detected. 0x%08X\n", int_reg);
-               writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
-               int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
-               return IRQ_NONE;
+               if (ioa_cfg->clear_isr) {
+                       if (ipr_debug && printk_ratelimit())
+                               dev_err(&ioa_cfg->pdev->dev,
+                                       "Spurious interrupt detected. 0x%08X\n", int_reg);
+                       writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
+                       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
+                       return IRQ_NONE;
+               }
        } else {
                if (int_reg & IPR_PCII_IOA_UNIT_CHECKED)
                        ioa_cfg->ioa_unit_checked = 1;
@@ -5154,6 +5162,9 @@ static irqreturn_t ipr_isr(int irq, void *devp)
                        }
                }
 
+               if (ipr_cmd && !ioa_cfg->clear_isr)
+                       break;
+
                if (ipr_cmd != NULL) {
                        /* Clear the PCI interrupt */
                        num_hrrq = 0;
@@ -5855,14 +5866,12 @@ static int ipr_queuecommand_lck(struct scsi_cmnd *scsi_cmd,
                        rc = ipr_build_ioadl(ioa_cfg, ipr_cmd);
        }
 
-       if (likely(rc == 0)) {
-               mb();
-               ipr_send_command(ipr_cmd);
-       } else {
-                list_move_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-                return SCSI_MLQUEUE_HOST_BUSY;
+       if (unlikely(rc != 0)) {
+               list_move_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+               return SCSI_MLQUEUE_HOST_BUSY;
        }
 
+       ipr_send_command(ipr_cmd);
        return 0;
 }
 
@@ -6240,8 +6249,6 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
                return AC_ERR_INVALID;
        }
 
-       mb();
-
        ipr_send_command(ipr_cmd);
 
        return 0;
@@ -8278,6 +8285,10 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
        if (ioa_cfg->ipr_cmd_pool)
                pci_pool_destroy (ioa_cfg->ipr_cmd_pool);
 
+       kfree(ioa_cfg->ipr_cmnd_list);
+       kfree(ioa_cfg->ipr_cmnd_list_dma);
+       ioa_cfg->ipr_cmnd_list = NULL;
+       ioa_cfg->ipr_cmnd_list_dma = NULL;
        ioa_cfg->ipr_cmd_pool = NULL;
 }
 
@@ -8353,11 +8364,19 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
        int i;
 
        ioa_cfg->ipr_cmd_pool = pci_pool_create (IPR_NAME, ioa_cfg->pdev,
-                                                sizeof(struct ipr_cmnd), 16, 0);
+                                                sizeof(struct ipr_cmnd), 512, 0);
 
        if (!ioa_cfg->ipr_cmd_pool)
                return -ENOMEM;
 
+       ioa_cfg->ipr_cmnd_list = kcalloc(IPR_NUM_CMD_BLKS, sizeof(struct ipr_cmnd *), GFP_KERNEL);
+       ioa_cfg->ipr_cmnd_list_dma = kcalloc(IPR_NUM_CMD_BLKS, sizeof(dma_addr_t), GFP_KERNEL);
+
+       if (!ioa_cfg->ipr_cmnd_list || !ioa_cfg->ipr_cmnd_list_dma) {
+               ipr_free_cmd_blks(ioa_cfg);
+               return -ENOMEM;
+       }
+
        for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
                ipr_cmd = pci_pool_alloc (ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
 
@@ -8585,6 +8604,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
        host->max_channel = IPR_MAX_BUS_TO_SCAN;
        host->unique_id = host->host_no;
        host->max_cmd_len = IPR_MAX_CDB_LEN;
+       host->can_queue = ioa_cfg->max_cmds;
        pci_set_drvdata(pdev, ioa_cfg);
 
        p = &ioa_cfg->chip_cfg->regs;
@@ -8769,6 +8789,8 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        /* set SIS 32 or SIS 64 */
        ioa_cfg->sis64 = ioa_cfg->ipr_chip->sis_type == IPR_SIS64 ? 1 : 0;
        ioa_cfg->chip_cfg = ioa_cfg->ipr_chip->cfg;
+       ioa_cfg->clear_isr = ioa_cfg->chip_cfg->clear_isr;
+       ioa_cfg->max_cmds = ioa_cfg->chip_cfg->max_cmds;
 
        if (ipr_transop_timeout)
                ioa_cfg->transop_timeout = ipr_transop_timeout;