SATA NCQ #4
PATCH 1/1 SATA NCQ #4
Hi,
This should be pretty final, at least only minor stuff left. Changes:
- (ahci) error handling updates
- (ahci) streamline/fix the ncq vs non-ncq interrupt handling. Important for error handling, where we have NCQ commands pending but may issue a non-NCQ command.
- (libata) improve ata_qc_from_tag()
- (libata) improve ncq setting in the scsi command translation
- (libata) fix READ_16/WRITE_16 translation for NCQ, it works now.
Patch is against 2.6.12-rc6 / current git. Jeff, I'll get you an incremental this time very shortly.
drivers/scsi/ahci.c +285 -53
@@ -19,8 +19,10 @@* If you do not delete the provisions above, a recipient may use your * version of this file under either the OSL or the GPL. * -* Version 1.0 of the AHCI specification: -* http://www.intel.com/technology/serialata/pdf/rev1_0.pdf +* Version 1.1 of the AHCI specification: +* http://www.intel.com/technology/serialata/pdf/rev1_1.pdf +* +* NCQ support (C) 2005 Jens Axboe <[email protected]> * */
@@ -47,10 +49,13 @@ enum {AHCI_MAX_SG =168 ,/* hardware max is 64K */ AHCI_DMA_BOUNDARY =0xffffffff ,AHCI_USE_CLUSTERING =0 , -AHCI_CMD_SLOT_SZ =32 *32 , -AHCI_RX_FIS_SZ =256 , +AHCI_MAX_CMDS =32 , +AHCI_CMD_SZ =32 ,AHCI_CMD_TBL_HDR =0x80 , -AHCI_CMD_TBL_SZ =AHCI_CMD_TBL_HDR + (AHCI_MAX_SG *16 ), +AHCI_CMD_SLOT_SZ =AHCI_MAX_CMDS *AHCI_CMD_SZ , +AHCI_RX_FIS_SZ =256 , +AHCI_CMD_TOTAL =AHCI_CMD_TBL_HDR + (AHCI_MAX_SG *16 ), +AHCI_CMD_TBL_SZ =AHCI_MAX_CMDS *AHCI_CMD_TOTAL ,AHCI_PORT_PRIV_DMA_SZ =AHCI_CMD_SLOT_SZ +AHCI_CMD_TBL_SZ +AHCI_RX_FIS_SZ , AHCI_IRQ_ON_SG = (1 << 31),
@@ -58,6 +63,7 @@ enum {AHCI_CMD_WRITE = (1 <<6 ),RX_FIS_D2H_REG =0x40 ,/* offset of D2H Register FIS data */ +RX_FIS_SDB_REG =0x58 ,/* offset of SDB Register FIS data */ board_ahci = 0,
@@ -75,6 +81,7 @@ enum {/* HOST_CAP bits */ HOST_CAP_64 = (1 <<31 ),/* PCI DAC (64-bit DMA) support */ +HOST_CAP_NCQ = (1 <<30 ),/* Native Command Queueing */ /* registers for each SATA port */ PORT_LST_ADDR = 0x00, /* command list DMA addr */
@@ -162,9 +169,9 @@ struct ahci_port_priv {dma_addr_t cmd_slot_dma;void *cmd_tbl;dma_addr_t cmd_tbl_dma; -struct ahci_sg *cmd_tbl_sg;void *rx_fis;dma_addr_t rx_fis_dma; +u32 sactive; };static u32 ahci_scr_read (struct ata_port *ap,unsigned int sc_reg);
@@ -182,7 +189,7 @@ static void ahci_tf_read(struct ata_portstatic void ahci_qc_prep (struct ata_queued_cmd *qc);static u8 ahci_check_status (struct ata_port *ap);static u8 ahci_check_err (struct ata_port *ap); -static inline int ahci_host_intr (struct ata_port *ap,struct ata_queued_cmd *qc); +static inline int ahci_host_intr (struct ata_port *ap);static Scsi_Host_Template ahci_sht = { .module =THIS_MODULE ,
@@ -190,7 +197,8 @@ static Scsi_Host_Template ahci_sht = { .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, - .can_queue = ATA_DEF_QUEUE, + .change_queue_depth = ata_scsi_change_queue_depth, + .can_queue = ATA_MAX_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = AHCI_MAX_SG, .max_sectors = ATA_MAX_SECTORS,
@@ -201,7 +209,7 @@ static Scsi_Host_Template ahci_sht = { .dma_boundary = AHCI_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, - .ordered_flush = 1, + .ordered_flush = 0, /* conflicts with NCQ for now */ };static struct ata_port_operations ahci_ops = {
@@ -342,14 +350,11 @@ static int ahci_port_start(struct ata_po mem_dma +=AHCI_RX_FIS_SZ ;/* -* Third item: data area for storing a single command -* and its scatter-gather table +* Third item: data area for storing commands and their sg tables */ pp->cmd_tbl = mem; pp->cmd_tbl_dma = mem_dma; - pp->cmd_tbl_sg = mem +AHCI_CMD_TBL_HDR ; - ap->private_data = pp;if (hpriv->cap &HOST_CAP_64 )
@@ -481,9 +486,10 @@ static void ahci_tf_read(struct ata_portata_tf_from_fis (d2h_fis, tf); } -static void ahci_fill_sg (struct ata_queued_cmd *qc) +static void ahci_fill_sg (struct ata_queued_cmd *qc,int offset) {struct ahci_port_priv *pp = qc->ap->private_data; +struct ahci_sg *cmd_tbl_sg;unsigned int i;VPRINTK ("ENTER\n" );
@@ -491,6 +497,7 @@ static void ahci_fill_sg(struct ata_queu/* * Next, the S/G list. */ + cmd_tbl_sg = pp->cmd_tbl + offset +AHCI_CMD_TBL_HDR ;for (i =0 ; i < qc->n_elem; i++) {u32 sg_len;dma_addr_t addr;
@@ -498,21 +505,22 @@ static void ahci_fill_sg(struct ata_queu addr =sg_dma_address (&qc->sg[i]); sg_len =sg_dma_len (&qc->sg[i]); - pp->cmd_tbl_sg[i].addr =cpu_to_le32 (addr &0xffffffff ); - pp->cmd_tbl_sg[i].addr_hi =cpu_to_le32 ((addr >>16 ) >>16 ); - pp->cmd_tbl_sg[i].flags_size =cpu_to_le32 (sg_len -1 ); + cmd_tbl_sg[i].addr =cpu_to_le32 (addr &0xffffffff ); + cmd_tbl_sg[i].addr_hi =cpu_to_le32 ((addr >>16 ) >>16 ); + cmd_tbl_sg[i].flags_size =cpu_to_le32 (sg_len -1 ); } }static void ahci_qc_prep (struct ata_queued_cmd *qc) {struct ahci_port_priv *pp = qc->ap->private_data; -u32 opts;const u32 cmd_fis_len =5 ;/* five dwords */ +dma_addr_t cmd_tbl_dma; +u32 opts; +int offset;/* -* Fill in command slot information (currently only one slot, -* slot 0, is currently since we don't do queueing) +* Fill in command slot information */ opts = (qc->n_elem <<16 ) | cmd_fis_len;
@@ -531,29 +539,39 @@ static void ahci_qc_prep(struct ata_queubreak ; } - pp->cmd_slot[0 ].opts =cpu_to_le32 (opts); - pp->cmd_slot[0 ].status =0 ; - pp->cmd_slot[0 ].tbl_addr =cpu_to_le32 (pp->cmd_tbl_dma &0xffffffff ); - pp->cmd_slot[0 ].tbl_addr_hi =cpu_to_le32 ((pp->cmd_tbl_dma >>16 ) >>16 ); +/* +* the tag determines the offset into the allocated cmd table +*/ + offset = qc->tag *AHCI_CMD_TOTAL ; + + cmd_tbl_dma = pp->cmd_tbl_dma + offset; + + pp->cmd_slot[qc->tag].opts =cpu_to_le32 (opts); + pp->cmd_slot[qc->tag].status =0 ; + pp->cmd_slot[qc->tag].tbl_addr =cpu_to_le32 (cmd_tbl_dma &0xffffffff ); + pp->cmd_slot[qc->tag].tbl_addr_hi =cpu_to_le32 ((cmd_tbl_dma >>16 ) >>16 );/* * Fill in command table information. First, the header, * a SATA Register - Host to Device command FIS. */ -ata_tf_to_fis (&qc->tf, pp->cmd_tbl,0 ); +ata_tf_to_fis (&qc->tf, pp->cmd_tbl + offset,0 );if (!(qc->flags &ATA_QCFLAG_DMAMAP ))return ; -ahci_fill_sg (qc); +ahci_fill_sg (qc, offset); } -static void ahci_intr_error (struct ata_port *ap,u32 irq_stat) +/* +* Return 1 if COMRESET was done +*/ +static int ahci_intr_error (struct ata_port *ap,u32 irq_stat) {void *mmio = ap->host_set->mmio_base;void *port_mmio =ahci_port_base (mmio, ap->port_no);u32 tmp; -int work; +int work, reset =0 ;/* stop DMA */ tmp =readl (port_mmio +PORT_CMD );
@@ -575,16 +593,22 @@ static void ahci_intr_error(struct ata_p tmp =readl (port_mmio +PORT_SCR_ERR );writel (tmp, port_mmio +PORT_SCR_ERR ); +/* clear status */ + tmp =readl (port_mmio +PORT_IRQ_STAT ); +writel (tmp, port_mmio +PORT_IRQ_STAT ); +/* if DRQ/BSY is set, device needs to be reset. * if so, issue COMRESET */ tmp =readl (port_mmio +PORT_TFDATA );if (tmp & (ATA_BUSY |ATA_DRQ )) { +printk (KERN_WARNING "ata%u: stat=%x, issuing COMRESET\n" , ap->id, tmp);writel (0x301 , port_mmio +PORT_SCR_CTL );readl (port_mmio +PORT_SCR_CTL );/* flush */ udelay (10 );writel (0x300 , port_mmio +PORT_SCR_CTL );readl (port_mmio +PORT_SCR_CTL );/* flush */ + reset =1 ; }/* re-start DMA */
@@ -594,9 +618,117 @@ static void ahci_intr_error(struct ata_preadl (port_mmio +PORT_CMD );/* flush */ printk (KERN_WARNING "ata%u: error occurred, port reset\n" , ap->id); +return reset; } -static void ahci_eng_timeout (struct ata_port *ap) +static void ahci_complete_requests (struct ata_port *ap,u32 tag_mask,int err) +{ +while (tag_mask) { +struct ata_queued_cmd *qc; +int tag =ffs (tag_mask) -1 ; + + tag_mask &= ~(1 << tag); + qc =ata_qc_from_tag (ap, tag); +if (qc) +ata_qc_complete (qc, err); +else +printk (KERN_ERR "ahci: missing tag %d\n" , tag); + } +} + +static void dump_log_page (unsigned char *p) +{ +int i; + +printk ("LOG 0x10: nq=%d, tag=%d\n" , p[0 ] >>7 , p[0 ] &0x1f ); + +for (i =2 ; i <14 ; i++) +printk ("%d:%d " , i, p[i]); + +printk ("\n" ); +} + +/* +* TODO: needs to use READ_LOG_EXT/page=10h to retrieve error information +*/ +extern void ata_qc_free (struct ata_queued_cmd *qc); +static void ahci_ncq_timeout (struct ata_port *ap) +{ +struct ahci_port_priv *pp = ap->private_data; +void *mmio = ap->host_set->mmio_base; +void *port_mmio =ahci_port_base (mmio, ap->port_no); +struct ata_queued_cmd *qc; +unsigned long flags; +char *buffer; +u32 sactive; +int reset; + +printk (KERN_WARNING "ata%u: ncq interrupt error (Q=%d)\n" , ap->id, ap->queue_depth); + +spin_lock_irqsave (&ap->host_set->lock, flags); + + sactive =readl (port_mmio +PORT_SCR_ACT ); + +printk (KERN_WARNING "ata%u: SActive 0x%x (0x%x)\n" , ap->id, sactive, pp->sactive); + reset =ahci_intr_error (ap,readl (port_mmio +PORT_IRQ_STAT )); + +spin_unlock_irqrestore (&ap->host_set->lock, flags); + +/* +* if COMRESET was done, we don't have to issue a log page read +*/ +if (reset) + goto done; + + buffer =kmalloc (512 ,GFP_KERNEL ); +if (!buffer) { +printk (KERN_ERR "ata%u: unable to allocate memory for error\n" , ap->id); + goto done; + } + +if (ata_read_log_page (ap,0 ,READ_LOG_SATA_NCQ_PAGE , buffer,1 )) { +printk (KERN_ERR "ata%u: unable to read log page\n" , ap->id); + goto out; + } + +dump_log_page (buffer); + +/* +* if NQ is cleared, bottom 5 bits contain the tag of the errored +* command +*/ +if ((buffer[0 ] & (1 <<7 )) ==0 ) { +int tag = buffer[0 ] &0x1f ; + + qc =ata_qc_from_tag (ap, tag); +if (qc) +ata_qc_complete (qc,ATA_ERR ); + } + +/* +* requeue the remaining commands +*/ +while (pp->sactive) { +int tag =ffs (pp->sactive) -1 ; + + pp->sactive &= ~(1 << tag); + qc =ata_qc_from_tag (ap, tag); +if (qc) { +if (qc->scsicmd) +ata_qc_free (qc); +else +ata_qc_complete (qc,ATA_ERR ); + }else +printk (KERN_ERR "ata%u: missing tag %d\n" , ap->id, tag); + } + +out: +kfree (buffer); +done: +ata_scsi_unblock_requests (ap); +} + +static void ahci_nonncq_timeout (struct ata_port *ap) {void *mmio = ap->host_set->mmio_base;void *port_mmio =ahci_port_base (mmio, ap->port_no);
@@ -620,13 +752,100 @@ static void ahci_eng_timeout(struct ata_ qc->scsidone = scsi_finish_command;ata_qc_complete (qc,ATA_ERR ); } +} + +static void ahci_eng_timeout (struct ata_port *ap) +{ +struct ahci_port_priv *pp = ap->private_data; +if (pp->sactive) +ahci_ncq_timeout (ap); +else +ahci_nonncq_timeout (ap); } -static inline int ahci_host_intr (struct ata_port *ap,struct ata_queued_cmd *qc) +static int ahci_ncq_intr (struct ata_port *ap,u32 status) { +struct ahci_port_priv *pp = ap->private_data;void *mmio = ap->host_set->mmio_base;void *port_mmio =ahci_port_base (mmio, ap->port_no); + +if (!pp->sactive) +return 0 ; + +if (status &PORT_IRQ_SDB_FIS ) { +u8 *sdb = pp->rx_fis +RX_FIS_SDB_REG ; +u32 sactive, mask; + +if (unlikely (sdb[2 ] &ATA_ERR )) { +printk ("SDB fis, stat %x, err %x\n" , sdb[2 ], sdb[3 ]); +return 1 ; + } + +/* +* SActive will have the bits cleared for completed commands +*/ + sactive =readl (port_mmio +PORT_SCR_ACT ); + mask = pp->sactive & ~sactive; +if (mask) { +ahci_complete_requests (ap, mask,0 ); + pp->sactive = sactive; +return 1 ; + }else +printk (KERN_INFO "ata%u: SDB with no bits cleared\n" , ap->id); + }else if (status &PORT_IRQ_D2H_REG_FIS ) { +u8 *d2h = pp->rx_fis +RX_FIS_D2H_REG ; + +/* +* pre-BSY clear error, let timeout error handling take care +* of it when it kicks in +*/ +if (d2h[2 ] &ATA_ERR ) { +VPRINTK ("D2H fis, err %x\n" , d2h[2 ]); +return 1 ; + } + +printk ("D2H fis\n" ); + }else +printk (KERN_WARNING "ata%u: unhandled FIS, stat %x\n" , ap->id, status); + +return 0 ; +} + +static void ahci_ncq_intr_error (struct ata_port *ap,u32 status) +{ +struct ahci_port_priv *pp = ap->private_data; +struct ata_queued_cmd *qc; +struct ata_taskfile tf; +int tag; + +printk (KERN_ERR "ata%u: NCQ err status 0x%x\n" , ap->id, status); + +if (status &PORT_IRQ_D2H_REG_FIS ) { +ahci_tf_read (ap, &tf); + tag = tf.nsect >>3 ; + + qc =ata_qc_from_tag (ap, tag); +if (qc) { +printk (KERN_ERR "ata%u: ending bad tag %d\n" , ap->id, tag); + pp->sactive &= ~(1 << tag); +ata_qc_complete (qc,ATA_ERR ); + }else +printk (KERN_ERR "ata%u: error on tag %d, but not present\n" , ap->id, tag); + } + +/* +* let command timeout deal with error handling +*/ +ata_scsi_block_requests (ap); +} + +static inline int ahci_host_intr (struct ata_port *ap) +{ +struct ahci_port_priv *pp = ap->private_data; +void *mmio = ap->host_set->mmio_base; +void *port_mmio =ahci_port_base (mmio, ap->port_no); +struct ata_queued_cmd *qc;u32 status, serr, ci; serr =readl (port_mmio +PORT_SCR_ERR );
@@ -635,18 +854,28 @@ static inline int ahci_host_intr(struct status =readl (port_mmio +PORT_IRQ_STAT );writel (status, port_mmio +PORT_IRQ_STAT ); - ci =readl (port_mmio +PORT_CMD_ISSUE ); -if (likely ((ci &0x1 ) ==0 )) { -if (qc) { -ata_qc_complete (qc,0 ); - qc =NULL ; - } +if (status &PORT_IRQ_FATAL ) { +printk ("ata%u: irq error %x %x, tag %d\n" , ap->id, serr, status, ap->active_tag); +if (pp->sactive) +ahci_ncq_intr_error (ap, status); +else +ahci_intr_error (ap, status); + +return 1 ; } -if (status &PORT_IRQ_FATAL ) { -ahci_intr_error (ap, status); -if (qc) -ata_qc_complete (qc,ATA_ERR ); +if (ahci_ncq_intr (ap, status)) +return 1 ; + + ci =readl (port_mmio +PORT_CMD_ISSUE ); + +if ((ci & (1 << ap->active_tag)) ==0 ) { +VPRINTK ("NON-NCQ interrupt\n" ); + + qc =ata_qc_from_tag (ap, ap->active_tag); +if (qc && (qc->flags &ATA_QCFLAG_ACTIVE ) && + !(qc->flags &ATA_QCFLAG_NCQ )) +ata_qc_complete (qc,0 ); }return 1 ;
@@ -679,18 +908,13 @@ static irqreturn_t ahci_interrupt (int ispin_lock (&host_set->lock);for (i =0 ; i < host_set->n_ports; i++) { -struct ata_port *ap; -u32 tmp; +struct ata_port *ap = host_set->ports[i];VPRINTK ("port %u\n" , i); - ap = host_set->ports[i]; - tmp = irq_stat & (1 << i); -if (tmp && ap) { -struct ata_queued_cmd *qc; - qc =ata_qc_from_tag (ap, ap->active_tag); -if (ahci_host_intr (ap, qc)) + +if (ap && (irq_stat & (1 << i))) +if (ahci_host_intr (ap)) irq_ack |= (1 << i); - } }if (irq_ack) {
@@ -705,15 +929,21 @@ static irqreturn_t ahci_interrupt (int ireturn IRQ_RETVAL (handled); } +static int ahci_qc_issue (struct ata_queued_cmd *qc) {struct ata_port *ap = qc->ap; +struct ahci_port_priv *pp = ap->private_data;void *port_mmio = (void *) ap->ioaddr.cmd_addr; -writel (1 , port_mmio +PORT_SCR_ACT ); -readl (port_mmio +PORT_SCR_ACT );/* flush */ +if (qc->flags &ATA_QCFLAG_NCQ ) { + pp->sactive |= (1 << qc->tag); -writel (1 , port_mmio +PORT_CMD_ISSUE ); +writel (1 << qc->tag, port_mmio +PORT_SCR_ACT ); +readl (port_mmio +PORT_SCR_ACT ); + } + +writel (1 << qc->tag, port_mmio +PORT_CMD_ISSUE );readl (port_mmio +PORT_CMD_ISSUE );/* flush */ return 0 ;
@@ -1030,6 +1260,9 @@ static int ahci_init_one (struct pci_devif (rc) goto err_out_hpriv; +if (hpriv->cap &HOST_CAP_NCQ ) + probe_ent->host_flags |=ATA_FLAG_NCQ ; +ahci_print_info (probe_ent);/* FIXME: check ata_device_add return value */
@@ -1052,7 +1285,6 @@ err_out:return rc; } -static int __init ahci_init (void ) {return pci_module_init (&ahci_pci_driver);
drivers/scsi/libata-core.c +189 -18
326 lines not on this page · raw message
drivers/scsi/libata-scsi.c +148 -13
276 lines not on this page · raw message
drivers/scsi/scsi_lib.c +5 -1
@@ -1292,13 +1292,17 @@ static void scsi_request_fn(struct reque shost = sdev->host;while (!blk_queue_plugged (q)) {int rtn; + +if (!scsi_dev_queue_ready (q, sdev)) +break ; +/* * get next queueable request. We do this early to make sure * that the request is fully prepared even if we cannot * accept it. */ req =elv_next_request (q); -if (!req || !scsi_dev_queue_ready (q, sdev)) +if (!req)break ;if (unlikely (!scsi_device_online (sdev))) {
include/linux/ata.h +10 -0
@@ -125,9 +125,17 @@ enum {ATA_CMD_PACKET =0xA0 ,ATA_CMD_VERIFY =0x40 ,ATA_CMD_VERIFY_EXT =0x42 , +ATA_CMD_FPDMA_READ =0x60 , +ATA_CMD_FPDMA_WRITE =0x61 , +ATA_CMD_READ_LOG_EXT =0x2f , + +/* READ_LOG_EXT pages */ +READ_LOG_SATA_NCQ_PAGE =0x10 ,/* SETFEATURES stuff */ SETFEATURES_XFER =0x03 , +SETFEATURES_EN_WCACHE =0x02 , +SETFEATURES_DIS_WCACHE =0x82 ,XFER_UDMA_7 =0x47 ,XFER_UDMA_6 =0x46 , XFER_UDMA_5 = 0x45,
@@ -233,7 +241,9 @@ struct ata_taskfile {#define ata_id_has_pm (id) ((id)[82] & (1 << 3))#define ata_id_has_lba (id) ((id)[49] & (1 << 9))#define ata_id_has_dma (id) ((id)[49] & (1 << 8)) +#define ata_id_has_ncq (id) ((id)[76] & (1 << 8))#define ata_id_removeable (id) ((id)[0] & (1 << 7)) +#define ata_id_queue_depth (id) (((id)[75] & 0x1f) + 1)#define ata_id_u32 (id,n) \ (((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)]))#define ata_id_u64 (id,n) \
include/linux/libata.h +34 -7
91 lines not on this page · raw message
Signature · 1 line
Jens Axboe
Hi Jens,
Quoted 2 lines · Jens Axboe
This should be pretty final, at least only minor stuff left. Changes:
Fell over here, on http://scatter.mine.nu/test/boxen/sempro/
No logged info, just scrolling heaps junk on screen --> libata I could see and I think 8 digit hex in [] on left.
Hit RESET to reboot, no apparent filesystem damage :) Sorry so little info. patched 2.6.12-rc6 cleanly seemed to go stupid during mount reiserfs partitions, about that stage of boot.
Being a sucker for punishment, I recompiled with 8KB stacks, highmem off (box has 1GB mem) and it go stupid when touch HDD, but USB started okay while it stupid, saw USB messages and mouse lit up.
Hit RESET to reboot... Again, box safely back in 2.6.11.11 land :)
--Grant.
Quoted 5 lines · Grant Coady
Hi Jens,
Quoted 2 lines · Jens Axboe
This should be pretty final, at least only minor stuff left. Changes:
Quoted 8 lines
Fell over here, on http://scatter.mine.nu/test/boxen/sempro/
No logged info, just scrolling heaps junk on screen --> libata I could see and I think 8 digit hex in [] on left.
Hit RESET to reboot, no apparent filesystem damage :) Sorry so little info. patched 2.6.12-rc6 cleanly seemed to go stupid during mount reiserfs partitions, about that stage of boot.
Interesting, looking at your boot log from 2.6.12-rc6 your controller is a via and thus doesn't support NCQ at all so the patch should do nothing for you.
I'll try and disable ahci on one box here to see if it catches anything, if not I'll probably ask you for more details.
Signature · 1 line
Jens Axboe
Quoted 15 lines · Jens Axboe
Quoted 5 lines · Grant Coady
Hi Jens,
Quoted 2 lines · Jens Axboe
This should be pretty final, at least only minor stuff left. Changes:
Quoted 8 lines
Fell over here, on http://scatter.mine.nu/test/boxen/sempro/
No logged info, just scrolling heaps junk on screen --> libata I could see and I think 8 digit hex in [] on left.
Hit RESET to reboot, no apparent filesystem damage :) Sorry so little info. patched 2.6.12-rc6 cleanly seemed to go stupid during mount reiserfs partitions, about that stage of boot.
Quoted 6 lines
Interesting, looking at your boot log from 2.6.12-rc6 your controller is a via and thus doesn't support NCQ at all so the patch should do nothing for you.
I'll try and disable ahci on one box here to see if it catches anything, if not I'll probably ask you for more details.
Boots for me. The drive in your system supports NCQ, which should be the same situation I just recreated here (drive supports NCQ, controller does not).
Any chance you can log the boot process when it fails, using serial console or something similar? At least write down the EIP of where it fails :-)
Signature · 1 line
Jens Axboe
Quoted 4 lines · Jens Axboe
Any chance you can log the boot process when it fails, using serial console or something similar? At least write down the EIP of where it fails :-)
Guess what? I switched box on this morning with monitor off and the boot completed, 'cos I'd logged in much time later ssh. Didn't give it enough time yesterday :(
I have one very large syslog... 139MB
How much of that would you like :)
Jun 9 04:27:45 sempro kernel: [<c0100ad3>] default_idle+0x23/0x30 Jun 9 04:27:45 sempro kernel: [<c0100b58>] cpu_idle+0x48/0x60 Jun 9 04:27:45 sempro kernel: [<c04867b8>] start_kernel+0x148/0x170 Jun 9 04:27:45 sempro kernel: [<c04863a0>] unknown_bootoption+0x0/0x1b0 Jun 9 04:27:45 sempro kernel: Badness in __ata_qc_complete at drivers/scsi/libata-core.c:3062 Jun 9 04:27:45 sempro kernel: [<c02ae908>] __ata_qc_complete+0x38/0x120 Jun 9 04:27:45 sempro kernel: [<c02b0d9b>] ata_scsi_qc_complete+0x2b/0x50 Jun 9 04:27:45 sempro kernel: [<c02aeac6>] ata_qc_complete+0x46/0xc0 Jun 9 04:27:45 sempro kernel: [<c02af13d>] ata_interrupt+0xcd/0x110 Jun 9 04:27:45 sempro kernel: [<c01308e0>] handle_IRQ_event+0x30/0x70 Jun 9 04:27:45 sempro kernel: [<c01309c2>] __do_IRQ+0xa2/0xe0 Jun 9 04:27:45 sempro kernel: [<c0105059>] do_IRQ+0x19/0x30 Jun 9 04:27:45 sempro kernel: [<c0103492>] common_interrupt+0x1a/0x20 Jun 9 04:27:45 sempro kernel: [<c0100ab0>] default_idle+0x0/0x30 Jun 9 04:27:45 sempro kernel: [<c0100ad3>] default_idle+0x23/0x30 Jun 9 04:27:45 sempro kernel: [<c0100b58>] cpu_idle+0x48/0x60 Jun 9 04:27:45 sempro kernel: [<c04867b8>] start_kernel+0x148/0x170 Jun 9 04:27:45 sempro kernel: [<c04863a0>] unknown_bootoption+0x0/0x1b0 Jun 9 04:27:45 sempro kernel: Badness in __ata_qc_complete at drivers/scsi/libata-core.c:3062
--Grant.
Quoted 12 lines · Grant Coady
Quoted 4 lines · Jens Axboe
Any chance you can log the boot process when it fails, using serial console or something similar? At least write down the EIP of where it fails :-)
Guess what? I switched box on this morning with monitor off and the boot completed, 'cos I'd logged in much time later ssh. Didn't give it enough time yesterday :(
I have one very large syslog... 139MB
Quoted 7 lines
How much of that would you like :)
Jun 9 04:27:45 sempro kernel: [<c0100ad3>] default_idle+0x23/0x30 Jun 9 04:27:45 sempro kernel: [<c0100b58>] cpu_idle+0x48/0x60 Jun 9 04:27:45 sempro kernel: [<c04867b8>] start_kernel+0x148/0x170 Jun 9 04:27:45 sempro kernel: [<c04863a0>] unknown_bootoption+0x0/0x1b0 Jun 9 04:27:45 sempro kernel: Badness in __ata_qc_complete at drivers/scsi/libata-core.c:3062
Ah duh, I never tested on UP, you have to use assert_spin_locked() there not the direct spin_is_locked().
So your system was functioning just fine, you just got a warning for every completed request slowing it down a lot :)
This should fix it. Jeff, can you apply that incremental to the ncq branch? Thanks!
drivers/scsi/libata-core.c renamed from drivers/scsi/libata-core.c~ +1 -1
@@ -3059,7 +3059,7 @@struct ata_port *ap = qc->ap;unsigned int tag, do_clear =0 ; -WARN_ON (!spin_is_locked (&ap->host_set->lock)); +WARN_ON (!assert_spin_locked (&ap->host_set->lock));if (likely (qc->flags &ATA_QCFLAG_ACTIVE )) {assert (ap->queue_depth);
Signature · 1 line
Jens Axboe
Quoted 33 lines · Jens Axboe
Quoted 12 lines · Grant Coady
Quoted 4 lines · Jens Axboe
Any chance you can log the boot process when it fails, using serial console or something similar? At least write down the EIP of where it fails :-)
Guess what? I switched box on this morning with monitor off and the boot completed, 'cos I'd logged in much time later ssh. Didn't give it enough time yesterday :(
I have one very large syslog... 139MB
Quoted 7 lines
How much of that would you like :)
Jun 9 04:27:45 sempro kernel: [<c0100ad3>] default_idle+0x23/0x30 Jun 9 04:27:45 sempro kernel: [<c0100b58>] cpu_idle+0x48/0x60 Jun 9 04:27:45 sempro kernel: [<c04867b8>] start_kernel+0x148/0x170 Jun 9 04:27:45 sempro kernel: [<c04863a0>] unknown_bootoption+0x0/0x1b0 Jun 9 04:27:45 sempro kernel: Badness in __ata_qc_complete at drivers/scsi/libata-core.c:3062Ah duh, I never tested on UP, you have to use
assert_spin_locked()there not the directspin_is_locked().So your system was functioning just fine, you just got a warning for every completed request slowing it down a lot :)
This should fix it. Jeff, can you apply that incremental to the ncq branch? Thanks!
drivers/scsi/libata-core.c line 3065
Quoted 8 lines
drivers/scsi/libata-core.c renamed from drivers/scsi/libata-core.c~ +1
-1@@ -3059,7 +3059,7 @@struct ata_port *ap = qc->ap;unsigned int tag, do_clear =0 ; -WARN_ON (!spin_is_locked (&ap->host_set->lock)); +WARN_ON (!assert_spin_locked (&ap->host_set->lock));if (likely (qc->flags &ATA_QCFLAG_ACTIVE )) {assert (ap->queue_depth);
Or just kill the check completely, it has served its purpose.
Signature · 1 line
Jens Axboe
Quoted 37 lines · Jens Axboe
Quoted 35 lines · Jens Axboe
Quoted 10 lines · Grant Coady
Quoted 3 lines · Jens Axboe
Any chance you can log the boot process when it fails, using serial console or something similar? At least write down the EIP of where it fails :-)
Guess what? I switched box on this morning with monitor off and the boot completed, 'cos I'd logged in much time later ssh. Didn't give it enough time yesterday :(
I have one very large syslog... 139MB
Quoted 7 lines
How much of that would you like :)
Jun 9 04:27:45 sempro kernel: [<c0100ad3>] default_idle+0x23/0x30 Jun 9 04:27:45 sempro kernel: [<c0100b58>] cpu_idle+0x48/0x60 Jun 9 04:27:45 sempro kernel: [<c04867b8>] start_kernel+0x148/0x170 Jun 9 04:27:45 sempro kernel: [<c04863a0>] unknown_bootoption+0x0/0x1b0 Jun 9 04:27:45 sempro kernel: Badness in __ata_qc_complete at drivers/scsi/libata-core.c:3062Ah duh, I never tested on UP, you have to use
assert_spin_locked()there not the directspin_is_locked().So your system was functioning just fine, you just got a warning for every completed request slowing it down a lot :)
This should fix it. Jeff, can you apply that incremental to the ncq branch? Thanks!
drivers/scsi/libata-core.c renamed from drivers/scsi/libata-core.c~ +0
-0@@ -3059,7 +3059,7 @@struct ata_port *ap = qc->ap;unsigned int tag, do_clear =0 ;
Quoted 8 lines
drivers/scsi/libata-core.c line 3065
Quoted 5 lines
drivers/scsi/libata-core.c renamed from drivers/scsi/libata-core.c~ +1
-1-WARN_ON (!spin_is_locked (&ap->host_set->lock)); +WARN_ON (!assert_spin_locked (&ap->host_set->lock));if (likely (qc->flags &ATA_QCFLAG_ACTIVE )) {assert (ap->queue_depth);Or just kill the check completely, it has served its purpose.
The solution that included the patch won the battle ;-)
I'll be pushing your incremental update out to kernel.org in a sec.
Jeff
Actually I wound up removing the WARN_ON(), since it broke my CONFIG_SMP build here :)
Jeff
Quoted 2 lines · Jeff Garzik
Actually I wound up removing the
WARN_ON(), since it broke myCONFIG_SMPbuild here :)
Good choice :-)
Signature · 1 line
Jens Axboe
Quoted 3 lines · Jens Axboe
So your system was functioning just fine, you just got a warning for every completed request slowing it down a lot :)
Yes! Too impatient yesterday...
--Grant.