libata: implement per-dev xfer masks
PATCH 1/4 libata: implement ata_unpack_xfermask()
In reply to Tejun HeoImplement ata_unpack_xfermask().
---
drivers/scsi/libata-core.c | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+), 0 deletions(-)
70ca1eb15f59fa81dc3dd8b8eaff40f7b4e07c95
drivers/scsi/libata-core.c +23 -0
@@ -252,6 +252,29 @@ static unsigned int ata_pack_xfermask(un ((udma_mask <<ATA_SHIFT_UDMA ) &ATA_MASK_UDMA ); } +/** +* ata_unpack_xfermask - Unpack xfer_mask into pio, mwdma and udma masks +* @xfer_mask: xfer_mask to unpack +* @pio_mask: resulting pio_mask +* @mwdma_mask: resulting mwdma_mask +* @udma_mask: resulting udma_mask +* +* Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask. +* Any NULL distination masks will be ignored. +*/ +static void ata_unpack_xfermask (unsigned int xfer_mask, +unsigned int *pio_mask, +unsigned int *mwdma_mask, +unsigned int *udma_mask) +{ +if (pio_mask) + *pio_mask = (xfer_mask &ATA_MASK_PIO ) >>ATA_SHIFT_PIO ; +if (mwdma_mask) + *mwdma_mask = (xfer_mask &ATA_MASK_MWDMA ) >>ATA_SHIFT_MWDMA ; +if (udma_mask) + *udma_mask = (xfer_mask &ATA_MASK_UDMA ) >>ATA_SHIFT_UDMA ; +} + static const struct ata_xfer_ent { unsigned int shift, bits; u8 base;
Signature · 1 line
1.2.4
PATCH 2/4 libata: implement ata_dev_init()
In reply to Tejun HeoImplement ata_dev_init() which is called before probing for new device. Note that ata_dev_init() is called only once for each attached device while ata_dev_configure() can be called multiple times for the same device.
This change will be used by following per-dev xfer_mask patch.
---
drivers/scsi/libata-core.c | 33 +++++++++++++++++++++++++-------- 1 files changed, 25 insertions(+), 8 deletions(-)
85ebfaba5b9f0c02afa9a3a2bde8eb6bf14380d4
drivers/scsi/libata-core.c +25 -8
@@ -1042,6 +1042,25 @@ unsigned int ata_pio_need_iordy(const st }/** +* ata_dev_init - initialize ata_device structure +* @ap: Port on which target device resides +* @dev: Target device to initialize +* +* Initialize @dev in preparation for device probing. This +* function is called only when a new device is about to be +* probed. ie. ata_dev_configure() is responsible for cleaning +* up affected fields across revalidations. +* +* LOCKING: +* none. +*/ +static void ata_dev_init (struct ata_port *ap,struct ata_device *dev) +{ +memset (dev,0 ,sizeof (*dev)); + dev->devno = dev - ap->device; +} + +/** * ata_dev_read_id - Read ID data from the specified device * @ap: port on which target device resides * @dev: target device
@@ -1367,11 +1386,14 @@ static int ata_bus_probe(struct ata_portata_port_probe (ap); +/* initialize devices and classes */ +for (i =0 ; i <ATA_MAX_DEVICES ; i++) { +ata_dev_init (ap, &ap->device[i]); + classes[i] =ATA_DEV_UNKNOWN ; + } +/* reset */ if (ap->ops->probe_reset) { -for (i =0 ; i <ATA_MAX_DEVICES ; i++) - classes[i] =ATA_DEV_UNKNOWN ; - rc = ap->ops->probe_reset (ap, classes);if (rc) {printk ("ata%u: reset failed (errno=%d)\n" , ap->id, rc);
@@ -4606,8 +4628,6 @@ static void ata_host_init(struct ata_porstruct ata_host_set *host_set, const struct ata_probe_ent *ent, unsigned int port_no) { - unsigned int i; - host->max_id = 16; host->max_lun =1 ; host->max_channel =1 ;
@@ -4634,9 +4654,6 @@ static void ata_host_init(struct ata_porINIT_WORK (&ap->port_task,NULL ,NULL );INIT_LIST_HEAD (&ap->eh_done_q); -for (i =0 ; i <ATA_MAX_DEVICES ; i++) - ap->device[i].devno = i; -#ifdef ATA_IRQ_TRAP ap->stats.unhandled_irq =1 ; ap->stats.idle_irq =1 ;
Signature · 1 line
1.2.4
PATCH 3/4 libata: add per-dev pio/mwdma/udma_mask
In reply to Tejun HeoAdd per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug.
---
drivers/scsi/libata-core.c | 38 ++++++++++++++++++++++---------------- include/linux/libata.h | 5 +++++ 2 files changed, 27 insertions(+), 16 deletions(-)
ff1f6ace25a33e2338f7dc18a15951e7aa22c14f
drivers/scsi/libata-core.c +22 -16
@@ -65,8 +65,7 @@ static unsigned int ata_dev_init_params( struct ata_device *dev);static void ata_set_mode (struct ata_port *ap);static void ata_dev_set_xfermode (struct ata_port *ap,struct ata_device *dev); -static unsigned int ata_dev_xfermask (struct ata_port *ap, -struct ata_device *dev); +static void ata_dev_xfermask (struct ata_port *ap,struct ata_device *dev);static unsigned int ata_unique_id =1 ;static struct workqueue_struct *ata_wq;
@@ -1058,6 +1057,10 @@ static void ata_dev_init(struct ata_port {memset (dev,0 ,sizeof (*dev)); dev->devno = dev - ap->device; + + dev->pio_mask =UINT_MAX ; + dev->mwdma_mask =UINT_MAX ; + dev->udma_mask =UINT_MAX ; }/**
@@ -1825,16 +1828,19 @@ static void ata_set_mode(struct ata_port/* step 1: calculate xfer_mask */ for (i =0 ; i <ATA_MAX_DEVICES ; i++) {struct ata_device *dev = &ap->device[i]; -unsigned int xfer_mask; +unsigned int pio_mask, dma_mask;if (!ata_dev_present (dev))continue ; - xfer_mask =ata_dev_xfermask (ap, dev); +ata_dev_xfermask (ap, dev); + +/* TODO: let LLDD filter dev->*_mask here */ - dev->pio_mode =ata_xfer_mask2mode (xfer_mask &ATA_MASK_PIO ); - dev->dma_mode =ata_xfer_mask2mode (xfer_mask & (ATA_MASK_MWDMA | -ATA_MASK_UDMA )); + pio_mask =ata_pack_xfermask (dev->pio_mask,0 ,0 ); + dma_mask =ata_pack_xfermask (0 , dev->mwdma_mask, dev->udma_mask); + dev->pio_mode =ata_xfer_mask2mode (pio_mask); + dev->dma_mode =ata_xfer_mask2mode (dma_mask); }/* step 2: always set host PIO timings */
@@ -2643,18 +2649,15 @@ static int ata_dma_blacklisted(const str* @ap: Port on which the device to compute xfermask for resides * @dev: Device to compute xfermask for * -* Compute supported xfermask of @dev. This function is -* responsible for applying all known limits including host -* controller limits, device blacklist, etc... +* Compute supported xfermask of @dev and store it in +* dev->*_mask. This function is responsible for applying all +* known limits including host controller limits, device +* blacklist, etc... * * LOCKING: * None. -* -* RETURNS: -* Computed xfermask. */ -static unsigned int ata_dev_xfermask (struct ata_port *ap, -struct ata_device *dev) +static void ata_dev_xfermask (struct ata_port *ap,struct ata_device *dev) {unsigned long xfer_mask;int i;
@@ -2667,6 +2670,8 @@ static unsigned int ata_dev_xfermask(strstruct ata_device *d = &ap->device[i];if (!ata_dev_present (d))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 );
@@ -2676,7 +2681,8 @@ static unsigned int ata_dev_xfermask(strprintk (KERN_WARNING "ata%u: dev %u is on DMA blacklist, " "disabling DMA\n" , ap->id, dev->devno); -return xfer_mask; +ata_unpack_xfermask (xfer_mask, &dev->pio_mask, &dev->mwdma_mask, + &dev->udma_mask); }/**
include/linux/libata.h +5 -0
@@ -358,6 +358,11 @@ struct ata_device {unsigned int max_sectors;/* per-device max sectors */ unsigned int cdb_len; +/* per-dev xfer mask */ +unsigned int pio_mask; +unsigned int mwdma_mask; +unsigned int udma_mask; +/* for CHS addressing */ u16 cylinders;/* Number of cylinders */ u16 heads;/* Number of heads */
Signature · 1 line
1.2.4
PATCH 1/1 libata: implement per-dev xfer masks
Hello, all.
This patchset adds per-dev pio, mwdma and udma_mask. Because port-wide xfer_mask is currently used, this patch does not change any behavior. Per-dev xfer masks will also be used by EH to slow down devices suffering frequent transmission errors.
I marked with comment where the mode filtering for low level drivers should be done but I'm not sure how the interface should look like. ->pre_set_mode(ap) is okay but then the LLDD should iterate over all devices. Maybe ->pre_set_mode(ap, dev) or ->filter_xfer_mask(ap, dev)?
The patchset is against the current #upstream[1].
Thanks.
--
tejun
[1] 418dc1f5a805822fcf1118804ddc689a4156db4a
PATCH 4/4 libata: make per-dev transfer mode limits per-dev
Now that each ata_device has xfer masks, per-dev limits can be made per-dev instead of per-port. Make per-dev limits per-dev.
---
drivers/scsi/libata-core.c | 2 +- drivers/scsi/sata_sil.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
c54ae650a5eeee6dc67e32b52be23d29f8e4d16f
drivers/scsi/libata-core.c +1 -1
@@ -1350,7 +1350,7 @@ static int ata_dev_configure(struct ata_if (print_info)printk (KERN_INFO "ata%u(%u): applying bridge limits\n" , ap->id, dev->devno); - ap->udma_mask &=ATA_UDMA5 ; + dev->udma_mask &=ATA_UDMA5 ; dev->max_sectors =ATA_MAX_SECTORS ; }
drivers/scsi/sata_sil.c +1 -1
@@ -372,7 +372,7 @@ static void sil_dev_config(struct ata_poif (quirks &SIL_QUIRK_UDMA5MAX ) {printk (KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n" , ap->id, dev->devno, model_num); - ap->udma_mask &=ATA_UDMA5 ; + dev->udma_mask &=ATA_UDMA5 ;return ; } }
Signature · 1 line
1.2.4
Quoted 2 lines · Tejun Heo
I marked with comment where the mode filtering for low level drivers should be done but I'm not sure how the interface should look like.
Currently the libata pata patch code calls a filter function if present which returns an updated bitmap for the mode type. I did that because we need to combine the cable, bridge, core and chip specific rules neatly and not have one forcing a mode the other cannot do.
Quoted 2 lines
->pre_set_mode(ap) is okay but then the LLDD should iterate over all devices. Maybe ->pre_set_mode(ap, dev) or ->filter_xfer_mask(ap, dev)?
Providing
1. The proposed speeds are set for both devices on the cable before the
call.
2. We reselect the speed of both devices on changedown or hotplug
then we should be just fine.
Quoted 8 lines · Alan Cox
Quoted 2 lines · Tejun Heo
I marked with comment where the mode filtering for low level drivers should be done but I'm not sure how the interface should look like.
Currently the libata pata patch code calls a filter function if present which returns an updated bitmap for the mode type. I did that because we need to combine the cable, bridge, core and chip specific rules neatly and not have one forcing a mode the other cannot do.
Understood.
Quoted 10 lines
Quoted 2 lines
->pre_set_mode(ap) is okay but then the LLDD should iterate over all devices. Maybe ->pre_set_mode(ap, dev) or ->filter_xfer_mask(ap, dev)?
Providing
1. The proposed speeds are set for both devices on the cable before the
call.
2. We reselect the speed of both devices on changedown or hotplugthen we should be just fine.
Yeap, both will hold. I'll just leave it as it is such that filtering callback can be added later when merging PATA code. One concern I have about the originally proposed ->mode_filter(ap, dev, mask, shift) interface is that if a LLDD wants to reject all UDMA and limit some of MWDMA, there is no way to do so. I think it's better and easier to filter all mode masks at once.
Thanks.
Signature · 1 line
tejun
PATCH 2/4 libata: implement ata_dev_init()
In reply to Tejun HeoImplement ata_dev_init() which is called before probing for new device. Note that ata_dev_init() is called only once for each attached device while ata_dev_configure() can be called multiple times for the same device.
This change will be used by following per-dev xfer_mask patch.
---
fix-class-handling-in-ata_bus_probe[1] patch clashes with this one. So, this is the regenerated patch. All others apply fine with offets.
[1] http://article.gmane.org/gmane.linux.ide/8712
libata-core.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-)
drivers/scsi/libata-core.c +22 -6
@@ -1045,6 +1045,25 @@ unsigned int ata_pio_need_iordy(const st }/** +* ata_dev_init - initialize ata_device structure +* @ap: Port on which target device resides +* @dev: Target device to initialize +* +* Initialize @dev in preparation for device probing. This +* function is called only when a new device is about to be +* probed. ie. ata_dev_configure() is responsible for cleaning +* up affected fields across revalidations. +* +* LOCKING: +* none. +*/ +static void ata_dev_init (struct ata_port *ap,struct ata_device *dev) +{ +memset (dev,0 ,sizeof (*dev)); + dev->devno = dev - ap->device; +} + +/** * ata_dev_read_id - Read ID data from the specified device * @ap: port on which target device resides * @dev: target device
@@ -1371,8 +1390,10 @@ static int ata_bus_probe(struct ata_portata_port_probe (ap);/* reset and determine device classes */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) +for (i =0 ; i <ATA_MAX_DEVICES ; i++) { +ata_dev_init (ap, &ap->device[i]); classes[i] =ATA_DEV_UNKNOWN ; + }if (ap->ops->probe_reset) { rc = ap->ops->probe_reset (ap, classes);
@@ -4607,8 +4628,6 @@ static void ata_host_init(struct ata_porstruct ata_host_set *host_set, const struct ata_probe_ent *ent, unsigned int port_no) { - unsigned int i; - host->max_id = 16; host->max_lun =1 ; host->max_channel =1 ;
@@ -4635,9 +4654,6 @@ static void ata_host_init(struct ata_porINIT_WORK (&ap->port_task,NULL ,NULL );INIT_LIST_HEAD (&ap->eh_done_q); -for (i =0 ; i <ATA_MAX_DEVICES ; i++) - ap->device[i].devno = i; -#ifdef ATA_IRQ_TRAP ap->stats.unhandled_irq =1 ; ap->stats.idle_irq =1 ;
Re: [PATCH 1/4] libata: implement ata_unpack_xfermask()
In reply to Tejun HeoQuoted 3 lines · Tejun Heo
Implement
ata_unpack_xfermask().Signed-off-by Tejun Heo <[email protected]>
ACK presuming it is still needed after comments...
Jeff Garzik
NAKRe: [PATCH 2/4] libata: implement ata_dev_init()
In reply to Tejun HeoQuoted 71 lines · Tejun Heo
Implement
ata_dev_init()which is called before probing for new device. Note thatata_dev_init()is called only once for each attached device whileata_dev_configure()can be called multiple times for the same device.This change will be used by following per-dev
xfer_maskpatch.Signed-off-by Tejun Heo <[email protected]>---
fix-class-handling-in-ata_bus_probe[1] patch clashes with this one. So, this is the regenerated patch. All others apply fine with offets.
[1] http://article.gmane.org/gmane.linux.ide/8712
libata-core.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-)Index:
work/drivers/scsi/libata-core.c
===================================================================drivers/scsi/libata-core.c +22
-3@@ -1045,6 +1045,25 @@ unsigned int ata_pio_need_iordy(const st }/** +* ata_dev_init - initialize ata_device structure +* @ap: Port on which target device resides +* @dev: Target device to initialize +* +* Initialize @dev in preparation for device probing. This +* function is called only when a new device is about to be +* probed. ie. ata_dev_configure() is responsible for cleaning +* up affected fields across revalidations. +* +* LOCKING: +* none. +*/ +static void ata_dev_init (struct ata_port *ap,struct ata_device *dev) +{ +memset (dev,0 ,sizeof (*dev)); + dev->devno = dev - ap->device; +} + +/** * ata_dev_read_id - Read ID data from the specified device * @ap: port on which target device resides * @dev: target device @@ -1371,8 +1390,10 @@ static int ata_bus_probe(struct ata_portata_port_probe (ap);/* reset and determine device classes */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) +for (i =0 ; i <ATA_MAX_DEVICES ; i++) { +ata_dev_init (ap, &ap->device[i]); classes[i] =ATA_DEV_UNKNOWN ; + }if (ap->ops->probe_reset) { rc = ap->ops->probe_reset (ap, classes);@@ -4607,8 +4628,6 @@ static void ata_host_init(struct ata_porstruct ata_host_set *host_set, const struct ata_probe_ent *ent, unsigned int port_no) { - unsigned int i; - host->max_id = 16; host->max_lun =1 ; host->max_channel =1 ;
drivers/scsi/libata-core.c static void ata_host_init(struct ata_por · line 4639
Quoted 5 lines
drivers/scsi/libata-core.c +0
-2@@ -4635,9 +4654,6 @@ static void ata_host_init(struct ata_porINIT_WORK (&ap->port_task,NULL ,NULL );INIT_LIST_HEAD (&ap->eh_done_q); -for (i =0 ; i <ATA_MAX_DEVICES ; i++) - ap->device[i].devno = i;
NAK:
1) the devices are embedded with ata_port, and so all static initialization should be done in ata_host_init(). It's only called once for each device, as you say, anyway... no need to separate it from the rest of the struct ata_port initialization AFAICS.
2) there is no need to memset() [unless you are re-initializing, I suppose]
Re: [PATCH 3/4] libata: add per-dev pio/mwdma/udma_mask
In reply to Tejun HeoQuoted 6 lines · Tejun Heo
Add per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug.
Signed-off-by Tejun Heo <[email protected]>
I don't see much value in the separation. Rather than 3 separate masks, it seems like this patch would be simplified if you simply added dev->xfer_mask.
Jeff
Re: [PATCH 4/4] libata: make per-dev transfer mode limits per-dev
In reply to Tejun HeoQuoted 4 lines · Tejun Heo
Now that each
ata_devicehas xfer masks, per-dev limits can be made per-dev instead of per-port. Make per-dev limits per-dev.Signed-off-by Tejun Heo <[email protected]>
Doesn't this patch break stuff? As you said in a previous patch, the per-dev masks aren't used yet?
Jeff
Re: [PATCH 2/4] libata: implement ata_dev_init()
In reply to Jeff GarzikQuoted 6 lines · Jeff Garzik
NAK:
1) the devices are embedded with
ata_port, and so all static initialization should be done inata_host_init(). It's only called once for each device, as you say, anyway... no need to separate it from the rest of the structata_portinitialization AFAICS.
I was mainly thinking of hotplug cases. dev liftime becomes different form ap lifetime in hotplug cases, so it needs reinitialization before recycling. I guess it can wait till we actually do hotplug. I'll drop this patch.
Quoted 1 line
2) there is no need to
memset()[unless you are re-initializing, I suppose]
ditto.
Signature · 1 line
tejun
Re: [PATCH 3/4] libata: add per-dev pio/mwdma/udma_mask
In reply to Jeff GarzikQuoted 6 lines · Jeff Garzik
Quoted 5 lines · Tejun Heo
Add per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug.
Quoted 6 lines
Quoted 1 line
Signed-off-by Tejun Heo <[email protected]>I don't see much value in the separation. Rather than 3 separate masks, it seems like this patch would be simplified if you simply added
dev->xfer_mask.
The thing is that ap->*_mask's are separated the same way and all masking constants are defined as such. e.g.
ap->udma_mask &= ATA_UDMA5; or ap->udma_mask &= ATA_UDMA_MASK_40C;
Making dev->*_mask's the same enables share those constants and code convention. So, things to consider here are...
1. Port xfer masks are defined as three separate masks.
2. All the constants are defined according to that.
3. Three separate masks are easier to deal with for LLDD's.
I'm okay either way but using different approach for port and device doesn't sound too hot.
Signature · 1 line
tejun
Re: [PATCH 4/4] libata: make per-dev transfer mode limits per-dev
In reply to Jeff GarzikQuoted 9 lines · Jeff Garzik
Quoted 4 lines · Tejun Heo
Now that each
ata_devicehas xfer masks, per-dev limits can be made per-dev instead of per-port. Make per-dev limits per-dev.Signed-off-by Tejun Heo <[email protected]>Doesn't this patch break stuff? As you said in a previous patch, the per-dev masks aren't used yet?
No, it doesn't break stuff. per-dev masks are applied in ata_dev_xfermask().
@@ -2667,6 +2670,8 @@ static unsigned int ata_dev_xfermask(str
struct ata_device *d = &ap->device[i];
if (!ata_dev_present(d))
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);
Signature · 1 line
tejun
Re: [PATCH 3/4] libata: add per-dev pio/mwdma/udma_mask
In reply to Tejun HeoQuoted 22 lines · Tejun Heo
Quoted 11 lines · Jeff Garzik
Quoted 6 lines · Tejun Heo
Add per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug.
Signed-off-by Tejun Heo <[email protected]>I don't see much value in the separation. Rather than 3 separate masks, it seems like this patch would be simplified if you simply added
dev->xfer_mask.The thing is that ap->*_mask's are separated the same way and all masking constants are defined as such. e.g.
ap->udma_mask &= ATA_UDMA5; or ap->udma_mask &= ATA_UDMA_MASK_40C;
Quoted 8 lines
Making dev->*_mask's the same enables share those constants and code convention. So, things to consider here are...
1. Port xfer masks are defined as three separate masks.
2. All the constants are defined according to that.
3. Three separate masks are easier to deal with for LLDD's.
Separate masks is better for the LLDD interface, but the packed version seems superior for internal libata use.
No reason why ATA_UDMA_MASK_40C can't simply operate on a packed xfer_mask variable, for example.
Jeff
Re: [PATCH 3/4] libata: add per-dev pio/mwdma/udma_mask
Quoted 28 lines · Jeff Garzik
Quoted 27 lines · Tejun Heo
Quoted 7 lines · Jeff Garzik
Quoted 5 lines · Tejun Heo
Add per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug.
Quoted 6 lines
Quoted 1 line
Signed-off-by Tejun Heo <[email protected]>I don't see much value in the separation. Rather than 3 separate masks, it seems like this patch would be simplified if you simply added
dev->xfer_mask.The thing is that ap->*_mask's are separated the same way and all masking constants are defined as such. e.g.
ap->udma_mask &= ATA_UDMA5; or ap->udma_mask &= ATA_UDMA_MASK_40C;Making dev->*_mask's the same enables share those constants and code convention. So, things to consider here are...
Quoted 8 lines
Quoted 5 lines
1. Port xfer masks are defined as three separate masks.
2. All the constants are defined according to that.
3. Three separate masks are easier to deal with for LLDD's.
Separate masks is better for the LLDD interface, but the packed version seems superior for internal libata use.
Yeah, dev->*_mask's will be used by LLDD's. Actually, in patch #4 of this series, sata_sil's ->dev_config() does exactly that. Also, mode mask filtering can be done by diddling dev->*_mask's.
Quoted 2 lines
No reason why
ATA_UDMA_MASK_40Ccan't simply operate on a packedxfer_maskvariable, for example.
Because it's used to filter ap->*_mask and to allow LLDD's use the same constants on dev->*_mask's.
Do you think LLDD's shouldn't access dev->*_mask's?
Signature · 1 line
tejun
Re: [PATCH 3/4] libata: add per-dev pio/mwdma/udma_mask
Quoted 45 lines · Tejun Heo
Quoted 29 lines · Jeff Garzik
Quoted 27 lines · Tejun Heo
Quoted 12 lines · Jeff Garzik
Quoted 6 lines · Tejun Heo
Add per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug.
Signed-off-by Tejun Heo <[email protected]>I don't see much value in the separation. Rather than 3 separate masks, it seems like this patch would be simplified if you simply added
dev->xfer_mask.The thing is that ap->*_mask's are separated the same way and all masking constants are defined as such. e.g.
ap->udma_mask &= ATA_UDMA5; or ap->udma_mask &= ATA_UDMA_MASK_40C;Making dev->*_mask's the same enables share those constants and code convention. So, things to consider here are...
Quoted 7 lines
Quoted 5 lines
1. Port xfer masks are defined as three separate masks.
2. All the constants are defined according to that.
3. Three separate masks are easier to deal with for LLDD's.
Separate masks is better for the LLDD interface, but the packed version seems superior for internal libata use.
Yeah, dev->*_mask's will be used by LLDD's. Actually, in patch #4 of this series, sata_sil's ->dev_config() does exactly that. Also, mode mask filtering can be done by diddling dev->*_mask's.
Quoted 7 lines
Quoted 1 line
No reason why
ATA_UDMA_MASK_40Ccan't simply operate on a packedxfer_maskvariable, for example.Because it's used to filter ap->*_mask and to allow LLDD's use the same constants on dev->*_mask's.
Do you think LLDD's shouldn't access dev->*_mask's?
When I spoke of "LLDD API", I largely meant the pio_mask/etc. in ata_port_info. That's the easiest way to present such information to driver maintainers.
OTOH, at runtime ->dev_config() and friends should probably just manipulate dev->xfer_mask.
Jeff
Re: [PATCH 3/4] libata: add per-dev pio/mwdma/udma_mask
Quoted 56 lines · Jeff Garzik
Quoted 55 lines · Tejun Heo
Quoted 31 lines · Jeff Garzik
Quoted 29 lines · Tejun Heo
Quoted 8 lines · Jeff Garzik
Quoted 5 lines · Tejun Heo
Add per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug.
Quoted 6 lines
Quoted 1 line
Signed-off-by Tejun Heo <[email protected]>I don't see much value in the separation. Rather than 3 separate masks, it seems like this patch would be simplified if you simply added
dev->xfer_mask.The thing is that ap->*_mask's are separated the same way and all masking constants are defined as such. e.g.
ap->udma_mask &= ATA_UDMA5; or ap->udma_mask &= ATA_UDMA_MASK_40C;Making dev->*_mask's the same enables share those constants and code convention. So, things to consider here are...
Quoted 8 lines
Quoted 5 lines
1. Port xfer masks are defined as three separate masks.
2. All the constants are defined according to that.
3. Three separate masks are easier to deal with for LLDD's.
Separate masks is better for the LLDD interface, but the packed version seems superior for internal libata use.
Yeah, dev->*_mask's will be used by LLDD's. Actually, in patch #4 of this series, sata_sil's ->dev_config() does exactly that. Also, mode mask filtering can be done by diddling dev->*_mask's.
Quoted 2 lines
No reason why
ATA_UDMA_MASK_40Ccan't simply operate on a packedxfer_maskvariable, for example.Because it's used to filter ap->*_mask and to allow LLDD's use the same constants on dev->*_mask's.
Quoted 8 lines
Quoted 1 line
Do you think LLDD's shouldn't access dev->*_mask's?
When I spoke of "LLDD API", I largely meant the pio_mask/etc. in
ata_port_info. That's the easiest way to present such information to driver maintainers.OTOH, at runtime ->dev_config() and friends should probably just manipulate
dev->xfer_mask.
I see.
So, ata_port_info uses pio/mwdma/udma_mask and ata_port and ata_device use single xfer_mask and all the masking constants are converted to mask single xfer_mask. Sounds good to you?
Signature · 1 line
tejun
Quoted 5 lines · Tejun Heo
callback can be added later when merging PATA code. One concern I have about the originally proposed ->mode_filter(ap, dev, mask, shift) interface is that if a LLDD wants to reject all UDMA and limit some of MWDMA, there is no way to do so. I think it's better and easier to filter all mode masks at once.
The current code is called three times once for PIO once for MWDMA and once for UDMA (since we don't do SWDMA yet). Doing it as one seems sensible enough, it just didn't fit how the old code worked.
I also agree strongly we need ap-> and dev-> masks in the same format throughout libata and the drivers or there are going to be disasters
Re: [PATCH 3/4] libata: add per-dev pio/mwdma/udma_mask
In reply to Tejun HeoQuoted 64 lines · Tejun Heo
Quoted 62 lines · Jeff Garzik
Quoted 50 lines · Tejun Heo
Quoted 32 lines · Jeff Garzik
Quoted 29 lines · Tejun Heo
Quoted 4 lines · Jeff Garzik
Tejun Heo wrote:
Quoted 9 lines
Quoted 6 lines
Add per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug.
Signed-off-by Tejun Heo <[email protected]>I don't see much value in the separation. Rather than 3 separate masks, it seems like this patch would be simplified if you simply added
dev->xfer_mask.The thing is that ap->*_mask's are separated the same way and all masking constants are defined as such. e.g.
ap->udma_mask &= ATA_UDMA5; or ap->udma_mask &= ATA_UDMA_MASK_40C;Making dev->*_mask's the same enables share those constants and code convention. So, things to consider here are...
Quoted 7 lines
Quoted 5 lines
1. Port xfer masks are defined as three separate masks.
2. All the constants are defined according to that.
3. Three separate masks are easier to deal with for LLDD's.
Separate masks is better for the LLDD interface, but the packed version seems superior for internal libata use.
Yeah, dev->*_mask's will be used by LLDD's. Actually, in patch #4 of this series, sata_sil's ->dev_config() does exactly that. Also, mode mask filtering can be done by diddling dev->*_mask's.
Quoted 7 lines
Quoted 1 line
No reason why
ATA_UDMA_MASK_40Ccan't simply operate on a packedxfer_maskvariable, for example.Because it's used to filter ap->*_mask and to allow LLDD's use the same constants on dev->*_mask's.
Do you think LLDD's shouldn't access dev->*_mask's?
When I spoke of "LLDD API", I largely meant the pio_mask/etc. in
ata_port_info. That's the easiest way to present such information to driver maintainers.
Quoted 8 lines
Quoted 1 line
OTOH, at runtime ->dev_config() and friends should probably just manipulate
dev->xfer_mask.I see.
So,
ata_port_infouses pio/mwdma/udma_mask andata_portandata_deviceuse singlexfer_maskand all the masking constants are converted to mask singlexfer_mask. Sounds good to you?
Well, if I read him correctly, Alan seems to have weighted in on the side of pio/mwdma/udma_mask.
Maybe we could go with your original patches' direction for now, and then move to a consolidated xfer_mask internally later.
Jeff
Re: [PATCH 3/4] libata: add per-dev pio/mwdma/udma_mask
Quoted 9 lines · Jeff Garzik
Quoted 3 lines
So,
ata_port_infouses pio/mwdma/udma_mask andata_portandata_deviceuse singlexfer_maskand all the masking constants are converted to mask singlexfer_mask. Sounds good to you?Well, if I read him correctly, Alan seems to have weighted in on the side of pio/mwdma/udma_mask.
Maybe we could go with your original patches' direction for now, and then move to a consolidated
xfer_maskinternally later.
What I've done for the filter side of things is kept the combined mask as what is filtered by the driver, and that looks tidy. What came out ugly that I objected to was the horribly mess you got when declaring all the driver modes available.