pata_it821x: sync with IDE it821x driver
PATCH 1/1 pata_it821x: sync with IDE it821x driver
* fix PIO setup for devices with different PIO speeds in passthru mode
IT821x allows one PIO setting per port se we have to limit maximum PIO mode to the one of the slowest device on the port.
* (partially) fix DMA in RAID mode
Code intended to check DMA status was checking DMA command register. Moreover firmware seems to "forget" to set DMA capable bit for the slave device (at least in RAID mode but without ITE RAID volumes) so check device ID for DMA capable bit when deciding whether to use DMA and remove DMA status check completely.
Thanks to Pavol Šimo for the bugreport and testing the initial fix.
This change unfortunately still doesn't fix DMA in RAID mode (which works fine with IDE it821x) but Alan is working on the missing pieces (pata_it821x vs libata EH issues).
---
drivers/ata/pata_it821x.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
drivers/ata/pata_it821x.c +10 -9
@@ -2,6 +2,7 @@* pata_it821x.c - IT821x PATA for new ATA layer * (C) 2005 Red Hat Inc * Alan Cox <[email protected]> +* (C) 2007 Bartlomiej Zolnierkiewicz * * based upon *
@@ -79,7 +80,7 @@#define DRV_NAME "pata_it821x" -#define DRV_VERSION "0.3.6" +#define DRV_VERSION "0.3.7"struct it821x_dev {
@@ -258,8 +259,14 @@ static void it821x_passthru_set_piomode(static const u8 pio_want[] = {ATA_66 ,ATA_66 ,ATA_66 ,ATA_66 ,ATA_ANY };struct it821x_dev *itdev = ap->private_data; +struct ata_device *pair =ata_dev_pair (adev);int unit = adev->devno; -int mode_wanted = adev->pio_mode -XFER_PIO_0 ; +int mode_wanted = adev->pio_mode; + +if (pair && adev->pio_mode > pair->pio_mode) + mode_wanted = pair->pio_mode; + + mode_wanted -=XFER_PIO_0 ;/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ itdev->want[unit][1 ] = pio_want[mode_wanted];
@@ -460,14 +467,8 @@ static unsigned int it821x_passthru_qc_istatic int it821x_smart_set_mode (struct ata_port *ap,struct ata_device **unused) { -int dma_enabled =0 ;int i; -/* Bits 5 and 6 indicate if DMA is active on master/slave */ -/* It is possible that BMDMA isn't allocated */ -if (ap->ioaddr.bmdma_addr) - dma_enabled =ioread8 (ap->ioaddr.bmdma_addr +ATA_DMA_CMD ); -for (i =0 ; i <ATA_MAX_DEVICES ; i++) {struct ata_device *dev = &ap->device[i];if (ata_dev_enabled (dev)) {
@@ -476,7 +477,7 @@ static int it821x_smart_set_mode(struct dev->dma_mode =XFER_MW_DMA_0 ;/* We do need the right mode information for DMA or PIO and this comes from the current configuration flags */ -if (dma_enabled & (1 << (5 + i))) { +if (ata_id_has_dma (dev->id)) {ata_dev_printk (dev,KERN_INFO ,"configured for DMA\n" ); dev->xfer_mode =XFER_MW_DMA_0 ; dev->xfer_shift =ATA_SHIFT_MWDMA ;
Hello,
Quoted 9 lines · Bartlomiej Zolnierkiewicz
* (partially) fix DMA in RAID mode
Code intended to check DMA status was checking DMA command register. Moreover firmware seems to "forget" to set DMA capable bit for the slave device (at least in RAID mode but without ITE RAID volumes) so check device ID for DMA capable bit when deciding whether to use DMA and remove DMA status check completely.
Thanks to Pavol Šimo for the bugreport and testing the initial fix.
Ah... This is the mysterious mwdma configuration in smart mode, right? Thanks for fixing this.
Quoted 3 lines
This change unfortunately still doesn't fix DMA in RAID mode (which works fine with IDE it821x) but Alan is working on the missing pieces (
pata_it821xvs libata EH issues).
This is the lbal/nsect SRST problem, right?
drivers/ata/pata_it821x.c static void it821x_passthru_set_piomode( · line 269
Quoted 13 lines
drivers/ata/pata_it821x.c +7
-1@@ -258,8 +259,14 @@ static void it821x_passthru_set_piomode(static const u8 pio_want[] = {ATA_66 ,ATA_66 ,ATA_66 ,ATA_66 ,ATA_ANY };struct it821x_dev *itdev = ap->private_data; +struct ata_device *pair =ata_dev_pair (adev);int unit = adev->devno; -int mode_wanted = adev->pio_mode -XFER_PIO_0 ; +int mode_wanted = adev->pio_mode; + +if (pair && adev->pio_mode > pair->pio_mode) + mode_wanted = pair->pio_mode; + + mode_wanted -=XFER_PIO_0 ;
I think this is better done by mode_filter callback which is guaranteed to be called before any actual mode configuration is performed and in device order (master then slave).
Thanks.
Signature · 1 line
tejun
Hello,
Quoted 11 lines · Tejun Heo
Hello,
Quoted 8 lines · Bartlomiej Zolnierkiewicz
* (partially) fix DMA in RAID mode
Code intended to check DMA status was checking DMA command register. Moreover firmware seems to "forget" to set DMA capable bit for the slave device (at least in RAID mode but without ITE RAID volumes) so check device ID for DMA capable bit when deciding whether to use DMA and remove DMA status check completely.
Quoted 3 lines
Quoted 1 line
Thanks to Pavol Šimo for the bugreport and testing the initial fix.
Ah... This is the mysterious mwdma configuration in smart mode, right?
Yep.
Quoted 7 lines
Thanks for fixing this.
Quoted 3 lines
This change unfortunately still doesn't fix DMA in RAID mode (which works fine with IDE it821x) but Alan is working on the missing pieces (
pata_it821xvs libata EH issues).This is the lbal/nsect SRST problem, right?
I think so, due to lack of time I'm not following libata discussions closely.
Quoted 17 lines
drivers/ata/pata_it821x.c static void it821x_passthru_set_piomode( · line 269
Quoted 13 lines
drivers/ata/pata_it821x.c +7
-1@@ -258,8 +259,14 @@ static void it821x_passthru_set_piomode(static const u8 pio_want[] = {ATA_66 ,ATA_66 ,ATA_66 ,ATA_66 ,ATA_ANY };struct it821x_dev *itdev = ap->private_data; +struct ata_device *pair =ata_dev_pair (adev);int unit = adev->devno; -int mode_wanted = adev->pio_mode -XFER_PIO_0 ; +int mode_wanted = adev->pio_mode; + +if (pair && adev->pio_mode > pair->pio_mode) + mode_wanted = pair->pio_mode; + + mode_wanted -=XFER_PIO_0 ;I think this is better done by
mode_filtercallback which is guaranteed to be called before any actual mode configuration is performed and in device order (master then slave).
I was thinking about using ->mode_filter but since all other PATA host drivers are doing PIO filtering in ->set_piomode methods and also since it seemed that using ->mode_filter method would result in slightly more complex code I opted for coherency / simplicity. However if you (or somebody else) want to make a follow-up change to this driver (and preferably other PATA host drivers ie. pata_sil680) to use ->mode_filter I'm also fine with that.
Thanks,
Bart
Quoted 17 lines · Bartlomiej Zolnierkiewicz
Quoted 16 lines
drivers/ata/pata_it821x.c static void it821x_passthru_set_piomode( · line 269
Quoted 13 lines
drivers/ata/pata_it821x.c +7
-1@@ -258,8 +259,14 @@ static void it821x_passthru_set_piomode(static const u8 pio_want[] = {ATA_66 ,ATA_66 ,ATA_66 ,ATA_66 ,ATA_ANY };struct it821x_dev *itdev = ap->private_data; +struct ata_device *pair =ata_dev_pair (adev);int unit = adev->devno; -int mode_wanted = adev->pio_mode -XFER_PIO_0 ; +int mode_wanted = adev->pio_mode; + +if (pair && adev->pio_mode > pair->pio_mode) + mode_wanted = pair->pio_mode; + + mode_wanted -=XFER_PIO_0 ;I think this is better done by
mode_filtercallback which is guaranteed to be called before any actual mode configuration is performed and in device order (master then slave).
Quoted 6 lines
I was thinking about using ->mode_filter but since all other PATA host drivers are doing PIO filtering in ->set_piomode methods and also since it seemed that using ->mode_filter method would result in slightly more complex code I opted for coherency / simplicity. However if you (or somebody else) want to make a follow-up change to this driver (and preferably other PATA host drivers ie.
pata_sil680) to use ->mode_filter I'm also fine with that.
Hmmm... indeed. Alan, is there any reason we do that in ->set_piomode not ->mode_filter? We end up with mismatching configuration between the controller and the higher speed drive.
Signature · 1 line
tejun
Quoted 3 lines
Hmmm... indeed. Alan, is there any reason we do that in ->set_piomode not ->mode_filter? We end up with mismatching configuration between the controller and the higher speed drive.
We always talk more slowly than the drive which is just fine. Just about every device on every controller does some variant of this, usually just for the address setup timings. Our current behaviour (both old and new IDE) may actually not be conservative enough for register rather than data timings, which quite possibly should always be at the lower speed.
Currently the PATA drivers use mode_filter to remove modes not allowed due to hardware issues/flaws/etc and a mix of their own timer merging and the intelligence in the ata_timing functions to work out what timing pattern should be used.
Beyond looking further into the register load timings and maybe making the 8bit timings more conseratively merged (as Sergei I think feels they should be) I don't plan to change this.
Alan
drivers/ata/pata_it821x.c static void it821x_passthru_set_piomode( · line 269
Quoted 13 lines
drivers/ata/pata_it821x.c +7
-1@@ -258,8 +259,14 @@ static void it821x_passthru_set_piomode(static const u8 pio_want[] = {ATA_66 ,ATA_66 ,ATA_66 ,ATA_66 ,ATA_ANY };struct it821x_dev *itdev = ap->private_data; +struct ata_device *pair =ata_dev_pair (adev);int unit = adev->devno; -int mode_wanted = adev->pio_mode -XFER_PIO_0 ; +int mode_wanted = adev->pio_mode; + +if (pair && adev->pio_mode > pair->pio_mode) + mode_wanted = pair->pio_mode; + + mode_wanted -=XFER_PIO_0 ;
NAK this too
Please see it821x_program.
it821x_passthru_set_piomode computes the required mode and the preferred clock for the modeit821x_clock_strategy the computes the best clock to use it821x_program the programs the device
Whenever we issue a command it821x_passthru_dev_select then does a timing mode switch and loads the PIO timing before doing the dev_select. The same is also done when doing a qc_issue_prot so each qc_issue will have the right timings loaded for the device.
So if you've got a problem case your diagnosis isn't one that makes a lot of sense, and the fix is clearly wrong but I've not seen most of the discussion between you and whoever you worked with to judge why.
One obvious possibility is that we are not currently doing timing clipping for the address setup and merge for the 8bit timings. However the docs I have strongly imply that the IT821x PIO/MWDMA timing register is for data cycles only.
The other would be that there is some kind of pattern of interaction between the ATA midlayer and the driver causing the wrong timings to get loaded at some point.
Your "fix" would happen to work for both of these cases, but is wrong for both of them.
If the register is switching all the timings then the fix is to switch the PIO timing loaded to the lowest of the two initially (in _program) and flip it back to the correct value at the start of the data transfer sequence. We can then flip it back next qc_issue or indeed at the end of the data xfer
If we've got an interaction problem then we need proper traces with LIBATA debug turned right up so we can fix the actual case where the switching occurs wrongly.
Alan
Hi Alan!
Quoted 15 lines · Alan Cox
drivers/ata/pata_it821x.c static void it821x_passthru_set_piomode( · line 269
Quoted 13 lines
drivers/ata/pata_it821x.c +7
-1@@ -258,8 +259,14 @@ static void it821x_passthru_set_piomode(static const u8 pio_want[] = {ATA_66 ,ATA_66 ,ATA_66 ,ATA_66 ,ATA_ANY };struct it821x_dev *itdev = ap->private_data; +struct ata_device *pair =ata_dev_pair (adev);int unit = adev->devno; -int mode_wanted = adev->pio_mode -XFER_PIO_0 ; +int mode_wanted = adev->pio_mode; + +if (pair && adev->pio_mode > pair->pio_mode) + mode_wanted = pair->pio_mode; + + mode_wanted -=XFER_PIO_0 ;NAK this too
OK, I'm able to understand the meaning of "NAK" [1] but "this too"?
[1] http://ozlabs.org/~rusty/index.cgi/2007/05/04
;)
Quoted 34 lines
Please see
it821x_program.
it821x_passthru_set_piomodecomputes the required mode and the preferred clock for the modeit821x_clock_strategythe computes the best clock to useit821x_programthe programs the deviceWhenever we issue a command
it821x_passthru_dev_selectthen does a timing mode switch and loads the PIO timing before doing thedev_select. The same is also done when doing aqc_issue_protso eachqc_issuewill have the right timings loaded for the device.So if you've got a problem case your diagnosis isn't one that makes a lot of sense, and the fix is clearly wrong but I've not seen most of the discussion between you and whoever you worked with to judge why.
One obvious possibility is that we are not currently doing timing clipping for the address setup and merge for the 8bit timings. However the docs I have strongly imply that the IT821x PIO/MWDMA timing register is for data cycles only.
The other would be that there is some kind of pattern of interaction between the ATA midlayer and the driver causing the wrong timings to get loaded at some point.
Your "fix" would happen to work for both of these cases, but is wrong for both of them.
If the register is switching all the timings then the fix is to switch the PIO timing loaded to the lowest of the two initially (in
_program) and flip it back to the correct value at the start of the data transfer sequence. We can then flip it back nextqc_issueor indeed at the end of the data xfer
Quoted 3 lines
If we've got an interaction problem then we need proper traces with LIBATA debug turned right up so we can fix the actual case where the switching occurs wrongly.
PIO fix was directly ported from my it821x.c patch. I now see that thanks to it821x_passthru_dev_select() it is not really needeed in pata_it821x.c.
OTOH DMA fixes are pata_it821x.c unique, I will respin the patch.
Bart
Quoted 3 lines
Quoted 1 line
NAK this too
OK, I'm able to understand the meaning of "NAK" [1] but "this too"?
That was me being confusing with something else I NAKked that wasn't from you. It may have made sense to Jeff but not you - sorry
Quoted 2 lines
PIO fix was directly ported from my
it821x.cpatch. I now see that thanks toit821x_passthru_dev_select()it is not really needeed inpata_it821x.c.
I don't think its needed but if we see problems with some drive mixes its worth further debug. One nice thing about libata is the qc interfaces make it possibly to do clock switches very cleanly.
Alan