libata: improve ATAPI data transfer handling, take #3
Subsystems (6)
PATCH 2/15 libata: zero xfer length on ATAPI data xfer IRQ is HSM violation
In reply to Tejun HeoFrom: Albert Lee <[email protected]>
Treat zero xfer length as HSM violation. While at it, add unlikely()'s to ATAPI ireason and transfer length checks.
tj: Formatted patch and added unlikely()'s.
--- drivers/ata/libata-core.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
drivers/ata/libata-core.c +5 -2
@@ -5280,12 +5280,15 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) bytes = (bc_hi <<8 ) | bc_lo;/* shall be cleared to zero, indicating xfer of data */ -if (ireason & (1 <<0 )) +if (unlikely (ireason & (1 <<0 ))) goto err_out;/* make sure transfer direction matches expected */ i_write = ((ireason & (1 <<1 )) ==0 ) ?1 :0 ; -if (do_write != i_write) +if (unlikely (do_write != i_write)) + goto err_out; + +if (unlikely (!bytes)) goto err_out;VPRINTK ("ata%u: xfering %d bytes\n" , ap->print_id, bytes);
Signature · 1 line
1.5.2.4
PATCH 1/1 libata: improve ATAPI data transfer handling, take #3
Hello,
This is the third take of improve-ATAPI-data-transfer patchset. Changes from the last take [L] are.
* 0001-libata-make-atapi_request_sense-use-sg.patch was moved forward as Jeff requested.
* 0002-libata-zero-xfer-length-on-ATAPI-data-xfer-IRQ-is-H.patch from Albert Lee is added.
* s/buflen/len/ dropped from 0007-change-data_xfer.patch.
* 0012-libata-make-qc-nbytes-include-extra-buffers.patch is previous add-dma_nbytes patch. qc->nbytes is now updated directly and the original value is stored in qc->raw_nbytes.
This patchset is against #upstream (f5d10948).
This patchset is also available as the following git tree.
master.kernel.org:/pub/scm/linux/kernel/git/tj/libata-dev.git improve-ATAPI-data-transfer
If you don't wanna pull the last use-PIO-for-misc-ATAPI-commands patch, pull from the following head.
master.kernel.org:/pub/scm/linux/kernel/git/tj/libata-dev.git improve-ATAPI-data-transfer-no-pio
Thanks.
--
tejun
PATCH 3/15 libata: update atapi_eh_request_sense() such that lbam/lbah contains buffer size
While updating lbam/h for ATAPI commands, atapi_eh_request_sense() was left out. Update it.
--- drivers/ata/libata-eh.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/ata/libata-eh.c +2 -2
@@ -1302,8 +1302,8 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc) tf.feature |=ATAPI_PKT_DMA ; }else { tf.protocol =ATA_PROT_ATAPI ; - tf.lbam = (8 *1024 ) &0xff ; - tf.lbah = (8 *1024 ) >>8 ; + tf.lbam =SCSI_SENSE_BUFFERSIZE ; + tf.lbah =0 ; } return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
Signature · 1 line
1.5.2.4
PATCH 1/15 libata: make atapi_request_sense() use sg
In reply to Tejun Heoatapi_request_sense() is now the only left user of ata_sg_init_one(). Convert it to use sg interface.
--- drivers/ata/libata-scsi.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
drivers/ata/libata-scsi.c +3 -1
@@ -2340,7 +2340,9 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)ata_qc_reinit (qc); -ata_sg_init_one (qc, cmd->sense_buffer,sizeof (cmd->sense_buffer)); +/* setup sg table and init transfer direction */ +sg_init_one (&qc->sgent, cmd->sense_buffer,sizeof (cmd->sense_buffer)); +ata_sg_init (qc, &qc->sgent,1 ); qc->dma_dir =DMA_FROM_DEVICE ;memset (&qc->cdb,0 , qc->dev->cdb_len);
Signature · 1 line
1.5.2.4
PATCH 6/15 libata: add ATAPI_* cmd types and implement atapi_cmd_type()
In reply to Tejun HeoAdd ATAPI command types - ATAPI_READ, WRITE, RW_BUF, READ_CD and MISC, and implement atapi_cmd_type() which takes SCSI opcode and returns to which class the opcode belongs. This will be used later to improve ATAPI handling.
--- include/linux/libata.h | 28 ++++++++++++++++++++++++++++ 1 files changed, 28 insertions(+), 0 deletions(-)
include/linux/libata.h +28 -0
@@ -35,6 +35,7 @@#include <linux/workqueue.h> #include <scsi/scsi_host.h> #include <linux/acpi.h> +#include <linux/cdrom.h> /* * Define if arch has non-standard setup. This is a _PCI_ standard
@@ -345,6 +346,12 @@ enum {ATA_DMA_MASK_ATA = (1 <<0 ),/* DMA on ATA Disk */ ATA_DMA_MASK_ATAPI = (1 <<1 ),/* DMA on ATAPI */ ATA_DMA_MASK_CFA = (1 <<2 ),/* DMA on CF Card */ + +/* ATAPI command types */ +ATAPI_READ =0 ,/* READs */ +ATAPI_WRITE =1 ,/* WRITEs */ +ATAPI_READ_CD =2 ,/* READ CD [MSF] */ + ATAPI_MISC = 3, /* the rest */ }; enum ata_xfer_mask {
@@ -1407,6 +1414,27 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)ata_id_has_flush_ext (dev->id); } +static inline int atapi_cmd_type (u8 opcode) +{ +switch (opcode) { +case GPCMD_READ_10 : +case GPCMD_READ_12 : +return ATAPI_READ ; + +case GPCMD_WRITE_10 : +case GPCMD_WRITE_12 : +case GPCMD_WRITE_AND_VERIFY_10 : +return ATAPI_WRITE ; + +case GPCMD_READ_CD : +case GPCMD_READ_CD_MSF : +return ATAPI_READ_CD ; + +default : +return ATAPI_MISC ; + } +} +static inline unsigned int ac_err_mask (u8 status) {if (status & (ATA_BUSY |ATA_DRQ ))
Signature · 1 line
1.5.2.4
PATCH 8/15 libata: improve ATAPI draining
In reply to Tejun HeoFor misc ATAPI commands which transfer variable length data to the host, overflow can occur due to application or hardware bug. Such overflows can be ignored safely as long as overflow data is properly drained. libata HSM implementation has this implemented in __atapi_pio_bytes() but it isn't enough. Improve drain logic such that...
* Multiple PIO data phases are allowed. Not allowing this used to be okay when transfer chunk size was set to 8k unconditionally but with transfer hcunk size set to allocation size, treating extra PIO data phases as HSM violations cause a lot of trouble.
* Limit the amount of draining to ATAPI_MAX_DRAIN (16k currently).
* Don't whine if overflow is allowed and safe. When unexpected overflow occurs, trigger HSM violation and report the problem using ehi error description.
* Properly calculate the number of bytes to be drained considering actual number of consumed bytes for partial draining.
* Add and use ata_drain_page for draining. This change fixes the problem where LLDs which do 32bit IOs consumes 4 bytes on each 2 byte draining resulting in draining twice more data than requested.
This patch fixes ATAPI regressions introduced by setting transfer chunk size to allocation size.
--- drivers/ata/libata-core.c | 126 ++++++++++++++++++++++++++++++--------------- include/linux/libata.h | 2 + 2 files changed, 87 insertions(+), 41 deletions(-)
drivers/ata/libata-core.c +85 -41
@@ -83,8 +83,8 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev);unsigned int ata_print_id =1 ;static struct workqueue_struct *ata_wq; -struct workqueue_struct *ata_aux_wq; +static void *ata_drain_page;int atapi_enabled =1 ;module_param (atapi_enabled, int,0444 );
@@ -4674,6 +4674,28 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) }/** +* atapi_qc_may_overflow - Check whether data transfer may overflow +* @qc: ATA command in question +* +* ATAPI commands which transfer variable length data to host +* might overflow due to application error or hardare bug. This +* function checks whether overflow should be drained and ignored +* for @qc. +* +* LOCKING: +* None. +* +* RETURNS: +* 1 if @qc may overflow; otherwise, 0. +*/ +static int atapi_qc_may_overflow (struct ata_queued_cmd *qc) +{ +return ata_is_atapi (qc->tf.protocol) &&ata_is_data (qc->tf.protocol) && +atapi_cmd_type (qc->cdb[0 ]) ==ATAPI_MISC && + !(qc->tf.flags &ATA_TFLAG_WRITE ); +} + +/** * ata_std_qc_defer - Check whether a qc needs to be deferred * @qc: ATA command in question *
@@ -5175,23 +5197,20 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)* Inherited from caller. * */ - -static void __atapi_pio_bytes (struct ata_queued_cmd *qc,unsigned int bytes) +static int __atapi_pio_bytes (struct ata_queued_cmd *qc,unsigned int bytes) { -int do_write = (qc->tf.flags &ATA_TFLAG_WRITE ); -struct scatterlist *sg = qc->__sg; -struct scatterlist *lsg =sg_last (qc->__sg, qc->n_elem); +int rw = (qc->tf.flags &ATA_TFLAG_WRITE ) ?WRITE :READ ;struct ata_port *ap = qc->ap; +struct ata_device *dev = qc->dev; +struct ata_eh_info *ehi = &dev->link->eh_info; +struct scatterlist *sg;struct page *page;unsigned char *buf; -unsigned int offset, count; -int no_more_sg =0 ; - -if (qc->curbytes + bytes >= qc->nbytes) - ap->hsm_task_state =HSM_ST_LAST ; +unsigned int offset, count, consumed; next_sg: -if (unlikely (no_more_sg)) { + sg = qc->cursg; +if (unlikely (!sg)) {/* * The end of qc->sg is reached and the device expects * more data to transfer. In order not to overrun qc->sg
@@ -5199,23 +5218,32 @@ next_sg:* - for read case, discard trailing data from the device * - for write case, padding zero data to the device */ -u16 pad_buf[1 ] = {0 }; -unsigned int words = bytes >>1 ; -unsigned int i; +if (qc->curbytes + bytes > qc->nbytes +ATAPI_MAX_DRAIN ) { +ata_ehi_push_desc (ehi,"too much trailing data " +"buf=%u cur=%u bytes=%u" , + qc->nbytes, qc->curbytes, bytes); +return -1 ; + } -if (words)/* warning if bytes > 1 */ -ata_dev_printk (qc->dev,KERN_WARNING , -"%u bytes trailing data\n" , bytes); +/* allow overflow only for misc ATAPI commands */ +if (!atapi_qc_may_overflow (qc)) { +ata_ehi_push_desc (ehi,"unexpected trailing data " +"%u bytes" , bytes); +return -1 ; + } -for (i =0 ; i < words; i++) - ap->ops->data_xfer (qc->dev, (unsigned char *)pad_buf,2 , do_write); + consumed =0 ; +while (consumed < bytes) { + count = min_t(unsigned int, + bytes - consumed,PAGE_SIZE ); + consumed += ap->ops->data_xfer (dev, ata_drain_page, + count, rw); + } - ap->hsm_task_state =HSM_ST_LAST ; -return ; + qc->curbytes += bytes; +return 0 ; } - sg = qc->cursg; - page =sg_page (sg); offset = sg->offset + qc->cursg_ofs;
@@ -5239,29 +5267,30 @@ next_sg: buf =kmap_atomic (page,KM_IRQ0 );/* do the actual data transfer */ - ap->ops->data_xfer (qc->dev, buf + offset, count, do_write); + consumed = ap->ops->data_xfer (dev, buf + offset, count, rw);kunmap_atomic (buf,KM_IRQ0 );local_irq_restore (flags); }else { buf =page_address (page); - ap->ops->data_xfer (qc->dev, buf + offset, count, do_write); + consumed = ap->ops->data_xfer (dev, buf + offset, count, rw); } - bytes -= count; + bytes -=min (bytes, consumed); qc->curbytes += count; qc->cursg_ofs += count;if (qc->cursg_ofs == sg->length) { -if (qc->cursg == lsg) - no_more_sg =1 ; - qc->cursg =sg_next (qc->cursg); qc->cursg_ofs =0 ; } +/* consumed can be larger than count only for the last transfer */ +WARN_ON (qc->cursg && count != consumed); +if (bytes) goto next_sg; +return 0 ; }/**
@@ -5278,6 +5307,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) {struct ata_port *ap = qc->ap;struct ata_device *dev = qc->dev; +struct ata_eh_info *ehi = &dev->link->eh_info;unsigned int ireason, bc_lo, bc_hi, bytes;int i_write, do_write = (qc->tf.flags &ATA_TFLAG_WRITE ) ?1 :0 ;
@@ -5295,25 +5325,28 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)/* shall be cleared to zero, indicating xfer of data */ if (unlikely (ireason & (1 <<0 ))) - goto err_out; + goto atapi_check;/* make sure transfer direction matches expected */ i_write = ((ireason & (1 <<1 )) ==0 ) ?1 :0 ;if (unlikely (do_write != i_write)) - goto err_out; + goto atapi_check;if (unlikely (!bytes)) - goto err_out; + goto atapi_check;VPRINTK ("ata%u: xfering %d bytes\n" , ap->print_id, bytes); -__atapi_pio_bytes (qc, bytes); +if (unlikely (__atapi_pio_bytes (qc, bytes))) + goto err_out;ata_altstatus (ap);/* flush */ return ; -err_out: -ata_dev_printk (dev,KERN_INFO ,"ATAPI check failed\n" ); + atapi_check: +ata_ehi_push_desc (ehi,"ATAPI check failed (ireason=0x%x bytes=%u)" , + ireason, bytes); + err_out: qc->err_mask |=AC_ERR_HSM ; ap->hsm_task_state =HSM_ST_ERR ; }
@@ -7434,24 +7467,35 @@ int ata_pci_device_resume(struct pci_dev *pdev)static int __init ata_init (void ) { ata_probe_timeout *=HZ ; + + ata_drain_page = (void *)__get_free_page (GFP_DMA32 ); +if (!ata_drain_page) + goto err_drain_page; + ata_wq =create_workqueue ("ata" );if (!ata_wq) -return -ENOMEM ; + goto err_ata_wq; ata_aux_wq =create_singlethread_workqueue ("ata_aux" ); -if (!ata_aux_wq) { -destroy_workqueue (ata_wq); -return -ENOMEM ; - } +if (!ata_aux_wq) + goto err_ata_aux_wq;printk (KERN_DEBUG "libata version " DRV_VERSION " loaded.\n" );return 0 ; + + err_ata_aux_wq: +destroy_workqueue (ata_wq); + err_ata_wq: +free_page ((unsigned long )ata_drain_page); + err_drain_page: +return -ENOMEM ; } static void __exit ata_exit(void) {destroy_workqueue (ata_wq);destroy_workqueue (ata_aux_wq); +free_page ((unsigned long )ata_drain_page); }subsys_initcall (ata_init);
include/linux/libata.h +2 -0
@@ -120,6 +120,8 @@ enum {ATA_DEF_BUSY_WAIT =10000 ,ATA_SHORT_PAUSE = (HZ >>6 ) +1 , +ATAPI_MAX_DRAIN =16 <<10 , +ATA_SHT_EMULATED =1 ,ATA_SHT_CMD_PER_LUN =1 , ATA_SHT_THIS_ID = -1,
Signature · 1 line
1.5.2.4
PATCH 10/15 libata: change ATA_QCFLAG_DMAMAP semantics
In reply to Tejun HeoATA_QCFLAG_DMAMAP was a bit peculiar in that it got set during qc initialization and cleared if DMA mapping wasn't necessary. Make it more straight forward by making the following changes.
* Don't set it during initialization. Set it after DMA is actually mapped.
* Add BUG_ON() to guarantee that there is data to transfer if DMAMAP is set. This always holds for the current code. The BUG_ON() is for docummentation and sanity check.
--- drivers/ata/libata-core.c | 15 +++++++-------- 1 files changed, 7 insertions(+), 8 deletions(-)
drivers/ata/libata-core.c +7 -8
@@ -4487,7 +4487,6 @@ void ata_sg_clean(struct ata_queued_cmd *qc)int dir = qc->dma_dir;void *pad_buf =NULL ; -WARN_ON (!(qc->flags &ATA_QCFLAG_DMAMAP ));WARN_ON (sg ==NULL );VPRINTK ("unmapping %u sg elements\n" , qc->n_elem);
@@ -4759,11 +4758,9 @@ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }* LOCKING: * spin_lock_irqsave(host lock) */ -void ata_sg_init (struct ata_queued_cmd *qc,struct scatterlist *sg,unsigned int n_elem) { - qc->flags |=ATA_QCFLAG_DMAMAP ; qc->__sg = sg; qc->n_elem = n_elem; qc->orig_n_elem = n_elem;
@@ -4792,7 +4789,6 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)int n_elem, pre_n_elem, dir, trim_sg =0 ;VPRINTK ("ENTER, ata%u\n" , ap->print_id); -WARN_ON (!(qc->flags &ATA_QCFLAG_DMAMAP ));/* we must lengthen transfers to end on a 32-bit boundary */ qc->pad_len = lsg->length &3 ;
@@ -4852,6 +4848,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) skip_map: qc->n_elem = n_elem; + qc->flags |=ATA_QCFLAG_DMAMAP ;return 0 ; }
@@ -5915,12 +5912,15 @@ void ata_qc_issue(struct ata_queued_cmd *qc) qc->flags |=ATA_QCFLAG_ACTIVE ; ap->qc_active |=1 << qc->tag; +/* We guarantee to LLDs that they will have at least one +* non-zero sg if the command is a data command. +*/ +BUG_ON (ata_is_data (prot) && (!qc->__sg || !qc->n_elem || !qc->nbytes)); +if (ata_is_dma (prot) || (ata_is_pio (prot) && - (ap->flags &ATA_FLAG_PIO_DMA ))) { + (ap->flags &ATA_FLAG_PIO_DMA )))if (ata_sg_setup (qc)) goto sg_err; - }else - qc->flags &=ATA_QCFLAG_DMAMAP ;/* if device is sleeping, schedule softreset and abort the link */ if (unlikely (qc->dev->flags &ATA_DFLAG_SLEEPING )) {
@@ -5938,7 +5938,6 @@ void ata_qc_issue(struct ata_queued_cmd *qc)return ; sg_err: - qc->flags &= ~ATA_QCFLAG_DMAMAP ; qc->err_mask |=AC_ERR_SYSTEM ; err:ata_qc_complete (qc);
Signature · 1 line
1.5.2.4
PATCH 12/15 libata: make qc->nbytes include extra buffers
In reply to Tejun Heoqc->nbytes didn't use to include extra buffers setup by libata core layer and my be odd. This patch makes qc->nbytes include any extra buffers setup by libata core layer and guaranteed to be aligned on 4 byte boundary.
This value is to be used to program the host controller. As this represents the actual length of buffer available to the controller and the controller must be able to deal with short transfers for ATAPI commands which can transfer variable length, this shouldn't break any controllers while making problems like rounding-down and controllers choking up on odd transfer bytes much less likely.
The unmodified value is stored in new field qc->raw_nbytes.
--- drivers/ata/libata-core.c | 14 ++++++++++---- include/linux/libata.h | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-)
drivers/ata/libata-core.c +10 -4
@@ -4760,13 +4760,15 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, }static unsigned int ata_sg_setup_extra (struct ata_queued_cmd *qc, -unsigned int *n_elem_extra) +unsigned int *n_elem_extra, +unsigned int *nbytes_extra) {struct ata_port *ap = qc->ap;unsigned int n_elem = qc->n_elem;struct scatterlist *lsg, *copy_lsg =NULL , *tsg =NULL , *esg =NULL ; *n_elem_extra =0 ; + *nbytes_extra =0 ;/* needs padding? */ qc->pad_len = qc->nbytes &3 ;
@@ -4830,6 +4832,7 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc, esg = &qc->extra_sg[1 ]; (*n_elem_extra)++; + (*nbytes_extra) +=4 - qc->pad_len; }if (copy_lsg)
@@ -4863,11 +4866,11 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,static int ata_sg_setup (struct ata_queued_cmd *qc) {struct ata_port *ap = qc->ap; -unsigned int n_elem, n_elem_extra; +unsigned int n_elem, n_elem_extra, nbytes_extra;VPRINTK ("ENTER, ata%u\n" , ap->print_id); - n_elem =ata_sg_setup_extra (qc, &n_elem_extra); + n_elem =ata_sg_setup_extra (qc, &n_elem_extra, &nbytes_extra);if (n_elem) { n_elem =dma_map_sg (ap->dev, qc->sg, n_elem, qc->dma_dir);
@@ -4882,7 +4885,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) qc->n_elem = qc->mapped_n_elem = n_elem; qc->n_elem += n_elem_extra; - + qc->nbytes += nbytes_extra; qc->flags |=ATA_QCFLAG_DMAMAP ;return 0 ;
@@ -5952,6 +5955,9 @@ void ata_qc_issue(struct ata_queued_cmd *qc)*/ BUG_ON (ata_is_data (prot) && (!qc->sg || !qc->n_elem || !qc->nbytes)); +/* ata_sg_setup() may update nbytes */ + qc->raw_nbytes = qc->nbytes; +if (ata_is_dma (prot) || (ata_is_pio (prot) && (ap->flags &ATA_FLAG_PIO_DMA )))if (ata_sg_setup (qc))
include/linux/libata.h +2 -1
@@ -467,6 +467,7 @@ struct ata_queued_cmd {unsigned int sect_size;unsigned int nbytes; +unsigned int raw_nbytes;unsigned int curbytes;struct scatterlist *cursg;
@@ -1363,7 +1364,7 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->flags =0 ; qc->cursg =NULL ; qc->cursg_ofs =0 ; - qc->nbytes = qc->curbytes =0 ; + qc->nbytes = qc->raw_nbytes = qc->curbytes =0 ; qc->n_elem =0 ; qc->mapped_n_elem =0 ; qc->n_iter =0 ;
Signature · 1 line
1.5.2.4
PATCH 5/15 libata: rename ATA_PROT_ATAPI_* to ATAPI_PROT_*
In reply to Tejun HeoATA_PROT_ATAPI_* are ugly and naming schemes between ATA_PROT_* and ATA_PROT_ATAPI_* are inconsistent causing confusion. Rename them to ATAPI_PROT_* and make them consistent with ATA counterpart.
--- drivers/ata/libata-core.c | 24 ++++++++++++------------ drivers/ata/libata-eh.c | 8 ++++---- drivers/ata/libata-scsi.c | 10 +++++----- drivers/ata/libata-sff.c | 2 +- drivers/ata/pata_pdc202xx_old.c | 5 ++--- drivers/ata/pdc_adma.c | 2 +- drivers/ata/sata_inic162x.c | 2 +- drivers/ata/sata_promise.c | 26 ++++++++++++-------------- drivers/ata/sata_qstor.c | 2 +- drivers/ata/sata_sx4.c | 2 +- drivers/scsi/ipr.c | 6 +++--- drivers/scsi/libsas/sas_ata.c | 2 +- include/linux/ata.h | 12 ++++++------ 13 files changed, 50 insertions(+), 53 deletions(-)
drivers/ata/libata-core.c +12 -12
@@ -5136,13 +5136,13 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)ata_altstatus (ap);/* flush */ switch (qc->tf.protocol) { -case ATA_PROT_ATAPI : +case ATAPI_PROT_PIO : ap->hsm_task_state =HSM_ST ;break ; -case ATA_PROT_ATAPI_NODATA : +case ATAPI_PROT_NODATA : ap->hsm_task_state =HSM_ST_LAST ;break ; -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA : ap->hsm_task_state =HSM_ST_LAST ;/* initiate bmdma */ ap->ops->bmdma_start (qc);
@@ -5488,7 +5488,7 @@ fsm_start:case HSM_ST :/* complete command or read/write the data register */ -if (qc->tf.protocol ==ATA_PROT_ATAPI ) { +if (qc->tf.protocol ==ATAPI_PROT_PIO ) {/* ATAPI PIO protocol */ if ((status &ATA_DRQ ) ==0 ) {/* No more data to transfer or device error.
@@ -6043,11 +6043,11 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)switch (qc->tf.protocol) {case ATA_PROT_PIO :case ATA_PROT_NODATA : -case ATA_PROT_ATAPI : -case ATA_PROT_ATAPI_NODATA : +case ATAPI_PROT_PIO : +case ATAPI_PROT_NODATA : qc->tf.flags |=ATA_TFLAG_POLLING ;break ; -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :if (qc->dev->flags &ATA_DFLAG_CDB_INTR )/* see ata_dma_blacklisted() */ BUG ();
@@ -6111,8 +6111,8 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)break ; -case ATA_PROT_ATAPI : -case ATA_PROT_ATAPI_NODATA : +case ATAPI_PROT_PIO : +case ATAPI_PROT_NODATA :if (qc->tf.flags &ATA_TFLAG_POLLING )ata_qc_set_polling (qc);
@@ -6126,7 +6126,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)ata_port_queue_task (ap, ata_pio_task, qc,0 );break ; -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :WARN_ON (qc->tf.flags &ATA_TFLAG_POLLING ); ap->ops->tf_load (ap, &qc->tf);/* load tf registers */
@@ -6187,7 +6187,7 @@ inline unsigned int ata_host_intr(struct ata_port *ap,break ;case HSM_ST_LAST :if (qc->tf.protocol ==ATA_PROT_DMA || - qc->tf.protocol ==ATA_PROT_ATAPI_DMA ) { + qc->tf.protocol ==ATAPI_PROT_DMA ) {/* check status of DMA engine */ host_stat = ap->ops->bmdma_status (ap); VPRINTK("ata%u: host_stat 0x%X\n",
@@ -6229,7 +6229,7 @@ inline unsigned int ata_host_intr(struct ata_port *ap,ata_hsm_move (ap, qc, status,0 );if (unlikely (qc->err_mask) && (qc->tf.protocol ==ATA_PROT_DMA || - qc->tf.protocol ==ATA_PROT_ATAPI_DMA )) + qc->tf.protocol ==ATAPI_PROT_DMA ))ata_ehi_push_desc (ehi,"BMDMA stat 0x%x" , host_stat);return 1 ;/* irq handled */
drivers/ata/libata-eh.c +4 -4
@@ -1298,10 +1298,10 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc)/* is it pointless to prefer PIO for "safety reasons"? */ if (ap->flags &ATA_FLAG_PIO_DMA ) { - tf.protocol =ATA_PROT_ATAPI_DMA ; + tf.protocol =ATAPI_PROT_DMA ; tf.feature |=ATAPI_PKT_DMA ; }else { - tf.protocol =ATA_PROT_ATAPI ; + tf.protocol =ATAPI_PROT_PIO ; tf.lbam =SCSI_SENSE_BUFFERSIZE ; tf.lbah =0 ; }
@@ -1968,8 +1968,8 @@ static void ata_eh_link_report(struct ata_link *link) [ATA_PROT_PIO] = "pio", [ATA_PROT_DMA] = "dma", [ATA_PROT_NCQ] = "ncq", - [ATA_PROT_ATAPI] = "pio", - [ATA_PROT_ATAPI_DMA ] ="dma" , + [ATAPI_PROT_PIO] = "pio", + [ATAPI_PROT_DMA ] ="dma" , }; snprintf(data_buf, sizeof(data_buf), " %s %u %s",
drivers/ata/libata-scsi.c +5 -5
@@ -2353,10 +2353,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) qc->tf.command =ATA_CMD_PACKET ;if (ata_pio_use_silly (ap)) { - qc->tf.protocol =ATA_PROT_ATAPI_DMA ; + qc->tf.protocol =ATAPI_PROT_DMA ; qc->tf.feature |=ATAPI_PKT_DMA ; }else { - qc->tf.protocol =ATA_PROT_ATAPI ; + qc->tf.protocol =ATAPI_PROT_PIO ; qc->tf.lbam =SCSI_SENSE_BUFFERSIZE ; qc->tf.lbah =0 ; }
@@ -2527,12 +2527,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)if (using_pio || nodata) {/* no data, or PIO data xfer */ if (nodata) - qc->tf.protocol =ATA_PROT_ATAPI_NODATA ; + qc->tf.protocol =ATAPI_PROT_NODATA ;else - qc->tf.protocol =ATA_PROT_ATAPI ; + qc->tf.protocol =ATAPI_PROT_PIO ; }else {/* DMA data xfer */ - qc->tf.protocol =ATA_PROT_ATAPI_DMA ; + qc->tf.protocol =ATAPI_PROT_DMA ; qc->tf.feature |=ATAPI_PKT_DMA ;if (atapi_dmadir && (scmd->sc_data_direction !=DMA_TO_DEVICE ))
drivers/ata/libata-sff.c +1 -1
@@ -417,7 +417,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ap->hsm_task_state =HSM_ST_IDLE ;if (qc && (qc->tf.protocol ==ATA_PROT_DMA || - qc->tf.protocol ==ATA_PROT_ATAPI_DMA )) { + qc->tf.protocol ==ATAPI_PROT_DMA )) {u8 host_stat; host_stat = ap->ops->bmdma_status (ap);
drivers/ata/pata_pdc202xx_old.c +2 -3
@@ -168,8 +168,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)pdc202xx_set_dmamode (ap, qc->dev);/* Cases the state machine will not complete correctly without help */ -if ((tf->flags &ATA_TFLAG_LBA48 ) || tf->protocol ==ATA_PROT_ATAPI_DMA ) - { +if ((tf->flags &ATA_TFLAG_LBA48 ) || tf->protocol ==ATAPI_PROT_DMA ) { len = qc->nbytes /2 ;if (tf->flags &ATA_TFLAG_WRITE )
@@ -208,7 +207,7 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc)void __iomem *atapi_reg = master +0x20 + (4 * ap->port_no);/* Cases the state machine will not complete correctly */ -if (tf->protocol ==ATA_PROT_ATAPI_DMA || ( tf->flags &ATA_TFLAG_LBA48 )) { +if (tf->protocol ==ATAPI_PROT_DMA || (tf->flags &ATA_TFLAG_LBA48 )) {iowrite32 (0 , atapi_reg);iowrite8 (ioread8 (clock) & ~sel66, clock); }
drivers/ata/pdc_adma.c +1 -1
@@ -455,7 +455,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)adma_packet_start (qc);return 0 ; -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :BUG ();break ;
drivers/ata/sata_inic162x.c +1 -1
@@ -585,7 +585,7 @@ static struct ata_port_operations inic_port_ops = { };static struct ata_port_info inic_port_info = { -/* For some reason, ATA_PROT_ATAPI is broken on this +/* For some reason, ATAPI_PROT_PIO is broken on this * controller, and no, PIO_POLLING does't fix it. It somehow * manages to report the wrong ireason and ignoring ireason * results in machine lock up. Tell libata to always prefer
drivers/ata/sata_promise.c +12 -14
@@ -456,13 +456,13 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)* and seq id (byte 2) */ switch (qc->tf.protocol) { -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :if (!(qc->tf.flags &ATA_TFLAG_WRITE )) buf32[0 ] =cpu_to_le32 (PDC_PKT_READ );else buf32[0 ] =0 ;break ; -case ATA_PROT_ATAPI_NODATA : +case ATAPI_PROT_NODATA : buf32[0 ] =cpu_to_le32 (PDC_PKT_NODATA );break ;default :
@@ -489,7 +489,7 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc) buf[19 ] = qc->tf.lbal;/* set feature and byte counter registers */ -if (qc->tf.protocol !=ATA_PROT_ATAPI_DMA ) +if (qc->tf.protocol !=ATAPI_PROT_DMA ) feature =PDC_FEATURE_ATAPI_PIO ;else feature =PDC_FEATURE_ATAPI_DMA ;
@@ -619,14 +619,14 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)pdc_pkt_footer (&qc->tf, pp->pkt, i);break ; -case ATA_PROT_ATAPI : +case ATAPI_PROT_PIO :pdc_fill_sg (qc);break ; -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :pdc_fill_sg (qc);/*FALLTHROUGH*/ -case ATA_PROT_ATAPI_NODATA : +case ATAPI_PROT_NODATA :pdc_atapi_pkt (qc);break ;
@@ -746,8 +746,8 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap,switch (qc->tf.protocol) {case ATA_PROT_DMA :case ATA_PROT_NODATA : -case ATA_PROT_ATAPI_DMA : -case ATA_PROT_ATAPI_NODATA : +case ATAPI_PROT_DMA : +case ATAPI_PROT_NODATA : qc->err_mask |=ac_err_mask (ata_wait_idle (ap));ata_qc_complete (qc); handled =1 ;
@@ -892,7 +892,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)static unsigned int pdc_qc_issue_prot (struct ata_queued_cmd *qc) {switch (qc->tf.protocol) { -case ATA_PROT_ATAPI_NODATA : +case ATAPI_PROT_NODATA :if (qc->dev->flags &ATA_DFLAG_CDB_INTR )break ;/*FALLTHROUGH*/
@@ -900,7 +900,7 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)if (qc->tf.flags &ATA_TFLAG_POLLING )break ;/*FALLTHROUGH*/ -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :case ATA_PROT_DMA :pdc_packet_start (qc);return 0 ;
@@ -914,16 +914,14 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)static void pdc_tf_load_mmio (struct ata_port *ap,const struct ata_taskfile *tf) { -WARN_ON (tf->protocol ==ATA_PROT_DMA || - tf->protocol ==ATA_PROT_ATAPI_DMA ); +WARN_ON (tf->protocol ==ATA_PROT_DMA || tf->protocol ==ATAPI_PROT_DMA );ata_tf_load (ap, tf); }static void pdc_exec_command_mmio (struct ata_port *ap,const struct ata_taskfile *tf) { -WARN_ON (tf->protocol ==ATA_PROT_DMA || - tf->protocol ==ATA_PROT_ATAPI_DMA ); +WARN_ON (tf->protocol ==ATA_PROT_DMA || tf->protocol ==ATAPI_PROT_DMA );ata_exec_command (ap, tf); }
drivers/ata/sata_qstor.c +1 -1
@@ -376,7 +376,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)qs_packet_start (qc);return 0 ; -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :BUG ();break ;
drivers/ata/sata_sx4.c +1 -1
@@ -700,7 +700,7 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)pdc20621_packet_start (qc);return 0 ; -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :BUG ();break ;
drivers/scsi/ipr.c +3 -3
@@ -5222,12 +5222,12 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc) regs->flags |=IPR_ATA_FLAG_XFER_TYPE_DMA ;break ; -case ATA_PROT_ATAPI : -case ATA_PROT_ATAPI_NODATA : +case ATAPI_PROT_PIO : +case ATAPI_PROT_NODATA : regs->flags |=IPR_ATA_FLAG_PACKET_CMD ;break ; -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA : regs->flags |=IPR_ATA_FLAG_PACKET_CMD ; regs->flags |=IPR_ATA_FLAG_XFER_TYPE_DMA ;break ;
drivers/scsi/libsas/sas_ata.c +1 -1
@@ -200,7 +200,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)case ATA_PROT_NCQ : task->ata_task.use_ncq =1 ;/* fall through */ -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :case ATA_PROT_DMA : task->ata_task.dma_xfer =1 ;break ;
include/linux/ata.h +6 -6
@@ -326,9 +326,9 @@ enum ata_tf_protocols {ATA_PROT_PIO ,/* PIO data xfer */ ATA_PROT_DMA ,/* DMA */ ATA_PROT_NCQ ,/* NCQ */ -ATA_PROT_ATAPI ,/* packet command, PIO data xfer*/ -ATA_PROT_ATAPI_NODATA ,/* packet command, no data */ - ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */ +ATAPI_PROT_NODATA ,/* packet command, no data */ +ATAPI_PROT_PIO ,/* packet command, PIO data xfer*/ + ATAPI_PROT_DMA, /* packet command with special DMA sauce */ }; enum ata_ioctls {
@@ -380,11 +380,11 @@ static inline unsigned int ata_prot_flags(u8 prot)return ATA_PROT_FLAG_DMA ;case ATA_PROT_NCQ :return ATA_PROT_FLAG_DMA |ATA_PROT_FLAG_NCQ ; -case ATA_PROT_ATAPI_NODATA : +case ATAPI_PROT_NODATA :return ATA_PROT_FLAG_ATAPI ; -case ATA_PROT_ATAPI : +case ATAPI_PROT_PIO :return ATA_PROT_FLAG_ATAPI |ATA_PROT_FLAG_PIO ; -case ATA_PROT_ATAPI_DMA : +case ATAPI_PROT_DMA :return ATA_PROT_FLAG_ATAPI |ATA_PROT_FLAG_DMA ; }return 0 ;
Signature · 1 line
1.5.2.4
PATCH 9/15 libata: kill non-sg DMA interface
In reply to Tejun HeoWith atapi_request_sense() converted to use sg, there's no user of non-sg interface. Kill non-sg interface.
* ATA_QCFLAG_SINGLE and ATA_QCFLAG_SG are removed. ATA_QCFLAG_DMAMAP is used instead. (this way no LLD change is necessary)
* qc->buf_virt is removed.
* ata_sg_init_one() and ata_sg_setup_one() are removed.
--- drivers/ata/libata-core.c | 148 +++++---------------------------------------- include/linux/libata.h | 7 +-- 2 files changed, 16 insertions(+), 139 deletions(-)
drivers/ata/libata-core.c +15 -133
@@ -4490,9 +4490,6 @@ void ata_sg_clean(struct ata_queued_cmd *qc)WARN_ON (!(qc->flags &ATA_QCFLAG_DMAMAP ));WARN_ON (sg ==NULL ); -if (qc->flags &ATA_QCFLAG_SINGLE ) -WARN_ON (qc->n_elem >1 ); -VPRINTK ("unmapping %u sg elements\n" , qc->n_elem);/* if we padded the buffer out to 32-bit bound, and data
@@ -4502,27 +4499,15 @@ void ata_sg_clean(struct ata_queued_cmd *qc)if (qc->pad_len && !(qc->tf.flags &ATA_TFLAG_WRITE )) pad_buf = ap->pad + (qc->tag *ATA_DMA_PAD_SZ ); -if (qc->flags &ATA_QCFLAG_SG ) { -if (qc->n_elem) -dma_unmap_sg (ap->dev, sg, qc->n_elem, dir); -/* restore last sg */ -sg_last (sg, qc->orig_n_elem)->length += qc->pad_len; -if (pad_buf) { -struct scatterlist *psg = &qc->pad_sgent; -void *addr =kmap_atomic (sg_page (psg),KM_IRQ0 ); -memcpy (addr + psg->offset, pad_buf, qc->pad_len); -kunmap_atomic (addr,KM_IRQ0 ); - } - }else { -if (qc->n_elem) -dma_unmap_single (ap->dev, -sg_dma_address (&sg[0 ]),sg_dma_len (&sg[0 ]), - dir); -/* restore sg */ - sg->length += qc->pad_len; -if (pad_buf) -memcpy (qc->buf_virt + sg->length - qc->pad_len, - pad_buf, qc->pad_len); +if (qc->n_elem) +dma_unmap_sg (ap->dev, sg, qc->n_elem, dir); +/* restore last sg */ +sg_last (sg, qc->orig_n_elem)->length += qc->pad_len; +if (pad_buf) { +struct scatterlist *psg = &qc->pad_sgent; +void *addr =kmap_atomic (sg_page (psg),KM_IRQ0 ); +memcpy (addr + psg->offset, pad_buf, qc->pad_len); +kunmap_atomic (addr,KM_IRQ0 ); } qc->flags &= ~ATA_QCFLAG_DMAMAP ;
@@ -4762,33 +4747,6 @@ void ata_dumb_qc_prep(struct ata_queued_cmd *qc)void ata_noop_qc_prep (struct ata_queued_cmd *qc) { }/** -* ata_sg_init_one - Associate command with memory buffer -* @qc: Command to be associated -* @buf: Memory buffer -* @buflen: Length of memory buffer, in bytes. -* -* Initialize the data-related elements of queued_cmd @qc -* to point to a single memory buffer, @buf of byte length @buflen. -* -* LOCKING: -* spin_lock_irqsave(host lock) -*/ - -void ata_sg_init_one (struct ata_queued_cmd *qc,void *buf,unsigned int buflen) -{ - qc->flags |=ATA_QCFLAG_SINGLE ; - - qc->__sg = &qc->sgent; - qc->n_elem =1 ; - qc->orig_n_elem =1 ; - qc->buf_virt = buf; - qc->nbytes = buflen; - qc->cursg = qc->__sg; - -sg_init_one (&qc->sgent, buf, buflen); -} - -/** * ata_sg_init - Associate command with scatter-gather table. * @qc: Command to be associated * @sg: Scatter-gather table.
@@ -4805,7 +4763,7 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)void ata_sg_init (struct ata_queued_cmd *qc,struct scatterlist *sg,unsigned int n_elem) { - qc->flags |=ATA_QCFLAG_SG ; + qc->flags |=ATA_QCFLAG_DMAMAP ; qc->__sg = sg; qc->n_elem = n_elem; qc->orig_n_elem = n_elem;
@@ -4813,75 +4771,6 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, }/** -* ata_sg_setup_one - DMA-map the memory buffer associated with a command. -* @qc: Command with memory buffer to be mapped. -* -* DMA-map the memory buffer associated with queued_cmd @qc. -* -* LOCKING: -* spin_lock_irqsave(host lock) -* -* RETURNS: -* Zero on success, negative on error. -*/ - -static int ata_sg_setup_one (struct ata_queued_cmd *qc) -{ -struct ata_port *ap = qc->ap; -int dir = qc->dma_dir; -struct scatterlist *sg = qc->__sg; -dma_addr_t dma_address; -int trim_sg =0 ; - -/* we must lengthen transfers to end on a 32-bit boundary */ - qc->pad_len = sg->length &3 ; -if (qc->pad_len) { -void *pad_buf = ap->pad + (qc->tag *ATA_DMA_PAD_SZ ); -struct scatterlist *psg = &qc->pad_sgent; - -WARN_ON (qc->dev->class !=ATA_DEV_ATAPI ); - -memset (pad_buf,0 ,ATA_DMA_PAD_SZ ); - -if (qc->tf.flags &ATA_TFLAG_WRITE ) -memcpy (pad_buf, qc->buf_virt + sg->length - qc->pad_len, - qc->pad_len); - -sg_dma_address (psg) = ap->pad_dma + (qc->tag *ATA_DMA_PAD_SZ ); -sg_dma_len (psg) =ATA_DMA_PAD_SZ ; -/* trim sg */ - sg->length -= qc->pad_len; -if (sg->length ==0 ) - trim_sg =1 ; - -DPRINTK ("padding done, sg->length=%u pad_len=%u\n" , - sg->length, qc->pad_len); - } - -if (trim_sg) { - qc->n_elem--; - goto skip_map; - } - - dma_address =dma_map_single (ap->dev, qc->buf_virt, - sg->length, dir); -if (dma_mapping_error (dma_address)) { -/* restore sg */ - sg->length += qc->pad_len; -return -1 ; - } - -sg_dma_address (sg) = dma_address; -sg_dma_len (sg) = sg->length; - -skip_map: -DPRINTK ("mapped buffer of %d bytes for %s\n" ,sg_dma_len (sg), - qc->tf.flags &ATA_TFLAG_WRITE ?"write" :"read" ); - -return 0 ; -} - -/** * ata_sg_setup - DMA-map the scatter-gather table associated with a command. * @qc: Command with scatter-gather table to be mapped. *
@@ -4903,7 +4792,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)int n_elem, pre_n_elem, dir, trim_sg =0 ;VPRINTK ("ENTER, ata%u\n" , ap->print_id); -WARN_ON (!(qc->flags &ATA_QCFLAG_SG )); +WARN_ON (!(qc->flags &ATA_QCFLAG_DMAMAP ));/* we must lengthen transfers to end on a 32-bit boundary */ qc->pad_len = lsg->length &3 ;
@@ -6028,16 +5917,10 @@ void ata_qc_issue(struct ata_queued_cmd *qc)if (ata_is_dma (prot) || (ata_is_pio (prot) && (ap->flags &ATA_FLAG_PIO_DMA ))) { -if (qc->flags &ATA_QCFLAG_SG ) { -if (ata_sg_setup (qc)) - goto sg_err; - }else if (qc->flags &ATA_QCFLAG_SINGLE ) { -if (ata_sg_setup_one (qc)) - goto sg_err; - } - }else { - qc->flags &= ~ATA_QCFLAG_DMAMAP ; - } +if (ata_sg_setup (qc)) + goto sg_err; + }else + qc->flags &=ATA_QCFLAG_DMAMAP ;/* if device is sleeping, schedule softreset and abort the link */ if (unlikely (qc->dev->flags &ATA_DFLAG_SLEEPING )) {
@@ -7625,7 +7508,6 @@ EXPORT_SYMBOL_GPL(ata_host_register);EXPORT_SYMBOL_GPL (ata_host_activate);EXPORT_SYMBOL_GPL (ata_host_detach);EXPORT_SYMBOL_GPL (ata_sg_init); -EXPORT_SYMBOL_GPL (ata_sg_init_one);EXPORT_SYMBOL_GPL (ata_hsm_move);EXPORT_SYMBOL_GPL (ata_qc_complete);EXPORT_SYMBOL_GPL (ata_qc_complete_multiple);
include/linux/libata.h +1 -6
@@ -220,9 +220,7 @@ enum {/* struct ata_queued_cmd flags */ ATA_QCFLAG_ACTIVE = (1 <<0 ),/* cmd not yet ack'd to scsi lyer */ -ATA_QCFLAG_SG = (1 <<1 ),/* have s/g table? */ -ATA_QCFLAG_SINGLE = (1 <<2 ),/* no s/g, just a single buffer */ -ATA_QCFLAG_DMAMAP =ATA_QCFLAG_SG |ATA_QCFLAG_SINGLE , +ATA_QCFLAG_DMAMAP = (1 <<1 ),/* SG table is DMA mapped */ ATA_QCFLAG_IO = (1 <<3 ),/* standard IO command */ ATA_QCFLAG_RESULT_TF = (1 <<4 ),/* result TF requested */ ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */
@@ -476,7 +474,6 @@ struct ata_queued_cmd {struct scatterlist sgent;struct scatterlist pad_sgent; -void *buf_virt;/* DO NOT iterate over __sg manually, use ata_for_each_sg() */ struct scatterlist *__sg;
@@ -892,8 +889,6 @@ extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);extern void ata_qc_prep (struct ata_queued_cmd *qc);extern void ata_noop_qc_prep (struct ata_queued_cmd *qc);extern unsigned int ata_qc_issue_prot (struct ata_queued_cmd *qc); -extern void ata_sg_init_one (struct ata_queued_cmd *qc,void *buf, -unsigned int buflen);extern void ata_sg_init (struct ata_queued_cmd *qc,struct scatterlist *sg,unsigned int n_elem);extern unsigned int ata_dev_classify (const struct ata_taskfile *tf);
Signature · 1 line
1.5.2.4
PATCH 4/15 cdrom: add more GPCMD_* constants
In reply to Tejun HeoAdd GPCMD_* constants for READ_BUFFER, WRITE_12 and WRITE_BUFFER for completeness. These will be used libata.
--- include/linux/cdrom.h | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
include/linux/cdrom.h +3 -0
@@ -451,6 +451,7 @@ struct cdrom_generic_command#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e#define GPCMD_READ_10 0x28#define GPCMD_READ_12 0xa8 +#define GPCMD_READ_BUFFER 0x3c#define GPCMD_READ_BUFFER_CAPACITY 0x5c#define GPCMD_READ_CDVD_CAPACITY 0x25#define GPCMD_READ_CD 0xbe
@@ -480,7 +481,9 @@ struct cdrom_generic_command#define GPCMD_TEST_UNIT_READY 0x00#define GPCMD_VERIFY_10 0x2f#define GPCMD_WRITE_10 0x2a +#define GPCMD_WRITE_12 0xaa#define GPCMD_WRITE_AND_VERIFY_10 0x2e +#define GPCMD_WRITE_BUFFER 0x3b/* This is listed as optional in ATAPI 2.6, but is (curiously) * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji * Table 377 as an MMC command for SCSi devices though... Most ATAPI
Signature · 1 line
1.5.2.4
PATCH 7/15 change-data_xfer
In reply to Tejun HeoDepending on how many bytes are transferred as a unit, PIO data tranasfer may consume more bytes than requested. Knowing how much data is consumed is necessary to determine how much is left for draining. This patch update ->data_xfer such that it returns the number of consumed bytes.
While at it, it also makes the following changes.
* s/adev/dev/
* use READ/WRITE constants for rw indication
* misc clean ups
--- drivers/ata/libata-core.c | 46 +++++++++++++++++++++++++++-------------- drivers/ata/pata_bf54x.c | 28 +++++++++++++----------- drivers/ata/pata_ixp4xx_cf.c | 26 ++++++++++++----------- drivers/ata/pata_legacy.c | 36 +++++++++++++++++--------------- drivers/ata/pata_qdi.c | 30 +++++++++++++++----------- drivers/ata/pata_scc.c | 30 ++++++++++++++------------ drivers/ata/pata_winbond.c | 28 ++++++++++++++----------- include/linux/libata.h | 11 +++++---- 8 files changed, 133 insertions(+), 102 deletions(-)
drivers/ata/libata-core.c +30 -16
@@ -4969,7 +4969,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)/** * ata_data_xfer - Transfer data by PIO -* @adev: device to target +* @dev: device to target * @buf: data buffer * @buflen: buffer length * @write_data: read/write
@@ -4978,37 +4978,44 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)* * LOCKING: * Inherited from caller. +* +* RETURNS: +* Bytes consumed. */ -void ata_data_xfer (struct ata_device *adev,unsigned char *buf, -unsigned int buflen,int write_data) +unsigned int ata_data_xfer (struct ata_device *dev,unsigned char *buf, +unsigned int buflen,int rw) { -struct ata_port *ap = adev->link->ap; +struct ata_port *ap = dev->link->ap; +void __iomem *data_addr = ap->ioaddr.data_addr;unsigned int words = buflen >>1 ;/* Transfer multiple of 2 bytes */ -if (write_data) -iowrite16_rep (ap->ioaddr.data_addr, buf, words); +if (rw ==READ ) +ioread16_rep (data_addr, buf, words);else -ioread16_rep (ap->ioaddr.data_addr, buf, words); +iowrite16_rep (data_addr, buf, words);/* Transfer trailing 1 byte, if any. */ if (unlikely (buflen &0x01 )) {u16 align_buf[1 ] = {0 };unsigned char *trailing_buf = buf + buflen -1 ; -if (write_data) { -memcpy (align_buf, trailing_buf,1 ); -iowrite16 (le16_to_cpu (align_buf[0 ]), ap->ioaddr.data_addr); - }else { - align_buf[0 ] =cpu_to_le16 (ioread16 (ap->ioaddr.data_addr)); +if (rw ==READ ) { + align_buf[0 ] =cpu_to_le16 (ioread16 (data_addr));memcpy (trailing_buf, align_buf,1 ); + }else { +memcpy (align_buf, trailing_buf,1 ); +iowrite16 (le16_to_cpu (align_buf[0 ]), data_addr); } + words++; } + +return words <<1 ; }/** * ata_data_xfer_noirq - Transfer data by PIO -* @adev: device to target +* @dev: device to target * @buf: data buffer * @buflen: buffer length * @write_data: read/write
@@ -5018,14 +5025,21 @@ void ata_data_xfer(struct ata_device *adev, unsigned char *buf,* * LOCKING: * Inherited from caller. +* +* RETURNS: +* Bytes consumed. */ -void ata_data_xfer_noirq (struct ata_device *adev,unsigned char *buf, -unsigned int buflen,int write_data) +unsigned int ata_data_xfer_noirq (struct ata_device *dev,unsigned char *buf, +unsigned int buflen,int rw) {unsigned long flags; +unsigned int consumed; +local_irq_save (flags); -ata_data_xfer (adev, buf, buflen, write_data); + consumed =ata_data_xfer (dev, buf, buflen, rw);local_irq_restore (flags); + +return consumed; }
drivers/ata/pata_bf54x.c +15 -13
@@ -1167,34 +1167,36 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)* Note: Original code is ata_data_xfer(). */ -static void bfin_data_xfer (struct ata_device *adev,unsigned char *buf, -unsigned int buflen,int write_data) +static unsigned int bfin_data_xfer (struct ata_device *dev,unsigned char *buf, +unsigned int buflen,int rw) { -struct ata_port *ap = adev->link->ap; -unsigned int words = buflen >>1 ; -unsigned short *buf16 = (u16 *) buf; +struct ata_port *ap = dev->link->ap;void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; +unsigned int words = buflen >>1 ; +unsigned short *buf16 = (u16 *)buf;/* Transfer multiple of 2 bytes */ -if (write_data) { -write_atapi_data (base, words, buf16); - }else { +if (rw ==READ )read_atapi_data (base, words, buf16); - } +else +write_atapi_data (base, words, buf16);/* Transfer trailing 1 byte, if any. */ if (unlikely (buflen &0x01 )) {unsigned short align_buf[1 ] = {0 };unsigned char *trailing_buf = buf + buflen -1 ; -if (write_data) { -memcpy (align_buf, trailing_buf,1 ); -write_atapi_data (base,1 , align_buf); - }else { +if (rw ==READ ) {read_atapi_data (base,1 , align_buf);memcpy (trailing_buf, align_buf,1 ); + }else { +memcpy (align_buf, trailing_buf,1 ); +write_atapi_data (base,1 , align_buf); } + words++; } + +return words <<1 ; }/**
drivers/ata/pata_ixp4xx_cf.c +14 -12
@@ -42,13 +42,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)return 0 ; } -static void ixp4xx_mmio_data_xfer (struct ata_device *adev,unsigned char *buf, -unsigned int buflen,int write_data) +static unsigned int ixp4xx_mmio_data_xfer (struct ata_device *dev, +unsigned char *buf,unsigned int buflen,int rw) {unsigned int i;unsigned int words = buflen >>1 ;u16 *buf16 = (u16 *) buf; -struct ata_port *ap = adev->link->ap; +struct ata_port *ap = dev->link->ap;void __iomem *mmio = ap->ioaddr.data_addr;struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
@@ -59,30 +59,32 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,udelay (100 );/* Transfer multiple of 2 bytes */ -if (write_data) { -for (i =0 ; i < words; i++) -writew (buf16[i], mmio); - }else { +if (rw ==READ )for (i =0 ; i < words; i++) buf16[i] =readw (mmio); - } +else +for (i =0 ; i < words; i++) +writew (buf16[i], mmio);/* Transfer trailing 1 byte, if any. */ if (unlikely (buflen &0x01 )) {u16 align_buf[1 ] = {0 };unsigned char *trailing_buf = buf + buflen -1 ; -if (write_data) { -memcpy (align_buf, trailing_buf,1 ); -writew (align_buf[0 ], mmio); - }else { +if (rw ==READ ) { align_buf[0 ] =readw (mmio);memcpy (trailing_buf, align_buf,1 ); + }else { +memcpy (align_buf, trailing_buf,1 ); +writew (align_buf[0 ], mmio); } + words++; }udelay (100 ); *data->cs0_cfg |=0x01 ; + +return words <<1 ; }static struct scsi_host_template ixp4xx_sht = {
drivers/ata/pata_legacy.c +19 -17
@@ -249,13 +249,14 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev) } -static void pdc_data_xfer_vlb (struct ata_device *adev,unsigned char *buf,unsigned int buflen,int write_data) +static unsigned int pdc_data_xfer_vlb (struct ata_device *dev, +unsigned char *buf,unsigned int buflen,int rw) { -struct ata_port *ap = adev->link->ap; -int slop = buflen &3 ; -unsigned long flags; -if (ata_id_has_dword_io (adev->id)) { +struct ata_port *ap = dev->link->ap; +int slop = buflen &3 ; +unsigned long flags; +local_irq_save (flags);/* Perform the 32bit I/O synchronization sequence */
@@ -264,28 +265,29 @@ static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigioread8 (ap->ioaddr.nsect_addr);/* Now the data */ - -if (write_data) -iowrite32_rep (ap->ioaddr.data_addr, buf, buflen >>2 ); -else +if (rw ==READ )ioread32_rep (ap->ioaddr.data_addr, buf, buflen >>2 ); +else +iowrite32_rep (ap->ioaddr.data_addr, buf, buflen >>2 );if (unlikely (slop)) {u32 pad; -if (write_data) { -memcpy (&pad, buf + buflen - slop, slop); - pad =le32_to_cpu (pad); -iowrite32 (pad, ap->ioaddr.data_addr); - }else { +if (rw ==READ ) { pad =ioread32 (ap->ioaddr.data_addr); pad =cpu_to_le16 (pad);memcpy (buf + buflen - slop, &pad, slop); + }else { +memcpy (&pad, buf + buflen - slop, slop); + pad =le32_to_cpu (pad); +iowrite32 (pad, ap->ioaddr.data_addr); } + buflen +=4 - slop; }local_irq_restore (flags); - } -else -ata_data_xfer_noirq (adev, buf, buflen, write_data); + }else + buflen =ata_data_xfer_noirq (dev, buf, buflen, rw); + +return buflen; }static struct ata_port_operations pdc20230_port_ops = {
drivers/ata/pata_qdi.c +17 -13
@@ -124,31 +124,35 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)return ata_qc_issue_prot (qc); } -static void qdi_data_xfer (struct ata_device *adev,unsigned char *buf,unsigned int buflen,int write_data) +static unsigned int qdi_data_xfer (struct ata_device *dev,unsigned char *buf, +unsigned int buflen,int rw) { -struct ata_port *ap = adev->link->ap; -int slop = buflen &3 ; +if (ata_id_has_dword_io (dev->id)) { +struct ata_port *ap = dev->link->ap; +int slop = buflen &3 ; -if (ata_id_has_dword_io (adev->id)) { -if (write_data) -iowrite32_rep (ap->ioaddr.data_addr, buf, buflen >>2 ); -else +if (rw ==READ )ioread32_rep (ap->ioaddr.data_addr, buf, buflen >>2 ); +else +iowrite32_rep (ap->ioaddr.data_addr, buf, buflen >>2 );if (unlikely (slop)) {u32 pad; -if (write_data) { -memcpy (&pad, buf + buflen - slop, slop); - pad =le32_to_cpu (pad); -iowrite32 (pad, ap->ioaddr.data_addr); - }else { +if (rw ==READ ) { pad =ioread32 (ap->ioaddr.data_addr); pad =cpu_to_le32 (pad);memcpy (buf + buflen - slop, &pad, slop); + }else { +memcpy (&pad, buf + buflen - slop, slop); + pad =le32_to_cpu (pad); +iowrite32 (pad, ap->ioaddr.data_addr); } + buflen +=4 - slop; } }else -ata_data_xfer (adev, buf, buflen, write_data); + buflen =ata_data_xfer (dev, buf, buflen, rw); + +return buflen; }static struct scsi_host_template qdi_sht = {
drivers/ata/pata_scc.c +16 -14
@@ -768,45 +768,47 @@ static u8 scc_bmdma_status (struct ata_port *ap)/** * scc_data_xfer - Transfer data by PIO -* @adev: device for this I/O +* @dev: device for this I/O * @buf: data buffer * @buflen: buffer length -* @write_data: read/write +* @rw: read/write * * Note: Original code is ata_data_xfer(). */ -static void scc_data_xfer (struct ata_device *adev,unsigned char *buf, -unsigned int buflen,int write_data) +static unsigned int scc_data_xfer (struct ata_device *dev,unsigned char *buf, +unsigned int buflen,int rw) { -struct ata_port *ap = adev->link->ap; +struct ata_port *ap = dev->link->ap;unsigned int words = buflen >>1 ;unsigned int i;u16 *buf16 = (u16 *) buf;void __iomem *mmio = ap->ioaddr.data_addr;/* Transfer multiple of 2 bytes */ -if (write_data) { -for (i =0 ; i < words; i++) -out_be32 (mmio,cpu_to_le16 (buf16[i])); - }else { +if (rw ==READ )for (i =0 ; i < words; i++) buf16[i] =le16_to_cpu (in_be32 (mmio)); - } +else +for (i =0 ; i < words; i++) +out_be32 (mmio,cpu_to_le16 (buf16[i]));/* Transfer trailing 1 byte, if any. */ if (unlikely (buflen &0x01 )) {u16 align_buf[1 ] = {0 };unsigned char *trailing_buf = buf + buflen -1 ; -if (write_data) { -memcpy (align_buf, trailing_buf,1 ); -out_be32 (mmio,cpu_to_le16 (align_buf[0 ])); - }else { +if (rw ==READ ) { align_buf[0 ] =le16_to_cpu (in_be32 (mmio));memcpy (trailing_buf, align_buf,1 ); + }else { +memcpy (align_buf, trailing_buf,1 ); +out_be32 (mmio,cpu_to_le16 (align_buf[0 ])); } + words++; } + +return words <<1 ; }/**
drivers/ata/pata_winbond.c +16 -12
@@ -92,31 +92,35 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) } -static void winbond_data_xfer (struct ata_device *adev,unsigned char *buf,unsigned int buflen,int write_data) +static void winbond_data_xfer (struct ata_device *dev,unsigned char *buf, +unsigned int buflen,int rw) { -struct ata_port *ap = adev->link->ap; +struct ata_port *ap = dev->link->ap;int slop = buflen &3 ; -if (ata_id_has_dword_io (adev->id)) { -if (write_data) -iowrite32_rep (ap->ioaddr.data_addr, buf, buflen >>2 ); -else +if (ata_id_has_dword_io (dev->id)) { +if (rw ==READ )ioread32_rep (ap->ioaddr.data_addr, buf, buflen >>2 ); +else +iowrite32_rep (ap->ioaddr.data_addr, buf, buflen >>2 );if (unlikely (slop)) {u32 pad; -if (write_data) { -memcpy (&pad, buf + buflen - slop, slop); - pad =le32_to_cpu (pad); -iowrite32 (pad, ap->ioaddr.data_addr); - }else { +if (rw == read) { pad =ioread32 (ap->ioaddr.data_addr); pad =cpu_to_le16 (pad);memcpy (buf + buflen - slop, &pad, slop); + }else { +memcpy (&pad, buf + buflen - slop, slop); + pad =le32_to_cpu (pad); +iowrite32 (pad, ap->ioaddr.data_addr); } + buflen +=4 - slop; } }else -ata_data_xfer (adev, buf, buflen, write_data); + buflen =ata_data_xfer (dev, buf, buflen, rw); + +return buflen; }static struct scsi_host_template winbond_sht = {
include/linux/libata.h +6 -5
@@ -700,7 +700,8 @@ struct ata_port_operations {void (*bmdma_setup) (struct ata_queued_cmd *qc);void (*bmdma_start) (struct ata_queued_cmd *qc); -void (*data_xfer) (struct ata_device *,unsigned char *,unsigned int ,int ); +unsigned int (*data_xfer) (struct ata_device *dev,unsigned char *buf, +unsigned int buflen,int rw);int (*qc_defer) (struct ata_queued_cmd *qc);void (*qc_prep) (struct ata_queued_cmd *qc);
@@ -880,10 +881,10 @@ extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)extern int ata_port_start (struct ata_port *ap);extern int ata_sff_port_start (struct ata_port *ap);extern irqreturn_t ata_interrupt (int irq,void *dev_instance); -extern void ata_data_xfer (struct ata_device *adev,unsigned char *buf, -unsigned int buflen,int write_data); -extern void ata_data_xfer_noirq (struct ata_device *adev,unsigned char *buf, -unsigned int buflen,int write_data); +extern unsigned int ata_data_xfer (struct ata_device *dev, +unsigned char *buf,unsigned int buflen,int rw); +extern unsigned int ata_data_xfer_noirq (struct ata_device *dev, +unsigned char *buf,unsigned int buflen,int rw);extern int ata_std_qc_defer (struct ata_queued_cmd *qc);extern void ata_dumb_qc_prep (struct ata_queued_cmd *qc);extern void ata_qc_prep (struct ata_queued_cmd *qc);
Signature · 1 line
1.5.2.4
PATCH 11/15 libata: convert to chained sg
In reply to Tejun Heolibata used private sg iterator to handle padding sg. Now that sg can be chained, padding can be handled using standard sg ops. Convert to chained sg.
* s/qc->__sg/qc->sg/
* s/qc->pad_sgent/qc->extra_sg[]/. Because chaining consumes one sg entry. There need to be two extra sg entries. The renaming is also for future addition of other extra sg entries.
* Padding setup is moved into ata_sg_setup_extra() which is organized in a way that future addition of other extra sg entries is easy.
* qc->orig_n_elem is unused and removed.
* qc->n_elem now contains the number of sg entries that LLDs should map. qc->mapped_n_elem is added to carry the original number of mapped sgs for unmapping.
* The last sg of the original sg list is used to chain to extra sg list. The original last sg is pointed to by qc->last_sg and the content is stored in qc->saved_last_sg. It's restored during ata_sg_clean().
* All sg walking code has been updated. Unnecessary assertions and checks for conditions the core layer already guarantees are removed.
--- drivers/ata/ahci.c | 18 ++--- drivers/ata/libata-core.c | 201 ++++++++++++++++++++++++----------------- drivers/ata/libata-scsi.c | 2 +- drivers/ata/pata_bf54x.c | 13 ++- drivers/ata/pata_icside.c | 3 +- drivers/ata/pdc_adma.c | 3 +- drivers/ata/sata_fsl.c | 4 +- drivers/ata/sata_mv.c | 3 +- drivers/ata/sata_nv.c | 25 ++---- drivers/ata/sata_promise.c | 40 ++++----- drivers/ata/sata_qstor.c | 13 +-- drivers/ata/sata_sil24.c | 6 +- drivers/ata/sata_sx4.c | 4 +- drivers/scsi/ipr.c | 3 +- drivers/scsi/libsas/sas_ata.c | 10 +-- include/linux/libata.h | 42 ++------- 16 files changed, 193 insertions(+), 197 deletions(-)
drivers/ata/ahci.c +7 -11
@@ -1481,28 +1481,24 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)static unsigned int ahci_fill_sg (struct ata_queued_cmd *qc,void *cmd_tbl) {struct scatterlist *sg; -struct ahci_sg *ahci_sg; -unsigned int n_sg =0 ; +struct ahci_sg *ahci_sg = cmd_tbl +AHCI_CMD_TBL_HDR_SZ ; +unsigned int si;VPRINTK ("ENTER\n" );/* * Next, the S/G list. */ - ahci_sg = cmd_tbl +AHCI_CMD_TBL_HDR_SZ ; -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {dma_addr_t addr =sg_dma_address (sg);u32 sg_len =sg_dma_len (sg); - ahci_sg->addr =cpu_to_le32 (addr &0xffffffff ); - ahci_sg->addr_hi =cpu_to_le32 ((addr >>16 ) >>16 ); - ahci_sg->flags_size =cpu_to_le32 (sg_len -1 ); - - ahci_sg++; - n_sg++; + ahci_sg[si].addr =cpu_to_le32 (addr &0xffffffff ); + ahci_sg[si].addr_hi =cpu_to_le32 ((addr >>16 ) >>16 ); + ahci_sg[si].flags_size =cpu_to_le32 (sg_len -1 ); } -return n_sg; +return si; }static void ahci_qc_prep (struct ata_queued_cmd *qc)
drivers/ata/libata-core.c +118 -83
316 lines not on this page · raw message
drivers/ata/libata-scsi.c +1 -1
@@ -517,7 +517,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, qc->scsicmd = cmd; qc->scsidone = done; - qc->__sg =scsi_sglist (cmd); + qc->sg =scsi_sglist (cmd); qc->n_elem =scsi_sg_count (cmd); }else { cmd->result = (DID_OK <<16 ) | (QUEUE_FULL <<1 );
drivers/ata/pata_bf54x.c +8 -5
@@ -832,6 +832,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc) {unsigned short config =WDSIZE_16 ;struct scatterlist *sg; +unsigned int si;pr_debug ("in atapi dma setup\n" );/* Program the ATA_CTRL register with dir */
@@ -839,7 +840,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)/* fill the ATAPI DMA controller */ set_dma_config (CH_ATAPI_TX , config);set_dma_x_modify (CH_ATAPI_TX ,2 ); -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {set_dma_start_addr (CH_ATAPI_TX ,sg_dma_address (sg));set_dma_x_count (CH_ATAPI_TX ,sg_dma_len (sg) >>1 ); }
@@ -848,7 +849,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)/* fill the ATAPI DMA controller */ set_dma_config (CH_ATAPI_RX , config);set_dma_x_modify (CH_ATAPI_RX ,2 ); -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {set_dma_start_addr (CH_ATAPI_RX ,sg_dma_address (sg));set_dma_x_count (CH_ATAPI_RX ,sg_dma_len (sg) >>1 ); }
@@ -867,6 +868,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)struct ata_port *ap = qc->ap;void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;struct scatterlist *sg; +unsigned int si;pr_debug ("in atapi dma start\n" );if (!(ap->udma_mask || ap->mwdma_mask))
@@ -881,7 +883,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)* data cache is enabled. Otherwise, this loop * is an empty loop and optimized out. */ -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {flush_dcache_range (sg_dma_address (sg),sg_dma_address (sg) +sg_dma_len (sg)); }
@@ -910,7 +912,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)ATAPI_SET_CONTROL (base,ATAPI_GET_CONTROL (base) |TFRCNT_RST );/* Set transfer length to buffer len */ -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {ATAPI_SET_XFER_LEN (base, (sg_dma_len (sg) >>1 )); }
@@ -932,6 +934,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc) {struct ata_port *ap = qc->ap;struct scatterlist *sg; +unsigned int si;pr_debug ("in atapi dma stop\n" );if (!(ap->udma_mask || ap->mwdma_mask))
@@ -950,7 +953,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)* data cache is enabled. Otherwise, this loop * is an empty loop and optimized out. */ -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {invalidate_dcache_range (sg_dma_address (sg), sg_dma_address(sg)
drivers/ata/pata_icside.c +2 -1
@@ -224,6 +224,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)struct pata_icside_state *state = ap->host->private_data;struct scatterlist *sg, *rsg = state->sg;unsigned int write = qc->tf.flags &ATA_TFLAG_WRITE ; +unsigned int si;/* * We are simplex; BUG if we try to fiddle with DMA
@@ -234,7 +235,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)/* * Copy ATAs scattered sg list into a contiguous array of sg */ -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {memcpy (rsg, sg,sizeof (*sg)); rsg++; }
drivers/ata/pdc_adma.c +2 -1
@@ -321,8 +321,9 @@ static int adma_fill_sg(struct ata_queued_cmd *qc)u8 *buf = pp->pkt, *last_buf =NULL ;int i = (2 + buf[3 ]) *8 ;u8 pFLAGS = pORD | ((qc->tf.flags &ATA_TFLAG_WRITE ) ? pDIRO :0 ); +unsigned int si; -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {u32 addr;u32 len;
drivers/ata/sata_fsl.c +3 -1
@@ -323,6 +323,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,struct scatterlist *sg;unsigned int num_prde =0 ;u32 ttl_dwords =0 ; +unsigned int si;/* * NOTE : direct & indirect prdt's are contigiously allocated
@@ -333,13 +334,14 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,struct prde *prd_ptr_to_indirect_ext =NULL ;unsigned indirect_ext_segment_sz =0 ;dma_addr_t indirect_ext_segment_paddr; +unsigned int si;VPRINTK ("SATA FSL : cd = 0x%x, prd = 0x%x\n" , cmd_desc, prd); indirect_ext_segment_paddr = cmd_desc_paddr +SATA_FSL_CMD_DESC_OFFSET_TO_PRDT +SATA_FSL_MAX_PRD_DIRECT *16 ; -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {dma_addr_t sg_addr =sg_dma_address (sg);u32 sg_len =sg_dma_len (sg);
drivers/ata/sata_mv.c +2 -1
@@ -1136,9 +1136,10 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)struct mv_port_priv *pp = qc->ap->private_data;struct scatterlist *sg;struct mv_sg *mv_sg, *last_sg =NULL ; +unsigned int si; mv_sg = pp->sg_tbl; -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {dma_addr_t addr =sg_dma_address (sg);u32 sg_len =sg_dma_len (sg);
drivers/ata/sata_nv.c +9 -16
@@ -1336,21 +1336,18 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,static void nv_adma_fill_sg (struct ata_queued_cmd *qc,struct nv_adma_cpb *cpb) {struct nv_adma_port_priv *pp = qc->ap->private_data; -unsigned int idx;struct nv_adma_prd *aprd;struct scatterlist *sg; +unsigned int si;VPRINTK ("ENTER\n" ); - idx =0 ; - -ata_for_each_sg (sg, qc) { - aprd = (idx <5 ) ? &cpb->aprd[idx] : - &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5 )]; -nv_adma_fill_aprd (qc, sg, idx, aprd); - idx++; +for_each_sg (qc->sg, sg, qc->n_elem, si) { + aprd = (si <5 ) ? &cpb->aprd[si] : + &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5 )]; +nv_adma_fill_aprd (qc, sg, si, aprd); } -if (idx >5 ) +if (si >5 ) cpb->next_aprd =cpu_to_le64 (((u64)(pp->aprd_dma +NV_ADMA_SGTBL_SZ * qc->tag)));else cpb->next_aprd =cpu_to_le64 (0 );
@@ -1995,17 +1992,14 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc) {struct ata_port *ap = qc->ap;struct scatterlist *sg; -unsigned int idx;struct nv_swncq_port_priv *pp = ap->private_data;struct ata_prd *prd; - -WARN_ON (qc->__sg ==NULL ); -WARN_ON (qc->n_elem ==0 && qc->pad_len ==0 ); +unsigned int si, idx; prd = pp->prd +ATA_MAX_PRD * qc->tag; idx =0 ; -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {u32 addr, offset;u32 sg_len, len;
@@ -2027,8 +2021,7 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc) } } -if (idx) - prd[idx -1 ].flags_len |=cpu_to_le32 (ATA_PRD_EOT ); + prd[idx -1 ].flags_len |=cpu_to_le32 (ATA_PRD_EOT ); } static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
drivers/ata/sata_promise.c +18 -22
@@ -533,17 +533,15 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc) {struct ata_port *ap = qc->ap;struct scatterlist *sg; -unsigned int idx;const u32 SG_COUNT_ASIC_BUG =41 *4 ; +unsigned int si, idx; +u32 len;if (!(qc->flags &ATA_QCFLAG_DMAMAP ))return ; -WARN_ON (qc->__sg ==NULL ); -WARN_ON (qc->n_elem ==0 && qc->pad_len ==0 ); - idx =0 ; -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {u32 addr, offset;u32 sg_len, len;
@@ -570,29 +568,27 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc) } } -if (idx) { -u32 len =le32_to_cpu (ap->prd[idx -1 ].flags_len); + len =le32_to_cpu (ap->prd[idx -1 ].flags_len); -if (len >SG_COUNT_ASIC_BUG ) { -u32 addr; +if (len >SG_COUNT_ASIC_BUG ) { +u32 addr; -VPRINTK ("Splitting last PRD.\n" ); +VPRINTK ("Splitting last PRD.\n" ); - addr =le32_to_cpu (ap->prd[idx -1 ].addr); - ap->prd[idx -1 ].flags_len =cpu_to_le32 (len -SG_COUNT_ASIC_BUG ); -VPRINTK ("PRD[%u] = (0x%X, 0x%X)\n" , idx -1 , addr,SG_COUNT_ASIC_BUG ); + addr =le32_to_cpu (ap->prd[idx -1 ].addr); + ap->prd[idx -1 ].flags_len =cpu_to_le32 (len -SG_COUNT_ASIC_BUG ); +VPRINTK ("PRD[%u] = (0x%X, 0x%X)\n" , idx -1 , addr,SG_COUNT_ASIC_BUG ); - addr = addr + len -SG_COUNT_ASIC_BUG ; - len =SG_COUNT_ASIC_BUG ; - ap->prd[idx].addr =cpu_to_le32 (addr); - ap->prd[idx].flags_len =cpu_to_le32 (len); -VPRINTK ("PRD[%u] = (0x%X, 0x%X)\n" , idx, addr, len); + addr = addr + len -SG_COUNT_ASIC_BUG ; + len =SG_COUNT_ASIC_BUG ; + ap->prd[idx].addr =cpu_to_le32 (addr); + ap->prd[idx].flags_len =cpu_to_le32 (len); +VPRINTK ("PRD[%u] = (0x%X, 0x%X)\n" , idx, addr, len); - idx++; - } - - ap->prd[idx -1 ].flags_len |=cpu_to_le32 (ATA_PRD_EOT ); + idx++; } + + ap->prd[idx -1 ].flags_len |=cpu_to_le32 (ATA_PRD_EOT ); }static void pdc_qc_prep (struct ata_queued_cmd *qc)
drivers/ata/sata_qstor.c +4 -9
@@ -287,14 +287,10 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)struct scatterlist *sg;struct ata_port *ap = qc->ap;struct qs_port_priv *pp = ap->private_data; -unsigned int nelem;u8 *prd = pp->pkt +QS_CPB_BYTES ; +unsigned int si; -WARN_ON (qc->__sg ==NULL ); -WARN_ON (qc->n_elem ==0 && qc->pad_len ==0 ); - - nelem =0 ; -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) {u64 addr;u32 len;
@@ -306,12 +302,11 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc) *(__le32 *)prd =cpu_to_le32 (len); prd +=sizeof (u64); -VPRINTK ("PRD[%u] = (0x%llX, 0x%X)\n" , nelem, +VPRINTK ("PRD[%u] = (0x%llX, 0x%X)\n" , si, (unsigned long long )addr, len); - nelem++; } -return nelem; +return si; }static void qs_qc_prep (struct ata_queued_cmd *qc)
drivers/ata/sata_sil24.c +3 -3
@@ -813,8 +813,9 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, {struct scatterlist *sg;struct sil24_sge *last_sge =NULL ; +unsigned int si; -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) { sge->addr =cpu_to_le64 (sg_dma_address (sg)); sge->cnt =cpu_to_le32 (sg_dma_len (sg)); sge->flags =0 ;
@@ -823,8 +824,7 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, sge++; } -if (likely (last_sge)) - last_sge->flags =cpu_to_le32 (SGE_TRM ); + last_sge->flags =cpu_to_le32 (SGE_TRM ); }static int sil24_qc_defer (struct ata_queued_cmd *qc)
drivers/ata/sata_sx4.c +2 -2
@@ -473,7 +473,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR ];void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR ];unsigned int portno = ap->port_no; -unsigned int i, idx, total_len =0 , sgt_len; +unsigned int i, si, idx, total_len =0 , sgt_len;u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ ];WARN_ON (!(qc->flags &ATA_QCFLAG_DMAMAP ));
@@ -487,7 +487,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)* Build S/G table */ idx =0 ; -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) { buf[idx++] =cpu_to_le32 (sg_dma_address (sg)); buf[idx++] =cpu_to_le32 (sg_dma_len (sg)); total_len +=sg_dma_len (sg);
drivers/scsi/ipr.c +2 -1
@@ -5142,6 +5142,7 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd,struct ipr_ioadl_desc *last_ioadl =NULL ;int len = qc->nbytes + qc->pad_len;struct scatterlist *sg; +unsigned int si;if (len ==0 )return ;
@@ -5159,7 +5160,7 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd,cpu_to_be32 (sizeof (struct ipr_ioadl_desc ) * ipr_cmd->dma_use_sg); } -ata_for_each_sg (sg, qc) { +for_each_sg (qc->sg, sg, qc->n_elem, si) { ioadl->flags_and_data_len =cpu_to_be32 (ioadl_flags |sg_dma_len (sg)); ioadl->address =cpu_to_be32 (sg_dma_address (sg));
drivers/scsi/libsas/sas_ata.c +4 -6
@@ -158,8 +158,8 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)struct Scsi_Host *host = sas_ha->core.shost;struct sas_internal *i =to_sas_internal (host->transportt);struct scatterlist *sg; -unsigned int num =0 ;unsigned int xfer =0 ; +unsigned int si; task =sas_alloc_task (GFP_ATOMIC );if (!task)
@@ -181,17 +181,15 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) task->total_xfer_len = qc->nbytes + qc->pad_len; task->num_scatter = qc->pad_len ? qc->n_elem +1 : qc->n_elem; }else { -ata_for_each_sg (sg, qc) { - num++; +for_each_sg (qc->sg, sg, qc->n_elem, si) xfer += sg->length; - } task->total_xfer_len = xfer; - task->num_scatter = num; + task->num_scatter = si; } task->data_dir = qc->dma_dir; - task->scatter = qc->__sg; + task->scatter = qc->sg; task->ata_task.retry_count =1 ; task->task_state_flags =SAS_TASK_STATE_PENDING ; qc->lldd_task = task;
include/linux/libata.h +8 -34
76 lines not on this page · raw message
Signature · 1 line
1.5.2.4
PATCH 13/15 libata: implement ATAPI drain buffer
In reply to Tejun HeoMisc ATAPI commands may try to transfer more bytes than requested. For PIO which is performed by libata HSM, this is worked around by draining extra bytes from __atapi_pio_bytes().
This patch implements drain buffer to perform draining for DMA and PIO-over-DMA cases. One page is allocated w/ GFP_DMA32 during libata core layer initialization. On host registration, this drain page is DMA mapped and ATAPI_MAX_DRAIN_PAGES sg entries are reserved.
ata_sg_setup_extra() uses these extra sg entries to map the drain page ATAPI_MAX_DRAIN_PAGES times, extending sg list by ATAPI_MAX_DRAIN bytes. This allows both DMA and PIO-over-DMA misc ATAPI commands to overflow by ATAPI_MAX_DRAIN bytes just like PIO commands.
--- drivers/ata/libata-core.c | 116 ++++++++++++++++++++++++++++++++++++++++----- drivers/ata/libata-scsi.c | 14 ++++-- include/linux/libata.h | 4 +- 3 files changed, 116 insertions(+), 18 deletions(-)
drivers/ata/libata-core.c +103 -13
@@ -4759,6 +4759,60 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, qc->cursg = qc->sg; } +/** +* ata_sg_setup_extra - Setup extra sg entries +* @qc: Command to setup extra sg entries for +* @n_elem_extra: Out parameter for the number of extra sg entries +* @nbytes_extra: Out parameter for the number of extra bytes +* +* Extra sg entries are used to deal with ATAPI peculiarities. +* First, the content to be transferred can be of any size but +* transfer length should be aligned to 4 bytes, so if data size +* isn't aligned, it needs to be padded. +* +* Second, for commands whose repsonse can be variable, due to +* userland bugs (more likely) and hardware bugs, devices can try +* to transfer more bytes than requested. This can be worked +* around by appending drain buffers at the end. +* +* This function sets up both padding and draining sg entries. +* For this purpose, each qc has 2 + ATAPI_MAX_DRAIN_PAGES extra +* sg entries. Each extra sg has assigned function. +* +* e[0] | e[1] | e[2] | ... | e[2 + ATAPI_MAX_DRAIN_PAGES - 1] +* ---------------------------------------------------------------------- +* link | padding | draining ... +* or link +* +* After sg setup is complete, sg list looks like the following. +* +* 1. Padding necessary, padding doesn't replace the last sg +* +* o[0][1][2]...[last] e[0][1]([2]... if draining is necessary) +* | ^ +* \------/ +* e[0] carries the original content of o[last]. +* +* 2. Padding necessary, padding replaces the last sg +* +* o[0][1][2]...[last] e[0][1]([2]... if draining is necessary) +* | ^ +* \---------/ +* e[1] completely includes what o[last] used to point to. +* +* 3. Only draining is necessary. +* +* [0][1][2]...[last] e[0][1][2]... +* | ^ +* \---------/ +* e[1] carries the original conetent of o[last]. +* +* LOCKING: +* spin_lock_irqsave(host lock) +* +* RETURNS: +* Adjusted n_elem which should be mapped. +*/ static unsigned int ata_sg_setup_extra (struct ata_queued_cmd *qc,unsigned int *n_elem_extra,unsigned int *nbytes_extra)
@@ -4766,6 +4820,7 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,struct ata_port *ap = qc->ap;unsigned int n_elem = qc->n_elem;struct scatterlist *lsg, *copy_lsg =NULL , *tsg =NULL , *esg =NULL ; +int drain; *n_elem_extra =0 ; *nbytes_extra =0 ;
@@ -4773,7 +4828,10 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,/* needs padding? */ qc->pad_len = qc->nbytes &3 ; -if (likely (!qc->pad_len)) +/* needs drain? */ + drain =atapi_qc_may_overflow (qc); + +if (likely (!qc->pad_len && !drain))return n_elem;/* locate last sg and save it */
@@ -4835,6 +4893,29 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc, (*nbytes_extra) +=4 - qc->pad_len; } +if (drain) { +struct scatterlist *dsg = qc->extra_sg +2 ; +int i; + +for (i =0 ; i <ATAPI_MAX_DRAIN_PAGES ; i++) { +sg_set_page (dsg,virt_to_page (ata_drain_page), +PAGE_SIZE ,0 ); +sg_dma_address (dsg) = ap->host->drain_page_dma; +sg_dma_len (dsg) =PAGE_SIZE ; + dsg++; + } + +if (!tsg) { + copy_lsg = &qc->extra_sg[1 ]; + tsg = &qc->extra_sg[1 ]; + } + + esg = dsg -1 ; + + (*n_elem_extra) +=ATAPI_MAX_DRAIN_PAGES ; + (*nbytes_extra) +=ATAPI_MAX_DRAIN_PAGES *PAGE_SIZE ; + } +if (copy_lsg)sg_set_page (copy_lsg,sg_page (lsg), lsg->length, lsg->offset);
@@ -6892,6 +6973,9 @@ static void ata_host_stop(struct device *gendev, void *res) ap->ops->port_stop (ap); } +dma_unmap_single (host->dev, host->drain_page_dma,PAGE_SIZE , +DMA_FROM_DEVICE ); +if (host->ops->host_stop) host->ops->host_stop (host); }
@@ -6914,8 +6998,8 @@ static void ata_host_stop(struct device *gendev, void *res)*/ int ata_host_start (struct ata_host *host) { -int have_stop =0 ;void *start_dr =NULL ; +dma_addr_t dma;int i, rc;if (host->flags &ATA_HOST_STARTED )
@@ -6926,20 +7010,23 @@ int ata_host_start(struct ata_host *host)if (!host->ops && !ata_port_is_dummy (ap)) host->ops = ap->ops; - -if (ap->ops->port_stop) - have_stop =1 ; } -if (host->ops->host_stop) - have_stop =1 ; + start_dr =devres_alloc (ata_host_stop,0 ,GFP_KERNEL ); +if (!start_dr) +return -ENOMEM ; -if (have_stop) { - start_dr =devres_alloc (ata_host_stop,0 ,GFP_KERNEL ); -if (!start_dr) -return -ENOMEM ; +/* map drain page */ + dma =dma_map_single (host->dev, ata_drain_page,PAGE_SIZE , +DMA_FROM_DEVICE ); +if (dma_mapping_error (dma)) { +dev_printk (KERN_ERR , host->dev,"failed to map drain page\n" ); + rc = -ENOMEM ; + goto err_map; } + host->drain_page_dma = dma; +/* start ports */ for (i =0 ; i < host->n_ports; i++) {struct ata_port *ap = host->ports[i];
@@ -6948,7 +7035,7 @@ int ata_host_start(struct ata_host *host)if (rc) {if (rc != -ENODEV )dev_printk (KERN_ERR , host->dev,"failed to start port %d (errno=%d)\n" , i, rc); - goto err_out; + goto err_start; } }ata_eh_freeze_port (ap);
@@ -6959,13 +7046,16 @@ int ata_host_start(struct ata_host *host) host->flags |=ATA_HOST_STARTED ;return 0 ; - err_out: + err_start:while (--i >=0 ) {struct ata_port *ap = host->ports[i];if (ap->ops->port_stop) ap->ops->port_stop (ap); } + err_map: +dma_unmap_single (host->dev, host->drain_page_dma,PAGE_SIZE , +DMA_FROM_DEVICE );devres_free (start_dr);return rc; }
drivers/ata/libata-scsi.c +10 -4
@@ -832,13 +832,19 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,/* configure max sectors */ blk_queue_max_sectors (sdev->request_queue, dev->max_sectors); -/* SATA DMA transfers must be multiples of 4 byte, so -* we need to pad ATAPI transfers using an extra sg. -* Decrement max hw segments accordingly. +/* SATA DMA transfers must be multiples of 4 byte, so we need +* to pad ATAPI transfers using an extra sg. Also, ATAPI +* commands with variable length reponse needs draining of +* extra data. Decrement max hw segments accordingly. */ if (dev->class ==ATA_DEV_ATAPI ) {struct request_queue *q = sdev->request_queue; -blk_queue_max_hw_segments (q, q->max_hw_segments -1 ); +unsigned short hw_segments = q->max_hw_segments; + +BUG_ON (hw_segments <=1 +ATAPI_MAX_DRAIN_PAGES ); + hw_segments -=1 +ATAPI_MAX_DRAIN_PAGES ; + +blk_queue_max_hw_segments (q, hw_segments); }if (dev->flags &ATA_DFLAG_AN )
include/linux/libata.h +3 -1
@@ -121,6 +121,7 @@ enum {ATA_SHORT_PAUSE = (HZ >>6 ) +1 ,ATAPI_MAX_DRAIN =16 <<10 , +ATAPI_MAX_DRAIN_PAGES =ATAPI_MAX_DRAIN >>PAGE_SHIFT ,ATA_SHT_EMULATED =1 , ATA_SHT_CMD_PER_LUN = 1,
@@ -438,6 +439,7 @@ struct ata_host {void *private_data;const struct ata_port_operations *ops;unsigned long flags; +dma_addr_t drain_page_dma;#ifdef CONFIG_ATA_ACPI acpi_handle acpi_handle;#endif
@@ -476,7 +478,7 @@ struct ata_queued_cmd {struct scatterlist *last_sg;struct scatterlist saved_last_sg;struct scatterlist sgent; -struct scatterlist extra_sg[2 ]; +struct scatterlist extra_sg[2 +ATAPI_MAX_DRAIN_PAGES ];struct scatterlist *sg;
Signature · 1 line
1.5.2.4
PATCH 14/15 libata: implement ATAPI per-command-type DMA horkages
In reply to Tejun HeoATAPI DMA is filled with mines. Sector aligned READ transfers usually work but many other commands transfer non-sector aligned or variable number of bytes, and there are devices and controllers which have problems dealing with such non-aligned DMA transactions.
This patch implement ATAPI per-command-type DMA horkages and EH logic to set those quickly. This way, failures localized to certain command type don't affect other operations (most importantly READs) and working configuration is found quickly such that the device can be used.
--- drivers/ata/libata-core.c | 21 +++++++++++++++++++++ drivers/ata/libata-eh.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/libata.h | 5 +++++ 3 files changed, 61 insertions(+), 0 deletions(-)
drivers/ata/libata-core.c +21 -0
@@ -4637,6 +4637,27 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)int ata_check_atapi_dma (struct ata_queued_cmd *qc) {struct ata_port *ap = qc->ap; +unsigned int horkage = qc->dev->horkage; + +switch (atapi_cmd_type (qc->cdb[0 ])) { +case ATAPI_READ : +break ; + +case ATAPI_WRITE : +if (horkage &ATAPI_DMA_HORKAGE_WRITE ) +return 1 ; +break ; + +case ATAPI_READ_CD : +if (horkage &ATAPI_DMA_HORKAGE_READ_CD ) +return 1 ; +break ; + +case ATAPI_MISC : +if (horkage &ATAPI_DMA_HORKAGE_MISC ) +return 1 ; +break ; + }/* Don't allow DMA if it isn't multiple of 16 bytes. Quite a * few ATAPI devices choke on such DMA requests.
drivers/ata/libata-eh.c +35 -0
@@ -1489,6 +1489,38 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,return action; } +static void atapi_eh_dma_horkages (struct ata_queued_cmd *qc) +{ +struct ata_device *dev = qc->dev; +const char *type; + +if (!ata_is_atapi (qc->tf.protocol) || !ata_is_dma (qc->tf.protocol) || + !(qc->err_mask & (AC_ERR_HSM |AC_ERR_TIMEOUT ))) +return ; + +switch (atapi_cmd_type (qc->cdb[0 ])) { +case ATAPI_WRITE : + type ="WRITE" ; + dev->horkage |=ATAPI_DMA_HORKAGE_WRITE ; +break ; +case ATAPI_READ_CD : + type ="READ CD [MSF]" ; + dev->horkage |=ATAPI_DMA_HORKAGE_READ_CD ; +break ; +case ATAPI_MISC : + type ="MISC" ; + dev->horkage |=ATAPI_DMA_HORKAGE_MISC ; +break ; +default : +return ; + } + +ata_dev_printk (dev,KERN_WARNING ,"ATAPI DMA for %s disabled (0x%x). \n" +" If this continues to happen, please report to\n" +" [email protected]\n" , + type, dev->horkage); +} +static int ata_eh_categorize_error (unsigned int eflags,unsigned int err_mask,int *xfer_ok) {
@@ -1809,6 +1841,9 @@ static void ata_eh_link_autopsy(struct ata_link *link) all_err_mask |= qc->err_mask;if (qc->flags &ATA_QCFLAG_IO ) eflags |=ATA_EFLAG_IS_IO ; + +/* handle ATAPI DMA horkages */ +atapi_eh_dma_horkages (qc); }/* enforce default EH actions */
include/linux/libata.h +5 -0
@@ -342,6 +342,11 @@ enum {ATA_HORKAGE_IVB = (1 <<8 ),/* cbl det validity bit bugs */ ATA_HORKAGE_STUCK_ERR = (1 <<9 ),/* stuck ERR on next PACKET */ +ATAPI_DMA_HORKAGE_WRITE = (1 <<28 ),/* PIO for WRITEs */ +ATAPI_DMA_HORKAGE_READ_CD = (1 <<29 ),/* PIO for READ_CDs */ +ATAPI_DMA_HORKAGE_READ_DVD_STR = (1 <<30 ),/* PIO for READ DVD STR */ +ATAPI_DMA_HORKAGE_MISC = (1 <<31 ),/* PIO for MISC commands */ +/* DMA mask for user DMA control: User visible values; DO NOT renumber */ ATA_DMA_MASK_ATA = (1 << 0), /* DMA on ATA Disk */
Signature · 1 line
1.5.2.4
PATCH 15/15 libata: use PIO for misc ATAPI commands
In reply to Tejun HeoATAPI devices come with plethora of bugs and many ATA controllers have trouble dealing with odd byte DMA transfers. The problem is currently somewhat masked by not allowing DMA transfers if the transfer size isn't aligned to 16 bytes plus partial masking in problematic LLDs.
This masking is taken verbatim from IDE and is far from perfection. There's no fundamental explanation why this should be sufficient and there are ATAPI devices which don't work with the IDE driver.
In addition, this mixture of PIO and DMA commands reduces test coverage which is already insufficient considering the crazy number of ATAPI devices out in the wild.
Also, these misc ATAPI commands usually transfer small amount of data and are used infrequently. There isn't much to be gained from using DMA. Combined with the fact that another OS which is probably the only one that most ATAPI device vendors test against uses PIO for these commands, it's much wiser to use PIO for these commands and concentrate debugging efforts on getting PIO right for misc commands and DMA for bulk transfer commands.
Private command type / transfer length filtering in sata_promise, pata_it821x and pata_pdc2027x are removed as core layer filtering is more conservative.
--- drivers/ata/libata-core.c | 10 +-------- drivers/ata/libata-eh.c | 17 ++------------- drivers/ata/libata-scsi.c | 17 ++------------- drivers/ata/pata_it821x.c | 4 --- drivers/ata/pata_pdc2027x.c | 44 ------------------------------------------- drivers/ata/sata_promise.c | 31 ++++++++--------------------- include/linux/libata.h | 1 - 7 files changed, 16 insertions(+), 108 deletions(-)
drivers/ata/libata-core.c +1 -9
@@ -4654,16 +4654,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)break ;case ATAPI_MISC : -if (horkage &ATAPI_DMA_HORKAGE_MISC ) -return 1 ; -break ; - } - -/* Don't allow DMA if it isn't multiple of 16 bytes. Quite a -* few ATAPI devices choke on such DMA requests. -*/ -if (unlikely (qc->nbytes &15 ))return 1 ; + }if (ap->ops->check_atapi_dma)return ap->ops->check_atapi_dma (qc);
drivers/ata/libata-eh.c +3 -14
@@ -1271,7 +1271,6 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc) {struct ata_device *dev = qc->dev;unsigned char *sense_buf = qc->scsicmd->sense_buffer; -struct ata_port *ap = dev->link->ap;struct ata_taskfile tf;u8 cdb[ATAPI_CDB_LEN ];
@@ -1296,15 +1295,9 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc) tf.flags |=ATA_TFLAG_ISADDR |ATA_TFLAG_DEVICE ; tf.command =ATA_CMD_PACKET ; -/* is it pointless to prefer PIO for "safety reasons"? */ -if (ap->flags &ATA_FLAG_PIO_DMA ) { - tf.protocol =ATAPI_PROT_DMA ; - tf.feature |=ATAPI_PKT_DMA ; - }else { - tf.protocol =ATAPI_PROT_PIO ; - tf.lbam =SCSI_SENSE_BUFFERSIZE ; - tf.lbah =0 ; - } + tf.protocol =ATAPI_PROT_PIO ; + tf.lbam =SCSI_SENSE_BUFFERSIZE ; + tf.lbah =0 ;return ata_exec_internal (dev, &tf, cdb,DMA_FROM_DEVICE , sense_buf,SCSI_SENSE_BUFFERSIZE ,0 );
@@ -1507,10 +1500,6 @@ static void atapi_eh_dma_horkages(struct ata_queued_cmd *qc) type ="READ CD [MSF]" ; dev->horkage |=ATAPI_DMA_HORKAGE_READ_CD ;break ; -case ATAPI_MISC : - type ="MISC" ; - dev->horkage |=ATAPI_DMA_HORKAGE_MISC ; -break ;default :return ; }
drivers/ata/libata-scsi.c +3 -14
@@ -2322,12 +2322,6 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc)ata_qc_free (qc); } -/* is it pointless to prefer PIO for "safety reasons"? */ -static inline int ata_pio_use_silly (struct ata_port *ap) -{ -return (ap->flags &ATA_FLAG_PIO_DMA ); -} -static void atapi_request_sense (struct ata_queued_cmd *qc) {struct ata_port *ap = qc->ap;
@@ -2357,15 +2351,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) qc->tf.flags |=ATA_TFLAG_ISADDR |ATA_TFLAG_DEVICE ; qc->tf.command =ATA_CMD_PACKET ; + qc->tf.protocol =ATAPI_PROT_PIO ; + qc->tf.lbam =SCSI_SENSE_BUFFERSIZE ; + qc->tf.lbah =0 ; -if (ata_pio_use_silly (ap)) { - qc->tf.protocol =ATAPI_PROT_DMA ; - qc->tf.feature |=ATAPI_PKT_DMA ; - }else { - qc->tf.protocol =ATAPI_PROT_PIO ; - qc->tf.lbam =SCSI_SENSE_BUFFERSIZE ; - qc->tf.lbah =0 ; - } qc->nbytes =SCSI_SENSE_BUFFERSIZE ; qc->complete_fn = atapi_sense_complete;
drivers/ata/pata_it821x.c +0 -4
@@ -532,10 +532,6 @@ static int it821x_check_atapi_dma(struct ata_queued_cmd *qc)struct ata_port *ap = qc->ap;struct it821x_dev *itdev = ap->private_data; -/* Only use dma for transfers to/from the media. */ -if (qc->nbytes <2048 ) -return -EOPNOTSUPP ; -/* No ATAPI DMA in smart mode */ if (itdev->smart)return -EOPNOTSUPP ;
drivers/ata/pata_pdc2027x.c +0 -44
68 lines not on this page · raw message
drivers/ata/sata_promise.c +9 -22
@@ -923,32 +923,19 @@ static void pdc_exec_command_mmio(struct ata_port *ap,static int pdc_check_atapi_dma (struct ata_queued_cmd *qc) { -u8 *scsicmd = qc->scsicmd->cmnd; -int pio =1 ;/* atapi dma off by default */ - -/* Whitelist commands that may use DMA. */ -switch (scsicmd[0 ]) { -case WRITE_12 : -case WRITE_10 : -case WRITE_6 : -case READ_12 : -case READ_10 : -case READ_6 : -case 0xad :/* READ_DVD_STRUCTURE */ -case 0xbe :/* READ_CD */ - pio =0 ; - } +const u8 *cdb = qc->cdb; +/* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */ -if (scsicmd[0 ] ==WRITE_10 ) { +if (cdb[0 ] ==WRITE_10 ) {unsigned int lba = - (scsicmd[2 ] <<24 ) | - (scsicmd[3 ] <<16 ) | - (scsicmd[4 ] <<8 ) | - scsicmd[5 ]; + (cdb[2 ] <<24 ) | + (cdb[3 ] <<16 ) | + (cdb[4 ] <<8 ) | + cdb[5 ];if (lba >=0xFFFF4FA2 ) - pio =1 ; +return 1 ; } -return pio; +return 0 ; }static int pdc_old_sata_check_atapi_dma (struct ata_queued_cmd *qc)
include/linux/libata.h +0 -1
@@ -345,7 +345,6 @@ enum {ATAPI_DMA_HORKAGE_WRITE = (1 <<28 ),/* PIO for WRITEs */ ATAPI_DMA_HORKAGE_READ_CD = (1 <<29 ),/* PIO for READ_CDs */ ATAPI_DMA_HORKAGE_READ_DVD_STR = (1 << 30), /* PIO for READ DVD STR */ - ATAPI_DMA_HORKAGE_MISC = (1 << 31), /* PIO for MISC commands *//* DMA mask for user DMA control: User visible values; DO NOT renumber */
Signature · 1 line
1.5.2.4
Re: [PATCH 15/15] libata: use PIO for misc ATAPI commands
Quoted 5 lines
Private command type / transfer length filtering in
sata_promise,pata_it821xandpata_pdc2027xare removed as core layer filtering is more conservative.Signed-off-by Tejun Heo <[email protected]>
NAK same reasons as the three previous times it was posted.
Re: [PATCH 02/15] libata: zero xfer length on ATAPI data xfer IRQ is HSM violation
In reply to Tejun HeoQuoted 25 lines · Tejun Heo
From: Albert Lee <[email protected]>
Treat zero xfer length as HSM violation. While at it, add unlikely()'s to ATAPI ireason and transfer length checks.
tj: Formatted patch and added unlikely()'s.
Signed-off-by Albert Lee <[email protected]>Signed-off-by Tejun Heo <[email protected]>--- drivers/ata/libata-core.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)drivers/ata/libata-core.c +1
-1@@ -5280,12 +5280,15 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) bytes = (bc_hi <<8 ) | bc_lo;/* shall be cleared to zero, indicating xfer of data */ -if (ireason & (1 <<0 )) +if (unlikely (ireason & (1 <<0 ))) goto err_out;
drivers/ata/libata-core.c static void atapi_pio_bytes(struct ata_queued_cmd *qc) · line 5294
Quoted 10 lines
drivers/ata/libata-core.c +4
-1/* make sure transfer direction matches expected */ i_write = ((ireason & (1 <<1 )) ==0 ) ?1 :0 ; -if (do_write != i_write) +if (unlikely (do_write != i_write)) + goto err_out; + +if (unlikely (!bytes)) goto err_out;VPRINTK ("ata%u: xfering %d bytes\n" , ap->print_id, bytes);
Looks good.
Re: [PATCH 08/15] libata: improve ATAPI draining
In reply to Tejun HeoQuoted 25 lines · Tejun Heo
For misc ATAPI commands which transfer variable length data to the host, overflow can occur due to application or hardware bug. Such overflows can be ignored safely as long as overflow data is properly drained. libata HSM implementation has this implemented in
__atapi_pio_bytes()but it isn't enough. Improve drain logic such that...* Multiple PIO data phases are allowed. Not allowing this used to be okay when transfer chunk size was set to 8k unconditionally but with transfer hcunk size set to allocation size, treating extra PIO data phases as HSM violations cause a lot of trouble.
* Limit the amount of draining to
ATAPI_MAX_DRAIN(16k currently).* Don't whine if overflow is allowed and safe. When unexpected overflow occurs, trigger HSM violation and report the problem using ehi error description.
* Properly calculate the number of bytes to be drained considering actual number of consumed bytes for partial draining.
* Add and use
ata_drain_pagefor draining. This change fixes the problem where LLDs which do 32bit IOs consumes 4 bytes on each 2 byte draining resulting in draining twice more data than requested.
Quoted 5 lines
This patch fixes ATAPI regressions introduced by setting transfer chunk size to allocation size.
Signed-off-by Tejun Heo <[email protected]>Cc Albert Lee <[email protected]>
Re: [PATCH 01/15] libata: make atapi_request_sense() use sg
In reply to Tejun HeoQuoted 14 lines · Tejun Heo
atapi_request_sense()is now the only left user ofata_sg_init_one(). Convert it to use sg interface.Signed-off-by Tejun Heo <[email protected]>Cc Rusty Russel <[email protected]>--- drivers/ata/libata-scsi.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)drivers/ata/libata-scsi.c +0
-0
drivers/ata/libata-scsi.c static void atapi_request_sense(struct ata_queued_cmd *qc) · line 2346
Quoted 8 lines
drivers/ata/libata-scsi.c +3
-1@@ -2340,7 +2340,9 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)ata_qc_reinit (qc); -ata_sg_init_one (qc, cmd->sense_buffer,sizeof (cmd->sense_buffer)); +/* setup sg table and init transfer direction */ +sg_init_one (&qc->sgent, cmd->sense_buffer,sizeof (cmd->sense_buffer)); +ata_sg_init (qc, &qc->sgent,1 ); qc->dma_dir =DMA_FROM_DEVICE ;
applied 1-4 to #upstream, although patch #3 was imported from upstream-fixes (update atapi buffersize in request-sense)
Jeff
Re: [PATCH 05/15] libata: rename ATA_PROT_ATAPI_* to ATAPI_PROT_*
In reply to Tejun HeoQuoted 5 lines · Tejun Heo
ATA_PROT_ATAPI_* are ugly and naming schemes between ATA_PROT_* and ATA_PROT_ATAPI_* are inconsistent causing confusion. Rename them to ATAPI_PROT_* and make them consistent with ATA counterpart.
Signed-off-by Tejun Heo <[email protected]>
Quoted 15 lines
--- drivers/ata/libata-core.c | 24 ++++++++++++------------ drivers/ata/libata-eh.c | 8 ++++---- drivers/ata/libata-scsi.c | 10 +++++----- drivers/ata/libata-sff.c | 2 +- drivers/ata/pata_pdc202xx_old.c | 5 ++--- drivers/ata/pdc_adma.c | 2 +- drivers/ata/sata_inic162x.c | 2 +- drivers/ata/sata_promise.c | 26 ++++++++++++-------------- drivers/ata/sata_qstor.c | 2 +- drivers/ata/sata_sx4.c | 2 +- drivers/scsi/ipr.c | 6 +++--- drivers/scsi/libsas/sas_ata.c | 2 +- include/linux/ata.h | 12 ++++++------ 13 files changed, 50 insertions(+), 53 deletions(-)
applied #upstream, with build fixes for recent #upstream-fixes changes
Re: [PATCH 07/15] change-data_xfer
In reply to Tejun HeoQuoted 13 lines · Tejun Heo
Depending on how many bytes are transferred as a unit, PIO data tranasfer may consume more bytes than requested. Knowing how much data is consumed is necessary to determine how much is left for draining. This patch update ->data_xfer such that it returns the number of consumed bytes.
While at it, it also makes the following changes.
* s/adev/dev/
* use READ/WRITE constants for rw indication
* misc clean upsSigned-off-by Tejun Heo <[email protected]>
Quoted 10 lines
--- drivers/ata/libata-core.c | 46 +++++++++++++++++++++++++++-------------- drivers/ata/pata_bf54x.c | 28 +++++++++++++----------- drivers/ata/pata_ixp4xx_cf.c | 26 ++++++++++++----------- drivers/ata/pata_legacy.c | 36 +++++++++++++++++--------------- drivers/ata/pata_qdi.c | 30 +++++++++++++++----------- drivers/ata/pata_scc.c | 30 ++++++++++++++------------ drivers/ata/pata_winbond.c | 28 ++++++++++++++----------- include/linux/libata.h | 11 +++++---- 8 files changed, 133 insertions(+), 102 deletions(-)
applied 6-7 to #upstream
Re: [PATCH 08/15] libata: improve ATAPI draining
In reply to Tejun HeoQuoted 25 lines · Tejun Heo
For misc ATAPI commands which transfer variable length data to the host, overflow can occur due to application or hardware bug. Such overflows can be ignored safely as long as overflow data is properly drained. libata HSM implementation has this implemented in
__atapi_pio_bytes()but it isn't enough. Improve drain logic such that...* Multiple PIO data phases are allowed. Not allowing this used to be okay when transfer chunk size was set to 8k unconditionally but with transfer hcunk size set to allocation size, treating extra PIO data phases as HSM violations cause a lot of trouble.
* Limit the amount of draining to
ATAPI_MAX_DRAIN(16k currently).* Don't whine if overflow is allowed and safe. When unexpected overflow occurs, trigger HSM violation and report the problem using ehi error description.
* Properly calculate the number of bytes to be drained considering actual number of consumed bytes for partial draining.
* Add and use
ata_drain_pagefor draining. This change fixes the problem where LLDs which do 32bit IOs consumes 4 bytes on each 2 byte draining resulting in draining twice more data than requested.
Quoted 5 lines
This patch fixes ATAPI regressions introduced by setting transfer chunk size to allocation size.
Signed-off-by Tejun Heo <[email protected]>Cc Albert Lee <[email protected]>
I'm dropping this one, since a good portion of it is already upstream as140b5e59119a172a91b5fa13d54ca4f79bbefee1
Jeff
Re: [PATCH 12/15] libata: make qc->nbytes include extra buffers
In reply to Tejun HeoQuoted 12 lines · Tejun Heo
qc->nbytesdidn't use to include extra buffers setup by libata core layer and my be odd. This patch makesqc->nbytesinclude any extra buffers setup by libata core layer and guaranteed to be aligned on 4 byte boundary.This value is to be used to program the host controller. As this represents the actual length of buffer available to the controller and the controller must be able to deal with short transfers for ATAPI commands which can transfer variable length, this shouldn't break any controllers while making problems like rounding-down and controllers choking up on odd transfer bytes much less likely.
Quoted 7 lines
The unmodified value is stored in new field
qc->raw_nbytes.Signed-off-by Tejun Heo <[email protected]>--- drivers/ata/libata-core.c | 14 ++++++++++---- include/linux/libata.h | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-)
applied 9-12 to #upstream
Re: [PATCH 13/15] libata: implement ATAPI drain buffer
In reply to Tejun HeoQuoted 14 lines · Tejun Heo
Misc ATAPI commands may try to transfer more bytes than requested. For PIO which is performed by libata HSM, this is worked around by draining extra bytes from
__atapi_pio_bytes().This patch implements drain buffer to perform draining for DMA and PIO-over-DMA cases. One page is allocated w/
GFP_DMA32during libata core layer initialization. On host registration, this drain page is DMA mapped andATAPI_MAX_DRAIN_PAGESsg entries are reserved.
ata_sg_setup_extra()uses these extra sg entries to map the drain pageATAPI_MAX_DRAIN_PAGEStimes, extending sg list byATAPI_MAX_DRAINbytes. This allows both DMA and PIO-over-DMA misc ATAPI commands to overflow byATAPI_MAX_DRAINbytes just like PIO commands.
Quoted 6 lines
Signed-off-by Tejun Heo <[email protected]>--- drivers/ata/libata-core.c | 116 ++++++++++++++++++++++++++++++++++++++++----- drivers/ata/libata-scsi.c | 14 ++++-- include/linux/libata.h | 4 +- 3 files changed, 116 insertions(+), 18 deletions(-)
ACK this patch and #14 (implement ATAPI per-command-type DMA horkages), but I am dropping both due to the need to be rediffed against latest #upstream (including recent #upstream-fixes changes).