diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-11-17 20:59:52 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 14:55:42 -0500 |
commit | b91bb296188118eea9fdc6093cfcf76bbe8589ba (patch) | |
tree | 8fe9dda8894514f9cd1184368eab975583c12f3c /drivers/scsi/aic94xx | |
parent | 87c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2 (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.h | 2 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_dev.c | 38 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_init.c | 2 |
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 | ||
81 | int asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags); | 81 | int asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags); |
82 | 82 | ||
83 | void asd_set_dmamode(struct domain_device *dev); | ||
84 | |||
83 | /* ---------- TMFs ---------- */ | 85 | /* ---------- TMFs ---------- */ |
84 | int asd_abort_task(struct sas_task *); | 86 | int asd_abort_task(struct sas_task *); |
85 | int asd_abort_task_set(struct domain_device *, u8 *lun); | 87 | 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 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 | ||
112 | static int asd_init_sata(struct domain_device *dev) | 112 | void 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 | |||
137 | static 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 | ||
144 | static int asd_init_target_ddb(struct domain_device *dev) | 154 | 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 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 | ||
1014 | static const struct pci_device_id aic94xx_pci_table[] __devinitdata = { | 1016 | static const struct pci_device_id aic94xx_pci_table[] __devinitdata = { |