Commit b91bb296 authored by Dan Williams's avatar Dan Williams Committed by James Bottomley

[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: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 87c8331f
...@@ -80,6 +80,8 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id); ...@@ -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); int asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags);
void asd_set_dmamode(struct domain_device *dev);
/* ---------- TMFs ---------- */ /* ---------- TMFs ---------- */
int asd_abort_task(struct sas_task *); int asd_abort_task(struct sas_task *);
int asd_abort_task_set(struct domain_device *, u8 *lun); 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) ...@@ -109,26 +109,37 @@ static int asd_init_sata_tag_ddb(struct domain_device *dev)
return 0; 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 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; int ddb = (int) (unsigned long) dev->lldd_dev;
u32 qdepth = 0; 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) {
if ((dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM_PORT) && if (ata_id_has_ncq(ata_dev->id))
dev->sata_dev.identify_device && qdepth = ata_id_queue_depth(ata_dev->id);
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;
asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK,
(1ULL<<qdepth)-1); (1ULL<<qdepth)-1);
asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth); 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 || if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM ||
dev->dev_type == SATA_PM_PORT) { dev->dev_type == SATA_PM_PORT) {
struct dev_to_host_fis *fis = (struct dev_to_host_fis *) 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,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_byte(asd_ha, ddb, SATA_STATUS, fis->status);
} }
asd_ddbsite_write_word(asd_ha, ddb, NCQ_DATA_SCB_PTR, 0xFFFF); asd_ddbsite_write_word(asd_ha, ddb, NCQ_DATA_SCB_PTR, 0xFFFF);
if (qdepth > 0)
res = asd_init_sata_tag_ddb(dev); return 0;
return res;
} }
static int asd_init_target_ddb(struct domain_device *dev) static int asd_init_target_ddb(struct domain_device *dev)
......
...@@ -1009,6 +1009,8 @@ static struct sas_domain_function_template aic94xx_transport_functions = { ...@@ -1009,6 +1009,8 @@ static struct sas_domain_function_template aic94xx_transport_functions = {
.lldd_clear_nexus_ha = asd_clear_nexus_ha, .lldd_clear_nexus_ha = asd_clear_nexus_ha,
.lldd_control_phy = asd_control_phy, .lldd_control_phy = asd_control_phy,
.lldd_ata_set_dmamode = asd_set_dmamode,
}; };
static const struct pci_device_id aic94xx_pci_table[] __devinitdata = { static const struct pci_device_id aic94xx_pci_table[] __devinitdata = {
......
This diff is collapsed.
...@@ -237,11 +237,6 @@ void sas_free_device(struct kref *kref) ...@@ -237,11 +237,6 @@ void sas_free_device(struct kref *kref)
if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV)
kfree(dev->ex_dev.ex_phy); kfree(dev->ex_dev.ex_phy);
if (dev_is_sata(dev)) {
kfree(dev->sata_dev.identify_device);
kfree(dev->sata_dev.identify_packet_device);
}
kfree(dev); kfree(dev);
} }
......
...@@ -164,9 +164,6 @@ enum ata_command_set { ...@@ -164,9 +164,6 @@ enum ata_command_set {
struct sata_device { struct sata_device {
enum ata_command_set command_set; enum ata_command_set command_set;
struct smp_resp rps_resp; /* report_phy_sata_resp */ struct smp_resp rps_resp; /* report_phy_sata_resp */
__le16 *identify_device;
__le16 *identify_packet_device;
u8 port_no; /* port number, if this is a PM (Port) */ u8 port_no; /* port number, if this is a PM (Port) */
struct list_head children; /* PM Ports if this is a PM */ struct list_head children; /* PM Ports if this is a PM */
...@@ -609,6 +606,7 @@ struct sas_domain_function_template { ...@@ -609,6 +606,7 @@ struct sas_domain_function_template {
int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); int (*lldd_clear_task_set)(struct domain_device *, u8 *lun);
int (*lldd_I_T_nexus_reset)(struct domain_device *); int (*lldd_I_T_nexus_reset)(struct domain_device *);
int (*lldd_ata_soft_reset)(struct domain_device *); int (*lldd_ata_soft_reset)(struct domain_device *);
void (*lldd_ata_set_dmamode)(struct domain_device *);
int (*lldd_lu_reset)(struct domain_device *, u8 *lun); int (*lldd_lu_reset)(struct domain_device *, u8 *lun);
int (*lldd_query_task)(struct sas_task *); int (*lldd_query_task)(struct sas_task *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment