summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic94xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aic94xx')
-rw-r--r--drivers/scsi/aic94xx/aic94xx.h2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_dev.c38
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c6
-rw-r--r--drivers/scsi/aic94xx/aic94xx_tmf.c11
4 files changed, 36 insertions, 21 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h
index 2863a9d2285..66cda669b41 100644
--- a/drivers/scsi/aic94xx/aic94xx.h
+++ b/drivers/scsi/aic94xx/aic94xx.h
@@ -80,6 +80,8 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id);
int asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags);
+void asd_set_dmamode(struct domain_device *dev);
+
/* ---------- TMFs ---------- */
int asd_abort_task(struct sas_task *);
int asd_abort_task_set(struct domain_device *, u8 *lun);
diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c
index 2e2ddec9c0b..64136c56e70 100644
--- a/drivers/scsi/aic94xx/aic94xx_dev.c
+++ b/drivers/scsi/aic94xx/aic94xx_dev.c
@@ -109,26 +109,37 @@ static int asd_init_sata_tag_ddb(struct domain_device *dev)
return 0;
}
-static int asd_init_sata(struct domain_device *dev)
+void asd_set_dmamode(struct domain_device *dev)
{
struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
+ struct ata_device *ata_dev = sas_to_ata_dev(dev);
int ddb = (int) (unsigned long) dev->lldd_dev;
u32 qdepth = 0;
- int res = 0;
- asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF);
- if ((dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM_PORT) &&
- dev->sata_dev.identify_device &&
- dev->sata_dev.identify_device[10] != 0) {
- u16 w75 = le16_to_cpu(dev->sata_dev.identify_device[75]);
- u16 w76 = le16_to_cpu(dev->sata_dev.identify_device[76]);
-
- if (w76 & 0x100) /* NCQ? */
- qdepth = (w75 & 0x1F) + 1;
+ if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM_PORT) {
+ if (ata_id_has_ncq(ata_dev->id))
+ qdepth = ata_id_queue_depth(ata_dev->id);
asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK,
(1ULL<<qdepth)-1);
asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth);
}
+
+ if (qdepth > 0)
+ if (asd_init_sata_tag_ddb(dev) != 0) {
+ unsigned long flags;
+
+ spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
+ ata_dev->flags |= ATA_DFLAG_NCQ_OFF;
+ spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
+ }
+}
+
+static int asd_init_sata(struct domain_device *dev)
+{
+ struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
+ int ddb = (int) (unsigned long) dev->lldd_dev;
+
+ asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF);
if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM ||
dev->dev_type == SATA_PM_PORT) {
struct dev_to_host_fis *fis = (struct dev_to_host_fis *)
@@ -136,9 +147,8 @@ static int asd_init_sata(struct domain_device *dev)
asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status);
}
asd_ddbsite_write_word(asd_ha, ddb, NCQ_DATA_SCB_PTR, 0xFFFF);
- if (qdepth > 0)
- res = asd_init_sata_tag_ddb(dev);
- return res;
+
+ return 0;
}
static int asd_init_target_ddb(struct domain_device *dev)
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index d5ff142c93a..ff80552ead8 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -68,7 +68,6 @@ static struct scsi_host_template aic94xx_sht = {
.queuecommand = sas_queuecommand,
.target_alloc = sas_target_alloc,
.slave_configure = sas_slave_configure,
- .slave_destroy = sas_slave_destroy,
.scan_finished = asd_scan_finished,
.scan_start = asd_scan_start,
.change_queue_depth = sas_change_queue_depth,
@@ -82,7 +81,6 @@ static struct scsi_host_template aic94xx_sht = {
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
};
@@ -972,7 +970,7 @@ static int asd_scan_finished(struct Scsi_Host *shost, unsigned long time)
if (time < HZ)
return 0;
/* Wait for discovery to finish */
- scsi_flush_work(shost);
+ sas_drain_work(SHOST_TO_SAS_HA(shost));
return 1;
}
@@ -1010,6 +1008,8 @@ static struct sas_domain_function_template aic94xx_transport_functions = {
.lldd_clear_nexus_ha = asd_clear_nexus_ha,
.lldd_control_phy = asd_control_phy,
+
+ .lldd_ata_set_dmamode = asd_set_dmamode,
};
static const struct pci_device_id aic94xx_pci_table[] __devinitdata = {
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index 0add73bdf2a..cf9040933da 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -181,7 +181,7 @@ static int asd_clear_nexus_I_T(struct domain_device *dev,
int asd_I_T_nexus_reset(struct domain_device *dev)
{
int res, tmp_res, i;
- struct sas_phy *phy = sas_find_local_phy(dev);
+ struct sas_phy *phy = sas_get_local_phy(dev);
/* Standard mandates link reset for ATA (type 0) and
* hard reset for SSP (type 1) */
int reset_type = (dev->dev_type == SATA_DEV ||
@@ -192,7 +192,7 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
ASD_DPRINTK("sending %s reset to %s\n",
reset_type ? "hard" : "soft", dev_name(&phy->dev));
res = sas_phy_reset(phy, reset_type);
- if (res == TMF_RESP_FUNC_COMPLETE) {
+ if (res == TMF_RESP_FUNC_COMPLETE || res == -ENODEV) {
/* wait for the maximum settle time */
msleep(500);
/* clear all outstanding commands (keep nexus suspended) */
@@ -201,7 +201,7 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
for (i = 0 ; i < 3; i++) {
tmp_res = asd_clear_nexus_I_T(dev, NEXUS_PHASE_RESUME);
if (tmp_res == TC_RESUME)
- return res;
+ goto out;
msleep(500);
}
@@ -211,7 +211,10 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
dev_printk(KERN_ERR, &phy->dev,
"Failed to resume nexus after reset 0x%x\n", tmp_res);
- return TMF_RESP_FUNC_FAILED;
+ res = TMF_RESP_FUNC_FAILED;
+ out:
+ sas_put_local_phy(phy);
+ return res;
}
static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun)