aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic94xx
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-11-17 20:59:52 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 14:55:42 -0500
commitb91bb296188118eea9fdc6093cfcf76bbe8589ba (patch)
tree8fe9dda8894514f9cd1184368eab975583c12f3c /drivers/scsi/aic94xx
parent87c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2 (diff)
[SCSI] libsas: use ->set_dmamode to notify lldds of NCQ parameters
sas_discover_sata() notifies lldds of sata devices twice. Once to allow the 'identify' to be sent, and a second time to allow aic94xx (the only libsas driver that cares about sata_dev.identify) to setup NCQ parameters before the device becomes known to the midlayer. Replace this double notification and intervening 'identify' with an explicit ->lldd_ata_set_dmamode notification. With this change all ata internal commands are issued by libata, so we no longer need sas_issue_ata_cmd(). The data from the identify command only needs to be cached in one location so ata_device.id replaces domain_device.sata_dev.identify. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
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.c2
3 files changed, 28 insertions, 14 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h
index 2863a9d22851..66cda669b417 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);
80 80
81int asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags); 81int asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags);
82 82
83void asd_set_dmamode(struct domain_device *dev);
84
83/* ---------- TMFs ---------- */ 85/* ---------- TMFs ---------- */
84int asd_abort_task(struct sas_task *); 86int asd_abort_task(struct sas_task *);
85int asd_abort_task_set(struct domain_device *, u8 *lun); 87int 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 2e2ddec9c0b6..64136c56e706 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)
109 return 0; 109 return 0;
110} 110}
111 111
112static int asd_init_sata(struct domain_device *dev) 112void asd_set_dmamode(struct domain_device *dev)
113{ 113{
114 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 114 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
115 struct ata_device *ata_dev = sas_to_ata_dev(dev);
115 int ddb = (int) (unsigned long) dev->lldd_dev; 116 int ddb = (int) (unsigned long) dev->lldd_dev;
116 u32 qdepth = 0; 117 u32 qdepth = 0;
117 int res = 0;
118 118
119 asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF); 119 if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM_PORT) {
120 if ((dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM_PORT) && 120 if (ata_id_has_ncq(ata_dev->id))
121 dev->sata_dev.identify_device && 121 qdepth = ata_id_queue_depth(ata_dev->id);
122 dev->sata_dev.identify_device[10] != 0) {
123 u16 w75 = le16_to_cpu(dev->sata_dev.identify_device[75]);
124 u16 w76 = le16_to_cpu(dev->sata_dev.identify_device[76]);
125
126 if (w76 & 0x100) /* NCQ? */
127 qdepth = (w75 & 0x1F) + 1;
128 asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, 122 asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK,
129 (1ULL<<qdepth)-1); 123 (1ULL<<qdepth)-1);
130 asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth); 124 asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth);
131 } 125 }
126
127 if (qdepth > 0)
128 if (asd_init_sata_tag_ddb(dev) != 0) {
129 unsigned long flags;
130
131 spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
132 ata_dev->flags |= ATA_DFLAG_NCQ_OFF;
133 spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
134 }
135}
136
137static int asd_init_sata(struct domain_device *dev)
138{
139 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
140 int ddb = (int) (unsigned long) dev->lldd_dev;
141
142 asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF);
132 if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM || 143 if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM ||
133 dev->dev_type == SATA_PM_PORT) { 144 dev->dev_type == SATA_PM_PORT) {
134 struct dev_to_host_fis *fis = (struct dev_to_host_fis *) 145 struct dev_to_host_fis *fis = (struct dev_to_host_fis *)
@@ -136,9 +147,8 @@ static int asd_init_sata(struct domain_device *dev)
136 asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status); 147 asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status);
137 } 148 }
138 asd_ddbsite_write_word(asd_ha, ddb, NCQ_DATA_SCB_PTR, 0xFFFF); 149 asd_ddbsite_write_word(asd_ha, ddb, NCQ_DATA_SCB_PTR, 0xFFFF);
139 if (qdepth > 0) 150
140 res = asd_init_sata_tag_ddb(dev); 151 return 0;
141 return res;
142} 152}
143 153
144static int asd_init_target_ddb(struct domain_device *dev) 154static 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 2b3717f6d22c..eea988a04f92 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -1009,6 +1009,8 @@ static struct sas_domain_function_template aic94xx_transport_functions = {
1009 .lldd_clear_nexus_ha = asd_clear_nexus_ha, 1009 .lldd_clear_nexus_ha = asd_clear_nexus_ha,
1010 1010
1011 .lldd_control_phy = asd_control_phy, 1011 .lldd_control_phy = asd_control_phy,
1012
1013 .lldd_ata_set_dmamode = asd_set_dmamode,
1012}; 1014};
1013 1015
1014static const struct pci_device_id aic94xx_pci_table[] __devinitdata = { 1016static const struct pci_device_id aic94xx_pci_table[] __devinitdata = {