From acf356b12d13c8b43c486e53e8ee12f1f435ecc8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Mar 2006 14:07:50 +0900 Subject: [PATCH] libata: add per-dev pio/mwdma/udma_mask Add per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index 7a54244d30aa..fbe8ba212598 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -358,6 +358,11 @@ struct ata_device { unsigned int max_sectors; /* per-device max sectors */ unsigned int cdb_len; + /* per-dev xfer mask */ + unsigned int pio_mask; + unsigned int mwdma_mask; + unsigned int udma_mask; + /* for CHS addressing */ u16 cylinders; /* Number of cylinders */ u16 heads; /* Number of heads */ -- cgit v1.2.3 From 082776e4be791736c32baf818e50f501a7f83819 Mon Sep 17 00:00:00 2001 From: Nigel Cunningham Date: Thu, 23 Mar 2006 23:22:16 +1000 Subject: [PATCH] Make libata not powerdown drivers on PM_EVENT_FREEZE. At the moment libata doesn't pass pm_message_t down ata_device_suspend. This causes drives to be powered down when we just want a freeze, causing unnecessary wear and tear. This patch gets pm_message_t passed down so that it can be used to determine whether to power down the drive. Signed-off-by: Nigel Cunningham drivers/scsi/libata-core.c | 5 +++-- drivers/scsi/libata-scsi.c | 4 ++-- drivers/scsi/scsi_sysfs.c | 2 +- include/linux/libata.h | 4 ++-- include/scsi/scsi_host.h | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 5 +++-- drivers/scsi/libata-scsi.c | 4 ++-- drivers/scsi/scsi_sysfs.c | 2 +- include/linux/libata.h | 4 ++-- include/scsi/scsi_host.h | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6970f6867334..d8f77f2a5af1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4336,14 +4336,15 @@ int ata_device_resume(struct ata_port *ap, struct ata_device *dev) * Flush the cache on the drive, if appropriate, then issue a * standbynow command. */ -int ata_device_suspend(struct ata_port *ap, struct ata_device *dev) +int ata_device_suspend(struct ata_port *ap, struct ata_device *dev, pm_message_t state) { if (!ata_dev_present(dev)) return 0; if (dev->class == ATA_DEV_ATA) ata_flush_cache(ap, dev); - ata_standby_drive(ap, dev); + if (state.event != PM_EVENT_FREEZE) + ata_standby_drive(ap, dev); ap->flags |= ATA_FLAG_SUSPENDED; return 0; } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index a1259b242b8e..1fd3826da97e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -414,12 +414,12 @@ int ata_scsi_device_resume(struct scsi_device *sdev) return ata_device_resume(ap, dev); } -int ata_scsi_device_suspend(struct scsi_device *sdev) +int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) { struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; struct ata_device *dev = &ap->device[sdev->id]; - return ata_device_suspend(ap, dev); + return ata_device_suspend(ap, dev, state); } /** diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 89055494dfee..a6fde52946d6 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -286,7 +286,7 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state) return err; if (sht->suspend) - err = sht->suspend(sdev); + err = sht->suspend(sdev, state); return err; } diff --git a/include/linux/libata.h b/include/linux/libata.h index fbe8ba212598..c52f13498556 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -520,9 +520,9 @@ extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); extern int ata_scsi_release(struct Scsi_Host *host); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern int ata_scsi_device_resume(struct scsi_device *); -extern int ata_scsi_device_suspend(struct scsi_device *); +extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); extern int ata_device_resume(struct ata_port *, struct ata_device *); -extern int ata_device_suspend(struct ata_port *, struct ata_device *); +extern int ata_device_suspend(struct ata_port *, struct ata_device *, pm_message_t state); extern int ata_ratelimit(void); extern unsigned int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index a6cf3e535c0b..dc6862d09e53 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -286,7 +286,7 @@ struct scsi_host_template { * suspend support */ int (*resume)(struct scsi_device *); - int (*suspend)(struct scsi_device *); + int (*suspend)(struct scsi_device *, pm_message_t state); /* * Name of proc directory -- cgit v1.2.3 From ebdfca6eb1b755d3bfe9a81339ecdafd92038c1a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 23 Mar 2006 15:38:34 +0000 Subject: [PATCH] libata: add ata_dev_pair helper Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 17 +++++++++++++++++ include/linux/libata.h | 2 ++ 2 files changed, 19 insertions(+) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d8f77f2a5af1..909568f7a72a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1575,6 +1575,23 @@ void sata_phy_reset(struct ata_port *ap) ata_bus_reset(ap); } +/** + * ata_dev_pair - return other device on cable + * @ap: port + * @adev: device + * + * Obtain the other device on the same cable, or if none is + * present NULL is returned + */ + +struct ata_device *ata_dev_pair(struct ata_port *ap, struct ata_device *adev) +{ + struct ata_device *pair = &ap->device[1 - adev->devno]; + if (!ata_dev_present(pair)) + return NULL; + return pair; +} + /** * ata_port_disable - Disable port. * @ap: Port to be disabled. diff --git a/include/linux/libata.h b/include/linux/libata.h index c52f13498556..80c2339da67d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -573,6 +573,8 @@ extern int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]); extern int ata_scsi_slave_config(struct scsi_device *sdev); +extern struct ata_device *ata_dev_pair(struct ata_port *ap, + struct ata_device *adev); /* * Timing helpers -- cgit v1.2.3 From 2f1f610b62bce36d6d50857859091b8989c70267 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 23 Mar 2006 17:30:15 -0600 Subject: [PATCH] libata: Remove dependence on host_set->dev for SAS Remove some of the dependence on the host_set struct in preparation for supporting SAS HBAs. Adds a struct device pointer to the ata_port struct. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 13 +++++++------ include/linux/libata.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 94ad4acf8a59..d279666dcb38 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2856,7 +2856,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) if (qc->flags & ATA_QCFLAG_SG) { if (qc->n_elem) - dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir); + dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); /* restore last sg */ sg[qc->orig_n_elem - 1].length += qc->pad_len; if (pad_buf) { @@ -2867,7 +2867,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) } } else { if (qc->n_elem) - dma_unmap_single(ap->host_set->dev, + dma_unmap_single(ap->dev, sg_dma_address(&sg[0]), sg_dma_len(&sg[0]), dir); /* restore sg */ @@ -3078,7 +3078,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) goto skip_map; } - dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, + dma_address = dma_map_single(ap->dev, qc->buf_virt, sg->length, dir); if (dma_mapping_error(dma_address)) { /* restore sg */ @@ -3166,7 +3166,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) } dir = qc->dma_dir; - n_elem = dma_map_sg(ap->host_set->dev, sg, pre_n_elem, dir); + n_elem = dma_map_sg(ap->dev, sg, pre_n_elem, dir); if (n_elem < 1) { /* restore last sg */ lsg->length += qc->pad_len; @@ -4381,7 +4381,7 @@ int ata_device_suspend(struct ata_port *ap, struct ata_device *dev, pm_message_t int ata_port_start (struct ata_port *ap) { - struct device *dev = ap->host_set->dev; + struct device *dev = ap->dev; int rc; ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); @@ -4414,7 +4414,7 @@ int ata_port_start (struct ata_port *ap) void ata_port_stop (struct ata_port *ap) { - struct device *dev = ap->host_set->dev; + struct device *dev = ap->dev; dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); ata_pad_free(ap, dev); @@ -4480,6 +4480,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->host = host; ap->ctl = ATA_DEVCTL_OBS; ap->host_set = host_set; + ap->dev = ent->dev; ap->port_no = port_no; ap->hard_port_no = ent->legacy_mode ? ent->hard_port_no : port_no; diff --git a/include/linux/libata.h b/include/linux/libata.h index 80c2339da67d..047192253c3a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -400,6 +400,7 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; + struct device *dev; struct work_struct port_task; -- cgit v1.2.3