linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHSET] libata: improve initialization and legacy handling, take#2
@ 2006-08-04 21:01 Tejun Heo
  2006-08-04 21:01 ` [PATCH 1/9] [libata] some function renaming Tejun Heo
                   ` (9 more replies)
  0 siblings, 10 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, alan, davej, linux-ide, htejun

Hello, all.

This is the second take of improve-init-and-legacy patchset.  This
patchset contains patches from Jeff Garzik, Alan Cox, Dave Jones and
me to fix/clean up initializaton and legacy handling.  Changes from
the last take[L] are

* fix patches moved out to fixes-to-upstream-fixes patchset[1].

* per-dev xfermask separated out from rework-legacy-handling patch,
  fixed to choose safe PIO mode and warning message added when DMA is
  disabled due to simplex.

This patchset is against

  libata-dev#upstream [U] 
  + fixes-to-upstream-fixes patchset [1]

This patchset is available in the following git tree (updates to
#upstream-fixes properly merged).

  http://htj.dyndns.org/git/?p=libata-tj.git;a=shortlog;h=tj-upstream
  git://htj.dyndns.org/libata-tj tj-upstream

PATA drivers have been updated accordingly and available at (again,
properly merged)

  http://htj.dyndns.org/git/?p=libata-tj.git;a=shortlog;h=tj-pata-drivers
  git://htj.dyndns.org/libata-tj tj-pata-drivers

Updated ALL branch is available at (ditto)

  http://htj.dyndns.org/git/?p=libata-tj.git;a=shortlog;h=tj-ALL
  git://htj.dyndns.org/libata-tj tj-ALL

PATA patch hasn't been changed other than being rebased.

Thanks.

--
tejun

[L] http://article.gmane.org/gmane.linux.ide/12347
[U] 236a686b56428a8967a057a2396f9be74e2ee652
[1] http://article.gmane.org/gmane.linux.ide/12393



^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/9] [libata] some function renaming
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
@ 2006-08-04 21:01 ` Tejun Heo
  2006-08-09  4:24   ` Jeff Garzik
  2006-08-09  4:25   ` Jeff Garzik
  2006-08-04 21:01 ` [PATCH 3/9] libata: implement per-dev xfermask Tejun Heo
                   ` (8 subsequent siblings)
  9 siblings, 2 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, alan, davej, linux-ide; +Cc: Jeff Garzik, Tejun Heo

s/ata_host_add/ata_port_add/
s/ata_host_init/ata_port_init/

libata naming got stuck in the middle of a Great Renaming:

	ata_host -> ata_port
	ata_host_set -> ata_host

To eliminate confusion, let's just give up for now, and simply ensure
that things are internally consistent.

Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/libata-core.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

580fa7772f5d87a414dee32b1b0d37c5caf826c7
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 351544d..b5af446 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5218,7 +5218,7 @@ void ata_dev_init(struct ata_device *dev
 }
 
 /**
- *	ata_host_init - Initialize an ata_port structure
+ *	ata_port_init - Initialize an ata_port structure
  *	@ap: Structure to initialize
  *	@host: associated SCSI mid-layer structure
  *	@host_set: Collection of hosts to which @ap belongs
@@ -5231,7 +5231,7 @@ void ata_dev_init(struct ata_device *dev
  *	LOCKING:
  *	Inherited from caller.
  */
-static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
+static void ata_port_init(struct ata_port *ap, struct Scsi_Host *host,
 			  struct ata_host_set *host_set,
 			  const struct ata_probe_ent *ent, unsigned int port_no)
 {
@@ -5298,7 +5298,7 @@ #endif
 }
 
 /**
- *	ata_host_add - Attach low-level ATA driver to system
+ *	ata_port_add - Attach low-level ATA driver to system
  *	@ent: Information provided by low-level driver
  *	@host_set: Collections of ports to which we add
  *	@port_no: Port number associated with this host
@@ -5312,7 +5312,7 @@ #endif
  *	New ata_port on success, for NULL on error.
  */
 
-static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
+static struct ata_port * ata_port_add(const struct ata_probe_ent *ent,
 				      struct ata_host_set *host_set,
 				      unsigned int port_no)
 {
@@ -5337,7 +5337,7 @@ static struct ata_port * ata_host_add(co
 
 	ap = ata_shost_to_port(host);
 
-	ata_host_init(ap, host, host_set, ent, port_no);
+	ata_port_init(ap, host, host_set, ent, port_no);
 
 	rc = ap->ops->port_start(ap);
 	if (rc)
@@ -5396,7 +5396,7 @@ int ata_device_add(const struct ata_prob
 		struct ata_port *ap;
 		unsigned long xfer_mode_mask;
 
-		ap = ata_host_add(ent, host_set, i);
+		ap = ata_port_add(ent, host_set, i);
 		if (!ap)
 			goto err_out;
 
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 7/9] libata: use dummy port for stolen legacy ports
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
                   ` (4 preceding siblings ...)
  2006-08-04 21:01 ` [PATCH 2/9] [libata] Kill 'count' var in ata_device_add() Tejun Heo
@ 2006-08-04 21:01 ` Tejun Heo
  2006-08-04 21:01 ` [PATCH 4/9] libata: rework legacy handling to remove much of the cruft Tejun Heo
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, alan, davej, linux-ide; +Cc: Tejun Heo

Use dummy port for stolen legacy ports.  This makes ap->port_no always
equal ap->hard_port_no.

Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/libata-bmdma.c |   41 +++++++++++++++++------------------------
 drivers/scsi/libata-core.c  |    2 --
 2 files changed, 17 insertions(+), 26 deletions(-)

521e56e4ce188a588e4457527734edddbcd8ebb1
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index d43dc9a..c4cd578 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -898,50 +898,43 @@ static struct ata_probe_ent *ata_pci_ini
 	struct ata_probe_ent *probe_ent;
 	unsigned long bmdma = pci_resource_start(pdev, 4);
 
-	int port_num = 0;
-
 	probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
 	if (!probe_ent)
 		return NULL;
 
-	probe_ent->legacy_mode = 1;
-	probe_ent->hard_port_no = 0;
+	probe_ent->n_ports = 2;
 	probe_ent->private_data = port[0]->private_data;
 
 	if (port_mask & ATA_PORT_PRIMARY) {
 		probe_ent->irq = 14;
-		probe_ent->port[port_num].cmd_addr = ATA_PRIMARY_CMD;
-		probe_ent->port[port_num].altstatus_addr =
-		probe_ent->port[port_num].ctl_addr = ATA_PRIMARY_CTL;
+		probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD;
+		probe_ent->port[0].altstatus_addr =
+		probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
 		if (bmdma) {
 			probe_ent->port[0].bmdma_addr = bmdma;
 			if (inb(bmdma + 2) & 0x80)
 				probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
 		}
-		ata_std_ports(&probe_ent->port[port_num]);
-		port_num ++;
-	}
+		ata_std_ports(&probe_ent->port[0]);
+	} else
+		probe_ent->dummy_port_mask |= ATA_PORT_PRIMARY;
+
 	if (port_mask & ATA_PORT_SECONDARY) {
-		if (port_num == 1)
+		if (probe_ent->irq)
 			probe_ent->irq2 = 15;
-		else {
-			/* Secondary only. IRQ 15 only and "first" port is port 1 */
+		else
 			probe_ent->irq = 15;
-			probe_ent->hard_port_no = 1;
-		}
-		probe_ent->port[port_num].cmd_addr = ATA_SECONDARY_CMD;
-		probe_ent->port[port_num].altstatus_addr =
-		probe_ent->port[port_num].ctl_addr = ATA_SECONDARY_CTL;
+		probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD;
+		probe_ent->port[1].altstatus_addr =
+		probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
 		if (bmdma) {
-			probe_ent->port[port_num].bmdma_addr = bmdma + 8;
+			probe_ent->port[1].bmdma_addr = bmdma + 8;
 			if (inb(bmdma + 10) & 0x80)
 				probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
 		}
-		ata_std_ports(&probe_ent->port[port_num]);
-		port_num ++;
-	}
-
-	probe_ent->n_ports = port_num;
+		ata_std_ports(&probe_ent->port[1]);
+	} else
+		probe_ent->dummy_port_mask |= ATA_PORT_SECONDARY;
 
 	return probe_ent;
 }
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 8818c84..453dce0 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5245,8 +5245,6 @@ static void ata_port_init(struct ata_por
 	ap->dev = ent->dev;
 	ap->port_no = port_no;
 	ap->hard_port_no = port_no;
-	if (ent->legacy_mode)
-		ap->hard_port_no += ent->hard_port_no;
 	ap->pio_mask = ent->pio_mask;
 	ap->mwdma_mask = ent->mwdma_mask;
 	ap->udma_mask = ent->udma_mask;
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/9] libata: implement per-dev xfermask
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
  2006-08-04 21:01 ` [PATCH 1/9] [libata] some function renaming Tejun Heo
@ 2006-08-04 21:01 ` Tejun Heo
  2006-08-05 13:38   ` Alan Cox
  2006-08-09  4:30   ` Jeff Garzik
  2006-08-04 21:01 ` [PATCH 5/9] libata: fix several bugs in reworked legacy handling Tejun Heo
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, alan, davej, linux-ide; +Cc: Tejun Heo

Implement per-dev xfermask.  libata used to determine xfermask
per-port - the fastest mode of the slowest device on the port.  This
patch enables per-dev xfermask.

Original patch is from Alan Cox <alan@redhat.com>.  The following
changes are made by me.

* simplex warning message is added
* fix port-wide PIO mode selection to aovid violating device selection
  timing.

Cc: Alan Cox <alan@redhat.com>
Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/libata-core.c |   49 +++++++++++++++++++-------------------------
 1 files changed, 21 insertions(+), 28 deletions(-)

fd045a27aab1d64997f30a97f64e7aac355dd14d
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 1810bb2..7e1f3ee 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -3040,10 +3040,6 @@ static int ata_dma_blacklisted(const str
  *	known limits including host controller limits, device
  *	blacklist, etc...
  *
- *	FIXME: The current implementation limits all transfer modes to
- *	the fastest of the lowested device on the port.  This is not
- *	required on most controllers.
- *
  *	LOCKING:
  *	None.
  */
@@ -3054,6 +3050,7 @@ static void ata_dev_xfermask(struct ata_
 	unsigned long xfer_mask;
 	int i;
 
+	/* controller modes available */
 	xfer_mask = ata_pack_xfermask(ap->pio_mask,
 				      ap->mwdma_mask, ap->udma_mask);
 
@@ -3063,34 +3060,30 @@ static void ata_dev_xfermask(struct ata_
 	if (ap->cbl == ATA_CBL_PATA40)
 		xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
 
-	/* FIXME: Use port-wide xfermask for now */
-	for (i = 0; i < ATA_MAX_DEVICES; i++) {
-		struct ata_device *d = &ap->device[i];
-
-		if (ata_dev_absent(d))
-			continue;
-
-		if (ata_dev_disabled(d)) {
-			/* to avoid violating device selection timing */
-			xfer_mask &= ata_pack_xfermask(d->pio_mask,
-						       UINT_MAX, UINT_MAX);
-			continue;
-		}
-
-		xfer_mask &= ata_pack_xfermask(d->pio_mask,
-					       d->mwdma_mask, d->udma_mask);
-		xfer_mask &= ata_id_xfermask(d->id);
-		if (ata_dma_blacklisted(d))
-			xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-	}
+	xfer_mask &= ata_pack_xfermask(dev->pio_mask,
+				       dev->mwdma_mask, dev->udma_mask);
+	xfer_mask &= ata_id_xfermask(dev->id);
 
-	if (ata_dma_blacklisted(dev))
+	if (ata_dma_blacklisted(dev)) {
+		xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
 		ata_dev_printk(dev, KERN_WARNING,
 			       "device is on DMA blacklist, disabling DMA\n");
+	}
+
+	if ((hs->flags & ATA_HOST_SIMPLEX) && hs->simplex_claimed) {
+		xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+		ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
+			       "other device, disabling DMA\n");
+	}
 
-	if (hs->flags & ATA_HOST_SIMPLEX) {
-		if (hs->simplex_claimed)
-			xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+	/* Use the lowest common PIO mode to avoid violating device
+	 * selection timing.
+	 */
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *d = &ap->device[i];
+		if (!ata_dev_absent(d))
+			xfer_mask &= ata_pack_xfermask(d->pio_mask,
+						       UINT_MAX, UINT_MAX);
 	}
 
 	if (ap->ops->mode_filter)
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/9] [libata] Kill 'count' var in ata_device_add()
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
                   ` (3 preceding siblings ...)
  2006-08-04 21:01 ` [PATCH 6/9] libata: implement dummy port Tejun Heo
@ 2006-08-04 21:01 ` Tejun Heo
  2006-08-04 21:01 ` [PATCH 7/9] libata: use dummy port for stolen legacy ports Tejun Heo
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, alan, davej, linux-ide; +Cc: Jeff Garzik, Tejun Heo

Eliminate redundant loop variable 'count'

Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/libata-core.c |   20 +++++++-------------
 1 files changed, 7 insertions(+), 13 deletions(-)

7f87806d447d40354b7df79727802d24e4cf960c
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index b5af446..1810bb2 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5370,7 +5370,7 @@ err_out:
  */
 int ata_device_add(const struct ata_probe_ent *ent)
 {
-	unsigned int count = 0, i;
+	unsigned int i;
 	struct device *dev = ent->dev;
 	struct ata_host_set *host_set;
 	int rc;
@@ -5392,7 +5392,7 @@ int ata_device_add(const struct ata_prob
 	host_set->flags = ent->host_set_flags;
 
 	/* register each port bound to this device */
-	for (i = 0; i < ent->n_ports; i++) {
+	for (i = 0; i < host_set->n_ports; i++) {
 		struct ata_port *ap;
 		unsigned long xfer_mode_mask;
 
@@ -5418,12 +5418,8 @@ int ata_device_add(const struct ata_prob
 		ata_chk_status(ap);
 		host_set->ops->irq_clear(ap);
 		ata_eh_freeze_port(ap);	/* freeze port before requesting IRQ */
-		count++;
 	}
 
-	if (!count)
-		goto err_free_ret;
-
 	/* obtain irq, that is shared between channels */
 	rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
 			 DRV_NAME, host_set);
@@ -5435,13 +5431,11 @@ int ata_device_add(const struct ata_prob
 
 	/* perform each probe synchronously */
 	DPRINTK("probe begin\n");
-	for (i = 0; i < count; i++) {
-		struct ata_port *ap;
+	for (i = 0; i < host_set->n_ports; i++) {
+		struct ata_port *ap = host_set->ports[i];
 		u32 scontrol;
 		int rc;
 
-		ap = host_set->ports[i];
-
 		/* init sata_spd_limit to the current value */
 		if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
 			int spd = (scontrol >> 4) & 0xf;
@@ -5497,7 +5491,7 @@ int ata_device_add(const struct ata_prob
 
 	/* probes are done, now scan each port's disk(s) */
 	DPRINTK("host probe begin\n");
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < host_set->n_ports; i++) {
 		struct ata_port *ap = host_set->ports[i];
 
 		ata_scsi_scan_host(ap);
@@ -5509,14 +5503,14 @@ int ata_device_add(const struct ata_prob
 	return ent->n_ports; /* success */
 
 err_out:
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < host_set->n_ports; i++) {
 		struct ata_port *ap = host_set->ports[i];
 		if (ap) {
 			ap->ops->port_stop(ap);
 			scsi_host_put(ap->host);
 		}
 	}
-err_free_ret:
+
 	kfree(host_set);
 	VPRINTK("EXIT, returning 0\n");
 	return 0;
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 5/9] libata: fix several bugs in reworked legacy handling
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
  2006-08-04 21:01 ` [PATCH 1/9] [libata] some function renaming Tejun Heo
  2006-08-04 21:01 ` [PATCH 3/9] libata: implement per-dev xfermask Tejun Heo
@ 2006-08-04 21:01 ` Tejun Heo
  2006-08-09  4:28   ` Jeff Garzik
  2006-08-04 21:01 ` [PATCH 6/9] libata: implement dummy port Tejun Heo
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, alan, davej, linux-ide; +Cc: Tejun Heo

This patch fixes the following bugs from reworked legacy handling.

* In ata_pci_init_legacy_port(), probe_num was incorrectly incremented
  during initialization of the secondary port and probe_ent->n_ports
  was incorrectly fixed to 1.

* Both legacy ports ended up having the same hard_port_no.

* When printing port information, both legacy ports printed the first
  irq.

Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/libata-bmdma.c |    5 +++--
 drivers/scsi/libata-core.c  |   14 ++++++++------
 2 files changed, 11 insertions(+), 8 deletions(-)

69cc948426e05f43ea99d1b5f5f65c57dc395834
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index 34343e5..d43dc9a 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -905,7 +905,6 @@ static struct ata_probe_ent *ata_pci_ini
 		return NULL;
 
 	probe_ent->legacy_mode = 1;
-	probe_ent->n_ports = 1;
 	probe_ent->hard_port_no = 0;
 	probe_ent->private_data = port[0]->private_data;
 
@@ -933,7 +932,6 @@ static struct ata_probe_ent *ata_pci_ini
 		probe_ent->port[port_num].cmd_addr = ATA_SECONDARY_CMD;
 		probe_ent->port[port_num].altstatus_addr =
 		probe_ent->port[port_num].ctl_addr = ATA_SECONDARY_CTL;
-		port_num ++;
 		if (bmdma) {
 			probe_ent->port[port_num].bmdma_addr = bmdma + 8;
 			if (inb(bmdma + 10) & 0x80)
@@ -942,6 +940,9 @@ static struct ata_probe_ent *ata_pci_ini
 		ata_std_ports(&probe_ent->port[port_num]);
 		port_num ++;
 	}
+
+	probe_ent->n_ports = port_num;
+
 	return probe_ent;
 }
 
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 16134d5..01eae98 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5244,8 +5244,9 @@ static void ata_port_init(struct ata_por
 	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;
+	ap->hard_port_no = port_no;
+	if (ent->legacy_mode)
+		ap->hard_port_no += ent->hard_port_no;
 	ap->pio_mask = ent->pio_mask;
 	ap->mwdma_mask = ent->mwdma_mask;
 	ap->udma_mask = ent->udma_mask;
@@ -5404,16 +5405,15 @@ int ata_device_add(const struct ata_prob
 				(ap->mwdma_mask << ATA_SHIFT_MWDMA) |
 				(ap->pio_mask << ATA_SHIFT_PIO);
 
-		/* FIXME: maybe print both IRQ lines ? */
 		/* print per-port info to dmesg */
 		ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX "
-				"ctl 0x%lX bmdma 0x%lX irq %lu\n",
+				"ctl 0x%lX bmdma 0x%lX irq %d\n",
 				ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
 				ata_mode_string(xfer_mode_mask),
 				ap->ioaddr.cmd_addr,
 				ap->ioaddr.ctl_addr,
 				ap->ioaddr.bmdma_addr,
-				ent->irq);
+				irq_line);
 
 		ata_chk_status(ap);
 		host_set->ops->irq_clear(ap);
@@ -5440,7 +5440,7 @@ int ata_device_add(const struct ata_prob
 		if (rc) {
 			dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
 				   ent->irq2, rc);
-			goto err_out;
+			goto err_out_free_irq;
 		}
 	}
 
@@ -5517,6 +5517,8 @@ int ata_device_add(const struct ata_prob
 	VPRINTK("EXIT, returning %u\n", ent->n_ports);
 	return ent->n_ports; /* success */
 
+err_out_free_irq:
+	free_irq(ent->irq, host_set);
 err_out:
 	for (i = 0; i < host_set->n_ports; i++) {
 		struct ata_port *ap = host_set->ports[i];
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/9] libata: rework legacy handling to remove much of the cruft
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
                   ` (5 preceding siblings ...)
  2006-08-04 21:01 ` [PATCH 7/9] libata: use dummy port for stolen legacy ports Tejun Heo
@ 2006-08-04 21:01 ` Tejun Heo
  2006-08-09  4:27   ` Jeff Garzik
  2006-08-04 21:01 ` [PATCH 8/9] libata: replace ap->hard_port_no with ap->port_no Tejun Heo
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, davej, linux-ide; +Cc: Alan Cox, Alan Cox, Andrew Morton, Tejun Heo

Kill host_set->next
Fix simplex support
Allow per platform setting of IDE legacy bases

Some of this can be tidied further later on, in particular all the
legacy port gunge belongs as a PCI quirk/PCI header decode to understand
the special legacy IDE rules in the PCI spec.

Longer term Jeff also wants to move the request_irq/free_irq out of core
which will make this even cleaner.

(tj: folded in two followup patches - ata_piix fix & broken arch fix -
as compilation fails without those, and separated per-dev xfermask
into separate patch)

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/ata_piix.c              |    2 -
 drivers/scsi/libata-bmdma.c          |  136 ++++++++++++++++------------------
 drivers/scsi/libata-core.c           |   49 ++++++++----
 include/asm-alpha/libata-portmap.h   |    1 
 include/asm-generic/libata-portmap.h |   12 +++
 include/asm-i386/libata-portmap.h    |    1 
 include/asm-ia64/libata-portmap.h    |    1 
 include/asm-powerpc/libata-portmap.h |    1 
 include/asm-sparc/libata-portmap.h   |    1 
 include/asm-sparc64/libata-portmap.h |    1 
 include/asm-x86_64/libata-portmap.h  |    1 
 include/linux/libata.h               |    5 +
 12 files changed, 117 insertions(+), 94 deletions(-)
 create mode 100644 include/asm-alpha/libata-portmap.h
 create mode 100644 include/asm-generic/libata-portmap.h
 create mode 100644 include/asm-i386/libata-portmap.h
 create mode 100644 include/asm-ia64/libata-portmap.h
 create mode 100644 include/asm-powerpc/libata-portmap.h
 create mode 100644 include/asm-sparc/libata-portmap.h
 create mode 100644 include/asm-sparc64/libata-portmap.h
 create mode 100644 include/asm-x86_64/libata-portmap.h

05ffc173480e285e3414f49c4279fa90fda31cad
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 298e464..dfdf4a7 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -932,8 +932,6 @@ static int piix_init_one (struct pci_dev
 
 static void piix_host_stop(struct ata_host_set *host_set)
 {
-	if (host_set->next == NULL)
-		kfree(host_set->private_data);
 	ata_host_stop(host_set);
 }
 
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index 9ce221f..34343e5 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -880,7 +880,7 @@ ata_pci_init_native_mode(struct pci_dev 
 		if (bmdma) {
 			bmdma += 8;
 			if(inb(bmdma + 2) & 0x80)
-			probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+				probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
 			probe_ent->port[p].bmdma_addr = bmdma;
 		}
 		ata_std_ports(&probe_ent->port[p]);
@@ -893,45 +893,55 @@ ata_pci_init_native_mode(struct pci_dev 
 
 
 static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
-				struct ata_port_info *port, int port_num)
+				struct ata_port_info **port, int port_mask)
 {
 	struct ata_probe_ent *probe_ent;
-	unsigned long bmdma;
+	unsigned long bmdma = pci_resource_start(pdev, 4);
+
+	int port_num = 0;
 
-	probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
+	probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
 	if (!probe_ent)
 		return NULL;
 
 	probe_ent->legacy_mode = 1;
 	probe_ent->n_ports = 1;
-	probe_ent->hard_port_no = port_num;
-	probe_ent->private_data = port->private_data;
-
-	switch(port_num)
-	{
-		case 0:
-			probe_ent->irq = 14;
-			probe_ent->port[0].cmd_addr = 0x1f0;
-			probe_ent->port[0].altstatus_addr =
-			probe_ent->port[0].ctl_addr = 0x3f6;
-			break;
-		case 1:
-			probe_ent->irq = 15;
-			probe_ent->port[0].cmd_addr = 0x170;
-			probe_ent->port[0].altstatus_addr =
-			probe_ent->port[0].ctl_addr = 0x376;
-			break;
-	}
+	probe_ent->hard_port_no = 0;
+	probe_ent->private_data = port[0]->private_data;
 
-	bmdma = pci_resource_start(pdev, 4);
-	if (bmdma != 0) {
-		bmdma += 8 * port_num;
-		probe_ent->port[0].bmdma_addr = bmdma;
-		if (inb(bmdma + 2) & 0x80)
-			probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+	if (port_mask & ATA_PORT_PRIMARY) {
+		probe_ent->irq = 14;
+		probe_ent->port[port_num].cmd_addr = ATA_PRIMARY_CMD;
+		probe_ent->port[port_num].altstatus_addr =
+		probe_ent->port[port_num].ctl_addr = ATA_PRIMARY_CTL;
+		if (bmdma) {
+			probe_ent->port[0].bmdma_addr = bmdma;
+			if (inb(bmdma + 2) & 0x80)
+				probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+		}
+		ata_std_ports(&probe_ent->port[port_num]);
+		port_num ++;
+	}
+	if (port_mask & ATA_PORT_SECONDARY) {
+		if (port_num == 1)
+			probe_ent->irq2 = 15;
+		else {
+			/* Secondary only. IRQ 15 only and "first" port is port 1 */
+			probe_ent->irq = 15;
+			probe_ent->hard_port_no = 1;
+		}
+		probe_ent->port[port_num].cmd_addr = ATA_SECONDARY_CMD;
+		probe_ent->port[port_num].altstatus_addr =
+		probe_ent->port[port_num].ctl_addr = ATA_SECONDARY_CTL;
+		port_num ++;
+		if (bmdma) {
+			probe_ent->port[port_num].bmdma_addr = bmdma + 8;
+			if (inb(bmdma + 10) & 0x80)
+				probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+		}
+		ata_std_ports(&probe_ent->port[port_num]);
+		port_num ++;
 	}
-	ata_std_ports(&probe_ent->port[0]);
-
 	return probe_ent;
 }
 
@@ -950,6 +960,10 @@ static struct ata_probe_ent *ata_pci_ini
  *	regions, sets the dma mask, enables bus master mode, and calls
  *	ata_device_add()
  *
+ *	ASSUMPTION:
+ *	Nobody makes a single channel controller that appears solely as
+ *	the secondary legacy port on PCI.
+ *
  *	LOCKING:
  *	Inherited from PCI layer (may sleep).
  *
@@ -960,7 +974,7 @@ static struct ata_probe_ent *ata_pci_ini
 int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 		      unsigned int n_ports)
 {
-	struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
+	struct ata_probe_ent *probe_ent = NULL;
 	struct ata_port_info *port[2];
 	u8 tmp8, mask;
 	unsigned int legacy_mode = 0;
@@ -1009,35 +1023,34 @@ int ata_pci_init_one (struct pci_dev *pd
 		goto err_out;
 	}
 
-	/* FIXME: Should use platform specific mappers for legacy port ranges */
 	if (legacy_mode) {
-		if (!request_region(0x1f0, 8, "libata")) {
+		if (!request_region(ATA_PRIMARY_CMD, 8, "libata")) {
 			struct resource *conflict, res;
-			res.start = 0x1f0;
-			res.end = 0x1f0 + 8 - 1;
+			res.start = ATA_PRIMARY_CMD;
+			res.end = ATA_PRIMARY_CMD + 8 - 1;
 			conflict = ____request_resource(&ioport_resource, &res);
 			if (!strcmp(conflict->name, "libata"))
-				legacy_mode |= (1 << 0);
+				legacy_mode |= ATA_PORT_PRIMARY;
 			else {
 				disable_dev_on_err = 0;
-				printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
+				printk(KERN_WARNING "ata: 0x%0X IDE port busy\n", ATA_PRIMARY_CMD);
 			}
 		} else
-			legacy_mode |= (1 << 0);
+			legacy_mode |= ATA_PORT_PRIMARY;
 
-		if (!request_region(0x170, 8, "libata")) {
+		if (!request_region(ATA_SECONDARY_CMD, 8, "libata")) {
 			struct resource *conflict, res;
-			res.start = 0x170;
-			res.end = 0x170 + 8 - 1;
+			res.start = ATA_SECONDARY_CMD;
+			res.end = ATA_SECONDARY_CMD + 8 - 1;
 			conflict = ____request_resource(&ioport_resource, &res);
 			if (!strcmp(conflict->name, "libata"))
-				legacy_mode |= (1 << 1);
+				legacy_mode |= ATA_PORT_SECONDARY;
 			else {
 				disable_dev_on_err = 0;
-				printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
+				printk(KERN_WARNING "ata: 0x%X IDE port busy\n", ATA_SECONDARY_CMD);
 			}
 		} else
-			legacy_mode |= (1 << 1);
+			legacy_mode |= ATA_PORT_SECONDARY;
 	}
 
 	/* we have legacy mode, but all ports are unavailable */
@@ -1055,17 +1068,14 @@ int ata_pci_init_one (struct pci_dev *pd
 		goto err_out_regions;
 
 	if (legacy_mode) {
-		if (legacy_mode & (1 << 0))
-			probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
-		if (legacy_mode & (1 << 1))
-			probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
+		probe_ent = ata_pci_init_legacy_port(pdev, port, legacy_mode);
 	} else {
 		if (n_ports == 2)
 			probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 		else
 			probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
 	}
-	if (!probe_ent && !probe_ent2) {
+	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
@@ -1073,35 +1083,17 @@ int ata_pci_init_one (struct pci_dev *pd
 	pci_set_master(pdev);
 
 	/* FIXME: check ata_device_add return */
-	if (legacy_mode) {
-		struct device *dev = &pdev->dev;
-		struct ata_host_set *host_set = NULL;
-
-		if (legacy_mode & (1 << 0)) {
-			ata_device_add(probe_ent);
-			host_set = dev_get_drvdata(dev);
-		}
-
-		if (legacy_mode & (1 << 1)) {
-			ata_device_add(probe_ent2);
-			if (host_set) {
-				host_set->next = dev_get_drvdata(dev);
-				dev_set_drvdata(dev, host_set);
-			}
-		}
-	} else
-		ata_device_add(probe_ent);
+	ata_device_add(probe_ent);
 
 	kfree(probe_ent);
-	kfree(probe_ent2);
 
 	return 0;
 
 err_out_regions:
-	if (legacy_mode & (1 << 0))
-		release_region(0x1f0, 8);
-	if (legacy_mode & (1 << 1))
-		release_region(0x170, 8);
+	if (legacy_mode & ATA_PORT_PRIMARY)
+		release_region(ATA_PRIMARY_CMD, 8);
+	if (legacy_mode & ATA_PORT_SECONDARY)
+		release_region(ATA_SECONDARY_CMD, 8);
 	pci_release_regions(pdev);
 err_out:
 	if (disable_dev_on_err)
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 7e1f3ee..16134d5 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5379,6 +5379,7 @@ int ata_device_add(const struct ata_prob
 	host_set->dev = dev;
 	host_set->n_ports = ent->n_ports;
 	host_set->irq = ent->irq;
+	host_set->irq2 = ent->irq2;
 	host_set->mmio_base = ent->mmio_base;
 	host_set->private_data = ent->private_data;
 	host_set->ops = ent->port_ops;
@@ -5388,16 +5389,22 @@ int ata_device_add(const struct ata_prob
 	for (i = 0; i < host_set->n_ports; i++) {
 		struct ata_port *ap;
 		unsigned long xfer_mode_mask;
+		int irq_line = ent->irq;
 
 		ap = ata_port_add(ent, host_set, i);
 		if (!ap)
 			goto err_out;
 
+		/* Report the secondary IRQ for second channel legacy */
+		if (i == 1 && ent->irq2)
+			irq_line = ent->irq2;
+
 		host_set->ports[i] = ap;
 		xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
 				(ap->mwdma_mask << ATA_SHIFT_MWDMA) |
 				(ap->pio_mask << ATA_SHIFT_PIO);
 
+		/* FIXME: maybe print both IRQ lines ? */
 		/* print per-port info to dmesg */
 		ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX "
 				"ctl 0x%lX bmdma 0x%lX irq %lu\n",
@@ -5413,7 +5420,7 @@ int ata_device_add(const struct ata_prob
 		ata_eh_freeze_port(ap);	/* freeze port before requesting IRQ */
 	}
 
-	/* obtain irq, that is shared between channels */
+	/* obtain irq, that may be shared between channels */
 	rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
 			 DRV_NAME, host_set);
 	if (rc) {
@@ -5422,6 +5429,21 @@ int ata_device_add(const struct ata_prob
 		goto err_out;
 	}
 
+	/* do we have a second IRQ for the other channel, eg legacy mode */
+	if (ent->irq2) {
+		/* We will get weird core code crashes later if this is true
+		   so trap it now */
+		BUG_ON(ent->irq == ent->irq2);
+
+		rc = request_irq(ent->irq2, ent->port_ops->irq_handler, ent->irq_flags,
+			 DRV_NAME, host_set);
+		if (rc) {
+			dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
+				   ent->irq2, rc);
+			goto err_out;
+		}
+	}
+
 	/* perform each probe synchronously */
 	DPRINTK("probe begin\n");
 	for (i = 0; i < host_set->n_ports; i++) {
@@ -5586,6 +5608,8 @@ void ata_host_set_remove(struct ata_host
 		ata_port_detach(host_set->ports[i]);
 
 	free_irq(host_set->irq, host_set);
+	if (host_set->irq2)
+		free_irq(host_set->irq2, host_set);
 
 	for (i = 0; i < host_set->n_ports; i++) {
 		struct ata_port *ap = host_set->ports[i];
@@ -5595,10 +5619,11 @@ void ata_host_set_remove(struct ata_host
 		if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
 			struct ata_ioports *ioaddr = &ap->ioaddr;
 
-			if (ioaddr->cmd_addr == 0x1f0)
-				release_region(0x1f0, 8);
-			else if (ioaddr->cmd_addr == 0x170)
-				release_region(0x170, 8);
+			/* FIXME: Add -ac IDE pci mods to remove these special cases */
+			if (ioaddr->cmd_addr == ATA_PRIMARY_CMD)
+				release_region(ATA_PRIMARY_CMD, 8);
+			else if (ioaddr->cmd_addr == ATA_SECONDARY_CMD)
+				release_region(ATA_SECONDARY_CMD, 8);
 		}
 
 		scsi_host_put(ap->host);
@@ -5691,11 +5716,8 @@ void ata_pci_remove_one (struct pci_dev 
 {
 	struct device *dev = pci_dev_to_dev(pdev);
 	struct ata_host_set *host_set = dev_get_drvdata(dev);
-	struct ata_host_set *host_set2 = host_set->next;
 
 	ata_host_set_remove(host_set);
-	if (host_set2)
-		ata_host_set_remove(host_set2);
 
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
@@ -5763,14 +5785,6 @@ int ata_pci_device_suspend(struct pci_de
 	if (rc)
 		return rc;
 
-	if (host_set->next) {
-		rc = ata_host_set_suspend(host_set->next, mesg);
-		if (rc) {
-			ata_host_set_resume(host_set);
-			return rc;
-		}
-	}
-
 	ata_pci_device_do_suspend(pdev, mesg);
 
 	return 0;
@@ -5782,9 +5796,6 @@ int ata_pci_device_resume(struct pci_dev
 
 	ata_pci_device_do_resume(pdev);
 	ata_host_set_resume(host_set);
-	if (host_set->next)
-		ata_host_set_resume(host_set->next);
-
 	return 0;
 }
 #endif /* CONFIG_PCI */
diff --git a/include/asm-alpha/libata-portmap.h b/include/asm-alpha/libata-portmap.h
new file mode 100644
index 0000000..75484ef
--- /dev/null
+++ b/include/asm-alpha/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-generic/libata-portmap.h b/include/asm-generic/libata-portmap.h
new file mode 100644
index 0000000..9202fd0
--- /dev/null
+++ b/include/asm-generic/libata-portmap.h
@@ -0,0 +1,12 @@
+#ifndef __ASM_GENERIC_LIBATA_PORTMAP_H
+#define __ASM_GENERIC_LIBATA_PORTMAP_H
+
+#define ATA_PRIMARY_CMD		0x1F0
+#define ATA_PRIMARY_CTL		0x3F6
+#define ATA_PRIMARY_IRQ		14
+
+#define ATA_SECONDARY_CMD	0x170
+#define ATA_SECONDARY_CTL	0x376
+#define ATA_SECONDARY_IRQ	15
+
+#endif
diff --git a/include/asm-i386/libata-portmap.h b/include/asm-i386/libata-portmap.h
new file mode 100644
index 0000000..75484ef
--- /dev/null
+++ b/include/asm-i386/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-ia64/libata-portmap.h b/include/asm-ia64/libata-portmap.h
new file mode 100644
index 0000000..75484ef
--- /dev/null
+++ b/include/asm-ia64/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-powerpc/libata-portmap.h b/include/asm-powerpc/libata-portmap.h
new file mode 100644
index 0000000..75484ef
--- /dev/null
+++ b/include/asm-powerpc/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-sparc/libata-portmap.h b/include/asm-sparc/libata-portmap.h
new file mode 100644
index 0000000..75484ef
--- /dev/null
+++ b/include/asm-sparc/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-sparc64/libata-portmap.h b/include/asm-sparc64/libata-portmap.h
new file mode 100644
index 0000000..75484ef
--- /dev/null
+++ b/include/asm-sparc64/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-x86_64/libata-portmap.h b/include/asm-x86_64/libata-portmap.h
new file mode 100644
index 0000000..75484ef
--- /dev/null
+++ b/include/asm-x86_64/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b941670..9a94778 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -36,6 +36,8 @@ #include <linux/ata.h>
 #include <linux/workqueue.h>
 #include <scsi/scsi_host.h>
 
+#include <asm/libata-portmap.h>
+
 /*
  * compile-time options: to be removed as soon as all the drivers are
  * converted to the new debugging mechanism
@@ -356,6 +358,7 @@ struct ata_probe_ent {
 	unsigned int		udma_mask;
 	unsigned int		legacy_mode;
 	unsigned long		irq;
+	unsigned long		irq2;
 	unsigned int		irq_flags;
 	unsigned long		host_flags;
 	unsigned long		host_set_flags;
@@ -367,6 +370,7 @@ struct ata_host_set {
 	spinlock_t		lock;
 	struct device 		*dev;
 	unsigned long		irq;
+	unsigned long		irq2;
 	void __iomem		*mmio_base;
 	unsigned int		n_ports;
 	void			*private_data;
@@ -374,7 +378,6 @@ struct ata_host_set {
 	unsigned long		flags;
 	int			simplex_claimed;	/* Keep seperate in case we
 							   ever need to do this locked */
-	struct ata_host_set	*next;		/* for legacy mode */
 	struct ata_port		*ports[0];
 };
 
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 6/9] libata: implement dummy port
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
                   ` (2 preceding siblings ...)
  2006-08-04 21:01 ` [PATCH 5/9] libata: fix several bugs in reworked legacy handling Tejun Heo
@ 2006-08-04 21:01 ` Tejun Heo
  2006-08-04 21:01 ` [PATCH 2/9] [libata] Kill 'count' var in ata_device_add() Tejun Heo
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, alan, davej, linux-ide; +Cc: Tejun Heo

Implement dummy port which can be requested by setting appropriate bit
in probe_ent->dummy_port_mask.  The dummy port is used as placeholder
for stolen legacy port.  This allows libata to guarantee that
index_of(ap) == ap->port_no == actual_device_port_no, and thus to
remove error-prone ap->hard_port_no.

As it's used only when one port of a legacy controller is reserved by
some other entity (e.g. IDE), the focus is on keeping the added *code*
complexity at minimum, so dummy port allocates all libata core
resources and acts as a normal port.  It just has all dummy port_ops.

This patch only implements dummy port.  The following patch will make
libata use it for stolen legacy ports.

Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/libata-core.c |   61 +++++++++++++++++++++++++++++++++++++-------
 include/linux/libata.h     |    8 ++++++
 2 files changed, 59 insertions(+), 10 deletions(-)

8bbc9c7f4500990614966a75ab95a3b9a20412f8
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 01eae98..8818c84 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5312,7 +5312,6 @@ static struct ata_port * ata_port_add(co
 {
 	struct Scsi_Host *host;
 	struct ata_port *ap;
-	int rc;
 
 	DPRINTK("ENTER\n");
 
@@ -5333,15 +5332,7 @@ static struct ata_port * ata_port_add(co
 
 	ata_port_init(ap, host, host_set, ent, port_no);
 
-	rc = ap->ops->port_start(ap);
-	if (rc)
-		goto err_out;
-
 	return ap;
-
-err_out:
-	scsi_host_put(host);
-	return NULL;
 }
 
 /**
@@ -5396,11 +5387,27 @@ int ata_device_add(const struct ata_prob
 		if (!ap)
 			goto err_out;
 
+		host_set->ports[i] = ap;
+
+		/* dummy? */
+		if (ent->dummy_port_mask & (1 << i)) {
+			ata_port_printk(ap, KERN_INFO, "DUMMY\n");
+			ap->ops = &ata_dummy_port_ops;
+			continue;
+		}
+
+		/* start port */
+		rc = ap->ops->port_start(ap);
+		if (rc) {
+			host_set->ports[i] = NULL;
+			scsi_host_put(ap->host);
+			goto err_out;
+		}
+
 		/* Report the secondary IRQ for second channel legacy */
 		if (i == 1 && ent->irq2)
 			irq_line = ent->irq2;
 
-		host_set->ports[i] = ap;
 		xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
 				(ap->mwdma_mask << ATA_SHIFT_MWDMA) |
 				(ap->pio_mask << ATA_SHIFT_PIO);
@@ -5897,6 +5904,39 @@ u32 ata_wait_register(void __iomem *reg,
 }
 
 /*
+ * Dummy port_ops
+ */
+static void ata_dummy_noret(struct ata_port *ap)	{ }
+static int ata_dummy_ret0(struct ata_port *ap)		{ return 0; }
+static void ata_dummy_qc_noret(struct ata_queued_cmd *qc) { }
+
+static u8 ata_dummy_check_status(struct ata_port *ap)
+{
+	return ATA_DRDY;
+}
+
+static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
+{
+	return AC_ERR_SYSTEM;
+}
+
+const struct ata_port_operations ata_dummy_port_ops = {
+	.port_disable		= ata_port_disable,
+	.check_status		= ata_dummy_check_status,
+	.check_altstatus	= ata_dummy_check_status,
+	.dev_select		= ata_noop_dev_select,
+	.qc_prep		= ata_noop_qc_prep,
+	.qc_issue		= ata_dummy_qc_issue,
+	.freeze			= ata_dummy_noret,
+	.thaw			= ata_dummy_noret,
+	.error_handler		= ata_dummy_noret,
+	.post_internal_cmd	= ata_dummy_qc_noret,
+	.irq_clear		= ata_dummy_noret,
+	.port_start		= ata_dummy_ret0,
+	.port_stop		= ata_dummy_noret,
+};
+
+/*
  * libata is essentially a library of internal helper functions for
  * low-level ATA host controller drivers.  As such, the API/ABI is
  * likely to change as new drivers are added and updated.
@@ -5906,6 +5946,7 @@ u32 ata_wait_register(void __iomem *reg,
 EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
 EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
 EXPORT_SYMBOL_GPL(sata_deb_timing_long);
+EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
 EXPORT_SYMBOL_GPL(ata_std_bios_param);
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_device_add);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 9a94778..6a81aed 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -353,6 +353,7 @@ struct ata_probe_ent {
 	struct ata_ioports	port[ATA_MAX_PORTS];
 	unsigned int		n_ports;
 	unsigned int		hard_port_no;
+	unsigned int		dummy_port_mask;
 	unsigned int		pio_mask;
 	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
@@ -652,6 +653,8 @@ extern const unsigned long sata_deb_timi
 extern const unsigned long sata_deb_timing_hotplug[];
 extern const unsigned long sata_deb_timing_long[];
 
+extern const struct ata_port_operations ata_dummy_port_ops;
+
 static inline const unsigned long *
 sata_ehc_deb_timing(struct ata_eh_context *ehc)
 {
@@ -661,6 +664,11 @@ sata_ehc_deb_timing(struct ata_eh_contex
 		return sata_deb_timing_normal;
 }
 
+static inline int ata_port_is_dummy(struct ata_port *ap)
+{
+	return ap->ops == &ata_dummy_port_ops;
+}
+
 extern void ata_port_probe(struct ata_port *);
 extern void __sata_phy_reset(struct ata_port *ap);
 extern void sata_phy_reset(struct ata_port *ap);
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 9/9] libata: kill unused hard_port_no and legacy_mode
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
                   ` (7 preceding siblings ...)
  2006-08-04 21:01 ` [PATCH 8/9] libata: replace ap->hard_port_no with ap->port_no Tejun Heo
@ 2006-08-04 21:01 ` Tejun Heo
  2006-08-09  4:29   ` Jeff Garzik
  2006-08-04 21:05 ` [PATCHSET] libata: improve initialization and legacy handling, take#2 Dave Jones
  9 siblings, 1 reply; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, alan, davej, linux-ide; +Cc: Tejun Heo

Kill unused probe_ent/ap->hard_port_no and probe_ent->legacy_mode.

Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/libata-core.c |    1 -
 include/linux/libata.h     |    3 ---
 2 files changed, 0 insertions(+), 4 deletions(-)

2c79fd77ad0e0a6e0b3655411684a4c1009f41c9
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 453dce0..9578b42 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5244,7 +5244,6 @@ static void ata_port_init(struct ata_por
 	ap->host_set = host_set;
 	ap->dev = ent->dev;
 	ap->port_no = port_no;
-	ap->hard_port_no = port_no;
 	ap->pio_mask = ent->pio_mask;
 	ap->mwdma_mask = ent->mwdma_mask;
 	ap->udma_mask = ent->udma_mask;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 6a81aed..1b6283c 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -352,12 +352,10 @@ struct ata_probe_ent {
 	struct scsi_host_template *sht;
 	struct ata_ioports	port[ATA_MAX_PORTS];
 	unsigned int		n_ports;
-	unsigned int		hard_port_no;
 	unsigned int		dummy_port_mask;
 	unsigned int		pio_mask;
 	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
-	unsigned int		legacy_mode;
 	unsigned long		irq;
 	unsigned long		irq2;
 	unsigned int		irq_flags;
@@ -509,7 +507,6 @@ struct ata_port {
 	unsigned int		pflags; /* ATA_PFLAG_xxx */
 	unsigned int		id;	/* unique id req'd by scsi midlyr */
 	unsigned int		port_no; /* unique port #; from zero */
-	unsigned int		hard_port_no;	/* hardware port #; from zero */
 
 	struct ata_prd		*prd;	 /* our SG list */
 	dma_addr_t		prd_dma; /* and its DMA mapping */
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 8/9] libata: replace ap->hard_port_no with ap->port_no
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
                   ` (6 preceding siblings ...)
  2006-08-04 21:01 ` [PATCH 4/9] libata: rework legacy handling to remove much of the cruft Tejun Heo
@ 2006-08-04 21:01 ` Tejun Heo
  2006-08-04 21:01 ` [PATCH 9/9] libata: kill unused hard_port_no and legacy_mode Tejun Heo
  2006-08-04 21:05 ` [PATCHSET] libata: improve initialization and legacy handling, take#2 Dave Jones
  9 siblings, 0 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:01 UTC (permalink / raw)
  To: jgarzik, alan, davej, linux-ide; +Cc: Tejun Heo

Replace ap->hard_port_no with ap->port_no.

Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/ata_piix.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

0a77da170fa203e495b08fd92ef488a51578a93c
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index dfdf4a7..99ed16c 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -487,7 +487,7 @@ static void piix_pata_cbl_detect(struct 
 		goto cbl40;
 
 	/* check BIOS cable detect results */
-	mask = ap->hard_port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
+	mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
 	pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
 	if ((tmp & mask) == 0)
 		goto cbl40;
@@ -513,7 +513,7 @@ static int piix_pata_prereset(struct ata
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
 
-	if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
+	if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) {
 		ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
 		ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
 		return 0;
@@ -550,7 +550,7 @@ static int piix_sata_prereset(struct ata
 	struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
 	struct piix_host_priv *hpriv = ap->host_set->private_data;
 	const unsigned int *map = hpriv->map;
-	int base = 2 * ap->hard_port_no;
+	int base = 2 * ap->port_no;
 	unsigned int present = 0;
 	int port, i;
 	u16 pcs;
@@ -601,7 +601,7 @@ static void piix_set_piomode (struct ata
 	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= to_pci_dev(ap->host_set->dev);
 	unsigned int is_slave	= (adev->devno != 0);
-	unsigned int master_port= ap->hard_port_no ? 0x42 : 0x40;
+	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
 	unsigned int slave_port	= 0x44;
 	u16 master_data;
 	u8 slave_data;
@@ -619,10 +619,10 @@ static void piix_set_piomode (struct ata
 		/* enable PPE, IE and TIME */
 		master_data |= 0x0070;
 		pci_read_config_byte(dev, slave_port, &slave_data);
-		slave_data &= (ap->hard_port_no ? 0x0f : 0xf0);
+		slave_data &= (ap->port_no ? 0x0f : 0xf0);
 		slave_data |=
 			(timings[pio][0] << 2) |
-			(timings[pio][1] << (ap->hard_port_no ? 4 : 0));
+			(timings[pio][1] << (ap->port_no ? 4 : 0));
 	} else {
 		master_data &= 0xccf8;
 		/* enable PPE, IE and TIME */
@@ -652,9 +652,9 @@ static void piix_set_dmamode (struct ata
 {
 	unsigned int udma	= adev->dma_mode; /* FIXME: MWDMA too */
 	struct pci_dev *dev	= to_pci_dev(ap->host_set->dev);
-	u8 maslave		= ap->hard_port_no ? 0x42 : 0x40;
+	u8 maslave		= ap->port_no ? 0x42 : 0x40;
 	u8 speed		= udma;
-	unsigned int drive_dn	= (ap->hard_port_no ? 2 : 0) + adev->devno;
+	unsigned int drive_dn	= (ap->port_no ? 2 : 0) + adev->devno;
 	int a_speed		= 3 << (drive_dn * 4);
 	int u_flag		= 1 << drive_dn;
 	int v_flag		= 0x01 << drive_dn;
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCHSET] libata: improve initialization and legacy handling, take#2
  2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
                   ` (8 preceding siblings ...)
  2006-08-04 21:01 ` [PATCH 9/9] libata: kill unused hard_port_no and legacy_mode Tejun Heo
@ 2006-08-04 21:05 ` Dave Jones
  2006-08-04 21:13   ` Tejun Heo
  9 siblings, 1 reply; 23+ messages in thread
From: Dave Jones @ 2006-08-04 21:05 UTC (permalink / raw)
  To: Tejun Heo; +Cc: jgarzik, alan, linux-ide

On Sat, Aug 05, 2006 at 06:01:32AM +0900, Tejun Heo wrote:
 > Hello, all.
 > 
 > This is the second take of improve-init-and-legacy patchset.  This
 > patchset contains patches from Jeff Garzik, Alan Cox, Dave Jones and
 > me to fix/clean up initializaton and legacy handling.

It does ?  I don't recall writing any of these :)

		Dave

-- 
http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCHSET] libata: improve initialization and legacy handling, take#2
  2006-08-04 21:05 ` [PATCHSET] libata: improve initialization and legacy handling, take#2 Dave Jones
@ 2006-08-04 21:13   ` Tejun Heo
  0 siblings, 0 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-04 21:13 UTC (permalink / raw)
  To: Dave Jones; +Cc: jgarzik, alan, linux-ide

Dave Jones wrote:
> On Sat, Aug 05, 2006 at 06:01:32AM +0900, Tejun Heo wrote:
>  > Hello, all.
>  > 
>  > This is the second take of improve-init-and-legacy patchset.  This
>  > patchset contains patches from Jeff Garzik, Alan Cox, Dave Jones and
>  > me to fix/clean up initializaton and legacy handling.
> 
> It does ?  I don't recall writing any of these :)

Oh.. that credit is for the following patch.

====
http://thread.gmane.org/gmane.linux.ide/12393/focus=12395

[PATCH 5/5] libata: fix ata_device_add() error path

* dereferences null host_set->ports[] element.
* calls scsi_remove_host() on not-yet-added shost.

This patch fixes both bugs.  The first problem was spotted and initial
patch submitted by Dave Jones <davej <at> redhat.com>.  The second 
problem was mentioned and fixed by Jeff Garzik <jgarzik <at> pobox.com> 
in a larger cleanup patch.
====

The patch got moved to another patchset but I forgot to move that part 
from head message.  Free credit! :)

-- 
tejun

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/9] libata: implement per-dev xfermask
  2006-08-04 21:01 ` [PATCH 3/9] libata: implement per-dev xfermask Tejun Heo
@ 2006-08-05 13:38   ` Alan Cox
  2006-08-06 14:41     ` Tejun Heo
  2006-08-09  4:30   ` Jeff Garzik
  1 sibling, 1 reply; 23+ messages in thread
From: Alan Cox @ 2006-08-05 13:38 UTC (permalink / raw)
  To: Tejun Heo; +Cc: jgarzik, davej, linux-ide

Ar Sad, 2006-08-05 am 06:01 +0900, ysgrifennodd Tejun Heo:
> +	/* Use the lowest common PIO mode to avoid violating device
> +	 * selection timing.
> +	 */
> +	for (i = 0; i < ATA_MAX_DEVICES; i++) {
> +		struct ata_device *d = &ap->device[i];
> +		if (!ata_dev_absent(d))
> +			xfer_mask &= ata_pack_xfermask(d->pio_mask,
> +						       UINT_MAX, UINT_MAX);
>  	}

We should not do this. Many of the controllers are smart enough to get
it right and those which do not implement this logic internally and
correctly by merging the relevant fields in the ata timing structure.

Alan


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/9] libata: implement per-dev xfermask
  2006-08-05 13:38   ` Alan Cox
@ 2006-08-06 14:41     ` Tejun Heo
  2006-08-06 15:56       ` Alan Cox
  0 siblings, 1 reply; 23+ messages in thread
From: Tejun Heo @ 2006-08-06 14:41 UTC (permalink / raw)
  To: Alan Cox; +Cc: jgarzik, davej, linux-ide, Mark Lord

Alan Cox wrote:
> Ar Sad, 2006-08-05 am 06:01 +0900, ysgrifennodd Tejun Heo:
>> +	/* Use the lowest common PIO mode to avoid violating device
>> +	 * selection timing.
>> +	 */
>> +	for (i = 0; i < ATA_MAX_DEVICES; i++) {
>> +		struct ata_device *d = &ap->device[i];
>> +		if (!ata_dev_absent(d))
>> +			xfer_mask &= ata_pack_xfermask(d->pio_mask,
>> +						       UINT_MAX, UINT_MAX);
>>  	}
> 
> We should not do this. Many of the controllers are smart enough to get
> it right and those which do not implement this logic internally and
> correctly by merging the relevant fields in the ata timing structure.

[Cc'ing Mark Lord for upstream PATA drivers]

I see.  I have a question though.  ATM, there are a few drives in the 
current #upstream which deal with PATA devices (ata_piix, pdc_adma and 
sata_promise).  Will they all act correctly without the above logic?  If 
so, I'll drop the above part and regenerate the tree.  If not, it can 
stay till those drivers are patched.

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/9] libata: implement per-dev xfermask
  2006-08-06 14:41     ` Tejun Heo
@ 2006-08-06 15:56       ` Alan Cox
  2006-08-06 16:08         ` Tejun Heo
  0 siblings, 1 reply; 23+ messages in thread
From: Alan Cox @ 2006-08-06 15:56 UTC (permalink / raw)
  To: Tejun Heo; +Cc: jgarzik, davej, linux-ide, Mark Lord

Ar Sul, 2006-08-06 am 23:41 +0900, ysgrifennodd Tejun Heo:
> I see.  I have a question though.  ATM, there are a few drives in the 
> current #upstream which deal with PATA devices (ata_piix, pdc_adma and 
> sata_promise).  Will they all act correctly without the above logic?  If 
> so, I'll drop the above part and regenerate the tree.  If not, it can 
> stay till those drivers are patched.

I went through them checking earlier. The majority of chipsets snoop the
drive select bit and will generate appropriate cycles by device
according to that bit.  Not everything does but I have been through and
made sure the ones that don't correctly merge timings. At least I hope I
have them all anyway.



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/9] libata: implement per-dev xfermask
  2006-08-06 15:56       ` Alan Cox
@ 2006-08-06 16:08         ` Tejun Heo
  0 siblings, 0 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-06 16:08 UTC (permalink / raw)
  To: Alan Cox; +Cc: jgarzik, davej, linux-ide, Mark Lord

Alan Cox wrote:
> Ar Sul, 2006-08-06 am 23:41 +0900, ysgrifennodd Tejun Heo:
>> I see.  I have a question though.  ATM, there are a few drives in the 
>> current #upstream which deal with PATA devices (ata_piix, pdc_adma and 
>> sata_promise).  Will they all act correctly without the above logic?  If 
>> so, I'll drop the above part and regenerate the tree.  If not, it can 
>> stay till those drivers are patched.
> 
> I went through them checking earlier. The majority of chipsets snoop the
> drive select bit and will generate appropriate cycles by device
> according to that bit.  Not everything does but I have been through and
> made sure the ones that don't correctly merge timings. At least I hope I
> have them all anyway.

I'm sure you've got them all correct in #pata-drivers :) but what I was 
worried about was whether the drivers in libata-dev#upstream are ready 
because, if not, those timing merge bits should be merged into #upstream 
first.  Hmmm... Diffing pata-drivers and upstream... Only ata_piix has 
set_piomode() update in #pata-drivers.  Can you please check whether 
ata_piix in #upstream will be safe?

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9] [libata] some function renaming
  2006-08-04 21:01 ` [PATCH 1/9] [libata] some function renaming Tejun Heo
@ 2006-08-09  4:24   ` Jeff Garzik
  2006-08-09  4:25   ` Jeff Garzik
  1 sibling, 0 replies; 23+ messages in thread
From: Jeff Garzik @ 2006-08-09  4:24 UTC (permalink / raw)
  To: Tejun Heo; +Cc: jgarzik, alan, davej, linux-ide

Unfortunately Brian King's SAS patches (now in #upstream) conflict with 
this.  Just FYI.

Will continue ACK/NAK review regardless.

	Jeff




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9] [libata] some function renaming
  2006-08-04 21:01 ` [PATCH 1/9] [libata] some function renaming Tejun Heo
  2006-08-09  4:24   ` Jeff Garzik
@ 2006-08-09  4:25   ` Jeff Garzik
  1 sibling, 0 replies; 23+ messages in thread
From: Jeff Garzik @ 2006-08-09  4:25 UTC (permalink / raw)
  To: Tejun Heo; +Cc: jgarzik, alan, davej, linux-ide

ACK patches 1-2


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 4/9] libata: rework legacy handling to remove much of the cruft
  2006-08-04 21:01 ` [PATCH 4/9] libata: rework legacy handling to remove much of the cruft Tejun Heo
@ 2006-08-09  4:27   ` Jeff Garzik
  0 siblings, 0 replies; 23+ messages in thread
From: Jeff Garzik @ 2006-08-09  4:27 UTC (permalink / raw)
  To: Tejun Heo; +Cc: alan, davej, linux-ide, Alan Cox, Andrew Morton

Tejun Heo wrote:
> Kill host_set->next
> Fix simplex support
> Allow per platform setting of IDE legacy bases
> 
> Some of this can be tidied further later on, in particular all the
> legacy port gunge belongs as a PCI quirk/PCI header decode to understand
> the special legacy IDE rules in the PCI spec.
> 
> Longer term Jeff also wants to move the request_irq/free_irq out of core
> which will make this even cleaner.
> 
> (tj: folded in two followup patches - ata_piix fix & broken arch fix -
> as compilation fails without those, and separated per-dev xfermask
> into separate patch)
> 
> Signed-off-by: Alan Cox <alan@redhat.com>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
> Signed-off-by: Tejun Heo <htejun@gmail.com>

ACK



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/9] libata: fix several bugs in reworked legacy handling
  2006-08-04 21:01 ` [PATCH 5/9] libata: fix several bugs in reworked legacy handling Tejun Heo
@ 2006-08-09  4:28   ` Jeff Garzik
  0 siblings, 0 replies; 23+ messages in thread
From: Jeff Garzik @ 2006-08-09  4:28 UTC (permalink / raw)
  To: Tejun Heo; +Cc: alan, davej, linux-ide

Tejun Heo wrote:
> This patch fixes the following bugs from reworked legacy handling.
> 
> * In ata_pci_init_legacy_port(), probe_num was incorrectly incremented
>   during initialization of the secondary port and probe_ent->n_ports
>   was incorrectly fixed to 1.
> 
> * Both legacy ports ended up having the same hard_port_no.
> 
> * When printing port information, both legacy ports printed the first
>   irq.
> 
> Signed-off-by: Tejun Heo <htejun@gmail.com>

ACK, though it would be better for 'git bisect' if this was merged into 
the previous patch (#4).



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 9/9] libata: kill unused hard_port_no and legacy_mode
  2006-08-04 21:01 ` [PATCH 9/9] libata: kill unused hard_port_no and legacy_mode Tejun Heo
@ 2006-08-09  4:29   ` Jeff Garzik
  0 siblings, 0 replies; 23+ messages in thread
From: Jeff Garzik @ 2006-08-09  4:29 UTC (permalink / raw)
  To: Tejun Heo; +Cc: alan, davej, linux-ide

ACK patches 6-9


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/9] libata: implement per-dev xfermask
  2006-08-04 21:01 ` [PATCH 3/9] libata: implement per-dev xfermask Tejun Heo
  2006-08-05 13:38   ` Alan Cox
@ 2006-08-09  4:30   ` Jeff Garzik
  1 sibling, 0 replies; 23+ messages in thread
From: Jeff Garzik @ 2006-08-09  4:30 UTC (permalink / raw)
  To: Tejun Heo; +Cc: alan, davej, linux-ide

Tejun Heo wrote:
> Implement per-dev xfermask.  libata used to determine xfermask
> per-port - the fastest mode of the slowest device on the port.  This
> patch enables per-dev xfermask.
> 
> Original patch is from Alan Cox <alan@redhat.com>.  The following
> changes are made by me.
> 
> * simplex warning message is added
> * fix port-wide PIO mode selection to aovid violating device selection
>   timing.

Since Alan squawked, perhaps break the port-wide PIO mode selection into 
a separate patch, so that the other stuff can go in?

Then longer term we can figure out what it the best course of action.



^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 6/9] libata: implement dummy port
  2006-08-10  8:16 [PATCHSET] libata: improve initialization and legacy handling, take#3 Tejun Heo
@ 2006-08-10  8:16 ` Tejun Heo
  0 siblings, 0 replies; 23+ messages in thread
From: Tejun Heo @ 2006-08-10  8:16 UTC (permalink / raw)
  To: jgarzik, alan, linux-ide; +Cc: Tejun Heo

Implement dummy port which can be requested by setting appropriate bit
in probe_ent->dummy_port_mask.  The dummy port is used as placeholder
for stolen legacy port.  This allows libata to guarantee that
index_of(ap) == ap->port_no == actual_device_port_no, and thus to
remove error-prone ap->hard_port_no.

As it's used only when one port of a legacy controller is reserved by
some other entity (e.g. IDE), the focus is on keeping the added *code*
complexity at minimum, so dummy port allocates all libata core
resources and acts as a normal port.  It just has all dummy port_ops.

This patch only implements dummy port.  The following patch will make
libata use it for stolen legacy ports.

Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/libata-core.c |   61 +++++++++++++++++++++++++++++++++++++-------
 include/linux/libata.h     |    8 ++++++
 2 files changed, 59 insertions(+), 10 deletions(-)

dd5b06c490de72440ec39f814de99a714a45a1a9
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 3634279..f2e7e2f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5311,7 +5311,6 @@ static struct ata_port * ata_port_add(co
 {
 	struct Scsi_Host *shost;
 	struct ata_port *ap;
-	int rc;
 
 	DPRINTK("ENTER\n");
 
@@ -5333,15 +5332,7 @@ static struct ata_port * ata_port_add(co
 	ata_port_init(ap, host_set, ent, port_no);
 	ata_port_init_shost(ap, shost);
 
-	rc = ap->ops->port_start(ap);
-	if (rc)
-		goto err_out;
-
 	return ap;
-
-err_out:
-	scsi_host_put(shost);
-	return NULL;
 }
 
 /**
@@ -5415,11 +5406,27 @@ int ata_device_add(const struct ata_prob
 		if (!ap)
 			goto err_out;
 
+		host_set->ports[i] = ap;
+
+		/* dummy? */
+		if (ent->dummy_port_mask & (1 << i)) {
+			ata_port_printk(ap, KERN_INFO, "DUMMY\n");
+			ap->ops = &ata_dummy_port_ops;
+			continue;
+		}
+
+		/* start port */
+		rc = ap->ops->port_start(ap);
+		if (rc) {
+			host_set->ports[i] = NULL;
+			scsi_host_put(ap->host);
+			goto err_out;
+		}
+
 		/* Report the secondary IRQ for second channel legacy */
 		if (i == 1 && ent->irq2)
 			irq_line = ent->irq2;
 
-		host_set->ports[i] = ap;
 		xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
 				(ap->mwdma_mask << ATA_SHIFT_MWDMA) |
 				(ap->pio_mask << ATA_SHIFT_PIO);
@@ -5941,6 +5948,39 @@ u32 ata_wait_register(void __iomem *reg,
 }
 
 /*
+ * Dummy port_ops
+ */
+static void ata_dummy_noret(struct ata_port *ap)	{ }
+static int ata_dummy_ret0(struct ata_port *ap)		{ return 0; }
+static void ata_dummy_qc_noret(struct ata_queued_cmd *qc) { }
+
+static u8 ata_dummy_check_status(struct ata_port *ap)
+{
+	return ATA_DRDY;
+}
+
+static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
+{
+	return AC_ERR_SYSTEM;
+}
+
+const struct ata_port_operations ata_dummy_port_ops = {
+	.port_disable		= ata_port_disable,
+	.check_status		= ata_dummy_check_status,
+	.check_altstatus	= ata_dummy_check_status,
+	.dev_select		= ata_noop_dev_select,
+	.qc_prep		= ata_noop_qc_prep,
+	.qc_issue		= ata_dummy_qc_issue,
+	.freeze			= ata_dummy_noret,
+	.thaw			= ata_dummy_noret,
+	.error_handler		= ata_dummy_noret,
+	.post_internal_cmd	= ata_dummy_qc_noret,
+	.irq_clear		= ata_dummy_noret,
+	.port_start		= ata_dummy_ret0,
+	.port_stop		= ata_dummy_noret,
+};
+
+/*
  * libata is essentially a library of internal helper functions for
  * low-level ATA host controller drivers.  As such, the API/ABI is
  * likely to change as new drivers are added and updated.
@@ -5950,6 +5990,7 @@ u32 ata_wait_register(void __iomem *reg,
 EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
 EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
 EXPORT_SYMBOL_GPL(sata_deb_timing_long);
+EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
 EXPORT_SYMBOL_GPL(ata_std_bios_param);
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_host_set_init);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 4504776..30bfe8f 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -353,6 +353,7 @@ struct ata_probe_ent {
 	struct ata_ioports	port[ATA_MAX_PORTS];
 	unsigned int		n_ports;
 	unsigned int		hard_port_no;
+	unsigned int		dummy_port_mask;
 	unsigned int		pio_mask;
 	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
@@ -652,6 +653,8 @@ extern const unsigned long sata_deb_timi
 extern const unsigned long sata_deb_timing_hotplug[];
 extern const unsigned long sata_deb_timing_long[];
 
+extern const struct ata_port_operations ata_dummy_port_ops;
+
 static inline const unsigned long *
 sata_ehc_deb_timing(struct ata_eh_context *ehc)
 {
@@ -661,6 +664,11 @@ sata_ehc_deb_timing(struct ata_eh_contex
 		return sata_deb_timing_normal;
 }
 
+static inline int ata_port_is_dummy(struct ata_port *ap)
+{
+	return ap->ops == &ata_dummy_port_ops;
+}
+
 extern void ata_port_probe(struct ata_port *);
 extern void __sata_phy_reset(struct ata_port *ap);
 extern void sata_phy_reset(struct ata_port *ap);
-- 
1.3.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2006-08-10  8:16 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-04 21:01 [PATCHSET] libata: improve initialization and legacy handling, take#2 Tejun Heo
2006-08-04 21:01 ` [PATCH 1/9] [libata] some function renaming Tejun Heo
2006-08-09  4:24   ` Jeff Garzik
2006-08-09  4:25   ` Jeff Garzik
2006-08-04 21:01 ` [PATCH 3/9] libata: implement per-dev xfermask Tejun Heo
2006-08-05 13:38   ` Alan Cox
2006-08-06 14:41     ` Tejun Heo
2006-08-06 15:56       ` Alan Cox
2006-08-06 16:08         ` Tejun Heo
2006-08-09  4:30   ` Jeff Garzik
2006-08-04 21:01 ` [PATCH 5/9] libata: fix several bugs in reworked legacy handling Tejun Heo
2006-08-09  4:28   ` Jeff Garzik
2006-08-04 21:01 ` [PATCH 6/9] libata: implement dummy port Tejun Heo
2006-08-04 21:01 ` [PATCH 2/9] [libata] Kill 'count' var in ata_device_add() Tejun Heo
2006-08-04 21:01 ` [PATCH 7/9] libata: use dummy port for stolen legacy ports Tejun Heo
2006-08-04 21:01 ` [PATCH 4/9] libata: rework legacy handling to remove much of the cruft Tejun Heo
2006-08-09  4:27   ` Jeff Garzik
2006-08-04 21:01 ` [PATCH 8/9] libata: replace ap->hard_port_no with ap->port_no Tejun Heo
2006-08-04 21:01 ` [PATCH 9/9] libata: kill unused hard_port_no and legacy_mode Tejun Heo
2006-08-09  4:29   ` Jeff Garzik
2006-08-04 21:05 ` [PATCHSET] libata: improve initialization and legacy handling, take#2 Dave Jones
2006-08-04 21:13   ` Tejun Heo
  -- strict thread matches above, loose matches on Subject: below --
2006-08-10  8:16 [PATCHSET] libata: improve initialization and legacy handling, take#3 Tejun Heo
2006-08-10  8:16 ` [PATCH 6/9] libata: implement dummy port Tejun Heo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).