[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>
Este cometimento está contido em:

cometido por
James Bottomley

ascendente
87c8331fcf
cometimento
b91bb29618
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -1009,6 +1009,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 = {
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador