linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC]hpt366/ide-probe  reset drive on probe error.
@ 2009-05-05 14:53 Karl Hiramoto
  2009-05-08 13:50 ` Bartlomiej Zolnierkiewicz
  0 siblings, 1 reply; 9+ messages in thread
From: Karl Hiramoto @ 2009-05-05 14:53 UTC (permalink / raw)
  To: linux-ide

Hi,

Part of this patch (htp366.c) is commented in an #if 0   in older 
kernels.   2.6.11 for sure.

I have an ARM IXP4xx based board with CompactFlash slot that this patch 
fixes some issues for.    I think the case, is only with a warm boot, 
where the drive was busy before the board was reset.   There is  no 
BIOS, only the redboot loader which loads the kernel.


A few questions:

1.  Would this be considerd to be brought into mainline?

2.  How would you port something like this to using the SATA layer?

Would it go to the ata_port_operations.prereset,  softreset or hardreset?

--
Karl

diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 3377766..ba4b802 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -1280,6 +1280,31 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
 	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 }
 
+/** routine to reset disk
+ *
+ * Since SUN Cobalt is attempting to do this operation, I should disclose
+ * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
+ * HOTSWAP ATA Infrastructure.
+ */
+
+static void hpt3xx_reset (ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+	unsigned long high_16;
+	u8 reset;
+	u8 reg59h = 0;
+
+	printk(KERN_INFO "%s reset drive channel %d\n", __func__, hwif->channel);
+	high_16 = pci_resource_start(dev, 4);
+
+	reset = hwif->channel ? 0x80 : 0x40;
+
+	pci_read_config_byte(dev, 0x59, &reg59h);
+	pci_write_config_byte(dev, 0x59, reg59h|reset);
+	pci_write_config_byte(dev, 0x59, reg59h);
+}
+
 static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
 {
 	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
@@ -1406,6 +1431,7 @@ static const struct ide_port_ops hpt3xx_port_ops = {
 	.set_pio_mode		= hpt3xx_set_pio_mode,
 	.set_dma_mode		= hpt3xx_set_mode,
 	.quirkproc		= hpt3xx_quirkproc,
+	.resetproc		= hpt3xx_reset,
 	.maskproc		= hpt3xx_maskproc,
 	.mdma_filter		= hpt3xx_mdma_filter,
 	.udma_filter		= hpt3xx_udma_filter,
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 7f264ed..09295b4 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -367,6 +367,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+	const struct ide_port_ops *port_ops = hwif->port_ops;
 	u16 *id = drive->id;
 	int rc;
 	u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
@@ -427,9 +428,20 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
 		/* ensure drive IRQ is clear */
 		stat = tp_ops->read_status(hwif);
 
-		if (rc == 1)
+		if (rc == 1) {
 			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
 					drive->name, stat);
+
+			if (port_ops->resetproc) {
+				port_ops->resetproc(drive);
+				msleep(50);
+			}
+			tp_ops->dev_select(drive);
+			msleep(50);
+			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
+			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
+			rc = ide_dev_read_id(drive, cmd, id);
+		}
 	} else {
 		/* not present or maybe ATAPI */
 		rc = 3;



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

* Re: [RFC]hpt366/ide-probe  reset drive on probe error.
  2009-05-05 14:53 [RFC]hpt366/ide-probe reset drive on probe error Karl Hiramoto
@ 2009-05-08 13:50 ` Bartlomiej Zolnierkiewicz
  2009-05-08 13:57   ` Bartlomiej Zolnierkiewicz
  2009-05-08 14:57   ` Sergei Shtylyov
  0 siblings, 2 replies; 9+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2009-05-08 13:50 UTC (permalink / raw)
  To: Karl Hiramoto; +Cc: linux-ide, Sergei Shtylyov


On Tuesday 05 May 2009 16:53:31 Karl Hiramoto wrote:
> Hi,
> 
> Part of this patch (htp366.c) is commented in an #if 0   in older 
> kernels.   2.6.11 for sure.
> 
> I have an ARM IXP4xx based board with CompactFlash slot that this patch 
> fixes some issues for.    I think the case, is only with a warm boot, 
> where the drive was busy before the board was reset.   There is  no 
> BIOS, only the redboot loader which loads the kernel.
> 
> 
> A few questions:
> 
> 1.  Would this be considerd to be brought into mainline?

When it comes to ide-probe.c changes: yes given that you split them on
smaller patches.  hpt366.c change also seems to be correct on the first
glance but I think that Sergei's opinion would be more suited here.

> 2.  How would you port something like this to using the SATA layer?
> 
> Would it go to the ata_port_operations.prereset,  softreset or hardreset?
> 
> --
> Karl
> 
> diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
> index 3377766..ba4b802 100644
> --- a/drivers/ide/hpt366.c
> +++ b/drivers/ide/hpt366.c
> @@ -1280,6 +1280,31 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
>  	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
>  }
>  
> +/** routine to reset disk
> + *
> + * Since SUN Cobalt is attempting to do this operation, I should disclose
> + * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
> + * HOTSWAP ATA Infrastructure.
> + */
> +
> +static void hpt3xx_reset (ide_drive_t *drive)
> +{
> +	ide_hwif_t *hwif = drive->hwif;
> +	struct pci_dev *dev = to_pci_dev(hwif->dev);
> +	unsigned long high_16;
> +	u8 reset;
> +	u8 reg59h = 0;
> +
> +	printk(KERN_INFO "%s reset drive channel %d\n", __func__, hwif->channel);
> +	high_16 = pci_resource_start(dev, 4);
> +
> +	reset = hwif->channel ? 0x80 : 0x40;
> +
> +	pci_read_config_byte(dev, 0x59, &reg59h);
> +	pci_write_config_byte(dev, 0x59, reg59h|reset);
> +	pci_write_config_byte(dev, 0x59, reg59h);
> +}
> +
>  static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
>  {
>  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
> @@ -1406,6 +1431,7 @@ static const struct ide_port_ops hpt3xx_port_ops = {
>  	.set_pio_mode		= hpt3xx_set_pio_mode,
>  	.set_dma_mode		= hpt3xx_set_mode,
>  	.quirkproc		= hpt3xx_quirkproc,
> +	.resetproc		= hpt3xx_reset,
>  	.maskproc		= hpt3xx_maskproc,
>  	.mdma_filter		= hpt3xx_mdma_filter,
>  	.udma_filter		= hpt3xx_udma_filter,
> diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
> index 7f264ed..09295b4 100644
> --- a/drivers/ide/ide-probe.c
> +++ b/drivers/ide/ide-probe.c
> @@ -367,6 +367,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>  {
>  	ide_hwif_t *hwif = drive->hwif;
>  	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
> +	const struct ide_port_ops *port_ops = hwif->port_ops;
>  	u16 *id = drive->id;
>  	int rc;
>  	u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
> @@ -427,9 +428,20 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>  		/* ensure drive IRQ is clear */
>  		stat = tp_ops->read_status(hwif);
>  
> -		if (rc == 1)
> +		if (rc == 1) {
>  			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
>  					drive->name, stat);
> +
> +			if (port_ops->resetproc) {
> +				port_ops->resetproc(drive);
> +				msleep(50);
> +			}
> +			tp_ops->dev_select(drive);
> +			msleep(50);
> +			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
> +			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
> +			rc = ide_dev_read_id(drive, cmd, id);
> +		}
>  	} else {
>  		/* not present or maybe ATAPI */
>  		rc = 3;

Since the current code in ide-probe.c looks like this:

		stat = tp_ops->read_status(hwif);

		if (stat == (ATA_BUSY | ATA_DRDY))
			return 4;

		if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
			printk(KERN_ERR "%s: no response (status = 0x%02x), "
					"resetting drive\n", drive->name, stat);
			msleep(50);
			tp_ops->dev_select(drive);
			msleep(50);
			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
			rc = ide_dev_read_id(drive, cmd, id);
		}

		/* ensure drive IRQ is clear */
		stat = tp_ops->read_status(hwif);

		if (rc == 1)
			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
					drive->name, stat);

I would really prefer fixing ATAPI case while we are at it
(+ this would also get rid of code duplication).

IOW:

- in patch #1 we would add ->resetproc call

- in patch #2 we would remove 'cmd == ATA_CMD_ID_ATAPI' check

Care to revise your patch?

Thanks,
Bart

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

* Re: [RFC]hpt366/ide-probe  reset drive on probe error.
  2009-05-08 13:50 ` Bartlomiej Zolnierkiewicz
@ 2009-05-08 13:57   ` Bartlomiej Zolnierkiewicz
  2009-05-08 14:07     ` Bartlomiej Zolnierkiewicz
  2009-05-08 14:57   ` Sergei Shtylyov
  1 sibling, 1 reply; 9+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2009-05-08 13:57 UTC (permalink / raw)
  To: Karl Hiramoto; +Cc: linux-ide, Sergei Shtylyov

On Friday 08 May 2009 15:50:11 Bartlomiej Zolnierkiewicz wrote:
> 
> On Tuesday 05 May 2009 16:53:31 Karl Hiramoto wrote:
> > Hi,
> > 
> > Part of this patch (htp366.c) is commented in an #if 0   in older 
> > kernels.   2.6.11 for sure.
> > 
> > I have an ARM IXP4xx based board with CompactFlash slot that this patch 
> > fixes some issues for.    I think the case, is only with a warm boot, 
> > where the drive was busy before the board was reset.   There is  no 
> > BIOS, only the redboot loader which loads the kernel.
> > 
> > 
> > A few questions:
> > 
> > 1.  Would this be considerd to be brought into mainline?
> 
> When it comes to ide-probe.c changes: yes given that you split them on
> smaller patches.  hpt366.c change also seems to be correct on the first
> glance but I think that Sergei's opinion would be more suited here.
> 
> > 2.  How would you port something like this to using the SATA layer?
> > 
> > Would it go to the ata_port_operations.prereset,  softreset or hardreset?
> > 
> > --
> > Karl
> > 
> > diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
> > index 3377766..ba4b802 100644
> > --- a/drivers/ide/hpt366.c
> > +++ b/drivers/ide/hpt366.c
> > @@ -1280,6 +1280,31 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
> >  	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
> >  }
> >  
> > +/** routine to reset disk
> > + *
> > + * Since SUN Cobalt is attempting to do this operation, I should disclose
> > + * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
> > + * HOTSWAP ATA Infrastructure.
> > + */
> > +
> > +static void hpt3xx_reset (ide_drive_t *drive)
> > +{
> > +	ide_hwif_t *hwif = drive->hwif;
> > +	struct pci_dev *dev = to_pci_dev(hwif->dev);
> > +	unsigned long high_16;
> > +	u8 reset;
> > +	u8 reg59h = 0;
> > +
> > +	printk(KERN_INFO "%s reset drive channel %d\n", __func__, hwif->channel);
> > +	high_16 = pci_resource_start(dev, 4);
> > +
> > +	reset = hwif->channel ? 0x80 : 0x40;
> > +
> > +	pci_read_config_byte(dev, 0x59, &reg59h);
> > +	pci_write_config_byte(dev, 0x59, reg59h|reset);
> > +	pci_write_config_byte(dev, 0x59, reg59h);
> > +}
> > +
> >  static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
> >  {
> >  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
> > @@ -1406,6 +1431,7 @@ static const struct ide_port_ops hpt3xx_port_ops = {
> >  	.set_pio_mode		= hpt3xx_set_pio_mode,
> >  	.set_dma_mode		= hpt3xx_set_mode,
> >  	.quirkproc		= hpt3xx_quirkproc,
> > +	.resetproc		= hpt3xx_reset,
> >  	.maskproc		= hpt3xx_maskproc,
> >  	.mdma_filter		= hpt3xx_mdma_filter,
> >  	.udma_filter		= hpt3xx_udma_filter,
> > diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
> > index 7f264ed..09295b4 100644
> > --- a/drivers/ide/ide-probe.c
> > +++ b/drivers/ide/ide-probe.c
> > @@ -367,6 +367,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
> >  {
> >  	ide_hwif_t *hwif = drive->hwif;
> >  	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
> > +	const struct ide_port_ops *port_ops = hwif->port_ops;
> >  	u16 *id = drive->id;
> >  	int rc;
> >  	u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
> > @@ -427,9 +428,20 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
> >  		/* ensure drive IRQ is clear */
> >  		stat = tp_ops->read_status(hwif);
> >  
> > -		if (rc == 1)
> > +		if (rc == 1) {
> >  			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
> >  					drive->name, stat);
> > +
> > +			if (port_ops->resetproc) {
> > +				port_ops->resetproc(drive);
> > +				msleep(50);
> > +			}
> > +			tp_ops->dev_select(drive);
> > +			msleep(50);
> > +			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
> > +			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
> > +			rc = ide_dev_read_id(drive, cmd, id);
> > +		}
> >  	} else {
> >  		/* not present or maybe ATAPI */
> >  		rc = 3;
> 
> Since the current code in ide-probe.c looks like this:
> 
> 		stat = tp_ops->read_status(hwif);
> 
> 		if (stat == (ATA_BUSY | ATA_DRDY))
> 			return 4;
> 
> 		if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
> 			printk(KERN_ERR "%s: no response (status = 0x%02x), "
> 					"resetting drive\n", drive->name, stat);
> 			msleep(50);
> 			tp_ops->dev_select(drive);
> 			msleep(50);
> 			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
> 			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
> 			rc = ide_dev_read_id(drive, cmd, id);
> 		}
> 
> 		/* ensure drive IRQ is clear */
> 		stat = tp_ops->read_status(hwif);
> 
> 		if (rc == 1)
> 			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
> 					drive->name, stat);
> 
> I would really prefer fixing ATAPI case while we are at it
> (+ this would also get rid of code duplication).
> 
> IOW:
> 
> - in patch #1 we would add ->resetproc call
> 
> - in patch #2 we would remove 'cmd == ATA_CMD_ID_ATAPI' check

[ looking a bit closer at the code in ide-probe.c ]

- in patch #2 we would move the ATAPI check to cover device selection/reset
  inside 'if ()' block

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

* Re: [RFC]hpt366/ide-probe  reset drive on probe error.
  2009-05-08 13:57   ` Bartlomiej Zolnierkiewicz
@ 2009-05-08 14:07     ` Bartlomiej Zolnierkiewicz
  2009-05-08 15:29       ` Sergei Shtylyov
  0 siblings, 1 reply; 9+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2009-05-08 14:07 UTC (permalink / raw)
  To: Karl Hiramoto; +Cc: linux-ide, Sergei Shtylyov

On Friday 08 May 2009 15:57:19 Bartlomiej Zolnierkiewicz wrote:
> On Friday 08 May 2009 15:50:11 Bartlomiej Zolnierkiewicz wrote:
> > 
> > On Tuesday 05 May 2009 16:53:31 Karl Hiramoto wrote:
> > > Hi,
> > > 
> > > Part of this patch (htp366.c) is commented in an #if 0   in older 
> > > kernels.   2.6.11 for sure.
> > > 
> > > I have an ARM IXP4xx based board with CompactFlash slot that this patch 
> > > fixes some issues for.    I think the case, is only with a warm boot, 
> > > where the drive was busy before the board was reset.   There is  no 
> > > BIOS, only the redboot loader which loads the kernel.
> > > 
> > > 
> > > A few questions:
> > > 
> > > 1.  Would this be considerd to be brought into mainline?
> > 
> > When it comes to ide-probe.c changes: yes given that you split them on
> > smaller patches.  hpt366.c change also seems to be correct on the first
> > glance but I think that Sergei's opinion would be more suited here.
> > 
> > > 2.  How would you port something like this to using the SATA layer?
> > > 
> > > Would it go to the ata_port_operations.prereset,  softreset or hardreset?
> > > 
> > > --
> > > Karl
> > > 
> > > diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
> > > index 3377766..ba4b802 100644
> > > --- a/drivers/ide/hpt366.c
> > > +++ b/drivers/ide/hpt366.c
> > > @@ -1280,6 +1280,31 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
> > >  	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
> > >  }
> > >  
> > > +/** routine to reset disk
> > > + *
> > > + * Since SUN Cobalt is attempting to do this operation, I should disclose
> > > + * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
> > > + * HOTSWAP ATA Infrastructure.
> > > + */
> > > +
> > > +static void hpt3xx_reset (ide_drive_t *drive)
> > > +{
> > > +	ide_hwif_t *hwif = drive->hwif;
> > > +	struct pci_dev *dev = to_pci_dev(hwif->dev);
> > > +	unsigned long high_16;
> > > +	u8 reset;
> > > +	u8 reg59h = 0;
> > > +
> > > +	printk(KERN_INFO "%s reset drive channel %d\n", __func__, hwif->channel);
> > > +	high_16 = pci_resource_start(dev, 4);
> > > +
> > > +	reset = hwif->channel ? 0x80 : 0x40;
> > > +
> > > +	pci_read_config_byte(dev, 0x59, &reg59h);
> > > +	pci_write_config_byte(dev, 0x59, reg59h|reset);
> > > +	pci_write_config_byte(dev, 0x59, reg59h);
> > > +}
> > > +
> > >  static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
> > >  {
> > >  	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
> > > @@ -1406,6 +1431,7 @@ static const struct ide_port_ops hpt3xx_port_ops = {
> > >  	.set_pio_mode		= hpt3xx_set_pio_mode,
> > >  	.set_dma_mode		= hpt3xx_set_mode,
> > >  	.quirkproc		= hpt3xx_quirkproc,
> > > +	.resetproc		= hpt3xx_reset,
> > >  	.maskproc		= hpt3xx_maskproc,
> > >  	.mdma_filter		= hpt3xx_mdma_filter,
> > >  	.udma_filter		= hpt3xx_udma_filter,
> > > diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
> > > index 7f264ed..09295b4 100644
> > > --- a/drivers/ide/ide-probe.c
> > > +++ b/drivers/ide/ide-probe.c
> > > @@ -367,6 +367,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
> > >  {
> > >  	ide_hwif_t *hwif = drive->hwif;
> > >  	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
> > > +	const struct ide_port_ops *port_ops = hwif->port_ops;
> > >  	u16 *id = drive->id;
> > >  	int rc;
> > >  	u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
> > > @@ -427,9 +428,20 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
> > >  		/* ensure drive IRQ is clear */
> > >  		stat = tp_ops->read_status(hwif);
> > >  
> > > -		if (rc == 1)
> > > +		if (rc == 1) {
> > >  			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
> > >  					drive->name, stat);
> > > +
> > > +			if (port_ops->resetproc) {
> > > +				port_ops->resetproc(drive);
> > > +				msleep(50);
> > > +			}
> > > +			tp_ops->dev_select(drive);
> > > +			msleep(50);
> > > +			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
> > > +			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
> > > +			rc = ide_dev_read_id(drive, cmd, id);
> > > +		}
> > >  	} else {
> > >  		/* not present or maybe ATAPI */
> > >  		rc = 3;
> > 
> > Since the current code in ide-probe.c looks like this:
> > 
> > 		stat = tp_ops->read_status(hwif);
> > 
> > 		if (stat == (ATA_BUSY | ATA_DRDY))
> > 			return 4;
> > 
> > 		if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
> > 			printk(KERN_ERR "%s: no response (status = 0x%02x), "
> > 					"resetting drive\n", drive->name, stat);
> > 			msleep(50);
> > 			tp_ops->dev_select(drive);
> > 			msleep(50);
> > 			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
> > 			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
> > 			rc = ide_dev_read_id(drive, cmd, id);
> > 		}
> > 
> > 		/* ensure drive IRQ is clear */
> > 		stat = tp_ops->read_status(hwif);
> > 
> > 		if (rc == 1)
> > 			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
> > 					drive->name, stat);
> > 
> > I would really prefer fixing ATAPI case while we are at it
> > (+ this would also get rid of code duplication).
> > 
> > IOW:
> > 
> > - in patch #1 we would add ->resetproc call
> > 
> > - in patch #2 we would remove 'cmd == ATA_CMD_ID_ATAPI' check
> 
> [ looking a bit closer at the code in ide-probe.c ]
> 
> - in patch #2 we would move the ATAPI check to cover device selection/reset
>   inside 'if ()' block

Sigh, this is even more complicated...

We should defer ->resetproc call until both drives are probed and do the
port reset after probing both drives given that:

- we didn't detect any devices

and 

- for one of devices do_probe() returned '1' (== "no response")

Also it would greatly help to clean/fix return values of do_probe()
and probe_for_drive() before doing the real changes.

Thanks,
Bart

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

* Re: [RFC]hpt366/ide-probe  reset drive on probe error.
  2009-05-08 13:50 ` Bartlomiej Zolnierkiewicz
  2009-05-08 13:57   ` Bartlomiej Zolnierkiewicz
@ 2009-05-08 14:57   ` Sergei Shtylyov
  2009-05-08 15:13     ` Sergei Shtylyov
  1 sibling, 1 reply; 9+ messages in thread
From: Sergei Shtylyov @ 2009-05-08 14:57 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz, Karl Hiramoto; +Cc: linux-ide

Bartlomiej Zolnierkiewicz wrote:

>>Hi,

>>Part of this patch (htp366.c) is commented in an #if 0   in older 
>>kernels.   2.6.11 for sure.

    ... and for a reason.

>>I have an ARM IXP4xx based board with CompactFlash slot that this patch 
>>fixes some issues for.    I think the case, is only with a warm boot, 
>>where the drive was busy before the board was reset.   There is  no 
>>BIOS, only the redboot loader which loads the kernel.

>>A few questions:

>>1.  Would this be considerd to be brought into mainline?

> When it comes to ide-probe.c changes: yes given that you split them on
> smaller patches.  hpt366.c change also seems to be correct on the first
> glance but I think that Sergei's opinion would be more suited here.

    Frankly speaking, I don't quite understand this patch.

[...]

>>--
>>Karl
>>
>>diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
>>index 3377766..ba4b802 100644
>>--- a/drivers/ide/hpt366.c
>>+++ b/drivers/ide/hpt366.c
>>@@ -1280,6 +1280,31 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
>> 	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
>> }
>> 
>>+/** routine to reset disk
>>+ *
>>+ * Since SUN Cobalt is attempting to do this operation, I should disclose
>>+ * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
>>+ * HOTSWAP ATA Infrastructure.

    This comment doesn't really belong to resetproc() method, it rather 
belongs to (now gone) tristate() method.

>>+ */
>>+
>>+static void hpt3xx_reset (ide_drive_t *drive)

    No spaces allowed before '('. Use scripts/checkpatch.pl please.

>>+{
>>+	ide_hwif_t *hwif = drive->hwif;
>>+	struct pci_dev *dev = to_pci_dev(hwif->dev);
>>+	unsigned long high_16;
>>+	u8 reset;
>>+	u8 reg59h = 0;
>>+
>>+	printk(KERN_INFO "%s reset drive channel %d\n", __func__, hwif->channel);
>>+	high_16 = pci_resource_start(dev, 4);

    Useless variable.

>>+
>>+	reset = hwif->channel ? 0x80 : 0x40;

    These HighPoint's "soft reset" (WTF does that mean I wonder?) bits are 
not the same between HPT366 and HPT370, so this code doesn't look right...

>>+
>>+	pci_read_config_byte(dev, 0x59, &reg59h);
>>+	pci_write_config_byte(dev, 0x59, reg59h|reset);
>>+	pci_write_config_byte(dev, 0x59, reg59h);
>>+}
>>+
>> static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
>> {
>> 	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
>>@@ -1406,6 +1431,7 @@ static const struct ide_port_ops hpt3xx_port_ops = {
>> 	.set_pio_mode		= hpt3xx_set_pio_mode,
>> 	.set_dma_mode		= hpt3xx_set_mode,
>> 	.quirkproc		= hpt3xx_quirkproc,
>>+	.resetproc		= hpt3xx_reset,
>> 	.maskproc		= hpt3xx_maskproc,
>> 	.mdma_filter		= hpt3xx_mdma_filter,
>> 	.udma_filter		= hpt3xx_udma_filter,
>>diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
>>index 7f264ed..09295b4 100644
>>--- a/drivers/ide/ide-probe.c
>>+++ b/drivers/ide/ide-probe.c
>>@@ -367,6 +367,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>> {
>> 	ide_hwif_t *hwif = drive->hwif;
>> 	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
>>+	const struct ide_port_ops *port_ops = hwif->port_ops;
>> 	u16 *id = drive->id;
>> 	int rc;
>> 	u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
>>@@ -427,9 +428,20 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>> 		/* ensure drive IRQ is clear */
>> 		stat = tp_ops->read_status(hwif);
>> 
>>-		if (rc == 1)
>>+		if (rc == 1) {
>> 			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
>> 					drive->name, stat);
>>+
>>+			if (port_ops->resetproc) {
>>+				port_ops->resetproc(drive);
>>+				msleep(50);

    Karl, why are you calling resetproc() without doing a reset? What this 
achieves?

>>+			}
>>+			tp_ops->dev_select(drive);
>>+			msleep(50);
>>+			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
>>+			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
>>+			rc = ide_dev_read_id(drive, cmd, id);
>>+		}
>> 	} else {
>> 		/* not present or maybe ATAPI */
>> 		rc = 3;

> Since the current code in ide-probe.c looks like this:

> 		stat = tp_ops->read_status(hwif);
> 
> 		if (stat == (ATA_BUSY | ATA_DRDY))
> 			return 4;
> 
> 		if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
> 			printk(KERN_ERR "%s: no response (status = 0x%02x), "
> 					"resetting drive\n", drive->name, stat);
> 			msleep(50);
> 			tp_ops->dev_select(drive);
> 			msleep(50);
> 			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
> 			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
> 			rc = ide_dev_read_id(drive, cmd, id);
> 		}
> 
> 		/* ensure drive IRQ is clear */
> 		stat = tp_ops->read_status(hwif);
> 
> 		if (rc == 1)
> 			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
> 					drive->name, stat);

> I would really prefer fixing ATAPI case while we are at it
> (+ this would also get rid of code duplication).

> IOW:

> - in patch #1 we would add ->resetproc call

    I would first like to hear an explanation of what it does...

> - in patch #2 we would remove 'cmd == ATA_CMD_ID_ATAPI' check

    Why? Does issuing ATA_CMD_DEV_RESET to hard drives make sense?

> Care to revise your patch?

> Thanks,
> Bart

MBR, Sergei

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

* Re: [RFC]hpt366/ide-probe  reset drive on probe error.
  2009-05-08 14:57   ` Sergei Shtylyov
@ 2009-05-08 15:13     ` Sergei Shtylyov
  2009-05-09 12:09       ` Karl Hiramoto
  0 siblings, 1 reply; 9+ messages in thread
From: Sergei Shtylyov @ 2009-05-08 15:13 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz, Karl Hiramoto; +Cc: linux-ide

Hello, I wrote:

>>> diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
>>> index 3377766..ba4b802 100644
>>> --- a/drivers/ide/hpt366.c
>>> +++ b/drivers/ide/hpt366.c
>>> @@ -1280,6 +1280,31 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
>>>     return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
>>> }
>>>
>>> +/** routine to reset disk
>>> + *
>>> + * Since SUN Cobalt is attempting to do this operation, I should 
>>> disclose
>>> + * this has been a long time ago Thu Jul 27 16:40:57 2000 was the 
>>> patch date
>>> + * HOTSWAP ATA Infrastructure.

>    This comment doesn't really belong to resetproc() method, it rather 
> belongs to (now gone) tristate() method.

>>> + */
>>> +
>>> +static void hpt3xx_reset (ide_drive_t *drive)

>    No spaces allowed before '('. Use scripts/checkpatch.pl please.

>>> +{
>>> +    ide_hwif_t *hwif = drive->hwif;
>>> +    struct pci_dev *dev = to_pci_dev(hwif->dev);
>>> +    unsigned long high_16;
>>> +    u8 reset;
>>> +    u8 reg59h = 0;
>>> +
>>> +    printk(KERN_INFO "%s reset drive channel %d\n", __func__, 
>>> hwif->channel);
>>> +    high_16 = pci_resource_start(dev, 4);

>    Useless variable.

>>> +
>>> +    reset = hwif->channel ? 0x80 : 0x40;

>    These HighPoint's "soft reset" (WTF does that mean I wonder?) bits 
> are not the same between HPT366 and HPT370, so this code doesn't look 
> right...

    Ah, these "soft" reset bits correspond to PRST_/SRST_ signals which are 
really primary/secondary channel hard resets (RESET- signal). This explains 
everything; and this patch is a pure hack then.

>>> +
>>> +    pci_read_config_byte(dev, 0x59, &reg59h);
>>> +    pci_write_config_byte(dev, 0x59, reg59h|reset);
>>> +    pci_write_config_byte(dev, 0x59, reg59h);
>>> +}
>>> +
>>> static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
>>> {
>>>     struct hpt_info *info    = hpt3xx_get_info(hwif->dev);
>>> @@ -1406,6 +1431,7 @@ static const struct ide_port_ops 
>>> hpt3xx_port_ops = {
>>>     .set_pio_mode        = hpt3xx_set_pio_mode,
>>>     .set_dma_mode        = hpt3xx_set_mode,
>>>     .quirkproc        = hpt3xx_quirkproc,
>>> +    .resetproc        = hpt3xx_reset,
>>>     .maskproc        = hpt3xx_maskproc,
>>>     .mdma_filter        = hpt3xx_mdma_filter,
>>>     .udma_filter        = hpt3xx_udma_filter,
>>> diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
>>> index 7f264ed..09295b4 100644
>>> --- a/drivers/ide/ide-probe.c
>>> +++ b/drivers/ide/ide-probe.c
>>> @@ -367,6 +367,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>>> {
>>>     ide_hwif_t *hwif = drive->hwif;
>>>     const struct ide_tp_ops *tp_ops = hwif->tp_ops;
>>> +    const struct ide_port_ops *port_ops = hwif->port_ops;
>>>     u16 *id = drive->id;
>>>     int rc;
>>>     u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
>>> @@ -427,9 +428,20 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>>>         /* ensure drive IRQ is clear */
>>>         stat = tp_ops->read_status(hwif);
>>>
>>> -        if (rc == 1)
>>> +        if (rc == 1) {
>>>             printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
>>>                     drive->name, stat);
>>> +
>>> +            if (port_ops->resetproc) {
>>> +                port_ops->resetproc(drive);
>>> +                msleep(50);

>    Karl, why are you calling resetproc() without doing a reset? What 
> this achieves?

    To reset the drives, apparently. But it's not the function of 
resetproc(). We should try soft-reset instead.

>>> +            }
>>> +            tp_ops->dev_select(drive);
>>> +            msleep(50);
>>> +            tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
>>> +            (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
>>> +            rc = ide_dev_read_id(drive, cmd, id);
>>> +        }
>>>     } else {
>>>         /* not present or maybe ATAPI */
>>>         rc = 3;

>> Since the current code in ide-probe.c looks like this:

>>         stat = tp_ops->read_status(hwif);
>>
>>         if (stat == (ATA_BUSY | ATA_DRDY))
>>             return 4;
>>
>>         if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
>>             printk(KERN_ERR "%s: no response (status = 0x%02x), "
>>                     "resetting drive\n", drive->name, stat);
>>             msleep(50);
>>             tp_ops->dev_select(drive);
>>             msleep(50);
>>             tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
>>             (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
>>             rc = ide_dev_read_id(drive, cmd, id);
>>         }
>>
>>         /* ensure drive IRQ is clear */
>>         stat = tp_ops->read_status(hwif);
>>
>>         if (rc == 1)
>>             printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
>>                     drive->name, stat);

>> I would really prefer fixing ATAPI case while we are at it
>> (+ this would also get rid of code duplication).

>> IOW:

>> - in patch #1 we would add ->resetproc call

>    I would first like to hear an explanation of what it does...

    I have to NAK this resetproc() addition. It tries to do things that it's 
not designed to do. We should instead try soft-resetting the channel...

>> - in patch #2 we would remove 'cmd == ATA_CMD_ID_ATAPI' check

>    Why? Does issuing ATA_CMD_DEV_RESET to hard drives make sense?

>> Care to revise your patch?

    I see no point in "revising" this hack now...

>> Thanks,
>> Bart

MBR, Sergei

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

* Re: [RFC]hpt366/ide-probe  reset drive on probe error.
  2009-05-08 14:07     ` Bartlomiej Zolnierkiewicz
@ 2009-05-08 15:29       ` Sergei Shtylyov
  0 siblings, 0 replies; 9+ messages in thread
From: Sergei Shtylyov @ 2009-05-08 15:29 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz; +Cc: Karl Hiramoto, linux-ide

Bartlomiej Zolnierkiewicz wrote:

>>>>diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
>>>>index 3377766..ba4b802 100644
>>>>--- a/drivers/ide/hpt366.c
>>>>+++ b/drivers/ide/hpt366.c
>>>>@@ -1280,6 +1280,31 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
>>>> 	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
>>>> }
>>>> 
>>>>+/** routine to reset disk
>>>>+ *
>>>>+ * Since SUN Cobalt is attempting to do this operation, I should disclose
>>>>+ * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
>>>>+ * HOTSWAP ATA Infrastructure.
>>>>+ */
>>>>+
>>>>+static void hpt3xx_reset (ide_drive_t *drive)
>>>>+{
>>>>+	ide_hwif_t *hwif = drive->hwif;
>>>>+	struct pci_dev *dev = to_pci_dev(hwif->dev);
>>>>+	unsigned long high_16;
>>>>+	u8 reset;
>>>>+	u8 reg59h = 0;
>>>>+
>>>>+	printk(KERN_INFO "%s reset drive channel %d\n", __func__, hwif->channel);
>>>>+	high_16 = pci_resource_start(dev, 4);
>>>>+
>>>>+	reset = hwif->channel ? 0x80 : 0x40;
>>>>+
>>>>+	pci_read_config_byte(dev, 0x59, &reg59h);
>>>>+	pci_write_config_byte(dev, 0x59, reg59h|reset);
>>>>+	pci_write_config_byte(dev, 0x59, reg59h);
>>>>+}
>>>>+
>>>> static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
>>>> {
>>>> 	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
>>>>@@ -1406,6 +1431,7 @@ static const struct ide_port_ops hpt3xx_port_ops = {
>>>> 	.set_pio_mode		= hpt3xx_set_pio_mode,
>>>> 	.set_dma_mode		= hpt3xx_set_mode,
>>>> 	.quirkproc		= hpt3xx_quirkproc,
>>>>+	.resetproc		= hpt3xx_reset,
>>>> 	.maskproc		= hpt3xx_maskproc,
>>>> 	.mdma_filter		= hpt3xx_mdma_filter,
>>>> 	.udma_filter		= hpt3xx_udma_filter,
>>>>diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
>>>>index 7f264ed..09295b4 100644
>>>>--- a/drivers/ide/ide-probe.c
>>>>+++ b/drivers/ide/ide-probe.c
>>>>@@ -367,6 +367,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>>>> {
>>>> 	ide_hwif_t *hwif = drive->hwif;
>>>> 	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
>>>>+	const struct ide_port_ops *port_ops = hwif->port_ops;
>>>> 	u16 *id = drive->id;
>>>> 	int rc;
>>>> 	u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
>>>>@@ -427,9 +428,20 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>>>> 		/* ensure drive IRQ is clear */
>>>> 		stat = tp_ops->read_status(hwif);
>>>> 
>>>>-		if (rc == 1)
>>>>+		if (rc == 1) {
>>>> 			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
>>>> 					drive->name, stat);
>>>>+
>>>>+			if (port_ops->resetproc) {
>>>>+				port_ops->resetproc(drive);
>>>>+				msleep(50);
>>>>+			}
>>>>+			tp_ops->dev_select(drive);
>>>>+			msleep(50);
>>>>+			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
>>>>+			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
>>>>+			rc = ide_dev_read_id(drive, cmd, id);
>>>>+		}
>>>> 	} else {
>>>> 		/* not present or maybe ATAPI */
>>>> 		rc = 3;
>>>
>>>Since the current code in ide-probe.c looks like this:
>>>
>>>		stat = tp_ops->read_status(hwif);
>>>
>>>		if (stat == (ATA_BUSY | ATA_DRDY))
>>>			return 4;
>>>
>>>		if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
>>>			printk(KERN_ERR "%s: no response (status = 0x%02x), "
>>>					"resetting drive\n", drive->name, stat);
>>>			msleep(50);
>>>			tp_ops->dev_select(drive);
>>>			msleep(50);
>>>			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
>>>			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
>>>			rc = ide_dev_read_id(drive, cmd, id);
>>>		}
>>>
>>>		/* ensure drive IRQ is clear */
>>>		stat = tp_ops->read_status(hwif);
>>>
>>>		if (rc == 1)
>>>			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
>>>					drive->name, stat);
>>>
>>>I would really prefer fixing ATAPI case while we are at it
>>>(+ this would also get rid of code duplication).
>>>
>>>IOW:
>>>
>>>- in patch #1 we would add ->resetproc call
>>>
>>>- in patch #2 we would remove 'cmd == ATA_CMD_ID_ATAPI' check
>>
>>[ looking a bit closer at the code in ide-probe.c ]
>>
>>- in patch #2 we would move the ATAPI check to cover device selection/reset
>>  inside 'if ()' block

> Sigh, this is even more complicated...

> We should defer ->resetproc call until both drives are probed and do the
> port reset after probing both drives given that:

    We should just reset the port (and call resetproc() as a part of that). 
The resetproc() change should not be needed.

> - we didn't detect any devices

> and 

> - for one of devices do_probe() returned '1' (== "no response")

> Also it would greatly help to clean/fix return values of do_probe()
> and probe_for_drive() before doing the real changes.

    Sounds like the plan. :-)

> Thanks,
> Bart

MBR, Sergei

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

* Re: [RFC]hpt366/ide-probe  reset drive on probe error.
  2009-05-08 15:13     ` Sergei Shtylyov
@ 2009-05-09 12:09       ` Karl Hiramoto
  2009-05-09 16:07         ` Bartlomiej Zolnierkiewicz
  0 siblings, 1 reply; 9+ messages in thread
From: Karl Hiramoto @ 2009-05-09 12:09 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Bartlomiej Zolnierkiewicz, linux-ide

Sergei Shtylyov wrote:
> Hello, I wrote:
>
>>>> +
>>>> +    reset = hwif->channel ? 0x80 : 0x40;
>
>>    These HighPoint's "soft reset" (WTF does that mean I wonder?) bits 
>> are not the same between HPT366 and HPT370, so this code doesn't look 
>> right...
>
>    Ah, these "soft" reset bits correspond to PRST_/SRST_ signals which 
> are really primary/secondary channel hard resets (RESET- signal). This 
> explains everything; and this patch is a pure hack then.
>
>>>> +
>>>> +    pci_read_config_byte(dev, 0x59, &reg59h);
>>>> +    pci_write_config_byte(dev, 0x59, reg59h|reset);
>>>> +    pci_write_config_byte(dev, 0x59, reg59h);
>>>> +}
>>>> +
>>>> static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
>>>> {
>>>>     struct hpt_info *info    = hpt3xx_get_info(hwif->dev);
>>>> @@ -1406,6 +1431,7 @@ static const struct ide_port_ops 
>>>> hpt3xx_port_ops = {
>>>>     .set_pio_mode        = hpt3xx_set_pio_mode,
>>>>     .set_dma_mode        = hpt3xx_set_mode,
>>>>     .quirkproc        = hpt3xx_quirkproc,
>>>> +    .resetproc        = hpt3xx_reset,
>>>>     .maskproc        = hpt3xx_maskproc,
>>>>     .mdma_filter        = hpt3xx_mdma_filter,
>>>>     .udma_filter        = hpt3xx_udma_filter,
>>>> diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
>>>> index 7f264ed..09295b4 100644
>>>> --- a/drivers/ide/ide-probe.c
>>>> +++ b/drivers/ide/ide-probe.c
>>>> @@ -367,6 +367,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>>>> {
>>>>     ide_hwif_t *hwif = drive->hwif;
>>>>     const struct ide_tp_ops *tp_ops = hwif->tp_ops;
>>>> +    const struct ide_port_ops *port_ops = hwif->port_ops;
>>>>     u16 *id = drive->id;
>>>>     int rc;
>>>>     u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
>>>> @@ -427,9 +428,20 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
>>>>         /* ensure drive IRQ is clear */
>>>>         stat = tp_ops->read_status(hwif);
>>>>
>>>> -        if (rc == 1)
>>>> +        if (rc == 1) {
>>>>             printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
>>>>                     drive->name, stat);
>>>> +
>>>> +            if (port_ops->resetproc) {
>>>> +                port_ops->resetproc(drive);
>>>> +                msleep(50);
>
>>    Karl, why are you calling resetproc() without doing a reset? What 
>> this achieves?
>
>    To reset the drives, apparently. But it's not the function of 
> resetproc(). We should try soft-reset instead.
>
Yes, to reset the drive that does not respond.

>>>> +            }
>>>> +            tp_ops->dev_select(drive);
>>>> +            msleep(50);
>>>> +            tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
>>>> +            (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
>>>> +            rc = ide_dev_read_id(drive, cmd, id);
>>>> +        }
>>>>     } else {
>>>>         /* not present or maybe ATAPI */
>>>>         rc = 3;
>
>>> Since the current code in ide-probe.c looks like this:
>
>>>         stat = tp_ops->read_status(hwif);
>>>
>>>         if (stat == (ATA_BUSY | ATA_DRDY))
>>>             return 4;
>>>
>>>         if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
>>>             printk(KERN_ERR "%s: no response (status = 0x%02x), "
>>>                     "resetting drive\n", drive->name, stat);
>>>             msleep(50);
>>>             tp_ops->dev_select(drive);
>>>             msleep(50);
>>>             tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
>>>             (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
>>>             rc = ide_dev_read_id(drive, cmd, id);
>>>         }
>>>
>>>         /* ensure drive IRQ is clear */
>>>         stat = tp_ops->read_status(hwif);
>>>
>>>         if (rc == 1)
>>>             printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
>>>                     drive->name, stat);
>
>>> I would really prefer fixing ATAPI case while we are at it
>>> (+ this would also get rid of code duplication).
>
>>> IOW:
>
>>> - in patch #1 we would add ->resetproc call
>
>>    I would first like to hear an explanation of what it does...
>
>    I have to NAK this resetproc() addition. It tries to do things that 
> it's not designed to do. We should instead try soft-resetting the 
> channel...

Where should the soft reset be done, for this to not be called a hack?   
should it be in ide_port_ops->reset_poll?
>
>>> Care to revise your patch?
>
>    I see no point in "revising" this hack now...

Why not reset the drive if it does not respond?  OK, you could blame 
this on a bugy board, or redboot that does not reset the drive on warm 
boot if it is busy.


--
Karl

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

* Re: [RFC]hpt366/ide-probe  reset drive on probe error.
  2009-05-09 12:09       ` Karl Hiramoto
@ 2009-05-09 16:07         ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 9+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2009-05-09 16:07 UTC (permalink / raw)
  To: Karl Hiramoto; +Cc: Sergei Shtylyov, linux-ide

On Saturday 09 May 2009 14:09:05 Karl Hiramoto wrote:
> Sergei Shtylyov wrote:

[...]

> >>> Care to revise your patch?
> >
> >    I see no point in "revising" this hack now...
> 
> Why not reset the drive if it does not respond?  OK, you could blame 
> this on a bugy board, or redboot that does not reset the drive on warm 
> boot if it is busy.

Please read the whole discussion between Sergei & me before getting
discouraged by our occasional use of the vivid language. ;)

Your idea is good but the current implementation needs to be reworked
into a form which doesn't duplicate the code and which would work also
for other hardware setups.

The nice starting point is sanitizing return values of do_probe()
and probe_for_drive(), and then making sure that they are propagated
correctly to higher level.  Once this is done we can use those values
in ide_probe_port() to reset and re-probe the port if necessary.

[ I think that the port reset itself would be best realized by reusing
  the existing code from do_reset1() (plese see the code for SRST near
  the end of this function). ]

Thanks,
Bart

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

end of thread, other threads:[~2009-05-09 16:04 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-05 14:53 [RFC]hpt366/ide-probe reset drive on probe error Karl Hiramoto
2009-05-08 13:50 ` Bartlomiej Zolnierkiewicz
2009-05-08 13:57   ` Bartlomiej Zolnierkiewicz
2009-05-08 14:07     ` Bartlomiej Zolnierkiewicz
2009-05-08 15:29       ` Sergei Shtylyov
2009-05-08 14:57   ` Sergei Shtylyov
2009-05-08 15:13     ` Sergei Shtylyov
2009-05-09 12:09       ` Karl Hiramoto
2009-05-09 16:07         ` Bartlomiej Zolnierkiewicz

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).